From eb108929dcd6a4883a6d945a9f218dff27e89351 Mon Sep 17 00:00:00 2001 From: Gert Wollny Date: Tue, 1 Dec 2015 02:36:18 +0100 Subject: [PATCH] Imported Upstream version 3.6.1~20150924 --- ANNOUNCE | 29 + CHANGES | 12 + CMake/3rdparty.cmake | 295 + CMake/CTest/CTestCustom.cmake | 79 + CMake/CTest/dcmtkCTestConfig.cmake.in | 36 + CMake/CTest/dcmtkCTestMacros.cmake | 27 + CMake/CTest/dcmtkCTestRunAndroid.cmake.in | 26 + CMake/CheckCMakeCommandExists.cmake | 12 + CMake/CheckFunctionWithHeaderExists.cmake | 56 + CMake/DCMTKConfig.cmake.in | 53 + CMake/DCMTKConfig.cmake26.in | 37 + CMake/FindCharset.cmake | 22 + CMake/FindICONV.cmake | 33 + CMake/FindSndfile.cmake | 32 + CMake/FindWrap.cmake | 32 + CMake/GenerateCMakeExports.cmake | 81 + CMake/GenerateDCMTKConfigure.cmake | 859 + CMake/android.toolchain.cmake | 1812 + CMake/dcmtkAfterModules.cmake | 27 + CMake/dcmtkMacros.cmake | 191 + CMake/dcmtkPrepare.cmake | 488 + CMake/dcmtkTestCharSignedness.cc | 6 + CMake/dcmtkTryCompile.cmake | 43 + CMake/dcmtkTryRun.cmake | 99 + CMake/dcmtkUseAndroidSDK.cmake | 618 + CMake/dcmtkUseWine.cmake | 73 + CMake/osconfig.h.in | 1135 + CMakeLists.txt | 134 + COPYRIGHT | 581 + CREDITS | 50 + FAQ | 3 + HISTORY | 65 + INSTALL | 793 + Makefile | 903 + README | 55 + VERSION | 1 + config/CMakeLists.txt | 5 + config/Makefile.def.in | 107 + config/Makefile.in | 68 + config/aclocal.m4 | 2013 ++ config/arith.cc | 591 + config/autoall | 29 + config/changext | 149 + config/config.guess | 1530 + config/config.sub | 1779 + config/configure | 16302 +++++++++ config/configure.in | 1362 + config/confmod | 2915 ++ config/confmod.in | 36 + config/docs/CMakeLists.txt | 2 + config/docs/config.dox | 40 + config/docs/config.txt | 122 + config/docs/cxx11.dox | 116 + config/docs/dirstruc.txt | 30 + config/docs/envvars.txt | 53 + config/docs/macros.txt | 457 + config/docs/modules.txt | 65 + config/general.m4 | 7 + config/include/dcmtk/config/osconfig.h.in | 1096 + config/install-sh | 527 + config/mkinstalldirs | 162 + config/modules | 1 + config/rootconf | 239 + config/templates/Makefile.lib | 51 + config/templates/Makefile.mod | 93 + config/templates/Makefile.src | 48 + config/templates/configure.mod | 52 + configure | 36 + dcmdata/CMakeLists.txt | 10 + dcmdata/Makefile.in | 102 + dcmdata/apps/CMakeLists.txt | 17 + dcmdata/apps/Makefile.dep | 1112 + dcmdata/apps/Makefile.in | 94 + dcmdata/apps/dcm2pdf.cc | 352 + dcmdata/apps/dcm2xml.cc | 572 + dcmdata/apps/dcmconv.cc | 604 + dcmdata/apps/dcmcrle.cc | 336 + dcmdata/apps/dcmdrle.cc | 306 + dcmdata/apps/dcmdump.cc | 825 + dcmdata/apps/dcmftest.cc | 88 + dcmdata/apps/dcmgpdir.cc | 630 + dcmdata/apps/dcmodify.cc | 40 + dcmdata/apps/dump2dcm.cc | 1098 + dcmdata/apps/img2dcm.cc | 420 + dcmdata/apps/mdfconen.cc | 662 + dcmdata/apps/mdfconen.h | 225 + dcmdata/apps/mdfdsman.cc | 744 + dcmdata/apps/mdfdsman.h | 258 + dcmdata/apps/pdf2dcm.cc | 593 + dcmdata/apps/xml2dcm.cc | 990 + dcmdata/configure | 56 + dcmdata/data/CMakeLists.txt | 2 + dcmdata/data/Makefile.in | 30 + dcmdata/data/SC.dump | 99 + dcmdata/data/VLP.dump | 115 + dcmdata/data/acrnema.dic | 200 + dcmdata/data/dcm2xml.dtd | 40 + dcmdata/data/dicom.dic | 4121 +++ dcmdata/data/diconde.dic | 173 + dcmdata/data/dumppat.txt | 4 + dcmdata/data/private.dic | 3040 ++ dcmdata/docs/CMakeLists.txt | 2 + dcmdata/docs/Makefile.in | 29 + dcmdata/docs/datadict.txt | 219 + dcmdata/docs/dcm2pdf.man | 211 + dcmdata/docs/dcm2xml.man | 387 + dcmdata/docs/dcmconv.man | 363 + dcmdata/docs/dcmcrle.man | 259 + dcmdata/docs/dcmdata.dox | 97 + dcmdata/docs/dcmdrle.man | 252 + dcmdata/docs/dcmdump.man | 397 + dcmdata/docs/dcmftest.man | 44 + dcmdata/docs/dcmgpdir.man | 301 + dcmdata/docs/dcmodify.man | 586 + dcmdata/docs/dump2dcm.man | 317 + dcmdata/docs/img2dcm.man | 496 + dcmdata/docs/pdf2dcm.man | 180 + dcmdata/docs/xml2dcm.man | 343 + dcmdata/etc/Makefile.in | 23 + dcmdata/include/CMakeLists.txt | 2 + dcmdata/include/Makefile.in | 32 + dcmdata/include/dcmtk/dcmdata/cmdlnarg.h | 53 + dcmdata/include/dcmtk/dcmdata/dcbytstr.h | 419 + dcmdata/include/dcmtk/dcmdata/dcchrstr.h | 157 + dcmdata/include/dcmtk/dcmdata/dccodec.h | 516 + dcmdata/include/dcmtk/dcmdata/dcdatset.h | 345 + dcmdata/include/dcmtk/dcmdata/dcdatutl.h | 85 + dcmdata/include/dcmtk/dcmdata/dcddirif.h | 1587 + dcmdata/include/dcmtk/dcmdata/dcdefine.h | 44 + dcmdata/include/dcmtk/dcmdata/dcdeftag.h | 4067 +++ dcmdata/include/dcmtk/dcmdata/dcdicdir.h | 221 + dcmdata/include/dcmtk/dcmdata/dcdicent.h | 400 + dcmdata/include/dcmtk/dcmdata/dcdict.h | 296 + dcmdata/include/dcmtk/dcmdata/dcdirrec.h | 528 + dcmdata/include/dcmtk/dcmdata/dcelem.h | 868 + dcmdata/include/dcmtk/dcmdata/dcerror.h | 173 + dcmdata/include/dcmtk/dcmdata/dcfcache.h | 111 + dcmdata/include/dcmtk/dcmdata/dcfilefo.h | 461 + dcmdata/include/dcmtk/dcmdata/dcfilter.h | 209 + dcmdata/include/dcmtk/dcmdata/dchashdi.h | 304 + dcmdata/include/dcmtk/dcmdata/dcistrma.h | 263 + dcmdata/include/dcmtk/dcmdata/dcistrmb.h | 201 + dcmdata/include/dcmtk/dcmdata/dcistrmf.h | 299 + dcmdata/include/dcmtk/dcmdata/dcistrmz.h | 198 + dcmdata/include/dcmtk/dcmdata/dcitem.h | 1366 + dcmdata/include/dcmtk/dcmdata/dclist.h | 187 + dcmdata/include/dcmtk/dcmdata/dcmetinf.h | 254 + dcmdata/include/dcmtk/dcmdata/dcobject.h | 769 + dcmdata/include/dcmtk/dcmdata/dcofsetl.h | 33 + dcmdata/include/dcmtk/dcmdata/dcostrma.h | 205 + dcmdata/include/dcmtk/dcmdata/dcostrmb.h | 168 + dcmdata/include/dcmtk/dcmdata/dcostrmf.h | 142 + dcmdata/include/dcmtk/dcmdata/dcostrmz.h | 179 + dcmdata/include/dcmtk/dcmdata/dcovlay.h | 109 + dcmdata/include/dcmtk/dcmdata/dcpath.h | 520 + dcmdata/include/dcmtk/dcmdata/dcpcache.h | 115 + dcmdata/include/dcmtk/dcmdata/dcpixel.h | 606 + dcmdata/include/dcmtk/dcmdata/dcpixseq.h | 291 + dcmdata/include/dcmtk/dcmdata/dcpxitem.h | 164 + dcmdata/include/dcmtk/dcmdata/dcrleccd.h | 180 + dcmdata/include/dcmtk/dcmdata/dcrlecce.h | 192 + dcmdata/include/dcmtk/dcmdata/dcrlecp.h | 137 + dcmdata/include/dcmtk/dcmdata/dcrledec.h | 264 + dcmdata/include/dcmtk/dcmdata/dcrledrg.h | 80 + dcmdata/include/dcmtk/dcmdata/dcrleenc.h | 416 + dcmdata/include/dcmtk/dcmdata/dcrleerg.h | 84 + dcmdata/include/dcmtk/dcmdata/dcrlerp.h | 65 + dcmdata/include/dcmtk/dcmdata/dcsequen.h | 606 + dcmdata/include/dcmtk/dcmdata/dcspchrs.h | 330 + dcmdata/include/dcmtk/dcmdata/dcstack.h | 152 + dcmdata/include/dcmtk/dcmdata/dcswap.h | 85 + dcmdata/include/dcmtk/dcmdata/dctag.h | 220 + dcmdata/include/dcmtk/dcmdata/dctagkey.h | 419 + dcmdata/include/dcmtk/dcmdata/dctk.h | 101 + dcmdata/include/dcmtk/dcmdata/dctypes.h | 240 + dcmdata/include/dcmtk/dcmdata/dcuid.h | 775 + dcmdata/include/dcmtk/dcmdata/dcvr.h | 389 + dcmdata/include/dcmtk/dcmdata/dcvrae.h | 122 + dcmdata/include/dcmtk/dcmdata/dcvras.h | 112 + dcmdata/include/dcmtk/dcmdata/dcvrat.h | 237 + dcmdata/include/dcmtk/dcmdata/dcvrcs.h | 136 + dcmdata/include/dcmtk/dcmdata/dcvrda.h | 214 + dcmdata/include/dcmtk/dcmdata/dcvrds.h | 150 + dcmdata/include/dcmtk/dcmdata/dcvrdt.h | 270 + dcmdata/include/dcmtk/dcmdata/dcvrfd.h | 208 + dcmdata/include/dcmtk/dcmdata/dcvrfl.h | 208 + dcmdata/include/dcmtk/dcmdata/dcvris.h | 129 + dcmdata/include/dcmtk/dcmdata/dcvrlo.h | 125 + dcmdata/include/dcmtk/dcmdata/dcvrlt.h | 133 + dcmdata/include/dcmtk/dcmdata/dcvrobow.h | 345 + dcmdata/include/dcmtk/dcmdata/dcvrod.h | 112 + dcmdata/include/dcmtk/dcmdata/dcvrof.h | 112 + dcmdata/include/dcmtk/dcmdata/dcvrpn.h | 293 + dcmdata/include/dcmtk/dcmdata/dcvrpobw.h | 225 + dcmdata/include/dcmtk/dcmdata/dcvrsh.h | 125 + dcmdata/include/dcmtk/dcmdata/dcvrsl.h | 205 + dcmdata/include/dcmtk/dcmdata/dcvrss.h | 205 + dcmdata/include/dcmtk/dcmdata/dcvrst.h | 134 + dcmdata/include/dcmtk/dcmdata/dcvrtm.h | 273 + dcmdata/include/dcmtk/dcmdata/dcvruc.h | 124 + dcmdata/include/dcmtk/dcmdata/dcvrui.h | 175 + dcmdata/include/dcmtk/dcmdata/dcvrul.h | 205 + dcmdata/include/dcmtk/dcmdata/dcvrulup.h | 117 + dcmdata/include/dcmtk/dcmdata/dcvrur.h | 133 + dcmdata/include/dcmtk/dcmdata/dcvrus.h | 205 + dcmdata/include/dcmtk/dcmdata/dcvrut.h | 134 + dcmdata/include/dcmtk/dcmdata/dcwcache.h | 136 + dcmdata/include/dcmtk/dcmdata/dcxfer.h | 324 + dcmdata/include/dcmtk/dcmdata/libi2d/i2d.h | 263 + .../include/dcmtk/dcmdata/libi2d/i2dbmps.h | 227 + .../include/dcmtk/dcmdata/libi2d/i2define.h | 38 + .../include/dcmtk/dcmdata/libi2d/i2dimgs.h | 117 + .../include/dcmtk/dcmdata/libi2d/i2djpgs.h | 353 + .../include/dcmtk/dcmdata/libi2d/i2doutpl.h | 222 + .../include/dcmtk/dcmdata/libi2d/i2dplnsc.h | 108 + .../include/dcmtk/dcmdata/libi2d/i2dplsc.h | 71 + .../include/dcmtk/dcmdata/libi2d/i2dplvlp.h | 71 + dcmdata/include/dcmtk/dcmdata/vrscan.h | 40 + dcmdata/libi2d/CMakeLists.txt | 4 + dcmdata/libi2d/Makefile.dep | 317 + dcmdata/libi2d/Makefile.in | 56 + dcmdata/libi2d/i2d.cc | 733 + dcmdata/libi2d/i2dbmps.cc | 617 + dcmdata/libi2d/i2djpgs.cc | 899 + dcmdata/libi2d/i2dplnsc.cc | 260 + dcmdata/libi2d/i2dplsc.cc | 72 + dcmdata/libi2d/i2dplvlp.cc | 85 + dcmdata/libsrc/CMakeLists.txt | 49 + dcmdata/libsrc/Makefile.dep | 3763 +++ dcmdata/libsrc/Makefile.in | 110 + dcmdata/libsrc/cmdlnarg.cc | 171 + dcmdata/libsrc/dcbytstr.cc | 870 + dcmdata/libsrc/dcchrstr.cc | 231 + dcmdata/libsrc/dccodec.cc | 645 + dcmdata/libsrc/dcdatset.cc | 761 + dcmdata/libsrc/dcdatutl.cc | 135 + dcmdata/libsrc/dcddirif.cc | 5646 ++++ dcmdata/libsrc/dcdicdir.cc | 1271 + dcmdata/libsrc/dcdicent.cc | 174 + dcmdata/libsrc/dcdict.cc | 878 + dcmdata/libsrc/dcdictbi.cc | 27598 ++++++++++++++++ dcmdata/libsrc/dcdirrec.cc | 1613 + dcmdata/libsrc/dcelem.cc | 2048 ++ dcmdata/libsrc/dcerror.cc | 82 + dcmdata/libsrc/dcfilefo.cc | 1050 + dcmdata/libsrc/dcfilter.cc | 94 + dcmdata/libsrc/dchashdi.cc | 410 + dcmdata/libsrc/dcistrma.cc | 125 + dcmdata/libsrc/dcistrmb.cc | 326 + dcmdata/libsrc/dcistrmf.cc | 259 + dcmdata/libsrc/dcistrmz.cc | 432 + dcmdata/libsrc/dcitem.cc | 4333 +++ dcmdata/libsrc/dclist.cc | 295 + dcmdata/libsrc/dcmetinf.cc | 630 + dcmdata/libsrc/dcobject.cc | 610 + dcmdata/libsrc/dcostrma.cc | 103 + dcmdata/libsrc/dcostrmb.cc | 118 + dcmdata/libsrc/dcostrmf.cc | 147 + dcmdata/libsrc/dcostrmz.cc | 359 + dcmdata/libsrc/dcpath.cc | 941 + dcmdata/libsrc/dcpcache.cc | 106 + dcmdata/libsrc/dcpixel.cc | 1150 + dcmdata/libsrc/dcpixseq.cc | 431 + dcmdata/libsrc/dcpxitem.cc | 419 + dcmdata/libsrc/dcrleccd.cc | 692 + dcmdata/libsrc/dcrlecce.cc | 436 + dcmdata/libsrc/dcrlecp.cc | 63 + dcmdata/libsrc/dcrledrg.cc | 68 + dcmdata/libsrc/dcrleerg.cc | 72 + dcmdata/libsrc/dcrlerp.cc | 59 + dcmdata/libsrc/dcsequen.cc | 1472 + dcmdata/libsrc/dcspchrs.cc | 789 + dcmdata/libsrc/dcstack.cc | 263 + dcmdata/libsrc/dcswap.cc | 134 + dcmdata/libsrc/dctag.cc | 268 + dcmdata/libsrc/dctagkey.cc | 94 + dcmdata/libsrc/dctypes.cc | 45 + dcmdata/libsrc/dcuid.cc | 1767 + dcmdata/libsrc/dcvr.cc | 438 + dcmdata/libsrc/dcvrae.cc | 115 + dcmdata/libsrc/dcvras.cc | 95 + dcmdata/libsrc/dcvrat.cc | 405 + dcmdata/libsrc/dcvrcs.cc | 144 + dcmdata/libsrc/dcvrda.cc | 296 + dcmdata/libsrc/dcvrds.cc | 227 + dcmdata/libsrc/dcvrdt.cc | 380 + dcmdata/libsrc/dcvrfd.cc | 362 + dcmdata/libsrc/dcvrfl.cc | 363 + dcmdata/libsrc/dcvris.cc | 142 + dcmdata/libsrc/dcvrlo.cc | 118 + dcmdata/libsrc/dcvrlt.cc | 131 + dcmdata/libsrc/dcvrobow.cc | 815 + dcmdata/libsrc/dcvrod.cc | 154 + dcmdata/libsrc/dcvrof.cc | 154 + dcmdata/libsrc/dcvrpn.cc | 476 + dcmdata/libsrc/dcvrpobw.cc | 311 + dcmdata/libsrc/dcvrsh.cc | 118 + dcmdata/libsrc/dcvrsl.cc | 366 + dcmdata/libsrc/dcvrss.cc | 351 + dcmdata/libsrc/dcvrst.cc | 131 + dcmdata/libsrc/dcvrtm.cc | 417 + dcmdata/libsrc/dcvruc.cc | 116 + dcmdata/libsrc/dcvrui.cc | 248 + dcmdata/libsrc/dcvrul.cc | 364 + dcmdata/libsrc/dcvrulup.cc | 131 + dcmdata/libsrc/dcvrur.cc | 125 + dcmdata/libsrc/dcvrus.cc | 349 + dcmdata/libsrc/dcvrut.cc | 131 + dcmdata/libsrc/dcwcache.cc | 91 + dcmdata/libsrc/dcxfer.cc | 694 + dcmdata/libsrc/mkdeftag.cc | 275 + dcmdata/libsrc/mkdictbi.cc | 297 + dcmdata/libsrc/vrscan.cc | 91 + dcmdata/libsrc/vrscani.h | 44 + dcmdata/libsrc/vrscanl.c | 6442 ++++ dcmdata/libsrc/vrscanl.h | 349 + dcmdata/libsrc/vrscanl.l | 125 + dcmdata/tests/CMakeLists.txt | 8 + dcmdata/tests/Makefile.dep | 1082 + dcmdata/tests/Makefile.in | 56 + dcmdata/tests/dcmpsdmp.tcl | 187 + dcmdata/tests/dctmacro.h | 126 + dcmdata/tests/tchval.cc | 275 + dcmdata/tests/tdict.cc | 108 + dcmdata/tests/telemlen.cc | 155 + dcmdata/tests/tests.cc | 104 + dcmdata/tests/tfilter.cc | 78 + dcmdata/tests/ti2dbmp.cc | 320 + dcmdata/tests/tparent.cc | 185 + dcmdata/tests/tparser.cc | 490 + dcmdata/tests/tpath.cc | 355 + dcmdata/tests/tpread.cc | 422 + dcmdata/tests/tspchrs.cc | 191 + dcmdata/tests/tstrval.cc | 67 + dcmdata/tests/tvrcomp.cc | 488 + dcmdata/tests/tvrdatim.cc | 144 + dcmdata/tests/tvrds.cc | 91 + dcmdata/tests/tvrfd.cc | 63 + dcmdata/tests/tvrpn.cc | 86 + dcmdata/tests/tvrui.cc | 85 + dcmfg/CMakeLists.txt | 10 + dcmfg/Makefile.in | 85 + dcmfg/configure | 56 + dcmfg/data/Makefile.in | 23 + dcmfg/docs/Makefile.in | 23 + dcmfg/docs/dcmfg.dox | 14 + dcmfg/etc/Makefile.in | 23 + dcmfg/include/CMakeLists.txt | 2 + dcmfg/include/Makefile.in | 27 + dcmfg/include/dcmtk/dcmfg/fg.h | 114 + dcmfg/include/dcmtk/dcmfg/fgbase.h | 258 + dcmfg/include/dcmtk/dcmfg/fgdefine.h | 36 + dcmfg/include/dcmtk/dcmfg/fgderimg.h | 379 + dcmfg/include/dcmtk/dcmfg/fgfact.h | 80 + dcmfg/include/dcmtk/dcmfg/fgfracon.h | 378 + dcmfg/include/dcmtk/dcmfg/fgframevoilut.h | 209 + dcmfg/include/dcmtk/dcmfg/fgimagedatatype.h | 179 + dcmfg/include/dcmtk/dcmfg/fginterface.h | 279 + dcmfg/include/dcmtk/dcmfg/fgpixmsr.h | 170 + dcmfg/include/dcmtk/dcmfg/fgplanor.h | 175 + dcmfg/include/dcmtk/dcmfg/fgplanorvol.h | 159 + dcmfg/include/dcmtk/dcmfg/fgplanpo.h | 157 + dcmfg/include/dcmtk/dcmfg/fgplanposvol.h | 157 + .../dcmtk/dcmfg/fgrealworldvaluemapping.h | 372 + dcmfg/include/dcmtk/dcmfg/fgseg.h | 128 + dcmfg/include/dcmtk/dcmfg/fgtypes.h | 209 + .../dcmtk/dcmfg/fgusimagedescription.h | 183 + dcmfg/include/dcmtk/dcmfg/stack.h | 144 + dcmfg/include/dcmtk/dcmfg/stackinterface.h | 73 + dcmfg/libsrc/CMakeLists.txt | 23 + dcmfg/libsrc/Makefile.dep | 2179 ++ dcmfg/libsrc/Makefile.in | 57 + dcmfg/libsrc/fg.cc | 131 + dcmfg/libsrc/fgbase.cc | 221 + dcmfg/libsrc/fgderimg.cc | 628 + dcmfg/libsrc/fgfact.cc | 144 + dcmfg/libsrc/fgfracon.cc | 370 + dcmfg/libsrc/fgframevoilut.cc | 221 + dcmfg/libsrc/fgimagedatatype.cc | 249 + dcmfg/libsrc/fginterface.cc | 677 + dcmfg/libsrc/fgpixmsr.cc | 162 + dcmfg/libsrc/fgplanor.cc | 185 + dcmfg/libsrc/fgplanorvol.cc | 160 + dcmfg/libsrc/fgplanpo.cc | 166 + dcmfg/libsrc/fgplanposvol.cc | 150 + dcmfg/libsrc/fgrealworldvaluemapping.cc | 390 + dcmfg/libsrc/fgseg.cc | 138 + dcmfg/libsrc/fgtypes.cc | 183 + dcmfg/libsrc/fgusimagedescription.cc | 200 + dcmfg/libsrc/stack.cc | 107 + dcmfg/libsrc/stackinterface.cc | 274 + dcmfg/tests/Makefile.in | 30 + dcmimage/CMakeLists.txt | 10 + dcmimage/Makefile.in | 97 + dcmimage/apps/CMakeLists.txt | 9 + dcmimage/apps/Makefile.dep | 401 + dcmimage/apps/Makefile.in | 60 + dcmimage/apps/dcm2pnm.cc | 1551 + dcmimage/apps/dcmquant.cc | 508 + dcmimage/apps/dcmscale.cc | 656 + dcmimage/configure | 56 + dcmimage/data/Makefile.in | 23 + dcmimage/docs/Makefile.in | 23 + dcmimage/docs/dcm2pnm.man | 502 + dcmimage/docs/dcmimage.dox | 44 + dcmimage/docs/dcmquant.man | 285 + dcmimage/docs/dcmscale.man | 271 + dcmimage/etc/Makefile.in | 23 + dcmimage/include/CMakeLists.txt | 2 + dcmimage/include/Makefile.in | 27 + dcmimage/include/dcmtk/dcmimage/diargimg.h | 90 + dcmimage/include/dcmtk/dcmimage/diargpxt.h | 193 + dcmimage/include/dcmtk/dcmimage/dicdefin.h | 38 + dcmimage/include/dcmtk/dcmimage/dicmyimg.h | 72 + dcmimage/include/dcmtk/dcmimage/dicmypxt.h | 146 + dcmimage/include/dcmtk/dcmimage/dicocpt.h | 91 + dcmimage/include/dcmtk/dcmimage/dicoflt.h | 107 + dcmimage/include/dcmtk/dcmimage/dicoimg.h | 446 + dcmimage/include/dcmtk/dcmimage/dicomot.h | 111 + dcmimage/include/dcmtk/dcmimage/dicoopx.h | 136 + dcmimage/include/dcmtk/dcmimage/dicoopxt.h | 417 + dcmimage/include/dcmtk/dcmimage/dicopx.h | 167 + dcmimage/include/dcmtk/dcmimage/dicopxt.h | 601 + dcmimage/include/dcmtk/dcmimage/dicorot.h | 107 + dcmimage/include/dcmtk/dcmimage/dicosct.h | 109 + dcmimage/include/dcmtk/dcmimage/dihsvimg.h | 72 + dcmimage/include/dcmtk/dcmimage/dihsvpxt.h | 210 + dcmimage/include/dcmtk/dcmimage/dilogger.h | 41 + dcmimage/include/dcmtk/dcmimage/dipalimg.h | 90 + dcmimage/include/dcmtk/dcmimage/dipalpxt.h | 115 + dcmimage/include/dcmtk/dcmimage/dipipng.h | 137 + dcmimage/include/dcmtk/dcmimage/dipitiff.h | 146 + dcmimage/include/dcmtk/dcmimage/diqtcmap.h | 131 + dcmimage/include/dcmtk/dcmimage/diqtctab.h | 232 + dcmimage/include/dcmtk/dcmimage/diqtfs.h | 220 + dcmimage/include/dcmtk/dcmimage/diqthash.h | 129 + dcmimage/include/dcmtk/dcmimage/diqthitl.h | 129 + dcmimage/include/dcmtk/dcmimage/diqthitm.h | 109 + dcmimage/include/dcmtk/dcmimage/diqtid.h | 100 + dcmimage/include/dcmtk/dcmimage/diqtpbox.h | 116 + dcmimage/include/dcmtk/dcmimage/diqtpix.h | 165 + dcmimage/include/dcmtk/dcmimage/diqtstab.h | 115 + dcmimage/include/dcmtk/dcmimage/diqttype.h | 74 + dcmimage/include/dcmtk/dcmimage/diquant.h | 85 + dcmimage/include/dcmtk/dcmimage/diregist.h | 88 + dcmimage/include/dcmtk/dcmimage/dirgbimg.h | 72 + dcmimage/include/dcmtk/dcmimage/dirgbpxt.h | 134 + dcmimage/include/dcmtk/dcmimage/diybrimg.h | 72 + dcmimage/include/dcmtk/dcmimage/diybrpxt.h | 284 + dcmimage/include/dcmtk/dcmimage/diyf2img.h | 72 + dcmimage/include/dcmtk/dcmimage/diyf2pxt.h | 156 + dcmimage/include/dcmtk/dcmimage/diyp2img.h | 72 + dcmimage/include/dcmtk/dcmimage/diyp2pxt.h | 136 + dcmimage/libsrc/CMakeLists.txt | 5 + dcmimage/libsrc/Makefile.dep | 1306 + dcmimage/libsrc/Makefile.in | 57 + dcmimage/libsrc/diargimg.cc | 152 + dcmimage/libsrc/dicmyimg.cc | 103 + dcmimage/libsrc/dicoimg.cc | 699 + dcmimage/libsrc/dicoopx.cc | 55 + dcmimage/libsrc/dicopx.cc | 106 + dcmimage/libsrc/dihsvimg.cc | 103 + dcmimage/libsrc/dilogger.cc | 32 + dcmimage/libsrc/dipalimg.cc | 169 + dcmimage/libsrc/dipipng.cc | 235 + dcmimage/libsrc/dipitiff.cc | 208 + dcmimage/libsrc/diqtctab.cc | 546 + dcmimage/libsrc/diqtfs.cc | 101 + dcmimage/libsrc/diqthash.cc | 114 + dcmimage/libsrc/diqthitl.cc | 53 + dcmimage/libsrc/diqtpbox.cc | 65 + dcmimage/libsrc/diquant.cc | 221 + dcmimage/libsrc/diregist.cc | 136 + dcmimage/libsrc/dirgbimg.cc | 103 + dcmimage/libsrc/diybrimg.cc | 104 + dcmimage/libsrc/diyf2img.cc | 102 + dcmimage/libsrc/diyp2img.cc | 101 + dcmimage/tests/Makefile.in | 29 + dcmimgle/CMakeLists.txt | 10 + dcmimgle/Makefile.in | 97 + dcmimgle/apps/CMakeLists.txt | 9 + dcmimgle/apps/Makefile.dep | 145 + dcmimgle/apps/Makefile.in | 56 + dcmimgle/apps/dcmdspfn.cc | 309 + dcmimgle/apps/dcod2lum.cc | 175 + dcmimgle/apps/dconvlum.cc | 110 + dcmimgle/configure | 56 + dcmimgle/data/CMakeLists.txt | 2 + dcmimgle/data/Makefile.in | 29 + dcmimgle/data/camera.lut | 26 + dcmimgle/data/monitor.lut | 270 + dcmimgle/data/printer.lut | 38 + dcmimgle/data/scanner.lut | 34 + dcmimgle/docs/Makefile.in | 23 + dcmimgle/docs/dcmdspfn.man | 201 + dcmimgle/docs/dcmimgle.dox | 48 + dcmimgle/docs/dcod2lum.man | 61 + dcmimgle/docs/dconvlum.man | 59 + dcmimgle/etc/Makefile.in | 23 + dcmimgle/include/CMakeLists.txt | 2 + dcmimgle/include/Makefile.in | 27 + dcmimgle/include/dcmtk/dcmimgle/dcmimage.h | 1905 ++ dcmimgle/include/dcmtk/dcmimgle/dibaslut.h | 310 + dcmimgle/include/dcmtk/dcmimgle/diciefn.h | 145 + dcmimgle/include/dcmtk/dcmimgle/dicielut.h | 108 + dcmimgle/include/dcmtk/dcmimgle/dicrvfit.h | 325 + dcmimgle/include/dcmtk/dcmimgle/didefine.h | 38 + dcmimgle/include/dcmtk/dcmimgle/didislut.h | 87 + dcmimgle/include/dcmtk/dcmimgle/didispfn.h | 487 + dcmimgle/include/dcmtk/dcmimgle/didocu.h | 424 + dcmimgle/include/dcmtk/dcmimgle/diflipt.h | 334 + dcmimgle/include/dcmtk/dcmimgle/digsdfn.h | 227 + dcmimgle/include/dcmtk/dcmimgle/digsdlut.h | 122 + dcmimgle/include/dcmtk/dcmimgle/diimage.h | 676 + dcmimgle/include/dcmtk/dcmimgle/diinpx.h | 208 + dcmimgle/include/dcmtk/dcmimgle/diinpxt.h | 673 + dcmimgle/include/dcmtk/dcmimgle/diluptab.h | 251 + dcmimgle/include/dcmtk/dcmimgle/dimo1img.h | 227 + dcmimgle/include/dcmtk/dcmimgle/dimo2img.h | 289 + dcmimgle/include/dcmtk/dcmimgle/dimocpt.h | 93 + dcmimgle/include/dcmtk/dcmimgle/dimoflt.h | 113 + dcmimgle/include/dcmtk/dcmimgle/dimoimg.h | 1155 + dcmimgle/include/dcmtk/dcmimgle/dimoipxt.h | 269 + dcmimgle/include/dcmtk/dcmimgle/dimomod.h | 283 + dcmimgle/include/dcmtk/dcmimgle/dimoopx.h | 157 + dcmimgle/include/dcmtk/dcmimgle/dimoopxt.h | 1294 + dcmimgle/include/dcmtk/dcmimgle/dimopx.h | 242 + dcmimgle/include/dcmtk/dcmimgle/dimopxt.h | 437 + dcmimgle/include/dcmtk/dcmimgle/dimorot.h | 112 + dcmimgle/include/dcmtk/dcmimgle/dimosct.h | 127 + dcmimgle/include/dcmtk/dcmimgle/diobjcou.h | 117 + dcmimgle/include/dcmtk/dcmimgle/diovdat.h | 85 + dcmimgle/include/dcmtk/dcmimgle/diovlay.h | 477 + dcmimgle/include/dcmtk/dcmimgle/diovlimg.h | 57 + dcmimgle/include/dcmtk/dcmimgle/diovpln.h | 560 + dcmimgle/include/dcmtk/dcmimgle/dipixel.h | 122 + dcmimgle/include/dcmtk/dcmimgle/diplugin.h | 77 + dcmimgle/include/dcmtk/dcmimgle/dipxrept.h | 159 + dcmimgle/include/dcmtk/dcmimgle/diregbas.h | 96 + dcmimgle/include/dcmtk/dcmimgle/dirotat.h | 347 + dcmimgle/include/dcmtk/dcmimgle/discalet.h | 1239 + dcmimgle/include/dcmtk/dcmimgle/displint.h | 187 + dcmimgle/include/dcmtk/dcmimgle/ditranst.h | 138 + dcmimgle/include/dcmtk/dcmimgle/diutils.h | 444 + dcmimgle/libsrc/CMakeLists.txt | 4 + dcmimgle/libsrc/Makefile.dep | 1530 + dcmimgle/libsrc/Makefile.in | 57 + dcmimgle/libsrc/dcmimage.cc | 795 + dcmimgle/libsrc/dibaslut.cc | 102 + dcmimgle/libsrc/diciefn.cc | 241 + dcmimgle/libsrc/dicielut.cc | 198 + dcmimgle/libsrc/didislut.cc | 49 + dcmimgle/libsrc/didispfn.cc | 679 + dcmimgle/libsrc/didocu.cc | 440 + dcmimgle/libsrc/digsdfn.cc | 430 + dcmimgle/libsrc/digsdlut.cc | 218 + dcmimgle/libsrc/diimage.cc | 856 + dcmimgle/libsrc/diinpx.cc | 56 + dcmimgle/libsrc/diluptab.cc | 545 + dcmimgle/libsrc/dimo1img.cc | 154 + dcmimgle/libsrc/dimo2img.cc | 200 + dcmimgle/libsrc/dimoimg.cc | 2166 ++ dcmimgle/libsrc/dimoimg3.cc | 84 + dcmimgle/libsrc/dimoimg4.cc | 84 + dcmimgle/libsrc/dimoimg5.cc | 84 + dcmimgle/libsrc/dimomod.cc | 293 + dcmimgle/libsrc/dimoopx.cc | 76 + dcmimgle/libsrc/dimopx.cc | 96 + dcmimgle/libsrc/diovdat.cc | 66 + dcmimgle/libsrc/diovlay.cc | 592 + dcmimgle/libsrc/diovlimg.cc | 94 + dcmimgle/libsrc/diovpln.cc | 613 + dcmimgle/libsrc/diutils.cc | 138 + dcmimgle/tests/Makefile.in | 29 + dcmiod/CMakeLists.txt | 10 + dcmiod/Makefile.in | 85 + dcmiod/configure | 56 + dcmiod/data/Makefile.in | 23 + dcmiod/docs/Makefile.in | 23 + dcmiod/docs/dcmiod.dox | 23 + dcmiod/etc/Makefile.in | 23 + dcmiod/include/CMakeLists.txt | 2 + dcmiod/include/Makefile.in | 27 + dcmiod/include/dcmtk/dcmiod/iodcommn.h | 225 + dcmiod/include/dcmtk/dcmiod/ioddef.h | 39 + dcmiod/include/dcmtk/dcmiod/iodimage.h | 95 + dcmiod/include/dcmtk/dcmiod/iodmacro.h | 1274 + dcmiod/include/dcmtk/dcmiod/iodrules.h | 246 + dcmiod/include/dcmtk/dcmiod/iodtypes.h | 138 + dcmiod/include/dcmtk/dcmiod/iodutil.h | 900 + .../dcmtk/dcmiod/modacquisitioncontext.h | 74 + dcmiod/include/dcmtk/dcmiod/modbase.h | 229 + .../dcmtk/dcmiod/modcommoninstanceref.h | 210 + dcmiod/include/dcmtk/dcmiod/modenhequipment.h | 157 + dcmiod/include/dcmtk/dcmiod/modenhusimage.h | 593 + dcmiod/include/dcmtk/dcmiod/modenhusseries.h | 134 + dcmiod/include/dcmtk/dcmiod/modequipment.h | 233 + dcmiod/include/dcmtk/dcmiod/modfor.h | 108 + dcmiod/include/dcmtk/dcmiod/modgeneralimage.h | 361 + .../include/dcmtk/dcmiod/modgeneralseries.h | 299 + dcmiod/include/dcmtk/dcmiod/modgeneralstudy.h | 245 + dcmiod/include/dcmtk/dcmiod/modhelp.h | 210 + dcmiod/include/dcmtk/dcmiod/modimagepixel.h | 261 + .../dcmtk/dcmiod/modmultiframedimension.h | 381 + dcmiod/include/dcmtk/dcmiod/modmultiframefg.h | 292 + dcmiod/include/dcmtk/dcmiod/modpatient.h | 141 + dcmiod/include/dcmtk/dcmiod/modpatientstudy.h | 145 + .../dcmtk/dcmiod/modsegmentationseries.h | 141 + dcmiod/include/dcmtk/dcmiod/modsopcommon.h | 211 + .../include/dcmtk/dcmiod/modsynchronisation.h | 208 + dcmiod/include/dcmtk/dcmiod/modusfor.h | 229 + dcmiod/libsrc/CMakeLists.txt | 33 + dcmiod/libsrc/Makefile.dep | 2422 ++ dcmiod/libsrc/Makefile.in | 59 + dcmiod/libsrc/iodcommn.cc | 240 + dcmiod/libsrc/iodimage.cc | 89 + dcmiod/libsrc/iodmacro.cc | 1712 + dcmiod/libsrc/iodrules.cc | 307 + dcmiod/libsrc/iodtypes.cc | 44 + dcmiod/libsrc/iodutil.cc | 569 + dcmiod/libsrc/modacquisitioncontext.cc | 67 + dcmiod/libsrc/modbase.cc | 260 + dcmiod/libsrc/modcommoninstanceref.cc | 203 + dcmiod/libsrc/modenhequipment.cc | 134 + dcmiod/libsrc/modenhusimage.cc | 654 + dcmiod/libsrc/modenhusseries.cc | 117 + dcmiod/libsrc/modequipment.cc | 208 + dcmiod/libsrc/modfor.cc | 102 + dcmiod/libsrc/modgeneralimage.cc | 379 + dcmiod/libsrc/modgeneralseries.cc | 316 + dcmiod/libsrc/modgeneralstudy.cc | 294 + dcmiod/libsrc/modhelp.cc | 345 + dcmiod/libsrc/modimagepixel.cc | 299 + dcmiod/libsrc/modmultiframedimension.cc | 620 + dcmiod/libsrc/modmultiframefg.cc | 286 + dcmiod/libsrc/modpatient.cc | 136 + dcmiod/libsrc/modpatientstudy.cc | 134 + dcmiod/libsrc/modsegmentationseries.cc | 147 + dcmiod/libsrc/modsopcommon.cc | 246 + dcmiod/libsrc/modsynchronization.cc | 224 + dcmiod/libsrc/modusfor.cc | 275 + dcmiod/tests/Makefile.in | 29 + dcmjpeg/CMakeLists.txt | 7 + dcmjpeg/Makefile.in | 112 + dcmjpeg/apps/CMakeLists.txt | 12 + dcmjpeg/apps/Makefile.dep | 498 + dcmjpeg/apps/Makefile.in | 90 + dcmjpeg/apps/dcmcjpeg.cc | 710 + dcmjpeg/apps/dcmdjpeg.cc | 349 + dcmjpeg/apps/dcmj2pnm.cc | 27 + dcmjpeg/apps/dcmmkdir.cc | 47 + dcmjpeg/configure | 56 + dcmjpeg/data/Makefile.in | 23 + dcmjpeg/docs/Makefile.in | 23 + dcmjpeg/docs/dcmcjpeg.man | 673 + dcmjpeg/docs/dcmdjpeg.man | 328 + dcmjpeg/docs/dcmj2pnm.man | 547 + dcmjpeg/docs/dcmjpeg.dox | 77 + dcmjpeg/docs/dcmmkdir.man | 464 + dcmjpeg/docs/ijg_filelist.txt | 239 + dcmjpeg/docs/ijg_libjpeg.txt | 3011 ++ dcmjpeg/docs/ijg_readme.txt | 385 + dcmjpeg/docs/ijg_structure.txt | 1042 + dcmjpeg/etc/Makefile.in | 23 + dcmjpeg/include/CMakeLists.txt | 2 + dcmjpeg/include/Makefile.in | 27 + dcmjpeg/include/dcmtk/dcmjpeg/ddpiimpl.h | 91 + dcmjpeg/include/dcmtk/dcmjpeg/dipijpeg.h | 104 + dcmjpeg/include/dcmtk/dcmjpeg/djcodecd.h | 266 + dcmjpeg/include/dcmtk/dcmjpeg/djcodece.h | 384 + dcmjpeg/include/dcmtk/dcmjpeg/djcparam.h | 403 + dcmjpeg/include/dcmtk/dcmjpeg/djdecabs.h | 85 + dcmjpeg/include/dcmtk/dcmjpeg/djdecbas.h | 63 + dcmjpeg/include/dcmtk/dcmjpeg/djdecext.h | 64 + dcmjpeg/include/dcmtk/dcmjpeg/djdeclol.h | 64 + dcmjpeg/include/dcmtk/dcmjpeg/djdecode.h | 93 + dcmjpeg/include/dcmtk/dcmjpeg/djdecpro.h | 64 + dcmjpeg/include/dcmtk/dcmjpeg/djdecsps.h | 64 + dcmjpeg/include/dcmtk/dcmjpeg/djdecsv1.h | 64 + dcmjpeg/include/dcmtk/dcmjpeg/djdefine.h | 38 + dcmjpeg/include/dcmtk/dcmjpeg/djdijg12.h | 128 + dcmjpeg/include/dcmtk/dcmjpeg/djdijg16.h | 128 + dcmjpeg/include/dcmtk/dcmjpeg/djdijg8.h | 128 + dcmjpeg/include/dcmtk/dcmjpeg/djeijg12.h | 173 + dcmjpeg/include/dcmtk/dcmjpeg/djeijg16.h | 163 + dcmjpeg/include/dcmtk/dcmjpeg/djeijg8.h | 169 + dcmjpeg/include/dcmtk/dcmjpeg/djencabs.h | 99 + dcmjpeg/include/dcmtk/dcmjpeg/djencbas.h | 86 + dcmjpeg/include/dcmtk/dcmjpeg/djencext.h | 86 + dcmjpeg/include/dcmtk/dcmjpeg/djenclol.h | 86 + dcmjpeg/include/dcmtk/dcmjpeg/djencode.h | 134 + dcmjpeg/include/dcmtk/dcmjpeg/djencpro.h | 86 + dcmjpeg/include/dcmtk/dcmjpeg/djencsps.h | 86 + dcmjpeg/include/dcmtk/dcmjpeg/djencsv1.h | 86 + dcmjpeg/include/dcmtk/dcmjpeg/djrplol.h | 90 + dcmjpeg/include/dcmtk/dcmjpeg/djrploss.h | 80 + dcmjpeg/include/dcmtk/dcmjpeg/djutils.h | 223 + dcmjpeg/libijg12/CMakeLists.txt | 2 + dcmjpeg/libijg12/Makefile.dep | 227 + dcmjpeg/libijg12/Makefile.in | 59 + dcmjpeg/libijg12/jaricom.c | 15 + dcmjpeg/libijg12/jcapimin.c | 280 + dcmjpeg/libijg12/jcapistd.c | 161 + dcmjpeg/libijg12/jcarith.c | 26 + dcmjpeg/libijg12/jccoefct.c | 454 + dcmjpeg/libijg12/jccolor.c | 459 + dcmjpeg/libijg12/jcdctmgr.c | 390 + dcmjpeg/libijg12/jcdiffct.c | 406 + dcmjpeg/libijg12/jchuff.c | 274 + dcmjpeg/libijg12/jchuff12.h | 54 + dcmjpeg/libijg12/jcinit.c | 57 + dcmjpeg/libijg12/jclhuff.c | 601 + dcmjpeg/libijg12/jclossls.c | 82 + dcmjpeg/libijg12/jclossy.c | 76 + dcmjpeg/libijg12/jcmainct.c | 296 + dcmjpeg/libijg12/jcmarker.c | 680 + dcmjpeg/libijg12/jcmaster.c | 657 + dcmjpeg/libijg12/jcodec.c | 53 + dcmjpeg/libijg12/jcomapi.c | 106 + dcmjpeg/libijg12/jconfig12.h | 73 + dcmjpeg/libijg12/jcparam.c | 687 + dcmjpeg/libijg12/jcphuff.c | 848 + dcmjpeg/libijg12/jcpred.c | 314 + dcmjpeg/libijg12/jcprepct.c | 354 + dcmjpeg/libijg12/jcsample.c | 519 + dcmjpeg/libijg12/jcscale.c | 63 + dcmjpeg/libijg12/jcshuff.c | 661 + dcmjpeg/libijg12/jctrans.c | 424 + dcmjpeg/libijg12/jdapimin.c | 401 + dcmjpeg/libijg12/jdapistd.c | 275 + dcmjpeg/libijg12/jdarith.c | 26 + dcmjpeg/libijg12/jdatadst.c | 151 + dcmjpeg/libijg12/jdatasrc.c | 212 + dcmjpeg/libijg12/jdcoefct.c | 743 + dcmjpeg/libijg12/jdcolor.c | 413 + dcmjpeg/libijg12/jdct12.h | 176 + dcmjpeg/libijg12/jddctmgr.c | 270 + dcmjpeg/libijg12/jddiffct.c | 399 + dcmjpeg/libijg12/jdhuff.c | 316 + dcmjpeg/libijg12/jdhuff12.h | 229 + dcmjpeg/libijg12/jdinput.c | 347 + dcmjpeg/libijg12/jdlhuff.c | 291 + dcmjpeg/libijg12/jdlossls.c | 98 + dcmjpeg/libijg12/jdlossy.c | 232 + dcmjpeg/libijg12/jdmainct.c | 512 + dcmjpeg/libijg12/jdmarker.c | 1370 + dcmjpeg/libijg12/jdmaster.c | 460 + dcmjpeg/libijg12/jdmerge.c | 400 + dcmjpeg/libijg12/jdphuff.c | 675 + dcmjpeg/libijg12/jdpostct.c | 290 + dcmjpeg/libijg12/jdpred.c | 263 + dcmjpeg/libijg12/jdsample.c | 478 + dcmjpeg/libijg12/jdscale.c | 119 + dcmjpeg/libijg12/jdshuff.c | 360 + dcmjpeg/libijg12/jdtrans.c | 138 + dcmjpeg/libijg12/jerror.c | 252 + dcmjpeg/libijg12/jerror12.h | 310 + dcmjpeg/libijg12/jfdctflt.c | 168 + dcmjpeg/libijg12/jfdctfst.c | 224 + dcmjpeg/libijg12/jfdctint.c | 283 + dcmjpeg/libijg12/jidctflt.c | 242 + dcmjpeg/libijg12/jidctfst.c | 368 + dcmjpeg/libijg12/jidctint.c | 389 + dcmjpeg/libijg12/jidctred.c | 398 + dcmjpeg/libijg12/jinclude12.h | 91 + dcmjpeg/libijg12/jlossls12.h | 151 + dcmjpeg/libijg12/jlossy12.h | 120 + dcmjpeg/libijg12/jmemmgr.c | 1174 + dcmjpeg/libijg12/jmemnobs.c | 109 + dcmjpeg/libijg12/jmemsys12.h | 198 + dcmjpeg/libijg12/jmorecfg12.h | 407 + dcmjpeg/libijg12/jpegint12.h | 373 + dcmjpeg/libijg12/jpeglib12.h | 1203 + dcmjpeg/libijg12/jquant1.c | 856 + dcmjpeg/libijg12/jquant2.c | 1310 + dcmjpeg/libijg12/jutils.c | 179 + dcmjpeg/libijg12/jversion12.h | 14 + dcmjpeg/libijg16/CMakeLists.txt | 2 + dcmjpeg/libijg16/Makefile.dep | 227 + dcmjpeg/libijg16/Makefile.in | 59 + dcmjpeg/libijg16/jaricom.c | 15 + dcmjpeg/libijg16/jcapimin.c | 280 + dcmjpeg/libijg16/jcapistd.c | 161 + dcmjpeg/libijg16/jcarith.c | 26 + dcmjpeg/libijg16/jccoefct.c | 454 + dcmjpeg/libijg16/jccolor.c | 470 + dcmjpeg/libijg16/jcdctmgr.c | 390 + dcmjpeg/libijg16/jcdiffct.c | 406 + dcmjpeg/libijg16/jchuff.c | 274 + dcmjpeg/libijg16/jchuff16.h | 54 + dcmjpeg/libijg16/jcinit.c | 57 + dcmjpeg/libijg16/jclhuff.c | 601 + dcmjpeg/libijg16/jclossls.c | 82 + dcmjpeg/libijg16/jclossy.c | 76 + dcmjpeg/libijg16/jcmainct.c | 296 + dcmjpeg/libijg16/jcmarker.c | 680 + dcmjpeg/libijg16/jcmaster.c | 657 + dcmjpeg/libijg16/jcodec.c | 53 + dcmjpeg/libijg16/jcomapi.c | 106 + dcmjpeg/libijg16/jconfig16.h | 73 + dcmjpeg/libijg16/jcparam.c | 687 + dcmjpeg/libijg16/jcphuff.c | 848 + dcmjpeg/libijg16/jcpred.c | 314 + dcmjpeg/libijg16/jcprepct.c | 354 + dcmjpeg/libijg16/jcsample.c | 519 + dcmjpeg/libijg16/jcscale.c | 63 + dcmjpeg/libijg16/jcshuff.c | 661 + dcmjpeg/libijg16/jctrans.c | 424 + dcmjpeg/libijg16/jdapimin.c | 401 + dcmjpeg/libijg16/jdapistd.c | 275 + dcmjpeg/libijg16/jdarith.c | 26 + dcmjpeg/libijg16/jdatadst.c | 151 + dcmjpeg/libijg16/jdatasrc.c | 212 + dcmjpeg/libijg16/jdcoefct.c | 743 + dcmjpeg/libijg16/jdcolor.c | 413 + dcmjpeg/libijg16/jdct16.h | 176 + dcmjpeg/libijg16/jddctmgr.c | 270 + dcmjpeg/libijg16/jddiffct.c | 399 + dcmjpeg/libijg16/jdhuff.c | 316 + dcmjpeg/libijg16/jdhuff16.h | 229 + dcmjpeg/libijg16/jdinput.c | 347 + dcmjpeg/libijg16/jdlhuff.c | 291 + dcmjpeg/libijg16/jdlossls.c | 98 + dcmjpeg/libijg16/jdlossy.c | 232 + dcmjpeg/libijg16/jdmainct.c | 512 + dcmjpeg/libijg16/jdmarker.c | 1370 + dcmjpeg/libijg16/jdmaster.c | 460 + dcmjpeg/libijg16/jdmerge.c | 400 + dcmjpeg/libijg16/jdphuff.c | 675 + dcmjpeg/libijg16/jdpostct.c | 290 + dcmjpeg/libijg16/jdpred.c | 279 + dcmjpeg/libijg16/jdsample.c | 478 + dcmjpeg/libijg16/jdscale.c | 119 + dcmjpeg/libijg16/jdshuff.c | 360 + dcmjpeg/libijg16/jdtrans.c | 138 + dcmjpeg/libijg16/jerror.c | 252 + dcmjpeg/libijg16/jerror16.h | 310 + dcmjpeg/libijg16/jfdctflt.c | 168 + dcmjpeg/libijg16/jfdctfst.c | 224 + dcmjpeg/libijg16/jfdctint.c | 283 + dcmjpeg/libijg16/jidctflt.c | 242 + dcmjpeg/libijg16/jidctfst.c | 368 + dcmjpeg/libijg16/jidctint.c | 389 + dcmjpeg/libijg16/jidctred.c | 398 + dcmjpeg/libijg16/jinclude16.h | 91 + dcmjpeg/libijg16/jlossls16.h | 157 + dcmjpeg/libijg16/jlossy16.h | 120 + dcmjpeg/libijg16/jmemmgr.c | 1174 + dcmjpeg/libijg16/jmemnobs.c | 109 + dcmjpeg/libijg16/jmemsys16.h | 198 + dcmjpeg/libijg16/jmorecfg16.h | 407 + dcmjpeg/libijg16/jpegint16.h | 373 + dcmjpeg/libijg16/jpeglib16.h | 1208 + dcmjpeg/libijg16/jquant1.c | 856 + dcmjpeg/libijg16/jquant2.c | 1310 + dcmjpeg/libijg16/jutils.c | 179 + dcmjpeg/libijg16/jversion16.h | 14 + dcmjpeg/libijg8/CMakeLists.txt | 2 + dcmjpeg/libijg8/Makefile.dep | 220 + dcmjpeg/libijg8/Makefile.in | 59 + dcmjpeg/libijg8/jaricom.c | 15 + dcmjpeg/libijg8/jcapimin.c | 280 + dcmjpeg/libijg8/jcapistd.c | 161 + dcmjpeg/libijg8/jcarith.c | 26 + dcmjpeg/libijg8/jccoefct.c | 454 + dcmjpeg/libijg8/jccolor.c | 459 + dcmjpeg/libijg8/jcdctmgr.c | 390 + dcmjpeg/libijg8/jcdiffct.c | 406 + dcmjpeg/libijg8/jchuff.c | 274 + dcmjpeg/libijg8/jchuff8.h | 54 + dcmjpeg/libijg8/jcinit.c | 57 + dcmjpeg/libijg8/jclhuff.c | 601 + dcmjpeg/libijg8/jclossls.c | 82 + dcmjpeg/libijg8/jclossy.c | 80 + dcmjpeg/libijg8/jcmainct.c | 296 + dcmjpeg/libijg8/jcmarker.c | 680 + dcmjpeg/libijg8/jcmaster.c | 657 + dcmjpeg/libijg8/jcodec.c | 53 + dcmjpeg/libijg8/jcomapi.c | 106 + dcmjpeg/libijg8/jconfig8.h | 73 + dcmjpeg/libijg8/jcparam.c | 687 + dcmjpeg/libijg8/jcphuff.c | 848 + dcmjpeg/libijg8/jcpred.c | 314 + dcmjpeg/libijg8/jcprepct.c | 354 + dcmjpeg/libijg8/jcsample.c | 519 + dcmjpeg/libijg8/jcscale.c | 63 + dcmjpeg/libijg8/jcshuff.c | 661 + dcmjpeg/libijg8/jctrans.c | 424 + dcmjpeg/libijg8/jdapimin.c | 401 + dcmjpeg/libijg8/jdapistd.c | 275 + dcmjpeg/libijg8/jdarith.c | 26 + dcmjpeg/libijg8/jdatadst.c | 151 + dcmjpeg/libijg8/jdatasrc.c | 212 + dcmjpeg/libijg8/jdcoefct.c | 743 + dcmjpeg/libijg8/jdcolor.c | 413 + dcmjpeg/libijg8/jdct8.h | 176 + dcmjpeg/libijg8/jddctmgr.c | 270 + dcmjpeg/libijg8/jddiffct.c | 399 + dcmjpeg/libijg8/jdhuff.c | 316 + dcmjpeg/libijg8/jdhuff8.h | 229 + dcmjpeg/libijg8/jdinput.c | 347 + dcmjpeg/libijg8/jdlhuff.c | 291 + dcmjpeg/libijg8/jdlossls.c | 98 + dcmjpeg/libijg8/jdlossy.c | 232 + dcmjpeg/libijg8/jdmainct.c | 512 + dcmjpeg/libijg8/jdmarker.c | 1370 + dcmjpeg/libijg8/jdmaster.c | 460 + dcmjpeg/libijg8/jdmerge.c | 400 + dcmjpeg/libijg8/jdphuff.c | 675 + dcmjpeg/libijg8/jdpostct.c | 290 + dcmjpeg/libijg8/jdpred.c | 263 + dcmjpeg/libijg8/jdsample.c | 478 + dcmjpeg/libijg8/jdscale.c | 119 + dcmjpeg/libijg8/jdshuff.c | 360 + dcmjpeg/libijg8/jdtrans.c | 138 + dcmjpeg/libijg8/jerror.c | 252 + dcmjpeg/libijg8/jerror8.h | 310 + dcmjpeg/libijg8/jfdctflt.c | 168 + dcmjpeg/libijg8/jfdctfst.c | 224 + dcmjpeg/libijg8/jfdctint.c | 283 + dcmjpeg/libijg8/jidctflt.c | 242 + dcmjpeg/libijg8/jidctfst.c | 368 + dcmjpeg/libijg8/jidctint.c | 389 + dcmjpeg/libijg8/jidctred.c | 398 + dcmjpeg/libijg8/jinclude8.h | 91 + dcmjpeg/libijg8/jlossls8.h | 151 + dcmjpeg/libijg8/jlossy8.h | 120 + dcmjpeg/libijg8/jmemmgr.c | 1174 + dcmjpeg/libijg8/jmemnobs.c | 110 + dcmjpeg/libijg8/jmemsys8.h | 198 + dcmjpeg/libijg8/jmorecfg8.h | 407 + dcmjpeg/libijg8/jpegint8.h | 373 + dcmjpeg/libijg8/jpeglib8.h | 1203 + dcmjpeg/libijg8/jquant1.c | 856 + dcmjpeg/libijg8/jquant2.c | 1310 + dcmjpeg/libijg8/jutils.c | 179 + dcmjpeg/libijg8/jversion8.h | 14 + dcmjpeg/libsrc/CMakeLists.txt | 7 + dcmjpeg/libsrc/Makefile.dep | 1710 + dcmjpeg/libsrc/Makefile.in | 55 + dcmjpeg/libsrc/ddpiimpl.cc | 119 + dcmjpeg/libsrc/dipijpeg.cc | 247 + dcmjpeg/libsrc/djcodecd.cc | 840 + dcmjpeg/libsrc/djcodece.cc | 1491 + dcmjpeg/libsrc/djcparam.cc | 126 + dcmjpeg/libsrc/djdecbas.cc | 54 + dcmjpeg/libsrc/djdecext.cc | 55 + dcmjpeg/libsrc/djdeclol.cc | 56 + dcmjpeg/libsrc/djdecode.cc | 119 + dcmjpeg/libsrc/djdecpro.cc | 55 + dcmjpeg/libsrc/djdecsps.cc | 55 + dcmjpeg/libsrc/djdecsv1.cc | 57 + dcmjpeg/libsrc/djdijg12.cc | 480 + dcmjpeg/libsrc/djdijg16.cc | 482 + dcmjpeg/libsrc/djdijg8.cc | 480 + dcmjpeg/libsrc/djeijg12.cc | 574 + dcmjpeg/libsrc/djeijg16.cc | 410 + dcmjpeg/libsrc/djeijg8.cc | 576 + dcmjpeg/libsrc/djencbas.cc | 81 + dcmjpeg/libsrc/djencext.cc | 86 + dcmjpeg/libsrc/djenclol.cc | 94 + dcmjpeg/libsrc/djencode.cc | 159 + dcmjpeg/libsrc/djencpro.cc | 86 + dcmjpeg/libsrc/djencsps.cc | 87 + dcmjpeg/libsrc/djencsv1.cc | 92 + dcmjpeg/libsrc/djrplol.cc | 67 + dcmjpeg/libsrc/djrploss.cc | 65 + dcmjpeg/libsrc/djutils.cc | 70 + dcmjpeg/tests/Makefile.in | 29 + dcmjpls/CMakeLists.txt | 7 + dcmjpls/Makefile.in | 102 + dcmjpls/apps/CMakeLists.txt | 12 + dcmjpls/apps/Makefile.dep | 377 + dcmjpls/apps/Makefile.in | 87 + dcmjpls/apps/dcmcjpls.cc | 509 + dcmjpls/apps/dcmdjpls.cc | 340 + dcmjpls/apps/dcml2pnm.cc | 27 + dcmjpls/configure | 56 + dcmjpls/data/Makefile.in | 23 + dcmjpls/docs/License.txt | 33 + dcmjpls/docs/Makefile.in | 23 + dcmjpls/docs/dcmcjpls.man | 381 + dcmjpls/docs/dcmdjpls.man | 280 + dcmjpls/docs/dcmjpls.dox | 77 + dcmjpls/docs/dcml2pnm.man | 503 + dcmjpls/docs/readme.txt | 16 + dcmjpls/etc/Makefile.in | 23 + dcmjpls/include/CMakeLists.txt | 2 + dcmjpls/include/Makefile.in | 27 + dcmjpls/include/dcmtk/dcmjpls/djcodecd.h | 335 + dcmjpls/include/dcmtk/dcmjpls/djcodece.h | 371 + dcmjpls/include/dcmtk/dcmjpls/djcparam.h | 278 + dcmjpls/include/dcmtk/dcmjpls/djdecode.h | 82 + dcmjpls/include/dcmtk/dcmjpls/djencode.h | 100 + dcmjpls/include/dcmtk/dcmjpls/djlsutil.h | 158 + dcmjpls/include/dcmtk/dcmjpls/djrparam.h | 97 + dcmjpls/include/dcmtk/dcmjpls/dldefine.h | 38 + dcmjpls/libcharls/CMakeLists.txt | 5 + dcmjpls/libcharls/Makefile.dep | 45 + dcmjpls/libcharls/Makefile.in | 45 + dcmjpls/libcharls/clrtrans.h | 180 + dcmjpls/libcharls/config.h | 63 + dcmjpls/libcharls/context.h | 122 + dcmjpls/libcharls/ctxtrmod.h | 101 + dcmjpls/libcharls/decodstr.h | 285 + dcmjpls/libcharls/deftrait.h | 126 + dcmjpls/libcharls/encodstr.h | 162 + dcmjpls/libcharls/header.cc | 625 + dcmjpls/libcharls/header.h | 63 + dcmjpls/libcharls/intrface.cc | 201 + dcmjpls/libcharls/intrface.h | 50 + dcmjpls/libcharls/jpegls.cc | 165 + dcmjpls/libcharls/lltraits.h | 128 + dcmjpls/libcharls/lokuptbl.h | 69 + dcmjpls/libcharls/procline.h | 227 + dcmjpls/libcharls/pubtypes.h | 76 + dcmjpls/libcharls/scan.h | 862 + dcmjpls/libcharls/streams.h | 156 + dcmjpls/libcharls/util.h | 152 + dcmjpls/libsrc/CMakeLists.txt | 7 + dcmjpls/libsrc/Makefile.dep | 412 + dcmjpls/libsrc/Makefile.in | 53 + dcmjpls/libsrc/djcodecd.cc | 742 + dcmjpls/libsrc/djcodece.cc | 1133 + dcmjpls/libsrc/djcparam.cc | 114 + dcmjpls/libsrc/djdecode.cc | 76 + dcmjpls/libsrc/djencode.cc | 88 + dcmjpls/libsrc/djerror.h | 73 + dcmjpls/libsrc/djrparam.cc | 72 + dcmjpls/libsrc/djutils.cc | 45 + dcmjpls/tests/Makefile.in | 29 + dcmnet/CMakeLists.txt | 10 + dcmnet/Makefile.in | 97 + dcmnet/apps/CMakeLists.txt | 28 + dcmnet/apps/Makefile.dep | 828 + dcmnet/apps/Makefile.in | 90 + dcmnet/apps/dcmrecv.cc | 319 + dcmnet/apps/dcmsend.cc | 586 + dcmnet/apps/echoscu.cc | 741 + dcmnet/apps/findscu.cc | 660 + dcmnet/apps/getscu.cc | 593 + dcmnet/apps/movescu.cc | 1626 + dcmnet/apps/storescp.cc | 2751 ++ dcmnet/apps/storescu.cc | 1746 + dcmnet/apps/termscu.cc | 297 + dcmnet/configure | 56 + dcmnet/data/Makefile.in | 23 + dcmnet/docs/CMakeLists.txt | 2 + dcmnet/docs/Makefile.in | 29 + dcmnet/docs/asconfig.txt | 236 + dcmnet/docs/cptscp.dox | 32 + dcmnet/docs/dcmnet.dox | 96 + dcmnet/docs/dcmrecv.man | 360 + dcmnet/docs/dcmsend.man | 412 + dcmnet/docs/echoscu.man | 247 + dcmnet/docs/findscu.man | 406 + dcmnet/docs/getscu.man | 536 + dcmnet/docs/movescu.man | 687 + dcmnet/docs/storescp.man | 842 + dcmnet/docs/storescu.man | 531 + dcmnet/docs/termscu.man | 148 + dcmnet/docs/testing.txt | 58 + dcmnet/etc/CMakeLists.txt | 2 + dcmnet/etc/Makefile.in | 29 + dcmnet/etc/storescp.cfg | 230 + dcmnet/etc/storescu.cfg | 293 + dcmnet/include/CMakeLists.txt | 2 + dcmnet/include/Makefile.in | 27 + dcmnet/include/dcmtk/dcmnet/assoc.h | 646 + dcmnet/include/dcmtk/dcmnet/cond.h | 264 + dcmnet/include/dcmtk/dcmnet/dcasccff.h | 99 + dcmnet/include/dcmtk/dcmnet/dcasccfg.h | 235 + dcmnet/include/dcmtk/dcmnet/dccfenmp.h | 196 + dcmnet/include/dcmtk/dcmnet/dccfpcmp.h | 188 + dcmnet/include/dcmtk/dcmnet/dccfprmp.h | 181 + dcmnet/include/dcmtk/dcmnet/dccfrsmp.h | 176 + dcmnet/include/dcmtk/dcmnet/dccftsmp.h | 111 + dcmnet/include/dcmtk/dcmnet/dccfuidh.h | 115 + dcmnet/include/dcmtk/dcmnet/dcmlayer.h | 106 + dcmnet/include/dcmtk/dcmnet/dcmsmap.h | 201 + dcmnet/include/dcmtk/dcmnet/dcmtrans.h | 331 + dcmnet/include/dcmtk/dcmnet/dcompat.h | 389 + dcmnet/include/dcmtk/dcmnet/dcuserid.h | 366 + dcmnet/include/dcmtk/dcmnet/dfindscu.h | 327 + dcmnet/include/dcmtk/dcmnet/dicom.h | 175 + dcmnet/include/dcmtk/dcmnet/dimse.h | 1102 + dcmnet/include/dcmtk/dcmnet/diutil.h | 135 + dcmnet/include/dcmtk/dcmnet/dndefine.h | 38 + dcmnet/include/dcmtk/dcmnet/dstorscp.h | 327 + dcmnet/include/dcmtk/dcmnet/dstorscu.h | 530 + dcmnet/include/dcmtk/dcmnet/dul.h | 509 + dcmnet/include/dcmtk/dcmnet/extneg.h | 56 + dcmnet/include/dcmtk/dcmnet/lst.h | 145 + dcmnet/include/dcmtk/dcmnet/scp.h | 1017 + dcmnet/include/dcmtk/dcmnet/scpcfg.h | 404 + dcmnet/include/dcmtk/dcmnet/scppool.h | 341 + dcmnet/include/dcmtk/dcmnet/scpthrd.h | 88 + dcmnet/include/dcmtk/dcmnet/scu.h | 1073 + dcmnet/libsrc/CMakeLists.txt | 5 + dcmnet/libsrc/Makefile.dep | 2458 ++ dcmnet/libsrc/Makefile.in | 56 + dcmnet/libsrc/assoc.cc | 2219 ++ dcmnet/libsrc/cond.cc | 134 + dcmnet/libsrc/dcasccff.cc | 486 + dcmnet/libsrc/dcasccfg.cc | 778 + dcmnet/libsrc/dccfenmp.cc | 270 + dcmnet/libsrc/dccfpcmp.cc | 219 + dcmnet/libsrc/dccfprmp.cc | 229 + dcmnet/libsrc/dccfrsmp.cc | 230 + dcmnet/libsrc/dccftsmp.cc | 156 + dcmnet/libsrc/dccfuidh.cc | 128 + dcmnet/libsrc/dcmlayer.cc | 35 + dcmnet/libsrc/dcmtrans.cc | 360 + dcmnet/libsrc/dcompat.cc | 474 + dcmnet/libsrc/dcuserid.cc | 637 + dcmnet/libsrc/dfindscu.cc | 561 + dcmnet/libsrc/dimcancl.cc | 141 + dcmnet/libsrc/dimcmd.cc | 2063 ++ dcmnet/libsrc/dimcmd.h | 103 + dcmnet/libsrc/dimdump.cc | 1169 + dcmnet/libsrc/dimecho.cc | 173 + dcmnet/libsrc/dimfind.cc | 458 + dcmnet/libsrc/dimget.cc | 371 + dcmnet/libsrc/dimmove.cc | 443 + dcmnet/libsrc/dimse.cc | 1781 + dcmnet/libsrc/dimstore.cc | 522 + dcmnet/libsrc/diutil.cc | 856 + dcmnet/libsrc/dstorscp.cc | 476 + dcmnet/libsrc/dstorscu.cc | 1206 + dcmnet/libsrc/dul.cc | 2731 ++ dcmnet/libsrc/dulconst.cc | 1526 + dcmnet/libsrc/dulextra.cc | 165 + dcmnet/libsrc/dulfsm.cc | 3961 +++ dcmnet/libsrc/dulfsm.h | 137 + dcmnet/libsrc/dulparse.cc | 832 + dcmnet/libsrc/dulpres.cc | 152 + dcmnet/libsrc/dulpriv.h | 114 + dcmnet/libsrc/dulstruc.h | 325 + dcmnet/libsrc/dwrap.c | 58 + dcmnet/libsrc/extneg.cc | 36 + dcmnet/libsrc/lst.cc | 148 + dcmnet/libsrc/scp.cc | 2003 ++ dcmnet/libsrc/scpcfg.cc | 455 + dcmnet/libsrc/scppool.cc | 350 + dcmnet/libsrc/scpthrd.cc | 75 + dcmnet/libsrc/scu.cc | 2499 ++ dcmnet/tests/CMakeLists.txt | 8 + dcmnet/tests/Makefile.dep | 231 + dcmnet/tests/Makefile.in | 52 + dcmnet/tests/tdump.cc | 50 + dcmnet/tests/tests.cc | 32 + dcmnet/tests/tpool.cc | 113 + dcmpstat/CMakeLists.txt | 10 + dcmpstat/Makefile.in | 99 + dcmpstat/apps/CMakeLists.txt | 12 + dcmpstat/apps/Makefile.dep | 1325 + dcmpstat/apps/Makefile.in | 138 + dcmpstat/apps/dcmmkcrv.cc | 403 + dcmpstat/apps/dcmmklut.cc | 1053 + dcmpstat/apps/dcmp2pgm.cc | 580 + dcmpstat/apps/dcmprscp.cc | 543 + dcmpstat/apps/dcmprscu.cc | 1147 + dcmpstat/apps/dcmpschk.cc | 1003 + dcmpstat/apps/dcmpsmk.cc | 389 + dcmpstat/apps/dcmpsprt.cc | 683 + dcmpstat/apps/dcmpsrcv.cc | 1468 + dcmpstat/apps/dcmpssnd.cc | 976 + dcmpstat/configure | 56 + dcmpstat/data/CMakeLists.txt | 2 + dcmpstat/data/Makefile.in | 31 + dcmpstat/data/philips.lut | 274 + dcmpstat/docs/Makefile.in | 23 + dcmpstat/docs/dcmmkcrv.man | 183 + dcmpstat/docs/dcmmklut.man | 253 + dcmpstat/docs/dcmp2pgm.man | 159 + dcmpstat/docs/dcmprscp.man | 146 + dcmpstat/docs/dcmprscu.man | 206 + dcmpstat/docs/dcmpschk.man | 137 + dcmpstat/docs/dcmpsmk.man | 250 + dcmpstat/docs/dcmpsprt.man | 317 + dcmpstat/docs/dcmpsrcv.man | 135 + dcmpstat/docs/dcmpssnd.man | 143 + dcmpstat/docs/dcmpstat.dox | 79 + dcmpstat/etc/CMakeLists.txt | 2 + dcmpstat/etc/Makefile.in | 29 + dcmpstat/etc/dcmpstat.cfg | 1384 + dcmpstat/etc/printers.cfg | 455 + dcmpstat/include/CMakeLists.txt | 2 + dcmpstat/include/Makefile.in | 27 + dcmpstat/include/dcmtk/dcmpstat/dcmpstat.h | 980 + dcmpstat/include/dcmtk/dcmpstat/dpdefine.h | 38 + dcmpstat/include/dcmtk/dcmpstat/dvcache.h | 897 + dcmpstat/include/dcmtk/dcmpstat/dviface.h | 1836 + dcmpstat/include/dcmtk/dcmpstat/dvpsab.h | 123 + dcmpstat/include/dcmtk/dcmpstat/dvpsabl.h | 156 + dcmpstat/include/dcmtk/dcmpstat/dvpsal.h | 114 + dcmpstat/include/dcmtk/dcmpstat/dvpsall.h | 175 + dcmpstat/include/dcmtk/dcmpstat/dvpscf.h | 1096 + dcmpstat/include/dcmtk/dcmpstat/dvpscu.h | 138 + dcmpstat/include/dcmtk/dcmpstat/dvpscul.h | 113 + dcmpstat/include/dcmtk/dcmpstat/dvpsda.h | 268 + dcmpstat/include/dcmtk/dcmpstat/dvpsdal.h | 142 + dcmpstat/include/dcmtk/dcmpstat/dvpsdef.h | 186 + dcmpstat/include/dcmtk/dcmpstat/dvpsfs.h | 179 + dcmpstat/include/dcmtk/dcmpstat/dvpsga.h | 186 + dcmpstat/include/dcmtk/dcmpstat/dvpsgal.h | 266 + dcmpstat/include/dcmtk/dcmpstat/dvpsgl.h | 167 + dcmpstat/include/dcmtk/dcmpstat/dvpsgll.h | 276 + dcmpstat/include/dcmtk/dcmpstat/dvpsgr.h | 140 + dcmpstat/include/dcmtk/dcmpstat/dvpsgrl.h | 116 + dcmpstat/include/dcmtk/dcmpstat/dvpshlp.h | 120 + dcmpstat/include/dcmtk/dcmpstat/dvpsib.h | 383 + dcmpstat/include/dcmtk/dcmpstat/dvpsibl.h | 388 + dcmpstat/include/dcmtk/dcmpstat/dvpsmsg.h | 273 + dcmpstat/include/dcmtk/dcmpstat/dvpsov.h | 167 + dcmpstat/include/dcmtk/dcmpstat/dvpsovl.h | 145 + dcmpstat/include/dcmtk/dcmpstat/dvpspl.h | 248 + dcmpstat/include/dcmtk/dcmpstat/dvpspll.h | 135 + dcmpstat/include/dcmtk/dcmpstat/dvpspr.h | 291 + dcmpstat/include/dcmtk/dcmpstat/dvpsprt.h | 313 + dcmpstat/include/dcmtk/dcmpstat/dvpsri.h | 173 + dcmpstat/include/dcmtk/dcmpstat/dvpsril.h | 208 + dcmpstat/include/dcmtk/dcmpstat/dvpsrs.h | 195 + dcmpstat/include/dcmtk/dcmpstat/dvpsrsl.h | 186 + dcmpstat/include/dcmtk/dcmpstat/dvpssp.h | 1117 + dcmpstat/include/dcmtk/dcmpstat/dvpsspl.h | 216 + dcmpstat/include/dcmtk/dcmpstat/dvpssv.h | 221 + dcmpstat/include/dcmtk/dcmpstat/dvpssvl.h | 164 + dcmpstat/include/dcmtk/dcmpstat/dvpstat.h | 1330 + dcmpstat/include/dcmtk/dcmpstat/dvpstx.h | 212 + dcmpstat/include/dcmtk/dcmpstat/dvpstxl.h | 118 + dcmpstat/include/dcmtk/dcmpstat/dvpstyp.h | 523 + dcmpstat/include/dcmtk/dcmpstat/dvpsvl.h | 97 + dcmpstat/include/dcmtk/dcmpstat/dvpsvll.h | 95 + dcmpstat/include/dcmtk/dcmpstat/dvpsvw.h | 100 + dcmpstat/include/dcmtk/dcmpstat/dvpsvwl.h | 94 + dcmpstat/include/dcmtk/dcmpstat/dvsighdl.h | 225 + dcmpstat/jni/Makefile.dep | 0 dcmpstat/jni/Makefile.in | 119 + dcmpstat/jni/make_stub.sh | 9 + dcmpstat/libsrc/CMakeLists.txt | 4 + dcmpstat/libsrc/Makefile.dep | 4622 +++ dcmpstat/libsrc/Makefile.in | 64 + dcmpstat/libsrc/dcmpstat.cc | 1935 ++ dcmpstat/libsrc/dviface.cc | 4223 +++ dcmpstat/libsrc/dvpsab.cc | 160 + dcmpstat/libsrc/dvpsabl.cc | 211 + dcmpstat/libsrc/dvpsal.cc | 101 + dcmpstat/libsrc/dvpsall.cc | 455 + dcmpstat/libsrc/dvpscf.cc | 1479 + dcmpstat/libsrc/dvpscu.cc | 343 + dcmpstat/libsrc/dvpscul.cc | 109 + dcmpstat/libsrc/dvpsda.cc | 441 + dcmpstat/libsrc/dvpsdal.cc | 198 + dcmpstat/libsrc/dvpsfs.cc | 834 + dcmpstat/libsrc/dvpsga.cc | 194 + dcmpstat/libsrc/dvpsgal.cc | 502 + dcmpstat/libsrc/dvpsgl.cc | 253 + dcmpstat/libsrc/dvpsgll.cc | 424 + dcmpstat/libsrc/dvpsgr.cc | 259 + dcmpstat/libsrc/dvpsgrl.cc | 157 + dcmpstat/libsrc/dvpshlp.cc | 220 + dcmpstat/libsrc/dvpsib.cc | 1307 + dcmpstat/libsrc/dvpsibl.cc | 582 + dcmpstat/libsrc/dvpsmsg.cc | 414 + dcmpstat/libsrc/dvpsov.cc | 253 + dcmpstat/libsrc/dvpsovl.cc | 186 + dcmpstat/libsrc/dvpspl.cc | 455 + dcmpstat/libsrc/dvpspl2.cc | 150 + dcmpstat/libsrc/dvpspll.cc | 249 + dcmpstat/libsrc/dvpspr.cc | 599 + dcmpstat/libsrc/dvpsprt.cc | 1091 + dcmpstat/libsrc/dvpsri.cc | 258 + dcmpstat/libsrc/dvpsril.cc | 333 + dcmpstat/libsrc/dvpsrs.cc | 218 + dcmpstat/libsrc/dvpsrsl.cc | 272 + dcmpstat/libsrc/dvpssp.cc | 3190 ++ dcmpstat/libsrc/dvpsspl.cc | 354 + dcmpstat/libsrc/dvpssv.cc | 332 + dcmpstat/libsrc/dvpssvl.cc | 311 + dcmpstat/libsrc/dvpstat.cc | 2166 ++ dcmpstat/libsrc/dvpstx.cc | 415 + dcmpstat/libsrc/dvpstxl.cc | 157 + dcmpstat/libsrc/dvpsvl.cc | 93 + dcmpstat/libsrc/dvpsvll.cc | 102 + dcmpstat/libsrc/dvpsvw.cc | 89 + dcmpstat/libsrc/dvpsvwl.cc | 107 + dcmpstat/libsrc/dvsighdl.cc | 865 + dcmpstat/tests/Makefile.dep | 56 + dcmpstat/tests/Makefile.in | 65 + dcmpstat/tests/dcmpschk.tcl | 161 + dcmpstat/tests/dcmpsprt.pl | 39 + dcmpstat/tests/msgserv.cc | 353 + dcmqrdb/CMakeLists.txt | 10 + dcmqrdb/Makefile.in | 97 + dcmqrdb/apps/CMakeLists.txt | 9 + dcmqrdb/apps/Makefile.dep | 219 + dcmqrdb/apps/Makefile.in | 74 + dcmqrdb/apps/dcmqridx.cc | 185 + dcmqrdb/apps/dcmqrscp.cc | 740 + dcmqrdb/apps/dcmqrti.cc | 399 + dcmqrdb/configure | 56 + dcmqrdb/data/Makefile.in | 23 + dcmqrdb/docs/CMakeLists.txt | 2 + dcmqrdb/docs/Makefile.in | 29 + dcmqrdb/docs/dcmqrcnf.txt | 136 + dcmqrdb/docs/dcmqrdb.dox | 32 + dcmqrdb/docs/dcmqridx.man | 136 + dcmqrdb/docs/dcmqrscp.man | 971 + dcmqrdb/docs/dcmqrset.txt | 122 + dcmqrdb/docs/dcmqrti.man | 448 + dcmqrdb/etc/CMakeLists.txt | 2 + dcmqrdb/etc/Makefile.in | 29 + dcmqrdb/etc/dcmqrscp.cfg | 77 + dcmqrdb/include/CMakeLists.txt | 2 + dcmqrdb/include/Makefile.in | 27 + dcmqrdb/include/dcmtk/dcmqrdb/dcmqrcbf.h | 94 + dcmqrdb/include/dcmtk/dcmqrdb/dcmqrcbg.h | 168 + dcmqrdb/include/dcmtk/dcmqrdb/dcmqrcbm.h | 182 + dcmqrdb/include/dcmtk/dcmqrdb/dcmqrcbs.h | 133 + dcmqrdb/include/dcmtk/dcmqrdb/dcmqrcnf.h | 444 + dcmqrdb/include/dcmtk/dcmqrdb/dcmqrdba.h | 223 + dcmqrdb/include/dcmtk/dcmqrdb/dcmqrdbi.h | 442 + dcmqrdb/include/dcmtk/dcmqrdb/dcmqrdbs.h | 78 + dcmqrdb/include/dcmtk/dcmqrdb/dcmqridx.h | 389 + dcmqrdb/include/dcmtk/dcmqrdb/dcmqropt.h | 166 + dcmqrdb/include/dcmtk/dcmqrdb/dcmqrptb.h | 96 + dcmqrdb/include/dcmtk/dcmqrdb/dcmqrsrv.h | 169 + dcmqrdb/include/dcmtk/dcmqrdb/dcmqrtis.h | 295 + dcmqrdb/include/dcmtk/dcmqrdb/qrdefine.h | 38 + dcmqrdb/libsrc/CMakeLists.txt | 4 + dcmqrdb/libsrc/Makefile.dep | 766 + dcmqrdb/libsrc/Makefile.in | 52 + dcmqrdb/libsrc/dcmqrcbf.cc | 90 + dcmqrdb/libsrc/dcmqrcbg.cc | 331 + dcmqrdb/libsrc/dcmqrcbm.cc | 677 + dcmqrdb/libsrc/dcmqrcbs.cc | 183 + dcmqrdb/libsrc/dcmqrcnf.cc | 1058 + dcmqrdb/libsrc/dcmqrdbi.cc | 3468 ++ dcmqrdb/libsrc/dcmqrdbs.cc | 73 + dcmqrdb/libsrc/dcmqropt.cc | 79 + dcmqrdb/libsrc/dcmqrptb.cc | 226 + dcmqrdb/libsrc/dcmqrsrv.cc | 1100 + dcmqrdb/libsrc/dcmqrtis.cc | 2194 ++ dcmqrdb/tests/Makefile.in | 29 + dcmrt/CHANGES | 802 + dcmrt/CMakeLists.txt | 10 + dcmrt/Makefile.in | 87 + dcmrt/apps/CMakeLists.txt | 5 + dcmrt/apps/Makefile.dep | 265 + dcmrt/apps/Makefile.in | 55 + dcmrt/apps/drtdump.cc | 517 + dcmrt/configure | 56 + dcmrt/docs/Makefile.in | 23 + dcmrt/docs/dcmrt.dox | 128 + dcmrt/docs/drtdump.man | 187 + dcmrt/include/CMakeLists.txt | 2 + dcmrt/include/Makefile.in | 31 + dcmrt/include/dcmtk/dcmrt/drmdose.h | 159 + dcmrt/include/dcmtk/dcmrt/drmimage.h | 276 + dcmrt/include/dcmtk/dcmrt/drmplan.h | 95 + dcmrt/include/dcmtk/dcmrt/drmsrch.h | 126 + dcmrt/include/dcmtk/dcmrt/drmstrct.h | 96 + dcmrt/include/dcmtk/dcmrt/drtdose.h | 4264 +++ dcmrt/include/dcmtk/dcmrt/drtimage.h | 4890 +++ dcmrt/include/dcmtk/dcmrt/drtionpl.h | 2743 ++ dcmrt/include/dcmtk/dcmrt/drtiontr.h | 2656 ++ dcmrt/include/dcmtk/dcmrt/drtplan.h | 2839 ++ dcmrt/include/dcmtk/dcmrt/drtstrct.h | 2534 ++ dcmrt/include/dcmtk/dcmrt/drttreat.h | 2472 ++ dcmrt/include/dcmtk/dcmrt/drttypes.h | 222 + dcmrt/include/dcmtk/dcmrt/seq/drtaadcs.h | 462 + dcmrt/include/dcmtk/dcmrt/seq/drtadcs.h | 462 + dcmrt/include/dcmtk/dcmrt/seq/drtads.h | 462 + dcmrt/include/dcmtk/dcmrt/seq/drtafs.h | 334 + dcmrt/include/dcmtk/dcmrt/seq/drtags.h | 350 + dcmrt/include/dcmtk/dcmrt/seq/drtajcs.h | 462 + dcmrt/include/dcmtk/dcmrt/seq/drtarics.h | 479 + dcmrt/include/dcmtk/dcmrt/seq/drtas1.h | 383 + dcmrt/include/dcmtk/dcmrt/seq/drtas5.h | 383 + dcmrt/include/dcmtk/dcmrt/seq/drtas6.h | 350 + dcmrt/include/dcmtk/dcmrt/seq/drtas7.h | 350 + dcmrt/include/dcmtk/dcmrt/seq/drtass.h | 482 + dcmrt/include/dcmtk/dcmrt/seq/drtbads.h | 442 + dcmrt/include/dcmtk/dcmrt/seq/drtbas.h | 462 + dcmrt/include/dcmtk/dcmrt/seq/drtbcps.h | 417 + dcmrt/include/dcmtk/dcmrt/seq/drtbl2.h | 542 + dcmrt/include/dcmtk/dcmrt/seq/drtbl5.h | 519 + dcmrt/include/dcmtk/dcmrt/seq/drtbldls.h | 325 + dcmrt/include/dcmtk/dcmrt/seq/drtbldps.h | 331 + dcmrt/include/dcmtk/dcmrt/seq/drtblds1.h | 377 + dcmrt/include/dcmtk/dcmrt/seq/drtblds5.h | 406 + dcmrt/include/dcmtk/dcmrt/seq/drtblds6.h | 406 + dcmrt/include/dcmtk/dcmrt/seq/drtbldts.h | 325 + dcmrt/include/dcmtk/dcmrt/seq/drtbrcss.h | 462 + dcmrt/include/dcmtk/dcmrt/seq/drtbrdrs.h | 332 + dcmrt/include/dcmtk/dcmrt/seq/drtbrs.h | 319 + dcmrt/include/dcmtk/dcmrt/seq/drtbs.h | 968 + dcmrt/include/dcmtk/dcmrt/seq/drtbvcps.h | 380 + dcmrt/include/dcmtk/dcmrt/seq/drtcbars.h | 479 + dcmrt/include/dcmtk/dcmrt/seq/drtccs.h | 462 + dcmrt/include/dcmtk/dcmrt/seq/drtcctus.h | 334 + dcmrt/include/dcmtk/dcmrt/seq/drtcdrs.h | 371 + dcmrt/include/dcmtk/dcmrt/seq/drtces.h | 549 + dcmrt/include/dcmtk/dcmrt/seq/drtchs.h | 782 + dcmrt/include/dcmtk/dcmrt/seq/drtcims.h | 537 + dcmrt/include/dcmtk/dcmrt/seq/drtcis.h | 357 + dcmrt/include/dcmtk/dcmrt/seq/drtcncs.h | 462 + dcmrt/include/dcmtk/dcmrt/seq/drtcos.h | 651 + dcmrt/include/dcmtk/dcmrt/seq/drtcpas.h | 357 + dcmrt/include/dcmtk/dcmrt/seq/drtcps.h | 865 + dcmrt/include/dcmtk/dcmrt/seq/drtcs.h | 469 + dcmrt/include/dcmtk/dcmrt/seq/drtcsas.h | 357 + dcmrt/include/dcmtk/dcmrt/seq/drtcshs.h | 426 + dcmrt/include/dcmtk/dcmrt/seq/drtcsis.h | 398 + dcmrt/include/dcmtk/dcmrt/seq/drtcss.h | 462 + dcmrt/include/dcmtk/dcmrt/seq/drtdcs.h | 462 + dcmrt/include/dcmtk/dcmrt/seq/drtdimcs.h | 462 + dcmrt/include/dcmtk/dcmrt/seq/drtdimrs.h | 318 + dcmrt/include/dcmtk/dcmrt/seq/drtdirs.h | 302 + dcmrt/include/dcmtk/dcmrt/seq/drtdrs.h | 701 + dcmrt/include/dcmtk/dcmrt/seq/drtds.h | 650 + dcmrt/include/dcmtk/dcmrt/seq/drtdspcs.h | 462 + dcmrt/include/dcmtk/dcmrt/seq/drtdss.h | 431 + dcmrt/include/dcmtk/dcmrt/seq/drtdvhs.h | 511 + dcmrt/include/dcmtk/dcmrt/seq/drtdvrrs.h | 325 + dcmrt/include/dcmtk/dcmrt/seq/drteas.h | 318 + dcmrt/include/dcmtk/dcmrt/seq/drtes.h | 748 + dcmrt/include/dcmtk/dcmrt/seq/drtfds.h | 398 + dcmrt/include/dcmtk/dcmrt/seq/drtfes.h | 350 + dcmrt/include/dcmtk/dcmrt/seq/drtfgs.h | 534 + dcmrt/include/dcmtk/dcmrt/seq/drtfgss.h | 388 + dcmrt/include/dcmtk/dcmrt/seq/drtfms.h | 325 + dcmrt/include/dcmtk/dcmrt/seq/drtfsss.h | 357 + dcmrt/include/dcmtk/dcmrt/seq/drtgas.h | 389 + dcmrt/include/dcmtk/dcmrt/seq/drthsdrs.h | 350 + dcmrt/include/dcmtk/dcmrt/seq/drtiais.h | 334 + dcmrt/include/dcmtk/dcmrt/seq/drtians.h | 334 + dcmrt/include/dcmtk/dcmrt/seq/drtiblds.h | 370 + dcmrt/include/dcmtk/dcmrt/seq/drtibls.h | 512 + dcmrt/include/dcmtk/dcmrt/seq/drtibs.h | 1204 + dcmrt/include/dcmtk/dcmrt/seq/drticpds.h | 996 + dcmrt/include/dcmtk/dcmrt/seq/drticps.h | 968 + dcmrt/include/dcmtk/dcmrt/seq/drtics.h | 462 + dcmrt/include/dcmtk/dcmrt/seq/drtiis.h | 613 + dcmrt/include/dcmtk/dcmrt/seq/drtipiqs.h | 381 + dcmrt/include/dcmtk/dcmrt/seq/drtircs.h | 618 + dcmrt/include/dcmtk/dcmrt/seq/drtiseis.h | 334 + dcmrt/include/dcmtk/dcmrt/seq/drtitts.h | 528 + dcmrt/include/dcmtk/dcmrt/seq/drtiwps.h | 341 + dcmrt/include/dcmtk/dcmrt/seq/drtiws.h | 419 + dcmrt/include/dcmtk/dcmrt/seq/drtlsds.h | 373 + dcmrt/include/dcmtk/dcmrt/seq/drtlsds6.h | 357 + dcmrt/include/dcmtk/dcmrt/seq/drtlsds7.h | 325 + dcmrt/include/dcmtk/dcmrt/seq/drtmacds.h | 342 + dcmrt/include/dcmtk/dcmrt/seq/drtmas.h | 282 + dcmrt/include/dcmtk/dcmrt/seq/drtmdrs.h | 403 + dcmrt/include/dcmtk/dcmrt/seq/drtmls.h | 350 + dcmrt/include/dcmtk/dcmrt/seq/drtmps.h | 350 + dcmrt/include/dcmtk/dcmrt/seq/drtmss.h | 350 + dcmrt/include/dcmtk/dcmrt/seq/drtmucs.h | 462 + dcmrt/include/dcmtk/dcmrt/seq/drtoas.h | 367 + dcmrt/include/dcmtk/dcmrt/seq/drtois.h | 382 + dcmrt/include/dcmtk/dcmrt/seq/drtopis.h | 351 + dcmrt/include/dcmtk/dcmrt/seq/drtos.h | 373 + dcmrt/include/dcmtk/dcmrt/seq/drtpbcs.h | 462 + dcmrt/include/dcmtk/dcmrt/seq/drtpcs.h | 462 + dcmrt/include/dcmtk/dcmrt/seq/drtpcxs.h | 552 + dcmrt/include/dcmtk/dcmrt/seq/drtpfms.h | 318 + dcmrt/include/dcmtk/dcmrt/seq/drtpics.h | 462 + dcmrt/include/dcmtk/dcmrt/seq/drtporcs.h | 462 + dcmrt/include/dcmtk/dcmrt/seq/drtporis.h | 382 + dcmrt/include/dcmtk/dcmrt/seq/drtppcs.h | 479 + dcmrt/include/dcmtk/dcmrt/seq/drtprsis.h | 382 + dcmrt/include/dcmtk/dcmrt/seq/drtpscs.h | 462 + dcmrt/include/dcmtk/dcmrt/seq/drtpsics.h | 462 + dcmrt/include/dcmtk/dcmrt/seq/drtpss.h | 535 + dcmrt/include/dcmtk/dcmrt/seq/drtpsss.h | 318 + dcmrt/include/dcmtk/dcmrt/seq/drtpvis.h | 514 + dcmrt/include/dcmtk/dcmrt/seq/drtras.h | 475 + dcmrt/include/dcmtk/dcmrt/seq/drtrbas2.h | 309 + dcmrt/include/dcmtk/dcmrt/seq/drtrbas8.h | 361 + dcmrt/include/dcmtk/dcmrt/seq/drtrbls.h | 357 + dcmrt/include/dcmtk/dcmrt/seq/drtrbos1.h | 357 + dcmrt/include/dcmtk/dcmrt/seq/drtrbos6.h | 325 + dcmrt/include/dcmtk/dcmrt/seq/drtrbos7.h | 325 + dcmrt/include/dcmtk/dcmrt/seq/drtrbs2.h | 326 + dcmrt/include/dcmtk/dcmrt/seq/drtrbs4.h | 417 + dcmrt/include/dcmtk/dcmrt/seq/drtrbs8.h | 417 + dcmrt/include/dcmtk/dcmrt/seq/drtrcdrs.h | 355 + dcmrt/include/dcmtk/dcmrt/seq/drtrcos.h | 341 + dcmrt/include/dcmtk/dcmrt/seq/drtrcps.h | 332 + dcmrt/include/dcmtk/dcmrt/seq/drtrcs.h | 349 + dcmrt/include/dcmtk/dcmrt/seq/drtrdros.h | 348 + dcmrt/include/dcmtk/dcmrt/seq/drtrdrs1.h | 332 + dcmrt/include/dcmtk/dcmrt/seq/drtrdrs6.h | 332 + dcmrt/include/dcmtk/dcmrt/seq/drtrdrs8.h | 562 + dcmrt/include/dcmtk/dcmrt/seq/drtrds.h | 318 + dcmrt/include/dcmtk/dcmrt/seq/drtrecs.h | 318 + dcmrt/include/dcmtk/dcmrt/seq/drtrfgs.h | 341 + dcmrt/include/dcmtk/dcmrt/seq/drtrfors.h | 319 + dcmrt/include/dcmtk/dcmrt/seq/drtrics.h | 462 + dcmrt/include/dcmtk/dcmrt/seq/drtrims.h | 374 + dcmrt/include/dcmtk/dcmrt/seq/drtris.h | 335 + dcmrt/include/dcmtk/dcmrt/seq/drtrlsds.h | 341 + dcmrt/include/dcmtk/dcmrt/seq/drtrmdrs.h | 355 + dcmrt/include/dcmtk/dcmrt/seq/drtrms.h | 389 + dcmrt/include/dcmtk/dcmrt/seq/drtrmss6.h | 389 + dcmrt/include/dcmtk/dcmrt/seq/drtrmss7.h | 341 + dcmrt/include/dcmtk/dcmrt/seq/drtrpcs.h | 462 + dcmrt/include/dcmtk/dcmrt/seq/drtrpis.h | 382 + dcmrt/include/dcmtk/dcmrt/seq/drtrppcs.h | 462 + dcmrt/include/dcmtk/dcmrt/seq/drtrpphs.h | 411 + dcmrt/include/dcmtk/dcmrt/seq/drtrpps.h | 342 + dcmrt/include/dcmtk/dcmrt/seq/drtrppss.h | 318 + dcmrt/include/dcmtk/dcmrt/seq/drtrps.h | 318 + dcmrt/include/dcmtk/dcmrt/seq/drtrris1.h | 387 + dcmrt/include/dcmtk/dcmrt/seq/drtrris6.h | 341 + dcmrt/include/dcmtk/dcmrt/seq/drtrris9.h | 318 + dcmrt/include/dcmtk/dcmrt/seq/drtrrms.h | 373 + dcmrt/include/dcmtk/dcmrt/seq/drtrros.h | 504 + dcmrt/include/dcmtk/dcmrt/seq/drtrrpcs.h | 462 + dcmrt/include/dcmtk/dcmrt/seq/drtrrros.h | 309 + dcmrt/include/dcmtk/dcmrt/seq/drtrrs.h | 325 + dcmrt/include/dcmtk/dcmrt/seq/drtrrshs.h | 341 + dcmrt/include/dcmtk/dcmrt/seq/drtrrtps.h | 335 + dcmrt/include/dcmtk/dcmrt/seq/drtrrtps3.h | 334 + dcmrt/include/dcmtk/dcmrt/seq/drtrrtps4.h | 318 + dcmrt/include/dcmtk/dcmrt/seq/drtrrtps5.h | 318 + dcmrt/include/dcmtk/dcmrt/seq/drtrscs.h | 462 + dcmrt/include/dcmtk/dcmrt/seq/drtrsers.h | 319 + dcmrt/include/dcmtk/dcmrt/seq/drtrses.h | 319 + dcmrt/include/dcmtk/dcmrt/seq/drtrshs.h | 373 + dcmrt/include/dcmtk/dcmrt/seq/drtrshs6.h | 357 + dcmrt/include/dcmtk/dcmrt/seq/drtrshs7.h | 325 + dcmrt/include/dcmtk/dcmrt/seq/drtrsis.h | 373 + dcmrt/include/dcmtk/dcmrt/seq/drtrsns.h | 318 + dcmrt/include/dcmtk/dcmrt/seq/drtrsos.h | 373 + dcmrt/include/dcmtk/dcmrt/seq/drtrsrs.h | 318 + dcmrt/include/dcmtk/dcmrt/seq/drtrss.h | 318 + dcmrt/include/dcmtk/dcmrt/seq/drtrsss.h | 318 + dcmrt/include/dcmtk/dcmrt/seq/drtrsts.h | 335 + dcmrt/include/dcmtk/dcmrt/seq/drtrtrs2.h | 335 + dcmrt/include/dcmtk/dcmrt/seq/drtrtrs4.h | 318 + dcmrt/include/dcmtk/dcmrt/seq/drtrvis.h | 318 + dcmrt/include/dcmtk/dcmrt/seq/drtrws.h | 403 + dcmrt/include/dcmtk/dcmrt/seq/drtrwvms.h | 415 + dcmrt/include/dcmtk/dcmrt/seq/drtscris.h | 319 + dcmrt/include/dcmtk/dcmrt/seq/drtsdcs.h | 462 + dcmrt/include/dcmtk/dcmrt/seq/drtsds.h | 389 + dcmrt/include/dcmtk/dcmrt/seq/drtshds.h | 366 + dcmrt/include/dcmtk/dcmrt/seq/drtsis.h | 406 + dcmrt/include/dcmtk/dcmrt/seq/drtsns.h | 318 + dcmrt/include/dcmtk/dcmrt/seq/drtspccs.h | 462 + dcmrt/include/dcmtk/dcmrt/seq/drtspcs.h | 479 + dcmrt/include/dcmtk/dcmrt/seq/drtss.h | 630 + dcmrt/include/dcmtk/dcmrt/seq/drtssrs.h | 429 + dcmrt/include/dcmtk/dcmrt/seq/drttms0.h | 398 + dcmrt/include/dcmtk/dcmrt/seq/drttms9.h | 398 + dcmrt/include/dcmtk/dcmrt/seq/drttscds.h | 348 + dcmrt/include/dcmtk/dcmrt/seq/drttsibs.h | 1213 + dcmrt/include/dcmtk/dcmrt/seq/drttsmds.h | 348 + dcmrt/include/dcmtk/dcmrt/seq/drttts.h | 551 + dcmrt/include/dcmtk/dcmrt/seq/drtvls.h | 334 + dcmrt/include/dcmtk/dcmrt/seq/drtwps.h | 325 + dcmrt/include/dcmtk/dcmrt/seq/drtwrs.h | 302 + dcmrt/include/dcmtk/dcmrt/seq/drtws.h | 449 + dcmrt/include/dcmtk/dcmrt/seq/drtxrs.h | 318 + dcmrt/libsrc/CMakeLists.txt | 4 + dcmrt/libsrc/Makefile.dep | 24333 ++++++++++++++ dcmrt/libsrc/Makefile.in | 82 + dcmrt/libsrc/drmdose.cc | 342 + dcmrt/libsrc/drmimage.cc | 106 + dcmrt/libsrc/drmplan.cc | 90 + dcmrt/libsrc/drmstrct.cc | 122 + dcmrt/libsrc/drtaadcs.cc | 834 + dcmrt/libsrc/drtadcs.cc | 834 + dcmrt/libsrc/drtads.cc | 834 + dcmrt/libsrc/drtafs.cc | 602 + dcmrt/libsrc/drtags.cc | 619 + dcmrt/libsrc/drtajcs.cc | 834 + dcmrt/libsrc/drtarics.cc | 841 + dcmrt/libsrc/drtas1.cc | 663 + dcmrt/libsrc/drtas5.cc | 663 + dcmrt/libsrc/drtas6.cc | 631 + dcmrt/libsrc/drtas7.cc | 631 + dcmrt/libsrc/drtass.cc | 795 + dcmrt/libsrc/drtbads.cc | 783 + dcmrt/libsrc/drtbas.cc | 834 + dcmrt/libsrc/drtbcps.cc | 708 + dcmrt/libsrc/drtbl2.cc | 955 + dcmrt/libsrc/drtbl5.cc | 917 + dcmrt/libsrc/drtbldls.cc | 582 + dcmrt/libsrc/drtbldps.cc | 591 + dcmrt/libsrc/drtblds1.cc | 667 + dcmrt/libsrc/drtblds5.cc | 714 + dcmrt/libsrc/drtblds6.cc | 714 + dcmrt/libsrc/drtbldts.cc | 582 + dcmrt/libsrc/drtbrcss.cc | 834 + dcmrt/libsrc/drtbrdrs.cc | 591 + dcmrt/libsrc/drtbrs.cc | 551 + dcmrt/libsrc/drtbs.cc | 1461 + dcmrt/libsrc/drtbvcps.cc | 666 + dcmrt/libsrc/drtcbars.cc | 841 + dcmrt/libsrc/drtccs.cc | 834 + dcmrt/libsrc/drtcctus.cc | 602 + dcmrt/libsrc/drtcdrs.cc | 658 + dcmrt/libsrc/drtces.cc | 944 + dcmrt/libsrc/drtchs.cc | 1311 + dcmrt/libsrc/drtcims.cc | 868 + dcmrt/libsrc/drtcis.cc | 636 + dcmrt/libsrc/drtcncs.cc | 834 + dcmrt/libsrc/drtcos.cc | 1134 + dcmrt/libsrc/drtcpas.cc | 636 + dcmrt/libsrc/drtcps.cc | 1409 + dcmrt/libsrc/drtcs.cc | 797 + dcmrt/libsrc/drtcsas.cc | 636 + dcmrt/libsrc/drtcshs.cc | 754 + dcmrt/libsrc/drtcsis.cc | 718 + dcmrt/libsrc/drtcss.cc | 834 + dcmrt/libsrc/drtdcs.cc | 834 + dcmrt/libsrc/drtdimcs.cc | 834 + dcmrt/libsrc/drtdimrs.cc | 573 + dcmrt/libsrc/drtdirs.cc | 544 + dcmrt/libsrc/drtdose.cc | 4869 +++ dcmrt/libsrc/drtdrs.cc | 1210 + dcmrt/libsrc/drtds.cc | 1160 + dcmrt/libsrc/drtdspcs.cc | 834 + dcmrt/libsrc/drtdss.cc | 768 + dcmrt/libsrc/drtdvhs.cc | 875 + dcmrt/libsrc/drtdvrrs.cc | 582 + dcmrt/libsrc/drteas.cc | 579 + dcmrt/libsrc/drtes.cc | 1178 + dcmrt/libsrc/drtfds.cc | 710 + dcmrt/libsrc/drtfes.cc | 619 + dcmrt/libsrc/drtfgs.cc | 858 + dcmrt/libsrc/drtfgss.cc | 665 + dcmrt/libsrc/drtfms.cc | 582 + dcmrt/libsrc/drtfsss.cc | 640 + dcmrt/libsrc/drtgas.cc | 694 + dcmrt/libsrc/drthsdrs.cc | 631 + dcmrt/libsrc/drtiais.cc | 602 + dcmrt/libsrc/drtians.cc | 602 + dcmrt/libsrc/drtiblds.cc | 654 + dcmrt/libsrc/drtibls.cc | 904 + dcmrt/libsrc/drtibs.cc | 1813 + dcmrt/libsrc/drticpds.cc | 1569 + dcmrt/libsrc/drticps.cc | 1535 + dcmrt/libsrc/drtics.cc | 834 + dcmrt/libsrc/drtiis.cc | 1054 + dcmrt/libsrc/drtimage.cc | 5547 ++++ dcmrt/libsrc/drtionpl.cc | 3033 ++ dcmrt/libsrc/drtiontr.cc | 2887 ++ dcmrt/libsrc/drtipiqs.cc | 623 + dcmrt/libsrc/drtircs.cc | 1069 + dcmrt/libsrc/drtiseis.cc | 602 + dcmrt/libsrc/drtitts.cc | 892 + dcmrt/libsrc/drtiwps.cc | 607 + dcmrt/libsrc/drtiws.cc | 741 + dcmrt/libsrc/drtlsds.cc | 669 + dcmrt/libsrc/drtlsds6.cc | 632 + dcmrt/libsrc/drtlsds7.cc | 582 + dcmrt/libsrc/drtmacds.cc | 589 + dcmrt/libsrc/drtmas.cc | 516 + dcmrt/libsrc/drtmdrs.cc | 716 + dcmrt/libsrc/drtmls.cc | 633 + dcmrt/libsrc/drtmps.cc | 627 + dcmrt/libsrc/drtmss.cc | 631 + dcmrt/libsrc/drtmucs.cc | 834 + dcmrt/libsrc/drtoas.cc | 638 + dcmrt/libsrc/drtois.cc | 645 + dcmrt/libsrc/drtopis.cc | 609 + dcmrt/libsrc/drtos.cc | 669 + dcmrt/libsrc/drtpbcs.cc | 834 + dcmrt/libsrc/drtpcs.cc | 834 + dcmrt/libsrc/drtpcxs.cc | 875 + dcmrt/libsrc/drtpfms.cc | 573 + dcmrt/libsrc/drtpics.cc | 834 + dcmrt/libsrc/drtplan.cc | 3146 ++ dcmrt/libsrc/drtporcs.cc | 834 + dcmrt/libsrc/drtporis.cc | 645 + dcmrt/libsrc/drtppcs.cc | 841 + dcmrt/libsrc/drtprsis.cc | 645 + dcmrt/libsrc/drtpscs.cc | 834 + dcmrt/libsrc/drtpsics.cc | 834 + dcmrt/libsrc/drtpss.cc | 847 + dcmrt/libsrc/drtpsss.cc | 573 + dcmrt/libsrc/drtpvis.cc | 895 + dcmrt/libsrc/drtras.cc | 753 + dcmrt/libsrc/drtrbas2.cc | 553 + dcmrt/libsrc/drtrbas8.cc | 638 + dcmrt/libsrc/drtrbls.cc | 640 + dcmrt/libsrc/drtrbos1.cc | 640 + dcmrt/libsrc/drtrbos6.cc | 582 + dcmrt/libsrc/drtrbos7.cc | 582 + dcmrt/libsrc/drtrbs2.cc | 560 + dcmrt/libsrc/drtrbs4.cc | 708 + dcmrt/libsrc/drtrbs8.cc | 708 + dcmrt/libsrc/drtrcdrs.cc | 629 + dcmrt/libsrc/drtrcos.cc | 611 + dcmrt/libsrc/drtrcps.cc | 591 + dcmrt/libsrc/drtrcs.cc | 598 + dcmrt/libsrc/drtrdros.cc | 620 + dcmrt/libsrc/drtrdrs1.cc | 591 + dcmrt/libsrc/drtrdrs6.cc | 591 + dcmrt/libsrc/drtrdrs8.cc | 971 + dcmrt/libsrc/drtrds.cc | 573 + dcmrt/libsrc/drtrecs.cc | 565 + dcmrt/libsrc/drtrfgs.cc | 567 + dcmrt/libsrc/drtrfors.cc | 551 + dcmrt/libsrc/drtrics.cc | 834 + dcmrt/libsrc/drtrims.cc | 643 + dcmrt/libsrc/drtris.cc | 580 + dcmrt/libsrc/drtrlsds.cc | 611 + dcmrt/libsrc/drtrmdrs.cc | 629 + dcmrt/libsrc/drtrms.cc | 698 + dcmrt/libsrc/drtrmss6.cc | 678 + dcmrt/libsrc/drtrmss7.cc | 603 + dcmrt/libsrc/drtrpcs.cc | 834 + dcmrt/libsrc/drtrpis.cc | 645 + dcmrt/libsrc/drtrppcs.cc | 834 + dcmrt/libsrc/drtrpphs.cc | 637 + dcmrt/libsrc/drtrpps.cc | 589 + dcmrt/libsrc/drtrppss.cc | 573 + dcmrt/libsrc/drtrps.cc | 573 + dcmrt/libsrc/drtrris1.cc | 687 + dcmrt/libsrc/drtrris6.cc | 611 + dcmrt/libsrc/drtrris9.cc | 573 + dcmrt/libsrc/drtrrms.cc | 669 + dcmrt/libsrc/drtrros.cc | 778 + dcmrt/libsrc/drtrrpcs.cc | 834 + dcmrt/libsrc/drtrrros.cc | 553 + dcmrt/libsrc/drtrrs.cc | 582 + dcmrt/libsrc/drtrrshs.cc | 611 + dcmrt/libsrc/drtrrtps.cc | 580 + dcmrt/libsrc/drtrrtps3.cc | 602 + dcmrt/libsrc/drtrrtps4.cc | 573 + dcmrt/libsrc/drtrrtps5.cc | 573 + dcmrt/libsrc/drtrscs.cc | 834 + dcmrt/libsrc/drtrsers.cc | 551 + dcmrt/libsrc/drtrses.cc | 551 + dcmrt/libsrc/drtrshs.cc | 669 + dcmrt/libsrc/drtrshs6.cc | 632 + dcmrt/libsrc/drtrshs7.cc | 582 + dcmrt/libsrc/drtrsis.cc | 665 + dcmrt/libsrc/drtrsns.cc | 573 + dcmrt/libsrc/drtrsos.cc | 665 + dcmrt/libsrc/drtrsrs.cc | 573 + dcmrt/libsrc/drtrss.cc | 573 + dcmrt/libsrc/drtrsss.cc | 573 + dcmrt/libsrc/drtrsts.cc | 580 + dcmrt/libsrc/drtrtrs2.cc | 580 + dcmrt/libsrc/drtrtrs4.cc | 573 + dcmrt/libsrc/drtrvis.cc | 573 + dcmrt/libsrc/drtrws.cc | 716 + dcmrt/libsrc/drtrwvms.cc | 705 + dcmrt/libsrc/drtscris.cc | 551 + dcmrt/libsrc/drtsdcs.cc | 834 + dcmrt/libsrc/drtsds.cc | 698 + dcmrt/libsrc/drtshds.cc | 660 + dcmrt/libsrc/drtsis.cc | 701 + dcmrt/libsrc/drtsns.cc | 573 + dcmrt/libsrc/drtspccs.cc | 834 + dcmrt/libsrc/drtspcs.cc | 841 + dcmrt/libsrc/drtss.cc | 1109 + dcmrt/libsrc/drtssrs.cc | 743 + dcmrt/libsrc/drtstrct.cc | 2789 ++ dcmrt/libsrc/drttms0.cc | 718 + dcmrt/libsrc/drttms9.cc | 718 + dcmrt/libsrc/drttreat.cc | 2696 ++ dcmrt/libsrc/drttscds.cc | 620 + dcmrt/libsrc/drttsibs.cc | 1803 + dcmrt/libsrc/drttsmds.cc | 620 + dcmrt/libsrc/drttts.cc | 930 + dcmrt/libsrc/drttypes.cc | 236 + dcmrt/libsrc/drtvls.cc | 604 + dcmrt/libsrc/drtwps.cc | 582 + dcmrt/libsrc/drtwrs.cc | 544 + dcmrt/libsrc/drtws.cc | 792 + dcmrt/libsrc/drtxrs.cc | 573 + dcmrt/tests/CMakeLists.txt | 10 + dcmrt/tests/Makefile.dep | 461 + dcmrt/tests/Makefile.in | 59 + dcmrt/tests/drttest.cc | 131 + dcmrt/tests/tests.cc | 27 + dcmrt/tests/tsearch.cc | 49 + dcmseg/CMakeLists.txt | 10 + dcmseg/Makefile.in | 86 + dcmseg/configure | 53 + dcmseg/data/Makefile.in | 23 + dcmseg/docs/Makefile.in | 23 + dcmseg/docs/dcmseg.dox | 16 + dcmseg/etc/Makefile.in | 23 + dcmseg/include/CMakeLists.txt | 2 + dcmseg/include/Makefile.in | 27 + dcmseg/include/dcmtk/dcmseg/segdef.h | 37 + dcmseg/include/dcmtk/dcmseg/segdoc.h | 622 + dcmseg/include/dcmtk/dcmseg/segment.h | 271 + dcmseg/include/dcmtk/dcmseg/segtypes.h | 345 + dcmseg/include/dcmtk/dcmseg/segutils.h | 67 + dcmseg/libsrc/CMakeLists.txt | 5 + dcmseg/libsrc/Makefile.dep | 532 + dcmseg/libsrc/Makefile.in | 56 + dcmseg/libsrc/segdoc.cc | 1266 + dcmseg/libsrc/segment.cc | 341 + dcmseg/libsrc/segtypes.cc | 345 + dcmseg/libsrc/segutils.cc | 130 + dcmseg/tests/Makefile.in | 29 + dcmsign/CMakeLists.txt | 10 + dcmsign/Makefile.in | 97 + dcmsign/apps/CMakeLists.txt | 6 + dcmsign/apps/Makefile.dep | 118 + dcmsign/apps/Makefile.in | 50 + dcmsign/apps/dcmsign.cc | 1163 + dcmsign/configure | 56 + dcmsign/data/Makefile.in | 23 + dcmsign/docs/Makefile.in | 23 + dcmsign/docs/dcmsign.dox | 90 + dcmsign/docs/dcmsign.man | 333 + dcmsign/etc/Makefile.in | 23 + dcmsign/include/CMakeLists.txt | 2 + dcmsign/include/Makefile.in | 27 + dcmsign/include/dcmtk/dcmsign/dcsignat.h | 263 + dcmsign/include/dcmtk/dcmsign/sialgo.h | 100 + dcmsign/include/dcmtk/dcmsign/siautopr.h | 53 + dcmsign/include/dcmtk/dcmsign/sibrsapr.h | 78 + dcmsign/include/dcmtk/dcmsign/sicert.h | 144 + dcmsign/include/dcmtk/dcmsign/sicertvf.h | 103 + dcmsign/include/dcmtk/dcmsign/sicreapr.h | 53 + dcmsign/include/dcmtk/dcmsign/sidefine.h | 38 + dcmsign/include/dcmtk/dcmsign/sidsa.h | 114 + dcmsign/include/dcmtk/dcmsign/simac.h | 83 + dcmsign/include/dcmtk/dcmsign/simaccon.h | 164 + dcmsign/include/dcmtk/dcmsign/simd5.h | 96 + dcmsign/include/dcmtk/dcmsign/sinullpr.h | 80 + dcmsign/include/dcmtk/dcmsign/siprivat.h | 114 + dcmsign/include/dcmtk/dcmsign/siripemd.h | 96 + dcmsign/include/dcmtk/dcmsign/sirsa.h | 116 + dcmsign/include/dcmtk/dcmsign/sisha1.h | 96 + dcmsign/include/dcmtk/dcmsign/sisprof.h | 130 + dcmsign/include/dcmtk/dcmsign/sitstamp.h | 66 + dcmsign/include/dcmtk/dcmsign/sitypes.h | 128 + dcmsign/libsrc/CMakeLists.txt | 5 + dcmsign/libsrc/Makefile.dep | 554 + dcmsign/libsrc/Makefile.in | 51 + dcmsign/libsrc/dcsignat.cc | 819 + dcmsign/libsrc/siautopr.cc | 79 + dcmsign/libsrc/sibrsapr.cc | 82 + dcmsign/libsrc/sicert.cc | 304 + dcmsign/libsrc/sicertvf.cc | 129 + dcmsign/libsrc/sicreapr.cc | 95 + dcmsign/libsrc/sidsa.cc | 125 + dcmsign/libsrc/simaccon.cc | 196 + dcmsign/libsrc/simd5.cc | 90 + dcmsign/libsrc/sinullpr.cc | 60 + dcmsign/libsrc/siprivat.cc | 189 + dcmsign/libsrc/siripemd.cc | 88 + dcmsign/libsrc/sirsa.cc | 125 + dcmsign/libsrc/sisha1.cc | 89 + dcmsign/libsrc/sisprof.cc | 139 + dcmsign/libsrc/sitypes.cc | 51 + dcmsign/tests/Makefile.in | 30 + dcmsr/CMakeLists.txt | 10 + dcmsr/Makefile.in | 102 + dcmsr/apps/CMakeLists.txt | 9 + dcmsr/apps/Makefile.dep | 520 + dcmsr/apps/Makefile.in | 66 + dcmsr/apps/dsr2html.cc | 501 + dcmsr/apps/dsr2xml.cc | 422 + dcmsr/apps/dsrdump.cc | 375 + dcmsr/apps/xml2dsr.cc | 367 + dcmsr/configure | 56 + dcmsr/data/CMakeLists.txt | 2 + dcmsr/data/Makefile.in | 29 + dcmsr/data/dsr2xml.xsd | 977 + dcmsr/data/report.css | 91 + dcmsr/data/reportx.css | 104 + dcmsr/docs/Makefile.in | 23 + dcmsr/docs/dcmsr.dox | 104 + dcmsr/docs/dsr2html.man | 348 + dcmsr/docs/dsr2xml.man | 331 + dcmsr/docs/dsrdump.man | 293 + dcmsr/docs/xml2dsr.man | 308 + dcmsr/etc/Makefile.in | 23 + dcmsr/include/CMakeLists.txt | 2 + dcmsr/include/Makefile.in | 29 + dcmsr/include/dcmtk/dcmsr/cmr/cid100.h | 169 + dcmsr/include/dcmtk/dcmsr/cmr/cid10013.h | 155 + dcmsr/include/dcmtk/dcmsr/cmr/cid10013e.h | 94 + dcmsr/include/dcmtk/dcmsr/cmr/cid10033.h | 149 + dcmsr/include/dcmtk/dcmsr/cmr/cid10033e.h | 98 + dcmsr/include/dcmtk/dcmsr/cmr/cid11.h | 187 + dcmsr/include/dcmtk/dcmsr/cmr/cid244.h | 153 + dcmsr/include/dcmtk/dcmsr/cmr/cid244e.h | 94 + dcmsr/include/dcmtk/dcmsr/cmr/cid29.h | 219 + dcmsr/include/dcmtk/dcmsr/cmr/cid29e.h | 85 + dcmsr/include/dcmtk/dcmsr/cmr/cid4020.h | 215 + dcmsr/include/dcmtk/dcmsr/cmr/cid4021.h | 297 + dcmsr/include/dcmtk/dcmsr/cmr/cid4031.h | 359 + dcmsr/include/dcmtk/dcmsr/cmr/cid4031e.h | 98 + dcmsr/include/dcmtk/dcmsr/cmr/cid42.h | 169 + dcmsr/include/dcmtk/dcmsr/cmr/cid5000.h | 168 + dcmsr/include/dcmtk/dcmsr/cmr/cid5001.h | 157 + dcmsr/include/dcmtk/dcmsr/cmr/cid7021.h | 153 + dcmsr/include/dcmtk/dcmsr/cmr/cid7445.h | 151 + dcmsr/include/dcmtk/dcmsr/cmr/cid7452.h | 181 + dcmsr/include/dcmtk/dcmsr/cmr/cid7453.h | 165 + dcmsr/include/dcmtk/dcmsr/cmr/define.h | 28 + dcmsr/include/dcmtk/dcmsr/cmr/init.h | 72 + dcmsr/include/dcmtk/dcmsr/cmr/logger.h | 35 + dcmsr/include/dcmtk/dcmsr/cmr/srnumvl.h | 106 + dcmsr/include/dcmtk/dcmsr/cmr/tid1001.h | 110 + dcmsr/include/dcmtk/dcmsr/cmr/tid1204.h | 58 + dcmsr/include/dcmtk/dcmsr/cmr/tid1600.h | 254 + dcmsr/include/dcmtk/dcmsr/codes/dcm.h | 3207 ++ dcmsr/include/dcmtk/dcmsr/codes/srt.h | 49 + dcmsr/include/dcmtk/dcmsr/codes/ucum.h | 56 + dcmsr/include/dcmtk/dcmsr/dsdefine.h | 38 + dcmsr/include/dcmtk/dcmsr/dsrbascc.h | 87 + dcmsr/include/dcmtk/dcmsr/dsrc3dcc.h | 87 + dcmsr/include/dcmtk/dcmsr/dsrchecc.h | 87 + dcmsr/include/dcmtk/dcmsr/dsrcitem.h | 619 + dcmsr/include/dcmtk/dcmsr/dsrcodtn.h | 157 + dcmsr/include/dcmtk/dcmsr/dsrcodvl.h | 713 + dcmsr/include/dcmtk/dcmsr/dsrcolcc.h | 87 + dcmsr/include/dcmtk/dcmsr/dsrcomcc.h | 87 + dcmsr/include/dcmtk/dcmsr/dsrcomtn.h | 155 + dcmsr/include/dcmtk/dcmsr/dsrcomvl.h | 368 + dcmsr/include/dcmtk/dcmsr/dsrcontn.h | 208 + dcmsr/include/dcmtk/dcmsr/dsrcsidl.h | 352 + dcmsr/include/dcmtk/dcmsr/dsrctpl.h | 182 + dcmsr/include/dcmtk/dcmsr/dsrctxgr.h | 281 + dcmsr/include/dcmtk/dcmsr/dsrdattn.h | 191 + dcmsr/include/dcmtk/dcmsr/dsrdoc.h | 1324 + dcmsr/include/dcmtk/dcmsr/dsrdocst.h | 524 + dcmsr/include/dcmtk/dcmsr/dsrdoctn.h | 747 + dcmsr/include/dcmtk/dcmsr/dsrdoctr.h | 250 + dcmsr/include/dcmtk/dcmsr/dsrdtitn.h | 191 + dcmsr/include/dcmtk/dcmsr/dsrenhcc.h | 87 + dcmsr/include/dcmtk/dcmsr/dsrimgfr.h | 99 + dcmsr/include/dcmtk/dcmsr/dsrimgse.h | 99 + dcmsr/include/dcmtk/dcmsr/dsrimgtn.h | 166 + dcmsr/include/dcmtk/dcmsr/dsrimgvl.h | 462 + dcmsr/include/dcmtk/dcmsr/dsrimpcc.h | 88 + dcmsr/include/dcmtk/dcmsr/dsriodcc.h | 87 + dcmsr/include/dcmtk/dcmsr/dsrkeycc.h | 88 + dcmsr/include/dcmtk/dcmsr/dsrmaccc.h | 88 + dcmsr/include/dcmtk/dcmsr/dsrmamcc.h | 87 + dcmsr/include/dcmtk/dcmsr/dsrnumtn.h | 157 + dcmsr/include/dcmtk/dcmsr/dsrnumvl.h | 498 + dcmsr/include/dcmtk/dcmsr/dsrpnmtn.h | 190 + dcmsr/include/dcmtk/dcmsr/dsrprocc.h | 87 + dcmsr/include/dcmtk/dcmsr/dsrrefin.h | 266 + dcmsr/include/dcmtk/dcmsr/dsrreftn.h | 297 + dcmsr/include/dcmtk/dcmsr/dsrrrdcc.h | 88 + dcmsr/include/dcmtk/dcmsr/dsrrtpl.h | 186 + dcmsr/include/dcmtk/dcmsr/dsrsc3gr.h | 177 + dcmsr/include/dcmtk/dcmsr/dsrsc3tn.h | 163 + dcmsr/include/dcmtk/dcmsr/dsrsc3vl.h | 298 + dcmsr/include/dcmtk/dcmsr/dsrscogr.h | 186 + dcmsr/include/dcmtk/dcmsr/dsrscotn.h | 163 + dcmsr/include/dcmtk/dcmsr/dsrscovl.h | 267 + dcmsr/include/dcmtk/dcmsr/dsrsoprf.h | 625 + dcmsr/include/dcmtk/dcmsr/dsrspecc.h | 88 + dcmsr/include/dcmtk/dcmsr/dsrstpl.h | 154 + dcmsr/include/dcmtk/dcmsr/dsrstrvl.h | 211 + dcmsr/include/dcmtk/dcmsr/dsrtcodt.h | 102 + dcmsr/include/dcmtk/dcmsr/dsrtcosp.h | 99 + dcmsr/include/dcmtk/dcmsr/dsrtcotn.h | 163 + dcmsr/include/dcmtk/dcmsr/dsrtcoto.h | 99 + dcmsr/include/dcmtk/dcmsr/dsrtcovl.h | 265 + dcmsr/include/dcmtk/dcmsr/dsrtextn.h | 184 + dcmsr/include/dcmtk/dcmsr/dsrtimtn.h | 191 + dcmsr/include/dcmtk/dcmsr/dsrtlist.h | 259 + dcmsr/include/dcmtk/dcmsr/dsrtnant.h | 128 + dcmsr/include/dcmtk/dcmsr/dsrtncsr.h | 775 + dcmsr/include/dcmtk/dcmsr/dsrtree.h | 896 + dcmsr/include/dcmtk/dcmsr/dsrtypes.h | 1510 + dcmsr/include/dcmtk/dcmsr/dsruidtn.h | 175 + dcmsr/include/dcmtk/dcmsr/dsrwavch.h | 188 + dcmsr/include/dcmtk/dcmsr/dsrwavtn.h | 163 + dcmsr/include/dcmtk/dcmsr/dsrwavvl.h | 221 + dcmsr/include/dcmtk/dcmsr/dsrxmlc.h | 137 + dcmsr/include/dcmtk/dcmsr/dsrxmld.h | 297 + dcmsr/include/dcmtk/dcmsr/dsrxrdcc.h | 87 + dcmsr/libcmr/CMakeLists.txt | 4 + dcmsr/libcmr/Makefile.dep | 3104 ++ dcmsr/libcmr/Makefile.in | 54 + dcmsr/libcmr/cid100.cc | 173 + dcmsr/libcmr/cid10013.cc | 166 + dcmsr/libcmr/cid10013e.cc | 88 + dcmsr/libcmr/cid10033.cc | 163 + dcmsr/libcmr/cid10033e.cc | 82 + dcmsr/libcmr/cid11.cc | 182 + dcmsr/libcmr/cid244.cc | 165 + dcmsr/libcmr/cid244e.cc | 86 + dcmsr/libcmr/cid29.cc | 198 + dcmsr/libcmr/cid29e.cc | 70 + dcmsr/libcmr/cid4020.cc | 196 + dcmsr/libcmr/cid4021.cc | 237 + dcmsr/libcmr/cid4031.cc | 268 + dcmsr/libcmr/cid4031e.cc | 187 + dcmsr/libcmr/cid42.cc | 173 + dcmsr/libcmr/cid5000.cc | 172 + dcmsr/libcmr/cid5001.cc | 167 + dcmsr/libcmr/cid7021.cc | 165 + dcmsr/libcmr/cid7445.cc | 164 + dcmsr/libcmr/cid7452.cc | 179 + dcmsr/libcmr/cid7453.cc | 171 + dcmsr/libcmr/init.cc | 80 + dcmsr/libcmr/logger.cc | 22 + dcmsr/libcmr/srnumvl.cc | 80 + dcmsr/libcmr/tid1001.cc | 204 + dcmsr/libcmr/tid1204.cc | 62 + dcmsr/libcmr/tid1600.cc | 580 + dcmsr/libsrc/CMakeLists.txt | 5 + dcmsr/libsrc/Makefile.dep | 7517 +++++ dcmsr/libsrc/Makefile.in | 63 + dcmsr/libsrc/dsrbascc.cc | 127 + dcmsr/libsrc/dsrc3dcc.cc | 141 + dcmsr/libsrc/dsrchecc.cc | 129 + dcmsr/libsrc/dsrcitem.cc | 772 + dcmsr/libsrc/dsrcodtn.cc | 178 + dcmsr/libsrc/dsrcodvl.cc | 771 + dcmsr/libsrc/dsrcolcc.cc | 127 + dcmsr/libsrc/dsrcomcc.cc | 139 + dcmsr/libsrc/dsrcomtn.cc | 145 + dcmsr/libsrc/dsrcomvl.cc | 409 + dcmsr/libsrc/dsrcontn.cc | 232 + dcmsr/libsrc/dsrcsidl.cc | 609 + dcmsr/libsrc/dsrctpl.cc | 139 + dcmsr/libsrc/dsrctxgr.cc | 209 + dcmsr/libsrc/dsrdattn.cc | 211 + dcmsr/libsrc/dsrdoc.cc | 2856 ++ dcmsr/libsrc/dsrdocst.cc | 908 + dcmsr/libsrc/dsrdoctn.cc | 1335 + dcmsr/libsrc/dsrdoctr.cc | 442 + dcmsr/libsrc/dsrdtitn.cc | 216 + dcmsr/libsrc/dsrenhcc.cc | 142 + dcmsr/libsrc/dsrimgfr.cc | 174 + dcmsr/libsrc/dsrimgse.cc | 160 + dcmsr/libsrc/dsrimgtn.cc | 149 + dcmsr/libsrc/dsrimgvl.cc | 723 + dcmsr/libsrc/dsrimpcc.cc | 102 + dcmsr/libsrc/dsriodcc.cc | 36 + dcmsr/libsrc/dsrkeycc.cc | 93 + dcmsr/libsrc/dsrmaccc.cc | 104 + dcmsr/libsrc/dsrmamcc.cc | 123 + dcmsr/libsrc/dsrnumtn.cc | 139 + dcmsr/libsrc/dsrnumvl.cc | 691 + dcmsr/libsrc/dsrpnmtn.cc | 225 + dcmsr/libsrc/dsrprocc.cc | 114 + dcmsr/libsrc/dsrrefin.cc | 454 + dcmsr/libsrc/dsrreftn.cc | 297 + dcmsr/libsrc/dsrrrdcc.cc | 117 + dcmsr/libsrc/dsrrtpl.cc | 137 + dcmsr/libsrc/dsrsc3gr.cc | 236 + dcmsr/libsrc/dsrsc3tn.cc | 161 + dcmsr/libsrc/dsrsc3vl.cc | 404 + dcmsr/libsrc/dsrscogr.cc | 211 + dcmsr/libsrc/dsrscotn.cc | 161 + dcmsr/libsrc/dsrscovl.cc | 352 + dcmsr/libsrc/dsrsoprf.cc | 1507 + dcmsr/libsrc/dsrspecc.cc | 82 + dcmsr/libsrc/dsrstpl.cc | 117 + dcmsr/libsrc/dsrstrvl.cc | 209 + dcmsr/libsrc/dsrtcodt.cc | 161 + dcmsr/libsrc/dsrtcosp.cc | 163 + dcmsr/libsrc/dsrtcotn.cc | 161 + dcmsr/libsrc/dsrtcoto.cc | 170 + dcmsr/libsrc/dsrtcovl.cc | 358 + dcmsr/libsrc/dsrtextn.cc | 173 + dcmsr/libsrc/dsrtimtn.cc | 210 + dcmsr/libsrc/dsrtncsr.cc | 29 + dcmsr/libsrc/dsrtree.cc | 32 + dcmsr/libsrc/dsrtypes.cc | 1684 + dcmsr/libsrc/dsruidtn.cc | 162 + dcmsr/libsrc/dsrwavch.cc | 195 + dcmsr/libsrc/dsrwavtn.cc | 149 + dcmsr/libsrc/dsrwavvl.cc | 263 + dcmsr/libsrc/dsrxmlc.cc | 112 + dcmsr/libsrc/dsrxmld.cc | 713 + dcmsr/libsrc/dsrxrdcc.cc | 133 + dcmsr/tests/CMakeLists.txt | 10 + dcmsr/tests/Makefile.dep | 1057 + dcmsr/tests/Makefile.in | 62 + dcmsr/tests/gmon.out | Bin 0 -> 2537788 bytes dcmsr/tests/mkreport.cc | 1258 + dcmsr/tests/tests.cc | 80 + dcmsr/tests/tsrcmr.cc | 315 + dcmsr/tests/tsrcodvl.cc | 134 + dcmsr/tests/tsrdoc.cc | 98 + dcmsr/tests/tsrdoctr.cc | 439 + dcmsr/tests/tsrnumvl.cc | 46 + dcmsr/tests/tsrtpl.cc | 170 + dcmsr/tests/tsrtree.cc | 516 + dcmtls/CMakeLists.txt | 10 + dcmtls/Makefile.in | 97 + dcmtls/apps/Makefile.dep | 0 dcmtls/apps/Makefile.in | 29 + dcmtls/configure | 56 + dcmtls/data/Makefile.in | 23 + dcmtls/docs/CMakeLists.txt | 2 + dcmtls/docs/Makefile.in | 29 + dcmtls/docs/ciphers.txt | 478 + dcmtls/docs/dcmtls.dox | 67 + dcmtls/docs/randseed.txt | 109 + dcmtls/etc/Makefile.in | 23 + dcmtls/include/CMakeLists.txt | 2 + dcmtls/include/Makefile.in | 27 + dcmtls/include/dcmtk/dcmtls/tlsdefin.h | 38 + dcmtls/include/dcmtk/dcmtls/tlslayer.h | 299 + dcmtls/include/dcmtk/dcmtls/tlsscu.h | 239 + dcmtls/include/dcmtk/dcmtls/tlstrans.h | 157 + dcmtls/libsrc/CMakeLists.txt | 5 + dcmtls/libsrc/Makefile.dep | 234 + dcmtls/libsrc/Makefile.in | 50 + dcmtls/libsrc/tlslayer.cc | 514 + dcmtls/libsrc/tlsscu.cc | 364 + dcmtls/libsrc/tlstrans.cc | 354 + dcmtls/tests/Makefile.in | 30 + dcmtls/tests/dcmtk_ca.pl | 461 + dcmwlm/CMakeLists.txt | 10 + dcmwlm/Makefile.in | 97 + dcmwlm/apps/CMakeLists.txt | 8 + dcmwlm/apps/Makefile.dep | 148 + dcmwlm/apps/Makefile.in | 68 + dcmwlm/apps/wlcefs.cc | 404 + dcmwlm/apps/wlcefs.h | 120 + dcmwlm/apps/wlmscpfs.cc | 49 + dcmwlm/configure | 56 + dcmwlm/data/CMakeLists.txt | 2 + dcmwlm/data/Makefile.in | 30 + dcmwlm/data/wlistdb/OFFIS/lockfile | 0 dcmwlm/data/wlistdb/OFFIS/wklist1.dump | 29 + dcmwlm/data/wlistdb/OFFIS/wklist10.dump | 29 + dcmwlm/data/wlistdb/OFFIS/wklist2.dump | 30 + dcmwlm/data/wlistdb/OFFIS/wklist3.dump | 29 + dcmwlm/data/wlistdb/OFFIS/wklist4.dump | 29 + dcmwlm/data/wlistdb/OFFIS/wklist5.dump | 29 + dcmwlm/data/wlistdb/OFFIS/wklist6.dump | 29 + dcmwlm/data/wlistdb/OFFIS/wklist7.dump | 29 + dcmwlm/data/wlistdb/OFFIS/wklist8.dump | 29 + dcmwlm/data/wlistdb/OFFIS/wklist9.dump | 29 + dcmwlm/data/wlistdb/README | 62 + dcmwlm/data/wlistqry/README | 16 + dcmwlm/data/wlistqry/wlistqry0.dump | 11 + dcmwlm/data/wlistqry/wlistqry1.dump | 19 + dcmwlm/data/wlistqry/wlistqry10.dump | 18 + dcmwlm/data/wlistqry/wlistqry11.dump | 31 + dcmwlm/data/wlistqry/wlistqry12.dump | 12 + dcmwlm/data/wlistqry/wlistqry2.dump | 31 + dcmwlm/data/wlistqry/wlistqry3.dump | 8 + dcmwlm/data/wlistqry/wlistqry4.dump | 9 + dcmwlm/data/wlistqry/wlistqry5.dump | 13 + dcmwlm/data/wlistqry/wlistqry6.dump | 10 + dcmwlm/data/wlistqry/wlistqry7.dump | 31 + dcmwlm/data/wlistqry/wlistqry8.dump | 11 + dcmwlm/data/wlistqry/wlistqry9.dump | 17 + dcmwlm/docs/Makefile.in | 23 + dcmwlm/docs/dcmwlm.dox | 29 + dcmwlm/docs/wlmscpfs.man | 444 + dcmwlm/etc/Makefile.in | 23 + dcmwlm/include/CMakeLists.txt | 2 + dcmwlm/include/Makefile.in | 27 + dcmwlm/include/dcmtk/dcmwlm/wldefine.h | 38 + dcmwlm/include/dcmtk/dcmwlm/wlds.h | 521 + dcmwlm/include/dcmtk/dcmwlm/wldsfs.h | 192 + dcmwlm/include/dcmtk/dcmwlm/wlfsim.h | 473 + dcmwlm/include/dcmtk/dcmwlm/wlmactmg.h | 218 + dcmwlm/include/dcmtk/dcmwlm/wltypdef.h | 128 + dcmwlm/libsrc/CMakeLists.txt | 4 + dcmwlm/libsrc/Makefile.dep | 355 + dcmwlm/libsrc/Makefile.in | 51 + dcmwlm/libsrc/wlds.cc | 1456 + dcmwlm/libsrc/wldsfs.cc | 776 + dcmwlm/libsrc/wlfsim.cc | 2045 ++ dcmwlm/libsrc/wlmactmg.cc | 1143 + dcmwlm/tests/Makefile.dep | 76 + dcmwlm/tests/Makefile.in | 54 + dcmwlm/tests/wltest.cc | 357 + docs/ANNOUNCE.310 | 28 + docs/ANNOUNCE.311 | 28 + docs/ANNOUNCE.312 | 28 + docs/ANNOUNCE.320 | 37 + docs/ANNOUNCE.321 | 37 + docs/ANNOUNCE.330 | 39 + docs/ANNOUNCE.331 | 45 + docs/ANNOUNCE.340 | 78 + docs/ANNOUNCE.341 | 66 + docs/ANNOUNCE.342 | 60 + docs/ANNOUNCE.350 | 57 + docs/ANNOUNCE.351 | 68 + docs/ANNOUNCE.352 | 129 + docs/ANNOUNCE.353 | 131 + docs/ANNOUNCE.354 | 143 + docs/ANNOUNCE.360 | 238 + docs/CHANGES.301 | 48 + docs/CHANGES.302 | 52 + docs/CHANGES.310 | 28 + docs/CHANGES.311 | 140 + docs/CHANGES.312 | 117 + docs/CHANGES.320 | 734 + docs/CHANGES.321 | 27 + docs/CHANGES.330 | 968 + docs/CHANGES.331 | 285 + docs/CHANGES.340 | 2932 ++ docs/CHANGES.341 | 2347 ++ docs/CHANGES.342 | 2594 ++ docs/CHANGES.350 | 505 + docs/CHANGES.351 | 2057 ++ docs/CHANGES.352 | 3812 +++ docs/CHANGES.353 | 5482 +++ docs/CHANGES.354 | 2262 ++ docs/CHANGES.360 | 12506 +++++++ docs/CHANGES.361 | 13726 ++++++++ docs/DCMIMAGE.11X | 1006 + doxygen/CMakeLists.txt | 66 + doxygen/Makefile.in | 68 + doxygen/configure | 56 + doxygen/footer.html | 5 + doxygen/htmldocs.cfg | 2364 ++ doxygen/htmldocs.dox | 79 + doxygen/layout.xml | 197 + doxygen/man2text.sh | 7 + doxygen/manpages.cfg | 2354 ++ doxygen/manpages/man1/dcm2pdf.1 | 160 + doxygen/manpages/man1/dcm2pnm.1 | 455 + doxygen/manpages/man1/dcm2xml.1 | 286 + doxygen/manpages/man1/dcmcjpeg.1 | 618 + doxygen/manpages/man1/dcmcjpls.1 | 333 + doxygen/manpages/man1/dcmconv.1 | 321 + doxygen/manpages/man1/dcmcrle.1 | 213 + doxygen/manpages/man1/dcmdjpeg.1 | 283 + doxygen/manpages/man1/dcmdjpls.1 | 238 + doxygen/manpages/man1/dcmdrle.1 | 209 + doxygen/manpages/man1/dcmdspfn.1 | 146 + doxygen/manpages/man1/dcmdump.1 | 336 + doxygen/manpages/man1/dcmftest.1 | 31 + doxygen/manpages/man1/dcmgpdir.1 | 231 + doxygen/manpages/man1/dcmj2pnm.1 | 501 + doxygen/manpages/man1/dcml2pnm.1 | 457 + doxygen/manpages/man1/dcmmkcrv.1 | 128 + doxygen/manpages/man1/dcmmkdir.1 | 412 + doxygen/manpages/man1/dcmmklut.1 | 192 + doxygen/manpages/man1/dcmodify.1 | 440 + doxygen/manpages/man1/dcmp2pgm.1 | 108 + doxygen/manpages/man1/dcmprscp.1 | 93 + doxygen/manpages/man1/dcmprscu.1 | 150 + doxygen/manpages/man1/dcmpschk.1 | 86 + doxygen/manpages/man1/dcmpsmk.1 | 200 + doxygen/manpages/man1/dcmpsprt.1 | 277 + doxygen/manpages/man1/dcmpsrcv.1 | 82 + doxygen/manpages/man1/dcmpssnd.1 | 87 + doxygen/manpages/man1/dcmqridx.1 | 88 + doxygen/manpages/man1/dcmqrscp.1 | 896 + doxygen/manpages/man1/dcmqrti.1 | 327 + doxygen/manpages/man1/dcmquant.1 | 241 + doxygen/manpages/man1/dcmrecv.1 | 286 + doxygen/manpages/man1/dcmscale.1 | 233 + doxygen/manpages/man1/dcmsend.1 | 320 + doxygen/manpages/man1/dcmsign.1 | 281 + doxygen/manpages/man1/dcod2lum.1 | 50 + doxygen/manpages/man1/dconvlum.1 | 37 + doxygen/manpages/man1/drtdump.1 | 135 + doxygen/manpages/man1/dsr2html.1 | 290 + doxygen/manpages/man1/dsr2xml.1 | 260 + doxygen/manpages/man1/dsrdump.1 | 243 + doxygen/manpages/man1/dump2dcm.1 | 266 + doxygen/manpages/man1/echoscu.1 | 204 + doxygen/manpages/man1/findscu.1 | 343 + doxygen/manpages/man1/getscu.1 | 456 + doxygen/manpages/man1/img2dcm.1 | 347 + doxygen/manpages/man1/movescu.1 | 589 + doxygen/manpages/man1/pdf2dcm.1 | 135 + doxygen/manpages/man1/storescp.1 | 708 + doxygen/manpages/man1/storescu.1 | 462 + doxygen/manpages/man1/termscu.1 | 102 + doxygen/manpages/man1/wlmscpfs.1 | 361 + doxygen/manpages/man1/xml2dcm.1 | 276 + doxygen/manpages/man1/xml2dsr.1 | 242 + doxygen/patchman.sh | 11 + oflog/CMakeLists.txt | 10 + oflog/Makefile.in | 89 + oflog/configure | 56 + oflog/data/Makefile.in | 23 + oflog/docs/LICENSE | 459 + oflog/docs/Makefile.in | 23 + oflog/docs/oflog.dox | 91 + oflog/etc/CMakeLists.txt | 2 + oflog/etc/Makefile.in | 29 + oflog/etc/filelog.cfg | 42 + oflog/etc/logger.cfg | 196 + oflog/include/CMakeLists.txt | 2 + oflog/include/Makefile.in | 43 + oflog/include/dcmtk/oflog/appender.h | 260 + oflog/include/dcmtk/oflog/asyncap.h | 93 + oflog/include/dcmtk/oflog/clfsap.h | 101 + oflog/include/dcmtk/oflog/clogger.h | 85 + oflog/include/dcmtk/oflog/config.h | 172 + oflog/include/dcmtk/oflog/config/defines.h | 363 + oflog/include/dcmtk/oflog/config/macosx.h | 37 + oflog/include/dcmtk/oflog/config/win32.h | 169 + oflog/include/dcmtk/oflog/config/windowsh.h | 159 + oflog/include/dcmtk/oflog/configrt.h | 372 + oflog/include/dcmtk/oflog/consap.h | 87 + oflog/include/dcmtk/oflog/fileap.h | 285 + oflog/include/dcmtk/oflog/fstreams.h | 59 + oflog/include/dcmtk/oflog/helpers/apndimpl.h | 121 + oflog/include/dcmtk/oflog/helpers/fileinfo.h | 62 + oflog/include/dcmtk/oflog/helpers/lloguser.h | 66 + oflog/include/dcmtk/oflog/helpers/lockfile.h | 73 + oflog/include/dcmtk/oflog/helpers/loglog.h | 146 + oflog/include/dcmtk/oflog/helpers/pointer.h | 195 + oflog/include/dcmtk/oflog/helpers/property.h | 162 + oflog/include/dcmtk/oflog/helpers/queue.h | 160 + oflog/include/dcmtk/oflog/helpers/sleep.h | 45 + oflog/include/dcmtk/oflog/helpers/snprintf.h | 63 + oflog/include/dcmtk/oflog/helpers/sockbuff.h | 81 + oflog/include/dcmtk/oflog/helpers/socket.h | 138 + oflog/include/dcmtk/oflog/helpers/strhelp.h | 201 + oflog/include/dcmtk/oflog/helpers/threadcf.h | 61 + oflog/include/dcmtk/oflog/helpers/timehelp.h | 183 + oflog/include/dcmtk/oflog/hierarchy.h | 327 + oflog/include/dcmtk/oflog/hierlock.h | 83 + oflog/include/dcmtk/oflog/internal/cygwin32.h | 56 + oflog/include/dcmtk/oflog/internal/env.h | 89 + oflog/include/dcmtk/oflog/internal/internal.h | 249 + oflog/include/dcmtk/oflog/internal/socket.h | 120 + oflog/include/dcmtk/oflog/layout.h | 598 + oflog/include/dcmtk/oflog/log4judp.h | 91 + oflog/include/dcmtk/oflog/logger.h | 324 + oflog/include/dcmtk/oflog/loglevel.h | 211 + oflog/include/dcmtk/oflog/logmacro.h | 416 + oflog/include/dcmtk/oflog/mdc.h | 80 + oflog/include/dcmtk/oflog/ndc.h | 329 + oflog/include/dcmtk/oflog/ntelogap.h | 86 + oflog/include/dcmtk/oflog/nullap.h | 67 + oflog/include/dcmtk/oflog/oflog.h | 134 + oflog/include/dcmtk/oflog/socketap.h | 173 + oflog/include/dcmtk/oflog/spi/apndatch.h | 92 + oflog/include/dcmtk/oflog/spi/factory.h | 275 + oflog/include/dcmtk/oflog/spi/filter.h | 289 + oflog/include/dcmtk/oflog/spi/logevent.h | 231 + oflog/include/dcmtk/oflog/spi/logfact.h | 62 + oflog/include/dcmtk/oflog/spi/logimpl.h | 221 + oflog/include/dcmtk/oflog/spi/objreg.h | 108 + oflog/include/dcmtk/oflog/spi/rootlog.h | 77 + oflog/include/dcmtk/oflog/streams.h | 59 + oflog/include/dcmtk/oflog/syslogap.h | 121 + oflog/include/dcmtk/oflog/tchar.h | 66 + .../dcmtk/oflog/thread/impl/syncimpl.h | 241 + .../dcmtk/oflog/thread/impl/syncpmsm.h | 119 + .../dcmtk/oflog/thread/impl/syncpthr.h | 515 + .../include/dcmtk/oflog/thread/impl/syncwin.h | 331 + .../dcmtk/oflog/thread/impl/thredimp.h | 162 + oflog/include/dcmtk/oflog/thread/impl/tls.h | 182 + oflog/include/dcmtk/oflog/thread/syncprim.h | 387 + oflog/include/dcmtk/oflog/thread/syncpub.h | 301 + oflog/include/dcmtk/oflog/thread/threads.h | 96 + oflog/include/dcmtk/oflog/tracelog.h | 82 + oflog/include/dcmtk/oflog/tstring.h | 104 + oflog/include/dcmtk/oflog/version.h | 56 + oflog/include/dcmtk/oflog/winconap.h | 84 + oflog/include/dcmtk/oflog/windebap.h | 71 + oflog/libsrc/CMakeLists.txt | 13 + oflog/libsrc/Makefile.dep | 1512 + oflog/libsrc/Makefile.in | 56 + oflog/libsrc/apndimpl.cc | 179 + oflog/libsrc/appender.cc | 359 + oflog/libsrc/asyncap.cc | 205 + oflog/libsrc/clfsap.cc | 304 + oflog/libsrc/clogger.cc | 189 + oflog/libsrc/config.cc | 758 + oflog/libsrc/consap.cc | 116 + oflog/libsrc/cygwin32.cc | 49 + oflog/libsrc/env.cc | 103 + oflog/libsrc/factory.cc | 190 + oflog/libsrc/fileap.cc | 912 + oflog/libsrc/fileinfo.cc | 74 + oflog/libsrc/filter.cc | 266 + oflog/libsrc/globinit.cc | 512 + oflog/libsrc/hierarchy.cc | 379 + oflog/libsrc/hierlock.cc | 137 + oflog/libsrc/layout.cc | 158 + oflog/libsrc/lloguser.cc | 55 + oflog/libsrc/lockfile.cc | 338 + oflog/libsrc/log4judp.cc | 263 + oflog/libsrc/logevent.cc | 265 + oflog/libsrc/logger.cc | 337 + oflog/libsrc/logimpl.cc | 178 + oflog/libsrc/loglevel.cc | 211 + oflog/libsrc/loglog.cc | 190 + oflog/libsrc/logmacro.cc | 91 + oflog/libsrc/mdc.cc | 98 + oflog/libsrc/ndc.cc | 312 + oflog/libsrc/ntelogap.cc | 351 + oflog/libsrc/nullap.cc | 78 + oflog/libsrc/objreg.cc | 121 + oflog/libsrc/oflog.cc | 260 + oflog/libsrc/patlay.cc | 1117 + oflog/libsrc/pointer.cc | 115 + oflog/libsrc/property.cc | 395 + oflog/libsrc/queue.cc | 191 + oflog/libsrc/rootlog.cc | 67 + oflog/libsrc/sleep.cc | 112 + oflog/libsrc/snprintf.cc | 244 + oflog/libsrc/sockbuff.cc | 283 + oflog/libsrc/socket.cc | 243 + oflog/libsrc/socketap.cc | 343 + oflog/libsrc/strccloc.cc | 233 + oflog/libsrc/strcloc.cc | 156 + oflog/libsrc/strhelp.cc | 222 + oflog/libsrc/striconv.cc | 268 + oflog/libsrc/syncprims.cc | 53 + oflog/libsrc/syslogap.cc | 430 + oflog/libsrc/threads.cc | 442 + oflog/libsrc/timehelp.cc | 530 + oflog/libsrc/tls.cc | 42 + oflog/libsrc/unixsock.cc | 421 + oflog/libsrc/version.cc | 40 + oflog/libsrc/winconap.cc | 187 + oflog/libsrc/windebap.cc | 90 + oflog/libsrc/winsock.cc | 396 + oflog/tests/Makefile.dep | 0 oflog/tests/Makefile.in | 29 + ofstd/CMakeLists.txt | 10 + ofstd/Makefile.in | 89 + ofstd/configure | 56 + ofstd/data/Makefile.in | 23 + ofstd/docs/Makefile.in | 23 + ofstd/docs/ofstd.dox | 54 + ofstd/etc/Makefile.in | 23 + ofstd/include/CMakeLists.txt | 2 + ofstd/include/Makefile.in | 31 + ofstd/include/dcmtk/ofstd/ofalgo.h | 214 + ofstd/include/dcmtk/ofstd/ofalign.h | 214 + ofstd/include/dcmtk/ofstd/ofaptr.h | 175 + ofstd/include/dcmtk/ofstd/ofbmanip.h | 154 + ofstd/include/dcmtk/ofstd/ofcast.h | 70 + ofstd/include/dcmtk/ofstd/ofchrenc.h | 404 + ofstd/include/dcmtk/ofstd/ofcmdln.h | 1067 + ofstd/include/dcmtk/ofstd/ofconapp.h | 238 + ofstd/include/dcmtk/ofstd/ofcond.h | 403 + ofstd/include/dcmtk/ofstd/ofconfig.h | 551 + ofstd/include/dcmtk/ofstd/ofconsol.h | 265 + ofstd/include/dcmtk/ofstd/ofcrc32.h | 81 + ofstd/include/dcmtk/ofstd/ofdate.h | 262 + ofstd/include/dcmtk/ofstd/ofdatime.h | 241 + ofstd/include/dcmtk/ofstd/ofdefine.h | 109 + ofstd/include/dcmtk/ofstd/ofexbl.h | 96 + ofstd/include/dcmtk/ofstd/ofexport.h | 60 + ofstd/include/dcmtk/ofstd/offile.h | 1038 + ofstd/include/dcmtk/ofstd/offname.h | 76 + ofstd/include/dcmtk/ofstd/ofglobal.h | 129 + ofstd/include/dcmtk/ofstd/ofgrp.h | 103 + ofstd/include/dcmtk/ofstd/oflimits.h | 1415 + ofstd/include/dcmtk/ofstd/oflist.h | 570 + ofstd/include/dcmtk/ofstd/ofmap.h | 233 + ofstd/include/dcmtk/ofstd/ofmem.h | 421 + ofstd/include/dcmtk/ofstd/ofnetdb.h | 101 + ofstd/include/dcmtk/ofstd/ofoption.h | 1084 + ofstd/include/dcmtk/ofstd/ofoset.h | 499 + ofstd/include/dcmtk/ofstd/ofpwd.h | 110 + ofstd/include/dcmtk/ofstd/ofset.h | 252 + ofstd/include/dcmtk/ofstd/ofsetit.h | 141 + ofstd/include/dcmtk/ofstd/ofstack.h | 277 + ofstd/include/dcmtk/ofstd/ofstd.h | 991 + ofstd/include/dcmtk/ofstd/ofstdinc.h | 381 + ofstd/include/dcmtk/ofstd/ofstream.h | 138 + ofstd/include/dcmtk/ofstd/ofstring.h | 1109 + ofstd/include/dcmtk/ofstd/oftempf.h | 122 + ofstd/include/dcmtk/ofstd/oftest.h | 515 + ofstd/include/dcmtk/ofstd/ofthread.h | 563 + ofstd/include/dcmtk/ofstd/oftime.h | 434 + ofstd/include/dcmtk/ofstd/oftimer.h | 94 + ofstd/include/dcmtk/ofstd/oftraits.h | 497 + ofstd/include/dcmtk/ofstd/oftuple.h | 733 + ofstd/include/dcmtk/ofstd/oftypes.h | 219 + ofstd/include/dcmtk/ofstd/ofuoset.h | 437 + ofstd/include/dcmtk/ofstd/ofutil.h | 528 + ofstd/include/dcmtk/ofstd/ofuuid.h | 143 + ofstd/include/dcmtk/ofstd/ofvector.h | 399 + ofstd/include/dcmtk/ofstd/ofxml.h | 803 + ofstd/include/dcmtk/ofstd/variadic/tuple.h | 2034 ++ ofstd/include/dcmtk/ofstd/variadic/tuplefrd.h | 29 + ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h | 69 + ofstd/libsrc/CMakeLists.txt | 4 + ofstd/libsrc/Makefile.dep | 142 + ofstd/libsrc/Makefile.in | 47 + ofstd/libsrc/ofchrenc.cc | 492 + ofstd/libsrc/ofcmdln.cc | 1709 + ofstd/libsrc/ofconapp.cc | 345 + ofstd/libsrc/ofcond.cc | 52 + ofstd/libsrc/ofconfig.cc | 635 + ofstd/libsrc/ofconsol.cc | 137 + ofstd/libsrc/ofcrc32.cc | 99 + ofstd/libsrc/ofdate.cc | 306 + ofstd/libsrc/ofdatime.cc | 266 + ofstd/libsrc/offile.cc | 207 + ofstd/libsrc/offname.cc | 139 + ofstd/libsrc/oflist.cc | 113 + ofstd/libsrc/ofmath.cc | 132 + ofstd/libsrc/ofstd.cc | 2869 ++ ofstd/libsrc/ofstring.cc | 1056 + ofstd/libsrc/oftempf.cc | 138 + ofstd/libsrc/ofthread.cc | 1003 + ofstd/libsrc/oftime.cc | 639 + ofstd/libsrc/oftimer.cc | 91 + ofstd/libsrc/ofuuid.cc | 366 + ofstd/libsrc/ofxml.cc | 3011 ++ ofstd/tests/CMakeLists.txt | 13 + ofstd/tests/Makefile.dep | 223 + ofstd/tests/Makefile.in | 54 + ofstd/tests/tatof.cc | 118 + ofstd/tests/tbase64.cc | 129 + ofstd/tests/tchrenc.cc | 226 + ofstd/tests/tests.cc | 80 + ofstd/tests/tftoa.cc | 152 + ofstd/tests/tlimits.cc | 76 + ofstd/tests/tlist.cc | 258 + ofstd/tests/tmap.cc | 74 + ofstd/tests/tmarkup.cc | 127 + ofstd/tests/tmem.cc | 95 + ofstd/tests/tofdatim.cc | 200 + ofstd/tests/toffile.cc | 397 + ofstd/tests/tofstd.cc | 258 + ofstd/tests/toption.cc | 104 + ofstd/tests/tstack.cc | 55 + ofstd/tests/tstlist.exp | 43 + ofstd/tests/tstring.cc | 296 + ofstd/tests/tthread.cc | 585 + ofstd/tests/ttuple.cc | 53 + ofstd/tests/tuuid.cc | 115 + ofstd/tests/tvec.cc | 118 + ofstd/tests/txml.cc | 82 + 2536 files changed, 1052377 insertions(+) create mode 100644 ANNOUNCE create mode 100644 CHANGES create mode 100755 CMake/3rdparty.cmake create mode 100644 CMake/CTest/CTestCustom.cmake create mode 100644 CMake/CTest/dcmtkCTestConfig.cmake.in create mode 100644 CMake/CTest/dcmtkCTestMacros.cmake create mode 100644 CMake/CTest/dcmtkCTestRunAndroid.cmake.in create mode 100644 CMake/CheckCMakeCommandExists.cmake create mode 100644 CMake/CheckFunctionWithHeaderExists.cmake create mode 100644 CMake/DCMTKConfig.cmake.in create mode 100644 CMake/DCMTKConfig.cmake26.in create mode 100644 CMake/FindCharset.cmake create mode 100644 CMake/FindICONV.cmake create mode 100644 CMake/FindSndfile.cmake create mode 100644 CMake/FindWrap.cmake create mode 100644 CMake/GenerateCMakeExports.cmake create mode 100644 CMake/GenerateDCMTKConfigure.cmake create mode 100644 CMake/android.toolchain.cmake create mode 100644 CMake/dcmtkAfterModules.cmake create mode 100644 CMake/dcmtkMacros.cmake create mode 100644 CMake/dcmtkPrepare.cmake create mode 100755 CMake/dcmtkTestCharSignedness.cc create mode 100644 CMake/dcmtkTryCompile.cmake create mode 100644 CMake/dcmtkTryRun.cmake create mode 100644 CMake/dcmtkUseAndroidSDK.cmake create mode 100644 CMake/dcmtkUseWine.cmake create mode 100644 CMake/osconfig.h.in create mode 100644 CMakeLists.txt create mode 100644 COPYRIGHT create mode 100644 CREDITS create mode 100644 FAQ create mode 100644 HISTORY create mode 100644 INSTALL create mode 100644 Makefile create mode 100644 README create mode 100644 VERSION create mode 100644 config/CMakeLists.txt create mode 100644 config/Makefile.def.in create mode 100644 config/Makefile.in create mode 100644 config/aclocal.m4 create mode 100644 config/arith.cc create mode 100755 config/autoall create mode 100755 config/changext create mode 100755 config/config.guess create mode 100755 config/config.sub create mode 100755 config/configure create mode 100644 config/configure.in create mode 100755 config/confmod create mode 100644 config/confmod.in create mode 100644 config/docs/CMakeLists.txt create mode 100644 config/docs/config.dox create mode 100644 config/docs/config.txt create mode 100644 config/docs/cxx11.dox create mode 100644 config/docs/dirstruc.txt create mode 100644 config/docs/envvars.txt create mode 100644 config/docs/macros.txt create mode 100644 config/docs/modules.txt create mode 100644 config/general.m4 create mode 100644 config/include/dcmtk/config/osconfig.h.in create mode 100755 config/install-sh create mode 100755 config/mkinstalldirs create mode 100644 config/modules create mode 100755 config/rootconf create mode 100644 config/templates/Makefile.lib create mode 100644 config/templates/Makefile.mod create mode 100644 config/templates/Makefile.src create mode 100755 config/templates/configure.mod create mode 100755 configure create mode 100644 dcmdata/CMakeLists.txt create mode 100644 dcmdata/Makefile.in create mode 100644 dcmdata/apps/CMakeLists.txt create mode 100644 dcmdata/apps/Makefile.dep create mode 100644 dcmdata/apps/Makefile.in create mode 100644 dcmdata/apps/dcm2pdf.cc create mode 100644 dcmdata/apps/dcm2xml.cc create mode 100644 dcmdata/apps/dcmconv.cc create mode 100644 dcmdata/apps/dcmcrle.cc create mode 100644 dcmdata/apps/dcmdrle.cc create mode 100644 dcmdata/apps/dcmdump.cc create mode 100644 dcmdata/apps/dcmftest.cc create mode 100644 dcmdata/apps/dcmgpdir.cc create mode 100644 dcmdata/apps/dcmodify.cc create mode 100644 dcmdata/apps/dump2dcm.cc create mode 100644 dcmdata/apps/img2dcm.cc create mode 100644 dcmdata/apps/mdfconen.cc create mode 100644 dcmdata/apps/mdfconen.h create mode 100644 dcmdata/apps/mdfdsman.cc create mode 100644 dcmdata/apps/mdfdsman.h create mode 100644 dcmdata/apps/pdf2dcm.cc create mode 100644 dcmdata/apps/xml2dcm.cc create mode 100755 dcmdata/configure create mode 100644 dcmdata/data/CMakeLists.txt create mode 100644 dcmdata/data/Makefile.in create mode 100644 dcmdata/data/SC.dump create mode 100644 dcmdata/data/VLP.dump create mode 100644 dcmdata/data/acrnema.dic create mode 100644 dcmdata/data/dcm2xml.dtd create mode 100644 dcmdata/data/dicom.dic create mode 100644 dcmdata/data/diconde.dic create mode 100644 dcmdata/data/dumppat.txt create mode 100644 dcmdata/data/private.dic create mode 100644 dcmdata/docs/CMakeLists.txt create mode 100644 dcmdata/docs/Makefile.in create mode 100644 dcmdata/docs/datadict.txt create mode 100644 dcmdata/docs/dcm2pdf.man create mode 100644 dcmdata/docs/dcm2xml.man create mode 100644 dcmdata/docs/dcmconv.man create mode 100644 dcmdata/docs/dcmcrle.man create mode 100644 dcmdata/docs/dcmdata.dox create mode 100644 dcmdata/docs/dcmdrle.man create mode 100644 dcmdata/docs/dcmdump.man create mode 100644 dcmdata/docs/dcmftest.man create mode 100644 dcmdata/docs/dcmgpdir.man create mode 100644 dcmdata/docs/dcmodify.man create mode 100644 dcmdata/docs/dump2dcm.man create mode 100644 dcmdata/docs/img2dcm.man create mode 100644 dcmdata/docs/pdf2dcm.man create mode 100644 dcmdata/docs/xml2dcm.man create mode 100644 dcmdata/etc/Makefile.in create mode 100644 dcmdata/include/CMakeLists.txt create mode 100644 dcmdata/include/Makefile.in create mode 100644 dcmdata/include/dcmtk/dcmdata/cmdlnarg.h create mode 100644 dcmdata/include/dcmtk/dcmdata/dcbytstr.h create mode 100644 dcmdata/include/dcmtk/dcmdata/dcchrstr.h create mode 100644 dcmdata/include/dcmtk/dcmdata/dccodec.h create mode 100644 dcmdata/include/dcmtk/dcmdata/dcdatset.h create mode 100644 dcmdata/include/dcmtk/dcmdata/dcdatutl.h create mode 100644 dcmdata/include/dcmtk/dcmdata/dcddirif.h create mode 100644 dcmdata/include/dcmtk/dcmdata/dcdefine.h create mode 100644 dcmdata/include/dcmtk/dcmdata/dcdeftag.h create mode 100644 dcmdata/include/dcmtk/dcmdata/dcdicdir.h create mode 100644 dcmdata/include/dcmtk/dcmdata/dcdicent.h create mode 100644 dcmdata/include/dcmtk/dcmdata/dcdict.h create mode 100644 dcmdata/include/dcmtk/dcmdata/dcdirrec.h create mode 100644 dcmdata/include/dcmtk/dcmdata/dcelem.h create mode 100644 dcmdata/include/dcmtk/dcmdata/dcerror.h create mode 100644 dcmdata/include/dcmtk/dcmdata/dcfcache.h create mode 100644 dcmdata/include/dcmtk/dcmdata/dcfilefo.h create mode 100644 dcmdata/include/dcmtk/dcmdata/dcfilter.h create mode 100644 dcmdata/include/dcmtk/dcmdata/dchashdi.h create mode 100644 dcmdata/include/dcmtk/dcmdata/dcistrma.h create mode 100644 dcmdata/include/dcmtk/dcmdata/dcistrmb.h create mode 100644 dcmdata/include/dcmtk/dcmdata/dcistrmf.h create mode 100644 dcmdata/include/dcmtk/dcmdata/dcistrmz.h create mode 100644 dcmdata/include/dcmtk/dcmdata/dcitem.h create mode 100644 dcmdata/include/dcmtk/dcmdata/dclist.h create mode 100644 dcmdata/include/dcmtk/dcmdata/dcmetinf.h create mode 100644 dcmdata/include/dcmtk/dcmdata/dcobject.h create mode 100644 dcmdata/include/dcmtk/dcmdata/dcofsetl.h create mode 100644 dcmdata/include/dcmtk/dcmdata/dcostrma.h create mode 100644 dcmdata/include/dcmtk/dcmdata/dcostrmb.h create mode 100644 dcmdata/include/dcmtk/dcmdata/dcostrmf.h create mode 100644 dcmdata/include/dcmtk/dcmdata/dcostrmz.h create mode 100644 dcmdata/include/dcmtk/dcmdata/dcovlay.h create mode 100644 dcmdata/include/dcmtk/dcmdata/dcpath.h create mode 100644 dcmdata/include/dcmtk/dcmdata/dcpcache.h create mode 100644 dcmdata/include/dcmtk/dcmdata/dcpixel.h create mode 100644 dcmdata/include/dcmtk/dcmdata/dcpixseq.h create mode 100644 dcmdata/include/dcmtk/dcmdata/dcpxitem.h create mode 100644 dcmdata/include/dcmtk/dcmdata/dcrleccd.h create mode 100644 dcmdata/include/dcmtk/dcmdata/dcrlecce.h create mode 100644 dcmdata/include/dcmtk/dcmdata/dcrlecp.h create mode 100644 dcmdata/include/dcmtk/dcmdata/dcrledec.h create mode 100644 dcmdata/include/dcmtk/dcmdata/dcrledrg.h create mode 100644 dcmdata/include/dcmtk/dcmdata/dcrleenc.h create mode 100644 dcmdata/include/dcmtk/dcmdata/dcrleerg.h create mode 100644 dcmdata/include/dcmtk/dcmdata/dcrlerp.h create mode 100644 dcmdata/include/dcmtk/dcmdata/dcsequen.h create mode 100644 dcmdata/include/dcmtk/dcmdata/dcspchrs.h create mode 100644 dcmdata/include/dcmtk/dcmdata/dcstack.h create mode 100644 dcmdata/include/dcmtk/dcmdata/dcswap.h create mode 100644 dcmdata/include/dcmtk/dcmdata/dctag.h create mode 100644 dcmdata/include/dcmtk/dcmdata/dctagkey.h create mode 100644 dcmdata/include/dcmtk/dcmdata/dctk.h create mode 100644 dcmdata/include/dcmtk/dcmdata/dctypes.h create mode 100644 dcmdata/include/dcmtk/dcmdata/dcuid.h create mode 100644 dcmdata/include/dcmtk/dcmdata/dcvr.h create mode 100644 dcmdata/include/dcmtk/dcmdata/dcvrae.h create mode 100644 dcmdata/include/dcmtk/dcmdata/dcvras.h create mode 100644 dcmdata/include/dcmtk/dcmdata/dcvrat.h create mode 100644 dcmdata/include/dcmtk/dcmdata/dcvrcs.h create mode 100644 dcmdata/include/dcmtk/dcmdata/dcvrda.h create mode 100644 dcmdata/include/dcmtk/dcmdata/dcvrds.h create mode 100644 dcmdata/include/dcmtk/dcmdata/dcvrdt.h create mode 100644 dcmdata/include/dcmtk/dcmdata/dcvrfd.h create mode 100644 dcmdata/include/dcmtk/dcmdata/dcvrfl.h create mode 100644 dcmdata/include/dcmtk/dcmdata/dcvris.h create mode 100644 dcmdata/include/dcmtk/dcmdata/dcvrlo.h create mode 100644 dcmdata/include/dcmtk/dcmdata/dcvrlt.h create mode 100644 dcmdata/include/dcmtk/dcmdata/dcvrobow.h create mode 100644 dcmdata/include/dcmtk/dcmdata/dcvrod.h create mode 100644 dcmdata/include/dcmtk/dcmdata/dcvrof.h create mode 100644 dcmdata/include/dcmtk/dcmdata/dcvrpn.h create mode 100644 dcmdata/include/dcmtk/dcmdata/dcvrpobw.h create mode 100644 dcmdata/include/dcmtk/dcmdata/dcvrsh.h create mode 100644 dcmdata/include/dcmtk/dcmdata/dcvrsl.h create mode 100644 dcmdata/include/dcmtk/dcmdata/dcvrss.h create mode 100644 dcmdata/include/dcmtk/dcmdata/dcvrst.h create mode 100644 dcmdata/include/dcmtk/dcmdata/dcvrtm.h create mode 100644 dcmdata/include/dcmtk/dcmdata/dcvruc.h create mode 100644 dcmdata/include/dcmtk/dcmdata/dcvrui.h create mode 100644 dcmdata/include/dcmtk/dcmdata/dcvrul.h create mode 100644 dcmdata/include/dcmtk/dcmdata/dcvrulup.h create mode 100644 dcmdata/include/dcmtk/dcmdata/dcvrur.h create mode 100644 dcmdata/include/dcmtk/dcmdata/dcvrus.h create mode 100644 dcmdata/include/dcmtk/dcmdata/dcvrut.h create mode 100644 dcmdata/include/dcmtk/dcmdata/dcwcache.h create mode 100644 dcmdata/include/dcmtk/dcmdata/dcxfer.h create mode 100644 dcmdata/include/dcmtk/dcmdata/libi2d/i2d.h create mode 100644 dcmdata/include/dcmtk/dcmdata/libi2d/i2dbmps.h create mode 100644 dcmdata/include/dcmtk/dcmdata/libi2d/i2define.h create mode 100644 dcmdata/include/dcmtk/dcmdata/libi2d/i2dimgs.h create mode 100644 dcmdata/include/dcmtk/dcmdata/libi2d/i2djpgs.h create mode 100644 dcmdata/include/dcmtk/dcmdata/libi2d/i2doutpl.h create mode 100644 dcmdata/include/dcmtk/dcmdata/libi2d/i2dplnsc.h create mode 100644 dcmdata/include/dcmtk/dcmdata/libi2d/i2dplsc.h create mode 100644 dcmdata/include/dcmtk/dcmdata/libi2d/i2dplvlp.h create mode 100644 dcmdata/include/dcmtk/dcmdata/vrscan.h create mode 100644 dcmdata/libi2d/CMakeLists.txt create mode 100644 dcmdata/libi2d/Makefile.dep create mode 100644 dcmdata/libi2d/Makefile.in create mode 100644 dcmdata/libi2d/i2d.cc create mode 100644 dcmdata/libi2d/i2dbmps.cc create mode 100644 dcmdata/libi2d/i2djpgs.cc create mode 100644 dcmdata/libi2d/i2dplnsc.cc create mode 100644 dcmdata/libi2d/i2dplsc.cc create mode 100644 dcmdata/libi2d/i2dplvlp.cc create mode 100644 dcmdata/libsrc/CMakeLists.txt create mode 100644 dcmdata/libsrc/Makefile.dep create mode 100644 dcmdata/libsrc/Makefile.in create mode 100644 dcmdata/libsrc/cmdlnarg.cc create mode 100644 dcmdata/libsrc/dcbytstr.cc create mode 100644 dcmdata/libsrc/dcchrstr.cc create mode 100644 dcmdata/libsrc/dccodec.cc create mode 100644 dcmdata/libsrc/dcdatset.cc create mode 100644 dcmdata/libsrc/dcdatutl.cc create mode 100644 dcmdata/libsrc/dcddirif.cc create mode 100644 dcmdata/libsrc/dcdicdir.cc create mode 100644 dcmdata/libsrc/dcdicent.cc create mode 100644 dcmdata/libsrc/dcdict.cc create mode 100644 dcmdata/libsrc/dcdictbi.cc create mode 100644 dcmdata/libsrc/dcdirrec.cc create mode 100644 dcmdata/libsrc/dcelem.cc create mode 100644 dcmdata/libsrc/dcerror.cc create mode 100644 dcmdata/libsrc/dcfilefo.cc create mode 100644 dcmdata/libsrc/dcfilter.cc create mode 100644 dcmdata/libsrc/dchashdi.cc create mode 100644 dcmdata/libsrc/dcistrma.cc create mode 100644 dcmdata/libsrc/dcistrmb.cc create mode 100644 dcmdata/libsrc/dcistrmf.cc create mode 100644 dcmdata/libsrc/dcistrmz.cc create mode 100644 dcmdata/libsrc/dcitem.cc create mode 100644 dcmdata/libsrc/dclist.cc create mode 100644 dcmdata/libsrc/dcmetinf.cc create mode 100644 dcmdata/libsrc/dcobject.cc create mode 100644 dcmdata/libsrc/dcostrma.cc create mode 100644 dcmdata/libsrc/dcostrmb.cc create mode 100644 dcmdata/libsrc/dcostrmf.cc create mode 100644 dcmdata/libsrc/dcostrmz.cc create mode 100644 dcmdata/libsrc/dcpath.cc create mode 100644 dcmdata/libsrc/dcpcache.cc create mode 100644 dcmdata/libsrc/dcpixel.cc create mode 100644 dcmdata/libsrc/dcpixseq.cc create mode 100644 dcmdata/libsrc/dcpxitem.cc create mode 100644 dcmdata/libsrc/dcrleccd.cc create mode 100644 dcmdata/libsrc/dcrlecce.cc create mode 100644 dcmdata/libsrc/dcrlecp.cc create mode 100644 dcmdata/libsrc/dcrledrg.cc create mode 100644 dcmdata/libsrc/dcrleerg.cc create mode 100644 dcmdata/libsrc/dcrlerp.cc create mode 100644 dcmdata/libsrc/dcsequen.cc create mode 100644 dcmdata/libsrc/dcspchrs.cc create mode 100644 dcmdata/libsrc/dcstack.cc create mode 100644 dcmdata/libsrc/dcswap.cc create mode 100644 dcmdata/libsrc/dctag.cc create mode 100644 dcmdata/libsrc/dctagkey.cc create mode 100644 dcmdata/libsrc/dctypes.cc create mode 100644 dcmdata/libsrc/dcuid.cc create mode 100644 dcmdata/libsrc/dcvr.cc create mode 100644 dcmdata/libsrc/dcvrae.cc create mode 100644 dcmdata/libsrc/dcvras.cc create mode 100644 dcmdata/libsrc/dcvrat.cc create mode 100644 dcmdata/libsrc/dcvrcs.cc create mode 100644 dcmdata/libsrc/dcvrda.cc create mode 100644 dcmdata/libsrc/dcvrds.cc create mode 100644 dcmdata/libsrc/dcvrdt.cc create mode 100644 dcmdata/libsrc/dcvrfd.cc create mode 100644 dcmdata/libsrc/dcvrfl.cc create mode 100644 dcmdata/libsrc/dcvris.cc create mode 100644 dcmdata/libsrc/dcvrlo.cc create mode 100644 dcmdata/libsrc/dcvrlt.cc create mode 100644 dcmdata/libsrc/dcvrobow.cc create mode 100644 dcmdata/libsrc/dcvrod.cc create mode 100644 dcmdata/libsrc/dcvrof.cc create mode 100644 dcmdata/libsrc/dcvrpn.cc create mode 100644 dcmdata/libsrc/dcvrpobw.cc create mode 100644 dcmdata/libsrc/dcvrsh.cc create mode 100644 dcmdata/libsrc/dcvrsl.cc create mode 100644 dcmdata/libsrc/dcvrss.cc create mode 100644 dcmdata/libsrc/dcvrst.cc create mode 100644 dcmdata/libsrc/dcvrtm.cc create mode 100644 dcmdata/libsrc/dcvruc.cc create mode 100644 dcmdata/libsrc/dcvrui.cc create mode 100644 dcmdata/libsrc/dcvrul.cc create mode 100644 dcmdata/libsrc/dcvrulup.cc create mode 100644 dcmdata/libsrc/dcvrur.cc create mode 100644 dcmdata/libsrc/dcvrus.cc create mode 100644 dcmdata/libsrc/dcvrut.cc create mode 100644 dcmdata/libsrc/dcwcache.cc create mode 100644 dcmdata/libsrc/dcxfer.cc create mode 100644 dcmdata/libsrc/mkdeftag.cc create mode 100644 dcmdata/libsrc/mkdictbi.cc create mode 100644 dcmdata/libsrc/vrscan.cc create mode 100644 dcmdata/libsrc/vrscani.h create mode 100644 dcmdata/libsrc/vrscanl.c create mode 100644 dcmdata/libsrc/vrscanl.h create mode 100644 dcmdata/libsrc/vrscanl.l create mode 100644 dcmdata/tests/CMakeLists.txt create mode 100644 dcmdata/tests/Makefile.dep create mode 100644 dcmdata/tests/Makefile.in create mode 100644 dcmdata/tests/dcmpsdmp.tcl create mode 100644 dcmdata/tests/dctmacro.h create mode 100644 dcmdata/tests/tchval.cc create mode 100644 dcmdata/tests/tdict.cc create mode 100644 dcmdata/tests/telemlen.cc create mode 100644 dcmdata/tests/tests.cc create mode 100644 dcmdata/tests/tfilter.cc create mode 100644 dcmdata/tests/ti2dbmp.cc create mode 100644 dcmdata/tests/tparent.cc create mode 100644 dcmdata/tests/tparser.cc create mode 100644 dcmdata/tests/tpath.cc create mode 100644 dcmdata/tests/tpread.cc create mode 100644 dcmdata/tests/tspchrs.cc create mode 100644 dcmdata/tests/tstrval.cc create mode 100644 dcmdata/tests/tvrcomp.cc create mode 100644 dcmdata/tests/tvrdatim.cc create mode 100644 dcmdata/tests/tvrds.cc create mode 100644 dcmdata/tests/tvrfd.cc create mode 100644 dcmdata/tests/tvrpn.cc create mode 100644 dcmdata/tests/tvrui.cc create mode 100644 dcmfg/CMakeLists.txt create mode 100644 dcmfg/Makefile.in create mode 100755 dcmfg/configure create mode 100644 dcmfg/data/Makefile.in create mode 100644 dcmfg/docs/Makefile.in create mode 100644 dcmfg/docs/dcmfg.dox create mode 100644 dcmfg/etc/Makefile.in create mode 100644 dcmfg/include/CMakeLists.txt create mode 100644 dcmfg/include/Makefile.in create mode 100644 dcmfg/include/dcmtk/dcmfg/fg.h create mode 100644 dcmfg/include/dcmtk/dcmfg/fgbase.h create mode 100644 dcmfg/include/dcmtk/dcmfg/fgdefine.h create mode 100644 dcmfg/include/dcmtk/dcmfg/fgderimg.h create mode 100644 dcmfg/include/dcmtk/dcmfg/fgfact.h create mode 100644 dcmfg/include/dcmtk/dcmfg/fgfracon.h create mode 100644 dcmfg/include/dcmtk/dcmfg/fgframevoilut.h create mode 100644 dcmfg/include/dcmtk/dcmfg/fgimagedatatype.h create mode 100644 dcmfg/include/dcmtk/dcmfg/fginterface.h create mode 100644 dcmfg/include/dcmtk/dcmfg/fgpixmsr.h create mode 100644 dcmfg/include/dcmtk/dcmfg/fgplanor.h create mode 100644 dcmfg/include/dcmtk/dcmfg/fgplanorvol.h create mode 100644 dcmfg/include/dcmtk/dcmfg/fgplanpo.h create mode 100644 dcmfg/include/dcmtk/dcmfg/fgplanposvol.h create mode 100644 dcmfg/include/dcmtk/dcmfg/fgrealworldvaluemapping.h create mode 100644 dcmfg/include/dcmtk/dcmfg/fgseg.h create mode 100644 dcmfg/include/dcmtk/dcmfg/fgtypes.h create mode 100644 dcmfg/include/dcmtk/dcmfg/fgusimagedescription.h create mode 100644 dcmfg/include/dcmtk/dcmfg/stack.h create mode 100644 dcmfg/include/dcmtk/dcmfg/stackinterface.h create mode 100644 dcmfg/libsrc/CMakeLists.txt create mode 100644 dcmfg/libsrc/Makefile.dep create mode 100644 dcmfg/libsrc/Makefile.in create mode 100644 dcmfg/libsrc/fg.cc create mode 100644 dcmfg/libsrc/fgbase.cc create mode 100644 dcmfg/libsrc/fgderimg.cc create mode 100644 dcmfg/libsrc/fgfact.cc create mode 100644 dcmfg/libsrc/fgfracon.cc create mode 100644 dcmfg/libsrc/fgframevoilut.cc create mode 100644 dcmfg/libsrc/fgimagedatatype.cc create mode 100644 dcmfg/libsrc/fginterface.cc create mode 100644 dcmfg/libsrc/fgpixmsr.cc create mode 100644 dcmfg/libsrc/fgplanor.cc create mode 100644 dcmfg/libsrc/fgplanorvol.cc create mode 100644 dcmfg/libsrc/fgplanpo.cc create mode 100644 dcmfg/libsrc/fgplanposvol.cc create mode 100644 dcmfg/libsrc/fgrealworldvaluemapping.cc create mode 100644 dcmfg/libsrc/fgseg.cc create mode 100644 dcmfg/libsrc/fgtypes.cc create mode 100644 dcmfg/libsrc/fgusimagedescription.cc create mode 100644 dcmfg/libsrc/stack.cc create mode 100644 dcmfg/libsrc/stackinterface.cc create mode 100644 dcmfg/tests/Makefile.in create mode 100644 dcmimage/CMakeLists.txt create mode 100644 dcmimage/Makefile.in create mode 100644 dcmimage/apps/CMakeLists.txt create mode 100644 dcmimage/apps/Makefile.dep create mode 100644 dcmimage/apps/Makefile.in create mode 100644 dcmimage/apps/dcm2pnm.cc create mode 100644 dcmimage/apps/dcmquant.cc create mode 100644 dcmimage/apps/dcmscale.cc create mode 100755 dcmimage/configure create mode 100644 dcmimage/data/Makefile.in create mode 100644 dcmimage/docs/Makefile.in create mode 100644 dcmimage/docs/dcm2pnm.man create mode 100644 dcmimage/docs/dcmimage.dox create mode 100644 dcmimage/docs/dcmquant.man create mode 100644 dcmimage/docs/dcmscale.man create mode 100644 dcmimage/etc/Makefile.in create mode 100644 dcmimage/include/CMakeLists.txt create mode 100644 dcmimage/include/Makefile.in create mode 100644 dcmimage/include/dcmtk/dcmimage/diargimg.h create mode 100644 dcmimage/include/dcmtk/dcmimage/diargpxt.h create mode 100644 dcmimage/include/dcmtk/dcmimage/dicdefin.h create mode 100644 dcmimage/include/dcmtk/dcmimage/dicmyimg.h create mode 100644 dcmimage/include/dcmtk/dcmimage/dicmypxt.h create mode 100644 dcmimage/include/dcmtk/dcmimage/dicocpt.h create mode 100644 dcmimage/include/dcmtk/dcmimage/dicoflt.h create mode 100644 dcmimage/include/dcmtk/dcmimage/dicoimg.h create mode 100644 dcmimage/include/dcmtk/dcmimage/dicomot.h create mode 100644 dcmimage/include/dcmtk/dcmimage/dicoopx.h create mode 100644 dcmimage/include/dcmtk/dcmimage/dicoopxt.h create mode 100644 dcmimage/include/dcmtk/dcmimage/dicopx.h create mode 100644 dcmimage/include/dcmtk/dcmimage/dicopxt.h create mode 100644 dcmimage/include/dcmtk/dcmimage/dicorot.h create mode 100644 dcmimage/include/dcmtk/dcmimage/dicosct.h create mode 100644 dcmimage/include/dcmtk/dcmimage/dihsvimg.h create mode 100644 dcmimage/include/dcmtk/dcmimage/dihsvpxt.h create mode 100644 dcmimage/include/dcmtk/dcmimage/dilogger.h create mode 100644 dcmimage/include/dcmtk/dcmimage/dipalimg.h create mode 100644 dcmimage/include/dcmtk/dcmimage/dipalpxt.h create mode 100644 dcmimage/include/dcmtk/dcmimage/dipipng.h create mode 100644 dcmimage/include/dcmtk/dcmimage/dipitiff.h create mode 100644 dcmimage/include/dcmtk/dcmimage/diqtcmap.h create mode 100644 dcmimage/include/dcmtk/dcmimage/diqtctab.h create mode 100644 dcmimage/include/dcmtk/dcmimage/diqtfs.h create mode 100644 dcmimage/include/dcmtk/dcmimage/diqthash.h create mode 100644 dcmimage/include/dcmtk/dcmimage/diqthitl.h create mode 100644 dcmimage/include/dcmtk/dcmimage/diqthitm.h create mode 100644 dcmimage/include/dcmtk/dcmimage/diqtid.h create mode 100644 dcmimage/include/dcmtk/dcmimage/diqtpbox.h create mode 100644 dcmimage/include/dcmtk/dcmimage/diqtpix.h create mode 100644 dcmimage/include/dcmtk/dcmimage/diqtstab.h create mode 100644 dcmimage/include/dcmtk/dcmimage/diqttype.h create mode 100644 dcmimage/include/dcmtk/dcmimage/diquant.h create mode 100644 dcmimage/include/dcmtk/dcmimage/diregist.h create mode 100644 dcmimage/include/dcmtk/dcmimage/dirgbimg.h create mode 100644 dcmimage/include/dcmtk/dcmimage/dirgbpxt.h create mode 100644 dcmimage/include/dcmtk/dcmimage/diybrimg.h create mode 100644 dcmimage/include/dcmtk/dcmimage/diybrpxt.h create mode 100644 dcmimage/include/dcmtk/dcmimage/diyf2img.h create mode 100644 dcmimage/include/dcmtk/dcmimage/diyf2pxt.h create mode 100644 dcmimage/include/dcmtk/dcmimage/diyp2img.h create mode 100644 dcmimage/include/dcmtk/dcmimage/diyp2pxt.h create mode 100644 dcmimage/libsrc/CMakeLists.txt create mode 100644 dcmimage/libsrc/Makefile.dep create mode 100644 dcmimage/libsrc/Makefile.in create mode 100644 dcmimage/libsrc/diargimg.cc create mode 100644 dcmimage/libsrc/dicmyimg.cc create mode 100644 dcmimage/libsrc/dicoimg.cc create mode 100644 dcmimage/libsrc/dicoopx.cc create mode 100644 dcmimage/libsrc/dicopx.cc create mode 100644 dcmimage/libsrc/dihsvimg.cc create mode 100644 dcmimage/libsrc/dilogger.cc create mode 100644 dcmimage/libsrc/dipalimg.cc create mode 100644 dcmimage/libsrc/dipipng.cc create mode 100644 dcmimage/libsrc/dipitiff.cc create mode 100644 dcmimage/libsrc/diqtctab.cc create mode 100644 dcmimage/libsrc/diqtfs.cc create mode 100644 dcmimage/libsrc/diqthash.cc create mode 100644 dcmimage/libsrc/diqthitl.cc create mode 100644 dcmimage/libsrc/diqtpbox.cc create mode 100644 dcmimage/libsrc/diquant.cc create mode 100644 dcmimage/libsrc/diregist.cc create mode 100644 dcmimage/libsrc/dirgbimg.cc create mode 100644 dcmimage/libsrc/diybrimg.cc create mode 100644 dcmimage/libsrc/diyf2img.cc create mode 100644 dcmimage/libsrc/diyp2img.cc create mode 100644 dcmimage/tests/Makefile.in create mode 100644 dcmimgle/CMakeLists.txt create mode 100644 dcmimgle/Makefile.in create mode 100644 dcmimgle/apps/CMakeLists.txt create mode 100644 dcmimgle/apps/Makefile.dep create mode 100644 dcmimgle/apps/Makefile.in create mode 100644 dcmimgle/apps/dcmdspfn.cc create mode 100644 dcmimgle/apps/dcod2lum.cc create mode 100644 dcmimgle/apps/dconvlum.cc create mode 100755 dcmimgle/configure create mode 100644 dcmimgle/data/CMakeLists.txt create mode 100644 dcmimgle/data/Makefile.in create mode 100644 dcmimgle/data/camera.lut create mode 100644 dcmimgle/data/monitor.lut create mode 100644 dcmimgle/data/printer.lut create mode 100644 dcmimgle/data/scanner.lut create mode 100644 dcmimgle/docs/Makefile.in create mode 100644 dcmimgle/docs/dcmdspfn.man create mode 100644 dcmimgle/docs/dcmimgle.dox create mode 100644 dcmimgle/docs/dcod2lum.man create mode 100644 dcmimgle/docs/dconvlum.man create mode 100644 dcmimgle/etc/Makefile.in create mode 100644 dcmimgle/include/CMakeLists.txt create mode 100644 dcmimgle/include/Makefile.in create mode 100644 dcmimgle/include/dcmtk/dcmimgle/dcmimage.h create mode 100644 dcmimgle/include/dcmtk/dcmimgle/dibaslut.h create mode 100644 dcmimgle/include/dcmtk/dcmimgle/diciefn.h create mode 100644 dcmimgle/include/dcmtk/dcmimgle/dicielut.h create mode 100644 dcmimgle/include/dcmtk/dcmimgle/dicrvfit.h create mode 100644 dcmimgle/include/dcmtk/dcmimgle/didefine.h create mode 100644 dcmimgle/include/dcmtk/dcmimgle/didislut.h create mode 100644 dcmimgle/include/dcmtk/dcmimgle/didispfn.h create mode 100644 dcmimgle/include/dcmtk/dcmimgle/didocu.h create mode 100644 dcmimgle/include/dcmtk/dcmimgle/diflipt.h create mode 100644 dcmimgle/include/dcmtk/dcmimgle/digsdfn.h create mode 100644 dcmimgle/include/dcmtk/dcmimgle/digsdlut.h create mode 100644 dcmimgle/include/dcmtk/dcmimgle/diimage.h create mode 100644 dcmimgle/include/dcmtk/dcmimgle/diinpx.h create mode 100644 dcmimgle/include/dcmtk/dcmimgle/diinpxt.h create mode 100644 dcmimgle/include/dcmtk/dcmimgle/diluptab.h create mode 100644 dcmimgle/include/dcmtk/dcmimgle/dimo1img.h create mode 100644 dcmimgle/include/dcmtk/dcmimgle/dimo2img.h create mode 100644 dcmimgle/include/dcmtk/dcmimgle/dimocpt.h create mode 100644 dcmimgle/include/dcmtk/dcmimgle/dimoflt.h create mode 100644 dcmimgle/include/dcmtk/dcmimgle/dimoimg.h create mode 100644 dcmimgle/include/dcmtk/dcmimgle/dimoipxt.h create mode 100644 dcmimgle/include/dcmtk/dcmimgle/dimomod.h create mode 100644 dcmimgle/include/dcmtk/dcmimgle/dimoopx.h create mode 100644 dcmimgle/include/dcmtk/dcmimgle/dimoopxt.h create mode 100644 dcmimgle/include/dcmtk/dcmimgle/dimopx.h create mode 100644 dcmimgle/include/dcmtk/dcmimgle/dimopxt.h create mode 100644 dcmimgle/include/dcmtk/dcmimgle/dimorot.h create mode 100644 dcmimgle/include/dcmtk/dcmimgle/dimosct.h create mode 100644 dcmimgle/include/dcmtk/dcmimgle/diobjcou.h create mode 100644 dcmimgle/include/dcmtk/dcmimgle/diovdat.h create mode 100644 dcmimgle/include/dcmtk/dcmimgle/diovlay.h create mode 100644 dcmimgle/include/dcmtk/dcmimgle/diovlimg.h create mode 100644 dcmimgle/include/dcmtk/dcmimgle/diovpln.h create mode 100644 dcmimgle/include/dcmtk/dcmimgle/dipixel.h create mode 100644 dcmimgle/include/dcmtk/dcmimgle/diplugin.h create mode 100644 dcmimgle/include/dcmtk/dcmimgle/dipxrept.h create mode 100644 dcmimgle/include/dcmtk/dcmimgle/diregbas.h create mode 100644 dcmimgle/include/dcmtk/dcmimgle/dirotat.h create mode 100644 dcmimgle/include/dcmtk/dcmimgle/discalet.h create mode 100644 dcmimgle/include/dcmtk/dcmimgle/displint.h create mode 100644 dcmimgle/include/dcmtk/dcmimgle/ditranst.h create mode 100644 dcmimgle/include/dcmtk/dcmimgle/diutils.h create mode 100644 dcmimgle/libsrc/CMakeLists.txt create mode 100644 dcmimgle/libsrc/Makefile.dep create mode 100644 dcmimgle/libsrc/Makefile.in create mode 100644 dcmimgle/libsrc/dcmimage.cc create mode 100644 dcmimgle/libsrc/dibaslut.cc create mode 100644 dcmimgle/libsrc/diciefn.cc create mode 100644 dcmimgle/libsrc/dicielut.cc create mode 100644 dcmimgle/libsrc/didislut.cc create mode 100644 dcmimgle/libsrc/didispfn.cc create mode 100644 dcmimgle/libsrc/didocu.cc create mode 100644 dcmimgle/libsrc/digsdfn.cc create mode 100644 dcmimgle/libsrc/digsdlut.cc create mode 100644 dcmimgle/libsrc/diimage.cc create mode 100644 dcmimgle/libsrc/diinpx.cc create mode 100644 dcmimgle/libsrc/diluptab.cc create mode 100644 dcmimgle/libsrc/dimo1img.cc create mode 100644 dcmimgle/libsrc/dimo2img.cc create mode 100644 dcmimgle/libsrc/dimoimg.cc create mode 100644 dcmimgle/libsrc/dimoimg3.cc create mode 100644 dcmimgle/libsrc/dimoimg4.cc create mode 100644 dcmimgle/libsrc/dimoimg5.cc create mode 100644 dcmimgle/libsrc/dimomod.cc create mode 100644 dcmimgle/libsrc/dimoopx.cc create mode 100644 dcmimgle/libsrc/dimopx.cc create mode 100644 dcmimgle/libsrc/diovdat.cc create mode 100644 dcmimgle/libsrc/diovlay.cc create mode 100644 dcmimgle/libsrc/diovlimg.cc create mode 100644 dcmimgle/libsrc/diovpln.cc create mode 100644 dcmimgle/libsrc/diutils.cc create mode 100644 dcmimgle/tests/Makefile.in create mode 100644 dcmiod/CMakeLists.txt create mode 100644 dcmiod/Makefile.in create mode 100755 dcmiod/configure create mode 100644 dcmiod/data/Makefile.in create mode 100644 dcmiod/docs/Makefile.in create mode 100644 dcmiod/docs/dcmiod.dox create mode 100644 dcmiod/etc/Makefile.in create mode 100644 dcmiod/include/CMakeLists.txt create mode 100644 dcmiod/include/Makefile.in create mode 100644 dcmiod/include/dcmtk/dcmiod/iodcommn.h create mode 100644 dcmiod/include/dcmtk/dcmiod/ioddef.h create mode 100644 dcmiod/include/dcmtk/dcmiod/iodimage.h create mode 100644 dcmiod/include/dcmtk/dcmiod/iodmacro.h create mode 100644 dcmiod/include/dcmtk/dcmiod/iodrules.h create mode 100644 dcmiod/include/dcmtk/dcmiod/iodtypes.h create mode 100644 dcmiod/include/dcmtk/dcmiod/iodutil.h create mode 100644 dcmiod/include/dcmtk/dcmiod/modacquisitioncontext.h create mode 100644 dcmiod/include/dcmtk/dcmiod/modbase.h create mode 100644 dcmiod/include/dcmtk/dcmiod/modcommoninstanceref.h create mode 100644 dcmiod/include/dcmtk/dcmiod/modenhequipment.h create mode 100644 dcmiod/include/dcmtk/dcmiod/modenhusimage.h create mode 100644 dcmiod/include/dcmtk/dcmiod/modenhusseries.h create mode 100644 dcmiod/include/dcmtk/dcmiod/modequipment.h create mode 100644 dcmiod/include/dcmtk/dcmiod/modfor.h create mode 100644 dcmiod/include/dcmtk/dcmiod/modgeneralimage.h create mode 100644 dcmiod/include/dcmtk/dcmiod/modgeneralseries.h create mode 100644 dcmiod/include/dcmtk/dcmiod/modgeneralstudy.h create mode 100644 dcmiod/include/dcmtk/dcmiod/modhelp.h create mode 100644 dcmiod/include/dcmtk/dcmiod/modimagepixel.h create mode 100644 dcmiod/include/dcmtk/dcmiod/modmultiframedimension.h create mode 100644 dcmiod/include/dcmtk/dcmiod/modmultiframefg.h create mode 100644 dcmiod/include/dcmtk/dcmiod/modpatient.h create mode 100644 dcmiod/include/dcmtk/dcmiod/modpatientstudy.h create mode 100644 dcmiod/include/dcmtk/dcmiod/modsegmentationseries.h create mode 100644 dcmiod/include/dcmtk/dcmiod/modsopcommon.h create mode 100644 dcmiod/include/dcmtk/dcmiod/modsynchronisation.h create mode 100644 dcmiod/include/dcmtk/dcmiod/modusfor.h create mode 100644 dcmiod/libsrc/CMakeLists.txt create mode 100644 dcmiod/libsrc/Makefile.dep create mode 100644 dcmiod/libsrc/Makefile.in create mode 100644 dcmiod/libsrc/iodcommn.cc create mode 100644 dcmiod/libsrc/iodimage.cc create mode 100644 dcmiod/libsrc/iodmacro.cc create mode 100644 dcmiod/libsrc/iodrules.cc create mode 100644 dcmiod/libsrc/iodtypes.cc create mode 100644 dcmiod/libsrc/iodutil.cc create mode 100644 dcmiod/libsrc/modacquisitioncontext.cc create mode 100644 dcmiod/libsrc/modbase.cc create mode 100644 dcmiod/libsrc/modcommoninstanceref.cc create mode 100644 dcmiod/libsrc/modenhequipment.cc create mode 100644 dcmiod/libsrc/modenhusimage.cc create mode 100644 dcmiod/libsrc/modenhusseries.cc create mode 100644 dcmiod/libsrc/modequipment.cc create mode 100644 dcmiod/libsrc/modfor.cc create mode 100644 dcmiod/libsrc/modgeneralimage.cc create mode 100644 dcmiod/libsrc/modgeneralseries.cc create mode 100644 dcmiod/libsrc/modgeneralstudy.cc create mode 100644 dcmiod/libsrc/modhelp.cc create mode 100644 dcmiod/libsrc/modimagepixel.cc create mode 100644 dcmiod/libsrc/modmultiframedimension.cc create mode 100644 dcmiod/libsrc/modmultiframefg.cc create mode 100644 dcmiod/libsrc/modpatient.cc create mode 100644 dcmiod/libsrc/modpatientstudy.cc create mode 100644 dcmiod/libsrc/modsegmentationseries.cc create mode 100644 dcmiod/libsrc/modsopcommon.cc create mode 100644 dcmiod/libsrc/modsynchronization.cc create mode 100644 dcmiod/libsrc/modusfor.cc create mode 100644 dcmiod/tests/Makefile.in create mode 100644 dcmjpeg/CMakeLists.txt create mode 100644 dcmjpeg/Makefile.in create mode 100644 dcmjpeg/apps/CMakeLists.txt create mode 100644 dcmjpeg/apps/Makefile.dep create mode 100644 dcmjpeg/apps/Makefile.in create mode 100644 dcmjpeg/apps/dcmcjpeg.cc create mode 100644 dcmjpeg/apps/dcmdjpeg.cc create mode 100644 dcmjpeg/apps/dcmj2pnm.cc create mode 100644 dcmjpeg/apps/dcmmkdir.cc create mode 100755 dcmjpeg/configure create mode 100644 dcmjpeg/data/Makefile.in create mode 100644 dcmjpeg/docs/Makefile.in create mode 100644 dcmjpeg/docs/dcmcjpeg.man create mode 100644 dcmjpeg/docs/dcmdjpeg.man create mode 100644 dcmjpeg/docs/dcmj2pnm.man create mode 100644 dcmjpeg/docs/dcmjpeg.dox create mode 100644 dcmjpeg/docs/dcmmkdir.man create mode 100644 dcmjpeg/docs/ijg_filelist.txt create mode 100644 dcmjpeg/docs/ijg_libjpeg.txt create mode 100644 dcmjpeg/docs/ijg_readme.txt create mode 100644 dcmjpeg/docs/ijg_structure.txt create mode 100644 dcmjpeg/etc/Makefile.in create mode 100644 dcmjpeg/include/CMakeLists.txt create mode 100644 dcmjpeg/include/Makefile.in create mode 100644 dcmjpeg/include/dcmtk/dcmjpeg/ddpiimpl.h create mode 100644 dcmjpeg/include/dcmtk/dcmjpeg/dipijpeg.h create mode 100644 dcmjpeg/include/dcmtk/dcmjpeg/djcodecd.h create mode 100644 dcmjpeg/include/dcmtk/dcmjpeg/djcodece.h create mode 100644 dcmjpeg/include/dcmtk/dcmjpeg/djcparam.h create mode 100644 dcmjpeg/include/dcmtk/dcmjpeg/djdecabs.h create mode 100644 dcmjpeg/include/dcmtk/dcmjpeg/djdecbas.h create mode 100644 dcmjpeg/include/dcmtk/dcmjpeg/djdecext.h create mode 100644 dcmjpeg/include/dcmtk/dcmjpeg/djdeclol.h create mode 100644 dcmjpeg/include/dcmtk/dcmjpeg/djdecode.h create mode 100644 dcmjpeg/include/dcmtk/dcmjpeg/djdecpro.h create mode 100644 dcmjpeg/include/dcmtk/dcmjpeg/djdecsps.h create mode 100644 dcmjpeg/include/dcmtk/dcmjpeg/djdecsv1.h create mode 100644 dcmjpeg/include/dcmtk/dcmjpeg/djdefine.h create mode 100644 dcmjpeg/include/dcmtk/dcmjpeg/djdijg12.h create mode 100644 dcmjpeg/include/dcmtk/dcmjpeg/djdijg16.h create mode 100644 dcmjpeg/include/dcmtk/dcmjpeg/djdijg8.h create mode 100644 dcmjpeg/include/dcmtk/dcmjpeg/djeijg12.h create mode 100644 dcmjpeg/include/dcmtk/dcmjpeg/djeijg16.h create mode 100644 dcmjpeg/include/dcmtk/dcmjpeg/djeijg8.h create mode 100644 dcmjpeg/include/dcmtk/dcmjpeg/djencabs.h create mode 100644 dcmjpeg/include/dcmtk/dcmjpeg/djencbas.h create mode 100644 dcmjpeg/include/dcmtk/dcmjpeg/djencext.h create mode 100644 dcmjpeg/include/dcmtk/dcmjpeg/djenclol.h create mode 100644 dcmjpeg/include/dcmtk/dcmjpeg/djencode.h create mode 100644 dcmjpeg/include/dcmtk/dcmjpeg/djencpro.h create mode 100644 dcmjpeg/include/dcmtk/dcmjpeg/djencsps.h create mode 100644 dcmjpeg/include/dcmtk/dcmjpeg/djencsv1.h create mode 100644 dcmjpeg/include/dcmtk/dcmjpeg/djrplol.h create mode 100644 dcmjpeg/include/dcmtk/dcmjpeg/djrploss.h create mode 100644 dcmjpeg/include/dcmtk/dcmjpeg/djutils.h create mode 100644 dcmjpeg/libijg12/CMakeLists.txt create mode 100644 dcmjpeg/libijg12/Makefile.dep create mode 100644 dcmjpeg/libijg12/Makefile.in create mode 100644 dcmjpeg/libijg12/jaricom.c create mode 100644 dcmjpeg/libijg12/jcapimin.c create mode 100644 dcmjpeg/libijg12/jcapistd.c create mode 100644 dcmjpeg/libijg12/jcarith.c create mode 100644 dcmjpeg/libijg12/jccoefct.c create mode 100644 dcmjpeg/libijg12/jccolor.c create mode 100644 dcmjpeg/libijg12/jcdctmgr.c create mode 100644 dcmjpeg/libijg12/jcdiffct.c create mode 100644 dcmjpeg/libijg12/jchuff.c create mode 100644 dcmjpeg/libijg12/jchuff12.h create mode 100644 dcmjpeg/libijg12/jcinit.c create mode 100644 dcmjpeg/libijg12/jclhuff.c create mode 100644 dcmjpeg/libijg12/jclossls.c create mode 100644 dcmjpeg/libijg12/jclossy.c create mode 100644 dcmjpeg/libijg12/jcmainct.c create mode 100644 dcmjpeg/libijg12/jcmarker.c create mode 100644 dcmjpeg/libijg12/jcmaster.c create mode 100644 dcmjpeg/libijg12/jcodec.c create mode 100644 dcmjpeg/libijg12/jcomapi.c create mode 100644 dcmjpeg/libijg12/jconfig12.h create mode 100644 dcmjpeg/libijg12/jcparam.c create mode 100644 dcmjpeg/libijg12/jcphuff.c create mode 100644 dcmjpeg/libijg12/jcpred.c create mode 100644 dcmjpeg/libijg12/jcprepct.c create mode 100644 dcmjpeg/libijg12/jcsample.c create mode 100644 dcmjpeg/libijg12/jcscale.c create mode 100644 dcmjpeg/libijg12/jcshuff.c create mode 100644 dcmjpeg/libijg12/jctrans.c create mode 100644 dcmjpeg/libijg12/jdapimin.c create mode 100644 dcmjpeg/libijg12/jdapistd.c create mode 100644 dcmjpeg/libijg12/jdarith.c create mode 100644 dcmjpeg/libijg12/jdatadst.c create mode 100644 dcmjpeg/libijg12/jdatasrc.c create mode 100644 dcmjpeg/libijg12/jdcoefct.c create mode 100644 dcmjpeg/libijg12/jdcolor.c create mode 100644 dcmjpeg/libijg12/jdct12.h create mode 100644 dcmjpeg/libijg12/jddctmgr.c create mode 100644 dcmjpeg/libijg12/jddiffct.c create mode 100644 dcmjpeg/libijg12/jdhuff.c create mode 100644 dcmjpeg/libijg12/jdhuff12.h create mode 100644 dcmjpeg/libijg12/jdinput.c create mode 100644 dcmjpeg/libijg12/jdlhuff.c create mode 100644 dcmjpeg/libijg12/jdlossls.c create mode 100644 dcmjpeg/libijg12/jdlossy.c create mode 100644 dcmjpeg/libijg12/jdmainct.c create mode 100644 dcmjpeg/libijg12/jdmarker.c create mode 100644 dcmjpeg/libijg12/jdmaster.c create mode 100644 dcmjpeg/libijg12/jdmerge.c create mode 100644 dcmjpeg/libijg12/jdphuff.c create mode 100644 dcmjpeg/libijg12/jdpostct.c create mode 100644 dcmjpeg/libijg12/jdpred.c create mode 100644 dcmjpeg/libijg12/jdsample.c create mode 100644 dcmjpeg/libijg12/jdscale.c create mode 100644 dcmjpeg/libijg12/jdshuff.c create mode 100644 dcmjpeg/libijg12/jdtrans.c create mode 100644 dcmjpeg/libijg12/jerror.c create mode 100644 dcmjpeg/libijg12/jerror12.h create mode 100644 dcmjpeg/libijg12/jfdctflt.c create mode 100644 dcmjpeg/libijg12/jfdctfst.c create mode 100644 dcmjpeg/libijg12/jfdctint.c create mode 100644 dcmjpeg/libijg12/jidctflt.c create mode 100644 dcmjpeg/libijg12/jidctfst.c create mode 100644 dcmjpeg/libijg12/jidctint.c create mode 100644 dcmjpeg/libijg12/jidctred.c create mode 100644 dcmjpeg/libijg12/jinclude12.h create mode 100644 dcmjpeg/libijg12/jlossls12.h create mode 100644 dcmjpeg/libijg12/jlossy12.h create mode 100644 dcmjpeg/libijg12/jmemmgr.c create mode 100644 dcmjpeg/libijg12/jmemnobs.c create mode 100644 dcmjpeg/libijg12/jmemsys12.h create mode 100644 dcmjpeg/libijg12/jmorecfg12.h create mode 100644 dcmjpeg/libijg12/jpegint12.h create mode 100644 dcmjpeg/libijg12/jpeglib12.h create mode 100644 dcmjpeg/libijg12/jquant1.c create mode 100644 dcmjpeg/libijg12/jquant2.c create mode 100644 dcmjpeg/libijg12/jutils.c create mode 100644 dcmjpeg/libijg12/jversion12.h create mode 100644 dcmjpeg/libijg16/CMakeLists.txt create mode 100644 dcmjpeg/libijg16/Makefile.dep create mode 100644 dcmjpeg/libijg16/Makefile.in create mode 100644 dcmjpeg/libijg16/jaricom.c create mode 100644 dcmjpeg/libijg16/jcapimin.c create mode 100644 dcmjpeg/libijg16/jcapistd.c create mode 100644 dcmjpeg/libijg16/jcarith.c create mode 100644 dcmjpeg/libijg16/jccoefct.c create mode 100644 dcmjpeg/libijg16/jccolor.c create mode 100644 dcmjpeg/libijg16/jcdctmgr.c create mode 100644 dcmjpeg/libijg16/jcdiffct.c create mode 100644 dcmjpeg/libijg16/jchuff.c create mode 100644 dcmjpeg/libijg16/jchuff16.h create mode 100644 dcmjpeg/libijg16/jcinit.c create mode 100644 dcmjpeg/libijg16/jclhuff.c create mode 100644 dcmjpeg/libijg16/jclossls.c create mode 100644 dcmjpeg/libijg16/jclossy.c create mode 100644 dcmjpeg/libijg16/jcmainct.c create mode 100644 dcmjpeg/libijg16/jcmarker.c create mode 100644 dcmjpeg/libijg16/jcmaster.c create mode 100644 dcmjpeg/libijg16/jcodec.c create mode 100644 dcmjpeg/libijg16/jcomapi.c create mode 100644 dcmjpeg/libijg16/jconfig16.h create mode 100644 dcmjpeg/libijg16/jcparam.c create mode 100644 dcmjpeg/libijg16/jcphuff.c create mode 100644 dcmjpeg/libijg16/jcpred.c create mode 100644 dcmjpeg/libijg16/jcprepct.c create mode 100644 dcmjpeg/libijg16/jcsample.c create mode 100644 dcmjpeg/libijg16/jcscale.c create mode 100644 dcmjpeg/libijg16/jcshuff.c create mode 100644 dcmjpeg/libijg16/jctrans.c create mode 100644 dcmjpeg/libijg16/jdapimin.c create mode 100644 dcmjpeg/libijg16/jdapistd.c create mode 100644 dcmjpeg/libijg16/jdarith.c create mode 100644 dcmjpeg/libijg16/jdatadst.c create mode 100644 dcmjpeg/libijg16/jdatasrc.c create mode 100644 dcmjpeg/libijg16/jdcoefct.c create mode 100644 dcmjpeg/libijg16/jdcolor.c create mode 100644 dcmjpeg/libijg16/jdct16.h create mode 100644 dcmjpeg/libijg16/jddctmgr.c create mode 100644 dcmjpeg/libijg16/jddiffct.c create mode 100644 dcmjpeg/libijg16/jdhuff.c create mode 100644 dcmjpeg/libijg16/jdhuff16.h create mode 100644 dcmjpeg/libijg16/jdinput.c create mode 100644 dcmjpeg/libijg16/jdlhuff.c create mode 100644 dcmjpeg/libijg16/jdlossls.c create mode 100644 dcmjpeg/libijg16/jdlossy.c create mode 100644 dcmjpeg/libijg16/jdmainct.c create mode 100644 dcmjpeg/libijg16/jdmarker.c create mode 100644 dcmjpeg/libijg16/jdmaster.c create mode 100644 dcmjpeg/libijg16/jdmerge.c create mode 100644 dcmjpeg/libijg16/jdphuff.c create mode 100644 dcmjpeg/libijg16/jdpostct.c create mode 100644 dcmjpeg/libijg16/jdpred.c create mode 100644 dcmjpeg/libijg16/jdsample.c create mode 100644 dcmjpeg/libijg16/jdscale.c create mode 100644 dcmjpeg/libijg16/jdshuff.c create mode 100644 dcmjpeg/libijg16/jdtrans.c create mode 100644 dcmjpeg/libijg16/jerror.c create mode 100644 dcmjpeg/libijg16/jerror16.h create mode 100644 dcmjpeg/libijg16/jfdctflt.c create mode 100644 dcmjpeg/libijg16/jfdctfst.c create mode 100644 dcmjpeg/libijg16/jfdctint.c create mode 100644 dcmjpeg/libijg16/jidctflt.c create mode 100644 dcmjpeg/libijg16/jidctfst.c create mode 100644 dcmjpeg/libijg16/jidctint.c create mode 100644 dcmjpeg/libijg16/jidctred.c create mode 100644 dcmjpeg/libijg16/jinclude16.h create mode 100644 dcmjpeg/libijg16/jlossls16.h create mode 100644 dcmjpeg/libijg16/jlossy16.h create mode 100644 dcmjpeg/libijg16/jmemmgr.c create mode 100644 dcmjpeg/libijg16/jmemnobs.c create mode 100644 dcmjpeg/libijg16/jmemsys16.h create mode 100644 dcmjpeg/libijg16/jmorecfg16.h create mode 100644 dcmjpeg/libijg16/jpegint16.h create mode 100644 dcmjpeg/libijg16/jpeglib16.h create mode 100644 dcmjpeg/libijg16/jquant1.c create mode 100644 dcmjpeg/libijg16/jquant2.c create mode 100644 dcmjpeg/libijg16/jutils.c create mode 100644 dcmjpeg/libijg16/jversion16.h create mode 100644 dcmjpeg/libijg8/CMakeLists.txt create mode 100644 dcmjpeg/libijg8/Makefile.dep create mode 100644 dcmjpeg/libijg8/Makefile.in create mode 100644 dcmjpeg/libijg8/jaricom.c create mode 100644 dcmjpeg/libijg8/jcapimin.c create mode 100644 dcmjpeg/libijg8/jcapistd.c create mode 100644 dcmjpeg/libijg8/jcarith.c create mode 100644 dcmjpeg/libijg8/jccoefct.c create mode 100644 dcmjpeg/libijg8/jccolor.c create mode 100644 dcmjpeg/libijg8/jcdctmgr.c create mode 100644 dcmjpeg/libijg8/jcdiffct.c create mode 100644 dcmjpeg/libijg8/jchuff.c create mode 100644 dcmjpeg/libijg8/jchuff8.h create mode 100644 dcmjpeg/libijg8/jcinit.c create mode 100644 dcmjpeg/libijg8/jclhuff.c create mode 100644 dcmjpeg/libijg8/jclossls.c create mode 100644 dcmjpeg/libijg8/jclossy.c create mode 100644 dcmjpeg/libijg8/jcmainct.c create mode 100644 dcmjpeg/libijg8/jcmarker.c create mode 100644 dcmjpeg/libijg8/jcmaster.c create mode 100644 dcmjpeg/libijg8/jcodec.c create mode 100644 dcmjpeg/libijg8/jcomapi.c create mode 100644 dcmjpeg/libijg8/jconfig8.h create mode 100644 dcmjpeg/libijg8/jcparam.c create mode 100644 dcmjpeg/libijg8/jcphuff.c create mode 100644 dcmjpeg/libijg8/jcpred.c create mode 100644 dcmjpeg/libijg8/jcprepct.c create mode 100644 dcmjpeg/libijg8/jcsample.c create mode 100644 dcmjpeg/libijg8/jcscale.c create mode 100644 dcmjpeg/libijg8/jcshuff.c create mode 100644 dcmjpeg/libijg8/jctrans.c create mode 100644 dcmjpeg/libijg8/jdapimin.c create mode 100644 dcmjpeg/libijg8/jdapistd.c create mode 100644 dcmjpeg/libijg8/jdarith.c create mode 100644 dcmjpeg/libijg8/jdatadst.c create mode 100644 dcmjpeg/libijg8/jdatasrc.c create mode 100644 dcmjpeg/libijg8/jdcoefct.c create mode 100644 dcmjpeg/libijg8/jdcolor.c create mode 100644 dcmjpeg/libijg8/jdct8.h create mode 100644 dcmjpeg/libijg8/jddctmgr.c create mode 100644 dcmjpeg/libijg8/jddiffct.c create mode 100644 dcmjpeg/libijg8/jdhuff.c create mode 100644 dcmjpeg/libijg8/jdhuff8.h create mode 100644 dcmjpeg/libijg8/jdinput.c create mode 100644 dcmjpeg/libijg8/jdlhuff.c create mode 100644 dcmjpeg/libijg8/jdlossls.c create mode 100644 dcmjpeg/libijg8/jdlossy.c create mode 100644 dcmjpeg/libijg8/jdmainct.c create mode 100644 dcmjpeg/libijg8/jdmarker.c create mode 100644 dcmjpeg/libijg8/jdmaster.c create mode 100644 dcmjpeg/libijg8/jdmerge.c create mode 100644 dcmjpeg/libijg8/jdphuff.c create mode 100644 dcmjpeg/libijg8/jdpostct.c create mode 100644 dcmjpeg/libijg8/jdpred.c create mode 100644 dcmjpeg/libijg8/jdsample.c create mode 100644 dcmjpeg/libijg8/jdscale.c create mode 100644 dcmjpeg/libijg8/jdshuff.c create mode 100644 dcmjpeg/libijg8/jdtrans.c create mode 100644 dcmjpeg/libijg8/jerror.c create mode 100644 dcmjpeg/libijg8/jerror8.h create mode 100644 dcmjpeg/libijg8/jfdctflt.c create mode 100644 dcmjpeg/libijg8/jfdctfst.c create mode 100644 dcmjpeg/libijg8/jfdctint.c create mode 100644 dcmjpeg/libijg8/jidctflt.c create mode 100644 dcmjpeg/libijg8/jidctfst.c create mode 100644 dcmjpeg/libijg8/jidctint.c create mode 100644 dcmjpeg/libijg8/jidctred.c create mode 100644 dcmjpeg/libijg8/jinclude8.h create mode 100644 dcmjpeg/libijg8/jlossls8.h create mode 100644 dcmjpeg/libijg8/jlossy8.h create mode 100644 dcmjpeg/libijg8/jmemmgr.c create mode 100644 dcmjpeg/libijg8/jmemnobs.c create mode 100644 dcmjpeg/libijg8/jmemsys8.h create mode 100644 dcmjpeg/libijg8/jmorecfg8.h create mode 100644 dcmjpeg/libijg8/jpegint8.h create mode 100644 dcmjpeg/libijg8/jpeglib8.h create mode 100644 dcmjpeg/libijg8/jquant1.c create mode 100644 dcmjpeg/libijg8/jquant2.c create mode 100644 dcmjpeg/libijg8/jutils.c create mode 100644 dcmjpeg/libijg8/jversion8.h create mode 100644 dcmjpeg/libsrc/CMakeLists.txt create mode 100644 dcmjpeg/libsrc/Makefile.dep create mode 100644 dcmjpeg/libsrc/Makefile.in create mode 100644 dcmjpeg/libsrc/ddpiimpl.cc create mode 100644 dcmjpeg/libsrc/dipijpeg.cc create mode 100644 dcmjpeg/libsrc/djcodecd.cc create mode 100644 dcmjpeg/libsrc/djcodece.cc create mode 100644 dcmjpeg/libsrc/djcparam.cc create mode 100644 dcmjpeg/libsrc/djdecbas.cc create mode 100644 dcmjpeg/libsrc/djdecext.cc create mode 100644 dcmjpeg/libsrc/djdeclol.cc create mode 100644 dcmjpeg/libsrc/djdecode.cc create mode 100644 dcmjpeg/libsrc/djdecpro.cc create mode 100644 dcmjpeg/libsrc/djdecsps.cc create mode 100644 dcmjpeg/libsrc/djdecsv1.cc create mode 100644 dcmjpeg/libsrc/djdijg12.cc create mode 100644 dcmjpeg/libsrc/djdijg16.cc create mode 100644 dcmjpeg/libsrc/djdijg8.cc create mode 100644 dcmjpeg/libsrc/djeijg12.cc create mode 100644 dcmjpeg/libsrc/djeijg16.cc create mode 100644 dcmjpeg/libsrc/djeijg8.cc create mode 100644 dcmjpeg/libsrc/djencbas.cc create mode 100644 dcmjpeg/libsrc/djencext.cc create mode 100644 dcmjpeg/libsrc/djenclol.cc create mode 100644 dcmjpeg/libsrc/djencode.cc create mode 100644 dcmjpeg/libsrc/djencpro.cc create mode 100644 dcmjpeg/libsrc/djencsps.cc create mode 100644 dcmjpeg/libsrc/djencsv1.cc create mode 100644 dcmjpeg/libsrc/djrplol.cc create mode 100644 dcmjpeg/libsrc/djrploss.cc create mode 100644 dcmjpeg/libsrc/djutils.cc create mode 100644 dcmjpeg/tests/Makefile.in create mode 100644 dcmjpls/CMakeLists.txt create mode 100644 dcmjpls/Makefile.in create mode 100644 dcmjpls/apps/CMakeLists.txt create mode 100644 dcmjpls/apps/Makefile.dep create mode 100644 dcmjpls/apps/Makefile.in create mode 100644 dcmjpls/apps/dcmcjpls.cc create mode 100644 dcmjpls/apps/dcmdjpls.cc create mode 100644 dcmjpls/apps/dcml2pnm.cc create mode 100755 dcmjpls/configure create mode 100644 dcmjpls/data/Makefile.in create mode 100644 dcmjpls/docs/License.txt create mode 100644 dcmjpls/docs/Makefile.in create mode 100644 dcmjpls/docs/dcmcjpls.man create mode 100644 dcmjpls/docs/dcmdjpls.man create mode 100644 dcmjpls/docs/dcmjpls.dox create mode 100644 dcmjpls/docs/dcml2pnm.man create mode 100644 dcmjpls/docs/readme.txt create mode 100644 dcmjpls/etc/Makefile.in create mode 100644 dcmjpls/include/CMakeLists.txt create mode 100644 dcmjpls/include/Makefile.in create mode 100644 dcmjpls/include/dcmtk/dcmjpls/djcodecd.h create mode 100644 dcmjpls/include/dcmtk/dcmjpls/djcodece.h create mode 100644 dcmjpls/include/dcmtk/dcmjpls/djcparam.h create mode 100644 dcmjpls/include/dcmtk/dcmjpls/djdecode.h create mode 100644 dcmjpls/include/dcmtk/dcmjpls/djencode.h create mode 100644 dcmjpls/include/dcmtk/dcmjpls/djlsutil.h create mode 100644 dcmjpls/include/dcmtk/dcmjpls/djrparam.h create mode 100644 dcmjpls/include/dcmtk/dcmjpls/dldefine.h create mode 100644 dcmjpls/libcharls/CMakeLists.txt create mode 100644 dcmjpls/libcharls/Makefile.dep create mode 100644 dcmjpls/libcharls/Makefile.in create mode 100644 dcmjpls/libcharls/clrtrans.h create mode 100644 dcmjpls/libcharls/config.h create mode 100644 dcmjpls/libcharls/context.h create mode 100644 dcmjpls/libcharls/ctxtrmod.h create mode 100644 dcmjpls/libcharls/decodstr.h create mode 100644 dcmjpls/libcharls/deftrait.h create mode 100644 dcmjpls/libcharls/encodstr.h create mode 100644 dcmjpls/libcharls/header.cc create mode 100644 dcmjpls/libcharls/header.h create mode 100644 dcmjpls/libcharls/intrface.cc create mode 100644 dcmjpls/libcharls/intrface.h create mode 100644 dcmjpls/libcharls/jpegls.cc create mode 100644 dcmjpls/libcharls/lltraits.h create mode 100644 dcmjpls/libcharls/lokuptbl.h create mode 100644 dcmjpls/libcharls/procline.h create mode 100644 dcmjpls/libcharls/pubtypes.h create mode 100644 dcmjpls/libcharls/scan.h create mode 100644 dcmjpls/libcharls/streams.h create mode 100644 dcmjpls/libcharls/util.h create mode 100644 dcmjpls/libsrc/CMakeLists.txt create mode 100644 dcmjpls/libsrc/Makefile.dep create mode 100644 dcmjpls/libsrc/Makefile.in create mode 100644 dcmjpls/libsrc/djcodecd.cc create mode 100644 dcmjpls/libsrc/djcodece.cc create mode 100644 dcmjpls/libsrc/djcparam.cc create mode 100644 dcmjpls/libsrc/djdecode.cc create mode 100644 dcmjpls/libsrc/djencode.cc create mode 100644 dcmjpls/libsrc/djerror.h create mode 100644 dcmjpls/libsrc/djrparam.cc create mode 100644 dcmjpls/libsrc/djutils.cc create mode 100644 dcmjpls/tests/Makefile.in create mode 100644 dcmnet/CMakeLists.txt create mode 100644 dcmnet/Makefile.in create mode 100644 dcmnet/apps/CMakeLists.txt create mode 100644 dcmnet/apps/Makefile.dep create mode 100644 dcmnet/apps/Makefile.in create mode 100644 dcmnet/apps/dcmrecv.cc create mode 100644 dcmnet/apps/dcmsend.cc create mode 100644 dcmnet/apps/echoscu.cc create mode 100644 dcmnet/apps/findscu.cc create mode 100644 dcmnet/apps/getscu.cc create mode 100644 dcmnet/apps/movescu.cc create mode 100644 dcmnet/apps/storescp.cc create mode 100644 dcmnet/apps/storescu.cc create mode 100644 dcmnet/apps/termscu.cc create mode 100755 dcmnet/configure create mode 100644 dcmnet/data/Makefile.in create mode 100644 dcmnet/docs/CMakeLists.txt create mode 100644 dcmnet/docs/Makefile.in create mode 100644 dcmnet/docs/asconfig.txt create mode 100644 dcmnet/docs/cptscp.dox create mode 100644 dcmnet/docs/dcmnet.dox create mode 100644 dcmnet/docs/dcmrecv.man create mode 100644 dcmnet/docs/dcmsend.man create mode 100644 dcmnet/docs/echoscu.man create mode 100644 dcmnet/docs/findscu.man create mode 100644 dcmnet/docs/getscu.man create mode 100644 dcmnet/docs/movescu.man create mode 100644 dcmnet/docs/storescp.man create mode 100644 dcmnet/docs/storescu.man create mode 100644 dcmnet/docs/termscu.man create mode 100644 dcmnet/docs/testing.txt create mode 100644 dcmnet/etc/CMakeLists.txt create mode 100644 dcmnet/etc/Makefile.in create mode 100644 dcmnet/etc/storescp.cfg create mode 100644 dcmnet/etc/storescu.cfg create mode 100644 dcmnet/include/CMakeLists.txt create mode 100644 dcmnet/include/Makefile.in create mode 100644 dcmnet/include/dcmtk/dcmnet/assoc.h create mode 100644 dcmnet/include/dcmtk/dcmnet/cond.h create mode 100644 dcmnet/include/dcmtk/dcmnet/dcasccff.h create mode 100644 dcmnet/include/dcmtk/dcmnet/dcasccfg.h create mode 100644 dcmnet/include/dcmtk/dcmnet/dccfenmp.h create mode 100644 dcmnet/include/dcmtk/dcmnet/dccfpcmp.h create mode 100644 dcmnet/include/dcmtk/dcmnet/dccfprmp.h create mode 100644 dcmnet/include/dcmtk/dcmnet/dccfrsmp.h create mode 100644 dcmnet/include/dcmtk/dcmnet/dccftsmp.h create mode 100644 dcmnet/include/dcmtk/dcmnet/dccfuidh.h create mode 100644 dcmnet/include/dcmtk/dcmnet/dcmlayer.h create mode 100644 dcmnet/include/dcmtk/dcmnet/dcmsmap.h create mode 100644 dcmnet/include/dcmtk/dcmnet/dcmtrans.h create mode 100644 dcmnet/include/dcmtk/dcmnet/dcompat.h create mode 100644 dcmnet/include/dcmtk/dcmnet/dcuserid.h create mode 100644 dcmnet/include/dcmtk/dcmnet/dfindscu.h create mode 100644 dcmnet/include/dcmtk/dcmnet/dicom.h create mode 100644 dcmnet/include/dcmtk/dcmnet/dimse.h create mode 100644 dcmnet/include/dcmtk/dcmnet/diutil.h create mode 100644 dcmnet/include/dcmtk/dcmnet/dndefine.h create mode 100644 dcmnet/include/dcmtk/dcmnet/dstorscp.h create mode 100644 dcmnet/include/dcmtk/dcmnet/dstorscu.h create mode 100644 dcmnet/include/dcmtk/dcmnet/dul.h create mode 100644 dcmnet/include/dcmtk/dcmnet/extneg.h create mode 100644 dcmnet/include/dcmtk/dcmnet/lst.h create mode 100644 dcmnet/include/dcmtk/dcmnet/scp.h create mode 100644 dcmnet/include/dcmtk/dcmnet/scpcfg.h create mode 100644 dcmnet/include/dcmtk/dcmnet/scppool.h create mode 100644 dcmnet/include/dcmtk/dcmnet/scpthrd.h create mode 100644 dcmnet/include/dcmtk/dcmnet/scu.h create mode 100644 dcmnet/libsrc/CMakeLists.txt create mode 100644 dcmnet/libsrc/Makefile.dep create mode 100644 dcmnet/libsrc/Makefile.in create mode 100644 dcmnet/libsrc/assoc.cc create mode 100644 dcmnet/libsrc/cond.cc create mode 100644 dcmnet/libsrc/dcasccff.cc create mode 100644 dcmnet/libsrc/dcasccfg.cc create mode 100644 dcmnet/libsrc/dccfenmp.cc create mode 100644 dcmnet/libsrc/dccfpcmp.cc create mode 100644 dcmnet/libsrc/dccfprmp.cc create mode 100644 dcmnet/libsrc/dccfrsmp.cc create mode 100644 dcmnet/libsrc/dccftsmp.cc create mode 100644 dcmnet/libsrc/dccfuidh.cc create mode 100644 dcmnet/libsrc/dcmlayer.cc create mode 100644 dcmnet/libsrc/dcmtrans.cc create mode 100644 dcmnet/libsrc/dcompat.cc create mode 100644 dcmnet/libsrc/dcuserid.cc create mode 100644 dcmnet/libsrc/dfindscu.cc create mode 100644 dcmnet/libsrc/dimcancl.cc create mode 100644 dcmnet/libsrc/dimcmd.cc create mode 100644 dcmnet/libsrc/dimcmd.h create mode 100644 dcmnet/libsrc/dimdump.cc create mode 100644 dcmnet/libsrc/dimecho.cc create mode 100644 dcmnet/libsrc/dimfind.cc create mode 100644 dcmnet/libsrc/dimget.cc create mode 100644 dcmnet/libsrc/dimmove.cc create mode 100644 dcmnet/libsrc/dimse.cc create mode 100644 dcmnet/libsrc/dimstore.cc create mode 100644 dcmnet/libsrc/diutil.cc create mode 100644 dcmnet/libsrc/dstorscp.cc create mode 100644 dcmnet/libsrc/dstorscu.cc create mode 100644 dcmnet/libsrc/dul.cc create mode 100644 dcmnet/libsrc/dulconst.cc create mode 100644 dcmnet/libsrc/dulextra.cc create mode 100644 dcmnet/libsrc/dulfsm.cc create mode 100644 dcmnet/libsrc/dulfsm.h create mode 100644 dcmnet/libsrc/dulparse.cc create mode 100644 dcmnet/libsrc/dulpres.cc create mode 100644 dcmnet/libsrc/dulpriv.h create mode 100644 dcmnet/libsrc/dulstruc.h create mode 100644 dcmnet/libsrc/dwrap.c create mode 100644 dcmnet/libsrc/extneg.cc create mode 100644 dcmnet/libsrc/lst.cc create mode 100644 dcmnet/libsrc/scp.cc create mode 100644 dcmnet/libsrc/scpcfg.cc create mode 100644 dcmnet/libsrc/scppool.cc create mode 100644 dcmnet/libsrc/scpthrd.cc create mode 100644 dcmnet/libsrc/scu.cc create mode 100644 dcmnet/tests/CMakeLists.txt create mode 100644 dcmnet/tests/Makefile.dep create mode 100644 dcmnet/tests/Makefile.in create mode 100644 dcmnet/tests/tdump.cc create mode 100644 dcmnet/tests/tests.cc create mode 100644 dcmnet/tests/tpool.cc create mode 100644 dcmpstat/CMakeLists.txt create mode 100644 dcmpstat/Makefile.in create mode 100644 dcmpstat/apps/CMakeLists.txt create mode 100644 dcmpstat/apps/Makefile.dep create mode 100644 dcmpstat/apps/Makefile.in create mode 100644 dcmpstat/apps/dcmmkcrv.cc create mode 100644 dcmpstat/apps/dcmmklut.cc create mode 100644 dcmpstat/apps/dcmp2pgm.cc create mode 100644 dcmpstat/apps/dcmprscp.cc create mode 100644 dcmpstat/apps/dcmprscu.cc create mode 100644 dcmpstat/apps/dcmpschk.cc create mode 100644 dcmpstat/apps/dcmpsmk.cc create mode 100644 dcmpstat/apps/dcmpsprt.cc create mode 100644 dcmpstat/apps/dcmpsrcv.cc create mode 100644 dcmpstat/apps/dcmpssnd.cc create mode 100755 dcmpstat/configure create mode 100644 dcmpstat/data/CMakeLists.txt create mode 100644 dcmpstat/data/Makefile.in create mode 100644 dcmpstat/data/philips.lut create mode 100644 dcmpstat/docs/Makefile.in create mode 100644 dcmpstat/docs/dcmmkcrv.man create mode 100644 dcmpstat/docs/dcmmklut.man create mode 100644 dcmpstat/docs/dcmp2pgm.man create mode 100644 dcmpstat/docs/dcmprscp.man create mode 100644 dcmpstat/docs/dcmprscu.man create mode 100644 dcmpstat/docs/dcmpschk.man create mode 100644 dcmpstat/docs/dcmpsmk.man create mode 100644 dcmpstat/docs/dcmpsprt.man create mode 100644 dcmpstat/docs/dcmpsrcv.man create mode 100644 dcmpstat/docs/dcmpssnd.man create mode 100644 dcmpstat/docs/dcmpstat.dox create mode 100644 dcmpstat/etc/CMakeLists.txt create mode 100644 dcmpstat/etc/Makefile.in create mode 100644 dcmpstat/etc/dcmpstat.cfg create mode 100644 dcmpstat/etc/printers.cfg create mode 100644 dcmpstat/include/CMakeLists.txt create mode 100644 dcmpstat/include/Makefile.in create mode 100644 dcmpstat/include/dcmtk/dcmpstat/dcmpstat.h create mode 100644 dcmpstat/include/dcmtk/dcmpstat/dpdefine.h create mode 100644 dcmpstat/include/dcmtk/dcmpstat/dvcache.h create mode 100644 dcmpstat/include/dcmtk/dcmpstat/dviface.h create mode 100644 dcmpstat/include/dcmtk/dcmpstat/dvpsab.h create mode 100644 dcmpstat/include/dcmtk/dcmpstat/dvpsabl.h create mode 100644 dcmpstat/include/dcmtk/dcmpstat/dvpsal.h create mode 100644 dcmpstat/include/dcmtk/dcmpstat/dvpsall.h create mode 100644 dcmpstat/include/dcmtk/dcmpstat/dvpscf.h create mode 100644 dcmpstat/include/dcmtk/dcmpstat/dvpscu.h create mode 100644 dcmpstat/include/dcmtk/dcmpstat/dvpscul.h create mode 100644 dcmpstat/include/dcmtk/dcmpstat/dvpsda.h create mode 100644 dcmpstat/include/dcmtk/dcmpstat/dvpsdal.h create mode 100644 dcmpstat/include/dcmtk/dcmpstat/dvpsdef.h create mode 100644 dcmpstat/include/dcmtk/dcmpstat/dvpsfs.h create mode 100644 dcmpstat/include/dcmtk/dcmpstat/dvpsga.h create mode 100644 dcmpstat/include/dcmtk/dcmpstat/dvpsgal.h create mode 100644 dcmpstat/include/dcmtk/dcmpstat/dvpsgl.h create mode 100644 dcmpstat/include/dcmtk/dcmpstat/dvpsgll.h create mode 100644 dcmpstat/include/dcmtk/dcmpstat/dvpsgr.h create mode 100644 dcmpstat/include/dcmtk/dcmpstat/dvpsgrl.h create mode 100644 dcmpstat/include/dcmtk/dcmpstat/dvpshlp.h create mode 100644 dcmpstat/include/dcmtk/dcmpstat/dvpsib.h create mode 100644 dcmpstat/include/dcmtk/dcmpstat/dvpsibl.h create mode 100644 dcmpstat/include/dcmtk/dcmpstat/dvpsmsg.h create mode 100644 dcmpstat/include/dcmtk/dcmpstat/dvpsov.h create mode 100644 dcmpstat/include/dcmtk/dcmpstat/dvpsovl.h create mode 100644 dcmpstat/include/dcmtk/dcmpstat/dvpspl.h create mode 100644 dcmpstat/include/dcmtk/dcmpstat/dvpspll.h create mode 100644 dcmpstat/include/dcmtk/dcmpstat/dvpspr.h create mode 100644 dcmpstat/include/dcmtk/dcmpstat/dvpsprt.h create mode 100644 dcmpstat/include/dcmtk/dcmpstat/dvpsri.h create mode 100644 dcmpstat/include/dcmtk/dcmpstat/dvpsril.h create mode 100644 dcmpstat/include/dcmtk/dcmpstat/dvpsrs.h create mode 100644 dcmpstat/include/dcmtk/dcmpstat/dvpsrsl.h create mode 100644 dcmpstat/include/dcmtk/dcmpstat/dvpssp.h create mode 100644 dcmpstat/include/dcmtk/dcmpstat/dvpsspl.h create mode 100644 dcmpstat/include/dcmtk/dcmpstat/dvpssv.h create mode 100644 dcmpstat/include/dcmtk/dcmpstat/dvpssvl.h create mode 100644 dcmpstat/include/dcmtk/dcmpstat/dvpstat.h create mode 100644 dcmpstat/include/dcmtk/dcmpstat/dvpstx.h create mode 100644 dcmpstat/include/dcmtk/dcmpstat/dvpstxl.h create mode 100644 dcmpstat/include/dcmtk/dcmpstat/dvpstyp.h create mode 100644 dcmpstat/include/dcmtk/dcmpstat/dvpsvl.h create mode 100644 dcmpstat/include/dcmtk/dcmpstat/dvpsvll.h create mode 100644 dcmpstat/include/dcmtk/dcmpstat/dvpsvw.h create mode 100644 dcmpstat/include/dcmtk/dcmpstat/dvpsvwl.h create mode 100644 dcmpstat/include/dcmtk/dcmpstat/dvsighdl.h create mode 100644 dcmpstat/jni/Makefile.dep create mode 100644 dcmpstat/jni/Makefile.in create mode 100755 dcmpstat/jni/make_stub.sh create mode 100644 dcmpstat/libsrc/CMakeLists.txt create mode 100644 dcmpstat/libsrc/Makefile.dep create mode 100644 dcmpstat/libsrc/Makefile.in create mode 100644 dcmpstat/libsrc/dcmpstat.cc create mode 100644 dcmpstat/libsrc/dviface.cc create mode 100644 dcmpstat/libsrc/dvpsab.cc create mode 100644 dcmpstat/libsrc/dvpsabl.cc create mode 100644 dcmpstat/libsrc/dvpsal.cc create mode 100644 dcmpstat/libsrc/dvpsall.cc create mode 100644 dcmpstat/libsrc/dvpscf.cc create mode 100644 dcmpstat/libsrc/dvpscu.cc create mode 100644 dcmpstat/libsrc/dvpscul.cc create mode 100644 dcmpstat/libsrc/dvpsda.cc create mode 100644 dcmpstat/libsrc/dvpsdal.cc create mode 100644 dcmpstat/libsrc/dvpsfs.cc create mode 100644 dcmpstat/libsrc/dvpsga.cc create mode 100644 dcmpstat/libsrc/dvpsgal.cc create mode 100644 dcmpstat/libsrc/dvpsgl.cc create mode 100644 dcmpstat/libsrc/dvpsgll.cc create mode 100644 dcmpstat/libsrc/dvpsgr.cc create mode 100644 dcmpstat/libsrc/dvpsgrl.cc create mode 100644 dcmpstat/libsrc/dvpshlp.cc create mode 100644 dcmpstat/libsrc/dvpsib.cc create mode 100644 dcmpstat/libsrc/dvpsibl.cc create mode 100644 dcmpstat/libsrc/dvpsmsg.cc create mode 100644 dcmpstat/libsrc/dvpsov.cc create mode 100644 dcmpstat/libsrc/dvpsovl.cc create mode 100644 dcmpstat/libsrc/dvpspl.cc create mode 100644 dcmpstat/libsrc/dvpspl2.cc create mode 100644 dcmpstat/libsrc/dvpspll.cc create mode 100644 dcmpstat/libsrc/dvpspr.cc create mode 100644 dcmpstat/libsrc/dvpsprt.cc create mode 100644 dcmpstat/libsrc/dvpsri.cc create mode 100644 dcmpstat/libsrc/dvpsril.cc create mode 100644 dcmpstat/libsrc/dvpsrs.cc create mode 100644 dcmpstat/libsrc/dvpsrsl.cc create mode 100644 dcmpstat/libsrc/dvpssp.cc create mode 100644 dcmpstat/libsrc/dvpsspl.cc create mode 100644 dcmpstat/libsrc/dvpssv.cc create mode 100644 dcmpstat/libsrc/dvpssvl.cc create mode 100644 dcmpstat/libsrc/dvpstat.cc create mode 100644 dcmpstat/libsrc/dvpstx.cc create mode 100644 dcmpstat/libsrc/dvpstxl.cc create mode 100644 dcmpstat/libsrc/dvpsvl.cc create mode 100644 dcmpstat/libsrc/dvpsvll.cc create mode 100644 dcmpstat/libsrc/dvpsvw.cc create mode 100644 dcmpstat/libsrc/dvpsvwl.cc create mode 100644 dcmpstat/libsrc/dvsighdl.cc create mode 100644 dcmpstat/tests/Makefile.dep create mode 100644 dcmpstat/tests/Makefile.in create mode 100644 dcmpstat/tests/dcmpschk.tcl create mode 100755 dcmpstat/tests/dcmpsprt.pl create mode 100644 dcmpstat/tests/msgserv.cc create mode 100644 dcmqrdb/CMakeLists.txt create mode 100644 dcmqrdb/Makefile.in create mode 100644 dcmqrdb/apps/CMakeLists.txt create mode 100644 dcmqrdb/apps/Makefile.dep create mode 100644 dcmqrdb/apps/Makefile.in create mode 100644 dcmqrdb/apps/dcmqridx.cc create mode 100644 dcmqrdb/apps/dcmqrscp.cc create mode 100644 dcmqrdb/apps/dcmqrti.cc create mode 100755 dcmqrdb/configure create mode 100644 dcmqrdb/data/Makefile.in create mode 100644 dcmqrdb/docs/CMakeLists.txt create mode 100644 dcmqrdb/docs/Makefile.in create mode 100644 dcmqrdb/docs/dcmqrcnf.txt create mode 100644 dcmqrdb/docs/dcmqrdb.dox create mode 100644 dcmqrdb/docs/dcmqridx.man create mode 100644 dcmqrdb/docs/dcmqrscp.man create mode 100644 dcmqrdb/docs/dcmqrset.txt create mode 100644 dcmqrdb/docs/dcmqrti.man create mode 100644 dcmqrdb/etc/CMakeLists.txt create mode 100644 dcmqrdb/etc/Makefile.in create mode 100644 dcmqrdb/etc/dcmqrscp.cfg create mode 100644 dcmqrdb/include/CMakeLists.txt create mode 100644 dcmqrdb/include/Makefile.in create mode 100644 dcmqrdb/include/dcmtk/dcmqrdb/dcmqrcbf.h create mode 100644 dcmqrdb/include/dcmtk/dcmqrdb/dcmqrcbg.h create mode 100644 dcmqrdb/include/dcmtk/dcmqrdb/dcmqrcbm.h create mode 100644 dcmqrdb/include/dcmtk/dcmqrdb/dcmqrcbs.h create mode 100644 dcmqrdb/include/dcmtk/dcmqrdb/dcmqrcnf.h create mode 100644 dcmqrdb/include/dcmtk/dcmqrdb/dcmqrdba.h create mode 100644 dcmqrdb/include/dcmtk/dcmqrdb/dcmqrdbi.h create mode 100644 dcmqrdb/include/dcmtk/dcmqrdb/dcmqrdbs.h create mode 100644 dcmqrdb/include/dcmtk/dcmqrdb/dcmqridx.h create mode 100644 dcmqrdb/include/dcmtk/dcmqrdb/dcmqropt.h create mode 100644 dcmqrdb/include/dcmtk/dcmqrdb/dcmqrptb.h create mode 100644 dcmqrdb/include/dcmtk/dcmqrdb/dcmqrsrv.h create mode 100644 dcmqrdb/include/dcmtk/dcmqrdb/dcmqrtis.h create mode 100644 dcmqrdb/include/dcmtk/dcmqrdb/qrdefine.h create mode 100644 dcmqrdb/libsrc/CMakeLists.txt create mode 100644 dcmqrdb/libsrc/Makefile.dep create mode 100644 dcmqrdb/libsrc/Makefile.in create mode 100644 dcmqrdb/libsrc/dcmqrcbf.cc create mode 100644 dcmqrdb/libsrc/dcmqrcbg.cc create mode 100644 dcmqrdb/libsrc/dcmqrcbm.cc create mode 100644 dcmqrdb/libsrc/dcmqrcbs.cc create mode 100644 dcmqrdb/libsrc/dcmqrcnf.cc create mode 100644 dcmqrdb/libsrc/dcmqrdbi.cc create mode 100644 dcmqrdb/libsrc/dcmqrdbs.cc create mode 100644 dcmqrdb/libsrc/dcmqropt.cc create mode 100644 dcmqrdb/libsrc/dcmqrptb.cc create mode 100644 dcmqrdb/libsrc/dcmqrsrv.cc create mode 100644 dcmqrdb/libsrc/dcmqrtis.cc create mode 100644 dcmqrdb/tests/Makefile.in create mode 100644 dcmrt/CHANGES create mode 100644 dcmrt/CMakeLists.txt create mode 100644 dcmrt/Makefile.in create mode 100644 dcmrt/apps/CMakeLists.txt create mode 100644 dcmrt/apps/Makefile.dep create mode 100644 dcmrt/apps/Makefile.in create mode 100644 dcmrt/apps/drtdump.cc create mode 100755 dcmrt/configure create mode 100644 dcmrt/docs/Makefile.in create mode 100644 dcmrt/docs/dcmrt.dox create mode 100644 dcmrt/docs/drtdump.man create mode 100644 dcmrt/include/CMakeLists.txt create mode 100644 dcmrt/include/Makefile.in create mode 100644 dcmrt/include/dcmtk/dcmrt/drmdose.h create mode 100644 dcmrt/include/dcmtk/dcmrt/drmimage.h create mode 100644 dcmrt/include/dcmtk/dcmrt/drmplan.h create mode 100644 dcmrt/include/dcmtk/dcmrt/drmsrch.h create mode 100644 dcmrt/include/dcmtk/dcmrt/drmstrct.h create mode 100644 dcmrt/include/dcmtk/dcmrt/drtdose.h create mode 100644 dcmrt/include/dcmtk/dcmrt/drtimage.h create mode 100644 dcmrt/include/dcmtk/dcmrt/drtionpl.h create mode 100644 dcmrt/include/dcmtk/dcmrt/drtiontr.h create mode 100644 dcmrt/include/dcmtk/dcmrt/drtplan.h create mode 100644 dcmrt/include/dcmtk/dcmrt/drtstrct.h create mode 100644 dcmrt/include/dcmtk/dcmrt/drttreat.h create mode 100644 dcmrt/include/dcmtk/dcmrt/drttypes.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtaadcs.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtadcs.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtads.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtafs.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtags.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtajcs.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtarics.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtas1.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtas5.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtas6.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtas7.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtass.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtbads.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtbas.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtbcps.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtbl2.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtbl5.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtbldls.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtbldps.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtblds1.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtblds5.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtblds6.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtbldts.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtbrcss.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtbrdrs.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtbrs.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtbs.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtbvcps.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtcbars.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtccs.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtcctus.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtcdrs.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtces.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtchs.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtcims.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtcis.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtcncs.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtcos.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtcpas.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtcps.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtcs.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtcsas.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtcshs.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtcsis.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtcss.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtdcs.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtdimcs.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtdimrs.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtdirs.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtdrs.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtds.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtdspcs.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtdss.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtdvhs.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtdvrrs.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drteas.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtes.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtfds.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtfes.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtfgs.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtfgss.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtfms.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtfsss.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtgas.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drthsdrs.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtiais.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtians.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtiblds.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtibls.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtibs.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drticpds.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drticps.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtics.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtiis.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtipiqs.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtircs.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtiseis.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtitts.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtiwps.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtiws.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtlsds.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtlsds6.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtlsds7.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtmacds.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtmas.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtmdrs.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtmls.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtmps.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtmss.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtmucs.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtoas.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtois.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtopis.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtos.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtpbcs.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtpcs.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtpcxs.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtpfms.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtpics.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtporcs.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtporis.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtppcs.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtprsis.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtpscs.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtpsics.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtpss.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtpsss.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtpvis.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtras.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtrbas2.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtrbas8.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtrbls.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtrbos1.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtrbos6.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtrbos7.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtrbs2.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtrbs4.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtrbs8.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtrcdrs.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtrcos.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtrcps.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtrcs.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtrdros.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtrdrs1.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtrdrs6.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtrdrs8.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtrds.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtrecs.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtrfgs.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtrfors.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtrics.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtrims.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtris.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtrlsds.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtrmdrs.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtrms.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtrmss6.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtrmss7.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtrpcs.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtrpis.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtrppcs.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtrpphs.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtrpps.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtrppss.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtrps.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtrris1.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtrris6.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtrris9.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtrrms.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtrros.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtrrpcs.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtrrros.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtrrs.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtrrshs.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtrrtps.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtrrtps3.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtrrtps4.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtrrtps5.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtrscs.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtrsers.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtrses.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtrshs.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtrshs6.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtrshs7.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtrsis.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtrsns.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtrsos.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtrsrs.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtrss.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtrsss.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtrsts.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtrtrs2.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtrtrs4.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtrvis.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtrws.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtrwvms.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtscris.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtsdcs.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtsds.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtshds.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtsis.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtsns.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtspccs.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtspcs.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtss.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtssrs.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drttms0.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drttms9.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drttscds.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drttsibs.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drttsmds.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drttts.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtvls.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtwps.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtwrs.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtws.h create mode 100644 dcmrt/include/dcmtk/dcmrt/seq/drtxrs.h create mode 100644 dcmrt/libsrc/CMakeLists.txt create mode 100644 dcmrt/libsrc/Makefile.dep create mode 100644 dcmrt/libsrc/Makefile.in create mode 100644 dcmrt/libsrc/drmdose.cc create mode 100644 dcmrt/libsrc/drmimage.cc create mode 100644 dcmrt/libsrc/drmplan.cc create mode 100644 dcmrt/libsrc/drmstrct.cc create mode 100644 dcmrt/libsrc/drtaadcs.cc create mode 100644 dcmrt/libsrc/drtadcs.cc create mode 100644 dcmrt/libsrc/drtads.cc create mode 100644 dcmrt/libsrc/drtafs.cc create mode 100644 dcmrt/libsrc/drtags.cc create mode 100644 dcmrt/libsrc/drtajcs.cc create mode 100644 dcmrt/libsrc/drtarics.cc create mode 100644 dcmrt/libsrc/drtas1.cc create mode 100644 dcmrt/libsrc/drtas5.cc create mode 100644 dcmrt/libsrc/drtas6.cc create mode 100644 dcmrt/libsrc/drtas7.cc create mode 100644 dcmrt/libsrc/drtass.cc create mode 100644 dcmrt/libsrc/drtbads.cc create mode 100644 dcmrt/libsrc/drtbas.cc create mode 100644 dcmrt/libsrc/drtbcps.cc create mode 100644 dcmrt/libsrc/drtbl2.cc create mode 100644 dcmrt/libsrc/drtbl5.cc create mode 100644 dcmrt/libsrc/drtbldls.cc create mode 100644 dcmrt/libsrc/drtbldps.cc create mode 100644 dcmrt/libsrc/drtblds1.cc create mode 100644 dcmrt/libsrc/drtblds5.cc create mode 100644 dcmrt/libsrc/drtblds6.cc create mode 100644 dcmrt/libsrc/drtbldts.cc create mode 100644 dcmrt/libsrc/drtbrcss.cc create mode 100644 dcmrt/libsrc/drtbrdrs.cc create mode 100644 dcmrt/libsrc/drtbrs.cc create mode 100644 dcmrt/libsrc/drtbs.cc create mode 100644 dcmrt/libsrc/drtbvcps.cc create mode 100644 dcmrt/libsrc/drtcbars.cc create mode 100644 dcmrt/libsrc/drtccs.cc create mode 100644 dcmrt/libsrc/drtcctus.cc create mode 100644 dcmrt/libsrc/drtcdrs.cc create mode 100644 dcmrt/libsrc/drtces.cc create mode 100644 dcmrt/libsrc/drtchs.cc create mode 100644 dcmrt/libsrc/drtcims.cc create mode 100644 dcmrt/libsrc/drtcis.cc create mode 100644 dcmrt/libsrc/drtcncs.cc create mode 100644 dcmrt/libsrc/drtcos.cc create mode 100644 dcmrt/libsrc/drtcpas.cc create mode 100644 dcmrt/libsrc/drtcps.cc create mode 100644 dcmrt/libsrc/drtcs.cc create mode 100644 dcmrt/libsrc/drtcsas.cc create mode 100644 dcmrt/libsrc/drtcshs.cc create mode 100644 dcmrt/libsrc/drtcsis.cc create mode 100644 dcmrt/libsrc/drtcss.cc create mode 100644 dcmrt/libsrc/drtdcs.cc create mode 100644 dcmrt/libsrc/drtdimcs.cc create mode 100644 dcmrt/libsrc/drtdimrs.cc create mode 100644 dcmrt/libsrc/drtdirs.cc create mode 100644 dcmrt/libsrc/drtdose.cc create mode 100644 dcmrt/libsrc/drtdrs.cc create mode 100644 dcmrt/libsrc/drtds.cc create mode 100644 dcmrt/libsrc/drtdspcs.cc create mode 100644 dcmrt/libsrc/drtdss.cc create mode 100644 dcmrt/libsrc/drtdvhs.cc create mode 100644 dcmrt/libsrc/drtdvrrs.cc create mode 100644 dcmrt/libsrc/drteas.cc create mode 100644 dcmrt/libsrc/drtes.cc create mode 100644 dcmrt/libsrc/drtfds.cc create mode 100644 dcmrt/libsrc/drtfes.cc create mode 100644 dcmrt/libsrc/drtfgs.cc create mode 100644 dcmrt/libsrc/drtfgss.cc create mode 100644 dcmrt/libsrc/drtfms.cc create mode 100644 dcmrt/libsrc/drtfsss.cc create mode 100644 dcmrt/libsrc/drtgas.cc create mode 100644 dcmrt/libsrc/drthsdrs.cc create mode 100644 dcmrt/libsrc/drtiais.cc create mode 100644 dcmrt/libsrc/drtians.cc create mode 100644 dcmrt/libsrc/drtiblds.cc create mode 100644 dcmrt/libsrc/drtibls.cc create mode 100644 dcmrt/libsrc/drtibs.cc create mode 100644 dcmrt/libsrc/drticpds.cc create mode 100644 dcmrt/libsrc/drticps.cc create mode 100644 dcmrt/libsrc/drtics.cc create mode 100644 dcmrt/libsrc/drtiis.cc create mode 100644 dcmrt/libsrc/drtimage.cc create mode 100644 dcmrt/libsrc/drtionpl.cc create mode 100644 dcmrt/libsrc/drtiontr.cc create mode 100644 dcmrt/libsrc/drtipiqs.cc create mode 100644 dcmrt/libsrc/drtircs.cc create mode 100644 dcmrt/libsrc/drtiseis.cc create mode 100644 dcmrt/libsrc/drtitts.cc create mode 100644 dcmrt/libsrc/drtiwps.cc create mode 100644 dcmrt/libsrc/drtiws.cc create mode 100644 dcmrt/libsrc/drtlsds.cc create mode 100644 dcmrt/libsrc/drtlsds6.cc create mode 100644 dcmrt/libsrc/drtlsds7.cc create mode 100644 dcmrt/libsrc/drtmacds.cc create mode 100644 dcmrt/libsrc/drtmas.cc create mode 100644 dcmrt/libsrc/drtmdrs.cc create mode 100644 dcmrt/libsrc/drtmls.cc create mode 100644 dcmrt/libsrc/drtmps.cc create mode 100644 dcmrt/libsrc/drtmss.cc create mode 100644 dcmrt/libsrc/drtmucs.cc create mode 100644 dcmrt/libsrc/drtoas.cc create mode 100644 dcmrt/libsrc/drtois.cc create mode 100644 dcmrt/libsrc/drtopis.cc create mode 100644 dcmrt/libsrc/drtos.cc create mode 100644 dcmrt/libsrc/drtpbcs.cc create mode 100644 dcmrt/libsrc/drtpcs.cc create mode 100644 dcmrt/libsrc/drtpcxs.cc create mode 100644 dcmrt/libsrc/drtpfms.cc create mode 100644 dcmrt/libsrc/drtpics.cc create mode 100644 dcmrt/libsrc/drtplan.cc create mode 100644 dcmrt/libsrc/drtporcs.cc create mode 100644 dcmrt/libsrc/drtporis.cc create mode 100644 dcmrt/libsrc/drtppcs.cc create mode 100644 dcmrt/libsrc/drtprsis.cc create mode 100644 dcmrt/libsrc/drtpscs.cc create mode 100644 dcmrt/libsrc/drtpsics.cc create mode 100644 dcmrt/libsrc/drtpss.cc create mode 100644 dcmrt/libsrc/drtpsss.cc create mode 100644 dcmrt/libsrc/drtpvis.cc create mode 100644 dcmrt/libsrc/drtras.cc create mode 100644 dcmrt/libsrc/drtrbas2.cc create mode 100644 dcmrt/libsrc/drtrbas8.cc create mode 100644 dcmrt/libsrc/drtrbls.cc create mode 100644 dcmrt/libsrc/drtrbos1.cc create mode 100644 dcmrt/libsrc/drtrbos6.cc create mode 100644 dcmrt/libsrc/drtrbos7.cc create mode 100644 dcmrt/libsrc/drtrbs2.cc create mode 100644 dcmrt/libsrc/drtrbs4.cc create mode 100644 dcmrt/libsrc/drtrbs8.cc create mode 100644 dcmrt/libsrc/drtrcdrs.cc create mode 100644 dcmrt/libsrc/drtrcos.cc create mode 100644 dcmrt/libsrc/drtrcps.cc create mode 100644 dcmrt/libsrc/drtrcs.cc create mode 100644 dcmrt/libsrc/drtrdros.cc create mode 100644 dcmrt/libsrc/drtrdrs1.cc create mode 100644 dcmrt/libsrc/drtrdrs6.cc create mode 100644 dcmrt/libsrc/drtrdrs8.cc create mode 100644 dcmrt/libsrc/drtrds.cc create mode 100644 dcmrt/libsrc/drtrecs.cc create mode 100644 dcmrt/libsrc/drtrfgs.cc create mode 100644 dcmrt/libsrc/drtrfors.cc create mode 100644 dcmrt/libsrc/drtrics.cc create mode 100644 dcmrt/libsrc/drtrims.cc create mode 100644 dcmrt/libsrc/drtris.cc create mode 100644 dcmrt/libsrc/drtrlsds.cc create mode 100644 dcmrt/libsrc/drtrmdrs.cc create mode 100644 dcmrt/libsrc/drtrms.cc create mode 100644 dcmrt/libsrc/drtrmss6.cc create mode 100644 dcmrt/libsrc/drtrmss7.cc create mode 100644 dcmrt/libsrc/drtrpcs.cc create mode 100644 dcmrt/libsrc/drtrpis.cc create mode 100644 dcmrt/libsrc/drtrppcs.cc create mode 100644 dcmrt/libsrc/drtrpphs.cc create mode 100644 dcmrt/libsrc/drtrpps.cc create mode 100644 dcmrt/libsrc/drtrppss.cc create mode 100644 dcmrt/libsrc/drtrps.cc create mode 100644 dcmrt/libsrc/drtrris1.cc create mode 100644 dcmrt/libsrc/drtrris6.cc create mode 100644 dcmrt/libsrc/drtrris9.cc create mode 100644 dcmrt/libsrc/drtrrms.cc create mode 100644 dcmrt/libsrc/drtrros.cc create mode 100644 dcmrt/libsrc/drtrrpcs.cc create mode 100644 dcmrt/libsrc/drtrrros.cc create mode 100644 dcmrt/libsrc/drtrrs.cc create mode 100644 dcmrt/libsrc/drtrrshs.cc create mode 100644 dcmrt/libsrc/drtrrtps.cc create mode 100644 dcmrt/libsrc/drtrrtps3.cc create mode 100644 dcmrt/libsrc/drtrrtps4.cc create mode 100644 dcmrt/libsrc/drtrrtps5.cc create mode 100644 dcmrt/libsrc/drtrscs.cc create mode 100644 dcmrt/libsrc/drtrsers.cc create mode 100644 dcmrt/libsrc/drtrses.cc create mode 100644 dcmrt/libsrc/drtrshs.cc create mode 100644 dcmrt/libsrc/drtrshs6.cc create mode 100644 dcmrt/libsrc/drtrshs7.cc create mode 100644 dcmrt/libsrc/drtrsis.cc create mode 100644 dcmrt/libsrc/drtrsns.cc create mode 100644 dcmrt/libsrc/drtrsos.cc create mode 100644 dcmrt/libsrc/drtrsrs.cc create mode 100644 dcmrt/libsrc/drtrss.cc create mode 100644 dcmrt/libsrc/drtrsss.cc create mode 100644 dcmrt/libsrc/drtrsts.cc create mode 100644 dcmrt/libsrc/drtrtrs2.cc create mode 100644 dcmrt/libsrc/drtrtrs4.cc create mode 100644 dcmrt/libsrc/drtrvis.cc create mode 100644 dcmrt/libsrc/drtrws.cc create mode 100644 dcmrt/libsrc/drtrwvms.cc create mode 100644 dcmrt/libsrc/drtscris.cc create mode 100644 dcmrt/libsrc/drtsdcs.cc create mode 100644 dcmrt/libsrc/drtsds.cc create mode 100644 dcmrt/libsrc/drtshds.cc create mode 100644 dcmrt/libsrc/drtsis.cc create mode 100644 dcmrt/libsrc/drtsns.cc create mode 100644 dcmrt/libsrc/drtspccs.cc create mode 100644 dcmrt/libsrc/drtspcs.cc create mode 100644 dcmrt/libsrc/drtss.cc create mode 100644 dcmrt/libsrc/drtssrs.cc create mode 100644 dcmrt/libsrc/drtstrct.cc create mode 100644 dcmrt/libsrc/drttms0.cc create mode 100644 dcmrt/libsrc/drttms9.cc create mode 100644 dcmrt/libsrc/drttreat.cc create mode 100644 dcmrt/libsrc/drttscds.cc create mode 100644 dcmrt/libsrc/drttsibs.cc create mode 100644 dcmrt/libsrc/drttsmds.cc create mode 100644 dcmrt/libsrc/drttts.cc create mode 100644 dcmrt/libsrc/drttypes.cc create mode 100644 dcmrt/libsrc/drtvls.cc create mode 100644 dcmrt/libsrc/drtwps.cc create mode 100644 dcmrt/libsrc/drtwrs.cc create mode 100644 dcmrt/libsrc/drtws.cc create mode 100644 dcmrt/libsrc/drtxrs.cc create mode 100644 dcmrt/tests/CMakeLists.txt create mode 100644 dcmrt/tests/Makefile.dep create mode 100644 dcmrt/tests/Makefile.in create mode 100644 dcmrt/tests/drttest.cc create mode 100644 dcmrt/tests/tests.cc create mode 100644 dcmrt/tests/tsearch.cc create mode 100644 dcmseg/CMakeLists.txt create mode 100644 dcmseg/Makefile.in create mode 100755 dcmseg/configure create mode 100644 dcmseg/data/Makefile.in create mode 100644 dcmseg/docs/Makefile.in create mode 100644 dcmseg/docs/dcmseg.dox create mode 100644 dcmseg/etc/Makefile.in create mode 100644 dcmseg/include/CMakeLists.txt create mode 100644 dcmseg/include/Makefile.in create mode 100644 dcmseg/include/dcmtk/dcmseg/segdef.h create mode 100644 dcmseg/include/dcmtk/dcmseg/segdoc.h create mode 100644 dcmseg/include/dcmtk/dcmseg/segment.h create mode 100644 dcmseg/include/dcmtk/dcmseg/segtypes.h create mode 100644 dcmseg/include/dcmtk/dcmseg/segutils.h create mode 100644 dcmseg/libsrc/CMakeLists.txt create mode 100644 dcmseg/libsrc/Makefile.dep create mode 100644 dcmseg/libsrc/Makefile.in create mode 100644 dcmseg/libsrc/segdoc.cc create mode 100644 dcmseg/libsrc/segment.cc create mode 100644 dcmseg/libsrc/segtypes.cc create mode 100644 dcmseg/libsrc/segutils.cc create mode 100644 dcmseg/tests/Makefile.in create mode 100644 dcmsign/CMakeLists.txt create mode 100644 dcmsign/Makefile.in create mode 100644 dcmsign/apps/CMakeLists.txt create mode 100644 dcmsign/apps/Makefile.dep create mode 100644 dcmsign/apps/Makefile.in create mode 100644 dcmsign/apps/dcmsign.cc create mode 100755 dcmsign/configure create mode 100644 dcmsign/data/Makefile.in create mode 100644 dcmsign/docs/Makefile.in create mode 100644 dcmsign/docs/dcmsign.dox create mode 100644 dcmsign/docs/dcmsign.man create mode 100644 dcmsign/etc/Makefile.in create mode 100644 dcmsign/include/CMakeLists.txt create mode 100644 dcmsign/include/Makefile.in create mode 100644 dcmsign/include/dcmtk/dcmsign/dcsignat.h create mode 100644 dcmsign/include/dcmtk/dcmsign/sialgo.h create mode 100644 dcmsign/include/dcmtk/dcmsign/siautopr.h create mode 100644 dcmsign/include/dcmtk/dcmsign/sibrsapr.h create mode 100644 dcmsign/include/dcmtk/dcmsign/sicert.h create mode 100644 dcmsign/include/dcmtk/dcmsign/sicertvf.h create mode 100644 dcmsign/include/dcmtk/dcmsign/sicreapr.h create mode 100644 dcmsign/include/dcmtk/dcmsign/sidefine.h create mode 100644 dcmsign/include/dcmtk/dcmsign/sidsa.h create mode 100644 dcmsign/include/dcmtk/dcmsign/simac.h create mode 100644 dcmsign/include/dcmtk/dcmsign/simaccon.h create mode 100644 dcmsign/include/dcmtk/dcmsign/simd5.h create mode 100644 dcmsign/include/dcmtk/dcmsign/sinullpr.h create mode 100644 dcmsign/include/dcmtk/dcmsign/siprivat.h create mode 100644 dcmsign/include/dcmtk/dcmsign/siripemd.h create mode 100644 dcmsign/include/dcmtk/dcmsign/sirsa.h create mode 100644 dcmsign/include/dcmtk/dcmsign/sisha1.h create mode 100644 dcmsign/include/dcmtk/dcmsign/sisprof.h create mode 100644 dcmsign/include/dcmtk/dcmsign/sitstamp.h create mode 100644 dcmsign/include/dcmtk/dcmsign/sitypes.h create mode 100644 dcmsign/libsrc/CMakeLists.txt create mode 100644 dcmsign/libsrc/Makefile.dep create mode 100644 dcmsign/libsrc/Makefile.in create mode 100644 dcmsign/libsrc/dcsignat.cc create mode 100644 dcmsign/libsrc/siautopr.cc create mode 100644 dcmsign/libsrc/sibrsapr.cc create mode 100644 dcmsign/libsrc/sicert.cc create mode 100644 dcmsign/libsrc/sicertvf.cc create mode 100644 dcmsign/libsrc/sicreapr.cc create mode 100644 dcmsign/libsrc/sidsa.cc create mode 100644 dcmsign/libsrc/simaccon.cc create mode 100644 dcmsign/libsrc/simd5.cc create mode 100644 dcmsign/libsrc/sinullpr.cc create mode 100644 dcmsign/libsrc/siprivat.cc create mode 100644 dcmsign/libsrc/siripemd.cc create mode 100644 dcmsign/libsrc/sirsa.cc create mode 100644 dcmsign/libsrc/sisha1.cc create mode 100644 dcmsign/libsrc/sisprof.cc create mode 100644 dcmsign/libsrc/sitypes.cc create mode 100644 dcmsign/tests/Makefile.in create mode 100644 dcmsr/CMakeLists.txt create mode 100644 dcmsr/Makefile.in create mode 100644 dcmsr/apps/CMakeLists.txt create mode 100644 dcmsr/apps/Makefile.dep create mode 100644 dcmsr/apps/Makefile.in create mode 100644 dcmsr/apps/dsr2html.cc create mode 100644 dcmsr/apps/dsr2xml.cc create mode 100644 dcmsr/apps/dsrdump.cc create mode 100644 dcmsr/apps/xml2dsr.cc create mode 100755 dcmsr/configure create mode 100644 dcmsr/data/CMakeLists.txt create mode 100644 dcmsr/data/Makefile.in create mode 100644 dcmsr/data/dsr2xml.xsd create mode 100644 dcmsr/data/report.css create mode 100644 dcmsr/data/reportx.css create mode 100644 dcmsr/docs/Makefile.in create mode 100644 dcmsr/docs/dcmsr.dox create mode 100644 dcmsr/docs/dsr2html.man create mode 100644 dcmsr/docs/dsr2xml.man create mode 100644 dcmsr/docs/dsrdump.man create mode 100644 dcmsr/docs/xml2dsr.man create mode 100644 dcmsr/etc/Makefile.in create mode 100644 dcmsr/include/CMakeLists.txt create mode 100644 dcmsr/include/Makefile.in create mode 100644 dcmsr/include/dcmtk/dcmsr/cmr/cid100.h create mode 100644 dcmsr/include/dcmtk/dcmsr/cmr/cid10013.h create mode 100644 dcmsr/include/dcmtk/dcmsr/cmr/cid10013e.h create mode 100644 dcmsr/include/dcmtk/dcmsr/cmr/cid10033.h create mode 100644 dcmsr/include/dcmtk/dcmsr/cmr/cid10033e.h create mode 100644 dcmsr/include/dcmtk/dcmsr/cmr/cid11.h create mode 100644 dcmsr/include/dcmtk/dcmsr/cmr/cid244.h create mode 100644 dcmsr/include/dcmtk/dcmsr/cmr/cid244e.h create mode 100644 dcmsr/include/dcmtk/dcmsr/cmr/cid29.h create mode 100644 dcmsr/include/dcmtk/dcmsr/cmr/cid29e.h create mode 100644 dcmsr/include/dcmtk/dcmsr/cmr/cid4020.h create mode 100644 dcmsr/include/dcmtk/dcmsr/cmr/cid4021.h create mode 100644 dcmsr/include/dcmtk/dcmsr/cmr/cid4031.h create mode 100644 dcmsr/include/dcmtk/dcmsr/cmr/cid4031e.h create mode 100644 dcmsr/include/dcmtk/dcmsr/cmr/cid42.h create mode 100644 dcmsr/include/dcmtk/dcmsr/cmr/cid5000.h create mode 100644 dcmsr/include/dcmtk/dcmsr/cmr/cid5001.h create mode 100644 dcmsr/include/dcmtk/dcmsr/cmr/cid7021.h create mode 100644 dcmsr/include/dcmtk/dcmsr/cmr/cid7445.h create mode 100644 dcmsr/include/dcmtk/dcmsr/cmr/cid7452.h create mode 100644 dcmsr/include/dcmtk/dcmsr/cmr/cid7453.h create mode 100644 dcmsr/include/dcmtk/dcmsr/cmr/define.h create mode 100644 dcmsr/include/dcmtk/dcmsr/cmr/init.h create mode 100644 dcmsr/include/dcmtk/dcmsr/cmr/logger.h create mode 100644 dcmsr/include/dcmtk/dcmsr/cmr/srnumvl.h create mode 100644 dcmsr/include/dcmtk/dcmsr/cmr/tid1001.h create mode 100644 dcmsr/include/dcmtk/dcmsr/cmr/tid1204.h create mode 100644 dcmsr/include/dcmtk/dcmsr/cmr/tid1600.h create mode 100644 dcmsr/include/dcmtk/dcmsr/codes/dcm.h create mode 100644 dcmsr/include/dcmtk/dcmsr/codes/srt.h create mode 100644 dcmsr/include/dcmtk/dcmsr/codes/ucum.h create mode 100644 dcmsr/include/dcmtk/dcmsr/dsdefine.h create mode 100644 dcmsr/include/dcmtk/dcmsr/dsrbascc.h create mode 100644 dcmsr/include/dcmtk/dcmsr/dsrc3dcc.h create mode 100644 dcmsr/include/dcmtk/dcmsr/dsrchecc.h create mode 100644 dcmsr/include/dcmtk/dcmsr/dsrcitem.h create mode 100644 dcmsr/include/dcmtk/dcmsr/dsrcodtn.h create mode 100644 dcmsr/include/dcmtk/dcmsr/dsrcodvl.h create mode 100644 dcmsr/include/dcmtk/dcmsr/dsrcolcc.h create mode 100644 dcmsr/include/dcmtk/dcmsr/dsrcomcc.h create mode 100644 dcmsr/include/dcmtk/dcmsr/dsrcomtn.h create mode 100644 dcmsr/include/dcmtk/dcmsr/dsrcomvl.h create mode 100644 dcmsr/include/dcmtk/dcmsr/dsrcontn.h create mode 100644 dcmsr/include/dcmtk/dcmsr/dsrcsidl.h create mode 100644 dcmsr/include/dcmtk/dcmsr/dsrctpl.h create mode 100644 dcmsr/include/dcmtk/dcmsr/dsrctxgr.h create mode 100644 dcmsr/include/dcmtk/dcmsr/dsrdattn.h create mode 100644 dcmsr/include/dcmtk/dcmsr/dsrdoc.h create mode 100644 dcmsr/include/dcmtk/dcmsr/dsrdocst.h create mode 100644 dcmsr/include/dcmtk/dcmsr/dsrdoctn.h create mode 100644 dcmsr/include/dcmtk/dcmsr/dsrdoctr.h create mode 100644 dcmsr/include/dcmtk/dcmsr/dsrdtitn.h create mode 100644 dcmsr/include/dcmtk/dcmsr/dsrenhcc.h create mode 100644 dcmsr/include/dcmtk/dcmsr/dsrimgfr.h create mode 100644 dcmsr/include/dcmtk/dcmsr/dsrimgse.h create mode 100644 dcmsr/include/dcmtk/dcmsr/dsrimgtn.h create mode 100644 dcmsr/include/dcmtk/dcmsr/dsrimgvl.h create mode 100644 dcmsr/include/dcmtk/dcmsr/dsrimpcc.h create mode 100644 dcmsr/include/dcmtk/dcmsr/dsriodcc.h create mode 100644 dcmsr/include/dcmtk/dcmsr/dsrkeycc.h create mode 100644 dcmsr/include/dcmtk/dcmsr/dsrmaccc.h create mode 100644 dcmsr/include/dcmtk/dcmsr/dsrmamcc.h create mode 100644 dcmsr/include/dcmtk/dcmsr/dsrnumtn.h create mode 100644 dcmsr/include/dcmtk/dcmsr/dsrnumvl.h create mode 100644 dcmsr/include/dcmtk/dcmsr/dsrpnmtn.h create mode 100644 dcmsr/include/dcmtk/dcmsr/dsrprocc.h create mode 100644 dcmsr/include/dcmtk/dcmsr/dsrrefin.h create mode 100644 dcmsr/include/dcmtk/dcmsr/dsrreftn.h create mode 100644 dcmsr/include/dcmtk/dcmsr/dsrrrdcc.h create mode 100644 dcmsr/include/dcmtk/dcmsr/dsrrtpl.h create mode 100644 dcmsr/include/dcmtk/dcmsr/dsrsc3gr.h create mode 100644 dcmsr/include/dcmtk/dcmsr/dsrsc3tn.h create mode 100644 dcmsr/include/dcmtk/dcmsr/dsrsc3vl.h create mode 100644 dcmsr/include/dcmtk/dcmsr/dsrscogr.h create mode 100644 dcmsr/include/dcmtk/dcmsr/dsrscotn.h create mode 100644 dcmsr/include/dcmtk/dcmsr/dsrscovl.h create mode 100644 dcmsr/include/dcmtk/dcmsr/dsrsoprf.h create mode 100644 dcmsr/include/dcmtk/dcmsr/dsrspecc.h create mode 100644 dcmsr/include/dcmtk/dcmsr/dsrstpl.h create mode 100644 dcmsr/include/dcmtk/dcmsr/dsrstrvl.h create mode 100644 dcmsr/include/dcmtk/dcmsr/dsrtcodt.h create mode 100644 dcmsr/include/dcmtk/dcmsr/dsrtcosp.h create mode 100644 dcmsr/include/dcmtk/dcmsr/dsrtcotn.h create mode 100644 dcmsr/include/dcmtk/dcmsr/dsrtcoto.h create mode 100644 dcmsr/include/dcmtk/dcmsr/dsrtcovl.h create mode 100644 dcmsr/include/dcmtk/dcmsr/dsrtextn.h create mode 100644 dcmsr/include/dcmtk/dcmsr/dsrtimtn.h create mode 100644 dcmsr/include/dcmtk/dcmsr/dsrtlist.h create mode 100644 dcmsr/include/dcmtk/dcmsr/dsrtnant.h create mode 100644 dcmsr/include/dcmtk/dcmsr/dsrtncsr.h create mode 100644 dcmsr/include/dcmtk/dcmsr/dsrtree.h create mode 100644 dcmsr/include/dcmtk/dcmsr/dsrtypes.h create mode 100644 dcmsr/include/dcmtk/dcmsr/dsruidtn.h create mode 100644 dcmsr/include/dcmtk/dcmsr/dsrwavch.h create mode 100644 dcmsr/include/dcmtk/dcmsr/dsrwavtn.h create mode 100644 dcmsr/include/dcmtk/dcmsr/dsrwavvl.h create mode 100644 dcmsr/include/dcmtk/dcmsr/dsrxmlc.h create mode 100644 dcmsr/include/dcmtk/dcmsr/dsrxmld.h create mode 100644 dcmsr/include/dcmtk/dcmsr/dsrxrdcc.h create mode 100644 dcmsr/libcmr/CMakeLists.txt create mode 100644 dcmsr/libcmr/Makefile.dep create mode 100644 dcmsr/libcmr/Makefile.in create mode 100644 dcmsr/libcmr/cid100.cc create mode 100644 dcmsr/libcmr/cid10013.cc create mode 100644 dcmsr/libcmr/cid10013e.cc create mode 100644 dcmsr/libcmr/cid10033.cc create mode 100644 dcmsr/libcmr/cid10033e.cc create mode 100644 dcmsr/libcmr/cid11.cc create mode 100644 dcmsr/libcmr/cid244.cc create mode 100644 dcmsr/libcmr/cid244e.cc create mode 100644 dcmsr/libcmr/cid29.cc create mode 100644 dcmsr/libcmr/cid29e.cc create mode 100644 dcmsr/libcmr/cid4020.cc create mode 100644 dcmsr/libcmr/cid4021.cc create mode 100644 dcmsr/libcmr/cid4031.cc create mode 100644 dcmsr/libcmr/cid4031e.cc create mode 100644 dcmsr/libcmr/cid42.cc create mode 100644 dcmsr/libcmr/cid5000.cc create mode 100644 dcmsr/libcmr/cid5001.cc create mode 100644 dcmsr/libcmr/cid7021.cc create mode 100644 dcmsr/libcmr/cid7445.cc create mode 100644 dcmsr/libcmr/cid7452.cc create mode 100644 dcmsr/libcmr/cid7453.cc create mode 100644 dcmsr/libcmr/init.cc create mode 100644 dcmsr/libcmr/logger.cc create mode 100644 dcmsr/libcmr/srnumvl.cc create mode 100644 dcmsr/libcmr/tid1001.cc create mode 100644 dcmsr/libcmr/tid1204.cc create mode 100644 dcmsr/libcmr/tid1600.cc create mode 100644 dcmsr/libsrc/CMakeLists.txt create mode 100644 dcmsr/libsrc/Makefile.dep create mode 100644 dcmsr/libsrc/Makefile.in create mode 100644 dcmsr/libsrc/dsrbascc.cc create mode 100644 dcmsr/libsrc/dsrc3dcc.cc create mode 100644 dcmsr/libsrc/dsrchecc.cc create mode 100644 dcmsr/libsrc/dsrcitem.cc create mode 100644 dcmsr/libsrc/dsrcodtn.cc create mode 100644 dcmsr/libsrc/dsrcodvl.cc create mode 100644 dcmsr/libsrc/dsrcolcc.cc create mode 100644 dcmsr/libsrc/dsrcomcc.cc create mode 100644 dcmsr/libsrc/dsrcomtn.cc create mode 100644 dcmsr/libsrc/dsrcomvl.cc create mode 100644 dcmsr/libsrc/dsrcontn.cc create mode 100644 dcmsr/libsrc/dsrcsidl.cc create mode 100644 dcmsr/libsrc/dsrctpl.cc create mode 100644 dcmsr/libsrc/dsrctxgr.cc create mode 100644 dcmsr/libsrc/dsrdattn.cc create mode 100644 dcmsr/libsrc/dsrdoc.cc create mode 100644 dcmsr/libsrc/dsrdocst.cc create mode 100644 dcmsr/libsrc/dsrdoctn.cc create mode 100644 dcmsr/libsrc/dsrdoctr.cc create mode 100644 dcmsr/libsrc/dsrdtitn.cc create mode 100644 dcmsr/libsrc/dsrenhcc.cc create mode 100644 dcmsr/libsrc/dsrimgfr.cc create mode 100644 dcmsr/libsrc/dsrimgse.cc create mode 100644 dcmsr/libsrc/dsrimgtn.cc create mode 100644 dcmsr/libsrc/dsrimgvl.cc create mode 100644 dcmsr/libsrc/dsrimpcc.cc create mode 100644 dcmsr/libsrc/dsriodcc.cc create mode 100644 dcmsr/libsrc/dsrkeycc.cc create mode 100644 dcmsr/libsrc/dsrmaccc.cc create mode 100644 dcmsr/libsrc/dsrmamcc.cc create mode 100644 dcmsr/libsrc/dsrnumtn.cc create mode 100644 dcmsr/libsrc/dsrnumvl.cc create mode 100644 dcmsr/libsrc/dsrpnmtn.cc create mode 100644 dcmsr/libsrc/dsrprocc.cc create mode 100644 dcmsr/libsrc/dsrrefin.cc create mode 100644 dcmsr/libsrc/dsrreftn.cc create mode 100644 dcmsr/libsrc/dsrrrdcc.cc create mode 100644 dcmsr/libsrc/dsrrtpl.cc create mode 100644 dcmsr/libsrc/dsrsc3gr.cc create mode 100644 dcmsr/libsrc/dsrsc3tn.cc create mode 100644 dcmsr/libsrc/dsrsc3vl.cc create mode 100644 dcmsr/libsrc/dsrscogr.cc create mode 100644 dcmsr/libsrc/dsrscotn.cc create mode 100644 dcmsr/libsrc/dsrscovl.cc create mode 100644 dcmsr/libsrc/dsrsoprf.cc create mode 100644 dcmsr/libsrc/dsrspecc.cc create mode 100644 dcmsr/libsrc/dsrstpl.cc create mode 100644 dcmsr/libsrc/dsrstrvl.cc create mode 100644 dcmsr/libsrc/dsrtcodt.cc create mode 100644 dcmsr/libsrc/dsrtcosp.cc create mode 100644 dcmsr/libsrc/dsrtcotn.cc create mode 100644 dcmsr/libsrc/dsrtcoto.cc create mode 100644 dcmsr/libsrc/dsrtcovl.cc create mode 100644 dcmsr/libsrc/dsrtextn.cc create mode 100644 dcmsr/libsrc/dsrtimtn.cc create mode 100644 dcmsr/libsrc/dsrtncsr.cc create mode 100644 dcmsr/libsrc/dsrtree.cc create mode 100644 dcmsr/libsrc/dsrtypes.cc create mode 100644 dcmsr/libsrc/dsruidtn.cc create mode 100644 dcmsr/libsrc/dsrwavch.cc create mode 100644 dcmsr/libsrc/dsrwavtn.cc create mode 100644 dcmsr/libsrc/dsrwavvl.cc create mode 100644 dcmsr/libsrc/dsrxmlc.cc create mode 100644 dcmsr/libsrc/dsrxmld.cc create mode 100644 dcmsr/libsrc/dsrxrdcc.cc create mode 100644 dcmsr/tests/CMakeLists.txt create mode 100644 dcmsr/tests/Makefile.dep create mode 100644 dcmsr/tests/Makefile.in create mode 100644 dcmsr/tests/gmon.out create mode 100644 dcmsr/tests/mkreport.cc create mode 100644 dcmsr/tests/tests.cc create mode 100644 dcmsr/tests/tsrcmr.cc create mode 100644 dcmsr/tests/tsrcodvl.cc create mode 100644 dcmsr/tests/tsrdoc.cc create mode 100644 dcmsr/tests/tsrdoctr.cc create mode 100644 dcmsr/tests/tsrnumvl.cc create mode 100644 dcmsr/tests/tsrtpl.cc create mode 100644 dcmsr/tests/tsrtree.cc create mode 100644 dcmtls/CMakeLists.txt create mode 100644 dcmtls/Makefile.in create mode 100644 dcmtls/apps/Makefile.dep create mode 100644 dcmtls/apps/Makefile.in create mode 100755 dcmtls/configure create mode 100644 dcmtls/data/Makefile.in create mode 100644 dcmtls/docs/CMakeLists.txt create mode 100644 dcmtls/docs/Makefile.in create mode 100644 dcmtls/docs/ciphers.txt create mode 100644 dcmtls/docs/dcmtls.dox create mode 100644 dcmtls/docs/randseed.txt create mode 100644 dcmtls/etc/Makefile.in create mode 100644 dcmtls/include/CMakeLists.txt create mode 100644 dcmtls/include/Makefile.in create mode 100644 dcmtls/include/dcmtk/dcmtls/tlsdefin.h create mode 100644 dcmtls/include/dcmtk/dcmtls/tlslayer.h create mode 100644 dcmtls/include/dcmtk/dcmtls/tlsscu.h create mode 100644 dcmtls/include/dcmtk/dcmtls/tlstrans.h create mode 100644 dcmtls/libsrc/CMakeLists.txt create mode 100644 dcmtls/libsrc/Makefile.dep create mode 100644 dcmtls/libsrc/Makefile.in create mode 100644 dcmtls/libsrc/tlslayer.cc create mode 100644 dcmtls/libsrc/tlsscu.cc create mode 100644 dcmtls/libsrc/tlstrans.cc create mode 100644 dcmtls/tests/Makefile.in create mode 100755 dcmtls/tests/dcmtk_ca.pl create mode 100644 dcmwlm/CMakeLists.txt create mode 100644 dcmwlm/Makefile.in create mode 100644 dcmwlm/apps/CMakeLists.txt create mode 100644 dcmwlm/apps/Makefile.dep create mode 100644 dcmwlm/apps/Makefile.in create mode 100644 dcmwlm/apps/wlcefs.cc create mode 100644 dcmwlm/apps/wlcefs.h create mode 100644 dcmwlm/apps/wlmscpfs.cc create mode 100755 dcmwlm/configure create mode 100644 dcmwlm/data/CMakeLists.txt create mode 100644 dcmwlm/data/Makefile.in create mode 100644 dcmwlm/data/wlistdb/OFFIS/lockfile create mode 100644 dcmwlm/data/wlistdb/OFFIS/wklist1.dump create mode 100644 dcmwlm/data/wlistdb/OFFIS/wklist10.dump create mode 100644 dcmwlm/data/wlistdb/OFFIS/wklist2.dump create mode 100644 dcmwlm/data/wlistdb/OFFIS/wklist3.dump create mode 100644 dcmwlm/data/wlistdb/OFFIS/wklist4.dump create mode 100644 dcmwlm/data/wlistdb/OFFIS/wklist5.dump create mode 100644 dcmwlm/data/wlistdb/OFFIS/wklist6.dump create mode 100644 dcmwlm/data/wlistdb/OFFIS/wklist7.dump create mode 100644 dcmwlm/data/wlistdb/OFFIS/wklist8.dump create mode 100644 dcmwlm/data/wlistdb/OFFIS/wklist9.dump create mode 100644 dcmwlm/data/wlistdb/README create mode 100644 dcmwlm/data/wlistqry/README create mode 100644 dcmwlm/data/wlistqry/wlistqry0.dump create mode 100644 dcmwlm/data/wlistqry/wlistqry1.dump create mode 100644 dcmwlm/data/wlistqry/wlistqry10.dump create mode 100644 dcmwlm/data/wlistqry/wlistqry11.dump create mode 100644 dcmwlm/data/wlistqry/wlistqry12.dump create mode 100644 dcmwlm/data/wlistqry/wlistqry2.dump create mode 100644 dcmwlm/data/wlistqry/wlistqry3.dump create mode 100644 dcmwlm/data/wlistqry/wlistqry4.dump create mode 100644 dcmwlm/data/wlistqry/wlistqry5.dump create mode 100644 dcmwlm/data/wlistqry/wlistqry6.dump create mode 100644 dcmwlm/data/wlistqry/wlistqry7.dump create mode 100644 dcmwlm/data/wlistqry/wlistqry8.dump create mode 100644 dcmwlm/data/wlistqry/wlistqry9.dump create mode 100644 dcmwlm/docs/Makefile.in create mode 100644 dcmwlm/docs/dcmwlm.dox create mode 100644 dcmwlm/docs/wlmscpfs.man create mode 100644 dcmwlm/etc/Makefile.in create mode 100644 dcmwlm/include/CMakeLists.txt create mode 100644 dcmwlm/include/Makefile.in create mode 100644 dcmwlm/include/dcmtk/dcmwlm/wldefine.h create mode 100644 dcmwlm/include/dcmtk/dcmwlm/wlds.h create mode 100644 dcmwlm/include/dcmtk/dcmwlm/wldsfs.h create mode 100644 dcmwlm/include/dcmtk/dcmwlm/wlfsim.h create mode 100644 dcmwlm/include/dcmtk/dcmwlm/wlmactmg.h create mode 100644 dcmwlm/include/dcmtk/dcmwlm/wltypdef.h create mode 100644 dcmwlm/libsrc/CMakeLists.txt create mode 100644 dcmwlm/libsrc/Makefile.dep create mode 100644 dcmwlm/libsrc/Makefile.in create mode 100644 dcmwlm/libsrc/wlds.cc create mode 100644 dcmwlm/libsrc/wldsfs.cc create mode 100644 dcmwlm/libsrc/wlfsim.cc create mode 100644 dcmwlm/libsrc/wlmactmg.cc create mode 100644 dcmwlm/tests/Makefile.dep create mode 100644 dcmwlm/tests/Makefile.in create mode 100644 dcmwlm/tests/wltest.cc create mode 100644 docs/ANNOUNCE.310 create mode 100644 docs/ANNOUNCE.311 create mode 100644 docs/ANNOUNCE.312 create mode 100644 docs/ANNOUNCE.320 create mode 100644 docs/ANNOUNCE.321 create mode 100644 docs/ANNOUNCE.330 create mode 100644 docs/ANNOUNCE.331 create mode 100644 docs/ANNOUNCE.340 create mode 100644 docs/ANNOUNCE.341 create mode 100644 docs/ANNOUNCE.342 create mode 100644 docs/ANNOUNCE.350 create mode 100644 docs/ANNOUNCE.351 create mode 100644 docs/ANNOUNCE.352 create mode 100644 docs/ANNOUNCE.353 create mode 100644 docs/ANNOUNCE.354 create mode 100644 docs/ANNOUNCE.360 create mode 100644 docs/CHANGES.301 create mode 100644 docs/CHANGES.302 create mode 100644 docs/CHANGES.310 create mode 100644 docs/CHANGES.311 create mode 100644 docs/CHANGES.312 create mode 100644 docs/CHANGES.320 create mode 100644 docs/CHANGES.321 create mode 100644 docs/CHANGES.330 create mode 100644 docs/CHANGES.331 create mode 100644 docs/CHANGES.340 create mode 100644 docs/CHANGES.341 create mode 100644 docs/CHANGES.342 create mode 100644 docs/CHANGES.350 create mode 100644 docs/CHANGES.351 create mode 100644 docs/CHANGES.352 create mode 100644 docs/CHANGES.353 create mode 100644 docs/CHANGES.354 create mode 100644 docs/CHANGES.360 create mode 100644 docs/CHANGES.361 create mode 100644 docs/DCMIMAGE.11X create mode 100644 doxygen/CMakeLists.txt create mode 100644 doxygen/Makefile.in create mode 100755 doxygen/configure create mode 100644 doxygen/footer.html create mode 100644 doxygen/htmldocs.cfg create mode 100644 doxygen/htmldocs.dox create mode 100644 doxygen/layout.xml create mode 100755 doxygen/man2text.sh create mode 100644 doxygen/manpages.cfg create mode 100644 doxygen/manpages/man1/dcm2pdf.1 create mode 100644 doxygen/manpages/man1/dcm2pnm.1 create mode 100644 doxygen/manpages/man1/dcm2xml.1 create mode 100644 doxygen/manpages/man1/dcmcjpeg.1 create mode 100644 doxygen/manpages/man1/dcmcjpls.1 create mode 100644 doxygen/manpages/man1/dcmconv.1 create mode 100644 doxygen/manpages/man1/dcmcrle.1 create mode 100644 doxygen/manpages/man1/dcmdjpeg.1 create mode 100644 doxygen/manpages/man1/dcmdjpls.1 create mode 100644 doxygen/manpages/man1/dcmdrle.1 create mode 100644 doxygen/manpages/man1/dcmdspfn.1 create mode 100644 doxygen/manpages/man1/dcmdump.1 create mode 100644 doxygen/manpages/man1/dcmftest.1 create mode 100644 doxygen/manpages/man1/dcmgpdir.1 create mode 100644 doxygen/manpages/man1/dcmj2pnm.1 create mode 100644 doxygen/manpages/man1/dcml2pnm.1 create mode 100644 doxygen/manpages/man1/dcmmkcrv.1 create mode 100644 doxygen/manpages/man1/dcmmkdir.1 create mode 100644 doxygen/manpages/man1/dcmmklut.1 create mode 100644 doxygen/manpages/man1/dcmodify.1 create mode 100644 doxygen/manpages/man1/dcmp2pgm.1 create mode 100644 doxygen/manpages/man1/dcmprscp.1 create mode 100644 doxygen/manpages/man1/dcmprscu.1 create mode 100644 doxygen/manpages/man1/dcmpschk.1 create mode 100644 doxygen/manpages/man1/dcmpsmk.1 create mode 100644 doxygen/manpages/man1/dcmpsprt.1 create mode 100644 doxygen/manpages/man1/dcmpsrcv.1 create mode 100644 doxygen/manpages/man1/dcmpssnd.1 create mode 100644 doxygen/manpages/man1/dcmqridx.1 create mode 100644 doxygen/manpages/man1/dcmqrscp.1 create mode 100644 doxygen/manpages/man1/dcmqrti.1 create mode 100644 doxygen/manpages/man1/dcmquant.1 create mode 100644 doxygen/manpages/man1/dcmrecv.1 create mode 100644 doxygen/manpages/man1/dcmscale.1 create mode 100644 doxygen/manpages/man1/dcmsend.1 create mode 100644 doxygen/manpages/man1/dcmsign.1 create mode 100644 doxygen/manpages/man1/dcod2lum.1 create mode 100644 doxygen/manpages/man1/dconvlum.1 create mode 100644 doxygen/manpages/man1/drtdump.1 create mode 100644 doxygen/manpages/man1/dsr2html.1 create mode 100644 doxygen/manpages/man1/dsr2xml.1 create mode 100644 doxygen/manpages/man1/dsrdump.1 create mode 100644 doxygen/manpages/man1/dump2dcm.1 create mode 100644 doxygen/manpages/man1/echoscu.1 create mode 100644 doxygen/manpages/man1/findscu.1 create mode 100644 doxygen/manpages/man1/getscu.1 create mode 100644 doxygen/manpages/man1/img2dcm.1 create mode 100644 doxygen/manpages/man1/movescu.1 create mode 100644 doxygen/manpages/man1/pdf2dcm.1 create mode 100644 doxygen/manpages/man1/storescp.1 create mode 100644 doxygen/manpages/man1/storescu.1 create mode 100644 doxygen/manpages/man1/termscu.1 create mode 100644 doxygen/manpages/man1/wlmscpfs.1 create mode 100644 doxygen/manpages/man1/xml2dcm.1 create mode 100644 doxygen/manpages/man1/xml2dsr.1 create mode 100755 doxygen/patchman.sh create mode 100644 oflog/CMakeLists.txt create mode 100644 oflog/Makefile.in create mode 100755 oflog/configure create mode 100644 oflog/data/Makefile.in create mode 100644 oflog/docs/LICENSE create mode 100644 oflog/docs/Makefile.in create mode 100644 oflog/docs/oflog.dox create mode 100644 oflog/etc/CMakeLists.txt create mode 100644 oflog/etc/Makefile.in create mode 100644 oflog/etc/filelog.cfg create mode 100644 oflog/etc/logger.cfg create mode 100644 oflog/include/CMakeLists.txt create mode 100644 oflog/include/Makefile.in create mode 100644 oflog/include/dcmtk/oflog/appender.h create mode 100644 oflog/include/dcmtk/oflog/asyncap.h create mode 100644 oflog/include/dcmtk/oflog/clfsap.h create mode 100644 oflog/include/dcmtk/oflog/clogger.h create mode 100644 oflog/include/dcmtk/oflog/config.h create mode 100644 oflog/include/dcmtk/oflog/config/defines.h create mode 100644 oflog/include/dcmtk/oflog/config/macosx.h create mode 100644 oflog/include/dcmtk/oflog/config/win32.h create mode 100644 oflog/include/dcmtk/oflog/config/windowsh.h create mode 100644 oflog/include/dcmtk/oflog/configrt.h create mode 100644 oflog/include/dcmtk/oflog/consap.h create mode 100644 oflog/include/dcmtk/oflog/fileap.h create mode 100644 oflog/include/dcmtk/oflog/fstreams.h create mode 100644 oflog/include/dcmtk/oflog/helpers/apndimpl.h create mode 100644 oflog/include/dcmtk/oflog/helpers/fileinfo.h create mode 100644 oflog/include/dcmtk/oflog/helpers/lloguser.h create mode 100644 oflog/include/dcmtk/oflog/helpers/lockfile.h create mode 100644 oflog/include/dcmtk/oflog/helpers/loglog.h create mode 100644 oflog/include/dcmtk/oflog/helpers/pointer.h create mode 100644 oflog/include/dcmtk/oflog/helpers/property.h create mode 100644 oflog/include/dcmtk/oflog/helpers/queue.h create mode 100644 oflog/include/dcmtk/oflog/helpers/sleep.h create mode 100644 oflog/include/dcmtk/oflog/helpers/snprintf.h create mode 100644 oflog/include/dcmtk/oflog/helpers/sockbuff.h create mode 100644 oflog/include/dcmtk/oflog/helpers/socket.h create mode 100644 oflog/include/dcmtk/oflog/helpers/strhelp.h create mode 100644 oflog/include/dcmtk/oflog/helpers/threadcf.h create mode 100644 oflog/include/dcmtk/oflog/helpers/timehelp.h create mode 100644 oflog/include/dcmtk/oflog/hierarchy.h create mode 100644 oflog/include/dcmtk/oflog/hierlock.h create mode 100644 oflog/include/dcmtk/oflog/internal/cygwin32.h create mode 100644 oflog/include/dcmtk/oflog/internal/env.h create mode 100644 oflog/include/dcmtk/oflog/internal/internal.h create mode 100644 oflog/include/dcmtk/oflog/internal/socket.h create mode 100644 oflog/include/dcmtk/oflog/layout.h create mode 100644 oflog/include/dcmtk/oflog/log4judp.h create mode 100644 oflog/include/dcmtk/oflog/logger.h create mode 100644 oflog/include/dcmtk/oflog/loglevel.h create mode 100644 oflog/include/dcmtk/oflog/logmacro.h create mode 100644 oflog/include/dcmtk/oflog/mdc.h create mode 100644 oflog/include/dcmtk/oflog/ndc.h create mode 100644 oflog/include/dcmtk/oflog/ntelogap.h create mode 100644 oflog/include/dcmtk/oflog/nullap.h create mode 100644 oflog/include/dcmtk/oflog/oflog.h create mode 100644 oflog/include/dcmtk/oflog/socketap.h create mode 100644 oflog/include/dcmtk/oflog/spi/apndatch.h create mode 100644 oflog/include/dcmtk/oflog/spi/factory.h create mode 100644 oflog/include/dcmtk/oflog/spi/filter.h create mode 100644 oflog/include/dcmtk/oflog/spi/logevent.h create mode 100644 oflog/include/dcmtk/oflog/spi/logfact.h create mode 100644 oflog/include/dcmtk/oflog/spi/logimpl.h create mode 100644 oflog/include/dcmtk/oflog/spi/objreg.h create mode 100644 oflog/include/dcmtk/oflog/spi/rootlog.h create mode 100644 oflog/include/dcmtk/oflog/streams.h create mode 100644 oflog/include/dcmtk/oflog/syslogap.h create mode 100644 oflog/include/dcmtk/oflog/tchar.h create mode 100644 oflog/include/dcmtk/oflog/thread/impl/syncimpl.h create mode 100644 oflog/include/dcmtk/oflog/thread/impl/syncpmsm.h create mode 100644 oflog/include/dcmtk/oflog/thread/impl/syncpthr.h create mode 100644 oflog/include/dcmtk/oflog/thread/impl/syncwin.h create mode 100644 oflog/include/dcmtk/oflog/thread/impl/thredimp.h create mode 100644 oflog/include/dcmtk/oflog/thread/impl/tls.h create mode 100644 oflog/include/dcmtk/oflog/thread/syncprim.h create mode 100644 oflog/include/dcmtk/oflog/thread/syncpub.h create mode 100644 oflog/include/dcmtk/oflog/thread/threads.h create mode 100644 oflog/include/dcmtk/oflog/tracelog.h create mode 100644 oflog/include/dcmtk/oflog/tstring.h create mode 100644 oflog/include/dcmtk/oflog/version.h create mode 100644 oflog/include/dcmtk/oflog/winconap.h create mode 100644 oflog/include/dcmtk/oflog/windebap.h create mode 100644 oflog/libsrc/CMakeLists.txt create mode 100644 oflog/libsrc/Makefile.dep create mode 100644 oflog/libsrc/Makefile.in create mode 100644 oflog/libsrc/apndimpl.cc create mode 100644 oflog/libsrc/appender.cc create mode 100644 oflog/libsrc/asyncap.cc create mode 100644 oflog/libsrc/clfsap.cc create mode 100644 oflog/libsrc/clogger.cc create mode 100644 oflog/libsrc/config.cc create mode 100644 oflog/libsrc/consap.cc create mode 100644 oflog/libsrc/cygwin32.cc create mode 100644 oflog/libsrc/env.cc create mode 100644 oflog/libsrc/factory.cc create mode 100644 oflog/libsrc/fileap.cc create mode 100644 oflog/libsrc/fileinfo.cc create mode 100644 oflog/libsrc/filter.cc create mode 100644 oflog/libsrc/globinit.cc create mode 100644 oflog/libsrc/hierarchy.cc create mode 100644 oflog/libsrc/hierlock.cc create mode 100644 oflog/libsrc/layout.cc create mode 100644 oflog/libsrc/lloguser.cc create mode 100644 oflog/libsrc/lockfile.cc create mode 100644 oflog/libsrc/log4judp.cc create mode 100644 oflog/libsrc/logevent.cc create mode 100644 oflog/libsrc/logger.cc create mode 100644 oflog/libsrc/logimpl.cc create mode 100644 oflog/libsrc/loglevel.cc create mode 100644 oflog/libsrc/loglog.cc create mode 100644 oflog/libsrc/logmacro.cc create mode 100644 oflog/libsrc/mdc.cc create mode 100644 oflog/libsrc/ndc.cc create mode 100644 oflog/libsrc/ntelogap.cc create mode 100644 oflog/libsrc/nullap.cc create mode 100644 oflog/libsrc/objreg.cc create mode 100644 oflog/libsrc/oflog.cc create mode 100644 oflog/libsrc/patlay.cc create mode 100644 oflog/libsrc/pointer.cc create mode 100644 oflog/libsrc/property.cc create mode 100644 oflog/libsrc/queue.cc create mode 100644 oflog/libsrc/rootlog.cc create mode 100644 oflog/libsrc/sleep.cc create mode 100644 oflog/libsrc/snprintf.cc create mode 100644 oflog/libsrc/sockbuff.cc create mode 100644 oflog/libsrc/socket.cc create mode 100644 oflog/libsrc/socketap.cc create mode 100644 oflog/libsrc/strccloc.cc create mode 100644 oflog/libsrc/strcloc.cc create mode 100644 oflog/libsrc/strhelp.cc create mode 100644 oflog/libsrc/striconv.cc create mode 100644 oflog/libsrc/syncprims.cc create mode 100644 oflog/libsrc/syslogap.cc create mode 100644 oflog/libsrc/threads.cc create mode 100644 oflog/libsrc/timehelp.cc create mode 100644 oflog/libsrc/tls.cc create mode 100644 oflog/libsrc/unixsock.cc create mode 100644 oflog/libsrc/version.cc create mode 100644 oflog/libsrc/winconap.cc create mode 100644 oflog/libsrc/windebap.cc create mode 100644 oflog/libsrc/winsock.cc create mode 100644 oflog/tests/Makefile.dep create mode 100644 oflog/tests/Makefile.in create mode 100644 ofstd/CMakeLists.txt create mode 100644 ofstd/Makefile.in create mode 100755 ofstd/configure create mode 100644 ofstd/data/Makefile.in create mode 100644 ofstd/docs/Makefile.in create mode 100644 ofstd/docs/ofstd.dox create mode 100644 ofstd/etc/Makefile.in create mode 100644 ofstd/include/CMakeLists.txt create mode 100644 ofstd/include/Makefile.in create mode 100644 ofstd/include/dcmtk/ofstd/ofalgo.h create mode 100644 ofstd/include/dcmtk/ofstd/ofalign.h create mode 100644 ofstd/include/dcmtk/ofstd/ofaptr.h create mode 100644 ofstd/include/dcmtk/ofstd/ofbmanip.h create mode 100644 ofstd/include/dcmtk/ofstd/ofcast.h create mode 100644 ofstd/include/dcmtk/ofstd/ofchrenc.h create mode 100644 ofstd/include/dcmtk/ofstd/ofcmdln.h create mode 100644 ofstd/include/dcmtk/ofstd/ofconapp.h create mode 100644 ofstd/include/dcmtk/ofstd/ofcond.h create mode 100644 ofstd/include/dcmtk/ofstd/ofconfig.h create mode 100644 ofstd/include/dcmtk/ofstd/ofconsol.h create mode 100644 ofstd/include/dcmtk/ofstd/ofcrc32.h create mode 100644 ofstd/include/dcmtk/ofstd/ofdate.h create mode 100644 ofstd/include/dcmtk/ofstd/ofdatime.h create mode 100644 ofstd/include/dcmtk/ofstd/ofdefine.h create mode 100644 ofstd/include/dcmtk/ofstd/ofexbl.h create mode 100644 ofstd/include/dcmtk/ofstd/ofexport.h create mode 100644 ofstd/include/dcmtk/ofstd/offile.h create mode 100644 ofstd/include/dcmtk/ofstd/offname.h create mode 100644 ofstd/include/dcmtk/ofstd/ofglobal.h create mode 100644 ofstd/include/dcmtk/ofstd/ofgrp.h create mode 100644 ofstd/include/dcmtk/ofstd/oflimits.h create mode 100644 ofstd/include/dcmtk/ofstd/oflist.h create mode 100644 ofstd/include/dcmtk/ofstd/ofmap.h create mode 100644 ofstd/include/dcmtk/ofstd/ofmem.h create mode 100644 ofstd/include/dcmtk/ofstd/ofnetdb.h create mode 100644 ofstd/include/dcmtk/ofstd/ofoption.h create mode 100644 ofstd/include/dcmtk/ofstd/ofoset.h create mode 100644 ofstd/include/dcmtk/ofstd/ofpwd.h create mode 100644 ofstd/include/dcmtk/ofstd/ofset.h create mode 100644 ofstd/include/dcmtk/ofstd/ofsetit.h create mode 100644 ofstd/include/dcmtk/ofstd/ofstack.h create mode 100644 ofstd/include/dcmtk/ofstd/ofstd.h create mode 100644 ofstd/include/dcmtk/ofstd/ofstdinc.h create mode 100644 ofstd/include/dcmtk/ofstd/ofstream.h create mode 100644 ofstd/include/dcmtk/ofstd/ofstring.h create mode 100644 ofstd/include/dcmtk/ofstd/oftempf.h create mode 100644 ofstd/include/dcmtk/ofstd/oftest.h create mode 100644 ofstd/include/dcmtk/ofstd/ofthread.h create mode 100644 ofstd/include/dcmtk/ofstd/oftime.h create mode 100644 ofstd/include/dcmtk/ofstd/oftimer.h create mode 100644 ofstd/include/dcmtk/ofstd/oftraits.h create mode 100644 ofstd/include/dcmtk/ofstd/oftuple.h create mode 100644 ofstd/include/dcmtk/ofstd/oftypes.h create mode 100644 ofstd/include/dcmtk/ofstd/ofuoset.h create mode 100644 ofstd/include/dcmtk/ofstd/ofutil.h create mode 100644 ofstd/include/dcmtk/ofstd/ofuuid.h create mode 100644 ofstd/include/dcmtk/ofstd/ofvector.h create mode 100644 ofstd/include/dcmtk/ofstd/ofxml.h create mode 100644 ofstd/include/dcmtk/ofstd/variadic/tuple.h create mode 100644 ofstd/include/dcmtk/ofstd/variadic/tuplefrd.h create mode 100644 ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h create mode 100644 ofstd/libsrc/CMakeLists.txt create mode 100644 ofstd/libsrc/Makefile.dep create mode 100644 ofstd/libsrc/Makefile.in create mode 100644 ofstd/libsrc/ofchrenc.cc create mode 100644 ofstd/libsrc/ofcmdln.cc create mode 100644 ofstd/libsrc/ofconapp.cc create mode 100644 ofstd/libsrc/ofcond.cc create mode 100644 ofstd/libsrc/ofconfig.cc create mode 100644 ofstd/libsrc/ofconsol.cc create mode 100644 ofstd/libsrc/ofcrc32.cc create mode 100644 ofstd/libsrc/ofdate.cc create mode 100644 ofstd/libsrc/ofdatime.cc create mode 100644 ofstd/libsrc/offile.cc create mode 100644 ofstd/libsrc/offname.cc create mode 100644 ofstd/libsrc/oflist.cc create mode 100644 ofstd/libsrc/ofmath.cc create mode 100644 ofstd/libsrc/ofstd.cc create mode 100644 ofstd/libsrc/ofstring.cc create mode 100644 ofstd/libsrc/oftempf.cc create mode 100644 ofstd/libsrc/ofthread.cc create mode 100644 ofstd/libsrc/oftime.cc create mode 100644 ofstd/libsrc/oftimer.cc create mode 100644 ofstd/libsrc/ofuuid.cc create mode 100644 ofstd/libsrc/ofxml.cc create mode 100644 ofstd/tests/CMakeLists.txt create mode 100644 ofstd/tests/Makefile.dep create mode 100644 ofstd/tests/Makefile.in create mode 100644 ofstd/tests/tatof.cc create mode 100644 ofstd/tests/tbase64.cc create mode 100644 ofstd/tests/tchrenc.cc create mode 100644 ofstd/tests/tests.cc create mode 100644 ofstd/tests/tftoa.cc create mode 100644 ofstd/tests/tlimits.cc create mode 100644 ofstd/tests/tlist.cc create mode 100644 ofstd/tests/tmap.cc create mode 100644 ofstd/tests/tmarkup.cc create mode 100644 ofstd/tests/tmem.cc create mode 100644 ofstd/tests/tofdatim.cc create mode 100644 ofstd/tests/toffile.cc create mode 100644 ofstd/tests/tofstd.cc create mode 100644 ofstd/tests/toption.cc create mode 100644 ofstd/tests/tstack.cc create mode 100644 ofstd/tests/tstlist.exp create mode 100644 ofstd/tests/tstring.cc create mode 100644 ofstd/tests/tthread.cc create mode 100644 ofstd/tests/ttuple.cc create mode 100644 ofstd/tests/tuuid.cc create mode 100644 ofstd/tests/tvec.cc create mode 100644 ofstd/tests/txml.cc diff --git a/ANNOUNCE b/ANNOUNCE new file mode 100644 index 00000000..4a26a22e --- /dev/null +++ b/ANNOUNCE @@ -0,0 +1,29 @@ + +------------------------------------------------------------------------------- + Since this is a development snapshot of the DCMTK, there is no public + announcement. This file will be updated for the next official release. +------------------------------------------------------------------------------- + + +ANNOUNCEMENT + +Version X.Y.Z of the OFFIS DCMTK (DICOM ToolKit) software is now available for +public release. This release includes the following main changes over the +previous version 3.6.0: + + [...] + +Many people have contributed to this new release of DCMTK, appearing here in +alphabetical order. Thank you very much for your support! + + [...] + +Members of the OFFIS DICOM Team who have worked on this release are: + + [...] + +The DCMTK software can be downloaded via: + + http://dicom.offis.de/dcmtk or http://www.dcmtk.org/ + +OFFIS e.V., Oldenburg, Germany, 2011-02-01 diff --git a/CHANGES b/CHANGES new file mode 100644 index 00000000..1eb7feb2 --- /dev/null +++ b/CHANGES @@ -0,0 +1,12 @@ + +In earlier versions of DCMTK, changes between releases had been documented in a +CHANGES.XXX file inside DCMTK's main directory. + +Now, the CHANGES.XXX file has been moved to the dcmtk/doc folder with the latest +one being updated every time that a new snapshot is released. Thus it always +contains all DCMTK changes between the last DCMTK release and the latest +snapshot. + +For very recent changes, i. e. those changes to DCMTK that have been applied +after release of the latest snapshot, see the DCMTK git repository log at +http://git.dcmtk.org/ . diff --git a/CMake/3rdparty.cmake b/CMake/3rdparty.cmake new file mode 100755 index 00000000..9fcca779 --- /dev/null +++ b/CMake/3rdparty.cmake @@ -0,0 +1,295 @@ +IF(WIN32) + + # For Windows, we don't used FIND_PACKAGE because DCMTK usually is used with its + # own set of 3rd-party support libraries that can be downloaded from DCMTK's + # website (pre-built). + + # libxml support: find out whether user has library + GET_FILENAME_COMPONENT(LIBXML_DIR "${DCMTK_SOURCE_DIR}/../libxml2-2.7.7" ABSOLUTE) + FIND_PATH(WITH_LIBXMLINC "/include/libxml/parser.h" "${LIBXML_DIR}" NO_DEFAULT_PATH) + + # libpng support: find out whether user has library + GET_FILENAME_COMPONENT(LIBPNG_DIR "${DCMTK_SOURCE_DIR}/../libpng-1.4.2" ABSOLUTE) + FIND_PATH(WITH_LIBPNGINC "include/png.h" "${LIBPNG_DIR}" NO_DEFAULT_PATH) + + # libtiff support: find out whether user has library + GET_FILENAME_COMPONENT(LIBTIFF_DIR "${DCMTK_SOURCE_DIR}/../tiff-3.9.2" ABSOLUTE) + FIND_PATH(WITH_LIBTIFFINC "include/tiff.h" "${LIBTIFF_DIR}" NO_DEFAULT_PATH) + + # OpenSSL support: find out whether user has library + GET_FILENAME_COMPONENT(OPENSSL_DIR "${DCMTK_SOURCE_DIR}/../openssl-1.0.0" ABSOLUTE) + FIND_PATH(WITH_OPENSSLINC "include/openssl/ssl.h" "${OPENSSL_DIR}" NO_DEFAULT_PATH) + + # zlib support: find out whether user has library + GET_FILENAME_COMPONENT(ZLIB_DIR "${DCMTK_SOURCE_DIR}/../zlib-1.2.5" ABSOLUTE) + FIND_PATH(WITH_ZLIBINC "include/zlib.h" "${ZLIB_DIR}" NO_DEFAULT_PATH) + + # sndfile support: find out whether user has library. Needed for module dcmwave (not in public DCMTK yet, marked as advanced) + GET_FILENAME_COMPONENT(SNDFILE_DIR "${DCMTK_SOURCE_DIR}/../libsndfile-1.0.17" ABSOLUTE) + FIND_PATH(WITH_SNDFILEINC "sndfile.h" "${SNDFILE_DIR}" NO_DEFAULT_PATH) + MARK_AS_ADVANCED(SNDFILE_DIR WITH_SNDFILEINC) + + # libiconv support: find out whether user has library + GET_FILENAME_COMPONENT(LIBICONV_DIR "${DCMTK_SOURCE_DIR}/../libiconv-1.14" ABSOLUTE) + FIND_PATH(WITH_LIBICONVINC "include/iconv.h" "${LIBICONV_DIR}" NO_DEFAULT_PATH) + + # libxml support: configure compiler + IF(DCMTK_WITH_XML) + IF(WITH_LIBXMLINC) + SET(LIBXML_INCDIR ${WITH_LIBXMLINC}/include) + SET(LIBXML_LIBDIR ${WITH_LIBXMLINC}/lib) + SET(LIBXML_LIBS debug ${LIBXML_LIBDIR}/libxml2_d.lib optimized ${LIBXML_LIBDIR}/libxml2_o.lib debug ${LIBXML_LIBDIR}/iconv_d.lib optimized ${LIBXML_LIBDIR}/iconv_o.lib) + MESSAGE(STATUS "Info: DCMTK XML support will be enabled") + SET(WITH_LIBXML 1) + ELSE(WITH_LIBXMLINC) # turn off library if library path not set + MESSAGE(STATUS "Warning: XML support will be disabled because libxml2 directory is not specified. Correct path and re-enable DCMTK_WITH_XML.") + SET(DCMTK_WITH_XML OFF CACHE BOOL "" FORCE) + SET(WITH_LIBXML "") + ENDIF(WITH_LIBXMLINC) + ENDIF(DCMTK_WITH_XML) + + # libpng support: configure compiler + IF(DCMTK_WITH_PNG) + IF(WITH_LIBPNGINC) + SET(LIBPNG_INCDIR ${WITH_LIBPNGINC}/include) + SET(LIBPNG_LIBDIR ${WITH_LIBPNGINC}/lib) + SET(LIBPNG_LIBS debug ${LIBPNG_LIBDIR}/libpng_d.lib optimized ${LIBPNG_LIBDIR}/libpng_o.lib) + MESSAGE(STATUS "Info: DCMTK PNG support will be enabled") + SET(WITH_LIBPNG 1) + ELSE(WITH_LIBPNGINC) # turn off library if library path not set + MESSAGE(STATUS "Warning: PNG support will be disabled because libpng directory was not specified. Correct path and re-enable DCMTK_WITH_PNG.") + SET(DCMTK_WITH_PNG OFF CACHE BOOL "" FORCE) + SET(WITH_LIBPNG "") + ENDIF(WITH_LIBPNGINC) + ENDIF(DCMTK_WITH_PNG) + + # libtiff support: configure compiler + IF(DCMTK_WITH_TIFF) + IF(WITH_LIBTIFFINC) + SET(LIBTIFF_INCDIR ${WITH_LIBTIFFINC}/include) + SET(LIBTIFF_LIBDIR ${WITH_LIBTIFFINC}/lib) + SET(LIBTIFF_LIBS debug ${LIBTIFF_LIBDIR}/libtiff_d.lib optimized ${LIBTIFF_LIBDIR}/libtiff_o.lib) + MESSAGE(STATUS "Info: DCMTK TIFF support will be enabled") + SET(WITH_LIBTIFF 1) + ELSE(WITH_LIBTIFFINC) # turn off library if library path not set + MESSAGE(STATUS "Warning: TIFF support will be disabled because libtiff directory was not specified. Correct path and re-enable DCMTK_WITH_TIFF.") + SET(DCMTK_WITH_TIFF OFF CACHE BOOL "" FORCE) + SET(WITH_LIBTIFF "") + ENDIF(WITH_LIBTIFFINC) + ENDIF(DCMTK_WITH_TIFF) + + # OpenSSL support: configure compiler + IF(DCMTK_WITH_OPENSSL) + IF(WITH_OPENSSLINC) + SET(OPENSSL_BINDIR ${WITH_OPENSSLINC}/bin) + SET(OPENSSL_INCDIR ${WITH_OPENSSLINC}/include) + SET(OPENSSL_LIBDIR ${WITH_OPENSSLINC}/lib) + SET(OPENSSL_LIBS debug ${OPENSSL_LIBDIR}/dcmtkssl_d.lib optimized ${OPENSSL_LIBDIR}/dcmtkssl_o.lib debug ${OPENSSL_LIBDIR}/dcmtkeay_d.lib optimized ${OPENSSL_LIBDIR}/dcmtkeay_o.lib) + MESSAGE(STATUS "Info: DCMTK OPENSSL support will be enabled") + SET(WITH_OPENSSL 1) + ELSE(WITH_OPENSSLINC) # turn off library if library path not set + MESSAGE(STATUS "Warning: OPENSSL support will be disabled because openssl directory was not specified. Correct path and re-enable DCMTK_WITH_OPENSSL.") + SET(DCMTK_WITH_OPENSSL OFF CACHE BOOL "" FORCE) + SET(WITH_OPENSSL "") + ENDIF(WITH_OPENSSLINC) + ENDIF(DCMTK_WITH_OPENSSL) + + # zlib support: configure compiler + IF(DCMTK_WITH_ZLIB) + IF(WITH_ZLIBINC) + SET(ZLIB_INCDIR ${WITH_ZLIBINC}/include) + SET(ZLIB_LIBDIR ${WITH_ZLIBINC}/lib) + SET(ZLIB_LIBS debug ${ZLIB_LIBDIR}/zlib_d.lib optimized ${ZLIB_LIBDIR}/zlib_o.lib) + MESSAGE(STATUS "Info: DCMTK ZLIB support will be enabled") + SET(WITH_ZLIB 1) + ELSE(WITH_ZLIBINC) # turn off library if library path not set + MESSAGE(STATUS "Warning: ZLIB support will be disabled because zlib directory was not specified. Correct path and re-enable DCMTK_WITH_ZLIB.") + SET(DCMTK_WITH_ZLIB OFF CACHE BOOL "" FORCE) + SET(WITH_ZLIB "") + ENDIF(WITH_ZLIBINC) + ENDIF(DCMTK_WITH_ZLIB) + + # sndfile support: configure compiler + IF(DCMTK_WITH_SNDFILE) + IF(WITH_SNDFILEINC) + SET(SNDFILE_INCDIR ${WITH_SNDFILEINC}/include) + SET(SNDFILE_LIBDIR ${WITH_SNDFILEINC}/lib) + SET(SNDFILE_LIBS debug ${SNDFILE_LIBDIR}/libsndfile_d.lib optimized ${SNDFILE_LIBDIR}/libsndfile_o.lib) + MESSAGE(STATUS "Info: DCMTK SNDFILE support will be enabled") + SET(WITH_SNDFILE 1) + ELSE(WITH_SNDFILEINC) # turn off library if library path not set + MESSAGE(STATUS "Warning: SNDFILE support will be disabled because libsndfile directory was not specified. Correct path and re-enable DCMTK_WITH_SNDFILE.") + SET(DCMTK_WITH_SNDFILE OFF CACHE BOOL "" FORCE) + SET(WITH_SNDFILE "") + ENDIF(WITH_SNDFILEINC) + ENDIF(DCMTK_WITH_SNDFILE) + + # libiconv support: configure compiler + IF(DCMTK_WITH_ICONV) + IF(WITH_LIBICONVINC) + SET(LIBICONV_INCDIR ${WITH_LIBICONVINC}/include) + SET(LIBICONV_LIBDIR ${WITH_LIBICONVINC}/lib) + SET(LIBICONV_LIBS debug ${LIBICONV_LIBDIR}/libiconv_d.lib optimized ${LIBICONV_LIBDIR}/libiconv_o.lib) + MESSAGE(STATUS "Info: DCMTK ICONV support will be enabled") + SET(WITH_LIBICONV 1) + ELSE(WITH_LIBICONVINC) # turn off library if library path not set + MESSAGE(STATUS "Warning: ICONV support will be disabled because libiconv directory was not specified. Correct path and re-enable DCMTK_WITH_ICONV.") + SET(DCMTK_WITH_ICONV OFF CACHE BOOL "" FORCE) + SET(WITH_LIBICONV "") + ENDIF(WITH_LIBICONVINC) + ENDIF(DCMTK_WITH_ICONV) + +ELSE(WIN32) + + # Find TIFF + IF(DCMTK_WITH_TIFF) + FIND_PACKAGE(TIFF QUIET) + # turn off library if it could not be found + IF(NOT TIFF_FOUND) + MESSAGE(STATUS "Warning: TIFF support will be disabled because libtiff was not found.") + SET(DCMTK_WITH_TIFF OFF CACHE BOOL "" FORCE) + SET(WITH_LIBTIFF "") + ELSE(NOT TIFF_FOUND) + MESSAGE(STATUS "Info: DCMTK TIFF support will be enabled") + SET(WITH_LIBTIFF 1) + # libtiff can be compiled with libjpeg support; if available, add libjpeg to library and include path + FIND_PACKAGE(JPEG QUIET) + INCLUDE_DIRECTORIES(${TIFF_INCLUDE_DIR} ${JPEG_INCLUDE_DIR}) + SET(LIBTIFF_LIBS ${TIFF_LIBRARY} ${JPEG_LIBRARY}) + ENDIF(NOT TIFF_FOUND) + ENDIF(DCMTK_WITH_TIFF) + + # Find PNG + IF(DCMTK_WITH_PNG) + FIND_PACKAGE(PNG QUIET) + IF(NOT PNG_FOUND) + SET(DCMTK_WITH_PNG OFF CACHE BOOL "" FORCE) + MESSAGE(STATUS "Warning: PNG support will be disabled because libpng was not found.") + SET(WITH_LIBPNG "") + ELSE(NOT PNG_FOUND) + MESSAGE(STATUS "Info: DCMTK PNG support will be enabled") + SET(WITH_LIBPNG 1) + INCLUDE_DIRECTORIES(${PNG_INCLUDE_DIR}) + SET(LIBPNG_LIBS ${PNG_LIBRARY}) + ENDIF(NOT PNG_FOUND) + ENDIF(DCMTK_WITH_PNG) + + # Find OpenSSL + IF(DCMTK_WITH_OPENSSL) + FIND_PACKAGE(OpenSSL QUIET) + IF(NOT OPENSSL_FOUND) + MESSAGE(STATUS "Warning: OPENSSL support will be disabled because openssl was not found.") + SET(WITH_OPENSSL "") + SET(DCMTK_WITH_OPENSSL OFF CACHE BOOL "" FORCE) + ELSE(NOT OPENSSL_FOUND) + MESSAGE(STATUS "Info: DCMTK OPENSSL support will be enabled") + SET(WITH_OPENSSL 1) + INCLUDE_DIRECTORIES(${OPENSSL_INCLUDE_DIR}) + SET(OPENSSL_LIBS ${OPENSSL_LIBRARIES}) + ENDIF(NOT OPENSSL_FOUND) + ENDIF(DCMTK_WITH_OPENSSL) + + # Find libXML2 + IF(DCMTK_WITH_XML) + FIND_PACKAGE(LibXml2 QUIET) + IF(NOT LIBXML2_FOUND) + MESSAGE(STATUS "Warning: XML support will be disabled because libxml2 was not found.") + SET(WITH_LIBXML "") + SET(DCMTK_WITH_XML OFF CACHE BOOL "" FORCE) + ELSE(NOT LIBXML2_FOUND) + MESSAGE(STATUS "Info: DCMTK XML support will be enabled") + SET(WITH_LIBXML 1) + INCLUDE_DIRECTORIES(${LIBXML2_INCLUDE_DIR}) + SET(LIBXML_LIBS ${LIBXML2_LIBRARIES}) + ENDIF(NOT LIBXML2_FOUND) + ENDIF(DCMTK_WITH_XML) + + # Find zlib + IF(DCMTK_WITH_ZLIB) + FIND_PACKAGE(ZLIB QUIET) + IF(NOT ZLIB_FOUND) + MESSAGE(STATUS "Warning: ZLIB support will be disabled because zlib was not found.") + SET(WITH_ZLIB "") + SET(DCMTK_WITH_ZLIB OFF CACHE BOOL "" FORCE) + ELSE(NOT ZLIB_FOUND) + MESSAGE(STATUS "Info: DCMTK ZLIB support will be enabled") + SET(WITH_ZLIB 1) + INCLUDE_DIRECTORIES(${ZLIB_INCLUDE_DIRS}) + SET(ZLIB_LIBS ${ZLIB_LIBRARIES}) + ENDIF(NOT ZLIB_FOUND) + ENDIF(DCMTK_WITH_ZLIB) + + # Find libsndfile + IF(DCMTK_WITH_SNDFILE) + FIND_PACKAGE(Sndfile QUIET) + IF(NOT SNDFILE_LIBS) + MESSAGE(STATUS "Warning: SNDFILE support will be disabled because libsndfile was not found.") + SET(WITH_SNDFILE "") + SET(DCMTK_WITH_SNDFILE OFF CACHE BOOL "" FORCE) + ELSE(NOT SNDFILE_LIBS) + MESSAGE(STATUS "Info: DCMTK SNDFILE support will be enabled") + SET(WITH_SNDFILE 1) + INCLUDE_DIRECTORIES(${SNDFILE_INCLUDE_DIRS}) + SET(SNDFILE_LIBS ${SNDFILE_LIBRARIES}) + ENDIF(NOT SNDFILE_LIBS) + ENDIF(DCMTK_WITH_SNDFILE) + + # Find libiconv + IF(DCMTK_WITH_ICONV) + FIND_PACKAGE(ICONV QUIET) + FIND_PACKAGE(Charset QUIET) + IF(NOT LIBICONV_FOUND OR NOT LIBCHARSET_FOUND) + MESSAGE(STATUS "Warning: ICONV support will be disabled because libiconv was not found. Correct LIBICONV_LIBDIR and LIBICONV_INCLUDE_DIR and re-enable DCMTK_WITH_ICONV.") + SET(DCMTK_WITH_ICONV OFF CACHE BOOL "" FORCE) + SET(WITH_LIBICONV "") + ELSE(NOT LIBICONV_FOUND OR NOT LIBCHARSET_FOUND) + MESSAGE(STATUS "Info: DCMTK ICONV support will be enabled") + SET(WITH_LIBICONV 1) + SET(LIBICONV_INCDIR ${LIBICONV_INCLUDE_DIRS} ${LIBCHARSET_INCLUDE_DIRS}) + SET(LIBICONV_LIBDIR ${LIBICONV_LIBDIR}) + SET(LIBICONV_LIBS ${LIBICONV_LIBRARIES} ${LIBCHARSET_LIBRARY}) + INCLUDE_DIRECTORIES(${LIBICONV_INCDIR}) + ENDIF(NOT LIBICONV_FOUND OR NOT LIBCHARSET_FOUND) + ENDIF(DCMTK_WITH_ICONV) + + # Find libwrap + IF(DCMTK_WITH_WRAP) + FIND_PACKAGE(Wrap QUIET) + IF(NOT WRAP_FOUND) + MESSAGE(STATUS "Warning: WRAP support will be disabled because libwrap was not found.") + SET(WITH_TCPWRAPPER "") + SET(DCMTK_WITH_WRAP OFF CACHE BOOL "" FORCE) + ELSE(NOT WRAP_FOUND) + MESSAGE(STATUS "Info: DCMTK WRAP support will be enabled") + SET(WITH_TCPWRAPPER 1) + INCLUDE_DIRECTORIES(${WRAP_INCLUDE_DIRS}) + SET(WRAP_LIBS ${WRAP_LIBRARIES}) + ENDIF(NOT WRAP_FOUND) + ENDIF(DCMTK_WITH_WRAP) + +ENDIF() + +# Find doxygen +IF(DCMTK_WITH_DOXYGEN) + FIND_PACKAGE(Doxygen QUIET) # will set variable DOXYGEN_EXECUTABLE + IF(NOT DOXYGEN_FOUND) + MESSAGE(STATUS "Warning: DOXYGEN support will be disabled because doxygen was not found.") + SET(DCMTK_WITH_DOXYGEN OFF CACHE BOOL "" FORCE) + ENDIF(NOT DOXYGEN_FOUND) +ENDIF(DCMTK_WITH_DOXYGEN) + +IF(DCMTK_WITH_ICONV) + INCLUDE(CheckCXXSourceCompiles) + SET(CMAKE_REQUIRED_INCLUDES ${LIBICONV_INCDIR}) + SET(CMAKE_REQUIRED_LIBRARIES ${LIBICONV_LIBS}) + CHECK_CXX_SOURCE_COMPILES(" + #include + int main() { + iconv_t cd = 0; + const char *in = 0; + iconv(cd, &in, 0, 0, 0); + return 0; + }" LIBICONV_SECOND_ARGUMENT_CONST) + SET(CMAKE_REQUIRED_INCLUDES) + SET(CMAKE_REQUIRED_LIBRARIES) +ENDIF(DCMTK_WITH_ICONV) diff --git a/CMake/CTest/CTestCustom.cmake b/CMake/CTest/CTestCustom.cmake new file mode 100644 index 00000000..d8f051d4 --- /dev/null +++ b/CMake/CTest/CTestCustom.cmake @@ -0,0 +1,79 @@ +# +# This file is run prior to the unit tests for preparing the testing +# environment. Currently only required / necessary for running the +# tests on the Android device emulator. +# + +# Restore the required settings of the CMake configuration step +INCLUDE(dcmtkCTestConfig.cmake NO_POLICY_SCOPE) + +# Emulate some required CMake commands while running inside CTest +INCLUDE(${DCMTK_CMAKE_INCLUDE}CMake/CTest/dcmtkCTestMacros.cmake) + +# Prepare the Android testing environment +IF(ANDROID) + # Load required functions for controlling the Android device emulator + INCLUDE(${DCMTK_CMAKE_INCLUDE}CMake/dcmtkUseAndroidSDK.cmake) + + # Prepare the emulator + DCMTK_ANDROID_START_EMULATOR(DCMTK_ANDROID_EMULATOR_INSTANCE) + DCMTK_ANDROID_WAIT_FOR_EMULATOR(DCMTK_ANDROID_EMULATOR_INSTANCE) + + # Get the emulator's name for emitting a shutdown command when done + DCMTK_ANDROID_GET_OBJECT_PROPERTIES(DCMTK_ANDROID_EMULATOR_INSTANCE) + DCMTK_ANDROID_STOP_EMULATOR_COMMAND(STOP_EMULATOR ${EMULATOR_NAME}) + DCMTK_ANDROID_EMULATOR_SHUTDOWN_MESSAGE(STOP_MESSAGE) + MESSAGE_COMMAND(STOP_MESSAGE ${STOP_MESSAGE}) + # CTEST_CUSTOM_POST_TESTS executes a sequence of 'non CMake' commands separated + # by ';' characters. Therefore the sequence a single command consists of must + # be translated appropriately first + STRING(REPLACE ";" " " STOP_EMULATOR "${STOP_EMULATOR}") + STRING(REPLACE ";" " " STOP_MESSAGE "${STOP_MESSAGE}") + SET(CLEANUP_COMMAND "${CMAKE_COMMAND} -E remove ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/dcmtkCTestRunAndroid.cmake") + # Register the cleanup hooks + SET(CTEST_CUSTOM_POST_TEST "${CLEANUP_COMMAND}" "${STOP_MESSAGE}" "${STOP_EMULATOR}") + + # Prepare the test script, most importantly set the current emulator instance handle + CONFIGURE_FILE( + ${DCMTK_CMAKE_INCLUDE}CMake/CTest/dcmtkCTestRunAndroid.cmake.in + ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/dcmtkCTestRunAndroid.cmake + @ONLY + ) + + # Collect the list of required libraries + IF(BUILD_SHARED_LIBS) + FOREACH(LIBRARY ${DCMTK_ALL_LIBRARIES}) + LIST(APPEND DCMTK_CREATED_SHARED_LIBRARIES ${CMAKE_BINARY_DIR}/lib/${CMAKE_SHARED_LIBRARY_PREFIX}${LIBRARY}${CMAKE_SHARED_LIBRARY_SUFFIX}.${DCMTK_PACKAGE_VERSION}) + ENDFOREACH() + ENDIF(BUILD_SHARED_LIBS) + + # Transmit the required executables and libraries to the emulator + DCMTK_ANDROID_PUSH(DCMTK_ANDROID_EMULATOR_INSTANCE + ${ANDROID_RUNTIME_LIBRARIES} + ${DCMTK_LIBRARY_DEPENDENCIES} + ${DCMTK_CREATED_SHARED_LIBRARIES} + ${DCMTK_TEST_EXECUTABLES} + DESTINATION ${ANDROID_TEMPORARY_FILES_LOCATION} + ) + + # Set executable permissions + FOREACH(TEST_EXECUTABLE ${DCMTK_TEST_EXECUTABLES}) + GET_FILENAME_COMPONENT(NAME ${TEST_EXECUTABLE} NAME) + DCMTK_ANDROID_SHELL(DCMTK_ANDROID_EMULATOR_INSTANCE + COMMAND chmod 755 ${ANDROID_TEMPORARY_FILES_LOCATION}/${NAME} + OUTPUT_QUIET + ERROR_QUIET + ) + ENDFOREACH() + + # Create necessary softlinks + IF(BUILD_SHARED_LIBS) + FOREACH(LIBRARY ${DCMTK_ALL_LIBRARIES}) + DCMTK_ANDROID_SHELL(DCMTK_ANDROID_EMULATOR_INSTANCE + COMMAND ln -s ./${CMAKE_SHARED_LIBRARY_PREFIX}${LIBRARY}${CMAKE_SHARED_LIBRARY_SUFFIX}.${DCMTK_PACKAGE_VERSION} ${ANDROID_TEMPORARY_FILES_LOCATION}/${CMAKE_SHARED_LIBRARY_PREFIX}${LIBRARY}${CMAKE_SHARED_LIBRARY_SUFFIX}.${DCMTK_ABI_VERSION} + OUTPUT_QUIET + ERROR_QUIET + ) + ENDFOREACH() + ENDIF(BUILD_SHARED_LIBS) +ENDIF(ANDROID) diff --git a/CMake/CTest/dcmtkCTestConfig.cmake.in b/CMake/CTest/dcmtkCTestConfig.cmake.in new file mode 100644 index 00000000..69ae53b7 --- /dev/null +++ b/CMake/CTest/dcmtkCTestConfig.cmake.in @@ -0,0 +1,36 @@ +# +# This file is used to recover the necessary CMake cache variables while +# running the unit tests. +# + +# Minimum CMake version required +CMAKE_MINIMUM_REQUIRED(VERSION 2.6) + +SET(CMAKE_COMMAND "@CMAKE_COMMAND@") +SET(CMAKE_BINARY_DIR "@CMAKE_BINARY_DIR@") +SET(CMAKE_CURRENT_BINARY_DIR "@CMAKE_BINARY_DIR@") +SET(CMAKE_FILES_DIRECTORY "@CMAKE_FILES_DIRECTORY@") +SET(CMAKE_MODULE_PATH "@CMAKE_ROOT@/Modules") +SET(CMAKE_SHARED_LIBRARY_PREFIX "@CMAKE_SHARED_LIBRARY_PREFIX@") +SET(CMAKE_SHARED_LIBRARY_SUFFIX "@CMAKE_SHARED_LIBRARY_SUFFIX@") +SET(CMAKE_HOST_SYSTEM "@CMAKE_HOST_SYSTEM@") +SET(DCMTK_CMAKE_INCLUDE "@CMAKE_SOURCE_DIR@/@DCMTK_CMAKE_INCLUDE@") +SET(DCMTK_TEST_EXECUTABLES "@DCMTK_TEST_EXECUTABLES@") +SET(DCMTK_ALL_LIBRARIES "@DCMTK_ALL_LIBRARIES@") +SET(DCMTK_LIBRARY_DEPENDENCIES "@DCMTK_LIBRARY_DEPENDENCIES@") +SET(DCMTK_PACKAGE_VERSION "@DCMTK_PACKAGE_VERSION@") +SET(DCMTK_ABI_VERSION "@DCMTK_ABI_VERSION@") +SET(BUILD_SHARED_LIBS "@BUILD_SHARED_LIBS@") + +# Variables used when cross compiling for Android, will be unset otherwise +SET(ANDROID "@ANDROID@") +IF(ANDROID) + SET(ANDROID_ADB_PROGRAM "@ANDROID_ADB_PROGRAM@") + SET(ANDROID_ANDROID_PROGRAM "@ANDROID_ANDROID_PROGRAM@") + SET(ANDROID_EMULATOR_PROGRAM "@ANDROID_EMULATOR_PROGRAM@") + SET(ANDROID_EMULATOR_AVD "@ANDROID_EMULATOR_AVD@") + SET(ANDROID_RUNTIME_LIBRARIES "@ANDROID_RUNTIME_LIBRARIES@") + SET(ANDROID_TEMPORARY_FILES_LOCATION "@ANDROID_TEMPORARY_FILES_LOCATION@") +ELSE(ANDROID) + UNSET(ANDROID) +ENDIF(ANDROID) diff --git a/CMake/CTest/dcmtkCTestMacros.cmake b/CMake/CTest/dcmtkCTestMacros.cmake new file mode 100644 index 00000000..b3a7eb50 --- /dev/null +++ b/CMake/CTest/dcmtkCTestMacros.cmake @@ -0,0 +1,27 @@ +# +# This file "re-implements" some of CMake's functionality +# that is missing inside CTest. +# + +MACRO(MESSAGE_COMMAND VAR MODE) + IF(${MODE} STREQUAL "STATUS") + SET(${VAR} ${CMAKE_COMMAND} -E echo -- ${ARGN}) + ELSEIF(${MODE} STREQUAL "WARNING") + SET(${VAR} ${CMAKE_COMMAND} -E echo WARNING: ${ARGN}) + ELSEIF(${MODE} STREQUAL "AUTHOR_WARNING") + SET(${VAR} ${CMAKE_COMMAND} -E echo Warning: ${ARGN}) + ELSEIF(${MODE} STREQUAL "SEND_ERROR") + SET(${VAR} ${CMAKE_COMMAND} -E echo Error: ${ARGN}) + ELSEIF(${MODE} STREQUAL "FATAL_ERROR") + SET(${VAR} ${CMAKE_COMMAND} -E echo ERROR: ${ARGN}) + ELSEIF(${MODE} STREQUAL "DEPRECATION") + SET(${VAR} ${CMAKE_COMMAND} -E echo ${ARGN}) + ELSE() + SET(${VAR} ${CMAKE_COMMAND} -E echo ${MODE} ${ARGN}) + ENDIF() +ENDMACRO(MESSAGE_COMMAND) + +FUNCTION(MESSAGE) + MESSAGE_COMMAND(COMMAND ${ARGN}) + EXECUTE_PROCESS(COMMAND ${COMMAND}) +ENDFUNCTION(MESSAGE) diff --git a/CMake/CTest/dcmtkCTestRunAndroid.cmake.in b/CMake/CTest/dcmtkCTestRunAndroid.cmake.in new file mode 100644 index 00000000..4cc1dcac --- /dev/null +++ b/CMake/CTest/dcmtkCTestRunAndroid.cmake.in @@ -0,0 +1,26 @@ +# +# This file is used to executed given unit test commands on a previously +# initialize Android device emulator instance +# + +# Restore the required settings of the CMake configuration step +INCLUDE(@CMAKE_BINARY_DIR@/dcmtkCTestConfig.cmake NO_POLICY_SCOPE) + +# Load required functions for accessing the Android device emulator +INCLUDE(${DCMTK_CMAKE_INCLUDE}CMake/dcmtkUseAndroidSDK.cmake) + +# Restore the Android device emulator instance handle +SET(DCMTK_ANDROID_EMULATOR_INSTANCE @DCMTK_ANDROID_EMULATOR_INSTANCE@) + +# Run the actual testcase on the remote device +DCMTK_ANDROID_SHELL(DCMTK_ANDROID_EMULATOR_INSTANCE + COMMAND "LD_LIBRARY_PATH=\$LD_LIBRARY_PATH:${ANDROID_TEMPORARY_FILES_LOCATION}" ${DCMTK_CTEST_TESTCASE_COMMAND} + WORKING_DIRECTORY ${ANDROID_TEMPORARY_FILES_LOCATION} + RESULT_VARIABLE RESULT +) + +# We cannot forward the result value to CMake, so print it instead and let CMake +# return with code '1' or whatever it deems appropriate to notify about an error. +IF(RESULT) + MESSAGE(FATAL_ERROR "Test command returned: ${RESULT}") +ENDIF() diff --git a/CMake/CheckCMakeCommandExists.cmake b/CMake/CheckCMakeCommandExists.cmake new file mode 100644 index 00000000..c204778e --- /dev/null +++ b/CMake/CheckCMakeCommandExists.cmake @@ -0,0 +1,12 @@ +# Helper macro that checks whether a given CMake command exists or not +MACRO(CHECK_CMAKE_COMMAND_EXISTS commandname) + MESSAGE(STATUS "Looking for CMake command ${commandname}") + string(TOUPPER ${commandname} commandname_upper) + IF(COMMAND ${commandname}) + SET(HAVE_${commandname_upper} TRUE) + MESSAGE(STATUS "Looking for CMake command ${commandname} - found") + ELSE() + SET(HAVE_${commandname_upper} FALSE) + MESSAGE(STATUS "Looking for CMake command ${commandname} - not found") + ENDIF() +ENDMACRO() diff --git a/CMake/CheckFunctionWithHeaderExists.cmake b/CMake/CheckFunctionWithHeaderExists.cmake new file mode 100644 index 00000000..e924c7f8 --- /dev/null +++ b/CMake/CheckFunctionWithHeaderExists.cmake @@ -0,0 +1,56 @@ +# +# Check if the symbol exists in include files +# +# CHECK_FUNCTIONWITHHEADER_EXISTS - macro which checks the symbol exists in include files. +# SYMBOL - symbol +# FILES - include files to check +# VARIABLE - variable to return result +# ... - additional arguments will be interpreted as additional libraries to link during testing. +# + +MACRO(CHECK_FUNCTIONWITHHEADER_EXISTS SYMBOL FILES VARIABLE) + IF(NOT DEFINED "${VARIABLE}") + SET(CHECK_SYMBOL_EXISTS_CONTENT "/* */\n") + SET(MACRO_CHECK_SYMBOL_EXISTS_FLAGS ${CMAKE_REQUIRED_FLAGS}) + IF(CMAKE_REQUIRED_LIBRARIES) + SET(CHECK_SYMBOL_EXISTS_LIBS + "-DLINK_LIBRARIES:STRING=${CMAKE_REQUIRED_LIBRARIES};${ARGN}") + ENDIF(CMAKE_REQUIRED_LIBRARIES) + FOREACH(FILE ${FILES}) + SET(CHECK_SYMBOL_EXISTS_CONTENT + "${CHECK_SYMBOL_EXISTS_CONTENT}#include <${FILE}>\n") + ENDFOREACH(FILE) + SET(CHECK_SYMBOL_EXISTS_CONTENT + "${CHECK_SYMBOL_EXISTS_CONTENT}\nint main()\n{\n${SYMBOL};return 0;\n}\n") + + FILE(WRITE ${CMAKE_BINARY_DIR}/CMakeTmp/CheckSymbolExists.cxx + "${CHECK_SYMBOL_EXISTS_CONTENT}") + + MESSAGE(STATUS "Looking for prototype of ${SYMBOL}") + TRY_COMPILE(${VARIABLE} + ${CMAKE_BINARY_DIR} + ${CMAKE_BINARY_DIR}/CMakeTmp/CheckSymbolExists.cxx + CMAKE_FLAGS + -DCOMPILE_DEFINITIONS:STRING=${MACRO_CHECK_SYMBOL_EXISTS_FLAGS} + "${CHECK_SYMBOL_EXISTS_LIBS}" + ${DCMTK_TRY_COMPILE_REQUIRED_CMAKE_FLAGS} + OUTPUT_VARIABLE OUTPUT) + IF(${VARIABLE}) + MESSAGE(STATUS "Looking for prototype of ${SYMBOL} - found") + SET(${VARIABLE} 1 CACHE INTERNAL "Have symbol ${SYMBOL}") + FILE(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log + "Determining if the ${SYMBOL} " + "exist passed with the following output:\n" + "${OUTPUT}\nFile ${CMAKE_BINARY_DIR}/CMakeTmp/CheckSymbolExists.ccc:\n" + "${CHECK_SYMBOL_EXISTS_CONTENT}\n") + ELSE(${VARIABLE}) + MESSAGE(STATUS "Looking for prototype of ${SYMBOL} - not found.") + SET(${VARIABLE} "" CACHE INTERNAL "Have symbol ${SYMBOL}") + FILE(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log + "Determining if the ${SYMBOL} " + "exist failed with the following output:\n" + "${OUTPUT}\nFile ${CMAKE_BINARY_DIR}/CMakeTmp/CheckSymbolExists.cxx:\n" + "${CHECK_SYMBOL_EXISTS_CONTENT}\n") + ENDIF(${VARIABLE}) + ENDIF(NOT DEFINED "${VARIABLE}") +ENDMACRO(CHECK_FUNCTIONWITHHEADER_EXISTS) diff --git a/CMake/DCMTKConfig.cmake.in b/CMake/DCMTKConfig.cmake.in new file mode 100644 index 00000000..b77a8560 --- /dev/null +++ b/CMake/DCMTKConfig.cmake.in @@ -0,0 +1,53 @@ +# +# DCMTKConfig.cmake - DCMTK CMake configuration file for external projects +# + +@PACKAGE_INIT@ + +# Basic version information +SET(DCMTK_MAJOR_VERSION @DCMTK_MAJOR_VERSION@) +SET(DCMTK_MINOR_VERSION @DCMTK_MINOR_VERSION@) +SET(DCMTK_BUILD_VERSION @DCMTK_BUILD_VERSION@) + +# DCMTK libraries and modules +SET(DCMTK_MODULES "@DCMTK_MODULES@") +SET(DCMTK_LIBRARIES "@DCMTK_LIBRARY_TARGETS@") + +# DCMTK build options +SET(DCMTK_WITH_TIFF @DCMTK_WITH_TIFF@) +SET(DCMTK_WITH_PNG @DCMTK_WITH_PNG@) +SET(DCMTK_WITH_XML @DCMTK_WITH_XML@) +SET(DCMTK_WITH_ZLIB @DCMTK_WITH_ZLIB@) +SET(DCMTK_WITH_OPENSSL @DCMTK_WITH_OPENSSL@) +SET(DCMTK_WITH_SNDFILE @DCMTK_WITH_SNDFILE@) +SET(DCMTK_WITH_ICONV @DCMTK_WITH_ICONV@) +SET(DCMTK_ENABLE_PRIVATE_TAGS @DCMTK_ENABLE_PRIVATE_TAGS@) +SET(DCMTK_WITH_THREADS @DCMTK_WITH_THREADS@) + +# DCMTK shared libraries +SET(DCMTK_SHARED_LIBRARIES @BUILD_SHARED_LIBS@) +SET(DCMTK_SINGLE_SHARED_LIBRARY @BUILD_SINGLE_SHARED_LIBRARY@) + +# DCMTK additional options +SET(DCMTK_OVERWRITE_WIN32_COMPILER_FLAGS @DCMTK_OVERWRITE_WIN32_COMPILER_FLAGS@) +SET(DCMTK_WIDE_CHAR_FILE_IO_FUNCTIONS @DCMTK_WIDE_CHAR_FILE_IO_FUNCTIONS@) +SET(DCMTK_WIDE_CHAR_MAIN_FUNCTION @DCMTK_WIDE_CHAR_MAIN_FUNCTION@) + +@DCMTK_INCLUDE_DIR_CONFIGS@ + +SET_AND_CHECK(DCMTK_TARGETS "@PACKAGE_DCMTK_CMKDIR_CONFIG@/DCMTKTargets.cmake") + +SET(DCMTK_INCLUDE_DIRS "") +FOREACH(module config ${DCMTK_MODULES}) + LIST(APPEND DCMTK_INCLUDE_DIRS ${DCMTK_${module}_INCLUDE_DIR}) +ENDFOREACH(module) + +@DCMTK_CONFIG_CODE@ + +# Compatibility: This variable is deprecated +SET(DCMTK_INCLUDE_DIR ${DCMTK_INCLUDE_DIRS}) + +IF(NOT DCMTK_TARGETS_IMPORTED) + SET(DCMTK_TARGETS_IMPORTED 1) + INCLUDE(${DCMTK_TARGETS}) +ENDIF(NOT DCMTK_TARGETS_IMPORTED) diff --git a/CMake/DCMTKConfig.cmake26.in b/CMake/DCMTKConfig.cmake26.in new file mode 100644 index 00000000..75cd8eb7 --- /dev/null +++ b/CMake/DCMTKConfig.cmake26.in @@ -0,0 +1,37 @@ +# +# DCMTKConfig.cmake - DCMTK CMake configuration file for external projects +# +# This is the old version that is used by CMake versions lower than 2.8.8 +# which introduced the more convenient CONFIGURE_PACKAGE_CONFIG_FILE command. +# As a result, this file lacks some information compared to the +# CONFIGURE_PACKAGE_CONFIG_FILE version. +# + +# Basic version information +SET(DCMTK_MAJOR_VERSION @DCMTK_MAJOR_VERSION@) +SET(DCMTK_MINOR_VERSION @DCMTK_MINOR_VERSION@) +SET(DCMTK_BUILD_VERSION @DCMTK_BUILD_VERSION@) + +# DCMTK libraries and modules +SET(DCMTK_MODULES "@DCMTK_MODULES@") +SET(DCMTK_LIBRARIES "@DCMTK_ALL_LIBRARIES@") + +# DCMTK build options +SET(DCMTK_WITH_TIFF @DCMTK_WITH_TIFF@) +SET(DCMTK_WITH_PNG @DCMTK_WITH_PNG@) +SET(DCMTK_WITH_XML @DCMTK_WITH_XML@) +SET(DCMTK_WITH_ZLIB @DCMTK_WITH_ZLIB@) +SET(DCMTK_WITH_OPENSSL @DCMTK_WITH_OPENSSL@) +SET(DCMTK_WITH_SNDFILE @DCMTK_WITH_SNDFILE@) +SET(DCMTK_WITH_ICONV @DCMTK_WITH_ICONV@) +SET(DCMTK_ENABLE_PRIVATE_TAGS @DCMTK_ENABLE_PRIVATE_TAGS@) +SET(DCMTK_WITH_THREADS @DCMTK_WITH_THREADS@) + +# DCMTK shared libraries +SET(DCMTK_SHARED_LIBRARIES @BUILD_SHARED_LIBS@) +SET(DCMTK_SINGLE_SHARED_LIBRARY @BUILD_SINGLE_SHARED_LIBRARY@) + +# DCMTK additional options +SET(DCMTK_OVERWRITE_WIN32_COMPILER_FLAGS @DCMTK_OVERWRITE_WIN32_COMPILER_FLAGS@) +SET(DCMTK_WIDE_CHAR_FILE_IO_FUNCTIONS @DCMTK_WIDE_CHAR_FILE_IO_FUNCTIONS@) +SET(DCMTK_WIDE_CHAR_MAIN_FUNCTION @DCMTK_WIDE_CHAR_MAIN_FUNCTION@) diff --git a/CMake/FindCharset.cmake b/CMake/FindCharset.cmake new file mode 100644 index 00000000..85a89a01 --- /dev/null +++ b/CMake/FindCharset.cmake @@ -0,0 +1,22 @@ +# Find charset library +# +# LIBCHARSET_INCLUDE_DIRS - where to find localcharset.h, etc +# LIBCHARSET_LIBRARIES - Lists of libraries when using charset +# LIBCHARSET_FOUND - True if charset found + +INCLUDE(FindPackageHandleStandardArgs) + +# Look for the header file +FIND_PATH(LIBCHARSET_INCLUDE_DIR NAMES localcharset.h) +MARK_AS_ADVANCED(LIBCHARSET_INCLUDE_DIR) + +SET(LIBCHARSET_LIBS charset) +FIND_LIBRARY(LIBCHARSET_LIBRARY NAMES ${LIBCHARSET_LIBS}) +MARK_AS_ADVANCED(LIBCHARSET_LIBRARY) + +FIND_PACKAGE_HANDLE_STANDARD_ARGS(LIBCHARSET REQUIRED_VARS LIBCHARSET_LIBRARY LIBCHARSET_INCLUDE_DIR) + +IF(LIBCHARSET_FOUND) + SET(LIBCHARSET_INCLUDE_DIRS ${LIBCHARSET_INCLUDE_DIR}) + SET(LIBCHARSET_LIBRARIES ${LIBCHARSET_LIBRARY}) +ENDIF(LIBCHARSET_FOUND) diff --git a/CMake/FindICONV.cmake b/CMake/FindICONV.cmake new file mode 100644 index 00000000..f010b794 --- /dev/null +++ b/CMake/FindICONV.cmake @@ -0,0 +1,33 @@ +# Find iconv library +# +# Released under BSD license +# +# LIBICONV_INCLUDE_DIRS - where to find iconv.h, etc +# LIBICONV_LIBRARIES - Lists of libraries when using iconv +# LIBICONV_FOUND - True if iconv found + +INCLUDE(FindPackageHandleStandardArgs) +INCLUDE(dcmtkTryCompile) + +# Look for the header file +FIND_PATH(LIBICONV_INCLUDE_DIR NAMES iconv.h) +MARK_AS_ADVANCED(LIBICONV_INCLUDE_DIR) + +# Look for the library +SET(LIBICONV_LIBS iconv) +FIND_LIBRARY(LIBICONV_LIBRARY NAMES ${LIBICONV_LIBS}) +MARK_AS_ADVANCED(LIBICONV_LIBRARY) + +FIND_PACKAGE_HANDLE_STANDARD_ARGS(LIBICONV REQUIRED_VARS LIBICONV_LIBRARY LIBICONV_INCLUDE_DIR) + +# Copy the result to output variables +IF(LIBICONV_FOUND) + SET(LIBICONV_LIBRARIES ${LIBICONV_LIBRARY}) + SET(LIBICONV_INCLUDE_DIRS ${LIBICONV_INCLUDE_DIR}) +ELSE(LIBICONV_FOUND) + SET(LIBICONV_LIBS) + SET(LIBICONV_LIBRARY) + SET(LIBICONV_LIBRARIES) + SET(LIBICONV_INCLUDE_DIR) + SET(LIBICONV_INCLUDE_DIRS) +ENDIF(LIBICONV_FOUND) diff --git a/CMake/FindSndfile.cmake b/CMake/FindSndfile.cmake new file mode 100644 index 00000000..b1d12148 --- /dev/null +++ b/CMake/FindSndfile.cmake @@ -0,0 +1,32 @@ +# Find sndfile library +# +# Released under BSD license +# +# SNDFILE_INCLUDE_DIRS - where to find sndfile.h, etc +# SNDFILE_LIBRARIES - Lists of libraries when using sndfile +# SNDFILE_FOUND - True if sndfile found + +INCLUDE(FindPackageHandleStandardArgs) + +# Look for the header file +FIND_PATH(SNDFILE_INCLUDE_DIR NAMES sndfile.h) +MARK_AS_ADVANCED(SNDFILE_INCLUDE_DIR) + +# Look for the library +SET(SNDFILE_LIBS sndfile) +FIND_LIBRARY(SNDFILE_LIBRARY NAMES ${SNDFILE_LIBS}) +MARK_AS_ADVANCED(SNDFILE_LIBRARY) + +FIND_PACKAGE_HANDLE_STANDARD_ARGS(SNDFILE REQUIRED_VARS SNDFILE_LIBRARY SNDFILE_INCLUDE_DIR) + +# Copy the result to output variables +IF(SNDFILE_FOUND) + SET(SNDFILE_LIBRARIES ${SNDFILE_LIBRARY}) + SET(SNDFILE_INCLUDE_DIRS ${SNDFILE_INCLUDE_DIR}) +ELSE(SNDFILE_FOUND) + SET(SNDFILE_LIBS) + SET(SNDFILE_LIBRARY) + SET(SNDFILE_LIBRARIES) + SET(SNDFILE_INCLUDE_DIR) + SET(SNDFILE_INCLUDE_DIRS) +ENDIF(SNDFILE_FOUND) diff --git a/CMake/FindWrap.cmake b/CMake/FindWrap.cmake new file mode 100644 index 00000000..5737e418 --- /dev/null +++ b/CMake/FindWrap.cmake @@ -0,0 +1,32 @@ +# Find wrap library +# +# Released under BSD license +# +# WRAP_INCLUDE_DIRS - where to find tcpd.h, etc +# WRAP_LIBRARIES - Lists of libraries when using libwrap +# WRAP_FOUND - True if wrap found + +INCLUDE(FindPackageHandleStandardArgs) + +# Look for the header file +FIND_PATH(WRAP_INCLUDE_DIR NAMES tcpd.h) +MARK_AS_ADVANCED(WRAP_INCLUDE_DIR) + +# Look for the library +SET(WRAP_LIBS wrap) +FIND_LIBRARY(WRAP_LIBRARY NAMES ${WRAP_LIBS}) +MARK_AS_ADVANCED(WRAP_LIBRARY) + +FIND_PACKAGE_HANDLE_STANDARD_ARGS(WRAP REQUIRED_VARS WRAP_LIBRARY WRAP_INCLUDE_DIR) + +# Copy the result to output variables +IF(WRAP_FOUND) + SET(WRAP_LIBRARIES ${WRAP_LIBRARY}) + SET(WRAP_INCLUDE_DIRS ${WRAP_INCLUDE_DIR}) +ELSE(WRAP_FOUND) + SET(WRAP_LIBS) + SET(WRAP_LIBRARY) + SET(WRAP_LIBRARIES) + SET(WRAP_INCLUDE_DIR) + SET(WRAP_INCLUDE_DIRS) +ENDIF(WRAP_FOUND) diff --git a/CMake/GenerateCMakeExports.cmake b/CMake/GenerateCMakeExports.cmake new file mode 100644 index 00000000..2cc3de4c --- /dev/null +++ b/CMake/GenerateCMakeExports.cmake @@ -0,0 +1,81 @@ +# This script creates files DCMTKTargets.cmake' and 'DCMTKConfigVersion.cmake' +# and 'DCMTKConfig.cmake'. These files are created within the build tree +# but also are installed with DCMTK. +# The files can be utilized (no matter whether they are installed or just +# located within the build tree) by external projects in order to use +# the related DCMTK build. +# In order to accomplish that, the files provide hints to the external project +# which libraries and executables are available, and which build options have +# been used to build them. The external project then uses the CMake +# find_package command in "CONFIG" mode in order to import the DCMTK package +# with help of these files. +# +# DCMTKTargets.cmake will contain list of available DCMTK executables and libs +# DCMTKConfigVersion.cmake provides checking of DCMTK version compatibility +# DCMTKConfig.cmake will contain options used to build this DCMTK package +# +# +# Get and store all executable targets to DCMTKTargets.cmake within build's main dir +GET_PROPERTY(DCMTK_EXECUTABLE_TARGETS GLOBAL PROPERTY DCMTK_EXECUTABLE_TARGETS) +EXPORT(TARGETS ${DCMTK_EXECUTABLE_TARGETS} APPEND FILE ${DCMTK_BUILD_CMKDIR}/DCMTKTargets.cmake) +# Get and store libraries to DCMTKTargets.cmake within the build's main dir +GET_PROPERTY(DCMTK_LIBRARY_TARGETS GLOBAL PROPERTY DCMTK_LIBRARY_TARGETS) +EXPORT(TARGETS ${DCMTK_LIBRARY_TARGETS} APPEND FILE ${DCMTK_BUILD_CMKDIR}/DCMTKTargets.cmake) + +# Create DCMTConfigVersion.cmake with basic DCMTK version information (build tree) +SET(DCMTK_CONFIG_VERSION ${DCMTK_BUILD_CMKDIR}/DCMTKConfigVersion.cmake) +WRITE_BASIC_PACKAGE_VERSION_FILE( + ${DCMTK_CONFIG_VERSION} + VERSION ${DCMTK_MAJOR_VERSION}.${DCMTK_MINOR_VERSION}.${DCMTK_BUILD_VERSION} + COMPATIBILITY SameMajorVersion) + +# Depending on whether we want to create the build tree or install tree +# version of DCMTKConfig.cmake, we need to use different paths (install +# destination but also include paths set within DCMTKConfig.cmake) since +# DCMTKConfig.cmake should only contain relative paths which differ for +# build and install tree versions of the file. + +# Case 1: Configure 'DCMTKConfig.cmake' for a build tree. +SET(DCMTK_CMKDIR_CONFIG ${DCMTK_BUILD_CMKDIR}) +# Collect include paths +SET(DCMTK_INCLUDE_DIR_CONFIGS + "SET_AND_CHECK(DCMTK_config_INCLUDE_DIR \"${DCMTK_BINARY_DIR}/config/include/dcmtk/config\")") +FOREACH(module ${DCMTK_MODULES}) + SET(DCMTK_INCLUDE_DIR_CONFIGS + "${DCMTK_INCLUDE_DIR_CONFIGS}\nSET_AND_CHECK(DCMTK_${module}_INCLUDE_DIR \"${DCMTK_SOURCE_DIR}/${module}/include/dcmtk/${module}\")") +ENDFOREACH(module) +SET(DCMTK_CONFIG_CODE "####### Expanded from \@DCMTK_CONFIG_CODE\@ #######\n") +SET(DCMTK_CONFIG_CODE "${DCMTK_CONFIG_CODE}list(APPEND DCMTK_INCLUDE_DIRS \"${DCMTK_BINARY_DIR}/config/include\")\n") +FOREACH(module ${DCMTK_MODULES}) + SET(DCMTK_CONFIG_CODE "${DCMTK_CONFIG_CODE}list(APPEND DCMTK_INCLUDE_DIRS \"${DCMTK_SOURCE_DIR}/${module}/include\")\n") +ENDFOREACH(module) +SET(DCMTK_CONFIG_CODE "${DCMTK_CONFIG_CODE}##################################################") +SET(dcmtk_config ${DCMTK_BUILD_CMKDIR}/DCMTKConfig.cmake) +# Actually configure file and write it to build's main directory +CONFIGURE_PACKAGE_CONFIG_FILE( + CMake/DCMTKConfig.cmake.in + ${dcmtk_config} + INSTALL_DESTINATION ${CMAKE_BINARY_DIR} + PATH_VARS DCMTK_CMKDIR_CONFIG DCMTK_INCLUDE_DIR_CONFIGS + NO_CHECK_REQUIRED_COMPONENTS_MACRO) + +# Case 2: Configure 'DCMTKConfig.cmake' for an install tree +SET(DCMTK_CMKDIR_CONFIG ${DCMTK_INSTALL_CMKDIR}) +# Collect include paths +SET(DCMTK_INCLUDE_DIR_CONFIGS + "SET_AND_CHECK(DCMTK_config_INCLUDE_DIR \"\${PACKAGE_PREFIX_DIR}/include/dcmtk/config\")") +FOREACH(module ${DCMTK_MODULES}) + SET(DCMTK_INCLUDE_DIR_CONFIGS + "${DCMTK_INCLUDE_DIR_CONFIGS}\nSET_AND_CHECK(DCMTK_${module}_INCLUDE_DIR \"\${PACKAGE_PREFIX_DIR}/include/dcmtk/${module}\")") +ENDFOREACH(module) +SET(DCMTK_CONFIG_CODE "####### Expanded from \@DCMTK_CONFIG_CODE\@ #######\n") +SET(DCMTK_CONFIG_CODE "${DCMTK_CONFIG_CODE}list(APPEND DCMTK_INCLUDE_DIRS \"\${PACKAGE_PREFIX_DIR}/include\")\n") +SET(DCMTK_CONFIG_CODE "${DCMTK_CONFIG_CODE}##################################################") +SET(dcmtk_install_config ${CMAKE_BINARY_DIR}/CMakeFiles/DCMTKConfig.cmake) +# Actually configure file and set rule to install it to installation subdir +CONFIGURE_PACKAGE_CONFIG_FILE( + CMake/DCMTKConfig.cmake.in + ${dcmtk_install_config} + INSTALL_DESTINATION ${CMAKE_INSTALL_PREFIX}/${DCMTK_INSTALL_CMKDIR} + PATH_VARS DCMTK_CMKDIR_CONFIG DCMTK_INCLUDE_DIR_CONFIGS + NO_CHECK_REQUIRED_COMPONENTS_MACRO) diff --git a/CMake/GenerateDCMTKConfigure.cmake b/CMake/GenerateDCMTKConfigure.cmake new file mode 100644 index 00000000..f8543a4a --- /dev/null +++ b/CMake/GenerateDCMTKConfigure.cmake @@ -0,0 +1,859 @@ +# Compiled-in dictionary support +IF(DCMTK_ENABLE_BUILTIN_DICTIONARY) + SET(ENABLE_BUILTIN_DICTIONARY 1) + MESSAGE(STATUS "Info: DCMTK will compile with built-in (compiled-in) dictionary") + # No extra variable needed since its only evaluated in CMake files +ELSE(DCMTK_ENABLE_BUILTIN_DICTIONARY) + SET(ENABLE_BUILTIN_DICTIONARY "") + MESSAGE(STATUS "Info: DCMTK will compile without built-in (compiled-in) dictionary") + # No extra variable needed since its only evaluated in CMake files +ENDIF(DCMTK_ENABLE_BUILTIN_DICTIONARY) + +# External dictionary support +IF(DCMTK_ENABLE_EXTERNAL_DICTIONARY) + SET(ENABLE_EXTERNAL_DICTIONARY 1) + MESSAGE(STATUS "Info: DCMTK will try to load external dictionary from default path on startup") +ELSE(DCMTK_ENABLE_EXTERNAL_DICTIONARY) + SET(ENABLE_EXTERNAL_DICTIONARY "") + MESSAGE(STATUS "Info: DCMTK will not try to load external dictionary from default path on startup") +ENDIF(DCMTK_ENABLE_EXTERNAL_DICTIONARY) + + +# Private tags +IF(DCMTK_ENABLE_PRIVATE_TAGS) + SET(ENABLE_PRIVATE_TAGS 1) + MESSAGE(STATUS "Info: DCMTK's builtin private dictionary support will be enabled") +ELSE(DCMTK_ENABLE_PRIVATE_TAGS) + SET(ENABLE_PRIVATE_TAGS "") + MESSAGE(STATUS "Info: DCMTK's builtin private dictionary support will be disabled") +ENDIF(DCMTK_ENABLE_PRIVATE_TAGS) + +# Thread support +IF(DCMTK_WITH_THREADS) + SET(WITH_THREADS 1) + MESSAGE(STATUS "Info: Thread support will be enabled") +ELSE(DCMTK_WITH_THREADS) + SET(WITH_THREADS "") + MESSAGE(STATUS "Info: Thread support will be disabled") +ENDIF(DCMTK_WITH_THREADS) + +# Wide char file I/O support +IF(DCMTK_WIDE_CHAR_FILE_IO_FUNCTIONS) + SET(WIDE_CHAR_FILE_IO_FUNCTIONS 1) + MESSAGE(STATUS "Info: Wide char file I/O functions will be enabled") +ELSE(DCMTK_WIDE_CHAR_FILE_IO_FUNCTIONS) + SET(WIDE_CHAR_FILE_IO_FUNCTIONS "") + MESSAGE(STATUS "Info: Wide char file I/O functions will be disabled") +ENDIF(DCMTK_WIDE_CHAR_FILE_IO_FUNCTIONS) + +# Wide char main function +IF(DCMTK_WIDE_CHAR_MAIN_FUNCTION) + SET(WIDE_CHAR_MAIN_FUNCTION 1) + MESSAGE(STATUS "Info: Wide char main function for command line tools will be enabled") +ELSE(DCMTK_WIDE_CHAR_MAIN_FUNCTION) + SET(WIDE_CHAR_MAIN_FUNCTION "") + MESSAGE(STATUS "Info: Wide char main function for command line tools will be disabled") +ENDIF(DCMTK_WIDE_CHAR_MAIN_FUNCTION) + +# Standard C++ headers (currently hard-coded) +#IF(VTK_USE_ANSI_STDLIB) + SET(USE_STD_CXX_INCLUDES 1) +#ELSE(VTK_USE_ANSI_STDLIB) +# SET(USE_STD_CXX_INCLUDES "") +#ENDIF(VTK_USE_ANSI_STDLIB) + +# Configure file + +# Windows being windows, it lies about its processor type to 32 bit binaries +SET(SYSTEM_PROCESSOR "$ENV{PROCESSOR_ARCHITEW6432}") +IF(NOT SYSTEM_PROCESSOR) + SET(SYSTEM_PROCESSOR "${CMAKE_SYSTEM_PROCESSOR}") +ENDIF(NOT SYSTEM_PROCESSOR) +# CMake doesn't provide a configure-style system type string +SET(CANONICAL_HOST_TYPE "${SYSTEM_PROCESSOR}-${CMAKE_SYSTEM_NAME}") +DCMTK_UNSET(SYSTEM_PROCESSOR) + +# Configure dictionary path and install prefix +IF(WIN32 AND NOT CYGWIN AND NOT MINGW) + # Set DCMTK_PREFIX needed within some code. Be sure that all / are replaced by \\. + SET(DCMTK_PREFIX "${CMAKE_INSTALL_PREFIX}") + STRING(REGEX REPLACE "/" "\\\\\\\\" DCMTK_PREFIX "${DCMTK_PREFIX}") + # Set path and multiple path separator being used in dictionary code etc. + SET(PATH_SEPARATOR "\\\\") + SET(ENVIRONMENT_PATH_SEPARATOR ";") + # Set dictionary path to the data dir inside install main dir (prefix) + IF(DCMTK_ENABLE_EXTERNAL_DICTIONARY) + SET(DCM_DICT_DEFAULT_PATH "${DCMTK_PREFIX}\\\\${DCMTK_INSTALL_DATDIR}\\\\dicom.dic") + # If private dictionary should be utilized, add it to default dictionary path. + IF(ENABLE_PRIVATE_TAGS) + SET(DCM_DICT_DEFAULT_PATH "${DCM_DICT_DEFAULT_PATH};${DCMTK_PREFIX}\\\\${DCMTK_INSTALL_DATDIR}\\\\private.dic") + ENDIF(ENABLE_PRIVATE_TAGS) + # Again, for Windows strip all / from path and replace it with \\. + STRING(REGEX REPLACE "/" "\\\\\\\\" DCM_DICT_DEFAULT_PATH "${DCM_DICT_DEFAULT_PATH}") + ELSE(DCMTK_ENABLE_EXTERNAL_DICTIONARY) + SET(DCM_DICT_DEFAULT_PATH "") + ENDIF(DCMTK_ENABLE_EXTERNAL_DICTIONARY) + # Set default directory for configuration and support data. + SET(DCMTK_DEFAULT_CONFIGURATION_DIR "") + SET(DCMTK_DEFAULT_SUPPORT_DATA_DIR "") +ELSE(WIN32 AND NOT CYGWIN AND NOT MINGW) + # Set DCMTK_PREFIX needed within some code. + SET(DCMTK_PREFIX "${CMAKE_INSTALL_PREFIX}") + # Set path and multiple path separator being used in dictionary code etc. + SET(PATH_SEPARATOR "/") + SET(ENVIRONMENT_PATH_SEPARATOR ":") + # Set dictionary path to the data dir inside install main dir (prefix). + if (DCMTK_ENABLE_EXTERNAL_DICTIONARY) + SET(DCM_DICT_DEFAULT_PATH "${DCMTK_PREFIX}/${DCMTK_INSTALL_DATDIR}/dicom.dic") + # If private dictionary should be utilized, add it to default dictionary path. + IF(ENABLE_PRIVATE_TAGS) + SET(DCM_DICT_DEFAULT_PATH "${DCM_DICT_DEFAULT_PATH}:${DCMTK_PREFIX}/${DCMTK_INSTALL_DATDIR}/private.dic") + ENDIF(ENABLE_PRIVATE_TAGS) + ELSE (DCMTK_ENABLE_EXTERNAL_DICTIONARY) + SET(DCM_DICT_DEFAULT_PATH "") + ENDIF (DCMTK_ENABLE_EXTERNAL_DICTIONARY) + # Set default directory for configuration and support data. + SET(DCMTK_DEFAULT_CONFIGURATION_DIR "${DCMTK_PREFIX}/${DCMTK_INSTALL_ETCDIR}/") + SET(DCMTK_DEFAULT_SUPPORT_DATA_DIR "${DCMTK_PREFIX}/${DCMTK_INSTALL_DATDIR}/") +ENDIF(WIN32 AND NOT CYGWIN AND NOT MINGW) + +# Check the sizes of various types +INCLUDE (CheckTypeSize) +CHECK_TYPE_SIZE("char" SIZEOF_CHAR) +CHECK_TYPE_SIZE("double" SIZEOF_DOUBLE) +CHECK_TYPE_SIZE("float" SIZEOF_FLOAT) +CHECK_TYPE_SIZE("int" SIZEOF_INT) +CHECK_TYPE_SIZE("long" SIZEOF_LONG) +CHECK_TYPE_SIZE("short" SIZEOF_SHORT) +CHECK_TYPE_SIZE("void*" SIZEOF_VOID_P) + +# Check for include files, libraries, and functions +INCLUDE(${CMAKE_ROOT}/Modules/CheckIncludeFileCXX.cmake) +INCLUDE(${CMAKE_ROOT}/Modules/CheckIncludeFiles.cmake) +INCLUDE(${CMAKE_ROOT}/Modules/CheckSymbolExists.cmake) +INCLUDE(${CMAKE_ROOT}/Modules/CheckFunctionExists.cmake) +INCLUDE(${CMAKE_ROOT}/Modules/CheckLibraryExists.cmake) +INCLUDE(${DCMTK_CMAKE_INCLUDE}CMake/CheckFunctionWithHeaderExists.cmake) + +CHECK_SYMBOL_EXISTS(__FUNCTION__ "" HAVE___FUNCTION___MACRO) +CHECK_SYMBOL_EXISTS(__PRETTY_FUNCTION__ "" HAVE___PRETTY_FUNCTION___MACRO) +CHECK_SYMBOL_EXISTS(__func__ "" HAVE___func___MACRO) + +# For Windows, hardcode these values to avoid long search times +IF(WIN32 AND NOT CYGWIN) + CHECK_INCLUDE_FILE_CXX("windows.h" HAVE_WINDOWS_H) + CHECK_INCLUDE_FILE_CXX("winsock.h" HAVE_WINSOCK_H) +ENDIF(WIN32 AND NOT CYGWIN) + + CHECK_INCLUDE_FILE_CXX("errno.h" HAVE_ERRNO_H) + CHECK_INCLUDE_FILE_CXX("dirent.h" HAVE_DIRENT_H) + CHECK_INCLUDE_FILE_CXX("fcntl.h" HAVE_FCNTL_H) + CHECK_INCLUDE_FILE_CXX("fstream" HAVE_FSTREAM) + CHECK_INCLUDE_FILE_CXX("fstream.h" HAVE_FSTREAM_H) + CHECK_INCLUDE_FILE_CXX("fnmatch.h" HAVE_FNMATCH_H) + CHECK_INCLUDE_FILE_CXX("float.h" HAVE_FLOAT_H) + CHECK_INCLUDE_FILE_CXX("grp.h" HAVE_GRP_H) + CHECK_INCLUDE_FILE_CXX("malloc.h" HAVE_MALLOC_H) + CHECK_INCLUDE_FILE_CXX("math.h" HAVE_MATH_H) + CHECK_INCLUDE_FILE_CXX("cmath" HAVE_CMATH) + CHECK_INCLUDE_FILE_CXX("ieeefp.h" HAVE_IEEEFP_H) + CHECK_INCLUDE_FILE_CXX("inttypes.h" HAVE_INTTYPES_H) + CHECK_INCLUDE_FILE_CXX("iomanip" HAVE_IOMANIP) + CHECK_INCLUDE_FILE_CXX("iomanip.h" HAVE_IOMANIP_H) + CHECK_INCLUDE_FILE_CXX("iostream" HAVE_IOSTREAM) + CHECK_INCLUDE_FILE_CXX("iostream.h" HAVE_IOSTREAM_H) + CHECK_INCLUDE_FILE_CXX("io.h" HAVE_IO_H) + CHECK_INCLUDE_FILE_CXX("iso646.h" HAVE_ISO646_H) + CHECK_INCLUDE_FILE_CXX("png.h" HAVE_LIBPNG_PNG_H) + CHECK_INCLUDE_FILE_CXX("limits.h" HAVE_LIMITS_H) + CHECK_INCLUDE_FILE_CXX("climits" HAVE_CLIMITS) + CHECK_INCLUDE_FILE_CXX("locale.h" HAVE_LOCALE_H) + CHECK_INCLUDE_FILE_CXX("ndir.h" HAVE_NDIR_H) + CHECK_INCLUDE_FILE_CXX("netdb.h" HAVE_NETDB_H) + CHECK_INCLUDE_FILE_CXX("new.h" HAVE_NEW_H) + CHECK_INCLUDE_FILE_CXX("pwd.h" HAVE_PWD_H) + CHECK_INCLUDE_FILE_CXX("semaphore.h" HAVE_SEMAPHORE_H) + CHECK_INCLUDE_FILE_CXX("setjmp.h" HAVE_SETJMP_H) + CHECK_INCLUDE_FILE_CXX("sstream" HAVE_SSTREAM) + CHECK_INCLUDE_FILE_CXX("sstream.h" HAVE_SSTREAM_H) + CHECK_INCLUDE_FILE_CXX("stat.h" HAVE_STAT_H) + CHECK_INCLUDE_FILE_CXX("stdbool.h" HAVE_STDBOOL_H) + CHECK_INCLUDE_FILE_CXX("stddef.h" HAVE_STDDEF_H) + CHECK_INCLUDE_FILE_CXX("cstddef" HAVE_CSTDDEF) + CHECK_INCLUDE_FILE_CXX("stdint.h" HAVE_STDINT_H) + CHECK_INCLUDE_FILE_CXX("cstdint" HAVE_CSTDINT) + CHECK_INCLUDE_FILE_CXX("stdio.h" HAVE_STDIO_H) + CHECK_INCLUDE_FILE_CXX("cstdio" HAVE_CSTDIO) + CHECK_INCLUDE_FILE_CXX("strings.h" HAVE_STRINGS_H) + CHECK_INCLUDE_FILE_CXX("string.h" HAVE_STRING_H) + CHECK_INCLUDE_FILE_CXX("strstream.h" HAVE_STRSTREAM_H) + CHECK_INCLUDE_FILE_CXX("strstream" HAVE_STRSTREAM) + CHECK_INCLUDE_FILE_CXX("strstrea.h" HAVE_STRSTREA_H) + CHECK_INCLUDE_FILE_CXX("synch.h" HAVE_SYNCH_H) + CHECK_INCLUDE_FILE_CXX("syslog.h" HAVE_SYSLOG_H) + CHECK_INCLUDE_FILE_CXX("sys/errno.h" HAVE_SYS_ERRNO_H) + CHECK_INCLUDE_FILE_CXX("sys/dir.h" HAVE_SYS_DIR_H) + CHECK_INCLUDE_FILE_CXX("sys/file.h" HAVE_SYS_FILE_H) + CHECK_INCLUDE_FILE_CXX("sys/ndir.h" HAVE_SYS_NDIR_H) + CHECK_INCLUDE_FILE_CXX("sys/param.h" HAVE_SYS_PARAM_H) + CHECK_INCLUDE_FILE_CXX("sys/resource.h" HAVE_SYS_RESOURCE_H) + CHECK_INCLUDE_FILE_CXX("sys/select.h" HAVE_SYS_SELECT_H) + CHECK_INCLUDE_FILE_CXX("sys/syscall.h" HAVE_SYS_SYSCALL_H) + CHECK_INCLUDE_FILE_CXX("sys/systeminfo.h" HAVE_SYS_SYSTEMINFO_H) + CHECK_INCLUDE_FILE_CXX("sys/time.h" HAVE_SYS_TIME_H) + CHECK_INCLUDE_FILE_CXX("sys/timeb.h" HAVE_SYS_TIMEB_H) + CHECK_INCLUDE_FILE_CXX("sys/types.h" HAVE_SYS_TYPES_H) + CHECK_INCLUDE_FILE_CXX("sys/utime.h" HAVE_SYS_UTIME_H) + CHECK_INCLUDE_FILE_CXX("sys/utsname.h" HAVE_SYS_UTSNAME_H) + CHECK_INCLUDE_FILE_CXX("sys/wait.h" HAVE_SYS_WAIT_H) + CHECK_INCLUDE_FILE_CXX("sys/socket.h" HAVE_SYS_SOCKET_H) + CHECK_INCLUDE_FILE_CXX("thread.h" HAVE_THREAD_H) + CHECK_INCLUDE_FILE_CXX("sys/stat.h" HAVE_SYS_STAT_H) + CHECK_INCLUDE_FILE_CXX("time.h" HAVE_TIME_H) + CHECK_INCLUDE_FILE_CXX("unistd.h" HAVE_UNISTD_H) + CHECK_INCLUDE_FILE_CXX("unix.h" HAVE_UNIX_H) + CHECK_INCLUDE_FILE_CXX("utime.h" HAVE_UTIME_H) + CHECK_INCLUDE_FILE_CXX("wchar.h" HAVE_WCHAR_H) + CHECK_INCLUDE_FILE_CXX("wctype.h" HAVE_WCTYPE_H) + CHECK_INCLUDE_FILE_CXX("alloca.h" HAVE_ALLOCA_H) + CHECK_INCLUDE_FILE_CXX("arpa/inet.h" HAVE_ARPA_INET_H) + CHECK_INCLUDE_FILE_CXX("ctype.h" HAVE_CTYPE_H) + CHECK_INCLUDE_FILE_CXX("memory.h" HAVE_MEMORY_H) + CHECK_INCLUDE_FILE_CXX("pthread.h" HAVE_PTHREAD_H) + CHECK_INCLUDE_FILE_CXX("libc.h" HAVE_LIBC_H) + CHECK_INCLUDE_FILE_CXX("stdlib.h" HAVE_STDLIB_H) + CHECK_INCLUDE_FILE_CXX("stdarg.h" HAVE_STDARG_H) + CHECK_INCLUDE_FILE_CXX("cstdarg" HAVE_CSTDARG) + CHECK_INCLUDE_FILE_CXX("signal.h" HAVE_SIGNAL_H) + CHECK_INCLUDE_FILE_CXX("fenv.h" HAVE_FENV_H) + + # This mimics the autoconf test. There are systems out there + # (e.g. FreeBSD and NeXT) where tcp.h can't be compiled on its own. + SET(TCP_H_DEPS "") + IF(HAVE_SYS_TYPES_H) + # This one is needed to make FreeBSD happy + SET(TCP_H_DEPS "sys/types.h") + ENDIF(HAVE_SYS_TYPES_H) + CHECK_INCLUDE_FILES("${TCP_H_DEPS};netinet/in_systm.h" HAVE_NETINET_IN_SYSTM_H) + IF(HAVE_NETINET_IN_SYSTM_H) + SET(TCP_H_DEPS "${TCP_H_DEPS};netinet/in_systm.h") + ENDIF(HAVE_NETINET_IN_SYSTM_H) + CHECK_INCLUDE_FILES("${TCP_H_DEPS};netinet/in.h" HAVE_NETINET_IN_H) + IF(HAVE_NETINET_IN_H) + SET(TCP_H_DEPS "${TCP_H_DEPS};netinet/in.h") + ENDIF(HAVE_NETINET_IN_H) + CHECK_INCLUDE_FILES("${TCP_H_DEPS};netinet/tcp.h" HAVE_NETINET_TCP_H) + + # There is no CMake macro to take care of these yet + + IF(WIN32 AND NOT CYGWIN AND NOT MINGW) + SET(HAVE_NO_TYPEDEF_SSIZE_T TRUE) + SET(HAVE_NO_TYPEDEF_PID_T TRUE) + ELSE(WIN32 AND NOT CYGWIN AND NOT MINGW) + SET(HAVE_NO_TYPEDEF_PID_T FALSE) + SET(HAVE_NO_TYPEDEF_SIZE_T FALSE) + IF(NOT ${HAVE_SYS_TYPES_H}) + SET(HAVE_NO_TYPEDEF_SSIZE_T TRUE) + ENDIF(NOT ${HAVE_SYS_TYPES_H}) + ENDIF(WIN32 AND NOT CYGWIN AND NOT MINGW) + + CHECK_FUNCTION_EXISTS(connect HAVE_CONNECT) + CHECK_FUNCTION_EXISTS(accept HAVE_ACCEPT) + CHECK_FUNCTION_EXISTS(access HAVE_ACCESS) + CHECK_FUNCTION_EXISTS(bcmp HAVE_BCMP) + CHECK_FUNCTION_EXISTS(bcopy HAVE_BCOPY) + CHECK_FUNCTION_EXISTS(bind HAVE_BIND) + CHECK_FUNCTION_EXISTS(bzero HAVE_BZERO) + CHECK_FUNCTION_EXISTS(cuserid HAVE_CUSERID) + CHECK_FUNCTION_EXISTS(_doprnt HAVE_DOPRNT) + CHECK_FUNCTION_EXISTS(finite HAVE_FINITE) + CHECK_FUNCTION_EXISTS(flock HAVE_FLOCK) + CHECK_FUNCTION_EXISTS(fork HAVE_FORK) + CHECK_FUNCTION_EXISTS(fseeko HAVE_FSEEKO) + CHECK_FUNCTION_EXISTS(ftime HAVE_FTIME) + CHECK_FUNCTION_EXISTS(getaddrinfo HAVE_GETADDRINFO) + CHECK_FUNCTION_EXISTS(getenv HAVE_GETENV) + CHECK_FUNCTION_EXISTS(geteuid HAVE_GETEUID) + CHECK_FUNCTION_EXISTS(getgrnam HAVE_GETGRNAM) + CHECK_FUNCTION_EXISTS(gethostbyname HAVE_GETHOSTBYNAME) + CHECK_FUNCTION_EXISTS(gethostbyname_r HAVE_GETHOSTBYNAME_R) + CHECK_FUNCTION_EXISTS(gethostbyaddr_r HAVE_GETHOSTBYADDR_R) + CHECK_FUNCTION_EXISTS(getgrnam_r HAVE_GETGRNAM_R) + CHECK_FUNCTION_EXISTS(getpwnam_r HAVE_GETPWNAM_R) + CHECK_FUNCTION_EXISTS(gethostname HAVE_GETHOSTNAME) + CHECK_FUNCTION_EXISTS(gethostid HAVE_GETHOSTID) + CHECK_FUNCTION_EXISTS(getlogin HAVE_GETLOGIN) + CHECK_FUNCTION_EXISTS(getpid HAVE_GETPID) + CHECK_FUNCTION_EXISTS(getpwnam HAVE_GETPWNAM) + CHECK_FUNCTION_EXISTS(getsockname HAVE_GETSOCKNAME) + CHECK_FUNCTION_EXISTS(getsockopt HAVE_GETSOCKOPT) + CHECK_FUNCTION_EXISTS(getuid HAVE_GETUID) + CHECK_FUNCTION_EXISTS(gmtime_r HAVE_GMTIME_R) + CHECK_FUNCTION_EXISTS(index HAVE_INDEX) + CHECK_FUNCTION_EXISTS(isinf HAVE_ISINF) + CHECK_FUNCTION_EXISTS(isnan HAVE_ISNAN) + CHECK_FUNCTION_EXISTS(itoa HAVE_ITOA) + CHECK_FUNCTION_EXISTS(listen HAVE_LISTEN) + CHECK_FUNCTION_EXISTS(localtime_r HAVE_LOCALTIME_R) + CHECK_FUNCTION_EXISTS(lockf HAVE_LOCKF) + CHECK_FUNCTION_EXISTS(lstat HAVE_LSTAT) + CHECK_FUNCTION_EXISTS(malloc_debug HAVE_MALLOC_DEBUG) + CHECK_FUNCTION_EXISTS(mbstowcs HAVE_MBSTOWCS) + CHECK_FUNCTION_EXISTS(wcstombs HAVE_WCSTOMBS) + CHECK_FUNCTION_EXISTS(memcmp HAVE_MEMCMP) + CHECK_FUNCTION_EXISTS(memcpy HAVE_MEMCPY) + CHECK_FUNCTION_EXISTS(memmove HAVE_MEMMOVE) + CHECK_FUNCTION_EXISTS(memset HAVE_MEMSET) + CHECK_FUNCTION_EXISTS(mkstemp HAVE_MKSTEMP) + CHECK_FUNCTION_EXISTS(mktemp HAVE_MKTEMP) + CHECK_FUNCTION_EXISTS(rindex HAVE_RINDEX) + CHECK_FUNCTION_EXISTS(select HAVE_SELECT) + CHECK_FUNCTION_EXISTS(setsockopt HAVE_SETSOCKOPT) + CHECK_FUNCTION_EXISTS(setuid HAVE_SETUID) + CHECK_FUNCTION_EXISTS(sleep HAVE_SLEEP) + CHECK_FUNCTION_EXISTS(socket HAVE_SOCKET) + CHECK_FUNCTION_EXISTS(stat HAVE_STAT) + CHECK_FUNCTION_EXISTS(strchr HAVE_STRCHR) + CHECK_FUNCTION_EXISTS(strdup HAVE_STRDUP) + CHECK_FUNCTION_EXISTS(strerror HAVE_STRERROR) + CHECK_FUNCTION_EXISTS(strlcat HAVE_STRLCAT) + CHECK_FUNCTION_EXISTS(strlcpy HAVE_STRLCPY) + CHECK_FUNCTION_EXISTS(strstr HAVE_STRSTR) + CHECK_FUNCTION_EXISTS(strtoul HAVE_STRTOUL) + CHECK_FUNCTION_EXISTS(sysinfo HAVE_SYSINFO) + CHECK_FUNCTION_EXISTS(tempnam HAVE_TEMPNAM) + CHECK_FUNCTION_EXISTS(tmpnam HAVE_TMPNAM) + CHECK_FUNCTION_EXISTS(uname HAVE_UNAME) + CHECK_FUNCTION_EXISTS(usleep HAVE_USLEEP) + CHECK_FUNCTION_EXISTS(_vsnprintf_s HAVE__VSNPRINTF_S) + CHECK_FUNCTION_EXISTS(vfprintf_s HAVE_VFPRINTF_S) + CHECK_FUNCTION_EXISTS(vprintf HAVE_VPRINTF) + CHECK_FUNCTION_EXISTS(vsnprintf HAVE_VSNPRINTF) + CHECK_FUNCTION_EXISTS(vsprintf_s HAVE_VSPRINTF_S) + CHECK_FUNCTION_EXISTS(wait3 HAVE_WAIT3) + CHECK_FUNCTION_EXISTS(waitpid HAVE_WAITPID) + CHECK_FUNCTION_EXISTS(_findfirst HAVE__FINDFIRST) + CHECK_FUNCTION_EXISTS(nanosleep HAVE_NANOSLEEP) + + SET(HEADERS) + + IF(HAVE_IO_H) + SET(HEADERS ${HEADERS} io.h) + ENDIF(HAVE_IO_H) + + IF(HAVE_IOSTREAM_H) + SET(HEADERS ${HEADERS} iostream.h) + ENDIF(HAVE_IOSTREAM_H) + + IF(HAVE_MATH_H) + SET(HEADERS ${HEADERS} math.h) + ENDIF(HAVE_MATH_H) + + IF(HAVE_CMATH) + SET(HEADERS ${HEADERS} cmath) + ENDIF(HAVE_CMATH) + + IF(HAVE_LIBC_H) + SET(HEADERS ${HEADERS} libc.h) + ENDIF(HAVE_LIBC_H) + + IF(HAVE_PTHREAD_H) + SET(HEADERS ${HEADERS} pthread.h) + ENDIF(HAVE_PTHREAD_H) + + IF(HAVE_UNISTD_H) + SET(HEADERS ${HEADERS} unistd.h) + ENDIF(HAVE_UNISTD_H) + + IF(HAVE_STDLIB_H) + SET(HEADERS ${HEADERS} stdlib.h) + ENDIF(HAVE_STDLIB_H) + + IF(HAVE_STDINT_H) + SET(HEADERS ${HEADERS} stdint.h) + ENDIF(HAVE_STDINT_H) + + IF(HAVE_STDDEF_H) + SET(HEADERS ${HEADERS} stddef.h) + ENDIF(HAVE_STDDEF_H) + + IF(HAVE_NETDB_H) + SET(HEADERS ${HEADERS} netdb.h) + ENDIF(HAVE_NETDB_H) + + IF(HAVE_SYS_FILE_H) + SET(HEADERS ${HEADERS} sys/file.h) + ENDIF(HAVE_SYS_FILE_H) + + IF(HAVE_STRING_H) + SET(HEADERS ${HEADERS} string.h) + ENDIF(HAVE_STRING_H) + + IF(HAVE_STRINGS_H) + SET(HEADERS ${HEADERS} strings.h) + ENDIF(HAVE_STRINGS_H) + + IF(HAVE_SYS_WAIT_H) + SET(HEADERS ${HEADERS} sys/wait.h) + ENDIF(HAVE_SYS_WAIT_H) + + IF(HAVE_SYS_TIME_H) + SET(HEADERS ${HEADERS} sys/time.h) + ENDIF(HAVE_SYS_TIME_H) + + IF(HAVE_SYS_RESOURCE_H) + SET(HEADERS ${HEADERS} sys/resource.h) + ENDIF(HAVE_SYS_RESOURCE_H) + + IF(HAVE_SYS_TYPES_H) + SET(HEADERS ${HEADERS} sys/types.h) + ENDIF(HAVE_SYS_TYPES_H) + + IF(HAVE_SYS_SOCKET_H) + SET(HEADERS ${HEADERS} sys/socket.h) + ENDIF(HAVE_SYS_SOCKET_H) + + IF(HAVE_STDARG_H) + SET(HEADERS ${HEADERS} stdarg.h) + ENDIF(HAVE_STDARG_H) + + IF(HAVE_STDIO_H) + SET(HEADERS ${HEADERS} stdio.h) + ENDIF(HAVE_STDIO_H) + + IF(HAVE_SYS_SELECT_H) + SET(HEADERS ${HEADERS} sys/select.h) + ENDIF(HAVE_SYS_SELECT_H) + + IF(HAVE_WINDOWS_H) + SET(HEADERS ${HEADERS} windows.h) + ENDIF(HAVE_WINDOWS_H) + + IF(HAVE_PWD_H) + SET(HEADERS ${HEADERS} pwd.h) + ENDIF(HAVE_PWD_H) + + IF(HAVE_SYS_SYSCALL_H) + SET(HEADERS ${HEADERS} sys/syscall.h) + ENDIF(HAVE_SYS_SYSCALL_H) + + IF(HAVE_WINSOCK_H) + SET(HEADERS ${HEADERS} winsock.h) + SET(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} ws2_32 netapi32 wsock32) + ENDIF(HAVE_WINSOCK_H) + + # std::vsnprintf and std::vsnprintf need the C++ version of the headers. + # We just assume they exist when the C version was found + SET(CXXHEADERS) + + IF(HAVE_CSTDIO) + SET(CXXHEADERS ${CXXHEADERS} cstdio) + ENDIF(HAVE_CSTDIO) + + IF(HAVE_CSTDARG) + SET(CXXHEADERS ${CXXHEADERS} cstdarg) + ENDIF(HAVE_CSTDARG) + + IF(HAVE_CSTDINT) + SET(CXXHEADERS ${CXXHEADERS} cstdint) + ENDIF(HAVE_CSTDINT) + + IF(HAVE_CSTDDEF) + SET(CXXHEADERS ${CXXHEADERS} cstddef) + ENDIF(HAVE_CSTDDEF) + + CHECK_FUNCTIONWITHHEADER_EXISTS(isinf "${HEADERS}" HAVE_PROTOTYPE_ISINF) + CHECK_FUNCTIONWITHHEADER_EXISTS(isnan "${HEADERS}" HAVE_PROTOTYPE_ISNAN) + CHECK_FUNCTIONWITHHEADER_EXISTS(finite "${HEADERS}" HAVE_PROTOTYPE_FINITE) + CHECK_FUNCTIONWITHHEADER_EXISTS(std::isinf "${HEADERS}" HAVE_PROTOTYPE_STD__ISINF) + CHECK_FUNCTIONWITHHEADER_EXISTS(std::isnan "${HEADERS}" HAVE_PROTOTYPE_STD__ISNAN) + CHECK_FUNCTIONWITHHEADER_EXISTS(std::finite "${HEADERS}" HAVE_PROTOTYPE_STD__FINITE) + CHECK_FUNCTIONWITHHEADER_EXISTS(flock "${HEADERS}" HAVE_PROTOTYPE_FLOCK) + CHECK_FUNCTIONWITHHEADER_EXISTS(gethostbyname "${HEADERS}" HAVE_PROTOTYPE_GETHOSTBYNAME) + CHECK_FUNCTIONWITHHEADER_EXISTS(gethostbyname_r "${HEADERS}" HAVE_PROTOTYPE_GETHOSTBYNAME_R) + CHECK_FUNCTIONWITHHEADER_EXISTS(gethostid "${HEADERS}" HAVE_PROTOTYPE_GETHOSTID) + CHECK_FUNCTIONWITHHEADER_EXISTS(bzero "${HEADERS}" HAVE_PROTOTYPE_BZERO) + CHECK_FUNCTIONWITHHEADER_EXISTS(gethostname "${HEADERS}" HAVE_PROTOTYPE_GETHOSTNAME) + CHECK_FUNCTIONWITHHEADER_EXISTS(waitpid "${HEADERS}" HAVE_PROTOTYPE_WAITPID) + CHECK_FUNCTIONWITHHEADER_EXISTS(wait3 "${HEADERS}" HAVE_PROTOTYPE_WAIT3) + CHECK_FUNCTIONWITHHEADER_EXISTS(usleep "${HEADERS}" HAVE_PROTOTYPE_USLEEP) + CHECK_FUNCTIONWITHHEADER_EXISTS(accept "${HEADERS}" HAVE_PROTOTYPE_ACCEPT) + CHECK_FUNCTIONWITHHEADER_EXISTS(bind "${HEADERS}" HAVE_PROTOTYPE_BIND) + CHECK_FUNCTIONWITHHEADER_EXISTS(getsockname "${HEADERS}" HAVE_PROTOTYPE_GETSOCKNAME) + CHECK_FUNCTIONWITHHEADER_EXISTS(getsockopt "${HEADERS}" HAVE_PROTOTYPE_GETSOCKOPT) + CHECK_FUNCTIONWITHHEADER_EXISTS(getsockname "${HEADERS}" HAVE_PROTOTYPE_GETSOCKNAME) + CHECK_FUNCTIONWITHHEADER_EXISTS(setsockopt "${HEADERS}" HAVE_PROTOTYPE_SETSOCKOPT) + CHECK_FUNCTIONWITHHEADER_EXISTS(socket "${HEADERS}" HAVE_PROTOTYPE_SOCKET) + CHECK_FUNCTIONWITHHEADER_EXISTS(listen "${HEADERS}" HAVE_PROTOTYPE_LISTEN) + CHECK_FUNCTIONWITHHEADER_EXISTS(std::vfprintf "${CXXHEADERS}" HAVE_PROTOTYPE_STD__VFPRINTF) + CHECK_FUNCTIONWITHHEADER_EXISTS(std::vsnprintf "${CXXHEADERS}" HAVE_PROTOTYPE_STD__VSNPRINTF) + CHECK_FUNCTIONWITHHEADER_EXISTS(_stricmp "${HEADERS}" HAVE_PROTOTYPE__STRICMP) + # "definition" is an (exchangeable) identifier that is needed for successful compile test + CHECK_FUNCTIONWITHHEADER_EXISTS("socklen_t definition" "${HEADERS}" HAVE_DECLARATION_SOCKLEN_T) + CHECK_FUNCTIONWITHHEADER_EXISTS(gettimeofday "${HEADERS}" HAVE_PROTOTYPE_GETTIMEOFDAY) + CHECK_FUNCTIONWITHHEADER_EXISTS(connect "${HEADERS}" HAVE_PROTOTYPE_CONNECT) + CHECK_FUNCTIONWITHHEADER_EXISTS(mkstemp "${HEADERS}" HAVE_PROTOTYPE_MKSTEMP) + CHECK_FUNCTIONWITHHEADER_EXISTS(mktemp "${HEADERS}" HAVE_PROTOTYPE_MKTEMP) + CHECK_FUNCTIONWITHHEADER_EXISTS(select "${HEADERS}" HAVE_PROTOTYPE_SELECT) + CHECK_FUNCTIONWITHHEADER_EXISTS(strcasecmp "${HEADERS}" HAVE_PROTOTYPE_STRCASECMP) + CHECK_FUNCTIONWITHHEADER_EXISTS(strncasecmp "${HEADERS}" HAVE_PROTOTYPE_STRNCASECMP) + CHECK_FUNCTIONWITHHEADER_EXISTS(strerror_r "${HEADERS}" HAVE_PROTOTYPE_STRERROR_R) + CHECK_FUNCTIONWITHHEADER_EXISTS(SYS_gettid "${HEADERS}" HAVE_SYS_GETTID) + # "definition" is an (exchangeable) identifier that is needed for successful compile test + CHECK_FUNCTIONWITHHEADER_EXISTS("std::ios_base::openmode definition" "${HEADERS}" HAVE_DECLARATION_STD__IOS_BASE__OPENMODE) + CHECK_FUNCTIONWITHHEADER_EXISTS(pthread_rwlock_init "${HEADERS}" HAVE_PTHREAD_RWLOCK) + CHECK_FUNCTIONWITHHEADER_EXISTS("__sync_add_and_fetch((int*)0,0)" "${HEADERS}" HAVE_SYNC_ADD_AND_FETCH) + CHECK_FUNCTIONWITHHEADER_EXISTS("__sync_sub_and_fetch((int*)0,0)" "${HEADERS}" HAVE_SYNC_SUB_AND_FETCH) + CHECK_FUNCTIONWITHHEADER_EXISTS("InterlockedIncrement((long*)0)" "${HEADERS}" HAVE_INTERLOCKED_INCREMENT) + CHECK_FUNCTIONWITHHEADER_EXISTS("InterlockedDecrement((long*)0)" "${HEADERS}" HAVE_INTERLOCKED_DECREMENT) + CHECK_FUNCTIONWITHHEADER_EXISTS("_fpclassf(0.0f)" "${HEADERS}" HAVE_PROTOTYPE__FPCLASSF) + CHECK_FUNCTIONWITHHEADER_EXISTS(nanosleep "${HEADERS}" HAVE_PROTOTYPE_NANOSLEEP) + CHECK_FUNCTIONWITHHEADER_EXISTS("&passwd::pw_gecos" "${HEADERS}" HAVE_PASSWD_GECOS) + + # TODO: Uncommented because it seems not to make sense. Remove if there are no complaints. + #CHECK_LIBRARY_EXISTS(iostream "" "" HAVE_LIBIOSTREAM) + #CHECK_LIBRARY_EXISTS(nsl "" "" HAVE_LIBNSL) + #CHECK_LIBRARY_EXISTS(socket "" "" HAVE_LIBSOCKET) + + # Check for some type definitions needed by JasPer and defines them if necessary + # Even if not functions but types are looked for, the script works fine. + # "definition" is an (exchangeable) identifier that is needed for successful compile test + CHECK_FUNCTIONWITHHEADER_EXISTS("uchar definition" "${HEADERS}" HAVE_UCHAR_TYPEDEF) + CHECK_FUNCTIONWITHHEADER_EXISTS("ushort definition" "${HEADERS}" HAVE_USHORT_TYPEDEF) + CHECK_FUNCTIONWITHHEADER_EXISTS("uint definition" "${HEADERS}" HAVE_UINT_TYPEDEF) + CHECK_FUNCTIONWITHHEADER_EXISTS("ulong definition" "${HEADERS}" HAVE_ULONG_TYPEDEF) + CHECK_FUNCTIONWITHHEADER_EXISTS("longlong definition" "${HEADERS}" HAVE_LONGLONG) + CHECK_FUNCTIONWITHHEADER_EXISTS("ulonglong definition" "${HEADERS}" HAVE_ULONGLONG) + CHECK_FUNCTIONWITHHEADER_EXISTS("long long definition" "${HEADERS}" HAVE_LONG_LONG) + CHECK_FUNCTIONWITHHEADER_EXISTS("unsigned long long definition" "${HEADERS}" HAVE_UNSIGNED_LONG_LONG) + + # File access stuff + CHECK_FUNCTIONWITHHEADER_EXISTS("fpos64_t definition" "${HEADERS}" HAVE_FPOS64_T) + CHECK_FUNCTIONWITHHEADER_EXISTS("off64_t definition" "${HEADERS}" HAVE_OFF64_T) + # Check if the POSIX functions are available (even on Windows). They are preferred + # to the Microsoft specific functions on compilers like MinGW. + CHECK_FUNCTIONWITHHEADER_EXISTS("popen" "${HEADERS}" HAVE_POPEN) + CHECK_FUNCTIONWITHHEADER_EXISTS("pclose" "${HEADERS}" HAVE_PCLOSE) + + # Signal handling functions + CHECK_FUNCTIONWITHHEADER_EXISTS("sigjmp_buf definition" "setjmp.h" HAVE_SIGJMP_BUF) + +IF(DCMTK_WITH_OPENSSL) + # Check if OpenSSL provides the SSL_CTX_get0_param function + CHECK_FUNCTIONWITHHEADER_EXISTS("SSL_CTX_get0_param" "openssl/ssl.h" HAVE_SSL_CTX_GET0_PARAM ${OPENSSL_LIBS}) + CHECK_FUNCTIONWITHHEADER_EXISTS("RAND_egd" "openssl/rand.h" HAVE_RAND_EGD ${OPENSSL_LIBS}) +ENDIF(DCMTK_WITH_OPENSSL) + +# Tests that require a try-compile +INCLUDE(${DCMTK_CMAKE_INCLUDE}CMake/dcmtkTryCompile.cmake) +INCLUDE(${DCMTK_CMAKE_INCLUDE}CMake/dcmtkTryRun.cmake) + +IF(NOT DEFINED C_CHAR_UNSIGNED) + MESSAGE(STATUS "Checking signedness of char") + DCMTK_TRY_RUN(C_CHAR_SIGNED C_CHAR_SIGNED_COMPILED ${CMAKE_BINARY_DIR}/CMakeTmp/Char + ${DCMTK_SOURCE_DIR}/CMake/dcmtkTestCharSignedness.cc + COMPILE_OUTPUT_VARIABLE C_CHAR_SIGNED_COMPILE_OUTPUT) + IF(C_CHAR_SIGNED_COMPILED) + IF(C_CHAR_SIGNED) + MESSAGE(STATUS "Checking signedness of char -- signed") + SET(C_CHAR_UNSIGNED 0 CACHE INTERNAL "Whether char is unsigned.") + ELSE(C_CHAR_SIGNED) + MESSAGE(STATUS "Checking signedness of char -- unsigned") + SET(C_CHAR_UNSIGNED 1 CACHE INTERNAL "Whether char is unsigned.") + ENDIF(C_CHAR_SIGNED) + ELSE(C_CHAR_SIGNED_COMPILED) + MESSAGE(STATUS "Checking signedness of char -- failed") + ENDIF(C_CHAR_SIGNED_COMPILED) +ENDIF(NOT DEFINED C_CHAR_UNSIGNED) + +DCMTK_TRY_COMPILE(HAVE_CXX_BOOL "C++ type bool exists" + "// Minimal test for existence of 'bool' type. +void TestBool(bool) {} + +int main() +{ + TestBool(false); + TestBool(true); + return 0; +}") + +# Check for thread type +IF (HAVE_WINDOWS_H) + SET(HAVE_INT_TYPE_PTHREAD_T 1) +ELSE (HAVE_WINDOWS_H) + DCMTK_TRY_COMPILE(HAVE_INT_TYPE_PTHREAD_T "pthread_t is an integer type" + "// test to see if pthread_t is a pointer type or not + +#include + +int main () +{ + pthread_t p; + unsigned long l = p; + return 0; +}") + IF (NOT HAVE_INT_TYPE_PTHREAD_T) + SET(HAVE_POINTER_TYPE_PTHREAD_T 1 CACHE INTERNAL "Set if pthread_t is a pointer type") + ELSE (NOT HAVE_INT_TYPE_PTHREAD_T) + SET(HAVE_POINTER_TYPE_PTHREAD_T 0 CACHE INTERNAL "Set if pthread_t is a pointer type") + ENDIF (NOT HAVE_INT_TYPE_PTHREAD_T) +ENDIF(HAVE_WINDOWS_H) + +# Check if typename works properly. Only MSC6 really fails here. +DCMTK_TRY_COMPILE(HAVE_TYPENAME "typename works correctly" + " +template +type identical(type arg) +{ + return arg; +} + +template +typename type::a foo(typename type::a arg) +{ + // This one is the usage of \"typename\" that we are checking for. + // MSC6 refuses this one incorrectly. + return identical(arg); +} + +class test { +public: + typedef int a; +}; + +int main() +{ + return foo(0); +}") + +# Check if ENAMETOOLONG is defined. +DCMTK_TRY_COMPILE(HAVE_ENAMETOOLONG "ENAMETOOLONG is defined" + "#include + +int main() +{ + int value = ENAMETOOLONG; + return 0; +}") + +# Check if strerror_r returns a char* is defined. +DCMTK_TRY_COMPILE(HAVE_INT_STRERROR_R "strerror_r returns an int" + "#include + +int main() +{ + char *buf = 0; + int i = strerror_r(0, buf, 100); + return i; +}") +IF(HAVE_INT_STRERROR_R) + SET(HAVE_CHARP_STRERROR_R 0 CACHE INTERNAL "Set if strerror_r() returns a char*") +ELSE(HAVE_INT_STRERROR_R) + SET(HAVE_CHARP_STRERROR_R 1 CACHE INTERNAL "Set if strerror_r() returns a char*") +ENDIF(HAVE_INT_STRERROR_R) + +# Check if variable length arrays are supported. +DCMTK_TRY_COMPILE(HAVE_VLA "variable length arrays are supported" + "int main() +{ + int n = 42; + int foo[n]; + return 0; +}") + +# Check if std::ios::nocreate exists +DCMTK_TRY_COMPILE(HAVE_IOS_NOCREATE "std::ios::nocreate exists" + "#include + +using namespace std; + +int main() +{ + std::ifstream file(\"name\", std::ios::nocreate); + return 0; +}") + +# Check for explicit large file support +DCMTK_TRY_COMPILE(_LARGEFILE64_SOURCE "explicit large file support is available" + "#define _LARGEFILE64_SOURCE +#include + +using namespace std; + +int main() +{ + FILE *f = fopen64(\"name\", \"r\"); + return 0; +}") + +IF(WIN32) + # If someone can tell me how to convince TRY_COMPILE to link against winsock, + # we could use tests for these. Until then, here is what would be the result: + SET(HAVE_INTP_ACCEPT 1 CACHE INTERNAL "Set if socket functions accept an int* argument") + SET(HAVE_INTP_GETSOCKOPT 1 CACHE INTERNAL "Set if socket functions accept an int* argument") + SET(HAVE_INTP_SELECT 0 CACHE INTERNAL "Set if select() accepts an int* argument") +ELSE(WIN32) + # Check if socket functions accept an int* + DCMTK_TRY_COMPILE(HAVE_INTP_SOCKET, "socket functions accept an int* argument" + " +#ifdef __cplusplus +extern \"C\" { +#endif +#ifdef _WIN32 +/* Windows is pure evil */ +#include +#else +#include +#endif +#ifdef __cplusplus +} +#endif + +int main() +{ + int i; + struct sockaddr *addr = 0; + int addrlen = 0; + int optlen = 0; + + i = accept(1, addr, &addrlen); + i = getsockopt(0, 0, 0, 0, &optlen); + + return 0; +}") + IF(HAVE_INTP_SOCKET) + SET(HAVE_INTP_ACCEPT 1 CACHE INTERNAL "Set if socket functions accept an int* argument") + SET(HAVE_INTP_GETSOCKOPT 1 CACHE INTERNAL "Set if socket functions accept an int* argument") + ELSE(HAVE_INTP_SOCKET) + SET(HAVE_INTP_ACCEPT 0 CACHE INTERNAL "Set if socket functions accept an int* argument") + SET(HAVE_INTP_GETSOCKOPT 0 CACHE INTERNAL "Set if socket functions accept an int* argument") + ENDIF(HAVE_INTP_SOCKET) + + # Check if select() accepts an int* + DCMTK_TRY_COMPILE(HAVE_INTP_SELECT "select() accepts an int* argument" + " +#ifdef __cplusplus +extern \"C\" { +#endif +#ifdef _WIN32 +/* Windows is pure evil */ +#include +#else +#include +#endif +#ifdef __cplusplus +} +#endif + +int main() +{ + int i; + int fds = 0; + + i = select(1, &fds, &fds, &fds, 0); + + return 0; +} +") +ENDIF(WIN32) + +# Check for alignment query / specifier support +DCMTK_TRY_COMPILE(HAVE_GNU_ALIGNOF "__alignof__ is supported" + "int main() +{ + char c[__alignof__(int)]; + return 0; +}") + +DCMTK_TRY_COMPILE(HAVE_MS_ALIGNOF "__alignof is supported" + "int main() +{ + char c[__alignof(int)]; + return 0; +}") + +DCMTK_TRY_COMPILE(HAVE_ATTRIBUTE_ALIGNED "__attribute__((aligned)) is supported" + "int main() +{ + __attribute__((aligned(4))) char c[16]; + return 0; +}") + +DCMTK_TRY_COMPILE(ATTRIBUTE_ALIGNED_SUPPORTS_TEMPLATES "__attribute__((aligned)) supports templates" + "template +struct test { typedef T type __attribute__((aligned(4))); }; +int main() +{ + test::type i; + return 0; +}") + +DCMTK_TRY_COMPILE(ALIGNAS_SUPPORTS_TYPEDEFS "alignas supports typedefs" + "int main() +{ + typedef char type[16] alignas(4); + return 0; +}") + +DCMTK_TRY_COMPILE(HAVE_DECLSPEC_ALIGN "__declspec(align) is supported" + "int main() +{ + __declspec(align(4)) char c[16]; + return 0; +}") + +DCMTK_TRY_COMPILE(HAVE_DEFAULT_CONSTRUCTOR_DETECTION_VIA_SFINAE "the compiler supports default constructor detection via SFINAE" + "struct no_type {}; +struct yes_type {double d;}; +template +struct consume{}; +template +static yes_type sfinae(consume*); +template +static no_type sfinae(...); +struct test { test( int ); }; +int main() +{ + return sizeof(sfinae(0)) == sizeof(yes_type); +}") + +# Compile config/arith.cc and generate config/arith.h +FUNCTION(INSPECT_FUNDAMENTAL_ARITHMETIC_TYPES) + SET(ARITH_H_FILE ${DCMTK_BINARY_DIR}/config/include/dcmtk/config/arith.h) + IF(CMAKE_CROSSCOMPILING) + IF(WIN32) + UNIX_TO_WINE_PATH(ARITH_H_FILE ${ARITH_H_FILE}) + STRING(REPLACE "\\" "\\\\" ARITH_H_FILE ${ARITH_H_FILE}) + ELSEIF(ANDROID) + SET(ARITH_H_DESTINATION ${ARITH_H_FILE}) + SET(ARITH_H_FILE "${ANDROID_TEMPORARY_FILES_LOCATION}/arith.h") + ENDIF() + ENDIF(CMAKE_CROSSCOMPILING) + DCMTK_TRY_RUN( + RESULT COMPILED + ${DCMTK_BINARY_DIR}/CMakeTmp/Arith + ${DCMTK_SOURCE_DIR}/config/arith.cc + COMPILE_DEFINITIONS -I"${DCMTK_BINARY_DIR}/config/include" -I"${DCMTK_SOURCE_DIR}/ofstd/include" -I"${DCMTK_SOURCE_DIR}/ofstd/libsrc" + RUN_OUTPUT_VARIABLE OUTPUT + COMPILE_OUTPUT_VARIABLE CERR + ARGS \"${ARITH_H_FILE}\" + ) + IF(COMPILED) + IF(NOT RESULT) + MESSAGE(STATUS "${OUTPUT}") + IF(CMAKE_CROSSCOMPILING) + IF(ANDROID) + DCMTK_ANDROID_PULL(DCMTK_ANDROID_EMULATOR_INSTANCE ${ARITH_H_FILE} DESTINATION ${ARITH_H_DESTINATION}) + ENDIF() + ENDIF(CMAKE_CROSSCOMPILING) + ELSE(NOT RESULT) + MESSAGE(FATAL_ERROR "${OUTPUT}") + ENDIF(NOT RESULT) + ELSE(COMPILED) + MESSAGE(FATAL_ERROR "${CERR}") + ENDIF(COMPILED) +ENDFUNCTION(INSPECT_FUNDAMENTAL_ARITHMETIC_TYPES) + +IF(CMAKE_CROSSCOMPILING) + SET(DCMTK_CROSS_COMPILING ${CMAKE_CROSSCOMPILING}) +ENDIF(CMAKE_CROSSCOMPILING) diff --git a/CMake/android.toolchain.cmake b/CMake/android.toolchain.cmake new file mode 100644 index 00000000..94f7da4c --- /dev/null +++ b/CMake/android.toolchain.cmake @@ -0,0 +1,1812 @@ +# +# +# Copyright (C) 2015, OFFIS e.V. +# All rights reserved. See COPYRIGHT file for details. +# +# This software and supporting documentation were developed by +# +# OFFIS e.V. +# R&D Division Health +# Escherweg 2 +# D-26121 Oldenburg, Germany +# +# Author: Jan Schlamelcher +# +# Purpose: +# Detecting and inspecting any available Android NDK installation +# and contained toolchains. Setting the depending CMake variables +# appropriately based on the detection results and user settings. +# +# This file is based upon this Android toolchain file found on +# github: https://github.com/taka-no-me/android-cmake, +# originally released under this license: + +# Copyright (c) 2010-2011, Ethan Rublee +# Copyright (c) 2011-2014, Andrey Kamaev +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# 3. Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from this +# software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +# ------------------------------------------------------------------------------ +# Android CMake toolchain file, for use with the Android NDK r5-r9 +# Requires cmake 2.6.3 or newer (2.8.5 or newer is recommended). +# See home page: https://github.com/taka-no-me/android-cmake +# +# The file is maintained by the OpenCV project. The latest version can be get at +# http://code.opencv.org/projects/opencv/repository/revisions/master/changes/android/android.toolchain.cmake +# +# Usage Linux: +# $ export ANDROID_NDK=/absolute/path/to/the/android-ndk +# $ mkdir build && cd build +# $ cmake -DCMAKE_TOOLCHAIN_FILE=path/to/the/android.toolchain.cmake .. +# $ make -j8 +# +# Usage Linux (using standalone toolchain): +# $ export ANDROID_STANDALONE_TOOLCHAIN=/absolute/path/to/android-toolchain +# $ mkdir build && cd build +# $ cmake -DCMAKE_TOOLCHAIN_FILE=path/to/the/android.toolchain.cmake .. +# $ make -j8 +# +# Usage Windows: +# You need native port of make to build your project. +# Android NDK r7 (or newer) already has make.exe on board. +# For older NDK you have to install it separately. +# For example, this one: http://gnuwin32.sourceforge.net/packages/make.htm +# +# $ SET ANDROID_NDK=C:\absolute\path\to\the\android-ndk +# $ mkdir build && cd build +# $ cmake.exe -G"MinGW Makefiles" +# -DCMAKE_TOOLCHAIN_FILE=path\to\the\android.toolchain.cmake +# -DCMAKE_MAKE_PROGRAM="%ANDROID_NDK%\prebuilt\windows\bin\make.exe" .. +# $ cmake.exe --build . +# +# +# Options (can be set as cmake parameters: -D=): +# ANDROID_NDK=/opt/android-ndk - path to the NDK root. +# Can be set as environment variable. Can be set only at first cmake run. +# +# ANDROID_STANDALONE_TOOLCHAIN=/opt/android-toolchain - path to the +# standalone toolchain. This option is not used if full NDK is found +# (ignored if ANDROID_NDK is set). +# Can be set as environment variable. Can be set only at first cmake run. +# +# ANDROID_ABI=armeabi-v7a - specifies the target Application Binary +# Interface (ABI). This option nearly matches to the APP_ABI variable +# used by ndk-build tool from Android NDK. +# +# Possible targets are: +# "armeabi" - matches to the NDK ABI with the same name. +# See ${ANDROID_NDK}/docs/CPU-ARCH-ABIS.html for the documentation. +# "armeabi-v7a" - matches to the NDK ABI with the same name. +# See ${ANDROID_NDK}/docs/CPU-ARCH-ABIS.html for the documentation. +# "armeabi-v7a with NEON" - same as armeabi-v7a, but +# sets NEON as floating-point unit +# "armeabi-v7a with VFPV3" - same as armeabi-v7a, but +# sets VFPV3 as floating-point unit (has 32 registers instead of 16). +# "armeabi-v6 with VFP" - tuned for ARMv6 processors having VFP. +# "x86" - matches to the NDK ABI with the same name. +# See ${ANDROID_NDK}/docs/CPU-ARCH-ABIS.html for the documentation. +# "mips" - matches to the NDK ABI with the same name. +# See ${ANDROID_NDK}/docs/CPU-ARCH-ABIS.html for the documentation. +# +# ANDROID_NATIVE_API_LEVEL=android-8 - level of Android API compile for. +# Option is read-only when standalone toolchain is used. +# +# ANDROID_TOOLCHAIN_NAME=arm-linux-androideabi-4.6 - the name of compiler +# toolchain to be used. The list of possible values depends on the NDK +# version. For NDK r8c the possible values are: +# +# * arm-linux-androideabi-4.4.3 +# * arm-linux-androideabi-4.6 +# * arm-linux-androideabi-clang3.1 +# * mipsel-linux-android-4.4.3 +# * mipsel-linux-android-4.6 +# * mipsel-linux-android-clang3.1 +# * x86-4.4.3 +# * x86-4.6 +# * x86-clang3.1 +# +# ANDROID_FORCE_ARM_BUILD=OFF - set ON to generate 32-bit ARM instructions +# instead of Thumb. Is not available for "x86" (inapplicable) and +# "armeabi-v6 with VFP" (is forced to be ON) ABIs. +# +# ANDROID_NO_UNDEFINED=ON - set ON to show all undefined symbols as linker +# errors even if they are not used. +# +# ANDROID_SO_UNDEFINED=OFF - set ON to allow undefined symbols in shared +# libraries. Automatically turned for NDK r5x and r6x due to GLESv2 +# problems. +# +# LIBRARY_OUTPUT_PATH_ROOT=${CMAKE_BINARY_DIR} - where to output binary +# files. See additional details below. +# +# ANDROID_SET_OBSOLETE_VARIABLES=ON - if set, then toolchain defines some +# obsolete variables which were used by previous versions of this file for +# backward compatibility. +# +# ANDROID_STL=gnustl_static - specify the runtime to use. +# +# Possible values are: +# none -> Do not configure the runtime. +# system -> Use the default minimal system C++ runtime library. +# Implies -fno-rtti -fno-exceptions. +# Is not available for standalone toolchain. +# system_re -> Use the default minimal system C++ runtime library. +# Implies -frtti -fexceptions. +# Is not available for standalone toolchain. +# gabi++_static -> Use the GAbi++ runtime as a static library. +# Implies -frtti -fno-exceptions. +# Available for NDK r7 and newer. +# Is not available for standalone toolchain. +# gabi++_shared -> Use the GAbi++ runtime as a shared library. +# Implies -frtti -fno-exceptions. +# Available for NDK r7 and newer. +# Is not available for standalone toolchain. +# stlport_static -> Use the STLport runtime as a static library. +# Implies -fno-rtti -fno-exceptions for NDK before r7. +# Implies -frtti -fno-exceptions for NDK r7 and newer. +# Is not available for standalone toolchain. +# stlport_shared -> Use the STLport runtime as a shared library. +# Implies -fno-rtti -fno-exceptions for NDK before r7. +# Implies -frtti -fno-exceptions for NDK r7 and newer. +# Is not available for standalone toolchain. +# gnustl_static -> Use the GNU STL as a static library. +# Implies -frtti -fexceptions. +# gnustl_shared -> Use the GNU STL as a shared library. +# Implies -frtti -fno-exceptions. +# Available for NDK r7b and newer. +# Silently degrades to gnustl_static if not available. +# +# ANDROID_STL_FORCE_FEATURES=ON - turn rtti and exceptions support based on +# chosen runtime. If disabled, then the user is responsible for settings +# these options. +# +# What?: +# android-cmake toolchain searches for NDK/toolchain in the following order: +# ANDROID_NDK - cmake parameter +# ANDROID_NDK - environment variable +# ANDROID_STANDALONE_TOOLCHAIN - cmake parameter +# ANDROID_STANDALONE_TOOLCHAIN - environment variable +# ANDROID_NDK - default locations +# ANDROID_STANDALONE_TOOLCHAIN - default locations +# +# Make sure to do the following in your scripts: +# SET( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${my_cxx_flags}" ) +# SET( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${my_cxx_flags}" ) +# The flags will be prepopulated with critical flags, so don't loose them. +# Also be aware that toolchain also sets configuration-specific compiler +# flags and linker flags. +# +# ANDROID and BUILD_ANDROID will be set to true, you may test any of these +# variables to make necessary Android-specific configuration changes. +# +# Also ARMEABI or ARMEABI_V7A or X86 or MIPS will be set true, mutually +# exclusive. NEON option will be set true if VFP is set to NEON. +# +# LIBRARY_OUTPUT_PATH_ROOT should be set in cache to determine where Android +# libraries will be installed. +# Default is ${CMAKE_BINARY_DIR}, and the android libs will always be +# under the ${LIBRARY_OUTPUT_PATH_ROOT}/libs/${ANDROID_NDK_ABI_NAME} +# (depending on the target ABI). This is convenient for Android packaging. +# +# Change Log: +# - initial version December 2010 +# - April 2011 +# [+] added possibility to build with NDK (without standalone toolchain) +# [+] support cross-compilation on Windows (native, no cygwin support) +# [+] added compiler option to force "char" type to be signed +# [+] added toolchain option to compile to 32-bit ARM instructions +# [+] added toolchain option to disable SWIG search +# [+] added platform "armeabi-v7a with VFPV3" +# [~] ARM_TARGETS renamed to ARM_TARGET +# [+] EXECUTABLE_OUTPUT_PATH is set by toolchain (required on Windows) +# [~] Fixed bug with ANDROID_API_LEVEL variable +# [~] turn off SWIG search if it is not found first time +# - May 2011 +# [~] ANDROID_LEVEL is renamed to ANDROID_API_LEVEL +# [+] ANDROID_API_LEVEL is detected by toolchain if not specified +# [~] added guard to prevent changing of output directories on the first +# cmake pass +# [~] toolchain exits with error if ARM_TARGET is not recognized +# - June 2011 +# [~] default NDK path is updated for version r5c +# [+] variable CMAKE_SYSTEM_PROCESSOR is set based on ARM_TARGET +# [~] toolchain install directory is added to linker paths +# [-] removed SWIG-related stuff from toolchain +# [+] added macro find_host_package, find_host_program to search +# packages/programs on the host system +# [~] fixed path to STL library +# - July 2011 +# [~] fixed options caching +# [~] search for all supported NDK versions +# [~] allowed spaces in NDK path +# - September 2011 +# [~] updated for NDK r6b +# - November 2011 +# [*] rewritten for NDK r7 +# [+] x86 toolchain support (experimental) +# [+] added "armeabi-v6 with VFP" ABI for ARMv6 processors. +# [~] improved compiler and linker flags management +# [+] support different build flags for Release and Debug configurations +# [~] by default compiler flags the same as used by ndk-build (but only +# where reasonable) +# [~] ANDROID_NDK_TOOLCHAIN_ROOT is split to ANDROID_STANDALONE_TOOLCHAIN +# and ANDROID_TOOLCHAIN_ROOT +# [~] ARM_TARGET is renamed to ANDROID_ABI +# [~] ARMEABI_NDK_NAME is renamed to ANDROID_NDK_ABI_NAME +# [~] ANDROID_API_LEVEL is renamed to ANDROID_NATIVE_API_LEVEL +# - January 2012 +# [+] added stlport_static support (experimental) +# [+] added special check for cygwin +# [+] filtered out hidden files (starting with .) while globbing inside NDK +# [+] automatically applied GLESv2 linkage fix for NDK revisions 5-6 +# [+] added ANDROID_GET_ABI_RAWNAME to get NDK ABI names by CMake flags +# - February 2012 +# [+] updated for NDK r7b +# [~] fixed cmake try_compile() command +# [~] Fix for missing install_name_tool on OS X +# - March 2012 +# [~] fixed incorrect C compiler flags +# [~] fixed CMAKE_SYSTEM_PROCESSOR change on ANDROID_ABI change +# [+] improved toolchain loading speed +# [+] added assembler language support (.S) +# [+] allowed preset search paths and extra search suffixes +# - April 2012 +# [+] updated for NDK r7c +# [~] fixed most of problems with compiler/linker flags and caching +# [+] added option ANDROID_FUNCTION_LEVEL_LINKING +# - May 2012 +# [+] updated for NDK r8 +# [+] added mips architecture support +# - August 2012 +# [+] updated for NDK r8b +# [~] all intermediate files generated by toolchain are moved to CMakeFiles +# [~] libstdc++ and libsupc are removed from explicit link libraries +# [+] added CCache support (via NDK_CCACHE environment or cmake variable) +# [+] added gold linker support for NDK r8b +# [~] fixed mips linker flags for NDK r8b +# - September 2012 +# [+] added NDK release name detection (see ANDROID_NDK_RELEASE) +# [+] added support for all C++ runtimes from NDK +# (system, gabi++, stlport, gnustl) +# [+] improved warnings on known issues of NDKs +# [~] use gold linker as default if available (NDK r8b) +# [~] globally turned off rpath +# [~] compiler options are aligned with NDK r8b +# - October 2012 +# [~] fixed C++ linking: explicitly link with math library (OpenCV #2426) +# - November 2012 +# [+] updated for NDK r8c +# [+] added support for clang compiler +# - December 2012 +# [+] suppress warning about unused CMAKE_TOOLCHAIN_FILE variable +# [+] adjust API level to closest compatible as NDK does +# [~] fixed ccache full path search +# [+] updated for NDK r8d +# [~] compiler options are aligned with NDK r8d +# - March 2013 +# [+] updated for NDK r8e (x86 version) +# [+] support x86_64 version of NDK +# - April 2013 +# [+] support non-release NDK layouts (from Linaro git and Android git) +# [~] automatically detect if explicit link to crtbegin_*.o is needed +# - June 2013 +# [~] fixed stl include path for standalone toolchain made by NDK >= r8c +# - July 2013 +# [+] updated for NDK r9 +# - November 2013 +# [+] updated for NDK r9b +# - December 2013 +# [+] updated for NDK r9c +# - January 2014 +# [~] fix copying of shared STL +# - April 2014 +# [+] updated for NDK r9d +# ------------------------------------------------------------------------------ + +cmake_minimum_required( VERSION 2.8.3 ) +if( ${CMAKE_VERSION} VERSION_GREATER 3.1 OR ${CMAKE_VERSION} VERSION_EQUAL 3.1 ) + cmake_policy( SET CMP0054 NEW ) +endif() + +if( DEFINED CMAKE_CROSSCOMPILING ) + # subsequent toolchain loading is not really needed + return() +endif() + +if( CMAKE_TOOLCHAIN_FILE ) + # touch toolchain variable only to suppress "unused variable" warning +endif() + +get_property( _CMAKE_IN_TRY_COMPILE GLOBAL PROPERTY IN_TRY_COMPILE ) +if( _CMAKE_IN_TRY_COMPILE ) + if( NOT ANDROID_TOOLCHAIN_CONFIG_FILE ) + set( ANDROID_TOOLCHAIN_CONFIG_FILE "${CMAKE_BINARY_DIR}/../android.toolchain.config.cmake" ) + endif() + include( "${ANDROID_TOOLCHAIN_CONFIG_FILE}" ) +endif() + +# this one is important +set( CMAKE_SYSTEM_NAME Linux ) +# this one not so much +set( CMAKE_SYSTEM_VERSION 1 ) + +# rpath makes low sense for Android +set( CMAKE_SKIP_RPATH TRUE CACHE BOOL "If set, runtime paths are not added when using shared libraries." ) + +set( ANDROID_SUPPORTED_NDK_VERSIONS ${ANDROID_EXTRA_NDK_VERSIONS} -r9d -r9c -r9b -r9 -r8e -r8d -r8c -r8b -r8 -r7c -r7b -r7 -r6b -r6 -r5c -r5b -r5 "" ) +if(NOT DEFINED ANDROID_NDK_SEARCH_PATHS) + if( CMAKE_HOST_WIN32 ) + file( TO_CMAKE_PATH "$ENV{PROGRAMFILES}" ANDROID_NDK_SEARCH_PATHS ) + set( ANDROID_NDK_SEARCH_PATHS "${ANDROID_NDK_SEARCH_PATHS}/android-ndk" "$ENV{SystemDrive}/NVPACK/android-ndk" ) + else() + file( TO_CMAKE_PATH "$ENV{HOME}" ANDROID_NDK_SEARCH_PATHS ) + set( ANDROID_NDK_SEARCH_PATHS /opt/android-ndk "${ANDROID_NDK_SEARCH_PATHS}/NVPACK/android-ndk" ) + endif() +endif() +if(NOT DEFINED ANDROID_STANDALONE_TOOLCHAIN_SEARCH_PATH) + set( ANDROID_STANDALONE_TOOLCHAIN_SEARCH_PATH /opt/android-toolchain ) +endif() + +set( ANDROID_SUPPORTED_ABIS_arm "armeabi-v7a;armeabi;armeabi-v7a with NEON;armeabi-v7a with VFPV3;armeabi-v6 with VFP" ) +set( ANDROID_SUPPORTED_ABIS_x86 "x86" ) +set( ANDROID_SUPPORTED_ABIS_mipsel "mips" ) + +set( ANDROID_DEFAULT_NDK_API_LEVEL 8 ) +set( ANDROID_DEFAULT_NDK_API_LEVEL_x86 9 ) +set( ANDROID_DEFAULT_NDK_API_LEVEL_mips 9 ) + + +macro( __LIST_FILTER listvar regex ) + if( ${listvar} ) + foreach( __val ${${listvar}} ) + if( __val MATCHES "${regex}" ) + list( REMOVE_ITEM ${listvar} "${__val}" ) + endif() + endforeach() + endif() +endmacro() + +macro( __INIT_VARIABLE var_name ) + set( __test_path 0 ) + foreach( __var ${ARGN} ) + if( __var STREQUAL "PATH" ) + set( __test_path 1 ) + break() + endif() + endforeach() + if( __test_path AND NOT EXISTS "${${var_name}}" ) + unset( ${var_name} CACHE ) + endif() + if( "${${var_name}}" STREQUAL "" ) + set( __values 0 ) + foreach( __var ${ARGN} ) + if( __var STREQUAL "VALUES" ) + set( __values 1 ) + elseif( NOT __var STREQUAL "PATH" ) + set( __obsolete 0 ) + if( __var MATCHES "^OBSOLETE_.*$" ) + string( REPLACE "OBSOLETE_" "" __var "${__var}" ) + set( __obsolete 1 ) + endif() + if( __var MATCHES "^ENV_.*$" ) + string( REPLACE "ENV_" "" __var "${__var}" ) + set( __value "$ENV{${__var}}" ) + elseif( DEFINED ${__var} ) + set( __value "${${__var}}" ) + else() + if( __values ) + set( __value "${__var}" ) + else() + set( __value "" ) + endif() + endif() + if( NOT "${__value}" STREQUAL "" ) + if( __test_path ) + if( EXISTS "${__value}" ) + file( TO_CMAKE_PATH "${__value}" ${var_name} ) + if( __obsolete AND NOT _CMAKE_IN_TRY_COMPILE ) + message( WARNING "Using value of obsolete variable ${__var} as initial value for ${var_name}. Please note, that ${__var} can be completely removed in future versions of the toolchain." ) + endif() + break() + endif() + else() + set( ${var_name} "${__value}" ) + if( __obsolete AND NOT _CMAKE_IN_TRY_COMPILE ) + message( WARNING "Using value of obsolete variable ${__var} as initial value for ${var_name}. Please note, that ${__var} can be completely removed in future versions of the toolchain." ) + endif() + break() + endif() + endif() + endif() + endforeach() + unset( __value ) + unset( __values ) + unset( __obsolete ) + elseif( __test_path ) + file( TO_CMAKE_PATH "${${var_name}}" ${var_name} ) + endif() + unset( __test_path ) +endmacro() + +macro( __DETECT_NATIVE_API_LEVEL _var _path ) + SET( __ndkApiLevelRegex "^[\t ]*#define[\t ]+__ANDROID_API__[\t ]+([0-9]+)[\t ]*$" ) + FILE( STRINGS ${_path} __apiFileContent REGEX "${__ndkApiLevelRegex}" ) + if( NOT __apiFileContent ) + message( SEND_ERROR "Could not get Android native API level. Probably you have specified invalid level value, or your copy of NDK/toolchain is broken." ) + endif() + string( REGEX REPLACE "${__ndkApiLevelRegex}" "\\1" ${_var} "${__apiFileContent}" ) + unset( __apiFileContent ) + unset( __ndkApiLevelRegex ) +endmacro() + +macro( __DETECT_TOOLCHAIN_MACHINE_NAME _var _root ) + if( EXISTS "${_root}" ) + file( GLOB __gccExePath RELATIVE "${_root}/bin/" "${_root}/bin/*-gcc${TOOL_OS_SUFFIX}" ) + __LIST_FILTER( __gccExePath "^[.].*" ) + list( LENGTH __gccExePath __gccExePathsCount ) + if( NOT __gccExePathsCount EQUAL 1 AND NOT _CMAKE_IN_TRY_COMPILE ) + message( WARNING "Could not determine machine name for compiler from ${_root}" ) + set( ${_var} "" ) + else() + get_filename_component( __gccExeName "${__gccExePath}" NAME_WE ) + string( REPLACE "-gcc" "" ${_var} "${__gccExeName}" ) + endif() + unset( __gccExePath ) + unset( __gccExePathsCount ) + unset( __gccExeName ) + else() + set( ${_var} "" ) + endif() +endmacro() + + +# fight against cygwin +set( ANDROID_FORBID_SYGWIN TRUE CACHE BOOL "Prevent cmake from working under cygwin and using cygwin tools") +mark_as_advanced( ANDROID_FORBID_SYGWIN ) +if( ANDROID_FORBID_SYGWIN ) + if( CYGWIN ) + message( FATAL_ERROR "Android NDK and android-cmake toolchain are not welcome Cygwin. It is unlikely that this cmake toolchain will work under cygwin. But if you want to try then you can set cmake variable ANDROID_FORBID_SYGWIN to FALSE and rerun cmake." ) + endif() + + if( CMAKE_HOST_WIN32 ) + # remove cygwin from PATH + set( __new_path "$ENV{PATH}") + __LIST_FILTER( __new_path "cygwin" ) + set(ENV{PATH} "${__new_path}") + unset(__new_path) + endif() +endif() + + +# detect current host platform +if( NOT DEFINED ANDROID_NDK_HOST_X64 AND (CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "amd64|x86_64|AMD64" OR CMAKE_HOST_APPLE) ) + set( ANDROID_NDK_HOST_X64 1 CACHE BOOL "Try to use 64-bit compiler toolchain" ) + mark_as_advanced( ANDROID_NDK_HOST_X64 ) +endif() + +set( TOOL_OS_SUFFIX "" ) +if( CMAKE_HOST_APPLE ) + set( ANDROID_NDK_HOST_SYSTEM_NAME "darwin-x86_64" ) + set( ANDROID_NDK_HOST_SYSTEM_NAME2 "darwin-x86" ) +elseif( CMAKE_HOST_WIN32 ) + set( ANDROID_NDK_HOST_SYSTEM_NAME "windows-x86_64" ) + set( ANDROID_NDK_HOST_SYSTEM_NAME2 "windows" ) + set( TOOL_OS_SUFFIX ".exe" ) +elseif( CMAKE_HOST_UNIX ) + set( ANDROID_NDK_HOST_SYSTEM_NAME "linux-x86_64" ) + set( ANDROID_NDK_HOST_SYSTEM_NAME2 "linux-x86" ) +else() + message( FATAL_ERROR "Cross-compilation on your platform is not supported by this cmake toolchain" ) +endif() + +if( NOT ANDROID_NDK_HOST_X64 ) + set( ANDROID_NDK_HOST_SYSTEM_NAME ${ANDROID_NDK_HOST_SYSTEM_NAME2} ) +endif() + +# see if we have path to Android NDK +__INIT_VARIABLE( ANDROID_NDK PATH ENV_ANDROID_NDK ) +if( NOT ANDROID_NDK ) + # see if we have path to Android standalone toolchain + __INIT_VARIABLE( ANDROID_STANDALONE_TOOLCHAIN PATH ENV_ANDROID_STANDALONE_TOOLCHAIN OBSOLETE_ANDROID_NDK_TOOLCHAIN_ROOT OBSOLETE_ENV_ANDROID_NDK_TOOLCHAIN_ROOT ) + + if( NOT ANDROID_STANDALONE_TOOLCHAIN ) + #try to find Android NDK in one of the the default locations + set( __ndkSearchPaths ) + foreach( __ndkSearchPath ${ANDROID_NDK_SEARCH_PATHS} ) + foreach( suffix ${ANDROID_SUPPORTED_NDK_VERSIONS} ) + list( APPEND __ndkSearchPaths "${__ndkSearchPath}${suffix}" ) + endforeach() + endforeach() + __INIT_VARIABLE( ANDROID_NDK PATH VALUES ${__ndkSearchPaths} ) + unset( __ndkSearchPaths ) + + if( ANDROID_NDK ) + message( STATUS "Using default path for Android NDK: ${ANDROID_NDK}" ) + message( STATUS " If you prefer to use a different location, please define a cmake or environment variable: ANDROID_NDK" ) + else() + #try to find Android standalone toolchain in one of the the default locations + __INIT_VARIABLE( ANDROID_STANDALONE_TOOLCHAIN PATH ANDROID_STANDALONE_TOOLCHAIN_SEARCH_PATH ) + + if( ANDROID_STANDALONE_TOOLCHAIN ) + message( STATUS "Using default path for standalone toolchain ${ANDROID_STANDALONE_TOOLCHAIN}" ) + message( STATUS " If you prefer to use a different location, please define the variable: ANDROID_STANDALONE_TOOLCHAIN" ) + endif( ANDROID_STANDALONE_TOOLCHAIN ) + endif( ANDROID_NDK ) + endif( NOT ANDROID_STANDALONE_TOOLCHAIN ) +endif( NOT ANDROID_NDK ) + +# remember found paths +if( ANDROID_NDK ) + get_filename_component( ANDROID_NDK "${ANDROID_NDK}" ABSOLUTE ) + set( ANDROID_NDK "${ANDROID_NDK}" CACHE INTERNAL "Path of the Android NDK" FORCE ) + set( BUILD_WITH_ANDROID_NDK True ) + if( EXISTS "${ANDROID_NDK}/RELEASE.TXT" ) + file( STRINGS "${ANDROID_NDK}/RELEASE.TXT" ANDROID_NDK_RELEASE_FULL LIMIT_COUNT 1 REGEX r[0-9]+[a-z]? ) + string( REGEX MATCH r[0-9]+[a-z]? ANDROID_NDK_RELEASE "${ANDROID_NDK_RELEASE_FULL}" ) + else() + set( ANDROID_NDK_RELEASE "r1x" ) + set( ANDROID_NDK_RELEASE_FULL "unreleased" ) + endif() +elseif( ANDROID_STANDALONE_TOOLCHAIN ) + get_filename_component( ANDROID_STANDALONE_TOOLCHAIN "${ANDROID_STANDALONE_TOOLCHAIN}" ABSOLUTE ) + # try to detect change + if( CMAKE_AR ) + string( LENGTH "${ANDROID_STANDALONE_TOOLCHAIN}" __length ) + string( SUBSTRING "${CMAKE_AR}" 0 ${__length} __androidStandaloneToolchainPreviousPath ) + if( NOT __androidStandaloneToolchainPreviousPath STREQUAL ANDROID_STANDALONE_TOOLCHAIN ) + message( FATAL_ERROR "It is not possible to change path to the Android standalone toolchain on subsequent run." ) + endif() + unset( __androidStandaloneToolchainPreviousPath ) + unset( __length ) + endif() + set( ANDROID_STANDALONE_TOOLCHAIN "${ANDROID_STANDALONE_TOOLCHAIN}" CACHE INTERNAL "Path of the Android standalone toolchain" FORCE ) + set( BUILD_WITH_STANDALONE_TOOLCHAIN True ) +else() + list(GET ANDROID_NDK_SEARCH_PATHS 0 ANDROID_NDK_SEARCH_PATH) + message( FATAL_ERROR "Could not find neither Android NDK nor Android standalone toolchain. + You should either set an environment variable: + export ANDROID_NDK=~/my-android-ndk + or + export ANDROID_STANDALONE_TOOLCHAIN=~/my-android-toolchain + or put the toolchain or NDK in the default path: + sudo ln -s ~/my-android-ndk ${ANDROID_NDK_SEARCH_PATH} + sudo ln -s ~/my-android-toolchain ${ANDROID_STANDALONE_TOOLCHAIN_SEARCH_PATH}" ) +endif() + +# android NDK layout +if( BUILD_WITH_ANDROID_NDK ) + if( NOT DEFINED ANDROID_NDK_LAYOUT ) + # try to automatically detect the layout + if( EXISTS "${ANDROID_NDK}/RELEASE.TXT") + set( ANDROID_NDK_LAYOUT "RELEASE" ) + elseif( EXISTS "${ANDROID_NDK}/../../linux-x86/toolchain/" ) + set( ANDROID_NDK_LAYOUT "LINARO" ) + elseif( EXISTS "${ANDROID_NDK}/../../gcc/" ) + set( ANDROID_NDK_LAYOUT "ANDROID" ) + endif() + endif() + set( ANDROID_NDK_LAYOUT "${ANDROID_NDK_LAYOUT}" CACHE STRING "The inner layout of NDK" ) + mark_as_advanced( ANDROID_NDK_LAYOUT ) + if( ANDROID_NDK_LAYOUT STREQUAL "LINARO" ) + set( ANDROID_NDK_HOST_SYSTEM_NAME ${ANDROID_NDK_HOST_SYSTEM_NAME2} ) # only 32-bit at the moment + set( ANDROID_NDK_TOOLCHAINS_PATH "${ANDROID_NDK}/../../${ANDROID_NDK_HOST_SYSTEM_NAME}/toolchain" ) + set( ANDROID_NDK_TOOLCHAINS_SUBPATH "" ) + set( ANDROID_NDK_TOOLCHAINS_SUBPATH2 "" ) + elseif( ANDROID_NDK_LAYOUT STREQUAL "ANDROID" ) + set( ANDROID_NDK_HOST_SYSTEM_NAME ${ANDROID_NDK_HOST_SYSTEM_NAME2} ) # only 32-bit at the moment + set( ANDROID_NDK_TOOLCHAINS_PATH "${ANDROID_NDK}/../../gcc/${ANDROID_NDK_HOST_SYSTEM_NAME}/arm" ) + set( ANDROID_NDK_TOOLCHAINS_SUBPATH "" ) + set( ANDROID_NDK_TOOLCHAINS_SUBPATH2 "" ) + else() # ANDROID_NDK_LAYOUT STREQUAL "RELEASE" + set( ANDROID_NDK_TOOLCHAINS_PATH "${ANDROID_NDK}/toolchains" ) + set( ANDROID_NDK_TOOLCHAINS_SUBPATH "/prebuilt/${ANDROID_NDK_HOST_SYSTEM_NAME}" ) + set( ANDROID_NDK_TOOLCHAINS_SUBPATH2 "/prebuilt/${ANDROID_NDK_HOST_SYSTEM_NAME2}" ) + endif() + get_filename_component( ANDROID_NDK_TOOLCHAINS_PATH "${ANDROID_NDK_TOOLCHAINS_PATH}" ABSOLUTE ) + + # try to detect change of NDK + if( CMAKE_AR ) + string( LENGTH "${ANDROID_NDK_TOOLCHAINS_PATH}" __length ) + string( SUBSTRING "${CMAKE_AR}" 0 ${__length} __androidNdkPreviousPath ) + if( NOT __androidNdkPreviousPath STREQUAL ANDROID_NDK_TOOLCHAINS_PATH ) + message( FATAL_ERROR "It is not possible to change the path to the NDK on subsequent CMake run. You must remove all generated files from your build folder first. + " ) + endif() + unset( __androidNdkPreviousPath ) + unset( __length ) + endif() +endif() + + +# get all the details about standalone toolchain +if( BUILD_WITH_STANDALONE_TOOLCHAIN ) + __DETECT_NATIVE_API_LEVEL( ANDROID_SUPPORTED_NATIVE_API_LEVELS "${ANDROID_STANDALONE_TOOLCHAIN}/sysroot/usr/include/android/api-level.h" ) + set( ANDROID_STANDALONE_TOOLCHAIN_API_LEVEL ${ANDROID_SUPPORTED_NATIVE_API_LEVELS} ) + set( __availableToolchains "standalone" ) + __DETECT_TOOLCHAIN_MACHINE_NAME( __availableToolchainMachines "${ANDROID_STANDALONE_TOOLCHAIN}" ) + if( NOT __availableToolchainMachines ) + message( FATAL_ERROR "Could not determine machine name of your toolchain. Probably your Android standalone toolchain is broken." ) + endif() + if( __availableToolchainMachines MATCHES i686 ) + set( __availableToolchainArchs "x86" ) + elseif( __availableToolchainMachines MATCHES arm ) + set( __availableToolchainArchs "arm" ) + elseif( __availableToolchainMachines MATCHES mipsel ) + set( __availableToolchainArchs "mipsel" ) + endif() + execute_process( COMMAND "${ANDROID_STANDALONE_TOOLCHAIN}/bin/${__availableToolchainMachines}-gcc${TOOL_OS_SUFFIX}" -dumpversion + OUTPUT_VARIABLE __availableToolchainCompilerVersions OUTPUT_STRIP_TRAILING_WHITESPACE ) + string( REGEX MATCH "[0-9]+[.][0-9]+([.][0-9]+)?" __availableToolchainCompilerVersions "${__availableToolchainCompilerVersions}" ) + if( EXISTS "${ANDROID_STANDALONE_TOOLCHAIN}/bin/clang${TOOL_OS_SUFFIX}" ) + list( APPEND __availableToolchains "standalone-clang" ) + list( APPEND __availableToolchainMachines ${__availableToolchainMachines} ) + list( APPEND __availableToolchainArchs ${__availableToolchainArchs} ) + list( APPEND __availableToolchainCompilerVersions ${__availableToolchainCompilerVersions} ) + endif() +endif() + +macro( __GLOB_NDK_TOOLCHAINS __availableToolchainsVar __availableToolchainsLst __toolchain_subpath ) + foreach( __toolchain ${${__availableToolchainsLst}} ) + if( "${__toolchain}" MATCHES "-clang3[.][0-9]$" AND NOT EXISTS "${ANDROID_NDK_TOOLCHAINS_PATH}/${__toolchain}${__toolchain_subpath}" ) + string( REGEX REPLACE "-clang3[.][0-9]$" "-4.6" __gcc_toolchain "${__toolchain}" ) + else() + set( __gcc_toolchain "${__toolchain}" ) + endif() + __DETECT_TOOLCHAIN_MACHINE_NAME( __machine "${ANDROID_NDK_TOOLCHAINS_PATH}/${__gcc_toolchain}${__toolchain_subpath}" ) + if( __machine ) + string( REGEX MATCH "[0-9]+[.][0-9]+([.][0-9x]+)?$" __version "${__gcc_toolchain}" ) + if( __machine MATCHES i686 ) + set( __arch "x86" ) + elseif( __machine MATCHES arm ) + set( __arch "arm" ) + elseif( __machine MATCHES mipsel ) + set( __arch "mipsel" ) + else() + unset( __arch ) + endif() + if( __arch ) + list( APPEND __availableToolchainMachines "${__machine}" ) + list( APPEND __availableToolchainArchs "${__arch}" ) + list( APPEND __availableToolchainCompilerVersions "${__version}" ) + list( APPEND ${__availableToolchainsVar} "${__toolchain}" ) + endif() + endif() + unset( __gcc_toolchain ) + endforeach() +endmacro() + +# get all the details about NDK +if( BUILD_WITH_ANDROID_NDK ) + file( GLOB ANDROID_SUPPORTED_NATIVE_API_LEVELS RELATIVE "${ANDROID_NDK}/platforms" "${ANDROID_NDK}/platforms/android-*" ) + string( REPLACE "android-" "" ANDROID_SUPPORTED_NATIVE_API_LEVELS "${ANDROID_SUPPORTED_NATIVE_API_LEVELS}" ) + set( __availableToolchains "" ) + set( __availableToolchainMachines "" ) + set( __availableToolchainArchs "" ) + set( __availableToolchainCompilerVersions "" ) + if( ANDROID_TOOLCHAIN_NAME AND EXISTS "${ANDROID_NDK_TOOLCHAINS_PATH}/${ANDROID_TOOLCHAIN_NAME}/" ) + # do not go through all toolchains if we know the name + set( __availableToolchainsLst "${ANDROID_TOOLCHAIN_NAME}" ) + __GLOB_NDK_TOOLCHAINS( __availableToolchains __availableToolchainsLst "${ANDROID_NDK_TOOLCHAINS_SUBPATH}" ) + if( NOT __availableToolchains AND NOT ANDROID_NDK_TOOLCHAINS_SUBPATH STREQUAL ANDROID_NDK_TOOLCHAINS_SUBPATH2 ) + __GLOB_NDK_TOOLCHAINS( __availableToolchains __availableToolchainsLst "${ANDROID_NDK_TOOLCHAINS_SUBPATH2}" ) + if( __availableToolchains ) + set( ANDROID_NDK_TOOLCHAINS_SUBPATH ${ANDROID_NDK_TOOLCHAINS_SUBPATH2} ) + endif() + endif() + endif() + if( NOT __availableToolchains ) + file( GLOB __availableToolchainsLst RELATIVE "${ANDROID_NDK_TOOLCHAINS_PATH}" "${ANDROID_NDK_TOOLCHAINS_PATH}/*" ) + if( __availableToolchains ) + list(SORT __availableToolchainsLst) # we need clang to go after gcc + endif() + __LIST_FILTER( __availableToolchainsLst "^[.]" ) + __LIST_FILTER( __availableToolchainsLst "llvm" ) + __LIST_FILTER( __availableToolchainsLst "renderscript" ) + __GLOB_NDK_TOOLCHAINS( __availableToolchains __availableToolchainsLst "${ANDROID_NDK_TOOLCHAINS_SUBPATH}" ) + if( NOT __availableToolchains AND NOT ANDROID_NDK_TOOLCHAINS_SUBPATH STREQUAL ANDROID_NDK_TOOLCHAINS_SUBPATH2 ) + __GLOB_NDK_TOOLCHAINS( __availableToolchains __availableToolchainsLst "${ANDROID_NDK_TOOLCHAINS_SUBPATH2}" ) + if( __availableToolchains ) + set( ANDROID_NDK_TOOLCHAINS_SUBPATH ${ANDROID_NDK_TOOLCHAINS_SUBPATH2} ) + endif() + endif() + endif() + if( NOT __availableToolchains ) + message( FATAL_ERROR "Could not find any working toolchain in the NDK. Probably your Android NDK is broken." ) + endif() +endif() + +# build list of available ABIs +set( ANDROID_SUPPORTED_ABIS "" ) +set( __uniqToolchainArchNames ${__availableToolchainArchs} ) +list( REMOVE_DUPLICATES __uniqToolchainArchNames ) +list( SORT __uniqToolchainArchNames ) +foreach( __arch ${__uniqToolchainArchNames} ) + list( APPEND ANDROID_SUPPORTED_ABIS ${ANDROID_SUPPORTED_ABIS_${__arch}} ) +endforeach() +unset( __uniqToolchainArchNames ) +if( NOT ANDROID_SUPPORTED_ABIS ) + message( FATAL_ERROR "No one of known Android ABIs is supported by this cmake toolchain." ) +endif() + +# choose target ABI +__INIT_VARIABLE( ANDROID_ABI OBSOLETE_ARM_TARGET OBSOLETE_ARM_TARGETS VALUES ${ANDROID_SUPPORTED_ABIS} ) +# verify that target ABI is supported +list( FIND ANDROID_SUPPORTED_ABIS "${ANDROID_ABI}" __androidAbiIdx ) +if( __androidAbiIdx EQUAL -1 ) + string( REPLACE ";" "\", \"" PRINTABLE_ANDROID_SUPPORTED_ABIS "${ANDROID_SUPPORTED_ABIS}" ) + message( FATAL_ERROR "Specified ANDROID_ABI = \"${ANDROID_ABI}\" is not supported by this cmake toolchain or your NDK/toolchain. + Supported values are: \"${PRINTABLE_ANDROID_SUPPORTED_ABIS}\" + " ) +endif() +unset( __androidAbiIdx ) + +# set target ABI options +if( ANDROID_ABI STREQUAL "x86" ) + set( X86 true ) + set( ANDROID_NDK_ABI_NAME "x86" ) + set( ANDROID_ARCH_NAME "x86" ) + set( ANDROID_ARCH_FULLNAME "x86" ) + set( ANDROID_LLVM_TRIPLE "i686-none-linux-android" ) + set( CMAKE_SYSTEM_PROCESSOR "i686" ) +elseif( ANDROID_ABI STREQUAL "mips" ) + set( MIPS true ) + set( ANDROID_NDK_ABI_NAME "mips" ) + set( ANDROID_ARCH_NAME "mips" ) + set( ANDROID_ARCH_FULLNAME "mipsel" ) + set( ANDROID_LLVM_TRIPLE "mipsel-none-linux-android" ) + set( CMAKE_SYSTEM_PROCESSOR "mips" ) +elseif( ANDROID_ABI STREQUAL "armeabi" ) + set( ARMEABI true ) + set( ANDROID_NDK_ABI_NAME "armeabi" ) + set( ANDROID_ARCH_NAME "arm" ) + set( ANDROID_ARCH_FULLNAME "arm" ) + set( ANDROID_LLVM_TRIPLE "armv5te-none-linux-androideabi" ) + set( CMAKE_SYSTEM_PROCESSOR "armv5te" ) +elseif( ANDROID_ABI STREQUAL "armeabi-v6 with VFP" ) + set( ARMEABI_V6 true ) + set( ANDROID_NDK_ABI_NAME "armeabi" ) + set( ANDROID_ARCH_NAME "arm" ) + set( ANDROID_ARCH_FULLNAME "arm" ) + set( ANDROID_LLVM_TRIPLE "armv5te-none-linux-androideabi" ) + set( CMAKE_SYSTEM_PROCESSOR "armv6" ) + # need always fallback to older platform + set( ARMEABI true ) +elseif( ANDROID_ABI STREQUAL "armeabi-v7a") + set( ARMEABI_V7A true ) + set( ANDROID_NDK_ABI_NAME "armeabi-v7a" ) + set( ANDROID_ARCH_NAME "arm" ) + set( ANDROID_ARCH_FULLNAME "arm" ) + set( ANDROID_LLVM_TRIPLE "armv7-none-linux-androideabi" ) + set( CMAKE_SYSTEM_PROCESSOR "armv7-a" ) +elseif( ANDROID_ABI STREQUAL "armeabi-v7a with VFPV3" ) + set( ARMEABI_V7A true ) + set( ANDROID_NDK_ABI_NAME "armeabi-v7a" ) + set( ANDROID_ARCH_NAME "arm" ) + set( ANDROID_ARCH_FULLNAME "arm" ) + set( ANDROID_LLVM_TRIPLE "armv7-none-linux-androideabi" ) + set( CMAKE_SYSTEM_PROCESSOR "armv7-a" ) + set( VFPV3 true ) +elseif( ANDROID_ABI STREQUAL "armeabi-v7a with NEON" ) + set( ARMEABI_V7A true ) + set( ANDROID_NDK_ABI_NAME "armeabi-v7a" ) + set( ANDROID_ARCH_NAME "arm" ) + set( ANDROID_ARCH_FULLNAME "arm" ) + set( ANDROID_LLVM_TRIPLE "armv7-none-linux-androideabi" ) + set( CMAKE_SYSTEM_PROCESSOR "armv7-a" ) + set( VFPV3 true ) + set( NEON true ) +else() + message( SEND_ERROR "Unknown ANDROID_ABI=\"${ANDROID_ABI}\" is specified." ) +endif() + +if( CMAKE_BINARY_DIR AND EXISTS "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeSystem.cmake" ) + # really dirty hack + # it is not possible to change CMAKE_SYSTEM_PROCESSOR after the first run... + file( APPEND "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeSystem.cmake" "SET(CMAKE_SYSTEM_PROCESSOR \"${CMAKE_SYSTEM_PROCESSOR}\")\n" ) +endif() + +if( ANDROID_ARCH_NAME STREQUAL "arm" AND NOT ARMEABI_V6 ) + __INIT_VARIABLE( ANDROID_FORCE_ARM_BUILD OBSOLETE_FORCE_ARM VALUES OFF ) + set( ANDROID_FORCE_ARM_BUILD ${ANDROID_FORCE_ARM_BUILD} CACHE BOOL "Use 32-bit ARM instructions instead of Thumb-1" FORCE ) + mark_as_advanced( ANDROID_FORCE_ARM_BUILD ) +else() + unset( ANDROID_FORCE_ARM_BUILD CACHE ) +endif() + +# choose toolchain +if( ANDROID_TOOLCHAIN_NAME ) + list( FIND __availableToolchains "${ANDROID_TOOLCHAIN_NAME}" __toolchainIdx ) + if( __toolchainIdx EQUAL -1 ) + list( SORT __availableToolchains ) + string( REPLACE ";" "\n * " toolchains_list "${__availableToolchains}" ) + set( toolchains_list " * ${toolchains_list}") + message( FATAL_ERROR "Specified toolchain \"${ANDROID_TOOLCHAIN_NAME}\" is missing in your NDK or broken. Please verify that your NDK is working or select another compiler toolchain. +To configure the toolchain set CMake variable ANDROID_TOOLCHAIN_NAME to one of the following values:\n${toolchains_list}\n" ) + endif() + list( GET __availableToolchainArchs ${__toolchainIdx} __toolchainArch ) + if( NOT __toolchainArch STREQUAL ANDROID_ARCH_FULLNAME ) + message( SEND_ERROR "Selected toolchain \"${ANDROID_TOOLCHAIN_NAME}\" is not able to compile binaries for the \"${ANDROID_ARCH_NAME}\" platform." ) + endif() +else() + set( __toolchainIdx -1 ) + set( __applicableToolchains "" ) + set( __toolchainMaxVersion "0.0.0" ) + list( LENGTH __availableToolchains __availableToolchainsCount ) + math( EXPR __availableToolchainsCount "${__availableToolchainsCount}-1" ) + foreach( __idx RANGE ${__availableToolchainsCount} ) + list( GET __availableToolchainArchs ${__idx} __toolchainArch ) + if( __toolchainArch STREQUAL ANDROID_ARCH_FULLNAME ) + list( GET __availableToolchainCompilerVersions ${__idx} __toolchainVersion ) + string( REPLACE "x" "99" __toolchainVersion "${__toolchainVersion}") + if( __toolchainVersion VERSION_GREATER __toolchainMaxVersion ) + set( __toolchainMaxVersion "${__toolchainVersion}" ) + set( __toolchainIdx ${__idx} ) + endif() + endif() + endforeach() + unset( __availableToolchainsCount ) + unset( __toolchainMaxVersion ) + unset( __toolchainVersion ) +endif() +unset( __toolchainArch ) +if( __toolchainIdx EQUAL -1 ) + message( FATAL_ERROR "No one of available compiler toolchains is able to compile for ${ANDROID_ARCH_NAME} platform." ) +endif() +list( GET __availableToolchains ${__toolchainIdx} ANDROID_TOOLCHAIN_NAME ) +list( GET __availableToolchainMachines ${__toolchainIdx} ANDROID_TOOLCHAIN_MACHINE_NAME ) +list( GET __availableToolchainCompilerVersions ${__toolchainIdx} ANDROID_COMPILER_VERSION ) + +unset( __toolchainIdx ) +unset( __availableToolchains ) +unset( __availableToolchainMachines ) +unset( __availableToolchainArchs ) +unset( __availableToolchainCompilerVersions ) + +# choose native API level +__INIT_VARIABLE( ANDROID_NATIVE_API_LEVEL ENV_ANDROID_NATIVE_API_LEVEL ANDROID_API_LEVEL ENV_ANDROID_API_LEVEL ANDROID_STANDALONE_TOOLCHAIN_API_LEVEL ANDROID_DEFAULT_NDK_API_LEVEL_${ANDROID_ARCH_NAME} ANDROID_DEFAULT_NDK_API_LEVEL ) +string( REGEX MATCH "[0-9]+" ANDROID_NATIVE_API_LEVEL "${ANDROID_NATIVE_API_LEVEL}" ) +# adjust API level +set( __real_api_level ${ANDROID_DEFAULT_NDK_API_LEVEL_${ANDROID_ARCH_NAME}} ) +foreach( __level ${ANDROID_SUPPORTED_NATIVE_API_LEVELS} ) + if( NOT __level GREATER ANDROID_NATIVE_API_LEVEL AND NOT __level LESS __real_api_level ) + set( __real_api_level ${__level} ) + endif() +endforeach() +if( __real_api_level AND NOT ANDROID_NATIVE_API_LEVEL EQUAL __real_api_level ) + message( STATUS "Adjusting Android API level 'android-${ANDROID_NATIVE_API_LEVEL}' to 'android-${__real_api_level}'") + set( ANDROID_NATIVE_API_LEVEL ${__real_api_level} ) +endif() +unset(__real_api_level) +# validate +list( FIND ANDROID_SUPPORTED_NATIVE_API_LEVELS "${ANDROID_NATIVE_API_LEVEL}" __levelIdx ) +if( __levelIdx EQUAL -1 ) + message( SEND_ERROR "Specified Android native API level 'android-${ANDROID_NATIVE_API_LEVEL}' is not supported by your NDK/toolchain." ) +else() + if( BUILD_WITH_ANDROID_NDK ) + __DETECT_NATIVE_API_LEVEL( __realApiLevel "${ANDROID_NDK}/platforms/android-${ANDROID_NATIVE_API_LEVEL}/arch-${ANDROID_ARCH_NAME}/usr/include/android/api-level.h" ) + if( NOT __realApiLevel EQUAL ANDROID_NATIVE_API_LEVEL ) + message( SEND_ERROR "Specified Android API level (${ANDROID_NATIVE_API_LEVEL}) does not match to the level found (${__realApiLevel}). Probably your copy of NDK is broken." ) + endif() + unset( __realApiLevel ) + endif() + set( ANDROID_NATIVE_API_LEVEL "${ANDROID_NATIVE_API_LEVEL}" CACHE STRING "Android API level for native code" FORCE ) + if( CMAKE_VERSION VERSION_GREATER "2.8" ) + list( SORT ANDROID_SUPPORTED_NATIVE_API_LEVELS ) + set_property( CACHE ANDROID_NATIVE_API_LEVEL PROPERTY STRINGS ${ANDROID_SUPPORTED_NATIVE_API_LEVELS} ) + endif() +endif() +unset( __levelIdx ) + + +# remember target ABI +set( ANDROID_ABI "${ANDROID_ABI}" CACHE STRING "The target ABI for Android. If arm, then armeabi-v7a is recommended for hardware floating point." FORCE ) +if( CMAKE_VERSION VERSION_GREATER "2.8" ) + list( SORT ANDROID_SUPPORTED_ABIS_${ANDROID_ARCH_FULLNAME} ) + set_property( CACHE ANDROID_ABI PROPERTY STRINGS ${ANDROID_SUPPORTED_ABIS_${ANDROID_ARCH_FULLNAME}} ) +endif() + + +# runtime choice (STL, rtti, exceptions) +if( NOT ANDROID_STL ) + # honor legacy ANDROID_USE_STLPORT + if( DEFINED ANDROID_USE_STLPORT ) + if( ANDROID_USE_STLPORT ) + set( ANDROID_STL stlport_static ) + endif() + message( WARNING "You are using an obsolete variable ANDROID_USE_STLPORT to select the STL variant. Use -DANDROID_STL=stlport_static instead." ) + endif() + if( NOT ANDROID_STL ) + set( ANDROID_STL gnustl_static ) + endif() +endif() +set( ANDROID_STL "${ANDROID_STL}" CACHE STRING "C++ runtime" ) +set( ANDROID_STL_FORCE_FEATURES ON CACHE BOOL "automatically configure rtti and exceptions support based on C++ runtime" ) +mark_as_advanced( ANDROID_STL ANDROID_STL_FORCE_FEATURES ) + +if( BUILD_WITH_ANDROID_NDK ) + if( NOT "${ANDROID_STL}" MATCHES "^(none|system|system_re|gabi\\+\\+_static|gabi\\+\\+_shared|stlport_static|stlport_shared|gnustl_static|gnustl_shared)$") + message( FATAL_ERROR "ANDROID_STL is set to invalid value \"${ANDROID_STL}\". +The possible values are: + none -> Do not configure the runtime. + system -> Use the default minimal system C++ runtime library. + system_re -> Same as system but with rtti and exceptions. + gabi++_static -> Use the GAbi++ runtime as a static library. + gabi++_shared -> Use the GAbi++ runtime as a shared library. + stlport_static -> Use the STLport runtime as a static library. + stlport_shared -> Use the STLport runtime as a shared library. + gnustl_static -> (default) Use the GNU STL as a static library. + gnustl_shared -> Use the GNU STL as a shared library. +" ) + endif() +elseif( BUILD_WITH_STANDALONE_TOOLCHAIN ) + if( NOT "${ANDROID_STL}" MATCHES "^(none|gnustl_static|gnustl_shared)$") + message( FATAL_ERROR "ANDROID_STL is set to invalid value \"${ANDROID_STL}\". +The possible values are: + none -> Do not configure the runtime. + gnustl_static -> (default) Use the GNU STL as a static library. + gnustl_shared -> Use the GNU STL as a shared library. +" ) + endif() +endif() + +unset( ANDROID_RTTI ) +unset( ANDROID_EXCEPTIONS ) +unset( ANDROID_STL_INCLUDE_DIRS ) +unset( __libstl ) +unset( __libsupcxx ) + +if( NOT _CMAKE_IN_TRY_COMPILE AND ANDROID_NDK_RELEASE STREQUAL "r7b" AND ARMEABI_V7A AND NOT VFPV3 AND ANDROID_STL MATCHES "gnustl" ) + message( WARNING "The GNU STL armeabi-v7a binaries from NDK r7b can crash non-NEON devices. The files provided with NDK r7b were not configured properly, resulting in crashes on Tegra2-based devices and others when trying to use certain floating-point functions (e.g., cosf, sinf, expf). +You are strongly recommended to switch to another NDK release. +" ) +endif() + +if( NOT _CMAKE_IN_TRY_COMPILE AND X86 AND ANDROID_STL MATCHES "gnustl" AND ANDROID_NDK_RELEASE STREQUAL "r6" ) + message( WARNING "The x86 system header file from NDK r6 has incorrect definition for ptrdiff_t. You are recommended to upgrade to a newer NDK release or manually patch the header: +See https://android.googlesource.com/platform/development.git f907f4f9d4e56ccc8093df6fee54454b8bcab6c2 + diff --git a/ndk/platforms/android-9/arch-x86/include/machine/_types.h b/ndk/platforms/android-9/arch-x86/include/machine/_types.h + index 5e28c64..65892a1 100644 + --- a/ndk/platforms/android-9/arch-x86/include/machine/_types.h + +++ b/ndk/platforms/android-9/arch-x86/include/machine/_types.h + @@ -51,7 +51,11 @@ typedef long int ssize_t; + #endif + #ifndef _PTRDIFF_T + #define _PTRDIFF_T + -typedef long ptrdiff_t; + +# ifdef __ANDROID__ + + typedef int ptrdiff_t; + +# else + + typedef long ptrdiff_t; + +# endif + #endif +" ) +endif() + + +# setup paths and STL for standalone toolchain +if( BUILD_WITH_STANDALONE_TOOLCHAIN ) + set( ANDROID_TOOLCHAIN_ROOT "${ANDROID_STANDALONE_TOOLCHAIN}" ) + set( ANDROID_CLANG_TOOLCHAIN_ROOT "${ANDROID_STANDALONE_TOOLCHAIN}" ) + set( ANDROID_SYSROOT "${ANDROID_STANDALONE_TOOLCHAIN}/sysroot" ) + + if( NOT ANDROID_STL STREQUAL "none" ) + set( ANDROID_STL_INCLUDE_DIRS "${ANDROID_STANDALONE_TOOLCHAIN}/include/c++/${ANDROID_COMPILER_VERSION}" ) + if( NOT EXISTS "${ANDROID_STL_INCLUDE_DIRS}" ) + # old location ( pre r8c ) + set( ANDROID_STL_INCLUDE_DIRS "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/include/c++/${ANDROID_COMPILER_VERSION}" ) + endif() + if( ARMEABI_V7A AND EXISTS "${ANDROID_STL_INCLUDE_DIRS}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/${CMAKE_SYSTEM_PROCESSOR}/bits" ) + list( APPEND ANDROID_STL_INCLUDE_DIRS "${ANDROID_STL_INCLUDE_DIRS}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/${CMAKE_SYSTEM_PROCESSOR}" ) + elseif( ARMEABI AND NOT ANDROID_FORCE_ARM_BUILD AND EXISTS "${ANDROID_STL_INCLUDE_DIRS}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/thumb/bits" ) + list( APPEND ANDROID_STL_INCLUDE_DIRS "${ANDROID_STL_INCLUDE_DIRS}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/thumb" ) + else() + list( APPEND ANDROID_STL_INCLUDE_DIRS "${ANDROID_STL_INCLUDE_DIRS}/${ANDROID_TOOLCHAIN_MACHINE_NAME}" ) + endif() + # always search static GNU STL to get the location of libsupc++.a + if( ARMEABI_V7A AND NOT ANDROID_FORCE_ARM_BUILD AND EXISTS "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}/thumb/libstdc++.a" ) + set( __libstl "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}/thumb" ) + elseif( ARMEABI_V7A AND EXISTS "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}/libstdc++.a" ) + set( __libstl "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}" ) + elseif( ARMEABI AND NOT ANDROID_FORCE_ARM_BUILD AND EXISTS "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/thumb/libstdc++.a" ) + set( __libstl "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/thumb" ) + elseif( EXISTS "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/libstdc++.a" ) + set( __libstl "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib" ) + endif() + if( __libstl ) + set( __libsupcxx "${__libstl}/libsupc++.a" ) + set( __libstl "${__libstl}/libstdc++.a" ) + endif() + if( NOT EXISTS "${__libsupcxx}" ) + message( FATAL_ERROR "The required libstdsupc++.a is missing in your standalone toolchain. + Usually it happens because of bug in make-standalone-toolchain.sh script from NDK r7, r7b and r7c. + You need to either upgrade to newer NDK or manually copy + $ANDROID_NDK/sources/cxx-stl/gnu-libstdc++/libs/${ANDROID_NDK_ABI_NAME}/libsupc++.a + to + ${__libsupcxx} + " ) + endif() + if( ANDROID_STL STREQUAL "gnustl_shared" ) + if( ARMEABI_V7A AND EXISTS "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}/libgnustl_shared.so" ) + set( __libstl "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}/libgnustl_shared.so" ) + elseif( ARMEABI AND NOT ANDROID_FORCE_ARM_BUILD AND EXISTS "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/thumb/libgnustl_shared.so" ) + set( __libstl "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/thumb/libgnustl_shared.so" ) + elseif( EXISTS "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/libgnustl_shared.so" ) + set( __libstl "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/libgnustl_shared.so" ) + endif() + endif() + endif() +endif() + +# clang +if( "${ANDROID_TOOLCHAIN_NAME}" STREQUAL "standalone-clang" ) + set( ANDROID_COMPILER_IS_CLANG 1 ) + execute_process( COMMAND "${ANDROID_CLANG_TOOLCHAIN_ROOT}/bin/clang${TOOL_OS_SUFFIX}" --version OUTPUT_VARIABLE ANDROID_CLANG_VERSION OUTPUT_STRIP_TRAILING_WHITESPACE ) + string( REGEX MATCH "[0-9]+[.][0-9]+" ANDROID_CLANG_VERSION "${ANDROID_CLANG_VERSION}") +elseif( "${ANDROID_TOOLCHAIN_NAME}" MATCHES "-clang3[.][0-9]?$" ) + string( REGEX MATCH "3[.][0-9]$" ANDROID_CLANG_VERSION "${ANDROID_TOOLCHAIN_NAME}") + string( REGEX REPLACE "-clang${ANDROID_CLANG_VERSION}$" "-4.6" ANDROID_GCC_TOOLCHAIN_NAME "${ANDROID_TOOLCHAIN_NAME}" ) + if( NOT EXISTS "${ANDROID_NDK_TOOLCHAINS_PATH}/llvm-${ANDROID_CLANG_VERSION}${ANDROID_NDK_TOOLCHAINS_SUBPATH}/bin/clang${TOOL_OS_SUFFIX}" ) + message( FATAL_ERROR "Could not find the Clang compiler driver" ) + endif() + set( ANDROID_COMPILER_IS_CLANG 1 ) + set( ANDROID_CLANG_TOOLCHAIN_ROOT "${ANDROID_NDK_TOOLCHAINS_PATH}/llvm-${ANDROID_CLANG_VERSION}${ANDROID_NDK_TOOLCHAINS_SUBPATH}" ) +else() + set( ANDROID_GCC_TOOLCHAIN_NAME "${ANDROID_TOOLCHAIN_NAME}" ) + unset( ANDROID_COMPILER_IS_CLANG CACHE ) +endif() + +string( REPLACE "." "" _clang_name "clang${ANDROID_CLANG_VERSION}" ) +if( NOT EXISTS "${ANDROID_CLANG_TOOLCHAIN_ROOT}/bin/${_clang_name}${TOOL_OS_SUFFIX}" ) + set( _clang_name "clang" ) +endif() + + +# setup paths and STL for NDK +if( BUILD_WITH_ANDROID_NDK ) + set( ANDROID_TOOLCHAIN_ROOT "${ANDROID_NDK_TOOLCHAINS_PATH}/${ANDROID_GCC_TOOLCHAIN_NAME}${ANDROID_NDK_TOOLCHAINS_SUBPATH}" ) + set( ANDROID_SYSROOT "${ANDROID_NDK}/platforms/android-${ANDROID_NATIVE_API_LEVEL}/arch-${ANDROID_ARCH_NAME}" ) + + if( ANDROID_STL STREQUAL "none" ) + # do nothing + elseif( ANDROID_STL STREQUAL "system" ) + set( ANDROID_RTTI OFF ) + set( ANDROID_EXCEPTIONS OFF ) + set( ANDROID_STL_INCLUDE_DIRS "${ANDROID_NDK}/sources/cxx-stl/system/include" ) + elseif( ANDROID_STL STREQUAL "system_re" ) + set( ANDROID_RTTI ON ) + set( ANDROID_EXCEPTIONS ON ) + set( ANDROID_STL_INCLUDE_DIRS "${ANDROID_NDK}/sources/cxx-stl/system/include" ) + elseif( ANDROID_STL MATCHES "gabi" ) + if( ANDROID_NDK_RELEASE STRLESS "r7" ) + message( FATAL_ERROR "gabi++ is not awailable in your NDK. You have to upgrade to NDK r7 or newer to use gabi++.") + endif() + set( ANDROID_RTTI ON ) + set( ANDROID_EXCEPTIONS OFF ) + set( ANDROID_STL_INCLUDE_DIRS "${ANDROID_NDK}/sources/cxx-stl/gabi++/include" ) + set( __libstl "${ANDROID_NDK}/sources/cxx-stl/gabi++/libs/${ANDROID_NDK_ABI_NAME}/libgabi++_static.a" ) + elseif( ANDROID_STL MATCHES "stlport" ) + if( NOT ANDROID_NDK_RELEASE STRLESS "r8d" ) + set( ANDROID_EXCEPTIONS ON ) + else() + set( ANDROID_EXCEPTIONS OFF ) + endif() + if( ANDROID_NDK_RELEASE STRLESS "r7" ) + set( ANDROID_RTTI OFF ) + else() + set( ANDROID_RTTI ON ) + endif() + set( ANDROID_STL_INCLUDE_DIRS "${ANDROID_NDK}/sources/cxx-stl/stlport/stlport" ) + set( __libstl "${ANDROID_NDK}/sources/cxx-stl/stlport/libs/${ANDROID_NDK_ABI_NAME}/libstlport_static.a" ) + elseif( ANDROID_STL MATCHES "gnustl" ) + set( ANDROID_EXCEPTIONS ON ) + set( ANDROID_RTTI ON ) + if( EXISTS "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/${ANDROID_COMPILER_VERSION}" ) + if( ARMEABI_V7A AND ANDROID_COMPILER_VERSION VERSION_EQUAL "4.7" AND ANDROID_NDK_RELEASE STREQUAL "r8d" ) + # gnustl binary for 4.7 compiler is buggy :( + # TODO: look for right fix + set( __libstl "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/4.6" ) + else() + set( __libstl "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/${ANDROID_COMPILER_VERSION}" ) + endif() + else() + set( __libstl "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++" ) + endif() + set( ANDROID_STL_INCLUDE_DIRS "${__libstl}/include" "${__libstl}/libs/${ANDROID_NDK_ABI_NAME}/include" ) + if( EXISTS "${__libstl}/libs/${ANDROID_NDK_ABI_NAME}/libgnustl_static.a" ) + set( __libstl "${__libstl}/libs/${ANDROID_NDK_ABI_NAME}/libgnustl_static.a" ) + else() + set( __libstl "${__libstl}/libs/${ANDROID_NDK_ABI_NAME}/libstdc++.a" ) + endif() + else() + message( FATAL_ERROR "Unknown runtime: ${ANDROID_STL}" ) + endif() + # find libsupc++.a - rtti & exceptions + if( ANDROID_STL STREQUAL "system_re" OR ANDROID_STL MATCHES "gnustl" ) + set( __libsupcxx "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/${ANDROID_COMPILER_VERSION}/libs/${ANDROID_NDK_ABI_NAME}/libsupc++.a" ) # r8b or newer + if( NOT EXISTS "${__libsupcxx}" ) + set( __libsupcxx "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/libs/${ANDROID_NDK_ABI_NAME}/libsupc++.a" ) # r7-r8 + endif() + if( NOT EXISTS "${__libsupcxx}" ) # before r7 + if( ARMEABI_V7A ) + if( ANDROID_FORCE_ARM_BUILD ) + set( __libsupcxx "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}/libsupc++.a" ) + else() + set( __libsupcxx "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}/thumb/libsupc++.a" ) + endif() + elseif( ARMEABI AND NOT ANDROID_FORCE_ARM_BUILD ) + set( __libsupcxx "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/thumb/libsupc++.a" ) + else() + set( __libsupcxx "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/libsupc++.a" ) + endif() + endif() + if( NOT EXISTS "${__libsupcxx}") + message( ERROR "Could not find libsupc++.a for a chosen platform. Either your NDK is not supported or is broken.") + endif() + endif() +endif() + + +# case of shared STL linkage +if( ANDROID_STL MATCHES "shared" AND DEFINED __libstl ) + string( REPLACE "_static.a" "_shared.so" __libstl "${__libstl}" ) + # TODO: check if .so file exists before the renaming +endif() + + +# ccache support +__INIT_VARIABLE( _ndk_ccache NDK_CCACHE ENV_NDK_CCACHE ) +if( _ndk_ccache ) + if( DEFINED NDK_CCACHE AND NOT EXISTS NDK_CCACHE ) + unset( NDK_CCACHE CACHE ) + endif() + find_program( NDK_CCACHE "${_ndk_ccache}" DOC "The path to ccache binary") +else() + unset( NDK_CCACHE CACHE ) +endif() +unset( _ndk_ccache ) + + +# setup the cross-compiler +if( NOT CMAKE_C_COMPILER ) + if( NDK_CCACHE AND NOT ANDROID_SYSROOT MATCHES "[ ;\"]" ) + set( CMAKE_C_COMPILER "${NDK_CCACHE}" CACHE PATH "ccache as C compiler" ) + set( CMAKE_CXX_COMPILER "${NDK_CCACHE}" CACHE PATH "ccache as C++ compiler" ) + if( ANDROID_COMPILER_IS_CLANG ) + set( CMAKE_C_COMPILER_ARG1 "${ANDROID_CLANG_TOOLCHAIN_ROOT}/bin/${_clang_name}${TOOL_OS_SUFFIX}" CACHE PATH "C compiler") + set( CMAKE_CXX_COMPILER_ARG1 "${ANDROID_CLANG_TOOLCHAIN_ROOT}/bin/${_clang_name}++${TOOL_OS_SUFFIX}" CACHE PATH "C++ compiler") + else() + set( CMAKE_C_COMPILER_ARG1 "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-gcc${TOOL_OS_SUFFIX}" CACHE PATH "C compiler") + set( CMAKE_CXX_COMPILER_ARG1 "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-g++${TOOL_OS_SUFFIX}" CACHE PATH "C++ compiler") + endif() + else() + if( ANDROID_COMPILER_IS_CLANG ) + set( CMAKE_C_COMPILER "${ANDROID_CLANG_TOOLCHAIN_ROOT}/bin/${_clang_name}${TOOL_OS_SUFFIX}" CACHE PATH "C compiler") + set( CMAKE_CXX_COMPILER "${ANDROID_CLANG_TOOLCHAIN_ROOT}/bin/${_clang_name}++${TOOL_OS_SUFFIX}" CACHE PATH "C++ compiler") + else() + set( CMAKE_C_COMPILER "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-gcc${TOOL_OS_SUFFIX}" CACHE PATH "C compiler" ) + set( CMAKE_CXX_COMPILER "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-g++${TOOL_OS_SUFFIX}" CACHE PATH "C++ compiler" ) + endif() + endif() + set( CMAKE_ASM_COMPILER "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-gcc${TOOL_OS_SUFFIX}" CACHE PATH "assembler" ) + set( CMAKE_STRIP "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-strip${TOOL_OS_SUFFIX}" CACHE PATH "strip" ) + set( CMAKE_AR "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-ar${TOOL_OS_SUFFIX}" CACHE PATH "archive" ) + set( CMAKE_LINKER "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-ld${TOOL_OS_SUFFIX}" CACHE PATH "linker" ) + set( CMAKE_NM "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-nm${TOOL_OS_SUFFIX}" CACHE PATH "nm" ) + set( CMAKE_OBJCOPY "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-objcopy${TOOL_OS_SUFFIX}" CACHE PATH "objcopy" ) + set( CMAKE_OBJDUMP "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-objdump${TOOL_OS_SUFFIX}" CACHE PATH "objdump" ) + set( CMAKE_RANLIB "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-ranlib${TOOL_OS_SUFFIX}" CACHE PATH "ranlib" ) +endif() + +set( _CMAKE_TOOLCHAIN_PREFIX "${ANDROID_TOOLCHAIN_MACHINE_NAME}-" ) +if( CMAKE_VERSION VERSION_LESS 2.8.5 ) + set( CMAKE_ASM_COMPILER_ARG1 "-c" ) +endif() +if( APPLE ) + find_program( CMAKE_INSTALL_NAME_TOOL NAMES install_name_tool ) + if( NOT CMAKE_INSTALL_NAME_TOOL ) + message( FATAL_ERROR "Could not find install_name_tool, please check your installation." ) + endif() + mark_as_advanced( CMAKE_INSTALL_NAME_TOOL ) +endif() + +# Force set compilers because standard identification works badly for us +include( CMakeForceCompiler ) +CMAKE_FORCE_C_COMPILER( "${CMAKE_C_COMPILER}" GNU ) +if( ANDROID_COMPILER_IS_CLANG ) + set( CMAKE_C_COMPILER_ID Clang) +endif() +set( CMAKE_C_PLATFORM_ID Linux ) +set( CMAKE_C_SIZEOF_DATA_PTR 4 ) +set( CMAKE_C_HAS_ISYSROOT 1 ) +set( CMAKE_C_COMPILER_ABI ELF ) +CMAKE_FORCE_CXX_COMPILER( "${CMAKE_CXX_COMPILER}" GNU ) +if( ANDROID_COMPILER_IS_CLANG ) + set( CMAKE_CXX_COMPILER_ID Clang) +endif() +set( CMAKE_CXX_PLATFORM_ID Linux ) +set( CMAKE_CXX_SIZEOF_DATA_PTR 4 ) +set( CMAKE_CXX_HAS_ISYSROOT 1 ) +set( CMAKE_CXX_COMPILER_ABI ELF ) +set( CMAKE_CXX_SOURCE_FILE_EXTENSIONS cc cp cxx cpp CPP c++ C ) +# force ASM compiler (required for CMake < 2.8.5) +set( CMAKE_ASM_COMPILER_ID_RUN TRUE ) +set( CMAKE_ASM_COMPILER_ID GNU ) +set( CMAKE_ASM_COMPILER_WORKS TRUE ) +set( CMAKE_ASM_COMPILER_FORCED TRUE ) +set( CMAKE_COMPILER_IS_GNUASM 1) +set( CMAKE_ASM_SOURCE_FILE_EXTENSIONS s S asm ) + +# flags and definitions +remove_definitions( -DANDROID ) +add_definitions( -DANDROID ) + +if( ANDROID_SYSROOT MATCHES "[ ;\"]" ) + if( CMAKE_HOST_WIN32 ) + # try to convert path to 8.3 form + file( WRITE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/cvt83.cmd" "@echo %~s1" ) + execute_process( COMMAND "$ENV{ComSpec}" /c "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/cvt83.cmd" "${ANDROID_SYSROOT}" + OUTPUT_VARIABLE __path OUTPUT_STRIP_TRAILING_WHITESPACE + RESULT_VARIABLE __result ERROR_QUIET ) + if( __result EQUAL 0 ) + file( TO_CMAKE_PATH "${__path}" ANDROID_SYSROOT ) + set( ANDROID_CXX_FLAGS "--sysroot=${ANDROID_SYSROOT}" ) + else() + set( ANDROID_CXX_FLAGS "--sysroot=\"${ANDROID_SYSROOT}\"" ) + endif() + else() + set( ANDROID_CXX_FLAGS "'--sysroot=${ANDROID_SYSROOT}'" ) + endif() + if( NOT _CMAKE_IN_TRY_COMPILE ) + # quotes can break try_compile and compiler identification + message(WARNING "Path to your Android NDK (or toolchain) has non-alphanumeric symbols.\nThe build might be broken.\n") + endif() +else() + set( ANDROID_CXX_FLAGS "--sysroot=${ANDROID_SYSROOT}" ) +endif() + +# NDK flags +if( ARMEABI OR ARMEABI_V7A ) + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -fpic -funwind-tables" ) + if( NOT ANDROID_FORCE_ARM_BUILD AND NOT ARMEABI_V6 ) + set( ANDROID_CXX_FLAGS_RELEASE "-mthumb -fomit-frame-pointer -fno-strict-aliasing" ) + set( ANDROID_CXX_FLAGS_DEBUG "-marm -fno-omit-frame-pointer -fno-strict-aliasing" ) + if( NOT ANDROID_COMPILER_IS_CLANG ) + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -finline-limit=64" ) + endif() + else() + # always compile ARMEABI_V6 in arm mode; otherwise there is no difference from ARMEABI + set( ANDROID_CXX_FLAGS_RELEASE "-marm -fomit-frame-pointer -fstrict-aliasing" ) + set( ANDROID_CXX_FLAGS_DEBUG "-marm -fno-omit-frame-pointer -fno-strict-aliasing" ) + if( NOT ANDROID_COMPILER_IS_CLANG ) + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -funswitch-loops -finline-limit=300" ) + endif() + endif() +elseif( X86 ) + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -funwind-tables" ) + if( NOT ANDROID_COMPILER_IS_CLANG ) + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -funswitch-loops -finline-limit=300" ) + else() + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -fPIC" ) + endif() + set( ANDROID_CXX_FLAGS_RELEASE "-fomit-frame-pointer -fstrict-aliasing" ) + set( ANDROID_CXX_FLAGS_DEBUG "-fno-omit-frame-pointer -fno-strict-aliasing" ) +elseif( MIPS ) + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -fpic -fno-strict-aliasing -finline-functions -ffunction-sections -funwind-tables -fmessage-length=0" ) + set( ANDROID_CXX_FLAGS_RELEASE "-fomit-frame-pointer" ) + set( ANDROID_CXX_FLAGS_DEBUG "-fno-omit-frame-pointer" ) + if( NOT ANDROID_COMPILER_IS_CLANG ) + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -fno-inline-functions-called-once -fgcse-after-reload -frerun-cse-after-loop -frename-registers" ) + set( ANDROID_CXX_FLAGS_RELEASE "${ANDROID_CXX_FLAGS_RELEASE} -funswitch-loops -finline-limit=300" ) + endif() +elseif() + set( ANDROID_CXX_FLAGS_RELEASE "" ) + set( ANDROID_CXX_FLAGS_DEBUG "" ) +endif() + +set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -fsigned-char" ) # good/necessary when porting desktop libraries + +if( NOT X86 AND NOT ANDROID_COMPILER_IS_CLANG ) + set( ANDROID_CXX_FLAGS "-Wno-psabi ${ANDROID_CXX_FLAGS}" ) +endif() + +if( NOT ANDROID_COMPILER_VERSION VERSION_LESS "4.6" ) + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -no-canonical-prefixes" ) # see https://android-review.googlesource.com/#/c/47564/ +endif() + +# ABI-specific flags +if( ARMEABI_V7A ) + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -march=armv7-a -mfloat-abi=softfp" ) + if( NEON ) + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -mfpu=neon" ) + elseif( VFPV3 ) + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -mfpu=vfpv3" ) + else() + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -mfpu=vfpv3-d16" ) + endif() +elseif( ARMEABI_V6 ) + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -march=armv6 -mfloat-abi=softfp -mfpu=vfp" ) # vfp == vfpv2 +elseif( ARMEABI ) + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -march=armv5te -mtune=xscale -msoft-float" ) +endif() + +if( ANDROID_STL MATCHES "gnustl" AND (EXISTS "${__libstl}" OR EXISTS "${__libsupcxx}") ) + set( CMAKE_CXX_CREATE_SHARED_LIBRARY " -o " ) + set( CMAKE_CXX_CREATE_SHARED_MODULE " -o " ) + set( CMAKE_CXX_LINK_EXECUTABLE " -o " ) +else() + set( CMAKE_CXX_CREATE_SHARED_LIBRARY " -o " ) + set( CMAKE_CXX_CREATE_SHARED_MODULE " -o " ) + set( CMAKE_CXX_LINK_EXECUTABLE " -o " ) +endif() + +# STL +if( EXISTS "${__libstl}" OR EXISTS "${__libsupcxx}" ) + if( EXISTS "${__libstl}" ) + set( CMAKE_CXX_CREATE_SHARED_LIBRARY "${CMAKE_CXX_CREATE_SHARED_LIBRARY} \"${__libstl}\"" ) + set( CMAKE_CXX_CREATE_SHARED_MODULE "${CMAKE_CXX_CREATE_SHARED_MODULE} \"${__libstl}\"" ) + set( CMAKE_CXX_LINK_EXECUTABLE "${CMAKE_CXX_LINK_EXECUTABLE} \"${__libstl}\"" ) + endif() + if( EXISTS "${__libsupcxx}" ) + set( CMAKE_CXX_CREATE_SHARED_LIBRARY "${CMAKE_CXX_CREATE_SHARED_LIBRARY} \"${__libsupcxx}\"" ) + set( CMAKE_CXX_CREATE_SHARED_MODULE "${CMAKE_CXX_CREATE_SHARED_MODULE} \"${__libsupcxx}\"" ) + set( CMAKE_CXX_LINK_EXECUTABLE "${CMAKE_CXX_LINK_EXECUTABLE} \"${__libsupcxx}\"" ) + # C objects: + set( CMAKE_C_CREATE_SHARED_LIBRARY " -o " ) + set( CMAKE_C_CREATE_SHARED_MODULE " -o " ) + set( CMAKE_C_LINK_EXECUTABLE " -o " ) + set( CMAKE_C_CREATE_SHARED_LIBRARY "${CMAKE_C_CREATE_SHARED_LIBRARY} \"${__libsupcxx}\"" ) + set( CMAKE_C_CREATE_SHARED_MODULE "${CMAKE_C_CREATE_SHARED_MODULE} \"${__libsupcxx}\"" ) + set( CMAKE_C_LINK_EXECUTABLE "${CMAKE_C_LINK_EXECUTABLE} \"${__libsupcxx}\"" ) + endif() + if( ANDROID_STL MATCHES "gnustl" ) + if( NOT EXISTS "${ANDROID_LIBM_PATH}" ) + set( ANDROID_LIBM_PATH -lm ) + endif() + set( CMAKE_CXX_CREATE_SHARED_LIBRARY "${CMAKE_CXX_CREATE_SHARED_LIBRARY} ${ANDROID_LIBM_PATH}" ) + set( CMAKE_CXX_CREATE_SHARED_MODULE "${CMAKE_CXX_CREATE_SHARED_MODULE} ${ANDROID_LIBM_PATH}" ) + set( CMAKE_CXX_LINK_EXECUTABLE "${CMAKE_CXX_LINK_EXECUTABLE} ${ANDROID_LIBM_PATH}" ) + endif() +endif() + +# variables controlling optional build flags +if (ANDROID_NDK_RELEASE STRLESS "r7") + # libGLESv2.so in NDK's prior to r7 refers to missing external symbols. + # So this flag option is required for all projects using OpenGL from native. + __INIT_VARIABLE( ANDROID_SO_UNDEFINED VALUES ON ) +else() + __INIT_VARIABLE( ANDROID_SO_UNDEFINED VALUES OFF ) +endif() +__INIT_VARIABLE( ANDROID_NO_UNDEFINED OBSOLETE_NO_UNDEFINED VALUES ON ) +__INIT_VARIABLE( ANDROID_FUNCTION_LEVEL_LINKING VALUES ON ) +__INIT_VARIABLE( ANDROID_GOLD_LINKER VALUES ON ) +__INIT_VARIABLE( ANDROID_NOEXECSTACK VALUES ON ) +__INIT_VARIABLE( ANDROID_RELRO VALUES ON ) + +set( ANDROID_NO_UNDEFINED ${ANDROID_NO_UNDEFINED} CACHE BOOL "Show all undefined symbols as linker errors" ) +set( ANDROID_SO_UNDEFINED ${ANDROID_SO_UNDEFINED} CACHE BOOL "Allows or disallows undefined symbols in shared libraries" ) +set( ANDROID_FUNCTION_LEVEL_LINKING ${ANDROID_FUNCTION_LEVEL_LINKING} CACHE BOOL "Allows or disallows undefined symbols in shared libraries" ) +set( ANDROID_GOLD_LINKER ${ANDROID_GOLD_LINKER} CACHE BOOL "Enables gold linker (only available for NDK r8b for ARM and x86 architectures on linux-86 and darwin-x86 hosts)" ) +set( ANDROID_NOEXECSTACK ${ANDROID_NOEXECSTACK} CACHE BOOL "Allows or disallows undefined symbols in shared libraries" ) +set( ANDROID_RELRO ${ANDROID_RELRO} CACHE BOOL "Enables RELRO - a memory corruption mitigation technique" ) +mark_as_advanced( ANDROID_NO_UNDEFINED ANDROID_SO_UNDEFINED ANDROID_FUNCTION_LEVEL_LINKING ANDROID_GOLD_LINKER ANDROID_NOEXECSTACK ANDROID_RELRO ) + +# linker flags +set( ANDROID_LINKER_FLAGS "" ) + +if( ARMEABI_V7A ) + # this is *required* to use the following linker flags that routes around + # a CPU bug in some Cortex-A8 implementations: + set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -Wl,--fix-cortex-a8" ) +endif() + +if( ANDROID_NO_UNDEFINED ) + if( MIPS ) + # there is some sysroot-related problem in mips linker... + if( NOT ANDROID_SYSROOT MATCHES "[ ;\"]" ) + set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -Wl,--no-undefined -Wl,-rpath-link,${ANDROID_SYSROOT}/usr/lib" ) + endif() + else() + set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -Wl,--no-undefined" ) + endif() +endif() + +if( ANDROID_SO_UNDEFINED ) + set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -Wl,-allow-shlib-undefined" ) +endif() + +if( ANDROID_FUNCTION_LEVEL_LINKING ) + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -fdata-sections -ffunction-sections" ) + set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -Wl,--gc-sections" ) +endif() + +if( ANDROID_COMPILER_VERSION VERSION_EQUAL "4.6" ) + if( ANDROID_GOLD_LINKER AND (CMAKE_HOST_UNIX OR ANDROID_NDK_RELEASE STRGREATER "r8b") AND (ARMEABI OR ARMEABI_V7A OR X86) ) + set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -fuse-ld=gold" ) + elseif( ANDROID_NDK_RELEASE STRGREATER "r8b") + set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -fuse-ld=bfd" ) + elseif( ANDROID_NDK_RELEASE STREQUAL "r8b" AND ARMEABI AND NOT _CMAKE_IN_TRY_COMPILE ) + message( WARNING "The default bfd linker from arm GCC 4.6 toolchain can fail with 'unresolvable R_ARM_THM_CALL relocation' error message. See https://code.google.com/p/android/issues/detail?id=35342 + On Linux and OS X host platform you can workaround this problem using gold linker (default). + Rerun cmake with -DANDROID_GOLD_LINKER=ON option in case of problems. +" ) + endif() +endif() # version 4.6 + +if( ANDROID_NOEXECSTACK ) + if( ANDROID_COMPILER_IS_CLANG ) + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -Xclang -mnoexecstack" ) + else() + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -Wa,--noexecstack" ) + endif() + set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -Wl,-z,noexecstack" ) +endif() + +if( ANDROID_RELRO ) + set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -Wl,-z,relro -Wl,-z,now" ) +endif() + +if( ANDROID_COMPILER_IS_CLANG ) + set( ANDROID_CXX_FLAGS "-Qunused-arguments ${ANDROID_CXX_FLAGS}" ) + if( ARMEABI_V7A AND NOT ANDROID_FORCE_ARM_BUILD ) + set( ANDROID_CXX_FLAGS_RELEASE "-target thumbv7-none-linux-androideabi ${ANDROID_CXX_FLAGS_RELEASE}" ) + set( ANDROID_CXX_FLAGS_DEBUG "-target ${ANDROID_LLVM_TRIPLE} ${ANDROID_CXX_FLAGS_DEBUG}" ) + else() + set( ANDROID_CXX_FLAGS "-target ${ANDROID_LLVM_TRIPLE} ${ANDROID_CXX_FLAGS}" ) + endif() + if( BUILD_WITH_ANDROID_NDK ) + set( ANDROID_CXX_FLAGS "-gcc-toolchain ${ANDROID_TOOLCHAIN_ROOT} ${ANDROID_CXX_FLAGS}" ) + endif() +endif() + +# cache flags +set( CMAKE_CXX_FLAGS "" CACHE STRING "c++ flags" ) +set( CMAKE_C_FLAGS "" CACHE STRING "c flags" ) +set( CMAKE_CXX_FLAGS_RELEASE "-O3 -DNDEBUG" CACHE STRING "c++ Release flags" ) +set( CMAKE_C_FLAGS_RELEASE "-O3 -DNDEBUG" CACHE STRING "c Release flags" ) +set( CMAKE_CXX_FLAGS_DEBUG "-O0 -g -DDEBUG -D_DEBUG" CACHE STRING "c++ Debug flags" ) +set( CMAKE_C_FLAGS_DEBUG "-O0 -g -DDEBUG -D_DEBUG" CACHE STRING "c Debug flags" ) +set( CMAKE_SHARED_LINKER_FLAGS "" CACHE STRING "shared linker flags" ) +set( CMAKE_MODULE_LINKER_FLAGS "" CACHE STRING "module linker flags" ) +set( CMAKE_EXE_LINKER_FLAGS "-Wl,-z,nocopyreloc" CACHE STRING "executable linker flags" ) + +# put flags to cache (for debug purpose only) +set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS}" CACHE INTERNAL "Android specific c/c++ flags" ) +set( ANDROID_CXX_FLAGS_RELEASE "${ANDROID_CXX_FLAGS_RELEASE}" CACHE INTERNAL "Android specific c/c++ Release flags" ) +set( ANDROID_CXX_FLAGS_DEBUG "${ANDROID_CXX_FLAGS_DEBUG}" CACHE INTERNAL "Android specific c/c++ Debug flags" ) +set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS}" CACHE INTERNAL "Android specific c/c++ linker flags" ) + +# finish flags +set( CMAKE_CXX_FLAGS "${ANDROID_CXX_FLAGS} ${CMAKE_CXX_FLAGS}" ) +set( CMAKE_C_FLAGS "${ANDROID_CXX_FLAGS} ${CMAKE_C_FLAGS}" ) +set( CMAKE_CXX_FLAGS_RELEASE "${ANDROID_CXX_FLAGS_RELEASE} ${CMAKE_CXX_FLAGS_RELEASE}" ) +set( CMAKE_C_FLAGS_RELEASE "${ANDROID_CXX_FLAGS_RELEASE} ${CMAKE_C_FLAGS_RELEASE}" ) +set( CMAKE_CXX_FLAGS_DEBUG "${ANDROID_CXX_FLAGS_DEBUG} ${CMAKE_CXX_FLAGS_DEBUG}" ) +set( CMAKE_C_FLAGS_DEBUG "${ANDROID_CXX_FLAGS_DEBUG} ${CMAKE_C_FLAGS_DEBUG}" ) +set( CMAKE_SHARED_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} ${CMAKE_SHARED_LINKER_FLAGS}" ) +set( CMAKE_MODULE_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} ${CMAKE_MODULE_LINKER_FLAGS}" ) +set( CMAKE_EXE_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} ${CMAKE_EXE_LINKER_FLAGS}" ) + +if( MIPS AND BUILD_WITH_ANDROID_NDK AND ANDROID_NDK_RELEASE STREQUAL "r8" ) + set( CMAKE_SHARED_LINKER_FLAGS "-Wl,-T,${ANDROID_NDK_TOOLCHAINS_PATH}/${ANDROID_GCC_TOOLCHAIN_NAME}/mipself.xsc ${CMAKE_SHARED_LINKER_FLAGS}" ) + set( CMAKE_MODULE_LINKER_FLAGS "-Wl,-T,${ANDROID_NDK_TOOLCHAINS_PATH}/${ANDROID_GCC_TOOLCHAIN_NAME}/mipself.xsc ${CMAKE_MODULE_LINKER_FLAGS}" ) + set( CMAKE_EXE_LINKER_FLAGS "-Wl,-T,${ANDROID_NDK_TOOLCHAINS_PATH}/${ANDROID_GCC_TOOLCHAIN_NAME}/mipself.x ${CMAKE_EXE_LINKER_FLAGS}" ) +endif() + +# configure rtti +if( DEFINED ANDROID_RTTI AND ANDROID_STL_FORCE_FEATURES ) + if( ANDROID_RTTI ) + set( CMAKE_CXX_FLAGS "-frtti ${CMAKE_CXX_FLAGS}" ) + else() + set( CMAKE_CXX_FLAGS "-fno-rtti ${CMAKE_CXX_FLAGS}" ) + endif() +endif() + +# configure exceptios +if( DEFINED ANDROID_EXCEPTIONS AND ANDROID_STL_FORCE_FEATURES ) + if( ANDROID_EXCEPTIONS ) + set( CMAKE_CXX_FLAGS "-fexceptions ${CMAKE_CXX_FLAGS}" ) + set( CMAKE_C_FLAGS "-fexceptions ${CMAKE_C_FLAGS}" ) + else() + set( CMAKE_CXX_FLAGS "-fno-exceptions ${CMAKE_CXX_FLAGS}" ) + set( CMAKE_C_FLAGS "-fno-exceptions ${CMAKE_C_FLAGS}" ) + endif() +endif() + +# global includes and link directories +include_directories( SYSTEM "${ANDROID_SYSROOT}/usr/include" ${ANDROID_STL_INCLUDE_DIRS} ) +get_filename_component(__android_install_path "${CMAKE_INSTALL_PREFIX}/libs/${ANDROID_NDK_ABI_NAME}" ABSOLUTE) # avoid CMP0015 policy warning +link_directories( "${__android_install_path}" ) + +# detect if need link crtbegin_so.o explicitly +if( NOT DEFINED ANDROID_EXPLICIT_CRT_LINK ) + set( __cmd "${CMAKE_CXX_CREATE_SHARED_LIBRARY}" ) + string( REPLACE "" "${CMAKE_CXX_COMPILER} ${CMAKE_CXX_COMPILER_ARG1}" __cmd "${__cmd}" ) + string( REPLACE "" "${CMAKE_C_COMPILER} ${CMAKE_C_COMPILER_ARG1}" __cmd "${__cmd}" ) + string( REPLACE "" "${CMAKE_CXX_FLAGS}" __cmd "${__cmd}" ) + string( REPLACE "" "" __cmd "${__cmd}" ) + string( REPLACE "" "${CMAKE_SHARED_LINKER_FLAGS}" __cmd "${__cmd}" ) + string( REPLACE "" "-shared" __cmd "${__cmd}" ) + string( REPLACE "" "" __cmd "${__cmd}" ) + string( REPLACE "" "" __cmd "${__cmd}" ) + string( REPLACE "" "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/toolchain_crtlink_test.so" __cmd "${__cmd}" ) + string( REPLACE "" "\"${ANDROID_SYSROOT}/usr/lib/crtbegin_so.o\"" __cmd "${__cmd}" ) + string( REPLACE "" "" __cmd "${__cmd}" ) + separate_arguments( __cmd ) + foreach( __var ANDROID_NDK ANDROID_NDK_TOOLCHAINS_PATH ANDROID_STANDALONE_TOOLCHAIN ) + if( ${__var} ) + set( __tmp "${${__var}}" ) + separate_arguments( __tmp ) + string( REPLACE "${__tmp}" "${${__var}}" __cmd "${__cmd}") + endif() + endforeach() + string( REPLACE "'" "" __cmd "${__cmd}" ) + string( REPLACE "\"" "" __cmd "${__cmd}" ) + execute_process( COMMAND ${__cmd} RESULT_VARIABLE __cmd_result OUTPUT_QUIET ERROR_QUIET ) + if( __cmd_result EQUAL 0 ) + set( ANDROID_EXPLICIT_CRT_LINK ON ) + else() + set( ANDROID_EXPLICIT_CRT_LINK OFF ) + endif() +endif() + +if( ANDROID_EXPLICIT_CRT_LINK ) + set( CMAKE_CXX_CREATE_SHARED_LIBRARY "${CMAKE_CXX_CREATE_SHARED_LIBRARY} \"${ANDROID_SYSROOT}/usr/lib/crtbegin_so.o\"" ) + set( CMAKE_CXX_CREATE_SHARED_MODULE "${CMAKE_CXX_CREATE_SHARED_MODULE} \"${ANDROID_SYSROOT}/usr/lib/crtbegin_so.o\"" ) +endif() + +# setup output directories +set( LIBRARY_OUTPUT_PATH_ROOT ${CMAKE_BINARY_DIR} CACHE PATH "root for library output, set this to change where android libs are installed to" ) +set( CMAKE_INSTALL_PREFIX "${ANDROID_TOOLCHAIN_ROOT}/user" CACHE STRING "path for installing" ) + +if(NOT _CMAKE_IN_TRY_COMPILE) + if( EXISTS "${CMAKE_SOURCE_DIR}/jni/CMakeLists.txt" ) + set( EXECUTABLE_OUTPUT_PATH "${LIBRARY_OUTPUT_PATH_ROOT}/bin/${ANDROID_NDK_ABI_NAME}" CACHE PATH "Output directory for applications" ) + else() + set( EXECUTABLE_OUTPUT_PATH "${LIBRARY_OUTPUT_PATH_ROOT}/bin" CACHE PATH "Output directory for applications" ) + endif() + set( LIBRARY_OUTPUT_PATH "${LIBRARY_OUTPUT_PATH_ROOT}/libs/${ANDROID_NDK_ABI_NAME}" CACHE PATH "path for android libs" ) +endif() + +# copy shaed stl library to build directory +if( NOT _CMAKE_IN_TRY_COMPILE AND __libstl MATCHES "[.]so$" ) + get_filename_component( __libstlname "${__libstl}" NAME ) + execute_process( COMMAND "${CMAKE_COMMAND}" -E copy_if_different "${__libstl}" "${LIBRARY_OUTPUT_PATH}/${__libstlname}" RESULT_VARIABLE __fileCopyProcess ) + if( NOT __fileCopyProcess EQUAL 0 OR NOT EXISTS "${LIBRARY_OUTPUT_PATH}/${__libstlname}") + message( SEND_ERROR "Failed copying of ${__libstl} to the ${LIBRARY_OUTPUT_PATH}/${__libstlname}" ) + endif() + unset( __fileCopyProcess ) + unset( __libstlname ) +endif() + + +# set these global flags for cmake client scripts to change behavior +set( ANDROID True ) +set( BUILD_ANDROID True ) + +# where is the target environment +set( CMAKE_FIND_ROOT_PATH "${ANDROID_TOOLCHAIN_ROOT}/bin" "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_MACHINE_NAME}" "${ANDROID_SYSROOT}" "${CMAKE_INSTALL_PREFIX}" "${CMAKE_INSTALL_PREFIX}/share" ) + +# only search for libraries and includes in the ndk toolchain +set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY ) +set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY ) +set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY ) + + +# macro to find packages on the host OS +macro( find_host_package ) + set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER ) + set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY NEVER ) + set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE NEVER ) + if( CMAKE_HOST_WIN32 ) + SET( WIN32 1 ) + SET( UNIX ) + elseif( CMAKE_HOST_APPLE ) + SET( APPLE 1 ) + SET( UNIX ) + endif() + find_package( ${ARGN} ) + SET( WIN32 ) + SET( APPLE ) + SET( UNIX 1 ) + set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY ) + set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY ) + set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY ) +endmacro() + + +# macro to find programs on the host OS +macro( find_host_program ) + set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER ) + set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY NEVER ) + set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE NEVER ) + if( CMAKE_HOST_WIN32 ) + SET( WIN32 1 ) + SET( UNIX ) + elseif( CMAKE_HOST_APPLE ) + SET( APPLE 1 ) + SET( UNIX ) + endif() + find_program( ${ARGN} ) + SET( WIN32 ) + SET( APPLE ) + SET( UNIX 1 ) + set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY ) + set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY ) + set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY ) +endmacro() + + +macro( ANDROID_GET_ABI_RAWNAME TOOLCHAIN_FLAG VAR ) + if( "${TOOLCHAIN_FLAG}" STREQUAL "ARMEABI" ) + set( ${VAR} "armeabi" ) + elseif( "${TOOLCHAIN_FLAG}" STREQUAL "ARMEABI_V7A" ) + set( ${VAR} "armeabi-v7a" ) + elseif( "${TOOLCHAIN_FLAG}" STREQUAL "X86" ) + set( ${VAR} "x86" ) + elseif( "${TOOLCHAIN_FLAG}" STREQUAL "MIPS" ) + set( ${VAR} "mips" ) + else() + set( ${VAR} "unknown" ) + endif() +endmacro() + + +# export toolchain settings for the try_compile() command +if( NOT PROJECT_NAME STREQUAL "CMAKE_TRY_COMPILE" ) + set( __toolchain_config "") + foreach( __var NDK_CCACHE LIBRARY_OUTPUT_PATH_ROOT ANDROID_FORBID_SYGWIN ANDROID_SET_OBSOLETE_VARIABLES + ANDROID_NDK_HOST_X64 + ANDROID_NDK + ANDROID_NDK_LAYOUT + ANDROID_STANDALONE_TOOLCHAIN + ANDROID_TOOLCHAIN_NAME + ANDROID_ABI + ANDROID_NATIVE_API_LEVEL + ANDROID_STL + ANDROID_STL_FORCE_FEATURES + ANDROID_FORCE_ARM_BUILD + ANDROID_NO_UNDEFINED + ANDROID_SO_UNDEFINED + ANDROID_FUNCTION_LEVEL_LINKING + ANDROID_GOLD_LINKER + ANDROID_NOEXECSTACK + ANDROID_RELRO + ANDROID_LIBM_PATH + ANDROID_EXPLICIT_CRT_LINK + ) + if( DEFINED ${__var} ) + if( "${__var}" MATCHES " ") + set( __toolchain_config "${__toolchain_config}set( ${__var} \"${${__var}}\" CACHE INTERNAL \"\" )\n" ) + else() + set( __toolchain_config "${__toolchain_config}set( ${__var} ${${__var}} CACHE INTERNAL \"\" )\n" ) + endif() + endif() + endforeach() + set( ANDROID_TOOLCHAIN_CONFIG_FILE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/android.toolchain.config.cmake" CACHE INTERNAL "" ) + file( WRITE "${ANDROID_TOOLCHAIN_CONFIG_FILE}" "${__toolchain_config}" ) + unset( __toolchain_config ) +endif() + + +# force cmake to produce / instead of \ in build commands for Ninja generator +if( CMAKE_GENERATOR MATCHES "Ninja" AND CMAKE_HOST_WIN32 ) + # it is a bad hack after all + # CMake generates Ninja makefiles with UNIX paths only if it thinks that we are going to build with MinGW + set( CMAKE_COMPILER_IS_MINGW TRUE ) # tell CMake that we are MinGW + set( CMAKE_CROSSCOMPILING TRUE ) # stop recursion + enable_language( C ) + enable_language( CXX ) + # unset( CMAKE_COMPILER_IS_MINGW ) # can't unset because CMake does not convert back-slashes in response files without it + unset( MINGW ) +endif() + + +# set some obsolete variables for backward compatibility +set( ANDROID_SET_OBSOLETE_VARIABLES ON CACHE BOOL "Define obsolete Andrid-specific cmake variables" ) +mark_as_advanced( ANDROID_SET_OBSOLETE_VARIABLES ) +if( ANDROID_SET_OBSOLETE_VARIABLES ) + set( ANDROID_API_LEVEL ${ANDROID_NATIVE_API_LEVEL} ) + set( ARM_TARGET "${ANDROID_ABI}" ) + set( ARMEABI_NDK_NAME "${ANDROID_NDK_ABI_NAME}" ) +endif() + + +# Variables controlling behavior or set by cmake toolchain: +# ANDROID_ABI : "armeabi-v7a" (default), "armeabi", "armeabi-v7a with NEON", "armeabi-v7a with VFPV3", "armeabi-v6 with VFP", "x86", "mips" +# ANDROID_NATIVE_API_LEVEL : 3,4,5,8,9,14 (depends on NDK version) +# ANDROID_STL : gnustl_static/gnustl_shared/stlport_static/stlport_shared/gabi++_static/gabi++_shared/system_re/system/none +# ANDROID_FORBID_SYGWIN : ON/OFF +# ANDROID_NO_UNDEFINED : ON/OFF +# ANDROID_SO_UNDEFINED : OFF/ON (default depends on NDK version) +# ANDROID_FUNCTION_LEVEL_LINKING : ON/OFF +# ANDROID_GOLD_LINKER : ON/OFF +# ANDROID_NOEXECSTACK : ON/OFF +# ANDROID_RELRO : ON/OFF +# ANDROID_FORCE_ARM_BUILD : ON/OFF +# ANDROID_STL_FORCE_FEATURES : ON/OFF +# ANDROID_SET_OBSOLETE_VARIABLES : ON/OFF +# Can be set only at the first run: +# ANDROID_NDK +# ANDROID_STANDALONE_TOOLCHAIN +# ANDROID_TOOLCHAIN_NAME : the NDK name of compiler toolchain +# ANDROID_NDK_HOST_X64 : try to use x86_64 toolchain (default for x64 host systems) +# ANDROID_NDK_LAYOUT : the inner NDK structure (RELEASE, LINARO, ANDROID) +# LIBRARY_OUTPUT_PATH_ROOT : +# NDK_CCACHE : +# Obsolete: +# ANDROID_API_LEVEL : superseded by ANDROID_NATIVE_API_LEVEL +# ARM_TARGET : superseded by ANDROID_ABI +# ARM_TARGETS : superseded by ANDROID_ABI (can be set only) +# ANDROID_NDK_TOOLCHAIN_ROOT : superseded by ANDROID_STANDALONE_TOOLCHAIN (can be set only) +# ANDROID_USE_STLPORT : superseded by ANDROID_STL=stlport_static +# ANDROID_LEVEL : superseded by ANDROID_NATIVE_API_LEVEL (completely removed) +# +# Primary read-only variables: +# ANDROID : always TRUE +# ARMEABI : TRUE for arm v6 and older devices +# ARMEABI_V6 : TRUE for arm v6 +# ARMEABI_V7A : TRUE for arm v7a +# NEON : TRUE if NEON unit is enabled +# VFPV3 : TRUE if VFP version 3 is enabled +# X86 : TRUE if configured for x86 +# MIPS : TRUE if configured for mips +# BUILD_ANDROID : always TRUE +# BUILD_WITH_ANDROID_NDK : TRUE if NDK is used +# BUILD_WITH_STANDALONE_TOOLCHAIN : TRUE if standalone toolchain is used +# ANDROID_NDK_HOST_SYSTEM_NAME : "windows", "linux-x86" or "darwin-x86" depending on host platform +# ANDROID_NDK_ABI_NAME : "armeabi", "armeabi-v7a", "x86" or "mips" depending on ANDROID_ABI +# ANDROID_NDK_RELEASE : one of r5, r5b, r5c, r6, r6b, r7, r7b, r7c, r8, r8b, r8c, r8d, r8e, r9, r9b, r9c, r9d; set only for NDK +# ANDROID_ARCH_NAME : "arm" or "x86" or "mips" depending on ANDROID_ABI +# ANDROID_SYSROOT : path to the compiler sysroot +# TOOL_OS_SUFFIX : "" or ".exe" depending on host platform +# ANDROID_COMPILER_IS_CLANG : TRUE if clang compiler is used +# Obsolete: +# ARMEABI_NDK_NAME : superseded by ANDROID_NDK_ABI_NAME +# +# Secondary (less stable) read-only variables: +# ANDROID_COMPILER_VERSION : GCC version used +# ANDROID_CXX_FLAGS : C/C++ compiler flags required by Android platform +# ANDROID_SUPPORTED_ABIS : list of currently allowed values for ANDROID_ABI +# ANDROID_TOOLCHAIN_MACHINE_NAME : "arm-linux-androideabi", "arm-eabi" or "i686-android-linux" +# ANDROID_TOOLCHAIN_ROOT : path to the top level of toolchain (standalone or placed inside NDK) +# ANDROID_CLANG_TOOLCHAIN_ROOT : path to clang tools +# ANDROID_SUPPORTED_NATIVE_API_LEVELS : list of native API levels found inside NDK +# ANDROID_STL_INCLUDE_DIRS : stl include paths +# ANDROID_RTTI : if rtti is enabled by the runtime +# ANDROID_EXCEPTIONS : if exceptions are enabled by the runtime +# ANDROID_GCC_TOOLCHAIN_NAME : read-only, differs from ANDROID_TOOLCHAIN_NAME only if clang is used +# ANDROID_CLANG_VERSION : version of clang compiler if clang is used +# ANDROID_LIBM_PATH : path to libm.so (set to something like $(TOP)/out/target/product//obj/lib/libm.so) to workaround unresolved `sincos` +# +# Defaults: +# ANDROID_DEFAULT_NDK_API_LEVEL +# ANDROID_DEFAULT_NDK_API_LEVEL_${ARCH} +# ANDROID_NDK_SEARCH_PATHS +# ANDROID_STANDALONE_TOOLCHAIN_SEARCH_PATH +# ANDROID_SUPPORTED_ABIS_${ARCH} +# ANDROID_SUPPORTED_NDK_VERSIONS diff --git a/CMake/dcmtkAfterModules.cmake b/CMake/dcmtkAfterModules.cmake new file mode 100644 index 00000000..d2e4aee6 --- /dev/null +++ b/CMake/dcmtkAfterModules.cmake @@ -0,0 +1,27 @@ +# Finish the setup. This should be run after all modules. + +IF(BUILD_SINGLE_SHARED_LIBRARY) + # Collect the object files of all libraries in all modules. + # The variable ${DCMTK_ALL_LIBRARIES} is set by DCMTK_ADD_LIBRARY(). + SET(LIBS) + FOREACH(LIB ${DCMTK_ALL_LIBRARIES}) + SET(LIBS ${LIBS} $) + ENDFOREACH(LIB) + + # Build a single "everything-library". + # The library dependencies are collected by DCMTK_TARGET_LINK_LIBRARIES(). + ADD_LIBRARY(dcmtk SHARED ${LIBS}) + TARGET_LINK_LIBRARIES(dcmtk ${DCMTK_LIBRARY_DEPENDENCIES}) + SET_TARGET_PROPERTIES(dcmtk PROPERTIES ${DCMTK_LIBRARY_PROPERTIES}) + + # Export target for build tree + SET_PROPERTY(GLOBAL APPEND PROPERTY DCMTK_LIBRARY_TARGETS dcmtk) + + # Declare installation files. Also export libs and executables to DCMTKTargets.cmake. + INSTALL(TARGETS dcmtk + EXPORT DCMTKTargets + COMPONENT lib + RUNTIME DESTINATION ${DCMTK_INSTALL_BINDIR} + LIBRARY DESTINATION ${DCMTK_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${DCMTK_INSTALL_LIBDIR}) +ENDIF(BUILD_SINGLE_SHARED_LIBRARY) diff --git a/CMake/dcmtkMacros.cmake b/CMake/dcmtkMacros.cmake new file mode 100644 index 00000000..a14d1a81 --- /dev/null +++ b/CMake/dcmtkMacros.cmake @@ -0,0 +1,191 @@ +# +# Register all tests for the current module +# +# DCMTK_ADD_TESTS - macro which registers all tests +# MODULE - name of the module that we are called for +# +MACRO(DCMTK_ADD_TESTS MODULE) + IF(CMAKE_CROSSCOMPILING) + IF(WIN32) + WINE_COMMAND(${MODULE}_TEST_CMD "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${MODULE}_tests") + STRING(REPLACE "\\" "\\\\" ${MODULE}_TEST_CMD "${${MODULE}_TEST_CMD}") + ELSEIF(ANDROID) + SET(${MODULE}_TEST_CMD -P ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/dcmtkCTestRunAndroid.cmake) + ELSE() + IF(NOT DEFINED DCMTK_UNIT_TESTS_UNSUPPORTED_WARN_ONCE) + SET(DCMTK_UNIT_TESTS_UNSUPPORTED_WARN_ONCE CACHE INTERNAL "") + MESSAGE(WARNING "Emulation for your target platform is not available, unit tests will fail!") + ENDIF() + SET(${MODULE}_TEST_CMD "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${MODULE}_tests") + ENDIF() + ELSE(CMAKE_CROSSCOMPILING) + SET(${MODULE}_TEST_CMD "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${MODULE}_tests") + ENDIF(CMAKE_CROSSCOMPILING) + LIST(APPEND DCMTK_TEST_EXECUTABLES "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${MODULE}_tests") + LIST(REMOVE_DUPLICATES DCMTK_TEST_EXECUTABLES) + SET(DCMTK_TEST_EXECUTABLES ${DCMTK_TEST_EXECUTABLES} CACHE INTERNAL "List of executables needed to run the unit tests") + FILE(STRINGS tests.cc AVAIL_TESTS REGEX "OFTEST_REGISTER\\([^)]*\\)") + FOREACH(TEST_LINE ${AVAIL_TESTS}) + # TODO: How can we parse tests.cc in a saner way? + STRING(REGEX MATCH "OFTEST_REGISTER\\([^)]*" TEST "${TEST_LINE}") + STRING(REPLACE "OFTEST_REGISTER(" "" TEST ${TEST}) + # This assumes that test names are globally unique + IF(CMAKE_CROSSCOMPILING AND ANDROID) + ADD_TEST("${TEST}" ${CMAKE_COMMAND} "-DDCMTK_CTEST_TESTCASE_COMMAND=${ANDROID_TEMPORARY_FILES_LOCATION}/${MODULE}_tests\;${TEST}" ${${MODULE}_TEST_CMD}) + ELSE() + ADD_TEST("${TEST}" ${${MODULE}_TEST_CMD} "${TEST}") + ENDIF() + SET_PROPERTY(TEST "${TEST}" PROPERTY LABELS "${MODULE}") + ENDFOREACH(TEST_LINE) +ENDMACRO(DCMTK_ADD_TESTS) + +# +# Setup an executable +# +# DCMTK_ADD_EXECUTABLE - macro which adds the needed setup for an executable +# PROGRAM - name of the executable that we are called for +# +MACRO(DCMTK_ADD_EXECUTABLE PROGRAM) + IF(BUILD_APPS) + ADD_EXECUTABLE(${PROGRAM} ${ARGN}) + + # Make wildcard arguments work + IF(WIN32 AND NOT MINGW) + SET_TARGET_PROPERTIES(${PROGRAM} PROPERTIES LINK_FLAGS ${WIN32_STD_OBJECTS}) + ENDIF(WIN32 AND NOT MINGW) + + # Collect executable as part of global DCMTK_EXECUTABLE_TARGETS property + SET_PROPERTY(GLOBAL APPEND PROPERTY DCMTK_EXECUTABLE_TARGETS ${PROGRAM}) + + # declare installation files, also export DCMTKTargets.cmake + INSTALL(TARGETS ${PROGRAM} + EXPORT DCMTKTargets + COMPONENT bin + DESTINATION ${DCMTK_INSTALL_BINDIR}) + ENDIF(BUILD_APPS) +ENDMACRO(DCMTK_ADD_EXECUTABLE) + +# +# Setup a library +# +# DCMTK_ADD_LIBRARY - macro which adds the needed setup for a library +# LIBRARY - name of the library that we are called for +# extra arguments - names of the library's source files +# +MACRO(DCMTK_ADD_LIBRARY LIBRARY) + # Actually add the library first + ADD_LIBRARY(${LIBRARY}${DCMTK_LIBRARY_SUFFIX} ${DCMTK_LIBRARY_TYPE} ${ARGN}) + SET(DCMTK_ALL_LIBRARIES ${DCMTK_ALL_LIBRARIES} ${LIBRARY}${DCMTK_LIBRARY_SUFFIX} CACHE INTERNAL "List of all libraries in the DCMTK.") + + # set proper version information for shared library + IF(BUILD_SHARED_LIBS AND NOT BUILD_SINGLE_SHARED_LIBRARY) + SET_TARGET_PROPERTIES(${LIBRARY}${DCMTK_LIBRARY_SUFFIX} PROPERTIES ${DCMTK_LIBRARY_PROPERTIES}) + ELSE(BUILD_SHARED_LIBS AND NOT BUILD_SINGLE_SHARED_LIBRARY) + # define the foo_EXPORTS-macro even when we are not building ("normal") shared libs + SET_TARGET_PROPERTIES(${LIBRARY}${DCMTK_LIBRARY_SUFFIX} PROPERTIES COMPILE_DEFINITIONS "${LIBRARY}_EXPORTS") + ENDIF(BUILD_SHARED_LIBS AND NOT BUILD_SINGLE_SHARED_LIBRARY) + + IF(NOT BUILD_SINGLE_SHARED_LIBRARY) + # Remember export target for writing it to build tree later + SET_PROPERTY(GLOBAL APPEND PROPERTY DCMTK_LIBRARY_TARGETS ${LIBRARY}${DCMTK_LIBRARY_SUFFIX}) + + # Declare installation files + INSTALL(TARGETS ${LIBRARY}${DCMTK_LIBRARY_SUFFIX} + EXPORT DCMTKTargets + RUNTIME DESTINATION ${DCMTK_INSTALL_BINDIR} COMPONENT bin + LIBRARY DESTINATION ${DCMTK_INSTALL_LIBDIR} COMPONENT shlib + ARCHIVE DESTINATION ${DCMTK_INSTALL_LIBDIR} COMPONENT lib) + ENDIF(NOT BUILD_SINGLE_SHARED_LIBRARY) +ENDMACRO(DCMTK_ADD_LIBRARY) + +# +# Specify a library's dependencies +# +# DCMTK_TARGET_LINK_LIBRARIES - macro for specifying a library's dependencies +# LIBRARY - name of the library that we are called for +# extra arguments - names of the library's dependencies +# +MACRO(DCMTK_TARGET_LINK_LIBRARIES LIBRARY) + SET(DCMTK_LIBRARY_DEPENDENCIES ${DCMTK_LIBRARY_DEPENDENCIES} ${ARGN} CACHE INTERNAL "Dependencies of the DCMTK libraries.") + # The name of this macro doesn't match, but it does just what we need here + DCMTK_TARGET_LINK_MODULES(${LIBRARY} ${ARGN}) +ENDMACRO(DCMTK_TARGET_LINK_LIBRARIES) + +# +# Link a target against other DCMTK modules +# +# DCMTK_TARGET_LINK_MODULES - macro which adds DCMTK modules to a target's dependencies +# TARGET - name of the target that we are called for +# extra arguments - names of the modules that should be added +# +MACRO(DCMTK_TARGET_LINK_MODULES TARGET) + # This macro is called for libraries and apps. Thus, we need some magic. + # 1. During "normal builds", always call TARGET_LINK_LIBRARIES() + # 2. When BUILD_SINGLE_SHARED_LIBRARY, never call it, because neither the + # libraries nor the apps really exist in this mode + # 3. When "just" BUILD_APPS is disabled, only call it for libs, not for apps + # These rules boil down to: If CMake knows the target (this handles all + # cases for apps) and we aren't building a single library (case 2) + IF(TARGET ${TARGET} AND NOT BUILD_SINGLE_SHARED_LIBRARY) + TARGET_LINK_LIBRARIES(${TARGET} ${ARGN}) + ENDIF(TARGET ${TARGET} AND NOT BUILD_SINGLE_SHARED_LIBRARY) +ENDMACRO(DCMTK_TARGET_LINK_MODULES TARGET) + +# This is an ugly hack to simulate global variables +SET(DCMTK_ALL_LIBRARIES CACHE INTERNAL "List of all libraries in the DCMTK.") +SET(DCMTK_LIBRARY_DEPENDENCIES CACHE INTERNAL "Dependencies of the DCMTK libraries.") + +# Failsafe implementation of UNSET for old CMake versions +IF(CMAKE_VERSION VERSION_LESS 2.6.3) + MACRO(DCMTK_UNSET VAR) + SET(${VAR}) + ENDMACRO(DCMTK_UNSET) +ELSE(CMAKE_VERSION VERSION_LESS 2.6.3) + MACRO(DCMTK_UNSET VAR) + UNSET(${VAR}) + ENDMACRO(DCMTK_UNSET) +ENDIF(CMAKE_VERSION VERSION_LESS 2.6.3) + +# Failsafe implementation of UNSET(... CACHE) for old CMake versions +IF(CMAKE_VERSION VERSION_LESS 2.6.3) + MACRO(DCMTK_UNSET_CACHE VAR) + SET(${VAR} CACHE INTERNAL "") + ENDMACRO(DCMTK_UNSET_CACHE) +ELSE(CMAKE_VERSION VERSION_LESS 2.6.3) + MACRO(DCMTK_UNSET_CACHE VAR) + UNSET(${VAR} CACHE) + ENDMACRO(DCMTK_UNSET_CACHE) +ENDIF(CMAKE_VERSION VERSION_LESS 2.6.3) + +# Failsafe implementation of UNSET(... PARENT_SCOPE) for old CMake versions +IF(CMAKE_VERSION VERSION_LESS 3.0) + MACRO(DCMTK_UNSET_PARENT_SCOPE VAR) + SET(${VAR} PARENT_SCOPE) + ENDMACRO(DCMTK_UNSET_PARENT_SCOPE) +ELSE(CMAKE_VERSION VERSION_LESS 3.0) + MACRO(DCMTK_UNSET_PARENT_SCOPE VAR) + UNSET(${VAR} PARENT_SCOPE) + ENDMACRO(DCMTK_UNSET_PARENT_SCOPE) +ENDIF(CMAKE_VERSION VERSION_LESS 3.0) + +# C style atexit for CMake +FUNCTION(DCMTK_ATEXIT_DISPATCHER) + # this will be called at every scope change, but CMAKE_PARENT_LIST_FILE will only + # be empty at exit. + IF(NOT CMAKE_PARENT_LIST_FILE) + FILE(WRITE ${CMAKE_BINARY_DIR}/CMakeTmp/atexit.cmake "${DCMTK_ATEXIT_HOOK}") + DCMTK_UNSET_CACHE(DCMTK_ATEXIT_HOOK) + INCLUDE(${CMAKE_BINARY_DIR}/CMakeTmp/atexit.cmake NO_POLICY_SCOPE) + FILE(REMOVE ${CMAKE_BINARY_DIR}/CMakeTmp/atexit.cmake) + ENDIF() +ENDFUNCTION(DCMTK_ATEXIT_DISPATCHER) + +# Necessary since it's sometimes not correctly cleaned up +DCMTK_UNSET_CACHE(DCMTK_ATEXIT_HOOK) + +MACRO(DCMTK_ATEXIT FUNCTION) + IF(NOT DCMTK_ATEXIT_HOOK) + VARIABLE_WATCH(CMAKE_PARENT_LIST_FILE DCMTK_ATEXIT_DISPATCHER) + ENDIF() + SET(DCMTK_ATEXIT_HOOK "${FUNCTION}(${ARGN})" CACHE INTERNAL "") +ENDMACRO(DCMTK_ATEXIT) diff --git a/CMake/dcmtkPrepare.cmake b/CMake/dcmtkPrepare.cmake new file mode 100644 index 00000000..54ebdb58 --- /dev/null +++ b/CMake/dcmtkPrepare.cmake @@ -0,0 +1,488 @@ +# Set up the build environment. +# This should be run before the individual modules are created. + +# This file should only run once +IF(DEFINED DCMTK_CONFIGURATION_DONE) + RETURN() +ENDIF(DEFINED DCMTK_CONFIGURATION_DONE) +SET(DCMTK_CONFIGURATION_DONE true) + +# Minimum CMake version required +CMAKE_MINIMUM_REQUIRED(VERSION 2.6) +IF(CMAKE_BACKWARDS_COMPATIBILITY GREATER 3.1.1) + SET(CMAKE_BACKWARDS_COMPATIBILITY 3.1.1 CACHE STRING "Latest version of CMake when this project was released." FORCE) +ENDIF(CMAKE_BACKWARDS_COMPATIBILITY GREATER 3.1.1) + +# CMAKE_BUILD_TYPE is set to value "Release" if none is specified by the +# selected build file generator. For those generators that support multiple +# configuration types (e.g. Debug, Release), CMAKE_CONFIGURATION_TYPES holds +# possible values. For other generators this value is empty, and for those +# generators the build type is controlled at CMake time by CMAKE_BUILD_TYPE. +# See http://www.cmake.org/pipermail/cmake/2006-January/008065.html for +# details. +# +# To disable the CMAKE_BUILD_TYPE default value, set CMAKE_BUILD_TYPE to value +# "None" during CMake configuration, e.g. use "-DCMAKE_BUILD_TYPE:STRING=None" +# on the command line. This may be useful if the compiler flags should be +# controlled manually (e.g. as defined in environment variables like CXXFLAGS) +# and no CMake defaults related to the selected configuration type kick in. +IF(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) + MESSAGE(STATUS "Setting build type to 'Release' as none was specified.") + SET(CMAKE_BUILD_TYPE Release CACHE STRING "Choose the type of build." FORCE) + # Set the possible values of build type for cmake-gui + SET_PROPERTY(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" "MinSizeRel" "RelWithDebInfo") +ENDIF(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) + + +# Basic version information +# (Starting with version 3.5.5, an odd number at the last position indicates +# a development snapshot and an even number indicates an official release.) +SET(DCMTK_MAJOR_VERSION 3) +SET(DCMTK_MINOR_VERSION 6) +SET(DCMTK_BUILD_VERSION 1) +# The ABI is not guaranteed to be stable between different snapshots/releases, +# so this particular version number is increased for each snapshot or release. +SET(DCMTK_ABI_VERSION 7) + +# Package "release" settings (some are currently unused and, therefore, disabled) +SET(DCMTK_PACKAGE_NAME "dcmtk") +SET(DCMTK_PACKAGE_DATE "DEV") +SET(DCMTK_PACKAGE_VERSION "${DCMTK_MAJOR_VERSION}.${DCMTK_MINOR_VERSION}.${DCMTK_BUILD_VERSION}") +SET(DCMTK_PACKAGE_VERSION_NUMBER ${DCMTK_MAJOR_VERSION}${DCMTK_MINOR_VERSION}${DCMTK_BUILD_VERSION}) +SET(DCMTK_PACKAGE_VERSION_SUFFIX "") +#SET(DCMTK_PACKAGE_TARNAME "dcmtk-${DCMTK_PACKAGE_VERSION}") +#SET(DCMTK_PACKAGE_STRING "dcmtk ${DCMTK_PACKAGE_VERSION}") +#SET(DCMTK_PACKAGE_BUGREPORT "bugs@dcmtk.org") +#SET(DCMTK_PACKAGE_URL "http://www.dcmtk.org/") + +# Shared library version information +SET(DCMTK_LIBRARY_PROPERTIES VERSION "${DCMTK_PACKAGE_VERSION}" SOVERSION "${DCMTK_ABI_VERSION}") + +# General build options and settings +OPTION(BUILD_APPS "Build command line applications and test programs." ON) +OPTION(BUILD_SHARED_LIBS "Build with shared libraries." OFF) +OPTION(BUILD_SINGLE_SHARED_LIBRARY "Build a single DCMTK library." OFF) +MARK_AS_ADVANCED(BUILD_SINGLE_SHARED_LIBRARY) +SET(CMAKE_DEBUG_POSTFIX "" CACHE STRING "Library postfix for debug builds. Usually left blank.") +SET(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/${DCMTK_CMAKE_INCLUDE}/CMake/") +IF(BUILD_SINGLE_SHARED_LIBRARY) + # When we are building a single shared lib, we are building shared libs :-) + SET(BUILD_SHARED_LIBS ON CACHE BOOL "" FORCE) +ENDIF(BUILD_SINGLE_SHARED_LIBRARY) + +# DCMTK build options +OPTION(DCMTK_WITH_TIFF "Configure DCMTK with support for TIFF." ON) +OPTION(DCMTK_WITH_PNG "Configure DCMTK with support for PNG." ON) +OPTION(DCMTK_WITH_XML "Configure DCMTK with support for XML." ON) +OPTION(DCMTK_WITH_ZLIB "Configure DCMTK with support for ZLIB." ON) +OPTION(DCMTK_WITH_OPENSSL "Configure DCMTK with support for OPENSSL." ON) +OPTION(DCMTK_WITH_SNDFILE "Configure DCMTK with support for SNDFILE." ON) +OPTION(DCMTK_WITH_ICONV "Configure DCMTK with support for ICONV." ON) +IF(NOT WIN32) + OPTION(DCMTK_WITH_WRAP "Configure DCMTK with support for WRAP." ON) +ENDIF(NOT WIN32) +OPTION(DCMTK_ENABLE_PRIVATE_TAGS "Configure DCMTK with support for DICOM private tags coming with DCMTK." OFF) +OPTION(DCMTK_WITH_THREADS "Configure DCMTK with support for multi-threading." ON) +OPTION(DCMTK_WITH_DOXYGEN "Build API documentation with DOXYGEN." ON) +OPTION(DCMTK_GENERATE_DOXYGEN_TAGFILE "Generate a tag file with DOXYGEN." OFF) +OPTION(DCMTK_WIDE_CHAR_FILE_IO_FUNCTIONS "Build with wide char file I/O functions." OFF) +OPTION(DCMTK_WIDE_CHAR_MAIN_FUNCTION "Build command line tools with wide char main function." OFF) + +# Built-in (compiled-in) dictionary enabled on Windows per default, otherwise +# disabled. Loading of external dictionary via run-time is, per default, +# configured the the opposite way since most users won't be interested in using +# the external default dictionary if it is already compiled in. +IF(WIN32 OR MINGW) + OPTION(DCMTK_ENABLE_BUILTIN_DICTIONARY "Configure DCMTK with compiled-in data dictionary" ON) + OPTION(DCMTK_ENABLE_EXTERNAL_DICTIONARY "Configure DCMTK to load external dictionary from default path on startup" OFF) +ELSE(WIN32 or MINGW) # built-in dictionary turned off on Unix per default + OPTION(DCMTK_ENABLE_BUILTIN_DICTIONARY "Configure DCMTK with compiled-in data dictionary" OFF) + OPTION(DCMTK_ENABLE_EXTERNAL_DICTIONARY "Configure DCMTK to load external dictionary from default path on startup" ON) +ENDIF(WIN32 OR MINGW) +if (NOT DCMTK_ENABLE_EXTERNAL_DICTIONARY AND NOT DCMTK_ENABLE_BUILTIN_DICTIONARY) + MESSAGE(WARNING "Either external or built-in dictionary should be enabled, otherwise dictionary must be loaded manually on startup!") +ENDIF(NOT DCMTK_ENABLE_EXTERNAL_DICTIONARY AND NOT DCMTK_ENABLE_BUILTIN_DICTIONARY) + +# Mark various settings as "advanced" +MARK_AS_ADVANCED(CMAKE_DEBUG_POSTFIX) +MARK_AS_ADVANCED(FORCE EXECUTABLE_OUTPUT_PATH LIBRARY_OUTPUT_PATH) +MARK_AS_ADVANCED(SNDFILE_DIR DCMTK_WITH_SNDFILE) # not yet needed in public DCMTK +MARK_AS_ADVANCED(DCMTK_GENERATE_DOXYGEN_TAGFILE) +IF(NOT WIN32) + # support for wide char file I/O functions is currently Windows-specific + MARK_AS_ADVANCED(DCMTK_WIDE_CHAR_FILE_IO_FUNCTIONS) + # support for wide char main function is Windows-specific + MARK_AS_ADVANCED(DCMTK_WIDE_CHAR_MAIN_FUNCTION) +ENDIF(NOT WIN32) + +ENABLE_TESTING() + +#----------------------------------------------------------------------------- +# Include appropriate modules and set required variables for cross compiling +#----------------------------------------------------------------------------- + +IF(CMAKE_CROSSCOMPILING) + IF(WIN32) + INCLUDE(${DCMTK_CMAKE_INCLUDE}CMake/dcmtkUseWine.cmake) + DCMTK_SETUP_WINE() + ELSEIF(ANDROID) + SET(DCMTK_TRY_COMPILE_REQUIRED_CMAKE_FLAGS "-DANDROID_TOOLCHAIN_CONFIG_FILE:INTERNAL=${ANDROID_TOOLCHAIN_CONFIG_FILE}") + INCLUDE(${DCMTK_CMAKE_INCLUDE}CMake/dcmtkUseAndroidSDK.cmake) + IF(NOT DCMTK_ANDROID_TOOLCHAIN_VERIFIED) + # Ensure the configuration variables for the Android device emulator exist in the cache. + DCMTK_SETUP_ANDROID_EMULATOR() + SET(DCMTK_ANDROID_TOOLCHAIN_VERIFIED TRUE CACHE INTERNAL "Set to TRUE to prevent aborting configuration on first Android toolchain run") + MESSAGE(FATAL_ERROR + "Please verify your Android toolchain configuration (e.g.\"ANDROID_NATIVE_API_LEVEL\") is correct before configuring DCMTK.\n" + "Hit \"Configure\" again to resume configuration when you are done.\n" + "NOTE: set \"DCMTK_ANDROID_TOOLCHAIN_VERIFIED\" to \"TRUE\" to avoid this check (e.g. to allow automated builds), you may use" + "something like\n \"cmake -DDCMTK_ANDROID_TOOLCHAIN_VERIFIED=TRUE ...\"\nto achieve that." + ) + ENDIF() + ENDIF() +ENDIF(CMAKE_CROSSCOMPILING) + +#----------------------------------------------------------------------------- +# Generic utilities used for configuring DCMTK +#----------------------------------------------------------------------------- + +INCLUDE(${DCMTK_CMAKE_INCLUDE}CMake/dcmtkMacros.cmake) + +#----------------------------------------------------------------------------- +# Prepare external dependencies for cross compiling +# (i.e. start the emulator if required) +#----------------------------------------------------------------------------- + +IF(CMAKE_CROSSCOMPILING) + UNSET(DCMTK_UNIT_TESTS_UNSUPPORTED_WARN_ONCE CACHE) + IF(ANDROID) + UNSET(DCMTK_TRY_RUN_ANDROID_RUNTIME_INSTALLED CACHE) + DCMTK_ANDROID_START_EMULATOR(DCMTK_ANDROID_EMULATOR_INSTANCE) + DCMTK_ATEXIT(DCMTK_ANDROID_STOP_EMULATOR DCMTK_ANDROID_EMULATOR_INSTANCE) + ENDIF() +ENDIF(CMAKE_CROSSCOMPILING) + +#----------------------------------------------------------------------------- +# Installation sub-directories +#----------------------------------------------------------------------------- + +SET(DCMTK_INSTALL_BINDIR "bin" CACHE STRING "Installation sub-directory for binary executables.") +SET(DCMTK_INSTALL_INCDIR "include" CACHE STRING "Installation sub-directory for header files.") +SET(DCMTK_INSTALL_LIBDIR "lib" CACHE STRING "Installation sub-directory for object code libraries.") +# CMake's files (DCMTKTarget.cmake, DCMTKConfigVersion.cmake and DCMTKConfig.cmake) are installed +# to different installation paths under Unix- and Windows-based systems +IF(UNIX) + SET(DCMTK_INSTALL_CMKDIR "lib/cmake/dcmtk" CACHE STRING "Installation sub-directory for CMake files.") +ELSEIF(WIN32) + SET(DCMTK_INSTALL_CMKDIR "cmake" CACHE STRING "Installation sub-directory for CMake files.") +ENDIF(UNIX) +SET(DCMTK_INSTALL_ETCDIR "etc/dcmtk" CACHE STRING "Installation sub-directory for configuration files.") +SET(DCMTK_INSTALL_DATDIR "share/dcmtk" CACHE STRING "Installation sub-directory for sample files and the like.") +SET(DCMTK_INSTALL_DOCDIR "share/doc/dcmtk" CACHE STRING "Installation sub-directory for general documentation.") +SET(DCMTK_INSTALL_HTMDIR "share/doc/dcmtk/html" CACHE STRING "Installation sub-directory for HTML documentation.") +SET(DCMTK_INSTALL_MANDIR "share/man" CACHE STRING "Installation sub-directory for man pages.") + +MARK_AS_ADVANCED(DCMTK_INSTALL_BINDIR DCMTK_INSTALL_INCDIR DCMTK_INSTALL_LIBDIR DCMTK_INSTALL_CMKDIR + DCMTK_INSTALL_ETCDIR DCMTK_INSTALL_DATDIR DCMTK_INSTALL_DOCDIR DCMTK_INSTALL_HTMDIR + DCMTK_INSTALL_MANDIR) + +#----------------------------------------------------------------------------- +# Build directories +#----------------------------------------------------------------------------- +SET(DCMTK_BUILD_CMKDIR ${CMAKE_BINARY_DIR}) + +#----------------------------------------------------------------------------- +# Start with clean DCMTKTargets.cmake, filled in GenerateCMakeExports.cmake +#----------------------------------------------------------------------------- +FILE(WRITE ${DCMTK_BUILD_CMKDIR}/DCMTKTargets.cmake "") + +#----------------------------------------------------------------------------- +# Platform-independent settings +#----------------------------------------------------------------------------- + +IF(COMMAND CMAKE_POLICY) + # Enable new CMake behaviour when dealing with libraries whose full path is + # given to the linker. This is necessary to avoid warnings in CMake versions + # greater than 2.6. + # See http://www.cmake.org/cmake/help/cmake-2.6.html#policy:CMP0003 + CMAKE_POLICY(SET CMP0003 NEW) + + # Works around warnings about escaped quotes in ADD_DEFINITIONS statements + CMAKE_POLICY(SET CMP0005 OLD) +ENDIF(COMMAND CMAKE_POLICY) + +# pass optional build date to compiler +ADD_DEFINITIONS(-DDCMTK_BUILD_DATE=\\\"2015-09-24\\\") + +# make OFString(NULL) safe by default +ADD_DEFINITIONS(-DUSE_NULL_SAFE_OFSTRING) + +# tell the DCMTK that we are building the DCMTK +ADD_DEFINITIONS(-DDCMTK_BUILD_IN_PROGRESS) + +# build output files in these directories +SET(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib") +SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib") +SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin") + +#----------------------------------------------------------------------------- +# Platform-specific settings +#----------------------------------------------------------------------------- + +# set project wide flags for compiler and linker + +IF(WIN32) + OPTION(DCMTK_OVERWRITE_WIN32_COMPILER_FLAGS "Overwrite compiler flags with DCMTK's WIN32 package default values." ON) +ELSE(WIN32) + SET(DCMTK_OVERWRITE_WIN32_COMPILER_FLAGS OFF) +ENDIF(WIN32) + +IF(DCMTK_OVERWRITE_WIN32_COMPILER_FLAGS AND NOT BUILD_SHARED_LIBS) + + # settings for Microsoft Visual Studio + IF(CMAKE_GENERATOR MATCHES "Visual Studio .*") + # get Visual Studio Version + STRING(REGEX REPLACE "Visual Studio ([0-9]+).*" "\\1" VS_VERSION "${CMAKE_GENERATOR}") + # these settings never change even for C or C++ + SET(CMAKE_C_FLAGS_DEBUG "/MTd /Z7 /Od") + SET(CMAKE_C_FLAGS_RELEASE "/DNDEBUG /MT /O2") + SET(CMAKE_C_FLAGS_MINSIZEREL "/DNDEBUG /MT /O2") + SET(CMAKE_C_FLAGS_RELWITHDEBINFO "/DNDEBUG /MTd /Z7 /Od") + SET(CMAKE_CXX_FLAGS_DEBUG "/MTd /Z7 /Od") + SET(CMAKE_CXX_FLAGS_RELEASE "/DNDEBUG /MT /O2") + SET(CMAKE_CXX_FLAGS_MINSIZEREL "/DNDEBUG /MT /O2") + SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "/DNDEBUG /MTd /Z7 /Od") + # specific settings for the various Visual Studio versions + IF(VS_VERSION EQUAL 6) + SET(CMAKE_C_FLAGS "/nologo /W3 /GX /Gy /YX") + SET(CMAKE_CXX_FLAGS "/nologo /W3 /GX /Gy /YX /Zm500") # /Zm500 increments heap size which is needed on some system to compile templates in dcmimgle + ENDIF(VS_VERSION EQUAL 6) + IF(VS_VERSION EQUAL 7) + SET(CMAKE_C_FLAGS "/nologo /W3 /Gy") + SET(CMAKE_CXX_FLAGS "/nologo /W3 /Gy") + ENDIF(VS_VERSION EQUAL 7) + IF(VS_VERSION GREATER 7) + SET(CMAKE_C_FLAGS "/nologo /W3 /Gy /EHsc") + SET(CMAKE_CXX_FLAGS "/nologo /W3 /Gy /EHsc") + ENDIF(VS_VERSION GREATER 7) + ENDIF(CMAKE_GENERATOR MATCHES "Visual Studio .*") + + # settings for Borland C++ + IF(CMAKE_GENERATOR MATCHES "Borland Makefiles") + # further settings required? not tested for a very long time! + SET(CMAKE_STANDARD_LIBRARIES "import32.lib cw32mt.lib") + ENDIF(CMAKE_GENERATOR MATCHES "Borland Makefiles") + +ENDIF(DCMTK_OVERWRITE_WIN32_COMPILER_FLAGS AND NOT BUILD_SHARED_LIBS) + +IF(BUILD_SHARED_LIBS) + SET(DCMTK_SHARED ON) + IF(BUILD_SINGLE_SHARED_LIBRARY) + # We can't build apps, because there is no way to tell CMake to link apps + # against the library. + SET(BUILD_APPS OFF CACHE BOOL "" FORCE) + # We are building static code that can be used in a shared lib + SET(DCMTK_BUILD_SINGLE_SHARED_LIBRARY ON) + # Make CMake build object libraries. They are just a list of object files + # which aren't linked together yet. + SET(DCMTK_LIBRARY_TYPE OBJECT) + # Static and shared libraries can have dependencies in CMake. Object + # libraries cannot. Since CMake saves dependencies in its cache, we have to + # make sure that it doesn't get confused when a "normal" library turns into + # an object library. Do this via a suffix. + SET(DCMTK_LIBRARY_SUFFIX _obj) + # This uses object libraries which are new in CMake 2.8.8 + CMAKE_MINIMUM_REQUIRED(VERSION 2.8.8) + ENDIF(BUILD_SINGLE_SHARED_LIBRARY) + + OPTION(USE_COMPILER_HIDDEN_VISIBILITY + "Use hidden visibility support if available" ON) + MARK_AS_ADVANCED(USE_COMPILER_HIDDEN_VISIBILITY) + + INCLUDE(CheckCXXCompilerFlag) + CHECK_CXX_COMPILER_FLAG("-fvisibility=hidden" GXX_SUPPORTS_VISIBILITY) + # This "NOT WIN32" is needed due to a CMake bug that was fixed in + # CMake 2.8.x. CHECK_CXX_COMPILER_FLAG() always says "ok" with MSC. + IF(GXX_SUPPORTS_VISIBILITY AND USE_COMPILER_HIDDEN_VISIBILITY AND NOT WIN32) + SET(HAVE_HIDDEN_VISIBILITY ON) + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden") + SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fvisibility=hidden") + ELSE(GXX_SUPPORTS_VISIBILITY AND USE_COMPILER_HIDDEN_VISIBILITY AND NOT WIN32) + SET(HAVE_HIDDEN_VISIBILITY) + ENDIF(GXX_SUPPORTS_VISIBILITY AND USE_COMPILER_HIDDEN_VISIBILITY AND NOT WIN32) +ENDIF(BUILD_SHARED_LIBS) + +IF(WIN32) # special handling for Windows systems + + IF(MINGW) + # Avoid auto-importing warnings on MinGW + SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--enable-auto-import") + ELSE(MINGW) + # On Visual Studio 8 MS deprecated C. This removes all 1.276E1265 security warnings. + IF(NOT BORLAND) + IF(NOT CYGWIN) + IF(NOT DCMTK_ENABLE_VISUAL_STUDIO_DEPRECATED_C_WARNINGS) + ADD_DEFINITIONS( + -D_CRT_FAR_MAPPINGS_NO_DEPRECATE + -D_CRT_IS_WCTYPE_NO_DEPRECATE + -D_CRT_MANAGED_FP_NO_DEPRECATE + -D_CRT_NONSTDC_NO_DEPRECATE + -D_CRT_SECURE_NO_DEPRECATE + -D_CRT_SECURE_NO_DEPRECATE_GLOBALS + -D_CRT_SETERRORMODE_BEEP_SLEEP_NO_DEPRECATE + -D_CRT_TIME_FUNCTIONS_NO_DEPRECATE + -D_CRT_VCCLRIT_NO_DEPRECATE + -D_SCL_SECURE_NO_DEPRECATE + ) + ENDIF(NOT DCMTK_ENABLE_VISUAL_STUDIO_DEPRECATED_C_WARNINGS) + ENDIF(NOT CYGWIN) + ENDIF(NOT BORLAND) + ENDIF(MINGW) + +ELSE(WIN32) # ... for non-Windows systems + + # Compiler flags for Mac OS X + IF(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D_XOPEN_SOURCE_EXTENDED -D_BSD_SOURCE -D_BSD_COMPAT -D_OSF_SOURCE -D_DARWIN_C_SOURCE") + SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_XOPEN_SOURCE_EXTENDED -D_BSD_SOURCE -D_BSD_COMPAT -D_OSF_SOURCE -D_DARWIN_C_SOURCE") + # FreeBSD and newer versions of OpenBSD fail with these flags + ELSEIF(NOT ${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD" AND (NOT ${CMAKE_SYSTEM_NAME} MATCHES "OpenBSD" OR ${CMAKE_SYSTEM_VERSION} VERSION_LESS 4)) + # Compiler flags for all other non-Windows systems + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D_XOPEN_SOURCE_EXTENDED -D_XOPEN_SOURCE=500 -D_BSD_SOURCE -D_DEFAULT_SOURCE -D_BSD_COMPAT -D_OSF_SOURCE -D_POSIX_C_SOURCE=199506L") + SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_XOPEN_SOURCE_EXTENDED -D_XOPEN_SOURCE=500 -D_BSD_SOURCE -D_DEFAULT_SOURCE -D_BSD_COMPAT -D_OSF_SOURCE -D_POSIX_C_SOURCE=199506L") + ENDIF() + + OPTION(DCMTK_FORCE_FPIC_ON_UNIX "Add -fPIC compiler flag on unix 64 bit machines to allow linking from dynamic libraries even if DCMTK is built statically" OFF) + MARK_AS_ADVANCED(DCMTK_FORCE_FPIC_ON_UNIX) + + # Setting for IA64 / x86_64 which needs -fPIC compiler flag required for shared library build on these platforms + IF(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64" AND UNIX AND DCMTK_FORCE_FPIC_ON_UNIX) + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC") + SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC") + ENDIF(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64" AND UNIX AND DCMTK_FORCE_FPIC_ON_UNIX) + +ENDIF(WIN32) + +# define libraries and object files that must be linked to most Windows applications +IF(WIN32) + SET(WIN32_STD_LIBRARIES ws2_32 netapi32 wsock32) + IF(NOT DEFINED MINGW) + # additional object file needed for wildcard expansion; for wchar_t* support, use 'wsetargv' + SET(WIN32_STD_OBJECTS setargv) + ENDIF(NOT DEFINED MINGW) + # settings for Borland C++ + IF(CMAKE_CXX_COMPILER MATCHES bcc32) + # to be checked: further settings required? + SET(CMAKE_STANDARD_LIBRARIES "import32.lib cw32mt.lib") + ENDIF(CMAKE_CXX_COMPILER MATCHES bcc32) +ENDIF(WIN32) + +# add definition of "DEBUG" to debug mode (since CMake does not do this automatically) +SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DDEBUG") +SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DDEBUG") + +#----------------------------------------------------------------------------- +# Third party libraries +#----------------------------------------------------------------------------- + +INCLUDE(${DCMTK_CMAKE_INCLUDE}CMake/3rdparty.cmake) + +#----------------------------------------------------------------------------- +# C++11 support +#----------------------------------------------------------------------------- + +MACRO(GET_CXX_VERSION VERSION) + EXECUTE_PROCESS(COMMAND ${CMAKE_CXX_COMPILER} --version OUTPUT_VARIABLE ${VERSION}) + STRING(REGEX REPLACE "^.*[ ]([0-9]\\.[0-9]\\.[0-9]).*$" "\\1" ${VERSION} "${${VERSION}}") +ENDMACRO(GET_CXX_VERSION VERSION) + +MACRO(ALLOW_CXX11_SUPPORT FLAGS) + IF(NOT DCMTK_CXX11_FLAGS) + SET(DCMTK_CXX11_FLAGS ${FLAGS} CACHE STRING "Flags used to enable C++11 support.") + ENDIF() + IF(DCMTK_USE_CXX11_STL) + MESSAGE(STATUS "Info: Configured DCMTK to use native C++11 features.") + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${DCMTK_CXX11_FLAGS}") + SET(DCMTK_TRY_COMPILE_REQUIRED_CMAKE_FLAGS ${DCMTK_TRY_COMPILE_REQUIRED_CMAKE_FLAGS} "-DCMAKE_CXX_FLAGS:STRING=${DCMTK_CXX11_FLAGS}") + ELSE() + MESSAGE(STATUS "Info: Your compiler supports C++11. You may enable C++11 features via \"DCMTK_USE_CXX11_STL\" to create a C++11 build of DCMTK.") + SET(DCMTK_USE_CXX11_STL OFF CACHE BOOL "Enable or disable C++11 while building DCMTK.") + ENDIF() +ENDMACRO(ALLOW_CXX11_SUPPORT) + +MACRO(DENY_CXX11_SUPPORT) + IF(DCMTK_USE_CXX11_STL) + IF(DCMTK_CXX11_FLAGS AND NOT DCMTK_CXX11_FLAGS STREQUAL "unknown") + MESSAGE(STATUS "Info: Enabling C++11 support with custom flags \"${DCMTK_CXX11_FLAGS}\" for a potentially unsupported compiler.") + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${DCMTK_CXX11_FLAGS}") + SET(DCMTK_TRY_COMPILE_REQUIRED_CMAKE_FLAGS ${DCMTK_TRY_COMPILE_REQUIRED_CMAKE_FLAGS} "-DCMAKE_CXX_FLAGS:STRING=${DCMTK_CXX11_FLAGS}") + ELSE() + MESSAGE(WARNING "DCMTK has been configured to use the C++11 STL, but the compiler does not seem to support C++11. Override this warning by setting DCMTK_CXX11_FLAGS to tell DCMTK how to enable C++11 support for your compiler.") + SET(DCMTK_CXX11_FLAGS "unknown" CACHE STRING "Flags used to enable C++11 support.") + ENDIF() + ENDIF() +ENDMACRO(DENY_CXX11_SUPPORT) + +IF(CMAKE_COMPILER_IS_GNUCXX) + GET_CXX_VERSION(GXX_VERSION) + IF(GXX_VERSION VERSION_GREATER 4.8.1 OR GXX_VERSION VERSION_EQUAL 4.8.1) + ALLOW_CXX11_SUPPORT("-std=c++11") + ELSE() + DENY_CXX11_SUPPORT() + ENDIF() +ELSEIF(CMAKE_CXX_COMPILER_ID MATCHES "Clang") + GET_CXX_VERSION(CLANG_VERSION) + IF(CLANG_VERSION VERSION_GREATER 3.3 OR CLANG_VERSION VERSION_EQUAL 3.3) + ALLOW_CXX11_SUPPORT("-std=c++11") + ELSE() + DENY_CXX11_SUPPORT() + ENDIF() +ELSE() + DENY_CXX11_SUPPORT() +ENDIF() + +#----------------------------------------------------------------------------- +# DCMTK libraries +#----------------------------------------------------------------------------- + +INCLUDE(${DCMTK_CMAKE_INCLUDE}CMake/GenerateDCMTKConfigure.cmake) + +#----------------------------------------------------------------------------- +# Dart configuration (disabled per default) +#----------------------------------------------------------------------------- + +# Includes build targets Experimental, Nightly and Continuous which are the standard +# groups pre-configured in Dashboard. In CTest these groups are called "Tracks". +# +# INCLUDE(${CMAKE_ROOT}/Modules/Dart.cmake) +# IF(BUILD_TESTING) +# ENABLE_TESTING() +# ENDIF(BUILD_TESTING) + +#----------------------------------------------------------------------------- +# Thread support +#----------------------------------------------------------------------------- + +# See dcmtk/config/configure.in +IF(WITH_THREADS) + ADD_DEFINITIONS(-D_REENTRANT) + IF(HAVE_PTHREAD_RWLOCK) + IF(APPLE) + ADD_DEFINITIONS(-D_XOPEN_SOURCE_EXTENDED -D_BSD_SOURCE -D_BSD_COMPAT -D_OSF_SOURCE) + ENDIF(APPLE) + IF("${CMAKE_SYSTEM_NAME}" MATCHES "^IRIX") + ADD_DEFINITIONS(-D_XOPEN_SOURCE_EXTENDED -D_BSD_SOURCE -D_BSD_COMPAT) + ENDIF("${CMAKE_SYSTEM_NAME}" MATCHES "^IRIX") + ENDIF(HAVE_PTHREAD_RWLOCK) + + IF(HAVE_PTHREAD_H) + CHECK_LIBRARY_EXISTS(pthread pthread_key_create "" HAVE_LIBPTHREAD) + IF(HAVE_LIBPTHREAD) + SET(THREAD_LIBS pthread) + ENDIF(HAVE_LIBPTHREAD) + CHECK_LIBRARY_EXISTS(rt sem_init "" HAVE_LIBRT) + IF(HAVE_LIBRT) + SET(THREAD_LIBS ${THREAD_LIBS} rt) + ENDIF(HAVE_LIBRT) + ENDIF(HAVE_PTHREAD_H) +ENDIF(WITH_THREADS) diff --git a/CMake/dcmtkTestCharSignedness.cc b/CMake/dcmtkTestCharSignedness.cc new file mode 100755 index 00000000..a25633c1 --- /dev/null +++ b/CMake/dcmtkTestCharSignedness.cc @@ -0,0 +1,6 @@ +/* Return 1 for char signed and 0 for char unsigned. */ +int main() +{ + unsigned char uc = 255; + return (*reinterpret_cast(&uc) < 0)?1:0; +} diff --git a/CMake/dcmtkTryCompile.cmake b/CMake/dcmtkTryCompile.cmake new file mode 100644 index 00000000..102864d2 --- /dev/null +++ b/CMake/dcmtkTryCompile.cmake @@ -0,0 +1,43 @@ +# +# Check if a given C++ source code compiles +# +# VAR - Variable to set to 1 or 0, depending on the result +# MESSAGE - Description of the thing that we are checking for +# SOURCE - Code to compile +# +# All extra arguments are passed to TRY_COMPILE(). +# + +MACRO(DCMTK_TRY_COMPILE VAR MESSAGE SOURCE) + SET(DCMTK_TRY_COMPILE_FILE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/src.cxx") + + # Do nothing if the variable is already set + IF(NOT DEFINED "${VAR}") + MESSAGE(STATUS "Checking whether ${MESSAGE}") + FILE(WRITE "${DCMTK_TRY_COMPILE_FILE}" "${SOURCE}\n") + IF(DCMTK_TRY_COMPILE_REQUIRED_CMAKE_FLAGS) + SET(DCMTK_TRY_COMPILE_CMAKE_FLAGS CMAKE_FLAGS ${DCMTK_TRY_COMPILE_REQUIRED_CMAKE_FLAGS}) + ELSE() + DCMTK_UNSET(DCMTK_TRY_COMPILE_CMAKE_FLAGS) + ENDIF() + TRY_COMPILE(${VAR} + ${CMAKE_BINARY_DIR} + ${DCMTK_TRY_COMPILE_FILE} + ${DCMTK_TRY_COMPILE_CMAKE_FLAGS} + OUTPUT_VARIABLE OUTPUT + ${ARGN}) + IF(${VAR}) + MESSAGE(STATUS "Checking whether ${MESSAGE} -- yes") + SET(${VAR} 1 CACHE INTERNAL "${MESSAGE}") + FILE(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log + "${MESSAGE} passed with the following output:\n" + "${OUTPUT}\n") + ELSE(${VAR}) + MESSAGE(STATUS "Checking whether ${MESSAGE} -- no") + SET(${VAR} 0 CACHE INTERNAL "${MESSAGE}") + FILE(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log + "${MESSAGE} failed with the following output:\n" + "${OUTPUT}\n") + ENDIF(${VAR}) + ENDIF(NOT DEFINED "${VAR}") +ENDMACRO(DCMTK_TRY_COMPILE) diff --git a/CMake/dcmtkTryRun.cmake b/CMake/dcmtkTryRun.cmake new file mode 100644 index 00000000..beba7ef3 --- /dev/null +++ b/CMake/dcmtkTryRun.cmake @@ -0,0 +1,99 @@ +# +# Wrapper implementation of TRY_RUN(), with some support for +# cross-compiling +# +# Usage and syntax is equivalent to CMake's TRY_RUN(). +# + +# CMakeParseArguments was introduced in CMake 2.8.3. +# DCMTK_TRY_RUN will revert to CMake's internal TRY_RUN() +# for versions prior to 2.8.3, as arguments can't be parsed +# in that case. This means cross compiling support will be +# disabled for CMake versions prior to 2.8.3. +IF(CMAKE_VERSION VERSION_LESS 2.8.3) + +MACRO(DCMTK_TRY_RUN) + TRY_RUN(${ARGN}) +ENDMACRO(DCMTK_TRY_RUN) + +ELSE(CMAKE_VERSION VERSION_LESS 2.8.3) + +INCLUDE(CMakeParseArguments) + +FUNCTION(DCMTK_TRY_RUN_CROSS RUN_RESULT_VAR COMPILE_RESULT_VAR bindir srcfile) + CMAKE_PARSE_ARGUMENTS(DCMTK_TRY_RUN + "" + "COMPILE_OUTPUT_VARIABLE;RUN_OUTPUT_VARIABLE;OUTPUT_VARIABLE" + "CMAKE_FLAGS;COMPILE_DEFINITIONS;ARGS" + ${ARGN} + ) + GET_FILENAME_COMPONENT(OUTPUT_EXECUTABLE_NAME ${srcfile} NAME) + SET(OUTPUT_EXECUTABLE_NAME ${OUTPUT_EXECUTABLE_NAME}${CMAKE_EXECUTABLE_SUFFIX}) + SET(OUTPUT_EXECUTABLE ${bindir}/${OUTPUT_EXECUTABLE_NAME}) + SET(TRY_COMPILE_ARGS ${COMPILE_RESULT_VAR} ${bindir} ${srcfile}) + IF(DCMTK_TRY_RUN_CMAKE_FLAGS) + LIST(APPEND TRY_COMPILE_ARGS CMAKE_FLAGS ${DCMTK_TRY_RUN_CMAKE_FLAGS} ${DCMTK_TRY_COMPILE_REQUIRED_CMAKE_FLAGS}) + ELSEIF(DCMTK_TRY_COMPILE_REQUIRED_CMAKE_FLAGS) + LIST(APPEND TRY_COMPILE_ARGS CMAKE_FLAGS ${DCMTK_TRY_COMPILE_REQUIRED_CMAKE_FLAGS}) + ENDIF() + IF(DCMTK_TRY_RUN_COMPILE_DEFINITIONS) + LIST(APPEND TRY_COMPILE_ARGS COMPILE_DEFINITIONS ${DCMTK_TRY_RUN_COMPILE_DEFINITIONS}) + ENDIF() + IF(DCMTK_TRY_RUN_COMPILE_OUTPUT_VARIABLE) + LIST(APPEND TRY_COMPILE_ARGS OUTPUT_VARIABLE ${DCMTK_TRY_RUN_COMPILE_OUTPUT_VARIABLE}) + ENDIF() + TRY_COMPILE(${TRY_COMPILE_ARGS} COPY_FILE ${OUTPUT_EXECUTABLE}) + SET(${COMPILE_RESULT_VAR} ${${COMPILE_RESULT_VAR}} PARENT_SCOPE) + IF(DCMTK_TRY_RUN_COMPILE_OUTPUT_VARIABLE) + SET(${DCMTK_TRY_RUN_COMPILE_OUTPUT_VARIABLE} ${${DCMTK_TRY_RUN_COMPILE_OUTPUT_VARIABLE}} PARENT_SCOPE) + ENDIF() + IF(${COMPILE_RESULT_VAR}) + IF(WIN32) + WINE_COMMAND(CMD ${OUTPUT_EXECUTABLE} ${DCMTK_TRY_RUN_ARGS}) + IF(CMD) + EXECUTE_PROCESS( + COMMAND ${CMD} + RESULT_VARIABLE ${RUN_RESULT_VAR} + OUTPUT_VARIABLE ${DCMTK_TRY_RUN_RUN_OUTPUT_VARIABLE} + ERROR_VARIABLE ${DCMTK_TRY_RUN_RUN_OUTPUT_VARIABLE} + ) + ENDIF() + ELSEIF(ANDROID) + DCMTK_ANDROID_WAIT_FOR_EMULATOR(DCMTK_ANDROID_EMULATOR_INSTANCE) + IF(NOT DCMTK_TRY_RUN_ANDROID_RUNTIME_INSTALLED) + DCMTK_ANDROID_FIND_RUNTIME_LIBRARIES(ANDROID_RUNTIME_LIBRARIES) + SET(ANDROID_RUNTIME_LIBRARIES ${ANDROID_RUNTIME_LIBRARIES} CACHE INTERNAL "") + DCMTK_ANDROID_PUSH(DCMTK_ANDROID_EMULATOR_INSTANCE ${ANDROID_RUNTIME_LIBRARIES} DESTINATION ${ANDROID_TEMPORARY_FILES_LOCATION}) + SET(DCMTK_TRY_RUN_ANDROID_RUNTIME_INSTALLED TRUE CACHE INTERNAL "") + ENDIF() + DCMTK_ANDROID_PUSH(DCMTK_ANDROID_EMULATOR_INSTANCE ${OUTPUT_EXECUTABLE} DESTINATION ${ANDROID_TEMPORARY_FILES_LOCATION}/${OUTPUT_EXECUTABLE_NAME}) + DCMTK_ANDROID_SHELL(DCMTK_ANDROID_EMULATOR_INSTANCE + COMMAND chmod 755 ${ANDROID_TEMPORARY_FILES_LOCATION}/${OUTPUT_EXECUTABLE_NAME} + OUTPUT_QUIET + ERROR_QUIET + ) + DCMTK_ANDROID_SHELL(DCMTK_ANDROID_EMULATOR_INSTANCE + COMMAND "LD_LIBRARY_PATH=\$LD_LIBRARY_PATH:${ANDROID_TEMPORARY_FILES_LOCATION}" ${ANDROID_TEMPORARY_FILES_LOCATION}/${OUTPUT_EXECUTABLE_NAME} ${DCMTK_TRY_RUN_ARGS} + RESULT_VARIABLE ${RUN_RESULT_VAR} + OUTPUT_VARIABLE ${DCMTK_TRY_RUN_RUN_OUTPUT_VARIABLE} + ERROR_VARIABLE ${DCMTK_TRY_RUN_RUN_OUTPUT_VARIABLE} + ) + ELSE() + MESSAGE(WARNING "Emulation for your target platform is not available, please fill in the required configure test results manually.") + TRY_RUN(${RUN_RESULT_VAR} ${COMPILE_RESULT_VAR} ${bindir} ${srcfile} ${ARGN}) + RETURN() + ENDIF() + SET(${RUN_RESULT_VAR} ${${RUN_RESULT_VAR}} PARENT_SCOPE) + SET(${DCMTK_TRY_RUN_RUN_OUTPUT_VARIABLE} ${${DCMTK_TRY_RUN_RUN_OUTPUT_VARIABLE}} PARENT_SCOPE) + ENDIF() +ENDFUNCTION(DCMTK_TRY_RUN_CROSS) + +MACRO(DCMTK_TRY_RUN) + IF(CMAKE_CROSSCOMPILING) + DCMTK_TRY_RUN_CROSS(${ARGN}) + ELSE(CMAKE_CROSSCOMPILING) + TRY_RUN(${ARGN}) + ENDIF(CMAKE_CROSSCOMPILING) +ENDMACRO(DCMTK_TRY_RUN) + +ENDIF(CMAKE_VERSION VERSION_LESS 2.8.3) diff --git a/CMake/dcmtkUseAndroidSDK.cmake b/CMake/dcmtkUseAndroidSDK.cmake new file mode 100644 index 00000000..925423e5 --- /dev/null +++ b/CMake/dcmtkUseAndroidSDK.cmake @@ -0,0 +1,618 @@ +# +# Functions for detection and usage of then Android SDK +# Used when cross compiling for Android +# +# The Android device emulator (included in the SDK) can +# be "remote" controlled by the functions and macros +# implemented in this file. +# They are employing a pseudo object-oriented approach +# to handle an emulator instance, that is an emulator +# instance is described by a so called emulator instance +# object handle which has to be passed to all functions +# operating on it as their first argument. +# Android emulator object handles consist of the +# following properties, which need to be tracked to +# describe and Android emulator instance: +# EMULATOR_STATE: the state of the emulator instance, +# can be one of the following values: +# * STARTING - the instance has been initialized +# and the emulator has been executed +# * RUNNING - the emulated device is online and +# can receive instructions +# * STOPPED - the emulated device has been +# shutdown or is currently being +# shutdown +# EMULATOR_UUID: a generated ID to identify the emulator +# instance. Meant to prevent accessing the wrong device +# in case multiple Android devices are accessible. +# EMULATOR_NAME: the name of the emulator instance. +# all running emulator instances are named by the SDK +# in a locally unique fashion. The name will only be +# available in case the state is 'RUNNING', since +# only the name of running devices can be retrieved +# by UUID matching. +# An emulator instance is accessed by the different +# tools of the NDK (e. g. 'adb') by referring to the +# instance with the value of EMULATOR_NAME. + +INCLUDE(CMakeParseArguments) + +# +# 'Unpacks' an Android emulator instance handle object to +# individual components. +# VAR - the emulator instance handle object to unpack +# EMULATOR_STATE - will contain the emulators state +# EMULATOR_UUID - will contain the generated UUID that +# identifies the emulator instance +# EMULATOR_NAME - will contain the instance name, required +# to access the emulator via 'adb' etc. +# All three outputs will be unset if the object in VAR +# is not a valid emulator instance handle. +# All additional arguments will be ignored. +# +MACRO(DCMTK_ANDROID_GET_OBJECT_PROPERTIES VAR) + LIST(LENGTH ${VAR} ${VAR}_LENGTH) + IF(${VAR}_LENGTH EQUAL 3) + LIST(GET ${VAR} 0 EMULATOR_STATE) + LIST(GET ${VAR} 1 EMULATOR_UUID) + LIST(GET ${VAR} 2 EMULATOR_NAME) + ELSE() + UNSET(EMULATOR_STATE) + UNSET(EMULATOR_UUID) + UNSET(EMULATOR_NAME) + ENDIF() +ENDMACRO(DCMTK_ANDROID_GET_OBJECT_PROPERTIES) + +# +# Stores the properties of an emulator instance inside an +# emulator instance handle object. +# VAR - the name of the variable that shall contain the +# resulting instance handle object. +# EMULATOR_STATE - the state to set +# EMULATOR_UUID - the UUID to set +# EMULATOR_NAME - the name to set +# All additional arguments will be ignored. +# +MACRO(DCMTK_ANDROID_SET_OBJECT_PROPERTIES VAR EMULATOR_STATE EMULATOR_UUID EMULATOR_NAME) + SET(${VAR} "${EMULATOR_STATE}" "${EMULATOR_UUID}" "${EMULATOR_NAME}" CACHE INTERNAL "") +ENDMACRO(DCMTK_ANDROID_SET_OBJECT_PROPERTIES) + +# +# Destroys an instance handle object. +# VAR - the name of the variable its emulator instance handle +# shall be object destroyed +# All additional arguments will be ignored. +# +MACRO(DCMTK_ANDROID_DESTROY_OBJECT VAR) + UNSET(${VAR} CACHE) +ENDMACRO(DCMTK_ANDROID_DESTROY_OBJECT) + +# +# Tries to detect any required shared objects within the NDK +# VAR - the name of the variable that will receive a list +# of required shared object files (if any) +# Will set VAR to an empty list if no shared objects are +# required (e. g. when they are linked statically). +# All additional arguments will be ignored. +# +FUNCTION(DCMTK_ANDROID_FIND_RUNTIME_LIBRARIES VAR) + SET(CMAKE_FIND_LIBRARY_SUFFIXES ".so") + FOREACH(DIR ${ANDROID_STL_INCLUDE_DIRS}) + IF(CMAKE_VERSION VERSION_LESS 2.8.11) + GET_FILENAME_COMPONENT(DIR ${DIR} PATH) + ELSE() + GET_FILENAME_COMPONENT(DIR ${DIR} DIRECTORY) + ENDIF() + LIST(APPEND ANDROID_STL_LIBRARY_DIRS ${DIR}) + ENDFOREACH() + FIND_LIBRARY(ANDROID_STL_SHARED_OBJECT ${ANDROID_STL} PATHS ${ANDROID_STL_LIBRARY_DIRS} NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH) + IF(ANDROID_STL_SHARED_OBJECT) + SET(${VAR} ${ANDROID_STL_SHARED_OBJECT} PARENT_SCOPE) + ENDIF() +ENDFUNCTION(DCMTK_ANDROID_FIND_RUNTIME_LIBRARIES) + +# +# Tries to detect the required executables and scripts automatically, +# which should be contained in the Android SDK. Emits an error that +# will halt the configuration process if that is not possible. +# Will also detect all available AVDs after tool detection was +# successful. +# All arguments will be ignored. +# +FUNCTION(DCMTK_SETUP_ANDROID_EMULATOR) + IF(NOT ANDROID_TEMPORARY_FILES_LOCATION) + SET(ANDROID_TEMPORARY_FILES_LOCATION "/cache" CACHE STRING "The path on the Android device that should be used for temporary files") + ENDIF() + IF(NOT ANDROID_SDK_ROOT) + IF(CMAKE_HOST_SYSTEM MATCHES "Windows.*") + FILE(TO_CMAKE_PATH "$ENV{PROGRAMFILES}" ANDROID_SDK_SEARCH_PATHS) + SET(ANDROID_SDK_ROOT "${ANDROID_SDK_SEARCH_PATHS}/android-sdk" CACHE PATH "Location of the Android SDK") + ELSE() + SET(ANDROID_SDK_ROOT "/opt/android-sdk" CACHE PATH "Location of the Android SDK") + ENDIF() + ENDIF() + FIND_PROGRAM(ANDROID_EMULATOR_PROGRAM emulator PATHS ${ANDROID_SDK_ROOT} PATH_SUFFIXES tools NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH) + IF(CMAKE_HOST_SYSTEM MATCHES "Windows.*") + FIND_PROGRAM(ANDROID_ANDROID_PROGRAM android.bat PATHS ${ANDROID_SDK_ROOT} PATH_SUFFIXES tools NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH) + ELSE() + FIND_PROGRAM(ANDROID_ANDROID_PROGRAM android PATHS ${ANDROID_SDK_ROOT} PATH_SUFFIXES tools NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH) + ENDIF() + FIND_PROGRAM(ANDROID_ADB_PROGRAM adb PATHS ${ANDROID_SDK_ROOT} PATH_SUFFIXES platform-tools NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH) + IF(NOT ANDROID_EMULATOR_PROGRAM OR NOT ANDROID_ANDROID_PROGRAM OR NOT ANDROID_ADB_PROGRAM) + MESSAGE(FATAL_ERROR + "Failed to detect the Android SDK, please set ANDROID_SDK_ROOT to the location of your Android SDK" + "or set the missing tools manually!" + ) + ELSE() + EXECUTE_PROCESS(COMMAND ${ANDROID_ANDROID_PROGRAM} list avd RESULT_VARIABLE RESULT OUTPUT_VARIABLE OUTPUT ERROR_QUIET) + STRING(REGEX MATCHALL "Name:[ \t]*[^\r\n]*" ANDROID_AVAILABLE_AVDS ${OUTPUT}) + STRING(REGEX REPLACE "Name:[ \t]*([^\r\n;]*)" "\\1" ANDROID_AVAILABLE_AVDS "${ANDROID_AVAILABLE_AVDS}") + SET(ANDROID_EMULATOR_AVD "${ANDROID_EMULATOR_AVD}" CACHE STRING "Android emulator Android Virtual Device (AVD) configuration" FORCE) + SET_PROPERTY(CACHE ANDROID_EMULATOR_AVD PROPERTY STRINGS ${ANDROID_AVAILABLE_AVDS}) + ENDIF() +ENDFUNCTION(DCMTK_SETUP_ANDROID_EMULATOR) + +# +# Enumerates all currently available Android devices +# (started emulators and connected devices) and separates +# them into two different lists. +# ONLINE - the name of the variable that will be set to a +# list of all currently online devices' names +# (devices that can receive instructions) +# OFFLINE - the name of the variable that will be set to a +# list of all currently offline device's names +# (devices that are connected but cannot receive +# instructions) +# Will ignore all additional arguments. +# +FUNCTION(DCMTK_ANDROID_LIST_EMULATORS ONLINE OFFLINE) + DCMTK_SETUP_ANDROID_EMULATOR() + IF(ANDROID_ADB_PROGRAM) + EXECUTE_PROCESS( + COMMAND ${ANDROID_ADB_PROGRAM} devices + RESULT_VARIABLE RESULT + OUTPUT_VARIABLE DEVICES_RAW + ERROR_QUIET + ) + STRING(REPLACE "\n" ";" DEVICES "${DEVICES_RAW}") + FOREACH(DEVICE ${DEVICES}) + STRING(REGEX REPLACE "(.+)\t(.+)" "\\1;\\2" DS "${DEVICE}") + LIST(LENGTH DS DSL) + IF(DSL EQUAL 2) + LIST(GET DS 0 EMULATOR_NAME) + LIST(GET DS 1 EMULATOR_STATE) + IF(EMULATOR_STATE MATCHES "^device$") + LIST(APPEND ${ONLINE} ${EMULATOR_NAME}) + ELSE() + LIST(APPEND ${OFFLINE} ${EMULATOR_NAME}) + ENDIF() + ENDIF() + ENDFOREACH() + ENDIF() + SET(${ONLINE} ${${ONLINE}} PARENT_SCOPE) + SET(${OFFLINE} ${${OFFLINE}} PARENT_SCOPE) +ENDFUNCTION(DCMTK_ANDROID_LIST_EMULATORS) + +# +# Generate a random ID that is hopefully unique +# enough to be used as the instance UUID. +# VAR - the name of the variable that will receive +# the generated UUID as a string value +# Will ignore all additional arguments. +# +IF(CMAKE_VERSION VERSION_LESS 2.8.11) +MACRO(DCMTK_ANDROID_EMULATOR_GENERATE_UUID VAR) + STRING(RANDOM LENGTH 20 ALPHABET "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" ${VAR}) +ENDMACRO(DCMTK_ANDROID_EMULATOR_GENERATE_UUID) +ELSE(CMAKE_VERSION VERSION_LESS 2.8.11) +FUNCTION(DCMTK_ANDROID_EMULATOR_GENERATE_UUID VAR) + STRING(RANDOM LENGTH 20 RAND) + STRING(TIMESTAMP TM) + SET(${VAR} "${TM}${RAND}") + STRING(MD5 ${VAR} ${${VAR}}) + SET(${VAR} ${${VAR}} PARENT_SCOPE) +ENDFUNCTION(DCMTK_ANDROID_EMULATOR_GENERATE_UUID) +ENDIF(CMAKE_VERSION VERSION_LESS 2.8.11) + +# +# Tries to query the UUID property of an accessible Android device. +# EMULATOR_NAME - the device name, as returned by DCMTK_ANDROID_LIST_EMULATORS +# VAR - the name of the variable that will be set to the device UUID +# Will unset the variable referred to by VAR if no device with the given name +# is accessible or the device is offline. +# Will ignore all additional arguments. +# +FUNCTION(DCMTK_ANDROID_GET_EMULATOR_UUID EMULATOR_NAME VAR) + EXECUTE_PROCESS( + COMMAND ${ANDROID_ADB_PROGRAM} -s ${EMULATOR_NAME} shell getprop + RESULT_VARIABLE RESULT + OUTPUT_VARIABLE OUTPUT + ERROR_QUIET + ) + DCMTK_UNSET_PARENT_SCOPE(${VAR}) + IF(NOT RESULT) + STRING(REGEX REPLACE ".*\\[emu\\.uuid\\]: \\[([^]]+)\\].*" "\\1" ${VAR} "${OUTPUT}") + IF(${VAR}) + SET(${VAR} ${${VAR}} PARENT_SCOPE) + ENDIF() + ENDIF() +ENDFUNCTION(DCMTK_ANDROID_GET_EMULATOR_UUID) + +# +# Retrieves the name of the emulator instance referred to by +# the given UUID. Will wait until the device becomes online +# to query the name. +# VAR - the name of the variable that will be set +# to the device name +# EMULATOR_UUID - the emulator UUID of the device to inquired +# Will wait until all available devices are online or the right +# one has been found. +# Will ignore all additional arguments. +# +FUNCTION(DCMTK_ANDROID_GET_EMULATOR_NAME VAR EMULATOR_UUID) + DCMTK_ANDROID_LIST_EMULATORS(ONLINE_EMULATORS OFFLINE_EMULATORS) + FOREACH(EMULATOR ${ONLINE_EMULATORS}) + DCMTK_ANDROID_GET_EMULATOR_UUID(${EMULATOR} UUID) + IF(EMULATOR_UUID STREQUAL UUID) + SET(${VAR} ${EMULATOR} PARENT_SCOPE) + RETURN() + ENDIF() + ENDFOREACH() + WHILE(OFFLINE_EMULATORS) + LIST(GET OFFLINE_EMULATORS 0 EMULATOR) + LIST(REMOVE_AT OFFLINE_EMULATORS 0) + EXECUTE_PROCESS( + COMMAND ${ANDROID_ADB_PROGRAM} -s ${EMULATOR} wait-for-device + TIMEOUT 1 + RESULT_VARIABLE RESULT + OUTPUT_QUIET + ERROR_QUIET + ) + IF(NOT RESULT) + DCMTK_ANDROID_GET_EMULATOR_UUID(${EMULATOR} UUID) + IF(UUID) + IF(EMULATOR_UUID STREQUAL UUID) + SET(${VAR} ${EMULATOR} PARENT_SCOPE) + RETURN() + ENDIF() + ELSE() + LIST(APPEND OFFLINE_EMULATORS ${EMULATOR}) + ENDIF() + ELSE() + LIST(APPEND OFFLINE_EMULATORS ${EMULATOR}) + ENDIF() + ENDWHILE() +ENDFUNCTION() + +# +# Sets up and starts a new emulator instance or reuses an +# existing one. +# VAR - the emulator instance handle object to reuse or +# initialize +# Will test if VAR refers to a valid emulator instance +# handle and, if so, ensure the device is started. +# Will initialize a new emulator instance and start it, +# if VAR does not refer to a valid emulator instance. +# Will ignore all additional arguments. +# +FUNCTION(DCMTK_ANDROID_START_EMULATOR VAR) + DCMTK_SETUP_ANDROID_EMULATOR() + IF(NOT ANDROID_EMULATOR_AVD) + MESSAGE(FATAL_ERROR "Please select which Android emulator Android Virtual Device (AVD) configuration to use!") + ELSE() + DCMTK_ANDROID_GET_OBJECT_PROPERTIES(${VAR}) + IF(NOT EMULATOR_STATE) + DCMTK_ANDROID_EMULATOR_GENERATE_UUID(EMULATOR_UUID) + ELSEIF(EMULATOR_STATE STREQUAL "RUNNING") + DCMTK_ANDROID_GET_EMULATOR_UUID(${EMULATOR_NAME} UUID) + # Do nothing if the running emulator instance is ok and can be reused. + # Otherwise restart it. + IF(UUID STREQUAL EMULATOR_UUID) + MESSAGE(STATUS "Reusing already running Android device emulator...") + RETURN() + ENDIF() + ELSEIF(EMULATOR_STATE STREQUAL "STARTING") + # Is it really starting, or has somebody aborted it? + MESSAGE(STATUS "Found previously started Android device emulator, checking if it's still present...") + DCMTK_ANDROID_GET_EMULATOR_NAME(EMULATOR_NAME ${EMULATOR_UUID}) + IF(EMULATOR_NAME) + MESSAGE(STATUS "Found previously started Android device emulator, checking if it's still present... yes") + DCMTK_ANDROID_SET_OBJECT_PROPERTIES(${VAR} RUNNING ${EMULATOR_UUID} ${EMULATOR_NAME}) + RETURN() + ENDIF() + MESSAGE(STATUS "Found previously started Android device emulator, checking if it's still present... no") + ENDIF() + MESSAGE(STATUS "Starting the Android device emulator...") + IF(CMAKE_HOST_SYSTEM MATCHES "Windows.*") + SET(COMMAND sh -c "${ANDROID_EMULATOR_PROGRAM} -avd ${ANDROID_EMULATOR_AVD} -no-boot-anim -noaudio -prop emu.uuid=${EMULATOR_UUID} >/dev/null 2>&1 < /dev/null &") + ELSE() + SET(COMMAND sh -c "${ANDROID_EMULATOR_PROGRAM} -avd ${ANDROID_EMULATOR_AVD} -no-window -no-boot-anim -noaudio -prop emu.uuid=${EMULATOR_UUID} >/dev/null 2>&1 < /dev/null &") + ENDIF() + EXECUTE_PROCESS( + COMMAND ${COMMAND} + RESULT_VARIABLE RESULT + OUTPUT_QUIET + ERROR_QUIET + ) + IF(NOT RESULT) + DCMTK_ANDROID_SET_OBJECT_PROPERTIES(${VAR} STARTING ${EMULATOR_UUID} "") + ELSE() + DCMTK_ANDROID_DESTROY_OBJECT(${VAR}) + MESSAGE(FATAL_ERROR "Error starting Android emulator.") + ENDIF() + ENDIF() +ENDFUNCTION(DCMTK_ANDROID_START_EMULATOR) + +# +# Waits until the given emulator instance becomes online (RUNNING). +# VAR - the emulator instance handle object referring to the emulator +# to wait for +# Will fail with a warning message if the given variable does not +# refer to a valid emulator instance handle object. +# Will set the object's state to "RUNNING" when successful. +# Will wait indefinitely if no such device exists or the device does +# not become online. +# Will ignore all additional arguments. +# +FUNCTION(DCMTK_ANDROID_WAIT_FOR_EMULATOR VAR) + DCMTK_ANDROID_GET_OBJECT_PROPERTIES(${VAR}) + IF(NOT EMULATOR_STATE) + MESSAGE(AUTHOR_WARNING "Error: ${VAR} is not a valid Android emulator instance handle.") + ELSEIF(EMULATOR_STATE STREQUAL "RUNNING") + # Emulator is running, no need to wait! + ELSEIF(EMULATOR_STATE STREQUAL "STOPPED") + MESSAGE(WARNING "The Android emulator has stopped, aborting...") + ELSE() + MESSAGE(STATUS "Waiting until the Android device emulator is ready to receive instructions...") + WHILE(NOT EMULATOR_NAME) + DCMTK_ANDROID_GET_EMULATOR_NAME(EMULATOR_NAME ${EMULATOR_UUID}) + ENDWHILE() + DCMTK_ANDROID_SET_OBJECT_PROPERTIES(${VAR} RUNNING ${EMULATOR_UUID} ${EMULATOR_NAME}) + ENDIF() +ENDFUNCTION(DCMTK_ANDROID_WAIT_FOR_EMULATOR) + +# +# Prepare a command that will shutdown the given Android emulator when +# in the local shell run. +# VAR - the name of the variable that will be set to the +# generated command +# EMULATOR_NAME - the name of the emulated device that shall be shut +# down +# Will unset the variable referred to by VAR if no such command can +# be generated for the current host platform (Windows). +# Will ignore all additional arguments. +# +MACRO(DCMTK_ANDROID_STOP_EMULATOR_COMMAND VAR EMULATOR_NAME) + IF(CMAKE_HOST_SYSTEM MATCHES "Windows.*") + UNSET(${VAR}) + ELSE() + SET(${VAR} ${ANDROID_ADB_PROGRAM} -s ${EMULATOR_NAME} emu kill) + ENDIF() +ENDMACRO(DCMTK_ANDROID_STOP_EMULATOR_COMMAND) + +# +# Prepare an emulator shutdown message or a warning message if automated +# shutdown is not possible. +# VAR - the name of the variable that will be set to the generated message +# Will ignore all additional arguments. +# +MACRO(DCMTK_ANDROID_EMULATOR_SHUTDOWN_MESSAGE VAR) + IF(CMAKE_HOST_SYSTEM MATCHES "Windows.*") + SET(${VAR} WARNING "The Android device emulator can't be terminated automatically under Windows, please shutdown \"${EMULATOR_NAME}\" manually!") + ELSE() + SET(${VAR} STATUS "Shutting down the Android device emulator...") + ENDIF() +ENDMACRO(DCMTK_ANDROID_EMULATOR_SHUTDOWN_MESSAGE) + +# +# Stops the emulator and sets its state to STOPPED when successful. +# VAR - the name of the variable referring to the emulator instance +# handle object +# Will emit a warning message if the emulator can't be stopped and +# won't modify its state in that case. +# Will ignore all additional arguments. +# +FUNCTION(DCMTK_ANDROID_STOP_EMULATOR VAR) + DCMTK_ANDROID_GET_OBJECT_PROPERTIES(${VAR}) + IF(NOT EMULATOR_STATE) + MESSAGE(AUTHOR_WARNING "Error: ${VAR} is not a valid Android emulator instance handle.") + ELSEIF(EMULATOR_STATE STREQUAL "STARTING") + # Can't tell it to stop if it is not done starting + DCMTK_ANDROID_WAIT_FOR_EMULATOR(${VAR}) + ELSEIF(EMULATOR_STATE STREQUAL "STOPPED") + # Emulator is already stopped, do nothing + RETURN() + ENDIF() + DCMTK_ANDROID_EMULATOR_SHUTDOWN_MESSAGE(MESSAGE) + MESSAGE(${MESSAGE}) + IF(NOT CMAKE_HOST_SYSTEM MATCHES "Windows.*") + DCMTK_ANDROID_STOP_EMULATOR_COMMAND(COMMAND ${EMULATOR_NAME}) + EXECUTE_PROCESS( + COMMAND ${COMMAND} + RESULT_VARIABLE RESULT + OUTPUT_QUIET + ERROR_QUIET + ) + IF(NOT RESULT) + DCMTK_ANDROID_SET_OBJECT_PROPERTIES(${VAR} STOPPED ${EMULATOR_UUID} "") + ELSE() + MESSAGE(WARNING "Unable to stop the android device emulator, please shutdown \"${EMULATOR_NAME}\" manually!") + ENDIF() + ENDIF() +ENDFUNCTION(DCMTK_ANDROID_STOP_EMULATOR) + +# +# Uploads local files to the given Android device using 'adb push'. +# VAR - the emulator instance handle object referring to the target +# device +# Requires the device to be running. +# Additional arguments will be parsed and interpreted similar to +# CMake's FILE(COPY ...) command. +# +FUNCTION(DCMTK_ANDROID_PUSH VAR) + DCMTK_ANDROID_GET_OBJECT_PROPERTIES(${VAR}) + IF(NOT EMULATOR_STATE) + MESSAGE(AUTHOR_WARNING "Error: ${VAR} is not a valid Android emulator instance handle.") + ELSEIF(EMULATOR_STATE STREQUAL "RUNNING") + CMAKE_PARSE_ARGUMENTS(DCMTK_ANDROID_PUSH "" "" "DESTINATION" ${ARGN}) + FOREACH(LOCAL_FILE ${DCMTK_ANDROID_PUSH_UNPARSED_ARGUMENTS}) + EXECUTE_PROCESS( + COMMAND ${ANDROID_ADB_PROGRAM} -s ${EMULATOR_NAME} push ${LOCAL_FILE} ${DCMTK_ANDROID_PUSH_DESTINATION} + RESULT_VARIABLE RESULT + OUTPUT_QUIET + ERROR_QUIET + ) + ENDFOREACH() + ELSE() + MESSAGE(AUTHOR_WARNING "Error: the Android emulator \"${VAR}\" is not ready to receive commands") + ENDIF() +ENDFUNCTION(DCMTK_ANDROID_PUSH) + +# +# Downloads remote files from the given Android device using 'adb pull'. +# VAR - the emulator instance handle object referring to the target +# device +# Requires the device to be running. +# Additional arguments will be parsed and interpreted similar to +# CMake's FILE(COPY ...) command. +# +FUNCTION(DCMTK_ANDROID_PULL VAR) + DCMTK_ANDROID_GET_OBJECT_PROPERTIES(${VAR}) + IF(NOT EMULATOR_STATE) + MESSAGE(AUTHOR_WARNING "Error: ${VAR} is not a valid Android emulator instance handle.") + ELSEIF(EMULATOR_STATE STREQUAL "RUNNING") + CMAKE_PARSE_ARGUMENTS(DCMTK_ANDROID_PULL "" "" "DESTINATION" ${ARGN}) + FOREACH(REMOTE_FILE ${DCMTK_ANDROID_PULL_UNPARSED_ARGUMENTS}) + EXECUTE_PROCESS( + COMMAND ${ANDROID_ADB_PROGRAM} -s ${EMULATOR_NAME} pull ${REMOTE_FILE} ${DCMTK_ANDROID_PULL_DESTINATION} + RESULT_VARIABLE RESULT + OUTPUT_QUIET + ERROR_QUIET + ) + ENDFOREACH() + ELSE() + MESSAGE(AUTHOR_WARNING "Error: the Android emulator \"${VAR}\" is not ready to receive commands") + ENDIF() +ENDFUNCTION(DCMTK_ANDROID_PULL) + +# +# Executes a shell command on the given Android device using 'adb shell'. +# VAR - the emulator instance handle object referring to the target +# device +# Requires the device to be running. +# Additional arguments will be parsed and interpreted similar to +# CMake's EXECUTE_PROCESS(...) command. +# +FUNCTION(DCMTK_ANDROID_SHELL VAR) + DCMTK_ANDROID_GET_OBJECT_PROPERTIES(${VAR}) + IF(NOT EMULATOR_STATE) + MESSAGE(AUTHOR_WARNING "Error: ${VAR} is not a valid Android emulator instance handle.") + ELSEIF(EMULATOR_STATE STREQUAL "RUNNING") + CMAKE_PARSE_ARGUMENTS(DCMTK_ANDROID_SHELL + "OUTPUT_QUIET;ERROR_QUIET" + "RESULT_VARIABLE;OUTPUT_VARIABLE;ERROR_VARIABLE;WORKING_DIRECTORY" + "COMMAND" + ${ARGN} + ) + + # Prepare commandline + SET(COMMAND ${ANDROID_ADB_PROGRAM} -s ${EMULATOR_NAME} shell) + IF(DCMTK_ANDROID_SHELL_WORKING_DIRECTORY) + LIST(APPEND COMMAND "cd" "${DCMTK_ANDROID_SHELL_WORKING_DIRECTORY}" "&&") + ENDIF() + LIST(APPEND COMMAND "${DCMTK_ANDROID_SHELL_COMMAND}") + + # Inspect output variable parameters + IF(DCMTK_ANDROID_SHELL_OUTPUT_VARIABLE) + SET(PUSH_OUTPUT_VAR TRUE) + IF(DCMTK_ANDROID_SHELL_ERROR_VARIABLE) + IF(DCMTK_ANDROID_SHELL_ERROR_VARIABLE STREQUAL DCMTK_ANDROID_SHELL_OUTPUT_VARIABLE) + SET(STREAMS_MERGED TRUE) + ELSE() + SET(PUSH_ERROR_VAR TRUE) + ENDIF() + ELSE() + SET(DCMTK_ANDROID_SHELL_ERROR_VARIABLE DCMTK_ANDROID_SHELL_ERROR_MESSAGE_BUFFER) + ENDIF() + ELSE() + SET(DCMTK_ANDROID_SHELL_OUTPUT_VARIABLE DCMTK_ANDROID_SHELL_OUTPUT_MESSAGE_BUFFER) + IF(DCMTK_ANDROID_SHELL_ERROR_VARIABLE) + SET(PUSH_ERROR_VAR TRUE) + ELSE() + SET(STREAMS_MERGED TRUE) + ENDIF() + ENDIF() + + # Prefix to prevent collision of output capturing files + IF(CMAKE_VERSION VERSION_LESS 2.8.7) + STRING(RANDOM LENGTH 20 ALPHABET "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" PREFIX) + ELSE() + STRING(MD5 PREFIX "${DCMTK_ANDROID_SHELL_COMMAND}") + ENDIF() + + # Prepare output redirection (buffering) + IF(STREAMS_MERGED) + LIST(APPEND COMMAND > ${ANDROID_TEMPORARY_FILES_LOCATION}/${PREFIX}_output 2>&1) + ELSE() + LIST(APPEND COMMAND > ${ANDROID_TEMPORARY_FILES_LOCATION}/${PREFIX}_output 2> ${ANDROID_TEMPORARY_FILES_LOCATION}/${PREFIX}_error) + ENDIF() + + # Prepare capturing the result + LIST(APPEND COMMAND "\;" echo -n $? > ${ANDROID_TEMPORARY_FILES_LOCATION}/${PREFIX}_result) + + # Run the command + EXECUTE_PROCESS( + COMMAND ${COMMAND} + RESULT_VARIABLE ADB_RESULT + OUTPUT_VARIABLE ADB_OUTPUT + ERROR_VARIABLE ADB_OUTPUT + ) + + # Deal with it + IF(ADB_RESULT) + MESSAGE(WARNING "Error sending command to the Android emulator, adb reported the error: ${ADB_OUTPUT}") + IF(DCMTK_ANDROID_SHELL_RESULT_VARIABLE) + SET(${DCMTK_ANDROID_SHELL_RESULT_VARIABLE} ${ADB_RESULT} PARENT_SCOPE) + ENDIF() + ELSE(ADB_RESULT) + # Receive results + DCMTK_ANDROID_PULL(${VAR} ${ANDROID_TEMPORARY_FILES_LOCATION}/${PREFIX}_output ${ANDROID_TEMPORARY_FILES_LOCATION}/${PREFIX}_error ${ANDROID_TEMPORARY_FILES_LOCATION}/${PREFIX}_result + DESTINATION ${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY} + ) + # Cleanup temp files + EXECUTE_PROCESS( + COMMAND ${ANDROID_ADB_PROGRAM} -s ${EMULATOR_NAME} shell rm ${ANDROID_TEMPORARY_FILES_LOCATION}/${PREFIX}_output "\;" rm ${ANDROID_TEMPORARY_FILES_LOCATION}/${PREFIX}_error "\;" rm ${ANDROID_TEMPORARY_FILES_LOCATION}/${PREFIX}_result + RESULT_VARIABLE RESULT_QUIET + OUTPUT_QUIET + ERROR_QUIET + ) + # Analyze results + IF(DCMTK_ANDROID_SHELL_RESULT_VARIABLE) + FILE(READ ${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/${PREFIX}_result ${DCMTK_ANDROID_SHELL_RESULT_VARIABLE}) + SET(${DCMTK_ANDROID_SHELL_RESULT_VARIABLE} ${${DCMTK_ANDROID_SHELL_RESULT_VARIABLE}} PARENT_SCOPE) + ENDIF() + IF(NOT DCMTK_ANDROID_SHELL_OUTPUT_QUIET OR (STREAMS_MERGED AND NOT DCMTK_ANDROID_SHELL_ERROR_QUIET)) + FILE(READ ${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/${PREFIX}_output ${DCMTK_ANDROID_SHELL_OUTPUT_VARIABLE}) + IF(PUSH_OUTPUT_VAR) + SET(${DCMTK_ANDROID_SHELL_OUTPUT_VARIABLE} ${${DCMTK_ANDROID_SHELL_OUTPUT_VARIABLE}} PARENT_SCOPE) + ELSE() + MESSAGE("${${DCMTK_ANDROID_SHELL_OUTPUT_VARIABLE}}") + ENDIF() + ENDIF() + IF(NOT DCMTK_ANDROID_SHELL_ERROR_QUIET AND NOT STREAMS_MERGED) + FILE(READ ${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/${PREFIX}_error ${DCMTK_ANDROID_SHELL_ERROR_VARIABLE}) + IF(PUSH_ERROR_VAR) + SET(${DCMTK_ANDROID_SHELL_ERROR_VARIABLE} ${${DCMTK_ANDROID_SHELL_ERROR_VARIABLE}} PARENT_SCOPE) + ELSE() + MESSAGE("${${DCMTK_ANDROID_SHELL_ERROR_VARIABLE}}") + ENDIF() + ENDIF() + # Cleanup temp files + FILE(REMOVE ${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/${PREFIX}_result) + FILE(REMOVE ${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/${PREFIX}_output) + FILE(REMOVE ${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/${PREFIX}_error) + ENDIF(ADB_RESULT) + ELSE() + MESSAGE(AUTHOR_WARNING "Error: the Android emulator \"${VAR}\" is not ready to receive commands") + ENDIF() +ENDFUNCTION(DCMTK_ANDROID_SHELL) diff --git a/CMake/dcmtkUseWine.cmake b/CMake/dcmtkUseWine.cmake new file mode 100644 index 00000000..0ae2a3e1 --- /dev/null +++ b/CMake/dcmtkUseWine.cmake @@ -0,0 +1,73 @@ +# +# Functions for detection and usage of Wine +# Used when cross compiling +# + +# +# Tries to detect the required executables and libraries automatically and emits an +# error that will halt the configuration process if that is not possible. +# All arguments will be ignored. +# +FUNCTION(DCMTK_SETUP_WINE) + FIND_PROGRAM(WINE_WINE_PROGRAM wine) + FIND_PROGRAM(WINE_WINEPATH_PROGRAM winepath) + IF(NOT WINE_CPP_RUNTIME) + SET(v 1) + UNSET(CMAKE_FIND_LIBRARY_SUFFIXES) + WHILE(${v} LESS 14) + LIST(APPEND CMAKE_FIND_LIBRARY_SUFFIXES "-${v}.dll") + MATH(EXPR v "${v} + 1") + ENDWHILE() + FIND_LIBRARY(CPP_RUNTIME stdc++ DOC "Location of the C++ runtime library used during target emulation") + IF(NOT CPP_RUNTIME) + MESSAGE(FATAL_ERROR "Please set the C++ runtime location (required for running applications targeting Windows).") + ELSE() + GET_FILENAME_COMPONENT(CPP_RUNTIME_LOCATION ${CPP_RUNTIME} PATH) + UNIX_TO_WINE_PATH(RT ${CPP_RUNTIME_LOCATION}) + SET(WINE_CPP_RUNTIME ${RT} CACHE INTERNAL "C++ RT in Wine path format") + ENDIF() + ENDIF() + IF(NOT WINE_WINE_PROGRAM OR NOT WINE_WINEPATH_PROGRAM) + MESSAGE(FATAL_ERROR + "Some wine related executables could not be detected automatically. " + "Please set WINE_WINE_PROGRAM and WINE_WINEPATH_PROGRAM appropriately." + ) + ENDIF() +ENDFUNCTION(DCMTK_SETUP_WINE) + +# +# Uses 'winepath' to translate a host path or filename to the location it can be +# accessed from within the emulated Windows environment (e. g. replaces '/' by '\'). +# VAR - name of the variable to store the result in +# PATH - the path to be translated +# Will unset VAR if an error occurred. +# Additional arguments will be ignored. +# +FUNCTION(UNIX_TO_WINE_PATH VAR PATH) + EXECUTE_PROCESS( + COMMAND ${WINE_WINEPATH_PROGRAM} -w ${PATH} + RESULT_VARIABLE ERROR + OUTPUT_VARIABLE RESULT + ERROR_VARIABLE STDERR + ) + IF(NOT ERROR) + STRING(REPLACE "\n" "" RESULT ${RESULT}) + SET(${VAR} ${RESULT} PARENT_SCOPE) + ELSE() + UNSET(${VAR} PARENT_SCOPE) + MESSAGE(WARNING "Unable to convert path to Wine format: ${STDERR}") + ENDIF() +ENDFUNCTION() + +# +# Create a command (as string) to run a given command in the emulated Windows +# environment by using 'wine'. +# VAR - name of the variable to store the resulting command in +# COMMAND - the command to run, e. g. 'dir' +# Additional arguments will be appended to the command. +# +FUNCTION(WINE_COMMAND VAR COMMAND) + UNIX_TO_WINE_PATH(CMD ${COMMAND}) + SEPARATE_ARGUMENTS(ARGS WINDOWS_COMMAND "${ARGN}") + SET(${VAR} ${WINE_WINE_PROGRAM} cmd /c "PATH=${WINE_CPP_RUNTIME}\;%PATH%" \\& ${CMD} ${ARGS} PARENT_SCOPE) +ENDFUNCTION() diff --git a/CMake/osconfig.h.in b/CMake/osconfig.h.in new file mode 100644 index 00000000..2b6325d8 --- /dev/null +++ b/CMake/osconfig.h.in @@ -0,0 +1,1135 @@ +#ifndef OSCONFIG_H +#define OSCONFIG_H + +/* +** Define enclosures for include files with C linkage (mostly system headers) +*/ +#ifdef __cplusplus +#define BEGIN_EXTERN_C extern "C" { +#define END_EXTERN_C } +#else +#define BEGIN_EXTERN_C +#define END_EXTERN_C +#endif + +/* Define when building a shared library */ +#cmakedefine DCMTK_SHARED @DCMTK_SHARED@ + +/* Define when building the whole toolkit as a single shared library */ +#cmakedefine DCMTK_BUILD_SINGLE_SHARED_LIBRARY @DCMTK_BUILD_SINGLE_SHARED_LIBRARY@ + +/* Define when the compiler supports hidden visibility */ +#cmakedefine HAVE_HIDDEN_VISIBILITY @HAVE_HIDDEN_VISIBILITY@ + +/* Define when building with wide char file I/O functions */ +#cmakedefine WIDE_CHAR_FILE_IO_FUNCTIONS @WIDE_CHAR_FILE_IO_FUNCTIONS@ + +/* Define when building command line tools with wide char main function */ +#cmakedefine WIDE_CHAR_MAIN_FUNCTION @WIDE_CHAR_MAIN_FUNCTION@ + +#ifdef _WIN32 + /* Define if you have the header file. */ +#cmakedefine HAVE_WINDOWS_H @HAVE_WINDOWS_H@ + /* Define if you have the header file. */ +#cmakedefine HAVE_WINSOCK_H @HAVE_WINSOCK_H@ +#endif + +/* Define the canonical host system type as a string constant */ +#define CANONICAL_HOST_TYPE "@CANONICAL_HOST_TYPE@" + +/* Define if char is unsigned on the C compiler */ +#cmakedefine C_CHAR_UNSIGNED @C_CHAR_UNSIGNED@ + +/* Define to the inline keyword supported by the C compiler, if any, or to the + empty string */ +#define C_INLINE __inline + +/* Define if >> is unsigned on the C compiler */ +/* #undef C_RIGHTSHIFT_UNSIGNED */ + +/* Define the DCMTK default path */ +#define DCMTK_PREFIX "@DCMTK_PREFIX@" + +/* Define the default data dictionary path for the dcmdata library package */ +#define DCM_DICT_DEFAULT_PATH "@DCM_DICT_DEFAULT_PATH@" + +/* Define if we want a populated builtin dictionary */ +#cmakedefine ENABLE_BUILTIN_DICTIONARY "@ENABLE_BUILTIN_DICTIONARY@" + +/* Define the environment variable path separator */ +#define ENVIRONMENT_PATH_SEPARATOR '@ENVIRONMENT_PATH_SEPARATOR@' + +/* Define to 1 if you have the `accept' function. */ +#cmakedefine HAVE_ACCEPT @HAVE_ACCEPT@ + +/* Define to 1 if you have the `access' function. */ +#cmakedefine HAVE_ACCESS @HAVE_ACCESS@ + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_ALLOCA_H @HAVE_ALLOCA_H@ + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_ARPA_INET_H @HAVE_ARPA_INET_H@ + +/* Define to 1 if you have the header file. */ +#define HAVE_ASSERT_H 1 + +/* Define to 1 if you have the `bcmp' function. */ +#cmakedefine HAVE_BCMP @HAVE_BCMP@ + +/* Define to 1 if you have the `bcopy' function. */ +#cmakedefine HAVE_BCOPY @HAVE_BCOPY@ + +/* Define to 1 if you have the `bind' function. */ +#cmakedefine HAVE_BIND @HAVE_BIND@ + +/* Define to 1 if you have the `bzero' function. */ +#cmakedefine HAVE_BZERO @HAVE_BZERO@ + +/* Define if your C++ compiler can work with class templates */ +#define HAVE_CLASS_TEMPLATE 1 + +/* Define to 1 if you have the `connect' function. */ +#cmakedefine HAVE_CONNECT @HAVE_CONNECT@ + +/* define if the compiler supports const_cast<> */ +#define HAVE_CONST_CAST 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_CTYPE_H @HAVE_CTYPE_H@ + +/* Define to 1 if you have the `cuserid' function. */ +#cmakedefine HAVE_CUSERID @HAVE_CUSERID@ + +/* Define if bool is a built-in type */ +#cmakedefine HAVE_CXX_BOOL @HAVE_CXX_BOOL@ + +/* Define if volatile is a known keyword */ +#define HAVE_CXX_VOLATILE 1 + +/* Define if "const" is supported by the C compiler */ +#define HAVE_C_CONST 1 + +/* Define if your system has a declaration for socklen_t in sys/types.h + sys/socket.h */ +#cmakedefine HAVE_DECLARATION_SOCKLEN_T @HAVE_DECLARATION_SOCKLEN_T@ + +/* Define if your system has a declaration for std::ios_base::openmode in + iostream.h */ +#cmakedefine HAVE_DECLARATION_STD__IOS_BASE__OPENMODE @HAVE_DECLARATION_STD__IOS_BASE__OPENMODE@ + +/* Define if your system has a declaration for struct utimbuf in sys/types.h + utime.h sys/utime.h */ +#define HAVE_DECLARATION_STRUCT_UTIMBUF 1 + +/* Define to 1 if you have the header file, and it defines `DIR'.*/ +#cmakedefine HAVE_DIRENT_H @HAVE_DIRENT_H@ + +/* Define to 1 if you have the `_doprnt' function. */ +#cmakedefine HAVE_DOPRNT @HAVE_DOPRNT@ + +/* define if the compiler supports dynamic_cast<> */ +#define HAVE_DYNAMIC_CAST 1 + +/* Define if your system cannot pass command line arguments into main() (e.g. Macintosh) */ +/* #undef HAVE_EMPTY_ARGC_ARGV */ + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_ERRNO_H @HAVE_ERRNO_H@ + +/* Define to 1 if defined ENAMETOOLONG. */ +#cmakedefine HAVE_ENAMETOOLONG @HAVE_ENAMETOOLONG@ + +/* Define if your C++ compiler supports the explicit template specialization + syntax */ +#define HAVE_EXPLICIT_TEMPLATE_SPECIALIZATION 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_FCNTL_H @HAVE_FCNTL_H@ + +/* Define to 1 if you have the `finite' function. */ +#cmakedefine HAVE_FINITE @HAVE_FINITE@ + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_FLOAT_H @HAVE_FLOAT_H@ + +/* Define to 1 if you have the `flock' function. */ +#cmakedefine HAVE_FLOCK @HAVE_FLOCK@ + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_FNMATCH_H @HAVE_FNMATCH_H@ + +/* Define to 1 if you have the `fork' function. */ +#cmakedefine HAVE_FORK @HAVE_FORK@ + +/* Define to 1 if fseeko (and presumably ftello) exists and is declared. */ +#cmakedefine HAVE_FSEEKO @HAVE_FSEEKO@ + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_FSTREAM @HAVE_FSTREAM@ + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_FSTREAM_H @HAVE_FSTREAM_H@ + +/* Define to 1 if you have the `ftime' function. */ +#cmakedefine HAVE_FTIME @HAVE_FTIME@ + +/* Define if your C++ compiler can work with function templates */ +#define HAVE_FUNCTION_TEMPLATE 1 + +/* Define to 1 if you have the `getaddrinfo' function. */ +#cmakedefine HAVE_GETADDRINFO @HAVE_GETADDRINFO@ + +/* Define to 1 if you have the `getenv' function. */ +#cmakedefine HAVE_GETENV @HAVE_GETENV@ + +/* Define to 1 if you have the `geteuid' function. */ +#cmakedefine HAVE_GETEUID @HAVE_GETEUID@ + +/* Define to 1 if you have the `getgrnam' function. */ +#cmakedefine HAVE_GETGRNAM @HAVE_GETGRNAM@ + +/* Define to 1 if you have the `gethostbyname' function. */ +#cmakedefine HAVE_GETHOSTBYNAME @HAVE_GETHOSTBYNAME@ + +/* Define to 1 if you have the `gethostbyname_r' function. */ +#cmakedefine HAVE_GETHOSTBYNAME_R @HAVE_GETHOSTBYNAME_R@ + +/* Define to 1 if you have the `gethostbyaddr_r' function. */ +#cmakedefine HAVE_GETHOSTBYADDR_R @HAVE_GETHOSTBYADDR_R@ + +/* Define to 1 if you have the `getgrnam_r' function. */ +#cmakedefine HAVE_GETGRNAM_R @HAVE_GETGRNAM_R@ + +/* Define to 1 if you have the `getpwnam_r' function. */ +#cmakedefine HAVE_GETPWNAM_R @HAVE_GETPWNAM_R@ + +/* Define to 1 if you have the `gethostid' function. */ +#cmakedefine HAVE_GETHOSTID @HAVE_GETHOSTID@ + +/* Define to 1 if you have the `gethostname' function. */ +#cmakedefine HAVE_GETHOSTNAME @HAVE_GETHOSTNAME@ + +/* Define to 1 if you have the `getlogin' function. */ +#cmakedefine HAVE_GETLOGIN @HAVE_GETLOGIN@ + +/* Define to 1 if you have the `getpid' function. */ +#cmakedefine HAVE_GETPID @HAVE_GETPID@ + +/* Define to 1 if you have the `getpwnam' function. */ +#cmakedefine HAVE_GETPWNAM @HAVE_GETPWNAM@ + +/* Define to 1 if you have the `getsockname' function. */ +#cmakedefine HAVE_GETSOCKNAME @HAVE_GETSOCKNAME@ + +/* Define to 1 if you have the `getsockopt' function. */ +#cmakedefine HAVE_GETSOCKOPT @HAVE_GETSOCKOPT@ + +/* Define to 1 if you have the `getuid' function. */ +#cmakedefine HAVE_GETUID @HAVE_GETUID@ + +/* Define to 1 if you have the `gmtime_r' function. */ +#cmakedefine HAVE_GMTIME_R @HAVE_GMTIME_R@ + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_GRP_H @HAVE_GRP_H@ + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_IEEEFP_H @HAVE_IEEEFP_H@ + +/* Define to 1 if you have the `index' function. */ +#cmakedefine HAVE_INDEX @HAVE_INDEX@ + +/* Define if your system declares argument 3 of accept() as int * instead of + size_t * or socklen_t * */ +#cmakedefine HAVE_INTP_ACCEPT @HAVE_INTP_ACCEPT@ + +/* Define if your system declares argument 5 of getsockopt() as int * instead + of size_t * or socklen_t */ +#cmakedefine HAVE_INTP_GETSOCKOPT @HAVE_INTP_GETSOCKOPT@ + +/* Define if your system declares argument 2-4 of select() as int * instead of + struct fd_set * */ +#cmakedefine HAVE_INTP_SELECT @HAVE_INTP_SELECT@ + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_INTTYPES_H @HAVE_INTTYPES_H@ + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_IOMANIP @HAVE_IOMANIP@ + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_IOMANIP_H @HAVE_IOMANIP_H@ + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_IOSTREAM @HAVE_IOSTREAM@ + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_IOSTREAM_H @HAVE_IOSTREAM_H@ + +/* Define if your system defines ios::nocreate in iostream.h */ +/* defined below */ + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_IO_H @HAVE_IO_H@ + +/* Define to 1 if you have the `isinf' function. */ +#cmakedefine HAVE_ISINF @HAVE_ISINF@ + +/* Define to 1 if you have the `isnan' function. */ +#cmakedefine HAVE_ISNAN @HAVE_ISNAN@ + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_ISO646_H @HAVE_ISO646_H@ + +/* Define to 1 if you have the `itoa' function. */ +#cmakedefine HAVE_ITOA @HAVE_ITOA@ + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_LIBC_H @HAVE_LIBC_H@ + +/* Define to 1 if you have the `iostream' library (-liostream). */ +#cmakedefine HAVE_LIBIOSTREAM @HAVE_LIBIOSTREAM@ + +/* Define to 1 if you have the `nsl' library (-lnsl). */ +#cmakedefine HAVE_LIBNSL @HAVE_LIBNSL@ + +/* Define to 1 if you have the header file. */ +/* Comment this out so inside dipipng.cxx we can include */ +/* instead of KW 20060622 */ +/* #cmakedefine HAVE_LIBPNG_PNG_H @HAVE_LIBPNG_PNG_H@ */ + +/* Define to 1 if you have the `socket' library (-lsocket). */ +#cmakedefine HAVE_LIBSOCKET @HAVE_LIBSOCKET@ + +/* Define if libtiff supports LZW compression */ +#define HAVE_LIBTIFF_LZW_COMPRESSION 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_LIMITS_H @HAVE_LIMITS_H@ + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_CLIMITS @HAVE_CLIMITS@ + +/* Define to 1 if you have the `listen' function. */ +#cmakedefine HAVE_LISTEN @HAVE_LISTEN@ + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_LOCALE_H @HAVE_LOCALE_H@ + +/* Define to 1 if you have the `localtime_r' function. */ +#cmakedefine HAVE_LOCALTIME_R @HAVE_LOCALTIME_R@ + +/* Define to 1 if you have the `lockf' function. */ +#cmakedefine HAVE_LOCKF @HAVE_LOCKF@ + +/* Define to 1 if you have the `lstat' function. */ +#cmakedefine HAVE_LSTAT @HAVE_LSTAT@ + +/* Define to 1 if you support file names longer than 14 characters. */ +#define HAVE_LONG_FILE_NAMES 1 + +/* Define to 1 if you have the `malloc_debug' function. */ +#cmakedefine HAVE_MALLOC_DEBUG @HAVE_MALLOC_DEBUG@ + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_MALLOC_H @HAVE_MALLOC_H@ + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_MATH_H @HAVE_MATH_H@ + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_CMATH @HAVE_CMATH@ + +/* Define to 1 if you have the `mbstowcs' function. */ +#cmakedefine HAVE_MBSTOWCS @HAVE_MBSTOWCS@ + +/* Define to 1 if you have the `memcmp' function. */ +#cmakedefine HAVE_MEMCMP @HAVE_MEMCMP@ + +/* Define to 1 if you have the `memcpy' function. */ +#cmakedefine HAVE_MEMCPY @HAVE_MEMCPY@ + +/* Define to 1 if you have the `memmove' function. */ +#cmakedefine HAVE_MEMMOVE @HAVE_MEMMOVE@ + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_MEMORY_H @HAVE_MEMORY_H@ + +/* Define to 1 if you have the `memset' function. */ +#cmakedefine HAVE_MEMSET @HAVE_MEMSET@ + +/* Define to 1 if you have the `mkstemp' function. */ +#cmakedefine HAVE_MKSTEMP @HAVE_MKSTEMP@ + +/* Define to 1 if you have the `mktemp' function. */ +#cmakedefine HAVE_MKTEMP @HAVE_MKTEMP@ + +/* Define to 1 if you have the header file, and it defines `DIR'. */ +#cmakedefine HAVE_NDIR_H @HAVE_NDIR_H@ + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_NETDB_H @HAVE_NETDB_H@ + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_NETINET_IN_H @HAVE_NETINET_IN_H@ + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_NETINET_IN_SYSTM_H @HAVE_NETINET_IN_SYSTM_H@ + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_NETINET_TCP_H @HAVE_NETINET_TCP_H@ + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_NEW_H @HAVE_NEW_H@ + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_FENV_H @HAVE_FENV_H@ + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_SYSTEMINFO_H @HAVE_SYS_SYSTEMINFO_H@ + +/* Define if your system supports readdir_r with the obsolete Posix 1.c draft + 6 declaration (2 arguments) instead of the Posix 1.c declaration with 3 + arguments. */ +/* #undef HAVE_OLD_READDIR_R */ + +/* Define if your system has a prototype for accept in sys/types.h + sys/socket.h */ +#cmakedefine HAVE_PROTOTYPE_ACCEPT @HAVE_PROTOTYPE_ACCEPT@ + +/* Define if your system has a prototype for bind in sys/types.h sys/socket.h */ +#cmakedefine HAVE_PROTOTYPE_BIND @HAVE_PROTOTYPE_BIND@ + +/* Define if your system has a prototype for bzero in string.h strings.h + libc.h unistd.h stdlib.h */ +#cmakedefine HAVE_PROTOTYPE_BZERO @HAVE_PROTOTYPE_BZERO@ + +/* Define if your system has a prototype for connect in sys/types.h + sys/socket.h */ +#cmakedefine HAVE_PROTOTYPE_CONNECT @HAVE_PROTOTYPE_CONNECT@ + +/* Define if your system has a prototype for finite in math.h */ +#cmakedefine HAVE_PROTOTYPE_FINITE @HAVE_PROTOTYPE_FINITE@ + +/* Define if your system has a prototype for std::finite in cmath */ +#cmakedefine HAVE_PROTOTYPE_STD__FINITE @HAVE_PROTOTYPE_STD__FINITE@ + +/* Define if your system has a prototype for flock in sys/file.h */ +#cmakedefine HAVE_PROTOTYPE_FLOCK @HAVE_PROTOTYPE_FLOCK@ + +/* Define if your system has a prototype for gethostbyname in libc.h unistd.h + stdlib.h netdb.h */ +#cmakedefine HAVE_PROTOTYPE_GETHOSTBYNAME @HAVE_PROTOTYPE_GETHOSTBYNAME@ + +/* Define if your system has a prototype for gethostbyname_r in libc.h unistd.h + stdlib.h netdb.h */ +#cmakedefine HAVE_PROTOTYPE_GETHOSTBYNAME_R @HAVE_PROTOTYPE_GETHOSTBYNAME_R@ + +/* Define if your system has a prototype for gethostid in libc.h unistd.h + stdlib.h netdb.h */ +#cmakedefine HAVE_PROTOTYPE_GETHOSTID @HAVE_PROTOTYPE_GETHOSTID@ + +/* Define if your system has a prototype for gethostname in unistd.h libc.h + stdlib.h netdb.h */ +#cmakedefine HAVE_PROTOTYPE_GETHOSTNAME @HAVE_PROTOTYPE_GETHOSTNAME@ + +/* Define if your system has a prototype for getsockname in sys/types.h + sys/socket.h */ +#cmakedefine HAVE_PROTOTYPE_GETSOCKNAME @HAVE_PROTOTYPE_GETSOCKNAME@ + +/* Define if your system has a prototype for getsockopt in sys/types.h + sys/socket.h */ +#cmakedefine HAVE_PROTOTYPE_GETSOCKOPT @HAVE_PROTOTYPE_GETSOCKOPT@ + +/* Define if your system has a prototype for gettimeofday in sys/time.h + unistd.h */ +#cmakedefine HAVE_PROTOTYPE_GETTIMEOFDAY @HAVE_PROTOTYPE_GETTIMEOFDAY@ + +/* Define if your system has a prototype for isinf in math.h */ +#cmakedefine HAVE_PROTOTYPE_ISINF @HAVE_PROTOTYPE_ISINF@ + +/* Define if your system has a prototype for isnan in math.h */ +#cmakedefine HAVE_PROTOTYPE_ISNAN @HAVE_PROTOTYPE_ISNAN@ + +/* Define if your system has a prototype for std::isinf in cmath */ +#cmakedefine HAVE_PROTOTYPE_STD__ISINF @HAVE_PROTOTYPE_STD__ISINF@ + +/* Define if your system has a prototype for std::isnan in cmath */ +#cmakedefine HAVE_PROTOTYPE_STD__ISNAN @HAVE_PROTOTYPE_STD__ISNAN@ + +/* Define if your system has a prototype for fpclassf in math.h */ +#cmakedefine HAVE_PROTOTYPE__FPCLASSF @HAVE_PROTOTYPE__FPCLASSF@ + +/* Define if your system has a prototype for listen in sys/types.h + sys/socket.h */ +#cmakedefine HAVE_PROTOTYPE_LISTEN @HAVE_PROTOTYPE_LISTEN@ + +/* Define if your system has a prototype for mkstemp in libc.h unistd.h + stdlib.h */ +#cmakedefine HAVE_PROTOTYPE_MKSTEMP @HAVE_PROTOTYPE_MKSTEMP@ + +/* Define if your system has a prototype for mktemp in libc.h unistd.h + stdlib.h */ +#cmakedefine HAVE_PROTOTYPE_MKTEMP @HAVE_PROTOTYPE_MKTEMP@ + +/* Define if your system has a prototype for select in sys/select.h + sys/types.h sys/socket.h sys/time.h */ +#cmakedefine HAVE_PROTOTYPE_SELECT @HAVE_PROTOTYPE_SELECT@ + +/* Define if your system has a prototype for setsockopt in sys/types.h + sys/socket.h */ +#cmakedefine HAVE_PROTOTYPE_SETSOCKOPT @HAVE_PROTOTYPE_SETSOCKOPT@ + +/* Define if your system has a prototype for socket in sys/types.h + sys/socket.h */ +#cmakedefine HAVE_PROTOTYPE_SOCKET @HAVE_PROTOTYPE_SOCKET@ + +/* Define if your system has a prototype for std::vfprintf in stdarg.h */ +#cmakedefine HAVE_PROTOTYPE_STD__VFPRINTF @HAVE_PROTOTYPE_STD__VFPRINTF@ + +/* Define if your system has a prototype for std::vsnprintf in stdio.h */ +#cmakedefine HAVE_PROTOTYPE_STD__VSNPRINTF @HAVE_PROTOTYPE_STD__VSNPRINTF@ + +/* Define if your system has a prototype for strcasecmp in string.h */ +#cmakedefine HAVE_PROTOTYPE_STRCASECMP @HAVE_PROTOTYPE_STRCASECMP@ + +/* Define if your system has a prototype for strncasecmp in string.h */ +#cmakedefine HAVE_PROTOTYPE_STRNCASECMP @HAVE_PROTOTYPE_STRNCASECMP@ + +/* Define if your system has a prototype for strerror_r in string.h */ +#cmakedefine HAVE_PROTOTYPE_STRERROR_R @HAVE_PROTOTYPE_STRERROR_R@ + +/* Define if your system has a prototype for gettid */ +#cmakedefine HAVE_SYS_GETTID @HAVE_SYS_GETTID@ + +/* Define if your system has a prototype for usleep in libc.h unistd.h + stdlib.h */ +#cmakedefine HAVE_PROTOTYPE_USLEEP @HAVE_PROTOTYPE_USLEEP@ + +/* Define if your system has a prototype for wait3 in libc.h sys/wait.h + sys/time.h sys/resource.h */ +#cmakedefine HAVE_PROTOTYPE_WAIT3 @HAVE_PROTOTYPE_WAIT3@ + +/* Define if your system has a prototype for waitpid in sys/wait.h sys/time.h + sys/resource.h */ +#cmakedefine HAVE_PROTOTYPE_WAITPID @HAVE_PROTOTYPE_WAITPID@ + +/* Define if your system has a prototype for _stricmp in string.h */ +#cmakedefine HAVE_PROTOTYPE__STRICMP @HAVE_PROTOTYPE__STRICMP@ + +/* Define if your system has a prototype for nanosleep in time.h */ +#cmakedefine HAVE_PROTOTYPE_NANOSLEEP @HAVE_PROTOTYPE_NANOSLEEP@ + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_PTHREAD_H @HAVE_PTHREAD_H@ + +/* Define if your system supports POSIX read/write locks */ +#cmakedefine HAVE_PTHREAD_RWLOCK @HAVE_PTHREAD_RWLOCK@ + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_PWD_H @HAVE_PWD_H@ + +/* define if the compiler supports reinterpret_cast<> */ +#define HAVE_REINTERPRET_CAST 1 + +/* Define to 1 if you have the `rindex' function. */ +#cmakedefine HAVE_RINDEX @HAVE_RINDEX@ + +/* Define to 1 if you have the `select' function. */ +#cmakedefine HAVE_SELECT @HAVE_SELECT@ + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SEMAPHORE_H @HAVE_SEMAPHORE_H@ + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SETJMP_H @HAVE_SETJMP_H@ + +/* Define to 1 if you have the `setsockopt' function. */ +#cmakedefine HAVE_SETSOCKOPT @HAVE_SETSOCKOPT@ + +/* Define to 1 if you have the `setuid' function. */ +#cmakedefine HAVE_SETUID @HAVE_SETUID@ + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SIGNAL_H @HAVE_SIGNAL_H@ + +/* Define to 1 if you have the `sleep' function. */ +#cmakedefine HAVE_SLEEP @HAVE_SLEEP@ + +/* Define to 1 if you have the `socket' function. */ +#cmakedefine HAVE_SOCKET @HAVE_SOCKET@ + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SSTREAM @HAVE_SSTREAM@ + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SSTREAM_H @HAVE_SSTREAM_H@ + +/* Define to 1 if you have the `stat' function. */ +#cmakedefine HAVE_STAT @HAVE_STAT@ + +/* define if the compiler supports static_cast<> */ +#define HAVE_STATIC_CAST 1 + +/* Define if your C++ compiler can work with static methods in class templates + */ +#define HAVE_STATIC_TEMPLATE_METHOD 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_STAT_H @HAVE_STAT_H@ + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_STDARG_H @HAVE_STDARG_H@ + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_STDBOOL_H @HAVE_STDBOOL_H@ + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_CSTDARG @HAVE_CSTDARG@ + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_STDDEF_H @HAVE_STDDEF_H@ + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_STDINT_H @HAVE_STDINT_H@ + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_CSTDINT @HAVE_CSTDINT@ + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_STDIO_H @HAVE_STDIO_H@ + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_CSTDIO @HAVE_CSTDIO@ + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_STDLIB_H @HAVE_STDLIB_H@ + +/* Define if ANSI standard C++ includes use std namespace */ +/* defined below */ + +/* Define if the compiler supports std::nothrow */ +/* defined below */ + +/* Define to 1 if you have the `strchr' function. */ +#cmakedefine HAVE_STRCHR @HAVE_STRCHR@ + +/* Define to 1 if you have the `strdup' function. */ +#cmakedefine HAVE_STRDUP @HAVE_STRDUP@ + +/* Define to 1 if you have the `strerror' function. */ +#cmakedefine HAVE_STRERROR @HAVE_STRERROR@ + +/* Define to 1 if `strerror_r' returns a char*. */ +#cmakedefine HAVE_CHARP_STRERROR_R @HAVE_CHARP_STRERROR_R@ + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_STRINGS_H @HAVE_STRINGS_H@ + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_STRING_H @HAVE_STRING_H@ + +/* Define to 1 if you have the `strlcat' function. */ +#cmakedefine HAVE_STRLCAT @HAVE_STRLCAT@ + +/* Define to 1 if you have the `strlcpy' function. */ +#cmakedefine HAVE_STRLCPY @HAVE_STRLCPY@ + +/* Define to 1 if you have the `strstr' function. */ +#cmakedefine HAVE_STRSTR @HAVE_STRSTR@ + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_STRSTREAM @HAVE_STRSTREAM@ + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_STRSTREAM_H @HAVE_STRSTREAM_H@ + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_STRSTREA_H @HAVE_STRSTREA_H@ + +/* Define to 1 if you have the `strtoul' function. */ +#cmakedefine HAVE_STRTOUL @HAVE_STRTOUL@ + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYNCH_H @HAVE_SYNCH_H@ + +/* Define if __sync_add_and_fetch is available */ +#cmakedefine HAVE_SYNC_ADD_AND_FETCH @HAVE_SYNC_ADD_AND_FETCH@ + +/* Define if __sync_sub_and_fetch is available */ +#cmakedefine HAVE_SYNC_SUB_AND_FETCH @HAVE_SYNC_SUB_AND_FETCH@ + +/* Define if InterlockedIncrement is available */ +#cmakedefine HAVE_INTERLOCKED_INCREMENT @HAVE_INTERLOCKED_INCREMENT@ + +/* Define if InterlockedDecrement is available */ +#cmakedefine HAVE_INTERLOCKED_DECREMENT @HAVE_INTERLOCKED_DECREMENT@ + +/* Define if passwd::pw_gecos is available */ +#cmakedefine HAVE_PASSWD_GECOS @HAVE_PASSWD_GECOS@ + +/* Define to 1 if you have the `sysinfo' function. */ +#cmakedefine HAVE_SYSINFO @HAVE_SYSINFO@ + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYSLOG_H @HAVE_SYSLOG_H@ + +/* Define to 1 if you have the header file, and it defines `DIR'.*/ +#cmakedefine HAVE_SYS_DIR_H @HAVE_SYS_DIR_H@ + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_ERRNO_H @HAVE_SYS_ERRNO_H@ + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_FILE_H @HAVE_SYS_FILE_H@ + +/* Define to 1 if you have the header file, and it defines `DIR'.*/ +#cmakedefine HAVE_SYS_NDIR_H @HAVE_SYS_NDIR_H@ + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_PARAM_H @HAVE_SYS_PARAM_H@ + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_RESOURCE_H @HAVE_SYS_RESOURCE_H@ + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_SELECT_H @HAVE_SYS_SELECT_H@ + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_SOCKET_H @HAVE_SYS_SOCKET_H@ + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_STAT_H @HAVE_SYS_STAT_H@ + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_SYSCALL_H @HAVE_SYS_SYSCALL_H@ + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_TIMEB_H @HAVE_SYS_TIMEB_H@ + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_TIME_H @HAVE_SYS_TIME_H@ + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_TYPES_H @HAVE_SYS_TYPES_H@ + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_UTIME_H @HAVE_SYS_UTIME_H@ + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_UTSNAME_H @HAVE_SYS_UTSNAME_H@ + +/* Define to 1 if you have that is POSIX.1 compatible. */ +#cmakedefine HAVE_SYS_WAIT_H @HAVE_SYS_WAIT_H@ + +/* Define to 1 if you have the `tempnam' function. */ +#cmakedefine HAVE_TEMPNAM @HAVE_TEMPNAM@ + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_THREAD_H @HAVE_THREAD_H@ + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_TIME_H @HAVE_TIME_H@ + +/* Define to 1 if you have the `tmpnam' function. */ +#cmakedefine HAVE_TMPNAM @HAVE_TMPNAM@ + +/* define if the compiler recognizes typename */ +#cmakedefine HAVE_TYPENAME @HAVE_TYPENAME@ + +/* Define to 1 if you have the `uname' function. */ +#cmakedefine HAVE_UNAME @HAVE_UNAME@ + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_UNISTD_H @HAVE_UNISTD_H@ + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_UNIX_H @HAVE_UNIX_H@ + +/* Define to 1 if you have the `usleep' function. */ +#cmakedefine HAVE_USLEEP @HAVE_USLEEP@ + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_UTIME_H @HAVE_UTIME_H@ + +/* Define to 1 if you have the `vprintf' function. */ +#cmakedefine HAVE_VPRINTF @HAVE_VPRINTF@ + +/* Define to 1 if you have the `_vsnprintf_s' function. */ +#cmakedefine HAVE__VSNPRINTF_S @HAVE__VSNPRINTF_S@ + +/* Define to 1 if you have the `vfprintf_s' function. */ +#cmakedefine HAVE_VFPRINTF_S @HAVE_VFPRINTF_S@ + +/* Define to 1 if you have the `vsnprintf' function. */ +#cmakedefine HAVE_VSNPRINTF @HAVE_VSNPRINTF@ + +/* Define to 1 if you have the `vsprintf_s' function. */ +#cmakedefine HAVE_VSPRINTF_S @HAVE_VSPRINTF_S@ + +/* Define to 1 if you have the `wait3' function. */ +#cmakedefine HAVE_WAIT3 @HAVE_WAIT3@ + +/* Define to 1 if you have the `waitpid' function. */ +#cmakedefine HAVE_WAITPID @HAVE_WAITPID@ + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_WCHAR_H @HAVE_WCHAR_H@ + +/* Define to 1 if you have the `wcstombs' function. */ +#cmakedefine HAVE_WCSTOMBS @HAVE_WCSTOMBS@ + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_WCTYPE_H @HAVE_WCTYPE_H@ + +/* Define to 1 if you have the `_findfirst' function. */ +#cmakedefine HAVE__FINDFIRST @HAVE__FINDFIRST@ + +/* Define to 1 if the compiler supports __FUNCTION__. */ +#cmakedefine HAVE___FUNCTION___MACRO @HAVE___FUNCTION___MACRO@ + +/* Define to 1 if the compiler supports __PRETTY_FUNCTION__. */ +#cmakedefine HAVE___PRETTY_FUNCTION___MACRO @HAVE___PRETTY_FUNCTION___MACRO@ + +/* Define to 1 if the compiler supports __func__. */ +#cmakedefine HAVE___func___MACRO @HAVE___func___MACRO@ + +/* Define to 1 if you have the `nanosleep' function. */ +#cmakedefine HAVE_NANOSLEEP @HAVE_NANOSLEEP@ + +/* Define if fails if included extern "C" */ +#define INCLUDE_MATH_H_AS_CXX 1 + +/* Define to 1 if you have variable length arrays. */ +#cmakedefine HAVE_VLA @HAVE_VLA@ + +/* Define to the address where bug reports for this package should be sent. */ +/* #undef PACKAGE_BUGREPORT */ + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "@DCMTK_PACKAGE_NAME@" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "@DCMTK_PACKAGE_STRING@" + +/* Define to the default configuration directory (used by some applications) */ +#define DEFAULT_CONFIGURATION_DIR "@DCMTK_DEFAULT_CONFIGURATION_DIR@" + +/* Define to the default support data directory (used by some applications) */ +#define DEFAULT_SUPPORT_DATA_DIR "@DCMTK_DEFAULT_SUPPORT_DATA_DIR@" + +/* Define to the one symbol short name of this package. */ +/* #undef PACKAGE_TARNAME */ + +/* Define to the date of this package. */ +#define PACKAGE_DATE "@DCMTK_PACKAGE_DATE@" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "@DCMTK_PACKAGE_VERSION@" + +/* Define to the version suffix of this package. */ +#define PACKAGE_VERSION_SUFFIX "@DCMTK_PACKAGE_VERSION_SUFFIX@" + +/* Define to the version number of this package. */ +#define PACKAGE_VERSION_NUMBER @DCMTK_PACKAGE_VERSION_NUMBER@ + +/* Define path separator */ +#define PATH_SEPARATOR '@PATH_SEPARATOR@' + +/* Define as the return type of signal handlers (`int' or `void'). */ +#define RETSIGTYPE void + +/* Define if signal handlers need ellipse (...) parameters */ +/* #undef SIGNAL_HANDLER_WITH_ELLIPSE */ + +/* Define to enable LFS64 (explicit large file support) if available*/ +#cmakedefine _LARGEFILE64_SOURCE @_LARGEFILE64_SOURCE@ + +/* Explicitly request large file support, assuming it exists if fseeko() exists */ +#if defined(HAVE_FSEEKO) && !defined(_LARGEFILE_SOURCE) +#define _LARGEFILE_SOURCE 1 +#endif +#if defined(_LARGEFILE_SOURCE) && !defined(_FILE_OFFSET_BITS) +#define _FILE_OFFSET_BITS 64 +#endif + +/* The size of a `char', as computed by sizeof. */ +#cmakedefine SIZEOF_CHAR @SIZEOF_CHAR@ + +/* The size of a `double', as computed by sizeof. */ +#cmakedefine SIZEOF_DOUBLE @SIZEOF_DOUBLE@ + +/* The size of a `float', as computed by sizeof. */ +#cmakedefine SIZEOF_FLOAT @SIZEOF_FLOAT@ + +/* The size of a `int', as computed by sizeof. */ +#cmakedefine SIZEOF_INT @SIZEOF_INT@ + +/* The size of a `long', as computed by sizeof. */ +#cmakedefine SIZEOF_LONG @SIZEOF_LONG@ + +/* The size of a `short', as computed by sizeof. */ +#cmakedefine SIZEOF_SHORT @SIZEOF_SHORT@ + +/* The size of a `void *', as computed by sizeof. */ +#cmakedefine SIZEOF_VOID_P @SIZEOF_VOID_P@ + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Define to 1 if your declares `struct tm'. */ +/* #undef TM_IN_SYS_TIME */ + +/* Define if ANSI standard C++ includes are used */ +#cmakedefine USE_STD_CXX_INCLUDES + +/* Define if we are compiling with libiconv support. */ +#cmakedefine WITH_LIBICONV + +/* Define if the second argument to iconv() is const */ +#cmakedefine LIBICONV_SECOND_ARGUMENT_CONST @LIBICONV_SECOND_ARGUMENT_CONST@ + +/* Define if we are compiling with libpng support */ +#cmakedefine WITH_LIBPNG + +/* Define if we are compiling with libtiff support */ +#cmakedefine WITH_LIBTIFF + +/* Define if we are compiling with libxml support */ +#cmakedefine WITH_LIBXML + +/* Define if we are compiling with OpenSSL support */ +#cmakedefine WITH_OPENSSL + +/* Define if we are compiling for built-in private tag dictionary */ +#cmakedefine ENABLE_PRIVATE_TAGS + +/* Define if we are compiling with sndfile support. */ +#cmakedefine WITH_SNDFILE + +/* Define if we are compiling with libwrap (TCP wrapper) support */ +#cmakedefine WITH_TCPWRAPPER + +/* Define if we are compiling with zlib support */ +#cmakedefine WITH_ZLIB + +/* Define if we are compiling with any type of Multi-thread support */ +#cmakedefine WITH_THREADS + +/* Define if pthread_t is a pointer type on your system */ +#cmakedefine HAVE_POINTER_TYPE_PTHREAD_T @HAVE_POINTER_TYPE_PTHREAD_T@ + +/* Define to 1 if on AIX 3. + System headers sometimes define this. + We just want to avoid a redefinition error message. */ +#ifndef _ALL_SOURCE +/* #undef _ALL_SOURCE */ +#endif + +/* Define to 1 if type `char' is unsigned and you are not using gcc. */ +#ifndef __CHAR_UNSIGNED__ +/* #undef __CHAR_UNSIGNED__ */ +#endif + +/* Define `pid_t' to `int' if does not define. */ +#cmakedefine HAVE_NO_TYPEDEF_PID_T +#ifdef HAVE_NO_TYPEDEF_PID_T +#define pid_t int +#endif + +/* Define `size_t' to `unsigned' if does not define. */ +#cmakedefine HAVE_NO_TYPEDEF_SIZE_T +#ifdef HAVE_NO_TYPEDEF_SIZE_T +#define size_t unsigned +#endif + +/* Define `ssize_t' to `long' if does not define. */ +#cmakedefine HAVE_NO_TYPEDEF_SSIZE_T +#ifdef HAVE_NO_TYPEDEF_SSIZE_T +#define ssize_t long +#endif + +/* Set typedefs as needed for JasPer library */ +#cmakedefine HAVE_UCHAR_TYPEDEF +#ifndef HAVE_UCHAR_TYPEDEF +typedef unsigned char uchar; +#endif + +#cmakedefine HAVE_USHORT_TYPEDEF +#ifndef HAVE_USHORT_TYPEDEF +typedef unsigned short ushort; +#endif + +#cmakedefine HAVE_UINT_TYPEDEF +#ifndef HAVE_UINT_TYPEDEF +typedef unsigned int uint; +#endif + +#cmakedefine HAVE_ULONG_TYPEDEF +#ifndef HAVE_ULONG_TYPEDEF +typedef unsigned long ulong; +#endif + +#cmakedefine HAVE_LONG_LONG +#cmakedefine HAVE_UNSIGNED_LONG_LONG + +/* evaluated by JasPer */ +#cmakedefine HAVE_LONGLONG +#cmakedefine HAVE_ULONGLONG + + /* Additional settings for Borland C++ Builder */ +#ifdef __BORLANDC__ +#define _stricmp stricmp /* _stricmp in MSVC is stricmp in Borland C++ */ +#define _strnicmp strnicmp /* _strnicmp in MSVC is strnicmp in Borland C++ */ + #pragma warn -8027 /* disable Warning W8027 "functions containing while are not expanded inline" */ + #pragma warn -8004 /* disable Warning W8004 "variable is assigned a value that is never used" */ + #pragma warn -8012 /* disable Warning W8012 "comparing signed and unsigned values" */ +#ifdef WITH_THREADS +#define __MT__ /* required for _beginthreadex() API in */ +#define _MT /* required for _errno on BCB6 */ +#endif +#define HAVE_PROTOTYPE_MKTEMP 1 +#undef HAVE_SYS_UTIME_H +#define NO_IOS_BASE_ASSIGN 1 +#define _MSC_VER 1200 /* Treat Borland C++ 5.5 as MSVC6. */ +#endif /* __BORLANDC__ */ + +/* Platform specific settings for Visual C++ + * By default, enable ANSI standard C++ includes on Visual C++ 6 and newer + * _MSC_VER == 1100 on Microsoft Visual C++ 5.0 + * _MSC_VER == 1200 on Microsoft Visual C++ 6.0 + * _MSC_VER == 1300 on Microsoft Visual C++ 7.0 + * _MSC_VER == 1310 on Microsoft Visual C++ 7.1 + * _MSC_VER == 1400 on Microsoft Visual C++ 8.0 + */ + +#ifdef _MSC_VER +#if _MSC_VER <= 1200 /* Additional settings for VC6 and older */ +/* disable warning that return type for 'identifier::operator ->' is not a UDT or reference to a UDT */ + #pragma warning( disable : 4284 ) +#define HAVE_OLD_INTERLOCKEDCOMPAREEXCHANGE 1 +#else +#define HAVE_VSNPRINTF 1 +#endif /* _MSC_VER <= 1200 */ + + #pragma warning( disable : 4251 ) /* disable warnings about needed dll-interface */ + /* http://www.unknownroad.com/rtfm/VisualStudio/warningC4251.html */ + #pragma warning( disable : 4099 ) /* disable warning about mismatched class and struct keywords */ + /* http://alfps.wordpress.com/2010/06/22/cppx-is-c4099-really-a-sillywarning-disabling-msvc-sillywarnings */ + #pragma warning( disable : 4521 ) /* disable warnings about multiple copy constructors and assignment operators,*/ + #pragma warning( disable : 4522 ) /* since these are sometimes necessary for correct overload resolution*/ + +#if _MSC_VER >= 1400 /* Additional settings for Visual Studio 2005 and newer */ + #pragma warning( disable : 4996 ) /* disable warnings about "deprecated" C runtime functions */ + #pragma warning( disable : 4351 ) /* disable warnings about "new behavior" when initializing the elements of an array */ +#endif /* _MSC_VER >= 1400 */ +#endif /* _MSC_VER */ + +/* Define if your system defines ios::nocreate in iostream.h */ +#cmakedefine HAVE_IOS_NOCREATE @HAVE_IOS_NOCREATE@ + +#ifdef USE_STD_CXX_INCLUDES + +/* Define if ANSI standard C++ includes use std namespace */ +#define HAVE_STD_NAMESPACE 1 + +/* Define if it is not possible to assign stream objects */ +#define NO_IOS_BASE_ASSIGN 1 + +/* Define if the compiler supports std::nothrow */ +#define HAVE_STD__NOTHROW 1 + +/* Define if the compiler supports operator delete (std::nothrow). + * Microsoft Visual C++ 6.0 does NOT have it, newer versions do. + * For other compilers, by default assume that it exists. + */ +#if defined(_MSC_VER) && (_MSC_VER <= 1200) +/* #undef HAVE_NOTHROW_DELETE */ +#else +#define HAVE_NOTHROW_DELETE 1 +#endif + +/* Define if your system has a prototype for std::vfprintf in stdarg.h */ +/* #undef HAVE_PROTOTYPE_STD__VFPRINTF */ + +#else + +/* Define if ANSI standard C++ includes use std namespace */ +/* #undef HAVE_STD_NAMESPACE */ + +/* Define if it is not possible to assign stream objects */ +/* #undef NO_IOS_BASE_ASSIGN */ + +/* Define if the compiler supports std::nothrow */ +/* #undef HAVE_STD__NOTHROW */ + +/* Define if the compiler supports operator delete (std::nothrow) */ +/* #undef HAVE_NOTHROW_DELETE */ + +/* Define if your system has a prototype for std::vfprintf in stdarg.h */ +#cmakedefine HAVE_PROTOTYPE_STD__VFPRINTF @HAVE_PROTOTYPE_STD__VFPRINTF@ + +#endif /* USE_STD_CXX_INCLUDES */ + +/* Define if your system has off64_t */ +#cmakedefine HAVE_OFF64_T @HAVE_OFF64_T@ + +/* Define if your system has fpos64_t */ +#cmakedefine HAVE_FPOS64_T @HAVE_FPOS64_T@ + +/* Define if your system uses _popen instead of popen */ +#cmakedefine HAVE_POPEN @HAVE_POPEN@ + +/* Define if your system uses _pclose instead of pclose */ +#cmakedefine HAVE_PCLOSE @HAVE_PCLOSE@ + +/* Define if your system provides sigjmp_buf as conditional jmp_buf alternative */ +#cmakedefine HAVE_SIGJMP_BUF @HAVE_SIGJMP_BUF@ + +/* Define if your OpenSSL library provides the SSL_CTX_GET0_PARAM function */ +#cmakedefine HAVE_SSL_CTX_GET0_PARAM @HAVE_SSL_CTX_GET0_PARAM@ + +/* Define if your OpenSSL library provides the RAND_egd function */ +#cmakedefine HAVE_RAND_EGD @HAVE_RAND_EGD@ + +/* Always define STDIO_NAMESPACE to ::, because MSVC6 gets mad if you don't. */ +#define STDIO_NAMESPACE :: + +/* Enable or disable C++11 while building DCMTK */ +#cmakedefine DCMTK_USE_CXX11_STL @DCMTK_USE_CXX11_STL@ + +#if defined(DCMTK_USE_CXX11_STL) && defined(__cplusplus) && __cplusplus < 201103L +#error\ + DCMTK was configured to use the C++11 STL, but your compiler is not configured\ + for building with C++11 features. +#endif + +/* Define if the compiler supports __alignof__ */ +#cmakedefine HAVE_GNU_ALIGNOF @HAVE_GNU_ALIGNOF@ + +/* Define if the compiler supports __alignof */ +#cmakedefine HAVE_MS_ALIGNOF @HAVE_MS_ALIGNOF@ + +/* Define if the compiler supports __attribute__((aligned)) */ +#cmakedefine HAVE_ATTRIBUTE_ALIGNED @HAVE_ATTRIBUTE_ALIGNED@ + +/* Define if __attribute__((aligned)) supports templates */ +#cmakedefine ATTRIBUTE_ALIGNED_SUPPORTS_TEMPLATES @ATTRIBUTE_ALIGNED_SUPPORTS_TEMPLATES@ + +/* Define if alignas supports typedefs */ +#cmakedefine ALIGNAS_SUPPORTS_TYPEDEFS @ALIGNAS_SUPPORTS_TYPEDEFS@ + +/* Define if the compiler supports __declspec(align) */ +#cmakedefine HAVE_DECLSPEC_ALIGN @HAVE_DECLSPEC_ALIGN@ + +/* Define if the compiler supports default constructor detection via SFINAE */ +#cmakedefine HAVE_DEFAULT_CONSTRUCTOR_DETECTION_VIA_SFINAE @HAVE_DEFAULT_CONSTRUCTOR_DETECTION_VIA_SFINAE@ + +/* Define if we are cross compiling */ +#cmakedefine DCMTK_CROSS_COMPILING @DCMTK_CROSS_COMPILING@ + +/* The path on the Android device that should be used for temporary files */ +#cmakedefine ANDROID_TEMPORARY_FILES_LOCATION "@ANDROID_TEMPORARY_FILES_LOCATION@" + +#endif /* !OSCONFIG_H*/ diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 00000000..c3234255 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,134 @@ +# Declare project +PROJECT(DCMTK) + +# Minimum CMake version required +CMAKE_MINIMUM_REQUIRED(VERSION 2.6.2) + +# Check the build system +INCLUDE(CMake/dcmtkPrepare.cmake NO_POLICY_SCOPE) + +#----------------------------------------------------------------------------- +# General project settings to configure DCMTK build process +#----------------------------------------------------------------------------- + +# Modules to be built + +SET(DCMTK_MODULES ofstd oflog dcmdata dcmimgle + dcmimage dcmjpeg dcmjpls dcmtls dcmnet dcmsr + dcmsign dcmwlm dcmqrdb dcmpstat dcmrt dcmiod dcmfg dcmseg + CACHE STRING "List of modules that should be built.") + +#----------------------------------------------------------------------------- +# Include directories +#----------------------------------------------------------------------------- + +SET(DCMTK_INCLUDE_DIR ${DCMTK_BINARY_DIR}/config/include) +FOREACH(inc ${DCMTK_MODULES}) + LIST(APPEND DCMTK_INCLUDE_DIR ${DCMTK_SOURCE_DIR}/${inc}/include) +ENDFOREACH(inc) + +INCLUDE_DIRECTORIES(${DCMTK_INCLUDE_DIR}) + +#----------------------------------------------------------------------------- +# Prepare osconfig.h +#----------------------------------------------------------------------------- + +# add the osconfig.h.in file +CONFIGURE_FILE(${DCMTK_SOURCE_DIR}/CMake/osconfig.h.in + ${DCMTK_BINARY_DIR}/config/include/dcmtk/config/osconfig.h) + +#----------------------------------------------------------------------------- +# Prepare arith.h +#----------------------------------------------------------------------------- + +INSPECT_FUNDAMENTAL_ARITHMETIC_TYPES() + +#----------------------------------------------------------------------------- +# Start actual compilation tasks +#----------------------------------------------------------------------------- + +# Recurse into subdirectories +FOREACH(module config doxygen ${DCMTK_MODULES}) + ADD_SUBDIRECTORY(${module}) +ENDFOREACH(module) +INCLUDE(CMake/dcmtkAfterModules.cmake NO_POLICY_SCOPE) + +#----------------------------------------------------------------------------- +# Installation tasks +#----------------------------------------------------------------------------- + +# Install global headers +INSTALL(FILES ${DCMTK_BINARY_DIR}/config/include/dcmtk/config/osconfig.h + DESTINATION ${DCMTK_INSTALL_INCDIR}/dcmtk/config + COMPONENT include) + +# Install DCMTK's general documentation files +INSTALL(FILES ANNOUNCE CHANGES COPYRIGHT CREDITS FAQ HISTORY VERSION + DESTINATION ${DCMTK_INSTALL_DOCDIR} + COMPONENT doc) + +#----------------------------------------------------------------------------- +# Create an install configuration files for external projects +#----------------------------------------------------------------------------- +# +# DCMTKTargets.cmake will contain list of executables and libraries produced +# DCMTKConfigVersion.cmake will contain DCMTK version information +# DCMTKConfig.cmake will contain options used to build DCMTK +# +# All three files are created within the build tree's main directory (handled in +# CMake/GenerateCMakeExports.cmake, and are installed to locations (OS-specific +# under the main install dir (handled directly below). + +# Only create fully-fledged CMake export files if we have the related commands +INCLUDE(CMake/CheckCMakeCommandExists.cmake) +INCLUDE(CMakePackageConfigHelpers OPTIONAL) +CHECK_CMAKE_COMMAND_EXISTS("CONFIGURE_PACKAGE_CONFIG_FILE") +CHECK_CMAKE_COMMAND_EXISTS("WRITE_BASIC_PACKAGE_VERSION_FILE") + +IF(HAVE_CONFIGURE_PACKAGE_CONFIG_FILE AND HAVE_WRITE_BASIC_PACKAGE_VERSION_FILE) + + # Create and configure CMake export files + INCLUDE(CMake/GenerateCMakeExports.cmake) + + # ${dcmtk_install_config} and ${dcmtk_config_version} are + # defined within CMake/GenerateCMakeExports.cmake. + # Install DCMTKTargets.cmake to install tree + INSTALL(EXPORT DCMTKTargets FILE DCMTKTargets.cmake + DESTINATION ${DCMTK_INSTALL_CMKDIR} COMPONENT cmake) + + # Install DCMTKConfigVersion.cmake + INSTALL(FILES ${dcmtk_install_config} ${dcmtk_config_version} + DESTINATION ${DCMTK_INSTALL_CMKDIR} COMPONENT cmake) + +ELSE(HAVE_CONFIGURE_PACKAGE_CONFIG_FILE AND HAVE_WRITE_BASIC_PACKAGE_VERSION_FILE) + + # Warning that we use old "configure_file" command + MESSAGE(STATUS "Warning: Using old CONFIGURE_FILE() mechanism to produce DCMTKConfig.cmake") + + # Actually configure file + CONFIGURE_FILE(${DCMTK_SOURCE_DIR}/CMake/DCMTKConfig.cmake26.in + ${DCMTK_BINARY_DIR}/DCMTKConfig.cmake @ONLY) + + # Install DCMTK's CMake configuration file + INSTALL(FILES ${DCMTK_BINARY_DIR}/DCMTKConfig.cmake + DESTINATION ${DCMTK_INSTALL_CMKDIR} + COMPONENT cmake) + +ENDIF(HAVE_CONFIGURE_PACKAGE_CONFIG_FILE AND HAVE_WRITE_BASIC_PACKAGE_VERSION_FILE) + +#----------------------------------------------------------------------------- +# Configure files needed for cross compiling (if any) +#----------------------------------------------------------------------------- + +IF(CMAKE_CROSSCOMPILING) + IF(ANDROID) + # setup the CTestCustom.cmake file as appropriate for android + FILE(COPY ${DCMTK_SOURCE_DIR}/CMake/CTest/CTestCustom.cmake + DESTINATION ${CMAKE_BINARY_DIR} + ) + # prepare the configuration for unit testing + CONFIGURE_FILE(${DCMTK_SOURCE_DIR}/CMake/CTest/dcmtkCTestConfig.cmake.in + ${CMAKE_BINARY_DIR}/dcmtkCTestConfig.cmake @ONLY + ) + ENDIF() +ENDIF(CMAKE_CROSSCOMPILING) diff --git a/COPYRIGHT b/COPYRIGHT new file mode 100644 index 00000000..86ac1d2c --- /dev/null +++ b/COPYRIGHT @@ -0,0 +1,581 @@ + +COPYRIGHT + +Unless otherwise specified, the DCMTK software package has the following +copyright: + +/* + * Copyright (C) 1994-2015, OFFIS e.V. + * All rights reserved. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * 26121 Oldenburg, Germany + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of OFFIS nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +Please note that some DCMTK modules, especially those that are not part +of the free toolkit, are covered by a separate license which can be found +in the COPYRIGHT file in the corresponding module directory. + +Some portions of the DCMTK software package are derived from earlier +versions of this software with the following copyright, and can be +identified by the following copyright notice located in each source file: + +/* + * Copyright (C) 1993/1994, OFFIS, Oldenburg University and CERIUM + * + * This software and supporting documentation were + * developed by + * + * Institut OFFIS + * Bereich Kommunikationssysteme + * Westerstr. 10-12 + * 26121 Oldenburg, Germany + * + * Fachbereich Informatik + * Abteilung Prozessinformatik + * Carl von Ossietzky Universitaet Oldenburg + * Ammerlaender Heerstr. 114-118 + * 26111 Oldenburg, Germany + * + * CERIUM + * Laboratoire SIM + * Faculte de Medecine + * 2 Avenue du Pr. Leon Bernard + * 35043 Rennes Cedex, France + * + * for CEN/TC251/WG4 as a contribution to the Radiological + * Society of North America (RSNA) 1993 Digital Imaging and + * Communications in Medicine (DICOM) Demonstration. + * + * THIS SOFTWARE IS MADE AVAILABLE, AS IS, AND NEITHER OFFIS, + * OLDENBURG UNIVERSITY NOR CERIUM MAKE ANY WARRANTY REGARDING + * THE SOFTWARE, ITS PERFORMANCE, ITS MERCHANTABILITY OR + * FITNESS FOR ANY PARTICULAR USE, FREEDOM FROM ANY COMPUTER + * DISEASES OR ITS CONFORMITY TO ANY SPECIFICATION. THE + * ENTIRE RISK AS TO QUALITY AND PERFORMANCE OF THE SOFTWARE + * IS WITH THE USER. + * + * Copyright of the software and supporting documentation + * is, unless otherwise stated, jointly owned by OFFIS, + * Oldenburg University and CERIUM and free access is hereby + * granted as a license to use this software, copy this + * software and prepare derivative works based upon this + * software. However, any distribution of this software + * source code or supporting documentation or derivative + * works (source code and supporting documentation) must + * include the three paragraphs of this copyright notice. + * + */ + +Some other parts of this software within the dcmtk/dcmnet sub-package +related to the DICOM Upper Layer Protocol are derived from software +developed for the RSNA'93 DICOM demonstration and kindly made available +to us by the Mallinckrodt Institute of Radiology. Such software can be +identified by the following copyright notice located in each affected +source file: + +/* + * Copyright (C) 1993, RSNA and Washington University + * + * The software and supporting documentation for the Radiological + * Society of North America (RSNA) 1993 Digital Imaging and + * Communications in Medicine (DICOM) Demonstration were developed + * at the + * Electronic Radiology Laboratory + * Mallinckrodt Institute of Radiology + * Washington University School of Medicine + * 510 S. Kingshighway Blvd. + * St. Louis, MO 63110 + * as part of the 1993 DICOM Central Test Node project for, and + * under contract with, the Radiological Society of North America. + * + * THIS SOFTWARE IS MADE AVAILABLE, AS IS, AND NEITHER RSNA NOR + * WASHINGTON UNIVERSITY MAKE ANY WARRANTY ABOUT THE SOFTWARE, ITS + * PERFORMANCE, ITS MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR + * USE, FREEDOM FROM ANY COMPUTER DISEASES OR ITS CONFORMITY TO ANY + * SPECIFICATION. THE ENTIRE RISK AS TO QUALITY AND PERFORMANCE OF + * THE SOFTWARE IS WITH THE USER. + * + * Copyright of the software and supporting documentation is + * jointly owned by RSNA and Washington University, and free access + * is hereby granted as a license to use this software, copy this + * software and prepare derivative works based upon this software. + * However, any distribution of this software source code or + * supporting documentation or derivative works (source code and + * supporting documentation) must include the three paragraphs of + * the copyright notice. + */ + +The dcmjpeg sub-package includes an adapted version of the Independent +JPEG Group Toolkit Version 6b, which is contained in dcmjpeg/libijg8, +dcmjpeg/libijg12 and dcmjpeg/libijg16. This toolkit is covered by the +following copyright. The original README file for the Independent JPEG +Group Toolkit is located in dcmjpeg/docs/ijg_readme.txt. + +/* + * The authors make NO WARRANTY or representation, either express or implied, + * with respect to this software, its quality, accuracy, merchantability, or + * fitness for a particular purpose. This software is provided "AS IS", and you, + * its user, assume the entire risk as to its quality and accuracy. + * + * This software is copyright (C) 1991-1998, Thomas G. Lane. + * All Rights Reserved except as specified below. + * + * Permission is hereby granted to use, copy, modify, and distribute this + * software (or portions thereof) for any purpose, without fee, subject to these + * conditions: + * (1) If any part of the source code for this software is distributed, then this + * README file must be included, with this copyright and no-warranty notice + * unaltered; and any additions, deletions, or changes to the original files + * must be clearly indicated in accompanying documentation. + * (2) If only executable code is distributed, then the accompanying + * documentation must state that "this software is based in part on the work of + * the Independent JPEG Group". + * (3) Permission for use of this software is granted only if the user accepts + * full responsibility for any undesirable consequences; the authors accept + * NO LIABILITY for damages of any kind. + * + * These conditions apply to any software derived from or based on the IJG code, + * not just to the unmodified library. If you use our work, you ought to + * acknowledge us. + * + * Permission is NOT granted for the use of any IJG author's name or company name + * in advertising or publicity relating to this software or products derived from + * it. This software may be referred to only as "the Independent JPEG Group's + * software". + * + * We specifically permit and encourage the use of this software as the basis of + * commercial products, provided that all warranty or liability claims are + * assumed by the product vendor. + */ + +The code for the interpolatePixel() image scaling algorithm in module +dcmimgle has been derived from code written by Jef Poskanzer for the +"Extended Portable Bitmap Toolkit" (pbmplus10dec91) which has the +following copyright: + +/* + * Copyright (C) 1991 by Jef Poskanzer. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, provided + * that the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation. This software is provided "as is" without express or + * implied warranty. + */ + +The color quantization code in module dcmimage (dcmquant and the related +classes) has been derived from code written by Jef Poskanzer for the +NetPBM toolkit which has the following copyright: + +/* + * Copyright (C) 1989, 1991 by Jef Poskanzer. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, provided + * that the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation. This software is provided "as is" without express or + * implied warranty. + */ + +The code for the OFStandard::strlcpy and OFStandard::strlcat helper +functions in ofstd/libsrc/ofstd.cc has been derived from the BSD +implementation of strlcpy() and strlcat() and which carries the +following copyright notice: + +/* + * Copyright (c) 1998 Todd C. Miller + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +The code for the OFStandard::atof helper function in ofstd/libsrc/ofstd.cc +has been derived from an implementation which carries the following +copyright notice: + +/* + * Copyright 1988 Regents of the University of California + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appear in all copies. The + * University of California makes no representations about the + * suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * + * The code for OFStandard::ftoa has been derived + * from an implementation which carries the following copyright notice: + * + * Copyright (c) 1988 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +The "Base64" encoder/decoder in ofstd/libsrc/ofstd.cc has been derived +from an implementation which carries the following copyright notice: + +/* + * Copyright (c) 1999, Bob Withers - bwit(at)pobox.com + * + * This code may be freely used for any purpose, either personal or commercial, + * provided the authors copyright notice remains intact. + */ + +The oflog sub-package is based on the log4cplus library which is covered by +the following two copyright notices (for details see oflog/docs/LICENSE): + +/* + * Copyright (C) 1999-2009 Contributors to log4cplus project. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modifica- + * tion, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- + * DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +// Module: Log4CPLUS +// File: appender.h +// Created: 6/2001 +// Author: Tad E. Smith +// +// +// Copyright 2001-2010 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +The dcmjpls sub-package is based on the CharLS library, which is contained +in dcmjpls/libcharls. This toolkit is covered by the following copyright: + +/* + * The CharLS library is available under the following license: + * ------------------------------------------------------------------------------- + * Copyright (c) 2007-2010, Jan de Vaan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * * Neither the name of my employer, nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +The file ofstd/include/dcmtk/ofstd/oftest.h is heavily based on quicktest.h +from the quicktest project, which is covered by the following copyright: + +/************************************************************************ +* QuickTest * +* http://quicktest.sourceforge.net * +* Copyright (C) 2005-2008 * +* Tyler Streeter (http://www.tylerstreeter.net) * +* * +* This library is free software; you can redistribute it and/or * +* modify it under the terms of EITHER: * +* (1) The GNU Lesser General Public License as published by the Free * +* Software Foundation; either version 2.1 of the License, or (at * +* your option) any later version. The text of the GNU Lesser * +* General Public License is included with this library in the * +* file license-LGPL.txt. * +* (2) The BSD-style license that is included with this library in * +* the file license-BSD.txt. * +* * +* This library is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * +* license-LGPL.txt and license-BSD.txt for more details. * +************************************************************************/ + +The above mentioned license-BSD.txt contains this text: + +BSD Open Source license for QuickTest +------------------------------------- + +QuickTest +Copyright (c) 2005-2008, Tyler Streeter +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, this + list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + +* Neither the name of QuickTest's copyright owners nor the names of its + contributors may be used to endorse or promote products derived from this + software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +--- + +The files ofstd/include/dcmtk/ofstd/ofxml.h and ofstd/libsrc/ofxml.cc are +derived from the XMLparser library, which is covered by the following +copyright: + +/* + * Copyright (c) 2002, Frank Vanden Berghen + * All rights reserved. + * + * The following license terms apply to projects that are in some way related to + * the "DCMTK project", including applications + * using "DCMTK project" and tools developed + * for enhancing "DCMTK project". All other projects + * (not related to "DCMTK project") have to use this + * code under the Aladdin Free Public License (AFPL) + * See the file "AFPL-license.txt" for more informations about the AFPL license. + * (see http://www.artifex.com/downloads/doc/Public.htm for detailed AFPL terms) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Frank Vanden Berghen nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY Frank Vanden Berghen ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +The dcmrt sub-package is covered by the following copyright: + +--------------------------------------------------------------------------- + +Copyright (c) 2008-2012, OFFIS e.V. and ICSMED AG, Oldenburg, Germany +Copyright (C) 2013-2014, J. Riesmeier, Oldenburg, Germany +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the copyright holders nor the names of its + contributors may be used to endorse or promote products derived from this + software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +Parts of the dcmsr sub-package are covered by the following copyright: + +--------------------------------------------------------------------------- + +Copyright (c) 2015, J. Riesmeier, Oldenburg, Germany +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the copyright holders nor the names of its + contributors may be used to endorse or promote products derived from this + software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +--------------------------------------------------------------------------- + +The Android toolchain configuration file for CMake +(CMake/android.toolchain.cmake) is borrowed from the OpenCV project and is +covered by the following copyright: + +--------------------------------------------------------------------------- + +# Copyright (c) 2010-2011, Ethan Rublee +# Copyright (c) 2011-2014, Andrey Kamaev +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# 3. Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from this +# software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +--------------------------------------------------------------------------- diff --git a/CREDITS b/CREDITS new file mode 100644 index 00000000..906d7eeb --- /dev/null +++ b/CREDITS @@ -0,0 +1,50 @@ + +CREDITS + +We would like to thank the following individuals, companies and organizations +(in alphabetical order) for supporting the development and maintenance of the +Open Source DICOM Toolkit DCMTK: + + +DKFZ: The work on the DCMTK module "dcmrt" was supported in part by funding + from the Deutsches Krebsforschungszentrum (Heidelberg, Germany). + +Epilepsieforschung: The Gesellschaft fuer Epilepsieforschung e.V. (Bielefeld, + Germany) supported the DCMTK by sponsoring the initial development of the + tool "dcmrecv" and the underlying class "DcmStorageSCP". + +ICSMED: From 2006 to 2012, the work on the DCMTK was supported by employees of + the ICSMED AG (Oldenburg, Germany), a spin-off from the OFFIS institute. + +ITH icoserve: The ITH icoserve technology for healthcare GmbH (Innsbruck, + Austria) regularly reports issues to the DCMTK team and contributes patches. + The company is also known for testing the latest DCMTK snapshots and providing + useful feedback. + +J. Riesmeier: The work on the DCMTK is supported by Joerg Riesmeier (Oldenburg, + Germany), a former employee of both the OFFIS institute and the ICSMED company + who now works as a freelancer. + +M. Malaterre: The GDCM developer Mathieu Malaterre (Lyon, France) regularly + reports possible issues to the DCMTK team. He is also responsible for + packaging the DCMTK library and tools for the Debian operating system. + +Open Connections: The work on the DCMTK is supported by employees of the Open + Connections GmbH (Oldenburg, Germany), a spin-off from the OFFIS institute. + +QIICR: The work on various DCMTK modules was supported in part by funding from + the National Institutes of Health and the NCI Informatics Technology for + Cancer Research (ITCR) initiative to the Quantitative Image Informatics for + Cancer Research (QIICR) project, award U24 CA180918. + +VISUS: The work on various extensions of the DCMTK was supported in part by + funding from the VISUS Technology Transfer GmbH (Bochum, Germany). + +YXLON: The work on the initial version of the DICONDE data dictionary was + supported by funding from the YXLON International GmbH (Hamburg, Germany). + + +Please note that this list does not claim to be exhaustive. Just send us an +email if you think that you or your company/organization should also be listed. + +DCMTK Team, 2015-09-12 diff --git a/FAQ b/FAQ new file mode 100644 index 00000000..3b034938 --- /dev/null +++ b/FAQ @@ -0,0 +1,3 @@ +DCMTK FAQ - Frequently Asked Questions + +The FAQ is now available online: http://forum.dcmtk.org/faq diff --git a/HISTORY b/HISTORY new file mode 100644 index 00000000..e69354da --- /dev/null +++ b/HISTORY @@ -0,0 +1,65 @@ + +The OFFIS DICOM Toolkit DCMTK + +In 1993, the OFFIS institute and Oldenburg University, Germany supported by +CERIUM, Rennes, France, developed a DICOM implementation on behalf of +CEN/TC251/WG4 as part of a DICOM demonstration at RSNA'93. The software +started with a early version of the DICOM Upper Layer Protocol facility +developed by the Mallinckrodt Institute of Radiology in St. Louis, USA. The +rest of this software was developed independently and successfully demonstrated +for the first time at RSNA'93. Interoperability was demonstrated with around +20 implementations from vendors of medical imaging equipment, with both this +software and the Mallinckrodt Institute of Radiology's own implementation. +This implementation became known as the European CTN (Central Test Node). + +The European CTN software was further extended by OFFIS in 1994 and 1995 and +used as part of DICOM demonstrations at EuroPACS'94 in Geneva, ECR'95 in Vienna +and CAR'95 in Berlin where even more vendors of imaging equipment were able to +demonstrate interoperability. + +During 1996, the software was rewritten by OFFIS to use a new C++ based DICOM +encoding/decoding library and has been supplemented with a Modality Worklist +CTN, demonstrated for the first time at CAR'96 in Paris, France. The CAR'96 +DICOM demonstration featured Modality Worklist Management and Image +Storage/Query/Retrieval. The available software includes source code and +documentation for the worklist management and image storage/query/retrieve +server applications, a number of test applications, and the necessary +libraries. A similar industry demonstration also took place at the European +Congress of Radiology (ECR '97) in Vienna and at CAR'97 in Berlin. + +Beginning with release 3.0 (1996), the software package was renamed to DCMTK +(DiCoM ToolKit). It contains a number of improvements over the "European CTN" +software previously available from OFFIS/Oldenburg University, the most +important being: + - configuration using GNU autoconf + - a modality worklist SCP and SCU + - a new C++ encoding/decoding library + - support for offline media + - support for explicit VR transfer syntaxes + - a user-extensible data dictionary + - support for all balloted image SOP classes + +In 1997, a tool allowing to create DICOMDIRs according to the "General Purpose +CD-R Image Interchange Profile" was added. This tool was used to master the +CAR' 97 and NEMA '97 DICOM Demonstration CDs. + +Beginning in 1998, new libraries for efficient rendering of DICOM grayscale +images, display calibration according to DICOM part 14 and an implementation of +the Grayscale Softcopy Presentation State (GSPS) supplement were added and +demonstrated at ECR '99 and RSNA InfoRAD '99. Together with an implementation +of DICOM basic grayscale print management (SCU and SCP, both supporting +presentation LUT) and a small GSPS checker these tools were used for testing +purposes for the "softcopy and hardcopy consistency" part of the IHE +(Integrating the Healthcare Enterprise), an initiative of RSNA and HIMSS. + +For the RSNA 2000 and the ECR 2001, DICOM's new security extensions on secure +transport connections (TLS - Transport Layer Security) and Digital Signatures +were added together with a library for DICOM Structured Reporting. Furthermore, +support for color images has been moved to the public part of the toolkit +(required separate licensing before). + +To be continued ... + +In addition to the freely available DCMTK software, OFFIS has also developed +other DICOM software which must be licensed separately. These separate packages +build on the facilities provided by DCMTK. -- See: http://dicom.offis.de/ diff --git a/INSTALL b/INSTALL new file mode 100644 index 00000000..4cdf279c --- /dev/null +++ b/INSTALL @@ -0,0 +1,793 @@ + +================================== +DICOM TOOLKIT (DCMTK) INSTALLATION +================================== + +------------------------------------------------------------------------------- + IMPORTANT NOTE FOR SNAPSHOT AND CURRENT DEVELOPMENT VERSION 3.6.1_DEV +------------------------------------------------------------------------------- + Please note that most sections of this document refer to the official release + DCMTK 3.6.0, i.e. they are not yet updated for the changes of the latest + development version 3.6.1. This will be done for the next release, which will + probably be called version 3.6.2. + + The toolkit should compile on Linux systems with gcc 4.7.2 to 4.9.2 since + this is our main development platform. Also on Windows systems, it usually + works with VisualStudio 2008 to 2013. However, there is no guarantee that + the software also compiles on your system. +------------------------------------------------------------------------------- + + +PRE-REQUISITES +============== + +The DICOM toolkit (DCMTK) needs to be compiled with a C++ compiler. We +recommend using the GNU C++ compiler in versions higher than 2.95 (most of the +development was done using GNU C++ 4.1.2 on Linux 2.6). The software is also +known to compile using the SUNPro C++ compiler, the Intel C++ compiler and the +Microsoft Visual C++ compiler. + +Compatibility with other C++ compilers is unknown, however, we have tried to +keep language demands to a minimum (newer C++ features such as ANSI C++ Library, +Exceptions and RTTI have been avoided). + +You will need several hundred Mbytes of disk space to compile all the software. + + +SUPPORTED SYSTEMS +================= + +Microsoft Windows +----------------- + +The DCMTK software can be compiled under a native Microsoft Windows environment +(see section "BUILDING (Windows)" below for more information). + +The current release successfully compiles on the following systems: + + Windows XP / Intel x86 / Microsoft Visual C++ 6.0 (Service Pack 6) + Windows XP / Intel x86 / Microsoft Visual C++ 2005 Standard (VS 8) + Windows XP / Intel x86 / Microsoft Visual C++ 2008 Express (VS 9) + Windows XP / Intel x86 / Microsoft Visual C++ 2010 Express (VS 10) + Windows Vista / Intel x86 / Microsoft Visual C++ 2008 Professional (VS 9) + Windows 7 / Intel x86 / Microsoft Visual C++ 2010 Express (VS 10) + Windows 7 / amd64|x86_64 / Microsoft Visual C++ 2010 Express (VS 10) + Windows 7 / amd64|x86_64 / Microsoft Visual C++ 2010 Ultimate (VS 10) + +The dcmqrscp tool has been ported to Windows, but does not yet support +multi-processing (i.e. multiple clients concurrently) under Windows. The +worklist WWW scripts require an HTTP server and a Perl interpreter and have +not been tested under Windows (file locking interaction with the wlmscpfs +server may or may not work). + +Unix (or lookalikes) +-------------------- + +The current DCMTK software release successfully compiles on the following +operating system / hardware / compiler combinations using the instructions +given below: + + FreeBSD 6.4 / Intel x86 / GNU gcc 3.4.6 + FreeBSD 7.3 / Intel x86 / GNU gcc 4.2.1 + FreeBSD 8.1 / Intel x86 / GNU gcc 4.2.1 + FreeBSD 8.1 / amd64|x86_64 / GNU gcc 4.2.1 + HP-UX 10.20 / HP PA-RISC / GNU gcc 2.95.3 (see note *1,*2) + IRIX 6.3 / SGI O2 / GNU gcc 2.95.3 (see note *1) + Linux 2.4.20 / Intel x86 / GNU gcc 2.95.3 (RedHat 7.3) + Linux 2.4.21 / Intel x86 / GNU gcc 3.4.6 (CentOS 3.9) + Linux 2.6.18 / Intel x86 / GNU gcc 4.1.2 (Debian 4.0) + Linux 2.6.18 / amd64|x86_64 / Intel Compiler 11.1 (Scientific Linux 5.5) + Linux 2.6.18 / amd64|x86_64 / GNU gcc 4.1.2 (Debian 4.0) + Linux 2.6.18 / amd64|x86_64 / GNU gcc 4.5.2 (CentOS 5.5) + Linux 2.6.26 / amd64|x86_64 / GNU gcc 4.3.2 (Debian 5.0) + Linux 2.6.32 / amd64|x86_64 / GNU gcc 4.4.4 (RHEL 6.0) + Linux 2.6.34 / amd64|x86_64 / Intel Compiler 11.1 (SuSE 11.3, see note *3) + Linux 2.6.35 / amd64|x86_64 / GNU gcc 4.4.5 (Ubuntu 10.10) + MacOS X 10.4.10 / amd64|x86_64 / Apple gcc 4.0.1 (see note *10) + MacOS X 10.6.5 / amd64|x86_64 / Apple gcc 4.2.1 (see note *10) + OpenBSD 4.4 / Intel x86 / GNU gcc 3.3.5 propolice + Solaris 9 / Sun Sparc / SunPro CC 5.8 (Sun Studio 11) + Solaris 10 / Sun Sparc / SunPro CC 5.9 (Sun Studio 12u2) + Solaris 10 / Sun Sparc / GNU gcc 3.4.3 + Windows XP / Intel x86 / CygWin 1.7.7-1 (gcc 3.4.4 and 4.3.4) + Windows XP / Intel x86 / MinGW/MSys 1.0.11 (gcc 4.5.0) + +Earlier releases are known to also compile on the following platforms which +are not available to us for testing purposes any more: + + FreeBSD 4.11 / Intel x86 / GNU gcc 2.95.4 + FreeBSD 6.0 / Intel x86 / GNU gcc 3.4.4 + HP-UX 9.05 / HP PA 1.1 / GNU gcc 2.7.2.1 + IBM AIX 3.2 / RS 6000 / IBM AIX XL C++ Compiler/6000 V1.0 + IRIX 5.3 / SGI Indy / GNU gcc 2.95.2 (see note *1) + IRIX 6.5 / SGI Onyx / GNU gcc 2.95.2 (see note *4) + IRIX 6.5 / SGI Onyx / MIPSpro 7.3.1.1m (see note *4) + Linux 2.0.33 / Intel x86 / GNU gcc 2.7.2.1 + Linux 2.2.16 / IBM S/390 / GNU gcc 2.95.2 + Linux 2.2.16 / Intel x86 / GNU gcc 2.95.2 + Linux 2.4.20 / Intel x86 / GNU gcc 2.95.4, 3.2.3, 3.3.6, 3.4.5 and 4.0.3 (Debian) + Linux 2.6.1 / amd64|x86_64 / GNU gcc 4.0 (Fedora Core 4) + MacOS X 10.1.5 / Power Mac G4 / Apple gcc-934.3 (gcc 2.95.2, see note *5) + MacOS X 10.3.3 / Power Mac G4 / Apple gcc-1640 (gcc 3.3) + MacOS X 10.4.3 / Power Mac G4 / Apple gcc 4.0.1 + NetBSD 1.6.2 / Intel x86 / GNU gcc 2.95.3 + NetBSD 2.1 / Intel x86 / GNU gcc 3.3.3 + NeXTStep 3.3 / Intel x86 / NeXT/GNU gcc 2.5.8 (see note *6) + OpenBSD 3.8 / Intel x86 / GNU gcc 3.3.5 propolice + OSF/1 4.0 / DEC Alpha / Compaq C++ V6.3-002 (see note *7) + OSF/1 4.0 / DEC Alpha / GNU gcc 2.95.3 + QNX 6.2.1 / Intel x86 / GNU gcc 2.95.3 (see note *8) + Solaris 2.5.1 / Sun Sparc / GNU egcs 1.1.2 (egcs-2.91.66) + Solaris 2.5.1 / Sun Sparc / Sun SC 2.0.1 (SunPro C++ 3.0.1) + Solaris 2.5.1 / Sun Sparc / SunPro CC 4.2 + Solaris 7 / Sun Sparc / GNU gcc 2.95.3 + Solaris 7 / Sun Sparc / SunPro CC 4.2 + Solaris 8 / Sun Sparc / GNU gcc 3.2.3, 3.4 + Solaris 8 / Sun Sparc / SunPro CC 5.2 (Sun WorkShop 6 update 1) + Solaris 9 / Sun Sparc / SunPro CC 5.2 (Sun WorkShop 6 update 1) + Solaris 10 / Intel x86 / SunPro CC 5.8 (Sun Studio 11) + SunOS 4.1.3 / Sun Sparc / GNU gcc 2.7.2 + Ultrix 4.4 / DEC MIPS / GNU gcc 2.95.2 (see notes *1,*9) + Windows 9x / Intel x86 / Microsoft Visual C++ 5.0 + Windows NT 4.0 / Intel x86 / Microsoft Visual C++ 6.0 (Service Pack 6) + Windows XP / Intel x86 / Microsoft Visual C++ .NET 2003 (VS 7.1) + Windows XP / Intel x86 / CygWin 1.5.18 (gcc 3.4.4) + Windows XP / Intel x86 / MinGW/MSys 1.0.10 (gcc 3.4.2) + +Platform Notes +-------------- + +(*1) The dcmimage/dcmimgle module makes intensive use of inlined templates. + Depending on the compiler and the available virtual memory, compilation + might fail if this module is compiled with optimization. Compilation + succeeds if the optimizer and any automatic inlining of code are switched + off. For example GNU gcc might require that the -O option is removed and + -fno-default-inline is added to the CXXFLAGS setting in the file + "config/Makefile.def", which is created by configure (see below). +(*2) HP-UX 10.2 requires DCMTK to be configured with --disable-lfs, i.e. + without large file support. +(*3) Building with Intel Compiler Suite 11.1 requires GNU C++ Standard Library + version 4.3. +(*4) IRIX 6 users are recommended to consult SGI's Notes on building Open + Source software on IRIX, available from: http://freeware.sgi.com/howto.html + In short, after running configure, the following modifications are + required in "config/Makefile.def" before DCMTK can be compiled: + - remove "-lsocket -lnsl" from LIBS + On IRIX, DCMTK should be built using GNU make (gmake), not with the IRIX + specific pmake/smake/make commands. +(*5) MacOS X 10.1 requires DCMTK to be configured with --disable-threads + because certain re-entrant Posix functions such as localtime_r are not + available. +(*6) The NeXT gcc 2.5.8 compiler provides only very limited support for C++ + templates and, therefore, might fail to compile the dcmimage/dcmimgle + module ("internal compiler error"). The gcc compiler also does not + properly support the "protected" derivation of classes which is used in + the dcmsr module. However, modules and applications that were present in + earlier releases of DCMTK still compile. +(*7) Might require -O0 in order to compile "dcmsr/libsrc/dsrdoctr.cc". +(*8) The libz.so included in QNX 6.2.1 is missing the zlibVersion() + function. This will cause the DCMTK compile to fail if configured with + --with-zlib. It has already been corrected in QNX's internal cvs + repository. Earlier QNX versions (6.2.0) and future versions (6.3.x) + should work fine. As a temporary measure it is possible to link against + /usr/lib/libz.so.1 which does include that function, or to disable zlib + support in DCMTK by calling configure --without-zlib. +(*9) Requires -fpermissive when compiled with GNU gcc due to the X11R5 header + files which are not ANSI compliant. +(*10) For MacOS X 10.4 and 10.6 the OFSemaphore class is not available since it + is compiling but not working on MacOS X. The reason is that semaphores + must be named in MacOS X and thus the current implementation fails to + construct semaphores in the OFSemaphore constructor. However, the toolkit + so far does not make any use of this class. + +Please note: Due to resource limitations it is not practical for us to ensure +that the newest release of DCMTK is problem free under all the above +combinations. Currently, our main development environment is Linux 2.6 using +GNU C++ 4.1.2 and DCMTK should always compile on this platform. + + +OPENSSL SUPPORT +=============== + +Starting with release 3.4.2, DCMTK supports the "DICOM Security Enhancements +One", i.e. DICOM network transmission "tunneled" through a secure TLSv1 +transport connection. DCMTK relies on the OpenSSL toolkit (www.openssl.org) +for the underlying cryptographic routines and the TLS protocol implementation. +This release of DCMTK is known to compile with the OpenSSL releases 0.9.8 to +1.0.0, although other releases may work as well. + +When using autoconf, if support for security enhancements is desired, a compiled +version of the OpenSSL libraries and include files must be available during +compilation of DCMTK. By default, DCMTK checks whether OpenSSL is installed +in the standard path and enables support automatically if present. + +When using CMake, if support for security enhancements is desired, a compiled +version of the OpenSSL libraries and include files must be available during +compilation of DCMTK, and the OpenSSL support must be switched on explicitly +(using CMake, see below). By default, DCMTK checks whether OpenSSL is installed +and enables support automatically if present. By default, DCMTK checks the +standard paths on Unix platforms. For Windows platforms, check the discussion +on CMake below. + + +ZLIB SUPPORT +============ + +Starting with release 3.5.2, DCMTK supports the "Deflated Explicit VR Little +Endian" Transfer Syntax, i.e. ZIP-compressed network transmission and media +storage. DCMTK relies on the zlib toolkit (www.zlib.org) for the underlying +compression routines. This release of DCMTK is known to compile with the +zlib releases 1.2.3 to 1.2.5, although other releases may work as well. + +When using autoconf, if support for zlib compression is desired, a compiled +version of the zlib library and include files must be available during +compilation of DCMTK. By default, DCMTK checks whether zlib is installed +in the standard path and enables support automatically if present. + +When using CMake, a compiled version of the zlib libraries and include +files must be available during compilation of DCMTK. See discussion on CMake +below. + + +LIBTIFF SUPPORT +=============== + +Starting with release 3.5.1, DCMTK supports the conversion of DICOM images +to TIFF. DCMTK relies on the libtiff toolkit (www.libtiff.org) for this +purpose. This release of DCMTK is known to compile with the libtiff releases +3.7.4 to 3.9.4, although other releases may work as well. However, libtiff +releases prior to version 3.7.0 will not work since the TIFFCleanup() function +was not yet available. On Windows, libtiff 3.7.4 or higher is required due to +incompatible API changes in libtiff. + +When using autoconf, if support for TIFF export is desired, a compiled version +of the libtiff libraries and include files must be available during compilation +of DCMTK, and the libtiff support must be switched on explicitly. By default, +DCMTK checks whether libtiff is installed in the standard path and enables +support automatically if present. + +When using CMake, a compiled version of the libtiff libraries and include +files must be available during compilation of DCMTK. See discussion on CMake +below. + + +LIBPNG SUPPORT +============== + +Starting with release 3.5.3, DCMTK supports the conversion of DICOM images to +PNG. DCMTK relies on the libpng toolkit (www.libpng.org) for this purpose. +This release of DCMTK is known to compile with the current libpng releases +1.2.8 to 1.4.3, although other releases may work as well. + +When using autoconf, if support for PNG export is desired, a compiled version of +the libpng libraries and include files must be available during compilation of +DCMTK, and the libpng support must be switched on explicitly. By default, +DCMTK checks whether libpng is installed in the standard path and enables +support automatically if present. It should be noted that libpng requires +zlib. + +When using CMake, a compiled version of the libpng libraries and include +files must be available during compilation of DCMTK. See discussion on CMake +below. + + +LIBXML2 SUPPORT +=============== + +Starting with release 3.5.3, DCMTK supports the conversion of XML documents to +DICOM files. DCMTK relies on the libxml2 toolkit (www.libxml.org) for this +purpose. This release of DCMTK is known to compile with the libxml2 releases +2.6.26 to 2.7.7, although other releases may work as well. + +When using autoconf, if support for XML import is desired, a compiled version of +the libxml2 (and possibly iconv) libraries and include files must be available +during compilation of DCMTK. By default, DCMTK checks whether libxml2 is +installed in the standard path and enables support automatically if present. + +When using CMake, if support for XML import is desired, a compiled version +of the libxml2 (and possibly iconv) libraries and include files must be +available during compilation of DCMTK. See discussion on CMake below. + + +TCP WRAPPER (LIBWRAP) SUPPORT +============================= + +Starting with release 3.5.3, DCMTK supports Wietse Venema's TCP wrappers +library (libwrap) which is freely available for most Unix platforms and part +of the default installation of most recent Linux distributions. This library +allows to enforce host-based access control via the "/etc/hosts.deny" and +"/etc/hosts.allow" configuration files. See hosts_access(5) man page for +details. + +When using autoconf, if support for TCP wrappers is desired, a compiled version +of the libwrap library and include file must be available during +compilation of DCMTK. By default, DCMTK checks whether libwrap is installed +in the standard path and enables support automatically if present. + +Since DCMTK uses the TCP wrappers from C++ code, an ANSI C compatible header +file is required. The official release 7.6 of the TCP wrappers +library is not ANSI C compatible and does not work with DCMTK (i.e. will not be +recognized by DCMTK's configure script). However, many current Linux and BSD +distributions ship with an ANSI C compatible header file. + +When using CMake, TCP wrappers are currently not supported. + + +LIBICONV SUPPORT +================ + +Starting with release 3.6.2, DCMTK supports the conversion between different +character encodings. For this purpose, DCMTK relies on the libiconv toolkit +(www.gnu.org/s/libiconv/). This release of DCMTK is known to compile with the +libiconv release 1.14, although other releases may work as well. + +When using autoconf, if support for libiconv conversion is desired, a compiled +version of the libiconv library and include files must be available during +compilation of DCMTK. Please note that DCMTK also needs the bundled copy of +libcharset. By default, DCMTK checks whether libiconv and libcharset are +installed in the standard path and enables support automatically if present. + +When using CMake, a compiled version of the libiconv and libcharset libraries +and include files must be available during compilation of DCMTK. See discussion +on CMake below. + + +C++11 SUPPORT +============= +DCMTK can be enabled to use the C++11 STL. This is controlled by the macro +"DCMTK_USE_CXX11_STL", described in "config/docs/macros.txt" (or +"/usr/local/share/doc/dcmtk/macros.txt"). + + +BUILDING (Unix with autoconf) +============================= + +GNU autoconf is used to configure the software for the hardware / operating +system you are using. You do not need to obtain GNU autoconf to compile and +install this software. All the necessary configure scripts are included in +this distribution. The configure scripts examine your system capabilities and +automatically generate include files and Makefiles. + +Perform the following steps from the top-level (dcmtk-3.6.0) directory to +compile and install the software: + +Step 1: + ./configure + +Step 1 executes the configure scripts in each subdirectory. First, the system +capabilities are examined and then Makefiles are generated. By default, +executables and other files will be installed (in Step 3) in the directory +"/usr/local" in the corresponding subdirectories. If you wish to use another +install prefix you can use the --prefix= flag to configure. E.g., if you +wish to install underneath your home directory in "~/dicom" then you should +start configure as: + + ./configure --prefix=$HOME/dicom + +Step 1 is also the place where support for the external libraries can be +enabled or disabled. By default, all libraries installed in the standard +path are enabled automatically. Use the --without-openssl switch to disable +OpenSSL support. The --with-opensslinc option allows to specify the directory +in which OpenSSL is installed. This is usually the directory that has been +used as --prefix when compiling and installing OpenSSL. + +For example, if you wish to enable the security enhancements, and OpenSSL is +installed in "/usr/local/apps/openssl-1.0.0", then you should start configure +as: + + ./configure --with-opensslinc=/usr/local/apps/openssl-1.0.0 + +Configure will assume that the OpenSSL include files are installed in +"/usr/local/apps/openssl-1.0.0/include" and will expect the library in +"/usr/local/apps/openssl-1.0.0/lib". Appropriate options will be passed to +the compiler and the linker. + +Support for zlib, libtiff, libpng, libxml2, libwrap and libiconv can be enabled +in a similar way (in case these libraries are not installed in the standard +path): + + ./configure --with-libzlibinc=/usr/local/apps/zlib-1.2.5 + --with-libtiffinc=/usr/local/apps/libtiff-3.9.4 + --with-libpnginc=/usr/local/apps/libpng-1.4.3 + --with-libxmlinc=/usr/local/apps/libxml-2.7.7 + --with-libwrapinc=/usr/local/apps/tcp_wrappers-7.6 + --with-libiconvinc=/usr/local/apps/libiconv-1.14 + +Different configure options can be combined in any order. configure --help +will print a list of all existing configure options. configure --help=short +will display only those options specific to the DCMTK. Useful configure +options are: + + --enable-debug compile with debug code, don't optimize + --disable-debug compile without debug code (default) + --enable-threads=TYPE compile with MT support (posix/solaris/auto=default) + --disable-threads compile without MT support + --enable-lfs=TYPE compile with LFS support (lfs/lfs64/auto=default) + --disable-lfs compile without LFS support + --enable-std-includes use C++ ANSI standard includes + --disable-std-includes use old C++ includes + +Step 2: + make all + +Step 2 will build the libraries and executables. If you run into problems see +the section "Solving configuration and compilation problems" below. + +Step 3: + make install + +Step 3 will install the executables and some support files (data dictionary, +configuration and documentation files). If you also wish to install the +libraries and include files then use "make install-lib". For the HTML +documentation (see below) use "make install-html" (requires Doxygen to be +installed); "make install-all" installs all of the above. + +In case the files should be installed in a temporary directory, e.g. in order +to create a distribution package, use "make install DESTDIR=" to prepend + to the installation directories specified for configure. + +Step 4: + make distclean + +Step 4 will revert the source tree to the state prior to Step 1. If you just +want to get rid of object files and local executables use "make clean" instead. + +Note: In case you do not want to compile all modules, you can remove those +modules from the text file "config/modules" prior to Step 1 and execute the +following commands: + + cd config + ./rootconf + cd .. + +This generates a new Makefile and configure script in the top-level toolkit +directory. + +Solving configuration and compilation problems: + +The configure script might not be able to guess the correct compiler and +compiler flags to use. For example, we have noticed that use of the -pedantic +flag to the GNU C++ compiler causes compilation errors on some systems (e.g. +SunOS 4.1.3) due to system include files with incorrect ANSI function +prototypes. + +You can set environment variables to initialize configure before it is called +(before Step 1 above): + + Set environment variable CC to the name of your C compiler. + Set environment variable CFLAGS to the compile flags of your C compiler. + Set environment variable CXX to the name of your C++ compiler. + Set environment variable CXXFLAGS to the compile flags of your C++ compiler. + Set environment variable LDFLAGS to your linker flags. + Set environment variable CPPFLAGS to you preprocessor flags. + +You do not need to specify all the above environment variables since the +default settings are sensible for most Unix compilers. Further influential +environment variables are listed in the output of configure --help. + +If the configure script fails you may have to change the configuration settings +in the config directory. See the "config/docs" directory for more information. + +See also the FAQ at http://forum.dcmtk.org/faq for more hints. + + +BUILDING (CMake in general) +=========================== + +CMake is a cross-platform, open-source make system which can be used to control +the software compilation process using simple configuration files. CMake can be +obtained free of charge from http://www.cmake.org/. For configuring the DCMTK, +the toolkit contains corresponding "CMakeLists.txt" files in all necessary +directories. In detail, these "CMakeLists.txt" files will serve as an input to +CMake which will generate suitable build files for all of DCMTK's projects from +these files. + +More info about building the DCMTK with CMake can be found in DCMTK's wiki: + + http://support.dcmtk.org/wiki/dcmtk/howto/cmakeconfiguration + + +Microsoft Windows with CMake +---------------------------- + +Starting with DCMTK 3.5.4, no project files for Visual Studio are provided +anymore. Project files for all supported compilers can be generated with +CMake. + +In order to be able to use CMake for configuration purposes in DCMTK, perform +the following steps to install CMake on your machine: + +1. Go to http://www.cmake.org/ to download the latest release version of CMake + for Windows. +2. Execute the file which was downloaded to install CMake on your machine. + Follow all install instructions appropriately. + +In order to manually configure the support for the above mentioned external +libraries (OpenSSL, zlib, libtiff, libpng, libxml2 and libiconv) through CMake, +perform the following steps: + +1. Go Start -> Programs -> CMake -> "CMake" or "CMake (cmake-gui)" to start the + CMake utility through which the configuration can be done. +2. In the entry field "Where is the source code:" enter the directory in which + the DCMTK source code resides, e.g. "C:\dcmtk-3.6.0". +3. In the entry field "Where to build the binaries:" enter the directory in + which the libraries and binaries are to be built, e.g. "C:\dcmtk-bin". +4. In the combobox "Build for:" or "Specify the generator for this project:" + select the corresponding development environment which shall be used to + compile DCMTK. +5. Go "Configure". (CMake will look for a corresponding compiler, read in all + of DCMTK's "CMakeLists.txt" files and perform some tests. The variables in + the tabular area will be displayed in red. These variables can now be set + in order to turn the support for any of the external libraries on or off.) +6. Make the corresponding configurations in CMake's user interface. For + example, in order to turn on libxml2 support, set the value of variable + "DCMTK_WITH_XML" to "ON" and set the value of variable "WITH_LIBXMLINC" + to the path where the include files and libraries of libxml2 can be found, + e.g. "C:\libxml2-2.7.7". The support of all other external libraries can + be turned on in a similar way: + + libpng support: + set "DCMTK_WITH_PNG" to "ON" and + set "WITH_LIBPNGINC" e.g. to "C:\libpng-1.4.2" + + libtiff support: + set "DCMTK_WITH_TIFF" to "ON" and + set "WITH_LIBTIFFINC" e.g. to "C:\tiff-3.9.2" + + OpenSSL support: + set "DCMTK_WITH_OPENSSL" to "ON" and + set "WITH_OPENSSLINC" e.g. to "C:\openssl-1.0.0" + + zlib support: + set "DCMTK_WITH_ZLIB" to "ON" and + set "WITH_ZLIBINC" e.g. to "C:\zlib-1.2.5" + + libiconv support: + set "DCMTK_WITH_ICONV" to "ON" and + set "WITH_LIBICONVINC" e.g. to "C:\libiconv-1.14" + + In order to turn the support of a certain external library off, set the + value of the corresponding variable ("DCMTK_WITH_XML", "DCMTK_WITH_PNG", + "DCMTK_WITH_TIFF", "DCMTK_WITH_OPENSSL", "DCMTK_WITH_ZLIB" or + "DCMTK_WITH_ICONV") to "OFF". + + (Please note that the include files of all external libraries are always + expected in a directory named "include" below the directory which is + specified in "WITH_LIBXMLINC", "WITH_LIBPNGINC", "WITH_LIBTIFFINC", + "WITH_OPENSSLINC", "WITH_ZLIBINC" or "WITH_LIBICONVINC".) + + (Please note also that the library files of all external libraries are + always expected in directory named "lib" below the directory which is + specified in "WITH_LIBXMLINC", "WITH_LIBPNGINC", "WITH_LIBTIFFINC", + "WITH_OPENSSLINC", "WITH_ZLIBINC" or "WITH_LIBICONV". Moreover, note that + the following filenames must be used for the corresponding lib files: + + libxml2: + "iconv_d.lib" - debug version + "iconv_o.lib" - release version (optimized) + "libxml2_d.lib" - debug version + "libxml2_o.lib" - release version (optimized) + + libpng: + "libpng_d.lib" - debug version + "libpng_o.lib" - release version (optimized) + + libtiff: + "libtiff_d.lib" - debug version + "libtiff_o.lib" - release version (optimized) + + openssl: + "libeay32_d.lib" - debug version + "libeay32_o.lib" - release version (optimized) + "ssleay32_d.lib" - debug version + "ssleay32_o.lib" - release version (optimized) + + zlib: + "zlib_d.lib" - debug version + "zlib_o.lib" - release version (optimized) + + libiconv: + "libiconv_d.lib" - debug version + "libiconv_o.lib" - release version (optimized) + "libchset_d.lib" - debug version + "libchset_o.lib" - release version (optimized) + + The debug versions of all libraries must be compiled for the multithread + debug version of the runtime (/MTd), the release version must be compiled + for the non-debug multithread runtime (/MT). Precompiled versions of all + libraries can be downloaded from http://dicom.offis.de/dcmtk#lib-win.) +7. Go "Configure" a second time. (CMake will adjust the configuration + according to the displayed specifications.) +8. Go "OK" or "Generate". (CMake will generate new project files in the + corresponding directories. These files will be adjusted according to the + displayed specifications, i.e. support for the external libraries will be + turned on or off.) + +Having performed these steps, the Microsoft Visual Studio IDE can be started, +DCMTK's workspace file can be opened, and one or more of DCMTK's subprojects +can be built. In case you want to build all libraries and applications, mark +the "ALL_BUILD" subproject and build it. The "INSTALL" subproject installs +the executables, libraries, include, support and documentation files to the +directory specified by the variable "CMAKE_INSTALL_PREFIX" (very similar to +"make install-all" on Unix systems). + +Compilation and installation of the various command line applications +(including the test programs) can be disabled by setting the "BUILD_APPS" +option to "OFF" before configuring and generating the project files. By +default, all command line applications are built and installed. + +Please note that other Windows compilers, e.g. Borland C++ Builder, are +currently not actively supported. However, they may work. + +Known limitations of DCMTK on the Windows platform. + +1. The dcmqrscp tool cannot spark multiple processes. Every association must + be handled completely before a new association is possible. +2. On Windows 95, dcmqrscp always uses exclusive file locking (the LockFileEx + API call is available on Windows NT only). This is no problem if only a + single process exists. +3. Most applications will only work if the computer has configured TCP/IP, a + network name and a TCP/IP address. If SLIP or PPP is used the applications + can only work if a connection to a provider exists (since the IP addresses + and hostnames are given dynamically). +4. Visual C++ contains two different implementations of I/O streams which + should never be mixed within one application because this may cause + application errors that are hard to find. The old, now deprecated + implementation uses the traditional cfront header files etc. + The new implementation uses etc. as defined in ANSI/ISO C++. + DCMTK can be configured to use either of the two interfaces. This behavior + can be changed in "config/include/dcmtk/config/osconfig.h" in the build + directory where the symbol USE_STD_CXX_INCLUDES is declared. + + NOTE: Previous releases of DCMTK (3.5.1 and older) used the old interface + when compiled with Visual C++ 6.0. When updating software that uses + DCMTK as a library, make sure that the use of the iostream library is + consistent throughout the complete application! + +5. DCMTK does not compile when UNICODE or _UNICODE is defined because the + VisualStudio compiler then uses the Unicode version instead of the ANSI + version for all Windows API functions (i.e. type wchar_t instead of char + for all character string parameters and return values). + + +Unix with CMake +--------------- + +Starting with DCMTK 3.6.0, CMake can also be used for non-Windows systems. + +NOTE: This is not (yet) the recommended way since this mechanism is not as + mature and stable as the above described approach using GNU autoconf. + Please feel free to test it and report any issue. Due to this, it is only + sparsely documented. See the previous section on building the DCMTK with + CMake on Windows platforms, but note that details may differ. + + +CMake and shared libraries +-------------------------- + +The CMake build system allows building shared libraries instead of static +libraries. On Windows systems, these are dynamic link libraries (.dll). +On Unix systems, these are shared objects (.so). To enable this, set the +"BUILD_SHARED_LIB" option to "ON". + +Additionally, it is possible to produce a single shared library for the whole +toolkit. This mode is controlled by the "BUILD_SINGLE_SHARED_LIBRARY" option. +If you don't want the whole toolkit in a single shared library, the +"DCMTK_MODULES" cache variable can be modified to select a subset of the +available modules. Please note that this option is marked as advanced and thus +is hidden by default. Also, when building a single shared library, applications +and tests cannot be built. + +Please note that support for shared libraries is still pretty new in DCMTK and +thus not that mature. + + +Default value for CMAKE_BUILD_TYPE +---------------------------------- + +CMAKE_BUILD_TYPE is set to value "Release" if none is specified by the +selected build file generator. For those generators that support multiple +configuration types (e.g. Debug, Release), CMAKE_CONFIGURATION_TYPES holds +possible values. For other generators this value is empty, and for those +generators the build type is controlled at CMake time by CMAKE_BUILD_TYPE. + +To disable the CMAKE_BUILD_TYPE default value, set CMAKE_BUILD_TYPE to value +"None" during CMake configuration, e.g. use "-DCMAKE_BUILD_TYPE:STRING=None" +on the command line. This may be useful if the compiler flags should be +controlled manually (e.g. as defined in environment variables like CXXFLAGS) +and no CMake defaults related to the selected configuration type kick in. + + +DCMTKConfig.cmake AND DCMTKTargets.cmake +---------------------------------------- + +CMake permits to write files that describe the DCMTK build configuration +(DCMTConfig.cmake) as well as all targets (executables and libraries) that have +been produced (DCMTKTargets.cmake). Those files can be utilized by external +projects by using CMake' find_package() mechanism in "CONFIG" mode in order to +adapt their own build configuration, and directly make use of all available +target libraries and executables. + +On systems using CMake versions equal or greater than 2.8.8, these files are +written during installation to the installation directory's subfolder +/cmake on Windows systems, and /lib/cmake/dcmtk on Unix-like systems. +Additionally, these files are already written to the main directory of CMake's +build tree during the build, with all content (e.g. the include paths within +DCMTConfig.cmake) pointing to the correct values for the build tree. Thus even +a DCMTK build tree can be used by external projects that process these two +files. + +On systems using CMake versions lower than 2.8.8, only a simplified +DCMTKConfig.cmake is created, which is only available in the install tree. +DCMTKTargets.cmake is not created at all. + + +HTML DOCUMENTATION AND MAN PAGES +================================ + +Most DCMTK modules have been documented with Doxygen (www.doxygen.org), a free +source code documentation system similar to Javadoc. Unix users who have +Doxygen installed can create a hypertext documentation with "make html" in the +"dcmtk-3.6.0" or "doxygen" directory; Windows and other CMake users should +build the "DOXYGEN" subproject. A project file for Microsoft's HTML Help +Workshop can also be generated allowing to create a single CHM file (compressed +HTML) from the documentation. Other output formats (e.g. LaTeX) can be enabled +by changing the configuration file in the "doxygen" directory. + +At the current time, dcmimage, dcmimgle, dcmjpeg, dcmpstat, dcmrt, dcmsign, +dcmsr, dcmtls, dcmwlm and ofstd are completely documented, dcmdata, dcmjpls, +dcmnet and oflog are almost completely documented. See FAQ entry: "Where is +rest of the documentation?" + +On Unix platforms, man pages for all command line tools are installed during +the "make install" step. In order to use them, just add the directory (e.g. +"/usr/local/share/man") to the MANPATH environment variable and try +"man dcmdump" to check whether it works. + +In order to generate plain text files from the man pages call "make text" in +the "doxygen" directory. The output files are stored in "doxygen/man2text". + + +COMPILE-TIME FLAGS AND ENVIRONMENT VARIABLES +============================================ + +The behavior of several DCMTK tools and libraries can be modified by a number +of compile-time flags (macros). Those macros which are not automatically +handled by the configure mechanism are documented in "config/docs/macros.txt" +(or "/usr/local/share/doc/dcmtk/macros.txt"). + +There is also a number of environment variables which affect DCMTK's behavior. +These are documented in "config/docs/envvars.txt" (or "/usr/local/share/doc/ +dcmtk/envvars.txt"). + + +RUNNING THE TEST SUITE +====================== + +DCMTK comes with a test suite that verifies that the toolkit works as expected. +The tests are contained in a module's "tests" subdirectory. + +When using configure for building DCMTK, all tests can be run via "make check". +If a test fails, make will stop and the failure reason of the test which failed +should be visible. + +You can also run the test suite with CMake. However, the steps needed for +running the test suite depend on the generator used. The Visual Studio +generators will create a "RUN_TESTS" subproject. Building this project will +call CTest and run all tests. When using the Makefile generator, "make test" +runs the test suite. Other generators should use a similar approach. + +For closer inspection, individual tests can be run directly. The Makefiles +will build the test runner for each module as "/tests/tests". CMake +will add the module name as a prefix to this file's name, e.g. "ofstd_tests". +For more information, call this program with the --help option. + + +--------- + +Have fun. + +M. Eichelberg, J. Riesmeier, M. Onken, U. Schlachter, J. Schlamelcher +DCMTK Development Team, Oldenburg, Germany. + +Last revised: 2015-09-18 (Riesmeier) diff --git a/Makefile b/Makefile new file mode 100644 index 00000000..2f191808 --- /dev/null +++ b/Makefile @@ -0,0 +1,903 @@ +# +# Makefile for dcmtk (DICOM Toolkit) +# + +SHELL = /bin/sh +configdir = config + +include $(configdir)/Makefile.def + +.NOTPARALLEL: + +all: config-all ofstd-all oflog-all dcmdata-all dcmiod-all dcmfg-all dcmseg-all dcmimgle-all dcmimage-all dcmjpeg-all dcmjpls-all dcmtls-all dcmnet-all dcmsr-all dcmsign-all dcmwlm-all dcmqrdb-all dcmpstat-all dcmrt-all + +libsrc-all: ofstd-libsrc-all oflog-libsrc-all dcmdata-libsrc-all dcmiod-libsrc-all dcmfg-libsrc-all dcmseg-libsrc-all dcmimgle-libsrc-all dcmimage-libsrc-all dcmjpeg-libsrc-all dcmjpls-libsrc-all dcmtls-libsrc-all dcmnet-libsrc-all dcmsr-libsrc-all dcmsign-libsrc-all dcmwlm-libsrc-all dcmqrdb-libsrc-all dcmpstat-libsrc-all dcmrt-libsrc-all + +tests-all: config-tests-all ofstd-tests-all oflog-tests-all dcmdata-tests-all dcmiod-tests-all dcmfg-tests-all dcmseg-tests-all dcmimgle-tests-all dcmimage-tests-all dcmjpeg-tests-all dcmjpls-tests-all dcmtls-tests-all dcmnet-tests-all dcmsr-tests-all dcmsign-tests-all dcmwlm-tests-all dcmqrdb-tests-all dcmpstat-tests-all dcmrt-tests-all + +install: config-install ofstd-install oflog-install dcmdata-install dcmiod-install dcmfg-install dcmseg-install dcmimgle-install dcmimage-install dcmjpeg-install dcmjpls-install dcmtls-install dcmnet-install dcmsr-install dcmsign-install dcmwlm-install dcmqrdb-install dcmpstat-install dcmrt-install dcmtk-install-doc install-man + +install-all: install install-lib install-html + +install-bin: config-install-bin ofstd-install-bin oflog-install-bin dcmdata-install-bin dcmiod-install-bin dcmfg-install-bin dcmseg-install-bin dcmimgle-install-bin dcmimage-install-bin dcmjpeg-install-bin dcmjpls-install-bin dcmtls-install-bin dcmnet-install-bin dcmsr-install-bin dcmsign-install-bin dcmwlm-install-bin dcmqrdb-install-bin dcmpstat-install-bin dcmrt-install-bin + +install-doc: config-install-doc ofstd-install-doc oflog-install-doc dcmdata-install-doc dcmiod-install-doc dcmfg-install-doc dcmseg-install-doc dcmimgle-install-doc dcmimage-install-doc dcmjpeg-install-doc dcmjpls-install-doc dcmtls-install-doc dcmnet-install-doc dcmsr-install-doc dcmsign-install-doc dcmwlm-install-doc dcmqrdb-install-doc dcmpstat-install-doc dcmrt-install-doc + +install-data: config-install-data ofstd-install-data oflog-install-data dcmdata-install-data dcmiod-install-data dcmfg-install-data dcmseg-install-data dcmimgle-install-data dcmimage-install-data dcmjpeg-install-data dcmjpls-install-data dcmtls-install-data dcmnet-install-data dcmsr-install-data dcmsign-install-data dcmwlm-install-data dcmqrdb-install-data dcmpstat-install-data dcmrt-install-data + +install-etc: config-install-etc ofstd-install-etc oflog-install-etc dcmdata-install-etc dcmiod-install-etc dcmfg-install-etc dcmseg-install-etc dcmimgle-install-etc dcmimage-install-etc dcmjpeg-install-etc dcmjpls-install-etc dcmtls-install-etc dcmnet-install-etc dcmsr-install-etc dcmsign-install-etc dcmwlm-install-etc dcmqrdb-install-etc dcmpstat-install-etc dcmrt-install-etc + +install-lib: config-install-lib ofstd-install-lib oflog-install-lib dcmdata-install-lib dcmiod-install-lib dcmfg-install-lib dcmseg-install-lib dcmimgle-install-lib dcmimage-install-lib dcmjpeg-install-lib dcmjpls-install-lib dcmtls-install-lib dcmnet-install-lib dcmsr-install-lib dcmsign-install-lib dcmwlm-install-lib dcmqrdb-install-lib dcmpstat-install-lib dcmrt-install-lib + +install-include: config-install-include ofstd-install-include oflog-install-include dcmdata-install-include dcmiod-install-include dcmfg-install-include dcmseg-install-include dcmimgle-install-include dcmimage-install-include dcmjpeg-install-include dcmjpls-install-include dcmtls-install-include dcmnet-install-include dcmsr-install-include dcmsign-install-include dcmwlm-install-include dcmqrdb-install-include dcmpstat-install-include dcmrt-install-include + +install-support: config-install-support ofstd-install-support oflog-install-support dcmdata-install-support dcmiod-install-support dcmfg-install-support dcmseg-install-support dcmimgle-install-support dcmimage-install-support dcmjpeg-install-support dcmjpls-install-support dcmtls-install-support dcmnet-install-support dcmsr-install-support dcmsign-install-support dcmwlm-install-support dcmqrdb-install-support dcmpstat-install-support dcmrt-install-support + +check: tests-all + $(MAKE) -s check-nosilent + +check-nosilent: config-check ofstd-check oflog-check dcmdata-check dcmiod-check dcmfg-check dcmseg-check dcmimgle-check dcmimage-check dcmjpeg-check dcmjpls-check dcmtls-check dcmnet-check dcmsr-check dcmsign-check dcmwlm-check dcmqrdb-check dcmpstat-check dcmrt-check + +check-exhaustive: tests-all + $(MAKE) -s check-nosilent-exhaustive + +check-nosilent-exhaustive: config-check-exhaustive ofstd-check-exhaustive oflog-check-exhaustive dcmdata-check-exhaustive dcmiod-check-exhaustive dcmfg-check-exhaustive dcmseg-check-exhaustive dcmimgle-check-exhaustive dcmimage-check-exhaustive dcmjpeg-check-exhaustive dcmjpls-check-exhaustive dcmtls-check-exhaustive dcmnet-check-exhaustive dcmsr-check-exhaustive dcmsign-check-exhaustive dcmwlm-check-exhaustive dcmqrdb-check-exhaustive dcmpstat-check-exhaustive dcmrt-check-exhaustive + +dcmtk-install-doc: + $(configdir)/mkinstalldirs $(DESTDIR)$(docdir) + for file in ANNOUNCE CHANGES COPYRIGHT CREDITS FAQ HISTORY VERSION; do \ + $(INSTALL_DATA) $$file $(DESTDIR)$(docdir) ;\ + done + +install-man: + (cd doxygen && $(MAKE) DESTDIR="$(DESTDIR)" install-man) + +install-html: + (cd doxygen && $(MAKE) DESTDIR="$(DESTDIR)" install-html) + +man: + (cd doxygen && $(MAKE) DESTDIR="$(DESTDIR)" man) + +html: + (cd doxygen && $(MAKE) DESTDIR="$(DESTDIR)" html) + +help: + @echo "Some available make targets:" + @echo "" + @echo "all: build all libraries, tests and applications" + @echo "libsrc-all: build all libraries" + @echo "install-all: install the toolkit with its libraries and documentation" + @echo "install: install all applications" + @echo "install-lib: install the libraries" + @echo "install-html: install the HTML documentation" + @echo "html: build the HTML documentation with doxygen" + @echo "man: build the man pages with doxygen" + @echo "check: build and run all tests, not including exhaustive tests" + @echo "check-exhaustive: build and run all tests, including exhaustive tests" + @echo "dependencies: update all Makefile.dep dependency files" + @echo "clean: remove compiler output" + @echo "distclean: remove compiler output and generated build structure" + @echo " (This removes all files generated by configure)" + @echo "" + @echo "Additionally, there are a number of module-specific targets available." + @echo "For example:" + @echo "" + @echo "-all build the complete module" + @echo "-libsrc-all build the module's libraries" + @echo "-install install the module" + @echo "-install-lib install the module's libraries" + @echo "-check build and run the module's tests, not including exhaustive tests" + @echo "-check-exhaustive build and run the module's tests, including exhaustive tests" + @echo "" + @echo "The following modules are available:" + @echo "" + @echo "ofstd oflog dcmdata dcmiod dcmfg dcmseg dcmimgle dcmimage dcmjpeg dcmjpls dcmtls dcmnet dcmsr dcmsign dcmwlm dcmqrdb dcmpstat dcmrt" + +config-all: + (cd config && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" all) + +config-libsrc-all: + (cd config && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" libsrc-all) + +config-tests-all: + (cd config && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" tests-all) + +config-install: + (cd config && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install) + +config-install-bin: + (cd config && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-bin) + +config-install-doc: + (cd config && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-doc) + +config-install-data: + (cd config && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-data) + +config-install-etc: + (cd config && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-etc) + +config-install-lib: + (cd config && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-lib) + +config-install-include: + (cd config && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-include) + +config-install-support: + (cd config && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-support) + +config-check: + (cd config && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" check) + +config-check-exhaustive: + (cd config && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" check-exhaustive) + +ofstd-all: + (cd ofstd && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" all) + +ofstd-libsrc-all: + (cd ofstd && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" libsrc-all) + +ofstd-tests-all: + (cd ofstd && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" tests-all) + +ofstd-install: + (cd ofstd && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install) + +ofstd-install-bin: + (cd ofstd && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-bin) + +ofstd-install-doc: + (cd ofstd && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-doc) + +ofstd-install-data: + (cd ofstd && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-data) + +ofstd-install-etc: + (cd ofstd && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-etc) + +ofstd-install-lib: + (cd ofstd && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-lib) + +ofstd-install-include: + (cd ofstd && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-include) + +ofstd-install-support: + (cd ofstd && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-support) + +ofstd-check: + (cd ofstd && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" check) + +ofstd-check-exhaustive: + (cd ofstd && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" check-exhaustive) + +oflog-all: + (cd oflog && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" all) + +oflog-libsrc-all: + (cd oflog && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" libsrc-all) + +oflog-tests-all: + (cd oflog && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" tests-all) + +oflog-install: + (cd oflog && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install) + +oflog-install-bin: + (cd oflog && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-bin) + +oflog-install-doc: + (cd oflog && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-doc) + +oflog-install-data: + (cd oflog && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-data) + +oflog-install-etc: + (cd oflog && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-etc) + +oflog-install-lib: + (cd oflog && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-lib) + +oflog-install-include: + (cd oflog && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-include) + +oflog-install-support: + (cd oflog && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-support) + +oflog-check: + (cd oflog && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" check) + +oflog-check-exhaustive: + (cd oflog && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" check-exhaustive) + +dcmdata-all: + (cd dcmdata && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" all) + +dcmdata-libsrc-all: + (cd dcmdata && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" libsrc-all) + +dcmdata-tests-all: + (cd dcmdata && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" tests-all) + +dcmdata-install: + (cd dcmdata && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install) + +dcmdata-install-bin: + (cd dcmdata && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-bin) + +dcmdata-install-doc: + (cd dcmdata && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-doc) + +dcmdata-install-data: + (cd dcmdata && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-data) + +dcmdata-install-etc: + (cd dcmdata && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-etc) + +dcmdata-install-lib: + (cd dcmdata && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-lib) + +dcmdata-install-include: + (cd dcmdata && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-include) + +dcmdata-install-support: + (cd dcmdata && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-support) + +dcmdata-check: + (cd dcmdata && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" check) + +dcmdata-check-exhaustive: + (cd dcmdata && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" check-exhaustive) + +dcmiod-all: + (cd dcmiod && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" all) + +dcmiod-libsrc-all: + (cd dcmiod && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" libsrc-all) + +dcmiod-tests-all: + (cd dcmiod && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" tests-all) + +dcmiod-install: + (cd dcmiod && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install) + +dcmiod-install-bin: + (cd dcmiod && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-bin) + +dcmiod-install-doc: + (cd dcmiod && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-doc) + +dcmiod-install-data: + (cd dcmiod && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-data) + +dcmiod-install-etc: + (cd dcmiod && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-etc) + +dcmiod-install-lib: + (cd dcmiod && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-lib) + +dcmiod-install-include: + (cd dcmiod && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-include) + +dcmiod-install-support: + (cd dcmiod && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-support) + +dcmiod-check: + (cd dcmiod && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" check) + +dcmiod-check-exhaustive: + (cd dcmiod && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" check-exhaustive) + +dcmfg-all: + (cd dcmfg && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" all) + +dcmfg-libsrc-all: + (cd dcmfg && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" libsrc-all) + +dcmfg-tests-all: + (cd dcmfg && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" tests-all) + +dcmfg-install: + (cd dcmfg && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install) + +dcmfg-install-bin: + (cd dcmfg && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-bin) + +dcmfg-install-doc: + (cd dcmfg && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-doc) + +dcmfg-install-data: + (cd dcmfg && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-data) + +dcmfg-install-etc: + (cd dcmfg && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-etc) + +dcmfg-install-lib: + (cd dcmfg && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-lib) + +dcmfg-install-include: + (cd dcmfg && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-include) + +dcmfg-install-support: + (cd dcmfg && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-support) + +dcmfg-check: + (cd dcmfg && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" check) + +dcmfg-check-exhaustive: + (cd dcmfg && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" check-exhaustive) + +dcmseg-all: + (cd dcmseg && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" all) + +dcmseg-libsrc-all: + (cd dcmseg && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" libsrc-all) + +dcmseg-tests-all: + (cd dcmseg && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" tests-all) + +dcmseg-install: + (cd dcmseg && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install) + +dcmseg-install-bin: + (cd dcmseg && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-bin) + +dcmseg-install-doc: + (cd dcmseg && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-doc) + +dcmseg-install-data: + (cd dcmseg && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-data) + +dcmseg-install-etc: + (cd dcmseg && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-etc) + +dcmseg-install-lib: + (cd dcmseg && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-lib) + +dcmseg-install-include: + (cd dcmseg && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-include) + +dcmseg-install-support: + (cd dcmseg && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-support) + +dcmseg-check: + (cd dcmseg && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" check) + +dcmseg-check-exhaustive: + (cd dcmseg && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" check-exhaustive) + +dcmimgle-all: + (cd dcmimgle && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" all) + +dcmimgle-libsrc-all: + (cd dcmimgle && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" libsrc-all) + +dcmimgle-tests-all: + (cd dcmimgle && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" tests-all) + +dcmimgle-install: + (cd dcmimgle && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install) + +dcmimgle-install-bin: + (cd dcmimgle && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-bin) + +dcmimgle-install-doc: + (cd dcmimgle && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-doc) + +dcmimgle-install-data: + (cd dcmimgle && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-data) + +dcmimgle-install-etc: + (cd dcmimgle && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-etc) + +dcmimgle-install-lib: + (cd dcmimgle && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-lib) + +dcmimgle-install-include: + (cd dcmimgle && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-include) + +dcmimgle-install-support: + (cd dcmimgle && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-support) + +dcmimgle-check: + (cd dcmimgle && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" check) + +dcmimgle-check-exhaustive: + (cd dcmimgle && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" check-exhaustive) + +dcmimage-all: + (cd dcmimage && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" all) + +dcmimage-libsrc-all: + (cd dcmimage && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" libsrc-all) + +dcmimage-tests-all: + (cd dcmimage && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" tests-all) + +dcmimage-install: + (cd dcmimage && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install) + +dcmimage-install-bin: + (cd dcmimage && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-bin) + +dcmimage-install-doc: + (cd dcmimage && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-doc) + +dcmimage-install-data: + (cd dcmimage && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-data) + +dcmimage-install-etc: + (cd dcmimage && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-etc) + +dcmimage-install-lib: + (cd dcmimage && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-lib) + +dcmimage-install-include: + (cd dcmimage && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-include) + +dcmimage-install-support: + (cd dcmimage && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-support) + +dcmimage-check: + (cd dcmimage && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" check) + +dcmimage-check-exhaustive: + (cd dcmimage && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" check-exhaustive) + +dcmjpeg-all: + (cd dcmjpeg && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" all) + +dcmjpeg-libsrc-all: + (cd dcmjpeg && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" libsrc-all) + +dcmjpeg-tests-all: + (cd dcmjpeg && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" tests-all) + +dcmjpeg-install: + (cd dcmjpeg && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install) + +dcmjpeg-install-bin: + (cd dcmjpeg && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-bin) + +dcmjpeg-install-doc: + (cd dcmjpeg && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-doc) + +dcmjpeg-install-data: + (cd dcmjpeg && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-data) + +dcmjpeg-install-etc: + (cd dcmjpeg && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-etc) + +dcmjpeg-install-lib: + (cd dcmjpeg && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-lib) + +dcmjpeg-install-include: + (cd dcmjpeg && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-include) + +dcmjpeg-install-support: + (cd dcmjpeg && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-support) + +dcmjpeg-check: + (cd dcmjpeg && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" check) + +dcmjpeg-check-exhaustive: + (cd dcmjpeg && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" check-exhaustive) + +dcmjpls-all: + (cd dcmjpls && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" all) + +dcmjpls-libsrc-all: + (cd dcmjpls && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" libsrc-all) + +dcmjpls-tests-all: + (cd dcmjpls && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" tests-all) + +dcmjpls-install: + (cd dcmjpls && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install) + +dcmjpls-install-bin: + (cd dcmjpls && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-bin) + +dcmjpls-install-doc: + (cd dcmjpls && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-doc) + +dcmjpls-install-data: + (cd dcmjpls && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-data) + +dcmjpls-install-etc: + (cd dcmjpls && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-etc) + +dcmjpls-install-lib: + (cd dcmjpls && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-lib) + +dcmjpls-install-include: + (cd dcmjpls && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-include) + +dcmjpls-install-support: + (cd dcmjpls && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-support) + +dcmjpls-check: + (cd dcmjpls && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" check) + +dcmjpls-check-exhaustive: + (cd dcmjpls && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" check-exhaustive) + +dcmtls-all: + (cd dcmtls && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" all) + +dcmtls-libsrc-all: + (cd dcmtls && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" libsrc-all) + +dcmtls-tests-all: + (cd dcmtls && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" tests-all) + +dcmtls-install: + (cd dcmtls && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install) + +dcmtls-install-bin: + (cd dcmtls && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-bin) + +dcmtls-install-doc: + (cd dcmtls && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-doc) + +dcmtls-install-data: + (cd dcmtls && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-data) + +dcmtls-install-etc: + (cd dcmtls && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-etc) + +dcmtls-install-lib: + (cd dcmtls && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-lib) + +dcmtls-install-include: + (cd dcmtls && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-include) + +dcmtls-install-support: + (cd dcmtls && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-support) + +dcmtls-check: + (cd dcmtls && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" check) + +dcmtls-check-exhaustive: + (cd dcmtls && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" check-exhaustive) + +dcmnet-all: + (cd dcmnet && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" all) + +dcmnet-libsrc-all: + (cd dcmnet && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" libsrc-all) + +dcmnet-tests-all: + (cd dcmnet && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" tests-all) + +dcmnet-install: + (cd dcmnet && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install) + +dcmnet-install-bin: + (cd dcmnet && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-bin) + +dcmnet-install-doc: + (cd dcmnet && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-doc) + +dcmnet-install-data: + (cd dcmnet && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-data) + +dcmnet-install-etc: + (cd dcmnet && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-etc) + +dcmnet-install-lib: + (cd dcmnet && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-lib) + +dcmnet-install-include: + (cd dcmnet && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-include) + +dcmnet-install-support: + (cd dcmnet && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-support) + +dcmnet-check: + (cd dcmnet && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" check) + +dcmnet-check-exhaustive: + (cd dcmnet && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" check-exhaustive) + +dcmsr-all: + (cd dcmsr && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" all) + +dcmsr-libsrc-all: + (cd dcmsr && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" libsrc-all) + +dcmsr-tests-all: + (cd dcmsr && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" tests-all) + +dcmsr-install: + (cd dcmsr && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install) + +dcmsr-install-bin: + (cd dcmsr && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-bin) + +dcmsr-install-doc: + (cd dcmsr && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-doc) + +dcmsr-install-data: + (cd dcmsr && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-data) + +dcmsr-install-etc: + (cd dcmsr && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-etc) + +dcmsr-install-lib: + (cd dcmsr && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-lib) + +dcmsr-install-include: + (cd dcmsr && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-include) + +dcmsr-install-support: + (cd dcmsr && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-support) + +dcmsr-check: + (cd dcmsr && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" check) + +dcmsr-check-exhaustive: + (cd dcmsr && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" check-exhaustive) + +dcmsign-all: + (cd dcmsign && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" all) + +dcmsign-libsrc-all: + (cd dcmsign && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" libsrc-all) + +dcmsign-tests-all: + (cd dcmsign && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" tests-all) + +dcmsign-install: + (cd dcmsign && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install) + +dcmsign-install-bin: + (cd dcmsign && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-bin) + +dcmsign-install-doc: + (cd dcmsign && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-doc) + +dcmsign-install-data: + (cd dcmsign && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-data) + +dcmsign-install-etc: + (cd dcmsign && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-etc) + +dcmsign-install-lib: + (cd dcmsign && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-lib) + +dcmsign-install-include: + (cd dcmsign && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-include) + +dcmsign-install-support: + (cd dcmsign && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-support) + +dcmsign-check: + (cd dcmsign && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" check) + +dcmsign-check-exhaustive: + (cd dcmsign && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" check-exhaustive) + +dcmwlm-all: + (cd dcmwlm && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" all) + +dcmwlm-libsrc-all: + (cd dcmwlm && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" libsrc-all) + +dcmwlm-tests-all: + (cd dcmwlm && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" tests-all) + +dcmwlm-install: + (cd dcmwlm && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install) + +dcmwlm-install-bin: + (cd dcmwlm && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-bin) + +dcmwlm-install-doc: + (cd dcmwlm && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-doc) + +dcmwlm-install-data: + (cd dcmwlm && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-data) + +dcmwlm-install-etc: + (cd dcmwlm && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-etc) + +dcmwlm-install-lib: + (cd dcmwlm && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-lib) + +dcmwlm-install-include: + (cd dcmwlm && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-include) + +dcmwlm-install-support: + (cd dcmwlm && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-support) + +dcmwlm-check: + (cd dcmwlm && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" check) + +dcmwlm-check-exhaustive: + (cd dcmwlm && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" check-exhaustive) + +dcmqrdb-all: + (cd dcmqrdb && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" all) + +dcmqrdb-libsrc-all: + (cd dcmqrdb && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" libsrc-all) + +dcmqrdb-tests-all: + (cd dcmqrdb && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" tests-all) + +dcmqrdb-install: + (cd dcmqrdb && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install) + +dcmqrdb-install-bin: + (cd dcmqrdb && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-bin) + +dcmqrdb-install-doc: + (cd dcmqrdb && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-doc) + +dcmqrdb-install-data: + (cd dcmqrdb && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-data) + +dcmqrdb-install-etc: + (cd dcmqrdb && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-etc) + +dcmqrdb-install-lib: + (cd dcmqrdb && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-lib) + +dcmqrdb-install-include: + (cd dcmqrdb && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-include) + +dcmqrdb-install-support: + (cd dcmqrdb && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-support) + +dcmqrdb-check: + (cd dcmqrdb && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" check) + +dcmqrdb-check-exhaustive: + (cd dcmqrdb && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" check-exhaustive) + +dcmpstat-all: + (cd dcmpstat && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" all) + +dcmpstat-libsrc-all: + (cd dcmpstat && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" libsrc-all) + +dcmpstat-tests-all: + (cd dcmpstat && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" tests-all) + +dcmpstat-install: + (cd dcmpstat && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install) + +dcmpstat-install-bin: + (cd dcmpstat && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-bin) + +dcmpstat-install-doc: + (cd dcmpstat && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-doc) + +dcmpstat-install-data: + (cd dcmpstat && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-data) + +dcmpstat-install-etc: + (cd dcmpstat && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-etc) + +dcmpstat-install-lib: + (cd dcmpstat && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-lib) + +dcmpstat-install-include: + (cd dcmpstat && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-include) + +dcmpstat-install-support: + (cd dcmpstat && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-support) + +dcmpstat-check: + (cd dcmpstat && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" check) + +dcmpstat-check-exhaustive: + (cd dcmpstat && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" check-exhaustive) + +dcmrt-all: + (cd dcmrt && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" all) + +dcmrt-libsrc-all: + (cd dcmrt && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" libsrc-all) + +dcmrt-tests-all: + (cd dcmrt && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" tests-all) + +dcmrt-install: + (cd dcmrt && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install) + +dcmrt-install-bin: + (cd dcmrt && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-bin) + +dcmrt-install-doc: + (cd dcmrt && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-doc) + +dcmrt-install-data: + (cd dcmrt && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-data) + +dcmrt-install-etc: + (cd dcmrt && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-etc) + +dcmrt-install-lib: + (cd dcmrt && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-lib) + +dcmrt-install-include: + (cd dcmrt && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-include) + +dcmrt-install-support: + (cd dcmrt && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-support) + +dcmrt-check: + (cd dcmrt && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" check) + +dcmrt-check-exhaustive: + (cd dcmrt && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" check-exhaustive) + +dependencies: + -(cd config && $(MAKE) dependencies) + (cd ofstd && $(MAKE) dependencies) + (cd oflog && $(MAKE) dependencies) + (cd dcmdata && $(MAKE) dependencies) + (cd dcmiod && $(MAKE) dependencies) + (cd dcmfg && $(MAKE) dependencies) + (cd dcmseg && $(MAKE) dependencies) + (cd dcmimgle && $(MAKE) dependencies) + (cd dcmimage && $(MAKE) dependencies) + (cd dcmjpeg && $(MAKE) dependencies) + (cd dcmjpls && $(MAKE) dependencies) + (cd dcmtls && $(MAKE) dependencies) + (cd dcmnet && $(MAKE) dependencies) + (cd dcmsr && $(MAKE) dependencies) + (cd dcmsign && $(MAKE) dependencies) + (cd dcmwlm && $(MAKE) dependencies) + (cd dcmqrdb && $(MAKE) dependencies) + (cd dcmpstat && $(MAKE) dependencies) + (cd dcmrt && $(MAKE) dependencies) + +clean: + (cd ofstd && $(MAKE) clean) + (cd oflog && $(MAKE) clean) + (cd dcmdata && $(MAKE) clean) + (cd dcmiod && $(MAKE) clean) + (cd dcmfg && $(MAKE) clean) + (cd dcmseg && $(MAKE) clean) + (cd dcmimgle && $(MAKE) clean) + (cd dcmimage && $(MAKE) clean) + (cd dcmjpeg && $(MAKE) clean) + (cd dcmjpls && $(MAKE) clean) + (cd dcmtls && $(MAKE) clean) + (cd dcmnet && $(MAKE) clean) + (cd dcmsr && $(MAKE) clean) + (cd dcmsign && $(MAKE) clean) + (cd dcmwlm && $(MAKE) clean) + (cd dcmqrdb && $(MAKE) clean) + (cd dcmpstat && $(MAKE) clean) + (cd dcmrt && $(MAKE) clean) + (cd doxygen && $(MAKE) clean) + -(cd config && $(MAKE) clean) + rm -f $(TRASH) + +distclean: + (cd ofstd && $(MAKE) distclean) + (cd oflog && $(MAKE) distclean) + (cd dcmdata && $(MAKE) distclean) + (cd dcmiod && $(MAKE) distclean) + (cd dcmfg && $(MAKE) distclean) + (cd dcmseg && $(MAKE) distclean) + (cd dcmimgle && $(MAKE) distclean) + (cd dcmimage && $(MAKE) distclean) + (cd dcmjpeg && $(MAKE) distclean) + (cd dcmjpls && $(MAKE) distclean) + (cd dcmtls && $(MAKE) distclean) + (cd dcmnet && $(MAKE) distclean) + (cd dcmsr && $(MAKE) distclean) + (cd dcmsign && $(MAKE) distclean) + (cd dcmwlm && $(MAKE) distclean) + (cd dcmqrdb && $(MAKE) distclean) + (cd dcmpstat && $(MAKE) distclean) + (cd dcmrt && $(MAKE) distclean) + (cd doxygen && $(MAKE) distclean) + -(cd config && $(MAKE) distclean) + rm -f $(TRASH) + diff --git a/README b/README new file mode 100644 index 00000000..d8317ef0 --- /dev/null +++ b/README @@ -0,0 +1,55 @@ + +DCMTK + +This DICOM ToolKit (DCMTK) package consists of source code, documentation +and installation instructions for a set of software libraries and +applications implementing part of the DICOM/MEDICOM Standard. + +DCMTK contains the following sub-packages, each in its own sub-directory: + + config - configuration utilities for DCMTK + dcmdata - a data encoding/decoding library and utility apps + dcmfg - a library for working with functional groups + dcmimage - adds support for color images to dcmimgle + dcmimgle - an image processing library and utility apps + dcmiod - a library for working with information objects and modules + dcmjpeg - a compression/decompression library and utility apps + dcmjpls - a compression/decompression library and utility apps + dcmnet - a networking library and utility apps + dcmpstat - a presentation state library and utility apps + dcmqrdb - an image database server + dcmrt - a radiation therapy library and utility apps + dcmseg - a library for working with segmentation objects + dcmsign - a digital signature library and utility apps + dcmsr - a structured report library and utility apps + dcmtls - security extensions for the network library + dcmwlm - a modality worklist database server + oflog - a logging library based on log4cplus + ofstd - a library of general purpose classes + +Each sub-directory (except config) contains further sub-directories for +application source code (apps), library source code (libsrc), library +include files (include), configuration data (etc), documentation (docs), +sample and support data (data) as well as test programs (tests). + +To build and install the DCMTK package see the INSTALL file. For copyright +information see the COPYRIGHT file. For information about the history of +this software see the HISTORY file. For answers to frequently asked +questions please consult the FAQ: + + http://forum.dcmtk.org/faq/ + +There is also a Wiki system where additional information can be found: + + http://support.dcmtk.org/wiki/ + +If you find bugs or other problems with this software, we would appreciate +hearing about them. Please send electronic mail to: + + bugs/at/dcmtk/dot/org + +Please try to describe the problem in detail and if possible give a +suggested fix. For general questions on how to compile, install or use +the toolkit we recommend the public discussion forum at: + + http://forum.dcmtk.org/ diff --git a/VERSION b/VERSION new file mode 100644 index 00000000..3ed5517e --- /dev/null +++ b/VERSION @@ -0,0 +1 @@ +3.6.1_20150924 diff --git a/config/CMakeLists.txt b/config/CMakeLists.txt new file mode 100644 index 00000000..53579a1b --- /dev/null +++ b/config/CMakeLists.txt @@ -0,0 +1,5 @@ +# declare project +PROJECT(config) + +# recurse into subdirectories +ADD_SUBDIRECTORY(docs) diff --git a/config/Makefile.def.in b/config/Makefile.def.in new file mode 100644 index 00000000..a6ba698a --- /dev/null +++ b/config/Makefile.def.in @@ -0,0 +1,107 @@ +# +# Makefile.def.in for all toolkit code +# The use of the following code requires: +# (a) definition of srcdir +# (b) definition of VPATH without using any Makefile variables (optional) +# (c) definition of LOCALDEFS an LOCALDEBUG (optional) +# + +prefix = @prefix@ +exec_prefix = @exec_prefix@ +datarootdir = @datarootdir@ + +bindir = @bindir@ +etcdir = @sysconfdir@ +datadir = @datadir@ +docdir = @docdir@ +mandir = @mandir@ +man1dir = @mandir@/man1 +htmldir = @htmldir@ +pdfdir = @pdfdir@ +libdir = @libdir@ +includedir = @includedir@ + +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ + +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_DATE = @PACKAGE_DATE@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PACKAGE_VERSION_NUMBER = @PACKAGE_VERSION_NUMBER@ +PACKAGE_VERSION_SUFFIX = @PACKAGE_VERSION_SUFFIX@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ + +# +# Definition of dependencies file +# + +DEP = Makefile.dep + +# Toolkit wide definitions for DEBUGGING +# +# -DDEBUG Compile with debug code and assertions +# -DNDEBUG Compile without debug code and assertions + +DEBUG = @DEBUG@ + +# +# Global definitions +# + +# We want the old behavior of OFString(NULL) for now, no crashes. +GLOBALDEFS = @DEFS@ -DDCMTK_BUILD_DATE=\"2015-09-24\" -DUSE_NULL_SAFE_OFSTRING -DDCMTK_BUILD_IN_PROGRESS + +# +# ARCH defines special machine archtecture compiler settings +# (e.g. -arch i386 on NeXT) +# + +# ARCH = + +CC = @CC@ +CFLAGS = @CFLAGS@ +CXX = @CXX@ +CXXFLAGS = @CXXFLAGS@ +CPPFLAGS = @CPPFLAGS@ +LDFLAGS = @LDFLAGS@ +RANLIB = @RANLIB@ +AR = @AR@ +ARFLAGS = @ARFLAGS@ +LIBS = @LIBS@ +MATHLIBS = @MATHLIBS@ +OPENSSLLIBS = @OPENSSLLIBS@ +TIFFLIBS = @TIFFLIBS@ +PNGLIBS = @PNGLIBS@ +ZLIBLIBS = @ZLIBLIBS@ +XMLLIBS = @XMLLIBS@ +TCPWRAPPERLIBS = @TCPWRAPPERLIBS@ +SNDFILELIBS = @SNDFILELIBS@ +ICONVLIBS = @ICONVLIBS@ +LIBEXT = @LIBEXT@ +BINEXT = @BINEXT@ +STRIP = @STRIP@ +DCMTK_ENABLE_BUILTIN_DICTIONARY= @DCMTK_ENABLE_BUILTIN_DICTIONARY@ + +# +# for clean and distclean +# +TRASH = *~ "\#*\#" *.bak core +DISTTRASH = $(TRASH) Makefile *.cache *.log *.status + +includes = -I. -I$(srcdir) -I$(top_srcdir)/include -I$(configdir)/include $(LOCALINCLUDES) +defines = $(GLOBALDEFS) $(LOCALDEFS) $(DEBUG) $(LOCALDEBUG) + + +.SUFFIXES: +.SUFFIXES: .o .cc .c .h + +.cc.o: + $(CXX) $(defines) -c $(includes) $(ARCH) \ + $(CPPFLAGS) $(CXXFLAGS) $< + +.c.o: + $(CC) $(defines) -c $(includes) $(ARCH) \ + $(CPPFLAGS) $(CFLAGS) $< diff --git a/config/Makefile.in b/config/Makefile.in new file mode 100644 index 00000000..9bd8f39e --- /dev/null +++ b/config/Makefile.in @@ -0,0 +1,68 @@ +# +# Makefile for config +# + +@SET_MAKE@ + +SHELL = /bin/sh + +include @common_makefile@ + + +all: include/dcmtk/config/arith.h + +install: install-doc + +install-bin: + +install-doc: docs-install + +install-data: + +install-etc: + +install-include: include-install + +install-lib: include-install + +install-support: + + +libsrc-all: + +tests-all: all + + +check: tests-all + +check-exhaustive: tests-all + + +include-install: + ./mkinstalldirs $(DESTDIR)$(includedir)/dcmtk/config + $(INSTALL_DATA) include/dcmtk/config/osconfig.h $(DESTDIR)$(includedir)/dcmtk/config + +docs-install: + ./mkinstalldirs $(DESTDIR)$(docdir) + $(INSTALL_DATA) docs/config.txt $(DESTDIR)$(docdir) + $(INSTALL_DATA) docs/envvars.txt $(DESTDIR)$(docdir) + $(INSTALL_DATA) docs/modules.txt $(DESTDIR)$(docdir) + $(INSTALL_DATA) docs/dirstruc.txt $(DESTDIR)$(docdir) + $(INSTALL_DATA) docs/macros.txt $(DESTDIR)$(docdir) + + +clean: + (cd include/dcmtk/config && rm -f $(TRASH)) + rm -rf $(TRASH) + +distclean: + (cd include/dcmtk/config && rm -f $(DISTTRASH) osconfig.h arith.h) + rm -rf $(DISTTRASH) Makefile.def lzwtest.tif arith + +include/dcmtk/config/arith.h: arith + ./arith $@ + +arith: arith.cc + $(CXX) $(CXXFLAGS) -Iinclude -I../ofstd/include -I../ofstd/libsrc -o$@ $@.cc + +dependencies: include/dcmtk/config/arith.h diff --git a/config/aclocal.m4 b/config/aclocal.m4 new file mode 100644 index 00000000..78e457e1 --- /dev/null +++ b/config/aclocal.m4 @@ -0,0 +1,2013 @@ +dnl +dnl Filename: aclocal.m4 +dnl +dnl Purpose: additional M4 macros for GNU autoconf +dnl +dnl Authors: Andreas Barth, Marco Eichelberg +dnl + + +dnl AC_CHECK_GXXLIB works like AC_CHECK_LIB, but for libg++. +dnl This additional macro is necessary because the /bin/sh will +dnl not allow you to define a variable "ac_cv_lib_g++" and +dnl thus AC_CHECK_LIB will fail for libg++. +dnl All symbols #defined by this macro replace G++ by GXX. + +dnl AC_CHECK_GXXLIB +AC_DEFUN(AC_CHECK_GXXLIB, +[AC_MSG_CHECKING([for -lg++]) +AC_CACHE_VAL(ac_cv_lib_gxx, +[ac_save_LIBS="$LIBS" +LIBS="-lg++ $LIBS" +AC_TRY_LINK(, [main()], eval "ac_cv_lib_gxx=yes", eval "ac_cv_lib_gxx=no") +LIBS="$ac_save_LIBS" +])dnl +if eval "test \"`echo '$ac_cv_lib_gxx'`\" = yes"; then + AC_MSG_RESULT(yes) + ifelse([$3], , +[changequote(, )dnl + ac_tr_lib=HAVE_LIBGXX +changequote([, ])dnl + AC_DEFINE_UNQUOTED($ac_tr_lib) + LIBS="-lg++ $LIBS" +], [$3]) +else + AC_MSG_RESULT(no) +ifelse([$4], , , [$4 +])dnl +fi +]) + +dnl AC_CHECK_PROTOTYPE checks if there is a prototype declaration +dnl for the given function. If header file(s) are given as argument 2, they +dnl are #included in the search. Otherwise only predefined functions will +dnl be found. The header files are only included in the search if they +dnl have already been found using the AC_CHECK_HEADERS(header) macro. +dnl Note: +dnl Since GNU autoheader does not support this macro, you must create entries +dnl in your acconfig.h for each function which is tested. +dnl Examples: +dnl in configure.in: +dnl AC_CHECK_PROTOTYPE(setsockopt, sys/types.h sys/socket.h) +dnl AC_CHECK_PROTOTYPE(gethostid) +dnl in acconfig.h: +dnl #undef HAVE_PROTOTYPE_SETSOCKOPT +dnl #undef HAVE_PROTOTYPE_GETHOSTID + +dnl AC_CHECK_PROTOTYPE(FUNCTION, HEADER-FILE..., ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]) +AC_DEFUN(AC_CHECK_PROTOTYPE, +[AC_MSG_CHECKING([ifelse([$2], , [predefined prototype for $1], [prototype for $1 (in $2)])]) +AH_TEMPLATE(AS_TR_CPP(HAVE_PROTOTYPE_$1), [Define if your system has a prototype for $1 in $2]) +ifelse([$3], , :, [$3]) + +ifelse([$2], , [ac_includes="" +], +[ac_includes="" +for ac_header in $2 +do + ac_safe=`echo "$ac_header" | sed 'y%./+-%__p_%'` + if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'}'`\" = yes"; then + ac_includes="$ac_includes +#include<$ac_header>" + fi +done]) +tmp_save_1=`echo $1 | tr ' :' '__'` +AC_CACHE_VAL(ac_cv_prototype_$tmp_save_1, +[AC_TRY_COMPILE( +[#ifdef __cplusplus +extern "C" { +#endif +$ac_includes +#ifdef __cplusplus +} +#endif +typedef union { int member; } dummyStruct; +#ifdef __cplusplus +extern "C" +#endif +dummyStruct $1(dummyStruct); +] +, ,eval "ac_cv_prototype_$tmp_save_1=no", eval "ac_cv_prototype_$tmp_save_1=yes")])dnl +if eval "test \"`echo '$''{'ac_cv_prototype_$tmp_save_1'}'`\" = yes"; then + AC_MSG_RESULT(yes) +changequote(, )dnl + ac_tr_prototype=HAVE_PROTOTYPE_`echo $tmp_save_1 | tr '[a-z]' '[A-Z]'` +changequote([, ])dnl + AC_DEFINE_UNQUOTED([$ac_tr_prototype]) + ifelse([$3], , :, [$3]) +else + AC_MSG_RESULT(no) +ifelse([$4], , , [$4 +])dnl +fi +]) + +dnl AC_CHECK_COMPILES verifies that the given code fragment can be compiled. +dnl It is assumed that successfully compiling means that the specified +dnl function is available. If header file(s) are given as argument 2, they +dnl #included in the search. Otherwise only predefined functions will be +dnl available. The header files are only included in the search if they have +dnl already been found using the AC_CHECK_HEADERS(header) macro. + +dnl AC_CHECK_COMPILES(FUNCTION, HEADER-FILE..., CODE, ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]) +AC_DEFUN(AC_CHECK_COMPILES, +[AC_MSG_CHECKING([ifelse([$2], , [for $1], [for $1 (in $2)])]) +AH_TEMPLATE(AS_TR_CPP(HAVE_PROTOTYPE_$1), [Define if your system has a prototype for $1 in $2]) +ifelse([$2], , [ac_includes="" +], +[ac_includes="" +for ac_header in $2 +do + ac_safe=`echo "$ac_header" | sed 'y%./+-%__p_%'` + if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'}'`\" = yes"; then + ac_includes="$ac_includes +#include<$ac_header>" + fi +done]) +tmp_save_1=`echo $1 | tr ' :' '__'` +AC_CACHE_VAL(ac_cv_compiles_$tmp_save_1, +[AC_TRY_COMPILE([$ac_includes], [$3], +eval "ac_cv_compiles_$tmp_save_1=yes", eval "ac_cv_compiles_$tmp_save_1=no")])dnl +if eval "test \"`echo '$''{'ac_cv_compiles_$tmp_save_1'}'`\" = yes"; then + AC_MSG_RESULT(yes) +changequote(, )dnl + ac_tr_prototype=HAVE_PROTOTYPE_`echo $tmp_save_1 | tr '[a-z]' '[A-Z]'` +changequote([, ])dnl + AC_DEFINE_UNQUOTED([$ac_tr_prototype]) + ifelse([$4], , :, [$4]) +else + AC_MSG_RESULT(no) +ifelse([$5], , , [$5 +])dnl +fi +]) + +dnl AC_CHECK_DECLARATION checks if a certain type is declared in the include files given as argument 2 or 3. +dnl Files given as argument 2 are included extern "C" in C++ mode, +dnl files given as argument 3 are included "as is". +dnl Header files are only included in the search if they +dnl have already been found using the AC_CHECK_HEADERS(header) macro. + +dnl AC_CHECK_DECLARATION(FUNCTION, C-HEADER-FILE..., C++-HEADER-FILE..., ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]) +AC_DEFUN(AC_CHECK_DECLARATION, +[ +AC_MSG_CHECKING([ifelse([$2 $3], , [predefined type $1], [ifelse([$2], , [declaration for $1 (in $3)], [ifelse([$3], , [declaration for $1 (in $2)], [declaration for $1 (in $2 $3)])])])]) +AH_TEMPLATE(AS_TR_CPP(HAVE_DECLARATION_$1), [Define if your system has a declaration for $1 in $2 $3]) +ifelse([$2], , [ac_includes="" +], +[ac_includes="" +for ac_header in $2 +do + ac_safe=`echo "$ac_header" | sed 'y%./+-%__p_%'` + if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'}'`\" = yes"; then + ac_includes="$ac_includes +#include<$ac_header>" + fi +done +]) +ifelse([$3], , [ac_cpp_includes="" +], +[ac_cpp_includes="" +for ac_header in $3 +do + ac_safe=`echo "$ac_header" | sed 'y%./+-%__p_%'` + if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'}'`\" = yes"; then + ac_cpp_includes="$ac_cpp_includes +#include<$ac_header>" + fi +done +]) +[ac_cv_declaration=`echo 'ac_cv_declaration_$1' | tr ' :' '__'` +] +AC_CACHE_VAL($ac_cv_declaration, +[AC_TRY_COMPILE( +[#ifdef __cplusplus +extern "C" { +#endif +$ac_includes +#ifdef __cplusplus +} +#endif +$ac_cpp_includes +$1 dummy; +] +, ,eval "$ac_cv_declaration=yes", eval "$ac_cv_declaration=no")])dnl +if eval "test \"\$$ac_cv_declaration\" = yes"; then + AC_MSG_RESULT(yes) +changequote(, )dnl + ac_tr_declaration=HAVE_DECLARATION_`echo $1 | tr ' :[a-z]' '__[A-Z]'` +changequote([, ])dnl + AC_DEFINE_UNQUOTED([$ac_tr_declaration]) + ifelse([$4], , :, [$4]) +else + AC_MSG_RESULT(no) +ifelse([$5], , , [$5 +])dnl +fi +unset ac_cv_declaration +]) + + +dnl AC_CHECK_INTP_SELECT checks if the prototype for select() +dnl specifies arguments 2-4 to be int* instead of struct fd_set *. +dnl This is true for HP UX 9.x and causes C++ code to break. + +dnl AC_CHECK_INTP_SELECT(HEADER-FILE..., ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]) +AC_DEFUN(AC_CHECK_INTP_SELECT, +[AC_MSG_CHECKING([ifelse([$1], , [if select() needs int* parameters], +[if select() needs int* parameters (in $1)])]) +AH_TEMPLATE([HAVE_INTP_SELECT], [Define if your system declares argument 2-4 of select() + as int * instead of struct fd_set *]) +ifelse([$1], , [ac_includes="" +], +[ac_includes="" +for ac_header in $1 +do + ac_safe=`echo "$ac_header" | sed 'y%./+-%__p_%'` + if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'}'`\" = yes"; then + ac_includes="$ac_includes +#include<$ac_header>" + fi +done]) +AC_CACHE_VAL(ac_cv_prototype_intp_select, +[AC_TRY_COMPILE( +[#ifdef __cplusplus +extern "C" { +#endif +$ac_includes +#ifdef __cplusplus +} +#endif +] +, +[ + int i; + fd_set fds; + i = select(1, &fds, &fds, &fds, NULL); +], +eval "ac_cv_prototype_intp_select=no", +[AC_TRY_COMPILE( +[#ifdef __cplusplus +extern "C" { +#endif +$ac_includes +#ifdef __cplusplus +} +#endif +] +, +[ + int i; + int fds; + i = select(1, &fds, &fds, &fds, NULL); +], +eval "ac_cv_prototype_intp_select=yes", eval "ac_cv_prototype_intp_select=no")])]) +if eval "test \"`echo $ac_cv_prototype_intp_select`\" = yes"; then + AC_MSG_RESULT(yes) +changequote(, )dnl + ac_tr_prototype=HAVE_INTP_SELECT +changequote([, ])dnl + AC_DEFINE_UNQUOTED($ac_tr_prototype) + ifelse([$2], , :, [$2]) +else + AC_MSG_RESULT(no) + ifelse([$3], , , [$3]) +fi +]) + + + +dnl AC_TRY_COMPILE_AND_LINK compiles a Source file into an object file +dnl and links the object file. This can create a different behaviour +dnl than compiling and linking the object file directly (e.g. +dnl Sun C++ 3.0.1 with template functions) + +dnl AC_TRY_COMPILE_AND_LINK(SOURCE, MAIN_BODY +dnl [, ACTION-IF-FOUND [,ACTION-IF-NOT-FOUND]]) +AC_DEFUN(AC_TRY_COMPILE_AND_LINK, +[ac_link_o='${CXX-g++} -o conftest $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.o $LIBS 1>&AC_FD_CC' +cat > conftest.$ac_ext <&AC_FD_CC + cat conftest.$ac_ext >&AC_FD_CC + ifelse([$4], , , [ rm -rf conftest* + $4 + ])dnl + fi +else + echo "configure: failed compile was:" >&AC_FD_CC + cat conftest.$ac_ext >&AC_FD_CC +ifelse([$4], , , [ rm -rf conftest* + $4 +])dnl +fi +rm -f conftest*]) + +dnl AC_CHECK_STD_NAMESPACE checks if the C++-Compiler supports the +dnl standard name space. + +dnl AC_CHECK_STD_NAMESPACE +AC_DEFUN(AC_CHECK_STD_NAMESPACE, +[AC_MSG_CHECKING([for C++ standard namespace]) +AH_TEMPLATE([HAVE_STD_NAMESPACE], [Define if ANSI standard C++ includes use std namespace]) +AC_CACHE_VAL(ac_cv_check_std_namespace, +[AC_TRY_COMPILE_AND_LINK([ +#include +using namespace std; +],[ + cout << "Hello World" << endl; +], eval "ac_cv_check_std_namespace=yes", eval "ac_cv_check_std_namespace=no")dnl +])dnl +if eval "test \"`echo '$ac_cv_check_std_namespace'`\" = yes"; then + AC_MSG_RESULT(yes) +changequote(, )dnl + ac_tr_std_namespace=HAVE_STD_NAMESPACE +changequote([, ])dnl + AC_DEFINE_UNQUOTED($ac_tr_std_namespace) +else + AC_MSG_RESULT(no) +fi +]) + + + +dnl AC_CHECK_CLASS_TEMPLATE checks if the C++-Compiler is capable of +dnl using class templates in the easiest form i. e. all methods are +dnl inline, no template methods and no typedefs in the class + +dnl AC_CHECK_CLASS_TEMPLATE +AC_DEFUN(AC_CHECK_CLASS_TEMPLATE, +[AC_MSG_CHECKING([for C++ class template]) +AH_TEMPLATE([HAVE_CLASS_TEMPLATE], [Define if your C++ compiler can work with class templates]) +AC_CACHE_VAL(ac_cv_check_class_template, +[AC_TRY_COMPILE_AND_LINK([ +template +class x +{ +private: + T a; +public: + void set(T i) { a = i; } + x(T i) { set(i); } + T get() { return a; } +}; +],[ + int i; + x a(4); + i = a.get(); + a.set(18); + i = a.get(); + a.set(i-1); +], eval "ac_cv_check_class_template=yes", eval "ac_cv_check_class_template=no")dnl +])dnl +if eval "test \"`echo '$ac_cv_check_class_template'`\" = yes"; then + AC_MSG_RESULT(yes) +changequote(, )dnl + ac_tr_class_template=HAVE_CLASS_TEMPLATE +changequote([, ])dnl + AC_DEFINE_UNQUOTED($ac_tr_class_template) +else + AC_MSG_RESULT(no) +fi +]) + + + +dnl AC_CHECK_FUNCTION_TEMPLATE checks if the C++-Compiler is capable of +dnl using function templates. + +dnl AC_CHECK_FUNCTION_TEMPLATE +AC_DEFUN(AC_CHECK_FUNCTION_TEMPLATE, +[AC_MSG_CHECKING([for C++ function template]) +AH_TEMPLATE([HAVE_FUNCTION_TEMPLATE], [Define if your C++ compiler can work with function templates]) +AC_CACHE_VAL(ac_cv_check_function_template, +[AC_TRY_COMPILE_AND_LINK([ +template +int f(T* a) +{ + if (a) return 1; + return 0; +} +],[ + int i, a; + i = f(&a); +], eval "ac_cv_check_function_template=yes", eval "ac_cv_check_function_template=no")dnl +])dnl +if eval "test \"`echo '$ac_cv_check_function_template'`\" = yes"; then + AC_MSG_RESULT(yes) +changequote(, )dnl + ac_tr_function_template=HAVE_FUNCTION_TEMPLATE +changequote([, ])dnl + AC_DEFINE_UNQUOTED($ac_tr_function_template) +else + AC_MSG_RESULT(no) +fi +]) + + +dnl AC_CHECK_STATIC_TEMPLATE_METHOD checks if the C++-Compiler is capable of +dnl using static methods in template classes + +dnl AC_CHECK_STATIC_TEMPLATE_METHOD +AC_DEFUN(AC_CHECK_STATIC_TEMPLATE_METHOD, +[AC_MSG_CHECKING([for C++ static methods in class templates]) +AH_TEMPLATE([HAVE_STATIC_TEMPLATE_METHOD], [Define if your C++ compiler can work with static methods in class templates]) +AC_CACHE_VAL(ac_cv_check_static_template_method, +[AC_TRY_COMPILE_AND_LINK([ +void additive(int & i) +{ + i++; +} + +template +class x +{ +public: + x() { } + static void do1(Function f, int & a) { f(a); } + static void do2(T b) { T a = b; }; +}; +],[ + int a = 1; + x::do1(additive, a); + x::do2(a); +], eval "ac_cv_check_static_template_method=yes", eval "ac_cv_check_static_template_method=no")dnl +])dnl +if eval "test \"`echo '$ac_cv_check_static_template_method'`\" = yes"; then + AC_MSG_RESULT(yes) +changequote(, )dnl + ac_tr_static_template_method=HAVE_STATIC_TEMPLATE_METHOD +changequote([, ])dnl + AC_DEFINE_UNQUOTED($ac_tr_static_template_method) +else + AC_MSG_RESULT(no) +fi +]) + + +dnl AC_CHECK_EXPLICIT_TEMPLATE_SPECIALIZATION checks if the C++-Compiler +dnl supports the explicit template specialization syntax, i.e. +dnl template<> int classname::functionname() + +dnl AC_CHECK_EXPLICIT_TEMPLATE_SPECIALIZATION +AC_DEFUN(AC_CHECK_EXPLICIT_TEMPLATE_SPECIALIZATION, +[AC_MSG_CHECKING([for C++ explicit template specialization syntax]) +AH_TEMPLATE([HAVE_EXPLICIT_TEMPLATE_SPECIALIZATION], [Define if your C++ compiler supports the explicit template specialization syntax]) +AC_CACHE_VAL(ac_cv_check_explicit_template_specialization, +[AC_TRY_COMPILE([ +template +class X +{ + public: + int fn(); +}; + +template<> +int X::fn() +{ + return 0; +} +],[X x], eval "ac_cv_check_explicit_template_specialization=yes", eval "ac_cv_check_explicit_template_specialization=no")dnl +])dnl +if eval "test \"`echo '$ac_cv_check_explicit_template_specialization'`\" = yes"; then + AC_MSG_RESULT(yes) +changequote(, )dnl + ac_tr_explicit_template_specialization=HAVE_EXPLICIT_TEMPLATE_SPECIALIZATION +changequote([, ])dnl + AC_DEFINE_UNQUOTED($ac_tr_explicit_template_specialization) +else + AC_MSG_RESULT(no) +fi +]) + + +dnl AC_CHECK_GNU_LIBTOOL checks whether libtool is GNU libtool. +dnl This macro requires that 'libtool' exists in the current path, +dnl i.e. AC_CHECK_PROGS(LIBTOOL, libtool, :) should be executed and evaluated +dnl before performing this test. +dnl If libtool is identified as GNU libtool, the environment variable $ac_cv_check_gnu_libtool +dnl is set to the value "yes", otherwise to "no". +dnl +dnl AC_CHECK_GNU_LIBTOOL +AC_DEFUN(AC_CHECK_GNU_LIBTOOL, +[AC_MSG_CHECKING([whether libtool is GNU libtool]) +AC_CACHE_VAL(ac_cv_check_gnu_libtool, +[ ac_cv_check_gnu_libtool=`libtool --version 2>/dev/null | grep "GNU libtool" | sed -e "s/.*\(GNU libtool\).*/\1/" ` + if test "${ac_cv_check_gnu_libtool}set" = "GNU libtoolset" ; then + ac_cv_check_gnu_libtool=yes + else + ac_cv_check_gnu_libtool=no + fi +]) + if test $ac_cv_check_gnu_libtool = yes ; then + AC_MSG_RESULT(yes) + else + AC_MSG_RESULT(no) + fi +]) + + + +dnl AC_CHECK_HEADER_WITH_INCLUDES works like AC_CHECK_HEADER but allows to specify +dnl additional code to be put into the test program before the #include statement +dnl generated by AC_CHECK_HEADER. +dnl Typically this additional code will be additional #include statements. +dnl For example, on Irix 6, cannot be included if is not +dnl included before (leads to parse error). +dnl +dnl AC_CHECK_HEADER_WITH_INCLUDES(HEADER-FILE, [INCLUDES, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]]) +AC_DEFUN(AC_CHECK_HEADER_WITH_INCLUDES, +[dnl Do the transliteration at runtime so arg 1 can be a shell variable. +ac_safe=`echo "$1" | sed 'y%./+-%__p_%'` +AC_MSG_CHECKING([for $1]) +AC_CACHE_VAL(ac_cv_header_$ac_safe, +[AC_TRY_CPP([$2 +#include <$1>], eval "ac_cv_header_$ac_safe=yes", + eval "ac_cv_header_$ac_safe=no")])dnl +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + AC_MSG_RESULT(yes) + ifelse([$3], , :, [$3]) +else + AC_MSG_RESULT(no) +ifelse([$4], , , [$4 +])dnl +fi +]) + +dnl AC_CHECK_HEADERS_WITH_INCLUDES works like AC_CHECK_HEADERS but allows to specify +dnl additional code to be put into the test program before the #include statement +dnl generated by AC_CHECK_HEADERS. +dnl Typically this additional code will be additional #include statements. +dnl For example, on Irix 6, cannot be included if is not +dnl included before (leads to parse error). +dnl +dnl AC_CHECK_HEADERS_WITH_INCLUDES(HEADER-FILE..., [INCLUDES, [, ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]]) +AC_DEFUN(AC_CHECK_HEADERS_WITH_INCLUDES, +[for ac_hdr in $1 +do +AC_CHECK_HEADER_WITH_INCLUDES($ac_hdr, $2, +[changequote(, )dnl + ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` +changequote([, ])dnl + AC_DEFINE_UNQUOTED($ac_tr_hdr) $3], $4)dnl +done +]) + + +dnl AC_CHECK_TCP_H +dnl checks for the presence of three system include files: +dnl +dnl +dnl +dnl On certain systems like Irix or NeXT these are interdependent, i.e. +dnl tcp.h can only be included if in.h is included before. This script +dnl accounts for these dependencies. +dnl +dnl Note: GNU autoheader recognizes the includes tested by this macro. +dnl No manual intervention required. +dnl +AC_DEFUN(AC_CHECK_TCP_H, +[AC_CHECK_HEADERS(netinet/in_systm.h) + +if eval "test \"`echo '$ac_cv_header_netinet_in_systm_h'`\" = yes"; then + AC_CHECK_HEADERS_WITH_INCLUDES(netinet/in.h, +#include +) + if eval "test \"`echo '$ac_cv_header_netinet_in_h'`\" = yes"; then + AC_CHECK_HEADERS_WITH_INCLUDES(netinet/tcp.h, +#include +#include +) + else + AC_CHECK_HEADERS_WITH_INCLUDES(netinet/tcp.h, +#include +) + fi +else + AC_CHECK_HEADERS(netinet/in.h) + if eval "test \"`echo '$ac_cv_header_netinet_in_h'`\" = yes"; then + AC_CHECK_HEADERS_WITH_INCLUDES(netinet/tcp.h, +#include +) + else + AC_CHECK_HEADERS(netinet/tcp.h) + fi +fi +]) + +dnl AC_CHECK_INTP_ACCEPT checks if the prototype for accept() +dnl specifies arguments 2-4 to be int* instead of size_t *. + +dnl AC_CHECK_INTP_ACCEPT(HEADER-FILE..., ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]) +AC_DEFUN(AC_CHECK_INTP_ACCEPT, +[AC_MSG_CHECKING([ifelse([$1], , [if accept() needs int* parameters], +[if accept() needs int* parameters (in $1)])]) +AH_TEMPLATE([HAVE_INTP_ACCEPT], [Define if your system declares argument 3 of accept() + as int * instead of size_t * or socklen_t *]) +ifelse([$1], , [ac_includes="" +], +[ac_includes="" +for ac_header in $1 +do + ac_includes="$ac_includes +#include<$ac_header>" +done]) +AC_CACHE_VAL(ac_cv_prototype_intp_accept, +[AC_TRY_COMPILE( +[#ifdef __cplusplus +extern "C" { +#endif +$ac_includes +#ifdef __cplusplus +} +#endif +] +, +[ + int i; + struct sockaddr *addr; + size_t addrlen; + + addr = 0; + addrlen = 0; + i = accept(1, addr, &addrlen); +], +eval "ac_cv_prototype_intp_accept=no", +[AC_TRY_COMPILE( +[#ifdef __cplusplus +extern "C" { +#endif +$ac_includes +#ifdef __cplusplus +} +#endif +] +, +[ + int i; + struct sockaddr *addr; + int addrlen; + + addr = 0; + addrlen = 0; + i = accept(1, addr, &addrlen); +], +eval "ac_cv_prototype_intp_accept=yes", eval "ac_cv_prototype_intp_accept=no")])]) +if eval "test \"`echo $ac_cv_prototype_intp_accept`\" = yes"; then + AC_MSG_RESULT(yes) +changequote(, )dnl + ac_tr_prototype=HAVE_INTP_ACCEPT +changequote([, ])dnl + AC_DEFINE_UNQUOTED($ac_tr_prototype) + ifelse([$2], , :, [$2]) +else + AC_MSG_RESULT(no) + ifelse([$3], , , [$3]) +fi +]) + + + + +dnl AC_CHECK_PTHREAD_OPTION checks whether the compiler requires the +dnl -pthread option to correctly link code containing posix thread calls. +dnl This is true for example on FreeBSD. +dnl This test assumes that is available. + +dnl If the test is positive, -pthread is added to CFLAGS and CXXFLAGS. + +dnl AC_CHECK_PTHREAD_OPTION +AC_DEFUN(AC_CHECK_PTHREAD_OPTION, +[AC_MSG_CHECKING(whether compiler requires -pthread option for posix threads) +REQUIRES_PTHREAD_OPTION="no" +AC_TRY_LINK( +[#ifdef __cplusplus +extern "C" { +#endif +] +#include +[#ifdef __cplusplus +} +#endif +] +, +[ + (void) pthread_create(NULL, NULL, NULL, NULL); +], , +SAVE_CXXFLAGS="$CXXFLAGS" +SAVE_CFLAGS="$CFLAGS" +CXXFLAGS="-pthread $CXXFLAGS" +CFLAGS="-pthread $CFLAGS" +AC_TRY_LINK( +[#ifdef __cplusplus +extern "C" { +#endif +] +#include +[#ifdef __cplusplus +} +#endif +] +, +[ + (void) pthread_create(NULL, NULL, NULL, NULL); +], +REQUIRES_PTHREAD_OPTION="yes" +, ) +CXXFLAGS="$SAVE_CXXFLAGS" +CFLAGS="$SAVE_CFLAGS" +) + +if test $REQUIRES_PTHREAD_OPTION = yes ; then + AC_MSG_RESULT([yes]) + CXXFLAGS="-pthread $CXXFLAGS" + CFLAGS="-pthread $CFLAGS" +else + AC_MSG_RESULT([no]) +fi +]) + + + +dnl AC_MY_C_INLINE works like the standard script AC_C_INLINE +dnl but defines C_INLINE instead of redefining "inline" directly. + +AC_DEFUN(AC_MY_C_INLINE, +[AH_TEMPLATE([C_INLINE], [Define to the inline keyword supported by the C compiler, if any, or to the empty string]) +AC_CACHE_CHECK([for inline], ac_cv_my_c_inline, +[ac_cv_my_c_inline=no +for ac_kw in inline __inline__ __inline; do + AC_TRY_COMPILE(, [} $ac_kw foo() {], [ac_cv_my_c_inline=$ac_kw; break]) +done +]) +case "$ac_cv_my_c_inline" in + inline | yes) AC_DEFINE(C_INLINE, inline) ;; + no) AC_DEFINE(C_INLINE, ) ;; + *) AC_DEFINE_UNQUOTED(C_INLINE, $ac_cv_my_c_inline) ;; +esac +]) + + +dnl AC_MY_C_CONST works like the standard script AC_C_CONST +dnl but defines HAVE_C_CONST instead of redefining "const" directly. + +AC_DEFUN(AC_MY_C_CONST, +[AH_TEMPLATE([HAVE_C_CONST], [Define if "const" is supported by the C compiler]) +dnl This message is consistent in form with the other checking messages, +dnl and with the result message. +AC_CACHE_CHECK([for working const], ac_cv_my_c_const, +[AC_TRY_COMPILE(, +changequote(<<, >>)dnl +<< +/* Ultrix mips cc rejects this. */ +typedef int charset[2]; const charset x; +/* SunOS 4.1.1 cc rejects this. */ +char const *const *ccp; +char **p; +/* NEC SVR4.0.2 mips cc rejects this. */ +struct point {int x, y;}; +static struct point const zero = {0,0}; +/* AIX XL C 1.02.0.0 rejects this. + It does not let you subtract one const X* pointer from another in an arm + of an if-expression whose if-part is not a constant expression */ +const char *g = "string"; +ccp = &g + (g ? g-g : 0); +/* HPUX 7.0 cc rejects these. */ +++ccp; +p = (char**) ccp; +ccp = (char const *const *) p; +{ /* SCO 3.2v4 cc rejects this. */ + char *t; + char const *s = 0 ? (char *) 0 : (char const *) 0; + + *t++ = 0; +} +{ /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */ + int x[] = {25, 17}; + const int *foo = &x[0]; + ++foo; +} +{ /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */ + typedef const int *iptr; + iptr p = 0; + ++p; +} +{ /* AIX XL C 1.02.0.0 rejects this saying + "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */ + struct s { int j; const int *ap[3]; }; + struct s *b; b->j = 5; +} +{ /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */ + const int foo = 10; +} +>>, +changequote([, ])dnl +ac_cv_my_c_const=yes, ac_cv_my_c_const=no)]) +if test $ac_cv_my_c_const = yes; then + AC_DEFINE_UNQUOTED(HAVE_C_CONST) +fi +]) + + +dnl AC_MY_C_CHAR_UNSIGNED works like the standard script AC_C_CHAR_UNSIGNED +dnl but defines C_CHAR_UNSIGNED instead of __CHAR_UNSIGNED__. + +AC_DEFUN(AC_MY_C_CHAR_UNSIGNED, +[AH_TEMPLATE([C_CHAR_UNSIGNED], [Define if char is unsigned on the C compiler]) +AC_CACHE_CHECK(whether char is unsigned, ac_cv_my_c_char_unsigned, +[if test "$GCC" = yes; then + # GCC predefines this symbol on systems where it applies. +AC_EGREP_CPP(yes, +[#ifdef __CHAR_UNSIGNED__ + yes +#endif +], ac_cv_my_c_char_unsigned=yes, ac_cv_my_c_char_unsigned=no) +else +AC_TRY_RUN( +[/* volatile prevents gcc2 from optimizing the test away on sparcs. */ +#if !defined(__STDC__) || __STDC__ != 1 +#define volatile +#endif +main() { + volatile char c = 255; exit(c < 0); +}], ac_cv_my_c_char_unsigned=yes, ac_cv_my_c_char_unsigned=no) +fi]) +if test $ac_cv_my_c_char_unsigned = yes ; then + AC_DEFINE(C_CHAR_UNSIGNED) +fi +]) + + +dnl AC_MY_C_RIGHTSHIFT_UNSIGNED checks whether the right shift operation +dnl is unsigned and, if yes, defines C_RIGHTSHIFT_UNSIGNED. + +AC_DEFUN(AC_MY_C_RIGHTSHIFT_UNSIGNED, +[AH_TEMPLATE([C_RIGHTSHIFT_UNSIGNED], [Define if >> is unsigned on the C compiler]) +AC_CACHE_CHECK(whether right shift is unsigned, ac_cv_my_c_rightshift_unsigned, +[ +AC_TRY_RUN( +[/* See whether right-shift on a long is signed or not. */ +int is_shifting_signed (long arg) +{ + long res = arg >> 4; + + if (res == -0x7F7E80CL) { /* expected result for signed shift */ + return 1; /* right shift is signed */ + } + /* see if unsigned-shift hack will fix it. */ + /* we can't just test exact value since it depends on width of long... */ + res |= (~0L) << (32-4); + if (res == -0x7F7E80CL) { /* expected result now? */ + return 0; /* right shift is unsigned */ + } + /* Right shift isn't acting as I expect it to, try it with unsigned anyway */ + return 0; +} + +int main() +{ + exit(is_shifting_signed(-0x7F7E80B1L)); +} +], ac_cv_my_c_rightshift_unsigned=yes, ac_cv_my_c_rightshift_unsigned=no) +]) +if test $ac_cv_my_c_rightshift_unsigned = yes ; then + AC_DEFINE(C_CHAR_UNSIGNED) +fi +]) + + +dnl AC_CHECK_IOS_NOCREATE checks if the flag ios::nocreate is defined. + +dnl AC_CHECK_IOS_NOCREATE(IOS-Name, header [, ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]) +AC_DEFUN(AC_CHECK_IOS_NOCREATE, +[ +AC_MSG_CHECKING([declaration of ios::nocreate (in $2)]) +AH_TEMPLATE([HAVE_IOS_NOCREATE], [Define if your system defines ios::nocreate in iostream.h]) +ac_cv_declaration=ac_cv_declaration_ios_nocreate +AC_CACHE_VAL($ac_cv_declaration, +[AC_TRY_COMPILE([ +#include <$2> +], [namespace std { } +using namespace std; +ifstream file("name", $1::nocreate)] ,eval "$ac_cv_declaration=yes", eval "$ac_cv_declaration=no")])dnl +if eval "test \"\$$ac_cv_declaration\" = yes"; then + AC_MSG_RESULT(yes) +changequote(, )dnl + ac_tr_declaration=HAVE_IOS_NOCREATE +changequote([, ])dnl + AC_DEFINE_UNQUOTED($ac_tr_declaration) + ifelse([$3], , :, [$3]) +else + AC_MSG_RESULT(no) +ifelse([$4], , , [$4 +])dnl +fi +unset ac_cv_declaration +]) + + + +dnl AC_CHECK_OLD_READDIR_R checks if there is a function readdir_r +dnl conforming to the Posix 1.c Draft 6 interface, i.e. +dnl struct dirent *readdir_r(DIR *dirp, struct dirent *entry); +dnl instead of the Posix 1.c interface, i.e. +dnl int readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result); +dnl +dnl The test macro AC_HEADER_DIRENT must be run before this test! +dnl +dnl AC_CHECK_OLD_READDIR_R([ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]) +AC_DEFUN(AC_CHECK_OLD_READDIR_R, +[ +AC_MSG_CHECKING([if declaration of readdir_r conforms to Posix 1.c draft 6]) +AH_TEMPLATE([HAVE_OLD_READDIR_R], [Define if your system supports readdir_r with the obsolete + Posix 1.c draft 6 declaration (2 arguments) instead of the + Posix 1.c declaration with 3 arguments.]) +ac_cv_result=ac_cv_old_readdir_r +AC_CACHE_VAL($ac_cv_result, +[AC_TRY_COMPILE([ +#ifdef __cplusplus +extern "C" { +#endif +#ifdef HAVE_DIRENT_H +#include +#else +#define dirent direct +#ifdef HAVE_SYS_NDIR_H +#include +#endif +#ifdef HAVE_SYS_DIR_H +#include +#endif +#ifdef HAVE_NDIR_H +#include +#endif +#endif +#ifdef __cplusplus +} +#endif +], [ + DIR *dirp; + struct dirent *dp; + dp = readdir_r(dirp, dp); +], eval "$ac_cv_result=yes", eval "$ac_cv_result=no")])dnl +if eval "test \"\$$ac_cv_result\" = yes"; then + AC_MSG_RESULT(yes) +changequote(, )dnl + ac_cv_result=HAVE_OLD_READDIR_R +changequote([, ])dnl + AC_DEFINE_UNQUOTED($ac_cv_result) + ifelse([$1], , , [$1 +])dnl +else + AC_MSG_RESULT(no) + ifelse([$2], , , [$2 +])dnl +fi +unset ac_cv_result +]) + + +dnl AC_CHECK_INTP_GETSOCKOPT checks if the prototype for getsockopt() +dnl specifies arguments 5 to be int* instead of size_t *. + +dnl AC_CHECK_INTP_GETSOCKOPT(HEADER-FILE..., ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]) +AC_DEFUN(AC_CHECK_INTP_GETSOCKOPT, +[AC_MSG_CHECKING([ifelse([$1], , [if getsockopt() needs int* parameters], +[if getsockopt() needs int* parameters (in $1)])]) +AH_TEMPLATE([HAVE_INTP_GETSOCKOPT], [Define if your system declares argument 5 of getsockopt() + as int * instead of size_t * or socklen_t]) +ifelse([$1], , [ac_includes="" +], +[ac_includes="" +for ac_header in $1 +do + ac_includes="$ac_includes +#include<$ac_header>" +done]) +AC_CACHE_VAL(ac_cv_prototype_intp_getsockopt, +[AC_TRY_COMPILE( +[#ifdef __cplusplus +extern "C" { +#endif +$ac_includes +#ifdef __cplusplus +} +#endif +] +, +[ + int i; + size_t optlen; + i = getsockopt(0, 0, 0, 0, &optlen); +], +eval "ac_cv_prototype_intp_getsockopt=no", +[AC_TRY_COMPILE( +[#ifdef __cplusplus +extern "C" { +#endif +$ac_includes +#ifdef __cplusplus +} +#endif +] +, +[ + int i; + int optlen; + i = getsockopt(0, 0, 0, 0, &optlen); +], +eval "ac_cv_prototype_intp_getsockopt=yes", eval "ac_cv_prototype_intp_getsockopt=no")])]) +if eval "test \"`echo $ac_cv_prototype_intp_getsockopt`\" = yes"; then + AC_MSG_RESULT(yes) +changequote(, )dnl + ac_tr_prototype=HAVE_INTP_GETSOCKOPT +changequote([, ])dnl + AC_DEFINE_UNQUOTED($ac_tr_prototype) + ifelse([$2], , :, [$2]) +else + AC_MSG_RESULT(no) + ifelse([$3], , , [$3]) +fi +]) + + +dnl AC_CHECK_ELLIPSE_SIGNAL_HANDLER checks if the prototype for the +dnl callback function passed to signal() needs an ellipse (...) +dnl as parameter. Needed for example on Irix 5. +dnl The header files for signal() have to be specified. + +dnl AC_CHECK_ELLIPSE_SIGNAL_HANDLER(HEADER-FILE..., ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]) +AC_DEFUN(AC_CHECK_ELLIPSE_SIGNAL_HANDLER, +[AC_MSG_CHECKING([ifelse([$1], , [if signal() callback needs ellipse], +[if signal() callback needs ellipse (in $1)])]) +AH_TEMPLATE([SIGNAL_HANDLER_WITH_ELLIPSE], [Define if signal handlers need ellipse (...) parameters]) +ifelse([$1], , [ac_includes="" +], +[ac_includes="" +for ac_header in $1 +do + ac_includes="$ac_includes +#include<$ac_header>" +done]) +AC_CACHE_VAL(ac_cv_signal_handler_with_ellipse, +[AC_TRY_COMPILE( +[#ifdef __cplusplus +extern "C" { +#endif +$ac_includes + + void signal_handler(int) + { + } +#ifdef __cplusplus +} +#endif +] +, +[ + (void) signal(0, signal_handler); +], +eval "ac_cv_signal_handler_with_ellipse=no", +[AC_TRY_COMPILE( +[#ifdef __cplusplus +extern "C" { +#endif +$ac_includes + + void signal_handler(...) + { + } +#ifdef __cplusplus +} +#endif +] +, +[ + (void) signal(0, signal_handler); +], +eval "ac_cv_signal_handler_with_ellipse=yes", eval "ac_cv_signal_handler_with_ellipse=no")])]) +if eval "test \"`echo $ac_cv_signal_handler_with_ellipse`\" = yes"; then + AC_MSG_RESULT(yes) +changequote(, )dnl + ac_tr_prototype=SIGNAL_HANDLER_WITH_ELLIPSE +changequote([, ])dnl + AC_DEFINE_UNQUOTED($ac_tr_prototype) + ifelse([$2], , :, [$2]) +else + AC_MSG_RESULT(no) + ifelse([$3], , , [$3]) +fi +]) + + + +dnl AC_INCLUDE_MATH_H_AS_CXX checks if must be included as a C++ +dnl include file (i.e. without extern "C"). Some sytems (Win32, HP/UX 10) +dnl use C++ language features in + +dnl AC_INCLUDE_MATH_H_AS_CXX(HEADER-FILE..., ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]) +AC_DEFUN(AC_INCLUDE_MATH_H_AS_CXX, +[AC_MSG_CHECKING([if fails if included extern "C"]) +AH_TEMPLATE([INCLUDE_MATH_H_AS_CXX], [Define if fails if included extern "C"]) +AC_CACHE_VAL(ac_cv_include_math_h_as_cxx, +[AC_TRY_COMPILE([ +extern "C" +{ +#include +} +], +[ +], +eval "ac_cv_include_math_h_as_cxx=no", +[AC_TRY_COMPILE([ +#include +], +[ +], +eval "ac_cv_include_math_h_as_cxx=yes", eval "ac_cv_include_math_h_as_cxx=no")])]) +if eval "test \"`echo $ac_cv_include_math_h_as_cxx`\" = yes"; then + AC_MSG_RESULT(yes) +changequote(, )dnl + ac_tr_prototype=INCLUDE_MATH_H_AS_CXX +changequote([, ])dnl + AC_DEFINE_UNQUOTED($ac_tr_prototype) + ifelse([$2], , :, [$2]) +else + AC_MSG_RESULT(no) + ifelse([$3], , , [$3]) +fi +]) + + +dnl AC_CHECK_CXX_BOOL checks if bool is a built-in C++ type +dnl (which is not the case on older compilers). + +dnl AC_CHECK_CXX_BOOL(ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]) +AC_DEFUN(AC_CHECK_CXX_BOOL, +[AC_MSG_CHECKING([if bool is built-in type]) +AH_TEMPLATE([HAVE_CXX_BOOL], [Define if bool is a built-in type]) +AC_CACHE_VAL(ac_cv_have_cxx_bool, +[AC_TRY_COMPILE([],[ +bool b1 = true; +bool b2 = false; +], +eval "ac_cv_have_cxx_bool=yes", +eval "ac_cv_have_cxx_bool=no")]) +if eval "test \"`echo $ac_cv_have_cxx_bool`\" = yes"; then + AC_MSG_RESULT(yes) +changequote(, )dnl + ac_tr_prototype=HAVE_CXX_BOOL +changequote([, ])dnl + AC_DEFINE_UNQUOTED($ac_tr_prototype) + ifelse([$1], , :, [$1]) +else + AC_MSG_RESULT(no) + ifelse([$2], , , [$2]) +fi +]) + + +dnl AC_CHECK_CXX_VOLATILE checks if volatile is a built-in C++ keyword +dnl (which is not the case on older compilers). + +dnl AC_CHECK_CXX_VOLATILE(ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]) +AC_DEFUN(AC_CHECK_CXX_VOLATILE, +[AC_MSG_CHECKING([if volatile is known keyword]) +AH_TEMPLATE([HAVE_CXX_VOLATILE], [Define if volatile is a known keyword]) +AC_CACHE_VAL(ac_cv_have_cxx_volatile, +[AC_TRY_COMPILE([],[ +volatile int i=0; +], +eval "ac_cv_have_cxx_volatile=yes", +eval "ac_cv_have_cxx_volatile=no")]) +if eval "test \"`echo $ac_cv_have_cxx_volatile`\" = yes"; then + AC_MSG_RESULT(yes) +changequote(, )dnl + ac_tr_prototype=HAVE_CXX_VOLATILE +changequote([, ])dnl + AC_DEFINE_UNQUOTED($ac_tr_prototype, ,[Define if volatile is a known keyword]) + ifelse([$1], , :, [$1]) +else + AC_MSG_RESULT(no) + ifelse([$2], , , [$2]) +fi +]) + + +dnl Available from the GNU Autoconf Macro Archive at: +dnl http://www.gnu.org/software/ac-archive/htmldoc/ac_cxx_typename.html +dnl +AC_DEFUN([AC_CXX_TYPENAME], +[AH_TEMPLATE([HAVE_TYPENAME], [Define if typename is a known keyword]) +AC_CACHE_CHECK(whether the compiler recognizes typename, +ac_cv_cxx_typename, +[AC_LANG_SAVE + AC_LANG_CPLUSPLUS + AC_TRY_COMPILE([templateclass X {public:X(){}};], +[X z; return 0;], + ac_cv_cxx_typename=yes, ac_cv_cxx_typename=no) + AC_LANG_RESTORE +]) +if test "$ac_cv_cxx_typename" = yes; then + AC_DEFINE(HAVE_TYPENAME,,[define if the compiler recognizes typename]) +fi +]) + + +dnl Available from the GNU Autoconf Macro Archive at: +dnl http://www.gnu.org/software/ac-archive/htmldoc/ac_cxx_const_cast.html +dnl +AC_DEFUN([AC_CXX_CONST_CAST], +[AH_TEMPLATE([HAVE_CONST_CAST], [Define if the compiler supports const_cast<>]) +AC_CACHE_CHECK(whether the compiler supports const_cast<>, +ac_cv_cxx_const_cast, +[AC_LANG_SAVE + AC_LANG_CPLUSPLUS + AC_TRY_COMPILE(,[int x = 0;const int& y = x;int& z = const_cast(y);return z;], + ac_cv_cxx_const_cast=yes, ac_cv_cxx_const_cast=no) + AC_LANG_RESTORE +]) +if test "$ac_cv_cxx_const_cast" = yes; then + AC_DEFINE(HAVE_CONST_CAST,,[define if the compiler supports const_cast<>]) +fi +]) + + +dnl Available from the GNU Autoconf Macro Archive at: +dnl http://www.gnu.org/software/ac-archive/htmldoc/ac_cxx_dynamic_cast.html +dnl +AC_DEFUN([AC_CXX_DYNAMIC_CAST], +[AH_TEMPLATE([HAVE_DYNAMIC_CAST], [Define if the compiler supports dynamic_cast<>]) +AC_CACHE_CHECK(whether the compiler supports dynamic_cast<>, +ac_cv_cxx_dynamic_cast, +[AC_LANG_SAVE + AC_LANG_CPLUSPLUS + AC_TRY_COMPILE([#include +class Base { public : Base () {} virtual void f () = 0;}; +class Derived : public Base { public : Derived () {} virtual void f () {} };],[ +Derived d; Base& b=d; return dynamic_cast(&b) ? 0 : 1;], + ac_cv_cxx_dynamic_cast=yes, ac_cv_cxx_dynamic_cast=no) + AC_LANG_RESTORE +]) +if test "$ac_cv_cxx_dynamic_cast" = yes; then + AC_DEFINE(HAVE_DYNAMIC_CAST,,[define if the compiler supports dynamic_cast<>]) +fi +]) + + +dnl Available from the GNU Autoconf Macro Archive at: +dnl http://www.gnu.org/software/ac-archive/htmldoc/ac_cxx_reinterpret_cast.html +dnl +AC_DEFUN([AC_CXX_REINTERPRET_CAST], +[AH_TEMPLATE([HAVE_REINTERPRET_CAST], [Define if the compiler supports reinterpret_cast<>]) +AC_CACHE_CHECK(whether the compiler supports reinterpret_cast<>, +ac_cv_cxx_reinterpret_cast, +[AC_LANG_SAVE + AC_LANG_CPLUSPLUS + AC_TRY_COMPILE([#include +class Base { public : Base () {} virtual void f () = 0;}; +class Derived : public Base { public : Derived () {} virtual void f () {} }; +class Unrelated { public : Unrelated () {} }; +int g (Unrelated&) { return 0; }],[ +Derived d;Base& b=d;Unrelated& e=reinterpret_cast(b);return g(e);], + ac_cv_cxx_reinterpret_cast=yes, ac_cv_cxx_reinterpret_cast=no) + AC_LANG_RESTORE +]) +if test "$ac_cv_cxx_reinterpret_cast" = yes; then + AC_DEFINE(HAVE_REINTERPRET_CAST,, + [define if the compiler supports reinterpret_cast<>]) +fi +]) + + +dnl Available from the GNU Autoconf Macro Archive at: +dnl http://www.gnu.org/software/ac-archive/htmldoc/ac_cxx_static_cast.html +dnl +AC_DEFUN([AC_CXX_STATIC_CAST], +[AH_TEMPLATE([HAVE_STATIC_CAST], [Define if the compiler supports static_cast<>]) +AC_CACHE_CHECK(whether the compiler supports static_cast<>, +ac_cv_cxx_static_cast, +[AC_LANG_SAVE + AC_LANG_CPLUSPLUS + AC_TRY_COMPILE([#include +class Base { public : Base () {} virtual void f () = 0; }; +class Derived : public Base { public : Derived () {} virtual void f () {} }; +int g (Derived&) { return 0; }],[ +Derived d; Base& b = d; Derived& s = static_cast (b); return g (s);], + ac_cv_cxx_static_cast=yes, ac_cv_cxx_static_cast=no) + AC_LANG_RESTORE +]) +if test "$ac_cv_cxx_static_cast" = yes; then + AC_DEFINE(HAVE_STATIC_CAST,, + [define if the compiler supports static_cast<>]) +fi +]) + + +dnl AC_CXX_STD_NOTHROW checks if the compiler supports non-throwing new using +dnl std::nothrow. + +AC_DEFUN([AC_CXX_STD_NOTHROW], +[AH_TEMPLATE([HAVE_STD__NOTHROW], [Define if the compiler supports std::nothrow]) +AC_CACHE_CHECK(whether the compiler supports std::nothrow, +ac_cv_cxx_std_nothrow, +[AC_LANG_SAVE + AC_LANG_CPLUSPLUS + AC_TRY_COMPILE([#include ],[int *i = new (std::nothrow) int], + ac_cv_cxx_std_nothrow=yes, ac_cv_cxx_std_nothrow=no) + AC_LANG_RESTORE +]) +if test "$ac_cv_cxx_std_nothrow" = yes; then + AC_DEFINE(HAVE_STD__NOTHROW,, [Define if the compiler supports std::nothrow]) +fi +]) + + +dnl AC_CXX_NOTHROW_DELETE checks if the compiler supports non-throwing delete using +dnl std::nothrow. + +AC_DEFUN([AC_CXX_NOTHROW_DELETE], +[AH_TEMPLATE([HAVE_NOTHROW_DELETE], [Define if the compiler supports operator delete (std::nothrow)]) +AC_CACHE_CHECK(whether the compiler supports operator delete (std::nothrow), +ac_cv_cxx_nothrow_delete, +[AC_LANG_SAVE + AC_LANG_CPLUSPLUS + AC_TRY_COMPILE([#include ],[int *i = new (std::nothrow) int; operator delete (i,std::nothrow)], + ac_cv_cxx_nothrow_delete=yes, ac_cv_cxx_nothrow_delete=no) + AC_LANG_RESTORE +]) +if test "$ac_cv_cxx_nothrow_delete" = yes; then + AC_DEFINE(HAVE_NOTHROW_DELETE,, [Define if the compiler supports operator delete (std::nothrow)]) +fi +]) + + +dnl AC_LIBTIFF_LZW_COMPRESSION checks if libtiff supports LZW compression. + +AC_DEFUN([AC_LIBTIFF_LZW_COMPRESSION], +[AH_TEMPLATE([HAVE_LIBTIFF_LZW_COMPRESSION], [Define if libtiff supports LZW compression]) +AC_CACHE_CHECK(whether libtiff supports LZW compression, +ac_cv_libtiff_lzw_compression, +[AC_TRY_RUN( +changequote({{, }})dnl +{{ +extern "C" { +#include +} + +int main() +{ + const char *data[256]; + for (int j=0; j<256; ++j) data[j]= 0; + + int OK = 1; + TIFF *tif = TIFFOpen("lzwtest.tif", "w"); + if (tif) + { + TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, 16); + TIFFSetField(tif, TIFFTAG_IMAGELENGTH, 16); + TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 8); + TIFFSetField(tif, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT); + TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_LZW); + TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK); + TIFFSetField(tif, TIFFTAG_FILLORDER, FILLORDER_MSB2LSB); + TIFFSetField(tif, TIFFTAG_DOCUMENTNAME, "unnamed"); + TIFFSetField(tif, TIFFTAG_IMAGEDESCRIPTION, "test"); + TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, 1); + TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, 512); + TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); + + for (unsigned long i=0; (i < 16) && OK; i++) + { + if (TIFFWriteScanline(tif, data + (i << 4), i, 0) < 0) OK = 0; + } + TIFFFlushData(tif); + TIFFClose(tif); + } + if (OK) return 0; else return 10; +} + +}} +changequote([, ])dnl + , ac_cv_libtiff_lzw_compression=yes, ac_cv_libtiff_lzw_compression=no, ac_cv_libtiff_lzw_compression=no) +]) +if test "$ac_cv_libtiff_lzw_compression" = yes; then + AC_DEFINE(HAVE_LIBTIFF_LZW_COMPRESSION,, [Define if libtiff supports LZW compression]) +fi +]) + + +dnl AC_CXX_LIBC_H_EXTERN_C checks if and cause a problem if +dnl libc.h is included extern "C" and math.h is not. This is the case on QNX 6.2.x + +AC_DEFUN([AC_CXX_LIBC_H_EXTERN_C], +[AH_TEMPLATE([INCLUDE_LIBC_H_AS_CXX], [Define if libc.h should be treated as a C++ header]) +AC_CACHE_CHECK(whether libc.h should be treated as a C++ header, +ac_cv_cxx_libc_h_is_cxx, +[AC_LANG_SAVE + AC_LANG_CPLUSPLUS + AC_TRY_COMPILE([#include +extern "C" { +#include +}],[int i = 0], + ac_cv_cxx_libc_h_is_cxx=no, ac_cv_cxx_libc_h_is_cxx=yes) + AC_LANG_RESTORE +]) +if test "$ac_cv_cxx_libc_h_is_cxx" = yes; then + AC_DEFINE(INCLUDE_LIBC_H_AS_CXX,, [Define if libc.h should be treated as a C++ header]) +fi +]) + + +dnl AC_CHECK_POINTER_TYPE checks if a given type is a pointer type. +dnl If header file(s) are given as argument 2, they +dnl are #included in the search. The header files are only included in the search if they +dnl have already been found using the AC_CHECK_HEADERS(header) macro. +dnl Examples: +dnl AC_CHECK_POINTER_TYPE(pthread_d, pthread.h) +dnl AC_CHECK_POINTER_TYPE(void *) + +dnl AC_CHECK_POINTER_TYPE(FUNCTION, HEADER-FILE...) +AC_DEFUN(AC_CHECK_POINTER_TYPE, +[AC_MSG_CHECKING([ifelse([$2], , [if $1 is a pointer type], [if $1 is a pointer type (in $2)])]) +AH_TEMPLATE(AS_TR_CPP(HAVE_POINTER_TYPE_$1), [Define if $1 is a pointer type on your system]) +ifelse([$2], , [ac_includes="" +], +[ac_includes="" +cpp_code="" +if eval "test \"`echo '$ac_cv_cxx_static_cast'`\" = yes"; then + cpp_code="unsigned long l = static_cast(p)" +else + cpp_code="unsigned long l = p" +fi +for ac_header in $2 +do + ac_safe=`echo "$ac_header" | sed 'y%./+-%__p_%'` + if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'}'`\" = yes"; then + ac_includes="$ac_includes +#include<$ac_header>" + fi +done]) +tmp_save_1=`echo $1 | tr ' :' '__'` +AC_CACHE_VAL(ac_cv_pointer_type_$tmp_save_1, +[AC_TRY_COMPILE( +[#ifdef __cplusplus +extern "C" { +#endif +$ac_includes +#ifdef __cplusplus +} +#endif +],[#ifdef __cplusplus +$1 p; $cpp_code +#else +$1 p; unsigned long l = p +#endif +], +eval "ac_cv_pointer_type_$tmp_save_1=no", eval "ac_cv_pointer_type_$tmp_save_1=yes")])dnl +if eval "test \"`echo '$''{'ac_cv_pointer_type_$tmp_save_1'}'`\" = yes"; then + AC_MSG_RESULT(yes) +changequote(, )dnl + ac_tr_prototype=HAVE_POINTER_TYPE_`echo $tmp_save_1 | tr '[a-z]' '[A-Z]'` +changequote([, ])dnl + AC_DEFINE_UNQUOTED([$ac_tr_prototype]) + ifelse([$3], , :, [$3]) +else + AC_MSG_RESULT(no) +fi +]) + + +dnl +dnl CHECK_VLA checks if the C Compiler supports variable-length arrays +dnl +AC_DEFUN(CHECK_VLA, +[AC_MSG_CHECKING([whether variable-length arrays are supported]) +AH_TEMPLATE([HAVE_VLA], [Define if variable-length arrays are supported in C]) +AC_LANG_SAVE +AC_LANG_C +AC_TRY_COMPILE([], [ + int n; int foo[n]; +], +[AC_MSG_RESULT(yes); AC_DEFINE(HAVE_VLA)], +AC_MSG_RESULT(no)) +AC_LANG_RESTORE +]) + + +# AC_TYPEDEF_HELPER(TYPE, +# [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND], +# [INCLUDES]) + +m4_define([AC_TYPEDEF_HELPER], +[AS_VAR_PUSHDEF([ac_Type], [ac_cv_type_$1])dnl +AC_CACHE_CHECK([for $1], ac_Type, +[AC_COMPILE_IFELSE([AC_LANG_PROGRAM([AC_INCLUDES_DEFAULT([$4])], +[if (($1 *) 0) + return 0; +if (sizeof ($1)) + return 0;])], + [AS_VAR_SET(ac_Type, yes)], + [AS_VAR_SET(ac_Type, no)])]) +AS_IF([test AS_VAR_GET(ac_Type) = yes], [$2], [$3])[]dnl +AS_VAR_POPDEF([ac_Type])dnl +])# AC_TYPEDEF_HELPER + +AC_DEFUN(AC_TYPEDEF_HELPER2,[ +AH_VERBATIM([$3[_TYPEDEF]], [#ifdef ]$3[ +typedef $2 $1; +#endif])])# AC_TYPEDEF_HELPER2 + +# +# AC_TYPEDEF(type, default) +# +# This macro works similar to the old (deprecated, pre-2.13) AC_CHECK_TYPE +# macro, but instead of creating a #define for the type if absent, it +# creates a clean typedef. +# +AC_DEFUN(AC_TYPEDEF,[ +m4_define(AC_TYPEDEF_TEMP,[AS_TR_CPP(HAVE_NO_TYPEDEF_$1)]) +AC_TYPEDEF_HELPER2([$1],[$2],AC_TYPEDEF_TEMP) +AC_TYPEDEF_HELPER([$1],[],[AC_DEFINE_UNQUOTED(AC_TYPEDEF_TEMP, [1], [Define `$1' to `$2' if does not define.])]) +])# AC_TYPEDEF + + +# +# AC_LFS64 +# +# This macro checks with the C compiler whether fopen64 is declared in +# when _LARGEFILE64_SOURCE is defined +# +AC_DEFUN([AC_LFS64], +[ AH_TEMPLATE([HAVE_LFS_SUPPORT], [Define if LFS (large file support) is available]) + AH_TEMPLATE([_LARGEFILE64_SOURCE], [Define to enable LFS64 (explicit large file support) if available]) + AC_MSG_CHECKING([for explicit large file support]) + ac_cv_lfs64_support=no + AC_LANG_SAVE + AC_LANG_C + AC_TRY_LINK([#define _LARGEFILE64_SOURCE + #include ],[FILE *f = fopen64("name", "r");], + ac_cv_lfs64_support=yes, ac_cv_lfs64_support=no) + AC_LANG_RESTORE + + if test "$ac_cv_lfs64_support" = yes; then + AC_MSG_RESULT([yes]) + AC_DEFINE(HAVE_LFS_SUPPORT,, [Define if LFS (large file support) is available]) + AC_DEFINE(_LARGEFILE64_SOURCE, 1, [Define to enable LFS64 (explicit large file support) if available]) + else + AC_MSG_RESULT([no]) + fi +]) + + +# MY_AC_SYS_LARGEFILE_TEST_INCLUDES +# Copied from autoconf 2.60 repository of specific tests and renamed +# ------------------------------- +m4_define([MY_AC_SYS_LARGEFILE_TEST_INCLUDES], +[@%:@include + /* Check that off_t can represent 2**63 - 1 correctly. + We can't simply define LARGE_OFF_T to be 9223372036854775807, + since some C++ compilers masquerading as C compilers + incorrectly reject 9223372036854775807. */ +@%:@define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) + int off_t_is_large[[(LARGE_OFF_T % 2147483629 == 721 + && LARGE_OFF_T % 2147483647 == 1) + ? 1 : -1]];[]dnl +]) + + +# MY_AC_SYS_LARGEFILE_MACRO_VALUE(C-MACRO, VALUE, +# CACHE-VAR, +# DESCRIPTION, +# PROLOGUE, [FUNCTION-BODY]) +# Copied from autoconf 2.60 repository of specific tests and renamed +# ---------------------------------------------------------- +m4_define([MY_AC_SYS_LARGEFILE_MACRO_VALUE], +[AC_CACHE_CHECK([for $1 value needed for large files], [$3], +[while :; do + $3=no + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([$5], [$6])], + [ac_cv_lfs_support=yes; break]) + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([@%:@define $1 $2 +$5], [$6])], + [$3=$2; ac_cv_lfs_support=yes; break]) + break +done]) +if test "$$3" != no; then + AC_DEFINE_UNQUOTED([$1], [$$3], [$4]) +fi +rm -f conftest*[]dnl +])# MY_AC_SYS_LARGEFILE_MACRO_VALUE + + +# MY_AC_SYS_LARGEFILE +# ---------------- +# Copied from autoconf 2.60 repository of specific tests and modified +# +# By default, many hosts won't let programs access large files; +# one must use special compiler options to get large-file access to work. +# For more details about this brain damage please see: +# http://www.unix-systems.org/version2/whatsnew/lfs20mar.html +AC_DEFUN([MY_AC_SYS_LARGEFILE], +[AC_CACHE_CHECK([for special C compiler options needed for large files], + ac_cv_sys_largefile_CC, + [ac_cv_sys_largefile_CC=no + if test "$GCC" != yes; then + AC_LANG_SAVE + AC_LANG_C + ac_save_CC=$CC + while :; do + # IRIX 6.2 and later do not support large files by default, + # so use the C compiler's -n32 option if that helps. + AC_LANG_CONFTEST([AC_LANG_PROGRAM([MY_AC_SYS_LARGEFILE_TEST_INCLUDES])]) + AC_COMPILE_IFELSE([], [break]) + CC="$CC -n32" + AC_COMPILE_IFELSE([], [ac_cv_sys_largefile_CC=' -n32'; break]) + break + done + CC=$ac_save_CC + rm -f conftest.$ac_ext + AC_LANG_RESTORE + fi]) + if test "$ac_cv_sys_largefile_CC" != no; then + CC=$CC$ac_cv_sys_largefile_CC + CXX=$CXX$ac_cv_sys_largefile_CC + fi + + ac_cv_lfs64_support=no + AH_TEMPLATE([HAVE_LFS_SUPPORT], [Define if LFS (large file support) is available]) + MY_AC_SYS_LARGEFILE_MACRO_VALUE(_FILE_OFFSET_BITS, 64, + ac_cv_sys_file_offset_bits, + [Number of bits in a file offset, on hosts where this is settable.], + [MY_AC_SYS_LARGEFILE_TEST_INCLUDES]) + MY_AC_SYS_LARGEFILE_MACRO_VALUE(_LARGE_FILES, 1, + ac_cv_sys_large_files, + [Define for large files, on AIX-style hosts.], + [MY_AC_SYS_LARGEFILE_TEST_INCLUDES]) + + if test "$ac_cv_lfs_support" = yes; then + AC_DEFINE(HAVE_LFS_SUPPORT,, [Define if LFS (large file support) is available]) + fi + +])# MY_AC_SYS_LARGEFILE + + +# +# AC_STDIO_NAMESPACE +# +# This macro checks with the C++ compiler whether fopen() in is +# in namespace standard or in global namespace. +# +AC_DEFUN([AC_STDIO_NAMESPACE], +[ AH_TEMPLATE([STDIO_NAMESPACE], [Namespace for ANSI C functions in standard C++ headers]) + ac_cv_stdio_namespace_is_std=no + AC_LANG_SAVE + AC_LANG_CPLUSPLUS + AC_TRY_COMPILE([ +#ifdef USE_STD_CXX_INCLUDES +#include +#else +#include +#endif +],[FILE *f = ::fopen("name", "r");], + ac_cv_stdio_namespace_is_std=no, ac_cv_stdio_namespace_is_std=yes) + AC_LANG_RESTORE + + if test "$ac_cv_stdio_namespace_is_std" = yes; then + AC_DEFINE(STDIO_NAMESPACE,[std::]) + else + AC_DEFINE(STDIO_NAMESPACE,[::]) + fi +]) + + +dnl AC_CHECK_CHARP_STRERROR_R checks if the prototype for strerror_r() +dnl specifies a return type of char * instead of int. This is the case +dnl for the GNU version, whereas the XOPEN (XSI-compliant) version returns int. + +dnl AC_CHECK_CHARP_STRERROR_R(HEADER-FILE..., ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]) +AC_DEFUN(AC_CHECK_CHARP_STRERROR_R, +[AC_MSG_CHECKING([ifelse([$1], , [if strerror_r() returns a char *], +[if strerror_r() returns a char * (in $1)])]) +AH_TEMPLATE([HAVE_CHARP_STRERROR_R], [Define if your system declares the return type of strerror_r + as char * instead of int]) +ifelse([$1], , [ac_includes="" +], +[ac_includes="" +for ac_header in $1 +do + ac_includes="$ac_includes +#include<$ac_header>" +done]) +AC_CACHE_VAL(ac_cv_prototype_charp_strerror_r, +[AC_TRY_COMPILE( +[#ifdef __cplusplus +extern "C" { +#endif +$ac_includes +#ifdef __cplusplus +} +#endif +] +, +[ + char *buf = 0; + int i = strerror_r(0, buf, 100) +], +eval "ac_cv_prototype_charp_strerror_r=no", +eval "ac_cv_prototype_charp_strerror_r=yes" +)]) +if eval "test \"`echo $ac_cv_prototype_charp_strerror_r`\" = yes"; then + AC_MSG_RESULT(yes) +changequote(, )dnl + ac_tr_prototype=HAVE_CHARP_STRERROR_R +changequote([, ])dnl + AC_DEFINE_UNQUOTED($ac_tr_prototype) + ifelse([$2], , :, [$2]) +else + AC_MSG_RESULT(no) + ifelse([$3], , , [$3]) +fi +]) + +dnl +dnl This macro adds the --disable-rpath option to configure +dnl and sets the variable $dcmtk_cv_rpath_works to "no", if needed. +dnl If that option isn't given, the availability of the rpath option is tested +AC_DEFUN([AC_MY_LIB_PATH_RPATH], +[ + AC_CACHE_CHECK([whether -Wl,-rpath is supported], [dcmtk_cv_rpath_works], + [AC_ARG_ENABLE([rpath], + [AS_HELP_STRING([--disable-rpath], [do not hardcode runtime library paths])], + [dcmtk_cv_rpath_works=$enableval], + [old_LDFLAGS="$LDFLAGS" + LDFLAGS="-Wl,-rpath,$srcdir $LDFLAGS" + AC_LINK_IFELSE([AC_LANG_PROGRAM([], [])], + [dcmtk_cv_rpath_works=yes], + [dcmtk_cv_rpath_works=no]) + LDFLAGS="$old_LDFLAGS"]) + ]) +]) + +dnl +dnl This macro adds the option --with-[OPTION_NAME]inc to configure. If this option +dnl is specified, include/ and lib/ are added to CPPFLAGS / LDFLAGS. +dnl +dnl AC_MY_LIB_PATH(OPTION_NAME, LIB_NAME) +AC_DEFUN([AC_MY_LIB_PATH], +[ + AC_REQUIRE([AC_MY_LIB_PATH_RPATH])dnl + m4_pushdef([OPTION], [$1inc])dnl + m4_pushdef([LONGOPTION], [--with-$1inc])dnl + m4_pushdef([LIBNAME], [m4_default([$2], [$1])])dnl + AC_ARG_WITH([OPTION], dnl +dnl The following line is underquoted on purpose, else the help line will be +dnl discarded because it is equal to an earlier help line. +AS_HELP_STRING([LONGOPTION=DIR], [location of LIBNAME includes and libraries]), + [AS_CASE([$withval], + [yes|no], [ + AC_MSG_WARN([LONGOPTION called without argument - will use default]) + ], + [ + if test ! -d ${withval}; then + AC_MSG_ERROR([called with LONGOPTION but LIBNAME base directory ${withval} does not exist or is not a directory.]) + fi + + CPPFLAGS="-I${withval}/include $CPPFLAGS" + LDFLAGS="-L${withval}/lib $LDFLAGS" + if test "x$dcmtk_cv_rpath_works" = "xyes"; then + LDFLAGS="-Wl,-rpath,${withval}/lib $LDFLAGS" + fi + ]) + ])dnl + m4_popdef([OPTION])dnl + m4_popdef([LONGOPTION])dnl + m4_popdef([LIBNAME])dnl +]) + +AC_DEFUN([AC_CHECK_SYNC_FN], +[ + AC_MSG_CHECKING([for $1]) + AC_LINK_IFELSE( + [ + AC_LANG_SOURCE( + [ + int main(){return $1((int *)0, 0);} + ]) + ], + [dcmtk_have_sync_fn=[yes]], + [dcmtk_have_sync_fn=[no]] + ) + if test "$dcmtk_have_sync_fn" = yes; then + AC_MSG_RESULT([yes]) + AC_DEFINE($2,[1],[Define if $1 is available]) + else + AC_MSG_RESULT([no]) + fi +]) + +AC_DEFUN([AC_CHECK_ALIGNOF], +[ + AC_MSG_CHECKING([for __alignof__]) + AC_LINK_IFELSE( + [ + AC_LANG_SOURCE( + [ + int main(){char c[[__alignof__(int)]];return 0;} + ]) + ], + [dcmtk_have_alignof=[yes]], + [dcmtk_have_alignof=[no]] + ) + if test "$dcmtk_have_alignof" = yes; then + AC_MSG_RESULT([yes]) + AC_DEFINE($1,[1],[Define if __alignof__ is available]) + else + AC_MSG_RESULT([no]) + fi +]) + +AC_DEFUN([AC_CHECK_ATTRIBUTE_ALIGNED], +[ + AC_MSG_CHECKING([for __attribute__((aligned))]) + AC_LINK_IFELSE( + [ + AC_LANG_SOURCE( + [ + int main(){__attribute__((aligned(4))) char c[[16]];return 0;} + ]) + ], + [dcmtk_have_attribute_aligned=[yes]], + [dcmtk_have_attribute_aligned=[no]] + ) + if test "$dcmtk_have_attribute_aligned" = yes; then + AC_MSG_RESULT([yes]) + AC_DEFINE($1,[1],[Define if __attribute__((aligned)) is available]) + else + AC_MSG_RESULT([no]) + fi +]) + +AC_DEFUN([AC_CHECK_ATTRIBUTE_ALIGNED_SUPPORTS_TEMPLATES], +[ + AC_MSG_CHECKING([whether __attribute__((aligned)) supports templates]) + AC_LINK_IFELSE( + [ + AC_LANG_SOURCE( + [ + template + struct test { typedef T type __attribute__((aligned(4))); }; + int main() + { + test::type i; + return 0; + } + ]) + ], + [dcmtk_attribute_aligned_supports_templates=[yes]], + [dcmtk_attribute_aligned_supports_templates=[no]] + ) + if test "$dcmtk_attribute_aligned_supports_templates" = yes; then + AC_MSG_RESULT([yes]) + AC_DEFINE($1,[1],[Define if __attribute__((aligned)) supports templates]) + else + AC_MSG_RESULT([no]) + fi +]) + +AC_DEFUN([AC_CHECK_ALIGNAS_SUPPORTS_TYPEDEFS], +[ + AC_MSG_CHECKING([whether alignas supports typedefs]) + AC_LINK_IFELSE( + [ + AC_LANG_SOURCE( + [ + int main() + { + typedef char type[[16]] alignas(4); + return 0; + } + ]) + ], + [dcmtk_alignas_supports_typedefs=[yes]], + [dcmtk_alignas_supports_typedefs=[no]] + ) + if test "$dcmtk_alignas_supports_typedefs" = yes; then + AC_MSG_RESULT([yes]) + AC_DEFINE($1,[1],[Define if alignas supports typedefs]) + else + AC_MSG_RESULT([no]) + fi +]) + +AC_DEFUN([AC_CHECK_DEFAULT_CONSTRUCTOR_DETECTION_VIA_SFINAE], +[ + AC_MSG_CHECKING([whether the compiler supports default constructor detection via SFINAE]) + AC_LINK_IFELSE( + [ + AC_LANG_SOURCE( + [ + struct no_type {}; + struct yes_type {double d;}; + template + struct consume{}; + template + static yes_type sfinae(consume*); + template + static no_type sfinae(...); + struct test { test( int ); }; + int main() + { + return sizeof(sfinae(0)) == sizeof(yes_type); + } + ]) + ], + [dcmtk_default_constructor_detection_via_sfinae=[yes]], + [dcmtk_default_constructor_detection_via_sfinae=[no]] + ) + if test "$dcmtk_default_constructor_detection_via_sfinae" = yes; then + AC_MSG_RESULT([yes]) + AC_DEFINE($1,[1],[Define if the compiler supports default constructor detection via SFINAE]) + else + AC_MSG_RESULT([no]) + fi +]) + + +dnl +dnl This macro checks if a given preprocessor symbol exists and is a string +dnl +dnl AC_MY_SYMBOL_EXISTS(SYMBOL) +AC_DEFUN([AC_MY_SYMBOL_EXISTS], +[ + AH_TEMPLATE([HAVE_$1_MACRO], [Define if the compiler supports $1.])dnl + AC_CACHE_CHECK([for $1 macro], [ac_cv_have_$1_macro], [dnl + AC_TRY_COMPILE([], [const char * func = $1;], [ac_cv_have_$1_macro=yes], [ac_cv_have_$1_macro=no])dnl + ]) + if test "x$ac_cv_have_$1_macro" = "xyes"; then + AC_DEFINE([HAVE_$1_MACRO]) + fi +]) + +dnl +dnl This macro checks if OpenSSL provides the SSL_CTX_get0_param function +dnl +dnl AC_CHECK_SSL_CTX_GET0_PARAM +AC_DEFUN([AC_CHECK_SSL_CTX_GET0_PARAM], +[ + AH_TEMPLATE([HAVE_SSL_CTX_GET0_PARAM], [Define if OpenSSL provides the SSL_CTX_get0_param function.])dnl + SAVELIBS=$LIBS + HAVE_SSL_CTX_GET0_PARAM=yes + LIBS="$LIBS $OPENSSLLIBS" + AC_MSG_CHECKING([whether OpenSSL provides the SSL_CTX_get0_param function]) + AC_COMPILE_IFELSE( + [ + AC_LANG_PROGRAM([[#include ]],[[&SSL_CTX_get0_param;]]) + ], + [ + AC_MSG_RESULT([yes]) + AC_DEFINE([HAVE_SSL_CTX_GET0_PARAM]) + ], + [ + AC_MSG_RESULT([no]) + ]) + LIBS=$SAVELIBS +]) + +dnl +dnl This macro checks if OpenSSL provides the RAND_egd function +dnl +dnl AC_CHECK_RAND_EGD +AC_DEFUN([AC_CHECK_RAND_EGD], +[ + AH_TEMPLATE([HAVE_RAND_EGD], [Define if OpenSSL provides the RAND_egd function.])dnl + SAVELIBS=$LIBS + HAVE_RAND_EGD=yes + LIBS="$LIBS $OPENSSLLIBS" + AC_MSG_CHECKING([whether OpenSSL provides the RAND_egd function]) + AC_COMPILE_IFELSE( + [ + AC_LANG_PROGRAM([[#include ]],[[&RAND_egd;]]) + ], + [ + AC_MSG_RESULT([yes]) + AC_DEFINE([HAVE_RAND_EGD]) + ], + [ + AC_MSG_RESULT([no]) + ]) + LIBS=$SAVELIBS +]) diff --git a/config/arith.cc b/config/arith.cc new file mode 100644 index 00000000..54c6bfe0 --- /dev/null +++ b/config/arith.cc @@ -0,0 +1,591 @@ +/* + * + * Copyright (C) 2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: config + * + * Author: Jan Schlamelcher + * + * Purpose: Query properties of fundamental arithmetic types + * for being used within oflimits.h. + */ + +// Note: This depends on some files of ofstd and osconfig.h, +// although it is part of configure testing itself. +// Therefore, ensure osconfig.h has already been generated +// before this program is used. +#define INCLUDE_CLIMITS +#define INCLUDE_CMATH +#define INCLUDE_CSETJMP +#define INCLUDE_CSIGNAL +#include "ofmath.cc" + +#ifdef HAVE_FENV_H +// For controlling floating point exceptions on Unix like systems. +#include +#endif + +#ifdef __APPLE__ +// For controlling floating point exceptions on OS X. +#include +#endif + +// hackish definition of cout, as we can't depend on +// OFConsole. +#define COUT STD_NAMESPACE cout + +// define sigjmp_buf if it isn't already +#ifndef HAVE_SIGJMP_BUF +typedef jmp_buf sigjmp_buf; +#endif + +// longjmp env (jump destination), ugly global var we +// need to recover from traps. +sigjmp_buf jbuf; + +// signal handler that "jumps back in time" to before +// the error occurred and fixes what has gone wrong +// in 1985. +static void capture( int sig ) +{ +#ifndef _WIN32 + // Unix like systems support this natively + siglongjmp( jbuf, sig ); +#else + // On Windows, we need to employ a workaround that + // only works for floating point exceptions! + _fpreset(); + longjmp( jbuf, sig ); +#endif +} + +static void register_signals() +{ + signal(SIGABRT, &capture); + signal(SIGFPE, &capture); + signal(SIGILL, &capture); + signal(SIGINT, &capture); + signal(SIGSEGV, &capture); + signal(SIGTERM, &capture); +} + +// print to "arith.h" +static void print_define( STD_NAMESPACE ostream& out, + const char* fname, const char* name ) +{ + out << "#define DCMTK_"; + // convert type name to uppercase and replace ' ' by underscore. + for( const char* pch = name; *pch; ++pch ) + out.put( *pch <= 'z' && *pch >= 'a' ? *pch - 'a' + 'A' : *pch == ' ' ? '_' : *pch ); + out << '_' << fname; +} + +// handles output to configure log and to "arith.h" +static int print_flag( STD_NAMESPACE ostream& out, int flag, + const char* fname, const char* name, + int width ) +{ + COUT << STD_NAMESPACE setw(width) << STD_NAMESPACE internal << ( flag ? "yes" : "no" ); + print_define( out, fname, name ); + out << " OF" << ( flag ? "True" : "False" ) << '\n'; + return flag; +} + +static const char all_one[8] = { '\377', '\377', '\377', '\377', '\377', '\377', '\377', '\377' }; + +template +static int test_modulo() +{ + // test if signed, otherwise it is modulo anyway + if( *OFreinterpret_cast( const T*, all_one ) > 0 ) + return 1; + const T max = *OFreinterpret_cast( const T*, all_one ) & ~(T(1) << (sizeof(T) * 8 - 1)); + const T min = T( max + 1 ); + return min < max && min < 0 && max > 0; +} + +template +static int test_trap( const FN& fn ) +{ +#ifndef _WIN32 + // On Unix like systems, we use the + // longjmp-module specifically designed for + // signals. + if( sigsetjmp( jbuf, 1 ) ) +#else + // On Windows, we use the normal longjmp + // that destroys everything and try to fix + // what is left. + if( setjmp( jbuf ) ) +#endif + { + // if a jump occurred, this means fn() + // caused a trap. + return 1; + } +#ifdef _MSC_VER + // On Visual Studio, we use their built-in + // SEH things, they consider to be C++. + __try +#else + // The rest of the world hopefully only + // has normal exceptions. + try +#endif + { + // Call the function. Did it trap? + fn(); + } +#ifdef _MSC_VER + // On Windows, we return 3 if any SEH exception + // occurred. Shall we consider this a trap, + // although it was really an exception? + // I don't know, for now it's yes. + __except(1){return 3;} +#else + // The rest of the world returns 2, which + // means "normal exception". + catch(...){return 2;} +#endif + // Nothing happened, so we return 0, for + // "nothing happened". Note: since MinGW's + // crazy SEH things are crazy, MinGW will always + // execute what is written in the brackets following + // __except1, and NEVER see this return statement. + return 0; +} + +template +static void divide_by_zero() +{ + // Note: we can't just do 1 / 0, since + // some compilers might optimize that + // away or emit compile-time errors. + volatile T t0 = 1; + volatile T t1 = 0; + t0 /= t1; +} + +// gathers and prints information for integer types +template +static void inspect( STD_NAMESPACE ostream& out, const char* name ) +{ + COUT << "-- " << STD_NAMESPACE left << STD_NAMESPACE setw(14) << name; + print_flag( out, test_trap( ÷_by_zero ), "TRAPS", name, 7 ); + print_flag( out, test_modulo(), "MODULO", name, 7 ); + COUT << OFendl; +} + +// print a constant's binary representation as a string, so it can be loaded +// instead of being calculated when needed +template +static void print_binary( STD_NAMESPACE ostream& out, const char* pname, const char* name, const T& t ) +{ + print_define( out, pname, name ); + out << " *OFreinterpret_cast( const " << name << "*, \""; + for( unsigned ui = 0; ui < sizeof(T); ++ui ) + out << '\\' << STD_NAMESPACE oct << STD_NAMESPACE setw(3) << STD_NAMESPACE right << STD_NAMESPACE setfill( '0' ) + << unsigned(((unsigned char*)&t)[ui]) << STD_NAMESPACE dec; + out << "\" )\n"; +} + +// try to create an infinite value and use whatever means +// to detect if it really is infinite +template +static int test_inf( STD_NAMESPACE ostream& out, const char* name ) +{ + const T t( HUGE_VAL ); + const int has_inf = print_flag + ( + out, + OFStandard::isinf(t), + "HAS_INFINITY", + name, + 7 + ); + print_binary( out, "INFINITY", name, t ); + return has_inf; +} + +template +static T guess_qnan() +{ +#ifdef NAN + // use NAN if available + return T( NAN ); +#else + // else do a barrel roll + T t( 0.0 ); + return t / t; +#endif +} + +template +static int test_qnan( STD_NAMESPACE ostream& out, const char* name ) +{ + const T t = guess_qnan(); + const int has_qnan = print_flag + ( + out, + OFStandard::isnan( t ), + "HAS_QUIET_NAN", + name, + 7 + ); + print_binary( out, "QUIET_NAN", name, t ); + return has_qnan; +} + +template +struct guess; + +template<> +struct guess +{ + // There is no way to create a signaling NaN employing only arithmetic + // operations. So we assume we have IEC-559 floating point types + // and convert the quiet NaNs we created to signaling NaNs by flipping + // the bits that would need to be flipped if it really were IEC-559 floats. + static const float& snan() + { + static float f = guess_qnan(); + ((unsigned char*)&f)[2] &= 0xbf; + ((unsigned char*)&f)[0] |= 0x01; + return f; + } + + static float denorm_min() + { + return float( ldexp( 1.0f, FLT_MIN_EXP - FLT_MANT_DIG ) ); + } + + static float denorm_max() + { + return FLT_MIN / 2; + } + + static float epsilon() + { + return FLT_EPSILON; + } +}; + +template<> +struct guess +{ + // There is no way to create a signaling NaN employing only arithmetic + // operations. So we assume we have IEC-559 floating point types + // and convert the quiet NaNs we created to signaling NaNs by flipping + // the bits that would need to be flipped if it really were IEC-559 floats. + static const double& snan() + { + static double d = guess_qnan(); + ((unsigned char*)&d)[6] &= 0xf7; + ((unsigned char*)&d)[0] |= 0x01; + return d; + } + + static double denorm_min() + { + return double( ldexp( 1.0, DBL_MIN_EXP - DBL_MANT_DIG ) ); + } + + static double denorm_max() + { + return DBL_MIN / 2; + } + + static double epsilon() + { + return DBL_EPSILON; + } +}; + +template +static void provoke_snan() +{ + // Enable floating point exceptions, Windows and Unix version. +#ifdef HAVE_WINDOWS_H + _clearfp(); + _controlfp( _controlfp(0,0) & ~_EM_INVALID, _MCW_EM ); +#elif defined(__APPLE__) + _MM_SET_EXCEPTION_MASK( _MM_GET_EXCEPTION_MASK() & ~_MM_MASK_INVALID ); +#elif defined(HAVE_FENV_H) + feenableexcept( FE_INVALID ); +#endif + // Visual Studio will emit an exception the moment + // we assign a signaling NaN to another float variable + // and convert it to a quiet NaN. + volatile T t = guess::snan(); + // Other compilers will trigger only if we use + // arithmetics. + ++t; +} + +template +static int test_snan( STD_NAMESPACE ostream& out, const char* name ) +{ + // Create signaling NaNs and test if they really are signaling NaNs + const T& t = guess::snan(); + int flag = OFStandard::isnan( t ) && test_trap( &provoke_snan ); + // Disable floating point exceptions that have been enabled for the test, + // Windows and Unix version. +#ifdef HAVE_WINDOWS_H + _clearfp(); + _controlfp( _controlfp(0,0) | _EM_INVALID, _MCW_EM ); +#elif defined(HAVE_FENV_H) + feclearexcept( FE_INVALID ); +#ifdef __APPLE__ + _MM_SET_EXCEPTION_MASK( _MM_GET_EXCEPTION_MASK() | _MM_MASK_INVALID ); +#else + fedisableexcept( FE_INVALID ); +#endif +#endif + // Print and return the result + print_flag + ( + out, + flag, + "HAS_SIGNALING_NAN", + name, + 7 + ); + print_binary( out, "SIGNALING_NAN", name, t ); + return flag; +} + +template +static void test_iec559( STD_NAMESPACE ostream& out, const char* name, int reqs ) +{ + // Assume we have IEC-559 floats if the appropriate macro was defined, + // or if infinity and both kinds of NaNs are supported and the characteristics + // of double are what we expect them to be. + print_flag + ( + out, +#if defined(__STDC_IEC_559__) || (DBL_DIG == 15 && DBL_MANT_DIG == 53 && DBL_MAX_10_EXP == 308 && DBL_MAX_EXP == 1024 && DBL_MIN_10_EXP == -307 && DBL_MIN_EXP == -1021) + reqs, +#else + 0, +#endif + "IS_IEC559", + name, + 7 + ); +} + +#ifndef _WIN32 +template +static int is_subnormal( T t ) +{ + return !STD_NAMESPACE isnormal( t ); +} +#else +static int is_subnormal( float f ) +{ +// Wine does not implement _fpclassf, so don't use it when cross compiling for Windows +// (Wine would emit an exception at runtime, so it's hard to test for _fpclassf availability) +#if defined(HAVE_PROTOTYPE__FPCLASSF) && !( defined(DCMTK_CROSS_COMPILING) && defined(_WIN32) ) + return ( _fpclassf( f ) & ( _FPCLASS_ND | _FPCLASS_PD ) ) != 0; +#else + return (((unsigned char*)&f)[(FLT_MANT_DIG - 1) / 8] & (1u << ((FLT_MANT_DIG - 1) % 8))) == 0; +#endif +} + +static int is_subnormal( double d ) +{ + return ( _fpclass( d ) & ( _FPCLASS_ND | _FPCLASS_PD ) ) != 0; +} +#endif + +template +static void test_subnormal( STD_NAMESPACE ostream& out, const char* name ) +{ +#ifdef HAVE_WINDOWS_H + _clearfp(); + _controlfp( _EM_DENORMAL | _EM_UNDERFLOW | _EM_INEXACT, _MCW_EM ); +#endif + const T denorm = guess::denorm_min(); + const int flag = is_subnormal( denorm ); + COUT << STD_NAMESPACE setw(7) << STD_NAMESPACE internal << ( flag ? "yes" : "no" ); + print_define( out, "HAS_DENORM", name ); + out << " OFdenorm_" << ( flag ? "pre" : "ab" ) << "sent\n"; + print_binary( out, "DENORM_MIN", name, denorm ); +} + +template +static void test_tinyness_before( STD_NAMESPACE ostream& out, const char* name ) +{ + volatile const T denorm_max = guess::denorm_max(); + volatile const T mult = T( 1.0 ) + guess::epsilon(); + +#ifdef HAVE_WINDOWS_H + _clearfp(); +#elif defined(HAVE_FENV_H) + feclearexcept( FE_ALL_EXCEPT ); +#endif + + volatile T result = denorm_max * mult; + (void)result; + + print_flag + ( + out, +#ifdef HAVE_WINDOWS_H + _statusfp() & _EM_UNDERFLOW, +#elif defined(HAVE_FENV_H) + fetestexcept( FE_UNDERFLOW ), +#else + 0, +#endif + "TINYNESS_BEFORE", + name, + 7 + ); +} + +template +static void test_denorm_loss( STD_NAMESPACE ostream& out, const char* name ) +{ + volatile T t = guess::denorm_min() * 3; + +#ifdef HAVE_WINDOWS_H + _clearfp(); +#elif defined(HAVE_FENV_H) + feclearexcept( FE_ALL_EXCEPT ); +#endif + + t /= 2; + + print_flag + ( + out, +#ifdef HAVE_WINDOWS_H + _statusfp() & _EM_UNDERFLOW, +#elif defined(HAVE_FENV_H) + fetestexcept( FE_UNDERFLOW ), +#else + 0, +#endif + "HAS_DENORM_LOSS", + name, + 7 + ); +} + +#ifdef HAVE_WINDOWS_H +// MinGW's crazy SEH stuff doesn't work on all MinGW "distributions" +// This is an even more ugly fallback implementation that seems to +// work for now +LONG WINAPI consume_seh_problems( struct _EXCEPTION_POINTERS* ) +{ + _fpreset(); + _clearfp(); + longjmp( jbuf, 0 ); + return EXCEPTION_CONTINUE_SEARCH; +} +#endif + +int main( int argc, char** argv ) +{ +#ifdef HAVE_WINDOWS_H + // Activate the fallback workaround, it will only be used + // if the SEH exceptions can't be caught "the right way" + SetErrorMode( SEM_FAILCRITICALERRORS ); + SetUnhandledExceptionFilter( consume_seh_problems ); +#endif + + COUT << "Inspecting fundamental arithmetic types... " << OFendl; + if( argc != 2 ) + { + STD_NAMESPACE cerr << "-- " << "Error: missing destination file " + << "to store collected information." << OFendl; + return 1; + } + + STD_NAMESPACE ofstream out( argv[1] ); + + out << "#ifndef CONFIG_ARITH_H" << '\n'; + out << "#define CONFIG_ARITH_H" << '\n'; + out << '\n'; + + COUT << "--" << OFendl; + + COUT << "-- " << STD_NAMESPACE setfill( ' ' ) << STD_NAMESPACE setw(17) << ' ' + << STD_NAMESPACE setw(7) << STD_NAMESPACE internal << "TRAPS" + << STD_NAMESPACE setw(7) << STD_NAMESPACE internal << "MODULO" << OFendl; + + register_signals(); + inspect( out, "char" ); + inspect( out, "signed char" ); + inspect( out, "unsigned char" ); + inspect( out, "signed short" ); + inspect( out, "unsigned short" ); + inspect( out, "signed int" ); + inspect( out, "unsigned int" ); + inspect( out, "signed long" ); + inspect( out, "unsigned long" ); + + COUT << "--" << OFendl; + + COUT << "-- " << STD_NAMESPACE setfill( ' ' ) << STD_NAMESPACE setw(18) << ' ' + << STD_NAMESPACE setw(7) << STD_NAMESPACE internal << "float" + << STD_NAMESPACE setw(7) << STD_NAMESPACE internal << "double" << OFendl; + + COUT << STD_NAMESPACE setw(20) << STD_NAMESPACE left << "-- TRAPS"; + print_flag( out, test_trap( ÷_by_zero ), "TRAPS", "float", 7 ); + print_flag( out, test_trap( ÷_by_zero ), "TRAPS", "double", 7 ); + COUT << OFendl; + + COUT << STD_NAMESPACE setw(20) << STD_NAMESPACE left << "-- HAS INFINITY"; + const int finf = test_inf( out, "float" ); + const int dinf = test_inf( out, "double" ); + COUT << OFendl; + + COUT << STD_NAMESPACE setw(20) << STD_NAMESPACE left << "-- QUIET NAN"; + const int fqnan = test_qnan( out, "float" ); + const int dqnan = test_qnan( out, "double" ); + COUT << OFendl; + + COUT << STD_NAMESPACE setw(20) << STD_NAMESPACE left << "-- SIGNALING NAN"; + const int fsnan = test_snan( out, "float" ); + const int dsnan = test_snan( out, "double" ); + COUT << OFendl; + + COUT << STD_NAMESPACE setw(20) << STD_NAMESPACE left << "-- IEC-559"; + test_iec559( out, "float", finf && fqnan && fsnan ); + test_iec559( out, "double", dinf && dqnan && dsnan ); + COUT << OFendl; + + COUT << STD_NAMESPACE setw(20) << STD_NAMESPACE left << "-- HAS DENORM"; + test_subnormal( out, "float" ); + test_subnormal( out, "double" ); + COUT << OFendl; + + COUT << STD_NAMESPACE setw(20) << STD_NAMESPACE left << "-- TINYNESS BEFORE"; + test_tinyness_before( out, "float" ); + test_tinyness_before( out, "double" ); + COUT << OFendl; + + COUT << STD_NAMESPACE setw(20) << STD_NAMESPACE left << "-- DENORM LOSS"; + test_denorm_loss( out, "float" ); + test_denorm_loss( out, "double" ); + COUT << OFendl; + + COUT << "--"; + + out << "#define DCMTK_ROUND_STYLE " << FLT_ROUNDS << '\n'; + out << '\n'; + out << "#endif // CONFIG_ARITH_H" << '\n'; + + return 0; +} diff --git a/config/autoall b/config/autoall new file mode 100755 index 00000000..1c6e4b8f --- /dev/null +++ b/config/autoall @@ -0,0 +1,29 @@ +# !/bin/sh + +autoheader +autoconf +autoconf confmod.in > confmod + +sed -e 's|^datadir=.*|datadir='\''${datarootdir}/dcmtk'\''|' \ + -e 's|^sysconfdir=.*|sysconfdir='\''${prefix}/etc/dcmtk'\''|' \ + -e 's|^docdir=.*|docdir='\''${datarootdir}/doc/dcmtk'\''|' \ + -e 's|^htmldir=.*|htmldir='\''${docdir}/html'\''|' \ + -e 's|^ --datadir=DIR.*| --datadir=DIR read-only arch.-independent data [DATAROOTDIR/dcmtk]|' \ + -e 's|^ --sysconfdir=DIR.*| --sysconfdir=DIR read-only single-machine data [PREFIX/etc/dcmtk]|' \ + -e 's|^ --docdir=DIR.*| --docdir=DIR documentation root [DATAROOTDIR/doc/dcmtk]|' \ + -e 's|^ --htmldir=DIR.*| --htmldir=DIR html documentation [DOCDIR/html]|' \ + configure > configure.tmp +mv configure.tmp configure +chmod a+x configure + +sed -e 's|^datadir=.*|datadir='\''${datarootdir}/dcmtk'\''|' \ + -e 's|^sysconfdir=.*|sysconfdir='\''${prefix}/etc/dcmtk'\''|' \ + -e 's|^docdir=.*|docdir='\''${datarootdir}/doc/dcmtk'\''|' \ + -e 's|^htmldir=.*|htmldir='\''${docdir}/html'\''|' \ + -e 's|^ --datadir=DIR.*| --datadir=DIR read-only arch.-independent data [DATAROOTDIR/dcmtk]|' \ + -e 's|^ --sysconfdir=DIR.*| --sysconfdir=DIR read-only single-machine data [PREFIX/etc/dcmtk]|' \ + -e 's|^ --docdir=DIR.*| --docdir=DIR documentation root [DATAROOTDIR/doc/dcmtk]|' \ + -e 's|^ --htmldir=DIR.*| --htmldir=DIR html documentation [DOCDIR/html]|' \ + confmod > confmod.tmp +mv confmod.tmp confmod +chmod a+x confmod diff --git a/config/changext b/config/changext new file mode 100755 index 00000000..3903081c --- /dev/null +++ b/config/changext @@ -0,0 +1,149 @@ +#! /bin/sh +# +# This script changes the file name extension for all C++ files +# from .cc to a different extension. This is useful for C++ compilers +# which do note recognise ".cc" as a valid extension for C++ code. +# For instance, the IBM xlC compiler on AIX 3.x requires ".C" and +# older versions of Microsoft Visual C++ need ".cpp" or ".cxx". +# +# The script must be called from the "dcmtk/" directory, e.g. +# cd dcmtk +# config/changext cpp +# +# The first command line argument (if given) overrides the +# new extension (default: C). +# You must not specify the dot preceding the extension. +# +# The second command line argument (if given) overrides the +# old extension (default: cc). This is useful if you want +# to "rename back". +# +# Author: Marco Eichelberg, (C) 1997-2011 Kuratorium OFFIS e.V. +# + +newext=${1-C} +oldext=${2-cc} + +echo "renaming C++ files from .$oldext to .$newext" +for file in `find . -name "*.$oldext" -print` +do + newfile=`echo $file | sed -e "s/\.$oldext/\.$newext/g"` + `mv $file $newfile` +done + +if [ -f dcmjpls/apps/dcml2pnm.$newext ] ; then + echo "updating implementation include in dcml2pnm.$newext" + `cat dcmjpls/apps/dcml2pnm.$newext | sed -e "s/#include \"\.\.\/\.\.\/dcmimage\/apps\/dcm2pnm\.$oldext\"/#include \"..\/..\/dcmimage\/apps\/dcm2pnm.$newext\"/g" >dcmjpls/apps/dcml2pnm.new` + `mv dcmjpls/apps/dcml2pnm.new dcmjpls/apps/dcml2pnm.$newext` +fi + +if [ -f dcmjpeg/apps/dcmj2pnm.$newext ] ; then + echo "updating implementation include in dcmj2pnm.$newext" + `cat dcmjpeg/apps/dcmj2pnm.$newext | sed -e "s/#include \"\.\.\/\.\.\/dcmimage\/apps\/dcm2pnm\.$oldext\"/#include \"..\/..\/dcmimage\/apps\/dcm2pnm.$newext\"/g" >dcmjpeg/apps/dcmj2pnm.new` + `mv dcmjpeg/apps/dcmj2pnm.new dcmjpeg/apps/dcmj2pnm.$newext` +fi + +if [ -f dcmjpeg/apps/dcmmkdir.$newext ] ; then + echo "updating implementation include in dcmmkdir.$newext" + `cat dcmjpeg/apps/dcmmkdir.$newext | sed -e "s/#include \"\.\.\/\.\.\/dcmdata\/apps\/dcmgpdir\.$oldext\"/#include \"..\/..\/dcmdata\/apps\/dcmgpdir.$newext\"/g" >dcmjpeg/apps/dcmmkdir.new` + `mv dcmjpeg/apps/dcmmkdir.new dcmjpeg/apps/dcmmkdir.$newext` +fi + +if [ -f dcmeval/apps/tcpsrv_e.$newext ] ; then + echo "updating implementation include in tcpsrv_e.$newext" + `cat dcmeval/apps/tcpsrv_e.$newext | sed -e "s/#include \"\.\.\/\.\.\/dcmprscp\/apps\/tcpsrv\.$oldext\"/#include \"..\/..\/dcmprscp\/apps\/tcpsrv.$newext\"/g" >dcmeval/apps/tcpsrv_e.new` + `mv dcmeval/apps/tcpsrv_e.new dcmeval/apps/tcpsrv_e.$newext` +fi + +if [ -f dcmeval/apps/tcpprt_e.$newext ] ; then + echo "updating implementation include in tcpprt_e.$newext" + `cat dcmeval/apps/tcpprt_e.$newext | sed -e "s/#include \"\.\.\/\.\.\/dcmprint\/apps\/tcpprt\.$oldext\"/#include \"..\/..\/dcmprint\/apps\/tcpprt.$newext\"/g" >dcmeval/apps/tcpprt_e.new` + `mv dcmeval/apps/tcpprt_e.new dcmeval/apps/tcpprt_e.$newext` +fi + +if [ -f dcmeval/apps/dcmcjp2k_e.$newext ] ; then + echo "updating implementation include in dcmcjp2k_e.$newext" + `cat dcmeval/apps/dcmcjp2k_e.$newext | sed -e "s/#include \"\.\.\/\.\.\/dcmjp2k\/apps\/dcmcjp2k\.$oldext\"/#include \"..\/..\/dcmjp2k\/apps\/dcmcjp2k.$newext\"/g" >dcmeval/apps/dcmcjp2k_e.new` + `mv dcmeval/apps/dcmcjp2k_e.new dcmeval/apps/dcmcjp2k_e.$newext` +fi + +if [ -f dcmeval/apps/dcmdjp2k_e.$newext ] ; then + echo "updating implementation include in dcmdjp2k_e.$newext" + `cat dcmeval/apps/dcmdjp2k_e.$newext | sed -e "s/#include \"\.\.\/\.\.\/dcmjp2k\/apps\/dcmdjp2k\.$oldext\"/#include \"..\/..\/dcmjp2k\/apps\/dcmdjp2k.$newext\"/g" >dcmeval/apps/dcmdjp2k_e.new` + `mv dcmeval/apps/dcmdjp2k_e.new dcmeval/apps/dcmdjp2k_e.$newext` +fi + +if [ -f dcmqrdbx/apps/dcmqrscq.$newext ] ; then + echo "updating implementation include in dcmqrscq.$newext" + `cat dcmqrdbx/apps/dcmqrscq.$newext | sed -e "s/#include \"\.\.\/\.\.\/dcmqrdb\/apps\/dcmqrscp\.$oldext\"/#include \"..\/..\/dcmqrdb\/apps\/dcmqrscp.$newext\"/g" >dcmqrdbx/apps/dcmqrscq.new` + `mv dcmqrdbx/apps/dcmqrscq.new dcmqrdbx/apps/dcmqrscq.$newext` +fi + +if [ -f dcmeval/apps/ppsscpfs_e.$newext ] ; then + echo "updating implementation include in ppsscpfs_e.$newext" + `cat dcmeval/apps/ppsscpfs_e.$newext | sed -e "s/#include \"\.\.\/\.\.\/dcmpps\/apps\/ppsscpfs\.$oldext\"/#include \"..\/..\/dcmpps\/apps\/ppsscpfs.$newext\"/g" | sed -e "s/#include \"\.\.\/\.\.\/dcmpps\/apps\/ppscefs\.$oldext\"/#include \"..\/..\/dcmpps\/apps\/ppscefs.$newext\"/g" >dcmeval/apps/ppsscpfs_e.new` + `mv dcmeval/apps/ppsscpfs_e.new dcmeval/apps/ppsscpfs_e.$newext` +fi + +if [ -f dcmeval/apps/ppsmgr_e.$newext ] ; then + echo "updating implementation include in ppsmgr_e.$newext" + `cat dcmeval/apps/ppsmgr_e.$newext | sed -e "s/#include \"\.\.\/\.\.\/dcmpps\/apps\/ppsmgr\.$oldext\"/#include \"..\/..\/dcmpps\/apps\/ppsmgr.$newext\"/g" | sed -e "s/#include \"\.\.\/\.\.\/dcmpps\/apps\/ppsmgrce\.$oldext\"/#include \"..\/..\/dcmpps\/apps\/ppsmgrce.$newext\"/g" >dcmeval/apps/ppsmgr_e.new` + `mv dcmeval/apps/ppsmgr_e.new dcmeval/apps/ppsmgr_e.$newext` +fi + +if [ -f dcmeval/apps/pawscpfs_e.$newext ] ; then + echo "updating implementation include in pawscpfs_e.$newext" + `cat dcmeval/apps/pawscpfs_e.$newext | sed -e "s/#include \"\.\.\/\.\.\/dcmppswm\/apps\/pawscpfs\.$oldext\"/#include \"..\/..\/dcmppswm\/apps\/pawscpfs.$newext\"/g" | sed -e "s/#include \"\.\.\/\.\.\/dcmppswm\/apps\/pawcefs\.$oldext\"/#include \"..\/..\/dcmppswm\/apps\/pawcefs.$newext\"/g" >dcmeval/apps/pawscpfs_e.new` + `mv dcmeval/apps/pawscpfs_e.new dcmeval/apps/pawscpfs_e.$newext` +fi + +if [ -f dcmeval/apps/dcmanon_e.$newext ] ; then + echo "updating implementation include in dcmanon_e.$newext" + `cat dcmeval/apps/dcmanon_e.$newext | sed -e "s/#include \"\.\.\/\.\.\/dcmmisc\/apps\/dcmanon\.$oldext\"/#include \"..\/..\/dcmmisc\/apps\/dcmanon.$newext\"/g" >dcmeval/apps/dcmanon_e.new` + `mv dcmeval/apps/dcmanon_e.new dcmeval/apps/dcmanon_e.$newext` +fi + +if [ -f dcmmisc/apps/detecscp.$newext ] ; then + echo "updating implementation include in detecscp.$newext" + `cat dcmmisc/apps/detecscp.$newext | sed -e "s/#include \"\.\.\/\.\.\/dcmnet\/apps\/storescp\.$oldext\"/#include \"..\/..\/dcmnet\/apps\/storescp.$newext\"/g" >dcmmisc/apps/detecscp.new` + `mv dcmmisc/apps/detecscp.new dcmmisc/apps/detecscp.$newext` +fi + +if [ -f dcmmisc/apps/detecscu.$newext ] ; then + echo "updating implementation include in detecscu.$newext" + `cat dcmmisc/apps/detecscu.$newext | sed -e "s/#include \"\.\.\/\.\.\/dcmnet\/apps\/echoscu\.$oldext\"/#include \"..\/..\/dcmnet\/apps\/echoscu.$newext\"/g" >dcmmisc/apps/detecscu.new` + `mv dcmmisc/apps/detecscu.new dcmmisc/apps/detecscu.$newext` +fi + +if [ -f dcmeval/apps/mppsscu_e.$newext ] ; then + echo "updating implementation include in mppsscu_e.$newext" + `cat dcmeval/apps/mppsscu_e.$newext | sed -e "s/#include \"\.\.\/\.\.\/dcmppscu\/apps\/mppsscu\.$oldext\"/#include \"..\/..\/dcmppscu\/apps\/mppsscu.$newext\"/g" >dcmeval/apps/mppsscu_e.new` + `mv dcmeval/apps/mppsscu_e.new dcmeval/apps/mppsscu_e.$newext` +fi + +if [ -f dcmeval/apps/stcomscu_e.$newext ] ; then + echo "updating implementation include in stcomscu_e.$newext" + `cat dcmeval/apps/stcomscu_e.$newext | sed -e "s/#include \"\.\.\/\.\.\/dcmstcom\/apps\/stcomscu\.$oldext\"/#include \"..\/..\/dcmstcom\/apps\/stcomscu.$newext\"/g" >dcmeval/apps/stcomscu_e.new` + `mv dcmeval/apps/stcomscu_e.new dcmeval/apps/stcomscu_e.$newext` +fi + +echo "updating makefiles" +for file in `find . -name "Makefile*" -print` +do + `cat $file | sed -e "s/\.$oldext/\.$newext/g" >$file.new` + `mv $file.new $file` +done + +if [ -f CMake/GenerateDCMTKConfigure.cmake ] ; then + echo "updating CMake/GenerateDCMTKConfigure.cmake" + cat CMake/GenerateDCMTKConfigure.cmake | sed -e "s/\.$oldext/.$newext/g" > CMake/GenerateDCMTKConfigure.cmake.new + mv CMake/GenerateDCMTKConfigure.cmake.new CMake/GenerateDCMTKConfigure.cmake +fi + +if [ -f CMake/dcmtkMacros.cmake ] ; then + echo "updating CMake/dcmtkMacros.cmake" + cat CMake/dcmtkMacros.cmake | sed -e "s/\.$oldext/.$newext/g" > CMake/dcmtkMacros.cmake.new + mv CMake/dcmtkMacros.cmake.new CMake/dcmtkMacros.cmake +fi + +echo "done." diff --git a/config/config.guess b/config/config.guess new file mode 100755 index 00000000..d622a44e --- /dev/null +++ b/config/config.guess @@ -0,0 +1,1530 @@ +#! /bin/sh +# Attempt to guess a canonical system name. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, +# 2011, 2012 Free Software Foundation, Inc. + +timestamp='2012-02-10' + +# This file is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see . +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + + +# Originally written by Per Bothner. Please send patches (context +# diff format) to and include a ChangeLog +# entry. +# +# This script attempts to guess a canonical system name similar to +# config.sub. If it succeeds, it prints the system name on stdout, and +# exits with 0. Otherwise, it exits with 1. +# +# You can get the latest version of this script from: +# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] + +Output the configuration name of the system \`$me' is run on. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.guess ($timestamp) + +Originally written by Per Bothner. +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, +2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 +Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" >&2 + exit 1 ;; + * ) + break ;; + esac +done + +if test $# != 0; then + echo "$me: too many arguments$help" >&2 + exit 1 +fi + +trap 'exit 1' 1 2 15 + +# CC_FOR_BUILD -- compiler used by this script. Note that the use of a +# compiler to aid in system detection is discouraged as it requires +# temporary files to be created and, as you can see below, it is a +# headache to deal with in a portable fashion. + +# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still +# use `HOST_CC' if defined, but it is deprecated. + +# Portable tmp directory creation inspired by the Autoconf team. + +set_cc_for_build=' +trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; +trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; +: ${TMPDIR=/tmp} ; + { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || + { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || + { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || + { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; +dummy=$tmp/dummy ; +tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; +case $CC_FOR_BUILD,$HOST_CC,$CC in + ,,) echo "int x;" > $dummy.c ; + for c in cc gcc c89 c99 ; do + if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then + CC_FOR_BUILD="$c"; break ; + fi ; + done ; + if test x"$CC_FOR_BUILD" = x ; then + CC_FOR_BUILD=no_compiler_found ; + fi + ;; + ,,*) CC_FOR_BUILD=$CC ;; + ,*,*) CC_FOR_BUILD=$HOST_CC ;; +esac ; set_cc_for_build= ;' + +# This is needed to find uname on a Pyramid OSx when run in the BSD universe. +# (ghazi@noc.rutgers.edu 1994-08-24) +if (test -f /.attbin/uname) >/dev/null 2>&1 ; then + PATH=$PATH:/.attbin ; export PATH +fi + +UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown +UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown +UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown +UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown + +# Note: order is significant - the case branches are not exclusive. + +case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in + *:NetBSD:*:*) + # NetBSD (nbsd) targets should (where applicable) match one or + # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*, + # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently + # switched to ELF, *-*-netbsd* would select the old + # object file format. This provides both forward + # compatibility and a consistent mechanism for selecting the + # object file format. + # + # Note: NetBSD doesn't particularly care about the vendor + # portion of the name. We always set it to "unknown". + sysctl="sysctl -n hw.machine_arch" + UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ + /usr/sbin/$sysctl 2>/dev/null || echo unknown)` + case "${UNAME_MACHINE_ARCH}" in + armeb) machine=armeb-unknown ;; + arm*) machine=arm-unknown ;; + sh3el) machine=shl-unknown ;; + sh3eb) machine=sh-unknown ;; + sh5el) machine=sh5le-unknown ;; + *) machine=${UNAME_MACHINE_ARCH}-unknown ;; + esac + # The Operating System including object format, if it has switched + # to ELF recently, or will in the future. + case "${UNAME_MACHINE_ARCH}" in + arm*|i386|m68k|ns32k|sh3*|sparc|vax) + eval $set_cc_for_build + if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ELF__ + then + # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). + # Return netbsd for either. FIX? + os=netbsd + else + os=netbsdelf + fi + ;; + *) + os=netbsd + ;; + esac + # The OS release + # Debian GNU/NetBSD machines have a different userland, and + # thus, need a distinct triplet. However, they do not need + # kernel version information, so it can be replaced with a + # suitable tag, in the style of linux-gnu. + case "${UNAME_VERSION}" in + Debian*) + release='-gnu' + ;; + *) + release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + ;; + esac + # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: + # contains redundant information, the shorter form: + # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. + echo "${machine}-${os}${release}" + exit ;; + *:OpenBSD:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` + echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} + exit ;; + *:ekkoBSD:*:*) + echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} + exit ;; + *:SolidBSD:*:*) + echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} + exit ;; + macppc:MirBSD:*:*) + echo powerpc-unknown-mirbsd${UNAME_RELEASE} + exit ;; + *:MirBSD:*:*) + echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} + exit ;; + alpha:OSF1:*:*) + case $UNAME_RELEASE in + *4.0) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` + ;; + *5.*) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` + ;; + esac + # According to Compaq, /usr/sbin/psrinfo has been available on + # OSF/1 and Tru64 systems produced since 1995. I hope that + # covers most systems running today. This code pipes the CPU + # types through head -n 1, so we only detect the type of CPU 0. + ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` + case "$ALPHA_CPU_TYPE" in + "EV4 (21064)") + UNAME_MACHINE="alpha" ;; + "EV4.5 (21064)") + UNAME_MACHINE="alpha" ;; + "LCA4 (21066/21068)") + UNAME_MACHINE="alpha" ;; + "EV5 (21164)") + UNAME_MACHINE="alphaev5" ;; + "EV5.6 (21164A)") + UNAME_MACHINE="alphaev56" ;; + "EV5.6 (21164PC)") + UNAME_MACHINE="alphapca56" ;; + "EV5.7 (21164PC)") + UNAME_MACHINE="alphapca57" ;; + "EV6 (21264)") + UNAME_MACHINE="alphaev6" ;; + "EV6.7 (21264A)") + UNAME_MACHINE="alphaev67" ;; + "EV6.8CB (21264C)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8AL (21264B)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8CX (21264D)") + UNAME_MACHINE="alphaev68" ;; + "EV6.9A (21264/EV69A)") + UNAME_MACHINE="alphaev69" ;; + "EV7 (21364)") + UNAME_MACHINE="alphaev7" ;; + "EV7.9 (21364A)") + UNAME_MACHINE="alphaev79" ;; + esac + # A Pn.n version is a patched version. + # A Vn.n version is a released version. + # A Tn.n version is a released field test version. + # A Xn.n version is an unreleased experimental baselevel. + # 1.2 uses "1.2" for uname -r. + echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + # Reset EXIT trap before exiting to avoid spurious non-zero exit code. + exitcode=$? + trap '' 0 + exit $exitcode ;; + Alpha\ *:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # Should we change UNAME_MACHINE based on the output of uname instead + # of the specific Alpha model? + echo alpha-pc-interix + exit ;; + 21064:Windows_NT:50:3) + echo alpha-dec-winnt3.5 + exit ;; + Amiga*:UNIX_System_V:4.0:*) + echo m68k-unknown-sysv4 + exit ;; + *:[Aa]miga[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-amigaos + exit ;; + *:[Mm]orph[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-morphos + exit ;; + *:OS/390:*:*) + echo i370-ibm-openedition + exit ;; + *:z/VM:*:*) + echo s390-ibm-zvmoe + exit ;; + *:OS400:*:*) + echo powerpc-ibm-os400 + exit ;; + arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) + echo arm-acorn-riscix${UNAME_RELEASE} + exit ;; + arm:riscos:*:*|arm:RISCOS:*:*) + echo arm-unknown-riscos + exit ;; + SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) + echo hppa1.1-hitachi-hiuxmpp + exit ;; + Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) + # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. + if test "`(/bin/universe) 2>/dev/null`" = att ; then + echo pyramid-pyramid-sysv3 + else + echo pyramid-pyramid-bsd + fi + exit ;; + NILE*:*:*:dcosx) + echo pyramid-pyramid-svr4 + exit ;; + DRS?6000:unix:4.0:6*) + echo sparc-icl-nx6 + exit ;; + DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) + case `/usr/bin/uname -p` in + sparc) echo sparc-icl-nx7; exit ;; + esac ;; + s390x:SunOS:*:*) + echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4H:SunOS:5.*:*) + echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) + echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) + echo i386-pc-auroraux${UNAME_RELEASE} + exit ;; + i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) + eval $set_cc_for_build + SUN_ARCH="i386" + # If there is a compiler, see if it is configured for 64-bit objects. + # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. + # This test works for both compilers. + if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + SUN_ARCH="x86_64" + fi + fi + echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:6*:*) + # According to config.sub, this is the proper way to canonicalize + # SunOS6. Hard to guess exactly what SunOS6 will be like, but + # it's likely to be more like Solaris than SunOS4. + echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:*:*) + case "`/usr/bin/arch -k`" in + Series*|S4*) + UNAME_RELEASE=`uname -v` + ;; + esac + # Japanese Language versions have a version number like `4.1.3-JL'. + echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` + exit ;; + sun3*:SunOS:*:*) + echo m68k-sun-sunos${UNAME_RELEASE} + exit ;; + sun*:*:4.2BSD:*) + UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` + test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 + case "`/bin/arch`" in + sun3) + echo m68k-sun-sunos${UNAME_RELEASE} + ;; + sun4) + echo sparc-sun-sunos${UNAME_RELEASE} + ;; + esac + exit ;; + aushp:SunOS:*:*) + echo sparc-auspex-sunos${UNAME_RELEASE} + exit ;; + # The situation for MiNT is a little confusing. The machine name + # can be virtually everything (everything which is not + # "atarist" or "atariste" at least should have a processor + # > m68000). The system name ranges from "MiNT" over "FreeMiNT" + # to the lowercase version "mint" (or "freemint"). Finally + # the system name "TOS" denotes a system which is actually not + # MiNT. But MiNT is downward compatible to TOS, so this should + # be no problem. + atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) + echo m68k-milan-mint${UNAME_RELEASE} + exit ;; + hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) + echo m68k-hades-mint${UNAME_RELEASE} + exit ;; + *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) + echo m68k-unknown-mint${UNAME_RELEASE} + exit ;; + m68k:machten:*:*) + echo m68k-apple-machten${UNAME_RELEASE} + exit ;; + powerpc:machten:*:*) + echo powerpc-apple-machten${UNAME_RELEASE} + exit ;; + RISC*:Mach:*:*) + echo mips-dec-mach_bsd4.3 + exit ;; + RISC*:ULTRIX:*:*) + echo mips-dec-ultrix${UNAME_RELEASE} + exit ;; + VAX*:ULTRIX*:*:*) + echo vax-dec-ultrix${UNAME_RELEASE} + exit ;; + 2020:CLIX:*:* | 2430:CLIX:*:*) + echo clipper-intergraph-clix${UNAME_RELEASE} + exit ;; + mips:*:*:UMIPS | mips:*:*:RISCos) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c +#ifdef __cplusplus +#include /* for printf() prototype */ + int main (int argc, char *argv[]) { +#else + int main (argc, argv) int argc; char *argv[]; { +#endif + #if defined (host_mips) && defined (MIPSEB) + #if defined (SYSTYPE_SYSV) + printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_SVR4) + printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) + printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); + #endif + #endif + exit (-1); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && + dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && + SYSTEM_NAME=`$dummy $dummyarg` && + { echo "$SYSTEM_NAME"; exit; } + echo mips-mips-riscos${UNAME_RELEASE} + exit ;; + Motorola:PowerMAX_OS:*:*) + echo powerpc-motorola-powermax + exit ;; + Motorola:*:4.3:PL8-*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:Power_UNIX:*:*) + echo powerpc-harris-powerunix + exit ;; + m88k:CX/UX:7*:*) + echo m88k-harris-cxux7 + exit ;; + m88k:*:4*:R4*) + echo m88k-motorola-sysv4 + exit ;; + m88k:*:3*:R3*) + echo m88k-motorola-sysv3 + exit ;; + AViiON:dgux:*:*) + # DG/UX returns AViiON for all architectures + UNAME_PROCESSOR=`/usr/bin/uname -p` + if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] + then + if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ + [ ${TARGET_BINARY_INTERFACE}x = x ] + then + echo m88k-dg-dgux${UNAME_RELEASE} + else + echo m88k-dg-dguxbcs${UNAME_RELEASE} + fi + else + echo i586-dg-dgux${UNAME_RELEASE} + fi + exit ;; + M88*:DolphinOS:*:*) # DolphinOS (SVR3) + echo m88k-dolphin-sysv3 + exit ;; + M88*:*:R3*:*) + # Delta 88k system running SVR3 + echo m88k-motorola-sysv3 + exit ;; + XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) + echo m88k-tektronix-sysv3 + exit ;; + Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) + echo m68k-tektronix-bsd + exit ;; + *:IRIX*:*:*) + echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` + exit ;; + ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. + echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id + exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' + i*86:AIX:*:*) + echo i386-ibm-aix + exit ;; + ia64:AIX:*:*) + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} + exit ;; + *:AIX:2:3) + if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + + main() + { + if (!__power_pc()) + exit(1); + puts("powerpc-ibm-aix3.2.5"); + exit(0); + } +EOF + if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` + then + echo "$SYSTEM_NAME" + else + echo rs6000-ibm-aix3.2.5 + fi + elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then + echo rs6000-ibm-aix3.2.4 + else + echo rs6000-ibm-aix3.2 + fi + exit ;; + *:AIX:*:[4567]) + IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` + if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then + IBM_ARCH=rs6000 + else + IBM_ARCH=powerpc + fi + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${IBM_ARCH}-ibm-aix${IBM_REV} + exit ;; + *:AIX:*:*) + echo rs6000-ibm-aix + exit ;; + ibmrt:4.4BSD:*|romp-ibm:BSD:*) + echo romp-ibm-bsd4.4 + exit ;; + ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and + echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to + exit ;; # report: romp-ibm BSD 4.3 + *:BOSX:*:*) + echo rs6000-bull-bosx + exit ;; + DPX/2?00:B.O.S.:*:*) + echo m68k-bull-sysv3 + exit ;; + 9000/[34]??:4.3bsd:1.*:*) + echo m68k-hp-bsd + exit ;; + hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) + echo m68k-hp-bsd4.4 + exit ;; + 9000/[34678]??:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + case "${UNAME_MACHINE}" in + 9000/31? ) HP_ARCH=m68000 ;; + 9000/[34]?? ) HP_ARCH=m68k ;; + 9000/[678][0-9][0-9]) + if [ -x /usr/bin/getconf ]; then + sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` + sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` + case "${sc_cpu_version}" in + 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 + 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 + 532) # CPU_PA_RISC2_0 + case "${sc_kernel_bits}" in + 32) HP_ARCH="hppa2.0n" ;; + 64) HP_ARCH="hppa2.0w" ;; + '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 + esac ;; + esac + fi + if [ "${HP_ARCH}" = "" ]; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + + #define _HPUX_SOURCE + #include + #include + + int main () + { + #if defined(_SC_KERNEL_BITS) + long bits = sysconf(_SC_KERNEL_BITS); + #endif + long cpu = sysconf (_SC_CPU_VERSION); + + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1"); break; + case CPU_PA_RISC2_0: + #if defined(_SC_KERNEL_BITS) + switch (bits) + { + case 64: puts ("hppa2.0w"); break; + case 32: puts ("hppa2.0n"); break; + default: puts ("hppa2.0"); break; + } break; + #else /* !defined(_SC_KERNEL_BITS) */ + puts ("hppa2.0"); break; + #endif + default: puts ("hppa1.0"); break; + } + exit (0); + } +EOF + (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` + test -z "$HP_ARCH" && HP_ARCH=hppa + fi ;; + esac + if [ ${HP_ARCH} = "hppa2.0w" ] + then + eval $set_cc_for_build + + # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating + # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler + # generating 64-bit code. GNU and HP use different nomenclature: + # + # $ CC_FOR_BUILD=cc ./config.guess + # => hppa2.0w-hp-hpux11.23 + # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess + # => hppa64-hp-hpux11.23 + + if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | + grep -q __LP64__ + then + HP_ARCH="hppa2.0w" + else + HP_ARCH="hppa64" + fi + fi + echo ${HP_ARCH}-hp-hpux${HPUX_REV} + exit ;; + ia64:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + echo ia64-hp-hpux${HPUX_REV} + exit ;; + 3050*:HI-UX:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + int + main () + { + long cpu = sysconf (_SC_CPU_VERSION); + /* The order matters, because CPU_IS_HP_MC68K erroneously returns + true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct + results, however. */ + if (CPU_IS_PA_RISC (cpu)) + { + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; + case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; + default: puts ("hppa-hitachi-hiuxwe2"); break; + } + } + else if (CPU_IS_HP_MC68K (cpu)) + puts ("m68k-hitachi-hiuxwe2"); + else puts ("unknown-hitachi-hiuxwe2"); + exit (0); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + echo unknown-hitachi-hiuxwe2 + exit ;; + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) + echo hppa1.1-hp-bsd + exit ;; + 9000/8??:4.3bsd:*:*) + echo hppa1.0-hp-bsd + exit ;; + *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) + echo hppa1.0-hp-mpeix + exit ;; + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) + echo hppa1.1-hp-osf + exit ;; + hp8??:OSF1:*:*) + echo hppa1.0-hp-osf + exit ;; + i*86:OSF1:*:*) + if [ -x /usr/sbin/sysversion ] ; then + echo ${UNAME_MACHINE}-unknown-osf1mk + else + echo ${UNAME_MACHINE}-unknown-osf1 + fi + exit ;; + parisc*:Lites*:*:*) + echo hppa1.1-hp-lites + exit ;; + C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) + echo c1-convex-bsd + exit ;; + C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) + echo c34-convex-bsd + exit ;; + C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) + echo c38-convex-bsd + exit ;; + C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) + echo c4-convex-bsd + exit ;; + CRAY*Y-MP:*:*:*) + echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*[A-Z]90:*:*:*) + echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ + | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ + -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ + -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*TS:*:*:*) + echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*T3E:*:*:*) + echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*SV1:*:*:*) + echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + *:UNICOS/mp:*:*) + echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) + FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` + echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + 5000:UNIX_System_V:4.*:*) + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` + echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) + echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} + exit ;; + sparc*:BSD/OS:*:*) + echo sparc-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:BSD/OS:*:*) + echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:FreeBSD:*:*) + UNAME_PROCESSOR=`/usr/bin/uname -p` + case ${UNAME_PROCESSOR} in + amd64) + echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + *) + echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + esac + exit ;; + i*:CYGWIN*:*) + echo ${UNAME_MACHINE}-pc-cygwin + exit ;; + *:MINGW*:*) + echo ${UNAME_MACHINE}-pc-mingw32 + exit ;; + i*:MSYS*:*) + echo ${UNAME_MACHINE}-pc-msys + exit ;; + i*:windows32*:*) + # uname -m includes "-pc" on this system. + echo ${UNAME_MACHINE}-mingw32 + exit ;; + i*:PW*:*) + echo ${UNAME_MACHINE}-pc-pw32 + exit ;; + *:Interix*:*) + case ${UNAME_MACHINE} in + x86) + echo i586-pc-interix${UNAME_RELEASE} + exit ;; + authenticamd | genuineintel | EM64T) + echo x86_64-unknown-interix${UNAME_RELEASE} + exit ;; + IA64) + echo ia64-unknown-interix${UNAME_RELEASE} + exit ;; + esac ;; + [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) + echo i${UNAME_MACHINE}-pc-mks + exit ;; + 8664:Windows_NT:*) + echo x86_64-pc-mks + exit ;; + i*:Windows_NT*:* | Pentium*:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we + # UNAME_MACHINE based on the output of uname instead of i386? + echo i586-pc-interix + exit ;; + i*:UWIN*:*) + echo ${UNAME_MACHINE}-pc-uwin + exit ;; + amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) + echo x86_64-unknown-cygwin + exit ;; + p*:CYGWIN*:*) + echo powerpcle-unknown-cygwin + exit ;; + prep*:SunOS:5.*:*) + echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + *:GNU:*:*) + # the GNU system + echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` + exit ;; + *:GNU/*:*:*) + # other systems with GNU libc and userland + echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu + exit ;; + i*86:Minix:*:*) + echo ${UNAME_MACHINE}-pc-minix + exit ;; + aarch64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + aarch64_be:Linux:*:*) + UNAME_MACHINE=aarch64_be + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + alpha:Linux:*:*) + case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in + EV5) UNAME_MACHINE=alphaev5 ;; + EV56) UNAME_MACHINE=alphaev56 ;; + PCA56) UNAME_MACHINE=alphapca56 ;; + PCA57) UNAME_MACHINE=alphapca56 ;; + EV6) UNAME_MACHINE=alphaev6 ;; + EV67) UNAME_MACHINE=alphaev67 ;; + EV68*) UNAME_MACHINE=alphaev68 ;; + esac + objdump --private-headers /bin/sh | grep -q ld.so.1 + if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi + echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} + exit ;; + arm*:Linux:*:*) + eval $set_cc_for_build + if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_EABI__ + then + echo ${UNAME_MACHINE}-unknown-linux-gnu + else + if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_PCS_VFP + then + echo ${UNAME_MACHINE}-unknown-linux-gnueabi + else + echo ${UNAME_MACHINE}-unknown-linux-gnueabihf + fi + fi + exit ;; + avr32*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + cris:Linux:*:*) + echo ${UNAME_MACHINE}-axis-linux-gnu + exit ;; + crisv32:Linux:*:*) + echo ${UNAME_MACHINE}-axis-linux-gnu + exit ;; + frv:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + hexagon:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + i*86:Linux:*:*) + LIBC=gnu + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #ifdef __dietlibc__ + LIBC=dietlibc + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'` + echo "${UNAME_MACHINE}-pc-linux-${LIBC}" + exit ;; + ia64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + m32r*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + m68*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + mips:Linux:*:* | mips64:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef ${UNAME_MACHINE} + #undef ${UNAME_MACHINE}el + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=${UNAME_MACHINE}el + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=${UNAME_MACHINE} + #else + CPU= + #endif + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` + test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } + ;; + or32:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + padre:Linux:*:*) + echo sparc-unknown-linux-gnu + exit ;; + parisc64:Linux:*:* | hppa64:Linux:*:*) + echo hppa64-unknown-linux-gnu + exit ;; + parisc:Linux:*:* | hppa:Linux:*:*) + # Look for CPU level + case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in + PA7*) echo hppa1.1-unknown-linux-gnu ;; + PA8*) echo hppa2.0-unknown-linux-gnu ;; + *) echo hppa-unknown-linux-gnu ;; + esac + exit ;; + ppc64:Linux:*:*) + echo powerpc64-unknown-linux-gnu + exit ;; + ppc:Linux:*:*) + echo powerpc-unknown-linux-gnu + exit ;; + s390:Linux:*:* | s390x:Linux:*:*) + echo ${UNAME_MACHINE}-ibm-linux + exit ;; + sh64*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + sh*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + sparc:Linux:*:* | sparc64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + tile*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + vax:Linux:*:*) + echo ${UNAME_MACHINE}-dec-linux-gnu + exit ;; + x86_64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + xtensa*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + i*86:DYNIX/ptx:4*:*) + # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. + # earlier versions are messed up and put the nodename in both + # sysname and nodename. + echo i386-sequent-sysv4 + exit ;; + i*86:UNIX_SV:4.2MP:2.*) + # Unixware is an offshoot of SVR4, but it has its own version + # number series starting with 2... + # I am not positive that other SVR4 systems won't match this, + # I just have to hope. -- rms. + # Use sysv4.2uw... so that sysv4* matches it. + echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} + exit ;; + i*86:OS/2:*:*) + # If we were able to find `uname', then EMX Unix compatibility + # is probably installed. + echo ${UNAME_MACHINE}-pc-os2-emx + exit ;; + i*86:XTS-300:*:STOP) + echo ${UNAME_MACHINE}-unknown-stop + exit ;; + i*86:atheos:*:*) + echo ${UNAME_MACHINE}-unknown-atheos + exit ;; + i*86:syllable:*:*) + echo ${UNAME_MACHINE}-pc-syllable + exit ;; + i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) + echo i386-unknown-lynxos${UNAME_RELEASE} + exit ;; + i*86:*DOS:*:*) + echo ${UNAME_MACHINE}-pc-msdosdjgpp + exit ;; + i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) + UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` + if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then + echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} + else + echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} + fi + exit ;; + i*86:*:5:[678]*) + # UnixWare 7.x, OpenUNIX and OpenServer 6. + case `/bin/uname -X | grep "^Machine"` in + *486*) UNAME_MACHINE=i486 ;; + *Pentium) UNAME_MACHINE=i586 ;; + *Pent*|*Celeron) UNAME_MACHINE=i686 ;; + esac + echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} + exit ;; + i*86:*:3.2:*) + if test -f /usr/options/cb.name; then + UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then + UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` + (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 + (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ + && UNAME_MACHINE=i586 + (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ + && UNAME_MACHINE=i686 + (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ + && UNAME_MACHINE=i686 + echo ${UNAME_MACHINE}-pc-sco$UNAME_REL + else + echo ${UNAME_MACHINE}-pc-sysv32 + fi + exit ;; + pc:*:*:*) + # Left here for compatibility: + # uname -m prints for DJGPP always 'pc', but it prints nothing about + # the processor, so we play safe by assuming i586. + # Note: whatever this is, it MUST be the same as what config.sub + # prints for the "djgpp" host, or else GDB configury will decide that + # this is a cross-build. + echo i586-pc-msdosdjgpp + exit ;; + Intel:Mach:3*:*) + echo i386-pc-mach3 + exit ;; + paragon:*:*:*) + echo i860-intel-osf1 + exit ;; + i860:*:4.*:*) # i860-SVR4 + if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then + echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 + else # Add other i860-SVR4 vendors below as they are discovered. + echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 + fi + exit ;; + mini*:CTIX:SYS*5:*) + # "miniframe" + echo m68010-convergent-sysv + exit ;; + mc68k:UNIX:SYSTEM5:3.51m) + echo m68k-convergent-sysv + exit ;; + M680?0:D-NIX:5.3:*) + echo m68k-diab-dnix + exit ;; + M68*:*:R3V[5678]*:*) + test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; + 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) + OS_REL='' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4; exit; } ;; + NCR*:*:4.2:* | MPRAS*:*:4.2:*) + OS_REL='.3' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) + echo m68k-unknown-lynxos${UNAME_RELEASE} + exit ;; + mc68030:UNIX_System_V:4.*:*) + echo m68k-atari-sysv4 + exit ;; + TSUNAMI:LynxOS:2.*:*) + echo sparc-unknown-lynxos${UNAME_RELEASE} + exit ;; + rs6000:LynxOS:2.*:*) + echo rs6000-unknown-lynxos${UNAME_RELEASE} + exit ;; + PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) + echo powerpc-unknown-lynxos${UNAME_RELEASE} + exit ;; + SM[BE]S:UNIX_SV:*:*) + echo mips-dde-sysv${UNAME_RELEASE} + exit ;; + RM*:ReliantUNIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + RM*:SINIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + *:SINIX-*:*:*) + if uname -p 2>/dev/null >/dev/null ; then + UNAME_MACHINE=`(uname -p) 2>/dev/null` + echo ${UNAME_MACHINE}-sni-sysv4 + else + echo ns32k-sni-sysv + fi + exit ;; + PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says + echo i586-unisys-sysv4 + exit ;; + *:UNIX_System_V:4*:FTX*) + # From Gerald Hewes . + # How about differentiating between stratus architectures? -djm + echo hppa1.1-stratus-sysv4 + exit ;; + *:*:*:FTX*) + # From seanf@swdc.stratus.com. + echo i860-stratus-sysv4 + exit ;; + i*86:VOS:*:*) + # From Paul.Green@stratus.com. + echo ${UNAME_MACHINE}-stratus-vos + exit ;; + *:VOS:*:*) + # From Paul.Green@stratus.com. + echo hppa1.1-stratus-vos + exit ;; + mc68*:A/UX:*:*) + echo m68k-apple-aux${UNAME_RELEASE} + exit ;; + news*:NEWS-OS:6*:*) + echo mips-sony-newsos6 + exit ;; + R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) + if [ -d /usr/nec ]; then + echo mips-nec-sysv${UNAME_RELEASE} + else + echo mips-unknown-sysv${UNAME_RELEASE} + fi + exit ;; + BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. + echo powerpc-be-beos + exit ;; + BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. + echo powerpc-apple-beos + exit ;; + BePC:BeOS:*:*) # BeOS running on Intel PC compatible. + echo i586-pc-beos + exit ;; + BePC:Haiku:*:*) # Haiku running on Intel PC compatible. + echo i586-pc-haiku + exit ;; + SX-4:SUPER-UX:*:*) + echo sx4-nec-superux${UNAME_RELEASE} + exit ;; + SX-5:SUPER-UX:*:*) + echo sx5-nec-superux${UNAME_RELEASE} + exit ;; + SX-6:SUPER-UX:*:*) + echo sx6-nec-superux${UNAME_RELEASE} + exit ;; + SX-7:SUPER-UX:*:*) + echo sx7-nec-superux${UNAME_RELEASE} + exit ;; + SX-8:SUPER-UX:*:*) + echo sx8-nec-superux${UNAME_RELEASE} + exit ;; + SX-8R:SUPER-UX:*:*) + echo sx8r-nec-superux${UNAME_RELEASE} + exit ;; + Power*:Rhapsody:*:*) + echo powerpc-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Rhapsody:*:*) + echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Darwin:*:*) + UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown + case $UNAME_PROCESSOR in + i386) + eval $set_cc_for_build + if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + UNAME_PROCESSOR="x86_64" + fi + fi ;; + unknown) UNAME_PROCESSOR=powerpc ;; + esac + echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} + exit ;; + *:procnto*:*:* | *:QNX:[0123456789]*:*) + UNAME_PROCESSOR=`uname -p` + if test "$UNAME_PROCESSOR" = "x86"; then + UNAME_PROCESSOR=i386 + UNAME_MACHINE=pc + fi + echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} + exit ;; + *:QNX:*:4*) + echo i386-pc-qnx + exit ;; + NEO-?:NONSTOP_KERNEL:*:*) + echo neo-tandem-nsk${UNAME_RELEASE} + exit ;; + NSE-?:NONSTOP_KERNEL:*:*) + echo nse-tandem-nsk${UNAME_RELEASE} + exit ;; + NSR-?:NONSTOP_KERNEL:*:*) + echo nsr-tandem-nsk${UNAME_RELEASE} + exit ;; + *:NonStop-UX:*:*) + echo mips-compaq-nonstopux + exit ;; + BS2000:POSIX*:*:*) + echo bs2000-siemens-sysv + exit ;; + DS/*:UNIX_System_V:*:*) + echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} + exit ;; + *:Plan9:*:*) + # "uname -m" is not consistent, so use $cputype instead. 386 + # is converted to i386 for consistency with other x86 + # operating systems. + if test "$cputype" = "386"; then + UNAME_MACHINE=i386 + else + UNAME_MACHINE="$cputype" + fi + echo ${UNAME_MACHINE}-unknown-plan9 + exit ;; + *:TOPS-10:*:*) + echo pdp10-unknown-tops10 + exit ;; + *:TENEX:*:*) + echo pdp10-unknown-tenex + exit ;; + KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) + echo pdp10-dec-tops20 + exit ;; + XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) + echo pdp10-xkl-tops20 + exit ;; + *:TOPS-20:*:*) + echo pdp10-unknown-tops20 + exit ;; + *:ITS:*:*) + echo pdp10-unknown-its + exit ;; + SEI:*:*:SEIUX) + echo mips-sei-seiux${UNAME_RELEASE} + exit ;; + *:DragonFly:*:*) + echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + exit ;; + *:*VMS:*:*) + UNAME_MACHINE=`(uname -p) 2>/dev/null` + case "${UNAME_MACHINE}" in + A*) echo alpha-dec-vms ; exit ;; + I*) echo ia64-dec-vms ; exit ;; + V*) echo vax-dec-vms ; exit ;; + esac ;; + *:XENIX:*:SysV) + echo i386-pc-xenix + exit ;; + i*86:skyos:*:*) + echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' + exit ;; + i*86:rdos:*:*) + echo ${UNAME_MACHINE}-pc-rdos + exit ;; + i*86:AROS:*:*) + echo ${UNAME_MACHINE}-pc-aros + exit ;; + x86_64:VMkernel:*:*) + echo ${UNAME_MACHINE}-unknown-esx + exit ;; +esac + +#echo '(No uname command or uname output not recognized.)' 1>&2 +#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 + +eval $set_cc_for_build +cat >$dummy.c < +# include +#endif +main () +{ +#if defined (sony) +#if defined (MIPSEB) + /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, + I don't know.... */ + printf ("mips-sony-bsd\n"); exit (0); +#else +#include + printf ("m68k-sony-newsos%s\n", +#ifdef NEWSOS4 + "4" +#else + "" +#endif + ); exit (0); +#endif +#endif + +#if defined (__arm) && defined (__acorn) && defined (__unix) + printf ("arm-acorn-riscix\n"); exit (0); +#endif + +#if defined (hp300) && !defined (hpux) + printf ("m68k-hp-bsd\n"); exit (0); +#endif + +#if defined (NeXT) +#if !defined (__ARCHITECTURE__) +#define __ARCHITECTURE__ "m68k" +#endif + int version; + version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; + if (version < 4) + printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); + else + printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); + exit (0); +#endif + +#if defined (MULTIMAX) || defined (n16) +#if defined (UMAXV) + printf ("ns32k-encore-sysv\n"); exit (0); +#else +#if defined (CMU) + printf ("ns32k-encore-mach\n"); exit (0); +#else + printf ("ns32k-encore-bsd\n"); exit (0); +#endif +#endif +#endif + +#if defined (__386BSD__) + printf ("i386-pc-bsd\n"); exit (0); +#endif + +#if defined (sequent) +#if defined (i386) + printf ("i386-sequent-dynix\n"); exit (0); +#endif +#if defined (ns32000) + printf ("ns32k-sequent-dynix\n"); exit (0); +#endif +#endif + +#if defined (_SEQUENT_) + struct utsname un; + + uname(&un); + + if (strncmp(un.version, "V2", 2) == 0) { + printf ("i386-sequent-ptx2\n"); exit (0); + } + if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ + printf ("i386-sequent-ptx1\n"); exit (0); + } + printf ("i386-sequent-ptx\n"); exit (0); + +#endif + +#if defined (vax) +# if !defined (ultrix) +# include +# if defined (BSD) +# if BSD == 43 + printf ("vax-dec-bsd4.3\n"); exit (0); +# else +# if BSD == 199006 + printf ("vax-dec-bsd4.3reno\n"); exit (0); +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# endif +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# else + printf ("vax-dec-ultrix\n"); exit (0); +# endif +#endif + +#if defined (alliant) && defined (i860) + printf ("i860-alliant-bsd\n"); exit (0); +#endif + + exit (1); +} +EOF + +$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + +# Apollos put the system type in the environment. + +test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; } + +# Convex versions that predate uname can use getsysinfo(1) + +if [ -x /usr/convex/getsysinfo ] +then + case `getsysinfo -f cpu_type` in + c1*) + echo c1-convex-bsd + exit ;; + c2*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + c34*) + echo c34-convex-bsd + exit ;; + c38*) + echo c38-convex-bsd + exit ;; + c4*) + echo c4-convex-bsd + exit ;; + esac +fi + +cat >&2 < in order to provide the needed +information to handle your system. + +config.guess timestamp = $timestamp + +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null` + +hostinfo = `(hostinfo) 2>/dev/null` +/bin/universe = `(/bin/universe) 2>/dev/null` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` +/bin/arch = `(/bin/arch) 2>/dev/null` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` + +UNAME_MACHINE = ${UNAME_MACHINE} +UNAME_RELEASE = ${UNAME_RELEASE} +UNAME_SYSTEM = ${UNAME_SYSTEM} +UNAME_VERSION = ${UNAME_VERSION} +EOF + +exit 1 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/config/config.sub b/config/config.sub new file mode 100755 index 00000000..59bb593f --- /dev/null +++ b/config/config.sub @@ -0,0 +1,1779 @@ +#! /bin/sh +# Configuration validation subroutine script. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, +# 2011, 2012 Free Software Foundation, Inc. + +timestamp='2012-04-18' + +# This file is (in principle) common to ALL GNU software. +# The presence of a machine in this file suggests that SOME GNU software +# can handle that machine. It does not imply ALL GNU software can. +# +# This file is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see . +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + + +# Please send patches to . Submit a context +# diff and a properly formatted GNU ChangeLog entry. +# +# Configuration subroutine to validate and canonicalize a configuration type. +# Supply the specified configuration type as an argument. +# If it is invalid, we print an error message on stderr and exit with code 1. +# Otherwise, we print the canonical config type on stdout and succeed. + +# You can get the latest version of this script from: +# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD + +# This file is supposed to be the same for all GNU packages +# and recognize all the CPU types, system types and aliases +# that are meaningful with *any* GNU software. +# Each package is responsible for reporting which valid configurations +# it does not support. The user should be able to distinguish +# a failure to support a valid configuration from a meaningless +# configuration. + +# The goal of this file is to map all the various variations of a given +# machine specification into a single specification in the form: +# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM +# or in some cases, the newer four-part form: +# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM +# It is wrong to echo any other type of specification. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] CPU-MFR-OPSYS + $0 [OPTION] ALIAS + +Canonicalize a configuration name. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.sub ($timestamp) + +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, +2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 +Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" + exit 1 ;; + + *local*) + # First pass through any local machine types. + echo $1 + exit ;; + + * ) + break ;; + esac +done + +case $# in + 0) echo "$me: missing argument$help" >&2 + exit 1;; + 1) ;; + *) echo "$me: too many arguments$help" >&2 + exit 1;; +esac + +# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). +# Here we must recognize all the valid KERNEL-OS combinations. +maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` +case $maybe_os in + nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ + linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ + knetbsd*-gnu* | netbsd*-gnu* | \ + kopensolaris*-gnu* | \ + storm-chaos* | os2-emx* | rtmk-nova*) + os=-$maybe_os + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` + ;; + android-linux) + os=-linux-android + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown + ;; + *) + basic_machine=`echo $1 | sed 's/-[^-]*$//'` + if [ $basic_machine != $1 ] + then os=`echo $1 | sed 's/.*-/-/'` + else os=; fi + ;; +esac + +### Let's recognize common machines as not being operating systems so +### that things like config.sub decstation-3100 work. We also +### recognize some manufacturers as not being operating systems, so we +### can provide default operating systems below. +case $os in + -sun*os*) + # Prevent following clause from handling this invalid input. + ;; + -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ + -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ + -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ + -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ + -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ + -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ + -apple | -axis | -knuth | -cray | -microblaze) + os= + basic_machine=$1 + ;; + -bluegene*) + os=-cnk + ;; + -sim | -cisco | -oki | -wec | -winbond) + os= + basic_machine=$1 + ;; + -scout) + ;; + -wrs) + os=-vxworks + basic_machine=$1 + ;; + -chorusos*) + os=-chorusos + basic_machine=$1 + ;; + -chorusrdb) + os=-chorusrdb + basic_machine=$1 + ;; + -hiux*) + os=-hiuxwe2 + ;; + -sco6) + os=-sco5v6 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5) + os=-sco3.2v5 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco4) + os=-sco3.2v4 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2.[4-9]*) + os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2v[4-9]*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5v6*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco*) + os=-sco3.2v2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -udk*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -isc) + os=-isc2.2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -clix*) + basic_machine=clipper-intergraph + ;; + -isc*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -lynx*178) + os=-lynxos178 + ;; + -lynx*5) + os=-lynxos5 + ;; + -lynx*) + os=-lynxos + ;; + -ptx*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` + ;; + -windowsnt*) + os=`echo $os | sed -e 's/windowsnt/winnt/'` + ;; + -psos*) + os=-psos + ;; + -mint | -mint[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; +esac + +# Decode aliases for certain CPU-COMPANY combinations. +case $basic_machine in + # Recognize the basic CPU types without company name. + # Some are omitted here because they have special meanings below. + 1750a | 580 \ + | a29k \ + | aarch64 | aarch64_be \ + | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ + | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ + | am33_2.0 \ + | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \ + | be32 | be64 \ + | bfin \ + | c4x | clipper \ + | d10v | d30v | dlx | dsp16xx \ + | epiphany \ + | fido | fr30 | frv \ + | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ + | hexagon \ + | i370 | i860 | i960 | ia64 \ + | ip2k | iq2000 \ + | le32 | le64 \ + | lm32 \ + | m32c | m32r | m32rle | m68000 | m68k | m88k \ + | maxq | mb | microblaze | mcore | mep | metag \ + | mips | mipsbe | mipseb | mipsel | mipsle \ + | mips16 \ + | mips64 | mips64el \ + | mips64octeon | mips64octeonel \ + | mips64orion | mips64orionel \ + | mips64r5900 | mips64r5900el \ + | mips64vr | mips64vrel \ + | mips64vr4100 | mips64vr4100el \ + | mips64vr4300 | mips64vr4300el \ + | mips64vr5000 | mips64vr5000el \ + | mips64vr5900 | mips64vr5900el \ + | mipsisa32 | mipsisa32el \ + | mipsisa32r2 | mipsisa32r2el \ + | mipsisa64 | mipsisa64el \ + | mipsisa64r2 | mipsisa64r2el \ + | mipsisa64sb1 | mipsisa64sb1el \ + | mipsisa64sr71k | mipsisa64sr71kel \ + | mipstx39 | mipstx39el \ + | mn10200 | mn10300 \ + | moxie \ + | mt \ + | msp430 \ + | nds32 | nds32le | nds32be \ + | nios | nios2 \ + | ns16k | ns32k \ + | open8 \ + | or32 \ + | pdp10 | pdp11 | pj | pjl \ + | powerpc | powerpc64 | powerpc64le | powerpcle \ + | pyramid \ + | rl78 | rx \ + | score \ + | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ + | sh64 | sh64le \ + | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ + | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ + | spu \ + | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ + | ubicom32 \ + | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ + | we32k \ + | x86 | xc16x | xstormy16 | xtensa \ + | z8k | z80) + basic_machine=$basic_machine-unknown + ;; + c54x) + basic_machine=tic54x-unknown + ;; + c55x) + basic_machine=tic55x-unknown + ;; + c6x) + basic_machine=tic6x-unknown + ;; + m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | picochip) + basic_machine=$basic_machine-unknown + os=-none + ;; + m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) + ;; + ms1) + basic_machine=mt-unknown + ;; + + strongarm | thumb | xscale) + basic_machine=arm-unknown + ;; + xgate) + basic_machine=$basic_machine-unknown + os=-none + ;; + xscaleeb) + basic_machine=armeb-unknown + ;; + + xscaleel) + basic_machine=armel-unknown + ;; + + # We use `pc' rather than `unknown' + # because (1) that's what they normally are, and + # (2) the word "unknown" tends to confuse beginning users. + i*86 | x86_64) + basic_machine=$basic_machine-pc + ;; + # Object if more than one company name word. + *-*-*) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; + # Recognize the basic CPU types with company name. + 580-* \ + | a29k-* \ + | aarch64-* | aarch64_be-* \ + | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ + | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ + | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ + | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ + | avr-* | avr32-* \ + | be32-* | be64-* \ + | bfin-* | bs2000-* \ + | c[123]* | c30-* | [cjt]90-* | c4x-* \ + | clipper-* | craynv-* | cydra-* \ + | d10v-* | d30v-* | dlx-* \ + | elxsi-* \ + | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ + | h8300-* | h8500-* \ + | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ + | hexagon-* \ + | i*86-* | i860-* | i960-* | ia64-* \ + | ip2k-* | iq2000-* \ + | le32-* | le64-* \ + | lm32-* \ + | m32c-* | m32r-* | m32rle-* \ + | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ + | m88110-* | m88k-* | maxq-* | mcore-* | metag-* | microblaze-* \ + | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ + | mips16-* \ + | mips64-* | mips64el-* \ + | mips64octeon-* | mips64octeonel-* \ + | mips64orion-* | mips64orionel-* \ + | mips64r5900-* | mips64r5900el-* \ + | mips64vr-* | mips64vrel-* \ + | mips64vr4100-* | mips64vr4100el-* \ + | mips64vr4300-* | mips64vr4300el-* \ + | mips64vr5000-* | mips64vr5000el-* \ + | mips64vr5900-* | mips64vr5900el-* \ + | mipsisa32-* | mipsisa32el-* \ + | mipsisa32r2-* | mipsisa32r2el-* \ + | mipsisa64-* | mipsisa64el-* \ + | mipsisa64r2-* | mipsisa64r2el-* \ + | mipsisa64sb1-* | mipsisa64sb1el-* \ + | mipsisa64sr71k-* | mipsisa64sr71kel-* \ + | mipstx39-* | mipstx39el-* \ + | mmix-* \ + | mt-* \ + | msp430-* \ + | nds32-* | nds32le-* | nds32be-* \ + | nios-* | nios2-* \ + | none-* | np1-* | ns16k-* | ns32k-* \ + | open8-* \ + | orion-* \ + | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ + | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ + | pyramid-* \ + | rl78-* | romp-* | rs6000-* | rx-* \ + | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ + | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ + | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ + | sparclite-* \ + | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \ + | tahoe-* \ + | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ + | tile*-* \ + | tron-* \ + | ubicom32-* \ + | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ + | vax-* \ + | we32k-* \ + | x86-* | x86_64-* | xc16x-* | xps100-* \ + | xstormy16-* | xtensa*-* \ + | ymp-* \ + | z8k-* | z80-*) + ;; + # Recognize the basic CPU types without company name, with glob match. + xtensa*) + basic_machine=$basic_machine-unknown + ;; + # Recognize the various machine names and aliases which stand + # for a CPU type and a company and sometimes even an OS. + 386bsd) + basic_machine=i386-unknown + os=-bsd + ;; + 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) + basic_machine=m68000-att + ;; + 3b*) + basic_machine=we32k-att + ;; + a29khif) + basic_machine=a29k-amd + os=-udi + ;; + abacus) + basic_machine=abacus-unknown + ;; + adobe68k) + basic_machine=m68010-adobe + os=-scout + ;; + alliant | fx80) + basic_machine=fx80-alliant + ;; + altos | altos3068) + basic_machine=m68k-altos + ;; + am29k) + basic_machine=a29k-none + os=-bsd + ;; + amd64) + basic_machine=x86_64-pc + ;; + amd64-*) + basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + amdahl) + basic_machine=580-amdahl + os=-sysv + ;; + amiga | amiga-*) + basic_machine=m68k-unknown + ;; + amigaos | amigados) + basic_machine=m68k-unknown + os=-amigaos + ;; + amigaunix | amix) + basic_machine=m68k-unknown + os=-sysv4 + ;; + apollo68) + basic_machine=m68k-apollo + os=-sysv + ;; + apollo68bsd) + basic_machine=m68k-apollo + os=-bsd + ;; + aros) + basic_machine=i386-pc + os=-aros + ;; + aux) + basic_machine=m68k-apple + os=-aux + ;; + balance) + basic_machine=ns32k-sequent + os=-dynix + ;; + blackfin) + basic_machine=bfin-unknown + os=-linux + ;; + blackfin-*) + basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + bluegene*) + basic_machine=powerpc-ibm + os=-cnk + ;; + c54x-*) + basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c55x-*) + basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c6x-*) + basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c90) + basic_machine=c90-cray + os=-unicos + ;; + cegcc) + basic_machine=arm-unknown + os=-cegcc + ;; + convex-c1) + basic_machine=c1-convex + os=-bsd + ;; + convex-c2) + basic_machine=c2-convex + os=-bsd + ;; + convex-c32) + basic_machine=c32-convex + os=-bsd + ;; + convex-c34) + basic_machine=c34-convex + os=-bsd + ;; + convex-c38) + basic_machine=c38-convex + os=-bsd + ;; + cray | j90) + basic_machine=j90-cray + os=-unicos + ;; + craynv) + basic_machine=craynv-cray + os=-unicosmp + ;; + cr16 | cr16-*) + basic_machine=cr16-unknown + os=-elf + ;; + crds | unos) + basic_machine=m68k-crds + ;; + crisv32 | crisv32-* | etraxfs*) + basic_machine=crisv32-axis + ;; + cris | cris-* | etrax*) + basic_machine=cris-axis + ;; + crx) + basic_machine=crx-unknown + os=-elf + ;; + da30 | da30-*) + basic_machine=m68k-da30 + ;; + decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) + basic_machine=mips-dec + ;; + decsystem10* | dec10*) + basic_machine=pdp10-dec + os=-tops10 + ;; + decsystem20* | dec20*) + basic_machine=pdp10-dec + os=-tops20 + ;; + delta | 3300 | motorola-3300 | motorola-delta \ + | 3300-motorola | delta-motorola) + basic_machine=m68k-motorola + ;; + delta88) + basic_machine=m88k-motorola + os=-sysv3 + ;; + dicos) + basic_machine=i686-pc + os=-dicos + ;; + djgpp) + basic_machine=i586-pc + os=-msdosdjgpp + ;; + dpx20 | dpx20-*) + basic_machine=rs6000-bull + os=-bosx + ;; + dpx2* | dpx2*-bull) + basic_machine=m68k-bull + os=-sysv3 + ;; + ebmon29k) + basic_machine=a29k-amd + os=-ebmon + ;; + elxsi) + basic_machine=elxsi-elxsi + os=-bsd + ;; + encore | umax | mmax) + basic_machine=ns32k-encore + ;; + es1800 | OSE68k | ose68k | ose | OSE) + basic_machine=m68k-ericsson + os=-ose + ;; + fx2800) + basic_machine=i860-alliant + ;; + genix) + basic_machine=ns32k-ns + ;; + gmicro) + basic_machine=tron-gmicro + os=-sysv + ;; + go32) + basic_machine=i386-pc + os=-go32 + ;; + h3050r* | hiux*) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + h8300hms) + basic_machine=h8300-hitachi + os=-hms + ;; + h8300xray) + basic_machine=h8300-hitachi + os=-xray + ;; + h8500hms) + basic_machine=h8500-hitachi + os=-hms + ;; + harris) + basic_machine=m88k-harris + os=-sysv3 + ;; + hp300-*) + basic_machine=m68k-hp + ;; + hp300bsd) + basic_machine=m68k-hp + os=-bsd + ;; + hp300hpux) + basic_machine=m68k-hp + os=-hpux + ;; + hp3k9[0-9][0-9] | hp9[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k2[0-9][0-9] | hp9k31[0-9]) + basic_machine=m68000-hp + ;; + hp9k3[2-9][0-9]) + basic_machine=m68k-hp + ;; + hp9k6[0-9][0-9] | hp6[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k7[0-79][0-9] | hp7[0-79][0-9]) + basic_machine=hppa1.1-hp + ;; + hp9k78[0-9] | hp78[0-9]) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][13679] | hp8[0-9][13679]) + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][0-9] | hp8[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hppa-next) + os=-nextstep3 + ;; + hppaosf) + basic_machine=hppa1.1-hp + os=-osf + ;; + hppro) + basic_machine=hppa1.1-hp + os=-proelf + ;; + i370-ibm* | ibm*) + basic_machine=i370-ibm + ;; + i*86v32) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv32 + ;; + i*86v4*) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv4 + ;; + i*86v) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv + ;; + i*86sol2) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-solaris2 + ;; + i386mach) + basic_machine=i386-mach + os=-mach + ;; + i386-vsta | vsta) + basic_machine=i386-unknown + os=-vsta + ;; + iris | iris4d) + basic_machine=mips-sgi + case $os in + -irix*) + ;; + *) + os=-irix4 + ;; + esac + ;; + isi68 | isi) + basic_machine=m68k-isi + os=-sysv + ;; + m68knommu) + basic_machine=m68k-unknown + os=-linux + ;; + m68knommu-*) + basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + m88k-omron*) + basic_machine=m88k-omron + ;; + magnum | m3230) + basic_machine=mips-mips + os=-sysv + ;; + merlin) + basic_machine=ns32k-utek + os=-sysv + ;; + microblaze) + basic_machine=microblaze-xilinx + ;; + mingw32) + basic_machine=i386-pc + os=-mingw32 + ;; + mingw32ce) + basic_machine=arm-unknown + os=-mingw32ce + ;; + miniframe) + basic_machine=m68000-convergent + ;; + *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; + mips3*-*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` + ;; + mips3*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown + ;; + monitor) + basic_machine=m68k-rom68k + os=-coff + ;; + morphos) + basic_machine=powerpc-unknown + os=-morphos + ;; + msdos) + basic_machine=i386-pc + os=-msdos + ;; + ms1-*) + basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` + ;; + msys) + basic_machine=i386-pc + os=-msys + ;; + mvs) + basic_machine=i370-ibm + os=-mvs + ;; + nacl) + basic_machine=le32-unknown + os=-nacl + ;; + ncr3000) + basic_machine=i486-ncr + os=-sysv4 + ;; + netbsd386) + basic_machine=i386-unknown + os=-netbsd + ;; + netwinder) + basic_machine=armv4l-rebel + os=-linux + ;; + news | news700 | news800 | news900) + basic_machine=m68k-sony + os=-newsos + ;; + news1000) + basic_machine=m68030-sony + os=-newsos + ;; + news-3600 | risc-news) + basic_machine=mips-sony + os=-newsos + ;; + necv70) + basic_machine=v70-nec + os=-sysv + ;; + next | m*-next ) + basic_machine=m68k-next + case $os in + -nextstep* ) + ;; + -ns2*) + os=-nextstep2 + ;; + *) + os=-nextstep3 + ;; + esac + ;; + nh3000) + basic_machine=m68k-harris + os=-cxux + ;; + nh[45]000) + basic_machine=m88k-harris + os=-cxux + ;; + nindy960) + basic_machine=i960-intel + os=-nindy + ;; + mon960) + basic_machine=i960-intel + os=-mon960 + ;; + nonstopux) + basic_machine=mips-compaq + os=-nonstopux + ;; + np1) + basic_machine=np1-gould + ;; + neo-tandem) + basic_machine=neo-tandem + ;; + nse-tandem) + basic_machine=nse-tandem + ;; + nsr-tandem) + basic_machine=nsr-tandem + ;; + op50n-* | op60c-*) + basic_machine=hppa1.1-oki + os=-proelf + ;; + openrisc | openrisc-*) + basic_machine=or32-unknown + ;; + os400) + basic_machine=powerpc-ibm + os=-os400 + ;; + OSE68000 | ose68000) + basic_machine=m68000-ericsson + os=-ose + ;; + os68k) + basic_machine=m68k-none + os=-os68k + ;; + pa-hitachi) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + paragon) + basic_machine=i860-intel + os=-osf + ;; + parisc) + basic_machine=hppa-unknown + os=-linux + ;; + parisc-*) + basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + pbd) + basic_machine=sparc-tti + ;; + pbb) + basic_machine=m68k-tti + ;; + pc532 | pc532-*) + basic_machine=ns32k-pc532 + ;; + pc98) + basic_machine=i386-pc + ;; + pc98-*) + basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium | p5 | k5 | k6 | nexgen | viac3) + basic_machine=i586-pc + ;; + pentiumpro | p6 | 6x86 | athlon | athlon_*) + basic_machine=i686-pc + ;; + pentiumii | pentium2 | pentiumiii | pentium3) + basic_machine=i686-pc + ;; + pentium4) + basic_machine=i786-pc + ;; + pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) + basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumpro-* | p6-* | 6x86-* | athlon-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium4-*) + basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pn) + basic_machine=pn-gould + ;; + power) basic_machine=power-ibm + ;; + ppc | ppcbe) basic_machine=powerpc-unknown + ;; + ppc-* | ppcbe-*) + basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppcle | powerpclittle | ppc-le | powerpc-little) + basic_machine=powerpcle-unknown + ;; + ppcle-* | powerpclittle-*) + basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64) basic_machine=powerpc64-unknown + ;; + ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64le | powerpc64little | ppc64-le | powerpc64-little) + basic_machine=powerpc64le-unknown + ;; + ppc64le-* | powerpc64little-*) + basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ps2) + basic_machine=i386-ibm + ;; + pw32) + basic_machine=i586-unknown + os=-pw32 + ;; + rdos) + basic_machine=i386-pc + os=-rdos + ;; + rom68k) + basic_machine=m68k-rom68k + os=-coff + ;; + rm[46]00) + basic_machine=mips-siemens + ;; + rtpc | rtpc-*) + basic_machine=romp-ibm + ;; + s390 | s390-*) + basic_machine=s390-ibm + ;; + s390x | s390x-*) + basic_machine=s390x-ibm + ;; + sa29200) + basic_machine=a29k-amd + os=-udi + ;; + sb1) + basic_machine=mipsisa64sb1-unknown + ;; + sb1el) + basic_machine=mipsisa64sb1el-unknown + ;; + sde) + basic_machine=mipsisa32-sde + os=-elf + ;; + sei) + basic_machine=mips-sei + os=-seiux + ;; + sequent) + basic_machine=i386-sequent + ;; + sh) + basic_machine=sh-hitachi + os=-hms + ;; + sh5el) + basic_machine=sh5le-unknown + ;; + sh64) + basic_machine=sh64-unknown + ;; + sparclite-wrs | simso-wrs) + basic_machine=sparclite-wrs + os=-vxworks + ;; + sps7) + basic_machine=m68k-bull + os=-sysv2 + ;; + spur) + basic_machine=spur-unknown + ;; + st2000) + basic_machine=m68k-tandem + ;; + stratus) + basic_machine=i860-stratus + os=-sysv4 + ;; + strongarm-* | thumb-*) + basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + sun2) + basic_machine=m68000-sun + ;; + sun2os3) + basic_machine=m68000-sun + os=-sunos3 + ;; + sun2os4) + basic_machine=m68000-sun + os=-sunos4 + ;; + sun3os3) + basic_machine=m68k-sun + os=-sunos3 + ;; + sun3os4) + basic_machine=m68k-sun + os=-sunos4 + ;; + sun4os3) + basic_machine=sparc-sun + os=-sunos3 + ;; + sun4os4) + basic_machine=sparc-sun + os=-sunos4 + ;; + sun4sol2) + basic_machine=sparc-sun + os=-solaris2 + ;; + sun3 | sun3-*) + basic_machine=m68k-sun + ;; + sun4) + basic_machine=sparc-sun + ;; + sun386 | sun386i | roadrunner) + basic_machine=i386-sun + ;; + sv1) + basic_machine=sv1-cray + os=-unicos + ;; + symmetry) + basic_machine=i386-sequent + os=-dynix + ;; + t3e) + basic_machine=alphaev5-cray + os=-unicos + ;; + t90) + basic_machine=t90-cray + os=-unicos + ;; + tile*) + basic_machine=$basic_machine-unknown + os=-linux-gnu + ;; + tx39) + basic_machine=mipstx39-unknown + ;; + tx39el) + basic_machine=mipstx39el-unknown + ;; + toad1) + basic_machine=pdp10-xkl + os=-tops20 + ;; + tower | tower-32) + basic_machine=m68k-ncr + ;; + tpf) + basic_machine=s390x-ibm + os=-tpf + ;; + udi29k) + basic_machine=a29k-amd + os=-udi + ;; + ultra3) + basic_machine=a29k-nyu + os=-sym1 + ;; + v810 | necv810) + basic_machine=v810-nec + os=-none + ;; + vaxv) + basic_machine=vax-dec + os=-sysv + ;; + vms) + basic_machine=vax-dec + os=-vms + ;; + vpp*|vx|vx-*) + basic_machine=f301-fujitsu + ;; + vxworks960) + basic_machine=i960-wrs + os=-vxworks + ;; + vxworks68) + basic_machine=m68k-wrs + os=-vxworks + ;; + vxworks29k) + basic_machine=a29k-wrs + os=-vxworks + ;; + w65*) + basic_machine=w65-wdc + os=-none + ;; + w89k-*) + basic_machine=hppa1.1-winbond + os=-proelf + ;; + xbox) + basic_machine=i686-pc + os=-mingw32 + ;; + xps | xps100) + basic_machine=xps100-honeywell + ;; + xscale-* | xscalee[bl]-*) + basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'` + ;; + ymp) + basic_machine=ymp-cray + os=-unicos + ;; + z8k-*-coff) + basic_machine=z8k-unknown + os=-sim + ;; + z80-*-coff) + basic_machine=z80-unknown + os=-sim + ;; + none) + basic_machine=none-none + os=-none + ;; + +# Here we handle the default manufacturer of certain CPU types. It is in +# some cases the only manufacturer, in others, it is the most popular. + w89k) + basic_machine=hppa1.1-winbond + ;; + op50n) + basic_machine=hppa1.1-oki + ;; + op60c) + basic_machine=hppa1.1-oki + ;; + romp) + basic_machine=romp-ibm + ;; + mmix) + basic_machine=mmix-knuth + ;; + rs6000) + basic_machine=rs6000-ibm + ;; + vax) + basic_machine=vax-dec + ;; + pdp10) + # there are many clones, so DEC is not a safe bet + basic_machine=pdp10-unknown + ;; + pdp11) + basic_machine=pdp11-dec + ;; + we32k) + basic_machine=we32k-att + ;; + sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) + basic_machine=sh-unknown + ;; + sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) + basic_machine=sparc-sun + ;; + cydra) + basic_machine=cydra-cydrome + ;; + orion) + basic_machine=orion-highlevel + ;; + orion105) + basic_machine=clipper-highlevel + ;; + mac | mpw | mac-mpw) + basic_machine=m68k-apple + ;; + pmac | pmac-mpw) + basic_machine=powerpc-apple + ;; + *-unknown) + # Make sure to match an already-canonicalized machine name. + ;; + *) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; +esac + +# Here we canonicalize certain aliases for manufacturers. +case $basic_machine in + *-digital*) + basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` + ;; + *-commodore*) + basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` + ;; + *) + ;; +esac + +# Decode manufacturer-specific aliases for certain operating systems. + +if [ x"$os" != x"" ] +then +case $os in + # First match some system type aliases + # that might get confused with valid system types. + # -solaris* is a basic system type, with this one exception. + -auroraux) + os=-auroraux + ;; + -solaris1 | -solaris1.*) + os=`echo $os | sed -e 's|solaris1|sunos4|'` + ;; + -solaris) + os=-solaris2 + ;; + -svr4*) + os=-sysv4 + ;; + -unixware*) + os=-sysv4.2uw + ;; + -gnu/linux*) + os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` + ;; + # First accept the basic system types. + # The portable systems comes first. + # Each alternative MUST END IN A *, to match a version number. + # -sysv* is not here because it comes later, after sysvr4. + -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ + | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ + | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ + | -sym* | -kopensolaris* \ + | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ + | -aos* | -aros* \ + | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ + | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ + | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ + | -openbsd* | -solidbsd* \ + | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ + | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ + | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ + | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ + | -chorusos* | -chorusrdb* | -cegcc* \ + | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ + | -mingw32* | -linux-gnu* | -linux-android* \ + | -linux-newlib* | -linux-uclibc* \ + | -uxpv* | -beos* | -mpeix* | -udk* \ + | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ + | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ + | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ + | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ + | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ + | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ + | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*) + # Remember, each alternative MUST END IN *, to match a version number. + ;; + -qnx*) + case $basic_machine in + x86-* | i*86-*) + ;; + *) + os=-nto$os + ;; + esac + ;; + -nto-qnx*) + ;; + -nto*) + os=`echo $os | sed -e 's|nto|nto-qnx|'` + ;; + -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ + | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ + | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) + ;; + -mac*) + os=`echo $os | sed -e 's|mac|macos|'` + ;; + -linux-dietlibc) + os=-linux-dietlibc + ;; + -linux*) + os=`echo $os | sed -e 's|linux|linux-gnu|'` + ;; + -sunos5*) + os=`echo $os | sed -e 's|sunos5|solaris2|'` + ;; + -sunos6*) + os=`echo $os | sed -e 's|sunos6|solaris3|'` + ;; + -opened*) + os=-openedition + ;; + -os400*) + os=-os400 + ;; + -wince*) + os=-wince + ;; + -osfrose*) + os=-osfrose + ;; + -osf*) + os=-osf + ;; + -utek*) + os=-bsd + ;; + -dynix*) + os=-bsd + ;; + -acis*) + os=-aos + ;; + -atheos*) + os=-atheos + ;; + -syllable*) + os=-syllable + ;; + -386bsd) + os=-bsd + ;; + -ctix* | -uts*) + os=-sysv + ;; + -nova*) + os=-rtmk-nova + ;; + -ns2 ) + os=-nextstep2 + ;; + -nsk*) + os=-nsk + ;; + # Preserve the version number of sinix5. + -sinix5.*) + os=`echo $os | sed -e 's|sinix|sysv|'` + ;; + -sinix*) + os=-sysv4 + ;; + -tpf*) + os=-tpf + ;; + -triton*) + os=-sysv3 + ;; + -oss*) + os=-sysv3 + ;; + -svr4) + os=-sysv4 + ;; + -svr3) + os=-sysv3 + ;; + -sysvr4) + os=-sysv4 + ;; + # This must come after -sysvr4. + -sysv*) + ;; + -ose*) + os=-ose + ;; + -es1800*) + os=-ose + ;; + -xenix) + os=-xenix + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + os=-mint + ;; + -aros*) + os=-aros + ;; + -kaos*) + os=-kaos + ;; + -zvmoe) + os=-zvmoe + ;; + -dicos*) + os=-dicos + ;; + -nacl*) + ;; + -none) + ;; + *) + # Get rid of the `-' at the beginning of $os. + os=`echo $os | sed 's/[^-]*-//'` + echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 + exit 1 + ;; +esac +else + +# Here we handle the default operating systems that come with various machines. +# The value should be what the vendor currently ships out the door with their +# machine or put another way, the most popular os provided with the machine. + +# Note that if you're going to try to match "-MANUFACTURER" here (say, +# "-sun"), then you have to tell the case statement up towards the top +# that MANUFACTURER isn't an operating system. Otherwise, code above +# will signal an error saying that MANUFACTURER isn't an operating +# system, and we'll never get to this point. + +case $basic_machine in + score-*) + os=-elf + ;; + spu-*) + os=-elf + ;; + *-acorn) + os=-riscix1.2 + ;; + arm*-rebel) + os=-linux + ;; + arm*-semi) + os=-aout + ;; + c4x-* | tic4x-*) + os=-coff + ;; + tic54x-*) + os=-coff + ;; + tic55x-*) + os=-coff + ;; + tic6x-*) + os=-coff + ;; + # This must come before the *-dec entry. + pdp10-*) + os=-tops20 + ;; + pdp11-*) + os=-none + ;; + *-dec | vax-*) + os=-ultrix4.2 + ;; + m68*-apollo) + os=-domain + ;; + i386-sun) + os=-sunos4.0.2 + ;; + m68000-sun) + os=-sunos3 + ;; + m68*-cisco) + os=-aout + ;; + mep-*) + os=-elf + ;; + mips*-cisco) + os=-elf + ;; + mips*-*) + os=-elf + ;; + or32-*) + os=-coff + ;; + *-tti) # must be before sparc entry or we get the wrong os. + os=-sysv3 + ;; + sparc-* | *-sun) + os=-sunos4.1.1 + ;; + *-be) + os=-beos + ;; + *-haiku) + os=-haiku + ;; + *-ibm) + os=-aix + ;; + *-knuth) + os=-mmixware + ;; + *-wec) + os=-proelf + ;; + *-winbond) + os=-proelf + ;; + *-oki) + os=-proelf + ;; + *-hp) + os=-hpux + ;; + *-hitachi) + os=-hiux + ;; + i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) + os=-sysv + ;; + *-cbm) + os=-amigaos + ;; + *-dg) + os=-dgux + ;; + *-dolphin) + os=-sysv3 + ;; + m68k-ccur) + os=-rtu + ;; + m88k-omron*) + os=-luna + ;; + *-next ) + os=-nextstep + ;; + *-sequent) + os=-ptx + ;; + *-crds) + os=-unos + ;; + *-ns) + os=-genix + ;; + i370-*) + os=-mvs + ;; + *-next) + os=-nextstep3 + ;; + *-gould) + os=-sysv + ;; + *-highlevel) + os=-bsd + ;; + *-encore) + os=-bsd + ;; + *-sgi) + os=-irix + ;; + *-siemens) + os=-sysv4 + ;; + *-masscomp) + os=-rtu + ;; + f30[01]-fujitsu | f700-fujitsu) + os=-uxpv + ;; + *-rom68k) + os=-coff + ;; + *-*bug) + os=-coff + ;; + *-apple) + os=-macos + ;; + *-atari*) + os=-mint + ;; + *) + os=-none + ;; +esac +fi + +# Here we handle the case where we know the os, and the CPU type, but not the +# manufacturer. We pick the logical manufacturer. +vendor=unknown +case $basic_machine in + *-unknown) + case $os in + -riscix*) + vendor=acorn + ;; + -sunos*) + vendor=sun + ;; + -cnk*|-aix*) + vendor=ibm + ;; + -beos*) + vendor=be + ;; + -hpux*) + vendor=hp + ;; + -mpeix*) + vendor=hp + ;; + -hiux*) + vendor=hitachi + ;; + -unos*) + vendor=crds + ;; + -dgux*) + vendor=dg + ;; + -luna*) + vendor=omron + ;; + -genix*) + vendor=ns + ;; + -mvs* | -opened*) + vendor=ibm + ;; + -os400*) + vendor=ibm + ;; + -ptx*) + vendor=sequent + ;; + -tpf*) + vendor=ibm + ;; + -vxsim* | -vxworks* | -windiss*) + vendor=wrs + ;; + -aux*) + vendor=apple + ;; + -hms*) + vendor=hitachi + ;; + -mpw* | -macos*) + vendor=apple + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + vendor=atari + ;; + -vos*) + vendor=stratus + ;; + esac + basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` + ;; +esac + +echo $basic_machine$os +exit + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/config/configure b/config/configure new file mode 100755 index 00000000..a5d0bd5a --- /dev/null +++ b/config/configure @@ -0,0 +1,16302 @@ +#! /bin/sh +# Guess values for system-dependent variables and create Makefiles. +# Generated by GNU Autoconf 2.69 for dcmtk 3.6.1. +# +# Report bugs to . +# +# +# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. +# +# +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +as_myself= +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +# Use a proper internal environment variable to ensure we don't fall + # into an infinite loop, continuously re-executing ourselves. + if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then + _as_can_reexec=no; export _as_can_reexec; + # We cannot yet assume a decent shell, so we have to provide a +# neutralization value for shells without unset; and this also +# works around shells that cannot unset nonexistent variables. +# Preserve -v and -x to the replacement shell. +BASH_ENV=/dev/null +ENV=/dev/null +(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV +case $- in # (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; +esac +exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} +# Admittedly, this is quite paranoid, since all the known shells bail +# out after a failed `exec'. +$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 +as_fn_exit 255 + fi + # We don't want this to propagate to other subprocesses. + { _as_can_reexec=; unset _as_can_reexec;} +if test "x$CONFIG_SHELL" = x; then + as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which + # is contrary to our usage. Disable this feature. + alias -g '\${1+\"\$@\"}'='\"\$@\"' + setopt NO_GLOB_SUBST +else + case \`(set -o) 2>/dev/null\` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi +" + as_required="as_fn_return () { (exit \$1); } +as_fn_success () { as_fn_return 0; } +as_fn_failure () { as_fn_return 1; } +as_fn_ret_success () { return 0; } +as_fn_ret_failure () { return 1; } + +exitcode=0 +as_fn_success || { exitcode=1; echo as_fn_success failed.; } +as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } +as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } +as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } +if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : + +else + exitcode=1; echo positional parameters were not saved. +fi +test x\$exitcode = x0 || exit 1 +test -x / || exit 1" + as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO + as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO + eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && + test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 +test \$(( 1 + 1 )) = 2 || exit 1" + if (eval "$as_required") 2>/dev/null; then : + as_have_required=yes +else + as_have_required=no +fi + if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : + +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +as_found=false +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + as_found=: + case $as_dir in #( + /*) + for as_base in sh bash ksh sh5; do + # Try only shells that exist, to save several forks. + as_shell=$as_dir/$as_base + if { test -f "$as_shell" || test -f "$as_shell.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : + CONFIG_SHELL=$as_shell as_have_required=yes + if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : + break 2 +fi +fi + done;; + esac + as_found=false +done +$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : + CONFIG_SHELL=$SHELL as_have_required=yes +fi; } +IFS=$as_save_IFS + + + if test "x$CONFIG_SHELL" != x; then : + export CONFIG_SHELL + # We cannot yet assume a decent shell, so we have to provide a +# neutralization value for shells without unset; and this also +# works around shells that cannot unset nonexistent variables. +# Preserve -v and -x to the replacement shell. +BASH_ENV=/dev/null +ENV=/dev/null +(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV +case $- in # (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; +esac +exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} +# Admittedly, this is quite paranoid, since all the known shells bail +# out after a failed `exec'. +$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 +exit 255 +fi + + if test x$as_have_required = xno; then : + $as_echo "$0: This script requires a shell more modern than all" + $as_echo "$0: the shells that I found on your system." + if test x${ZSH_VERSION+set} = xset ; then + $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" + $as_echo "$0: be upgraded to zsh 4.3.4 or later." + else + $as_echo "$0: Please tell bug-autoconf@gnu.org and bugs@dcmtk.org +$0: about your system, including any error possibly output +$0: before this message. Then install a modern shell, or +$0: manually run the script under such a shell if you do +$0: have one." + fi + exit 1 +fi +fi +fi +SHELL=${CONFIG_SHELL-/bin/sh} +export SHELL +# Unset more variables known to interfere with behavior of common tools. +CLICOLOR_FORCE= GREP_OPTIONS= +unset CLICOLOR_FORCE GREP_OPTIONS + +## --------------------- ## +## M4sh Shell Functions. ## +## --------------------- ## +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} # as_fn_mkdir_p + +# as_fn_executable_p FILE +# ----------------------- +# Test if FILE is an executable regular file. +as_fn_executable_p () +{ + test -f "$1" && test -x "$1" +} # as_fn_executable_p +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 + as_fn_exit $as_status +} # as_fn_error + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + + + as_lineno_1=$LINENO as_lineno_1a=$LINENO + as_lineno_2=$LINENO as_lineno_2a=$LINENO + eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && + test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { + # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) + sed -n ' + p + /[$]LINENO/= + ' <$as_myself | + sed ' + s/[$]LINENO.*/&-/ + t lineno + b + :lineno + N + :loop + s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ + t loop + s/-\n.*// + ' >$as_me.lineno && + chmod +x "$as_me.lineno" || + { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } + + # If we had to re-execute with $CONFIG_SHELL, we're ensured to have + # already done that, so ensure we don't try to do so again and fall + # in an infinite loop. This has already happened in practice. + _as_can_reexec=no; export _as_can_reexec + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensitive to this). + . "./$as_me.lineno" + # Exit status is that of the last command. + exit +} + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -pR'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -pR' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -pR' + fi +else + as_ln_s='cp -pR' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +as_test_x='test -x' +as_executable_p=as_fn_executable_p + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +test -n "$DJDIR" || exec 7<&0 &1 + +# Name of the host. +# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, +# so uname gets run too. +ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` + +# +# Initializations. +# +ac_default_prefix=/usr/local +ac_clean_files= +ac_config_libobj_dir=. +LIBOBJS= +cross_compiling=no +subdirs= +MFLAGS= +MAKEFLAGS= + +# Identity of this package. +PACKAGE_NAME='dcmtk' +PACKAGE_TARNAME='dcmtk-3.6.1' +PACKAGE_VERSION='3.6.1' +PACKAGE_STRING='dcmtk 3.6.1' +PACKAGE_BUGREPORT='bugs@dcmtk.org' +PACKAGE_URL='http://www.dcmtk.org/' + +ac_unique_file="Makefile.in" +ac_default_prefix=/usr/local +# Factoring default headers for most tests. +ac_includes_default="\ +#include +#ifdef HAVE_SYS_TYPES_H +# include +#endif +#ifdef HAVE_SYS_STAT_H +# include +#endif +#ifdef STDC_HEADERS +# include +# include +#else +# ifdef HAVE_STDLIB_H +# include +# endif +#endif +#ifdef HAVE_STRING_H +# if !defined STDC_HEADERS && defined HAVE_MEMORY_H +# include +# endif +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif +#ifdef HAVE_INTTYPES_H +# include +#endif +#ifdef HAVE_STDINT_H +# include +#endif +#ifdef HAVE_UNISTD_H +# include +#endif" + +ac_subst_vars='LTLIBOBJS +DCMTK_ENABLE_BUILTIN_DICTIONARY +DEBUG +ICONVLIBS +SNDFILELIBS +TCPWRAPPERLIBS +XMLLIBS +ZLIBLIBS +MATHLIBS +PNGLIBS +TIFFLIBS +OPENSSLLIBS +LIBOBJS +EGREP +GREP +STRIP +BINEXT +LIBEXT +ARFLAGS +LIBTOOL +AR +RANLIB +CXXCPP +ac_ct_CXX +CXXFLAGS +CXX +CPP +OBJEXT +EXEEXT +ac_ct_CC +CPPFLAGS +LDFLAGS +CFLAGS +CC +INSTALL_DATA +INSTALL_SCRIPT +INSTALL_PROGRAM +common_makefile +SET_MAKE +host_os +host_vendor +host_cpu +host +build_os +build_vendor +build_cpu +build +PACKAGE_DATE +PACKAGE_VERSION_SUFFIX +PACKAGE_VERSION_NUMBER +target_alias +host_alias +build_alias +LIBS +ECHO_T +ECHO_N +ECHO_C +DEFS +mandir +localedir +libdir +psdir +pdfdir +dvidir +htmldir +infodir +docdir +oldincludedir +includedir +localstatedir +sharedstatedir +sysconfdir +datadir +datarootdir +libexecdir +sbindir +bindir +program_transform_name +prefix +exec_prefix +PACKAGE_URL +PACKAGE_BUGREPORT +PACKAGE_STRING +PACKAGE_VERSION +PACKAGE_TARNAME +PACKAGE_NAME +PATH_SEPARATOR +SHELL' +ac_subst_files='' +ac_user_opts=' +enable_option_checking +enable_debug +enable_threads +enable_lfs +enable_std_includes +enable_private_tags +enable_external_dict +enable_builtin_dict +enable_rpath +with_opensslinc +with_openssl +with_zlibinc +with_zlib +with_libtiffinc +with_libtiff +with_libpnginc +with_libpng +with_libxmlinc +with_libxml +with_libwrapinc +with_libwrap +with_libsndfileinc +with_libsndfile +with_libiconvinc +with_libiconv +with_cxx11_stl +' + ac_precious_vars='build_alias +host_alias +target_alias +CC +CFLAGS +LDFLAGS +LIBS +CPPFLAGS +CPP +CXX +CXXFLAGS +CCC +CXXCPP' + + +# Initialize some variables set by options. +ac_init_help= +ac_init_version=false +ac_unrecognized_opts= +ac_unrecognized_sep= +# The variables have the same names as the options, with +# dashes changed to underlines. +cache_file=/dev/null +exec_prefix=NONE +no_create= +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +verbose= +x_includes=NONE +x_libraries=NONE + +# Installation directory options. +# These are left unexpanded so users can "make install exec_prefix=/foo" +# and all the variables that are supposed to be based on exec_prefix +# by default will actually change. +# Use braces instead of parens because sh, perl, etc. also accept them. +# (The list follows the same order as the GNU Coding Standards.) +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datarootdir='${prefix}/share' +datadir='${datarootdir}/dcmtk' +sysconfdir='${prefix}/etc/dcmtk' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +includedir='${prefix}/include' +oldincludedir='/usr/include' +docdir='${datarootdir}/doc/dcmtk' +infodir='${datarootdir}/info' +htmldir='${docdir}/html' +dvidir='${docdir}' +pdfdir='${docdir}' +psdir='${docdir}' +libdir='${exec_prefix}/lib' +localedir='${datarootdir}/locale' +mandir='${datarootdir}/man' + +ac_prev= +ac_dashdash= +for ac_option +do + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval $ac_prev=\$ac_option + ac_prev= + continue + fi + + case $ac_option in + *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; + *=) ac_optarg= ;; + *) ac_optarg=yes ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case $ac_dashdash$ac_option in + --) + ac_dashdash=yes ;; + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir=$ac_optarg ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build_alias ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build_alias=$ac_optarg ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file=$ac_optarg ;; + + --config-cache | -C) + cache_file=config.cache ;; + + -datadir | --datadir | --datadi | --datad) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=*) + datadir=$ac_optarg ;; + + -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ + | --dataroo | --dataro | --datar) + ac_prev=datarootdir ;; + -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ + | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) + datarootdir=$ac_optarg ;; + + -disable-* | --disable-*) + ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=no ;; + + -docdir | --docdir | --docdi | --doc | --do) + ac_prev=docdir ;; + -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) + docdir=$ac_optarg ;; + + -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) + ac_prev=dvidir ;; + -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) + dvidir=$ac_optarg ;; + + -enable-* | --enable-*) + ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=\$ac_optarg ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix=$ac_optarg ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he | -h) + ac_init_help=long ;; + -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) + ac_init_help=recursive ;; + -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) + ac_init_help=short ;; + + -host | --host | --hos | --ho) + ac_prev=host_alias ;; + -host=* | --host=* | --hos=* | --ho=*) + host_alias=$ac_optarg ;; + + -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) + ac_prev=htmldir ;; + -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ + | --ht=*) + htmldir=$ac_optarg ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir=$ac_optarg ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir=$ac_optarg ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir=$ac_optarg ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir=$ac_optarg ;; + + -localedir | --localedir | --localedi | --localed | --locale) + ac_prev=localedir ;; + -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) + localedir=$ac_optarg ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst | --locals) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) + localstatedir=$ac_optarg ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir=$ac_optarg ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c | -n) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir=$ac_optarg ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix=$ac_optarg ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix=$ac_optarg ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix=$ac_optarg ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name=$ac_optarg ;; + + -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) + ac_prev=pdfdir ;; + -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) + pdfdir=$ac_optarg ;; + + -psdir | --psdir | --psdi | --psd | --ps) + ac_prev=psdir ;; + -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) + psdir=$ac_optarg ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir=$ac_optarg ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir=$ac_optarg ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site=$ac_optarg ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir=$ac_optarg ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir=$ac_optarg ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target_alias ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target_alias=$ac_optarg ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers | -V) + ac_init_version=: ;; + + -with-* | --with-*) + ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=\$ac_optarg ;; + + -without-* | --without-*) + ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=no ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes=$ac_optarg ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries=$ac_optarg ;; + + -*) as_fn_error $? "unrecognized option: \`$ac_option' +Try \`$0 --help' for more information" + ;; + + *=*) + ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` + # Reject names that are not valid shell variable names. + case $ac_envvar in #( + '' | [0-9]* | *[!_$as_cr_alnum]* ) + as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; + esac + eval $ac_envvar=\$ac_optarg + export $ac_envvar ;; + + *) + # FIXME: should be removed in autoconf 3.0. + $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 + expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && + $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 + : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" + ;; + + esac +done + +if test -n "$ac_prev"; then + ac_option=--`echo $ac_prev | sed 's/_/-/g'` + as_fn_error $? "missing argument to $ac_option" +fi + +if test -n "$ac_unrecognized_opts"; then + case $enable_option_checking in + no) ;; + fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; + *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; + esac +fi + +# Check all directory arguments for consistency. +for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ + datadir sysconfdir sharedstatedir localstatedir includedir \ + oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ + libdir localedir mandir +do + eval ac_val=\$$ac_var + # Remove trailing slashes. + case $ac_val in + */ ) + ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` + eval $ac_var=\$ac_val;; + esac + # Be sure to have absolute directory names. + case $ac_val in + [\\/$]* | ?:[\\/]* ) continue;; + NONE | '' ) case $ac_var in *prefix ) continue;; esac;; + esac + as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" +done + +# There might be people who depend on the old broken behavior: `$host' +# used to hold the argument of --host etc. +# FIXME: To remove some day. +build=$build_alias +host=$host_alias +target=$target_alias + +# FIXME: To remove some day. +if test "x$host_alias" != x; then + if test "x$build_alias" = x; then + cross_compiling=maybe + elif test "x$build_alias" != "x$host_alias"; then + cross_compiling=yes + fi +fi + +ac_tool_prefix= +test -n "$host_alias" && ac_tool_prefix=$host_alias- + +test "$silent" = yes && exec 6>/dev/null + + +ac_pwd=`pwd` && test -n "$ac_pwd" && +ac_ls_di=`ls -di .` && +ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || + as_fn_error $? "working directory cannot be determined" +test "X$ac_ls_di" = "X$ac_pwd_ls_di" || + as_fn_error $? "pwd does not report name of working directory" + + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then the parent directory. + ac_confdir=`$as_dirname -- "$as_myself" || +$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_myself" : 'X\(//\)[^/]' \| \ + X"$as_myself" : 'X\(//\)$' \| \ + X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_myself" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + srcdir=$ac_confdir + if test ! -r "$srcdir/$ac_unique_file"; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r "$srcdir/$ac_unique_file"; then + test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." + as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" +fi +ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" +ac_abs_confdir=`( + cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" + pwd)` +# When building in place, set srcdir=. +if test "$ac_abs_confdir" = "$ac_pwd"; then + srcdir=. +fi +# Remove unnecessary trailing slashes from srcdir. +# Double slashes in file names in object file debugging info +# mess up M-x gdb in Emacs. +case $srcdir in +*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; +esac +for ac_var in $ac_precious_vars; do + eval ac_env_${ac_var}_set=\${${ac_var}+set} + eval ac_env_${ac_var}_value=\$${ac_var} + eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} + eval ac_cv_env_${ac_var}_value=\$${ac_var} +done + +# +# Report the --help message. +# +if test "$ac_init_help" = "long"; then + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat <<_ACEOF +\`configure' configures dcmtk 3.6.1 to adapt to many kinds of systems. + +Usage: $0 [OPTION]... [VAR=VALUE]... + +To assign environment variables (e.g., CC, CFLAGS...), specify them as +VAR=VALUE. See below for descriptions of some of the useful variables. + +Defaults for the options are specified in brackets. + +Configuration: + -h, --help display this help and exit + --help=short display options specific to this package + --help=recursive display the short help of all the included packages + -V, --version display version information and exit + -q, --quiet, --silent do not print \`checking ...' messages + --cache-file=FILE cache test results in FILE [disabled] + -C, --config-cache alias for \`--cache-file=config.cache' + -n, --no-create do not create output files + --srcdir=DIR find the sources in DIR [configure dir or \`..'] + +Installation directories: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [PREFIX] + +By default, \`make install' will install all the files in +\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify +an installation prefix other than \`$ac_default_prefix' using \`--prefix', +for instance \`--prefix=\$HOME'. + +For better control, use the options below. + +Fine tuning of the installation directories: + --bindir=DIR user executables [EPREFIX/bin] + --sbindir=DIR system admin executables [EPREFIX/sbin] + --libexecdir=DIR program executables [EPREFIX/libexec] + --sysconfdir=DIR read-only single-machine data [PREFIX/etc/dcmtk] + --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] + --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --libdir=DIR object code libraries [EPREFIX/lib] + --includedir=DIR C header files [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc [/usr/include] + --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] + --datadir=DIR read-only arch.-independent data [DATAROOTDIR/dcmtk] + --infodir=DIR info documentation [DATAROOTDIR/info] + --localedir=DIR locale-dependent data [DATAROOTDIR/locale] + --mandir=DIR man documentation [DATAROOTDIR/man] + --docdir=DIR documentation root [DATAROOTDIR/doc/dcmtk] + --htmldir=DIR html documentation [DOCDIR/html] + --dvidir=DIR dvi documentation [DOCDIR] + --pdfdir=DIR pdf documentation [DOCDIR] + --psdir=DIR ps documentation [DOCDIR] +_ACEOF + + cat <<\_ACEOF + +System types: + --build=BUILD configure for building on BUILD [guessed] + --host=HOST cross-compile to build programs to run on HOST [BUILD] +_ACEOF +fi + +if test -n "$ac_init_help"; then + case $ac_init_help in + short | recursive ) echo "Configuration of dcmtk 3.6.1:";; + esac + cat <<\_ACEOF + +Optional Features: + --disable-option-checking ignore unrecognized --enable/--with options + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --enable-debug compile with debug code, don't optimize + --disable-debug compile without debug code (default) + --enable-threads=TYPE compile with MT support (posix/solaris/auto=default) + --disable-threads compile without MT support + --enable-lfs=TYPE compile with LFS support (lfs/lfs64/auto=default) + --disable-lfs compile without LFS support + --enable-std-includes use C++ ANSI standard includes (default: auto) + --disable-std-includes use old C++ includes + --enable-private-tags enable private tag dictionary + --disable-private-tags don't enable private tag dictionary (default) + --enable-external-dict enable loading of external dictionary (default) + --disable-external-dict don't load external dictionary + --enable-builtin-dict enable loading of built-in dictionary + --disable-builtin-dict don't load built-in dictionary (default) + --disable-rpath do not hardcode runtime library paths + +Optional Packages: + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --with-opensslinc=DIR location of OpenSSL includes and libraries + --with-openssl include OpenSSL support (default: auto) + --without-openssl don't include OpenSSL support + --with-zlibinc=DIR location of zlib includes and libraries + --with-zlib include zlib support (default: auto) + --without-zlib don't include zlib support + --with-libtiffinc=DIR location of libtiff includes and libraries + --with-libtiff include libtiff support (default: auto) + --without-libtiff don't include libtiff support + --with-libpnginc=DIR location of libpng includes and libraries + --with-libpng include libpng support (default: auto) + --without-libpng don't include libpng support + --with-libxmlinc=DIR location of libxml includes and libraries + --with-libxml include libxml support (default: auto) + --without-libxml don't include libxml support + --with-libwrapinc=DIR location of libwrap includes and libraries + --with-libwrap include libwrap support (default: auto) + --without-libwrap don't include libwrap support + --with-libsndfileinc=DIR + location of libsndfile includes and libraries + --with-libsndfile include libsndfile support (default: auto) + --without-libsndfile don't include libsndfile support + --with-libiconvinc=DIR location of libiconv includes and libraries + --with-libiconv include libiconv support (default: auto) + --without-libiconv don't include libiconv support + --with-cxx11-stl enable C++11 STL + --without-cxx11-stl disable C++11 STL (default) + +Some influential environment variables: + CC C compiler command + CFLAGS C compiler flags + LDFLAGS linker flags, e.g. -L if you have libraries in a + nonstandard directory + LIBS libraries to pass to the linker, e.g. -l + CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if + you have headers in a nonstandard directory + CPP C preprocessor + CXX C++ compiler command + CXXFLAGS C++ compiler flags + CXXCPP C++ preprocessor + +Use these variables to override the choices made by `configure' or to help +it to find libraries and programs with nonstandard names/locations. + +Report bugs to . +dcmtk home page: . +_ACEOF +ac_status=$? +fi + +if test "$ac_init_help" = "recursive"; then + # If there are subdirs, report their specific --help. + for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue + test -d "$ac_dir" || + { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || + continue + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + cd "$ac_dir" || { ac_status=$?; continue; } + # Check for guested configure. + if test -f "$ac_srcdir/configure.gnu"; then + echo && + $SHELL "$ac_srcdir/configure.gnu" --help=recursive + elif test -f "$ac_srcdir/configure"; then + echo && + $SHELL "$ac_srcdir/configure" --help=recursive + else + $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 + fi || ac_status=$? + cd "$ac_pwd" || { ac_status=$?; break; } + done +fi + +test -n "$ac_init_help" && exit $ac_status +if $ac_init_version; then + cat <<\_ACEOF +dcmtk configure 3.6.1 +generated by GNU Autoconf 2.69 + +Copyright (C) 2012 Free Software Foundation, Inc. +This configure script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it. +_ACEOF + exit +fi + +## ------------------------ ## +## Autoconf initialization. ## +## ------------------------ ## + +# ac_fn_c_try_compile LINENO +# -------------------------- +# Try to compile conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext + if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_compile + +# ac_fn_c_try_cpp LINENO +# ---------------------- +# Try to preprocess conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_cpp () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } > conftest.i && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_cpp + +# ac_fn_cxx_try_compile LINENO +# ---------------------------- +# Try to compile conftest.$ac_ext, and return whether this succeeded. +ac_fn_cxx_try_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext + if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_cxx_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_cxx_try_compile + +# ac_fn_cxx_try_cpp LINENO +# ------------------------ +# Try to preprocess conftest.$ac_ext, and return whether this succeeded. +ac_fn_cxx_try_cpp () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } > conftest.i && { + test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" || + test ! -s conftest.err + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_cxx_try_cpp + +# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES +# ------------------------------------------------------- +# Tests whether HEADER exists, giving a warning if it cannot be compiled using +# the include files in INCLUDES and setting the cache variable VAR +# accordingly. +ac_fn_c_check_header_mongrel () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if eval \${$3+:} false; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +else + # Is the header compilable? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 +$as_echo_n "checking $2 usability... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +#include <$2> +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_header_compiler=yes +else + ac_header_compiler=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 +$as_echo "$ac_header_compiler" >&6; } + +# Is the header present? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 +$as_echo_n "checking $2 presence... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <$2> +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + ac_header_preproc=yes +else + ac_header_preproc=no +fi +rm -f conftest.err conftest.i conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 +$as_echo "$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #(( + yes:no: ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 +$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} + ;; + no:yes:* ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 +$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 +$as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 +$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 +$as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} +( $as_echo "## ----------------------------- ## +## Report this to bugs@dcmtk.org ## +## ----------------------------- ##" + ) | sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + eval "$3=\$ac_header_compiler" +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_header_mongrel + +# ac_fn_c_try_run LINENO +# ---------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes +# that executables *can* be run. +ac_fn_c_try_run () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then : + ac_retval=0 +else + $as_echo "$as_me: program exited with status $ac_status" >&5 + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=$ac_status +fi + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_run + +# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES +# ------------------------------------------------------- +# Tests whether HEADER exists and can be compiled using the include files in +# INCLUDES, setting the cache variable VAR accordingly. +ac_fn_c_check_header_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +#include <$2> +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_header_compile + +# ac_fn_c_try_link LINENO +# ----------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_link () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext conftest$ac_exeext + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + test -x conftest$ac_exeext + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information + # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would + # interfere with the next link command; also delete a directory that is + # left behind by Apple's compiler. We do this before executing the actions. + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_link + +# ac_fn_c_check_type LINENO TYPE VAR INCLUDES +# ------------------------------------------- +# Tests whether TYPE exists after having included INCLUDES, setting cache +# variable VAR accordingly. +ac_fn_c_check_type () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + eval "$3=no" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +if (sizeof ($2)) + return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +if (sizeof (($2))) + return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +else + eval "$3=yes" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_type + +# ac_fn_c_check_func LINENO FUNC VAR +# ---------------------------------- +# Tests whether FUNC exists, setting the cache variable VAR accordingly +ac_fn_c_check_func () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +/* Define $2 to an innocuous variant, in case declares $2. + For example, HP-UX 11i declares gettimeofday. */ +#define $2 innocuous_$2 + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $2 (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $2 + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $2 (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$2 || defined __stub___$2 +choke me +#endif + +int +main () +{ +return $2 (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_func + +# ac_fn_cxx_try_link LINENO +# ------------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. +ac_fn_cxx_try_link () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext conftest$ac_exeext + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_cxx_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + test -x conftest$ac_exeext + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information + # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would + # interfere with the next link command; also delete a directory that is + # left behind by Apple's compiler. We do this before executing the actions. + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_cxx_try_link + +# ac_fn_cxx_try_run LINENO +# ------------------------ +# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes +# that executables *can* be run. +ac_fn_cxx_try_run () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then : + ac_retval=0 +else + $as_echo "$as_me: program exited with status $ac_status" >&5 + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=$ac_status +fi + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_cxx_try_run + +# ac_fn_cxx_check_header_mongrel LINENO HEADER VAR INCLUDES +# --------------------------------------------------------- +# Tests whether HEADER exists, giving a warning if it cannot be compiled using +# the include files in INCLUDES and setting the cache variable VAR +# accordingly. +ac_fn_cxx_check_header_mongrel () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if eval \${$3+:} false; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +else + # Is the header compilable? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 +$as_echo_n "checking $2 usability... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +#include <$2> +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_header_compiler=yes +else + ac_header_compiler=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 +$as_echo "$ac_header_compiler" >&6; } + +# Is the header present? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 +$as_echo_n "checking $2 presence... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <$2> +_ACEOF +if ac_fn_cxx_try_cpp "$LINENO"; then : + ac_header_preproc=yes +else + ac_header_preproc=no +fi +rm -f conftest.err conftest.i conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 +$as_echo "$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_cxx_preproc_warn_flag in #(( + yes:no: ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 +$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} + ;; + no:yes:* ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 +$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 +$as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 +$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 +$as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} +( $as_echo "## ----------------------------- ## +## Report this to bugs@dcmtk.org ## +## ----------------------------- ##" + ) | sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + eval "$3=\$ac_header_compiler" +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_cxx_check_header_mongrel + +# ac_fn_cxx_compute_int LINENO EXPR VAR INCLUDES +# ---------------------------------------------- +# Tries to find the compile-time value of EXPR in a program that includes +# INCLUDES, setting VAR accordingly. Returns whether the value could be +# computed +ac_fn_cxx_compute_int () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if test "$cross_compiling" = yes; then + # Depending upon the size, compute the lo and hi bounds. +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +static int test_array [1 - 2 * !(($2) >= 0)]; +test_array [0] = 0; +return test_array [0]; + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_lo=0 ac_mid=0 + while :; do + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +static int test_array [1 - 2 * !(($2) <= $ac_mid)]; +test_array [0] = 0; +return test_array [0]; + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_hi=$ac_mid; break +else + as_fn_arith $ac_mid + 1 && ac_lo=$as_val + if test $ac_lo -le $ac_mid; then + ac_lo= ac_hi= + break + fi + as_fn_arith 2 '*' $ac_mid + 1 && ac_mid=$as_val +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + done +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +static int test_array [1 - 2 * !(($2) < 0)]; +test_array [0] = 0; +return test_array [0]; + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_hi=-1 ac_mid=-1 + while :; do + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +static int test_array [1 - 2 * !(($2) >= $ac_mid)]; +test_array [0] = 0; +return test_array [0]; + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_lo=$ac_mid; break +else + as_fn_arith '(' $ac_mid ')' - 1 && ac_hi=$as_val + if test $ac_mid -le $ac_hi; then + ac_lo= ac_hi= + break + fi + as_fn_arith 2 '*' $ac_mid && ac_mid=$as_val +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + done +else + ac_lo= ac_hi= +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +# Binary search between lo and hi bounds. +while test "x$ac_lo" != "x$ac_hi"; do + as_fn_arith '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo && ac_mid=$as_val + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +static int test_array [1 - 2 * !(($2) <= $ac_mid)]; +test_array [0] = 0; +return test_array [0]; + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_hi=$ac_mid +else + as_fn_arith '(' $ac_mid ')' + 1 && ac_lo=$as_val +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +done +case $ac_lo in #(( +?*) eval "$3=\$ac_lo"; ac_retval=0 ;; +'') ac_retval=1 ;; +esac + else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +static long int longval () { return $2; } +static unsigned long int ulongval () { return $2; } +#include +#include +int +main () +{ + + FILE *f = fopen ("conftest.val", "w"); + if (! f) + return 1; + if (($2) < 0) + { + long int i = longval (); + if (i != ($2)) + return 1; + fprintf (f, "%ld", i); + } + else + { + unsigned long int i = ulongval (); + if (i != ($2)) + return 1; + fprintf (f, "%lu", i); + } + /* Do not output a trailing newline, as this causes \r\n confusion + on some platforms. */ + return ferror (f) || fclose (f) != 0; + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_run "$LINENO"; then : + echo >>conftest.val; read $3 config.log <<_ACEOF +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. + +It was created by dcmtk $as_me 3.6.1, which was +generated by GNU Autoconf 2.69. Invocation command line was + + $ $0 $@ + +_ACEOF +exec 5>>config.log +{ +cat <<_ASUNAME +## --------- ## +## Platform. ## +## --------- ## + +hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` + +/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` +/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` +/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` +/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` + +_ASUNAME + +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + $as_echo "PATH: $as_dir" + done +IFS=$as_save_IFS + +} >&5 + +cat >&5 <<_ACEOF + + +## ----------- ## +## Core tests. ## +## ----------- ## + +_ACEOF + + +# Keep a trace of the command line. +# Strip out --no-create and --no-recursion so they do not pile up. +# Strip out --silent because we don't want to record it for future runs. +# Also quote any args containing shell meta-characters. +# Make two passes to allow for proper duplicate-argument suppression. +ac_configure_args= +ac_configure_args0= +ac_configure_args1= +ac_must_keep_next=false +for ac_pass in 1 2 +do + for ac_arg + do + case $ac_arg in + -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + continue ;; + *\'*) + ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + case $ac_pass in + 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; + 2) + as_fn_append ac_configure_args1 " '$ac_arg'" + if test $ac_must_keep_next = true; then + ac_must_keep_next=false # Got value, back to normal. + else + case $ac_arg in + *=* | --config-cache | -C | -disable-* | --disable-* \ + | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ + | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ + | -with-* | --with-* | -without-* | --without-* | --x) + case "$ac_configure_args0 " in + "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; + esac + ;; + -* ) ac_must_keep_next=true ;; + esac + fi + as_fn_append ac_configure_args " '$ac_arg'" + ;; + esac + done +done +{ ac_configure_args0=; unset ac_configure_args0;} +{ ac_configure_args1=; unset ac_configure_args1;} + +# When interrupted or exit'd, cleanup temporary files, and complete +# config.log. We remove comments because anyway the quotes in there +# would cause problems or look ugly. +# WARNING: Use '\'' to represent an apostrophe within the trap. +# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. +trap 'exit_status=$? + # Save into config.log some information that might help in debugging. + { + echo + + $as_echo "## ---------------- ## +## Cache variables. ## +## ---------------- ##" + echo + # The following way of writing the cache mishandles newlines in values, +( + for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + (set) 2>&1 | + case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + sed -n \ + "s/'\''/'\''\\\\'\'''\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" + ;; #( + *) + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) + echo + + $as_echo "## ----------------- ## +## Output variables. ## +## ----------------- ##" + echo + for ac_var in $ac_subst_vars + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + + if test -n "$ac_subst_files"; then + $as_echo "## ------------------- ## +## File substitutions. ## +## ------------------- ##" + echo + for ac_var in $ac_subst_files + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + fi + + if test -s confdefs.h; then + $as_echo "## ----------- ## +## confdefs.h. ## +## ----------- ##" + echo + cat confdefs.h + echo + fi + test "$ac_signal" != 0 && + $as_echo "$as_me: caught signal $ac_signal" + $as_echo "$as_me: exit $exit_status" + } >&5 + rm -f core *.core core.conftest.* && + rm -f -r conftest* confdefs* conf$$* $ac_clean_files && + exit $exit_status +' 0 +for ac_signal in 1 2 13 15; do + trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal +done +ac_signal=0 + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -f -r conftest* confdefs.h + +$as_echo "/* confdefs.h */" > confdefs.h + +# Predefined preprocessor variables. + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_NAME "$PACKAGE_NAME" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_TARNAME "$PACKAGE_TARNAME" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_VERSION "$PACKAGE_VERSION" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_STRING "$PACKAGE_STRING" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_URL "$PACKAGE_URL" +_ACEOF + + +# Let the site file select an alternate cache file if it wants to. +# Prefer an explicitly selected file to automatically selected ones. +ac_site_file1=NONE +ac_site_file2=NONE +if test -n "$CONFIG_SITE"; then + # We do not want a PATH search for config.site. + case $CONFIG_SITE in #(( + -*) ac_site_file1=./$CONFIG_SITE;; + */*) ac_site_file1=$CONFIG_SITE;; + *) ac_site_file1=./$CONFIG_SITE;; + esac +elif test "x$prefix" != xNONE; then + ac_site_file1=$prefix/share/config.site + ac_site_file2=$prefix/etc/config.site +else + ac_site_file1=$ac_default_prefix/share/config.site + ac_site_file2=$ac_default_prefix/etc/config.site +fi +for ac_site_file in "$ac_site_file1" "$ac_site_file2" +do + test "x$ac_site_file" = xNONE && continue + if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 +$as_echo "$as_me: loading site script $ac_site_file" >&6;} + sed 's/^/| /' "$ac_site_file" >&5 + . "$ac_site_file" \ + || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "failed to load site script $ac_site_file +See \`config.log' for more details" "$LINENO" 5; } + fi +done + +if test -r "$cache_file"; then + # Some versions of bash will fail to source /dev/null (special files + # actually), so we avoid doing that. DJGPP emulates it as a regular file. + if test /dev/null != "$cache_file" && test -f "$cache_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 +$as_echo "$as_me: loading cache $cache_file" >&6;} + case $cache_file in + [\\/]* | ?:[\\/]* ) . "$cache_file";; + *) . "./$cache_file";; + esac + fi +else + { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 +$as_echo "$as_me: creating cache $cache_file" >&6;} + >$cache_file +fi + +# Check that the precious variables saved in the cache have kept the same +# value. +ac_cache_corrupted=false +for ac_var in $ac_precious_vars; do + eval ac_old_set=\$ac_cv_env_${ac_var}_set + eval ac_new_set=\$ac_env_${ac_var}_set + eval ac_old_val=\$ac_cv_env_${ac_var}_value + eval ac_new_val=\$ac_env_${ac_var}_value + case $ac_old_set,$ac_new_set in + set,) + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,set) + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,);; + *) + if test "x$ac_old_val" != "x$ac_new_val"; then + # differences in whitespace do not lead to failure. + ac_old_val_w=`echo x $ac_old_val` + ac_new_val_w=`echo x $ac_new_val` + if test "$ac_old_val_w" != "$ac_new_val_w"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 +$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} + ac_cache_corrupted=: + else + { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 +$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} + eval $ac_var=\$ac_old_val + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 +$as_echo "$as_me: former value: \`$ac_old_val'" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 +$as_echo "$as_me: current value: \`$ac_new_val'" >&2;} + fi;; + esac + # Pass precious variables to config.status. + if test "$ac_new_set" = set; then + case $ac_new_val in + *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; + *) ac_arg=$ac_var=$ac_new_val ;; + esac + case " $ac_configure_args " in + *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. + *) as_fn_append ac_configure_args " '$ac_arg'" ;; + esac + fi +done +if $ac_cache_corrupted; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 +$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} + as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 +fi +## -------------------- ## +## Main body of script. ## +## -------------------- ## + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + + +ac_config_headers="$ac_config_headers include/dcmtk/config/osconfig.h" + + + +PACKAGE_VERSION_NUMBER=361 +PACKAGE_VERSION_SUFFIX="" +PACKAGE_DATE="DEV" + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_VERSION_NUMBER ${PACKAGE_VERSION_NUMBER} +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_VERSION_SUFFIX "${PACKAGE_VERSION_SUFFIX}" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_DATE "${PACKAGE_DATE}" +_ACEOF + + + + + + + +ac_aux_dir= +for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do + if test -f "$ac_dir/install-sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f "$ac_dir/install.sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + elif test -f "$ac_dir/shtool"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/shtool install -c" + break + fi +done +if test -z "$ac_aux_dir"; then + as_fn_error $? "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5 +fi + +# These three variables are undocumented and unsupported, +# and are intended to be withdrawn in a future Autoconf release. +# They can cause serious problems if a builder's source tree is in a directory +# whose full name contains unusual characters. +ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. +ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. +ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. + + +# Make sure we can run config.sub. +$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || + as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5 + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5 +$as_echo_n "checking build system type... " >&6; } +if ${ac_cv_build+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_build_alias=$build_alias +test "x$ac_build_alias" = x && + ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"` +test "x$ac_build_alias" = x && + as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5 +ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` || + as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5 + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5 +$as_echo "$ac_cv_build" >&6; } +case $ac_cv_build in +*-*-*) ;; +*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;; +esac +build=$ac_cv_build +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_build +shift +build_cpu=$1 +build_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +build_os=$* +IFS=$ac_save_IFS +case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5 +$as_echo_n "checking host system type... " >&6; } +if ${ac_cv_host+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "x$host_alias" = x; then + ac_cv_host=$ac_cv_build +else + ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` || + as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5 +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5 +$as_echo "$ac_cv_host" >&6; } +case $ac_cv_host in +*-*-*) ;; +*) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;; +esac +host=$ac_cv_host +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_host +shift +host_cpu=$1 +host_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +host_os=$* +IFS=$ac_save_IFS +case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac + + + +cat >>confdefs.h <<_ACEOF +#define CANONICAL_HOST_TYPE "${host}" +_ACEOF + + +case "${host}" in + *-*-cygwin) + BINEXT=".exe" + ;; + *-*-mingw32) + BINEXT=".exe" + ;; + *) + BINEXT="" + ;; +esac + + +if test "x$prefix" = xNONE ; then + +cat >>confdefs.h <<_ACEOF +#define DCMTK_PREFIX "${ac_default_prefix}" +_ACEOF + +else + +cat >>confdefs.h <<_ACEOF +#define DCMTK_PREFIX "${prefix}" +_ACEOF + +fi + +DATA_DIR="${datadir}" +DATA_DIR=`( + test "$prefix" = NONE && prefix=${ac_default_prefix} + test "$exec_prefix" = NONE && exec_prefix=${prefix} + eval eval echo "$DATA_DIR" +)` + +cat >>confdefs.h <<_ACEOF +#define DCM_DICT_DEFAULT_PATH "${DATA_DIR}/dicom.dic" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define DEFAULT_SUPPORT_DATA_DIR "${DATA_DIR}/" +_ACEOF + + +CONF_DIR="${sysconfdir}" +CONF_DIR=`( + test "$prefix" = NONE && prefix=${ac_default_prefix} + test "$exec_prefix" = NONE && exec_prefix=${prefix} + eval echo "$CONF_DIR" +)` + +cat >>confdefs.h <<_ACEOF +#define DEFAULT_CONFIGURATION_DIR "${CONF_DIR}/" +_ACEOF + + + + + + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 +$as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } +set x ${MAKE-make} +ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` +if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat >conftest.make <<\_ACEOF +SHELL = /bin/sh +all: + @echo '@@@%%%=$(MAKE)=@@@%%%' +_ACEOF +# GNU make sometimes prints "make[1]: Entering ...", which would confuse us. +case `${MAKE-make} -f conftest.make 2>/dev/null` in + *@@@%%%=?*=@@@%%%*) + eval ac_cv_prog_make_${ac_make}_set=yes;; + *) + eval ac_cv_prog_make_${ac_make}_set=no;; +esac +rm -f conftest.make +fi +if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + SET_MAKE= +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + SET_MAKE="MAKE=${MAKE-make}" +fi + + +common_makefile=Makefile.def + + +ac_aux_dir= +for ac_dir in . "$srcdir"/.; do + if test -f "$ac_dir/install-sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f "$ac_dir/install.sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + elif test -f "$ac_dir/shtool"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/shtool install -c" + break + fi +done +if test -z "$ac_aux_dir"; then + as_fn_error $? "cannot find install-sh, install.sh, or shtool in . \"$srcdir\"/." "$LINENO" 5 +fi + +# These three variables are undocumented and unsupported, +# and are intended to be withdrawn in a future Autoconf release. +# They can cause serious problems if a builder's source tree is in a directory +# whose full name contains unusual characters. +ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. +ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. +ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. + + + + +# Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AmigaOS /C/install, which installs bootblocks on floppy discs +# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# OS/2's system install, which has a completely different semantic +# ./install, which can be erroneously created by make from ./install.sh. +# Reject install programs that cannot install multiple files. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5 +$as_echo_n "checking for a BSD-compatible install... " >&6; } +if test -z "$INSTALL"; then +if ${ac_cv_path_install+:} false; then : + $as_echo_n "(cached) " >&6 +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + # Account for people who put trailing slashes in PATH elements. +case $as_dir/ in #(( + ./ | .// | /[cC]/* | \ + /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ + ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \ + /usr/ucb/* ) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + # Don't use installbsd from OSF since it installs stuff as root + # by default. + for ac_prog in ginstall scoinst install; do + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then + if test $ac_prog = install && + grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + : + elif test $ac_prog = install && + grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # program-specific install script used by HP pwplus--don't use. + : + else + rm -rf conftest.one conftest.two conftest.dir + echo one > conftest.one + echo two > conftest.two + mkdir conftest.dir + if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" && + test -s conftest.one && test -s conftest.two && + test -s conftest.dir/conftest.one && + test -s conftest.dir/conftest.two + then + ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" + break 3 + fi + fi + fi + done + done + ;; +esac + + done +IFS=$as_save_IFS + +rm -rf conftest.one conftest.two conftest.dir + +fi + if test "${ac_cv_path_install+set}" = set; then + INSTALL=$ac_cv_path_install + else + # As a last resort, use the slow shell script. Don't cache a + # value for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the value is a relative name. + INSTALL=$ac_install_sh + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5 +$as_echo "$INSTALL" >&6; } + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' + +test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. +set dummy ${ac_tool_prefix}gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +else + CC="$ac_cv_prog_CC" +fi + +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. +set dummy ${ac_tool_prefix}cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + fi +fi +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + ac_prog_rejected=no +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# != 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" + fi +fi +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + for ac_prog in cl.exe + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$CC" && break + done +fi +if test -z "$CC"; then + ac_ct_CC=$CC + for ac_prog in cl.exe +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_CC" && break +done + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +fi + +fi + + +test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "no acceptable C compiler found in \$PATH +See \`config.log' for more details" "$LINENO" 5; } + +# Provide some information about the compiler. +$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 +set X $ac_compile +ac_compiler=$2 +for ac_option in --version -v -V -qversion; do + { { ac_try="$ac_compiler $ac_option >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compiler $ac_option >&5") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + sed '10a\ +... rest of stderr output deleted ... + 10q' conftest.err >conftest.er1 + cat conftest.er1 >&5 + fi + rm -f conftest.er1 conftest.err + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } +done + +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" +# Try to create an executable without -o first, disregard a.out. +# It will help us diagnose broken compilers, and finding out an intuition +# of exeext. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 +$as_echo_n "checking whether the C compiler works... " >&6; } +ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` + +# The possible output files: +ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" + +ac_rmfiles= +for ac_file in $ac_files +do + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + * ) ac_rmfiles="$ac_rmfiles $ac_file";; + esac +done +rm -f $ac_rmfiles + +if { { ac_try="$ac_link_default" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link_default") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. +# So ignore a value of `no', otherwise this would lead to `EXEEXT = no' +# in a Makefile. We should not override ac_cv_exeext if it was cached, +# so that the user can short-circuit this test for compilers unknown to +# Autoconf. +for ac_file in $ac_files '' +do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) + ;; + [ab].out ) + # We found the default executable, but exeext='' is most + # certainly right. + break;; + *.* ) + if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; + then :; else + ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + fi + # We set ac_cv_exeext here because the later test for it is not + # safe: cross compilers may not add the suffix if given an `-o' + # argument, so we may need to know it at that point already. + # Even if this section looks crufty: it has the advantage of + # actually working. + break;; + * ) + break;; + esac +done +test "$ac_cv_exeext" = no && ac_cv_exeext= + +else + ac_file='' +fi +if test -z "$ac_file"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +$as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "C compiler cannot create executables +See \`config.log' for more details" "$LINENO" 5; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 +$as_echo_n "checking for C compiler default output file name... " >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 +$as_echo "$ac_file" >&6; } +ac_exeext=$ac_cv_exeext + +rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out +ac_clean_files=$ac_clean_files_save +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 +$as_echo_n "checking for suffix of executables... " >&6; } +if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + # If both `conftest.exe' and `conftest' are `present' (well, observable) +# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will +# work properly (i.e., refer to `conftest.exe'), while it won't with +# `rm'. +for ac_file in conftest.exe conftest conftest.*; do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + break;; + * ) break;; + esac +done +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details" "$LINENO" 5; } +fi +rm -f conftest conftest$ac_cv_exeext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 +$as_echo "$ac_cv_exeext" >&6; } + +rm -f conftest.$ac_ext +EXEEXT=$ac_cv_exeext +ac_exeext=$EXEEXT +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +FILE *f = fopen ("conftest.out", "w"); + return ferror (f) || fclose (f) != 0; + + ; + return 0; +} +_ACEOF +ac_clean_files="$ac_clean_files conftest.out" +# Check that the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 +$as_echo_n "checking whether we are cross compiling... " >&6; } +if test "$cross_compiling" != yes; then + { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + if { ac_try='./conftest$ac_cv_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then + cross_compiling=no + else + if test "$cross_compiling" = maybe; then + cross_compiling=yes + else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot run C compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details" "$LINENO" 5; } + fi + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 +$as_echo "$cross_compiling" >&6; } + +rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out +ac_clean_files=$ac_clean_files_save +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 +$as_echo_n "checking for suffix of object files... " >&6; } +if ${ac_cv_objext+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.o conftest.obj +if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + for ac_file in conftest.o conftest.obj conftest.*; do + test -f "$ac_file" || continue; + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; + *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` + break;; + esac +done +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot compute suffix of object files: cannot compile +See \`config.log' for more details" "$LINENO" 5; } +fi +rm -f conftest.$ac_cv_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 +$as_echo "$ac_cv_objext" >&6; } +OBJEXT=$ac_cv_objext +ac_objext=$OBJEXT +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 +$as_echo_n "checking whether we are using the GNU C compiler... " >&6; } +if ${ac_cv_c_compiler_gnu+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_compiler_gnu=yes +else + ac_compiler_gnu=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_c_compiler_gnu=$ac_compiler_gnu + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 +$as_echo "$ac_cv_c_compiler_gnu" >&6; } +if test $ac_compiler_gnu = yes; then + GCC=yes +else + GCC= +fi +ac_test_CFLAGS=${CFLAGS+set} +ac_save_CFLAGS=$CFLAGS +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 +$as_echo_n "checking whether $CC accepts -g... " >&6; } +if ${ac_cv_prog_cc_g+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_save_c_werror_flag=$ac_c_werror_flag + ac_c_werror_flag=yes + ac_cv_prog_cc_g=no + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +else + CFLAGS="" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +else + ac_c_werror_flag=$ac_save_c_werror_flag + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_c_werror_flag=$ac_save_c_werror_flag +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 +$as_echo "$ac_cv_prog_cc_g" >&6; } +if test "$ac_test_CFLAGS" = set; then + CFLAGS=$ac_save_CFLAGS +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 +$as_echo_n "checking for $CC option to accept ISO C89... " >&6; } +if ${ac_cv_prog_cc_c89+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_prog_cc_c89=no +ac_save_CC=$CC +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +struct stat; +/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ +struct buf { int x; }; +FILE * (*rcsopen) (struct buf *, struct stat *, int); +static char *e (p, i) + char **p; + int i; +{ + return p[i]; +} +static char *f (char * (*g) (char **, int), char **p, ...) +{ + char *s; + va_list v; + va_start (v,p); + s = g (p, va_arg (v,int)); + va_end (v); + return s; +} + +/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has + function prototypes and stuff, but not '\xHH' hex character constants. + These don't provoke an error unfortunately, instead are silently treated + as 'x'. The following induces an error, until -std is added to get + proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an + array size at least. It's necessary to write '\x00'==0 to get something + that's true only with -std. */ +int osf4_cc_array ['\x00' == 0 ? 1 : -1]; + +/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters + inside strings and character constants. */ +#define FOO(x) 'x' +int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; + +int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);}; +int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); +int argc; +char **argv; +int +main () +{ +return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; + ; + return 0; +} +_ACEOF +for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ + -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_c89=$ac_arg +fi +rm -f core conftest.err conftest.$ac_objext + test "x$ac_cv_prog_cc_c89" != "xno" && break +done +rm -f conftest.$ac_ext +CC=$ac_save_CC + +fi +# AC_CACHE_VAL +case "x$ac_cv_prog_cc_c89" in + x) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 +$as_echo "none needed" >&6; } ;; + xno) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 +$as_echo "unsupported" >&6; } ;; + *) + CC="$CC $ac_cv_prog_cc_c89" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 +$as_echo "$ac_cv_prog_cc_c89" >&6; } ;; +esac +if test "x$ac_cv_prog_cc_c89" != xno; then : + +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 +$as_echo_n "checking how to run the C preprocessor... " >&6; } +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then + if ${ac_cv_prog_CPP+:} false; then : + $as_echo_n "(cached) " >&6 +else + # Double quotes because CPP needs to be expanded + for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" + do + ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + break +fi + + done + ac_cv_prog_CPP=$CPP + +fi + CPP=$ac_cv_prog_CPP +else + ac_cv_prog_CPP=$CPP +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 +$as_echo "$CPP" >&6; } +ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details" "$LINENO" 5; } +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +for ac_prog in $CCC c++ cc++ g++ gcc CC cxx +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CXX+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CXX"; then + ac_cv_prog_CXX="$CXX" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CXX="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CXX=$ac_cv_prog_CXX +if test -n "$CXX"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXX" >&5 +$as_echo "$CXX" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$CXX" && break +done +test -n "$CXX" || CXX="gcc" + + +pedantic="" +if test -f /bin/uname ; then + os=`uname -s` + rev=`uname -r` + if test \( "$os" = SunOS \) ; then + case "$rev" in + # only use the -pedantic compiler option on + # Solaris 2 machines. + 5.*) pedantic="-pedantic" ;; + esac + fi +fi +if test "${CXXFLAGS}set" = set ; then + case "$CXX" in + c++|g++|gcc) + CXXFLAGS="-Wall $pedantic" + CFLAGS="-Wall $pedantic" + ;; + cc++) + CXXFLAGS="-Wall" + CFLAGS="-Wall" + ;; + *) + CXXFLAGS="" + CFLAGS="" + ;; + esac +fi + +ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu +if test -z "$CXX"; then + if test -n "$CCC"; then + CXX=$CCC + else + if test -n "$ac_tool_prefix"; then + for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CXX+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CXX"; then + ac_cv_prog_CXX="$CXX" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CXX="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CXX=$ac_cv_prog_CXX +if test -n "$CXX"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXX" >&5 +$as_echo "$CXX" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$CXX" && break + done +fi +if test -z "$CXX"; then + ac_ct_CXX=$CXX + for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CXX+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CXX"; then + ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CXX="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CXX=$ac_cv_prog_ac_ct_CXX +if test -n "$ac_ct_CXX"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CXX" >&5 +$as_echo "$ac_ct_CXX" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_CXX" && break +done + + if test "x$ac_ct_CXX" = x; then + CXX="g++" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CXX=$ac_ct_CXX + fi +fi + + fi +fi +# Provide some information about the compiler. +$as_echo "$as_me:${as_lineno-$LINENO}: checking for C++ compiler version" >&5 +set X $ac_compile +ac_compiler=$2 +for ac_option in --version -v -V -qversion; do + { { ac_try="$ac_compiler $ac_option >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compiler $ac_option >&5") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + sed '10a\ +... rest of stderr output deleted ... + 10q' conftest.err >conftest.er1 + cat conftest.er1 >&5 + fi + rm -f conftest.er1 conftest.err + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } +done + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C++ compiler" >&5 +$as_echo_n "checking whether we are using the GNU C++ compiler... " >&6; } +if ${ac_cv_cxx_compiler_gnu+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_compiler_gnu=yes +else + ac_compiler_gnu=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_cxx_compiler_gnu=$ac_compiler_gnu + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cxx_compiler_gnu" >&5 +$as_echo "$ac_cv_cxx_compiler_gnu" >&6; } +if test $ac_compiler_gnu = yes; then + GXX=yes +else + GXX= +fi +ac_test_CXXFLAGS=${CXXFLAGS+set} +ac_save_CXXFLAGS=$CXXFLAGS +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX accepts -g" >&5 +$as_echo_n "checking whether $CXX accepts -g... " >&6; } +if ${ac_cv_prog_cxx_g+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_save_cxx_werror_flag=$ac_cxx_werror_flag + ac_cxx_werror_flag=yes + ac_cv_prog_cxx_g=no + CXXFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_cv_prog_cxx_g=yes +else + CXXFLAGS="" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + +else + ac_cxx_werror_flag=$ac_save_cxx_werror_flag + CXXFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_cv_prog_cxx_g=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_cxx_werror_flag=$ac_save_cxx_werror_flag +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_g" >&5 +$as_echo "$ac_cv_prog_cxx_g" >&6; } +if test "$ac_test_CXXFLAGS" = set; then + CXXFLAGS=$ac_save_CXXFLAGS +elif test $ac_cv_prog_cxx_g = yes; then + if test "$GXX" = yes; then + CXXFLAGS="-g -O2" + else + CXXFLAGS="-g" + fi +else + if test "$GXX" = yes; then + CXXFLAGS="-O2" + else + CXXFLAGS= + fi +fi +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C++ preprocessor" >&5 +$as_echo_n "checking how to run the C++ preprocessor... " >&6; } +if test -z "$CXXCPP"; then + if ${ac_cv_prog_CXXCPP+:} false; then : + $as_echo_n "(cached) " >&6 +else + # Double quotes because CXXCPP needs to be expanded + for CXXCPP in "$CXX -E" "/lib/cpp" + do + ac_preproc_ok=false +for ac_cxx_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if ac_fn_cxx_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_cxx_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + break +fi + + done + ac_cv_prog_CXXCPP=$CXXCPP + +fi + CXXCPP=$ac_cv_prog_CXXCPP +else + ac_cv_prog_CXXCPP=$CXXCPP +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXXCPP" >&5 +$as_echo "$CXXCPP" >&6; } +ac_preproc_ok=false +for ac_cxx_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if ac_fn_cxx_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_cxx_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "C++ preprocessor \"$CXXCPP\" fails sanity check +See \`config.log' for more details" "$LINENO" 5; } +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +for ac_prog in ranlib +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_RANLIB+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$RANLIB"; then + ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_RANLIB="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +RANLIB=$ac_cv_prog_RANLIB +if test -n "$RANLIB"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 +$as_echo "$RANLIB" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$RANLIB" && break +done +test -n "$RANLIB" || RANLIB=":" + + +for ac_prog in ar +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_AR+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$AR"; then + ac_cv_prog_AR="$AR" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_AR="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +AR=$ac_cv_prog_AR +if test -n "$AR"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5 +$as_echo "$AR" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$AR" && break +done +test -n "$AR" || AR=":" + +for ac_prog in libtool +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_LIBTOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$LIBTOOL"; then + ac_cv_prog_LIBTOOL="$LIBTOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_LIBTOOL="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +LIBTOOL=$ac_cv_prog_LIBTOOL +if test -n "$LIBTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIBTOOL" >&5 +$as_echo "$LIBTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$LIBTOOL" && break +done +test -n "$LIBTOOL" || LIBTOOL=":" + +if test "${LIBTOOL}set" = libtoolset ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether libtool is GNU libtool" >&5 +$as_echo_n "checking whether libtool is GNU libtool... " >&6; } +if ${ac_cv_check_gnu_libtool+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_check_gnu_libtool=`libtool --version 2>/dev/null | grep "GNU libtool" | sed -e "s/.*\(GNU libtool\).*/\1/" ` + if test "${ac_cv_check_gnu_libtool}set" = "GNU libtoolset" ; then + ac_cv_check_gnu_libtool=yes + else + ac_cv_check_gnu_libtool=no + fi + +fi + + if test $ac_cv_check_gnu_libtool = yes ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + fi + + if test $ac_cv_check_gnu_libtool = yes ; then + : + else + AR=$LIBTOOL + fi +fi + +case "$AR" in +libtool) ARFLAGS=-o ;; +ar) ARFLAGS=cruv ;; +esac + +if test "${LIBEXT}set" = set ; then + LIBEXT="a" +fi + + + + + +# Try to find a strip utility +for ac_prog in strip +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$STRIP"; then + ac_cv_prog_STRIP="$STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_STRIP="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +STRIP=$ac_cv_prog_STRIP +if test -n "$STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 +$as_echo "$STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$STRIP" && break +done +test -n "$STRIP" || STRIP=":" + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 +$as_echo_n "checking for grep that handles long lines and -e... " >&6; } +if ${ac_cv_path_GREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$GREP"; then + ac_path_GREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in grep ggrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_GREP" || continue +# Check for GNU ac_path_GREP and select it if it is found. + # Check for GNU $ac_path_GREP +case `"$ac_path_GREP" --version 2>&1` in +*GNU*) + ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'GREP' >> "conftest.nl" + "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_GREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_GREP="$ac_path_GREP" + ac_path_GREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_GREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_GREP"; then + as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_GREP=$GREP +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 +$as_echo "$ac_cv_path_GREP" >&6; } + GREP="$ac_cv_path_GREP" + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 +$as_echo_n "checking for egrep... " >&6; } +if ${ac_cv_path_EGREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 + then ac_cv_path_EGREP="$GREP -E" + else + if test -z "$EGREP"; then + ac_path_EGREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in egrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_EGREP" || continue +# Check for GNU ac_path_EGREP and select it if it is found. + # Check for GNU $ac_path_EGREP +case `"$ac_path_EGREP" --version 2>&1` in +*GNU*) + ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'EGREP' >> "conftest.nl" + "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_EGREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_EGREP="$ac_path_EGREP" + ac_path_EGREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_EGREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_EGREP"; then + as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_EGREP=$EGREP +fi + + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 +$as_echo "$ac_cv_path_EGREP" >&6; } + EGREP="$ac_cv_path_EGREP" + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 +$as_echo_n "checking for ANSI C header files... " >&6; } +if ${ac_cv_header_stdc+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#include +#include + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_header_stdc=yes +else + ac_cv_header_stdc=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "memchr" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "free" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. + if test "$cross_compiling" = yes; then : + : +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#if ((' ' & 0x0FF) == 0x020) +# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#else +# define ISLOWER(c) \ + (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) +# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) +#endif + +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int +main () +{ + int i; + for (i = 0; i < 256; i++) + if (XOR (islower (i), ISLOWER (i)) + || toupper (i) != TOUPPER (i)) + return 2; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + +else + ac_cv_header_stdc=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 +$as_echo "$ac_cv_header_stdc" >&6; } +if test $ac_cv_header_stdc = yes; then + +$as_echo "#define STDC_HEADERS 1" >>confdefs.h + +fi + +# On IRIX 5.3, sys/types and inttypes.h are conflicting. +for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ + inttypes.h stdint.h unistd.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default +" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + + + ac_fn_c_check_header_mongrel "$LINENO" "minix/config.h" "ac_cv_header_minix_config_h" "$ac_includes_default" +if test "x$ac_cv_header_minix_config_h" = xyes; then : + MINIX=yes +else + MINIX= +fi + + + if test "$MINIX" = yes; then + +$as_echo "#define _POSIX_SOURCE 1" >>confdefs.h + + +$as_echo "#define _POSIX_1_SOURCE 2" >>confdefs.h + + +$as_echo "#define _MINIX 1" >>confdefs.h + + fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether it is safe to define __EXTENSIONS__" >&5 +$as_echo_n "checking whether it is safe to define __EXTENSIONS__... " >&6; } +if ${ac_cv_safe_to_define___extensions__+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +# define __EXTENSIONS__ 1 + $ac_includes_default +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_safe_to_define___extensions__=yes +else + ac_cv_safe_to_define___extensions__=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_safe_to_define___extensions__" >&5 +$as_echo "$ac_cv_safe_to_define___extensions__" >&6; } + test $ac_cv_safe_to_define___extensions__ = yes && + $as_echo "#define __EXTENSIONS__ 1" >>confdefs.h + + $as_echo "#define _ALL_SOURCE 1" >>confdefs.h + + $as_echo "#define _GNU_SOURCE 1" >>confdefs.h + + $as_echo "#define _POSIX_PTHREAD_SEMANTICS 1" >>confdefs.h + + $as_echo "#define _TANDEM_SOURCE 1" >>confdefs.h + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing strerror" >&5 +$as_echo_n "checking for library containing strerror... " >&6; } +if ${ac_cv_search_strerror+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char strerror (); +int +main () +{ +return strerror (); + ; + return 0; +} +_ACEOF +for ac_lib in '' cposix; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_strerror=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_strerror+:} false; then : + break +fi +done +if ${ac_cv_search_strerror+:} false; then : + +else + ac_cv_search_strerror=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_strerror" >&5 +$as_echo "$ac_cv_search_strerror" >&6; } +ac_res=$ac_cv_search_strerror +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for long file names" >&5 +$as_echo_n "checking for long file names... " >&6; } +if ${ac_cv_sys_long_file_names+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_sys_long_file_names=yes +# Test for long file names in all the places we know might matter: +# . the current directory, where building will happen +# $prefix/lib where we will be installing things +# $exec_prefix/lib likewise +# $TMPDIR if set, where it might want to write temporary files +# /tmp where it might want to write temporary files +# /var/tmp likewise +# /usr/tmp likewise +for ac_dir in . "$TMPDIR" /tmp /var/tmp /usr/tmp "$prefix/lib" "$exec_prefix/lib"; do + # Skip $TMPDIR if it is empty or bogus, and skip $exec_prefix/lib + # in the usual case where exec_prefix is '${prefix}'. + case $ac_dir in #( + . | /* | ?:[\\/]*) ;; #( + *) continue;; + esac + test -w "$ac_dir/." || continue # It is less confusing to not echo anything here. + ac_xdir=$ac_dir/cf$$ + (umask 077 && mkdir "$ac_xdir" 2>/dev/null) || continue + ac_tf1=$ac_xdir/conftest9012345 + ac_tf2=$ac_xdir/conftest9012346 + touch "$ac_tf1" 2>/dev/null && test -f "$ac_tf1" && test ! -f "$ac_tf2" || + ac_cv_sys_long_file_names=no + rm -f -r "$ac_xdir" 2>/dev/null + test $ac_cv_sys_long_file_names = no && break +done +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_long_file_names" >&5 +$as_echo "$ac_cv_sys_long_file_names" >&6; } +if test $ac_cv_sys_long_file_names = yes; then + +$as_echo "#define HAVE_LONG_FILE_NAMES 1" >>confdefs.h + +fi + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for inline" >&5 +$as_echo_n "checking for inline... " >&6; } +if ${ac_cv_my_c_inline+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_my_c_inline=no +for ac_kw in inline __inline__ __inline; do + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +} $ac_kw foo() { + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_my_c_inline=$ac_kw; break +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +done + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_my_c_inline" >&5 +$as_echo "$ac_cv_my_c_inline" >&6; } +case "$ac_cv_my_c_inline" in + inline | yes) $as_echo "#define C_INLINE inline" >>confdefs.h + ;; + no) $as_echo "#define C_INLINE /**/" >>confdefs.h + ;; + *) cat >>confdefs.h <<_ACEOF +#define C_INLINE $ac_cv_my_c_inline +_ACEOF + ;; +esac + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for working const" >&5 +$as_echo_n "checking for working const... " >&6; } +if ${ac_cv_my_c_const+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + +/* Ultrix mips cc rejects this. */ +typedef int charset[2]; const charset x; +/* SunOS 4.1.1 cc rejects this. */ +char const *const *ccp; +char **p; +/* NEC SVR4.0.2 mips cc rejects this. */ +struct point {int x, y;}; +static struct point const zero = {0,0}; +/* AIX XL C 1.02.0.0 rejects this. + It does not let you subtract one const X* pointer from another in an arm + of an if-expression whose if-part is not a constant expression */ +const char *g = "string"; +ccp = &g + (g ? g-g : 0); +/* HPUX 7.0 cc rejects these. */ +++ccp; +p = (char**) ccp; +ccp = (char const *const *) p; +{ /* SCO 3.2v4 cc rejects this. */ + char *t; + char const *s = 0 ? (char *) 0 : (char const *) 0; + + *t++ = 0; +} +{ /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */ + int x[] = {25, 17}; + const int *foo = &x[0]; + ++foo; +} +{ /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */ + typedef const int *iptr; + iptr p = 0; + ++p; +} +{ /* AIX XL C 1.02.0.0 rejects this saying + "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */ + struct s { int j; const int *ap[3]; }; + struct s *b; b->j = 5; +} +{ /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */ + const int foo = 10; +} + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_my_c_const=yes +else + ac_cv_my_c_const=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_my_c_const" >&5 +$as_echo "$ac_cv_my_c_const" >&6; } +if test $ac_cv_my_c_const = yes; then + cat >>confdefs.h <<_ACEOF +#define HAVE_C_CONST 1 +_ACEOF + +fi + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether char is unsigned" >&5 +$as_echo_n "checking whether char is unsigned... " >&6; } +if ${ac_cv_my_c_char_unsigned+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "$GCC" = yes; then + # GCC predefines this symbol on systems where it applies. +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __CHAR_UNSIGNED__ + yes +#endif + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "yes" >/dev/null 2>&1; then : + ac_cv_my_c_char_unsigned=yes +else + ac_cv_my_c_char_unsigned=no +fi +rm -f conftest* + +else +if test "$cross_compiling" = yes; then : + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot run test program while cross compiling +See \`config.log' for more details" "$LINENO" 5; } +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +/* volatile prevents gcc2 from optimizing the test away on sparcs. */ +#if !defined(__STDC__) || __STDC__ != 1 +#define volatile +#endif +main() { + volatile char c = 255; exit(c < 0); +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + ac_cv_my_c_char_unsigned=yes +else + ac_cv_my_c_char_unsigned=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_my_c_char_unsigned" >&5 +$as_echo "$ac_cv_my_c_char_unsigned" >&6; } +if test $ac_cv_my_c_char_unsigned = yes ; then + $as_echo "#define C_CHAR_UNSIGNED 1" >>confdefs.h + +fi + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether right shift is unsigned" >&5 +$as_echo_n "checking whether right shift is unsigned... " >&6; } +if ${ac_cv_my_c_rightshift_unsigned+:} false; then : + $as_echo_n "(cached) " >&6 +else + +if test "$cross_compiling" = yes; then : + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot run test program while cross compiling +See \`config.log' for more details" "$LINENO" 5; } +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +/* See whether right-shift on a long is signed or not. */ +int is_shifting_signed (long arg) +{ + long res = arg >> 4; + + if (res == -0x7F7E80CL) { /* expected result for signed shift */ + return 1; /* right shift is signed */ + } + /* see if unsigned-shift hack will fix it. */ + /* we can't just test exact value since it depends on width of long... */ + res |= (~0L) << (32-4); + if (res == -0x7F7E80CL) { /* expected result now? */ + return 0; /* right shift is unsigned */ + } + /* Right shift isn't acting as I expect it to, try it with unsigned anyway */ + return 0; +} + +int main() +{ + exit(is_shifting_signed(-0x7F7E80B1L)); +} + +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + ac_cv_my_c_rightshift_unsigned=yes +else + ac_cv_my_c_rightshift_unsigned=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_my_c_rightshift_unsigned" >&5 +$as_echo "$ac_cv_my_c_rightshift_unsigned" >&6; } +if test $ac_cv_my_c_rightshift_unsigned = yes ; then + $as_echo "#define C_CHAR_UNSIGNED 1" >>confdefs.h + +fi + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for uchar" >&5 +$as_echo_n "checking for uchar... " >&6; } +if ${ac_cv_type_uchar+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +if ((uchar *) 0) + return 0; +if (sizeof (uchar)) + return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_type_uchar=yes +else + ac_cv_type_uchar=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_type_uchar" >&5 +$as_echo "$ac_cv_type_uchar" >&6; } +if test $ac_cv_type_uchar = yes; then : + +else + +cat >>confdefs.h <<_ACEOF +#define HAVE_NO_TYPEDEF_UCHAR 1 +_ACEOF + +fi + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ushort" >&5 +$as_echo_n "checking for ushort... " >&6; } +if ${ac_cv_type_ushort+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +if ((ushort *) 0) + return 0; +if (sizeof (ushort)) + return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_type_ushort=yes +else + ac_cv_type_ushort=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_type_ushort" >&5 +$as_echo "$ac_cv_type_ushort" >&6; } +if test $ac_cv_type_ushort = yes; then : + +else + +cat >>confdefs.h <<_ACEOF +#define HAVE_NO_TYPEDEF_USHORT 1 +_ACEOF + +fi + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for uint" >&5 +$as_echo_n "checking for uint... " >&6; } +if ${ac_cv_type_uint+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +if ((uint *) 0) + return 0; +if (sizeof (uint)) + return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_type_uint=yes +else + ac_cv_type_uint=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_type_uint" >&5 +$as_echo "$ac_cv_type_uint" >&6; } +if test $ac_cv_type_uint = yes; then : + +else + +cat >>confdefs.h <<_ACEOF +#define HAVE_NO_TYPEDEF_UINT 1 +_ACEOF + +fi + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ulong" >&5 +$as_echo_n "checking for ulong... " >&6; } +if ${ac_cv_type_ulong+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +if ((ulong *) 0) + return 0; +if (sizeof (ulong)) + return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_type_ulong=yes +else + ac_cv_type_ulong=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_type_ulong" >&5 +$as_echo "$ac_cv_type_ulong" >&6; } +if test $ac_cv_type_ulong = yes; then : + +else + +cat >>confdefs.h <<_ACEOF +#define HAVE_NO_TYPEDEF_ULONG 1 +_ACEOF + +fi + +ac_fn_c_check_type "$LINENO" "longlong" "ac_cv_type_longlong" "$ac_includes_default" +if test "x$ac_cv_type_longlong" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_LONGLONG 1 +_ACEOF + + +fi + +ac_fn_c_check_type "$LINENO" "ulonglong" "ac_cv_type_ulonglong" "$ac_includes_default" +if test "x$ac_cv_type_ulonglong" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_ULONGLONG 1 +_ACEOF + + +fi + +ac_fn_c_check_type "$LINENO" "long long" "ac_cv_type_long_long" "$ac_includes_default" +if test "x$ac_cv_type_long_long" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_LONG_LONG 1 +_ACEOF + + +fi + +ac_fn_c_check_type "$LINENO" "unsigned long long" "ac_cv_type_unsigned_long_long" "$ac_includes_default" +if test "x$ac_cv_type_unsigned_long_long" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_UNSIGNED_LONG_LONG 1 +_ACEOF + + +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether variable-length arrays are supported" >&5 +$as_echo_n "checking whether variable-length arrays are supported... " >&6; } + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + int n; int foo[n]; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; }; $as_echo "#define HAVE_VLA 1" >>confdefs.h + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + +ac_fn_c_check_type "$LINENO" "fpos64_t" "ac_cv_type_fpos64_t" "$ac_includes_default" +if test "x$ac_cv_type_fpos64_t" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_FPOS64_T 1 +_ACEOF + + +fi + +ac_fn_c_check_type "$LINENO" "off64_t" "ac_cv_type_off64_t" "$ac_includes_default" +if test "x$ac_cv_type_off64_t" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_OFF64_T 1 +_ACEOF + + +fi + + +for ac_header in stdbool.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "stdbool.h" "ac_cv_header_stdbool_h" "$ac_includes_default" +if test "x$ac_cv_header_stdbool_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_STDBOOL_H 1 +_ACEOF + +fi + +done + +for ac_header in stdint.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "stdint.h" "ac_cv_header_stdint_h" "$ac_includes_default" +if test "x$ac_cv_header_stdint_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_STDINT_H 1 +_ACEOF + +fi + +done + +for ac_header in cstdint +do : + ac_fn_c_check_header_mongrel "$LINENO" "cstdint" "ac_cv_header_cstdint" "$ac_includes_default" +if test "x$ac_cv_header_cstdint" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_CSTDINT 1 +_ACEOF + +fi + +done + + +ac_fn_c_check_type "$LINENO" "int64_t" "ac_cv_type_int64_t" "$ac_includes_default" +if test "x$ac_cv_type_int64_t" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_INT64_T 1 +_ACEOF + + +fi + +ac_fn_c_check_type "$LINENO" "uint64_t" "ac_cv_type_uint64_t" "$ac_includes_default" +if test "x$ac_cv_type_uint64_t" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_UINT64_T 1 +_ACEOF + + +fi + + +ac_fn_c_check_type "$LINENO" "sigjmp_buf" "ac_cv_type_sigjmp_buf" "#include +" +if test "x$ac_cv_type_sigjmp_buf" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_SIGJMP_BUF 1 +_ACEOF + + +fi + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for working memcmp" >&5 +$as_echo_n "checking for working memcmp... " >&6; } +if ${ac_cv_func_memcmp_working+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "$cross_compiling" = yes; then : + ac_cv_func_memcmp_working=no +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ + + /* Some versions of memcmp are not 8-bit clean. */ + char c0 = '\100', c1 = '\200', c2 = '\201'; + if (memcmp(&c0, &c2, 1) >= 0 || memcmp(&c1, &c2, 1) >= 0) + return 1; + + /* The Next x86 OpenStep bug shows up only when comparing 16 bytes + or more and with at least one buffer not starting on a 4-byte boundary. + William Lewis provided this test program. */ + { + char foo[21]; + char bar[21]; + int i; + for (i = 0; i < 4; i++) + { + char *a = foo + i; + char *b = bar + i; + strcpy (a, "--------01111111"); + strcpy (b, "--------10000000"); + if (memcmp (a, b, 16) >= 0) + return 1; + } + return 0; + } + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + ac_cv_func_memcmp_working=yes +else + ac_cv_func_memcmp_working=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_memcmp_working" >&5 +$as_echo "$ac_cv_func_memcmp_working" >&6; } +test $ac_cv_func_memcmp_working = no && case " $LIBOBJS " in + *" memcmp.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS memcmp.$ac_objext" + ;; +esac + + +for ac_func in vprintf +do : + ac_fn_c_check_func "$LINENO" "vprintf" "ac_cv_func_vprintf" +if test "x$ac_cv_func_vprintf" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_VPRINTF 1 +_ACEOF + +ac_fn_c_check_func "$LINENO" "_doprnt" "ac_cv_func__doprnt" +if test "x$ac_cv_func__doprnt" = xyes; then : + +$as_echo "#define HAVE_DOPRNT 1" >>confdefs.h + +fi + +fi +done + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking return type of signal handlers" >&5 +$as_echo_n "checking return type of signal handlers... " >&6; } +if ${ac_cv_type_signal+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include + +int +main () +{ +return *(signal (0, 0)) (0) == 1; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_type_signal=int +else + ac_cv_type_signal=void +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_type_signal" >&5 +$as_echo "$ac_cv_type_signal" >&6; } + +cat >>confdefs.h <<_ACEOF +#define RETSIGTYPE $ac_cv_type_signal +_ACEOF + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for wait3 that fills in rusage" >&5 +$as_echo_n "checking for wait3 that fills in rusage... " >&6; } +if ${ac_cv_func_wait3_rusage+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "$cross_compiling" = yes; then : + ac_cv_func_wait3_rusage=no +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$ac_includes_default +#include +#include +#include +/* HP-UX has wait3 but does not fill in rusage at all. */ +int +main () +{ + struct rusage r; + int i; + /* Use a field that we can force nonzero -- + voluntary context switches. + For systems like NeXT and OSF/1 that don't set it, + also use the system CPU time. And page faults (I/O) for Linux. */ + r.ru_nvcsw = 0; + r.ru_stime.tv_sec = 0; + r.ru_stime.tv_usec = 0; + r.ru_majflt = r.ru_minflt = 0; + switch (fork ()) + { + case 0: /* Child. */ + sleep(1); /* Give up the CPU. */ + _exit(0); + break; + case -1: /* What can we do? */ + _exit(0); + break; + default: /* Parent. */ + wait3(&i, 0, &r); + /* Avoid "text file busy" from rm on fast HP-UX machines. */ + sleep(2); + return (r.ru_nvcsw == 0 && r.ru_majflt == 0 && r.ru_minflt == 0 + && r.ru_stime.tv_sec == 0 && r.ru_stime.tv_usec == 0); + } +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + ac_cv_func_wait3_rusage=yes +else + ac_cv_func_wait3_rusage=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_wait3_rusage" >&5 +$as_echo "$ac_cv_func_wait3_rusage" >&6; } +if test $ac_cv_func_wait3_rusage = yes; then + +$as_echo "#define HAVE_WAIT3 1" >>confdefs.h + +fi + +for ac_func in gethostname gethostid socket sysinfo +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + +for ac_func in strchr strstr strtoul itoa +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + +for ac_func in memcpy memset memmove memcmp bcopy bcmp +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + +for ac_func in getpid mktemp tempnam tmpnam getenv mkstemp +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + +for ac_func in stat +do : + ac_fn_c_check_func "$LINENO" "stat" "ac_cv_func_stat" +if test "x$ac_cv_func_stat" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_STAT 1 +_ACEOF + +fi +done + +for ac_func in malloc_debug +do : + ac_fn_c_check_func "$LINENO" "malloc_debug" "ac_cv_func_malloc_debug" +if test "x$ac_cv_func_malloc_debug" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_MALLOC_DEBUG 1 +_ACEOF + +fi +done + +for ac_func in strerror strdup bzero index rindex access +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + +for ac_func in uname cuserid getlogin +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + +for ac_func in usleep +do : + ac_fn_c_check_func "$LINENO" "usleep" "ac_cv_func_usleep" +if test "x$ac_cv_func_usleep" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_USLEEP 1 +_ACEOF + +fi +done + +for ac_func in flock lockf +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + +for ac_func in listen connect setsockopt getsockopt select +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + +for ac_func in gethostbyname gethostbyname_r +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + +for ac_func in gethostbyaddr_r getgrnam_r getpwnam_r +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + +for ac_func in bind accept getsockname getaddrinfo +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + +for ac_func in waitpid +do : + ac_fn_c_check_func "$LINENO" "waitpid" "ac_cv_func_waitpid" +if test "x$ac_cv_func_waitpid" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_WAITPID 1 +_ACEOF + +fi +done + +for ac_func in getuid geteuid setuid getpwnam getgrnam +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + +for ac_func in sleep fork +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + +for ac_func in _findfirst +do : + ac_fn_c_check_func "$LINENO" "_findfirst" "ac_cv_func__findfirst" +if test "x$ac_cv_func__findfirst" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE__FINDFIRST 1 +_ACEOF + +fi +done + +for ac_func in strlcpy strlcat +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + +for ac_func in vsnprintf +do : + ac_fn_c_check_func "$LINENO" "vsnprintf" "ac_cv_func_vsnprintf" +if test "x$ac_cv_func_vsnprintf" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_VSNPRINTF 1 +_ACEOF + +fi +done + +for ac_func in mbstowcs wcstombs +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + +for ac_func in popen pclose +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for _LARGEFILE_SOURCE value needed for large files" >&5 +$as_echo_n "checking for _LARGEFILE_SOURCE value needed for large files... " >&6; } +if ${ac_cv_sys_largefile_source+:} false; then : + $as_echo_n "(cached) " >&6 +else + while :; do + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include /* for off_t */ + #include +int +main () +{ +int (*fp) (FILE *, off_t, int) = fseeko; + return fseeko (stdin, 0, 0) && fp (stdin, 0, 0); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_sys_largefile_source=no; break +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#define _LARGEFILE_SOURCE 1 +#include /* for off_t */ + #include +int +main () +{ +int (*fp) (FILE *, off_t, int) = fseeko; + return fseeko (stdin, 0, 0) && fp (stdin, 0, 0); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_sys_largefile_source=1; break +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + ac_cv_sys_largefile_source=unknown + break +done +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_largefile_source" >&5 +$as_echo "$ac_cv_sys_largefile_source" >&6; } +case $ac_cv_sys_largefile_source in #( + no | unknown) ;; + *) +cat >>confdefs.h <<_ACEOF +#define _LARGEFILE_SOURCE $ac_cv_sys_largefile_source +_ACEOF +;; +esac +rm -rf conftest* + +# We used to try defining _XOPEN_SOURCE=500 too, to work around a bug +# in glibc 2.1.3, but that breaks too many other things. +# If you want fseeko and ftello with glibc, upgrade to a fixed glibc. +if test $ac_cv_sys_largefile_source != unknown; then + +$as_echo "#define HAVE_FSEEKO 1" >>confdefs.h + +fi + + + + + + +for ac_func in ftime gmtime_r localtime_r lstat nanosleep fcntl +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + +for ac_func in htons htonl ntohs ntohl +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + +for ac_header in netinet/in.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "netinet/in.h" "ac_cv_header_netinet_in_h" "$ac_includes_default" +if test "x$ac_cv_header_netinet_in_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_NETINET_IN_H 1 +_ACEOF + +fi + +done + +for ac_header in syslog.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "syslog.h" "ac_cv_header_syslog_h" "$ac_includes_default" +if test "x$ac_cv_header_syslog_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_SYSLOG_H 1 +_ACEOF + +fi + +done + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for socklen_t" >&5 +$as_echo_n "checking for socklen_t... " >&6; } +if ${ac_cv_type_socklen_t+:} false; then : + $as_echo_n "(cached) " >&6 +else + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + #include +int +main () +{ +socklen_t len = 42; return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_type_socklen_t=yes +else + ac_cv_type_socklen_t=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_type_socklen_t" >&5 +$as_echo "$ac_cv_type_socklen_t" >&6; } + if test $ac_cv_type_socklen_t != yes; then + $as_echo "#define socklen_t int" >>confdefs.h + + fi + + + +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +int value = ENAMETOOLONG; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +$as_echo "#define HAVE_ENAMETOOLONG /**/" >>confdefs.h + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + + +SAVELIBS="$LIBS" +LIBS="$LIBS -lm" +for ac_func in finite isinf isnan +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + +LIBS="$SAVELIBS" + +ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports const_cast<>" >&5 +$as_echo_n "checking whether the compiler supports const_cast<>... " >&6; } +if ${ac_cv_cxx_const_cast+:} false; then : + $as_echo_n "(cached) " >&6 +else + + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +int x = 0;const int& y = x;int& z = const_cast(y);return z; + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_cv_cxx_const_cast=yes +else + ac_cv_cxx_const_cast=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cxx_const_cast" >&5 +$as_echo "$ac_cv_cxx_const_cast" >&6; } +if test "$ac_cv_cxx_const_cast" = yes; then + +$as_echo "#define HAVE_CONST_CAST /**/" >>confdefs.h + +fi + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports dynamic_cast<>" >&5 +$as_echo_n "checking whether the compiler supports dynamic_cast<>... " >&6; } +if ${ac_cv_cxx_dynamic_cast+:} false; then : + $as_echo_n "(cached) " >&6 +else + + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +class Base { public : Base () {} virtual void f () = 0;}; +class Derived : public Base { public : Derived () {} virtual void f () {} }; +int +main () +{ + +Derived d; Base& b=d; return dynamic_cast(&b) ? 0 : 1; + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_cv_cxx_dynamic_cast=yes +else + ac_cv_cxx_dynamic_cast=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cxx_dynamic_cast" >&5 +$as_echo "$ac_cv_cxx_dynamic_cast" >&6; } +if test "$ac_cv_cxx_dynamic_cast" = yes; then + +$as_echo "#define HAVE_DYNAMIC_CAST /**/" >>confdefs.h + +fi + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports reinterpret_cast<>" >&5 +$as_echo_n "checking whether the compiler supports reinterpret_cast<>... " >&6; } +if ${ac_cv_cxx_reinterpret_cast+:} false; then : + $as_echo_n "(cached) " >&6 +else + + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +class Base { public : Base () {} virtual void f () = 0;}; +class Derived : public Base { public : Derived () {} virtual void f () {} }; +class Unrelated { public : Unrelated () {} }; +int g (Unrelated&) { return 0; } +int +main () +{ + +Derived d;Base& b=d;Unrelated& e=reinterpret_cast(b);return g(e); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_cv_cxx_reinterpret_cast=yes +else + ac_cv_cxx_reinterpret_cast=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cxx_reinterpret_cast" >&5 +$as_echo "$ac_cv_cxx_reinterpret_cast" >&6; } +if test "$ac_cv_cxx_reinterpret_cast" = yes; then + +$as_echo "#define HAVE_REINTERPRET_CAST /**/" >>confdefs.h + +fi + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports static_cast<>" >&5 +$as_echo_n "checking whether the compiler supports static_cast<>... " >&6; } +if ${ac_cv_cxx_static_cast+:} false; then : + $as_echo_n "(cached) " >&6 +else + + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +class Base { public : Base () {} virtual void f () = 0; }; +class Derived : public Base { public : Derived () {} virtual void f () {} }; +int g (Derived&) { return 0; } +int +main () +{ + +Derived d; Base& b = d; Derived& s = static_cast (b); return g (s); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_cv_cxx_static_cast=yes +else + ac_cv_cxx_static_cast=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cxx_static_cast" >&5 +$as_echo "$ac_cv_cxx_static_cast" >&6; } +if test "$ac_cv_cxx_static_cast" = yes; then + +$as_echo "#define HAVE_STATIC_CAST /**/" >>confdefs.h + +fi + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports std::nothrow" >&5 +$as_echo_n "checking whether the compiler supports std::nothrow... " >&6; } +if ${ac_cv_cxx_std_nothrow+:} false; then : + $as_echo_n "(cached) " >&6 +else + + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +int *i = new (std::nothrow) int + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_cv_cxx_std_nothrow=yes +else + ac_cv_cxx_std_nothrow=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cxx_std_nothrow" >&5 +$as_echo "$ac_cv_cxx_std_nothrow" >&6; } +if test "$ac_cv_cxx_std_nothrow" = yes; then + +$as_echo "#define HAVE_STD__NOTHROW /**/" >>confdefs.h + +fi + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports operator delete (std::nothrow)" >&5 +$as_echo_n "checking whether the compiler supports operator delete (std::nothrow)... " >&6; } +if ${ac_cv_cxx_nothrow_delete+:} false; then : + $as_echo_n "(cached) " >&6 +else + + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +int *i = new (std::nothrow) int; operator delete (i,std::nothrow) + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_cv_cxx_nothrow_delete=yes +else + ac_cv_cxx_nothrow_delete=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cxx_nothrow_delete" >&5 +$as_echo "$ac_cv_cxx_nothrow_delete" >&6; } +if test "$ac_cv_cxx_nothrow_delete" = yes; then + +$as_echo "#define HAVE_NOTHROW_DELETE /**/" >>confdefs.h + +fi + + + +DEBUG="-DNDEBUG" +DEBUGCXXFLAGS= +DEBUGCFLAGS= +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to compile in debug mode" >&5 +$as_echo_n "checking whether to compile in debug mode... " >&6; } +# Check whether --enable-debug was given. +if test "${enable_debug+set}" = set; then : + enableval=$enable_debug; case "$enableval" in + yes) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + DEBUGCXXFLAGS="-g" + DEBUGCFLAGS="-g" + DEBUG="-DDEBUG" + ;; + *) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + DEBUGCXXFLAGS="-O" + DEBUGCFLAGS="-O" + ;; + esac +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + DEBUGCXXFLAGS="-O" + DEBUGCFLAGS="-O" + +fi + + + +THREADSUPPORT="auto" +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable thread support" >&5 +$as_echo_n "checking whether to enable thread support... " >&6; } +# Check whether --enable-threads was given. +if test "${enable_threads+set}" = set; then : + enableval=$enable_threads; case "$enableval" in + yes|auto) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: automatic detection" >&5 +$as_echo "automatic detection" >&6; } + ;; + posix) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes, type=posix" >&5 +$as_echo "yes, type=posix" >&6; } + THREADSUPPORT="posix" + ;; + solaris) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes, type=solaris" >&5 +$as_echo "yes, type=solaris" >&6; } + THREADSUPPORT="solaris" + ;; + no) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + THREADSUPPORT="no" + ;; + *) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes - type $enableval is unknown - using automatic detection" >&5 +$as_echo "yes - type $enableval is unknown - using automatic detection" >&6; } + ;; + esac +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: automatic detection" >&5 +$as_echo "automatic detection" >&6; } + +fi + + + +LFSSUPPORT="auto" +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable large file support" >&5 +$as_echo_n "checking whether to enable large file support... " >&6; } +# Check whether --enable-lfs was given. +if test "${enable_lfs+set}" = set; then : + enableval=$enable_lfs; case "$enableval" in + yes|auto) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: automatic detection" >&5 +$as_echo "automatic detection" >&6; } + ;; + lfs) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes, type=LFS" >&5 +$as_echo "yes, type=LFS" >&6; } + LFSSUPPORT="lfs" + ;; + lfs64) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes, type=LFS64" >&5 +$as_echo "yes, type=LFS64" >&6; } + LFSSUPPORT="lfs64" + ;; + no) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + LFSSUPPORT="no" + ;; + *) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes - type $enableval is unknown - using automatic detection" >&5 +$as_echo "yes - type $enableval is unknown - using automatic detection" >&6; } + ;; + esac +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: automatic detection" >&5 +$as_echo "automatic detection" >&6; } + +fi + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for -lg++" >&5 +$as_echo_n "checking for -lg++... " >&6; } +if ${ac_cv_lib_gxx+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_save_LIBS="$LIBS" +LIBS="-lg++ $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +main() + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + eval "ac_cv_lib_gxx=yes" +else + eval "ac_cv_lib_gxx=no" +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_gxx'`\" = yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + ac_tr_lib=HAVE_LIBGXX + cat >>confdefs.h <<_ACEOF +#define $ac_tr_lib 1 +_ACEOF + + LIBS="-lg++ $LIBS" + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -liostream" >&5 +$as_echo_n "checking for main in -liostream... " >&6; } +if ${ac_cv_lib_iostream_main+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-liostream $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + +int +main () +{ +return main (); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + ac_cv_lib_iostream_main=yes +else + ac_cv_lib_iostream_main=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_iostream_main" >&5 +$as_echo "$ac_cv_lib_iostream_main" >&6; } +if test "x$ac_cv_lib_iostream_main" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBIOSTREAM 1 +_ACEOF + + LIBS="-liostream $LIBS" + +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lnsl" >&5 +$as_echo_n "checking for main in -lnsl... " >&6; } +if ${ac_cv_lib_nsl_main+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lnsl $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + +int +main () +{ +return main (); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + ac_cv_lib_nsl_main=yes +else + ac_cv_lib_nsl_main=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_nsl_main" >&5 +$as_echo "$ac_cv_lib_nsl_main" >&6; } +if test "x$ac_cv_lib_nsl_main" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBNSL 1 +_ACEOF + + LIBS="-lnsl $LIBS" + +fi + +if test $ac_cv_lib_nsl_main = no ; then +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for gethostbyname in -lnsl" >&5 +$as_echo_n "checking for gethostbyname in -lnsl... " >&6; } +if ${ac_cv_lib_nsl_gethostbyname+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lnsl $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char gethostbyname (); +int +main () +{ +return gethostbyname (); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + ac_cv_lib_nsl_gethostbyname=yes +else + ac_cv_lib_nsl_gethostbyname=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_nsl_gethostbyname" >&5 +$as_echo "$ac_cv_lib_nsl_gethostbyname" >&6; } +if test "x$ac_cv_lib_nsl_gethostbyname" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBNSL 1 +_ACEOF + + LIBS="-lnsl $LIBS" + +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lsocket" >&5 +$as_echo_n "checking for main in -lsocket... " >&6; } +if ${ac_cv_lib_socket_main+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lsocket $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + +int +main () +{ +return main (); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + ac_cv_lib_socket_main=yes +else + ac_cv_lib_socket_main=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_socket_main" >&5 +$as_echo "$ac_cv_lib_socket_main" >&6; } +if test "x$ac_cv_lib_socket_main" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBSOCKET 1 +_ACEOF + + LIBS="-lsocket $LIBS" + +fi + +if test $ac_cv_lib_socket_main = no ; then +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for socket in -lsocket" >&5 +$as_echo_n "checking for socket in -lsocket... " >&6; } +if ${ac_cv_lib_socket_socket+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lsocket $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char socket (); +int +main () +{ +return socket (); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + ac_cv_lib_socket_socket=yes +else + ac_cv_lib_socket_socket=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_socket_socket" >&5 +$as_echo "$ac_cv_lib_socket_socket" >&6; } +if test "x$ac_cv_lib_socket_socket" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBSOCKET 1 +_ACEOF + + LIBS="-lsocket $LIBS" + +fi + +fi + +OPENSSLLIBS="" +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -ldl" >&5 +$as_echo_n "checking for main in -ldl... " >&6; } +if ${ac_cv_lib_dl_main+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldl $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + +int +main () +{ +return main (); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + ac_cv_lib_dl_main=yes +else + ac_cv_lib_dl_main=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_main" >&5 +$as_echo "$ac_cv_lib_dl_main" >&6; } +if test "x$ac_cv_lib_dl_main" = xyes; then : + +OPENSSLLIBS="-ldl" + +fi + +if test $ac_cv_lib_dl_main = no ; then +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 +$as_echo_n "checking for dlopen in -ldl... " >&6; } +if ${ac_cv_lib_dl_dlopen+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldl $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + ac_cv_lib_dl_dlopen=yes +else + ac_cv_lib_dl_dlopen=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 +$as_echo "$ac_cv_lib_dl_dlopen" >&6; } +if test "x$ac_cv_lib_dl_dlopen" = xyes; then : + +OPENSSLLIBS="-ldl" + +fi + +fi + +MATHLIBS="" +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lm" >&5 +$as_echo_n "checking for main in -lm... " >&6; } +if ${ac_cv_lib_m_main+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lm $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + +int +main () +{ +return main (); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + ac_cv_lib_m_main=yes +else + ac_cv_lib_m_main=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_m_main" >&5 +$as_echo "$ac_cv_lib_m_main" >&6; } +if test "x$ac_cv_lib_m_main" = xyes; then : + +MATHLIBS="-lm" + +fi + +if test $ac_cv_lib_m_main = no ; then +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for sin in -lm" >&5 +$as_echo_n "checking for sin in -lm... " >&6; } +if ${ac_cv_lib_m_sin+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lm $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char sin (); +int +main () +{ +return sin (); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + ac_cv_lib_m_sin=yes +else + ac_cv_lib_m_sin=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_m_sin" >&5 +$as_echo "$ac_cv_lib_m_sin" >&6; } +if test "x$ac_cv_lib_m_sin" = xyes; then : + +MATHLIBS="-lm" + +fi + +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lwsock32" >&5 +$as_echo_n "checking for main in -lwsock32... " >&6; } +if ${ac_cv_lib_wsock32_main+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lwsock32 $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + +int +main () +{ +return main (); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + ac_cv_lib_wsock32_main=yes +else + ac_cv_lib_wsock32_main=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_wsock32_main" >&5 +$as_echo "$ac_cv_lib_wsock32_main" >&6; } +if test "x$ac_cv_lib_wsock32_main" = xyes; then : + +LIBS="$LIBS -lwsock32" + +fi + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lnetapi32" >&5 +$as_echo_n "checking for main in -lnetapi32... " >&6; } +if ${ac_cv_lib_netapi32_main+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lnetapi32 $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + +int +main () +{ +return main (); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + ac_cv_lib_netapi32_main=yes +else + ac_cv_lib_netapi32_main=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_netapi32_main" >&5 +$as_echo "$ac_cv_lib_netapi32_main" >&6; } +if test "x$ac_cv_lib_netapi32_main" = xyes; then : + +LIBS="$LIBS -lnetapi32" + +fi + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 +$as_echo_n "checking for ANSI C header files... " >&6; } +if ${ac_cv_header_stdc+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#include +#include + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_cv_header_stdc=yes +else + ac_cv_header_stdc=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "memchr" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "free" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. + if test "$cross_compiling" = yes; then : + : +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#if ((' ' & 0x0FF) == 0x020) +# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#else +# define ISLOWER(c) \ + (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) +# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) +#endif + +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int +main () +{ + int i; + for (i = 0; i < 256; i++) + if (XOR (islower (i), ISLOWER (i)) + || toupper (i) != TOUPPER (i)) + return 2; + return 0; +} +_ACEOF +if ac_fn_cxx_try_run "$LINENO"; then : + +else + ac_cv_header_stdc=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 +$as_echo "$ac_cv_header_stdc" >&6; } +if test $ac_cv_header_stdc = yes; then + +$as_echo "#define STDC_HEADERS 1" >>confdefs.h + +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for sys/wait.h that is POSIX.1 compatible" >&5 +$as_echo_n "checking for sys/wait.h that is POSIX.1 compatible... " >&6; } +if ${ac_cv_header_sys_wait_h+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#ifndef WEXITSTATUS +# define WEXITSTATUS(stat_val) ((unsigned int) (stat_val) >> 8) +#endif +#ifndef WIFEXITED +# define WIFEXITED(stat_val) (((stat_val) & 255) == 0) +#endif + +int +main () +{ + int s; + wait (&s); + s = WIFEXITED (s) ? WEXITSTATUS (s) : 1; + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_cv_header_sys_wait_h=yes +else + ac_cv_header_sys_wait_h=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_sys_wait_h" >&5 +$as_echo "$ac_cv_header_sys_wait_h" >&6; } +if test $ac_cv_header_sys_wait_h = yes; then + +$as_echo "#define HAVE_SYS_WAIT_H 1" >>confdefs.h + +fi + +ac_header_dirent=no +for ac_hdr in dirent.h sys/ndir.h sys/dir.h ndir.h; do + as_ac_Header=`$as_echo "ac_cv_header_dirent_$ac_hdr" | $as_tr_sh` +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_hdr that defines DIR" >&5 +$as_echo_n "checking for $ac_hdr that defines DIR... " >&6; } +if eval \${$as_ac_Header+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include <$ac_hdr> + +int +main () +{ +if ((DIR *) 0) +return 0; + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + eval "$as_ac_Header=yes" +else + eval "$as_ac_Header=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$as_ac_Header + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_hdr" | $as_tr_cpp` 1 +_ACEOF + +ac_header_dirent=$ac_hdr; break +fi + +done +# Two versions of opendir et al. are in -ldir and -lx on SCO Xenix. +if test $ac_header_dirent = dirent.h; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing opendir" >&5 +$as_echo_n "checking for library containing opendir... " >&6; } +if ${ac_cv_search_opendir+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char opendir (); +int +main () +{ +return opendir (); + ; + return 0; +} +_ACEOF +for ac_lib in '' dir; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_cxx_try_link "$LINENO"; then : + ac_cv_search_opendir=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_opendir+:} false; then : + break +fi +done +if ${ac_cv_search_opendir+:} false; then : + +else + ac_cv_search_opendir=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_opendir" >&5 +$as_echo "$ac_cv_search_opendir" >&6; } +ac_res=$ac_cv_search_opendir +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +fi + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing opendir" >&5 +$as_echo_n "checking for library containing opendir... " >&6; } +if ${ac_cv_search_opendir+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char opendir (); +int +main () +{ +return opendir (); + ; + return 0; +} +_ACEOF +for ac_lib in '' x; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_cxx_try_link "$LINENO"; then : + ac_cv_search_opendir=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_opendir+:} false; then : + break +fi +done +if ${ac_cv_search_opendir+:} false; then : + +else + ac_cv_search_opendir=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_opendir" >&5 +$as_echo "$ac_cv_search_opendir" >&6; } +ac_res=$ac_cv_search_opendir +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +fi + +fi + +for ac_header in netinet/in_systm.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "netinet/in_systm.h" "ac_cv_header_netinet_in_systm_h" "$ac_includes_default" +if test "x$ac_cv_header_netinet_in_systm_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_NETINET_IN_SYSTM_H 1 +_ACEOF + +fi + +done + + +if eval "test \"`echo '$ac_cv_header_netinet_in_systm_h'`\" = yes"; then + for ac_hdr in netinet/in.h +do +ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_hdr" >&5 +$as_echo_n "checking for $ac_hdr... " >&6; } +if eval \${ac_cv_header_$ac_safe+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +#include <$ac_hdr> +_ACEOF +if ac_fn_cxx_try_cpp "$LINENO"; then : + eval "ac_cv_header_$ac_safe=yes" +else + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest.err conftest.i conftest.$ac_ext +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` + cat >>confdefs.h <<_ACEOF +#define $ac_tr_hdr 1 +_ACEOF + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +done + + if eval "test \"`echo '$ac_cv_header_netinet_in_h'`\" = yes"; then + for ac_hdr in netinet/tcp.h +do +ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_hdr" >&5 +$as_echo_n "checking for $ac_hdr... " >&6; } +if eval \${ac_cv_header_$ac_safe+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include + +#include <$ac_hdr> +_ACEOF +if ac_fn_cxx_try_cpp "$LINENO"; then : + eval "ac_cv_header_$ac_safe=yes" +else + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest.err conftest.i conftest.$ac_ext +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` + cat >>confdefs.h <<_ACEOF +#define $ac_tr_hdr 1 +_ACEOF + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +done + + else + for ac_hdr in netinet/tcp.h +do +ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_hdr" >&5 +$as_echo_n "checking for $ac_hdr... " >&6; } +if eval \${ac_cv_header_$ac_safe+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +#include <$ac_hdr> +_ACEOF +if ac_fn_cxx_try_cpp "$LINENO"; then : + eval "ac_cv_header_$ac_safe=yes" +else + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest.err conftest.i conftest.$ac_ext +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` + cat >>confdefs.h <<_ACEOF +#define $ac_tr_hdr 1 +_ACEOF + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +done + + fi +else + for ac_header in netinet/in.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "netinet/in.h" "ac_cv_header_netinet_in_h" "$ac_includes_default" +if test "x$ac_cv_header_netinet_in_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_NETINET_IN_H 1 +_ACEOF + +fi + +done + + if eval "test \"`echo '$ac_cv_header_netinet_in_h'`\" = yes"; then + for ac_hdr in netinet/tcp.h +do +ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_hdr" >&5 +$as_echo_n "checking for $ac_hdr... " >&6; } +if eval \${ac_cv_header_$ac_safe+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +#include <$ac_hdr> +_ACEOF +if ac_fn_cxx_try_cpp "$LINENO"; then : + eval "ac_cv_header_$ac_safe=yes" +else + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest.err conftest.i conftest.$ac_ext +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` + cat >>confdefs.h <<_ACEOF +#define $ac_tr_hdr 1 +_ACEOF + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +done + + else + for ac_header in netinet/tcp.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "netinet/tcp.h" "ac_cv_header_netinet_tcp_h" "$ac_includes_default" +if test "x$ac_cv_header_netinet_tcp_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_NETINET_TCP_H 1 +_ACEOF + +fi + +done + + fi +fi + +for ac_header in alloca.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "alloca.h" "ac_cv_header_alloca_h" "$ac_includes_default" +if test "x$ac_cv_header_alloca_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_ALLOCA_H 1 +_ACEOF + +fi + +done + +for ac_header in arpa/inet.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "arpa/inet.h" "ac_cv_header_arpa_inet_h" "$ac_includes_default" +if test "x$ac_cv_header_arpa_inet_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_ARPA_INET_H 1 +_ACEOF + +fi + +done + +for ac_header in assert.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "assert.h" "ac_cv_header_assert_h" "$ac_includes_default" +if test "x$ac_cv_header_assert_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_ASSERT_H 1 +_ACEOF + +fi + +done + +for ac_header in ctype.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "ctype.h" "ac_cv_header_ctype_h" "$ac_includes_default" +if test "x$ac_cv_header_ctype_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_CTYPE_H 1 +_ACEOF + +fi + +done + +for ac_header in errno.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "errno.h" "ac_cv_header_errno_h" "$ac_includes_default" +if test "x$ac_cv_header_errno_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_ERRNO_H 1 +_ACEOF + +fi + +done + +for ac_header in fcntl.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "fcntl.h" "ac_cv_header_fcntl_h" "$ac_includes_default" +if test "x$ac_cv_header_fcntl_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_FCNTL_H 1 +_ACEOF + +fi + +done + +for ac_header in float.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "float.h" "ac_cv_header_float_h" "$ac_includes_default" +if test "x$ac_cv_header_float_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_FLOAT_H 1 +_ACEOF + +fi + +done + +for ac_header in fnmatch.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "fnmatch.h" "ac_cv_header_fnmatch_h" "$ac_includes_default" +if test "x$ac_cv_header_fnmatch_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_FNMATCH_H 1 +_ACEOF + +fi + +done + +for ac_header in fstream +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "fstream" "ac_cv_header_fstream" "$ac_includes_default" +if test "x$ac_cv_header_fstream" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_FSTREAM 1 +_ACEOF + +fi + +done + +for ac_header in fstream.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "fstream.h" "ac_cv_header_fstream_h" "$ac_includes_default" +if test "x$ac_cv_header_fstream_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_FSTREAM_H 1 +_ACEOF + +fi + +done + +for ac_header in grp.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "grp.h" "ac_cv_header_grp_h" "$ac_includes_default" +if test "x$ac_cv_header_grp_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_GRP_H 1 +_ACEOF + +fi + +done + +for ac_header in ieeefp.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "ieeefp.h" "ac_cv_header_ieeefp_h" "$ac_includes_default" +if test "x$ac_cv_header_ieeefp_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_IEEEFP_H 1 +_ACEOF + +fi + +done + +for ac_header in io.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "io.h" "ac_cv_header_io_h" "$ac_includes_default" +if test "x$ac_cv_header_io_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_IO_H 1 +_ACEOF + +fi + +done + +for ac_header in iomanip +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "iomanip" "ac_cv_header_iomanip" "$ac_includes_default" +if test "x$ac_cv_header_iomanip" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_IOMANIP 1 +_ACEOF + +fi + +done + +for ac_header in iomanip.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "iomanip.h" "ac_cv_header_iomanip_h" "$ac_includes_default" +if test "x$ac_cv_header_iomanip_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_IOMANIP_H 1 +_ACEOF + +fi + +done + +for ac_header in iostream +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "iostream" "ac_cv_header_iostream" "$ac_includes_default" +if test "x$ac_cv_header_iostream" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_IOSTREAM 1 +_ACEOF + +fi + +done + +for ac_header in iostream.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "iostream.h" "ac_cv_header_iostream_h" "$ac_includes_default" +if test "x$ac_cv_header_iostream_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_IOSTREAM_H 1 +_ACEOF + +fi + +done + +for ac_header in iso646.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "iso646.h" "ac_cv_header_iso646_h" "$ac_includes_default" +if test "x$ac_cv_header_iso646_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_ISO646_H 1 +_ACEOF + +fi + +done + +for ac_header in libc.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "libc.h" "ac_cv_header_libc_h" "$ac_includes_default" +if test "x$ac_cv_header_libc_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBC_H 1 +_ACEOF + +fi + +done + +for ac_header in limits.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "limits.h" "ac_cv_header_limits_h" "$ac_includes_default" +if test "x$ac_cv_header_limits_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIMITS_H 1 +_ACEOF + +fi + +done + +for ac_header in climits +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "climits" "ac_cv_header_climits" "$ac_includes_default" +if test "x$ac_cv_header_climits" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_CLIMITS 1 +_ACEOF + +fi + +done + +for ac_header in locale.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "locale.h" "ac_cv_header_locale_h" "$ac_includes_default" +if test "x$ac_cv_header_locale_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LOCALE_H 1 +_ACEOF + +fi + +done + +for ac_header in malloc.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "malloc.h" "ac_cv_header_malloc_h" "$ac_includes_default" +if test "x$ac_cv_header_malloc_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_MALLOC_H 1 +_ACEOF + +fi + +done + +for ac_header in math.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "math.h" "ac_cv_header_math_h" "$ac_includes_default" +if test "x$ac_cv_header_math_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_MATH_H 1 +_ACEOF + +fi + +done + +for ac_header in cmath +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "cmath" "ac_cv_header_cmath" "$ac_includes_default" +if test "x$ac_cv_header_cmath" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_CMATH 1 +_ACEOF + +fi + +done + +for ac_header in new +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "new" "ac_cv_header_new" "$ac_includes_default" +if test "x$ac_cv_header_new" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_NEW 1 +_ACEOF + +fi + +done + +for ac_header in new.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "new.h" "ac_cv_header_new_h" "$ac_includes_default" +if test "x$ac_cv_header_new_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_NEW_H 1 +_ACEOF + +fi + +done + +for ac_header in netdb.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "netdb.h" "ac_cv_header_netdb_h" "$ac_includes_default" +if test "x$ac_cv_header_netdb_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_NETDB_H 1 +_ACEOF + +fi + +done + +for ac_header in pthread.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "pthread.h" "ac_cv_header_pthread_h" "$ac_includes_default" +if test "x$ac_cv_header_pthread_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_PTHREAD_H 1 +_ACEOF + +fi + +done + +for ac_header in pwd.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "pwd.h" "ac_cv_header_pwd_h" "$ac_includes_default" +if test "x$ac_cv_header_pwd_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_PWD_H 1 +_ACEOF + +fi + +done + +for ac_header in semaphore.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "semaphore.h" "ac_cv_header_semaphore_h" "$ac_includes_default" +if test "x$ac_cv_header_semaphore_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_SEMAPHORE_H 1 +_ACEOF + +fi + +done + +for ac_header in setjmp.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "setjmp.h" "ac_cv_header_setjmp_h" "$ac_includes_default" +if test "x$ac_cv_header_setjmp_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_SETJMP_H 1 +_ACEOF + +fi + +done + +for ac_header in signal.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "signal.h" "ac_cv_header_signal_h" "$ac_includes_default" +if test "x$ac_cv_header_signal_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_SIGNAL_H 1 +_ACEOF + +fi + +done + +for ac_header in sstream +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "sstream" "ac_cv_header_sstream" "$ac_includes_default" +if test "x$ac_cv_header_sstream" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_SSTREAM 1 +_ACEOF + +fi + +done + +for ac_header in sstream.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "sstream.h" "ac_cv_header_sstream_h" "$ac_includes_default" +if test "x$ac_cv_header_sstream_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_SSTREAM_H 1 +_ACEOF + +fi + +done + +for ac_header in stat.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "stat.h" "ac_cv_header_stat_h" "$ac_includes_default" +if test "x$ac_cv_header_stat_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_STAT_H 1 +_ACEOF + +fi + +done + +for ac_header in cstdarg +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "cstdarg" "ac_cv_header_cstdarg" "$ac_includes_default" +if test "x$ac_cv_header_cstdarg" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_CSTDARG 1 +_ACEOF + +fi + +done + +for ac_header in stdarg.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "stdarg.h" "ac_cv_header_stdarg_h" "$ac_includes_default" +if test "x$ac_cv_header_stdarg_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_STDARG_H 1 +_ACEOF + +fi + +done + +for ac_header in stddef.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "stddef.h" "ac_cv_header_stddef_h" "$ac_includes_default" +if test "x$ac_cv_header_stddef_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_STDDEF_H 1 +_ACEOF + +fi + +done + +for ac_header in cstddef +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "cstddef" "ac_cv_header_cstddef" "$ac_includes_default" +if test "x$ac_cv_header_cstddef" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_CSTDDEF 1 +_ACEOF + +fi + +done + +for ac_header in cstdio +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "cstdio" "ac_cv_header_cstdio" "$ac_includes_default" +if test "x$ac_cv_header_cstdio" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_CSTDIO 1 +_ACEOF + +fi + +done + +for ac_header in stdio.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "stdio.h" "ac_cv_header_stdio_h" "$ac_includes_default" +if test "x$ac_cv_header_stdio_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_STDIO_H 1 +_ACEOF + +fi + +done + +for ac_header in stdint.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "stdint.h" "ac_cv_header_stdint_h" "$ac_includes_default" +if test "x$ac_cv_header_stdint_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_STDINT_H 1 +_ACEOF + +fi + +done + +for ac_header in stdlib.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "stdlib.h" "ac_cv_header_stdlib_h" "$ac_includes_default" +if test "x$ac_cv_header_stdlib_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_STDLIB_H 1 +_ACEOF + +fi + +done + +for ac_header in string.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "string.h" "ac_cv_header_string_h" "$ac_includes_default" +if test "x$ac_cv_header_string_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_STRING_H 1 +_ACEOF + +fi + +done + +for ac_header in strings.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "strings.h" "ac_cv_header_strings_h" "$ac_includes_default" +if test "x$ac_cv_header_strings_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_STRINGS_H 1 +_ACEOF + +fi + +done + +for ac_header in strstrea.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "strstrea.h" "ac_cv_header_strstrea_h" "$ac_includes_default" +if test "x$ac_cv_header_strstrea_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_STRSTREA_H 1 +_ACEOF + +fi + +done + +for ac_header in strstream +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "strstream" "ac_cv_header_strstream" "$ac_includes_default" +if test "x$ac_cv_header_strstream" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_STRSTREAM 1 +_ACEOF + +fi + +done + +for ac_header in strstream.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "strstream.h" "ac_cv_header_strstream_h" "$ac_includes_default" +if test "x$ac_cv_header_strstream_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_STRSTREAM_H 1 +_ACEOF + +fi + +done + +for ac_header in synch.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "synch.h" "ac_cv_header_synch_h" "$ac_includes_default" +if test "x$ac_cv_header_synch_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_SYNCH_H 1 +_ACEOF + +fi + +done + +for ac_header in sys/errno.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "sys/errno.h" "ac_cv_header_sys_errno_h" "$ac_includes_default" +if test "x$ac_cv_header_sys_errno_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_SYS_ERRNO_H 1 +_ACEOF + +fi + +done + +for ac_header in sys/file.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "sys/file.h" "ac_cv_header_sys_file_h" "$ac_includes_default" +if test "x$ac_cv_header_sys_file_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_SYS_FILE_H 1 +_ACEOF + +fi + +done + +for ac_header in sys/param.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "sys/param.h" "ac_cv_header_sys_param_h" "$ac_includes_default" +if test "x$ac_cv_header_sys_param_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_SYS_PARAM_H 1 +_ACEOF + +fi + +done + +for ac_header in sys/resource.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "sys/resource.h" "ac_cv_header_sys_resource_h" "$ac_includes_default" +if test "x$ac_cv_header_sys_resource_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_SYS_RESOURCE_H 1 +_ACEOF + +fi + +done + +for ac_header in sys/select.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "sys/select.h" "ac_cv_header_sys_select_h" "$ac_includes_default" +if test "x$ac_cv_header_sys_select_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_SYS_SELECT_H 1 +_ACEOF + +fi + +done + +for ac_header in sys/socket.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "sys/socket.h" "ac_cv_header_sys_socket_h" "$ac_includes_default" +if test "x$ac_cv_header_sys_socket_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_SYS_SOCKET_H 1 +_ACEOF + +fi + +done + +for ac_header in sys/stat.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "sys/stat.h" "ac_cv_header_sys_stat_h" "$ac_includes_default" +if test "x$ac_cv_header_sys_stat_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_SYS_STAT_H 1 +_ACEOF + +fi + +done + +for ac_header in sys/syscall.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "sys/syscall.h" "ac_cv_header_sys_syscall_h" "$ac_includes_default" +if test "x$ac_cv_header_sys_syscall_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_SYS_SYSCALL_H 1 +_ACEOF + +fi + +done + +for ac_header in sys/systeminfo.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "sys/systeminfo.h" "ac_cv_header_sys_systeminfo_h" "$ac_includes_default" +if test "x$ac_cv_header_sys_systeminfo_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_SYS_SYSTEMINFO_H 1 +_ACEOF + +fi + +done + +for ac_header in sys/time.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "sys/time.h" "ac_cv_header_sys_time_h" "$ac_includes_default" +if test "x$ac_cv_header_sys_time_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_SYS_TIME_H 1 +_ACEOF + +fi + +done + +for ac_header in sys/timeb.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "sys/timeb.h" "ac_cv_header_sys_timeb_h" "$ac_includes_default" +if test "x$ac_cv_header_sys_timeb_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_SYS_TIMEB_H 1 +_ACEOF + +fi + +done + +for ac_header in sys/types.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "sys/types.h" "ac_cv_header_sys_types_h" "$ac_includes_default" +if test "x$ac_cv_header_sys_types_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_SYS_TYPES_H 1 +_ACEOF + +fi + +done + +for ac_header in sys/utime.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "sys/utime.h" "ac_cv_header_sys_utime_h" "$ac_includes_default" +if test "x$ac_cv_header_sys_utime_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_SYS_UTIME_H 1 +_ACEOF + +fi + +done + +for ac_header in sys/utsname.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "sys/utsname.h" "ac_cv_header_sys_utsname_h" "$ac_includes_default" +if test "x$ac_cv_header_sys_utsname_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_SYS_UTSNAME_H 1 +_ACEOF + +fi + +done + +for ac_header in thread.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "thread.h" "ac_cv_header_thread_h" "$ac_includes_default" +if test "x$ac_cv_header_thread_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_THREAD_H 1 +_ACEOF + +fi + +done + +for ac_header in time.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "time.h" "ac_cv_header_time_h" "$ac_includes_default" +if test "x$ac_cv_header_time_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_TIME_H 1 +_ACEOF + +fi + +done + +for ac_header in unistd.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "unistd.h" "ac_cv_header_unistd_h" "$ac_includes_default" +if test "x$ac_cv_header_unistd_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_UNISTD_H 1 +_ACEOF + +fi + +done + +for ac_header in unix.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "unix.h" "ac_cv_header_unix_h" "$ac_includes_default" +if test "x$ac_cv_header_unix_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_UNIX_H 1 +_ACEOF + +fi + +done + +for ac_header in utime.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "utime.h" "ac_cv_header_utime_h" "$ac_includes_default" +if test "x$ac_cv_header_utime_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_UTIME_H 1 +_ACEOF + +fi + +done + +for ac_header in wchar.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "wchar.h" "ac_cv_header_wchar_h" "$ac_includes_default" +if test "x$ac_cv_header_wchar_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_WCHAR_H 1 +_ACEOF + +fi + +done + +for ac_header in wctype.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "wctype.h" "ac_cv_header_wctype_h" "$ac_includes_default" +if test "x$ac_cv_header_wctype_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_WCTYPE_H 1 +_ACEOF + +fi + +done + +for ac_header in fenv.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "fenv.h" "ac_cv_header_fenv_h" "$ac_includes_default" +if test "x$ac_cv_header_fenv_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_FENV_H 1 +_ACEOF + +fi + +done + + +if test $ac_cv_header_libc_h = yes ; then + if test $ac_cv_header_math_h = yes ; then + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether libc.h should be treated as a C++ header" >&5 +$as_echo_n "checking whether libc.h should be treated as a C++ header... " >&6; } +if ${ac_cv_cxx_libc_h_is_cxx+:} false; then : + $as_echo_n "(cached) " >&6 +else + + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +extern "C" { +#include +} +int +main () +{ +int i = 0 + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_cv_cxx_libc_h_is_cxx=no +else + ac_cv_cxx_libc_h_is_cxx=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cxx_libc_h_is_cxx" >&5 +$as_echo "$ac_cv_cxx_libc_h_is_cxx" >&6; } +if test "$ac_cv_cxx_libc_h_is_cxx" = yes; then + +$as_echo "#define INCLUDE_LIBC_H_AS_CXX /**/" >>confdefs.h + +fi + + fi +fi + + +if test $ac_cv_header_pthread_h = yes ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if pthread_t is a pointer type (in pthread.h)" >&5 +$as_echo_n "checking if pthread_t is a pointer type (in pthread.h)... " >&6; } + +ac_includes="" +cpp_code="" +if eval "test \"`echo '$ac_cv_cxx_static_cast'`\" = yes"; then + cpp_code="unsigned long l = static_cast(p)" +else + cpp_code="unsigned long l = p" +fi +for ac_header in pthread.h +do + ac_safe=`echo "$ac_header" | sed 'y%./+-%__p_%'` + if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'}'`\" = yes"; then + ac_includes="$ac_includes +#include<$ac_header>" + fi +done +tmp_save_1=`echo pthread_t | tr ' :' '__'` +if eval \${ac_cv_pointer_type_$tmp_save_1+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __cplusplus +extern "C" { +#endif +$ac_includes +#ifdef __cplusplus +} +#endif + +int +main () +{ +#ifdef __cplusplus +pthread_t p; $cpp_code +#else +pthread_t p; unsigned long l = p +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + eval "ac_cv_pointer_type_$tmp_save_1=no" +else + eval "ac_cv_pointer_type_$tmp_save_1=yes" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +if eval "test \"`echo '$''{'ac_cv_pointer_type_$tmp_save_1'}'`\" = yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + ac_tr_prototype=HAVE_POINTER_TYPE_`echo $tmp_save_1 | tr '[a-z]' '[A-Z]'` + cat >>confdefs.h <<_ACEOF +#define $ac_tr_prototype 1 +_ACEOF + + : +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + +fi + + +if test $THREADSUPPORT = auto ; then + if test $ac_cv_header_synch_h = yes ; then + THREADSUPPORT="solaris" + fi +fi +if test $THREADSUPPORT = auto ; then + if test $ac_cv_header_pthread_h = yes ; then + THREADSUPPORT="posix" + fi +fi +if test $THREADSUPPORT = auto ; then + THREADSUPPORT="no" +fi + + +if test $THREADSUPPORT = solaris ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sema_init in -lthread" >&5 +$as_echo_n "checking for sema_init in -lthread... " >&6; } +if ${ac_cv_lib_thread_sema_init+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lthread $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char sema_init (); +int +main () +{ +return sema_init (); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + ac_cv_lib_thread_sema_init=yes +else + ac_cv_lib_thread_sema_init=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_thread_sema_init" >&5 +$as_echo "$ac_cv_lib_thread_sema_init" >&6; } +if test "x$ac_cv_lib_thread_sema_init" = xyes; then : + + ac_tr_lib=HAVE_LIBTHREAD + cat >>confdefs.h <<_ACEOF +#define $ac_tr_lib 1 +_ACEOF + + LIBS="-lthread $LIBS" + +fi + +fi + +if test $THREADSUPPORT = posix ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_key_create in -lpthread" >&5 +$as_echo_n "checking for pthread_key_create in -lpthread... " >&6; } +if ${ac_cv_lib_pthread_pthread_key_create+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lpthread $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char pthread_key_create (); +int +main () +{ +return pthread_key_create (); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + ac_cv_lib_pthread_pthread_key_create=yes +else + ac_cv_lib_pthread_pthread_key_create=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthread_pthread_key_create" >&5 +$as_echo "$ac_cv_lib_pthread_pthread_key_create" >&6; } +if test "x$ac_cv_lib_pthread_pthread_key_create" = xyes; then : + + ac_tr_lib=HAVE_LIBPTHREAD + cat >>confdefs.h <<_ACEOF +#define $ac_tr_lib 1 +_ACEOF + + LIBS="-lpthread $LIBS" + +fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sem_init in -lrt" >&5 +$as_echo_n "checking for sem_init in -lrt... " >&6; } +if ${ac_cv_lib_rt_sem_init+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lrt $LIBS $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char sem_init (); +int +main () +{ +return sem_init (); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + ac_cv_lib_rt_sem_init=yes +else + ac_cv_lib_rt_sem_init=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_rt_sem_init" >&5 +$as_echo "$ac_cv_lib_rt_sem_init" >&6; } +if test "x$ac_cv_lib_rt_sem_init" = xyes; then : + + ac_tr_lib=HAVE_LIBRT + cat >>confdefs.h <<_ACEOF +#define $ac_tr_lib 1 +_ACEOF + + LIBS="-lrt $LIBS" + +fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether compiler requires -pthread option for posix threads" >&5 +$as_echo_n "checking whether compiler requires -pthread option for posix threads... " >&6; } +REQUIRES_PTHREAD_OPTION="no" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __cplusplus +extern "C" { +#endif + +#include +#ifdef __cplusplus +} +#endif + + +int +main () +{ + + (void) pthread_create(NULL, NULL, NULL, NULL); + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + +else + SAVE_CXXFLAGS="$CXXFLAGS" +SAVE_CFLAGS="$CFLAGS" +CXXFLAGS="-pthread $CXXFLAGS" +CFLAGS="-pthread $CFLAGS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __cplusplus +extern "C" { +#endif + +#include +#ifdef __cplusplus +} +#endif + + +int +main () +{ + + (void) pthread_create(NULL, NULL, NULL, NULL); + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + REQUIRES_PTHREAD_OPTION="yes" + +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +CXXFLAGS="$SAVE_CXXFLAGS" +CFLAGS="$SAVE_CFLAGS" + +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + +if test $REQUIRES_PTHREAD_OPTION = yes ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + CXXFLAGS="-pthread $CXXFLAGS" + CFLAGS="-pthread $CFLAGS" +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + POSIXRWLOCKSAVAILABLE="no" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_rwlock_init in -lpthread" >&5 +$as_echo_n "checking for pthread_rwlock_init in -lpthread... " >&6; } +if ${ac_cv_lib_pthread_pthread_rwlock_init+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lpthread $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char pthread_rwlock_init (); +int +main () +{ +return pthread_rwlock_init (); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + ac_cv_lib_pthread_pthread_rwlock_init=yes +else + ac_cv_lib_pthread_pthread_rwlock_init=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthread_pthread_rwlock_init" >&5 +$as_echo "$ac_cv_lib_pthread_pthread_rwlock_init" >&6; } +if test "x$ac_cv_lib_pthread_pthread_rwlock_init" = xyes; then : + + +$as_echo "#define HAVE_PTHREAD_RWLOCK /**/" >>confdefs.h + + POSIXRWLOCKSAVAILABLE="yes" + case "${host}" in + mips-sgi-irix6*) + CXXFLAGS="-D_XOPEN_SOURCE_EXTENDED -D_BSD_SOURCE -D_BSD_COMPAT $CXXFLAGS" + CFLAGS="-D_XOPEN_SOURCE_EXTENDED -D_BSD_SOURCE -D_BSD_COMPAT $CFLAGS" + ;; + *-*-openbsd3*) + CXXFLAGS="-D_POSIX_C_SOURCE=199506L $CXXFLAGS" + CFLAGS="-D_POSIX_C_SOURCE=199506L $CFLAGS" + ;; + *-*-openbsd4*) + ;; + *-*-openbsd5*) + ;; + *-*-freebsd*) + ;; + *-*-netbsdelf2*) + ;; + *-*-darwin*) + CXXFLAGS="-D_XOPEN_SOURCE_EXTENDED -D_BSD_SOURCE -D_BSD_COMPAT -D_OSF_SOURCE -D_DARWIN_C_SOURCE $CXXFLAGS" + CFLAGS="-D_XOPEN_SOURCE_EXTENDED -D_BSD_SOURCE -D_BSD_COMPAT -D_OSF_SOURCE -D_DARWIN_C_SOURCE $CXXFLAGS" + ;; + *) + CXXFLAGS="-D_XOPEN_SOURCE_EXTENDED -D_XOPEN_SOURCE=500 -D_BSD_SOURCE -D_DEFAULT_SOURCE -D_BSD_COMPAT -D_OSF_SOURCE -D_POSIX_C_SOURCE=199506L $CXXFLAGS" + CFLAGS="-D_XOPEN_SOURCE_EXTENDED -D_XOPEN_SOURCE=500 -D_BSD_SOURCE -D_DEFAULT_SOURCE -D_BSD_COMPAT -D_OSF_SOURCE -D_POSIX_C_SOURCE=199506L $CFLAGS" + ;; + esac + +else + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_rwlock_init in default libraries" >&5 +$as_echo_n "checking for pthread_rwlock_init in default libraries... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +extern "C" int pthread_rwlock_init(void *rwlock, void *attr); + +int +main () +{ +(void) pthread_rwlock_init(NULL, NULL); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +$as_echo "#define HAVE_PTHREAD_RWLOCK /**/" >>confdefs.h + + POSIXRWLOCKSAVAILABLE="yes" + case "${host}" in + mips-sgi-irix6*) + CXXFLAGS="-D_XOPEN_SOURCE_EXTENDED -D_BSD_SOURCE -D_BSD_COMPAT $CXXFLAGS" + CFLAGS="-D_XOPEN_SOURCE_EXTENDED -D_BSD_SOURCE -D_BSD_COMPAT $CFLAGS" + ;; + *-*-openbsd3*) + CXXFLAGS="-D_POSIX_C_SOURCE=199506L $CXXFLAGS" + CFLAGS="-D_POSIX_C_SOURCE=199506L $CFLAGS" + ;; + *-*-openbsd4*) + ;; + *-*-openbsd5*) + ;; + *-*-freebsd*) + ;; + *-*-netbsdelf2*) + ;; + *-*-darwin*) + CXXFLAGS="-D_XOPEN_SOURCE_EXTENDED -D_BSD_SOURCE -D_BSD_COMPAT -D_OSF_SOURCE -D_DARWIN_C_SOURCE $CXXFLAGS" + CFLAGS="-D_XOPEN_SOURCE_EXTENDED -D_BSD_SOURCE -D_BSD_COMPAT -D_OSF_SOURCE -D_DARWIN_C_SOURCE $CXXFLAGS" + ;; + *) + CXXFLAGS="-D_XOPEN_SOURCE_EXTENDED -D_XOPEN_SOURCE=500 -D_BSD_SOURCE -D_DEFAULT_SOURCE -D_BSD_COMPAT -D_OSF_SOURCE -D_POSIX_C_SOURCE=199506L $CXXFLAGS" + CFLAGS="-D_XOPEN_SOURCE_EXTENDED -D_XOPEN_SOURCE=500 -D_BSD_SOURCE -D_DEFAULT_SOURCE -D_BSD_COMPAT -D_OSF_SOURCE -D_POSIX_C_SOURCE=199506L $CFLAGS" + ;; + esac + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + + +fi + +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking multi-thread support" >&5 +$as_echo_n "checking multi-thread support... " >&6; } +case "$THREADSUPPORT" in + solaris) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes, solaris threads" >&5 +$as_echo "yes, solaris threads" >&6; } + CXXFLAGS="-D_REENTRANT $CXXFLAGS" + CFLAGS="-D_REENTRANT $CFLAGS" + +$as_echo "#define WITH_THREADS /**/" >>confdefs.h + + ;; + posix) + if test $POSIXRWLOCKSAVAILABLE = yes ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes, posix threads with rwlock" >&5 +$as_echo "yes, posix threads with rwlock" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes, posix threads without rwlock" >&5 +$as_echo "yes, posix threads without rwlock" >&6; } + fi + CXXFLAGS="-D_REENTRANT $CXXFLAGS" + CFLAGS="-D_REENTRANT $CFLAGS" + +$as_echo "#define WITH_THREADS /**/" >>confdefs.h + + ;; + *) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5 +$as_echo "none" >&6; } + ;; +esac + + +if test $LFSSUPPORT = auto -o $LFSSUPPORT = lfs64; then + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for explicit large file support" >&5 +$as_echo_n "checking for explicit large file support... " >&6; } + ac_cv_lfs64_support=no + + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#define _LARGEFILE64_SOURCE + #include +int +main () +{ +FILE *f = fopen64("name", "r"); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lfs64_support=yes +else + ac_cv_lfs64_support=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + + if test "$ac_cv_lfs64_support" = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +$as_echo "#define HAVE_LFS_SUPPORT /**/" >>confdefs.h + + +$as_echo "#define _LARGEFILE64_SOURCE 1" >>confdefs.h + + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + fi + + if test $ac_cv_lfs64_support = yes ; then + LFSSUPPORT="lfs64" + fi +fi + +if test $LFSSUPPORT = auto -o $LFSSUPPORT = lfs; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for special C compiler options needed for large files" >&5 +$as_echo_n "checking for special C compiler options needed for large files... " >&6; } +if ${ac_cv_sys_largefile_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_sys_largefile_CC=no + if test "$GCC" != yes; then + + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + ac_save_CC=$CC + while :; do + # IRIX 6.2 and later do not support large files by default, + # so use the C compiler's -n32 option if that helps. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + /* Check that off_t can represent 2**63 - 1 correctly. + We can't simply define LARGE_OFF_T to be 9223372036854775807, + since some C++ compilers masquerading as C compilers + incorrectly reject 9223372036854775807. */ +#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) + int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 + && LARGE_OFF_T % 2147483647 == 1) + ? 1 : -1]; +int +main () +{ + + ; + return 0; +} +_ACEOF + if ac_fn_c_try_compile "$LINENO"; then : + break +fi +rm -f core conftest.err conftest.$ac_objext + CC="$CC -n32" + if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_sys_largefile_CC=' -n32'; break +fi +rm -f core conftest.err conftest.$ac_objext + break + done + CC=$ac_save_CC + rm -f conftest.$ac_ext + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_largefile_CC" >&5 +$as_echo "$ac_cv_sys_largefile_CC" >&6; } + if test "$ac_cv_sys_largefile_CC" != no; then + CC=$CC$ac_cv_sys_largefile_CC + CXX=$CXX$ac_cv_sys_largefile_CC + fi + + ac_cv_lfs64_support=no + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _FILE_OFFSET_BITS value needed for large files" >&5 +$as_echo_n "checking for _FILE_OFFSET_BITS value needed for large files... " >&6; } +if ${ac_cv_sys_file_offset_bits+:} false; then : + $as_echo_n "(cached) " >&6 +else + while :; do + ac_cv_sys_file_offset_bits=no + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + /* Check that off_t can represent 2**63 - 1 correctly. + We can't simply define LARGE_OFF_T to be 9223372036854775807, + since some C++ compilers masquerading as C compilers + incorrectly reject 9223372036854775807. */ +#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) + int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 + && LARGE_OFF_T % 2147483647 == 1) + ? 1 : -1]; +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_cv_lfs_support=yes; break +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#define _FILE_OFFSET_BITS 64 +#include + /* Check that off_t can represent 2**63 - 1 correctly. + We can't simply define LARGE_OFF_T to be 9223372036854775807, + since some C++ compilers masquerading as C compilers + incorrectly reject 9223372036854775807. */ +#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) + int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 + && LARGE_OFF_T % 2147483647 == 1) + ? 1 : -1]; +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_cv_sys_file_offset_bits=64; ac_cv_lfs_support=yes; break +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + break +done +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_file_offset_bits" >&5 +$as_echo "$ac_cv_sys_file_offset_bits" >&6; } +if test "$ac_cv_sys_file_offset_bits" != no; then + +cat >>confdefs.h <<_ACEOF +#define _FILE_OFFSET_BITS $ac_cv_sys_file_offset_bits +_ACEOF + +fi +rm -f conftest* + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _LARGE_FILES value needed for large files" >&5 +$as_echo_n "checking for _LARGE_FILES value needed for large files... " >&6; } +if ${ac_cv_sys_large_files+:} false; then : + $as_echo_n "(cached) " >&6 +else + while :; do + ac_cv_sys_large_files=no + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + /* Check that off_t can represent 2**63 - 1 correctly. + We can't simply define LARGE_OFF_T to be 9223372036854775807, + since some C++ compilers masquerading as C compilers + incorrectly reject 9223372036854775807. */ +#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) + int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 + && LARGE_OFF_T % 2147483647 == 1) + ? 1 : -1]; +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_cv_lfs_support=yes; break +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#define _LARGE_FILES 1 +#include + /* Check that off_t can represent 2**63 - 1 correctly. + We can't simply define LARGE_OFF_T to be 9223372036854775807, + since some C++ compilers masquerading as C compilers + incorrectly reject 9223372036854775807. */ +#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) + int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 + && LARGE_OFF_T % 2147483647 == 1) + ? 1 : -1]; +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_cv_sys_large_files=1; ac_cv_lfs_support=yes; break +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + break +done +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_large_files" >&5 +$as_echo "$ac_cv_sys_large_files" >&6; } +if test "$ac_cv_sys_large_files" != no; then + +cat >>confdefs.h <<_ACEOF +#define _LARGE_FILES $ac_cv_sys_large_files +_ACEOF + +fi +rm -f conftest* + + if test "$ac_cv_lfs_support" = yes; then + +$as_echo "#define HAVE_LFS_SUPPORT /**/" >>confdefs.h + + fi + + +fi + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for size_t" >&5 +$as_echo_n "checking for size_t... " >&6; } +if ${ac_cv_type_size_t+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +if ((size_t *) 0) + return 0; +if (sizeof (size_t)) + return 0; + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_cv_type_size_t=yes +else + ac_cv_type_size_t=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_type_size_t" >&5 +$as_echo "$ac_cv_type_size_t" >&6; } +if test $ac_cv_type_size_t = yes; then : + +else + +cat >>confdefs.h <<_ACEOF +#define HAVE_NO_TYPEDEF_SIZE_T 1 +_ACEOF + +fi + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ssize_t" >&5 +$as_echo_n "checking for ssize_t... " >&6; } +if ${ac_cv_type_ssize_t+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +if ((ssize_t *) 0) + return 0; +if (sizeof (ssize_t)) + return 0; + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_cv_type_ssize_t=yes +else + ac_cv_type_ssize_t=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_type_ssize_t" >&5 +$as_echo "$ac_cv_type_ssize_t" >&6; } +if test $ac_cv_type_ssize_t = yes; then : + +else + +cat >>confdefs.h <<_ACEOF +#define HAVE_NO_TYPEDEF_SSIZE_T 1 +_ACEOF + +fi + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for pid_t" >&5 +$as_echo_n "checking for pid_t... " >&6; } +if ${ac_cv_type_pid_t+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +if ((pid_t *) 0) + return 0; +if (sizeof (pid_t)) + return 0; + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_cv_type_pid_t=yes +else + ac_cv_type_pid_t=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_type_pid_t" >&5 +$as_echo "$ac_cv_type_pid_t" >&6; } +if test $ac_cv_type_pid_t = yes; then : + +else + +cat >>confdefs.h <<_ACEOF +#define HAVE_NO_TYPEDEF_PID_T 1 +_ACEOF + +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether char is unsigned" >&5 +$as_echo_n "checking whether char is unsigned... " >&6; } +if ${ac_cv_c_char_unsigned+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +static int test_array [1 - 2 * !(((char) -1) < 0)]; +test_array [0] = 0; +return test_array [0]; + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_cv_c_char_unsigned=no +else + ac_cv_c_char_unsigned=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_char_unsigned" >&5 +$as_echo "$ac_cv_c_char_unsigned" >&6; } +if test $ac_cv_c_char_unsigned = yes && test "$GCC" != yes; then + $as_echo "#define __CHAR_UNSIGNED__ 1" >>confdefs.h + +fi + +# The cast to long int works around a bug in the HP C Compiler +# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects +# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. +# This bug is HP SR number 8606223364. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of char" >&5 +$as_echo_n "checking size of char... " >&6; } +if ${ac_cv_sizeof_char+:} false; then : + $as_echo_n "(cached) " >&6 +else + if ac_fn_cxx_compute_int "$LINENO" "(long int) (sizeof (char))" "ac_cv_sizeof_char" "$ac_includes_default"; then : + +else + if test "$ac_cv_type_char" = yes; then + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "cannot compute sizeof (char) +See \`config.log' for more details" "$LINENO" 5; } + else + ac_cv_sizeof_char=0 + fi +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_char" >&5 +$as_echo "$ac_cv_sizeof_char" >&6; } + + + +cat >>confdefs.h <<_ACEOF +#define SIZEOF_CHAR $ac_cv_sizeof_char +_ACEOF + + +# The cast to long int works around a bug in the HP C Compiler +# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects +# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. +# This bug is HP SR number 8606223364. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of short" >&5 +$as_echo_n "checking size of short... " >&6; } +if ${ac_cv_sizeof_short+:} false; then : + $as_echo_n "(cached) " >&6 +else + if ac_fn_cxx_compute_int "$LINENO" "(long int) (sizeof (short))" "ac_cv_sizeof_short" "$ac_includes_default"; then : + +else + if test "$ac_cv_type_short" = yes; then + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "cannot compute sizeof (short) +See \`config.log' for more details" "$LINENO" 5; } + else + ac_cv_sizeof_short=0 + fi +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_short" >&5 +$as_echo "$ac_cv_sizeof_short" >&6; } + + + +cat >>confdefs.h <<_ACEOF +#define SIZEOF_SHORT $ac_cv_sizeof_short +_ACEOF + + +# The cast to long int works around a bug in the HP C Compiler +# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects +# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. +# This bug is HP SR number 8606223364. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of int" >&5 +$as_echo_n "checking size of int... " >&6; } +if ${ac_cv_sizeof_int+:} false; then : + $as_echo_n "(cached) " >&6 +else + if ac_fn_cxx_compute_int "$LINENO" "(long int) (sizeof (int))" "ac_cv_sizeof_int" "$ac_includes_default"; then : + +else + if test "$ac_cv_type_int" = yes; then + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "cannot compute sizeof (int) +See \`config.log' for more details" "$LINENO" 5; } + else + ac_cv_sizeof_int=0 + fi +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_int" >&5 +$as_echo "$ac_cv_sizeof_int" >&6; } + + + +cat >>confdefs.h <<_ACEOF +#define SIZEOF_INT $ac_cv_sizeof_int +_ACEOF + + +# The cast to long int works around a bug in the HP C Compiler +# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects +# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. +# This bug is HP SR number 8606223364. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of long" >&5 +$as_echo_n "checking size of long... " >&6; } +if ${ac_cv_sizeof_long+:} false; then : + $as_echo_n "(cached) " >&6 +else + if ac_fn_cxx_compute_int "$LINENO" "(long int) (sizeof (long))" "ac_cv_sizeof_long" "$ac_includes_default"; then : + +else + if test "$ac_cv_type_long" = yes; then + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "cannot compute sizeof (long) +See \`config.log' for more details" "$LINENO" 5; } + else + ac_cv_sizeof_long=0 + fi +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_long" >&5 +$as_echo "$ac_cv_sizeof_long" >&6; } + + + +cat >>confdefs.h <<_ACEOF +#define SIZEOF_LONG $ac_cv_sizeof_long +_ACEOF + + +# The cast to long int works around a bug in the HP C Compiler +# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects +# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. +# This bug is HP SR number 8606223364. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of float" >&5 +$as_echo_n "checking size of float... " >&6; } +if ${ac_cv_sizeof_float+:} false; then : + $as_echo_n "(cached) " >&6 +else + if ac_fn_cxx_compute_int "$LINENO" "(long int) (sizeof (float))" "ac_cv_sizeof_float" "$ac_includes_default"; then : + +else + if test "$ac_cv_type_float" = yes; then + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "cannot compute sizeof (float) +See \`config.log' for more details" "$LINENO" 5; } + else + ac_cv_sizeof_float=0 + fi +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_float" >&5 +$as_echo "$ac_cv_sizeof_float" >&6; } + + + +cat >>confdefs.h <<_ACEOF +#define SIZEOF_FLOAT $ac_cv_sizeof_float +_ACEOF + + +# The cast to long int works around a bug in the HP C Compiler +# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects +# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. +# This bug is HP SR number 8606223364. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of double" >&5 +$as_echo_n "checking size of double... " >&6; } +if ${ac_cv_sizeof_double+:} false; then : + $as_echo_n "(cached) " >&6 +else + if ac_fn_cxx_compute_int "$LINENO" "(long int) (sizeof (double))" "ac_cv_sizeof_double" "$ac_includes_default"; then : + +else + if test "$ac_cv_type_double" = yes; then + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "cannot compute sizeof (double) +See \`config.log' for more details" "$LINENO" 5; } + else + ac_cv_sizeof_double=0 + fi +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_double" >&5 +$as_echo "$ac_cv_sizeof_double" >&6; } + + + +cat >>confdefs.h <<_ACEOF +#define SIZEOF_DOUBLE $ac_cv_sizeof_double +_ACEOF + + +# The cast to long int works around a bug in the HP C Compiler +# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects +# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. +# This bug is HP SR number 8606223364. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of void *" >&5 +$as_echo_n "checking size of void *... " >&6; } +if ${ac_cv_sizeof_void_p+:} false; then : + $as_echo_n "(cached) " >&6 +else + if ac_fn_cxx_compute_int "$LINENO" "(long int) (sizeof (void *))" "ac_cv_sizeof_void_p" "$ac_includes_default"; then : + +else + if test "$ac_cv_type_void_p" = yes; then + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "cannot compute sizeof (void *) +See \`config.log' for more details" "$LINENO" 5; } + else + ac_cv_sizeof_void_p=0 + fi +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_void_p" >&5 +$as_echo "$ac_cv_sizeof_void_p" >&6; } + + + +cat >>confdefs.h <<_ACEOF +#define SIZEOF_VOID_P $ac_cv_sizeof_void_p +_ACEOF + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether struct tm is in sys/time.h or time.h" >&5 +$as_echo_n "checking whether struct tm is in sys/time.h or time.h... " >&6; } +if ${ac_cv_struct_tm+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include + +int +main () +{ +struct tm tm; + int *p = &tm.tm_sec; + return !p; + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_cv_struct_tm=time.h +else + ac_cv_struct_tm=sys/time.h +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_struct_tm" >&5 +$as_echo "$ac_cv_struct_tm" >&6; } +if test $ac_cv_struct_tm = sys/time.h; then + +$as_echo "#define TM_IN_SYS_TIME 1" >>confdefs.h + +fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for __FUNCTION__ macro" >&5 +$as_echo_n "checking for __FUNCTION__ macro... " >&6; } +if ${ac_cv_have___FUNCTION___macro+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +const char * func = __FUNCTION__; + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_cv_have___FUNCTION___macro=yes +else + ac_cv_have___FUNCTION___macro=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have___FUNCTION___macro" >&5 +$as_echo "$ac_cv_have___FUNCTION___macro" >&6; } + if test "x$ac_cv_have___FUNCTION___macro" = "xyes"; then + $as_echo "#define HAVE___FUNCTION___MACRO 1" >>confdefs.h + + fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for __PRETTY_FUNCTION__ macro" >&5 +$as_echo_n "checking for __PRETTY_FUNCTION__ macro... " >&6; } +if ${ac_cv_have___PRETTY_FUNCTION___macro+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +const char * func = __PRETTY_FUNCTION__; + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_cv_have___PRETTY_FUNCTION___macro=yes +else + ac_cv_have___PRETTY_FUNCTION___macro=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have___PRETTY_FUNCTION___macro" >&5 +$as_echo "$ac_cv_have___PRETTY_FUNCTION___macro" >&6; } + if test "x$ac_cv_have___PRETTY_FUNCTION___macro" = "xyes"; then + $as_echo "#define HAVE___PRETTY_FUNCTION___MACRO 1" >>confdefs.h + + fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for __func__ macro" >&5 +$as_echo_n "checking for __func__ macro... " >&6; } +if ${ac_cv_have___func___macro+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +const char * func = __func__; + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_cv_have___func___macro=yes +else + ac_cv_have___func___macro=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have___func___macro" >&5 +$as_echo "$ac_cv_have___func___macro" >&6; } + if test "x$ac_cv_have___func___macro" = "xyes"; then + $as_echo "#define HAVE___func___MACRO 1" >>confdefs.h + + fi + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking prototype for _stricmp (in string.h)" >&5 +$as_echo_n "checking prototype for _stricmp (in string.h)... " >&6; } + +: + +ac_includes="" +for ac_header in string.h +do + ac_safe=`echo "$ac_header" | sed 'y%./+-%__p_%'` + if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'}'`\" = yes"; then + ac_includes="$ac_includes +#include<$ac_header>" + fi +done +tmp_save_1=`echo _stricmp | tr ' :' '__'` +if eval \${ac_cv_prototype_$tmp_save_1+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __cplusplus +extern "C" { +#endif +$ac_includes +#ifdef __cplusplus +} +#endif +typedef union { int member; } dummyStruct; +#ifdef __cplusplus +extern "C" +#endif +dummyStruct _stricmp(dummyStruct); + + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + eval "ac_cv_prototype_$tmp_save_1=no" +else + eval "ac_cv_prototype_$tmp_save_1=yes" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +if eval "test \"`echo '$''{'ac_cv_prototype_$tmp_save_1'}'`\" = yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + ac_tr_prototype=HAVE_PROTOTYPE_`echo $tmp_save_1 | tr '[a-z]' '[A-Z]'` + cat >>confdefs.h <<_ACEOF +#define $ac_tr_prototype 1 +_ACEOF + + : +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking prototype for accept (in sys/types.h sys/socket.h)" >&5 +$as_echo_n "checking prototype for accept (in sys/types.h sys/socket.h)... " >&6; } + +: + +ac_includes="" +for ac_header in sys/types.h sys/socket.h +do + ac_safe=`echo "$ac_header" | sed 'y%./+-%__p_%'` + if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'}'`\" = yes"; then + ac_includes="$ac_includes +#include<$ac_header>" + fi +done +tmp_save_1=`echo accept | tr ' :' '__'` +if eval \${ac_cv_prototype_$tmp_save_1+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __cplusplus +extern "C" { +#endif +$ac_includes +#ifdef __cplusplus +} +#endif +typedef union { int member; } dummyStruct; +#ifdef __cplusplus +extern "C" +#endif +dummyStruct accept(dummyStruct); + + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + eval "ac_cv_prototype_$tmp_save_1=no" +else + eval "ac_cv_prototype_$tmp_save_1=yes" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +if eval "test \"`echo '$''{'ac_cv_prototype_$tmp_save_1'}'`\" = yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + ac_tr_prototype=HAVE_PROTOTYPE_`echo $tmp_save_1 | tr '[a-z]' '[A-Z]'` + cat >>confdefs.h <<_ACEOF +#define $ac_tr_prototype 1 +_ACEOF + + : +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + +if test $ac_cv_prototype_accept = yes ; then +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if accept() needs int* parameters (in sys/types.h sys/socket.h)" >&5 +$as_echo_n "checking if accept() needs int* parameters (in sys/types.h sys/socket.h)... " >&6; } + +ac_includes="" +for ac_header in sys/types.h sys/socket.h +do + ac_includes="$ac_includes +#include<$ac_header>" +done +if ${ac_cv_prototype_intp_accept+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __cplusplus +extern "C" { +#endif +$ac_includes +#ifdef __cplusplus +} +#endif + + +int +main () +{ + + int i; + struct sockaddr *addr; + size_t addrlen; + + addr = 0; + addrlen = 0; + i = accept(1, addr, &addrlen); + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + eval "ac_cv_prototype_intp_accept=no" +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __cplusplus +extern "C" { +#endif +$ac_includes +#ifdef __cplusplus +} +#endif + + +int +main () +{ + + int i; + struct sockaddr *addr; + int addrlen; + + addr = 0; + addrlen = 0; + i = accept(1, addr, &addrlen); + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + eval "ac_cv_prototype_intp_accept=yes" +else + eval "ac_cv_prototype_intp_accept=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi + +if eval "test \"`echo $ac_cv_prototype_intp_accept`\" = yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + ac_tr_prototype=HAVE_INTP_ACCEPT + cat >>confdefs.h <<_ACEOF +#define $ac_tr_prototype 1 +_ACEOF + + : +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking prototype for bind (in sys/types.h sys/socket.h)" >&5 +$as_echo_n "checking prototype for bind (in sys/types.h sys/socket.h)... " >&6; } + +: + +ac_includes="" +for ac_header in sys/types.h sys/socket.h +do + ac_safe=`echo "$ac_header" | sed 'y%./+-%__p_%'` + if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'}'`\" = yes"; then + ac_includes="$ac_includes +#include<$ac_header>" + fi +done +tmp_save_1=`echo bind | tr ' :' '__'` +if eval \${ac_cv_prototype_$tmp_save_1+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __cplusplus +extern "C" { +#endif +$ac_includes +#ifdef __cplusplus +} +#endif +typedef union { int member; } dummyStruct; +#ifdef __cplusplus +extern "C" +#endif +dummyStruct bind(dummyStruct); + + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + eval "ac_cv_prototype_$tmp_save_1=no" +else + eval "ac_cv_prototype_$tmp_save_1=yes" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +if eval "test \"`echo '$''{'ac_cv_prototype_$tmp_save_1'}'`\" = yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + ac_tr_prototype=HAVE_PROTOTYPE_`echo $tmp_save_1 | tr '[a-z]' '[A-Z]'` + cat >>confdefs.h <<_ACEOF +#define $ac_tr_prototype 1 +_ACEOF + + : +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking prototype for bzero (in string.h strings.h libc.h unistd.h stdlib.h)" >&5 +$as_echo_n "checking prototype for bzero (in string.h strings.h libc.h unistd.h stdlib.h)... " >&6; } + +: + +ac_includes="" +for ac_header in string.h strings.h libc.h unistd.h stdlib.h +do + ac_safe=`echo "$ac_header" | sed 'y%./+-%__p_%'` + if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'}'`\" = yes"; then + ac_includes="$ac_includes +#include<$ac_header>" + fi +done +tmp_save_1=`echo bzero | tr ' :' '__'` +if eval \${ac_cv_prototype_$tmp_save_1+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __cplusplus +extern "C" { +#endif +$ac_includes +#ifdef __cplusplus +} +#endif +typedef union { int member; } dummyStruct; +#ifdef __cplusplus +extern "C" +#endif +dummyStruct bzero(dummyStruct); + + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + eval "ac_cv_prototype_$tmp_save_1=no" +else + eval "ac_cv_prototype_$tmp_save_1=yes" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +if eval "test \"`echo '$''{'ac_cv_prototype_$tmp_save_1'}'`\" = yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + ac_tr_prototype=HAVE_PROTOTYPE_`echo $tmp_save_1 | tr '[a-z]' '[A-Z]'` + cat >>confdefs.h <<_ACEOF +#define $ac_tr_prototype 1 +_ACEOF + + : +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking prototype for connect (in sys/types.h sys/socket.h)" >&5 +$as_echo_n "checking prototype for connect (in sys/types.h sys/socket.h)... " >&6; } + +: + +ac_includes="" +for ac_header in sys/types.h sys/socket.h +do + ac_safe=`echo "$ac_header" | sed 'y%./+-%__p_%'` + if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'}'`\" = yes"; then + ac_includes="$ac_includes +#include<$ac_header>" + fi +done +tmp_save_1=`echo connect | tr ' :' '__'` +if eval \${ac_cv_prototype_$tmp_save_1+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __cplusplus +extern "C" { +#endif +$ac_includes +#ifdef __cplusplus +} +#endif +typedef union { int member; } dummyStruct; +#ifdef __cplusplus +extern "C" +#endif +dummyStruct connect(dummyStruct); + + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + eval "ac_cv_prototype_$tmp_save_1=no" +else + eval "ac_cv_prototype_$tmp_save_1=yes" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +if eval "test \"`echo '$''{'ac_cv_prototype_$tmp_save_1'}'`\" = yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + ac_tr_prototype=HAVE_PROTOTYPE_`echo $tmp_save_1 | tr '[a-z]' '[A-Z]'` + cat >>confdefs.h <<_ACEOF +#define $ac_tr_prototype 1 +_ACEOF + + : +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking prototype for finite (in math.h)" >&5 +$as_echo_n "checking prototype for finite (in math.h)... " >&6; } + +: + +ac_includes="" +for ac_header in math.h +do + ac_safe=`echo "$ac_header" | sed 'y%./+-%__p_%'` + if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'}'`\" = yes"; then + ac_includes="$ac_includes +#include<$ac_header>" + fi +done +tmp_save_1=`echo finite | tr ' :' '__'` +if eval \${ac_cv_prototype_$tmp_save_1+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __cplusplus +extern "C" { +#endif +$ac_includes +#ifdef __cplusplus +} +#endif +typedef union { int member; } dummyStruct; +#ifdef __cplusplus +extern "C" +#endif +dummyStruct finite(dummyStruct); + + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + eval "ac_cv_prototype_$tmp_save_1=no" +else + eval "ac_cv_prototype_$tmp_save_1=yes" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +if eval "test \"`echo '$''{'ac_cv_prototype_$tmp_save_1'}'`\" = yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + ac_tr_prototype=HAVE_PROTOTYPE_`echo $tmp_save_1 | tr '[a-z]' '[A-Z]'` + cat >>confdefs.h <<_ACEOF +#define $ac_tr_prototype 1 +_ACEOF + + : +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking prototype for isinf (in math.h)" >&5 +$as_echo_n "checking prototype for isinf (in math.h)... " >&6; } + +: + +ac_includes="" +for ac_header in math.h +do + ac_safe=`echo "$ac_header" | sed 'y%./+-%__p_%'` + if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'}'`\" = yes"; then + ac_includes="$ac_includes +#include<$ac_header>" + fi +done +tmp_save_1=`echo isinf | tr ' :' '__'` +if eval \${ac_cv_prototype_$tmp_save_1+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __cplusplus +extern "C" { +#endif +$ac_includes +#ifdef __cplusplus +} +#endif +typedef union { int member; } dummyStruct; +#ifdef __cplusplus +extern "C" +#endif +dummyStruct isinf(dummyStruct); + + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + eval "ac_cv_prototype_$tmp_save_1=no" +else + eval "ac_cv_prototype_$tmp_save_1=yes" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +if eval "test \"`echo '$''{'ac_cv_prototype_$tmp_save_1'}'`\" = yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + ac_tr_prototype=HAVE_PROTOTYPE_`echo $tmp_save_1 | tr '[a-z]' '[A-Z]'` + cat >>confdefs.h <<_ACEOF +#define $ac_tr_prototype 1 +_ACEOF + + : +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking prototype for isnan (in math.h)" >&5 +$as_echo_n "checking prototype for isnan (in math.h)... " >&6; } + +: + +ac_includes="" +for ac_header in math.h +do + ac_safe=`echo "$ac_header" | sed 'y%./+-%__p_%'` + if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'}'`\" = yes"; then + ac_includes="$ac_includes +#include<$ac_header>" + fi +done +tmp_save_1=`echo isnan | tr ' :' '__'` +if eval \${ac_cv_prototype_$tmp_save_1+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __cplusplus +extern "C" { +#endif +$ac_includes +#ifdef __cplusplus +} +#endif +typedef union { int member; } dummyStruct; +#ifdef __cplusplus +extern "C" +#endif +dummyStruct isnan(dummyStruct); + + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + eval "ac_cv_prototype_$tmp_save_1=no" +else + eval "ac_cv_prototype_$tmp_save_1=yes" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +if eval "test \"`echo '$''{'ac_cv_prototype_$tmp_save_1'}'`\" = yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + ac_tr_prototype=HAVE_PROTOTYPE_`echo $tmp_save_1 | tr '[a-z]' '[A-Z]'` + cat >>confdefs.h <<_ACEOF +#define $ac_tr_prototype 1 +_ACEOF + + : +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking prototype for std::finite (in cmath)" >&5 +$as_echo_n "checking prototype for std::finite (in cmath)... " >&6; } + +: + +ac_includes="" +for ac_header in cmath +do + ac_safe=`echo "$ac_header" | sed 'y%./+-%__p_%'` + if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'}'`\" = yes"; then + ac_includes="$ac_includes +#include<$ac_header>" + fi +done +tmp_save_1=`echo std::finite | tr ' :' '__'` +if eval \${ac_cv_prototype_$tmp_save_1+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __cplusplus +extern "C" { +#endif +$ac_includes +#ifdef __cplusplus +} +#endif +typedef union { int member; } dummyStruct; +#ifdef __cplusplus +extern "C" +#endif +dummyStruct std::finite(dummyStruct); + + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + eval "ac_cv_prototype_$tmp_save_1=no" +else + eval "ac_cv_prototype_$tmp_save_1=yes" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +if eval "test \"`echo '$''{'ac_cv_prototype_$tmp_save_1'}'`\" = yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + ac_tr_prototype=HAVE_PROTOTYPE_`echo $tmp_save_1 | tr '[a-z]' '[A-Z]'` + cat >>confdefs.h <<_ACEOF +#define $ac_tr_prototype 1 +_ACEOF + + : +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking prototype for std::isinf (in cmath)" >&5 +$as_echo_n "checking prototype for std::isinf (in cmath)... " >&6; } + +: + +ac_includes="" +for ac_header in cmath +do + ac_safe=`echo "$ac_header" | sed 'y%./+-%__p_%'` + if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'}'`\" = yes"; then + ac_includes="$ac_includes +#include<$ac_header>" + fi +done +tmp_save_1=`echo std::isinf | tr ' :' '__'` +if eval \${ac_cv_prototype_$tmp_save_1+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __cplusplus +extern "C" { +#endif +$ac_includes +#ifdef __cplusplus +} +#endif +typedef union { int member; } dummyStruct; +#ifdef __cplusplus +extern "C" +#endif +dummyStruct std::isinf(dummyStruct); + + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + eval "ac_cv_prototype_$tmp_save_1=no" +else + eval "ac_cv_prototype_$tmp_save_1=yes" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +if eval "test \"`echo '$''{'ac_cv_prototype_$tmp_save_1'}'`\" = yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + ac_tr_prototype=HAVE_PROTOTYPE_`echo $tmp_save_1 | tr '[a-z]' '[A-Z]'` + cat >>confdefs.h <<_ACEOF +#define $ac_tr_prototype 1 +_ACEOF + + : +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking prototype for std::isnan (in cmath)" >&5 +$as_echo_n "checking prototype for std::isnan (in cmath)... " >&6; } + +: + +ac_includes="" +for ac_header in cmath +do + ac_safe=`echo "$ac_header" | sed 'y%./+-%__p_%'` + if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'}'`\" = yes"; then + ac_includes="$ac_includes +#include<$ac_header>" + fi +done +tmp_save_1=`echo std::isnan | tr ' :' '__'` +if eval \${ac_cv_prototype_$tmp_save_1+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __cplusplus +extern "C" { +#endif +$ac_includes +#ifdef __cplusplus +} +#endif +typedef union { int member; } dummyStruct; +#ifdef __cplusplus +extern "C" +#endif +dummyStruct std::isnan(dummyStruct); + + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + eval "ac_cv_prototype_$tmp_save_1=no" +else + eval "ac_cv_prototype_$tmp_save_1=yes" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +if eval "test \"`echo '$''{'ac_cv_prototype_$tmp_save_1'}'`\" = yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + ac_tr_prototype=HAVE_PROTOTYPE_`echo $tmp_save_1 | tr '[a-z]' '[A-Z]'` + cat >>confdefs.h <<_ACEOF +#define $ac_tr_prototype 1 +_ACEOF + + : +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking prototype for flock (in sys/file.h)" >&5 +$as_echo_n "checking prototype for flock (in sys/file.h)... " >&6; } + +: + +ac_includes="" +for ac_header in sys/file.h +do + ac_safe=`echo "$ac_header" | sed 'y%./+-%__p_%'` + if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'}'`\" = yes"; then + ac_includes="$ac_includes +#include<$ac_header>" + fi +done +tmp_save_1=`echo flock | tr ' :' '__'` +if eval \${ac_cv_prototype_$tmp_save_1+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __cplusplus +extern "C" { +#endif +$ac_includes +#ifdef __cplusplus +} +#endif +typedef union { int member; } dummyStruct; +#ifdef __cplusplus +extern "C" +#endif +dummyStruct flock(dummyStruct); + + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + eval "ac_cv_prototype_$tmp_save_1=no" +else + eval "ac_cv_prototype_$tmp_save_1=yes" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +if eval "test \"`echo '$''{'ac_cv_prototype_$tmp_save_1'}'`\" = yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + ac_tr_prototype=HAVE_PROTOTYPE_`echo $tmp_save_1 | tr '[a-z]' '[A-Z]'` + cat >>confdefs.h <<_ACEOF +#define $ac_tr_prototype 1 +_ACEOF + + : +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking prototype for gethostbyname (in libc.h unistd.h stdlib.h netdb.h)" >&5 +$as_echo_n "checking prototype for gethostbyname (in libc.h unistd.h stdlib.h netdb.h)... " >&6; } + +: + +ac_includes="" +for ac_header in libc.h unistd.h stdlib.h netdb.h +do + ac_safe=`echo "$ac_header" | sed 'y%./+-%__p_%'` + if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'}'`\" = yes"; then + ac_includes="$ac_includes +#include<$ac_header>" + fi +done +tmp_save_1=`echo gethostbyname | tr ' :' '__'` +if eval \${ac_cv_prototype_$tmp_save_1+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __cplusplus +extern "C" { +#endif +$ac_includes +#ifdef __cplusplus +} +#endif +typedef union { int member; } dummyStruct; +#ifdef __cplusplus +extern "C" +#endif +dummyStruct gethostbyname(dummyStruct); + + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + eval "ac_cv_prototype_$tmp_save_1=no" +else + eval "ac_cv_prototype_$tmp_save_1=yes" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +if eval "test \"`echo '$''{'ac_cv_prototype_$tmp_save_1'}'`\" = yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + ac_tr_prototype=HAVE_PROTOTYPE_`echo $tmp_save_1 | tr '[a-z]' '[A-Z]'` + cat >>confdefs.h <<_ACEOF +#define $ac_tr_prototype 1 +_ACEOF + + : +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking prototype for gethostbyname_r (in libc.h unistd.h stdlib.h netdb.h)" >&5 +$as_echo_n "checking prototype for gethostbyname_r (in libc.h unistd.h stdlib.h netdb.h)... " >&6; } + +: + +ac_includes="" +for ac_header in libc.h unistd.h stdlib.h netdb.h +do + ac_safe=`echo "$ac_header" | sed 'y%./+-%__p_%'` + if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'}'`\" = yes"; then + ac_includes="$ac_includes +#include<$ac_header>" + fi +done +tmp_save_1=`echo gethostbyname_r | tr ' :' '__'` +if eval \${ac_cv_prototype_$tmp_save_1+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __cplusplus +extern "C" { +#endif +$ac_includes +#ifdef __cplusplus +} +#endif +typedef union { int member; } dummyStruct; +#ifdef __cplusplus +extern "C" +#endif +dummyStruct gethostbyname_r(dummyStruct); + + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + eval "ac_cv_prototype_$tmp_save_1=no" +else + eval "ac_cv_prototype_$tmp_save_1=yes" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +if eval "test \"`echo '$''{'ac_cv_prototype_$tmp_save_1'}'`\" = yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + ac_tr_prototype=HAVE_PROTOTYPE_`echo $tmp_save_1 | tr '[a-z]' '[A-Z]'` + cat >>confdefs.h <<_ACEOF +#define $ac_tr_prototype 1 +_ACEOF + + : +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking prototype for gethostid (in libc.h unistd.h stdlib.h netdb.h)" >&5 +$as_echo_n "checking prototype for gethostid (in libc.h unistd.h stdlib.h netdb.h)... " >&6; } + +: + +ac_includes="" +for ac_header in libc.h unistd.h stdlib.h netdb.h +do + ac_safe=`echo "$ac_header" | sed 'y%./+-%__p_%'` + if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'}'`\" = yes"; then + ac_includes="$ac_includes +#include<$ac_header>" + fi +done +tmp_save_1=`echo gethostid | tr ' :' '__'` +if eval \${ac_cv_prototype_$tmp_save_1+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __cplusplus +extern "C" { +#endif +$ac_includes +#ifdef __cplusplus +} +#endif +typedef union { int member; } dummyStruct; +#ifdef __cplusplus +extern "C" +#endif +dummyStruct gethostid(dummyStruct); + + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + eval "ac_cv_prototype_$tmp_save_1=no" +else + eval "ac_cv_prototype_$tmp_save_1=yes" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +if eval "test \"`echo '$''{'ac_cv_prototype_$tmp_save_1'}'`\" = yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + ac_tr_prototype=HAVE_PROTOTYPE_`echo $tmp_save_1 | tr '[a-z]' '[A-Z]'` + cat >>confdefs.h <<_ACEOF +#define $ac_tr_prototype 1 +_ACEOF + + : +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking prototype for gethostname (in unistd.h libc.h stdlib.h netdb.h)" >&5 +$as_echo_n "checking prototype for gethostname (in unistd.h libc.h stdlib.h netdb.h)... " >&6; } + +: + +ac_includes="" +for ac_header in unistd.h libc.h stdlib.h netdb.h +do + ac_safe=`echo "$ac_header" | sed 'y%./+-%__p_%'` + if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'}'`\" = yes"; then + ac_includes="$ac_includes +#include<$ac_header>" + fi +done +tmp_save_1=`echo gethostname | tr ' :' '__'` +if eval \${ac_cv_prototype_$tmp_save_1+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __cplusplus +extern "C" { +#endif +$ac_includes +#ifdef __cplusplus +} +#endif +typedef union { int member; } dummyStruct; +#ifdef __cplusplus +extern "C" +#endif +dummyStruct gethostname(dummyStruct); + + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + eval "ac_cv_prototype_$tmp_save_1=no" +else + eval "ac_cv_prototype_$tmp_save_1=yes" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +if eval "test \"`echo '$''{'ac_cv_prototype_$tmp_save_1'}'`\" = yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + ac_tr_prototype=HAVE_PROTOTYPE_`echo $tmp_save_1 | tr '[a-z]' '[A-Z]'` + cat >>confdefs.h <<_ACEOF +#define $ac_tr_prototype 1 +_ACEOF + + : +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking prototype for getsockname (in sys/types.h sys/socket.h)" >&5 +$as_echo_n "checking prototype for getsockname (in sys/types.h sys/socket.h)... " >&6; } + +: + +ac_includes="" +for ac_header in sys/types.h sys/socket.h +do + ac_safe=`echo "$ac_header" | sed 'y%./+-%__p_%'` + if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'}'`\" = yes"; then + ac_includes="$ac_includes +#include<$ac_header>" + fi +done +tmp_save_1=`echo getsockname | tr ' :' '__'` +if eval \${ac_cv_prototype_$tmp_save_1+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __cplusplus +extern "C" { +#endif +$ac_includes +#ifdef __cplusplus +} +#endif +typedef union { int member; } dummyStruct; +#ifdef __cplusplus +extern "C" +#endif +dummyStruct getsockname(dummyStruct); + + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + eval "ac_cv_prototype_$tmp_save_1=no" +else + eval "ac_cv_prototype_$tmp_save_1=yes" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +if eval "test \"`echo '$''{'ac_cv_prototype_$tmp_save_1'}'`\" = yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + ac_tr_prototype=HAVE_PROTOTYPE_`echo $tmp_save_1 | tr '[a-z]' '[A-Z]'` + cat >>confdefs.h <<_ACEOF +#define $ac_tr_prototype 1 +_ACEOF + + : +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking prototype for getsockopt (in sys/types.h sys/socket.h)" >&5 +$as_echo_n "checking prototype for getsockopt (in sys/types.h sys/socket.h)... " >&6; } + +: + +ac_includes="" +for ac_header in sys/types.h sys/socket.h +do + ac_safe=`echo "$ac_header" | sed 'y%./+-%__p_%'` + if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'}'`\" = yes"; then + ac_includes="$ac_includes +#include<$ac_header>" + fi +done +tmp_save_1=`echo getsockopt | tr ' :' '__'` +if eval \${ac_cv_prototype_$tmp_save_1+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __cplusplus +extern "C" { +#endif +$ac_includes +#ifdef __cplusplus +} +#endif +typedef union { int member; } dummyStruct; +#ifdef __cplusplus +extern "C" +#endif +dummyStruct getsockopt(dummyStruct); + + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + eval "ac_cv_prototype_$tmp_save_1=no" +else + eval "ac_cv_prototype_$tmp_save_1=yes" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +if eval "test \"`echo '$''{'ac_cv_prototype_$tmp_save_1'}'`\" = yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + ac_tr_prototype=HAVE_PROTOTYPE_`echo $tmp_save_1 | tr '[a-z]' '[A-Z]'` + cat >>confdefs.h <<_ACEOF +#define $ac_tr_prototype 1 +_ACEOF + + : +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking prototype for strerror_r (in string.h)" >&5 +$as_echo_n "checking prototype for strerror_r (in string.h)... " >&6; } + +: + +ac_includes="" +for ac_header in string.h +do + ac_safe=`echo "$ac_header" | sed 'y%./+-%__p_%'` + if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'}'`\" = yes"; then + ac_includes="$ac_includes +#include<$ac_header>" + fi +done +tmp_save_1=`echo strerror_r | tr ' :' '__'` +if eval \${ac_cv_prototype_$tmp_save_1+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __cplusplus +extern "C" { +#endif +$ac_includes +#ifdef __cplusplus +} +#endif +typedef union { int member; } dummyStruct; +#ifdef __cplusplus +extern "C" +#endif +dummyStruct strerror_r(dummyStruct); + + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + eval "ac_cv_prototype_$tmp_save_1=no" +else + eval "ac_cv_prototype_$tmp_save_1=yes" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +if eval "test \"`echo '$''{'ac_cv_prototype_$tmp_save_1'}'`\" = yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + ac_tr_prototype=HAVE_PROTOTYPE_`echo $tmp_save_1 | tr '[a-z]' '[A-Z]'` + cat >>confdefs.h <<_ACEOF +#define $ac_tr_prototype 1 +_ACEOF + + : +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + +if test $ac_cv_prototype_strerror_r = yes ; then +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if strerror_r() returns a char * (in string.h)" >&5 +$as_echo_n "checking if strerror_r() returns a char * (in string.h)... " >&6; } + +ac_includes="" +for ac_header in string.h +do + ac_includes="$ac_includes +#include<$ac_header>" +done +if ${ac_cv_prototype_charp_strerror_r+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __cplusplus +extern "C" { +#endif +$ac_includes +#ifdef __cplusplus +} +#endif + + +int +main () +{ + + char *buf = 0; + int i = strerror_r(0, buf, 100) + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + eval "ac_cv_prototype_charp_strerror_r=no" +else + eval "ac_cv_prototype_charp_strerror_r=yes" + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi + +if eval "test \"`echo $ac_cv_prototype_charp_strerror_r`\" = yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + ac_tr_prototype=HAVE_CHARP_STRERROR_R + cat >>confdefs.h <<_ACEOF +#define $ac_tr_prototype 1 +_ACEOF + + : +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +fi + +fi +if test $ac_cv_prototype_getsockopt = yes ; then +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if getsockopt() needs int* parameters (in sys/types.h sys/socket.h)" >&5 +$as_echo_n "checking if getsockopt() needs int* parameters (in sys/types.h sys/socket.h)... " >&6; } + +ac_includes="" +for ac_header in sys/types.h sys/socket.h +do + ac_includes="$ac_includes +#include<$ac_header>" +done +if ${ac_cv_prototype_intp_getsockopt+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __cplusplus +extern "C" { +#endif +$ac_includes +#ifdef __cplusplus +} +#endif + + +int +main () +{ + + int i; + size_t optlen; + i = getsockopt(0, 0, 0, 0, &optlen); + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + eval "ac_cv_prototype_intp_getsockopt=no" +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __cplusplus +extern "C" { +#endif +$ac_includes +#ifdef __cplusplus +} +#endif + + +int +main () +{ + + int i; + int optlen; + i = getsockopt(0, 0, 0, 0, &optlen); + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + eval "ac_cv_prototype_intp_getsockopt=yes" +else + eval "ac_cv_prototype_intp_getsockopt=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi + +if eval "test \"`echo $ac_cv_prototype_intp_getsockopt`\" = yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + ac_tr_prototype=HAVE_INTP_GETSOCKOPT + cat >>confdefs.h <<_ACEOF +#define $ac_tr_prototype 1 +_ACEOF + + : +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking prototype for gettimeofday (in sys/time.h unistd.h)" >&5 +$as_echo_n "checking prototype for gettimeofday (in sys/time.h unistd.h)... " >&6; } + +: + +ac_includes="" +for ac_header in sys/time.h unistd.h +do + ac_safe=`echo "$ac_header" | sed 'y%./+-%__p_%'` + if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'}'`\" = yes"; then + ac_includes="$ac_includes +#include<$ac_header>" + fi +done +tmp_save_1=`echo gettimeofday | tr ' :' '__'` +if eval \${ac_cv_prototype_$tmp_save_1+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __cplusplus +extern "C" { +#endif +$ac_includes +#ifdef __cplusplus +} +#endif +typedef union { int member; } dummyStruct; +#ifdef __cplusplus +extern "C" +#endif +dummyStruct gettimeofday(dummyStruct); + + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + eval "ac_cv_prototype_$tmp_save_1=no" +else + eval "ac_cv_prototype_$tmp_save_1=yes" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +if eval "test \"`echo '$''{'ac_cv_prototype_$tmp_save_1'}'`\" = yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + ac_tr_prototype=HAVE_PROTOTYPE_`echo $tmp_save_1 | tr '[a-z]' '[A-Z]'` + cat >>confdefs.h <<_ACEOF +#define $ac_tr_prototype 1 +_ACEOF + + : +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking prototype for listen (in sys/types.h sys/socket.h)" >&5 +$as_echo_n "checking prototype for listen (in sys/types.h sys/socket.h)... " >&6; } + +: + +ac_includes="" +for ac_header in sys/types.h sys/socket.h +do + ac_safe=`echo "$ac_header" | sed 'y%./+-%__p_%'` + if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'}'`\" = yes"; then + ac_includes="$ac_includes +#include<$ac_header>" + fi +done +tmp_save_1=`echo listen | tr ' :' '__'` +if eval \${ac_cv_prototype_$tmp_save_1+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __cplusplus +extern "C" { +#endif +$ac_includes +#ifdef __cplusplus +} +#endif +typedef union { int member; } dummyStruct; +#ifdef __cplusplus +extern "C" +#endif +dummyStruct listen(dummyStruct); + + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + eval "ac_cv_prototype_$tmp_save_1=no" +else + eval "ac_cv_prototype_$tmp_save_1=yes" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +if eval "test \"`echo '$''{'ac_cv_prototype_$tmp_save_1'}'`\" = yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + ac_tr_prototype=HAVE_PROTOTYPE_`echo $tmp_save_1 | tr '[a-z]' '[A-Z]'` + cat >>confdefs.h <<_ACEOF +#define $ac_tr_prototype 1 +_ACEOF + + : +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking prototype for mktemp (in libc.h unistd.h stdlib.h)" >&5 +$as_echo_n "checking prototype for mktemp (in libc.h unistd.h stdlib.h)... " >&6; } + +: + +ac_includes="" +for ac_header in libc.h unistd.h stdlib.h +do + ac_safe=`echo "$ac_header" | sed 'y%./+-%__p_%'` + if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'}'`\" = yes"; then + ac_includes="$ac_includes +#include<$ac_header>" + fi +done +tmp_save_1=`echo mktemp | tr ' :' '__'` +if eval \${ac_cv_prototype_$tmp_save_1+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __cplusplus +extern "C" { +#endif +$ac_includes +#ifdef __cplusplus +} +#endif +typedef union { int member; } dummyStruct; +#ifdef __cplusplus +extern "C" +#endif +dummyStruct mktemp(dummyStruct); + + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + eval "ac_cv_prototype_$tmp_save_1=no" +else + eval "ac_cv_prototype_$tmp_save_1=yes" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +if eval "test \"`echo '$''{'ac_cv_prototype_$tmp_save_1'}'`\" = yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + ac_tr_prototype=HAVE_PROTOTYPE_`echo $tmp_save_1 | tr '[a-z]' '[A-Z]'` + cat >>confdefs.h <<_ACEOF +#define $ac_tr_prototype 1 +_ACEOF + + : +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking prototype for mkstemp (in libc.h unistd.h stdlib.h)" >&5 +$as_echo_n "checking prototype for mkstemp (in libc.h unistd.h stdlib.h)... " >&6; } + +: + +ac_includes="" +for ac_header in libc.h unistd.h stdlib.h +do + ac_safe=`echo "$ac_header" | sed 'y%./+-%__p_%'` + if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'}'`\" = yes"; then + ac_includes="$ac_includes +#include<$ac_header>" + fi +done +tmp_save_1=`echo mkstemp | tr ' :' '__'` +if eval \${ac_cv_prototype_$tmp_save_1+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __cplusplus +extern "C" { +#endif +$ac_includes +#ifdef __cplusplus +} +#endif +typedef union { int member; } dummyStruct; +#ifdef __cplusplus +extern "C" +#endif +dummyStruct mkstemp(dummyStruct); + + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + eval "ac_cv_prototype_$tmp_save_1=no" +else + eval "ac_cv_prototype_$tmp_save_1=yes" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +if eval "test \"`echo '$''{'ac_cv_prototype_$tmp_save_1'}'`\" = yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + ac_tr_prototype=HAVE_PROTOTYPE_`echo $tmp_save_1 | tr '[a-z]' '[A-Z]'` + cat >>confdefs.h <<_ACEOF +#define $ac_tr_prototype 1 +_ACEOF + + : +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking prototype for select (in sys/select.h sys/types.h sys/socket.h sys/time.h)" >&5 +$as_echo_n "checking prototype for select (in sys/select.h sys/types.h sys/socket.h sys/time.h)... " >&6; } + +: + +ac_includes="" +for ac_header in sys/select.h sys/types.h sys/socket.h sys/time.h +do + ac_safe=`echo "$ac_header" | sed 'y%./+-%__p_%'` + if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'}'`\" = yes"; then + ac_includes="$ac_includes +#include<$ac_header>" + fi +done +tmp_save_1=`echo select | tr ' :' '__'` +if eval \${ac_cv_prototype_$tmp_save_1+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __cplusplus +extern "C" { +#endif +$ac_includes +#ifdef __cplusplus +} +#endif +typedef union { int member; } dummyStruct; +#ifdef __cplusplus +extern "C" +#endif +dummyStruct select(dummyStruct); + + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + eval "ac_cv_prototype_$tmp_save_1=no" +else + eval "ac_cv_prototype_$tmp_save_1=yes" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +if eval "test \"`echo '$''{'ac_cv_prototype_$tmp_save_1'}'`\" = yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + ac_tr_prototype=HAVE_PROTOTYPE_`echo $tmp_save_1 | tr '[a-z]' '[A-Z]'` + cat >>confdefs.h <<_ACEOF +#define $ac_tr_prototype 1 +_ACEOF + + : +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + +if test $ac_cv_prototype_select = yes ; then +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if select() needs int* parameters (in sys/select.h sys/types.h sys/socket.h sys/time.h)" >&5 +$as_echo_n "checking if select() needs int* parameters (in sys/select.h sys/types.h sys/socket.h sys/time.h)... " >&6; } + +ac_includes="" +for ac_header in sys/select.h sys/types.h sys/socket.h sys/time.h +do + ac_safe=`echo "$ac_header" | sed 'y%./+-%__p_%'` + if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'}'`\" = yes"; then + ac_includes="$ac_includes +#include<$ac_header>" + fi +done +if ${ac_cv_prototype_intp_select+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __cplusplus +extern "C" { +#endif +$ac_includes +#ifdef __cplusplus +} +#endif + + +int +main () +{ + + int i; + fd_set fds; + i = select(1, &fds, &fds, &fds, NULL); + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + eval "ac_cv_prototype_intp_select=no" +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __cplusplus +extern "C" { +#endif +$ac_includes +#ifdef __cplusplus +} +#endif + + +int +main () +{ + + int i; + int fds; + i = select(1, &fds, &fds, &fds, NULL); + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + eval "ac_cv_prototype_intp_select=yes" +else + eval "ac_cv_prototype_intp_select=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi + +if eval "test \"`echo $ac_cv_prototype_intp_select`\" = yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + ac_tr_prototype=HAVE_INTP_SELECT + cat >>confdefs.h <<_ACEOF +#define $ac_tr_prototype 1 +_ACEOF + + : +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking prototype for setsockopt (in sys/types.h sys/socket.h)" >&5 +$as_echo_n "checking prototype for setsockopt (in sys/types.h sys/socket.h)... " >&6; } + +: + +ac_includes="" +for ac_header in sys/types.h sys/socket.h +do + ac_safe=`echo "$ac_header" | sed 'y%./+-%__p_%'` + if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'}'`\" = yes"; then + ac_includes="$ac_includes +#include<$ac_header>" + fi +done +tmp_save_1=`echo setsockopt | tr ' :' '__'` +if eval \${ac_cv_prototype_$tmp_save_1+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __cplusplus +extern "C" { +#endif +$ac_includes +#ifdef __cplusplus +} +#endif +typedef union { int member; } dummyStruct; +#ifdef __cplusplus +extern "C" +#endif +dummyStruct setsockopt(dummyStruct); + + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + eval "ac_cv_prototype_$tmp_save_1=no" +else + eval "ac_cv_prototype_$tmp_save_1=yes" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +if eval "test \"`echo '$''{'ac_cv_prototype_$tmp_save_1'}'`\" = yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + ac_tr_prototype=HAVE_PROTOTYPE_`echo $tmp_save_1 | tr '[a-z]' '[A-Z]'` + cat >>confdefs.h <<_ACEOF +#define $ac_tr_prototype 1 +_ACEOF + + : +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking prototype for socket (in sys/types.h sys/socket.h)" >&5 +$as_echo_n "checking prototype for socket (in sys/types.h sys/socket.h)... " >&6; } + +: + +ac_includes="" +for ac_header in sys/types.h sys/socket.h +do + ac_safe=`echo "$ac_header" | sed 'y%./+-%__p_%'` + if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'}'`\" = yes"; then + ac_includes="$ac_includes +#include<$ac_header>" + fi +done +tmp_save_1=`echo socket | tr ' :' '__'` +if eval \${ac_cv_prototype_$tmp_save_1+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __cplusplus +extern "C" { +#endif +$ac_includes +#ifdef __cplusplus +} +#endif +typedef union { int member; } dummyStruct; +#ifdef __cplusplus +extern "C" +#endif +dummyStruct socket(dummyStruct); + + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + eval "ac_cv_prototype_$tmp_save_1=no" +else + eval "ac_cv_prototype_$tmp_save_1=yes" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +if eval "test \"`echo '$''{'ac_cv_prototype_$tmp_save_1'}'`\" = yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + ac_tr_prototype=HAVE_PROTOTYPE_`echo $tmp_save_1 | tr '[a-z]' '[A-Z]'` + cat >>confdefs.h <<_ACEOF +#define $ac_tr_prototype 1 +_ACEOF + + : +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking prototype for strcasecmp (in string.h)" >&5 +$as_echo_n "checking prototype for strcasecmp (in string.h)... " >&6; } + +: + +ac_includes="" +for ac_header in string.h +do + ac_safe=`echo "$ac_header" | sed 'y%./+-%__p_%'` + if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'}'`\" = yes"; then + ac_includes="$ac_includes +#include<$ac_header>" + fi +done +tmp_save_1=`echo strcasecmp | tr ' :' '__'` +if eval \${ac_cv_prototype_$tmp_save_1+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __cplusplus +extern "C" { +#endif +$ac_includes +#ifdef __cplusplus +} +#endif +typedef union { int member; } dummyStruct; +#ifdef __cplusplus +extern "C" +#endif +dummyStruct strcasecmp(dummyStruct); + + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + eval "ac_cv_prototype_$tmp_save_1=no" +else + eval "ac_cv_prototype_$tmp_save_1=yes" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +if eval "test \"`echo '$''{'ac_cv_prototype_$tmp_save_1'}'`\" = yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + ac_tr_prototype=HAVE_PROTOTYPE_`echo $tmp_save_1 | tr '[a-z]' '[A-Z]'` + cat >>confdefs.h <<_ACEOF +#define $ac_tr_prototype 1 +_ACEOF + + : +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking prototype for strncasecmp (in string.h)" >&5 +$as_echo_n "checking prototype for strncasecmp (in string.h)... " >&6; } + +: + +ac_includes="" +for ac_header in string.h +do + ac_safe=`echo "$ac_header" | sed 'y%./+-%__p_%'` + if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'}'`\" = yes"; then + ac_includes="$ac_includes +#include<$ac_header>" + fi +done +tmp_save_1=`echo strncasecmp | tr ' :' '__'` +if eval \${ac_cv_prototype_$tmp_save_1+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __cplusplus +extern "C" { +#endif +$ac_includes +#ifdef __cplusplus +} +#endif +typedef union { int member; } dummyStruct; +#ifdef __cplusplus +extern "C" +#endif +dummyStruct strncasecmp(dummyStruct); + + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + eval "ac_cv_prototype_$tmp_save_1=no" +else + eval "ac_cv_prototype_$tmp_save_1=yes" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +if eval "test \"`echo '$''{'ac_cv_prototype_$tmp_save_1'}'`\" = yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + ac_tr_prototype=HAVE_PROTOTYPE_`echo $tmp_save_1 | tr '[a-z]' '[A-Z]'` + cat >>confdefs.h <<_ACEOF +#define $ac_tr_prototype 1 +_ACEOF + + : +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking prototype for usleep (in libc.h unistd.h stdlib.h)" >&5 +$as_echo_n "checking prototype for usleep (in libc.h unistd.h stdlib.h)... " >&6; } + +: + +ac_includes="" +for ac_header in libc.h unistd.h stdlib.h +do + ac_safe=`echo "$ac_header" | sed 'y%./+-%__p_%'` + if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'}'`\" = yes"; then + ac_includes="$ac_includes +#include<$ac_header>" + fi +done +tmp_save_1=`echo usleep | tr ' :' '__'` +if eval \${ac_cv_prototype_$tmp_save_1+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __cplusplus +extern "C" { +#endif +$ac_includes +#ifdef __cplusplus +} +#endif +typedef union { int member; } dummyStruct; +#ifdef __cplusplus +extern "C" +#endif +dummyStruct usleep(dummyStruct); + + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + eval "ac_cv_prototype_$tmp_save_1=no" +else + eval "ac_cv_prototype_$tmp_save_1=yes" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +if eval "test \"`echo '$''{'ac_cv_prototype_$tmp_save_1'}'`\" = yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + ac_tr_prototype=HAVE_PROTOTYPE_`echo $tmp_save_1 | tr '[a-z]' '[A-Z]'` + cat >>confdefs.h <<_ACEOF +#define $ac_tr_prototype 1 +_ACEOF + + : +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking prototype for vsnprintf (in stdio.h stdarg.h)" >&5 +$as_echo_n "checking prototype for vsnprintf (in stdio.h stdarg.h)... " >&6; } + +: + +ac_includes="" +for ac_header in stdio.h stdarg.h +do + ac_safe=`echo "$ac_header" | sed 'y%./+-%__p_%'` + if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'}'`\" = yes"; then + ac_includes="$ac_includes +#include<$ac_header>" + fi +done +tmp_save_1=`echo vsnprintf | tr ' :' '__'` +if eval \${ac_cv_prototype_$tmp_save_1+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __cplusplus +extern "C" { +#endif +$ac_includes +#ifdef __cplusplus +} +#endif +typedef union { int member; } dummyStruct; +#ifdef __cplusplus +extern "C" +#endif +dummyStruct vsnprintf(dummyStruct); + + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + eval "ac_cv_prototype_$tmp_save_1=no" +else + eval "ac_cv_prototype_$tmp_save_1=yes" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +if eval "test \"`echo '$''{'ac_cv_prototype_$tmp_save_1'}'`\" = yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + ac_tr_prototype=HAVE_PROTOTYPE_`echo $tmp_save_1 | tr '[a-z]' '[A-Z]'` + cat >>confdefs.h <<_ACEOF +#define $ac_tr_prototype 1 +_ACEOF + + : +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking prototype for wait3 (in libc.h sys/wait.h sys/time.h sys/resource.h)" >&5 +$as_echo_n "checking prototype for wait3 (in libc.h sys/wait.h sys/time.h sys/resource.h)... " >&6; } + +: + +ac_includes="" +for ac_header in libc.h sys/wait.h sys/time.h sys/resource.h +do + ac_safe=`echo "$ac_header" | sed 'y%./+-%__p_%'` + if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'}'`\" = yes"; then + ac_includes="$ac_includes +#include<$ac_header>" + fi +done +tmp_save_1=`echo wait3 | tr ' :' '__'` +if eval \${ac_cv_prototype_$tmp_save_1+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __cplusplus +extern "C" { +#endif +$ac_includes +#ifdef __cplusplus +} +#endif +typedef union { int member; } dummyStruct; +#ifdef __cplusplus +extern "C" +#endif +dummyStruct wait3(dummyStruct); + + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + eval "ac_cv_prototype_$tmp_save_1=no" +else + eval "ac_cv_prototype_$tmp_save_1=yes" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +if eval "test \"`echo '$''{'ac_cv_prototype_$tmp_save_1'}'`\" = yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + ac_tr_prototype=HAVE_PROTOTYPE_`echo $tmp_save_1 | tr '[a-z]' '[A-Z]'` + cat >>confdefs.h <<_ACEOF +#define $ac_tr_prototype 1 +_ACEOF + + : +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking prototype for waitpid (in sys/wait.h sys/time.h sys/resource.h)" >&5 +$as_echo_n "checking prototype for waitpid (in sys/wait.h sys/time.h sys/resource.h)... " >&6; } + +: + +ac_includes="" +for ac_header in sys/wait.h sys/time.h sys/resource.h +do + ac_safe=`echo "$ac_header" | sed 'y%./+-%__p_%'` + if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'}'`\" = yes"; then + ac_includes="$ac_includes +#include<$ac_header>" + fi +done +tmp_save_1=`echo waitpid | tr ' :' '__'` +if eval \${ac_cv_prototype_$tmp_save_1+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __cplusplus +extern "C" { +#endif +$ac_includes +#ifdef __cplusplus +} +#endif +typedef union { int member; } dummyStruct; +#ifdef __cplusplus +extern "C" +#endif +dummyStruct waitpid(dummyStruct); + + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + eval "ac_cv_prototype_$tmp_save_1=no" +else + eval "ac_cv_prototype_$tmp_save_1=yes" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +if eval "test \"`echo '$''{'ac_cv_prototype_$tmp_save_1'}'`\" = yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + ac_tr_prototype=HAVE_PROTOTYPE_`echo $tmp_save_1 | tr '[a-z]' '[A-Z]'` + cat >>confdefs.h <<_ACEOF +#define $ac_tr_prototype 1 +_ACEOF + + : +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking declaration for struct utimbuf (in sys/types.h utime.h sys/utime.h)" >&5 +$as_echo_n "checking declaration for struct utimbuf (in sys/types.h utime.h sys/utime.h)... " >&6; } + +ac_includes="" +for ac_header in sys/types.h utime.h sys/utime.h +do + ac_safe=`echo "$ac_header" | sed 'y%./+-%__p_%'` + if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'}'`\" = yes"; then + ac_includes="$ac_includes +#include<$ac_header>" + fi +done + +ac_cpp_includes="" + +ac_cv_declaration=`echo 'ac_cv_declaration_struct utimbuf' | tr ' :' '__'` + +if eval \${$ac_cv_declaration+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __cplusplus +extern "C" { +#endif +$ac_includes +#ifdef __cplusplus +} +#endif +$ac_cpp_includes +struct utimbuf dummy; + + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + eval "$ac_cv_declaration=yes" +else + eval "$ac_cv_declaration=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +if eval "test \"\$$ac_cv_declaration\" = yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + ac_tr_declaration=HAVE_DECLARATION_`echo struct utimbuf | tr ' :[a-z]' '__[A-Z]'` + cat >>confdefs.h <<_ACEOF +#define $ac_tr_declaration 1 +_ACEOF + + : +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +unset ac_cv_declaration + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking declaration for socklen_t (in sys/types.h sys/socket.h)" >&5 +$as_echo_n "checking declaration for socklen_t (in sys/types.h sys/socket.h)... " >&6; } + +ac_includes="" +for ac_header in sys/types.h sys/socket.h +do + ac_safe=`echo "$ac_header" | sed 'y%./+-%__p_%'` + if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'}'`\" = yes"; then + ac_includes="$ac_includes +#include<$ac_header>" + fi +done + +ac_cpp_includes="" + +ac_cv_declaration=`echo 'ac_cv_declaration_socklen_t' | tr ' :' '__'` + +if eval \${$ac_cv_declaration+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __cplusplus +extern "C" { +#endif +$ac_includes +#ifdef __cplusplus +} +#endif +$ac_cpp_includes +socklen_t dummy; + + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + eval "$ac_cv_declaration=yes" +else + eval "$ac_cv_declaration=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +if eval "test \"\$$ac_cv_declaration\" = yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + ac_tr_declaration=HAVE_DECLARATION_`echo socklen_t | tr ' :[a-z]' '__[A-Z]'` + cat >>confdefs.h <<_ACEOF +#define $ac_tr_declaration 1 +_ACEOF + + : +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +unset ac_cv_declaration + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if declaration of readdir_r conforms to Posix 1.c draft 6" >&5 +$as_echo_n "checking if declaration of readdir_r conforms to Posix 1.c draft 6... " >&6; } + +ac_cv_result=ac_cv_old_readdir_r +if eval \${$ac_cv_result+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#ifdef __cplusplus +extern "C" { +#endif +#ifdef HAVE_DIRENT_H +#include +#else +#define dirent direct +#ifdef HAVE_SYS_NDIR_H +#include +#endif +#ifdef HAVE_SYS_DIR_H +#include +#endif +#ifdef HAVE_NDIR_H +#include +#endif +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ + + DIR *dirp; + struct dirent *dp; + dp = readdir_r(dirp, dp); + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + eval "$ac_cv_result=yes" +else + eval "$ac_cv_result=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +if eval "test \"\$$ac_cv_result\" = yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + ac_cv_result=HAVE_OLD_READDIR_R + cat >>confdefs.h <<_ACEOF +#define $ac_cv_result 1 +_ACEOF + + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + fi +unset ac_cv_result + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if signal() callback needs ellipse (in signal.h)" >&5 +$as_echo_n "checking if signal() callback needs ellipse (in signal.h)... " >&6; } + +ac_includes="" +for ac_header in signal.h +do + ac_includes="$ac_includes +#include<$ac_header>" +done +if ${ac_cv_signal_handler_with_ellipse+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __cplusplus +extern "C" { +#endif +$ac_includes + + void signal_handler(int) + { + } +#ifdef __cplusplus +} +#endif + + +int +main () +{ + + (void) signal(0, signal_handler); + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + eval "ac_cv_signal_handler_with_ellipse=no" +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __cplusplus +extern "C" { +#endif +$ac_includes + + void signal_handler(...) + { + } +#ifdef __cplusplus +} +#endif + + +int +main () +{ + + (void) signal(0, signal_handler); + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + eval "ac_cv_signal_handler_with_ellipse=yes" +else + eval "ac_cv_signal_handler_with_ellipse=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi + +if eval "test \"`echo $ac_cv_signal_handler_with_ellipse`\" = yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + ac_tr_prototype=SIGNAL_HANDLER_WITH_ELLIPSE + cat >>confdefs.h <<_ACEOF +#define $ac_tr_prototype 1 +_ACEOF + + : +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +fi + +if test $ac_cv_header_math_h = yes ; then +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if fails if included extern \"C\"" >&5 +$as_echo_n "checking if fails if included extern \"C\"... " >&6; } + +if ${ac_cv_include_math_h_as_cxx+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +extern "C" +{ +#include +} + +int +main () +{ + + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + eval "ac_cv_include_math_h_as_cxx=no" +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include + +int +main () +{ + + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + eval "ac_cv_include_math_h_as_cxx=yes" +else + eval "ac_cv_include_math_h_as_cxx=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi + +if eval "test \"`echo $ac_cv_include_math_h_as_cxx`\" = yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + ac_tr_prototype=INCLUDE_MATH_H_AS_CXX + cat >>confdefs.h <<_ACEOF +#define $ac_tr_prototype 1 +_ACEOF + + : +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +fi + +fi + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to use C++ standard includes" >&5 +$as_echo_n "checking whether to use C++ standard includes... " >&6; } +ac_use_std_includes="auto" +# Check whether --enable-std-includes was given. +if test "${enable_std_includes+set}" = set; then : + enableval=$enable_std_includes; case "$enableval" in + yes) + ac_use_std_includes="yes" + ;; + + *) + ac_use_std_includes="no" + ;; + esac + +fi + + +if test "$ac_cv_header_fstream" = "yes" -a "$ac_cv_header_iostream" = "yes" -a "$ac_cv_header_iomanip" = "yes"; then + ac_have_std_includes="yes" +else + ac_have_std_includes="no" +fi + +if test "$ac_cv_header_fstream_h" = "yes" -a "$ac_cv_header_iostream_h" = "yes" -a "$ac_cv_header_iomanip_h" = "yes"; then + ac_have_old_includes="yes" +else + ac_have_old_includes="no" +fi + +if test "$ac_use_std_includes" = "yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +$as_echo "#define USE_STD_CXX_INCLUDES /**/" >>confdefs.h + +elif test "$ac_use_std_includes" = "no"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +elif test "$ac_have_std_includes" = "yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +$as_echo "#define USE_STD_CXX_INCLUDES /**/" >>confdefs.h + + ac_use_std_includes="yes" +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + ac_use_std_includes="no" +fi + +if test "$ac_use_std_includes" = "yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for C++ standard namespace" >&5 +$as_echo_n "checking for C++ standard namespace... " >&6; } + +if ${ac_cv_check_std_namespace+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_link_o='${CXX-g++} -o conftest $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.o $LIBS 1>&5' +cat > conftest.$ac_ext < +using namespace std; + +int main() { + + cout << "Hello World" << endl; + +; return 0; } +EOF +if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link_o\""; } >&5 + (eval $ac_link_o) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + rm -rf conftest* + eval "ac_cv_check_std_namespace=yes" + else + echo "configure: failed link was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_check_std_namespace=no" + fi +else + echo "configure: failed compile was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_check_std_namespace=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_check_std_namespace'`\" = yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + ac_tr_std_namespace=HAVE_STD_NAMESPACE + cat >>confdefs.h <<_ACEOF +#define $ac_tr_std_namespace 1 +_ACEOF + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking declaration for std::ios_base::openmode (in iostream)" >&5 +$as_echo_n "checking declaration for std::ios_base::openmode (in iostream)... " >&6; } + +ac_includes="" + +ac_cpp_includes="" +for ac_header in iostream +do + ac_safe=`echo "$ac_header" | sed 'y%./+-%__p_%'` + if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'}'`\" = yes"; then + ac_cpp_includes="$ac_cpp_includes +#include<$ac_header>" + fi +done + +ac_cv_declaration=`echo 'ac_cv_declaration_std::ios_base::openmode' | tr ' :' '__'` + +if eval \${$ac_cv_declaration+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __cplusplus +extern "C" { +#endif +$ac_includes +#ifdef __cplusplus +} +#endif +$ac_cpp_includes +std::ios_base::openmode dummy; + + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + eval "$ac_cv_declaration=yes" +else + eval "$ac_cv_declaration=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +if eval "test \"\$$ac_cv_declaration\" = yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + ac_tr_declaration=HAVE_DECLARATION_`echo std::ios_base::openmode | tr ' :[a-z]' '__[A-Z]'` + cat >>confdefs.h <<_ACEOF +#define $ac_tr_declaration 1 +_ACEOF + + : +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +unset ac_cv_declaration + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking declaration of ios::nocreate (in fstream)" >&5 +$as_echo_n "checking declaration of ios::nocreate (in fstream)... " >&6; } + +ac_cv_declaration=ac_cv_declaration_ios_nocreate +if eval \${$ac_cv_declaration+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include + +int +main () +{ +namespace std { } +using namespace std; +ifstream file("name", std::ios::nocreate) + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + eval "$ac_cv_declaration=yes" +else + eval "$ac_cv_declaration=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +if eval "test \"\$$ac_cv_declaration\" = yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + ac_tr_declaration=HAVE_IOS_NOCREATE + cat >>confdefs.h <<_ACEOF +#define $ac_tr_declaration 1 +_ACEOF + + : +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +unset ac_cv_declaration + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for std::vfprintf (in cstdarg cstdio)" >&5 +$as_echo_n "checking for std::vfprintf (in cstdarg cstdio)... " >&6; } + +ac_includes="" +for ac_header in cstdarg cstdio +do + ac_safe=`echo "$ac_header" | sed 'y%./+-%__p_%'` + if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'}'`\" = yes"; then + ac_includes="$ac_includes +#include<$ac_header>" + fi +done +tmp_save_1=`echo std::vfprintf | tr ' :' '__'` +if eval \${ac_cv_compiles_$tmp_save_1+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$ac_includes +int +main () +{ +FILE *stream; va_list ap; std::vfprintf(stream, "", ap); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + eval "ac_cv_compiles_$tmp_save_1=yes" +else + eval "ac_cv_compiles_$tmp_save_1=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +if eval "test \"`echo '$''{'ac_cv_compiles_$tmp_save_1'}'`\" = yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + ac_tr_prototype=HAVE_PROTOTYPE_`echo $tmp_save_1 | tr '[a-z]' '[A-Z]'` + cat >>confdefs.h <<_ACEOF +#define $ac_tr_prototype 1 +_ACEOF + + : +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for std::vsnprintf (in cstdarg cstdio)" >&5 +$as_echo_n "checking for std::vsnprintf (in cstdarg cstdio)... " >&6; } + +ac_includes="" +for ac_header in cstdarg cstdio +do + ac_safe=`echo "$ac_header" | sed 'y%./+-%__p_%'` + if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'}'`\" = yes"; then + ac_includes="$ac_includes +#include<$ac_header>" + fi +done +tmp_save_1=`echo std::vsnprintf | tr ' :' '__'` +if eval \${ac_cv_compiles_$tmp_save_1+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$ac_includes +int +main () +{ +char buf[256]; va_list ap; std::vsnprintf(buf, 0, "", ap); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + eval "ac_cv_compiles_$tmp_save_1=yes" +else + eval "ac_cv_compiles_$tmp_save_1=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +if eval "test \"`echo '$''{'ac_cv_compiles_$tmp_save_1'}'`\" = yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + ac_tr_prototype=HAVE_PROTOTYPE_`echo $tmp_save_1 | tr '[a-z]' '[A-Z]'` + cat >>confdefs.h <<_ACEOF +#define $ac_tr_prototype 1 +_ACEOF + + : +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + +else + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking declaration for std::ios_base::openmode (in iostream.h)" >&5 +$as_echo_n "checking declaration for std::ios_base::openmode (in iostream.h)... " >&6; } + +ac_includes="" + +ac_cpp_includes="" +for ac_header in iostream.h +do + ac_safe=`echo "$ac_header" | sed 'y%./+-%__p_%'` + if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'}'`\" = yes"; then + ac_cpp_includes="$ac_cpp_includes +#include<$ac_header>" + fi +done + +ac_cv_declaration=`echo 'ac_cv_declaration_std::ios_base::openmode' | tr ' :' '__'` + +if eval \${$ac_cv_declaration+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __cplusplus +extern "C" { +#endif +$ac_includes +#ifdef __cplusplus +} +#endif +$ac_cpp_includes +std::ios_base::openmode dummy; + + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + eval "$ac_cv_declaration=yes" +else + eval "$ac_cv_declaration=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +if eval "test \"\$$ac_cv_declaration\" = yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + ac_tr_declaration=HAVE_DECLARATION_`echo std::ios_base::openmode | tr ' :[a-z]' '__[A-Z]'` + cat >>confdefs.h <<_ACEOF +#define $ac_tr_declaration 1 +_ACEOF + + : +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +unset ac_cv_declaration + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking declaration of ios::nocreate (in fstream.h)" >&5 +$as_echo_n "checking declaration of ios::nocreate (in fstream.h)... " >&6; } + +ac_cv_declaration=ac_cv_declaration_ios_nocreate +if eval \${$ac_cv_declaration+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include + +int +main () +{ +namespace std { } +using namespace std; +ifstream file("name", ios::nocreate) + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + eval "$ac_cv_declaration=yes" +else + eval "$ac_cv_declaration=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +if eval "test \"\$$ac_cv_declaration\" = yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + ac_tr_declaration=HAVE_IOS_NOCREATE + cat >>confdefs.h <<_ACEOF +#define $ac_tr_declaration 1 +_ACEOF + + : +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +unset ac_cv_declaration + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for std::vfprintf (in stdarg.h stdio.h)" >&5 +$as_echo_n "checking for std::vfprintf (in stdarg.h stdio.h)... " >&6; } + +ac_includes="" +for ac_header in stdarg.h stdio.h +do + ac_safe=`echo "$ac_header" | sed 'y%./+-%__p_%'` + if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'}'`\" = yes"; then + ac_includes="$ac_includes +#include<$ac_header>" + fi +done +tmp_save_1=`echo std::vfprintf | tr ' :' '__'` +if eval \${ac_cv_compiles_$tmp_save_1+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$ac_includes +int +main () +{ +FILE *stream; va_list ap; std::vfprintf(stream, "", ap); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + eval "ac_cv_compiles_$tmp_save_1=yes" +else + eval "ac_cv_compiles_$tmp_save_1=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +if eval "test \"`echo '$''{'ac_cv_compiles_$tmp_save_1'}'`\" = yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + ac_tr_prototype=HAVE_PROTOTYPE_`echo $tmp_save_1 | tr '[a-z]' '[A-Z]'` + cat >>confdefs.h <<_ACEOF +#define $ac_tr_prototype 1 +_ACEOF + + : +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for std::vsnprintf (in stdarg.h stdio.h)" >&5 +$as_echo_n "checking for std::vsnprintf (in stdarg.h stdio.h)... " >&6; } + +ac_includes="" +for ac_header in stdarg.h stdio.h +do + ac_safe=`echo "$ac_header" | sed 'y%./+-%__p_%'` + if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'}'`\" = yes"; then + ac_includes="$ac_includes +#include<$ac_header>" + fi +done +tmp_save_1=`echo std::vsnprintf | tr ' :' '__'` +if eval \${ac_cv_compiles_$tmp_save_1+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$ac_includes +int +main () +{ +char buf[256]; va_list ap; std::vsnprintf(buf, 0, "", ap); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + eval "ac_cv_compiles_$tmp_save_1=yes" +else + eval "ac_cv_compiles_$tmp_save_1=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +if eval "test \"`echo '$''{'ac_cv_compiles_$tmp_save_1'}'`\" = yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + ac_tr_prototype=HAVE_PROTOTYPE_`echo $tmp_save_1 | tr '[a-z]' '[A-Z]'` + cat >>confdefs.h <<_ACEOF +#define $ac_tr_prototype 1 +_ACEOF + + : +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C++ class template" >&5 +$as_echo_n "checking for C++ class template... " >&6; } + +if ${ac_cv_check_class_template+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_link_o='${CXX-g++} -o conftest $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.o $LIBS 1>&5' +cat > conftest.$ac_ext < +class x +{ +private: + T a; +public: + void set(T i) { a = i; } + x(T i) { set(i); } + T get() { return a; } +}; + +int main() { + + int i; + x a(4); + i = a.get(); + a.set(18); + i = a.get(); + a.set(i-1); + +; return 0; } +EOF +if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link_o\""; } >&5 + (eval $ac_link_o) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + rm -rf conftest* + eval "ac_cv_check_class_template=yes" + else + echo "configure: failed link was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_check_class_template=no" + fi +else + echo "configure: failed compile was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_check_class_template=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_check_class_template'`\" = yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + ac_tr_class_template=HAVE_CLASS_TEMPLATE + cat >>confdefs.h <<_ACEOF +#define $ac_tr_class_template 1 +_ACEOF + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C++ static methods in class templates" >&5 +$as_echo_n "checking for C++ static methods in class templates... " >&6; } + +if ${ac_cv_check_static_template_method+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_link_o='${CXX-g++} -o conftest $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.o $LIBS 1>&5' +cat > conftest.$ac_ext < +class x +{ +public: + x() { } + static void do1(Function f, int & a) { f(a); } + static void do2(T b) { T a = b; }; +}; + +int main() { + + int a = 1; + x::do1(additive, a); + x::do2(a); + +; return 0; } +EOF +if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link_o\""; } >&5 + (eval $ac_link_o) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + rm -rf conftest* + eval "ac_cv_check_static_template_method=yes" + else + echo "configure: failed link was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_check_static_template_method=no" + fi +else + echo "configure: failed compile was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_check_static_template_method=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_check_static_template_method'`\" = yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + ac_tr_static_template_method=HAVE_STATIC_TEMPLATE_METHOD + cat >>confdefs.h <<_ACEOF +#define $ac_tr_static_template_method 1 +_ACEOF + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C++ function template" >&5 +$as_echo_n "checking for C++ function template... " >&6; } + +if ${ac_cv_check_function_template+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_link_o='${CXX-g++} -o conftest $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.o $LIBS 1>&5' +cat > conftest.$ac_ext < +int f(T* a) +{ + if (a) return 1; + return 0; +} + +int main() { + + int i, a; + i = f(&a); + +; return 0; } +EOF +if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link_o\""; } >&5 + (eval $ac_link_o) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + rm -rf conftest* + eval "ac_cv_check_function_template=yes" + else + echo "configure: failed link was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_check_function_template=no" + fi +else + echo "configure: failed compile was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_check_function_template=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_check_function_template'`\" = yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + ac_tr_function_template=HAVE_FUNCTION_TEMPLATE + cat >>confdefs.h <<_ACEOF +#define $ac_tr_function_template 1 +_ACEOF + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C++ explicit template specialization syntax" >&5 +$as_echo_n "checking for C++ explicit template specialization syntax... " >&6; } + +if ${ac_cv_check_explicit_template_specialization+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +template +class X +{ + public: + int fn(); +}; + +template<> +int X::fn() +{ + return 0; +} + +int +main () +{ +X x + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + eval "ac_cv_check_explicit_template_specialization=yes" +else + eval "ac_cv_check_explicit_template_specialization=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +if eval "test \"`echo '$ac_cv_check_explicit_template_specialization'`\" = yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + ac_tr_explicit_template_specialization=HAVE_EXPLICIT_TEMPLATE_SPECIALIZATION + cat >>confdefs.h <<_ACEOF +#define $ac_tr_explicit_template_specialization 1 +_ACEOF + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if bool is built-in type" >&5 +$as_echo_n "checking if bool is built-in type... " >&6; } + +if ${ac_cv_have_cxx_bool+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + +bool b1 = true; +bool b2 = false; + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + eval "ac_cv_have_cxx_bool=yes" +else + eval "ac_cv_have_cxx_bool=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi + +if eval "test \"`echo $ac_cv_have_cxx_bool`\" = yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + ac_tr_prototype=HAVE_CXX_BOOL + cat >>confdefs.h <<_ACEOF +#define $ac_tr_prototype 1 +_ACEOF + + : +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if volatile is known keyword" >&5 +$as_echo_n "checking if volatile is known keyword... " >&6; } + +if ${ac_cv_have_cxx_volatile+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + +volatile int i=0; + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + eval "ac_cv_have_cxx_volatile=yes" +else + eval "ac_cv_have_cxx_volatile=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi + +if eval "test \"`echo $ac_cv_have_cxx_volatile`\" = yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + ac_tr_prototype=HAVE_CXX_VOLATILE + +cat >>confdefs.h <<_ACEOF +#define $ac_tr_prototype /**/ +_ACEOF + + : +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +fi + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler recognizes typename" >&5 +$as_echo_n "checking whether the compiler recognizes typename... " >&6; } +if ${ac_cv_cxx_typename+:} false; then : + $as_echo_n "(cached) " >&6 +else + + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +templateclass X {public:X(){}}; +int +main () +{ +X z; return 0; + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_cv_cxx_typename=yes +else + ac_cv_cxx_typename=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cxx_typename" >&5 +$as_echo "$ac_cv_cxx_typename" >&6; } +if test "$ac_cv_cxx_typename" = yes; then + +$as_echo "#define HAVE_TYPENAME /**/" >>confdefs.h + +fi + + + ac_cv_stdio_namespace_is_std=no + + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#ifdef USE_STD_CXX_INCLUDES +#include +#else +#include +#endif + +int +main () +{ +FILE *f = ::fopen("name", "r"); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_cv_stdio_namespace_is_std=no +else + ac_cv_stdio_namespace_is_std=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + + if test "$ac_cv_stdio_namespace_is_std" = yes; then + $as_echo "#define STDIO_NAMESPACE std::" >>confdefs.h + + else + $as_echo "#define STDIO_NAMESPACE ::" >>confdefs.h + + fi + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable private tag dictionary" >&5 +$as_echo_n "checking whether to enable private tag dictionary... " >&6; } +# Check whether --enable-private-tags was given. +if test "${enable_private_tags+set}" = set; then : + enableval=$enable_private_tags; case "$enableval" in + yes) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +$as_echo "#define ENABLE_PRIVATE_TAGS /**/" >>confdefs.h + + +cat >>confdefs.h <<_ACEOF +#define DCM_DICT_DEFAULT_PATH "${DATA_DIR}/dicom.dic:${DATA_DIR}/private.dic" +_ACEOF + + ;; + *) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + ;; + esac +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +fi + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable loading external dictionary from default path" >&5 +$as_echo_n "checking whether to enable loading external dictionary from default path... " >&6; } +# Check whether --enable-external-dict was given. +if test "${enable_external_dict+set}" = set; then : + enableval=$enable_external_dict; case "$enableval" in + yes) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +$as_echo "#define ENABLE_EXTERNAL_DICTIONARY /**/" >>confdefs.h + + ;; + *) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +cat >>confdefs.h <<_ACEOF +#define DCM_DICT_DEFAULT_PATH "" +_ACEOF + + ;; + esac +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +$as_echo "#define ENABLE_EXTERNAL_DICTIONARY /**/" >>confdefs.h + + +fi + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable built-in dictionary loading" >&5 +$as_echo_n "checking whether to enable built-in dictionary loading... " >&6; } +# Check whether --enable-builtin-dict was given. +if test "${enable_builtin_dict+set}" = set; then : + enableval=$enable_builtin_dict; case "$enableval" in + yes) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + DCMTK_ENABLE_BUILTIN_DICTIONARY=true + ;; + *) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + ;; + esac +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +fi + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -Wl,-rpath is supported" >&5 +$as_echo_n "checking whether -Wl,-rpath is supported... " >&6; } +if ${dcmtk_cv_rpath_works+:} false; then : + $as_echo_n "(cached) " >&6 +else + # Check whether --enable-rpath was given. +if test "${enable_rpath+set}" = set; then : + enableval=$enable_rpath; dcmtk_cv_rpath_works=$enableval +else + old_LDFLAGS="$LDFLAGS" + LDFLAGS="-Wl,-rpath,$srcdir $LDFLAGS" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + dcmtk_cv_rpath_works=yes +else + dcmtk_cv_rpath_works=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS="$old_LDFLAGS" +fi + + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $dcmtk_cv_rpath_works" >&5 +$as_echo "$dcmtk_cv_rpath_works" >&6; } + + + +# Check whether --with-opensslinc was given. +if test "${with_opensslinc+set}" = set; then : + withval=$with_opensslinc; case $withval in #( + yes|no) : + + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: --with-opensslinc called without argument - will use default" >&5 +$as_echo "$as_me: WARNING: --with-opensslinc called without argument - will use default" >&2;} + ;; #( + *) : + + if test ! -d ${withval}; then + as_fn_error $? "called with --with-opensslinc but OpenSSL base directory ${withval} does not exist or is not a directory." "$LINENO" 5 + fi + + CPPFLAGS="-I${withval}/include $CPPFLAGS" + LDFLAGS="-L${withval}/lib $LDFLAGS" + if test "x$dcmtk_cv_rpath_works" = "xyes"; then + LDFLAGS="-Wl,-rpath,${withval}/lib $LDFLAGS" + fi + ;; +esac + +fi + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to include OpenSSL support" >&5 +$as_echo_n "checking whether to include OpenSSL support... " >&6; } + +# Check whether --with-openssl was given. +if test "${with_openssl+set}" = set; then : + withval=$with_openssl; case "$withval" in + yes) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +$as_echo "#define WITH_OPENSSL /**/" >>confdefs.h + + OPENSSLLIBS="-lssl -lcrypto $OPENSSLLIBS" + ;; + *) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + ;; + esac +else + SAVELIBS="$LIBS" + LIBS="$LIBS -lssl -lcrypto" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +(void) TLSv1_method() + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +$as_echo "#define WITH_OPENSSL /**/" >>confdefs.h + + OPENSSLLIBS="-lssl -lcrypto $OPENSSLLIBS" +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LIBS="$SAVELIBS" +fi + + + + SAVELIBS=$LIBS + HAVE_SSL_CTX_GET0_PARAM=yes + LIBS="$LIBS $OPENSSLLIBS" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether OpenSSL provides the SSL_CTX_get0_param function" >&5 +$as_echo_n "checking whether OpenSSL provides the SSL_CTX_get0_param function... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + #include +int +main () +{ +&SSL_CTX_get0_param; + ; + return 0; +} + +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + $as_echo "#define HAVE_SSL_CTX_GET0_PARAM 1" >>confdefs.h + + +else + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + LIBS=$SAVELIBS + + + SAVELIBS=$LIBS + HAVE_RAND_EGD=yes + LIBS="$LIBS $OPENSSLLIBS" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether OpenSSL provides the RAND_egd function" >&5 +$as_echo_n "checking whether OpenSSL provides the RAND_egd function... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + #include +int +main () +{ +&RAND_egd; + ; + return 0; +} + +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + $as_echo "#define HAVE_RAND_EGD 1" >>confdefs.h + + +else + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + LIBS=$SAVELIBS + + + +JPEGLIBS="" +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for jpeg_set_defaults in -ljpeg" >&5 +$as_echo_n "checking for jpeg_set_defaults in -ljpeg... " >&6; } +if ${ac_cv_lib_jpeg_jpeg_set_defaults+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ljpeg $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char jpeg_set_defaults (); +int +main () +{ +return jpeg_set_defaults (); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + ac_cv_lib_jpeg_jpeg_set_defaults=yes +else + ac_cv_lib_jpeg_jpeg_set_defaults=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_jpeg_jpeg_set_defaults" >&5 +$as_echo "$ac_cv_lib_jpeg_jpeg_set_defaults" >&6; } +if test "x$ac_cv_lib_jpeg_jpeg_set_defaults" = xyes; then : + +JPEGLIBS="-ljpeg" + +fi + +if test $ac_cv_lib_jpeg_jpeg_set_defaults = no ; then +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for jSetDefaults in -ljpeg" >&5 +$as_echo_n "checking for jSetDefaults in -ljpeg... " >&6; } +if ${ac_cv_lib_jpeg_jSetDefaults+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ljpeg $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char jSetDefaults (); +int +main () +{ +return jSetDefaults (); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + ac_cv_lib_jpeg_jSetDefaults=yes +else + ac_cv_lib_jpeg_jSetDefaults=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_jpeg_jSetDefaults" >&5 +$as_echo "$ac_cv_lib_jpeg_jSetDefaults" >&6; } +if test "x$ac_cv_lib_jpeg_jSetDefaults" = xyes; then : + +JPEGLIBS="-ljpeg" + +fi + +fi + + + + +# Check whether --with-zlibinc was given. +if test "${with_zlibinc+set}" = set; then : + withval=$with_zlibinc; case $withval in #( + yes|no) : + + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: --with-zlibinc called without argument - will use default" >&5 +$as_echo "$as_me: WARNING: --with-zlibinc called without argument - will use default" >&2;} + ;; #( + *) : + + if test ! -d ${withval}; then + as_fn_error $? "called with --with-zlibinc but zlib base directory ${withval} does not exist or is not a directory." "$LINENO" 5 + fi + + CPPFLAGS="-I${withval}/include $CPPFLAGS" + LDFLAGS="-L${withval}/lib $LDFLAGS" + if test "x$dcmtk_cv_rpath_works" = "xyes"; then + LDFLAGS="-Wl,-rpath,${withval}/lib $LDFLAGS" + fi + ;; +esac + +fi + + +ZLIBLIBS="" +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to include zlib support" >&5 +$as_echo_n "checking whether to include zlib support... " >&6; } + +# Check whether --with-zlib was given. +if test "${with_zlib+set}" = set; then : + withval=$with_zlib; case "$withval" in + yes) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +$as_echo "#define WITH_ZLIB /**/" >>confdefs.h + + ZLIBLIBS="-lz" + ;; + *) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + ;; + esac +else + SAVELIBS="$LIBS" + LIBS="$LIBS -lz" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +(void) zlibVersion() + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +$as_echo "#define WITH_ZLIB /**/" >>confdefs.h + + ZLIBLIBS="-lz" +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LIBS="$SAVELIBS" +fi + + + + + +# Check whether --with-libtiffinc was given. +if test "${with_libtiffinc+set}" = set; then : + withval=$with_libtiffinc; case $withval in #( + yes|no) : + + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: --with-libtiffinc called without argument - will use default" >&5 +$as_echo "$as_me: WARNING: --with-libtiffinc called without argument - will use default" >&2;} + ;; #( + *) : + + if test ! -d ${withval}; then + as_fn_error $? "called with --with-libtiffinc but libtiff base directory ${withval} does not exist or is not a directory." "$LINENO" 5 + fi + + CPPFLAGS="-I${withval}/include $CPPFLAGS" + LDFLAGS="-L${withval}/lib $LDFLAGS" + if test "x$dcmtk_cv_rpath_works" = "xyes"; then + LDFLAGS="-Wl,-rpath,${withval}/lib $LDFLAGS" + fi + ;; +esac + +fi + + +TIFFLIBS="" +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to include libtiff support" >&5 +$as_echo_n "checking whether to include libtiff support... " >&6; } + +# Check whether --with-libtiff was given. +if test "${with_libtiff+set}" = set; then : + withval=$with_libtiff; case "$withval" in + yes) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +$as_echo "#define WITH_LIBTIFF /**/" >>confdefs.h + + TIFFLIBS="-ltiff $JPEGLIBS $ZLIBLIBS" + SAVELIBS="$LIBS" + LIBS="$LIBS -ltiff $JPEGLIBS $ZLIBLIBS" + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether libtiff supports LZW compression" >&5 +$as_echo_n "checking whether libtiff supports LZW compression... " >&6; } +if ${ac_cv_libtiff_lzw_compression+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "$cross_compiling" = yes; then : + ac_cv_libtiff_lzw_compression=no +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +extern "C" { +#include +} + +int main() +{ + const char *data[256]; + for (int j=0; j<256; ++j) data[j]= 0; + + int OK = 1; + TIFF *tif = TIFFOpen("lzwtest.tif", "w"); + if (tif) + { + TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, 16); + TIFFSetField(tif, TIFFTAG_IMAGELENGTH, 16); + TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 8); + TIFFSetField(tif, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT); + TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_LZW); + TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK); + TIFFSetField(tif, TIFFTAG_FILLORDER, FILLORDER_MSB2LSB); + TIFFSetField(tif, TIFFTAG_DOCUMENTNAME, "unnamed"); + TIFFSetField(tif, TIFFTAG_IMAGEDESCRIPTION, "test"); + TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, 1); + TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, 512); + TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); + + for (unsigned long i=0; (i < 16) && OK; i++) + { + if (TIFFWriteScanline(tif, data + (i << 4), i, 0) < 0) OK = 0; + } + TIFFFlushData(tif); + TIFFClose(tif); + } + if (OK) return 0; else return 10; +} + + + +_ACEOF +if ac_fn_cxx_try_run "$LINENO"; then : + ac_cv_libtiff_lzw_compression=yes +else + ac_cv_libtiff_lzw_compression=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_libtiff_lzw_compression" >&5 +$as_echo "$ac_cv_libtiff_lzw_compression" >&6; } +if test "$ac_cv_libtiff_lzw_compression" = yes; then + +$as_echo "#define HAVE_LIBTIFF_LZW_COMPRESSION /**/" >>confdefs.h + +fi + + LIBS="$SAVELIBS" + ;; + *) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + ;; + esac +else + SAVELIBS="$LIBS" + LIBS="$LIBS -ltiff $JPEGLIBS $ZLIBLIBS" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +(void) TIFFGetVersion() + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +$as_echo "#define WITH_LIBTIFF /**/" >>confdefs.h + + TIFFLIBS="-ltiff $JPEGLIBS $ZLIBLIBS" + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether libtiff supports LZW compression" >&5 +$as_echo_n "checking whether libtiff supports LZW compression... " >&6; } +if ${ac_cv_libtiff_lzw_compression+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "$cross_compiling" = yes; then : + ac_cv_libtiff_lzw_compression=no +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +extern "C" { +#include +} + +int main() +{ + const char *data[256]; + for (int j=0; j<256; ++j) data[j]= 0; + + int OK = 1; + TIFF *tif = TIFFOpen("lzwtest.tif", "w"); + if (tif) + { + TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, 16); + TIFFSetField(tif, TIFFTAG_IMAGELENGTH, 16); + TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 8); + TIFFSetField(tif, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT); + TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_LZW); + TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK); + TIFFSetField(tif, TIFFTAG_FILLORDER, FILLORDER_MSB2LSB); + TIFFSetField(tif, TIFFTAG_DOCUMENTNAME, "unnamed"); + TIFFSetField(tif, TIFFTAG_IMAGEDESCRIPTION, "test"); + TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, 1); + TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, 512); + TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); + + for (unsigned long i=0; (i < 16) && OK; i++) + { + if (TIFFWriteScanline(tif, data + (i << 4), i, 0) < 0) OK = 0; + } + TIFFFlushData(tif); + TIFFClose(tif); + } + if (OK) return 0; else return 10; +} + + + +_ACEOF +if ac_fn_cxx_try_run "$LINENO"; then : + ac_cv_libtiff_lzw_compression=yes +else + ac_cv_libtiff_lzw_compression=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_libtiff_lzw_compression" >&5 +$as_echo "$ac_cv_libtiff_lzw_compression" >&6; } +if test "$ac_cv_libtiff_lzw_compression" = yes; then + +$as_echo "#define HAVE_LIBTIFF_LZW_COMPRESSION /**/" >>confdefs.h + +fi + + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LIBS="$SAVELIBS" +fi + + + + + + +# Check whether --with-libpnginc was given. +if test "${with_libpnginc+set}" = set; then : + withval=$with_libpnginc; case $withval in #( + yes|no) : + + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: --with-libpnginc called without argument - will use default" >&5 +$as_echo "$as_me: WARNING: --with-libpnginc called without argument - will use default" >&2;} + ;; #( + *) : + + if test ! -d ${withval}; then + as_fn_error $? "called with --with-libpnginc but libpng base directory ${withval} does not exist or is not a directory." "$LINENO" 5 + fi + + CPPFLAGS="-I${withval}/include $CPPFLAGS" + LDFLAGS="-L${withval}/lib $LDFLAGS" + if test "x$dcmtk_cv_rpath_works" = "xyes"; then + LDFLAGS="-Wl,-rpath,${withval}/lib $LDFLAGS" + fi + ;; +esac + +fi + + +for ac_header in libpng/png.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "libpng/png.h" "ac_cv_header_libpng_png_h" "$ac_includes_default" +if test "x$ac_cv_header_libpng_png_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBPNG_PNG_H 1 +_ACEOF + +fi + +done + + +PNGLIBS="" +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to include libpng support" >&5 +$as_echo_n "checking whether to include libpng support... " >&6; } + +# Check whether --with-libpng was given. +if test "${with_libpng+set}" = set; then : + withval=$with_libpng; case "$withval" in + yes) + if test "x$ZLIBLIBS" != x; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +$as_echo "#define WITH_LIBPNG /**/" >>confdefs.h + + PNGLIBS="-lpng" + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no because libpng requires zlib" >&5 +$as_echo "no because libpng requires zlib" >&6; } + fi + ;; + *) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + ;; + esac +else + if test "x$ZLIBLIBS" != x; then + SAVELIBS="$LIBS" + LIBS="$LIBS -lpng $ZLIBLIBS" + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef HAVE_LIBPNG_PNG_H +#include +#else +#include +#endif +int +main () +{ +(void) png_access_version_number() + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +$as_echo "#define WITH_LIBPNG /**/" >>confdefs.h + + PNGLIBS="-lpng" +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + + LIBS="$SAVELIBS" + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no because libpng requires zlib" >&5 +$as_echo "no because libpng requires zlib" >&6; } + fi + +fi + + + + + +# Check whether --with-libxmlinc was given. +if test "${with_libxmlinc+set}" = set; then : + withval=$with_libxmlinc; case $withval in #( + yes|no) : + + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: --with-libxmlinc called without argument - will use default" >&5 +$as_echo "$as_me: WARNING: --with-libxmlinc called without argument - will use default" >&2;} + ;; #( + *) : + + if test ! -d ${withval}; then + as_fn_error $? "called with --with-libxmlinc but libxml base directory ${withval} does not exist or is not a directory." "$LINENO" 5 + fi + + CPPFLAGS="-I${withval}/include $CPPFLAGS" + LDFLAGS="-L${withval}/lib $LDFLAGS" + if test "x$dcmtk_cv_rpath_works" = "xyes"; then + LDFLAGS="-Wl,-rpath,${withval}/lib $LDFLAGS" + fi + ;; +esac + +fi + + +LIBXMLCFLAGS=`xml2-config --cflags 2>/dev/null` +if test "${LIBXMLCFLAGS+set}" = set; then + CXXFLAGS="$LIBXMLCFLAGS $CXXFLAGS" + CFLAGS="$LIBXMLCFLAGS $CFLAGS" +fi + +XMLLIBS="" +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to include libxml support" >&5 +$as_echo_n "checking whether to include libxml support... " >&6; } + +# Check whether --with-libxml was given. +if test "${with_libxml+set}" = set; then : + withval=$with_libxml; case "$withval" in + yes) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +$as_echo "#define WITH_LIBXML /**/" >>confdefs.h + + XMLLIBS="-lxml2" + ;; + *) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + ;; + esac +else + SAVELIBS="$LIBS" + LIBS="$LIBS -lxml2 $ZLIBLIBS" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +(void) xmlInitParser() + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +$as_echo "#define WITH_LIBXML /**/" >>confdefs.h + + XMLLIBS="-lxml2" +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LIBS="$SAVELIBS" +fi + + + + + +# Check whether --with-libwrapinc was given. +if test "${with_libwrapinc+set}" = set; then : + withval=$with_libwrapinc; case $withval in #( + yes|no) : + + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: --with-libwrapinc called without argument - will use default" >&5 +$as_echo "$as_me: WARNING: --with-libwrapinc called without argument - will use default" >&2;} + ;; #( + *) : + + if test ! -d ${withval}; then + as_fn_error $? "called with --with-libwrapinc but libwrap base directory ${withval} does not exist or is not a directory." "$LINENO" 5 + fi + + CPPFLAGS="-I${withval}/include $CPPFLAGS" + LDFLAGS="-L${withval}/lib $LDFLAGS" + if test "x$dcmtk_cv_rpath_works" = "xyes"; then + LDFLAGS="-Wl,-rpath,${withval}/lib $LDFLAGS" + fi + ;; +esac + +fi + + +TCPWRAPPERLIBS="" +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to include libwrap support" >&5 +$as_echo_n "checking whether to include libwrap support... " >&6; } + +# Check whether --with-libwrap was given. +if test "${with_libwrap+set}" = set; then : + withval=$with_libwrap; case "$withval" in + yes) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +$as_echo "#define WITH_TCPWRAPPER /**/" >>confdefs.h + + TCPWRAPPERLIBS="-lwrap" + ;; + *) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + ;; + esac +else + SAVELIBS="$LIBS" + LIBS="-lwrap $LIBS" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __cplusplus + extern "C" { + #endif + #ifdef HAVE_STDIO_H + /* on some platforms, tcpd.h needs stdio.h */ + #include + #endif + #ifdef HAVE_SYS_TYPES_H + /* on some platforms, tcpd.h needs sys/types.h */ + #include + #endif + #include + #ifdef __cplusplus + } + #endif + int deny_severity = 0; + int allow_severity = 0; +int +main () +{ +struct request_info r; (void) hosts_access(&r) + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +$as_echo "#define WITH_TCPWRAPPER /**/" >>confdefs.h + + TCPWRAPPERLIBS="-lwrap" +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LIBS="$SAVELIBS" +fi + + + + + + +# Check whether --with-libsndfileinc was given. +if test "${with_libsndfileinc+set}" = set; then : + withval=$with_libsndfileinc; case $withval in #( + yes|no) : + + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: --with-libsndfileinc called without argument - will use default" >&5 +$as_echo "$as_me: WARNING: --with-libsndfileinc called without argument - will use default" >&2;} + ;; #( + *) : + + if test ! -d ${withval}; then + as_fn_error $? "called with --with-libsndfileinc but libsndfile base directory ${withval} does not exist or is not a directory." "$LINENO" 5 + fi + + CPPFLAGS="-I${withval}/include $CPPFLAGS" + LDFLAGS="-L${withval}/lib $LDFLAGS" + if test "x$dcmtk_cv_rpath_works" = "xyes"; then + LDFLAGS="-Wl,-rpath,${withval}/lib $LDFLAGS" + fi + ;; +esac + +fi + + +SNDFILELIBS="" +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to include libsndfile support" >&5 +$as_echo_n "checking whether to include libsndfile support... " >&6; } + +# Check whether --with-libsndfile was given. +if test "${with_libsndfile+set}" = set; then : + withval=$with_libsndfile; case "$withval" in + yes) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +$as_echo "#define WITH_SNDFILE /**/" >>confdefs.h + + SNDFILELIBS="-lsndfile" + ;; + *) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + ;; + esac +else + SAVELIBS="$LIBS" + LIBS="$LIBS -lsndfile" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +char buffer [128]; sf_command (NULL, SFC_GET_LIB_VERSION, buffer, sizeof (buffer)); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +$as_echo "#define WITH_SNDFILE /**/" >>confdefs.h + + SNDFILELIBS="-lsndfile" +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LIBS="$SAVELIBS" + +fi + + + + + +# Check whether --with-libiconvinc was given. +if test "${with_libiconvinc+set}" = set; then : + withval=$with_libiconvinc; case $withval in #( + yes|no) : + + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: --with-libiconvinc called without argument - will use default" >&5 +$as_echo "$as_me: WARNING: --with-libiconvinc called without argument - will use default" >&2;} + ;; #( + *) : + + if test ! -d ${withval}; then + as_fn_error $? "called with --with-libiconvinc but libiconv base directory ${withval} does not exist or is not a directory." "$LINENO" 5 + fi + + CPPFLAGS="-I${withval}/include $CPPFLAGS" + LDFLAGS="-L${withval}/lib $LDFLAGS" + if test "x$dcmtk_cv_rpath_works" = "xyes"; then + LDFLAGS="-Wl,-rpath,${withval}/lib $LDFLAGS" + fi + ;; +esac + +fi + + +ICONVLIBS="" +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to include libiconv support" >&5 +$as_echo_n "checking whether to include libiconv support... " >&6; } + +# Check whether --with-libiconv was given. +if test "${with_libiconv+set}" = set; then : + withval=$with_libiconv; case "$withval" in + yes) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +$as_echo "#define WITH_LIBICONV /**/" >>confdefs.h + + ICONVLIBS="-liconv -lcharset" + ;; + *) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + ;; + esac +else + SAVELIBS="$LIBS" + LIBS="$LIBS -liconv -lcharset" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +iconv_t cd = iconv_open("", ""); iconv(cd, NULL, NULL, NULL, NULL); iconv_close(cd); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +$as_echo "#define WITH_LIBICONV /**/" >>confdefs.h + + ICONVLIBS="-liconv -lcharset" +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LIBS="$SAVELIBS" +fi + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the second argument to iconv() is const" >&5 +$as_echo_n "checking whether the second argument to iconv() is const... " >&6; } +SAVELIBS="$LIBS" +LIBS="$LIBS $ICONVLIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +iconv_t cd = iconv_open("", ""); const char *in = 0; iconv(cd, &in, NULL, NULL, NULL); iconv_close(cd); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +$as_echo "#define LIBICONV_SECOND_ARGUMENT_CONST /**/" >>confdefs.h + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +LIBS="$SAVELIBS" + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if the C++11 STL should be used" >&5 +$as_echo_n "checking if the C++11 STL should be used... " >&6; } + +# Check whether --with-cxx11-stl was given. +if test "${with_cxx11_stl+set}" = set; then : + withval=$with_cxx11_stl; case "$withval" in + yes) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +$as_echo "#define DCMTK_USE_CXX11_STL /**/" >>confdefs.h + + ;; + *) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + ;; + esac +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +fi + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for __sync_add_and_fetch" >&5 +$as_echo_n "checking for __sync_add_and_fetch... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + + int main(){return __sync_add_and_fetch((int *)0, 0);} + + +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + dcmtk_have_sync_fn=yes +else + dcmtk_have_sync_fn=no + +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + if test "$dcmtk_have_sync_fn" = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +$as_echo "#define HAVE_SYNC_ADD_AND_FETCH 1" >>confdefs.h + + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for __sync_sub_and_fetch" >&5 +$as_echo_n "checking for __sync_sub_and_fetch... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + + int main(){return __sync_sub_and_fetch((int *)0, 0);} + + +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + dcmtk_have_sync_fn=yes +else + dcmtk_have_sync_fn=no + +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + if test "$dcmtk_have_sync_fn" = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +$as_echo "#define HAVE_SYNC_SUB_AND_FETCH 1" >>confdefs.h + + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for __alignof__" >&5 +$as_echo_n "checking for __alignof__... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + + int main(){char c[__alignof__(int)];return 0;} + + +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + dcmtk_have_alignof=yes +else + dcmtk_have_alignof=no + +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + if test "$dcmtk_have_alignof" = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +$as_echo "#define HAVE_GNU_ALIGNOF 1" >>confdefs.h + + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for __attribute__((aligned))" >&5 +$as_echo_n "checking for __attribute__((aligned))... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + + int main(){__attribute__((aligned(4))) char c[16];return 0;} + + +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + dcmtk_have_attribute_aligned=yes +else + dcmtk_have_attribute_aligned=no + +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + if test "$dcmtk_have_attribute_aligned" = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +$as_echo "#define HAVE_ATTRIBUTE_ALIGNED 1" >>confdefs.h + + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether __attribute__((aligned)) supports templates" >&5 +$as_echo_n "checking whether __attribute__((aligned)) supports templates... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + + template + struct test { typedef T type __attribute__((aligned(4))); }; + int main() + { + test::type i; + return 0; + } + + +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + dcmtk_attribute_aligned_supports_templates=yes +else + dcmtk_attribute_aligned_supports_templates=no + +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + if test "$dcmtk_attribute_aligned_supports_templates" = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +$as_echo "#define ATTRIBUTE_ALIGNED_SUPPORTS_TEMPLATES 1" >>confdefs.h + + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether alignas supports typedefs" >&5 +$as_echo_n "checking whether alignas supports typedefs... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + + int main() + { + typedef char type[16] alignas(4); + return 0; + } + + +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + dcmtk_alignas_supports_typedefs=yes +else + dcmtk_alignas_supports_typedefs=no + +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + if test "$dcmtk_alignas_supports_typedefs" = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +$as_echo "#define ALIGNAS_SUPPORTS_TYPEDEFS 1" >>confdefs.h + + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports default constructor detection via SFINAE" >&5 +$as_echo_n "checking whether the compiler supports default constructor detection via SFINAE... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + + struct no_type {}; + struct yes_type {double d;}; + template + struct consume{}; + template + static yes_type sfinae(consume*); + template + static no_type sfinae(...); + struct test { test( int ); }; + int main() + { + return sizeof(sfinae(0)) == sizeof(yes_type); + } + + +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + dcmtk_default_constructor_detection_via_sfinae=yes +else + dcmtk_default_constructor_detection_via_sfinae=no + +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + if test "$dcmtk_default_constructor_detection_via_sfinae" = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +$as_echo "#define HAVE_DEFAULT_CONSTRUCTOR_DETECTION_VIA_SFINAE 1" >>confdefs.h + + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + fi + +o + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether struct pwd contains the field pw_gecos" >&5 +$as_echo_n "checking whether struct pwd contains the field pw_gecos... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +&passwd::pw_gecos; + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +$as_echo "#define HAVE_PASSWD_GECOS /**/" >>confdefs.h + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for SYS_gettid in sys/syscall.h" >&5 +$as_echo_n "checking for SYS_gettid in sys/syscall.h... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +SYS_gettid; + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +$as_echo "#define HAVE_SYS_GETTID /**/" >>confdefs.h + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +CFLAGS="$DEBUGCFLAGS $CFLAGS" +CXXFLAGS="$DEBUGCXXFLAGS $CXXFLAGS" + + + + + + + + + + + + + + +ac_config_files="$ac_config_files Makefile.def Makefile" + +cat >confcache <<\_ACEOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs, see configure's option --config-cache. +# It is not useful on other systems. If it contains results you don't +# want to keep, you may remove or edit it. +# +# config.status only pays attention to the cache file if you give it +# the --recheck option to rerun configure. +# +# `ac_cv_env_foo' variables (set or unset) will be overridden when +# loading this file, other *unset* `ac_cv_foo' will be assigned the +# following values. + +_ACEOF + +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, we kill variables containing newlines. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +( + for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + + (set) 2>&1 | + case $as_nl`(ac_space=' '; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + # `set' does not quote correctly, so add quotes: double-quote + # substitution turns \\\\ into \\, and sed turns \\ into \. + sed -n \ + "s/'/'\\\\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" + ;; #( + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) | + sed ' + /^ac_cv_env_/b end + t clear + :clear + s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ + t end + s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ + :end' >>confcache +if diff "$cache_file" confcache >/dev/null 2>&1; then :; else + if test -w "$cache_file"; then + if test "x$cache_file" != "x/dev/null"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 +$as_echo "$as_me: updating cache $cache_file" >&6;} + if test ! -f "$cache_file" || test -h "$cache_file"; then + cat confcache >"$cache_file" + else + case $cache_file in #( + */* | ?:*) + mv -f confcache "$cache_file"$$ && + mv -f "$cache_file"$$ "$cache_file" ;; #( + *) + mv -f confcache "$cache_file" ;; + esac + fi + fi + else + { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 +$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} + fi +fi +rm -f confcache + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +DEFS=-DHAVE_CONFIG_H + +ac_libobjs= +ac_ltlibobjs= +U= +for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue + # 1. Remove the extension, and $U if already installed. + ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' + ac_i=`$as_echo "$ac_i" | sed "$ac_script"` + # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR + # will be set to the directory where LIBOBJS objects are built. + as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" + as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' +done +LIBOBJS=$ac_libobjs + +LTLIBOBJS=$ac_ltlibobjs + + + +: "${CONFIG_STATUS=./config.status}" +ac_write_fail=0 +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files $CONFIG_STATUS" +{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 +$as_echo "$as_me: creating $CONFIG_STATUS" >&6;} +as_write_fail=0 +cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 +#! $SHELL +# Generated by $as_me. +# Run this file to recreate the current configuration. +# Compiler output produced by configure, useful for debugging +# configure, is in config.log if it exists. + +debug=false +ac_cs_recheck=false +ac_cs_silent=false + +SHELL=\${CONFIG_SHELL-$SHELL} +export SHELL +_ASEOF +cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +as_myself= +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + + +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 + as_fn_exit $as_status +} # as_fn_error + + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -pR'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -pR' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -pR' + fi +else + as_ln_s='cp -pR' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} # as_fn_mkdir_p +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + + +# as_fn_executable_p FILE +# ----------------------- +# Test if FILE is an executable regular file. +as_fn_executable_p () +{ + test -f "$1" && test -x "$1" +} # as_fn_executable_p +as_test_x='test -x' +as_executable_p=as_fn_executable_p + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +exec 6>&1 +## ----------------------------------- ## +## Main body of $CONFIG_STATUS script. ## +## ----------------------------------- ## +_ASEOF +test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# Save the log message, to keep $0 and so on meaningful, and to +# report actual input values of CONFIG_FILES etc. instead of their +# values after options handling. +ac_log=" +This file was extended by dcmtk $as_me 3.6.1, which was +generated by GNU Autoconf 2.69. Invocation command line was + + CONFIG_FILES = $CONFIG_FILES + CONFIG_HEADERS = $CONFIG_HEADERS + CONFIG_LINKS = $CONFIG_LINKS + CONFIG_COMMANDS = $CONFIG_COMMANDS + $ $0 $@ + +on `(hostname || uname -n) 2>/dev/null | sed 1q` +" + +_ACEOF + +case $ac_config_files in *" +"*) set x $ac_config_files; shift; ac_config_files=$*;; +esac + +case $ac_config_headers in *" +"*) set x $ac_config_headers; shift; ac_config_headers=$*;; +esac + + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +# Files that config.status was made for. +config_files="$ac_config_files" +config_headers="$ac_config_headers" + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +ac_cs_usage="\ +\`$as_me' instantiates files and other configuration actions +from templates according to the current configuration. Unless the files +and actions are specified as TAGs, all are instantiated by default. + +Usage: $0 [OPTION]... [TAG]... + + -h, --help print this help, then exit + -V, --version print version number and configuration settings, then exit + --config print configuration, then exit + -q, --quiet, --silent + do not print progress messages + -d, --debug don't remove temporary files + --recheck update $as_me by reconfiguring in the same conditions + --file=FILE[:TEMPLATE] + instantiate the configuration file FILE + --header=FILE[:TEMPLATE] + instantiate the configuration header FILE + +Configuration files: +$config_files + +Configuration headers: +$config_headers + +Report bugs to . +dcmtk home page: ." + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" +ac_cs_version="\\ +dcmtk config.status 3.6.1 +configured by $0, generated by GNU Autoconf 2.69, + with options \\"\$ac_cs_config\\" + +Copyright (C) 2012 Free Software Foundation, Inc. +This config.status script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it." + +ac_pwd='$ac_pwd' +srcdir='$srcdir' +INSTALL='$INSTALL' +test -n "\$AWK" || AWK=awk +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# The default lists apply if the user does not specify any file. +ac_need_defaults=: +while test $# != 0 +do + case $1 in + --*=?*) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` + ac_shift=: + ;; + --*=) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg= + ac_shift=: + ;; + *) + ac_option=$1 + ac_optarg=$2 + ac_shift=shift + ;; + esac + + case $ac_option in + # Handling of the options. + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + ac_cs_recheck=: ;; + --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) + $as_echo "$ac_cs_version"; exit ;; + --config | --confi | --conf | --con | --co | --c ) + $as_echo "$ac_cs_config"; exit ;; + --debug | --debu | --deb | --de | --d | -d ) + debug=: ;; + --file | --fil | --fi | --f ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + '') as_fn_error $? "missing file argument" ;; + esac + as_fn_append CONFIG_FILES " '$ac_optarg'" + ac_need_defaults=false;; + --header | --heade | --head | --hea ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + as_fn_append CONFIG_HEADERS " '$ac_optarg'" + ac_need_defaults=false;; + --he | --h) + # Conflict between --help and --header + as_fn_error $? "ambiguous option: \`$1' +Try \`$0 --help' for more information.";; + --help | --hel | -h ) + $as_echo "$ac_cs_usage"; exit ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil | --si | --s) + ac_cs_silent=: ;; + + # This is an error. + -*) as_fn_error $? "unrecognized option: \`$1' +Try \`$0 --help' for more information." ;; + + *) as_fn_append ac_config_targets " $1" + ac_need_defaults=false ;; + + esac + shift +done + +ac_configure_extra_args= + +if $ac_cs_silent; then + exec 6>/dev/null + ac_configure_extra_args="$ac_configure_extra_args --silent" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +if \$ac_cs_recheck; then + set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion + shift + \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 + CONFIG_SHELL='$SHELL' + export CONFIG_SHELL + exec "\$@" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +exec 5>>config.log +{ + echo + sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX +## Running $as_me. ## +_ASBOX + $as_echo "$ac_log" +} >&5 + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 + +# Handling of arguments. +for ac_config_target in $ac_config_targets +do + case $ac_config_target in + "include/dcmtk/config/osconfig.h") CONFIG_HEADERS="$CONFIG_HEADERS include/dcmtk/config/osconfig.h" ;; + "Makefile.def") CONFIG_FILES="$CONFIG_FILES Makefile.def" ;; + "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; + + *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; + esac +done + + +# If the user did not use the arguments to specify the items to instantiate, +# then the envvar interface is used. Set only those that are not. +# We use the long form for the default assignment because of an extremely +# bizarre bug on SunOS 4.1.3. +if $ac_need_defaults; then + test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files + test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers +fi + +# Have a temporary directory for convenience. Make it in the build tree +# simply because there is no reason against having it here, and in addition, +# creating and moving files from /tmp can sometimes cause problems. +# Hook for its removal unless debugging. +# Note that there is a small window in which the directory will not be cleaned: +# after its creation but before its name has been assigned to `$tmp'. +$debug || +{ + tmp= ac_tmp= + trap 'exit_status=$? + : "${ac_tmp:=$tmp}" + { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status +' 0 + trap 'as_fn_exit 1' 1 2 13 15 +} +# Create a (secure) tmp directory for tmp files. + +{ + tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && + test -d "$tmp" +} || +{ + tmp=./conf$$-$RANDOM + (umask 077 && mkdir "$tmp") +} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 +ac_tmp=$tmp + +# Set up the scripts for CONFIG_FILES section. +# No need to generate them if there are no CONFIG_FILES. +# This happens for instance with `./config.status config.h'. +if test -n "$CONFIG_FILES"; then + + +ac_cr=`echo X | tr X '\015'` +# On cygwin, bash can eat \r inside `` if the user requested igncr. +# But we know of no other shell where ac_cr would be empty at this +# point, so we can use a bashism as a fallback. +if test "x$ac_cr" = x; then + eval ac_cr=\$\'\\r\' +fi +ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` +if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then + ac_cs_awk_cr='\\r' +else + ac_cs_awk_cr=$ac_cr +fi + +echo 'BEGIN {' >"$ac_tmp/subs1.awk" && +_ACEOF + + +{ + echo "cat >conf$$subs.awk <<_ACEOF" && + echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && + echo "_ACEOF" +} >conf$$subs.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 +ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` +ac_delim='%!_!# ' +for ac_last_try in false false false false false :; do + . ./conf$$subs.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + + ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` + if test $ac_delim_n = $ac_delim_num; then + break + elif $ac_last_try; then + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done +rm -f conf$$subs.sh + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && +_ACEOF +sed -n ' +h +s/^/S["/; s/!.*/"]=/ +p +g +s/^[^!]*!// +:repl +t repl +s/'"$ac_delim"'$// +t delim +:nl +h +s/\(.\{148\}\)..*/\1/ +t more1 +s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ +p +n +b repl +:more1 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t nl +:delim +h +s/\(.\{148\}\)..*/\1/ +t more2 +s/["\\]/\\&/g; s/^/"/; s/$/"/ +p +b +:more2 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t delim +' >$CONFIG_STATUS || ac_write_fail=1 +rm -f conf$$subs.awk +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +_ACAWK +cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && + for (key in S) S_is_set[key] = 1 + FS = "" + +} +{ + line = $ 0 + nfields = split(line, field, "@") + substed = 0 + len = length(field[1]) + for (i = 2; i < nfields; i++) { + key = field[i] + keylen = length(key) + if (S_is_set[key]) { + value = S[key] + line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) + len += length(value) + length(field[++i]) + substed = 1 + } else + len += 1 + keylen + } + + print line +} + +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then + sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" +else + cat +fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ + || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 +_ACEOF + +# VPATH may cause trouble with some makes, so we remove sole $(srcdir), +# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and +# trailing colons and then remove the whole line if VPATH becomes empty +# (actually we leave an empty line to preserve line numbers). +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ +h +s/// +s/^/:/ +s/[ ]*$/:/ +s/:\$(srcdir):/:/g +s/:\${srcdir}:/:/g +s/:@srcdir@:/:/g +s/^:*// +s/:*$// +x +s/\(=[ ]*\).*/\1/ +G +s/\n// +s/^[^=]*=[ ]*$// +}' +fi + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +fi # test -n "$CONFIG_FILES" + +# Set up the scripts for CONFIG_HEADERS section. +# No need to generate them if there are no CONFIG_HEADERS. +# This happens for instance with `./config.status Makefile'. +if test -n "$CONFIG_HEADERS"; then +cat >"$ac_tmp/defines.awk" <<\_ACAWK || +BEGIN { +_ACEOF + +# Transform confdefs.h into an awk script `defines.awk', embedded as +# here-document in config.status, that substitutes the proper values into +# config.h.in to produce config.h. + +# Create a delimiter string that does not exist in confdefs.h, to ease +# handling of long lines. +ac_delim='%!_!# ' +for ac_last_try in false false :; do + ac_tt=`sed -n "/$ac_delim/p" confdefs.h` + if test -z "$ac_tt"; then + break + elif $ac_last_try; then + as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done + +# For the awk script, D is an array of macro values keyed by name, +# likewise P contains macro parameters if any. Preserve backslash +# newline sequences. + +ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* +sed -n ' +s/.\{148\}/&'"$ac_delim"'/g +t rset +:rset +s/^[ ]*#[ ]*define[ ][ ]*/ / +t def +d +:def +s/\\$// +t bsnl +s/["\\]/\\&/g +s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ +D["\1"]=" \3"/p +s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p +d +:bsnl +s/["\\]/\\&/g +s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ +D["\1"]=" \3\\\\\\n"\\/p +t cont +s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p +t cont +d +:cont +n +s/.\{148\}/&'"$ac_delim"'/g +t clear +:clear +s/\\$// +t bsnlc +s/["\\]/\\&/g; s/^/"/; s/$/"/p +d +:bsnlc +s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p +b cont +' >$CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + for (key in D) D_is_set[key] = 1 + FS = "" +} +/^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ { + line = \$ 0 + split(line, arg, " ") + if (arg[1] == "#") { + defundef = arg[2] + mac1 = arg[3] + } else { + defundef = substr(arg[1], 2) + mac1 = arg[2] + } + split(mac1, mac2, "(") #) + macro = mac2[1] + prefix = substr(line, 1, index(line, defundef) - 1) + if (D_is_set[macro]) { + # Preserve the white space surrounding the "#". + print prefix "define", macro P[macro] D[macro] + next + } else { + # Replace #undef with comments. This is necessary, for example, + # in the case of _POSIX_SOURCE, which is predefined and required + # on some systems where configure will not decide to define it. + if (defundef == "undef") { + print "/*", prefix defundef, macro, "*/" + next + } + } +} +{ print } +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 + as_fn_error $? "could not setup config headers machinery" "$LINENO" 5 +fi # test -n "$CONFIG_HEADERS" + + +eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS " +shift +for ac_tag +do + case $ac_tag in + :[FHLC]) ac_mode=$ac_tag; continue;; + esac + case $ac_mode$ac_tag in + :[FHL]*:*);; + :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; + :[FH]-) ac_tag=-:-;; + :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; + esac + ac_save_IFS=$IFS + IFS=: + set x $ac_tag + IFS=$ac_save_IFS + shift + ac_file=$1 + shift + + case $ac_mode in + :L) ac_source=$1;; + :[FH]) + ac_file_inputs= + for ac_f + do + case $ac_f in + -) ac_f="$ac_tmp/stdin";; + *) # Look for the file first in the build tree, then in the source tree + # (if the path is not absolute). The absolute path cannot be DOS-style, + # because $ac_f cannot contain `:'. + test -f "$ac_f" || + case $ac_f in + [\\/$]*) false;; + *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; + esac || + as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; + esac + case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac + as_fn_append ac_file_inputs " '$ac_f'" + done + + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + configure_input='Generated from '` + $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' + `' by configure.' + if test x"$ac_file" != x-; then + configure_input="$ac_file. $configure_input" + { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 +$as_echo "$as_me: creating $ac_file" >&6;} + fi + # Neutralize special characters interpreted by sed in replacement strings. + case $configure_input in #( + *\&* | *\|* | *\\* ) + ac_sed_conf_input=`$as_echo "$configure_input" | + sed 's/[\\\\&|]/\\\\&/g'`;; #( + *) ac_sed_conf_input=$configure_input;; + esac + + case $ac_tag in + *:-:* | *:-) cat >"$ac_tmp/stdin" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; + esac + ;; + esac + + ac_dir=`$as_dirname -- "$ac_file" || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + as_dir="$ac_dir"; as_fn_mkdir_p + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + + case $ac_mode in + :F) + # + # CONFIG_FILE + # + + case $INSTALL in + [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; + *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; + esac +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# If the template does not know about datarootdir, expand it. +# FIXME: This hack should be removed a few years after 2.60. +ac_datarootdir_hack=; ac_datarootdir_seen= +ac_sed_dataroot=' +/datarootdir/ { + p + q +} +/@datadir@/p +/@docdir@/p +/@infodir@/p +/@localedir@/p +/@mandir@/p' +case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in +*datarootdir*) ac_datarootdir_seen=yes;; +*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 +$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + ac_datarootdir_hack=' + s&@datadir@&$datadir&g + s&@docdir@&$docdir&g + s&@infodir@&$infodir&g + s&@localedir@&$localedir&g + s&@mandir@&$mandir&g + s&\\\${datarootdir}&$datarootdir&g' ;; +esac +_ACEOF + +# Neutralize VPATH when `$srcdir' = `.'. +# Shell code in configure.ac might set extrasub. +# FIXME: do we really want to maintain this feature? +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_sed_extra="$ac_vpsub +$extrasub +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +:t +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +s|@configure_input@|$ac_sed_conf_input|;t t +s&@top_builddir@&$ac_top_builddir_sub&;t t +s&@top_build_prefix@&$ac_top_build_prefix&;t t +s&@srcdir@&$ac_srcdir&;t t +s&@abs_srcdir@&$ac_abs_srcdir&;t t +s&@top_srcdir@&$ac_top_srcdir&;t t +s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t +s&@builddir@&$ac_builddir&;t t +s&@abs_builddir@&$ac_abs_builddir&;t t +s&@abs_top_builddir@&$ac_abs_top_builddir&;t t +s&@INSTALL@&$ac_INSTALL&;t t +$ac_datarootdir_hack +" +eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ + >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + +test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && + { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && + { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ + "$ac_tmp/out"`; test -z "$ac_out"; } && + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&5 +$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&2;} + + rm -f "$ac_tmp/stdin" + case $ac_file in + -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; + *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; + esac \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + ;; + :H) + # + # CONFIG_HEADER + # + if test x"$ac_file" != x-; then + { + $as_echo "/* $configure_input */" \ + && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" + } >"$ac_tmp/config.h" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then + { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 +$as_echo "$as_me: $ac_file is unchanged" >&6;} + else + rm -f "$ac_file" + mv "$ac_tmp/config.h" "$ac_file" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + fi + else + $as_echo "/* $configure_input */" \ + && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \ + || as_fn_error $? "could not create -" "$LINENO" 5 + fi + ;; + + + esac + +done # for ac_tag + + +as_fn_exit 0 +_ACEOF +ac_clean_files=$ac_clean_files_save + +test $ac_write_fail = 0 || + as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 + + +# configure is writing to config.log, and then calls config.status. +# config.status does its own redirection, appending to config.log. +# Unfortunately, on DOS this fails, as config.log is still kept open +# by configure, so config.status won't be able to write to it; its +# output is simply discarded. So we exec the FD to /dev/null, +# effectively closing config.log, so it can be properly (re)opened and +# appended to by config.status. When coming back to configure, we +# need to make the FD available again. +if test "$no_create" != yes; then + ac_cs_success=: + ac_config_status_args= + test "$silent" = yes && + ac_config_status_args="$ac_config_status_args --quiet" + exec 5>/dev/null + $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false + exec 5>>config.log + # Use ||, not &&, to avoid exiting from the if with $? = 1, which + # would make configure fail if this is the last instruction. + $ac_cs_success || as_fn_exit 1 +fi +if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 +$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} +fi + + diff --git a/config/configure.in b/config/configure.in new file mode 100644 index 00000000..84665ab6 --- /dev/null +++ b/config/configure.in @@ -0,0 +1,1362 @@ +dnl Process this file with autoconf to produce a configure script. +AC_INIT(dcmtk, 3.6.1, [bugs@dcmtk.org], [dcmtk-3.6.1], [http://www.dcmtk.org/]) +AC_PREREQ(2.60) +AC_CONFIG_SRCDIR(Makefile.in) +AC_CONFIG_HEADER(include/dcmtk/config/osconfig.h) + +dnl ------------------------------------------------------- +dnl Additional Package Information +dnl ------------------------------------------------------- + +PACKAGE_VERSION_NUMBER=361 +PACKAGE_VERSION_SUFFIX="" +PACKAGE_DATE="DEV" + +AC_DEFINE_UNQUOTED(PACKAGE_VERSION_NUMBER,${PACKAGE_VERSION_NUMBER},[Define to the version number of this package.]) +AC_DEFINE_UNQUOTED(PACKAGE_VERSION_SUFFIX,"${PACKAGE_VERSION_SUFFIX}",[Define to the version suffix of this package.]) +AC_DEFINE_UNQUOTED(PACKAGE_DATE,"${PACKAGE_DATE}",[Define to the release date of this package.]) + +AC_SUBST(PACKAGE_VERSION_NUMBER) +AC_SUBST(PACKAGE_VERSION_SUFFIX) +AC_SUBST(PACKAGE_DATE) + +dnl ------------------------------------------------------- +dnl Identify the host platform we're compiling for, +dnl using config.guess and config.sub. +dnl ------------------------------------------------------- + +AC_CANONICAL_HOST +AC_DEFINE_UNQUOTED(CANONICAL_HOST_TYPE, "${host}", [Define the canonical host system type as a string constant.]) + +case "${host}" in + *-*-cygwin) + BINEXT=".exe" + ;; + *-*-mingw32) + BINEXT=".exe" + ;; + *) + BINEXT="" + ;; +esac + +dnl ------------------------------------------------------- +dnl Configuration Utilities +dnl ------------------------------------------------------- + +if test "x$prefix" = xNONE ; then +AC_DEFINE_UNQUOTED(DCMTK_PREFIX, "${ac_default_prefix}", [Define the DCMTK default path.]) +else +AC_DEFINE_UNQUOTED(DCMTK_PREFIX, "${prefix}", [Define the DCMTK default path.]) +fi + +DATA_DIR="${datadir}" +DATA_DIR=`( + test "$prefix" = NONE && prefix=${ac_default_prefix} + test "$exec_prefix" = NONE && exec_prefix=${prefix} + eval eval echo "$DATA_DIR" +)` +AC_DEFINE_UNQUOTED(DCM_DICT_DEFAULT_PATH, "${DATA_DIR}/dicom.dic", [Define the default data dictionary path for the dcmdata library package.]) +AC_DEFINE_UNQUOTED(DEFAULT_SUPPORT_DATA_DIR, "${DATA_DIR}/", [Define the default directory where support data files reside.]) + +CONF_DIR="${sysconfdir}" +CONF_DIR=`( + test "$prefix" = NONE && prefix=${ac_default_prefix} + test "$exec_prefix" = NONE && exec_prefix=${prefix} + eval echo "$CONF_DIR" +)` +AC_DEFINE_UNQUOTED(DEFAULT_CONFIGURATION_DIR, "${CONF_DIR}/", [Define the default directory where configuration files reside.]) + +AH_VERBATIM([PATH_SEPARATOR], [/* Define path separator. */ +#define PATH_SEPARATOR '/']) + +AH_VERBATIM([ENVIRONMENT_PATH_SEPARATOR], [/* Define the environment variable path separator. */ +#ifndef ENVIRONMENT_PATH_SEPARATOR +#define ENVIRONMENT_PATH_SEPARATOR ':' +#endif]) + +AH_VERBATIM([HAVE_EMPTY_ARGC_ARGV], [/* Define if your system cannot pass command line arguments into main() (e.g. Macintosh). */ +/* #undef HAVE_EMPTY_ARGC_ARGV */]) + +AH_TOP([#ifndef OSCONFIG_H +#define OSCONFIG_H + +/* +** Define enclosures for include files with C linkage (mostly system headers) +*/ +#ifdef __cplusplus +#define BEGIN_EXTERN_C extern "C" { +#define END_EXTERN_C } +#else +#define BEGIN_EXTERN_C +#define END_EXTERN_C +#endif + +/* MinGW needs some special handling because it is a mixture of WIN32 and Posix. + * The following settings are not tested by configure but need to be set for MinGW. + */ +#ifdef __MINGW32__ +#define HAVE_WINDOWS_H 1 +#define HAVE_WINSOCK_H 1 +#define NO_IOS_BASE_ASSIGN 1 +#define ENVIRONMENT_PATH_SEPARATOR ';' +#endif]) + +AH_BOTTOM([#if defined(DCMTK_USE_CXX11_STL) && defined(__cplusplus) && __cplusplus < 201103L +#error\ + DCMTK was configured to use the C++11 STL, but your compiler is not configured\ + for building with C++11 features. +#endif + +#endif /* OSCONFIG_H */]) + + +dnl Include general file +sinclude(general.m4)dnl + +AC_CONFIG_AUX_DIR([.]) + +dnl Checks for programs. + +AC_PROG_INSTALL +AC_PROG_CC +AC_PROG_CPP +AC_CHECK_PROGS(CXX, $CCC c++ cc++ g++ gcc CC cxx, gcc) + +pedantic="" +if test -f /bin/uname ; then + os=`uname -s` + rev=`uname -r` + if test \( "$os" = SunOS \) ; then + case "$rev" in + # only use the -pedantic compiler option on + # Solaris 2 machines. + 5.*) pedantic="-pedantic" ;; + esac + fi +fi +if test "${CXXFLAGS}set" = set ; then + case "$CXX" in + c++|g++|gcc) + CXXFLAGS="-Wall $pedantic" + CFLAGS="-Wall $pedantic" + ;; + cc++) + CXXFLAGS="-Wall" + CFLAGS="-Wall" + ;; + *) + CXXFLAGS="" + CFLAGS="" + ;; + esac +fi + +AC_PROG_CXXCPP +dnl The next test is equivalent to AC_PROG_RANLIB +dnl Do not use AC_PROG_RANLIB because this produces +dnl an error on LINUX-systems in the configure script +AC_CHECK_PROGS(RANLIB, ranlib, :) + +dnl Check for "ar" and "libtool". On certain systems, e.g. NeXTStep, we must +dnl prefer "libtool" over "ar" if both are present. However, we don't use +dnl GNU libtool at the moment which is something completely different +dnl (not an "ar" replacement). +AC_CHECK_PROGS(AR, ar, :) +AC_CHECK_PROGS(LIBTOOL, libtool, :) +if test "${LIBTOOL}set" = libtoolset ; then + AC_CHECK_GNU_LIBTOOL + if test $ac_cv_check_gnu_libtool = yes ; then + : + else + AR=$LIBTOOL + fi +fi + +case "$AR" in +libtool) ARFLAGS=-o ;; +ar) ARFLAGS=cruv ;; +esac + +if test "${LIBEXT}set" = set ; then + LIBEXT="a" +fi + +AC_SUBST(ARFLAGS) +AC_SUBST(LIBEXT) +AC_SUBST(BINEXT) + +# Try to find a strip utility +AC_CHECK_PROGS(STRIP, strip, :) + +dnl ------------------------------------------------------- +dnl Check special systems +dnl ------------------------------------------------------- + +AC_AIX +AC_ISC_POSIX +AC_SYS_LONG_FILE_NAMES + +dnl ------------------------------------------------------- +dnl Perform some tests with the C compiler, needed for dcmjpeg +dnl ------------------------------------------------------- + +AC_MY_C_INLINE +AC_MY_C_CONST +AC_MY_C_CHAR_UNSIGNED +AC_MY_C_RIGHTSHIFT_UNSIGNED + +dnl ------------------------------------------------------- +dnl Check some typedefs versus definitions in , +dnl needed for JasPer support +dnl ------------------------------------------------------- + +AC_TYPEDEF(uchar, unsigned char) +AC_TYPEDEF(ushort, unsigned short) +AC_TYPEDEF(uint, unsigned int) +AC_TYPEDEF(ulong, unsigned long) +AC_CHECK_TYPES(longlong) +AC_CHECK_TYPES(ulonglong) +AC_CHECK_TYPES(long long) +AC_CHECK_TYPES(unsigned long long) +CHECK_VLA + +dnl File access stuff +AC_CHECK_TYPES(fpos64_t) +AC_CHECK_TYPES(off64_t) + +dnl stdbool.h and stdint.h are only defined in ANSI C, not in C++ +AC_CHECK_HEADERS(stdbool.h) +AC_CHECK_HEADERS(stdint.h) +AC_CHECK_HEADERS(cstdint) + +AC_CHECK_TYPES(int64_t) +AC_CHECK_TYPES(uint64_t) + +AC_CHECK_TYPES([sigjmp_buf], [], [], [[#include ]]) + +dnl ------------------------------------------------------- +dnl Checks for libc library functions. +dnl ------------------------------------------------------- + +AC_FUNC_MEMCMP +AC_FUNC_VPRINTF +AC_TYPE_SIGNAL +AC_FUNC_WAIT3 +AC_CHECK_FUNCS(gethostname gethostid socket sysinfo) +AC_CHECK_FUNCS(strchr strstr strtoul itoa) +AC_CHECK_FUNCS(memcpy memset memmove memcmp bcopy bcmp) +AC_CHECK_FUNCS(getpid mktemp tempnam tmpnam getenv mkstemp) +AC_CHECK_FUNCS(stat) +AC_CHECK_FUNCS(malloc_debug) +AC_CHECK_FUNCS(strerror strdup bzero index rindex access) +AC_CHECK_FUNCS(uname cuserid getlogin) +AC_CHECK_FUNCS(usleep) +AC_CHECK_FUNCS(flock lockf) +AC_CHECK_FUNCS(listen connect setsockopt getsockopt select) +AC_CHECK_FUNCS(gethostbyname gethostbyname_r) +AC_CHECK_FUNCS(gethostbyaddr_r getgrnam_r getpwnam_r) +AC_CHECK_FUNCS(bind accept getsockname getaddrinfo) +AC_CHECK_FUNCS(waitpid) +AC_CHECK_FUNCS(getuid geteuid setuid getpwnam getgrnam) +AC_CHECK_FUNCS(sleep fork) +AC_CHECK_FUNCS(_findfirst) +AC_CHECK_FUNCS(strlcpy strlcat) +AC_CHECK_FUNCS(vsnprintf) +AC_CHECK_FUNCS(mbstowcs wcstombs) +AC_CHECK_FUNCS(popen pclose) +AC_FUNC_FSEEKO + + +dnl ------------------------------------------------------- +dnl Checks for libcs library functions needed by oflog +dnl ------------------------------------------------------- + +AC_DEFUN([TYPE_SOCKLEN_T], +[ +AH_TEMPLATE([socklen_t], [Define to int if undefined.]) +AC_CACHE_CHECK([for socklen_t], ac_cv_type_socklen_t, +[ + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include + #include ]], [[socklen_t len = 42; return 0;]])],[ac_cv_type_socklen_t=yes],[ac_cv_type_socklen_t=no]) +]) + if test $ac_cv_type_socklen_t != yes; then + AC_DEFINE(socklen_t, int) + fi +]) + +AC_CHECK_FUNCS(ftime gmtime_r localtime_r lstat nanosleep fcntl) +AC_CHECK_FUNCS(htons htonl ntohs ntohl) +AC_CHECK_HEADERS(netinet/in.h) +AC_CHECK_HEADERS(syslog.h) +TYPE_SOCKLEN_T + +AH_TEMPLATE([HAVE_ENAMETOOLONG]) +AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM([#include ], [int value = ENAMETOOLONG;])], + [AC_DEFINE([HAVE_ENAMETOOLONG], , [Define if your system provides ENAMETOOLONG errno value.])]) + +dnl ------------------------------------------------------- +dnl Checks for libm library functions. +dnl ------------------------------------------------------- + +SAVELIBS="$LIBS" +LIBS="$LIBS -lm" +AC_CHECK_FUNCS(finite isinf isnan) +LIBS="$SAVELIBS" + +dnl ------------------------------------------------------- +dnl Perform remaining tests with C++ compiler +dnl ------------------------------------------------------- +AC_LANG(C++) + +AC_CXX_CONST_CAST +AC_CXX_DYNAMIC_CAST +AC_CXX_REINTERPRET_CAST +AC_CXX_STATIC_CAST +AC_CXX_STD_NOTHROW +AC_CXX_NOTHROW_DELETE + +dnl ------------------------------------------------------- +dnl Check for Debug Mode +dnl ------------------------------------------------------- + +DEBUG="-DNDEBUG" +DEBUGCXXFLAGS= +DEBUGCFLAGS= +AC_MSG_CHECKING(whether to compile in debug mode) +AC_ARG_ENABLE(debug, +[ --enable-debug compile with debug code, don't optimize + --disable-debug compile without debug code (default)], +[ case "$enableval" in + yes) + AC_MSG_RESULT(yes) + DEBUGCXXFLAGS="-g" + DEBUGCFLAGS="-g" + DEBUG="-DDEBUG" + ;; + *) + AC_MSG_RESULT(no) + DEBUGCXXFLAGS="-O" + DEBUGCFLAGS="-O" + ;; + esac ], + AC_MSG_RESULT(no) + DEBUGCXXFLAGS="-O" + DEBUGCFLAGS="-O" +) + +dnl ------------------------------------------------------- +dnl Check for thread support +dnl ------------------------------------------------------- + +THREADSUPPORT="auto" +AC_MSG_CHECKING(whether to enable thread support) +AC_ARG_ENABLE(threads, +[ --enable-threads=TYPE compile with MT support (posix/solaris/auto=default) + --disable-threads compile without MT support], +[ case "$enableval" in + yes|auto) + AC_MSG_RESULT(automatic detection) + ;; + posix) + AC_MSG_RESULT([yes, type=posix]) + THREADSUPPORT="posix" + ;; + solaris) + AC_MSG_RESULT([yes, type=solaris]) + THREADSUPPORT="solaris" + ;; + no) + AC_MSG_RESULT(no) + THREADSUPPORT="no" + ;; + *) + AC_MSG_RESULT([yes - type $enableval is unknown - using automatic detection]) + ;; + esac ], + AC_MSG_RESULT(automatic detection) +) + +dnl ------------------------------------------------------- +dnl Check for large file support +dnl ------------------------------------------------------- + +LFSSUPPORT="auto" +AC_MSG_CHECKING(whether to enable large file support) +AC_ARG_ENABLE(lfs, +[ --enable-lfs=TYPE compile with LFS support (lfs/lfs64/auto=default) + --disable-lfs compile without LFS support], +[ case "$enableval" in + yes|auto) + AC_MSG_RESULT(automatic detection) + ;; + lfs) + AC_MSG_RESULT([yes, type=LFS]) + LFSSUPPORT="lfs" + ;; + lfs64) + AC_MSG_RESULT([yes, type=LFS64]) + LFSSUPPORT="lfs64" + ;; + no) + AC_MSG_RESULT(no) + LFSSUPPORT="no" + ;; + *) + AC_MSG_RESULT([yes - type $enableval is unknown - using automatic detection]) + ;; + esac ], + AC_MSG_RESULT(automatic detection) +) + +dnl ------------------------------------------------------- +dnl Checks for libraries. +dnl ------------------------------------------------------- + +AC_CHECK_GXXLIB +AC_CHECK_LIB(iostream, main) +dnl Some C++ compilers have problems with recursive main calls +dnl (e.g. Sun C++ 4.2). In this case we must test another function +dnl to link. +AC_CHECK_LIB(nsl, main) +if test $ac_cv_lib_nsl_main = no ; then +AC_CHECK_LIB(nsl, gethostbyname) +fi +AC_CHECK_LIB(socket, main) +if test $ac_cv_lib_socket_main = no ; then +AC_CHECK_LIB(socket, socket) +fi + +dnl Some newer versions of OpenSSL must be linked against libdl. +dnl We just check whether libdl exists and in this case always +dnl add -ldl to OPENSSLLIBS. +dnl +OPENSSLLIBS="" +AC_CHECK_LIB(dl, main,[ +OPENSSLLIBS="-ldl" +]) +if test $ac_cv_lib_dl_main = no ; then +AC_CHECK_LIB(dl, dlopen,[ +OPENSSLLIBS="-ldl" +]) +fi + +MATHLIBS="" +AC_CHECK_LIB(m, main,[ +MATHLIBS="-lm" +]) +if test $ac_cv_lib_m_main = no ; then +AC_CHECK_LIB(m, sin,[ +MATHLIBS="-lm" +]) +fi + +dnl On MinGW we have to link against the winsock32 library +dnl +AC_CHECK_LIB(wsock32, main,[ +LIBS="$LIBS -lwsock32" +]) + +dnl On MinGW we have to link against the netapi32 library +dnl +AC_CHECK_LIB(netapi32, main,[ +LIBS="$LIBS -lnetapi32" +]) + +dnl ------------------------------------------------------- +dnl Checks for header files. +dnl ------------------------------------------------------- + +AC_HEADER_STDC +AC_HEADER_SYS_WAIT +AC_HEADER_DIRENT +AC_CHECK_TCP_H +AC_CHECK_HEADERS(alloca.h) +AC_CHECK_HEADERS(arpa/inet.h) +AC_CHECK_HEADERS(assert.h) +AC_CHECK_HEADERS(ctype.h) +AC_CHECK_HEADERS(errno.h) +AC_CHECK_HEADERS(fcntl.h) +AC_CHECK_HEADERS(float.h) +AC_CHECK_HEADERS(fnmatch.h) +AC_CHECK_HEADERS(fstream) +AC_CHECK_HEADERS(fstream.h) +AC_CHECK_HEADERS(grp.h) +AC_CHECK_HEADERS(ieeefp.h) +AC_CHECK_HEADERS(io.h) +AC_CHECK_HEADERS(iomanip) +AC_CHECK_HEADERS(iomanip.h) +AC_CHECK_HEADERS(iostream) +AC_CHECK_HEADERS(iostream.h) +AC_CHECK_HEADERS(iso646.h) +AC_CHECK_HEADERS(libc.h) +AC_CHECK_HEADERS(limits.h) +AC_CHECK_HEADERS(climits) +AC_CHECK_HEADERS(locale.h) +AC_CHECK_HEADERS(malloc.h) +AC_CHECK_HEADERS(math.h) +AC_CHECK_HEADERS(cmath) +AC_CHECK_HEADERS(new) +AC_CHECK_HEADERS(new.h) +AC_CHECK_HEADERS(netdb.h) +AC_CHECK_HEADERS(pthread.h) +AC_CHECK_HEADERS(pwd.h) +AC_CHECK_HEADERS(semaphore.h) +AC_CHECK_HEADERS(setjmp.h) +AC_CHECK_HEADERS(signal.h) +AC_CHECK_HEADERS(sstream) +AC_CHECK_HEADERS(sstream.h) +AC_CHECK_HEADERS(stat.h) +AC_CHECK_HEADERS(cstdarg) +AC_CHECK_HEADERS(stdarg.h) +AC_CHECK_HEADERS(stddef.h) +AC_CHECK_HEADERS(cstddef) +AC_CHECK_HEADERS(cstdio) +AC_CHECK_HEADERS(stdio.h) +AC_CHECK_HEADERS(stdint.h) +AC_CHECK_HEADERS(stdlib.h) +AC_CHECK_HEADERS(string.h) +AC_CHECK_HEADERS(strings.h) +AC_CHECK_HEADERS(strstrea.h) +AC_CHECK_HEADERS(strstream) +AC_CHECK_HEADERS(strstream.h) +AC_CHECK_HEADERS(synch.h) +AC_CHECK_HEADERS(sys/errno.h) +AC_CHECK_HEADERS(sys/file.h) +AC_CHECK_HEADERS(sys/param.h) +AC_CHECK_HEADERS(sys/resource.h) +AC_CHECK_HEADERS(sys/select.h) +AC_CHECK_HEADERS(sys/socket.h) +AC_CHECK_HEADERS(sys/stat.h) +AC_CHECK_HEADERS(sys/syscall.h) +AC_CHECK_HEADERS(sys/systeminfo.h) +AC_CHECK_HEADERS(sys/time.h) +AC_CHECK_HEADERS(sys/timeb.h) +AC_CHECK_HEADERS(sys/types.h) +AC_CHECK_HEADERS(sys/utime.h) +AC_CHECK_HEADERS(sys/utsname.h) +AC_CHECK_HEADERS(thread.h) +AC_CHECK_HEADERS(time.h) +AC_CHECK_HEADERS(unistd.h) +AC_CHECK_HEADERS(unix.h) +AC_CHECK_HEADERS(utime.h) +AC_CHECK_HEADERS(wchar.h) +AC_CHECK_HEADERS(wctype.h) +AC_CHECK_HEADERS(fenv.h) + +if test $ac_cv_header_libc_h = yes ; then + if test $ac_cv_header_math_h = yes ; then + AC_CXX_LIBC_H_EXTERN_C + fi +fi + +dnl ------------------------------------------------------- +dnl Tests for pointer vs. integer types +dnl These tests REQUIRE as a prerequisite AC_CXX_STATIC_CAST +dnl ------------------------------------------------------- + +if test $ac_cv_header_pthread_h = yes ; then + AC_CHECK_POINTER_TYPE(pthread_t, pthread.h) +fi + +dnl ------------------------------------------------------- +dnl Check for thread support +dnl ------------------------------------------------------- + +dnl +dnl in auto mode, check whether we use solaris or posix threads +dnl +if test $THREADSUPPORT = auto ; then + if test $ac_cv_header_synch_h = yes ; then + THREADSUPPORT="solaris" + fi +fi +if test $THREADSUPPORT = auto ; then + if test $ac_cv_header_pthread_h = yes ; then + THREADSUPPORT="posix" + fi +fi +if test $THREADSUPPORT = auto ; then + THREADSUPPORT="no" +fi + +dnl +dnl in solaris mode, check for -lthread +dnl + +if test $THREADSUPPORT = solaris ; then + AC_CHECK_LIB(thread, sema_init, [ + ac_tr_lib=HAVE_LIBTHREAD + AC_DEFINE_UNQUOTED($ac_tr_lib) + LIBS="-lthread $LIBS" + ]) +fi + +if test $THREADSUPPORT = posix ; then + dnl + dnl check Posix MT libraries -lrt and -lpthread + dnl OSF/1 re-#defines most of the pthread function names. + dnl This is why we use pthread_key_create for the test. + dnl + AC_CHECK_LIB(pthread, pthread_key_create, [ + ac_tr_lib=HAVE_LIBPTHREAD + AC_DEFINE_UNQUOTED($ac_tr_lib) + LIBS="-lpthread $LIBS" + ]) + + AC_CHECK_LIB(rt, sem_init, [ + ac_tr_lib=HAVE_LIBRT + AC_DEFINE_UNQUOTED($ac_tr_lib) + LIBS="-lrt $LIBS" + ], , $LIBS ) + + dnl + dnl check whether the compiler required the -pthread option + dnl to correctly link code containing posix thread calls. + dnl This is true on FreeBSD. + dnl + AC_CHECK_PTHREAD_OPTION + + dnl + dnl check whether Posix read/write locks are available + dnl + POSIXRWLOCKSAVAILABLE="no" + AC_CHECK_LIB(pthread, pthread_rwlock_init, [ + AC_DEFINE(HAVE_PTHREAD_RWLOCK, , [Define if your system supports POSIX read/write locks.]) + dnl + dnl we're going to use POSIX threads with read/write locks. + dnl Linux 2.2.x only declares all prototypes if _XOPEN_SOURCE=500 and _BSD_SOURCE + dnl OSF/1 requires _XOPEN_SOURCE=500, _XOPEN_SOURCE_EXTENDED, _OSF_SOURCE and _POSIX_C_SOURCE=199506L + dnl Irix 6.x does not like _XOPEN_SOURCE=500 and _POSIX_C_SOURCE=199506L + dnl + POSIXRWLOCKSAVAILABLE="yes" + case "${host}" in + mips-sgi-irix6*) + CXXFLAGS="-D_XOPEN_SOURCE_EXTENDED -D_BSD_SOURCE -D_BSD_COMPAT $CXXFLAGS" + CFLAGS="-D_XOPEN_SOURCE_EXTENDED -D_BSD_SOURCE -D_BSD_COMPAT $CFLAGS" + ;; + *-*-openbsd3*) + CXXFLAGS="-D_POSIX_C_SOURCE=199506L $CXXFLAGS" + CFLAGS="-D_POSIX_C_SOURCE=199506L $CFLAGS" + ;; + *-*-openbsd4*) + ;; + *-*-openbsd5*) + ;; + *-*-freebsd*) + ;; + *-*-netbsdelf2*) + ;; + *-*-darwin*) + dnl On Mac OS X we need to have _DARWIN_C_SOURCE defined to enable UNIX standard API for system headers + CXXFLAGS="-D_XOPEN_SOURCE_EXTENDED -D_BSD_SOURCE -D_BSD_COMPAT -D_OSF_SOURCE -D_DARWIN_C_SOURCE $CXXFLAGS" + CFLAGS="-D_XOPEN_SOURCE_EXTENDED -D_BSD_SOURCE -D_BSD_COMPAT -D_OSF_SOURCE -D_DARWIN_C_SOURCE $CXXFLAGS" + ;; + *) + CXXFLAGS="-D_XOPEN_SOURCE_EXTENDED -D_XOPEN_SOURCE=500 -D_BSD_SOURCE -D_DEFAULT_SOURCE -D_BSD_COMPAT -D_OSF_SOURCE -D_POSIX_C_SOURCE=199506L $CXXFLAGS" + CFLAGS="-D_XOPEN_SOURCE_EXTENDED -D_XOPEN_SOURCE=500 -D_BSD_SOURCE -D_DEFAULT_SOURCE -D_BSD_COMPAT -D_OSF_SOURCE -D_POSIX_C_SOURCE=199506L $CFLAGS" + ;; + esac + ], + [ + dnl + dnl We did not find pthread_rwlock_init in libpthread. Maybe it is somewhere else, e.g. in libc_r on FreeBSD. + dnl We give it another try by just linking against the default libraries. + dnl + AC_MSG_CHECKING(for pthread_rwlock_init in default libraries) + AC_TRY_LINK([extern "C" int pthread_rwlock_init(void *rwlock, void *attr); + ] , [(void) pthread_rwlock_init(NULL, NULL);], [ + AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_PTHREAD_RWLOCK, , [Define if your system supports POSIX read/write locks.]) + dnl + dnl we're going to use POSIX threads with read/write locks. + dnl Linux 2.2.x only declares all prototypes if _XOPEN_SOURCE=500 and _BSD_SOURCE + dnl OSF/1 requires _XOPEN_SOURCE=500, _XOPEN_SOURCE_EXTENDED, _OSF_SOURCE and _POSIX_C_SOURCE=199506L + dnl Irix 6.x does not like _XOPEN_SOURCE=500 and _POSIX_C_SOURCE=199506L + dnl + POSIXRWLOCKSAVAILABLE="yes" + case "${host}" in + mips-sgi-irix6*) + CXXFLAGS="-D_XOPEN_SOURCE_EXTENDED -D_BSD_SOURCE -D_BSD_COMPAT $CXXFLAGS" + CFLAGS="-D_XOPEN_SOURCE_EXTENDED -D_BSD_SOURCE -D_BSD_COMPAT $CFLAGS" + ;; + *-*-openbsd3*) + CXXFLAGS="-D_POSIX_C_SOURCE=199506L $CXXFLAGS" + CFLAGS="-D_POSIX_C_SOURCE=199506L $CFLAGS" + ;; + *-*-openbsd4*) + ;; + *-*-openbsd5*) + ;; + *-*-freebsd*) + ;; + *-*-netbsdelf2*) + ;; + *-*-darwin*) + dnl On Mac OS X we need to have _DARWIN_C_SOURCE source defined to enable UNIX standard API for system headers + CXXFLAGS="-D_XOPEN_SOURCE_EXTENDED -D_BSD_SOURCE -D_BSD_COMPAT -D_OSF_SOURCE -D_DARWIN_C_SOURCE $CXXFLAGS" + CFLAGS="-D_XOPEN_SOURCE_EXTENDED -D_BSD_SOURCE -D_BSD_COMPAT -D_OSF_SOURCE -D_DARWIN_C_SOURCE $CXXFLAGS" + ;; + *) + CXXFLAGS="-D_XOPEN_SOURCE_EXTENDED -D_XOPEN_SOURCE=500 -D_BSD_SOURCE -D_DEFAULT_SOURCE -D_BSD_COMPAT -D_OSF_SOURCE -D_POSIX_C_SOURCE=199506L $CXXFLAGS" + CFLAGS="-D_XOPEN_SOURCE_EXTENDED -D_XOPEN_SOURCE=500 -D_BSD_SOURCE -D_DEFAULT_SOURCE -D_BSD_COMPAT -D_OSF_SOURCE -D_POSIX_C_SOURCE=199506L $CFLAGS" + ;; + esac + ], AC_MSG_RESULT(no)) + ] + ) +fi + +AC_MSG_CHECKING(multi-thread support) +case "$THREADSUPPORT" in + solaris) + AC_MSG_RESULT([yes, solaris threads]) + CXXFLAGS="-D_REENTRANT $CXXFLAGS" + CFLAGS="-D_REENTRANT $CFLAGS" + AC_DEFINE(WITH_THREADS, , [Define if we are compiling with any type of multi-thread support.]) + ;; + posix) + if test $POSIXRWLOCKSAVAILABLE = yes ; then + AC_MSG_RESULT([yes, posix threads with rwlock]) + else + AC_MSG_RESULT([yes, posix threads without rwlock]) + fi + CXXFLAGS="-D_REENTRANT $CXXFLAGS" + CFLAGS="-D_REENTRANT $CFLAGS" + AC_DEFINE(WITH_THREADS, , [Define if we are compiling with any type of multi-thread support.]) + ;; + *) + AC_MSG_RESULT(none) + ;; +esac + +dnl ------------------------------------------------------- +dnl Check for LFS support +dnl ------------------------------------------------------- + +if test $LFSSUPPORT = auto -o $LFSSUPPORT = lfs64; then + AC_LFS64 + if test $ac_cv_lfs64_support = yes ; then + LFSSUPPORT="lfs64" + fi +fi + +if test $LFSSUPPORT = auto -o $LFSSUPPORT = lfs; then + MY_AC_SYS_LARGEFILE +fi + +dnl ------------------------------------------------------- +dnl Checks for typedefs, structures, and compiler characteristics. +dnl ------------------------------------------------------- + +AC_TYPEDEF(size_t, unsigned) +AC_TYPEDEF(ssize_t, long) +AC_TYPEDEF(pid_t, int) +AC_C_CHAR_UNSIGNED +AC_CHECK_SIZEOF(char) +AC_CHECK_SIZEOF(short) +AC_CHECK_SIZEOF(int) +AC_CHECK_SIZEOF(long) +AC_CHECK_SIZEOF(float) +AC_CHECK_SIZEOF(double) +AC_CHECK_SIZEOF(void *) +AC_STRUCT_TM +AC_MY_SYMBOL_EXISTS([__FUNCTION__]) +AC_MY_SYMBOL_EXISTS([__PRETTY_FUNCTION__]) +AC_MY_SYMBOL_EXISTS([__func__]) + +dnl ------------------------------------------------------- +dnl Checks for prototypes +dnl ------------------------------------------------------- +dnl +dnl The following AC_CHECK_* macros _must_ have corresponding entries in +dnl the acconfig.h file. This is because the macros are specific to the +dnl DCMTK project and are not supported by GNU autoheader. + +AC_CHECK_PROTOTYPE(_stricmp, string.h) +AC_CHECK_PROTOTYPE(accept, sys/types.h sys/socket.h) +if test $ac_cv_prototype_accept = yes ; then +AC_CHECK_INTP_ACCEPT(sys/types.h sys/socket.h) +fi +AC_CHECK_PROTOTYPE(bind, sys/types.h sys/socket.h) +AC_CHECK_PROTOTYPE(bzero, string.h strings.h libc.h unistd.h stdlib.h) +AC_CHECK_PROTOTYPE(connect, sys/types.h sys/socket.h) +AC_CHECK_PROTOTYPE(finite, math.h) +AC_CHECK_PROTOTYPE(isinf, math.h) +AC_CHECK_PROTOTYPE(isnan, math.h) +AC_CHECK_PROTOTYPE(std::finite, cmath) +AC_CHECK_PROTOTYPE(std::isinf, cmath) +AC_CHECK_PROTOTYPE(std::isnan, cmath) +AC_CHECK_PROTOTYPE(flock, sys/file.h) +AC_CHECK_PROTOTYPE(gethostbyname, libc.h unistd.h stdlib.h netdb.h) +AC_CHECK_PROTOTYPE(gethostbyname_r, libc.h unistd.h stdlib.h netdb.h) +AC_CHECK_PROTOTYPE(gethostid, libc.h unistd.h stdlib.h netdb.h) +AC_CHECK_PROTOTYPE(gethostname, unistd.h libc.h stdlib.h netdb.h) +AC_CHECK_PROTOTYPE(getsockname, sys/types.h sys/socket.h) +AC_CHECK_PROTOTYPE(getsockopt, sys/types.h sys/socket.h) +AC_CHECK_PROTOTYPE(strerror_r, string.h) +if test $ac_cv_prototype_strerror_r = yes ; then +AC_CHECK_CHARP_STRERROR_R(string.h) +fi +if test $ac_cv_prototype_getsockopt = yes ; then +AC_CHECK_INTP_GETSOCKOPT(sys/types.h sys/socket.h) +fi +AC_CHECK_PROTOTYPE(gettimeofday, sys/time.h unistd.h) +AC_CHECK_PROTOTYPE(listen, sys/types.h sys/socket.h) +AC_CHECK_PROTOTYPE(mktemp, libc.h unistd.h stdlib.h) +AC_CHECK_PROTOTYPE(mkstemp, libc.h unistd.h stdlib.h) +AC_CHECK_PROTOTYPE(select, sys/select.h sys/types.h sys/socket.h sys/time.h) +if test $ac_cv_prototype_select = yes ; then +AC_CHECK_INTP_SELECT(sys/select.h sys/types.h sys/socket.h sys/time.h) +fi +AC_CHECK_PROTOTYPE(setsockopt, sys/types.h sys/socket.h) +AC_CHECK_PROTOTYPE(socket, sys/types.h sys/socket.h) +AC_CHECK_PROTOTYPE(strcasecmp, string.h) +AC_CHECK_PROTOTYPE(strncasecmp, string.h) +AC_CHECK_PROTOTYPE(usleep, libc.h unistd.h stdlib.h) +AC_CHECK_PROTOTYPE(vsnprintf, stdio.h stdarg.h) +AC_CHECK_PROTOTYPE(wait3, libc.h sys/wait.h sys/time.h sys/resource.h) +AC_CHECK_PROTOTYPE(waitpid, sys/wait.h sys/time.h sys/resource.h) +AC_CHECK_DECLARATION(struct utimbuf, sys/types.h utime.h sys/utime.h) +AC_CHECK_DECLARATION(socklen_t, sys/types.h sys/socket.h) +AC_CHECK_OLD_READDIR_R +AC_CHECK_ELLIPSE_SIGNAL_HANDLER(signal.h) +if test $ac_cv_header_math_h = yes ; then +AC_INCLUDE_MATH_H_AS_CXX +fi + +dnl ------------------------------------------------------- +dnl Checks for the usage of standard C++ headers. +dnl ------------------------------------------------------- + +AC_MSG_CHECKING(whether to use C++ standard includes) +ac_use_std_includes="auto" +AC_ARG_ENABLE(std-includes, +[ --enable-std-includes use C++ ANSI standard includes (default: auto) + --disable-std-includes use old C++ includes ], +[ case "$enableval" in + yes) + ac_use_std_includes="yes" + ;; + + *) + ac_use_std_includes="no" + ;; + esac ] +) + +if test "$ac_cv_header_fstream" = "yes" -a "$ac_cv_header_iostream" = "yes" -a "$ac_cv_header_iomanip" = "yes"; then + ac_have_std_includes="yes" +else + ac_have_std_includes="no" +fi + +if test "$ac_cv_header_fstream_h" = "yes" -a "$ac_cv_header_iostream_h" = "yes" -a "$ac_cv_header_iomanip_h" = "yes"; then + ac_have_old_includes="yes" +else + ac_have_old_includes="no" +fi + +if test "$ac_use_std_includes" = "yes"; then + AC_MSG_RESULT(yes) + AC_DEFINE(USE_STD_CXX_INCLUDES, , [Define if ANSI standard C++ includes are used.]) +elif test "$ac_use_std_includes" = "no"; then + AC_MSG_RESULT(no) +elif test "$ac_have_std_includes" = "yes"; then + AC_MSG_RESULT(yes) + AC_DEFINE(USE_STD_CXX_INCLUDES, , [Define if ANSI standard C++ includes are used.]) + ac_use_std_includes="yes" +else + AC_MSG_RESULT(no) + ac_use_std_includes="no" +fi + +if test "$ac_use_std_includes" = "yes"; then + AC_CHECK_STD_NAMESPACE + AC_CHECK_DECLARATION(std::ios_base::openmode, , iostream) + AC_CHECK_IOS_NOCREATE(std::ios, fstream) + AC_CHECK_COMPILES(std::vfprintf, cstdarg cstdio, + [FILE *stream; va_list ap; std::vfprintf(stream, "", ap);]) + AC_CHECK_COMPILES(std::vsnprintf, cstdarg cstdio, + [char buf[256]; va_list ap; std::vsnprintf(buf, 0, "", ap);]) +else + AC_CHECK_DECLARATION(std::ios_base::openmode, , iostream.h) + AC_CHECK_IOS_NOCREATE(ios, fstream.h) + AC_CHECK_COMPILES(std::vfprintf, stdarg.h stdio.h, + [FILE *stream; va_list ap; std::vfprintf(stream, "", ap);]) + AC_CHECK_COMPILES(std::vsnprintf, stdarg.h stdio.h, + [char buf[256]; va_list ap; std::vsnprintf(buf, 0, "", ap);]) +fi + +AC_CHECK_CLASS_TEMPLATE +AC_CHECK_STATIC_TEMPLATE_METHOD +AC_CHECK_FUNCTION_TEMPLATE +AC_CHECK_EXPLICIT_TEMPLATE_SPECIALIZATION +AC_CHECK_CXX_BOOL +AC_CHECK_CXX_VOLATILE +AC_CXX_TYPENAME +AC_STDIO_NAMESPACE + +dnl ------------------------------------------------------- +dnl Check for Private Tag support +dnl ------------------------------------------------------- + +AC_MSG_CHECKING(whether to enable private tag dictionary) +AC_ARG_ENABLE(private-tags, +[ --enable-private-tags enable private tag dictionary + --disable-private-tags don't enable private tag dictionary (default)], +[ case "$enableval" in + yes) + AC_MSG_RESULT(yes) + AC_DEFINE(ENABLE_PRIVATE_TAGS, , [Define if we are compiling for enabling external private tag dictionary.]) + AC_DEFINE_UNQUOTED(DCM_DICT_DEFAULT_PATH, "${DATA_DIR}/dicom.dic:${DATA_DIR}/private.dic", [Define the default data dictionary path for the dcmdata library package.]) + ;; + *) + AC_MSG_RESULT(no) + ;; + esac ], + AC_MSG_RESULT(no) +) + +dnl ------------------------------------------------------- +dnl Check for External Dictionary support +dnl ------------------------------------------------------- + +AC_MSG_CHECKING(whether to enable loading external dictionary from default path) +AC_ARG_ENABLE(external-dict, +[ --enable-external-dict enable loading of external dictionary (default) + --disable-external-dict don't load external dictionary], +[ case "$enableval" in + yes) + AC_MSG_RESULT(yes) + AC_DEFINE(ENABLE_EXTERNAL_DICTIONARY, , [Define if we are compiling for loading external dictionary from default path.]) + ;; + *) + AC_MSG_RESULT(no) + dnl Reset default path so the dictionary is not loaded automatically on startup + AC_DEFINE_UNQUOTED(DCM_DICT_DEFAULT_PATH, "", [Empty default data dictionary path for the dcmdata library package.]) + ;; + esac ], + AC_MSG_RESULT(yes) + AC_DEFINE(ENABLE_EXTERNAL_DICTIONARY, , [Define if we are compiling for loading external dictionary from default path.]) +) + +dnl ------------------------------------------------------- +dnl Check for Built-in (compiled-in) Dictionary support +dnl ------------------------------------------------------- + +AC_MSG_CHECKING(whether to enable built-in dictionary loading) +AC_ARG_ENABLE(builtin-dict, +[ --enable-builtin-dict enable loading of built-in dictionary + --disable-builtin-dict don't load built-in dictionary (default)], +[ case "$enableval" in + yes) + AC_MSG_RESULT(yes) + dnl Remember for later evaluation when building dcmdata libary, i.e. for + dnl including the populated dictionary object and not the + dnl empty dummy dictionary in dcmdata + DCMTK_ENABLE_BUILTIN_DICTIONARY=true + AC_DEFINE(ENABLE_BUILTIN_DICTIONARY, , [Define if we are compiling for loading external dictionary from default path.]) + ;; + *) + AC_MSG_RESULT(no) + ;; + esac ], + AC_MSG_RESULT(no) +) + +dnl ------------------------------------------------------- +dnl Check for OpenSSL support +dnl ------------------------------------------------------- + +AC_MY_LIB_PATH([openssl], [OpenSSL]) + +AC_MSG_CHECKING([whether to include OpenSSL support]) +AC_ARG_WITH(openssl, +[AS_HELP_STRING([--with-openssl], [include OpenSSL support (default: auto)]) +AS_HELP_STRING([--without-openssl], [don't include OpenSSL support])], +[ case "$withval" in + yes) + AC_MSG_RESULT(yes) + AC_DEFINE(WITH_OPENSSL, , [Define if we are compiling with OpenSSL support.]) + OPENSSLLIBS="-lssl -lcrypto $OPENSSLLIBS" + ;; + *) + AC_MSG_RESULT(no) + ;; + esac ], +[ SAVELIBS="$LIBS" + LIBS="$LIBS -lssl -lcrypto" + AC_TRY_LINK([#include ], [(void) TLSv1_method()], + [ AC_MSG_RESULT(yes) + AC_DEFINE(WITH_OPENSSL, , [Define if we are compiling with OpenSSL support.]) + OPENSSLLIBS="-lssl -lcrypto $OPENSSLLIBS" ], + [AC_MSG_RESULT(no)]) + LIBS="$SAVELIBS"] ) + +AC_CHECK_SSL_CTX_GET0_PARAM +AC_CHECK_RAND_EGD + +dnl ------------------------------------------------------- +dnl Check for libjpeg, which is needed by libtiff on some platforms +dnl ------------------------------------------------------- + +JPEGLIBS="" +AC_CHECK_LIB(jpeg, jpeg_set_defaults,[ +JPEGLIBS="-ljpeg" +]) +if test $ac_cv_lib_jpeg_jpeg_set_defaults = no ; then +AC_CHECK_LIB(jpeg, jSetDefaults,[ +JPEGLIBS="-ljpeg" +]) +fi + +dnl ------------------------------------------------------- +dnl Check for zlib support +dnl ------------------------------------------------------- + +AC_MY_LIB_PATH([zlib]) + +ZLIBLIBS="" +AC_MSG_CHECKING(whether to include zlib support) +AC_ARG_WITH(zlib, +[AS_HELP_STRING([--with-zlib], [include zlib support (default: auto)]) +AS_HELP_STRING([--without-zlib], [don't include zlib support])], +[ case "$withval" in + yes) + AC_MSG_RESULT(yes) + AC_DEFINE(WITH_ZLIB, , [Define if we are compiling with zlib support.]) + ZLIBLIBS="-lz" + ;; + *) + AC_MSG_RESULT(no) + ;; + esac ], +[ SAVELIBS="$LIBS" + LIBS="$LIBS -lz" + AC_TRY_LINK([#include ], [(void) zlibVersion()], + [ AC_MSG_RESULT(yes) + AC_DEFINE(WITH_ZLIB, , [Define if we are compiling with zlib support.]) + ZLIBLIBS="-lz" ], + [AC_MSG_RESULT(no)]) + LIBS="$SAVELIBS"] ) + +dnl ------------------------------------------------------- +dnl Check for libtiff support +dnl ------------------------------------------------------- + +AC_MY_LIB_PATH([libtiff]) + +TIFFLIBS="" +AC_MSG_CHECKING(whether to include libtiff support) +AC_ARG_WITH(libtiff, +[AS_HELP_STRING([--with-libtiff], [include libtiff support (default: auto)]) +AS_HELP_STRING([--without-libtiff], [don't include libtiff support])], +[ case "$withval" in + yes) + AC_MSG_RESULT(yes) + AC_DEFINE(WITH_LIBTIFF, , [Define if we are compiling with libtiff support.]) + TIFFLIBS="-ltiff $JPEGLIBS $ZLIBLIBS" + SAVELIBS="$LIBS" + LIBS="$LIBS -ltiff $JPEGLIBS $ZLIBLIBS" + AC_LIBTIFF_LZW_COMPRESSION + LIBS="$SAVELIBS" + ;; + *) + AC_MSG_RESULT(no) + ;; + esac ], +[ SAVELIBS="$LIBS" + LIBS="$LIBS -ltiff $JPEGLIBS $ZLIBLIBS" + AC_TRY_LINK([#include ], [(void) TIFFGetVersion()], + [ AC_MSG_RESULT(yes) + AC_DEFINE(WITH_LIBTIFF, , [Define if we are compiling with libtiff support.]) + TIFFLIBS="-ltiff $JPEGLIBS $ZLIBLIBS" + AC_LIBTIFF_LZW_COMPRESSION + ], + [AC_MSG_RESULT(no)]) + LIBS="$SAVELIBS"] ) + + +dnl ------------------------------------------------------- +dnl Check for libpng support +dnl ------------------------------------------------------- + +AC_MY_LIB_PATH([libpng]) + +dnl perform check for only after we have evaluated --with-libpnginc +AC_CHECK_HEADERS(libpng/png.h) + +PNGLIBS="" +AC_MSG_CHECKING(whether to include libpng support) +AC_ARG_WITH(libpng, +[AS_HELP_STRING([--with-libpng], [include libpng support (default: auto)]) +AS_HELP_STRING([--without-libpng], [don't include libpng support])], +[ case "$withval" in + yes) + if test "x$ZLIBLIBS" != x; then + AC_MSG_RESULT(yes) + AC_DEFINE(WITH_LIBPNG, , [Define if we are compiling with libpng support.]) + PNGLIBS="-lpng" + else + AC_MSG_RESULT(no because libpng requires zlib) + fi + ;; + *) + AC_MSG_RESULT(no) + ;; + esac ], +[ if test "x$ZLIBLIBS" != x; then + SAVELIBS="$LIBS" + LIBS="$LIBS -lpng $ZLIBLIBS" + + AC_TRY_LINK([#ifdef HAVE_LIBPNG_PNG_H +#include +#else +#include +#endif], [(void) png_access_version_number()], + [ AC_MSG_RESULT(yes) + AC_DEFINE(WITH_LIBPNG, , [Define if we are compiling with libpng support.]) + PNGLIBS="-lpng" ], + [AC_MSG_RESULT(no)]) + + LIBS="$SAVELIBS" + else + AC_MSG_RESULT(no because libpng requires zlib) + fi +] ) + +dnl ------------------------------------------------------- +dnl Check for libxml support +dnl ------------------------------------------------------- + +AC_MY_LIB_PATH([libxml]) + +LIBXMLCFLAGS=`xml2-config --cflags 2>/dev/null` +if test "${LIBXMLCFLAGS+set}" = set; then + CXXFLAGS="$LIBXMLCFLAGS $CXXFLAGS" + CFLAGS="$LIBXMLCFLAGS $CFLAGS" +fi + +XMLLIBS="" +AC_MSG_CHECKING(whether to include libxml support) +AC_ARG_WITH(libxml, +[AS_HELP_STRING([--with-libxml], [include libxml support (default: auto)]) +AS_HELP_STRING([--without-libxml], [don't include libxml support])], +[ case "$withval" in + yes) + AC_MSG_RESULT(yes) + AC_DEFINE(WITH_LIBXML, , [Define if we are compiling with libxml support.]) + XMLLIBS="-lxml2" + ;; + *) + AC_MSG_RESULT(no) + ;; + esac ], +[ SAVELIBS="$LIBS" + LIBS="$LIBS -lxml2 $ZLIBLIBS" + AC_TRY_LINK([#include ], [(void) xmlInitParser()], + [ AC_MSG_RESULT(yes) + AC_DEFINE(WITH_LIBXML, , [Define if we are compiling with libxml support.]) + XMLLIBS="-lxml2" ], + [AC_MSG_RESULT(no)]) + LIBS="$SAVELIBS"] ) + +dnl ------------------------------------------------------- +dnl Check for libwrap (TCP wrapper) support +dnl ------------------------------------------------------- + +AC_MY_LIB_PATH([libwrap]) + +TCPWRAPPERLIBS="" +AC_MSG_CHECKING(whether to include libwrap support) +AC_ARG_WITH(libwrap, +[AS_HELP_STRING([--with-libwrap], [include libwrap support (default: auto)]) +AS_HELP_STRING([--without-libwrap], [don't include libwrap support])], +[ case "$withval" in + yes) + AC_MSG_RESULT(yes) + AC_DEFINE(WITH_TCPWRAPPER, , [Define if we are compiling with libwrap (TCP wrapper) support.]) + TCPWRAPPERLIBS="-lwrap" + ;; + *) + AC_MSG_RESULT(no) + ;; + esac ], +[ SAVELIBS="$LIBS" + LIBS="-lwrap $LIBS" + AC_TRY_LINK( + [#ifdef __cplusplus + extern "C" { + #endif + #ifdef HAVE_STDIO_H + /* on some platforms, tcpd.h needs stdio.h */ + #include + #endif + #ifdef HAVE_SYS_TYPES_H + /* on some platforms, tcpd.h needs sys/types.h */ + #include + #endif + #include + #ifdef __cplusplus + } + #endif + int deny_severity = 0; + int allow_severity = 0;], [struct request_info r; (void) hosts_access(&r)], + [ AC_MSG_RESULT(yes) + AC_DEFINE(WITH_TCPWRAPPER, , [Define if we are compiling with libwrap (TCP wrapper) support.]) + TCPWRAPPERLIBS="-lwrap" ], + [AC_MSG_RESULT(no)]) + LIBS="$SAVELIBS"] ) + + +dnl ------------------------------------------------------- +dnl Check for libsndfile support +dnl ------------------------------------------------------- + +AC_MY_LIB_PATH([libsndfile]) + +SNDFILELIBS="" +AC_MSG_CHECKING(whether to include libsndfile support) +AC_ARG_WITH(libsndfile, + [AS_HELP_STRING([--with-libsndfile], [include libsndfile support (default: auto)]) +AS_HELP_STRING([--without-libsndfile], [don't include libsndfile support])], + [ case "$withval" in + yes) + AC_MSG_RESULT(yes) + AC_DEFINE(WITH_SNDFILE, , [Define if we are compiling with libsndfile support.]) + SNDFILELIBS="-lsndfile" + ;; + *) + AC_MSG_RESULT(no) + ;; + esac ], + [ SAVELIBS="$LIBS" + LIBS="$LIBS -lsndfile" + AC_TRY_LINK([#include ], [char buffer [128]; sf_command (NULL, SFC_GET_LIB_VERSION, buffer, sizeof (buffer));], + [ AC_MSG_RESULT(yes) + AC_DEFINE(WITH_SNDFILE, , [Define if we are compiling with libsndfile support.]) + SNDFILELIBS="-lsndfile" ], + [AC_MSG_RESULT(no)]) + LIBS="$SAVELIBS"] +) + +dnl ------------------------------------------------------- +dnl Check for libiconv support +dnl ------------------------------------------------------- + +AC_MY_LIB_PATH([libiconv]) + +ICONVLIBS="" +AC_MSG_CHECKING(whether to include libiconv support) +AC_ARG_WITH(libiconv, +[AS_HELP_STRING([--with-libiconv], [include libiconv support (default: auto)]) +AS_HELP_STRING([--without-libiconv], [don't include libiconv support])], +[ case "$withval" in + yes) + AC_MSG_RESULT(yes) + AC_DEFINE(WITH_LIBICONV, , [Define if we are compiling with libiconv support.]) + ICONVLIBS="-liconv -lcharset" + ;; + *) + AC_MSG_RESULT(no) + ;; + esac ], +[ SAVELIBS="$LIBS" + LIBS="$LIBS -liconv -lcharset" + AC_TRY_LINK([#include ], [iconv_t cd = iconv_open("", ""); iconv(cd, NULL, NULL, NULL, NULL); iconv_close(cd);], + [ AC_MSG_RESULT(yes) + AC_DEFINE(WITH_LIBICONV, , [Define if we are compiling with libiconv support.]) + ICONVLIBS="-liconv -lcharset" ], + [AC_MSG_RESULT(no)]) + LIBS="$SAVELIBS"] ) + +AC_MSG_CHECKING(whether the second argument to iconv() is const) +SAVELIBS="$LIBS" +LIBS="$LIBS $ICONVLIBS" +AC_TRY_COMPILE([#include ], [iconv_t cd = iconv_open("", ""); const char *in = 0; iconv(cd, &in, NULL, NULL, NULL); iconv_close(cd);], + [ AC_MSG_RESULT(yes) + AC_DEFINE(LIBICONV_SECOND_ARGUMENT_CONST, , [Define if the second argument to iconv() is const.]) ], + [AC_MSG_RESULT(no)]) +LIBS="$SAVELIBS" + +dnl ------------------------------------------------------- +dnl C++11 support +dnl ------------------------------------------------------- + +AC_MSG_CHECKING(if the C++11 STL should be used) +AC_ARG_WITH(cxx11-stl, +[ --with-cxx11-stl enable C++11 STL + --without-cxx11-stl disable C++11 STL (default)], +[ case "$withval" in + yes) + AC_MSG_RESULT(yes) + AC_DEFINE(DCMTK_USE_CXX11_STL, , [Enable or disable C++11 while building DCMTK.]) + ;; + *) + AC_MSG_RESULT(no) + ;; + esac ], + AC_MSG_RESULT(no) +) + +dnl ------------------------------------------------------- +dnl Test for some additional functions and keywords +dnl ------------------------------------------------------- + +AC_CHECK_SYNC_FN([__sync_add_and_fetch],[HAVE_SYNC_ADD_AND_FETCH]) +AC_CHECK_SYNC_FN([__sync_sub_and_fetch],[HAVE_SYNC_SUB_AND_FETCH]) +AC_CHECK_ALIGNOF([HAVE_GNU_ALIGNOF]) +AC_CHECK_ATTRIBUTE_ALIGNED([HAVE_ATTRIBUTE_ALIGNED]) +AC_CHECK_ATTRIBUTE_ALIGNED_SUPPORTS_TEMPLATES([ATTRIBUTE_ALIGNED_SUPPORTS_TEMPLATES]) +AC_CHECK_ALIGNAS_SUPPORTS_TYPEDEFS([ALIGNAS_SUPPORTS_TYPEDEFS]) +AC_CHECK_DEFAULT_CONSTRUCTOR_DETECTION_VIA_SFINAE([HAVE_DEFAULT_CONSTRUCTOR_DETECTION_VIA_SFINAE]) +o +dnl ------------------------------------------------------- +dnl Test if passwd has the pw_gecos field +dnl ------------------------------------------------------- + +AC_MSG_CHECKING(whether struct pwd contains the field pw_gecos) +AC_TRY_COMPILE([#include ], + [&passwd::pw_gecos;], + [ AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_PASSWD_GECOS, , [Define if passwd::pw_gecos is available.]) ], + [AC_MSG_RESULT(no)]) + +dnl ------------------------------------------------------- +dnl Test if SYS_gettid is available +dnl ------------------------------------------------------- + +AC_MSG_CHECKING(for SYS_gettid in sys/syscall.h) +AC_TRY_COMPILE([#include ], + [SYS_gettid;], + [ AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_SYS_GETTID, , [Define if your system has a prototype for gettid.]) ], + [AC_MSG_RESULT(no)]) + +dnl ------------------------------------------------------- +dnl Set optimizer and debug compiler flags +dnl ------------------------------------------------------- +CFLAGS="$DEBUGCFLAGS $CFLAGS" +CXXFLAGS="$DEBUGCXXFLAGS $CXXFLAGS" + +dnl ------------------------------------------------------- +dnl Special Definitions for output +dnl ------------------------------------------------------- +AC_SUBST(CXXFLAGS) +AC_SUBST(OPENSSLLIBS) +AC_SUBST(TIFFLIBS) +AC_SUBST(PNGLIBS) +AC_SUBST(MATHLIBS) +AC_SUBST(ZLIBLIBS) +AC_SUBST(XMLLIBS) +AC_SUBST(TCPWRAPPERLIBS) +AC_SUBST(SNDFILELIBS) +AC_SUBST(ICONVLIBS) +AC_SUBST(DEBUG) +AC_SUBST(DCMTK_ENABLE_BUILTIN_DICTIONARY) + +AC_OUTPUT(Makefile.def Makefile) + +dnl disabled: AC_ARG_PROGRAM diff --git a/config/confmod b/config/confmod new file mode 100755 index 00000000..b7fff7da --- /dev/null +++ b/config/confmod @@ -0,0 +1,2915 @@ +#! /bin/sh +# Guess values for system-dependent variables and create Makefiles. +# Generated by GNU Autoconf 2.69. +# +# +# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. +# +# +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +as_myself= +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +# Use a proper internal environment variable to ensure we don't fall + # into an infinite loop, continuously re-executing ourselves. + if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then + _as_can_reexec=no; export _as_can_reexec; + # We cannot yet assume a decent shell, so we have to provide a +# neutralization value for shells without unset; and this also +# works around shells that cannot unset nonexistent variables. +# Preserve -v and -x to the replacement shell. +BASH_ENV=/dev/null +ENV=/dev/null +(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV +case $- in # (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; +esac +exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} +# Admittedly, this is quite paranoid, since all the known shells bail +# out after a failed `exec'. +$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 +as_fn_exit 255 + fi + # We don't want this to propagate to other subprocesses. + { _as_can_reexec=; unset _as_can_reexec;} +if test "x$CONFIG_SHELL" = x; then + as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which + # is contrary to our usage. Disable this feature. + alias -g '\${1+\"\$@\"}'='\"\$@\"' + setopt NO_GLOB_SUBST +else + case \`(set -o) 2>/dev/null\` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi +" + as_required="as_fn_return () { (exit \$1); } +as_fn_success () { as_fn_return 0; } +as_fn_failure () { as_fn_return 1; } +as_fn_ret_success () { return 0; } +as_fn_ret_failure () { return 1; } + +exitcode=0 +as_fn_success || { exitcode=1; echo as_fn_success failed.; } +as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } +as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } +as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } +if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : + +else + exitcode=1; echo positional parameters were not saved. +fi +test x\$exitcode = x0 || exit 1 +test -x / || exit 1" + as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO + as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO + eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && + test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1" + if (eval "$as_required") 2>/dev/null; then : + as_have_required=yes +else + as_have_required=no +fi + if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : + +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +as_found=false +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + as_found=: + case $as_dir in #( + /*) + for as_base in sh bash ksh sh5; do + # Try only shells that exist, to save several forks. + as_shell=$as_dir/$as_base + if { test -f "$as_shell" || test -f "$as_shell.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : + CONFIG_SHELL=$as_shell as_have_required=yes + if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : + break 2 +fi +fi + done;; + esac + as_found=false +done +$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : + CONFIG_SHELL=$SHELL as_have_required=yes +fi; } +IFS=$as_save_IFS + + + if test "x$CONFIG_SHELL" != x; then : + export CONFIG_SHELL + # We cannot yet assume a decent shell, so we have to provide a +# neutralization value for shells without unset; and this also +# works around shells that cannot unset nonexistent variables. +# Preserve -v and -x to the replacement shell. +BASH_ENV=/dev/null +ENV=/dev/null +(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV +case $- in # (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; +esac +exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} +# Admittedly, this is quite paranoid, since all the known shells bail +# out after a failed `exec'. +$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 +exit 255 +fi + + if test x$as_have_required = xno; then : + $as_echo "$0: This script requires a shell more modern than all" + $as_echo "$0: the shells that I found on your system." + if test x${ZSH_VERSION+set} = xset ; then + $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" + $as_echo "$0: be upgraded to zsh 4.3.4 or later." + else + $as_echo "$0: Please tell bug-autoconf@gnu.org about your system, +$0: including any error possibly output before this +$0: message. Then install a modern shell, or manually run +$0: the script under such a shell if you do have one." + fi + exit 1 +fi +fi +fi +SHELL=${CONFIG_SHELL-/bin/sh} +export SHELL +# Unset more variables known to interfere with behavior of common tools. +CLICOLOR_FORCE= GREP_OPTIONS= +unset CLICOLOR_FORCE GREP_OPTIONS + +## --------------------- ## +## M4sh Shell Functions. ## +## --------------------- ## +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} # as_fn_mkdir_p + +# as_fn_executable_p FILE +# ----------------------- +# Test if FILE is an executable regular file. +as_fn_executable_p () +{ + test -f "$1" && test -x "$1" +} # as_fn_executable_p +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 + as_fn_exit $as_status +} # as_fn_error + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + + + as_lineno_1=$LINENO as_lineno_1a=$LINENO + as_lineno_2=$LINENO as_lineno_2a=$LINENO + eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && + test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { + # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) + sed -n ' + p + /[$]LINENO/= + ' <$as_myself | + sed ' + s/[$]LINENO.*/&-/ + t lineno + b + :lineno + N + :loop + s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ + t loop + s/-\n.*// + ' >$as_me.lineno && + chmod +x "$as_me.lineno" || + { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } + + # If we had to re-execute with $CONFIG_SHELL, we're ensured to have + # already done that, so ensure we don't try to do so again and fall + # in an infinite loop. This has already happened in practice. + _as_can_reexec=no; export _as_can_reexec + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensitive to this). + . "./$as_me.lineno" + # Exit status is that of the last command. + exit +} + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -pR'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -pR' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -pR' + fi +else + as_ln_s='cp -pR' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +as_test_x='test -x' +as_executable_p=as_fn_executable_p + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +test -n "$DJDIR" || exec 7<&0 &1 + +# Name of the host. +# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, +# so uname gets run too. +ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` + +# +# Initializations. +# +ac_default_prefix=/usr/local +ac_clean_files= +ac_config_libobj_dir=. +LIBOBJS= +cross_compiling=no +subdirs= +MFLAGS= +MAKEFLAGS= + +# Identity of this package. +PACKAGE_NAME= +PACKAGE_TARNAME= +PACKAGE_VERSION= +PACKAGE_STRING= +PACKAGE_BUGREPORT= +PACKAGE_URL= + +ac_unique_file="Makefile.in" +enable_option_checking=no +ac_default_prefix=/usr/local +ac_subst_vars='LTLIBOBJS +LIBOBJS +configdir +common_makefile +SET_MAKE +target_alias +host_alias +build_alias +LIBS +ECHO_T +ECHO_N +ECHO_C +DEFS +mandir +localedir +libdir +psdir +pdfdir +dvidir +htmldir +infodir +docdir +oldincludedir +includedir +localstatedir +sharedstatedir +sysconfdir +datadir +datarootdir +libexecdir +sbindir +bindir +program_transform_name +prefix +exec_prefix +PACKAGE_URL +PACKAGE_BUGREPORT +PACKAGE_STRING +PACKAGE_VERSION +PACKAGE_TARNAME +PACKAGE_NAME +PATH_SEPARATOR +SHELL' +ac_subst_files='' +ac_user_opts=' +enable_option_checking +' + ac_precious_vars='build_alias +host_alias +target_alias' + + +# Initialize some variables set by options. +ac_init_help= +ac_init_version=false +ac_unrecognized_opts= +ac_unrecognized_sep= +# The variables have the same names as the options, with +# dashes changed to underlines. +cache_file=/dev/null +exec_prefix=NONE +no_create= +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +verbose= +x_includes=NONE +x_libraries=NONE + +# Installation directory options. +# These are left unexpanded so users can "make install exec_prefix=/foo" +# and all the variables that are supposed to be based on exec_prefix +# by default will actually change. +# Use braces instead of parens because sh, perl, etc. also accept them. +# (The list follows the same order as the GNU Coding Standards.) +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datarootdir='${prefix}/share' +datadir='${datarootdir}/dcmtk' +sysconfdir='${prefix}/etc/dcmtk' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +includedir='${prefix}/include' +oldincludedir='/usr/include' +docdir='${datarootdir}/doc/dcmtk' +infodir='${datarootdir}/info' +htmldir='${docdir}/html' +dvidir='${docdir}' +pdfdir='${docdir}' +psdir='${docdir}' +libdir='${exec_prefix}/lib' +localedir='${datarootdir}/locale' +mandir='${datarootdir}/man' + +ac_prev= +ac_dashdash= +for ac_option +do + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval $ac_prev=\$ac_option + ac_prev= + continue + fi + + case $ac_option in + *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; + *=) ac_optarg= ;; + *) ac_optarg=yes ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case $ac_dashdash$ac_option in + --) + ac_dashdash=yes ;; + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir=$ac_optarg ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build_alias ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build_alias=$ac_optarg ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file=$ac_optarg ;; + + --config-cache | -C) + cache_file=config.cache ;; + + -datadir | --datadir | --datadi | --datad) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=*) + datadir=$ac_optarg ;; + + -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ + | --dataroo | --dataro | --datar) + ac_prev=datarootdir ;; + -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ + | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) + datarootdir=$ac_optarg ;; + + -disable-* | --disable-*) + ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=no ;; + + -docdir | --docdir | --docdi | --doc | --do) + ac_prev=docdir ;; + -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) + docdir=$ac_optarg ;; + + -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) + ac_prev=dvidir ;; + -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) + dvidir=$ac_optarg ;; + + -enable-* | --enable-*) + ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=\$ac_optarg ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix=$ac_optarg ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he | -h) + ac_init_help=long ;; + -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) + ac_init_help=recursive ;; + -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) + ac_init_help=short ;; + + -host | --host | --hos | --ho) + ac_prev=host_alias ;; + -host=* | --host=* | --hos=* | --ho=*) + host_alias=$ac_optarg ;; + + -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) + ac_prev=htmldir ;; + -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ + | --ht=*) + htmldir=$ac_optarg ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir=$ac_optarg ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir=$ac_optarg ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir=$ac_optarg ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir=$ac_optarg ;; + + -localedir | --localedir | --localedi | --localed | --locale) + ac_prev=localedir ;; + -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) + localedir=$ac_optarg ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst | --locals) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) + localstatedir=$ac_optarg ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir=$ac_optarg ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c | -n) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir=$ac_optarg ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix=$ac_optarg ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix=$ac_optarg ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix=$ac_optarg ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name=$ac_optarg ;; + + -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) + ac_prev=pdfdir ;; + -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) + pdfdir=$ac_optarg ;; + + -psdir | --psdir | --psdi | --psd | --ps) + ac_prev=psdir ;; + -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) + psdir=$ac_optarg ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir=$ac_optarg ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir=$ac_optarg ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site=$ac_optarg ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir=$ac_optarg ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir=$ac_optarg ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target_alias ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target_alias=$ac_optarg ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers | -V) + ac_init_version=: ;; + + -with-* | --with-*) + ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=\$ac_optarg ;; + + -without-* | --without-*) + ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=no ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes=$ac_optarg ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries=$ac_optarg ;; + + -*) as_fn_error $? "unrecognized option: \`$ac_option' +Try \`$0 --help' for more information" + ;; + + *=*) + ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` + # Reject names that are not valid shell variable names. + case $ac_envvar in #( + '' | [0-9]* | *[!_$as_cr_alnum]* ) + as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; + esac + eval $ac_envvar=\$ac_optarg + export $ac_envvar ;; + + *) + # FIXME: should be removed in autoconf 3.0. + $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 + expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && + $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 + : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" + ;; + + esac +done + +if test -n "$ac_prev"; then + ac_option=--`echo $ac_prev | sed 's/_/-/g'` + as_fn_error $? "missing argument to $ac_option" +fi + +if test -n "$ac_unrecognized_opts"; then + case $enable_option_checking in + no) ;; + fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; + *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; + esac +fi + +# Check all directory arguments for consistency. +for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ + datadir sysconfdir sharedstatedir localstatedir includedir \ + oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ + libdir localedir mandir +do + eval ac_val=\$$ac_var + # Remove trailing slashes. + case $ac_val in + */ ) + ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` + eval $ac_var=\$ac_val;; + esac + # Be sure to have absolute directory names. + case $ac_val in + [\\/$]* | ?:[\\/]* ) continue;; + NONE | '' ) case $ac_var in *prefix ) continue;; esac;; + esac + as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" +done + +# There might be people who depend on the old broken behavior: `$host' +# used to hold the argument of --host etc. +# FIXME: To remove some day. +build=$build_alias +host=$host_alias +target=$target_alias + +# FIXME: To remove some day. +if test "x$host_alias" != x; then + if test "x$build_alias" = x; then + cross_compiling=maybe + elif test "x$build_alias" != "x$host_alias"; then + cross_compiling=yes + fi +fi + +ac_tool_prefix= +test -n "$host_alias" && ac_tool_prefix=$host_alias- + +test "$silent" = yes && exec 6>/dev/null + + +ac_pwd=`pwd` && test -n "$ac_pwd" && +ac_ls_di=`ls -di .` && +ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || + as_fn_error $? "working directory cannot be determined" +test "X$ac_ls_di" = "X$ac_pwd_ls_di" || + as_fn_error $? "pwd does not report name of working directory" + + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then the parent directory. + ac_confdir=`$as_dirname -- "$as_myself" || +$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_myself" : 'X\(//\)[^/]' \| \ + X"$as_myself" : 'X\(//\)$' \| \ + X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_myself" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + srcdir=$ac_confdir + if test ! -r "$srcdir/$ac_unique_file"; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r "$srcdir/$ac_unique_file"; then + test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." + as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" +fi +ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" +ac_abs_confdir=`( + cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" + pwd)` +# When building in place, set srcdir=. +if test "$ac_abs_confdir" = "$ac_pwd"; then + srcdir=. +fi +# Remove unnecessary trailing slashes from srcdir. +# Double slashes in file names in object file debugging info +# mess up M-x gdb in Emacs. +case $srcdir in +*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; +esac +for ac_var in $ac_precious_vars; do + eval ac_env_${ac_var}_set=\${${ac_var}+set} + eval ac_env_${ac_var}_value=\$${ac_var} + eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} + eval ac_cv_env_${ac_var}_value=\$${ac_var} +done + +# +# Report the --help message. +# +if test "$ac_init_help" = "long"; then + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat <<_ACEOF +\`configure' configures this package to adapt to many kinds of systems. + +Usage: $0 [OPTION]... [VAR=VALUE]... + +To assign environment variables (e.g., CC, CFLAGS...), specify them as +VAR=VALUE. See below for descriptions of some of the useful variables. + +Defaults for the options are specified in brackets. + +Configuration: + -h, --help display this help and exit + --help=short display options specific to this package + --help=recursive display the short help of all the included packages + -V, --version display version information and exit + -q, --quiet, --silent do not print \`checking ...' messages + --cache-file=FILE cache test results in FILE [disabled] + -C, --config-cache alias for \`--cache-file=config.cache' + -n, --no-create do not create output files + --srcdir=DIR find the sources in DIR [configure dir or \`..'] + +Installation directories: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [PREFIX] + +By default, \`make install' will install all the files in +\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify +an installation prefix other than \`$ac_default_prefix' using \`--prefix', +for instance \`--prefix=\$HOME'. + +For better control, use the options below. + +Fine tuning of the installation directories: + --bindir=DIR user executables [EPREFIX/bin] + --sbindir=DIR system admin executables [EPREFIX/sbin] + --libexecdir=DIR program executables [EPREFIX/libexec] + --sysconfdir=DIR read-only single-machine data [PREFIX/etc/dcmtk] + --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] + --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --libdir=DIR object code libraries [EPREFIX/lib] + --includedir=DIR C header files [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc [/usr/include] + --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] + --datadir=DIR read-only arch.-independent data [DATAROOTDIR/dcmtk] + --infodir=DIR info documentation [DATAROOTDIR/info] + --localedir=DIR locale-dependent data [DATAROOTDIR/locale] + --mandir=DIR man documentation [DATAROOTDIR/man] + --docdir=DIR documentation root [DATAROOTDIR/doc/dcmtk] + --htmldir=DIR html documentation [DOCDIR/html] + --dvidir=DIR dvi documentation [DOCDIR] + --pdfdir=DIR pdf documentation [DOCDIR] + --psdir=DIR ps documentation [DOCDIR] +_ACEOF + + cat <<\_ACEOF +_ACEOF +fi + +if test -n "$ac_init_help"; then + + cat <<\_ACEOF + +Report bugs to the package provider. +_ACEOF +ac_status=$? +fi + +if test "$ac_init_help" = "recursive"; then + # If there are subdirs, report their specific --help. + for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue + test -d "$ac_dir" || + { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || + continue + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + cd "$ac_dir" || { ac_status=$?; continue; } + # Check for guested configure. + if test -f "$ac_srcdir/configure.gnu"; then + echo && + $SHELL "$ac_srcdir/configure.gnu" --help=recursive + elif test -f "$ac_srcdir/configure"; then + echo && + $SHELL "$ac_srcdir/configure" --help=recursive + else + $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 + fi || ac_status=$? + cd "$ac_pwd" || { ac_status=$?; break; } + done +fi + +test -n "$ac_init_help" && exit $ac_status +if $ac_init_version; then + cat <<\_ACEOF +configure +generated by GNU Autoconf 2.69 + +Copyright (C) 2012 Free Software Foundation, Inc. +This configure script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it. +_ACEOF + exit +fi + +## ------------------------ ## +## Autoconf initialization. ## +## ------------------------ ## +cat >config.log <<_ACEOF +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. + +It was created by $as_me, which was +generated by GNU Autoconf 2.69. Invocation command line was + + $ $0 $@ + +_ACEOF +exec 5>>config.log +{ +cat <<_ASUNAME +## --------- ## +## Platform. ## +## --------- ## + +hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` + +/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` +/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` +/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` +/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` + +_ASUNAME + +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + $as_echo "PATH: $as_dir" + done +IFS=$as_save_IFS + +} >&5 + +cat >&5 <<_ACEOF + + +## ----------- ## +## Core tests. ## +## ----------- ## + +_ACEOF + + +# Keep a trace of the command line. +# Strip out --no-create and --no-recursion so they do not pile up. +# Strip out --silent because we don't want to record it for future runs. +# Also quote any args containing shell meta-characters. +# Make two passes to allow for proper duplicate-argument suppression. +ac_configure_args= +ac_configure_args0= +ac_configure_args1= +ac_must_keep_next=false +for ac_pass in 1 2 +do + for ac_arg + do + case $ac_arg in + -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + continue ;; + *\'*) + ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + case $ac_pass in + 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; + 2) + as_fn_append ac_configure_args1 " '$ac_arg'" + if test $ac_must_keep_next = true; then + ac_must_keep_next=false # Got value, back to normal. + else + case $ac_arg in + *=* | --config-cache | -C | -disable-* | --disable-* \ + | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ + | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ + | -with-* | --with-* | -without-* | --without-* | --x) + case "$ac_configure_args0 " in + "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; + esac + ;; + -* ) ac_must_keep_next=true ;; + esac + fi + as_fn_append ac_configure_args " '$ac_arg'" + ;; + esac + done +done +{ ac_configure_args0=; unset ac_configure_args0;} +{ ac_configure_args1=; unset ac_configure_args1;} + +# When interrupted or exit'd, cleanup temporary files, and complete +# config.log. We remove comments because anyway the quotes in there +# would cause problems or look ugly. +# WARNING: Use '\'' to represent an apostrophe within the trap. +# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. +trap 'exit_status=$? + # Save into config.log some information that might help in debugging. + { + echo + + $as_echo "## ---------------- ## +## Cache variables. ## +## ---------------- ##" + echo + # The following way of writing the cache mishandles newlines in values, +( + for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + (set) 2>&1 | + case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + sed -n \ + "s/'\''/'\''\\\\'\'''\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" + ;; #( + *) + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) + echo + + $as_echo "## ----------------- ## +## Output variables. ## +## ----------------- ##" + echo + for ac_var in $ac_subst_vars + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + + if test -n "$ac_subst_files"; then + $as_echo "## ------------------- ## +## File substitutions. ## +## ------------------- ##" + echo + for ac_var in $ac_subst_files + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + fi + + if test -s confdefs.h; then + $as_echo "## ----------- ## +## confdefs.h. ## +## ----------- ##" + echo + cat confdefs.h + echo + fi + test "$ac_signal" != 0 && + $as_echo "$as_me: caught signal $ac_signal" + $as_echo "$as_me: exit $exit_status" + } >&5 + rm -f core *.core core.conftest.* && + rm -f -r conftest* confdefs* conf$$* $ac_clean_files && + exit $exit_status +' 0 +for ac_signal in 1 2 13 15; do + trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal +done +ac_signal=0 + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -f -r conftest* confdefs.h + +$as_echo "/* confdefs.h */" > confdefs.h + +# Predefined preprocessor variables. + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_NAME "$PACKAGE_NAME" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_TARNAME "$PACKAGE_TARNAME" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_VERSION "$PACKAGE_VERSION" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_STRING "$PACKAGE_STRING" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_URL "$PACKAGE_URL" +_ACEOF + + +# Let the site file select an alternate cache file if it wants to. +# Prefer an explicitly selected file to automatically selected ones. +ac_site_file1=NONE +ac_site_file2=NONE +if test -n "$CONFIG_SITE"; then + # We do not want a PATH search for config.site. + case $CONFIG_SITE in #(( + -*) ac_site_file1=./$CONFIG_SITE;; + */*) ac_site_file1=$CONFIG_SITE;; + *) ac_site_file1=./$CONFIG_SITE;; + esac +elif test "x$prefix" != xNONE; then + ac_site_file1=$prefix/share/config.site + ac_site_file2=$prefix/etc/config.site +else + ac_site_file1=$ac_default_prefix/share/config.site + ac_site_file2=$ac_default_prefix/etc/config.site +fi +for ac_site_file in "$ac_site_file1" "$ac_site_file2" +do + test "x$ac_site_file" = xNONE && continue + if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 +$as_echo "$as_me: loading site script $ac_site_file" >&6;} + sed 's/^/| /' "$ac_site_file" >&5 + . "$ac_site_file" \ + || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "failed to load site script $ac_site_file +See \`config.log' for more details" "$LINENO" 5; } + fi +done + +if test -r "$cache_file"; then + # Some versions of bash will fail to source /dev/null (special files + # actually), so we avoid doing that. DJGPP emulates it as a regular file. + if test /dev/null != "$cache_file" && test -f "$cache_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 +$as_echo "$as_me: loading cache $cache_file" >&6;} + case $cache_file in + [\\/]* | ?:[\\/]* ) . "$cache_file";; + *) . "./$cache_file";; + esac + fi +else + { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 +$as_echo "$as_me: creating cache $cache_file" >&6;} + >$cache_file +fi + +# Check that the precious variables saved in the cache have kept the same +# value. +ac_cache_corrupted=false +for ac_var in $ac_precious_vars; do + eval ac_old_set=\$ac_cv_env_${ac_var}_set + eval ac_new_set=\$ac_env_${ac_var}_set + eval ac_old_val=\$ac_cv_env_${ac_var}_value + eval ac_new_val=\$ac_env_${ac_var}_value + case $ac_old_set,$ac_new_set in + set,) + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,set) + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,);; + *) + if test "x$ac_old_val" != "x$ac_new_val"; then + # differences in whitespace do not lead to failure. + ac_old_val_w=`echo x $ac_old_val` + ac_new_val_w=`echo x $ac_new_val` + if test "$ac_old_val_w" != "$ac_new_val_w"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 +$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} + ac_cache_corrupted=: + else + { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 +$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} + eval $ac_var=\$ac_old_val + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 +$as_echo "$as_me: former value: \`$ac_old_val'" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 +$as_echo "$as_me: current value: \`$ac_new_val'" >&2;} + fi;; + esac + # Pass precious variables to config.status. + if test "$ac_new_set" = set; then + case $ac_new_val in + *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; + *) ac_arg=$ac_var=$ac_new_val ;; + esac + case " $ac_configure_args " in + *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. + *) as_fn_append ac_configure_args " '$ac_arg'" ;; + esac + fi +done +if $ac_cache_corrupted; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 +$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} + as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 +fi +## -------------------- ## +## Main body of script. ## +## -------------------- ## + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + + + +parentdir=`pwd` +relparentdir=. +configdir="configdir" + +while test "$parentdir" != "/" -a "$configdir" = "configdir"; do + if test -d "$parentdir/config" ; then + configdir=`echo $relparentdir | sed 's/^\.\///'`/config + else + parentdir=`echo $parentdir | sed 's/\/[^\/]*$//'` + relparentdir=$relparentdir/.. + fi +done + +if test "$configdir" = "configdir" ; then + echo "Cannot find configure directory" + exit 1 +fi + +ac_aux_dir= +for ac_dir in $configdir "$srcdir"/$configdir; do + if test -f "$ac_dir/install-sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f "$ac_dir/install.sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + elif test -f "$ac_dir/shtool"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/shtool install -c" + break + fi +done +if test -z "$ac_aux_dir"; then + as_fn_error $? "cannot find install-sh, install.sh, or shtool in $configdir \"$srcdir\"/$configdir" "$LINENO" 5 +fi + +# These three variables are undocumented and unsupported, +# and are intended to be withdrawn in a future Autoconf release. +# They can cause serious problems if a builder's source tree is in a directory +# whose full name contains unusual characters. +ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. +ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. +ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 +$as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } +set x ${MAKE-make} +ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` +if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat >conftest.make <<\_ACEOF +SHELL = /bin/sh +all: + @echo '@@@%%%=$(MAKE)=@@@%%%' +_ACEOF +# GNU make sometimes prints "make[1]: Entering ...", which would confuse us. +case `${MAKE-make} -f conftest.make 2>/dev/null` in + *@@@%%%=?*=@@@%%%*) + eval ac_cv_prog_make_${ac_make}_set=yes;; + *) + eval ac_cv_prog_make_${ac_make}_set=no;; +esac +rm -f conftest.make +fi +if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + SET_MAKE= +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + SET_MAKE="MAKE=${MAKE-make}" +fi + + +common_makefile=Makefile.def + + + + +files=`find . -name "*.in" -print | grep -v "/config" | sed -e 's/.in$/ /g'` + +ac_config_files="$ac_config_files $files" + +cat >confcache <<\_ACEOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs, see configure's option --config-cache. +# It is not useful on other systems. If it contains results you don't +# want to keep, you may remove or edit it. +# +# config.status only pays attention to the cache file if you give it +# the --recheck option to rerun configure. +# +# `ac_cv_env_foo' variables (set or unset) will be overridden when +# loading this file, other *unset* `ac_cv_foo' will be assigned the +# following values. + +_ACEOF + +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, we kill variables containing newlines. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +( + for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + + (set) 2>&1 | + case $as_nl`(ac_space=' '; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + # `set' does not quote correctly, so add quotes: double-quote + # substitution turns \\\\ into \\, and sed turns \\ into \. + sed -n \ + "s/'/'\\\\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" + ;; #( + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) | + sed ' + /^ac_cv_env_/b end + t clear + :clear + s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ + t end + s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ + :end' >>confcache +if diff "$cache_file" confcache >/dev/null 2>&1; then :; else + if test -w "$cache_file"; then + if test "x$cache_file" != "x/dev/null"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 +$as_echo "$as_me: updating cache $cache_file" >&6;} + if test ! -f "$cache_file" || test -h "$cache_file"; then + cat confcache >"$cache_file" + else + case $cache_file in #( + */* | ?:*) + mv -f confcache "$cache_file"$$ && + mv -f "$cache_file"$$ "$cache_file" ;; #( + *) + mv -f confcache "$cache_file" ;; + esac + fi + fi + else + { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 +$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} + fi +fi +rm -f confcache + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +# Transform confdefs.h into DEFS. +# Protect against shell expansion while executing Makefile rules. +# Protect against Makefile macro expansion. +# +# If the first sed substitution is executed (which looks for macros that +# take arguments), then branch to the quote section. Otherwise, +# look for a macro that doesn't take arguments. +ac_script=' +:mline +/\\$/{ + N + s,\\\n,, + b mline +} +t clear +:clear +s/^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*([^)]*)\)[ ]*\(.*\)/-D\1=\2/g +t quote +s/^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)/-D\1=\2/g +t quote +b any +:quote +s/[ `~#$^&*(){}\\|;'\''"<>?]/\\&/g +s/\[/\\&/g +s/\]/\\&/g +s/\$/$$/g +H +:any +${ + g + s/^\n// + s/\n/ /g + p +} +' +DEFS=`sed -n "$ac_script" confdefs.h` + + +ac_libobjs= +ac_ltlibobjs= +U= +for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue + # 1. Remove the extension, and $U if already installed. + ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' + ac_i=`$as_echo "$ac_i" | sed "$ac_script"` + # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR + # will be set to the directory where LIBOBJS objects are built. + as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" + as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' +done +LIBOBJS=$ac_libobjs + +LTLIBOBJS=$ac_ltlibobjs + + + +: "${CONFIG_STATUS=./config.status}" +ac_write_fail=0 +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files $CONFIG_STATUS" +{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 +$as_echo "$as_me: creating $CONFIG_STATUS" >&6;} +as_write_fail=0 +cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 +#! $SHELL +# Generated by $as_me. +# Run this file to recreate the current configuration. +# Compiler output produced by configure, useful for debugging +# configure, is in config.log if it exists. + +debug=false +ac_cs_recheck=false +ac_cs_silent=false + +SHELL=\${CONFIG_SHELL-$SHELL} +export SHELL +_ASEOF +cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +as_myself= +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + + +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 + as_fn_exit $as_status +} # as_fn_error + + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -pR'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -pR' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -pR' + fi +else + as_ln_s='cp -pR' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} # as_fn_mkdir_p +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + + +# as_fn_executable_p FILE +# ----------------------- +# Test if FILE is an executable regular file. +as_fn_executable_p () +{ + test -f "$1" && test -x "$1" +} # as_fn_executable_p +as_test_x='test -x' +as_executable_p=as_fn_executable_p + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +exec 6>&1 +## ----------------------------------- ## +## Main body of $CONFIG_STATUS script. ## +## ----------------------------------- ## +_ASEOF +test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# Save the log message, to keep $0 and so on meaningful, and to +# report actual input values of CONFIG_FILES etc. instead of their +# values after options handling. +ac_log=" +This file was extended by $as_me, which was +generated by GNU Autoconf 2.69. Invocation command line was + + CONFIG_FILES = $CONFIG_FILES + CONFIG_HEADERS = $CONFIG_HEADERS + CONFIG_LINKS = $CONFIG_LINKS + CONFIG_COMMANDS = $CONFIG_COMMANDS + $ $0 $@ + +on `(hostname || uname -n) 2>/dev/null | sed 1q` +" + +_ACEOF + +case $ac_config_files in *" +"*) set x $ac_config_files; shift; ac_config_files=$*;; +esac + + + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +# Files that config.status was made for. +config_files="$ac_config_files" + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +ac_cs_usage="\ +\`$as_me' instantiates files and other configuration actions +from templates according to the current configuration. Unless the files +and actions are specified as TAGs, all are instantiated by default. + +Usage: $0 [OPTION]... [TAG]... + + -h, --help print this help, then exit + -V, --version print version number and configuration settings, then exit + --config print configuration, then exit + -q, --quiet, --silent + do not print progress messages + -d, --debug don't remove temporary files + --recheck update $as_me by reconfiguring in the same conditions + --file=FILE[:TEMPLATE] + instantiate the configuration file FILE + +Configuration files: +$config_files + +Report bugs to the package provider." + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" +ac_cs_version="\\ +config.status +configured by $0, generated by GNU Autoconf 2.69, + with options \\"\$ac_cs_config\\" + +Copyright (C) 2012 Free Software Foundation, Inc. +This config.status script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it." + +ac_pwd='$ac_pwd' +srcdir='$srcdir' +test -n "\$AWK" || AWK=awk +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# The default lists apply if the user does not specify any file. +ac_need_defaults=: +while test $# != 0 +do + case $1 in + --*=?*) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` + ac_shift=: + ;; + --*=) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg= + ac_shift=: + ;; + *) + ac_option=$1 + ac_optarg=$2 + ac_shift=shift + ;; + esac + + case $ac_option in + # Handling of the options. + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + ac_cs_recheck=: ;; + --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) + $as_echo "$ac_cs_version"; exit ;; + --config | --confi | --conf | --con | --co | --c ) + $as_echo "$ac_cs_config"; exit ;; + --debug | --debu | --deb | --de | --d | -d ) + debug=: ;; + --file | --fil | --fi | --f ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + '') as_fn_error $? "missing file argument" ;; + esac + as_fn_append CONFIG_FILES " '$ac_optarg'" + ac_need_defaults=false;; + --he | --h | --help | --hel | -h ) + $as_echo "$ac_cs_usage"; exit ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil | --si | --s) + ac_cs_silent=: ;; + + # This is an error. + -*) as_fn_error $? "unrecognized option: \`$1' +Try \`$0 --help' for more information." ;; + + *) as_fn_append ac_config_targets " $1" + ac_need_defaults=false ;; + + esac + shift +done + +ac_configure_extra_args= + +if $ac_cs_silent; then + exec 6>/dev/null + ac_configure_extra_args="$ac_configure_extra_args --silent" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +if \$ac_cs_recheck; then + set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion + shift + \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 + CONFIG_SHELL='$SHELL' + export CONFIG_SHELL + exec "\$@" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +exec 5>>config.log +{ + echo + sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX +## Running $as_me. ## +_ASBOX + $as_echo "$ac_log" +} >&5 + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 + +# Handling of arguments. +for ac_config_target in $ac_config_targets +do + case $ac_config_target in + "$files") CONFIG_FILES="$CONFIG_FILES $files" ;; + + *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; + esac +done + + +# If the user did not use the arguments to specify the items to instantiate, +# then the envvar interface is used. Set only those that are not. +# We use the long form for the default assignment because of an extremely +# bizarre bug on SunOS 4.1.3. +if $ac_need_defaults; then + test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files +fi + +# Have a temporary directory for convenience. Make it in the build tree +# simply because there is no reason against having it here, and in addition, +# creating and moving files from /tmp can sometimes cause problems. +# Hook for its removal unless debugging. +# Note that there is a small window in which the directory will not be cleaned: +# after its creation but before its name has been assigned to `$tmp'. +$debug || +{ + tmp= ac_tmp= + trap 'exit_status=$? + : "${ac_tmp:=$tmp}" + { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status +' 0 + trap 'as_fn_exit 1' 1 2 13 15 +} +# Create a (secure) tmp directory for tmp files. + +{ + tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && + test -d "$tmp" +} || +{ + tmp=./conf$$-$RANDOM + (umask 077 && mkdir "$tmp") +} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 +ac_tmp=$tmp + +# Set up the scripts for CONFIG_FILES section. +# No need to generate them if there are no CONFIG_FILES. +# This happens for instance with `./config.status config.h'. +if test -n "$CONFIG_FILES"; then + + +ac_cr=`echo X | tr X '\015'` +# On cygwin, bash can eat \r inside `` if the user requested igncr. +# But we know of no other shell where ac_cr would be empty at this +# point, so we can use a bashism as a fallback. +if test "x$ac_cr" = x; then + eval ac_cr=\$\'\\r\' +fi +ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` +if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then + ac_cs_awk_cr='\\r' +else + ac_cs_awk_cr=$ac_cr +fi + +echo 'BEGIN {' >"$ac_tmp/subs1.awk" && +_ACEOF + + +{ + echo "cat >conf$$subs.awk <<_ACEOF" && + echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && + echo "_ACEOF" +} >conf$$subs.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 +ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` +ac_delim='%!_!# ' +for ac_last_try in false false false false false :; do + . ./conf$$subs.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + + ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` + if test $ac_delim_n = $ac_delim_num; then + break + elif $ac_last_try; then + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done +rm -f conf$$subs.sh + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && +_ACEOF +sed -n ' +h +s/^/S["/; s/!.*/"]=/ +p +g +s/^[^!]*!// +:repl +t repl +s/'"$ac_delim"'$// +t delim +:nl +h +s/\(.\{148\}\)..*/\1/ +t more1 +s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ +p +n +b repl +:more1 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t nl +:delim +h +s/\(.\{148\}\)..*/\1/ +t more2 +s/["\\]/\\&/g; s/^/"/; s/$/"/ +p +b +:more2 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t delim +' >$CONFIG_STATUS || ac_write_fail=1 +rm -f conf$$subs.awk +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +_ACAWK +cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && + for (key in S) S_is_set[key] = 1 + FS = "" + +} +{ + line = $ 0 + nfields = split(line, field, "@") + substed = 0 + len = length(field[1]) + for (i = 2; i < nfields; i++) { + key = field[i] + keylen = length(key) + if (S_is_set[key]) { + value = S[key] + line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) + len += length(value) + length(field[++i]) + substed = 1 + } else + len += 1 + keylen + } + + print line +} + +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then + sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" +else + cat +fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ + || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 +_ACEOF + +# VPATH may cause trouble with some makes, so we remove sole $(srcdir), +# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and +# trailing colons and then remove the whole line if VPATH becomes empty +# (actually we leave an empty line to preserve line numbers). +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ +h +s/// +s/^/:/ +s/[ ]*$/:/ +s/:\$(srcdir):/:/g +s/:\${srcdir}:/:/g +s/:@srcdir@:/:/g +s/^:*// +s/:*$// +x +s/\(=[ ]*\).*/\1/ +G +s/\n// +s/^[^=]*=[ ]*$// +}' +fi + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +fi # test -n "$CONFIG_FILES" + + +eval set X " :F $CONFIG_FILES " +shift +for ac_tag +do + case $ac_tag in + :[FHLC]) ac_mode=$ac_tag; continue;; + esac + case $ac_mode$ac_tag in + :[FHL]*:*);; + :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; + :[FH]-) ac_tag=-:-;; + :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; + esac + ac_save_IFS=$IFS + IFS=: + set x $ac_tag + IFS=$ac_save_IFS + shift + ac_file=$1 + shift + + case $ac_mode in + :L) ac_source=$1;; + :[FH]) + ac_file_inputs= + for ac_f + do + case $ac_f in + -) ac_f="$ac_tmp/stdin";; + *) # Look for the file first in the build tree, then in the source tree + # (if the path is not absolute). The absolute path cannot be DOS-style, + # because $ac_f cannot contain `:'. + test -f "$ac_f" || + case $ac_f in + [\\/$]*) false;; + *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; + esac || + as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; + esac + case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac + as_fn_append ac_file_inputs " '$ac_f'" + done + + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + configure_input='Generated from '` + $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' + `' by configure.' + if test x"$ac_file" != x-; then + configure_input="$ac_file. $configure_input" + { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 +$as_echo "$as_me: creating $ac_file" >&6;} + fi + # Neutralize special characters interpreted by sed in replacement strings. + case $configure_input in #( + *\&* | *\|* | *\\* ) + ac_sed_conf_input=`$as_echo "$configure_input" | + sed 's/[\\\\&|]/\\\\&/g'`;; #( + *) ac_sed_conf_input=$configure_input;; + esac + + case $ac_tag in + *:-:* | *:-) cat >"$ac_tmp/stdin" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; + esac + ;; + esac + + ac_dir=`$as_dirname -- "$ac_file" || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + as_dir="$ac_dir"; as_fn_mkdir_p + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + + case $ac_mode in + :F) + # + # CONFIG_FILE + # + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# If the template does not know about datarootdir, expand it. +# FIXME: This hack should be removed a few years after 2.60. +ac_datarootdir_hack=; ac_datarootdir_seen= +ac_sed_dataroot=' +/datarootdir/ { + p + q +} +/@datadir@/p +/@docdir@/p +/@infodir@/p +/@localedir@/p +/@mandir@/p' +case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in +*datarootdir*) ac_datarootdir_seen=yes;; +*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 +$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + ac_datarootdir_hack=' + s&@datadir@&$datadir&g + s&@docdir@&$docdir&g + s&@infodir@&$infodir&g + s&@localedir@&$localedir&g + s&@mandir@&$mandir&g + s&\\\${datarootdir}&$datarootdir&g' ;; +esac +_ACEOF + +# Neutralize VPATH when `$srcdir' = `.'. +# Shell code in configure.ac might set extrasub. +# FIXME: do we really want to maintain this feature? +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_sed_extra="$ac_vpsub +$extrasub +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +:t +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +s|@configure_input@|$ac_sed_conf_input|;t t +s&@top_builddir@&$ac_top_builddir_sub&;t t +s&@top_build_prefix@&$ac_top_build_prefix&;t t +s&@srcdir@&$ac_srcdir&;t t +s&@abs_srcdir@&$ac_abs_srcdir&;t t +s&@top_srcdir@&$ac_top_srcdir&;t t +s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t +s&@builddir@&$ac_builddir&;t t +s&@abs_builddir@&$ac_abs_builddir&;t t +s&@abs_top_builddir@&$ac_abs_top_builddir&;t t +$ac_datarootdir_hack +" +eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ + >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + +test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && + { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && + { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ + "$ac_tmp/out"`; test -z "$ac_out"; } && + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&5 +$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&2;} + + rm -f "$ac_tmp/stdin" + case $ac_file in + -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; + *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; + esac \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + ;; + + + + esac + +done # for ac_tag + + +as_fn_exit 0 +_ACEOF +ac_clean_files=$ac_clean_files_save + +test $ac_write_fail = 0 || + as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 + + +# configure is writing to config.log, and then calls config.status. +# config.status does its own redirection, appending to config.log. +# Unfortunately, on DOS this fails, as config.log is still kept open +# by configure, so config.status won't be able to write to it; its +# output is simply discarded. So we exec the FD to /dev/null, +# effectively closing config.log, so it can be properly (re)opened and +# appended to by config.status. When coming back to configure, we +# need to make the FD available again. +if test "$no_create" != yes; then + ac_cs_success=: + ac_config_status_args= + test "$silent" = yes && + ac_config_status_args="$ac_config_status_args --quiet" + exec 5>/dev/null + $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false + exec 5>>config.log + # Use ||, not &&, to avoid exiting from the if with $? = 1, which + # would make configure fail if this is the last instruction. + $ac_cs_success || as_fn_exit 1 +fi +if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 +$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} +fi + diff --git a/config/confmod.in b/config/confmod.in new file mode 100644 index 00000000..1257f14b --- /dev/null +++ b/config/confmod.in @@ -0,0 +1,36 @@ +dnl Process this file with autoconf to produce a configure script. + +AC_INIT(Makefile.in) +AC_DISABLE_OPTION_CHECKING + +parentdir=`pwd` +relparentdir=. +configdir="configdir" + +while test "$parentdir" != "/" -a "$configdir" = "configdir"; do + if test -d "$parentdir/config" ; then + configdir=`echo $relparentdir | sed 's/^\.\///'`/config + else +changequote(, )dnl + parentdir=`echo $parentdir | sed 's/\/[^\/]*$//'` +changequote([, ])dnl + relparentdir=$relparentdir/.. + fi +done + +if test "$configdir" = "configdir" ; then + echo "Cannot find configure directory" + exit 1 +fi + +dnl Configuration Utilities +AC_CONFIG_AUX_DIR($configdir) + +dnl Include general file +sinclude(general.m4)dnl + +AC_SUBST(configdir) + +files=`find . -name "*.in" -print | grep -v "/config" | sed -e 's/.in$/ /g'` + +AC_OUTPUT($files) diff --git a/config/docs/CMakeLists.txt b/config/docs/CMakeLists.txt new file mode 100644 index 00000000..eb46e4c1 --- /dev/null +++ b/config/docs/CMakeLists.txt @@ -0,0 +1,2 @@ +# declare installation files +INSTALL(FILES config.txt dirstruc.txt envvars.txt macros.txt modules.txt DESTINATION ${DCMTK_INSTALL_DOCDIR} COMPONENT doc) diff --git a/config/docs/config.dox b/config/docs/config.dox new file mode 100644 index 00000000..56102313 --- /dev/null +++ b/config/docs/config.dox @@ -0,0 +1,40 @@ +/*! + +\page mod_config config: configuration utilities for dcmtk + +This module contains configuration files for the OFFIS "dcmtk" (DICOM Toolkit). +The configuration mechanism uses GNU autoconf / configure facilities. + +\section Files + +The following files provide further documentation: +\li \ref file_config +\li \ref file_dirstruc +\li \ref file_envvars +\li \ref file_macros +\li \ref file_modules + +\section sec_cxx11_support C++11 Support +DCMTK supports some C++11 features. See \ref cxx11_support for details. +*/ + +/*! + \page file_config config.txt file + \verbinclude config.txt +*/ +/*! + \page file_dirstruc dirstruc.txt file + \verbinclude dirstruc.txt +*/ +/*! + \page file_envvars envvars.txt file + \verbinclude envvars.txt +*/ +/*! + \page file_macros macros.txt file + \verbinclude macros.txt +*/ +/*! + \page file_modules modules.txt file + \verbinclude modules.txt +*/ diff --git a/config/docs/config.txt b/config/docs/config.txt new file mode 100644 index 00000000..ca0fed59 --- /dev/null +++ b/config/docs/config.txt @@ -0,0 +1,122 @@ +The config directory +==================== + +The "config" directory contains configuration files for the OFFIS DCMTK +(DICOM ToolKit) to be used with GNU autoconf / configure. See INSTALL file +in the root directory for details. + + +templates directory: +==================== + +The "templates" directory contains templates for Makefiles and configure +scripts used for the DCMTK modules. For more information see "dirstruc.txt". + + +include directory: +================== + +The "config/include" directory contains OS-specific configuration files. The +file "osconfig.h.in" is created by "configure.in" using "autoheader" from the +GNU autoconf system. + +All your source files (*.h, *.c, *.cc) must contain the following #include- +statement at the beginning (before everything else is defined): + + #include "dcmtk/config/osconfig.h" + +The file "osconfig.h" is created during the configuration step using GNU +autoconf. + + +Programs in config/: +==================== + +The configuration directory contains the following programs: + +autoall creates "configure" and "confmod" +mkinstalldirs creates recursive directories, used for "make install" +install-sh BSD-compatible install script, used in Makefiles +rootconf creates "Makefile" and "configure" script for the root + directory. If the "modules" file in the "config" directory + is available, the modules are extracted from this file. It + contains a whitespace separated list of module names. +configure main configure script created by "autoall" or "autoconf". + "configure" must be started from the "config" directory. +confmod configure script for the modules created by "autoall" or + "autoconf confmod.in > confmod". "confmod" cannot be started + from the "config" directory. See "modules.txt" for more + information. + +In every module's main directory the "configure.mod" script from the +"templates" directory must be present. + +To create the "configure" script in the "config" directory you must call +"autoconf" or "autoall". + + +Configuration files in config/: +=============================== + +configure.in to specify configurations for "osconfig.h" and "Makefile.def" +aclocal.m4 to define new tests for "configure" +general.m4 common configurations for "configure" und "confmod" +confmod.in to specify tests for "confmod" (the modules) + +For "confmod.in" see "modules.txt". + +Do not edit these files unless you really know what you do. Consult the +autoconf manual (in emacs and on paper). + + +configure.in aclocal.m4 +======================= + +"configure.in" contains configuration tests mainly for the main configuration +header file "osconfig.h" and the default Makefile configuration "Makefile.def". +"Makefile.def" defines the compiler, linker, default flags, and the library +manager. "configure.in" does not specify special configurations for the +Makefiles of the various modules. These configurations can be found in +"confmod.in" (see "modules.txt"). + +You can change configurations for different operating systems or compilers in +these files. Please consider the autoconf manual. This part describes changes +to the normal autoconf tests: + +Additional tests are defined in "aclocal.m4": + +AC_CHECK_GXXLIB: + +Works like AC_CHECK_LIB, but for libg++. This additional macro is necessary +because "/bin/sh" will not allow you to define a variable "ac_cv_lib_g++" +and AC_CHECK_LIB will fail for libg++. All symbols #defined by this macro +replace G++ by GXX. + +AC_CHECK_PROTOTYPE: + +Checks if there is a prototype declaration for the given function. If header +file(s) are given as argument 2, they are #included in the search. Otherwise +only predefined functions will be found. +Examples: + in configure.in: + AC_CHECK_PROTOTYPE(setsockopt, sys/types.h sys/socket.h) + AC_CHECK_PROTOTYPE(gethostid) + +AC_CHECK_DECLARATION: + +Checks if a certain type is declared in the #include files given as argument 2. +Example: + in configure.in: + AC_CHECK_DECLARATION(struct sembuf, sys/types.h sys/ipc.h sys/sem.h) + + +general.m4 +========== + +Contains configuration tests commonly used in the "configure" and the "modconf" +script. "configure.in" and "confmod.in" use a special include command to get +these configuration. You can change or add configuration tests for the +"config" directory and the modules' Makefiles in/to "general.m4". + + +Have Fun! diff --git a/config/docs/cxx11.dox b/config/docs/cxx11.dox new file mode 100644 index 00000000..b7742891 --- /dev/null +++ b/config/docs/cxx11.dox @@ -0,0 +1,116 @@ +/*! + +\page cxx11_support C++11 support in DCMTK + +You may compile DCMTK with C++11 support enabled. This may increase performance +since some operations can be performed in a more efficient manner, e.g. +utilizing +move semantics. +To create a C++11 build of DCMTK, you simply need to set the appropriate +compiler-flags while building it (e.g. -std=c++11). This will however not +enable DCMTK to use available C++11 features that aren't implicitly used by +legacy code. This is especially important regarding some C++11 classes DCMTK +directly supports, for example: + +\li OFunique_ptr (std::unique_ptr) +\li OFshared_ptr (std::shared_ptr) + +Since not every compiler supports C++11, legacy implementations for the +respective functionality have been created, which are enabled by default. + +If you use C++11 in your project, you may want to use the native C++11 classes +instead, so you don't need to convert your objects to use them with DCMTK. To +do so, you need to configure DCMTK to use the C++11 STL, which is described +below. + +

Enabling DCMTK to use the C++11 STL

+ +By enabling DCMTK to use the C++11 STL, you gain the following advantages: + +\li DCMTK will use available C++11 features instead of its only legacy + implementations. These are probably more efficient and complete. +\li The enabling of C++11 becomes part of DCMTK's configuration, which allows + DCMTK to assist you when checking for API/ABI (in-)compatibility between + C++11 and non C++11 builds. + +Trying to include a DCMTK build with C++11 STL enabled from a non C++11 +environment will give you the following error message: + +@verbatim +DCMTK was configured to use the C++11 STL, but your compiler is not configured for building with C++11 features. +@endverbatim + +To reduce DCMTK's implementation complexity, the C++11 STL shall only be used if +your compiler conforms closely to the C++11 Standard. As far as we know, +this is currently true for the following compilers: + +\li GNU C++ Compiler (g++) Version 4.8.1 or later. +\li Clang (clang++) Version 3.3 or later. + +To enable the C++11 STL, different steps are necessary on CMake and GNU +Autoconf, see the appropriate section below: + +

CMake

+ +CMake detects the C++11 compilers mentioned above and knows how to enable C++11 +features on these compilers. If your compiler was detected successfully, CMake +will give you the following message during configure: + +@verbatim +Info: Your compiler supports C++11. You may enable C++11 features via "DCMTK_USE_CXX11_STL" to create a C++11 build of DCMTK. +@endverbatim + +As mentioned in this message, you may enable the C++11 STL by setting +DCMTK_USE_CXX11_STL, for example via: + +@verbatim +cmake ... -DDCMTK_USE_CXX11_STL:BOOL=ON +@endverbatim + +Doing so will give you the following message during configure: + +@verbatim +Info: Configured DCMTK to use native C++11 features. +@endverbatim + +You may need to override the flags to enable C++11, for example to enable C++14 +instead. Doing so can be done via DCMTK_CXX11_FLAGS, for example: + +@verbatim +cmake ... -DDCMTK_USE_CXX11_STL:BOOL=ON -DDCMTK_CXX11_FLAGS=-std=c++14 +@endverbatim + +

Unsupported Compilers

+ +If CMake does not know how to enable C++11 on your compiler or your compiler +does not support C++11 completely, you will see the following warning message +when you try to enable DCMTK_USE_CXX11_STL anyway: + +@verbatim +DCMTK has been configured to use the C++11 STL, but the compiler does not seem to support C++11. +Override this warning by setting DCMTK_CXX11_FLAGS to tell DCMTK how to enable C++11 support for your compiler. +@endverbatim + +As the message states, you need to take care about configuring your compiler for +C++11 manually, for example by setting CMAKE_CXX_FLAGS appropriately. +Setting DCMTK_CXX11_FLAGS instead will have the same result (CMake +will set CMAKE_CXX_FLAGS based on DCMTK_CXX_FLAGS), but +the warning goes away and instead you will see the following output: + +@verbatim +Info: Enabling C++11 support with custom flags "< YOUR FLAGS >" for a potentially unsupported compiler. +@endverbatim + +

GNU Autoconf

+ +Our GNU Autoconf setup understands the argument \--with-cxx11-stl, +that may be used to configure DCMTK to use the C++11 STL. But this only enables +API/ABI checks and maps DCMTK's functionalities to the respective STL ones. You +still need to configure your compiler for C++11 manually, for example by setting +the CXXFLAGS like this when using GCC 4.9: + +@verbatim +./configure --with-cxx11-stl CXXFLAGS=-std=c++11 +@endverbatim + +*/ diff --git a/config/docs/dirstruc.txt b/config/docs/dirstruc.txt new file mode 100644 index 00000000..fa41580c --- /dev/null +++ b/config/docs/dirstruc.txt @@ -0,0 +1,30 @@ +Recommended project directory structure for the DCMTK project +============================================================= + +dcmtk + config + docs + include + templates + module1 + apps # application programs + data # support files + docs # documentation + etc # configuration files + include # include directory + libsrc # library sources + tests # test programs + module2 + ... + +If you use this structure, copy from the config/templates directory + Makefile.mod -> dcmtk/moduleX/Makefile.in + configure.mod -> dcmtk/moduleX/configure + +They can be used without any changes if you are using the structure above. + +There are more files in the template directory: + Makefile.lib: Sample Makefile.in for libraries in libsrc + Makefile.src: Sample Makefile.in for applications in apps, tests + +More information about configure.mod can be found in modules.txt diff --git a/config/docs/envvars.txt b/config/docs/envvars.txt new file mode 100644 index 00000000..2b1d0a5e --- /dev/null +++ b/config/docs/envvars.txt @@ -0,0 +1,53 @@ + +=========================== +DCMTK ENVIRONMENT VARIABLES +=========================== + +The behavior of the DCMTK tools and libraries can be modified by a +number of runtime environment variables which are explained below. + + +DCMDICTPATH + Affected: dcmdata + Explanation: On Unix platforms, all DCMTK applications load a DICOM + data dictionary from file upon startup. By default, the file + /usr/local/share/dcmtk/dicom.dic will be loaded. If the DCMDICTPATH + environment variable is set, the applications will attempt to load + DICOM data dictionaries specified in the DCMDICTPATH environment + variable instead. The DCMDICTPATH environment variable has the same + format as the shell PATH variable in that a colon (":") separates + entries. The data dictionary code will attempt to load each file + specified in the DCMDICTPATH environment variable. It is an error + if no data dictionary can be loaded. + On Win32 platforms, a built-in dictionary is used by default. If + the DCMDICTPATH environment variable is set, the applications will + attempt to load _additional_ DICOM data dictionaries specified in + the DCMDICTPATH environment variable instead. The DCMDICTPATH + environment variable has the same format as the shell PATH variable + in that a semicolon (";") separates entries. The data dictionary + code will attempt to load each file specified in the DCMDICTPATH + environment variable. + + See also: documentation in dcmdata/docs/datadict.txt or + /usr/local/share/doc/dcmtk/datadict.txt. + +TCP_BUFFER_LENGTH + Affected: dcmnet + Explanation: By default, DCMTK uses a TCP send and receive buffer + length of 64K. If the environment variable TCP_BUFFER_LENGTH is set, + it specifies an override for the TCP buffer length. The value is + specified in bytes, not in Kbytes. + +TCP_NODELAY + Affected: dcmnet + Explanation: If this environment variable contains a non-zero number, + the Nagle algorithm will not be disabled for TCP transport + connections. Also see documentation for macro + DONT_DISABLE_NAGLE_ALGORITHM in config/docs/macros.txt or + /usr/local/share/doc/dcmtk/macros.txt. + +TMPDIR + Affected: dcmnet + Explanation: Affects the implementation of the tempnam() emulation on + platforms where tempnam() is not defined. See tempnam(3S) man page + for a description. diff --git a/config/docs/macros.txt b/config/docs/macros.txt new file mode 100644 index 00000000..02090de5 --- /dev/null +++ b/config/docs/macros.txt @@ -0,0 +1,457 @@ +=================================== +DCMTK COMPILE TIME FLAGS AND MACROS +=================================== + +The behavior of several DCMTK tools and libraries can be modified by +a number of compile time flags (macros), which are explained below. +Most of these macros enable experimental or rarely needed features +in DCMTK, others disable certain functions. So please, use with care! + +ALLOW_ILLUMINATION_OVERRIDE + Affected: dcmprscu + Type of modification: Activates experimental or rarely used feature + Explanation: Allows the settings for Illumination and Reflected + Ambient Light, which are stored in a Stored Print object, to be + overridden from the print job command file. + +BUGGY_IMPLEMENTATION_CLASS_UID_PREFIX + Affected: storescp + Type of modification: Activates workaround for known bug in other product + Explanation: The dcmnet module contains a workaround that allows to + communicate with some buggy Storage SCUs. If the global flag + dcmPeerRequiresExactUIDCopy is enabled, an illegal space padding in + the Affected SOP Instance UID field of the C-STORE-RQ message is + retained in the corresponding C-STORE-RSP message. When this + preprocessor macro is defined, it should contain the prefix of an + implementation class UID of an implementation known to exhibit the + buggy behavior. The workaround is then activated in storescp + whenever a Storage SCU with the given implementation class UID root + connects. + +DCMTK_BUILD_DATE + Affected: dcmdata + Type of modification: Toolkit customization + Explanation: When this macro is defined (typically in config/Makefile.def), + the given date is used instead of the official DCMTK release data. This + allows for example to specify the date of a current development snapshot. + +DCMTK_BUILD_IN_PROGRESS + Affected: all modules + Type of modification: Toolkit customization + Explanation: When building DLLs, exported symbols must be marked differently + if the DLL itself is built or when the DLL shall be used. This macro is + defined when the DCMTK gets built and should not be defined when user code + that just uses the DCMTK is built. Based on this, the correct annotation + gets selected and is used in the code. There should be no valid reasons to + define this macro yourself since this is done automatically by the build + system. + +DCMTK_GUI + Affected: all modules + Type of modification: Activates experimental or rarely used feature + Explanation: When this macro is defined, DCMTK re-assigns the standard + output and error streams maintained by ofConsole to string streams. + This will allow a GUI based application to extract the messages and + either present them to the user or store them in a log file. See + comments in ofstd/include/dcmtk/ofstd/ofconsol.h. + +DCMTK_USE_CXX11_STL + Affected: ofstd + Type of modification: Activates feature + Explanation: DCMTK_USE_CXX11_STL is defined when the appropriate options are + passed to the configuration system. DCMTK will then use the native C++11 + STL classes and functions instead of it's own (legacy) implementations. + +DICOMDIR_WITHOUT_BACKUP + Affected: dcmdata + Type of modification: Disables feature + Explanation: By default DCMTK creates a backup of an existing DICOMDIR + (using the name DICOMDIR.$$$) when a DcmDicomDir object is written + to file. The creation of the backup can be disabled with this macro. + +DISABLE_COMPRESSION_EXTENSION + Affected: dcmqrdb + Type of modification: Disables feature + Explanation: Disables the support of compression (various transfer + syntaxes) in dcmqrdb, a feature which is still experimental. + +DISABLE_OFSTD_ATOF + Affected: all modules + Type of modification: Disables feature + Explanation: By default, DCMTK uses its own implementation of atof() + to convert strings to double numbers in a locale-independent manner. + This flag forces DCMTK to use the standard sscanf() function + instead, which is normally much faster and gives a higher precision + than DCMTK's built in code, but is locale dependent, i.e. cannot be + used with locales such as German since DICOM decimal strings always + use the Posix locale. + +DISABLE_OFSTD_FTOA + Affected: all modules + Type of modification: Disables feature + Explanation: By default, DCMTK uses its own implementation to convert + double numbers to strings to in a locale-independent manner. + This flag forces DCMTK to use the standard sprintf() function + instead, which is locale dependent, i.e. cannot be used with locales + such as German since DICOM decimal strings always use the Posix + locale. + +DISABLE_PORT_PERMISSION_CHECK + Affected: most/all network server tools + Type of modification: Disables feature + Explanation: By default, most network server tools (e.g. storescp) check + for sufficient privileges to listen on the specified port (if geteuid() + is available on the particular system). For examples, on Unix systems + listening on port < 1024 usually requires root privileges. However, + the port permission check might prevent the tool from being run on such + ports on systems with fine-grained permission control (e.g. Linux). + Therefore, this check can be disabled using this flag. + +DISABLE_RECV_TIMEOUT + Affected: dcmnet + Type of modification: Disables feature + Explanation: By default, DCMTK specifies a timeout of 60 seconds for + the recv() function. This is especially useful in cases where the + receiver (e.g. storescp) looses the connection to the sender because + the network cable is pulled (e.g. for a mobile device). This flag + disables the call to the setsockopt() function so that no timeout is + specified. + +DISABLE_SEND_TIMEOUT + Affected: dcmnet + Type of modification: Disables feature + Explanation: By default, DCMTK specifies a timeout of 60 seconds for + the send() function. This is especially useful in cases where the + sender (e.g. storescu) looses the connection to the receiver because + the network cable is pulled (e.g. for a mobile device). This flag + disables the call to the setsockopt() function so that no timeout is + specified. + +DONT_DISABLE_NAGLE_ALGORITHM + Affected: dcmnet + Type of modification: Disables feature + Explanation: By default, DCMTK disables the so-called Nagle algorithm + for each DICOM transport connection. This provides a 2-4 times + performance improvement (WinNT4/SP4, 100Mbit/s Ethernet). Effects on + other environments are unknown. When compiled with this macro, the + code affecting the Nagle algorithm is disabled. See documentation + for environment variable TCP_NODELAY in config/docs/envvars.txt. + +DONT_LOAD_EXTERNAL_DICTIONARIES + Affected: dcmdata + Type of modification: Disables feature + Explanation: By default, DCMTK loads data dictionaries from files at + application start (before the main function is called). These files + are either specified by the DCMDICTPATH environment variable or the + default files are used. This flag disables the loading of external + dictionaries from file at application start, which might be useful + when only the builtin dictionary should be used. However, if no + dictionary gets loaded, this is likely to cause unexpected behavior. + Even if this flag is defined, the reloadDictionaries() method can be + used to load the external dictionaries after application start. + +DOXYGEN + Affected: everything + Type of modification: Hides complexity from Doxygen + Explanation: Doxygen is unable to parse some complex statements correctly + and it is sometimes sufficient to provide documentation for the basic + functionality instead of documenting every detail. + This macro is defined when creating the documentation with Doxygen and + should NEVER be defined when compiling DCMTK with a C/C++ compiler. + NOTE: Doxygen is still unable to expand some macros correctly + (e.g. HAVE_WINDOWS_H). Using this macro at the appropriate locations + could be a solution for this problem. + +ENABLE_BUILTIN_DICTIONARY + Affected: dcmdata + Type of modification: Enables or disables population of builtin dictionary + Explanation: If enabled, DCMTK's global builtin dictionary, that is always + loaded on startup, is populated with known DICOM tags. Otherwise, the + builtin dictionary stays empty. For more further information about + dictionary configuration read dcmdata/docs/datadict.txt. + +EXPERIMENTAL_READ_FROM_FILE + Affected: dump2dcm + Type of modification: Activates experimental or rarely used feature + Explanation: When this macro is defined, the relatively new function + createValueFromTempFile() is used for reading large binary data files. + +HAVE_STD_STRING + Affected: ofstd + Type of modification: Activates feature + Explanation: When this macro is defined, the ANSI C++ standard string + class is used instead of DCMTK's own implementation. + +HAVE_STL + Affected: ofstd + Type of modification: Activates feature + Explanation: When this macro is defined, the STL (standard template + library) list, map, stack, vector and auto_ptr classes as well as + the STL algorithms are used instead of DCMTK's own implementations. + +HAVE_STL_ALGORITHMS + Affected: ofstd + Type of modification: Activates feature + Explanation: When this macro is defined, the STL (standard template + library) algorithms are used instead of DCMTK's own implementation. + Also see HAVE_STL. + +HAVE_STL_AUTO_PTR + Affected: ofstd + Type of modification: Activates feature + Explanation: When this macro is defined, the STL (standard template + library) auto_ptr class is used instead of DCMTK's own implementation. + Also see HAVE_STL. + +HAVE_STL_LIST + Affected: ofstd + Type of modification: Activates feature + Explanation: When this macro is defined, the STL (standard template + library) list class is used instead of DCMTK's own implementation. + Also see HAVE_STL. + +HAVE_STL_MAP + Affected: ofstd + Type of modification: Activates feature + Explanation: When this macro is defined, the STL (standard template + library) map class is used instead of DCMTK's own implementation. + Also see HAVE_STL. + +HAVE_STL_STACK + Affected: ofstd + Type of modification: Activates feature + Explanation: When this macro is defined, the STL (standard template + library) stack class is used instead of DCMTK's own implementation. + Also see HAVE_STL. + +HAVE_STL_VECTOR + Affected: ofstd + Type of modification: Activates feature + Explanation: When this macro is defined, the STL (standard template + library) vector class is used instead of DCMTK's own implementation. + Also see HAVE_STL. + +LOCK_IMAGE_FILES + Affected: dcmpstat, dcmqrdb + Type of modification: Activates experimental or rarely used feature + Explanation: When this macro is defined, the DICOM image file to be + send or received/created is locked exclusively. + +LOG4CPLUS_DISABLE_xxx +(where xxx is one of TRACE, DEBUG, INFO, WARN, ERROR and FATAL) + Affected: oflog + Type of modification: Disables feature + Explanation: When one of these macros is defined all log message of + this type and lower are disabled and optimized away. + +NO_GET_SUPPORT + Affected: dcmqrdb + Type of modification: Disables feature + Explanation: Disables the experimental C-GET support in dcmqrdb. + +NO_IOS_BASE_ASSIGN + Affected: all command line tools + Type of modification: Disables feature + Explanation: On Win32 platforms, the prepareCmdLineArgs() function + maps cout to cerr by assignment. This does not work with all + iostream implementations and can, therefore, be disabled with this + macro. + +NO_PATIENTSTUDYONLY_SUPPORT + Affected: dcmqrdb + Type of modification: Disables feature + Explanation: Disables support for the Patient/Study Only Query/Retrieve + Model in dcmqrdb. + +NO_WINDOWS95_ADDRESS_TRANSLATION_WORKAROUND + Affected: dcmnet + Type of modification: Disables feature + Explanation: Under Windows 95 gethostbyname() will not accept an IP + address e.g. "134.106.1.1". This appears to work without problems + with other Windows versions and several Unix variants. As a + workaround, DCMTK explicitly handles the IP address case. The + workaround can be disabled with this macro. + +OFCONDITION_IMPLICIT_BOOL_CONVERSION + Affected: ofstd + Type of modification: Activates experimental or rarely used feature + Explanation: Activates an implicit conversion from OFCondition to + OFBool, i.e. operator OFBool(). Implicit conversion might not always + be a good idea since it can hide unwanted constructs. Therefore, + this operator is disabled by default. + +ON_THE_FLY_COMPRESSION + Affected: storescu + Type of modification: Activates experimental or rarely used feature + Explanation: When this macro is defined, the storescu tries to compress + or decompress the DICOM image to be sent (if required) depending on + the negotiated transfer syntax. + +OLD_USER_INFO_SUB_ITEM_ORDER + Affected: dcmnet + Type of modification: Activates experimental or rarely used feature + Explanation: Prior DCMTK releases did not encode A-ASSOCIATE user + information sub-items in ascending order, i.e. they sent 55H + followed by 54H and 56H. This behavior has been "legalized" by + DICOM CP 280 but is known to create problems with some other + toolkits. The current DCMTK release always sends the user + information sub-items in ascending order, but can be "forced" with + this macro to revert to the old behavior. It should be re-activated + for testing purposes only. + +PASTEL_COLOR_OUTPUT + Affected: dcmimgle, dcmimage + Type of modification: Activates experimental or rarely used feature + Explanation: Activates experimental code in dcmimgle/dcmimage that + renders monochrome images with pastel colors. + +PDV_TEST + Affected: dcmnet + Type of modification: Activates experimental or rarely used feature + Explanation: Causes the network module to insert a false, zero-length + PDV (2 byte header) into each P-DATA-PDU. + +PIXELSTACK_MEMORY_LEAK_WORKAROUND + Affected: dcmdata + Type of modification: Activates experimental or rarely used feature + Explanation: On certain platforms there seems to be a memory leak in + DcmDataset::chooseRepresentation(). The work-around activated by + this macro should solve this issue. + +PRINT_REPLACED_DICTIONARY_ENTRIES + Affected: dcmdata + Type of modification: Activates experimental or rarely used feature + Explanation: When reading the data dictionary, duplicate entries (i.e. + entries replacing an older entry in the dictionary) are reported on + console if compiled with this macro. Useful for testing a new + dictionary version. + +REJECT_FILE_IF_META_GROUP_LENGTH_ABSENT + Affected: dcmdata + Type of modification: Disables feature + Explanation: When reading the a file that contains an incorrect meta + header where meta header group length (0002,0000) is absent, DCMTK + since release 3.5.4 nevertheless tries to parse the file, unless this + macro is enabled, in which case the behavior up to DCMTK 3.5.3 is + retained. + +RETAIN_ASSOCIATION + Affected: dcmqrti + Type of modification: Activates experimental or rarely used feature + Explanation: Keeps association to remote Query SCP open after + study/series/image listing. Default behavior is to open new + association for each query. + +REVERSE_OVERLAY_ORIGIN_ORDER + Affected: dcmimgle + Type of modification: Activates experimental or rarely used feature + Explanation: When compiled with this macro, dcmimgle assumes that the + values in DCM_ImageFrameOrigin are in reverse order, i.e. X\Y + instead of Y\X. + +SITE_UID_ROOT + Affected: dcmdata + Type of modification: Site customization + Explanation: dcmdata contains a routine that generates DICOM unique + identifiers (UIDs). By default, these are constructed from the OFFIS + UID namespace, i.e. using the OFFIS UID Root "1.2.276.0.7230010.3". + Users who prefer to let the toolkit generate UIDs from their own UID + namespace should compile DCMTK with SITE_UID_ROOT defined to their own + UID root. Please make sure that the resulting UIDs do not exceed the + 64 characters limit! + +STARVIEW + Affected: dcmimgle, dcmimage + Type of modification: Activates experimental or rarely used feature + Explanation: Enables support for old StarView 2 GUI class library from + Star Division. + +STRICT_COMPARE + Affected: dcmqrdb + Type of modification: Activates experimental or rarely used feature + Explanation: By default, dcmqrdb ignores illegal leading and trailing + space characters when comparing UIDs. This behavior can be modified + by defining this macro. + +SUPPRESS_CREATE_STAMP + Affected: dcmdata + Type of modification: Activates experimental or rarely used feature + Explanation: When defined, suppresses the creation of a time stamp + comment when re-generating dcdeftag.h and dcdictbi.cc. + +USE__LOCKING + Affected: dcmnet + Type of modification: Activates alternative implementation + Explanation: Activates an alternative emulation of flock() on Win32 + platforms using _locking(). This version should only be used on + compilers where _get_osfhandle() is not available since it does not + implement shared locks. + +USE_BINARY_MODE_FOR_STDOUT_ON_WINDOWS + Affected: dcmdata + Type of modification: Activates experimental or rarely used feature + Explanation: On Windows systems, the standard output (stdout) is opened in + text mode by default. Therefore, the binary output of tools like dcm2pnm + to stdout does not work correctly (in contrast to Unix systems). When + this preprocessor macro is defined, the binary mode is enabled for stdout. + However, this causes newlines in the textual output to be converted to LF + only (instead of CR LF which would be the usual translation for Windows). + +USE_NULL_SAFE_OFSTRING + Affected: ofstd + Type of modification: Activates feature + Explanation: When this macro is defined, OFString(NULL) results in an + empty string. If this macro is not defined, OFString(NULL) causes a + NULL pointer dereference. This macro has no effect when + HAVE_STD_STRING is also defined. Currently, this macro is always defined + by DCMTK's Makefiles. This will change in future releases. + +USING_STD_NAMESPACE + Affected: all modules + Type of modification: Re-activated behavior of earlier DCMTK releases + Explanation: DCMTK by default does not anymore pollute the default namespace + by importing namespace std. Earlier releases did this to simplify + compatibility with older compilers where STL classes were not consistently + defined in namespace std. We now have configure macros which should care + for this. If user code still relies on namespace std to be included, + compile with this macro defined. + +WIDE_CHAR_FILE_IO_FUNCTIONS + Affected: ofstd + Type of modification: Activates feature + Explanation: In addition to the standard file I/O functions, the OFFile class + also defines the corresponding wide character functions from C99 standard. + Since these functions are not yet supported by all compilers and the + current implementation is Windows-specific, this feature is disabled by + default. When using CMake, you can enable this macro by setting the CMake + option DCMTK_WIDE_CHAR_FILE_IO_FUNCTIONS to "on". + +WIDE_CHAR_MAIN_FUNCTION + Affected: currently not used + Type of modification: Activates experimental or rarely used feature + Explanation: On Windows (at least for MSVC), a different main function has + to be used in order to get the command line arguments with wide character + encoding (UTF-16). By defining this flag, the macro DCMTK_MAIN_FUNCTION + expands to wmain() instead of main(). When using CMake, you can enable + this macro by setting the CMake option DCMTK_WIDE_CHAR_MAIN_FUNCTION to + "on". Usually, WIDE_CHAR_FILE_IO_FUNCTIONS should also be enabled. + +WRITE_VERY_LARGE_CHUNKS + Affected: dcmdata + Type of modification: Re-activated behavior of earlier DCMTK releases + Explanation: On Windows (at least for some versions of MSVC), calls to + fwrite() for more than 67,076,095 bytes (a bit less than 64 MByte) fail if + we're writing to a network share. See MSDN KB899149. As a workaround, we + always write in chunks of 32M which should hardly negatively affect + performance. This macro enables the behavior of earlier DCMTK releases, + i.e. to always call fwrite with as much data as possible, which is known + not to work correctly on Win32 but might offer very minor performance + benefits on other platforms. + +ZLIB_ENCODE_RFC1950_HEADER + Affected: dcmdata + Type of modification: Activates experimental or rarely used feature + Explanation: When this macro is defined, the deflated ZLIB format is created + instead of the deflated bitstream format (i.e. RFC 1950 instead of RFC + 1951). Please note that the resulting bitstream is not DICOM compliant. + So, use only for testing, and use with care! diff --git a/config/docs/modules.txt b/config/docs/modules.txt new file mode 100644 index 00000000..3b2b8678 --- /dev/null +++ b/config/docs/modules.txt @@ -0,0 +1,65 @@ +Configuration of the different Modules +====================================== + +The following files in the "config" directory are used for the configuration +of the DCMTK modules: + +confmod.in definition of configuration tests for modules +confmod creates "configure" for modules +general.m4 general configuration tests (see "config.txt") +Makefile.def general default Makefile definitions for all modules, generated + by "configure" +templates/configure.mod + "configure" for the modules' directories, must be copied to the + main module directory (see "dirstruc.txt") +include/dcmtk/config/osconfig.h + definition that must be included into the modules' source + files, generated by "configure" + +"confmod" must be copied to the module's main directory and renamed to +"configure". + + +Modules configure +================= + +This configure script runs the modules' and the main configure script in the +"config" directory (using special options): + +Syntax: + configure [-a|-c] + +Purpose: + Without options, this script calls "confmod" in the "config" directory + to create the configuration for the Makefiles in the module. + Using -a mean that first the "configure" in the "config" directory is + called and then "confmod". With -c only the "configure" in the + "config" directory is started. The "configure" options are passed to + the called scripts. + To determine the "config" directory the script searches from the local + directory to the root to find a directory named "config". The output + of the "confmod" script (*.cache, *.status, *.log) is stored in the + module's directory. It is not possible to call "confmod" from the + "config" directory. + +"confmod.in" stores the configurations that must be used in the modules and not +in the "config" directory. This is mainly used to define variables that +specify the "config" directory and the default Makefile template. + + +Modules Makefiles +================= + +All Makefiles in the modules' directories must include the following lines: + +@SET_MAKE@ + +SHELL = /bin/sh +VPATH = @srcdir@:@top_srcdir@/include:@top_srcdir@/@configdir@/include +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +configdir = @top_srcdir@/@configdir@ + +include $(configdir)/@common_makefile@ + +See the Makefile.* in the config/templates directory. diff --git a/config/general.m4 b/config/general.m4 new file mode 100644 index 00000000..1d3d6f6e --- /dev/null +++ b/config/general.m4 @@ -0,0 +1,7 @@ +dnl This file is includes into configure.in + +dnl Get configuration directory +AC_PROG_MAKE_SET +AC_PREFIX_DEFAULT(/usr/local) +common_makefile=Makefile.def +AC_SUBST(common_makefile) diff --git a/config/include/dcmtk/config/osconfig.h.in b/config/include/dcmtk/config/osconfig.h.in new file mode 100644 index 00000000..0b7399b2 --- /dev/null +++ b/config/include/dcmtk/config/osconfig.h.in @@ -0,0 +1,1096 @@ +/* include/dcmtk/config/osconfig.h.in. Generated from configure.in by autoheader. */ + +#ifndef OSCONFIG_H +#define OSCONFIG_H + +/* +** Define enclosures for include files with C linkage (mostly system headers) +*/ +#ifdef __cplusplus +#define BEGIN_EXTERN_C extern "C" { +#define END_EXTERN_C } +#else +#define BEGIN_EXTERN_C +#define END_EXTERN_C +#endif + +/* MinGW needs some special handling because it is a mixture of WIN32 and Posix. + * The following settings are not tested by configure but need to be set for MinGW. + */ +#ifdef __MINGW32__ +#define HAVE_WINDOWS_H 1 +#define HAVE_WINSOCK_H 1 +#define NO_IOS_BASE_ASSIGN 1 +#define ENVIRONMENT_PATH_SEPARATOR ';' +#endif + +/* Define if alignas supports typedefs */ +#undef ALIGNAS_SUPPORTS_TYPEDEFS + +/* Define if __attribute__((aligned)) supports templates */ +#undef ATTRIBUTE_ALIGNED_SUPPORTS_TEMPLATES + +/* Define the canonical host system type as a string constant. */ +#undef CANONICAL_HOST_TYPE + +/* Define if char is unsigned on the C compiler */ +#undef C_CHAR_UNSIGNED + +/* Define to the inline keyword supported by the C compiler, if any, or to the + empty string */ +#undef C_INLINE + +/* Define if >> is unsigned on the C compiler */ +#undef C_RIGHTSHIFT_UNSIGNED + +/* Define the DCMTK default path. */ +#undef DCMTK_PREFIX + +/* Enable or disable C++11 while building DCMTK. */ +#undef DCMTK_USE_CXX11_STL + +/* Empty default data dictionary path for the dcmdata library package. */ +#undef DCM_DICT_DEFAULT_PATH + +/* Define the default directory where configuration files reside. */ +#undef DEFAULT_CONFIGURATION_DIR + +/* Define the default directory where support data files reside. */ +#undef DEFAULT_SUPPORT_DATA_DIR + +/* Define if we are compiling for loading external dictionary from default + path. */ +#undef ENABLE_EXTERNAL_DICTIONARY + +/* Define if we are compiling with built-in dictionary */ +#undef ENABLE_BUILTIN_DICTIONARY + +/* Define if we are compiling for enabling external private tag dictionary. */ +#undef ENABLE_PRIVATE_TAGS + +/* Define the environment variable path separator. */ +#ifndef ENVIRONMENT_PATH_SEPARATOR +#define ENVIRONMENT_PATH_SEPARATOR ':' +#endif + +/* Define to 1 if you have the `accept' function. */ +#undef HAVE_ACCEPT + +/* Define to 1 if you have the `access' function. */ +#undef HAVE_ACCESS + +/* Define to 1 if you have the header file. */ +#undef HAVE_ALLOCA_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_ARPA_INET_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_ASSERT_H + +/* Define if __attribute__((aligned)) is available */ +#undef HAVE_ATTRIBUTE_ALIGNED + +/* Define to 1 if you have the `bcmp' function. */ +#undef HAVE_BCMP + +/* Define to 1 if you have the `bcopy' function. */ +#undef HAVE_BCOPY + +/* Define to 1 if you have the `bind' function. */ +#undef HAVE_BIND + +/* Define to 1 if you have the `bzero' function. */ +#undef HAVE_BZERO + +/* Define if your system declares the return type of strerror_r as char * + instead of int */ +#undef HAVE_CHARP_STRERROR_R + +/* Define if your C++ compiler can work with class templates */ +#undef HAVE_CLASS_TEMPLATE + +/* Define to 1 if you have the header file. */ +#undef HAVE_CLIMITS + +/* Define to 1 if you have the header file. */ +#undef HAVE_CMATH + +/* Define to 1 if you have the `connect' function. */ +#undef HAVE_CONNECT + +/* define if the compiler supports const_cast<> */ +#undef HAVE_CONST_CAST + +/* Define to 1 if you have the header file. */ +#undef HAVE_CSTDARG + +/* Define to 1 if you have the header file. */ +#undef HAVE_CSTDDEF + +/* Define to 1 if you have the header file. */ +#undef HAVE_CSTDINT + +/* Define to 1 if you have the header file. */ +#undef HAVE_CSTDIO + +/* Define to 1 if you have the header file. */ +#undef HAVE_CTYPE_H + +/* Define to 1 if you have the `cuserid' function. */ +#undef HAVE_CUSERID + +/* Define if bool is a built-in type */ +#undef HAVE_CXX_BOOL + +/* Define if volatile is a known keyword */ +#undef HAVE_CXX_VOLATILE + +/* Define if "const" is supported by the C compiler */ +#undef HAVE_C_CONST + +/* Define if your system has a declaration for socklen_t in sys/types.h + sys/socket.h */ +#undef HAVE_DECLARATION_SOCKLEN_T + +/* Define if your system has a declaration for std::ios_base::openmode in + iostream.h */ +#undef HAVE_DECLARATION_STD__IOS_BASE__OPENMODE + +/* Define if your system has a declaration for struct utimbuf in sys/types.h + utime.h sys/utime.h */ +#undef HAVE_DECLARATION_STRUCT_UTIMBUF + +/* Define if the compiler supports default constructor detection via SFINAE */ +#undef HAVE_DEFAULT_CONSTRUCTOR_DETECTION_VIA_SFINAE + +/* Define to 1 if you have the header file, and it defines `DIR'. + */ +#undef HAVE_DIRENT_H + +/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */ +#undef HAVE_DOPRNT + +/* define if the compiler supports dynamic_cast<> */ +#undef HAVE_DYNAMIC_CAST + +/* Define if your system cannot pass command line arguments into main() (e.g. Macintosh). */ +/* #undef HAVE_EMPTY_ARGC_ARGV */ + +/* Define if your system provides ENAMETOOLONG errno value. */ +#undef HAVE_ENAMETOOLONG + +/* Define to 1 if you have the header file. */ +#undef HAVE_ERRNO_H + +/* Define if your C++ compiler supports the explicit template specialization + syntax */ +#undef HAVE_EXPLICIT_TEMPLATE_SPECIALIZATION + +/* Define to 1 if you have the `fcntl' function. */ +#undef HAVE_FCNTL + +/* Define to 1 if you have the header file. */ +#undef HAVE_FCNTL_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_FENV_H + +/* Define to 1 if you have the `finite' function. */ +#undef HAVE_FINITE + +/* Define to 1 if you have the header file. */ +#undef HAVE_FLOAT_H + +/* Define to 1 if you have the `flock' function. */ +#undef HAVE_FLOCK + +/* Define to 1 if you have the header file. */ +#undef HAVE_FNMATCH_H + +/* Define to 1 if you have the `fork' function. */ +#undef HAVE_FORK + +/* Define to 1 if the system has the type `fpos64_t'. */ +#undef HAVE_FPOS64_T + +/* Define to 1 if fseeko (and presumably ftello) exists and is declared. */ +#undef HAVE_FSEEKO + +/* Define to 1 if you have the header file. */ +#undef HAVE_FSTREAM + +/* Define to 1 if you have the header file. */ +#undef HAVE_FSTREAM_H + +/* Define to 1 if you have the `ftime' function. */ +#undef HAVE_FTIME + +/* Define if your C++ compiler can work with function templates */ +#undef HAVE_FUNCTION_TEMPLATE + +/* Define to 1 if you have the `getaddrinfo' function. */ +#undef HAVE_GETADDRINFO + +/* Define to 1 if you have the `getenv' function. */ +#undef HAVE_GETENV + +/* Define to 1 if you have the `geteuid' function. */ +#undef HAVE_GETEUID + +/* Define to 1 if you have the `getgrnam' function. */ +#undef HAVE_GETGRNAM + +/* Define to 1 if you have the `getgrnam_r' function. */ +#undef HAVE_GETGRNAM_R + +/* Define to 1 if you have the `gethostbyaddr_r' function. */ +#undef HAVE_GETHOSTBYADDR_R + +/* Define to 1 if you have the `gethostbyname' function. */ +#undef HAVE_GETHOSTBYNAME + +/* Define to 1 if you have the `gethostbyname_r' function. */ +#undef HAVE_GETHOSTBYNAME_R + +/* Define to 1 if you have the `gethostid' function. */ +#undef HAVE_GETHOSTID + +/* Define to 1 if you have the `gethostname' function. */ +#undef HAVE_GETHOSTNAME + +/* Define to 1 if you have the `getlogin' function. */ +#undef HAVE_GETLOGIN + +/* Define to 1 if you have the `getpid' function. */ +#undef HAVE_GETPID + +/* Define to 1 if you have the `getpwnam' function. */ +#undef HAVE_GETPWNAM + +/* Define to 1 if you have the `getpwnam_r' function. */ +#undef HAVE_GETPWNAM_R + +/* Define to 1 if you have the `getsockname' function. */ +#undef HAVE_GETSOCKNAME + +/* Define to 1 if you have the `getsockopt' function. */ +#undef HAVE_GETSOCKOPT + +/* Define to 1 if you have the `getuid' function. */ +#undef HAVE_GETUID + +/* Define to 1 if you have the `gmtime_r' function. */ +#undef HAVE_GMTIME_R + +/* Define if __alignof__ is available */ +#undef HAVE_GNU_ALIGNOF + +/* Define to 1 if you have the header file. */ +#undef HAVE_GRP_H + +/* Define to 1 if you have the `htonl' function. */ +#undef HAVE_HTONL + +/* Define to 1 if you have the `htons' function. */ +#undef HAVE_HTONS + +/* Define to 1 if you have the header file. */ +#undef HAVE_IEEEFP_H + +/* Define to 1 if you have the `index' function. */ +#undef HAVE_INDEX + +/* Define to 1 if the system has the type `int64_t'. */ +#undef HAVE_INT64_T + +/* Define if your system declares argument 3 of accept() as int * instead of + size_t * or socklen_t * */ +#undef HAVE_INTP_ACCEPT + +/* Define if your system declares argument 5 of getsockopt() as int * instead + of size_t * or socklen_t */ +#undef HAVE_INTP_GETSOCKOPT + +/* Define if your system declares argument 2-4 of select() as int * instead of + struct fd_set * */ +#undef HAVE_INTP_SELECT + +/* Define to 1 if you have the header file. */ +#undef HAVE_INTTYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_IOMANIP + +/* Define to 1 if you have the header file. */ +#undef HAVE_IOMANIP_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_IOSTREAM + +/* Define to 1 if you have the header file. */ +#undef HAVE_IOSTREAM_H + +/* Define if your system defines ios::nocreate in iostream.h */ +#undef HAVE_IOS_NOCREATE + +/* Define to 1 if you have the header file. */ +#undef HAVE_IO_H + +/* Define to 1 if you have the `isinf' function. */ +#undef HAVE_ISINF + +/* Define to 1 if you have the `isnan' function. */ +#undef HAVE_ISNAN + +/* Define to 1 if you have the header file. */ +#undef HAVE_ISO646_H + +/* Define to 1 if you have the `itoa' function. */ +#undef HAVE_ITOA + +/* Define if LFS (large file support) is available */ +#undef HAVE_LFS_SUPPORT + +/* Define to 1 if you have the header file. */ +#undef HAVE_LIBC_H + +/* Define to 1 if you have the `iostream' library (-liostream). */ +#undef HAVE_LIBIOSTREAM + +/* Define to 1 if you have the `nsl' library (-lnsl). */ +#undef HAVE_LIBNSL + +/* Define to 1 if you have the header file. */ +#undef HAVE_LIBPNG_PNG_H + +/* Define to 1 if you have the `socket' library (-lsocket). */ +#undef HAVE_LIBSOCKET + +/* Define if libtiff supports LZW compression */ +#undef HAVE_LIBTIFF_LZW_COMPRESSION + +/* Define to 1 if you have the header file. */ +#undef HAVE_LIMITS_H + +/* Define to 1 if you have the `listen' function. */ +#undef HAVE_LISTEN + +/* Define to 1 if you have the header file. */ +#undef HAVE_LOCALE_H + +/* Define to 1 if you have the `localtime_r' function. */ +#undef HAVE_LOCALTIME_R + +/* Define to 1 if you have the `lockf' function. */ +#undef HAVE_LOCKF + +/* Define to 1 if the system has the type `longlong'. */ +#undef HAVE_LONGLONG + +/* Define to 1 if you support file names longer than 14 characters. */ +#undef HAVE_LONG_FILE_NAMES + +/* Define to 1 if the system has the type `long long'. */ +#undef HAVE_LONG_LONG + +/* Define to 1 if you have the `lstat' function. */ +#undef HAVE_LSTAT + +/* Define to 1 if you have the `malloc_debug' function. */ +#undef HAVE_MALLOC_DEBUG + +/* Define to 1 if you have the header file. */ +#undef HAVE_MALLOC_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_MATH_H + +/* Define to 1 if you have the `mbstowcs' function. */ +#undef HAVE_MBSTOWCS + +/* Define to 1 if you have the `memcmp' function. */ +#undef HAVE_MEMCMP + +/* Define to 1 if you have the `memcpy' function. */ +#undef HAVE_MEMCPY + +/* Define to 1 if you have the `memmove' function. */ +#undef HAVE_MEMMOVE + +/* Define to 1 if you have the header file. */ +#undef HAVE_MEMORY_H + +/* Define to 1 if you have the `memset' function. */ +#undef HAVE_MEMSET + +/* Define to 1 if you have the `mkstemp' function. */ +#undef HAVE_MKSTEMP + +/* Define to 1 if you have the `mktemp' function. */ +#undef HAVE_MKTEMP + +/* Define to 1 if you have the `nanosleep' function. */ +#undef HAVE_NANOSLEEP + +/* Define to 1 if you have the header file, and it defines `DIR'. */ +#undef HAVE_NDIR_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_NETDB_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_NETINET_IN_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_NETINET_IN_SYSTM_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_NETINET_TCP_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_NEW + +/* Define to 1 if you have the header file. */ +#undef HAVE_NEW_H + +/* Define if the compiler supports operator delete (std::nothrow) */ +#undef HAVE_NOTHROW_DELETE + +/* Define `pid_t' to `int' if does not define. */ +#undef HAVE_NO_TYPEDEF_PID_T + +#ifdef HAVE_NO_TYPEDEF_PID_T +typedef int pid_t; +#endif + +/* Define `size_t' to `unsigned' if does not define. */ +#undef HAVE_NO_TYPEDEF_SIZE_T + +#ifdef HAVE_NO_TYPEDEF_SIZE_T +typedef unsigned size_t; +#endif + +/* Define `ssize_t' to `long' if does not define. */ +#undef HAVE_NO_TYPEDEF_SSIZE_T + +#ifdef HAVE_NO_TYPEDEF_SSIZE_T +typedef long ssize_t; +#endif + +/* Define `uchar' to `unsigned char' if does not define. */ +#undef HAVE_NO_TYPEDEF_UCHAR + +#ifdef HAVE_NO_TYPEDEF_UCHAR +typedef unsigned char uchar; +#endif + +/* Define `uint' to `unsigned int' if does not define. */ +#undef HAVE_NO_TYPEDEF_UINT + +#ifdef HAVE_NO_TYPEDEF_UINT +typedef unsigned int uint; +#endif + +/* Define `ulong' to `unsigned long' if does not define. */ +#undef HAVE_NO_TYPEDEF_ULONG + +#ifdef HAVE_NO_TYPEDEF_ULONG +typedef unsigned long ulong; +#endif + +/* Define `ushort' to `unsigned short' if does not define. */ +#undef HAVE_NO_TYPEDEF_USHORT + +#ifdef HAVE_NO_TYPEDEF_USHORT +typedef unsigned short ushort; +#endif + +/* Define to 1 if you have the `ntohl' function. */ +#undef HAVE_NTOHL + +/* Define to 1 if you have the `ntohs' function. */ +#undef HAVE_NTOHS + +/* Define to 1 if the system has the type `off64_t'. */ +#undef HAVE_OFF64_T + +/* Define if your system supports readdir_r with the obsolete Posix 1.c draft + 6 declaration (2 arguments) instead of the Posix 1.c declaration with 3 + arguments. */ +#undef HAVE_OLD_READDIR_R + +/* Define if passwd::pw_gecos is available. */ +#undef HAVE_PASSWD_GECOS + +/* Define to 1 if you have the `pclose' function. */ +#undef HAVE_PCLOSE + +/* Define if pthread_t is a pointer type on your system */ +#undef HAVE_POINTER_TYPE_PTHREAD_T + +/* Define to 1 if you have the `popen' function. */ +#undef HAVE_POPEN + +/* Define if your system has a prototype for accept in sys/types.h + sys/socket.h */ +#undef HAVE_PROTOTYPE_ACCEPT + +/* Define if your system has a prototype for bind in sys/types.h sys/socket.h + */ +#undef HAVE_PROTOTYPE_BIND + +/* Define if your system has a prototype for bzero in string.h strings.h + libc.h unistd.h stdlib.h */ +#undef HAVE_PROTOTYPE_BZERO + +/* Define if your system has a prototype for connect in sys/types.h + sys/socket.h */ +#undef HAVE_PROTOTYPE_CONNECT + +/* Define if your system has a prototype for finite in math.h */ +#undef HAVE_PROTOTYPE_FINITE + +/* Define if your system has a prototype for flock in sys/file.h */ +#undef HAVE_PROTOTYPE_FLOCK + +/* Define if your system has a prototype for gethostbyname in libc.h unistd.h + stdlib.h netdb.h */ +#undef HAVE_PROTOTYPE_GETHOSTBYNAME + +/* Define if your system has a prototype for gethostbyname_r in libc.h + unistd.h stdlib.h netdb.h */ +#undef HAVE_PROTOTYPE_GETHOSTBYNAME_R + +/* Define if your system has a prototype for gethostid in libc.h unistd.h + stdlib.h netdb.h */ +#undef HAVE_PROTOTYPE_GETHOSTID + +/* Define if your system has a prototype for gethostname in unistd.h libc.h + stdlib.h netdb.h */ +#undef HAVE_PROTOTYPE_GETHOSTNAME + +/* Define if your system has a prototype for getsockname in sys/types.h + sys/socket.h */ +#undef HAVE_PROTOTYPE_GETSOCKNAME + +/* Define if your system has a prototype for getsockopt in sys/types.h + sys/socket.h */ +#undef HAVE_PROTOTYPE_GETSOCKOPT + +/* Define if your system has a prototype for gettimeofday in sys/time.h + unistd.h */ +#undef HAVE_PROTOTYPE_GETTIMEOFDAY + +/* Define if your system has a prototype for isinf in math.h */ +#undef HAVE_PROTOTYPE_ISINF + +/* Define if your system has a prototype for isnan in math.h */ +#undef HAVE_PROTOTYPE_ISNAN + +/* Define if your system has a prototype for listen in sys/types.h + sys/socket.h */ +#undef HAVE_PROTOTYPE_LISTEN + +/* Define if your system has a prototype for mkstemp in libc.h unistd.h + stdlib.h */ +#undef HAVE_PROTOTYPE_MKSTEMP + +/* Define if your system has a prototype for mktemp in libc.h unistd.h + stdlib.h */ +#undef HAVE_PROTOTYPE_MKTEMP + +/* Define if your system has a prototype for select in sys/select.h + sys/types.h sys/socket.h sys/time.h */ +#undef HAVE_PROTOTYPE_SELECT + +/* Define if your system has a prototype for setsockopt in sys/types.h + sys/socket.h */ +#undef HAVE_PROTOTYPE_SETSOCKOPT + +/* Define if your system has a prototype for socket in sys/types.h + sys/socket.h */ +#undef HAVE_PROTOTYPE_SOCKET + +/* Define if your system has a prototype for std::finite in cmath */ +#undef HAVE_PROTOTYPE_STD__FINITE + +/* Define if your system has a prototype for std::isinf in cmath */ +#undef HAVE_PROTOTYPE_STD__ISINF + +/* Define if your system has a prototype for std::isnan in cmath */ +#undef HAVE_PROTOTYPE_STD__ISNAN + +/* Define if your system has a prototype for std::vfprintf in stdarg.h stdio.h + */ +#undef HAVE_PROTOTYPE_STD__VFPRINTF + +/* Define if your system has a prototype for std::vsnprintf in stdarg.h + stdio.h */ +#undef HAVE_PROTOTYPE_STD__VSNPRINTF + +/* Define if your system has a prototype for strcasecmp in string.h */ +#undef HAVE_PROTOTYPE_STRCASECMP + +/* Define if your system has a prototype for strerror_r in string.h */ +#undef HAVE_PROTOTYPE_STRERROR_R + +/* Define if your system has a prototype for strncasecmp in string.h */ +#undef HAVE_PROTOTYPE_STRNCASECMP + +/* Define if your system has a prototype for usleep in libc.h unistd.h + stdlib.h */ +#undef HAVE_PROTOTYPE_USLEEP + +/* Define if your system has a prototype for vsnprintf in stdio.h stdarg.h */ +#undef HAVE_PROTOTYPE_VSNPRINTF + +/* Define if your system has a prototype for wait3 in libc.h sys/wait.h + sys/time.h sys/resource.h */ +#undef HAVE_PROTOTYPE_WAIT3 + +/* Define if your system has a prototype for waitpid in sys/wait.h sys/time.h + sys/resource.h */ +#undef HAVE_PROTOTYPE_WAITPID + +/* Define if your system has a prototype for _stricmp in string.h */ +#undef HAVE_PROTOTYPE__STRICMP + +/* Define to 1 if you have the header file. */ +#undef HAVE_PTHREAD_H + +/* Define if your system supports POSIX read/write locks. */ +#undef HAVE_PTHREAD_RWLOCK + +/* Define to 1 if you have the header file. */ +#undef HAVE_PWD_H + +/* Define if OpenSSL provides the RAND_egd function. */ +#undef HAVE_RAND_EGD + +/* define if the compiler supports reinterpret_cast<> */ +#undef HAVE_REINTERPRET_CAST + +/* Define to 1 if you have the `rindex' function. */ +#undef HAVE_RINDEX + +/* Define to 1 if you have the `select' function. */ +#undef HAVE_SELECT + +/* Define to 1 if you have the header file. */ +#undef HAVE_SEMAPHORE_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SETJMP_H + +/* Define to 1 if you have the `setsockopt' function. */ +#undef HAVE_SETSOCKOPT + +/* Define to 1 if you have the `setuid' function. */ +#undef HAVE_SETUID + +/* Define to 1 if the system has the type `sigjmp_buf'. */ +#undef HAVE_SIGJMP_BUF + +/* Define to 1 if you have the header file. */ +#undef HAVE_SIGNAL_H + +/* Define to 1 if you have the `sleep' function. */ +#undef HAVE_SLEEP + +/* Define to 1 if you have the `socket' function. */ +#undef HAVE_SOCKET + +/* Define if OpenSSL provides the SSL_CTX_get0_param function. */ +#undef HAVE_SSL_CTX_GET0_PARAM + +/* Define to 1 if you have the header file. */ +#undef HAVE_SSTREAM + +/* Define to 1 if you have the header file. */ +#undef HAVE_SSTREAM_H + +/* Define to 1 if you have the `stat' function. */ +#undef HAVE_STAT + +/* define if the compiler supports static_cast<> */ +#undef HAVE_STATIC_CAST + +/* Define if your C++ compiler can work with static methods in class templates + */ +#undef HAVE_STATIC_TEMPLATE_METHOD + +/* Define to 1 if you have the header file. */ +#undef HAVE_STAT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDARG_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDBOOL_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDDEF_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDIO_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDLIB_H + +/* Define if ANSI standard C++ includes use std namespace */ +#undef HAVE_STD_NAMESPACE + +/* Define if the compiler supports std::nothrow */ +#undef HAVE_STD__NOTHROW + +/* Define to 1 if you have the `strchr' function. */ +#undef HAVE_STRCHR + +/* Define to 1 if you have the `strdup' function. */ +#undef HAVE_STRDUP + +/* Define to 1 if you have the `strerror' function. */ +#undef HAVE_STRERROR + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRING_H + +/* Define to 1 if you have the `strlcat' function. */ +#undef HAVE_STRLCAT + +/* Define to 1 if you have the `strlcpy' function. */ +#undef HAVE_STRLCPY + +/* Define to 1 if you have the `strstr' function. */ +#undef HAVE_STRSTR + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRSTREAM + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRSTREAM_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRSTREA_H + +/* Define to 1 if you have the `strtoul' function. */ +#undef HAVE_STRTOUL + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYNCH_H + +/* Define if __sync_add_and_fetch is available */ +#undef HAVE_SYNC_ADD_AND_FETCH + +/* Define if __sync_sub_and_fetch is available */ +#undef HAVE_SYNC_SUB_AND_FETCH + +/* Define to 1 if you have the `sysinfo' function. */ +#undef HAVE_SYSINFO + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYSLOG_H + +/* Define to 1 if you have the header file, and it defines `DIR'. + */ +#undef HAVE_SYS_DIR_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_ERRNO_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_FILE_H + +/* Define if your system has a prototype for gettid. */ +#undef HAVE_SYS_GETTID + +/* Define to 1 if you have the header file, and it defines `DIR'. + */ +#undef HAVE_SYS_NDIR_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_PARAM_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_RESOURCE_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_SELECT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_SOCKET_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_SYSCALL_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_SYSTEMINFO_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TIMEB_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TIME_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_UTIME_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_UTSNAME_H + +/* Define to 1 if you have that is POSIX.1 compatible. */ +#undef HAVE_SYS_WAIT_H + +/* Define to 1 if you have the `tempnam' function. */ +#undef HAVE_TEMPNAM + +/* Define to 1 if you have the header file. */ +#undef HAVE_THREAD_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_TIME_H + +/* Define to 1 if you have the `tmpnam' function. */ +#undef HAVE_TMPNAM + +/* define if the compiler recognizes typename */ +#undef HAVE_TYPENAME + +/* Define to 1 if the system has the type `uint64_t'. */ +#undef HAVE_UINT64_T + +/* Define to 1 if the system has the type `ulonglong'. */ +#undef HAVE_ULONGLONG + +/* Define to 1 if you have the `uname' function. */ +#undef HAVE_UNAME + +/* Define to 1 if you have the header file. */ +#undef HAVE_UNISTD_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_UNIX_H + +/* Define to 1 if the system has the type `unsigned long long'. */ +#undef HAVE_UNSIGNED_LONG_LONG + +/* Define to 1 if you have the `usleep' function. */ +#undef HAVE_USLEEP + +/* Define to 1 if you have the header file. */ +#undef HAVE_UTIME_H + +/* Define if variable-length arrays are supported in C */ +#undef HAVE_VLA + +/* Define to 1 if you have the `vprintf' function. */ +#undef HAVE_VPRINTF + +/* Define to 1 if you have the `vsnprintf' function. */ +#undef HAVE_VSNPRINTF + +/* Define to 1 if you have the `wait3' system call. Deprecated, you should no + longer depend upon `wait3'. */ +#undef HAVE_WAIT3 + +/* Define to 1 if you have the `waitpid' function. */ +#undef HAVE_WAITPID + +/* Define to 1 if you have the header file. */ +#undef HAVE_WCHAR_H + +/* Define to 1 if you have the `wcstombs' function. */ +#undef HAVE_WCSTOMBS + +/* Define to 1 if you have the header file. */ +#undef HAVE_WCTYPE_H + +/* Define to 1 if you have the `_findfirst' function. */ +#undef HAVE__FINDFIRST + +/* Define if the compiler supports __FUNCTION__. */ +#undef HAVE___FUNCTION___MACRO + +/* Define if the compiler supports __PRETTY_FUNCTION__. */ +#undef HAVE___PRETTY_FUNCTION___MACRO + +/* Define if the compiler supports __func__. */ +#undef HAVE___func___MACRO + +/* Define if libc.h should be treated as a C++ header */ +#undef INCLUDE_LIBC_H_AS_CXX + +/* Define if fails if included extern "C" */ +#undef INCLUDE_MATH_H_AS_CXX + +/* Define if the second argument to iconv() is const. */ +#undef LIBICONV_SECOND_ARGUMENT_CONST + +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT + +/* Define to the release date of this package. */ +#undef PACKAGE_DATE + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the home page for this package. */ +#undef PACKAGE_URL + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION + +/* Define to the version number of this package. */ +#undef PACKAGE_VERSION_NUMBER + +/* Define to the version suffix of this package. */ +#undef PACKAGE_VERSION_SUFFIX + +/* Define path separator. */ +#define PATH_SEPARATOR '/' + +/* Define as the return type of signal handlers (`int' or `void'). */ +#undef RETSIGTYPE + +/* Define if signal handlers need ellipse (...) parameters */ +#undef SIGNAL_HANDLER_WITH_ELLIPSE + +/* The size of `char', as computed by sizeof. */ +#undef SIZEOF_CHAR + +/* The size of `double', as computed by sizeof. */ +#undef SIZEOF_DOUBLE + +/* The size of `float', as computed by sizeof. */ +#undef SIZEOF_FLOAT + +/* The size of `int', as computed by sizeof. */ +#undef SIZEOF_INT + +/* The size of `long', as computed by sizeof. */ +#undef SIZEOF_LONG + +/* The size of `short', as computed by sizeof. */ +#undef SIZEOF_SHORT + +/* The size of `void *', as computed by sizeof. */ +#undef SIZEOF_VOID_P + +/* Define to 1 if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* Namespace for ANSI C functions in standard C++ headers */ +#undef STDIO_NAMESPACE + +/* Define to 1 if your declares `struct tm'. */ +#undef TM_IN_SYS_TIME + +/* Define if ANSI standard C++ includes are used. */ +#undef USE_STD_CXX_INCLUDES + +/* Enable extensions on AIX 3, Interix. */ +#ifndef _ALL_SOURCE +# undef _ALL_SOURCE +#endif +/* Enable GNU extensions on systems that have them. */ +#ifndef _GNU_SOURCE +# undef _GNU_SOURCE +#endif +/* Enable threading extensions on Solaris. */ +#ifndef _POSIX_PTHREAD_SEMANTICS +# undef _POSIX_PTHREAD_SEMANTICS +#endif +/* Enable extensions on HP NonStop. */ +#ifndef _TANDEM_SOURCE +# undef _TANDEM_SOURCE +#endif +/* Enable general extensions on Solaris. */ +#ifndef __EXTENSIONS__ +# undef __EXTENSIONS__ +#endif + + +/* Define if we are compiling with libiconv support. */ +#undef WITH_LIBICONV + +/* Define if we are compiling with libpng support. */ +#undef WITH_LIBPNG + +/* Define if we are compiling with libtiff support. */ +#undef WITH_LIBTIFF + +/* Define if we are compiling with libxml support. */ +#undef WITH_LIBXML + +/* Define if we are compiling with OpenSSL support. */ +#undef WITH_OPENSSL + +/* Define if we are compiling with libsndfile support. */ +#undef WITH_SNDFILE + +/* Define if we are compiling with libwrap (TCP wrapper) support. */ +#undef WITH_TCPWRAPPER + +/* Define if we are compiling with any type of multi-thread support. */ +#undef WITH_THREADS + +/* Define if we are compiling with zlib support. */ +#undef WITH_ZLIB + +/* Number of bits in a file offset, on hosts where this is settable. */ +#undef _FILE_OFFSET_BITS + +/* Define to enable LFS64 (explicit large file support) if available */ +#undef _LARGEFILE64_SOURCE + +/* Define to 1 to make fseeko visible on some hosts (e.g. glibc 2.2). */ +#undef _LARGEFILE_SOURCE + +/* Define for large files, on AIX-style hosts. */ +#undef _LARGE_FILES + +/* Define to 1 if on MINIX. */ +#undef _MINIX + +/* Define to 2 if the system does not provide POSIX.1 features except with + this defined. */ +#undef _POSIX_1_SOURCE + +/* Define to 1 if you need to in order for `stat' and other things to work. */ +#undef _POSIX_SOURCE + +/* Define to 1 if type `char' is unsigned and you are not using gcc. */ +#ifndef __CHAR_UNSIGNED__ +# undef __CHAR_UNSIGNED__ +#endif + +/* Define to int if undefined. */ +#undef socklen_t + +#if defined(DCMTK_USE_CXX11_STL) && defined(__cplusplus) && __cplusplus < 201103L +#error\ + DCMTK was configured to use the C++11 STL, but your compiler is not configured\ + for building with C++11 features. +#endif + +#endif /* OSCONFIG_H */ diff --git a/config/install-sh b/config/install-sh new file mode 100755 index 00000000..377bb868 --- /dev/null +++ b/config/install-sh @@ -0,0 +1,527 @@ +#!/bin/sh +# install - install a program, script, or datafile + +scriptversion=2011-11-20.07; # UTC + +# This originates from X11R5 (mit/util/scripts/install.sh), which was +# later released in X11R6 (xc/config/util/install.sh) with the +# following copyright and license. +# +# Copyright (C) 1994 X Consortium +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- +# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +# Except as contained in this notice, the name of the X Consortium shall not +# be used in advertising or otherwise to promote the sale, use or other deal- +# ings in this Software without prior written authorization from the X Consor- +# tium. +# +# +# FSF changes to this file are in the public domain. +# +# Calling this script install-sh is preferred over install.sh, to prevent +# 'make' implicit rules from creating a file called install from it +# when there is no Makefile. +# +# This script is compatible with the BSD install script, but was written +# from scratch. + +nl=' +' +IFS=" "" $nl" + +# set DOITPROG to echo to test this script + +# Don't use :- since 4.3BSD and earlier shells don't like it. +doit=${DOITPROG-} +if test -z "$doit"; then + doit_exec=exec +else + doit_exec=$doit +fi + +# Put in absolute file names if you don't have them in your path; +# or use environment vars. + +chgrpprog=${CHGRPPROG-chgrp} +chmodprog=${CHMODPROG-chmod} +chownprog=${CHOWNPROG-chown} +cmpprog=${CMPPROG-cmp} +cpprog=${CPPROG-cp} +mkdirprog=${MKDIRPROG-mkdir} +mvprog=${MVPROG-mv} +rmprog=${RMPROG-rm} +stripprog=${STRIPPROG-strip} + +posix_glob='?' +initialize_posix_glob=' + test "$posix_glob" != "?" || { + if (set -f) 2>/dev/null; then + posix_glob= + else + posix_glob=: + fi + } +' + +posix_mkdir= + +# Desired mode of installed file. +mode=0755 + +chgrpcmd= +chmodcmd=$chmodprog +chowncmd= +mvcmd=$mvprog +rmcmd="$rmprog -f" +stripcmd= + +src= +dst= +dir_arg= +dst_arg= + +copy_on_change=false +no_target_directory= + +usage="\ +Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE + or: $0 [OPTION]... SRCFILES... DIRECTORY + or: $0 [OPTION]... -t DIRECTORY SRCFILES... + or: $0 [OPTION]... -d DIRECTORIES... + +In the 1st form, copy SRCFILE to DSTFILE. +In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. +In the 4th, create DIRECTORIES. + +Options: + --help display this help and exit. + --version display version info and exit. + + -c (ignored) + -C install only if different (preserve the last data modification time) + -d create directories instead of installing files. + -g GROUP $chgrpprog installed files to GROUP. + -m MODE $chmodprog installed files to MODE. + -o USER $chownprog installed files to USER. + -s $stripprog installed files. + -t DIRECTORY install into DIRECTORY. + -T report an error if DSTFILE is a directory. + +Environment variables override the default commands: + CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG + RMPROG STRIPPROG +" + +while test $# -ne 0; do + case $1 in + -c) ;; + + -C) copy_on_change=true;; + + -d) dir_arg=true;; + + -g) chgrpcmd="$chgrpprog $2" + shift;; + + --help) echo "$usage"; exit $?;; + + -m) mode=$2 + case $mode in + *' '* | *' '* | *' +'* | *'*'* | *'?'* | *'['*) + echo "$0: invalid mode: $mode" >&2 + exit 1;; + esac + shift;; + + -o) chowncmd="$chownprog $2" + shift;; + + -s) stripcmd=$stripprog;; + + -t) dst_arg=$2 + # Protect names problematic for 'test' and other utilities. + case $dst_arg in + -* | [=\(\)!]) dst_arg=./$dst_arg;; + esac + shift;; + + -T) no_target_directory=true;; + + --version) echo "$0 $scriptversion"; exit $?;; + + --) shift + break;; + + -*) echo "$0: invalid option: $1" >&2 + exit 1;; + + *) break;; + esac + shift +done + +if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then + # When -d is used, all remaining arguments are directories to create. + # When -t is used, the destination is already specified. + # Otherwise, the last argument is the destination. Remove it from $@. + for arg + do + if test -n "$dst_arg"; then + # $@ is not empty: it contains at least $arg. + set fnord "$@" "$dst_arg" + shift # fnord + fi + shift # arg + dst_arg=$arg + # Protect names problematic for 'test' and other utilities. + case $dst_arg in + -* | [=\(\)!]) dst_arg=./$dst_arg;; + esac + done +fi + +if test $# -eq 0; then + if test -z "$dir_arg"; then + echo "$0: no input file specified." >&2 + exit 1 + fi + # It's OK to call 'install-sh -d' without argument. + # This can happen when creating conditional directories. + exit 0 +fi + +if test -z "$dir_arg"; then + do_exit='(exit $ret); exit $ret' + trap "ret=129; $do_exit" 1 + trap "ret=130; $do_exit" 2 + trap "ret=141; $do_exit" 13 + trap "ret=143; $do_exit" 15 + + # Set umask so as not to create temps with too-generous modes. + # However, 'strip' requires both read and write access to temps. + case $mode in + # Optimize common cases. + *644) cp_umask=133;; + *755) cp_umask=22;; + + *[0-7]) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw='% 200' + fi + cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; + *) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw=,u+rw + fi + cp_umask=$mode$u_plus_rw;; + esac +fi + +for src +do + # Protect names problematic for 'test' and other utilities. + case $src in + -* | [=\(\)!]) src=./$src;; + esac + + if test -n "$dir_arg"; then + dst=$src + dstdir=$dst + test -d "$dstdir" + dstdir_status=$? + else + + # Waiting for this to be detected by the "$cpprog $src $dsttmp" command + # might cause directories to be created, which would be especially bad + # if $src (and thus $dsttmp) contains '*'. + if test ! -f "$src" && test ! -d "$src"; then + echo "$0: $src does not exist." >&2 + exit 1 + fi + + if test -z "$dst_arg"; then + echo "$0: no destination specified." >&2 + exit 1 + fi + dst=$dst_arg + + # If destination is a directory, append the input filename; won't work + # if double slashes aren't ignored. + if test -d "$dst"; then + if test -n "$no_target_directory"; then + echo "$0: $dst_arg: Is a directory" >&2 + exit 1 + fi + dstdir=$dst + dst=$dstdir/`basename "$src"` + dstdir_status=0 + else + # Prefer dirname, but fall back on a substitute if dirname fails. + dstdir=` + (dirname "$dst") 2>/dev/null || + expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$dst" : 'X\(//\)[^/]' \| \ + X"$dst" : 'X\(//\)$' \| \ + X"$dst" : 'X\(/\)' \| . 2>/dev/null || + echo X"$dst" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q' + ` + + test -d "$dstdir" + dstdir_status=$? + fi + fi + + obsolete_mkdir_used=false + + if test $dstdir_status != 0; then + case $posix_mkdir in + '') + # Create intermediate dirs using mode 755 as modified by the umask. + # This is like FreeBSD 'install' as of 1997-10-28. + umask=`umask` + case $stripcmd.$umask in + # Optimize common cases. + *[2367][2367]) mkdir_umask=$umask;; + .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; + + *[0-7]) + mkdir_umask=`expr $umask + 22 \ + - $umask % 100 % 40 + $umask % 20 \ + - $umask % 10 % 4 + $umask % 2 + `;; + *) mkdir_umask=$umask,go-w;; + esac + + # With -d, create the new directory with the user-specified mode. + # Otherwise, rely on $mkdir_umask. + if test -n "$dir_arg"; then + mkdir_mode=-m$mode + else + mkdir_mode= + fi + + posix_mkdir=false + case $umask in + *[123567][0-7][0-7]) + # POSIX mkdir -p sets u+wx bits regardless of umask, which + # is incompatible with FreeBSD 'install' when (umask & 300) != 0. + ;; + *) + tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ + trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0 + + if (umask $mkdir_umask && + exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1 + then + if test -z "$dir_arg" || { + # Check for POSIX incompatibilities with -m. + # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or + # other-writable bit of parent directory when it shouldn't. + # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. + ls_ld_tmpdir=`ls -ld "$tmpdir"` + case $ls_ld_tmpdir in + d????-?r-*) different_mode=700;; + d????-?--*) different_mode=755;; + *) false;; + esac && + $mkdirprog -m$different_mode -p -- "$tmpdir" && { + ls_ld_tmpdir_1=`ls -ld "$tmpdir"` + test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" + } + } + then posix_mkdir=: + fi + rmdir "$tmpdir/d" "$tmpdir" + else + # Remove any dirs left behind by ancient mkdir implementations. + rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null + fi + trap '' 0;; + esac;; + esac + + if + $posix_mkdir && ( + umask $mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" + ) + then : + else + + # The umask is ridiculous, or mkdir does not conform to POSIX, + # or it failed possibly due to a race condition. Create the + # directory the slow way, step by step, checking for races as we go. + + case $dstdir in + /*) prefix='/';; + [-=\(\)!]*) prefix='./';; + *) prefix='';; + esac + + eval "$initialize_posix_glob" + + oIFS=$IFS + IFS=/ + $posix_glob set -f + set fnord $dstdir + shift + $posix_glob set +f + IFS=$oIFS + + prefixes= + + for d + do + test X"$d" = X && continue + + prefix=$prefix$d + if test -d "$prefix"; then + prefixes= + else + if $posix_mkdir; then + (umask=$mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break + # Don't fail if two instances are running concurrently. + test -d "$prefix" || exit 1 + else + case $prefix in + *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; + *) qprefix=$prefix;; + esac + prefixes="$prefixes '$qprefix'" + fi + fi + prefix=$prefix/ + done + + if test -n "$prefixes"; then + # Don't fail if two instances are running concurrently. + (umask $mkdir_umask && + eval "\$doit_exec \$mkdirprog $prefixes") || + test -d "$dstdir" || exit 1 + obsolete_mkdir_used=true + fi + fi + fi + + if test -n "$dir_arg"; then + { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && + { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || + test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 + else + + # Make a couple of temp file names in the proper directory. + dsttmp=$dstdir/_inst.$$_ + rmtmp=$dstdir/_rm.$$_ + + # Trap to clean up those temp files at exit. + trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 + + # Copy the file name to the temp name. + (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && + + # and set any options; do chmod last to preserve setuid bits. + # + # If any of these fail, we abort the whole thing. If we want to + # ignore errors from any of these, just make sure not to ignore + # errors from the above "$doit $cpprog $src $dsttmp" command. + # + { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && + { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && + { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && + + # If -C, don't bother to copy if it wouldn't change the file. + if $copy_on_change && + old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && + new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && + + eval "$initialize_posix_glob" && + $posix_glob set -f && + set X $old && old=:$2:$4:$5:$6 && + set X $new && new=:$2:$4:$5:$6 && + $posix_glob set +f && + + test "$old" = "$new" && + $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 + then + rm -f "$dsttmp" + else + # Rename the file to the real destination. + $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || + + # The rename failed, perhaps because mv can't rename something else + # to itself, or perhaps because mv is so ancient that it does not + # support -f. + { + # Now remove or move aside any old file at destination location. + # We try this two ways since rm can't unlink itself on some + # systems and the destination file might be busy for other + # reasons. In this case, the final cleanup might fail but the new + # file should still install successfully. + { + test ! -f "$dst" || + $doit $rmcmd -f "$dst" 2>/dev/null || + { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && + { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } + } || + { echo "$0: cannot unlink or rename $dst" >&2 + (exit 1); exit 1 + } + } && + + # Now rename the file to the real destination. + $doit $mvcmd "$dsttmp" "$dst" + } + fi || exit 1 + + trap '' 0 + fi +done + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/config/mkinstalldirs b/config/mkinstalldirs new file mode 100755 index 00000000..55d537f8 --- /dev/null +++ b/config/mkinstalldirs @@ -0,0 +1,162 @@ +#! /bin/sh +# mkinstalldirs --- make directory hierarchy + +scriptversion=2009-04-28.21; # UTC + +# Original author: Noah Friedman +# Created: 1993-05-16 +# Public domain. +# +# This file is maintained in Automake, please report +# bugs to or send patches to +# . + +nl=' +' +IFS=" "" $nl" +errstatus=0 +dirmode= + +usage="\ +Usage: mkinstalldirs [-h] [--help] [--version] [-m MODE] DIR ... + +Create each directory DIR (with mode MODE, if specified), including all +leading file name components. + +Report bugs to ." + +# process command line arguments +while test $# -gt 0 ; do + case $1 in + -h | --help | --h*) # -h for help + echo "$usage" + exit $? + ;; + -m) # -m PERM arg + shift + test $# -eq 0 && { echo "$usage" 1>&2; exit 1; } + dirmode=$1 + shift + ;; + --version) + echo "$0 $scriptversion" + exit $? + ;; + --) # stop option processing + shift + break + ;; + -*) # unknown option + echo "$usage" 1>&2 + exit 1 + ;; + *) # first non-opt arg + break + ;; + esac +done + +for file +do + if test -d "$file"; then + shift + else + break + fi +done + +case $# in + 0) exit 0 ;; +esac + +# Solaris 8's mkdir -p isn't thread-safe. If you mkdir -p a/b and +# mkdir -p a/c at the same time, both will detect that a is missing, +# one will create a, then the other will try to create a and die with +# a "File exists" error. This is a problem when calling mkinstalldirs +# from a parallel make. We use --version in the probe to restrict +# ourselves to GNU mkdir, which is thread-safe. +case $dirmode in + '') + if mkdir -p --version . >/dev/null 2>&1 && test ! -d ./--version; then + echo "mkdir -p -- $*" + exec mkdir -p -- "$@" + else + # On NextStep and OpenStep, the 'mkdir' command does not + # recognize any option. It will interpret all options as + # directories to create, and then abort because '.' already + # exists. + test -d ./-p && rmdir ./-p + test -d ./--version && rmdir ./--version + fi + ;; + *) + if mkdir -m "$dirmode" -p --version . >/dev/null 2>&1 && + test ! -d ./--version; then + echo "mkdir -m $dirmode -p -- $*" + exec mkdir -m "$dirmode" -p -- "$@" + else + # Clean up after NextStep and OpenStep mkdir. + for d in ./-m ./-p ./--version "./$dirmode"; + do + test -d $d && rmdir $d + done + fi + ;; +esac + +for file +do + case $file in + /*) pathcomp=/ ;; + *) pathcomp= ;; + esac + oIFS=$IFS + IFS=/ + set fnord $file + shift + IFS=$oIFS + + for d + do + test "x$d" = x && continue + + pathcomp=$pathcomp$d + case $pathcomp in + -*) pathcomp=./$pathcomp ;; + esac + + if test ! -d "$pathcomp"; then + echo "mkdir $pathcomp" + + mkdir "$pathcomp" || lasterr=$? + + if test ! -d "$pathcomp"; then + errstatus=$lasterr + else + if test ! -z "$dirmode"; then + echo "chmod $dirmode $pathcomp" + lasterr= + chmod "$dirmode" "$pathcomp" || lasterr=$? + + if test ! -z "$lasterr"; then + errstatus=$lasterr + fi + fi + fi + fi + + pathcomp=$pathcomp/ + done +done + +exit $errstatus + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/config/modules b/config/modules new file mode 100644 index 00000000..2e28fdc5 --- /dev/null +++ b/config/modules @@ -0,0 +1 @@ +ofstd oflog dcmdata dcmiod dcmfg dcmseg dcmimgle dcmimage dcmjpeg dcmjpls dcmtls dcmnet dcmsr dcmsign dcmwlm dcmqrdb dcmpstat dcmrt diff --git a/config/rootconf b/config/rootconf new file mode 100755 index 00000000..581920a9 --- /dev/null +++ b/config/rootconf @@ -0,0 +1,239 @@ +#! /bin/sh + +modulesfile=modules +topdir=.. +output=$topdir/Makefile + +cat > $output <> $output <-all build the complete module" + @echo "-libsrc-all build the module's libraries" + @echo "-install install the module" + @echo "-install-lib install the module's libraries" + @echo "-check build and run the module's tests, not including exhaustive tests" + @echo "-check-exhaustive build and run the module's tests, including exhaustive tests" + @echo "" + @echo "The following modules are available:" + @echo "" + @echo "$modules" + +EOF + +for module in config $modules; do + cat >> $output <> $output + if test $tag = dependencies ; then + echo " -(cd config && \$(MAKE) ${tag})" >> $output + fi + for module in $modules; do + echo " (cd ${module} && \$(MAKE) ${tag})" >> $output + done + if test $tag != dependencies ; then + echo " (cd doxygen && \$(MAKE) ${tag})" >> $output + echo " -(cd config && \$(MAKE) ${tag})" >> $output + fi + if test $tag = clean ; then + echo " rm -f \$(TRASH)" >> $output + elif test $tag = distclean ; then + echo " rm -f \$(TRASH)" >> $output + fi + echo >> $output +done + +output=$topdir/configure +cat > $output <&2 + exit 1 + fi + (cd \$module && ./configure \$* ) || exit 1 + done +fi +EOF +chmod 755 $output diff --git a/config/templates/Makefile.lib b/config/templates/Makefile.lib new file mode 100644 index 00000000..27dfd7fa --- /dev/null +++ b/config/templates/Makefile.lib @@ -0,0 +1,51 @@ +# +# Makefile for module/libsrc +# + +@SET_MAKE@ + +SHELL = /bin/sh +VPATH = @srcdir@:@top_srcdir@/include:@top_srcdir@/@configdir@/include +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +configdir = @top_srcdir@/@configdir@ + +include $(configdir)/@common_makefile@ + +LOCALINCLUDES = +LIBDIRS = +LOCALLIBS = +LOCALDEFS = + +objs = # all objects in library +library = libname.$(LIBEXT) + + +all: $(library) + + +install: $(library) + $(configdir)/mkinstalldirs $(DESTDIR)$(libdir) + $(INSTALL_DATA) $(library) $(DESTDIR)$(libdir)/$(library) + $(RANLIB) $(DESTDIR)$(libdir)/$(library) + + +$(library): $(objs) + $(AR) $(ARFLAGS) $@ $(objs) + $(RANLIB) $@ + +# Clean-up + +clean: + rm -f $(objs) $(library) $(TRASH) + +distclean: clean + rm -f $(DISTTRASH) + + +# Dependencies + +dependencies: + $(CXX) -MM $(defines) $(includes) $(CPPFLAGS) $(CXXFLAGS) *.cc > $(DEP) + +include $(DEP) diff --git a/config/templates/Makefile.mod b/config/templates/Makefile.mod new file mode 100644 index 00000000..f1577879 --- /dev/null +++ b/config/templates/Makefile.mod @@ -0,0 +1,93 @@ +# +# Makefile for module +# + +@SET_MAKE@ + +SHELL = /bin/sh +VPATH = @srcdir@:@top_srcdir@/include:@top_srcdir@/@configdir@/include +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +configdir = @top_srcdir@/@configdir@ + +include $(configdir)/@common_makefile@ + + +all: include-all libsrc-all apps-all tests-all + +install: install-bin install-doc install-support + +install-bin: apps-install + +install-doc: docs-install + +install-data: data-install + +install-etc: etc-install + +install-include: include-install + +install-lib: libsrc-install install-include + +install-support: install-data install-etc + + +include-all: + (cd include && $(MAKE) ARCH="$(ARCH)" all) + +libsrc-all: include-all + (cd libsrc && $(MAKE) ARCH="$(ARCH)" all) + +apps-all: libsrc-all + (cd apps && $(MAKE) ARCH="$(ARCH)" all) + +tests-all: libsrc-all + (cd tests && $(MAKE) ARCH="$(ARCH)" all) + + +include-install: + (cd include && $(MAKE) ARCH="$(ARCH)" install) + +libsrc-install: libsrc-all + (cd libsrc && $(MAKE) ARCH="$(ARCH)" install) + +apps-install: apps-all + (cd apps && $(MAKE) ARCH="$(ARCH)" install) + +docs-install: + (cd docs && $(MAKE) install) + +data-install: + (cd data && $(MAKE) install) + +etc-install: + (cd etc && $(MAKE) install) + + +clean: + (cd include && $(MAKE) clean) + (cd libsrc && $(MAKE) clean) + (cd apps && $(MAKE) clean) + (cd tests && $(MAKE) clean) + (cd docs && $(MAKE) clean) + (cd data && $(MAKE) clean) + (cd etc && $(MAKE) clean) + rm -f $(TRASH) + +distclean: + (cd include && $(MAKE) distclean) + (cd libsrc && $(MAKE) distclean) + (cd apps && $(MAKE) distclean) + (cd tests && $(MAKE) distclean) + (cd docs && $(MAKE) distclean) + (cd data && $(MAKE) distclean) + (cd etc && $(MAKE) distclean) + rm -f $(DISTTRASH) + +dependencies: + (cd libsrc && touch $(DEP) && $(MAKE) dependencies) + (cd apps && touch $(DEP) && $(MAKE) dependencies) + (cd tests && touch $(DEP) && $(MAKE) dependencies) + +check: + (cd tests && $(MAKE) check) diff --git a/config/templates/Makefile.src b/config/templates/Makefile.src new file mode 100644 index 00000000..55a913ae --- /dev/null +++ b/config/templates/Makefile.src @@ -0,0 +1,48 @@ +# +# Makefile for module/apps +# + +@SET_MAKE@ + +SHELL = /bin/sh +VPATH = @srcdir@:@top_srcdir@/include:@top_srcdir@/@configdir@/include +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +configdir = @top_srcdir@/@configdir@ + +include $(configdir)/@common_makefile@ + +LOCALINCLUDES = +LIBDIRS = -L$(top_srcdir)/libsrc -L$(libdir) +LOCALLIBS = # every non-system library you need to compile + +objs = # all objects to compile +progs = # all programs to make + + +all: $(progs) + +prog: prog.o # additionally a not install library + $(CXX) $(CXXFLAGS) $(LIBDIRS) $(LDFLAGS) -o $@ $@.o $(LOCALLIBS) $(LIBS) + + +install: install-bin + +install-bin: all + $(configdir)/mkinstalldirs $(DESTDIR)$(bindir) + for prog in $(progs); do \ + $(INSTALL_PROGRAM) $$prog$(BINEXT) $(DESTDIR)$(bindir) && $(STRIP) $(DESTDIR)$(bindir)/$$prog$(BINEXT) ;\ + done + + +clean: + rm -f $(objs) $(progs) $(TRASH) + +distclean: + rm -f $(objs) $(progs) $(DISTTRASH) + + +dependencies: + $(CXX) -MM $(defines) $(includes) $(CPPFLAGS) $(CXXFLAGS) *.cc > $(DEP) + +include $(DEP) diff --git a/config/templates/configure.mod b/config/templates/configure.mod new file mode 100755 index 00000000..30dd11a6 --- /dev/null +++ b/config/templates/configure.mod @@ -0,0 +1,52 @@ +#! /bin/sh + +parentdir=`pwd` +thisdir=$parentdir + +# The following test constructs relative path from the module +# directory to the configuration directory. If you know this path +# you can substitute this with +# configdir= +# It is very important that the configdir path is relative. + +configdir="configdir" + +while test "$parentdir" != "/" -a "$configdir" = "configdir"; do + if test -d "$parentdir/config" ; then + configdir=$parentdir/config + else + parentdir=`echo $parentdir | sed 's/\/[^\/]*$//'` + fi +done + +if test "$configdir" = "configdir" ; then + echo "Cannot find configure directory" + exit 1 +fi + +if test $# != 0; then + case $1 in + -a) + shift + cd "$configdir" + echo "running configure in config-directory" + ./configure $* + cd $thisdir + echo "running configure for this module" + sh "$configdir/confmod" --srcdir=. $* + ;; + -c) + shift + cd "$configdir" + echo "running configure in config-directory" + ./configure $* + ;; + *) + echo "running configure for this module" + sh "$configdir/confmod" --srcdir=. $* + ;; + esac +else + echo "running configure for this module" + sh "$configdir/confmod" --srcdir=. $* +fi diff --git a/configure b/configure new file mode 100755 index 00000000..ca98151c --- /dev/null +++ b/configure @@ -0,0 +1,36 @@ +#! /bin/sh +if test -d config ; then + if test -f config/modules ; then + tmp=`cat config/modules` + modules=`ls -d $tmp` + else + for dir in `ls`; do + if test -d $dir ; then + modules="$modules $dir" + fi + done + fi + modules=`echo $modules | sed -e "s/config//g" | sed -e "s/CVS//g"` + modules="config $modules doxygen" +else + echo "Cannot find configure directory (config or ../config)" + exit 1 +fi +if test "x--help" = "x$*"; then + config/configure --help +elif test "x--help=short" = "x$*"; then + config/configure --help=short +elif test "x--help=recursive" = "x$*"; then + config/configure --help=recursive +elif test "x--version" = "x$*"; then + config/configure --version +else + for module in $modules ; do + echo "Running configure for module $module." + if test ! -x "$module/configure" ; then + echo "Module $module does not contain a configure script!" >&2 + exit 1 + fi + (cd $module && ./configure $* ) || exit 1 + done +fi diff --git a/dcmdata/CMakeLists.txt b/dcmdata/CMakeLists.txt new file mode 100644 index 00000000..3a78f5dd --- /dev/null +++ b/dcmdata/CMakeLists.txt @@ -0,0 +1,10 @@ +# declare project +PROJECT(dcmdata) + +# declare include directories which hold for all subdirectories +INCLUDE_DIRECTORIES(${dcmdata_SOURCE_DIR}/include ${ofstd_SOURCE_DIR}/include ${oflog_SOURCE_DIR}/include ${ZLIB_INCDIR}) + +# recurse into subdirectories +FOREACH(SUBDIR libsrc libi2d apps include docs data tests) + ADD_SUBDIRECTORY(${SUBDIR}) +ENDFOREACH(SUBDIR) diff --git a/dcmdata/Makefile.in b/dcmdata/Makefile.in new file mode 100644 index 00000000..350f3f9e --- /dev/null +++ b/dcmdata/Makefile.in @@ -0,0 +1,102 @@ +# +# Makefile for dcmdata +# + +@SET_MAKE@ + +SHELL = /bin/sh +VPATH = @srcdir@:@top_srcdir@/include:@top_srcdir@/@configdir@/include +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +configdir = @top_srcdir@/@configdir@ + +include $(configdir)/@common_makefile@ + + +all: include-all libsrc-all apps-all tests-all + +install: install-bin install-doc install-support + +install-bin: apps-install + +install-doc: docs-install + +install-data: data-install + +install-etc: etc-install + +install-include: include-install + +install-lib: libsrc-install install-include + +install-support: install-data install-etc + + +include-all: + (cd include && $(MAKE) ARCH="$(ARCH)" all) + +libsrc-all: include-all + (cd libsrc && $(MAKE) ARCH="$(ARCH)" all) + (cd libi2d && $(MAKE) ARCH="$(ARCH)" all) + +apps-all: libsrc-all + (cd apps && $(MAKE) ARCH="$(ARCH)" all) + +tests-all: libsrc-all + (cd tests && $(MAKE) ARCH="$(ARCH)" all) + + +check: tests-all + (cd tests && $(MAKE) check) + +check-exhaustive: tests-all + (cd tests && $(MAKE) check-exhaustive) + + +include-install: + (cd include && $(MAKE) ARCH="$(ARCH)" install) + +libsrc-install: libsrc-all + (cd libsrc && $(MAKE) ARCH="$(ARCH)" install-lib) + (cd libi2d && $(MAKE) ARCH="$(ARCH)" install-lib) + +apps-install: apps-all + (cd apps && $(MAKE) ARCH="$(ARCH)" install) + +docs-install: + (cd docs && $(MAKE) install) + +data-install: + (cd data && $(MAKE) install) + +etc-install: + (cd etc && $(MAKE) install) + + +clean: + (cd include && $(MAKE) clean) + (cd libsrc && $(MAKE) clean) + (cd libi2d && $(MAKE) clean) + (cd apps && $(MAKE) clean) + (cd tests && $(MAKE) clean) + (cd docs && $(MAKE) clean) + (cd data && $(MAKE) clean) + (cd etc && $(MAKE) clean) + rm -f $(TRASH) + +distclean: + (cd include && $(MAKE) distclean) + (cd libsrc && $(MAKE) distclean) + (cd libi2d && $(MAKE) distclean) + (cd apps && $(MAKE) distclean) + (cd tests && $(MAKE) distclean) + (cd docs && $(MAKE) distclean) + (cd data && $(MAKE) distclean) + (cd etc && $(MAKE) distclean) + rm -f $(DISTTRASH) + +dependencies: + (cd libsrc && touch $(DEP) && $(MAKE) dependencies) + (cd libi2d && touch $(DEP) && $(MAKE) dependencies) + (cd apps && touch $(DEP) && $(MAKE) dependencies) + (cd tests && touch $(DEP) && $(MAKE) dependencies) diff --git a/dcmdata/apps/CMakeLists.txt b/dcmdata/apps/CMakeLists.txt new file mode 100644 index 00000000..5394b1ec --- /dev/null +++ b/dcmdata/apps/CMakeLists.txt @@ -0,0 +1,17 @@ +# declare additional include directories +INCLUDE_DIRECTORIES(${LIBXML_INCDIR}) + +# declare executables +FOREACH(PROGRAM dcm2xml dcmconv dcmcrle dcmdrle dcmdump dcmftest dcmgpdir dump2dcm xml2dcm pdf2dcm dcm2pdf img2dcm) + DCMTK_ADD_EXECUTABLE(${PROGRAM} ${PROGRAM}) +ENDFOREACH(PROGRAM) +DCMTK_ADD_EXECUTABLE(dcmodify dcmodify mdfconen mdfdsman) + +# make sure executables are linked to the corresponding libraries +FOREACH(PROGRAM dcm2xml dcmconv dcmcrle dcmdrle dcmdump dcmgpdir dcmodify dump2dcm xml2dcm pdf2dcm dcm2pdf img2dcm) + DCMTK_TARGET_LINK_MODULES(${PROGRAM} dcmdata oflog ofstd) +ENDFOREACH(PROGRAM) + +DCMTK_TARGET_LINK_MODULES(dcmftest ofstd) +DCMTK_TARGET_LINK_LIBRARIES(xml2dcm ${LIBXML_LIBS}) +DCMTK_TARGET_LINK_MODULES(img2dcm i2d dcmdata) diff --git a/dcmdata/apps/Makefile.dep b/dcmdata/apps/Makefile.dep new file mode 100644 index 00000000..b2818e50 --- /dev/null +++ b/dcmdata/apps/Makefile.dep @@ -0,0 +1,1112 @@ +dcm2pdf.o: dcm2pdf.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../include/dcmtk/dcmdata/dctk.h ../include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../include/dcmtk/dcmdata/dcdefine.h ../include/dcmtk/dcmdata/dcswap.h \ + ../include/dcmtk/dcmdata/dcerror.h ../include/dcmtk/dcmdata/dcxfer.h \ + ../include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../include/dcmtk/dcmdata/dcistrma.h ../include/dcmtk/dcmdata/dcostrma.h \ + ../include/dcmtk/dcmdata/dcuid.h ../include/dcmtk/dcmdata/dctagkey.h \ + ../include/dcmtk/dcmdata/dctag.h ../include/dcmtk/dcmdata/dcdicent.h \ + ../include/dcmtk/dcmdata/dchashdi.h ../include/dcmtk/dcmdata/dcdict.h \ + ../include/dcmtk/dcmdata/dcdeftag.h ../include/dcmtk/dcmdata/dcobject.h \ + ../include/dcmtk/dcmdata/dcstack.h ../include/dcmtk/dcmdata/dcelem.h \ + ../include/dcmtk/dcmdata/dcitem.h ../include/dcmtk/dcmdata/dclist.h \ + ../include/dcmtk/dcmdata/dcpcache.h ../include/dcmtk/dcmdata/dcmetinf.h \ + ../include/dcmtk/dcmdata/dcdatset.h ../include/dcmtk/dcmdata/dcsequen.h \ + ../include/dcmtk/dcmdata/dcfilefo.h ../include/dcmtk/dcmdata/dcdicdir.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../include/dcmtk/dcmdata/dcdirrec.h ../include/dcmtk/dcmdata/dcvrulup.h \ + ../include/dcmtk/dcmdata/dcvrul.h ../include/dcmtk/dcmdata/dcpixseq.h \ + ../include/dcmtk/dcmdata/dcofsetl.h ../include/dcmtk/dcmdata/dcbytstr.h \ + ../include/dcmtk/dcmdata/dcvrae.h ../include/dcmtk/dcmdata/dcvras.h \ + ../include/dcmtk/dcmdata/dcvrcs.h ../include/dcmtk/dcmdata/dcvrda.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../include/dcmtk/dcmdata/dcvrds.h ../include/dcmtk/dcmdata/dcvrdt.h \ + ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../include/dcmtk/dcmdata/dcvris.h ../include/dcmtk/dcmdata/dcvrtm.h \ + ../include/dcmtk/dcmdata/dcvrui.h ../include/dcmtk/dcmdata/dcvrur.h \ + ../include/dcmtk/dcmdata/dcchrstr.h ../include/dcmtk/dcmdata/dcvrlo.h \ + ../include/dcmtk/dcmdata/dcvrlt.h ../include/dcmtk/dcmdata/dcvrpn.h \ + ../include/dcmtk/dcmdata/dcvrsh.h ../include/dcmtk/dcmdata/dcvrst.h \ + ../include/dcmtk/dcmdata/dcvruc.h ../include/dcmtk/dcmdata/dcvrut.h \ + ../include/dcmtk/dcmdata/dcvrobow.h ../include/dcmtk/dcmdata/dcpixel.h \ + ../include/dcmtk/dcmdata/dcvrpobw.h ../include/dcmtk/dcmdata/dcovlay.h \ + ../include/dcmtk/dcmdata/dcvrat.h ../include/dcmtk/dcmdata/dcvrss.h \ + ../include/dcmtk/dcmdata/dcvrus.h ../include/dcmtk/dcmdata/dcvrsl.h \ + ../include/dcmtk/dcmdata/dcvrfl.h ../include/dcmtk/dcmdata/dcvrfd.h \ + ../include/dcmtk/dcmdata/dcvrof.h ../include/dcmtk/dcmdata/dcvrod.h \ + ../include/dcmtk/dcmdata/cmdlnarg.h ../include/dcmtk/dcmdata/dcistrmz.h +dcm2xml.o: dcm2xml.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmdata/dctk.h ../include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../include/dcmtk/dcmdata/dcdefine.h ../include/dcmtk/dcmdata/dcswap.h \ + ../include/dcmtk/dcmdata/dcerror.h ../include/dcmtk/dcmdata/dcxfer.h \ + ../include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../include/dcmtk/dcmdata/dcistrma.h ../include/dcmtk/dcmdata/dcostrma.h \ + ../include/dcmtk/dcmdata/dcuid.h ../include/dcmtk/dcmdata/dctagkey.h \ + ../include/dcmtk/dcmdata/dctag.h ../include/dcmtk/dcmdata/dcdicent.h \ + ../include/dcmtk/dcmdata/dchashdi.h ../include/dcmtk/dcmdata/dcdict.h \ + ../include/dcmtk/dcmdata/dcdeftag.h ../include/dcmtk/dcmdata/dcobject.h \ + ../include/dcmtk/dcmdata/dcstack.h ../include/dcmtk/dcmdata/dcelem.h \ + ../include/dcmtk/dcmdata/dcitem.h ../include/dcmtk/dcmdata/dclist.h \ + ../include/dcmtk/dcmdata/dcpcache.h ../include/dcmtk/dcmdata/dcmetinf.h \ + ../include/dcmtk/dcmdata/dcdatset.h ../include/dcmtk/dcmdata/dcsequen.h \ + ../include/dcmtk/dcmdata/dcfilefo.h ../include/dcmtk/dcmdata/dcdicdir.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../include/dcmtk/dcmdata/dcdirrec.h ../include/dcmtk/dcmdata/dcvrulup.h \ + ../include/dcmtk/dcmdata/dcvrul.h ../include/dcmtk/dcmdata/dcpixseq.h \ + ../include/dcmtk/dcmdata/dcofsetl.h ../include/dcmtk/dcmdata/dcbytstr.h \ + ../include/dcmtk/dcmdata/dcvrae.h ../include/dcmtk/dcmdata/dcvras.h \ + ../include/dcmtk/dcmdata/dcvrcs.h ../include/dcmtk/dcmdata/dcvrda.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../include/dcmtk/dcmdata/dcvrds.h ../include/dcmtk/dcmdata/dcvrdt.h \ + ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../include/dcmtk/dcmdata/dcvris.h ../include/dcmtk/dcmdata/dcvrtm.h \ + ../include/dcmtk/dcmdata/dcvrui.h ../include/dcmtk/dcmdata/dcvrur.h \ + ../include/dcmtk/dcmdata/dcchrstr.h ../include/dcmtk/dcmdata/dcvrlo.h \ + ../include/dcmtk/dcmdata/dcvrlt.h ../include/dcmtk/dcmdata/dcvrpn.h \ + ../include/dcmtk/dcmdata/dcvrsh.h ../include/dcmtk/dcmdata/dcvrst.h \ + ../include/dcmtk/dcmdata/dcvruc.h ../include/dcmtk/dcmdata/dcvrut.h \ + ../include/dcmtk/dcmdata/dcvrobow.h ../include/dcmtk/dcmdata/dcpixel.h \ + ../include/dcmtk/dcmdata/dcvrpobw.h ../include/dcmtk/dcmdata/dcovlay.h \ + ../include/dcmtk/dcmdata/dcvrat.h ../include/dcmtk/dcmdata/dcvrss.h \ + ../include/dcmtk/dcmdata/dcvrus.h ../include/dcmtk/dcmdata/dcvrsl.h \ + ../include/dcmtk/dcmdata/dcvrfl.h ../include/dcmtk/dcmdata/dcvrfd.h \ + ../include/dcmtk/dcmdata/dcvrof.h ../include/dcmtk/dcmdata/dcvrod.h \ + ../include/dcmtk/dcmdata/cmdlnarg.h \ + ../../ofstd/include/dcmtk/ofstd/ofchrenc.h +dcmconv.o: dcmconv.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../include/dcmtk/dcmdata/dctk.h ../include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../include/dcmtk/dcmdata/dcdefine.h ../include/dcmtk/dcmdata/dcswap.h \ + ../include/dcmtk/dcmdata/dcerror.h ../include/dcmtk/dcmdata/dcxfer.h \ + ../include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../include/dcmtk/dcmdata/dcistrma.h ../include/dcmtk/dcmdata/dcostrma.h \ + ../include/dcmtk/dcmdata/dcuid.h ../include/dcmtk/dcmdata/dctagkey.h \ + ../include/dcmtk/dcmdata/dctag.h ../include/dcmtk/dcmdata/dcdicent.h \ + ../include/dcmtk/dcmdata/dchashdi.h ../include/dcmtk/dcmdata/dcdict.h \ + ../include/dcmtk/dcmdata/dcdeftag.h ../include/dcmtk/dcmdata/dcobject.h \ + ../include/dcmtk/dcmdata/dcstack.h ../include/dcmtk/dcmdata/dcelem.h \ + ../include/dcmtk/dcmdata/dcitem.h ../include/dcmtk/dcmdata/dclist.h \ + ../include/dcmtk/dcmdata/dcpcache.h ../include/dcmtk/dcmdata/dcmetinf.h \ + ../include/dcmtk/dcmdata/dcdatset.h ../include/dcmtk/dcmdata/dcsequen.h \ + ../include/dcmtk/dcmdata/dcfilefo.h ../include/dcmtk/dcmdata/dcdicdir.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../include/dcmtk/dcmdata/dcdirrec.h ../include/dcmtk/dcmdata/dcvrulup.h \ + ../include/dcmtk/dcmdata/dcvrul.h ../include/dcmtk/dcmdata/dcpixseq.h \ + ../include/dcmtk/dcmdata/dcofsetl.h ../include/dcmtk/dcmdata/dcbytstr.h \ + ../include/dcmtk/dcmdata/dcvrae.h ../include/dcmtk/dcmdata/dcvras.h \ + ../include/dcmtk/dcmdata/dcvrcs.h ../include/dcmtk/dcmdata/dcvrda.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../include/dcmtk/dcmdata/dcvrds.h ../include/dcmtk/dcmdata/dcvrdt.h \ + ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../include/dcmtk/dcmdata/dcvris.h ../include/dcmtk/dcmdata/dcvrtm.h \ + ../include/dcmtk/dcmdata/dcvrui.h ../include/dcmtk/dcmdata/dcvrur.h \ + ../include/dcmtk/dcmdata/dcchrstr.h ../include/dcmtk/dcmdata/dcvrlo.h \ + ../include/dcmtk/dcmdata/dcvrlt.h ../include/dcmtk/dcmdata/dcvrpn.h \ + ../include/dcmtk/dcmdata/dcvrsh.h ../include/dcmtk/dcmdata/dcvrst.h \ + ../include/dcmtk/dcmdata/dcvruc.h ../include/dcmtk/dcmdata/dcvrut.h \ + ../include/dcmtk/dcmdata/dcvrobow.h ../include/dcmtk/dcmdata/dcpixel.h \ + ../include/dcmtk/dcmdata/dcvrpobw.h ../include/dcmtk/dcmdata/dcovlay.h \ + ../include/dcmtk/dcmdata/dcvrat.h ../include/dcmtk/dcmdata/dcvrss.h \ + ../include/dcmtk/dcmdata/dcvrus.h ../include/dcmtk/dcmdata/dcvrsl.h \ + ../include/dcmtk/dcmdata/dcvrfl.h ../include/dcmtk/dcmdata/dcvrfd.h \ + ../include/dcmtk/dcmdata/dcvrof.h ../include/dcmtk/dcmdata/dcvrod.h \ + ../include/dcmtk/dcmdata/cmdlnarg.h ../include/dcmtk/dcmdata/dcostrmz.h \ + ../include/dcmtk/dcmdata/dcistrmz.h \ + ../../ofstd/include/dcmtk/ofstd/ofchrenc.h +dcmcrle.o: dcmcrle.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../include/dcmtk/dcmdata/dctk.h ../include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../include/dcmtk/dcmdata/dcdefine.h ../include/dcmtk/dcmdata/dcswap.h \ + ../include/dcmtk/dcmdata/dcerror.h ../include/dcmtk/dcmdata/dcxfer.h \ + ../include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../include/dcmtk/dcmdata/dcistrma.h ../include/dcmtk/dcmdata/dcostrma.h \ + ../include/dcmtk/dcmdata/dcuid.h ../include/dcmtk/dcmdata/dctagkey.h \ + ../include/dcmtk/dcmdata/dctag.h ../include/dcmtk/dcmdata/dcdicent.h \ + ../include/dcmtk/dcmdata/dchashdi.h ../include/dcmtk/dcmdata/dcdict.h \ + ../include/dcmtk/dcmdata/dcdeftag.h ../include/dcmtk/dcmdata/dcobject.h \ + ../include/dcmtk/dcmdata/dcstack.h ../include/dcmtk/dcmdata/dcelem.h \ + ../include/dcmtk/dcmdata/dcitem.h ../include/dcmtk/dcmdata/dclist.h \ + ../include/dcmtk/dcmdata/dcpcache.h ../include/dcmtk/dcmdata/dcmetinf.h \ + ../include/dcmtk/dcmdata/dcdatset.h ../include/dcmtk/dcmdata/dcsequen.h \ + ../include/dcmtk/dcmdata/dcfilefo.h ../include/dcmtk/dcmdata/dcdicdir.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../include/dcmtk/dcmdata/dcdirrec.h ../include/dcmtk/dcmdata/dcvrulup.h \ + ../include/dcmtk/dcmdata/dcvrul.h ../include/dcmtk/dcmdata/dcpixseq.h \ + ../include/dcmtk/dcmdata/dcofsetl.h ../include/dcmtk/dcmdata/dcbytstr.h \ + ../include/dcmtk/dcmdata/dcvrae.h ../include/dcmtk/dcmdata/dcvras.h \ + ../include/dcmtk/dcmdata/dcvrcs.h ../include/dcmtk/dcmdata/dcvrda.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../include/dcmtk/dcmdata/dcvrds.h ../include/dcmtk/dcmdata/dcvrdt.h \ + ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../include/dcmtk/dcmdata/dcvris.h ../include/dcmtk/dcmdata/dcvrtm.h \ + ../include/dcmtk/dcmdata/dcvrui.h ../include/dcmtk/dcmdata/dcvrur.h \ + ../include/dcmtk/dcmdata/dcchrstr.h ../include/dcmtk/dcmdata/dcvrlo.h \ + ../include/dcmtk/dcmdata/dcvrlt.h ../include/dcmtk/dcmdata/dcvrpn.h \ + ../include/dcmtk/dcmdata/dcvrsh.h ../include/dcmtk/dcmdata/dcvrst.h \ + ../include/dcmtk/dcmdata/dcvruc.h ../include/dcmtk/dcmdata/dcvrut.h \ + ../include/dcmtk/dcmdata/dcvrobow.h ../include/dcmtk/dcmdata/dcpixel.h \ + ../include/dcmtk/dcmdata/dcvrpobw.h ../include/dcmtk/dcmdata/dcovlay.h \ + ../include/dcmtk/dcmdata/dcvrat.h ../include/dcmtk/dcmdata/dcvrss.h \ + ../include/dcmtk/dcmdata/dcvrus.h ../include/dcmtk/dcmdata/dcvrsl.h \ + ../include/dcmtk/dcmdata/dcvrfl.h ../include/dcmtk/dcmdata/dcvrfd.h \ + ../include/dcmtk/dcmdata/dcvrof.h ../include/dcmtk/dcmdata/dcvrod.h \ + ../include/dcmtk/dcmdata/cmdlnarg.h ../include/dcmtk/dcmdata/dcrleerg.h +dcmdrle.o: dcmdrle.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../include/dcmtk/dcmdata/dctk.h ../include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../include/dcmtk/dcmdata/dcdefine.h ../include/dcmtk/dcmdata/dcswap.h \ + ../include/dcmtk/dcmdata/dcerror.h ../include/dcmtk/dcmdata/dcxfer.h \ + ../include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../include/dcmtk/dcmdata/dcistrma.h ../include/dcmtk/dcmdata/dcostrma.h \ + ../include/dcmtk/dcmdata/dcuid.h ../include/dcmtk/dcmdata/dctagkey.h \ + ../include/dcmtk/dcmdata/dctag.h ../include/dcmtk/dcmdata/dcdicent.h \ + ../include/dcmtk/dcmdata/dchashdi.h ../include/dcmtk/dcmdata/dcdict.h \ + ../include/dcmtk/dcmdata/dcdeftag.h ../include/dcmtk/dcmdata/dcobject.h \ + ../include/dcmtk/dcmdata/dcstack.h ../include/dcmtk/dcmdata/dcelem.h \ + ../include/dcmtk/dcmdata/dcitem.h ../include/dcmtk/dcmdata/dclist.h \ + ../include/dcmtk/dcmdata/dcpcache.h ../include/dcmtk/dcmdata/dcmetinf.h \ + ../include/dcmtk/dcmdata/dcdatset.h ../include/dcmtk/dcmdata/dcsequen.h \ + ../include/dcmtk/dcmdata/dcfilefo.h ../include/dcmtk/dcmdata/dcdicdir.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../include/dcmtk/dcmdata/dcdirrec.h ../include/dcmtk/dcmdata/dcvrulup.h \ + ../include/dcmtk/dcmdata/dcvrul.h ../include/dcmtk/dcmdata/dcpixseq.h \ + ../include/dcmtk/dcmdata/dcofsetl.h ../include/dcmtk/dcmdata/dcbytstr.h \ + ../include/dcmtk/dcmdata/dcvrae.h ../include/dcmtk/dcmdata/dcvras.h \ + ../include/dcmtk/dcmdata/dcvrcs.h ../include/dcmtk/dcmdata/dcvrda.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../include/dcmtk/dcmdata/dcvrds.h ../include/dcmtk/dcmdata/dcvrdt.h \ + ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../include/dcmtk/dcmdata/dcvris.h ../include/dcmtk/dcmdata/dcvrtm.h \ + ../include/dcmtk/dcmdata/dcvrui.h ../include/dcmtk/dcmdata/dcvrur.h \ + ../include/dcmtk/dcmdata/dcchrstr.h ../include/dcmtk/dcmdata/dcvrlo.h \ + ../include/dcmtk/dcmdata/dcvrlt.h ../include/dcmtk/dcmdata/dcvrpn.h \ + ../include/dcmtk/dcmdata/dcvrsh.h ../include/dcmtk/dcmdata/dcvrst.h \ + ../include/dcmtk/dcmdata/dcvruc.h ../include/dcmtk/dcmdata/dcvrut.h \ + ../include/dcmtk/dcmdata/dcvrobow.h ../include/dcmtk/dcmdata/dcpixel.h \ + ../include/dcmtk/dcmdata/dcvrpobw.h ../include/dcmtk/dcmdata/dcovlay.h \ + ../include/dcmtk/dcmdata/dcvrat.h ../include/dcmtk/dcmdata/dcvrss.h \ + ../include/dcmtk/dcmdata/dcvrus.h ../include/dcmtk/dcmdata/dcvrsl.h \ + ../include/dcmtk/dcmdata/dcvrfl.h ../include/dcmtk/dcmdata/dcvrfd.h \ + ../include/dcmtk/dcmdata/dcvrof.h ../include/dcmtk/dcmdata/dcvrod.h \ + ../include/dcmtk/dcmdata/cmdlnarg.h ../include/dcmtk/dcmdata/dcrledrg.h +dcmdump.o: dcmdump.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../include/dcmtk/dcmdata/dctk.h ../include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../include/dcmtk/dcmdata/dcdefine.h ../include/dcmtk/dcmdata/dcswap.h \ + ../include/dcmtk/dcmdata/dcerror.h ../include/dcmtk/dcmdata/dcxfer.h \ + ../include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../include/dcmtk/dcmdata/dcistrma.h ../include/dcmtk/dcmdata/dcostrma.h \ + ../include/dcmtk/dcmdata/dcuid.h ../include/dcmtk/dcmdata/dctagkey.h \ + ../include/dcmtk/dcmdata/dctag.h ../include/dcmtk/dcmdata/dcdicent.h \ + ../include/dcmtk/dcmdata/dchashdi.h ../include/dcmtk/dcmdata/dcdict.h \ + ../include/dcmtk/dcmdata/dcdeftag.h ../include/dcmtk/dcmdata/dcobject.h \ + ../include/dcmtk/dcmdata/dcstack.h ../include/dcmtk/dcmdata/dcelem.h \ + ../include/dcmtk/dcmdata/dcitem.h ../include/dcmtk/dcmdata/dclist.h \ + ../include/dcmtk/dcmdata/dcpcache.h ../include/dcmtk/dcmdata/dcmetinf.h \ + ../include/dcmtk/dcmdata/dcdatset.h ../include/dcmtk/dcmdata/dcsequen.h \ + ../include/dcmtk/dcmdata/dcfilefo.h ../include/dcmtk/dcmdata/dcdicdir.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../include/dcmtk/dcmdata/dcdirrec.h ../include/dcmtk/dcmdata/dcvrulup.h \ + ../include/dcmtk/dcmdata/dcvrul.h ../include/dcmtk/dcmdata/dcpixseq.h \ + ../include/dcmtk/dcmdata/dcofsetl.h ../include/dcmtk/dcmdata/dcbytstr.h \ + ../include/dcmtk/dcmdata/dcvrae.h ../include/dcmtk/dcmdata/dcvras.h \ + ../include/dcmtk/dcmdata/dcvrcs.h ../include/dcmtk/dcmdata/dcvrda.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../include/dcmtk/dcmdata/dcvrds.h ../include/dcmtk/dcmdata/dcvrdt.h \ + ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../include/dcmtk/dcmdata/dcvris.h ../include/dcmtk/dcmdata/dcvrtm.h \ + ../include/dcmtk/dcmdata/dcvrui.h ../include/dcmtk/dcmdata/dcvrur.h \ + ../include/dcmtk/dcmdata/dcchrstr.h ../include/dcmtk/dcmdata/dcvrlo.h \ + ../include/dcmtk/dcmdata/dcvrlt.h ../include/dcmtk/dcmdata/dcvrpn.h \ + ../include/dcmtk/dcmdata/dcvrsh.h ../include/dcmtk/dcmdata/dcvrst.h \ + ../include/dcmtk/dcmdata/dcvruc.h ../include/dcmtk/dcmdata/dcvrut.h \ + ../include/dcmtk/dcmdata/dcvrobow.h ../include/dcmtk/dcmdata/dcpixel.h \ + ../include/dcmtk/dcmdata/dcvrpobw.h ../include/dcmtk/dcmdata/dcovlay.h \ + ../include/dcmtk/dcmdata/dcvrat.h ../include/dcmtk/dcmdata/dcvrss.h \ + ../include/dcmtk/dcmdata/dcvrus.h ../include/dcmtk/dcmdata/dcvrsl.h \ + ../include/dcmtk/dcmdata/dcvrfl.h ../include/dcmtk/dcmdata/dcvrfd.h \ + ../include/dcmtk/dcmdata/dcvrof.h ../include/dcmtk/dcmdata/dcvrod.h \ + ../include/dcmtk/dcmdata/cmdlnarg.h ../include/dcmtk/dcmdata/dcistrmz.h \ + ../../ofstd/include/dcmtk/ofstd/ofchrenc.h +dcmftest.o: dcmftest.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../include/dcmtk/dcmdata/dcmetinf.h ../include/dcmtk/dcmdata/dcitem.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../include/dcmtk/dcmdata/dcdefine.h ../include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../include/dcmtk/dcmdata/dcerror.h ../include/dcmtk/dcmdata/dcxfer.h \ + ../include/dcmtk/dcmdata/dcvr.h ../include/dcmtk/dcmdata/dctag.h \ + ../include/dcmtk/dcmdata/dctagkey.h ../include/dcmtk/dcmdata/dcstack.h \ + ../include/dcmtk/dcmdata/dclist.h ../include/dcmtk/dcmdata/dcpcache.h \ + ../include/dcmtk/dcmdata/dcuid.h +dcmgpdir.o: dcmgpdir.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmdata/dctk.h ../include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../include/dcmtk/dcmdata/dcdefine.h ../include/dcmtk/dcmdata/dcswap.h \ + ../include/dcmtk/dcmdata/dcerror.h ../include/dcmtk/dcmdata/dcxfer.h \ + ../include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../include/dcmtk/dcmdata/dcistrma.h ../include/dcmtk/dcmdata/dcostrma.h \ + ../include/dcmtk/dcmdata/dcuid.h ../include/dcmtk/dcmdata/dctagkey.h \ + ../include/dcmtk/dcmdata/dctag.h ../include/dcmtk/dcmdata/dcdicent.h \ + ../include/dcmtk/dcmdata/dchashdi.h ../include/dcmtk/dcmdata/dcdict.h \ + ../include/dcmtk/dcmdata/dcdeftag.h ../include/dcmtk/dcmdata/dcobject.h \ + ../include/dcmtk/dcmdata/dcstack.h ../include/dcmtk/dcmdata/dcelem.h \ + ../include/dcmtk/dcmdata/dcitem.h ../include/dcmtk/dcmdata/dclist.h \ + ../include/dcmtk/dcmdata/dcpcache.h ../include/dcmtk/dcmdata/dcmetinf.h \ + ../include/dcmtk/dcmdata/dcdatset.h ../include/dcmtk/dcmdata/dcsequen.h \ + ../include/dcmtk/dcmdata/dcfilefo.h ../include/dcmtk/dcmdata/dcdicdir.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../include/dcmtk/dcmdata/dcdirrec.h ../include/dcmtk/dcmdata/dcvrulup.h \ + ../include/dcmtk/dcmdata/dcvrul.h ../include/dcmtk/dcmdata/dcpixseq.h \ + ../include/dcmtk/dcmdata/dcofsetl.h ../include/dcmtk/dcmdata/dcbytstr.h \ + ../include/dcmtk/dcmdata/dcvrae.h ../include/dcmtk/dcmdata/dcvras.h \ + ../include/dcmtk/dcmdata/dcvrcs.h ../include/dcmtk/dcmdata/dcvrda.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../include/dcmtk/dcmdata/dcvrds.h ../include/dcmtk/dcmdata/dcvrdt.h \ + ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../include/dcmtk/dcmdata/dcvris.h ../include/dcmtk/dcmdata/dcvrtm.h \ + ../include/dcmtk/dcmdata/dcvrui.h ../include/dcmtk/dcmdata/dcvrur.h \ + ../include/dcmtk/dcmdata/dcchrstr.h ../include/dcmtk/dcmdata/dcvrlo.h \ + ../include/dcmtk/dcmdata/dcvrlt.h ../include/dcmtk/dcmdata/dcvrpn.h \ + ../include/dcmtk/dcmdata/dcvrsh.h ../include/dcmtk/dcmdata/dcvrst.h \ + ../include/dcmtk/dcmdata/dcvruc.h ../include/dcmtk/dcmdata/dcvrut.h \ + ../include/dcmtk/dcmdata/dcvrobow.h ../include/dcmtk/dcmdata/dcpixel.h \ + ../include/dcmtk/dcmdata/dcvrpobw.h ../include/dcmtk/dcmdata/dcovlay.h \ + ../include/dcmtk/dcmdata/dcvrat.h ../include/dcmtk/dcmdata/dcvrss.h \ + ../include/dcmtk/dcmdata/dcvrus.h ../include/dcmtk/dcmdata/dcvrsl.h \ + ../include/dcmtk/dcmdata/dcvrfl.h ../include/dcmtk/dcmdata/dcvrfd.h \ + ../include/dcmtk/dcmdata/dcvrof.h ../include/dcmtk/dcmdata/dcvrod.h \ + ../include/dcmtk/dcmdata/cmdlnarg.h ../include/dcmtk/dcmdata/dcddirif.h +dcmodify.o: dcmodify.cc ../../config/include/dcmtk/config/osconfig.h \ + mdfconen.h ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../include/dcmtk/dcmdata/dcxfer.h ../include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../include/dcmtk/dcmdata/dcdefine.h ../include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../include/dcmtk/dcmdata/dcpath.h ../include/dcmtk/dcmdata/dcdatset.h \ + ../include/dcmtk/dcmdata/dcitem.h ../include/dcmtk/dcmdata/dcobject.h \ + ../include/dcmtk/dcmdata/dcerror.h ../include/dcmtk/dcmdata/dctag.h \ + ../include/dcmtk/dcmdata/dctagkey.h ../include/dcmtk/dcmdata/dcstack.h \ + ../include/dcmtk/dcmdata/dclist.h ../include/dcmtk/dcmdata/dcpcache.h +dump2dcm.o: dump2dcm.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h ../include/dcmtk/dcmdata/dctk.h \ + ../include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../include/dcmtk/dcmdata/dcdefine.h ../include/dcmtk/dcmdata/dcswap.h \ + ../include/dcmtk/dcmdata/dcerror.h ../include/dcmtk/dcmdata/dcxfer.h \ + ../include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../include/dcmtk/dcmdata/dcistrma.h ../include/dcmtk/dcmdata/dcostrma.h \ + ../include/dcmtk/dcmdata/dcuid.h ../include/dcmtk/dcmdata/dctagkey.h \ + ../include/dcmtk/dcmdata/dctag.h ../include/dcmtk/dcmdata/dcdicent.h \ + ../include/dcmtk/dcmdata/dchashdi.h ../include/dcmtk/dcmdata/dcdict.h \ + ../include/dcmtk/dcmdata/dcdeftag.h ../include/dcmtk/dcmdata/dcobject.h \ + ../include/dcmtk/dcmdata/dcstack.h ../include/dcmtk/dcmdata/dcelem.h \ + ../include/dcmtk/dcmdata/dcitem.h ../include/dcmtk/dcmdata/dclist.h \ + ../include/dcmtk/dcmdata/dcpcache.h ../include/dcmtk/dcmdata/dcmetinf.h \ + ../include/dcmtk/dcmdata/dcdatset.h ../include/dcmtk/dcmdata/dcsequen.h \ + ../include/dcmtk/dcmdata/dcfilefo.h ../include/dcmtk/dcmdata/dcdicdir.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../include/dcmtk/dcmdata/dcdirrec.h ../include/dcmtk/dcmdata/dcvrulup.h \ + ../include/dcmtk/dcmdata/dcvrul.h ../include/dcmtk/dcmdata/dcpixseq.h \ + ../include/dcmtk/dcmdata/dcofsetl.h ../include/dcmtk/dcmdata/dcbytstr.h \ + ../include/dcmtk/dcmdata/dcvrae.h ../include/dcmtk/dcmdata/dcvras.h \ + ../include/dcmtk/dcmdata/dcvrcs.h ../include/dcmtk/dcmdata/dcvrda.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../include/dcmtk/dcmdata/dcvrds.h ../include/dcmtk/dcmdata/dcvrdt.h \ + ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../include/dcmtk/dcmdata/dcvris.h ../include/dcmtk/dcmdata/dcvrtm.h \ + ../include/dcmtk/dcmdata/dcvrui.h ../include/dcmtk/dcmdata/dcvrur.h \ + ../include/dcmtk/dcmdata/dcchrstr.h ../include/dcmtk/dcmdata/dcvrlo.h \ + ../include/dcmtk/dcmdata/dcvrlt.h ../include/dcmtk/dcmdata/dcvrpn.h \ + ../include/dcmtk/dcmdata/dcvrsh.h ../include/dcmtk/dcmdata/dcvrst.h \ + ../include/dcmtk/dcmdata/dcvruc.h ../include/dcmtk/dcmdata/dcvrut.h \ + ../include/dcmtk/dcmdata/dcvrobow.h ../include/dcmtk/dcmdata/dcpixel.h \ + ../include/dcmtk/dcmdata/dcvrpobw.h ../include/dcmtk/dcmdata/dcovlay.h \ + ../include/dcmtk/dcmdata/dcvrat.h ../include/dcmtk/dcmdata/dcvrss.h \ + ../include/dcmtk/dcmdata/dcvrus.h ../include/dcmtk/dcmdata/dcvrsl.h \ + ../include/dcmtk/dcmdata/dcvrfl.h ../include/dcmtk/dcmdata/dcvrfd.h \ + ../include/dcmtk/dcmdata/dcvrof.h ../include/dcmtk/dcmdata/dcvrod.h \ + ../include/dcmtk/dcmdata/cmdlnarg.h ../include/dcmtk/dcmdata/dcpxitem.h \ + ../include/dcmtk/dcmdata/dcostrmz.h +img2dcm.o: img2dcm.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmdata/cmdlnarg.h ../include/dcmtk/dcmdata/dcdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../include/dcmtk/dcmdata/dcuid.h ../include/dcmtk/dcmdata/dcfilefo.h \ + ../include/dcmtk/dcmdata/dcsequen.h ../include/dcmtk/dcmdata/dcelem.h \ + ../include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../include/dcmtk/dcmdata/dcerror.h ../include/dcmtk/dcmdata/dcxfer.h \ + ../include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../include/dcmtk/dcmdata/dcvr.h ../include/dcmtk/dcmdata/dctag.h \ + ../include/dcmtk/dcmdata/dctagkey.h ../include/dcmtk/dcmdata/dcstack.h \ + ../include/dcmtk/dcmdata/dclist.h ../include/dcmtk/dcmdata/dcdatset.h \ + ../include/dcmtk/dcmdata/dcitem.h ../include/dcmtk/dcmdata/dcpcache.h \ + ../include/dcmtk/dcmdata/dcdict.h ../include/dcmtk/dcmdata/dchashdi.h \ + ../include/dcmtk/dcmdata/libi2d/i2d.h \ + ../include/dcmtk/dcmdata/libi2d/i2doutpl.h \ + ../include/dcmtk/dcmdata/libi2d/i2define.h \ + ../include/dcmtk/dcmdata/libi2d/i2dimgs.h \ + ../include/dcmtk/dcmdata/dcpixel.h ../include/dcmtk/dcmdata/dcvrpobw.h \ + ../include/dcmtk/dcmdata/dcvrobow.h \ + ../include/dcmtk/dcmdata/libi2d/i2djpgs.h \ + ../include/dcmtk/dcmdata/libi2d/i2dbmps.h \ + ../include/dcmtk/dcmdata/libi2d/i2dplsc.h \ + ../include/dcmtk/dcmdata/libi2d/i2dplvlp.h \ + ../include/dcmtk/dcmdata/libi2d/i2dplnsc.h +mdfconen.o: mdfconen.cc ../../config/include/dcmtk/config/osconfig.h \ + mdfconen.h ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../include/dcmtk/dcmdata/dcxfer.h ../include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../include/dcmtk/dcmdata/dcdefine.h ../include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h mdfdsman.h \ + ../include/dcmtk/dcmdata/dctagkey.h ../include/dcmtk/dcmdata/dctk.h \ + ../include/dcmtk/dcmdata/dcswap.h ../include/dcmtk/dcmdata/dcerror.h \ + ../include/dcmtk/dcmdata/dcistrma.h ../include/dcmtk/dcmdata/dcostrma.h \ + ../include/dcmtk/dcmdata/dcuid.h ../include/dcmtk/dcmdata/dctag.h \ + ../include/dcmtk/dcmdata/dcdicent.h ../include/dcmtk/dcmdata/dchashdi.h \ + ../include/dcmtk/dcmdata/dcdict.h ../include/dcmtk/dcmdata/dcdeftag.h \ + ../include/dcmtk/dcmdata/dcobject.h ../include/dcmtk/dcmdata/dcstack.h \ + ../include/dcmtk/dcmdata/dcelem.h ../include/dcmtk/dcmdata/dcitem.h \ + ../include/dcmtk/dcmdata/dclist.h ../include/dcmtk/dcmdata/dcpcache.h \ + ../include/dcmtk/dcmdata/dcmetinf.h ../include/dcmtk/dcmdata/dcdatset.h \ + ../include/dcmtk/dcmdata/dcsequen.h ../include/dcmtk/dcmdata/dcfilefo.h \ + ../include/dcmtk/dcmdata/dcdicdir.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../include/dcmtk/dcmdata/dcdirrec.h ../include/dcmtk/dcmdata/dcvrulup.h \ + ../include/dcmtk/dcmdata/dcvrul.h ../include/dcmtk/dcmdata/dcpixseq.h \ + ../include/dcmtk/dcmdata/dcofsetl.h ../include/dcmtk/dcmdata/dcbytstr.h \ + ../include/dcmtk/dcmdata/dcvrae.h ../include/dcmtk/dcmdata/dcvras.h \ + ../include/dcmtk/dcmdata/dcvrcs.h ../include/dcmtk/dcmdata/dcvrda.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../include/dcmtk/dcmdata/dcvrds.h ../include/dcmtk/dcmdata/dcvrdt.h \ + ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../include/dcmtk/dcmdata/dcvris.h ../include/dcmtk/dcmdata/dcvrtm.h \ + ../include/dcmtk/dcmdata/dcvrui.h ../include/dcmtk/dcmdata/dcvrur.h \ + ../include/dcmtk/dcmdata/dcchrstr.h ../include/dcmtk/dcmdata/dcvrlo.h \ + ../include/dcmtk/dcmdata/dcvrlt.h ../include/dcmtk/dcmdata/dcvrpn.h \ + ../include/dcmtk/dcmdata/dcvrsh.h ../include/dcmtk/dcmdata/dcvrst.h \ + ../include/dcmtk/dcmdata/dcvruc.h ../include/dcmtk/dcmdata/dcvrut.h \ + ../include/dcmtk/dcmdata/dcvrobow.h ../include/dcmtk/dcmdata/dcpixel.h \ + ../include/dcmtk/dcmdata/dcvrpobw.h ../include/dcmtk/dcmdata/dcovlay.h \ + ../include/dcmtk/dcmdata/dcvrat.h ../include/dcmtk/dcmdata/dcvrss.h \ + ../include/dcmtk/dcmdata/dcvrus.h ../include/dcmtk/dcmdata/dcvrsl.h \ + ../include/dcmtk/dcmdata/dcvrfl.h ../include/dcmtk/dcmdata/dcvrfd.h \ + ../include/dcmtk/dcmdata/dcvrof.h ../include/dcmtk/dcmdata/dcvrod.h \ + ../include/dcmtk/dcmdata/cmdlnarg.h ../include/dcmtk/dcmdata/dcistrmz.h +mdfdsman.o: mdfdsman.cc ../../config/include/dcmtk/config/osconfig.h \ + mdfdsman.h ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../include/dcmtk/dcmdata/dctagkey.h ../include/dcmtk/dcmdata/dcdefine.h \ + ../include/dcmtk/dcmdata/dcxfer.h ../include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../include/dcmtk/dcmdata/dctk.h ../include/dcmtk/dcmdata/dcswap.h \ + ../include/dcmtk/dcmdata/dcerror.h ../include/dcmtk/dcmdata/dcistrma.h \ + ../include/dcmtk/dcmdata/dcostrma.h ../include/dcmtk/dcmdata/dcuid.h \ + ../include/dcmtk/dcmdata/dctag.h ../include/dcmtk/dcmdata/dcdicent.h \ + ../include/dcmtk/dcmdata/dchashdi.h ../include/dcmtk/dcmdata/dcdict.h \ + ../include/dcmtk/dcmdata/dcdeftag.h ../include/dcmtk/dcmdata/dcobject.h \ + ../include/dcmtk/dcmdata/dcstack.h ../include/dcmtk/dcmdata/dcelem.h \ + ../include/dcmtk/dcmdata/dcitem.h ../include/dcmtk/dcmdata/dclist.h \ + ../include/dcmtk/dcmdata/dcpcache.h ../include/dcmtk/dcmdata/dcmetinf.h \ + ../include/dcmtk/dcmdata/dcdatset.h ../include/dcmtk/dcmdata/dcsequen.h \ + ../include/dcmtk/dcmdata/dcfilefo.h ../include/dcmtk/dcmdata/dcdicdir.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../include/dcmtk/dcmdata/dcdirrec.h ../include/dcmtk/dcmdata/dcvrulup.h \ + ../include/dcmtk/dcmdata/dcvrul.h ../include/dcmtk/dcmdata/dcpixseq.h \ + ../include/dcmtk/dcmdata/dcofsetl.h ../include/dcmtk/dcmdata/dcbytstr.h \ + ../include/dcmtk/dcmdata/dcvrae.h ../include/dcmtk/dcmdata/dcvras.h \ + ../include/dcmtk/dcmdata/dcvrcs.h ../include/dcmtk/dcmdata/dcvrda.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../include/dcmtk/dcmdata/dcvrds.h ../include/dcmtk/dcmdata/dcvrdt.h \ + ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../include/dcmtk/dcmdata/dcvris.h ../include/dcmtk/dcmdata/dcvrtm.h \ + ../include/dcmtk/dcmdata/dcvrui.h ../include/dcmtk/dcmdata/dcvrur.h \ + ../include/dcmtk/dcmdata/dcchrstr.h ../include/dcmtk/dcmdata/dcvrlo.h \ + ../include/dcmtk/dcmdata/dcvrlt.h ../include/dcmtk/dcmdata/dcvrpn.h \ + ../include/dcmtk/dcmdata/dcvrsh.h ../include/dcmtk/dcmdata/dcvrst.h \ + ../include/dcmtk/dcmdata/dcvruc.h ../include/dcmtk/dcmdata/dcvrut.h \ + ../include/dcmtk/dcmdata/dcvrobow.h ../include/dcmtk/dcmdata/dcpixel.h \ + ../include/dcmtk/dcmdata/dcvrpobw.h ../include/dcmtk/dcmdata/dcovlay.h \ + ../include/dcmtk/dcmdata/dcvrat.h ../include/dcmtk/dcmdata/dcvrss.h \ + ../include/dcmtk/dcmdata/dcvrus.h ../include/dcmtk/dcmdata/dcvrsl.h \ + ../include/dcmtk/dcmdata/dcvrfl.h ../include/dcmtk/dcmdata/dcvrfd.h \ + ../include/dcmtk/dcmdata/dcvrof.h ../include/dcmtk/dcmdata/dcvrod.h \ + ../include/dcmtk/dcmdata/cmdlnarg.h ../include/dcmtk/dcmdata/dcpath.h \ + ../include/dcmtk/dcmdata/dcistrmf.h +pdf2dcm.o: pdf2dcm.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../include/dcmtk/dcmdata/dctk.h ../include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../include/dcmtk/dcmdata/dcdefine.h ../include/dcmtk/dcmdata/dcswap.h \ + ../include/dcmtk/dcmdata/dcerror.h ../include/dcmtk/dcmdata/dcxfer.h \ + ../include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../include/dcmtk/dcmdata/dcistrma.h ../include/dcmtk/dcmdata/dcostrma.h \ + ../include/dcmtk/dcmdata/dcuid.h ../include/dcmtk/dcmdata/dctagkey.h \ + ../include/dcmtk/dcmdata/dctag.h ../include/dcmtk/dcmdata/dcdicent.h \ + ../include/dcmtk/dcmdata/dchashdi.h ../include/dcmtk/dcmdata/dcdict.h \ + ../include/dcmtk/dcmdata/dcdeftag.h ../include/dcmtk/dcmdata/dcobject.h \ + ../include/dcmtk/dcmdata/dcstack.h ../include/dcmtk/dcmdata/dcelem.h \ + ../include/dcmtk/dcmdata/dcitem.h ../include/dcmtk/dcmdata/dclist.h \ + ../include/dcmtk/dcmdata/dcpcache.h ../include/dcmtk/dcmdata/dcmetinf.h \ + ../include/dcmtk/dcmdata/dcdatset.h ../include/dcmtk/dcmdata/dcsequen.h \ + ../include/dcmtk/dcmdata/dcfilefo.h ../include/dcmtk/dcmdata/dcdicdir.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../include/dcmtk/dcmdata/dcdirrec.h ../include/dcmtk/dcmdata/dcvrulup.h \ + ../include/dcmtk/dcmdata/dcvrul.h ../include/dcmtk/dcmdata/dcpixseq.h \ + ../include/dcmtk/dcmdata/dcofsetl.h ../include/dcmtk/dcmdata/dcbytstr.h \ + ../include/dcmtk/dcmdata/dcvrae.h ../include/dcmtk/dcmdata/dcvras.h \ + ../include/dcmtk/dcmdata/dcvrcs.h ../include/dcmtk/dcmdata/dcvrda.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../include/dcmtk/dcmdata/dcvrds.h ../include/dcmtk/dcmdata/dcvrdt.h \ + ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../include/dcmtk/dcmdata/dcvris.h ../include/dcmtk/dcmdata/dcvrtm.h \ + ../include/dcmtk/dcmdata/dcvrui.h ../include/dcmtk/dcmdata/dcvrur.h \ + ../include/dcmtk/dcmdata/dcchrstr.h ../include/dcmtk/dcmdata/dcvrlo.h \ + ../include/dcmtk/dcmdata/dcvrlt.h ../include/dcmtk/dcmdata/dcvrpn.h \ + ../include/dcmtk/dcmdata/dcvrsh.h ../include/dcmtk/dcmdata/dcvrst.h \ + ../include/dcmtk/dcmdata/dcvruc.h ../include/dcmtk/dcmdata/dcvrut.h \ + ../include/dcmtk/dcmdata/dcvrobow.h ../include/dcmtk/dcmdata/dcpixel.h \ + ../include/dcmtk/dcmdata/dcvrpobw.h ../include/dcmtk/dcmdata/dcovlay.h \ + ../include/dcmtk/dcmdata/dcvrat.h ../include/dcmtk/dcmdata/dcvrss.h \ + ../include/dcmtk/dcmdata/dcvrus.h ../include/dcmtk/dcmdata/dcvrsl.h \ + ../include/dcmtk/dcmdata/dcvrfl.h ../include/dcmtk/dcmdata/dcvrfd.h \ + ../include/dcmtk/dcmdata/dcvrof.h ../include/dcmtk/dcmdata/dcvrod.h \ + ../include/dcmtk/dcmdata/cmdlnarg.h ../include/dcmtk/dcmdata/dccodec.h +xml2dcm.o: xml2dcm.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmdata/dctk.h ../include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../include/dcmtk/dcmdata/dcdefine.h ../include/dcmtk/dcmdata/dcswap.h \ + ../include/dcmtk/dcmdata/dcerror.h ../include/dcmtk/dcmdata/dcxfer.h \ + ../include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../include/dcmtk/dcmdata/dcistrma.h ../include/dcmtk/dcmdata/dcostrma.h \ + ../include/dcmtk/dcmdata/dcuid.h ../include/dcmtk/dcmdata/dctagkey.h \ + ../include/dcmtk/dcmdata/dctag.h ../include/dcmtk/dcmdata/dcdicent.h \ + ../include/dcmtk/dcmdata/dchashdi.h ../include/dcmtk/dcmdata/dcdict.h \ + ../include/dcmtk/dcmdata/dcdeftag.h ../include/dcmtk/dcmdata/dcobject.h \ + ../include/dcmtk/dcmdata/dcstack.h ../include/dcmtk/dcmdata/dcelem.h \ + ../include/dcmtk/dcmdata/dcitem.h ../include/dcmtk/dcmdata/dclist.h \ + ../include/dcmtk/dcmdata/dcpcache.h ../include/dcmtk/dcmdata/dcmetinf.h \ + ../include/dcmtk/dcmdata/dcdatset.h ../include/dcmtk/dcmdata/dcsequen.h \ + ../include/dcmtk/dcmdata/dcfilefo.h ../include/dcmtk/dcmdata/dcdicdir.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../include/dcmtk/dcmdata/dcdirrec.h ../include/dcmtk/dcmdata/dcvrulup.h \ + ../include/dcmtk/dcmdata/dcvrul.h ../include/dcmtk/dcmdata/dcpixseq.h \ + ../include/dcmtk/dcmdata/dcofsetl.h ../include/dcmtk/dcmdata/dcbytstr.h \ + ../include/dcmtk/dcmdata/dcvrae.h ../include/dcmtk/dcmdata/dcvras.h \ + ../include/dcmtk/dcmdata/dcvrcs.h ../include/dcmtk/dcmdata/dcvrda.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../include/dcmtk/dcmdata/dcvrds.h ../include/dcmtk/dcmdata/dcvrdt.h \ + ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../include/dcmtk/dcmdata/dcvris.h ../include/dcmtk/dcmdata/dcvrtm.h \ + ../include/dcmtk/dcmdata/dcvrui.h ../include/dcmtk/dcmdata/dcvrur.h \ + ../include/dcmtk/dcmdata/dcchrstr.h ../include/dcmtk/dcmdata/dcvrlo.h \ + ../include/dcmtk/dcmdata/dcvrlt.h ../include/dcmtk/dcmdata/dcvrpn.h \ + ../include/dcmtk/dcmdata/dcvrsh.h ../include/dcmtk/dcmdata/dcvrst.h \ + ../include/dcmtk/dcmdata/dcvruc.h ../include/dcmtk/dcmdata/dcvrut.h \ + ../include/dcmtk/dcmdata/dcvrobow.h ../include/dcmtk/dcmdata/dcpixel.h \ + ../include/dcmtk/dcmdata/dcvrpobw.h ../include/dcmtk/dcmdata/dcovlay.h \ + ../include/dcmtk/dcmdata/dcvrat.h ../include/dcmtk/dcmdata/dcvrss.h \ + ../include/dcmtk/dcmdata/dcvrus.h ../include/dcmtk/dcmdata/dcvrsl.h \ + ../include/dcmtk/dcmdata/dcvrfl.h ../include/dcmtk/dcmdata/dcvrfd.h \ + ../include/dcmtk/dcmdata/dcvrof.h ../include/dcmtk/dcmdata/dcvrod.h \ + ../include/dcmtk/dcmdata/cmdlnarg.h ../include/dcmtk/dcmdata/dcpxitem.h \ + ../include/dcmtk/dcmdata/dcostrmz.h diff --git a/dcmdata/apps/Makefile.in b/dcmdata/apps/Makefile.in new file mode 100644 index 00000000..90bafb23 --- /dev/null +++ b/dcmdata/apps/Makefile.in @@ -0,0 +1,94 @@ +# +# Makefile for dcmdata/apps +# + +@SET_MAKE@ + +SHELL = /bin/sh +VPATH = @srcdir@:@top_srcdir@/include:@top_srcdir@/@configdir@/include +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +configdir = @top_srcdir@/@configdir@ + +include $(configdir)/@common_makefile@ + +ofstddir = $(top_srcdir)/../ofstd +oflogdir = $(top_srcdir)/../oflog + +LOCALINCLUDES = -I$(ofstddir)/include -I$(oflogdir)/include +LIBDIRS = -L$(top_srcdir)/libi2d -L$(top_srcdir)/libsrc -L$(ofstddir)/libsrc \ + -L$(oflogdir)/libsrc +LOCALLIBS = -ldcmdata -loflog -lofstd $(ZLIBLIBS) $(ICONVLIBS) +LIBI2D = -li2d + +objs = dcmftest.o dcmconv.o dcmdump.o dump2dcm.o dcmgpdir.o dcm2xml.o \ + xml2dcm.o dcmcrle.o dcmdrle.o dcmodify.o mdfdsman.o mdfconen.o \ + pdf2dcm.o dcm2pdf.o img2dcm.o + +progs = dcmftest dcmconv dcmdump dump2dcm dcmgpdir dcm2xml xml2dcm dcmcrle \ + dcmdrle dcmodify pdf2dcm dcm2pdf img2dcm + + +all: $(progs) + +# Note: dcmftest does not need LOCALLIBS on most platforms, but on OSF1 it is required. +dcmftest: dcmftest.o + $(CXX) $(CXXFLAGS) $(LIBDIRS) $(LDFLAGS) -o $@ $@.o $(LOCALLIBS) $(MATHLIBS) $(LIBS) + +dcmconv: dcmconv.o + $(CXX) $(CXXFLAGS) $(LIBDIRS) $(LDFLAGS) -o $@ $@.o $(LOCALLIBS) $(MATHLIBS) $(LIBS) + +dcmdump: dcmdump.o + $(CXX) $(CXXFLAGS) $(LIBDIRS) $(LDFLAGS) -o $@ $@.o $(LOCALLIBS) $(MATHLIBS) $(LIBS) + +dump2dcm: dump2dcm.o + $(CXX) $(CXXFLAGS) $(LIBDIRS) $(LDFLAGS) -o $@ $@.o $(LOCALLIBS) $(MATHLIBS) $(LIBS) + +dcmgpdir: dcmgpdir.o + $(CXX) $(CXXFLAGS) $(LIBDIRS) $(LDFLAGS) -o $@ $@.o $(LOCALLIBS) $(MATHLIBS) $(LIBS) + +dcmcrle: dcmcrle.o + $(CXX) $(CXXFLAGS) $(LIBDIRS) $(LDFLAGS) -o $@ $@.o $(LOCALLIBS) $(MATHLIBS) $(LIBS) + +dcmdrle: dcmdrle.o + $(CXX) $(CXXFLAGS) $(LIBDIRS) $(LDFLAGS) -o $@ $@.o $(LOCALLIBS) $(MATHLIBS) $(LIBS) + +dcm2xml: dcm2xml.o + $(CXX) $(CXXFLAGS) $(LIBDIRS) $(LDFLAGS) -o $@ $@.o $(LOCALLIBS) $(MATHLIBS) $(LIBS) + +xml2dcm: xml2dcm.o + $(CXX) $(CXXFLAGS) $(LIBDIRS) $(LDFLAGS) -o $@ $@.o $(XMLLIBS) $(LOCALLIBS) $(MATHLIBS) $(LIBS) + +dcmodify: dcmodify.o mdfconen.o mdfdsman.o + $(CXX) $(CXXFLAGS) $(LIBDIRS) $(LDFLAGS) -o $@ $@.o mdfconen.o mdfdsman.o $(LOCALLIBS) $(MATHLIBS) $(LIBS) + +pdf2dcm: pdf2dcm.o + $(CXX) $(CXXFLAGS) $(LIBDIRS) $(LDFLAGS) -o $@ $@.o $(LOCALLIBS) $(MATHLIBS) $(LIBS) + +dcm2pdf: dcm2pdf.o + $(CXX) $(CXXFLAGS) $(LIBDIRS) $(LDFLAGS) -o $@ $@.o $(LOCALLIBS) $(MATHLIBS) $(LIBS) + +img2dcm: img2dcm.o + $(CXX) $(CXXFLAGS) $(LIBDIRS) $(LDFLAGS) -o $@ $@.o $(LIBI2D) $(LOCALLIBS) $(MATHLIBS) $(LIBS) + + +install: install-bin + +install-bin: all + $(configdir)/mkinstalldirs $(DESTDIR)$(bindir) + for prog in $(progs); do \ + $(INSTALL_PROGRAM) $$prog$(BINEXT) $(DESTDIR)$(bindir) && $(STRIP) $(DESTDIR)$(bindir)/$$prog$(BINEXT) ;\ + done + + +clean: + rm -f $(objs) $(progs) $(TRASH) + +distclean: + rm -f $(objs) $(progs) $(DISTTRASH) + + +dependencies: + $(CXX) -MM $(defines) $(includes) $(CPPFLAGS) $(CXXFLAGS) *.cc > $(DEP) + +include $(DEP) diff --git a/dcmdata/apps/dcm2pdf.cc b/dcmdata/apps/dcm2pdf.cc new file mode 100644 index 00000000..2f0d1378 --- /dev/null +++ b/dcmdata/apps/dcm2pdf.cc @@ -0,0 +1,352 @@ +/* + * + * Copyright (C) 2007-2012, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Marco Eichelberg + * + * Purpose: Exctract PDF file from DICOM encapsulated PDF storage object + * + */ + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#define INCLUDE_CSTDLIB +#define INCLUDE_CSTDIO +#define INCLUDE_CSTRING +#include "dcmtk/ofstd/ofstdinc.h" + +BEGIN_EXTERN_C +#ifdef HAVE_FCNTL_H +#include /* for O_RDONLY */ +#endif +#ifdef HAVE_SYS_TYPES_H +#include /* required for sys/stat.h */ +#endif +#ifdef HAVE_SYS_STAT_H +#include /* for stat, fstat */ +#endif +END_EXTERN_C + +#include "dcmtk/dcmdata/dctk.h" +#include "dcmtk/dcmdata/cmdlnarg.h" +#include "dcmtk/ofstd/ofconapp.h" +#include "dcmtk/dcmdata/dcuid.h" /* for dcmtk version name */ +#include "dcmtk/ofstd/ofstd.h" +#include "dcmtk/dcmdata/dcistrmz.h" /* for dcmZlibExpectRFC1950Encoding */ + +#ifdef WITH_ZLIB +#include /* for zlibVersion() */ +#endif + +#define OFFIS_CONSOLE_APPLICATION "dcm2pdf" + +static OFLogger dcm2pdfLogger = OFLog::getLogger("dcmtk.apps." OFFIS_CONSOLE_APPLICATION); + +static char rcsid[] = "$dcmtk: " OFFIS_CONSOLE_APPLICATION " v" + OFFIS_DCMTK_VERSION " " OFFIS_DCMTK_RELEASEDATE " $"; + +#define FILENAME_PLACEHOLDER "#f" + +static OFString replaceChars(const OFString &srcstr, const OFString &pattern, const OFString &substitute) + /* + * This function replaces all occurrences of pattern in srcstr with substitute and returns + * the result as a new OFString variable. Note that srcstr itself will not be changed. + * + * Parameters: + * srcstr - [in] The source string. + * pattern - [in] The pattern string which shall be substituted. + * substitute - [in] The substitute for pattern in srcstr. + */ +{ + OFString result = srcstr; + size_t pos = 0; + + while (pos != OFString_npos) + { + pos = result.find(pattern, pos); + + if (pos != OFString_npos) + { + result.replace(pos, pattern.size(), substitute); + pos += substitute.size(); + } + } + + return result; +} + + +#define SHORTCOL 3 +#define LONGCOL 20 + +int main(int argc, char *argv[]) +{ + const char *opt_ifname = NULL; + const char *opt_ofname = NULL; + const char *opt_execString = NULL; + E_FileReadMode opt_readMode = ERM_autoDetect; + E_TransferSyntax opt_ixfer = EXS_Unknown; + + OFConsoleApplication app(OFFIS_CONSOLE_APPLICATION, "Extract PDF file from DICOM encapsulated PDF", rcsid); + OFCommandLine cmd; + cmd.setOptionColumns(LONGCOL, SHORTCOL); + cmd.setParamColumn(LONGCOL + SHORTCOL + 4); + + cmd.addParam("dcmfile-in", "DICOM input filename"); + cmd.addParam("pdffile-out", "PDF output filename"); + + cmd.addGroup("general options:", LONGCOL, SHORTCOL + 2); + cmd.addOption("--help", "-h", "print this help text and exit", OFCommandLine::AF_Exclusive); + cmd.addOption("--version", "print version information and exit", OFCommandLine::AF_Exclusive); + OFLog::addOptions(cmd); + + cmd.addGroup("input options:"); + cmd.addSubGroup("input file format:"); + cmd.addOption("--read-file", "+f", "read file format or data set (default)"); + cmd.addOption("--read-file-only", "+fo", "read file format only"); + cmd.addOption("--read-dataset", "-f", "read data set without file meta information"); + cmd.addSubGroup("input transfer syntax:", LONGCOL, SHORTCOL); + cmd.addOption("--read-xfer-auto", "-t=", "use TS recognition (default)"); + cmd.addOption("--read-xfer-detect", "-td", "ignore TS specified in the file meta header"); + cmd.addOption("--read-xfer-little", "-te", "read with explicit VR little endian TS"); + cmd.addOption("--read-xfer-big", "-tb", "read with explicit VR big endian TS"); + cmd.addOption("--read-xfer-implicit", "-ti", "read with implicit VR little endian TS"); + cmd.addSubGroup("parsing of odd-length attributes:"); + cmd.addOption("--accept-odd-length", "+ao", "accept odd length attributes (default)"); + cmd.addOption("--assume-even-length", "+ae", "assume real length is one byte larger"); + cmd.addSubGroup("handling of undefined length UN elements:"); + cmd.addOption("--enable-cp246", "+ui", "read undefined len UN as implicit VR (default)"); + cmd.addOption("--disable-cp246", "-ui", "read undefined len UN as explicit VR"); + cmd.addSubGroup("handling of defined length UN elements:"); + cmd.addOption("--retain-un", "-uc", "retain elements as UN (default)"); + cmd.addOption("--convert-un", "+uc", "convert to real VR if known"); + cmd.addSubGroup("automatic data correction:"); + cmd.addOption("--enable-correction", "+dc", "enable automatic data correction (default)"); + cmd.addOption("--disable-correction", "-dc", "disable automatic data correction"); +#ifdef WITH_ZLIB + cmd.addSubGroup("bitstream format of deflated input:"); + cmd.addOption("--bitstream-deflated", "+bd", "expect deflated bitstream (default)"); + cmd.addOption("--bitstream-zlib", "+bz", "expect deflated zlib bitstream"); +#endif + + cmd.addGroup("execution options:", LONGCOL, SHORTCOL + 2); + cmd.addOption("--exec", "-x", 1, "[c]ommand: string", + "execute command c after PDF extraction"); + /* evaluate command line */ + prepareCmdLineArgs(argc, argv, OFFIS_CONSOLE_APPLICATION); + if (app.parseCommandLine(cmd, argc, argv)) + { + /* check exclusive options first */ + if (cmd.hasExclusiveOption()) + { + if (cmd.findOption("--version")) + { + app.printHeader(OFTrue /*print host identifier*/); + COUT << OFendl << "External libraries used:"; +#ifdef WITH_ZLIB + COUT << OFendl << "- ZLIB, Version " << zlibVersion() << OFendl; +#else + COUT << " none" << OFendl; +#endif + return 0; + } + } + + /* command line parameters and options */ + cmd.getParam(1, opt_ifname); + cmd.getParam(2, opt_ofname); + + OFLog::configureFromCommandLine(cmd, app); + + cmd.beginOptionBlock(); + if (cmd.findOption("--read-file")) opt_readMode = ERM_autoDetect; + if (cmd.findOption("--read-file-only")) opt_readMode = ERM_fileOnly; + if (cmd.findOption("--read-dataset")) opt_readMode = ERM_dataset; + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--read-xfer-auto")) + opt_ixfer = EXS_Unknown; + if (cmd.findOption("--read-xfer-detect")) + dcmAutoDetectDatasetXfer.set(OFTrue); + if (cmd.findOption("--read-xfer-little")) + { + app.checkDependence("--read-xfer-little", "--read-dataset", opt_readMode == ERM_dataset); + opt_ixfer = EXS_LittleEndianExplicit; + } + if (cmd.findOption("--read-xfer-big")) + { + app.checkDependence("--read-xfer-big", "--read-dataset", opt_readMode == ERM_dataset); + opt_ixfer = EXS_BigEndianExplicit; + } + if (cmd.findOption("--read-xfer-implicit")) + { + app.checkDependence("--read-xfer-implicit", "--read-dataset", opt_readMode == ERM_dataset); + opt_ixfer = EXS_LittleEndianImplicit; + } + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--accept-odd-length")) + { + dcmAcceptOddAttributeLength.set(OFTrue); + } + if (cmd.findOption("--assume-even-length")) + { + dcmAcceptOddAttributeLength.set(OFFalse); + } + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--enable-cp246")) + { + dcmEnableCP246Support.set(OFTrue); + } + if (cmd.findOption("--disable-cp246")) + { + dcmEnableCP246Support.set(OFFalse); + } + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--retain-un")) + { + dcmEnableUnknownVRConversion.set(OFFalse); + } + if (cmd.findOption("--convert-un")) + { + dcmEnableUnknownVRConversion.set(OFTrue); + } + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--enable-correction")) + { + dcmEnableAutomaticInputDataCorrection.set(OFTrue); + } + if (cmd.findOption("--disable-correction")) + { + dcmEnableAutomaticInputDataCorrection.set(OFFalse); + } + cmd.endOptionBlock(); + +#ifdef WITH_ZLIB + cmd.beginOptionBlock(); + if (cmd.findOption("--bitstream-deflated")) + { + dcmZlibExpectRFC1950Encoding.set(OFFalse); + } + if (cmd.findOption("--bitstream-zlib")) + { + dcmZlibExpectRFC1950Encoding.set(OFTrue); + } + cmd.endOptionBlock(); +#endif + + if (cmd.findOption("--exec")) app.checkValue(cmd.getValue(opt_execString)); + } + + /* print resource identifier */ + OFLOG_DEBUG(dcm2pdfLogger, rcsid << OFendl); + + /* make sure data dictionary is loaded */ + if (!dcmDataDict.isDictionaryLoaded()) + { + OFLOG_WARN(dcm2pdfLogger, "no data dictionary loaded, check environment variable: " + << DCM_DICT_ENVIRONMENT_VARIABLE); + } + + // open inputfile + if ((opt_ifname == NULL) || (strlen(opt_ifname) == 0)) + { + OFLOG_FATAL(dcm2pdfLogger, "invalid filename: "); + return 1; + } + + DcmFileFormat fileformat; + DcmDataset * dataset = fileformat.getDataset(); + + OFLOG_INFO(dcm2pdfLogger, "open input file " << opt_ifname); + + OFCondition error = fileformat.loadFile(opt_ifname, opt_ixfer, EGL_noChange, DCM_MaxReadLength, opt_readMode); + + if (error.bad()) + { + OFLOG_FATAL(dcm2pdfLogger, error.text() << ": reading file: " << opt_ifname); + return 1; + } + + OFString sopClass; + error = dataset->findAndGetOFString(DCM_SOPClassUID, sopClass); + if (error.bad() || sopClass != UID_EncapsulatedPDFStorage) + { + OFLOG_FATAL(dcm2pdfLogger, "not an Encapsulated PDF Storage object: " << opt_ifname); + return 1; + } + + DcmElement *delem = NULL; + error = dataset->findAndGetElement(DCM_EncapsulatedDocument, delem); + if (error.bad() || delem == NULL) + { + OFLOG_FATAL(dcm2pdfLogger, "attribute (0042,0011) Encapsulated Document missing."); + return 1; + } + + Uint32 len = delem->getLength(); + Uint8 *pdfDocument = NULL; + error = delem->getUint8Array(pdfDocument); + if (error.bad() || pdfDocument == NULL || len == 0) + { + OFLOG_FATAL(dcm2pdfLogger, "attribute (0042,0011) Encapsulated Document empty or wrong VR."); + return 1; + } + + /* strip pad byte at end of file, if there is one. The PDF format expects + * files to end with %%EOF followed by CR/LF. If the last character of the + * file is not a CR or LF, we assume it is a pad byte and remove it. + */ + if (pdfDocument[len-1] != 10 && pdfDocument[len-1] != 13) + { + --len; + } + + FILE *pdffile = fopen(opt_ofname, "wb"); + if (pdffile == NULL) + { + OFLOG_FATAL(dcm2pdfLogger, "unable to create file " << opt_ofname); + return 1; + } + + if (len != fwrite(pdfDocument, 1, len, pdffile)) + { + OFLOG_FATAL(dcm2pdfLogger, "write error in file " << opt_ofname); + fclose(pdffile); + return 1; + } + + fclose(pdffile); + + OFLOG_INFO(dcm2pdfLogger, "conversion successful"); + + if (opt_execString) + { + OFString cmdStr = opt_execString; + cmdStr = replaceChars(cmdStr, OFString(FILENAME_PLACEHOLDER), opt_ofname); + + // Execute command and return result + return system(cmdStr.c_str()); + } + + return 0; +} diff --git a/dcmdata/apps/dcm2xml.cc b/dcmdata/apps/dcm2xml.cc new file mode 100644 index 00000000..171e254d --- /dev/null +++ b/dcmdata/apps/dcm2xml.cc @@ -0,0 +1,572 @@ +/* + * + * Copyright (C) 2002-2015, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Joerg Riesmeier + * + * Purpose: Convert the contents of a DICOM file to XML format + * + */ + + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/dcmdata/dctk.h" +#include "dcmtk/dcmdata/cmdlnarg.h" +#include "dcmtk/ofstd/ofstd.h" +#include "dcmtk/ofstd/ofstream.h" +#include "dcmtk/ofstd/ofconapp.h" + +#ifdef WITH_ZLIB +#include /* for zlibVersion() */ +#endif +#ifdef WITH_LIBICONV +#include "dcmtk/ofstd/ofchrenc.h" /* for OFCharacterEncoding */ +#endif + +#define OFFIS_CONSOLE_APPLICATION "dcm2xml" +#define OFFIS_CONSOLE_DESCRIPTION "Convert DICOM file and data set to XML" + +#define DOCUMENT_TYPE_DEFINITION_FILE "dcm2xml.dtd" + +static OFLogger dcm2xmlLogger = OFLog::getLogger("dcmtk.apps." OFFIS_CONSOLE_APPLICATION); + +static char rcsid[] = "$dcmtk: " OFFIS_CONSOLE_APPLICATION " v" + OFFIS_DCMTK_VERSION " " OFFIS_DCMTK_RELEASEDATE " $"; + +// ******************************************** + +static OFCondition writeFile(STD_NAMESPACE ostream &out, + const char *ifname, + DcmFileFormat *dfile, + const E_FileReadMode readMode, + const OFBool loadIntoMemory, + const char *dtdFilename, + const char *defaultCharset, + /*const*/ size_t writeFlags, + const OFBool checkAllStrings) +{ + OFCondition result = EC_IllegalParameter; + if ((ifname != NULL) && (dfile != NULL)) + { + DcmDataset *dset = dfile->getDataset(); + if (loadIntoMemory) + dset->loadAllDataIntoMemory(); + /* determine dataset character encoding */ + OFString encString; + OFString csetString; + if (dset->findAndGetOFStringArray(DCM_SpecificCharacterSet, csetString).good()) + { + if (csetString == "ISO_IR 6") // should never be present in a dataset, but ... + encString = "UTF-8"; + else if (csetString == "ISO_IR 192") + encString = "UTF-8"; + else if (csetString == "ISO_IR 100") + encString = "ISO-8859-1"; + else if (csetString == "ISO_IR 101") + encString = "ISO-8859-2"; + else if (csetString == "ISO_IR 109") + encString = "ISO-8859-3"; + else if (csetString == "ISO_IR 110") + encString = "ISO-8859-4"; + else if (csetString == "ISO_IR 148") + encString = "ISO-8859-9"; + else if (csetString == "ISO_IR 144") + encString = "ISO-8859-5"; + else if (csetString == "ISO_IR 127") + encString = "ISO-8859-6"; + else if (csetString == "ISO_IR 126") + encString = "ISO-8859-7"; + else if (csetString == "ISO_IR 138") + encString = "ISO-8859-8"; + else { + if (!csetString.empty()) + { + OFLOG_WARN(dcm2xmlLogger, OFFIS_CONSOLE_APPLICATION << ": SpecificCharacterSet (0008,0005) " + << "value '" << csetString << "' not supported ... quoting non-ASCII characters"); +#ifdef WITH_LIBICONV + OFLOG_DEBUG(dcm2xmlLogger, "using option --convert-to-utf8 to convert the DICOM file to " + "UTF-8 encoding might also help to solve this problem more appropriately"); +#endif + } + /* make sure that non-ASCII characters are quoted appropriately */ + writeFlags |= DCMTypes::XF_convertNonASCII; + } + } else { + /* SpecificCharacterSet is not present in the dataset */ + if (dset->containsExtendedCharacters(checkAllStrings)) + { + if (defaultCharset == NULL) + { + /* the dataset contains non-ASCII characters that really should not be there */ + OFLOG_ERROR(dcm2xmlLogger, OFFIS_CONSOLE_APPLICATION << ": SpecificCharacterSet (0008,0005) " + << "element absent (on the main dataset level) but extended characters used in file: " << ifname); + OFLOG_DEBUG(dcm2xmlLogger, "use option --charset-assume to manually specify an appropriate character set"); + return EC_IllegalCall; + } else { + OFString sopClass; + csetString = defaultCharset; + /* use the default character set specified by the user */ + if (csetString == "ISO_IR 192") + encString = "UTF-8"; + else if (csetString == "ISO_IR 100") + encString = "ISO-8859-1"; + else if (csetString == "ISO_IR 101") + encString = "ISO-8859-2"; + else if (csetString == "ISO_IR 109") + encString = "ISO-8859-3"; + else if (csetString == "ISO_IR 110") + encString = "ISO-8859-4"; + else if (csetString == "ISO_IR 148") + encString = "ISO-8859-9"; + else if (csetString == "ISO_IR 144") + encString = "ISO-8859-5"; + else if (csetString == "ISO_IR 127") + encString = "ISO-8859-6"; + else if (csetString == "ISO_IR 126") + encString = "ISO-8859-7"; + else if (csetString == "ISO_IR 138") + encString = "ISO-8859-8"; + else { + OFLOG_FATAL(dcm2xmlLogger, OFFIS_CONSOLE_APPLICATION << ": Character set '" + << defaultCharset << "' specified with option --charset-assume not supported"); + return EC_IllegalCall; + } + /* check whether this file is a DICOMDIR */ + if (dfile->getMetaInfo()->findAndGetOFString(DCM_MediaStorageSOPClassUID, sopClass).bad() || + (sopClass != UID_MediaStorageDirectoryStorage)) + { + OFLOG_INFO(dcm2xmlLogger, "inserting SpecificCharacterSet (0008,0005) element with value '" + << defaultCharset << "'"); + /* insert the SpecificCharacterSet (0008,0005) element */ + dset->putAndInsertString(DCM_SpecificCharacterSet, defaultCharset); + } + } + } else { + if (defaultCharset != NULL) + { + /* use "debug" instead of "warn" in order to avoid too much output in default mode */ + OFLOG_DEBUG(dcm2xmlLogger, "ignoring character set '" << defaultCharset + << "' specified with option --charset-assume since it is not needed for this dataset"); + } + /* by default, we use UTF-8 encoding */ + encString = "UTF-8"; + } + } + + /* write XML document header */ + out << "" << OFendl; + /* add document type definition (DTD) */ + if (writeFlags & DCMTypes::XF_addDocumentType) + { + out << "" << OFendl; + } + /* write XML document content */ + if (readMode == ERM_dataset) + result = dset->writeXML(out, writeFlags); + else + result = dfile->writeXML(out, writeFlags); + } + return result; +} + + +#define SHORTCOL 4 +#define LONGCOL 20 + + +int main(int argc, char *argv[]) +{ + size_t opt_writeFlags = 0; + OFBool opt_loadIntoMemory = OFFalse; + OFBool opt_checkAllStrings = OFFalse; +#ifdef WITH_LIBICONV + OFBool opt_convertToUTF8 = OFFalse; +#endif + const char *opt_defaultCharset = NULL; + E_FileReadMode opt_readMode = ERM_autoDetect; + E_TransferSyntax opt_ixfer = EXS_Unknown; + OFCmdUnsignedInt opt_maxReadLength = 4096; // default is 4 KB + const char *opt_dtdFilename = DEFAULT_SUPPORT_DATA_DIR DOCUMENT_TYPE_DEFINITION_FILE; + OFString optStr; + + OFConsoleApplication app(OFFIS_CONSOLE_APPLICATION, OFFIS_CONSOLE_DESCRIPTION, rcsid); + OFCommandLine cmd; + cmd.setOptionColumns(LONGCOL, SHORTCOL); + cmd.setParamColumn(LONGCOL + SHORTCOL + 4); + + cmd.addParam("dcmfile-in", "DICOM input filename to be converted", OFCmdParam::PM_Mandatory); + cmd.addParam("xmlfile-out", "XML output filename (default: stdout)", OFCmdParam::PM_Optional); + + cmd.addGroup("general options:", LONGCOL, SHORTCOL + 2); + cmd.addOption("--help", "-h", "print this help text and exit", OFCommandLine::AF_Exclusive); + cmd.addOption("--version", "print version information and exit", OFCommandLine::AF_Exclusive); + OFLog::addOptions(cmd); + + cmd.addGroup("input options:"); + cmd.addSubGroup("input file format:"); + cmd.addOption("--read-file", "+f", "read file format or data set (default)"); + cmd.addOption("--read-file-only", "+fo", "read file format only"); + cmd.addOption("--read-dataset", "-f", "read data set without file meta information"); + cmd.addSubGroup("input transfer syntax:"); + cmd.addOption("--read-xfer-auto", "-t=", "use TS recognition (default)"); + cmd.addOption("--read-xfer-detect", "-td", "ignore TS specified in the file meta header"); + cmd.addOption("--read-xfer-little", "-te", "read with explicit VR little endian TS"); + cmd.addOption("--read-xfer-big", "-tb", "read with explicit VR big endian TS"); + cmd.addOption("--read-xfer-implicit", "-ti", "read with implicit VR little endian TS"); + cmd.addSubGroup("long tag values:"); + cmd.addOption("--load-all", "+M", "load very long tag values (e.g. pixel data)"); + cmd.addOption("--load-short", "-M", "do not load very long values (default)"); + cmd.addOption("--max-read-length", "+R", 1, "[k]bytes: integer (4..4194302, default: 4)", + "set threshold for long values to k kbytes"); + cmd.addGroup("processing options:"); + cmd.addSubGroup("specific character set:"); + cmd.addOption("--charset-require", "+Cr", "require declaration of extended charset (def.)"); + cmd.addOption("--charset-assume", "+Ca", 1, "[c]harset: string", + "assume charset c if no extended charset declared"); + cmd.addOption("--charset-check-all", "+Cc", "check all data elements with string values\n(default: only PN, LO, LT, SH, ST and UT)"); +#ifdef WITH_LIBICONV + cmd.addOption("--convert-to-utf8", "+U8", "convert all element values that are affected\nby Specific Character Set (0008,0005) to UTF-8"); +#endif + cmd.addGroup("output options:"); + cmd.addSubGroup("general XML format:"); + cmd.addOption("--dcmtk-format", "-dtk", "output in DCMTK-specific format (default)"); + cmd.addOption("--native-format", "-nat", "output in Native DICOM Model format (part 19)"); + cmd.addOption("--use-xml-namespace", "+Xn", "add XML namespace declaration to root element"); + cmd.addSubGroup("DCMTK-specific format (not with --native-format):"); + cmd.addOption("--add-dtd-reference", "+Xd", "add reference to document type definition (DTD)"); + cmd.addOption("--embed-dtd-content", "+Xe", "embed document type definition into XML document"); + optStr = "use specified DTD file (only with +Xe)\n(default: "; + optStr += opt_dtdFilename; + optStr += ")"; + cmd.addOption("--use-dtd-file", "+Xf", 1, "[f]ilename: string", + optStr.c_str()); + cmd.addOption("--write-element-name", "+Wn", "write name of the DICOM data elements (default)"); + cmd.addOption("--no-element-name", "-Wn", "do not write name of the DICOM data elements"); + cmd.addOption("--write-binary-data", "+Wb", "write binary data of OB and OW elements\n(default: off, be careful with --load-all)"); + cmd.addSubGroup("encoding of binary data:"); + cmd.addOption("--encode-hex", "+Eh", "encode binary data as hex numbers\n(default for DCMTK-specific format)"); + cmd.addOption("--encode-uuid", "+Eu", "encode binary data as a UUID reference\n(default for Native DICOM Model)"); + cmd.addOption("--encode-base64", "+Eb", "encode binary data as Base64 (RFC 2045, MIME)"); + + /* evaluate command line */ + prepareCmdLineArgs(argc, argv, OFFIS_CONSOLE_APPLICATION); + if (app.parseCommandLine(cmd, argc, argv)) + { + /* check exclusive options first */ + if (cmd.hasExclusiveOption()) + { + if (cmd.findOption("--version")) + { + app.printHeader(OFTrue /*print host identifier*/); + COUT << OFendl << "External libraries used:"; +#if !defined(WITH_ZLIB) && !defined(WITH_LIBICONV) + COUT << " none" << OFendl; +#else + COUT << OFendl; +#endif +#ifdef WITH_ZLIB + COUT << "- ZLIB, Version " << zlibVersion() << OFendl; +#endif +#ifdef WITH_LIBICONV + COUT << "- " << OFCharacterEncoding::getLibraryVersionString() << OFendl; +#endif + return 0; + } + } + + /* general options */ + OFLog::configureFromCommandLine(cmd, app); + + /* input options */ + cmd.beginOptionBlock(); + if (cmd.findOption("--read-file")) opt_readMode = ERM_autoDetect; + if (cmd.findOption("--read-file-only")) opt_readMode = ERM_fileOnly; + if (cmd.findOption("--read-dataset")) opt_readMode = ERM_dataset; + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--read-xfer-auto")) + opt_ixfer = EXS_Unknown; + if (cmd.findOption("--read-xfer-detect")) + dcmAutoDetectDatasetXfer.set(OFTrue); + if (cmd.findOption("--read-xfer-little")) + { + app.checkDependence("--read-xfer-little", "--read-dataset", opt_readMode == ERM_dataset); + opt_ixfer = EXS_LittleEndianExplicit; + } + if (cmd.findOption("--read-xfer-big")) + { + app.checkDependence("--read-xfer-big", "--read-dataset", opt_readMode == ERM_dataset); + opt_ixfer = EXS_BigEndianExplicit; + } + if (cmd.findOption("--read-xfer-implicit")) + { + app.checkDependence("--read-xfer-implicit", "--read-dataset", opt_readMode == ERM_dataset); + opt_ixfer = EXS_LittleEndianImplicit; + } + cmd.endOptionBlock(); + + if (cmd.findOption("--max-read-length")) + { + app.checkValue(cmd.getValueAndCheckMinMax(opt_maxReadLength, 4, 4194302)); + opt_maxReadLength *= 1024; // convert kbytes to bytes + } + cmd.beginOptionBlock(); + if (cmd.findOption("--load-all")) + opt_loadIntoMemory = OFTrue; + if (cmd.findOption("--load-short")) + opt_loadIntoMemory = OFFalse; + cmd.endOptionBlock(); + + /* processing options */ + cmd.beginOptionBlock(); + if (cmd.findOption("--charset-require")) + opt_defaultCharset = NULL; + if (cmd.findOption("--charset-assume")) + app.checkValue(cmd.getValue(opt_defaultCharset)); + cmd.endOptionBlock(); + if (cmd.findOption("--charset-check-all")) + opt_checkAllStrings = OFTrue; +#ifdef WITH_LIBICONV + if (cmd.findOption("--convert-to-utf8")) + opt_convertToUTF8 = OFTrue; +#endif + + /* output options */ + cmd.beginOptionBlock(); + if (cmd.findOption("--native-format")) + opt_writeFlags |= DCMTypes::XF_useNativeModel; + if (cmd.findOption("--dcmtk-format")) + opt_writeFlags &= ~DCMTypes::XF_useNativeModel; + cmd.endOptionBlock(); + + if (cmd.findOption("--use-xml-namespace")) + opt_writeFlags |= DCMTypes::XF_useXMLNamespace; + + cmd.beginOptionBlock(); + if (cmd.findOption("--add-dtd-reference")) + { + app.checkConflict("--add-dtd-reference", "--native-format", (opt_writeFlags & DCMTypes::XF_useNativeModel) > 0); + opt_writeFlags |= DCMTypes::XF_addDocumentType; + } + if (cmd.findOption("--embed-dtd-content")) + { + app.checkConflict("--embed-dtd-content", "--native-format", (opt_writeFlags & DCMTypes::XF_useNativeModel) > 0); + opt_writeFlags |= DCMTypes::XF_addDocumentType | DCMTypes::XF_embedDocumentType; + } + cmd.endOptionBlock(); + + if (cmd.findOption("--use-dtd-file")) + { + app.checkConflict("--use-dtd-file", "--native-format", (opt_writeFlags & DCMTypes::XF_useNativeModel) > 0); + app.checkDependence("--use-dtd-file", "--embed-dtd-content", (opt_writeFlags & DCMTypes::XF_embedDocumentType) > 0); + app.checkValue(cmd.getValue(opt_dtdFilename)); + } + + cmd.beginOptionBlock(); + if (cmd.findOption("--write-element-name")) + { + app.checkConflict("--write-element-name", "--native-format", (opt_writeFlags & DCMTypes::XF_useNativeModel) > 0); + opt_writeFlags &= ~DCMTypes::XF_omitDataElementName; + } + if (cmd.findOption("--no-element-name")) + { + app.checkConflict("--no-element-name", "--native-format", (opt_writeFlags & DCMTypes::XF_useNativeModel) > 0); + opt_writeFlags |= DCMTypes::XF_omitDataElementName; + } + cmd.endOptionBlock(); + + if (cmd.findOption("--write-binary-data")) + { + app.checkConflict("--write-binary-data", "--native-format", (opt_writeFlags & DCMTypes::XF_useNativeModel) > 0); + opt_writeFlags |= DCMTypes::XF_writeBinaryData; + } + + cmd.beginOptionBlock(); + if (cmd.findOption("--encode-hex")) + { + app.checkConflict("--encode-hex", "--native-format", (opt_writeFlags & DCMTypes::XF_useNativeModel) > 0); + app.checkDependence("--encode-hex", "--write-binary-data", (opt_writeFlags & DCMTypes::XF_writeBinaryData) > 0); + opt_writeFlags &= ~DCMTypes::XF_encodeBase64; + } + if (cmd.findOption("--encode-uuid")) + { + app.checkDependence("--encode-uuid", "--native-format", (opt_writeFlags & DCMTypes::XF_useNativeModel) > 0); + opt_writeFlags &= ~DCMTypes::XF_encodeBase64; + } + if (cmd.findOption("--encode-base64")) + { + if (!(opt_writeFlags & DCMTypes::XF_useNativeModel)) + app.checkDependence("--encode-base64", "--write-binary-data", (opt_writeFlags & DCMTypes::XF_writeBinaryData) > 0); + opt_writeFlags |= DCMTypes::XF_encodeBase64; + } + cmd.endOptionBlock(); + } + + /* print resource identifier */ + OFLOG_DEBUG(dcm2xmlLogger, rcsid << OFendl); + + /* make sure data dictionary is loaded */ + if (!dcmDataDict.isDictionaryLoaded()) + { + OFLOG_WARN(dcm2xmlLogger, "no data dictionary loaded, check environment variable: " + << DCM_DICT_ENVIRONMENT_VARIABLE); + } + + /* make sure document type definition file exists */ + if ((opt_writeFlags & DCMTypes::XF_embedDocumentType) && !OFStandard::fileExists(opt_dtdFilename)) + { + OFLOG_WARN(dcm2xmlLogger, OFFIS_CONSOLE_APPLICATION << ": DTD file \"" << opt_dtdFilename + << "\" does not exist ... adding reference instead"); + opt_writeFlags &= ~DCMTypes::XF_embedDocumentType; + } + + int result = 0; + /* first parameter is treated as the input filename */ + const char *ifname = NULL; + cmd.getParam(1, ifname); + /* check input file */ + if ((ifname != NULL) && (strlen(ifname) > 0)) + { + /* read DICOM file or data set */ + DcmFileFormat dfile; + OFCondition status = dfile.loadFile(ifname, opt_ixfer, EGL_noChange, OFstatic_cast(Uint32, opt_maxReadLength), opt_readMode); + if (status.good()) + { + // map "old" charset names to DICOM defined terms + if (opt_defaultCharset != NULL) + { + OFString charset(opt_defaultCharset); + if (charset == "latin-1") + opt_defaultCharset = "ISO_IR 100"; + else if (charset == "latin-2") + opt_defaultCharset = "ISO_IR 101"; + else if (charset == "latin-3") + opt_defaultCharset = "ISO_IR 109"; + else if (charset == "latin-4") + opt_defaultCharset = "ISO_IR 110"; + else if (charset == "latin-5") + opt_defaultCharset = "ISO_IR 148"; + else if (charset == "cyrillic") + opt_defaultCharset = "ISO_IR 144"; + else if (charset == "arabic") + opt_defaultCharset = "ISO_IR 127"; + else if (charset == "greek") + opt_defaultCharset = "ISO_IR 126"; + else if (charset == "hebrew") + opt_defaultCharset = "ISO_IR 138"; + } +#ifdef WITH_LIBICONV + DcmDataset *dset = dfile.getDataset(); + /* convert all DICOM strings to UTF-8 (if requested) */ + if (opt_convertToUTF8) + { + OFLOG_INFO(dcm2xmlLogger, "converting all element values that are affected by SpecificCharacterSet (0008,0005) to UTF-8"); + // check whether SpecificCharacterSet is absent but needed + if ((opt_defaultCharset != NULL) && !dset->tagExistsWithValue(DCM_SpecificCharacterSet) && + dset->containsExtendedCharacters(OFFalse /*checkAllStrings*/)) + { + // use the manually specified source character set + status = dset->convertCharacterSet(opt_defaultCharset, OFString("ISO_IR 192")); + } else { + // expect that SpecificCharacterSet contains the correct value + status = dset->convertToUTF8(); + } + if (status.bad()) + { + OFLOG_FATAL(dcm2xmlLogger, status.text() << ": converting file to UTF-8: " << ifname); + result = 4; + } + } else { + OFString sopClass; + /* check whether the file is a DICOMDIR ... */ + if (dfile.getMetaInfo()->findAndGetOFString(DCM_MediaStorageSOPClassUID, sopClass).good() && + (sopClass == UID_MediaStorageDirectoryStorage)) + { + /* ... with one or more SpecificCharacterSet elements */ + if (dset->tagExistsWithValue(DCM_SpecificCharacterSet, OFTrue /*searchIntoSub*/)) + { + OFLOG_WARN(dcm2xmlLogger, OFFIS_CONSOLE_APPLICATION << ": this is a DICOMDIR file, which can contain more than one " + << "SpecificCharacterSet (0008,0005) element ... using option --convert-to-utf8 is strongly recommended"); + } + } + } +#endif + if (result == 0) + { + /* if second parameter is present, it is treated as the output filename ("stdout" otherwise) */ + if (cmd.getParamCount() == 2) + { + const char *ofname = NULL; + cmd.getParam(2, ofname); + STD_NAMESPACE ofstream stream(ofname); + if (stream.good()) + { + /* write content in XML format to file */ + if (writeFile(stream, ifname, &dfile, opt_readMode, opt_loadIntoMemory, opt_dtdFilename, + opt_defaultCharset, opt_writeFlags, opt_checkAllStrings).bad()) + result = 2; + } else + result = 1; + } else { + /* write content in XML format to standard output */ + if (writeFile(COUT, ifname, &dfile, opt_readMode, opt_loadIntoMemory, opt_dtdFilename, + opt_defaultCharset, opt_writeFlags, opt_checkAllStrings).bad()) + result = 3; + } + } + } else { + OFLOG_ERROR(dcm2xmlLogger, OFFIS_CONSOLE_APPLICATION << ": error (" << status.text() << ") reading file: "<< ifname); + result = 5; + } + } else { + OFLOG_ERROR(dcm2xmlLogger, OFFIS_CONSOLE_APPLICATION << ": invalid filename: "); + result = 6; + } + + return result; +} diff --git a/dcmdata/apps/dcmconv.cc b/dcmdata/apps/dcmconv.cc new file mode 100644 index 00000000..73491092 --- /dev/null +++ b/dcmdata/apps/dcmconv.cc @@ -0,0 +1,604 @@ +/* + * + * Copyright (C) 1994-2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Andrew Hewett + * + * Purpose: Convert dicom file encoding + * + */ + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#define INCLUDE_CSTDLIB +#define INCLUDE_CSTDIO +#define INCLUDE_CSTRING +#include "dcmtk/ofstd/ofstdinc.h" + +#ifdef HAVE_GUSI_H +#include +#endif + +#include "dcmtk/dcmdata/dctk.h" +#include "dcmtk/dcmdata/cmdlnarg.h" +#include "dcmtk/ofstd/ofconapp.h" +#include "dcmtk/dcmdata/dcuid.h" /* for dcmtk version name */ +#include "dcmtk/dcmdata/dcostrmz.h" /* for dcmZlibCompressionLevel */ +#include "dcmtk/dcmdata/dcistrmz.h" /* for dcmZlibExpectRFC1950Encoding */ + +#ifdef WITH_ZLIB +#include /* for zlibVersion() */ +#endif +#ifdef WITH_LIBICONV +#include "dcmtk/ofstd/ofchrenc.h" /* for OFCharacterEncoding */ +#endif + +#define OFFIS_CONSOLE_APPLICATION "dcmconv" + +static OFLogger dcmconvLogger = OFLog::getLogger("dcmtk.apps." OFFIS_CONSOLE_APPLICATION); + +static char rcsid[] = "$dcmtk: " OFFIS_CONSOLE_APPLICATION " v" + OFFIS_DCMTK_VERSION " " OFFIS_DCMTK_RELEASEDATE " $"; + +// ******************************************** + + +#define SHORTCOL 3 +#define LONGCOL 21 + +static DcmTagKey parseTagKey(const char *tagName) +{ + unsigned int group = 0xffff; + unsigned int elem = 0xffff; + if (sscanf(tagName, "%x,%x", &group, &elem) != 2) + { + DcmTagKey tagKey; + /* it is a name */ + const DcmDataDictionary &globalDataDict = dcmDataDict.rdlock(); + const DcmDictEntry *dicent = globalDataDict.findEntry(tagName); + if (dicent == NULL) + { + OFLOG_ERROR(dcmconvLogger, "unrecognised tag name: '" << tagName << "'"); + tagKey = DCM_UndefinedTagKey; + } else { + tagKey = dicent->getKey(); + } + dcmDataDict.unlock(); + return tagKey; + } else /* tag name has format "gggg,eeee" */ + { + return DcmTagKey(OFstatic_cast(Uint16, group),OFstatic_cast(Uint16, elem)); + } +} + +int main(int argc, char *argv[]) +{ + +#ifdef HAVE_GUSI_H + GUSISetup(GUSIwithSIOUXSockets); + GUSISetup(GUSIwithInternetSockets); +#endif + + const char *opt_ifname = NULL; + const char *opt_ofname = NULL; + + E_FileReadMode opt_readMode = ERM_autoDetect; + E_FileWriteMode opt_writeMode = EWM_fileformat; + E_TransferSyntax opt_ixfer = EXS_Unknown; + E_TransferSyntax opt_oxfer = EXS_Unknown; + E_GrpLenEncoding opt_oglenc = EGL_recalcGL; + E_EncodingType opt_oenctype = EET_ExplicitLength; + E_PaddingEncoding opt_opadenc = EPD_noChange; + OFCmdUnsignedInt opt_filepad = 0; + OFCmdUnsignedInt opt_itempad = 0; +#ifdef WITH_ZLIB + OFCmdUnsignedInt opt_compressionLevel = 0; +#endif +#ifdef WITH_LIBICONV + const char *opt_convertToCharset = NULL; + OFBool opt_transliterate = OFFalse; + OFBool opt_discardIllegal = OFFalse; +#endif + OFBool opt_noInvalidGroups = OFFalse; + + OFConsoleApplication app(OFFIS_CONSOLE_APPLICATION , "Convert DICOM file encoding", rcsid); + OFCommandLine cmd; + cmd.setOptionColumns(LONGCOL, SHORTCOL); + cmd.setParamColumn(LONGCOL + SHORTCOL + 4); + + cmd.addParam("dcmfile-in", "DICOM input filename to be converted"); + cmd.addParam("dcmfile-out", "DICOM output filename"); + + cmd.addGroup("general options:", LONGCOL, SHORTCOL + 2); + cmd.addOption("--help", "-h", "print this help text and exit", OFCommandLine::AF_Exclusive); + cmd.addOption("--version", "print version information and exit", OFCommandLine::AF_Exclusive); + OFLog::addOptions(cmd); + + cmd.addGroup("input options:"); + cmd.addSubGroup("input file format:"); + cmd.addOption("--read-file", "+f", "read file format or data set (default)"); + cmd.addOption("--read-file-only", "+fo", "read file format only"); + cmd.addOption("--read-dataset", "-f", "read data set without file meta information"); + cmd.addSubGroup("input transfer syntax:", LONGCOL, SHORTCOL); + cmd.addOption("--read-xfer-auto", "-t=", "use TS recognition (default)"); + cmd.addOption("--read-xfer-detect", "-td", "ignore TS specified in the file meta header"); + cmd.addOption("--read-xfer-little", "-te", "read with explicit VR little endian TS"); + cmd.addOption("--read-xfer-big", "-tb", "read with explicit VR big endian TS"); + cmd.addOption("--read-xfer-implicit", "-ti", "read with implicit VR little endian TS"); + cmd.addSubGroup("parsing of file meta information:"); + cmd.addOption("--use-meta-length", "+ml", "use file meta information group length (default)"); + cmd.addOption("--ignore-meta-length", "-ml", "ignore file meta information group length"); + cmd.addSubGroup("parsing of odd-length attributes:"); + cmd.addOption("--accept-odd-length", "+ao", "accept odd length attributes (default)"); + cmd.addOption("--assume-even-length", "+ae", "assume real length is one byte larger"); + cmd.addSubGroup("handling of explicit VR:"); + cmd.addOption("--use-explicit-vr", "+ev", "use explicit VR from dataset (default)"); + cmd.addOption("--ignore-explicit-vr", "-ev", "ignore explicit VR (prefer data dictionary)"); + cmd.addSubGroup("handling of non-standard VR:"); + cmd.addOption("--treat-as-unknown", "+vr", "treat non-standard VR as unknown (default)"); + cmd.addOption("--assume-implicit", "-vr", "try to read with implicit VR little endian TS"); + cmd.addSubGroup("handling of undefined length UN elements:"); + cmd.addOption("--enable-cp246", "+ui", "read undefined len UN as implicit VR (default)"); + cmd.addOption("--disable-cp246", "-ui", "read undefined len UN as explicit VR"); + cmd.addSubGroup("handling of defined length UN elements:"); + cmd.addOption("--retain-un", "-uc", "retain elements as UN (default)"); + cmd.addOption("--convert-un", "+uc", "convert to real VR if known"); + cmd.addSubGroup("handling of private max-length elements (implicit VR):"); + cmd.addOption("--maxlength-dict", "-sq", "read as defined in dictionary (default)"); + cmd.addOption("--maxlength-seq", "+sq", "read as sequence with undefined length"); + cmd.addSubGroup("handling of wrong delimitation items:"); + cmd.addOption("--use-delim-items", "-rd", "use delimitation items from dataset (default)"); + cmd.addOption("--replace-wrong-delim", "+rd", "replace wrong sequence/item delimitation items"); + cmd.addSubGroup("general handling of parser errors: "); + cmd.addOption("--ignore-parse-errors", "+Ep", "try to recover from parse errors"); + cmd.addOption("--handle-parse-errors", "-Ep", "handle parse errors and stop parsing (default)"); + cmd.addSubGroup("other parsing options:"); + cmd.addOption("--stop-after-elem", "+st", 1, "[t]ag: \"gggg,eeee\" or dictionary name", + "stop parsing after element specified by t"); + cmd.addSubGroup("automatic data correction:"); + cmd.addOption("--enable-correction", "+dc", "enable automatic data correction (default)"); + cmd.addOption("--disable-correction", "-dc", "disable automatic data correction"); +#ifdef WITH_ZLIB + cmd.addSubGroup("bitstream format of deflated input:"); + cmd.addOption("--bitstream-deflated", "+bd", "expect deflated bitstream (default)"); + cmd.addOption("--bitstream-zlib", "+bz", "expect deflated zlib bitstream"); +#endif + + cmd.addGroup("processing options:"); +#ifdef WITH_LIBICONV + cmd.addSubGroup("specific character set:"); + cmd.addOption("--convert-to-utf8", "+U8", "convert all element values that are affected\nby Specific Character Set (0008,0005) to UTF-8"); + cmd.addOption("--convert-to-latin1", "+L1", "convert affected element values to ISO 8859-1"); + cmd.addOption("--convert-to-ascii", "+A7", "convert affected element values to 7-bit ASCII"); + cmd.addOption("--convert-to-charset", "+C", 1, "[c]harset: string", + "convert affected element values to the character\nset specified by the DICOM defined term c"); + cmd.addOption("--transliterate", "-Ct", "try to approximate characters that cannot be\nrepresented through similar looking characters"); + cmd.addOption("--discard-illegal", "-Cd", "discard characters that cannot be represented\nin destination character set"); +#endif + cmd.addSubGroup("other processing options:"); + cmd.addOption("--no-invalid-groups", "-ig", "remove elements with invalid group number"); + + cmd.addGroup("output options:"); + cmd.addSubGroup("output file format:"); + cmd.addOption("--write-file", "+F", "write file format (default)"); + cmd.addOption("--write-new-meta-info", "+Fm", "write file format with new meta information"); + cmd.addOption("--write-dataset", "-F", "write data set without file meta information"); + cmd.addSubGroup("output transfer syntax:"); + cmd.addOption("--write-xfer-same", "+t=", "write with same TS as input (default)"); + cmd.addOption("--write-xfer-little", "+te", "write with explicit VR little endian TS"); + cmd.addOption("--write-xfer-big", "+tb", "write with explicit VR big endian TS"); + cmd.addOption("--write-xfer-implicit", "+ti", "write with implicit VR little endian TS"); +#ifdef WITH_ZLIB + cmd.addOption("--write-xfer-deflated", "+td", "write with deflated explicit VR little endian TS"); +#endif + cmd.addSubGroup("post-1993 value representations:"); + cmd.addOption("--enable-new-vr", "+u", "enable support for new VRs (UN/UT) (default)"); + cmd.addOption("--disable-new-vr", "-u", "disable support for new VRs, convert to OB"); + cmd.addSubGroup("group length encoding:"); + cmd.addOption("--group-length-recalc", "+g=", "recalculate group lengths if present (default)"); + cmd.addOption("--group-length-create", "+g", "always write with group length elements"); + cmd.addOption("--group-length-remove", "-g", "always write without group length elements"); + cmd.addSubGroup("length encoding in sequences and items:"); + cmd.addOption("--length-explicit", "+e", "write with explicit lengths (default)"); + cmd.addOption("--length-undefined", "-e", "write with undefined lengths"); + cmd.addOption("--write-oversized", "+eo", "write oversized explicit length sequences\nand items with undefined length (default)"); + cmd.addOption("--abort-oversized", "-eo", "abort on oversized explicit sequences/items"); + cmd.addSubGroup("data set trailing padding (not with --write-dataset):"); + cmd.addOption("--padding-retain", "-p=", "do not change padding\n(default if not --write-dataset)"); + cmd.addOption("--padding-off", "-p", "no padding (implicit if --write-dataset)"); + cmd.addOption("--padding-create", "+p", 2, "[f]ile-pad [i]tem-pad: integer", + "align file on multiple of f bytes\nand items on multiple of i bytes"); +#ifdef WITH_ZLIB + cmd.addSubGroup("deflate compression level (only with --write-xfer-deflated):"); + cmd.addOption("--compression-level", "+cl", 1, "[l]evel: integer (default: 6)", + "0=uncompressed, 1=fastest, 9=best compression"); +#endif + + /* evaluate command line */ + prepareCmdLineArgs(argc, argv, OFFIS_CONSOLE_APPLICATION); + if (app.parseCommandLine(cmd, argc, argv)) + { + /* check exclusive options first */ + if (cmd.hasExclusiveOption()) + { + if (cmd.findOption("--version")) + { + app.printHeader(OFTrue /*print host identifier*/); + COUT << OFendl << "External libraries used:"; +#if !defined(WITH_ZLIB) && !defined(WITH_LIBICONV) + COUT << " none" << OFendl; +#else + COUT << OFendl; +#endif +#ifdef WITH_ZLIB + COUT << "- ZLIB, Version " << zlibVersion() << OFendl; +#endif +#ifdef WITH_LIBICONV + COUT << "- " << OFCharacterEncoding::getLibraryVersionString() << OFendl; +#endif + return 0; + } + } + + /* command line parameters */ + cmd.getParam(1, opt_ifname); + cmd.getParam(2, opt_ofname); + + /* general options */ + OFLog::configureFromCommandLine(cmd, app); + + /* input options */ + cmd.beginOptionBlock(); + if (cmd.findOption("--read-file")) opt_readMode = ERM_autoDetect; + if (cmd.findOption("--read-file-only")) opt_readMode = ERM_fileOnly; + if (cmd.findOption("--read-dataset")) opt_readMode = ERM_dataset; + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--read-xfer-auto")) + opt_ixfer = EXS_Unknown; + if (cmd.findOption("--read-xfer-detect")) + dcmAutoDetectDatasetXfer.set(OFTrue); + if (cmd.findOption("--read-xfer-little")) + { + app.checkDependence("--read-xfer-little", "--read-dataset", opt_readMode == ERM_dataset); + opt_ixfer = EXS_LittleEndianExplicit; + } + if (cmd.findOption("--read-xfer-big")) + { + app.checkDependence("--read-xfer-big", "--read-dataset", opt_readMode == ERM_dataset); + opt_ixfer = EXS_BigEndianExplicit; + } + if (cmd.findOption("--read-xfer-implicit")) + { + app.checkDependence("--read-xfer-implicit", "--read-dataset", opt_readMode == ERM_dataset); + opt_ixfer = EXS_LittleEndianImplicit; + } + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--use-meta-length")) + { + dcmIgnoreFileMetaInformationGroupLength.set(OFFalse); + } + if (cmd.findOption("--ignore-meta-length")) + { + dcmIgnoreFileMetaInformationGroupLength.set(OFTrue); + } + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--accept-odd-length")) + { + dcmAcceptOddAttributeLength.set(OFTrue); + } + if (cmd.findOption("--assume-even-length")) + { + dcmAcceptOddAttributeLength.set(OFFalse); + } + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--use-explicit-vr")) + { + dcmPreferVRFromDataDictionary.set(OFFalse); + } + if (cmd.findOption("--ignore-explicit-vr")) + { + dcmPreferVRFromDataDictionary.set(OFTrue); + } + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--treat-as-unknown")) + { + dcmAcceptUnexpectedImplicitEncoding.set(OFFalse); + } + if (cmd.findOption("--assume-implicit")) + { + dcmAcceptUnexpectedImplicitEncoding.set(OFTrue); + } + + cmd.beginOptionBlock(); + if (cmd.findOption("--enable-cp246")) + { + dcmEnableCP246Support.set(OFTrue); + } + if (cmd.findOption("--disable-cp246")) + { + dcmEnableCP246Support.set(OFFalse); + } + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--retain-un")) + { + dcmEnableUnknownVRConversion.set(OFFalse); + } + if (cmd.findOption("--convert-un")) + { + dcmEnableUnknownVRConversion.set(OFTrue); + } + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--maxlength-dict")) + { + dcmReadImplPrivAttribMaxLengthAsSQ.set(OFFalse); + } + if (cmd.findOption("--maxlength-seq")) + { + dcmReadImplPrivAttribMaxLengthAsSQ.set(OFTrue); + } + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--use-delim-items")) + { + dcmReplaceWrongDelimitationItem.set(OFFalse); + } + if (cmd.findOption("--replace-wrong-delim")) + { + dcmReplaceWrongDelimitationItem.set(OFTrue); + } + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--ignore-parse-errors")) + { + dcmIgnoreParsingErrors.set(OFTrue); + } + if (cmd.findOption("--handle-parse-errors")) + { + dcmIgnoreParsingErrors.set(OFFalse); + } + cmd.endOptionBlock(); + + if (cmd.findOption("--stop-after-elem")) + { + const char *tagName = NULL; + app.checkValue(cmd.getValue(tagName)); + DcmTagKey key = parseTagKey(tagName); + if (key != DCM_UndefinedTagKey) + dcmStopParsingAfterElement.set(key); + else + app.printError("no valid key given for option --stop-after-elem"); + } + + cmd.beginOptionBlock(); + if (cmd.findOption("--enable-correction")) + { + dcmEnableAutomaticInputDataCorrection.set(OFTrue); + } + if (cmd.findOption("--disable-correction")) + { + dcmEnableAutomaticInputDataCorrection.set(OFFalse); + } + cmd.endOptionBlock(); + +#ifdef WITH_ZLIB + cmd.beginOptionBlock(); + if (cmd.findOption("--bitstream-deflated")) + { + dcmZlibExpectRFC1950Encoding.set(OFFalse); + } + if (cmd.findOption("--bitstream-zlib")) + { + dcmZlibExpectRFC1950Encoding.set(OFTrue); + } + cmd.endOptionBlock(); +#endif + + /* processing options */ +#ifdef WITH_LIBICONV + cmd.beginOptionBlock(); + if (cmd.findOption("--convert-to-utf8")) opt_convertToCharset = "ISO_IR 192"; + if (cmd.findOption("--convert-to-latin1")) opt_convertToCharset = "ISO_IR 100"; + if (cmd.findOption("--convert-to-ascii")) opt_convertToCharset = ""; + if (cmd.findOption("--convert-to-charset")) app.checkValue(cmd.getValue(opt_convertToCharset)); + cmd.endOptionBlock(); + if (cmd.findOption("--transliterate")) + { + app.checkDependence("--transliterate", "one of the --convert-to-xxx options", opt_convertToCharset != NULL); + opt_transliterate = OFTrue; + } + if (cmd.findOption("--discard-illegal")) + { + app.checkDependence("--discard-illegal", "one of the --convert-to-xxx options", opt_convertToCharset != NULL); + opt_discardIllegal = OFTrue; + } +#endif + if (cmd.findOption("--no-invalid-groups")) opt_noInvalidGroups = OFTrue; + + /* output options */ + cmd.beginOptionBlock(); + if (cmd.findOption("--write-file")) opt_writeMode = EWM_fileformat; + if (cmd.findOption("--write-new-meta-info")) opt_writeMode = EWM_createNewMeta; + if (cmd.findOption("--write-dataset")) opt_writeMode = EWM_dataset; + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--write-xfer-same")) opt_oxfer = EXS_Unknown; + if (cmd.findOption("--write-xfer-little")) opt_oxfer = EXS_LittleEndianExplicit; + if (cmd.findOption("--write-xfer-big")) opt_oxfer = EXS_BigEndianExplicit; + if (cmd.findOption("--write-xfer-implicit")) opt_oxfer = EXS_LittleEndianImplicit; +#ifdef WITH_ZLIB + if (cmd.findOption("--write-xfer-deflated")) opt_oxfer = EXS_DeflatedLittleEndianExplicit; +#endif + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--enable-new-vr")) + { + dcmEnableGenerationOfNewVRs(); + } + if (cmd.findOption("--disable-new-vr")) + { + dcmDisableGenerationOfNewVRs(); + } + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--group-length-recalc")) opt_oglenc = EGL_recalcGL; + if (cmd.findOption("--group-length-create")) opt_oglenc = EGL_withGL; + if (cmd.findOption("--group-length-remove")) opt_oglenc = EGL_withoutGL; + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--length-explicit")) opt_oenctype = EET_ExplicitLength; + if (cmd.findOption("--length-undefined")) opt_oenctype = EET_UndefinedLength; + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--write-oversized")) dcmWriteOversizedSeqsAndItemsUndefined.set(OFTrue); + if (cmd.findOption("--abort-oversized")) dcmWriteOversizedSeqsAndItemsUndefined.set(OFFalse); + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--padding-retain")) + { + app.checkConflict("--padding-retain", "--write-dataset", opt_writeMode == EWM_dataset); + opt_opadenc = EPD_noChange; + } + if (cmd.findOption("--padding-off")) opt_opadenc = EPD_withoutPadding; + if (cmd.findOption("--padding-create")) + { + app.checkConflict("--padding-create", "--write-dataset", opt_writeMode == EWM_dataset); + app.checkValue(cmd.getValueAndCheckMin(opt_filepad, 0)); + app.checkValue(cmd.getValueAndCheckMin(opt_itempad, 0)); + opt_opadenc = EPD_withPadding; + } + cmd.endOptionBlock(); + +#ifdef WITH_ZLIB + if (cmd.findOption("--compression-level")) + { + app.checkDependence("--compression-level", "--write-xfer-deflated", opt_oxfer == EXS_DeflatedLittleEndianExplicit); + app.checkValue(cmd.getValueAndCheckMinMax(opt_compressionLevel, 0, 9)); + dcmZlibCompressionLevel.set(OFstatic_cast(int, opt_compressionLevel)); + } +#endif + } + + /* print resource identifier */ + OFLOG_DEBUG(dcmconvLogger, rcsid << OFendl); + + /* make sure data dictionary is loaded */ + if (!dcmDataDict.isDictionaryLoaded()) + { + OFLOG_WARN(dcmconvLogger, "no data dictionary loaded, check environment variable: " + << DCM_DICT_ENVIRONMENT_VARIABLE); + } + + /* open input file */ + if ((opt_ifname == NULL) || (strlen(opt_ifname) == 0)) + { + OFLOG_FATAL(dcmconvLogger, "invalid filename: "); + return 1; + } + + DcmFileFormat fileformat; + DcmDataset *dataset = fileformat.getDataset(); + + OFLOG_INFO(dcmconvLogger, "open input file " << opt_ifname); + + OFCondition error = fileformat.loadFile(opt_ifname, opt_ixfer, EGL_noChange, DCM_MaxReadLength, opt_readMode); + + if (error.bad()) + { + OFLOG_FATAL(dcmconvLogger, error.text() << ": reading file: " << opt_ifname); + return 1; + } + + OFLOG_INFO(dcmconvLogger, "load all data into memory"); + /* make sure that pixel data is loaded before output file is created */ + dataset->loadAllDataIntoMemory(); + + if (opt_noInvalidGroups) + { + OFLOG_INFO(dcmconvLogger, "remove all elements with an invalid group number"); + fileformat.removeInvalidGroups(); + } +#ifdef WITH_LIBICONV + if (opt_convertToCharset != NULL) + { + OFString toCharset(opt_convertToCharset); + /* convert the complete dataset to a new character encoding */ + OFLOG_INFO(dcmconvLogger, "converting all element values that are affected by " + << "Specific Character Set (0008,0005) to '" << opt_convertToCharset << "'" + << (toCharset.empty() ? " (ASCII)" : "")); + error = fileformat.convertCharacterSet(toCharset, opt_transliterate, opt_discardIllegal); + if (error.bad()) + { + OFLOG_FATAL(dcmconvLogger, error.text() << ": processing file: " << opt_ifname); + return 1; + } + } +#endif + + if (opt_oxfer == EXS_Unknown) + { + OFLOG_INFO(dcmconvLogger, "set output transfer syntax to input transfer syntax"); + opt_oxfer = dataset->getOriginalXfer(); + } + + OFLOG_INFO(dcmconvLogger, "check if new output transfer syntax is possible"); + + DcmXfer opt_oxferSyn(opt_oxfer); + + dataset->chooseRepresentation(opt_oxfer, NULL); + + if (dataset->canWriteXfer(opt_oxfer)) + { + OFLOG_INFO(dcmconvLogger, "output transfer syntax " << opt_oxferSyn.getXferName() << " can be written"); + } else { + OFLOG_FATAL(dcmconvLogger, "no conversion to transfer syntax " << opt_oxferSyn.getXferName() << " possible!"); + return 1; + } + + OFLOG_INFO(dcmconvLogger, "create output file " << opt_ofname); + + error = fileformat.saveFile(opt_ofname, opt_oxfer, opt_oenctype, opt_oglenc, opt_opadenc, + OFstatic_cast(Uint32, opt_filepad), OFstatic_cast(Uint32, opt_itempad), opt_writeMode); + + if (error.bad()) + { + OFLOG_FATAL(dcmconvLogger, error.text() << ": writing file: " << opt_ofname); + return 1; + } + + OFLOG_INFO(dcmconvLogger, "conversion successful"); + + return 0; +} diff --git a/dcmdata/apps/dcmcrle.cc b/dcmdata/apps/dcmcrle.cc new file mode 100644 index 00000000..58f75b34 --- /dev/null +++ b/dcmdata/apps/dcmcrle.cc @@ -0,0 +1,336 @@ +/* + * + * Copyright (C) 2002-2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Marco Eichelberg + * + * Purpose: Compress DICOM file with RLE Transfer Syntax + * + */ + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#define INCLUDE_CSTDLIB +#define INCLUDE_CSTDIO +#define INCLUDE_CSTRING +#include "dcmtk/ofstd/ofstdinc.h" + +#ifdef HAVE_GUSI_H +#include +#endif + +#include "dcmtk/dcmdata/dctk.h" +#include "dcmtk/dcmdata/cmdlnarg.h" +#include "dcmtk/ofstd/ofconapp.h" +#include "dcmtk/dcmdata/dcuid.h" /* for dcmtk version name */ +#include "dcmtk/dcmdata/dcrleerg.h" /* for DcmRLEEncoderRegistration */ + +#ifdef WITH_ZLIB +#include /* for zlibVersion() */ +#endif + +#define OFFIS_CONSOLE_APPLICATION "dcmcrle" + +static OFLogger dcmcrleLogger = OFLog::getLogger("dcmtk.apps." OFFIS_CONSOLE_APPLICATION); + +static char rcsid[] = "$dcmtk: " OFFIS_CONSOLE_APPLICATION " v" + OFFIS_DCMTK_VERSION " " OFFIS_DCMTK_RELEASEDATE " $"; + +// ******************************************** + + +#define SHORTCOL 3 +#define LONGCOL 21 + +int main(int argc, char *argv[]) +{ + +#ifdef HAVE_GUSI_H + GUSISetup(GUSIwithSIOUXSockets); + GUSISetup(GUSIwithInternetSockets); +#endif + + const char *opt_ifname = NULL; + const char *opt_ofname = NULL; + + E_FileReadMode opt_readMode = ERM_autoDetect; + E_TransferSyntax opt_ixfer = EXS_Unknown; + E_GrpLenEncoding opt_oglenc = EGL_recalcGL; + E_EncodingType opt_oenctype = EET_ExplicitLength; + E_PaddingEncoding opt_opadenc = EPD_noChange; + OFCmdUnsignedInt opt_filepad = 0; + OFCmdUnsignedInt opt_itempad = 0; + + // RLE options + E_TransferSyntax opt_oxfer = EXS_RLELossless; + OFCmdUnsignedInt opt_fragmentSize = 0; // 0=unlimited + OFBool opt_createOffsetTable = OFTrue; + OFBool opt_uidcreation = OFFalse; + OFBool opt_secondarycapture = OFFalse; + + OFConsoleApplication app(OFFIS_CONSOLE_APPLICATION, "Encode DICOM file to RLE transfer syntax", rcsid); + OFCommandLine cmd; + cmd.setOptionColumns(LONGCOL, SHORTCOL); + cmd.setParamColumn(LONGCOL + SHORTCOL + 4); + + cmd.addParam("dcmfile-in", "DICOM input filename to be converted"); + cmd.addParam("dcmfile-out", "DICOM output filename"); + + cmd.addGroup("general options:", LONGCOL, SHORTCOL + 2); + cmd.addOption("--help", "-h", "print this help text and exit", OFCommandLine::AF_Exclusive); + cmd.addOption("--version", "print version information and exit", OFCommandLine::AF_Exclusive); + OFLog::addOptions(cmd); + + cmd.addGroup("input options:"); + cmd.addSubGroup("input file format:"); + cmd.addOption("--read-file", "+f", "read file format or data set (default)"); + cmd.addOption("--read-file-only", "+fo", "read file format only"); + cmd.addOption("--read-dataset", "-f", "read data set without file meta information"); + cmd.addSubGroup("input transfer syntax:", LONGCOL, SHORTCOL); + cmd.addOption("--read-xfer-auto", "-t=", "use TS recognition (default)"); + cmd.addOption("--read-xfer-detect", "-td", "ignore TS specified in the file meta header"); + cmd.addOption("--read-xfer-little", "-te", "read with explicit VR little endian TS"); + cmd.addOption("--read-xfer-big", "-tb", "read with explicit VR big endian TS"); + cmd.addOption("--read-xfer-implicit", "-ti", "read with implicit VR little endian TS"); + + cmd.addGroup("encapsulated pixel data encoding options:"); + cmd.addSubGroup("pixel data fragmentation:"); + cmd.addOption("--fragment-per-frame", "+ff", "encode each frame as one fragment (default)"); + cmd.addOption("--fragment-size", "+fs", 1, "[s]ize: integer", + "limit fragment size to s kbytes (non-standard)"); + cmd.addSubGroup("basic offset table encoding:"); + cmd.addOption("--offset-table-create", "+ot", "create offset table (default)"); + cmd.addOption("--offset-table-empty", "-ot", "leave offset table empty"); + + cmd.addSubGroup("SOP Class UID:"); + cmd.addOption("--class-default", "+cd", "keep SOP Class UID (default)"); + cmd.addOption("--class-sc", "+cs", "convert to Secondary Capture Image\n(implies --uid-always)"); + + cmd.addSubGroup("SOP Instance UID:"); + cmd.addOption("--uid-never", "+un", "never assign new UID (default)"); + cmd.addOption("--uid-always", "+ua", "always assign new UID"); + + cmd.addGroup("output options:"); + cmd.addSubGroup("post-1993 value representations:"); + cmd.addOption("--enable-new-vr", "+u", "enable support for new VRs (UN/UT) (default)"); + cmd.addOption("--disable-new-vr", "-u", "disable support for new VRs, convert to OB"); + cmd.addSubGroup("group length encoding:"); + cmd.addOption("--group-length-recalc", "+g=", "recalculate group lengths if present (default)"); + cmd.addOption("--group-length-create", "+g", "always write with group length elements"); + cmd.addOption("--group-length-remove", "-g", "always write without group length elements"); + cmd.addSubGroup("length encoding in sequences and items:"); + cmd.addOption("--length-explicit", "+e", "write with explicit lengths (default)"); + cmd.addOption("--length-undefined", "-e", "write with undefined lengths"); + cmd.addSubGroup("data set trailing padding:"); + cmd.addOption("--padding-retain", "-p=", "do not change padding (default)"); + cmd.addOption("--padding-off", "-p", "no padding"); + cmd.addOption("--padding-create", "+p", 2, "[f]ile-pad [i]tem-pad: integer", + "align file on multiple of f bytes\nand items on multiple of i bytes"); + + /* evaluate command line */ + prepareCmdLineArgs(argc, argv, OFFIS_CONSOLE_APPLICATION); + if (app.parseCommandLine(cmd, argc, argv)) + { + /* check exclusive options first */ + if (cmd.hasExclusiveOption()) + { + if (cmd.findOption("--version")) + { + app.printHeader(OFTrue /*print host identifier*/); + COUT << OFendl << "External libraries used:"; +#ifdef WITH_ZLIB + COUT << OFendl << "- ZLIB, Version " << zlibVersion() << OFendl; +#else + COUT << " none" << OFendl; +#endif + return 0; + } + } + + /* command line parameters */ + + cmd.getParam(1, opt_ifname); + cmd.getParam(2, opt_ofname); + + OFLog::configureFromCommandLine(cmd, app); + + cmd.beginOptionBlock(); + if (cmd.findOption("--read-file")) opt_readMode = ERM_autoDetect; + if (cmd.findOption("--read-file-only")) opt_readMode = ERM_fileOnly; + if (cmd.findOption("--read-dataset")) opt_readMode = ERM_dataset; + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--read-xfer-auto")) + opt_ixfer = EXS_Unknown; + if (cmd.findOption("--read-xfer-detect")) + dcmAutoDetectDatasetXfer.set(OFTrue); + if (cmd.findOption("--read-xfer-little")) + { + app.checkDependence("--read-xfer-little", "--read-dataset", opt_readMode == ERM_dataset); + opt_ixfer = EXS_LittleEndianExplicit; + } + if (cmd.findOption("--read-xfer-big")) + { + app.checkDependence("--read-xfer-big", "--read-dataset", opt_readMode == ERM_dataset); + opt_ixfer = EXS_BigEndianExplicit; + } + if (cmd.findOption("--read-xfer-implicit")) + { + app.checkDependence("--read-xfer-implicit", "--read-dataset", opt_readMode == ERM_dataset); + opt_ixfer = EXS_LittleEndianImplicit; + } + cmd.endOptionBlock(); + + // RLE options + + cmd.beginOptionBlock(); + if (cmd.findOption("--fragment-per-frame")) opt_fragmentSize = 0; + if (cmd.findOption("--fragment-size")) + { + app.checkValue(cmd.getValueAndCheckMin(opt_fragmentSize, OFstatic_cast(OFCmdUnsignedInt, 1))); + } + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--offset-table-create")) opt_createOffsetTable = OFTrue; + if (cmd.findOption("--offset-table-empty")) opt_createOffsetTable = OFFalse; + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--class-default")) opt_secondarycapture = OFFalse; + if (cmd.findOption("--class-sc")) opt_secondarycapture = OFTrue; + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--uid-always")) opt_uidcreation = OFTrue; + if (cmd.findOption("--uid-never")) opt_uidcreation = OFFalse; + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--enable-new-vr")) dcmEnableGenerationOfNewVRs(); + if (cmd.findOption("--disable-new-vr")) dcmDisableGenerationOfNewVRs(); + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--group-length-recalc")) opt_oglenc = EGL_recalcGL; + if (cmd.findOption("--group-length-create")) opt_oglenc = EGL_withGL; + if (cmd.findOption("--group-length-remove")) opt_oglenc = EGL_withoutGL; + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--length-explicit")) opt_oenctype = EET_ExplicitLength; + if (cmd.findOption("--length-undefined")) opt_oenctype = EET_UndefinedLength; + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--padding-retain")) opt_opadenc = EPD_noChange; + if (cmd.findOption("--padding-off")) opt_opadenc = EPD_withoutPadding; + if (cmd.findOption("--padding-create")) + { + app.checkValue(cmd.getValueAndCheckMin(opt_filepad, 0)); + app.checkValue(cmd.getValueAndCheckMin(opt_itempad, 0)); + opt_opadenc = EPD_withPadding; + } + cmd.endOptionBlock(); + } + + /* print resource identifier */ + OFLOG_DEBUG(dcmcrleLogger, rcsid << OFendl); + + // register RLE compression codec + DcmRLEEncoderRegistration::registerCodecs(opt_uidcreation, + OFstatic_cast(Uint32, opt_fragmentSize), opt_createOffsetTable, opt_secondarycapture); + + /* make sure data dictionary is loaded */ + if (!dcmDataDict.isDictionaryLoaded()) + { + OFLOG_WARN(dcmcrleLogger, "no data dictionary loaded, check environment variable: " + << DCM_DICT_ENVIRONMENT_VARIABLE); + } + + // open inputfile + if ((opt_ifname == NULL) || (strlen(opt_ifname) == 0)) + { + OFLOG_FATAL(dcmcrleLogger, "invalid filename: "); + return 1; + } + + DcmFileFormat fileformat; + DcmDataset * dataset = fileformat.getDataset(); + + OFLOG_INFO(dcmcrleLogger, "open input file " << opt_ifname); + + OFCondition error = fileformat.loadFile(opt_ifname, opt_ixfer, EGL_noChange, DCM_MaxReadLength, opt_readMode); + + if (error.bad()) + { + OFLOG_FATAL(dcmcrleLogger, error.text() << ": reading file: " << opt_ifname); + return 1; + } + + DcmXfer original_xfer(dataset->getOriginalXfer()); + if (original_xfer.isEncapsulated()) + { + OFLOG_INFO(dcmcrleLogger, "DICOM file is already compressed, converting to uncompressed transfer syntax first"); + if (EC_Normal != dataset->chooseRepresentation(EXS_LittleEndianExplicit, NULL)) + { + OFLOG_FATAL(dcmcrleLogger, "No conversion from compressed original to uncompressed transfer syntax possible!"); + return 1; + } + } + + OFString sopClass; + if (fileformat.getMetaInfo()->findAndGetOFString(DCM_MediaStorageSOPClassUID, sopClass).good()) + { + /* check for DICOMDIR files */ + if (sopClass == UID_MediaStorageDirectoryStorage) + { + OFLOG_FATAL(dcmcrleLogger, "DICOMDIR files (Media Storage Directory Storage SOP Class) cannot be compressed!"); + return 1; + } + } + + OFLOG_INFO(dcmcrleLogger, "Convert DICOM file to compressed transfer syntax"); + + DcmXfer opt_oxferSyn(opt_oxfer); + + dataset->chooseRepresentation(opt_oxfer, NULL); + if (dataset->canWriteXfer(opt_oxfer)) + { + OFLOG_INFO(dcmcrleLogger, "Output transfer syntax " << opt_oxferSyn.getXferName() << " can be written"); + } else { + OFLOG_FATAL(dcmcrleLogger, "No conversion to transfer syntax " << opt_oxferSyn.getXferName() << " possible!"); + return 1; + } + + OFLOG_INFO(dcmcrleLogger, "create output file " << opt_ofname); + + fileformat.loadAllDataIntoMemory(); + error = fileformat.saveFile(opt_ofname, opt_oxfer, opt_oenctype, opt_oglenc, opt_opadenc, + OFstatic_cast(Uint32, opt_filepad), OFstatic_cast(Uint32, opt_itempad), EWM_updateMeta); + + if (error.bad()) + { + OFLOG_FATAL(dcmcrleLogger, error.text() << ": writing file: " << opt_ofname); + return 1; + } + + OFLOG_INFO(dcmcrleLogger, "conversion successful"); + + // deregister RLE codec + DcmRLEEncoderRegistration::cleanup(); + + return 0; +} diff --git a/dcmdata/apps/dcmdrle.cc b/dcmdata/apps/dcmdrle.cc new file mode 100644 index 00000000..30c6dc52 --- /dev/null +++ b/dcmdata/apps/dcmdrle.cc @@ -0,0 +1,306 @@ +/* + * + * Copyright (C) 2002-2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Marco Eichelberg + * + * Purpose: Decompress RLE-compressed DICOM file + * + */ + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#define INCLUDE_CSTDLIB +#define INCLUDE_CSTDIO +#define INCLUDE_CSTRING +#include "dcmtk/ofstd/ofstdinc.h" + +#ifdef HAVE_GUSI_H +#include +#endif + +#include "dcmtk/dcmdata/dctk.h" +#include "dcmtk/dcmdata/cmdlnarg.h" +#include "dcmtk/ofstd/ofconapp.h" +#include "dcmtk/dcmdata/dcuid.h" /* for dcmtk version name */ +#include "dcmtk/dcmdata/dcrledrg.h" /* for DcmRLEDecoderRegistration */ + +#ifdef WITH_ZLIB +#include /* for zlibVersion() */ +#endif + +#define OFFIS_CONSOLE_APPLICATION "dcmdrle" + +static OFLogger dcmdrleLogger = OFLog::getLogger("dcmtk.apps." OFFIS_CONSOLE_APPLICATION); + +static char rcsid[] = "$dcmtk: " OFFIS_CONSOLE_APPLICATION " v" + OFFIS_DCMTK_VERSION " " OFFIS_DCMTK_RELEASEDATE " $"; + +// ******************************************** + + +#define SHORTCOL 3 +#define LONGCOL 21 + +int main(int argc, char *argv[]) +{ + +#ifdef HAVE_GUSI_H + GUSISetup(GUSIwithSIOUXSockets); + GUSISetup(GUSIwithInternetSockets); +#endif + + const char *opt_ifname = NULL; + const char *opt_ofname = NULL; + + E_TransferSyntax opt_oxfer = EXS_LittleEndianExplicit; + E_GrpLenEncoding opt_oglenc = EGL_recalcGL; + E_EncodingType opt_oenctype = EET_ExplicitLength; + E_PaddingEncoding opt_opadenc = EPD_noChange; + OFCmdUnsignedInt opt_filepad = 0; + OFCmdUnsignedInt opt_itempad = 0; + E_FileReadMode opt_readMode = ERM_autoDetect; + E_FileWriteMode opt_writeMode = EWM_fileformat; + E_TransferSyntax opt_ixfer = EXS_Unknown; + + // RLE parameters + OFBool opt_uidcreation = OFFalse; + OFBool opt_reversebyteorder = OFFalse; + + OFConsoleApplication app(OFFIS_CONSOLE_APPLICATION, "Decode RLE-compressed DICOM file", rcsid); + OFCommandLine cmd; + cmd.setOptionColumns(LONGCOL, SHORTCOL); + cmd.setParamColumn(LONGCOL + SHORTCOL + 4); + + cmd.addParam("dcmfile-in", "DICOM input filename to be converted"); + cmd.addParam("dcmfile-out", "DICOM output filename"); + + cmd.addGroup("general options:", LONGCOL, SHORTCOL + 2); + cmd.addOption("--help", "-h", "print this help text and exit", OFCommandLine::AF_Exclusive); + cmd.addOption("--version", "print version information and exit", OFCommandLine::AF_Exclusive); + OFLog::addOptions(cmd); + + cmd.addGroup("input options:"); + cmd.addSubGroup("input file format:"); + cmd.addOption("--read-file", "+f", "read file format or data set (default)"); + cmd.addOption("--read-file-only", "+fo", "read file format only"); + cmd.addOption("--read-dataset", "-f", "read data set without file meta information"); + + cmd.addGroup("processing options:"); + cmd.addSubGroup("SOP Instance UID:"); + cmd.addOption("--uid-default", "+ud", "keep same SOP Instance UID (default)"); + cmd.addOption("--uid-always", "+ua", "always assign new UID"); + cmd.addSubGroup("RLE byte segment order:"); + cmd.addOption("--byte-order-default", "+bd", "most significant byte first (default)"); + cmd.addOption("--byte-order-reverse", "+br", "least significant byte first"); + + cmd.addGroup("output options:"); + cmd.addSubGroup("output file format:"); + cmd.addOption("--write-file", "+F", "write file format (default)"); + cmd.addOption("--write-dataset", "-F", "write data set without file meta information"); + cmd.addSubGroup("output transfer syntax:"); + cmd.addOption("--write-xfer-little", "+te", "write with explicit VR little endian (default)"); + cmd.addOption("--write-xfer-big", "+tb", "write with explicit VR big endian TS"); + cmd.addOption("--write-xfer-implicit", "+ti", "write with implicit VR little endian TS"); + cmd.addSubGroup("post-1993 value representations:"); + cmd.addOption("--enable-new-vr", "+u", "enable support for new VRs (UN/UT) (default)"); + cmd.addOption("--disable-new-vr", "-u", "disable support for new VRs, convert to OB"); + cmd.addSubGroup("group length encoding:"); + cmd.addOption("--group-length-recalc", "+g=", "recalculate group lengths if present (default)"); + cmd.addOption("--group-length-create", "+g", "always write with group length elements"); + cmd.addOption("--group-length-remove", "-g", "always write without group length elements"); + cmd.addSubGroup("length encoding in sequences and items:"); + cmd.addOption("--length-explicit", "+e", "write with explicit lengths (default)"); + cmd.addOption("--length-undefined", "-e", "write with undefined lengths"); + cmd.addSubGroup("data set trailing padding (not with --write-dataset):"); + cmd.addOption("--padding-retain", "-p=", "do not change padding\n(default if not --write-dataset)"); + cmd.addOption("--padding-off", "-p", "no padding (implicit if --write-dataset)"); + cmd.addOption("--padding-create", "+p", 2, "[f]ile-pad [i]tem-pad: integer", + "align file on multiple of f bytes\nand items on multiple of i bytes"); + + /* evaluate command line */ + prepareCmdLineArgs(argc, argv, OFFIS_CONSOLE_APPLICATION); + if (app.parseCommandLine(cmd, argc, argv)) + { + /* check exclusive options first */ + if (cmd.hasExclusiveOption()) + { + if (cmd.findOption("--version")) + { + app.printHeader(OFTrue /*print host identifier*/); + COUT << OFendl << "External libraries used:"; +#ifdef WITH_ZLIB + COUT << OFendl << "- ZLIB, Version " << zlibVersion() << OFendl; +#else + COUT << " none" << OFendl; +#endif + return 0; + } + } + + /* command line parameters */ + + cmd.getParam(1, opt_ifname); + cmd.getParam(2, opt_ofname); + + OFLog::configureFromCommandLine(cmd, app); + + cmd.beginOptionBlock(); + if (cmd.findOption("--uid-default")) opt_uidcreation = OFFalse; + if (cmd.findOption("--uid-always")) opt_uidcreation = OFTrue; + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--byte-order-default")) opt_reversebyteorder = OFFalse; + if (cmd.findOption("--byte-order-reverse")) opt_reversebyteorder = OFTrue; + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--read-file")) + { + opt_readMode = ERM_autoDetect; + opt_ixfer = EXS_Unknown; + } + if (cmd.findOption("--read-file-only")) + { + opt_readMode = ERM_fileOnly; + opt_ixfer = EXS_Unknown; + } + if (cmd.findOption("--read-dataset")) + { + opt_readMode = ERM_dataset; + opt_ixfer = EXS_RLELossless; + } + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--write-file")) opt_writeMode = EWM_fileformat; + if (cmd.findOption("--write-dataset")) opt_writeMode = EWM_dataset; + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--write-xfer-little")) opt_oxfer = EXS_LittleEndianExplicit; + if (cmd.findOption("--write-xfer-big")) opt_oxfer = EXS_BigEndianExplicit; + if (cmd.findOption("--write-xfer-implicit")) opt_oxfer = EXS_LittleEndianImplicit; + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--enable-new-vr")) dcmEnableGenerationOfNewVRs(); + if (cmd.findOption("--disable-new-vr")) dcmDisableGenerationOfNewVRs(); + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--group-length-recalc")) opt_oglenc = EGL_recalcGL; + if (cmd.findOption("--group-length-create")) opt_oglenc = EGL_withGL; + if (cmd.findOption("--group-length-remove")) opt_oglenc = EGL_withoutGL; + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--length-explicit")) opt_oenctype = EET_ExplicitLength; + if (cmd.findOption("--length-undefined")) opt_oenctype = EET_UndefinedLength; + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--padding-retain")) + { + app.checkConflict("--padding-retain", "--write-dataset", opt_writeMode == EWM_dataset); + opt_opadenc = EPD_noChange; + } + if (cmd.findOption("--padding-off")) opt_opadenc = EPD_withoutPadding; + if (cmd.findOption("--padding-create")) + { + app.checkConflict("--padding-create", "--write-dataset", opt_writeMode == EWM_dataset); + app.checkValue(cmd.getValueAndCheckMin(opt_filepad, 0)); + app.checkValue(cmd.getValueAndCheckMin(opt_itempad, 0)); + opt_opadenc = EPD_withPadding; + } + cmd.endOptionBlock(); + } + + /* print resource identifier */ + OFLOG_DEBUG(dcmdrleLogger, rcsid << OFendl); + + // register global decompression codecs + DcmRLEDecoderRegistration::registerCodecs(opt_uidcreation, opt_reversebyteorder); + + /* make sure data dictionary is loaded */ + if (!dcmDataDict.isDictionaryLoaded()) + { + OFLOG_WARN(dcmdrleLogger, "no data dictionary loaded, check environment variable: " + << DCM_DICT_ENVIRONMENT_VARIABLE); + } + + // open inputfile + if ((opt_ifname == NULL) || (strlen(opt_ifname) == 0)) + { + OFLOG_FATAL(dcmdrleLogger, "invalid filename: "); + return 1; + } + + DcmFileFormat fileformat; + DcmDataset * dataset = fileformat.getDataset(); + + OFLOG_INFO(dcmdrleLogger, "open input file " << opt_ifname); + + OFCondition error = fileformat.loadFile(opt_ifname, opt_ixfer, EGL_noChange, DCM_MaxReadLength, opt_readMode); + + if (error.bad()) + { + OFLOG_FATAL(dcmdrleLogger, error.text() << ": reading file: " << opt_ifname); + return 1; + } + + OFLOG_INFO(dcmdrleLogger, "decompressing file"); + + DcmXfer opt_oxferSyn(opt_oxfer); + DcmXfer original_xfer(dataset->getOriginalXfer()); + + error = dataset->chooseRepresentation(opt_oxfer, NULL); + if (error.bad()) + { + OFLOG_FATAL(dcmdrleLogger, error.text() << ": decompressing file: " << opt_ifname); + if (error == EC_CannotChangeRepresentation) + OFLOG_FATAL(dcmdrleLogger, "input transfer syntax " << original_xfer.getXferName() << " not supported"); + return 1; + } + + if (! dataset->canWriteXfer(opt_oxfer)) + { + OFLOG_FATAL(dcmdrleLogger, "no conversion to transfer syntax " << opt_oxferSyn.getXferName() << " possible"); + return 1; + } + + OFLOG_INFO(dcmdrleLogger, "create output file " << opt_ofname); + + // update file meta information with new SOP Instance UID + if (opt_uidcreation && (opt_writeMode == EWM_fileformat)) + opt_writeMode = EWM_updateMeta; + + fileformat.loadAllDataIntoMemory(); + error = fileformat.saveFile(opt_ofname, opt_oxfer, opt_oenctype, opt_oglenc, opt_opadenc, + OFstatic_cast(Uint32, opt_filepad), OFstatic_cast(Uint32, opt_itempad), opt_writeMode); + + if (error.bad()) + { + OFLOG_FATAL(dcmdrleLogger, error.text() << ": writing file: " << opt_ofname); + return 1; + } + + OFLOG_INFO(dcmdrleLogger, "conversion successful"); + + // deregister RLE codec + DcmRLEDecoderRegistration::cleanup(); + + return 0; +} diff --git a/dcmdata/apps/dcmdump.cc b/dcmdata/apps/dcmdump.cc new file mode 100644 index 00000000..1c121724 --- /dev/null +++ b/dcmdata/apps/dcmdump.cc @@ -0,0 +1,825 @@ +/* + * + * Copyright (C) 1994-2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Gerd Ehlers + * + * Purpose: List the contents of a dicom file + * + */ + + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ +#include "dcmtk/ofstd/ofstream.h" +#include "dcmtk/dcmdata/dctk.h" +#include "dcmtk/dcmdata/cmdlnarg.h" +#include "dcmtk/ofstd/ofconapp.h" +#include "dcmtk/ofstd/ofstd.h" +#include "dcmtk/dcmdata/dcuid.h" /* for dcmtk version name */ +#include "dcmtk/dcmdata/dcistrmz.h" /* for dcmZlibExpectRFC1950Encoding */ + +#define INCLUDE_CSTDLIB +#define INCLUDE_CSTRING +#include "dcmtk/ofstd/ofstdinc.h" + +#ifdef WITH_ZLIB +#include /* for zlibVersion() */ +#endif +#ifdef WITH_LIBICONV +#include "dcmtk/ofstd/ofchrenc.h" /* for OFCharacterEncoding */ +#endif + +#if defined (HAVE_WINDOWS_H) || defined(HAVE_FNMATCH_H) +#define PATTERN_MATCHING_AVAILABLE +#endif + +#ifndef HAVE_WINDOWS_H +#define ANSI_ESCAPE_CODES_AVAILABLE +#endif + +#define OFFIS_CONSOLE_APPLICATION "dcmdump" + +static OFLogger dcmdumpLogger = OFLog::getLogger("dcmtk.apps." OFFIS_CONSOLE_APPLICATION); + +static char rcsid[] = "$dcmtk: " OFFIS_CONSOLE_APPLICATION " v" + OFFIS_DCMTK_VERSION " " OFFIS_DCMTK_RELEASEDATE " $"; + +#ifdef HAVE_GUSI_H +/* needed for Macintosh */ +#include +#include +#endif + +static int dumpFile(STD_NAMESPACE ostream &out, + const OFFilename &ifname, + const E_FileReadMode readMode, + const E_TransferSyntax xfer, + const size_t printFlags, + const OFBool loadIntoMemory, + const OFBool stopOnErrors, + const OFBool convertToUTF8, + const char *pixelDirectory); + +// ******************************************** + +static OFBool printFilename = OFFalse; +static OFBool printFileSearch = OFFalse; +static OFBool printAllInstances = OFTrue; +static OFBool prependSequenceHierarchy = OFFalse; +static int printTagCount = 0; +static const int MAX_PRINT_TAG_NAMES = 1024; +static const char *printTagNames[MAX_PRINT_TAG_NAMES]; +static const DcmTagKey *printTagKeys[MAX_PRINT_TAG_NAMES]; +static OFCmdUnsignedInt maxReadLength = 4096; // default is 4 KB +static size_t fileCounter = 0; + + +static DcmTagKey parseTagKey(const char *tagName) +{ + unsigned int group = 0xffff; + unsigned int elem = 0xffff; + if (sscanf(tagName, "%x,%x", &group, &elem) != 2) + { + DcmTagKey tagKey; + /* it is a name */ + const DcmDataDictionary &globalDataDict = dcmDataDict.rdlock(); + const DcmDictEntry *dicent = globalDataDict.findEntry(tagName); + if (dicent == NULL) { + OFLOG_WARN(dcmdumpLogger, "unrecognized tag name: '" << tagName << "'"); + tagKey = DCM_UndefinedTagKey; + } else { + tagKey = dicent->getKey(); + } + dcmDataDict.unlock(); + return tagKey; + } else /* tag name has format "gggg,eeee" */ + { + return DcmTagKey(OFstatic_cast(Uint16, group),OFstatic_cast(Uint16, elem)); + } +} + +static OFBool addPrintTagName(const char *tagName) +{ + if (printTagCount >= MAX_PRINT_TAG_NAMES) { + OFLOG_WARN(dcmdumpLogger, "too many print tag options (max: " << MAX_PRINT_TAG_NAMES << ")"); + return OFFalse; + } + + unsigned int group = 0xffff; + unsigned int elem = 0xffff; + if (sscanf(tagName, "%x,%x", &group, &elem) != 2) + { + /* it is a name */ + const DcmDataDictionary &globalDataDict = dcmDataDict.rdlock(); + const DcmDictEntry *dicent = globalDataDict.findEntry(tagName); + if (dicent == NULL) { + OFLOG_WARN(dcmdumpLogger, "unrecognized tag name: '" << tagName << "'"); + dcmDataDict.unlock(); + return OFFalse; + } else { + /* note for later */ + printTagKeys[printTagCount] = new DcmTagKey(dicent->getKey()); + } + dcmDataDict.unlock(); + } else { + /* tag name has format xxxx,xxxx */ + /* do not lookup in dictionary, tag could be private */ + printTagKeys[printTagCount] = NULL; + } + + printTagNames[printTagCount] = strcpy(OFstatic_cast(char*, malloc(strlen(tagName)+1)), tagName); + printTagCount++; + return OFTrue; +} + + +/* main program */ + +#define SHORTCOL 3 +#define LONGCOL 21 + +// this macro either expands to main() or wmain() +DCMTK_MAIN_FUNCTION +{ + OFBool loadIntoMemory = OFTrue; + size_t printFlags = DCMTypes::PF_shortenLongTagValues; + E_FileReadMode readMode = ERM_autoDetect; + E_TransferSyntax xfer = EXS_Unknown; + OFBool stopOnErrors = OFTrue; + OFBool scanDir = OFFalse; + OFBool recurse = OFFalse; + const char *scanPattern = ""; + const char *pixelDirectory = NULL; + OFBool convertToUTF8 = OFFalse; + +#ifdef HAVE_GUSI_H + /* needed for Macintosh */ + /* set options for the Metrowerks CodeWarrior SIOUX console */ + SIOUXSettings.autocloseonquit = OFFalse; + SIOUXSettings.asktosaveonclose = OFFalse; + SIOUXSettings.showstatusline = OFTrue; + SIOUXSettings.setupmenus = OFTrue; + /* set options for the GUSI sockets library */ + GUSISetup(GUSIwithSIOUXSockets); + GUSISetup(GUSIwithInternetSockets); +#endif + + OFConsoleApplication app(OFFIS_CONSOLE_APPLICATION, "Dump DICOM file and data set", rcsid); + OFCommandLine cmd; + cmd.setOptionColumns(LONGCOL, SHORTCOL); + cmd.setParamColumn(LONGCOL + SHORTCOL + 4); + + cmd.addParam("dcmfile-in", "DICOM input file or directory to be dumped", OFCmdParam::PM_MultiMandatory); + + cmd.addGroup("general options:", LONGCOL, SHORTCOL + 2); + cmd.addOption("--help", "-h", "print this help text and exit", OFCommandLine::AF_Exclusive); + cmd.addOption("--version", "print version information and exit", OFCommandLine::AF_Exclusive); + OFLog::addOptions(cmd); + + cmd.addGroup("input options:"); + cmd.addSubGroup("input file format:"); + cmd.addOption("--read-file", "+f", "read file format or data set (default)"); + cmd.addOption("--read-file-only", "+fo", "read file format only"); + cmd.addOption("--read-dataset", "-f", "read data set without file meta information"); + cmd.addSubGroup("input transfer syntax:"); + cmd.addOption("--read-xfer-auto", "-t=", "use TS recognition (default)"); + cmd.addOption("--read-xfer-detect", "-td", "ignore TS specified in the file meta header"); + cmd.addOption("--read-xfer-little", "-te", "read with explicit VR little endian TS"); + cmd.addOption("--read-xfer-big", "-tb", "read with explicit VR big endian TS"); + cmd.addOption("--read-xfer-implicit", "-ti", "read with implicit VR little endian TS"); + cmd.addSubGroup("input files:"); + cmd.addOption("--scan-directories", "+sd", "scan directories for input files (dcmfile-in)"); +#ifdef PATTERN_MATCHING_AVAILABLE + cmd.addOption("--scan-pattern", "+sp", 1, "[p]attern: string (only with --scan-directories)", + "pattern for filename matching (wildcards)"); +#endif + cmd.addOption("--no-recurse", "-r", "do not recurse within directories (default)"); + cmd.addOption("--recurse", "+r", "recurse within specified directories"); + cmd.addSubGroup("long tag values:"); + cmd.addOption("--load-all", "+M", "load very long tag values (default)"); + cmd.addOption("--load-short", "-M", "do not load very long values (e.g. pixel data)"); + cmd.addOption("--max-read-length", "+R", 1, "[k]bytes: integer (4..4194302, default: 4)", + "set threshold for long values to k kbytes"); + cmd.addSubGroup("parsing of file meta information:"); + cmd.addOption("--use-meta-length", "+ml", "use file meta information group length (default)"); + cmd.addOption("--ignore-meta-length", "-ml", "ignore file meta information group length"); + cmd.addSubGroup("parsing of odd-length attributes:"); + cmd.addOption("--accept-odd-length", "+ao", "accept odd length attributes (default)"); + cmd.addOption("--assume-even-length", "+ae", "assume real length is one byte larger"); + cmd.addSubGroup("handling of explicit VR:"); + cmd.addOption("--use-explicit-vr", "+ev", "use explicit VR from dataset (default)"); + cmd.addOption("--ignore-explicit-vr", "-ev", "ignore explicit VR (prefer data dictionary)"); + cmd.addSubGroup("handling of non-standard VR:"); + cmd.addOption("--treat-as-unknown", "+vr", "treat non-standard VR as unknown (default)"); + cmd.addOption("--assume-implicit", "-vr", "try to read with implicit VR little endian TS"); + cmd.addSubGroup("handling of undefined length UN elements:"); + cmd.addOption("--enable-cp246", "+ui", "read undefined len UN as implicit VR (default)"); + cmd.addOption("--disable-cp246", "-ui", "read undefined len UN as explicit VR"); + cmd.addSubGroup("handling of defined length UN elements:"); + cmd.addOption("--retain-un", "-uc", "retain elements as UN (default)"); + cmd.addOption("--convert-un", "+uc", "convert to real VR if known"); + cmd.addSubGroup("handling of private max-length elements (implicit VR):"); + cmd.addOption("--maxlength-dict", "-sq", "read as defined in dictionary (default)"); + cmd.addOption("--maxlength-seq", "+sq", "read as sequence with undefined length"); + cmd.addSubGroup("handling of wrong delimitation items:"); + cmd.addOption("--use-delim-items", "-rd", "use delimitation items from dataset (default)"); + cmd.addOption("--replace-wrong-delim", "+rd", "replace wrong sequence/item delimitation items"); + cmd.addSubGroup("general handling of parser errors: "); + cmd.addOption("--ignore-parse-errors", "+Ep", "try to recover from parse errors"); + cmd.addOption("--handle-parse-errors", "-Ep", "handle parse errors and stop parsing (default)"); + cmd.addSubGroup("other parsing options:"); + cmd.addOption("--stop-after-elem", "+st", 1, "[t]ag: \"gggg,eeee\" or dictionary name", + "stop parsing after element specified by t"); + cmd.addSubGroup("automatic data correction:"); + cmd.addOption("--enable-correction", "+dc", "enable automatic data correction (default)"); + cmd.addOption("--disable-correction", "-dc", "disable automatic data correction"); +#ifdef WITH_ZLIB + cmd.addSubGroup("bitstream format of deflated input:"); + cmd.addOption("--bitstream-deflated", "+bd", "expect deflated bitstream (default)"); + cmd.addOption("--bitstream-zlib", "+bz", "expect deflated zlib bitstream"); +#endif + +#ifdef WITH_LIBICONV + cmd.addGroup("processing options:"); + cmd.addSubGroup("specific character set:"); + cmd.addOption("--convert-to-utf8", "+U8", "convert all element values that are affected\nby Specific Character Set (0008,0005) to UTF-8"); +#endif + + cmd.addGroup("output options:"); + cmd.addSubGroup("printing:"); + cmd.addOption("--print-all", "+L", "print long tag values completely"); + cmd.addOption("--print-short", "-L", "print long tag values shortened (default)"); + cmd.addOption("--print-tree", "+T", "print hierarchical structure as a simple tree"); + cmd.addOption("--print-indented", "-T", "print hierarchical structure indented (default)"); + cmd.addOption("--print-filename", "+F", "print header with filename for each input file"); + cmd.addOption("--print-file-search", "+Fs", "print header with filename only for those input\nfiles that contain one of the searched tags"); + cmd.addSubGroup("mapping:"); + cmd.addOption("--map-uid-names", "+Un", "map well-known UID numbers to names (default)"); + cmd.addOption("--no-uid-names", "-Un", "do not map well-known UID numbers to names"); + cmd.addSubGroup("quoting:"); + cmd.addOption("--quote-nonascii", "+Qn", "quote non-ASCII and control chars as XML markup"); + cmd.addOption("--quote-as-octal", "+Qo", "quote non-ASCII and control ch. as octal numbers"); + cmd.addOption("--print-nonascii", "-Qn", "print non-ASCII and control chars (default)"); +#ifdef ANSI_ESCAPE_CODES_AVAILABLE + cmd.addSubGroup("color:"); + cmd.addOption("--print-color", "+C", "use ANSI escape codes for colored output"); + cmd.addOption("--no-color", "-C", "do not use any ANSI escape codes (default)"); +#endif + + cmd.addSubGroup("error handling:"); + cmd.addOption("--stop-on-error", "-E", "do not print if file is damaged (default)"); + cmd.addOption("--ignore-errors", "+E", "attempt to print even if file is damaged"); + + cmd.addSubGroup("searching:"); + cmd.addOption("--search", "+P", 1, "[t]ag: \"gggg,eeee\" or dictionary name", + "print the textual dump of tag t\nthis option can be specified multiple times\n(default: the complete file is printed)"); + cmd.addOption("--search-all", "+s", "print all instances of searched tags (default)"); + cmd.addOption("--search-first", "-s", "only print first instance of searched tags"); + cmd.addOption("--prepend", "+p", "prepend sequence hierarchy to printed tag,\ndenoted by: (gggg,eeee).(gggg,eeee).*\n(only when used with --search)"); + cmd.addOption("--no-prepend", "-p", "do not prepend hierarchy to tag (default)"); + + cmd.addSubGroup("writing:"); + cmd.addOption("--write-pixel", "+W", 1, "[d]irectory: string", + "write pixel data to a .raw file stored in d\n(little endian, filename created automatically)"); + + /* evaluate command line */ + prepareCmdLineArgs(argc, argv, OFFIS_CONSOLE_APPLICATION); + if (app.parseCommandLine(cmd, argc, argv)) + { + /* check exclusive options first */ + if (cmd.hasExclusiveOption()) + { + if (cmd.findOption("--version")) + { + app.printHeader(OFTrue /*print host identifier*/); + COUT << OFendl << "External libraries used:"; +#if !defined(WITH_ZLIB) && !defined(WITH_LIBICONV) + COUT << " none" << OFendl; +#else + COUT << OFendl; +#endif +#ifdef WITH_ZLIB + COUT << "- ZLIB, Version " << zlibVersion() << OFendl; +#endif +#ifdef WITH_LIBICONV + COUT << "- " << OFCharacterEncoding::getLibraryVersionString() << OFendl; +#endif + return 0; + } + } + + /* general options */ + OFLog::configureFromCommandLine(cmd, app); + + /* input options */ + cmd.beginOptionBlock(); + if (cmd.findOption("--read-file")) readMode = ERM_autoDetect; + if (cmd.findOption("--read-file-only")) readMode = ERM_fileOnly; + if (cmd.findOption("--read-dataset")) readMode = ERM_dataset; + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--read-xfer-auto")) + xfer = EXS_Unknown; + if (cmd.findOption("--read-xfer-detect")) + dcmAutoDetectDatasetXfer.set(OFTrue); + if (cmd.findOption("--read-xfer-little")) + { + app.checkDependence("--read-xfer-little", "--read-dataset", readMode == ERM_dataset); + xfer = EXS_LittleEndianExplicit; + } + if (cmd.findOption("--read-xfer-big")) + { + app.checkDependence("--read-xfer-big", "--read-dataset", readMode == ERM_dataset); + xfer = EXS_BigEndianExplicit; + } + if (cmd.findOption("--read-xfer-implicit")) + { + app.checkDependence("--read-xfer-implicit", "--read-dataset", readMode == ERM_dataset); + xfer = EXS_LittleEndianImplicit; + } + cmd.endOptionBlock(); + + if (cmd.findOption("--scan-directories")) scanDir = OFTrue; +#ifdef PATTERN_MATCHING_AVAILABLE + if (cmd.findOption("--scan-pattern")) + { + app.checkDependence("--scan-pattern", "--scan-directories", scanDir); + app.checkValue(cmd.getValue(scanPattern)); + } +#endif + cmd.beginOptionBlock(); + if (cmd.findOption("--no-recurse")) recurse = OFFalse; + if (cmd.findOption("--recurse")) + { + app.checkDependence("--recurse", "--scan-directories", scanDir); + recurse = OFTrue; + } + cmd.endOptionBlock(); + + if (cmd.findOption("--max-read-length")) + { + app.checkValue(cmd.getValueAndCheckMinMax(maxReadLength, 4, 4194302)); + maxReadLength *= 1024; // convert kbytes to bytes + } + cmd.beginOptionBlock(); + if (cmd.findOption("--load-all")) loadIntoMemory = OFTrue; + if (cmd.findOption("--load-short")) loadIntoMemory = OFFalse; + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--use-meta-length")) + { + dcmIgnoreFileMetaInformationGroupLength.set(OFFalse); + } + if (cmd.findOption("--ignore-meta-length")) + { + dcmIgnoreFileMetaInformationGroupLength.set(OFTrue); + } + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--accept-odd-length")) + { + dcmAcceptOddAttributeLength.set(OFTrue); + } + if (cmd.findOption("--assume-even-length")) + { + dcmAcceptOddAttributeLength.set(OFFalse); + } + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--use-explicit-vr")) + { + dcmPreferVRFromDataDictionary.set(OFFalse); + } + if (cmd.findOption("--ignore-explicit-vr")) + { + dcmPreferVRFromDataDictionary.set(OFTrue); + } + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--treat-as-unknown")) + { + dcmAcceptUnexpectedImplicitEncoding.set(OFFalse); + } + if (cmd.findOption("--assume-implicit")) + { + dcmAcceptUnexpectedImplicitEncoding.set(OFTrue); + } + + cmd.beginOptionBlock(); + if (cmd.findOption("--enable-cp246")) + { + dcmEnableCP246Support.set(OFTrue); + } + if (cmd.findOption("--disable-cp246")) + { + dcmEnableCP246Support.set(OFFalse); + } + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--retain-un")) + { + dcmEnableUnknownVRConversion.set(OFFalse); + } + if (cmd.findOption("--convert-un")) + { + dcmEnableUnknownVRConversion.set(OFTrue); + } + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--maxlength-dict")) + { + dcmReadImplPrivAttribMaxLengthAsSQ.set(OFFalse); + } + if (cmd.findOption("--maxlength-seq")) + { + dcmReadImplPrivAttribMaxLengthAsSQ.set(OFTrue); + } + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--use-delim-items")) + { + dcmReplaceWrongDelimitationItem.set(OFFalse); + } + if (cmd.findOption("--replace-wrong-delim")) + { + dcmReplaceWrongDelimitationItem.set(OFTrue); + } + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--ignore-parse-errors")) + { + dcmIgnoreParsingErrors.set(OFTrue); + } + if (cmd.findOption("--handle-parse-errors")) + { + dcmIgnoreParsingErrors.set(OFFalse); + } + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--enable-correction")) + { + dcmEnableAutomaticInputDataCorrection.set(OFTrue); + } + if (cmd.findOption("--disable-correction")) + { + dcmEnableAutomaticInputDataCorrection.set(OFFalse); + } + cmd.endOptionBlock(); + +#ifdef WITH_ZLIB + cmd.beginOptionBlock(); + if (cmd.findOption("--bitstream-deflated")) + { + dcmZlibExpectRFC1950Encoding.set(OFFalse); + } + if (cmd.findOption("--bitstream-zlib")) + { + dcmZlibExpectRFC1950Encoding.set(OFTrue); + } + cmd.endOptionBlock(); +#endif + + /* processing options */ +#ifdef WITH_LIBICONV + if (cmd.findOption("--convert-to-utf8")) convertToUTF8 = OFTrue; +#endif + + /* output options */ + cmd.beginOptionBlock(); + if (cmd.findOption("--print-all")) printFlags &= ~DCMTypes::PF_shortenLongTagValues; + if (cmd.findOption("--print-short")) printFlags |= DCMTypes::PF_shortenLongTagValues; + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--print-tree")) printFlags |= DCMTypes::PF_showTreeStructure; + if (cmd.findOption("--print-indented")) printFlags &= ~DCMTypes::PF_showTreeStructure; + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--print-filename")) + { + printFilename = OFTrue; + printFileSearch = OFFalse; + } + if (cmd.findOption("--print-file-search")) + { + printFileSearch = OFTrue; + printFilename = OFFalse; + } + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--map-uid-names")) printFlags &= ~DCMTypes::PF_doNotMapUIDsToNames; + if (cmd.findOption("--no-uid-names")) printFlags |= DCMTypes::PF_doNotMapUIDsToNames; + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--quote-nonascii")) + printFlags = (printFlags & ~DCMTypes::PF_convertToOctalNumbers) | DCMTypes::PF_convertToMarkup; + if (cmd.findOption("--quote-as-octal")) + printFlags = (printFlags & ~DCMTypes::PF_convertToMarkup) | DCMTypes::PF_convertToOctalNumbers; + if (cmd.findOption("--print-nonascii")) + printFlags = printFlags & ~(DCMTypes::PF_convertToMarkup | DCMTypes::PF_convertToOctalNumbers); + cmd.endOptionBlock(); + +#ifdef ANSI_ESCAPE_CODES_AVAILABLE + cmd.beginOptionBlock(); + if (cmd.findOption("--print-color")) printFlags |= DCMTypes::PF_useANSIEscapeCodes; + if (cmd.findOption("--no-color")) printFlags &= ~DCMTypes::PF_useANSIEscapeCodes; + cmd.endOptionBlock(); +#endif + + cmd.beginOptionBlock(); + if (cmd.findOption("--stop-on-error")) stopOnErrors = OFTrue; + if (cmd.findOption("--ignore-errors")) stopOnErrors = OFFalse; + cmd.endOptionBlock(); + + if (cmd.findOption("--stop-after-elem")) + { + const char *tagName = NULL; + app.checkValue(cmd.getValue(tagName)); + DcmTagKey key = parseTagKey(tagName); + if (key != DCM_UndefinedTagKey) + dcmStopParsingAfterElement.set(key); + else + app.printError("no valid key given for option --stop-after-elem"); + } + + if (cmd.findOption("--search", 0, OFCommandLine::FOM_FirstFromLeft)) + { + const char *tagName = NULL; + do + { + app.checkValue(cmd.getValue(tagName)); + if (!addPrintTagName(tagName)) return 1; + } while (cmd.findOption("--search", 0, OFCommandLine::FOM_NextFromLeft)); + } + + if (printFileSearch) + app.checkDependence("--print-file-search", "--search", printTagCount > 0); + + cmd.beginOptionBlock(); + if (cmd.findOption("--search-all")) + { + app.checkDependence("--search-all", "--search", printTagCount > 0); + printAllInstances = OFTrue; + } + if (cmd.findOption("--search-first")) + { + app.checkDependence("--search-first", "--search", printTagCount > 0); + printAllInstances = OFFalse; + } + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--prepend")) + { + app.checkDependence("--prepend", "--search", printTagCount > 0); + prependSequenceHierarchy = OFTrue; + } + if (cmd.findOption("--no-prepend")) + { + app.checkDependence("--no-prepend", "--search", printTagCount > 0); + prependSequenceHierarchy = OFFalse; + } + cmd.endOptionBlock(); + app.checkConflict("--prepend", "--print-tree", prependSequenceHierarchy && (printFlags & DCMTypes::PF_showTreeStructure) > 0); + + if (cmd.findOption("--write-pixel")) + app.checkValue(cmd.getValue(pixelDirectory)); + } + + /* print resource identifier */ + OFLOG_DEBUG(dcmdumpLogger, rcsid << OFendl); + + /* make sure data dictionary is loaded */ + if (!dcmDataDict.isDictionaryLoaded()) + { + OFLOG_WARN(dcmdumpLogger, "no data dictionary loaded, check environment variable: " + << DCM_DICT_ENVIRONMENT_VARIABLE); + } + + /* make sure the pixel data directory exists and is writable */ + if (pixelDirectory != NULL) + { + if (!OFStandard::dirExists(pixelDirectory)) + { + OFLOG_WARN(dcmdumpLogger, "directory specified for --write-pixel does not exist, ignoring this option"); + pixelDirectory = NULL; + } + else if (!OFStandard::isWriteable(pixelDirectory)) + { + OFLOG_WARN(dcmdumpLogger, "directory specified for --write-pixel is not writeable, ignoring this option"); + pixelDirectory = NULL; + } + } + + int errorCount = 0; + + /* create list of input files */ + OFFilename paramValue; + OFList inputFiles; + const int paramCount = cmd.getParamCount(); + /* iterate over all input filenames */ + for (int i = 1; i <= paramCount; i++) + { + cmd.getParam(i, paramValue); + /* search directory recursively (if required) */ + if (OFStandard::dirExists(paramValue)) + { + if (scanDir) + OFStandard::searchDirectoryRecursively(paramValue, inputFiles, scanPattern, "" /*dirPrefix*/, recurse); + else + OFLOG_WARN(dcmdumpLogger, "ignoring directory because option --scan-directories is not set: " << paramValue); + } else + inputFiles.push_back(paramValue); + } + /* check whether there are any input files at all */ + if (inputFiles.empty()) + { + OFLOG_FATAL(dcmdumpLogger, "no input files to be dumped"); + return 1; + } + + const size_t count = inputFiles.size(); + OFFilename current; + OFListIterator(OFFilename) if_iter = inputFiles.begin(); + OFListIterator(OFFilename) if_last = inputFiles.end(); + /* iterate over all input filenames */ + while (if_iter != if_last) + { + current = (*if_iter++); + if (printFilename) + { + /* a newline separates two consecutive "dumps" */ + if (++fileCounter > 1) + COUT << OFendl; + /* print header with filename */ + COUT << "# " << OFFIS_CONSOLE_APPLICATION << " (" << fileCounter << "/" << count << "): " << current << OFendl; + } + errorCount += dumpFile(COUT, current, readMode, xfer, printFlags, loadIntoMemory, stopOnErrors, convertToUTF8, pixelDirectory); + } + + return errorCount; +} + +static void printResult(STD_NAMESPACE ostream &out, + DcmStack &stack, + size_t printFlags, + const char*pixelFileName = NULL, + size_t *pixelCounter = NULL) +{ + unsigned long n = stack.card(); + if (n == 0) { + return; + } + + if (prependSequenceHierarchy) { + if (printFlags & DCMTypes::PF_useANSIEscapeCodes) + out << DCMDATA_ANSI_ESCAPE_CODE_TAG; + /* print the path leading up to the top stack elem */ + for (unsigned long i = n - 1; i >= 1; i--) { + DcmObject *dobj = stack.elem(i); + /* do not print if a DCM_Item as this is not + * very helpful to distinguish instances. + */ + if (dobj != NULL && dobj->getTag().getXTag() != DCM_Item) { + out << dobj->getTag() << "."; + } + } + } + + /* print the tag and its value */ + DcmObject *dobj = stack.top(); + dobj->print(out, printFlags, 1 /*level*/, pixelFileName, pixelCounter); +} + +static int dumpFile(STD_NAMESPACE ostream &out, + const OFFilename &ifname, + const E_FileReadMode readMode, + const E_TransferSyntax xfer, + const size_t printFlags, + const OFBool loadIntoMemory, + const OFBool stopOnErrors, + const OFBool convertToUTF8, + const char *pixelDirectory) +{ + int result = 0; + + if (ifname.isEmpty()) + { + OFLOG_ERROR(dcmdumpLogger, OFFIS_CONSOLE_APPLICATION << ": invalid filename: "); + return 1; + } + + DcmFileFormat dfile; + DcmObject *dset = &dfile; + if (readMode == ERM_dataset) dset = dfile.getDataset(); + OFCondition cond = dfile.loadFile(ifname, xfer, EGL_noChange, OFstatic_cast(Uint32, maxReadLength), readMode); + if (cond.bad()) + { + OFLOG_ERROR(dcmdumpLogger, OFFIS_CONSOLE_APPLICATION << ": " << cond.text() + << ": reading file: "<< ifname); + result = 1; + if (stopOnErrors) return result; + } + + if (loadIntoMemory) dfile.loadAllDataIntoMemory(); + +#ifdef WITH_LIBICONV + if (convertToUTF8) + { + OFLOG_INFO(dcmdumpLogger, "converting all element values that are affected by Specific Character Set (0008,0005) to UTF-8"); + cond = dfile.convertToUTF8(); + if (cond.bad()) + { + OFLOG_FATAL(dcmdumpLogger, cond.text() << ": converting file to UTF-8: " << ifname); + result = 1; + if (stopOnErrors) return result; + } + } +#endif + + size_t pixelCounter = 0; + const char *pixelFileName = NULL; + OFFilename pixelFilenameStr; + if (pixelDirectory != NULL) + { + /* create filename for pixel data */ + OFFilename fileName; + OFStandard::getFilenameFromPath(fileName, ifname); + OFStandard::combineDirAndFilename(pixelFilenameStr, pixelDirectory, fileName); + pixelFileName = pixelFilenameStr.getCharPointer(); + } + + /* dump complete file content */ + if (printTagCount == 0) + { + dset->print(out, printFlags, 0 /*level*/, pixelFileName, &pixelCounter); + } else { + OFBool firstTag = OFTrue; + /* only print specified tags */ + for (int i = 0; i < printTagCount; i++) + { + unsigned int group = 0xffff; + unsigned int elem = 0xffff; + DcmTagKey searchKey; + const char *tagName = printTagNames[i]; + if (printTagKeys[i]) + searchKey = *printTagKeys[i]; + else if (sscanf(tagName, "%x,%x", &group, &elem) == 2) + searchKey.set(OFstatic_cast(Uint16, group), OFstatic_cast(Uint16, elem)); + else { + OFLOG_FATAL(dcmdumpLogger, "Internal ERROR in File " << __FILE__ << ", Line " + << __LINE__ << OFendl << " -- Named tag inconsistency"); + abort(); + } + + DcmStack stack; + if (dset->search(searchKey, stack, ESM_fromHere, OFTrue) == EC_Normal) + { + if (firstTag) + { + if (!printFilename) + { + /* a newline separates two consecutive "dumps" */ + if (++fileCounter > 1) + COUT << OFendl; + } + /* print header with filename */ + if (printFileSearch) + COUT << "# " << OFFIS_CONSOLE_APPLICATION << " (" << fileCounter << "): " << ifname << OFendl; + firstTag = OFFalse; + } + printResult(out, stack, printFlags, pixelFileName, &pixelCounter); + if (printAllInstances) + { + while (dset->search(searchKey, stack, ESM_afterStackTop, OFTrue) == EC_Normal) + printResult(out, stack, printFlags, pixelFileName, &pixelCounter); + } + } + } + } + return result; +} diff --git a/dcmdata/apps/dcmftest.cc b/dcmdata/apps/dcmftest.cc new file mode 100644 index 00000000..b4771226 --- /dev/null +++ b/dcmdata/apps/dcmftest.cc @@ -0,0 +1,88 @@ +/* + * + * Copyright (C) 1994-2012, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Andrew Hewett + * + * Purpose: Test if a file uses DICOM Part 10 format. + * + */ + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#define INCLUDE_CSTDLIB +#define INCLUDE_CSTDIO +#define INCLUDE_CSTRING +#define INCLUDE_LIBC +#define INCLUDE_UNISTD +#include "dcmtk/ofstd/ofstdinc.h" + +#include "dcmtk/dcmdata/dcmetinf.h" +#include "dcmtk/ofstd/ofconapp.h" +#include "dcmtk/dcmdata/dcuid.h" /* for dcmtk version name */ + +#define OFFIS_CONSOLE_APPLICATION "dcmftest" + +static char rcsid[] = "$dcmtk: " OFFIS_CONSOLE_APPLICATION " v" + OFFIS_DCMTK_VERSION " " OFFIS_DCMTK_RELEASEDATE " $"; + +// ******************************************** + +int main(int argc, char *argv[]) +{ + OFConsoleApplication app(OFFIS_CONSOLE_APPLICATION , "Test if file uses DICOM part 10 format", rcsid); + OFCommandLine cmd; + + /* evaluate command line */ + cmd.addParam("file", OFCmdParam::PM_MultiMandatory); + app.parseCommandLine(cmd, argc, argv); + + int badCount = 0; + int count = cmd.getParamCount(); + const char *fname = NULL; + for (int i=1; i<=count; i++) { + cmd.getParam(i, fname); + OFBool ok = OFFalse; + FILE* f = NULL; + + if (fname && (strlen(fname) > 0)) f = fopen(fname, "rb"); + if (f == 0) { + ok = OFFalse; + } else { + char signature[4]; + if ((fseek(f, DCM_PreambleLen, SEEK_SET) < 0) || + (fread(signature, 1, DCM_MagicLen, f) != DCM_MagicLen)) { + ok = OFFalse; + } else if (strncmp(signature, DCM_Magic, DCM_MagicLen) != 0) { + ok = OFFalse; + } else { + /* looks ok */ + ok = OFTrue; + } + fclose(f); + } + if (ok) { + COUT << "yes: " << fname << OFendl; + } else { + COUT << "no: " << fname << OFendl; + badCount++; + } + } + + /* + ** if all files are ok then return zero, otherwise the + ** number of non-dicom files. + */ + return badCount; +} diff --git a/dcmdata/apps/dcmgpdir.cc b/dcmdata/apps/dcmgpdir.cc new file mode 100644 index 00000000..40cba12a --- /dev/null +++ b/dcmdata/apps/dcmgpdir.cc @@ -0,0 +1,630 @@ +/* + * + * Copyright (C) 1994-2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Andrew Hewett, Joerg Riesmeier + * + * Purpose: + * Make a DICOMDIR according to the DICOM Part 11 Media Storage Application + * Profiles. Supports the following profiles: + * - General Purpose CD-R Interchange (STD-GEN-CD) + * - General Purpose Interchange on DVD-RAM Media (STD-GEN-DVD-RAM) + * If build with 'BUILD_DCMGPDIR_AS_DCMMKDIR' it also supports: + * - General Purpose DVD Interchange with JPEG (STD-GEN-DVD-JPEG) + * - General Purpose DVD Interchange with JPEG 2000 (STD-GEN-DVD-J2K) + * - General Purpose BD Interchange with JPEG (STD-GEN-BD-JPEG) + * - General Purpose BD Interchange with JPEG 2000 (STD-GEN-BD-J2K) + * - General Purpose BD Interchange with MPEG2 MP@ML (STD-GEN-BD-MPEG2-MPML) + * - General Purpose BD Interchange with MPEG2 MP@HL (STD-GEN-BD-MPEG2-MPHL) + * - General Purpose BD Interchange with MPEG-4 AVC/H.264 HiP@Level4.1 (STD-GEN-BD-MPEG4-HPLV41) + * - General Purpose BD Interchange with MPEG-4 AVC/H.264 BD-Compatible HiP@Level4.1 (STD-GEN-BD-MPEG4-HPLV41BD) + * - General Purpose USB and Flash Memory Interchange with JPEG (STD-GEN-USB/MMC/CF/SD-JPEG) + * - General Purpose USB and Flash Memory Interchange with JPEG 2000 (STD-GEN-USB/MMC/CF/SD-J2K) + * - General Purpose MIME Interchange (STD-GEN-MIME) + * - DVD Interchange with MPEG2 MP@ML (STD-DVD-MPEG2-MPML) + * - Basic Cardiac X-Ray Angiographic Studies on CD-R Media (STD-XABC-CD) + * - 1024 X-Ray Angiographic Studies on CD-R Media (STD-XA1K-CD) + * - 1024 X-Ray Angiographic Studies on DVD Media (STD-XA1K-DVD) + * - Dental Radiograph Interchange (STD-DEN-CD) + * - CT/MR Studies on various Media (STD-CTMR-xxxx) + * - Ultrasound Single Frame for Image Display (STD-US-ID-SF-xxxx) + * - Ultrasound Single Frame with Spatial Calibration (STD-US-SC-SF-xxxx) + * - Ultrasound Single Frame with Combined Calibration (STD-US-CC-SF-xxxx) + * - Ultrasound Single & Multi-Frame for Image Display (STD-US-ID-MF-xxxx) + * - Ultrasound Single & Multi-Frame with Spatial Calibration (STD-US-SC-MF-xxxx) + * - Ultrasound Single & Multi-Frame with Combined Calibration (STD-US-CC-MF-xxxx) + * - 12-lead ECG Interchange on Diskette (STD-WVFM-ECG-FD) + * - Hemodynamic Waveform Interchange on Diskette (STD-WVFM-HD-FD) + * There should be no need to set this compiler flag manually, just compile + * dcmjpeg/apps/dcmmkdir.cc. + * + */ + + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/dcmdata/dctk.h" +#include "dcmtk/dcmdata/dcuid.h" /* for dcmtk version name */ +#include "dcmtk/dcmdata/dcddirif.h" /* for class DicomDirInterface */ +#include "dcmtk/ofstd/ofstd.h" /* for class OFStandard */ +#include "dcmtk/ofstd/ofconapp.h" /* for class OFConsoleApplication */ +#include "dcmtk/ofstd/ofcond.h" /* for class OFCondition */ + +#ifdef BUILD_DCMGPDIR_AS_DCMMKDIR +#include "dcmtk/dcmimage/diregist.h" /* include to support color images */ +#include "dcmtk/dcmdata/dcrledrg.h" /* for DcmRLEDecoderRegistration */ +#include "dcmtk/dcmjpeg/djdecode.h" /* for dcmjpeg decoders */ +#include "dcmtk/dcmjpeg/dipijpeg.h" /* for dcmimage JPEG plugin */ +#include "dcmtk/dcmjpeg/ddpiimpl.h" /* for class DicomDirImageImplementation */ +#endif + +#ifdef WITH_ZLIB +#include /* for zlibVersion() */ +#endif + +#ifdef BUILD_DCMGPDIR_AS_DCMMKDIR +#define OFFIS_CONSOLE_APPLICATION "dcmmkdir" +#define OFFIS_CONSOLE_DESCRIPTION "Create a DICOMDIR file" +#else +#define OFFIS_CONSOLE_APPLICATION "dcmgpdir" +#define OFFIS_CONSOLE_DESCRIPTION "Create a general purpose DICOMDIR" +#endif + +#if defined (HAVE_WINDOWS_H) || defined(HAVE_FNMATCH_H) +#define PATTERN_MATCHING_AVAILABLE +#endif + + +static char rcsid[] = "$dcmtk: " OFFIS_CONSOLE_APPLICATION " v" + OFFIS_DCMTK_VERSION " " OFFIS_DCMTK_RELEASEDATE " $"; + +static OFLogger dcmgpdirLogger = OFLog::getLogger("dcmtk.dcmdata." OFFIS_CONSOLE_APPLICATION); + +#define SHORTCOL 4 +#define LONGCOL 23 + +// ******************************************** + +// this macro either expands to main() or wmain() +DCMTK_MAIN_FUNCTION +{ + OFBool opt_write = OFTrue; + OFBool opt_append = OFFalse; + OFBool opt_update = OFFalse; + OFBool opt_recurse = OFFalse; + E_EncodingType opt_enctype = EET_ExplicitLength; + E_GrpLenEncoding opt_glenc = EGL_withoutGL; + OFFilename opt_output(DEFAULT_DICOMDIR_NAME); + const char *opt_fileset = DEFAULT_FILESETID; + const char *opt_descriptor = NULL; + const char *opt_charset = DEFAULT_DESCRIPTOR_CHARSET; + OFFilename opt_directory; + OFFilename opt_pattern; + DicomDirInterface::E_ApplicationProfile opt_profile = DicomDirInterface::AP_GeneralPurpose; + +#ifdef BUILD_DCMGPDIR_AS_DCMMKDIR + // register global decompression codecs (no verbose/debug mode set) + DcmRLEDecoderRegistration::registerCodecs(); + DJDecoderRegistration::registerCodecs(); + // enable the following lines for JPEG 2000 decompression support +/* + D2JPEG2000Library::initialize(); + D2DecoderRegistration::registerCodecs(); +*/ +#endif + + /* DICOMDIR interface (checks for JPEG/RLE availability) */ + DicomDirInterface ddir; + + /* set-up command line parameters and options */ + OFConsoleApplication app(OFFIS_CONSOLE_APPLICATION, OFFIS_CONSOLE_DESCRIPTION, rcsid); + OFCommandLine cmd; + cmd.setOptionColumns(LONGCOL, SHORTCOL); + cmd.setParamColumn(LONGCOL + SHORTCOL + 4); + + cmd.addParam("dcmfile-in", "ref. DICOM file (or directory to be scanned)", OFCmdParam::PM_MultiOptional); + + cmd.addGroup("general options:", LONGCOL, SHORTCOL + 2); + cmd.addOption("--help", "-h", "print this help text and exit", OFCommandLine::AF_Exclusive); + cmd.addOption("--version", "print version information and exit", OFCommandLine::AF_Exclusive); + OFLog::addOptions(cmd); + + cmd.addGroup("input options:"); + cmd.addSubGroup("DICOMDIR identifiers:"); + cmd.addOption("--fileset-id", "+F", 1, "[i]d: string", + "use specific file-set ID\n(default: " DEFAULT_FILESETID ", \"\" for none)"); + cmd.addOption("--descriptor", "+R", 1, "[f]ilename: string", + "add a file-set descriptor file ID\n(e.g. README, default: no descriptor)"); + cmd.addOption("--char-set", "+C", 1, "[c]harset: string", + "add a specific character set for descriptor\n(default: \"" DEFAULT_DESCRIPTOR_CHARSET "\" if descriptor present)"); + cmd.addSubGroup("reading:"); + cmd.addOption("--input-directory", "+id", 1, "[d]irectory: string", + "read referenced DICOM files from directory d\n(default for --recurse: current directory)"); + cmd.addOption("--keep-filenames", "-m", "expect filenames to be in DICOM format (def.)"); + cmd.addOption("--map-filenames", "+m", "map to DICOM filenames (lowercase->uppercase,\nand remove trailing period)"); + cmd.addOption("--no-recurse", "-r", "do not recurse within directories (default)"); + cmd.addOption("--recurse", "+r", "recurse within filesystem directories"); +#ifdef PATTERN_MATCHING_AVAILABLE + cmd.addOption("--pattern", "+p", 1, "[p]attern: string (only with --recurse)", + "pattern for filename matching (wildcards)"); +#endif + cmd.addGroup("processing options:"); + cmd.addSubGroup("consistency check:"); + cmd.addOption("--no-consistency-check", "-W", "do not check files for consistency"); + cmd.addOption("--warn-inconsist-files", "+W", "warn about inconsistent files (default)"); + cmd.addOption("--abort-inconsist-file", "-a", "abort on first inconsistent file"); + cmd.addSubGroup("type 1 attributes:"); + cmd.addOption("--strict", "-I", "exit with error if DICOMDIR type 1 attributes\nare missing in DICOM file (default)"); + cmd.addOption("--invent", "+I", "invent DICOMDIR type 1 attributes\nif missing in DICOM file"); + cmd.addOption("--invent-patient-id", "+Ipi", "invent new PatientID in case of inconsistent\nPatientName attributes"); + cmd.addSubGroup("other checks:"); + cmd.addOption("--allow-retired-sop", "+Nrs", "allow retired SOP classes defined in previous\neditions of the DICOM standard"); + cmd.addOption("--no-xfer-check", "-Nxc", "do not reject images with non-standard\ntransfer syntax (just warn)"); +#ifdef BUILD_DCMGPDIR_AS_DCMMKDIR + cmd.addOption("--no-encoding-check", "-Nec", "do not reject images with non-standard\npixel encoding (just warn)"); + cmd.addOption("--no-resolution-check", "-Nrc", "do not reject images with non-standard\nspatial resolution (just warn)"); + cmd.addSubGroup("icon images:"); + cmd.addOption("--add-icon-image", "+X", "add monochrome icon image on IMAGE level\n(default for cardiac profiles)"); + cmd.addOption("--icon-image-size", "-Xs", 1, "[s]ize: integer (1..128)", + "width and height of the icon image (in pixel)\n(fixed: 128 for XA, 64 for CT/MR profile)"); + cmd.addOption("--icon-file-prefix", "-Xi", 1, "[p]refix: string", + "use PGM image 'prefix'+'dcmfile-in' as icon\n(default: create icon from DICOM image)"); + cmd.addOption("--default-icon", "-Xd", 1, "[f]ilename: string", + "use specified PGM image if icon cannot be\ncreated automatically (default: black image)"); +#endif + cmd.addGroup("output options:"); + cmd.addSubGroup("DICOMDIR file:"); + cmd.addOption("--output-file", "+D", 1, "[f]ilename: string", + "generate specific DICOMDIR file\n(default: " DEFAULT_DICOMDIR_NAME " in current directory)"); +#ifdef BUILD_DCMGPDIR_AS_DCMMKDIR + cmd.addSubGroup("profiles:"); + cmd.addOption("--general-purpose", "-Pgp", "General Purpose Interchange on CD-R or\nDVD-RAM Media (STD-GEN-CD/DVD-RAM, default)"); + cmd.addOption("--general-dvd-jpeg", "-Pdv", "General Purpose DVD Interchange with JPEG\n(STD-GEN-DVD-JPEG)"); + cmd.addOption("--general-dvd-j2k", "-Pd2", "General Purpose DVD Interchange with JPEG\n2000 (STD-GEN-DVD-J2K)"); + cmd.addOption("--general-bd-jpeg", "-Pbd", "General Purpose BD Interchange with JPEG\n(STD-GEN-BD-JPEG)"); + cmd.addOption("--general-bd-j2k", "-Pb2", "General Purpose BD Interchange with JPEG\n2000 (STD-GEN-BD-J2K)"); + cmd.addOption("--general-bd-mpeg2-mpml", "-Pbm", "General Purpose BD Interchange with MPEG2\nMP@ML (STD-GEN-BD-MPEG2-MPML)"); + cmd.addOption("--general-bd-mpeg2-mphl", "-Pbh", "General Purpose BD Interchange with MPEG2\nMP@HL (STD-GEN-BD-MPEG2-MPHL)"); + cmd.addOption("--general-bd-mpeg4-hp", "-Pba", "General Purpose BD Interchange with MPEG-4\nAVC/H.264 HiP@Level4.1\n(STD-GEN-BD-MPEG4-HPLV41)"); + cmd.addOption("--general-bd-mpeg4-hpbd", "-Pbb", "General Purpose BD Interchange with MPEG-4\nAVC/H.264 BD-Compatible HiP@Level4.1\n(STD-GEN-BD-MPEG4-HPLV41BD)"); + cmd.addOption("--usb-and-flash-jpeg", "-Pfl", "General Purpose USB/Flash Memory Interchange\nwith JPEG (STD-GEN-USB/MMC/CF/SD-JPEG)"); + cmd.addOption("--usb-and-flash-j2k", "-Pf2", "General Purpose USB/Flash Memory Interchange\nwith JPEG 2000 (STD-GEN-USB/MMC/CF/SD-J2K)"); + cmd.addOption("--general-mime", "-Pmi", "General Purpose MIME Interchange\n(STD-GEN-MIME)"); + cmd.addOption("--mpeg2-mpml-dvd", "-Pmp", "DVD Interchange with MPEG2 Main Profile @\nMain Level (STD-DVD-MPEG2-MPML)"); + cmd.addOption("--basic-cardiac", "-Pbc", "Basic Cardiac X-Ray Angiographic Studies on\nCD-R Media (STD-XABC-CD)"); + cmd.addOption("--xray-angiographic", "-Pxa", "1024 X-Ray Angiographic Studies on CD-R Media\n(STD-XA1K-CD)"); + cmd.addOption("--xray-angiographic-dvd", "-Pxd", "1024 X-Ray Angiographic Studies on DVD Media\n(STD-XA1K-DVD)"); + cmd.addOption("--dental-radiograph", "-Pde", "Dental Radiograph Interchange (STD-DEN-CD)"); + cmd.addOption("--ct-and-mr", "-Pcm", "CT/MR Studies (STD-CTMR-xxxx)"); + cmd.addOption("--ultrasound-id-sf", "-Pus", "Ultrasound Single Frame for Image Display\n(STD-US-ID-SF-xxxx)"); + cmd.addOption("--ultrasound-sc-sf", "Ultrasound Single Frame with Spatial\nCalibration (STD-US-SC-SF-xxxx)"); + cmd.addOption("--ultrasound-cc-sf", "Ultrasound Single Frame with Combined\nCalibration (STD-US-CC-SF-xxxx)"); + cmd.addOption("--ultrasound-id-mf", "-Pum", "Ultrasound Single & Multi-Frame for Image\nDisplay (STD-US-ID-MF-xxxx)"); + cmd.addOption("--ultrasound-sc-mf", "Ultrasound Single & Multi-Frame with Spatial\nCalibration (STD-UD-SC-MF-xxxx)"); + cmd.addOption("--ultrasound-cc-mf", "Ultrasound Single & Multi-Frame with Combined\nCalibration (STD-UD-CC-MF-xxxx)"); + cmd.addOption("--12-lead-ecg", "-Pec", "12-lead ECG Interchange on Diskette\n(STD-WVFM-ECG-FD)"); + cmd.addOption("--hemodynamic-waveform", "-Phd", "Hemodynamic Waveform Interchange on Diskette\n(STD-WVFM-HD-FD)"); +#endif + cmd.addSubGroup("writing:"); + cmd.addOption("--replace", "-A", "replace existing DICOMDIR (default)"); + cmd.addOption("--append", "+A", "append to existing DICOMDIR"); + cmd.addOption("--update", "+U", "update existing DICOMDIR"); + cmd.addOption("--discard", "-w", "do not write out DICOMDIR"); + cmd.addSubGroup("backup:"); + cmd.addOption("--create-backup", "create a backup of existing DICOMDIR (def.)"); + cmd.addOption("--no-backup", "-nb", "do not create a backup of existing DICOMDIR"); + cmd.addSubGroup("post-1993 value representations:"); + cmd.addOption("--enable-new-vr", "+u", "enable support for new VRs (UN/UT) (default)"); + cmd.addOption("--disable-new-vr", "-u", "disable support for new VRs, convert to OB"); + cmd.addSubGroup("group length encoding:"); + cmd.addOption("--group-length-remove", "-g", "write without group length elements (default)"); + cmd.addOption("--group-length-create", "+g", "write with group length elements"); + cmd.addSubGroup("length encoding in sequences and items:"); + cmd.addOption("--length-explicit", "+e", "write with explicit lengths (default)"); + cmd.addOption("--length-undefined", "-e", "write with undefined lengths"); + + /* evaluate command line */ + prepareCmdLineArgs(argc, argv, OFFIS_CONSOLE_APPLICATION); + if (app.parseCommandLine(cmd, argc, argv)) + { + /* print help text and exit */ + if (cmd.getArgCount() == 0) + app.printUsage(); + + /* check exclusive options first */ + if (cmd.hasExclusiveOption()) + { + if (cmd.findOption("--version")) + { + app.printHeader(OFTrue /*print host identifier*/); + COUT << OFendl << "External libraries used:"; +#if !defined(WITH_ZLIB) && !defined(BUILD_DCMGPDIR_AS_DCMMKDIR) + COUT << " none" << OFendl; +#else + COUT << OFendl; +#endif +#ifdef WITH_ZLIB + COUT << "- ZLIB, Version " << zlibVersion() << OFendl; +#endif +#ifdef BUILD_DCMGPDIR_AS_DCMMKDIR + COUT << "- " << DiJPEGPlugin::getLibraryVersionString() << OFendl; +#endif + return 0; + } + } + + /* general options */ + OFLog::configureFromCommandLine(cmd, app); + + /* input options */ + if (cmd.findOption("--fileset-id")) + app.checkValue(cmd.getValue(opt_fileset)); + if (cmd.findOption("--descriptor")) + app.checkValue(cmd.getValue(opt_descriptor)); + if (cmd.findOption("--char-set")) + app.checkValue(cmd.getValue(opt_charset)); + + if (cmd.findOption("--input-directory")) + app.checkValue(cmd.getValue(opt_directory)); + + cmd.beginOptionBlock(); + if (cmd.findOption("--keep-filenames")) + ddir.enableMapFilenamesMode(OFFalse); + if (cmd.findOption("--map-filenames")) + ddir.enableMapFilenamesMode(OFTrue); + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--no-recurse")) + opt_recurse = OFFalse; + if (cmd.findOption("--recurse")) + { + opt_recurse = OFTrue; + if (opt_directory.isEmpty()) + opt_directory.set(".", OFTrue /*convert*/); + } + cmd.endOptionBlock(); + +#ifdef PATTERN_MATCHING_AVAILABLE + if (cmd.findOption("--pattern")) + { + app.checkDependence("--pattern", "--recurse", opt_recurse); + app.checkValue(cmd.getValue(opt_pattern)); + } +#endif + + /* processing options */ + cmd.beginOptionBlock(); + if (cmd.findOption("--no-consistency-check")) + ddir.disableConsistencyCheck(); + if (cmd.findOption("--warn-inconsist-files")) + ddir.enableAbortMode(OFFalse); + if (cmd.findOption("--abort-inconsist-file")) + ddir.enableAbortMode(OFTrue); + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--strict")) + ddir.enableInventMode(OFFalse); + if (cmd.findOption("--invent")) + ddir.enableInventMode(OFTrue); + cmd.endOptionBlock(); + + if (cmd.findOption("--invent-patient-id")) + ddir.enableInventPatientIDMode(); + + if (cmd.findOption("--allow-retired-sop")) + ddir.enableRetiredSOPClassSupport(); + if (cmd.findOption("--no-xfer-check")) + ddir.disableTransferSyntaxCheck(); + +#ifdef BUILD_DCMGPDIR_AS_DCMMKDIR + if (cmd.findOption("--no-encoding-check")) + ddir.disableEncodingCheck(); + if (cmd.findOption("--no-resolution-check")) + ddir.disableResolutionCheck(); + if (cmd.findOption("--add-icon-image")) + ddir.enableIconImageMode(); + if (cmd.findOption("--icon-image-size")) + { + OFCmdUnsignedInt iconSize = 0; + app.checkValue(cmd.getValueAndCheckMinMax(iconSize, 1, 128)); + ddir.setIconSize(OFstatic_cast(unsigned int, iconSize)); + } + if (cmd.findOption("--icon-file-prefix")) + { + OFFilename iconPrefix; + app.checkValue(cmd.getValue(iconPrefix)); + ddir.setIconPrefix(iconPrefix); + } + if (cmd.findOption("--default-icon")) + { + OFFilename defaultIcon; + app.checkValue(cmd.getValue(defaultIcon)); + ddir.setDefaultIcon(defaultIcon); + } +#endif + + /* output options */ + if (cmd.findOption("--output-file")) + app.checkValue(cmd.getValue(opt_output)); + +#ifdef BUILD_DCMGPDIR_AS_DCMMKDIR + cmd.beginOptionBlock(); + if (cmd.findOption("--general-purpose")) + opt_profile = DicomDirInterface::AP_GeneralPurpose; + if (cmd.findOption("--general-dvd-jpeg")) + opt_profile = DicomDirInterface::AP_GeneralPurposeDVDJPEG; + if (cmd.findOption("--general-dvd-j2k")) + opt_profile = DicomDirInterface::AP_GeneralPurposeDVDJPEG2000; + if (cmd.findOption("--general-bd-jpeg")) + opt_profile = DicomDirInterface::AP_GeneralPurposeBDJPEG; + if (cmd.findOption("--general-bd-j2k")) + opt_profile = DicomDirInterface::AP_GeneralPurposeBDJPEG2000; + if (cmd.findOption("--general-bd-mpeg2-mpml")) + opt_profile = DicomDirInterface::AP_GeneralPurposeBDMPEG2MPatML; + if (cmd.findOption("--general-bd-mpeg2-mphl")) + opt_profile = DicomDirInterface::AP_GeneralPurposeBDMPEG2MPatHL; + if (cmd.findOption("--general-bd-mpeg4-hp")) + opt_profile = DicomDirInterface::AP_GeneralPurposeBDMPEG4HPatLV41; + if (cmd.findOption("--general-bd-mpeg4-hpbd")) + opt_profile = DicomDirInterface::AP_GeneralPurposeBDMPEG4HPatLV41BD; + if (cmd.findOption("--usb-and-flash-jpeg")) + opt_profile = DicomDirInterface::AP_USBandFlashJPEG; + if (cmd.findOption("--usb-and-flash-j2k")) + opt_profile = DicomDirInterface::AP_USBandFlashJPEG2000; + if (cmd.findOption("--general-mime")) + opt_profile = DicomDirInterface::AP_GeneralPurposeMIME; + if (cmd.findOption("--mpeg2-mpml-dvd")) + opt_profile = DicomDirInterface::AP_MPEG2MPatMLDVD; + if (cmd.findOption("--basic-cardiac")) + opt_profile = DicomDirInterface::AP_BasicCardiac; + if (cmd.findOption("--xray-angiographic")) + opt_profile = DicomDirInterface::AP_XrayAngiographic; + if (cmd.findOption("--xray-angiographic-dvd")) + opt_profile = DicomDirInterface::AP_XrayAngiographicDVD; + if (cmd.findOption("--dental-radiograph")) + opt_profile = DicomDirInterface::AP_DentalRadiograph; + if (cmd.findOption("--ct-and-mr")) + opt_profile = DicomDirInterface::AP_CTandMR; + if (cmd.findOption("--ultrasound-id-sf")) + opt_profile = DicomDirInterface::AP_UltrasoundIDSF; + if (cmd.findOption("--ultrasound-sc-sf")) + opt_profile = DicomDirInterface::AP_UltrasoundSCSF; + if (cmd.findOption("--ultrasound-cc-sf")) + opt_profile = DicomDirInterface::AP_UltrasoundCCSF; + if (cmd.findOption("--ultrasound-id-mf")) + opt_profile = DicomDirInterface::AP_UltrasoundIDMF; + if (cmd.findOption("--ultrasound-sc-mf")) + opt_profile = DicomDirInterface::AP_UltrasoundSCMF; + if (cmd.findOption("--ultrasound-cc-mf")) + opt_profile = DicomDirInterface::AP_UltrasoundCCMF; + if (cmd.findOption("--12-lead-ecg")) + opt_profile = DicomDirInterface::AP_TwelveLeadECG; + if (cmd.findOption("--hemodynamic-waveform")) + opt_profile = DicomDirInterface::AP_HemodynamicWaveform; + cmd.endOptionBlock(); +#endif + + cmd.beginOptionBlock(); + if (cmd.findOption("--replace")) + { + opt_write = OFTrue; + opt_append = OFFalse; + opt_update = OFFalse; + } + if (cmd.findOption("--append")) + { + opt_write = OFTrue; + opt_append = OFTrue; + opt_update = OFFalse; + } + if (cmd.findOption("--update")) + { + opt_write = OFTrue; + opt_append = OFFalse; + opt_update = OFTrue; + } + if (cmd.findOption("--discard")) + { + opt_write = OFFalse; + opt_append = OFFalse; + opt_update = OFFalse; + } + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--create-backup")) + ddir.disableBackupMode(OFTrue); + if (cmd.findOption("--no-backup")) + ddir.disableBackupMode(OFFalse); + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--enable-new-vr")) + dcmEnableGenerationOfNewVRs(); + if (cmd.findOption("--disable-new-vr")) + dcmDisableGenerationOfNewVRs(); + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--group-length-create")) + opt_glenc = EGL_withGL; + if (cmd.findOption("--group-length-remove")) + opt_glenc = EGL_withoutGL; + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--length-explicit")) + opt_enctype = EET_ExplicitLength; + if (cmd.findOption("--length-undefined")) + opt_enctype = EET_UndefinedLength; + cmd.endOptionBlock(); + + /* post check */ + if ((opt_profile == DicomDirInterface::AP_BasicCardiac) || + (opt_profile == DicomDirInterface::AP_XrayAngiographic) || + (opt_profile == DicomDirInterface::AP_CTandMR)) + { + app.checkConflict("--icon-image-size", "--basic-cardiac, --xray-angiographic or --ct-and-mr", cmd.findOption("--icon-image-size")); + } + } + + /* print resource identifier */ + OFLOG_DEBUG(dcmgpdirLogger, rcsid << OFendl); + + /* make sure data dictionary is loaded */ + if (!dcmDataDict.isDictionaryLoaded()) + { + OFLOG_FATAL(dcmgpdirLogger, "no data dictionary loaded, check environment variable: " + << DCM_DICT_ENVIRONMENT_VARIABLE); + return 1; /* DcmDicomDir class dumps core when no data dictionary present */ + } + + /* make sure input directory exists (if specified) */ + if (!opt_directory.isEmpty()) + { + if (!OFStandard::dirExists(opt_directory)) + { + OFLOG_FATAL(dcmgpdirLogger, "specified input directory does not exist"); + return 1; + } + } + + /* create list of input files */ + OFFilename paramValue; + OFFilename pathName; + OFList fileNames; + const int count = cmd.getParamCount(); + if (opt_recurse) + OFLOG_INFO(dcmgpdirLogger, "determining input files ..."); + /* no parameters? */ + if (count == 0) + { + if (opt_recurse) + OFStandard::searchDirectoryRecursively(OFFilename(), fileNames, opt_pattern, opt_directory); + else + app.printError("Missing parameter dcmfile-in"); + } else { + /* iterate over all input filenames */ + for (int i = 1; i <= count; i++) + { + cmd.getParam(i, paramValue); + /* add input directory */ + OFStandard::combineDirAndFilename(pathName, opt_directory, paramValue, OFTrue /*allowEmptyDirName*/); + /* search directory recursively (if required) */ + if (OFStandard::dirExists(pathName)) + { + if (opt_recurse) + OFStandard::searchDirectoryRecursively(paramValue, fileNames, opt_pattern, opt_directory); + else + OFLOG_WARN(dcmgpdirLogger, "ignoring directory because option --recurse is not set: " << paramValue); + } else + fileNames.push_back(paramValue); + } + } + /* check whether there are any input files */ + if (fileNames.empty()) + { + OFLOG_FATAL(dcmgpdirLogger, "no input files: DICOMDIR not created"); + return 1; + } + +#ifdef BUILD_DCMGPDIR_AS_DCMMKDIR + // add image support to DICOMDIR class + DicomDirImageImplementation imagePlugin; + ddir.addImageSupport(&imagePlugin); +#endif + + OFCondition result; + /* create new general purpose DICOMDIR, append to or update existing one */ + if (opt_append) + result = ddir.appendToDicomDir(opt_profile, opt_output); + else if (opt_update) + result = ddir.updateDicomDir(opt_profile, opt_output); + else + result = ddir.createNewDicomDir(opt_profile, opt_output, opt_fileset); + if (result.good()) + { + /* set fileset descriptor and character set */ + result = ddir.setFilesetDescriptor(opt_descriptor, opt_charset); + if (result.good()) + { + /* collect 'bad' files */ + OFList badFiles; + unsigned int goodFiles = 0; + OFListIterator(OFFilename) iter = fileNames.begin(); + OFListIterator(OFFilename) last = fileNames.end(); + /* iterate over all input filenames */ + while ((iter != last) && result.good()) + { + /* add files to the DICOMDIR */ + result = ddir.addDicomFile((*iter), opt_directory); + if (result.bad()) + { + badFiles.push_back(*iter); + if (!ddir.abortMode()) + { + /* ignore inconsistent file, just warn (already done inside "ddir") */ + result = EC_Normal; + } + } else + ++goodFiles; + ++iter; + } + /* evaluate result of file checking/adding procedure */ + if (goodFiles == 0) + { + OFLOG_ERROR(dcmgpdirLogger, "no good files: DICOMDIR not created"); + result = EC_IllegalCall; + } + else if (!badFiles.empty()) + { + OFOStringStream oss; + oss << badFiles.size() << " file(s) cannot be added to DICOMDIR: "; + iter = badFiles.begin(); + last = badFiles.end(); + while (iter != last) + { + oss << OFendl << " " << (*iter); + ++iter; + } + oss << OFStringStream_ends; + OFSTRINGSTREAM_GETSTR(oss, tmpString) + OFLOG_WARN(dcmgpdirLogger, tmpString); + OFSTRINGSTREAM_FREESTR(tmpString) + } + /* write DICOMDIR file */ + if (result.good() && opt_write) + result = ddir.writeDicomDir(opt_enctype, opt_glenc); + } + } + +#ifdef BUILD_DCMGPDIR_AS_DCMMKDIR + // deregister global decompression codecs + DcmRLEDecoderRegistration::cleanup(); + DJDecoderRegistration::cleanup(); + // enable the following lines for JPEG 2000 decompression support +/* + D2DecoderRegistration::cleanup(); + D2JPEG2000Library::cleanup(); +*/ +#endif + +#ifdef DEBUG + dcmDataDict.clear(); /* useful for debugging with dmalloc */ +#endif + + return result.status(); +} diff --git a/dcmdata/apps/dcmodify.cc b/dcmdata/apps/dcmodify.cc new file mode 100644 index 00000000..c3cad29e --- /dev/null +++ b/dcmdata/apps/dcmodify.cc @@ -0,0 +1,40 @@ +/* + * + * Copyright (C) 2003-2010, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Michael Onken + * + * Purpose: Commandline-Application to modify tags in DICOM-Files + * + */ + +#include "dcmtk/config/osconfig.h" // make sure OS specific configuration is included first +#include "mdfconen.h" +#include "dcmtk/dcmdata/dcpath.h" + +#define OFFIS_CONSOLE_APPLICATION "dcmodify" + +static OFLogger dcmodifyLogger = OFLog::getLogger("dcmtk.apps." OFFIS_CONSOLE_APPLICATION); + +int main(int argc, char *argv[]) +{ + int error_count = 0; + MdfConsoleEngine engine(argc, argv, OFFIS_CONSOLE_APPLICATION); + error_count = engine.startProvidingService(); + if (error_count == 1) + OFLOG_ERROR(dcmodifyLogger, "There was 1 error"); + else if (error_count > 1) + OFLOG_ERROR(dcmodifyLogger, "There were " << error_count << " errors"); + return(error_count); +} diff --git a/dcmdata/apps/dump2dcm.cc b/dcmdata/apps/dump2dcm.cc new file mode 100644 index 00000000..16408088 --- /dev/null +++ b/dcmdata/apps/dump2dcm.cc @@ -0,0 +1,1098 @@ +/* + * + * Copyright (C) 1994-2015, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Andreas Barth + * + * Purpose: create a Dicom FileFormat or DataSet from an ASCII-dump + * + */ + +/* + * Input File Description: + * The input file can be an output of dcmdump. One element (tag, VR, value) + * must be written into one line separated by arbitrary spaces or tab characters. + * A '#' begins a comment that ends at the line end. Empty lines are allowed. + * The individual parts of a line have the following syntax: + * Tag: (gggg,eeee) + * with gggg and eeee are 4 character hexadecimal values representing + * group and element tag. Spaces and tabs can be anywhere in a tag + * specification. + * VR: Value Representation must be written as 2 characters as in Part 6 + * of the DICOM standard. No spaces or tabs are allowed between the + * two characters. If the VR can determined from the tag, this part + * of a line is optional. + * Value: There are several rules for writing values: + * 1. US, SS, SL, UL, FD, FL are written as decimal strings that can + * be read by scanf(). + * 2. AT is written as '(gggg,eeee)' with additional spaces stripped + * off automatically and gggg and eeee being decimal strings that + * can be read by scanf(). + * 3. OB and OW values are written as byte or word hexadecimal values + * separated by '\' character. Alternatively, OB or OW values can + * be read from a separate file by writing the filename prefixed + * by a '=' character (e.g. '=largepix.dat'). The contents of the + * file will be read as is. By default, OW data is expected to be + * little endian ordered and will be swapped if necessary. No + * checks will be made to ensure that the amount of data is + * reasonable in terms of other attributes such as Rows or Columns. + * In case of compressed pixel data, the line should start with + * '(7fe0,0010) OB (PixelSequence' in order to distinguish from + * uncompressed pixel data. + * 4. UI is written as '=Name' in data dictionary or as unique + * identifier string (see 6.) , e.g. '[1.2.840.....]' + * 5. Strings without () <> [] spaces, tabs and # can be written + * directly. + * 6. Other strings must be surrounded by '[' and ']'. No bracket + * structure is passed. The value ends at the last ']' in the + * line. Anything after the ']' is interpreted as comment. + * 7. '(' and '<' are interpreted special and may not be used when + * writing an input file by hand as beginning characters of a + * string. Multiple Value are separated by '\'. The sequence of + * lines must not be ordered but they can. References in DICOM + * Directories are not supported. Semantic errors are not detected. + * + * Examples: + * (0008,0020) DA [19921012] # 8, 1 StudyDate + * (0008,0016) UI =MRImageStorage # 26, 1 SOPClassUID + * (0002,0012) UI [1.2.276.0.7230010.100.1.1] + * (0020,0032) DS [0.0\0.0] # 8, 2 ImagePositionPatient + * (0028,0009) AT (3004,000c) # 4, 1 FrameIncrementPointer + * (0028,0010) US 256 # 4, 1 Rows + * (0002,0001) OB 01\00 + * + */ + +#include "dcmtk/config/osconfig.h" + +// if defined, use createValueFromTempFile() for large binary data files +//#define EXPERIMENTAL_READ_FROM_FILE + +#define INCLUDE_CSTDLIB +#define INCLUDE_CSTDIO +#define INCLUDE_CCTYPE +#include "dcmtk/ofstd/ofstdinc.h" + +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_GUSI_H +#include +#endif + +#include "dcmtk/ofstd/ofstd.h" +#include "dcmtk/ofstd/ofconapp.h" +#include "dcmtk/ofstd/ofstream.h" +#include "dcmtk/dcmdata/dctk.h" +#include "dcmtk/dcmdata/dcpxitem.h" +#include "dcmtk/dcmdata/cmdlnarg.h" +#include "dcmtk/dcmdata/dcuid.h" /* for dcmtk version name */ +#include "dcmtk/dcmdata/dcostrmz.h" /* for dcmZlibCompressionLevel */ + +#ifdef EXPERIMENTAL_READ_FROM_FILE +#include "dcmtk/dcmdata/dcistrmf.h" /* for class DcmInputFileStream */ +#endif + +#ifdef WITH_ZLIB +#include /* for zlibVersion() */ +#endif + +#define OFFIS_CONSOLE_APPLICATION "dump2dcm" + +static OFLogger dump2dcmLogger = OFLog::getLogger("dcmtk.apps." OFFIS_CONSOLE_APPLICATION); + +static char rcsid[] = "$dcmtk: " OFFIS_CONSOLE_APPLICATION " v" + OFFIS_DCMTK_VERSION " " OFFIS_DCMTK_RELEASEDATE " $"; + +#define SHORTCOL 3 +#define LONGCOL 21 + +// Maximum Line Size (default) + +const unsigned int DCM_DumpMaxLineSize = 4096; + +// Global variables + +static E_ByteOrder opt_fileContentsByteOrdering = EBO_LittleEndian; + +// Field definition separators + +#define DCM_DumpCommentChar '#' +#define DCM_DumpTagDelim ')' +#define DCM_DumpOpenString '[' +#define DCM_DumpCloseString ']' +#define DCM_DumpOpenDescription '(' +#define DCM_DumpOpenFile '<' +#define DCM_DumpCloseFile '>' + +#define TO_UCHAR(s) OFstatic_cast(unsigned char, (s)) +static void +stripWhitespace(char *s) +{ + char *p; + + if (s == NULL) return; + + p = s; + while (*s != '\0') { + if (isspace(TO_UCHAR(*s)) == OFFalse) { + *p++ = *s; + } + s++; + } + *p = '\0'; +} + +static char * +stripTrailingWhitespace(char *s) +{ + if (s == NULL) return s; + for (size_t i = strlen(s); i > 0 && isspace(TO_UCHAR(s[--i])); s[i] = '\0'); + return s; +} + + +static char * +stripPrecedingWhitespace(char *s) +{ + char *p; + if (s == NULL) return s; + + for(p = s; *p && isspace(TO_UCHAR(*p)); p++) + ; + + return p; +} + +static OFBool +onlyWhitespace(const char *s) +{ + while(*s) if (!isspace(TO_UCHAR(*s++))) + return OFFalse; + return OFTrue; +} + +static char * +getLine(char *line, int maxLineLen, FILE *f, const unsigned long lineNumber) +{ + char *s; + + s = fgets(line, maxLineLen, f); + + // if line is too long, throw rest of it away + if (s && strlen(s) == size_t(maxLineLen - 1) && s[maxLineLen - 2] != '\n') + { + int c = fgetc(f); + while(c != '\n' && c != EOF) + c = fgetc(f); + OFLOG_ERROR(dump2dcmLogger, "line " << lineNumber << " too long"); + } + + /* strip any trailing white space */ + stripTrailingWhitespace(s); + + return s; +} + +static OFBool +isaCommentLine(const char *s) +{ + // skip leading spaces + while(isspace(TO_UCHAR(*s))) ++s; + return *s == DCM_DumpCommentChar; +} + +static OFBool +parseTag(char *&s, DcmTagKey &key) +{ + OFBool ok = OFTrue; + char *p; + unsigned int g, e; + + // find tag begin + p = strchr(s, DCM_DumpTagDelim); + if (p) + { + // string all white spaces and read tag + size_t len = p - s + 1; + p = new char[len + 1]; + OFStandard::strlcpy(p, s, len + 1); + stripWhitespace(p); + s += len; + + if (sscanf(p, "(%x,%x)", &g, &e) == 2) + key.set(OFstatic_cast(Uint16, g), OFstatic_cast(Uint16, e)); + else + ok = OFFalse; + delete[] p; + } + else ok = OFFalse; + + return ok; +} + + +static OFBool +parseVR(char *&s, DcmEVR &vr) +{ + OFBool ok = OFTrue; + + s = stripPrecedingWhitespace(s); + + // Are there two upper characters? + if (isupper(TO_UCHAR(*s)) && isupper(TO_UCHAR(*(s + 1)))) + { + char c_vr[3]; + OFStandard::strlcpy(c_vr, s, 3); + // Convert to VR + DcmVR dcmVR(c_vr); + vr = dcmVR.getEVR(); + s += 2; + } + else if ((*s == 'p') && (*(s + 1) == 'i')) + { + vr = EVR_pixelItem; + s += 2; + } + else if (((*s == 'o') && (*(s + 1) == 'x')) || + ((*s == 'x') && (*(s + 1) == 's')) || + ((*s == 'n') && (*(s + 1) == 'a')) || + ((*s == 'u') && (*(s + 1) == 'p'))) + { + // swallow internal VRs + vr = EVR_UNKNOWN; + s += 2; + } + else ok = OFFalse; + + return ok; +} +#undef TO_UCHAR + + +static size_t +searchLastClose(char *s, const char closeChar) +{ + // search last close bracket in a line + // no bracket structure will be considered + + char *found = NULL; + char *p = s; + + while(p && *p) + { + p = strchr(p, closeChar); + if (p) + { + found = p; + p++; + } + } + + if (found) + return (found - s) + 1; + else + return 0; +} + + +static size_t +searchCommentOrEol(char *s) +{ + char *comment = strchr(s, DCM_DumpCommentChar); + if (comment) + return comment - s; + else if (s) + return strlen(s); + else + return 0; +} + + +static void +convertNewlineCharacters(char *s) +{ + // convert the string "\n" into the \r\n combination required by DICOM + if (s) for (; *s; ++s) if (*s == '\\' && *(s+1) == 'n') + { + *s = '\r'; + *++s = '\n'; + } +} + +static OFBool +parseValue(char *&s, char *&value, DcmEVR &vr, const DcmTagKey &tagkey) +{ + OFBool ok = OFTrue; + size_t len; + value = NULL; + + s = stripPrecedingWhitespace(s); + + switch (*s) + { + case DCM_DumpOpenString: + len = searchLastClose(s, DCM_DumpCloseString); + if (len == 0) + ok = OFFalse; + else if (len > 2) + { + value = new char[len - 1]; + OFStandard::strlcpy(value, s + 1, len - 1); + convertNewlineCharacters(value); + } + else + value = NULL; + break; + + case DCM_DumpOpenDescription: + /* need to distinguish VR=AT from description field */ + /* NB: if the VR is unknown this workaround will not succeed */ + if (vr == EVR_AT) + { + len = searchLastClose(s, DCM_DumpTagDelim); + if (len >= 11) // (gggg,eeee) allow non-significant spaces + { + char *pv = s; + DcmTagKey tag; + if (parseTag(pv, tag)) // check for valid tag format + { + value = new char[len + 1]; + OFStandard::strlcpy(value, s, len + 1); + stripWhitespace(value); + } else + ok = OFFalse; // skip description + } + else + ok = OFFalse; // skip description + } + /* need to distinguish pixel sequence */ + else if ((tagkey == DCM_PixelData) && (vr == EVR_OB)) + { + if (strncmp(s + 1, "PixelSequence", 13) == 0) + vr = EVR_pixelSQ; + } + break; + + case DCM_DumpOpenFile: + ok = OFFalse; // currently not supported + break; + + case DCM_DumpCommentChar: + break; + + default: + len = searchCommentOrEol(s); + if (len) + { + value = new char[len + 1]; + OFStandard::strlcpy(value, s, len + 1); + stripTrailingWhitespace(value); + } + break; + } + return ok; +} + +static OFCondition +putFileContentsIntoElement(DcmElement *elem, const char *filename) +{ + OFCondition ec = EC_Normal; +#ifdef EXPERIMENTAL_READ_FROM_FILE + /* create stream object for binary file */ + DcmInputFileStream fileStream(filename); + ec = fileStream.status(); + if (ec.good()) + { + /* NB: if size is odd file will be rejected */ + const size_t fileLen = OFStandard::getFileSize(filename); + /* read element value from binary file (requires even length) */ + ec = elem->createValueFromTempFile(fileStream.newFactory(), fileLen, EBO_LittleEndian); + if (ec.bad()) + OFLOG_ERROR(dump2dcmLogger, "cannot process binary data file: " << filename); + } else { + OFLOG_ERROR(dump2dcmLogger, "cannot open binary data file: " << filename); + ec = EC_InvalidTag; + } +#else + FILE *f = NULL; + if ((f = fopen(filename, "rb")) == NULL) + { + OFLOG_ERROR(dump2dcmLogger, "cannot open binary data file: " << filename); + return EC_InvalidTag; + } + + const size_t len = OFStandard::getFileSize(filename); + size_t buflen = len; + if (buflen & 1) + buflen++; /* if odd then make even (DICOM requires even length values) */ + + Uint8 *buf = NULL; + const DcmEVR evr = elem->getVR(); + /* create buffer of OB or OW data */ + if (evr == EVR_OB || evr == EVR_pixelItem) + ec = elem->createUint8Array(OFstatic_cast(Uint32, buflen), buf); + else if (evr == EVR_OW) + { + Uint16 *buf16 = NULL; + ec = elem->createUint16Array(OFstatic_cast(Uint32, buflen / 2), buf16); + buf = OFreinterpret_cast(Uint8 *, buf16); + } else + ec = EC_IllegalCall; + if (ec.good()) + { + /* read binary file into the buffer */ + if (fread(buf, 1, len, f) != len) + { + char errBuf[256]; + OFLOG_ERROR(dump2dcmLogger, "error reading binary data file: " << filename + << ": " << OFStandard::strerror(errno, errBuf, sizeof(errBuf))); + ec = EC_CorruptedData; + } + else if (evr == EVR_OW) + { + /* swap 16 bit OW data (if necessary) */ + swapIfNecessary(gLocalByteOrder, opt_fileContentsByteOrdering, buf, OFstatic_cast(Uint32, buflen), sizeof(Uint16)); + } + } + else if (ec == EC_MemoryExhausted) + OFLOG_ERROR(dump2dcmLogger, "out of memory reading binary data file: " << filename); + else + OFLOG_ERROR(dump2dcmLogger, "illegal call processing binary data file: " << filename); + + fclose(f); +#endif + return ec; +} + +static OFCondition +insertIntoSet(DcmStack &stack, const E_TransferSyntax xfer, const DcmTagKey &tagkey, + const DcmEVR &vr, const char *value) +{ + // insert new element into dataset or metaheader + + OFCondition l_error = EC_Normal; + OFCondition newElementError = EC_Normal; + + if (stack.empty()) + l_error = EC_CorruptedData; + + if (l_error == EC_Normal) + { + DcmElement *newElement = NULL; + DcmObject *topOfStack = stack.top(); + + // convert tagkey to tag including VR + DcmTag tag(tagkey); + DcmVR dcmvr(vr); + + const DcmEVR tagvr = tag.getEVR(); + /* check VR and consider various special cases */ + if (tagvr != vr && vr != EVR_UNKNOWN && tagvr != EVR_UNKNOWN && + (tagkey != DCM_LUTData || (vr != EVR_US && vr != EVR_SS && vr != EVR_OW)) && + (tagkey != DCM_PixelData || (vr != EVR_OB && vr != EVR_OW && vr != EVR_pixelSQ)) && + (tagvr != EVR_xs || (vr != EVR_US && vr != EVR_SS)) && + (tagvr != EVR_ox || (vr != EVR_OB && vr != EVR_OW)) && + (tagvr != EVR_na || vr != EVR_pixelItem)) + { + OFLOG_WARN(dump2dcmLogger, "Tag " << tag << " with wrong VR '" + << dcmvr.getVRName() << "' found, correct is '" + << tag.getVR().getVRName() << "'"); + } + else if ((tagvr == EVR_UNKNOWN) && (vr == EVR_UNKNOWN)) + { + OFLOG_WARN(dump2dcmLogger, "VR of Tag " << tag << " is unknown, " + << "using 'UN' for this data element"); + } + + if (vr != EVR_UNKNOWN) + tag.setVR(dcmvr); + const DcmEVR newTagVR = tag.getEVR(); + + // create new element (special handling for pixel sequence and item) + if (newTagVR == EVR_pixelSQ) + newElement = new DcmPixelData(tag); + else if (newTagVR == EVR_pixelItem) + newElement = new DcmPixelItem(DCM_PixelItemTag); + else + newElementError = newDicomElement(newElement, tag); + + if (newElementError == EC_Normal) + { + // tag describes an element + if (!newElement) + { + // Tag was ambiguous - should never happen according to the current implementation of newDicomElement() + l_error = EC_InvalidVR; + } + else + { + // check for uncompressed pixel data (i.e. no pixel sequence present) + if (tagkey == DCM_PixelData && (newTagVR == EVR_OB || newTagVR == EVR_OW)) + OFstatic_cast(DcmPixelData *, newElement)->setNonEncapsulationFlag(OFTrue /*alwaysUnencapsulated*/); + // fill value + if (value) + { + if (value[0] == '=' && (newTagVR == EVR_OB || newTagVR == EVR_OW || newTagVR == EVR_pixelItem)) + { + /* + * Special case handling for OB, OW and pixel item data. + * Allow a value beginning with a '=' character to represent + * a file containing data to be used as the attribute value. + * A '=' character is not a normal value since OB and OW values + * must be written as multivalued hexadecimal (e.g. "00\ff\0d\8f"); + */ + l_error = putFileContentsIntoElement(newElement, value + 1); + } else { + l_error = newElement->putString(value); + } + } + + // insert element into hierarchy + if (l_error == EC_Normal) + { + switch(topOfStack->ident()) + { + case EVR_item: + case EVR_dirRecord: + case EVR_dataset: + case EVR_metainfo: + { + DcmItem *item = OFstatic_cast(DcmItem *, topOfStack); + item->insert(newElement); + // special handling for pixel sequence + if (newTagVR == EVR_pixelSQ) + { + DcmPixelSequence *pixelSeq = new DcmPixelSequence(DCM_PixelSequenceTag); + if (pixelSeq != NULL) + { + OFstatic_cast(DcmPixelData *, newElement)->putOriginalRepresentation(xfer, NULL, pixelSeq); + stack.push(pixelSeq); + } + } + else if (newElement->ident() == EVR_SQ) + stack.push(newElement); + } + break; + case EVR_pixelSQ: + if (newTagVR == EVR_pixelItem) + { + DcmPixelSequence *pixelSeq = OFstatic_cast(DcmPixelSequence *, topOfStack); + pixelSeq->insert(OFstatic_cast(DcmPixelItem *, newElement)); + } else + l_error = EC_InvalidTag; + break; + default: + l_error = EC_InvalidTag; + break; + } + } + } + } + else if (newElementError == EC_SequEnd) + { + // pop stack if stack object was a sequence + if (topOfStack->ident() == EVR_SQ || topOfStack->ident() == EVR_pixelSQ) + stack.pop(); + else + l_error = EC_InvalidTag; + } + else if (newElementError == EC_ItemEnd) + { + // pop stack if stack object was an item + switch (topOfStack->ident()) + { + case EVR_item: + case EVR_dirRecord: + case EVR_dataset: + case EVR_metainfo: + stack.pop(); + break; + + default: + l_error = EC_InvalidTag; + break; + } + } + else if (newElementError == EC_InvalidTag) + { + if (tag.getXTag() == DCM_Item) + { + DcmItem *item = NULL; + if (topOfStack->getTag().getXTag() == DCM_DirectoryRecordSequence) + { + // an Item must be pushed to the stack + item = new DcmDirectoryRecord(tag, 0); + OFstatic_cast(DcmSequenceOfItems *, topOfStack)->insert(item); + stack.push(item); + } + else if (topOfStack->ident() == EVR_SQ) + { + // an item must be pushed to the stack + item = new DcmItem(tag); + OFstatic_cast(DcmSequenceOfItems *, topOfStack)->insert(item); + stack.push(item); + } + else + l_error = EC_InvalidTag; + } + else + l_error = EC_InvalidTag; + } + else + l_error = EC_InvalidTag; + } + + return l_error; +} + +static OFBool +readDumpFile(DcmMetaInfo *metaheader, DcmDataset *dataset, + FILE *infile, const char *ifname, E_TransferSyntax &xfer, + const OFBool stopOnErrors, const unsigned long maxLineLength) +{ + char *lineBuf = new char[maxLineLength]; + int lineNumber = 0; + OFBool errorOnThisLine = OFFalse; + char *parse = NULL; + char *value = NULL; + DcmEVR vr = EVR_UNKNOWN; + int errorsEncountered = 0; + DcmTagKey tagkey; + DcmStack metaheaderStack; + DcmStack datasetStack; + xfer = EXS_Unknown; + + if (metaheader) + metaheaderStack.push(metaheader); + + datasetStack.push(dataset); + + while (getLine(lineBuf, OFstatic_cast(int, maxLineLength), infile, lineNumber + 1)) + { + lineNumber++; + + OFLOG_TRACE(dump2dcmLogger, "processing line " << lineNumber << " of the input file"); + + // ignore empty lines and comment lines + if (onlyWhitespace(lineBuf)) + continue; + if (isaCommentLine(lineBuf)) + continue; + + errorOnThisLine = OFFalse; + + parse = &lineBuf[0]; + + // parse tag an the line + if (!parseTag(parse, tagkey)) + { + OFLOG_ERROR(dump2dcmLogger, OFFIS_CONSOLE_APPLICATION ": "<< ifname << ": " + << "no Tag found (line " << lineNumber << ")"); + errorOnThisLine = OFTrue; + } + + // parse optional VR + if (!errorOnThisLine && !parseVR(parse, vr)) + vr = EVR_UNKNOWN; + + // parse optional value + if (!errorOnThisLine && !parseValue(parse, value, vr, tagkey)) + { + OFLOG_ERROR(dump2dcmLogger, OFFIS_CONSOLE_APPLICATION ": "<< ifname << ": " + << "incorrect value specification (line " << lineNumber << ")"); + errorOnThisLine = OFTrue; + } + + + // insert new element that consists of tag, VR, and value + if (!errorOnThisLine) + { + OFCondition l_error = EC_Normal; + if (tagkey.getGroup() == 0x0002) + { + if (metaheader) + { + l_error = insertIntoSet(metaheaderStack, xfer, tagkey, vr, value); + // check for transfer syntax in meta-header + if ((tagkey == DCM_TransferSyntaxUID) && (xfer == EXS_Unknown)) + { + const char *xferUID; + // use resolved value (UID) + if (metaheader->findAndGetString(DCM_TransferSyntaxUID, xferUID).good()) + xfer = DcmXfer(xferUID).getXfer(); + } + } + } + else + l_error = insertIntoSet(datasetStack, xfer, tagkey, vr, value); + + if (value) + { + delete[] value; + value = NULL; + } + if (l_error != EC_Normal) + { + errorOnThisLine = OFTrue; + OFLOG_ERROR(dump2dcmLogger, OFFIS_CONSOLE_APPLICATION ": " << ifname << ": Error in creating Element: " + << l_error.text() << " (line " << lineNumber << ")"); + } + + } + + if (errorOnThisLine) + errorsEncountered++; + } + + + // test blocking structure + if (metaheader && metaheaderStack.card() != 1) + { + OFLOG_ERROR(dump2dcmLogger, OFFIS_CONSOLE_APPLICATION ": " << ifname << ": Block Error in metaheader"); + errorsEncountered++; + } + + if (datasetStack.card() != 1) + { + OFLOG_ERROR(dump2dcmLogger, OFFIS_CONSOLE_APPLICATION ": " << ifname << ": Block Error in dataset"); + errorsEncountered++; + } + + delete[] lineBuf; + + if (errorsEncountered) + { + OFLOG_ERROR(dump2dcmLogger, errorsEncountered << " Errors found in " << ifname); + return !stopOnErrors; + } + else + return OFTrue; +} + +// ******************************************** + +int main(int argc, char *argv[]) +{ +#ifdef HAVE_GUSI_H + GUSISetup(GUSIwithSIOUXSockets); + GUSISetup(GUSIwithInternetSockets); +#endif + + OFConsoleApplication app(OFFIS_CONSOLE_APPLICATION , "Convert ASCII dump to DICOM file", rcsid); + OFCommandLine cmd; + + cmd.setOptionColumns(LONGCOL, SHORTCOL); + cmd.setParamColumn(LONGCOL + SHORTCOL + 4); + + cmd.addParam("dumpfile-in", "dump input filename"); + cmd.addParam("dcmfile-out", "DICOM output filename"); + + cmd.addGroup("general options:", LONGCOL, SHORTCOL + 2); + cmd.addOption("--help", "-h", "print this help text and exit", OFCommandLine::AF_Exclusive); + cmd.addOption("--version", "print version information and exit", OFCommandLine::AF_Exclusive); + OFLog::addOptions(cmd); + + cmd.addGroup("input options:", LONGCOL, SHORTCOL + 2); + cmd.addSubGroup("input file format:"); + cmd.addOption("--read-meta-info", "+f", "read meta information if present (default)"); + cmd.addOption("--ignore-meta-info", "-f", "ignore file meta information"); + cmd.addSubGroup("file contents byte ordering:"); + cmd.addOption("--read-file-little", "+rl", "read OW data with little endian (default)"); + cmd.addOption("--read-file-big", "+rb", "read OW data from file with big endian"); + cmd.addSubGroup("other input options:"); + cmd.addOption("--line", "+l", 1, "[m]ax-length: integer", + "maximum line length m (default: 4096)"); + + cmd.addGroup("processing options:"); + cmd.addSubGroup("unique identifiers:"); + cmd.addOption("--generate-new-uids", "+Ug", "generate new Study/Series/SOP Instance UID"); + cmd.addOption("--dont-overwrite-uids", "-Uo", "do not overwrite existing UIDs (default)"); + cmd.addOption("--overwrite-uids", "+Uo", "overwrite existing UIDs"); + + cmd.addGroup("output options:"); + cmd.addSubGroup("output file format:"); + cmd.addOption("--write-file", "+F", "write file format (default)"); + cmd.addOption("--write-dataset", "-F", "write data set without file meta information"); + cmd.addOption("--update-meta-info", "+Fu", "update particular file meta information"); + cmd.addSubGroup("output transfer syntax:"); + cmd.addOption("--write-xfer-same", "+t=", "write with same TS as input (default)"); + cmd.addOption("--write-xfer-little", "+te", "write with explicit VR little endian"); + cmd.addOption("--write-xfer-big", "+tb", "write with explicit VR big endian TS"); + cmd.addOption("--write-xfer-implicit", "+ti", "write with implicit VR little endian TS"); +#ifdef WITH_ZLIB + cmd.addOption("--write-xfer-deflated", "+td", "write with deflated expl. VR little endian TS"); +#endif + cmd.addSubGroup("error handling:"); + cmd.addOption("--stop-on-error", "-E", "do not write if dump is damaged (default)"); + cmd.addOption("--ignore-errors", "+E", "attempt to write even if dump is damaged"); + cmd.addSubGroup("post-1993 value representations:"); + cmd.addOption("--enable-new-vr", "+u", "enable support for new VRs (UN/UT) (default)"); + cmd.addOption("--disable-new-vr", "-u", "disable support for new VRs, convert to OB"); + cmd.addSubGroup("group length encoding:"); + cmd.addOption("--group-length-recalc", "+g=", "recalculate group lengths if present (default)"); + cmd.addOption("--group-length-create", "+g", "always write with group length elements"); + cmd.addOption("--group-length-remove", "-g", "always write without group length elements"); + cmd.addSubGroup("length encoding in sequences and items:"); + cmd.addOption("--length-explicit", "+e", "write with explicit lengths (default)"); + cmd.addOption("--length-undefined", "-e", "write with undefined lengths"); + cmd.addSubGroup("data set trailing padding (not with --write-dataset):"); + cmd.addOption("--padding-retain", "-p=", "do not change padding (default)"); + cmd.addOption("--padding-off", "-p", "no padding (implicit if --write-dataset)"); + cmd.addOption("--padding-create", "+p", 2, "[f]ile-pad [i]tem-pad: integer", + "align file on multiple of f bytes\nand items on multiple of i bytes"); +#ifdef WITH_ZLIB + cmd.addSubGroup("deflate compression level (only with --write-xfer-deflated):"); + cmd.addOption("--compression-level", "+cl", 1, "[l]evel: integer (default: 6)", + "0=uncompressed, 1=fastest, 9=best compression"); +#endif + + const char *opt_ifname = NULL; + const char *opt_ofname = NULL; + E_TransferSyntax opt_xfer = EXS_Unknown; + E_EncodingType opt_enctype = EET_ExplicitLength; + E_GrpLenEncoding opt_glenc = EGL_recalcGL; + E_PaddingEncoding opt_padenc = EPD_withoutPadding; + E_FileWriteMode opt_writeMode = EWM_fileformat; + OFCmdUnsignedInt opt_filepad = 0; + OFCmdUnsignedInt opt_itempad = 0; + OFCmdUnsignedInt opt_linelength = DCM_DumpMaxLineSize; + OFBool opt_stopOnErrors = OFTrue; + OFBool opt_metaInfo = OFTrue; + OFBool opt_generateUIDs = OFFalse; + OFBool opt_overwriteUIDs = OFFalse; + + /* evaluate command line */ + prepareCmdLineArgs(argc, argv, OFFIS_CONSOLE_APPLICATION); + if (app.parseCommandLine(cmd, argc, argv)) + { + /* check exclusive options first */ + if (cmd.hasExclusiveOption()) + { + if (cmd.findOption("--version")) + { + app.printHeader(OFTrue /*print host identifier*/); + COUT << OFendl << "External libraries used:"; +#ifdef WITH_ZLIB + COUT << OFendl << "- ZLIB, Version " << zlibVersion() << OFendl; +#else + COUT << " none" << OFendl; +#endif + return 0; + } + } + + /* command line parameters */ + + cmd.getParam(1, opt_ifname); + cmd.getParam(2, opt_ofname); + + OFLog::configureFromCommandLine(cmd, app); + + /* input options */ + + cmd.beginOptionBlock(); + if (cmd.findOption("--read-meta-info")) opt_metaInfo = OFTrue; + if (cmd.findOption("--ignore-meta-info")) opt_metaInfo = OFFalse; + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--read-file-little")) opt_fileContentsByteOrdering = EBO_LittleEndian; + if (cmd.findOption("--read-file-big")) opt_fileContentsByteOrdering = EBO_BigEndian; + cmd.endOptionBlock(); + + if (cmd.findOption("--line")) + app.checkValue(cmd.getValueAndCheckMin(opt_linelength, 80)); + + /* processing options */ + + if (cmd.findOption("--generate-new-uids")) opt_generateUIDs = OFTrue; + + cmd.beginOptionBlock(); + if (cmd.findOption("--dont-overwrite-uids")) opt_overwriteUIDs = OFFalse; + if (cmd.findOption("--overwrite-uids")) opt_overwriteUIDs = OFTrue; + cmd.endOptionBlock(); + + /* output options */ + + cmd.beginOptionBlock(); + if (cmd.findOption("--write-file")) opt_writeMode = EWM_fileformat; + if (cmd.findOption("--write-dataset")) opt_writeMode = EWM_dataset; + cmd.endOptionBlock(); + + if (cmd.findOption("--update-meta-info")) + { + app.checkConflict("--update-meta-info", "--write-dataset", opt_writeMode == EWM_dataset); + opt_writeMode = EWM_updateMeta; + } + + cmd.beginOptionBlock(); + if (cmd.findOption("--write-xfer-same")) opt_xfer = EXS_Unknown;; + if (cmd.findOption("--write-xfer-little")) opt_xfer = EXS_LittleEndianExplicit; + if (cmd.findOption("--write-xfer-big")) opt_xfer = EXS_BigEndianExplicit; + if (cmd.findOption("--write-xfer-implicit")) opt_xfer = EXS_LittleEndianImplicit; +#ifdef WITH_ZLIB + if (cmd.findOption("--write-xfer-deflated")) opt_xfer = EXS_DeflatedLittleEndianExplicit; +#endif + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--stop-on-error")) opt_stopOnErrors = OFTrue; + if (cmd.findOption("--ignore-errors")) opt_stopOnErrors = OFFalse; + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--enable-new-vr")) dcmEnableGenerationOfNewVRs(); + if (cmd.findOption("--disable-new-vr")) dcmDisableGenerationOfNewVRs(); + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--group-length-recalc")) opt_glenc = EGL_recalcGL; + if (cmd.findOption("--group-length-create")) opt_glenc = EGL_withGL; + if (cmd.findOption("--group-length-remove")) opt_glenc = EGL_withoutGL; + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--length-explicit")) opt_enctype = EET_ExplicitLength; + if (cmd.findOption("--length-undefined")) opt_enctype = EET_UndefinedLength; + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--padding-retain")) + { + app.checkConflict("--padding-retain", "--write-dataset", opt_writeMode == EWM_dataset); + opt_padenc = EPD_noChange; + } + if (cmd.findOption("--padding-off")) opt_padenc = EPD_withoutPadding; + if (cmd.findOption("--padding-create")) + { + app.checkConflict("--padding-create", "--write-dataset", opt_writeMode == EWM_dataset); + app.checkValue(cmd.getValueAndCheckMin(opt_filepad, 0)); + app.checkValue(cmd.getValueAndCheckMin(opt_itempad, 0)); + opt_padenc = EPD_withPadding; + } + cmd.endOptionBlock(); + +#ifdef WITH_ZLIB + if (cmd.findOption("--compression-level")) + { + OFCmdUnsignedInt comprLevel = 0; + app.checkDependence("--compression-level", "--write-xfer-deflated", opt_xfer == EXS_DeflatedLittleEndianExplicit); + app.checkValue(cmd.getValueAndCheckMinMax(comprLevel, 0, 9)); + dcmZlibCompressionLevel.set(OFstatic_cast(int, comprLevel)); + } +#endif + } + + /* print resource identifier */ + OFLOG_DEBUG(dump2dcmLogger, rcsid << OFendl); + + DcmFileFormat fileformat; + DcmMetaInfo *metaheader = (opt_metaInfo) ? fileformat.getMetaInfo() : NULL; + DcmDataset *dataset = fileformat.getDataset(); + + /* make sure data dictionary is loaded */ + if (!dcmDataDict.isDictionaryLoaded()) + { + OFLOG_WARN(dump2dcmLogger, "no data dictionary loaded, check environment variable: " + << DCM_DICT_ENVIRONMENT_VARIABLE); + } + + // open input dump file + if ((opt_ifname == NULL) || (strlen(opt_ifname) == 0)) + { + OFLOG_FATAL(dump2dcmLogger, "invalid input filename: "); + return 1; + } + OFLOG_INFO(dump2dcmLogger, "reading dump file: " << opt_ifname); + + FILE *dumpfile = fopen(opt_ifname, "r"); + if (!dumpfile) + { + OFLOG_FATAL(dump2dcmLogger, "input file does not exist: " << opt_ifname); + return 1; + } + + int status = 0; + E_TransferSyntax xfer; + // read dump file into metaheader and dataset + if (readDumpFile(metaheader, dataset, dumpfile, opt_ifname, xfer, opt_stopOnErrors, + OFstatic_cast(unsigned long, opt_linelength))) + { + /* generate new UIDs (if required) */ + if (opt_generateUIDs) + { + char uid[100]; + if (opt_overwriteUIDs || !dataset->tagExistsWithValue(DCM_StudyInstanceUID)) + { + OFLOG_INFO(dump2dcmLogger, "generating new Study Instance UID"); + dataset->putAndInsertString(DCM_StudyInstanceUID, dcmGenerateUniqueIdentifier(uid, SITE_STUDY_UID_ROOT)); + } + if (opt_overwriteUIDs || !dataset->tagExistsWithValue(DCM_SeriesInstanceUID)) + { + OFLOG_INFO(dump2dcmLogger, "generating new Series Instance UID"); + dataset->putAndInsertString(DCM_SeriesInstanceUID, dcmGenerateUniqueIdentifier(uid, SITE_SERIES_UID_ROOT)); + } + if (opt_overwriteUIDs || !dataset->tagExistsWithValue(DCM_SOPInstanceUID)) + { + OFLOG_INFO(dump2dcmLogger, "generating new SOP Instance UID"); + dataset->putAndInsertString(DCM_SOPInstanceUID, dcmGenerateUniqueIdentifier(uid, SITE_INSTANCE_UID_ROOT)); + /* make sure that the file meta information is updated correspondingly */ + if (opt_writeMode == EWM_fileformat) + opt_writeMode = EWM_updateMeta; + } + } + + // write into file format or dataset + OFLOG_INFO(dump2dcmLogger, "writing DICOM file"); + + /* determine transfer syntax to write the file */ + if (opt_xfer == EXS_Unknown) + { + opt_xfer = xfer; + /* check whether output xfer is still unknown */ + if (opt_xfer == EXS_Unknown) + { + OFLOG_WARN(dump2dcmLogger, "output transfer syntax unknown, assuming --write-xfer-little"); + opt_xfer = EXS_LittleEndianExplicit; + } + } + /* check whether it is possible to write the file */ + if (fileformat.canWriteXfer(opt_xfer)) + { + /* check whether pixel data is compressed */ + if ((opt_writeMode == EWM_dataset) && DcmXfer(xfer).isEncapsulated()) + { + OFLOG_WARN(dump2dcmLogger, "encapsulated pixel data require file format, ignoring --write-dataset"); + opt_writeMode = EWM_fileformat; + } + OFCondition l_error = fileformat.saveFile(opt_ofname, opt_xfer, opt_enctype, opt_glenc, opt_padenc, + OFstatic_cast(Uint32, opt_filepad), OFstatic_cast(Uint32, opt_itempad), opt_writeMode); + + if (l_error == EC_Normal) + { + OFLOG_INFO(dump2dcmLogger, "dump successfully converted"); + } else { + OFLOG_ERROR(dump2dcmLogger, l_error.text() << ": writing file: " << opt_ofname); + status = 1; + } + } else { + OFLOG_ERROR(dump2dcmLogger, "no conversion to transfer syntax " << DcmXfer(opt_xfer).getXferName() << " possible!"); + status = 2; + } + } + fclose(dumpfile); + + return status; +} diff --git a/dcmdata/apps/img2dcm.cc b/dcmdata/apps/img2dcm.cc new file mode 100644 index 00000000..e547b5ea --- /dev/null +++ b/dcmdata/apps/img2dcm.cc @@ -0,0 +1,420 @@ +/* + * + * Copyright (C) 2007-2013, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Michael Onken + * + * Purpose: Implements utility for converting standard image formats to DICOM + * + */ + + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmdata/cmdlnarg.h" +#include "dcmtk/ofstd/ofconapp.h" +#include "dcmtk/dcmdata/dcuid.h" +#include "dcmtk/dcmdata/dcfilefo.h" +#include "dcmtk/dcmdata/dcdict.h" +#include "dcmtk/dcmdata/libi2d/i2d.h" +#include "dcmtk/dcmdata/libi2d/i2djpgs.h" +#include "dcmtk/dcmdata/libi2d/i2dbmps.h" +#include "dcmtk/dcmdata/libi2d/i2dplsc.h" +#include "dcmtk/dcmdata/libi2d/i2dplvlp.h" +#include "dcmtk/dcmdata/libi2d/i2dplnsc.h" + +#define OFFIS_CONSOLE_APPLICATION "img2dcm" +static char rcsid[] = "$dcmtk: " OFFIS_CONSOLE_APPLICATION " v" OFFIS_DCMTK_VERSION " " OFFIS_DCMTK_RELEASEDATE " $"; + +#define SHORTCOL 4 +#define LONGCOL 21 + +static OFLogger img2dcmLogger = OFLog::getLogger("dcmtk.apps." OFFIS_CONSOLE_APPLICATION); + +static OFCondition evaluateFromFileOptions(OFCommandLine& cmd, + Image2Dcm& converter) +{ + OFCondition cond; + // Parse command line options dealing with DICOM file import + if ( cmd.findOption("--dataset-from") ) + { + OFString tempStr; + OFCommandLine::E_ValueStatus valStatus; + valStatus = cmd.getValue(tempStr); + if (valStatus != OFCommandLine::VS_Normal) + return makeOFCondition(OFM_dcmdata, 18, OF_error, "Unable to read value of --dataset-from option"); + converter.setTemplateFile(tempStr); + } + + if (cmd.findOption("--study-from")) + { + OFString tempStr; + OFCommandLine::E_ValueStatus valStatus; + valStatus = cmd.getValue(tempStr); + if (valStatus != OFCommandLine::VS_Normal) + return makeOFCondition(OFM_dcmdata, 18, OF_error, "Unable to read value of --study-from option"); + converter.setStudyFrom(tempStr); + } + + if (cmd.findOption("--series-from")) + { + OFString tempStr; + OFCommandLine::E_ValueStatus valStatus; + valStatus = cmd.getValue(tempStr); + if (valStatus != OFCommandLine::VS_Normal) + return makeOFCondition(OFM_dcmdata, 18, OF_error, "Unable to read value of --series-from option"); + converter.setSeriesFrom(tempStr); + } + + if (cmd.findOption("--instance-inc")) + converter.setIncrementInstanceNumber(OFTrue); + + // Return success + return EC_Normal; +} + + +static void addCmdLineOptions(OFCommandLine& cmd) +{ + cmd.addParam("imgfile-in", "image input filename"); + cmd.addParam("dcmfile-out", "DICOM output filename"); + + cmd.addGroup("general options:", LONGCOL, SHORTCOL + 2); + cmd.addOption("--help", "-h", "print this help text and exit", OFCommandLine::AF_Exclusive); + cmd.addOption("--version", "print version information and exit", OFCommandLine::AF_Exclusive); + OFLog::addOptions(cmd); + + cmd.addGroup("input options:", LONGCOL, SHORTCOL + 2); + cmd.addSubGroup("general:"); + cmd.addOption("--input-format", "-i", 1, "[i]nput file format: string", "supported formats: JPEG (default), BMP"); + cmd.addOption("--dataset-from", "-df", 1, "[f]ilename: string", + "use dataset from DICOM file f"); + + cmd.addOption("--study-from", "-stf", 1, "[f]ilename: string", + "read patient/study from DICOM file f"); + cmd.addOption("--series-from", "-sef", 1, "[f]ilename: string", + "read patient/study/series from DICOM file f"); + cmd.addOption("--instance-inc", "-ii", "increase instance number read from DICOM file"); + cmd.addSubGroup("JPEG format:"); + cmd.addOption("--disable-progr", "-dp", "disable support for progressive JPEG"); + cmd.addOption("--disable-ext", "-de", "disable support for extended sequential JPEG"); + cmd.addOption("--insist-on-jfif", "-jf", "insist on JFIF header"); + cmd.addOption("--keep-appn", "-ka", "keep APPn sections (except JFIF)"); + + cmd.addGroup("processing options:", LONGCOL, SHORTCOL + 2); + cmd.addSubGroup("attribute checking:"); + cmd.addOption("--do-checks", "enable attribute validity checking (default)"); + cmd.addOption("--no-checks", "disable attribute validity checking"); + cmd.addOption("--insert-type2", "+i2", "insert missing type 2 attributes (default)\n(only with --do-checks)"); + cmd.addOption("--no-type2-insert", "-i2", "do not insert missing type 2 attributes \n(only with --do-checks)"); + cmd.addOption("--invent-type1", "+i1", "invent missing type 1 attributes (default)\n(only with --do-checks)"); + cmd.addOption("--no-type1-invent", "-i1", "do not invent missing type 1 attributes\n(only with --do-checks)"); + cmd.addSubGroup("character set:"); + cmd.addOption("--latin1", "+l1", "set latin-1 as standard character set (default)"); + cmd.addOption("--no-latin1", "-l1", "keep 7-bit ASCII as standard character set"); + cmd.addSubGroup("other processing options:"); + cmd.addOption("--key", "-k", 1, "[k]ey: gggg,eeee=\"str\", path or dict. name=\"str\"", + "add further attribute"); + + cmd.addGroup("output options:"); + cmd.addSubGroup("target SOP class:"); + cmd.addOption("--sec-capture", "-sc", "write Secondary Capture SOP class (default)"); + cmd.addOption("--new-sc", "-nsc", "write new Secondary Capture SOP classes"); + cmd.addOption("--vl-photo", "-vlp", "write Visible Light Photographic SOP class"); + + cmd.addSubGroup("output file format:"); + cmd.addOption("--write-file", "+F", "write file format (default)"); + cmd.addOption("--write-dataset", "-F", "write data set without file meta information"); + cmd.addSubGroup("group length encoding:"); + cmd.addOption("--group-length-recalc", "+g=", "recalculate group lengths if present (default)"); + cmd.addOption("--group-length-create", "+g", "always write with group length elements"); + cmd.addOption("--group-length-remove", "-g", "always write without group length elements"); + cmd.addSubGroup("length encoding in sequences and items:"); + cmd.addOption("--length-explicit", "+e", "write with explicit lengths (default)"); + cmd.addOption("--length-undefined", "-e", "write with undefined lengths"); + cmd.addSubGroup("data set trailing padding (not with --write-dataset):"); + cmd.addOption("--padding-off", "-p", "no padding (implicit if --write-dataset)"); + cmd.addOption("--padding-create", "+p", 2, "[f]ile-pad [i]tem-pad: integer", + "align file on multiple of f bytes\nand items on multiple of i bytes"); +} + + +static OFCondition startConversion(OFCommandLine& cmd, + int argc, + char *argv[]) +{ + // Parse command line and exclusive options + prepareCmdLineArgs(argc, argv, OFFIS_CONSOLE_APPLICATION); + OFConsoleApplication app(OFFIS_CONSOLE_APPLICATION, "Convert standard image formats into DICOM format", rcsid); + if (app.parseCommandLine(cmd, argc, argv)) + { + /* check exclusive options first */ + if (cmd.hasExclusiveOption()) + { + if (cmd.findOption("--version")) + { + app.printHeader(OFTrue /*print host identifier*/); + exit(0); + } + } + } + + /* print resource identifier */ + OFLOG_DEBUG(img2dcmLogger, rcsid << OFendl); + + // Main class for controlling conversion + Image2Dcm i2d; + // Output plugin to use (i.e. SOP class to write) + I2DOutputPlug *outPlug = NULL; + // Input plugin to use (i.e. file format to read) + I2DImgSource *inputPlug = NULL; + // Group length encoding mode for output DICOM file + E_GrpLenEncoding grpLengthEnc = EGL_recalcGL; + // Item and Sequence encoding mode for output DICOM file + E_EncodingType lengthEnc = EET_ExplicitLength; + // Padding mode for output DICOM file + E_PaddingEncoding padEnc = EPD_noChange; + // File pad length for output DICOM file + OFCmdUnsignedInt filepad = 0; + // Item pad length for output DICOM file + OFCmdUnsignedInt itempad = 0; + // Write only pure dataset, i.e. without meta header + E_FileWriteMode writeMode = EWM_fileformat; + // Override keys are applied at the very end of the conversion "pipeline" + OFList overrideKeys; + // The transfer syntax proposed to be written by output plugin + E_TransferSyntax writeXfer; + + // Parse rest of command line options + OFLog::configureFromCommandLine(cmd, app); + + OFString pixDataFile, outputFile, tempStr; + cmd.getParam(1, tempStr); + + if (tempStr.empty()) + { + OFLOG_ERROR(img2dcmLogger, "No image input filename specified"); + return EC_IllegalCall; + } + else + pixDataFile = tempStr; + + cmd.getParam(2, tempStr); + if (tempStr.empty()) + { + OFLOG_ERROR(img2dcmLogger, "No DICOM output filename specified"); + return EC_IllegalCall; + } + else + outputFile = tempStr; + + if (cmd.findOption("--input-format")) + { + app.checkValue(cmd.getValue(tempStr)); + if (tempStr == "JPEG") + { + inputPlug = new I2DJpegSource(); + } + else if (tempStr == "BMP") + { + inputPlug = new I2DBmpSource(); + } + else + { + return makeOFCondition(OFM_dcmdata, 18, OF_error, "No plugin for selected input format available"); + } + if (!inputPlug) + { + return EC_MemoryExhausted; + } + } + else // default is JPEG + { + inputPlug = new I2DJpegSource(); + } + OFLOG_INFO(img2dcmLogger, OFFIS_CONSOLE_APPLICATION ": Instantiated input plugin: " << inputPlug->inputFormat()); + + // Find out which plugin to use + cmd.beginOptionBlock(); + if (cmd.findOption("--sec-capture")) + outPlug = new I2DOutputPlugSC(); + if (cmd.findOption("--vl-photo")) + { + outPlug = new I2DOutputPlugVLP(); + } + if (cmd.findOption("--new-sc")) + outPlug = new I2DOutputPlugNewSC(); + cmd.endOptionBlock(); + if (!outPlug) // default is the old Secondary Capture object + outPlug = new I2DOutputPlugSC(); + if (outPlug == NULL) return EC_MemoryExhausted; + OFLOG_INFO(img2dcmLogger, OFFIS_CONSOLE_APPLICATION ": Instantiated output plugin: " << outPlug->ident()); + + cmd.beginOptionBlock(); + if (cmd.findOption("--write-file")) writeMode = EWM_fileformat; + if (cmd.findOption("--write-dataset")) writeMode = EWM_dataset; + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--group-length-recalc")) grpLengthEnc = EGL_recalcGL; + if (cmd.findOption("--group-length-create")) grpLengthEnc = EGL_withGL; + if (cmd.findOption("--group-length-remove")) grpLengthEnc = EGL_withoutGL; + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--length-explicit")) lengthEnc = EET_ExplicitLength; + if (cmd.findOption("--length-undefined")) lengthEnc = EET_UndefinedLength; + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--padding-off")) + { + filepad = 0; + itempad = 0; + } + else if (cmd.findOption("--padding-create")) + { + OFCmdUnsignedInt opt_filepad; OFCmdUnsignedInt opt_itempad; + app.checkValue(cmd.getValueAndCheckMin(opt_filepad, 0)); + app.checkValue(cmd.getValueAndCheckMin(opt_itempad, 0)); + itempad = opt_itempad; + filepad = opt_filepad; + } + cmd.endOptionBlock(); + + // create override attribute dataset (copied from findscu code) + if (cmd.findOption("--key", 0, OFCommandLine::FOM_FirstFromLeft)) + { + const char *ovKey = NULL; + do { + app.checkValue(cmd.getValue(ovKey)); + overrideKeys.push_back(ovKey); + } while (cmd.findOption("--key", 0, OFCommandLine::FOM_NextFromLeft)); + } + i2d.setOverrideKeys(overrideKeys); + + // Test for ISO Latin 1 option + OFBool insertLatin1 = OFTrue; + cmd.beginOptionBlock(); + if (cmd.findOption("--latin1")) + insertLatin1 = OFTrue; + if (cmd.findOption("--no-latin1")) + insertLatin1 = OFFalse; + cmd.endOptionBlock(); + i2d.setISOLatin1(insertLatin1); + + // evaluate validity checking options + OFBool insertType2 = OFTrue; + OFBool inventType1 = OFTrue; + OFBool doChecks = OFTrue; + cmd.beginOptionBlock(); + if (cmd.findOption("--no-checks")) + doChecks = OFFalse; + if (cmd.findOption("--do-checks")) + doChecks = OFTrue; + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--insert-type2")) + insertType2 = OFTrue; + if (cmd.findOption("--no-type2-insert")) + insertType2 = OFFalse; + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--invent-type1")) + inventType1 = OFTrue; + if (cmd.findOption("--no-type1-invent")) + inventType1 = OFFalse; + cmd.endOptionBlock(); + i2d.setValidityChecking(doChecks, insertType2, inventType1); + outPlug->setValidityChecking(doChecks, insertType2, inventType1); + + // evaluate --xxx-from options and transfer syntax options + OFCondition cond; + cond = evaluateFromFileOptions(cmd, i2d); + if (cond.bad()) + { + delete outPlug; outPlug = NULL; + delete inputPlug; inputPlug = NULL; + return cond; + } + + if (inputPlug->inputFormat() == "JPEG") + { + I2DJpegSource *jpgSource = OFstatic_cast(I2DJpegSource*, inputPlug); + if (!jpgSource) + { + delete outPlug; outPlug = NULL; + delete inputPlug; inputPlug = NULL; + return EC_MemoryExhausted; + } + if ( cmd.findOption("--disable-progr") ) + jpgSource->setProgrSupport(OFFalse); + if ( cmd.findOption("--disable-ext") ) + jpgSource->setExtSeqSupport(OFFalse); + if ( cmd.findOption("--insist-on-jfif") ) + jpgSource->setInsistOnJFIF(OFTrue); + if ( cmd.findOption("--keep-appn") ) + jpgSource->setKeepAPPn(OFTrue); + } + inputPlug->setImageFile(pixDataFile); + + /* make sure data dictionary is loaded */ + if (!dcmDataDict.isDictionaryLoaded()) + { + OFLOG_WARN(img2dcmLogger, "no data dictionary loaded, check environment variable: " + << DCM_DICT_ENVIRONMENT_VARIABLE); + } + + DcmDataset *resultObject = NULL; + OFLOG_INFO(img2dcmLogger, OFFIS_CONSOLE_APPLICATION ": Starting image conversion"); + cond = i2d.convert(inputPlug, outPlug, resultObject, writeXfer); + + // Save + if (cond.good()) + { + OFLOG_INFO(img2dcmLogger, OFFIS_CONSOLE_APPLICATION ": Saving output DICOM to file " << outputFile); + DcmFileFormat dcmff(resultObject); + cond = dcmff.saveFile(outputFile.c_str(), writeXfer, lengthEnc, grpLengthEnc, padEnc, OFstatic_cast(Uint32, filepad), OFstatic_cast(Uint32, itempad), writeMode); + } + + // Cleanup and return + delete outPlug; outPlug = NULL; + delete inputPlug; inputPlug = NULL; + delete resultObject; resultObject = NULL; + + return cond; +} + + +int main(int argc, char *argv[]) +{ + + // variables for command line + OFConsoleApplication app(OFFIS_CONSOLE_APPLICATION, "Convert image file to DICOM", rcsid); + OFCommandLine cmd; + + cmd.setOptionColumns(LONGCOL, SHORTCOL); + cmd.setParamColumn(LONGCOL + SHORTCOL + 4); + addCmdLineOptions(cmd); + + OFCondition cond = startConversion(cmd, argc, argv); + if (cond.bad()) + { + OFLOG_FATAL(img2dcmLogger, "Error converting file: " << cond.text()); + return 1; + } + + return 0; +} diff --git a/dcmdata/apps/mdfconen.cc b/dcmdata/apps/mdfconen.cc new file mode 100644 index 00000000..0f3d2be9 --- /dev/null +++ b/dcmdata/apps/mdfconen.cc @@ -0,0 +1,662 @@ +/* + * + * Copyright (C) 2003-2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Michael Onken + * + * Purpose: Class for modifying DICOM files from comandline + * + */ + +#include "dcmtk/config/osconfig.h" // make sure OS specific configuration is included first + +#include "mdfconen.h" +#include "mdfdsman.h" +#include "dcmtk/ofstd/ofstd.h" +#include "dcmtk/dcmdata/dctk.h" +#include "dcmtk/dcmdata/dcistrmz.h" /* for dcmZlibExpectRFC1950Encoding */ + +#define SHORTCOL 4 +#define LONGCOL 21 + +#ifdef WITH_ZLIB +BEGIN_EXTERN_C +#include +END_EXTERN_C +#endif + +static OFLogger dcmodifyLogger = OFLog::getLogger("dcmtk.apps.dcmodify"); + +MdfJob::MdfJob(const MdfJob& other) +: option(other.option), path(other.path), value(other.value) +{ +} + +OFBool MdfJob::operator==(const MdfJob &j) const +{ + return (option == j.option) && (path == j.path) && (value == j.value); +} + +MdfJob &MdfJob::operator=(const MdfJob &j) +{ + option = j.option; + path = j.path; + value = j.value; + return *this; +} + + +MdfConsoleEngine::MdfConsoleEngine(int argc, char *argv[], + const char *application_name) + : app(NULL), cmd(NULL), ds_man(NULL), ignore_errors_option(OFFalse), + update_metaheader_uids_option(OFTrue), no_backup_option(OFFalse), + read_mode_option(ERM_autoDetect), input_xfer_option(EXS_Unknown), + output_dataset_option(OFFalse), output_xfer_option(EXS_Unknown), + glenc_option(EGL_recalcGL), enctype_option(EET_ExplicitLength), + padenc_option(EPD_withoutPadding), filepad_option(0), + itempad_option(0), ignore_missing_tags_option(OFFalse), + no_reservation_checks(OFFalse), ignore_un_modifies(OFFalse), + create_if_necessary(OFFalse), was_created(OFFalse), jobs(NULL), files(NULL) +{ + char rcsid[200]; + // print application header + sprintf(rcsid, "$dcmtk: %s v%s %s $", application_name, OFFIS_DCMTK_VERSION, OFFIS_DCMTK_RELEASEDATE); + + // the next lines describe commandline arguments/options + app = new OFConsoleApplication(application_name, "Modify DICOM files", rcsid); + cmd = new OFCommandLine(); + + cmd->setOptionColumns(LONGCOL, SHORTCOL); + cmd->setParamColumn(LONGCOL + SHORTCOL + 4); + + cmd->addParam("dcmfile-in", "DICOM input filename to be modified", OFCmdParam::PM_MultiMandatory); + + // add options to commandline application + cmd->addGroup("general options:", LONGCOL, SHORTCOL + 2); + cmd->addOption("--help", "-h", "print this help text and exit", OFCommandLine::AF_Exclusive); + cmd->addOption("--version", "print version information and exit", OFCommandLine::AF_Exclusive); + OFLog::addOptions(*cmd); + cmd->addGroup("input options:"); + cmd->addSubGroup("input file format:"); + cmd->addOption("--read-file", "+f", "read file format or data set (default)"); + cmd->addOption("--read-file-only", "+fo", "read file format only"); + cmd->addOption("--read-dataset", "-f", "read data set without file meta information"); + cmd->addOption("--create-file", "+fc", "create file format if file does not exist"); + cmd->addSubGroup("input transfer syntax:"); + cmd->addOption("--read-xfer-auto", "-t=", "use TS recognition (default)"); + cmd->addOption("--read-xfer-detect", "-td", "ignore TS specified in the file meta header"); + cmd->addOption("--read-xfer-little", "-te", "read with explicit VR little endian TS"); + cmd->addOption("--read-xfer-big", "-tb", "read with explicit VR big endian TS"); + cmd->addOption("--read-xfer-implicit", "-ti", "read with implicit VR little endian TS"); + cmd->addSubGroup("parsing of odd-length attributes:"); + cmd->addOption("--accept-odd-length", "+ao", "accept odd length attributes (default)"); + cmd->addOption("--assume-even-length", "+ae", "assume real length is one byte larger"); + cmd->addSubGroup("automatic data correction:"); + cmd->addOption("--enable-correction", "+dc", "enable automatic data correction (default)"); + cmd->addOption("--disable-correction", "-dc", "disable automatic data correction"); +#ifdef WITH_ZLIB + cmd->addSubGroup("bitstream format of deflated input:"); + cmd->addOption("--bitstream-deflated", "+bd", "expect deflated bitstream (default)"); + cmd->addOption("--bitstream-zlib", "+bz", "expect deflated zlib bitstream"); +#endif + + cmd->addGroup("processing options:"); + cmd->addSubGroup("backup input files:"); + cmd->addOption("--backup", "backup files before modifying (default)"); + cmd->addOption("--no-backup", "-nb", "don't backup files (DANGEROUS)"); + cmd->addSubGroup("insert mode:"); + cmd->addOption("--insert", "-i", 1, "\"[t]ag-path=[v]alue\"", + "insert (or overwrite) path at position t\nwith value v", OFCommandLine::AF_NoWarning); + cmd->addOption("--insert-from-file", "-if", 1, "\"[t]ag-path=[f]ilename\"", + "insert (or overwrite) path at position t\nwith value from file f", OFCommandLine::AF_NoWarning); + cmd->addOption("--no-reserv-check", "-nrc", "do not check private reservations\nwhen inserting private tags"); + cmd->addSubGroup("modify mode:"); + cmd->addOption("--modify", "-m", 1, "\"[t]ag-path=[v]alue\"", + "modify tag at position t to value v", OFCommandLine::AF_NoWarning); + cmd->addOption("--modify-from-file", "-mf", 1, "\"[t]ag-path=[f]ilename\"", + "modify tag at position t to value from file f", OFCommandLine::AF_NoWarning); + cmd->addOption("--modify-all", "-ma", 1, "\"[t]ag=[v]alue\"", + "modify ALL matching tags t in file to value v", OFCommandLine::AF_NoWarning); + cmd->addSubGroup("erase mode:"); + cmd->addOption("--erase", "-e", 1, "\"[t]ag-path\"", + "erase tag/item at position t", OFCommandLine::AF_NoWarning); + cmd->addOption("--erase-all", "-ea", 1, "\"[t]ag\"", + "erase ALL matching tags t in file", OFCommandLine::AF_NoWarning); + cmd->addOption("--erase-private", "-ep", "erase ALL private data from file", OFCommandLine::AF_NoWarning); + cmd->addSubGroup("unique identifier:"); + cmd->addOption("--gen-stud-uid", "-gst", "generate new Study Instance UID", OFCommandLine::AF_NoWarning); + cmd->addOption("--gen-ser-uid", "-gse", "generate new Series Instance UID", OFCommandLine::AF_NoWarning); + cmd->addOption("--gen-inst-uid", "-gin", "generate new SOP Instance UID", OFCommandLine::AF_NoWarning); + cmd->addOption("--no-meta-uid", "-nmu", "do not update metaheader UIDs if related\nUIDs in the dataset are modified"); + cmd->addSubGroup("error handling:"); + cmd->addOption("--ignore-errors", "-ie", "continue with file, if modify error occurs"); + cmd->addOption("--ignore-missing-tags", "-imt", "treat 'tag not found' as success\nwhen modifying or erasing in datasets"); + cmd->addOption("--ignore-un-values", "-iun", "do not try writing any values to elements\nhaving a VR of UN"); + cmd->addGroup("output options:"); + cmd->addSubGroup("output file format:"); + cmd->addOption("--write-file", "+F", "write file format (default)"); + cmd->addOption("--write-dataset", "-F", "write data set without file meta information"); + cmd->addSubGroup("output transfer syntax:"); + cmd->addOption("--write-xfer-same", "+t=", "write with same TS as input (default)"); + cmd->addOption("--write-xfer-little", "+te", "write with explicit VR little endian TS"); + cmd->addOption("--write-xfer-big", "+tb", "write with explicit VR big endian TS"); + cmd->addOption("--write-xfer-implicit", "+ti", "write with implicit VR little endian TS"); + cmd->addSubGroup("post-1993 value representations:"); + cmd->addOption("--enable-new-vr", "+u", "enable support for new VRs (UN/UT) (default)"); + cmd->addOption("--disable-new-vr", "-u", "disable support for new VRs, convert to OB"); + cmd->addSubGroup("group length encoding:"); + cmd->addOption("--group-length-recalc", "+g=", "recalculate group lengths if present (default)"); + cmd->addOption("--group-length-create", "+g", "always write with group length elements"); + cmd->addOption("--group-length-remove", "-g", "always write without group length elements"); + cmd->addSubGroup("length encoding in sequences and items:"); + cmd->addOption("--length-explicit", "+le", "write with explicit lengths (default)"); + cmd->addOption("--length-undefined", "-le", "write with undefined lengths"); + cmd->addSubGroup("data set trailing padding (not with --write-dataset):"); + cmd->addOption("--padding-retain", "-p=", "do not change padding\n(default if not --write-dataset)"); + cmd->addOption("--padding-off", "-p", "no padding (implicit if --write-dataset)"); + cmd->addOption("--padding-create", "+p", 2, "[f]ile-pad [i]tem-pad: integer", + "align file on multiple of f bytes\nand items on multiple of i bytes"); + + // evaluate commandline + prepareCmdLineArgs(argc, argv, application_name); + if (app->parseCommandLine(*cmd, argc, argv)) + { + /* print help text and exit */ + if (cmd->getArgCount() == 0) + app->printUsage(); + + /* check exclusive options first */ + if (cmd->hasExclusiveOption()) + { + if (cmd->findOption("--version")) + { + app->printHeader(OFTrue /*print host identifier*/); + ofConsole.lockCout() << OFendl << "External libraries used:"; +#ifdef WITH_ZLIB + ofConsole.getCout() << OFendl << "- ZLIB, Version " << zlibVersion() << OFendl; +#else + ofConsole.getCout() << " none" << OFendl; +#endif + ofConsole.unlockCout(); + delete app; + delete cmd; + exit(0); + } + } + + // iterate the files (parameters) and save them in list + files = new OFList; + OFString current_file; + for (int i = 1; i <= cmd->getParamCount(); i++) + { + cmd->getParam(i,current_file); + files->push_back(current_file); + } + // if no files are given: return with error message + if (files->empty()) + { + OFLOG_ERROR(dcmodifyLogger, "no dicom files given!"); + delete app; + delete cmd; + exit(1); + } + + // make sure data dictionary is loaded + if (!dcmDataDict.isDictionaryLoaded()) + OFLOG_WARN(dcmodifyLogger, "no data dictionary loaded, " + << "check environment variable: " << DCM_DICT_ENVIRONMENT_VARIABLE); + } + + /* print resource identifier */ + OFLOG_DEBUG(dcmodifyLogger, rcsid << OFendl); +} + + +void MdfConsoleEngine::parseNonJobOptions() +{ + // catch "general" options + OFLog::configureFromCommandLine(*cmd, *app); + + // input options + cmd->beginOptionBlock(); + if (cmd->findOption("--read-file")) + read_mode_option = ERM_autoDetect; + if (cmd->findOption("--read-file-only")) + read_mode_option = ERM_fileOnly; + if (cmd->findOption("--read-dataset")) + read_mode_option = ERM_dataset; + cmd->endOptionBlock(); + + if (cmd->findOption("--create-file")) + create_if_necessary = OFTrue; + + cmd->beginOptionBlock(); + if (cmd->findOption("--read-xfer-auto")) + input_xfer_option = EXS_Unknown; + if (cmd->findOption("--read-xfer-detect")) + dcmAutoDetectDatasetXfer.set(OFTrue); + if (cmd->findOption("--read-xfer-little")) + { + app->checkDependence("--read-xfer-little", "--read-dataset", read_mode_option == ERM_dataset); + input_xfer_option = EXS_LittleEndianExplicit; + } + if (cmd->findOption("--read-xfer-big")) + { + app->checkDependence("--read-xfer-big", "--read-dataset", read_mode_option == ERM_dataset); + input_xfer_option = EXS_BigEndianExplicit; + } + if (cmd->findOption("--read-xfer-implicit")) + { + app->checkDependence("--read-xfer-implicit", "--read-dataset", read_mode_option == ERM_dataset); + input_xfer_option = EXS_LittleEndianImplicit; + } + cmd->endOptionBlock(); + + cmd->beginOptionBlock(); + if (cmd->findOption("--accept-odd-length")) + dcmAcceptOddAttributeLength.set(OFTrue); + if (cmd->findOption("--assume-even-length")) + dcmAcceptOddAttributeLength.set(OFFalse); + cmd->endOptionBlock(); + + cmd->beginOptionBlock(); + if (cmd->findOption("--enable-correction")) + dcmEnableAutomaticInputDataCorrection.set(OFTrue); + if (cmd->findOption("--disable-correction")) + dcmEnableAutomaticInputDataCorrection.set(OFFalse); + cmd->endOptionBlock(); + +#ifdef WITH_ZLIB + cmd->beginOptionBlock(); + if (cmd->findOption("--bitstream-deflated")) + dcmZlibExpectRFC1950Encoding.set(OFFalse); + if (cmd->findOption("--bitstream-zlib")) + dcmZlibExpectRFC1950Encoding.set(OFTrue); + cmd->endOptionBlock(); +#endif + + // processing options + cmd->beginOptionBlock(); + if (cmd->findOption("--backup")) + no_backup_option = OFFalse; + if (cmd->findOption("--no-backup")) + no_backup_option = OFTrue; + cmd->endOptionBlock(); + + if (cmd->findOption("--no-reserv-check")) + no_reservation_checks = OFTrue; + + if (cmd->findOption("--no-meta-uid")) + update_metaheader_uids_option = OFFalse; + + if (cmd->findOption("--ignore-errors")) + ignore_errors_option = OFTrue; + if (cmd->findOption("--ignore-missing-tags")) + ignore_missing_tags_option = OFTrue; + if (cmd->findOption("--ignore-un-values")) + ignore_un_modifies = OFTrue; + + // output options + cmd->beginOptionBlock(); + if (cmd->findOption("--write-file")) + output_dataset_option = OFFalse; + if (cmd->findOption("--write-dataset")) + { + output_dataset_option = OFTrue; + app->checkConflict("--write-dataset", "--create-file", create_if_necessary); + } + cmd->endOptionBlock(); + + cmd->beginOptionBlock(); + if (cmd->findOption("--write-xfer-same")) + output_xfer_option = EXS_Unknown; + if (cmd->findOption("--write-xfer-little")) + output_xfer_option = EXS_LittleEndianExplicit; + if (cmd->findOption("--write-xfer-big")) + output_xfer_option = EXS_BigEndianExplicit; + if (cmd->findOption("--write-xfer-implicit")) + output_xfer_option = EXS_LittleEndianImplicit; + cmd->endOptionBlock(); + + cmd->beginOptionBlock(); + if (cmd->findOption("--enable-new-vr")) + dcmEnableGenerationOfNewVRs(); + if (cmd->findOption("--disable-new-vr")) + dcmDisableGenerationOfNewVRs(); + cmd->endOptionBlock(); + + cmd->beginOptionBlock(); + if (cmd->findOption("--group-length-recalc")) + glenc_option = EGL_recalcGL; + if (cmd->findOption("--group-length-create")) + glenc_option = EGL_withGL; + if (cmd->findOption("--group-length-remove")) + glenc_option = EGL_withoutGL; + cmd->endOptionBlock(); + + cmd->beginOptionBlock(); + if (cmd->findOption("--length-explicit")) + enctype_option = EET_ExplicitLength; + if (cmd->findOption("--length-undefined")) + enctype_option = EET_UndefinedLength; + cmd->endOptionBlock(); + + cmd->beginOptionBlock(); + if (cmd->findOption("--padding-retain")) + { + app->checkConflict("--padding-retain", "--write-dataset", output_dataset_option); + padenc_option = EPD_noChange; + } + if (cmd->findOption("--padding-off")) + padenc_option = EPD_withoutPadding; + if (cmd->findOption("--padding-create")) + { + app->checkConflict("--padding-create", "--write-dataset", output_dataset_option); + app->checkValue(cmd->getValueAndCheckMin(filepad_option, 0)); + app->checkValue(cmd->getValueAndCheckMin(itempad_option, 0)); + padenc_option = EPD_withPadding; + } + cmd->endOptionBlock(); +} + + +void MdfConsoleEngine::parseCommandLine() +{ + jobs = new OFList; + OFString option_string; + // check all options, that don't belong to a specific job + parseNonJobOptions(); + + cmd->gotoFirstOption(); + // iterate over commandline arguments from first to last + do { + if (cmd->getCurrentOption(option_string)) + { + MdfJob aJob; + OFString option_value, tag_path, tag_value; + if (option_string == "--insert") + aJob.option = "i"; + else if (option_string == "--insert-from-file") + aJob.option = "if"; + else if (option_string == "--modify") + aJob.option = "m"; + else if (option_string == "--modify-from-file") + aJob.option = "mf"; + else if (option_string == "--modify-all") + aJob.option = "ma"; + else if (option_string == "--erase") + aJob.option = "e"; + else if (option_string == "--erase-all") + aJob.option = "ea"; + else if (option_string == "--erase-private") + aJob.option = "ep"; + else if (option_string == "--gen-stud-uid") + aJob.option = "gst"; + else if (option_string == "--gen-ser-uid") + aJob.option = "gse"; + else if (option_string == "--gen-inst-uid") + aJob.option = "gin"; + // else this is a non job option, e.g. -v, -d, -f, ... + else + continue; + // get any parameters if job expects some + if (jobOptionExpectsParameters(aJob.option)) + { + cmd->getValue(option_value); + splitPathAndValue(option_value, tag_path, tag_value); + aJob.path = tag_path; + aJob.value = tag_value; + } + // finally, and schedule job + jobs->push_back(aJob); + } + } while (cmd->gotoNextOption()); +} + + +OFBool MdfConsoleEngine::jobOptionExpectsParameters(const OFString &job) +{ + return (job != "ep") && (job != "gst") && (job != "gse") && (job != "gin"); +} + + +void MdfConsoleEngine::splitPathAndValue(const OFString &whole, + OFString &path, + OFString &value) +{ + size_t pos = whole.find("="); + if (pos != OFString_npos) + { + path = whole.substr(0, pos); + value = whole.substr(pos + 1, value.length() - 1); + } + else path = whole; +} + + +int MdfConsoleEngine::executeJob(const MdfJob &job, + const char *filename) +{ + OFCondition result; + int count = 0; + int error_count = 0; + OFLOG_INFO(dcmodifyLogger, "Executing (option|path|value): " + << job.option << "|" << job.path << "|" << job.value); + // start modify operation based on job option + if (job.option=="i") + result = ds_man->modifyOrInsertPath(job.path, job.value, OFFalse, update_metaheader_uids_option, ignore_missing_tags_option, no_reservation_checks); + else if (job.option == "if") + result = ds_man->modifyOrInsertFromFile(job.path, job.value /*filename*/, OFFalse, update_metaheader_uids_option, ignore_missing_tags_option, no_reservation_checks); + else if (job.option == "m") + result = ds_man->modifyOrInsertPath(job.path, job.value, OFTrue, update_metaheader_uids_option, ignore_missing_tags_option, no_reservation_checks); + else if (job.option == "mf") + result = ds_man->modifyOrInsertFromFile(job.path, job.value /*filename*/, OFTrue, update_metaheader_uids_option, ignore_missing_tags_option, no_reservation_checks); + else if (job.option == "ma") + result = ds_man->modifyAllTags(job.path, job.value, update_metaheader_uids_option, count); + else if (job.option == "e") + result = ds_man->deleteTag(job.path, OFFalse, ignore_missing_tags_option); + else if (job.option == "ea") + result = ds_man->deleteTag(job.path, OFTrue, ignore_missing_tags_option); + else if (job.option == "ep") + result = ds_man->deletePrivateData(); + else if (job.option == "gst") + result = ds_man->generateAndInsertUID(DCM_StudyInstanceUID); + else if (job.option == "gse") + result = ds_man->generateAndInsertUID(DCM_SeriesInstanceUID); + else if (job.option == "gin") + result = ds_man->generateAndInsertUID(DCM_SOPInstanceUID); + // no valid job option found: + else + { + error_count++; + OFLOG_ERROR(dcmodifyLogger, "no valid option: " << job.option); + } + // if modify operation failed + if (result.bad() && error_count == 0) + { + if (filename != NULL) + OFLOG_ERROR(dcmodifyLogger, "modifying tag in file " << OFString(filename) << ": " << result.text()); + else + OFLOG_ERROR(dcmodifyLogger, "modifying tag: " << result.text()); + error_count++; + } + return error_count; +} + + +int MdfConsoleEngine::startProvidingService() +{ + OFCondition result; + const char *filename; + // return value of this function + int errors = 0; + // parse command line into file and job list + parseCommandLine(); + // iterators for job and file loops + OFListIterator(MdfJob) job_it; + OFListIterator(MdfJob) job_last = jobs->end();; + OFListIterator(OFString) file_it = files->begin(); + OFListIterator(OFString) file_last = files->end();; + // outer loop: iterate over all files + while (file_it != file_last) + { + filename = (*file_it).c_str(); + result = loadFile(filename); + + // if file could be loaded: + if (result.good()) + { + // for each file, set job iterator back to first entry + job_it = jobs->begin(); + // inner loop: iterate over jobs, execute all jobs for current file + while (job_it != job_last) + { + errors += executeJob(*job_it, filename); + job_it++; + } + // if there were no errors or user wants to override them, save: + if (errors == 0 || ignore_errors_option) + { + if (was_created && (output_xfer_option == EXS_Unknown)) + { + output_xfer_option = EXS_LittleEndianExplicit; + } + result = ds_man->saveFile(filename, output_xfer_option, + enctype_option, glenc_option, + padenc_option, filepad_option, + itempad_option, output_dataset_option); + if (result.bad()) + { + OFLOG_ERROR(dcmodifyLogger, "couldn't save file: " << result.text()); + errors++; + if (!no_backup_option && !was_created) + { + result = restoreFile(filename); + if (result.bad()) + { + OFLOG_ERROR(dcmodifyLogger, "couldn't restore file: " << result.text()); + errors++; + } + } + } + } + // errors occured and user doesn't want to ignore them: + else if (!no_backup_option && !was_created) + { + result = restoreFile(filename); + if (result.bad()) + { + OFLOG_ERROR(dcmodifyLogger, "couldn't restore file!"); + errors++; + } + } + } + // if loading fails: + else + { + errors++; + OFLOG_ERROR(dcmodifyLogger, "unable to load file " << filename <<": " << result.text()); + } + file_it++; + // output separator line if required + if ((file_it != file_last) || (errors > 0)) + OFLOG_INFO(dcmodifyLogger, "------------------------------------"); + } + return errors; +} + + +OFCondition MdfConsoleEngine::loadFile(const char *filename) +{ + OFCondition result; + // free memory + delete ds_man; + ds_man = new MdfDatasetManager(); + ds_man->setModifyUNValues(!ignore_un_modifies); + OFLOG_INFO(dcmodifyLogger, "Processing file: " << filename); + // load file into dataset manager + was_created = !OFStandard::fileExists(filename); + result = ds_man->loadFile(filename, read_mode_option, input_xfer_option, create_if_necessary); + if (result.good() && !no_backup_option && !was_created) + result = backupFile(filename); + return result; +} + + +OFCondition MdfConsoleEngine::backupFile(const char *filename) +{ + int result; + OFString backup = filename; + backup += ".bak"; + OFLOG_INFO(dcmodifyLogger, "Creating backup of input file: " << backup); + // delete backup file, if it already exists + if (OFStandard::fileExists(backup.c_str())) + { + result = remove(backup.c_str()); + if (result != 0) + { + OFLOG_ERROR(dcmodifyLogger, "couldn't delete previous backup file, unable to backup!"); + return EC_IllegalCall; + } + } + // if backup file could be removed, backup original file + result = rename(filename, backup.c_str()); + // set return value + if (result != 0) + { + OFLOG_ERROR(dcmodifyLogger, "unable to backup, no write permission?"); + return EC_IllegalCall; + } + + return EC_Normal; +} + + +OFCondition MdfConsoleEngine::restoreFile(const char *filename) +{ + int result; + OFString backup = filename; + backup += ".bak"; + OFLOG_INFO(dcmodifyLogger, "Restoring original file from backup"); + // delete the (original) file that dcmodify couldn't modify + if (OFStandard::fileExists(filename)) + { + result = remove(filename); + if (result != 0) + { + OFLOG_ERROR(dcmodifyLogger, "unable to delete original file for restoring backup!"); + return EC_IllegalCall; + } + } + // and rename backup file back to original filename + result = rename(backup.c_str(), filename); + // error renaming backup file + if (result != 0) + { + OFLOG_ERROR(dcmodifyLogger, "unable to rename backup file to original filename!"); + return EC_IllegalCall; + } + // you only get to this point, if restoring was completely successful + return EC_Normal; +} + + +MdfConsoleEngine::~MdfConsoleEngine() +{ + delete app; + delete cmd; + delete files; + delete jobs; + delete ds_man; +} diff --git a/dcmdata/apps/mdfconen.h b/dcmdata/apps/mdfconen.h new file mode 100644 index 00000000..55fc886f --- /dev/null +++ b/dcmdata/apps/mdfconen.h @@ -0,0 +1,225 @@ +/* + * + * Copyright (C) 2003-2010, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Michael Onken + * + * Purpose: Class for modifying DICOM files from comandline + * + */ + +#ifndef MDFCONEN_H +#define MDFCONEN_H + +#include "dcmtk/config/osconfig.h" // make sure OS specific configuration is included first + +#include "dcmtk/ofstd/ofcond.h" +#include "dcmtk/dcmdata/dcxfer.h" + + +// forward declarations +class MdfDatasetManager; +class OFConsoleApplication; +class OFCommandLine; + + +/** class reflecting a modify operation (called Job in this context) + */ +class MdfJob { + +public : + + OFString option; + OFString path; + OFString value; + + MdfJob() : option(), path(), value() { } + + MdfJob(const MdfJob& other); + + /** Comparison operator between Jobs + */ + OFBool operator==(const MdfJob &j) const; + + /** Assignment operator + */ + MdfJob &operator=(const MdfJob &j); +}; + + +/** This class encapsulates data structures and operations for modifying + * Dicom files from the commandline + */ +class MdfConsoleEngine +{ +public: + + /** Constructor + * @param argc Number of commandline arguments + * @param argv Array holding the commandline arguments + * @param appl_name Name of calling application, that instantiates + * this class + */ + MdfConsoleEngine(int argc, + char *argv[], + const char *appl_name); + + /** Destructor + */ + ~MdfConsoleEngine(); + + /** This function looks at commandline options and decides what to do. + * It evaluates option values from commandline and prepares them for + * starting the corresponding private functions. + * @return Returns 0 if successful, another value if errors occurreds + */ + int startProvidingService(); + +protected: + + /** Checks for non-job commandline options like --debug etc. and + * sets corresponding internal flags + */ + void parseNonJobOptions(); + + /** Parses commandline options into corresponding file- and job lists and + * enables debug/verbose mode. The joblist is built in order of modify + * options on commandline + */ + void parseCommandLine(); + + /** Checks whether given job expects more values on commandline, e. g. a + * a tag path or any kind of value. + * @param job [in] The job option to check (e. g. "i", "m", "ma"...) + * @return OFTrue, if a value is expected. + */ + static OFBool jobOptionExpectsParameters(const OFString &job); + + /** This function splits a modify option (inclusive value) as + * found on commandline into to parts (path and value) + * e.g. "(0010,0010)=value" into path "(0010,0010)" and "value" + * @param whole string to be splitted + * @param path returns part containing the path + * @param value returns part containing the value(if theres one) + */ + static void splitPathAndValue(const OFString &whole, + OFString &path, + OFString &value); + + /** Executes given modify job + * @param job job to be executed + * @param filename name of the file to be processed (optional) + * @return returns 0 if no error occured, else the number of errors + */ + int executeJob(const MdfJob &job, + const char *filename = NULL); + + /** Backup and load file into internal MdfDatasetManager + * @param filename name of file to load + * @return OFCondition, whether loading/backuping was successful including + * error description + */ + OFCondition loadFile(const char *filename); + + /** Backup given file from file to file.bak + * @param file_name filename of file, that should be backuped + * @return OFCondition, whether backup was successful or not + */ + OFCondition backupFile(const char *file_name); + + /** Restore given file from file.bak to original (without .bak) + * @param filename restore "filename".bak to original without .bak + * @return OFCondition, whether restoring was successful + */ + OFCondition restoreFile(const char *filename); + +private: + + /// helper class for console applications + OFConsoleApplication *app; + + /// helper class for commandline parsing + OFCommandLine *cmd; + + /// dataset manager that is used for modify operations + MdfDatasetManager *ds_man; + + /// ignore errors option + OFBool ignore_errors_option; + + /// if false, metaheader UIDs are not updated when related dataset UIDs change + OFBool update_metaheader_uids_option; + + /// if true, no backup is made before modifying a file + OFBool no_backup_option; + + /// read file with or without metaheader + E_FileReadMode read_mode_option; + + /// denotes the expected transfersyntax + E_TransferSyntax input_xfer_option; + + /// decides whether to with/without metaheader + OFBool output_dataset_option; + + /// denotes the transfer syntax that should be written + E_TransferSyntax output_xfer_option; + + /// option for group length recalcing + E_GrpLenEncoding glenc_option; + + /// write explicit or implicit length encoding + E_EncodingType enctype_option; + + /// padding output + E_PaddingEncoding padenc_option; + + /// internal padding variables + OFCmdUnsignedInt filepad_option; + OFCmdUnsignedInt itempad_option; + + /// if true, 'tag not found' errors are treated as being successful for + /// modify and erase operations + OFBool ignore_missing_tags_option; + + /// If true, it is not checked whether there is a corresponding private + /// reservation during insertion of private tags + OFBool no_reservation_checks; + + /// If enabled, any value modifications of UN leaf elements are not + /// executed + OFBool ignore_un_modifies; + + /// If enabled, a new dataset is created in memory if a file is not existing. + OFBool create_if_necessary; + + /// Used to remember, whether a file was newly created. + OFBool was_created; + + /// list of jobs to be executed + OFList *jobs; + + /// list of files to be modified + OFList *files; + + /** private undefined assignment operator + */ + MdfConsoleEngine &operator=(const MdfConsoleEngine &); + + /** private undefined copy constructor + */ + MdfConsoleEngine(const MdfConsoleEngine &); +}; + +#endif // MDFCONEN_H diff --git a/dcmdata/apps/mdfdsman.cc b/dcmdata/apps/mdfdsman.cc new file mode 100644 index 00000000..2a7ac2dd --- /dev/null +++ b/dcmdata/apps/mdfdsman.cc @@ -0,0 +1,744 @@ +/* + * + * Copyright (C) 2003-2013, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Michael Onken + * + * Purpose: Class for modifying DICOM files + * + */ + + +#include "dcmtk/config/osconfig.h" // make sure OS specific configuration is included first + +#include "mdfdsman.h" +#include "dcmtk/ofstd/ofstd.h" +#include "dcmtk/dcmdata/dctk.h" +#include "dcmtk/dcmdata/dcpath.h" +#include "dcmtk/dcmdata/dcistrmf.h" /* for class DcmInputFileStream */ + +#define INCLUDE_CSTDIO +#include "dcmtk/ofstd/ofstdinc.h" + + +static OFLogger mdfdsmanLogger = OFLog::getLogger("dcmtk.dcmdata.mdfdsman"); + +MdfDatasetManager::MdfDatasetManager() +: current_file(""), + dfile(NULL), + dset(NULL), + ignore_un_modifies(OFFalse) +{ +} + + +OFCondition MdfDatasetManager::loadFile(const char *file_name, + const E_FileReadMode readMode, + const E_TransferSyntax xfer, + const OFBool createIfNecessary) +{ + OFCondition cond; + // delete old dfile and free memory and reset current_file + delete dfile; + current_file = ""; + dfile = new DcmFileFormat(); + dset = dfile->getDataset(); + + // load file into dfile if it exists + OFLOG_INFO(mdfdsmanLogger, "Loading file into dataset manager: " << file_name); + if (OFStandard::fileExists(file_name)) + { + cond = dfile->loadFile(file_name, xfer, EGL_noChange, DCM_MaxReadLength, readMode); + } + // if it does not already exist, check whether it should be created + else if (createIfNecessary) + { + OFLOG_DEBUG(mdfdsmanLogger, "File " << file_name << "does not exist, creating it as desired"); + cond = dfile->saveFile(file_name, EXS_LittleEndianExplicit /* might change later */); + } + // no file, we have an error + else + cond = makeOFCondition(OFM_dcmdata, 22, OF_error,"No such file or directory"); + + // if there are errors: + if (cond.bad()) + { + dset = NULL; + } + // file successfully loaded into dfile + else + { + // get dataset from file + OFLOG_INFO(mdfdsmanLogger, "Getting dataset from loaded file: " << file_name); + dset=dfile->getDataset(); + /* load also pixeldata into memory: + * Without this command pixeldata wouldn't be included into the file, + * that's saved after modifying, because original filename was renamed + * meanwhile + */ + dset->loadAllDataIntoMemory(); + // save filename to member variable + current_file = file_name; + } + return cond; +} + + +static DcmTagKey getTagKeyFromDictionary(OFString tag) +{ + DcmTagKey key(0xffff,0xffff); + const DcmDataDictionary& globalDataDict = dcmDataDict.rdlock(); + const DcmDictEntry *dicent = globalDataDict.findEntry(tag.c_str()); + // successfull lookup in dictionary -> translate to tag and return + if (dicent) + { + key = dicent->getKey(); + } + dcmDataDict.unlock(); + return key; +} + + +static int readNextToken(const char *c, int& pos, DcmTagKey& key, Uint32& idx) +{ + OFString aString; + int lpos = pos; + int spos = 0; + if (c[lpos]=='\0') return -1; // EOF + if (c[lpos]=='.') + { + ++pos; + return 3; // period + } + // look for item index between [] + if (c[lpos]=='[') + { + spos = ++lpos; + while ((c[lpos] >= '0')&&(c[lpos] <= '9')) ++lpos; + if (c[lpos] != ']') return 0; // parse error + unsigned long newindex = 0; + if (1 != sscanf(c+spos,"%lu", &newindex)) return 0; // parse error + idx = OFstatic_cast(Uint32, newindex); + pos = ++lpos; + return 2; // index + } + // look for tag between () + if (c[lpos]=='(') + { + spos = ++lpos; + while ((c[lpos] != ')')&&(c[lpos] != '\0')) ++lpos; + if (c[lpos] != ')') return 0; // parse error + unsigned int group=0; + unsigned int elem=0; + if (2 != sscanf(c+spos,"%x,%x", &group, &elem)) return 0; // parse error + key = DcmTagKey(OFstatic_cast(Uint16, group),OFstatic_cast(Uint16, elem)); + pos = ++lpos; + return 1; // tag key + } + // so far no tag and no item index found. So check if it's a dictionary name + spos = lpos; + while ( ((c[lpos] >= 'a')&&(c[lpos] <= 'z')) || + ((c[lpos] >= 'A')&&(c[lpos] <= 'Z')) || + ((c[lpos] >= '0')&&(c[lpos] <= '9'))) ++lpos; + aString.append(c + spos, (lpos-spos)); + key=getTagKeyFromDictionary(aString); + // if key was found in dictionary, return 1 for tag key + if ( (key.getGroup()!=0xffff) && (key.getElement()!=0xffff) ) + { + pos=lpos; + return 1; // tag key + } + // if no return command was processed this far, the token could not be parsed + return 0; // parse error +} + + +static DcmItem* getItemFromPath(DcmItem &dataset, + const char *location, + OFString &message) +{ + DcmTagKey key; + Uint32 idx = 0; + int pos = 0; + int token = 0; + int expected = 1; // first expected is a tagkey + OFBool finished = OFFalse; + DcmItem *result = &dataset; + DcmSequenceOfItems *sq = NULL; + DcmStack stack; + message.clear(); + do + { + token = readNextToken(location, pos, key, idx); + if ((token != expected)&&(token != -1)) + { + message=message + "parse error in path '" + location + "'"; + return NULL; + } + if (token == -1) + { + if (!finished) + { + message=message + "Error: path '" + location + "' incomplete"; + return NULL; + } + return result; + } + if (token == 1) + { + // we have read a tag key + stack.clear(); + if (EC_Normal != result->search(key, stack, ESM_fromHere, OFFalse)) + { + message=message + "Error: attribute not found in dataset (path is '" + + location + "')"; + return NULL; + } + if (stack.top()->ident() == EVR_SQ) + { + sq = OFstatic_cast(DcmSequenceOfItems *, stack.top()); + } else { + message=message + "Error: attribute is not a sequence (path is '" + location + "')"; + return NULL; + } + expected = 2; + finished = OFFalse; + } + else if (token == 2) + { + // we have read an index + if (sq == NULL) + { + message=message + "Error: sequence not found in path '" + location +"'"; + return NULL; + } + if (idx >= sq->card()) + { + message=message + "Error: cannot allocate item in sequence (path is '" + location + "')"; + return NULL; + } + result = sq->getItem(idx); + if (result == NULL) + { + message=message + "Error: item not found in path '" + location + "'"; + return NULL; + } + expected = 3; + finished = OFTrue; + } + else if (token == 3) + { + // we have read a period + expected = 1; + finished = OFFalse; + } + } while (token > 0); + return NULL; +} + + +static OFCondition splitTagPath(OFString &tag_path, + DcmTagKey &key) +{ + OFString target_tag; + unsigned int group,elem; + size_t lpos,rpos; + rpos=tag_path.size()-1; + lpos=rpos; + if (tag_path[rpos]==')') + { + // get opening '(' of target tag; if its not found -> return error + while ( (tag_path[lpos]!='(') && (lpos>0) ) --lpos; + if (tag_path[lpos]!='(') + return makeOFCondition(OFM_dcmdata,22,OF_error,"Invalid tag path!"); + // now lpos and rpos "point" to braces of target tag + // copy target tag from tag path + target_tag=tag_path.substr(lpos,rpos-lpos+1); + // delete target tag from path (inclusive trailing '.') + tag_path.erase(lpos,tag_path.length()-lpos); + // if there's a tag path left, remove the '.', too + if ( !tag_path.empty() && (tag_path[tag_path.length()-1]=='.')) + tag_path.erase(tag_path.length()-1,1); + // parse target_tag into DcmTagKey + if (2 != sscanf(target_tag.c_str(),"(%x,%x)", &group, &elem)) + return makeOFCondition(OFM_dcmdata,22,OF_error,"Invalid target tag!"); + key = DcmTagKey(OFstatic_cast(Uint16, group),OFstatic_cast(Uint16, elem)); + } + else + // otherwise we could have a dictionary name + { + while ( (lpos>0) && (((tag_path[lpos] >= 'a')&&(tag_path[lpos] <= 'z')) || + ((tag_path[lpos] >= 'A')&&(tag_path[lpos] <= 'Z')) || + ((tag_path[lpos] >= '0')&&(tag_path[lpos] <= '9'))) + ) lpos--; + target_tag=tag_path.substr(lpos,rpos-lpos+1); + if (target_tag[0]=='.') target_tag.erase(0,1); + tag_path.erase(lpos,tag_path.length()-lpos); + key=getTagKeyFromDictionary(target_tag); + if ( (key.getGroup()==0xffff) && (key.getElement()==0xffff) ) + { + OFString message=target_tag; + message.append(" not found in dictionary!"); + return makeOFCondition(OFM_dcmdata,22,OF_error,message.c_str()); + } + } + return EC_Normal; +} + + +OFCondition MdfDatasetManager::modifyOrInsertPath(OFString tag_path, + const OFString &value, + const OFBool &only_modify, + const OFBool update_metaheader, + const OFBool ignore_missing_tags, + const OFBool no_reservation_checks) +{ + // if no file loaded: return an error + if (dfile == NULL) + return makeOFCondition(OFM_dcmdata, 22, OF_error, "No file loaded yet!"); + + // find or create specified path + DcmPathProcessor proc; + proc.checkPrivateReservations(!no_reservation_checks); + OFCondition result = proc.findOrCreatePath(dset, tag_path, !only_modify /*create if desired*/); + // if desired, handle tag not found as being not an error + if ( (result == EC_TagNotFound) && only_modify && ignore_missing_tags ) + return EC_Normal; + if (result.bad()) return result; + OFList resultPaths; + Uint32 numResultPaths = proc.getResults(resultPaths); + if (numResultPaths == 0) return EC_IllegalCall; + + // general validity checking; must only be done for one result + OFListIterator(DcmPath*) resultPath = resultPaths.begin(); + // verify that groups 0 (invalid) and 2 (meta header) were not used + if ( (*resultPath)->containsGroup(0) || (*resultPath)->containsGroup(2) ) + return makeOFCondition(OFM_dcmdata, 22, OF_error, "Cannot insert/modify tags with group 0000 or 0002!"); + // also - according to the standard - groups 1,3,5,7,FF are illegal + if ( (*resultPath)->containsGroup(1) || (*resultPath)->containsGroup(3) || + (*resultPath)->containsGroup(5) || (*resultPath)->containsGroup(7) || + (*resultPath)->containsGroup(0xffff) ) + return makeOFCondition(OFM_dcmdata, 22, OF_error, "Groups 0001,0003,0005,0007,FFFF are illegal!"); + + DcmPathNode *lastElement = (*resultPath)->back(); + if (lastElement == NULL) return EC_IllegalCall; + DcmObject *obj = lastElement->m_obj; + if (obj == NULL) return EC_IllegalCall; + // if object at the end is not a leaf, the insertion is completed (or must fail) + if (!obj->isLeaf()) + { + // if user specified a value to be inserted into non-leaf element, return error + if (!value.empty()) + return makeOFCondition(OFM_dcmdata, 22, OF_error, "Cannot put value into non-leaf elements!"); + // non-leaf elements (items/sequences) cannot just be modified + if (only_modify) + return makeOFCondition(OFM_dcmdata, 22, OF_error, "Cannot modify non-leaf elements!"); + // we have inserted an item/sequence at the end -> job completed + return EC_Normal; + } + + // start modifying element value as desired + resultPath = resultPaths.begin(); + while (resultPath != resultPaths.end()) + { + lastElement = (*resultPath)->back(); + if (lastElement == NULL) return EC_IllegalCall; + // if tag is already present, start modify operation + DcmElement *elem = OFstatic_cast(DcmElement*, lastElement->m_obj); + if (elem == NULL) return EC_IllegalCall; + result = startModify(elem, value); + if (result.bad()) return result; + if (update_metaheader) + deleteRelatedMetaheaderTag(elem->getTag()); + resultPath++; + } + return EC_Normal; +} + + +OFCondition MdfDatasetManager::modifyOrInsertFromFile(OFString tag_path, + const OFString &filename, + const OFBool &only_modify, + const OFBool update_metaheader, + const OFBool ignore_missing_tags, + const OFBool no_reservation_checks) +{ + // if no file loaded: return an error + if (dfile == NULL) + return makeOFCondition(OFM_dcmdata, 22, OF_error, "No file loaded yet!"); + + // first, perform some basic checks on the specified file(name) + if (filename.empty()) + return makeOFCondition(OFM_dcmdata, 22, OF_error, "No filename specified to read value from!"); + if (!OFStandard::fileExists(filename)) + return makeOFCondition(OFM_dcmdata, 22, OF_error, "File to read value from does not exist!"); + if (!OFStandard::isReadable(filename)) + return makeOFCondition(OFM_dcmdata, 22, OF_error, "File to read value from is not readable!"); + + // find or create specified path + DcmPathProcessor proc; + proc.checkPrivateReservations(!no_reservation_checks); + OFCondition result = proc.findOrCreatePath(dset, tag_path, !only_modify /*create if desired*/); + // if desired, handle tag not found as being not an error + if ((result == EC_TagNotFound) && only_modify && ignore_missing_tags) + return EC_Normal; + if (result.bad()) return result; + OFList resultPaths; + Uint32 numResultPaths = proc.getResults(resultPaths); + if (numResultPaths == 0) return EC_IllegalCall; + + // general validity checking; must only be done for one result + OFListIterator(DcmPath*) resultPath = resultPaths.begin(); + // verify that groups 0 (invalid) and 2 (meta header) were not used + if ((*resultPath)->containsGroup(0) || (*resultPath)->containsGroup(2)) + return makeOFCondition(OFM_dcmdata,22,OF_error, "Cannot insert/modify tags with group 0000 or 0002!"); + // also - according to the standard - groups 1,3,5,7,FF are illegal + if ((*resultPath)->containsGroup(1) || (*resultPath)->containsGroup(3) || + (*resultPath)->containsGroup(5) || (*resultPath)->containsGroup(7) || + (*resultPath)->containsGroup(0xffff)) + return makeOFCondition(OFM_dcmdata, 22, OF_error, "Groups 0001,0003,0005,0007,FFFF are illegal!"); + + DcmPathNode *lastElement = (*resultPath)->back(); + if (lastElement == NULL) return EC_IllegalCall; + DcmObject *obj = lastElement->m_obj; + if (obj == NULL) return EC_IllegalCall; + // if object at the end is not a leaf, the insertion/modification fails + if (!obj->isLeaf()) + return makeOFCondition(OFM_dcmdata, 22, OF_error, "Cannot put value into non-leaf elements!"); + + // start modifying element value as desired + resultPath = resultPaths.begin(); + while (resultPath != resultPaths.end()) + { + lastElement = (*resultPath)->back(); + if (lastElement == NULL) return EC_IllegalCall; + // if tag is already present, start modify operation + DcmElement *elem = OFstatic_cast(DcmElement*, lastElement->m_obj); + if (elem == NULL) return EC_IllegalCall; + // check whether VR is "unknown" + DcmEVR vr = elem->getTag().getEVR(); + if (ignore_un_modifies && ((vr == EVR_UN) || (vr == EVR_UNKNOWN) || (vr == EVR_UNKNOWN2B))) + { + OFLOG_WARN(mdfdsmanLogger, "will not write value to attribute having VR=UN: " << elem->getTag()); + return EC_Normal; + } + // create stream object for binary file + DcmInputFileStream fileStream(filename.c_str()); + result = fileStream.status(); + if (result.good()) + { + const size_t fileLen = OFStandard::getFileSize(filename); + if (fileLen & 1) + return makeOFCondition(OFM_dcmdata, 22, OF_error, "Cannot insert/modify value with odd length from file!"); + // read element value from binary file (requires even length) + result = elem->createValueFromTempFile(fileStream.newFactory(), OFstatic_cast(Uint32, fileLen), EBO_LittleEndian); + } + if (result.bad()) return result; + if (update_metaheader) + deleteRelatedMetaheaderTag(elem->getTag()); + resultPath++; + } + return EC_Normal; +} + + +OFCondition MdfDatasetManager::modifyAllTags(OFString tag_path, + const OFString &value, + const OFBool update_metaheader, + int &count, + const OFBool ignore_missing_tags) +{ + // if no file loaded: return an error + if (dfile == NULL) + return makeOFCondition(OFM_dcmdata,22,OF_error,"No file loaded yet!"); + DcmTagKey key; + OFCondition result; + + // split tag_path into the path itself and the target tag + result=splitTagPath(tag_path, key); + if ( result.bad() ) + return result; + + // check whether tag with this group can be modified + if (!key.hasValidGroup()) + return makeOFCondition(OFM_dcmdata,22,OF_error,"Invalid group number!"); + + // modify metaheader if necessary; not necessary if not a main level tag + if ( update_metaheader && tag_path.empty() ) + deleteRelatedMetaheaderTag(key); + // this stack will hold result of element search + DcmStack result_stack; + DcmObject *elem; + // get references to all matching tags in dataset and store them in stack + OFLOG_DEBUG(mdfdsmanLogger, "looking for occurences of: " << key.toString()); + result=dset->findAndGetElements(key, result_stack); + // if there are elements found, modify metaheader if necessary + OFLOG_DEBUG(mdfdsmanLogger, "found " << result_stack.card() << " occurences"); + // as long there are matching elements left on the stack + while( result_stack.card() > 0 && result.good() ) + { + // get the top element + elem=result_stack.pop(); + // if user gives e.g. a sequence delimiter,don't try to change it! + if (elem->isLeaf()) + { + // and put new value to element + OFLOG_DEBUG(mdfdsmanLogger, "accessing existing tag for modify operation"); + result=startModify(OFstatic_cast(DcmElement*,elem),value); + if (result.good()) count++; + } + // if user gave "unchangeable" tag: + else result = makeOFCondition(OFM_dcmdata,22,OF_error,"Unable to modify tag!"); + } + // if desired, handle "tag not found" as being OK + if (ignore_missing_tags && (result == EC_TagNotFound)) + return EC_Normal; + return result; +} + + +OFCondition MdfDatasetManager::deleteTag(OFString tag_path, + const OFBool all_tags, + const OFBool ignore_missing_tags) +{ + + // if no file loaded: return an error + if (dfile == NULL) + return makeOFCondition(OFM_dcmdata,22,OF_error,"No file loaded yet!"); + + OFCondition result; + if (all_tags) + { + // split tag path into item path and target tag + DcmTagKey key; + result = splitTagPath(tag_path, key); + if (result.bad()) + return result; // error parsing tag path + + // if group is 0 or 2: abort; deletion of tags with 1,3,5,7 should be allowed + if ( (key.getGroup() == 0) || (key.getGroup() == 2) ) + return makeOFCondition(OFM_dcmdata,22,OF_error, "Cannot delete tags with group 0000 or 0002!"); + + // if tag path still contains characters, user wants to modify item tag + if (!tag_path.empty()) + { + OFString error; + DcmItem *item=NULL; + item = getItemFromPath(*dset, tag_path.c_str(), error); + if (item != NULL) + result = item->findAndDeleteElement(key, all_tags, all_tags); + else + return makeOFCondition(OFM_dcmdata,22,OF_error,error.c_str()); + } + // other user specified single tag without path + else + { + result = dset->findAndDeleteElement(key, all_tags, all_tags); + } + if (ignore_missing_tags && (result == EC_TagNotFound)) + return EC_Normal; + return result; + } + + // do not delete all tags -> use path functions + DcmPathProcessor pathProc; + + Uint32 numDeletions = 0; + result = pathProc.findOrDeletePath(dset, tag_path, numDeletions); + if (ignore_missing_tags && (result == EC_TagNotFound)) + return EC_Normal; + return result; +} + + +OFCondition MdfDatasetManager::deletePrivateData() +{ + // if no file loaded : return an error + if (dfile == NULL) + return makeOFCondition(OFM_dcmdata,22,OF_error,"No file loaded yet!"); + + DcmStack stack; + DcmObject *dobj = NULL; + DcmTagKey tag; + OFCondition status = dset->nextObject(stack, OFTrue); + while (status.good()) + { + dobj = stack.top(); + tag = dobj->getTag(); + if (tag.getGroup() & 1) // private tag ? + { + stack.pop(); + delete OFstatic_cast(DcmItem *, (stack.top()))->remove(dobj); + } + status = dset->nextObject(stack, OFTrue); + } + return EC_Normal; +} + + +OFCondition MdfDatasetManager::generateAndInsertUID(const DcmTagKey& uidKey) +{ + // if no file loaded : return an error + if (dfile==NULL) + return makeOFCondition(OFM_dcmdata,22,OF_error,"No file loaded yet!"); + + OFCondition result; + char uid[100]; + if (uidKey == DCM_StudyInstanceUID) + dcmGenerateUniqueIdentifier(uid, SITE_STUDY_UID_ROOT); + else if (uidKey == DCM_SeriesInstanceUID) + dcmGenerateUniqueIdentifier(uid, SITE_SERIES_UID_ROOT); + else if (uidKey == DCM_SOPInstanceUID) + { + dcmGenerateUniqueIdentifier(uid, SITE_INSTANCE_UID_ROOT); + // force meta-header to refresh SOP Class/Instance UIDs. + DcmItem *meta_info = dfile->getMetaInfo(); + if (meta_info) + { + delete meta_info->remove(DCM_MediaStorageSOPInstanceUID); + } + } + else return EC_IllegalCall; + result = dset->putAndInsertString(uidKey, uid); + return result; +} + + +OFCondition MdfDatasetManager::saveFile(const char *file_name, + E_TransferSyntax opt_xfer, + E_EncodingType opt_enctype, + E_GrpLenEncoding opt_glenc, + E_PaddingEncoding opt_padenc, + OFCmdUnsignedInt opt_filepad, + OFCmdUnsignedInt opt_itempad, + OFBool opt_dataset) +{ + // if no file loaded: return an error + if (dfile==NULL) + return makeOFCondition(OFM_dcmdata,22,OF_error,"No file loaded yet!"); + + OFCondition result; + /* check whether transfer syntax is possible */ + if ( (opt_xfer==EXS_Unknown) || (dfile->canWriteXfer(opt_xfer)) ) + { + /* check whether pixel data is compressed */ + if (opt_dataset && DcmXfer(opt_xfer).isEncapsulated()) + { + OFLOG_WARN(mdfdsmanLogger, "encapsulated pixel data requires file format, ignoring --write-dataset"); + opt_dataset = OFFalse; + } + /* be sure that we have a known transfer syntax. The original xfer can + * be unknown if the dataset was created in memory, or if the originally + * loaded file does not contain attributes which could make sense if + * it is a template file that should be processed with dcmodify. + */ + if ((dfile->getDataset()->getOriginalXfer() == EXS_Unknown) && (opt_xfer == EXS_Unknown)) + { + opt_xfer = EXS_LittleEndianExplicit; + } + /* write DICOM file */ + result = dfile->saveFile(file_name, opt_xfer, opt_enctype, opt_glenc, + opt_padenc, + OFstatic_cast(Uint32, opt_filepad), + OFstatic_cast(Uint32, opt_itempad), + (opt_dataset) ? EWM_dataset : EWM_fileformat); + + } else { + OFLOG_DEBUG(mdfdsmanLogger, "no conversion to transfer syntax " << DcmXfer(opt_xfer).getXferName() << " possible!"); + result = EC_CannotChangeRepresentation; + } + // save file + OFLOG_INFO(mdfdsmanLogger, "Saving current dataset to file: " << file_name); + return result; +} + + +OFCondition MdfDatasetManager::saveFile() +{ + // save file without changing any parameters + return saveFile(current_file.c_str(), EXS_Unknown, EET_UndefinedLength, + EGL_recalcGL, EPD_noChange, 0, 0, OFFalse); +} + + +OFCondition MdfDatasetManager::startModify(DcmElement *elem, + const OFString &value) +{ + OFCondition result; + DcmEVR vr = elem->getTag().getEVR(); + if ( ignore_un_modifies && ((vr == EVR_UN) || (vr == EVR_UNKNOWN) || (vr == EVR_UNKNOWN2B))) + { + OFLOG_WARN(mdfdsmanLogger, "will not write value to attribute having VR=UN: " << elem->getTag().toString()); + return EC_Normal; + } + // start putString function being defined on all VRs + result = elem->putString(value.c_str()); + return result; +} + + +void MdfDatasetManager::deleteRelatedMetaheaderTag(const DcmTagKey &key) +{ + DcmItem *meta_info=dfile->getMetaInfo(); + if (meta_info) + { + if (key==DCM_SOPInstanceUID) + delete meta_info->remove(DCM_MediaStorageSOPInstanceUID); + else if (key==DCM_SOPClassUID) + delete meta_info->remove(DCM_MediaStorageSOPClassUID); + } +} + + +DcmDataset* MdfDatasetManager::getDataset() +{ + return dset; +} + + +DcmFileFormat* MdfDatasetManager::getFileFormat() +{ + return dfile; +} + + +OFString MdfDatasetManager::getFilename() const +{ + return current_file; +} + + +OFBool MdfDatasetManager::isTagInDictionary(const DcmTagKey &search_key) +{ + const DcmDataDictionary& globalDataDict = dcmDataDict.rdlock(); + const DcmDictEntry *dicent = globalDataDict.findEntry(search_key,NULL); + // successfull lookup in dictionary -> translate to tag and return + dcmDataDict.unlock(); + if (dicent) + return OFTrue; + else return OFFalse; +} + + +void MdfDatasetManager::setModifyUNValues(OFBool modifyUNValues) +{ + ignore_un_modifies = !modifyUNValues; +} + + +MdfDatasetManager::~MdfDatasetManager() +{ + // cleanup + delete dfile; +} diff --git a/dcmdata/apps/mdfdsman.h b/dcmdata/apps/mdfdsman.h new file mode 100644 index 00000000..7c5214fc --- /dev/null +++ b/dcmdata/apps/mdfdsman.h @@ -0,0 +1,258 @@ +/* + * + * Copyright (C) 2003-2010, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Michael Onken + * + * Purpose: Class for modifying DICOM files + * + */ + +#ifndef MDFDSMAN_H +#define MDFDSMAN_H + +#include "dcmtk/config/osconfig.h" // make sure OS specific configuration is included first + +#include "dcmtk/ofstd/ofcond.h" +#include "dcmtk/dcmdata/dctagkey.h" +#include "dcmtk/dcmdata/dcxfer.h" + + +// forward declarations +class DcmDataset; +class DcmFileFormat; +class DcmElement; + + +/** This class encapsulates data structures and operations for modifying + * Dicom files. Therefore it allows the process of load->modify->save to + * provide this service. + */ +class MdfDatasetManager +{ +public: + + /** Constructor, initializes member-variables + */ + MdfDatasetManager(); + + /** Destructor + */ + ~MdfDatasetManager(); + + /** Loads a file into dataset manager + * @param file_name file to be loaded + @param readMode read file with or without metaheader. Default=autodetect + @param xfer try to read with this transfer syntax. Default=autodetect + @param createIfNecessary If true, the file is created if it does not exist + * @return returns EC_normal if everything is ok, else an error + */ + OFCondition loadFile(const char *file_name, + const E_FileReadMode readMode = ERM_autoDetect, + const E_TransferSyntax xfer = EXS_Unknown, + const OFBool createIfNecessary = OFFalse); + + /** Modifies/Inserts a path (with a specific value if desired). + * @param tag_path path to item/element + * @param value denotes new value of tag + * @param only_modify if true, only existing tags are processed. If false, + * any not existing tag is inserted + * @param update_metaheader updates metaheader UIDs, if related UIDs in + * dataset are changed (default=true) + * @param ignore_missing_tags if true, tags that could not be found + * while modifying (only_modify must be true) + * are handled as non-errors + * @param no_reservation_checks if true, any missing private reservation + * tags are ignored when inserting private + * tags. Only makes sense w/o only_modify + * @return returns EC_normal if everything is ok, else an error + */ + OFCondition modifyOrInsertPath(OFString tag_path, + const OFString &value, + const OFBool &only_modify, + const OFBool update_metaheader = OFTrue, + const OFBool ignore_missing_tags = OFFalse, + const OFBool no_reservation_checks = OFFalse); + + /** Modifies/Inserts a path with a specific value read from file + * @param tag_path path to item/element + * @param filename name of the file from which the value should be read + * @param only_modify if true, only existing tags are processed. If false, + * any not existing tag is inserted + * @param update_metaheader updates metaheader UIDs, if related UIDs in + * dataset are changed (default=true) + * @param ignore_missing_tags if true, tags that could not be found + * while modifying (only_modify must be true) + * are handled as non-errors + * @param no_reservation_checks if true, any missing private reservation + * tags are ignored when inserting private + * tags. Only makes sense w/o only_modify + * @return returns EC_normal if everything is ok, else an error + */ + OFCondition modifyOrInsertFromFile(OFString tag_path, + const OFString &filename, + const OFBool &only_modify, + const OFBool update_metaheader = OFTrue, + const OFBool ignore_missing_tags = OFFalse, + const OFBool no_reservation_checks = OFFalse); + + /** Modifies all matching tags in dataset to a new value + * @param tag_path denotes, which tag to modify + * @param value denotes new value of tag + * @param update_metaheader if true, metaheader uids are updated, + * if related dataset uids are changed, (default=true) + * @param count returns holds the number of tags, that were affected + * @param ignore_missing_tags if true, tags that could not be found + * while modifying (only_modify must be true) + * are handled as non-errors + * @return returns EC_normal if everything is ok, else an error + */ + OFCondition modifyAllTags(OFString tag_path, + const OFString &value, + const OFBool update_metaheader, + int &count, + const OFBool ignore_missing_tags = OFFalse); + + /** Deletes tag in dataset + * @param tag_path holds complete path to tag + * @param all_tags if true, tag is deleted at all levels of dataset, + * else only 1st level is accessed + * @param ignore_missing_tags if true, tags that could not be found + * while modifying (only_modify must be true) + * are handled as non-errors + * @return returns EC_normal if everything is ok, else an error + */ + OFCondition deleteTag(OFString tag_path, + const OFBool all_tags, + const OFBool ignore_missing_tags); + + /** Deletes all private data from file, ie. all tags having + * odd group numbers. + * @return EC_Normal, if deletion was successful; error code otherwise + */ + OFCondition deletePrivateData(); + + /** Inserts new Study, Series or SOP Instance UID. If SOP Instance + * UID is generated, the related tag in the metaheader is deleted, too + * so that the new UID is also applied there when saving to disk later. + * @param uidkey [in] The Instance UID to insert (study, series or sop + * instance UID key permitted). + * @return EC_Normal, if insertion was successful, error otherwise + */ + OFCondition generateAndInsertUID(const DcmTagKey &uidKey); + + /** Saves current dataset back to a file. Caution: After saving + * MdfDatasetManager keeps working on old filename. + * @param file_name filename to save to + * @param opt_xfer transfer syntax to save to (EXS_Unknown: dont change) + * @param opt_enctype write with explicit or implicit length encoding + * @param opt_glenc option to set group lenghth calculation mode + * @param opt_padenc sets padding option + * @param opt_filepad pad file to a multiple of this options value + * @param opt_itempad pad item to a multiple of this options value + * @param opt_dataset if true:ony write only dataset, else write fileformat + * @return returns EC_normal if everything is ok, else an error + */ + OFCondition saveFile(const char *file_name, + E_TransferSyntax opt_xfer = EXS_Unknown, + E_EncodingType opt_enctype = EET_UndefinedLength, + E_GrpLenEncoding opt_glenc = EGL_recalcGL, + E_PaddingEncoding opt_padenc = EPD_noChange, + OFCmdUnsignedInt opt_filepad = 0, + OFCmdUnsignedInt opt_itempad = 0, + OFBool opt_dataset = OFFalse); + + /** Saves current dataset back to file using original filename and original + * parameters like transfer syntax, padding etc. + * @return returns EC_normal if everything is ok, else an error + */ + OFCondition saveFile(); + + /** Returns the dataset, that this MdfDatasetManager handles. + * You should use the returned object with care to avoid + * sideeffects with other class methods, that modify this object, too. + * @return returns the dataset, this MdfDatasetManager manages and NULL, if + * no dataset is loaded + */ + DcmDataset* getDataset(); + + + /** Returns the DcmFileFormat, that this MdfDatasetManager handles. + * You should use the returned object with care to avoid + * sideeffects with other class methods, that modify this object, too. + * @return returns the DcmFileFormat, this MdfDatasetManager manages and + * NULL, if no file is loaded + */ + DcmFileFormat* getFileFormat(); + + /** Returns filename of the file, that's loaded currently. + * @return returns filename and "" if no file is loaded. + */ + OFString getFilename() const; + + /** Sets whether attributes with VR of UN should be modified or + * left alone. + * @param modifyUNValues [in] If set, UN values will be modified (default) + */ + void setModifyUNValues(OFBool modifyUNValues); + +protected: + + /** modifies element to a specific value + * @param elem element, that should be changed + * @param value the value, the element should be changed to + * @return OFCondition, which returns an error code if an error occurs + */ + OFCondition startModify(DcmElement *elem, + const OFString &value); + + /** If key is the tag for SOPInstanceUID or SOPClassUID, then this function + * removes the related MediaStorage UIDs from the metaheader. The + * metaheader is then updated automagically when the file is saved back to + * disk. + * @param key tag to examine + */ + void deleteRelatedMetaheaderTag(const DcmTagKey &key); + + /** Returns true, if given tag key can be found in dictionary + * @param search_key tag to lookup + * @return OFTrue if tag could be found, else OFFalse + */ + OFBool isTagInDictionary(const DcmTagKey &search_key); + +private: + + /// name of file, that is loaded currently + OFString current_file; + + /// will hold file to modify + DcmFileFormat *dfile; + + /// will hold the dataset, that should be modified + DcmDataset *dset; + + /// if enabled, no value modifications on attributes having VR of UN + /// are not executed + OFBool ignore_un_modifies; + + /** private undefined assignment operator + */ + MdfDatasetManager &operator=(const MdfDatasetManager &); + + /** private undefined copy constructor + */ + MdfDatasetManager(const MdfDatasetManager &); +}; + +#endif // MDFDSMAN_H diff --git a/dcmdata/apps/pdf2dcm.cc b/dcmdata/apps/pdf2dcm.cc new file mode 100644 index 00000000..9132008e --- /dev/null +++ b/dcmdata/apps/pdf2dcm.cc @@ -0,0 +1,593 @@ +/* + * + * Copyright (C) 2005-2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Marco Eichelberg + * + * Purpose: Convert PDF file to DICOM format + * + */ + + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#define INCLUDE_CSTDLIB +#define INCLUDE_CSTDIO +#define INCLUDE_CSTRING +#include "dcmtk/ofstd/ofstdinc.h" + +#ifdef HAVE_GUSI_H +#include +#endif + +BEGIN_EXTERN_C +#ifdef HAVE_FCNTL_H +#include /* for O_RDONLY */ +#endif +#ifdef HAVE_SYS_TYPES_H +#include /* required for sys/stat.h */ +#endif +#ifdef HAVE_SYS_STAT_H +#include /* for stat, fstat */ +#endif +END_EXTERN_C + +#include "dcmtk/dcmdata/dctk.h" +#include "dcmtk/dcmdata/cmdlnarg.h" +#include "dcmtk/ofstd/ofconapp.h" +#include "dcmtk/dcmdata/dcuid.h" /* for dcmtk version name */ +#include "dcmtk/ofstd/ofstd.h" +#include "dcmtk/ofstd/ofdatime.h" +#include "dcmtk/dcmdata/dccodec.h" + +#ifdef WITH_ZLIB +#include /* for zlibVersion() */ +#endif + +#define OFFIS_CONSOLE_APPLICATION "pdf2dcm" + +static OFLogger pdf2dcmLogger = OFLog::getLogger("dcmtk.apps." OFFIS_CONSOLE_APPLICATION); + +static char rcsid[] = "$dcmtk: " OFFIS_CONSOLE_APPLICATION " v" + OFFIS_DCMTK_VERSION " " OFFIS_DCMTK_RELEASEDATE " $"; + +static OFCondition createHeader( + DcmItem *dataset, + const char *opt_patientName, + const char *opt_patientID, + const char *opt_patientBirthdate, + const char *opt_patientSex, + OFBool opt_burnedInAnnotation, + const char *opt_studyUID, + const char *opt_seriesUID, + const char *opt_documentTitle, + const char *opt_conceptCSD, + const char *opt_conceptCV, + const char *opt_conceptCM, + Sint32 opt_instanceNumber) +{ + OFCondition result = EC_Normal; + char buf[80]; + + // insert empty type 2 attributes + if (result.good()) result = dataset->insertEmptyElement(DCM_StudyDate); + if (result.good()) result = dataset->insertEmptyElement(DCM_StudyTime); + if (result.good()) result = dataset->insertEmptyElement(DCM_AccessionNumber); + if (result.good()) result = dataset->insertEmptyElement(DCM_Manufacturer); + if (result.good()) result = dataset->insertEmptyElement(DCM_ReferringPhysicianName); + if (result.good()) result = dataset->insertEmptyElement(DCM_StudyID); + if (result.good()) result = dataset->insertEmptyElement(DCM_ContentDate); + if (result.good()) result = dataset->insertEmptyElement(DCM_ContentTime); + if (result.good()) result = dataset->insertEmptyElement(DCM_AcquisitionDateTime); + + if (result.good() && opt_conceptCSD && opt_conceptCV && opt_conceptCM) + { + result = DcmCodec::insertCodeSequence(dataset, DCM_ConceptNameCodeSequence, opt_conceptCSD, opt_conceptCV, opt_conceptCM); + } + else + { + result = dataset->insertEmptyElement(DCM_ConceptNameCodeSequence); + } + + // insert const value attributes + if (result.good()) result = dataset->putAndInsertString(DCM_SpecificCharacterSet, "ISO_IR 100"); + if (result.good()) result = dataset->putAndInsertString(DCM_SOPClassUID, UID_EncapsulatedPDFStorage); + // we are now using "DOC" for the modality, which seems to be more appropriate than "OT" (see CP-749) + if (result.good()) result = dataset->putAndInsertString(DCM_Modality, "DOC"); + if (result.good()) result = dataset->putAndInsertString(DCM_ConversionType, "WSD"); + if (result.good()) result = dataset->putAndInsertString(DCM_MIMETypeOfEncapsulatedDocument, "application/pdf"); + + // there is no way we could determine a meaningful series number, so we just use a constant. + if (result.good()) result = dataset->putAndInsertString(DCM_SeriesNumber, "1"); + + // insert variable value attributes + if (result.good()) result = dataset->putAndInsertString(DCM_DocumentTitle, opt_documentTitle); + if (result.good()) result = dataset->putAndInsertString(DCM_PatientName, opt_patientName); + if (result.good()) result = dataset->putAndInsertString(DCM_PatientID, opt_patientID); + if (result.good()) result = dataset->putAndInsertString(DCM_PatientBirthDate, opt_patientBirthdate); + if (result.good()) result = dataset->putAndInsertString(DCM_PatientSex, opt_patientSex); + if (result.good()) result = dataset->putAndInsertString(DCM_BurnedInAnnotation, opt_burnedInAnnotation ? "YES" : "NO"); + + sprintf(buf, "%ld", OFstatic_cast(long, opt_instanceNumber)); + if (result.good()) result = dataset->putAndInsertString(DCM_InstanceNumber, buf); + + dcmGenerateUniqueIdentifier(buf, SITE_INSTANCE_UID_ROOT); + if (result.good()) result = dataset->putAndInsertString(DCM_StudyInstanceUID, opt_studyUID); + if (result.good()) result = dataset->putAndInsertString(DCM_SeriesInstanceUID, opt_seriesUID); + if (result.good()) result = dataset->putAndInsertString(DCM_SOPInstanceUID, buf); + + // set instance creation date and time + OFString s; + if (result.good()) result = DcmDate::getCurrentDate(s); + if (result.good()) result = dataset->putAndInsertOFStringArray(DCM_InstanceCreationDate, s); + if (result.good()) result = DcmTime::getCurrentTime(s); + if (result.good()) result = dataset->putAndInsertOFStringArray(DCM_InstanceCreationTime, s); + + return result; +} + +static OFCondition insertPDFFile( + DcmItem *dataset, + const char *filename) +{ + size_t fileSize = 0; + struct stat fileStat; + char buf[100]; + + if (0 == stat(filename, &fileStat)) fileSize = OFstatic_cast(size_t, fileStat.st_size); + else + { + OFLOG_ERROR(pdf2dcmLogger, "file " << filename << " not found"); + return EC_IllegalCall; + } + + if (fileSize == 0) + { + OFLOG_ERROR(pdf2dcmLogger, "file " << filename << " is empty"); + return EC_IllegalCall; + } + + FILE *pdffile = fopen(filename, "rb"); + if (pdffile == NULL) + { + OFLOG_ERROR(pdf2dcmLogger, "unable to read file " << filename); + return EC_IllegalCall; + } + + size_t buflen = 100; + if (fileSize < buflen) buflen = fileSize; + if (buflen != fread(buf, 1, buflen, pdffile)) + { + OFLOG_ERROR(pdf2dcmLogger, "read error in file " << filename); + fclose(pdffile); + return EC_IllegalCall; + } + + // check magic word for PDF file + if (0 != strncmp("%PDF-", buf, 5)) + { + OFLOG_ERROR(pdf2dcmLogger, "file " << filename << " is not a PDF file"); + fclose(pdffile); + return EC_IllegalCall; + } + + // check PDF version number + char *version = buf + 5; + OFBool found = OFFalse; + for (int i = 0; i < 5; ++i) + { + if (version[i] == 10 || version[i] == 13) + { + version[i] = 0; // insert end of string + found = OFTrue; + break; + } + } + + if (! found) + { + OFLOG_ERROR(pdf2dcmLogger, "file " << filename << ": unable to decode PDF version number"); + fclose(pdffile); + return EC_IllegalCall; + } + + OFLOG_INFO(pdf2dcmLogger, "file " << filename << ": PDF " << version << ", " << (fileSize + 1023) / 1024 << "kB"); + + if (0 != fseek(pdffile, 0, SEEK_SET)) + { + OFLOG_ERROR(pdf2dcmLogger, "file " << filename << ": seek error"); + fclose(pdffile); + return EC_IllegalCall; + } + + OFCondition result = EC_Normal; + DcmPolymorphOBOW *elem = new DcmPolymorphOBOW(DCM_EncapsulatedDocument); + if (elem) + { + size_t numBytes = fileSize; + if (numBytes & 1) ++numBytes; + Uint8 *bytes = NULL; + result = elem->createUint8Array(OFstatic_cast(Uint32, numBytes), bytes); + if (result.good()) + { + // blank pad byte + bytes[numBytes - 1] = 0; + + // read PDF content + if (fileSize != fread(bytes, 1, fileSize, pdffile)) + { + OFLOG_ERROR(pdf2dcmLogger, "read error in file " << filename); + result = EC_IllegalCall; + } + } + } else result = EC_MemoryExhausted; + + // if successful, insert element into dataset + if (result.good()) result = dataset->insert(elem); else delete elem; + + // close file + fclose(pdffile); + + return result; +} + + +static void createIdentifiers( + OFBool opt_readSeriesInfo, + const char *opt_seriesFile, + OFString& studyUID, + OFString& seriesUID, + OFString& patientName, + OFString& patientID, + OFString& patientBirthDate, + OFString& patientSex, + Sint32& incrementedInstance) +{ + char buf[100]; + if (opt_seriesFile) + { + DcmFileFormat dfile; + OFCondition cond = dfile.loadFile(opt_seriesFile, EXS_Unknown, EGL_noChange); + if (cond.bad()) + { + OFLOG_WARN(pdf2dcmLogger, cond.text() << ": reading file: "<< opt_seriesFile); + } + else + { + const char *c = NULL; + DcmDataset *dset = dfile.getDataset(); + if (dset) + { + // read patient attributes + c = NULL; + if (dset->findAndGetString(DCM_PatientName, c).good() && c) patientName = c; + c = NULL; + if (dset->findAndGetString(DCM_PatientID, c).good() && c) patientID = c; + c = NULL; + if (dset->findAndGetString(DCM_PatientBirthDate, c).good() && c) patientBirthDate = c; + c = NULL; + if (dset->findAndGetString(DCM_PatientSex, c).good() && c) patientSex = c; + + // read study attributes + c = NULL; + if (dset->findAndGetString(DCM_StudyInstanceUID, c).good() && c) studyUID = c; + + // read series attributes + if (opt_readSeriesInfo) + { + c = NULL; + if (dset->findAndGetString(DCM_SeriesInstanceUID, c).good() && c) seriesUID = c; + if (dset->findAndGetSint32(DCM_InstanceNumber, incrementedInstance).good()) ++incrementedInstance; else incrementedInstance = 0; + } + } + } + } + if (studyUID.empty()) + { + dcmGenerateUniqueIdentifier(buf, SITE_STUDY_UID_ROOT); + studyUID = buf; + } + if (seriesUID.empty()) + { + dcmGenerateUniqueIdentifier(buf, SITE_SERIES_UID_ROOT); + seriesUID = buf; + } +} + + +#define SHORTCOL 3 +#define LONGCOL 19 + +int main(int argc, char *argv[]) +{ + +#ifdef HAVE_GUSI_H + GUSISetup(GUSIwithSIOUXSockets); + GUSISetup(GUSIwithInternetSockets); +#endif + + const char *opt_ifname = NULL; + const char *opt_ofname = NULL; + + E_TransferSyntax opt_oxfer = EXS_LittleEndianExplicit; + E_GrpLenEncoding opt_oglenc = EGL_withoutGL; + E_EncodingType opt_oenctype = EET_ExplicitLength; + E_PaddingEncoding opt_opadenc = EPD_withoutPadding; + OFCmdUnsignedInt opt_filepad = 0; + OFCmdUnsignedInt opt_itempad = 0; + + // document specific options + const char * opt_seriesFile = NULL; + const char * opt_patientName = NULL; + const char * opt_patientID = NULL; + const char * opt_patientBirthdate = NULL; + const char * opt_documentTitle = NULL; + const char * opt_conceptCSD = NULL; + const char * opt_conceptCV = NULL; + const char * opt_conceptCM = NULL; + + OFBool opt_readSeriesInfo = OFFalse; + const char * opt_patientSex = NULL; + OFBool opt_annotation = OFTrue; + OFCmdSignedInt opt_instance = 1; + OFBool opt_increment = OFFalse; + + OFConsoleApplication app(OFFIS_CONSOLE_APPLICATION , "Convert PDF file to DICOM", rcsid); + OFCommandLine cmd; + cmd.setOptionColumns(LONGCOL, SHORTCOL); + cmd.setParamColumn(LONGCOL + SHORTCOL + 4); + + cmd.addParam("pdffile-in", "PDF input filename to be converted"); + cmd.addParam("dcmfile-out", "DICOM output filename"); + + cmd.addGroup("general options:", LONGCOL, SHORTCOL + 2); + cmd.addOption("--help", "-h", "print this help text and exit", OFCommandLine::AF_Exclusive); + cmd.addOption("--version", "print version information and exit", OFCommandLine::AF_Exclusive); + OFLog::addOptions(cmd); + + cmd.addGroup("DICOM document options:"); + cmd.addSubGroup("burned-in annotation:"); + cmd.addOption("--annotation-yes", "+an", "PDF contains patient identifying data (default)"); + cmd.addOption("--annotation-no", "-an", "PDF does not contain patient identifying data"); + + cmd.addSubGroup("document title:"); + cmd.addOption("--title", "+t", 1, "[t]itle: string (default: empty)", + "document title"); + cmd.addOption("--concept-name", "+cn", 3, "[CSD] [CV] [CM]: string (default: empty)", + "document title as concept name code sequence\n" + "with coding scheme designator CSD, code value CV\n" + "and code meaning CM"); + cmd.addSubGroup("patient data:"); + cmd.addOption("--patient-name", "+pn", 1, "[n]ame: string", + "patient's name in DICOM PN syntax"); + cmd.addOption("--patient-id", "+pi", 1, "[i]d: string", + "patient identifier"); + cmd.addOption("--patient-birthdate", "+pb", 1, "[d]ate: string (YYYYMMDD)", + "patient's birth date"); + cmd.addOption("--patient-sex", "+ps", 1, "[s]ex: string (M, F or O)", + "patient's sex"); + + cmd.addSubGroup("study and series:"); + cmd.addOption("--generate", "+sg", "generate new study and series UIDs (default)"); + cmd.addOption("--study-from", "+st", 1, "[f]ilename: string", + "read patient/study data from DICOM file"); + cmd.addOption("--series-from", "+se", 1, "[f]ilename: string", + "read patient/study/series data from DICOM file"); + cmd.addSubGroup("instance number:"); + cmd.addOption("--instance-one", "+i1", "use instance number 1 (default, not with +se)"); + cmd.addOption("--instance-inc", "+ii", "increment instance number (only with +se)"); + cmd.addOption("--instance-set", "+is", 1, "[i]nstance number: integer", "use instance number i"); + + /* evaluate command line */ + prepareCmdLineArgs(argc, argv, OFFIS_CONSOLE_APPLICATION); + if (app.parseCommandLine(cmd, argc, argv)) + { + /* check exclusive options first */ + if (cmd.hasExclusiveOption()) + { + if (cmd.findOption("--version")) + { + app.printHeader(OFTrue /*print host identifier*/); + COUT << OFendl << "External libraries used:"; +#ifdef WITH_ZLIB + COUT << OFendl << "- ZLIB, Version " << zlibVersion() << OFendl; +#else + COUT << " none" << OFendl; +#endif + return 0; + } + } + + /* command line parameters and options */ + cmd.getParam(1, opt_ifname); + cmd.getParam(2, opt_ofname); + + OFLog::configureFromCommandLine(cmd, app); + + dcmEnableGenerationOfNewVRs(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--generate")) + { + opt_seriesFile = NULL; + opt_readSeriesInfo = OFFalse; + } + if (cmd.findOption("--series-from")) + { + app.checkValue(cmd.getValue(opt_seriesFile)); + opt_readSeriesInfo = OFTrue; + } + if (cmd.findOption("--study-from")) + { + app.checkValue(cmd.getValue(opt_seriesFile)); + opt_readSeriesInfo = OFFalse; + } + cmd.endOptionBlock(); + + if (cmd.findOption("--title")) + { + app.checkValue(cmd.getValue(opt_documentTitle)); + } + + if (cmd.findOption("--concept-name")) + { + app.checkValue(cmd.getValue(opt_conceptCSD)); + app.checkValue(cmd.getValue(opt_conceptCV)); + app.checkValue(cmd.getValue(opt_conceptCM)); + } + + if (cmd.findOption("--patient-name")) + { + app.checkValue(cmd.getValue(opt_patientName)); + app.checkConflict("--patient-name", "--study-from or --series-from", opt_seriesFile != NULL); + } + if (cmd.findOption("--patient-id")) + { + app.checkValue(cmd.getValue(opt_patientID)); + app.checkConflict("--patient-id", "--study-from or --series-from", opt_seriesFile != NULL); + } + if (cmd.findOption("--patient-birthdate")) + { + app.checkValue(cmd.getValue(opt_patientBirthdate)); + app.checkConflict("--patient-birthdate", "--study-from or --series-from", opt_seriesFile != NULL); + } + if (cmd.findOption("--patient-sex")) + { + app.checkValue(cmd.getValue(opt_patientSex)); + app.checkConflict("--patient-sex", "--study-from or --series-from", opt_seriesFile != NULL); + } + + cmd.beginOptionBlock(); + if (cmd.findOption("--annotation-yes")) + { + opt_annotation = OFTrue; + } + if (cmd.findOption("--annotation-no")) + { + opt_annotation = OFTrue; + } + cmd.endOptionBlock(); + + // initialize default for --series-from + if (opt_seriesFile && opt_readSeriesInfo) opt_increment = OFTrue; + + cmd.beginOptionBlock(); + if (cmd.findOption("--instance-one")) + { + app.checkConflict("--instance-one", "--series-from", (opt_seriesFile != NULL) && opt_readSeriesInfo); + opt_increment = OFFalse; + opt_instance = 1; + } + if (cmd.findOption("--instance-inc")) + { + app.checkDependence("--instance-inc", "--series-from", (opt_seriesFile != NULL) && opt_readSeriesInfo); + opt_increment = OFTrue; + } + if (cmd.findOption("--instance-set")) + { + opt_increment = OFFalse; + app.checkValue(cmd.getValueAndCheckMin(opt_instance, 1)); + } + } + + /* print resource identifier */ + OFLOG_DEBUG(pdf2dcmLogger, rcsid << OFendl); + + /* make sure data dictionary is loaded */ + if (!dcmDataDict.isDictionaryLoaded()) + { + OFLOG_WARN(pdf2dcmLogger, "no data dictionary loaded, check environment variable: " + << DCM_DICT_ENVIRONMENT_VARIABLE); + } + + // read raw file + if ((opt_ifname == NULL) || (strlen(opt_ifname) == 0)) + { + OFLOG_FATAL(pdf2dcmLogger, "invalid filename: "); + return 1; + } + + // create study and series UID + OFString studyUID; + OFString seriesUID; + OFString patientName; + OFString patientID; + OFString patientBirthDate; + OFString patientSex; + Sint32 incrementedInstance = 0; + + if (opt_patientName) patientName = opt_patientName; + if (opt_patientID) patientID = opt_patientID; + if (opt_patientBirthdate) patientBirthDate = opt_patientBirthdate; + if (opt_patientSex) patientSex = opt_patientSex; + + createIdentifiers(opt_readSeriesInfo, opt_seriesFile, studyUID, seriesUID, patientName, patientID, patientBirthDate, patientSex, incrementedInstance); + if (opt_increment) opt_instance = incrementedInstance; + + OFLOG_INFO(pdf2dcmLogger, "creating encapsulated PDF object"); + + DcmFileFormat fileformat; + + OFCondition result = insertPDFFile(fileformat.getDataset(), opt_ifname); + if (result.bad()) + { + OFLOG_ERROR(pdf2dcmLogger, "unable to create PDF DICOM encapsulation"); + return 10; + } + if (result.bad()) return 10; + + // now we need to generate an instance number that is guaranteed to be unique within a series. + + result = createHeader(fileformat.getDataset(), patientName.c_str(), patientID.c_str(), + patientBirthDate.c_str(), patientSex.c_str(), opt_annotation, studyUID.c_str(), + seriesUID.c_str(), opt_documentTitle, opt_conceptCSD, opt_conceptCV, opt_conceptCM, OFstatic_cast(Sint32, opt_instance)); + + if (result.bad()) + { + OFLOG_ERROR(pdf2dcmLogger, "unable to create DICOM header: " << result.text()); + return 10; + } + + OFLOG_INFO(pdf2dcmLogger, "writing encapsulated PDF object as file " << opt_ofname); + + OFCondition error = EC_Normal; + + OFLOG_INFO(pdf2dcmLogger, "Check if new output transfer syntax is possible"); + + DcmXfer opt_oxferSyn(opt_oxfer); + + fileformat.getDataset()->chooseRepresentation(opt_oxfer, NULL); + if (fileformat.getDataset()->canWriteXfer(opt_oxfer)) + { + OFLOG_INFO(pdf2dcmLogger, "Output transfer syntax " << opt_oxferSyn.getXferName() << " can be written"); + } else { + OFLOG_ERROR(pdf2dcmLogger, "No conversion to transfer syntax " << opt_oxferSyn.getXferName() << " possible!"); + return 1; + } + + OFLOG_INFO(pdf2dcmLogger, "write converted DICOM file with metaheader"); + + error = fileformat.saveFile(opt_ofname, opt_oxfer, opt_oenctype, opt_oglenc, opt_opadenc, + OFstatic_cast(Uint32, opt_filepad), OFstatic_cast(Uint32, opt_itempad)); + + if (error.bad()) + { + OFLOG_ERROR(pdf2dcmLogger, error.text() << ": writing file: " << opt_ofname); + return 1; + } + + OFLOG_INFO(pdf2dcmLogger, "conversion successful"); + + return 0; +} diff --git a/dcmdata/apps/xml2dcm.cc b/dcmdata/apps/xml2dcm.cc new file mode 100644 index 00000000..8eb34966 --- /dev/null +++ b/dcmdata/apps/xml2dcm.cc @@ -0,0 +1,990 @@ +/* + * + * Copyright (C) 2003-2015, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Joerg Riesmeier + * + * Purpose: Convert XML document to DICOM file or data set + * + */ + + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/dcmdata/dctk.h" +#include "dcmtk/dcmdata/dcpxitem.h" /* for class DcmPixelItem */ +#include "dcmtk/dcmdata/cmdlnarg.h" +#include "dcmtk/ofstd/ofstd.h" +#include "dcmtk/ofstd/ofconapp.h" +#include "dcmtk/dcmdata/dcostrmz.h" /* for dcmZlibCompressionLevel */ + +#define INCLUDE_CSTDARG +#include "dcmtk/ofstd/ofstdinc.h" + +#ifdef WITH_ZLIB +#include /* for zlibVersion() */ +#endif + +#define OFFIS_CONSOLE_APPLICATION "xml2dcm" +#define OFFIS_CONSOLE_DESCRIPTION "Convert XML document to DICOM file or data set" + +// currently not used since DTD is always retrieved from XML document +//#define DOCUMENT_TYPE_DEFINITION_FILE "dcm2xml.dtd" + +static OFLogger xml2dcmLogger = OFLog::getLogger("dcmtk.apps." OFFIS_CONSOLE_APPLICATION); +static OFLogger xmlLogger = OFLog::getLogger("dcmtk.apps." OFFIS_CONSOLE_APPLICATION ".libxml"); + +static char rcsid[] = "$dcmtk: " OFFIS_CONSOLE_APPLICATION " v" + OFFIS_DCMTK_VERSION " " OFFIS_DCMTK_RELEASEDATE " $"; + +// ******************************************** + +#ifdef WITH_LIBXML + +#include + +// stores pointer to character encoding handler +static xmlCharEncodingHandlerPtr EncodingHandler = NULL; + +// This function is also used in dcmsr, try to stay in sync! +extern "C" void errorFunction(void * ctx, const char *msg, ...) +{ +#if defined(HAVE_VSNPRINTF) && defined(HAVE_PROTOTYPE_VSNPRINTF) + // Classic C requires us to declare variables at the beginning of the function. + OFString &buffer = *OFstatic_cast(OFString*, ctx); +#endif + + if (!xmlLogger.isEnabledFor(OFLogger::DEBUG_LOG_LEVEL)) + return; + +#if defined(HAVE_VSNPRINTF) && defined(HAVE_PROTOTYPE_VSNPRINTF) + // libxml calls us multiple times for one line of log output which would + // result in garbled output. To avoid this, we buffer the output in a local + // string in the caller which we get through our 'ctx' parameter. Then, we + // output this string on one go when we receive a newline. + va_list ap; + char buf[1024]; + + va_start(ap, msg); +#ifdef HAVE_PROTOTYPE_STD__VSNPRINTF + std::vsnprintf(buf, 1024, msg, ap); +#else + vsnprintf(buf, 1024, msg, ap); +#endif + va_end(ap); + + // Since we can't do anything about a too small buffer for vsnprintf(), we + // ignore it. But we do make sure the buffer is null-terminated! + buf[1023] = '\0'; + buffer += buf; + + // If there is a full line in the buffer... + size_t pos = buffer.find('\n'); + while (pos != OFString_npos) + { + // ..output it and remove it from the buffer + OFLOG_DEBUG(xmlLogger, buffer.substr(0, pos)); + buffer.erase(0, pos + 1); + + pos = buffer.find('\n'); + } +#elif defined(HAVE_VPRINTF) + // No vsnprint, but at least vfprintf. Output the messages directly to stderr. + va_list ap; + va_start(ap, msg); +#ifdef HAVE_PROTOTYPE_STD__VFPRINTF + std::vfprintf(stderr, msg, ap); +#else + vfprintf(stderr, msg, ap); +#endif + va_end(ap); +#else + // We can only show the most basic part of the message, this will look bad :( + printf("%s", msg); +#endif +} + + +static OFBool convertUtf8ToCharset(const xmlChar *fromString, + OFString &toString) +{ + OFBool result = OFFalse; + if (EncodingHandler != NULL) + { + /* prepare input/output buffers */ + xmlBufferPtr fromBuffer = xmlBufferCreate(); + xmlBufferPtr toBuffer = xmlBufferCreate(); + xmlBufferCat(fromBuffer, fromString); + /* convert character encoding of given string */ + result = (xmlCharEncOutFunc(EncodingHandler, toBuffer, fromBuffer) >= 0); + if (result) + toString = OFreinterpret_cast(const char *, xmlBufferContent(toBuffer)); + /* free allocated memory */ + xmlBufferFree(toBuffer); + xmlBufferFree(fromBuffer); + } + return result; +} + + +static OFCondition checkNode(xmlNodePtr current, + const char *name) +{ + OFCondition result = EC_Normal; + /* check whether node is valid at all */ + if (current != NULL) + { + /* check whether node has expected name */ + if (xmlStrcmp(current->name, OFreinterpret_cast(const xmlChar *, name)) != 0) + { + OFLOG_ERROR(xml2dcmLogger, "document of the wrong type, was '" << current->name << "', '" << name << "' expected"); + result = EC_IllegalCall; + } + } else { + OFLOG_ERROR(xml2dcmLogger, "document of the wrong type, '" << name << "' expected"); + result = EC_IllegalCall; + } + return result; +} + + +static OFCondition createNewElement(xmlNodePtr current, + DcmElement *&newElem) +{ + OFCondition result = EC_IllegalCall; + /* check whether node is valid */ + if (current != NULL) + { + /* get required information from XML element */ + xmlChar *elemTag = xmlGetProp(current, OFreinterpret_cast(const xmlChar *, "tag")); + xmlChar *elemVR = xmlGetProp(current, OFreinterpret_cast(const xmlChar *, "vr")); + /* convert tag string */ + DcmTagKey dcmTagKey; + unsigned int group = 0xffff; + unsigned int elem = 0xffff; + if (sscanf(OFreinterpret_cast(char *, elemTag), "%x,%x", &group, &elem ) == 2) + { + dcmTagKey.set(OFstatic_cast(Uint16, group), OFstatic_cast(Uint16, elem)); + DcmTag dcmTag(dcmTagKey); + /* convert vr string */ + DcmVR dcmVR(OFreinterpret_cast(char *, elemVR)); + DcmEVR dcmEVR = dcmVR.getEVR(); + if (dcmEVR == EVR_UNKNOWN) + { + OFLOG_WARN(xml2dcmLogger, "invalid 'vr' attribute (" << elemVR + << ") for " << dcmTag << ", using unknown VR"); + } + /* check for correct vr */ + const DcmEVR tagEVR = dcmTag.getEVR(); + if ((tagEVR != dcmEVR) && (dcmEVR != EVR_UNKNOWN) && (tagEVR != EVR_UNKNOWN) && + ((dcmTagKey != DCM_LUTData) || ((dcmEVR != EVR_US) && (dcmEVR != EVR_SS) && (dcmEVR != EVR_OW))) && + ((tagEVR != EVR_xs) || ((dcmEVR != EVR_US) && (dcmEVR != EVR_SS))) && + ((tagEVR != EVR_ox) || ((dcmEVR != EVR_OB) && (dcmEVR != EVR_OW)))) + { + OFLOG_WARN(xml2dcmLogger, "tag " << dcmTag << " has wrong VR (" << dcmVR.getVRName() + << "), correct is " << dcmTag.getVR().getVRName()); + } + if (dcmEVR != EVR_UNKNOWN) + dcmTag.setVR(dcmVR); + /* create DICOM element */ + result = newDicomElement(newElem, dcmTag); + } else { + OFLOG_WARN(xml2dcmLogger, "invalid 'tag' attribute (" << elemTag << "), ignoring node"); + result = EC_InvalidTag; + } + if (result.bad()) + { + /* delete new element if an error occured */ + delete newElem; + newElem = NULL; + } + /* free allocated memory */ + xmlFree(elemTag); + xmlFree(elemVR); + } + return result; +} + + +static OFCondition putElementContent(xmlNodePtr current, + DcmElement *element) +{ + OFCondition result = EC_IllegalCall; + /* check whether node and element are valid */ + if ((current != NULL) && (element != NULL)) + { + DcmEVR dcmEVR = element->getVR(); + /* get the XML node content */ + xmlChar *elemVal = xmlNodeGetContent(current); + xmlChar *attrVal = xmlGetProp(current, OFreinterpret_cast(const xmlChar *, "binary")); + /* check whether node content is present */ + if (xmlStrcmp(attrVal, OFreinterpret_cast(const xmlChar *, "hidden")) == 0) + OFLOG_WARN(xml2dcmLogger, "content of node " << element->getTag() << " is 'hidden', empty element inserted"); + /* check whether node content is base64 encoded */ + else if (xmlStrcmp(attrVal, OFreinterpret_cast(const xmlChar *, "base64")) == 0) + { + Uint8 *data = NULL; + const size_t length = OFStandard::decodeBase64(OFreinterpret_cast(char *, elemVal), data); + if (length > 0) + { + if (dcmEVR == EVR_OW) + { + /* Base64 decoder produces big endian output data, convert to local byte order */ + swapIfNecessary(gLocalByteOrder, EBO_BigEndian, data, OFstatic_cast(Uint32, length), sizeof(Uint16)); + } + result = element->putUint8Array(data, length); + /* delete buffer since data is copied into the element */ + delete[] data; + } + } + /* check whether node content is stored in a file */ + else if (xmlStrcmp(attrVal, OFreinterpret_cast(const xmlChar *, "file")) == 0) + { + if (xmlStrlen(elemVal) > 0) + { + const char *filename = OFreinterpret_cast(char *, elemVal); + /* try to open binary file */ + FILE *f = fopen(filename, "rb"); + if (f != NULL) + { + /* determine filesize */ + const size_t fileSize = OFStandard::getFileSize(filename); + unsigned long buflen = fileSize; + /* if odd then make even (DICOM requires even length values) */ + if (buflen & 1) + buflen++; + Uint8 *buf = NULL; + /* create buffer of OB or OW data */ + if (dcmEVR == EVR_OW) + { + Uint16 *buf16 = NULL; + result = element->createUint16Array(OFstatic_cast(Uint32, buflen / 2), buf16); + buf = OFreinterpret_cast(Uint8 *, buf16); + } else + result = element->createUint8Array(OFstatic_cast(Uint32, buflen), buf); + if (result.good()) + { + /* read binary file into the buffer */ + if (fread(buf, 1, OFstatic_cast(size_t, fileSize), f) != fileSize) + { + char errBuf[256]; + const char *text = OFStandard::strerror(errno, errBuf, sizeof(errBuf)); + if (text == NULL) text = "(unknown error code)"; + OFLOG_ERROR(xml2dcmLogger, "error reading binary data file: " << filename << ": " << text); + result = EC_CorruptedData; + } + else if (dcmEVR == EVR_OW) + { + /* swap 16 bit OW data (if necessary) */ + swapIfNecessary(gLocalByteOrder, EBO_LittleEndian, buf, OFstatic_cast(Uint32, buflen), sizeof(Uint16)); + } + } + fclose(f); + } else { + OFLOG_ERROR(xml2dcmLogger, "cannot open binary data file: " << filename); + result = EC_InvalidTag; + } + } else + OFLOG_ERROR(xml2dcmLogger, "filename for element " << element->getTag() << " is missing, empty element inserted"); + } else { + OFString dicomVal; + /* convert character set from UTF-8 (for specific VRs only) */ + if (((dcmEVR == EVR_PN) || (dcmEVR == EVR_SH) || (dcmEVR == EVR_LO) || + (dcmEVR == EVR_ST) || (dcmEVR == EVR_LT) || (dcmEVR == EVR_UT)) && + (xmlStrlen(elemVal) > 0) && convertUtf8ToCharset(elemVal, dicomVal)) + { + result = element->putOFStringArray(dicomVal); + } else { + /* set the value of the newly created element */ + result = element->putString(OFreinterpret_cast(char *, elemVal)); + } + } + /* free allocated memory */ + xmlFree(elemVal); + xmlFree(attrVal); + } + return result; +} + + +static OFCondition parseElement(DcmItem *dataset, + xmlNodePtr current) +{ + DcmElement *newElem = NULL; + /* create new DICOM element from XML element */ + OFCondition result = createNewElement(current, newElem); + if (result.good()) + { + /* retrieve specific character set (only on main dataset level) */ + if ((EncodingHandler == NULL) && (dataset->ident() == EVR_dataset) && + (newElem->getTag() == DCM_SpecificCharacterSet)) + { + const char *encString = NULL; + xmlChar *elemVal = xmlNodeGetContent(current); + /* check for known character set */ + if (xmlStrcmp(elemVal, OFreinterpret_cast(const xmlChar *, "ISO_IR 6")) == 0) + encString = "UTF-8"; + else if (xmlStrcmp(elemVal, OFreinterpret_cast(const xmlChar *, "ISO_IR 192")) == 0) + encString = "UTF-8"; + else if (xmlStrcmp(elemVal, OFreinterpret_cast(const xmlChar *, "ISO_IR 100")) == 0) + encString = "ISO-8859-1"; + else if (xmlStrcmp(elemVal, OFreinterpret_cast(const xmlChar *, "ISO_IR 101")) == 0) + encString = "ISO-8859-2"; + else if (xmlStrcmp(elemVal, OFreinterpret_cast(const xmlChar *, "ISO_IR 109")) == 0) + encString = "ISO-8859-3"; + else if (xmlStrcmp(elemVal, OFreinterpret_cast(const xmlChar *, "ISO_IR 110")) == 0) + encString = "ISO-8859-4"; + else if (xmlStrcmp(elemVal, OFreinterpret_cast(const xmlChar *, "ISO_IR 148")) == 0) + encString = "ISO-8859-9"; + else if (xmlStrcmp(elemVal, OFreinterpret_cast(const xmlChar *, "ISO_IR 144")) == 0) + encString = "ISO-8859-5"; + else if (xmlStrcmp(elemVal, OFreinterpret_cast(const xmlChar *, "ISO_IR 127")) == 0) + encString = "ISO-8859-6"; + else if (xmlStrcmp(elemVal, OFreinterpret_cast(const xmlChar *, "ISO_IR 126")) == 0) + encString = "ISO-8859-7"; + else if (xmlStrcmp(elemVal, OFreinterpret_cast(const xmlChar *, "ISO_IR 138")) == 0) + encString = "ISO-8859-8"; + else if (xmlStrlen(elemVal) > 0) + OFLOG_ERROR(xml2dcmLogger, "character set '" << elemVal << "' not supported"); + if (encString != NULL) + { + /* find appropriate encoding handler */ + EncodingHandler = xmlFindCharEncodingHandler(encString); + } + xmlFree(elemVal); + } + /* set the element value */ + result = putElementContent(current, newElem); + /* insert the new element into the dataset */ + if (result.good()) + result = dataset->insert(newElem, OFTrue /*replaceOld*/); + if (result.bad()) + { + /* delete element if insertion or putting the value failed */ + delete newElem; + } + } + return result; +} + + +// forward declaration +static OFCondition parseDataSet(DcmItem *dataset, + xmlNodePtr current, + E_TransferSyntax xfer); + + +static OFCondition parseSequence(DcmSequenceOfItems *sequence, + xmlNodePtr current, + E_TransferSyntax xfer) +{ + OFCondition result = EC_IllegalCall; + if (sequence != NULL) + { + /* ignore blank (empty or whitespace only) nodes */ + while ((current != NULL) && xmlIsBlankNode(current)) + current = current->next; + while (current != NULL) + { + /* ignore non-item nodes */ + if (xmlStrcmp(current->name, OFreinterpret_cast(const xmlChar *, "item")) == 0) + { + /* create new sequence item */ + DcmItem *newItem = new DcmItem(); + if (newItem != NULL) + { + sequence->insert(newItem); + /* proceed parsing the item content */ + parseDataSet(newItem, current->xmlChildrenNode, xfer); + } + } else if (!xmlIsBlankNode(current)) + OFLOG_WARN(xml2dcmLogger, "unexpected node '" << current->name << "', 'item' expected, skipping"); + /* proceed with next node */ + current = current->next; + } + result = EC_Normal; + } + return result; +} + + +static OFCondition parsePixelSequence(DcmPixelSequence *sequence, + xmlNodePtr current) +{ + OFCondition result = EC_IllegalCall; + if (sequence != NULL) + { + /* ignore blank (empty or whitespace only) nodes */ + while ((current != NULL) && xmlIsBlankNode(current)) + current = current->next; + while (current != NULL) + { + /* ignore non-pixel-item nodes */ + if (xmlStrcmp(current->name, OFreinterpret_cast(const xmlChar *, "pixel-item")) == 0) + { + /* create new pixel item */ + DcmPixelItem *newItem = new DcmPixelItem(DCM_PixelItemTag); + if (newItem != NULL) + { + sequence->insert(newItem); + /* put pixel data into the item */ + putElementContent(current, newItem); + } + } else if (!xmlIsBlankNode(current)) + OFLOG_WARN(xml2dcmLogger, "unexpected node '" << current->name << "', 'pixel-item' expected, skipping"); + /* proceed with next node */ + current = current->next; + } + result = EC_Normal; + } + return result; +} + + +static OFCondition parseMetaHeader(DcmMetaInfo *metainfo, + xmlNodePtr current, + const OFBool parse) +{ + /* check for valid node and correct name */ + OFCondition result = checkNode(current, "meta-header"); + if (result.good() && parse) + { + /* get child nodes */ + current = current->xmlChildrenNode; + while (current != NULL) + { + /* ignore non-element nodes */ + if (xmlStrcmp(current->name, OFreinterpret_cast(const xmlChar *, "element")) == 0) + parseElement(metainfo, current); + else if (!xmlIsBlankNode(current)) + OFLOG_WARN(xml2dcmLogger, "unexpected node '" << current->name << "', 'element' expected, skipping"); + /* proceed with next node */ + current = current->next; + } + } + return result; +} + + +static OFCondition parseDataSet(DcmItem *dataset, + xmlNodePtr current, + E_TransferSyntax xfer) +{ + OFCondition result = EC_Normal; + /* ignore blank (empty or whitespace only) nodes */ + while ((current != NULL) && xmlIsBlankNode(current)) + current = current->next; + while (current != NULL) + { + /* ignore non-element/sequence nodes */ + if (xmlStrcmp(current->name, OFreinterpret_cast(const xmlChar *, "element")) == 0) + parseElement(dataset, current); + else if (xmlStrcmp(current->name, OFreinterpret_cast(const xmlChar *, "sequence")) == 0) + { + DcmElement *newElem = NULL; + /* create new sequence element */ + if (createNewElement(current, newElem).good()) + { + /* insert new sequence element into the dataset */ + result = dataset->insert(newElem, OFTrue /*replaceOld*/); + if (result.good()) + { + /* special handling for compressed pixel data */ + if (newElem->getTag() == DCM_PixelData) + { + /* create new pixel sequence */ + DcmPixelSequence *sequence = new DcmPixelSequence(DCM_PixelSequenceTag); + if (sequence != NULL) + { + /* ... insert it into the dataset and proceed with the pixel items */ + OFstatic_cast(DcmPixelData *, newElem)->putOriginalRepresentation(xfer, NULL, sequence); + parsePixelSequence(sequence, current->xmlChildrenNode); + } + } else { + /* proceed parsing the items of the sequence */ + parseSequence(OFstatic_cast(DcmSequenceOfItems *, newElem), current->xmlChildrenNode, xfer); + } + } else { + /* delete element if insertion failed */ + delete newElem; + } + } + } else if (!xmlIsBlankNode(current)) + OFLOG_WARN(xml2dcmLogger, "unexpected node '" << current->name << "', skipping"); + /* proceed with next node */ + current = current->next; + } + return result; +} + + +static OFCondition validateXmlDocument(xmlDocPtr doc) +{ + OFCondition result = EC_Normal; + OFLOG_INFO(xml2dcmLogger, "validating XML document ..."); + xmlGenericError(xmlGenericErrorContext, "--- libxml validating ---\n"); + /* temporary buffer needed for errorFunction - more detailed explanation there */ + OFString tmpErrorString; + /* create context for document validation */ + xmlValidCtxt cvp; + cvp.userData = &tmpErrorString; + cvp.error = errorFunction; + cvp.warning = errorFunction; + /* validate the document */ + const int valid = xmlValidateDocument(&cvp, doc); + xmlGenericError(xmlGenericErrorContext, "-------------------------\n"); + if (!valid) + { + OFLOG_ERROR(xml2dcmLogger, "document does not validate"); + result = EC_IllegalCall; + } + return result; +} + + +static OFCondition readXmlFile(const char *ifname, + DcmFileFormat &fileformat, + E_TransferSyntax &xfer, + const OFBool metaInfo, + const OFBool checkNamespace, + const OFBool validateDocument) +{ + OFCondition result = EC_Normal; + xfer = EXS_Unknown; + xmlGenericError(xmlGenericErrorContext, "--- libxml parsing ------\n"); + /* build an XML tree from the file */ +#if LIBXML_VERSION >= 20703 + /* + * Starting with libxml version 2.7.3, the maximum length of XML element values + * is limited to 10 MB. The following code disables this default limitation. + */ + xmlDocPtr doc = xmlReadFile(ifname, NULL /*encoding*/, XML_PARSE_HUGE); +#else + xmlDocPtr doc = xmlParseFile(ifname); +#endif + xmlGenericError(xmlGenericErrorContext, "-------------------------\n"); + if (doc != NULL) + { + /* validate document */ + if (validateDocument) + result = validateXmlDocument(doc); + if (result.good()) + { + /* check whether the document is of the right kind */ + xmlNodePtr current = xmlDocGetRootElement(doc); + if (current != NULL) + { + /* check namespace declaration (if required) */ + if (!checkNamespace || (xmlSearchNsByHref(doc, current, OFreinterpret_cast(const xmlChar *, DCMTK_XML_NAMESPACE_URI)) != NULL)) + { + /* check whether to parse a "file-format" or "data-set" */ + if (xmlStrcmp(current->name, OFreinterpret_cast(const xmlChar *, "file-format")) == 0) + { + OFLOG_INFO(xml2dcmLogger, "parsing file-format ..."); + if (metaInfo) + OFLOG_INFO(xml2dcmLogger, "parsing meta-header ..."); + else + OFLOG_INFO(xml2dcmLogger, "skipping meta-header ..."); + + current = current->xmlChildrenNode; + /* ignore blank (empty or whitespace only) nodes */ + while ((current != NULL) && xmlIsBlankNode(current)) + current = current->next; + /* parse/skip "meta-header" */ + result = parseMetaHeader(fileformat.getMetaInfo(), current, metaInfo /*parse*/); + if (result.good()) + { + current = current->next; + /* ignore blank (empty or whitespace only) nodes */ + while ((current != NULL) && xmlIsBlankNode(current)) + current = current->next; + } + } + /* there should always be a "data-set" node */ + if (result.good()) + { + OFLOG_INFO(xml2dcmLogger, "parsing data-set ..."); + /* parse "data-set" */ + result = checkNode(current, "data-set"); + if (result.good()) + { + DcmDataset *dataset = fileformat.getDataset(); + /* determine stored transfer syntax */ + xmlChar *xferUID = xmlGetProp(current, OFreinterpret_cast(const xmlChar *, "xfer")); + if (xferUID != NULL) + xfer = DcmXfer(OFreinterpret_cast(char *, xferUID)).getXfer(); + result = parseDataSet(dataset, current->xmlChildrenNode, xfer); + /* free allocated memory */ + xmlFree(xferUID); + } + } + if (result.bad() && xmlLogger.isEnabledFor(OFLogger::DEBUG_LOG_LEVEL)) + { + /* dump XML document for debugging purposes */ + xmlChar *str; + int size; + xmlDocDumpFormatMemory(doc, &str, &size, 1); + OFLOG_DEBUG(xmlLogger, str); + xmlFree(str); + } + } else { + OFLOG_ERROR(xml2dcmLogger, "document has wrong type, dcmtk namespace not found"); + result = EC_IllegalCall; + } + } else { + OFLOG_ERROR(xml2dcmLogger, "document is empty: " << ifname); + result = EC_IllegalCall; + } + } + } else { + OFLOG_ERROR(xml2dcmLogger, "could not parse document: " << ifname); + result = EC_IllegalCall; + } + /* free allocated memory */ + xmlFreeDoc(doc); + return result; +} + + +#define SHORTCOL 3 +#define LONGCOL 21 + + +int main(int argc, char *argv[]) +{ + OFBool opt_metaInfo = OFTrue; + OFBool opt_namespace = OFFalse; + OFBool opt_validate = OFFalse; + OFBool opt_generateUIDs = OFFalse; + OFBool opt_overwriteUIDs = OFFalse; + E_TransferSyntax opt_xfer = EXS_Unknown; + E_EncodingType opt_enctype = EET_ExplicitLength; + E_GrpLenEncoding opt_glenc = EGL_recalcGL; + E_PaddingEncoding opt_padenc = EPD_withoutPadding; + E_FileWriteMode opt_writeMode = EWM_fileformat; + OFCmdUnsignedInt opt_filepad = 0; + OFCmdUnsignedInt opt_itempad = 0; + + /* set-up command line parameters and options */ + OFConsoleApplication app(OFFIS_CONSOLE_APPLICATION, OFFIS_CONSOLE_DESCRIPTION, rcsid); + OFCommandLine cmd; + cmd.setOptionColumns(LONGCOL, SHORTCOL); + cmd.setParamColumn(LONGCOL + SHORTCOL + 4); + + cmd.addParam("xmlfile-in", "XML input filename to be converted (stdin: \"-\")", OFCmdParam::PM_Mandatory); + cmd.addParam("dcmfile-out", "DICOM output filename", OFCmdParam::PM_Mandatory); + + cmd.addGroup("general options:", LONGCOL, SHORTCOL + 2); + cmd.addOption("--help", "-h", "print this help text and exit", OFCommandLine::AF_Exclusive); + cmd.addOption("--version", "print version information and exit", OFCommandLine::AF_Exclusive); + OFLog::addOptions(cmd); + + cmd.addGroup("input options:"); + cmd.addSubGroup("input file format:"); + cmd.addOption("--read-meta-info", "+f", "read meta information if present (default)"); + cmd.addOption("--ignore-meta-info", "-f", "ignore file meta information"); + + cmd.addGroup("processing options:"); + cmd.addSubGroup("validation:"); + cmd.addOption("--validate-document", "+Vd", "validate XML document against DTD"); + cmd.addOption("--check-namespace", "+Vn", "check XML namespace in document root"); + cmd.addSubGroup("unique identifiers:"); + cmd.addOption("--generate-new-uids", "+Ug", "generate new Study/Series/SOP Instance UID"); + cmd.addOption("--dont-overwrite-uids", "-Uo", "do not overwrite existing UIDs (default)"); + cmd.addOption("--overwrite-uids", "+Uo", "overwrite existing UIDs"); + + cmd.addGroup("output options:"); + cmd.addSubGroup("output file format:"); + cmd.addOption("--write-file", "+F", "write file format (default)"); + cmd.addOption("--write-dataset", "-F", "write data set without file meta information"); + cmd.addOption("--update-meta-info", "+Fu", "update particular file meta information"); + cmd.addSubGroup("output transfer syntax:"); + cmd.addOption("--write-xfer-same", "+t=", "write with same TS as input (default)"); + cmd.addOption("--write-xfer-little", "+te", "write with explicit VR little endian TS"); + cmd.addOption("--write-xfer-big", "+tb", "write with explicit VR big endian TS"); + cmd.addOption("--write-xfer-implicit", "+ti", "write with implicit VR little endian TS"); +#ifdef WITH_ZLIB + cmd.addOption("--write-xfer-deflated", "+td", "write with deflated expl. VR little endian TS"); +#endif + cmd.addSubGroup("post-1993 value representations:"); + cmd.addOption("--enable-new-vr", "+u", "enable support for new VRs (UN/UT) (default)"); + cmd.addOption("--disable-new-vr", "-u", "disable support for new VRs, convert to OB"); + cmd.addSubGroup("group length encoding:"); + cmd.addOption("--group-length-recalc", "+g=", "recalculate group lengths if present (default)"); + cmd.addOption("--group-length-create", "+g", "always write with group length elements"); + cmd.addOption("--group-length-remove", "-g", "always write without group length elements"); + cmd.addSubGroup("length encoding in sequences and items:"); + cmd.addOption("--length-explicit", "+e", "write with explicit lengths (default)"); + cmd.addOption("--length-undefined", "-e", "write with undefined lengths"); + cmd.addSubGroup("data set trailing padding (not with --write-dataset):"); + cmd.addOption("--padding-retain", "-p=", "do not change padding\n(default if not --write-dataset)"); + cmd.addOption("--padding-off", "-p", "no padding (implicit if --write-dataset)"); + cmd.addOption("--padding-create", "+p", 2, "[f]ile-pad [i]tem-pad: integer", + "align file on multiple of f bytes\nand items on multiple of i bytes"); +#ifdef WITH_ZLIB + cmd.addSubGroup("deflate compression level (only with --write-xfer-deflated):"); + cmd.addOption("--compression-level", "+cl", 1, "[l]evel: integer (default: 6)", + "0=uncompressed, 1=fastest, 9=best compression"); +#endif + + /* evaluate command line */ + prepareCmdLineArgs(argc, argv, OFFIS_CONSOLE_APPLICATION); + if (app.parseCommandLine(cmd, argc, argv)) + { + /* check exclusive options first */ + if (cmd.hasExclusiveOption()) + { + if (cmd.findOption("--version")) + { + app.printHeader(OFTrue /*print host identifier*/); + COUT << OFendl << "External libraries used:" << OFendl; +#ifdef WITH_ZLIB + COUT << "- ZLIB, Version " << zlibVersion() << OFendl; +#endif + COUT << "- LIBXML, Version " << LIBXML_DOTTED_VERSION << OFendl; +#if defined(LIBXML_ICONV_ENABLED) && defined(LIBXML_ZLIB_ENABLED) + COUT << " with built-in LIBICONV and ZLIB support" << OFendl; +#elif defined(LIBXML_ICONV_ENABLED) + COUT << " with built-in LIBICONV support" << OFendl; +#elif defined(LIBXML_ZLIB_ENABLED) + COUT << " with built-in ZLIB support" << OFendl; +#endif + return 0; + } + } + + /* general options */ + OFLog::configureFromCommandLine(cmd, app); + + /* input options */ + + cmd.beginOptionBlock(); + if (cmd.findOption("--read-meta-info")) + opt_metaInfo = OFTrue; + if (cmd.findOption("--ignore-meta-info")) + opt_metaInfo = OFFalse; + cmd.endOptionBlock(); + + /* processing options */ + + if (cmd.findOption("--validate-document")) + opt_validate = OFTrue; + if (cmd.findOption("--check-namespace")) + opt_namespace = OFTrue; + + if (cmd.findOption("--generate-new-uids")) + opt_generateUIDs = OFTrue; + + cmd.beginOptionBlock(); + if (cmd.findOption("--dont-overwrite-uids")) + opt_overwriteUIDs = OFFalse; + if (cmd.findOption("--overwrite-uids")) + opt_overwriteUIDs = OFTrue; + cmd.endOptionBlock(); + + /* output options */ + + cmd.beginOptionBlock(); + if (cmd.findOption("--write-file")) + opt_writeMode = EWM_fileformat; + if (cmd.findOption("--write-dataset")) + opt_writeMode = EWM_dataset; + cmd.endOptionBlock(); + + if (cmd.findOption("--update-meta-info")) + { + app.checkConflict("--update-meta-info", "--write-dataset", opt_writeMode == EWM_dataset); + opt_writeMode = EWM_updateMeta; + } + + cmd.beginOptionBlock(); + if (cmd.findOption("--write-xfer-same")) + opt_xfer = EXS_Unknown; + if (cmd.findOption("--write-xfer-little")) + opt_xfer = EXS_LittleEndianExplicit; + if (cmd.findOption("--write-xfer-big")) + opt_xfer = EXS_BigEndianExplicit; + if (cmd.findOption("--write-xfer-implicit")) + opt_xfer = EXS_LittleEndianImplicit; +#ifdef WITH_ZLIB + if (cmd.findOption("--write-xfer-deflated")) + opt_xfer = EXS_DeflatedLittleEndianExplicit; +#endif + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--enable-new-vr")) + dcmEnableGenerationOfNewVRs(); + if (cmd.findOption("--disable-new-vr")) + dcmDisableGenerationOfNewVRs(); + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--group-length-recalc")) + opt_glenc = EGL_recalcGL; + if (cmd.findOption("--group-length-create")) + opt_glenc = EGL_withGL; + if (cmd.findOption("--group-length-remove")) + opt_glenc = EGL_withoutGL; + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--length-explicit")) + opt_enctype = EET_ExplicitLength; + if (cmd.findOption("--length-undefined")) + opt_enctype = EET_UndefinedLength; + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--padding-retain")) + { + app.checkConflict("--padding-retain", "--write-dataset", opt_writeMode == EWM_dataset); + opt_padenc = EPD_noChange; + } + if (cmd.findOption("--padding-off")) + opt_padenc = EPD_withoutPadding; + if (cmd.findOption("--padding-create")) + { + app.checkConflict("--padding-create", "--write-dataset", opt_writeMode == EWM_dataset); + app.checkValue(cmd.getValueAndCheckMin(opt_filepad, 0)); + app.checkValue(cmd.getValueAndCheckMin(opt_itempad, 0)); + opt_padenc = EPD_withPadding; + } + cmd.endOptionBlock(); + +#ifdef WITH_ZLIB + if (cmd.findOption("--compression-level")) + { + OFCmdUnsignedInt comprLevel = 0; + app.checkDependence("--compression-level", "--write-xfer-deflated", opt_xfer == EXS_DeflatedLittleEndianExplicit); + app.checkValue(cmd.getValueAndCheckMinMax(comprLevel, 0, 9)); + dcmZlibCompressionLevel.set(OFstatic_cast(int, comprLevel)); + } +#endif + } + + /* print resource identifier */ + OFLOG_DEBUG(xml2dcmLogger, rcsid << OFendl); + + /* make sure data dictionary is loaded */ + if (!dcmDataDict.isDictionaryLoaded()) + { + OFLOG_WARN(xml2dcmLogger, "no data dictionary loaded, check environment variable: " + << DCM_DICT_ENVIRONMENT_VARIABLE); + } + + /* check for compatible libxml version */ + LIBXML_TEST_VERSION + /* temporary buffer needed for errorFunction - more detailed explanation there */ + OFString tmpErrorString; + /* initialize the XML library (only required for MT-safety) */ + xmlInitParser(); + /* substitute default entities (XML mnenonics) */ + xmlSubstituteEntitiesDefault(1); + /* add line number to debug messages */ + xmlLineNumbersDefault(1); + xmlGetWarningsDefaultValue = 1; + xmlSetGenericErrorFunc(&tmpErrorString, errorFunction); + + OFCondition result = EC_Normal; + const char *opt_ifname = NULL; + const char *opt_ofname = NULL; + cmd.getParam(1, opt_ifname); + cmd.getParam(2, opt_ofname); + + /* check filenames */ + if ((opt_ifname == NULL) || (strlen(opt_ifname) == 0)) + { + OFLOG_ERROR(xml2dcmLogger, OFFIS_CONSOLE_APPLICATION << ": invalid input filename: "); + result = EC_IllegalParameter; + } + if ((opt_ofname == NULL) || (strlen(opt_ofname) == 0)) + { + OFLOG_ERROR(xml2dcmLogger, OFFIS_CONSOLE_APPLICATION << ": invalid output filename: "); + result = EC_IllegalParameter; + } + + if (result.good()) + { + DcmFileFormat fileformat; + E_TransferSyntax xfer; + OFLOG_INFO(xml2dcmLogger, "reading XML input file: " << opt_ifname); + /* read XML file and feed data into DICOM fileformat */ + result = readXmlFile(opt_ifname, fileformat, xfer, opt_metaInfo, opt_namespace, opt_validate); + if (result.good()) + { + DcmDataset *dataset = fileformat.getDataset(); + /* generate new UIDs (if required) */ + if (opt_generateUIDs) + { + char uid[100]; + if (opt_overwriteUIDs || !dataset->tagExistsWithValue(DCM_StudyInstanceUID)) + { + OFLOG_INFO(xml2dcmLogger, "generating new Study Instance UID"); + dataset->putAndInsertString(DCM_StudyInstanceUID, dcmGenerateUniqueIdentifier(uid, SITE_STUDY_UID_ROOT)); + } + if (opt_overwriteUIDs || !dataset->tagExistsWithValue(DCM_SeriesInstanceUID)) + { + OFLOG_INFO(xml2dcmLogger, "generating new Series Instance UID"); + dataset->putAndInsertString(DCM_SeriesInstanceUID, dcmGenerateUniqueIdentifier(uid, SITE_SERIES_UID_ROOT)); + } + if (opt_overwriteUIDs || !dataset->tagExistsWithValue(DCM_SOPInstanceUID)) + { + OFLOG_INFO(xml2dcmLogger, "generating new SOP Instance UID"); + dataset->putAndInsertString(DCM_SOPInstanceUID, dcmGenerateUniqueIdentifier(uid, SITE_INSTANCE_UID_ROOT)); + } + } + OFLOG_INFO(xml2dcmLogger, "writing DICOM output file: " << opt_ofname); + /* determine transfer syntax to write the file */ + if ((opt_xfer == EXS_Unknown) && (xfer != EXS_Unknown)) + opt_xfer = xfer; + /* check whether this is possible */ + if (fileformat.canWriteXfer(opt_xfer)) + { + /* check whether pixel data is compressed */ + if ((opt_writeMode == EWM_dataset) && DcmXfer(xfer).isEncapsulated()) + { + OFLOG_ERROR(xml2dcmLogger, "encapsulated pixel data require file format, ignoring --write-dataset"); + opt_writeMode = EWM_fileformat; + } + /* write DICOM file */ + result = fileformat.saveFile(opt_ofname, opt_xfer, opt_enctype, opt_glenc, opt_padenc, + OFstatic_cast(Uint32, opt_filepad), OFstatic_cast(Uint32, opt_itempad), opt_writeMode); + if (result.bad()) + OFLOG_ERROR(xml2dcmLogger, result.text() << ": writing file: " << opt_ofname); + } else { + OFLOG_ERROR(xml2dcmLogger, "no conversion to transfer syntax " << DcmXfer(opt_xfer).getXferName() << " possible!"); + result = EC_CannotChangeRepresentation; + } + } + } + + /* clean up XML library before quitting */ + xmlCleanupParser(); + + return result.status(); +} + +#else /* WITH_LIBXML */ + +int main(int, char *[]) +{ + CERR << rcsid << OFendl << OFFIS_CONSOLE_DESCRIPTION << OFendl << OFendl + << OFFIS_CONSOLE_APPLICATION " requires the libxml library." << OFendl + << "This " OFFIS_CONSOLE_APPLICATION " has been configured and compiled without libxml." << OFendl + << "Please reconfigure your system and recompile if appropriate." << OFendl; + return 0; +} + +#endif /* WITH_LIBXML */ diff --git a/dcmdata/configure b/dcmdata/configure new file mode 100755 index 00000000..396668ee --- /dev/null +++ b/dcmdata/configure @@ -0,0 +1,56 @@ +#! /bin/sh + +parentdir=`pwd` +thisdir=$parentdir + +# The following test constructs relative path from the module +# directory to the configuration directory. If you know this path +# you can substitute this with +# configdir= +# It is very important that the configdir path is relative. + +configdir="configdir" + +while test "$parentdir" != "/" -a "$configdir" = "configdir"; do + if test -d "$parentdir/config" ; then + configdir=$parentdir/config + else + parentdir=`echo $parentdir | sed 's/\/[^\/]*$//'` + fi +done + +if test "$configdir" = "configdir" ; then + echo "Cannot find configure directory" + exit 1 +fi + +if test $# != 0; then + case $1 in + -a) + shift + cd "$configdir" + echo "running configure in config-directory" + ./configure $* + cd $thisdir + echo "running configure for this module" + sh "$configdir/confmod" --srcdir=. $* + ;; + -c) + shift + cd "$configdir" + echo "running configure in config-directory" + ./configure $* + ;; + *) + echo "running configure for this module" + sh "$configdir/confmod" --srcdir=. $* + ;; + esac +else + echo "running configure for this module" + sh "$configdir/confmod" --srcdir=. $* +fi + + + + diff --git a/dcmdata/data/CMakeLists.txt b/dcmdata/data/CMakeLists.txt new file mode 100644 index 00000000..976506b7 --- /dev/null +++ b/dcmdata/data/CMakeLists.txt @@ -0,0 +1,2 @@ +# declare installation files +INSTALL(FILES dicom.dic acrnema.dic private.dic diconde.dic dcm2xml.dtd dumppat.txt SC.dump VLP.dump DESTINATION ${DCMTK_INSTALL_DATDIR} COMPONENT data) diff --git a/dcmdata/data/Makefile.in b/dcmdata/data/Makefile.in new file mode 100644 index 00000000..80afba45 --- /dev/null +++ b/dcmdata/data/Makefile.in @@ -0,0 +1,30 @@ +# +# Makefile for dcmdata/data +# + +@SET_MAKE@ + +SHELL = /bin/sh +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +configdir = @top_srcdir@/@configdir@ + +include $(configdir)/@common_makefile@ + +files = dicom.dic acrnema.dic private.dic diconde.dic dcm2xml.dtd dumppat.txt \ + SC.dump VLP.dump + + +all: + +install: + $(configdir)/mkinstalldirs $(DESTDIR)$(datadir) + for file in $(files); do \ + $(INSTALL_DATA) $$file $(DESTDIR)$(datadir) ;\ + done + +clean: + rm -f $(TRASH) + +distclean: + rm -f $(DISTTRASH) diff --git a/dcmdata/data/SC.dump b/dcmdata/data/SC.dump new file mode 100644 index 00000000..66ec3ab8 --- /dev/null +++ b/dcmdata/data/SC.dump @@ -0,0 +1,99 @@ + +################################################################################ +# IMG2DCM TEMPLATE FOR WRITING SECONDARY CAPTURE OBJECTS # +# SOP Class: 1.2.840.10008.5.1.4.1.1.7 (SC) # +################################################################################ +# Type 1: Value MUST be filled in # +# Type 1C: Value MUST be filled in if known, if certain condition (see # +# standard) is fullfilled, otherwise DO NOT insert # +# Type 2: Value MUST be filled in if known, MUST be left empty otherwise # +# Type 2C: Same as 2, if a certain condition (see standard) is met. If the # +# condition is not met, DO NOT insert # +# Type 3: User optional, CAN be written (if it should not, delete line). # +# The value written can be chosen freely, but has to conform to # +# element's VR (see standard) # +################################################################################ + +########################### Patient Module ##################################### + +# Patient's Name, Type 2 +(0010,0010) PN [] + +# Patient ID, Type 2 +(0010,0020) LO [] + +# Patient's Birth Date, Type 2 +(0010,0030) DA [] + +# Patient's Sex, Type 2 +(0010,0040) CS [] + +# Responsible Organization, Type 2C (only included if patient is animal...) +# (0010,2299) LO [] + +########################### General Study Module ############################## +# All attributes from the General Study Module are overwritten by the # +# --study-from and series-from options # +############################################################################### + +# Study Date, Type 2 +(0008,0020) DA [] + +# Study Time, Type 2 +(0008,0030) TM [] + +# Accession Number, Type 2 +(0008,0050) SH [] + +# Referring Physician's Name, Type 2 +(0008,0090) PN [] + +# Study ID, Type 2 +(0020,0010) SH [] + +# Study Instance UID, Type 1, usually provided automatically (newly created) +#(0020,000d) UI [] + +########################### General Series Module ############################## +# All attributes from the General Series Module are overwritten by the # +# --series-from option # +################################################################################ + +# Patient Position, Type 2C +(0018,5100) CS (no value available) + +# Series Instance UID, Type 1, usually provided automatically (newly created) +# (0020,000e) UI [] + +# Series Number, Type 2 +(0020,0011) IS [] + +# Laterality, Type 2C +# (0020,0060) CS (no value available) + +###################### SC Equipment Module ##################################### + +# Conversion Type, Type 1, Defined Terms, see Standard (SI=Scanned Image) +(0008,0064) CS [SI] + +###################### General Image Module #################################### + +# Content Date, Type 2C +#(0008,0023) DA [] + +# Instance Number, Type 2 +(0020,0013) IS [] + +# Patient Orientation, Type 2C +(0020,0020) CS (no value available) + +###################### Image Pixel Module ###################################### +# The Image Pixel Module is written by the img2dcm application # +################################################################################ + +########################### SOP Common Module ################################## + +# Specific Character Set, Type 1C. +# "ISO_IR 100" should be used if ISO Latin 1 characters could/are used in file +# If only plain ASCII is used, this line could (but does not have to) be deleted +(0008,0005) CS [ISO_IR 100] diff --git a/dcmdata/data/VLP.dump b/dcmdata/data/VLP.dump new file mode 100644 index 00000000..271ca536 --- /dev/null +++ b/dcmdata/data/VLP.dump @@ -0,0 +1,115 @@ + +################################################################################ +# IMG2DCM TEMPLATE FOR WRITING VISIBLE LIGHT PHOTOGRAPHY OBJECTS # +# SOP Class: 1.2.840.10008.5.1.4.1.1.77.1.4 (XC) # +################################################################################ +# Type 1: Value MUST be filled in # +# Type 1C: Value MUST be filled in if known, if certain condition (see # +# standard) is fullfilled, otherwise LEAVE OUT line # +# Type 2: Value MUST be filled in if known, MUST be left empty otherwise # +# Type 2C: Same as 2, if a certain condition (see standard) is met. If the # +# condition is not met, LEAVE OUT line # +# Type 3: User optional, CAN be written (if it should not, delete line). # +# The value written can be chosen freely, but has to conform to # +# element's VR (see standard) # +################################################################################ + +########################### Patient Module ##################################### + +# Patient's Name, Type 2 +(0010,0010) PN [] + +# Patient ID, Type 2 +(0010,0020) LO [] + +# Patient's Birth Date, Type 2 +(0010,0030) DA [] + +# Patient's Sex, Type 2 +(0010,0040) CS [] + +# Responsible Organization, Type 2C (only included if patient is animal...) +# (0010,2299) LO [] + +########################### General Study Module ############################## +# All attributes from the General Study Module are overwritten by the # +# --study-from and series-from options # +############################################################################### + +# Study Date, Type 2 +(0008,0020) DA [] + +# Study Time, Type 2 +(0008,0030) TM [] + +# Accession Number, Type 2 +(0008,0050) SH [] + +# Referring Physician's Name, Type 2 +(0008,0090) PN [] + +# Study ID, Type 2 +(0020,0010) SH [] + +# Study Instance UID, Type 1, usually provided automatically (newly created) +#(0020,000d) UI [] + +########################### General Series Module ############################## +# All attributes from the General Series Module are overwritten by the # +# --study-from option # +################################################################################ + +# Patient Position, Type 2C +(0018,5100) CS (no value available) + +# Series Instance UID, Type 1, usually provided automatically (newly created) +# (0020,000e) UI [] + +# Series Number, Type 2 +(0020,0011) IS [] + +# Laterality, Type 2C +# (0020,0060) CS (no value available) + +###################### General Equipment Module ############################### + +# Manufacturer, Type 2 +(0008,0070) LO [] + +###################### General Image Module ############################### + +# Content Date, Type 2C +#(0008,0023) DA [] + +# Instance Number, Type 2 +(0020,0013) IS [] + +# Patient Orientation, Type 2C +(0020,0020) CS (no value available) + +###################### Image Pixel Module ##################################### +# The Image Pixel Module is written by the img2dcm application # +############################################################################### + +#################### Acquisition Context Module ################################ + +# Acquisition Context Sequence, Type 2 +(0040,0555) SQ (Sequence with explicit length #=0) +(fffe,e0dd) na (SequenceDelimitationItem for re-encod.) + +########################### VL Image Module ################################### + +# Image Type, Type 1 (Defined Terms) +(0008,0008) CS [DERIVED\SECONDARY] + +# Content Time, Type 1C +#(0008,0033) TM [] + +# Lossy Image Compression, Type 2, Enumerated Values ("00" and "01") +(0028,2110) CS [01] + +########################### SOP Common Module ################################## + +# Specific Character Set, Type 1C. +# "ISO_IR 100" should be used if ISO Latin 1 characters could/are used in file +(0008,0005) CS [ISO_IR 100] diff --git a/dcmdata/data/acrnema.dic b/dcmdata/data/acrnema.dic new file mode 100644 index 00000000..d4e86ff1 --- /dev/null +++ b/dcmdata/data/acrnema.dic @@ -0,0 +1,200 @@ +# +# Copyright (C) 1994-2014, OFFIS e.V. +# All rights reserved. See COPYRIGHT file for details. +# +# This software and supporting documentation were developed by +# +# OFFIS e.V. +# R&D Division Health +# Escherweg 2 +# D-26121 Oldenburg, Germany +# +# +# Module: dcmdata +# +# Author: Andrew Hewett, Marco Eichelberg, Joerg Riesmeier +# +# Purpose: ACR/NEMA data dictionary for the DICOM toolkit DCMTK +# +# This file contains the complete data dictionary from the DICOM predecessor +# ACR/NEMA. Please note that the file "dicom.dic" contains more or less the +# same tag definitions since they are now officially part of the DICOM standard +# (introduced with CP-607), so there is usually no need to use this file. It +# is mainly provided for backward compatibility with previous versions of the +# DCMTK. +# +# Each line represents an entry in the data dictionary. Each line has 5 fields +# (Tag, VR, Name, VM, Version). Entries need not be in ascending tag order. +# +# Entries may override existing entries. +# +# Each field must be separated by a single tab. The tag values (gggg,eeee) +# must be in hexadecimal and must be surrounded by parentheses. Repeating +# groups are represented by indicating the range (gggg-gggg,eeee). By default +# the repeating notation only represents even numbers. A range where only +# odd numbers are valid is represented using the notation (gggg-o-gggg,eeee). +# A range can represent both even and odd numbers using the notation +# (gggg-u-gggg,eeee). The element part of the tag can also be a range. +# +# Comments have a '#' at the beginning of the line. +# +# Tag VR Name VM Version +# +#--------------------------------------------------------------------------- +# +# Retired data elements from ACR/NEMA 2 (1988) +# +(0000,0001) UL ACR_NEMA_CommandGroupLengthToEnd 1 ACR/NEMA2 +(0000,0010) CS ACR_NEMA_CommandRecognitionCode 1 ACR/NEMA2 +(0000,0200) LO ACR_NEMA_Initiator 1 ACR/NEMA2 +(0000,0300) LO ACR_NEMA_Receiver 1 ACR/NEMA2 +(0000,0400) LO ACR_NEMA_FindLocation 1 ACR/NEMA2 +(0000,0850) US ACR_NEMA_NumberOfMatches 1 ACR/NEMA2 +(0000,0860) US ACR_NEMA_ResponseSequenceNumber 1 ACR/NEMA2 +(0000,4000) LO ACR_NEMA_DialogReceiver 1 ACR/NEMA2 +(0000,4010) LO ACR_NEMA_TerminalType 1 ACR/NEMA2 +(0000,5010) LO ACR_NEMA_MessageSetID 1 ACR/NEMA2 +(0000,5020) LO ACR_NEMA_EndMessageSet 1 ACR/NEMA2 +(0000,5110) LO ACR_NEMA_DisplayFormat 1 ACR/NEMA2 +(0000,5120) LO ACR_NEMA_PagePositionID 1 ACR/NEMA2 +(0000,5130) LO ACR_NEMA_TextFormatID 1 ACR/NEMA2 +(0000,5140) CS ACR_NEMA_NormalReverse 1 ACR/NEMA2 +(0000,5150) CS ACR_NEMA_AddGrayScale 1 ACR/NEMA2 +(0000,5160) CS ACR_NEMA_Borders 1 ACR/NEMA2 +(0000,5170) IS ACR_NEMA_Copies 1 ACR/NEMA2 +(0000,5180) LO ACR_NEMA_MagnificationType 1 ACR/NEMA2 +(0000,5190) LO ACR_NEMA_Erase 1-n ACR/NEMA2 +(0000,51A0) CS ACR_NEMA_Print 1 ACR/NEMA2 +(0000,51B0) US ACR_NEMA_Overlays 1-n ACR/NEMA2 +(0008,0001) UL ACR_NEMA_IdentifyingGroupLengthToEnd 1 ACR/NEMA2 +(0008,0010) LO ACR_NEMA_RecognitionCode 1 ACR/NEMA2 +(0008,0040) US ACR_NEMA_OldDataSetType 1 ACR/NEMA2 +(0008,0041) LO ACR_NEMA_DataSetSubtype 1 ACR/NEMA2 +(0008,1000) LO ACR_NEMA_NetworkID 1 ACR/NEMA2 +(0008,4000) LT ACR_NEMA_IdentifyingComments 1-n ACR/NEMA2 +(0010,1050) LT ACR_NEMA_InsurancePlanIdentification 1-n ACR/NEMA2 +(0018,1240) IS ACR_NEMA_UpperLowerPixelValues 1-n ACR/NEMA2 +(0018,4000) LT ACR_NEMA_AcquisitionComments 1-n ACR/NEMA2 +(0018,5030) DS ACR_NEMA_DynamicRange 1 ACR/NEMA2 +(0018,5040) DS ACR_NEMA_TotalGain 1 ACR/NEMA2 +(0020,0030) DS ACR_NEMA_ImagePosition 3 ACR/NEMA2 +(0020,0035) DS ACR_NEMA_ImageOrientation 6 ACR/NEMA2 +(0020,0050) DS ACR_NEMA_Location 1 ACR/NEMA2 +(0020,0070) LO ACR_NEMA_ImageGeometryType 1 ACR/NEMA2 +(0020,0080) LO ACR_NEMA_MaskingImage 1-n ACR/NEMA2 +(0020,1001) IS ACR_NEMA_AcquisitionsInSeries 1 ACR/NEMA2 +(0020,1003) IS ACR_NEMA_ImagesInSeries 1 ACR/NEMA2 +(0020,1005) IS ACR_NEMA_ImagesInStudy 1 ACR/NEMA2 +(0020,1020) LO ACR_NEMA_Reference 1-n ACR/NEMA2 +(0020,3100-31FF) LO ACR_NEMA_SourceImageID 1-n ACR/NEMA2 +(0020,3401) LO ACR_NEMA_ModifyingDeviceID 1 ACR/NEMA2 +(0020,3402) LO ACR_NEMA_ModifiedImageID 1 ACR/NEMA2 +(0020,3403) DA ACR_NEMA_ModifiedImageDate 1 ACR/NEMA2 +(0020,3404) LO ACR_NEMA_ModifyingDeviceManufacturer 1 ACR/NEMA2 +(0020,3405) TM ACR_NEMA_ModifiedImageTime 1 ACR/NEMA2 +(0020,3406) LO ACR_NEMA_ModifiedImageDescription 1 ACR/NEMA2 +(0020,5000) AT ACR_NEMA_OriginalImageIdentification 1-n ACR/NEMA2 +(0020,5002) LO ACR_NEMA_OriginalImageIdentificationNomenclature 1-n ACR/NEMA2 +(0028,0005) US ACR_NEMA_ImageDimensions 1 ACR/NEMA2 +(0028,0040) CS ACR_NEMA_ImageFormat 1 ACR/NEMA2 +(0028,0050) LO ACR_NEMA_ManipulatedImage 1-n ACR/NEMA2 +(0028,0060) CS ACR_NEMA_CompressionCode 1 ACR/NEMA2 +(0028,0104) xs ACR_NEMA_SmallestValidPixelValue 1 ACR/NEMA2 +(0028,0105) xs ACR_NEMA_LargestValidPixelValue 1 ACR/NEMA2 +(0028,0200) US ACR_NEMA_ImageLocation 1 ACR/NEMA2 +(0028,1080) CS ACR_NEMA_GrayScale 1 ACR/NEMA2 +(0028,1100) xs ACR_NEMA_GrayLookupTableDescriptor 3 ACR/NEMA2 +(0028,1200) xs ACR_NEMA_GrayLookupTableData 1-n ACR/NEMA2 +(0028,4000) LT ACR_NEMA_ImagePresentationComments 1-n ACR/NEMA2 +(4000,0000) UL ACR_NEMA_TextGroupLength 1 ACR/NEMA2 +(4000,0010) LT ACR_NEMA_TextArbitrary 1-n ACR/NEMA2 +(4000,4000) LT ACR_NEMA_TextComments 1-n ACR/NEMA2 +(6000-60FF,0110) CS ACR_NEMA_OverlayFormat 1 ACR/NEMA2 +(6000-60FF,0200) US ACR_NEMA_OverlayLocation 1 ACR/NEMA2 +(6000-60FF,4000) LT ACR_NEMA_OverlayComments 1-n ACR/NEMA2 +# +#--------------------------------------------------------------------------- +# +# Retired data elements from the ACR/NEMA 2 compression enhancements +# +(0028,005F) CS ACR_NEMA_2C_CompressionRecognitionCode 1 ACR/NEMA2C +(0028,0061) SH ACR_NEMA_2C_CompressionOriginator 1 ACR/NEMA2C +(0028,0062) SH ACR_NEMA_2C_CompressionLabel 1 ACR/NEMA2C +(0028,0063) SH ACR_NEMA_2C_CompressionDescription 1 ACR/NEMA2C +(0028,0065) CS ACR_NEMA_2C_CompressionSequence 1-n ACR/NEMA2C +(0028,0066) AT ACR_NEMA_2C_CompressionStepPointers 1-n ACR/NEMA2C +(0028,0068) US ACR_NEMA_2C_RepeatInterval 1 ACR/NEMA2C +(0028,0069) US ACR_NEMA_2C_BitsGrouped 1 ACR/NEMA2C +(0028,0070) US ACR_NEMA_2C_PerimeterTable 1-n ACR/NEMA2C +(0028,0071) xs ACR_NEMA_2C_PerimeterValue 1 ACR/NEMA2C +(0028,0080) US ACR_NEMA_2C_PredictorRows 1 ACR/NEMA2C +(0028,0081) US ACR_NEMA_2C_PredictorColumns 1 ACR/NEMA2C +(0028,0082) US ACR_NEMA_2C_PredictorConstants 1-n ACR/NEMA2C +(0028,0090) CS ACR_NEMA_2C_BlockedPixels 1 ACR/NEMA2C +(0028,0091) US ACR_NEMA_2C_BlockRows 1 ACR/NEMA2C +(0028,0092) US ACR_NEMA_2C_BlockColumns 1 ACR/NEMA2C +(0028,0093) US ACR_NEMA_2C_RowOverlap 1 ACR/NEMA2C +(0028,0094) US ACR_NEMA_2C_ColumnOverlap 1 ACR/NEMA2C +(0028,0400) CS ACR_NEMA_2C_TransformLabel 1 ACR/NEMA2C +(0028,0401) CS ACR_NEMA_2C_TransformVersionNumber 1 ACR/NEMA2C +(0028,0402) US ACR_NEMA_2C_NumberOfTransformSteps 1 ACR/NEMA2C +(0028,0403) CS ACR_NEMA_2C_SequenceOfCompressedData 1-n ACR/NEMA2C +(0028,0404) AT ACR_NEMA_2C_DetailsOfCoefficients 1-n ACR/NEMA2C +# according to the DICOM standard, the following 4 attributes +# should have a tag in the range of (0028,04x1) to (0028,04x3) +(0028,0410) US ACR_NEMA_2C_RowsForNthOrderCoefficients 1 ACR/NEMA2C +(0028,0411) US ACR_NEMA_2C_ColumnsForNthOrderCoefficients 1 ACR/NEMA2C +(0028,0412) CS ACR_NEMA_2C_CoefficientCoding 1-n ACR/NEMA2C +(0028,0413) AT ACR_NEMA_2C_CoefficientCodingPointers 1-n ACR/NEMA2C +(0028,0700) CS ACR_NEMA_2C_DCTLabel 1 ACR/NEMA2C +(0028,0701) CS ACR_NEMA_2C_DataBlockDescription 1-n ACR/NEMA2C +(0028,0702) AT ACR_NEMA_2C_DataBlock 1-n ACR/NEMA2C +(0028,0710) US ACR_NEMA_2C_NormalizationFactorFormat 1 ACR/NEMA2C +(0028,0720) US ACR_NEMA_2C_ZonalMapNumberFormat 1 ACR/NEMA2C +(0028,0721) AT ACR_NEMA_2C_ZonalMapLocation 1-n ACR/NEMA2C +(0028,0722) US ACR_NEMA_2C_ZonalMapFormat 1 ACR/NEMA2C +(0028,0730) US ACR_NEMA_2C_AdaptiveMapFormat 1 ACR/NEMA2C +(0028,0740) US ACR_NEMA_2C_CodeNumberFormat 1 ACR/NEMA2C +# according to the DICOM standard, the following 5 attributes +# should have a tag in the range of (0028,08x0) to (0028,08x8) +(0028,0800) CS ACR_NEMA_2C_CodeLabel 1-n ACR/NEMA2C +(0028,0802) US ACR_NEMA_2C_NumberOfTables 1 ACR/NEMA2C +(0028,0803) AT ACR_NEMA_2C_CodeTableLocation 1-n ACR/NEMA2C +(0028,0804) US ACR_NEMA_2C_BitsForCodeWord 1 ACR/NEMA2C +(0028,0808) AT ACR_NEMA_2C_ImageDataLocation 1-n ACR/NEMA2C +(1000,0000) UL ACR_NEMA_2C_CodeTableGroupLength 1 ACR/NEMA2C +# according to the DICOM standard, the following 6 attributes +# should have a tag in the range of (1000,xxx0) to (1000,xxx5) +(1000,0010) US ACR_NEMA_2C_EscapeTriplet 3 ACR/NEMA2C +(1000,0011) US ACR_NEMA_2C_RunLengthTriplet 3 ACR/NEMA2C +(1000,0012) US ACR_NEMA_2C_HuffmanTableSize 1 ACR/NEMA2C +(1000,0013) US ACR_NEMA_2C_HuffmanTableTriplet 3 ACR/NEMA2C +(1000,0014) US ACR_NEMA_2C_ShiftTableSize 1 ACR/NEMA2C +(1000,0015) US ACR_NEMA_2C_ShiftTableTriplet 3 ACR/NEMA2C +(1010,0000) UL ACR_NEMA_2C_ZonalMapGroupLength 1 ACR/NEMA2C +# according to the DICOM standard, the following attribute +# should have the tag (1010,xxxx) where "x" is "0" to "F" +(1010,0004) US ACR_NEMA_2C_ZonalMap 1-n ACR/NEMA2C +(6000-60FF,0060) CS ACR_NEMA_2C_OverlayCompressionCode 1 ACR/NEMA2C +(6000-60FF,0061) SH ACR_NEMA_2C_OverlayCompressionOriginator 1 ACR/NEMA2C +(6000-60FF,0062) SH ACR_NEMA_2C_OverlayCompressionLabel 1 ACR/NEMA2C +(6000-60FF,0063) SH ACR_NEMA_2C_OverlayCompressionDescription 1 ACR/NEMA2C +(6000-60FF,0066) AT ACR_NEMA_2C_OverlayCompressionStepPointers 1-n ACR/NEMA2C +(6000-60FF,0068) US ACR_NEMA_2C_OverlayRepeatInterval 1 ACR/NEMA2C +(6000-60FF,0069) US ACR_NEMA_2C_OverlayBitsGrouped 1 ACR/NEMA2C +(6000-60FF,0800) CS ACR_NEMA_2C_OverlayCodeLabel 1-n ACR/NEMA2C +(6000-60FF,0802) US ACR_NEMA_2C_OverlayNumberOfTables 1 ACR/NEMA2C +(6000-60FF,0803) AT ACR_NEMA_2C_OverlayCodeTableLocation 1-n ACR/NEMA2C +(6000-60FF,0804) US ACR_NEMA_2C_OverlayBitsForCodeWord 1 ACR/NEMA2C +(7F00-7FFF,0000) UL ACR_NEMA_2C_VariablePixelDataGroupLength 1 ACR/NEMA2C +(7F00-7FFF,0010) ox ACR_NEMA_2C_VariablePixelData 1 ACR/NEMA2C +(7F00-7FFF,0011) AT ACR_NEMA_2C_VariableNextDataGroup 1 ACR/NEMA2C +(7F00-7FFF,0020) OW ACR_NEMA_2C_VariableCoefficientsSDVN 1-n ACR/NEMA2C +(7F00-7FFF,0030) OW ACR_NEMA_2C_VariableCoefficientsSDHN 1-n ACR/NEMA2C +(7F00-7FFF,0040) OW ACR_NEMA_2C_VariableCoefficientsSDDN 1-n ACR/NEMA2C +(7FE0,0020) OW ACR_NEMA_2C_CoefficientsSDVN 1-n ACR/NEMA2C +(7FE0,0030) OW ACR_NEMA_2C_CoefficientsSDHN 1-n ACR/NEMA2C +(7FE0,0040) OW ACR_NEMA_2C_CoefficientsSDDN 1-n ACR/NEMA2C +# +# end of acrnema.dic +# diff --git a/dcmdata/data/dcm2xml.dtd b/dcmdata/data/dcm2xml.dtd new file mode 100644 index 00000000..fa8b8699 --- /dev/null +++ b/dcmdata/data/dcm2xml.dtd @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dcmdata/data/dicom.dic b/dcmdata/data/dicom.dic new file mode 100644 index 00000000..0c9cf4de --- /dev/null +++ b/dcmdata/data/dicom.dic @@ -0,0 +1,4121 @@ +# +# Copyright (C) 1994-2015, OFFIS e.V. +# All rights reserved. See COPYRIGHT file for details. +# +# This software and supporting documentation were developed by +# +# OFFIS e.V. +# R&D Division Health +# Escherweg 2 +# D-26121 Oldenburg, Germany +# +# +# Module: dcmdata +# +# Author: Andrew Hewett, Marco Eichelberg, Joerg Riesmeier +# +# Purpose: This is the global standard DICOM data dictionary for the DCMTK. +# +# This file contains the complete data dictionary from the latest edition of +# the DICOM standard. This also includes the non-private definitions from the +# DICONDE (Digital Imaging and Communication in Nondestructive Evaluation) and +# DICOS (Digital Imaging and Communications in Security) standard. +# +# Generated automatically from DICOM PS 3.6-2015c and PS 3.7-2015c. +# File created on 2015-07-05 12:23:01 by J. Riesmeier on thinkpad. +# File updated manually on 2015-09-18 by J. Riesmeier. +# +# In addition, the data dictionary entries from the following final text +# supplements and correction items (CP) have been incorporated: +# - Supplement 156 +# - CP 1441, 1454, 1458, 1461 +# +# Each line represents an entry in the data dictionary. Each line has 5 fields +# (Tag, VR, Name, VM, Version). Entries need not be in ascending tag order. +# +# Entries may override existing entries. +# +# Each field must be separated by a single tab. The tag values (gggg,eeee) +# must be in hexadecimal and must be surrounded by parentheses. Repeating +# groups are represented by indicating the range (gggg-gggg,eeee). By default +# the repeating notation only represents even numbers. A range where only +# odd numbers are valid is represented using the notation (gggg-o-gggg,eeee). +# A range can represent both even and odd numbers using the notation +# (gggg-u-gggg,eeee). The element part of the tag can also be a range. +# +# Comments have a '#' at the beginning of the line. +# +# Tag VR Name VM Version +# +(0000,0000) UL CommandGroupLength 1 DICOM +(0000,0002) UI AffectedSOPClassUID 1 DICOM +(0000,0003) UI RequestedSOPClassUID 1 DICOM +(0000,0100) US CommandField 1 DICOM +(0000,0110) US MessageID 1 DICOM +(0000,0120) US MessageIDBeingRespondedTo 1 DICOM +(0000,0600) AE MoveDestination 1 DICOM +(0000,0700) US Priority 1 DICOM +(0000,0800) US CommandDataSetType 1 DICOM +(0000,0900) US Status 1 DICOM +(0000,0901) AT OffendingElement 1-n DICOM +(0000,0902) LO ErrorComment 1 DICOM +(0000,0903) US ErrorID 1 DICOM +(0000,1000) UI AffectedSOPInstanceUID 1 DICOM +(0000,1001) UI RequestedSOPInstanceUID 1 DICOM +(0000,1002) US EventTypeID 1 DICOM +(0000,1005) AT AttributeIdentifierList 1-n DICOM +(0000,1008) US ActionTypeID 1 DICOM +(0000,1020) US NumberOfRemainingSuboperations 1 DICOM +(0000,1021) US NumberOfCompletedSuboperations 1 DICOM +(0000,1022) US NumberOfFailedSuboperations 1 DICOM +(0000,1023) US NumberOfWarningSuboperations 1 DICOM +(0000,1030) AE MoveOriginatorApplicationEntityTitle 1 DICOM +(0000,1031) US MoveOriginatorMessageID 1 DICOM +(0002,0000) UL FileMetaInformationGroupLength 1 DICOM +(0002,0001) OB FileMetaInformationVersion 1 DICOM +(0002,0002) UI MediaStorageSOPClassUID 1 DICOM +(0002,0003) UI MediaStorageSOPInstanceUID 1 DICOM +(0002,0010) UI TransferSyntaxUID 1 DICOM +(0002,0012) UI ImplementationClassUID 1 DICOM +(0002,0013) SH ImplementationVersionName 1 DICOM +(0002,0016) AE SourceApplicationEntityTitle 1 DICOM +(0002,0017) AE SendingApplicationEntityTitle 1 DICOM +(0002,0018) AE ReceivingApplicationEntityTitle 1 DICOM +(0002,0100) UI PrivateInformationCreatorUID 1 DICOM +(0002,0102) OB PrivateInformation 1 DICOM +(0004,1130) CS FileSetID 1 DICOM +(0004,1141) CS FileSetDescriptorFileID 1-8 DICOM +(0004,1142) CS SpecificCharacterSetOfFileSetDescriptorFile 1 DICOM +(0004,1200) up OffsetOfTheFirstDirectoryRecordOfTheRootDirectoryEntity 1 DICOM +(0004,1202) up OffsetOfTheLastDirectoryRecordOfTheRootDirectoryEntity 1 DICOM +(0004,1212) US FileSetConsistencyFlag 1 DICOM +(0004,1220) SQ DirectoryRecordSequence 1 DICOM +(0004,1400) up OffsetOfTheNextDirectoryRecord 1 DICOM +(0004,1410) US RecordInUseFlag 1 DICOM +(0004,1420) up OffsetOfReferencedLowerLevelDirectoryEntity 1 DICOM +(0004,1430) CS DirectoryRecordType 1 DICOM +(0004,1432) UI PrivateRecordUID 1 DICOM +(0004,1500) CS ReferencedFileID 1-8 DICOM +(0004,1510) UI ReferencedSOPClassUIDInFile 1 DICOM +(0004,1511) UI ReferencedSOPInstanceUIDInFile 1 DICOM +(0004,1512) UI ReferencedTransferSyntaxUIDInFile 1 DICOM +(0004,151A) UI ReferencedRelatedGeneralSOPClassUIDInFile 1-n DICOM +(0008,0005) CS SpecificCharacterSet 1-n DICOM +(0008,0006) SQ LanguageCodeSequence 1 DICOM +(0008,0008) CS ImageType 2-n DICOM +(0008,0012) DA InstanceCreationDate 1 DICOM +(0008,0013) TM InstanceCreationTime 1 DICOM +(0008,0014) UI InstanceCreatorUID 1 DICOM +(0008,0015) DT InstanceCoercionDateTime 1 DICOM +(0008,0016) UI SOPClassUID 1 DICOM +(0008,0018) UI SOPInstanceUID 1 DICOM +(0008,001A) UI RelatedGeneralSOPClassUID 1-n DICOM +(0008,001B) UI OriginalSpecializedSOPClassUID 1 DICOM +(0008,0020) DA StudyDate 1 DICOM +(0008,0021) DA SeriesDate 1 DICOM +(0008,0022) DA AcquisitionDate 1 DICOM +(0008,0023) DA ContentDate 1 DICOM +(0008,002A) DT AcquisitionDateTime 1 DICOM +(0008,0030) TM StudyTime 1 DICOM +(0008,0031) TM SeriesTime 1 DICOM +(0008,0032) TM AcquisitionTime 1 DICOM +(0008,0033) TM ContentTime 1 DICOM +(0008,0050) SH AccessionNumber 1 DICOM +(0008,0051) SQ IssuerOfAccessionNumberSequence 1 DICOM +(0008,0052) CS QueryRetrieveLevel 1 DICOM +(0008,0053) CS QueryRetrieveView 1 DICOM +(0008,0054) AE RetrieveAETitle 1-n DICOM +(0008,0056) CS InstanceAvailability 1 DICOM +(0008,0058) UI FailedSOPInstanceUIDList 1-n DICOM +(0008,0060) CS Modality 1 DICOM +(0008,0061) CS ModalitiesInStudy 1-n DICOM +(0008,0062) UI SOPClassesInStudy 1-n DICOM +(0008,0064) CS ConversionType 1 DICOM +(0008,0068) CS PresentationIntentType 1 DICOM +(0008,0070) LO Manufacturer 1 DICOM +(0008,0080) LO InstitutionName 1 DICOM +(0008,0081) ST InstitutionAddress 1 DICOM +(0008,0082) SQ InstitutionCodeSequence 1 DICOM +(0008,0090) PN ReferringPhysicianName 1 DICOM +(0008,0092) ST ReferringPhysicianAddress 1 DICOM +(0008,0094) SH ReferringPhysicianTelephoneNumbers 1-n DICOM +(0008,0096) SQ ReferringPhysicianIdentificationSequence 1 DICOM +(0008,009C) PN ConsultingPhysicianName 1-n DICOM +(0008,009D) SQ ConsultingPhysicianIdentificationSequence 1 DICOM +(0008,0100) SH CodeValue 1 DICOM +(0008,0101) LO ExtendedCodeValue 1 DICOM/DICOS +(0008,0102) SH CodingSchemeDesignator 1 DICOM +(0008,0103) SH CodingSchemeVersion 1 DICOM +(0008,0104) LO CodeMeaning 1 DICOM +(0008,0105) CS MappingResource 1 DICOM +(0008,0106) DT ContextGroupVersion 1 DICOM +(0008,0107) DT ContextGroupLocalVersion 1 DICOM +(0008,0108) LT ExtendedCodeMeaning 1 DICOM/DICOS +(0008,010B) CS ContextGroupExtensionFlag 1 DICOM +(0008,010C) UI CodingSchemeUID 1 DICOM +(0008,010D) UI ContextGroupExtensionCreatorUID 1 DICOM +(0008,010F) CS ContextIdentifier 1 DICOM +(0008,0110) SQ CodingSchemeIdentificationSequence 1 DICOM +(0008,0112) LO CodingSchemeRegistry 1 DICOM +(0008,0114) ST CodingSchemeExternalID 1 DICOM +(0008,0115) ST CodingSchemeName 1 DICOM +(0008,0116) ST CodingSchemeResponsibleOrganization 1 DICOM +(0008,0117) UI ContextUID 1 DICOM +(0008,0118) UI MappingResourceUID 1 DICOM +(0008,0119) UC LongCodeValue 1 DICOM +(0008,0120) UR URNCodeValue 1 DICOM +(0008,0121) SQ EquivalentCodeSequence 1 DICOM +(0008,0201) SH TimezoneOffsetFromUTC 1 DICOM +(0008,0300) SQ PrivateDataElementCharacteristicsSequence 1 DICOM +(0008,0301) US PrivateGroupReference 1 DICOM +(0008,0302) LO PrivateCreatorReference 1 DICOM +(0008,0303) CS BlockIdentifyingInformationStatus 1 DICOM +(0008,0304) US NonidentifyingPrivateElements 1-n DICOM +(0008,0305) SQ DeidentificationActionSequence 1 DICOM +(0008,0306) US IdentifyingPrivateElements 1-n DICOM +(0008,0307) CS DeidentificationAction 1 DICOM +(0008,1010) SH StationName 1 DICOM +(0008,1030) LO StudyDescription 1 DICOM +(0008,1032) SQ ProcedureCodeSequence 1 DICOM +(0008,103E) LO SeriesDescription 1 DICOM +(0008,103F) SQ SeriesDescriptionCodeSequence 1 DICOM +(0008,1040) LO InstitutionalDepartmentName 1 DICOM +(0008,1048) PN PhysiciansOfRecord 1-n DICOM +(0008,1049) SQ PhysiciansOfRecordIdentificationSequence 1 DICOM +(0008,1050) PN PerformingPhysicianName 1-n DICOM +(0008,1052) SQ PerformingPhysicianIdentificationSequence 1 DICOM +(0008,1060) PN NameOfPhysiciansReadingStudy 1-n DICOM +(0008,1062) SQ PhysiciansReadingStudyIdentificationSequence 1 DICOM +(0008,1070) PN OperatorsName 1-n DICOM +(0008,1072) SQ OperatorIdentificationSequence 1 DICOM +(0008,1080) LO AdmittingDiagnosesDescription 1-n DICOM +(0008,1084) SQ AdmittingDiagnosesCodeSequence 1 DICOM +(0008,1090) LO ManufacturerModelName 1 DICOM +(0008,1110) SQ ReferencedStudySequence 1 DICOM +(0008,1111) SQ ReferencedPerformedProcedureStepSequence 1 DICOM +(0008,1115) SQ ReferencedSeriesSequence 1 DICOM +(0008,1120) SQ ReferencedPatientSequence 1 DICOM +(0008,1125) SQ ReferencedVisitSequence 1 DICOM +(0008,1134) SQ ReferencedStereometricInstanceSequence 1 DICOM +(0008,113A) SQ ReferencedWaveformSequence 1 DICOM +(0008,1140) SQ ReferencedImageSequence 1 DICOM +(0008,114A) SQ ReferencedInstanceSequence 1 DICOM +(0008,114B) SQ ReferencedRealWorldValueMappingInstanceSequence 1 DICOM +(0008,1150) UI ReferencedSOPClassUID 1 DICOM +(0008,1155) UI ReferencedSOPInstanceUID 1 DICOM +(0008,115A) UI SOPClassesSupported 1-n DICOM +(0008,1160) IS ReferencedFrameNumber 1-n DICOM +(0008,1161) UL SimpleFrameList 1-n DICOM +(0008,1162) UL CalculatedFrameList 3-3n DICOM +(0008,1163) FD TimeRange 2 DICOM +(0008,1164) SQ FrameExtractionSequence 1 DICOM +(0008,1167) UI MultiFrameSourceSOPInstanceUID 1 DICOM +(0008,1190) UR RetrieveURL 1 DICOM +(0008,1195) UI TransactionUID 1 DICOM +(0008,1196) US WarningReason 1 DICOM +(0008,1197) US FailureReason 1 DICOM +(0008,1198) SQ FailedSOPSequence 1 DICOM +(0008,1199) SQ ReferencedSOPSequence 1 DICOM +(0008,1200) SQ StudiesContainingOtherReferencedInstancesSequence 1 DICOM +(0008,1250) SQ RelatedSeriesSequence 1 DICOM +(0008,2111) ST DerivationDescription 1 DICOM +(0008,2112) SQ SourceImageSequence 1 DICOM +(0008,2120) SH StageName 1 DICOM +(0008,2122) IS StageNumber 1 DICOM +(0008,2124) IS NumberOfStages 1 DICOM +(0008,2127) SH ViewName 1 DICOM +(0008,2128) IS ViewNumber 1 DICOM +(0008,2129) IS NumberOfEventTimers 1 DICOM +(0008,212A) IS NumberOfViewsInStage 1 DICOM +(0008,2130) DS EventElapsedTimes 1-n DICOM +(0008,2132) LO EventTimerNames 1-n DICOM +(0008,2133) SQ EventTimerSequence 1 DICOM +(0008,2134) FD EventTimeOffset 1 DICOM +(0008,2135) SQ EventCodeSequence 1 DICOM +(0008,2142) IS StartTrim 1 DICOM +(0008,2143) IS StopTrim 1 DICOM +(0008,2144) IS RecommendedDisplayFrameRate 1 DICOM +(0008,2218) SQ AnatomicRegionSequence 1 DICOM +(0008,2220) SQ AnatomicRegionModifierSequence 1 DICOM +(0008,2228) SQ PrimaryAnatomicStructureSequence 1 DICOM +(0008,2229) SQ AnatomicStructureSpaceOrRegionSequence 1 DICOM +(0008,2230) SQ PrimaryAnatomicStructureModifierSequence 1 DICOM +(0008,3001) SQ AlternateRepresentationSequence 1 DICOM +(0008,3010) UI IrradiationEventUID 1-n DICOM +(0008,3011) SQ SourceIrradiationEventSequence 1 DICOM +(0008,3012) UI RadiopharmaceuticalAdministrationEventUID 1 DICOM +(0008,9007) CS FrameType 4 DICOM +(0008,9092) SQ ReferencedImageEvidenceSequence 1 DICOM +(0008,9121) SQ ReferencedRawDataSequence 1 DICOM +(0008,9123) UI CreatorVersionUID 1 DICOM +(0008,9124) SQ DerivationImageSequence 1 DICOM +(0008,9154) SQ SourceImageEvidenceSequence 1 DICOM +(0008,9205) CS PixelPresentation 1 DICOM +(0008,9206) CS VolumetricProperties 1 DICOM +(0008,9207) CS VolumeBasedCalculationTechnique 1 DICOM +(0008,9208) CS ComplexImageComponent 1 DICOM +(0008,9209) CS AcquisitionContrast 1 DICOM +(0008,9215) SQ DerivationCodeSequence 1 DICOM +(0008,9237) SQ ReferencedPresentationStateSequence 1 DICOM +(0008,9410) SQ ReferencedOtherPlaneSequence 1 DICOM +(0008,9458) SQ FrameDisplaySequence 1 DICOM +(0008,9459) FL RecommendedDisplayFrameRateInFloat 1 DICOM +(0008,9460) CS SkipFrameRangeFlag 1 DICOM +(0010,0010) PN PatientName 1 DICOM +(0010,0020) LO PatientID 1 DICOM +(0010,0021) LO IssuerOfPatientID 1 DICOM +(0010,0022) CS TypeOfPatientID 1 DICOM +(0010,0024) SQ IssuerOfPatientIDQualifiersSequence 1 DICOM +(0010,0030) DA PatientBirthDate 1 DICOM +(0010,0032) TM PatientBirthTime 1 DICOM +(0010,0040) CS PatientSex 1 DICOM +(0010,0050) SQ PatientInsurancePlanCodeSequence 1 DICOM +(0010,0101) SQ PatientPrimaryLanguageCodeSequence 1 DICOM +(0010,0102) SQ PatientPrimaryLanguageModifierCodeSequence 1 DICOM +(0010,0200) CS QualityControlSubject 1 DICOM +(0010,0201) SQ QualityControlSubjectTypeCodeSequence 1 DICOM +(0010,1000) LO OtherPatientIDs 1-n DICOM +(0010,1001) PN OtherPatientNames 1-n DICOM +(0010,1002) SQ OtherPatientIDsSequence 1 DICOM +(0010,1005) PN PatientBirthName 1 DICOM +(0010,1010) AS PatientAge 1 DICOM +(0010,1020) DS PatientSize 1 DICOM +(0010,1021) SQ PatientSizeCodeSequence 1 DICOM +(0010,1030) DS PatientWeight 1 DICOM +(0010,1040) LO PatientAddress 1 DICOM +(0010,1060) PN PatientMotherBirthName 1 DICOM +(0010,1080) LO MilitaryRank 1 DICOM +(0010,1081) LO BranchOfService 1 DICOM +(0010,1090) LO MedicalRecordLocator 1 DICOM +(0010,1100) SQ ReferencedPatientPhotoSequence 1 DICOM +(0010,2000) LO MedicalAlerts 1-n DICOM +(0010,2110) LO Allergies 1-n DICOM +(0010,2150) LO CountryOfResidence 1 DICOM +(0010,2152) LO RegionOfResidence 1 DICOM +(0010,2154) SH PatientTelephoneNumbers 1-n DICOM +(0010,2155) LT PatientTelecomInformation 1 DICOM +(0010,2160) SH EthnicGroup 1 DICOM +(0010,2180) SH Occupation 1 DICOM +(0010,21A0) CS SmokingStatus 1 DICOM +(0010,21B0) LT AdditionalPatientHistory 1 DICOM +(0010,21C0) US PregnancyStatus 1 DICOM +(0010,21D0) DA LastMenstrualDate 1 DICOM +(0010,21F0) LO PatientReligiousPreference 1 DICOM +(0010,2201) LO PatientSpeciesDescription 1 DICOM +(0010,2202) SQ PatientSpeciesCodeSequence 1 DICOM +(0010,2203) CS PatientSexNeutered 1 DICOM +(0010,2210) CS AnatomicalOrientationType 1 DICOM +(0010,2292) LO PatientBreedDescription 1 DICOM +(0010,2293) SQ PatientBreedCodeSequence 1 DICOM +(0010,2294) SQ BreedRegistrationSequence 1 DICOM +(0010,2295) LO BreedRegistrationNumber 1 DICOM +(0010,2296) SQ BreedRegistryCodeSequence 1 DICOM +(0010,2297) PN ResponsiblePerson 1 DICOM +(0010,2298) CS ResponsiblePersonRole 1 DICOM +(0010,2299) LO ResponsibleOrganization 1 DICOM +(0010,4000) LT PatientComments 1 DICOM +(0010,9431) FL ExaminedBodyThickness 1 DICOM +(0012,0010) LO ClinicalTrialSponsorName 1 DICOM +(0012,0020) LO ClinicalTrialProtocolID 1 DICOM +(0012,0021) LO ClinicalTrialProtocolName 1 DICOM +(0012,0030) LO ClinicalTrialSiteID 1 DICOM +(0012,0031) LO ClinicalTrialSiteName 1 DICOM +(0012,0040) LO ClinicalTrialSubjectID 1 DICOM +(0012,0042) LO ClinicalTrialSubjectReadingID 1 DICOM +(0012,0050) LO ClinicalTrialTimePointID 1 DICOM +(0012,0051) ST ClinicalTrialTimePointDescription 1 DICOM +(0012,0060) LO ClinicalTrialCoordinatingCenterName 1 DICOM +(0012,0062) CS PatientIdentityRemoved 1 DICOM +(0012,0063) LO DeidentificationMethod 1-n DICOM +(0012,0064) SQ DeidentificationMethodCodeSequence 1 DICOM +(0012,0071) LO ClinicalTrialSeriesID 1 DICOM +(0012,0072) LO ClinicalTrialSeriesDescription 1 DICOM +(0012,0081) LO ClinicalTrialProtocolEthicsCommitteeName 1 DICOM +(0012,0082) LO ClinicalTrialProtocolEthicsCommitteeApprovalNumber 1 DICOM +(0012,0083) SQ ConsentForClinicalTrialUseSequence 1 DICOM +(0012,0084) CS DistributionType 1 DICOM +(0012,0085) CS ConsentForDistributionFlag 1 DICOM +(0014,0025) ST ComponentManufacturingProcedure 1-n DICOM/DICONDE +(0014,0028) ST ComponentManufacturer 1-n DICOM/DICONDE +(0014,0030) DS MaterialThickness 1-n DICOM/DICONDE +(0014,0032) DS MaterialPipeDiameter 1-n DICOM/DICONDE +(0014,0034) DS MaterialIsolationDiameter 1-n DICOM/DICONDE +(0014,0042) ST MaterialGrade 1-n DICOM/DICONDE +(0014,0044) ST MaterialPropertiesDescription 1-n DICOM/DICONDE +(0014,0046) LT MaterialNotes 1 DICOM/DICONDE +(0014,0050) CS ComponentShape 1 DICOM/DICONDE +(0014,0052) CS CurvatureType 1 DICOM/DICONDE +(0014,0054) DS OuterDiameter 1 DICOM/DICONDE +(0014,0056) DS InnerDiameter 1 DICOM/DICONDE +(0014,1010) ST ActualEnvironmentalConditions 1 DICOM/DICONDE +(0014,1020) DA ExpiryDate 1 DICOM/DICONDE +(0014,1040) ST EnvironmentalConditions 1 DICOM/DICONDE +(0014,2002) SQ EvaluatorSequence 1 DICOM/DICONDE +(0014,2004) IS EvaluatorNumber 1 DICOM/DICONDE +(0014,2006) PN EvaluatorName 1 DICOM/DICONDE +(0014,2008) IS EvaluationAttempt 1 DICOM/DICONDE +(0014,2012) SQ IndicationSequence 1 DICOM/DICONDE +(0014,2014) IS IndicationNumber 1 DICOM/DICONDE +(0014,2016) SH IndicationLabel 1 DICOM/DICONDE +(0014,2018) ST IndicationDescription 1 DICOM/DICONDE +(0014,201A) CS IndicationType 1-n DICOM/DICONDE +(0014,201C) CS IndicationDisposition 1 DICOM/DICONDE +(0014,201E) SQ IndicationROISequence 1 DICOM/DICONDE +(0014,2030) SQ IndicationPhysicalPropertySequence 1 DICOM/DICONDE +(0014,2032) SH PropertyLabel 1 DICOM/DICONDE +(0014,2202) IS CoordinateSystemNumberOfAxes 1 DICOM/DICONDE +(0014,2204) SQ CoordinateSystemAxesSequence 1 DICOM/DICONDE +(0014,2206) ST CoordinateSystemAxisDescription 1 DICOM/DICONDE +(0014,2208) CS CoordinateSystemDataSetMapping 1 DICOM/DICONDE +(0014,220A) IS CoordinateSystemAxisNumber 1 DICOM/DICONDE +(0014,220C) CS CoordinateSystemAxisType 1 DICOM/DICONDE +(0014,220E) CS CoordinateSystemAxisUnits 1 DICOM/DICONDE +(0014,2210) OB CoordinateSystemAxisValues 1 DICOM/DICONDE +(0014,2220) SQ CoordinateSystemTransformSequence 1 DICOM/DICONDE +(0014,2222) ST TransformDescription 1 DICOM/DICONDE +(0014,2224) IS TransformNumberOfAxes 1 DICOM/DICONDE +(0014,2226) IS TransformOrderOfAxes 1-n DICOM/DICONDE +(0014,2228) CS TransformedAxisUnits 1 DICOM/DICONDE +(0014,222A) DS CoordinateSystemTransformRotationAndScaleMatrix 1-n DICOM/DICONDE +(0014,222C) DS CoordinateSystemTransformTranslationMatrix 1-n DICOM/DICONDE +(0014,3011) DS InternalDetectorFrameTime 1 DICOM/DICONDE +(0014,3012) DS NumberOfFramesIntegrated 1 DICOM/DICONDE +(0014,3020) SQ DetectorTemperatureSequence 1 DICOM/DICONDE +(0014,3022) ST SensorName 1 DICOM/DICONDE +(0014,3024) DS HorizontalOffsetOfSensor 1 DICOM/DICONDE +(0014,3026) DS VerticalOffsetOfSensor 1 DICOM/DICONDE +(0014,3028) DS SensorTemperature 1 DICOM/DICONDE +(0014,3040) SQ DarkCurrentSequence 1 DICOM/DICONDE +(0014,3050) ox DarkCurrentCounts 1 DICOM/DICONDE +(0014,3060) SQ GainCorrectionReferenceSequence 1 DICOM/DICONDE +(0014,3070) ox AirCounts 1 DICOM/DICONDE +(0014,3071) DS KVUsedInGainCalibration 1 DICOM/DICONDE +(0014,3072) DS MAUsedInGainCalibration 1 DICOM/DICONDE +(0014,3073) DS NumberOfFramesUsedForIntegration 1 DICOM/DICONDE +(0014,3074) LO FilterMaterialUsedInGainCalibration 1 DICOM/DICONDE +(0014,3075) DS FilterThicknessUsedInGainCalibration 1 DICOM/DICONDE +(0014,3076) DA DateOfGainCalibration 1 DICOM/DICONDE +(0014,3077) TM TimeOfGainCalibration 1 DICOM/DICONDE +(0014,3080) OB BadPixelImage 1 DICOM/DICONDE +(0014,3099) LT CalibrationNotes 1 DICOM/DICONDE +(0014,4002) SQ PulserEquipmentSequence 1 DICOM/DICONDE +(0014,4004) CS PulserType 1 DICOM/DICONDE +(0014,4006) LT PulserNotes 1 DICOM/DICONDE +(0014,4008) SQ ReceiverEquipmentSequence 1 DICOM/DICONDE +(0014,400A) CS AmplifierType 1 DICOM/DICONDE +(0014,400C) LT ReceiverNotes 1 DICOM/DICONDE +(0014,400E) SQ PreAmplifierEquipmentSequence 1 DICOM/DICONDE +(0014,400F) LT PreAmplifierNotes 1 DICOM/DICONDE +(0014,4010) SQ TransmitTransducerSequence 1 DICOM/DICONDE +(0014,4011) SQ ReceiveTransducerSequence 1 DICOM/DICONDE +(0014,4012) US NumberOfElements 1 DICOM/DICONDE +(0014,4013) CS ElementShape 1 DICOM/DICONDE +(0014,4014) DS ElementDimensionA 1 DICOM/DICONDE +(0014,4015) DS ElementDimensionB 1 DICOM/DICONDE +(0014,4016) DS ElementPitchA 1 DICOM/DICONDE +(0014,4017) DS MeasuredBeamDimensionA 1 DICOM/DICONDE +(0014,4018) DS MeasuredBeamDimensionB 1 DICOM/DICONDE +(0014,4019) DS LocationOfMeasuredBeamDiameter 1 DICOM/DICONDE +(0014,401A) DS NominalFrequency 1 DICOM/DICONDE +(0014,401B) DS MeasuredCenterFrequency 1 DICOM/DICONDE +(0014,401C) DS MeasuredBandwidth 1 DICOM/DICONDE +(0014,401D) DS ElementPitchB 1 DICOM/DICONDE +(0014,4020) SQ PulserSettingsSequence 1 DICOM/DICONDE +(0014,4022) DS PulseWidth 1 DICOM/DICONDE +(0014,4024) DS ExcitationFrequency 1 DICOM/DICONDE +(0014,4026) CS ModulationType 1 DICOM/DICONDE +(0014,4028) DS Damping 1 DICOM/DICONDE +(0014,4030) SQ ReceiverSettingsSequence 1 DICOM/DICONDE +(0014,4031) DS AcquiredSoundpathLength 1 DICOM/DICONDE +(0014,4032) CS AcquisitionCompressionType 1 DICOM/DICONDE +(0014,4033) IS AcquisitionSampleSize 1 DICOM/DICONDE +(0014,4034) DS RectifierSmoothing 1 DICOM/DICONDE +(0014,4035) SQ DACSequence 1 DICOM/DICONDE +(0014,4036) CS DACType 1 DICOM/DICONDE +(0014,4038) DS DACGainPoints 1-n DICOM/DICONDE +(0014,403A) DS DACTimePoints 1-n DICOM/DICONDE +(0014,403C) DS DACAmplitude 1-n DICOM/DICONDE +(0014,4040) SQ PreAmplifierSettingsSequence 1 DICOM/DICONDE +(0014,4050) SQ TransmitTransducerSettingsSequence 1 DICOM/DICONDE +(0014,4051) SQ ReceiveTransducerSettingsSequence 1 DICOM/DICONDE +(0014,4052) DS IncidentAngle 1 DICOM/DICONDE +(0014,4054) ST CouplingTechnique 1 DICOM/DICONDE +(0014,4056) ST CouplingMedium 1 DICOM/DICONDE +(0014,4057) DS CouplingVelocity 1 DICOM/DICONDE +(0014,4058) DS ProbeCenterLocationX 1 DICOM/DICONDE +(0014,4059) DS ProbeCenterLocationZ 1 DICOM/DICONDE +(0014,405A) DS SoundPathLength 1 DICOM/DICONDE +(0014,405C) ST DelayLawIdentifier 1 DICOM/DICONDE +(0014,4060) SQ GateSettingsSequence 1 DICOM/DICONDE +(0014,4062) DS GateThreshold 1 DICOM/DICONDE +(0014,4064) DS VelocityOfSound 1 DICOM/DICONDE +(0014,4070) SQ CalibrationSettingsSequence 1 DICOM/DICONDE +(0014,4072) ST CalibrationProcedure 1 DICOM/DICONDE +(0014,4074) SH ProcedureVersion 1 DICOM/DICONDE +(0014,4076) DA ProcedureCreationDate 1 DICOM/DICONDE +(0014,4078) DA ProcedureExpirationDate 1 DICOM/DICONDE +(0014,407A) DA ProcedureLastModifiedDate 1 DICOM/DICONDE +(0014,407C) TM CalibrationTime 1-n DICOM/DICONDE +(0014,407E) DA CalibrationDate 1-n DICOM/DICONDE +(0014,4080) SQ ProbeDriveEquipmentSequence 1 DICOM/DICONDE +(0014,4081) CS DriveType 1 DICOM/DICONDE +(0014,4082) LT ProbeDriveNotes 1 DICOM/DICONDE +(0014,4083) SQ DriveProbeSequence 1 DICOM/DICONDE +(0014,4084) DS ProbeInductance 1 DICOM/DICONDE +(0014,4085) DS ProbeResistance 1 DICOM/DICONDE +(0014,4086) SQ ReceiveProbeSequence 1 DICOM/DICONDE +(0014,4087) SQ ProbeDriveSettingsSequence 1 DICOM/DICONDE +(0014,4088) DS BridgeResistors 1 DICOM/DICONDE +(0014,4089) DS ProbeOrientationAngle 1 DICOM/DICONDE +(0014,408B) DS UserSelectedGainY 1 DICOM/DICONDE +(0014,408C) DS UserSelectedPhase 1 DICOM/DICONDE +(0014,408D) DS UserSelectedOffsetX 1 DICOM/DICONDE +(0014,408E) DS UserSelectedOffsetY 1 DICOM/DICONDE +(0014,4091) SQ ChannelSettingsSequence 1 DICOM/DICONDE +(0014,4092) DS ChannelThreshold 1 DICOM/DICONDE +(0014,409A) SQ ScannerSettingsSequence 1 DICOM/DICONDE +(0014,409B) ST ScanProcedure 1 DICOM/DICONDE +(0014,409C) DS TranslationRateX 1 DICOM/DICONDE +(0014,409D) DS TranslationRateY 1 DICOM/DICONDE +(0014,409F) DS ChannelOverlap 1 DICOM/DICONDE +(0014,40A0) LO ImageQualityIndicatorType 1 DICOM/DICONDE +(0014,40A1) LO ImageQualityIndicatorMaterial 1 DICOM/DICONDE +(0014,40A2) LO ImageQualityIndicatorSize 1 DICOM/DICONDE +(0014,5002) IS LINACEnergy 1 DICOM/DICONDE +(0014,5004) IS LINACOutput 1 DICOM/DICONDE +(0014,5100) US ActiveAperture 1 DICOM/DICONDE +(0014,5101) DS TotalAperture 1 DICOM/DICONDE +(0014,5102) DS ApertureElevation 1 DICOM/DICONDE +(0014,5103) DS MainLobeAngle 1 DICOM/DICONDE +(0014,5104) DS MainRoofAngle 1 DICOM/DICONDE +(0014,5105) CS ConnectorType 1 DICOM/DICONDE +(0014,5106) SH WedgeModelNumber 1 DICOM/DICONDE +(0014,5107) DS WedgeAngleFloat 1 DICOM/DICONDE +(0014,5108) DS WedgeRoofAngle 1 DICOM/DICONDE +(0014,5109) CS WedgeElement1Position 1 DICOM/DICONDE +(0014,510A) DS WedgeMaterialVelocity 1 DICOM/DICONDE +(0014,510B) SH WedgeMaterial 1 DICOM/DICONDE +(0014,510C) DS WedgeOffsetZ 1 DICOM/DICONDE +(0014,510D) DS WedgeOriginOffsetX 1 DICOM/DICONDE +(0014,510E) DS WedgeTimeDelay 1 DICOM/DICONDE +(0014,510F) SH WedgeName 1 DICOM/DICONDE +(0014,5110) SH WedgeManufacturerName 1 DICOM/DICONDE +(0014,5111) LO WedgeDescription 1 DICOM/DICONDE +(0014,5112) DS NominalBeamAngle 1 DICOM/DICONDE +(0014,5113) DS WedgeOffsetX 1 DICOM/DICONDE +(0014,5114) DS WedgeOffsetY 1 DICOM/DICONDE +(0014,5115) DS WedgeTotalLength 1 DICOM/DICONDE +(0014,5116) DS WedgeInContactLength 1 DICOM/DICONDE +(0014,5117) DS WedgeFrontGap 1 DICOM/DICONDE +(0014,5118) DS WedgeTotalHeight 1 DICOM/DICONDE +(0014,5119) DS WedgeFrontHeight 1 DICOM/DICONDE +(0014,511A) DS WedgeRearHeight 1 DICOM/DICONDE +(0014,511B) DS WedgeTotalWidth 1 DICOM/DICONDE +(0014,511C) DS WedgeInContactWidth 1 DICOM/DICONDE +(0014,511D) DS WedgeChamferHeight 1 DICOM/DICONDE +(0014,511E) CS WedgeCurve 1 DICOM/DICONDE +(0014,511F) DS RadiusAlongWedge 1 DICOM/DICONDE +(0018,0010) LO ContrastBolusAgent 1 DICOM +(0018,0012) SQ ContrastBolusAgentSequence 1 DICOM +(0018,0013) FL ContrastBolusT1Relaxivity 1 DICOM +(0018,0014) SQ ContrastBolusAdministrationRouteSequence 1 DICOM +(0018,0015) CS BodyPartExamined 1 DICOM +(0018,0020) CS ScanningSequence 1-n DICOM +(0018,0021) CS SequenceVariant 1-n DICOM +(0018,0022) CS ScanOptions 1-n DICOM +(0018,0023) CS MRAcquisitionType 1 DICOM +(0018,0024) SH SequenceName 1 DICOM +(0018,0025) CS AngioFlag 1 DICOM +(0018,0026) SQ InterventionDrugInformationSequence 1 DICOM +(0018,0027) TM InterventionDrugStopTime 1 DICOM +(0018,0028) DS InterventionDrugDose 1 DICOM +(0018,0029) SQ InterventionDrugCodeSequence 1 DICOM +(0018,002A) SQ AdditionalDrugSequence 1 DICOM +(0018,0031) LO Radiopharmaceutical 1 DICOM +(0018,0034) LO InterventionDrugName 1 DICOM +(0018,0035) TM InterventionDrugStartTime 1 DICOM +(0018,0036) SQ InterventionSequence 1 DICOM +(0018,0038) CS InterventionStatus 1 DICOM +(0018,003A) ST InterventionDescription 1 DICOM +(0018,0040) IS CineRate 1 DICOM +(0018,0042) CS InitialCineRunState 1 DICOM +(0018,0050) DS SliceThickness 1 DICOM +(0018,0060) DS KVP 1 DICOM +(0018,0070) IS CountsAccumulated 1 DICOM +(0018,0071) CS AcquisitionTerminationCondition 1 DICOM +(0018,0072) DS EffectiveDuration 1 DICOM +(0018,0073) CS AcquisitionStartCondition 1 DICOM +(0018,0074) IS AcquisitionStartConditionData 1 DICOM +(0018,0075) IS AcquisitionTerminationConditionData 1 DICOM +(0018,0080) DS RepetitionTime 1 DICOM +(0018,0081) DS EchoTime 1 DICOM +(0018,0082) DS InversionTime 1 DICOM +(0018,0083) DS NumberOfAverages 1 DICOM +(0018,0084) DS ImagingFrequency 1 DICOM +(0018,0085) SH ImagedNucleus 1 DICOM +(0018,0086) IS EchoNumbers 1-n DICOM +(0018,0087) DS MagneticFieldStrength 1 DICOM +(0018,0088) DS SpacingBetweenSlices 1 DICOM +(0018,0089) IS NumberOfPhaseEncodingSteps 1 DICOM +(0018,0090) DS DataCollectionDiameter 1 DICOM +(0018,0091) IS EchoTrainLength 1 DICOM +(0018,0093) DS PercentSampling 1 DICOM +(0018,0094) DS PercentPhaseFieldOfView 1 DICOM +(0018,0095) DS PixelBandwidth 1 DICOM +(0018,1000) LO DeviceSerialNumber 1 DICOM +(0018,1002) UI DeviceUID 1 DICOM +(0018,1003) LO DeviceID 1 DICOM +(0018,1004) LO PlateID 1 DICOM +(0018,1005) LO GeneratorID 1 DICOM +(0018,1006) LO GridID 1 DICOM +(0018,1007) LO CassetteID 1 DICOM +(0018,1008) LO GantryID 1 DICOM +(0018,1010) LO SecondaryCaptureDeviceID 1 DICOM +(0018,1012) DA DateOfSecondaryCapture 1 DICOM +(0018,1014) TM TimeOfSecondaryCapture 1 DICOM +(0018,1016) LO SecondaryCaptureDeviceManufacturer 1 DICOM +(0018,1018) LO SecondaryCaptureDeviceManufacturerModelName 1 DICOM +(0018,1019) LO SecondaryCaptureDeviceSoftwareVersions 1-n DICOM +(0018,1020) LO SoftwareVersions 1-n DICOM +(0018,1022) SH VideoImageFormatAcquired 1 DICOM +(0018,1023) LO DigitalImageFormatAcquired 1 DICOM +(0018,1030) LO ProtocolName 1 DICOM +(0018,1040) LO ContrastBolusRoute 1 DICOM +(0018,1041) DS ContrastBolusVolume 1 DICOM +(0018,1042) TM ContrastBolusStartTime 1 DICOM +(0018,1043) TM ContrastBolusStopTime 1 DICOM +(0018,1044) DS ContrastBolusTotalDose 1 DICOM +(0018,1045) IS SyringeCounts 1 DICOM +(0018,1046) DS ContrastFlowRate 1-n DICOM +(0018,1047) DS ContrastFlowDuration 1-n DICOM +(0018,1048) CS ContrastBolusIngredient 1 DICOM +(0018,1049) DS ContrastBolusIngredientConcentration 1 DICOM +(0018,1050) DS SpatialResolution 1 DICOM +(0018,1060) DS TriggerTime 1 DICOM +(0018,1061) LO TriggerSourceOrType 1 DICOM +(0018,1062) IS NominalInterval 1 DICOM +(0018,1063) DS FrameTime 1 DICOM +(0018,1064) LO CardiacFramingType 1 DICOM +(0018,1065) DS FrameTimeVector 1-n DICOM +(0018,1066) DS FrameDelay 1 DICOM +(0018,1067) DS ImageTriggerDelay 1 DICOM +(0018,1068) DS MultiplexGroupTimeOffset 1 DICOM +(0018,1069) DS TriggerTimeOffset 1 DICOM +(0018,106A) CS SynchronizationTrigger 1 DICOM +(0018,106C) US SynchronizationChannel 2 DICOM +(0018,106E) UL TriggerSamplePosition 1 DICOM +(0018,1070) LO RadiopharmaceuticalRoute 1 DICOM +(0018,1071) DS RadiopharmaceuticalVolume 1 DICOM +(0018,1072) TM RadiopharmaceuticalStartTime 1 DICOM +(0018,1073) TM RadiopharmaceuticalStopTime 1 DICOM +(0018,1074) DS RadionuclideTotalDose 1 DICOM +(0018,1075) DS RadionuclideHalfLife 1 DICOM +(0018,1076) DS RadionuclidePositronFraction 1 DICOM +(0018,1077) DS RadiopharmaceuticalSpecificActivity 1 DICOM +(0018,1078) DT RadiopharmaceuticalStartDateTime 1 DICOM +(0018,1079) DT RadiopharmaceuticalStopDateTime 1 DICOM +(0018,1080) CS BeatRejectionFlag 1 DICOM +(0018,1081) IS LowRRValue 1 DICOM +(0018,1082) IS HighRRValue 1 DICOM +(0018,1083) IS IntervalsAcquired 1 DICOM +(0018,1084) IS IntervalsRejected 1 DICOM +(0018,1085) LO PVCRejection 1 DICOM +(0018,1086) IS SkipBeats 1 DICOM +(0018,1088) IS HeartRate 1 DICOM +(0018,1090) IS CardiacNumberOfImages 1 DICOM +(0018,1094) IS TriggerWindow 1 DICOM +(0018,1100) DS ReconstructionDiameter 1 DICOM +(0018,1110) DS DistanceSourceToDetector 1 DICOM +(0018,1111) DS DistanceSourceToPatient 1 DICOM +(0018,1114) DS EstimatedRadiographicMagnificationFactor 1 DICOM +(0018,1120) DS GantryDetectorTilt 1 DICOM +(0018,1121) DS GantryDetectorSlew 1 DICOM +(0018,1130) DS TableHeight 1 DICOM +(0018,1131) DS TableTraverse 1 DICOM +(0018,1134) CS TableMotion 1 DICOM +(0018,1135) DS TableVerticalIncrement 1-n DICOM +(0018,1136) DS TableLateralIncrement 1-n DICOM +(0018,1137) DS TableLongitudinalIncrement 1-n DICOM +(0018,1138) DS TableAngle 1 DICOM +(0018,113A) CS TableType 1 DICOM +(0018,1140) CS RotationDirection 1 DICOM +(0018,1142) DS RadialPosition 1-n DICOM +(0018,1143) DS ScanArc 1 DICOM +(0018,1144) DS AngularStep 1 DICOM +(0018,1145) DS CenterOfRotationOffset 1 DICOM +(0018,1147) CS FieldOfViewShape 1 DICOM +(0018,1149) IS FieldOfViewDimensions 1-2 DICOM +(0018,1150) IS ExposureTime 1 DICOM +(0018,1151) IS XRayTubeCurrent 1 DICOM +(0018,1152) IS Exposure 1 DICOM +(0018,1153) IS ExposureInuAs 1 DICOM +(0018,1154) DS AveragePulseWidth 1 DICOM +(0018,1155) CS RadiationSetting 1 DICOM +(0018,1156) CS RectificationType 1 DICOM +(0018,115A) CS RadiationMode 1 DICOM +(0018,115E) DS ImageAndFluoroscopyAreaDoseProduct 1 DICOM +(0018,1160) SH FilterType 1 DICOM +(0018,1161) LO TypeOfFilters 1-n DICOM +(0018,1162) DS IntensifierSize 1 DICOM +(0018,1164) DS ImagerPixelSpacing 2 DICOM +(0018,1166) CS Grid 1-n DICOM +(0018,1170) IS GeneratorPower 1 DICOM +(0018,1180) SH CollimatorGridName 1 DICOM +(0018,1181) CS CollimatorType 1 DICOM +(0018,1182) IS FocalDistance 1-2 DICOM +(0018,1183) DS XFocusCenter 1-2 DICOM +(0018,1184) DS YFocusCenter 1-2 DICOM +(0018,1190) DS FocalSpots 1-n DICOM +(0018,1191) CS AnodeTargetMaterial 1 DICOM +(0018,11A0) DS BodyPartThickness 1 DICOM +(0018,11A2) DS CompressionForce 1 DICOM +(0018,11A4) LO PaddleDescription 1 DICOM +(0018,1200) DA DateOfLastCalibration 1-n DICOM +(0018,1201) TM TimeOfLastCalibration 1-n DICOM +(0018,1202) DT DateTimeOfLastCalibration 1 DICOM +(0018,1210) SH ConvolutionKernel 1-n DICOM +(0018,1242) IS ActualFrameDuration 1 DICOM +(0018,1243) IS CountRate 1 DICOM +(0018,1244) US PreferredPlaybackSequencing 1 DICOM +(0018,1250) SH ReceiveCoilName 1 DICOM +(0018,1251) SH TransmitCoilName 1 DICOM +(0018,1260) SH PlateType 1 DICOM +(0018,1261) LO PhosphorType 1 DICOM +(0018,1300) DS ScanVelocity 1 DICOM +(0018,1301) CS WholeBodyTechnique 1-n DICOM +(0018,1302) IS ScanLength 1 DICOM +(0018,1310) US AcquisitionMatrix 4 DICOM +(0018,1312) CS InPlanePhaseEncodingDirection 1 DICOM +(0018,1314) DS FlipAngle 1 DICOM +(0018,1315) CS VariableFlipAngleFlag 1 DICOM +(0018,1316) DS SAR 1 DICOM +(0018,1318) DS dBdt 1 DICOM +(0018,1400) LO AcquisitionDeviceProcessingDescription 1 DICOM +(0018,1401) LO AcquisitionDeviceProcessingCode 1 DICOM +(0018,1402) CS CassetteOrientation 1 DICOM +(0018,1403) CS CassetteSize 1 DICOM +(0018,1404) US ExposuresOnPlate 1 DICOM +(0018,1405) IS RelativeXRayExposure 1 DICOM +(0018,1411) DS ExposureIndex 1 DICOM +(0018,1412) DS TargetExposureIndex 1 DICOM +(0018,1413) DS DeviationIndex 1 DICOM +(0018,1450) DS ColumnAngulation 1 DICOM +(0018,1460) DS TomoLayerHeight 1 DICOM +(0018,1470) DS TomoAngle 1 DICOM +(0018,1480) DS TomoTime 1 DICOM +(0018,1490) CS TomoType 1 DICOM +(0018,1491) CS TomoClass 1 DICOM +(0018,1495) IS NumberOfTomosynthesisSourceImages 1 DICOM +(0018,1500) CS PositionerMotion 1 DICOM +(0018,1508) CS PositionerType 1 DICOM +(0018,1510) DS PositionerPrimaryAngle 1 DICOM +(0018,1511) DS PositionerSecondaryAngle 1 DICOM +(0018,1520) DS PositionerPrimaryAngleIncrement 1-n DICOM +(0018,1521) DS PositionerSecondaryAngleIncrement 1-n DICOM +(0018,1530) DS DetectorPrimaryAngle 1 DICOM +(0018,1531) DS DetectorSecondaryAngle 1 DICOM +(0018,1600) CS ShutterShape 1-3 DICOM +(0018,1602) IS ShutterLeftVerticalEdge 1 DICOM +(0018,1604) IS ShutterRightVerticalEdge 1 DICOM +(0018,1606) IS ShutterUpperHorizontalEdge 1 DICOM +(0018,1608) IS ShutterLowerHorizontalEdge 1 DICOM +(0018,1610) IS CenterOfCircularShutter 2 DICOM +(0018,1612) IS RadiusOfCircularShutter 1 DICOM +(0018,1620) IS VerticesOfThePolygonalShutter 2-2n DICOM +(0018,1622) US ShutterPresentationValue 1 DICOM +(0018,1623) US ShutterOverlayGroup 1 DICOM +(0018,1624) US ShutterPresentationColorCIELabValue 3 DICOM +(0018,1700) CS CollimatorShape 1-3 DICOM +(0018,1702) IS CollimatorLeftVerticalEdge 1 DICOM +(0018,1704) IS CollimatorRightVerticalEdge 1 DICOM +(0018,1706) IS CollimatorUpperHorizontalEdge 1 DICOM +(0018,1708) IS CollimatorLowerHorizontalEdge 1 DICOM +(0018,1710) IS CenterOfCircularCollimator 2 DICOM +(0018,1712) IS RadiusOfCircularCollimator 1 DICOM +(0018,1720) IS VerticesOfThePolygonalCollimator 2-2n DICOM +(0018,1800) CS AcquisitionTimeSynchronized 1 DICOM +(0018,1801) SH TimeSource 1 DICOM +(0018,1802) CS TimeDistributionProtocol 1 DICOM +(0018,1803) LO NTPSourceAddress 1 DICOM +(0018,2001) IS PageNumberVector 1-n DICOM +(0018,2002) SH FrameLabelVector 1-n DICOM +(0018,2003) DS FramePrimaryAngleVector 1-n DICOM +(0018,2004) DS FrameSecondaryAngleVector 1-n DICOM +(0018,2005) DS SliceLocationVector 1-n DICOM +(0018,2006) SH DisplayWindowLabelVector 1-n DICOM +(0018,2010) DS NominalScannedPixelSpacing 2 DICOM +(0018,2020) CS DigitizingDeviceTransportDirection 1 DICOM +(0018,2030) DS RotationOfScannedFilm 1 DICOM +(0018,2041) SQ BiopsyTargetSequence 1 DICOM +(0018,2042) UI TargetUID 1 DICOM +(0018,2043) FL LocalizingCursorPosition 2 DICOM +(0018,2044) FL CalculatedTargetPosition 3 DICOM +(0018,2045) SH TargetLabel 1 DICOM +(0018,2046) FL DisplayedZValue 1 DICOM +(0018,3100) CS IVUSAcquisition 1 DICOM +(0018,3101) DS IVUSPullbackRate 1 DICOM +(0018,3102) DS IVUSGatedRate 1 DICOM +(0018,3103) IS IVUSPullbackStartFrameNumber 1 DICOM +(0018,3104) IS IVUSPullbackStopFrameNumber 1 DICOM +(0018,3105) IS LesionNumber 1-n DICOM +(0018,5000) SH OutputPower 1-n DICOM +(0018,5010) LO TransducerData 1-n DICOM +(0018,5012) DS FocusDepth 1 DICOM +(0018,5020) LO ProcessingFunction 1 DICOM +(0018,5022) DS MechanicalIndex 1 DICOM +(0018,5024) DS BoneThermalIndex 1 DICOM +(0018,5026) DS CranialThermalIndex 1 DICOM +(0018,5027) DS SoftTissueThermalIndex 1 DICOM +(0018,5028) DS SoftTissueFocusThermalIndex 1 DICOM +(0018,5029) DS SoftTissueSurfaceThermalIndex 1 DICOM +(0018,5050) IS DepthOfScanField 1 DICOM +(0018,5100) CS PatientPosition 1 DICOM +(0018,5101) CS ViewPosition 1 DICOM +(0018,5104) SQ ProjectionEponymousNameCodeSequence 1 DICOM +(0018,6000) DS Sensitivity 1 DICOM +(0018,6011) SQ SequenceOfUltrasoundRegions 1 DICOM +(0018,6012) US RegionSpatialFormat 1 DICOM +(0018,6014) US RegionDataType 1 DICOM +(0018,6016) UL RegionFlags 1 DICOM +(0018,6018) UL RegionLocationMinX0 1 DICOM +(0018,601A) UL RegionLocationMinY0 1 DICOM +(0018,601C) UL RegionLocationMaxX1 1 DICOM +(0018,601E) UL RegionLocationMaxY1 1 DICOM +(0018,6020) SL ReferencePixelX0 1 DICOM +(0018,6022) SL ReferencePixelY0 1 DICOM +(0018,6024) US PhysicalUnitsXDirection 1 DICOM +(0018,6026) US PhysicalUnitsYDirection 1 DICOM +(0018,6028) FD ReferencePixelPhysicalValueX 1 DICOM +(0018,602A) FD ReferencePixelPhysicalValueY 1 DICOM +(0018,602C) FD PhysicalDeltaX 1 DICOM +(0018,602E) FD PhysicalDeltaY 1 DICOM +(0018,6030) UL TransducerFrequency 1 DICOM +(0018,6031) CS TransducerType 1 DICOM +(0018,6032) UL PulseRepetitionFrequency 1 DICOM +(0018,6034) FD DopplerCorrectionAngle 1 DICOM +(0018,6036) FD SteeringAngle 1 DICOM +(0018,6039) SL DopplerSampleVolumeXPosition 1 DICOM +(0018,603B) SL DopplerSampleVolumeYPosition 1 DICOM +(0018,603D) SL TMLinePositionX0 1 DICOM +(0018,603F) SL TMLinePositionY0 1 DICOM +(0018,6041) SL TMLinePositionX1 1 DICOM +(0018,6043) SL TMLinePositionY1 1 DICOM +(0018,6044) US PixelComponentOrganization 1 DICOM +(0018,6046) UL PixelComponentMask 1 DICOM +(0018,6048) UL PixelComponentRangeStart 1 DICOM +(0018,604A) UL PixelComponentRangeStop 1 DICOM +(0018,604C) US PixelComponentPhysicalUnits 1 DICOM +(0018,604E) US PixelComponentDataType 1 DICOM +(0018,6050) UL NumberOfTableBreakPoints 1 DICOM +(0018,6052) UL TableOfXBreakPoints 1-n DICOM +(0018,6054) FD TableOfYBreakPoints 1-n DICOM +(0018,6056) UL NumberOfTableEntries 1 DICOM +(0018,6058) UL TableOfPixelValues 1-n DICOM +(0018,605A) FL TableOfParameterValues 1-n DICOM +(0018,6060) FL RWaveTimeVector 1-n DICOM +(0018,7000) CS DetectorConditionsNominalFlag 1 DICOM +(0018,7001) DS DetectorTemperature 1 DICOM +(0018,7004) CS DetectorType 1 DICOM +(0018,7005) CS DetectorConfiguration 1 DICOM +(0018,7006) LT DetectorDescription 1 DICOM +(0018,7008) LT DetectorMode 1 DICOM +(0018,700A) SH DetectorID 1 DICOM +(0018,700C) DA DateOfLastDetectorCalibration 1 DICOM +(0018,700E) TM TimeOfLastDetectorCalibration 1 DICOM +(0018,7010) IS ExposuresOnDetectorSinceLastCalibration 1 DICOM +(0018,7011) IS ExposuresOnDetectorSinceManufactured 1 DICOM +(0018,7012) DS DetectorTimeSinceLastExposure 1 DICOM +(0018,7014) DS DetectorActiveTime 1 DICOM +(0018,7016) DS DetectorActivationOffsetFromExposure 1 DICOM +(0018,701A) DS DetectorBinning 2 DICOM +(0018,7020) DS DetectorElementPhysicalSize 2 DICOM +(0018,7022) DS DetectorElementSpacing 2 DICOM +(0018,7024) CS DetectorActiveShape 1 DICOM +(0018,7026) DS DetectorActiveDimensions 1-2 DICOM +(0018,7028) DS DetectorActiveOrigin 2 DICOM +(0018,702A) LO DetectorManufacturerName 1 DICOM +(0018,702B) LO DetectorManufacturerModelName 1 DICOM +(0018,7030) DS FieldOfViewOrigin 2 DICOM +(0018,7032) DS FieldOfViewRotation 1 DICOM +(0018,7034) CS FieldOfViewHorizontalFlip 1 DICOM +(0018,7036) FL PixelDataAreaOriginRelativeToFOV 2 DICOM +(0018,7038) FL PixelDataAreaRotationAngleRelativeToFOV 1 DICOM +(0018,7040) LT GridAbsorbingMaterial 1 DICOM +(0018,7041) LT GridSpacingMaterial 1 DICOM +(0018,7042) DS GridThickness 1 DICOM +(0018,7044) DS GridPitch 1 DICOM +(0018,7046) IS GridAspectRatio 2 DICOM +(0018,7048) DS GridPeriod 1 DICOM +(0018,704C) DS GridFocalDistance 1 DICOM +(0018,7050) CS FilterMaterial 1-n DICOM +(0018,7052) DS FilterThicknessMinimum 1-n DICOM +(0018,7054) DS FilterThicknessMaximum 1-n DICOM +(0018,7056) FL FilterBeamPathLengthMinimum 1-n DICOM +(0018,7058) FL FilterBeamPathLengthMaximum 1-n DICOM +(0018,7060) CS ExposureControlMode 1 DICOM +(0018,7062) LT ExposureControlModeDescription 1 DICOM +(0018,7064) CS ExposureStatus 1 DICOM +(0018,7065) DS PhototimerSetting 1 DICOM +(0018,8150) DS ExposureTimeInuS 1 DICOM +(0018,8151) DS XRayTubeCurrentInuA 1 DICOM +(0018,9004) CS ContentQualification 1 DICOM +(0018,9005) SH PulseSequenceName 1 DICOM +(0018,9006) SQ MRImagingModifierSequence 1 DICOM +(0018,9008) CS EchoPulseSequence 1 DICOM +(0018,9009) CS InversionRecovery 1 DICOM +(0018,9010) CS FlowCompensation 1 DICOM +(0018,9011) CS MultipleSpinEcho 1 DICOM +(0018,9012) CS MultiPlanarExcitation 1 DICOM +(0018,9014) CS PhaseContrast 1 DICOM +(0018,9015) CS TimeOfFlightContrast 1 DICOM +(0018,9016) CS Spoiling 1 DICOM +(0018,9017) CS SteadyStatePulseSequence 1 DICOM +(0018,9018) CS EchoPlanarPulseSequence 1 DICOM +(0018,9019) FD TagAngleFirstAxis 1 DICOM +(0018,9020) CS MagnetizationTransfer 1 DICOM +(0018,9021) CS T2Preparation 1 DICOM +(0018,9022) CS BloodSignalNulling 1 DICOM +(0018,9024) CS SaturationRecovery 1 DICOM +(0018,9025) CS SpectrallySelectedSuppression 1 DICOM +(0018,9026) CS SpectrallySelectedExcitation 1 DICOM +(0018,9027) CS SpatialPresaturation 1 DICOM +(0018,9028) CS Tagging 1 DICOM +(0018,9029) CS OversamplingPhase 1 DICOM +(0018,9030) FD TagSpacingFirstDimension 1 DICOM +(0018,9032) CS GeometryOfKSpaceTraversal 1 DICOM +(0018,9033) CS SegmentedKSpaceTraversal 1 DICOM +(0018,9034) CS RectilinearPhaseEncodeReordering 1 DICOM +(0018,9035) FD TagThickness 1 DICOM +(0018,9036) CS PartialFourierDirection 1 DICOM +(0018,9037) CS CardiacSynchronizationTechnique 1 DICOM +(0018,9041) LO ReceiveCoilManufacturerName 1 DICOM +(0018,9042) SQ MRReceiveCoilSequence 1 DICOM +(0018,9043) CS ReceiveCoilType 1 DICOM +(0018,9044) CS QuadratureReceiveCoil 1 DICOM +(0018,9045) SQ MultiCoilDefinitionSequence 1 DICOM +(0018,9046) LO MultiCoilConfiguration 1 DICOM +(0018,9047) SH MultiCoilElementName 1 DICOM +(0018,9048) CS MultiCoilElementUsed 1 DICOM +(0018,9049) SQ MRTransmitCoilSequence 1 DICOM +(0018,9050) LO TransmitCoilManufacturerName 1 DICOM +(0018,9051) CS TransmitCoilType 1 DICOM +(0018,9052) FD SpectralWidth 1-2 DICOM +(0018,9053) FD ChemicalShiftReference 1-2 DICOM +(0018,9054) CS VolumeLocalizationTechnique 1 DICOM +(0018,9058) US MRAcquisitionFrequencyEncodingSteps 1 DICOM +(0018,9059) CS Decoupling 1 DICOM +(0018,9060) CS DecoupledNucleus 1-2 DICOM +(0018,9061) FD DecouplingFrequency 1-2 DICOM +(0018,9062) CS DecouplingMethod 1 DICOM +(0018,9063) FD DecouplingChemicalShiftReference 1-2 DICOM +(0018,9064) CS KSpaceFiltering 1 DICOM +(0018,9065) CS TimeDomainFiltering 1-2 DICOM +(0018,9066) US NumberOfZeroFills 1-2 DICOM +(0018,9067) CS BaselineCorrection 1 DICOM +(0018,9069) FD ParallelReductionFactorInPlane 1 DICOM +(0018,9070) FD CardiacRRIntervalSpecified 1 DICOM +(0018,9073) FD AcquisitionDuration 1 DICOM +(0018,9074) DT FrameAcquisitionDateTime 1 DICOM +(0018,9075) CS DiffusionDirectionality 1 DICOM +(0018,9076) SQ DiffusionGradientDirectionSequence 1 DICOM +(0018,9077) CS ParallelAcquisition 1 DICOM +(0018,9078) CS ParallelAcquisitionTechnique 1 DICOM +(0018,9079) FD InversionTimes 1-n DICOM +(0018,9080) ST MetaboliteMapDescription 1 DICOM +(0018,9081) CS PartialFourier 1 DICOM +(0018,9082) FD EffectiveEchoTime 1 DICOM +(0018,9083) SQ MetaboliteMapCodeSequence 1 DICOM +(0018,9084) SQ ChemicalShiftSequence 1 DICOM +(0018,9085) CS CardiacSignalSource 1 DICOM +(0018,9087) FD DiffusionBValue 1 DICOM +(0018,9089) FD DiffusionGradientOrientation 3 DICOM +(0018,9090) FD VelocityEncodingDirection 3 DICOM +(0018,9091) FD VelocityEncodingMinimumValue 1 DICOM +(0018,9092) SQ VelocityEncodingAcquisitionSequence 1 DICOM +(0018,9093) US NumberOfKSpaceTrajectories 1 DICOM +(0018,9094) CS CoverageOfKSpace 1 DICOM +(0018,9095) UL SpectroscopyAcquisitionPhaseRows 1 DICOM +(0018,9098) FD TransmitterFrequency 1-2 DICOM +(0018,9100) CS ResonantNucleus 1-2 DICOM +(0018,9101) CS FrequencyCorrection 1 DICOM +(0018,9103) SQ MRSpectroscopyFOVGeometrySequence 1 DICOM +(0018,9104) FD SlabThickness 1 DICOM +(0018,9105) FD SlabOrientation 3 DICOM +(0018,9106) FD MidSlabPosition 3 DICOM +(0018,9107) SQ MRSpatialSaturationSequence 1 DICOM +(0018,9112) SQ MRTimingAndRelatedParametersSequence 1 DICOM +(0018,9114) SQ MREchoSequence 1 DICOM +(0018,9115) SQ MRModifierSequence 1 DICOM +(0018,9117) SQ MRDiffusionSequence 1 DICOM +(0018,9118) SQ CardiacSynchronizationSequence 1 DICOM +(0018,9119) SQ MRAveragesSequence 1 DICOM +(0018,9125) SQ MRFOVGeometrySequence 1 DICOM +(0018,9126) SQ VolumeLocalizationSequence 1 DICOM +(0018,9127) UL SpectroscopyAcquisitionDataColumns 1 DICOM +(0018,9147) CS DiffusionAnisotropyType 1 DICOM +(0018,9151) DT FrameReferenceDateTime 1 DICOM +(0018,9152) SQ MRMetaboliteMapSequence 1 DICOM +(0018,9155) FD ParallelReductionFactorOutOfPlane 1 DICOM +(0018,9159) UL SpectroscopyAcquisitionOutOfPlanePhaseSteps 1 DICOM +(0018,9168) FD ParallelReductionFactorSecondInPlane 1 DICOM +(0018,9169) CS CardiacBeatRejectionTechnique 1 DICOM +(0018,9170) CS RespiratoryMotionCompensationTechnique 1 DICOM +(0018,9171) CS RespiratorySignalSource 1 DICOM +(0018,9172) CS BulkMotionCompensationTechnique 1 DICOM +(0018,9173) CS BulkMotionSignalSource 1 DICOM +(0018,9174) CS ApplicableSafetyStandardAgency 1 DICOM +(0018,9175) LO ApplicableSafetyStandardDescription 1 DICOM +(0018,9176) SQ OperatingModeSequence 1 DICOM +(0018,9177) CS OperatingModeType 1 DICOM +(0018,9178) CS OperatingMode 1 DICOM +(0018,9179) CS SpecificAbsorptionRateDefinition 1 DICOM +(0018,9180) CS GradientOutputType 1 DICOM +(0018,9181) FD SpecificAbsorptionRateValue 1 DICOM +(0018,9182) FD GradientOutput 1 DICOM +(0018,9183) CS FlowCompensationDirection 1 DICOM +(0018,9184) FD TaggingDelay 1 DICOM +(0018,9185) ST RespiratoryMotionCompensationTechniqueDescription 1 DICOM +(0018,9186) SH RespiratorySignalSourceID 1 DICOM +(0018,9197) SQ MRVelocityEncodingSequence 1 DICOM +(0018,9198) CS FirstOrderPhaseCorrection 1 DICOM +(0018,9199) CS WaterReferencedPhaseCorrection 1 DICOM +(0018,9200) CS MRSpectroscopyAcquisitionType 1 DICOM +(0018,9214) CS RespiratoryCyclePosition 1 DICOM +(0018,9217) FD VelocityEncodingMaximumValue 1 DICOM +(0018,9218) FD TagSpacingSecondDimension 1 DICOM +(0018,9219) SS TagAngleSecondAxis 1 DICOM +(0018,9220) FD FrameAcquisitionDuration 1 DICOM +(0018,9226) SQ MRImageFrameTypeSequence 1 DICOM +(0018,9227) SQ MRSpectroscopyFrameTypeSequence 1 DICOM +(0018,9231) US MRAcquisitionPhaseEncodingStepsInPlane 1 DICOM +(0018,9232) US MRAcquisitionPhaseEncodingStepsOutOfPlane 1 DICOM +(0018,9234) UL SpectroscopyAcquisitionPhaseColumns 1 DICOM +(0018,9236) CS CardiacCyclePosition 1 DICOM +(0018,9239) SQ SpecificAbsorptionRateSequence 1 DICOM +(0018,9240) US RFEchoTrainLength 1 DICOM +(0018,9241) US GradientEchoTrainLength 1 DICOM +(0018,9250) CS ArterialSpinLabelingContrast 1 DICOM +(0018,9251) SQ MRArterialSpinLabelingSequence 1 DICOM +(0018,9252) LO ASLTechniqueDescription 1 DICOM +(0018,9253) US ASLSlabNumber 1 DICOM +(0018,9254) FD ASLSlabThickness 1 DICOM +(0018,9255) FD ASLSlabOrientation 3 DICOM +(0018,9256) FD ASLMidSlabPosition 3 DICOM +(0018,9257) CS ASLContext 1 DICOM +(0018,9258) UL ASLPulseTrainDuration 1 DICOM +(0018,9259) CS ASLCrusherFlag 1 DICOM +(0018,925A) FD ASLCrusherFlowLimit 1 DICOM +(0018,925B) LO ASLCrusherDescription 1 DICOM +(0018,925C) CS ASLBolusCutoffFlag 1 DICOM +(0018,925D) SQ ASLBolusCutoffTimingSequence 1 DICOM +(0018,925E) LO ASLBolusCutoffTechnique 1 DICOM +(0018,925F) UL ASLBolusCutoffDelayTime 1 DICOM +(0018,9260) SQ ASLSlabSequence 1 DICOM +(0018,9295) FD ChemicalShiftMinimumIntegrationLimitInppm 1 DICOM +(0018,9296) FD ChemicalShiftMaximumIntegrationLimitInppm 1 DICOM +(0018,9297) CS WaterReferenceAcquisition 1 DICOM +(0018,9298) IS EchoPeakPosition 1 DICOM +(0018,9301) SQ CTAcquisitionTypeSequence 1 DICOM +(0018,9302) CS AcquisitionType 1 DICOM +(0018,9303) FD TubeAngle 1 DICOM +(0018,9304) SQ CTAcquisitionDetailsSequence 1 DICOM +(0018,9305) FD RevolutionTime 1 DICOM +(0018,9306) FD SingleCollimationWidth 1 DICOM +(0018,9307) FD TotalCollimationWidth 1 DICOM +(0018,9308) SQ CTTableDynamicsSequence 1 DICOM +(0018,9309) FD TableSpeed 1 DICOM +(0018,9310) FD TableFeedPerRotation 1 DICOM +(0018,9311) FD SpiralPitchFactor 1 DICOM +(0018,9312) SQ CTGeometrySequence 1 DICOM +(0018,9313) FD DataCollectionCenterPatient 3 DICOM +(0018,9314) SQ CTReconstructionSequence 1 DICOM +(0018,9315) CS ReconstructionAlgorithm 1 DICOM +(0018,9316) CS ConvolutionKernelGroup 1 DICOM +(0018,9317) FD ReconstructionFieldOfView 2 DICOM +(0018,9318) FD ReconstructionTargetCenterPatient 3 DICOM +(0018,9319) FD ReconstructionAngle 1 DICOM +(0018,9320) SH ImageFilter 1 DICOM +(0018,9321) SQ CTExposureSequence 1 DICOM +(0018,9322) FD ReconstructionPixelSpacing 2 DICOM +(0018,9323) CS ExposureModulationType 1 DICOM +(0018,9324) FD EstimatedDoseSaving 1 DICOM +(0018,9325) SQ CTXRayDetailsSequence 1 DICOM +(0018,9326) SQ CTPositionSequence 1 DICOM +(0018,9327) FD TablePosition 1 DICOM +(0018,9328) FD ExposureTimeInms 1 DICOM +(0018,9329) SQ CTImageFrameTypeSequence 1 DICOM +(0018,9330) FD XRayTubeCurrentInmA 1 DICOM +(0018,9332) FD ExposureInmAs 1 DICOM +(0018,9333) CS ConstantVolumeFlag 1 DICOM +(0018,9334) CS FluoroscopyFlag 1 DICOM +(0018,9335) FD DistanceSourceToDataCollectionCenter 1 DICOM +(0018,9337) US ContrastBolusAgentNumber 1 DICOM +(0018,9338) SQ ContrastBolusIngredientCodeSequence 1 DICOM +(0018,9340) SQ ContrastAdministrationProfileSequence 1 DICOM +(0018,9341) SQ ContrastBolusUsageSequence 1 DICOM +(0018,9342) CS ContrastBolusAgentAdministered 1 DICOM +(0018,9343) CS ContrastBolusAgentDetected 1 DICOM +(0018,9344) CS ContrastBolusAgentPhase 1 DICOM +(0018,9345) FD CTDIvol 1 DICOM +(0018,9346) SQ CTDIPhantomTypeCodeSequence 1 DICOM +(0018,9351) FL CalciumScoringMassFactorPatient 1 DICOM +(0018,9352) FL CalciumScoringMassFactorDevice 3 DICOM +(0018,9353) FL EnergyWeightingFactor 1 DICOM +(0018,9360) SQ CTAdditionalXRaySourceSequence 1 DICOM +(0018,9401) SQ ProjectionPixelCalibrationSequence 1 DICOM +(0018,9402) FL DistanceSourceToIsocenter 1 DICOM +(0018,9403) FL DistanceObjectToTableTop 1 DICOM +(0018,9404) FL ObjectPixelSpacingInCenterOfBeam 2 DICOM +(0018,9405) SQ PositionerPositionSequence 1 DICOM +(0018,9406) SQ TablePositionSequence 1 DICOM +(0018,9407) SQ CollimatorShapeSequence 1 DICOM +(0018,9410) CS PlanesInAcquisition 1 DICOM +(0018,9412) SQ XAXRFFrameCharacteristicsSequence 1 DICOM +(0018,9417) SQ FrameAcquisitionSequence 1 DICOM +(0018,9420) CS XRayReceptorType 1 DICOM +(0018,9423) LO AcquisitionProtocolName 1 DICOM +(0018,9424) LT AcquisitionProtocolDescription 1 DICOM +(0018,9425) CS ContrastBolusIngredientOpaque 1 DICOM +(0018,9426) FL DistanceReceptorPlaneToDetectorHousing 1 DICOM +(0018,9427) CS IntensifierActiveShape 1 DICOM +(0018,9428) FL IntensifierActiveDimensions 1-2 DICOM +(0018,9429) FL PhysicalDetectorSize 2 DICOM +(0018,9430) FL PositionOfIsocenterProjection 2 DICOM +(0018,9432) SQ FieldOfViewSequence 1 DICOM +(0018,9433) LO FieldOfViewDescription 1 DICOM +(0018,9434) SQ ExposureControlSensingRegionsSequence 1 DICOM +(0018,9435) CS ExposureControlSensingRegionShape 1 DICOM +(0018,9436) SS ExposureControlSensingRegionLeftVerticalEdge 1 DICOM +(0018,9437) SS ExposureControlSensingRegionRightVerticalEdge 1 DICOM +(0018,9438) SS ExposureControlSensingRegionUpperHorizontalEdge 1 DICOM +(0018,9439) SS ExposureControlSensingRegionLowerHorizontalEdge 1 DICOM +(0018,9440) SS CenterOfCircularExposureControlSensingRegion 2 DICOM +(0018,9441) US RadiusOfCircularExposureControlSensingRegion 1 DICOM +(0018,9442) SS VerticesOfThePolygonalExposureControlSensingRegion 2-n DICOM +(0018,9447) FL ColumnAngulationPatient 1 DICOM +(0018,9449) FL BeamAngle 1 DICOM +(0018,9451) SQ FrameDetectorParametersSequence 1 DICOM +(0018,9452) FL CalculatedAnatomyThickness 1 DICOM +(0018,9455) SQ CalibrationSequence 1 DICOM +(0018,9456) SQ ObjectThicknessSequence 1 DICOM +(0018,9457) CS PlaneIdentification 1 DICOM +(0018,9461) FL FieldOfViewDimensionsInFloat 1-2 DICOM +(0018,9462) SQ IsocenterReferenceSystemSequence 1 DICOM +(0018,9463) FL PositionerIsocenterPrimaryAngle 1 DICOM +(0018,9464) FL PositionerIsocenterSecondaryAngle 1 DICOM +(0018,9465) FL PositionerIsocenterDetectorRotationAngle 1 DICOM +(0018,9466) FL TableXPositionToIsocenter 1 DICOM +(0018,9467) FL TableYPositionToIsocenter 1 DICOM +(0018,9468) FL TableZPositionToIsocenter 1 DICOM +(0018,9469) FL TableHorizontalRotationAngle 1 DICOM +(0018,9470) FL TableHeadTiltAngle 1 DICOM +(0018,9471) FL TableCradleTiltAngle 1 DICOM +(0018,9472) SQ FrameDisplayShutterSequence 1 DICOM +(0018,9473) FL AcquiredImageAreaDoseProduct 1 DICOM +(0018,9474) CS CArmPositionerTabletopRelationship 1 DICOM +(0018,9476) SQ XRayGeometrySequence 1 DICOM +(0018,9477) SQ IrradiationEventIdentificationSequence 1 DICOM +(0018,9504) SQ XRay3DFrameTypeSequence 1 DICOM +(0018,9506) SQ ContributingSourcesSequence 1 DICOM +(0018,9507) SQ XRay3DAcquisitionSequence 1 DICOM +(0018,9508) FL PrimaryPositionerScanArc 1 DICOM +(0018,9509) FL SecondaryPositionerScanArc 1 DICOM +(0018,9510) FL PrimaryPositionerScanStartAngle 1 DICOM +(0018,9511) FL SecondaryPositionerScanStartAngle 1 DICOM +(0018,9514) FL PrimaryPositionerIncrement 1 DICOM +(0018,9515) FL SecondaryPositionerIncrement 1 DICOM +(0018,9516) DT StartAcquisitionDateTime 1 DICOM +(0018,9517) DT EndAcquisitionDateTime 1 DICOM +(0018,9518) SS PrimaryPositionerIncrementSign 1 DICOM +(0018,9519) SS SecondaryPositionerIncrementSign 1 DICOM +(0018,9524) LO ApplicationName 1 DICOM +(0018,9525) LO ApplicationVersion 1 DICOM +(0018,9526) LO ApplicationManufacturer 1 DICOM +(0018,9527) CS AlgorithmType 1 DICOM +(0018,9528) LO AlgorithmDescription 1 DICOM +(0018,9530) SQ XRay3DReconstructionSequence 1 DICOM +(0018,9531) LO ReconstructionDescription 1 DICOM +(0018,9538) SQ PerProjectionAcquisitionSequence 1 DICOM +(0018,9541) SQ DetectorPositionSequence 1 DICOM +(0018,9542) SQ XRayAcquisitionDoseSequence 1 DICOM +(0018,9543) FD XRaySourceIsocenterPrimaryAngle 1 DICOM +(0018,9544) FD XRaySourceIsocenterSecondaryAngle 1 DICOM +(0018,9545) FD BreastSupportIsocenterPrimaryAngle 1 DICOM +(0018,9546) FD BreastSupportIsocenterSecondaryAngle 1 DICOM +(0018,9547) FD BreastSupportXPositionToIsocenter 1 DICOM +(0018,9548) FD BreastSupportYPositionToIsocenter 1 DICOM +(0018,9549) FD BreastSupportZPositionToIsocenter 1 DICOM +(0018,9550) FD DetectorIsocenterPrimaryAngle 1 DICOM +(0018,9551) FD DetectorIsocenterSecondaryAngle 1 DICOM +(0018,9552) FD DetectorXPositionToIsocenter 1 DICOM +(0018,9553) FD DetectorYPositionToIsocenter 1 DICOM +(0018,9554) FD DetectorZPositionToIsocenter 1 DICOM +(0018,9555) SQ XRayGridSequence 1 DICOM +(0018,9556) SQ XRayFilterSequence 1 DICOM +(0018,9557) FD DetectorActiveAreaTLHCPosition 3 DICOM +(0018,9558) FD DetectorActiveAreaOrientation 6 DICOM +(0018,9559) CS PositionerPrimaryAngleDirection 1 DICOM +(0018,9601) SQ DiffusionBMatrixSequence 1 DICOM +(0018,9602) FD DiffusionBValueXX 1 DICOM +(0018,9603) FD DiffusionBValueXY 1 DICOM +(0018,9604) FD DiffusionBValueXZ 1 DICOM +(0018,9605) FD DiffusionBValueYY 1 DICOM +(0018,9606) FD DiffusionBValueYZ 1 DICOM +(0018,9607) FD DiffusionBValueZZ 1 DICOM +(0018,9701) DT DecayCorrectionDateTime 1 DICOM +(0018,9715) FD StartDensityThreshold 1 DICOM +(0018,9716) FD StartRelativeDensityDifferenceThreshold 1 DICOM +(0018,9717) FD StartCardiacTriggerCountThreshold 1 DICOM +(0018,9718) FD StartRespiratoryTriggerCountThreshold 1 DICOM +(0018,9719) FD TerminationCountsThreshold 1 DICOM +(0018,9720) FD TerminationDensityThreshold 1 DICOM +(0018,9721) FD TerminationRelativeDensityThreshold 1 DICOM +(0018,9722) FD TerminationTimeThreshold 1 DICOM +(0018,9723) FD TerminationCardiacTriggerCountThreshold 1 DICOM +(0018,9724) FD TerminationRespiratoryTriggerCountThreshold 1 DICOM +(0018,9725) CS DetectorGeometry 1 DICOM +(0018,9726) FD TransverseDetectorSeparation 1 DICOM +(0018,9727) FD AxialDetectorDimension 1 DICOM +(0018,9729) US RadiopharmaceuticalAgentNumber 1 DICOM +(0018,9732) SQ PETFrameAcquisitionSequence 1 DICOM +(0018,9733) SQ PETDetectorMotionDetailsSequence 1 DICOM +(0018,9734) SQ PETTableDynamicsSequence 1 DICOM +(0018,9735) SQ PETPositionSequence 1 DICOM +(0018,9736) SQ PETFrameCorrectionFactorsSequence 1 DICOM +(0018,9737) SQ RadiopharmaceuticalUsageSequence 1 DICOM +(0018,9738) CS AttenuationCorrectionSource 1 DICOM +(0018,9739) US NumberOfIterations 1 DICOM +(0018,9740) US NumberOfSubsets 1 DICOM +(0018,9749) SQ PETReconstructionSequence 1 DICOM +(0018,9751) SQ PETFrameTypeSequence 1 DICOM +(0018,9755) CS TimeOfFlightInformationUsed 1 DICOM +(0018,9756) CS ReconstructionType 1 DICOM +(0018,9758) CS DecayCorrected 1 DICOM +(0018,9759) CS AttenuationCorrected 1 DICOM +(0018,9760) CS ScatterCorrected 1 DICOM +(0018,9761) CS DeadTimeCorrected 1 DICOM +(0018,9762) CS GantryMotionCorrected 1 DICOM +(0018,9763) CS PatientMotionCorrected 1 DICOM +(0018,9764) CS CountLossNormalizationCorrected 1 DICOM +(0018,9765) CS RandomsCorrected 1 DICOM +(0018,9766) CS NonUniformRadialSamplingCorrected 1 DICOM +(0018,9767) CS SensitivityCalibrated 1 DICOM +(0018,9768) CS DetectorNormalizationCorrection 1 DICOM +(0018,9769) CS IterativeReconstructionMethod 1 DICOM +(0018,9770) CS AttenuationCorrectionTemporalRelationship 1 DICOM +(0018,9771) SQ PatientPhysiologicalStateSequence 1 DICOM +(0018,9772) SQ PatientPhysiologicalStateCodeSequence 1 DICOM +(0018,9801) FD DepthsOfFocus 1-n DICOM +(0018,9803) SQ ExcludedIntervalsSequence 1 DICOM +(0018,9804) DT ExclusionStartDateTime 1 DICOM +(0018,9805) FD ExclusionDuration 1 DICOM +(0018,9806) SQ USImageDescriptionSequence 1 DICOM +(0018,9807) SQ ImageDataTypeSequence 1 DICOM +(0018,9808) CS DataType 1 DICOM +(0018,9809) SQ TransducerScanPatternCodeSequence 1 DICOM +(0018,980B) CS AliasedDataType 1 DICOM +(0018,980C) CS PositionMeasuringDeviceUsed 1 DICOM +(0018,980D) SQ TransducerGeometryCodeSequence 1 DICOM +(0018,980E) SQ TransducerBeamSteeringCodeSequence 1 DICOM +(0018,980F) SQ TransducerApplicationCodeSequence 1 DICOM +(0018,9810) xs ZeroVelocityPixelValue 1 DICOM +(0018,A001) SQ ContributingEquipmentSequence 1 DICOM +(0018,A002) DT ContributionDateTime 1 DICOM +(0018,A003) ST ContributionDescription 1 DICOM +(0020,000D) UI StudyInstanceUID 1 DICOM +(0020,000E) UI SeriesInstanceUID 1 DICOM +(0020,0010) SH StudyID 1 DICOM +(0020,0011) IS SeriesNumber 1 DICOM +(0020,0012) IS AcquisitionNumber 1 DICOM +(0020,0013) IS InstanceNumber 1 DICOM +(0020,0019) IS ItemNumber 1 DICOM +(0020,0020) CS PatientOrientation 2 DICOM +(0020,0032) DS ImagePositionPatient 3 DICOM +(0020,0037) DS ImageOrientationPatient 6 DICOM +(0020,0052) UI FrameOfReferenceUID 1 DICOM +(0020,0060) CS Laterality 1 DICOM +(0020,0062) CS ImageLaterality 1 DICOM +(0020,0100) IS TemporalPositionIdentifier 1 DICOM +(0020,0105) IS NumberOfTemporalPositions 1 DICOM +(0020,0110) DS TemporalResolution 1 DICOM +(0020,0200) UI SynchronizationFrameOfReferenceUID 1 DICOM +(0020,0242) UI SOPInstanceUIDOfConcatenationSource 1 DICOM +(0020,1002) IS ImagesInAcquisition 1 DICOM +(0020,1040) LO PositionReferenceIndicator 1 DICOM +(0020,1041) DS SliceLocation 1 DICOM +(0020,1200) IS NumberOfPatientRelatedStudies 1 DICOM +(0020,1202) IS NumberOfPatientRelatedSeries 1 DICOM +(0020,1204) IS NumberOfPatientRelatedInstances 1 DICOM +(0020,1206) IS NumberOfStudyRelatedSeries 1 DICOM +(0020,1208) IS NumberOfStudyRelatedInstances 1 DICOM +(0020,1209) IS NumberOfSeriesRelatedInstances 1 DICOM +(0020,4000) LT ImageComments 1 DICOM +(0020,9056) SH StackID 1 DICOM +(0020,9057) UL InStackPositionNumber 1 DICOM +(0020,9071) SQ FrameAnatomySequence 1 DICOM +(0020,9072) CS FrameLaterality 1 DICOM +(0020,9111) SQ FrameContentSequence 1 DICOM +(0020,9113) SQ PlanePositionSequence 1 DICOM +(0020,9116) SQ PlaneOrientationSequence 1 DICOM +(0020,9128) UL TemporalPositionIndex 1 DICOM +(0020,9153) FD NominalCardiacTriggerDelayTime 1 DICOM +(0020,9154) FL NominalCardiacTriggerTimePriorToRPeak 1 DICOM +(0020,9155) FL ActualCardiacTriggerTimePriorToRPeak 1 DICOM +(0020,9156) US FrameAcquisitionNumber 1 DICOM +(0020,9157) UL DimensionIndexValues 1-n DICOM +(0020,9158) LT FrameComments 1 DICOM +(0020,9161) UI ConcatenationUID 1 DICOM +(0020,9162) US InConcatenationNumber 1 DICOM +(0020,9163) US InConcatenationTotalNumber 1 DICOM +(0020,9164) UI DimensionOrganizationUID 1 DICOM +(0020,9165) AT DimensionIndexPointer 1 DICOM +(0020,9167) AT FunctionalGroupPointer 1 DICOM +(0020,9170) SQ UnassignedSharedConvertedAttributesSequence 1 DICOM +(0020,9171) SQ UnassignedPerFrameConvertedAttributesSequence 1 DICOM +(0020,9172) SQ ConversionSourceAttributesSequence 1 DICOM +(0020,9213) LO DimensionIndexPrivateCreator 1 DICOM +(0020,9221) SQ DimensionOrganizationSequence 1 DICOM +(0020,9222) SQ DimensionIndexSequence 1 DICOM +(0020,9228) UL ConcatenationFrameOffsetNumber 1 DICOM +(0020,9238) LO FunctionalGroupPrivateCreator 1 DICOM +(0020,9241) FL NominalPercentageOfCardiacPhase 1 DICOM +(0020,9245) FL NominalPercentageOfRespiratoryPhase 1 DICOM +(0020,9246) FL StartingRespiratoryAmplitude 1 DICOM +(0020,9247) CS StartingRespiratoryPhase 1 DICOM +(0020,9248) FL EndingRespiratoryAmplitude 1 DICOM +(0020,9249) CS EndingRespiratoryPhase 1 DICOM +(0020,9250) CS RespiratoryTriggerType 1 DICOM +(0020,9251) FD RRIntervalTimeNominal 1 DICOM +(0020,9252) FD ActualCardiacTriggerDelayTime 1 DICOM +(0020,9253) SQ RespiratorySynchronizationSequence 1 DICOM +(0020,9254) FD RespiratoryIntervalTime 1 DICOM +(0020,9255) FD NominalRespiratoryTriggerDelayTime 1 DICOM +(0020,9256) FD RespiratoryTriggerDelayThreshold 1 DICOM +(0020,9257) FD ActualRespiratoryTriggerDelayTime 1 DICOM +(0020,9301) FD ImagePositionVolume 3 DICOM +(0020,9302) FD ImageOrientationVolume 6 DICOM +(0020,9307) CS UltrasoundAcquisitionGeometry 1 DICOM +(0020,9308) FD ApexPosition 3 DICOM +(0020,9309) FD VolumeToTransducerMappingMatrix 16 DICOM +(0020,930A) FD VolumeToTableMappingMatrix 16 DICOM +(0020,930B) CS VolumeToTransducerRelationship 1 DICOM +(0020,930C) CS PatientFrameOfReferenceSource 1 DICOM +(0020,930D) FD TemporalPositionTimeOffset 1 DICOM +(0020,930E) SQ PlanePositionVolumeSequence 1 DICOM +(0020,930F) SQ PlaneOrientationVolumeSequence 1 DICOM +(0020,9310) SQ TemporalPositionSequence 1 DICOM +(0020,9311) CS DimensionOrganizationType 1 DICOM +(0020,9312) UI VolumeFrameOfReferenceUID 1 DICOM +(0020,9313) UI TableFrameOfReferenceUID 1 DICOM +(0020,9421) LO DimensionDescriptionLabel 1 DICOM +(0020,9450) SQ PatientOrientationInFrameSequence 1 DICOM +(0020,9453) LO FrameLabel 1 DICOM +(0020,9518) US AcquisitionIndex 1-n DICOM +(0020,9529) SQ ContributingSOPInstancesReferenceSequence 1 DICOM +(0020,9536) US ReconstructionIndex 1 DICOM +(0022,0001) US LightPathFilterPassThroughWavelength 1 DICOM +(0022,0002) US LightPathFilterPassBand 2 DICOM +(0022,0003) US ImagePathFilterPassThroughWavelength 1 DICOM +(0022,0004) US ImagePathFilterPassBand 2 DICOM +(0022,0005) CS PatientEyeMovementCommanded 1 DICOM +(0022,0006) SQ PatientEyeMovementCommandCodeSequence 1 DICOM +(0022,0007) FL SphericalLensPower 1 DICOM +(0022,0008) FL CylinderLensPower 1 DICOM +(0022,0009) FL CylinderAxis 1 DICOM +(0022,000A) FL EmmetropicMagnification 1 DICOM +(0022,000B) FL IntraOcularPressure 1 DICOM +(0022,000C) FL HorizontalFieldOfView 1 DICOM +(0022,000D) CS PupilDilated 1 DICOM +(0022,000E) FL DegreeOfDilation 1 DICOM +(0022,0010) FL StereoBaselineAngle 1 DICOM +(0022,0011) FL StereoBaselineDisplacement 1 DICOM +(0022,0012) FL StereoHorizontalPixelOffset 1 DICOM +(0022,0013) FL StereoVerticalPixelOffset 1 DICOM +(0022,0014) FL StereoRotation 1 DICOM +(0022,0015) SQ AcquisitionDeviceTypeCodeSequence 1 DICOM +(0022,0016) SQ IlluminationTypeCodeSequence 1 DICOM +(0022,0017) SQ LightPathFilterTypeStackCodeSequence 1 DICOM +(0022,0018) SQ ImagePathFilterTypeStackCodeSequence 1 DICOM +(0022,0019) SQ LensesCodeSequence 1 DICOM +(0022,001A) SQ ChannelDescriptionCodeSequence 1 DICOM +(0022,001B) SQ RefractiveStateSequence 1 DICOM +(0022,001C) SQ MydriaticAgentCodeSequence 1 DICOM +(0022,001D) SQ RelativeImagePositionCodeSequence 1 DICOM +(0022,001E) FL CameraAngleOfView 1 DICOM +(0022,0020) SQ StereoPairsSequence 1 DICOM +(0022,0021) SQ LeftImageSequence 1 DICOM +(0022,0022) SQ RightImageSequence 1 DICOM +(0022,0028) CS StereoPairsPresent 1 DICOM +(0022,0030) FL AxialLengthOfTheEye 1 DICOM +(0022,0031) SQ OphthalmicFrameLocationSequence 1 DICOM +(0022,0032) FL ReferenceCoordinates 2-2n DICOM +(0022,0035) FL DepthSpatialResolution 1 DICOM +(0022,0036) FL MaximumDepthDistortion 1 DICOM +(0022,0037) FL AlongScanSpatialResolution 1 DICOM +(0022,0038) FL MaximumAlongScanDistortion 1 DICOM +(0022,0039) CS OphthalmicImageOrientation 1 DICOM +(0022,0041) FL DepthOfTransverseImage 1 DICOM +(0022,0042) SQ MydriaticAgentConcentrationUnitsSequence 1 DICOM +(0022,0048) FL AcrossScanSpatialResolution 1 DICOM +(0022,0049) FL MaximumAcrossScanDistortion 1 DICOM +(0022,004E) DS MydriaticAgentConcentration 1 DICOM +(0022,0055) FL IlluminationWaveLength 1 DICOM +(0022,0056) FL IlluminationPower 1 DICOM +(0022,0057) FL IlluminationBandwidth 1 DICOM +(0022,0058) SQ MydriaticAgentSequence 1 DICOM +(0022,1007) SQ OphthalmicAxialMeasurementsRightEyeSequence 1 DICOM +(0022,1008) SQ OphthalmicAxialMeasurementsLeftEyeSequence 1 DICOM +(0022,1009) CS OphthalmicAxialMeasurementsDeviceType 1 DICOM +(0022,1010) CS OphthalmicAxialLengthMeasurementsType 1 DICOM +(0022,1012) SQ OphthalmicAxialLengthSequence 1 DICOM +(0022,1019) FL OphthalmicAxialLength 1 DICOM +(0022,1024) SQ LensStatusCodeSequence 1 DICOM +(0022,1025) SQ VitreousStatusCodeSequence 1 DICOM +(0022,1028) SQ IOLFormulaCodeSequence 1 DICOM +(0022,1029) LO IOLFormulaDetail 1 DICOM +(0022,1033) FL KeratometerIndex 1 DICOM +(0022,1035) SQ SourceOfOphthalmicAxialLengthCodeSequence 1 DICOM +(0022,1037) FL TargetRefraction 1 DICOM +(0022,1039) CS RefractiveProcedureOccurred 1 DICOM +(0022,1040) SQ RefractiveSurgeryTypeCodeSequence 1 DICOM +(0022,1044) SQ OphthalmicUltrasoundMethodCodeSequence 1 DICOM +(0022,1050) SQ OphthalmicAxialLengthMeasurementsSequence 1 DICOM +(0022,1053) FL IOLPower 1 DICOM +(0022,1054) FL PredictedRefractiveError 1 DICOM +(0022,1059) FL OphthalmicAxialLengthVelocity 1 DICOM +(0022,1065) LO LensStatusDescription 1 DICOM +(0022,1066) LO VitreousStatusDescription 1 DICOM +(0022,1090) SQ IOLPowerSequence 1 DICOM +(0022,1092) SQ LensConstantSequence 1 DICOM +(0022,1093) LO IOLManufacturer 1 DICOM +(0022,1095) LO ImplantName 1 DICOM +(0022,1096) SQ KeratometryMeasurementTypeCodeSequence 1 DICOM +(0022,1097) LO ImplantPartNumber 1 DICOM +(0022,1100) SQ ReferencedOphthalmicAxialMeasurementsSequence 1 DICOM +(0022,1101) SQ OphthalmicAxialLengthMeasurementsSegmentNameCodeSequence 1 DICOM +(0022,1103) SQ RefractiveErrorBeforeRefractiveSurgeryCodeSequence 1 DICOM +(0022,1121) FL IOLPowerForExactEmmetropia 1 DICOM +(0022,1122) FL IOLPowerForExactTargetRefraction 1 DICOM +(0022,1125) SQ AnteriorChamberDepthDefinitionCodeSequence 1 DICOM +(0022,1127) SQ LensThicknessSequence 1 DICOM +(0022,1128) SQ AnteriorChamberDepthSequence 1 DICOM +(0022,1130) FL LensThickness 1 DICOM +(0022,1131) FL AnteriorChamberDepth 1 DICOM +(0022,1132) SQ SourceOfLensThicknessDataCodeSequence 1 DICOM +(0022,1133) SQ SourceOfAnteriorChamberDepthDataCodeSequence 1 DICOM +(0022,1134) SQ SourceOfRefractiveMeasurementsSequence 1 DICOM +(0022,1135) SQ SourceOfRefractiveMeasurementsCodeSequence 1 DICOM +(0022,1140) CS OphthalmicAxialLengthMeasurementModified 1 DICOM +(0022,1150) SQ OphthalmicAxialLengthDataSourceCodeSequence 1 DICOM +(0022,1155) FL SignalToNoiseRatio 1 DICOM +(0022,1159) LO OphthalmicAxialLengthDataSourceDescription 1 DICOM +(0022,1210) SQ OphthalmicAxialLengthMeasurementsTotalLengthSequence 1 DICOM +(0022,1211) SQ OphthalmicAxialLengthMeasurementsSegmentalLengthSequence 1 DICOM +(0022,1212) SQ OphthalmicAxialLengthMeasurementsLengthSummationSequence 1 DICOM +(0022,1220) SQ UltrasoundOphthalmicAxialLengthMeasurementsSequence 1 DICOM +(0022,1225) SQ OpticalOphthalmicAxialLengthMeasurementsSequence 1 DICOM +(0022,1230) SQ UltrasoundSelectedOphthalmicAxialLengthSequence 1 DICOM +(0022,1250) SQ OphthalmicAxialLengthSelectionMethodCodeSequence 1 DICOM +(0022,1255) SQ OpticalSelectedOphthalmicAxialLengthSequence 1 DICOM +(0022,1257) SQ SelectedSegmentalOphthalmicAxialLengthSequence 1 DICOM +(0022,1260) SQ SelectedTotalOphthalmicAxialLengthSequence 1 DICOM +(0022,1262) SQ OphthalmicAxialLengthQualityMetricSequence 1 DICOM +(0022,1300) SQ IntraocularLensCalculationsRightEyeSequence 1 DICOM +(0022,1310) SQ IntraocularLensCalculationsLeftEyeSequence 1 DICOM +(0022,1330) SQ ReferencedOphthalmicAxialLengthMeasurementQCImageSequence 1 DICOM +(0022,1415) CS OphthalmicMappingDeviceType 1 DICOM +(0022,1420) SQ AcquisitionMethodCodeSequence 1 DICOM +(0022,1423) SQ AcquisitionMethodAlgorithmSequence 1 DICOM +(0022,1436) SQ OphthalmicThicknessMapTypeCodeSequence 1 DICOM +(0022,1443) SQ OphthalmicThicknessMappingNormalsSequence 1 DICOM +(0022,1445) SQ RetinalThicknessDefinitionCodeSequence 1 DICOM +(0022,1450) SQ PixelValueMappingToCodedConceptSequence 1 DICOM +(0022,1452) xs MappedPixelValue 1 DICOM +(0022,1454) LO PixelValueMappingExplanation 1 DICOM +(0022,1458) SQ OphthalmicThicknessMapQualityThresholdSequence 1 DICOM +(0022,1460) FL OphthalmicThicknessMapThresholdQualityRating 1 DICOM +(0022,1463) FL AnatomicStructureReferencePoint 2 DICOM +(0022,1465) SQ RegistrationToLocalizerSequence 1 DICOM +(0022,1466) CS RegisteredLocalizerUnits 1 DICOM +(0022,1467) FL RegisteredLocalizerTopLeftHandCorner 2 DICOM +(0022,1468) FL RegisteredLocalizerBottomRightHandCorner 2 DICOM +(0022,1470) SQ OphthalmicThicknessMapQualityRatingSequence 1 DICOM +(0022,1472) SQ RelevantOPTAttributesSequence 1 DICOM +(0022,1512) SQ TransformationMethodCodeSequence 1 DICOM +(0022,1513) SQ TransformationAlgorithmSequence 1 DICOM +(0022,1515) CS OphthalmicAxialLengthMethod 1 DICOM +(0022,1517) FL OphthalmicFOV 1 DICOM +(0022,1518) SQ TwoDimensionalToThreeDimensionalMapSequence 1 DICOM +(0022,1525) SQ WideFieldOphthalmicPhotographyQualityRatingSequence 1 DICOM +(0022,1526) SQ WideFieldOphthalmicPhotographyQualityThresholdSequence 1 DICOM +(0022,1527) FL WideFieldOphthalmicPhotographyThresholdQualityRating 1 DICOM +(0022,1528) FL XCoordinatesCenterPixelViewAngle 1 DICOM +(0022,1529) FL YCoordinatesCenterPixelViewAngle 1 DICOM +(0022,1530) UL NumberOfMapPoints 1 DICOM +(0022,1531) OF TwoDimensionalToThreeDimensionalMapData 1 DICOM +(0024,0010) FL VisualFieldHorizontalExtent 1 DICOM +(0024,0011) FL VisualFieldVerticalExtent 1 DICOM +(0024,0012) CS VisualFieldShape 1 DICOM +(0024,0016) SQ ScreeningTestModeCodeSequence 1 DICOM +(0024,0018) FL MaximumStimulusLuminance 1 DICOM +(0024,0020) FL BackgroundLuminance 1 DICOM +(0024,0021) SQ StimulusColorCodeSequence 1 DICOM +(0024,0024) SQ BackgroundIlluminationColorCodeSequence 1 DICOM +(0024,0025) FL StimulusArea 1 DICOM +(0024,0028) FL StimulusPresentationTime 1 DICOM +(0024,0032) SQ FixationSequence 1 DICOM +(0024,0033) SQ FixationMonitoringCodeSequence 1 DICOM +(0024,0034) SQ VisualFieldCatchTrialSequence 1 DICOM +(0024,0035) US FixationCheckedQuantity 1 DICOM +(0024,0036) US PatientNotProperlyFixatedQuantity 1 DICOM +(0024,0037) CS PresentedVisualStimuliDataFlag 1 DICOM +(0024,0038) US NumberOfVisualStimuli 1 DICOM +(0024,0039) CS ExcessiveFixationLossesDataFlag 1 DICOM +(0024,0040) CS ExcessiveFixationLosses 1 DICOM +(0024,0042) US StimuliRetestingQuantity 1 DICOM +(0024,0044) LT CommentsOnPatientPerformanceOfVisualField 1 DICOM +(0024,0045) CS FalseNegativesEstimateFlag 1 DICOM +(0024,0046) FL FalseNegativesEstimate 1 DICOM +(0024,0048) US NegativeCatchTrialsQuantity 1 DICOM +(0024,0050) US FalseNegativesQuantity 1 DICOM +(0024,0051) CS ExcessiveFalseNegativesDataFlag 1 DICOM +(0024,0052) CS ExcessiveFalseNegatives 1 DICOM +(0024,0053) CS FalsePositivesEstimateFlag 1 DICOM +(0024,0054) FL FalsePositivesEstimate 1 DICOM +(0024,0055) CS CatchTrialsDataFlag 1 DICOM +(0024,0056) US PositiveCatchTrialsQuantity 1 DICOM +(0024,0057) CS TestPointNormalsDataFlag 1 DICOM +(0024,0058) SQ TestPointNormalsSequence 1 DICOM +(0024,0059) CS GlobalDeviationProbabilityNormalsFlag 1 DICOM +(0024,0060) US FalsePositivesQuantity 1 DICOM +(0024,0061) CS ExcessiveFalsePositivesDataFlag 1 DICOM +(0024,0062) CS ExcessiveFalsePositives 1 DICOM +(0024,0063) CS VisualFieldTestNormalsFlag 1 DICOM +(0024,0064) SQ ResultsNormalsSequence 1 DICOM +(0024,0065) SQ AgeCorrectedSensitivityDeviationAlgorithmSequence 1 DICOM +(0024,0066) FL GlobalDeviationFromNormal 1 DICOM +(0024,0067) SQ GeneralizedDefectSensitivityDeviationAlgorithmSequence 1 DICOM +(0024,0068) FL LocalizedDeviationFromNormal 1 DICOM +(0024,0069) LO PatientReliabilityIndicator 1 DICOM +(0024,0070) FL VisualFieldMeanSensitivity 1 DICOM +(0024,0071) FL GlobalDeviationProbability 1 DICOM +(0024,0072) CS LocalDeviationProbabilityNormalsFlag 1 DICOM +(0024,0073) FL LocalizedDeviationProbability 1 DICOM +(0024,0074) CS ShortTermFluctuationCalculated 1 DICOM +(0024,0075) FL ShortTermFluctuation 1 DICOM +(0024,0076) CS ShortTermFluctuationProbabilityCalculated 1 DICOM +(0024,0077) FL ShortTermFluctuationProbability 1 DICOM +(0024,0078) CS CorrectedLocalizedDeviationFromNormalCalculated 1 DICOM +(0024,0079) FL CorrectedLocalizedDeviationFromNormal 1 DICOM +(0024,0080) CS CorrectedLocalizedDeviationFromNormalProbabilityCalculated 1 DICOM +(0024,0081) FL CorrectedLocalizedDeviationFromNormalProbability 1 DICOM +(0024,0083) SQ GlobalDeviationProbabilitySequence 1 DICOM +(0024,0085) SQ LocalizedDeviationProbabilitySequence 1 DICOM +(0024,0086) CS FovealSensitivityMeasured 1 DICOM +(0024,0087) FL FovealSensitivity 1 DICOM +(0024,0088) FL VisualFieldTestDuration 1 DICOM +(0024,0089) SQ VisualFieldTestPointSequence 1 DICOM +(0024,0090) FL VisualFieldTestPointXCoordinate 1 DICOM +(0024,0091) FL VisualFieldTestPointYCoordinate 1 DICOM +(0024,0092) FL AgeCorrectedSensitivityDeviationValue 1 DICOM +(0024,0093) CS StimulusResults 1 DICOM +(0024,0094) FL SensitivityValue 1 DICOM +(0024,0095) CS RetestStimulusSeen 1 DICOM +(0024,0096) FL RetestSensitivityValue 1 DICOM +(0024,0097) SQ VisualFieldTestPointNormalsSequence 1 DICOM +(0024,0098) FL QuantifiedDefect 1 DICOM +(0024,0100) FL AgeCorrectedSensitivityDeviationProbabilityValue 1 DICOM +(0024,0102) CS GeneralizedDefectCorrectedSensitivityDeviationFlag 1 DICOM +(0024,0103) FL GeneralizedDefectCorrectedSensitivityDeviationValue 1 DICOM +(0024,0104) FL GeneralizedDefectCorrectedSensitivityDeviationProbabilityValue 1 DICOM +(0024,0105) FL MinimumSensitivityValue 1 DICOM +(0024,0106) CS BlindSpotLocalized 1 DICOM +(0024,0107) FL BlindSpotXCoordinate 1 DICOM +(0024,0108) FL BlindSpotYCoordinate 1 DICOM +(0024,0110) SQ VisualAcuityMeasurementSequence 1 DICOM +(0024,0112) SQ RefractiveParametersUsedOnPatientSequence 1 DICOM +(0024,0113) CS MeasurementLaterality 1 DICOM +(0024,0114) SQ OphthalmicPatientClinicalInformationLeftEyeSequence 1 DICOM +(0024,0115) SQ OphthalmicPatientClinicalInformationRightEyeSequence 1 DICOM +(0024,0117) CS FovealPointNormativeDataFlag 1 DICOM +(0024,0118) FL FovealPointProbabilityValue 1 DICOM +(0024,0120) CS ScreeningBaselineMeasured 1 DICOM +(0024,0122) SQ ScreeningBaselineMeasuredSequence 1 DICOM +(0024,0124) CS ScreeningBaselineType 1 DICOM +(0024,0126) FL ScreeningBaselineValue 1 DICOM +(0024,0202) LO AlgorithmSource 1 DICOM +(0024,0306) LO DataSetName 1 DICOM +(0024,0307) LO DataSetVersion 1 DICOM +(0024,0308) LO DataSetSource 1 DICOM +(0024,0309) LO DataSetDescription 1 DICOM +(0024,0317) SQ VisualFieldTestReliabilityGlobalIndexSequence 1 DICOM +(0024,0320) SQ VisualFieldGlobalResultsIndexSequence 1 DICOM +(0024,0325) SQ DataObservationSequence 1 DICOM +(0024,0338) CS IndexNormalsFlag 1 DICOM +(0024,0341) FL IndexProbability 1 DICOM +(0024,0344) SQ IndexProbabilitySequence 1 DICOM +(0028,0002) US SamplesPerPixel 1 DICOM +(0028,0003) US SamplesPerPixelUsed 1 DICOM +(0028,0004) CS PhotometricInterpretation 1 DICOM +(0028,0006) US PlanarConfiguration 1 DICOM +(0028,0008) IS NumberOfFrames 1 DICOM +(0028,0009) AT FrameIncrementPointer 1-n DICOM +(0028,000A) AT FrameDimensionPointer 1-n DICOM +(0028,0010) US Rows 1 DICOM +(0028,0011) US Columns 1 DICOM +(0028,0014) US UltrasoundColorDataPresent 1 DICOM +(0028,0030) DS PixelSpacing 2 DICOM +(0028,0031) DS ZoomFactor 2 DICOM +(0028,0032) DS ZoomCenter 2 DICOM +(0028,0034) IS PixelAspectRatio 2 DICOM +(0028,0051) CS CorrectedImage 1-n DICOM +(0028,0100) US BitsAllocated 1 DICOM +(0028,0101) US BitsStored 1 DICOM +(0028,0102) US HighBit 1 DICOM +(0028,0103) US PixelRepresentation 1 DICOM +(0028,0106) xs SmallestImagePixelValue 1 DICOM +(0028,0107) xs LargestImagePixelValue 1 DICOM +(0028,0108) xs SmallestPixelValueInSeries 1 DICOM +(0028,0109) xs LargestPixelValueInSeries 1 DICOM +(0028,0120) xs PixelPaddingValue 1 DICOM +(0028,0121) xs PixelPaddingRangeLimit 1 DICOM +(0028,0122) FL FloatPixelPaddingValue 1 DICOM +(0028,0123) FD DoubleFloatPixelPaddingValue 1 DICOM +(0028,0124) FL FloatPixelPaddingRangeLimit 1 DICOM +(0028,0125) FD DoubleFloatPixelPaddingRangeLimit 1 DICOM +(0028,0300) CS QualityControlImage 1 DICOM +(0028,0301) CS BurnedInAnnotation 1 DICOM +(0028,0302) CS RecognizableVisualFeatures 1 DICOM +(0028,0303) CS LongitudinalTemporalInformationModified 1 DICOM +(0028,0304) UI ReferencedColorPaletteInstanceUID 1 DICOM +(0028,0A02) CS PixelSpacingCalibrationType 1 DICOM +(0028,0A04) LO PixelSpacingCalibrationDescription 1 DICOM +(0028,1040) CS PixelIntensityRelationship 1 DICOM +(0028,1041) SS PixelIntensityRelationshipSign 1 DICOM +(0028,1050) DS WindowCenter 1-n DICOM +(0028,1051) DS WindowWidth 1-n DICOM +(0028,1052) DS RescaleIntercept 1 DICOM +(0028,1053) DS RescaleSlope 1 DICOM +(0028,1054) LO RescaleType 1 DICOM +(0028,1055) LO WindowCenterWidthExplanation 1-n DICOM +(0028,1056) CS VOILUTFunction 1 DICOM +(0028,1090) CS RecommendedViewingMode 1 DICOM +(0028,1101) xs RedPaletteColorLookupTableDescriptor 3 DICOM +(0028,1102) xs GreenPaletteColorLookupTableDescriptor 3 DICOM +(0028,1103) xs BluePaletteColorLookupTableDescriptor 3 DICOM +(0028,1104) US AlphaPaletteColorLookupTableDescriptor 3 DICOM +(0028,1199) UI PaletteColorLookupTableUID 1 DICOM +(0028,1201) OW RedPaletteColorLookupTableData 1 DICOM +(0028,1202) OW GreenPaletteColorLookupTableData 1 DICOM +(0028,1203) OW BluePaletteColorLookupTableData 1 DICOM +(0028,1204) OW AlphaPaletteColorLookupTableData 1 DICOM +(0028,1221) OW SegmentedRedPaletteColorLookupTableData 1 DICOM +(0028,1222) OW SegmentedGreenPaletteColorLookupTableData 1 DICOM +(0028,1223) OW SegmentedBluePaletteColorLookupTableData 1 DICOM +(0028,1300) CS BreastImplantPresent 1 DICOM +(0028,1350) CS PartialView 1 DICOM +(0028,1351) ST PartialViewDescription 1 DICOM +(0028,1352) SQ PartialViewCodeSequence 1 DICOM +(0028,135A) CS SpatialLocationsPreserved 1 DICOM +(0028,1401) SQ DataFrameAssignmentSequence 1 DICOM +(0028,1402) CS DataPathAssignment 1 DICOM +(0028,1403) US BitsMappedToColorLookupTable 1 DICOM +(0028,1404) SQ BlendingLUT1Sequence 1 DICOM +(0028,1405) CS BlendingLUT1TransferFunction 1 DICOM +(0028,1406) FD BlendingWeightConstant 1 DICOM +(0028,1407) US BlendingLookupTableDescriptor 3 DICOM +(0028,1408) OW BlendingLookupTableData 1 DICOM +(0028,140B) SQ EnhancedPaletteColorLookupTableSequence 1 DICOM +(0028,140C) SQ BlendingLUT2Sequence 1 DICOM +(0028,140D) CS BlendingLUT2TransferFunction 1 DICOM +(0028,140E) CS DataPathID 1 DICOM +(0028,140F) CS RGBLUTTransferFunction 1 DICOM +(0028,1410) CS AlphaLUTTransferFunction 1 DICOM +(0028,2000) OB ICCProfile 1 DICOM +(0028,2110) CS LossyImageCompression 1 DICOM +(0028,2112) DS LossyImageCompressionRatio 1-n DICOM +(0028,2114) CS LossyImageCompressionMethod 1-n DICOM +(0028,3000) SQ ModalityLUTSequence 1 DICOM +(0028,3002) xs LUTDescriptor 3 DICOM +(0028,3003) LO LUTExplanation 1 DICOM +(0028,3004) LO ModalityLUTType 1 DICOM +(0028,3006) lt LUTData 1-n DICOM +(0028,3010) SQ VOILUTSequence 1 DICOM +(0028,3110) SQ SoftcopyVOILUTSequence 1 DICOM +(0028,6010) US RepresentativeFrameNumber 1 DICOM +(0028,6020) US FrameNumbersOfInterest 1-n DICOM +(0028,6022) LO FrameOfInterestDescription 1-n DICOM +(0028,6023) CS FrameOfInterestType 1-n DICOM +(0028,6040) US RWavePointer 1-n DICOM +(0028,6100) SQ MaskSubtractionSequence 1 DICOM +(0028,6101) CS MaskOperation 1 DICOM +(0028,6102) US ApplicableFrameRange 2-2n DICOM +(0028,6110) US MaskFrameNumbers 1-n DICOM +(0028,6112) US ContrastFrameAveraging 1 DICOM +(0028,6114) FL MaskSubPixelShift 2 DICOM +(0028,6120) SS TIDOffset 1 DICOM +(0028,6190) ST MaskOperationExplanation 1 DICOM +(0028,7000) SQ EquipmentAdministratorSequence 1 DICOM +(0028,7001) US NumberOfDisplaySubsystems 1 DICOM +(0028,7002) US CurrentConfigurationID 1 DICOM +(0028,7003) US DisplaySubsystemID 1 DICOM +(0028,7004) SH DisplaySubsystemName 1 DICOM +(0028,7005) LO DisplaySubsystemDescription 1 DICOM +(0028,7006) CS SystemStatus 1 DICOM +(0028,7007) LO SystemStatusComment 1 DICOM +(0028,7008) SQ TargetLuminanceCharacteristicsSequence 1 DICOM +(0028,7009) US LuminanceCharacteristicsID 1 DICOM +(0028,700A) SQ DisplaySubsystemConfigurationSequence 1 DICOM +(0028,700B) US ConfigurationID 1 DICOM +(0028,700C) SH ConfigurationName 1 DICOM +(0028,700D) LO ConfigurationDescription 1 DICOM +(0028,700E) US ReferencedTargetLuminanceCharacteristicsID 1 DICOM +(0028,700F) SQ QAResultsSequence 1 DICOM +(0028,7010) SQ DisplaySubsystemQAResultsSequence 1 DICOM +(0028,7011) SQ ConfigurationQAResultsSequence 1 DICOM +(0028,7012) SQ MeasurementEquipmentSequence 1 DICOM +(0028,7013) CS MeasurementFunctions 1-n DICOM +(0028,7014) CS MeasurementEquipmentType 1 DICOM +(0028,7015) SQ VisualEvaluationResultSequence 1 DICOM +(0028,7016) SQ DisplayCalibrationResultSequence 1 DICOM +(0028,7017) US DDLValue 1 DICOM +(0028,7018) FL CIExyWhitePoint 2 DICOM +(0028,7019) CS DisplayFunctionType 1 DICOM +(0028,701A) FL GammaValue 1 DICOM +(0028,701B) US NumberOfLuminancePoints 1 DICOM +(0028,701C) SQ LuminanceResponseSequence 1 DICOM +(0028,701D) FL TargetMinimumLuminance 1 DICOM +(0028,701E) FL TargetMaximumLuminance 1 DICOM +(0028,701F) FL LuminanceValue 1 DICOM +(0028,7020) LO LuminanceResponseDescription 1 DICOM +(0028,7021) CS WhitePointFlag 1 DICOM +(0028,7022) SQ DisplayDeviceTypeCodeSequence 1 DICOM +(0028,7023) SQ DisplaySubsystemSequence 1 DICOM +(0028,7024) SQ LuminanceResultSequence 1 DICOM +(0028,7025) CS AmbientLightValueSource 1 DICOM +(0028,7026) CS MeasuredCharacteristics 1-n DICOM +(0028,7027) SQ LuminanceUniformityResultSequence 1 DICOM +(0028,7028) SQ VisualEvaluationTestSequence 1 DICOM +(0028,7029) CS TestResult 1 DICOM +(0028,702A) LO TestResultComment 1 DICOM +(0028,702B) CS TestImageValidation 1 DICOM +(0028,702C) SQ TestPatternCodeSequence 1 DICOM +(0028,702D) SQ MeasurementPatternCodeSequence 1 DICOM +(0028,702E) SQ VisualEvaluationMethodCodeSequence 1 DICOM +(0028,7FE0) UR PixelDataProviderURL 1 DICOM +(0028,9001) UL DataPointRows 1 DICOM +(0028,9002) UL DataPointColumns 1 DICOM +(0028,9003) CS SignalDomainColumns 1 DICOM +(0028,9108) CS DataRepresentation 1 DICOM +(0028,9110) SQ PixelMeasuresSequence 1 DICOM +(0028,9132) SQ FrameVOILUTSequence 1 DICOM +(0028,9145) SQ PixelValueTransformationSequence 1 DICOM +(0028,9235) CS SignalDomainRows 1 DICOM +(0028,9411) FL DisplayFilterPercentage 1 DICOM +(0028,9415) SQ FramePixelShiftSequence 1 DICOM +(0028,9416) US SubtractionItemID 1 DICOM +(0028,9422) SQ PixelIntensityRelationshipLUTSequence 1 DICOM +(0028,9443) SQ FramePixelDataPropertiesSequence 1 DICOM +(0028,9444) CS GeometricalProperties 1 DICOM +(0028,9445) FL GeometricMaximumDistortion 1 DICOM +(0028,9446) CS ImageProcessingApplied 1-n DICOM +(0028,9454) CS MaskSelectionMode 1 DICOM +(0028,9474) CS LUTFunction 1 DICOM +(0028,9478) FL MaskVisibilityPercentage 1 DICOM +(0028,9501) SQ PixelShiftSequence 1 DICOM +(0028,9502) SQ RegionPixelShiftSequence 1 DICOM +(0028,9503) SS VerticesOfTheRegion 2-2n DICOM +(0028,9505) SQ MultiFramePresentationSequence 1 DICOM +(0028,9506) US PixelShiftFrameRange 2-2n DICOM +(0028,9507) US LUTFrameRange 2-2n DICOM +(0028,9520) DS ImageToEquipmentMappingMatrix 16 DICOM +(0028,9537) CS EquipmentCoordinateSystemIdentification 1 DICOM +(0032,1031) SQ RequestingPhysicianIdentificationSequence 1 DICOM +(0032,1032) PN RequestingPhysician 1 DICOM +(0032,1033) LO RequestingService 1 DICOM +(0032,1034) SQ RequestingServiceCodeSequence 1 DICOM +(0032,1060) LO RequestedProcedureDescription 1 DICOM +(0032,1064) SQ RequestedProcedureCodeSequence 1 DICOM +(0032,1070) LO RequestedContrastAgent 1 DICOM +(0038,0004) SQ ReferencedPatientAliasSequence 1 DICOM +(0038,0008) CS VisitStatusID 1 DICOM +(0038,0010) LO AdmissionID 1 DICOM +(0038,0014) SQ IssuerOfAdmissionIDSequence 1 DICOM +(0038,0016) LO RouteOfAdmissions 1 DICOM +(0038,0020) DA AdmittingDate 1 DICOM +(0038,0021) TM AdmittingTime 1 DICOM +(0038,0050) LO SpecialNeeds 1 DICOM +(0038,0060) LO ServiceEpisodeID 1 DICOM +(0038,0062) LO ServiceEpisodeDescription 1 DICOM +(0038,0064) SQ IssuerOfServiceEpisodeIDSequence 1 DICOM +(0038,0100) SQ PertinentDocumentsSequence 1 DICOM +(0038,0101) SQ PertinentResourcesSequence 1 DICOM +(0038,0102) LO ResourceDescription 1 DICOM +(0038,0300) LO CurrentPatientLocation 1 DICOM +(0038,0400) LO PatientInstitutionResidence 1 DICOM +(0038,0500) LO PatientState 1 DICOM +(0038,0502) SQ PatientClinicalTrialParticipationSequence 1 DICOM +(0038,4000) LT VisitComments 1 DICOM +(003A,0004) CS WaveformOriginality 1 DICOM +(003A,0005) US NumberOfWaveformChannels 1 DICOM +(003A,0010) UL NumberOfWaveformSamples 1 DICOM +(003A,001A) DS SamplingFrequency 1 DICOM +(003A,0020) SH MultiplexGroupLabel 1 DICOM +(003A,0200) SQ ChannelDefinitionSequence 1 DICOM +(003A,0202) IS WaveformChannelNumber 1 DICOM +(003A,0203) SH ChannelLabel 1 DICOM +(003A,0205) CS ChannelStatus 1-n DICOM +(003A,0208) SQ ChannelSourceSequence 1 DICOM +(003A,0209) SQ ChannelSourceModifiersSequence 1 DICOM +(003A,020A) SQ SourceWaveformSequence 1 DICOM +(003A,020C) LO ChannelDerivationDescription 1 DICOM +(003A,0210) DS ChannelSensitivity 1 DICOM +(003A,0211) SQ ChannelSensitivityUnitsSequence 1 DICOM +(003A,0212) DS ChannelSensitivityCorrectionFactor 1 DICOM +(003A,0213) DS ChannelBaseline 1 DICOM +(003A,0214) DS ChannelTimeSkew 1 DICOM +(003A,0215) DS ChannelSampleSkew 1 DICOM +(003A,0218) DS ChannelOffset 1 DICOM +(003A,021A) US WaveformBitsStored 1 DICOM +(003A,0220) DS FilterLowFrequency 1 DICOM +(003A,0221) DS FilterHighFrequency 1 DICOM +(003A,0222) DS NotchFilterFrequency 1 DICOM +(003A,0223) DS NotchFilterBandwidth 1 DICOM +(003A,0230) FL WaveformDataDisplayScale 1 DICOM +(003A,0231) US WaveformDisplayBackgroundCIELabValue 3 DICOM +(003A,0240) SQ WaveformPresentationGroupSequence 1 DICOM +(003A,0241) US PresentationGroupNumber 1 DICOM +(003A,0242) SQ ChannelDisplaySequence 1 DICOM +(003A,0244) US ChannelRecommendedDisplayCIELabValue 3 DICOM +(003A,0245) FL ChannelPosition 1 DICOM +(003A,0246) CS DisplayShadingFlag 1 DICOM +(003A,0247) FL FractionalChannelDisplayScale 1 DICOM +(003A,0248) FL AbsoluteChannelDisplayScale 1 DICOM +(003A,0300) SQ MultiplexedAudioChannelsDescriptionCodeSequence 1 DICOM +(003A,0301) IS ChannelIdentificationCode 1 DICOM +(003A,0302) CS ChannelMode 1 DICOM +(0040,0001) AE ScheduledStationAETitle 1-n DICOM +(0040,0002) DA ScheduledProcedureStepStartDate 1 DICOM +(0040,0003) TM ScheduledProcedureStepStartTime 1 DICOM +(0040,0004) DA ScheduledProcedureStepEndDate 1 DICOM +(0040,0005) TM ScheduledProcedureStepEndTime 1 DICOM +(0040,0006) PN ScheduledPerformingPhysicianName 1 DICOM +(0040,0007) LO ScheduledProcedureStepDescription 1 DICOM +(0040,0008) SQ ScheduledProtocolCodeSequence 1 DICOM +(0040,0009) SH ScheduledProcedureStepID 1 DICOM +(0040,000A) SQ StageCodeSequence 1 DICOM +(0040,000B) SQ ScheduledPerformingPhysicianIdentificationSequence 1 DICOM +(0040,0010) SH ScheduledStationName 1-n DICOM +(0040,0011) SH ScheduledProcedureStepLocation 1 DICOM +(0040,0012) LO PreMedication 1 DICOM +(0040,0020) CS ScheduledProcedureStepStatus 1 DICOM +(0040,0026) SQ OrderPlacerIdentifierSequence 1 DICOM +(0040,0027) SQ OrderFillerIdentifierSequence 1 DICOM +(0040,0031) UT LocalNamespaceEntityID 1 DICOM +(0040,0032) UT UniversalEntityID 1 DICOM +(0040,0033) CS UniversalEntityIDType 1 DICOM +(0040,0035) CS IdentifierTypeCode 1 DICOM +(0040,0036) SQ AssigningFacilitySequence 1 DICOM +(0040,0039) SQ AssigningJurisdictionCodeSequence 1 DICOM +(0040,003A) SQ AssigningAgencyOrDepartmentCodeSequence 1 DICOM +(0040,0100) SQ ScheduledProcedureStepSequence 1 DICOM +(0040,0220) SQ ReferencedNonImageCompositeSOPInstanceSequence 1 DICOM +(0040,0241) AE PerformedStationAETitle 1 DICOM +(0040,0242) SH PerformedStationName 1 DICOM +(0040,0243) SH PerformedLocation 1 DICOM +(0040,0244) DA PerformedProcedureStepStartDate 1 DICOM +(0040,0245) TM PerformedProcedureStepStartTime 1 DICOM +(0040,0250) DA PerformedProcedureStepEndDate 1 DICOM +(0040,0251) TM PerformedProcedureStepEndTime 1 DICOM +(0040,0252) CS PerformedProcedureStepStatus 1 DICOM +(0040,0253) SH PerformedProcedureStepID 1 DICOM +(0040,0254) LO PerformedProcedureStepDescription 1 DICOM +(0040,0255) LO PerformedProcedureTypeDescription 1 DICOM +(0040,0260) SQ PerformedProtocolCodeSequence 1 DICOM +(0040,0261) CS PerformedProtocolType 1 DICOM +(0040,0270) SQ ScheduledStepAttributesSequence 1 DICOM +(0040,0275) SQ RequestAttributesSequence 1 DICOM +(0040,0280) ST CommentsOnThePerformedProcedureStep 1 DICOM +(0040,0281) SQ PerformedProcedureStepDiscontinuationReasonCodeSequence 1 DICOM +(0040,0293) SQ QuantitySequence 1 DICOM +(0040,0294) DS Quantity 1 DICOM +(0040,0295) SQ MeasuringUnitsSequence 1 DICOM +(0040,0296) SQ BillingItemSequence 1 DICOM +(0040,0300) US TotalTimeOfFluoroscopy 1 DICOM +(0040,0301) US TotalNumberOfExposures 1 DICOM +(0040,0302) US EntranceDose 1 DICOM +(0040,0303) US ExposedArea 1-2 DICOM +(0040,0306) DS DistanceSourceToEntrance 1 DICOM +(0040,030E) SQ ExposureDoseSequence 1 DICOM +(0040,0310) ST CommentsOnRadiationDose 1 DICOM +(0040,0312) DS XRayOutput 1 DICOM +(0040,0314) DS HalfValueLayer 1 DICOM +(0040,0316) DS OrganDose 1 DICOM +(0040,0318) CS OrganExposed 1 DICOM +(0040,0320) SQ BillingProcedureStepSequence 1 DICOM +(0040,0321) SQ FilmConsumptionSequence 1 DICOM +(0040,0324) SQ BillingSuppliesAndDevicesSequence 1 DICOM +(0040,0340) SQ PerformedSeriesSequence 1 DICOM +(0040,0400) LT CommentsOnTheScheduledProcedureStep 1 DICOM +(0040,0440) SQ ProtocolContextSequence 1 DICOM +(0040,0441) SQ ContentItemModifierSequence 1 DICOM +(0040,0500) SQ ScheduledSpecimenSequence 1 DICOM +(0040,0512) LO ContainerIdentifier 1 DICOM +(0040,0513) SQ IssuerOfTheContainerIdentifierSequence 1 DICOM +(0040,0515) SQ AlternateContainerIdentifierSequence 1 DICOM +(0040,0518) SQ ContainerTypeCodeSequence 1 DICOM +(0040,051A) LO ContainerDescription 1 DICOM +(0040,0520) SQ ContainerComponentSequence 1 DICOM +(0040,0551) LO SpecimenIdentifier 1 DICOM +(0040,0554) UI SpecimenUID 1 DICOM +(0040,0555) SQ AcquisitionContextSequence 1 DICOM +(0040,0556) ST AcquisitionContextDescription 1 DICOM +(0040,0560) SQ SpecimenDescriptionSequence 1 DICOM +(0040,0562) SQ IssuerOfTheSpecimenIdentifierSequence 1 DICOM +(0040,059A) SQ SpecimenTypeCodeSequence 1 DICOM +(0040,0600) LO SpecimenShortDescription 1 DICOM +(0040,0602) UT SpecimenDetailedDescription 1 DICOM +(0040,0610) SQ SpecimenPreparationSequence 1 DICOM +(0040,0612) SQ SpecimenPreparationStepContentItemSequence 1 DICOM +(0040,0620) SQ SpecimenLocalizationContentItemSequence 1 DICOM +(0040,071A) SQ ImageCenterPointCoordinatesSequence 1 DICOM +(0040,072A) DS XOffsetInSlideCoordinateSystem 1 DICOM +(0040,073A) DS YOffsetInSlideCoordinateSystem 1 DICOM +(0040,074A) DS ZOffsetInSlideCoordinateSystem 1 DICOM +(0040,08EA) SQ MeasurementUnitsCodeSequence 1 DICOM +(0040,1001) SH RequestedProcedureID 1 DICOM +(0040,1002) LO ReasonForTheRequestedProcedure 1 DICOM +(0040,1003) SH RequestedProcedurePriority 1 DICOM +(0040,1004) LO PatientTransportArrangements 1 DICOM +(0040,1005) LO RequestedProcedureLocation 1 DICOM +(0040,1008) LO ConfidentialityCode 1 DICOM +(0040,1009) SH ReportingPriority 1 DICOM +(0040,100A) SQ ReasonForRequestedProcedureCodeSequence 1 DICOM +(0040,1010) PN NamesOfIntendedRecipientsOfResults 1-n DICOM +(0040,1011) SQ IntendedRecipientsOfResultsIdentificationSequence 1 DICOM +(0040,1012) SQ ReasonForPerformedProcedureCodeSequence 1 DICOM +(0040,1101) SQ PersonIdentificationCodeSequence 1 DICOM +(0040,1102) ST PersonAddress 1 DICOM +(0040,1103) LO PersonTelephoneNumbers 1-n DICOM +(0040,1104) LT PersonTelecomInformation 1 DICOM +(0040,1400) LT RequestedProcedureComments 1 DICOM +(0040,2004) DA IssueDateOfImagingServiceRequest 1 DICOM +(0040,2005) TM IssueTimeOfImagingServiceRequest 1 DICOM +(0040,2008) PN OrderEnteredBy 1 DICOM +(0040,2009) SH OrderEntererLocation 1 DICOM +(0040,2010) SH OrderCallbackPhoneNumber 1 DICOM +(0040,2011) LT OrderCallbackTelecomInformation 1 DICOM +(0040,2016) LO PlacerOrderNumberImagingServiceRequest 1 DICOM +(0040,2017) LO FillerOrderNumberImagingServiceRequest 1 DICOM +(0040,2400) LT ImagingServiceRequestComments 1 DICOM +(0040,3001) LO ConfidentialityConstraintOnPatientDataDescription 1 DICOM +(0040,4005) DT ScheduledProcedureStepStartDateTime 1 DICOM +(0040,4007) SQ PerformedProcessingApplicationsCodeSequence 1 DICOM +(0040,4009) SQ HumanPerformerCodeSequence 1 DICOM +(0040,4010) DT ScheduledProcedureStepModificationDateTime 1 DICOM +(0040,4011) DT ExpectedCompletionDateTime 1 DICOM +(0040,4018) SQ ScheduledWorkitemCodeSequence 1 DICOM +(0040,4019) SQ PerformedWorkitemCodeSequence 1 DICOM +(0040,4020) CS InputAvailabilityFlag 1 DICOM +(0040,4021) SQ InputInformationSequence 1 DICOM +(0040,4025) SQ ScheduledStationNameCodeSequence 1 DICOM +(0040,4026) SQ ScheduledStationClassCodeSequence 1 DICOM +(0040,4027) SQ ScheduledStationGeographicLocationCodeSequence 1 DICOM +(0040,4028) SQ PerformedStationNameCodeSequence 1 DICOM +(0040,4029) SQ PerformedStationClassCodeSequence 1 DICOM +(0040,4030) SQ PerformedStationGeographicLocationCodeSequence 1 DICOM +(0040,4033) SQ OutputInformationSequence 1 DICOM +(0040,4034) SQ ScheduledHumanPerformersSequence 1 DICOM +(0040,4035) SQ ActualHumanPerformersSequence 1 DICOM +(0040,4036) LO HumanPerformerOrganization 1 DICOM +(0040,4037) PN HumanPerformerName 1 DICOM +(0040,4040) CS RawDataHandling 1 DICOM +(0040,4041) CS InputReadinessState 1 DICOM +(0040,4050) DT PerformedProcedureStepStartDateTime 1 DICOM +(0040,4051) DT PerformedProcedureStepEndDateTime 1 DICOM +(0040,4052) DT ProcedureStepCancellationDateTime 1 DICOM +(0040,8302) DS EntranceDoseInmGy 1 DICOM +(0040,9092) SQ ParametricMapFrameTypeSequence 1 DICOM +(0040,9094) SQ ReferencedImageRealWorldValueMappingSequence 1 DICOM +(0040,9096) SQ RealWorldValueMappingSequence 1 DICOM +(0040,9098) SQ PixelValueMappingCodeSequence 1 DICOM +(0040,9210) SH LUTLabel 1 DICOM +(0040,9211) xs RealWorldValueLastValueMapped 1 DICOM +(0040,9212) FD RealWorldValueLUTData 1-n DICOM +(0040,9216) xs RealWorldValueFirstValueMapped 1 DICOM +(0040,9220) SQ QuantityDefinitionSequence 1 DICOM +(0040,9224) FD RealWorldValueIntercept 1 DICOM +(0040,9225) FD RealWorldValueSlope 1 DICOM +(0040,A010) CS RelationshipType 1 DICOM +(0040,A027) LO VerifyingOrganization 1 DICOM +(0040,A030) DT VerificationDateTime 1 DICOM +(0040,A032) DT ObservationDateTime 1 DICOM +(0040,A040) CS ValueType 1 DICOM +(0040,A043) SQ ConceptNameCodeSequence 1 DICOM +(0040,A050) CS ContinuityOfContent 1 DICOM +(0040,A073) SQ VerifyingObserverSequence 1 DICOM +(0040,A075) PN VerifyingObserverName 1 DICOM +(0040,A078) SQ AuthorObserverSequence 1 DICOM +(0040,A07A) SQ ParticipantSequence 1 DICOM +(0040,A07C) SQ CustodialOrganizationSequence 1 DICOM +(0040,A080) CS ParticipationType 1 DICOM +(0040,A082) DT ParticipationDateTime 1 DICOM +(0040,A084) CS ObserverType 1 DICOM +(0040,A088) SQ VerifyingObserverIdentificationCodeSequence 1 DICOM +(0040,A0B0) US ReferencedWaveformChannels 2-2n DICOM +(0040,A120) DT DateTime 1 DICOM +(0040,A121) DA Date 1 DICOM +(0040,A122) TM Time 1 DICOM +(0040,A123) PN PersonName 1 DICOM +(0040,A124) UI UID 1 DICOM +(0040,A130) CS TemporalRangeType 1 DICOM +(0040,A132) UL ReferencedSamplePositions 1-n DICOM +(0040,A136) US ReferencedFrameNumbers 1-n DICOM +(0040,A138) DS ReferencedTimeOffsets 1-n DICOM +(0040,A13A) DT ReferencedDateTime 1-n DICOM +(0040,A160) UT TextValue 1 DICOM +(0040,A161) FD FloatingPointValue 1-n DICOM +(0040,A162) SL RationalNumeratorValue 1-n DICOM +(0040,A163) UL RationalDenominatorValue 1-n DICOM +(0040,A168) SQ ConceptCodeSequence 1 DICOM +(0040,A170) SQ PurposeOfReferenceCodeSequence 1 DICOM +(0040,A171) UI ObservationUID 1 DICOM +(0040,A180) US AnnotationGroupNumber 1 DICOM +(0040,A195) SQ ModifierCodeSequence 1 DICOM +(0040,A300) SQ MeasuredValueSequence 1 DICOM +(0040,A301) SQ NumericValueQualifierCodeSequence 1 DICOM +(0040,A30A) DS NumericValue 1-n DICOM +(0040,A360) SQ PredecessorDocumentsSequence 1 DICOM +(0040,A370) SQ ReferencedRequestSequence 1 DICOM +(0040,A372) SQ PerformedProcedureCodeSequence 1 DICOM +(0040,A375) SQ CurrentRequestedProcedureEvidenceSequence 1 DICOM +(0040,A385) SQ PertinentOtherEvidenceSequence 1 DICOM +(0040,A390) SQ HL7StructuredDocumentReferenceSequence 1 DICOM +(0040,A491) CS CompletionFlag 1 DICOM +(0040,A492) LO CompletionFlagDescription 1 DICOM +(0040,A493) CS VerificationFlag 1 DICOM +(0040,A494) CS ArchiveRequested 1 DICOM +(0040,A496) CS PreliminaryFlag 1 DICOM +(0040,A504) SQ ContentTemplateSequence 1 DICOM +(0040,A525) SQ IdenticalDocumentsSequence 1 DICOM +(0040,A730) SQ ContentSequence 1 DICOM +(0040,B020) SQ WaveformAnnotationSequence 1 DICOM +(0040,DB00) CS TemplateIdentifier 1 DICOM +(0040,DB73) UL ReferencedContentItemIdentifier 1-n DICOM +(0040,E001) ST HL7InstanceIdentifier 1 DICOM +(0040,E004) DT HL7DocumentEffectiveTime 1 DICOM +(0040,E006) SQ HL7DocumentTypeCodeSequence 1 DICOM +(0040,E008) SQ DocumentClassCodeSequence 1 DICOM +(0040,E010) UR RetrieveURI 1 DICOM +(0040,E011) UI RetrieveLocationUID 1 DICOM +(0040,E020) CS TypeOfInstances 1 DICOM +(0040,E021) SQ DICOMRetrievalSequence 1 DICOM +(0040,E022) SQ DICOMMediaRetrievalSequence 1 DICOM +(0040,E023) SQ WADORetrievalSequence 1 DICOM +(0040,E024) SQ XDSRetrievalSequence 1 DICOM +(0040,E025) SQ WADORSRetrievalSequence 1 DICOM +(0040,E030) UI RepositoryUniqueID 1 DICOM +(0040,E031) UI HomeCommunityID 1 DICOM +(0042,0010) ST DocumentTitle 1 DICOM +(0042,0011) OB EncapsulatedDocument 1 DICOM +(0042,0012) LO MIMETypeOfEncapsulatedDocument 1 DICOM +(0042,0013) SQ SourceInstanceSequence 1 DICOM +(0042,0014) LO ListOfMIMETypes 1-n DICOM +(0044,0001) ST ProductPackageIdentifier 1 DICOM +(0044,0002) CS SubstanceAdministrationApproval 1 DICOM +(0044,0003) LT ApprovalStatusFurtherDescription 1 DICOM +(0044,0004) DT ApprovalStatusDateTime 1 DICOM +(0044,0007) SQ ProductTypeCodeSequence 1 DICOM +(0044,0008) LO ProductName 1-n DICOM +(0044,0009) LT ProductDescription 1 DICOM +(0044,000A) LO ProductLotIdentifier 1 DICOM +(0044,000B) DT ProductExpirationDateTime 1 DICOM +(0044,0010) DT SubstanceAdministrationDateTime 1 DICOM +(0044,0011) LO SubstanceAdministrationNotes 1 DICOM +(0044,0012) LO SubstanceAdministrationDeviceID 1 DICOM +(0044,0013) SQ ProductParameterSequence 1 DICOM +(0044,0019) SQ SubstanceAdministrationParameterSequence 1 DICOM +(0046,0012) LO LensDescription 1 DICOM +(0046,0014) SQ RightLensSequence 1 DICOM +(0046,0015) SQ LeftLensSequence 1 DICOM +(0046,0016) SQ UnspecifiedLateralityLensSequence 1 DICOM +(0046,0018) SQ CylinderSequence 1 DICOM +(0046,0028) SQ PrismSequence 1 DICOM +(0046,0030) FD HorizontalPrismPower 1 DICOM +(0046,0032) CS HorizontalPrismBase 1 DICOM +(0046,0034) FD VerticalPrismPower 1 DICOM +(0046,0036) CS VerticalPrismBase 1 DICOM +(0046,0038) CS LensSegmentType 1 DICOM +(0046,0040) FD OpticalTransmittance 1 DICOM +(0046,0042) FD ChannelWidth 1 DICOM +(0046,0044) FD PupilSize 1 DICOM +(0046,0046) FD CornealSize 1 DICOM +(0046,0050) SQ AutorefractionRightEyeSequence 1 DICOM +(0046,0052) SQ AutorefractionLeftEyeSequence 1 DICOM +(0046,0060) FD DistancePupillaryDistance 1 DICOM +(0046,0062) FD NearPupillaryDistance 1 DICOM +(0046,0063) FD IntermediatePupillaryDistance 1 DICOM +(0046,0064) FD OtherPupillaryDistance 1 DICOM +(0046,0070) SQ KeratometryRightEyeSequence 1 DICOM +(0046,0071) SQ KeratometryLeftEyeSequence 1 DICOM +(0046,0074) SQ SteepKeratometricAxisSequence 1 DICOM +(0046,0075) FD RadiusOfCurvature 1 DICOM +(0046,0076) FD KeratometricPower 1 DICOM +(0046,0077) FD KeratometricAxis 1 DICOM +(0046,0080) SQ FlatKeratometricAxisSequence 1 DICOM +(0046,0092) CS BackgroundColor 1 DICOM +(0046,0094) CS Optotype 1 DICOM +(0046,0095) CS OptotypePresentation 1 DICOM +(0046,0097) SQ SubjectiveRefractionRightEyeSequence 1 DICOM +(0046,0098) SQ SubjectiveRefractionLeftEyeSequence 1 DICOM +(0046,0100) SQ AddNearSequence 1 DICOM +(0046,0101) SQ AddIntermediateSequence 1 DICOM +(0046,0102) SQ AddOtherSequence 1 DICOM +(0046,0104) FD AddPower 1 DICOM +(0046,0106) FD ViewingDistance 1 DICOM +(0046,0121) SQ VisualAcuityTypeCodeSequence 1 DICOM +(0046,0122) SQ VisualAcuityRightEyeSequence 1 DICOM +(0046,0123) SQ VisualAcuityLeftEyeSequence 1 DICOM +(0046,0124) SQ VisualAcuityBothEyesOpenSequence 1 DICOM +(0046,0125) CS ViewingDistanceType 1 DICOM +(0046,0135) SS VisualAcuityModifiers 2 DICOM +(0046,0137) FD DecimalVisualAcuity 1 DICOM +(0046,0139) LO OptotypeDetailedDefinition 1 DICOM +(0046,0145) SQ ReferencedRefractiveMeasurementsSequence 1 DICOM +(0046,0146) FD SpherePower 1 DICOM +(0046,0147) FD CylinderPower 1 DICOM +(0046,0201) CS CornealTopographySurface 1 DICOM +(0046,0202) FL CornealVertexLocation 2 DICOM +(0046,0203) FL PupilCentroidXCoordinate 1 DICOM +(0046,0204) FL PupilCentroidYCoordinate 1 DICOM +(0046,0205) FL EquivalentPupilRadius 1 DICOM +(0046,0207) SQ CornealTopographyMapTypeCodeSequence 1 DICOM +(0046,0208) IS VerticesOfTheOutlineOfPupil 2-2n DICOM +(0046,0210) SQ CornealTopographyMappingNormalsSequence 1 DICOM +(0046,0211) SQ MaximumCornealCurvatureSequence 1 DICOM +(0046,0212) FL MaximumCornealCurvature 1 DICOM +(0046,0213) FL MaximumCornealCurvatureLocation 2 DICOM +(0046,0215) SQ MinimumKeratometricSequence 1 DICOM +(0046,0218) SQ SimulatedKeratometricCylinderSequence 1 DICOM +(0046,0220) FL AverageCornealPower 1 DICOM +(0046,0224) FL CornealISValue 1 DICOM +(0046,0227) FL AnalyzedArea 1 DICOM +(0046,0230) FL SurfaceRegularityIndex 1 DICOM +(0046,0232) FL SurfaceAsymmetryIndex 1 DICOM +(0046,0234) FL CornealEccentricityIndex 1 DICOM +(0046,0236) FL KeratoconusPredictionIndex 1 DICOM +(0046,0238) FL DecimalPotentialVisualAcuity 1 DICOM +(0046,0242) CS CornealTopographyMapQualityEvaluation 1 DICOM +(0046,0244) SQ SourceImageCornealProcessedDataSequence 1 DICOM +(0046,0247) FL CornealPointLocation 3 DICOM +(0046,0248) CS CornealPointEstimated 1 DICOM +(0046,0249) FL AxialPower 1 DICOM +(0046,0250) FL TangentialPower 1 DICOM +(0046,0251) FL RefractivePower 1 DICOM +(0046,0252) FL RelativeElevation 1 DICOM +(0046,0253) FL CornealWavefront 1 DICOM +(0048,0001) FL ImagedVolumeWidth 1 DICOM +(0048,0002) FL ImagedVolumeHeight 1 DICOM +(0048,0003) FL ImagedVolumeDepth 1 DICOM +(0048,0006) UL TotalPixelMatrixColumns 1 DICOM +(0048,0007) UL TotalPixelMatrixRows 1 DICOM +(0048,0008) SQ TotalPixelMatrixOriginSequence 1 DICOM +(0048,0010) CS SpecimenLabelInImage 1 DICOM +(0048,0011) CS FocusMethod 1 DICOM +(0048,0012) CS ExtendedDepthOfField 1 DICOM +(0048,0013) US NumberOfFocalPlanes 1 DICOM +(0048,0014) FL DistanceBetweenFocalPlanes 1 DICOM +(0048,0015) US RecommendedAbsentPixelCIELabValue 3 DICOM +(0048,0100) SQ IlluminatorTypeCodeSequence 1 DICOM +(0048,0102) DS ImageOrientationSlide 6 DICOM +(0048,0105) SQ OpticalPathSequence 1 DICOM +(0048,0106) SH OpticalPathIdentifier 1 DICOM +(0048,0107) ST OpticalPathDescription 1 DICOM +(0048,0108) SQ IlluminationColorCodeSequence 1 DICOM +(0048,0110) SQ SpecimenReferenceSequence 1 DICOM +(0048,0111) DS CondenserLensPower 1 DICOM +(0048,0112) DS ObjectiveLensPower 1 DICOM +(0048,0113) DS ObjectiveLensNumericalAperture 1 DICOM +(0048,0120) SQ PaletteColorLookupTableSequence 1 DICOM +(0048,0200) SQ ReferencedImageNavigationSequence 1 DICOM +(0048,0201) US TopLeftHandCornerOfLocalizerArea 2 DICOM +(0048,0202) US BottomRightHandCornerOfLocalizerArea 2 DICOM +(0048,0207) SQ OpticalPathIdentificationSequence 1 DICOM +(0048,021A) SQ PlanePositionSlideSequence 1 DICOM +(0048,021E) SL ColumnPositionInTotalImagePixelMatrix 1 DICOM +(0048,021F) SL RowPositionInTotalImagePixelMatrix 1 DICOM +(0048,0301) CS PixelOriginInterpretation 1 DICOM +(0050,0004) CS CalibrationImage 1 DICOM +(0050,0010) SQ DeviceSequence 1 DICOM +(0050,0012) SQ ContainerComponentTypeCodeSequence 1 DICOM +(0050,0013) FD ContainerComponentThickness 1 DICOM +(0050,0014) DS DeviceLength 1 DICOM +(0050,0015) FD ContainerComponentWidth 1 DICOM +(0050,0016) DS DeviceDiameter 1 DICOM +(0050,0017) CS DeviceDiameterUnits 1 DICOM +(0050,0018) DS DeviceVolume 1 DICOM +(0050,0019) DS InterMarkerDistance 1 DICOM +(0050,001A) CS ContainerComponentMaterial 1 DICOM +(0050,001B) LO ContainerComponentID 1 DICOM +(0050,001C) FD ContainerComponentLength 1 DICOM +(0050,001D) FD ContainerComponentDiameter 1 DICOM +(0050,001E) LO ContainerComponentDescription 1 DICOM +(0050,0020) LO DeviceDescription 1 DICOM +(0052,0001) FL ContrastBolusIngredientPercentByVolume 1 DICOM +(0052,0002) FD OCTFocalDistance 1 DICOM +(0052,0003) FD BeamSpotSize 1 DICOM +(0052,0004) FD EffectiveRefractiveIndex 1 DICOM +(0052,0006) CS OCTAcquisitionDomain 1 DICOM +(0052,0007) FD OCTOpticalCenterWavelength 1 DICOM +(0052,0008) FD AxialResolution 1 DICOM +(0052,0009) FD RangingDepth 1 DICOM +(0052,0011) FD ALineRate 1 DICOM +(0052,0012) US ALinesPerFrame 1 DICOM +(0052,0013) FD CatheterRotationalRate 1 DICOM +(0052,0014) FD ALinePixelSpacing 1 DICOM +(0052,0016) SQ ModeOfPercutaneousAccessSequence 1 DICOM +(0052,0025) SQ IntravascularOCTFrameTypeSequence 1 DICOM +(0052,0026) CS OCTZOffsetApplied 1 DICOM +(0052,0027) SQ IntravascularFrameContentSequence 1 DICOM +(0052,0028) FD IntravascularLongitudinalDistance 1 DICOM +(0052,0029) SQ IntravascularOCTFrameContentSequence 1 DICOM +(0052,0030) SS OCTZOffsetCorrection 1 DICOM +(0052,0031) CS CatheterDirectionOfRotation 1 DICOM +(0052,0033) FD SeamLineLocation 1 DICOM +(0052,0034) FD FirstALineLocation 1 DICOM +(0052,0036) US SeamLineIndex 1 DICOM +(0052,0038) US NumberOfPaddedALines 1 DICOM +(0052,0039) CS InterpolationType 1 DICOM +(0052,003A) CS RefractiveIndexApplied 1 DICOM +(0054,0010) US EnergyWindowVector 1-n DICOM +(0054,0011) US NumberOfEnergyWindows 1 DICOM +(0054,0012) SQ EnergyWindowInformationSequence 1 DICOM +(0054,0013) SQ EnergyWindowRangeSequence 1 DICOM +(0054,0014) DS EnergyWindowLowerLimit 1 DICOM +(0054,0015) DS EnergyWindowUpperLimit 1 DICOM +(0054,0016) SQ RadiopharmaceuticalInformationSequence 1 DICOM +(0054,0017) IS ResidualSyringeCounts 1 DICOM +(0054,0018) SH EnergyWindowName 1 DICOM +(0054,0020) US DetectorVector 1-n DICOM +(0054,0021) US NumberOfDetectors 1 DICOM +(0054,0022) SQ DetectorInformationSequence 1 DICOM +(0054,0030) US PhaseVector 1-n DICOM +(0054,0031) US NumberOfPhases 1 DICOM +(0054,0032) SQ PhaseInformationSequence 1 DICOM +(0054,0033) US NumberOfFramesInPhase 1 DICOM +(0054,0036) IS PhaseDelay 1 DICOM +(0054,0038) IS PauseBetweenFrames 1 DICOM +(0054,0039) CS PhaseDescription 1 DICOM +(0054,0050) US RotationVector 1-n DICOM +(0054,0051) US NumberOfRotations 1 DICOM +(0054,0052) SQ RotationInformationSequence 1 DICOM +(0054,0053) US NumberOfFramesInRotation 1 DICOM +(0054,0060) US RRIntervalVector 1-n DICOM +(0054,0061) US NumberOfRRIntervals 1 DICOM +(0054,0062) SQ GatedInformationSequence 1 DICOM +(0054,0063) SQ DataInformationSequence 1 DICOM +(0054,0070) US TimeSlotVector 1-n DICOM +(0054,0071) US NumberOfTimeSlots 1 DICOM +(0054,0072) SQ TimeSlotInformationSequence 1 DICOM +(0054,0073) DS TimeSlotTime 1 DICOM +(0054,0080) US SliceVector 1-n DICOM +(0054,0081) US NumberOfSlices 1 DICOM +(0054,0090) US AngularViewVector 1-n DICOM +(0054,0100) US TimeSliceVector 1-n DICOM +(0054,0101) US NumberOfTimeSlices 1 DICOM +(0054,0200) DS StartAngle 1 DICOM +(0054,0202) CS TypeOfDetectorMotion 1 DICOM +(0054,0210) IS TriggerVector 1-n DICOM +(0054,0211) US NumberOfTriggersInPhase 1 DICOM +(0054,0220) SQ ViewCodeSequence 1 DICOM +(0054,0222) SQ ViewModifierCodeSequence 1 DICOM +(0054,0300) SQ RadionuclideCodeSequence 1 DICOM +(0054,0302) SQ AdministrationRouteCodeSequence 1 DICOM +(0054,0304) SQ RadiopharmaceuticalCodeSequence 1 DICOM +(0054,0306) SQ CalibrationDataSequence 1 DICOM +(0054,0308) US EnergyWindowNumber 1 DICOM +(0054,0400) SH ImageID 1 DICOM +(0054,0410) SQ PatientOrientationCodeSequence 1 DICOM +(0054,0412) SQ PatientOrientationModifierCodeSequence 1 DICOM +(0054,0414) SQ PatientGantryRelationshipCodeSequence 1 DICOM +(0054,0500) CS SliceProgressionDirection 1 DICOM +(0054,0501) CS ScanProgressionDirection 1 DICOM +(0054,1000) CS SeriesType 2 DICOM +(0054,1001) CS Units 1 DICOM +(0054,1002) CS CountsSource 1 DICOM +(0054,1004) CS ReprojectionMethod 1 DICOM +(0054,1006) CS SUVType 1 DICOM +(0054,1100) CS RandomsCorrectionMethod 1 DICOM +(0054,1101) LO AttenuationCorrectionMethod 1 DICOM +(0054,1102) CS DecayCorrection 1 DICOM +(0054,1103) LO ReconstructionMethod 1 DICOM +(0054,1104) LO DetectorLinesOfResponseUsed 1 DICOM +(0054,1105) LO ScatterCorrectionMethod 1 DICOM +(0054,1200) DS AxialAcceptance 1 DICOM +(0054,1201) IS AxialMash 2 DICOM +(0054,1202) IS TransverseMash 1 DICOM +(0054,1203) DS DetectorElementSize 2 DICOM +(0054,1210) DS CoincidenceWindowWidth 1 DICOM +(0054,1220) CS SecondaryCountsType 1-n DICOM +(0054,1300) DS FrameReferenceTime 1 DICOM +(0054,1310) IS PrimaryPromptsCountsAccumulated 1 DICOM +(0054,1311) IS SecondaryCountsAccumulated 1-n DICOM +(0054,1320) DS SliceSensitivityFactor 1 DICOM +(0054,1321) DS DecayFactor 1 DICOM +(0054,1322) DS DoseCalibrationFactor 1 DICOM +(0054,1323) DS ScatterFractionFactor 1 DICOM +(0054,1324) DS DeadTimeFactor 1 DICOM +(0054,1330) US ImageIndex 1 DICOM +(0060,3000) SQ HistogramSequence 1 DICOM +(0060,3002) US HistogramNumberOfBins 1 DICOM +(0060,3004) xs HistogramFirstBinValue 1 DICOM +(0060,3006) xs HistogramLastBinValue 1 DICOM +(0060,3008) US HistogramBinWidth 1 DICOM +(0060,3010) LO HistogramExplanation 1 DICOM +(0060,3020) UL HistogramData 1-n DICOM +(0062,0001) CS SegmentationType 1 DICOM +(0062,0002) SQ SegmentSequence 1 DICOM +(0062,0003) SQ SegmentedPropertyCategoryCodeSequence 1 DICOM +(0062,0004) US SegmentNumber 1 DICOM +(0062,0005) LO SegmentLabel 1 DICOM +(0062,0006) ST SegmentDescription 1 DICOM +(0062,0008) CS SegmentAlgorithmType 1 DICOM +(0062,0009) LO SegmentAlgorithmName 1 DICOM +(0062,000A) SQ SegmentIdentificationSequence 1 DICOM +(0062,000B) US ReferencedSegmentNumber 1-n DICOM +(0062,000C) US RecommendedDisplayGrayscaleValue 1 DICOM +(0062,000D) US RecommendedDisplayCIELabValue 3 DICOM +(0062,000E) US MaximumFractionalValue 1 DICOM +(0062,000F) SQ SegmentedPropertyTypeCodeSequence 1 DICOM +(0062,0010) CS SegmentationFractionalType 1 DICOM +(0062,0011) SQ SegmentedPropertyTypeModifierCodeSequence 1 DICOM +(0062,0012) SQ UsedSegmentsSequence 1 DICOM +(0064,0002) SQ DeformableRegistrationSequence 1 DICOM +(0064,0003) UI SourceFrameOfReferenceUID 1 DICOM +(0064,0005) SQ DeformableRegistrationGridSequence 1 DICOM +(0064,0007) UL GridDimensions 3 DICOM +(0064,0008) FD GridResolution 3 DICOM +(0064,0009) OF VectorGridData 1 DICOM +(0064,000F) SQ PreDeformationMatrixRegistrationSequence 1 DICOM +(0064,0010) SQ PostDeformationMatrixRegistrationSequence 1 DICOM +(0066,0001) UL NumberOfSurfaces 1 DICOM +(0066,0002) SQ SurfaceSequence 1 DICOM +(0066,0003) UL SurfaceNumber 1 DICOM +(0066,0004) LT SurfaceComments 1 DICOM +(0066,0009) CS SurfaceProcessing 1 DICOM +(0066,000A) FL SurfaceProcessingRatio 1 DICOM +(0066,000B) LO SurfaceProcessingDescription 1 DICOM +(0066,000C) FL RecommendedPresentationOpacity 1 DICOM +(0066,000D) CS RecommendedPresentationType 1 DICOM +(0066,000E) CS FiniteVolume 1 DICOM +(0066,0010) CS Manifold 1 DICOM +(0066,0011) SQ SurfacePointsSequence 1 DICOM +(0066,0012) SQ SurfacePointsNormalsSequence 1 DICOM +(0066,0013) SQ SurfaceMeshPrimitivesSequence 1 DICOM +(0066,0015) UL NumberOfSurfacePoints 1 DICOM +(0066,0016) OF PointCoordinatesData 1 DICOM +(0066,0017) FL PointPositionAccuracy 3 DICOM +(0066,0018) FL MeanPointDistance 1 DICOM +(0066,0019) FL MaximumPointDistance 1 DICOM +(0066,001A) FL PointsBoundingBoxCoordinates 6 DICOM +(0066,001B) FL AxisOfRotation 3 DICOM +(0066,001C) FL CenterOfRotation 3 DICOM +(0066,001E) UL NumberOfVectors 1 DICOM +(0066,001F) US VectorDimensionality 1 DICOM +(0066,0020) FL VectorAccuracy 1-n DICOM +(0066,0021) OF VectorCoordinateData 1 DICOM +(0066,0023) OW TrianglePointIndexList 1 DICOM +(0066,0024) OW EdgePointIndexList 1 DICOM +(0066,0025) OW VertexPointIndexList 1 DICOM +(0066,0026) SQ TriangleStripSequence 1 DICOM +(0066,0027) SQ TriangleFanSequence 1 DICOM +(0066,0028) SQ LineSequence 1 DICOM +(0066,0029) OW PrimitivePointIndexList 1 DICOM +(0066,002A) UL SurfaceCount 1 DICOM +(0066,002B) SQ ReferencedSurfaceSequence 1 DICOM +(0066,002C) UL ReferencedSurfaceNumber 1 DICOM +(0066,002D) SQ SegmentSurfaceGenerationAlgorithmIdentificationSequence 1 DICOM +(0066,002E) SQ SegmentSurfaceSourceInstanceSequence 1 DICOM +(0066,002F) SQ AlgorithmFamilyCodeSequence 1 DICOM +(0066,0030) SQ AlgorithmNameCodeSequence 1 DICOM +(0066,0031) LO AlgorithmVersion 1 DICOM +(0066,0032) LT AlgorithmParameters 1 DICOM +(0066,0034) SQ FacetSequence 1 DICOM +(0066,0035) SQ SurfaceProcessingAlgorithmIdentificationSequence 1 DICOM +(0066,0036) LO AlgorithmName 1 DICOM +(0066,0037) FL RecommendedPointRadius 1 DICOM +(0066,0038) FL RecommendedLineThickness 1 DICOM +(0066,0040) UL LongPrimitivePointIndexList 1-n DICOM +(0066,0041) UL LongTrianglePointIndexList 3-3n DICOM +(0066,0042) UL LongEdgePointIndexList 2-2n DICOM +(0066,0043) UL LongVertexPointIndexList 1-n DICOM +(0068,6210) LO ImplantSize 1 DICOM +(0068,6221) LO ImplantTemplateVersion 1 DICOM +(0068,6222) SQ ReplacedImplantTemplateSequence 1 DICOM +(0068,6223) CS ImplantType 1 DICOM +(0068,6224) SQ DerivationImplantTemplateSequence 1 DICOM +(0068,6225) SQ OriginalImplantTemplateSequence 1 DICOM +(0068,6226) DT EffectiveDateTime 1 DICOM +(0068,6230) SQ ImplantTargetAnatomySequence 1 DICOM +(0068,6260) SQ InformationFromManufacturerSequence 1 DICOM +(0068,6265) SQ NotificationFromManufacturerSequence 1 DICOM +(0068,6270) DT InformationIssueDateTime 1 DICOM +(0068,6280) ST InformationSummary 1 DICOM +(0068,62A0) SQ ImplantRegulatoryDisapprovalCodeSequence 1 DICOM +(0068,62A5) FD OverallTemplateSpatialTolerance 1 DICOM +(0068,62C0) SQ HPGLDocumentSequence 1 DICOM +(0068,62D0) US HPGLDocumentID 1 DICOM +(0068,62D5) LO HPGLDocumentLabel 1 DICOM +(0068,62E0) SQ ViewOrientationCodeSequence 1 DICOM +(0068,62F0) FD ViewOrientationModifier 9 DICOM +(0068,62F2) FD HPGLDocumentScaling 1 DICOM +(0068,6300) OB HPGLDocument 1 DICOM +(0068,6310) US HPGLContourPenNumber 1 DICOM +(0068,6320) SQ HPGLPenSequence 1 DICOM +(0068,6330) US HPGLPenNumber 1 DICOM +(0068,6340) LO HPGLPenLabel 1 DICOM +(0068,6345) ST HPGLPenDescription 1 DICOM +(0068,6346) FD RecommendedRotationPoint 2 DICOM +(0068,6347) FD BoundingRectangle 4 DICOM +(0068,6350) US ImplantTemplate3DModelSurfaceNumber 1-n DICOM +(0068,6360) SQ SurfaceModelDescriptionSequence 1 DICOM +(0068,6380) LO SurfaceModelLabel 1 DICOM +(0068,6390) FD SurfaceModelScalingFactor 1 DICOM +(0068,63A0) SQ MaterialsCodeSequence 1 DICOM +(0068,63A4) SQ CoatingMaterialsCodeSequence 1 DICOM +(0068,63A8) SQ ImplantTypeCodeSequence 1 DICOM +(0068,63AC) SQ FixationMethodCodeSequence 1 DICOM +(0068,63B0) SQ MatingFeatureSetsSequence 1 DICOM +(0068,63C0) US MatingFeatureSetID 1 DICOM +(0068,63D0) LO MatingFeatureSetLabel 1 DICOM +(0068,63E0) SQ MatingFeatureSequence 1 DICOM +(0068,63F0) US MatingFeatureID 1 DICOM +(0068,6400) SQ MatingFeatureDegreeOfFreedomSequence 1 DICOM +(0068,6410) US DegreeOfFreedomID 1 DICOM +(0068,6420) CS DegreeOfFreedomType 1 DICOM +(0068,6430) SQ TwoDMatingFeatureCoordinatesSequence 1 DICOM +(0068,6440) US ReferencedHPGLDocumentID 1 DICOM +(0068,6450) FD TwoDMatingPoint 2 DICOM +(0068,6460) FD TwoDMatingAxes 4 DICOM +(0068,6470) SQ TwoDDegreeOfFreedomSequence 1 DICOM +(0068,6490) FD ThreeDDegreeOfFreedomAxis 3 DICOM +(0068,64A0) FD RangeOfFreedom 2 DICOM +(0068,64C0) FD ThreeDMatingPoint 3 DICOM +(0068,64D0) FD ThreeDMatingAxes 9 DICOM +(0068,64F0) FD TwoDDegreeOfFreedomAxis 3 DICOM +(0068,6500) SQ PlanningLandmarkPointSequence 1 DICOM +(0068,6510) SQ PlanningLandmarkLineSequence 1 DICOM +(0068,6520) SQ PlanningLandmarkPlaneSequence 1 DICOM +(0068,6530) US PlanningLandmarkID 1 DICOM +(0068,6540) LO PlanningLandmarkDescription 1 DICOM +(0068,6545) SQ PlanningLandmarkIdentificationCodeSequence 1 DICOM +(0068,6550) SQ TwoDPointCoordinatesSequence 1 DICOM +(0068,6560) FD TwoDPointCoordinates 2 DICOM +(0068,6590) FD ThreeDPointCoordinates 3 DICOM +(0068,65A0) SQ TwoDLineCoordinatesSequence 1 DICOM +(0068,65B0) FD TwoDLineCoordinates 4 DICOM +(0068,65D0) FD ThreeDLineCoordinates 6 DICOM +(0068,65E0) SQ TwoDPlaneCoordinatesSequence 1 DICOM +(0068,65F0) FD TwoDPlaneIntersection 4 DICOM +(0068,6610) FD ThreeDPlaneOrigin 3 DICOM +(0068,6620) FD ThreeDPlaneNormal 3 DICOM +(0070,0001) SQ GraphicAnnotationSequence 1 DICOM +(0070,0002) CS GraphicLayer 1 DICOM +(0070,0003) CS BoundingBoxAnnotationUnits 1 DICOM +(0070,0004) CS AnchorPointAnnotationUnits 1 DICOM +(0070,0005) CS GraphicAnnotationUnits 1 DICOM +(0070,0006) ST UnformattedTextValue 1 DICOM +(0070,0008) SQ TextObjectSequence 1 DICOM +(0070,0009) SQ GraphicObjectSequence 1 DICOM +(0070,0010) FL BoundingBoxTopLeftHandCorner 2 DICOM +(0070,0011) FL BoundingBoxBottomRightHandCorner 2 DICOM +(0070,0012) CS BoundingBoxTextHorizontalJustification 1 DICOM +(0070,0014) FL AnchorPoint 2 DICOM +(0070,0015) CS AnchorPointVisibility 1 DICOM +(0070,0020) US GraphicDimensions 1 DICOM +(0070,0021) US NumberOfGraphicPoints 1 DICOM +(0070,0022) FL GraphicData 2-n DICOM +(0070,0023) CS GraphicType 1 DICOM +(0070,0024) CS GraphicFilled 1 DICOM +(0070,0041) CS ImageHorizontalFlip 1 DICOM +(0070,0042) US ImageRotation 1 DICOM +(0070,0052) SL DisplayedAreaTopLeftHandCorner 2 DICOM +(0070,0053) SL DisplayedAreaBottomRightHandCorner 2 DICOM +(0070,005A) SQ DisplayedAreaSelectionSequence 1 DICOM +(0070,0060) SQ GraphicLayerSequence 1 DICOM +(0070,0062) IS GraphicLayerOrder 1 DICOM +(0070,0066) US GraphicLayerRecommendedDisplayGrayscaleValue 1 DICOM +(0070,0068) LO GraphicLayerDescription 1 DICOM +(0070,0080) CS ContentLabel 1 DICOM +(0070,0081) LO ContentDescription 1 DICOM +(0070,0082) DA PresentationCreationDate 1 DICOM +(0070,0083) TM PresentationCreationTime 1 DICOM +(0070,0084) PN ContentCreatorName 1 DICOM +(0070,0086) SQ ContentCreatorIdentificationCodeSequence 1 DICOM +(0070,0087) SQ AlternateContentDescriptionSequence 1 DICOM +(0070,0100) CS PresentationSizeMode 1 DICOM +(0070,0101) DS PresentationPixelSpacing 2 DICOM +(0070,0102) IS PresentationPixelAspectRatio 2 DICOM +(0070,0103) FL PresentationPixelMagnificationRatio 1 DICOM +(0070,0207) LO GraphicGroupLabel 1 DICOM +(0070,0208) ST GraphicGroupDescription 1 DICOM +(0070,0209) SQ CompoundGraphicSequence 1 DICOM +(0070,0226) UL CompoundGraphicInstanceID 1 DICOM +(0070,0227) LO FontName 1 DICOM +(0070,0228) CS FontNameType 1 DICOM +(0070,0229) LO CSSFontName 1 DICOM +(0070,0230) FD RotationAngle 1 DICOM +(0070,0231) SQ TextStyleSequence 1 DICOM +(0070,0232) SQ LineStyleSequence 1 DICOM +(0070,0233) SQ FillStyleSequence 1 DICOM +(0070,0234) SQ GraphicGroupSequence 1 DICOM +(0070,0241) US TextColorCIELabValue 3 DICOM +(0070,0242) CS HorizontalAlignment 1 DICOM +(0070,0243) CS VerticalAlignment 1 DICOM +(0070,0244) CS ShadowStyle 1 DICOM +(0070,0245) FL ShadowOffsetX 1 DICOM +(0070,0246) FL ShadowOffsetY 1 DICOM +(0070,0247) US ShadowColorCIELabValue 3 DICOM +(0070,0248) CS Underlined 1 DICOM +(0070,0249) CS Bold 1 DICOM +(0070,0250) CS Italic 1 DICOM +(0070,0251) US PatternOnColorCIELabValue 3 DICOM +(0070,0252) US PatternOffColorCIELabValue 3 DICOM +(0070,0253) FL LineThickness 1 DICOM +(0070,0254) CS LineDashingStyle 1 DICOM +(0070,0255) UL LinePattern 1 DICOM +(0070,0256) OB FillPattern 1 DICOM +(0070,0257) CS FillMode 1 DICOM +(0070,0258) FL ShadowOpacity 1 DICOM +(0070,0261) FL GapLength 1 DICOM +(0070,0262) FL DiameterOfVisibility 1 DICOM +(0070,0273) FL RotationPoint 2 DICOM +(0070,0274) CS TickAlignment 1 DICOM +(0070,0278) CS ShowTickLabel 1 DICOM +(0070,0279) CS TickLabelAlignment 1 DICOM +(0070,0282) CS CompoundGraphicUnits 1 DICOM +(0070,0284) FL PatternOnOpacity 1 DICOM +(0070,0285) FL PatternOffOpacity 1 DICOM +(0070,0287) SQ MajorTicksSequence 1 DICOM +(0070,0288) FL TickPosition 1 DICOM +(0070,0289) SH TickLabel 1 DICOM +(0070,0294) CS CompoundGraphicType 1 DICOM +(0070,0295) UL GraphicGroupID 1 DICOM +(0070,0306) CS ShapeType 1 DICOM +(0070,0308) SQ RegistrationSequence 1 DICOM +(0070,0309) SQ MatrixRegistrationSequence 1 DICOM +(0070,030A) SQ MatrixSequence 1 DICOM +(0070,030C) CS FrameOfReferenceTransformationMatrixType 1 DICOM +(0070,030D) SQ RegistrationTypeCodeSequence 1 DICOM +(0070,030F) ST FiducialDescription 1 DICOM +(0070,0310) SH FiducialIdentifier 1 DICOM +(0070,0311) SQ FiducialIdentifierCodeSequence 1 DICOM +(0070,0312) FD ContourUncertaintyRadius 1 DICOM +(0070,0314) SQ UsedFiducialsSequence 1 DICOM +(0070,0318) SQ GraphicCoordinatesDataSequence 1 DICOM +(0070,031A) UI FiducialUID 1 DICOM +(0070,031C) SQ FiducialSetSequence 1 DICOM +(0070,031E) SQ FiducialSequence 1 DICOM +(0070,0401) US GraphicLayerRecommendedDisplayCIELabValue 3 DICOM +(0070,0402) SQ BlendingSequence 1 DICOM +(0070,0403) FL RelativeOpacity 1 DICOM +(0070,0404) SQ ReferencedSpatialRegistrationSequence 1 DICOM +(0070,0405) CS BlendingPosition 1 DICOM +(0072,0002) SH HangingProtocolName 1 DICOM +(0072,0004) LO HangingProtocolDescription 1 DICOM +(0072,0006) CS HangingProtocolLevel 1 DICOM +(0072,0008) LO HangingProtocolCreator 1 DICOM +(0072,000A) DT HangingProtocolCreationDateTime 1 DICOM +(0072,000C) SQ HangingProtocolDefinitionSequence 1 DICOM +(0072,000E) SQ HangingProtocolUserIdentificationCodeSequence 1 DICOM +(0072,0010) LO HangingProtocolUserGroupName 1 DICOM +(0072,0012) SQ SourceHangingProtocolSequence 1 DICOM +(0072,0014) US NumberOfPriorsReferenced 1 DICOM +(0072,0020) SQ ImageSetsSequence 1 DICOM +(0072,0022) SQ ImageSetSelectorSequence 1 DICOM +(0072,0024) CS ImageSetSelectorUsageFlag 1 DICOM +(0072,0026) AT SelectorAttribute 1 DICOM +(0072,0028) US SelectorValueNumber 1 DICOM +(0072,0030) SQ TimeBasedImageSetsSequence 1 DICOM +(0072,0032) US ImageSetNumber 1 DICOM +(0072,0034) CS ImageSetSelectorCategory 1 DICOM +(0072,0038) US RelativeTime 2 DICOM +(0072,003A) CS RelativeTimeUnits 1 DICOM +(0072,003C) SS AbstractPriorValue 2 DICOM +(0072,003E) SQ AbstractPriorCodeSequence 1 DICOM +(0072,0040) LO ImageSetLabel 1 DICOM +(0072,0050) CS SelectorAttributeVR 1 DICOM +(0072,0052) AT SelectorSequencePointer 1-n DICOM +(0072,0054) LO SelectorSequencePointerPrivateCreator 1-n DICOM +(0072,0056) LO SelectorAttributePrivateCreator 1 DICOM +(0072,0060) AT SelectorATValue 1-n DICOM +(0072,0062) CS SelectorCSValue 1-n DICOM +(0072,0064) IS SelectorISValue 1-n DICOM +(0072,0066) LO SelectorLOValue 1-n DICOM +(0072,0068) LT SelectorLTValue 1 DICOM +(0072,006A) PN SelectorPNValue 1-n DICOM +(0072,006C) SH SelectorSHValue 1-n DICOM +(0072,006E) ST SelectorSTValue 1 DICOM +(0072,0070) UT SelectorUTValue 1 DICOM +(0072,0072) DS SelectorDSValue 1-n DICOM +(0072,0074) FD SelectorFDValue 1-n DICOM +(0072,0076) FL SelectorFLValue 1-n DICOM +(0072,0078) UL SelectorULValue 1-n DICOM +(0072,007A) US SelectorUSValue 1-n DICOM +(0072,007C) SL SelectorSLValue 1-n DICOM +(0072,007E) SS SelectorSSValue 1-n DICOM +(0072,007F) UI SelectorUIValue 1-n DICOM +(0072,0080) SQ SelectorCodeSequenceValue 1 DICOM +(0072,0100) US NumberOfScreens 1 DICOM +(0072,0102) SQ NominalScreenDefinitionSequence 1 DICOM +(0072,0104) US NumberOfVerticalPixels 1 DICOM +(0072,0106) US NumberOfHorizontalPixels 1 DICOM +(0072,0108) FD DisplayEnvironmentSpatialPosition 4 DICOM +(0072,010A) US ScreenMinimumGrayscaleBitDepth 1 DICOM +(0072,010C) US ScreenMinimumColorBitDepth 1 DICOM +(0072,010E) US ApplicationMaximumRepaintTime 1 DICOM +(0072,0200) SQ DisplaySetsSequence 1 DICOM +(0072,0202) US DisplaySetNumber 1 DICOM +(0072,0203) LO DisplaySetLabel 1 DICOM +(0072,0204) US DisplaySetPresentationGroup 1 DICOM +(0072,0206) LO DisplaySetPresentationGroupDescription 1 DICOM +(0072,0208) CS PartialDataDisplayHandling 1 DICOM +(0072,0210) SQ SynchronizedScrollingSequence 1 DICOM +(0072,0212) US DisplaySetScrollingGroup 2-n DICOM +(0072,0214) SQ NavigationIndicatorSequence 1 DICOM +(0072,0216) US NavigationDisplaySet 1 DICOM +(0072,0218) US ReferenceDisplaySets 1-n DICOM +(0072,0300) SQ ImageBoxesSequence 1 DICOM +(0072,0302) US ImageBoxNumber 1 DICOM +(0072,0304) CS ImageBoxLayoutType 1 DICOM +(0072,0306) US ImageBoxTileHorizontalDimension 1 DICOM +(0072,0308) US ImageBoxTileVerticalDimension 1 DICOM +(0072,0310) CS ImageBoxScrollDirection 1 DICOM +(0072,0312) CS ImageBoxSmallScrollType 1 DICOM +(0072,0314) US ImageBoxSmallScrollAmount 1 DICOM +(0072,0316) CS ImageBoxLargeScrollType 1 DICOM +(0072,0318) US ImageBoxLargeScrollAmount 1 DICOM +(0072,0320) US ImageBoxOverlapPriority 1 DICOM +(0072,0330) FD CineRelativeToRealTime 1 DICOM +(0072,0400) SQ FilterOperationsSequence 1 DICOM +(0072,0402) CS FilterByCategory 1 DICOM +(0072,0404) CS FilterByAttributePresence 1 DICOM +(0072,0406) CS FilterByOperator 1 DICOM +(0072,0420) US StructuredDisplayBackgroundCIELabValue 3 DICOM +(0072,0421) US EmptyImageBoxCIELabValue 3 DICOM +(0072,0422) SQ StructuredDisplayImageBoxSequence 1 DICOM +(0072,0424) SQ StructuredDisplayTextBoxSequence 1 DICOM +(0072,0427) SQ ReferencedFirstFrameSequence 1 DICOM +(0072,0430) SQ ImageBoxSynchronizationSequence 1 DICOM +(0072,0432) US SynchronizedImageBoxList 2-n DICOM +(0072,0434) CS TypeOfSynchronization 1 DICOM +(0072,0500) CS BlendingOperationType 1 DICOM +(0072,0510) CS ReformattingOperationType 1 DICOM +(0072,0512) FD ReformattingThickness 1 DICOM +(0072,0514) FD ReformattingInterval 1 DICOM +(0072,0516) CS ReformattingOperationInitialViewDirection 1 DICOM +(0072,0520) CS ThreeDRenderingType 1-n DICOM +(0072,0600) SQ SortingOperationsSequence 1 DICOM +(0072,0602) CS SortByCategory 1 DICOM +(0072,0604) CS SortingDirection 1 DICOM +(0072,0700) CS DisplaySetPatientOrientation 2 DICOM +(0072,0702) CS VOIType 1 DICOM +(0072,0704) CS PseudoColorType 1 DICOM +(0072,0705) SQ PseudoColorPaletteInstanceReferenceSequence 1 DICOM +(0072,0706) CS ShowGrayscaleInverted 1 DICOM +(0072,0710) CS ShowImageTrueSizeFlag 1 DICOM +(0072,0712) CS ShowGraphicAnnotationFlag 1 DICOM +(0072,0714) CS ShowPatientDemographicsFlag 1 DICOM +(0072,0716) CS ShowAcquisitionTechniquesFlag 1 DICOM +(0072,0717) CS DisplaySetHorizontalJustification 1 DICOM +(0072,0718) CS DisplaySetVerticalJustification 1 DICOM +(0074,0120) FD ContinuationStartMeterset 1 DICOM +(0074,0121) FD ContinuationEndMeterset 1 DICOM +(0074,1000) CS ProcedureStepState 1 DICOM +(0074,1002) SQ ProcedureStepProgressInformationSequence 1 DICOM +(0074,1004) DS ProcedureStepProgress 1 DICOM +(0074,1006) ST ProcedureStepProgressDescription 1 DICOM +(0074,1008) SQ ProcedureStepCommunicationsURISequence 1 DICOM +(0074,100A) UR ContactURI 1 DICOM +(0074,100C) LO ContactDisplayName 1 DICOM +(0074,100E) SQ ProcedureStepDiscontinuationReasonCodeSequence 1 DICOM +(0074,1020) SQ BeamTaskSequence 1 DICOM +(0074,1022) CS BeamTaskType 1 DICOM +(0074,1025) CS AutosequenceFlag 1 DICOM +(0074,1026) FD TableTopVerticalAdjustedPosition 1 DICOM +(0074,1027) FD TableTopLongitudinalAdjustedPosition 1 DICOM +(0074,1028) FD TableTopLateralAdjustedPosition 1 DICOM +(0074,102A) FD PatientSupportAdjustedAngle 1 DICOM +(0074,102B) FD TableTopEccentricAdjustedAngle 1 DICOM +(0074,102C) FD TableTopPitchAdjustedAngle 1 DICOM +(0074,102D) FD TableTopRollAdjustedAngle 1 DICOM +(0074,1030) SQ DeliveryVerificationImageSequence 1 DICOM +(0074,1032) CS VerificationImageTiming 1 DICOM +(0074,1034) CS DoubleExposureFlag 1 DICOM +(0074,1036) CS DoubleExposureOrdering 1 DICOM +(0074,1040) SQ RelatedReferenceRTImageSequence 1 DICOM +(0074,1042) SQ GeneralMachineVerificationSequence 1 DICOM +(0074,1044) SQ ConventionalMachineVerificationSequence 1 DICOM +(0074,1046) SQ IonMachineVerificationSequence 1 DICOM +(0074,1048) SQ FailedAttributesSequence 1 DICOM +(0074,104A) SQ OverriddenAttributesSequence 1 DICOM +(0074,104C) SQ ConventionalControlPointVerificationSequence 1 DICOM +(0074,104E) SQ IonControlPointVerificationSequence 1 DICOM +(0074,1050) SQ AttributeOccurrenceSequence 1 DICOM +(0074,1052) AT AttributeOccurrencePointer 1 DICOM +(0074,1054) UL AttributeItemSelector 1 DICOM +(0074,1056) LO AttributeOccurrencePrivateCreator 1 DICOM +(0074,1057) IS SelectorSequencePointerItems 1-n DICOM +(0074,1200) CS ScheduledProcedureStepPriority 1 DICOM +(0074,1202) LO WorklistLabel 1 DICOM +(0074,1204) LO ProcedureStepLabel 1 DICOM +(0074,1210) SQ ScheduledProcessingParametersSequence 1 DICOM +(0074,1212) SQ PerformedProcessingParametersSequence 1 DICOM +(0074,1216) SQ UnifiedProcedureStepPerformedProcedureSequence 1 DICOM +(0074,1224) SQ ReplacedProcedureStepSequence 1 DICOM +(0074,1230) LO DeletionLock 1 DICOM +(0074,1234) AE ReceivingAE 1 DICOM +(0074,1236) AE RequestingAE 1 DICOM +(0074,1238) LT ReasonForCancellation 1 DICOM +(0074,1242) CS SCPStatus 1 DICOM +(0074,1244) CS SubscriptionListStatus 1 DICOM +(0074,1246) CS UnifiedProcedureStepListStatus 1 DICOM +(0074,1324) UL BeamOrderIndex 1 DICOM +(0074,1338) FD DoubleExposureMeterset 1 DICOM +(0074,133A) FD DoubleExposureFieldDelta 4 DICOM +(0076,0001) LO ImplantAssemblyTemplateName 1 DICOM +(0076,0003) LO ImplantAssemblyTemplateIssuer 1 DICOM +(0076,0006) LO ImplantAssemblyTemplateVersion 1 DICOM +(0076,0008) SQ ReplacedImplantAssemblyTemplateSequence 1 DICOM +(0076,000A) CS ImplantAssemblyTemplateType 1 DICOM +(0076,000C) SQ OriginalImplantAssemblyTemplateSequence 1 DICOM +(0076,000E) SQ DerivationImplantAssemblyTemplateSequence 1 DICOM +(0076,0010) SQ ImplantAssemblyTemplateTargetAnatomySequence 1 DICOM +(0076,0020) SQ ProcedureTypeCodeSequence 1 DICOM +(0076,0030) LO SurgicalTechnique 1 DICOM +(0076,0032) SQ ComponentTypesSequence 1 DICOM +(0076,0034) CS ComponentTypeCodeSequence 1 DICOM +(0076,0036) CS ExclusiveComponentType 1 DICOM +(0076,0038) CS MandatoryComponentType 1 DICOM +(0076,0040) SQ ComponentSequence 1 DICOM +(0076,0055) US ComponentID 1 DICOM +(0076,0060) SQ ComponentAssemblySequence 1 DICOM +(0076,0070) US Component1ReferencedID 1 DICOM +(0076,0080) US Component1ReferencedMatingFeatureSetID 1 DICOM +(0076,0090) US Component1ReferencedMatingFeatureID 1 DICOM +(0076,00A0) US Component2ReferencedID 1 DICOM +(0076,00B0) US Component2ReferencedMatingFeatureSetID 1 DICOM +(0076,00C0) US Component2ReferencedMatingFeatureID 1 DICOM +(0078,0001) LO ImplantTemplateGroupName 1 DICOM +(0078,0010) ST ImplantTemplateGroupDescription 1 DICOM +(0078,0020) LO ImplantTemplateGroupIssuer 1 DICOM +(0078,0024) LO ImplantTemplateGroupVersion 1 DICOM +(0078,0026) SQ ReplacedImplantTemplateGroupSequence 1 DICOM +(0078,0028) SQ ImplantTemplateGroupTargetAnatomySequence 1 DICOM +(0078,002A) SQ ImplantTemplateGroupMembersSequence 1 DICOM +(0078,002E) US ImplantTemplateGroupMemberID 1 DICOM +(0078,0050) FD ThreeDImplantTemplateGroupMemberMatchingPoint 3 DICOM +(0078,0060) FD ThreeDImplantTemplateGroupMemberMatchingAxes 9 DICOM +(0078,0070) SQ ImplantTemplateGroupMemberMatching2DCoordinatesSequence 1 DICOM +(0078,0090) FD TwoDImplantTemplateGroupMemberMatchingPoint 2 DICOM +(0078,00A0) FD TwoDImplantTemplateGroupMemberMatchingAxes 4 DICOM +(0078,00B0) SQ ImplantTemplateGroupVariationDimensionSequence 1 DICOM +(0078,00B2) LO ImplantTemplateGroupVariationDimensionName 1 DICOM +(0078,00B4) SQ ImplantTemplateGroupVariationDimensionRankSequence 1 DICOM +(0078,00B6) US ReferencedImplantTemplateGroupMemberID 1 DICOM +(0078,00B8) US ImplantTemplateGroupVariationDimensionRank 1 DICOM +(0080,0001) SQ SurfaceScanAcquisitionTypeCodeSequence 1 DICOM +(0080,0002) SQ SurfaceScanModeCodeSequence 1 DICOM +(0080,0003) SQ RegistrationMethodCodeSequence 1 DICOM +(0080,0004) FD ShotDurationTime 1 DICOM +(0080,0005) FD ShotOffsetTime 1 DICOM +(0080,0006) US SurfacePointPresentationValueData 1-n DICOM +(0080,0007) US SurfacePointColorCIELabValueData 3-3n DICOM +(0080,0008) SQ UVMappingSequence 1 DICOM +(0080,0009) SH TextureLabel 1 DICOM +(0080,0010) OF UValueData 1-n DICOM +(0080,0011) OF VValueData 1-n DICOM +(0080,0012) SQ ReferencedTextureSequence 1 DICOM +(0080,0013) SQ ReferencedSurfaceDataSequence 1 DICOM +(0088,0130) SH StorageMediaFileSetID 1 DICOM +(0088,0140) UI StorageMediaFileSetUID 1 DICOM +(0088,0200) SQ IconImageSequence 1 DICOM +(0100,0410) CS SOPInstanceStatus 1 DICOM +(0100,0420) DT SOPAuthorizationDateTime 1 DICOM +(0100,0424) LT SOPAuthorizationComment 1 DICOM +(0100,0426) LO AuthorizationEquipmentCertificationNumber 1 DICOM +(0400,0005) US MACIDNumber 1 DICOM +(0400,0010) UI MACCalculationTransferSyntaxUID 1 DICOM +(0400,0015) CS MACAlgorithm 1 DICOM +(0400,0020) AT DataElementsSigned 1-n DICOM +(0400,0100) UI DigitalSignatureUID 1 DICOM +(0400,0105) DT DigitalSignatureDateTime 1 DICOM +(0400,0110) CS CertificateType 1 DICOM +(0400,0115) OB CertificateOfSigner 1 DICOM +(0400,0120) OB Signature 1 DICOM +(0400,0305) CS CertifiedTimestampType 1 DICOM +(0400,0310) OB CertifiedTimestamp 1 DICOM +(0400,0401) SQ DigitalSignaturePurposeCodeSequence 1 DICOM +(0400,0402) SQ ReferencedDigitalSignatureSequence 1 DICOM +(0400,0403) SQ ReferencedSOPInstanceMACSequence 1 DICOM +(0400,0404) OB MAC 1 DICOM +(0400,0500) SQ EncryptedAttributesSequence 1 DICOM +(0400,0510) UI EncryptedContentTransferSyntaxUID 1 DICOM +(0400,0520) OB EncryptedContent 1 DICOM +(0400,0550) SQ ModifiedAttributesSequence 1 DICOM +(0400,0561) SQ OriginalAttributesSequence 1 DICOM +(0400,0562) DT AttributeModificationDateTime 1 DICOM +(0400,0563) LO ModifyingSystem 1 DICOM +(0400,0564) LO SourceOfPreviousValues 1 DICOM +(0400,0565) CS ReasonForTheAttributeModification 1 DICOM +(2000,0010) IS NumberOfCopies 1 DICOM +(2000,001E) SQ PrinterConfigurationSequence 1 DICOM +(2000,0020) CS PrintPriority 1 DICOM +(2000,0030) CS MediumType 1 DICOM +(2000,0040) CS FilmDestination 1 DICOM +(2000,0050) LO FilmSessionLabel 1 DICOM +(2000,0060) IS MemoryAllocation 1 DICOM +(2000,0061) IS MaximumMemoryAllocation 1 DICOM +(2000,00A0) US MemoryBitDepth 1 DICOM +(2000,00A1) US PrintingBitDepth 1 DICOM +(2000,00A2) SQ MediaInstalledSequence 1 DICOM +(2000,00A4) SQ OtherMediaAvailableSequence 1 DICOM +(2000,00A8) SQ SupportedImageDisplayFormatsSequence 1 DICOM +(2000,0500) SQ ReferencedFilmBoxSequence 1 DICOM +(2010,0010) ST ImageDisplayFormat 1 DICOM +(2010,0030) CS AnnotationDisplayFormatID 1 DICOM +(2010,0040) CS FilmOrientation 1 DICOM +(2010,0050) CS FilmSizeID 1 DICOM +(2010,0052) CS PrinterResolutionID 1 DICOM +(2010,0054) CS DefaultPrinterResolutionID 1 DICOM +(2010,0060) CS MagnificationType 1 DICOM +(2010,0080) CS SmoothingType 1 DICOM +(2010,00A6) CS DefaultMagnificationType 1 DICOM +(2010,00A7) CS OtherMagnificationTypesAvailable 1-n DICOM +(2010,00A8) CS DefaultSmoothingType 1 DICOM +(2010,00A9) CS OtherSmoothingTypesAvailable 1-n DICOM +(2010,0100) CS BorderDensity 1 DICOM +(2010,0110) CS EmptyImageDensity 1 DICOM +(2010,0120) US MinDensity 1 DICOM +(2010,0130) US MaxDensity 1 DICOM +(2010,0140) CS Trim 1 DICOM +(2010,0150) ST ConfigurationInformation 1 DICOM +(2010,0152) LT ConfigurationInformationDescription 1 DICOM +(2010,0154) IS MaximumCollatedFilms 1 DICOM +(2010,015E) US Illumination 1 DICOM +(2010,0160) US ReflectedAmbientLight 1 DICOM +(2010,0376) DS PrinterPixelSpacing 2 DICOM +(2010,0500) SQ ReferencedFilmSessionSequence 1 DICOM +(2010,0510) SQ ReferencedImageBoxSequence 1 DICOM +(2010,0520) SQ ReferencedBasicAnnotationBoxSequence 1 DICOM +(2020,0010) US ImageBoxPosition 1 DICOM +(2020,0020) CS Polarity 1 DICOM +(2020,0030) DS RequestedImageSize 1 DICOM +(2020,0040) CS RequestedDecimateCropBehavior 1 DICOM +(2020,0050) CS RequestedResolutionID 1 DICOM +(2020,00A0) CS RequestedImageSizeFlag 1 DICOM +(2020,00A2) CS DecimateCropResult 1 DICOM +(2020,0110) SQ BasicGrayscaleImageSequence 1 DICOM +(2020,0111) SQ BasicColorImageSequence 1 DICOM +(2030,0010) US AnnotationPosition 1 DICOM +(2030,0020) LO TextString 1 DICOM +(2050,0010) SQ PresentationLUTSequence 1 DICOM +(2050,0020) CS PresentationLUTShape 1 DICOM +(2050,0500) SQ ReferencedPresentationLUTSequence 1 DICOM +(2100,0020) CS ExecutionStatus 1 DICOM +(2100,0030) CS ExecutionStatusInfo 1 DICOM +(2100,0040) DA CreationDate 1 DICOM +(2100,0050) TM CreationTime 1 DICOM +(2100,0070) AE Originator 1 DICOM +(2100,0160) SH OwnerID 1 DICOM +(2100,0170) IS NumberOfFilms 1 DICOM +(2110,0010) CS PrinterStatus 1 DICOM +(2110,0020) CS PrinterStatusInfo 1 DICOM +(2110,0030) LO PrinterName 1 DICOM +(2200,0001) CS LabelUsingInformationExtractedFromInstances 1 DICOM +(2200,0002) UT LabelText 1 DICOM +(2200,0003) CS LabelStyleSelection 1 DICOM +(2200,0004) LT MediaDisposition 1 DICOM +(2200,0005) LT BarcodeValue 1 DICOM +(2200,0006) CS BarcodeSymbology 1 DICOM +(2200,0007) CS AllowMediaSplitting 1 DICOM +(2200,0008) CS IncludeNonDICOMObjects 1 DICOM +(2200,0009) CS IncludeDisplayApplication 1 DICOM +(2200,000A) CS PreserveCompositeInstancesAfterMediaCreation 1 DICOM +(2200,000B) US TotalNumberOfPiecesOfMediaCreated 1 DICOM +(2200,000C) LO RequestedMediaApplicationProfile 1 DICOM +(2200,000D) SQ ReferencedStorageMediaSequence 1 DICOM +(2200,000E) AT FailureAttributes 1-n DICOM +(2200,000F) CS AllowLossyCompression 1 DICOM +(2200,0020) CS RequestPriority 1 DICOM +(3002,0002) SH RTImageLabel 1 DICOM +(3002,0003) LO RTImageName 1 DICOM +(3002,0004) ST RTImageDescription 1 DICOM +(3002,000A) CS ReportedValuesOrigin 1 DICOM +(3002,000C) CS RTImagePlane 1 DICOM +(3002,000D) DS XRayImageReceptorTranslation 3 DICOM +(3002,000E) DS XRayImageReceptorAngle 1 DICOM +(3002,0010) DS RTImageOrientation 6 DICOM +(3002,0011) DS ImagePlanePixelSpacing 2 DICOM +(3002,0012) DS RTImagePosition 2 DICOM +(3002,0020) SH RadiationMachineName 1 DICOM +(3002,0022) DS RadiationMachineSAD 1 DICOM +(3002,0024) DS RadiationMachineSSD 1 DICOM +(3002,0026) DS RTImageSID 1 DICOM +(3002,0028) DS SourceToReferenceObjectDistance 1 DICOM +(3002,0029) IS FractionNumber 1 DICOM +(3002,0030) SQ ExposureSequence 1 DICOM +(3002,0032) DS MetersetExposure 1 DICOM +(3002,0034) DS DiaphragmPosition 4 DICOM +(3002,0040) SQ FluenceMapSequence 1 DICOM +(3002,0041) CS FluenceDataSource 1 DICOM +(3002,0042) DS FluenceDataScale 1 DICOM +(3002,0050) SQ PrimaryFluenceModeSequence 1 DICOM +(3002,0051) CS FluenceMode 1 DICOM +(3002,0052) SH FluenceModeID 1 DICOM +(3004,0001) CS DVHType 1 DICOM +(3004,0002) CS DoseUnits 1 DICOM +(3004,0004) CS DoseType 1 DICOM +(3004,0005) CS SpatialTransformOfDose 1 DICOM +(3004,0006) LO DoseComment 1 DICOM +(3004,0008) DS NormalizationPoint 3 DICOM +(3004,000A) CS DoseSummationType 1 DICOM +(3004,000C) DS GridFrameOffsetVector 2-n DICOM +(3004,000E) DS DoseGridScaling 1 DICOM +(3004,0010) SQ RTDoseROISequence 1 DICOM +(3004,0012) DS DoseValue 1 DICOM +(3004,0014) CS TissueHeterogeneityCorrection 1-3 DICOM +(3004,0040) DS DVHNormalizationPoint 3 DICOM +(3004,0042) DS DVHNormalizationDoseValue 1 DICOM +(3004,0050) SQ DVHSequence 1 DICOM +(3004,0052) DS DVHDoseScaling 1 DICOM +(3004,0054) CS DVHVolumeUnits 1 DICOM +(3004,0056) IS DVHNumberOfBins 1 DICOM +(3004,0058) DS DVHData 2-2n DICOM +(3004,0060) SQ DVHReferencedROISequence 1 DICOM +(3004,0062) CS DVHROIContributionType 1 DICOM +(3004,0070) DS DVHMinimumDose 1 DICOM +(3004,0072) DS DVHMaximumDose 1 DICOM +(3004,0074) DS DVHMeanDose 1 DICOM +(3006,0002) SH StructureSetLabel 1 DICOM +(3006,0004) LO StructureSetName 1 DICOM +(3006,0006) ST StructureSetDescription 1 DICOM +(3006,0008) DA StructureSetDate 1 DICOM +(3006,0009) TM StructureSetTime 1 DICOM +(3006,0010) SQ ReferencedFrameOfReferenceSequence 1 DICOM +(3006,0012) SQ RTReferencedStudySequence 1 DICOM +(3006,0014) SQ RTReferencedSeriesSequence 1 DICOM +(3006,0016) SQ ContourImageSequence 1 DICOM +(3006,0018) SQ PredecessorStructureSetSequence 1 DICOM +(3006,0020) SQ StructureSetROISequence 1 DICOM +(3006,0022) IS ROINumber 1 DICOM +(3006,0024) UI ReferencedFrameOfReferenceUID 1 DICOM +(3006,0026) LO ROIName 1 DICOM +(3006,0028) ST ROIDescription 1 DICOM +(3006,002A) IS ROIDisplayColor 3 DICOM +(3006,002C) DS ROIVolume 1 DICOM +(3006,0030) SQ RTRelatedROISequence 1 DICOM +(3006,0033) CS RTROIRelationship 1 DICOM +(3006,0036) CS ROIGenerationAlgorithm 1 DICOM +(3006,0038) LO ROIGenerationDescription 1 DICOM +(3006,0039) SQ ROIContourSequence 1 DICOM +(3006,0040) SQ ContourSequence 1 DICOM +(3006,0042) CS ContourGeometricType 1 DICOM +(3006,0044) DS ContourSlabThickness 1 DICOM +(3006,0045) DS ContourOffsetVector 3 DICOM +(3006,0046) IS NumberOfContourPoints 1 DICOM +(3006,0048) IS ContourNumber 1 DICOM +(3006,0049) IS AttachedContours 1-n DICOM +(3006,0050) DS ContourData 3-3n DICOM +(3006,0080) SQ RTROIObservationsSequence 1 DICOM +(3006,0082) IS ObservationNumber 1 DICOM +(3006,0084) IS ReferencedROINumber 1 DICOM +(3006,0085) SH ROIObservationLabel 1 DICOM +(3006,0086) SQ RTROIIdentificationCodeSequence 1 DICOM +(3006,0088) ST ROIObservationDescription 1 DICOM +(3006,00A0) SQ RelatedRTROIObservationsSequence 1 DICOM +(3006,00A4) CS RTROIInterpretedType 1 DICOM +(3006,00A6) PN ROIInterpreter 1 DICOM +(3006,00B0) SQ ROIPhysicalPropertiesSequence 1 DICOM +(3006,00B2) CS ROIPhysicalProperty 1 DICOM +(3006,00B4) DS ROIPhysicalPropertyValue 1 DICOM +(3006,00B6) SQ ROIElementalCompositionSequence 1 DICOM +(3006,00B7) US ROIElementalCompositionAtomicNumber 1 DICOM +(3006,00B8) FL ROIElementalCompositionAtomicMassFraction 1 DICOM +(3006,00B9) SQ AdditionalRTROIIdentificationCodeSequence 1 DICOM +(3006,00C6) DS FrameOfReferenceTransformationMatrix 16 DICOM +(3006,00C8) LO FrameOfReferenceTransformationComment 1 DICOM +(3008,0010) SQ MeasuredDoseReferenceSequence 1 DICOM +(3008,0012) ST MeasuredDoseDescription 1 DICOM +(3008,0014) CS MeasuredDoseType 1 DICOM +(3008,0016) DS MeasuredDoseValue 1 DICOM +(3008,0020) SQ TreatmentSessionBeamSequence 1 DICOM +(3008,0021) SQ TreatmentSessionIonBeamSequence 1 DICOM +(3008,0022) IS CurrentFractionNumber 1 DICOM +(3008,0024) DA TreatmentControlPointDate 1 DICOM +(3008,0025) TM TreatmentControlPointTime 1 DICOM +(3008,002A) CS TreatmentTerminationStatus 1 DICOM +(3008,002B) SH TreatmentTerminationCode 1 DICOM +(3008,002C) CS TreatmentVerificationStatus 1 DICOM +(3008,0030) SQ ReferencedTreatmentRecordSequence 1 DICOM +(3008,0032) DS SpecifiedPrimaryMeterset 1 DICOM +(3008,0033) DS SpecifiedSecondaryMeterset 1 DICOM +(3008,0036) DS DeliveredPrimaryMeterset 1 DICOM +(3008,0037) DS DeliveredSecondaryMeterset 1 DICOM +(3008,003A) DS SpecifiedTreatmentTime 1 DICOM +(3008,003B) DS DeliveredTreatmentTime 1 DICOM +(3008,0040) SQ ControlPointDeliverySequence 1 DICOM +(3008,0041) SQ IonControlPointDeliverySequence 1 DICOM +(3008,0042) DS SpecifiedMeterset 1 DICOM +(3008,0044) DS DeliveredMeterset 1 DICOM +(3008,0045) FL MetersetRateSet 1 DICOM +(3008,0046) FL MetersetRateDelivered 1 DICOM +(3008,0047) FL ScanSpotMetersetsDelivered 1-n DICOM +(3008,0048) DS DoseRateDelivered 1 DICOM +(3008,0050) SQ TreatmentSummaryCalculatedDoseReferenceSequence 1 DICOM +(3008,0052) DS CumulativeDoseToDoseReference 1 DICOM +(3008,0054) DA FirstTreatmentDate 1 DICOM +(3008,0056) DA MostRecentTreatmentDate 1 DICOM +(3008,005A) IS NumberOfFractionsDelivered 1 DICOM +(3008,0060) SQ OverrideSequence 1 DICOM +(3008,0061) AT ParameterSequencePointer 1 DICOM +(3008,0062) AT OverrideParameterPointer 1 DICOM +(3008,0063) IS ParameterItemIndex 1 DICOM +(3008,0064) IS MeasuredDoseReferenceNumber 1 DICOM +(3008,0065) AT ParameterPointer 1 DICOM +(3008,0066) ST OverrideReason 1 DICOM +(3008,0068) SQ CorrectedParameterSequence 1 DICOM +(3008,006A) FL CorrectionValue 1 DICOM +(3008,0070) SQ CalculatedDoseReferenceSequence 1 DICOM +(3008,0072) IS CalculatedDoseReferenceNumber 1 DICOM +(3008,0074) ST CalculatedDoseReferenceDescription 1 DICOM +(3008,0076) DS CalculatedDoseReferenceDoseValue 1 DICOM +(3008,0078) DS StartMeterset 1 DICOM +(3008,007A) DS EndMeterset 1 DICOM +(3008,0080) SQ ReferencedMeasuredDoseReferenceSequence 1 DICOM +(3008,0082) IS ReferencedMeasuredDoseReferenceNumber 1 DICOM +(3008,0090) SQ ReferencedCalculatedDoseReferenceSequence 1 DICOM +(3008,0092) IS ReferencedCalculatedDoseReferenceNumber 1 DICOM +(3008,00A0) SQ BeamLimitingDeviceLeafPairsSequence 1 DICOM +(3008,00B0) SQ RecordedWedgeSequence 1 DICOM +(3008,00C0) SQ RecordedCompensatorSequence 1 DICOM +(3008,00D0) SQ RecordedBlockSequence 1 DICOM +(3008,00E0) SQ TreatmentSummaryMeasuredDoseReferenceSequence 1 DICOM +(3008,00F0) SQ RecordedSnoutSequence 1 DICOM +(3008,00F2) SQ RecordedRangeShifterSequence 1 DICOM +(3008,00F4) SQ RecordedLateralSpreadingDeviceSequence 1 DICOM +(3008,00F6) SQ RecordedRangeModulatorSequence 1 DICOM +(3008,0100) SQ RecordedSourceSequence 1 DICOM +(3008,0105) LO SourceSerialNumber 1 DICOM +(3008,0110) SQ TreatmentSessionApplicationSetupSequence 1 DICOM +(3008,0116) CS ApplicationSetupCheck 1 DICOM +(3008,0120) SQ RecordedBrachyAccessoryDeviceSequence 1 DICOM +(3008,0122) IS ReferencedBrachyAccessoryDeviceNumber 1 DICOM +(3008,0130) SQ RecordedChannelSequence 1 DICOM +(3008,0132) DS SpecifiedChannelTotalTime 1 DICOM +(3008,0134) DS DeliveredChannelTotalTime 1 DICOM +(3008,0136) IS SpecifiedNumberOfPulses 1 DICOM +(3008,0138) IS DeliveredNumberOfPulses 1 DICOM +(3008,013A) DS SpecifiedPulseRepetitionInterval 1 DICOM +(3008,013C) DS DeliveredPulseRepetitionInterval 1 DICOM +(3008,0140) SQ RecordedSourceApplicatorSequence 1 DICOM +(3008,0142) IS ReferencedSourceApplicatorNumber 1 DICOM +(3008,0150) SQ RecordedChannelShieldSequence 1 DICOM +(3008,0152) IS ReferencedChannelShieldNumber 1 DICOM +(3008,0160) SQ BrachyControlPointDeliveredSequence 1 DICOM +(3008,0162) DA SafePositionExitDate 1 DICOM +(3008,0164) TM SafePositionExitTime 1 DICOM +(3008,0166) DA SafePositionReturnDate 1 DICOM +(3008,0168) TM SafePositionReturnTime 1 DICOM +(3008,0171) SQ PulseSpecificBrachyControlPointDeliveredSequence 1 DICOM +(3008,0172) US PulseNumber 1 DICOM +(3008,0173) SQ BrachyPulseControlPointDeliveredSequence 1 DICOM +(3008,0200) CS CurrentTreatmentStatus 1 DICOM +(3008,0202) ST TreatmentStatusComment 1 DICOM +(3008,0220) SQ FractionGroupSummarySequence 1 DICOM +(3008,0223) IS ReferencedFractionNumber 1 DICOM +(3008,0224) CS FractionGroupType 1 DICOM +(3008,0230) CS BeamStopperPosition 1 DICOM +(3008,0240) SQ FractionStatusSummarySequence 1 DICOM +(3008,0250) DA TreatmentDate 1 DICOM +(3008,0251) TM TreatmentTime 1 DICOM +(300A,0002) SH RTPlanLabel 1 DICOM +(300A,0003) LO RTPlanName 1 DICOM +(300A,0004) ST RTPlanDescription 1 DICOM +(300A,0006) DA RTPlanDate 1 DICOM +(300A,0007) TM RTPlanTime 1 DICOM +(300A,0009) LO TreatmentProtocols 1-n DICOM +(300A,000A) CS PlanIntent 1 DICOM +(300A,000B) LO TreatmentSites 1-n DICOM +(300A,000C) CS RTPlanGeometry 1 DICOM +(300A,000E) ST PrescriptionDescription 1 DICOM +(300A,0010) SQ DoseReferenceSequence 1 DICOM +(300A,0012) IS DoseReferenceNumber 1 DICOM +(300A,0013) UI DoseReferenceUID 1 DICOM +(300A,0014) CS DoseReferenceStructureType 1 DICOM +(300A,0015) CS NominalBeamEnergyUnit 1 DICOM +(300A,0016) LO DoseReferenceDescription 1 DICOM +(300A,0018) DS DoseReferencePointCoordinates 3 DICOM +(300A,001A) DS NominalPriorDose 1 DICOM +(300A,0020) CS DoseReferenceType 1 DICOM +(300A,0021) DS ConstraintWeight 1 DICOM +(300A,0022) DS DeliveryWarningDose 1 DICOM +(300A,0023) DS DeliveryMaximumDose 1 DICOM +(300A,0025) DS TargetMinimumDose 1 DICOM +(300A,0026) DS TargetPrescriptionDose 1 DICOM +(300A,0027) DS TargetMaximumDose 1 DICOM +(300A,0028) DS TargetUnderdoseVolumeFraction 1 DICOM +(300A,002A) DS OrganAtRiskFullVolumeDose 1 DICOM +(300A,002B) DS OrganAtRiskLimitDose 1 DICOM +(300A,002C) DS OrganAtRiskMaximumDose 1 DICOM +(300A,002D) DS OrganAtRiskOverdoseVolumeFraction 1 DICOM +(300A,0040) SQ ToleranceTableSequence 1 DICOM +(300A,0042) IS ToleranceTableNumber 1 DICOM +(300A,0043) SH ToleranceTableLabel 1 DICOM +(300A,0044) DS GantryAngleTolerance 1 DICOM +(300A,0046) DS BeamLimitingDeviceAngleTolerance 1 DICOM +(300A,0048) SQ BeamLimitingDeviceToleranceSequence 1 DICOM +(300A,004A) DS BeamLimitingDevicePositionTolerance 1 DICOM +(300A,004B) FL SnoutPositionTolerance 1 DICOM +(300A,004C) DS PatientSupportAngleTolerance 1 DICOM +(300A,004E) DS TableTopEccentricAngleTolerance 1 DICOM +(300A,004F) FL TableTopPitchAngleTolerance 1 DICOM +(300A,0050) FL TableTopRollAngleTolerance 1 DICOM +(300A,0051) DS TableTopVerticalPositionTolerance 1 DICOM +(300A,0052) DS TableTopLongitudinalPositionTolerance 1 DICOM +(300A,0053) DS TableTopLateralPositionTolerance 1 DICOM +(300A,0055) CS RTPlanRelationship 1 DICOM +(300A,0070) SQ FractionGroupSequence 1 DICOM +(300A,0071) IS FractionGroupNumber 1 DICOM +(300A,0072) LO FractionGroupDescription 1 DICOM +(300A,0078) IS NumberOfFractionsPlanned 1 DICOM +(300A,0079) IS NumberOfFractionPatternDigitsPerDay 1 DICOM +(300A,007A) IS RepeatFractionCycleLength 1 DICOM +(300A,007B) LT FractionPattern 1 DICOM +(300A,0080) IS NumberOfBeams 1 DICOM +(300A,0082) DS BeamDoseSpecificationPoint 3 DICOM +(300A,0084) DS BeamDose 1 DICOM +(300A,0086) DS BeamMeterset 1 DICOM +(300A,008B) CS BeamDoseMeaning 1 DICOM +(300A,008C) SQ BeamDoseVerificationControlPointSequence 1 DICOM +(300A,008D) FL AverageBeamDosePointDepth 1 DICOM +(300A,008E) FL AverageBeamDosePointEquivalentDepth 1 DICOM +(300A,008F) FL AverageBeamDosePointSSD 1 DICOM +(300A,00A0) IS NumberOfBrachyApplicationSetups 1 DICOM +(300A,00A2) DS BrachyApplicationSetupDoseSpecificationPoint 3 DICOM +(300A,00A4) DS BrachyApplicationSetupDose 1 DICOM +(300A,00B0) SQ BeamSequence 1 DICOM +(300A,00B2) SH TreatmentMachineName 1 DICOM +(300A,00B3) CS PrimaryDosimeterUnit 1 DICOM +(300A,00B4) DS SourceAxisDistance 1 DICOM +(300A,00B6) SQ BeamLimitingDeviceSequence 1 DICOM +(300A,00B8) CS RTBeamLimitingDeviceType 1 DICOM +(300A,00BA) DS SourceToBeamLimitingDeviceDistance 1 DICOM +(300A,00BB) FL IsocenterToBeamLimitingDeviceDistance 1 DICOM +(300A,00BC) IS NumberOfLeafJawPairs 1 DICOM +(300A,00BE) DS LeafPositionBoundaries 3-n DICOM +(300A,00C0) IS BeamNumber 1 DICOM +(300A,00C2) LO BeamName 1 DICOM +(300A,00C3) ST BeamDescription 1 DICOM +(300A,00C4) CS BeamType 1 DICOM +(300A,00C5) FD BeamDeliveryDurationLimit 1 DICOM +(300A,00C6) CS RadiationType 1 DICOM +(300A,00C7) CS HighDoseTechniqueType 1 DICOM +(300A,00C8) IS ReferenceImageNumber 1 DICOM +(300A,00CA) SQ PlannedVerificationImageSequence 1 DICOM +(300A,00CC) LO ImagingDeviceSpecificAcquisitionParameters 1-n DICOM +(300A,00CE) CS TreatmentDeliveryType 1 DICOM +(300A,00D0) IS NumberOfWedges 1 DICOM +(300A,00D1) SQ WedgeSequence 1 DICOM +(300A,00D2) IS WedgeNumber 1 DICOM +(300A,00D3) CS WedgeType 1 DICOM +(300A,00D4) SH WedgeID 1 DICOM +(300A,00D5) IS WedgeAngle 1 DICOM +(300A,00D6) DS WedgeFactor 1 DICOM +(300A,00D7) FL TotalWedgeTrayWaterEquivalentThickness 1 DICOM +(300A,00D8) DS WedgeOrientation 1 DICOM +(300A,00D9) FL IsocenterToWedgeTrayDistance 1 DICOM +(300A,00DA) DS SourceToWedgeTrayDistance 1 DICOM +(300A,00DB) FL WedgeThinEdgePosition 1 DICOM +(300A,00DC) SH BolusID 1 DICOM +(300A,00DD) ST BolusDescription 1 DICOM +(300A,00DE) DS EffectiveWedgeAngle 1 DICOM +(300A,00E0) IS NumberOfCompensators 1 DICOM +(300A,00E1) SH MaterialID 1 DICOM +(300A,00E2) DS TotalCompensatorTrayFactor 1 DICOM +(300A,00E3) SQ CompensatorSequence 1 DICOM +(300A,00E4) IS CompensatorNumber 1 DICOM +(300A,00E5) SH CompensatorID 1 DICOM +(300A,00E6) DS SourceToCompensatorTrayDistance 1 DICOM +(300A,00E7) IS CompensatorRows 1 DICOM +(300A,00E8) IS CompensatorColumns 1 DICOM +(300A,00E9) DS CompensatorPixelSpacing 2 DICOM +(300A,00EA) DS CompensatorPosition 2 DICOM +(300A,00EB) DS CompensatorTransmissionData 1-n DICOM +(300A,00EC) DS CompensatorThicknessData 1-n DICOM +(300A,00ED) IS NumberOfBoli 1 DICOM +(300A,00EE) CS CompensatorType 1 DICOM +(300A,00EF) SH CompensatorTrayID 1 DICOM +(300A,00F0) IS NumberOfBlocks 1 DICOM +(300A,00F2) DS TotalBlockTrayFactor 1 DICOM +(300A,00F3) FL TotalBlockTrayWaterEquivalentThickness 1 DICOM +(300A,00F4) SQ BlockSequence 1 DICOM +(300A,00F5) SH BlockTrayID 1 DICOM +(300A,00F6) DS SourceToBlockTrayDistance 1 DICOM +(300A,00F7) FL IsocenterToBlockTrayDistance 1 DICOM +(300A,00F8) CS BlockType 1 DICOM +(300A,00F9) LO AccessoryCode 1 DICOM +(300A,00FA) CS BlockDivergence 1 DICOM +(300A,00FB) CS BlockMountingPosition 1 DICOM +(300A,00FC) IS BlockNumber 1 DICOM +(300A,00FE) LO BlockName 1 DICOM +(300A,0100) DS BlockThickness 1 DICOM +(300A,0102) DS BlockTransmission 1 DICOM +(300A,0104) IS BlockNumberOfPoints 1 DICOM +(300A,0106) DS BlockData 2-2n DICOM +(300A,0107) SQ ApplicatorSequence 1 DICOM +(300A,0108) SH ApplicatorID 1 DICOM +(300A,0109) CS ApplicatorType 1 DICOM +(300A,010A) LO ApplicatorDescription 1 DICOM +(300A,010C) DS CumulativeDoseReferenceCoefficient 1 DICOM +(300A,010E) DS FinalCumulativeMetersetWeight 1 DICOM +(300A,0110) IS NumberOfControlPoints 1 DICOM +(300A,0111) SQ ControlPointSequence 1 DICOM +(300A,0112) IS ControlPointIndex 1 DICOM +(300A,0114) DS NominalBeamEnergy 1 DICOM +(300A,0115) DS DoseRateSet 1 DICOM +(300A,0116) SQ WedgePositionSequence 1 DICOM +(300A,0118) CS WedgePosition 1 DICOM +(300A,011A) SQ BeamLimitingDevicePositionSequence 1 DICOM +(300A,011C) DS LeafJawPositions 2-2n DICOM +(300A,011E) DS GantryAngle 1 DICOM +(300A,011F) CS GantryRotationDirection 1 DICOM +(300A,0120) DS BeamLimitingDeviceAngle 1 DICOM +(300A,0121) CS BeamLimitingDeviceRotationDirection 1 DICOM +(300A,0122) DS PatientSupportAngle 1 DICOM +(300A,0123) CS PatientSupportRotationDirection 1 DICOM +(300A,0124) DS TableTopEccentricAxisDistance 1 DICOM +(300A,0125) DS TableTopEccentricAngle 1 DICOM +(300A,0126) CS TableTopEccentricRotationDirection 1 DICOM +(300A,0128) DS TableTopVerticalPosition 1 DICOM +(300A,0129) DS TableTopLongitudinalPosition 1 DICOM +(300A,012A) DS TableTopLateralPosition 1 DICOM +(300A,012C) DS IsocenterPosition 3 DICOM +(300A,012E) DS SurfaceEntryPoint 3 DICOM +(300A,0130) DS SourceToSurfaceDistance 1 DICOM +(300A,0131) FL AverageBeamDosePointSourceToExternalContourSurfaceDistance 1 DICOM +(300A,0132) FL SourceToExternalContourDistance 1 DICOM +(300A,0133) FL ExternalContourEntryPoint 3 DICOM +(300A,0134) DS CumulativeMetersetWeight 1 DICOM +(300A,0140) FL TableTopPitchAngle 1 DICOM +(300A,0142) CS TableTopPitchRotationDirection 1 DICOM +(300A,0144) FL TableTopRollAngle 1 DICOM +(300A,0146) CS TableTopRollRotationDirection 1 DICOM +(300A,0148) FL HeadFixationAngle 1 DICOM +(300A,014A) FL GantryPitchAngle 1 DICOM +(300A,014C) CS GantryPitchRotationDirection 1 DICOM +(300A,014E) FL GantryPitchAngleTolerance 1 DICOM +(300A,0180) SQ PatientSetupSequence 1 DICOM +(300A,0182) IS PatientSetupNumber 1 DICOM +(300A,0183) LO PatientSetupLabel 1 DICOM +(300A,0184) LO PatientAdditionalPosition 1 DICOM +(300A,0190) SQ FixationDeviceSequence 1 DICOM +(300A,0192) CS FixationDeviceType 1 DICOM +(300A,0194) SH FixationDeviceLabel 1 DICOM +(300A,0196) ST FixationDeviceDescription 1 DICOM +(300A,0198) SH FixationDevicePosition 1 DICOM +(300A,0199) FL FixationDevicePitchAngle 1 DICOM +(300A,019A) FL FixationDeviceRollAngle 1 DICOM +(300A,01A0) SQ ShieldingDeviceSequence 1 DICOM +(300A,01A2) CS ShieldingDeviceType 1 DICOM +(300A,01A4) SH ShieldingDeviceLabel 1 DICOM +(300A,01A6) ST ShieldingDeviceDescription 1 DICOM +(300A,01A8) SH ShieldingDevicePosition 1 DICOM +(300A,01B0) CS SetupTechnique 1 DICOM +(300A,01B2) ST SetupTechniqueDescription 1 DICOM +(300A,01B4) SQ SetupDeviceSequence 1 DICOM +(300A,01B6) CS SetupDeviceType 1 DICOM +(300A,01B8) SH SetupDeviceLabel 1 DICOM +(300A,01BA) ST SetupDeviceDescription 1 DICOM +(300A,01BC) DS SetupDeviceParameter 1 DICOM +(300A,01D0) ST SetupReferenceDescription 1 DICOM +(300A,01D2) DS TableTopVerticalSetupDisplacement 1 DICOM +(300A,01D4) DS TableTopLongitudinalSetupDisplacement 1 DICOM +(300A,01D6) DS TableTopLateralSetupDisplacement 1 DICOM +(300A,0200) CS BrachyTreatmentTechnique 1 DICOM +(300A,0202) CS BrachyTreatmentType 1 DICOM +(300A,0206) SQ TreatmentMachineSequence 1 DICOM +(300A,0210) SQ SourceSequence 1 DICOM +(300A,0212) IS SourceNumber 1 DICOM +(300A,0214) CS SourceType 1 DICOM +(300A,0216) LO SourceManufacturer 1 DICOM +(300A,0218) DS ActiveSourceDiameter 1 DICOM +(300A,021A) DS ActiveSourceLength 1 DICOM +(300A,021B) SH SourceModelID 1 DICOM +(300A,021C) LO SourceDescription 1 DICOM +(300A,0222) DS SourceEncapsulationNominalThickness 1 DICOM +(300A,0224) DS SourceEncapsulationNominalTransmission 1 DICOM +(300A,0226) LO SourceIsotopeName 1 DICOM +(300A,0228) DS SourceIsotopeHalfLife 1 DICOM +(300A,0229) CS SourceStrengthUnits 1 DICOM +(300A,022A) DS ReferenceAirKermaRate 1 DICOM +(300A,022B) DS SourceStrength 1 DICOM +(300A,022C) DA SourceStrengthReferenceDate 1 DICOM +(300A,022E) TM SourceStrengthReferenceTime 1 DICOM +(300A,0230) SQ ApplicationSetupSequence 1 DICOM +(300A,0232) CS ApplicationSetupType 1 DICOM +(300A,0234) IS ApplicationSetupNumber 1 DICOM +(300A,0236) LO ApplicationSetupName 1 DICOM +(300A,0238) LO ApplicationSetupManufacturer 1 DICOM +(300A,0240) IS TemplateNumber 1 DICOM +(300A,0242) SH TemplateType 1 DICOM +(300A,0244) LO TemplateName 1 DICOM +(300A,0250) DS TotalReferenceAirKerma 1 DICOM +(300A,0260) SQ BrachyAccessoryDeviceSequence 1 DICOM +(300A,0262) IS BrachyAccessoryDeviceNumber 1 DICOM +(300A,0263) SH BrachyAccessoryDeviceID 1 DICOM +(300A,0264) CS BrachyAccessoryDeviceType 1 DICOM +(300A,0266) LO BrachyAccessoryDeviceName 1 DICOM +(300A,026A) DS BrachyAccessoryDeviceNominalThickness 1 DICOM +(300A,026C) DS BrachyAccessoryDeviceNominalTransmission 1 DICOM +(300A,0280) SQ ChannelSequence 1 DICOM +(300A,0282) IS ChannelNumber 1 DICOM +(300A,0284) DS ChannelLength 1 DICOM +(300A,0286) DS ChannelTotalTime 1 DICOM +(300A,0288) CS SourceMovementType 1 DICOM +(300A,028A) IS NumberOfPulses 1 DICOM +(300A,028C) DS PulseRepetitionInterval 1 DICOM +(300A,0290) IS SourceApplicatorNumber 1 DICOM +(300A,0291) SH SourceApplicatorID 1 DICOM +(300A,0292) CS SourceApplicatorType 1 DICOM +(300A,0294) LO SourceApplicatorName 1 DICOM +(300A,0296) DS SourceApplicatorLength 1 DICOM +(300A,0298) LO SourceApplicatorManufacturer 1 DICOM +(300A,029C) DS SourceApplicatorWallNominalThickness 1 DICOM +(300A,029E) DS SourceApplicatorWallNominalTransmission 1 DICOM +(300A,02A0) DS SourceApplicatorStepSize 1 DICOM +(300A,02A2) IS TransferTubeNumber 1 DICOM +(300A,02A4) DS TransferTubeLength 1 DICOM +(300A,02B0) SQ ChannelShieldSequence 1 DICOM +(300A,02B2) IS ChannelShieldNumber 1 DICOM +(300A,02B3) SH ChannelShieldID 1 DICOM +(300A,02B4) LO ChannelShieldName 1 DICOM +(300A,02B8) DS ChannelShieldNominalThickness 1 DICOM +(300A,02BA) DS ChannelShieldNominalTransmission 1 DICOM +(300A,02C8) DS FinalCumulativeTimeWeight 1 DICOM +(300A,02D0) SQ BrachyControlPointSequence 1 DICOM +(300A,02D2) DS ControlPointRelativePosition 1 DICOM +(300A,02D4) DS ControlPoint3DPosition 3 DICOM +(300A,02D6) DS CumulativeTimeWeight 1 DICOM +(300A,02E0) CS CompensatorDivergence 1 DICOM +(300A,02E1) CS CompensatorMountingPosition 1 DICOM +(300A,02E2) DS SourceToCompensatorDistance 1-n DICOM +(300A,02E3) FL TotalCompensatorTrayWaterEquivalentThickness 1 DICOM +(300A,02E4) FL IsocenterToCompensatorTrayDistance 1 DICOM +(300A,02E5) FL CompensatorColumnOffset 1 DICOM +(300A,02E6) FL IsocenterToCompensatorDistances 1-n DICOM +(300A,02E7) FL CompensatorRelativeStoppingPowerRatio 1 DICOM +(300A,02E8) FL CompensatorMillingToolDiameter 1 DICOM +(300A,02EA) SQ IonRangeCompensatorSequence 1 DICOM +(300A,02EB) LT CompensatorDescription 1 DICOM +(300A,0302) IS RadiationMassNumber 1 DICOM +(300A,0304) IS RadiationAtomicNumber 1 DICOM +(300A,0306) SS RadiationChargeState 1 DICOM +(300A,0308) CS ScanMode 1 DICOM +(300A,030A) FL VirtualSourceAxisDistances 2 DICOM +(300A,030C) SQ SnoutSequence 1 DICOM +(300A,030D) FL SnoutPosition 1 DICOM +(300A,030F) SH SnoutID 1 DICOM +(300A,0312) IS NumberOfRangeShifters 1 DICOM +(300A,0314) SQ RangeShifterSequence 1 DICOM +(300A,0316) IS RangeShifterNumber 1 DICOM +(300A,0318) SH RangeShifterID 1 DICOM +(300A,0320) CS RangeShifterType 1 DICOM +(300A,0322) LO RangeShifterDescription 1 DICOM +(300A,0330) IS NumberOfLateralSpreadingDevices 1 DICOM +(300A,0332) SQ LateralSpreadingDeviceSequence 1 DICOM +(300A,0334) IS LateralSpreadingDeviceNumber 1 DICOM +(300A,0336) SH LateralSpreadingDeviceID 1 DICOM +(300A,0338) CS LateralSpreadingDeviceType 1 DICOM +(300A,033A) LO LateralSpreadingDeviceDescription 1 DICOM +(300A,033C) FL LateralSpreadingDeviceWaterEquivalentThickness 1 DICOM +(300A,0340) IS NumberOfRangeModulators 1 DICOM +(300A,0342) SQ RangeModulatorSequence 1 DICOM +(300A,0344) IS RangeModulatorNumber 1 DICOM +(300A,0346) SH RangeModulatorID 1 DICOM +(300A,0348) CS RangeModulatorType 1 DICOM +(300A,034A) LO RangeModulatorDescription 1 DICOM +(300A,034C) SH BeamCurrentModulationID 1 DICOM +(300A,0350) CS PatientSupportType 1 DICOM +(300A,0352) SH PatientSupportID 1 DICOM +(300A,0354) LO PatientSupportAccessoryCode 1 DICOM +(300A,0356) FL FixationLightAzimuthalAngle 1 DICOM +(300A,0358) FL FixationLightPolarAngle 1 DICOM +(300A,035A) FL MetersetRate 1 DICOM +(300A,0360) SQ RangeShifterSettingsSequence 1 DICOM +(300A,0362) LO RangeShifterSetting 1 DICOM +(300A,0364) FL IsocenterToRangeShifterDistance 1 DICOM +(300A,0366) FL RangeShifterWaterEquivalentThickness 1 DICOM +(300A,0370) SQ LateralSpreadingDeviceSettingsSequence 1 DICOM +(300A,0372) LO LateralSpreadingDeviceSetting 1 DICOM +(300A,0374) FL IsocenterToLateralSpreadingDeviceDistance 1 DICOM +(300A,0380) SQ RangeModulatorSettingsSequence 1 DICOM +(300A,0382) FL RangeModulatorGatingStartValue 1 DICOM +(300A,0384) FL RangeModulatorGatingStopValue 1 DICOM +(300A,0386) FL RangeModulatorGatingStartWaterEquivalentThickness 1 DICOM +(300A,0388) FL RangeModulatorGatingStopWaterEquivalentThickness 1 DICOM +(300A,038A) FL IsocenterToRangeModulatorDistance 1 DICOM +(300A,0390) SH ScanSpotTuneID 1 DICOM +(300A,0392) IS NumberOfScanSpotPositions 1 DICOM +(300A,0394) FL ScanSpotPositionMap 1-n DICOM +(300A,0396) FL ScanSpotMetersetWeights 1-n DICOM +(300A,0398) FL ScanningSpotSize 2 DICOM +(300A,039A) IS NumberOfPaintings 1 DICOM +(300A,03A0) SQ IonToleranceTableSequence 1 DICOM +(300A,03A2) SQ IonBeamSequence 1 DICOM +(300A,03A4) SQ IonBeamLimitingDeviceSequence 1 DICOM +(300A,03A6) SQ IonBlockSequence 1 DICOM +(300A,03A8) SQ IonControlPointSequence 1 DICOM +(300A,03AA) SQ IonWedgeSequence 1 DICOM +(300A,03AC) SQ IonWedgePositionSequence 1 DICOM +(300A,0401) SQ ReferencedSetupImageSequence 1 DICOM +(300A,0402) ST SetupImageComment 1 DICOM +(300A,0410) SQ MotionSynchronizationSequence 1 DICOM +(300A,0412) FL ControlPointOrientation 3 DICOM +(300A,0420) SQ GeneralAccessorySequence 1 DICOM +(300A,0421) SH GeneralAccessoryID 1 DICOM +(300A,0422) ST GeneralAccessoryDescription 1 DICOM +(300A,0423) CS GeneralAccessoryType 1 DICOM +(300A,0424) IS GeneralAccessoryNumber 1 DICOM +(300A,0425) FL SourceToGeneralAccessoryDistance 1 DICOM +(300A,0431) SQ ApplicatorGeometrySequence 1 DICOM +(300A,0432) CS ApplicatorApertureShape 1 DICOM +(300A,0433) FL ApplicatorOpening 1 DICOM +(300A,0434) FL ApplicatorOpeningX 1 DICOM +(300A,0435) FL ApplicatorOpeningY 1 DICOM +(300A,0436) FL SourceToApplicatorMountingPositionDistance 1 DICOM +(300A,0440) IS NumberOfBlockSlabItems 1 DICOM +(300A,0441) SQ BlockSlabSequence 1 DICOM +(300A,0442) DS BlockSlabThickness 1 DICOM +(300A,0443) US BlockSlabNumber 1 DICOM +(300A,0450) SQ DeviceMotionControlSequence 1 DICOM +(300A,0451) CS DeviceMotionExecutionMode 1 DICOM +(300A,0452) CS DeviceMotionObservationMode 1 DICOM +(300A,0453) SQ DeviceMotionParameterCodeSequence 1 DICOM +(300C,0002) SQ ReferencedRTPlanSequence 1 DICOM +(300C,0004) SQ ReferencedBeamSequence 1 DICOM +(300C,0006) IS ReferencedBeamNumber 1 DICOM +(300C,0007) IS ReferencedReferenceImageNumber 1 DICOM +(300C,0008) DS StartCumulativeMetersetWeight 1 DICOM +(300C,0009) DS EndCumulativeMetersetWeight 1 DICOM +(300C,000A) SQ ReferencedBrachyApplicationSetupSequence 1 DICOM +(300C,000C) IS ReferencedBrachyApplicationSetupNumber 1 DICOM +(300C,000E) IS ReferencedSourceNumber 1 DICOM +(300C,0020) SQ ReferencedFractionGroupSequence 1 DICOM +(300C,0022) IS ReferencedFractionGroupNumber 1 DICOM +(300C,0040) SQ ReferencedVerificationImageSequence 1 DICOM +(300C,0042) SQ ReferencedReferenceImageSequence 1 DICOM +(300C,0050) SQ ReferencedDoseReferenceSequence 1 DICOM +(300C,0051) IS ReferencedDoseReferenceNumber 1 DICOM +(300C,0055) SQ BrachyReferencedDoseReferenceSequence 1 DICOM +(300C,0060) SQ ReferencedStructureSetSequence 1 DICOM +(300C,006A) IS ReferencedPatientSetupNumber 1 DICOM +(300C,0080) SQ ReferencedDoseSequence 1 DICOM +(300C,00A0) IS ReferencedToleranceTableNumber 1 DICOM +(300C,00B0) SQ ReferencedBolusSequence 1 DICOM +(300C,00C0) IS ReferencedWedgeNumber 1 DICOM +(300C,00D0) IS ReferencedCompensatorNumber 1 DICOM +(300C,00E0) IS ReferencedBlockNumber 1 DICOM +(300C,00F0) IS ReferencedControlPointIndex 1 DICOM +(300C,00F2) SQ ReferencedControlPointSequence 1 DICOM +(300C,00F4) IS ReferencedStartControlPointIndex 1 DICOM +(300C,00F6) IS ReferencedStopControlPointIndex 1 DICOM +(300C,0100) IS ReferencedRangeShifterNumber 1 DICOM +(300C,0102) IS ReferencedLateralSpreadingDeviceNumber 1 DICOM +(300C,0104) IS ReferencedRangeModulatorNumber 1 DICOM +(300C,0111) SQ OmittedBeamTaskSequence 1 DICOM +(300C,0112) CS ReasonForOmission 1 DICOM +(300C,0113) LO ReasonForOmissionDescription 1 DICOM +(300E,0002) CS ApprovalStatus 1 DICOM +(300E,0004) DA ReviewDate 1 DICOM +(300E,0005) TM ReviewTime 1 DICOM +(300E,0008) PN ReviewerName 1 DICOM +(4010,0001) CS LowEnergyDetectors 1 DICOM/DICOS +(4010,0002) CS HighEnergyDetectors 1 DICOM/DICOS +(4010,0004) SQ DetectorGeometrySequence 1 DICOM/DICOS +(4010,1001) SQ ThreatROIVoxelSequence 1 DICOM/DICOS +(4010,1004) FL ThreatROIBase 3 DICOM/DICOS +(4010,1005) FL ThreatROIExtents 3 DICOM/DICOS +(4010,1006) OB ThreatROIBitmap 1 DICOM/DICOS +(4010,1007) SH RouteSegmentID 1 DICOM/DICOS +(4010,1008) CS GantryType 1 DICOM/DICOS +(4010,1009) CS OOIOwnerType 1 DICOM/DICOS +(4010,100A) SQ RouteSegmentSequence 1 DICOM/DICOS +(4010,1010) US PotentialThreatObjectID 1 DICOM/DICOS +(4010,1011) SQ ThreatSequence 1 DICOM/DICOS +(4010,1012) CS ThreatCategory 1 DICOM/DICOS +(4010,1013) LT ThreatCategoryDescription 1 DICOM/DICOS +(4010,1014) CS ATDAbilityAssessment 1 DICOM/DICOS +(4010,1015) CS ATDAssessmentFlag 1 DICOM/DICOS +(4010,1016) FL ATDAssessmentProbability 1 DICOM/DICOS +(4010,1017) FL Mass 1 DICOM/DICOS +(4010,1018) FL Density 1 DICOM/DICOS +(4010,1019) FL ZEffective 1 DICOM/DICOS +(4010,101A) SH BoardingPassID 1 DICOM/DICOS +(4010,101B) FL CenterOfMass 3 DICOM/DICOS +(4010,101C) FL CenterOfPTO 3 DICOM/DICOS +(4010,101D) FL BoundingPolygon 6-n DICOM/DICOS +(4010,101E) SH RouteSegmentStartLocationID 1 DICOM/DICOS +(4010,101F) SH RouteSegmentEndLocationID 1 DICOM/DICOS +(4010,1020) CS RouteSegmentLocationIDType 1 DICOM/DICOS +(4010,1021) CS AbortReason 1-n DICOM/DICOS +(4010,1023) FL VolumeOfPTO 1 DICOM/DICOS +(4010,1024) CS AbortFlag 1 DICOM/DICOS +(4010,1025) DT RouteSegmentStartTime 1 DICOM/DICOS +(4010,1026) DT RouteSegmentEndTime 1 DICOM/DICOS +(4010,1027) CS TDRType 1 DICOM/DICOS +(4010,1028) CS InternationalRouteSegment 1 DICOM/DICOS +(4010,1029) LO ThreatDetectionAlgorithmandVersion 1-n DICOM/DICOS +(4010,102A) SH AssignedLocation 1 DICOM/DICOS +(4010,102B) DT AlarmDecisionTime 1 DICOM/DICOS +(4010,1031) CS AlarmDecision 1 DICOM/DICOS +(4010,1033) US NumberOfTotalObjects 1 DICOM/DICOS +(4010,1034) US NumberOfAlarmObjects 1 DICOM/DICOS +(4010,1037) SQ PTORepresentationSequence 1 DICOM/DICOS +(4010,1038) SQ ATDAssessmentSequence 1 DICOM/DICOS +(4010,1039) CS TIPType 1 DICOM/DICOS +(4010,103A) CS DICOSVersion 1 DICOM/DICOS +(4010,1041) DT OOIOwnerCreationTime 1 DICOM/DICOS +(4010,1042) CS OOIType 1 DICOM/DICOS +(4010,1043) FL OOISize 3 DICOM/DICOS +(4010,1044) CS AcquisitionStatus 1 DICOM/DICOS +(4010,1045) SQ BasisMaterialsCodeSequence 1 DICOM/DICOS +(4010,1046) CS PhantomType 1 DICOM/DICOS +(4010,1047) SQ OOIOwnerSequence 1 DICOM/DICOS +(4010,1048) CS ScanType 1 DICOM/DICOS +(4010,1051) LO ItineraryID 1 DICOM/DICOS +(4010,1052) SH ItineraryIDType 1 DICOM/DICOS +(4010,1053) LO ItineraryIDAssigningAuthority 1 DICOM/DICOS +(4010,1054) SH RouteID 1 DICOM/DICOS +(4010,1055) SH RouteIDAssigningAuthority 1 DICOM/DICOS +(4010,1056) CS InboundArrivalType 1 DICOM/DICOS +(4010,1058) SH CarrierID 1 DICOM/DICOS +(4010,1059) CS CarrierIDAssigningAuthority 1 DICOM/DICOS +(4010,1060) FL SourceOrientation 3 DICOM/DICOS +(4010,1061) FL SourcePosition 3 DICOM/DICOS +(4010,1062) FL BeltHeight 1 DICOM/DICOS +(4010,1064) SQ AlgorithmRoutingCodeSequence 1 DICOM/DICOS +(4010,1067) CS TransportClassification 1 DICOM/DICOS +(4010,1068) LT OOITypeDescriptor 1 DICOM/DICOS +(4010,1069) FL TotalProcessingTime 1 DICOM/DICOS +(4010,106C) OB DetectorCalibrationData 1 DICOM/DICOS +(4010,106D) CS AdditionalScreeningPerformed 1 DICOM/DICOS +(4010,106E) CS AdditionalInspectionSelectionCriteria 1 DICOM/DICOS +(4010,106F) SQ AdditionalInspectionMethodSequence 1 DICOM/DICOS +(4010,1070) CS AITDeviceType 1 DICOM/DICOS +(4010,1071) SQ QRMeasurementsSequence 1 DICOM/DICOS +(4010,1072) SQ TargetMaterialSequence 1 DICOM/DICOS +(4010,1073) FD SNRThreshold 1 DICOM/DICOS +(4010,1075) DS ImageScaleRepresentation 1 DICOM/DICOS +(4010,1076) SQ ReferencedPTOSequence 1 DICOM/DICOS +(4010,1077) SQ ReferencedTDRInstanceSequence 1 DICOM/DICOS +(4010,1078) ST PTOLocationDescription 1 DICOM/DICOS +(4010,1079) SQ AnomalyLocatorIndicatorSequence 1 DICOM/DICOS +(4010,107A) FL AnomalyLocatorIndicator 3 DICOM/DICOS +(4010,107B) SQ PTORegionSequence 1 DICOM/DICOS +(4010,107C) CS InspectionSelectionCriteria 1 DICOM/DICOS +(4010,107D) SQ SecondaryInspectionMethodSequence 1 DICOM/DICOS +(4010,107E) DS PRCSToRCSOrientation 6 DICOM/DICOS +(4FFE,0001) SQ MACParametersSequence 1 DICOM +(5200,9229) SQ SharedFunctionalGroupsSequence 1 DICOM +(5200,9230) SQ PerFrameFunctionalGroupsSequence 1 DICOM +(5400,0100) SQ WaveformSequence 1 DICOM +(5400,0110) ox ChannelMinimumValue 1 DICOM +(5400,0112) ox ChannelMaximumValue 1 DICOM +(5400,1004) US WaveformBitsAllocated 1 DICOM +(5400,1006) CS WaveformSampleInterpretation 1 DICOM +(5400,100A) ox WaveformPaddingValue 1 DICOM +(5400,1010) ox WaveformData 1 DICOM +(5600,0010) OF FirstOrderPhaseCorrectionAngle 1 DICOM +(5600,0020) OF SpectroscopyData 1 DICOM +(6000-60FF,0010) US OverlayRows 1 DICOM +(6000-60FF,0011) US OverlayColumns 1 DICOM +(6000-60FF,0015) IS NumberOfFramesInOverlay 1 DICOM +(6000-60FF,0022) LO OverlayDescription 1 DICOM +(6000-60FF,0040) CS OverlayType 1 DICOM +(6000-60FF,0045) LO OverlaySubtype 1 DICOM +(6000-60FF,0050) SS OverlayOrigin 2 DICOM +(6000-60FF,0051) US ImageFrameOrigin 1 DICOM +(6000-60FF,0100) US OverlayBitsAllocated 1 DICOM +(6000-60FF,0102) US OverlayBitPosition 1 DICOM +(6000-60FF,1001) CS OverlayActivationLayer 1 DICOM +(6000-60FF,1301) IS ROIArea 1 DICOM +(6000-60FF,1302) DS ROIMean 1 DICOM +(6000-60FF,1303) DS ROIStandardDeviation 1 DICOM +(6000-60FF,1500) LO OverlayLabel 1 DICOM +(6000-60FF,3000) ox OverlayData 1 DICOM +(7FE0,0008) OF FloatPixelData 1 DICOM +(7FE0,0009) OD DoubleFloatPixelData 1 DICOM +(7FE0,0010) ox PixelData 1 DICOM +(FFFA,FFFA) SQ DigitalSignaturesSequence 1 DICOM +(FFFC,FFFC) OB DataSetTrailingPadding 1 DICOM +(FFFE,E000) na Item 1 DICOM +(FFFE,E00D) na ItemDelimitationItem 1 DICOM +(FFFE,E0DD) na SequenceDelimitationItem 1 DICOM +# +#--------------------------------------------------------------------------- +# +# Supplement 156 (Planar MPR Volumetric Presentation State) +# +(0028,1224) OW SegmentedAlphaPaletteColorLookupTableData 1 Supplement_156 +(0070,1101) UI PresentationDisplayCollectionUID 1 Supplement_156 +(0070,1102) UI PresentationSequenceCollectionUID 1 Supplement_156 +(0070,1103) US PresentationSequencePositionIndex 1 Supplement_156 +(0070,1104) SQ RenderedImageReferenceSequence 1 Supplement_156 +(0070,1201) SQ VolumetricPresentationStateInputSequence 1 Supplement_156 +(0070,1202) CS PresentationInputType 1 Supplement_156 +(0070,1203) US InputSequencePositionIndex 1 Supplement_156 +(0070,1204) CS Crop 1 Supplement_156 +(0070,1205) US CroppingSpecificationIndex 1-n Supplement_156 +(0070,1206) CS CompositingMethod 1 Supplement_156 +(0070,1207) US VolumetricPresentationInputNumber 1 Supplement_156 +(0070,1208) CS ImageVolumeGeometry 1 Supplement_156 +(0070,1301) SQ VolumeCroppingSequence 1 Supplement_156 +(0070,1302) CS VolumeCroppingMethod 1 Supplement_156 +(0070,1303) FD BoundingBoxCrop 6 Supplement_156 +(0070,1304) SQ ObliqueCroppingPlaneSequence 1 Supplement_156 +(0070,1305) FD ObliqueCroppingPlane 4 Supplement_156 +(0070,1306) FD ObliqueCroppingPlaneNormal 3 Supplement_156 +(0070,1309) US CroppingSpecificationNumber 1 Supplement_156 +(0070,1501) CS MultiPlanarReconstructionStyle 1 Supplement_156 +(0070,1502) CS MPRThicknessType 1 Supplement_156 +(0070,1503) FD MPRSlabThickness 1 Supplement_156 +(0070,1505) FD MPRTopLeftHandCorner 3 Supplement_156 +(0070,1507) FD MPRViewWidthDirection 3 Supplement_156 +(0070,1508) FD MPRViewWidth 1 Supplement_156 +(0070,150C) FL NumberOfVolumetricCurvePoints 1 Supplement_156 +(0070,150D) OD VolumetricCurvePoints 1 Supplement_156 +(0070,1511) FD MPRViewHeightDirection 3 Supplement_156 +(0070,1512) FD MPRViewHeight 1 Supplement_156 +(0070,1801) SQ PresentationStateClassificationComponentSequence 1 Supplement_156 +(0070,1802) CS ComponentType 1 Supplement_156 +(0070,1803) SQ ComponentInputSequence 1 Supplement_156 +(0070,1804) US VolumetricPresentationInputIndex 1 Supplement_156 +(0070,1805) SQ PresentationStateCompositorComponentSequence 1 Supplement_156 +(0070,1806) SQ WeightingTransferFunctionSequence 1 Supplement_156 +(0070,1807) US WeightingLookupTableDescriptor 3 Supplement_156 +(0070,1808) OB WeightingLookupTableData 1 Supplement_156 +(0070,1901) SQ VolumetricAnnotationSequence 1 Supplement_156 +(0070,1903) SQ ReferencedStructuredContextSequence 1 Supplement_156 +(0070,1904) UI ReferencedContentItem 1 Supplement_156 +(0070,1905) SQ VolumetricPresentationInputAnnotationSequence 1 Supplement_156 +(0070,1907) CS AnnotationClipping 1 Supplement_156 +(0070,1A01) CS PresentationAnimationStyle 1 Supplement_156 +(0070,1A03) FD RecommendedAnimationRate 1 Supplement_156 +(0070,1A04) SQ AnimationCurveSequence 1 Supplement_156 +(0070,1A05) FD AnimationStepSize 1 Supplement_156 +# +#--------------------------------------------------------------------------- +# +# Correction Items 1441, 1454, 1458, 1461 +# +(0040,4070) SQ OutputDestinationSequence 1 CP_1441 +(0040,4071) SQ DICOMStorageSequence 1 CP_1441 +(0040,4072) SQ STOWRSStorageSequence 1 CP_1441 +(0040,4073) UR StorageURL 1 CP_1441 +(0040,4074) SQ XDSStorageSequence 1 CP_1441 +(0028,2002) CS ColorSpace 1 CP_1454 +(0040,9213) FD DoubleFloatRealWorldValueLastValueMapped 1 CP_1458 +(0040,9214) FD DoubleFloatRealWorldValueFirstValueMapped 1 CP_1458 +(0018,1320) FL B1rms 1 CP_1461 +# +#--------------------------------------------------------------------------- +# +# Private Creator Data Elements +# +(0009-o-FFFF,0000) UL PrivateGroupLength 1 PRIVATE +(0009-o-FFFF,0010-u-00FF) LO PrivateCreator 1 PRIVATE +(0001-o-0007,0000) UL IllegalGroupLength 1 ILLEGAL +(0001-o-0007,0010-u-00FF) LO IllegalPrivateCreator 1 ILLEGAL +# +#--------------------------------------------------------------------------- +# +# A "catch all" for group length elements +# +(0000-u-FFFF,0000) UL GenericGroupLength 1 GENERIC +# +#--------------------------------------------------------------------------- +# +# Retired data elements from previous editions of the DICOM standard +# +(0000,0001) UL RETIRED_CommandLengthToEnd 1 DICOM/retired +(0000,0010) SH RETIRED_CommandRecognitionCode 1 DICOM/retired +(0000,0200) AE RETIRED_Initiator 1 DICOM/retired +(0000,0300) AE RETIRED_Receiver 1 DICOM/retired +(0000,0400) AE RETIRED_FindLocation 1 DICOM/retired +(0000,0850) US RETIRED_NumberOfMatches 1 DICOM/retired +(0000,0860) US RETIRED_ResponseSequenceNumber 1 DICOM/retired +(0000,4000) LT RETIRED_DialogReceiver 1 DICOM/retired +(0000,4010) LT RETIRED_TerminalType 1 DICOM/retired +(0000,5010) SH RETIRED_MessageSetID 1 DICOM/retired +(0000,5020) SH RETIRED_EndMessageID 1 DICOM/retired +(0000,5110) LT RETIRED_DisplayFormat 1 DICOM/retired +(0000,5120) LT RETIRED_PagePositionID 1 DICOM/retired +(0000,5130) CS RETIRED_TextFormatID 1 DICOM/retired +(0000,5140) CS RETIRED_NormalReverse 1 DICOM/retired +(0000,5150) CS RETIRED_AddGrayScale 1 DICOM/retired +(0000,5160) CS RETIRED_Borders 1 DICOM/retired +(0000,5170) IS RETIRED_Copies 1 DICOM/retired +(0000,5180) CS RETIRED_CommandMagnificationType 1 DICOM/retired +(0000,5190) CS RETIRED_Erase 1 DICOM/retired +(0000,51A0) CS RETIRED_Print 1 DICOM/retired +(0000,51B0) US RETIRED_Overlays 1-n DICOM/retired +(0004,1504) up RETIRED_MRDRDirectoryRecordOffset 1 DICOM/retired +(0004,1600) UL RETIRED_NumberOfReferences 1 DICOM/retired +(0008,0001) UL RETIRED_LengthToEnd 1 DICOM/retired +(0008,0010) SH RETIRED_RecognitionCode 1 DICOM/retired +(0008,0024) DA RETIRED_OverlayDate 1 DICOM/retired +(0008,0025) DA RETIRED_CurveDate 1 DICOM/retired +(0008,0034) TM RETIRED_OverlayTime 1 DICOM/retired +(0008,0035) TM RETIRED_CurveTime 1 DICOM/retired +(0008,0040) US RETIRED_DataSetType 1 DICOM/retired +(0008,0041) LO RETIRED_DataSetSubtype 1 DICOM/retired +(0008,0042) CS RETIRED_NuclearMedicineSeriesType 1 DICOM/retired +(0008,1000) AE RETIRED_NetworkID 1 DICOM/retired +(0008,1100) SQ RETIRED_ReferencedResultsSequence 1 DICOM/retired +(0008,1130) SQ RETIRED_ReferencedOverlaySequence 1 DICOM/retired +(0008,1145) SQ RETIRED_ReferencedCurveSequence 1 DICOM/retired +(0008,2110) CS RETIRED_LossyImageCompressionRetired 1 DICOM/retired +(0008,2200) CS RETIRED_TransducerPosition 1 DICOM/retired +(0008,2204) CS RETIRED_TransducerOrientation 1 DICOM/retired +(0008,2208) CS RETIRED_AnatomicStructure 1 DICOM/retired +(0008,2240) SQ RETIRED_TransducerPositionSequence 1 DICOM/retired +(0008,2242) SQ RETIRED_TransducerPositionModifierSequence 1 DICOM/retired +(0008,2244) SQ RETIRED_TransducerOrientationSequence 1 DICOM/retired +(0008,2246) SQ RETIRED_TransducerOrientationModifierSequence 1 DICOM/retired +(0008,2251) SQ RETIRED_AnatomicStructureSpaceOrRegionCodeSequenceTrial 1 DICOM/retired +(0008,2253) SQ RETIRED_AnatomicPortalOfEntranceCodeSequenceTrial 1 DICOM/retired +(0008,2255) SQ RETIRED_AnatomicApproachDirectionCodeSequenceTrial 1 DICOM/retired +(0008,2256) ST RETIRED_AnatomicPerspectiveDescriptionTrial 1 DICOM/retired +(0008,2257) SQ RETIRED_AnatomicPerspectiveCodeSequenceTrial 1 DICOM/retired +(0008,2258) ST RETIRED_AnatomicLocationOfExaminingInstrumentDescriptionTrial 1 DICOM/retired +(0008,2259) SQ RETIRED_AnatomicLocationOfExaminingInstrumentCodeSequenceTrial 1 DICOM/retired +(0008,225A) SQ RETIRED_AnatomicStructureSpaceOrRegionModifierCodeSequenceTrial 1 DICOM/retired +(0008,225C) SQ RETIRED_OnAxisBackgroundAnatomicStructureCodeSequenceTrial 1 DICOM/retired +(0008,4000) LT RETIRED_IdentifyingComments 1 DICOM/retired +(0010,1050) LO RETIRED_InsurancePlanIdentification 1-n DICOM/retired +(0014,0023) ST RETIRED_CADFileFormat 1-n DICOM/retired +(0014,0024) ST RETIRED_ComponentReferenceSystem 1-n DICOM/retired +(0014,0045) ST RETIRED_MaterialPropertiesFileFormatRetired 1-n DICOM/retired +(0018,0030) LO RETIRED_Radionuclide 1-n DICOM/retired +(0018,0032) DS RETIRED_EnergyWindowCenterline 1 DICOM/retired +(0018,0033) DS RETIRED_EnergyWindowTotalWidth 1-n DICOM/retired +(0018,0037) CS RETIRED_TherapyType 1 DICOM/retired +(0018,0039) CS RETIRED_TherapyDescription 1 DICOM/retired +(0018,1011) LO RETIRED_HardcopyCreationDeviceID 1 DICOM/retired +(0018,1017) LO RETIRED_HardcopyDeviceManufacturer 1 DICOM/retired +(0018,101A) LO RETIRED_HardcopyDeviceSoftwareVersion 1-n DICOM/retired +(0018,101B) LO RETIRED_HardcopyDeviceManufacturerModelName 1 DICOM/retired +(0018,1141) DS RETIRED_AngularPosition 1 DICOM/retired +(0018,1146) DS RETIRED_RotationOffset 1-n DICOM/retired +(0018,1240) IS RETIRED_UpperLowerPixelValues 1-n DICOM/retired +(0018,4000) LT RETIRED_AcquisitionComments 1 DICOM/retired +(0018,5021) LO RETIRED_PostprocessingFunction 1 DICOM/retired +(0018,5030) DS RETIRED_DynamicRange 1 DICOM/retired +(0018,5040) DS RETIRED_TotalGain 1 DICOM/retired +(0018,5210) DS RETIRED_ImageTransformationMatrix 6 DICOM/retired +(0018,5212) DS RETIRED_ImageTranslationVector 3 DICOM/retired +(0018,6038) UL RETIRED_DopplerSampleVolumeXPositionRetired 1 DICOM/retired +(0018,603A) UL RETIRED_DopplerSampleVolumeYPositionRetired 1 DICOM/retired +(0018,603C) UL RETIRED_TMLinePositionX0Retired 1 DICOM/retired +(0018,603E) UL RETIRED_TMLinePositionY0Retired 1 DICOM/retired +(0018,6040) UL RETIRED_TMLinePositionX1Retired 1 DICOM/retired +(0018,6042) UL RETIRED_TMLinePositionY1Retired 1 DICOM/retired +(0018,9096) FD RETIRED_ParallelReductionFactorInPlaneRetired 1 DICOM/retired +(0018,9166) CS RETIRED_BulkMotionStatus 1 DICOM/retired +(0018,9195) FD RETIRED_ChemicalShiftMinimumIntegrationLimitInHz 1 DICOM/retired +(0018,9196) FD RETIRED_ChemicalShiftMaximumIntegrationLimitInHz 1 DICOM/retired +(0020,0014) IS RETIRED_IsotopeNumber 1 DICOM/retired +(0020,0015) IS RETIRED_PhaseNumber 1 DICOM/retired +(0020,0016) IS RETIRED_IntervalNumber 1 DICOM/retired +(0020,0017) IS RETIRED_TimeSlotNumber 1 DICOM/retired +(0020,0018) IS RETIRED_AngleNumber 1 DICOM/retired +(0020,0022) IS RETIRED_OverlayNumber 1 DICOM/retired +(0020,0024) IS RETIRED_CurveNumber 1 DICOM/retired +(0020,0026) IS RETIRED_LUTNumber 1 DICOM/retired +(0020,0030) DS RETIRED_ImagePosition 3 DICOM/retired +(0020,0035) DS RETIRED_ImageOrientation 6 DICOM/retired +(0020,0050) DS RETIRED_Location 1 DICOM/retired +(0020,0070) LO RETIRED_ImageGeometryType 1 DICOM/retired +(0020,0080) CS RETIRED_MaskingImage 1-n DICOM/retired +(0020,00AA) IS RETIRED_ReportNumber 1 DICOM/retired +(0020,1000) IS RETIRED_SeriesInStudy 1 DICOM/retired +(0020,1001) IS RETIRED_AcquisitionsInSeries 1 DICOM/retired +(0020,1003) IS RETIRED_ImagesInSeries 1 DICOM/retired +(0020,1004) IS RETIRED_AcquisitionsInStudy 1 DICOM/retired +(0020,1005) IS RETIRED_ImagesInStudy 1 DICOM/retired +(0020,1020) LO RETIRED_Reference 1-n DICOM/retired +(0020,1070) IS RETIRED_OtherStudyNumbers 1-n DICOM/retired +(0020,3100-31FF) CS RETIRED_SourceImageIDs 1-n DICOM/retired +(0020,3401) CS RETIRED_ModifyingDeviceID 1 DICOM/retired +(0020,3402) CS RETIRED_ModifiedImageID 1 DICOM/retired +(0020,3403) DA RETIRED_ModifiedImageDate 1 DICOM/retired +(0020,3404) LO RETIRED_ModifyingDeviceManufacturer 1 DICOM/retired +(0020,3405) TM RETIRED_ModifiedImageTime 1 DICOM/retired +(0020,3406) LO RETIRED_ModifiedImageDescription 1 DICOM/retired +(0020,5000) AT RETIRED_OriginalImageIdentification 1-n DICOM/retired +(0020,5002) LO RETIRED_OriginalImageIdentificationNomenclature 1-n DICOM/retired +(0022,1094) LO RETIRED_LensConstantDescription 1 DICOM/retired +(0022,1153) SQ RETIRED_OphthalmicAxialLengthAcquisitionMethodCodeSequence 1 DICOM/retired +(0022,1265) SQ RETIRED_OphthalmicAxialLengthQualityMetricTypeCodeSequence 1 DICOM/retired +(0022,1273) LO RETIRED_OphthalmicAxialLengthQualityMetricTypeDescription 1 DICOM/retired +(0028,0005) US RETIRED_ImageDimensions 1 DICOM/retired +(0028,0012) US RETIRED_Planes 1 DICOM/retired +(0028,0040) CS RETIRED_ImageFormat 1 DICOM/retired +(0028,0050) LO RETIRED_ManipulatedImage 1-n DICOM/retired +(0028,005F) LO RETIRED_CompressionRecognitionCode 1 DICOM/retired +(0028,0060) CS RETIRED_CompressionCode 1 DICOM/retired +(0028,0061) SH RETIRED_CompressionOriginator 1 DICOM/retired +(0028,0062) LO RETIRED_CompressionLabel 1 DICOM/retired +(0028,0063) SH RETIRED_CompressionDescription 1 DICOM/retired +(0028,0065) CS RETIRED_CompressionSequence 1-n DICOM/retired +(0028,0066) AT RETIRED_CompressionStepPointers 1-n DICOM/retired +(0028,0068) US RETIRED_RepeatInterval 1 DICOM/retired +(0028,0069) US RETIRED_BitsGrouped 1 DICOM/retired +(0028,0070) US RETIRED_PerimeterTable 1-n DICOM/retired +(0028,0071) xs RETIRED_PerimeterValue 1 DICOM/retired +(0028,0080) US RETIRED_PredictorRows 1 DICOM/retired +(0028,0081) US RETIRED_PredictorColumns 1 DICOM/retired +(0028,0082) US RETIRED_PredictorConstants 1-n DICOM/retired +(0028,0090) CS RETIRED_BlockedPixels 1 DICOM/retired +(0028,0091) US RETIRED_BlockRows 1 DICOM/retired +(0028,0092) US RETIRED_BlockColumns 1 DICOM/retired +(0028,0093) US RETIRED_RowOverlap 1 DICOM/retired +(0028,0094) US RETIRED_ColumnOverlap 1 DICOM/retired +(0028,0104) xs RETIRED_SmallestValidPixelValue 1 DICOM/retired +(0028,0105) xs RETIRED_LargestValidPixelValue 1 DICOM/retired +(0028,0110) xs RETIRED_SmallestImagePixelValueInPlane 1 DICOM/retired +(0028,0111) xs RETIRED_LargestImagePixelValueInPlane 1 DICOM/retired +(0028,0200) US RETIRED_ImageLocation 1 DICOM/retired +(0028,0400) LO RETIRED_TransformLabel 1 DICOM/retired +(0028,0401) LO RETIRED_TransformVersionNumber 1 DICOM/retired +(0028,0402) US RETIRED_NumberOfTransformSteps 1 DICOM/retired +(0028,0403) LO RETIRED_SequenceOfCompressedData 1-n DICOM/retired +(0028,0404) AT RETIRED_DetailsOfCoefficients 1-n DICOM/retired +# according to the DICOM standard, the following 4 attributes +# should have a tag in the range of (0028,04x1) to (0028,04x3) +(0028,0410) US RETIRED_RowsForNthOrderCoefficients 1 DICOM/retired +(0028,0411) US RETIRED_ColumnsForNthOrderCoefficients 1 DICOM/retired +(0028,0412) LO RETIRED_CoefficientCoding 1-n DICOM/retired +(0028,0413) AT RETIRED_CoefficientCodingPointers 1-n DICOM/retired +(0028,0700) LO RETIRED_DCTLabel 1 DICOM/retired +(0028,0701) CS RETIRED_DataBlockDescription 1-n DICOM/retired +(0028,0702) AT RETIRED_DataBlock 1-n DICOM/retired +(0028,0710) US RETIRED_NormalizationFactorFormat 1 DICOM/retired +(0028,0720) US RETIRED_ZonalMapNumberFormat 1 DICOM/retired +(0028,0721) AT RETIRED_ZonalMapLocation 1-n DICOM/retired +(0028,0722) US RETIRED_ZonalMapFormat 1 DICOM/retired +(0028,0730) US RETIRED_AdaptiveMapFormat 1 DICOM/retired +(0028,0740) US RETIRED_CodeNumberFormat 1 DICOM/retired +# according to the DICOM standard, the following 5 attributes +# should have a tag in the range of (0028,08x0) to (0028,08x8) +(0028,0800) CS RETIRED_CodeLabel 1-n DICOM/retired +(0028,0802) US RETIRED_NumberOfTables 1 DICOM/retired +(0028,0803) AT RETIRED_CodeTableLocation 1-n DICOM/retired +(0028,0804) US RETIRED_BitsForCodeWord 1 DICOM/retired +(0028,0808) AT RETIRED_ImageDataLocation 1-n DICOM/retired +(0028,1080) CS RETIRED_GrayScale 1 DICOM/retired +(0028,1100) xs RETIRED_GrayLookupTableDescriptor 3 DICOM/retired +(0028,1111) xs RETIRED_LargeRedPaletteColorLookupTableDescriptor 4 DICOM/retired +(0028,1112) xs RETIRED_LargeGreenPaletteColorLookupTableDescriptor 4 DICOM/retired +(0028,1113) xs RETIRED_LargeBluePaletteColorLookupTableDescriptor 4 DICOM/retired +(0028,1200) lt RETIRED_GrayLookupTableData 1-n DICOM/retired +(0028,1211) OW RETIRED_LargeRedPaletteColorLookupTableData 1 DICOM/retired +(0028,1212) OW RETIRED_LargeGreenPaletteColorLookupTableData 1 DICOM/retired +(0028,1213) OW RETIRED_LargeBluePaletteColorLookupTableData 1 DICOM/retired +(0028,1214) UI RETIRED_LargePaletteColorLookupTableUID 1 DICOM/retired +(0028,4000) LT RETIRED_ImagePresentationComments 1 DICOM/retired +(0028,5000) SQ RETIRED_BiPlaneAcquisitionSequence 1 DICOM/retired +(0028,6030) US RETIRED_MaskPointers 1-n DICOM/retired +(0028,9099) US RETIRED_LargestMonochromePixelValue 1 DICOM/retired +(0032,000A) CS RETIRED_StudyStatusID 1 DICOM/retired +(0032,000C) CS RETIRED_StudyPriorityID 1 DICOM/retired +(0032,0012) LO RETIRED_StudyIDIssuer 1 DICOM/retired +(0032,0032) DA RETIRED_StudyVerifiedDate 1 DICOM/retired +(0032,0033) TM RETIRED_StudyVerifiedTime 1 DICOM/retired +(0032,0034) DA RETIRED_StudyReadDate 1 DICOM/retired +(0032,0035) TM RETIRED_StudyReadTime 1 DICOM/retired +(0032,1000) DA RETIRED_ScheduledStudyStartDate 1 DICOM/retired +(0032,1001) TM RETIRED_ScheduledStudyStartTime 1 DICOM/retired +(0032,1010) DA RETIRED_ScheduledStudyStopDate 1 DICOM/retired +(0032,1011) TM RETIRED_ScheduledStudyStopTime 1 DICOM/retired +(0032,1020) LO RETIRED_ScheduledStudyLocation 1 DICOM/retired +(0032,1021) AE RETIRED_ScheduledStudyLocationAETitle 1-n DICOM/retired +(0032,1030) LO RETIRED_ReasonForStudy 1 DICOM/retired +(0032,1040) DA RETIRED_StudyArrivalDate 1 DICOM/retired +(0032,1041) TM RETIRED_StudyArrivalTime 1 DICOM/retired +(0032,1050) DA RETIRED_StudyCompletionDate 1 DICOM/retired +(0032,1051) TM RETIRED_StudyCompletionTime 1 DICOM/retired +(0032,1055) CS RETIRED_StudyComponentStatusID 1 DICOM/retired +(0032,4000) LT RETIRED_StudyComments 1 DICOM/retired +(0038,0011) LO RETIRED_IssuerOfAdmissionID 1 DICOM/retired +(0038,001A) DA RETIRED_ScheduledAdmissionDate 1 DICOM/retired +(0038,001B) TM RETIRED_ScheduledAdmissionTime 1 DICOM/retired +(0038,001C) DA RETIRED_ScheduledDischargeDate 1 DICOM/retired +(0038,001D) TM RETIRED_ScheduledDischargeTime 1 DICOM/retired +(0038,001E) LO RETIRED_ScheduledPatientInstitutionResidence 1 DICOM/retired +(0038,0030) DA RETIRED_DischargeDate 1 DICOM/retired +(0038,0032) TM RETIRED_DischargeTime 1 DICOM/retired +(0038,0040) LO RETIRED_DischargeDiagnosisDescription 1 DICOM/retired +(0038,0044) SQ RETIRED_DischargeDiagnosisCodeSequence 1 DICOM/retired +(0038,0061) LO RETIRED_IssuerOfServiceEpisodeID 1 DICOM/retired +(0040,0307) DS RETIRED_DistanceSourceToSupport 1 DICOM/retired +(0040,0330) SQ RETIRED_ReferencedProcedureStepSequence 1 DICOM/retired +(0040,050A) LO RETIRED_SpecimenAccessionNumber 1 DICOM/retired +(0040,0550) SQ RETIRED_SpecimenSequence 1 DICOM/retired +(0040,0552) SQ RETIRED_SpecimenDescriptionSequenceTrial 1 DICOM/retired +(0040,0553) ST RETIRED_SpecimenDescriptionTrial 1 DICOM/retired +(0040,06FA) LO RETIRED_SlideIdentifier 1 DICOM/retired +(0040,08D8) SQ RETIRED_PixelSpacingSequence 1 DICOM/retired +(0040,08DA) SQ RETIRED_CoordinateSystemAxisCodeSequence 1 DICOM/retired +(0040,09F8) SQ RETIRED_VitalStainCodeSequenceTrial 1 DICOM/retired +(0040,1006) SH RETIRED_PlacerOrderNumberProcedure 1 DICOM/retired +(0040,1007) SH RETIRED_FillerOrderNumberProcedure 1 DICOM/retired +(0040,1060) LO RETIRED_RequestedProcedureDescriptionTrial 1 DICOM/retired +(0040,2001) LO RETIRED_ReasonForTheImagingServiceRequest 1 DICOM/retired +(0040,2006) SH RETIRED_PlacerOrderNumberImagingServiceRequestRetired 1 DICOM/retired +(0040,2007) SH RETIRED_FillerOrderNumberImagingServiceRequestRetired 1 DICOM/retired +(0040,4001) CS RETIRED_GeneralPurposeScheduledProcedureStepStatus 1 DICOM/retired +(0040,4002) CS RETIRED_GeneralPurposePerformedProcedureStepStatus 1 DICOM/retired +(0040,4003) CS RETIRED_GeneralPurposeScheduledProcedureStepPriority 1 DICOM/retired +(0040,4004) SQ RETIRED_ScheduledProcessingApplicationsCodeSequence 1 DICOM/retired +(0040,4006) CS RETIRED_MultipleCopiesFlag 1 DICOM/retired +(0040,4015) SQ RETIRED_ResultingGeneralPurposePerformedProcedureStepsSequence 1 DICOM/retired +(0040,4016) SQ RETIRED_ReferencedGeneralPurposeScheduledProcedureStepSequence 1 DICOM/retired +(0040,4022) SQ RETIRED_RelevantInformationSequence 1 DICOM/retired +(0040,4023) UI RETIRED_ReferencedGeneralPurposeScheduledProcedureStepTransactionUID 1 DICOM/retired +(0040,4031) SQ RETIRED_RequestedSubsequentWorkitemCodeSequence 1 DICOM/retired +(0040,4032) SQ RETIRED_NonDICOMOutputCodeSequence 1 DICOM/retired +(0040,A007) CS RETIRED_FindingsFlagTrial 1 DICOM/retired +(0040,A020) SQ RETIRED_FindingsSequenceTrial 1 DICOM/retired +(0040,A021) UI RETIRED_FindingsGroupUIDTrial 1 DICOM/retired +(0040,A022) UI RETIRED_ReferencedFindingsGroupUIDTrial 1 DICOM/retired +(0040,A023) DA RETIRED_FindingsGroupRecordingDateTrial 1 DICOM/retired +(0040,A024) TM RETIRED_FindingsGroupRecordingTimeTrial 1 DICOM/retired +(0040,A026) SQ RETIRED_FindingsSourceCategoryCodeSequenceTrial 1 DICOM/retired +(0040,A028) SQ RETIRED_DocumentingOrganizationIdentifierCodeSequenceTrial 1 DICOM/retired +(0040,A047) LO RETIRED_MeasurementPrecisionDescriptionTrial 1 DICOM/retired +(0040,A057) CS RETIRED_UrgencyOrPriorityAlertsTrial 1-n DICOM/retired +(0040,A060) LO RETIRED_SequencingIndicatorTrial 1 DICOM/retired +(0040,A066) SQ RETIRED_DocumentIdentifierCodeSequenceTrial 1 DICOM/retired +(0040,A067) PN RETIRED_DocumentAuthorTrial 1 DICOM/retired +(0040,A068) SQ RETIRED_DocumentAuthorIdentifierCodeSequenceTrial 1 DICOM/retired +(0040,A070) SQ RETIRED_IdentifierCodeSequenceTrial 1 DICOM/retired +(0040,A074) OB RETIRED_ObjectBinaryIdentifierTrial 1 DICOM/retired +(0040,A076) SQ RETIRED_DocumentingObserverIdentifierCodeSequenceTrial 1 DICOM/retired +(0040,A085) SQ RETIRED_ProcedureIdentifierCodeSequenceTrial 1 DICOM/retired +(0040,A089) OB RETIRED_ObjectDirectoryBinaryIdentifierTrial 1 DICOM/retired +(0040,A090) SQ RETIRED_EquivalentCDADocumentSequence 1 DICOM/retired +(0040,A110) DA RETIRED_DateOfDocumentOrVerbalTransactionTrial 1 DICOM/retired +(0040,A112) TM RETIRED_TimeOfDocumentCreationOrVerbalTransactionTrial 1 DICOM/retired +(0040,A125) CS RETIRED_ReportStatusIDTrial 2 DICOM/retired +(0040,A167) SQ RETIRED_ObservationCategoryCodeSequenceTrial 1 DICOM/retired +(0040,A16A) ST RETIRED_BibliographicCitationTrial 1 DICOM/retired +# the following attribute is defined as SQ in the DICOM standard, +# it was defined as CS in Supplement 23 (frozen draft) from 1997. +#(0040,A170) CS RETIRED_ObservationClassTrial 1 DICOM/retired +(0040,A172) UI RETIRED_ReferencedObservationUIDTrial 1 DICOM/retired +(0040,A173) CS RETIRED_ReferencedObservationClassTrial 1 DICOM/retired +(0040,A174) CS RETIRED_ReferencedObjectObservationClassTrial 1 DICOM/retired +(0040,A192) DA RETIRED_ObservationDateTrial 1 DICOM/retired +(0040,A193) TM RETIRED_ObservationTimeTrial 1 DICOM/retired +(0040,A194) CS RETIRED_MeasurementAutomationTrial 1 DICOM/retired +(0040,A224) ST RETIRED_IdentificationDescriptionTrial 1 DICOM/retired +(0040,A290) CS RETIRED_CoordinatesSetGeometricTypeTrial 1 DICOM/retired +(0040,A296) SQ RETIRED_AlgorithmCodeSequenceTrial 1 DICOM/retired +(0040,A297) ST RETIRED_AlgorithmDescriptionTrial 1 DICOM/retired +(0040,A29A) SL RETIRED_PixelCoordinatesSetTrial 2-2n DICOM/retired +(0040,A307) PN RETIRED_CurrentObserverTrial 1 DICOM/retired +(0040,A313) SQ RETIRED_ReferencedAccessionSequenceTrial 1 DICOM/retired +(0040,A33A) ST RETIRED_ReportStatusCommentTrial 1 DICOM/retired +(0040,A340) SQ RETIRED_ProcedureContextSequenceTrial 1 DICOM/retired +(0040,A352) PN RETIRED_VerbalSourceTrial 1 DICOM/retired +(0040,A353) ST RETIRED_AddressTrial 1 DICOM/retired +(0040,A354) LO RETIRED_TelephoneNumberTrial 1 DICOM/retired +(0040,A358) SQ RETIRED_VerbalSourceIdentifierCodeSequenceTrial 1 DICOM/retired +(0040,A380) SQ RETIRED_ReportDetailSequenceTrial 1 DICOM/retired +(0040,A402) UI RETIRED_ObservationSubjectUIDTrial 1 DICOM/retired +(0040,A403) CS RETIRED_ObservationSubjectClassTrial 1 DICOM/retired +(0040,A404) SQ RETIRED_ObservationSubjectTypeCodeSequenceTrial 1 DICOM/retired +(0040,A600) CS RETIRED_ObservationSubjectContextFlagTrial 1 DICOM/retired +(0040,A601) CS RETIRED_ObserverContextFlagTrial 1 DICOM/retired +(0040,A603) CS RETIRED_ProcedureContextFlagTrial 1 DICOM/retired +(0040,A731) SQ RETIRED_RelationshipSequenceTrial 1 DICOM/retired +(0040,A732) SQ RETIRED_RelationshipTypeCodeSequenceTrial 1 DICOM/retired +(0040,A744) SQ RETIRED_LanguageCodeSequenceTrial 1 DICOM/retired +(0040,A992) ST RETIRED_UniformResourceLocatorTrial 1 DICOM/retired +(0040,DB06) DT RETIRED_TemplateVersion 1 DICOM/retired +(0040,DB07) DT RETIRED_TemplateLocalVersion 1 DICOM/retired +(0040,DB0B) CS RETIRED_TemplateExtensionFlag 1 DICOM/retired +(0040,DB0C) UI RETIRED_TemplateExtensionOrganizationUID 1 DICOM/retired +(0040,DB0D) UI RETIRED_TemplateExtensionCreatorUID 1 DICOM/retired +(0054,1400) CS RETIRED_CountsIncluded 1-n DICOM/retired +(0054,1401) CS RETIRED_DeadTimeCorrectionFlag 1 DICOM/retired +(0070,0040) IS RETIRED_ImageRotationRetired 1 DICOM/retired +(0070,0050) US RETIRED_DisplayedAreaTopLeftHandCornerTrial 2 DICOM/retired +(0070,0051) US RETIRED_DisplayedAreaBottomRightHandCornerTrial 2 DICOM/retired +(0070,0067) US RETIRED_GraphicLayerRecommendedDisplayRGBValue 3 DICOM/retired +(0074,1024) IS RETIRED_BeamOrderIndexTrial 1 DICOM/retired +(0074,1038) DS RETIRED_DoubleExposureMetersetTrial 1 DICOM/retired +(0074,103A) DS RETIRED_DoubleExposureFieldDeltaTrial 4 DICOM/retired +(0074,1220) SQ RETIRED_RelatedProcedureStepSequence 1 DICOM/retired +(0074,1222) LO RETIRED_ProcedureStepRelationshipType 1 DICOM/retired +(0088,0904) LO RETIRED_TopicTitle 1 DICOM/retired +(0088,0906) ST RETIRED_TopicSubject 1 DICOM/retired +(0088,0910) LO RETIRED_TopicAuthor 1 DICOM/retired +(0088,0912) LO RETIRED_TopicKeywords 1-32 DICOM/retired +# according to the DICOM standard, the following 6 attributes +# should have a tag in the range of (1000,xxx0) to (1000,xxx5) +(1000,0010) US RETIRED_EscapeTriplet 3 DICOM/retired +(1000,0011) US RETIRED_RunLengthTriplet 3 DICOM/retired +(1000,0012) US RETIRED_HuffmanTableSize 1 DICOM/retired +(1000,0013) US RETIRED_HuffmanTableTriplet 3 DICOM/retired +(1000,0014) US RETIRED_ShiftTableSize 1 DICOM/retired +(1000,0015) US RETIRED_ShiftTableTriplet 3 DICOM/retired +# according to the DICOM standard, the following attribute +# should have the tag (1010,xxxx) where "x" is "0" to "F" +(1010,0004) US RETIRED_ZonalMap 1-n DICOM/retired +(2000,0062) CS RETIRED_ColorImagePrintingFlag 1 DICOM/retired +(2000,0063) CS RETIRED_CollationFlag 1 DICOM/retired +(2000,0065) CS RETIRED_AnnotationFlag 1 DICOM/retired +(2000,0067) CS RETIRED_ImageOverlayFlag 1 DICOM/retired +(2000,0069) CS RETIRED_PresentationLUTFlag 1 DICOM/retired +(2000,006A) CS RETIRED_ImageBoxPresentationLUTFlag 1 DICOM/retired +(2000,0510) SQ RETIRED_ReferencedStoredPrintSequence 1 DICOM/retired +(2020,0130) SQ RETIRED_ReferencedImageOverlayBoxSequence 1 DICOM/retired +(2020,0140) SQ RETIRED_ReferencedVOILUTBoxSequence 1 DICOM/retired +(2040,0010) SQ RETIRED_ReferencedOverlayPlaneSequence 1 DICOM/retired +(2040,0011) US RETIRED_ReferencedOverlayPlaneGroups 1-99 DICOM/retired +(2040,0020) SQ RETIRED_OverlayPixelDataSequence 1 DICOM/retired +(2040,0060) CS RETIRED_OverlayMagnificationType 1 DICOM/retired +(2040,0070) CS RETIRED_OverlaySmoothingType 1 DICOM/retired +(2040,0072) CS RETIRED_OverlayOrImageMagnification 1 DICOM/retired +(2040,0074) US RETIRED_MagnifyToNumberOfColumns 1 DICOM/retired +(2040,0080) CS RETIRED_OverlayForegroundDensity 1 DICOM/retired +(2040,0082) CS RETIRED_OverlayBackgroundDensity 1 DICOM/retired +(2040,0090) CS RETIRED_OverlayMode 1 DICOM/retired +(2040,0100) CS RETIRED_ThresholdDensity 1 DICOM/retired +(2040,0500) SQ RETIRED_ReferencedImageBoxSequenceRetired 1 DICOM/retired +(2100,0010) SH RETIRED_PrintJobID 1 DICOM/retired +(2100,0140) AE RETIRED_DestinationAE 1 DICOM/retired +(2100,0500) SQ RETIRED_ReferencedPrintJobSequencePullStoredPrint 1 DICOM/retired +(2110,0099) SH RETIRED_PrintQueueID 1 DICOM/retired +(2120,0010) CS RETIRED_QueueStatus 1 DICOM/retired +(2120,0050) SQ RETIRED_PrintJobDescriptionSequence 1 DICOM/retired +(2120,0070) SQ RETIRED_ReferencedPrintJobSequence 1 DICOM/retired +(2130,0010) SQ RETIRED_PrintManagementCapabilitiesSequence 1 DICOM/retired +(2130,0015) SQ RETIRED_PrinterCharacteristicsSequence 1 DICOM/retired +(2130,0030) SQ RETIRED_FilmBoxContentSequence 1 DICOM/retired +(2130,0040) SQ RETIRED_ImageBoxContentSequence 1 DICOM/retired +(2130,0050) SQ RETIRED_AnnotationContentSequence 1 DICOM/retired +(2130,0060) SQ RETIRED_ImageOverlayBoxContentSequence 1 DICOM/retired +(2130,0080) SQ RETIRED_PresentationLUTContentSequence 1 DICOM/retired +(2130,00A0) SQ RETIRED_ProposedStudySequence 1 DICOM/retired +(2130,00C0) SQ RETIRED_OriginalImageSequence 1 DICOM/retired +(3006,00C0) SQ RETIRED_FrameOfReferenceRelationshipSequence 1 DICOM/retired +(3006,00C2) UI RETIRED_RelatedFrameOfReferenceUID 1 DICOM/retired +(3006,00C4) CS RETIRED_FrameOfReferenceTransformationType 1 DICOM/retired +(300A,0088) FL RETIRED_BeamDosePointDepth 1 DICOM/retired +(300A,0089) FL RETIRED_BeamDosePointEquivalentDepth 1 DICOM/retired +(300A,008A) FL RETIRED_BeamDosePointSSD 1 DICOM/retired +(4000,0010) LT RETIRED_Arbitrary 1 DICOM/retired +(4000,4000) LT RETIRED_TextComments 1 DICOM/retired +(4008,0040) SH RETIRED_ResultsID 1 DICOM/retired +(4008,0042) LO RETIRED_ResultsIDIssuer 1 DICOM/retired +(4008,0050) SQ RETIRED_ReferencedInterpretationSequence 1 DICOM/retired +(4008,00FF) CS RETIRED_ReportProductionStatusTrial 1 DICOM/retired +(4008,0100) DA RETIRED_InterpretationRecordedDate 1 DICOM/retired +(4008,0101) TM RETIRED_InterpretationRecordedTime 1 DICOM/retired +(4008,0102) PN RETIRED_InterpretationRecorder 1 DICOM/retired +(4008,0103) LO RETIRED_ReferenceToRecordedSound 1 DICOM/retired +(4008,0108) DA RETIRED_InterpretationTranscriptionDate 1 DICOM/retired +(4008,0109) TM RETIRED_InterpretationTranscriptionTime 1 DICOM/retired +(4008,010A) PN RETIRED_InterpretationTranscriber 1 DICOM/retired +(4008,010B) ST RETIRED_InterpretationText 1 DICOM/retired +(4008,010C) PN RETIRED_InterpretationAuthor 1 DICOM/retired +(4008,0111) SQ RETIRED_InterpretationApproverSequence 1 DICOM/retired +(4008,0112) DA RETIRED_InterpretationApprovalDate 1 DICOM/retired +(4008,0113) TM RETIRED_InterpretationApprovalTime 1 DICOM/retired +(4008,0114) PN RETIRED_PhysicianApprovingInterpretation 1 DICOM/retired +(4008,0115) LT RETIRED_InterpretationDiagnosisDescription 1 DICOM/retired +(4008,0117) SQ RETIRED_InterpretationDiagnosisCodeSequence 1 DICOM/retired +(4008,0118) SQ RETIRED_ResultsDistributionListSequence 1 DICOM/retired +(4008,0119) PN RETIRED_DistributionName 1 DICOM/retired +(4008,011A) LO RETIRED_DistributionAddress 1 DICOM/retired +(4008,0200) SH RETIRED_InterpretationID 1 DICOM/retired +(4008,0202) LO RETIRED_InterpretationIDIssuer 1 DICOM/retired +(4008,0210) CS RETIRED_InterpretationTypeID 1 DICOM/retired +(4008,0212) CS RETIRED_InterpretationStatusID 1 DICOM/retired +(4008,0300) ST RETIRED_Impressions 1 DICOM/retired +(4008,4000) ST RETIRED_ResultsComments 1 DICOM/retired +(5000-50FF,0005) US RETIRED_CurveDimensions 1 DICOM/retired +(5000-50FF,0010) US RETIRED_NumberOfPoints 1 DICOM/retired +(5000-50FF,0020) CS RETIRED_TypeOfData 1 DICOM/retired +(5000-50FF,0022) LO RETIRED_CurveDescription 1 DICOM/retired +(5000-50FF,0030) SH RETIRED_AxisUnits 1-n DICOM/retired +(5000-50FF,0040) SH RETIRED_AxisLabels 1-n DICOM/retired +(5000-50FF,0103) US RETIRED_DataValueRepresentation 1 DICOM/retired +(5000-50FF,0104) US RETIRED_MinimumCoordinateValue 1-n DICOM/retired +(5000-50FF,0105) US RETIRED_MaximumCoordinateValue 1-n DICOM/retired +(5000-50FF,0106) SH RETIRED_CurveRange 1-n DICOM/retired +(5000-50FF,0110) US RETIRED_CurveDataDescriptor 1-n DICOM/retired +(5000-50FF,0112) US RETIRED_CoordinateStartValue 1-n DICOM/retired +(5000-50FF,0114) US RETIRED_CoordinateStepValue 1-n DICOM/retired +(5000-50FF,1001) CS RETIRED_CurveActivationLayer 1 DICOM/retired +(5000-50FF,2000) US RETIRED_AudioType 1 DICOM/retired +(5000-50FF,2002) US RETIRED_AudioSampleFormat 1 DICOM/retired +(5000-50FF,2004) US RETIRED_NumberOfChannels 1 DICOM/retired +(5000-50FF,2006) UL RETIRED_NumberOfSamples 1 DICOM/retired +(5000-50FF,2008) UL RETIRED_SampleRate 1 DICOM/retired +(5000-50FF,200A) UL RETIRED_TotalTime 1 DICOM/retired +(5000-50FF,200C) ox RETIRED_AudioSampleData 1 DICOM/retired +(5000-50FF,200E) LT RETIRED_AudioComments 1 DICOM/retired +(5000-50FF,2500) LO RETIRED_CurveLabel 1 DICOM/retired +(5000-50FF,2600) SQ RETIRED_CurveReferencedOverlaySequence 1 DICOM/retired +(5000-50FF,2610) US RETIRED_CurveReferencedOverlayGroup 1 DICOM/retired +(5000-50FF,3000) ox RETIRED_CurveData 1 DICOM/retired +(6000-60FF,0012) US RETIRED_OverlayPlanes 1 DICOM/retired +(6000-60FF,0052) US RETIRED_OverlayPlaneOrigin 1 DICOM/retired +(6000-60FF,0060) CS RETIRED_OverlayCompressionCode 1 DICOM/retired +(6000-60FF,0061) SH RETIRED_OverlayCompressionOriginator 1 DICOM/retired +(6000-60FF,0062) SH RETIRED_OverlayCompressionLabel 1 DICOM/retired +(6000-60FF,0063) CS RETIRED_OverlayCompressionDescription 1 DICOM/retired +(6000-60FF,0066) AT RETIRED_OverlayCompressionStepPointers 1-n DICOM/retired +(6000-60FF,0068) US RETIRED_OverlayRepeatInterval 1 DICOM/retired +(6000-60FF,0069) US RETIRED_OverlayBitsGrouped 1 DICOM/retired +(6000-60FF,0110) CS RETIRED_OverlayFormat 1 DICOM/retired +(6000-60FF,0200) US RETIRED_OverlayLocation 1 DICOM/retired +(6000-60FF,0800) CS RETIRED_OverlayCodeLabel 1-n DICOM/retired +(6000-60FF,0802) US RETIRED_OverlayNumberOfTables 1 DICOM/retired +(6000-60FF,0803) AT RETIRED_OverlayCodeTableLocation 1-n DICOM/retired +(6000-60FF,0804) US RETIRED_OverlayBitsForCodeWord 1 DICOM/retired +(6000-60FF,1100) US RETIRED_OverlayDescriptorGray 1 DICOM/retired +(6000-60FF,1101) US RETIRED_OverlayDescriptorRed 1 DICOM/retired +(6000-60FF,1102) US RETIRED_OverlayDescriptorGreen 1 DICOM/retired +(6000-60FF,1103) US RETIRED_OverlayDescriptorBlue 1 DICOM/retired +(6000-60FF,1200) US RETIRED_OverlaysGray 1-n DICOM/retired +(6000-60FF,1201) US RETIRED_OverlaysRed 1-n DICOM/retired +(6000-60FF,1202) US RETIRED_OverlaysGreen 1-n DICOM/retired +(6000-60FF,1203) US RETIRED_OverlaysBlue 1-n DICOM/retired +(6000-60FF,4000) LT RETIRED_OverlayComments 1 DICOM/retired +(7FE0,0020) OW RETIRED_CoefficientsSDVN 1 DICOM/retired +(7FE0,0030) OW RETIRED_CoefficientsSDHN 1 DICOM/retired +(7FE0,0040) OW RETIRED_CoefficientsSDDN 1 DICOM/retired +(7F00-7FFF,0010) ox RETIRED_VariablePixelData 1 DICOM/retired +(7F00-7FFF,0011) US RETIRED_VariableNextDataGroup 1 DICOM/retired +(7F00-7FFF,0020) OW RETIRED_VariableCoefficientsSDVN 1 DICOM/retired +(7F00-7FFF,0030) OW RETIRED_VariableCoefficientsSDHN 1 DICOM/retired +(7F00-7FFF,0040) OW RETIRED_VariableCoefficientsSDDN 1 DICOM/retired +# +# end of dicom.dic +# diff --git a/dcmdata/data/diconde.dic b/dcmdata/data/diconde.dic new file mode 100644 index 00000000..0af79562 --- /dev/null +++ b/dcmdata/data/diconde.dic @@ -0,0 +1,173 @@ +# +# Copyright (C) 2010-2014, OFFIS e.V. +# All rights reserved. See COPYRIGHT file for details. +# +# This software and supporting documentation were developed by +# +# OFFIS e.V. +# R&D Division Health +# Escherweg 2 +# D-26121 Oldenburg, Germany +# +# +# Module: dcmdata +# +# Author: Joerg Riesmeier +# +# Purpose: DICONDE data dictionary for the DICOM toolkit DCMTK +# +# +# Dictionary of Digital Imaging and Communication in Nondestructive +# Evaluation (DICONDE) tags. Please note that the file "dicom.dic" +# contains the non-private DICONDE tag definitions since they are now +# official part of the DICOM standard (beginning with 2011 edition). +# +# Each line represents an entry in the data dictionary. Each line +# has 5 fields (Tag, VR, Name, VM, Version). Entries need not be +# in ascending tag order. +# +# Entries may override existing entries. +# +# Each field must be separated by a single tab. +# The tag value may take one of three forms: +# (gggg,eeee) +# (gggg,"CREATOR",ee) +# (gggg,"CREATOR",eeee) [eeee >= 1000] +# The first form represents a standard tag with group and element number. +# The second form describes a private tag that may be used with different +# element numbers as reserved by the private creator element. The third +# form describes a private tag that may only occur with a certain fixed +# element number. In all cases, the tag values must be in hexadecimal. +# +# Comments have a '#' at the beginning of the line. +# +# Tag VR Name VM Version +# +(0008,0080) LO CompanyName 1 DICONDE10 +(0008,0081) ST CompanyAddress 1 DICONDE10 +(0008,0090) PN ComponentOwnerName 1 DICONDE10 +(0008,1040) LO DepartmentName 1 DICONDE10 +(0008,1048) PN InspectingCompanyName 1-n DICONDE10 +(0008,1050) PN InspectorName 1-n DICONDE10 +(0008,1060) PN CertifyingInspectorName 1-n DICONDE10 +(0010,0010) PN ComponentName 1 DICONDE10 +(0010,0020) LO ComponentIDNumber 1 DICONDE10 +(0010,0030) DA ComponentManufacturingDate 1 DICONDE10 +(0010,1000) LO OtherComponentIDs 1-n DICONDE10 +(0010,1001) PN OtherComponentNames 1-n DICONDE10 +(0010,2160) SH MaterialName 1 DICONDE10 +(0010,4000) LT ComponentNotes 1 DICONDE10 +(0018,1008) LO ScannerID 1 DICONDE10 +(0032,4000) LT ExaminationNotes 1 DICONDE10 + +(0009,"astm.org/diconde/iod/ComponentStudy",20) DA ExpiryDate 1 DICONDE10 + +(0009,"astm.org/diconde/iod/ComponentSeries",10) ST ActualEnvironmentalConditions 1 DICONDE10 +(0009,"astm.org/diconde/iod/ComponentSeries",40) ST EnvironmentalConditions 1 DICONDE10 + +(0011,"astm.org/diconde/iod/Component",23) ST CADFileFormat 1-n DICONDE10 +(0011,"astm.org/diconde/iod/Component",24) ST ComponentRefSystem 1-n DICONDE10 +(0011,"astm.org/diconde/iod/Component",25) ST ComponentManufacturingProcedure 1-n DICONDE10 +(0011,"astm.org/diconde/iod/Component",28) ST ComponentManufacturer 1-n DICONDE10 +(0011,"astm.org/diconde/iod/Component",30) DS Thickness 1-n DICONDE10 +(0011,"astm.org/diconde/iod/Component",32) DS MaterialPipeDiameter 1-n DICONDE10 +(0011,"astm.org/diconde/iod/Component",34) DS MaterialIsolationDiameter 1-n DICONDE10 +(0011,"astm.org/diconde/iod/Component",42) ST MaterialGrade 1-n DICONDE10 +(0011,"astm.org/diconde/iod/Component",44) ST MaterialPropertiesFileID 1-n DICONDE10 +(0011,"astm.org/diconde/iod/Component",45) ST MaterialPropertiesFileFormat 1-n DICONDE10 +(0011,"astm.org/diconde/iod/Component",46) LT MaterialNotes 1 DICONDE10 +(0011,"astm.org/diconde/iod/Component",50) CS Shape 1 DICONDE10 +(0011,"astm.org/diconde/iod/Component",52) CS CurvatureType 1 DICONDE10 +(0011,"astm.org/diconde/iod/Component",54) DS OuterDiameter 1 DICONDE10 +(0011,"astm.org/diconde/iod/Component",56) DS InnerDiameter 1 DICONDE10 + +(0021,"astm.org/diconde/iod/NdeIndication",02) SQ EvaluatorSequence 1 DICONDE10 +(0021,"astm.org/diconde/iod/NdeIndication",04) IS EvaluatorNumber 1 DICONDE10 +(0021,"astm.org/diconde/iod/NdeIndication",06) PN EvaluatorName 1 DICONDE10 +(0021,"astm.org/diconde/iod/NdeIndication",08) IS EvaluationAttempt 1 DICONDE10 +(0021,"astm.org/diconde/iod/NdeIndication",12) SQ IndicationSequence 1 DICONDE10 +(0021,"astm.org/diconde/iod/NdeIndication",14) IS IndicationNumber 1 DICONDE10 +(0021,"astm.org/diconde/iod/NdeIndication",16) SH IndicationLabel 1 DICONDE10 +(0021,"astm.org/diconde/iod/NdeIndication",18) ST IndicationDesription 1 DICONDE10 +(0021,"astm.org/diconde/iod/NdeIndication",1A) CS IndicationType 1-n DICONDE10 +(0021,"astm.org/diconde/iod/NdeIndication",1C) CS IndicationDisposition 1 DICONDE10 +(0021,"astm.org/diconde/iod/NdeIndication",1E) SQ IndicationROISequence 1 DICONDE10 +(0021,"astm.org/diconde/iod/NdeIndication",20) CS IndicationROIGeometricType 1 DICONDE10 +(0021,"astm.org/diconde/iod/NdeIndication",22) IS NumberOfROIContourPoints 1 DICONDE10 +(0021,"astm.org/diconde/iod/NdeIndication",24) DS IndicationROIContourData 3-3n DICONDE10 +(0021,"astm.org/diconde/iod/NdeIndication",26) CS IndicationROIContourPointUnits 3 DICONDE10 +(0021,"astm.org/diconde/iod/NdeIndication",28) IS IndicationROIDimensionality 1 DICONDE10 +(0021,"astm.org/diconde/iod/NdeIndication",30) SQ IndicationPhysicalPropertySequence 1 DICONDE10 +(0021,"astm.org/diconde/iod/NdeIndication",32) SH PropertyLabel 1 DICONDE10 +(0021,"astm.org/diconde/iod/NdeIndication",34) DS PropertyValue 1 DICONDE10 +(0021,"astm.org/diconde/iod/NdeIndication",36) CS PropertyUnits 1 DICONDE10 + +(0021,"astm.org/diconde/iod/NDEGeometry",02) IS NumberOfAxes 1 DICONDE10 +(0021,"astm.org/diconde/iod/NDEGeometry",04) SQ AxesSequence 1 DICONDE10 +(0021,"astm.org/diconde/iod/NDEGeometry",06) ST AxisDescription 1 DICONDE10 +(0021,"astm.org/diconde/iod/NDEGeometry",08) CS DataSetMapping 1 DICONDE10 +(0021,"astm.org/diconde/iod/NDEGeometry",0A) IS AxisNumber 1 DICONDE10 +(0021,"astm.org/diconde/iod/NDEGeometry",0C) CS AxisType 1 DICONDE10 +(0021,"astm.org/diconde/iod/NDEGeometry",0E) CS AxisUnits 1 DICONDE10 +(0021,"astm.org/diconde/iod/NDEGeometry",10) OB AxisValues 1 DICONDE10 +(0021,"astm.org/diconde/iod/NDEGeometry",20) SQ TransformSequence 1 DICONDE10 +(0021,"astm.org/diconde/iod/NDEGeometry",22) ST TransformDescription 1 DICONDE10 +(0021,"astm.org/diconde/iod/NDEGeometry",24) IS NumberOfAxes 1 DICONDE10 +(0021,"astm.org/diconde/iod/NDEGeometry",26) IS OrderOfAxes 1-n DICONDE10 +(0021,"astm.org/diconde/iod/NDEGeometry",28) CS TransformedAxisUnits 1 DICONDE10 +(0021,"astm.org/diconde/iod/NDEGeometry",2A) DS RotationAndScaleMatrix 1-n DICONDE10 +(0021,"astm.org/diconde/iod/NDEGeometry",2C) DS TranslationMatrix 11 DICONDE10 + +# X-ray Computed Tomography (CT) + +(0009,"astm.org/diconde/iod/NdeCTImage",02) IS LINACEnergy 1 DICONDE10_CT +(0009,"astm.org/diconde/iod/NdeCTImage",04) IS LINACOutput 1 DICONDE10_CT + +(0009,"astm.org/diconde/iod/NdeCtDetector",11) DS InternalDetectorFrameTime 1 DICONDE10_CT +(0009,"astm.org/diconde/iod/NdeCtDetector",12) DS NumberOfFramesIntegrated 1 DICONDE10_CT +(0009,"astm.org/diconde/iod/NdeCtDetector",20) SQ DetectorTemperatureSequence 1 DICONDE10_CT +(0009,"astm.org/diconde/iod/NdeCtDetector",22) DS SensorName 1 DICONDE10_CT +(0009,"astm.org/diconde/iod/NdeCtDetector",24) DS HorizontalOffset 1 DICONDE10_CT +(0009,"astm.org/diconde/iod/NdeCtDetector",26) DS VerticalOffset 1 DICONDE10_CT +(0009,"astm.org/diconde/iod/NdeCtDetector",28) DS Temperature 1 DICONDE10_CT + +(0009,"astm.org/diconde/iod/NdeCtCalibrationData",40) SQ DarkCurrentSequence 1 DICONDE10_CT +(0009,"astm.org/diconde/iod/NdeCtCalibrationData",50) ox DarkCurrentCounts 1 DICONDE10_CT +(0009,"astm.org/diconde/iod/NdeCtCalibrationData",60) SQ GainCorrectionReferenceSequence 1 DICONDE10_CT +(0009,"astm.org/diconde/iod/NdeCtCalibrationData",70) ox AirCounts 1 DICONDE10_CT +(0009,"astm.org/diconde/iod/NdeCtCalibrationData",71) DS KVUsedinGainCalibration 1 DICONDE10_CT +(0009,"astm.org/diconde/iod/NdeCtCalibrationData",72) DS MAsUsedInGainCalibration 1 DICONDE10_CT +(0009,"astm.org/diconde/iod/NdeCtCalibrationData",73) DS NumberOfFrames 1 DICONDE10_CT +(0009,"astm.org/diconde/iod/NdeCtCalibrationData",74) LO FilterMaterialUsedInGainCalibration 1 DICONDE10_CT +(0009,"astm.org/diconde/iod/NdeCtCalibrationData",75) DS FilterThicknessUsedInGainCalibration 1 DICONDE10_CT +(0009,"astm.org/diconde/iod/NdeCtCalibrationData",76) DA DateOfGainCalibration 1-n DICONDE10_CT +(0009,"astm.org/diconde/iod/NdeCtCalibrationData",77) TM TimeOfGainCalibration 1-n DICONDE10_CT +(0009,"astm.org/diconde/iod/NdeCtCalibrationData",80) OB BadPixelImage 1 DICONDE10_CT +(0009,"astm.org/diconde/iod/NdeCtCalibrationData",99) LT CalibrationNotes 1 DICONDE10_CT + +# Digital Radiographic (DR) + +(0009,"astm.org/diconde/iod/NdeDxDetector",11) DS InternalDetectorFrameTime 1 DICONDE10_DR +(0009,"astm.org/diconde/iod/NdeDxDetector",12) DS NumberOfFramesIntegrated 1 DICONDE10_DR +(0009,"astm.org/diconde/iod/NdeDxDetector",20) SQ DetectorTemperatureSequence 1 DICONDE10_DR +(0009,"astm.org/diconde/iod/NdeDxDetector",22) DS SensorName 1 DICONDE10_DR +(0009,"astm.org/diconde/iod/NdeDxDetector",24) DS HorizontalOffset 1 DICONDE10_DR +(0009,"astm.org/diconde/iod/NdeDxDetector",26) DS VerticalOffset 1 DICONDE10_DR +(0009,"astm.org/diconde/iod/NdeDxDetector",28) DS Temperature 1 DICONDE10_DR + +(0009,"astm.org/diconde/iod/NdeDxCalibrationData",40) SQ DarkCurrentSequence 1 DICONDE10_DR +(0009,"astm.org/diconde/iod/NdeDxCalibrationData",50) ox DarkCurrentCounts 1 DICONDE10_DR +(0009,"astm.org/diconde/iod/NdeDxCalibrationData",60) SQ GainCorrectionReferenceSequence 1 DICONDE10_DR +(0009,"astm.org/diconde/iod/NdeDxCalibrationData",70) ox AirCounts 1 DICONDE10_DR +(0009,"astm.org/diconde/iod/NdeDxCalibrationData",71) DS KVUsedinGainCalibration 1 DICONDE10_DR +(0009,"astm.org/diconde/iod/NdeDxCalibrationData",72) DS MAsUsedInGainCalibration 1 DICONDE10_DR +(0009,"astm.org/diconde/iod/NdeDxCalibrationData",73) DS NumberOfFrames 1 DICONDE10_DR +(0009,"astm.org/diconde/iod/NdeDxCalibrationData",74) LO FilterMaterialUsedInGainCalibration 1 DICONDE10_DR +(0009,"astm.org/diconde/iod/NdeDxCalibrationData",75) DS FilterThicknessUsedInGainCalibration 1 DICONDE10_DR +(0009,"astm.org/diconde/iod/NdeDxCalibrationData",76) DA DateOfGainCalibration 1-n DICONDE10_DR +(0009,"astm.org/diconde/iod/NdeDxCalibrationData",77) TM TimeOfGainCalibration 1-n DICONDE10_DR +(0009,"astm.org/diconde/iod/NdeDxCalibrationData",80) OB BadPixelImage 1 DICONDE10_DR +(0009,"astm.org/diconde/iod/NdeDxCalibrationData",99) LT CalibrationNotes 1 DICONDE10_DR +# +# end of diconde.dic +# diff --git a/dcmdata/data/dumppat.txt b/dcmdata/data/dumppat.txt new file mode 100644 index 00000000..1f375d46 --- /dev/null +++ b/dcmdata/data/dumppat.txt @@ -0,0 +1,4 @@ +--search PatientName +--search PatientID +--search PatientBirthDate +--search PatientSex \ No newline at end of file diff --git a/dcmdata/data/private.dic b/dcmdata/data/private.dic new file mode 100644 index 00000000..880753fa --- /dev/null +++ b/dcmdata/data/private.dic @@ -0,0 +1,3040 @@ +# +# Copyright (C) 1994-2013, OFFIS e.V. +# All rights reserved. See COPYRIGHT file for details. +# +# This software and supporting documentation were developed by +# +# OFFIS e.V. +# R&D Division Health +# Escherweg 2 +# D-26121 Oldenburg, Germany +# +# +# Module: dcmdata +# +# Author: Andrew Hewett, Marco Eichelberg, Joerg Riesmeier +# +# Purpose: +# This is the private tag DICOM data dictionary for the dcmtk class library. +# +# +# Dictionary of Private Tags +# +# This dictionary contains the private tags defined in the following +# reference documents (in alphabetical order): +# - AGFA IMPAX 6.5.x Solution conformance statement +# - Circle Cardiovascular Imaging cmr42 3.0 conformance statement +# - David Clunie's dicom3tools package, 2002-04-20 snapshot +# - Fuji CR console, 3rd release +# - Intelerad Medical Systems Inc., Image Server +# - OCULUS Pentacam 1.17 conformance statement +# - Philips Digital Diagnost 1.3 conformance statement +# - Philips Integris H, catheterization laboratory, RIS-interface +# - Philips Intera Achieva conformance statement +# - Philips MR Achieva conformance statement +# - Siemens Somatom syngo VA40B conformance statement +# - Siemens AXIOM Artis VB30 conformance statement +# - SonoWand Invite 2.1.1 conformance statement +# - Swissvision TR4000 conformance statement +# - private tags for DCMTK anonymizer tool +# +# Each line represents an entry in the data dictionary. Each line +# has 5 fields (Tag, VR, Name, VM, Version). Entries need not be +# in ascending tag order. +# +# Entries may override existing entries. +# +# Each field must be separated by a single tab. +# The tag value may take one of two forms: +# (gggg,"CREATOR",ee) +# (gggg,"CREATOR",eeee) [eeee >= 1000] +# The first form describes a private tag that may be used with different +# element numbers as reserved by the private creator element. +# The second form describes a private tag that may only occur with a +# certain fixed element number. +# In both cases, the tag values must be in hexadecimal. +# Repeating groups are represented by indicating the range +# (gggg-o-gggg,"CREATOR",ee) or (gggg-o-gggg,"CREATOR",eeee) +# where "-o-" indicates that only odd group numbers match the definition. +# The element part of the tag can also be a range. +# +# Comments have a '#' at the beginning of the line. +# +# Tag VR Name VM Version / Description +# +(0019,"1.2.840.113681",10) ST CRImageParamsCommon 1 PrivateTag +(0019,"1.2.840.113681",11) ST CRImageIPParamsSingle 1 PrivateTag +(0019,"1.2.840.113681",12) ST CRImageIPParamsLeft 1 PrivateTag +(0019,"1.2.840.113681",13) ST CRImageIPParamsRight 1 PrivateTag + +(0087,"1.2.840.113708.794.1.1.2.0",10) CS MediaType 1 PrivateTag +(0087,"1.2.840.113708.794.1.1.2.0",20) CS MediaLocation 1 PrivateTag +(0087,"1.2.840.113708.794.1.1.2.0",50) IS EstimatedRetrieveTime 1 PrivateTag + +(0009,"ACUSON",00) IS Unknown 1 PrivateTag +(0009,"ACUSON",01) IS Unknown 1 PrivateTag +(0009,"ACUSON",02) UN Unknown 1 PrivateTag +(0009,"ACUSON",03) UN Unknown 1 PrivateTag +(0009,"ACUSON",04) UN Unknown 1 PrivateTag +(0009,"ACUSON",05) UN Unknown 1 PrivateTag +(0009,"ACUSON",06) UN Unknown 1 PrivateTag +(0009,"ACUSON",07) UN Unknown 1 PrivateTag +(0009,"ACUSON",08) LT Unknown 1 PrivateTag +(0009,"ACUSON",09) LT Unknown 1 PrivateTag +(0009,"ACUSON",0a) IS Unknown 1 PrivateTag +(0009,"ACUSON",0b) IS Unknown 1 PrivateTag +(0009,"ACUSON",0c) IS Unknown 1 PrivateTag +(0009,"ACUSON",0d) IS Unknown 1 PrivateTag +(0009,"ACUSON",0e) IS Unknown 1 PrivateTag +(0009,"ACUSON",0f) UN Unknown 1 PrivateTag +(0009,"ACUSON",10) IS Unknown 1 PrivateTag +(0009,"ACUSON",11) UN Unknown 1 PrivateTag +(0009,"ACUSON",12) IS Unknown 1 PrivateTag +(0009,"ACUSON",13) IS Unknown 1 PrivateTag +(0009,"ACUSON",14) LT Unknown 1 PrivateTag +(0009,"ACUSON",15) UN Unknown 1 PrivateTag + +(0003,"AEGIS_DICOM_2.00",00) US Unknown 1-n PrivateTag +(0005,"AEGIS_DICOM_2.00",00) US Unknown 1-n PrivateTag +(0009,"AEGIS_DICOM_2.00",00) US Unknown 1-n PrivateTag +(0019,"AEGIS_DICOM_2.00",00) US Unknown 1-n PrivateTag +(0029,"AEGIS_DICOM_2.00",00) US Unknown 1-n PrivateTag +(1369,"AEGIS_DICOM_2.00",00) US Unknown 1-n PrivateTag + +(0009,"AGFA",10) LO Unknown 1 PrivateTag +(0009,"AGFA",11) LO Unknown 1 PrivateTag +(0009,"AGFA",13) LO Unknown 1 PrivateTag +(0009,"AGFA",14) LO Unknown 1 PrivateTag +(0009,"AGFA",15) LO Unknown 1 PrivateTag + +(0031,"AGFA PACS Archive Mirroring 1.0",00) CS StudyStatus 1 PrivateTag +(0031,"AGFA PACS Archive Mirroring 1.0",01) UL DateTimeVerified 1 PrivateTag + +(0029,"CAMTRONICS IP",10) LT Unknown 1 PrivateTag +(0029,"CAMTRONICS IP",20) UN Unknown 1 PrivateTag +(0029,"CAMTRONICS IP",30) UN Unknown 1 PrivateTag +(0029,"CAMTRONICS IP",40) UN Unknown 1 PrivateTag + +(0029,"CAMTRONICS",10) LT Commentline 1 PrivateTag +(0029,"CAMTRONICS",20) DS EdgeEnhancementCoefficient 1 PrivateTag +(0029,"CAMTRONICS",50) LT SceneText 1 PrivateTag +(0029,"CAMTRONICS",60) LT ImageText 1 PrivateTag +(0029,"CAMTRONICS",70) IS PixelShiftHorizontal 1 PrivateTag +(0029,"CAMTRONICS",80) IS PixelShiftVertical 1 PrivateTag +(0029,"CAMTRONICS",90) IS Unknown 1 PrivateTag + +(0009,"CARDIO-D.R. 1.0",00) UL FileLocation 1 PrivateTag +(0009,"CARDIO-D.R. 1.0",01) UL FileSize 1 PrivateTag +(0009,"CARDIO-D.R. 1.0",40) SQ AlternateImageSequence 1 PrivateTag +(0019,"CARDIO-D.R. 1.0",00) CS ImageBlankingShape 1 PrivateTag +(0019,"CARDIO-D.R. 1.0",02) IS ImageBlankingLeftVerticalEdge 1 PrivateTag +(0019,"CARDIO-D.R. 1.0",04) IS ImageBlankingRightVerticalEdge 1 PrivateTag +(0019,"CARDIO-D.R. 1.0",06) IS ImageBlankingUpperHorizontalEdge 1 PrivateTag +(0019,"CARDIO-D.R. 1.0",08) IS ImageBlankingLowerHorizontalEdge 1 PrivateTag +(0019,"CARDIO-D.R. 1.0",10) IS CenterOfCircularImageBlanking 1 PrivateTag +(0019,"CARDIO-D.R. 1.0",12) IS RadiusOfCircularImageBlanking 1 PrivateTag +(0019,"CARDIO-D.R. 1.0",30) UL MaximumImageFrameSize 1 PrivateTag +(0021,"CARDIO-D.R. 1.0",13) IS ImageSequenceNumber 1 PrivateTag +(0029,"CARDIO-D.R. 1.0",00) SQ EdgeEnhancementSequence 1 PrivateTag +(0029,"CARDIO-D.R. 1.0",01) US ConvolutionKernelSize 2 PrivateTag +(0029,"CARDIO-D.R. 1.0",02) DS ConvolutionKernelCoefficients 1-n PrivateTag +(0029,"CARDIO-D.R. 1.0",03) DS EdgeEnhancementGain 1 PrivateTag + +(0025,"CMR42 CIRCLECVI",1010) LO WorkspaceID 1 PrivateTag +(0025,"CMR42 CIRCLECVI",1020) LO WorkspaceTimeString 1 PrivateTag +(0025,"CMR42 CIRCLECVI",1030) OB WorkspaceStream 1 PrivateTag + +(0009,"DCMTK_ANONYMIZER",00) SQ AnonymizerUIDMap 1 PrivateTag +(0009,"DCMTK_ANONYMIZER",10) UI AnonymizerUIDKey 1 PrivateTag +(0009,"DCMTK_ANONYMIZER",20) UI AnonymizerUIDValue 1 PrivateTag +(0009,"DCMTK_ANONYMIZER",30) SQ AnonymizerPatientIDMap 1 PrivateTag +(0009,"DCMTK_ANONYMIZER",40) LO AnonymizerPatientIDKey 1 PrivateTag +(0009,"DCMTK_ANONYMIZER",50) LO AnonymizerPatientIDValue 1 PrivateTag + +(0019,"DIDI TO PCR 1.1",22) UN RouteAET 1 PrivateTag +(0019,"DIDI TO PCR 1.1",23) DS PCRPrintScale 1 PrivateTag +(0019,"DIDI TO PCR 1.1",24) UN PCRPrintJobEnd 1 PrivateTag +(0019,"DIDI TO PCR 1.1",25) IS PCRNoFilmCopies 1 PrivateTag +(0019,"DIDI TO PCR 1.1",26) IS PCRFilmLayoutPosition 1 PrivateTag +(0019,"DIDI TO PCR 1.1",27) UN PCRPrintReportName 1 PrivateTag +(0019,"DIDI TO PCR 1.1",70) UN RADProtocolPrinter 1 PrivateTag +(0019,"DIDI TO PCR 1.1",71) UN RADProtocolMedium 1 PrivateTag +(0019,"DIDI TO PCR 1.1",90) LO UnprocessedFlag 1 PrivateTag +(0019,"DIDI TO PCR 1.1",91) UN KeyValues 1 PrivateTag +(0019,"DIDI TO PCR 1.1",92) UN DestinationPostprocessingFunction 1 PrivateTag +(0019,"DIDI TO PCR 1.1",A0) UN Version 1 PrivateTag +(0019,"DIDI TO PCR 1.1",A1) UN RangingMode 1 PrivateTag +(0019,"DIDI TO PCR 1.1",A2) UN AbdomenBrightness 1 PrivateTag +(0019,"DIDI TO PCR 1.1",A3) UN FixedBrightness 1 PrivateTag +(0019,"DIDI TO PCR 1.1",A4) UN DetailContrast 1 PrivateTag +(0019,"DIDI TO PCR 1.1",A5) UN ContrastBalance 1 PrivateTag +(0019,"DIDI TO PCR 1.1",A6) UN StructureBoost 1 PrivateTag +(0019,"DIDI TO PCR 1.1",A7) UN StructurePreference 1 PrivateTag +(0019,"DIDI TO PCR 1.1",A8) UN NoiseRobustness 1 PrivateTag +(0019,"DIDI TO PCR 1.1",A9) UN NoiseDoseLimit 1 PrivateTag +(0019,"DIDI TO PCR 1.1",AA) UN NoiseDoseStep 1 PrivateTag +(0019,"DIDI TO PCR 1.1",AB) UN NoiseFrequencyLimit 1 PrivateTag +(0019,"DIDI TO PCR 1.1",AC) UN WeakContrastLimit 1 PrivateTag +(0019,"DIDI TO PCR 1.1",AD) UN StrongContrastLimit 1 PrivateTag +(0019,"DIDI TO PCR 1.1",AE) UN StructureBoostOffset 1 PrivateTag +(0019,"DIDI TO PCR 1.1",AF) UN SmoothGain 1 PrivateTag +(0019,"DIDI TO PCR 1.1",B0) UN MeasureField1 1 PrivateTag +(0019,"DIDI TO PCR 1.1",B1) UN MeasureField2 1 PrivateTag +(0019,"DIDI TO PCR 1.1",B2) UN KeyPercentile1 1 PrivateTag +(0019,"DIDI TO PCR 1.1",B3) UN KeyPercentile2 1 PrivateTag +(0019,"DIDI TO PCR 1.1",B4) UN DensityLUT 1 PrivateTag +(0019,"DIDI TO PCR 1.1",B5) UN Brightness 1 PrivateTag +(0019,"DIDI TO PCR 1.1",B6) UN Gamma 1 PrivateTag +(0089,"DIDI TO PCR 1.1",10) SQ Unknown 1 PrivateTag + +(0029,"DIGISCAN IMAGE",31) US Unknown 1-n PrivateTag +(0029,"DIGISCAN IMAGE",32) US Unknown 1-n PrivateTag +(0029,"DIGISCAN IMAGE",33) LT Unknown 1 PrivateTag +(0029,"DIGISCAN IMAGE",34) LT Unknown 1 PrivateTag + +(7001-o-70ff,"DLX_ANNOT_01",04) ST TextAnnotation 1 PrivateTag +(7001-o-70ff,"DLX_ANNOT_01",05) IS Box 2 PrivateTag +(7001-o-70ff,"DLX_ANNOT_01",07) IS ArrowEnd 2 PrivateTag + +(0015,"DLX_EXAMS_01",01) DS StenosisCalibrationRatio 1 PrivateTag +(0015,"DLX_EXAMS_01",02) DS StenosisMagnification 1 PrivateTag +(0015,"DLX_EXAMS_01",03) DS CardiacCalibrationRatio 1 PrivateTag + +(6001-o-60ff,"DLX_LKUP_01",01) US GrayPaletteColorLookupTableDescriptor 3 PrivateTag +(6001-o-60ff,"DLX_LKUP_01",02) US GrayPaletteColorLookupTableData 1 PrivateTag + +(0011,"DLX_PATNT_01",01) LT PatientDOB 1 PrivateTag + +(0019,"DLX_SERIE_01",01) DS AngleValueLArm 1 PrivateTag +(0019,"DLX_SERIE_01",02) DS AngleValuePArm 1 PrivateTag +(0019,"DLX_SERIE_01",03) DS AngleValueCArm 1 PrivateTag +(0019,"DLX_SERIE_01",04) CS AngleLabelLArm 1 PrivateTag +(0019,"DLX_SERIE_01",05) CS AngleLabelPArm 1 PrivateTag +(0019,"DLX_SERIE_01",06) CS AngleLabelCArm 1 PrivateTag +(0019,"DLX_SERIE_01",07) ST ProcedureName 1 PrivateTag +(0019,"DLX_SERIE_01",08) ST ExamName 1 PrivateTag +(0019,"DLX_SERIE_01",09) SH PatientSize 1 PrivateTag +(0019,"DLX_SERIE_01",0a) IS RecordView 1 PrivateTag +(0019,"DLX_SERIE_01",10) DS InjectorDelay 1 PrivateTag +(0019,"DLX_SERIE_01",11) CS AutoInject 1 PrivateTag +(0019,"DLX_SERIE_01",14) IS AcquisitionMode 1 PrivateTag +(0019,"DLX_SERIE_01",15) CS CameraRotationEnabled 1 PrivateTag +(0019,"DLX_SERIE_01",16) CS ReverseSweep 1 PrivateTag +(0019,"DLX_SERIE_01",17) IS SpatialFilterStrength 1 PrivateTag +(0019,"DLX_SERIE_01",18) IS ZoomFactor 1 PrivateTag +(0019,"DLX_SERIE_01",19) IS XZoomCenter 1 PrivateTag +(0019,"DLX_SERIE_01",1a) IS YZoomCenter 1 PrivateTag +(0019,"DLX_SERIE_01",1b) DS Focus 1 PrivateTag +(0019,"DLX_SERIE_01",1c) CS Dose 1 PrivateTag +(0019,"DLX_SERIE_01",1d) IS SideMark 1 PrivateTag +(0019,"DLX_SERIE_01",1e) IS PercentageLandscape 1 PrivateTag +(0019,"DLX_SERIE_01",1f) DS ExposureDuration 1 PrivateTag + +(00E1,"ELSCINT1",01) US DataDictionaryVersion 1 PrivateTag +(00E1,"ELSCINT1",14) LT Unknown 1 PrivateTag +(00E1,"ELSCINT1",22) DS Unknown 2 PrivateTag +(00E1,"ELSCINT1",23) DS Unknown 2 PrivateTag +(00E1,"ELSCINT1",24) LT Unknown 1 PrivateTag +(00E1,"ELSCINT1",25) LT Unknown 1 PrivateTag +(00E1,"ELSCINT1",40) SH OffsetFromCTMRImages 1 PrivateTag +(0601,"ELSCINT1",00) SH ImplementationVersion 1 PrivateTag +(0601,"ELSCINT1",20) DS RelativeTablePosition 1 PrivateTag +(0601,"ELSCINT1",21) DS RelativeTableHeight 1 PrivateTag +(0601,"ELSCINT1",30) SH SurviewDirection 1 PrivateTag +(0601,"ELSCINT1",31) DS SurviewLength 1 PrivateTag +(0601,"ELSCINT1",50) SH ImageViewType 1 PrivateTag +(0601,"ELSCINT1",70) DS BatchNumber 1 PrivateTag +(0601,"ELSCINT1",71) DS BatchSize 1 PrivateTag +(0601,"ELSCINT1",72) DS BatchSliceNumber 1 PrivateTag + +(0009,"FDMS 1.0",04) SH ImageControlUnit 1 PrivateTag +(0009,"FDMS 1.0",05) OW ImageUID 1 PrivateTag +(0009,"FDMS 1.0",06) OW RouteImageUID 1 PrivateTag +(0009,"FDMS 1.0",08) UL ImageDisplayInformationVersionNo 1 PrivateTag +(0009,"FDMS 1.0",09) UL PatientInformationVersionNo 1 PrivateTag +(0009,"FDMS 1.0",0C) OW FilmUID 1 PrivateTag +(0009,"FDMS 1.0",10) CS ExposureUnitTypeCode 1 PrivateTag +(0009,"FDMS 1.0",80) LO KanjiHospitalName 1 PrivateTag +(0009,"FDMS 1.0",90) ST DistributionCode 1 PrivateTag +(0009,"FDMS 1.0",92) SH KanjiDepartmentName 1 PrivateTag +(0009,"FDMS 1.0",F0) CS BlackeningProcessFlag 1 PrivateTag +(0019,"FDMS 1.0",15) LO KanjiBodyPartForExposure 1 PrivateTag +(0019,"FDMS 1.0",32) LO KanjiMenuName 1 PrivateTag +(0019,"FDMS 1.0",40) CS ImageProcessingType 1 PrivateTag +(0019,"FDMS 1.0",50) CS EDRMode 1 PrivateTag +(0019,"FDMS 1.0",60) SH RadiographersCode 1 PrivateTag +(0019,"FDMS 1.0",70) IS SplitExposureFormat 1 PrivateTag +(0019,"FDMS 1.0",71) IS NoOfSplitExposureFrames 1 PrivateTag +(0019,"FDMS 1.0",80) IS ReadingPositionSpecification 1 PrivateTag +(0019,"FDMS 1.0",81) IS ReadingSensitivityCenter 1 PrivateTag +(0019,"FDMS 1.0",90) SH FilmAnnotationCharacterString1 1 PrivateTag +(0019,"FDMS 1.0",91) SH FilmAnnotationCharacterString2 1 PrivateTag +(0021,"FDMS 1.0",10) CS FCRImageID 1 PrivateTag +(0021,"FDMS 1.0",30) CS SetNo 1 PrivateTag +(0021,"FDMS 1.0",40) IS ImageNoInTheSet 1 PrivateTag +(0021,"FDMS 1.0",50) CS PairProcessingInformation 1 PrivateTag +(0021,"FDMS 1.0",80) OB EquipmentTypeSpecificInformation 1 PrivateTag +(0023,"FDMS 1.0",10) SQ Unknown 1 PrivateTag +(0023,"FDMS 1.0",20) SQ Unknown 1 PrivateTag +(0023,"FDMS 1.0",30) SQ Unknown 1 PrivateTag +(0025,"FDMS 1.0",10) US RelativeLightEmissionAmountSk 1 PrivateTag +(0025,"FDMS 1.0",11) US TermOfCorrectionForEachIPTypeSt 1 PrivateTag +(0025,"FDMS 1.0",12) US ReadingGainGp 1 PrivateTag +(0025,"FDMS 1.0",13) US Unknown 1 PrivateTag +(0025,"FDMS 1.0",15) CS Unknown 1 PrivateTag +(0025,"FDMS 1.0",20) US Unknown 2 PrivateTag +(0025,"FDMS 1.0",21) US Unknown 1 PrivateTag +(0025,"FDMS 1.0",30) US Unknown 1 PrivateTag +(0025,"FDMS 1.0",31) SS Unknown 1 PrivateTag +(0025,"FDMS 1.0",32) US Unknown 1 PrivateTag +(0025,"FDMS 1.0",33) SS Unknown 1 PrivateTag +(0025,"FDMS 1.0",34) SS Unknown 1 PrivateTag +(0025,"FDMS 1.0",40) US Unknown 1 PrivateTag +(0025,"FDMS 1.0",41) US Unknown 1 PrivateTag +(0025,"FDMS 1.0",42) US Unknown 1 PrivateTag +(0025,"FDMS 1.0",43) US Unknown 1 PrivateTag +(0025,"FDMS 1.0",50) US Unknown 1 PrivateTag +(0025,"FDMS 1.0",51) US Unknown 1 PrivateTag +(0025,"FDMS 1.0",52) US Unknown 1 PrivateTag +(0025,"FDMS 1.0",53) US Unknown 1 PrivateTag +(0025,"FDMS 1.0",60) US Unknown 1 PrivateTag +(0025,"FDMS 1.0",61) US Unknown 1 PrivateTag +(0025,"FDMS 1.0",62) US Unknown 1 PrivateTag +(0025,"FDMS 1.0",63) CS Unknown 1 PrivateTag +(0025,"FDMS 1.0",70) US Unknown 1 PrivateTag +(0025,"FDMS 1.0",71) US Unknown 1 PrivateTag +(0025,"FDMS 1.0",72) US Unknown 1 PrivateTag +(0025,"FDMS 1.0",73) US Unknown 1-n PrivateTag +(0025,"FDMS 1.0",74) US Unknown 1-n PrivateTag +(0025,"FDMS 1.0",80) US Unknown 1 PrivateTag +(0025,"FDMS 1.0",81) US Unknown 1 PrivateTag +(0025,"FDMS 1.0",82) US Unknown 1 PrivateTag +(0025,"FDMS 1.0",83) US Unknown 1-n PrivateTag +(0025,"FDMS 1.0",84) US Unknown 1-n PrivateTag +(0025,"FDMS 1.0",90) US Unknown 1 PrivateTag +(0025,"FDMS 1.0",91) US Unknown 1 PrivateTag +(0025,"FDMS 1.0",92) US Unknown 1 PrivateTag +(0025,"FDMS 1.0",93) US Unknown 1 PrivateTag +(0025,"FDMS 1.0",94) US Unknown 1 PrivateTag +(0025,"FDMS 1.0",95) US Unknown 1 PrivateTag +(0025,"FDMS 1.0",96) CS Unknown 1 PrivateTag +(0025,"FDMS 1.0",a0) US Unknown 1 PrivateTag +(0025,"FDMS 1.0",a1) SS Unknown 1 PrivateTag +(0025,"FDMS 1.0",a2) US Unknown 1 PrivateTag +(0025,"FDMS 1.0",a3) SS Unknown 1 PrivateTag +(0027,"FDMS 1.0",10) SQ Unknown 1 PrivateTag +(0027,"FDMS 1.0",20) SQ Unknown 1 PrivateTag +(0027,"FDMS 1.0",30) SQ Unknown 1 PrivateTag +(0027,"FDMS 1.0",40) SQ Unknown 1 PrivateTag +(0027,"FDMS 1.0",50) SQ Unknown 1 PrivateTag +(0027,"FDMS 1.0",60) SQ Unknown 1 PrivateTag +(0027,"FDMS 1.0",70) SQ Unknown 1 PrivateTag +(0027,"FDMS 1.0",80) SQ Unknown 1 PrivateTag +(0027,"FDMS 1.0",a0) IS Unknown 1 PrivateTag +(0027,"FDMS 1.0",a1) CS Unknown 2 PrivateTag +(0027,"FDMS 1.0",a2) CS Unknown 2 PrivateTag +(0027,"FDMS 1.0",a3) SS Unknown 1-n PrivateTag +(0029,"FDMS 1.0",20) CS ImageScanningDirection 1 PrivateTag +(0029,"FDMS 1.0",30) CS ExtendedReadingSizeValue 1 PrivateTag +(0029,"FDMS 1.0",34) US MagnificationReductionRatio 1 PrivateTag +(0029,"FDMS 1.0",44) CS LineDensityCode 1 PrivateTag +(0029,"FDMS 1.0",50) CS DataCompressionCode 1 PrivateTag +(2011,"FDMS 1.0",11) CS ImagePosition SpecifyingFlag 1 PrivateTag +(50F1,"FDMS 1.0",06) CS EnergySubtractionParam 1 PrivateTag +(50F1,"FDMS 1.0",07) CS SubtractionRegistrationResult 1 PrivateTag +(50F1,"FDMS 1.0",08) CS EnergySubtractionParam2 1 PrivateTag +(50F1,"FDMS 1.0",09) SL AfinConversionCoefficient 1 PrivateTag +(50F1,"FDMS 1.0",10) CS FilmOutputFormat 1 PrivateTag +(50F1,"FDMS 1.0",20) CS ImageProcessingModificationFlag 1 PrivateTag + +(0009,"FFP DATA",01) UN CRHeaderInformation 1 PrivateTag + +(0019,"GE ??? From Adantage Review CS",30) LO CREDRMode 1 PrivateTag +(0019,"GE ??? From Adantage Review CS",40) LO CRLatitude 1 PrivateTag +(0019,"GE ??? From Adantage Review CS",50) LO CRGroupNumber 1 PrivateTag +(0019,"GE ??? From Adantage Review CS",70) LO CRImageSerialNumber 1 PrivateTag +(0019,"GE ??? From Adantage Review CS",80) LO CRBarCodeNumber 1 PrivateTag +(0019,"GE ??? From Adantage Review CS",90) LO CRFilmOutputExposures 1 PrivateTag + +(0009,"GEMS_ACQU_01",24) DS Unknown 1 PrivateTag +(0009,"GEMS_ACQU_01",25) US Unknown 1 PrivateTag +(0009,"GEMS_ACQU_01",3e) US Unknown 1 PrivateTag +(0009,"GEMS_ACQU_01",3f) US Unknown 1 PrivateTag +(0009,"GEMS_ACQU_01",42) US Unknown 1 PrivateTag +(0009,"GEMS_ACQU_01",43) US Unknown 1 PrivateTag +(0009,"GEMS_ACQU_01",f8) US Unknown 1 PrivateTag +(0009,"GEMS_ACQU_01",fb) IS Unknown 1 PrivateTag +(0019,"GEMS_ACQU_01",01) LT Unknown 1 PrivateTag +(0019,"GEMS_ACQU_01",02) SL NumberOfCellsInDetector 1 PrivateTag +(0019,"GEMS_ACQU_01",03) DS CellNumberAtTheta 1 PrivateTag +(0019,"GEMS_ACQU_01",04) DS CellSpacing 1 PrivateTag +(0019,"GEMS_ACQU_01",05) LT Unknown 1 PrivateTag +(0019,"GEMS_ACQU_01",06) UN Unknown 1 PrivateTag +(0019,"GEMS_ACQU_01",0e) US Unknown 1 PrivateTag +(0019,"GEMS_ACQU_01",0f) DS HorizontalFrameOfReference 1 PrivateTag +(0019,"GEMS_ACQU_01",11) SS SeriesContrast 1 PrivateTag +(0019,"GEMS_ACQU_01",12) SS LastPseq 1 PrivateTag +(0019,"GEMS_ACQU_01",13) SS StartNumberForBaseline 1 PrivateTag +(0019,"GEMS_ACQU_01",14) SS End NumberForBaseline 1 PrivateTag +(0019,"GEMS_ACQU_01",15) SS StartNumberForEnhancedScans 1 PrivateTag +(0019,"GEMS_ACQU_01",16) SS EndNumberForEnhancedScans 1 PrivateTag +(0019,"GEMS_ACQU_01",17) SS SeriesPlane 1 PrivateTag +(0019,"GEMS_ACQU_01",18) LO FirstScanRAS 1 PrivateTag +(0019,"GEMS_ACQU_01",19) DS FirstScanLocation 1 PrivateTag +(0019,"GEMS_ACQU_01",1a) LO LastScanRAS 1 PrivateTag +(0019,"GEMS_ACQU_01",1b) DS LastScanLocation 1 PrivateTag +(0019,"GEMS_ACQU_01",1e) DS DisplayFieldOfView 1 PrivateTag +(0019,"GEMS_ACQU_01",20) DS Unknown 1 PrivateTag +(0019,"GEMS_ACQU_01",22) DS Unknown 1 PrivateTag +(0019,"GEMS_ACQU_01",23) DS TableSpeed 1 PrivateTag +(0019,"GEMS_ACQU_01",24) DS MidScanTime 1 PrivateTag +(0019,"GEMS_ACQU_01",25) SS MidScanFlag 1 PrivateTag +(0019,"GEMS_ACQU_01",26) SL DegreesOfAzimuth 1 PrivateTag +(0019,"GEMS_ACQU_01",27) DS GantryPeriod 1 PrivateTag +(0019,"GEMS_ACQU_01",2a) DS XrayOnPosition 1 PrivateTag +(0019,"GEMS_ACQU_01",2b) DS XrayOffPosition 1 PrivateTag +(0019,"GEMS_ACQU_01",2c) SL NumberOfTriggers 1 PrivateTag +(0019,"GEMS_ACQU_01",2d) US Unknown 1 PrivateTag +(0019,"GEMS_ACQU_01",2e) DS AngleOfFirstView 1 PrivateTag +(0019,"GEMS_ACQU_01",2f) DS TriggerFrequency 1 PrivateTag +(0019,"GEMS_ACQU_01",39) SS ScanFOVType 1 PrivateTag +(0019,"GEMS_ACQU_01",3a) IS Unknown 1 PrivateTag +(0019,"GEMS_ACQU_01",3b) LT Unknown 1 PrivateTag +(0019,"GEMS_ACQU_01",3c) UN Unknown 1 PrivateTag +(0019,"GEMS_ACQU_01",3e) UN Unknown 1 PrivateTag +(0019,"GEMS_ACQU_01",3f) UN Unknown 1 PrivateTag +(0019,"GEMS_ACQU_01",40) SS StatReconFlag 1 PrivateTag +(0019,"GEMS_ACQU_01",41) SS ComputeType 1 PrivateTag +(0019,"GEMS_ACQU_01",42) SS SegmentNumber 1 PrivateTag +(0019,"GEMS_ACQU_01",43) SS TotalSegmentsRequested 1 PrivateTag +(0019,"GEMS_ACQU_01",44) DS InterscanDelay 1 PrivateTag +(0019,"GEMS_ACQU_01",47) SS ViewCompressionFactor 1 PrivateTag +(0019,"GEMS_ACQU_01",48) US Unknown 1 PrivateTag +(0019,"GEMS_ACQU_01",49) US Unknown 1 PrivateTag +(0019,"GEMS_ACQU_01",4a) SS TotalNumberOfRefChannels 1 PrivateTag +(0019,"GEMS_ACQU_01",4b) SL DataSizeForScanData 1 PrivateTag +(0019,"GEMS_ACQU_01",52) SS ReconPostProcessingFlag 1 PrivateTag +(0019,"GEMS_ACQU_01",54) UN Unknown 1 PrivateTag +(0019,"GEMS_ACQU_01",57) SS CTWaterNumber 1 PrivateTag +(0019,"GEMS_ACQU_01",58) SS CTBoneNumber 1 PrivateTag +(0019,"GEMS_ACQU_01",5a) FL AcquisitionDuration 1 PrivateTag +(0019,"GEMS_ACQU_01",5d) US Unknown 1 PrivateTag +(0019,"GEMS_ACQU_01",5e) SL NumberOfChannels1To512 1 PrivateTag +(0019,"GEMS_ACQU_01",5f) SL IncrementBetweenChannels 1 PrivateTag +(0019,"GEMS_ACQU_01",60) SL StartingView 1 PrivateTag +(0019,"GEMS_ACQU_01",61) SL NumberOfViews 1 PrivateTag +(0019,"GEMS_ACQU_01",62) SL IncrementBetweenViews 1 PrivateTag +(0019,"GEMS_ACQU_01",6a) SS DependantOnNumberOfViewsProcessed 1 PrivateTag +(0019,"GEMS_ACQU_01",6b) SS FieldOfViewInDetectorCells 1 PrivateTag +(0019,"GEMS_ACQU_01",70) SS ValueOfBackProjectionButton 1 PrivateTag +(0019,"GEMS_ACQU_01",71) SS SetIfFatqEstimatesWereUsed 1 PrivateTag +(0019,"GEMS_ACQU_01",72) DS ZChannelAvgOverViews 1 PrivateTag +(0019,"GEMS_ACQU_01",73) DS AvgOfLeftRefChannelsOverViews 1 PrivateTag +(0019,"GEMS_ACQU_01",74) DS MaxLeftChannelOverViews 1 PrivateTag +(0019,"GEMS_ACQU_01",75) DS AvgOfRightRefChannelsOverViews 1 PrivateTag +(0019,"GEMS_ACQU_01",76) DS MaxRightChannelOverViews 1 PrivateTag +(0019,"GEMS_ACQU_01",7d) DS SecondEcho 1 PrivateTag +(0019,"GEMS_ACQU_01",7e) SS NumberOfEchos 1 PrivateTag +(0019,"GEMS_ACQU_01",7f) DS TableDelta 1 PrivateTag +(0019,"GEMS_ACQU_01",81) SS Contiguous 1 PrivateTag +(0019,"GEMS_ACQU_01",82) US Unknown 1 PrivateTag +(0019,"GEMS_ACQU_01",83) DS Unknown 1 PrivateTag +(0019,"GEMS_ACQU_01",84) DS PeakSAR 1 PrivateTag +(0019,"GEMS_ACQU_01",85) SS MonitorSAR 1 PrivateTag +(0019,"GEMS_ACQU_01",86) US Unknown 1 PrivateTag +(0019,"GEMS_ACQU_01",87) DS CardiacRepetition Time 1 PrivateTag +(0019,"GEMS_ACQU_01",88) SS ImagesPerCardiacCycle 1 PrivateTag +(0019,"GEMS_ACQU_01",8a) SS ActualReceiveGainAnalog 1 PrivateTag +(0019,"GEMS_ACQU_01",8b) SS ActualReceiveGainDigital 1 PrivateTag +(0019,"GEMS_ACQU_01",8d) DS DelayAfterTrigger 1 PrivateTag +(0019,"GEMS_ACQU_01",8f) SS SwapPhaseFrequency 1 PrivateTag +(0019,"GEMS_ACQU_01",90) SS PauseInterval 1 PrivateTag +(0019,"GEMS_ACQU_01",91) DS PulseTime 1 PrivateTag +(0019,"GEMS_ACQU_01",92) SL SliceOffsetOnFrequencyAxis 1 PrivateTag +(0019,"GEMS_ACQU_01",93) DS CenterFrequency 1 PrivateTag +(0019,"GEMS_ACQU_01",94) SS TransmitGain 1 PrivateTag +(0019,"GEMS_ACQU_01",95) SS AnalogReceiverGain 1 PrivateTag +(0019,"GEMS_ACQU_01",96) SS DigitalReceiverGain 1 PrivateTag +(0019,"GEMS_ACQU_01",97) SL BitmapDefiningCVs 1 PrivateTag +(0019,"GEMS_ACQU_01",98) SS CenterFrequencyMethod 1 PrivateTag +(0019,"GEMS_ACQU_01",99) US Unknown 1 PrivateTag +(0019,"GEMS_ACQU_01",9b) SS PulseSequenceMode 1 PrivateTag +(0019,"GEMS_ACQU_01",9c) LO PulseSequenceName 1 PrivateTag +(0019,"GEMS_ACQU_01",9d) DT PulseSequenceDate 1 PrivateTag +(0019,"GEMS_ACQU_01",9e) LO InternalPulseSequenceName 1 PrivateTag +(0019,"GEMS_ACQU_01",9f) SS TransmittingCoil 1 PrivateTag +(0019,"GEMS_ACQU_01",a0) SS SurfaceCoilType 1 PrivateTag +(0019,"GEMS_ACQU_01",a1) SS ExtremityCoilFlag 1 PrivateTag +(0019,"GEMS_ACQU_01",a2) SL RawDataRunNumber 1 PrivateTag +(0019,"GEMS_ACQU_01",a3) UL CalibratedFieldStrength 1 PrivateTag +(0019,"GEMS_ACQU_01",a4) SS SATFatWaterBone 1 PrivateTag +(0019,"GEMS_ACQU_01",a5) DS ReceiveBandwidth 1 PrivateTag +(0019,"GEMS_ACQU_01",a7) DS UserData 1 PrivateTag +(0019,"GEMS_ACQU_01",a8) DS UserData 1 PrivateTag +(0019,"GEMS_ACQU_01",a9) DS UserData 1 PrivateTag +(0019,"GEMS_ACQU_01",aa) DS UserData 1 PrivateTag +(0019,"GEMS_ACQU_01",ab) DS UserData 1 PrivateTag +(0019,"GEMS_ACQU_01",ac) DS UserData 1 PrivateTag +(0019,"GEMS_ACQU_01",ad) DS UserData 1 PrivateTag +(0019,"GEMS_ACQU_01",ae) DS UserData 1 PrivateTag +(0019,"GEMS_ACQU_01",af) DS UserData 1 PrivateTag +(0019,"GEMS_ACQU_01",b0) DS UserData 1 PrivateTag +(0019,"GEMS_ACQU_01",b1) DS UserData 1 PrivateTag +(0019,"GEMS_ACQU_01",b2) DS UserData 1 PrivateTag +(0019,"GEMS_ACQU_01",b3) DS UserData 1 PrivateTag +(0019,"GEMS_ACQU_01",b4) DS UserData 1 PrivateTag +(0019,"GEMS_ACQU_01",b5) DS UserData 1 PrivateTag +(0019,"GEMS_ACQU_01",b6) DS UserData 1 PrivateTag +(0019,"GEMS_ACQU_01",b7) DS UserData 1 PrivateTag +(0019,"GEMS_ACQU_01",b8) DS UserData 1 PrivateTag +(0019,"GEMS_ACQU_01",b9) DS UserData 1 PrivateTag +(0019,"GEMS_ACQU_01",ba) DS UserData 1 PrivateTag +(0019,"GEMS_ACQU_01",bb) DS UserData 1 PrivateTag +(0019,"GEMS_ACQU_01",bc) DS UserData 1 PrivateTag +(0019,"GEMS_ACQU_01",bd) DS UserData 1 PrivateTag +(0019,"GEMS_ACQU_01",be) DS ProjectionAngle 1 PrivateTag +(0019,"GEMS_ACQU_01",c0) SS SaturationPlanes 1 PrivateTag +(0019,"GEMS_ACQU_01",c1) SS SurfaceCoilIntensityCorrectionFlag 1 PrivateTag +(0019,"GEMS_ACQU_01",c2) SS SATLocationR 1 PrivateTag +(0019,"GEMS_ACQU_01",c3) SS SATLocationL 1 PrivateTag +(0019,"GEMS_ACQU_01",c4) SS SATLocationA 1 PrivateTag +(0019,"GEMS_ACQU_01",c5) SS SATLocationP 1 PrivateTag +(0019,"GEMS_ACQU_01",c6) SS SATLocationH 1 PrivateTag +(0019,"GEMS_ACQU_01",c7) SS SATLocationF 1 PrivateTag +(0019,"GEMS_ACQU_01",c8) SS SATThicknessRL 1 PrivateTag +(0019,"GEMS_ACQU_01",c9) SS SATThicknessAP 1 PrivateTag +(0019,"GEMS_ACQU_01",ca) SS SATThicknessHF 1 PrivateTag +(0019,"GEMS_ACQU_01",cb) SS PrescribedFlowAxis 1 PrivateTag +(0019,"GEMS_ACQU_01",cc) SS VelocityEncoding 1 PrivateTag +(0019,"GEMS_ACQU_01",cd) SS ThicknessDisclaimer 1 PrivateTag +(0019,"GEMS_ACQU_01",ce) SS PrescanType 1 PrivateTag +(0019,"GEMS_ACQU_01",cf) SS PrescanStatus 1 PrivateTag +(0019,"GEMS_ACQU_01",d0) SH RawDataType 1 PrivateTag +(0019,"GEMS_ACQU_01",d2) SS ProjectionAlgorithm 1 PrivateTag +(0019,"GEMS_ACQU_01",d3) SH ProjectionAlgorithm 1 PrivateTag +(0019,"GEMS_ACQU_01",d4) US Unknown 1 PrivateTag +(0019,"GEMS_ACQU_01",d5) SS FractionalEcho 1 PrivateTag +(0019,"GEMS_ACQU_01",d6) SS PrepPulse 1 PrivateTag +(0019,"GEMS_ACQU_01",d7) SS CardiacPhases 1 PrivateTag +(0019,"GEMS_ACQU_01",d8) SS VariableEchoFlag 1 PrivateTag +(0019,"GEMS_ACQU_01",d9) DS ConcatenatedSAT 1 PrivateTag +(0019,"GEMS_ACQU_01",da) SS ReferenceChannelUsed 1 PrivateTag +(0019,"GEMS_ACQU_01",db) DS BackProjectorCoefficient 1 PrivateTag +(0019,"GEMS_ACQU_01",dc) SS PrimarySpeedCorrectionUsed 1 PrivateTag +(0019,"GEMS_ACQU_01",dd) SS OverrangeCorrectionUsed 1 PrivateTag +(0019,"GEMS_ACQU_01",de) DS DynamicZAlphaValue 1 PrivateTag +(0019,"GEMS_ACQU_01",df) DS UserData 1 PrivateTag +(0019,"GEMS_ACQU_01",e0) DS UserData 1 PrivateTag +(0019,"GEMS_ACQU_01",e1) DS Unknown 1 PrivateTag +(0019,"GEMS_ACQU_01",e2) DS VelocityEncodeScale 1 PrivateTag +(0019,"GEMS_ACQU_01",e3) LT Unknown 1 PrivateTag +(0019,"GEMS_ACQU_01",e4) LT Unknown 1 PrivateTag +(0019,"GEMS_ACQU_01",e5) IS Unknown 1 PrivateTag +(0019,"GEMS_ACQU_01",e6) US Unknown 1 PrivateTag +(0019,"GEMS_ACQU_01",e8) DS Unknown 1 PrivateTag +(0019,"GEMS_ACQU_01",e9) DS Unknown 1 PrivateTag +(0019,"GEMS_ACQU_01",eb) DS Unknown 1 PrivateTag +(0019,"GEMS_ACQU_01",ec) US Unknown 1 PrivateTag +(0019,"GEMS_ACQU_01",f0) UN Unknown 1 PrivateTag +(0019,"GEMS_ACQU_01",f1) LT Unknown 1 PrivateTag +(0019,"GEMS_ACQU_01",f2) SS FastPhases 1 PrivateTag +(0019,"GEMS_ACQU_01",f3) LT Unknown 1 PrivateTag +(0019,"GEMS_ACQU_01",f4) LT Unknown 1 PrivateTag +(0019,"GEMS_ACQU_01",f9) DS TransmitGain 1 PrivateTag + +(0023,"GEMS_ACRQA_1.0 BLOCK1",00) LO CRExposureMenuCode 1 PrivateTag +(0023,"GEMS_ACRQA_1.0 BLOCK1",10) LO CRExposureMenuString 1 PrivateTag +(0023,"GEMS_ACRQA_1.0 BLOCK1",20) LO CREDRMode 1 PrivateTag +(0023,"GEMS_ACRQA_1.0 BLOCK1",30) LO CRLatitude 1 PrivateTag +(0023,"GEMS_ACRQA_1.0 BLOCK1",40) LO CRGroupNumber 1 PrivateTag +(0023,"GEMS_ACRQA_1.0 BLOCK1",50) US CRImageSerialNumber 1 PrivateTag +(0023,"GEMS_ACRQA_1.0 BLOCK1",60) LO CRBarCodeNumber 1 PrivateTag +(0023,"GEMS_ACRQA_1.0 BLOCK1",70) LO CRFilmOutputExposure 1 PrivateTag +(0023,"GEMS_ACRQA_1.0 BLOCK1",80) LO CRFilmFormat 1 PrivateTag +(0023,"GEMS_ACRQA_1.0 BLOCK1",90) LO CRSShiftString 1 PrivateTag +(0023,"GEMS_ACRQA_1.0 BLOCK2",00) US CRSShift 1 PrivateTag +(0023,"GEMS_ACRQA_1.0 BLOCK2",10) DS CRCShift 1 PrivateTag +(0023,"GEMS_ACRQA_1.0 BLOCK2",20) DS CRGT 1 PrivateTag +(0023,"GEMS_ACRQA_1.0 BLOCK2",30) DS CRGA 1 PrivateTag +(0023,"GEMS_ACRQA_1.0 BLOCK2",40) DS CRGC 1 PrivateTag +(0023,"GEMS_ACRQA_1.0 BLOCK2",50) DS CRGS 1 PrivateTag +(0023,"GEMS_ACRQA_1.0 BLOCK2",60) DS CRRT 1 PrivateTag +(0023,"GEMS_ACRQA_1.0 BLOCK2",70) DS CRRE 1 PrivateTag +(0023,"GEMS_ACRQA_1.0 BLOCK2",80) US CRRN 1 PrivateTag +(0023,"GEMS_ACRQA_1.0 BLOCK2",90) DS CRDRT 1 PrivateTag +(0023,"GEMS_ACRQA_1.0 BLOCK3",00) DS CRDRE 1 PrivateTag +(0023,"GEMS_ACRQA_1.0 BLOCK3",10) US CRDRN 1 PrivateTag +(0023,"GEMS_ACRQA_1.0 BLOCK3",20) DS CRORE 1 PrivateTag +(0023,"GEMS_ACRQA_1.0 BLOCK3",30) US CRORN 1 PrivateTag +(0023,"GEMS_ACRQA_1.0 BLOCK3",40) US CRORD 1 PrivateTag +(0023,"GEMS_ACRQA_1.0 BLOCK3",50) LO CRCassetteSize 1 PrivateTag +(0023,"GEMS_ACRQA_1.0 BLOCK3",60) LO CRMachineID 1 PrivateTag +(0023,"GEMS_ACRQA_1.0 BLOCK3",70) LO CRMachineType 1 PrivateTag +(0023,"GEMS_ACRQA_1.0 BLOCK3",80) LO CRTechnicianCode 1 PrivateTag +(0023,"GEMS_ACRQA_1.0 BLOCK3",90) LO CREnergySubtractionParameters 1 PrivateTag +(0023,"GEMS_ACRQA_2.0 BLOCK1",00) LO CRExposureMenuCode 1 PrivateTag +(0023,"GEMS_ACRQA_2.0 BLOCK1",10) LO CRExposureMenuString 1 PrivateTag +(0023,"GEMS_ACRQA_2.0 BLOCK1",20) LO CREDRMode 1 PrivateTag +(0023,"GEMS_ACRQA_2.0 BLOCK1",30) LO CRLatitude 1 PrivateTag +(0023,"GEMS_ACRQA_2.0 BLOCK1",40) LO CRGroupNumber 1 PrivateTag +(0023,"GEMS_ACRQA_2.0 BLOCK1",50) US CRImageSerialNumber 1 PrivateTag +(0023,"GEMS_ACRQA_2.0 BLOCK1",60) LO CRBarCodeNumber 1 PrivateTag +(0023,"GEMS_ACRQA_2.0 BLOCK1",70) LO CRFilmOutputExposure 1 PrivateTag +(0023,"GEMS_ACRQA_2.0 BLOCK1",80) LO CRFilmFormat 1 PrivateTag +(0023,"GEMS_ACRQA_2.0 BLOCK1",90) LO CRSShiftString 1 PrivateTag +(0023,"GEMS_ACRQA_2.0 BLOCK2",00) US CRSShift 1 PrivateTag +(0023,"GEMS_ACRQA_2.0 BLOCK2",10) LO CRCShift 1 PrivateTag +(0023,"GEMS_ACRQA_2.0 BLOCK2",20) LO CRGT 1 PrivateTag +(0023,"GEMS_ACRQA_2.0 BLOCK2",30) DS CRGA 1 PrivateTag +(0023,"GEMS_ACRQA_2.0 BLOCK2",40) DS CRGC 1 PrivateTag +(0023,"GEMS_ACRQA_2.0 BLOCK2",50) DS CRGS 1 PrivateTag +(0023,"GEMS_ACRQA_2.0 BLOCK2",60) LO CRRT 1 PrivateTag +(0023,"GEMS_ACRQA_2.0 BLOCK2",70) DS CRRE 1 PrivateTag +(0023,"GEMS_ACRQA_2.0 BLOCK2",80) US CRRN 1 PrivateTag +(0023,"GEMS_ACRQA_2.0 BLOCK2",90) DS CRDRT 1 PrivateTag +(0023,"GEMS_ACRQA_2.0 BLOCK3",00) DS CRDRE 1 PrivateTag +(0023,"GEMS_ACRQA_2.0 BLOCK3",10) US CRDRN 1 PrivateTag +(0023,"GEMS_ACRQA_2.0 BLOCK3",20) DS CRORE 1 PrivateTag +(0023,"GEMS_ACRQA_2.0 BLOCK3",30) US CRORN 1 PrivateTag +(0023,"GEMS_ACRQA_2.0 BLOCK3",40) US CRORD 1 PrivateTag +(0023,"GEMS_ACRQA_2.0 BLOCK3",50) LO CRCassetteSize 1 PrivateTag +(0023,"GEMS_ACRQA_2.0 BLOCK3",60) LO CRMachineID 1 PrivateTag +(0023,"GEMS_ACRQA_2.0 BLOCK3",70) LO CRMachineType 1 PrivateTag +(0023,"GEMS_ACRQA_2.0 BLOCK3",80) LO CRTechnicianCode 1 PrivateTag +(0023,"GEMS_ACRQA_2.0 BLOCK3",90) LO CREnergySubtractionParameters 1 PrivateTag +(0023,"GEMS_ACRQA_2.0 BLOCK3",f0) LO CRDistributionCode 1 PrivateTag +(0023,"GEMS_ACRQA_2.0 BLOCK3",ff) US CRShuttersApplied 1 PrivateTag + +(0047,"GEMS_ADWSoft_3D1",01) SQ Reconstruction Parameters Sequence 1 PrivateTag +(0047,"GEMS_ADWSoft_3D1",50) UL VolumeVoxelCount 1 PrivateTag +(0047,"GEMS_ADWSoft_3D1",51) UL VolumeSegmentCount 1 PrivateTag +(0047,"GEMS_ADWSoft_3D1",53) US VolumeSliceSize 1 PrivateTag +(0047,"GEMS_ADWSoft_3D1",54) US VolumeSliceCount 1 PrivateTag +(0047,"GEMS_ADWSoft_3D1",55) SL VolumeThresholdValue 1 PrivateTag +(0047,"GEMS_ADWSoft_3D1",57) DS VolumeVoxelRatio 1 PrivateTag +(0047,"GEMS_ADWSoft_3D1",58) DS VolumeVoxelSize 1 PrivateTag +(0047,"GEMS_ADWSoft_3D1",59) US VolumeZPositionSize 1 PrivateTag +(0047,"GEMS_ADWSoft_3D1",60) DS VolumeBaseLine 9 PrivateTag +(0047,"GEMS_ADWSoft_3D1",61) DS VolumeCenterPoint 3 PrivateTag +(0047,"GEMS_ADWSoft_3D1",63) SL VolumeSkewBase 1 PrivateTag +(0047,"GEMS_ADWSoft_3D1",64) DS VolumeRegistrationTransformRotationMatrix 9 PrivateTag +(0047,"GEMS_ADWSoft_3D1",65) DS VolumeRegistrationTransformTranslationVector 3 PrivateTag +(0047,"GEMS_ADWSoft_3D1",70) DS KVPList 1-n PrivateTag +(0047,"GEMS_ADWSoft_3D1",71) IS XRayTubeCurrentList 1-n PrivateTag +(0047,"GEMS_ADWSoft_3D1",72) IS ExposureList 1-n PrivateTag +(0047,"GEMS_ADWSoft_3D1",80) LO AcquisitionDLXIdentifier 1 PrivateTag +(0047,"GEMS_ADWSoft_3D1",85) SQ AcquisitionDLX2DSeriesSequence 1 PrivateTag +(0047,"GEMS_ADWSoft_3D1",89) DS ContrastAgentVolumeList 1-n PrivateTag +(0047,"GEMS_ADWSoft_3D1",8A) US NumberOfInjections 1 PrivateTag +(0047,"GEMS_ADWSoft_3D1",8B) US FrameCount 1 PrivateTag +(0047,"GEMS_ADWSoft_3D1",91) LO XA3DReconstructionAlgorithmName 1 PrivateTag +(0047,"GEMS_ADWSoft_3D1",92) CS XA3DReconstructionAlgorithmVersion 1 PrivateTag +(0047,"GEMS_ADWSoft_3D1",93) DA DLXCalibrationDate 1 PrivateTag +(0047,"GEMS_ADWSoft_3D1",94) TM DLXCalibrationTime 1 PrivateTag +(0047,"GEMS_ADWSoft_3D1",95) CS DLXCalibrationStatus 1 PrivateTag +(0047,"GEMS_ADWSoft_3D1",96) IS UsedFrames 1-n PrivateTag +(0047,"GEMS_ADWSoft_3D1",98) US TransformCount 1 PrivateTag +(0047,"GEMS_ADWSoft_3D1",99) SQ TransformSequence 1 PrivateTag +(0047,"GEMS_ADWSoft_3D1",9A) DS TransformRotationMatrix 9 PrivateTag +(0047,"GEMS_ADWSoft_3D1",9B) DS TransformTranslationVector 3 PrivateTag +(0047,"GEMS_ADWSoft_3D1",9C) LO TransformLabel 1 PrivateTag +(0047,"GEMS_ADWSoft_3D1",B0) SQ WireframeList 1 PrivateTag +(0047,"GEMS_ADWSoft_3D1",B1) US WireframeCount 1 PrivateTag +(0047,"GEMS_ADWSoft_3D1",B2) US LocationSystem 1 PrivateTag +(0047,"GEMS_ADWSoft_3D1",B5) LO WireframeName 1 PrivateTag +(0047,"GEMS_ADWSoft_3D1",B6) LO WireframeGroupName 1 PrivateTag +(0047,"GEMS_ADWSoft_3D1",B7) LO WireframeColor 1 PrivateTag +(0047,"GEMS_ADWSoft_3D1",B8) SL WireframeAttributes 1 PrivateTag +(0047,"GEMS_ADWSoft_3D1",B9) SL WireframePointCount 1 PrivateTag +(0047,"GEMS_ADWSoft_3D1",BA) SL WireframeTimestamp 1 PrivateTag +(0047,"GEMS_ADWSoft_3D1",BB) SQ WireframePointList 1 PrivateTag +(0047,"GEMS_ADWSoft_3D1",BC) DS WireframePointsCoordinates 3 PrivateTag +(0047,"GEMS_ADWSoft_3D1",C0) DS VolumeUpperLeftHighCornerRAS 3 PrivateTag +(0047,"GEMS_ADWSoft_3D1",C1) DS VolumeSliceToRASRotationMatrix 9 PrivateTag +(0047,"GEMS_ADWSoft_3D1",C2) DS VolumeUpperLeftHighCornerTLOC 1 PrivateTag +(0047,"GEMS_ADWSoft_3D1",D1) OB VolumeSegmentList 1 PrivateTag +(0047,"GEMS_ADWSoft_3D1",D2) OB VolumeGradientList 1 PrivateTag +(0047,"GEMS_ADWSoft_3D1",D3) OB VolumeDensityList 1 PrivateTag +(0047,"GEMS_ADWSoft_3D1",D4) OB VolumeZPositionList 1 PrivateTag +(0047,"GEMS_ADWSoft_3D1",D5) OB VolumeOriginalIndexList 1 PrivateTag +(0039,"GEMS_ADWSoft_DPO",80) IS PrivateEntityNumber 1 PrivateTag +(0039,"GEMS_ADWSoft_DPO",85) DA PrivateEntityDate 1 PrivateTag +(0039,"GEMS_ADWSoft_DPO",90) TM PrivateEntityTime 1 PrivateTag +(0039,"GEMS_ADWSoft_DPO",95) LO PrivateEntityLaunchCommand 1 PrivateTag +(0039,"GEMS_ADWSoft_DPO",AA) CS PrivateEntityType 1 PrivateTag + +(0033,"GEMS_CTHD_01",02) UN Unknown 1 PrivateTag + +(0037,"GEMS_DRS_1",10) LO ReferringDepartment 1 PrivateTag +(0037,"GEMS_DRS_1",20) US ScreenNumber 1 PrivateTag +(0037,"GEMS_DRS_1",40) SH LeftOrientation 1 PrivateTag +(0037,"GEMS_DRS_1",42) SH RightOrientation 1 PrivateTag +(0037,"GEMS_DRS_1",50) CS Inversion 1 PrivateTag +(0037,"GEMS_DRS_1",60) US DSA 1 PrivateTag + +(0009,"GEMS_GENIE_1",10) LO Unknown 1 PrivateTag +(0009,"GEMS_GENIE_1",11) SL StudyFlags 1 PrivateTag +(0009,"GEMS_GENIE_1",12) SL StudyType 1 PrivateTag +(0009,"GEMS_GENIE_1",1e) UI Unknown 1 PrivateTag +(0009,"GEMS_GENIE_1",20) LO Unknown 1 PrivateTag +(0009,"GEMS_GENIE_1",21) SL SeriesFlags 1 PrivateTag +(0009,"GEMS_GENIE_1",22) SH UserOrientation 1 PrivateTag +(0009,"GEMS_GENIE_1",23) SL InitiationType 1 PrivateTag +(0009,"GEMS_GENIE_1",24) SL InitiationDelay 1 PrivateTag +(0009,"GEMS_GENIE_1",25) SL InitiationCountRate 1 PrivateTag +(0009,"GEMS_GENIE_1",26) SL NumberEnergySets 1 PrivateTag +(0009,"GEMS_GENIE_1",27) SL NumberDetectors 1 PrivateTag +(0009,"GEMS_GENIE_1",29) SL Unknown 1 PrivateTag +(0009,"GEMS_GENIE_1",2a) SL Unknown 1 PrivateTag +(0009,"GEMS_GENIE_1",2c) LO SeriesComments 1 PrivateTag +(0009,"GEMS_GENIE_1",2d) SL TrackBeatAverage 1 PrivateTag +(0009,"GEMS_GENIE_1",2e) FD DistancePrescribed 1 PrivateTag +(0009,"GEMS_GENIE_1",30) LO Unknown 1 PrivateTag +(0009,"GEMS_GENIE_1",35) SL GantryLocusType 1 PrivateTag +(0009,"GEMS_GENIE_1",37) SL StartingHeartRate 1 PrivateTag +(0009,"GEMS_GENIE_1",38) SL RRWindowWidth 1 PrivateTag +(0009,"GEMS_GENIE_1",39) SL RRWindowOffset 1 PrivateTag +(0009,"GEMS_GENIE_1",3a) SL PercentCycleImaged 1 PrivateTag +(0009,"GEMS_GENIE_1",40) LO Unknown 1 PrivateTag +(0009,"GEMS_GENIE_1",41) SL PatientFlags 1 PrivateTag +(0009,"GEMS_GENIE_1",42) DA PatientCreationDate 1 PrivateTag +(0009,"GEMS_GENIE_1",43) TM PatientCreationTime 1 PrivateTag +(0011,"GEMS_GENIE_1",0a) SL SeriesType 1 PrivateTag +(0011,"GEMS_GENIE_1",0b) SL EffectiveSeriesDuration 1 PrivateTag +(0011,"GEMS_GENIE_1",0c) SL NumBeats 1 PrivateTag +(0011,"GEMS_GENIE_1",0d) LO RadioNuclideName 1 PrivateTag +(0011,"GEMS_GENIE_1",10) LO Unknown 1 PrivateTag +(0011,"GEMS_GENIE_1",12) LO DatasetName 1 PrivateTag +(0011,"GEMS_GENIE_1",13) SL DatasetType 1 PrivateTag +(0011,"GEMS_GENIE_1",15) SL DetectorNumber 1 PrivateTag +(0011,"GEMS_GENIE_1",16) SL EnergyNumber 1 PrivateTag +(0011,"GEMS_GENIE_1",17) SL RRIntervalWindowNumber 1 PrivateTag +(0011,"GEMS_GENIE_1",18) SL MGBinNumber 1 PrivateTag +(0011,"GEMS_GENIE_1",19) FD RadiusOfRotation 1 PrivateTag +(0011,"GEMS_GENIE_1",1a) SL DetectorCountZone 1 PrivateTag +(0011,"GEMS_GENIE_1",1b) SL NumEnergyWindows 1 PrivateTag +(0011,"GEMS_GENIE_1",1c) SL EnergyOffset 4 PrivateTag +(0011,"GEMS_GENIE_1",1d) SL EnergyRange 1 PrivateTag +(0011,"GEMS_GENIE_1",1f) SL ImageOrientation 1 PrivateTag +(0011,"GEMS_GENIE_1",23) SL UseFOVMask 1 PrivateTag +(0011,"GEMS_GENIE_1",24) SL FOVMaskYCutoffAngle 1 PrivateTag +(0011,"GEMS_GENIE_1",25) SL FOVMaskCutoffAngle 1 PrivateTag +(0011,"GEMS_GENIE_1",26) SL TableOrientation 1 PrivateTag +(0011,"GEMS_GENIE_1",27) SL ROITopLeft 2 PrivateTag +(0011,"GEMS_GENIE_1",28) SL ROIBottomRight 2 PrivateTag +(0011,"GEMS_GENIE_1",30) LO Unknown 1 PrivateTag +(0011,"GEMS_GENIE_1",33) LO EnergyCorrectName 1 PrivateTag +(0011,"GEMS_GENIE_1",34) LO SpatialCorrectName 1 PrivateTag +(0011,"GEMS_GENIE_1",35) LO TuningCalibName 1 PrivateTag +(0011,"GEMS_GENIE_1",36) LO UniformityCorrectName 1 PrivateTag +(0011,"GEMS_GENIE_1",37) LO AcquisitionSpecificCorrectName 1 PrivateTag +(0011,"GEMS_GENIE_1",38) SL ByteOrder 1 PrivateTag +(0011,"GEMS_GENIE_1",3a) SL PictureFormat 1 PrivateTag +(0011,"GEMS_GENIE_1",3b) FD PixelScale 1 PrivateTag +(0011,"GEMS_GENIE_1",3c) FD PixelOffset 1 PrivateTag +(0011,"GEMS_GENIE_1",3e) SL FOVShape 1 PrivateTag +(0011,"GEMS_GENIE_1",3f) SL DatasetFlags 1 PrivateTag +(0011,"GEMS_GENIE_1",44) FD ThresholdCenter 1 PrivateTag +(0011,"GEMS_GENIE_1",45) FD ThresholdWidth 1 PrivateTag +(0011,"GEMS_GENIE_1",46) SL InterpolationType 1 PrivateTag +(0011,"GEMS_GENIE_1",55) FD Period 1 PrivateTag +(0011,"GEMS_GENIE_1",56) FD ElapsedTime 1 PrivateTag +(0013,"GEMS_GENIE_1",10) FD DigitalFOV 2 PrivateTag +(0013,"GEMS_GENIE_1",11) SL Unknown 1 PrivateTag +(0013,"GEMS_GENIE_1",12) SL Unknown 1 PrivateTag +(0013,"GEMS_GENIE_1",16) SL AutoTrackPeak 1 PrivateTag +(0013,"GEMS_GENIE_1",17) SL AutoTrackWidth 1 PrivateTag +(0013,"GEMS_GENIE_1",18) FD TransmissionScanTime 1 PrivateTag +(0013,"GEMS_GENIE_1",19) FD TransmissionMaskWidth 1 PrivateTag +(0013,"GEMS_GENIE_1",1a) FD CopperAttenuatorThickness 1 PrivateTag +(0013,"GEMS_GENIE_1",1c) FD Unknown 1 PrivateTag +(0013,"GEMS_GENIE_1",1d) FD Unknown 1 PrivateTag +(0013,"GEMS_GENIE_1",1e) FD TomoViewOffset 1-n PrivateTag +(0013,"GEMS_GENIE_1",26) LT StudyComments 1 PrivateTag + +(0033,"GEMS_GNHD_01",01) UN Unknown 1 PrivateTag +(0033,"GEMS_GNHD_01",02) UN Unknown 1 PrivateTag + +(0009,"GEMS_IDEN_01",01) LO FullFidelity 1 PrivateTag +(0009,"GEMS_IDEN_01",02) SH SuiteId 1 PrivateTag +(0009,"GEMS_IDEN_01",04) SH ProductId 1 PrivateTag +(0009,"GEMS_IDEN_01",17) LT Unknown 1 PrivateTag +(0009,"GEMS_IDEN_01",1a) US Unknown 1 PrivateTag +(0009,"GEMS_IDEN_01",20) US Unknown 1 PrivateTag +(0009,"GEMS_IDEN_01",27) SL ImageActualDate 1 PrivateTag +(0009,"GEMS_IDEN_01",2f) LT Unknown 1 PrivateTag +(0009,"GEMS_IDEN_01",30) SH ServiceId 1 PrivateTag +(0009,"GEMS_IDEN_01",31) SH MobileLocationNumber 1 PrivateTag +(0009,"GEMS_IDEN_01",e2) LT Unknown 1 PrivateTag +(0009,"GEMS_IDEN_01",e3) UI EquipmentUID 1 PrivateTag +(0009,"GEMS_IDEN_01",e6) SH GenesisVersionNow 1 PrivateTag +(0009,"GEMS_IDEN_01",e7) UL ExamRecordChecksum 1 PrivateTag +(0009,"GEMS_IDEN_01",e8) UL Unknown 1 PrivateTag +(0009,"GEMS_IDEN_01",e9) SL ActualSeriesDataTimeStamp 1 PrivateTag + +(0027,"GEMS_IMAG_01",06) SL ImageArchiveFlag 1 PrivateTag +(0027,"GEMS_IMAG_01",10) SS ScoutType 1 PrivateTag +(0027,"GEMS_IMAG_01",1c) SL VmaMamp 1 PrivateTag +(0027,"GEMS_IMAG_01",1d) SS VmaPhase 1 PrivateTag +(0027,"GEMS_IMAG_01",1e) SL VmaMod 1 PrivateTag +(0027,"GEMS_IMAG_01",1f) SL VmaClip 1 PrivateTag +(0027,"GEMS_IMAG_01",20) SS SmartScanOnOffFlag 1 PrivateTag +(0027,"GEMS_IMAG_01",30) SH ForeignImageRevision 1 PrivateTag +(0027,"GEMS_IMAG_01",31) SS ImagingMode 1 PrivateTag +(0027,"GEMS_IMAG_01",32) SS PulseSequence 1 PrivateTag +(0027,"GEMS_IMAG_01",33) SL ImagingOptions 1 PrivateTag +(0027,"GEMS_IMAG_01",35) SS PlaneType 1 PrivateTag +(0027,"GEMS_IMAG_01",36) SL ObliquePlane 1 PrivateTag +(0027,"GEMS_IMAG_01",40) SH RASLetterOfImageLocation 1 PrivateTag +(0027,"GEMS_IMAG_01",41) FL ImageLocation 1 PrivateTag +(0027,"GEMS_IMAG_01",42) FL CenterRCoordOfPlaneImage 1 PrivateTag +(0027,"GEMS_IMAG_01",43) FL CenterACoordOfPlaneImage 1 PrivateTag +(0027,"GEMS_IMAG_01",44) FL CenterSCoordOfPlaneImage 1 PrivateTag +(0027,"GEMS_IMAG_01",45) FL NormalRCoord 1 PrivateTag +(0027,"GEMS_IMAG_01",46) FL NormalACoord 1 PrivateTag +(0027,"GEMS_IMAG_01",47) FL NormalSCoord 1 PrivateTag +(0027,"GEMS_IMAG_01",48) FL RCoordOfTopRightCorner 1 PrivateTag +(0027,"GEMS_IMAG_01",49) FL ACoordOfTopRightCorner 1 PrivateTag +(0027,"GEMS_IMAG_01",4a) FL SCoordOfTopRightCorner 1 PrivateTag +(0027,"GEMS_IMAG_01",4b) FL RCoordOfBottomRightCorner 1 PrivateTag +(0027,"GEMS_IMAG_01",4c) FL ACoordOfBottomRightCorner 1 PrivateTag +(0027,"GEMS_IMAG_01",4d) FL SCoordOfBottomRightCorner 1 PrivateTag +(0027,"GEMS_IMAG_01",50) FL TableStartLocation 1 PrivateTag +(0027,"GEMS_IMAG_01",51) FL TableEndLocation 1 PrivateTag +(0027,"GEMS_IMAG_01",52) SH RASLetterForSideOfImage 1 PrivateTag +(0027,"GEMS_IMAG_01",53) SH RASLetterForAnteriorPosterior 1 PrivateTag +(0027,"GEMS_IMAG_01",54) SH RASLetterForScoutStartLoc 1 PrivateTag +(0027,"GEMS_IMAG_01",55) SH RASLetterForScoutEndLoc 1 PrivateTag +(0027,"GEMS_IMAG_01",60) FL ImageDimensionX 1 PrivateTag +(0027,"GEMS_IMAG_01",61) FL ImageDimensionY 1 PrivateTag +(0027,"GEMS_IMAG_01",62) FL NumberOfExcitations 1 PrivateTag + +(0029,"GEMS_IMPS_01",04) SL LowerRangeOfPixels 1 PrivateTag +(0029,"GEMS_IMPS_01",05) DS LowerRangeOfPixels 1 PrivateTag +(0029,"GEMS_IMPS_01",06) DS LowerRangeOfPixels 1 PrivateTag +(0029,"GEMS_IMPS_01",07) SL LowerRangeOfPixels 1 PrivateTag +(0029,"GEMS_IMPS_01",08) SH LowerRangeOfPixels 1 PrivateTag +(0029,"GEMS_IMPS_01",09) SH LowerRangeOfPixels 1 PrivateTag +(0029,"GEMS_IMPS_01",0a) SS LowerRangeOfPixels 1 PrivateTag +(0029,"GEMS_IMPS_01",15) SL LowerRangeOfPixels 1 PrivateTag +(0029,"GEMS_IMPS_01",16) SL LowerRangeOfPixels 1 PrivateTag +(0029,"GEMS_IMPS_01",17) SL LowerRangeOfPixels 1 PrivateTag +(0029,"GEMS_IMPS_01",18) SL UpperRangeOfPixels 1 PrivateTag +(0029,"GEMS_IMPS_01",1a) SL LengthOfTotalHeaderInBytes 1 PrivateTag +(0029,"GEMS_IMPS_01",26) SS VersionOfHeaderStructure 1 PrivateTag +(0029,"GEMS_IMPS_01",34) SL AdvantageCompOverflow 1 PrivateTag +(0029,"GEMS_IMPS_01",35) SL AdvantageCompUnderflow 1 PrivateTag + +(0043,"GEMS_PARM_01",01) SS BitmapOfPrescanOptions 1 PrivateTag +(0043,"GEMS_PARM_01",02) SS GradientOffsetInX 1 PrivateTag +(0043,"GEMS_PARM_01",03) SS GradientOffsetInY 1 PrivateTag +(0043,"GEMS_PARM_01",04) SS GradientOffsetInZ 1 PrivateTag +(0043,"GEMS_PARM_01",05) SS ImageIsOriginalOrUnoriginal 1 PrivateTag +(0043,"GEMS_PARM_01",06) SS NumberOfEPIShots 1 PrivateTag +(0043,"GEMS_PARM_01",07) SS ViewsPerSegment 1 PrivateTag +(0043,"GEMS_PARM_01",08) SS RespiratoryRateInBPM 1 PrivateTag +(0043,"GEMS_PARM_01",09) SS RespiratoryTriggerPoint 1 PrivateTag +(0043,"GEMS_PARM_01",0a) SS TypeOfReceiverUsed 1 PrivateTag +(0043,"GEMS_PARM_01",0b) DS PeakRateOfChangeOfGradientField 1 PrivateTag +(0043,"GEMS_PARM_01",0c) DS LimitsInUnitsOfPercent 1 PrivateTag +(0043,"GEMS_PARM_01",0d) DS PSDEstimatedLimit 1 PrivateTag +(0043,"GEMS_PARM_01",0e) DS PSDEstimatedLimitInTeslaPerSecond 1 PrivateTag +(0043,"GEMS_PARM_01",0f) DS SARAvgHead 1 PrivateTag +(0043,"GEMS_PARM_01",10) US WindowValue 1 PrivateTag +(0043,"GEMS_PARM_01",11) US TotalInputViews 1 PrivateTag +(0043,"GEMS_PARM_01",12) SS XrayChain 3 PrivateTag +(0043,"GEMS_PARM_01",13) SS ReconKernelParameters 5 PrivateTag +(0043,"GEMS_PARM_01",14) SS CalibrationParameters 3 PrivateTag +(0043,"GEMS_PARM_01",15) SS TotalOutputViews 3 PrivateTag +(0043,"GEMS_PARM_01",16) SS NumberOfOverranges 5 PrivateTag +(0043,"GEMS_PARM_01",17) DS IBHImageScaleFactors 1 PrivateTag +(0043,"GEMS_PARM_01",18) DS BBHCoefficients 3 PrivateTag +(0043,"GEMS_PARM_01",19) SS NumberOfBBHChainsToBlend 1 PrivateTag +(0043,"GEMS_PARM_01",1a) SL StartingChannelNumber 1 PrivateTag +(0043,"GEMS_PARM_01",1b) SS PPScanParameters 1 PrivateTag +(0043,"GEMS_PARM_01",1c) SS GEImageIntegrity 1 PrivateTag +(0043,"GEMS_PARM_01",1d) SS LevelValue 1 PrivateTag +(0043,"GEMS_PARM_01",1e) DS DeltaStartTime 1 PrivateTag +(0043,"GEMS_PARM_01",1f) SL MaxOverrangesInAView 1 PrivateTag +(0043,"GEMS_PARM_01",20) DS AvgOverrangesAllViews 1 PrivateTag +(0043,"GEMS_PARM_01",21) SS CorrectedAfterglowTerms 1 PrivateTag +(0043,"GEMS_PARM_01",25) SS ReferenceChannels 6 PrivateTag +(0043,"GEMS_PARM_01",26) US NoViewsRefChannelsBlocked 6 PrivateTag +(0043,"GEMS_PARM_01",27) SH ScanPitchRatio 1 PrivateTag +(0043,"GEMS_PARM_01",28) OB UniqueImageIdentifier 1 PrivateTag +(0043,"GEMS_PARM_01",29) OB HistogramTables 1 PrivateTag +(0043,"GEMS_PARM_01",2a) OB UserDefinedData 1 PrivateTag +(0043,"GEMS_PARM_01",2b) SS PrivateScanOptions 4 PrivateTag +(0043,"GEMS_PARM_01",2c) SS EffectiveEchoSpacing 1 PrivateTag +(0043,"GEMS_PARM_01",2d) SH StringSlopField1 1 PrivateTag +(0043,"GEMS_PARM_01",2e) SH StringSlopField2 1 PrivateTag +(0043,"GEMS_PARM_01",2f) SS RawDataType 1 PrivateTag +(0043,"GEMS_PARM_01",30) SS RawDataType 1 PrivateTag +(0043,"GEMS_PARM_01",31) DS RACoordOfTargetReconCentre 2 PrivateTag +(0043,"GEMS_PARM_01",32) SS RawDataType 1 PrivateTag +(0043,"GEMS_PARM_01",33) FL NegScanSpacing 1 PrivateTag +(0043,"GEMS_PARM_01",34) IS OffsetFrequency 1 PrivateTag +(0043,"GEMS_PARM_01",35) UL UserUsageTag 1 PrivateTag +(0043,"GEMS_PARM_01",36) UL UserFillMapMSW 1 PrivateTag +(0043,"GEMS_PARM_01",37) UL UserFillMapLSW 1 PrivateTag +(0043,"GEMS_PARM_01",38) FL User25ToUser48 24 PrivateTag +(0043,"GEMS_PARM_01",39) IS SlopInteger6ToSlopInteger9 4 PrivateTag +(0043,"GEMS_PARM_01",40) FL TriggerOnPosition 4 PrivateTag +(0043,"GEMS_PARM_01",41) FL DegreeOfRotation 4 PrivateTag +(0043,"GEMS_PARM_01",42) SL DASTriggerSource 4 PrivateTag +(0043,"GEMS_PARM_01",43) SL DASFpaGain 4 PrivateTag +(0043,"GEMS_PARM_01",44) SL DASOutputSource 4 PrivateTag +(0043,"GEMS_PARM_01",45) SL DASAdInput 4 PrivateTag +(0043,"GEMS_PARM_01",46) SL DASCalMode 4 PrivateTag +(0043,"GEMS_PARM_01",47) SL DASCalFrequency 4 PrivateTag +(0043,"GEMS_PARM_01",48) SL DASRegXm 4 PrivateTag +(0043,"GEMS_PARM_01",49) SL DASAutoZero 4 PrivateTag +(0043,"GEMS_PARM_01",4a) SS StartingChannelOfView 4 PrivateTag +(0043,"GEMS_PARM_01",4b) SL DASXmPattern 4 PrivateTag +(0043,"GEMS_PARM_01",4c) SS TGGCTriggerMode 4 PrivateTag +(0043,"GEMS_PARM_01",4d) FL StartScanToXrayOnDelay 4 PrivateTag +(0043,"GEMS_PARM_01",4e) FL DurationOfXrayOn 4 PrivateTag +(0043,"GEMS_PARM_01",60) IS SlopInteger10ToSlopInteger17 8 PrivateTag +(0043,"GEMS_PARM_01",61) UI ScannerStudyEntityUID 1 PrivateTag +(0043,"GEMS_PARM_01",62) SH ScannerStudyID 1 PrivateTag +(0043,"GEMS_PARM_01",6f) DS ScannerTableEntry 3 PrivateTag +(0043,"GEMS_PARM_01",70) LO ParadigmName 1 PrivateTag +(0043,"GEMS_PARM_01",71) ST ParadigmDescription 1 PrivateTag +(0043,"GEMS_PARM_01",72) UI ParadigmUID 1 PrivateTag +(0043,"GEMS_PARM_01",73) US ExperimentType 1 PrivateTag +(0043,"GEMS_PARM_01",74) US NumberOfRestVolumes 1 PrivateTag +(0043,"GEMS_PARM_01",75) US NumberOfActiveVolumes 1 PrivateTag +(0043,"GEMS_PARM_01",76) US NumberOfDummyScans 1 PrivateTag +(0043,"GEMS_PARM_01",77) SH ApplicationName 1 PrivateTag +(0043,"GEMS_PARM_01",78) SH ApplicationVersion 1 PrivateTag +(0043,"GEMS_PARM_01",79) US SlicesPerVolume 1 PrivateTag +(0043,"GEMS_PARM_01",7a) US ExpectedTimePoints 1 PrivateTag +(0043,"GEMS_PARM_01",7b) FL RegressorValues 1-n PrivateTag +(0043,"GEMS_PARM_01",7c) FL DelayAfterSliceGroup 1 PrivateTag +(0043,"GEMS_PARM_01",7d) US ReconModeFlagWord 1 PrivateTag +(0043,"GEMS_PARM_01",7e) LO PACCSpecificInformation 1-n PrivateTag +(0043,"GEMS_PARM_01",7f) DS EDWIScaleFactor 1-n PrivateTag +(0043,"GEMS_PARM_01",80) LO CoilIDData 1-n PrivateTag +(0043,"GEMS_PARM_01",81) LO GECoilName 1 PrivateTag +(0043,"GEMS_PARM_01",82) LO SystemConfigurationInformation 1-n PrivateTag +(0043,"GEMS_PARM_01",83) DS AssetRFactors 1-2 PrivateTag +(0043,"GEMS_PARM_01",84) LO AdditionalAssetData 5-n PrivateTag +(0043,"GEMS_PARM_01",85) UT DebugDataTextFormat 1 PrivateTag +(0043,"GEMS_PARM_01",86) OB DebugDataBinaryFormat 1 PrivateTag +(0043,"GEMS_PARM_01",87) UT ScannerSoftwareVersionLongForm 1 PrivateTag +(0043,"GEMS_PARM_01",88) UI PUREAcquisitionCalibrationSeriesUID 1 PrivateTag +(0043,"GEMS_PARM_01",89) LO GoverningBodydBdtAndSARDefinition 3 PrivateTag +(0043,"GEMS_PARM_01",8a) CS PrivateInPlanePhaseEncodingDirection 1 PrivateTag +(0043,"GEMS_PARM_01",8b) OB FMRIBinaryDataBlock 1 PrivateTag +(0043,"GEMS_PARM_01",8c) DS VoxelLocation 6 PrivateTag +(0043,"GEMS_PARM_01",8d) DS SATBandLocations 7-7n PrivateTag +(0043,"GEMS_PARM_01",8e) DS SpectroPrescanValues 3 PrivateTag +(0043,"GEMS_PARM_01",8f) DS SpectroParameters 3 PrivateTag +(0043,"GEMS_PARM_01",90) LO SARDefinition 1-n PrivateTag +(0043,"GEMS_PARM_01",91) DS SARValue 1-n PrivateTag +(0043,"GEMS_PARM_01",92) LO ImageErrorText 1 PrivateTag +(0043,"GEMS_PARM_01",93) DS SpectroQuantitationValues 1-n PrivateTag +(0043,"GEMS_PARM_01",94) DS SpectroRatioValues 1-n PrivateTag +(0043,"GEMS_PARM_01",95) LO PrescanReuseString 1 PrivateTag +(0043,"GEMS_PARM_01",96) CS ContentQualification 1 PrivateTag +(0043,"GEMS_PARM_01",97) LO ImageFilteringParameters 9 PrivateTag +(0043,"GEMS_PARM_01",98) UI ASSETAcquisitionCalibrationSeriesUID 1 PrivateTag +(0043,"GEMS_PARM_01",99) LO ExtendedOptions 1-n PrivateTag +(0043,"GEMS_PARM_01",9a) IS RxStackIdentification 1 PrivateTag +(0043,"GEMS_PARM_01",9b) DS NPWFactor 1 PrivateTag +(0043,"GEMS_PARM_01",9c) OB ResearchTag1 1 PrivateTag +(0043,"GEMS_PARM_01",9d) OB ResearchTag2 1 PrivateTag +(0043,"GEMS_PARM_01",9e) OB ResearchTag3 1 PrivateTag +(0043,"GEMS_PARM_01",9f) OB ResearchTag4 1 PrivateTag + +(0011,"GEMS_PATI_01",10) SS PatientStatus 1 PrivateTag + +(0021,"GEMS_RELA_01",03) SS SeriesFromWhichPrescribed 1 PrivateTag +(0021,"GEMS_RELA_01",05) SH GenesisVersionNow 1 PrivateTag +(0021,"GEMS_RELA_01",07) UL SeriesRecordChecksum 1 PrivateTag +(0021,"GEMS_RELA_01",15) US Unknown 1 PrivateTag +(0021,"GEMS_RELA_01",16) SS Unknown 1 PrivateTag +(0021,"GEMS_RELA_01",18) SH GenesisVersionNow 1 PrivateTag +(0021,"GEMS_RELA_01",19) UL AcqReconRecordChecksum 1 PrivateTag +(0021,"GEMS_RELA_01",20) DS TableStartLocation 1 PrivateTag +(0021,"GEMS_RELA_01",35) SS SeriesFromWhichPrescribed 1 PrivateTag +(0021,"GEMS_RELA_01",36) SS ImageFromWhichPrescribed 1 PrivateTag +(0021,"GEMS_RELA_01",37) SS ScreenFormat 1 PrivateTag +(0021,"GEMS_RELA_01",4a) LO AnatomicalReferenceForScout 1 PrivateTag +(0021,"GEMS_RELA_01",4e) US Unknown 1 PrivateTag +(0021,"GEMS_RELA_01",4f) SS LocationsInAcquisition 1 PrivateTag +(0021,"GEMS_RELA_01",50) SS GraphicallyPrescribed 1 PrivateTag +(0021,"GEMS_RELA_01",51) DS RotationFromSourceXRot 1 PrivateTag +(0021,"GEMS_RELA_01",52) DS RotationFromSourceYRot 1 PrivateTag +(0021,"GEMS_RELA_01",53) DS RotationFromSourceZRot 1 PrivateTag +(0021,"GEMS_RELA_01",54) SH ImagePosition 3 PrivateTag +(0021,"GEMS_RELA_01",55) SH ImageOrientation 6 PrivateTag +(0021,"GEMS_RELA_01",56) SL IntegerSlop 1 PrivateTag +(0021,"GEMS_RELA_01",57) SL IntegerSlop 1 PrivateTag +(0021,"GEMS_RELA_01",58) SL IntegerSlop 1 PrivateTag +(0021,"GEMS_RELA_01",59) SL IntegerSlop 1 PrivateTag +(0021,"GEMS_RELA_01",5a) SL IntegerSlop 1 PrivateTag +(0021,"GEMS_RELA_01",5b) DS FloatSlop 1 PrivateTag +(0021,"GEMS_RELA_01",5c) DS FloatSlop 1 PrivateTag +(0021,"GEMS_RELA_01",5d) DS FloatSlop 1 PrivateTag +(0021,"GEMS_RELA_01",5e) DS FloatSlop 1 PrivateTag +(0021,"GEMS_RELA_01",5f) DS FloatSlop 1 PrivateTag +(0021,"GEMS_RELA_01",70) LT Unknown 1 PrivateTag +(0021,"GEMS_RELA_01",71) LT Unknown 1 PrivateTag +(0021,"GEMS_RELA_01",81) DS AutoWindowLevelAlpha 1 PrivateTag +(0021,"GEMS_RELA_01",82) DS AutoWindowLevelBeta 1 PrivateTag +(0021,"GEMS_RELA_01",83) DS AutoWindowLevelWindow 1 PrivateTag +(0021,"GEMS_RELA_01",84) DS AutoWindowLevelLevel 1 PrivateTag +(0021,"GEMS_RELA_01",90) SS TubeFocalSpotPosition 1 PrivateTag +(0021,"GEMS_RELA_01",91) SS BiopsyPosition 1 PrivateTag +(0021,"GEMS_RELA_01",92) FL BiopsyTLocation 1 PrivateTag +(0021,"GEMS_RELA_01",93) FL BiopsyRefLocation 1 PrivateTag + +(0045,"GEMS_SENO_02",04) CS AES 1 PrivateTag +(0045,"GEMS_SENO_02",06) DS Angulation 1 PrivateTag +(0045,"GEMS_SENO_02",09) DS RealMagnificationFactor 1 PrivateTag +(0045,"GEMS_SENO_02",0b) CS SenographType 1 PrivateTag +(0045,"GEMS_SENO_02",0c) DS IntegrationTime 1 PrivateTag +(0045,"GEMS_SENO_02",0d) DS ROIOriginXY 1 PrivateTag +(0045,"GEMS_SENO_02",11) DS ReceptorSizeCmXY 2 PrivateTag +(0045,"GEMS_SENO_02",12) IS ReceptorSizePixelsXY 2 PrivateTag +(0045,"GEMS_SENO_02",13) ST Screen 1 PrivateTag +(0045,"GEMS_SENO_02",14) DS PixelPitchMicrons 1 PrivateTag +(0045,"GEMS_SENO_02",15) IS PixelDepthBits 1 PrivateTag +(0045,"GEMS_SENO_02",16) IS BinningFactorXY 2 PrivateTag +(0045,"GEMS_SENO_02",1B) CS ClinicalView 1 PrivateTag +(0045,"GEMS_SENO_02",1D) DS MeanOfRawGrayLevels 1 PrivateTag +(0045,"GEMS_SENO_02",1E) DS MeanOfOffsetGrayLevels 1 PrivateTag +(0045,"GEMS_SENO_02",1F) DS MeanOfCorrectedGrayLevels 1 PrivateTag +(0045,"GEMS_SENO_02",20) DS MeanOfRegionGrayLevels 1 PrivateTag +(0045,"GEMS_SENO_02",21) DS MeanOfLogRegionGrayLevels 1 PrivateTag +(0045,"GEMS_SENO_02",22) DS StandardDeviationOfRawGrayLevels 1 PrivateTag +(0045,"GEMS_SENO_02",23) DS StandardDeviationOfCorrectedGrayLevels 1 PrivateTag +(0045,"GEMS_SENO_02",24) DS StandardDeviationOfRegionGrayLevels 1 PrivateTag +(0045,"GEMS_SENO_02",25) DS StandardDeviationOfLogRegionGrayLevels 1 PrivateTag +(0045,"GEMS_SENO_02",26) OB MAOBuffer 1 PrivateTag +(0045,"GEMS_SENO_02",27) IS SetNumber 1 PrivateTag +(0045,"GEMS_SENO_02",28) CS WindowingType 1 PrivateTag +(0045,"GEMS_SENO_02",29) DS WindowingParameters 1-n PrivateTag +(0045,"GEMS_SENO_02",2a) IS CrosshairCursorXCoordinates 1 PrivateTag +(0045,"GEMS_SENO_02",2b) IS CrosshairCursorYCoordinates 1 PrivateTag +(0045,"GEMS_SENO_02",39) US VignetteRows 1 PrivateTag +(0045,"GEMS_SENO_02",3a) US VignetteColumns 1 PrivateTag +(0045,"GEMS_SENO_02",3b) US VignetteBitsAllocated 1 PrivateTag +(0045,"GEMS_SENO_02",3c) US VignetteBitsStored 1 PrivateTag +(0045,"GEMS_SENO_02",3d) US VignetteHighBit 1 PrivateTag +(0045,"GEMS_SENO_02",3e) US VignettePixelRepresentation 1 PrivateTag +(0045,"GEMS_SENO_02",3f) OB VignettePixelData 1 PrivateTag + +(0025,"GEMS_SERS_01",06) SS LastPulseSequenceUsed 1 PrivateTag +(0025,"GEMS_SERS_01",07) SL ImagesInSeries 1 PrivateTag +(0025,"GEMS_SERS_01",10) SL LandmarkCounter 1 PrivateTag +(0025,"GEMS_SERS_01",11) SS NumberOfAcquisitions 1 PrivateTag +(0025,"GEMS_SERS_01",14) SL IndicatesNumberOfUpdatesToHeader 1 PrivateTag +(0025,"GEMS_SERS_01",17) SL SeriesCompleteFlag 1 PrivateTag +(0025,"GEMS_SERS_01",18) SL NumberOfImagesArchived 1 PrivateTag +(0025,"GEMS_SERS_01",19) SL LastImageNumberUsed 1 PrivateTag +(0025,"GEMS_SERS_01",1a) SH PrimaryReceiverSuiteAndHost 1 PrivateTag + +(0023,"GEMS_STDY_01",01) SL NumberOfSeriesInStudy 1 PrivateTag +(0023,"GEMS_STDY_01",02) SL NumberOfUnarchivedSeries 1 PrivateTag +(0023,"GEMS_STDY_01",10) SS ReferenceImageField 1 PrivateTag +(0023,"GEMS_STDY_01",50) SS SummaryImage 1 PrivateTag +(0023,"GEMS_STDY_01",70) FD StartTimeSecsInFirstAxial 1 PrivateTag +(0023,"GEMS_STDY_01",74) SL NumberOfUpdatesToHeader 1 PrivateTag +(0023,"GEMS_STDY_01",7d) SS IndicatesIfStudyHasCompleteInfo 1 PrivateTag + +(0033,"GEMS_YMHD_01",05) UN Unknown 1 PrivateTag +(0033,"GEMS_YMHD_01",06) UN Unknown 1 PrivateTag + +(0019,"GE_GENESIS_REV3.0",39) SS AxialType 1 PrivateTag +(0019,"GE_GENESIS_REV3.0",8f) SS SwapPhaseFrequency 1 PrivateTag +(0019,"GE_GENESIS_REV3.0",9c) SS PulseSequenceName 1 PrivateTag +(0019,"GE_GENESIS_REV3.0",9f) SS CoilType 1 PrivateTag +(0019,"GE_GENESIS_REV3.0",a4) SS SATFatWaterBone 1 PrivateTag +(0019,"GE_GENESIS_REV3.0",c0) SS BitmapOfSATSelections 1 PrivateTag +(0019,"GE_GENESIS_REV3.0",c1) SS SurfaceCoilIntensityCorrectionFlag 1 PrivateTag +(0019,"GE_GENESIS_REV3.0",cb) SS PhaseContrastFlowAxis 1 PrivateTag +(0019,"GE_GENESIS_REV3.0",cc) SS PhaseContrastVelocityEncoding 1 PrivateTag +(0019,"GE_GENESIS_REV3.0",d5) SS FractionalEcho 1 PrivateTag +(0019,"GE_GENESIS_REV3.0",d8) SS VariableEchoFlag 1 PrivateTag +(0019,"GE_GENESIS_REV3.0",d9) DS ConcatenatedSat 1 PrivateTag +(0019,"GE_GENESIS_REV3.0",f2) SS NumberOfPhases 1 PrivateTag +(0043,"GE_GENESIS_REV3.0",1e) DS DeltaStartTime 1 PrivateTag +(0043,"GE_GENESIS_REV3.0",27) SH ScanPitchRatio 1 PrivateTag + +(0029,"INTELERAD MEDICAL SYSTEMS",01) FD ImageCompressionFraction 1 PrivateTag +(0029,"INTELERAD MEDICAL SYSTEMS",02) FD ImageQuality 1 PrivateTag +(0029,"INTELERAD MEDICAL SYSTEMS",03) FD ImageBytesTransferred 1 PrivateTag +(0029,"INTELERAD MEDICAL SYSTEMS",10) SH J2cParameterType 1 PrivateTag +(0029,"INTELERAD MEDICAL SYSTEMS",11) US J2cPixelRepresentation 1 PrivateTag +(0029,"INTELERAD MEDICAL SYSTEMS",12) US J2cBitsAllocated 1 PrivateTag +(0029,"INTELERAD MEDICAL SYSTEMS",13) US J2cPixelShiftValue 1 PrivateTag +(0029,"INTELERAD MEDICAL SYSTEMS",14) US J2cPlanarConfiguration 1 PrivateTag +(0029,"INTELERAD MEDICAL SYSTEMS",15) DS J2cRescaleIntercept 1 PrivateTag +(0029,"INTELERAD MEDICAL SYSTEMS",20) LO PixelDataMD5SumPerFrame 1 PrivateTag +(0029,"INTELERAD MEDICAL SYSTEMS",21) US HistogramPercentileLabels 1 PrivateTag +(0029,"INTELERAD MEDICAL SYSTEMS",22) FD HistogramPercentileValues 1 PrivateTag +(3f01,"INTELERAD MEDICAL SYSTEMS",01) LO InstitutionCode 1 PrivateTag +(3f01,"INTELERAD MEDICAL SYSTEMS",02) LO RoutedTransferAE 1 PrivateTag +(3f01,"INTELERAD MEDICAL SYSTEMS",03) LO SourceAE 1 PrivateTag +(3f01,"INTELERAD MEDICAL SYSTEMS",04) SH DeferredValidation 1 PrivateTag +(3f01,"INTELERAD MEDICAL SYSTEMS",05) LO SeriesOwner 1 PrivateTag +(3f01,"INTELERAD MEDICAL SYSTEMS",06) LO OrderGroupNumber 1 PrivateTag +(3f01,"INTELERAD MEDICAL SYSTEMS",07) SH StrippedPixelData 1 PrivateTag +(3f01,"INTELERAD MEDICAL SYSTEMS",08) SH PendingMoveRequest 1 PrivateTag + +(0041,"INTEGRIS 1.0",20) FL AccumulatedFluoroscopyDose 1 PrivateTag +(0041,"INTEGRIS 1.0",30) FL AccumulatedExposureDose 1 PrivateTag +(0041,"INTEGRIS 1.0",40) FL TotalDose 1 PrivateTag +(0041,"INTEGRIS 1.0",41) FL TotalNumberOfFrames 1 PrivateTag +(0041,"INTEGRIS 1.0",50) SQ ExposureInformationSequence 1 PrivateTag +(0009,"INTEGRIS 1.0",08) CS ExposureChannel 1-n PrivateTag +(0009,"INTEGRIS 1.0",32) TM ExposureStartTime 1 PrivateTag +(0019,"INTEGRIS 1.0",00) LO APRName 1 PrivateTag +(0019,"INTEGRIS 1.0",40) DS FrameRate 1 PrivateTag +(0021,"INTEGRIS 1.0",12) IS ExposureNumber 1 PrivateTag +(0029,"INTEGRIS 1.0",08) IS NumberOfExposureResults 1 PrivateTag + +(0029,"ISG shadow",70) IS Unknown 1 PrivateTag +(0029,"ISG shadow",80) IS Unknown 1 PrivateTag +(0029,"ISG shadow",90) IS Unknown 1 PrivateTag + +(0009,"ISI",01) UN SIENETGeneralPurposeIMGEF 1 PrivateTag + +(0009,"MERGE TECHNOLOGIES, INC.",00) OB Unknown 1 PrivateTag + +(0029,"OCULUS Optikgeraete GmbH",1010) OB OriginalMeasuringData 1 PrivateTag +(0029,"OCULUS Optikgeraete GmbH",1012) UL OriginalMeasuringDataLength 1 PrivateTag +(0029,"OCULUS Optikgeraete GmbH",1020) OB OriginalMeasuringRawData 1 PrivateTag +(0029,"OCULUS Optikgeraete GmbH",1022) UL OriginalMeasuringRawDataLength 1 PrivateTag + +(0041,"PAPYRUS 3.0",00) LT PapyrusComments 1 PrivateTag +(0041,"PAPYRUS 3.0",10) SQ PointerSequence 1 PrivateTag +(0041,"PAPYRUS 3.0",11) UL ImagePointer 1 PrivateTag +(0041,"PAPYRUS 3.0",12) UL PixelOffset 1 PrivateTag +(0041,"PAPYRUS 3.0",13) SQ ImageIdentifierSequence 1 PrivateTag +(0041,"PAPYRUS 3.0",14) SQ ExternalFileReferenceSequence 1 PrivateTag +(0041,"PAPYRUS 3.0",15) US NumberOfImages 1 PrivateTag +(0041,"PAPYRUS 3.0",21) UI ReferencedSOPClassUID 1 PrivateTag +(0041,"PAPYRUS 3.0",22) UI ReferencedSOPInstanceUID 1 PrivateTag +(0041,"PAPYRUS 3.0",31) LT ReferencedFileName 1 PrivateTag +(0041,"PAPYRUS 3.0",32) LT ReferencedFilePath 1-n PrivateTag +(0041,"PAPYRUS 3.0",41) UI ReferencedImageSOPClassUID 1 PrivateTag +(0041,"PAPYRUS 3.0",42) UI ReferencedImageSOPInstanceUID 1 PrivateTag +(0041,"PAPYRUS 3.0",50) SQ ImageSequence 1 PrivateTag +(6001-o-60ff,"PAPYRUS 3.0",00) IS OverlayID 1 PrivateTag +(6001-o-60ff,"PAPYRUS 3.0",01) LT LinkedOverlays 1-n PrivateTag +(6001-o-60ff,"PAPYRUS 3.0",10) US OverlayRows 1 PrivateTag +(6001-o-60ff,"PAPYRUS 3.0",11) US OverlayColumns 1 PrivateTag +(6001-o-60ff,"PAPYRUS 3.0",40) LO OverlayType 1 PrivateTag +(6001-o-60ff,"PAPYRUS 3.0",50) US OverlayOrigin 1-n PrivateTag +(6001-o-60ff,"PAPYRUS 3.0",60) LO Editable 1 PrivateTag +(6001-o-60ff,"PAPYRUS 3.0",70) LO OverlayFont 1 PrivateTag +(6001-o-60ff,"PAPYRUS 3.0",72) LO OverlayStyle 1 PrivateTag +(6001-o-60ff,"PAPYRUS 3.0",74) US OverlayFontSize 1 PrivateTag +(6001-o-60ff,"PAPYRUS 3.0",76) LO OverlayColor 1 PrivateTag +(6001-o-60ff,"PAPYRUS 3.0",78) US ShadowSize 1 PrivateTag +(6001-o-60ff,"PAPYRUS 3.0",80) LO FillPattern 1 PrivateTag +(6001-o-60ff,"PAPYRUS 3.0",82) US OverlayPenSize 1 PrivateTag +(6001-o-60ff,"PAPYRUS 3.0",a0) LO Label 1 PrivateTag +(6001-o-60ff,"PAPYRUS 3.0",a2) LT PostItText 1 PrivateTag +(6001-o-60ff,"PAPYRUS 3.0",a4) US AnchorPoint 2 PrivateTag +(6001-o-60ff,"PAPYRUS 3.0",b0) LO ROIType 1 PrivateTag +(6001-o-60ff,"PAPYRUS 3.0",b2) LT AttachedAnnotation 1 PrivateTag +(6001-o-60ff,"PAPYRUS 3.0",ba) US ContourPoints 1-n PrivateTag +(6001-o-60ff,"PAPYRUS 3.0",bc) US MaskData 1-n PrivateTag +(6001-o-60ff,"PAPYRUS 3.0",c0) SQ UINOverlaySequence 1 PrivateTag + +(0009,"PAPYRUS",00) LT OriginalFileName 1 PrivateTag +(0009,"PAPYRUS",10) LT OriginalFileLocation 1 PrivateTag +(0009,"PAPYRUS",18) LT DataSetIdentifier 1 PrivateTag +(0041,"PAPYRUS",00) LT PapyrusComments 1-n PrivateTag +(0041,"PAPYRUS",10) US FolderType 1 PrivateTag +(0041,"PAPYRUS",11) LT PatientFolderDataSetID 1 PrivateTag +(0041,"PAPYRUS",20) LT FolderName 1 PrivateTag +(0041,"PAPYRUS",30) DA CreationDate 1 PrivateTag +(0041,"PAPYRUS",32) TM CreationTime 1 PrivateTag +(0041,"PAPYRUS",34) DA ModifiedDate 1 PrivateTag +(0041,"PAPYRUS",36) TM ModifiedTime 1 PrivateTag +(0041,"PAPYRUS",40) LT OwnerName 1-n PrivateTag +(0041,"PAPYRUS",50) LT FolderStatus 1 PrivateTag +(0041,"PAPYRUS",60) UL NumberOfImages 1 PrivateTag +(0041,"PAPYRUS",62) UL NumberOfOther 1 PrivateTag +(0041,"PAPYRUS",a0) LT ExternalFolderElementDSID 1-n PrivateTag +(0041,"PAPYRUS",a1) US ExternalFolderElementDataSetType 1-n PrivateTag +(0041,"PAPYRUS",a2) LT ExternalFolderElementFileLocation 1-n PrivateTag +(0041,"PAPYRUS",a3) UL ExternalFolderElementLength 1-n PrivateTag +(0041,"PAPYRUS",b0) LT InternalFolderElementDSID 1-n PrivateTag +(0041,"PAPYRUS",b1) US InternalFolderElementDataSetType 1-n PrivateTag +(0041,"PAPYRUS",b2) UL InternalOffsetToDataSet 1-n PrivateTag +(0041,"PAPYRUS",b3) UL InternalOffsetToImage 1-n + +# Note: Some Philips devices use these private tags with reservation value +# "Philips Imaging DD 001", others use "PHILIPS IMAGING DD 001". All attributes +# should thus be present twice in this dictionary, once for each spelling variant. +# +(2001,"Philips Imaging DD 001",01) FL ChemicalShift 1 PrivateTag +(2001,"Philips Imaging DD 001",02) IS ChemicalShiftNumberMR 1 PrivateTag +(2001,"Philips Imaging DD 001",03) FL DiffusionBFactor 1 PrivateTag +(2001,"Philips Imaging DD 001",04) CS DiffusionDirection 1 PrivateTag +(2001,"Philips Imaging DD 001",06) CS ImageEnhanced 1 PrivateTag +(2001,"Philips Imaging DD 001",07) CS ImageTypeEDES 1 PrivateTag +(2001,"Philips Imaging DD 001",08) IS PhaseNumber 1 PrivateTag +(2001,"Philips Imaging DD 001",09) FL ImagePrepulseDelay 1 PrivateTag +(2001,"Philips Imaging DD 001",0a) IS SliceNumberMR 1 PrivateTag +(2001,"Philips Imaging DD 001",0b) CS SliceOrientation 1 PrivateTag +(2001,"Philips Imaging DD 001",0c) CS ArrhythmiaRejection 1 PrivateTag +(2001,"Philips Imaging DD 001",0e) CS CardiacCycled 1 PrivateTag +(2001,"Philips Imaging DD 001",0f) SS CardiacGateWidth 1 PrivateTag +(2001,"Philips Imaging DD 001",10) CS CardiacSync 1 PrivateTag +(2001,"Philips Imaging DD 001",11) FL DiffusionEchoTime 1 PrivateTag +(2001,"Philips Imaging DD 001",12) CS DynamicSeries 1 PrivateTag +(2001,"Philips Imaging DD 001",13) SL EPIFactor 1 PrivateTag +(2001,"Philips Imaging DD 001",14) SL NumberOfEchoes 1 PrivateTag +(2001,"Philips Imaging DD 001",15) SS NumberOfLocations 1 PrivateTag +(2001,"Philips Imaging DD 001",16) SS NumberOfPCDirections 1 PrivateTag +(2001,"Philips Imaging DD 001",17) SL NumberOfPhasesMR 1 PrivateTag +(2001,"Philips Imaging DD 001",18) SL NumberOfSlicesMR 1 PrivateTag +(2001,"Philips Imaging DD 001",19) CS PartialMatrixScanned 1 PrivateTag +(2001,"Philips Imaging DD 001",1a) FL PCVelocity 1-n PrivateTag +(2001,"Philips Imaging DD 001",1b) FL PrepulseDelay 1 PrivateTag +(2001,"Philips Imaging DD 001",1c) CS PrepulseType 1 PrivateTag +(2001,"Philips Imaging DD 001",1d) IS ReconstructionNumberMR 1 PrivateTag +(2001,"Philips Imaging DD 001",1f) CS RespirationSync 1 PrivateTag +(2001,"Philips Imaging DD 001",20) LO ScanningTechnique 1 PrivateTag +(2001,"Philips Imaging DD 001",21) CS SPIR 1 PrivateTag +(2001,"Philips Imaging DD 001",22) FL WaterFatShift 1 PrivateTag +(2001,"Philips Imaging DD 001",23) DS FlipAnglePhilips 1 PrivateTag +(2001,"Philips Imaging DD 001",24) CS SeriesIsInteractive 1 PrivateTag +(2001,"Philips Imaging DD 001",25) SH EchoTimeDisplayMR 1 PrivateTag +(2001,"Philips Imaging DD 001",26) CS PresentationStateSubtractionActive 1 PrivateTag +(2001,"Philips Imaging DD 001",2d) SS StackNumberOfSlices 1 PrivateTag +(2001,"Philips Imaging DD 001",32) FL StackRadialAngle 1 PrivateTag +(2001,"Philips Imaging DD 001",33) CS StackRadialAxis 1 PrivateTag +(2001,"Philips Imaging DD 001",35) SS StackSliceNumber 1 PrivateTag +(2001,"Philips Imaging DD 001",36) CS StackType 1 PrivateTag +(2001,"Philips Imaging DD 001",3f) CS ZoomMode 1 PrivateTag +(2001,"Philips Imaging DD 001",58) UL ContrastTransferTaste 1 PrivateTag +(2001,"Philips Imaging DD 001",5f) SQ StackSequence 1 PrivateTag +(2001,"Philips Imaging DD 001",60) SL NumberOfStacks 1 PrivateTag +(2001,"Philips Imaging DD 001",61) CS SeriesTransmitted 1 PrivateTag +(2001,"Philips Imaging DD 001",62) CS SeriesCommitted 1 PrivateTag +(2001,"Philips Imaging DD 001",63) CS ExaminationSource 1 PrivateTag +(2001,"Philips Imaging DD 001",67) CS LinearPresentationGLTrafoShapeSub 1 PrivateTag +(2001,"Philips Imaging DD 001",77) CS GLTrafoType 1 PrivateTag +(2001,"Philips Imaging DD 001",7b) IS AcquisitionNumber 1 PrivateTag +(2001,"Philips Imaging DD 001",81) IS NumberOfDynamicScans 1 PrivateTag +(2001,"Philips Imaging DD 001",9f) US PixelProcessingKernelSize 1 PrivateTag +(2001,"Philips Imaging DD 001",a1) CS IsRawImage 1 PrivateTag +(2001,"Philips Imaging DD 001",f1) FL ProspectiveMotionCorrection 1 PrivateTag +(2001,"Philips Imaging DD 001",f2) FL RetrospectiveMotionCorrection 1 PrivateTag + +# Note: Some Philips devices use these private tags with reservation value +# "Philips Imaging DD 001", others use "PHILIPS IMAGING DD 001". All attributes +# should thus be present twice in this dictionary, once for each spelling variant. +# +(2001,"PHILIPS IMAGING DD 001",01) FL ChemicalShift 1 PrivateTag +(2001,"PHILIPS IMAGING DD 001",02) IS ChemicalShiftNumberMR 1 PrivateTag +(2001,"PHILIPS IMAGING DD 001",03) FL DiffusionBFactor 1 PrivateTag +(2001,"PHILIPS IMAGING DD 001",04) CS DiffusionDirection 1 PrivateTag +(2001,"PHILIPS IMAGING DD 001",06) CS ImageEnhanced 1 PrivateTag +(2001,"PHILIPS IMAGING DD 001",07) CS ImageTypeEDES 1 PrivateTag +(2001,"PHILIPS IMAGING DD 001",08) IS PhaseNumber 1 PrivateTag +(2001,"PHILIPS IMAGING DD 001",09) FL ImagePrepulseDelay 1 PrivateTag +(2001,"PHILIPS IMAGING DD 001",0a) IS SliceNumberMR 1 PrivateTag +(2001,"PHILIPS IMAGING DD 001",0b) CS SliceOrientation 1 PrivateTag +(2001,"PHILIPS IMAGING DD 001",0c) CS ArrhythmiaRejection 1 PrivateTag +(2001,"PHILIPS IMAGING DD 001",0e) CS CardiacCycled 1 PrivateTag +(2001,"PHILIPS IMAGING DD 001",0f) SS CardiacGateWidth 1 PrivateTag +(2001,"PHILIPS IMAGING DD 001",10) CS CardiacSync 1 PrivateTag +(2001,"PHILIPS IMAGING DD 001",11) FL DiffusionEchoTime 1 PrivateTag +(2001,"PHILIPS IMAGING DD 001",12) CS DynamicSeries 1 PrivateTag +(2001,"PHILIPS IMAGING DD 001",13) SL EPIFactor 1 PrivateTag +(2001,"PHILIPS IMAGING DD 001",14) SL NumberOfEchoes 1 PrivateTag +(2001,"PHILIPS IMAGING DD 001",15) SS NumberOfLocations 1 PrivateTag +(2001,"PHILIPS IMAGING DD 001",16) SS NumberOfPCDirections 1 PrivateTag +(2001,"PHILIPS IMAGING DD 001",17) SL NumberOfPhasesMR 1 PrivateTag +(2001,"PHILIPS IMAGING DD 001",18) SL NumberOfSlicesMR 1 PrivateTag +(2001,"PHILIPS IMAGING DD 001",19) CS PartialMatrixScanned 1 PrivateTag +(2001,"PHILIPS IMAGING DD 001",1a) FL PCVelocity 1-n PrivateTag +(2001,"PHILIPS IMAGING DD 001",1b) FL PrepulseDelay 1 PrivateTag +(2001,"PHILIPS IMAGING DD 001",1c) CS PrepulseType 1 PrivateTag +(2001,"PHILIPS IMAGING DD 001",1d) IS ReconstructionNumberMR 1 PrivateTag +(2001,"PHILIPS IMAGING DD 001",1f) CS RespirationSync 1 PrivateTag +(2001,"PHILIPS IMAGING DD 001",20) LO ScanningTechnique 1 PrivateTag +(2001,"PHILIPS IMAGING DD 001",21) CS SPIR 1 PrivateTag +(2001,"PHILIPS IMAGING DD 001",22) FL WaterFatShift 1 PrivateTag +(2001,"PHILIPS IMAGING DD 001",23) DS FlipAnglePhilips 1 PrivateTag +(2001,"PHILIPS IMAGING DD 001",24) CS SeriesIsInteractive 1 PrivateTag +(2001,"PHILIPS IMAGING DD 001",25) SH EchoTimeDisplayMR 1 PrivateTag +(2001,"PHILIPS IMAGING DD 001",26) CS PresentationStateSubtractionActive 1 PrivateTag +(2001,"PHILIPS IMAGING DD 001",2d) SS StackNumberOfSlices 1 PrivateTag +(2001,"PHILIPS IMAGING DD 001",32) FL StackRadialAngle 1 PrivateTag +(2001,"PHILIPS IMAGING DD 001",33) CS StackRadialAxis 1 PrivateTag +(2001,"PHILIPS IMAGING DD 001",35) SS StackSliceNumber 1 PrivateTag +(2001,"PHILIPS IMAGING DD 001",36) CS StackType 1 PrivateTag +(2001,"PHILIPS IMAGING DD 001",3f) CS ZoomMode 1 PrivateTag +(2001,"PHILIPS IMAGING DD 001",58) UL ContrastTransferTaste 1 PrivateTag +(2001,"PHILIPS IMAGING DD 001",5f) SQ StackSequence 1 PrivateTag +(2001,"PHILIPS IMAGING DD 001",60) SL NumberOfStacks 1 PrivateTag +(2001,"PHILIPS IMAGING DD 001",61) CS SeriesTransmitted 1 PrivateTag +(2001,"PHILIPS IMAGING DD 001",62) CS SeriesCommitted 1 PrivateTag +(2001,"PHILIPS IMAGING DD 001",63) CS ExaminationSource 1 PrivateTag +(2001,"PHILIPS IMAGING DD 001",67) CS LinearPresentationGLTrafoShapeSub 1 PrivateTag +(2001,"PHILIPS IMAGING DD 001",77) CS GLTrafoType 1 PrivateTag +(2001,"PHILIPS IMAGING DD 001",7b) IS AcquisitionNumber 1 PrivateTag +(2001,"PHILIPS IMAGING DD 001",81) IS NumberOfDynamicScans 1 PrivateTag +(2001,"PHILIPS IMAGING DD 001",9f) US PixelProcessingKernelSize 1 PrivateTag +(2001,"PHILIPS IMAGING DD 001",a1) CS IsRawImage 1 PrivateTag +(2001,"PHILIPS IMAGING DD 001",f1) FL ProspectiveMotionCorrection 1 PrivateTag +(2001,"PHILIPS IMAGING DD 001",f2) FL RetrospectiveMotionCorrection 1 PrivateTag + +# Note: Some Philips devices use these private tags with reservation value +# "Philips MR Imaging DD 001", others use "PHILIPS MR IMAGING DD 001". All attributes +# should thus be present twice in this dictionary, once for each spelling variant. +# +(2005,"Philips MR Imaging DD 001",05) CS SynergyReconstructionType 1 PrivateTag +(2005,"Philips MR Imaging DD 001",1e) SH MIPProtocol 1 PrivateTag +(2005,"Philips MR Imaging DD 001",1f) SH MPRProtocol 1 PrivateTag +(2005,"Philips MR Imaging DD 001",20) SL NumberOfChemicalShifts 1 PrivateTag +(2005,"Philips MR Imaging DD 001",2d) SS NumberOfStackSlices 1 PrivateTag +(2005,"Philips MR Imaging DD 001",83) SQ Unknown 1 PrivateTag +(2005,"Philips MR Imaging DD 001",a1) CS SyncraScanType 1 PrivateTag +(2005,"Philips MR Imaging DD 001",b0) FL DiffusionDirectionRL 1 PrivateTag +(2005,"Philips MR Imaging DD 001",b1) FL DiffusionDirectionAP 1 PrivateTag +(2005,"Philips MR Imaging DD 001",b2) FL DiffusionDirectionFH 1 PrivateTag + +(2005,"Philips MR Imaging DD 005",02) SQ Unknown 1 PrivateTag + +# Note: Some Philips devices use these private tags with reservation value +# "Philips MR Imaging DD 001", others use "PHILIPS MR IMAGING DD 001". All attributes +# should thus be present twice in this dictionary, once for each spelling variant. +# +(2005,"PHILIPS MR IMAGING DD 001",05) CS SynergyReconstructionType 1 PrivateTag +(2005,"PHILIPS MR IMAGING DD 001",1e) SH MIPProtocol 1 PrivateTag +(2005,"PHILIPS MR IMAGING DD 001",1f) SH MPRProtocol 1 PrivateTag +(2005,"PHILIPS MR IMAGING DD 001",20) SL NumberOfChemicalShifts 1 PrivateTag +(2005,"PHILIPS MR IMAGING DD 001",2d) SS NumberOfStackSlices 1 PrivateTag +(2005,"PHILIPS MR IMAGING DD 001",83) SQ Unknown 1 PrivateTag +(2005,"PHILIPS MR IMAGING DD 001",a1) CS SyncraScanType 1 PrivateTag +(2005,"PHILIPS MR IMAGING DD 001",b0) FL DiffusionDirectionRL 1 PrivateTag +(2005,"PHILIPS MR IMAGING DD 001",b1) FL DiffusionDirectionAP 1 PrivateTag +(2005,"PHILIPS MR IMAGING DD 001",b2) FL DiffusionDirectionFH 1 PrivateTag + +(0019,"PHILIPS MR R5.5/PART",1000) DS FieldOfView 1 PrivateTag +(0019,"PHILIPS MR R5.6/PART",1000) DS FieldOfView 1 PrivateTag + +(0019,"PHILIPS MR SPECTRO;1",01) US Unknown 1 PrivateTag +(0019,"PHILIPS MR SPECTRO;1",02) US Unknown 1 PrivateTag +(0019,"PHILIPS MR SPECTRO;1",03) US Unknown 1 PrivateTag +(0019,"PHILIPS MR SPECTRO;1",04) US Unknown 1 PrivateTag +(0019,"PHILIPS MR SPECTRO;1",05) US Unknown 1 PrivateTag +(0019,"PHILIPS MR SPECTRO;1",06) US Unknown 1 PrivateTag +(0019,"PHILIPS MR SPECTRO;1",07) IS Unknown 1 PrivateTag +(0019,"PHILIPS MR SPECTRO;1",08) IS Unknown 1 PrivateTag +(0019,"PHILIPS MR SPECTRO;1",09) IS Unknown 1 PrivateTag +(0019,"PHILIPS MR SPECTRO;1",10) IS Unknown 1 PrivateTag +(0019,"PHILIPS MR SPECTRO;1",12) IS Unknown 1 PrivateTag +(0019,"PHILIPS MR SPECTRO;1",13) IS Unknown 1 PrivateTag +(0019,"PHILIPS MR SPECTRO;1",14) US Unknown 1 PrivateTag +(0019,"PHILIPS MR SPECTRO;1",15) US Unknown 1-n PrivateTag +(0019,"PHILIPS MR SPECTRO;1",16) IS Unknown 1 PrivateTag +(0019,"PHILIPS MR SPECTRO;1",17) IS Unknown 1 PrivateTag +(0019,"PHILIPS MR SPECTRO;1",18) UN Unknown 1 PrivateTag +(0019,"PHILIPS MR SPECTRO;1",20) IS Unknown 1 PrivateTag +(0019,"PHILIPS MR SPECTRO;1",21) IS Unknown 1 PrivateTag +(0019,"PHILIPS MR SPECTRO;1",22) IS Unknown 1 PrivateTag +(0019,"PHILIPS MR SPECTRO;1",23) IS Unknown 1 PrivateTag +(0019,"PHILIPS MR SPECTRO;1",24) IS Unknown 1 PrivateTag +(0019,"PHILIPS MR SPECTRO;1",25) IS Unknown 1 PrivateTag +(0019,"PHILIPS MR SPECTRO;1",26) IS Unknown 1 PrivateTag +(0019,"PHILIPS MR SPECTRO;1",27) IS Unknown 1 PrivateTag +(0019,"PHILIPS MR SPECTRO;1",28) IS Unknown 1 PrivateTag +(0019,"PHILIPS MR SPECTRO;1",29) IS Unknown 1-n PrivateTag +(0019,"PHILIPS MR SPECTRO;1",31) US Unknown 1 PrivateTag +(0019,"PHILIPS MR SPECTRO;1",32) US Unknown 1 PrivateTag +(0019,"PHILIPS MR SPECTRO;1",41) LT Unknown 1 PrivateTag +(0019,"PHILIPS MR SPECTRO;1",42) IS Unknown 2 PrivateTag +(0019,"PHILIPS MR SPECTRO;1",43) IS Unknown 2 PrivateTag +(0019,"PHILIPS MR SPECTRO;1",45) US Unknown 1 PrivateTag +(0019,"PHILIPS MR SPECTRO;1",46) US Unknown 1 PrivateTag +(0019,"PHILIPS MR SPECTRO;1",47) IS Unknown 1 PrivateTag +(0019,"PHILIPS MR SPECTRO;1",48) IS Unknown 1 PrivateTag +(0019,"PHILIPS MR SPECTRO;1",49) US Unknown 1 PrivateTag +(0019,"PHILIPS MR SPECTRO;1",50) UN Unknown 1 PrivateTag +(0019,"PHILIPS MR SPECTRO;1",60) US Unknown 1 PrivateTag +(0019,"PHILIPS MR SPECTRO;1",61) US Unknown 1 PrivateTag +(0019,"PHILIPS MR SPECTRO;1",70) UN Unknown 1 PrivateTag +(0019,"PHILIPS MR SPECTRO;1",71) IS Unknown 1-n PrivateTag +(0019,"PHILIPS MR SPECTRO;1",72) US Unknown 1 PrivateTag +(0019,"PHILIPS MR SPECTRO;1",73) US Unknown 1 PrivateTag +(0019,"PHILIPS MR SPECTRO;1",74) US Unknown 1 PrivateTag +(0019,"PHILIPS MR SPECTRO;1",76) US Unknown 1 PrivateTag +(0019,"PHILIPS MR SPECTRO;1",77) US Unknown 1 PrivateTag +(0019,"PHILIPS MR SPECTRO;1",78) US Unknown 1 PrivateTag +(0019,"PHILIPS MR SPECTRO;1",79) US Unknown 1 PrivateTag +(0019,"PHILIPS MR SPECTRO;1",80) IS Unknown 1 PrivateTag + +(0009,"PHILIPS MR",10) LO SPIRelease 1 PrivateTag +(0009,"PHILIPS MR",12) LO Unknown 1 PrivateTag + +(0019,"PHILIPS MR/LAST",09) DS MainMagneticField 1 PrivateTag +(0019,"PHILIPS MR/LAST",0e) IS FlowCompensation 1 PrivateTag +(0019,"PHILIPS MR/LAST",b1) IS MinimumRRInterval 1 PrivateTag +(0019,"PHILIPS MR/LAST",b2) IS MaximumRRInterval 1 PrivateTag +(0019,"PHILIPS MR/LAST",b3) IS NumberOfRejections 1 PrivateTag +(0019,"PHILIPS MR/LAST",b4) IS NumberOfRRIntervals 1-n PrivateTag +(0019,"PHILIPS MR/LAST",b5) IS ArrhythmiaRejection 1 PrivateTag +(0019,"PHILIPS MR/LAST",c0) DS Unknown 1-n PrivateTag +(0019,"PHILIPS MR/LAST",c6) IS CycledMultipleSlice 1 PrivateTag +(0019,"PHILIPS MR/LAST",ce) IS REST 1 PrivateTag +(0019,"PHILIPS MR/LAST",d5) DS Unknown 1 PrivateTag +(0019,"PHILIPS MR/LAST",d6) IS FourierInterpolation 1 PrivateTag +(0019,"PHILIPS MR/LAST",d9) IS Unknown 1-n PrivateTag +(0019,"PHILIPS MR/LAST",e0) IS Prepulse 1 PrivateTag +(0019,"PHILIPS MR/LAST",e1) DS PrepulseDelay 1 PrivateTag +(0019,"PHILIPS MR/LAST",e2) IS Unknown 1 PrivateTag +(0019,"PHILIPS MR/LAST",e3) DS Unknown 1 PrivateTag +(0019,"PHILIPS MR/LAST",f0) LT WSProtocolString1 1 PrivateTag +(0019,"PHILIPS MR/LAST",f1) LT WSProtocolString2 1 PrivateTag +(0019,"PHILIPS MR/LAST",f2) LT WSProtocolString3 1 PrivateTag +(0019,"PHILIPS MR/LAST",f3) LT WSProtocolString4 1 PrivateTag +(0021,"PHILIPS MR/LAST",00) IS Unknown 1 PrivateTag +(0021,"PHILIPS MR/LAST",10) IS Unknown 1 PrivateTag +(0021,"PHILIPS MR/LAST",20) IS Unknown 1 PrivateTag +(0021,"PHILIPS MR/LAST",21) DS SliceGap 1 PrivateTag +(0021,"PHILIPS MR/LAST",22) DS StackRadialAngle 1 PrivateTag +(0027,"PHILIPS MR/LAST",00) US Unknown 1 PrivateTag +(0027,"PHILIPS MR/LAST",11) US Unknown 1-n PrivateTag +(0027,"PHILIPS MR/LAST",12) DS Unknown 1-n PrivateTag +(0027,"PHILIPS MR/LAST",13) DS Unknown 1-n PrivateTag +(0027,"PHILIPS MR/LAST",14) DS Unknown 1-n PrivateTag +(0027,"PHILIPS MR/LAST",15) DS Unknown 1-n PrivateTag +(0027,"PHILIPS MR/LAST",16) LO Unknown 1 PrivateTag +(0029,"PHILIPS MR/LAST",10) DS FPMin 1 PrivateTag +(0029,"PHILIPS MR/LAST",20) DS FPMax 1 PrivateTag +(0029,"PHILIPS MR/LAST",30) DS ScaledMinimum 1 PrivateTag +(0029,"PHILIPS MR/LAST",40) DS ScaledMaximum 1 PrivateTag +(0029,"PHILIPS MR/LAST",50) DS WindowMinimum 1 PrivateTag +(0029,"PHILIPS MR/LAST",60) DS WindowMaximum 1 PrivateTag +(0029,"PHILIPS MR/LAST",61) IS Unknown 1 PrivateTag +(0029,"PHILIPS MR/LAST",70) DS Unknown 1 PrivateTag +(0029,"PHILIPS MR/LAST",71) DS Unknown 1 PrivateTag +(0029,"PHILIPS MR/LAST",72) IS Unknown 1 PrivateTag +(0029,"PHILIPS MR/LAST",80) IS ViewCenter 1 PrivateTag +(0029,"PHILIPS MR/LAST",81) IS ViewSize 1 PrivateTag +(0029,"PHILIPS MR/LAST",82) IS ViewZoom 1 PrivateTag +(0029,"PHILIPS MR/LAST",83) IS ViewTransform 1 PrivateTag +(6001,"PHILIPS MR/LAST",00) LT Unknown 1 PrivateTag + +(0019,"PHILIPS MR/PART",1000) DS FieldOfView 1 PrivateTag +(0019,"PHILIPS MR/PART",1005) DS CCAngulation 1 PrivateTag +(0019,"PHILIPS MR/PART",1006) DS APAngulation 1 PrivateTag +(0019,"PHILIPS MR/PART",1007) DS LRAngulation 1 PrivateTag +(0019,"PHILIPS MR/PART",1008) IS PatientPosition 1 PrivateTag +(0019,"PHILIPS MR/PART",1009) IS PatientOrientation 1 PrivateTag +(0019,"PHILIPS MR/PART",100a) IS SliceOrientation 1 PrivateTag +(0019,"PHILIPS MR/PART",100b) DS LROffcenter 1 PrivateTag +(0019,"PHILIPS MR/PART",100c) DS CCOffcenter 1 PrivateTag +(0019,"PHILIPS MR/PART",100d) DS APOffcenter 1 PrivateTag +(0019,"PHILIPS MR/PART",100e) DS Unknown 1 PrivateTag +(0019,"PHILIPS MR/PART",100f) IS NumberOfSlices 1 PrivateTag +(0019,"PHILIPS MR/PART",1010) DS SliceFactor 1 PrivateTag +(0019,"PHILIPS MR/PART",1011) DS EchoTimes 1-n PrivateTag +(0019,"PHILIPS MR/PART",1015) IS DynamicStudy 1 PrivateTag +(0019,"PHILIPS MR/PART",1018) DS HeartbeatInterval 1 PrivateTag +(0019,"PHILIPS MR/PART",1019) DS RepetitionTimeFFE 1 PrivateTag +(0019,"PHILIPS MR/PART",101a) DS FFEFlipAngle 1 PrivateTag +(0019,"PHILIPS MR/PART",101b) IS NumberOfScans 1 PrivateTag +(0019,"PHILIPS MR/PART",1021) DS Unknown 1-n PrivateTag +(0019,"PHILIPS MR/PART",1022) DS DynamicScanTimeBegin 1 PrivateTag +(0019,"PHILIPS MR/PART",1024) IS Unknown 1 PrivateTag +(0019,"PHILIPS MR/PART",1064) DS RepetitionTimeSE 1 PrivateTag +(0019,"PHILIPS MR/PART",1065) DS RepetitionTimeIR 1 PrivateTag +(0019,"PHILIPS MR/PART",1069) IS NumberOfPhases 1 PrivateTag +(0019,"PHILIPS MR/PART",106a) IS CardiacFrequency 1 PrivateTag +(0019,"PHILIPS MR/PART",106b) DS InversionDelay 1 PrivateTag +(0019,"PHILIPS MR/PART",106c) DS GateDelay 1 PrivateTag +(0019,"PHILIPS MR/PART",106d) DS GateWidth 1 PrivateTag +(0019,"PHILIPS MR/PART",106e) DS TriggerDelayTime 1 PrivateTag +(0019,"PHILIPS MR/PART",1080) IS NumberOfChemicalShifts 1 PrivateTag +(0019,"PHILIPS MR/PART",1081) DS ChemicalShift 1 PrivateTag +(0019,"PHILIPS MR/PART",1084) IS NumberOfRows 1 PrivateTag +(0019,"PHILIPS MR/PART",1085) IS NumberOfSamples 1 PrivateTag +(0019,"PHILIPS MR/PART",1094) LO MagnetizationTransferContrast 1 PrivateTag +(0019,"PHILIPS MR/PART",1095) LO SpectralPresaturationWithInversionRecovery 1 PrivateTag +(0019,"PHILIPS MR/PART",1096) IS Unknown 1 PrivateTag +(0019,"PHILIPS MR/PART",1097) LO Unknown 1 PrivateTag +(0019,"PHILIPS MR/PART",10a0) IS Unknown 1 PrivateTag +(0019,"PHILIPS MR/PART",10a1) DS Unknown 1 PrivateTag +(0019,"PHILIPS MR/PART",10a3) DS Unknown 1 PrivateTag +(0019,"PHILIPS MR/PART",10a4) CS Unknown 1 PrivateTag +(0019,"PHILIPS MR/PART",10c8) IS Unknown 1 PrivateTag +(0019,"PHILIPS MR/PART",10c9) IS FoldoverDirectionTransverse 1 PrivateTag +(0019,"PHILIPS MR/PART",10ca) IS FoldoverDirectionSagittal 1 PrivateTag +(0019,"PHILIPS MR/PART",10cb) IS FoldoverDirectionCoronal 1 PrivateTag +(0019,"PHILIPS MR/PART",10cc) IS Unknown 1 PrivateTag +(0019,"PHILIPS MR/PART",10cd) IS Unknown 1 PrivateTag +(0019,"PHILIPS MR/PART",10ce) IS Unknown 1 PrivateTag +(0019,"PHILIPS MR/PART",10cf) IS NumberOfEchoes 1 PrivateTag +(0019,"PHILIPS MR/PART",10d0) IS ScanResolution 1 PrivateTag +(0019,"PHILIPS MR/PART",10d2) LO WaterFatShift 2 PrivateTag +(0019,"PHILIPS MR/PART",10d4) IS ArtifactReduction 1 PrivateTag +(0019,"PHILIPS MR/PART",10d5) IS Unknown 1 PrivateTag +(0019,"PHILIPS MR/PART",10d6) IS Unknown 1 PrivateTag +(0019,"PHILIPS MR/PART",10d7) DS ScanPercentage 1 PrivateTag +(0019,"PHILIPS MR/PART",10d8) IS Halfscan 1 PrivateTag +(0019,"PHILIPS MR/PART",10d9) IS EPIFactor 1 PrivateTag +(0019,"PHILIPS MR/PART",10da) IS TurboFactor 1 PrivateTag +(0019,"PHILIPS MR/PART",10db) IS Unknown 1 PrivateTag +(0019,"PHILIPS MR/PART",10e0) IS PercentageOfScanCompleted 1 PrivateTag +(0019,"PHILIPS MR/PART",10e1) IS Unknown 1 PrivateTag +(0019,"PHILIPS MR/PART",1100) IS NumberOfStacks 1 PrivateTag +(0019,"PHILIPS MR/PART",1101) IS StackType 1-n PrivateTag +(0019,"PHILIPS MR/PART",1102) IS Unknown 1-n PrivateTag +(0019,"PHILIPS MR/PART",110b) DS LROffcenter 1 PrivateTag +(0019,"PHILIPS MR/PART",110c) DS CCOffcenter 1 PrivateTag +(0019,"PHILIPS MR/PART",110d) DS APOffcenter 1 PrivateTag +(0019,"PHILIPS MR/PART",1145) IS ReconstructionResolution 1 PrivateTag +(0019,"PHILIPS MR/PART",11fc) IS ResonanceFrequency 1 PrivateTag +(0019,"PHILIPS MR/PART",12c0) DS TriggerDelayTimes 1 PrivateTag +(0019,"PHILIPS MR/PART",12e0) IS PrepulseType 1 PrivateTag +(0019,"PHILIPS MR/PART",12e1) DS PrepulseDelay 1 PrivateTag +(0019,"PHILIPS MR/PART",12e3) DS PhaseContrastVelocity 1 PrivateTag +(0021,"PHILIPS MR/PART",1000) IS ReconstructionNumber 1 PrivateTag +(0021,"PHILIPS MR/PART",1010) IS ImageType 1 PrivateTag +(0021,"PHILIPS MR/PART",1020) IS SliceNumber 1 PrivateTag +(0021,"PHILIPS MR/PART",1030) IS EchoNumber 1 PrivateTag +(0021,"PHILIPS MR/PART",1031) DS PatientReferenceID 1 PrivateTag +(0021,"PHILIPS MR/PART",1035) IS ChemicalShiftNumber 1 PrivateTag +(0021,"PHILIPS MR/PART",1040) IS PhaseNumber 1 PrivateTag +(0021,"PHILIPS MR/PART",1050) IS DynamicScanNumber 1 PrivateTag +(0021,"PHILIPS MR/PART",1060) IS NumberOfRowsInObject 1 PrivateTag +(0021,"PHILIPS MR/PART",1061) IS RowNumber 1-n PrivateTag +(0021,"PHILIPS MR/PART",1062) IS Unknown 1-n PrivateTag +(0021,"PHILIPS MR/PART",1100) DA ScanDate 1 PrivateTag +(0021,"PHILIPS MR/PART",1110) TM ScanTime 1 PrivateTag +(0021,"PHILIPS MR/PART",1221) IS SliceGap 1 PrivateTag +(0029,"PHILIPS MR/PART",00) DS Unknown 2 PrivateTag +(0029,"PHILIPS MR/PART",04) US Unknown 1 PrivateTag +(0029,"PHILIPS MR/PART",10) DS Unknown 1 PrivateTag +(0029,"PHILIPS MR/PART",11) DS Unknown 1 PrivateTag +(0029,"PHILIPS MR/PART",20) LO Unknown 1 PrivateTag +(0029,"PHILIPS MR/PART",31) DS Unknown 2 PrivateTag +(0029,"PHILIPS MR/PART",32) DS Unknown 2 PrivateTag +(0029,"PHILIPS MR/PART",c3) IS ScanResolution 1 PrivateTag +(0029,"PHILIPS MR/PART",c4) IS FieldOfView 1 PrivateTag +(0029,"PHILIPS MR/PART",d5) LT SliceThickness 1 PrivateTag + +(0019,"PHILIPS-MR-1",11) IS ChemicalShiftNumber 1 PrivateTag +(0019,"PHILIPS-MR-1",12) IS PhaseNumber 1 PrivateTag +(0021,"PHILIPS-MR-1",01) IS ReconstructionNumber 1 PrivateTag +(0021,"PHILIPS-MR-1",02) IS SliceNumber 1 PrivateTag + +(7001,"Picker NM Private Group",01) UI Unknown 1 PrivateTag +(7001,"Picker NM Private Group",02) OB Unknown 1 PrivateTag + +(0019,"SIEMENS CM VA0 ACQU",10) LT ParameterFileName 1 PrivateTag +(0019,"SIEMENS CM VA0 ACQU",11) LO SequenceFileName 1 PrivateTag +(0019,"SIEMENS CM VA0 ACQU",12) LT SequenceFileOwner 1 PrivateTag +(0019,"SIEMENS CM VA0 ACQU",13) LT SequenceDescription 1 PrivateTag +(0019,"SIEMENS CM VA0 ACQU",14) LT EPIFileName 1 PrivateTag + +(0009,"SIEMENS CM VA0 CMS",00) DS NumberOfMeasurements 1 PrivateTag +(0009,"SIEMENS CM VA0 CMS",10) LT StorageMode 1 PrivateTag +(0009,"SIEMENS CM VA0 CMS",12) UL EvaluationMaskImage 1 PrivateTag +(0009,"SIEMENS CM VA0 CMS",26) DA LastMoveDate 1 PrivateTag +(0009,"SIEMENS CM VA0 CMS",27) TM LastMoveTime 1 PrivateTag +(0011,"SIEMENS CM VA0 CMS",0a) LT Unknown 1 PrivateTag +(0011,"SIEMENS CM VA0 CMS",10) DA RegistrationDate 1 PrivateTag +(0011,"SIEMENS CM VA0 CMS",11) TM RegistrationTime 1 PrivateTag +(0011,"SIEMENS CM VA0 CMS",22) LT Unknown 1 PrivateTag +(0011,"SIEMENS CM VA0 CMS",23) DS UsedPatientWeight 1 PrivateTag +(0011,"SIEMENS CM VA0 CMS",40) IS OrganCode 1 PrivateTag +(0013,"SIEMENS CM VA0 CMS",00) LT ModifyingPhysician 1 PrivateTag +(0013,"SIEMENS CM VA0 CMS",10) DA ModificationDate 1 PrivateTag +(0013,"SIEMENS CM VA0 CMS",12) TM ModificationTime 1 PrivateTag +(0013,"SIEMENS CM VA0 CMS",20) LO PatientName 1 PrivateTag +(0013,"SIEMENS CM VA0 CMS",22) LO PatientId 1 PrivateTag +(0013,"SIEMENS CM VA0 CMS",30) DA PatientBirthdate 1 PrivateTag +(0013,"SIEMENS CM VA0 CMS",31) DS PatientWeight 1 PrivateTag +(0013,"SIEMENS CM VA0 CMS",32) LT PatientsMaidenName 1 PrivateTag +(0013,"SIEMENS CM VA0 CMS",33) LT ReferringPhysician 1 PrivateTag +(0013,"SIEMENS CM VA0 CMS",34) LT AdmittingDiagnosis 1 PrivateTag +(0013,"SIEMENS CM VA0 CMS",35) LO PatientSex 1 PrivateTag +(0013,"SIEMENS CM VA0 CMS",40) LO ProcedureDescription 1 PrivateTag +(0013,"SIEMENS CM VA0 CMS",42) LO RestDirection 1 PrivateTag +(0013,"SIEMENS CM VA0 CMS",44) LO PatientPosition 1 PrivateTag +(0013,"SIEMENS CM VA0 CMS",46) LT ViewDirection 1 PrivateTag +(0013,"SIEMENS CM VA0 CMS",50) LT Unknown 1 PrivateTag +(0013,"SIEMENS CM VA0 CMS",51) LT Unknown 1 PrivateTag +(0013,"SIEMENS CM VA0 CMS",52) LT Unknown 1 PrivateTag +(0013,"SIEMENS CM VA0 CMS",53) LT Unknown 1 PrivateTag +(0013,"SIEMENS CM VA0 CMS",54) LT Unknown 1 PrivateTag +(0013,"SIEMENS CM VA0 CMS",55) LT Unknown 1 PrivateTag +(0013,"SIEMENS CM VA0 CMS",56) LT Unknown 1 PrivateTag +(0019,"SIEMENS CM VA0 CMS",10) DS NetFrequency 1 PrivateTag +(0019,"SIEMENS CM VA0 CMS",20) LT MeasurementMode 1 PrivateTag +(0019,"SIEMENS CM VA0 CMS",30) LT CalculationMode 1 PrivateTag +(0019,"SIEMENS CM VA0 CMS",50) IS NoiseLevel 1 PrivateTag +(0019,"SIEMENS CM VA0 CMS",60) IS NumberOfDataBytes 1 PrivateTag +(0021,"SIEMENS CM VA0 CMS",20) DS FoV 2 PrivateTag +(0021,"SIEMENS CM VA0 CMS",22) DS ImageMagnificationFactor 1 PrivateTag +(0021,"SIEMENS CM VA0 CMS",24) DS ImageScrollOffset 2 PrivateTag +(0021,"SIEMENS CM VA0 CMS",26) IS ImagePixelOffset 1 PrivateTag +(0021,"SIEMENS CM VA0 CMS",30) LT ViewDirection 1 PrivateTag +(0021,"SIEMENS CM VA0 CMS",32) CS PatientRestDirection 1 PrivateTag +(0021,"SIEMENS CM VA0 CMS",60) DS ImagePosition 3 PrivateTag +(0021,"SIEMENS CM VA0 CMS",61) DS ImageNormal 3 PrivateTag +(0021,"SIEMENS CM VA0 CMS",63) DS ImageDistance 1 PrivateTag +(0021,"SIEMENS CM VA0 CMS",65) US ImagePositioningHistoryMask 1 PrivateTag +(0021,"SIEMENS CM VA0 CMS",6a) DS ImageRow 3 PrivateTag +(0021,"SIEMENS CM VA0 CMS",6b) DS ImageColumn 3 PrivateTag +(0021,"SIEMENS CM VA0 CMS",70) LT PatientOrientationSet1 3 PrivateTag +(0021,"SIEMENS CM VA0 CMS",71) LT PatientOrientationSet2 3 PrivateTag +(0021,"SIEMENS CM VA0 CMS",80) LT StudyName 1 PrivateTag +(0021,"SIEMENS CM VA0 CMS",82) LT StudyType 3 PrivateTag +(0029,"SIEMENS CM VA0 CMS",10) LT WindowStyle 1 PrivateTag +(0029,"SIEMENS CM VA0 CMS",11) LT Unknown 1 PrivateTag +(0029,"SIEMENS CM VA0 CMS",13) LT Unknown 1 PrivateTag +(0029,"SIEMENS CM VA0 CMS",20) LT PixelQualityCode 3 PrivateTag +(0029,"SIEMENS CM VA0 CMS",22) IS PixelQualityValue 3 PrivateTag +(0029,"SIEMENS CM VA0 CMS",50) LT ArchiveCode 1 PrivateTag +(0029,"SIEMENS CM VA0 CMS",51) LT ExposureCode 1 PrivateTag +(0029,"SIEMENS CM VA0 CMS",52) LT SortCode 1 PrivateTag +(0029,"SIEMENS CM VA0 CMS",53) LT Unknown 1 PrivateTag +(0029,"SIEMENS CM VA0 CMS",60) LT Splash 1 PrivateTag +(0051,"SIEMENS CM VA0 CMS",10) LT ImageText 1-n PrivateTag +(6021,"SIEMENS CM VA0 CMS",00) LT ImageGraphicsFormatCode 1 PrivateTag +(6021,"SIEMENS CM VA0 CMS",10) LT ImageGraphics 1 PrivateTag +(7fe1,"SIEMENS CM VA0 CMS",00) OB BinaryData 1-n PrivateTag + +(0009,"SIEMENS CM VA0 LAB",10) LT GeneratorIdentificationLabel 1 PrivateTag +(0009,"SIEMENS CM VA0 LAB",11) LT GantryIdentificationLabel 1 PrivateTag +(0009,"SIEMENS CM VA0 LAB",12) LT X-RayTubeIdentificationLabel 1 PrivateTag +(0009,"SIEMENS CM VA0 LAB",13) LT DetectorIdentificationLabel 1 PrivateTag +(0009,"SIEMENS CM VA0 LAB",14) LT DASIdentificationLabel 1 PrivateTag +(0009,"SIEMENS CM VA0 LAB",15) LT SMIIdentificationLabel 1 PrivateTag +(0009,"SIEMENS CM VA0 LAB",16) LT CPUIdentificationLabel 1 PrivateTag +(0009,"SIEMENS CM VA0 LAB",20) LT HeaderVersion 1 PrivateTag + +(0029,"SIEMENS CSA HEADER",08) CS CSAImageHeaderType 1 PrivateTag +(0029,"SIEMENS CSA HEADER",09) LO CSAImageHeaderVersion 1 PrivateTag +(0029,"SIEMENS CSA HEADER",10) OB CSAImageHeaderInfo 1 PrivateTag +(0029,"SIEMENS CSA HEADER",18) CS CSASeriesHeaderType 1 PrivateTag +(0029,"SIEMENS CSA HEADER",19) LO CSASeriesHeaderVersion 1 PrivateTag +(0029,"SIEMENS CSA HEADER",20) OB CSASeriesHeaderInfo 1 PrivateTag + +(0029,"SIEMENS CSA NON-IMAGE",08) CS CSADataType 1 PrivateTag +(0029,"SIEMENS CSA NON-IMAGE",09) LO CSADataVersion 1 PrivateTag +(0029,"SIEMENS CSA NON-IMAGE",10) OB CSADataInfo 1 PrivateTag +(7FE1,"SIEMENS CSA NON-IMAGE",10) OB CSAData 1 PrivateTag + +(0019,"SIEMENS CT VA0 COAD",10) DS DistanceSourceToSourceSideCollimator 1 PrivateTag +(0019,"SIEMENS CT VA0 COAD",11) DS DistanceSourceToDetectorSideCollimator 1 PrivateTag +(0019,"SIEMENS CT VA0 COAD",20) IS NumberOfPossibleChannels 1 PrivateTag +(0019,"SIEMENS CT VA0 COAD",21) IS MeanChannelNumber 1 PrivateTag +(0019,"SIEMENS CT VA0 COAD",22) DS DetectorSpacing 1 PrivateTag +(0019,"SIEMENS CT VA0 COAD",23) DS DetectorCenter 1 PrivateTag +(0019,"SIEMENS CT VA0 COAD",24) DS ReadingIntegrationTime 1 PrivateTag +(0019,"SIEMENS CT VA0 COAD",50) DS DetectorAlignment 1 PrivateTag +(0019,"SIEMENS CT VA0 COAD",52) DS Unknown 1 PrivateTag +(0019,"SIEMENS CT VA0 COAD",54) DS Unknown 1 PrivateTag +(0019,"SIEMENS CT VA0 COAD",60) DS FocusAlignment 1 PrivateTag +(0019,"SIEMENS CT VA0 COAD",65) UL FocalSpotDeflectionAmplitude 1 PrivateTag +(0019,"SIEMENS CT VA0 COAD",66) UL FocalSpotDeflectionPhase 1 PrivateTag +(0019,"SIEMENS CT VA0 COAD",67) UL FocalSpotDeflectionOffset 1 PrivateTag +(0019,"SIEMENS CT VA0 COAD",70) DS WaterScalingFactor 1 PrivateTag +(0019,"SIEMENS CT VA0 COAD",71) DS InterpolationFactor 1 PrivateTag +(0019,"SIEMENS CT VA0 COAD",80) LT PatientRegion 1 PrivateTag +(0019,"SIEMENS CT VA0 COAD",82) LT PatientPhaseOfLife 1 PrivateTag +(0019,"SIEMENS CT VA0 COAD",90) DS OsteoOffset 1 PrivateTag +(0019,"SIEMENS CT VA0 COAD",92) DS OsteoRegressionLineSlope 1 PrivateTag +(0019,"SIEMENS CT VA0 COAD",93) DS OsteoRegressionLineIntercept 1 PrivateTag +(0019,"SIEMENS CT VA0 COAD",94) DS OsteoStandardizationCode 1 PrivateTag +(0019,"SIEMENS CT VA0 COAD",96) IS OsteoPhantomNumber 1 PrivateTag +(0019,"SIEMENS CT VA0 COAD",A3) US Unknown 1-n PrivateTag +(0019,"SIEMENS CT VA0 COAD",A4) DS Unknown 1 PrivateTag +(0019,"SIEMENS CT VA0 COAD",A5) DS Unknown 1 PrivateTag +(0019,"SIEMENS CT VA0 COAD",A6) US Unknown 1-n PrivateTag +(0019,"SIEMENS CT VA0 COAD",A7) US Unknown 1-n PrivateTag +(0019,"SIEMENS CT VA0 COAD",A8) US Unknown 1-n PrivateTag +(0019,"SIEMENS CT VA0 COAD",A9) DS Unknown 1 PrivateTag +(0019,"SIEMENS CT VA0 COAD",AA) LT Unknown 1 PrivateTag +(0019,"SIEMENS CT VA0 COAD",AB) DS Unknown 1 PrivateTag +(0019,"SIEMENS CT VA0 COAD",AC) DS Unknown 1 PrivateTag +(0019,"SIEMENS CT VA0 COAD",AD) DS Unknown 1 PrivateTag +(0019,"SIEMENS CT VA0 COAD",AE) DS Unknown 1 PrivateTag +(0019,"SIEMENS CT VA0 COAD",AF) DS Unknown 1 PrivateTag +(0019,"SIEMENS CT VA0 COAD",B0) DS FeedPerRotation 1 PrivateTag +(0019,"SIEMENS CT VA0 COAD",BD) IS PulmoTriggerLevel 1 PrivateTag +(0019,"SIEMENS CT VA0 COAD",BE) DS ExpiratoricReserveVolume 1 PrivateTag +(0019,"SIEMENS CT VA0 COAD",BF) DS VitalCapacity 1 PrivateTag +(0019,"SIEMENS CT VA0 COAD",C0) DS PulmoWater 1 PrivateTag +(0019,"SIEMENS CT VA0 COAD",C1) DS PulmoAir 1 PrivateTag +(0019,"SIEMENS CT VA0 COAD",C2) DA PulmoDate 1 PrivateTag +(0019,"SIEMENS CT VA0 COAD",C3) TM PulmoTime 1 PrivateTag + +(0019,"SIEMENS CT VA0 GEN",10) DS SourceSideCollimatorAperture 1 PrivateTag +(0019,"SIEMENS CT VA0 GEN",11) DS DetectorSideCollimatorAperture 1 PrivateTag +(0019,"SIEMENS CT VA0 GEN",20) DS ExposureTime 1 PrivateTag +(0019,"SIEMENS CT VA0 GEN",21) DS ExposureCurrent 1 PrivateTag +(0019,"SIEMENS CT VA0 GEN",25) DS KVPGeneratorPowerCurrent 1 PrivateTag +(0019,"SIEMENS CT VA0 GEN",26) DS GeneratorVoltage 1 PrivateTag +(0019,"SIEMENS CT VA0 GEN",40) UL MasterControlMask 1 PrivateTag +(0019,"SIEMENS CT VA0 GEN",42) US ProcessingMask 5 PrivateTag +(0019,"SIEMENS CT VA0 GEN",44) US Unknown 1-n PrivateTag +(0019,"SIEMENS CT VA0 GEN",45) US Unknown 1-n PrivateTag +(0019,"SIEMENS CT VA0 GEN",62) IS NumberOfVirtuellChannels 1 PrivateTag +(0019,"SIEMENS CT VA0 GEN",70) IS NumberOfReadings 1 PrivateTag +(0019,"SIEMENS CT VA0 GEN",71) LT Unknown 1-n PrivateTag +(0019,"SIEMENS CT VA0 GEN",74) IS NumberOfProjections 1 PrivateTag +(0019,"SIEMENS CT VA0 GEN",75) IS NumberOfBytes 1 PrivateTag +(0019,"SIEMENS CT VA0 GEN",80) LT ReconstructionAlgorithmSet 1 PrivateTag +(0019,"SIEMENS CT VA0 GEN",81) LT ReconstructionAlgorithmIndex 1 PrivateTag +(0019,"SIEMENS CT VA0 GEN",82) LT RegenerationSoftwareVersion 1 PrivateTag +(0019,"SIEMENS CT VA0 GEN",88) DS Unknown 1 PrivateTag +(0021,"SIEMENS CT VA0 GEN",10) IS RotationAngle 1 PrivateTag +(0021,"SIEMENS CT VA0 GEN",11) IS StartAngle 1 PrivateTag +(0021,"SIEMENS CT VA0 GEN",20) US Unknown 1-n PrivateTag +(0021,"SIEMENS CT VA0 GEN",30) IS TopogramTubePosition 1 PrivateTag +(0021,"SIEMENS CT VA0 GEN",32) DS LengthOfTopogram 1 PrivateTag +(0021,"SIEMENS CT VA0 GEN",34) DS TopogramCorrectionFactor 1 PrivateTag +(0021,"SIEMENS CT VA0 GEN",36) DS MaximumTablePosition 1 PrivateTag +(0021,"SIEMENS CT VA0 GEN",40) IS TableMoveDirectionCode 1 PrivateTag +(0021,"SIEMENS CT VA0 GEN",45) IS VOIStartRow 1 PrivateTag +(0021,"SIEMENS CT VA0 GEN",46) IS VOIStopRow 1 PrivateTag +(0021,"SIEMENS CT VA0 GEN",47) IS VOIStartColumn 1 PrivateTag +(0021,"SIEMENS CT VA0 GEN",48) IS VOIStopColumn 1 PrivateTag +(0021,"SIEMENS CT VA0 GEN",49) IS VOIStartSlice 1 PrivateTag +(0021,"SIEMENS CT VA0 GEN",4a) IS VOIStopSlice 1 PrivateTag +(0021,"SIEMENS CT VA0 GEN",50) IS VectorStartRow 1 PrivateTag +(0021,"SIEMENS CT VA0 GEN",51) IS VectorRowStep 1 PrivateTag +(0021,"SIEMENS CT VA0 GEN",52) IS VectorStartColumn 1 PrivateTag +(0021,"SIEMENS CT VA0 GEN",53) IS VectorColumnStep 1 PrivateTag +(0021,"SIEMENS CT VA0 GEN",60) IS RangeTypeCode 1 PrivateTag +(0021,"SIEMENS CT VA0 GEN",62) IS ReferenceTypeCode 1 PrivateTag +(0021,"SIEMENS CT VA0 GEN",70) DS ObjectOrientation 3 PrivateTag +(0021,"SIEMENS CT VA0 GEN",72) DS LightOrientation 3 PrivateTag +(0021,"SIEMENS CT VA0 GEN",75) DS LightBrightness 1 PrivateTag +(0021,"SIEMENS CT VA0 GEN",76) DS LightContrast 1 PrivateTag +(0021,"SIEMENS CT VA0 GEN",7a) IS OverlayThreshold 2 PrivateTag +(0021,"SIEMENS CT VA0 GEN",7b) IS SurfaceThreshold 2 PrivateTag +(0021,"SIEMENS CT VA0 GEN",7c) IS GreyScaleThreshold 2 PrivateTag +(0021,"SIEMENS CT VA0 GEN",a0) DS Unknown 1 PrivateTag +(0021,"SIEMENS CT VA0 GEN",a2) LT Unknown 1 PrivateTag +(0021,"SIEMENS CT VA0 GEN",a7) LT Unknown 1 PrivateTag + +(0009,"SIEMENS CT VA0 IDE",10) LT Unknown 1 PrivateTag +(0009,"SIEMENS CT VA0 IDE",30) LT Unknown 1 PrivateTag +(0009,"SIEMENS CT VA0 IDE",31) LT Unknown 1 PrivateTag +(0009,"SIEMENS CT VA0 IDE",32) LT Unknown 1 PrivateTag +(0009,"SIEMENS CT VA0 IDE",34) LT Unknown 1 PrivateTag +(0009,"SIEMENS CT VA0 IDE",40) LT Unknown 1 PrivateTag +(0009,"SIEMENS CT VA0 IDE",42) LT Unknown 1 PrivateTag +(0009,"SIEMENS CT VA0 IDE",50) LT Unknown 1 PrivateTag +(0009,"SIEMENS CT VA0 IDE",51) LT Unknown 1 PrivateTag + +(0009,"SIEMENS CT VA0 ORI",20) LT Unknown 1 PrivateTag +(0009,"SIEMENS CT VA0 ORI",30) LT Unknown 1 PrivateTag + +(6021,"SIEMENS CT VA0 OST",00) LT OsteoContourComment 1 PrivateTag +(6021,"SIEMENS CT VA0 OST",10) US OsteoContourBuffer 256 PrivateTag + +(0021,"SIEMENS CT VA0 RAW",10) UL CreationMask 2 PrivateTag +(0021,"SIEMENS CT VA0 RAW",20) UL EvaluationMask 2 PrivateTag +(0021,"SIEMENS CT VA0 RAW",30) US ExtendedProcessingMask 7 PrivateTag +(0021,"SIEMENS CT VA0 RAW",40) US Unknown 1-n PrivateTag +(0021,"SIEMENS CT VA0 RAW",41) US Unknown 1-n PrivateTag +(0021,"SIEMENS CT VA0 RAW",42) US Unknown 1-n PrivateTag +(0021,"SIEMENS CT VA0 RAW",43) US Unknown 1-n PrivateTag +(0021,"SIEMENS CT VA0 RAW",44) US Unknown 1-n PrivateTag +(0021,"SIEMENS CT VA0 RAW",50) LT Unknown 1 PrivateTag + +(0009,"SIEMENS DICOM",10) UN Unknown 1 PrivateTag +(0009,"SIEMENS DICOM",12) LT Unknown 1 PrivateTag + +(0019,"SIEMENS DLR.01",10) LT MeasurementMode 1 PrivateTag +(0019,"SIEMENS DLR.01",11) LT ImageType 1 PrivateTag +(0019,"SIEMENS DLR.01",15) LT SoftwareVersion 1 PrivateTag +(0019,"SIEMENS DLR.01",20) LT MPMCode 1 PrivateTag +(0019,"SIEMENS DLR.01",21) LT Latitude 1 PrivateTag +(0019,"SIEMENS DLR.01",22) LT Sensitivity 1 PrivateTag +(0019,"SIEMENS DLR.01",23) LT EDR 1 PrivateTag +(0019,"SIEMENS DLR.01",24) LT LFix 1 PrivateTag +(0019,"SIEMENS DLR.01",25) LT SFix 1 PrivateTag +(0019,"SIEMENS DLR.01",26) LT PresetMode 1 PrivateTag +(0019,"SIEMENS DLR.01",27) LT Region 1 PrivateTag +(0019,"SIEMENS DLR.01",28) LT Subregion 1 PrivateTag +(0019,"SIEMENS DLR.01",30) LT Orientation 1 PrivateTag +(0019,"SIEMENS DLR.01",31) LT MarkOnFilm 1 PrivateTag +(0019,"SIEMENS DLR.01",32) LT RotationOnDRC 1 PrivateTag +(0019,"SIEMENS DLR.01",40) LT ReaderType 1 PrivateTag +(0019,"SIEMENS DLR.01",41) LT SubModality 1 PrivateTag +(0019,"SIEMENS DLR.01",42) LT ReaderSerialNumber 1 PrivateTag +(0019,"SIEMENS DLR.01",50) LT CassetteScale 1 PrivateTag +(0019,"SIEMENS DLR.01",51) LT CassetteMatrix 1 PrivateTag +(0019,"SIEMENS DLR.01",52) LT CassetteSubmatrix 1 PrivateTag +(0019,"SIEMENS DLR.01",53) LT Barcode 1 PrivateTag +(0019,"SIEMENS DLR.01",60) LT ContrastType 1 PrivateTag +(0019,"SIEMENS DLR.01",61) LT RotationAmount 1 PrivateTag +(0019,"SIEMENS DLR.01",62) LT RotationCenter 1 PrivateTag +(0019,"SIEMENS DLR.01",63) LT DensityShift 1 PrivateTag +(0019,"SIEMENS DLR.01",64) US FrequencyRank 1 PrivateTag +(0019,"SIEMENS DLR.01",65) LT FrequencyEnhancement 1 PrivateTag +(0019,"SIEMENS DLR.01",66) LT FrequencyType 1 PrivateTag +(0019,"SIEMENS DLR.01",67) LT KernelLength 1 PrivateTag +(0019,"SIEMENS DLR.01",68) UL KernelMode 1 PrivateTag +(0019,"SIEMENS DLR.01",69) UL ConvolutionMode 1 PrivateTag +(0019,"SIEMENS DLR.01",70) LT PLASource 1 PrivateTag +(0019,"SIEMENS DLR.01",71) LT PLADestination 1 PrivateTag +(0019,"SIEMENS DLR.01",75) LT UIDOriginalImage 1 PrivateTag +(0019,"SIEMENS DLR.01",76) LT Unknown 1 PrivateTag +(0019,"SIEMENS DLR.01",80) LT ReaderHeader 1 PrivateTag +(0019,"SIEMENS DLR.01",90) LT PLAOfSecondaryDestination 1 PrivateTag +(0019,"SIEMENS DLR.01",a0) DS Unknown 1 PrivateTag +(0019,"SIEMENS DLR.01",a1) DS Unknown 1 PrivateTag +(0041,"SIEMENS DLR.01",10) US NumberOfHardcopies 1 PrivateTag +(0041,"SIEMENS DLR.01",20) LT FilmFormat 1 PrivateTag +(0041,"SIEMENS DLR.01",30) LT FilmSize 1 PrivateTag +(0041,"SIEMENS DLR.01",31) LT FullFilmFormat 1 PrivateTag + +(0003,"SIEMENS ISI",08) US ISICommandField 1 PrivateTag +(0003,"SIEMENS ISI",11) US AttachIDApplicationCode 1 PrivateTag +(0003,"SIEMENS ISI",12) UL AttachIDMessageCount 1 PrivateTag +(0003,"SIEMENS ISI",13) DA AttachIDDate 1 PrivateTag +(0003,"SIEMENS ISI",14) TM AttachIDTime 1 PrivateTag +(0003,"SIEMENS ISI",20) US MessageType 1 PrivateTag +(0003,"SIEMENS ISI",30) DA MaxWaitingDate 1 PrivateTag +(0003,"SIEMENS ISI",31) TM MaxWaitingTime 1 PrivateTag +(0009,"SIEMENS ISI",01) UN RISPatientInfoIMGEF 1 PrivateTag +(0011,"SIEMENS ISI",03) LT PatientUID 1 PrivateTag +(0011,"SIEMENS ISI",04) LT PatientID 1 PrivateTag +(0011,"SIEMENS ISI",0a) LT CaseID 1 PrivateTag +(0011,"SIEMENS ISI",22) LT RequestID 1 PrivateTag +(0011,"SIEMENS ISI",23) LT ExaminationUID 1 PrivateTag +(0011,"SIEMENS ISI",a1) DA PatientRegistrationDate 1 PrivateTag +(0011,"SIEMENS ISI",a2) TM PatientRegistrationTime 1 PrivateTag +(0011,"SIEMENS ISI",b0) LT PatientLastName 1 PrivateTag +(0011,"SIEMENS ISI",b2) LT PatientFirstName 1 PrivateTag +(0011,"SIEMENS ISI",b4) LT PatientHospitalStatus 1 PrivateTag +(0011,"SIEMENS ISI",bc) TM CurrentLocationTime 1 PrivateTag +(0011,"SIEMENS ISI",c0) LT PatientInsuranceStatus 1 PrivateTag +(0011,"SIEMENS ISI",d0) LT PatientBillingType 1 PrivateTag +(0011,"SIEMENS ISI",d2) LT PatientBillingAddress 1 PrivateTag +(0031,"SIEMENS ISI",12) LT ExaminationReason 1 PrivateTag +(0031,"SIEMENS ISI",30) DA RequestedDate 1 PrivateTag +(0031,"SIEMENS ISI",32) TM WorklistRequestStartTime 1 PrivateTag +(0031,"SIEMENS ISI",33) TM WorklistRequestEndTime 1 PrivateTag +(0031,"SIEMENS ISI",4a) TM RequestedTime 1 PrivateTag +(0031,"SIEMENS ISI",80) LT RequestedLocation 1 PrivateTag +(0055,"SIEMENS ISI",46) LT CurrentWard 1 PrivateTag +(0193,"SIEMENS ISI",02) DS RISKey 1 PrivateTag +(0307,"SIEMENS ISI",01) UN RISWorklistIMGEF 1 PrivateTag +(0309,"SIEMENS ISI",01) UN RISReportIMGEF 1 PrivateTag +(4009,"SIEMENS ISI",01) LT ReportID 1 PrivateTag +(4009,"SIEMENS ISI",20) LT ReportStatus 1 PrivateTag +(4009,"SIEMENS ISI",30) DA ReportCreationDate 1 PrivateTag +(4009,"SIEMENS ISI",70) LT ReportApprovingPhysician 1 PrivateTag +(4009,"SIEMENS ISI",e0) LT ReportText 1 PrivateTag +(4009,"SIEMENS ISI",e1) LT ReportAuthor 1 PrivateTag +(4009,"SIEMENS ISI",e3) LT ReportingRadiologist 1 PrivateTag + +(0029,"SIEMENS MED DISPLAY",04) LT PhotometricInterpretation 1 PrivateTag +(0029,"SIEMENS MED DISPLAY",10) US RowsOfSubmatrix 1 PrivateTag +(0029,"SIEMENS MED DISPLAY",11) US ColumnsOfSubmatrix 1 PrivateTag +(0029,"SIEMENS MED DISPLAY",20) US Unknown 1 PrivateTag +(0029,"SIEMENS MED DISPLAY",21) US Unknown 1 PrivateTag +(0029,"SIEMENS MED DISPLAY",50) US OriginOfSubmatrix 1 PrivateTag +(0029,"SIEMENS MED DISPLAY",99) LT ShutterType 1 PrivateTag +(0029,"SIEMENS MED DISPLAY",a0) US RowsOfRectangularShutter 1 PrivateTag +(0029,"SIEMENS MED DISPLAY",a1) US ColumnsOfRectangularShutter 1 PrivateTag +(0029,"SIEMENS MED DISPLAY",a2) US OriginOfRectangularShutter 1 PrivateTag +(0029,"SIEMENS MED DISPLAY",b0) US RadiusOfCircularShutter 1 PrivateTag +(0029,"SIEMENS MED DISPLAY",b2) US OriginOfCircularShutter 1 PrivateTag +(0029,"SIEMENS MED DISPLAY",c1) US ContourOfIrregularShutter 1 PrivateTag + +(0029,"SIEMENS MED HG",10) US ListOfGroupNumbers 1 PrivateTag +(0029,"SIEMENS MED HG",15) LT ListOfShadowOwnerCodes 1 PrivateTag +(0029,"SIEMENS MED HG",20) US ListOfElementNumbers 1 PrivateTag +(0029,"SIEMENS MED HG",30) US ListOfTotalDisplayLength 1 PrivateTag +(0029,"SIEMENS MED HG",40) LT ListOfDisplayPrefix 1 PrivateTag +(0029,"SIEMENS MED HG",50) LT ListOfDisplayPostfix 1 PrivateTag +(0029,"SIEMENS MED HG",60) US ListOfTextPosition 1 PrivateTag +(0029,"SIEMENS MED HG",70) LT ListOfTextConcatenation 1 PrivateTag +(0029,"SIEMENS MED MG",10) US ListOfGroupNumbers 1 PrivateTag +(0029,"SIEMENS MED MG",15) LT ListOfShadowOwnerCodes 1 PrivateTag +(0029,"SIEMENS MED MG",20) US ListOfElementNumbers 1 PrivateTag +(0029,"SIEMENS MED MG",30) US ListOfTotalDisplayLength 1 PrivateTag +(0029,"SIEMENS MED MG",40) LT ListOfDisplayPrefix 1 PrivateTag +(0029,"SIEMENS MED MG",50) LT ListOfDisplayPostfix 1 PrivateTag +(0029,"SIEMENS MED MG",60) US ListOfTextPosition 1 PrivateTag +(0029,"SIEMENS MED MG",70) LT ListOfTextConcatenation 1 PrivateTag + +(0009,"SIEMENS MED",10) LO RecognitionCode 1 PrivateTag +(0009,"SIEMENS MED",30) UL ByteOffsetOfOriginalHeader 1 PrivateTag +(0009,"SIEMENS MED",31) UL LengthOfOriginalHeader 1 PrivateTag +(0009,"SIEMENS MED",40) UL ByteOffsetOfPixelmatrix 1 PrivateTag +(0009,"SIEMENS MED",41) UL LengthOfPixelmatrixInBytes 1 PrivateTag +(0009,"SIEMENS MED",50) LT Unknown 1 PrivateTag +(0009,"SIEMENS MED",51) LT Unknown 1 PrivateTag +(0009,"SIEMENS MED",f5) LT PDMEFIDPlaceholder 1 PrivateTag +(0009,"SIEMENS MED",f6) LT PDMDataObjectTypeExtension 1 PrivateTag +(0021,"SIEMENS MED",10) DS Zoom 1 PrivateTag +(0021,"SIEMENS MED",11) DS Target 2 PrivateTag +(0021,"SIEMENS MED",12) IS TubeAngle 1 PrivateTag +(0021,"SIEMENS MED",20) US ROIMask 1 PrivateTag +(7001,"SIEMENS MED",10) LT Dummy 1 PrivateTag +(7003,"SIEMENS MED",10) LT Header 1 PrivateTag +(7005,"SIEMENS MED",10) LT Dummy 1 PrivateTag + +(0029,"SIEMENS MEDCOM HEADER",08) CS MedComHeaderType 1 PrivateTag +(0029,"SIEMENS MEDCOM HEADER",09) LO MedComHeaderVersion 1 PrivateTag +(0029,"SIEMENS MEDCOM HEADER",10) OB MedComHeaderInfo 1 PrivateTag +(0029,"SIEMENS MEDCOM HEADER",20) OB MedComHistoryInformation 1 PrivateTag +(0029,"SIEMENS MEDCOM HEADER",31) LO PMTFInformation1 1 PrivateTag +(0029,"SIEMENS MEDCOM HEADER",32) UL PMTFInformation2 1 PrivateTag +(0029,"SIEMENS MEDCOM HEADER",33) UL PMTFInformation3 1 PrivateTag +(0029,"SIEMENS MEDCOM HEADER",34) CS PMTFInformation4 1 PrivateTag +(0029,"SIEMENS MEDCOM HEADER",35) UL PMTFInformation5 1 PrivateTag +(0029,"SIEMENS MEDCOM HEADER",40) SQ ApplicationHeaderSequence 1 PrivateTag +(0029,"SIEMENS MEDCOM HEADER",41) CS ApplicationHeaderType 1 PrivateTag +(0029,"SIEMENS MEDCOM HEADER",42) LO ApplicationHeaderID 1 PrivateTag +(0029,"SIEMENS MEDCOM HEADER",43) LO ApplicationHeaderVersion 1 PrivateTag +(0029,"SIEMENS MEDCOM HEADER",44) OB ApplicationHeaderInfo 1 PrivateTag +(0029,"SIEMENS MEDCOM HEADER",50) LO WorkflowControlFlags 8 PrivateTag +(0029,"SIEMENS MEDCOM HEADER",51) CS ArchiveManagementFlagKeepOnline 1 PrivateTag +(0029,"SIEMENS MEDCOM HEADER",52) CS ArchiveManagementFlagDoNotArchive 1 PrivateTag +(0029,"SIEMENS MEDCOM HEADER",53) CS ImageLocationStatus 1 PrivateTag +(0029,"SIEMENS MEDCOM HEADER",54) DS EstimatedRetrieveTime 1 PrivateTag +(0029,"SIEMENS MEDCOM HEADER",55) DS DataSizeOfRetrievedImages 1 PrivateTag +(0029,"SIEMENS MEDCOM HEADER",70) SQ SiemensLinkSequence 1 PrivateTag +(0029,"SIEMENS MEDCOM HEADER",71) AT ReferencedTag 1 PrivateTag +(0029,"SIEMENS MEDCOM HEADER",72) CS ReferencedTagType 1 PrivateTag +(0029,"SIEMENS MEDCOM HEADER",73) UL ReferencedValueLength 1 PrivateTag +(0029,"SIEMENS MEDCOM HEADER",74) CS ReferencedObjectDeviceType 1 PrivateTag +(0029,"SIEMENS MEDCOM HEADER",75) OB ReferencedObjectDeviceLocation 1 PrivateTag +(0029,"SIEMENS MEDCOM HEADER",76) OB ReferencedObjectDeviceID 1 PrivateTag + +(0029,"SIEMENS MEDCOM HEADER2",60) LO SeriesWorkflowStatus 1 PrivateTag + +(0029,"SIEMENS MEDCOM OOG",08) CS MEDCOMOOGType 1 PrivateTag +(0029,"SIEMENS MEDCOM OOG",09) LO MEDCOMOOGVersion 1 PrivateTag +(0029,"SIEMENS MEDCOM OOG",10) OB MEDCOMOOGInfo 1 PrivateTag + +(0019,"SIEMENS MR VA0 COAD",12) DS MagneticFieldStrength 1 PrivateTag +(0019,"SIEMENS MR VA0 COAD",14) DS ADCVoltage 1 PrivateTag +(0019,"SIEMENS MR VA0 COAD",16) DS ADCOffset 2 PrivateTag +(0019,"SIEMENS MR VA0 COAD",20) DS TransmitterAmplitude 1 PrivateTag +(0019,"SIEMENS MR VA0 COAD",21) IS NumberOfTransmitterAmplitudes 1 PrivateTag +(0019,"SIEMENS MR VA0 COAD",22) DS TransmitterAttenuator 1 PrivateTag +(0019,"SIEMENS MR VA0 COAD",24) DS TransmitterCalibration 1 PrivateTag +(0019,"SIEMENS MR VA0 COAD",26) DS TransmitterReference 1 PrivateTag +(0019,"SIEMENS MR VA0 COAD",50) DS ReceiverTotalGain 1 PrivateTag +(0019,"SIEMENS MR VA0 COAD",51) DS ReceiverAmplifierGain 1 PrivateTag +(0019,"SIEMENS MR VA0 COAD",52) DS ReceiverPreamplifierGain 1 PrivateTag +(0019,"SIEMENS MR VA0 COAD",54) DS ReceiverCableAttenuation 1 PrivateTag +(0019,"SIEMENS MR VA0 COAD",55) DS ReceiverReferenceGain 1 PrivateTag +(0019,"SIEMENS MR VA0 COAD",56) DS ReceiverFilterFrequency 1 PrivateTag +(0019,"SIEMENS MR VA0 COAD",60) DS ReconstructionScaleFactor 1 PrivateTag +(0019,"SIEMENS MR VA0 COAD",62) DS ReferenceScaleFactor 1 PrivateTag +(0019,"SIEMENS MR VA0 COAD",70) DS PhaseGradientAmplitude 1 PrivateTag +(0019,"SIEMENS MR VA0 COAD",71) DS ReadoutGradientAmplitude 1 PrivateTag +(0019,"SIEMENS MR VA0 COAD",72) DS SelectionGradientAmplitude 1 PrivateTag +(0019,"SIEMENS MR VA0 COAD",80) DS GradientDelayTime 3 PrivateTag +(0019,"SIEMENS MR VA0 COAD",82) DS TotalGradientDelayTime 1 PrivateTag +(0019,"SIEMENS MR VA0 COAD",90) LT SensitivityCorrectionLabel 1 PrivateTag +(0019,"SIEMENS MR VA0 COAD",91) DS SaturationPhaseEncodingVectorCoronalComponent 6 PrivateTag +(0019,"SIEMENS MR VA0 COAD",92) DS SaturationReadoutVectorCoronalComponent 6 PrivateTag +(0019,"SIEMENS MR VA0 COAD",a0) US RFWatchdogMask 3 PrivateTag +(0019,"SIEMENS MR VA0 COAD",a1) DS EPIReconstructionSlope 1 PrivateTag +(0019,"SIEMENS MR VA0 COAD",a2) DS RFPowerErrorIndicator 1 PrivateTag +(0019,"SIEMENS MR VA0 COAD",a5) DS SpecificAbsorptionRateWholeBody 3 PrivateTag +(0019,"SIEMENS MR VA0 COAD",a6) DS SpecificEnergyDose 3 PrivateTag +(0019,"SIEMENS MR VA0 COAD",b0) UL AdjustmentStatusMask 1 PrivateTag +(0019,"SIEMENS MR VA0 COAD",c1) DS EPICapacity 6 PrivateTag +(0019,"SIEMENS MR VA0 COAD",c2) DS EPIInductance 3 PrivateTag +(0019,"SIEMENS MR VA0 COAD",c3) IS EPISwitchConfigurationCode 1-n PrivateTag +(0019,"SIEMENS MR VA0 COAD",c4) IS EPISwitchHardwareCode 1-n PrivateTag +(0019,"SIEMENS MR VA0 COAD",c5) DS EPISwitchDelayTime 1-n PrivateTag +(0019,"SIEMENS MR VA0 COAD",d1) DS FlowSensitivity 1 PrivateTag +(0019,"SIEMENS MR VA0 COAD",d2) LT CalculationSubmode 1 PrivateTag +(0019,"SIEMENS MR VA0 COAD",d3) DS FieldOfViewRatio 1 PrivateTag +(0019,"SIEMENS MR VA0 COAD",d4) IS BaseRawMatrixSize 1 PrivateTag +(0019,"SIEMENS MR VA0 COAD",d5) IS 2DOversamplingLines 1 PrivateTag +(0019,"SIEMENS MR VA0 COAD",d6) IS 3DPhaseOversamplingPartitions 1 PrivateTag +(0019,"SIEMENS MR VA0 COAD",d7) IS EchoLinePosition 1 PrivateTag +(0019,"SIEMENS MR VA0 COAD",d8) IS EchoColumnPosition 1 PrivateTag +(0019,"SIEMENS MR VA0 COAD",d9) IS LinesPerSegment 1 PrivateTag +(0019,"SIEMENS MR VA0 COAD",da) LT PhaseCodingDirection 1 PrivateTag + +(0019,"SIEMENS MR VA0 GEN",10) DS TotalMeasurementTimeNominal 1 PrivateTag +(0019,"SIEMENS MR VA0 GEN",11) DS TotalMeasurementTimeCurrent 1 PrivateTag +(0019,"SIEMENS MR VA0 GEN",12) DS StartDelayTime 1 PrivateTag +(0019,"SIEMENS MR VA0 GEN",13) DS DwellTime 1 PrivateTag +(0019,"SIEMENS MR VA0 GEN",14) IS NumberOfPhases 1 PrivateTag +(0019,"SIEMENS MR VA0 GEN",16) UL SequenceControlMask 2 PrivateTag +(0019,"SIEMENS MR VA0 GEN",18) UL MeasurementStatusMask 1 PrivateTag +(0019,"SIEMENS MR VA0 GEN",20) IS NumberOfFourierLinesNominal 1 PrivateTag +(0019,"SIEMENS MR VA0 GEN",21) IS NumberOfFourierLinesCurrent 1 PrivateTag +(0019,"SIEMENS MR VA0 GEN",26) IS NumberOfFourierLinesAfterZero 1 PrivateTag +(0019,"SIEMENS MR VA0 GEN",28) IS FirstMeasuredFourierLine 1 PrivateTag +(0019,"SIEMENS MR VA0 GEN",30) IS AcquisitionColumns 1 PrivateTag +(0019,"SIEMENS MR VA0 GEN",31) IS ReconstructionColumns 1 PrivateTag +(0019,"SIEMENS MR VA0 GEN",40) IS ArrayCoilElementNumber 1 PrivateTag +(0019,"SIEMENS MR VA0 GEN",41) UL ArrayCoilElementSelectMask 1 PrivateTag +(0019,"SIEMENS MR VA0 GEN",42) UL ArrayCoilElementDataMask 1 PrivateTag +(0019,"SIEMENS MR VA0 GEN",43) IS ArrayCoilElementToADCConnect 1-n PrivateTag +(0019,"SIEMENS MR VA0 GEN",44) DS ArrayCoilElementNoiseLevel 1-n PrivateTag +(0019,"SIEMENS MR VA0 GEN",45) IS ArrayCoilADCPairNumber 1 PrivateTag +(0019,"SIEMENS MR VA0 GEN",46) UL ArrayCoilCombinationMask 1 PrivateTag +(0019,"SIEMENS MR VA0 GEN",50) IS NumberOfAverages 1 PrivateTag +(0019,"SIEMENS MR VA0 GEN",60) DS FlipAngle 1 PrivateTag +(0019,"SIEMENS MR VA0 GEN",70) IS NumberOfPrescans 1 PrivateTag +(0019,"SIEMENS MR VA0 GEN",81) LT FilterTypeForRawData 1 PrivateTag +(0019,"SIEMENS MR VA0 GEN",82) DS FilterParameterForRawData 1-n PrivateTag +(0019,"SIEMENS MR VA0 GEN",83) LT FilterTypeForImageData 1 PrivateTag +(0019,"SIEMENS MR VA0 GEN",84) DS FilterParameterForImageData 1-n PrivateTag +(0019,"SIEMENS MR VA0 GEN",85) LT FilterTypeForPhaseCorrection 1 PrivateTag +(0019,"SIEMENS MR VA0 GEN",86) DS FilterParameterForPhaseCorrection 1-n PrivateTag +(0019,"SIEMENS MR VA0 GEN",87) LT NormalizationFilterTypeForImageData 1 PrivateTag +(0019,"SIEMENS MR VA0 GEN",88) DS NormalizationFilterParameterForImageData 1-n PrivateTag +(0019,"SIEMENS MR VA0 GEN",90) IS NumberOfSaturationRegions 1 PrivateTag +(0019,"SIEMENS MR VA0 GEN",91) DS SaturationPhaseEncodingVectorSagittalComponent 6 PrivateTag +(0019,"SIEMENS MR VA0 GEN",92) DS SaturationReadoutVectorSagittalComponent 6 PrivateTag +(0019,"SIEMENS MR VA0 GEN",93) DS EPIStimulationMonitorMode 1 PrivateTag +(0019,"SIEMENS MR VA0 GEN",94) DS ImageRotationAngle 1 PrivateTag +(0019,"SIEMENS MR VA0 GEN",96) UL CoilIDMask 3 PrivateTag +(0019,"SIEMENS MR VA0 GEN",97) UL CoilClassMask 2 PrivateTag +(0019,"SIEMENS MR VA0 GEN",98) DS CoilPosition 3 PrivateTag +(0019,"SIEMENS MR VA0 GEN",a0) DS EPIReconstructionPhase 1 PrivateTag +(0019,"SIEMENS MR VA0 GEN",a1) DS EPIReconstructionSlope 1 PrivateTag +(0021,"SIEMENS MR VA0 GEN",20) IS PhaseCorrectionRowsSequence 1 PrivateTag +(0021,"SIEMENS MR VA0 GEN",21) IS PhaseCorrectionColumnsSequence 1 PrivateTag +(0021,"SIEMENS MR VA0 GEN",22) IS PhaseCorrectionRowsReconstruction 1 PrivateTag +(0021,"SIEMENS MR VA0 GEN",24) IS PhaseCorrectionColumnsReconstruction 1 PrivateTag +(0021,"SIEMENS MR VA0 GEN",30) IS NumberOf3DRawPartitionsNominal 1 PrivateTag +(0021,"SIEMENS MR VA0 GEN",31) IS NumberOf3DRawPartitionsCurrent 1 PrivateTag +(0021,"SIEMENS MR VA0 GEN",34) IS NumberOf3DImagePartitions 1 PrivateTag +(0021,"SIEMENS MR VA0 GEN",36) IS Actual3DImagePartitionNumber 1 PrivateTag +(0021,"SIEMENS MR VA0 GEN",39) DS SlabThickness 1 PrivateTag +(0021,"SIEMENS MR VA0 GEN",40) IS NumberOfSlicesNominal 1 PrivateTag +(0021,"SIEMENS MR VA0 GEN",41) IS NumberOfSlicesCurrent 1 PrivateTag +(0021,"SIEMENS MR VA0 GEN",42) IS CurrentSliceNumber 1 PrivateTag +(0021,"SIEMENS MR VA0 GEN",43) IS CurrentGroupNumber 1 PrivateTag +(0021,"SIEMENS MR VA0 GEN",44) DS CurrentSliceDistanceFactor 1 PrivateTag +(0021,"SIEMENS MR VA0 GEN",45) IS MIPStartRow 1 PrivateTag +(0021,"SIEMENS MR VA0 GEN",46) IS MIPStopRow 1 PrivateTag +(0021,"SIEMENS MR VA0 GEN",47) IS MIPStartColumn 1 PrivateTag +(0021,"SIEMENS MR VA0 GEN",48) IS MIPStartColumn 1 PrivateTag +(0021,"SIEMENS MR VA0 GEN",49) IS MIPStartSlice Name= 1 PrivateTag +(0021,"SIEMENS MR VA0 GEN",4a) IS MIPStartSlice 1 PrivateTag +(0021,"SIEMENS MR VA0 GEN",4f) LT OrderofSlices 1 PrivateTag +(0021,"SIEMENS MR VA0 GEN",50) US SignalMask 1 PrivateTag +(0021,"SIEMENS MR VA0 GEN",52) DS DelayAfterTrigger 1 PrivateTag +(0021,"SIEMENS MR VA0 GEN",53) IS RRInterval 1 PrivateTag +(0021,"SIEMENS MR VA0 GEN",54) DS NumberOfTriggerPulses 1 PrivateTag +(0021,"SIEMENS MR VA0 GEN",56) DS RepetitionTimeEffective 1 PrivateTag +(0021,"SIEMENS MR VA0 GEN",57) LT GatePhase 1 PrivateTag +(0021,"SIEMENS MR VA0 GEN",58) DS GateThreshold 1 PrivateTag +(0021,"SIEMENS MR VA0 GEN",59) DS GatedRatio 1 PrivateTag +(0021,"SIEMENS MR VA0 GEN",60) IS NumberOfInterpolatedImages 1 PrivateTag +(0021,"SIEMENS MR VA0 GEN",70) IS NumberOfEchoes 1 PrivateTag +(0021,"SIEMENS MR VA0 GEN",72) DS SecondEchoTime 1 PrivateTag +(0021,"SIEMENS MR VA0 GEN",73) DS SecondRepetitionTime 1 PrivateTag +(0021,"SIEMENS MR VA0 GEN",80) IS CardiacCode 1 PrivateTag +(0021,"SIEMENS MR VA0 GEN",91) DS SaturationPhaseEncodingVectorTransverseComponent 6 PrivateTag +(0021,"SIEMENS MR VA0 GEN",92) DS SaturationReadoutVectorTransverseComponent 6 PrivateTag +(0021,"SIEMENS MR VA0 GEN",93) DS EPIChangeValueOfMagnitude 1 PrivateTag +(0021,"SIEMENS MR VA0 GEN",94) DS EPIChangeValueOfXComponent 1 PrivateTag +(0021,"SIEMENS MR VA0 GEN",95) DS EPIChangeValueOfYComponent 1 PrivateTag +(0021,"SIEMENS MR VA0 GEN",96) DS EPIChangeValueOfZComponent 1 PrivateTag + +(0021,"SIEMENS MR VA0 RAW",00) LT SequenceType 1 PrivateTag +(0021,"SIEMENS MR VA0 RAW",01) IS VectorSizeOriginal 1 PrivateTag +(0021,"SIEMENS MR VA0 RAW",02) IS VectorSizeExtended 1 PrivateTag +(0021,"SIEMENS MR VA0 RAW",03) DS AcquiredSpectralRange 1 PrivateTag +(0021,"SIEMENS MR VA0 RAW",04) DS VOIPosition 3 PrivateTag +(0021,"SIEMENS MR VA0 RAW",05) DS VOISize 3 PrivateTag +(0021,"SIEMENS MR VA0 RAW",06) IS CSIMatrixSizeOriginal 3 PrivateTag +(0021,"SIEMENS MR VA0 RAW",07) IS CSIMatrixSizeExtended 3 PrivateTag +(0021,"SIEMENS MR VA0 RAW",08) DS SpatialGridShift 3 PrivateTag +(0021,"SIEMENS MR VA0 RAW",09) DS SignalLimitsMinimum 1 PrivateTag +(0021,"SIEMENS MR VA0 RAW",10) DS SignalLimitsMaximum 1 PrivateTag +(0021,"SIEMENS MR VA0 RAW",11) DS SpecInfoMask 1 PrivateTag +(0021,"SIEMENS MR VA0 RAW",12) DS EPITimeRateOfChangeOfMagnitude 1 PrivateTag +(0021,"SIEMENS MR VA0 RAW",13) DS EPITimeRateOfChangeOfXComponent 1 PrivateTag +(0021,"SIEMENS MR VA0 RAW",14) DS EPITimeRateOfChangeOfYComponent 1 PrivateTag +(0021,"SIEMENS MR VA0 RAW",15) DS EPITimeRateOfChangeOfZComponent 1 PrivateTag +(0021,"SIEMENS MR VA0 RAW",16) DS EPITimeRateOfChangeLegalLimit1 1 PrivateTag +(0021,"SIEMENS MR VA0 RAW",17) DS EPIOperationModeFlag 1 PrivateTag +(0021,"SIEMENS MR VA0 RAW",18) DS EPIFieldCalculationSafetyFactor 1 PrivateTag +(0021,"SIEMENS MR VA0 RAW",19) DS EPILegalLimit1OfChangeValue 1 PrivateTag +(0021,"SIEMENS MR VA0 RAW",20) DS EPILegalLimit2OfChangeValue 1 PrivateTag +(0021,"SIEMENS MR VA0 RAW",21) DS EPIRiseTime 1 PrivateTag +(0021,"SIEMENS MR VA0 RAW",30) DS ArrayCoilADCOffset 16 PrivateTag +(0021,"SIEMENS MR VA0 RAW",31) DS ArrayCoilPreamplifierGain 16 PrivateTag +(0021,"SIEMENS MR VA0 RAW",50) LT SaturationType 1 PrivateTag +(0021,"SIEMENS MR VA0 RAW",51) DS SaturationNormalVector 3 PrivateTag +(0021,"SIEMENS MR VA0 RAW",52) DS SaturationPositionVector 3 PrivateTag +(0021,"SIEMENS MR VA0 RAW",53) DS SaturationThickness 6 PrivateTag +(0021,"SIEMENS MR VA0 RAW",54) DS SaturationWidth 6 PrivateTag +(0021,"SIEMENS MR VA0 RAW",55) DS SaturationDistance 6 PrivateTag + +(7fe3,"SIEMENS NUMARIS II",00) LT ImageGraphicsFormatCode 1 PrivateTag +(7fe3,"SIEMENS NUMARIS II",10) OB ImageGraphics 1 PrivateTag +(7fe3,"SIEMENS NUMARIS II",20) OB ImageGraphicsDummy 1 PrivateTag + +(0011,"SIEMENS RA GEN",20) SL FluoroTimer 1 PrivateTag +(0011,"SIEMENS RA GEN",25) SL PtopDoseAreaProduct 1 PrivateTag +(0011,"SIEMENS RA GEN",26) SL PtopTotalSkinDose 1 PrivateTag +(0011,"SIEMENS RA GEN",30) LT Unknown 1 PrivateTag +(0011,"SIEMENS RA GEN",35) LO PatientInitialPuckCounter 1 PrivateTag +(0011,"SIEMENS RA GEN",40) SS SPIDataObjectType 1 PrivateTag +(0019,"SIEMENS RA GEN",15) LO AcquiredPlane 1 PrivateTag +(0019,"SIEMENS RA GEN",1f) SS DefaultTableIsoCenterHeight 1 PrivateTag +(0019,"SIEMENS RA GEN",20) SL SceneFlag 1 PrivateTag +(0019,"SIEMENS RA GEN",22) SL RefPhotofileFlag 1 PrivateTag +(0019,"SIEMENS RA GEN",24) LO SceneName 1 PrivateTag +(0019,"SIEMENS RA GEN",26) SS AcquisitionIndex 1 PrivateTag +(0019,"SIEMENS RA GEN",28) SS MixedPulseMode 1 PrivateTag +(0019,"SIEMENS RA GEN",2a) SS NoOfPositions 1 PrivateTag +(0019,"SIEMENS RA GEN",2c) SS NoOfPhases 1 PrivateTag +(0019,"SIEMENS RA GEN",2e) SS FrameRateForPositions 1-n PrivateTag +(0019,"SIEMENS RA GEN",30) SS NoOfFramesForPositions 1-n PrivateTag +(0019,"SIEMENS RA GEN",32) SS SteppingDirection 1 PrivateTag +(0019,"SIEMENS RA GEN",34) US Unknown 1 PrivateTag +(0019,"SIEMENS RA GEN",36) US Unknown 1 PrivateTag +(0019,"SIEMENS RA GEN",38) US Unknown 1 PrivateTag +(0019,"SIEMENS RA GEN",3a) US Unknown 1 PrivateTag +(0019,"SIEMENS RA GEN",3c) US Unknown 1 PrivateTag +(0019,"SIEMENS RA GEN",3e) US Unknown 1 PrivateTag +(0019,"SIEMENS RA GEN",40) US Unknown 1 PrivateTag +(0019,"SIEMENS RA GEN",42) US Unknown 1 PrivateTag +(0019,"SIEMENS RA GEN",44) SS ImageTransferDelay 1 PrivateTag +(0019,"SIEMENS RA GEN",46) SL InversFlag 1 PrivateTag +(0019,"SIEMENS RA GEN",48) US Unknown 1 PrivateTag +(0019,"SIEMENS RA GEN",4a) US Unknown 1 PrivateTag +(0019,"SIEMENS RA GEN",4c) SS BlankingCircleDiameter 1 PrivateTag +(0019,"SIEMENS RA GEN",50) SL StandDataValid 1 PrivateTag +(0019,"SIEMENS RA GEN",52) SS TableTilt 1 PrivateTag +(0019,"SIEMENS RA GEN",54) SS TableAxisRotation 1 PrivateTag +(0019,"SIEMENS RA GEN",56) SS TableLongitudalPosition 1 PrivateTag +(0019,"SIEMENS RA GEN",58) SS TableSideOffset 1 PrivateTag +(0019,"SIEMENS RA GEN",5a) SS TableIsoCenterHeight 1 PrivateTag +(0019,"SIEMENS RA GEN",5c) UN Unknown 1 PrivateTag +(0019,"SIEMENS RA GEN",5e) SL CollimationDataValid 1 PrivateTag +(0019,"SIEMENS RA GEN",60) SL PeriSequenceNo 1 PrivateTag +(0019,"SIEMENS RA GEN",62) SL PeriTotalScenes 1 PrivateTag +(0019,"SIEMENS RA GEN",64) SL PeriOverlapTop 1 PrivateTag +(0019,"SIEMENS RA GEN",66) SL PeriOverlapBottom 1 PrivateTag +(0019,"SIEMENS RA GEN",68) SL RawImageNumber 1 PrivateTag +(0019,"SIEMENS RA GEN",6a) SL XRayDataValid 1 PrivateTag +(0019,"SIEMENS RA GEN",70) US Unknown 1-n PrivateTag +(0019,"SIEMENS RA GEN",72) US Unknown 1-n PrivateTag +(0019,"SIEMENS RA GEN",74) US Unknown 1-n PrivateTag +(0019,"SIEMENS RA GEN",76) SL FillingAverageFactor 1 PrivateTag +(0019,"SIEMENS RA GEN",78) US Unknown 1-n PrivateTag +(0019,"SIEMENS RA GEN",7a) US Unknown 1-n PrivateTag +(0019,"SIEMENS RA GEN",7c) US Unknown 1-n PrivateTag +(0019,"SIEMENS RA GEN",7e) US Unknown 1-n PrivateTag +(0019,"SIEMENS RA GEN",80) US Unknown 1-n PrivateTag +(0019,"SIEMENS RA GEN",82) US Unknown 1-n PrivateTag +(0019,"SIEMENS RA GEN",84) US Unknown 1-n PrivateTag +(0019,"SIEMENS RA GEN",86) US Unknown 1-n PrivateTag +(0019,"SIEMENS RA GEN",88) US Unknown 1-n PrivateTag +(0019,"SIEMENS RA GEN",8a) US Unknown 1-n PrivateTag +(0019,"SIEMENS RA GEN",8c) US Unknown 1-n PrivateTag +(0019,"SIEMENS RA GEN",8e) US Unknown 1-n PrivateTag +(0019,"SIEMENS RA GEN",92) US Unknown 1-n PrivateTag +(0019,"SIEMENS RA GEN",94) US Unknown 1-n PrivateTag +(0019,"SIEMENS RA GEN",96) US Unknown 1-n PrivateTag +(0019,"SIEMENS RA GEN",98) US Unknown 1-n PrivateTag +(0019,"SIEMENS RA GEN",9a) US Unknown 1-n PrivateTag +(0019,"SIEMENS RA GEN",9c) SL IntensifierLevelCalibrationFactor 1 PrivateTag +(0019,"SIEMENS RA GEN",9e) SL NativeReviewFlag 1 PrivateTag +(0019,"SIEMENS RA GEN",a2) SL SceneNumber 1 PrivateTag +(0019,"SIEMENS RA GEN",a4) SS AcquisitionMode 1 PrivateTag +(0019,"SIEMENS RA GEN",a5) SS AcquisitonFrameRate 1 PrivateTag +(0019,"SIEMENS RA GEN",a6) SL ECGFlag 1 PrivateTag +(0019,"SIEMENS RA GEN",a7) SL AdditionalSceneData 1 PrivateTag +(0019,"SIEMENS RA GEN",a8) SL FileCopyFlag 1 PrivateTag +(0019,"SIEMENS RA GEN",a9) SL PhlebovisionFlag 1 PrivateTag +(0019,"SIEMENS RA GEN",aa) SL Co2Flag 1 PrivateTag +(0019,"SIEMENS RA GEN",ab) SS MaxSpeed 1 PrivateTag +(0019,"SIEMENS RA GEN",ac) SS StepWidth 1 PrivateTag +(0019,"SIEMENS RA GEN",ad) SL DigitalAcquisitionZoom 1 PrivateTag +(0019,"SIEMENS RA GEN",ff) SS Internal 1-n PrivateTag +(0021,"SIEMENS RA GEN",15) SS ImagesInStudy 1 PrivateTag +(0021,"SIEMENS RA GEN",20) SS ScenesInStudy 1 PrivateTag +(0021,"SIEMENS RA GEN",25) SS ImagesInPhotofile 1 PrivateTag +(0021,"SIEMENS RA GEN",27) SS PlaneBImagesExist 1 PrivateTag +(0021,"SIEMENS RA GEN",28) SS NoOf2MBChunks 1 PrivateTag +(0021,"SIEMENS RA GEN",30) SS ImagesInAllScenes 1 PrivateTag +(0021,"SIEMENS RA GEN",40) SS ArchiveSWInternalVersion 1 PrivateTag + +(0011,"SIEMENS RA PLANE A",28) SL FluoroTimerA 1 PrivateTag +(0011,"SIEMENS RA PLANE A",29) SL FluoroSkinDoseA 1 PrivateTag +(0011,"SIEMENS RA PLANE A",2a) SL TotalSkinDoseA 1 PrivateTag +(0011,"SIEMENS RA PLANE A",2b) SL FluoroDoseAreaProductA 1 PrivateTag +(0011,"SIEMENS RA PLANE A",2c) SL TotalDoseAreaProductA 1 PrivateTag +(0019,"SIEMENS RA PLANE A",15) LT OfflineUID 1 PrivateTag +(0019,"SIEMENS RA PLANE A",18) SS Internal 1 PrivateTag +(0019,"SIEMENS RA PLANE A",19) SS Internal 1 PrivateTag +(0019,"SIEMENS RA PLANE A",1a) SS Internal 1 PrivateTag +(0019,"SIEMENS RA PLANE A",1b) SS Internal 1 PrivateTag +(0019,"SIEMENS RA PLANE A",1c) SS Internal 1 PrivateTag +(0019,"SIEMENS RA PLANE A",1d) SS Internal 1 PrivateTag +(0019,"SIEMENS RA PLANE A",1e) SS Internal 1 PrivateTag +(0019,"SIEMENS RA PLANE A",1f) SS Internal 1-n PrivateTag +(0019,"SIEMENS RA PLANE A",20) SS SystemCalibFactorPlaneA 1 PrivateTag +(0019,"SIEMENS RA PLANE A",22) SS XRayParameterSetNo 1 PrivateTag +(0019,"SIEMENS RA PLANE A",24) SS XRaySystem 1 PrivateTag +(0019,"SIEMENS RA PLANE A",26) US Unknown 1 PrivateTag +(0019,"SIEMENS RA PLANE A",28) SS AcquiredDisplayMode 1 PrivateTag +(0019,"SIEMENS RA PLANE A",2a) SS AcquisitionDelay 1 PrivateTag +(0019,"SIEMENS RA PLANE A",2c) US Unknown 1 PrivateTag +(0019,"SIEMENS RA PLANE A",2e) SS MaxFramesLimit 1 PrivateTag +(0019,"SIEMENS RA PLANE A",30) US MaximumFrameSizeNIU 1 PrivateTag +(0019,"SIEMENS RA PLANE A",32) SS SubtractedFilterType 1 PrivateTag +(0019,"SIEMENS RA PLANE A",34) SS FilterFactorNative 1 PrivateTag +(0019,"SIEMENS RA PLANE A",36) SS AnatomicBackgroundFactor 1 PrivateTag +(0019,"SIEMENS RA PLANE A",38) SS WindowUpperLimitNative 1 PrivateTag +(0019,"SIEMENS RA PLANE A",3a) SS WindowLowerLimitNative 1 PrivateTag +(0019,"SIEMENS RA PLANE A",3c) SS WindowBrightnessPhase1 1 PrivateTag +(0019,"SIEMENS RA PLANE A",3e) SS WindowBrightnessPhase2 1 PrivateTag +(0019,"SIEMENS RA PLANE A",40) SS WindowContrastPhase1 1 PrivateTag +(0019,"SIEMENS RA PLANE A",42) SS WindowContrastPhase2 1 PrivateTag +(0019,"SIEMENS RA PLANE A",44) SS FilterFactorSub 1 PrivateTag +(0019,"SIEMENS RA PLANE A",46) SS PeakOpacified 1 PrivateTag +(0019,"SIEMENS RA PLANE A",48) SL MaskFrame 1 PrivateTag +(0019,"SIEMENS RA PLANE A",4a) SL BIHFrame 1 PrivateTag +(0019,"SIEMENS RA PLANE A",4c) SS CentBeamAngulationCaudCran 1 PrivateTag +(0019,"SIEMENS RA PLANE A",4e) SS CentBeamAngulationLRAnterior 1 PrivateTag +(0019,"SIEMENS RA PLANE A",50) SS LongitudinalPosition 1 PrivateTag +(0019,"SIEMENS RA PLANE A",52) SS SideOffset 1 PrivateTag +(0019,"SIEMENS RA PLANE A",54) SS IsoCenterHeight 1 PrivateTag +(0019,"SIEMENS RA PLANE A",56) SS ImageTwist 1 PrivateTag +(0019,"SIEMENS RA PLANE A",58) SS SourceImageDistance 1 PrivateTag +(0019,"SIEMENS RA PLANE A",5a) SS MechanicalMagnificationFactor 1 PrivateTag +(0019,"SIEMENS RA PLANE A",5c) SL CalibrationFlag 1 PrivateTag +(0019,"SIEMENS RA PLANE A",5e) SL CalibrationAngleCranCaud 1 PrivateTag +(0019,"SIEMENS RA PLANE A",60) SL CalibrationAngleRAOLAO 1 PrivateTag +(0019,"SIEMENS RA PLANE A",62) SL CalibrationTableToFloorDist 1 PrivateTag +(0019,"SIEMENS RA PLANE A",64) SL CalibrationIsocenterToFloorDist 1 PrivateTag +(0019,"SIEMENS RA PLANE A",66) SL CalibrationIsocenterToSourceDist 1 PrivateTag +(0019,"SIEMENS RA PLANE A",68) SL CalibrationSourceToII 1 PrivateTag +(0019,"SIEMENS RA PLANE A",6a) SL CalibrationIIZoom 1 PrivateTag +(0019,"SIEMENS RA PLANE A",6c) SL CalibrationIIField 1 PrivateTag +(0019,"SIEMENS RA PLANE A",6e) SL CalibrationFactor 1 PrivateTag +(0019,"SIEMENS RA PLANE A",70) SL CalibrationObjectToImageDistance 1 PrivateTag +(0019,"SIEMENS RA PLANE A",72) SL CalibrationSystemFactor 1-n PrivateTag +(0019,"SIEMENS RA PLANE A",74) SL CalibrationSystemCorrection 1-n PrivateTag +(0019,"SIEMENS RA PLANE A",76) SL CalibrationSystemIIFormats 1-n PrivateTag +(0019,"SIEMENS RA PLANE A",78) SL CalibrationGantryDataValid 1 PrivateTag +(0019,"SIEMENS RA PLANE A",7a) SS CollimatorSquareBreadth 1 PrivateTag +(0019,"SIEMENS RA PLANE A",7c) SS CollimatorSquareHeight 1 PrivateTag +(0019,"SIEMENS RA PLANE A",7e) SS CollimatorSquareDiameter 1 PrivateTag +(0019,"SIEMENS RA PLANE A",80) SS CollimaterFingerTurnAngle 1 PrivateTag +(0019,"SIEMENS RA PLANE A",82) SS CollimaterFingerPosition 1 PrivateTag +(0019,"SIEMENS RA PLANE A",84) SS CollimaterDiaphragmTurnAngle 1 PrivateTag +(0019,"SIEMENS RA PLANE A",86) SS CollimaterDiaphragmPosition1 1 PrivateTag +(0019,"SIEMENS RA PLANE A",88) SS CollimaterDiaphragmPosition2 1 PrivateTag +(0019,"SIEMENS RA PLANE A",8a) SS CollimaterDiaphragmMode 1 PrivateTag +(0019,"SIEMENS RA PLANE A",8c) SS CollimaterBeamLimitBreadth 1 PrivateTag +(0019,"SIEMENS RA PLANE A",8e) SS CollimaterBeamLimitHeight 1 PrivateTag +(0019,"SIEMENS RA PLANE A",90) SS CollimaterBeamLimitDiameter 1 PrivateTag +(0019,"SIEMENS RA PLANE A",92) SS X-RayControlMOde 1 PrivateTag +(0019,"SIEMENS RA PLANE A",94) SS X-RaySystem 1 PrivateTag +(0019,"SIEMENS RA PLANE A",96) SS FocalSpot 1 PrivateTag +(0019,"SIEMENS RA PLANE A",98) SS ExposureControl 1 PrivateTag +(0019,"SIEMENS RA PLANE A",9a) SL XRayVoltage 1 PrivateTag +(0019,"SIEMENS RA PLANE A",9c) SL XRayCurrent 1 PrivateTag +(0019,"SIEMENS RA PLANE A",9e) SL XRayCurrentTimeProduct 1 PrivateTag +(0019,"SIEMENS RA PLANE A",a0) SL XRayPulseTime 1 PrivateTag +(0019,"SIEMENS RA PLANE A",a2) SL XRaySceneTimeFluoroClock 1 PrivateTag +(0019,"SIEMENS RA PLANE A",a4) SS MaximumPulseRate 1 PrivateTag +(0019,"SIEMENS RA PLANE A",a6) SS PulsesPerScene 1 PrivateTag +(0019,"SIEMENS RA PLANE A",a8) SL DoseAreaProductOfScene 1 PrivateTag +(0019,"SIEMENS RA PLANE A",aa) SS Dose 1 PrivateTag +(0019,"SIEMENS RA PLANE A",ac) SS DoseRate 1 PrivateTag +(0019,"SIEMENS RA PLANE A",ae) SL IIToCoverDistance 1 PrivateTag +(0019,"SIEMENS RA PLANE A",b0) SS LastFramePhase1 1 PrivateTag +(0019,"SIEMENS RA PLANE A",b1) SS FrameRatePhase1 1 PrivateTag +(0019,"SIEMENS RA PLANE A",b2) SS LastFramePhase2 1 PrivateTag +(0019,"SIEMENS RA PLANE A",b3) SS FrameRatePhase2 1 PrivateTag +(0019,"SIEMENS RA PLANE A",b4) SS LastFramePhase3 1 PrivateTag +(0019,"SIEMENS RA PLANE A",b5) SS FrameRatePhase3 1 PrivateTag +(0019,"SIEMENS RA PLANE A",b6) SS LastFramePhase4 1 PrivateTag +(0019,"SIEMENS RA PLANE A",b7) SS FrameRatePhase4 1 PrivateTag +(0019,"SIEMENS RA PLANE A",b8) SS GammaOfNativeImage 1 PrivateTag +(0019,"SIEMENS RA PLANE A",b9) SS GammaOfTVSystem 1 PrivateTag +(0019,"SIEMENS RA PLANE A",bb) SL PixelshiftX 1 PrivateTag +(0019,"SIEMENS RA PLANE A",bc) SL PixelshiftY 1 PrivateTag +(0019,"SIEMENS RA PLANE A",bd) SL MaskAverageFactor 1 PrivateTag +(0019,"SIEMENS RA PLANE A",be) SL BlankingCircleFlag 1 PrivateTag +(0019,"SIEMENS RA PLANE A",bf) SL CircleRowStart 1 PrivateTag +(0019,"SIEMENS RA PLANE A",c0) SL CircleRowEnd 1 PrivateTag +(0019,"SIEMENS RA PLANE A",c1) SL CircleColumnStart 1 PrivateTag +(0019,"SIEMENS RA PLANE A",c2) SL CircleColumnEnd 1 PrivateTag +(0019,"SIEMENS RA PLANE A",c3) SL CircleDiameter 1 PrivateTag +(0019,"SIEMENS RA PLANE A",c4) SL RectangularCollimaterFlag 1 PrivateTag +(0019,"SIEMENS RA PLANE A",c5) SL RectangleRowStart 1 PrivateTag +(0019,"SIEMENS RA PLANE A",c6) SL RectangleRowEnd 1 PrivateTag +(0019,"SIEMENS RA PLANE A",c7) SL RectangleColumnStart 1 PrivateTag +(0019,"SIEMENS RA PLANE A",c8) SL RectangleColumnEnd 1 PrivateTag +(0019,"SIEMENS RA PLANE A",c9) SL RectangleAngulation 1 PrivateTag +(0019,"SIEMENS RA PLANE A",ca) SL IrisCollimatorFlag 1 PrivateTag +(0019,"SIEMENS RA PLANE A",cb) SL IrisRowStart 1 PrivateTag +(0019,"SIEMENS RA PLANE A",cc) SL IrisRowEnd 1 PrivateTag +(0019,"SIEMENS RA PLANE A",cd) SL IrisColumnStart 1 PrivateTag +(0019,"SIEMENS RA PLANE A",ce) SL IrisColumnEnd 1 PrivateTag +(0019,"SIEMENS RA PLANE A",cf) SL IrisAngulation 1 PrivateTag +(0019,"SIEMENS RA PLANE A",d1) SS NumberOfFramesPlane 1 PrivateTag +(0019,"SIEMENS RA PLANE A",d2) SS Internal 1 PrivateTag +(0019,"SIEMENS RA PLANE A",d3) SS Internal 1 PrivateTag +(0019,"SIEMENS RA PLANE A",d4) SS Internal 1 PrivateTag +(0019,"SIEMENS RA PLANE A",d5) SS Internal 1 PrivateTag +(0019,"SIEMENS RA PLANE A",d6) SS Internal 1-n PrivateTag +(0019,"SIEMENS RA PLANE A",d7) SS Internal 1-n PrivateTag +(0019,"SIEMENS RA PLANE A",d8) SS Internal 1 PrivateTag +(0019,"SIEMENS RA PLANE A",d9) SS Internal 1 PrivateTag +(0019,"SIEMENS RA PLANE A",da) SS Internal 1 PrivateTag +(0019,"SIEMENS RA PLANE A",db) SS Internal 1 PrivateTag +(0019,"SIEMENS RA PLANE A",dc) SS Internal 1 PrivateTag +(0019,"SIEMENS RA PLANE A",dd) SL AnatomicBackground 1 PrivateTag +(0019,"SIEMENS RA PLANE A",de) SL AutoWindowBase 1-n PrivateTag +(0019,"SIEMENS RA PLANE A",df) SS Internal 1 PrivateTag +(0019,"SIEMENS RA PLANE A",e0) SL Internal 1 PrivateTag + +(0011,"SIEMENS RA PLANE B",28) SL FluoroTimerB 1 PrivateTag +(0011,"SIEMENS RA PLANE B",29) SL FluoroSkinDoseB 1 PrivateTag +(0011,"SIEMENS RA PLANE B",2a) SL TotalSkinDoseB 1 PrivateTag +(0011,"SIEMENS RA PLANE B",2b) SL FluoroDoseAreaProductB 1 PrivateTag +(0011,"SIEMENS RA PLANE B",2c) SL TotalDoseAreaProductB 1 PrivateTag +(0019,"SIEMENS RA PLANE B",18) SS Internal 1 PrivateTag +(0019,"SIEMENS RA PLANE B",19) SS Internal 1 PrivateTag +(0019,"SIEMENS RA PLANE B",1a) SS Internal 1 PrivateTag +(0019,"SIEMENS RA PLANE B",1b) SS Internal 1 PrivateTag +(0019,"SIEMENS RA PLANE B",1c) SS Internal 1 PrivateTag +(0019,"SIEMENS RA PLANE B",1d) SS Internal 1 PrivateTag +(0019,"SIEMENS RA PLANE B",1e) SS Internal 1 PrivateTag +(0019,"SIEMENS RA PLANE B",1f) SS Internal 1 PrivateTag +(0019,"SIEMENS RA PLANE B",20) SL SystemCalibFactorPlaneB 1-n PrivateTag +(0019,"SIEMENS RA PLANE B",22) US Unknown 1 PrivateTag +(0019,"SIEMENS RA PLANE B",24) US Unknown 1 PrivateTag +(0019,"SIEMENS RA PLANE B",26) US Unknown 1 PrivateTag +(0019,"SIEMENS RA PLANE B",28) US Unknown 1 PrivateTag +(0019,"SIEMENS RA PLANE B",2a) US Unknown 1 PrivateTag +(0019,"SIEMENS RA PLANE B",2c) US Unknown 1 PrivateTag +(0019,"SIEMENS RA PLANE B",2e) US Unknown 1 PrivateTag +(0019,"SIEMENS RA PLANE B",30) US Unknown 1 PrivateTag +(0019,"SIEMENS RA PLANE B",32) US Unknown 1 PrivateTag +(0019,"SIEMENS RA PLANE B",34) US Unknown 1 PrivateTag +(0019,"SIEMENS RA PLANE B",36) US Unknown 1 PrivateTag +(0019,"SIEMENS RA PLANE B",38) US Unknown 1 PrivateTag +(0019,"SIEMENS RA PLANE B",3a) US Unknown 1 PrivateTag +(0019,"SIEMENS RA PLANE B",3c) US Unknown 1 PrivateTag +(0019,"SIEMENS RA PLANE B",3e) US Unknown 1 PrivateTag +(0019,"SIEMENS RA PLANE B",40) US Unknown 1 PrivateTag +(0019,"SIEMENS RA PLANE B",42) US Unknown 1 PrivateTag +(0019,"SIEMENS RA PLANE B",44) US Unknown 1 PrivateTag +(0019,"SIEMENS RA PLANE B",46) US Unknown 1 PrivateTag +(0019,"SIEMENS RA PLANE B",48) US Unknown 1 PrivateTag +(0019,"SIEMENS RA PLANE B",4a) US Unknown 1-n PrivateTag +(0019,"SIEMENS RA PLANE B",4c) US Unknown 1-n PrivateTag +(0019,"SIEMENS RA PLANE B",4e) US Unknown 1-n PrivateTag +(0019,"SIEMENS RA PLANE B",50) US Unknown 1 PrivateTag +(0019,"SIEMENS RA PLANE B",52) US Unknown 1 PrivateTag +(0019,"SIEMENS RA PLANE B",54) US Unknown 1 PrivateTag +(0019,"SIEMENS RA PLANE B",56) US Unknown 1 PrivateTag +(0019,"SIEMENS RA PLANE B",58) US Unknown 1 PrivateTag +(0019,"SIEMENS RA PLANE B",5a) US Unknown 1 PrivateTag +(0019,"SIEMENS RA PLANE B",5c) US Unknown 1-n PrivateTag +(0019,"SIEMENS RA PLANE B",5e) US Unknown 1-n PrivateTag +(0019,"SIEMENS RA PLANE B",60) US Unknown 1-n PrivateTag +(0019,"SIEMENS RA PLANE B",62) US Unknown 1-n PrivateTag +(0019,"SIEMENS RA PLANE B",64) US Unknown 1-n PrivateTag +(0019,"SIEMENS RA PLANE B",66) US Unknown 1-n PrivateTag +(0019,"SIEMENS RA PLANE B",68) US Unknown 1-n PrivateTag +(0019,"SIEMENS RA PLANE B",6a) US Unknown 1-n PrivateTag +(0019,"SIEMENS RA PLANE B",6c) US Unknown 1-n PrivateTag +(0019,"SIEMENS RA PLANE B",6e) US Unknown 1-n PrivateTag +(0019,"SIEMENS RA PLANE B",70) US Unknown 1-n PrivateTag +(0019,"SIEMENS RA PLANE B",72) UN Unknown 1 PrivateTag +(0019,"SIEMENS RA PLANE B",74) UN Unknown 1 PrivateTag +(0019,"SIEMENS RA PLANE B",76) UN Unknown 1 PrivateTag +(0019,"SIEMENS RA PLANE B",78) US Unknown 1-n PrivateTag +(0019,"SIEMENS RA PLANE B",7a) US Unknown 1 PrivateTag +(0019,"SIEMENS RA PLANE B",7c) US Unknown 1 PrivateTag +(0019,"SIEMENS RA PLANE B",7e) US Unknown 1 PrivateTag +(0019,"SIEMENS RA PLANE B",80) US Unknown 1 PrivateTag +(0019,"SIEMENS RA PLANE B",82) US Unknown 1 PrivateTag +(0019,"SIEMENS RA PLANE B",84) US Unknown 1 PrivateTag +(0019,"SIEMENS RA PLANE B",86) US Unknown 1 PrivateTag +(0019,"SIEMENS RA PLANE B",88) US Unknown 1 PrivateTag +(0019,"SIEMENS RA PLANE B",8a) US Unknown 1 PrivateTag +(0019,"SIEMENS RA PLANE B",8c) US Unknown 1 PrivateTag +(0019,"SIEMENS RA PLANE B",8e) US Unknown 1 PrivateTag +(0019,"SIEMENS RA PLANE B",90) US Unknown 1 PrivateTag +(0019,"SIEMENS RA PLANE B",92) US Unknown 1 PrivateTag +(0019,"SIEMENS RA PLANE B",94) US Unknown 1 PrivateTag +(0019,"SIEMENS RA PLANE B",96) US Unknown 1 PrivateTag +(0019,"SIEMENS RA PLANE B",98) US Unknown 1 PrivateTag +(0019,"SIEMENS RA PLANE B",9a) US Unknown 1-n PrivateTag +(0019,"SIEMENS RA PLANE B",9c) US Unknown 1-n PrivateTag +(0019,"SIEMENS RA PLANE B",9e) US Unknown 1-n PrivateTag +(0019,"SIEMENS RA PLANE B",a0) US Unknown 1-n PrivateTag +(0019,"SIEMENS RA PLANE B",a2) US Unknown 1-n PrivateTag +(0019,"SIEMENS RA PLANE B",a4) US Unknown 1 PrivateTag +(0019,"SIEMENS RA PLANE B",a6) US Unknown 1 PrivateTag +(0019,"SIEMENS RA PLANE B",a8) US Unknown 1-n PrivateTag +(0019,"SIEMENS RA PLANE B",aa) US Unknown 1 PrivateTag +(0019,"SIEMENS RA PLANE B",ac) US Unknown 1 PrivateTag + +(0011,"SIEMENS RIS",10) LT PatientUID 1 PrivateTag +(0011,"SIEMENS RIS",11) LT PatientID 1 PrivateTag +(0011,"SIEMENS RIS",20) DA PatientRegistrationDate 1 PrivateTag +(0011,"SIEMENS RIS",21) TM PatientRegistrationTime 1 PrivateTag +(0011,"SIEMENS RIS",30) LT PatientnameRIS 1 PrivateTag +(0011,"SIEMENS RIS",31) LT PatientprenameRIS 1 PrivateTag +(0011,"SIEMENS RIS",40) LT PatientHospitalStatus 1 PrivateTag +(0011,"SIEMENS RIS",41) LT MedicalAlerts 1 PrivateTag +(0011,"SIEMENS RIS",42) LT ContrastAllergies 1 PrivateTag +(0031,"SIEMENS RIS",10) LT RequestUID 1 PrivateTag +(0031,"SIEMENS RIS",45) LT RequestingPhysician 1 PrivateTag +(0031,"SIEMENS RIS",50) LT RequestedPhysician 1 PrivateTag +(0033,"SIEMENS RIS",10) LT PatientStudyUID 1 PrivateTag + +(0021,"SIEMENS SMS-AX ACQ 1.0",00) US AcquisitionType 1 PrivateTag +(0021,"SIEMENS SMS-AX ACQ 1.0",01) US AcquisitionMode 1 PrivateTag +(0021,"SIEMENS SMS-AX ACQ 1.0",02) US FootswitchIndex 1 PrivateTag +(0021,"SIEMENS SMS-AX ACQ 1.0",03) US AcquisitionRoom 1 PrivateTag +(0021,"SIEMENS SMS-AX ACQ 1.0",04) SL CurrentTimeProduct 1 PrivateTag +(0021,"SIEMENS SMS-AX ACQ 1.0",05) SL Dose 1 PrivateTag +(0021,"SIEMENS SMS-AX ACQ 1.0",06) SL SkinDosePercent 1 PrivateTag +(0021,"SIEMENS SMS-AX ACQ 1.0",07) SL SkinDoseAccumulation 1 PrivateTag +(0021,"SIEMENS SMS-AX ACQ 1.0",08) SL SkinDoseRate 1 PrivateTag +(0021,"SIEMENS SMS-AX ACQ 1.0",0A) UL CopperFilter 1 PrivateTag +(0021,"SIEMENS SMS-AX ACQ 1.0",0B) US MeasuringField 1 PrivateTag +(0021,"SIEMENS SMS-AX ACQ 1.0",0C) SS PostBlankingCircle 3 PrivateTag +(0021,"SIEMENS SMS-AX ACQ 1.0",0D) SS DynaAngles 2-2n PrivateTag +(0021,"SIEMENS SMS-AX ACQ 1.0",0E) SS TotalSteps 1 PrivateTag +(0021,"SIEMENS SMS-AX ACQ 1.0",0F) SL DynaXRayInfo 3-3n PrivateTag +(0021,"SIEMENS SMS-AX ACQ 1.0",10) US ModalityLUTInputGamma 1 PrivateTag +(0021,"SIEMENS SMS-AX ACQ 1.0",11) US ModalityLUTOutputGamma 1 PrivateTag +(0021,"SIEMENS SMS-AX ACQ 1.0",12) OB SH_STPAR 1-n PrivateTag +(0021,"SIEMENS SMS-AX ACQ 1.0",13) US AcquisitionZoom 1 PrivateTag +(0021,"SIEMENS SMS-AX ACQ 1.0",14) SS DynaAngulationStepWidth 1 PrivateTag +(0021,"SIEMENS SMS-AX ACQ 1.0",15) US Harmonization 1 PrivateTag +(0021,"SIEMENS SMS-AX ACQ 1.0",16) US DRSingleFlag 1 PrivateTag +(0021,"SIEMENS SMS-AX ACQ 1.0",17) SL SourceToIsocenter 1 PrivateTag +(0021,"SIEMENS SMS-AX ACQ 1.0",18) US PressureData 1 PrivateTag +(0021,"SIEMENS SMS-AX ACQ 1.0",19) SL ECGIndexArray 1 PrivateTag +(0021,"SIEMENS SMS-AX ACQ 1.0",1A) US FDFlag 1 PrivateTag +(0021,"SIEMENS SMS-AX ACQ 1.0",1B) OB SH_ZOOM 1 PrivateTag +(0021,"SIEMENS SMS-AX ACQ 1.0",1C) OB SH_COLPAR 1 PrivateTag +(0021,"SIEMENS SMS-AX ACQ 1.0",1D) US K_Factor 1 PrivateTag +(0021,"SIEMENS SMS-AX ACQ 1.0",1E) US EVE 8 PrivateTag +(0021,"SIEMENS SMS-AX ACQ 1.0",1F) SL TotalSceneTime 1 PrivateTag +(0021,"SIEMENS SMS-AX ACQ 1.0",20) US RestoreFlag 1 PrivateTag +(0021,"SIEMENS SMS-AX ACQ 1.0",21) US StandMovementFlag 1 PrivateTag +(0021,"SIEMENS SMS-AX ACQ 1.0",22) US FDRows 1 PrivateTag +(0021,"SIEMENS SMS-AX ACQ 1.0",23) US FDColumns 1 PrivateTag +(0021,"SIEMENS SMS-AX ACQ 1.0",24) US TableMovementFlag 1 PrivateTag +(0021,"SIEMENS SMS-AX ACQ 1.0",25) LO OriginalOrganProgramName 1 PrivateTag +(0021,"SIEMENS SMS-AX ACQ 1.0",26) DS CrispyXPIFilter 1 PrivateTag + +(0025,"SIEMENS SMS-AX ORIGINAL IMAGE INFO 1.0",00) US ViewNative 1 PrivateTag +(0025,"SIEMENS SMS-AX ORIGINAL IMAGE INFO 1.0",01) US OriginalSeriesNumber 1 PrivateTag +(0025,"SIEMENS SMS-AX ORIGINAL IMAGE INFO 1.0",02) US OriginalImageNumber 1 PrivateTag +(0025,"SIEMENS SMS-AX ORIGINAL IMAGE INFO 1.0",03) US WinCenter 1 PrivateTag +(0025,"SIEMENS SMS-AX ORIGINAL IMAGE INFO 1.0",04) US WinWidth 1 PrivateTag +(0025,"SIEMENS SMS-AX ORIGINAL IMAGE INFO 1.0",05) US WinBrightness 1 PrivateTag +(0025,"SIEMENS SMS-AX ORIGINAL IMAGE INFO 1.0",06) US WinContrast 1 PrivateTag +(0025,"SIEMENS SMS-AX ORIGINAL IMAGE INFO 1.0",07) US OriginalFrameNumber 1 PrivateTag +(0025,"SIEMENS SMS-AX ORIGINAL IMAGE INFO 1.0",08) US OriginalMaskFrameNumber 1 PrivateTag +(0025,"SIEMENS SMS-AX ORIGINAL IMAGE INFO 1.0",09) US Opac 1 PrivateTag +(0025,"SIEMENS SMS-AX ORIGINAL IMAGE INFO 1.0",0A) US OriginalNumberOfFrames 1 PrivateTag +(0025,"SIEMENS SMS-AX ORIGINAL IMAGE INFO 1.0",0B) DS OriginalSceneDuration 1 PrivateTag +(0025,"SIEMENS SMS-AX ORIGINAL IMAGE INFO 1.0",0C) LO IdentifierLOID 1 PrivateTag +(0025,"SIEMENS SMS-AX ORIGINAL IMAGE INFO 1.0",0D) SS OriginalSceneVFRInfo 1-n PrivateTag +(0025,"SIEMENS SMS-AX ORIGINAL IMAGE INFO 1.0",0E) SS OriginalFrameECGPosition 1 PrivateTag +(0025,"SIEMENS SMS-AX ORIGINAL IMAGE INFO 1.0",0F) SS OriginalECG1stFrameOffset_retired 1 PrivateTag +(0025,"SIEMENS SMS-AX ORIGINAL IMAGE INFO 1.0",10) SS ZoomFlag 1 PrivateTag +(0025,"SIEMENS SMS-AX ORIGINAL IMAGE INFO 1.0",11) US Flex 1 PrivateTag +(0025,"SIEMENS SMS-AX ORIGINAL IMAGE INFO 1.0",12) US NumberOfMaskFrames 1 PrivateTag +(0025,"SIEMENS SMS-AX ORIGINAL IMAGE INFO 1.0",13) US NumberOfFillFrames 1 PrivateTag +(0025,"SIEMENS SMS-AX ORIGINAL IMAGE INFO 1.0",14) US SeriesNumber 1 PrivateTag +(0025,"SIEMENS SMS-AX ORIGINAL IMAGE INFO 1.0",15) IS ImageNumber 1 PrivateTag + +(0023,"SIEMENS SMS-AX QUANT 1.0",00) DS HorizontalCalibrationPixelSize 2 PrivateTag +(0023,"SIEMENS SMS-AX QUANT 1.0",01) DS VerticalCalibrationPixelSize 2 PrivateTag +(0023,"SIEMENS SMS-AX QUANT 1.0",02) LO CalibrationObject 1 PrivateTag +(0023,"SIEMENS SMS-AX QUANT 1.0",03) DS CalibrationObjectSize 1 PrivateTag +(0023,"SIEMENS SMS-AX QUANT 1.0",04) LO CalibrationMethod 1 PrivateTag +(0023,"SIEMENS SMS-AX QUANT 1.0",05) ST Filename 1 PrivateTag +(0023,"SIEMENS SMS-AX QUANT 1.0",06) IS FrameNumber 1 PrivateTag +(0023,"SIEMENS SMS-AX QUANT 1.0",07) IS CalibrationFactorMultiplicity 2 PrivateTag +(0023,"SIEMENS SMS-AX QUANT 1.0",08) IS CalibrationTODValue 1 PrivateTag + +(0019,"SIEMENS SMS-AX VIEW 1.0",00) US ReviewMode 1 PrivateTag +(0019,"SIEMENS SMS-AX VIEW 1.0",01) US AnatomicalBackgroundPercent 1 PrivateTag +(0019,"SIEMENS SMS-AX VIEW 1.0",02) US NumberOfPhases 1 PrivateTag +(0019,"SIEMENS SMS-AX VIEW 1.0",03) US ApplyAnatomicalBackground 1 PrivateTag +(0019,"SIEMENS SMS-AX VIEW 1.0",04) SS PixelShiftArray 4-4n PrivateTag +(0019,"SIEMENS SMS-AX VIEW 1.0",05) US Brightness 1 PrivateTag +(0019,"SIEMENS SMS-AX VIEW 1.0",06) US Contrast 1 PrivateTag +(0019,"SIEMENS SMS-AX VIEW 1.0",07) US Enabled 1 PrivateTag +(0019,"SIEMENS SMS-AX VIEW 1.0",08) US NativeEdgeEnhancementPercentGain 1 PrivateTag +(0019,"SIEMENS SMS-AX VIEW 1.0",09) SS NativeEdgeEnhancementLUTIndex 1 PrivateTag +(0019,"SIEMENS SMS-AX VIEW 1.0",0A) SS NativeEdgeEnhancementKernelSize 1 PrivateTag +(0019,"SIEMENS SMS-AX VIEW 1.0",0B) US SubtrEdgeEnhancementPercentGain 1 PrivateTag +(0019,"SIEMENS SMS-AX VIEW 1.0",0C) SS SubtrEdgeEnhancementLUTIndex 1 PrivateTag +(0019,"SIEMENS SMS-AX VIEW 1.0",0D) SS SubtrEdgeEnhancementKernelSize 1 PrivateTag +(0019,"SIEMENS SMS-AX VIEW 1.0",0E) US FadePercent 1 PrivateTag +(0019,"SIEMENS SMS-AX VIEW 1.0",0F) US FlippedBeforeLateralityApplied 1 PrivateTag +(0019,"SIEMENS SMS-AX VIEW 1.0",10) US ApplyFade 1 PrivateTag +(0019,"SIEMENS SMS-AX VIEW 1.0",12) US Zoom 1 PrivateTag +(0019,"SIEMENS SMS-AX VIEW 1.0",13) SS PanX 1 PrivateTag +(0019,"SIEMENS SMS-AX VIEW 1.0",14) SS PanY 1 PrivateTag +(0019,"SIEMENS SMS-AX VIEW 1.0",15) SS NativeEdgeEnhancementAdvPercGain 1 PrivateTag +(0019,"SIEMENS SMS-AX VIEW 1.0",16) SS SubtrEdgeEnhancementAdvPercGain 1 PrivateTag +(0019,"SIEMENS SMS-AX VIEW 1.0",17) US InvertFlag 1 PrivateTag +(0019,"SIEMENS SMS-AX VIEW 1.0",1A) OB Quant1KOverlay 1 PrivateTag +(0019,"SIEMENS SMS-AX VIEW 1.0",1B) US OriginalResolution 1 PrivateTag +(0019,"SIEMENS SMS-AX VIEW 1.0",1C) DS AutoWindowCenter 1 PrivateTag +(0019,"SIEMENS SMS-AX VIEW 1.0",1D) DS AutoWindowWidth 1 PrivateTag + +(0009,"SIENET",01) US SIENETCommandField 1 PrivateTag +(0009,"SIENET",14) LT ReceiverPLA 1 PrivateTag +(0009,"SIENET",16) US TransferPriority 1 PrivateTag +(0009,"SIENET",29) LT ActualUser 1 PrivateTag +(0095,"SIENET",01) LT ExaminationFolderID 1 PrivateTag +(0095,"SIENET",04) UL FolderReportedStatus 1 PrivateTag +(0095,"SIENET",05) LT FolderReportingRadiologist 1 PrivateTag +(0095,"SIENET",07) LT SIENETISAPLA 1 PrivateTag +(0099,"SIENET",02) UL DataObjectAttributes 1 PrivateTag + +(0009,"SPI RELEASE 1",10) LT Comments 1 PrivateTag +(0009,"SPI RELEASE 1",15) LO SPIImageUID 1 PrivateTag +(0009,"SPI RELEASE 1",40) US DataObjectType 1 PrivateTag +(0009,"SPI RELEASE 1",41) LO DataObjectSubtype 1 PrivateTag +(0011,"SPI RELEASE 1",10) LO Organ 1 PrivateTag +(0011,"SPI RELEASE 1",15) LO AllergyIndication 1 PrivateTag +(0011,"SPI RELEASE 1",20) LO Pregnancy 1 PrivateTag +(0029,"SPI RELEASE 1",60) LT CompressionAlgorithm 1 PrivateTag + +(0009,"SPI Release 1",10) LT Comments 1 PrivateTag +(0009,"SPI Release 1",15) LO SPIImageUID 1 PrivateTag +(0009,"SPI Release 1",40) US DataObjectType 1 PrivateTag +(0009,"SPI Release 1",41) LO DataObjectSubtype 1 PrivateTag +(0011,"SPI Release 1",10) LO Organ 1 PrivateTag +(0011,"SPI Release 1",15) LO AllergyIndication 1 PrivateTag +(0011,"SPI Release 1",20) LO Pregnancy 1 PrivateTag +(0029,"SPI Release 1",60) LT CompressionAlgorithm 1 PrivateTag + +(0009,"SPI",10) LO Comments 1 PrivateTag +(0009,"SPI",15) LO SPIImageUID 1 PrivateTag +(0009,"SPI",40) US DataObjectType 1 PrivateTag +(0009,"SPI",41) LT DataObjectSubtype 1 PrivateTag +(0011,"SPI",10) LT Organ 1 PrivateTag +(0011,"SPI",15) LT AllergyIndication 1 PrivateTag +(0011,"SPI",20) LT Pregnancy 1 PrivateTag +(0029,"SPI",60) LT CompressionAlgorithm 1 PrivateTag + +(0011,"SPI RELEASE 1",10) LO Organ 1 PrivateTag +(0011,"SPI RELEASE 1",15) LO AllergyIndication 1 PrivateTag +(0011,"SPI RELEASE 1",20) LO Pregnancy 1 PrivateTag + +(0009,"SPI-P Release 1",00) LT DataObjectRecognitionCode 1 PrivateTag +(0009,"SPI-P Release 1",04) LO ImageDataConsistence 1 PrivateTag +(0009,"SPI-P Release 1",08) US Unknown 1 PrivateTag +(0009,"SPI-P Release 1",12) LO Unknown 1 PrivateTag +(0009,"SPI-P Release 1",15) LO UniqueIdentifier 1 PrivateTag +(0009,"SPI-P Release 1",16) LO Unknown 1 PrivateTag +(0009,"SPI-P Release 1",18) LO Unknown 1 PrivateTag +(0009,"SPI-P Release 1",21) LT Unknown 1 PrivateTag +(0009,"SPI-P Release 1",31) LT PACSUniqueIdentifier 1 PrivateTag +(0009,"SPI-P Release 1",34) LT ClusterUniqueIdentifier 1 PrivateTag +(0009,"SPI-P Release 1",38) LT SystemUniqueIdentifier 1 PrivateTag +(0009,"SPI-P Release 1",39) LT Unknown 1 PrivateTag +(0009,"SPI-P Release 1",51) LT StudyUniqueIdentifier 1 PrivateTag +(0009,"SPI-P Release 1",61) LT SeriesUniqueIdentifier 1 PrivateTag +(0009,"SPI-P Release 1",91) LT Unknown 1 PrivateTag +(0009,"SPI-P Release 1",f2) LT Unknown 1 PrivateTag +(0009,"SPI-P Release 1",f3) UN Unknown 1 PrivateTag +(0009,"SPI-P Release 1",f4) LT Unknown 1 PrivateTag +(0009,"SPI-P Release 1",f5) UN Unknown 1 PrivateTag +(0009,"SPI-P Release 1",f7) LT Unknown 1 PrivateTag +(0011,"SPI-P Release 1",10) LT PatientEntryID 1 PrivateTag +(0011,"SPI-P Release 1",21) UN Unknown 1 PrivateTag +(0011,"SPI-P Release 1",22) UN Unknown 1 PrivateTag +(0011,"SPI-P Release 1",31) UN Unknown 1 PrivateTag +(0011,"SPI-P Release 1",32) UN Unknown 1 PrivateTag +(0019,"SPI-P Release 1",00) UN Unknown 1 PrivateTag +(0019,"SPI-P Release 1",01) UN Unknown 1 PrivateTag +(0019,"SPI-P Release 1",02) UN Unknown 1 PrivateTag +(0019,"SPI-P Release 1",10) US MainsFrequency 1 PrivateTag +(0019,"SPI-P Release 1",25) LT OriginalPixelDataQuality 1-n PrivateTag +(0019,"SPI-P Release 1",30) US ECGTriggering 1 PrivateTag +(0019,"SPI-P Release 1",31) UN ECG1Offset 1 PrivateTag +(0019,"SPI-P Release 1",32) UN ECG2Offset1 1 PrivateTag +(0019,"SPI-P Release 1",33) UN ECG2Offset2 1 PrivateTag +(0019,"SPI-P Release 1",50) US VideoScanMode 1 PrivateTag +(0019,"SPI-P Release 1",51) US VideoLineRate 1 PrivateTag +(0019,"SPI-P Release 1",60) US XrayTechnique 1 PrivateTag +(0019,"SPI-P Release 1",61) DS ImageIdentifierFromat 1 PrivateTag +(0019,"SPI-P Release 1",62) US IrisDiaphragm 1 PrivateTag +(0019,"SPI-P Release 1",63) CS Filter 1 PrivateTag +(0019,"SPI-P Release 1",64) CS CineParallel 1 PrivateTag +(0019,"SPI-P Release 1",65) CS CineMaster 1 PrivateTag +(0019,"SPI-P Release 1",70) US ExposureChannel 1 PrivateTag +(0019,"SPI-P Release 1",71) UN ExposureChannelFirstImage 1 PrivateTag +(0019,"SPI-P Release 1",72) US ProcessingChannel 1 PrivateTag +(0019,"SPI-P Release 1",80) DS AcquisitionDelay 1 PrivateTag +(0019,"SPI-P Release 1",81) UN RelativeImageTime 1 PrivateTag +(0019,"SPI-P Release 1",90) CS VideoWhiteCompression 1 PrivateTag +(0019,"SPI-P Release 1",a0) US Angulation 1 PrivateTag +(0019,"SPI-P Release 1",a1) US Rotation 1 PrivateTag +(0021,"SPI-P Release 1",12) LT SeriesUniqueIdentifier 1 PrivateTag +(0021,"SPI-P Release 1",14) LT Unknown 1 PrivateTag +(0029,"SPI-P Release 1",00) DS Unknown 4 PrivateTag +(0029,"SPI-P Release 1",20) DS PixelAspectRatio 1 PrivateTag +(0029,"SPI-P Release 1",25) LO ProcessedPixelDataQuality 1-n PrivateTag +(0029,"SPI-P Release 1",30) LT Unknown 1 PrivateTag +(0029,"SPI-P Release 1",38) US Unknown 1 PrivateTag +(0029,"SPI-P Release 1",60) LT Unknown 1 PrivateTag +(0029,"SPI-P Release 1",61) LT Unknown 1 PrivateTag +(0029,"SPI-P Release 1",67) LT Unknown 1 PrivateTag +(0029,"SPI-P Release 1",70) LT WindowID 1 PrivateTag +(0029,"SPI-P Release 1",71) CS VideoInvertSubtracted 1 PrivateTag +(0029,"SPI-P Release 1",72) CS VideoInvertNonsubtracted 1 PrivateTag +(0029,"SPI-P Release 1",77) CS WindowSelectStatus 1 PrivateTag +(0029,"SPI-P Release 1",78) LT ECGDisplayPrintingID 1 PrivateTag +(0029,"SPI-P Release 1",79) CS ECGDisplayPrinting 1 PrivateTag +(0029,"SPI-P Release 1",7e) CS ECGDisplayPrintingEnableStatus 1 PrivateTag +(0029,"SPI-P Release 1",7f) CS ECGDisplayPrintingSelectStatus 1 PrivateTag +(0029,"SPI-P Release 1",80) LT PhysiologicalDisplayID 1 PrivateTag +(0029,"SPI-P Release 1",81) US PreferredPhysiologicalChannelDisplay 1 PrivateTag +(0029,"SPI-P Release 1",8e) CS PhysiologicalDisplayEnableStatus 1 PrivateTag +(0029,"SPI-P Release 1",8f) CS PhysiologicalDisplaySelectStatus 1 PrivateTag +(0029,"SPI-P Release 1",c0) LT FunctionalShutterID 1 PrivateTag +(0029,"SPI-P Release 1",c1) US FieldOfShutter 1 PrivateTag +(0029,"SPI-P Release 1",c5) LT FieldOfShutterRectangle 1 PrivateTag +(0029,"SPI-P Release 1",ce) CS ShutterEnableStatus 1 PrivateTag +(0029,"SPI-P Release 1",cf) CS ShutterSelectStatus 1 PrivateTag +(7FE1,"SPI-P Release 1",10) ox PixelData 1 PrivateTag + +(0009,"SPI-P Release 1;1",c0) LT Unknown 1 PrivateTag +(0009,"SPI-P Release 1;1",c1) LT Unknown 1 PrivateTag +(0019,"SPI-P Release 1;1",00) UN PhysiologicalDataType 1 PrivateTag +(0019,"SPI-P Release 1;1",01) UN PhysiologicalDataChannelAndKind 1 PrivateTag +(0019,"SPI-P Release 1;1",02) US SampleBitsAllocated 1 PrivateTag +(0019,"SPI-P Release 1;1",03) US SampleBitsStored 1 PrivateTag +(0019,"SPI-P Release 1;1",04) US SampleHighBit 1 PrivateTag +(0019,"SPI-P Release 1;1",05) US SampleRepresentation 1 PrivateTag +(0019,"SPI-P Release 1;1",06) UN SmallestSampleValue 1 PrivateTag +(0019,"SPI-P Release 1;1",07) UN LargestSampleValue 1 PrivateTag +(0019,"SPI-P Release 1;1",08) UN NumberOfSamples 1 PrivateTag +(0019,"SPI-P Release 1;1",09) UN SampleData 1 PrivateTag +(0019,"SPI-P Release 1;1",0a) UN SampleRate 1 PrivateTag +(0019,"SPI-P Release 1;1",10) UN PhysiologicalDataType2 1 PrivateTag +(0019,"SPI-P Release 1;1",11) UN PhysiologicalDataChannelAndKind2 1 PrivateTag +(0019,"SPI-P Release 1;1",12) US SampleBitsAllocated2 1 PrivateTag +(0019,"SPI-P Release 1;1",13) US SampleBitsStored2 1 PrivateTag +(0019,"SPI-P Release 1;1",14) US SampleHighBit2 1 PrivateTag +(0019,"SPI-P Release 1;1",15) US SampleRepresentation2 1 PrivateTag +(0019,"SPI-P Release 1;1",16) UN SmallestSampleValue2 1 PrivateTag +(0019,"SPI-P Release 1;1",17) UN LargestSampleValue2 1 PrivateTag +(0019,"SPI-P Release 1;1",18) UN NumberOfSamples2 1 PrivateTag +(0019,"SPI-P Release 1;1",19) UN SampleData2 1 PrivateTag +(0019,"SPI-P Release 1;1",1a) UN SampleRate2 1 PrivateTag +(0029,"SPI-P Release 1;1",00) LT ZoomID 1 PrivateTag +(0029,"SPI-P Release 1;1",01) DS ZoomRectangle 1-n PrivateTag +(0029,"SPI-P Release 1;1",03) DS ZoomFactor 1 PrivateTag +(0029,"SPI-P Release 1;1",04) US ZoomFunction 1 PrivateTag +(0029,"SPI-P Release 1;1",0e) CS ZoomEnableStatus 1 PrivateTag +(0029,"SPI-P Release 1;1",0f) CS ZoomSelectStatus 1 PrivateTag +(0029,"SPI-P Release 1;1",40) LT MagnifyingGlassID 1 PrivateTag +(0029,"SPI-P Release 1;1",41) DS MagnifyingGlassRectangle 1-n PrivateTag +(0029,"SPI-P Release 1;1",43) DS MagnifyingGlassFactor 1 PrivateTag +(0029,"SPI-P Release 1;1",44) US MagnifyingGlassFunction 1 PrivateTag +(0029,"SPI-P Release 1;1",4e) CS MagnifyingGlassEnableStatus 1 PrivateTag +(0029,"SPI-P Release 1;1",4f) CS MagnifyingGlassSelectStatus 1 PrivateTag + +(0029,"SPI-P Release 1;2",00) LT SubtractionMaskID 1 PrivateTag +(0029,"SPI-P Release 1;2",04) UN MaskingFunction 1 PrivateTag +(0029,"SPI-P Release 1;2",0c) UN ProprietaryMaskingParameters 1 PrivateTag +(0029,"SPI-P Release 1;2",1e) CS SubtractionMaskEnableStatus 1 PrivateTag +(0029,"SPI-P Release 1;2",1f) CS SubtractionMaskSelectStatus 1 PrivateTag +(0029,"SPI-P Release 1;3",00) LT ImageEnhancementID 1 PrivateTag +(0029,"SPI-P Release 1;3",01) LT ImageEnhancement 1 PrivateTag +(0029,"SPI-P Release 1;3",02) LT ConvolutionID 1 PrivateTag +(0029,"SPI-P Release 1;3",03) LT ConvolutionType 1 PrivateTag +(0029,"SPI-P Release 1;3",04) LT ConvolutionKernelSizeID 1 PrivateTag +(0029,"SPI-P Release 1;3",05) US ConvolutionKernelSize 2 PrivateTag +(0029,"SPI-P Release 1;3",06) US ConvolutionKernel 1-n PrivateTag +(0029,"SPI-P Release 1;3",0c) DS EnhancementGain 1 PrivateTag +(0029,"SPI-P Release 1;3",1e) CS ImageEnhancementEnableStatus 1 PrivateTag +(0029,"SPI-P Release 1;3",1f) CS ImageEnhancementSelectStatus 1 PrivateTag + +(0011,"SPI-P Release 2;1",18) LT Unknown 1 PrivateTag +(0023,"SPI-P Release 2;1",0d) UI Unknown 1 PrivateTag +(0023,"SPI-P Release 2;1",0e) UI Unknown 1 PrivateTag + +(0009,"SPI-P-GV-CT Release 1",00) LO Unknown 1 PrivateTag +(0009,"SPI-P-GV-CT Release 1",10) LO Unknown 1 PrivateTag +(0009,"SPI-P-GV-CT Release 1",20) LO Unknown 1 PrivateTag +(0009,"SPI-P-GV-CT Release 1",30) LO Unknown 1 PrivateTag +(0009,"SPI-P-GV-CT Release 1",40) LO Unknown 1 PrivateTag +(0009,"SPI-P-GV-CT Release 1",50) LO Unknown 1 PrivateTag +(0009,"SPI-P-GV-CT Release 1",60) LO Unknown 1 PrivateTag +(0009,"SPI-P-GV-CT Release 1",70) LO Unknown 1 PrivateTag +(0009,"SPI-P-GV-CT Release 1",75) LO Unknown 1 PrivateTag +(0009,"SPI-P-GV-CT Release 1",80) LO Unknown 1 PrivateTag +(0009,"SPI-P-GV-CT Release 1",90) LO Unknown 1 PrivateTag +(0019,"SPI-P-GV-CT Release 1",08) IS Unknown 1 PrivateTag +(0019,"SPI-P-GV-CT Release 1",09) IS Unknown 1 PrivateTag +(0019,"SPI-P-GV-CT Release 1",0a) IS Unknown 1 PrivateTag +(0019,"SPI-P-GV-CT Release 1",10) LO Unknown 1 PrivateTag +(0019,"SPI-P-GV-CT Release 1",20) TM Unknown 1 PrivateTag +(0019,"SPI-P-GV-CT Release 1",50) LO Unknown 1 PrivateTag +(0019,"SPI-P-GV-CT Release 1",60) DS Unknown 1 PrivateTag +(0019,"SPI-P-GV-CT Release 1",61) US Unknown 1 PrivateTag +(0019,"SPI-P-GV-CT Release 1",63) LO Unknown 1 PrivateTag +(0019,"SPI-P-GV-CT Release 1",64) US Unknown 1 PrivateTag +(0019,"SPI-P-GV-CT Release 1",65) IS Unknown 1 PrivateTag +(0019,"SPI-P-GV-CT Release 1",70) LT Unknown 1 PrivateTag +(0019,"SPI-P-GV-CT Release 1",80) LO Unknown 1 PrivateTag +(0019,"SPI-P-GV-CT Release 1",81) LO Unknown 1 PrivateTag +(0019,"SPI-P-GV-CT Release 1",90) LO Unknown 1 PrivateTag +(0019,"SPI-P-GV-CT Release 1",a0) LO Unknown 1 PrivateTag +(0019,"SPI-P-GV-CT Release 1",a1) US Unknown 1 PrivateTag +(0019,"SPI-P-GV-CT Release 1",a2) US Unknown 1 PrivateTag +(0019,"SPI-P-GV-CT Release 1",a3) US Unknown 1 PrivateTag +(0019,"SPI-P-GV-CT Release 1",b0) LO Unknown 1 PrivateTag +(0019,"SPI-P-GV-CT Release 1",b1) LO Unknown 1 PrivateTag +(0021,"SPI-P-GV-CT Release 1",20) LO Unknown 1 PrivateTag +(0021,"SPI-P-GV-CT Release 1",30) DS Unknown 1 PrivateTag +(0021,"SPI-P-GV-CT Release 1",40) LO Unknown 1 PrivateTag +(0021,"SPI-P-GV-CT Release 1",50) LO Unknown 1 PrivateTag +(0021,"SPI-P-GV-CT Release 1",60) DS Unknown 1 PrivateTag +(0021,"SPI-P-GV-CT Release 1",70) DS Unknown 1 PrivateTag +(0021,"SPI-P-GV-CT Release 1",80) DS Unknown 1 PrivateTag +(0021,"SPI-P-GV-CT Release 1",90) DS Unknown 1 PrivateTag +(0021,"SPI-P-GV-CT Release 1",a0) US Unknown 1 PrivateTag +(0021,"SPI-P-GV-CT Release 1",a1) DS Unknown 1 PrivateTag +(0021,"SPI-P-GV-CT Release 1",a2) DS Unknown 1 PrivateTag +(0021,"SPI-P-GV-CT Release 1",a3) LT Unknown 1 PrivateTag +(0021,"SPI-P-GV-CT Release 1",a4) LT Unknown 1 PrivateTag +(0021,"SPI-P-GV-CT Release 1",b0) LO Unknown 1 PrivateTag +(0021,"SPI-P-GV-CT Release 1",c0) LO Unknown 1 PrivateTag +(0029,"SPI-P-GV-CT Release 1",10) LO Unknown 1 PrivateTag +(0029,"SPI-P-GV-CT Release 1",30) UL Unknown 1 PrivateTag +(0029,"SPI-P-GV-CT Release 1",31) UL Unknown 1 PrivateTag +(0029,"SPI-P-GV-CT Release 1",32) UL Unknown 1 PrivateTag +(0029,"SPI-P-GV-CT Release 1",33) UL Unknown 1 PrivateTag +(0029,"SPI-P-GV-CT Release 1",80) LO Unknown 1 PrivateTag +(0029,"SPI-P-GV-CT Release 1",90) LO Unknown 1 PrivateTag +(0029,"SPI-P-GV-CT Release 1",d0) IS Unknown 1 PrivateTag +(0029,"SPI-P-GV-CT Release 1",d1) IS Unknown 1 PrivateTag + +(0019,"SPI-P-PCR Release 2",30) US Unknown 1 PrivateTag + +(0021,"SPI-P-Private-CWS Release 1",00) LT WindowOfImagesID 1 PrivateTag +(0021,"SPI-P-Private-CWS Release 1",01) CS WindowOfImagesType 1 PrivateTag +(0021,"SPI-P-Private-CWS Release 1",02) IS WindowOfImagesScope 1-n PrivateTag + +(0019,"SPI-P-Private-DCI Release 1",10) UN ECGTimeMapDataBitsAllocated 1 PrivateTag +(0019,"SPI-P-Private-DCI Release 1",11) UN ECGTimeMapDataBitsStored 1 PrivateTag +(0019,"SPI-P-Private-DCI Release 1",12) UN ECGTimeMapDataHighBit 1 PrivateTag +(0019,"SPI-P-Private-DCI Release 1",13) UN ECGTimeMapDataRepresentation 1 PrivateTag +(0019,"SPI-P-Private-DCI Release 1",14) UN ECGTimeMapDataSmallestDataValue 1 PrivateTag +(0019,"SPI-P-Private-DCI Release 1",15) UN ECGTimeMapDataLargestDataValue 1 PrivateTag +(0019,"SPI-P-Private-DCI Release 1",16) UN ECGTimeMapDataNumberOfDataValues 1 PrivateTag +(0019,"SPI-P-Private-DCI Release 1",17) UN ECGTimeMapData 1 PrivateTag + +(0021,"SPI-P-Private_CDS Release 1",40) IS Unknown 1 PrivateTag +(0029,"SPI-P-Private_CDS Release 1",00) UN Unknown 1 PrivateTag + +(0019,"SPI-P-Private_ICS Release 1",30) DS Unknown 1 PrivateTag +(0019,"SPI-P-Private_ICS Release 1",31) LO Unknown 1 PrivateTag +(0029,"SPI-P-Private_ICS Release 1",08) SQ Unknown 1 PrivateTag +(0029,"SPI-P-Private_ICS Release 1",0f) SQ Unknown 1 PrivateTag +(0029,"SPI-P-Private_ICS Release 1",10) SQ Unknown 1 PrivateTag +(0029,"SPI-P-Private_ICS Release 1",1b) SQ Unknown 1 PrivateTag +(0029,"SPI-P-Private_ICS Release 1",1c) SQ Unknown 1 PrivateTag +(0029,"SPI-P-Private_ICS Release 1",21) SQ Unknown 1 PrivateTag +(0029,"SPI-P-Private_ICS Release 1",43) SQ Unknown 1 PrivateTag +(0029,"SPI-P-Private_ICS Release 1",44) SQ Unknown 1 PrivateTag +(0029,"SPI-P-Private_ICS Release 1",4C) SQ Unknown 1 PrivateTag +(0029,"SPI-P-Private_ICS Release 1",67) LO Unknown 1 PrivateTag +(0029,"SPI-P-Private_ICS Release 1",68) US Unknown 1 PrivateTag +(0029,"SPI-P-Private_ICS Release 1",6A) LO Unknown 1 PrivateTag +(0029,"SPI-P-Private_ICS Release 1",6B) US Unknown 1 PrivateTag + +(0029,"SPI-P-Private_ICS Release 1;1",00) SL Unknown 1 PrivateTag +(0029,"SPI-P-Private_ICS Release 1;1",05) FL Unknown 1 PrivateTag +(0029,"SPI-P-Private_ICS Release 1;1",06) FL Unknown 1 PrivateTag +(0029,"SPI-P-Private_ICS Release 1;1",20) FL Unknown 1 PrivateTag +(0029,"SPI-P-Private_ICS Release 1;1",21) FL Unknown 1 PrivateTag +(0029,"SPI-P-Private_ICS Release 1;1",CD) SQ Unknown 1 PrivateTag + +(0029,"SPI-P-Private_ICS Release 1;2",00) FD Unknown 1 PrivateTag +(0029,"SPI-P-Private_ICS Release 1;2",01) FD Unknown 1 PrivateTag +(0029,"SPI-P-Private_ICS Release 1;2",02) FD Unknown 1 PrivateTag +(0029,"SPI-P-Private_ICS Release 1;2",03) SL Unknown 1 PrivateTag +(0029,"SPI-P-Private_ICS Release 1;2",04) SL Unknown 1 PrivateTag +(0029,"SPI-P-Private_ICS Release 1;2",05) SL Unknown 1 PrivateTag + +(0029,"SPI-P-Private_ICS Release 1;3",C0) SQ Unknown 1 PrivateTag +(0029,"SPI-P-Private_ICS Release 1;3",C1) SQ Unknown 1 PrivateTag +(0029,"SPI-P-Private_ICS Release 1;3",C2) SQ Unknown 1 PrivateTag +(0029,"SPI-P-Private_ICS Release 1;3",C3) SQ Unknown 1 PrivateTag +(0029,"SPI-P-Private_ICS Release 1;3",C4) SQ Unknown 1 PrivateTag +(0029,"SPI-P-Private_ICS Release 1;3",C5) SQ Unknown 1 PrivateTag + +(0029,"SPI-P-Private_ICS Release 1;4",02) SQ Unknown 1 PrivateTag +(0029,"SPI-P-Private_ICS Release 1;4",9A) SQ Unknown 1 PrivateTag +(0029,"SPI-P-Private_ICS Release 1;4",E0) SQ Unknown 1 PrivateTag + +(0029,"SPI-P-Private_ICS Release 1;5",50) CS Unknown 1 PrivateTag +(0029,"SPI-P-Private_ICS Release 1;5",55) CS Unknown 1 PrivateTag + +(0019,"SPI-P-XSB-DCI Release 1",10) LT VideoBeamBoost 1 PrivateTag +(0019,"SPI-P-XSB-DCI Release 1",11) US ChannelGeneratingVideoSync 1 PrivateTag +(0019,"SPI-P-XSB-DCI Release 1",12) US VideoGain 1 PrivateTag +(0019,"SPI-P-XSB-DCI Release 1",13) US VideoOffset 1 PrivateTag +(0019,"SPI-P-XSB-DCI Release 1",20) DS RTDDataCompressionFactor 1 PrivateTag + +(0029,"Silhouette Annot V1.0",11) IS AnnotationName 1 PrivateTag +(0029,"Silhouette Annot V1.0",12) LT AnnotationFont 1 PrivateTag +(0029,"Silhouette Annot V1.0",13) LT AnnotationTextForegroundColor 1 PrivateTag +(0029,"Silhouette Annot V1.0",14) LT AnnotationTextBackgroundColor 1 PrivateTag +(0029,"Silhouette Annot V1.0",15) UL AnnotationTextBackingMode 1 PrivateTag +(0029,"Silhouette Annot V1.0",16) UL AnnotationTextJustification 1 PrivateTag +(0029,"Silhouette Annot V1.0",17) UL AnnotationTextLocation 1 PrivateTag +(0029,"Silhouette Annot V1.0",18) LT AnnotationTextString 1 PrivateTag +(0029,"Silhouette Annot V1.0",19) UL AnnotationTextAttachMode 1 PrivateTag +(0029,"Silhouette Annot V1.0",20) UL AnnotationTextCursorMode 1 PrivateTag +(0029,"Silhouette Annot V1.0",21) UL AnnotationTextShadowOffsetX 1 PrivateTag +(0029,"Silhouette Annot V1.0",22) UL AnnotationTextShadowOffsetY 1 PrivateTag +(0029,"Silhouette Annot V1.0",23) LT AnnotationLineColor 1 PrivateTag +(0029,"Silhouette Annot V1.0",24) UL AnnotationLineThickness 1 PrivateTag +(0029,"Silhouette Annot V1.0",25) UL AnnotationLineType 1 PrivateTag +(0029,"Silhouette Annot V1.0",26) UL AnnotationLineStyle 1 PrivateTag +(0029,"Silhouette Annot V1.0",27) UL AnnotationLineDashLength 1 PrivateTag +(0029,"Silhouette Annot V1.0",28) UL AnnotationLineAttachMode 1 PrivateTag +(0029,"Silhouette Annot V1.0",29) UL AnnotationLinePointCount 1 PrivateTag +(0029,"Silhouette Annot V1.0",30) FD AnnotationLinePoints 1 PrivateTag +(0029,"Silhouette Annot V1.0",31) UL AnnotationLineControlSize 1 PrivateTag +(0029,"Silhouette Annot V1.0",32) LT AnnotationMarkerColor 1 PrivateTag +(0029,"Silhouette Annot V1.0",33) UL AnnotationMarkerType 1 PrivateTag +(0029,"Silhouette Annot V1.0",34) UL AnnotationMarkerSize 1 PrivateTag +(0029,"Silhouette Annot V1.0",35) FD AnnotationMarkerLocation 1 PrivateTag +(0029,"Silhouette Annot V1.0",36) UL AnnotationMarkerAttachMode 1 PrivateTag +(0029,"Silhouette Annot V1.0",37) LT AnnotationGeomColor 1 PrivateTag +(0029,"Silhouette Annot V1.0",38) UL AnnotationGeomThickness 1 PrivateTag +(0029,"Silhouette Annot V1.0",39) UL AnnotationGeomLineStyle 1 PrivateTag +(0029,"Silhouette Annot V1.0",40) UL AnnotationGeomDashLength 1 PrivateTag +(0029,"Silhouette Annot V1.0",41) UL AnnotationGeomFillPattern 1 PrivateTag +(0029,"Silhouette Annot V1.0",42) UL AnnotationInteractivity 1 PrivateTag +(0029,"Silhouette Annot V1.0",43) FD AnnotationArrowLength 1 PrivateTag +(0029,"Silhouette Annot V1.0",44) FD AnnotationArrowAngle 1 PrivateTag +(0029,"Silhouette Annot V1.0",45) UL AnnotationDontSave 1 PrivateTag + +(0029,"Silhouette Graphics Export V1.0",00) UI Unknown 1 PrivateTag + +(0029,"Silhouette Line V1.0",11) IS LineName 1 PrivateTag +(0029,"Silhouette Line V1.0",12) LT LineNameFont 1 PrivateTag +(0029,"Silhouette Line V1.0",13) UL LineNameDisplay 1 PrivateTag +(0029,"Silhouette Line V1.0",14) LT LineNormalColor 1 PrivateTag +(0029,"Silhouette Line V1.0",15) UL LineType 1 PrivateTag +(0029,"Silhouette Line V1.0",16) UL LineThickness 1 PrivateTag +(0029,"Silhouette Line V1.0",17) UL LineStyle 1 PrivateTag +(0029,"Silhouette Line V1.0",18) UL LineDashLength 1 PrivateTag +(0029,"Silhouette Line V1.0",19) UL LineInteractivity 1 PrivateTag +(0029,"Silhouette Line V1.0",20) LT LineMeasurementColor 1 PrivateTag +(0029,"Silhouette Line V1.0",21) LT LineMeasurementFont 1 PrivateTag +(0029,"Silhouette Line V1.0",22) UL LineMeasurementDashLength 1 PrivateTag +(0029,"Silhouette Line V1.0",23) UL LinePointSpace 1 PrivateTag +(0029,"Silhouette Line V1.0",24) FD LinePoints 1 PrivateTag +(0029,"Silhouette Line V1.0",25) UL LineControlPointSize 1 PrivateTag +(0029,"Silhouette Line V1.0",26) UL LineControlPointSpace 1 PrivateTag +(0029,"Silhouette Line V1.0",27) FD LineControlPoints 1 PrivateTag +(0029,"Silhouette Line V1.0",28) LT LineLabel 1 PrivateTag +(0029,"Silhouette Line V1.0",29) UL LineDontSave 1 PrivateTag + +(0029,"Silhouette ROI V1.0",11) IS ROIName 1 PrivateTag +(0029,"Silhouette ROI V1.0",12) LT ROINameFont 1 PrivateTag +(0029,"Silhouette ROI V1.0",13) LT ROINormalColor 1 PrivateTag +(0029,"Silhouette ROI V1.0",14) UL ROIFillPattern 1 PrivateTag +(0029,"Silhouette ROI V1.0",15) UL ROIBpSeg 1 PrivateTag +(0029,"Silhouette ROI V1.0",16) UN ROIBpSegPairs 1 PrivateTag +(0029,"Silhouette ROI V1.0",17) UL ROISeedSpace 1 PrivateTag +(0029,"Silhouette ROI V1.0",18) UN ROISeeds 1 PrivateTag +(0029,"Silhouette ROI V1.0",19) UL ROILineThickness 1 PrivateTag +(0029,"Silhouette ROI V1.0",20) UL ROILineStyle 1 PrivateTag +(0029,"Silhouette ROI V1.0",21) UL ROILineDashLength 1 PrivateTag +(0029,"Silhouette ROI V1.0",22) UL ROIInteractivity 1 PrivateTag +(0029,"Silhouette ROI V1.0",23) UL ROINamePosition 1 PrivateTag +(0029,"Silhouette ROI V1.0",24) UL ROINameDisplay 1 PrivateTag +(0029,"Silhouette ROI V1.0",25) LT ROILabel 1 PrivateTag +(0029,"Silhouette ROI V1.0",26) UL ROIShape 1 PrivateTag +(0029,"Silhouette ROI V1.0",27) FD ROIShapeTilt 1 PrivateTag +(0029,"Silhouette ROI V1.0",28) UL ROIShapePointsCount 1 PrivateTag +(0029,"Silhouette ROI V1.0",29) UL ROIShapePointsSpace 1 PrivateTag +(0029,"Silhouette ROI V1.0",30) FD ROIShapePoints 1 PrivateTag +(0029,"Silhouette ROI V1.0",31) UL ROIShapeControlPointsCount 1 PrivateTag +(0029,"Silhouette ROI V1.0",32) UL ROIShapeControlPointsSpace 1 PrivateTag +(0029,"Silhouette ROI V1.0",33) FD ROIShapeControlPoints 1 PrivateTag +(0029,"Silhouette ROI V1.0",34) UL ROIDontSave 1 PrivateTag + +(0029,"Silhouette Sequence Ids V1.0",41) SQ Unknown 1 PrivateTag +(0029,"Silhouette Sequence Ids V1.0",42) SQ Unknown 1 PrivateTag +(0029,"Silhouette Sequence Ids V1.0",43) SQ Unknown 1 PrivateTag + +(0029,"Silhouette V1.0",13) UL Unknown 1 PrivateTag +(0029,"Silhouette V1.0",14) UL Unknown 1 PrivateTag +(0029,"Silhouette V1.0",17) UN Unknown 1 PrivateTag +(0029,"Silhouette V1.0",18) UN Unknown 1 PrivateTag +(0029,"Silhouette V1.0",19) UL Unknown 1 PrivateTag +(0029,"Silhouette V1.0",1a) UN Unknown 1 PrivateTag +(0029,"Silhouette V1.0",1b) UL Unknown 1 PrivateTag +(0029,"Silhouette V1.0",1c) UL Unknown 1 PrivateTag +(0029,"Silhouette V1.0",1d) UN Unknown 1 PrivateTag +(0029,"Silhouette V1.0",1e) UN Unknown 1 PrivateTag +(0029,"Silhouette V1.0",21) US Unknown 1 PrivateTag +(0029,"Silhouette V1.0",22) US Unknown 1 PrivateTag +(0029,"Silhouette V1.0",23) US Unknown 1 PrivateTag +(0029,"Silhouette V1.0",24) US Unknown 1 PrivateTag +(0029,"Silhouette V1.0",25) US Unknown 1 PrivateTag +(0029,"Silhouette V1.0",27) UN Unknown 1 PrivateTag +(0029,"Silhouette V1.0",28) UN Unknown 1 PrivateTag +(0029,"Silhouette V1.0",29) UN Unknown 1 PrivateTag +(0029,"Silhouette V1.0",30) UN Unknown 1 PrivateTag +(0029,"Silhouette V1.0",52) US Unknown 1 PrivateTag +(0029,"Silhouette V1.0",53) LT Unknown 1 PrivateTag +(0029,"Silhouette V1.0",54) UN Unknown 1 PrivateTag +(0029,"Silhouette V1.0",55) LT Unknown 1 PrivateTag +(0029,"Silhouette V1.0",56) LT Unknown 1 PrivateTag +(0029,"Silhouette V1.0",57) UN Unknown 1 PrivateTag + +(0135,"SONOWAND AS",10) LO UltrasoundScannerName 1 PrivateTag +(0135,"SONOWAND AS",11) LO TransducerSerial 1 PrivateTag +(0135,"SONOWAND AS",12) LO ProbeApplication 1 PrivateTag + +(0017,"SVISION",00) LO ExtendedBodyPart 1 PrivateTag +(0017,"SVISION",10) LO ExtendedViewPosition 1 PrivateTag +(0017,"SVISION",F0) IS ImagesSOPClass 1 PrivateTag +(0019,"SVISION",00) IS AECField 1 PrivateTag +(0019,"SVISION",01) IS AECFilmScreen 1 PrivateTag +(0019,"SVISION",02) IS AECDensity 1 PrivateTag +(0019,"SVISION",10) IS PatientThickness 1 PrivateTag +(0019,"SVISION",18) IS BeamDistance 1 PrivateTag +(0019,"SVISION",20) IS WorkstationNumber 1 PrivateTag +(0019,"SVISION",28) IS TubeNumber 1 PrivateTag +(0019,"SVISION",30) IS BuckyGrid 1 PrivateTag +(0019,"SVISION",34) IS Focus 1 PrivateTag +(0019,"SVISION",38) IS Child 1 PrivateTag +(0019,"SVISION",40) IS CollimatorDistanceX 1 PrivateTag +(0019,"SVISION",41) IS CollimatorDistanceY 1 PrivateTag +(0019,"SVISION",50) IS CentralBeamHeight 1 PrivateTag +(0019,"SVISION",60) IS BuckyAngle 1 PrivateTag +(0019,"SVISION",68) IS CArmAngle 1 PrivateTag +(0019,"SVISION",69) IS CollimatorAngle 1 PrivateTag +(0019,"SVISION",70) IS FilterNumber 1 PrivateTag +(0019,"SVISION",74) LO FilterMaterial1 1 PrivateTag +(0019,"SVISION",75) LO FilterMaterial2 1 PrivateTag +(0019,"SVISION",78) DS FilterThickness1 1 PrivateTag +(0019,"SVISION",79) DS FilterThickness2 1 PrivateTag +(0019,"SVISION",80) IS BuckyFormat 1 PrivateTag +(0019,"SVISION",81) IS ObjectPosition 1 PrivateTag +(0019,"SVISION",90) LO DeskCommand 1 PrivateTag +(0019,"SVISION",A0) DS ExtendedExposureTime 1 PrivateTag +(0019,"SVISION",A1) DS ActualExposureTime 1 PrivateTag +(0019,"SVISION",A8) DS ExtendedXRayTubeCurrent 1 PrivateTag +(0021,"SVISION",00) DS NoiseReduction 1 PrivateTag +(0021,"SVISION",01) DS ContrastAmplification 1 PrivateTag +(0021,"SVISION",02) DS EdgeContrastBoosting 1 PrivateTag +(0021,"SVISION",03) DS LatitudeReduction 1 PrivateTag +(0021,"SVISION",10) LO FindRangeAlgorithm 1 PrivateTag +(0021,"SVISION",11) DS ThresholdCAlgorithm 1 PrivateTag +(0021,"SVISION",20) LO SensometricCurve 1 PrivateTag +(0021,"SVISION",30) DS LowerWindowOffset 1 PrivateTag +(0021,"SVISION",31) DS UpperWindowOffset 1 PrivateTag +(0021,"SVISION",40) DS MinPrintableDensity 1 PrivateTag +(0021,"SVISION",41) DS MaxPrintableDensity 1 PrivateTag +(0021,"SVISION",90) DS Brightness 1 PrivateTag +(0021,"SVISION",91) DS Contrast 1 PrivateTag +(0021,"SVISION",92) DS ShapeFactor 1 PrivateTag +(0023,"SVISION",00) LO ImageLaterality 1 PrivateTag +(0023,"SVISION",01) IS LetterPosition 1 PrivateTag +(0023,"SVISION",02) IS BurnedInAnnotation 1 PrivateTag +(0023,"SVISION",03) LO Unknown 1 PrivateTag +(0023,"SVISION",F0) IS ImageSOPClass 1 PrivateTag +(0025,"SVISION",00) IS OriginalImage 1 PrivateTag +(0025,"SVISION",01) IS NotProcessedImage 1 PrivateTag +(0025,"SVISION",02) IS CutOutImage 1 PrivateTag +(0025,"SVISION",03) IS DuplicatedImage 1 PrivateTag +(0025,"SVISION",04) IS StoredImage 1 PrivateTag +(0025,"SVISION",05) IS RetrievedImage 1 PrivateTag +(0025,"SVISION",06) IS RemoteImage 1 PrivateTag +(0025,"SVISION",07) IS MediaStoredImage 1 PrivateTag +(0025,"SVISION",08) IS ImageState 1 PrivateTag +(0025,"SVISION",20) LO SourceImageFile 1 PrivateTag +(0025,"SVISION",21) UI Unknown 1 PrivateTag +(0027,"SVISION",00) IS NumberOfSeries 1 PrivateTag +(0027,"SVISION",01) IS NumberOfStudies 1 PrivateTag +(0027,"SVISION",10) DT OldestSeries 1 PrivateTag +(0027,"SVISION",11) DT NewestSeries 1 PrivateTag +(0027,"SVISION",12) DT OldestStudy 1 PrivateTag +(0027,"SVISION",13) DT NewestStudy 1 PrivateTag + +(0009,"TOSHIBA_MEC_1.0",01) LT Unknown 1 PrivateTag +(0009,"TOSHIBA_MEC_1.0",02) US Unknown 1-n PrivateTag +(0009,"TOSHIBA_MEC_1.0",03) US Unknown 1-n PrivateTag +(0009,"TOSHIBA_MEC_1.0",04) US Unknown 1-n PrivateTag +(0011,"TOSHIBA_MEC_1.0",01) LT Unknown 1 PrivateTag +(0011,"TOSHIBA_MEC_1.0",02) US Unknown 1-n PrivateTag +(0019,"TOSHIBA_MEC_1.0",01) US Unknown 1-n PrivateTag +(0019,"TOSHIBA_MEC_1.0",02) US Unknown 1-n PrivateTag +(0021,"TOSHIBA_MEC_1.0",01) US Unknown 1-n PrivateTag +(0021,"TOSHIBA_MEC_1.0",02) US Unknown 1-n PrivateTag +(0021,"TOSHIBA_MEC_1.0",03) US Unknown 1-n PrivateTag +(7ff1,"TOSHIBA_MEC_1.0",01) US Unknown 1-n PrivateTag +(7ff1,"TOSHIBA_MEC_1.0",02) US Unknown 1-n PrivateTag +(7ff1,"TOSHIBA_MEC_1.0",03) US Unknown 1-n PrivateTag +(7ff1,"TOSHIBA_MEC_1.0",10) US Unknown 1-n PrivateTag + +(0019,"TOSHIBA_MEC_CT_1.0",01) IS Unknown 1 PrivateTag +(0019,"TOSHIBA_MEC_CT_1.0",02) IS Unknown 1 PrivateTag +(0019,"TOSHIBA_MEC_CT_1.0",03) US Unknown 1-n PrivateTag +(0019,"TOSHIBA_MEC_CT_1.0",04) LT Unknown 1 PrivateTag +(0019,"TOSHIBA_MEC_CT_1.0",05) LT Unknown 1 PrivateTag +(0019,"TOSHIBA_MEC_CT_1.0",06) US Unknown 1-n PrivateTag +(0019,"TOSHIBA_MEC_CT_1.0",07) US Unknown 1-n PrivateTag +(0019,"TOSHIBA_MEC_CT_1.0",08) LT OrientationHeadFeet 1 PrivateTag +(0019,"TOSHIBA_MEC_CT_1.0",09) LT ViewDirection 1 PrivateTag +(0019,"TOSHIBA_MEC_CT_1.0",0a) LT OrientationSupineProne 1 PrivateTag +(0019,"TOSHIBA_MEC_CT_1.0",0b) DS Unknown 1 PrivateTag +(0019,"TOSHIBA_MEC_CT_1.0",0c) US Unknown 1-n PrivateTag +(0019,"TOSHIBA_MEC_CT_1.0",0d) TM Time 1 PrivateTag +(0019,"TOSHIBA_MEC_CT_1.0",0e) DS Unknown 1 PrivateTag +(7ff1,"TOSHIBA_MEC_CT_1.0",01) US Unknown 1-n PrivateTag +(7ff1,"TOSHIBA_MEC_CT_1.0",02) US Unknown 1-n PrivateTag +(7ff1,"TOSHIBA_MEC_CT_1.0",03) IS Unknown 1 PrivateTag +(7ff1,"TOSHIBA_MEC_CT_1.0",04) IS Unknown 1 PrivateTag +(7ff1,"TOSHIBA_MEC_CT_1.0",05) US Unknown 1-n PrivateTag +(7ff1,"TOSHIBA_MEC_CT_1.0",07) US Unknown 1-n PrivateTag +(7ff1,"TOSHIBA_MEC_CT_1.0",08) US Unknown 1-n PrivateTag +(7ff1,"TOSHIBA_MEC_CT_1.0",09) US Unknown 1-n PrivateTag +(7ff1,"TOSHIBA_MEC_CT_1.0",0a) LT Unknown 1 PrivateTag +(7ff1,"TOSHIBA_MEC_CT_1.0",0b) US Unknown 1-n PrivateTag +(7ff1,"TOSHIBA_MEC_CT_1.0",0c) US Unknown 1-n PrivateTag +(7ff1,"TOSHIBA_MEC_CT_1.0",0d) US Unknown 1-n PrivateTag +# +# end of private.dic +# diff --git a/dcmdata/docs/CMakeLists.txt b/dcmdata/docs/CMakeLists.txt new file mode 100644 index 00000000..4c37c72e --- /dev/null +++ b/dcmdata/docs/CMakeLists.txt @@ -0,0 +1,2 @@ +# declare installation files +INSTALL(FILES datadict.txt DESTINATION ${DCMTK_INSTALL_DOCDIR} COMPONENT doc) diff --git a/dcmdata/docs/Makefile.in b/dcmdata/docs/Makefile.in new file mode 100644 index 00000000..db2b71f6 --- /dev/null +++ b/dcmdata/docs/Makefile.in @@ -0,0 +1,29 @@ +# +# Makefile for dcmdata/docs +# + +@SET_MAKE@ + +SHELL = /bin/sh +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +configdir = @top_srcdir@/@configdir@ + +include $(configdir)/@common_makefile@ + +files = datadict.txt + + +all: + +install: + $(configdir)/mkinstalldirs $(DESTDIR)$(docdir) + for file in $(files); do \ + $(INSTALL_DATA) $$file $(DESTDIR)$(docdir) ;\ + done + +clean: + rm -f $(TRASH) + +distclean: + rm -f $(DISTTRASH) diff --git a/dcmdata/docs/datadict.txt b/dcmdata/docs/datadict.txt new file mode 100644 index 00000000..9a139805 --- /dev/null +++ b/dcmdata/docs/datadict.txt @@ -0,0 +1,219 @@ +----------------------------------------------------------------------------- +DICOM DATA DICTIONARY IN DCMTK +----------------------------------------------------------------------------- + +In DICOM, the Data Dictionary (part 6 of the DICOM standard) stores for all +tags their respective VR, VM, attribute name and other information. This +information must also be made available in DCMTK. This is accomplished +through a global data dictionary class. + +The global data dictionary is loaded within a C++ constructor into the global +DcmDataDictionary class instance called dcmDataDict once it is accessed for the +first time from the code. The dictionary content is populated by three +different approaches: Either the content (tags, VR, ...) can be compiled +into the dictionary code, or the dictionary is filled by loading a text file +on startup from a pre-defined file path (also called an "external" data +dictionary). Lastly, DCMTK will load one or more additional external +dictionaries from the path set in the environment variable DCMDICTPATH, if set. + +The built-in approach offers the advantage that a binary will not have to +load any information from a separate file which may get lost or or used in an +outdated version. Loading the dictionary content from a separate file, +however, has the advantage that application programs need not be recompiled +if additions or corrections are made to the data dictionary. + +DCMTK uses an external data dictionary per default on Posix systems (Linux, +Mac OS X, etc.) while a built-in dictionary is used on Windows systems. How +these defaults can be changed or how both approaches can even be combined +is further explained below. + +----------------------------------------------------------------------------- +DICTIONARY DEFAULT: AUTOCONF ON POSIX SYSTEMS +----------------------------------------------------------------------------- + +By default on a Posix system the global data dictionary will attempt to load +the data dictionary from an external file. The location is pre-configured +to $DCMTK_DAT_DIR/dicom.dic where $DCMTK_DAT_DIR is DCMTK's data +installation prefix chosen using configure's --datadir option (default: +/dcmtk). See also --datarootdir and --prefix options. The resulting path is +stored as DCM_DICT_DEFAULT_PATH in the file +config/include/dcmtk/config/osconfig.h, which is created by autoconf +during the execution of the configure script and thus is available to the +dictionary code that includes osconfig.h. + +----------------------------------------------------------------------------- +DICTIONARY DEFAULT: CMAKE ON WINDOWS AND POSIX SYSTEMS +----------------------------------------------------------------------------- + +On Windows (and Posix if using CMake on this platform), the default behaviour +is to compile a fully-populated DICOM dictionary as global data dictionary +into the dcmdata library. Thus, it is not required to load an external data +dictionary from a file and dcmdata will not try loading such a file by default. + +----------------------------------------------------------------------------- +CHANGING DICTIONARY DEFAULTS +----------------------------------------------------------------------------- + +Autoconf as well as CMake provide options to change their default dictionary +behaviour. For autoconf, configure offers the options: + + --enable-external-dict enable loading of external dictionary (default) + --disable-external-dict don't load external dictionary + --enable-builtin-dict enable loading of built-in dictionary (default) + --disable-builtin-dict don't load built-in dictionary + +They can be used toggle both dictionaries on and off: If the external +dictionary is turned off, it is not tried to load it from any default +location. + +When building with CMake, the related options are called + + - DCMTK_ENABLE_EXTERNAL_DICTIONARY + - DCMTK_ENABLE_BUILTIN_DICTIONARY + +----------------------------------------------------------------------------- +DICTIONARY LOAD ORDER AND USING MULTIPLE DICTIONARIES +----------------------------------------------------------------------------- + +The built-in dictionary, if enabled, is always loaded first on startup, +followed by any external dictionary. Data dictionary entries loaded later in +the load sequence override entries loaded earlier. + +Note that most of the time (no matter whether using autoconf or CMake) it +makes sense to enable only the built-in dictionary or only the external +dictionary. If both external and built-in version are enabled, the global data +dictionary is populated first with the compiled-in data, and afterwards the +external dictionary is loaded. If the latter is the default one shipping with +DCMTK (dicom.dic) then the external dictionary provides no extra information +since it contains exactly the same data as the built-in one but only takes time +loading. Thus it only makes sense to use enable both options if the external +dictionary is modified to include (only) additional information not available in +the built-in dictionary. + +If the user disables both options, no dictionary will be loaded per default +on startup. However, a dictionary can be defined using the DCMDICTPATH +environment variable (see below). If DCMDICTPATH is used, the default external +dictionary will not be loaded at all. + +Application programs should check that a data dictionary has been loaded +before using the functionality of the dcmdata library. The absence of +a data dictionary is likely to cause unexpected behaviour (e.g. unknown +attributes will be encoded using VR=UN). + +----------------------------------------------------------------------------- +CUSTOM EXTERNAL DICTIONARIES THROUGH ENVIRONMENT VARIABLE "DCMDICTPATH" +----------------------------------------------------------------------------- + +Sometimes it makes sense to change the dictionary that should be loaded +without recompiling the source code. This can be done either be modifying +the dicom.dic that is already loaded, or, by specifying a different location +in an environment variable that is evaluated on DCMTK startup. That +enviornment variable is called "DCMDICTPATH" and is considered on Windows +and Posix platforms. If DCMDICTPATH is not set, the behaviour described in +the the sections above takes place (built-in and/or external dictionary from +default path is loaded). + +Otherwise, the file provided in the environment variable DCMDICTPATH is loaded +and any default external dictionary is ignored(!). However, note that the +built-in dictionary (if configured) will be always loaded. + +In order to set DCMDICTPATH on Unix, the csh shell command + + setenv DCMDICTPATH $HOME/dicom.dic + +would cause all applications using the dcmdata library to load the data +dictionary dicom.dic from the users home directory. + +For Windows, the call + + set DCMDICTPATH=c:\dicom.dic + +will cause all applications using the dcmdata library to load the data +dictionary dicom.dic from the main directory on drive C. + +----------------------------------------------------------------------------- +USING MORE THAN ONE EXTERNAL DICTIONARY +----------------------------------------------------------------------------- + +The DCMDICTPATH environment variable can even contain several data +dictionaries separated by colons (":") on Unix systems, and semicolon on +Windows systems. Thus the Unix csh command: + + setenv DCMDICTPATH /usr/local/share/dcmtk/dicom.dic:$HOME/dicom.dic + +would cause all applications using the dcmdata library to first load the +default data dictionary and subsequently load the data dictionary dicom.dic +from the users home directory. On Windows systems, an example could be + + set DCMDICTPATH=c:\dcmtk-install\share\dcmtk\dicom.dic;c:\dicom.dic + +Also here, data dictionary entries loaded later in the load sequence override +entries loaded earlier. + +----------------------------------------------------------------------------- +DATA DICTIONARIES INCLUDED IN DCMTK (DICOM.DIC, PRIVATE.DIC AND BUILT-IN) +----------------------------------------------------------------------------- + +An example DICOM data dictionary can be found in dcmdata/data/dicom.dic +which is also installed (using autoconf or CMake) and used as the default +external dictionary (if external default dictionary is enabled). + +The example data dictionary is relatively complete and includes all +standard DICOM tags (see the header of the file, where the implemented +version of the standard plus all supplements and CPs are listed), obsolete +ACR/NEMA version 2 tags, obsolete SPI tags, and the tags used by Papyrus +version 3. An early version of this data dictionary was based on a data +dictionary put together by David Clunie. + +Another example dictionary included is the dcmdata/data/private.dic which +includes any private tag information known to DCMTK developers and partly +taken over from other DICOM toolkits and various other sources like +Conformance Statements. There is no guarantee that the tag information +contained is valid or even complete. Per default, this dictionary is not +taken into account. It can be enabled to load on startup as an extra +external dictionary using autoconf's configure option "--enable-private-tags" +and in CMake using the option "DCMTK_ENABLE_PRIVATE_TAGS". Enabling will +result in private.dic being added to the DCM_DICT_DEFAULT_PATH which lists those +external dictionaries to be loaded on startup (see above). Note that the +private tag option is only considered for external dictionaries if external +dictionaries are not turned off. + +DCMTK also includes two predefined built-in dictionaries, one fully populated +containing the information from DCMTK's dicom.dic file, and one that is empty. +Both are defined in dcdictbi.cc and the one to be used is selected by the +builtin dictionary build options (see above). + +The code for a useful built-in data dictionary can be regenerated at any time +by the mkdictbi program (dcmdata/libsrc/mkdictbi). The dcmdata library +Makefiles (for autoconf dcmdata/libsrc/Makefile.in, and for CMake +dcmdata/libsrc/CMakeLists.txt) include a target (updatebuiltindict) for this +purpose. After regenerating dcdictbi.cc, rebuilding the libdcmdata.a library +and relinking all your applications will ensure that the built-in data +dictionary is used. + +----------------------------------------------------------------------------- +TAG NAME CONSTANTS FOR USE IN APPLICATIONS +----------------------------------------------------------------------------- + +The include file dcmdata/include/dcmtk/dcmdata/dcdeftag.h can be generated +from a data dictionary by the program mkdeftag. The include file defines +tag names for use in application programs. The names are generated from +the names specified in the data dictionary. Duplicate names in the data +dictionary will result in compiler warnings due to duplicate #define's +when compiling code which includes the dcdeftag.h header file. Thus, when +adding new entries to the data dictionary, care should be taken to ensure +that attribute names are not duplicated for distinct tags. +The dcmdata library Makefiles (for autoconf dcmdata/libsrc/Makefile.in and for +CMake dcmdata/libsrc/CMakeLists.txt) include a target (updatedeftag) which +builds the mkdeftag tool and uses it to generate the +dcmdata/include/dcmtk/dcmdata/dcdeftag.h header file. The header file should +be regenerated whenever additions or name modifications are made to the data +dictionary. Care should be taken before modifying any tag names since existing +application programs may already use the old name and might subsequently fail +to compile. + +------------ + +OFFIS e.V., Oldenburg, Germany + +Last revised: 2015-09-16 (Onken). diff --git a/dcmdata/docs/dcm2pdf.man b/dcmdata/docs/dcm2pdf.man new file mode 100644 index 00000000..b0400a6b --- /dev/null +++ b/dcmdata/docs/dcm2pdf.man @@ -0,0 +1,211 @@ +/*! + +\if MANPAGES +\page dcm2pdf Extract PDF file from DICOM encapsulated PDF +\else +\page dcm2pdf dcm2pdf: Extract PDF file from DICOM encapsulated PDF +\endif + +\section synopsis SYNOPSIS + +\verbatim +dcm2pdf [options] dcmfile-in pdffile-out +\endverbatim + +\section description DESCRIPTION + +The \b dcm2pdf utility reads a DICOM file of the Encapsulated PDF Storage SOP +Class (\e dcmfile-in), extracts the embedded PDF document and writes it to an +output file (\e pdffile-out). Optionally a command can be executed after the +creation of the PDF file. + +\section parameters PARAMETERS + +\verbatim +dcmfile-in DICOM input filename + +pdffile-out PDF output filename +\endverbatim + +\section options OPTIONS + +\subsection general_options general options +\verbatim + -h --help + print this help text and exit + + --version + print version information and exit + + --arguments + print expanded command line arguments + + -q --quiet + quiet mode, print no warnings and errors + + -v --verbose + verbose mode, print processing details + + -d --debug + debug mode, print debug information + + -ll --log-level [l]evel: string constant + (fatal, error, warn, info, debug, trace) + use level l for the logger + + -lc --log-config [f]ilename: string + use config file f for the logger +\endverbatim + +\subsection input_options input options +\verbatim +input file format: + + +f --read-file + read file format or data set (default) + + +fo --read-file-only + read file format only + + -f --read-dataset + read data set without file meta information + +input transfer syntax: + + -t= --read-xfer-auto + use TS recognition (default) + + -td --read-xfer-detect + ignore TS specified in the file meta header + + -te --read-xfer-little + read with explicit VR little endian TS + + -tb --read-xfer-big + read with explicit VR big endian TS + + -ti --read-xfer-implicit + read with implicit VR little endian TS + +parsing of odd-length attributes: + + +ao --accept-odd-length + accept odd length attributes (default) + + +ae --assume-even-length + assume real length is one byte larger + +handling of undefined length UN elements: + + +ui --enable-cp246 + read undefined len UN as implicit VR (default) + + -ui --disable-cp246 + read undefined len UN as explicit VR + +handling of defined length UN elements: + + -uc --retain-un + retain elements as UN (default) + + +uc --convert-un + convert to real VR if known + +automatic data correction: + + +dc --enable-correction + enable automatic data correction (default) + + -dc --disable-correction + disable automatic data correction + +bitstream format of deflated input: + + +bd --bitstream-deflated + expect deflated bitstream (default) + + +bz --bitstream-zlib + expect deflated zlib bitstream +\endverbatim + +\subsection execution_options execution options +\verbatim + -x --exec [c]ommand: string + execute command c after PDF extraction +\endverbatim + +\section notes NOTES + +Option \e --exec allows for the execution of a certain command line after the +creation of the PDF document. The command line to be executed is passed to +this option as a parameter. The specified command line may contain the +placeholder '\#f', which will be replaced by the PDF filename at run time. +The specified command line is executed in the foreground, i.e. \b pdf2dcm will +be blocked until the command terminates. + +\section logging LOGGING + +The level of logging output of the various command line tools and underlying +libraries can be specified by the user. By default, only errors and warnings +are written to the standard error stream. Using option \e --verbose also +informational messages like processing details are reported. Option +\e --debug can be used to get more details on the internal activity, e.g. for +debugging purposes. Other logging levels can be selected using option +\e --log-level. In \e --quiet mode only fatal errors are reported. In such +very severe error events, the application will usually terminate. For more +details on the different logging levels, see documentation of module "oflog". + +In case the logging output should be written to file (optionally with logfile +rotation), to syslog (Unix) or the event log (Windows) option \e --log-config +can be used. This configuration file also allows for directing only certain +messages to a particular output stream and for filtering certain messages +based on the module or application where they are generated. An example +configuration file is provided in \/logger.cfg. + +\section command_line COMMAND LINE + +All command line tools use the following notation for parameters: square +brackets enclose optional values (0-1), three trailing dots indicate that +multiple values are allowed (1-n), a combination of both means 0 to n values. + +Command line options are distinguished from parameters by a leading '+' or '-' +sign, respectively. Usually, order and position of command line options are +arbitrary (i.e. they can appear anywhere). However, if options are mutually +exclusive the rightmost appearance is used. This behavior conforms to the +standard evaluation rules of common Unix shells. + +In addition, one or more command files can be specified using an '@' sign as a +prefix to the filename (e.g. \@command.txt). Such a command argument +is replaced by the content of the corresponding text file (multiple +whitespaces are treated as a single separator unless they appear between two +quotation marks) prior to any further evaluation. Please note that a command +file cannot contain another command file. This simple but effective approach +allows one to summarize common combinations of options/parameters and avoids +longish and confusing command lines (an example is provided in file +\/dumppat.txt). + +\section environment ENVIRONMENT + +The \b dcm2pdf utility will attempt to load DICOM data dictionaries specified +in the \e DCMDICTPATH environment variable. By default, i.e. if the +\e DCMDICTPATH environment variable is not set, the file +\/dicom.dic will be loaded unless the dictionary is built +into the application (default for Windows). + +The default behavior should be preferred and the \e DCMDICTPATH environment +variable only used when alternative data dictionaries are required. The +\e DCMDICTPATH environment variable has the same format as the Unix shell +\e PATH variable in that a colon (":") separates entries. On Windows systems, +a semicolon (";") is used as a separator. The data dictionary code will +attempt to load each file specified in the \e DCMDICTPATH environment variable. +It is an error if no data dictionary can be loaded. + +\section see_also SEE ALSO + +pdf2dcm(1) + +\section copyright COPYRIGHT + +Copyright (C) 2007-2014 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany. + +*/ diff --git a/dcmdata/docs/dcm2xml.man b/dcmdata/docs/dcm2xml.man new file mode 100644 index 00000000..e4b80e38 --- /dev/null +++ b/dcmdata/docs/dcm2xml.man @@ -0,0 +1,387 @@ +/*! + +\if MANPAGES +\page dcm2xml Convert DICOM file and data set to XML +\else +\page dcm2xml dcm2xml: Convert DICOM file and data set to XML +\endif + +\section synopsis SYNOPSIS + +\verbatim +dcm2xml [options] dcmfile-in [xmlfile-out] +\endverbatim + +\section description DESCRIPTION + +The \b dcm2xml utility converts the contents of a DICOM file (file format or +raw data set) to XML (Extensible Markup Language). There are two output +formats. The first one is specific to DCMTK with its DTD (Document Type +Definition) described in the file dcm2xml.dtd. The second one refers +to the "Native DICOM Model" which is specified for the DICOM Application +Hosting service found in DICOM part 19. + +If \b dcm2xml reads a raw data set (DICOM data without a file format +meta-header) it will attempt to guess the transfer syntax by examining the +first few bytes of the file. It is not always possible to correctly guess the +transfer syntax and it is better to convert a data set to a file format +whenever possible (using the \b dcmconv utility). It is also possible to use +the \e -f and -t[ieb] options to force \b dcm2xml to read a data set +with a particular transfer syntax. + +\section parameters PARAMETERS + +\verbatim +dcmfile-in DICOM input filename to be converted + +xmlfile-out XML output filename (default: stdout) +\endverbatim + +\section options OPTIONS + +\subsection general_options general options +\verbatim + -h --help + print this help text and exit + + --version + print version information and exit + + --arguments + print expanded command line arguments + + -q --quiet + quiet mode, print no warnings and errors + + -v --verbose + verbose mode, print processing details + + -d --debug + debug mode, print debug information + + -ll --log-level [l]evel: string constant + (fatal, error, warn, info, debug, trace) + use level l for the logger + + -lc --log-config [f]ilename: string + use config file f for the logger +\endverbatim + +\subsection input_options input options +\verbatim +input file format: + + +f --read-file + read file format or data set (default) + + +fo --read-file-only + read file format only + + -f --read-dataset + read data set without file meta information + +input transfer syntax: + + -t= --read-xfer-auto + use TS recognition (default) + + -td --read-xfer-detect + ignore TS specified in the file meta header + + -te --read-xfer-little + read with explicit VR little endian TS + + -tb --read-xfer-big + read with explicit VR big endian TS + + -ti --read-xfer-implicit + read with implicit VR little endian TS + +long tag values: + + +M --load-all + load very long tag values (e.g. pixel data) + + -M --load-short + do not load very long values (default) + + +R --max-read-length [k]bytes: integer (4..4194302, default: 4) + set threshold for long values to k kbytes +\endverbatim + +\subsection processing_options processing options +\verbatim +specific character set: + + +Cr --charset-require + require declaration of extended charset (default) + + +Ca --charset-assume [c]harset: string + assume charset c if no extended charset declared + + +Cc --charset-check-all + check all data elements with string values + (default: only PN, LO, LT, SH, ST and UT) + + # this option is only used for the mapping to an appropriate + # XML character encoding, but not for the conversion to UTF-8 + + +U8 --convert-to-utf8 + convert all element values that are affected + by Specific Character Set (0008,0005) to UTF-8 + + # requires support from the libiconv toolkit +\endverbatim + +\subsection output_options output options +\verbatim +general XML format: + + -dtk --dcmtk-format + output in DCMTK-specific format (default) + + -nat --native-format + output in Native DICOM Model format (part 19) + + +Xn --use-xml-namespace + add XML namespace declaration to root element + +DCMTK-specific format (not with --native-format): + + +Xd --add-dtd-reference + add reference to document type definition (DTD) + + +Xe --embed-dtd-content + embed document type definition into XML document + + +Xf --use-dtd-file [f]ilename: string + use specified DTD file (only with +Xe) + (default: /usr/local/share/dcmtk/dcm2xml.dtd) + + +Wn --write-element-name + write name of the DICOM data elements (default) + + -Wn --no-element-name + do not write name of the DICOM data elements + + +Wb --write-binary-data + write binary data of OB and OW elements + (default: off, be careful with --load-all) + +encoding of binary data: + + +Eh --encode-hex + encode binary data as hex numbers + (default for DCMTK-specific format) + + +Eu --encode-uuid + encode binary data as a UUID reference + (default for Native DICOM Model) + + +Eb --encode-base64 + encode binary data as Base64 (RFC 2045, MIME) +\endverbatim + +\section dcmtk_format DCMTK Format + +The basic structure of the DCMTK-specific XML output created from a DICOM file +looks like the following: + +\verbatim + + + + + + 166 + + ... + + OFFIS_DCMTK_353 + + + + + ISO_IR 100 + + ... + + + + 256\\0\\8 + + ... + + ... + + ... + + + + +\endverbatim + +The "file-format" and "meta-header" tags are absent for DICOM data sets. + +\subsection xml_encoding XML Encoding + +Attributes with very large value fields (e.g. pixel data) are not loaded by +default. They can be identified by the additional attribute "loaded" with a +value of "no" (see example above). The command line option \e --load-all +forces to load all value fields including the very long ones. + +Furthermore, binary information of OB and OW attributes are not written to the +XML output file by default. These elements can be identified by the +additional attribute "binary" with a value of "hidden" (default is "no"). The +command line option \e --write-binary-data causes also binary value fields to +be printed (attribute value is "yes" or "base64"). But, be careful when using +this option together with \e --load-all because of the large amounts of pixel +data that might be printed to the output. Please note that in this context +element values with a VR of OD or OF are not regarded as "binary information". + +Multiple values (i.e. where the DICOM value multiplicity is greater than 1) +are separated by a backslash "\" (except for Base64 encoded data). The "len" +attribute indicates the number of bytes for the particular value field as +stored in the DICOM data set, i.e. it might deviate from the XML encoded value +length e.g. because of non-significant padding that has been removed. If this +attribute is missing in "sequence" or "item" start tags, the corresponding +DICOM element has been stored with undefined length. + +\section native_format Native DICOM Model Format + +The description of the Native DICOM Model format can be found in the DICOM +standard, part 19 ("Application Hosting"). + +\subsection bulk_data Bulk Data + +Binary data, i.e. DICOM element values with Value Representations (VR) of OB +or OW, as well as OD, OF and UN values are by default not written to the XML +output because of their size. Instead, for each element, a new Universally +Unique Identifier (UUID) is being generated and written as an attribute of a +\ XML element. So far, there is no possibility to write an +additional file to hold the binary data for each of the binary data chunks. +This is not required by the standard, however, it might be useful for +implementing an Application Hosting interface; thus this feature may be +available in future versions of \b dcm2xml. + +In addition, Supplement 163 (Store Over the Web by Representational State +Transfer Services) introduces a new \ XML element that allows +for encoding binary data as Base64. Currently, the command line option +\e --encode-base64 enables this encoding for the following VRs: OB, OD, OF, OW, +and UN. + +\subsection known_issues Known Issues + +In addition to what is written in the above section on "Bulk Data", there are +further known issues with the current implementation of the Native DICOM Model +format. For example, large element values with a VR other than OB, OD, OF, OW +or UN are currently never written as bulk data, although it might be useful, +e.g. for very long text elements (especially UT) or very long numeric fields +(of various VRs). + +\section notes NOTES + +\subsection character_encoding Character Encoding + +The XML encoding is determined automatically from the DICOM attribute +(0008,0005) "Specific Character Set" using the following mapping: + +\verbatim +ASCII (ISO_IR 6) => "UTF-8" +UTF-8 "ISO_IR 192" => "UTF-8" +ISO Latin 1 "ISO_IR 100" => "ISO-8859-1" +ISO Latin 2 "ISO_IR 101" => "ISO-8859-2" +ISO Latin 3 "ISO_IR 109" => "ISO-8859-3" +ISO Latin 4 "ISO_IR 110" => "ISO-8859-4" +ISO Latin 5 "ISO_IR 148" => "ISO-8859-9" +Cyrillic "ISO_IR 144" => "ISO-8859-5" +Arabic "ISO_IR 127" => "ISO-8859-6" +Greek "ISO_IR 126" => "ISO-8859-7" +Hebrew "ISO_IR 138" => "ISO-8859-8" +\endverbatim + +If this DICOM attribute is missing in the input file, although needed, option +\e --charset-assume can be used to specify an appropriate character set +manually (using one of the DICOM defined terms). + +Multiple character sets using code extension techniques are not supported. If +needed, option \e --convert-to-utf8 can be used to convert the DICOM file or +data set to UTF-8 encoding prior to the conversion to XML format. This is also +useful for DICOMDIR files where each directory record can have a different +character set. + +\section logging LOGGING + +The level of logging output of the various command line tools and underlying +libraries can be specified by the user. By default, only errors and warnings +are written to the standard error stream. Using option \e --verbose also +informational messages like processing details are reported. Option +\e --debug can be used to get more details on the internal activity, e.g. for +debugging purposes. Other logging levels can be selected using option +\e --log-level. In \e --quiet mode only fatal errors are reported. In such +very severe error events, the application will usually terminate. For more +details on the different logging levels, see documentation of module "oflog". + +In case the logging output should be written to file (optionally with logfile +rotation), to syslog (Unix) or the event log (Windows) option \e --log-config +can be used. This configuration file also allows for directing only certain +messages to a particular output stream and for filtering certain messages +based on the module or application where they are generated. An example +configuration file is provided in \/logger.cfg. + +\section command_line COMMAND LINE + +All command line tools use the following notation for parameters: square +brackets enclose optional values (0-1), three trailing dots indicate that +multiple values are allowed (1-n), a combination of both means 0 to n values. + +Command line options are distinguished from parameters by a leading '+' or '-' +sign, respectively. Usually, order and position of command line options are +arbitrary (i.e. they can appear anywhere). However, if options are mutually +exclusive the rightmost appearance is used. This behavior conforms to the +standard evaluation rules of common Unix shells. + +In addition, one or more command files can be specified using an '@' sign as a +prefix to the filename (e.g. \@command.txt). Such a command argument +is replaced by the content of the corresponding text file (multiple +whitespaces are treated as a single separator unless they appear between two +quotation marks) prior to any further evaluation. Please note that a command +file cannot contain another command file. This simple but effective approach +allows one to summarize common combinations of options/parameters and avoids +longish and confusing command lines (an example is provided in file +\/dumppat.txt). + +\section environment ENVIRONMENT + +The \b dcm2xml utility will attempt to load DICOM data dictionaries specified +in the \e DCMDICTPATH environment variable. By default, i.e. if the +\e DCMDICTPATH environment variable is not set, the file +\/dicom.dic will be loaded unless the dictionary is built +into the application (default for Windows). + +The default behavior should be preferred and the \e DCMDICTPATH environment +variable only used when alternative data dictionaries are required. The +\e DCMDICTPATH environment variable has the same format as the Unix shell +\e PATH variable in that a colon (":") separates entries. On Windows systems, +a semicolon (";") is used as a separator. The data dictionary code will +attempt to load each file specified in the \e DCMDICTPATH environment variable. +It is an error if no data dictionary can be loaded. + +\section files FILES + +\/dcm2xml.dtd - Document Type Definition (DTD) file + +\section see_also SEE ALSO + +xml2dcm(1), dcmconv(1) + +\section copyright COPYRIGHT + +Copyright (C) 2002-2014 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany. + +*/ diff --git a/dcmdata/docs/dcmconv.man b/dcmdata/docs/dcmconv.man new file mode 100644 index 00000000..f57557f4 --- /dev/null +++ b/dcmdata/docs/dcmconv.man @@ -0,0 +1,363 @@ +/*! + +\if MANPAGES +\page dcmconv Convert DICOM file encoding +\else +\page dcmconv dcmconv: Convert DICOM file encoding +\endif + +\section synopsis SYNOPSIS + +\verbatim +dcmconv [options] dcmfile-in dcmfile-out +\endverbatim + +\section description DESCRIPTION + +The \b dcmconv utility reads a DICOM file (\e dcmfile-in), performs an encoding +conversion and writes the converted data to an output file (\e dcmfile-out). + +\section parameters PARAMETERS + +\verbatim +dcmfile-in DICOM input filename to be converted + +dcmfile-out DICOM output filename to write to +\endverbatim + +\section options OPTIONS + +\subsection general_options general options +\verbatim + -h --help + print this help text and exit + + --version + print version information and exit + + --arguments + print expanded command line arguments + + -q --quiet + quiet mode, print no warnings and errors + + -v --verbose + verbose mode, print processing details + + -d --debug + debug mode, print debug information + + -l --log-level [l]evel: string constant + (fatal, error, warn, info, debug, trace) + use level l for the logger + + -l --log-config [f]ilename: string + use config file f for the logger +\endverbatim + +\subsection input_options input options +\verbatim +input file format: + + +f --read-file + read file format or data set (default) + + +fo --read-file-only + read file format only + + -f --read-dataset + read data set without file meta information + +input transfer syntax: + + -t= --read-xfer-auto + use TS recognition (default) + + -td --read-xfer-detect + ignore TS specified in the file meta header + + -te --read-xfer-little + read with explicit VR little endian TS + + -tb --read-xfer-big + read with explicit VR big endian TS + + -ti --read-xfer-implicit + read with implicit VR little endian TS + +parsing of file meta information: + + +ml --use-meta-length + use file meta information group length (default) + + -ml --ignore-meta-length + ignore file meta information group length + +parsing of odd-length attributes: + + +ao --accept-odd-length + accept odd length attributes (default) + + +ae --assume-even-length + assume real length is one byte larger + +handling of explicit VR: + + +ev --use-explicit-vr + use explicit VR from dataset (default) + + -ev --ignore-explicit-vr + ignore explicit VR (prefer data dictionary) + +handling of non-standard VR: + + +vr --treat-as-unknown + treat non-standard VR as unknown (default) + + -vr --assume-implicit + try to read with implicit VR little endian TS + +handling of undefined length UN elements: + + +ui --enable-cp246 + read undefined len UN as implicit VR (default) + + -ui --disable-cp246 + read undefined len UN as explicit VR + +handling of defined length UN elements: + + -uc --retain-un + retain elements as UN (default) + + +uc --convert-un + convert to real VR if known + +handling of private max-length elements (implicit VR): + + -sq --maxlength-dict + read as defined in dictionary (default) + + +sq --maxlength-seq + read as sequence with undefined length + +handling of wrong delimitation items: + + -rd --use-delim-items + use delimitation items from dataset (default) + + +rd --replace-wrong-delim + replace wrong sequence/item delimitation items + +general handling of parser errors: + + +Ep --ignore-parse-errors + try to recover from parse errors + + -Ep --handle-parse-errors + handle parse errors and stop parsing (default) + +other parsing options: + + +st --stop-after-elem [t]ag: "gggg,eeee" or dictionary name + stop parsing after element specified by t + +automatic data correction: + + +dc --enable-correction + enable automatic data correction (default) + + -dc --disable-correction + disable automatic data correction + +bitstream format of deflated input: + + +bd --bitstream-deflated + expect deflated bitstream (default) + + +bz --bitstream-zlib + expect deflated zlib bitstream +\endverbatim + +\subsection processing_options processing options +\verbatim +specific character set: + + # the following options require support from the libiconv toolkit + + +U8 --convert-to-utf8 + convert all element values that are affected + by Specific Character Set (0008,0005) to UTF-8 + + +L1 --convert-to-latin1 + convert affected element values to ISO 8859-1 + + +A7 --convert-to-ascii + convert affected element values to 7-bit ASCII + + +C --convert-to-charset [c]harset: string + convert affected element values to the character + set specified by the DICOM defined term c + + -Ct --transliterate + try to approximate characters that cannot be + represented through similar looking characters + + -Cd --discard-illegal + discard characters that cannot be represented + in destination character set + +other processing options: + + -ig --no-invalid-groups + remove elements with invalid group number +\endverbatim + +\subsection output_options output options +\verbatim +output file format: + + +F --write-file + write file format (default) + + +Fm --write-new-meta-info + write file format with new meta information + + -F --write-dataset + write data set without file meta information + +output transfer syntax: + + +t= --write-xfer-same + write with same TS as input (default) + + +te --write-xfer-little + write with explicit VR little endian TS + + +tb --write-xfer-big + write with explicit VR big endian TS + + +ti --write-xfer-implicit + write with implicit VR little endian TS + + +td --write-xfer-deflated + write with deflated explicit VR little endian TS + +post-1993 value representations: + + +u --enable-new-vr + enable support for new VRs (UN/UT) (default) + + -u --disable-new-vr + disable support for new VRs, convert to OB + +group length encoding: + + +g= --group-length-recalc + recalculate group lengths if present (default) + + +g --group-length-create + always write with group length elements + + -g --group-length-remove + always write without group length elements + +length encoding in sequences and items: + + +e --length-explicit + write with explicit lengths (default) + + -e --length-undefined + write with undefined lengths + + +eo --write-oversized + write oversized explicit length sequences + and items with undefined length (default) + + -eo --abort-oversized + abort on oversized explicit sequences/items + +data set trailing padding (not with --write-dataset): + + -p= --padding-retain + do not change padding (default if not --write-dataset) + + -p --padding-off + no padding (implicit if --write-dataset) + + +p --padding-create [f]ile-pad [i]tem-pad: integer + align file on multiple of f bytes + and items on multiple of i bytes + +deflate compression level (only with --write-xfer-deflated): + + +cl --compression-level [l]evel: integer (default: 6) + 0=uncompressed, 1=fastest, 9=best compression +\endverbatim + +\section logging LOGGING + +The level of logging output of the various command line tools and underlying +libraries can be specified by the user. By default, only errors and warnings +are written to the standard error stream. Using option \e --verbose also +informational messages like processing details are reported. Option +\e --debug can be used to get more details on the internal activity, e.g. for +debugging purposes. Other logging levels can be selected using option +\e --log-level. In \e --quiet mode only fatal errors are reported. In such +very severe error events, the application will usually terminate. For more +details on the different logging levels, see documentation of module "oflog". + +In case the logging output should be written to file (optionally with logfile +rotation), to syslog (Unix) or the event log (Windows) option \e --log-config +can be used. This configuration file also allows for directing only certain +messages to a particular output stream and for filtering certain messages +based on the module or application where they are generated. An example +configuration file is provided in \/logger.cfg. + +\section command_line COMMAND LINE + +All command line tools use the following notation for parameters: square +brackets enclose optional values (0-1), three trailing dots indicate that +multiple values are allowed (1-n), a combination of both means 0 to n values. + +Command line options are distinguished from parameters by a leading '+' or '-' +sign, respectively. Usually, order and position of command line options are +arbitrary (i.e. they can appear anywhere). However, if options are mutually +exclusive the rightmost appearance is used. This behavior conforms to the +standard evaluation rules of common Unix shells. + +In addition, one or more command files can be specified using an '@' sign as a +prefix to the filename (e.g. \@command.txt). Such a command argument +is replaced by the content of the corresponding text file (multiple +whitespaces are treated as a single separator unless they appear between two +quotation marks) prior to any further evaluation. Please note that a command +file cannot contain another command file. This simple but effective approach +allows one to summarize common combinations of options/parameters and avoids +longish and confusing command lines (an example is provided in file +\/dumppat.txt). + +\section environment ENVIRONMENT + +The \b dcmconv utility will attempt to load DICOM data dictionaries specified +in the \e DCMDICTPATH environment variable. By default, i.e. if the +\e DCMDICTPATH environment variable is not set, the file +\/dicom.dic will be loaded unless the dictionary is built +into the application (default for Windows). + +The default behavior should be preferred and the \e DCMDICTPATH environment +variable only used when alternative data dictionaries are required. The +\e DCMDICTPATH environment variable has the same format as the Unix shell +\e PATH variable in that a colon (":") separates entries. On Windows systems, +a semicolon (";") is used as a separator. The data dictionary code will +attempt to load each file specified in the \e DCMDICTPATH environment variable. +It is an error if no data dictionary can be loaded. + +\section see_also SEE ALSO + +dcmdump(1) + +\section copyright COPYRIGHT + +Copyright (C) 1994-2014 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany. + +*/ diff --git a/dcmdata/docs/dcmcrle.man b/dcmdata/docs/dcmcrle.man new file mode 100644 index 00000000..09b749c6 --- /dev/null +++ b/dcmdata/docs/dcmcrle.man @@ -0,0 +1,259 @@ +/*! + +\if MANPAGES +\page dcmcrle Encode DICOM file to RLE transfer syntax +\else +\page dcmcrle dcmcrle: Encode DICOM file to RLE transfer syntax +\endif + +\section synopsis SYNOPSIS + +\verbatim +dcmcrle [options] dcmfile-in dcmfile-out +\endverbatim + +\section description DESCRIPTION + +The \b dcmcrle utility reads an uncompressed DICOM image (\e dcmfile-in), +performs RLE compression (i.e. conversion to an encapsulated DICOM transfer +syntax) and writes the converted image to an output file (\e dcmfile-out). + +\section parameters PARAMETERS + +\verbatim +dcmfile-in DICOM input filename to be converted + +dcmfile-out DICOM output filename +\endverbatim + +\section options OPTIONS + +\subsection general_options general options +\verbatim + -h --help + print this help text and exit + + --version + print version information and exit + + --arguments + print expanded command line arguments + + -q --quiet + quiet mode, print no warnings and errors + + -v --verbose + verbose mode, print processing details + + -d --debug + debug mode, print debug information + + -ll --log-level [l]evel: string constant + (fatal, error, warn, info, debug, trace) + use level l for the logger + + -lc --log-config [f]ilename: string + use config file f for the logger +\endverbatim + +\subsection input_options input options +\verbatim +input file format: + + +f --read-file + read file format or data set (default) + + +fo --read-file-only + read file format only + + -f --read-dataset + read data set without file meta information + +input transfer syntax: + + -t= --read-xfer-auto + use TS recognition (default) + + -td --read-xfer-detect + ignore TS specified in the file meta header + + -te --read-xfer-little + read with explicit VR little endian TS + + -tb --read-xfer-big + read with explicit VR big endian TS + + -ti --read-xfer-implicit + read with implicit VR little endian TS +\endverbatim + +\subsection enc_pix_data_encoding_opt encapsulated pixel data encoding options +\verbatim +pixel data fragmentation: + + +ff --fragment-per-frame + encode each frame as one fragment (default) + + +fs --fragment-size [s]ize: integer + limit fragment size to s kbytes (non-standard) + +basic offset table encoding: + + +ot --offset-table-create + create offset table (default) + + -ot --offset-table-empty + leave offset table empty + +SOP Class UID: + + +cd --class-default + keep SOP Class UID (default) + + +cs --class-sc + convert to Secondary Capture Image (implies --uid-always) + +SOP Instance UID: + +un --uid-never + never assign new UID (default) + + +ua --uid-always + always assign new UID +\endverbatim + +\subsection output_options output options +\verbatim +post-1993 value representations: + + +u --enable-new-vr + enable support for new VRs (UN/UT) (default) + + -u --disable-new-vr + disable support for new VRs, convert to OB + +group length encoding: + + +g= --group-length-recalc + recalculate group lengths if present (default) + + +g --group-length-create + always write with group length elements + + -g --group-length-remove + always write without group length elements + +length encoding in sequences and items: + + +e --length-explicit + write with explicit lengths (default) + + -e --length-undefined + write with undefined lengths + +data set trailing padding: + + -p= --padding-retain + do not change padding (default) + + -p --padding-off + no padding + + +p --padding-create [f]ile-pad [i]tem-pad: integer + align file on multiple of f bytes + and items on multiple of i bytes +\endverbatim + +\section notes NOTES + +Please note that the DICOM standard does not allow for storing the pixel data +with multiple fragments per frame (when RLE compression is used). So limiting +the fragment size with option \e --fragment-size (or \e +fs) may result in a +non-standard conformant DICOM image. + +\section transfer_syntaxes TRANSFER SYNTAXES + +\b dcmcrle supports the following transfer syntaxes for input +(\e dcmfile-in): + +\verbatim +LittleEndianImplicitTransferSyntax 1.2.840.10008.1.2 +LittleEndianExplicitTransferSyntax 1.2.840.10008.1.2.1 +DeflatedExplicitVRLittleEndianTransferSyntax 1.2.840.10008.1.2.1.99 (*) +BigEndianExplicitTransferSyntax 1.2.840.10008.1.2.2 +\endverbatim + +(*) if compiled with zlib support enabled + +\b dcmcrle supports the following transfer syntaxes for output +(\e dcmfile-out): + +\verbatim +RLELosslessTransferSyntax 1.2.840.10008.1.2.5 +\endverbatim + +\section logging LOGGING + +The level of logging output of the various command line tools and underlying +libraries can be specified by the user. By default, only errors and warnings +are written to the standard error stream. Using option \e --verbose also +informational messages like processing details are reported. Option +\e --debug can be used to get more details on the internal activity, e.g. for +debugging purposes. Other logging levels can be selected using option +\e --log-level. In \e --quiet mode only fatal errors are reported. In such +very severe error events, the application will usually terminate. For more +details on the different logging levels, see documentation of module "oflog". + +In case the logging output should be written to file (optionally with logfile +rotation), to syslog (Unix) or the event log (Windows) option \e --log-config +can be used. This configuration file also allows for directing only certain +messages to a particular output stream and for filtering certain messages +based on the module or application where they are generated. An example +configuration file is provided in \/logger.cfg. + +\section command_line COMMAND LINE + +All command line tools use the following notation for parameters: square +brackets enclose optional values (0-1), three trailing dots indicate that +multiple values are allowed (1-n), a combination of both means 0 to n values. + +Command line options are distinguished from parameters by a leading '+' or '-' +sign, respectively. Usually, order and position of command line options are +arbitrary (i.e. they can appear anywhere). However, if options are mutually +exclusive the rightmost appearance is used. This behavior conforms to the +standard evaluation rules of common Unix shells. + +In addition, one or more command files can be specified using an '@' sign as a +prefix to the filename (e.g. \@command.txt). Such a command argument +is replaced by the content of the corresponding text file (multiple +whitespaces are treated as a single separator unless they appear between two +quotation marks) prior to any further evaluation. Please note that a command +file cannot contain another command file. This simple but effective approach +allows one to summarize common combinations of options/parameters and avoids +longish and confusing command lines (an example is provided in file +\/dumppat.txt). + +\section environment ENVIRONMENT + +The \b dcmcrle utility will attempt to load DICOM data dictionaries specified +in the \e DCMDICTPATH environment variable. By default, i.e. if the +\e DCMDICTPATH environment variable is not set, the file +\/dicom.dic will be loaded unless the dictionary is built +into the application (default for Windows). + +The default behavior should be preferred and the \e DCMDICTPATH environment +variable only used when alternative data dictionaries are required. The +\e DCMDICTPATH environment variable has the same format as the Unix shell +\e PATH variable in that a colon (":") separates entries. On Windows systems, +a semicolon (";") is used as a separator. The data dictionary code will +attempt to load each file specified in the \e DCMDICTPATH environment variable. +It is an error if no data dictionary can be loaded. + +\section see_also SEE ALSO + +dcmdrle(1) + +\section copyright COPYRIGHT + +Copyright (C) 2002-2014 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany. + +*/ diff --git a/dcmdata/docs/dcmdata.dox b/dcmdata/docs/dcmdata.dox new file mode 100644 index 00000000..dbf84a05 --- /dev/null +++ b/dcmdata/docs/dcmdata.dox @@ -0,0 +1,97 @@ +/*! + +\page mod_dcmdata dcmdata: a data encoding/decoding library and utility apps + +This module contains classes to manage DICOM data structures and files. It +also provides support for DICOMDIR files as required for DICOM storage media. + +The main interface classes are: +\li \b DcmFileFormat +\li \b DcmDataset +\li \b DcmItem +\li \b DcmElement + +Here are some further classes that are of interest: +\li \b DcmTag +\li \b DcmTagKey +\li \b DicomDirInterface + +\section Tools + +This module contains the following command line tools: +\li \ref dcm2pdf +\li \ref dcm2xml +\li \ref dcmconv +\li \ref dcmcrle +\li \ref dcmdrle +\li \ref dcmdump +\li \ref dcmftest +\li \ref dcmgpdir +\li \ref dcmodify +\li \ref dump2dcm +\li \ref img2dcm +\li \ref pdf2dcm +\li \ref xml2dcm + +\section Files + +The following file provides further documentation: +\li \ref file_datadict + +\section Examples + +The following example shows how to load a DICOM file and output the patient's name: + +\code +DcmFileFormat fileformat; +OFCondition status = fileformat.loadFile("test.dcm"); +if (status.good()) +{ + OFString patientName; + if (fileformat.getDataset()->findAndGetOFString(DCM_PatientName, patientName).good()) + { + cout << "Patient's Name: " << patientName << endl; + } else + cerr << "Error: cannot access Patient's Name!" << endl; +} else + cerr << "Error: cannot read DICOM file (" << status.text() << ")" << endl; +\endcode + +The following example shows how to create a DICOM dataset and save it to a file: + +\code +char uid[100]; +DcmFileFormat fileformat; +DcmDataset *dataset = fileformat.getDataset(); +dataset->putAndInsertString(DCM_SOPClassUID, UID_SecondaryCaptureImageStorage); +dataset->putAndInsertString(DCM_SOPInstanceUID, dcmGenerateUniqueIdentifier(uid, SITE_INSTANCE_UID_ROOT)); +dataset->putAndInsertString(DCM_PatientName, "Doe^John"); +/* ... */ +dataset->putAndInsertUint8Array(DCM_PixelData, pixelData, pixelLength); +OFCondition status = fileformat.saveFile("test.dcm", EXS_LittleEndianExplicit); +if (status.bad()) + cerr << "Error: cannot write DICOM file (" << status.text() << ")" << endl; +\endcode + +The following example shows how to create a general purpose DICOMDIR from multiple files: + +\code +DicomDirInterface dicomdir; +OFCondition status = dicomdir.createNewDicomDir(); +if (status.good()) +{ + while ( /* there are files */ ) + dicomdir.addDicomFile( /* current filename */ ); + status = dicomdir.writeDicomDir(); + if (status.bad()) + cerr << "Error: cannot write DICOMDIR (" << status.text() << ")" << endl; +} else + cerr << "Error: cannot create DICOMDIR (" << status.text() << ")" << endl; +\endcode + +*/ + +/*! + \page file_datadict datadict.txt file + \verbinclude datadict.txt +*/ diff --git a/dcmdata/docs/dcmdrle.man b/dcmdata/docs/dcmdrle.man new file mode 100644 index 00000000..e884f0bd --- /dev/null +++ b/dcmdata/docs/dcmdrle.man @@ -0,0 +1,252 @@ +/*! + +\if MANPAGES +\page dcmdrle Decode RLE-compressed DICOM file +\else +\page dcmdrle dcmdrle: Decode RLE-compressed DICOM file +\endif + +\section synopsis SYNOPSIS + +\verbatim +dcmdrle [options] dcmfile-in dcmfile-out +\endverbatim + +\section description DESCRIPTION + +The \b dcmdrle utility reads a RLE-compressed DICOM image (\e dcmfile-in), +decompresses the image data (i.e. conversion to a native DICOM transfer syntax) +and writes the converted image to an output file (\e dcmfile-out). + +\section parameters PARAMETERS + +\verbatim +dcmfile-in DICOM input filename to be converted + +dcmfile-out DICOM output filename +\endverbatim + +\section options OPTIONS + +\subsection general_options general options +\verbatim + -h --help + print this help text and exit + + --version + print version information and exit + + --arguments + print expanded command line arguments + + -q --quiet + quiet mode, print no warnings and errors + + -v --verbose + verbose mode, print processing details + + -d --debug + debug mode, print debug information + + -ll --log-level [l]evel: string constant + (fatal, error, warn, info, debug, trace) + use level l for the logger + + -lc --log-config [f]ilename: string + use config file f for the logger +\endverbatim + +\subsection input_options input options + +\verbatim +input file format: + + +f --read-file + read file format or data set (default) + + +fo --read-file-only + read file format only + + -f --read-dataset + read data set without file meta information + + # This option allows one to decompress RLE compressed DICOM objects that have + # been stored as dataset without meta-header. Such a thing should not exist + # since the transfer syntax cannot be reliably determined without meta-header, + # but unfortunately it does. +\endverbatim + +\subsection processing_options processing options +\verbatim +SOP Instance UID: + + +ud --uid-default + keep same SOP Instance UID (default) + + +ua --uid-always + always assign new UID + +RLE byte segment order: + + +bd --byte-order-default + most significant byte first (default) + + +br --byte-order-reverse + least significant byte first + + # This option allows one to decompress RLE compressed DICOM files in which + # the order of byte segments is encoded in incorrect order. This only affects + # images with more than one byte per sample. +\endverbatim + +\subsection output_options output options +\verbatim +output file format: + + +F --write-file + write file format (default) + + -F --write-dataset + write data set without file meta information + +output transfer syntax: + + +te --write-xfer-little + write with explicit VR little endian (default) + + +tb --write-xfer-big + write with explicit VR big endian TS + + +ti --write-xfer-implicit + write with implicit VR little endian TS + +post-1993 value representations: + + +u --enable-new-vr + enable support for new VRs (UN/UT) (default) + + -u --disable-new-vr + disable support for new VRs, convert to OB + +group length encoding: + + +g= --group-length-recalc + recalculate group lengths if present (default) + + +g --group-length-create + always write with group length elements + + -g --group-length-remove + always write without group length elements + +length encoding in sequences and items: + + +e --length-explicit + write with explicit lengths (default) + + -e --length-undefined + write with undefined lengths + +data set trailing padding (not with --write-dataset): + + -p= --padding-retain + do not change padding (default if not --write-dataset) + + -p --padding-off + no padding (implicit if --write-dataset) + + +p --padding-create [f]ile-pad [i]tem-pad: integer + align file on multiple of f bytes + and items on multiple of i bytes +\endverbatim + +\section transfer_syntaxes TRANSFER SYNTAXES + +\b dcmdrle supports the following transfer syntaxes for input +(\e dcmfile-in): + +\verbatim +LittleEndianImplicitTransferSyntax 1.2.840.10008.1.2 +LittleEndianExplicitTransferSyntax 1.2.840.10008.1.2.1 +DeflatedExplicitVRLittleEndianTransferSyntax 1.2.840.10008.1.2.1.99 (*) +BigEndianExplicitTransferSyntax 1.2.840.10008.1.2.2 +RLELosslessTransferSyntax 1.2.840.10008.1.2.5 +\endverbatim + +(*) if compiled with zlib support enabled + +\b dcmdrle supports the following transfer syntaxes for output +(\e dcmfile-out): + +\verbatim +LittleEndianImplicitTransferSyntax 1.2.840.10008.1.2 +LittleEndianExplicitTransferSyntax 1.2.840.10008.1.2.1 +BigEndianExplicitTransferSyntax 1.2.840.10008.1.2.2 +\endverbatim + +\section logging LOGGING + +The level of logging output of the various command line tools and underlying +libraries can be specified by the user. By default, only errors and warnings +are written to the standard error stream. Using option \e --verbose also +informational messages like processing details are reported. Option +\e --debug can be used to get more details on the internal activity, e.g. for +debugging purposes. Other logging levels can be selected using option +\e --log-level. In \e --quiet mode only fatal errors are reported. In such +very severe error events, the application will usually terminate. For more +details on the different logging levels, see documentation of module "oflog". + +In case the logging output should be written to file (optionally with logfile +rotation), to syslog (Unix) or the event log (Windows) option \e --log-config +can be used. This configuration file also allows for directing only certain +messages to a particular output stream and for filtering certain messages +based on the module or application where they are generated. An example +configuration file is provided in \/logger.cfg. + +\section command_line COMMAND LINE + +All command line tools use the following notation for parameters: square +brackets enclose optional values (0-1), three trailing dots indicate that +multiple values are allowed (1-n), a combination of both means 0 to n values. + +Command line options are distinguished from parameters by a leading '+' or '-' +sign, respectively. Usually, order and position of command line options are +arbitrary (i.e. they can appear anywhere). However, if options are mutually +exclusive the rightmost appearance is used. This behavior conforms to the +standard evaluation rules of common Unix shells. + +In addition, one or more command files can be specified using an '@' sign as a +prefix to the filename (e.g. \@command.txt). Such a command argument +is replaced by the content of the corresponding text file (multiple +whitespaces are treated as a single separator unless they appear between two +quotation marks) prior to any further evaluation. Please note that a command +file cannot contain another command file. This simple but effective approach +allows one to summarize common combinations of options/parameters and avoids +longish and confusing command lines (an example is provided in file +\/dumppat.txt). + +\section environment ENVIRONMENT + +The \b dcmdrle utility will attempt to load DICOM data dictionaries specified +in the \e DCMDICTPATH environment variable. By default, i.e. if the +\e DCMDICTPATH environment variable is not set, the file +\/dicom.dic will be loaded unless the dictionary is built +into the application (default for Windows). + +The default behavior should be preferred and the \e DCMDICTPATH environment +variable only used when alternative data dictionaries are required. The +\e DCMDICTPATH environment variable has the same format as the Unix shell +\e PATH variable in that a colon (":") separates entries. On Windows systems, +a semicolon (";") is used as a separator. The data dictionary code will +attempt to load each file specified in the \e DCMDICTPATH environment variable. +It is an error if no data dictionary can be loaded. + +\section see_also SEE ALSO + +dcmcrle(1) + +\section copyright COPYRIGHT + +Copyright (C) 2002-2014 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany + +*/ diff --git a/dcmdata/docs/dcmdump.man b/dcmdata/docs/dcmdump.man new file mode 100644 index 00000000..cead41c4 --- /dev/null +++ b/dcmdata/docs/dcmdump.man @@ -0,0 +1,397 @@ +/*! + +\if MANPAGES +\page dcmdump Dump DICOM file and data set +\else +\page dcmdump dcmdump: Dump DICOM file and data set +\endif + +\section synopsis SYNOPSIS + +\verbatim +dcmdump [options] dcmfile-in... +\endverbatim + +\section description DESCRIPTION + +The \b dcmdump utility dumps the contents of a DICOM file (file format or raw +data set) to stdout in textual form. Attributes with very large value fields +(e.g. pixel data) can be described as "(not loaded)". String value fields +will be delimited with square brackets ([]). Known UIDs will be displayed by +their names prefixed by an equals sign (e.g. "=MRImageStorage") unless this +mapping would be explicitly switched off. Empty value fields are described as +"(no value available)". + +If \b dcmdump reads a raw data set (DICOM data without a file format +meta-header) it will attempt to guess the transfer syntax by examining the +first few bytes of the file. It is not always possible to correctly guess the +transfer syntax and it is better to convert a data set to a file format +whenever possible (using the \b dcmconv utility). It is also possible to use +the \e -f and -t[ieb] options to force \b dcmdump to read a dataset +with a particular transfer syntax. + +\section parameters PARAMETERS + +\verbatim +dcmfile-in DICOM input file or directory to be dumped +\endverbatim + +\section options OPTIONS + +\subsection general_options general options +\verbatim + -h --help + print this help text and exit + + --version + print version information and exit + + --arguments + print expanded command line arguments + + -q --quiet + quiet mode, print no warnings and errors + + -v --verbose + verbose mode, print processing details + + -d --debug + debug mode, print debug information + + -ll --log-level [l]evel: string constant + (fatal, error, warn, info, debug, trace) + use level l for the logger + + -lc --log-config [f]ilename: string + use config file f for the logger +\endverbatim + +\subsection input_options input options +\verbatim +input file format: + + +f --read-file + read file format or data set (default) + + +fo --read-file-only + read file format only + + -f --read-dataset + read data set without file meta information + +input transfer syntax: + + -t= --read-xfer-auto + use TS recognition (default) + + -td --read-xfer-detect + ignore TS specified in the file meta header + + -te --read-xfer-little + read with explicit VR little endian TS + + -tb --read-xfer-big + read with explicit VR big endian TS + + -ti --read-xfer-implicit + read with implicit VR little endian TS + +input files: + + +sd --scan-directories + scan directories for input files (dcmfile-in) + + +sp --scan-pattern [p]attern: string (only with --scan-directories) + pattern for filename matching (wildcards) + + # possibly not available on all systems + + -r --no-recurse + do not recurse within directories (default) + + +r --recurse + recurse within specified directories + +long tag values: + + +M --load-all + load very long tag values (default) + + -M --load-short + do not load very long values (e.g. pixel data) + + +R --max-read-length [k]bytes: integer (4..4194302, default: 4) + set threshold for long values to k kbytes + +parsing of file meta information: + + +ml --use-meta-length + use file meta information group length (default) + + -ml --ignore-meta-length + ignore file meta information group length + +parsing of odd-length attributes: + + +ao --accept-odd-length + accept odd length attributes (default) + + +ae --assume-even-length + assume real length is one byte larger + +handling of explicit VR: + + +ev --use-explicit-vr + use explicit VR from dataset (default) + + -ev --ignore-explicit-vr + ignore explicit VR (prefer data dictionary) + +handling of non-standard VR: + + +vr --treat-as-unknown + treat non-standard VR as unknown (default) + + -vr --assume-implicit + try to read with implicit VR little endian TS + +handling of undefined length UN elements: + + +ui --enable-cp246 + read undefined len UN as implicit VR (default) + + -ui --disable-cp246 + read undefined len UN as explicit VR + +handling of defined length UN elements: + + -uc --retain-un + retain elements as UN (default) + + +uc --convert-un + convert to real VR if known + +handling of private max-length elements (implicit VR): + + -sq --maxlength-dict + read as defined in dictionary (default) + + +sq --maxlength-seq + read as sequence with undefined length + +handling of wrong delimitation items: + + -rd --use-delim-items + use delimitation items from dataset (default) + + +rd --replace-wrong-delim + replace wrong sequence/item delimitation items + +general handling of parser errors: + + +Ep --ignore-parse-errors + try to recover from parse errors + + -Ep --handle-parse-errors + handle parse errors and stop parsing (default) + +other parsing options: + + +st --stop-after-elem [t]ag: "gggg,eeee" or dictionary name + stop parsing after element specified by t + +automatic data correction: + + +dc --enable-correction + enable automatic data correction (default) + + -dc --disable-correction + disable automatic data correction + +bitstream format of deflated input: + + +bd --bitstream-deflated + expect deflated bitstream (default) + + +bz --bitstream-zlib + expect deflated zlib bitstream +\endverbatim + +\subsection processing_options processing options +\verbatim +specific character set: + + +U8 --convert-to-utf8 + convert all element values that are affected + by Specific Character Set (0008,0005) to UTF-8 + + # requires support from the libiconv toolkit +\endverbatim + +\subsection output_options output options +\verbatim +printing: + + +L --print-all + print long tag values completely + + -L --print-short + print long tag values shortened (default) + + +T --print-tree + print hierarchical structure as a simple tree + + -T --print-indented + print hierarchical structure indented (default) + + +F --print-filename + print header with filename for each input file + + +Fs --print-file-search + print header with filename only for those input files + that contain one of the searched tags + +mapping: + + +Un --map-uid-names + map well-known UID numbers to names (default) + + -Un --no-uid-names + do not map well-known UID numbers to names + +quoting: + + +Qn --quote-nonascii + quote non-ASCII and control chars as XML markup + + +Qo --quote-as-octal + quote non-ASCII and control chars as octal numbers + + -Qn --print-nonascii + print non-ASCII and control chars (default) + +color: + + +C --print-color + use ANSI escape codes for colored output + + # not available on Windows systems + + -C --no-color + do not use any ANSI escape codes (default) + + # not available on Windows systems + +error handling: + + -E --stop-on-error + do not print if file is damaged (default) + + +E --ignore-errors + attempt to print even if file is damaged + +searching: + + +P --search [t]ag: "gggg,eeee" or dictionary name + print the textual dump of tag t + this option can be specified multiple times + (default: the complete file is printed) + + +s --search-all + print all instances of searched tags (default) + + -s --search-first + only print first instance of searched tags + + +p --prepend + prepend sequence hierarchy to printed tag, + denoted by: (gggg,eeee).(gggg,eeee).* + (only when used with --search) + + -p --no-prepend + do not prepend hierarchy to tag (default) + +writing: + + +W --write-pixel [d]irectory: string + write pixel data to a .raw file stored in d + (little endian, filename created automatically) +\endverbatim + +\section notes NOTES + +Adding directories as a parameter to the command line only makes sense if +option \e --scan-directories is also given. If the files in the provided +directories should be selected according to a specific name pattern (e.g. +using wildcard matching), option \e --scan-pattern has to be used. Please +note that this file pattern only applies to the files within the scanned +directories, and, if any other patterns are specified on the command line +outside the \e --scan-pattern option (e.g. in order to select further +files), these do not apply to the specified directories. + +\section logging LOGGING + +The level of logging output of the various command line tools and underlying +libraries can be specified by the user. By default, only errors and warnings +are written to the standard error stream. Using option \e --verbose also +informational messages like processing details are reported. Option +\e --debug can be used to get more details on the internal activity, e.g. for +debugging purposes. Other logging levels can be selected using option +\e --log-level. In \e --quiet mode only fatal errors are reported. In such +very severe error events, the application will usually terminate. For more +details on the different logging levels, see documentation of module "oflog". + +In case the logging output should be written to file (optionally with logfile +rotation), to syslog (Unix) or the event log (Windows) option \e --log-config +can be used. This configuration file also allows for directing only certain +messages to a particular output stream and for filtering certain messages +based on the module or application where they are generated. An example +configuration file is provided in \/logger.cfg. + +\section command_line COMMAND LINE + +All command line tools use the following notation for parameters: square +brackets enclose optional values (0-1), three trailing dots indicate that +multiple values are allowed (1-n), a combination of both means 0 to n values. + +Command line options are distinguished from parameters by a leading '+' or '-' +sign, respectively. Usually, order and position of command line options are +arbitrary (i.e. they can appear anywhere). However, if options are mutually +exclusive the rightmost appearance is used. This behavior conforms to the +standard evaluation rules of common Unix shells. + +In addition, one or more command files can be specified using an '@' sign as a +prefix to the filename (e.g. \@command.txt). Such a command argument +is replaced by the content of the corresponding text file (multiple +whitespaces are treated as a single separator unless they appear between two +quotation marks) prior to any further evaluation. Please note that a command +file cannot contain another command file. This simple but effective approach +allows one to summarize common combinations of options/parameters and avoids +longish and confusing command lines (an example is provided in file +\/dumppat.txt). + +\section environment ENVIRONMENT + +The \b dcmdump utility will attempt to load DICOM data dictionaries specified +in the \e DCMDICTPATH environment variable. By default, i.e. if the +\e DCMDICTPATH environment variable is not set, the file +\/dicom.dic will be loaded unless the dictionary is built +into the application (default for Windows). + +The default behavior should be preferred and the \e DCMDICTPATH environment +variable only used when alternative data dictionaries are required. The +\e DCMDICTPATH environment variable has the same format as the Unix shell +\e PATH variable in that a colon (":") separates entries. On Windows systems, +a semicolon (";") is used as a separator. The data dictionary code will +attempt to load each file specified in the \e DCMDICTPATH environment variable. +It is an error if no data dictionary can be loaded. + +\section see_also SEE ALSO + +dump2dcm(1), dcmconv(1) + +\section copyright COPYRIGHT + +Copyright (C) 1994-2014 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany. + +*/ diff --git a/dcmdata/docs/dcmftest.man b/dcmdata/docs/dcmftest.man new file mode 100644 index 00000000..c5c3d82a --- /dev/null +++ b/dcmdata/docs/dcmftest.man @@ -0,0 +1,44 @@ +/*! + +\if MANPAGES +\page dcmftest Test if file uses DICOM part 10 format +\else +\page dcmftest dcmftest: Test if file uses DICOM part 10 format +\endif + +\section synopsis SYNOPSIS + +\verbatim +dcmftest file... +\endverbatim + +\section description DESCRIPTION + +The \b dcmftest utility checks whether the files specified on the command line +are DICOM files in part 10 format (with meta-header). + +\section parameters PARAMETERS + +\verbatim +dcmfile-in DICOM input filename to be dumped +\endverbatim + +\section notes NOTES + +All files specified on the command line are checked for the presence of the +DICOM "magic word" 'DICM' at byte position 128. No attempt is made to parse +the complete data set. For each file the test result is printed to \e stdout +in the form "yes: \n" or "no: \n". The utility terminates +with a return code corresponding to the number of files found to be non-DICOM, +i.e. if all files pass as DICOM files, the return value is 0. This behavior +is intended for use in shell script programming. + +\section see_also SEE ALSO + +dcmgpdir(1), dcmmkdir(1) + +\section copyright COPYRIGHT + +Copyright (C) 1997-2014 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany. + +*/ \ No newline at end of file diff --git a/dcmdata/docs/dcmgpdir.man b/dcmdata/docs/dcmgpdir.man new file mode 100644 index 00000000..6c2a671c --- /dev/null +++ b/dcmdata/docs/dcmgpdir.man @@ -0,0 +1,301 @@ +/*! + +\if MANPAGES +\page dcmgpdir Create a general purpose DICOMDIR +\else +\page dcmgpdir dcmgpdir: Create a general purpose DICOMDIR +\endif + +\section synopsis SYNOPSIS + +\verbatim +dcmgpdir [options] [dcmfile-in...] +\endverbatim + +\section description DESCRIPTION + +The \b dcmgpdir utility creates a \e DICOMDIR file from the specified +referenced DICOM files according to the DICOM Part 11 Media Storage +Application Profiles. + +Currently, the following profiles are supported: + +\li General Purpose CD-R Interchange (STD-GEN-CD) +\li General Purpose Interchange on DVD-RAM Media (STD-GEN-DVD-RAM) + +\b dcmmkdir is an extended version of this tool which also supports other +Media Storage Application Profiles than the general purpose one (e.g. both +cardio profiles requiring the use of icon images). + +\section parameters PARAMETERS + +\verbatim +dcmfile-in referenced DICOM file (or directory to be scanned) +\endverbatim + +\section options OPTIONS + +\subsection general_options general options +\verbatim + -h --help + print this help text and exit + + --version + print version information and exit + + --arguments + print expanded command line arguments + + -q --quiet + quiet mode, print no warnings and errors + + -v --verbose + verbose mode, print processing details + + -d --debug + debug mode, print debug information + + -ll --log-level [l]evel: string constant + (fatal, error, warn, info, debug, trace) + use level l for the logger + + -lc --log-config [f]ilename: string + use config file f for the logger +\endverbatim + +\subsection input_options input options +\verbatim +DICOMDIR identifiers: + + +F --fileset-id [i]d: string + use specific file-set ID + (default: DCMTK_MEDIA_DEMO, "" for none) + + +R --descriptor [f]ilename: string + add a file-set descriptor file ID + (e.g. README, default: no descriptor) + + +C --char-set [c]harset: string + add a specific character set for descriptor + (default: "ISO_IR 100" if descriptor present) + +reading: + + +id --input-directory [d]irectory: string + read referenced DICOM files from directory d + (default for --recurse: current directory) + + -m --keep-filenames + expect filenames to be in DICOM format (default) + + +m --map-filenames + map to DICOM filenames (lowercase->uppercase, + and remove trailing period) + + -r --no-recurse + do not recurse within directories (default) + + +r --recurse + recurse within filesystem directories + + +p --pattern [p]attern: string (only with --recurse) + pattern for filename matching (wildcards) + + # possibly not available on all systems +\endverbatim + +\subsection processing_options processing options +\verbatim +consistency check: + + -W --no-consistency-check + do not check files for consistency + + +W --warn-inconsist-files + warn about inconsistent files (default) + + -a --abort-inconsist-file + abort on first inconsistent file + +type 1 attributes: + + -I --strict + exit with error if DICOMDIR type 1 attributes + are missing in DICOM file (default) + + +I --invent + invent DICOMDIR type 1 attributes if missing in DICOM file + + +Ipi --invent-patient-id + invent new PatientID in case of inconsistent + PatientName attributes + +other checks: + + +Nrs --allow-retired-sop + allow retired SOP classes defined in previous editions + of the DICOM standard + + -Nxc --no-xfer-check + do not reject images with non-standard transfer syntax + (just warn) +\endverbatim + +\subsection output_options output options +\verbatim +DICOMDIR file: + + +D --output-file [f]ilename: string + generate specific DICOMDIR file + (default: DICOMDIR in current directory) + +writing: + + -A --replace + replace existing DICOMDIR (default) + + +A --append + append to existing DICOMDIR + + +U --update + update existing DICOMDIR + + -w --discard + do not write out DICOMDIR + +backup: + + --create-backup + create a backup of existing DICOMDIR (default) + + -nb --no-backup + do not create a backup of existing DICOMDIR + +post-1993 value representations: + + +u --enable-new-vr + enable support for new VRs (UN/UT) (default) + + -u --disable-new-vr + disable support for new VRs, convert to OB + +group length encoding: + + -g --group-length-remove + write without group length elements (default) + + +g --group-length-create + write with group length elements + +length encoding in sequences and items: + + +e --length-explicit + write with explicit lengths (default) + + -e --length-undefined + write with undefined lengths +\endverbatim + +\section notes NOTES + +All files specified on the command line (or discovered by recursively examining +the contents of directories with the \e +r option) are first evaluated for +their compatibility with the General Purpose CD-R Image Interchange Profile +(Supplement 19). Only appropriate files encoded using the Explicit VR Little +Endian Uncompressed Transfer Syntax will be accepted. Files having invalid +filenames will be rejected (the rules can be relaxed via the \e +m option). +Files missing required attributes will be rejected (the \e +I option can relax +this behavior). + +A \e DICOMDIR file will only be constructed if all files have passed initial +tests. + +The \b dcmgpdir utility also allows one to append new entries to and to update +existing entries in a \e DICOMDIR file. Using option \e +A new entries are +only appended to the DICOMDIR, i.e. existing records like the ones for PATIENT +information are not updated. Using option \e +U also existing records are +updated according to the information found in the referenced DICOM files. +Please note that this update process might be slower than just appending new +entries. However, it makes sure that additional information that is required +for the selected application profile is also added to existing records. + +\subsection scanning_directories Scanning Directories + +Adding files from directories is possible by using option \e --recurse. If no +further command line parameters are given, the directory specified by option +\e --input-directory (default: current directory) is scanned for files. If +parameters are given, they can either specify a file or directory name; the +input directory is always prepended. If the files in the provided directories +should be selected according to a specific name pattern (e.g. using wildcard +matching), option \e --pattern has to be used. Please note that this file +pattern only applies to the files within the scanned directories, and, if any +other patterns are specified on the command line outside the +\e --input-directory option (e.g. in order to select further files), these do +not apply to the specified directories. + +\section logging LOGGING + +The level of logging output of the various command line tools and underlying +libraries can be specified by the user. By default, only errors and warnings +are written to the standard error stream. Using option \e --verbose also +informational messages like processing details are reported. Option +\e --debug can be used to get more details on the internal activity, e.g. for +debugging purposes. Other logging levels can be selected using option +\e --log-level. In \e --quiet mode only fatal errors are reported. In such +very severe error events, the application will usually terminate. For more +details on the different logging levels, see documentation of module "oflog". + +In case the logging output should be written to file (optionally with logfile +rotation), to syslog (Unix) or the event log (Windows) option \e --log-config +can be used. This configuration file also allows for directing only certain +messages to a particular output stream and for filtering certain messages +based on the module or application where they are generated. An example +configuration file is provided in \/logger.cfg. + +\section command_line COMMAND LINE + +All command line tools use the following notation for parameters: square +brackets enclose optional values (0-1), three trailing dots indicate that +multiple values are allowed (1-n), a combination of both means 0 to n values. + +Command line options are distinguished from parameters by a leading '+' or '-' +sign, respectively. Usually, order and position of command line options are +arbitrary (i.e. they can appear anywhere). However, if options are mutually +exclusive the rightmost appearance is used. This behavior conforms to the +standard evaluation rules of common Unix shells. + +In addition, one or more command files can be specified using an '@' sign as a +prefix to the filename (e.g. \@command.txt). Such a command argument +is replaced by the content of the corresponding text file (multiple +whitespaces are treated as a single separator unless they appear between two +quotation marks) prior to any further evaluation. Please note that a command +file cannot contain another command file. This simple but effective approach +allows one to summarize common combinations of options/parameters and avoids +longish and confusing command lines (an example is provided in file +\/dumppat.txt). + +\section environment ENVIRONMENT + +The \b dcmgpdir utility will attempt to load DICOM data dictionaries specified +in the \e DCMDICTPATH environment variable. By default, i.e. if the +\e DCMDICTPATH environment variable is not set, the file +\/dicom.dic will be loaded unless the dictionary is built +into the application (default for Windows). + +The default behavior should be preferred and the \e DCMDICTPATH environment +variable only used when alternative data dictionaries are required. The +\e DCMDICTPATH environment variable has the same format as the Unix shell +\e PATH variable in that a colon (":") separates entries. On Windows systems, +a semicolon (";") is used as a separator. The data dictionary code will +attempt to load each file specified in the \e DCMDICTPATH environment variable. +It is an error if no data dictionary can be loaded. + +\section see_also SEE ALSO + +dcmmkdir(1) + +\section copyright COPYRIGHT + +Copyright (C) 1996-2014 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany. + +*/ diff --git a/dcmdata/docs/dcmodify.man b/dcmdata/docs/dcmodify.man new file mode 100644 index 00000000..b2031805 --- /dev/null +++ b/dcmdata/docs/dcmodify.man @@ -0,0 +1,586 @@ +/*! + +\if MANPAGES +\page dcmodify Modify DICOM files +\else +\page dcmodify dcmodify: Modify DICOM files +\endif + +\section synopsis SYNOPSIS + +\verbatim +dcmodify [options] dcmfile-in... +\endverbatim + +\section description DESCRIPTION + +\b dcmodify is a tool that allows one to modify, insert and delete tags and +items in DICOM files. Sequences and tags with a value multiplicity > 1 are +also supported. Metaheader information and the tag's VR can not be modified +directly by \b dcmodify at this time. In addition to tag modifications, +\b dcmodify makes available some input options - forcing \b dcmodify to +handle its input files as the user specifies - and output options to control +the output format of the resulting files. + +In case multiple modifications have to be performed, \b dcmodify does the +modifications in the same order as they appear on the command line. Please +note that \b dcmodify does not check whether a given value matches its value +representation (VR). Usually, an error message is printed but generally the +user should take care of the right VR usage. + +If \b dcmodify doesn't know the tag it should insert, then the tag's VR is set +to UN and the value provided on command line is interpreted as being a series +of hexadecimal numbers (like they are provided for VR=OB). Please insert these +tags into the dictionary to avoid this behavior. Also, specifying the \e -iun +option, it is possible to force \b dcmodify to leave UN values untouched. +Using option \e -u lets \b dcmodify saving all VR=UN attributes as OB. + +\b dcmodify is able to work with so-called tag paths to access tags in +sequences. The (pseudo-formalized) syntax is + +\verbatim +{sequence[item-no].}*element +\endverbatim + +where 'sequence' is a sequence tag like (0008,1111) or a dictionary name for a +tag. 'item-no' describes the item number to be accessed (counting from zero). +'element' defines the target tag to work on. A tag can either be specified +directly as (0010,0010) or through the corresponding dictionary name +"PatientName". The '*' denotes that you can repeat sequence statements to +access deeper levels in DICOM files (see EXAMPLES section). For 'item-no', +also a wildcard character '*' can be used selecting all items in surrounding +sequence (see section WILDCARDS below). + +When inserting tag paths consisting of multiple nodes (i.e. not a single +element) using the \e -i option, any missing path elements (items, sequences, +leaf elements) are inserted automatically when missing. That does not work +for item wildcards: When no single item exists in the surrounding sequence +\b dcmodify of course can't decide, how many items should be generated. +However, if specifying an item number like '5', all 6 items (counted from zero) +can be (and are) automatically generated in insert mode. If already 2 items +would exist, the rest (4) would be inserted. + +Please note that there are some issues concerning the modification of private +tags (see PRIVATE TAGS section) and for changing UIDs (CHANGING UIDs section). + +\section parameters PARAMETERS + +\verbatim +dcmfile-in DICOM input filename(s) to be modified +\endverbatim + +\section options OPTIONS + +\subsection general_options general options +\verbatim + -h --help + print this help text and exit + + --version + print version information and exit + + --arguments + print expanded command line arguments + + -q --quiet + quiet mode, print no warnings and errors + + -v --verbose + verbose mode, print processing details + + -d --debug + debug mode, print debug information + + -ll --log-level [l]evel: string constant + (fatal, error, warn, info, debug, trace) + use level l for the logger + + -lc --log-config [f]ilename: string + use config file f for the logger +\endverbatim + +\subsection input_options input options +\verbatim +input file format: + + +f --read-file + read file format or data set (default) + + +fo --read-file-only + read file format only + + -f --read-dataset + read data set without file meta information + + +fc --create-file + create file format if file does not exist + +input transfer syntax: + + -t= --read-xfer-auto + use TS recognition (default) + + -td --read-xfer-detect + ignore TS specified in the file meta header + + -te --read-xfer-little + read with explicit VR little endian TS + + -tb --read-xfer-big + read with explicit VR big endian TS + + -ti --read-xfer-implicit + read with implicit VR little endian TS + +parsing of odd-length attributes: + + +ao --accept-odd-length + accept odd length attributes (default) + + +ae --assume-even-length + assume real length is one byte larger + +automatic data correction: + + +dc --enable-correction + enable automatic data correction (default) + + -dc --disable-correction + disable automatic data correction + +bitstream format of deflated input: + + +bd --bitstream-deflated + expect deflated bitstream (default) + + +bz --bitstream-zlib + expect deflated zlib bitstream +\endverbatim + +\subsection processing_options processing options +\verbatim +backup input files: + + --backup + backup files before modifying (default) + + -nb --no-backup + don't backup files (DANGEROUS) + +insert mode: + + -i --insert "[t]ag-path=[v]alue" + insert (or overwrite) path at position t with value v + + -if --insert-from-file "[t]ag-path=[f]ilename" + insert (or overwrite) path at position t with value from file f + + -nrc --no-reserv-check + do not check private reservations + +modify mode: + + -m --modify "[t]ag-path=[v]alue" + modify tag at position t to value v + + -mf --modify-from-file "[t]ag-path=[f]ilename" + modify tag at position t to value from file f + + -ma --modify-all "[t]ag=[v]alue" + modify ALL matching tags t in file to value v + +erase mode: + + -e --erase "[t]ag-path" + erase tag/item at position t + + -ea --erase-all "[t]ag" + erase ALL matching tags t in file + + -ep --erase-private + erase ALL private data from file + +unique identifier: + + -gst --gen-stud-uid + generate new Study Instance UID + + -gse --gen-ser-uid + generate new Series Instance UID + + -gin --gen-inst-uid + generate new SOP Instance UID + + -nmu --no-meta-uid + do not update metaheader UIDs if related + UIDs in the dataset are modified + +error handling: + + -ie --ignore-errors + continue with file, if modify error occurs + + -imt --ignore-missing-tags + treat 'tag not found' as success + when modifying or erasing in files + + -iun --ignore-un-values + do not try writing any values to elements + having a VR of UN +\endverbatim + +\subsection output_options output options +\verbatim +output file format: + + +F --write-file + write file format (default) + + -F --write-dataset + write data set without file meta information + +output transfer syntax: + + +t= --write-xfer-same + write with same TS as input (default) + + +te --write-xfer-little + write with explicit VR little endian TS + + +tb --write-xfer-big + write with explicit VR big endian TS + + +ti --write-xfer-implicit + write with implicit VR little endian TS + +post-1993 value representations: + + +u --enable-new-vr + enable support for new VRs (UN/UT) (default) + + -u --disable-new-vr + disable support for new VRs, convert to OB + +group length encoding: + + +g= --group-length-recalc + recalculate group lengths if present (default) + + +g --group-length-create + always write with group length elements + + -g --group-length-remove + always write without group length elements + +length encoding in sequences and items: + + +le --length-explicit + write with explicit lengths (default) + + -le --length-undefined + write with undefined lengths + +data set trailing padding (not with --write-dataset): + + -p= --padding-retain + do not change padding (default if not --write-dataset) + + -p --padding-off + no padding (implicit if --write-dataset) + + +p --padding-create [f]ile-pad [i]tem-pad: integer + align file on multiple of f bytes and items on + multiple of i bytes +\endverbatim + +\section private_tags PRIVATE TAGS + +There are some issues you have to consider when working with private tags. +However, the insertion or modification of a reservation tag (gggg,00xx) should +always work. + +\subsection private_insertions Insertions + +If you wish to insert a private tag (not a reservation with gggg,00xx), be +sure, that you've listed it in your dictionary (see +\/datadict.txt for details). If it's not listed, \b dcmodify +will insert it with VR=UN. Also, for some cases insertion may even fail for +some values. + +If you've got your private tag in the dictionary, \b dcmodify acts as follows: +When it finds a reservation in the tag's enclosing dataset, whose private +creator matches, insertion is done with the VR found in the dictionary and the +value given on command line. But if the private creator doesn't match or none +is set, \b dcmodify will return with an error. If a private tag should be +inserted regardless whether a reservation does not exist, the option \e -nrc +can be used, forcing an insertion. However, the VR is set to UN then, because +the tag then cannot be found in the dictionary. + +See description above how inserting values into elements with unknown VR +are handled. + +\subsection private_modifications Modifications + +If you modify a private tags value, \b dcmodify won't check its VR against the +dictionary. So please be careful to enter only values that match the tag's VR. + +If you wish to change a private tags value \e and VR, because you just added +this tag to your dictionary, you can delete it with \b dcmodify and re-insert +it. Then \b dcmodify uses your dictionary entry to determine the right VR +(also see subsection insertions). + +Also, see description above how inserting values into elements with unknown VR +are handled. + +\subsection private_deletions Deletions + +When you use \b dcmodify to delete a private reservation tag, please note that +\b dcmodify won't touch the private tags that are under this reservation. The +user is forced to handle the consistency between reservations and their +associated private tags. + +For the deletion of private non-reservation tags there are no special issues. + +\section changing_uids CHANGING UIDS + +\b dcmodify will automatically correct 'Media Storage SOP Class UID' and +'Media Storage SOP Instance UID' in the metaheader, if you make changes to the +related tags in the dataset ('SOP Class UID' and 'SOP Instance UID') via +insert or modify mode options. You can disable this behavior by using the +\e -nmu option. + +If you generate new UID's with \e -gst, \e -gse or \e -gin, this will only +affect the UID you chose to generate. So if you use \e -gst to generate a +new 'Study Instance UID', then 'Series Instance UID' and 'SOP Instance UID' +will not be affected! This gives you the possibility to generate each value +separately. Normally, you would also modify the 'underlying' UIDs. As a +disadvantage of this flexibility, the user has to assure, that when creating +'new' DICOM files with new UIDs with \b dcmodify, other UIDs have to be updated +by the user as necessary. + +When choosing the \e -gin option, the related metaheader tag ('Media Storage +SOP Instance UID') is updated automatically. This behavior cannot be +disabled. + +\section creating_new_files CREATING NEW FILES + +Option \e --create-file lets \b dcmodify create a file if it does not already +exist on disk. This can be used in order to create files from scratch by +performing consecutive insertions with options like \e --insert. This might +especially become handy when creating query files for tools like \b findscu or +\b movescu. In case no specific output transfer syntax is defined, \b dcmodify +chooses Little Endian Explicit Uncompressed for output. Files that are newly +created are always written as DICOM file format, i.e. option \e --write-dataset +is not permitted together with \e --create. This way, at least the metaheader +is written and no file with zero byte length is created in a case where no +insertions are performed in the \b dcmodify call. + +\section element_values_from_file ELEMENT VALUES FROM FILE + +In order to read the element value from a file instead of specifying it on the +command line, option \e -mf and \e -if can be used. Please note that for OW +elements, the data is expected to be little endian ordered and will be swapped +if necessary. The file size should always be an even number of bytes, i.e. no +automatic padding is performed. + +\section wildcards WILDCARDS + +\b dcmodify also permits the usage of a wildcard character "*" for item numbers +in path expressions, e.g. "ContentSequence[*].CodeValue" selects all "Code +Value" attributes in all items of the ContentSequence. Using a wildcard is +possible for all basic operations, i.e. modifying \e -m, inserting \e -i and +\e -e options which makes it, together with the automatic creation of +intermediate path nodes a powerful tool for construction and processing complex +datasets. + +The options \e -ma and \e -ea for modifying or deleting all occurrences of a +DICOM element based on its tag do not accept any wildcards but only work on +single elements (i.e. a single dictionary name or tag key). + +\section examples EXAMPLES + +\verbatim +-i --insert: + dcmodify -i "(0010,0010)=A Name" file.dcm + Inserts the PatientName tag into 'file.dcm' at 1st level. + If tag already exists, -i will overwrite it! If you want to + insert an element with value multiplicity > 1 (e.g. 4) you + can do this with: dcmodify -i "(0018,1310)=1\\2\\3\\4" + + dcmodify -i "(0008,1111)[0].PatientName=Another Name" *.dcm + Inserts PatientName tag into the first item of sequence + (0008,1111). Note that the use of wildcards for files is + possible. You can specify longer tag paths, too (e.g. + "(0008,1111)[0].(0008,1111)[1].(0010,0010)=A Third One"). + If any part of the path, e.g. the sequence or the item "0" + does not exist, it is automatically inserted by dcmodify. + + dcmodify -i "(0008,1111)[*].PatientName=Another Name" *.dcm + Inserts PatientName tag into _every_ item of sequence + (0008,1111). Note that the use of wildcards for files is + possible. You can specify longer tag paths, too (e.g. + "(0008,1111)[*].(0008,1111)[*].(0010,0010)=A Third One"). + +-if --insert-from-file: + dcmodify -if "PixelData=pixel.raw" file.dcm + Inserts the content of file 'pixel.raw' into the PixelData element + of 'file.dcm'. The contents of the file will be read as is. + OW data is expected to be little endian ordered and will be + swapped if necessary. No checks will be made to ensure that the + amount of data is reasonable in terms of other attributes such as + Rows or Columns. + +-m --modify: + dcmodify -m "(0010,0010)=A Name" file.dcm + Changes tag (0010,0010) on 1st level to "A Name". + + This option also permits longer tag paths as demonstrated + above for -i. If the leaf element or any intermediate + part of the path does not exist, it is not inserted as it + would be if using the '-i' option. + + dcmodify -m "(0010,0010)=A Name" -imt file.dcm + Changes tag (0010,0010) on 1st level to "A Name". Due to the + given option '-imt', success is returned instead of "tag not found", + if the element/item (or any intermediate node in a longer path) does + not exist. + + Note that for the '-m' option the last node in the path must be + a leaf element, i.e. not a sequence or an item. + +-mf --modify-from-file: + dcmodify -mf "PixelData=pixel.raw" file.dcm + Does the same as -if in case there was already a PixelData element + in 'file.dcm'. Otherwise nothing is changed. + +-ma --modify-all: + dcmodify -ma "(0010,0010)=New Name" file.dcm + Does the same as -m but works on all matching tags found in + 'file.dcm'. Therefore, it searches the whole dataset including + sequences for tag (0010,0010) and changes them to "New Name" + +-e --erase: + dcmodify -e "(0010,0010)" *.dcm + Erases tag (0010,0010) in all *.dcm files at 1st level. + + This option also allows longer tag paths as demonstrated + above for -i. + + dcmodify -e "(0010,0010)" -imt *.dcm + Erases tag (0010,0010) in all *.dcm files at 1st level. Due to the + given option '-imt', success is returned instead of "tag not found", + if the element/item (or any intermediate node in a longer path) does + not exist. + +-ea --erase-all: + dcmodify -ea "(0010,0010)" *.dcm + Same as -e, but also searches in sequences and items. + +-ep --erase-private: + dcmodify -ep *.dcm + Deletes all private tags (i.e. tags having an odd group number) from + all files matching *.dcm in the current directory. + +-gst --gen-stud-uid: + dcmodify -gst file.dcm + This generates a new value for the StudyInstanceUID + (0020,000d). Other UIDs are not modified! + +-gse --gen-ser-uid: + dcmodify -gse file.dcm + This generates a new value for the SeriesInstanceUID + (0020,000e). Other UIDs are not modified! + +-gin --gen-inst-uid: + dcmodify -gin file.dcm + This command generates a new value for the SOPInstanceUID + (0008,0018). The corresponding MediaStorageSOPInstanceUID + (0002,0003) is adjusted to the new value automatically. + Please note that it's not possible to avoid this metaheader + update via the -nmu option. + +-nmu --no-meta-uid: + dcmodify -m "SOPInstanceUID=[UID]" -nmu *.dcm + This will modify the SOPInstanceUID to the given [UID], + but -nmu avoids, that dcmodify adjusts the + MediaStorageSOPInstanceUID in the metaheader, too. + +\endverbatim + +\section error_handling ERROR HANDLING + +\b dcmodify tries executing each modify operation given on command line: If +one returns an error, the others are being performed anyway. However in case +of any error, the modified file is not saved, unless the \e --ignore-errors +option is specified. If that option is selected, \b dcmodify also +continues modifying further files specified on command line; otherwise +\b dcmodify exits after the first file that had modification errors. + +If the \e --ignore-missing-tags option is enabled, any modify or erase +operations (i.e. not \e --insert) that fails because of a non-existing tag is +treated as being successful. That does make sense if someone wants to be sure +that specific tags are not present in the file or that - if they exist - that +they are set to a specific value. + +\section logging LOGGING + +The level of logging output of the various command line tools and underlying +libraries can be specified by the user. By default, only errors and warnings +are written to the standard error stream. Using option \e --verbose also +informational messages like processing details are reported. Option +\e --debug can be used to get more details on the internal activity, e.g. for +debugging purposes. Other logging levels can be selected using option +\e --log-level. In \e --quiet mode only fatal errors are reported. In such +very severe error events, the application will usually terminate. For more +details on the different logging levels, see documentation of module "oflog". + +In case the logging output should be written to file (optionally with logfile +rotation), to syslog (Unix) or the event log (Windows) option \e --log-config +can be used. This configuration file also allows for directing only certain +messages to a particular output stream and for filtering certain messages +based on the module or application where they are generated. An example +configuration file is provided in \/logger.cfg. + +\section command_line COMMAND LINE + +All command line tools use the following notation for parameters: square +brackets enclose optional values (0-1), three trailing dots indicate that +multiple values are allowed (1-n), a combination of both means 0 to n values. + +Command line options are distinguished from parameters by a leading '+' or '-' +sign, respectively. Usually, order and position of command line options are +arbitrary (i.e. they can appear anywhere). However, if options are mutually +exclusive the rightmost appearance is used. This behavior conforms to the +standard evaluation rules of common Unix shells. + +In addition, one or more command files can be specified using an '@' sign as a +prefix to the filename (e.g. \@command.txt). Such a command argument +is replaced by the content of the corresponding text file (multiple +whitespaces are treated as a single separator unless they appear between two +quotation marks) prior to any further evaluation. Please note that a command +file cannot contain another command file. This simple but effective approach +allows one to summarize common combinations of options/parameters and avoids +longish and confusing command lines (an example is provided in file +\/dumppat.txt). + +\section environment ENVIRONMENT + +The \b dcmodify utility will attempt to load DICOM data dictionaries specified +in the \e DCMDICTPATH environment variable. By default, i.e. if the +\e DCMDICTPATH environment variable is not set, the file +\/dicom.dic will be loaded unless the dictionary is built +into the application (default for Windows). + +The default behavior should be preferred and the \e DCMDICTPATH environment +variable only used when alternative data dictionaries are required. The +\e DCMDICTPATH environment variable has the same format as the Unix shell +\e PATH variable in that a colon (":") separates entries. On Windows systems, +a semicolon (";") is used as a separator. The data dictionary code will +attempt to load each file specified in the \e DCMDICTPATH environment variable. +It is an error if no data dictionary can be loaded. + +\section copyright COPYRIGHT + +Copyright (C) 2003-2014 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany. + +*/ diff --git a/dcmdata/docs/dump2dcm.man b/dcmdata/docs/dump2dcm.man new file mode 100644 index 00000000..17f914cb --- /dev/null +++ b/dcmdata/docs/dump2dcm.man @@ -0,0 +1,317 @@ +/*! + +\if MANPAGES +\page dump2dcm Convert ASCII dump to DICOM file +\else +\page dump2dcm dump2dcm: Convert ASCII dump to DICOM file +\endif + +\section synopsis SYNOPSIS + +\verbatim +dump2dcm [options] dumpfile-in dcmfile-out +\endverbatim + +\section description DESCRIPTION + +The \b dump2dcm utility converts an ASCII dump file to a DICOM file. The +dump file has the same format as the output of \b dcmdump. Thus it is possible +to capture the output of \b dcmdump into a file, modify some attributes and +create a new DICOM file. + +\section parameters PARAMETERS + +\verbatim +dumpfile-in dump input filename + +dcmfile-out DICOM output filename +\endverbatim + +\section options OPTIONS + +\subsection general_options general options +\verbatim + -h --help + print this help text and exit + + --version + print version information and exit + + --arguments + print expanded command line arguments + + -q --quiet + quiet mode, print no warnings and errors + + -v --verbose + verbose mode, print processing details + + -d --debug + debug mode, print debug information + + -ll --log-level [l]evel: string constant + (fatal, error, warn, info, debug, trace) + use level l for the logger + + -lc --log-config [f]ilename: string + use config file f for the logger +\endverbatim + +\subsection input_options input options +\verbatim +input file format: + + +f --read-meta-info + read meta information if present (default) + + -f --ignore-meta-info + ignore file meta information + +file contents byte ordering: + + +rl --read-file-little + read OW data with little endian (default) + + +rb --read-file-big + read OW data from file with big endian + +other input options: + + +l --line [m]ax-length: integer + maximum line length m (default: 4096) +\endverbatim + +\subsection processing_options processing options +\verbatim +unique identifiers: + + +Ug --generate-new-uids + generate new Study/Series/SOP Instance UID + + -Uo --dont-overwrite-uids + do not overwrite existing UIDs (default) + + +Uo --overwrite-uids + overwrite existing UIDs +\endverbatim + +\subsection output_options output options +\verbatim +output file format: + + +F --write-file + write file format (default) + + -F --write-dataset + write data set without file meta information + + +Fu --update-meta-info + update particular file meta information + +output transfer syntax: + + +t= --write-xfer-same + write with same TS as input (default) + + +te --write-xfer-little + write with explicit VR little endian + + +tb --write-xfer-big + write with explicit VR big endian TS + + +ti --write-xfer-implicit + write with implicit VR little endian TS + + +td --write-xfer-deflated + write with deflated explicit VR little endian TS + +error handling: + + -E --stop-on-error + do not write if dump is damaged (default) + + +E --ignore-errors + attempt to write even if dump is damaged + +post-1993 value representations: + + +u --enable-new-vr + enable support for new VRs (UN/UT) (default) + + -u --disable-new-vr + disable support for new VRs, convert to OB + +group length encoding: + + +g= --group-length-recalc + recalculate group lengths if present (default) + + +g --group-length-create + always write with group length elements + + -g --group-length-remove + always write without group length elements + +length encoding in sequences and items: + + +e --length-explicit + write with explicit lengths (default) + + -e --length-undefined + write with undefined lengths + +data set trailing padding (not with --write-dataset): + + -p= --padding-retain + do not change padding (default if not --write-dataset) + + -p --padding-off + no padding (implicit if --write-dataset) + + +p --padding-create [f]ile-pad [i]tem-pad: integer + align file on multiple of f bytes + and items on multiple of i bytes + +deflate compression level (only with --write-xfer-deflated): + + +cl --compression-level [l]evel: integer (default: 6) + 0=uncompressed, 1=fastest, 9=best compression +\endverbatim + +\section notes NOTES + +\subsection notes_description Dump File Description + +The input file can be an output of \b dcmdump (default indented format only). +One element (tag, VR, value) must be written into one line separated by +arbitrary spaces or tab characters. A '#' begins a comment that ends at the +line end. Empty lines are allowed. + +The individual parts of a line have the following syntax: + +\verbatim +Tag: (gggg,eeee) + with gggg and eeee are 4 character hexadecimal values + representing group and element tag. Spaces and tabs can be + anywhere in a tag specification. +VR: Value Representation must be written as 2 characters as in + Part 6 of the DICOM standard. No spaces or tabs are allowed + between the two characters. If the VR can be determined from + the tag, this part of a line is optional. +Value: There are several rules for writing values: + 1. US, SS, SL, UL, FD, FL are written as decimal strings that + can be read by scanf(). + 2. AT is written as '(gggg,eeee)' with additional spaces + stripped off automatically and gggg and eeee being decimal + strings that can be read by scanf(). + 3. OB and OW values are written as byte or word hexadecimal + values separated by '\\' character. Alternatively, OB or OW + values can be read from a separate file by writing the + filename prefixed by a '=' character (e.g. '=largepix.dat'). + The contents of the file will be read as is. By default, OW + data is expected to be little endian ordered and will be + swapped if necessary. No checks will be made to ensure that + the amount of data is reasonable in terms of other attributes + such as Rows or Columns. + In case of compressed pixel data, the line should start with + '(7fe0,0010) OB (PixelSequence' in order to distinguish from + uncompressed pixel data. + 4. UI is written as '=Name' in data dictionary or as unique + identifier string (see 6.), e.g. '[1.2.840.....]'. + 5. Strings without () <> [] spaces, tabs and # can be written + directly. + 6. Other strings must be surrounded by '[' and ']'. No bracket + structure is passed. The value ends at the last ']' in the + line. Anything after the ']' is interpreted as comment. + 7. '(' and '<' are interpreted special and may not be used when + writing an input file by hand as beginning characters of a + string. Multiple Value are separated by '\\'. The lines + need not be sorted into ascending tag order. References in + DICOM Directories are not supported. Semantic errors are + not detected. +\endverbatim + +\subsection notes_example Example + +\verbatim + (0008,0020) DA [19921012] # 8, 1 StudyDate + (0008,0016) UI =MRImageStorage # 26, 1 SOPClassUID + (0002,0012) UI [1.2.276.0.7230010.100.1.1] + (0020,0032) DS [0.0\\0.0] # 8, 2 ImagePositionPatient + (0028,0009) AT (3004,000c) # 4, 1 FrameIncrementPointer + (0028,0010) US 256 # 4, 1 Rows + (0002,0001) OB 01\\00 +\endverbatim + +\subsection limitations Limitations + +Please note that \b dump2dcm currently does not fully support DICOMDIR files. +Specifically, the value of the various offset data elements is not updated +automatically by this tool. + +\section logging LOGGING + +The level of logging output of the various command line tools and underlying +libraries can be specified by the user. By default, only errors and warnings +are written to the standard error stream. Using option \e --verbose also +informational messages like processing details are reported. Option +\e --debug can be used to get more details on the internal activity, e.g. for +debugging purposes. Other logging levels can be selected using option +\e --log-level. In \e --quiet mode only fatal errors are reported. In such +very severe error events, the application will usually terminate. For more +details on the different logging levels, see documentation of module "oflog". + +In case the logging output should be written to file (optionally with logfile +rotation), to syslog (Unix) or the event log (Windows) option \e --log-config +can be used. This configuration file also allows for directing only certain +messages to a particular output stream and for filtering certain messages +based on the module or application where they are generated. An example +configuration file is provided in \/logger.cfg. + +\section command_line COMMAND LINE + +All command line tools use the following notation for parameters: square +brackets enclose optional values (0-1), three trailing dots indicate that +multiple values are allowed (1-n), a combination of both means 0 to n values. + +Command line options are distinguished from parameters by a leading '+' or '-' +sign, respectively. Usually, order and position of command line options are +arbitrary (i.e. they can appear anywhere). However, if options are mutually +exclusive the rightmost appearance is used. This behavior conforms to the +standard evaluation rules of common Unix shells. + +In addition, one or more command files can be specified using an '@' sign as a +prefix to the filename (e.g. \@command.txt). Such a command argument +is replaced by the content of the corresponding text file (multiple +whitespaces are treated as a single separator unless they appear between two +quotation marks) prior to any further evaluation. Please note that a command +file cannot contain another command file. This simple but effective approach +allows one to summarize common combinations of options/parameters and avoids +longish and confusing command lines (an example is provided in file +\/dumppat.txt). + +\section environment ENVIRONMENT + +The \b dump2dcm utility will attempt to load DICOM data dictionaries specified +in the \e DCMDICTPATH environment variable. By default, i.e. if the +\e DCMDICTPATH environment variable is not set, the file +\/dicom.dic will be loaded unless the dictionary is built +into the application (default for Windows). + +The default behavior should be preferred and the \e DCMDICTPATH environment +variable only used when alternative data dictionaries are required. The +\e DCMDICTPATH environment variable has the same format as the Unix shell +\e PATH variable in that a colon (":") separates entries. On Windows systems, +a semicolon (";") is used as a separator. The data dictionary code will +attempt to load each file specified in the \e DCMDICTPATH environment variable. +It is an error if no data dictionary can be loaded. + +\section see_also SEE ALSO + +dcmdump(1) + +\section copyright COPYRIGHT + +Copyright (C) 1996-2014 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany. + +*/ diff --git a/dcmdata/docs/img2dcm.man b/dcmdata/docs/img2dcm.man new file mode 100644 index 00000000..3998999b --- /dev/null +++ b/dcmdata/docs/img2dcm.man @@ -0,0 +1,496 @@ +/*! + +\if MANPAGES +\page img2dcm Convert standard image formats into DICOM format +\else +\page img2dcm img2dcm: Convert standard image formats into DICOM format +\endif + +\section synopsis SYNOPSIS + +\verbatim +img2dcm [options] imgfile-in dcmfile-out +\endverbatim + +\section description DESCRIPTION + +The \b img2dcm tool serves as a conversion tool from a standard image format +like JPEG or BMP to DICOM. Different output SOP Classes can be selected. The +additional information (regarding patients, series, etc.) stored in the DICOM +output file can be extracted from other DICOM files which serve as a "template" +for the resulting DICOM object. \b img2dcm can also be configured to invent +missing DICOM type 1 and type 2 attributes to work even without any template +dataset. + +\section parameters PARAMETERS +\verbatim +imgfile-in image file to be imported + +dcmfile-out DICOM output file +\endverbatim + +\section options OPTIONS +\subsection general_options general options +\verbatim + -h --help + print this help text and exit + + --version + print version information and exit + + --arguments + print expanded command line arguments + + -q --quiet + quiet mode, print no warnings and errors + + -v --verbose + verbose mode, print processing details + + -d --debug + debug mode, print debug information + + -ll --log-level [l]evel: string constant + (fatal, error, warn, info, debug, trace) + use level l for the logger + + -lc --log-config [f]ilename: string + use config file f for the logger +\endverbatim + +\subsection input_options input options +\verbatim +general: + + -i --input-format [i]nput file format: string + supported formats: JPEG (default), BMP + + -df --dataset-from [f]ilename: string + use dataset from DICOM file f + + -stf --study-from [f]ilename: string + read patient/study from DICOM file f + + -sef --series-from [f]ilename: string + read patient/study/series from DICOM file f + + -ii --instance-inc + increase instance number read from DICOM file + +JPEG format: + + -dp --disable-progr + disable support for progressive JPEG + + -de --disable-ext + disable support for extended sequential JPEG + + -jf --insist-on-jfif + insist on JFIF header existence + + -ka --keep-appn + keep APPn sections (except JFIF) +\endverbatim + +\subsection processing_options processing options +\verbatim +attribute checking: + + --do-checks + enable attribute validity checking (default) + + --no-checks + disable attribute validity checking + + +i2 --insert-type2 + insert missing type 2 attributes (default) + (only with --do-checks) + + -i2 --no-type2-insert + do not insert missing type 2 attributes + (only with --do-checks) + + +i1 --invent-type1 + invent missing type 1 attributes + (only with --do-checks) + + -i1 --no-type1-invent + do not invent missing type 1 attributes + (only with --do-checks) + +character set: + + +l1 --latin1 + set latin-1 as standard character set (default) + + -l1 --no-latin1 + keep 7-bit ASCII as standard character set + +other processing options: + + -k --key [k]ey: gggg,eeee="str", path or dictionary name="str" + add further attribute +\endverbatim + +\subsection output_options output options +\verbatim +target SOP class: + + -sc --sec-capture + write Secondary Capture SOP class + + -nsc --new-sc + write new Secondary Capture SOP classes + + -vlp --vl-photo + write Visible Light Photographic SOP class (default) + +output file format: + + +F --write-file + write file format (default) + + -F --write-dataset + write data set without file meta information + +group length encoding: + + +g= --group-length-recalc + recalculate group lengths if present (default) + + +g --group-length-create + always write with group length elements + + -g --group-length-remove + always write without group length elements + +length encoding in sequences and items: + + +e --length-explicit + write with explicit lengths (default) + + -e --length-undefined + write with undefined lengths + +data set trailing padding (not with --write-dataset): + + -p --padding-off + no padding (implicit if --write-dataset) + + +p --padding-create [f]ile-pad [i]tem-pad: integer + align file on multiple of f bytes + and items on multiple of i bytes +\endverbatim + +\section notes NOTES + +\subsection attribute_sources Attribute Sources + +For converting a general image format into DICOM format, the \b img2dcm +application may be fed with some additional input for filling mandatory (and +optional) attributes in the new DICOM file like patient, study and series +information. This information can be collected using different approaches, +which can be combined and are applied to the result file in the following +order: + +\li Using the \e --dataset-from option \b img2dcm is forced to import + attributes from an existing DICOM file. The given DICOM file is fully + imported and serves as the basis for all further export operations. + As an exception, the SOP Instance UID is not copied by this option. + Also image related data like Rows, Columns etc. is exchanged during + conversion. Note that \b img2dcm does not check any other attribute + values for validity, e. g. it does not look into sequences to adapt any + attributes to the new object (referenced images etc.). Therefore, it is + recommended to use the templates in the data directory for (old) SC and + VLP objects. See also section "Input Templates". + +\li The \e --study-from and \e --series-from options (mutually exclusive) can + be used to import patient, study and series information from an existing + DICOM file. If \e --series-from is specified, then the given DICOM file + is opened by \b img2dcm and all mandatory information down to the series + level is imported. Note that this includes patient, study and series + information. In case of \e --study-from, the series information is + excluded. The following attributes are taken over: + \verbatim + Patient Level: + Patient's Name + Patient ID + Patient's Sex + Patient's Birth Date + Specific Character Set + + Study Level: + Study Instance UID + Study Date + Study Time + Referring Physician's Name + Study ID + Accession Number + + Series Level (only in case of option --series-from): + Series Instance UID + Series Number + Manufacturer + \endverbatim + +\li With the \e --insert-type2 and \e --invent-type1 options (both enabled per + default), missing attributes (type 2 attributes) and/or missing attribute + values (for type 1 attributes) are automatically added and invented by + \b img2dcm. Please note that these options are only evaluated if option + \e --do-checks is enabled (default). If the \e --no-checks options is + enabled, no automatic attribute insertion will take place. + +\li The \e --key option can be used to add further attributes to the DICOM + output file. This option is applied at the very end, just before saving the + DICOM file. It is also possible to specify sequences, items and nested + attributes using the \e --key option. In these cases, a special "path" + notation has to be used. Details on this path notation can be found in the + documentation of \b dcmodify. + +\subsection uids UIDs + +New Study and Series Instance UIDs are generated if necessary after +applying the \e --study-from and \e --series options. If Study Instance UID or +Series Instance UID are not present after these steps, they are newly generated, +independently from each other. +A contrary behavior is chosen for the SOP Instance UID that one could expect +to be taken over when using the \e --dataset-from option. This is \b not the +case, the SOP Instance UID is \b not copied to the new object. This should +be the desirable behavior for most use cases. However, if a certain SOP +Instance UID should be inserted into the new object, the \e --key option should +be used. + +\subsection input_templates Input Templates + +For supporting the conversion into DICOM, \b img2dcm comes with some +pre-defined templates which can be used for the \e --dataset-from option (see +sample files \e SC.dump and \e VLP.dump). These templates should be filled with +the desired values and then must be dumped (converted) to a DICOM file before +actually being used with \b img2dcm. Use \b dump2dcm to convert the dump to +DICOM. Example: +\verbatim + dump2dcm SC.dump SC.dcm +\endverbatim + +It is possible to use any DICOM file as a template. Please note that the +complete DICOM dataset is imported; hence, it should be assured that only +attributes are present which should be part of the constructed DICOM object. +The SOP Class UID and the Pixel Data attributes (including attributes like +Rows, Columns etc.) are not copied but replaced by \b img2dcm during conversion. + +\subsection input_plugins Input Plugins + +The \b img2dcm application currently supports the JPEG and the BMP image format +as input. + +\subsubsection jpeg_input_plugin JPEG Input Plugin + +For JPEG, the original JPEG from the source file is not decoded but extracted +and slightly transformed (e. g. JFIF header is cut off) to allow fast +conversion of even big JPEG files without the need of decoding and re-encoding. +The JPEG plugin chooses the necessary output transfer syntax automatically +depending on the actual encoding of the data inside the JPEG file. Therefore, +the following Transfer Syntaxes (and their corresponding JPEG encodings) are +used by the JPEG plugin: + +\li JPEG Coding Process 1 + Baseline, Lossy, Non-Hierarchical, Sequential, DCT, Huffman, 8 Bit + SOP Class = 1.2.840.10008.1.2.4.50 + +\li JPEG Coding Process 2 (8-bit) and 4 (12-bit) + Extended, Lossy, Non-Hierarchical, Sequential, DCT, Huffman, 8/12 Bit + SOP Class = 1.2.840.10008.1.2.4.51 + +\li JPEG Coding Process 10 (8-bit) and 12 (12-bit) + Full Progression, lossy, Non-Hierarch., Progressive, DCT, Huffman, 8/12 Bit + SOP Class = 1.2.840.10008.1.2.4.55 + +Color and grayscale images are supported. + +The support for the Extended JPEG Transfer Syntax can be disabled +(\e --disable-ext option) as well as the support for the (retired) Progressive +JPEG Transfer Syntax (\e --disable-progr option). + +JPEG lossless encoding as well as any arithmetic or hierarchical JPEG encoding +modes are not supported by the plugin. + +JFIF (JPEG File Interchange Format) information facilitates optional APPn +markers in a JPEG file. Many digital cameras do not integrate such JFIF +information into the JPEG output they create. For example, JFIF contains +information about the pixel aspect ratio of the compressed image. If you want +the \b img2dcm application to insist on a JFIF header in the JPEG stream, you +can use the option \e --insist-on-jfif which will abort if no JFIF information +can be found. By default, missing JFIF information is ignored. + +For DICOM it is kind of a "gray zone", whether the integration of JFIF (or any +other APPn) data into the DICOM object's internal JPEG stream is allowed or +not. However, the most reliable approach is to cut those markers and their +information off the JPEG stream. This approach is also taken by the \b img2dcm +application. By default, all APPn markers are cut off from the original JPEG +stream. However, if you want to keep other APPn markers than JFIF (e. g. +EXIF information) inside the DICOM stream, the option \e --keep-appn +does the trick. It should also be slightly faster than cutting off APPn +information, because it is not necessary to scan the whole JPEG stream for +such data. JFIF information is \b always removed by \b img2dcm. + +\subsubsection bmp_input_plugin BMP Input Plugin + +\b img2dcm supports BMP as input format. However, so far only the most commmon +BMP images are supported. In particular, BMP images which use bitfields or +run length encoding will be rejected. Such images are uncommon. All input images +will be converted into a DICOM image with RGB color model and a bit depth of 24. +There are no specific options for fine-tuning BMP format conversion. + +\subsection output_plugins Output Plugins + +The desired output SOP Class can be selected on the command line. Currently, +an export plugin for the Secondary Capture Image SOP class (default, option +\e -sc), the new Secondary Capture Image SOP classes (option \e -nsc) and +Visible Light Photographic Image SOP class (option \e -vl) are available. +Please note that the first one is deprecated according to the DICOM standard +but is selected as a default because it is widely supported. Future versions +of \b img2dcm might provide further output plugins for other SOP Classes. + +For the new Secondary Capture SOP classes, it is not possible to specify which +specific SOP class should be used for output. That is because these new SOP +classes are differentiated from each other by color depth (1/8/16) and the +fact whether the image is black/white or color. That is why \b img2dcm decides +during conversion, which output SOP class is suitable for a given source image. + +\section examples EXAMPLES + +Here are some examples that show how the \b img2dcm application can be used. + +
    + +
  1. +img2dcm image.jpg out.dcm +
    Read JPEG file "image.jpg", convert to the old Secondary Capture SOP class +and save the result to DICOM file "out.dcm". This is the easiest way of using +\b img2dcm. Any type 1 and type 2 attributes required for writing valid objects +of this SOP class are inserted automatically. +
  2. + +
  3. +img2dcm -i BMP image.bmp out.dcm +
    Same as above but tells img2dcm to read a BMP file instead of JPEG. +
  4. + +
  5. +img2dcm image.jpg out.dcm -vlp -k "PatientName=Bond^James" +
    Same as first example, but writes Visible Light Photographic Image object +to "out.dcm" and sets PatientName to "Bond^James" which otherwise would be +left empty. +
  6. + +
  7. +img2dcm image.jpg out.dcm --series-from template.dcm -k +"PatientName=Bond^James" +
    Same as 1), but imports patient/study/series infomation from DICOM file +"template.dcm". Please note that attribute PatientName will contain +"Bond^James" at the end, any value from "template.dcm" will be overwritten. +That is, because the -k option is applied at the very end of the conversion +pipeline (see above). +
  8. + +
  9. +img2dcm image.jpg out.dcm --no-checks +
    Same as 1), but does not perform any attribute checking and no type 1 and +type 2 attribute insertion! So in this case, an invalid DICOM object would be +generated. This can be interesting if the output file is not meant to be +completed but will undergo further transformations, e. g. adding attributes +using \b dcmodify. Only use option \e --no-checks if you know what you are +doing! +
  10. + +
  11. +img2dcm image.jpg out.dcm --no-type1-invent +
    Same as 1), but does not insert missing type 1 attributes and/or their +values. Type 2 attributes will be inserted. Note that in this case it must be +assured that all type 1 attributes are provided by other means, i. e. by adding +them with the \e --key option. Otherwise, \b img2dcm will report an error and +will stop converting. +
  12. + +
  13. +img2dcm image.jpg out.dcm --keep-appn --insist-on-jfif +
    Same as 1), but takes over APPn information like EXIF into the DICOM +object's resulting JPEG stream. Further, \e --insist-on-jfif will force +\b img2dcm to abort if no JFIF information is existent in the source file. +
  14. + +
+ +\section logging LOGGING + +The level of logging output of the various command line tools and underlying +libraries can be specified by the user. By default, only errors and warnings +are written to the standard error stream. Using option \e --verbose also +informational messages like processing details are reported. Option +\e --debug can be used to get more details on the internal activity, e.g. for +debugging purposes. Other logging levels can be selected using option +\e --log-level. In \e --quiet mode only fatal errors are reported. In such +very severe error events, the application will usually terminate. For more +details on the different logging levels, see documentation of module "oflog". + +In case the logging output should be written to file (optionally with logfile +rotation), to syslog (Unix) or the event log (Windows) option \e --log-config +can be used. This configuration file also allows for directing only certain +messages to a particular output stream and for filtering certain messages +based on the module or application where they are generated. An example +configuration file is provided in \/logger.cfg. + +\section command_line COMMAND LINE + +All command line tools use the following notation for parameters: square +brackets enclose optional values (0-1), three trailing dots indicate that +multiple values are allowed (1-n), a combination of both means 0 to n values. + +Command line options are distinguished from parameters by a leading '+' or '-' +sign, respectively. Usually, order and position of command line options are +arbitrary (i.e. they can appear anywhere). However, if options are mutually +exclusive the rightmost appearance is used. This behavior conforms to the +standard evaluation rules of common Unix shells. + +In addition, one or more command files can be specified using an '@' sign as a +prefix to the filename (e.g. \@command.txt). Such a command argument +is replaced by the content of the corresponding text file (multiple +whitespaces are treated as a single separator unless they appear between two +quotation marks) prior to any further evaluation. Please note that a command +file cannot contain another command file. This simple but effective approach +allows one to summarize common combinations of options/parameters and avoids +longish and confusing command lines (an example is provided in file +\/dumppat.txt). + +\section environment ENVIRONMENT + +The \b img2dcm utility will attempt to load DICOM data dictionaries specified +in the \e DCMDICTPATH environment variable. By default, i.e. if the +\e DCMDICTPATH environment variable is not set, the file +\/dicom.dic will be loaded unless the dictionary is built +into the application (default for Windows). + +The default behavior should be preferred and the \e DCMDICTPATH environment +variable only used when alternative data dictionaries are required. The +\e DCMDICTPATH environment variable has the same format as the Unix shell +\e PATH variable in that a colon (":") separates entries. On Windows systems, +a semicolon (";") is used as a separator. The data dictionary code will +attempt to load each file specified in the \e DCMDICTPATH environment variable. +It is an error if no data dictionary can be loaded. + +\section files FILES + +\/SC.dump - Sample dump file for Secondary Capture images +\n\/VLP.dump - Sample dump file for Visible Light Photographic +images + +\section see_also SEE ALSO + +dcm2pnm(1), dcmj2pnm(1), dump2dcm(1), dcmconv(1), +dcmodify(1) + +\section copyright COPYRIGHT + +Copyright (C) 2007-2014 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany. + +*/ diff --git a/dcmdata/docs/pdf2dcm.man b/dcmdata/docs/pdf2dcm.man new file mode 100644 index 00000000..377cfece --- /dev/null +++ b/dcmdata/docs/pdf2dcm.man @@ -0,0 +1,180 @@ +/*! + +\if MANPAGES +\page pdf2dcm Convert PDF file to DICOM +\else +\page pdf2dcm pdf2dcm: Convert PDF file to DICOM +\endif + +\section synopsis SYNOPSIS + +\verbatim +pdf2dcm [options] pdffile-in dcmfile-out +\endverbatim + +\section description DESCRIPTION + +The \b pdf2dcm utility reads a PDF file (\e pdffile-in), converts it to a +DICOM Encapsulated PDF Storage SOP instance and stores the converted data +to an output file (\e dcmfile-out). + +\section parameters PARAMETERS + +\verbatim +pdffile-in PDF input filename to be converted + +dcmfile-out DICOM output filename +\endverbatim + +\section options OPTIONS + +\subsection general_options general options +\verbatim + -h --help + print this help text and exit + + --version + print version information and exit + + --arguments + print expanded command line arguments + + -q --quiet + quiet mode, print no warnings and errors + + -v --verbose + verbose mode, print processing details + + -d --debug + debug mode, print debug information + + -ll --log-level [l]evel: string constant + (fatal, error, warn, info, debug, trace) + use level l for the logger + + -lc --log-config [f]ilename: string + use config file f for the logger +\endverbatim + +\subsection dicom_document_options DICOM document options +\verbatim +burned-in annotation: + + +an --annotation-yes + PDF contains patient identifying data (default) + + -an --annotation-no + PDF does not contain patient identifying data + +document title: + + +t --title [t]itle: string (default: empty) + document title + + +cn --concept-name [CSD] [CV] [CM]: string (default: empty) + document title as concept name code sequence with coding + scheme designator CSD, code value CV and code meaning CM + +patient data: + + +pn --patient-name [n]ame: string + patient's name in DICOM PN syntax + + +pi --patient-id [i]d: string + patient identifier + + +pb --patient-birthdate [d]ate: string (YYYYMMDD) + patient's birth date + + +ps --patient-sex [s]ex: string (M, F or O) + patient's sex + +study and series: + + +sg --generate + generate new study and series UIDs (default) + + +st --study-from [f]ilename: string + read patient/study data from DICOM file + + +se --series-from [f]ilename: string + read patient/study/series data from DICOM file + +instance number: + + +i1 --instance-one + use instance number 1 (default, not with +se) + + +ii --instance-inc + increment instance number (only with +se) + + +is --instance-set [i]nstance number: integer + use instance number i +\endverbatim + +\section logging LOGGING + +The level of logging output of the various command line tools and underlying +libraries can be specified by the user. By default, only errors and warnings +are written to the standard error stream. Using option \e --verbose also +informational messages like processing details are reported. Option +\e --debug can be used to get more details on the internal activity, e.g. for +debugging purposes. Other logging levels can be selected using option +\e --log-level. In \e --quiet mode only fatal errors are reported. In such +very severe error events, the application will usually terminate. For more +details on the different logging levels, see documentation of module "oflog". + +In case the logging output should be written to file (optionally with logfile +rotation), to syslog (Unix) or the event log (Windows) option \e --log-config +can be used. This configuration file also allows for directing only certain +messages to a particular output stream and for filtering certain messages +based on the module or application where they are generated. An example +configuration file is provided in \/logger.cfg. + +\section command_line COMMAND LINE + +All command line tools use the following notation for parameters: square +brackets enclose optional values (0-1), three trailing dots indicate that +multiple values are allowed (1-n), a combination of both means 0 to n values. + +Command line options are distinguished from parameters by a leading '+' or '-' +sign, respectively. Usually, order and position of command line options are +arbitrary (i.e. they can appear anywhere). However, if options are mutually +exclusive the rightmost appearance is used. This behavior conforms to the +standard evaluation rules of common Unix shells. + +In addition, one or more command files can be specified using an '@' sign as a +prefix to the filename (e.g. \@command.txt). Such a command argument +is replaced by the content of the corresponding text file (multiple +whitespaces are treated as a single separator unless they appear between two +quotation marks) prior to any further evaluation. Please note that a command +file cannot contain another command file. This simple but effective approach +allows one to summarize common combinations of options/parameters and avoids +longish and confusing command lines (an example is provided in file +\/dumppat.txt). + +\section environment ENVIRONMENT + +The \b pdf2dcm utility will attempt to load DICOM data dictionaries specified +in the \e DCMDICTPATH environment variable. By default, i.e. if the +\e DCMDICTPATH environment variable is not set, the file +\/dicom.dic will be loaded unless the dictionary is built +into the application (default for Windows). + +The default behavior should be preferred and the \e DCMDICTPATH environment +variable only used when alternative data dictionaries are required. The +\e DCMDICTPATH environment variable has the same format as the Unix shell +\e PATH variable in that a colon (":") separates entries. On Windows systems, +a semicolon (";") is used as a separator. The data dictionary code will +attempt to load each file specified in the \e DCMDICTPATH environment variable. +It is an error if no data dictionary can be loaded. + +\section see_also SEE ALSO + +dcm2pdf(1) + +\section copyright COPYRIGHT + +Copyright (C) 2005-2014 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany. + +*/ diff --git a/dcmdata/docs/xml2dcm.man b/dcmdata/docs/xml2dcm.man new file mode 100644 index 00000000..c54243bb --- /dev/null +++ b/dcmdata/docs/xml2dcm.man @@ -0,0 +1,343 @@ +/*! + +\if MANPAGES +\page xml2dcm Convert XML document to DICOM file or data set +\else +\page xml2dcm xml2dcm: Convert XML document to DICOM file or data set +\endif + +\section synopsis SYNOPSIS + +\verbatim +xml2dcm [options] xmlfile-in dcmfile-out +\endverbatim + +\section description DESCRIPTION + +The \b xml2dcm utility converts the contents of an XML (Extensible Markup +Language) document to DICOM file or data set. The XML document is expected to +validate against the DTD (Document Type Definition) which is described in file +dcm2xml.dtd. An appropriate XML file can be created using the +\b dcm2xml tool (option \e +Wb recommended to include binary data). + +\section parameters PARAMETERS + +\verbatim +xmlfile-in XML input filename to be converted (stdin: "-") + +dcmfile-out DICOM output filename +\endverbatim + +\section options OPTIONS + +\subsection general_options general options +\verbatim + -h --help + print this help text and exit + + --version + print version information and exit + + --arguments + print expanded command line arguments + + -q --quiet + quiet mode, print no warnings and errors + + -v --verbose + verbose mode, print processing details + + -d --debug + debug mode, print debug information + + -ll --log-level [l]evel: string constant + (fatal, error, warn, info, debug, trace) + use level l for the logger + + -lc --log-config [f]ilename: string + use config file f for the logger +\endverbatim + +\subsection input_options input options +\verbatim +input file format: + + +f --read-meta-info + read meta information if present (default) + + -f --ignore-meta-info + ignore file meta information +\endverbatim + +\subsection processing_options processing options +\verbatim +validation: + + +Vd --validate-document + validate XML document against DTD + + +Vn --check-namespace + check XML namespace in document root + +unique identifiers: + + +Ug --generate-new-uids + generate new Study/Series/SOP Instance UID + + -Uo --dont-overwrite-uids + do not overwrite existing UIDs (default) + + +Uo --overwrite-uids + overwrite existing UIDs +\endverbatim + +\subsection output_options output options +\verbatim +output file format: + + +F --write-file + write file format (default) + + -F --write-dataset + write data set without file meta information + + +Fu --update-meta-info + update particular file meta information + +output transfer syntax: + + +t= --write-xfer-same + write with same TS as input (default) + + +te --write-xfer-little + write with explicit VR little endian TS + + +tb --write-xfer-big + write with explicit VR big endian TS + + +ti --write-xfer-implicit + write with implicit VR little endian TS + + +td --write-xfer-deflated + write with deflated explicit VR little endian TS + +post-1993 value representations: + + +u --enable-new-vr + enable support for new VRs (UN/UT) (default) + + -u --disable-new-vr + disable support for new VRs, convert to OB + +group length encoding: + + +g= --group-length-recalc + recalculate group lengths if present (default) + + +g --group-length-create + always write with group length elements + + -g --group-length-remove + always write without group length elements + +length encoding in sequences and items: + + +e --length-explicit + write with explicit lengths (default) + + -e --length-undefined + write with undefined lengths + +data set trailing padding (not with --write-dataset): + + -p= --padding-retain + do not change padding (default if not --write-dataset) + + -p --padding-off + no padding (implicit if --write-dataset) + + +p --padding-create [f]ile-pad [i]tem-pad: integer + align file on multiple of f bytes and items on + multiple of i bytes + +deflate compression level (only with --write-xfer-deflated): + + +cl --compression-level [l]evel: integer (default: 6) + 0=uncompressed, 1=fastest, 9=best compression +\endverbatim + +\section notes NOTES + +The basic structure of the XML input expected looks like the following: + +\verbatim + + + + + + 166 + + ... + + OFFIS_DCMTK_353 + + + + + ISO_IR 100 + + ... + + + + 256\\0\\8 + + ... + + ... + + ... + + + + +\endverbatim + +The "file-format" and "meta-header" tags may be absent for DICOM data sets. + +\subsection character_encoding Character Encoding + +The DICOM character encoding is determined automatically from the element with +tag "0008,0005" (Specific Character Set) - if present. The following +character sets are currently supported (requires \b libxml to include \b iconv +support, see \e --version output): + +\verbatim +ASCII (ISO_IR 6) (UTF-8) +UTF-8 "ISO_IR 192" (UTF-8) +ISO Latin 1 "ISO_IR 100" (ISO-8859-1) +ISO Latin 2 "ISO_IR 101" (ISO-8859-2) +ISO Latin 3 "ISO_IR 109" (ISO-8859-3) +ISO Latin 4 "ISO_IR 110" (ISO-8859-4) +ISO Latin 5 "ISO_IR 148" (ISO-8859-9) +Cyrillic "ISO_IR 144" (ISO-8859-5) +Arabic "ISO_IR 127" (ISO-8859-6) +Greek "ISO_IR 126" (ISO-8859-7) +Hebrew "ISO_IR 138" (ISO-8859-8) +\endverbatim + +Multiple character sets are not supported (only the first value of the +"Specific Character Set" is used for the character encoding in case of value +multiplicity). + +See \b dcm2xml documentation for more details on the XML structure. + +\subsection binary_data Binary Data + +Binary data can be encoded either as a sequence of hex numbers separated by a +backslash "\" or in Base64 format (binary="base64"). In addition, binary data +can also be read from file (binary="file"). In this case, the filename has to +be specified as the element value, e.g. + +\verbatim +subdir/pixeldata.raw +\endverbatim + +Please note that the contents of the file will be read as is. OW data is +expected to be little endian ordered and will be swapped if necessary. No +checks will be made to ensure that the amount of data is reasonable in terms +of other attributes such as Rows or Columns. + +\subsection compression Compression + +If libxml is compiled with zlib support, the input file (\e xmlfile-in) can +also be compressed with ZIP, which usually results in much smaller files. See +output of option \e --version in order to check whether zlib support is +available. + +\subsection limitations Limitations + +Different versions of libxml might have different limits for the maximum +length of an XML element value. Therefore, it should be avoided to use very +long element values (e.g. for pixel data). + +Please note that \b xml2dcm currently does not fully support DICOMDIR files. +Specifically, the value of the various offset data elements is not updated +automatically by this tool. + +\section logging LOGGING + +The level of logging output of the various command line tools and underlying +libraries can be specified by the user. By default, only errors and warnings +are written to the standard error stream. Using option \e --verbose also +informational messages like processing details are reported. Option +\e --debug can be used to get more details on the internal activity, e.g. for +debugging purposes. Other logging levels can be selected using option +\e --log-level. In \e --quiet mode only fatal errors are reported. In such +very severe error events, the application will usually terminate. For more +details on the different logging levels, see documentation of module "oflog". + +In case the logging output should be written to file (optionally with logfile +rotation), to syslog (Unix) or the event log (Windows) option \e --log-config +can be used. This configuration file also allows for directing only certain +messages to a particular output stream and for filtering certain messages +based on the module or application where they are generated. An example +configuration file is provided in \/logger.cfg. + +\section command_line COMMAND LINE + +All command line tools use the following notation for parameters: square +brackets enclose optional values (0-1), three trailing dots indicate that +multiple values are allowed (1-n), a combination of both means 0 to n values. + +Command line options are distinguished from parameters by a leading '+' or '-' +sign, respectively. Usually, order and position of command line options are +arbitrary (i.e. they can appear anywhere). However, if options are mutually +exclusive the rightmost appearance is used. This behavior conforms to the +standard evaluation rules of common Unix shells. + +In addition, one or more command files can be specified using an '@' sign as a +prefix to the filename (e.g. \@command.txt). Such a command argument +is replaced by the content of the corresponding text file (multiple +whitespaces are treated as a single separator unless they appear between two +quotation marks) prior to any further evaluation. Please note that a command +file cannot contain another command file. This simple but effective approach +allows one to summarize common combinations of options/parameters and avoids +longish and confusing command lines (an example is provided in file +\/dumppat.txt). + +\section environment ENVIRONMENT + +The \b xml2dcm utility will attempt to load DICOM data dictionaries specified +in the \e DCMDICTPATH environment variable. By default, i.e. if the +\e DCMDICTPATH environment variable is not set, the file +\/dicom.dic will be loaded unless the dictionary is built +into the application (default for Windows). + +The default behavior should be preferred and the \e DCMDICTPATH environment +variable only used when alternative data dictionaries are required. The +\e DCMDICTPATH environment variable has the same format as the Unix shell +\e PATH variable in that a colon (":") separates entries. On Windows systems, +a semicolon (";") is used as a separator. The data dictionary code will +attempt to load each file specified in the \e DCMDICTPATH environment variable. +It is an error if no data dictionary can be loaded. + +\section files FILES + +\/dcm2xml.dtd - Document Type Definition (DTD) file + +\section see_also SEE ALSO + +dcm2xml(1) + +\section copyright COPYRIGHT + +Copyright (C) 2003-2014 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany. + +*/ diff --git a/dcmdata/etc/Makefile.in b/dcmdata/etc/Makefile.in new file mode 100644 index 00000000..5018dc7b --- /dev/null +++ b/dcmdata/etc/Makefile.in @@ -0,0 +1,23 @@ +# +# Makefile for dcmdata/etc +# + +@SET_MAKE@ + +SHELL = /bin/sh +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +configdir = @top_srcdir@/@configdir@ + +include $(configdir)/@common_makefile@ + + +all: + +install: + +clean: + rm -f $(TRASH) + +distclean: + rm -f $(DISTTRASH) diff --git a/dcmdata/include/CMakeLists.txt b/dcmdata/include/CMakeLists.txt new file mode 100644 index 00000000..fb1b52f3 --- /dev/null +++ b/dcmdata/include/CMakeLists.txt @@ -0,0 +1,2 @@ +# declare installation files +INSTALL(DIRECTORY dcmtk/dcmdata DESTINATION ${DCMTK_INSTALL_INCDIR}/dcmtk COMPONENT include FILES_MATCHING PATTERN "*.h") diff --git a/dcmdata/include/Makefile.in b/dcmdata/include/Makefile.in new file mode 100644 index 00000000..25103028 --- /dev/null +++ b/dcmdata/include/Makefile.in @@ -0,0 +1,32 @@ +# +# Makefile for dcmdata/include +# + +@SET_MAKE@ + +SHELL = /bin/sh +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +configdir = @top_srcdir@/@configdir@ + +include $(configdir)/@common_makefile@ + + +all: + +install: + $(configdir)/mkinstalldirs $(DESTDIR)$(includedir)/dcmtk/dcmdata + for file in dcmtk/dcmdata/*.h ; do \ + $(INSTALL_DATA) $$file $(DESTDIR)$(includedir)/dcmtk/dcmdata ;\ + done + $(configdir)/mkinstalldirs $(DESTDIR)$(includedir)/dcmtk/dcmdata/libi2d + for file in dcmtk/dcmdata/libi2d/*.h ; do \ + $(INSTALL_DATA) $$file $(DESTDIR)$(includedir)/dcmtk/dcmdata/libi2d ;\ + done + + +clean: + rm -f $(TRASH) + +distclean: + rm -f $(DISTTRASH) diff --git a/dcmdata/include/dcmtk/dcmdata/cmdlnarg.h b/dcmdata/include/dcmtk/dcmdata/cmdlnarg.h new file mode 100644 index 00000000..82c4c55f --- /dev/null +++ b/dcmdata/include/dcmtk/dcmdata/cmdlnarg.h @@ -0,0 +1,53 @@ +/* + * + * Copyright (C) 1994-2012, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Andrew Hewett + * + * Purpose: Provide prototype of command line argument gathering routine + * for OS environments which cannot pass arguments on the command line. + * + */ + +#ifndef CMDLNARG_H +#define CMDLNARG_H + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/dcmdata/dcdefine.h" + +/** this function is used on certain operating systems (in particular, classic MacOS) + * and allows command line arguments to be input from stdin. + * MT level: Thread unsafe! + * @param argc the argc parameter of main() is passed in this parameter + * @param argv the argv parameter of main() is passed in this parameter + * @param progname program name + */ +DCMTK_DCMDATA_EXPORT void prepareCmdLineArgs(int& argc, char** argv, const char* progname = "aProgram"); + +#ifdef HAVE_WINDOWS_H + +/** this function is used on certain operating systems (in particular, classic MacOS) + * and allows command line arguments to be input from stdin. + * MT level: Thread unsafe! + * This is a Windows-specific version supporting the wide character encoding (UTF-16). + * @param argc the argc parameter of main() is passed in this parameter (not used) + * @param argv the argv parameter of main() is passed in this parameter (not used) + * @param progname program name (not used) + */ +DCMTK_DCMDATA_EXPORT void prepareCmdLineArgs(int& argc, wchar_t** argv, const char* progname = "aProgram"); + +#endif // HAVE_WINDOWS_H + +#endif diff --git a/dcmdata/include/dcmtk/dcmdata/dcbytstr.h b/dcmdata/include/dcmtk/dcmdata/dcbytstr.h new file mode 100644 index 00000000..ada8a415 --- /dev/null +++ b/dcmdata/include/dcmtk/dcmdata/dcbytstr.h @@ -0,0 +1,419 @@ +/* + * + * Copyright (C) 1994-2013, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Gerd Ehlers, Andreas Barth + * + * Purpose: Interface of class DcmByteString + * + */ + + +#ifndef DCBYTSTR_H +#define DCBYTSTR_H + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/dcmdata/dctypes.h" +#include "dcmtk/dcmdata/dcelem.h" +#include "dcmtk/ofstd/ofstring.h" + + +/** This flag defines whether the VR checker is actually used by the various + * checkStringValue() methods. Since this checker is currently limited to + * ASCII and Latin-1, and the detection of the character set might fail for + * incorrectly encoded DICOM datasets, this check can be disabled globally. + * Please note, however, that other checks (i.e. VM and max. value length) + * are still performed if the optional parameters are set accordingly. + * By default, the VR checker is enabled (value: "OFTrue"). + */ +extern DCMTK_DCMDATA_EXPORT OFGlobal dcmEnableVRCheckerForStringValues; /* default: OFTrue */ + + +/** base class for all DICOM value representations storing a character string + */ +class DCMTK_DCMDATA_EXPORT DcmByteString: public DcmElement +{ + + public: + + /** constructor. + * Create new element from given tag and length. + * @param tag DICOM tag for the new element + * @param len value length for the new element + */ + DcmByteString(const DcmTag &tag, + const Uint32 len = 0); + + /** copy constructor + * @param old element to be copied + */ + DcmByteString(const DcmByteString &old); + + /** destructor + */ + virtual ~DcmByteString(); + + /** assignment operator + * @param obj element to be assigned/copied + * @return reference to this object + */ + DcmByteString& operator=(const DcmByteString& obj); + + /** comparison operator that compares the normalized value of this object + * with a given object of the same type. The tag of the element is also + * considered as the first component that is compared, followed by the + * object types (VR, i.e. DCMTK'S EVR) and the comparison of all value + * components of the object, preferrably in the order declared in the + * object (if applicable). + * @param rhs the right hand side of the comparison + * @return 0 if the object values are equal. + * -1 if either the value of the first component that does not match + * is lower in this object than in rhs, or all compared components match + * but this object has fewer components than rhs. Also returned if rhs + * cannot be casted to this object type. + * 1 if either the value of the first component that does not match + * is greater in this object than in rhs object, or all compared + * components match but the this component is longer. + */ + virtual int compare(const DcmElement& rhs) const; + + + /** clone method + * @return deep copy of this object + */ + virtual DcmObject *clone() const + { + return new DcmByteString(*this); + } + + /** Virtual object copying. This method can be used for DcmObject + * and derived classes to get a deep copy of an object. Internally + * the assignment operator is called if the given DcmObject parameter + * is of the same type as "this" object instance. If not, an error + * is returned. This function permits copying an object by value + * in a virtual way which therefore is different to just calling the + * assignment operator of DcmElement which could result in slicing + * the object. + * @param rhs - [in] The instance to copy from. Has to be of the same + * class type as "this" object + * @return EC_Normal if copying was successful, error otherwise + */ + virtual OFCondition copyFrom(const DcmObject& rhs); + + /** get element type identifier + * @return type identifier of this class (EVR_UNKNOWN) + */ + virtual DcmEVR ident() const; + + /** clear the currently stored value + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition clear(); + + /** get value multiplicity + * @return number of string components (separated by a backslash) + */ + virtual unsigned long getVM(); + + /** get length of the stored value. + * Trailing spaces (padding characters) are ignored for the "real" length. + * @return number of characters stored for the string value + */ + Uint32 getRealLength(); + + /** get DICOM length of the stored value. + * The string value is padded if required. Therefore, the returned length + * always has an even value. + * @param xfer not used + * @param enctype not used + * @return number of characters stored in DICOM representation + */ + virtual Uint32 getLength(const E_TransferSyntax xfer = EXS_LittleEndianImplicit, + const E_EncodingType enctype = EET_UndefinedLength); + + /** print element to a stream. + * The output format of the value is a backslash separated sequence of string + * components (if any). + * @param out output stream + * @param flags optional flag used to customize the output (see DCMTypes::PF_xxx) + * @param level current level of nested items. Used for indentation. + * @param pixelFileName not used + * @param pixelCounter not used + */ + virtual void print(STD_NAMESPACE ostream&out, + const size_t flags = 0, + const int level = 0, + const char *pixelFileName = NULL, + size_t *pixelCounter = NULL); + + /** write data element to a stream + * @param outStream output stream + * @param oxfer transfer syntax used to write the data + * @param enctype flag, specifying the encoding with undefined or explicit length + * @param wcache pointer to write cache object, may be NULL + */ + virtual OFCondition write(DcmOutputStream &outStream, + const E_TransferSyntax oxfer, + const E_EncodingType enctype, + DcmWriteCache *wcache); + + /** write data element to a stream as required for the creation of digital signatures + * @param outStream output stream + * @param oxfer transfer syntax used to write the data + * @param enctype flag, specifying the encoding with undefined or explicit length + * @param wcache pointer to write cache object, may be NULL + */ + virtual OFCondition writeSignatureFormat(DcmOutputStream &outStream, + const E_TransferSyntax oxfer, + const E_EncodingType enctype, + DcmWriteCache *wcache); + + /** get a copy of a particular string component + * @param stringVal variable in which the result value is stored + * @param pos index of the value in case of multi-valued elements (0..vm-1) + * @param normalize not used since string normalization depends on value representation + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getOFString(OFString &stringVal, + const unsigned long pos, + OFBool normalize = OFTrue); + + /** get entire element value as a character string. + * In case of VM > 1 the individual values are separated by a backslash ('\'). + * @param stringVal variable in which the result value is stored + * @param normalize normalize each element value prior to concatenation + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getOFStringArray(OFString &stringVal, + OFBool normalize = OFTrue); + + /** get a pointer to the current string value. + * This includes all string components and separators. + * NB: This method does not copy the stored value. + * @param stringVal reference to the pointer variable + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getString(char *&stringVal); + + /** get a pointer to the current string value. + * This includes all string components and separators. Since the length is returned + * separately, the string value can contain more than one NULL byte. + * NB: This method does not copy the stored value. + * @param stringVal reference to the pointer variable + * @param stringLen length of the string (number of characters without the trailing + * NULL byte) + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getString(char *&stringVal, + Uint32 &stringLen); + + /** set element value from the given character string. + * The length of the given string is determined automatically by searching for the + * first NULL byte. + * @param stringVal input character string (possibly multi-valued) + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition putString(const char *stringVal); + + /** set element value from the given character string. + * The length of the string has to be specified explicitly. The string can, therefore, + * also contain more than one NULL byte. + * @param stringVal input character string (possibly multi-valued) + * @param stringLen length of the string (number of characters without the trailing + * NULL byte) + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition putString(const char *stringVal, + const Uint32 stringLen); + + /** check the currently stored string value. + * Checks every string component for the maximum length specified for the particular + * value representation. + * @param autocorrect correct value and value component length if OFTrue + * @return status, EC_Normal if value length is correct, an error code otherwise + */ + virtual OFCondition verify(const OFBool autocorrect = OFFalse); + + /** check if this element contains non-ASCII characters. Please note that this check + * is pretty simple and only works for single-byte character sets that do include + * the 7-bit ASCII codes, e.g. for the ISO 8859 family. In other words: All character + * codes below 128 are considered to be ASCII codes and all others are considered to + * be non-ASCII. + * @param checkAllStrings if true, also check elements with string values not affected + * by SpecificCharacterSet (0008,0005), default: only check PN, LO, LT, SH, ST, UT + * @return true if element contains non-ASCII characters, false otherwise + */ + virtual OFBool containsExtendedCharacters(const OFBool checkAllStrings = OFFalse); + + /** check if this element is affected by SpecificCharacterSet + * @return always returns false since none of the derived VR classes is affected by + * the SpecificCharacterSet (0008,0005) element + */ + virtual OFBool isAffectedBySpecificCharacterSet() const; + + /** check if this object is empty + * @param normalize normalize value before checking (ignore non-significant characters) + * @return true if object is empty, i.e.\ has no value, false otherwise + */ + virtual OFBool isEmpty(const OFBool normalize = OFTrue); + + protected: + + /// internal type used to specify the current string representation + enum E_StringMode + { + /// string has internal representation (no padding) + DCM_MachineString, + /// string has DICOM representation (even length) + DCM_DicomString, + /// string has unknown representation (maybe multiple padding chars?) + DCM_UnknownString + }; + + /** create a new value field (string buffer) of the previously defined size + * (member variable 'Length'). Also handles odd value length by allocating + * extra space for the padding character. + * This method is used by derived classes only. + * @return pointer to the newly created value field + */ + virtual Uint8 *newValueField(); + + /** method is called after the element value has been loaded. + * Can be used to correct the value before it is used for the first time. + */ + virtual void postLoadValue(); + + /** get current representation of the string value + * @return current representation of the string value + */ + E_StringMode getStringMode() const { return fStringMode; } + + /** convert currently stored string value to internal representation. + * It removes any trailing space character and recomputes the string length. + * @param length number of characters of the string value (optional) + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition makeMachineByteString(const Uint32 length = 0); + + /** convert currently stored string value to DICOM representation. + * It removes trailing spaces apart from a possibly required single padding + * character (in case of odd string length). + * @return status, EC_Normal if successful, an error code otherwise + */ + OFCondition makeDicomByteString(); + + /** get a copy of the current string value. + * This includes all string components and separators. + * @param stringVal variable in which the result is stored + * @return status, EC_Normal if successful, an error code otherwise + */ + OFCondition getStringValue(OFString &stringVal); + + /** get the maximum number of characters for each string component + * @return maximum number of characters for each string component + */ + Uint32 getMaxLength() const { return maxLength; } + + /** get the end-of-string padding character + * @return end-of-string padding character + */ + char getPaddingChar() const { return paddingChar; } + + /** set the end-of-string padding character + * @param c end-of-string padding character + */ + void setPaddingChar(char c) { paddingChar = c; } + + /** set the maximum number of characters for each string component + * @param val maximum number of characters for each string component + */ + void setMaxLength(Uint32 val) { maxLength = val; } + + /** set non-significant characters used to determine whether the value is empty + * @param characters non-significant characters used to determine whether the value is empty + */ + void setNonSignificantChars(const OFString &characters) { nonSignificantChars = characters; } + + /* --- static helper functions --- */ + + /** check whether given string value conforms to a certain VR and VM. + * @param value string value to be checked (possibly multi-valued) + * @param vm value multiplicity (according to the data dictionary) to be checked for. + * (See DcmElement::checkVM() for a list of valid values; "" for no check.) + * @param vr two-character identifier of the VR to be checked (lower case) + * @param vrID expected numeric identifier of the VR + * @param maxLen maximum number of characters allowed for a single value (0 = no check) + * @param charset character set (according to the value of the SpecificCharacterSet + * element) to be used for checking the string value. The default is ASCII (7-bit). + * @return status of the check, EC_Normal if value is correct, an error code otherwise + */ + static OFCondition checkStringValue(const OFString &value, + const OFString &vm, + const OFString &vr, + const int vrID, + const size_t maxLen = 0, + const OFString &charset = ""); + +private: + + /// padding character used to adjust odd value length (e.g. a space) + char paddingChar; + + /// maximum number of characters for each string component + Uint32 maxLength; + + /// number of characters of the internal string representation + Uint32 realLength; + + /// current representation of the string value + E_StringMode fStringMode; + + /// non-significant characters used to determine whether the value is empty + OFString nonSignificantChars; +}; + + +/** @name string normalization flags. + * These flags can be used with normalizeString() to specify the extent of normalization. + */ +//@{ + +/// delete trailing spaces +const OFBool DELETE_TRAILING = OFTrue; +/// delete leading spaces +const OFBool DELETE_LEADING = OFTrue; +/// handle string as multi-valued (components separated by a backslash) +const OFBool MULTIPART = OFTrue; + +//@} + + +/* Function to get part out of a String for VM > 1 */ + +/** normalize the given string value, i.e.\ remove leading and/or trailing padding + * @param string input and output string value to be normalized + * @param multiPart handle string as multi-valued if OFTrue + * @param leading delete leading spaces if OFTrue + * @param trailing delete trailing spaces if OFTrue + * @param paddingChar padding character to be removed (usually a space) + */ +DCMTK_DCMDATA_EXPORT void normalizeString(OFString &string, + const OFBool multiPart, + const OFBool leading, + const OFBool trailing, + const char paddingChar = ' '); + + +#endif // DCBYTSTR_H diff --git a/dcmdata/include/dcmtk/dcmdata/dcchrstr.h b/dcmdata/include/dcmtk/dcmdata/dcchrstr.h new file mode 100644 index 00000000..50611b98 --- /dev/null +++ b/dcmdata/include/dcmtk/dcmdata/dcchrstr.h @@ -0,0 +1,157 @@ +/* + * + * Copyright (C) 1994-2015, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Andreas Barth + * + * Purpose: Interface of class DcmCharString + * + */ + + +#ifndef DCCHRSTR_H +#define DCCHRSTR_H + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +// +// This implementation does not support 16 bit character sets. Since 8 bit +// character sets are supported by the class DcmByteString the class +// DcmCharString is derived from DcmByteString without any extensions. +// +// If the extension for 16 bit character sets will be implemented, this class +// must be derived directly from DcmElement. This class is designed to support +// the value representations (LO, LT, PN, SH, ST, UC and UT). They are a problem +// because their value width (1, 2, ... bytes) is specified by the element +// SpecificCharacterSet (0008,0005) and an implementation must support +// different value widths that cannot be derived from the value representation. +// + +#include "dcmtk/dcmdata/dcbytstr.h" + + +/** base class for DICOM elements with value representation LO, LT, PN, SH, ST, UC and UT + */ +class DCMTK_DCMDATA_EXPORT DcmCharString + : public DcmByteString +{ + + public: + + /** constructor. + * Create new element from given tag and length. + * @param tag DICOM tag for the new element + * @param len value length for the new element + */ + DcmCharString(const DcmTag &tag, + const Uint32 len); + + /** copy constructor + * @param old element to be copied + */ + DcmCharString(const DcmCharString &old); + + /** destructor + */ + virtual ~DcmCharString(); + + /** assignment operator + * @param obj element to be assigned/copied + * @return reference to this object + */ + DcmCharString &operator=(const DcmCharString &obj); + + /** clone method + * @return deep copy of this object + */ + virtual DcmObject *clone() const + { + return new DcmCharString(*this); + } + + /** Virtual object copying. This method can be used for DcmObject + * and derived classes to get a deep copy of an object. Internally + * the assignment operator is called if the given DcmObject parameter + * is of the same type as "this" object instance. If not, an error + * is returned. This function permits copying an object by value + * in a virtual way which therefore is different to just calling the + * assignment operator of DcmElement which could result in slicing + * the object. + * @param rhs - [in] The instance to copy from. Has to be of the same + * class type as "this" object + * @return EC_Normal if copying was successful, error otherwise + */ + virtual OFCondition copyFrom(const DcmObject& rhs); + + /** check the currently stored string value. + * Checks every string component for the maximum length specified for the particular + * value representation. + * @param autocorrect correct value and value component length if OFTrue. + * NB: This parameter does currently nothing since it is unknown to this class + * whether a character consists of one or more bytes. To be fixed in a future + * version when multi-byte character sets are (hopefully) supported. + * @return status, EC_Normal if value length is correct, an error code otherwise + */ + virtual OFCondition verify(const OFBool autocorrect = OFFalse); + + /** check if this element contains non-ASCII characters. Please note that this check + * is pretty simple and only works for single-byte character sets that do include + * the 7-bit ASCII codes, e.g. for the ISO 8859 family. In other words: All character + * codes below 128 are considered to be ASCII codes and all others are considered to + * be non-ASCII. + * @param checkAllStrings not used in this class + * @return true if element contains non-ASCII characters, false otherwise + */ + virtual OFBool containsExtendedCharacters(const OFBool checkAllStrings = OFFalse); + + /** check if this element is affected by SpecificCharacterSet + * @return always returns true since all derived VR classes are affected by the + * SpecificCharacterSet (0008,0005) element + */ + virtual OFBool isAffectedBySpecificCharacterSet() const; + + /** convert this element value from the currently selected source character set to + * the currently selected destination character set + * @param converter character set converter to be used to convert the element value + * @return always returns EC_Normal, since nothing to do in this base class + */ + virtual OFCondition convertCharacterSet(DcmSpecificCharacterSet &converter); + + protected: + + /** delimiter characters specifying when to switch back to the default character set + * (in case code extension techniques like ISO 2022 are used) + * @param characters delimiter characters to be used for character set conversion + */ + void setDelimiterChars(const OFString &characters) { delimiterChars = characters; } + + /** get value of the SpecificCharacterSet element of the surrounding dataset/item + * @param charset reference to variable that will store the result value. The + * variable is not cleared in case of error! + * @return status, EC_Normal if successful (i.e. the element could be found), + * an error code otherwise. Typical error codes are: + * - EC_TagNotFound if the SpecificCharacterSet element could not be found + * - EC_CorruptedData if this object is not contained in a dataset/item + */ + OFCondition getSpecificCharacterSet(OFString &charset); + + private: + + /// delimiter characters specifying when to switch back to the default character set + /// (in case code extension techniques like ISO 2022 are used) + OFString delimiterChars; +}; + + +#endif // DCCHRSTR_H diff --git a/dcmdata/include/dcmtk/dcmdata/dccodec.h b/dcmdata/include/dcmtk/dcmdata/dccodec.h new file mode 100644 index 00000000..5fad12c3 --- /dev/null +++ b/dcmdata/include/dcmtk/dcmdata/dccodec.h @@ -0,0 +1,516 @@ +/* + * + * Copyright (C) 1997-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Andreas Barth + * + * Purpose: Interface of abstract class DcmCodec and the class DcmCodecStruct + * + */ + +#ifndef DCCODEC_H +#define DCCODEC_H + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ +#include "dcmtk/ofstd/ofcond.h" +#include "dcmtk/dcmdata/dctypes.h" +#include "dcmtk/dcmdata/dcxfer.h" +#include "dcmtk/ofstd/oflist.h" + +class DcmStack; +class DcmRepresentationParameter; +class DcmPixelSequence; +class DcmPolymorphOBOW; +class DcmItem; +class DcmTagKey; + +/** abstract base class for a codec parameter object that + * describes the settings (modes of operations) for one + * particular codec (DcmCodec) object. + */ +class DCMTK_DCMDATA_EXPORT DcmCodecParameter +{ +public: + /// default constructor + DcmCodecParameter() {} + + /// copy constructor + DcmCodecParameter(const DcmCodecParameter&) {} + + /// destructor + virtual ~DcmCodecParameter() {} + + /** this methods creates a copy of type DcmCodecParameter * + * it must be overweritten in every subclass. + * @return copy of this object + */ + virtual DcmCodecParameter *clone() const = 0; + + /** returns the class name as string. + * can be used as poor man's RTTI replacement. + */ + virtual const char *className() const = 0; + +}; + + +/** abstract base class for a codec object that can be registered + * in dcmdata and performs transfer syntax transformation (i.e. + * compressing, decompressing or transcoding between different + * compressed transfer syntaxes). + * When dcmdata is requested to write a transfer syntax that differs + * from the current one (i.e. the one in which the object was read), + * dcmdata dynamically searches for a DcmCodec object that is able + * to create the desired transfer syntax. If no suitable codec + * is found, the write operation fails. + */ +class DCMTK_DCMDATA_EXPORT DcmCodec +{ +public: + /// default constructor + DcmCodec() {} + + /// destructor + virtual ~DcmCodec() {} + + /** decompresses the given pixel sequence and + * stores the result in the given uncompressedPixelData element. + * @param fromRepParam current representation parameter of compressed data, may be NULL + * @param pixSeq compressed pixel sequence + * @param uncompressedPixelData uncompressed pixel data stored in this element + * @param cp codec parameters for this codec + * @param objStack stack pointing to the location of the pixel data + * element in the current dataset. + * @return EC_Normal if successful, an error code otherwise. + */ + virtual OFCondition decode( + const DcmRepresentationParameter * fromRepParam, + DcmPixelSequence * pixSeq, + DcmPolymorphOBOW& uncompressedPixelData, + const DcmCodecParameter * cp, + const DcmStack& objStack) const = 0; + + /** decompresses a single frame from the given pixel sequence and + * stores the result in the given buffer. + * @param fromParam representation parameter of current compressed + * representation, may be NULL. + * @param fromPixSeq compressed pixel sequence + * @param cp codec parameters for this codec + * @param dataset pointer to dataset in which pixel data element is contained + * @param frameNo number of frame, starting with 0 for the first frame + * @param startFragment index of the compressed fragment that contains + * all or the first part of the compressed bitstream for the given frameNo. + * Upon successful return this parameter is updated to contain the index + * of the first compressed fragment of the next frame. + * When unknown, zero should be passed. In this case the decompression + * algorithm will try to determine the index by itself, which will always + * work if frames are decompressed in increasing order from first to last, + * but may fail if frames are decompressed in random order, multiple fragments + * per frame and multiple frames are present in the dataset, and the offset + * table is empty. + * @param buffer pointer to buffer where frame is to be stored + * @param bufSize size of buffer in bytes + * @param decompressedColorModel upon successful return, the color model + * of the decompressed image (which may be different from the one used + * in the compressed images) is returned in this parameter. + * @return EC_Normal if successful, an error code otherwise. + */ + virtual OFCondition decodeFrame( + const DcmRepresentationParameter * fromParam, + DcmPixelSequence * fromPixSeq, + const DcmCodecParameter * cp, + DcmItem *dataset, + Uint32 frameNo, + Uint32& startFragment, + void *buffer, + Uint32 bufSize, + OFString& decompressedColorModel) const = 0; + + /** compresses the given uncompressed DICOM image and stores + * the result in the given pixSeq element. + * @param pixelData pointer to the uncompressed image data in OW format + * and local byte order + * @param length of the pixel data field in bytes + * @param toRepParam representation parameter describing the desired + * compressed representation (e.g. JPEG quality) + * @param pixSeq compressed pixel sequence (pointer to new DcmPixelSequence object + * allocated on heap) returned in this parameter upon success. + * @param cp codec parameters for this codec + * @param objStack stack pointing to the location of the pixel data + * element in the current dataset. + * @return EC_Normal if successful, an error code otherwise. + */ + virtual OFCondition encode( + const Uint16 * pixelData, + const Uint32 length, + const DcmRepresentationParameter * toRepParam, + DcmPixelSequence * & pixSeq, + const DcmCodecParameter *cp, + DcmStack & objStack) const = 0; + + /** transcodes (re-compresses) the given compressed DICOM image and stores + * the result in the given toPixSeq element. + * @param fromRepType current transfer syntax of the compressed image + * @param fromRepParam current representation parameter of compressed data, may be NULL + * @param fromPixSeq compressed pixel sequence + * @param toRepParam representation parameter describing the desired + * new compressed representation (e.g. JPEG quality) + * @param toPixSeq compressed pixel sequence (pointer to new DcmPixelSequence object + * allocated on heap) returned in this parameter upon success. + * @param cp codec parameters for this codec + * @param objStack stack pointing to the location of the pixel data + * element in the current dataset. + * @return EC_Normal if successful, an error code otherwise. + */ + virtual OFCondition encode( + const E_TransferSyntax fromRepType, + const DcmRepresentationParameter * fromRepParam, + DcmPixelSequence * fromPixSeq, + const DcmRepresentationParameter * toRepParam, + DcmPixelSequence * & toPixSeq, + const DcmCodecParameter * cp, + DcmStack & objStack) const = 0; + + /** checks if this codec is able to convert from the + * given current transfer syntax to the given new + * transfer syntax + * @param oldRepType current transfer syntax + * @param newRepType desired new transfer syntax + * @return true if transformation is supported by this codec, false otherwise. + */ + virtual OFBool canChangeCoding( + const E_TransferSyntax oldRepType, + const E_TransferSyntax newRepType) const = 0; + + /** determine color model of the decompressed image + * @param fromParam representation parameter of current compressed + * representation, may be NULL + * @param fromPixSeq compressed pixel sequence + * @param cp codec parameters for this codec + * @param dataset pointer to dataset in which pixel data element is contained + * @param dataset pointer to DICOM dataset in which this pixel data object + * is located. Used to access photometric interpretation. + * @param decompressedColorModel upon successful return, the color model + * of the decompressed image (which may be different from the one used + * in the compressed images) is returned in this parameter + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition determineDecompressedColorModel( + const DcmRepresentationParameter *fromParam, + DcmPixelSequence *fromPixSeq, + const DcmCodecParameter *cp, + DcmItem *dataset, + OFString &decompressedColorModel) const = 0; + + // static helper methods that have proven useful in codec classes derived from DcmCodec + + /** helper function that inserts a string attribute with a given value into a dataset + * if missing in the dataset. + * @param dataset dataset to insert to, must not be NULL. + * @param tag tag key of attribute to check/insert + * @param val string value, may be NULL. + * @return EC_Normal if successful, an error code otherwise + */ + static OFCondition insertStringIfMissing(DcmItem *dataset, const DcmTagKey& tag, const char *val); + + /** helper function that converts a dataset containing a DICOM image + * into a valid (standard extended) Secondary Capture object + * by inserting all attributes that are type 1/2 in Secondary Capture + * and missing in the source dataset. Replaces SOP Class UID + * by Secondary Capture. It does not, however, change an existing SOP Instance UID. + * @param dataset dataset to insert to, must not be NULL. + * @return EC_Normal if successful, an error code otherwise + */ + static OFCondition convertToSecondaryCapture(DcmItem *dataset); + + /** create new SOP instance UID and Source Image Sequence + * referencing the old SOP instance (if present) + * @param dataset dataset to be modified + * @param purposeOfReferenceCodingScheme coding scheme designator for purpose of reference code sequence + * @param purposeOfReferenceCodeValue code value for purpose of reference code sequence + * @param purposeOfReferenceCodeMeaning code meaning for purpose of reference code sequence + * @return EC_Normal if successful, an error code otherwise + */ + static OFCondition newInstance( + DcmItem *dataset, + const char *purposeOfReferenceCodingScheme = NULL, + const char *purposeOfReferenceCodeValue = NULL, + const char *purposeOfReferenceCodeMeaning = NULL); + + /** set first value of Image Type to DERIVED. + * @param dataset dataset to be modified + * @return EC_Normal if successful, an error code otherwise + */ + static OFCondition updateImageType(DcmItem *dataset); + + /** insert code sequence into the given dataset + * @param dataset dataset to insert into + * @param tagKey tag of the code sequence + * @param codingSchemeDesignator coding scheme designator for the sequence item + * @param codeValue code value for the sequence item + * @param codeMeaning code meaning for the sequence item + * @return EC_Normal if successul, an error code otherwise + */ + static OFCondition insertCodeSequence( + DcmItem *dataset, + const DcmTagKey &tagKey, + const char *codingSchemeDesignator, + const char *codeValue, + const char *codeMeaning); + + /** determine the index number (starting with zero) of the compressed pixel data fragment + * corresponding to the given frame (also starting with zero) + * @param frameNo frame number + * @param numberOfFrames number of frames of this image + * @param fromPixSeq compressed pixel sequence + * @param currentItem index of compressed pixel data fragment returned in this parameter on success + * @return EC_Normal if successful, an error code otherwise + */ + static OFCondition determineStartFragment( + Uint32 frameNo, + Sint32 numberOfFrames, + DcmPixelSequence * fromPixSeq, + Uint32& currentItem); +}; + + +/** singleton that keeps list of registered codecs for dcmdata. + * All operations on the list are protected by a read/write lock + * and, therefore, are safe for multi-thread applications. + */ +class DCMTK_DCMDATA_EXPORT DcmCodecList +{ + +public: + + /// destructor + virtual ~DcmCodecList(); + + /** registers a codec object in the global list of codecs consulted by dcmdata + * whenever conversion to/from compressed transfer syntaxes is requested. + * This function must not be called before main() is started, e.g. from + * a constructor of a global object. + * This call is safe in multi-thread operations. + * @param aCodec pointer to codec object. + * Must remain unmodified and valid until the codec has been deregistered. + * @param aDefaultRepParam default representation parameter. + * Must remain unmodified and valid until the codec has been deregistered. + * @param aCodecParameter codec parameter. + * Must remain unmodified and valid until the codec has been deregistered or the + * parameter has been replaced by a call to updateCodecParameter() + * @return EC_Normal if successful, an error code otherwise + */ + static OFCondition registerCodec( + const DcmCodec *aCodec, + const DcmRepresentationParameter *aDefaultRepParam, + const DcmCodecParameter *aCodecParameter); + + /** deregisters a codec and it's parameter objects from the global list. + * This call is safe in multi-thread operations. + * @param aCodec pointer to registered codec + * @return EC_Normal if successful, an error code otherwise + */ + static OFCondition deregisterCodec(const DcmCodec *aCodec); + + /** updates the codec parameters object for a codec that has been registered before. + * This call is safe in multi-thread operations. + * @param aCodec pointer to codec object that has been registered before + * @param aCodecParameter codec parameter. + * Must remain unmodified and valid until the codec has been deregistered or the + * parameter has been replaced by another call to updateCodecParameter() + * @return EC_Normal if successful, an error code otherwise + */ + static OFCondition updateCodecParameter( + const DcmCodec *aCodec, + const DcmCodecParameter *aCodecParameter); + + /** looks for a codec that is able to decode from the given transfer syntax + * and calls the decode() method of the codec. A read lock on the list of + * codecs is acquired until this method returns. + * @param fromType transfer syntax to decode from + * @param fromParam representation parameter of current compressed + * representation, may be NULL. + * @param fromPixSeq compressed pixel sequence + * @param uncompressedPixelData uncompressed pixel data stored in this element + * @param pixelStack stack pointing to the location of the pixel data + * element in the current dataset. + * @return EC_Normal if successful, an error code otherwise. + */ + static OFCondition decode( + const DcmXfer & fromType, + const DcmRepresentationParameter * fromParam, + DcmPixelSequence * fromPixSeq, + DcmPolymorphOBOW& uncompressedPixelData, + DcmStack & pixelStack); + + /** looks for a codec that is able to decode from the given transfer syntax + * and calls the decodeFrame() method of the codec. A read lock on the list of + * codecs is acquired until this method returns. + * @param fromType transfer syntax to decode from + * @param fromParam representation parameter of current compressed + * representation, may be NULL. + * @param fromPixSeq compressed pixel sequence + * @param dataset pointer to dataset in which pixel data element is contained + * @param frameNo number of frame, starting with 0 for the first frame + * @param startFragment index of the compressed fragment that contains + * all or the first part of the compressed bitstream for the given frameNo. + * Upon successful return this parameter is updated to contain the index + * of the first compressed fragment of the next frame. + * When unknown, zero should be passed. In this case the decompression + * algorithm will try to determine the index by itself, which will always + * work if frames are decompressed in increasing order from first to last, + * but may fail if frames are decompressed in random order, multiple fragments + * per frame and multiple frames are present in the dataset, and the offset + * table is empty. + * @param buffer pointer to buffer where frame is to be stored + * @param bufSize size of buffer in bytes + * @param decompressedColorModel upon successful return, the color model + * of the decompressed image (which may be different from the one used + * in the compressed images) is returned in this parameter. + * @return EC_Normal if successful, an error code otherwise. + */ + static OFCondition decodeFrame( + const DcmXfer & fromType, + const DcmRepresentationParameter * fromParam, + DcmPixelSequence * fromPixSeq, + DcmItem *dataset, + Uint32 frameNo, + Uint32& startFragment, + void *buffer, + Uint32 bufSize, + OFString& decompressedColorModel); + + /** looks for a codec that is able to encode from the given transfer syntax + * and calls the encode() method of the codec. A read lock on the list of + * codecs is acquired until this method returns. + * @param fromRepType transfer syntax to encode from + * @param pixelData pointer to the uncompressed image data in OW format + * and local byte order + * @param length of the pixel data field in bytes + * @param toRepType transfer syntax to compress to + * @param toRepParam representation parameter describing the desired + * compressed representation (e.g. JPEG quality) + * @param pixSeq compressed pixel sequence (pointer to new DcmPixelSequence object + * allocated on heap) returned in this parameter upon success. + * @param pixelStack stack pointing to the location of the pixel data + * element in the current dataset. + * @return EC_Normal if successful, an error code otherwise. + */ + static OFCondition encode( + const E_TransferSyntax fromRepType, + const Uint16 * pixelData, + const Uint32 length, + const E_TransferSyntax toRepType, + const DcmRepresentationParameter * toRepParam, + DcmPixelSequence * & pixSeq, + DcmStack & pixelStack); + + /** looks for a codec that is able to transcode (re-compresses) + * from the given transfer syntax to the given transfer syntax + * and calls the encode() method of the codec. + * A read lock on the list of + * codecs is acquired until this method returns. + * @param fromRepType current transfer syntax of the compressed image + * @param fromParam current representation parameter of compressed data, may be NULL + * @param fromPixSeq compressed pixel sequence + * @param toRepType transfer syntax to compress to + * @param toRepParam representation parameter describing the desired + * new compressed representation (e.g. JPEG quality) + * @param toPixSeq compressed pixel sequence (pointer to new DcmPixelSequence object + * allocated on heap) returned in this parameter upon success. + * @param pixelStack stack pointing to the location of the pixel data + * element in the current dataset. + * @return EC_Normal if successful, an error code otherwise. + */ + static OFCondition encode( + const E_TransferSyntax fromRepType, + const DcmRepresentationParameter * fromParam, + DcmPixelSequence * fromPixSeq, + const E_TransferSyntax toRepType, + const DcmRepresentationParameter * toRepParam, + DcmPixelSequence * & toPixSeq, + DcmStack & pixelStack); + + /** looks for a codec that claims to be able to convert + * between the given transfer syntaxes. + * A read lock on the list of + * codecs is acquired until this method returns. + * @param fromRepType current transfer syntax + * @param toRepType desired new transfer syntax + * @return true if transformation is supported by a codec, false otherwise. + */ + static OFBool canChangeCoding( + const E_TransferSyntax fromRepType, + const E_TransferSyntax toRepType); + + /** determine color model of the decompressed image + * @param fromType transfer syntax to decode from + * @param fromParam representation parameter of current compressed + * representation, may be NULL + * @param fromPixSeq compressed pixel sequence + * @param dataset pointer to dataset in which pixel data element is contained + * @param decompressedColorModel upon successful return, the color model + * of the decompressed image (which may be different from the one used + * in the compressed images) is returned in this parameter + * @return EC_Normal if successful, an error code otherwise + */ + static OFCondition determineDecompressedColorModel( + const DcmXfer &fromType, + const DcmRepresentationParameter *fromParam, + DcmPixelSequence *fromPixSeq, + DcmItem *dataset, + OFString &decompressedColorModel); + +private: + + /** constructor + * @param aCodec pointer to codec object. + * @param aDefaultRepParam default representation parameter. + * @param aCodecParameter codec parameter. + */ + DcmCodecList( + const DcmCodec *aCodec, + const DcmRepresentationParameter *aDefaultRepParam, + const DcmCodecParameter *aCodecParameter); + + /// private undefined copy constructor + DcmCodecList(const DcmCodecList &); + + /// private undefined copy assignment operator + DcmCodecList &operator=(const DcmCodecList &); + + /// pointer to codec object + const DcmCodec * codec; + + /// pointer to default representation parameter + const DcmRepresentationParameter * defaultRepParam; + + /// pointer to codec parameter set + const DcmCodecParameter * codecParameter; + + /// singleton list of registered codecs + static OFList registeredCodecs; + +#ifdef WITH_THREADS + /// read/write lock guarding access to singleton list + static OFReadWriteLock codecLock; +#endif + + // dummy friend declaration to prevent gcc from complaining + // that this class only defines private constructors and has no friends. + friend class DcmCodecListDummyFriend; +}; + + +#endif diff --git a/dcmdata/include/dcmtk/dcmdata/dcdatset.h b/dcmdata/include/dcmtk/dcmdata/dcdatset.h new file mode 100644 index 00000000..9df3abc4 --- /dev/null +++ b/dcmdata/include/dcmtk/dcmdata/dcdatset.h @@ -0,0 +1,345 @@ +/* + * + * Copyright (C) 1994-2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Gerd Ehlers, Andreas Barth + * + * Purpose: Interface of the class DcmDataset + * + */ + + +#ifndef DCDATSET_H +#define DCDATSET_H + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/dcmdata/dcitem.h" + + +// forward declarations +class DcmInputStream; +class DcmOutputStream; +class DcmRepresentationParameter; + + +/** a class handling the DICOM dataset format (files without meta header) + */ +class DCMTK_DCMDATA_EXPORT DcmDataset + : public DcmItem +{ + + public: + + /** default constructor + */ + DcmDataset(); + + /** copy constructor + * @param old dataset to be copied + */ + DcmDataset(const DcmDataset &old); + + /** destructor + */ + virtual ~DcmDataset(); + + /** assignment operator + * @param obj the dataset to be copied + */ + DcmDataset& operator=(const DcmDataset& obj); + + /** clone method + * @return deep copy of this object + */ + virtual DcmObject *clone() const + { + return new DcmDataset(*this); + } + + /** Virtual object copying. This method can be used for DcmObject + * and derived classes to get a deep copy of an object. Internally + * the assignment operator is called if the given DcmObject parameter + * is of the same type as "this" object instance. If not, an error + * is returned. This function permits copying an object by value + * in a virtual way which therefore is different to just calling the + * assignment operator of DcmElement which could result in slicing + * the object. + * @param rhs - [in] The instance to copy from. Has to be of the same + * class type as "this" object + * @return EC_Normal if copying was successful, error otherwise + */ + virtual OFCondition copyFrom(const DcmObject& rhs); + + /** get type identifier + * @return type identifier of this class (EVR_dataset) + */ + virtual DcmEVR ident() const; + + /** clear (remove) attribute value + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition clear(); + + /** remove all elements with an invalid group number, i.e. 0x0000 to 0x0003, + * 0x0005, 0x0007 and 0xFFFF in case of a data set. For sequence items, also + * group 0x0006 is disallowed. For command sets, only group 0x0000 is allowed, + * i.e. the elements from all other groups are removed. + * @param cmdSet specifies whether this object represents a command or data set + */ + virtual void removeInvalidGroups(const OFBool cmdSet = OFFalse); + + /** return the transfer syntax in which this dataset was originally read or created. + * See updateOriginalXfer() on how to update this value when created in memory. + * @return transfer syntax in which this dataset was originally read. Might be + * EXS_Unknown if the dataset was created in memory. + */ + E_TransferSyntax getOriginalXfer() const; + + /** return the current transfer syntax, i.e.\ the one that was last used with + * chooseRepresentation() in order to select a specific representation or with write() + * or writeSignatureFormat() in order to create a byte stream according to the DICOM + * encoding rules. The default value is the transfer syntax in which this dataset was + * originally read (see getOriginalXfer()) or, if this dataset was created from memory, + * the explicit VR with local endianness. + * Please note that the current transfer syntax might also change after calling + * updateOriginalXfer(). + * @return transfer syntax in which this dataset is currently stored (see above) + */ + E_TransferSyntax getCurrentXfer() const; + + /** update the original transfer syntax, e.g.\ in case the dataset was created in memory + * and pixel data was added with a particular representation. Icon images and other + * nested pixel data elements are not checked. If previously unknown, the original + * transfer syntax is set to the default EXS_LittleEndianExplicit. Please note that the + * current transfer syntax might also be updated if its value was not in sync with the + * internal representation of the pixel data. + */ + virtual void updateOriginalXfer(); + + /** print all elements of the dataset to a stream + * @param out output stream + * @param flags optional flag used to customize the output (see DCMTypes::PF_xxx) + * @param level current level of nested items. Used for indentation. + * @param pixelFileName optional filename used to write the raw pixel data file + * @param pixelCounter optional counter used for automatic pixel data filename creation + */ + virtual void print(STD_NAMESPACE ostream &out, + const size_t flags = 0, + const int level = 0, + const char *pixelFileName = NULL, + size_t *pixelCounter = NULL); + + /** calculate the length of this DICOM element when encoded with the + * given transfer syntax and the given encoding type for sequences. + * For elements, the length includes the length of the tag, length field, + * VR field and the value itself, for items and sequences it returns + * the length of the complete item or sequence including delimitation tags + * if applicable. Never returns undefined length. + * @param xfer transfer syntax for length calculation + * @param enctype sequence encoding type for length calculation + * @return length of DICOM element + */ + Uint32 calcElementLength(const E_TransferSyntax xfer, + const E_EncodingType enctype); + + /** check if this DICOM object can be encoded in the given transfer syntax. + * @param newXfer transfer syntax in which the DICOM object is to be encoded + * @param oldXfer transfer syntax in which the DICOM object was read or created + * (optional). If EXS_Unknown, the return value of getOriginalXfer() is used. + * @return true if object can be encoded in desired transfer syntax, false otherwise. + */ + virtual OFBool canWriteXfer(const E_TransferSyntax newXfer, + const E_TransferSyntax oldXfer = EXS_Unknown); + + /** This function reads the information of all attributes which + * are captured in the input stream and captures this information + * in this->elementList. Each attribute is represented as an + * element in this list. Having read all information for this + * particular data set or command, this function will also take + * care of group length (according to what is specified in glenc) + * and padding elements (don't change anything). + * @param inStream The stream which contains the information. + * @param xfer The transfer syntax which was used to encode + * the information in inStream. + * @param glenc Encoding type for group length; specifies what + * will be done with group length tags. + * @param maxReadLength Maximum read length for reading an attribute value. + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition read(DcmInputStream &inStream, + const E_TransferSyntax xfer = EXS_Unknown, + const E_GrpLenEncoding glenc = EGL_noChange, + const Uint32 maxReadLength = DCM_MaxReadLength); + + /** write dataset to a stream + * @param outStream DICOM output stream + * @param oxfer output transfer syntax (EXS_Unknown means use original) + * @param enctype encoding types (undefined or explicit length) + * @param wcache pointer to write cache object, may be NULL + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition write(DcmOutputStream &outStream, + const E_TransferSyntax oxfer, + const E_EncodingType enctype, + DcmWriteCache *wcache); + + /** This function writes data values which are contained in this + * DcmDataset object to the stream which is passed as first argument. + * With regard to the writing of information, the other parameters + * which are passed are accounted for. The function will return + * EC_Normal, if the information from all elements of this data + * set has been written to the buffer, it will return EC_StreamNotifyClient, + * if there is no more space in the buffer and _not_ all elements + * have been written to it, and it will return some other (error) + * value if there was an error. + * @param outStream The stream that the information will be written to. + * @param oxfer The transfer syntax which shall be used (EXS_Unknown + * means use original). + * @param enctype Encoding type for sequences; specifies how sequences + * will be handled. + * @param wcache pointer to write cache object, may be NULL + * @param glenc Encoding type for group length; specifies what will + * be done with group length tags. + * @param padenc Encoding type for padding. Specifies what will be done + * with padding tags. + * @param padlen The length up to which the dataset shall be padded, if + * padding is desired. + * @param subPadlen For sequences (ie sub elements), the length up to which + * item shall be padded, if padding is desired. + * @param instanceLength Number of extra bytes added to the item/dataset length + * used when computing the padding; this parameter is for + * instance used to pass the length of the file meta header + * from the DcmFileFormat to the DcmDataset object. + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition write(DcmOutputStream &outStream, + const E_TransferSyntax oxfer, + const E_EncodingType enctype, + DcmWriteCache *wcache, + const E_GrpLenEncoding glenc, + const E_PaddingEncoding padenc = EPD_noChange, + const Uint32 padlen = 0, + const Uint32 subPadlen = 0, + Uint32 instanceLength = 0); + + /** special write method for creation of digital signatures + * @param outStream DICOM output stream + * @param oxfer output transfer syntax (EXS_Unknown means use original) + * @param enctype encoding types (undefined or explicit length) + * @param wcache pointer to write cache object, may be NULL + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition writeSignatureFormat(DcmOutputStream &outStream, + const E_TransferSyntax oxfer, + const E_EncodingType enctype, + DcmWriteCache *wcache); + + /** write object in XML format. + * The XML declaration (e.g. ) is not written by this function. + * @param out output stream to which the XML document is written + * @param flags optional flag used to customize the output (see DCMTypes::XF_xxx) + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition writeXML(STD_NAMESPACE ostream &out, + const size_t flags = 0); + + /** load object from a DICOM file. + * This method only supports DICOM objects stored as a dataset, i.e. without meta header. + * Use DcmFileFormat::loadFile() to load files with meta header. + * @param fileName name of the file to load (may contain wide chars if support enabled). + * Since there are various constructors for the OFFilename class, a "char *", "OFString" + * or "wchar_t *" can also be passed directly to this parameter. + * @param readXfer transfer syntax used to read the data (auto detection if EXS_Unknown) + * @param groupLength flag, specifying how to handle the group length tags + * @param maxReadLength maximum number of bytes to be read for an element value. + * Element values with a larger size are not loaded until their value is retrieved + * (with getXXX()) or loadAllDataIntoMemory() is called. + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition loadFile(const OFFilename &fileName, + const E_TransferSyntax readXfer = EXS_Unknown, + const E_GrpLenEncoding groupLength = EGL_noChange, + const Uint32 maxReadLength = DCM_MaxReadLength); + + /** save object to a DICOM file. + * This method only supports DICOM objects stored as a dataset, i.e. without meta header. + * Use DcmFileFormat::saveFile() to save files with meta header. + * @param fileName name of the file to save (may contain wide chars if support enabled). + * Since there are various constructors for the OFFilename class, a "char *", "OFString" + * or "wchar_t *" can also be passed directly to this parameter. + * @param writeXfer transfer syntax used to write the data (EXS_Unknown means use original) + * @param encodingType flag, specifying the encoding with undefined or explicit length + * @param groupLength flag, specifying how to handle the group length tags + * @param padEncoding flag, specifying how to handle the padding tags + * @param padLength number of bytes used for the dataset padding (has to be an even number) + * @param subPadLength number of bytes used for the item padding (has to be an even number) + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition saveFile(const OFFilename &fileName, + const E_TransferSyntax writeXfer = EXS_Unknown, + const E_EncodingType encodingType = EET_UndefinedLength, + const E_GrpLenEncoding groupLength = EGL_recalcGL, + const E_PaddingEncoding padEncoding = EPD_noChange, + const Uint32 padLength = 0, + const Uint32 subPadLength = 0); + + // methods for different pixel representations + + /** select a specific representation (compressed or uncompressed) of the dataset + * and create the representation if needed. This may cause compression or decompression + * to be applied to the pixel data in the dataset. + * @param repType desired transfer syntax + * @param repParam desired representation parameter (e.g. quality factor for lossy compression) + * @return EC_Normal upon success, an error code otherwise. + */ + OFCondition chooseRepresentation(const E_TransferSyntax repType, + const DcmRepresentationParameter *repParam); + + /** check if all PixelData elements in this dataset have a representation conforming + * to the given transfer syntax and representation parameters (see dcpixel.h for + * definition of "conforming"). + * @param repType desired transfer syntax + * @param repParam desired representation parameter (e.g. quality factor for lossy compression) + * @return true if all pixel elements have the desired representation, false otherwise + */ + OFBool hasRepresentation(const E_TransferSyntax repType, + const DcmRepresentationParameter *repParam); + + /** removes all but the original representation in all pixel data elements + */ + void removeAllButOriginalRepresentations(); + + /** removes all but the current representation and sets the original + * representation to current + */ + void removeAllButCurrentRepresentations(); + + /** mode specifying whether the SpecificCharacterSet (0008,0005) element should be + * checked by convertCharacterSet() or not, i.e.\ whether this element might be + * present on this dataset-level. + * @return always returns OFTrue, i.e.\ SpecificCharacterSet should be checked + */ + virtual OFBool checkForSpecificCharacterSet() const { return OFTrue; } + + private: + + /// original transfer syntax of the dataset + E_TransferSyntax OriginalXfer; + /// current transfer syntax of the dataset + E_TransferSyntax CurrentXfer; +}; + + +#endif // DCDATSET_H diff --git a/dcmdata/include/dcmtk/dcmdata/dcdatutl.h b/dcmdata/include/dcmtk/dcmdata/dcdatutl.h new file mode 100644 index 00000000..b7751ad2 --- /dev/null +++ b/dcmdata/include/dcmtk/dcmdata/dcdatutl.h @@ -0,0 +1,85 @@ +/* + * + * Copyright (C) 2015, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmiod + * + * Author: Michael Onken + * + * Purpose: Static helper functionality for dcmdata module + * + */ + +#ifndef DCDATUTL_H +#define DCDATUTL_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/ofstd/ofstring.h" +#include "dcmtk/dcmdata/dcdefine.h" +#include "dcmtk/dcmdata/dcxfer.h" +#include "dcmtk/dcmdata/dcdatset.h" + +/** Class with helper functions used within the dcmiod module (and beyond) + */ +class DCMTK_DCMDATA_EXPORT DcmDataUtil +{ + +public: + + /** Get SOP Class UID, SOP Instance UID and Transfer Syntax UID from a DICOM + * file. The first two UID values are either copied from the meta-header + * (preferred) or from the dataset. The latter is either copied from the + * meta-header (preferred) or determined automatically (if possible). + * @param filename Name of the DICOM file from which the SOP Class UID + * and SOP Instance UID values are retrieved + * @param sopClassUID Variable to which the value of the SOP Class UID + * is stored + * @param sopInstanceUID Variable to which the value of the SOP Instance UID + * is stored + * @param transferSyntaxUID Variable to which the value of the Transfer + * Syntax UID is stored + * @param readMode Read mode passed to the DcmFileFormat::loadFile() method. + * If ERM_fileOnly, only the file meta information header is + * loaded, i.e. the behavior is identical to using + * ERM_metaOnly. + * @return EC_Normal if successful, an error code otherwise + */ + static OFCondition getSOPInstanceFromFile(const OFString &filename, + OFString &sopClassUID, + OFString &sopInstanceUID, + OFString &transferSyntaxUID, + const E_FileReadMode readMode = ERM_fileOnly); + + /** Get SOP Class UID, SOP Instance UID and Transfer Syntax UID from a + * DICOM dataset. The first two UID values are directly copied from the + * dataset. The latter is either taken from the parameter 'datasetXfer' or, + * if it is unknown, determined automatically from the dataset (if possible). + * @param dataset DICOM dataset from which the SOP Class UID and SOP + * Instance UID values are retrieved + * @param datasetXfer Transfer syntax of the dataset (if known, otherwise + * set to set to EXS_Unknown and then it is determined automatically) + * @param sopClassUID Variable in which the value of the SOP Class UID is + * stored + * @param sopInstanceUID Variable in which the value of the SOP Instance UID + * is stored + * @param transferSyntaxUID Variable in which the value of the Transfer + * Syntax UID is stored + * @return EC_Normal if successful, an error code otherwise + */ + static OFCondition getSOPInstanceFromDataset(DcmDataset *dataset, + const E_TransferSyntax datasetXfer, + OFString &sopClassUID, + OFString &sopInstanceUID, + OFString &transferSyntaxUID); +}; + +#endif // DCDATUTL_H diff --git a/dcmdata/include/dcmtk/dcmdata/dcddirif.h b/dcmdata/include/dcmtk/dcmdata/dcddirif.h new file mode 100644 index 00000000..95c43612 --- /dev/null +++ b/dcmdata/include/dcmtk/dcmdata/dcddirif.h @@ -0,0 +1,1587 @@ +/* + * + * Copyright (C) 2002-2015, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Joerg Riesmeier + * + * Purpose: Interface class for simplified creation of a DICOMDIR + * + */ + + +#ifndef DCDDIRIF_H +#define DCDDIRIF_H + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/dcmdata/dcdicdir.h" + + +/*------------------------------------* + * constant declarations and macros * + *------------------------------------*/ + +// default file-set ID +#define DEFAULT_FILESETID "DCMTK_MEDIA_DEMO" +// default specific character set of file-set descriptor file +#define DEFAULT_DESCRIPTOR_CHARSET "ISO_IR 100" + + +/*----------------------* + * class declarations * + *----------------------*/ + +/** Abstract interface to plugable image support for the DICOMDIR class. + * This is an abstract base class used as an interface to access DICOM + * images from the DicomDirInterface. The implementation can be found + * in dcmjpeg/libsrc/ddpiimpl.cc (incl. JPEG support). + */ +class DCMTK_DCMDATA_EXPORT DicomDirImagePlugin +{ + public: + + /** destructor (virtual) + */ + virtual ~DicomDirImagePlugin() {} + + /** scale image (pixel data) to specified size + * @param srcData pointer to 8 bit source pixel data (original image) + * @param srcWidth width of the source image + * @param srcHeight height of the source image + * @param dstData pointer to 8 bit destination pixel data (scaled image). + * This array needs to be allocated prior to calling this function. + * @param dstWidth width of the destination image + * @param dstHeight height of the destination image + * @return OFTrue if successful, OFFalse otherwise + */ + virtual OFBool scaleData(const Uint8 *srcData, + const unsigned int srcWidth, + const unsigned int srcHeight, + Uint8 *dstData, + const unsigned int dstWidth, + const unsigned int dstHeight) const = 0; + + /** scale image (from DICOM dataset) to specified size + * @param dataset DICOM dataset where the pixel data is stored (original image) + * @param pixel pointer to 8 bit destination pixel data (scaled image). + * This array needs to be allocated prior to calling this function. + * @param count number of bytes allocated for the 'pixel' array + * @param frame index of the frame to be scaled (0..n-1) + * @param width width of the destination image + * @param height height of the destination image + * @param decompressAll always decompress complete pixel data if true + * @return OFTrue if successful, OFFalse otherwise + */ + virtual OFBool scaleImage(DcmItem *dataset, + Uint8 *pixel, + const unsigned long count, + const unsigned long frame, + const unsigned int width, + const unsigned int height, + const OFBool decompressAll = OFFalse) const = 0; + + protected: + + /** constructor (protected) + */ + DicomDirImagePlugin() {} +}; + + +/** An interface class for simplified creation of a DICOMDIR. + * @note Please make sure that for all OFFilename parameters, passed to the various + * methods of this class, at least the 8-bit version of the string value is present + * since in some cases only this version is (can be) used. + */ +class DCMTK_DCMDATA_EXPORT DicomDirInterface +{ + + public: + + /** list of supported media storage application profiles + */ + enum E_ApplicationProfile + { + /// General Purpose Interchange on CD-R or DVD-RAM Media (STD-GEN-CD/DVD-RAM) + AP_GeneralPurpose, + /// default application profile: General Purpose Interchange on CD-R or DVD-RAM Media + AP_Default = AP_GeneralPurpose, + /// General Purpose DVD Interchange with JPEG (STD-GEN-DVD-JPEG) + AP_GeneralPurposeDVDJPEG, + /// General Purpose DVD Interchange with JPEG 2000 (STD-GEN-DVD-J2K) + AP_GeneralPurposeDVDJPEG2000, + /// General Purpose BD Interchange with JPEG (STD-GEN-BD-JPEG) + AP_GeneralPurposeBDJPEG, + /// General Purpose BD Interchange with JPEG 2000 (STD-GEN-BD-J2K) + AP_GeneralPurposeBDJPEG2000, + /// General Purpose BD Interchange with MPEG2 MP\@ML (STD-GEN-BD-MPEG2-MPML) + AP_GeneralPurposeBDMPEG2MPatML, + /// General Purpose BD Interchange with MPEG2 MP\@HL (STD-GEN-BD-MPEG2-MPHL) + AP_GeneralPurposeBDMPEG2MPatHL, + /// General Purpose BD Interchange with MPEG-4 AVC/H.264 HiP\@Level4.1 (STD-GEN-BD-MPEG4-HPLV41) + AP_GeneralPurposeBDMPEG4HPatLV41, + /// General Purpose BD Interchange with MPEG-4 AVC/H.264 BD-Compatible HiP\@Level4.1 (STD-GEN-BD-MPEG4-HPLV41BD) + AP_GeneralPurposeBDMPEG4HPatLV41BD, + /// General Purpose USB and Flash Memory Interchange with JPEG (STD-GEN-USB/MMC/CF/SD-JPEG) + AP_USBandFlashJPEG, + /// General Purpose USB and Flash Memory Interchange with JPEG 2000 (STD-GEN-USB/MMC/CF/SD-J2K) + AP_USBandFlashJPEG2000, + /// General Purpose MIME Interchange Profile (STD-GEN-MIME) + AP_GeneralPurposeMIME, + /// DVD Interchange with MPEG2 MP\@ML (STD-DVD-MPEG2-MPML) + AP_MPEG2MPatMLDVD, + /// Basic Cardiac X-Ray Angiographic Studies on CD-R Media (STD-XABC-CD) + AP_BasicCardiac, + /// 1024 X-Ray Angiographic Studies on CD-R Media (STD-XA1K-CD) + AP_XrayAngiographic, + /// 1024 X-Ray Angiographic Studies on DVD Media (STD-XA1K-DVD) + AP_XrayAngiographicDVD, + /// Dental Radiograph Interchange (STD-DEN-CD) + AP_DentalRadiograph, + /// CT/MR Studies (STD-CTMR-xxxx) + AP_CTandMR, + /// Ultrasound Single Frame for Image Display (STD-US-ID-SF-xxxx) + AP_UltrasoundIDSF, + /// Ultrasound Single Frame with Spatial Calibration (STD-US-SC-SF-xxxx) + AP_UltrasoundSCSF, + /// Ultrasound Single Frame with Combined Calibration (STD-US-CC-SF-xxxx) + AP_UltrasoundCCSF, + /// Ultrasound Single & Multi-Frame for Image Display (STD-US-ID-MF-xxxx) + AP_UltrasoundIDMF, + /// Ultrasound Single & Multi-Frame with Spatial Calibration (STD-UD-SC-MF-xxxx) + AP_UltrasoundSCMF, + /// Ultrasound Single & Multi-Frame with Combined Calibration (STD-UD-CC-MF-xxxx) + AP_UltrasoundCCMF, + /// 12-lead ECG Interchange on Diskette (STD-WVFM-ECG-FD) + AP_TwelveLeadECG, + /// Hemodynamic Waveform Interchange on Diskette (STD-WVFM-HD-FD) + AP_HemodynamicWaveform + }; + + /** constructor (default). + * No DICOMDIR object is created by default (see methods createNewDicomDir(), + * appendToDicomDir() and updateDicomDir()). + */ + DicomDirInterface(); + + /** destructor (virtual). + * Free all memory allocated by this class. + */ + virtual ~DicomDirInterface(); + + /** reset the object to its initial state. + * That means e.g. free memory. + */ + void cleanup(); + + /** check whether current DICOMDIR is valid. + * That means e.g. that it can be written to a file. + * @return OFTrue if DICOMDIR is valid, OFFalse otherwise + */ + OFBool isDicomDirValid() const; + + /** create a new DICOMDIR object. + * This function replaces any previously existing DICOMDIR file with the specified + * 'filename'. If the backup mode (see disableBackupMode()) is enabled, a backup + * copy ('filename' + ".BAK") is created from the existing file and automatically + * deleted after the new file has been written without any errors. + * @param profile media storage application profile to be used for the DICOMDIR + * @param filename name of the DICOMDIR file to be created (default: 'DICOMDIR'). + * The filename may include a fully qualified pathname. + * @param filesetID value of the attribute FileSetID (default: 'DCMTK_MEDIA_DEMO', + * might be empty) + * @return EC_Normal upon success, an error code otherwise + */ + OFCondition createNewDicomDir(const E_ApplicationProfile profile = AP_GeneralPurpose, + const OFFilename &filename = OFFilename(DEFAULT_DICOMDIR_NAME), + const OFString &filesetID = DEFAULT_FILESETID); + + /** create a DICOMDIR object based on an existing DICOMDIR file (append). + * This function can be used to append new entries to an existing DICOMDIR file. + * If the backup mode (see disableBackupMode()) is enabled, a backup copy ('filename' + * + ".BAK") is created from the existing file and automatically deleted after the + * new file has been written without any errors. + * @param profile media storage application profile to be used for the DICOMDIR. + * NB: The same profile should be used as for the creation of the DICOMDIR file. + * @param filename name of the DICOMDIR file to be appended. The filename may + * include a fully qualified pathname. + * @return EC_Normal upon success, an error code otherwise + */ + OFCondition appendToDicomDir(const E_ApplicationProfile profile, + const OFFilename &filename); + + /** create a DICOMDIR object based on an existing DICOMDIR file (update). + * This function can be used to append new entries to and update existing entries + * in an existing DICOMDIR file. + * If the backup mode (see disableBackupMode()) is enabled, a backup copy ('filename' + * + ".BAK") is created from the existing file and automatically deleted after the + * new file has been written without any errors. + * @param profile media storage application profile to be used for the DICOMDIR + * @param filename name of the DICOMDIR file to be updated. The filename may + * include a fully qualified pathname. + * @return EC_Normal upon success, an error code otherwise + */ + OFCondition updateDicomDir(const E_ApplicationProfile profile, + const OFFilename &filename); + + /** write the current DICOMDIR object to file. + * NB: The filename has already been specified for the object creation (see above). + * @param encodingType flag, specifying the encoding with undefined or explicit length + * @param groupLength flag, specifying how to handle the group length tags + * @return EC_Normal upon success, an error code otherwise + */ + OFCondition writeDicomDir(const E_EncodingType encodingType = EET_UndefinedLength, + const E_GrpLenEncoding groupLength = EGL_withoutGL); + + /** check whether specified filename is valid. i.e. conforms to the DICOM standard + * requirements (length, number of components and proper characters). This function + * is called automatically for the following methods: checkDicomFile(), addDicomFile() + * and setFilesetDescriptor(). So usually there's no need to call it manually + * (especially not in addition to the above mentioned methods). + * @param filename filename to be checked for standard conformance + * @param allowEmpty empty filename (zero length) allowed if OFTrue + * @return OFTrue if filename is valid, OFFalse otherwise + */ + OFBool isFilenameValid(const OFFilename &filename, + const OFBool allowEmpty = OFFalse); + + /** check whether given charset identifier is valid. + * Valid character sets are (see DICOM PS3.3 for details): ISO_IR 100, ISO_IR 101, + * ISO_IR 109, ISO_IR 110, ISO_IR 144, ISO_IR 127, ISO_IR 126, ISO_IR 138, ISO_IR 148, + * ISO_IR 166, ISO_IR 13, ISO_IR 192. + * @param charset character set identifier to be checked + * @return OFTrue if charset is valid, OFFalse otherwise + */ + OFBool isCharsetValid(const char *charset); + + /** check whether specified DICOM file is suitable to be included into the DICOMDIR. + * This method loads the given file and checks whether it conforms to the current + * application profile. Since this check is also performed by addDicomFile() there + * is usually no need to call this method directly. + * @param filename name of the DICOM file to be checked + * @param directory directory where the DICOM file is stored (optional). + * This parameter might be useful in cases where the DICOM file is not (yet) + * stored in the final directory (i.e. "relative" to the DICOMDIR location). + * @param checkFilename flag indicating whether to check the filename with + * isFilenameValid() or not. In case where the DICOM file is copied or + * renamed after this method is called, it might be useful to disable + * this check. + * @return EC_Normal upon success, an error code otherwise + */ + OFCondition checkDicomFile(const OFFilename &filename, + const OFFilename &directory = OFFilename(), + const OFBool checkFilename = OFTrue); + + /** add specified DICOM file to the current DICOMDIR. + * This method loads the given file, checks whether it conforms to the current + * application profile and finally adds it to the DICOMDIR (in case of conformance). + * @param filename name of the DICOM file to be added + * @param directory directory where the DICOM file is stored (optional). + * This parameter might be useful in cases where the DICOM file is not (yet) + * stored in the final directory (i.e. "relative" to the DICOMDIR location). + * @return EC_Normal upon success, an error code otherwise + */ + OFCondition addDicomFile(const OFFilename &filename, + const OFFilename &directory = OFFilename()); + + /** set the file-set descriptor file ID and character set. + * Prior to any internal modification both 'filename' and 'charset' are checked + * using the above checking routines. Existence of 'filename' is not checked. + * Requires a DICOMDIR object to exist (see createNewDicomDir(), appendToDicomDir() + * or updateDicomDir()). + * @param filename name of the file-set descriptor file to be set + * @param charset character set of the file-set descriptor file to be set. + * default: ISO Latin 1 ("ISO_IR 100"), use NULL or empty string to omit value. + * @return EC_Normal upon success, an error code otherwise + */ + OFCondition setFilesetDescriptor(const char *filename, + const char *charset = DEFAULT_DESCRIPTOR_CHARSET); + + /** set preferred size of the icon images. + * NB: some application profiles require a particular icon size. + * In those cases this manual setting is implicitly ignored. + * @param size size of the icon images in pixels (1..256, initial: 64) + * @return EC_Normal upon success, an error code otherwise + */ + OFCondition setIconSize(const unsigned int size); + + /** set filename prefix for alternative icon images. + * If non-empty the filename prefix is used to create the icon image from an + * externally stored PGM (portable gray map, 8 bit binary) file instead of the + * DICOM image file. The PGM filename is: 'prefix' + 'dicom_filename'. The + * image does not need to have the correct size as it is scaled automatically. + * @param prefix filename prefix (empty value to disable = default) + * @return always returns EC_Normal + */ + OFCondition setIconPrefix(const OFFilename &prefix); + + /** set filename of default icon image. + * For cases that the icon image cannot be created (neither from PGM nor from + * DICOM file, respectively) a default icon (8 bit binary PGM) can be specified. + * If this image also fails to load a black icon (filled with zeros) is used. + * @param filename name of the default PGM file + * @return always returns EC_Normal + */ + OFCondition setDefaultIcon(const OFFilename &filename); + + /** get current status of the "abort on first error" mode. + * See enableAbortMode() for more details. + * @return OFTrue if mode is enabled, OFFalse otherwise + */ + OFBool abortMode() const + { + return AbortMode; + } + + /** get current status of the "map filenames" mode. + * See enableMapFilenamesMode() for more details. + * @return OFTrue if mode is enabled, OFFalse otherwise + */ + OFBool mapFilenamesMode() const + { + return MapFilenamesMode; + } + + /** get current status of the "invent missing values" mode. + * See enableInventMode() for more details. + * @return OFTrue if mode is enabled, OFFalse otherwise + */ + OFBool inventMode() const + { + return InventMode; + } + + /** get current status of the "invent missing patient ID" mode. + * See enableInventPatientIDMode() for more details. + * @return OFTrue if mode is enabled, OFFalse otherwise + */ + OFBool inventPatientIDMode() const + { + return InventPatientIDMode; + } + + /** get current status of the "retired SOP class support" mode. + * See enableRetiredSOPClassSupport() for more details. + * @return OFTrue if support is enabled, OFFalse otherwise + */ + OFBool retiredSOPClassSupport() const + { + return RetiredSOPClassSupport; + } + + /** get current status of the "create icon images" mode. + * See enableIconImageMode() for more details. + * @return OFTrue if mode is enabled, OFFalse otherwise + */ + OFBool iconImageMode() const + { + return IconImageMode; + } + + /** get current status of the "create backup" mode. + * See disableBackupMode() for more details. + * @return OFTrue if mode is enabled, OFFalse otherwise + */ + OFBool backupMode() const + { + return BackupMode; + } + + /** get current status of the "pixel encoding check" mode. + * See disableEncodingCheck() for more details. + * @return OFTrue if check is enabled, OFFalse otherwise + */ + OFBool encodingCheck() const + { + return EncodingCheck; + } + + /** get current status of the "spatial resolution check" mode. + * See disableResolutionCheck() for more details. + * @return OFTrue if check is enabled, OFFalse otherwise + */ + OFBool resolutionCheck() const + { + return ResolutionCheck; + } + + /** get current status of the "transfer syntax check" mode. + * See disableTransferSyntaxCheck() for more details. + * @return OFTrue if check is enabled, OFFalse otherwise + */ + OFBool transferSyntaxCheck() const + { + return TransferSyntaxCheck; + } + + /** get current status of the "DICOM file format check" mode. + * See disableFileFormatCheck() for more details. + * @return OFTrue if check is enabled, OFFalse otherwise + */ + OFBool fileFormatCheck() const + { + return FileFormatCheck; + } + + /** get current status of the "consistency check" mode. + * See disableConsistencyCheck() for more details. + * @return OFTrue if check is enabled, OFFalse otherwise + */ + OFBool consistencyCheck() const + { + return ConsistencyCheck; + } + + /** enable/disable the "abort on first error" mode. + * If the mode is enabled, addDicomFile() reports an error message and + * returns with an error status code if something went wrong. + * Default: off, do not abort + * @param newMode enable mode if OFTrue, disable if OFFalse + * @return previously stored value + */ + OFBool enableAbortMode(const OFBool newMode = OFTrue); + + /** enable/disable the "map filenames" mode. + * If the mode is enabled, filenames are automatically mapped to DICOM format + * (convert lower case to upper case characters and remove trailing period). + * Default: off, do not map filenames + * @param newMode enable mode if OFTrue, disable if OFFalse + * @return previously stored value + */ + OFBool enableMapFilenamesMode(const OFBool newMode = OFTrue); + + /** enable/disable the "invent missing values" mode. + * If the mode is enabled, required DICOMDIR attributes (type 1) are + * invented when missing in the DICOM file. + * Default: off, do not invent attribute values + * @param newMode enable mode if OFTrue, disable if OFFalse + * @return previously stored value + */ + OFBool enableInventMode(const OFBool newMode = OFTrue); + + /** enable/disable the "invent new patient ID" mode. + * If the mode is enabled, a new PatientID is invented in case of + * inconsistent PatientName attributes, i.e. when different patients + * share the same ID. + * Default: off, do not invent new patient ID + * @param newMode enable mode if OFTrue, disable if OFFalse + * @return previously stored value + */ + OFBool enableInventPatientIDMode(const OFBool newMode = OFTrue); + + /** enable/disable the "retired SOP class support" mode. + * If the mode is enabled, retired SOP classes defined in previous editions + * of the DICOM standard are also accepted. + * Default: off, do not accept retired SOP classes + * @param newMode enable mode if OFTrue, disable if OFFalse + * @return previously stored value + */ + OFBool enableRetiredSOPClassSupport(const OFBool newMode = OFTrue); + + /** enable/disable the "create icon images" mode. + * If the mode is enabled, icon images are created for each IMAGE record. + * Please note that particular application profiles (e.g. Basic Cardiac) + * require an icon images to be present. Therefore, this mode does not + * affect the icon images creation of such profiles. + * Default: off, do not create (optional) icon images + * @param newMode enable mode if OFTrue, disable if OFFalse + * @return previously stored value + */ + OFBool enableIconImageMode(const OFBool newMode = OFTrue); + + /** disable/enable the "create backup file" mode. + * If this mode is disabled, no backup file of an existing DICOMDIR is created. + * However, when appending new files to an existing DICOMDIR a _temporary_ + * backup file ".$$$" is always created. + * Default: on, create a backup file ".BAK" + * @param newMode disable mode if OFFalse, enable if OFTrue + * @return previously stored value + */ + OFBool disableBackupMode(const OFBool newMode = OFFalse); + + /** disable/enable the "pixel encoding check". + * If this mode is disabled, the pixel encoding is not check for compliance + * with the selected application profile. + * Default: on, check pixel encoding (bits allocated/stored, high bit) + * @warning Please use this switch with care since the resulting DICOMDIR will + * probably violate the rules for the selected application profile. + * @param newMode disable check if OFFalse, enable if OFTrue + * @return previously stored value + */ + OFBool disableEncodingCheck(const OFBool newMode = OFFalse); + + /** disable/enable the "spatial resolution check". + * If this mode is disabled, the spatial resolution is not check for compliance + * with the selected application profile. + * Default: on, check spatial resolution + * @warning Please use this switch with care since the resulting DICOMDIR will + * probably violate the rules for the selected application profile. + * @param newMode disable check if OFFalse, enable if OFTrue + * @return previously stored value + */ + OFBool disableResolutionCheck(const OFBool newMode = OFFalse); + + /** disable/enable the "transfer syntax check". + * If this mode is disabled, the transfer syntax is not check for compliance + * with the selected application profile. + * Default: on, check transfer syntax + * @warning Please use this switch with care since the resulting DICOMDIR will + * probably violate the rules for the selected application profile. + * @param newMode disable check if OFFalse, enable if OFTrue + * @return previously stored value + */ + OFBool disableTransferSyntaxCheck(const OFBool newMode = OFFalse); + + /** disable/enable the "DICOM file format check". + * If this mode is disabled, it is not checked whether the file to be added + * contains file meta information (according to DICOM part 10). + * Default: on, check DICOM file format + * @warning Please use this switch with care since the resulting DICOMDIR will + * violate the rules of the DICOM standard if it references files that are + * missing the file meta information. + * @param newMode disable check if OFFalse, enable if OFTrue + * @return previously stored value + */ + OFBool disableFileFormatCheck(const OFBool newMode = OFFalse); + + /** disable/enable the "consistency check". + * If this mode is disabled, the consistency of newly added records with + * already existing ones is not checked (see warnAboutInconsistentAttributes() + * for details). + * Default: on, perform consistency check + * @param newMode disable check if OFFalse, enable if OFTrue + * @return previously stored value + */ + OFBool disableConsistencyCheck(const OFBool newMode = OFFalse); + + /** add pluggable image support. + * NB: This plugin is required to create icon images from DICOM files! + * @param plugin pointer to an instance of the plugin implementation. + * See class DicomDirImageImplementation (dcmjpeg/include/ddpiimpl.h). + * @return OFTrue if successful, OFFalse otherwise + */ + OFBool addImageSupport(DicomDirImagePlugin *plugin); + + /* -- static function -- */ + + /** get name/identifier associated with the given application profile + * @param profile media storage application profile + * @return name of the application profile (e.g. "STD-GEN-CD/DVD-RAM") + */ + static const char *getProfileName(const E_ApplicationProfile profile); + + /** get string associated with the given directory record entry type. + * @param recordType record type + * @return text string representing the record type + */ + static OFString recordTypeToName(const E_DirRecType recordType); + + protected: + + /** select given application profile + * @param profile storage media application profile to be selected + * @return EC_Normal upon success, an error code otherwise + */ + OFCondition selectApplicationProfile(const E_ApplicationProfile profile); + + /** load and check DICOM file regarding the current application profile + * @param filename name of the DICOM file to be checked + * @param directory directory where the DICOM file is stored (optional) + * @param fileformat object in which the loaded data is stored + * @param checkFilename flag indicating whether to check the filename with + * isFilenameValid() or not + * @return EC_Normal upon success, an error code otherwise + */ + OFCondition loadAndCheckDicomFile(const OFFilename &filename, + const OFFilename &directory, + DcmFileFormat &fileformat, + const OFBool checkFilename = OFTrue); + + /** check SOP class and transfer syntax for compliance with current profile + * @param metainfo object where the DICOM file meta information is stored + * @param dataset object where the DICOM dataset is stored + * @param filename name of the DICOM file to be checked + * @return EC_Normal upon success, an error code otherwise + */ + OFCondition checkSOPClassAndXfer(DcmMetaInfo *metainfo, + DcmItem *dataset, + const OFFilename &filename); + + /** check attributes for compliance with Basic Cardiac application profile + * @param dataset object where the DICOM dataset is stored + * @param filename name of the DICOM file to be checked + * @return EC_Normal upon success, an error code otherwise + */ + OFCondition checkBasicCardiacAttributes(DcmItem *dataset, + const OFFilename &filename); + + /** check attributes for compliance with X-ray Angiography application profile + * @param dataset object where the DICOM dataset is stored + * @param sopClass SOP class of the DICOM data to be checked + * @param filename name of the DICOM file to be checked + * @return EC_Normal upon success, an error code otherwise + */ + OFCondition checkXrayAngiographicAttributes(DcmItem *dataset, + const OFString &sopClass, + const OFFilename &filename); + + /** check attributes for compliance with dental radiograph application profile + * @param dataset object where the DICOM dataset is stored + * @param filename name of the DICOM file to be checked + * @return EC_Normal upon success, an error code otherwise + */ + OFCondition checkDentalRadiographAttributes(DcmItem *dataset, + const OFFilename &filename); + + /** check attributes for compliance with CT and MR application profile + * @param dataset object where the DICOM dataset is stored + * @param sopClass SOP class of the DICOM data to be checked + * @param filename name of the DICOM file to be checked + * @return EC_Normal upon success, an error code otherwise + */ + OFCondition checkCTandMRAttributes(DcmItem *dataset, + const OFString &sopClass, + const OFFilename &filename); + + /** check attributes for compliance with Ultrasound application profiles + * @param dataset object where the DICOM dataset is stored + * @param transferSyntax transfer syntax of the DICOM data to be checked + * @param filename name of the DICOM file to be checked + * @return EC_Normal upon success, an error code otherwise + */ + OFCondition checkUltrasoundAttributes(DcmItem *dataset, + const OFString &transferSyntax, + const OFFilename &filename); + + /** check attributes for compliance with current application profile + * @param metainfo object where the DICOM file meta information is stored + * @param dataset object where the DICOM dataset is stored + * @param filename name of the DICOM file to be checked + * @return EC_Normal upon success, an error code otherwise + */ + OFCondition checkMandatoryAttributes(DcmMetaInfo *metainfo, + DcmItem *dataset, + const OFFilename &filename); + + /** check whether given directory record matches dataset. + * The check depends on the record type and is performed mainly based on + * the unique key defined for the particular record type (e.g. SOPInstanceUID + * for IMAGE records). For PATIENT records the PatientName may also be used + * if the PatientID is absent. + * @param record directory record to be checked + * @param dataset DICOM dataset of the current file + * @return OFTrue if record matches, OFFalse otherwise + */ + OFBool recordMatchesDataset(DcmDirectoryRecord *record, + DcmItem *dataset); + + /** search for a given directory record + * @param parent higher-level structure where the records are stored + * @param recordType type of directory record to be searched for + * @param dataset DICOM dataset of the current file + * @return pointer to record if found, NULL otherwise + */ + DcmDirectoryRecord *findExistingRecord(DcmDirectoryRecord *parent, + const E_DirRecType recordType, + DcmItem* dataset); + + /** create or update patient record and copy required values from dataset + * @param record record to be updated, use NULL to create a new one + * @param fileformat DICOM dataset of the current file + * @param sourceFilename name of the source DICOM file + * @return pointer to new or updated record, NULL if an error occurred + */ + DcmDirectoryRecord *buildPatientRecord(DcmDirectoryRecord *record, + DcmFileFormat *fileformat, + const OFFilename &sourceFilename); + + /** create or update study record and copy required values from dataset + * @param record record to be updated, use NULL to create a new one + * @param fileformat DICOM dataset of the current file + * @param sourceFilename name of the source DICOM file + * @return pointer to new or updated record, NULL if an error occurred + */ + DcmDirectoryRecord *buildStudyRecord(DcmDirectoryRecord *record, + DcmFileFormat *fileformat, + const OFFilename &sourceFilename); + + /** create or update new series record and copy required values from dataset + * @param record record to be updated, use NULL to create a new one + * @param fileformat DICOM dataset of the current file + * @param sourceFilename name of the source DICOM file + * @return pointer to new or updated record, NULL if an error occurred + */ + DcmDirectoryRecord *buildSeriesRecord(DcmDirectoryRecord *record, + DcmFileFormat *fileformat, + const OFFilename &sourceFilename); + + /** create or update overlay record and copy required values from dataset + * @param record record to be updated, use NULL to create a new one + * @param fileformat DICOM dataset of the current file + * @param referencedFileID value of the Referenced File ID attribute + * @param sourceFilename name of the source DICOM file + * @return pointer to new or updated record, NULL if an error occurred + */ + DcmDirectoryRecord *buildOverlayRecord(DcmDirectoryRecord *record, + DcmFileFormat *fileformat, + const OFString &referencedFileID, + const OFFilename &sourceFilename); + + /** create or update modality LUT record and copy required values from dataset + * @param record record to be updated, use NULL to create a new one + * @param fileformat DICOM dataset of the current file + * @param referencedFileID value of the Referenced File ID attribute + * @param sourceFilename name of the source DICOM file + * @return pointer to new or updated record, NULL if an error occurred + */ + DcmDirectoryRecord *buildModalityLutRecord(DcmDirectoryRecord *record, + DcmFileFormat *fileformat, + const OFString &referencedFileID, + const OFFilename &sourceFilename); + + /** create or update VOI LUT record and copy required values from dataset + * @param record record to be updated, use NULL to create a new one + * @param fileformat DICOM dataset of the current file + * @param referencedFileID value of the Referenced File ID attribute + * @param sourceFilename name of the source DICOM file + * @return pointer to new or updated record, NULL if an error occurred + */ + DcmDirectoryRecord *buildVoiLutRecord(DcmDirectoryRecord *record, + DcmFileFormat *fileformat, + const OFString &referencedFileID, + const OFFilename &sourceFilename); + + /** create or update curve record and copy required values from dataset + * @param record record to be updated, use NULL to create a new one + * @param fileformat DICOM dataset of the current file + * @param referencedFileID value of the Referenced File ID attribute + * @param sourceFilename name of the source DICOM file + * @return pointer to new or updated record, NULL if an error occurred + */ + DcmDirectoryRecord *buildCurveRecord(DcmDirectoryRecord *record, + DcmFileFormat *fileformat, + const OFString &referencedFileID, + const OFFilename &sourceFilename); + + /** create or update structure reporting record and copy required values from dataset + * @param record record to be updated, use NULL to create a new one + * @param fileformat DICOM dataset of the current file + * @param referencedFileID value of the Referenced File ID attribute + * @param sourceFilename name of the source DICOM file + * @return pointer to new or updated record, NULL if an error occurred + */ + DcmDirectoryRecord *buildStructReportRecord(DcmDirectoryRecord *record, + DcmFileFormat *fileformat, + const OFString &referencedFileID, + const OFFilename &sourceFilename); + + /** create or update presentation state record and copy required values from dataset + * @param record record to be updated, use NULL to create a new one + * @param fileformat DICOM dataset of the current file + * @param referencedFileID value of the Referenced File ID attribute + * @param sourceFilename name of the source DICOM file + * @return pointer to new or updated record, NULL if an error occurred + */ + DcmDirectoryRecord *buildPresentationRecord(DcmDirectoryRecord *record, + DcmFileFormat *fileformat, + const OFString &referencedFileID, + const OFFilename &sourceFilename); + + /** create or update waveform record and copy required values from dataset + * @param record record to be updated, use NULL to create a new one + * @param fileformat DICOM dataset of the current file + * @param referencedFileID value of the Referenced File ID attribute + * @param sourceFilename name of the source DICOM file + * @return pointer to new or updated record, NULL if an error occurred + */ + DcmDirectoryRecord *buildWaveformRecord(DcmDirectoryRecord *record, + DcmFileFormat *fileformat, + const OFString &referencedFileID, + const OFFilename &sourceFilename); + + /** create or update RT dose record and copy required values from dataset + * @param record record to be updated, use NULL to create a new one + * @param fileformat DICOM dataset of the current file + * @param referencedFileID value of the Referenced File ID attribute + * @param sourceFilename name of the source DICOM file + * @return pointer to new or updated record, NULL if an error occurred + */ + DcmDirectoryRecord *buildRTDoseRecord(DcmDirectoryRecord *record, + DcmFileFormat *fileformat, + const OFString &referencedFileID, + const OFFilename &sourceFilename); + + /** create or update RT structure set record and copy required values from dataset + * @param record record to be updated, use NULL to create a new one + * @param fileformat DICOM dataset of the current file + * @param referencedFileID value of the Referenced File ID attribute + * @param sourceFilename name of the source DICOM file + * @return pointer to new or updated record, NULL if an error occurred + */ + DcmDirectoryRecord *buildRTStructureSetRecord(DcmDirectoryRecord *record, + DcmFileFormat *fileformat, + const OFString &referencedFileID, + const OFFilename &sourceFilename); + + /** create or update RT plan record and copy required values from dataset + * @param record record to be updated, use NULL to create a new one + * @param fileformat DICOM dataset of the current file + * @param referencedFileID value of the Referenced File ID attribute + * @param sourceFilename name of the source DICOM file + * @return pointer to new or updated record, NULL if an error occurred + */ + DcmDirectoryRecord *buildRTPlanRecord(DcmDirectoryRecord *record, + DcmFileFormat *fileformat, + const OFString &referencedFileID, + const OFFilename &sourceFilename); + + /** create or update RT treatment record and copy required values from dataset + * @param record record to be updated, use NULL to create a new one + * @param fileformat DICOM dataset of the current file + * @param referencedFileID value of the Referenced File ID attribute + * @param sourceFilename name of the source DICOM file + * @return pointer to new or updated record, NULL if an error occurred + */ + DcmDirectoryRecord *buildRTTreatmentRecord(DcmDirectoryRecord *record, + DcmFileFormat *fileformat, + const OFString &referencedFileID, + const OFFilename &sourceFilename); + + /** create or update stored print record and copy required values from dataset + * @param record record to be updated, use NULL to create a new one + * @param fileformat DICOM dataset of the current file + * @param referencedFileID value of the Referenced File ID attribute + * @param sourceFilename name of the source DICOM file + * @return pointer to new or updated record, NULL if an error occurred + */ + DcmDirectoryRecord *buildStoredPrintRecord(DcmDirectoryRecord *record, + DcmFileFormat *fileformat, + const OFString &referencedFileID, + const OFFilename &sourceFilename); + + /** create or update key object doc record and copy required values from dataset + * @param record record to be updated, use NULL to create a new one + * @param fileformat DICOM dataset of the current file + * @param referencedFileID value of the Referenced File ID attribute + * @param sourceFilename name of the source DICOM file + * @return pointer to new or updated record, NULL if an error occurred + */ + DcmDirectoryRecord *buildKeyObjectDocRecord(DcmDirectoryRecord *record, + DcmFileFormat *fileformat, + const OFString &referencedFileID, + const OFFilename &sourceFilename); + + /** create or update registration record and copy required values from dataset + * @param record record to be updated, use NULL to create a new one + * @param fileformat DICOM dataset of the current file + * @param referencedFileID value of the Referenced File ID attribute + * @param sourceFilename name of the source DICOM file + * @return pointer to new or updated record, NULL if an error occurred + */ + DcmDirectoryRecord *buildRegistrationRecord(DcmDirectoryRecord *record, + DcmFileFormat *fileformat, + const OFString &referencedFileID, + const OFFilename &sourceFilename); + + /** create or update fiducial record and copy required values from dataset + * @param record record to be updated, use NULL to create a new one + * @param fileformat DICOM dataset of the current file + * @param referencedFileID value of the Referenced File ID attribute + * @param sourceFilename name of the source DICOM file + * @return pointer to new or updated record, NULL if an error occurred + */ + DcmDirectoryRecord *buildFiducialRecord(DcmDirectoryRecord *record, + DcmFileFormat *fileformat, + const OFString &referencedFileID, + const OFFilename &sourceFilename); + + /** create or update raw data record and copy required values from dataset + * @param record record to be updated, use NULL to create a new one + * @param fileformat DICOM dataset of the current file + * @param referencedFileID value of the Referenced File ID attribute + * @param sourceFilename name of the source DICOM file + * @return pointer to new or updated record, NULL if an error occurred + */ + DcmDirectoryRecord *buildRawDataRecord(DcmDirectoryRecord *record, + DcmFileFormat *fileformat, + const OFString &referencedFileID, + const OFFilename &sourceFilename); + + /** create or update spectroscopy record and copy required values from dataset + * @param record record to be updated, use NULL to create a new one + * @param fileformat DICOM dataset of the current file + * @param referencedFileID value of the Referenced File ID attribute + * @param sourceFilename name of the source DICOM file + * @return pointer to new or updated record, NULL if an error occurred + */ + DcmDirectoryRecord *buildSpectroscopyRecord(DcmDirectoryRecord *record, + DcmFileFormat *fileformat, + const OFString &referencedFileID, + const OFFilename &sourceFilename); + + /** create or update encap doc record and copy required values from dataset + * @param record record to be updated, use NULL to create a new one + * @param fileformat DICOM dataset of the current file + * @param referencedFileID value of the Referenced File ID attribute + * @param sourceFilename name of the source DICOM file + * @return pointer to new or updated record, NULL if an error occurred + */ + DcmDirectoryRecord *buildEncapDocRecord(DcmDirectoryRecord *record, + DcmFileFormat *fileformat, + const OFString &referencedFileID, + const OFFilename &sourceFilename); + + /** create or update value map record and copy required values from dataset + * @param record record to be updated, use NULL to create a new one + * @param fileformat DICOM dataset of the current file + * @param referencedFileID value of the Referenced File ID attribute + * @param sourceFilename name of the source DICOM file + * @return pointer to new or updated record, NULL if an error occurred + */ + DcmDirectoryRecord *buildValueMapRecord(DcmDirectoryRecord *record, + DcmFileFormat *fileformat, + const OFString &referencedFileID, + const OFFilename &sourceFilename); + + /** create or update hanging protocol record and copy required values from dataset + * @param record record to be updated, use NULL to create a new one + * @param fileformat DICOM dataset of the current file + * @param referencedFileID value of the Referenced File ID attribute + * @param sourceFilename name of the source DICOM file + * @return pointer to new or updated record, NULL if an error occurred + */ + DcmDirectoryRecord *buildHangingProtocolRecord(DcmDirectoryRecord *record, + DcmFileFormat *fileformat, + const OFString &referencedFileID, + const OFFilename &sourceFilename); + + /** create or update stereometric record and copy required values from dataset + * @param record record to be updated, use NULL to create a new one + * @param fileformat DICOM dataset of the current file + * @param referencedFileID value of the Referenced File ID attribute + * @param sourceFilename name of the source DICOM file + * @return pointer to new or updated record, NULL if an error occurred + */ + DcmDirectoryRecord *buildStereometricRecord(DcmDirectoryRecord *record, + DcmFileFormat *fileformat, + const OFString &referencedFileID, + const OFFilename &sourceFilename); + + /** create or update palette record and copy required values from dataset + * @param record record to be updated, use NULL to create a new one + * @param fileformat DICOM dataset of the current file + * @param referencedFileID value of the Referenced File ID attribute + * @param sourceFilename name of the source DICOM file + * @return pointer to new or updated record, NULL if an error occurred + */ + DcmDirectoryRecord *buildPaletteRecord(DcmDirectoryRecord *record, + DcmFileFormat *fileformat, + const OFString &referencedFileID, + const OFFilename &sourceFilename); + + /** create or update surface record and copy required values from dataset + * @param record record to be updated, use NULL to create a new one + * @param fileformat DICOM dataset of the current file + * @param referencedFileID value of the Referenced File ID attribute + * @param sourceFilename name of the source DICOM file + * @return pointer to new or updated record, NULL if an error occurred + */ + DcmDirectoryRecord *buildSurfaceRecord(DcmDirectoryRecord *record, + DcmFileFormat *fileformat, + const OFString &referencedFileID, + const OFFilename &sourceFilename); + + /** create or update measurement record and copy required values from dataset + * @param record record to be updated, use NULL to create a new one + * @param fileformat DICOM dataset of the current file + * @param referencedFileID value of the Referenced File ID attribute + * @param sourceFilename name of the source DICOM file + * @return pointer to new or updated record, NULL if an error occurred + */ + DcmDirectoryRecord *buildMeasurementRecord(DcmDirectoryRecord *record, + DcmFileFormat *fileformat, + const OFString &referencedFileID, + const OFFilename &sourceFilename); + + /** create or update implant record and copy required values from dataset + * @param record record to be updated, use NULL to create a new one + * @param fileformat DICOM dataset of the current file + * @param referencedFileID value of the Referenced File ID attribute + * @param sourceFilename name of the source DICOM file + * @return pointer to new or updated record, NULL if an error occurred + */ + DcmDirectoryRecord *buildImplantRecord(DcmDirectoryRecord *record, + DcmFileFormat *fileformat, + const OFString &referencedFileID, + const OFFilename &sourceFilename); + + /** create or update implant group record and copy required values from dataset + * @param record record to be updated, use NULL to create a new one + * @param fileformat DICOM dataset of the current file + * @param referencedFileID value of the Referenced File ID attribute + * @param sourceFilename name of the source DICOM file + * @return pointer to new or updated record, NULL if an error occurred + */ + DcmDirectoryRecord *buildImplantGroupRecord(DcmDirectoryRecord *record, + DcmFileFormat *fileformat, + const OFString &referencedFileID, + const OFFilename &sourceFilename); + + /** create or update implant assy record and copy required values from dataset + * @param record record to be updated, use NULL to create a new one + * @param fileformat DICOM dataset of the current file + * @param referencedFileID value of the Referenced File ID attribute + * @param sourceFilename name of the source DICOM file + * @return pointer to new or updated record, NULL if an error occurred + */ + DcmDirectoryRecord *buildImplantAssyRecord(DcmDirectoryRecord *record, + DcmFileFormat *fileformat, + const OFString &referencedFileID, + const OFFilename &sourceFilename); + + /** create or update plan record and copy required values from dataset + * @param record record to be updated, use NULL to create a new one + * @param fileformat DICOM dataset of the current file + * @param referencedFileID value of the Referenced File ID attribute + * @param sourceFilename name of the source DICOM file + * @return pointer to new or updated record, NULL if an error occurred + */ + DcmDirectoryRecord *buildPlanRecord(DcmDirectoryRecord *record, + DcmFileFormat *fileformat, + const OFString &referencedFileID, + const OFFilename &sourceFilename); + + /** create or update surface scan record and copy required values from dataset + * @param record record to be updated, use NULL to create a new one + * @param fileformat DICOM dataset of the current file + * @param referencedFileID value of the Referenced File ID attribute + * @param sourceFilename name of the source DICOM file + * @return pointer to new or updated record, NULL if an error occurred + */ + DcmDirectoryRecord *buildSurfaceScanRecord(DcmDirectoryRecord *record, + DcmFileFormat *fileformat, + const OFString &referencedFileID, + const OFFilename &sourceFilename); + + /** create or update image record and copy required values from dataset + * @param record record to be updated, use NULL to create a new one + * @param fileformat DICOM dataset of the current file + * @param referencedFileID value of the Referenced File ID attribute + * @param sourceFilename name of the source DICOM file + * @return pointer to new or updated record, NULL if an error occurred + */ + DcmDirectoryRecord *buildImageRecord(DcmDirectoryRecord *record, + DcmFileFormat *fileformat, + const OFString &referencedFileID, + const OFFilename &sourceFilename); + + /** create icon image from given PGM (portable gray map) file. + * Please note that only grayscale images in binary format are currently + * supported (magic word "P5"). Memory has to be allocated by the caller. + * @param filename name of the PGM file to be loaded + * @param pixel pointer to memory buffer where the pixel data are to be stored + * @param count number of bytes allocated for the 'pixel' memory buffer + * @param width width of the scaled icon image (in pixels ) + * @param height height of the scaled icon image (in pixels) + * @return OFTrue if successful, OFFalse otherwise + */ + OFBool getIconFromFile(const OFFilename &filename, + Uint8 *pixel, + const unsigned long count, + const unsigned int width, + const unsigned int height); + + /** create icon image from DICOM dataset. + * Please note that the memory buffer has to be allocated by the caller. + * @param dataset DICOM dataset from which the icon image is created + * @param pixel pointer to memory buffer where the pixel data are to be stored + * @param count number of bytes allocated for the 'pixel' memory buffer + * @param width width of the scaled icon image (in pixels ) + * @param height height of the scaled icon image (in pixels) + * @return OFTrue if successful, OFFalse otherwise + */ + OFBool getIconFromDataset(DcmItem *dataset, + Uint8 *pixel, + const unsigned long count, + const unsigned int width, + const unsigned int height); + + /** add icon image sequence to directory record. + * If the icon image cannot be created from the DICOM dataset and there is no + * PGM file specified (neither for the particular image not a default one) a + * black image is used instead. + * @param record directory record where the icon image is stored + * @param dataset DICOM dataset from which the icon image is possibly created + * @param size resolution of the icon image to be created (width and height) + * @param sourceFilename name of the source DICOM file + * @return EC_Normal upon success, an error code otherwise + */ + OFCondition addIconImage(DcmDirectoryRecord *record, + DcmItem *dataset, + const unsigned int size, + const OFFilename &sourceFilename); + + /** add child record to a given parent record. + * A new record is only added if it does not already exist. + * @param parent parent record (add new record as a child of this one) + * @param recordType type of directory record to be created + * @param fileformat DICOM dataset containing data of the new record + * @param referencedFileID value of the Referenced File ID attribute + * @param sourceFilename name of the source DICOM file + * @return pointer to new/existing record, NULL if an error occurred + */ + DcmDirectoryRecord *addRecord(DcmDirectoryRecord *parent, + const E_DirRecType recordType, + DcmFileFormat *fileformat, + const OFString &referencedFileID, + const OFFilename &sourceFilename); + + /** check referenced SOP instance for consistency with a new directory record + * @param record directory record to be checked + * @param dataset DICOM dataset containing data of the new record + * @param referencedFileID value of the Referenced File ID attribute + * @param sourceFilename name of the source DICOM file + */ + OFBool checkReferencedSOPInstance(DcmDirectoryRecord *record, + DcmItem *dataset, + const OFString &referencedFileID, + const OFFilename &sourceFilename); + + /** invent missing type 1 attributes for all child records (from patient level) + * @param parent invent missing attributes for all children of this record (root) + * @param recurse invent missing attributes also for lower level records if OFTrue. + * Only invent attributes for the top (patient) level if OFFalse. + */ + void inventMissingAttributes(DcmDirectoryRecord *parent, + const OFBool recurse = OFTrue); + + /** invent missing type 1 attributes for all child records (from study level) + * @param parent invent missing attributes for all children of this record + */ + void inventMissingStudyLevelAttributes(DcmDirectoryRecord *parent); + + /** invent missing type 1 attributes for all child records (from series level) + * @param parent invent missing attributes for all children of this record + */ + void inventMissingSeriesLevelAttributes(DcmDirectoryRecord *parent); + + /** invent missing type 1 attributes for all child records (from instance level) + * @param parent invent missing attributes for all children of this record + */ + void inventMissingInstanceLevelAttributes(DcmDirectoryRecord *parent); + + /** create backup of a given file + * @param filename name of the file to be backuped + */ + void createDicomDirBackup(const OFFilename &filename); + + /** delete backup file if one has been created + */ + void deleteDicomDirBackup(); + + /** print a message that the value of a given tag is unexpected. + * The output format is: "{Error|Warning}: attribute + * has other value than expected[ in file: ]" + * @param key affected tag + * @param filename name of the file (optional, might be empty) + * @param errorMsg print error message if OFTrue, a warning message otherwise + */ + void printUnexpectedValueMessage(const DcmTagKey &key, + const OFFilename &filename = OFFilename(), + const OFBool errorMsg = OFTrue); + + /** print an error message that a required attribute is missing/empty. + * The output format is: "Error: : required attribute + * {empty|missing}[ in file: ]" + * @param key affected tag + * @param filename name of the file (optional, might be empty) + * @param emptyMsg print "empty" if OFTrue, "missing" otherwise + */ + void printRequiredAttributeMessage(const DcmTagKey &key, + const OFFilename &filename = OFFilename(), + const OFBool emptyMsg = OFFalse); + + /** print an error message that something went wrong with an attribute. + * The output format is: "Error: : [cannot ] + * " + * @param key affected tag + * @param error status to be reported (only if ".bad()") + * @param operation name of the operation that failed (optional, might be NULL) + */ + void printAttributeErrorMessage(const DcmTagKey &key, + const OFCondition &error, + const char *operation); + + /** print an error message that something went wrong with a given record. + * The output format is: "Error: : [cannot ] + * directory record" + * @param error status to be reported (only if ".bad()") + * @param recordType type of directory record which caused the error + * @param operation name of the operation that failed (optional, might be NULL) + */ + void printRecordErrorMessage(const OFCondition &error, + const E_DirRecType recordType, + const char *operation); + + /** copy contents of specified file + * @param fromFilename name of the file to be copied + * @param toFilename name of the new file (copy of 'fromFilename') + * @return OFTrue if successful, OFFalse otherwise + */ + OFBool copyFile(const OFFilename &fromFilename, + const OFFilename &toFilename); + + /** check if all the attributes in record match the values in dataset and warn if not + * @param record directory record to be checked + * @param dataset DICOM dataset to be compared with the directory record + * @param sourceFilename name of the source DICOM file + * @param abortCheck flag indicating whether to abort on the first inconsistent record + * @return OFTrue in case of any inconsistency, OFFalse otherwise + */ + OFBool warnAboutInconsistentAttributes(DcmDirectoryRecord *record, + DcmItem *dataset, + const OFFilename &sourceFilename, + const OFBool abortCheck = OFFalse); + + /** check whether given file-set ID is valid + * @param filesetID file-set ID to be checked + * @return OFTrue if ID is valid, OFFalse otherwise + */ + OFBool checkFilesetID(const OFString &filesetID); + + /** check whether given tag exists in the DICOM dataset + * @param dataset DICOM dataset to be checked + * @param key tag to be searched for + * @param filename of the file (optional, report any error if non-empty) + * @return OFTrue if tag exists, OFFalse otherwise + */ + OFBool checkExists(DcmItem *dataset, + const DcmTagKey &key, + const OFFilename &filename = OFFilename()); + + /** check whether given tag exists with a value in the DICOM dataset + * @param dataset DICOM dataset to be checked + * @param key tag to be searched for + * @param filename of the file (optional, report any error if non-empty) + * @return OFTrue if tag exists with value, OFFalse otherwise + */ + OFBool checkExistsWithValue(DcmItem *dataset, + const DcmTagKey &key, + const OFFilename &filename = OFFilename()); + + /** check whether given tag exists in the DICOM dataset and has the expected string value + * @param dataset DICOM dataset to be checked + * @param key tag to be searched for + * @param value expected string value + * @param filename of the file (optional, report any error if non-empty) + * @return OFTrue if tag exists with given string value, OFFalse otherwise + */ + OFBool checkExistsWithStringValue(DcmItem *dataset, + const DcmTagKey &key, + const OFString &value, + const OFFilename &filename = OFFilename()); + + /** check whether given tag exists in the DICOM dataset and has the expected integer value + * @param dataset DICOM dataset to be checked + * @param key tag to be searched for + * @param value expected integer value + * @param filename of the file (optional, report any error if non-empty) + * @param reject report an "Error" if OFTrue, a "Warning" if OFFalse + * @return OFTrue if tag exists with given string value, OFFalse otherwise + */ + OFBool checkExistsWithIntegerValue(DcmItem *dataset, + const DcmTagKey &key, + const long value, + const OFFilename &filename = OFFilename(), + const OFBool reject = OFTrue); + + /** check whether given tag exists in the DICOM dataset and has an integer value in the + * expected range + * @param dataset DICOM dataset to be checked + * @param key tag to be searched for + * @param min minimum integer value of the expected range + * @param max maximum integer value of the expected range + * @param filename of the file (optional, report any error if non-empty) + * @param reject report an "Error" if OFTrue, a "Warning" if OFFalse + * @return OFTrue if tag exists with given string value, OFFalse otherwise + */ + OFBool checkExistsWithMinMaxValue(DcmItem *dataset, + const DcmTagKey &key, + const long min, + const long max, + const OFFilename &filename = OFFilename(), + const OFBool reject = OFTrue); + + /** get string value from dataset and report an error (if any) + * @param dataset dataset from which the string value is to be retrieved + * @param key tag of the attribute to be retrieved + * @param result string variable in which the resulting value is stored + * @param searchIntoSub flag indicating whether to do a deep search or not + * @return reference to the resulting string value (parameter 'result') + */ + OFString &getStringFromDataset(DcmItem *dataset, + const DcmTagKey &key, + OFString &result, + OFBool searchIntoSub = OFFalse); + + /** get string value component from dataset and report an error (if any) + * @param dataset dataset from which the string value is to be retrieved + * @param key tag of the attribute to be retrieved + * @param result string variable in which the resulting value is stored + * @param pos index of the component in case of multi-valued elements (0..vm-1) + * @param searchIntoSub flag indicating whether to do a deep search or not + * @return reference to the resulting string value (parameter 'result') + */ + OFString &getStringComponentFromDataset(DcmItem *dataset, + const DcmTagKey &key, + OFString &result, + const unsigned long pos, + OFBool searchIntoSub = OFFalse); + + /** get string value from file and report an error (if any) + * @param filename name of the file from which the string value is to be retrieved + * @param key tag of the attribute to be retrieved + * @param result string variable in which the resulting value is stored + * @param searchIntoSub flag indicating whether to do a deep search or not + * @return reference to the resulting string value (parameter 'result') + */ + OFString &getStringFromFile(const OFFilename &filename, + const DcmTagKey &key, + OFString &result, + OFBool searchIntoSub = OFFalse); + + /** copy element from given dataset to directory record + * @param dataset DICOM dataset containing the original data + * @param key tag of the element to be copied + * @param record directory record to which the element is to be copied + * @param sourceFilename name of the source DICOM file + * @param optional flag indicating whether the element is optional or required + * @param copyEmpty flag indicating whether to copy an empty element (no value) + */ + void copyElement(DcmItem *dataset, + const DcmTagKey &key, + DcmDirectoryRecord *record, + const OFFilename &sourceFilename, + const OFBool optional = OFFalse, + const OFBool copyEmpty = OFTrue); + + /** copy type 1C element from given dataset or first item of the given sequence + * to directory record. Typically, the SharedFunctionalGroupsSequence is used + * with this method. + * @param dataset DICOM dataset containing the original data + * @param elementKey tag of the element to be copied + * @param sequenceKey tag of the sequence element to be used in case the element + * cannot be found on the main dataset level + * @param record directory record to which the element is to be copied + * @param sourceFilename name of the source DICOM file + */ + void copyElementType1CFromDatasetOrSequenceItem(DcmItem *dataset, + const DcmTagKey &elementKey, + const DcmTagKey &sequenceKey, + DcmDirectoryRecord *record, + const OFFilename &sourceFilename); + + /** copy type 1 element from given dataset to directory record + * @param dataset DICOM dataset containing the original data + * @param key tag of the element to be copied + * @param record directory record to which the element is to be copied + * @param sourceFilename name of the source DICOM file + */ + void copyElementType1(DcmItem *dataset, + const DcmTagKey &key, + DcmDirectoryRecord *record, + const OFFilename &sourceFilename) + { + copyElement(dataset, key, record, sourceFilename, OFFalse /*optional*/, OFFalse /*copyEmpty*/); + } + + /** copy type 1C element from given dataset to directory record + * @param dataset DICOM dataset containing the original data + * @param key tag of the element to be copied + * @param record directory record to which the element is to be copied + * @param sourceFilename name of the source DICOM file + */ + void copyElementType1C(DcmItem *dataset, + const DcmTagKey &key, + DcmDirectoryRecord *record, + const OFFilename &sourceFilename) + { + copyElement(dataset, key, record, sourceFilename, OFTrue /*optional*/, OFFalse /*copyEmpty*/); + } + + /** copy type 2 element from given dataset to directory record + * @param dataset DICOM dataset containing the original data + * @param key tag of the element to be copied + * @param record directory record to which the element is to be copied + * @param sourceFilename name of the source DICOM file + */ + void copyElementType2(DcmItem *dataset, + const DcmTagKey &key, + DcmDirectoryRecord *record, + const OFFilename &sourceFilename) + { + copyElement(dataset, key, record, sourceFilename, OFFalse /*optional*/, OFTrue /*copyEmpty*/); + } + + /** copy type 3 element from given dataset to directory record + * @param dataset DICOM dataset containing the original data + * @param key tag of the element to be copied + * @param record directory record to which the element is to be copied + * @param sourceFilename name of the source DICOM file + */ + void copyElementType3(DcmItem *dataset, + const DcmTagKey &key, + DcmDirectoryRecord *record, + const OFFilename &sourceFilename) + { + copyElement(dataset, key, record, sourceFilename, OFTrue /*optional*/, OFTrue /*copyEmpty*/); + } + + /** copy optional string value from given dataset to directory record + * @param dataset DICOM dataset containing the original data + * @param key tag of the element value to be copied + * @param record directory record to which the element value is to be copied + * @param sourceFilename name of the source DICOM file + * @param defaultValue default string value used in case the element is missing + * @param printWarning print warning message if element does not exist (with a value) + * and no default value is given + */ + void copyStringWithDefault(DcmItem *dataset, + const DcmTagKey &key, + DcmDirectoryRecord *record, + const OFFilename &sourceFilename, + const char *defaultValue = "", + const OFBool printWarning = OFFalse); + + /** compare string attribute from dataset and record and report any deviation + * @param dataset DICOM dataset where the string value is stored + * @param datKey tag of the string value to be compared (dataset) + * @param record directory record where the string value is stored + * @param recKey tag of the string value to be compared (record) + * @param sourceFilename name of the source DICOM file + * @param errorMsg report error if true, warning message otherwise (default) + * @return OFTrue if string values are identical, OFFalse otherwise + */ + OFBool compareStringAttributes(DcmItem *dataset, + const DcmTagKey &datKey, + DcmDirectoryRecord *record, + const DcmTagKey &recKey, + const OFFilename &sourceFilename, + const OFBool errorMsg = OFFalse); + + /** compare sequence attribute from dataset and record and report any deviation + * @param dataset DICOM dataset where the sequence value is stored + * @param key tag of the sequence to be compared + * @param record directory record where the sequence value is stored + * @param sourceFilename name of the source DICOM file + * @return OFTrue if sequences are identical, OFFalse otherwise + */ + OFBool compareSequenceAttributes(DcmItem *dataset, + DcmTagKey &key, + DcmDirectoryRecord *record, + const OFFilename &sourceFilename); + + /** set default value (number or prefix and number) to a given tag + * @param record directory record where the elements are stored + * @param key tag of the element to be modified + * @param number numeric value to be set as a the element value + * @param prefix optional prefix to be added to the numeric value + */ + void setDefaultValue(DcmDirectoryRecord *record, + const DcmTagKey &key, + const unsigned long number, + const char *prefix = NULL); + + + private: + + /// pointer to the current DICOMDIR object + DcmDicomDir *DicomDir; + + /// pointer to the optional image plugin (required for icon image support) + DicomDirImagePlugin *ImagePlugin; + + /// currently selected application profile + E_ApplicationProfile ApplicationProfile; + + /// create DICOMDIR backup + OFBool BackupMode; + /// abort on first inconsistent record + OFBool AbortMode; + /// automatically map filenames + OFBool MapFilenamesMode; + /// invent missing attributes mode + OFBool InventMode; + /// invent missing patient ID mode + OFBool InventPatientIDMode; + /// support retired SOP classes + OFBool RetiredSOPClassSupport; + /// check pixel encoding + OFBool EncodingCheck; + /// check image resolution + OFBool ResolutionCheck; + /// check transfer syntax + OFBool TransferSyntaxCheck; + /// check DICOM file format + OFBool FileFormatCheck; + /// check consistency of newly added record + OFBool ConsistencyCheck; + /// create icon images + OFBool IconImageMode; + /// update existing file-set + OFBool FilesetUpdateMode; + + /// name of the DICOMDIR backup file + OFFilename BackupFilename; + /// flag indicating whether a backup has been created + OFBool BackupCreated; + + /// size of the optional icon image in pixels + unsigned int IconSize; + /// filename prefix for the external icon images + OFFilename IconPrefix; + /// filename of the default icon (if any) + OFFilename DefaultIcon; + + /// flag indicating whether RLE decompression is supported + OFBool RLESupport; + /// flag indicating whether JPEG decompression is supported + OFBool JPEGSupport; + /// flag indicating whether JPEG 2000 decompression is supported + OFBool JP2KSupport; + + /// current patient number used to invent missing attribute values + unsigned long AutoPatientNumber; + /// current study number used to invent missing attribute values + unsigned long AutoStudyNumber; + /// current series number used to invent missing attribute values + unsigned long AutoSeriesNumber; + /// current instance number used to invent missing attribute values + unsigned long AutoInstanceNumber; + /// current overlay number used to invent missing attribute values + unsigned long AutoOverlayNumber; + /// current LUT number used to invent missing attribute values + unsigned long AutoLutNumber; + /// current curve number used to invent missing attribute values + unsigned long AutoCurveNumber; + + /// private undefined copy constructor + DicomDirInterface(const DicomDirInterface &obj); + + /// private undefined assignment operator + DicomDirInterface &operator=(const DicomDirInterface &obj); +}; + + +#endif diff --git a/dcmdata/include/dcmtk/dcmdata/dcdefine.h b/dcmdata/include/dcmtk/dcmdata/dcdefine.h new file mode 100644 index 00000000..7ec44b0a --- /dev/null +++ b/dcmdata/include/dcmtk/dcmdata/dcdefine.h @@ -0,0 +1,44 @@ +/* + * + * Copyright (C) 2011-2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Uli Schlachter + * + * Purpose: Contains preprocessor definitions + * + */ + + +#ifndef DCDEFINE_H +#define DCDEFINE_H + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/ofstd/ofdefine.h" + +// Workaround for Visual Studio to disable dll storage specifiers when linking directly into the executable. +// This is needed since the built-in dictionary code is created by the tools mkdeftag and mkdictbi and thus +// those tools statically link the few required dcmdata source files instead of linking to dcmdata as a whole. +#ifndef DCMDATA_BUILD_DICTIONARY +#ifdef dcmdata_EXPORTS +#define DCMTK_DCMDATA_EXPORT DCMTK_DECL_EXPORT +#else +#define DCMTK_DCMDATA_EXPORT DCMTK_DECL_IMPORT +#endif +#else +#define DCMTK_DCMDATA_EXPORT +#endif + + +#endif // DCDEFINE_H diff --git a/dcmdata/include/dcmtk/dcmdata/dcdeftag.h b/dcmdata/include/dcmtk/dcmdata/dcdeftag.h new file mode 100644 index 00000000..1f6e5c11 --- /dev/null +++ b/dcmdata/include/dcmtk/dcmdata/dcdeftag.h @@ -0,0 +1,4067 @@ +/* +** DO NOT EDIT THIS FILE !!! +** It was generated automatically by: +** +** User: joergr +** Host: thinkpad +** Date: 2015-09-18 11:18:13 +** Prog: /home/joergr/Source/dcmtk-full/public/dcmdata/libsrc/mkdeftag +** +** From: ../data/dicom.dic +** ../data/private.dic +** +*/ + +#ifndef DCDEFTAG_H +#define DCDEFTAG_H + +#include "dcmtk/dcmdata/dctagkey.h" + +#define DCM_DICT_DEFTAG_BUILD_DATE "2015-09-18 11:18:13" + + +/* +** Fixed Tags in ascending (gggg,eeee) order. +** Number of entries: 3956 +** Tags with a repeating component (repeating tags) are listed later. +*/ +#define DCM_CommandGroupLength DcmTagKey(0x0000, 0x0000) +#define DCM_RETIRED_CommandLengthToEnd DcmTagKey(0x0000, 0x0001) +#define DCM_AffectedSOPClassUID DcmTagKey(0x0000, 0x0002) +#define DCM_RequestedSOPClassUID DcmTagKey(0x0000, 0x0003) +#define DCM_RETIRED_CommandRecognitionCode DcmTagKey(0x0000, 0x0010) +#define DCM_CommandField DcmTagKey(0x0000, 0x0100) +#define DCM_MessageID DcmTagKey(0x0000, 0x0110) +#define DCM_MessageIDBeingRespondedTo DcmTagKey(0x0000, 0x0120) +#define DCM_RETIRED_Initiator DcmTagKey(0x0000, 0x0200) +#define DCM_RETIRED_Receiver DcmTagKey(0x0000, 0x0300) +#define DCM_RETIRED_FindLocation DcmTagKey(0x0000, 0x0400) +#define DCM_MoveDestination DcmTagKey(0x0000, 0x0600) +#define DCM_Priority DcmTagKey(0x0000, 0x0700) +#define DCM_CommandDataSetType DcmTagKey(0x0000, 0x0800) +#define DCM_RETIRED_NumberOfMatches DcmTagKey(0x0000, 0x0850) +#define DCM_RETIRED_ResponseSequenceNumber DcmTagKey(0x0000, 0x0860) +#define DCM_Status DcmTagKey(0x0000, 0x0900) +#define DCM_OffendingElement DcmTagKey(0x0000, 0x0901) +#define DCM_ErrorComment DcmTagKey(0x0000, 0x0902) +#define DCM_ErrorID DcmTagKey(0x0000, 0x0903) +#define DCM_AffectedSOPInstanceUID DcmTagKey(0x0000, 0x1000) +#define DCM_RequestedSOPInstanceUID DcmTagKey(0x0000, 0x1001) +#define DCM_EventTypeID DcmTagKey(0x0000, 0x1002) +#define DCM_AttributeIdentifierList DcmTagKey(0x0000, 0x1005) +#define DCM_ActionTypeID DcmTagKey(0x0000, 0x1008) +#define DCM_NumberOfRemainingSuboperations DcmTagKey(0x0000, 0x1020) +#define DCM_NumberOfCompletedSuboperations DcmTagKey(0x0000, 0x1021) +#define DCM_NumberOfFailedSuboperations DcmTagKey(0x0000, 0x1022) +#define DCM_NumberOfWarningSuboperations DcmTagKey(0x0000, 0x1023) +#define DCM_MoveOriginatorApplicationEntityTitle DcmTagKey(0x0000, 0x1030) +#define DCM_MoveOriginatorMessageID DcmTagKey(0x0000, 0x1031) +#define DCM_RETIRED_DialogReceiver DcmTagKey(0x0000, 0x4000) +#define DCM_RETIRED_TerminalType DcmTagKey(0x0000, 0x4010) +#define DCM_RETIRED_MessageSetID DcmTagKey(0x0000, 0x5010) +#define DCM_RETIRED_EndMessageID DcmTagKey(0x0000, 0x5020) +#define DCM_RETIRED_DisplayFormat DcmTagKey(0x0000, 0x5110) +#define DCM_RETIRED_PagePositionID DcmTagKey(0x0000, 0x5120) +#define DCM_RETIRED_TextFormatID DcmTagKey(0x0000, 0x5130) +#define DCM_RETIRED_NormalReverse DcmTagKey(0x0000, 0x5140) +#define DCM_RETIRED_AddGrayScale DcmTagKey(0x0000, 0x5150) +#define DCM_RETIRED_Borders DcmTagKey(0x0000, 0x5160) +#define DCM_RETIRED_Copies DcmTagKey(0x0000, 0x5170) +#define DCM_RETIRED_CommandMagnificationType DcmTagKey(0x0000, 0x5180) +#define DCM_RETIRED_Erase DcmTagKey(0x0000, 0x5190) +#define DCM_RETIRED_Print DcmTagKey(0x0000, 0x51a0) +#define DCM_RETIRED_Overlays DcmTagKey(0x0000, 0x51b0) +#define DCM_FileMetaInformationGroupLength DcmTagKey(0x0002, 0x0000) +#define DCM_FileMetaInformationVersion DcmTagKey(0x0002, 0x0001) +#define DCM_MediaStorageSOPClassUID DcmTagKey(0x0002, 0x0002) +#define DCM_MediaStorageSOPInstanceUID DcmTagKey(0x0002, 0x0003) +#define DCM_TransferSyntaxUID DcmTagKey(0x0002, 0x0010) +#define DCM_ImplementationClassUID DcmTagKey(0x0002, 0x0012) +#define DCM_ImplementationVersionName DcmTagKey(0x0002, 0x0013) +#define DCM_SourceApplicationEntityTitle DcmTagKey(0x0002, 0x0016) +#define DCM_SendingApplicationEntityTitle DcmTagKey(0x0002, 0x0017) +#define DCM_ReceivingApplicationEntityTitle DcmTagKey(0x0002, 0x0018) +#define DCM_PrivateInformationCreatorUID DcmTagKey(0x0002, 0x0100) +#define DCM_PrivateInformation DcmTagKey(0x0002, 0x0102) +#define DCM_FileSetID DcmTagKey(0x0004, 0x1130) +#define DCM_FileSetDescriptorFileID DcmTagKey(0x0004, 0x1141) +#define DCM_SpecificCharacterSetOfFileSetDescriptorFile DcmTagKey(0x0004, 0x1142) +#define DCM_OffsetOfTheFirstDirectoryRecordOfTheRootDirectoryEntity DcmTagKey(0x0004, 0x1200) +#define DCM_OffsetOfTheLastDirectoryRecordOfTheRootDirectoryEntity DcmTagKey(0x0004, 0x1202) +#define DCM_FileSetConsistencyFlag DcmTagKey(0x0004, 0x1212) +#define DCM_DirectoryRecordSequence DcmTagKey(0x0004, 0x1220) +#define DCM_OffsetOfTheNextDirectoryRecord DcmTagKey(0x0004, 0x1400) +#define DCM_RecordInUseFlag DcmTagKey(0x0004, 0x1410) +#define DCM_OffsetOfReferencedLowerLevelDirectoryEntity DcmTagKey(0x0004, 0x1420) +#define DCM_DirectoryRecordType DcmTagKey(0x0004, 0x1430) +#define DCM_PrivateRecordUID DcmTagKey(0x0004, 0x1432) +#define DCM_ReferencedFileID DcmTagKey(0x0004, 0x1500) +#define DCM_RETIRED_MRDRDirectoryRecordOffset DcmTagKey(0x0004, 0x1504) +#define DCM_ReferencedSOPClassUIDInFile DcmTagKey(0x0004, 0x1510) +#define DCM_ReferencedSOPInstanceUIDInFile DcmTagKey(0x0004, 0x1511) +#define DCM_ReferencedTransferSyntaxUIDInFile DcmTagKey(0x0004, 0x1512) +#define DCM_ReferencedRelatedGeneralSOPClassUIDInFile DcmTagKey(0x0004, 0x151a) +#define DCM_RETIRED_NumberOfReferences DcmTagKey(0x0004, 0x1600) +#define DCM_RETIRED_LengthToEnd DcmTagKey(0x0008, 0x0001) +#define DCM_SpecificCharacterSet DcmTagKey(0x0008, 0x0005) +#define DCM_LanguageCodeSequence DcmTagKey(0x0008, 0x0006) +#define DCM_ImageType DcmTagKey(0x0008, 0x0008) +#define DCM_RETIRED_RecognitionCode DcmTagKey(0x0008, 0x0010) +#define DCM_InstanceCreationDate DcmTagKey(0x0008, 0x0012) +#define DCM_InstanceCreationTime DcmTagKey(0x0008, 0x0013) +#define DCM_InstanceCreatorUID DcmTagKey(0x0008, 0x0014) +#define DCM_InstanceCoercionDateTime DcmTagKey(0x0008, 0x0015) +#define DCM_SOPClassUID DcmTagKey(0x0008, 0x0016) +#define DCM_SOPInstanceUID DcmTagKey(0x0008, 0x0018) +#define DCM_RelatedGeneralSOPClassUID DcmTagKey(0x0008, 0x001a) +#define DCM_OriginalSpecializedSOPClassUID DcmTagKey(0x0008, 0x001b) +#define DCM_StudyDate DcmTagKey(0x0008, 0x0020) +#define DCM_SeriesDate DcmTagKey(0x0008, 0x0021) +#define DCM_AcquisitionDate DcmTagKey(0x0008, 0x0022) +#define DCM_ContentDate DcmTagKey(0x0008, 0x0023) +#define DCM_RETIRED_OverlayDate DcmTagKey(0x0008, 0x0024) +#define DCM_RETIRED_CurveDate DcmTagKey(0x0008, 0x0025) +#define DCM_AcquisitionDateTime DcmTagKey(0x0008, 0x002a) +#define DCM_StudyTime DcmTagKey(0x0008, 0x0030) +#define DCM_SeriesTime DcmTagKey(0x0008, 0x0031) +#define DCM_AcquisitionTime DcmTagKey(0x0008, 0x0032) +#define DCM_ContentTime DcmTagKey(0x0008, 0x0033) +#define DCM_RETIRED_OverlayTime DcmTagKey(0x0008, 0x0034) +#define DCM_RETIRED_CurveTime DcmTagKey(0x0008, 0x0035) +#define DCM_RETIRED_DataSetType DcmTagKey(0x0008, 0x0040) +#define DCM_RETIRED_DataSetSubtype DcmTagKey(0x0008, 0x0041) +#define DCM_RETIRED_NuclearMedicineSeriesType DcmTagKey(0x0008, 0x0042) +#define DCM_AccessionNumber DcmTagKey(0x0008, 0x0050) +#define DCM_IssuerOfAccessionNumberSequence DcmTagKey(0x0008, 0x0051) +#define DCM_QueryRetrieveLevel DcmTagKey(0x0008, 0x0052) +#define DCM_QueryRetrieveView DcmTagKey(0x0008, 0x0053) +#define DCM_RetrieveAETitle DcmTagKey(0x0008, 0x0054) +#define DCM_InstanceAvailability DcmTagKey(0x0008, 0x0056) +#define DCM_FailedSOPInstanceUIDList DcmTagKey(0x0008, 0x0058) +#define DCM_Modality DcmTagKey(0x0008, 0x0060) +#define DCM_ModalitiesInStudy DcmTagKey(0x0008, 0x0061) +#define DCM_SOPClassesInStudy DcmTagKey(0x0008, 0x0062) +#define DCM_ConversionType DcmTagKey(0x0008, 0x0064) +#define DCM_PresentationIntentType DcmTagKey(0x0008, 0x0068) +#define DCM_Manufacturer DcmTagKey(0x0008, 0x0070) +#define DCM_InstitutionName DcmTagKey(0x0008, 0x0080) +#define DCM_InstitutionAddress DcmTagKey(0x0008, 0x0081) +#define DCM_InstitutionCodeSequence DcmTagKey(0x0008, 0x0082) +#define DCM_ReferringPhysicianName DcmTagKey(0x0008, 0x0090) +#define DCM_ReferringPhysicianAddress DcmTagKey(0x0008, 0x0092) +#define DCM_ReferringPhysicianTelephoneNumbers DcmTagKey(0x0008, 0x0094) +#define DCM_ReferringPhysicianIdentificationSequence DcmTagKey(0x0008, 0x0096) +#define DCM_ConsultingPhysicianName DcmTagKey(0x0008, 0x009c) +#define DCM_ConsultingPhysicianIdentificationSequence DcmTagKey(0x0008, 0x009d) +#define DCM_CodeValue DcmTagKey(0x0008, 0x0100) +#define DCM_ExtendedCodeValue DcmTagKey(0x0008, 0x0101) +#define DCM_CodingSchemeDesignator DcmTagKey(0x0008, 0x0102) +#define DCM_CodingSchemeVersion DcmTagKey(0x0008, 0x0103) +#define DCM_CodeMeaning DcmTagKey(0x0008, 0x0104) +#define DCM_MappingResource DcmTagKey(0x0008, 0x0105) +#define DCM_ContextGroupVersion DcmTagKey(0x0008, 0x0106) +#define DCM_ContextGroupLocalVersion DcmTagKey(0x0008, 0x0107) +#define DCM_ExtendedCodeMeaning DcmTagKey(0x0008, 0x0108) +#define DCM_ContextGroupExtensionFlag DcmTagKey(0x0008, 0x010b) +#define DCM_CodingSchemeUID DcmTagKey(0x0008, 0x010c) +#define DCM_ContextGroupExtensionCreatorUID DcmTagKey(0x0008, 0x010d) +#define DCM_ContextIdentifier DcmTagKey(0x0008, 0x010f) +#define DCM_CodingSchemeIdentificationSequence DcmTagKey(0x0008, 0x0110) +#define DCM_CodingSchemeRegistry DcmTagKey(0x0008, 0x0112) +#define DCM_CodingSchemeExternalID DcmTagKey(0x0008, 0x0114) +#define DCM_CodingSchemeName DcmTagKey(0x0008, 0x0115) +#define DCM_CodingSchemeResponsibleOrganization DcmTagKey(0x0008, 0x0116) +#define DCM_ContextUID DcmTagKey(0x0008, 0x0117) +#define DCM_MappingResourceUID DcmTagKey(0x0008, 0x0118) +#define DCM_LongCodeValue DcmTagKey(0x0008, 0x0119) +#define DCM_URNCodeValue DcmTagKey(0x0008, 0x0120) +#define DCM_EquivalentCodeSequence DcmTagKey(0x0008, 0x0121) +#define DCM_TimezoneOffsetFromUTC DcmTagKey(0x0008, 0x0201) +#define DCM_PrivateDataElementCharacteristicsSequence DcmTagKey(0x0008, 0x0300) +#define DCM_PrivateGroupReference DcmTagKey(0x0008, 0x0301) +#define DCM_PrivateCreatorReference DcmTagKey(0x0008, 0x0302) +#define DCM_BlockIdentifyingInformationStatus DcmTagKey(0x0008, 0x0303) +#define DCM_NonidentifyingPrivateElements DcmTagKey(0x0008, 0x0304) +#define DCM_DeidentificationActionSequence DcmTagKey(0x0008, 0x0305) +#define DCM_IdentifyingPrivateElements DcmTagKey(0x0008, 0x0306) +#define DCM_DeidentificationAction DcmTagKey(0x0008, 0x0307) +#define DCM_RETIRED_NetworkID DcmTagKey(0x0008, 0x1000) +#define DCM_StationName DcmTagKey(0x0008, 0x1010) +#define DCM_StudyDescription DcmTagKey(0x0008, 0x1030) +#define DCM_ProcedureCodeSequence DcmTagKey(0x0008, 0x1032) +#define DCM_SeriesDescription DcmTagKey(0x0008, 0x103e) +#define DCM_SeriesDescriptionCodeSequence DcmTagKey(0x0008, 0x103f) +#define DCM_InstitutionalDepartmentName DcmTagKey(0x0008, 0x1040) +#define DCM_PhysiciansOfRecord DcmTagKey(0x0008, 0x1048) +#define DCM_PhysiciansOfRecordIdentificationSequence DcmTagKey(0x0008, 0x1049) +#define DCM_PerformingPhysicianName DcmTagKey(0x0008, 0x1050) +#define DCM_PerformingPhysicianIdentificationSequence DcmTagKey(0x0008, 0x1052) +#define DCM_NameOfPhysiciansReadingStudy DcmTagKey(0x0008, 0x1060) +#define DCM_PhysiciansReadingStudyIdentificationSequence DcmTagKey(0x0008, 0x1062) +#define DCM_OperatorsName DcmTagKey(0x0008, 0x1070) +#define DCM_OperatorIdentificationSequence DcmTagKey(0x0008, 0x1072) +#define DCM_AdmittingDiagnosesDescription DcmTagKey(0x0008, 0x1080) +#define DCM_AdmittingDiagnosesCodeSequence DcmTagKey(0x0008, 0x1084) +#define DCM_ManufacturerModelName DcmTagKey(0x0008, 0x1090) +#define DCM_RETIRED_ReferencedResultsSequence DcmTagKey(0x0008, 0x1100) +#define DCM_ReferencedStudySequence DcmTagKey(0x0008, 0x1110) +#define DCM_ReferencedPerformedProcedureStepSequence DcmTagKey(0x0008, 0x1111) +#define DCM_ReferencedSeriesSequence DcmTagKey(0x0008, 0x1115) +#define DCM_ReferencedPatientSequence DcmTagKey(0x0008, 0x1120) +#define DCM_ReferencedVisitSequence DcmTagKey(0x0008, 0x1125) +#define DCM_RETIRED_ReferencedOverlaySequence DcmTagKey(0x0008, 0x1130) +#define DCM_ReferencedStereometricInstanceSequence DcmTagKey(0x0008, 0x1134) +#define DCM_ReferencedWaveformSequence DcmTagKey(0x0008, 0x113a) +#define DCM_ReferencedImageSequence DcmTagKey(0x0008, 0x1140) +#define DCM_RETIRED_ReferencedCurveSequence DcmTagKey(0x0008, 0x1145) +#define DCM_ReferencedInstanceSequence DcmTagKey(0x0008, 0x114a) +#define DCM_ReferencedRealWorldValueMappingInstanceSequence DcmTagKey(0x0008, 0x114b) +#define DCM_ReferencedSOPClassUID DcmTagKey(0x0008, 0x1150) +#define DCM_ReferencedSOPInstanceUID DcmTagKey(0x0008, 0x1155) +#define DCM_SOPClassesSupported DcmTagKey(0x0008, 0x115a) +#define DCM_ReferencedFrameNumber DcmTagKey(0x0008, 0x1160) +#define DCM_SimpleFrameList DcmTagKey(0x0008, 0x1161) +#define DCM_CalculatedFrameList DcmTagKey(0x0008, 0x1162) +#define DCM_TimeRange DcmTagKey(0x0008, 0x1163) +#define DCM_FrameExtractionSequence DcmTagKey(0x0008, 0x1164) +#define DCM_MultiFrameSourceSOPInstanceUID DcmTagKey(0x0008, 0x1167) +#define DCM_RetrieveURL DcmTagKey(0x0008, 0x1190) +#define DCM_TransactionUID DcmTagKey(0x0008, 0x1195) +#define DCM_WarningReason DcmTagKey(0x0008, 0x1196) +#define DCM_FailureReason DcmTagKey(0x0008, 0x1197) +#define DCM_FailedSOPSequence DcmTagKey(0x0008, 0x1198) +#define DCM_ReferencedSOPSequence DcmTagKey(0x0008, 0x1199) +#define DCM_StudiesContainingOtherReferencedInstancesSequence DcmTagKey(0x0008, 0x1200) +#define DCM_RelatedSeriesSequence DcmTagKey(0x0008, 0x1250) +#define DCM_RETIRED_LossyImageCompressionRetired DcmTagKey(0x0008, 0x2110) +#define DCM_DerivationDescription DcmTagKey(0x0008, 0x2111) +#define DCM_SourceImageSequence DcmTagKey(0x0008, 0x2112) +#define DCM_StageName DcmTagKey(0x0008, 0x2120) +#define DCM_StageNumber DcmTagKey(0x0008, 0x2122) +#define DCM_NumberOfStages DcmTagKey(0x0008, 0x2124) +#define DCM_ViewName DcmTagKey(0x0008, 0x2127) +#define DCM_ViewNumber DcmTagKey(0x0008, 0x2128) +#define DCM_NumberOfEventTimers DcmTagKey(0x0008, 0x2129) +#define DCM_NumberOfViewsInStage DcmTagKey(0x0008, 0x212a) +#define DCM_EventElapsedTimes DcmTagKey(0x0008, 0x2130) +#define DCM_EventTimerNames DcmTagKey(0x0008, 0x2132) +#define DCM_EventTimerSequence DcmTagKey(0x0008, 0x2133) +#define DCM_EventTimeOffset DcmTagKey(0x0008, 0x2134) +#define DCM_EventCodeSequence DcmTagKey(0x0008, 0x2135) +#define DCM_StartTrim DcmTagKey(0x0008, 0x2142) +#define DCM_StopTrim DcmTagKey(0x0008, 0x2143) +#define DCM_RecommendedDisplayFrameRate DcmTagKey(0x0008, 0x2144) +#define DCM_RETIRED_TransducerPosition DcmTagKey(0x0008, 0x2200) +#define DCM_RETIRED_TransducerOrientation DcmTagKey(0x0008, 0x2204) +#define DCM_RETIRED_AnatomicStructure DcmTagKey(0x0008, 0x2208) +#define DCM_AnatomicRegionSequence DcmTagKey(0x0008, 0x2218) +#define DCM_AnatomicRegionModifierSequence DcmTagKey(0x0008, 0x2220) +#define DCM_PrimaryAnatomicStructureSequence DcmTagKey(0x0008, 0x2228) +#define DCM_AnatomicStructureSpaceOrRegionSequence DcmTagKey(0x0008, 0x2229) +#define DCM_PrimaryAnatomicStructureModifierSequence DcmTagKey(0x0008, 0x2230) +#define DCM_RETIRED_TransducerPositionSequence DcmTagKey(0x0008, 0x2240) +#define DCM_RETIRED_TransducerPositionModifierSequence DcmTagKey(0x0008, 0x2242) +#define DCM_RETIRED_TransducerOrientationSequence DcmTagKey(0x0008, 0x2244) +#define DCM_RETIRED_TransducerOrientationModifierSequence DcmTagKey(0x0008, 0x2246) +#define DCM_RETIRED_AnatomicStructureSpaceOrRegionCodeSequenceTrial DcmTagKey(0x0008, 0x2251) +#define DCM_RETIRED_AnatomicPortalOfEntranceCodeSequenceTrial DcmTagKey(0x0008, 0x2253) +#define DCM_RETIRED_AnatomicApproachDirectionCodeSequenceTrial DcmTagKey(0x0008, 0x2255) +#define DCM_RETIRED_AnatomicPerspectiveDescriptionTrial DcmTagKey(0x0008, 0x2256) +#define DCM_RETIRED_AnatomicPerspectiveCodeSequenceTrial DcmTagKey(0x0008, 0x2257) +#define DCM_RETIRED_AnatomicLocationOfExaminingInstrumentDescriptionTrial DcmTagKey(0x0008, 0x2258) +#define DCM_RETIRED_AnatomicLocationOfExaminingInstrumentCodeSequenceTrial DcmTagKey(0x0008, 0x2259) +#define DCM_RETIRED_AnatomicStructureSpaceOrRegionModifierCodeSequenceTrial DcmTagKey(0x0008, 0x225a) +#define DCM_RETIRED_OnAxisBackgroundAnatomicStructureCodeSequenceTrial DcmTagKey(0x0008, 0x225c) +#define DCM_AlternateRepresentationSequence DcmTagKey(0x0008, 0x3001) +#define DCM_IrradiationEventUID DcmTagKey(0x0008, 0x3010) +#define DCM_SourceIrradiationEventSequence DcmTagKey(0x0008, 0x3011) +#define DCM_RadiopharmaceuticalAdministrationEventUID DcmTagKey(0x0008, 0x3012) +#define DCM_RETIRED_IdentifyingComments DcmTagKey(0x0008, 0x4000) +#define DCM_FrameType DcmTagKey(0x0008, 0x9007) +#define DCM_ReferencedImageEvidenceSequence DcmTagKey(0x0008, 0x9092) +#define DCM_ReferencedRawDataSequence DcmTagKey(0x0008, 0x9121) +#define DCM_CreatorVersionUID DcmTagKey(0x0008, 0x9123) +#define DCM_DerivationImageSequence DcmTagKey(0x0008, 0x9124) +#define DCM_SourceImageEvidenceSequence DcmTagKey(0x0008, 0x9154) +#define DCM_PixelPresentation DcmTagKey(0x0008, 0x9205) +#define DCM_VolumetricProperties DcmTagKey(0x0008, 0x9206) +#define DCM_VolumeBasedCalculationTechnique DcmTagKey(0x0008, 0x9207) +#define DCM_ComplexImageComponent DcmTagKey(0x0008, 0x9208) +#define DCM_AcquisitionContrast DcmTagKey(0x0008, 0x9209) +#define DCM_DerivationCodeSequence DcmTagKey(0x0008, 0x9215) +#define DCM_ReferencedPresentationStateSequence DcmTagKey(0x0008, 0x9237) +#define DCM_ReferencedOtherPlaneSequence DcmTagKey(0x0008, 0x9410) +#define DCM_FrameDisplaySequence DcmTagKey(0x0008, 0x9458) +#define DCM_RecommendedDisplayFrameRateInFloat DcmTagKey(0x0008, 0x9459) +#define DCM_SkipFrameRangeFlag DcmTagKey(0x0008, 0x9460) +#define DCM_PatientName DcmTagKey(0x0010, 0x0010) +#define DCM_PatientID DcmTagKey(0x0010, 0x0020) +#define DCM_IssuerOfPatientID DcmTagKey(0x0010, 0x0021) +#define DCM_TypeOfPatientID DcmTagKey(0x0010, 0x0022) +#define DCM_IssuerOfPatientIDQualifiersSequence DcmTagKey(0x0010, 0x0024) +#define DCM_PatientBirthDate DcmTagKey(0x0010, 0x0030) +#define DCM_PatientBirthTime DcmTagKey(0x0010, 0x0032) +#define DCM_PatientSex DcmTagKey(0x0010, 0x0040) +#define DCM_PatientInsurancePlanCodeSequence DcmTagKey(0x0010, 0x0050) +#define DCM_PatientPrimaryLanguageCodeSequence DcmTagKey(0x0010, 0x0101) +#define DCM_PatientPrimaryLanguageModifierCodeSequence DcmTagKey(0x0010, 0x0102) +#define DCM_QualityControlSubject DcmTagKey(0x0010, 0x0200) +#define DCM_QualityControlSubjectTypeCodeSequence DcmTagKey(0x0010, 0x0201) +#define DCM_OtherPatientIDs DcmTagKey(0x0010, 0x1000) +#define DCM_OtherPatientNames DcmTagKey(0x0010, 0x1001) +#define DCM_OtherPatientIDsSequence DcmTagKey(0x0010, 0x1002) +#define DCM_PatientBirthName DcmTagKey(0x0010, 0x1005) +#define DCM_PatientAge DcmTagKey(0x0010, 0x1010) +#define DCM_PatientSize DcmTagKey(0x0010, 0x1020) +#define DCM_PatientSizeCodeSequence DcmTagKey(0x0010, 0x1021) +#define DCM_PatientWeight DcmTagKey(0x0010, 0x1030) +#define DCM_PatientAddress DcmTagKey(0x0010, 0x1040) +#define DCM_RETIRED_InsurancePlanIdentification DcmTagKey(0x0010, 0x1050) +#define DCM_PatientMotherBirthName DcmTagKey(0x0010, 0x1060) +#define DCM_MilitaryRank DcmTagKey(0x0010, 0x1080) +#define DCM_BranchOfService DcmTagKey(0x0010, 0x1081) +#define DCM_MedicalRecordLocator DcmTagKey(0x0010, 0x1090) +#define DCM_ReferencedPatientPhotoSequence DcmTagKey(0x0010, 0x1100) +#define DCM_MedicalAlerts DcmTagKey(0x0010, 0x2000) +#define DCM_Allergies DcmTagKey(0x0010, 0x2110) +#define DCM_CountryOfResidence DcmTagKey(0x0010, 0x2150) +#define DCM_RegionOfResidence DcmTagKey(0x0010, 0x2152) +#define DCM_PatientTelephoneNumbers DcmTagKey(0x0010, 0x2154) +#define DCM_PatientTelecomInformation DcmTagKey(0x0010, 0x2155) +#define DCM_EthnicGroup DcmTagKey(0x0010, 0x2160) +#define DCM_Occupation DcmTagKey(0x0010, 0x2180) +#define DCM_SmokingStatus DcmTagKey(0x0010, 0x21a0) +#define DCM_AdditionalPatientHistory DcmTagKey(0x0010, 0x21b0) +#define DCM_PregnancyStatus DcmTagKey(0x0010, 0x21c0) +#define DCM_LastMenstrualDate DcmTagKey(0x0010, 0x21d0) +#define DCM_PatientReligiousPreference DcmTagKey(0x0010, 0x21f0) +#define DCM_PatientSpeciesDescription DcmTagKey(0x0010, 0x2201) +#define DCM_PatientSpeciesCodeSequence DcmTagKey(0x0010, 0x2202) +#define DCM_PatientSexNeutered DcmTagKey(0x0010, 0x2203) +#define DCM_AnatomicalOrientationType DcmTagKey(0x0010, 0x2210) +#define DCM_PatientBreedDescription DcmTagKey(0x0010, 0x2292) +#define DCM_PatientBreedCodeSequence DcmTagKey(0x0010, 0x2293) +#define DCM_BreedRegistrationSequence DcmTagKey(0x0010, 0x2294) +#define DCM_BreedRegistrationNumber DcmTagKey(0x0010, 0x2295) +#define DCM_BreedRegistryCodeSequence DcmTagKey(0x0010, 0x2296) +#define DCM_ResponsiblePerson DcmTagKey(0x0010, 0x2297) +#define DCM_ResponsiblePersonRole DcmTagKey(0x0010, 0x2298) +#define DCM_ResponsibleOrganization DcmTagKey(0x0010, 0x2299) +#define DCM_PatientComments DcmTagKey(0x0010, 0x4000) +#define DCM_ExaminedBodyThickness DcmTagKey(0x0010, 0x9431) +#define DCM_ClinicalTrialSponsorName DcmTagKey(0x0012, 0x0010) +#define DCM_ClinicalTrialProtocolID DcmTagKey(0x0012, 0x0020) +#define DCM_ClinicalTrialProtocolName DcmTagKey(0x0012, 0x0021) +#define DCM_ClinicalTrialSiteID DcmTagKey(0x0012, 0x0030) +#define DCM_ClinicalTrialSiteName DcmTagKey(0x0012, 0x0031) +#define DCM_ClinicalTrialSubjectID DcmTagKey(0x0012, 0x0040) +#define DCM_ClinicalTrialSubjectReadingID DcmTagKey(0x0012, 0x0042) +#define DCM_ClinicalTrialTimePointID DcmTagKey(0x0012, 0x0050) +#define DCM_ClinicalTrialTimePointDescription DcmTagKey(0x0012, 0x0051) +#define DCM_ClinicalTrialCoordinatingCenterName DcmTagKey(0x0012, 0x0060) +#define DCM_PatientIdentityRemoved DcmTagKey(0x0012, 0x0062) +#define DCM_DeidentificationMethod DcmTagKey(0x0012, 0x0063) +#define DCM_DeidentificationMethodCodeSequence DcmTagKey(0x0012, 0x0064) +#define DCM_ClinicalTrialSeriesID DcmTagKey(0x0012, 0x0071) +#define DCM_ClinicalTrialSeriesDescription DcmTagKey(0x0012, 0x0072) +#define DCM_ClinicalTrialProtocolEthicsCommitteeName DcmTagKey(0x0012, 0x0081) +#define DCM_ClinicalTrialProtocolEthicsCommitteeApprovalNumber DcmTagKey(0x0012, 0x0082) +#define DCM_ConsentForClinicalTrialUseSequence DcmTagKey(0x0012, 0x0083) +#define DCM_DistributionType DcmTagKey(0x0012, 0x0084) +#define DCM_ConsentForDistributionFlag DcmTagKey(0x0012, 0x0085) +#define DCM_RETIRED_CADFileFormat DcmTagKey(0x0014, 0x0023) +#define DCM_RETIRED_ComponentReferenceSystem DcmTagKey(0x0014, 0x0024) +#define DCM_ComponentManufacturingProcedure DcmTagKey(0x0014, 0x0025) +#define DCM_ComponentManufacturer DcmTagKey(0x0014, 0x0028) +#define DCM_MaterialThickness DcmTagKey(0x0014, 0x0030) +#define DCM_MaterialPipeDiameter DcmTagKey(0x0014, 0x0032) +#define DCM_MaterialIsolationDiameter DcmTagKey(0x0014, 0x0034) +#define DCM_MaterialGrade DcmTagKey(0x0014, 0x0042) +#define DCM_MaterialPropertiesDescription DcmTagKey(0x0014, 0x0044) +#define DCM_RETIRED_MaterialPropertiesFileFormatRetired DcmTagKey(0x0014, 0x0045) +#define DCM_MaterialNotes DcmTagKey(0x0014, 0x0046) +#define DCM_ComponentShape DcmTagKey(0x0014, 0x0050) +#define DCM_CurvatureType DcmTagKey(0x0014, 0x0052) +#define DCM_OuterDiameter DcmTagKey(0x0014, 0x0054) +#define DCM_InnerDiameter DcmTagKey(0x0014, 0x0056) +#define DCM_ActualEnvironmentalConditions DcmTagKey(0x0014, 0x1010) +#define DCM_ExpiryDate DcmTagKey(0x0014, 0x1020) +#define DCM_EnvironmentalConditions DcmTagKey(0x0014, 0x1040) +#define DCM_EvaluatorSequence DcmTagKey(0x0014, 0x2002) +#define DCM_EvaluatorNumber DcmTagKey(0x0014, 0x2004) +#define DCM_EvaluatorName DcmTagKey(0x0014, 0x2006) +#define DCM_EvaluationAttempt DcmTagKey(0x0014, 0x2008) +#define DCM_IndicationSequence DcmTagKey(0x0014, 0x2012) +#define DCM_IndicationNumber DcmTagKey(0x0014, 0x2014) +#define DCM_IndicationLabel DcmTagKey(0x0014, 0x2016) +#define DCM_IndicationDescription DcmTagKey(0x0014, 0x2018) +#define DCM_IndicationType DcmTagKey(0x0014, 0x201a) +#define DCM_IndicationDisposition DcmTagKey(0x0014, 0x201c) +#define DCM_IndicationROISequence DcmTagKey(0x0014, 0x201e) +#define DCM_IndicationPhysicalPropertySequence DcmTagKey(0x0014, 0x2030) +#define DCM_PropertyLabel DcmTagKey(0x0014, 0x2032) +#define DCM_CoordinateSystemNumberOfAxes DcmTagKey(0x0014, 0x2202) +#define DCM_CoordinateSystemAxesSequence DcmTagKey(0x0014, 0x2204) +#define DCM_CoordinateSystemAxisDescription DcmTagKey(0x0014, 0x2206) +#define DCM_CoordinateSystemDataSetMapping DcmTagKey(0x0014, 0x2208) +#define DCM_CoordinateSystemAxisNumber DcmTagKey(0x0014, 0x220a) +#define DCM_CoordinateSystemAxisType DcmTagKey(0x0014, 0x220c) +#define DCM_CoordinateSystemAxisUnits DcmTagKey(0x0014, 0x220e) +#define DCM_CoordinateSystemAxisValues DcmTagKey(0x0014, 0x2210) +#define DCM_CoordinateSystemTransformSequence DcmTagKey(0x0014, 0x2220) +#define DCM_TransformDescription DcmTagKey(0x0014, 0x2222) +#define DCM_TransformNumberOfAxes DcmTagKey(0x0014, 0x2224) +#define DCM_TransformOrderOfAxes DcmTagKey(0x0014, 0x2226) +#define DCM_TransformedAxisUnits DcmTagKey(0x0014, 0x2228) +#define DCM_CoordinateSystemTransformRotationAndScaleMatrix DcmTagKey(0x0014, 0x222a) +#define DCM_CoordinateSystemTransformTranslationMatrix DcmTagKey(0x0014, 0x222c) +#define DCM_InternalDetectorFrameTime DcmTagKey(0x0014, 0x3011) +#define DCM_NumberOfFramesIntegrated DcmTagKey(0x0014, 0x3012) +#define DCM_DetectorTemperatureSequence DcmTagKey(0x0014, 0x3020) +#define DCM_SensorName DcmTagKey(0x0014, 0x3022) +#define DCM_HorizontalOffsetOfSensor DcmTagKey(0x0014, 0x3024) +#define DCM_VerticalOffsetOfSensor DcmTagKey(0x0014, 0x3026) +#define DCM_SensorTemperature DcmTagKey(0x0014, 0x3028) +#define DCM_DarkCurrentSequence DcmTagKey(0x0014, 0x3040) +#define DCM_DarkCurrentCounts DcmTagKey(0x0014, 0x3050) +#define DCM_GainCorrectionReferenceSequence DcmTagKey(0x0014, 0x3060) +#define DCM_AirCounts DcmTagKey(0x0014, 0x3070) +#define DCM_KVUsedInGainCalibration DcmTagKey(0x0014, 0x3071) +#define DCM_MAUsedInGainCalibration DcmTagKey(0x0014, 0x3072) +#define DCM_NumberOfFramesUsedForIntegration DcmTagKey(0x0014, 0x3073) +#define DCM_FilterMaterialUsedInGainCalibration DcmTagKey(0x0014, 0x3074) +#define DCM_FilterThicknessUsedInGainCalibration DcmTagKey(0x0014, 0x3075) +#define DCM_DateOfGainCalibration DcmTagKey(0x0014, 0x3076) +#define DCM_TimeOfGainCalibration DcmTagKey(0x0014, 0x3077) +#define DCM_BadPixelImage DcmTagKey(0x0014, 0x3080) +#define DCM_CalibrationNotes DcmTagKey(0x0014, 0x3099) +#define DCM_PulserEquipmentSequence DcmTagKey(0x0014, 0x4002) +#define DCM_PulserType DcmTagKey(0x0014, 0x4004) +#define DCM_PulserNotes DcmTagKey(0x0014, 0x4006) +#define DCM_ReceiverEquipmentSequence DcmTagKey(0x0014, 0x4008) +#define DCM_AmplifierType DcmTagKey(0x0014, 0x400a) +#define DCM_ReceiverNotes DcmTagKey(0x0014, 0x400c) +#define DCM_PreAmplifierEquipmentSequence DcmTagKey(0x0014, 0x400e) +#define DCM_PreAmplifierNotes DcmTagKey(0x0014, 0x400f) +#define DCM_TransmitTransducerSequence DcmTagKey(0x0014, 0x4010) +#define DCM_ReceiveTransducerSequence DcmTagKey(0x0014, 0x4011) +#define DCM_NumberOfElements DcmTagKey(0x0014, 0x4012) +#define DCM_ElementShape DcmTagKey(0x0014, 0x4013) +#define DCM_ElementDimensionA DcmTagKey(0x0014, 0x4014) +#define DCM_ElementDimensionB DcmTagKey(0x0014, 0x4015) +#define DCM_ElementPitchA DcmTagKey(0x0014, 0x4016) +#define DCM_MeasuredBeamDimensionA DcmTagKey(0x0014, 0x4017) +#define DCM_MeasuredBeamDimensionB DcmTagKey(0x0014, 0x4018) +#define DCM_LocationOfMeasuredBeamDiameter DcmTagKey(0x0014, 0x4019) +#define DCM_NominalFrequency DcmTagKey(0x0014, 0x401a) +#define DCM_MeasuredCenterFrequency DcmTagKey(0x0014, 0x401b) +#define DCM_MeasuredBandwidth DcmTagKey(0x0014, 0x401c) +#define DCM_ElementPitchB DcmTagKey(0x0014, 0x401d) +#define DCM_PulserSettingsSequence DcmTagKey(0x0014, 0x4020) +#define DCM_PulseWidth DcmTagKey(0x0014, 0x4022) +#define DCM_ExcitationFrequency DcmTagKey(0x0014, 0x4024) +#define DCM_ModulationType DcmTagKey(0x0014, 0x4026) +#define DCM_Damping DcmTagKey(0x0014, 0x4028) +#define DCM_ReceiverSettingsSequence DcmTagKey(0x0014, 0x4030) +#define DCM_AcquiredSoundpathLength DcmTagKey(0x0014, 0x4031) +#define DCM_AcquisitionCompressionType DcmTagKey(0x0014, 0x4032) +#define DCM_AcquisitionSampleSize DcmTagKey(0x0014, 0x4033) +#define DCM_RectifierSmoothing DcmTagKey(0x0014, 0x4034) +#define DCM_DACSequence DcmTagKey(0x0014, 0x4035) +#define DCM_DACType DcmTagKey(0x0014, 0x4036) +#define DCM_DACGainPoints DcmTagKey(0x0014, 0x4038) +#define DCM_DACTimePoints DcmTagKey(0x0014, 0x403a) +#define DCM_DACAmplitude DcmTagKey(0x0014, 0x403c) +#define DCM_PreAmplifierSettingsSequence DcmTagKey(0x0014, 0x4040) +#define DCM_TransmitTransducerSettingsSequence DcmTagKey(0x0014, 0x4050) +#define DCM_ReceiveTransducerSettingsSequence DcmTagKey(0x0014, 0x4051) +#define DCM_IncidentAngle DcmTagKey(0x0014, 0x4052) +#define DCM_CouplingTechnique DcmTagKey(0x0014, 0x4054) +#define DCM_CouplingMedium DcmTagKey(0x0014, 0x4056) +#define DCM_CouplingVelocity DcmTagKey(0x0014, 0x4057) +#define DCM_ProbeCenterLocationX DcmTagKey(0x0014, 0x4058) +#define DCM_ProbeCenterLocationZ DcmTagKey(0x0014, 0x4059) +#define DCM_SoundPathLength DcmTagKey(0x0014, 0x405a) +#define DCM_DelayLawIdentifier DcmTagKey(0x0014, 0x405c) +#define DCM_GateSettingsSequence DcmTagKey(0x0014, 0x4060) +#define DCM_GateThreshold DcmTagKey(0x0014, 0x4062) +#define DCM_VelocityOfSound DcmTagKey(0x0014, 0x4064) +#define DCM_CalibrationSettingsSequence DcmTagKey(0x0014, 0x4070) +#define DCM_CalibrationProcedure DcmTagKey(0x0014, 0x4072) +#define DCM_ProcedureVersion DcmTagKey(0x0014, 0x4074) +#define DCM_ProcedureCreationDate DcmTagKey(0x0014, 0x4076) +#define DCM_ProcedureExpirationDate DcmTagKey(0x0014, 0x4078) +#define DCM_ProcedureLastModifiedDate DcmTagKey(0x0014, 0x407a) +#define DCM_CalibrationTime DcmTagKey(0x0014, 0x407c) +#define DCM_CalibrationDate DcmTagKey(0x0014, 0x407e) +#define DCM_ProbeDriveEquipmentSequence DcmTagKey(0x0014, 0x4080) +#define DCM_DriveType DcmTagKey(0x0014, 0x4081) +#define DCM_ProbeDriveNotes DcmTagKey(0x0014, 0x4082) +#define DCM_DriveProbeSequence DcmTagKey(0x0014, 0x4083) +#define DCM_ProbeInductance DcmTagKey(0x0014, 0x4084) +#define DCM_ProbeResistance DcmTagKey(0x0014, 0x4085) +#define DCM_ReceiveProbeSequence DcmTagKey(0x0014, 0x4086) +#define DCM_ProbeDriveSettingsSequence DcmTagKey(0x0014, 0x4087) +#define DCM_BridgeResistors DcmTagKey(0x0014, 0x4088) +#define DCM_ProbeOrientationAngle DcmTagKey(0x0014, 0x4089) +#define DCM_UserSelectedGainY DcmTagKey(0x0014, 0x408b) +#define DCM_UserSelectedPhase DcmTagKey(0x0014, 0x408c) +#define DCM_UserSelectedOffsetX DcmTagKey(0x0014, 0x408d) +#define DCM_UserSelectedOffsetY DcmTagKey(0x0014, 0x408e) +#define DCM_ChannelSettingsSequence DcmTagKey(0x0014, 0x4091) +#define DCM_ChannelThreshold DcmTagKey(0x0014, 0x4092) +#define DCM_ScannerSettingsSequence DcmTagKey(0x0014, 0x409a) +#define DCM_ScanProcedure DcmTagKey(0x0014, 0x409b) +#define DCM_TranslationRateX DcmTagKey(0x0014, 0x409c) +#define DCM_TranslationRateY DcmTagKey(0x0014, 0x409d) +#define DCM_ChannelOverlap DcmTagKey(0x0014, 0x409f) +#define DCM_ImageQualityIndicatorType DcmTagKey(0x0014, 0x40a0) +#define DCM_ImageQualityIndicatorMaterial DcmTagKey(0x0014, 0x40a1) +#define DCM_ImageQualityIndicatorSize DcmTagKey(0x0014, 0x40a2) +#define DCM_LINACEnergy DcmTagKey(0x0014, 0x5002) +#define DCM_LINACOutput DcmTagKey(0x0014, 0x5004) +#define DCM_ActiveAperture DcmTagKey(0x0014, 0x5100) +#define DCM_TotalAperture DcmTagKey(0x0014, 0x5101) +#define DCM_ApertureElevation DcmTagKey(0x0014, 0x5102) +#define DCM_MainLobeAngle DcmTagKey(0x0014, 0x5103) +#define DCM_MainRoofAngle DcmTagKey(0x0014, 0x5104) +#define DCM_ConnectorType DcmTagKey(0x0014, 0x5105) +#define DCM_WedgeModelNumber DcmTagKey(0x0014, 0x5106) +#define DCM_WedgeAngleFloat DcmTagKey(0x0014, 0x5107) +#define DCM_WedgeRoofAngle DcmTagKey(0x0014, 0x5108) +#define DCM_WedgeElement1Position DcmTagKey(0x0014, 0x5109) +#define DCM_WedgeMaterialVelocity DcmTagKey(0x0014, 0x510a) +#define DCM_WedgeMaterial DcmTagKey(0x0014, 0x510b) +#define DCM_WedgeOffsetZ DcmTagKey(0x0014, 0x510c) +#define DCM_WedgeOriginOffsetX DcmTagKey(0x0014, 0x510d) +#define DCM_WedgeTimeDelay DcmTagKey(0x0014, 0x510e) +#define DCM_WedgeName DcmTagKey(0x0014, 0x510f) +#define DCM_WedgeManufacturerName DcmTagKey(0x0014, 0x5110) +#define DCM_WedgeDescription DcmTagKey(0x0014, 0x5111) +#define DCM_NominalBeamAngle DcmTagKey(0x0014, 0x5112) +#define DCM_WedgeOffsetX DcmTagKey(0x0014, 0x5113) +#define DCM_WedgeOffsetY DcmTagKey(0x0014, 0x5114) +#define DCM_WedgeTotalLength DcmTagKey(0x0014, 0x5115) +#define DCM_WedgeInContactLength DcmTagKey(0x0014, 0x5116) +#define DCM_WedgeFrontGap DcmTagKey(0x0014, 0x5117) +#define DCM_WedgeTotalHeight DcmTagKey(0x0014, 0x5118) +#define DCM_WedgeFrontHeight DcmTagKey(0x0014, 0x5119) +#define DCM_WedgeRearHeight DcmTagKey(0x0014, 0x511a) +#define DCM_WedgeTotalWidth DcmTagKey(0x0014, 0x511b) +#define DCM_WedgeInContactWidth DcmTagKey(0x0014, 0x511c) +#define DCM_WedgeChamferHeight DcmTagKey(0x0014, 0x511d) +#define DCM_WedgeCurve DcmTagKey(0x0014, 0x511e) +#define DCM_RadiusAlongWedge DcmTagKey(0x0014, 0x511f) +#define DCM_ContrastBolusAgent DcmTagKey(0x0018, 0x0010) +#define DCM_ContrastBolusAgentSequence DcmTagKey(0x0018, 0x0012) +#define DCM_ContrastBolusT1Relaxivity DcmTagKey(0x0018, 0x0013) +#define DCM_ContrastBolusAdministrationRouteSequence DcmTagKey(0x0018, 0x0014) +#define DCM_BodyPartExamined DcmTagKey(0x0018, 0x0015) +#define DCM_ScanningSequence DcmTagKey(0x0018, 0x0020) +#define DCM_SequenceVariant DcmTagKey(0x0018, 0x0021) +#define DCM_ScanOptions DcmTagKey(0x0018, 0x0022) +#define DCM_MRAcquisitionType DcmTagKey(0x0018, 0x0023) +#define DCM_SequenceName DcmTagKey(0x0018, 0x0024) +#define DCM_AngioFlag DcmTagKey(0x0018, 0x0025) +#define DCM_InterventionDrugInformationSequence DcmTagKey(0x0018, 0x0026) +#define DCM_InterventionDrugStopTime DcmTagKey(0x0018, 0x0027) +#define DCM_InterventionDrugDose DcmTagKey(0x0018, 0x0028) +#define DCM_InterventionDrugCodeSequence DcmTagKey(0x0018, 0x0029) +#define DCM_AdditionalDrugSequence DcmTagKey(0x0018, 0x002a) +#define DCM_RETIRED_Radionuclide DcmTagKey(0x0018, 0x0030) +#define DCM_Radiopharmaceutical DcmTagKey(0x0018, 0x0031) +#define DCM_RETIRED_EnergyWindowCenterline DcmTagKey(0x0018, 0x0032) +#define DCM_RETIRED_EnergyWindowTotalWidth DcmTagKey(0x0018, 0x0033) +#define DCM_InterventionDrugName DcmTagKey(0x0018, 0x0034) +#define DCM_InterventionDrugStartTime DcmTagKey(0x0018, 0x0035) +#define DCM_InterventionSequence DcmTagKey(0x0018, 0x0036) +#define DCM_RETIRED_TherapyType DcmTagKey(0x0018, 0x0037) +#define DCM_InterventionStatus DcmTagKey(0x0018, 0x0038) +#define DCM_RETIRED_TherapyDescription DcmTagKey(0x0018, 0x0039) +#define DCM_InterventionDescription DcmTagKey(0x0018, 0x003a) +#define DCM_CineRate DcmTagKey(0x0018, 0x0040) +#define DCM_InitialCineRunState DcmTagKey(0x0018, 0x0042) +#define DCM_SliceThickness DcmTagKey(0x0018, 0x0050) +#define DCM_KVP DcmTagKey(0x0018, 0x0060) +#define DCM_CountsAccumulated DcmTagKey(0x0018, 0x0070) +#define DCM_AcquisitionTerminationCondition DcmTagKey(0x0018, 0x0071) +#define DCM_EffectiveDuration DcmTagKey(0x0018, 0x0072) +#define DCM_AcquisitionStartCondition DcmTagKey(0x0018, 0x0073) +#define DCM_AcquisitionStartConditionData DcmTagKey(0x0018, 0x0074) +#define DCM_AcquisitionTerminationConditionData DcmTagKey(0x0018, 0x0075) +#define DCM_RepetitionTime DcmTagKey(0x0018, 0x0080) +#define DCM_EchoTime DcmTagKey(0x0018, 0x0081) +#define DCM_InversionTime DcmTagKey(0x0018, 0x0082) +#define DCM_NumberOfAverages DcmTagKey(0x0018, 0x0083) +#define DCM_ImagingFrequency DcmTagKey(0x0018, 0x0084) +#define DCM_ImagedNucleus DcmTagKey(0x0018, 0x0085) +#define DCM_EchoNumbers DcmTagKey(0x0018, 0x0086) +#define DCM_MagneticFieldStrength DcmTagKey(0x0018, 0x0087) +#define DCM_SpacingBetweenSlices DcmTagKey(0x0018, 0x0088) +#define DCM_NumberOfPhaseEncodingSteps DcmTagKey(0x0018, 0x0089) +#define DCM_DataCollectionDiameter DcmTagKey(0x0018, 0x0090) +#define DCM_EchoTrainLength DcmTagKey(0x0018, 0x0091) +#define DCM_PercentSampling DcmTagKey(0x0018, 0x0093) +#define DCM_PercentPhaseFieldOfView DcmTagKey(0x0018, 0x0094) +#define DCM_PixelBandwidth DcmTagKey(0x0018, 0x0095) +#define DCM_DeviceSerialNumber DcmTagKey(0x0018, 0x1000) +#define DCM_DeviceUID DcmTagKey(0x0018, 0x1002) +#define DCM_DeviceID DcmTagKey(0x0018, 0x1003) +#define DCM_PlateID DcmTagKey(0x0018, 0x1004) +#define DCM_GeneratorID DcmTagKey(0x0018, 0x1005) +#define DCM_GridID DcmTagKey(0x0018, 0x1006) +#define DCM_CassetteID DcmTagKey(0x0018, 0x1007) +#define DCM_GantryID DcmTagKey(0x0018, 0x1008) +#define DCM_SecondaryCaptureDeviceID DcmTagKey(0x0018, 0x1010) +#define DCM_RETIRED_HardcopyCreationDeviceID DcmTagKey(0x0018, 0x1011) +#define DCM_DateOfSecondaryCapture DcmTagKey(0x0018, 0x1012) +#define DCM_TimeOfSecondaryCapture DcmTagKey(0x0018, 0x1014) +#define DCM_SecondaryCaptureDeviceManufacturer DcmTagKey(0x0018, 0x1016) +#define DCM_RETIRED_HardcopyDeviceManufacturer DcmTagKey(0x0018, 0x1017) +#define DCM_SecondaryCaptureDeviceManufacturerModelName DcmTagKey(0x0018, 0x1018) +#define DCM_SecondaryCaptureDeviceSoftwareVersions DcmTagKey(0x0018, 0x1019) +#define DCM_RETIRED_HardcopyDeviceSoftwareVersion DcmTagKey(0x0018, 0x101a) +#define DCM_RETIRED_HardcopyDeviceManufacturerModelName DcmTagKey(0x0018, 0x101b) +#define DCM_SoftwareVersions DcmTagKey(0x0018, 0x1020) +#define DCM_VideoImageFormatAcquired DcmTagKey(0x0018, 0x1022) +#define DCM_DigitalImageFormatAcquired DcmTagKey(0x0018, 0x1023) +#define DCM_ProtocolName DcmTagKey(0x0018, 0x1030) +#define DCM_ContrastBolusRoute DcmTagKey(0x0018, 0x1040) +#define DCM_ContrastBolusVolume DcmTagKey(0x0018, 0x1041) +#define DCM_ContrastBolusStartTime DcmTagKey(0x0018, 0x1042) +#define DCM_ContrastBolusStopTime DcmTagKey(0x0018, 0x1043) +#define DCM_ContrastBolusTotalDose DcmTagKey(0x0018, 0x1044) +#define DCM_SyringeCounts DcmTagKey(0x0018, 0x1045) +#define DCM_ContrastFlowRate DcmTagKey(0x0018, 0x1046) +#define DCM_ContrastFlowDuration DcmTagKey(0x0018, 0x1047) +#define DCM_ContrastBolusIngredient DcmTagKey(0x0018, 0x1048) +#define DCM_ContrastBolusIngredientConcentration DcmTagKey(0x0018, 0x1049) +#define DCM_SpatialResolution DcmTagKey(0x0018, 0x1050) +#define DCM_TriggerTime DcmTagKey(0x0018, 0x1060) +#define DCM_TriggerSourceOrType DcmTagKey(0x0018, 0x1061) +#define DCM_NominalInterval DcmTagKey(0x0018, 0x1062) +#define DCM_FrameTime DcmTagKey(0x0018, 0x1063) +#define DCM_CardiacFramingType DcmTagKey(0x0018, 0x1064) +#define DCM_FrameTimeVector DcmTagKey(0x0018, 0x1065) +#define DCM_FrameDelay DcmTagKey(0x0018, 0x1066) +#define DCM_ImageTriggerDelay DcmTagKey(0x0018, 0x1067) +#define DCM_MultiplexGroupTimeOffset DcmTagKey(0x0018, 0x1068) +#define DCM_TriggerTimeOffset DcmTagKey(0x0018, 0x1069) +#define DCM_SynchronizationTrigger DcmTagKey(0x0018, 0x106a) +#define DCM_SynchronizationChannel DcmTagKey(0x0018, 0x106c) +#define DCM_TriggerSamplePosition DcmTagKey(0x0018, 0x106e) +#define DCM_RadiopharmaceuticalRoute DcmTagKey(0x0018, 0x1070) +#define DCM_RadiopharmaceuticalVolume DcmTagKey(0x0018, 0x1071) +#define DCM_RadiopharmaceuticalStartTime DcmTagKey(0x0018, 0x1072) +#define DCM_RadiopharmaceuticalStopTime DcmTagKey(0x0018, 0x1073) +#define DCM_RadionuclideTotalDose DcmTagKey(0x0018, 0x1074) +#define DCM_RadionuclideHalfLife DcmTagKey(0x0018, 0x1075) +#define DCM_RadionuclidePositronFraction DcmTagKey(0x0018, 0x1076) +#define DCM_RadiopharmaceuticalSpecificActivity DcmTagKey(0x0018, 0x1077) +#define DCM_RadiopharmaceuticalStartDateTime DcmTagKey(0x0018, 0x1078) +#define DCM_RadiopharmaceuticalStopDateTime DcmTagKey(0x0018, 0x1079) +#define DCM_BeatRejectionFlag DcmTagKey(0x0018, 0x1080) +#define DCM_LowRRValue DcmTagKey(0x0018, 0x1081) +#define DCM_HighRRValue DcmTagKey(0x0018, 0x1082) +#define DCM_IntervalsAcquired DcmTagKey(0x0018, 0x1083) +#define DCM_IntervalsRejected DcmTagKey(0x0018, 0x1084) +#define DCM_PVCRejection DcmTagKey(0x0018, 0x1085) +#define DCM_SkipBeats DcmTagKey(0x0018, 0x1086) +#define DCM_HeartRate DcmTagKey(0x0018, 0x1088) +#define DCM_CardiacNumberOfImages DcmTagKey(0x0018, 0x1090) +#define DCM_TriggerWindow DcmTagKey(0x0018, 0x1094) +#define DCM_ReconstructionDiameter DcmTagKey(0x0018, 0x1100) +#define DCM_DistanceSourceToDetector DcmTagKey(0x0018, 0x1110) +#define DCM_DistanceSourceToPatient DcmTagKey(0x0018, 0x1111) +#define DCM_EstimatedRadiographicMagnificationFactor DcmTagKey(0x0018, 0x1114) +#define DCM_GantryDetectorTilt DcmTagKey(0x0018, 0x1120) +#define DCM_GantryDetectorSlew DcmTagKey(0x0018, 0x1121) +#define DCM_TableHeight DcmTagKey(0x0018, 0x1130) +#define DCM_TableTraverse DcmTagKey(0x0018, 0x1131) +#define DCM_TableMotion DcmTagKey(0x0018, 0x1134) +#define DCM_TableVerticalIncrement DcmTagKey(0x0018, 0x1135) +#define DCM_TableLateralIncrement DcmTagKey(0x0018, 0x1136) +#define DCM_TableLongitudinalIncrement DcmTagKey(0x0018, 0x1137) +#define DCM_TableAngle DcmTagKey(0x0018, 0x1138) +#define DCM_TableType DcmTagKey(0x0018, 0x113a) +#define DCM_RotationDirection DcmTagKey(0x0018, 0x1140) +#define DCM_RETIRED_AngularPosition DcmTagKey(0x0018, 0x1141) +#define DCM_RadialPosition DcmTagKey(0x0018, 0x1142) +#define DCM_ScanArc DcmTagKey(0x0018, 0x1143) +#define DCM_AngularStep DcmTagKey(0x0018, 0x1144) +#define DCM_CenterOfRotationOffset DcmTagKey(0x0018, 0x1145) +#define DCM_RETIRED_RotationOffset DcmTagKey(0x0018, 0x1146) +#define DCM_FieldOfViewShape DcmTagKey(0x0018, 0x1147) +#define DCM_FieldOfViewDimensions DcmTagKey(0x0018, 0x1149) +#define DCM_ExposureTime DcmTagKey(0x0018, 0x1150) +#define DCM_XRayTubeCurrent DcmTagKey(0x0018, 0x1151) +#define DCM_Exposure DcmTagKey(0x0018, 0x1152) +#define DCM_ExposureInuAs DcmTagKey(0x0018, 0x1153) +#define DCM_AveragePulseWidth DcmTagKey(0x0018, 0x1154) +#define DCM_RadiationSetting DcmTagKey(0x0018, 0x1155) +#define DCM_RectificationType DcmTagKey(0x0018, 0x1156) +#define DCM_RadiationMode DcmTagKey(0x0018, 0x115a) +#define DCM_ImageAndFluoroscopyAreaDoseProduct DcmTagKey(0x0018, 0x115e) +#define DCM_FilterType DcmTagKey(0x0018, 0x1160) +#define DCM_TypeOfFilters DcmTagKey(0x0018, 0x1161) +#define DCM_IntensifierSize DcmTagKey(0x0018, 0x1162) +#define DCM_ImagerPixelSpacing DcmTagKey(0x0018, 0x1164) +#define DCM_Grid DcmTagKey(0x0018, 0x1166) +#define DCM_GeneratorPower DcmTagKey(0x0018, 0x1170) +#define DCM_CollimatorGridName DcmTagKey(0x0018, 0x1180) +#define DCM_CollimatorType DcmTagKey(0x0018, 0x1181) +#define DCM_FocalDistance DcmTagKey(0x0018, 0x1182) +#define DCM_XFocusCenter DcmTagKey(0x0018, 0x1183) +#define DCM_YFocusCenter DcmTagKey(0x0018, 0x1184) +#define DCM_FocalSpots DcmTagKey(0x0018, 0x1190) +#define DCM_AnodeTargetMaterial DcmTagKey(0x0018, 0x1191) +#define DCM_BodyPartThickness DcmTagKey(0x0018, 0x11a0) +#define DCM_CompressionForce DcmTagKey(0x0018, 0x11a2) +#define DCM_PaddleDescription DcmTagKey(0x0018, 0x11a4) +#define DCM_DateOfLastCalibration DcmTagKey(0x0018, 0x1200) +#define DCM_TimeOfLastCalibration DcmTagKey(0x0018, 0x1201) +#define DCM_DateTimeOfLastCalibration DcmTagKey(0x0018, 0x1202) +#define DCM_ConvolutionKernel DcmTagKey(0x0018, 0x1210) +#define DCM_RETIRED_UpperLowerPixelValues DcmTagKey(0x0018, 0x1240) +#define DCM_ActualFrameDuration DcmTagKey(0x0018, 0x1242) +#define DCM_CountRate DcmTagKey(0x0018, 0x1243) +#define DCM_PreferredPlaybackSequencing DcmTagKey(0x0018, 0x1244) +#define DCM_ReceiveCoilName DcmTagKey(0x0018, 0x1250) +#define DCM_TransmitCoilName DcmTagKey(0x0018, 0x1251) +#define DCM_PlateType DcmTagKey(0x0018, 0x1260) +#define DCM_PhosphorType DcmTagKey(0x0018, 0x1261) +#define DCM_ScanVelocity DcmTagKey(0x0018, 0x1300) +#define DCM_WholeBodyTechnique DcmTagKey(0x0018, 0x1301) +#define DCM_ScanLength DcmTagKey(0x0018, 0x1302) +#define DCM_AcquisitionMatrix DcmTagKey(0x0018, 0x1310) +#define DCM_InPlanePhaseEncodingDirection DcmTagKey(0x0018, 0x1312) +#define DCM_FlipAngle DcmTagKey(0x0018, 0x1314) +#define DCM_VariableFlipAngleFlag DcmTagKey(0x0018, 0x1315) +#define DCM_SAR DcmTagKey(0x0018, 0x1316) +#define DCM_dBdt DcmTagKey(0x0018, 0x1318) +#define DCM_B1rms DcmTagKey(0x0018, 0x1320) +#define DCM_AcquisitionDeviceProcessingDescription DcmTagKey(0x0018, 0x1400) +#define DCM_AcquisitionDeviceProcessingCode DcmTagKey(0x0018, 0x1401) +#define DCM_CassetteOrientation DcmTagKey(0x0018, 0x1402) +#define DCM_CassetteSize DcmTagKey(0x0018, 0x1403) +#define DCM_ExposuresOnPlate DcmTagKey(0x0018, 0x1404) +#define DCM_RelativeXRayExposure DcmTagKey(0x0018, 0x1405) +#define DCM_ExposureIndex DcmTagKey(0x0018, 0x1411) +#define DCM_TargetExposureIndex DcmTagKey(0x0018, 0x1412) +#define DCM_DeviationIndex DcmTagKey(0x0018, 0x1413) +#define DCM_ColumnAngulation DcmTagKey(0x0018, 0x1450) +#define DCM_TomoLayerHeight DcmTagKey(0x0018, 0x1460) +#define DCM_TomoAngle DcmTagKey(0x0018, 0x1470) +#define DCM_TomoTime DcmTagKey(0x0018, 0x1480) +#define DCM_TomoType DcmTagKey(0x0018, 0x1490) +#define DCM_TomoClass DcmTagKey(0x0018, 0x1491) +#define DCM_NumberOfTomosynthesisSourceImages DcmTagKey(0x0018, 0x1495) +#define DCM_PositionerMotion DcmTagKey(0x0018, 0x1500) +#define DCM_PositionerType DcmTagKey(0x0018, 0x1508) +#define DCM_PositionerPrimaryAngle DcmTagKey(0x0018, 0x1510) +#define DCM_PositionerSecondaryAngle DcmTagKey(0x0018, 0x1511) +#define DCM_PositionerPrimaryAngleIncrement DcmTagKey(0x0018, 0x1520) +#define DCM_PositionerSecondaryAngleIncrement DcmTagKey(0x0018, 0x1521) +#define DCM_DetectorPrimaryAngle DcmTagKey(0x0018, 0x1530) +#define DCM_DetectorSecondaryAngle DcmTagKey(0x0018, 0x1531) +#define DCM_ShutterShape DcmTagKey(0x0018, 0x1600) +#define DCM_ShutterLeftVerticalEdge DcmTagKey(0x0018, 0x1602) +#define DCM_ShutterRightVerticalEdge DcmTagKey(0x0018, 0x1604) +#define DCM_ShutterUpperHorizontalEdge DcmTagKey(0x0018, 0x1606) +#define DCM_ShutterLowerHorizontalEdge DcmTagKey(0x0018, 0x1608) +#define DCM_CenterOfCircularShutter DcmTagKey(0x0018, 0x1610) +#define DCM_RadiusOfCircularShutter DcmTagKey(0x0018, 0x1612) +#define DCM_VerticesOfThePolygonalShutter DcmTagKey(0x0018, 0x1620) +#define DCM_ShutterPresentationValue DcmTagKey(0x0018, 0x1622) +#define DCM_ShutterOverlayGroup DcmTagKey(0x0018, 0x1623) +#define DCM_ShutterPresentationColorCIELabValue DcmTagKey(0x0018, 0x1624) +#define DCM_CollimatorShape DcmTagKey(0x0018, 0x1700) +#define DCM_CollimatorLeftVerticalEdge DcmTagKey(0x0018, 0x1702) +#define DCM_CollimatorRightVerticalEdge DcmTagKey(0x0018, 0x1704) +#define DCM_CollimatorUpperHorizontalEdge DcmTagKey(0x0018, 0x1706) +#define DCM_CollimatorLowerHorizontalEdge DcmTagKey(0x0018, 0x1708) +#define DCM_CenterOfCircularCollimator DcmTagKey(0x0018, 0x1710) +#define DCM_RadiusOfCircularCollimator DcmTagKey(0x0018, 0x1712) +#define DCM_VerticesOfThePolygonalCollimator DcmTagKey(0x0018, 0x1720) +#define DCM_AcquisitionTimeSynchronized DcmTagKey(0x0018, 0x1800) +#define DCM_TimeSource DcmTagKey(0x0018, 0x1801) +#define DCM_TimeDistributionProtocol DcmTagKey(0x0018, 0x1802) +#define DCM_NTPSourceAddress DcmTagKey(0x0018, 0x1803) +#define DCM_PageNumberVector DcmTagKey(0x0018, 0x2001) +#define DCM_FrameLabelVector DcmTagKey(0x0018, 0x2002) +#define DCM_FramePrimaryAngleVector DcmTagKey(0x0018, 0x2003) +#define DCM_FrameSecondaryAngleVector DcmTagKey(0x0018, 0x2004) +#define DCM_SliceLocationVector DcmTagKey(0x0018, 0x2005) +#define DCM_DisplayWindowLabelVector DcmTagKey(0x0018, 0x2006) +#define DCM_NominalScannedPixelSpacing DcmTagKey(0x0018, 0x2010) +#define DCM_DigitizingDeviceTransportDirection DcmTagKey(0x0018, 0x2020) +#define DCM_RotationOfScannedFilm DcmTagKey(0x0018, 0x2030) +#define DCM_BiopsyTargetSequence DcmTagKey(0x0018, 0x2041) +#define DCM_TargetUID DcmTagKey(0x0018, 0x2042) +#define DCM_LocalizingCursorPosition DcmTagKey(0x0018, 0x2043) +#define DCM_CalculatedTargetPosition DcmTagKey(0x0018, 0x2044) +#define DCM_TargetLabel DcmTagKey(0x0018, 0x2045) +#define DCM_DisplayedZValue DcmTagKey(0x0018, 0x2046) +#define DCM_IVUSAcquisition DcmTagKey(0x0018, 0x3100) +#define DCM_IVUSPullbackRate DcmTagKey(0x0018, 0x3101) +#define DCM_IVUSGatedRate DcmTagKey(0x0018, 0x3102) +#define DCM_IVUSPullbackStartFrameNumber DcmTagKey(0x0018, 0x3103) +#define DCM_IVUSPullbackStopFrameNumber DcmTagKey(0x0018, 0x3104) +#define DCM_LesionNumber DcmTagKey(0x0018, 0x3105) +#define DCM_RETIRED_AcquisitionComments DcmTagKey(0x0018, 0x4000) +#define DCM_OutputPower DcmTagKey(0x0018, 0x5000) +#define DCM_TransducerData DcmTagKey(0x0018, 0x5010) +#define DCM_FocusDepth DcmTagKey(0x0018, 0x5012) +#define DCM_ProcessingFunction DcmTagKey(0x0018, 0x5020) +#define DCM_RETIRED_PostprocessingFunction DcmTagKey(0x0018, 0x5021) +#define DCM_MechanicalIndex DcmTagKey(0x0018, 0x5022) +#define DCM_BoneThermalIndex DcmTagKey(0x0018, 0x5024) +#define DCM_CranialThermalIndex DcmTagKey(0x0018, 0x5026) +#define DCM_SoftTissueThermalIndex DcmTagKey(0x0018, 0x5027) +#define DCM_SoftTissueFocusThermalIndex DcmTagKey(0x0018, 0x5028) +#define DCM_SoftTissueSurfaceThermalIndex DcmTagKey(0x0018, 0x5029) +#define DCM_RETIRED_DynamicRange DcmTagKey(0x0018, 0x5030) +#define DCM_RETIRED_TotalGain DcmTagKey(0x0018, 0x5040) +#define DCM_DepthOfScanField DcmTagKey(0x0018, 0x5050) +#define DCM_PatientPosition DcmTagKey(0x0018, 0x5100) +#define DCM_ViewPosition DcmTagKey(0x0018, 0x5101) +#define DCM_ProjectionEponymousNameCodeSequence DcmTagKey(0x0018, 0x5104) +#define DCM_RETIRED_ImageTransformationMatrix DcmTagKey(0x0018, 0x5210) +#define DCM_RETIRED_ImageTranslationVector DcmTagKey(0x0018, 0x5212) +#define DCM_Sensitivity DcmTagKey(0x0018, 0x6000) +#define DCM_SequenceOfUltrasoundRegions DcmTagKey(0x0018, 0x6011) +#define DCM_RegionSpatialFormat DcmTagKey(0x0018, 0x6012) +#define DCM_RegionDataType DcmTagKey(0x0018, 0x6014) +#define DCM_RegionFlags DcmTagKey(0x0018, 0x6016) +#define DCM_RegionLocationMinX0 DcmTagKey(0x0018, 0x6018) +#define DCM_RegionLocationMinY0 DcmTagKey(0x0018, 0x601a) +#define DCM_RegionLocationMaxX1 DcmTagKey(0x0018, 0x601c) +#define DCM_RegionLocationMaxY1 DcmTagKey(0x0018, 0x601e) +#define DCM_ReferencePixelX0 DcmTagKey(0x0018, 0x6020) +#define DCM_ReferencePixelY0 DcmTagKey(0x0018, 0x6022) +#define DCM_PhysicalUnitsXDirection DcmTagKey(0x0018, 0x6024) +#define DCM_PhysicalUnitsYDirection DcmTagKey(0x0018, 0x6026) +#define DCM_ReferencePixelPhysicalValueX DcmTagKey(0x0018, 0x6028) +#define DCM_ReferencePixelPhysicalValueY DcmTagKey(0x0018, 0x602a) +#define DCM_PhysicalDeltaX DcmTagKey(0x0018, 0x602c) +#define DCM_PhysicalDeltaY DcmTagKey(0x0018, 0x602e) +#define DCM_TransducerFrequency DcmTagKey(0x0018, 0x6030) +#define DCM_TransducerType DcmTagKey(0x0018, 0x6031) +#define DCM_PulseRepetitionFrequency DcmTagKey(0x0018, 0x6032) +#define DCM_DopplerCorrectionAngle DcmTagKey(0x0018, 0x6034) +#define DCM_SteeringAngle DcmTagKey(0x0018, 0x6036) +#define DCM_RETIRED_DopplerSampleVolumeXPositionRetired DcmTagKey(0x0018, 0x6038) +#define DCM_DopplerSampleVolumeXPosition DcmTagKey(0x0018, 0x6039) +#define DCM_RETIRED_DopplerSampleVolumeYPositionRetired DcmTagKey(0x0018, 0x603a) +#define DCM_DopplerSampleVolumeYPosition DcmTagKey(0x0018, 0x603b) +#define DCM_RETIRED_TMLinePositionX0Retired DcmTagKey(0x0018, 0x603c) +#define DCM_TMLinePositionX0 DcmTagKey(0x0018, 0x603d) +#define DCM_RETIRED_TMLinePositionY0Retired DcmTagKey(0x0018, 0x603e) +#define DCM_TMLinePositionY0 DcmTagKey(0x0018, 0x603f) +#define DCM_RETIRED_TMLinePositionX1Retired DcmTagKey(0x0018, 0x6040) +#define DCM_TMLinePositionX1 DcmTagKey(0x0018, 0x6041) +#define DCM_RETIRED_TMLinePositionY1Retired DcmTagKey(0x0018, 0x6042) +#define DCM_TMLinePositionY1 DcmTagKey(0x0018, 0x6043) +#define DCM_PixelComponentOrganization DcmTagKey(0x0018, 0x6044) +#define DCM_PixelComponentMask DcmTagKey(0x0018, 0x6046) +#define DCM_PixelComponentRangeStart DcmTagKey(0x0018, 0x6048) +#define DCM_PixelComponentRangeStop DcmTagKey(0x0018, 0x604a) +#define DCM_PixelComponentPhysicalUnits DcmTagKey(0x0018, 0x604c) +#define DCM_PixelComponentDataType DcmTagKey(0x0018, 0x604e) +#define DCM_NumberOfTableBreakPoints DcmTagKey(0x0018, 0x6050) +#define DCM_TableOfXBreakPoints DcmTagKey(0x0018, 0x6052) +#define DCM_TableOfYBreakPoints DcmTagKey(0x0018, 0x6054) +#define DCM_NumberOfTableEntries DcmTagKey(0x0018, 0x6056) +#define DCM_TableOfPixelValues DcmTagKey(0x0018, 0x6058) +#define DCM_TableOfParameterValues DcmTagKey(0x0018, 0x605a) +#define DCM_RWaveTimeVector DcmTagKey(0x0018, 0x6060) +#define DCM_DetectorConditionsNominalFlag DcmTagKey(0x0018, 0x7000) +#define DCM_DetectorTemperature DcmTagKey(0x0018, 0x7001) +#define DCM_DetectorType DcmTagKey(0x0018, 0x7004) +#define DCM_DetectorConfiguration DcmTagKey(0x0018, 0x7005) +#define DCM_DetectorDescription DcmTagKey(0x0018, 0x7006) +#define DCM_DetectorMode DcmTagKey(0x0018, 0x7008) +#define DCM_DetectorID DcmTagKey(0x0018, 0x700a) +#define DCM_DateOfLastDetectorCalibration DcmTagKey(0x0018, 0x700c) +#define DCM_TimeOfLastDetectorCalibration DcmTagKey(0x0018, 0x700e) +#define DCM_ExposuresOnDetectorSinceLastCalibration DcmTagKey(0x0018, 0x7010) +#define DCM_ExposuresOnDetectorSinceManufactured DcmTagKey(0x0018, 0x7011) +#define DCM_DetectorTimeSinceLastExposure DcmTagKey(0x0018, 0x7012) +#define DCM_DetectorActiveTime DcmTagKey(0x0018, 0x7014) +#define DCM_DetectorActivationOffsetFromExposure DcmTagKey(0x0018, 0x7016) +#define DCM_DetectorBinning DcmTagKey(0x0018, 0x701a) +#define DCM_DetectorElementPhysicalSize DcmTagKey(0x0018, 0x7020) +#define DCM_DetectorElementSpacing DcmTagKey(0x0018, 0x7022) +#define DCM_DetectorActiveShape DcmTagKey(0x0018, 0x7024) +#define DCM_DetectorActiveDimensions DcmTagKey(0x0018, 0x7026) +#define DCM_DetectorActiveOrigin DcmTagKey(0x0018, 0x7028) +#define DCM_DetectorManufacturerName DcmTagKey(0x0018, 0x702a) +#define DCM_DetectorManufacturerModelName DcmTagKey(0x0018, 0x702b) +#define DCM_FieldOfViewOrigin DcmTagKey(0x0018, 0x7030) +#define DCM_FieldOfViewRotation DcmTagKey(0x0018, 0x7032) +#define DCM_FieldOfViewHorizontalFlip DcmTagKey(0x0018, 0x7034) +#define DCM_PixelDataAreaOriginRelativeToFOV DcmTagKey(0x0018, 0x7036) +#define DCM_PixelDataAreaRotationAngleRelativeToFOV DcmTagKey(0x0018, 0x7038) +#define DCM_GridAbsorbingMaterial DcmTagKey(0x0018, 0x7040) +#define DCM_GridSpacingMaterial DcmTagKey(0x0018, 0x7041) +#define DCM_GridThickness DcmTagKey(0x0018, 0x7042) +#define DCM_GridPitch DcmTagKey(0x0018, 0x7044) +#define DCM_GridAspectRatio DcmTagKey(0x0018, 0x7046) +#define DCM_GridPeriod DcmTagKey(0x0018, 0x7048) +#define DCM_GridFocalDistance DcmTagKey(0x0018, 0x704c) +#define DCM_FilterMaterial DcmTagKey(0x0018, 0x7050) +#define DCM_FilterThicknessMinimum DcmTagKey(0x0018, 0x7052) +#define DCM_FilterThicknessMaximum DcmTagKey(0x0018, 0x7054) +#define DCM_FilterBeamPathLengthMinimum DcmTagKey(0x0018, 0x7056) +#define DCM_FilterBeamPathLengthMaximum DcmTagKey(0x0018, 0x7058) +#define DCM_ExposureControlMode DcmTagKey(0x0018, 0x7060) +#define DCM_ExposureControlModeDescription DcmTagKey(0x0018, 0x7062) +#define DCM_ExposureStatus DcmTagKey(0x0018, 0x7064) +#define DCM_PhototimerSetting DcmTagKey(0x0018, 0x7065) +#define DCM_ExposureTimeInuS DcmTagKey(0x0018, 0x8150) +#define DCM_XRayTubeCurrentInuA DcmTagKey(0x0018, 0x8151) +#define DCM_ContentQualification DcmTagKey(0x0018, 0x9004) +#define DCM_PulseSequenceName DcmTagKey(0x0018, 0x9005) +#define DCM_MRImagingModifierSequence DcmTagKey(0x0018, 0x9006) +#define DCM_EchoPulseSequence DcmTagKey(0x0018, 0x9008) +#define DCM_InversionRecovery DcmTagKey(0x0018, 0x9009) +#define DCM_FlowCompensation DcmTagKey(0x0018, 0x9010) +#define DCM_MultipleSpinEcho DcmTagKey(0x0018, 0x9011) +#define DCM_MultiPlanarExcitation DcmTagKey(0x0018, 0x9012) +#define DCM_PhaseContrast DcmTagKey(0x0018, 0x9014) +#define DCM_TimeOfFlightContrast DcmTagKey(0x0018, 0x9015) +#define DCM_Spoiling DcmTagKey(0x0018, 0x9016) +#define DCM_SteadyStatePulseSequence DcmTagKey(0x0018, 0x9017) +#define DCM_EchoPlanarPulseSequence DcmTagKey(0x0018, 0x9018) +#define DCM_TagAngleFirstAxis DcmTagKey(0x0018, 0x9019) +#define DCM_MagnetizationTransfer DcmTagKey(0x0018, 0x9020) +#define DCM_T2Preparation DcmTagKey(0x0018, 0x9021) +#define DCM_BloodSignalNulling DcmTagKey(0x0018, 0x9022) +#define DCM_SaturationRecovery DcmTagKey(0x0018, 0x9024) +#define DCM_SpectrallySelectedSuppression DcmTagKey(0x0018, 0x9025) +#define DCM_SpectrallySelectedExcitation DcmTagKey(0x0018, 0x9026) +#define DCM_SpatialPresaturation DcmTagKey(0x0018, 0x9027) +#define DCM_Tagging DcmTagKey(0x0018, 0x9028) +#define DCM_OversamplingPhase DcmTagKey(0x0018, 0x9029) +#define DCM_TagSpacingFirstDimension DcmTagKey(0x0018, 0x9030) +#define DCM_GeometryOfKSpaceTraversal DcmTagKey(0x0018, 0x9032) +#define DCM_SegmentedKSpaceTraversal DcmTagKey(0x0018, 0x9033) +#define DCM_RectilinearPhaseEncodeReordering DcmTagKey(0x0018, 0x9034) +#define DCM_TagThickness DcmTagKey(0x0018, 0x9035) +#define DCM_PartialFourierDirection DcmTagKey(0x0018, 0x9036) +#define DCM_CardiacSynchronizationTechnique DcmTagKey(0x0018, 0x9037) +#define DCM_ReceiveCoilManufacturerName DcmTagKey(0x0018, 0x9041) +#define DCM_MRReceiveCoilSequence DcmTagKey(0x0018, 0x9042) +#define DCM_ReceiveCoilType DcmTagKey(0x0018, 0x9043) +#define DCM_QuadratureReceiveCoil DcmTagKey(0x0018, 0x9044) +#define DCM_MultiCoilDefinitionSequence DcmTagKey(0x0018, 0x9045) +#define DCM_MultiCoilConfiguration DcmTagKey(0x0018, 0x9046) +#define DCM_MultiCoilElementName DcmTagKey(0x0018, 0x9047) +#define DCM_MultiCoilElementUsed DcmTagKey(0x0018, 0x9048) +#define DCM_MRTransmitCoilSequence DcmTagKey(0x0018, 0x9049) +#define DCM_TransmitCoilManufacturerName DcmTagKey(0x0018, 0x9050) +#define DCM_TransmitCoilType DcmTagKey(0x0018, 0x9051) +#define DCM_SpectralWidth DcmTagKey(0x0018, 0x9052) +#define DCM_ChemicalShiftReference DcmTagKey(0x0018, 0x9053) +#define DCM_VolumeLocalizationTechnique DcmTagKey(0x0018, 0x9054) +#define DCM_MRAcquisitionFrequencyEncodingSteps DcmTagKey(0x0018, 0x9058) +#define DCM_Decoupling DcmTagKey(0x0018, 0x9059) +#define DCM_DecoupledNucleus DcmTagKey(0x0018, 0x9060) +#define DCM_DecouplingFrequency DcmTagKey(0x0018, 0x9061) +#define DCM_DecouplingMethod DcmTagKey(0x0018, 0x9062) +#define DCM_DecouplingChemicalShiftReference DcmTagKey(0x0018, 0x9063) +#define DCM_KSpaceFiltering DcmTagKey(0x0018, 0x9064) +#define DCM_TimeDomainFiltering DcmTagKey(0x0018, 0x9065) +#define DCM_NumberOfZeroFills DcmTagKey(0x0018, 0x9066) +#define DCM_BaselineCorrection DcmTagKey(0x0018, 0x9067) +#define DCM_ParallelReductionFactorInPlane DcmTagKey(0x0018, 0x9069) +#define DCM_CardiacRRIntervalSpecified DcmTagKey(0x0018, 0x9070) +#define DCM_AcquisitionDuration DcmTagKey(0x0018, 0x9073) +#define DCM_FrameAcquisitionDateTime DcmTagKey(0x0018, 0x9074) +#define DCM_DiffusionDirectionality DcmTagKey(0x0018, 0x9075) +#define DCM_DiffusionGradientDirectionSequence DcmTagKey(0x0018, 0x9076) +#define DCM_ParallelAcquisition DcmTagKey(0x0018, 0x9077) +#define DCM_ParallelAcquisitionTechnique DcmTagKey(0x0018, 0x9078) +#define DCM_InversionTimes DcmTagKey(0x0018, 0x9079) +#define DCM_MetaboliteMapDescription DcmTagKey(0x0018, 0x9080) +#define DCM_PartialFourier DcmTagKey(0x0018, 0x9081) +#define DCM_EffectiveEchoTime DcmTagKey(0x0018, 0x9082) +#define DCM_MetaboliteMapCodeSequence DcmTagKey(0x0018, 0x9083) +#define DCM_ChemicalShiftSequence DcmTagKey(0x0018, 0x9084) +#define DCM_CardiacSignalSource DcmTagKey(0x0018, 0x9085) +#define DCM_DiffusionBValue DcmTagKey(0x0018, 0x9087) +#define DCM_DiffusionGradientOrientation DcmTagKey(0x0018, 0x9089) +#define DCM_VelocityEncodingDirection DcmTagKey(0x0018, 0x9090) +#define DCM_VelocityEncodingMinimumValue DcmTagKey(0x0018, 0x9091) +#define DCM_VelocityEncodingAcquisitionSequence DcmTagKey(0x0018, 0x9092) +#define DCM_NumberOfKSpaceTrajectories DcmTagKey(0x0018, 0x9093) +#define DCM_CoverageOfKSpace DcmTagKey(0x0018, 0x9094) +#define DCM_SpectroscopyAcquisitionPhaseRows DcmTagKey(0x0018, 0x9095) +#define DCM_RETIRED_ParallelReductionFactorInPlaneRetired DcmTagKey(0x0018, 0x9096) +#define DCM_TransmitterFrequency DcmTagKey(0x0018, 0x9098) +#define DCM_ResonantNucleus DcmTagKey(0x0018, 0x9100) +#define DCM_FrequencyCorrection DcmTagKey(0x0018, 0x9101) +#define DCM_MRSpectroscopyFOVGeometrySequence DcmTagKey(0x0018, 0x9103) +#define DCM_SlabThickness DcmTagKey(0x0018, 0x9104) +#define DCM_SlabOrientation DcmTagKey(0x0018, 0x9105) +#define DCM_MidSlabPosition DcmTagKey(0x0018, 0x9106) +#define DCM_MRSpatialSaturationSequence DcmTagKey(0x0018, 0x9107) +#define DCM_MRTimingAndRelatedParametersSequence DcmTagKey(0x0018, 0x9112) +#define DCM_MREchoSequence DcmTagKey(0x0018, 0x9114) +#define DCM_MRModifierSequence DcmTagKey(0x0018, 0x9115) +#define DCM_MRDiffusionSequence DcmTagKey(0x0018, 0x9117) +#define DCM_CardiacSynchronizationSequence DcmTagKey(0x0018, 0x9118) +#define DCM_MRAveragesSequence DcmTagKey(0x0018, 0x9119) +#define DCM_MRFOVGeometrySequence DcmTagKey(0x0018, 0x9125) +#define DCM_VolumeLocalizationSequence DcmTagKey(0x0018, 0x9126) +#define DCM_SpectroscopyAcquisitionDataColumns DcmTagKey(0x0018, 0x9127) +#define DCM_DiffusionAnisotropyType DcmTagKey(0x0018, 0x9147) +#define DCM_FrameReferenceDateTime DcmTagKey(0x0018, 0x9151) +#define DCM_MRMetaboliteMapSequence DcmTagKey(0x0018, 0x9152) +#define DCM_ParallelReductionFactorOutOfPlane DcmTagKey(0x0018, 0x9155) +#define DCM_SpectroscopyAcquisitionOutOfPlanePhaseSteps DcmTagKey(0x0018, 0x9159) +#define DCM_RETIRED_BulkMotionStatus DcmTagKey(0x0018, 0x9166) +#define DCM_ParallelReductionFactorSecondInPlane DcmTagKey(0x0018, 0x9168) +#define DCM_CardiacBeatRejectionTechnique DcmTagKey(0x0018, 0x9169) +#define DCM_RespiratoryMotionCompensationTechnique DcmTagKey(0x0018, 0x9170) +#define DCM_RespiratorySignalSource DcmTagKey(0x0018, 0x9171) +#define DCM_BulkMotionCompensationTechnique DcmTagKey(0x0018, 0x9172) +#define DCM_BulkMotionSignalSource DcmTagKey(0x0018, 0x9173) +#define DCM_ApplicableSafetyStandardAgency DcmTagKey(0x0018, 0x9174) +#define DCM_ApplicableSafetyStandardDescription DcmTagKey(0x0018, 0x9175) +#define DCM_OperatingModeSequence DcmTagKey(0x0018, 0x9176) +#define DCM_OperatingModeType DcmTagKey(0x0018, 0x9177) +#define DCM_OperatingMode DcmTagKey(0x0018, 0x9178) +#define DCM_SpecificAbsorptionRateDefinition DcmTagKey(0x0018, 0x9179) +#define DCM_GradientOutputType DcmTagKey(0x0018, 0x9180) +#define DCM_SpecificAbsorptionRateValue DcmTagKey(0x0018, 0x9181) +#define DCM_GradientOutput DcmTagKey(0x0018, 0x9182) +#define DCM_FlowCompensationDirection DcmTagKey(0x0018, 0x9183) +#define DCM_TaggingDelay DcmTagKey(0x0018, 0x9184) +#define DCM_RespiratoryMotionCompensationTechniqueDescription DcmTagKey(0x0018, 0x9185) +#define DCM_RespiratorySignalSourceID DcmTagKey(0x0018, 0x9186) +#define DCM_RETIRED_ChemicalShiftMinimumIntegrationLimitInHz DcmTagKey(0x0018, 0x9195) +#define DCM_RETIRED_ChemicalShiftMaximumIntegrationLimitInHz DcmTagKey(0x0018, 0x9196) +#define DCM_MRVelocityEncodingSequence DcmTagKey(0x0018, 0x9197) +#define DCM_FirstOrderPhaseCorrection DcmTagKey(0x0018, 0x9198) +#define DCM_WaterReferencedPhaseCorrection DcmTagKey(0x0018, 0x9199) +#define DCM_MRSpectroscopyAcquisitionType DcmTagKey(0x0018, 0x9200) +#define DCM_RespiratoryCyclePosition DcmTagKey(0x0018, 0x9214) +#define DCM_VelocityEncodingMaximumValue DcmTagKey(0x0018, 0x9217) +#define DCM_TagSpacingSecondDimension DcmTagKey(0x0018, 0x9218) +#define DCM_TagAngleSecondAxis DcmTagKey(0x0018, 0x9219) +#define DCM_FrameAcquisitionDuration DcmTagKey(0x0018, 0x9220) +#define DCM_MRImageFrameTypeSequence DcmTagKey(0x0018, 0x9226) +#define DCM_MRSpectroscopyFrameTypeSequence DcmTagKey(0x0018, 0x9227) +#define DCM_MRAcquisitionPhaseEncodingStepsInPlane DcmTagKey(0x0018, 0x9231) +#define DCM_MRAcquisitionPhaseEncodingStepsOutOfPlane DcmTagKey(0x0018, 0x9232) +#define DCM_SpectroscopyAcquisitionPhaseColumns DcmTagKey(0x0018, 0x9234) +#define DCM_CardiacCyclePosition DcmTagKey(0x0018, 0x9236) +#define DCM_SpecificAbsorptionRateSequence DcmTagKey(0x0018, 0x9239) +#define DCM_RFEchoTrainLength DcmTagKey(0x0018, 0x9240) +#define DCM_GradientEchoTrainLength DcmTagKey(0x0018, 0x9241) +#define DCM_ArterialSpinLabelingContrast DcmTagKey(0x0018, 0x9250) +#define DCM_MRArterialSpinLabelingSequence DcmTagKey(0x0018, 0x9251) +#define DCM_ASLTechniqueDescription DcmTagKey(0x0018, 0x9252) +#define DCM_ASLSlabNumber DcmTagKey(0x0018, 0x9253) +#define DCM_ASLSlabThickness DcmTagKey(0x0018, 0x9254) +#define DCM_ASLSlabOrientation DcmTagKey(0x0018, 0x9255) +#define DCM_ASLMidSlabPosition DcmTagKey(0x0018, 0x9256) +#define DCM_ASLContext DcmTagKey(0x0018, 0x9257) +#define DCM_ASLPulseTrainDuration DcmTagKey(0x0018, 0x9258) +#define DCM_ASLCrusherFlag DcmTagKey(0x0018, 0x9259) +#define DCM_ASLCrusherFlowLimit DcmTagKey(0x0018, 0x925a) +#define DCM_ASLCrusherDescription DcmTagKey(0x0018, 0x925b) +#define DCM_ASLBolusCutoffFlag DcmTagKey(0x0018, 0x925c) +#define DCM_ASLBolusCutoffTimingSequence DcmTagKey(0x0018, 0x925d) +#define DCM_ASLBolusCutoffTechnique DcmTagKey(0x0018, 0x925e) +#define DCM_ASLBolusCutoffDelayTime DcmTagKey(0x0018, 0x925f) +#define DCM_ASLSlabSequence DcmTagKey(0x0018, 0x9260) +#define DCM_ChemicalShiftMinimumIntegrationLimitInppm DcmTagKey(0x0018, 0x9295) +#define DCM_ChemicalShiftMaximumIntegrationLimitInppm DcmTagKey(0x0018, 0x9296) +#define DCM_WaterReferenceAcquisition DcmTagKey(0x0018, 0x9297) +#define DCM_EchoPeakPosition DcmTagKey(0x0018, 0x9298) +#define DCM_CTAcquisitionTypeSequence DcmTagKey(0x0018, 0x9301) +#define DCM_AcquisitionType DcmTagKey(0x0018, 0x9302) +#define DCM_TubeAngle DcmTagKey(0x0018, 0x9303) +#define DCM_CTAcquisitionDetailsSequence DcmTagKey(0x0018, 0x9304) +#define DCM_RevolutionTime DcmTagKey(0x0018, 0x9305) +#define DCM_SingleCollimationWidth DcmTagKey(0x0018, 0x9306) +#define DCM_TotalCollimationWidth DcmTagKey(0x0018, 0x9307) +#define DCM_CTTableDynamicsSequence DcmTagKey(0x0018, 0x9308) +#define DCM_TableSpeed DcmTagKey(0x0018, 0x9309) +#define DCM_TableFeedPerRotation DcmTagKey(0x0018, 0x9310) +#define DCM_SpiralPitchFactor DcmTagKey(0x0018, 0x9311) +#define DCM_CTGeometrySequence DcmTagKey(0x0018, 0x9312) +#define DCM_DataCollectionCenterPatient DcmTagKey(0x0018, 0x9313) +#define DCM_CTReconstructionSequence DcmTagKey(0x0018, 0x9314) +#define DCM_ReconstructionAlgorithm DcmTagKey(0x0018, 0x9315) +#define DCM_ConvolutionKernelGroup DcmTagKey(0x0018, 0x9316) +#define DCM_ReconstructionFieldOfView DcmTagKey(0x0018, 0x9317) +#define DCM_ReconstructionTargetCenterPatient DcmTagKey(0x0018, 0x9318) +#define DCM_ReconstructionAngle DcmTagKey(0x0018, 0x9319) +#define DCM_ImageFilter DcmTagKey(0x0018, 0x9320) +#define DCM_CTExposureSequence DcmTagKey(0x0018, 0x9321) +#define DCM_ReconstructionPixelSpacing DcmTagKey(0x0018, 0x9322) +#define DCM_ExposureModulationType DcmTagKey(0x0018, 0x9323) +#define DCM_EstimatedDoseSaving DcmTagKey(0x0018, 0x9324) +#define DCM_CTXRayDetailsSequence DcmTagKey(0x0018, 0x9325) +#define DCM_CTPositionSequence DcmTagKey(0x0018, 0x9326) +#define DCM_TablePosition DcmTagKey(0x0018, 0x9327) +#define DCM_ExposureTimeInms DcmTagKey(0x0018, 0x9328) +#define DCM_CTImageFrameTypeSequence DcmTagKey(0x0018, 0x9329) +#define DCM_XRayTubeCurrentInmA DcmTagKey(0x0018, 0x9330) +#define DCM_ExposureInmAs DcmTagKey(0x0018, 0x9332) +#define DCM_ConstantVolumeFlag DcmTagKey(0x0018, 0x9333) +#define DCM_FluoroscopyFlag DcmTagKey(0x0018, 0x9334) +#define DCM_DistanceSourceToDataCollectionCenter DcmTagKey(0x0018, 0x9335) +#define DCM_ContrastBolusAgentNumber DcmTagKey(0x0018, 0x9337) +#define DCM_ContrastBolusIngredientCodeSequence DcmTagKey(0x0018, 0x9338) +#define DCM_ContrastAdministrationProfileSequence DcmTagKey(0x0018, 0x9340) +#define DCM_ContrastBolusUsageSequence DcmTagKey(0x0018, 0x9341) +#define DCM_ContrastBolusAgentAdministered DcmTagKey(0x0018, 0x9342) +#define DCM_ContrastBolusAgentDetected DcmTagKey(0x0018, 0x9343) +#define DCM_ContrastBolusAgentPhase DcmTagKey(0x0018, 0x9344) +#define DCM_CTDIvol DcmTagKey(0x0018, 0x9345) +#define DCM_CTDIPhantomTypeCodeSequence DcmTagKey(0x0018, 0x9346) +#define DCM_CalciumScoringMassFactorPatient DcmTagKey(0x0018, 0x9351) +#define DCM_CalciumScoringMassFactorDevice DcmTagKey(0x0018, 0x9352) +#define DCM_EnergyWeightingFactor DcmTagKey(0x0018, 0x9353) +#define DCM_CTAdditionalXRaySourceSequence DcmTagKey(0x0018, 0x9360) +#define DCM_ProjectionPixelCalibrationSequence DcmTagKey(0x0018, 0x9401) +#define DCM_DistanceSourceToIsocenter DcmTagKey(0x0018, 0x9402) +#define DCM_DistanceObjectToTableTop DcmTagKey(0x0018, 0x9403) +#define DCM_ObjectPixelSpacingInCenterOfBeam DcmTagKey(0x0018, 0x9404) +#define DCM_PositionerPositionSequence DcmTagKey(0x0018, 0x9405) +#define DCM_TablePositionSequence DcmTagKey(0x0018, 0x9406) +#define DCM_CollimatorShapeSequence DcmTagKey(0x0018, 0x9407) +#define DCM_PlanesInAcquisition DcmTagKey(0x0018, 0x9410) +#define DCM_XAXRFFrameCharacteristicsSequence DcmTagKey(0x0018, 0x9412) +#define DCM_FrameAcquisitionSequence DcmTagKey(0x0018, 0x9417) +#define DCM_XRayReceptorType DcmTagKey(0x0018, 0x9420) +#define DCM_AcquisitionProtocolName DcmTagKey(0x0018, 0x9423) +#define DCM_AcquisitionProtocolDescription DcmTagKey(0x0018, 0x9424) +#define DCM_ContrastBolusIngredientOpaque DcmTagKey(0x0018, 0x9425) +#define DCM_DistanceReceptorPlaneToDetectorHousing DcmTagKey(0x0018, 0x9426) +#define DCM_IntensifierActiveShape DcmTagKey(0x0018, 0x9427) +#define DCM_IntensifierActiveDimensions DcmTagKey(0x0018, 0x9428) +#define DCM_PhysicalDetectorSize DcmTagKey(0x0018, 0x9429) +#define DCM_PositionOfIsocenterProjection DcmTagKey(0x0018, 0x9430) +#define DCM_FieldOfViewSequence DcmTagKey(0x0018, 0x9432) +#define DCM_FieldOfViewDescription DcmTagKey(0x0018, 0x9433) +#define DCM_ExposureControlSensingRegionsSequence DcmTagKey(0x0018, 0x9434) +#define DCM_ExposureControlSensingRegionShape DcmTagKey(0x0018, 0x9435) +#define DCM_ExposureControlSensingRegionLeftVerticalEdge DcmTagKey(0x0018, 0x9436) +#define DCM_ExposureControlSensingRegionRightVerticalEdge DcmTagKey(0x0018, 0x9437) +#define DCM_ExposureControlSensingRegionUpperHorizontalEdge DcmTagKey(0x0018, 0x9438) +#define DCM_ExposureControlSensingRegionLowerHorizontalEdge DcmTagKey(0x0018, 0x9439) +#define DCM_CenterOfCircularExposureControlSensingRegion DcmTagKey(0x0018, 0x9440) +#define DCM_RadiusOfCircularExposureControlSensingRegion DcmTagKey(0x0018, 0x9441) +#define DCM_VerticesOfThePolygonalExposureControlSensingRegion DcmTagKey(0x0018, 0x9442) +#define DCM_ColumnAngulationPatient DcmTagKey(0x0018, 0x9447) +#define DCM_BeamAngle DcmTagKey(0x0018, 0x9449) +#define DCM_FrameDetectorParametersSequence DcmTagKey(0x0018, 0x9451) +#define DCM_CalculatedAnatomyThickness DcmTagKey(0x0018, 0x9452) +#define DCM_CalibrationSequence DcmTagKey(0x0018, 0x9455) +#define DCM_ObjectThicknessSequence DcmTagKey(0x0018, 0x9456) +#define DCM_PlaneIdentification DcmTagKey(0x0018, 0x9457) +#define DCM_FieldOfViewDimensionsInFloat DcmTagKey(0x0018, 0x9461) +#define DCM_IsocenterReferenceSystemSequence DcmTagKey(0x0018, 0x9462) +#define DCM_PositionerIsocenterPrimaryAngle DcmTagKey(0x0018, 0x9463) +#define DCM_PositionerIsocenterSecondaryAngle DcmTagKey(0x0018, 0x9464) +#define DCM_PositionerIsocenterDetectorRotationAngle DcmTagKey(0x0018, 0x9465) +#define DCM_TableXPositionToIsocenter DcmTagKey(0x0018, 0x9466) +#define DCM_TableYPositionToIsocenter DcmTagKey(0x0018, 0x9467) +#define DCM_TableZPositionToIsocenter DcmTagKey(0x0018, 0x9468) +#define DCM_TableHorizontalRotationAngle DcmTagKey(0x0018, 0x9469) +#define DCM_TableHeadTiltAngle DcmTagKey(0x0018, 0x9470) +#define DCM_TableCradleTiltAngle DcmTagKey(0x0018, 0x9471) +#define DCM_FrameDisplayShutterSequence DcmTagKey(0x0018, 0x9472) +#define DCM_AcquiredImageAreaDoseProduct DcmTagKey(0x0018, 0x9473) +#define DCM_CArmPositionerTabletopRelationship DcmTagKey(0x0018, 0x9474) +#define DCM_XRayGeometrySequence DcmTagKey(0x0018, 0x9476) +#define DCM_IrradiationEventIdentificationSequence DcmTagKey(0x0018, 0x9477) +#define DCM_XRay3DFrameTypeSequence DcmTagKey(0x0018, 0x9504) +#define DCM_ContributingSourcesSequence DcmTagKey(0x0018, 0x9506) +#define DCM_XRay3DAcquisitionSequence DcmTagKey(0x0018, 0x9507) +#define DCM_PrimaryPositionerScanArc DcmTagKey(0x0018, 0x9508) +#define DCM_SecondaryPositionerScanArc DcmTagKey(0x0018, 0x9509) +#define DCM_PrimaryPositionerScanStartAngle DcmTagKey(0x0018, 0x9510) +#define DCM_SecondaryPositionerScanStartAngle DcmTagKey(0x0018, 0x9511) +#define DCM_PrimaryPositionerIncrement DcmTagKey(0x0018, 0x9514) +#define DCM_SecondaryPositionerIncrement DcmTagKey(0x0018, 0x9515) +#define DCM_StartAcquisitionDateTime DcmTagKey(0x0018, 0x9516) +#define DCM_EndAcquisitionDateTime DcmTagKey(0x0018, 0x9517) +#define DCM_PrimaryPositionerIncrementSign DcmTagKey(0x0018, 0x9518) +#define DCM_SecondaryPositionerIncrementSign DcmTagKey(0x0018, 0x9519) +#define DCM_ApplicationName DcmTagKey(0x0018, 0x9524) +#define DCM_ApplicationVersion DcmTagKey(0x0018, 0x9525) +#define DCM_ApplicationManufacturer DcmTagKey(0x0018, 0x9526) +#define DCM_AlgorithmType DcmTagKey(0x0018, 0x9527) +#define DCM_AlgorithmDescription DcmTagKey(0x0018, 0x9528) +#define DCM_XRay3DReconstructionSequence DcmTagKey(0x0018, 0x9530) +#define DCM_ReconstructionDescription DcmTagKey(0x0018, 0x9531) +#define DCM_PerProjectionAcquisitionSequence DcmTagKey(0x0018, 0x9538) +#define DCM_DetectorPositionSequence DcmTagKey(0x0018, 0x9541) +#define DCM_XRayAcquisitionDoseSequence DcmTagKey(0x0018, 0x9542) +#define DCM_XRaySourceIsocenterPrimaryAngle DcmTagKey(0x0018, 0x9543) +#define DCM_XRaySourceIsocenterSecondaryAngle DcmTagKey(0x0018, 0x9544) +#define DCM_BreastSupportIsocenterPrimaryAngle DcmTagKey(0x0018, 0x9545) +#define DCM_BreastSupportIsocenterSecondaryAngle DcmTagKey(0x0018, 0x9546) +#define DCM_BreastSupportXPositionToIsocenter DcmTagKey(0x0018, 0x9547) +#define DCM_BreastSupportYPositionToIsocenter DcmTagKey(0x0018, 0x9548) +#define DCM_BreastSupportZPositionToIsocenter DcmTagKey(0x0018, 0x9549) +#define DCM_DetectorIsocenterPrimaryAngle DcmTagKey(0x0018, 0x9550) +#define DCM_DetectorIsocenterSecondaryAngle DcmTagKey(0x0018, 0x9551) +#define DCM_DetectorXPositionToIsocenter DcmTagKey(0x0018, 0x9552) +#define DCM_DetectorYPositionToIsocenter DcmTagKey(0x0018, 0x9553) +#define DCM_DetectorZPositionToIsocenter DcmTagKey(0x0018, 0x9554) +#define DCM_XRayGridSequence DcmTagKey(0x0018, 0x9555) +#define DCM_XRayFilterSequence DcmTagKey(0x0018, 0x9556) +#define DCM_DetectorActiveAreaTLHCPosition DcmTagKey(0x0018, 0x9557) +#define DCM_DetectorActiveAreaOrientation DcmTagKey(0x0018, 0x9558) +#define DCM_PositionerPrimaryAngleDirection DcmTagKey(0x0018, 0x9559) +#define DCM_DiffusionBMatrixSequence DcmTagKey(0x0018, 0x9601) +#define DCM_DiffusionBValueXX DcmTagKey(0x0018, 0x9602) +#define DCM_DiffusionBValueXY DcmTagKey(0x0018, 0x9603) +#define DCM_DiffusionBValueXZ DcmTagKey(0x0018, 0x9604) +#define DCM_DiffusionBValueYY DcmTagKey(0x0018, 0x9605) +#define DCM_DiffusionBValueYZ DcmTagKey(0x0018, 0x9606) +#define DCM_DiffusionBValueZZ DcmTagKey(0x0018, 0x9607) +#define DCM_DecayCorrectionDateTime DcmTagKey(0x0018, 0x9701) +#define DCM_StartDensityThreshold DcmTagKey(0x0018, 0x9715) +#define DCM_StartRelativeDensityDifferenceThreshold DcmTagKey(0x0018, 0x9716) +#define DCM_StartCardiacTriggerCountThreshold DcmTagKey(0x0018, 0x9717) +#define DCM_StartRespiratoryTriggerCountThreshold DcmTagKey(0x0018, 0x9718) +#define DCM_TerminationCountsThreshold DcmTagKey(0x0018, 0x9719) +#define DCM_TerminationDensityThreshold DcmTagKey(0x0018, 0x9720) +#define DCM_TerminationRelativeDensityThreshold DcmTagKey(0x0018, 0x9721) +#define DCM_TerminationTimeThreshold DcmTagKey(0x0018, 0x9722) +#define DCM_TerminationCardiacTriggerCountThreshold DcmTagKey(0x0018, 0x9723) +#define DCM_TerminationRespiratoryTriggerCountThreshold DcmTagKey(0x0018, 0x9724) +#define DCM_DetectorGeometry DcmTagKey(0x0018, 0x9725) +#define DCM_TransverseDetectorSeparation DcmTagKey(0x0018, 0x9726) +#define DCM_AxialDetectorDimension DcmTagKey(0x0018, 0x9727) +#define DCM_RadiopharmaceuticalAgentNumber DcmTagKey(0x0018, 0x9729) +#define DCM_PETFrameAcquisitionSequence DcmTagKey(0x0018, 0x9732) +#define DCM_PETDetectorMotionDetailsSequence DcmTagKey(0x0018, 0x9733) +#define DCM_PETTableDynamicsSequence DcmTagKey(0x0018, 0x9734) +#define DCM_PETPositionSequence DcmTagKey(0x0018, 0x9735) +#define DCM_PETFrameCorrectionFactorsSequence DcmTagKey(0x0018, 0x9736) +#define DCM_RadiopharmaceuticalUsageSequence DcmTagKey(0x0018, 0x9737) +#define DCM_AttenuationCorrectionSource DcmTagKey(0x0018, 0x9738) +#define DCM_NumberOfIterations DcmTagKey(0x0018, 0x9739) +#define DCM_NumberOfSubsets DcmTagKey(0x0018, 0x9740) +#define DCM_PETReconstructionSequence DcmTagKey(0x0018, 0x9749) +#define DCM_PETFrameTypeSequence DcmTagKey(0x0018, 0x9751) +#define DCM_TimeOfFlightInformationUsed DcmTagKey(0x0018, 0x9755) +#define DCM_ReconstructionType DcmTagKey(0x0018, 0x9756) +#define DCM_DecayCorrected DcmTagKey(0x0018, 0x9758) +#define DCM_AttenuationCorrected DcmTagKey(0x0018, 0x9759) +#define DCM_ScatterCorrected DcmTagKey(0x0018, 0x9760) +#define DCM_DeadTimeCorrected DcmTagKey(0x0018, 0x9761) +#define DCM_GantryMotionCorrected DcmTagKey(0x0018, 0x9762) +#define DCM_PatientMotionCorrected DcmTagKey(0x0018, 0x9763) +#define DCM_CountLossNormalizationCorrected DcmTagKey(0x0018, 0x9764) +#define DCM_RandomsCorrected DcmTagKey(0x0018, 0x9765) +#define DCM_NonUniformRadialSamplingCorrected DcmTagKey(0x0018, 0x9766) +#define DCM_SensitivityCalibrated DcmTagKey(0x0018, 0x9767) +#define DCM_DetectorNormalizationCorrection DcmTagKey(0x0018, 0x9768) +#define DCM_IterativeReconstructionMethod DcmTagKey(0x0018, 0x9769) +#define DCM_AttenuationCorrectionTemporalRelationship DcmTagKey(0x0018, 0x9770) +#define DCM_PatientPhysiologicalStateSequence DcmTagKey(0x0018, 0x9771) +#define DCM_PatientPhysiologicalStateCodeSequence DcmTagKey(0x0018, 0x9772) +#define DCM_DepthsOfFocus DcmTagKey(0x0018, 0x9801) +#define DCM_ExcludedIntervalsSequence DcmTagKey(0x0018, 0x9803) +#define DCM_ExclusionStartDateTime DcmTagKey(0x0018, 0x9804) +#define DCM_ExclusionDuration DcmTagKey(0x0018, 0x9805) +#define DCM_USImageDescriptionSequence DcmTagKey(0x0018, 0x9806) +#define DCM_ImageDataTypeSequence DcmTagKey(0x0018, 0x9807) +#define DCM_DataType DcmTagKey(0x0018, 0x9808) +#define DCM_TransducerScanPatternCodeSequence DcmTagKey(0x0018, 0x9809) +#define DCM_AliasedDataType DcmTagKey(0x0018, 0x980b) +#define DCM_PositionMeasuringDeviceUsed DcmTagKey(0x0018, 0x980c) +#define DCM_TransducerGeometryCodeSequence DcmTagKey(0x0018, 0x980d) +#define DCM_TransducerBeamSteeringCodeSequence DcmTagKey(0x0018, 0x980e) +#define DCM_TransducerApplicationCodeSequence DcmTagKey(0x0018, 0x980f) +#define DCM_ZeroVelocityPixelValue DcmTagKey(0x0018, 0x9810) +#define DCM_ContributingEquipmentSequence DcmTagKey(0x0018, 0xa001) +#define DCM_ContributionDateTime DcmTagKey(0x0018, 0xa002) +#define DCM_ContributionDescription DcmTagKey(0x0018, 0xa003) +#define DCM_StudyInstanceUID DcmTagKey(0x0020, 0x000d) +#define DCM_SeriesInstanceUID DcmTagKey(0x0020, 0x000e) +#define DCM_StudyID DcmTagKey(0x0020, 0x0010) +#define DCM_SeriesNumber DcmTagKey(0x0020, 0x0011) +#define DCM_AcquisitionNumber DcmTagKey(0x0020, 0x0012) +#define DCM_InstanceNumber DcmTagKey(0x0020, 0x0013) +#define DCM_RETIRED_IsotopeNumber DcmTagKey(0x0020, 0x0014) +#define DCM_RETIRED_PhaseNumber DcmTagKey(0x0020, 0x0015) +#define DCM_RETIRED_IntervalNumber DcmTagKey(0x0020, 0x0016) +#define DCM_RETIRED_TimeSlotNumber DcmTagKey(0x0020, 0x0017) +#define DCM_RETIRED_AngleNumber DcmTagKey(0x0020, 0x0018) +#define DCM_ItemNumber DcmTagKey(0x0020, 0x0019) +#define DCM_PatientOrientation DcmTagKey(0x0020, 0x0020) +#define DCM_RETIRED_OverlayNumber DcmTagKey(0x0020, 0x0022) +#define DCM_RETIRED_CurveNumber DcmTagKey(0x0020, 0x0024) +#define DCM_RETIRED_LUTNumber DcmTagKey(0x0020, 0x0026) +#define DCM_RETIRED_ImagePosition DcmTagKey(0x0020, 0x0030) +#define DCM_ImagePositionPatient DcmTagKey(0x0020, 0x0032) +#define DCM_RETIRED_ImageOrientation DcmTagKey(0x0020, 0x0035) +#define DCM_ImageOrientationPatient DcmTagKey(0x0020, 0x0037) +#define DCM_RETIRED_Location DcmTagKey(0x0020, 0x0050) +#define DCM_FrameOfReferenceUID DcmTagKey(0x0020, 0x0052) +#define DCM_Laterality DcmTagKey(0x0020, 0x0060) +#define DCM_ImageLaterality DcmTagKey(0x0020, 0x0062) +#define DCM_RETIRED_ImageGeometryType DcmTagKey(0x0020, 0x0070) +#define DCM_RETIRED_MaskingImage DcmTagKey(0x0020, 0x0080) +#define DCM_RETIRED_ReportNumber DcmTagKey(0x0020, 0x00aa) +#define DCM_TemporalPositionIdentifier DcmTagKey(0x0020, 0x0100) +#define DCM_NumberOfTemporalPositions DcmTagKey(0x0020, 0x0105) +#define DCM_TemporalResolution DcmTagKey(0x0020, 0x0110) +#define DCM_SynchronizationFrameOfReferenceUID DcmTagKey(0x0020, 0x0200) +#define DCM_SOPInstanceUIDOfConcatenationSource DcmTagKey(0x0020, 0x0242) +#define DCM_RETIRED_SeriesInStudy DcmTagKey(0x0020, 0x1000) +#define DCM_RETIRED_AcquisitionsInSeries DcmTagKey(0x0020, 0x1001) +#define DCM_ImagesInAcquisition DcmTagKey(0x0020, 0x1002) +#define DCM_RETIRED_ImagesInSeries DcmTagKey(0x0020, 0x1003) +#define DCM_RETIRED_AcquisitionsInStudy DcmTagKey(0x0020, 0x1004) +#define DCM_RETIRED_ImagesInStudy DcmTagKey(0x0020, 0x1005) +#define DCM_RETIRED_Reference DcmTagKey(0x0020, 0x1020) +#define DCM_PositionReferenceIndicator DcmTagKey(0x0020, 0x1040) +#define DCM_SliceLocation DcmTagKey(0x0020, 0x1041) +#define DCM_RETIRED_OtherStudyNumbers DcmTagKey(0x0020, 0x1070) +#define DCM_NumberOfPatientRelatedStudies DcmTagKey(0x0020, 0x1200) +#define DCM_NumberOfPatientRelatedSeries DcmTagKey(0x0020, 0x1202) +#define DCM_NumberOfPatientRelatedInstances DcmTagKey(0x0020, 0x1204) +#define DCM_NumberOfStudyRelatedSeries DcmTagKey(0x0020, 0x1206) +#define DCM_NumberOfStudyRelatedInstances DcmTagKey(0x0020, 0x1208) +#define DCM_NumberOfSeriesRelatedInstances DcmTagKey(0x0020, 0x1209) +#define DCM_RETIRED_ModifyingDeviceID DcmTagKey(0x0020, 0x3401) +#define DCM_RETIRED_ModifiedImageID DcmTagKey(0x0020, 0x3402) +#define DCM_RETIRED_ModifiedImageDate DcmTagKey(0x0020, 0x3403) +#define DCM_RETIRED_ModifyingDeviceManufacturer DcmTagKey(0x0020, 0x3404) +#define DCM_RETIRED_ModifiedImageTime DcmTagKey(0x0020, 0x3405) +#define DCM_RETIRED_ModifiedImageDescription DcmTagKey(0x0020, 0x3406) +#define DCM_ImageComments DcmTagKey(0x0020, 0x4000) +#define DCM_RETIRED_OriginalImageIdentification DcmTagKey(0x0020, 0x5000) +#define DCM_RETIRED_OriginalImageIdentificationNomenclature DcmTagKey(0x0020, 0x5002) +#define DCM_StackID DcmTagKey(0x0020, 0x9056) +#define DCM_InStackPositionNumber DcmTagKey(0x0020, 0x9057) +#define DCM_FrameAnatomySequence DcmTagKey(0x0020, 0x9071) +#define DCM_FrameLaterality DcmTagKey(0x0020, 0x9072) +#define DCM_FrameContentSequence DcmTagKey(0x0020, 0x9111) +#define DCM_PlanePositionSequence DcmTagKey(0x0020, 0x9113) +#define DCM_PlaneOrientationSequence DcmTagKey(0x0020, 0x9116) +#define DCM_TemporalPositionIndex DcmTagKey(0x0020, 0x9128) +#define DCM_NominalCardiacTriggerDelayTime DcmTagKey(0x0020, 0x9153) +#define DCM_NominalCardiacTriggerTimePriorToRPeak DcmTagKey(0x0020, 0x9154) +#define DCM_ActualCardiacTriggerTimePriorToRPeak DcmTagKey(0x0020, 0x9155) +#define DCM_FrameAcquisitionNumber DcmTagKey(0x0020, 0x9156) +#define DCM_DimensionIndexValues DcmTagKey(0x0020, 0x9157) +#define DCM_FrameComments DcmTagKey(0x0020, 0x9158) +#define DCM_ConcatenationUID DcmTagKey(0x0020, 0x9161) +#define DCM_InConcatenationNumber DcmTagKey(0x0020, 0x9162) +#define DCM_InConcatenationTotalNumber DcmTagKey(0x0020, 0x9163) +#define DCM_DimensionOrganizationUID DcmTagKey(0x0020, 0x9164) +#define DCM_DimensionIndexPointer DcmTagKey(0x0020, 0x9165) +#define DCM_FunctionalGroupPointer DcmTagKey(0x0020, 0x9167) +#define DCM_UnassignedSharedConvertedAttributesSequence DcmTagKey(0x0020, 0x9170) +#define DCM_UnassignedPerFrameConvertedAttributesSequence DcmTagKey(0x0020, 0x9171) +#define DCM_ConversionSourceAttributesSequence DcmTagKey(0x0020, 0x9172) +#define DCM_DimensionIndexPrivateCreator DcmTagKey(0x0020, 0x9213) +#define DCM_DimensionOrganizationSequence DcmTagKey(0x0020, 0x9221) +#define DCM_DimensionIndexSequence DcmTagKey(0x0020, 0x9222) +#define DCM_ConcatenationFrameOffsetNumber DcmTagKey(0x0020, 0x9228) +#define DCM_FunctionalGroupPrivateCreator DcmTagKey(0x0020, 0x9238) +#define DCM_NominalPercentageOfCardiacPhase DcmTagKey(0x0020, 0x9241) +#define DCM_NominalPercentageOfRespiratoryPhase DcmTagKey(0x0020, 0x9245) +#define DCM_StartingRespiratoryAmplitude DcmTagKey(0x0020, 0x9246) +#define DCM_StartingRespiratoryPhase DcmTagKey(0x0020, 0x9247) +#define DCM_EndingRespiratoryAmplitude DcmTagKey(0x0020, 0x9248) +#define DCM_EndingRespiratoryPhase DcmTagKey(0x0020, 0x9249) +#define DCM_RespiratoryTriggerType DcmTagKey(0x0020, 0x9250) +#define DCM_RRIntervalTimeNominal DcmTagKey(0x0020, 0x9251) +#define DCM_ActualCardiacTriggerDelayTime DcmTagKey(0x0020, 0x9252) +#define DCM_RespiratorySynchronizationSequence DcmTagKey(0x0020, 0x9253) +#define DCM_RespiratoryIntervalTime DcmTagKey(0x0020, 0x9254) +#define DCM_NominalRespiratoryTriggerDelayTime DcmTagKey(0x0020, 0x9255) +#define DCM_RespiratoryTriggerDelayThreshold DcmTagKey(0x0020, 0x9256) +#define DCM_ActualRespiratoryTriggerDelayTime DcmTagKey(0x0020, 0x9257) +#define DCM_ImagePositionVolume DcmTagKey(0x0020, 0x9301) +#define DCM_ImageOrientationVolume DcmTagKey(0x0020, 0x9302) +#define DCM_UltrasoundAcquisitionGeometry DcmTagKey(0x0020, 0x9307) +#define DCM_ApexPosition DcmTagKey(0x0020, 0x9308) +#define DCM_VolumeToTransducerMappingMatrix DcmTagKey(0x0020, 0x9309) +#define DCM_VolumeToTableMappingMatrix DcmTagKey(0x0020, 0x930a) +#define DCM_VolumeToTransducerRelationship DcmTagKey(0x0020, 0x930b) +#define DCM_PatientFrameOfReferenceSource DcmTagKey(0x0020, 0x930c) +#define DCM_TemporalPositionTimeOffset DcmTagKey(0x0020, 0x930d) +#define DCM_PlanePositionVolumeSequence DcmTagKey(0x0020, 0x930e) +#define DCM_PlaneOrientationVolumeSequence DcmTagKey(0x0020, 0x930f) +#define DCM_TemporalPositionSequence DcmTagKey(0x0020, 0x9310) +#define DCM_DimensionOrganizationType DcmTagKey(0x0020, 0x9311) +#define DCM_VolumeFrameOfReferenceUID DcmTagKey(0x0020, 0x9312) +#define DCM_TableFrameOfReferenceUID DcmTagKey(0x0020, 0x9313) +#define DCM_DimensionDescriptionLabel DcmTagKey(0x0020, 0x9421) +#define DCM_PatientOrientationInFrameSequence DcmTagKey(0x0020, 0x9450) +#define DCM_FrameLabel DcmTagKey(0x0020, 0x9453) +#define DCM_AcquisitionIndex DcmTagKey(0x0020, 0x9518) +#define DCM_ContributingSOPInstancesReferenceSequence DcmTagKey(0x0020, 0x9529) +#define DCM_ReconstructionIndex DcmTagKey(0x0020, 0x9536) +#define DCM_LightPathFilterPassThroughWavelength DcmTagKey(0x0022, 0x0001) +#define DCM_LightPathFilterPassBand DcmTagKey(0x0022, 0x0002) +#define DCM_ImagePathFilterPassThroughWavelength DcmTagKey(0x0022, 0x0003) +#define DCM_ImagePathFilterPassBand DcmTagKey(0x0022, 0x0004) +#define DCM_PatientEyeMovementCommanded DcmTagKey(0x0022, 0x0005) +#define DCM_PatientEyeMovementCommandCodeSequence DcmTagKey(0x0022, 0x0006) +#define DCM_SphericalLensPower DcmTagKey(0x0022, 0x0007) +#define DCM_CylinderLensPower DcmTagKey(0x0022, 0x0008) +#define DCM_CylinderAxis DcmTagKey(0x0022, 0x0009) +#define DCM_EmmetropicMagnification DcmTagKey(0x0022, 0x000a) +#define DCM_IntraOcularPressure DcmTagKey(0x0022, 0x000b) +#define DCM_HorizontalFieldOfView DcmTagKey(0x0022, 0x000c) +#define DCM_PupilDilated DcmTagKey(0x0022, 0x000d) +#define DCM_DegreeOfDilation DcmTagKey(0x0022, 0x000e) +#define DCM_StereoBaselineAngle DcmTagKey(0x0022, 0x0010) +#define DCM_StereoBaselineDisplacement DcmTagKey(0x0022, 0x0011) +#define DCM_StereoHorizontalPixelOffset DcmTagKey(0x0022, 0x0012) +#define DCM_StereoVerticalPixelOffset DcmTagKey(0x0022, 0x0013) +#define DCM_StereoRotation DcmTagKey(0x0022, 0x0014) +#define DCM_AcquisitionDeviceTypeCodeSequence DcmTagKey(0x0022, 0x0015) +#define DCM_IlluminationTypeCodeSequence DcmTagKey(0x0022, 0x0016) +#define DCM_LightPathFilterTypeStackCodeSequence DcmTagKey(0x0022, 0x0017) +#define DCM_ImagePathFilterTypeStackCodeSequence DcmTagKey(0x0022, 0x0018) +#define DCM_LensesCodeSequence DcmTagKey(0x0022, 0x0019) +#define DCM_ChannelDescriptionCodeSequence DcmTagKey(0x0022, 0x001a) +#define DCM_RefractiveStateSequence DcmTagKey(0x0022, 0x001b) +#define DCM_MydriaticAgentCodeSequence DcmTagKey(0x0022, 0x001c) +#define DCM_RelativeImagePositionCodeSequence DcmTagKey(0x0022, 0x001d) +#define DCM_CameraAngleOfView DcmTagKey(0x0022, 0x001e) +#define DCM_StereoPairsSequence DcmTagKey(0x0022, 0x0020) +#define DCM_LeftImageSequence DcmTagKey(0x0022, 0x0021) +#define DCM_RightImageSequence DcmTagKey(0x0022, 0x0022) +#define DCM_StereoPairsPresent DcmTagKey(0x0022, 0x0028) +#define DCM_AxialLengthOfTheEye DcmTagKey(0x0022, 0x0030) +#define DCM_OphthalmicFrameLocationSequence DcmTagKey(0x0022, 0x0031) +#define DCM_ReferenceCoordinates DcmTagKey(0x0022, 0x0032) +#define DCM_DepthSpatialResolution DcmTagKey(0x0022, 0x0035) +#define DCM_MaximumDepthDistortion DcmTagKey(0x0022, 0x0036) +#define DCM_AlongScanSpatialResolution DcmTagKey(0x0022, 0x0037) +#define DCM_MaximumAlongScanDistortion DcmTagKey(0x0022, 0x0038) +#define DCM_OphthalmicImageOrientation DcmTagKey(0x0022, 0x0039) +#define DCM_DepthOfTransverseImage DcmTagKey(0x0022, 0x0041) +#define DCM_MydriaticAgentConcentrationUnitsSequence DcmTagKey(0x0022, 0x0042) +#define DCM_AcrossScanSpatialResolution DcmTagKey(0x0022, 0x0048) +#define DCM_MaximumAcrossScanDistortion DcmTagKey(0x0022, 0x0049) +#define DCM_MydriaticAgentConcentration DcmTagKey(0x0022, 0x004e) +#define DCM_IlluminationWaveLength DcmTagKey(0x0022, 0x0055) +#define DCM_IlluminationPower DcmTagKey(0x0022, 0x0056) +#define DCM_IlluminationBandwidth DcmTagKey(0x0022, 0x0057) +#define DCM_MydriaticAgentSequence DcmTagKey(0x0022, 0x0058) +#define DCM_OphthalmicAxialMeasurementsRightEyeSequence DcmTagKey(0x0022, 0x1007) +#define DCM_OphthalmicAxialMeasurementsLeftEyeSequence DcmTagKey(0x0022, 0x1008) +#define DCM_OphthalmicAxialMeasurementsDeviceType DcmTagKey(0x0022, 0x1009) +#define DCM_OphthalmicAxialLengthMeasurementsType DcmTagKey(0x0022, 0x1010) +#define DCM_OphthalmicAxialLengthSequence DcmTagKey(0x0022, 0x1012) +#define DCM_OphthalmicAxialLength DcmTagKey(0x0022, 0x1019) +#define DCM_LensStatusCodeSequence DcmTagKey(0x0022, 0x1024) +#define DCM_VitreousStatusCodeSequence DcmTagKey(0x0022, 0x1025) +#define DCM_IOLFormulaCodeSequence DcmTagKey(0x0022, 0x1028) +#define DCM_IOLFormulaDetail DcmTagKey(0x0022, 0x1029) +#define DCM_KeratometerIndex DcmTagKey(0x0022, 0x1033) +#define DCM_SourceOfOphthalmicAxialLengthCodeSequence DcmTagKey(0x0022, 0x1035) +#define DCM_TargetRefraction DcmTagKey(0x0022, 0x1037) +#define DCM_RefractiveProcedureOccurred DcmTagKey(0x0022, 0x1039) +#define DCM_RefractiveSurgeryTypeCodeSequence DcmTagKey(0x0022, 0x1040) +#define DCM_OphthalmicUltrasoundMethodCodeSequence DcmTagKey(0x0022, 0x1044) +#define DCM_OphthalmicAxialLengthMeasurementsSequence DcmTagKey(0x0022, 0x1050) +#define DCM_IOLPower DcmTagKey(0x0022, 0x1053) +#define DCM_PredictedRefractiveError DcmTagKey(0x0022, 0x1054) +#define DCM_OphthalmicAxialLengthVelocity DcmTagKey(0x0022, 0x1059) +#define DCM_LensStatusDescription DcmTagKey(0x0022, 0x1065) +#define DCM_VitreousStatusDescription DcmTagKey(0x0022, 0x1066) +#define DCM_IOLPowerSequence DcmTagKey(0x0022, 0x1090) +#define DCM_LensConstantSequence DcmTagKey(0x0022, 0x1092) +#define DCM_IOLManufacturer DcmTagKey(0x0022, 0x1093) +#define DCM_RETIRED_LensConstantDescription DcmTagKey(0x0022, 0x1094) +#define DCM_ImplantName DcmTagKey(0x0022, 0x1095) +#define DCM_KeratometryMeasurementTypeCodeSequence DcmTagKey(0x0022, 0x1096) +#define DCM_ImplantPartNumber DcmTagKey(0x0022, 0x1097) +#define DCM_ReferencedOphthalmicAxialMeasurementsSequence DcmTagKey(0x0022, 0x1100) +#define DCM_OphthalmicAxialLengthMeasurementsSegmentNameCodeSequence DcmTagKey(0x0022, 0x1101) +#define DCM_RefractiveErrorBeforeRefractiveSurgeryCodeSequence DcmTagKey(0x0022, 0x1103) +#define DCM_IOLPowerForExactEmmetropia DcmTagKey(0x0022, 0x1121) +#define DCM_IOLPowerForExactTargetRefraction DcmTagKey(0x0022, 0x1122) +#define DCM_AnteriorChamberDepthDefinitionCodeSequence DcmTagKey(0x0022, 0x1125) +#define DCM_LensThicknessSequence DcmTagKey(0x0022, 0x1127) +#define DCM_AnteriorChamberDepthSequence DcmTagKey(0x0022, 0x1128) +#define DCM_LensThickness DcmTagKey(0x0022, 0x1130) +#define DCM_AnteriorChamberDepth DcmTagKey(0x0022, 0x1131) +#define DCM_SourceOfLensThicknessDataCodeSequence DcmTagKey(0x0022, 0x1132) +#define DCM_SourceOfAnteriorChamberDepthDataCodeSequence DcmTagKey(0x0022, 0x1133) +#define DCM_SourceOfRefractiveMeasurementsSequence DcmTagKey(0x0022, 0x1134) +#define DCM_SourceOfRefractiveMeasurementsCodeSequence DcmTagKey(0x0022, 0x1135) +#define DCM_OphthalmicAxialLengthMeasurementModified DcmTagKey(0x0022, 0x1140) +#define DCM_OphthalmicAxialLengthDataSourceCodeSequence DcmTagKey(0x0022, 0x1150) +#define DCM_RETIRED_OphthalmicAxialLengthAcquisitionMethodCodeSequence DcmTagKey(0x0022, 0x1153) +#define DCM_SignalToNoiseRatio DcmTagKey(0x0022, 0x1155) +#define DCM_OphthalmicAxialLengthDataSourceDescription DcmTagKey(0x0022, 0x1159) +#define DCM_OphthalmicAxialLengthMeasurementsTotalLengthSequence DcmTagKey(0x0022, 0x1210) +#define DCM_OphthalmicAxialLengthMeasurementsSegmentalLengthSequence DcmTagKey(0x0022, 0x1211) +#define DCM_OphthalmicAxialLengthMeasurementsLengthSummationSequence DcmTagKey(0x0022, 0x1212) +#define DCM_UltrasoundOphthalmicAxialLengthMeasurementsSequence DcmTagKey(0x0022, 0x1220) +#define DCM_OpticalOphthalmicAxialLengthMeasurementsSequence DcmTagKey(0x0022, 0x1225) +#define DCM_UltrasoundSelectedOphthalmicAxialLengthSequence DcmTagKey(0x0022, 0x1230) +#define DCM_OphthalmicAxialLengthSelectionMethodCodeSequence DcmTagKey(0x0022, 0x1250) +#define DCM_OpticalSelectedOphthalmicAxialLengthSequence DcmTagKey(0x0022, 0x1255) +#define DCM_SelectedSegmentalOphthalmicAxialLengthSequence DcmTagKey(0x0022, 0x1257) +#define DCM_SelectedTotalOphthalmicAxialLengthSequence DcmTagKey(0x0022, 0x1260) +#define DCM_OphthalmicAxialLengthQualityMetricSequence DcmTagKey(0x0022, 0x1262) +#define DCM_RETIRED_OphthalmicAxialLengthQualityMetricTypeCodeSequence DcmTagKey(0x0022, 0x1265) +#define DCM_RETIRED_OphthalmicAxialLengthQualityMetricTypeDescription DcmTagKey(0x0022, 0x1273) +#define DCM_IntraocularLensCalculationsRightEyeSequence DcmTagKey(0x0022, 0x1300) +#define DCM_IntraocularLensCalculationsLeftEyeSequence DcmTagKey(0x0022, 0x1310) +#define DCM_ReferencedOphthalmicAxialLengthMeasurementQCImageSequence DcmTagKey(0x0022, 0x1330) +#define DCM_OphthalmicMappingDeviceType DcmTagKey(0x0022, 0x1415) +#define DCM_AcquisitionMethodCodeSequence DcmTagKey(0x0022, 0x1420) +#define DCM_AcquisitionMethodAlgorithmSequence DcmTagKey(0x0022, 0x1423) +#define DCM_OphthalmicThicknessMapTypeCodeSequence DcmTagKey(0x0022, 0x1436) +#define DCM_OphthalmicThicknessMappingNormalsSequence DcmTagKey(0x0022, 0x1443) +#define DCM_RetinalThicknessDefinitionCodeSequence DcmTagKey(0x0022, 0x1445) +#define DCM_PixelValueMappingToCodedConceptSequence DcmTagKey(0x0022, 0x1450) +#define DCM_MappedPixelValue DcmTagKey(0x0022, 0x1452) +#define DCM_PixelValueMappingExplanation DcmTagKey(0x0022, 0x1454) +#define DCM_OphthalmicThicknessMapQualityThresholdSequence DcmTagKey(0x0022, 0x1458) +#define DCM_OphthalmicThicknessMapThresholdQualityRating DcmTagKey(0x0022, 0x1460) +#define DCM_AnatomicStructureReferencePoint DcmTagKey(0x0022, 0x1463) +#define DCM_RegistrationToLocalizerSequence DcmTagKey(0x0022, 0x1465) +#define DCM_RegisteredLocalizerUnits DcmTagKey(0x0022, 0x1466) +#define DCM_RegisteredLocalizerTopLeftHandCorner DcmTagKey(0x0022, 0x1467) +#define DCM_RegisteredLocalizerBottomRightHandCorner DcmTagKey(0x0022, 0x1468) +#define DCM_OphthalmicThicknessMapQualityRatingSequence DcmTagKey(0x0022, 0x1470) +#define DCM_RelevantOPTAttributesSequence DcmTagKey(0x0022, 0x1472) +#define DCM_TransformationMethodCodeSequence DcmTagKey(0x0022, 0x1512) +#define DCM_TransformationAlgorithmSequence DcmTagKey(0x0022, 0x1513) +#define DCM_OphthalmicAxialLengthMethod DcmTagKey(0x0022, 0x1515) +#define DCM_OphthalmicFOV DcmTagKey(0x0022, 0x1517) +#define DCM_TwoDimensionalToThreeDimensionalMapSequence DcmTagKey(0x0022, 0x1518) +#define DCM_WideFieldOphthalmicPhotographyQualityRatingSequence DcmTagKey(0x0022, 0x1525) +#define DCM_WideFieldOphthalmicPhotographyQualityThresholdSequence DcmTagKey(0x0022, 0x1526) +#define DCM_WideFieldOphthalmicPhotographyThresholdQualityRating DcmTagKey(0x0022, 0x1527) +#define DCM_XCoordinatesCenterPixelViewAngle DcmTagKey(0x0022, 0x1528) +#define DCM_YCoordinatesCenterPixelViewAngle DcmTagKey(0x0022, 0x1529) +#define DCM_NumberOfMapPoints DcmTagKey(0x0022, 0x1530) +#define DCM_TwoDimensionalToThreeDimensionalMapData DcmTagKey(0x0022, 0x1531) +#define DCM_VisualFieldHorizontalExtent DcmTagKey(0x0024, 0x0010) +#define DCM_VisualFieldVerticalExtent DcmTagKey(0x0024, 0x0011) +#define DCM_VisualFieldShape DcmTagKey(0x0024, 0x0012) +#define DCM_ScreeningTestModeCodeSequence DcmTagKey(0x0024, 0x0016) +#define DCM_MaximumStimulusLuminance DcmTagKey(0x0024, 0x0018) +#define DCM_BackgroundLuminance DcmTagKey(0x0024, 0x0020) +#define DCM_StimulusColorCodeSequence DcmTagKey(0x0024, 0x0021) +#define DCM_BackgroundIlluminationColorCodeSequence DcmTagKey(0x0024, 0x0024) +#define DCM_StimulusArea DcmTagKey(0x0024, 0x0025) +#define DCM_StimulusPresentationTime DcmTagKey(0x0024, 0x0028) +#define DCM_FixationSequence DcmTagKey(0x0024, 0x0032) +#define DCM_FixationMonitoringCodeSequence DcmTagKey(0x0024, 0x0033) +#define DCM_VisualFieldCatchTrialSequence DcmTagKey(0x0024, 0x0034) +#define DCM_FixationCheckedQuantity DcmTagKey(0x0024, 0x0035) +#define DCM_PatientNotProperlyFixatedQuantity DcmTagKey(0x0024, 0x0036) +#define DCM_PresentedVisualStimuliDataFlag DcmTagKey(0x0024, 0x0037) +#define DCM_NumberOfVisualStimuli DcmTagKey(0x0024, 0x0038) +#define DCM_ExcessiveFixationLossesDataFlag DcmTagKey(0x0024, 0x0039) +#define DCM_ExcessiveFixationLosses DcmTagKey(0x0024, 0x0040) +#define DCM_StimuliRetestingQuantity DcmTagKey(0x0024, 0x0042) +#define DCM_CommentsOnPatientPerformanceOfVisualField DcmTagKey(0x0024, 0x0044) +#define DCM_FalseNegativesEstimateFlag DcmTagKey(0x0024, 0x0045) +#define DCM_FalseNegativesEstimate DcmTagKey(0x0024, 0x0046) +#define DCM_NegativeCatchTrialsQuantity DcmTagKey(0x0024, 0x0048) +#define DCM_FalseNegativesQuantity DcmTagKey(0x0024, 0x0050) +#define DCM_ExcessiveFalseNegativesDataFlag DcmTagKey(0x0024, 0x0051) +#define DCM_ExcessiveFalseNegatives DcmTagKey(0x0024, 0x0052) +#define DCM_FalsePositivesEstimateFlag DcmTagKey(0x0024, 0x0053) +#define DCM_FalsePositivesEstimate DcmTagKey(0x0024, 0x0054) +#define DCM_CatchTrialsDataFlag DcmTagKey(0x0024, 0x0055) +#define DCM_PositiveCatchTrialsQuantity DcmTagKey(0x0024, 0x0056) +#define DCM_TestPointNormalsDataFlag DcmTagKey(0x0024, 0x0057) +#define DCM_TestPointNormalsSequence DcmTagKey(0x0024, 0x0058) +#define DCM_GlobalDeviationProbabilityNormalsFlag DcmTagKey(0x0024, 0x0059) +#define DCM_FalsePositivesQuantity DcmTagKey(0x0024, 0x0060) +#define DCM_ExcessiveFalsePositivesDataFlag DcmTagKey(0x0024, 0x0061) +#define DCM_ExcessiveFalsePositives DcmTagKey(0x0024, 0x0062) +#define DCM_VisualFieldTestNormalsFlag DcmTagKey(0x0024, 0x0063) +#define DCM_ResultsNormalsSequence DcmTagKey(0x0024, 0x0064) +#define DCM_AgeCorrectedSensitivityDeviationAlgorithmSequence DcmTagKey(0x0024, 0x0065) +#define DCM_GlobalDeviationFromNormal DcmTagKey(0x0024, 0x0066) +#define DCM_GeneralizedDefectSensitivityDeviationAlgorithmSequence DcmTagKey(0x0024, 0x0067) +#define DCM_LocalizedDeviationFromNormal DcmTagKey(0x0024, 0x0068) +#define DCM_PatientReliabilityIndicator DcmTagKey(0x0024, 0x0069) +#define DCM_VisualFieldMeanSensitivity DcmTagKey(0x0024, 0x0070) +#define DCM_GlobalDeviationProbability DcmTagKey(0x0024, 0x0071) +#define DCM_LocalDeviationProbabilityNormalsFlag DcmTagKey(0x0024, 0x0072) +#define DCM_LocalizedDeviationProbability DcmTagKey(0x0024, 0x0073) +#define DCM_ShortTermFluctuationCalculated DcmTagKey(0x0024, 0x0074) +#define DCM_ShortTermFluctuation DcmTagKey(0x0024, 0x0075) +#define DCM_ShortTermFluctuationProbabilityCalculated DcmTagKey(0x0024, 0x0076) +#define DCM_ShortTermFluctuationProbability DcmTagKey(0x0024, 0x0077) +#define DCM_CorrectedLocalizedDeviationFromNormalCalculated DcmTagKey(0x0024, 0x0078) +#define DCM_CorrectedLocalizedDeviationFromNormal DcmTagKey(0x0024, 0x0079) +#define DCM_CorrectedLocalizedDeviationFromNormalProbabilityCalculated DcmTagKey(0x0024, 0x0080) +#define DCM_CorrectedLocalizedDeviationFromNormalProbability DcmTagKey(0x0024, 0x0081) +#define DCM_GlobalDeviationProbabilitySequence DcmTagKey(0x0024, 0x0083) +#define DCM_LocalizedDeviationProbabilitySequence DcmTagKey(0x0024, 0x0085) +#define DCM_FovealSensitivityMeasured DcmTagKey(0x0024, 0x0086) +#define DCM_FovealSensitivity DcmTagKey(0x0024, 0x0087) +#define DCM_VisualFieldTestDuration DcmTagKey(0x0024, 0x0088) +#define DCM_VisualFieldTestPointSequence DcmTagKey(0x0024, 0x0089) +#define DCM_VisualFieldTestPointXCoordinate DcmTagKey(0x0024, 0x0090) +#define DCM_VisualFieldTestPointYCoordinate DcmTagKey(0x0024, 0x0091) +#define DCM_AgeCorrectedSensitivityDeviationValue DcmTagKey(0x0024, 0x0092) +#define DCM_StimulusResults DcmTagKey(0x0024, 0x0093) +#define DCM_SensitivityValue DcmTagKey(0x0024, 0x0094) +#define DCM_RetestStimulusSeen DcmTagKey(0x0024, 0x0095) +#define DCM_RetestSensitivityValue DcmTagKey(0x0024, 0x0096) +#define DCM_VisualFieldTestPointNormalsSequence DcmTagKey(0x0024, 0x0097) +#define DCM_QuantifiedDefect DcmTagKey(0x0024, 0x0098) +#define DCM_AgeCorrectedSensitivityDeviationProbabilityValue DcmTagKey(0x0024, 0x0100) +#define DCM_GeneralizedDefectCorrectedSensitivityDeviationFlag DcmTagKey(0x0024, 0x0102) +#define DCM_GeneralizedDefectCorrectedSensitivityDeviationValue DcmTagKey(0x0024, 0x0103) +#define DCM_GeneralizedDefectCorrectedSensitivityDeviationProbabilityValue DcmTagKey(0x0024, 0x0104) +#define DCM_MinimumSensitivityValue DcmTagKey(0x0024, 0x0105) +#define DCM_BlindSpotLocalized DcmTagKey(0x0024, 0x0106) +#define DCM_BlindSpotXCoordinate DcmTagKey(0x0024, 0x0107) +#define DCM_BlindSpotYCoordinate DcmTagKey(0x0024, 0x0108) +#define DCM_VisualAcuityMeasurementSequence DcmTagKey(0x0024, 0x0110) +#define DCM_RefractiveParametersUsedOnPatientSequence DcmTagKey(0x0024, 0x0112) +#define DCM_MeasurementLaterality DcmTagKey(0x0024, 0x0113) +#define DCM_OphthalmicPatientClinicalInformationLeftEyeSequence DcmTagKey(0x0024, 0x0114) +#define DCM_OphthalmicPatientClinicalInformationRightEyeSequence DcmTagKey(0x0024, 0x0115) +#define DCM_FovealPointNormativeDataFlag DcmTagKey(0x0024, 0x0117) +#define DCM_FovealPointProbabilityValue DcmTagKey(0x0024, 0x0118) +#define DCM_ScreeningBaselineMeasured DcmTagKey(0x0024, 0x0120) +#define DCM_ScreeningBaselineMeasuredSequence DcmTagKey(0x0024, 0x0122) +#define DCM_ScreeningBaselineType DcmTagKey(0x0024, 0x0124) +#define DCM_ScreeningBaselineValue DcmTagKey(0x0024, 0x0126) +#define DCM_AlgorithmSource DcmTagKey(0x0024, 0x0202) +#define DCM_DataSetName DcmTagKey(0x0024, 0x0306) +#define DCM_DataSetVersion DcmTagKey(0x0024, 0x0307) +#define DCM_DataSetSource DcmTagKey(0x0024, 0x0308) +#define DCM_DataSetDescription DcmTagKey(0x0024, 0x0309) +#define DCM_VisualFieldTestReliabilityGlobalIndexSequence DcmTagKey(0x0024, 0x0317) +#define DCM_VisualFieldGlobalResultsIndexSequence DcmTagKey(0x0024, 0x0320) +#define DCM_DataObservationSequence DcmTagKey(0x0024, 0x0325) +#define DCM_IndexNormalsFlag DcmTagKey(0x0024, 0x0338) +#define DCM_IndexProbability DcmTagKey(0x0024, 0x0341) +#define DCM_IndexProbabilitySequence DcmTagKey(0x0024, 0x0344) +#define DCM_SamplesPerPixel DcmTagKey(0x0028, 0x0002) +#define DCM_SamplesPerPixelUsed DcmTagKey(0x0028, 0x0003) +#define DCM_PhotometricInterpretation DcmTagKey(0x0028, 0x0004) +#define DCM_RETIRED_ImageDimensions DcmTagKey(0x0028, 0x0005) +#define DCM_PlanarConfiguration DcmTagKey(0x0028, 0x0006) +#define DCM_NumberOfFrames DcmTagKey(0x0028, 0x0008) +#define DCM_FrameIncrementPointer DcmTagKey(0x0028, 0x0009) +#define DCM_FrameDimensionPointer DcmTagKey(0x0028, 0x000a) +#define DCM_Rows DcmTagKey(0x0028, 0x0010) +#define DCM_Columns DcmTagKey(0x0028, 0x0011) +#define DCM_RETIRED_Planes DcmTagKey(0x0028, 0x0012) +#define DCM_UltrasoundColorDataPresent DcmTagKey(0x0028, 0x0014) +#define DCM_PixelSpacing DcmTagKey(0x0028, 0x0030) +#define DCM_ZoomFactor DcmTagKey(0x0028, 0x0031) +#define DCM_ZoomCenter DcmTagKey(0x0028, 0x0032) +#define DCM_PixelAspectRatio DcmTagKey(0x0028, 0x0034) +#define DCM_RETIRED_ImageFormat DcmTagKey(0x0028, 0x0040) +#define DCM_RETIRED_ManipulatedImage DcmTagKey(0x0028, 0x0050) +#define DCM_CorrectedImage DcmTagKey(0x0028, 0x0051) +#define DCM_RETIRED_CompressionRecognitionCode DcmTagKey(0x0028, 0x005f) +#define DCM_RETIRED_CompressionCode DcmTagKey(0x0028, 0x0060) +#define DCM_RETIRED_CompressionOriginator DcmTagKey(0x0028, 0x0061) +#define DCM_RETIRED_CompressionLabel DcmTagKey(0x0028, 0x0062) +#define DCM_RETIRED_CompressionDescription DcmTagKey(0x0028, 0x0063) +#define DCM_RETIRED_CompressionSequence DcmTagKey(0x0028, 0x0065) +#define DCM_RETIRED_CompressionStepPointers DcmTagKey(0x0028, 0x0066) +#define DCM_RETIRED_RepeatInterval DcmTagKey(0x0028, 0x0068) +#define DCM_RETIRED_BitsGrouped DcmTagKey(0x0028, 0x0069) +#define DCM_RETIRED_PerimeterTable DcmTagKey(0x0028, 0x0070) +#define DCM_RETIRED_PerimeterValue DcmTagKey(0x0028, 0x0071) +#define DCM_RETIRED_PredictorRows DcmTagKey(0x0028, 0x0080) +#define DCM_RETIRED_PredictorColumns DcmTagKey(0x0028, 0x0081) +#define DCM_RETIRED_PredictorConstants DcmTagKey(0x0028, 0x0082) +#define DCM_RETIRED_BlockedPixels DcmTagKey(0x0028, 0x0090) +#define DCM_RETIRED_BlockRows DcmTagKey(0x0028, 0x0091) +#define DCM_RETIRED_BlockColumns DcmTagKey(0x0028, 0x0092) +#define DCM_RETIRED_RowOverlap DcmTagKey(0x0028, 0x0093) +#define DCM_RETIRED_ColumnOverlap DcmTagKey(0x0028, 0x0094) +#define DCM_BitsAllocated DcmTagKey(0x0028, 0x0100) +#define DCM_BitsStored DcmTagKey(0x0028, 0x0101) +#define DCM_HighBit DcmTagKey(0x0028, 0x0102) +#define DCM_PixelRepresentation DcmTagKey(0x0028, 0x0103) +#define DCM_RETIRED_SmallestValidPixelValue DcmTagKey(0x0028, 0x0104) +#define DCM_RETIRED_LargestValidPixelValue DcmTagKey(0x0028, 0x0105) +#define DCM_SmallestImagePixelValue DcmTagKey(0x0028, 0x0106) +#define DCM_LargestImagePixelValue DcmTagKey(0x0028, 0x0107) +#define DCM_SmallestPixelValueInSeries DcmTagKey(0x0028, 0x0108) +#define DCM_LargestPixelValueInSeries DcmTagKey(0x0028, 0x0109) +#define DCM_RETIRED_SmallestImagePixelValueInPlane DcmTagKey(0x0028, 0x0110) +#define DCM_RETIRED_LargestImagePixelValueInPlane DcmTagKey(0x0028, 0x0111) +#define DCM_PixelPaddingValue DcmTagKey(0x0028, 0x0120) +#define DCM_PixelPaddingRangeLimit DcmTagKey(0x0028, 0x0121) +#define DCM_FloatPixelPaddingValue DcmTagKey(0x0028, 0x0122) +#define DCM_DoubleFloatPixelPaddingValue DcmTagKey(0x0028, 0x0123) +#define DCM_FloatPixelPaddingRangeLimit DcmTagKey(0x0028, 0x0124) +#define DCM_DoubleFloatPixelPaddingRangeLimit DcmTagKey(0x0028, 0x0125) +#define DCM_RETIRED_ImageLocation DcmTagKey(0x0028, 0x0200) +#define DCM_QualityControlImage DcmTagKey(0x0028, 0x0300) +#define DCM_BurnedInAnnotation DcmTagKey(0x0028, 0x0301) +#define DCM_RecognizableVisualFeatures DcmTagKey(0x0028, 0x0302) +#define DCM_LongitudinalTemporalInformationModified DcmTagKey(0x0028, 0x0303) +#define DCM_ReferencedColorPaletteInstanceUID DcmTagKey(0x0028, 0x0304) +#define DCM_RETIRED_TransformLabel DcmTagKey(0x0028, 0x0400) +#define DCM_RETIRED_TransformVersionNumber DcmTagKey(0x0028, 0x0401) +#define DCM_RETIRED_NumberOfTransformSteps DcmTagKey(0x0028, 0x0402) +#define DCM_RETIRED_SequenceOfCompressedData DcmTagKey(0x0028, 0x0403) +#define DCM_RETIRED_DetailsOfCoefficients DcmTagKey(0x0028, 0x0404) +#define DCM_RETIRED_RowsForNthOrderCoefficients DcmTagKey(0x0028, 0x0410) +#define DCM_RETIRED_ColumnsForNthOrderCoefficients DcmTagKey(0x0028, 0x0411) +#define DCM_RETIRED_CoefficientCoding DcmTagKey(0x0028, 0x0412) +#define DCM_RETIRED_CoefficientCodingPointers DcmTagKey(0x0028, 0x0413) +#define DCM_RETIRED_DCTLabel DcmTagKey(0x0028, 0x0700) +#define DCM_RETIRED_DataBlockDescription DcmTagKey(0x0028, 0x0701) +#define DCM_RETIRED_DataBlock DcmTagKey(0x0028, 0x0702) +#define DCM_RETIRED_NormalizationFactorFormat DcmTagKey(0x0028, 0x0710) +#define DCM_RETIRED_ZonalMapNumberFormat DcmTagKey(0x0028, 0x0720) +#define DCM_RETIRED_ZonalMapLocation DcmTagKey(0x0028, 0x0721) +#define DCM_RETIRED_ZonalMapFormat DcmTagKey(0x0028, 0x0722) +#define DCM_RETIRED_AdaptiveMapFormat DcmTagKey(0x0028, 0x0730) +#define DCM_RETIRED_CodeNumberFormat DcmTagKey(0x0028, 0x0740) +#define DCM_RETIRED_CodeLabel DcmTagKey(0x0028, 0x0800) +#define DCM_RETIRED_NumberOfTables DcmTagKey(0x0028, 0x0802) +#define DCM_RETIRED_CodeTableLocation DcmTagKey(0x0028, 0x0803) +#define DCM_RETIRED_BitsForCodeWord DcmTagKey(0x0028, 0x0804) +#define DCM_RETIRED_ImageDataLocation DcmTagKey(0x0028, 0x0808) +#define DCM_PixelSpacingCalibrationType DcmTagKey(0x0028, 0x0a02) +#define DCM_PixelSpacingCalibrationDescription DcmTagKey(0x0028, 0x0a04) +#define DCM_PixelIntensityRelationship DcmTagKey(0x0028, 0x1040) +#define DCM_PixelIntensityRelationshipSign DcmTagKey(0x0028, 0x1041) +#define DCM_WindowCenter DcmTagKey(0x0028, 0x1050) +#define DCM_WindowWidth DcmTagKey(0x0028, 0x1051) +#define DCM_RescaleIntercept DcmTagKey(0x0028, 0x1052) +#define DCM_RescaleSlope DcmTagKey(0x0028, 0x1053) +#define DCM_RescaleType DcmTagKey(0x0028, 0x1054) +#define DCM_WindowCenterWidthExplanation DcmTagKey(0x0028, 0x1055) +#define DCM_VOILUTFunction DcmTagKey(0x0028, 0x1056) +#define DCM_RETIRED_GrayScale DcmTagKey(0x0028, 0x1080) +#define DCM_RecommendedViewingMode DcmTagKey(0x0028, 0x1090) +#define DCM_RETIRED_GrayLookupTableDescriptor DcmTagKey(0x0028, 0x1100) +#define DCM_RedPaletteColorLookupTableDescriptor DcmTagKey(0x0028, 0x1101) +#define DCM_GreenPaletteColorLookupTableDescriptor DcmTagKey(0x0028, 0x1102) +#define DCM_BluePaletteColorLookupTableDescriptor DcmTagKey(0x0028, 0x1103) +#define DCM_AlphaPaletteColorLookupTableDescriptor DcmTagKey(0x0028, 0x1104) +#define DCM_RETIRED_LargeRedPaletteColorLookupTableDescriptor DcmTagKey(0x0028, 0x1111) +#define DCM_RETIRED_LargeGreenPaletteColorLookupTableDescriptor DcmTagKey(0x0028, 0x1112) +#define DCM_RETIRED_LargeBluePaletteColorLookupTableDescriptor DcmTagKey(0x0028, 0x1113) +#define DCM_PaletteColorLookupTableUID DcmTagKey(0x0028, 0x1199) +#define DCM_RETIRED_GrayLookupTableData DcmTagKey(0x0028, 0x1200) +#define DCM_RedPaletteColorLookupTableData DcmTagKey(0x0028, 0x1201) +#define DCM_GreenPaletteColorLookupTableData DcmTagKey(0x0028, 0x1202) +#define DCM_BluePaletteColorLookupTableData DcmTagKey(0x0028, 0x1203) +#define DCM_AlphaPaletteColorLookupTableData DcmTagKey(0x0028, 0x1204) +#define DCM_RETIRED_LargeRedPaletteColorLookupTableData DcmTagKey(0x0028, 0x1211) +#define DCM_RETIRED_LargeGreenPaletteColorLookupTableData DcmTagKey(0x0028, 0x1212) +#define DCM_RETIRED_LargeBluePaletteColorLookupTableData DcmTagKey(0x0028, 0x1213) +#define DCM_RETIRED_LargePaletteColorLookupTableUID DcmTagKey(0x0028, 0x1214) +#define DCM_SegmentedRedPaletteColorLookupTableData DcmTagKey(0x0028, 0x1221) +#define DCM_SegmentedGreenPaletteColorLookupTableData DcmTagKey(0x0028, 0x1222) +#define DCM_SegmentedBluePaletteColorLookupTableData DcmTagKey(0x0028, 0x1223) +#define DCM_SegmentedAlphaPaletteColorLookupTableData DcmTagKey(0x0028, 0x1224) +#define DCM_BreastImplantPresent DcmTagKey(0x0028, 0x1300) +#define DCM_PartialView DcmTagKey(0x0028, 0x1350) +#define DCM_PartialViewDescription DcmTagKey(0x0028, 0x1351) +#define DCM_PartialViewCodeSequence DcmTagKey(0x0028, 0x1352) +#define DCM_SpatialLocationsPreserved DcmTagKey(0x0028, 0x135a) +#define DCM_DataFrameAssignmentSequence DcmTagKey(0x0028, 0x1401) +#define DCM_DataPathAssignment DcmTagKey(0x0028, 0x1402) +#define DCM_BitsMappedToColorLookupTable DcmTagKey(0x0028, 0x1403) +#define DCM_BlendingLUT1Sequence DcmTagKey(0x0028, 0x1404) +#define DCM_BlendingLUT1TransferFunction DcmTagKey(0x0028, 0x1405) +#define DCM_BlendingWeightConstant DcmTagKey(0x0028, 0x1406) +#define DCM_BlendingLookupTableDescriptor DcmTagKey(0x0028, 0x1407) +#define DCM_BlendingLookupTableData DcmTagKey(0x0028, 0x1408) +#define DCM_EnhancedPaletteColorLookupTableSequence DcmTagKey(0x0028, 0x140b) +#define DCM_BlendingLUT2Sequence DcmTagKey(0x0028, 0x140c) +#define DCM_BlendingLUT2TransferFunction DcmTagKey(0x0028, 0x140d) +#define DCM_DataPathID DcmTagKey(0x0028, 0x140e) +#define DCM_RGBLUTTransferFunction DcmTagKey(0x0028, 0x140f) +#define DCM_AlphaLUTTransferFunction DcmTagKey(0x0028, 0x1410) +#define DCM_ICCProfile DcmTagKey(0x0028, 0x2000) +#define DCM_ColorSpace DcmTagKey(0x0028, 0x2002) +#define DCM_LossyImageCompression DcmTagKey(0x0028, 0x2110) +#define DCM_LossyImageCompressionRatio DcmTagKey(0x0028, 0x2112) +#define DCM_LossyImageCompressionMethod DcmTagKey(0x0028, 0x2114) +#define DCM_ModalityLUTSequence DcmTagKey(0x0028, 0x3000) +#define DCM_LUTDescriptor DcmTagKey(0x0028, 0x3002) +#define DCM_LUTExplanation DcmTagKey(0x0028, 0x3003) +#define DCM_ModalityLUTType DcmTagKey(0x0028, 0x3004) +#define DCM_LUTData DcmTagKey(0x0028, 0x3006) +#define DCM_VOILUTSequence DcmTagKey(0x0028, 0x3010) +#define DCM_SoftcopyVOILUTSequence DcmTagKey(0x0028, 0x3110) +#define DCM_RETIRED_ImagePresentationComments DcmTagKey(0x0028, 0x4000) +#define DCM_RETIRED_BiPlaneAcquisitionSequence DcmTagKey(0x0028, 0x5000) +#define DCM_RepresentativeFrameNumber DcmTagKey(0x0028, 0x6010) +#define DCM_FrameNumbersOfInterest DcmTagKey(0x0028, 0x6020) +#define DCM_FrameOfInterestDescription DcmTagKey(0x0028, 0x6022) +#define DCM_FrameOfInterestType DcmTagKey(0x0028, 0x6023) +#define DCM_RETIRED_MaskPointers DcmTagKey(0x0028, 0x6030) +#define DCM_RWavePointer DcmTagKey(0x0028, 0x6040) +#define DCM_MaskSubtractionSequence DcmTagKey(0x0028, 0x6100) +#define DCM_MaskOperation DcmTagKey(0x0028, 0x6101) +#define DCM_ApplicableFrameRange DcmTagKey(0x0028, 0x6102) +#define DCM_MaskFrameNumbers DcmTagKey(0x0028, 0x6110) +#define DCM_ContrastFrameAveraging DcmTagKey(0x0028, 0x6112) +#define DCM_MaskSubPixelShift DcmTagKey(0x0028, 0x6114) +#define DCM_TIDOffset DcmTagKey(0x0028, 0x6120) +#define DCM_MaskOperationExplanation DcmTagKey(0x0028, 0x6190) +#define DCM_EquipmentAdministratorSequence DcmTagKey(0x0028, 0x7000) +#define DCM_NumberOfDisplaySubsystems DcmTagKey(0x0028, 0x7001) +#define DCM_CurrentConfigurationID DcmTagKey(0x0028, 0x7002) +#define DCM_DisplaySubsystemID DcmTagKey(0x0028, 0x7003) +#define DCM_DisplaySubsystemName DcmTagKey(0x0028, 0x7004) +#define DCM_DisplaySubsystemDescription DcmTagKey(0x0028, 0x7005) +#define DCM_SystemStatus DcmTagKey(0x0028, 0x7006) +#define DCM_SystemStatusComment DcmTagKey(0x0028, 0x7007) +#define DCM_TargetLuminanceCharacteristicsSequence DcmTagKey(0x0028, 0x7008) +#define DCM_LuminanceCharacteristicsID DcmTagKey(0x0028, 0x7009) +#define DCM_DisplaySubsystemConfigurationSequence DcmTagKey(0x0028, 0x700a) +#define DCM_ConfigurationID DcmTagKey(0x0028, 0x700b) +#define DCM_ConfigurationName DcmTagKey(0x0028, 0x700c) +#define DCM_ConfigurationDescription DcmTagKey(0x0028, 0x700d) +#define DCM_ReferencedTargetLuminanceCharacteristicsID DcmTagKey(0x0028, 0x700e) +#define DCM_QAResultsSequence DcmTagKey(0x0028, 0x700f) +#define DCM_DisplaySubsystemQAResultsSequence DcmTagKey(0x0028, 0x7010) +#define DCM_ConfigurationQAResultsSequence DcmTagKey(0x0028, 0x7011) +#define DCM_MeasurementEquipmentSequence DcmTagKey(0x0028, 0x7012) +#define DCM_MeasurementFunctions DcmTagKey(0x0028, 0x7013) +#define DCM_MeasurementEquipmentType DcmTagKey(0x0028, 0x7014) +#define DCM_VisualEvaluationResultSequence DcmTagKey(0x0028, 0x7015) +#define DCM_DisplayCalibrationResultSequence DcmTagKey(0x0028, 0x7016) +#define DCM_DDLValue DcmTagKey(0x0028, 0x7017) +#define DCM_CIExyWhitePoint DcmTagKey(0x0028, 0x7018) +#define DCM_DisplayFunctionType DcmTagKey(0x0028, 0x7019) +#define DCM_GammaValue DcmTagKey(0x0028, 0x701a) +#define DCM_NumberOfLuminancePoints DcmTagKey(0x0028, 0x701b) +#define DCM_LuminanceResponseSequence DcmTagKey(0x0028, 0x701c) +#define DCM_TargetMinimumLuminance DcmTagKey(0x0028, 0x701d) +#define DCM_TargetMaximumLuminance DcmTagKey(0x0028, 0x701e) +#define DCM_LuminanceValue DcmTagKey(0x0028, 0x701f) +#define DCM_LuminanceResponseDescription DcmTagKey(0x0028, 0x7020) +#define DCM_WhitePointFlag DcmTagKey(0x0028, 0x7021) +#define DCM_DisplayDeviceTypeCodeSequence DcmTagKey(0x0028, 0x7022) +#define DCM_DisplaySubsystemSequence DcmTagKey(0x0028, 0x7023) +#define DCM_LuminanceResultSequence DcmTagKey(0x0028, 0x7024) +#define DCM_AmbientLightValueSource DcmTagKey(0x0028, 0x7025) +#define DCM_MeasuredCharacteristics DcmTagKey(0x0028, 0x7026) +#define DCM_LuminanceUniformityResultSequence DcmTagKey(0x0028, 0x7027) +#define DCM_VisualEvaluationTestSequence DcmTagKey(0x0028, 0x7028) +#define DCM_TestResult DcmTagKey(0x0028, 0x7029) +#define DCM_TestResultComment DcmTagKey(0x0028, 0x702a) +#define DCM_TestImageValidation DcmTagKey(0x0028, 0x702b) +#define DCM_TestPatternCodeSequence DcmTagKey(0x0028, 0x702c) +#define DCM_MeasurementPatternCodeSequence DcmTagKey(0x0028, 0x702d) +#define DCM_VisualEvaluationMethodCodeSequence DcmTagKey(0x0028, 0x702e) +#define DCM_PixelDataProviderURL DcmTagKey(0x0028, 0x7fe0) +#define DCM_DataPointRows DcmTagKey(0x0028, 0x9001) +#define DCM_DataPointColumns DcmTagKey(0x0028, 0x9002) +#define DCM_SignalDomainColumns DcmTagKey(0x0028, 0x9003) +#define DCM_RETIRED_LargestMonochromePixelValue DcmTagKey(0x0028, 0x9099) +#define DCM_DataRepresentation DcmTagKey(0x0028, 0x9108) +#define DCM_PixelMeasuresSequence DcmTagKey(0x0028, 0x9110) +#define DCM_FrameVOILUTSequence DcmTagKey(0x0028, 0x9132) +#define DCM_PixelValueTransformationSequence DcmTagKey(0x0028, 0x9145) +#define DCM_SignalDomainRows DcmTagKey(0x0028, 0x9235) +#define DCM_DisplayFilterPercentage DcmTagKey(0x0028, 0x9411) +#define DCM_FramePixelShiftSequence DcmTagKey(0x0028, 0x9415) +#define DCM_SubtractionItemID DcmTagKey(0x0028, 0x9416) +#define DCM_PixelIntensityRelationshipLUTSequence DcmTagKey(0x0028, 0x9422) +#define DCM_FramePixelDataPropertiesSequence DcmTagKey(0x0028, 0x9443) +#define DCM_GeometricalProperties DcmTagKey(0x0028, 0x9444) +#define DCM_GeometricMaximumDistortion DcmTagKey(0x0028, 0x9445) +#define DCM_ImageProcessingApplied DcmTagKey(0x0028, 0x9446) +#define DCM_MaskSelectionMode DcmTagKey(0x0028, 0x9454) +#define DCM_LUTFunction DcmTagKey(0x0028, 0x9474) +#define DCM_MaskVisibilityPercentage DcmTagKey(0x0028, 0x9478) +#define DCM_PixelShiftSequence DcmTagKey(0x0028, 0x9501) +#define DCM_RegionPixelShiftSequence DcmTagKey(0x0028, 0x9502) +#define DCM_VerticesOfTheRegion DcmTagKey(0x0028, 0x9503) +#define DCM_MultiFramePresentationSequence DcmTagKey(0x0028, 0x9505) +#define DCM_PixelShiftFrameRange DcmTagKey(0x0028, 0x9506) +#define DCM_LUTFrameRange DcmTagKey(0x0028, 0x9507) +#define DCM_ImageToEquipmentMappingMatrix DcmTagKey(0x0028, 0x9520) +#define DCM_EquipmentCoordinateSystemIdentification DcmTagKey(0x0028, 0x9537) +#define DCM_RETIRED_StudyStatusID DcmTagKey(0x0032, 0x000a) +#define DCM_RETIRED_StudyPriorityID DcmTagKey(0x0032, 0x000c) +#define DCM_RETIRED_StudyIDIssuer DcmTagKey(0x0032, 0x0012) +#define DCM_RETIRED_StudyVerifiedDate DcmTagKey(0x0032, 0x0032) +#define DCM_RETIRED_StudyVerifiedTime DcmTagKey(0x0032, 0x0033) +#define DCM_RETIRED_StudyReadDate DcmTagKey(0x0032, 0x0034) +#define DCM_RETIRED_StudyReadTime DcmTagKey(0x0032, 0x0035) +#define DCM_RETIRED_ScheduledStudyStartDate DcmTagKey(0x0032, 0x1000) +#define DCM_RETIRED_ScheduledStudyStartTime DcmTagKey(0x0032, 0x1001) +#define DCM_RETIRED_ScheduledStudyStopDate DcmTagKey(0x0032, 0x1010) +#define DCM_RETIRED_ScheduledStudyStopTime DcmTagKey(0x0032, 0x1011) +#define DCM_RETIRED_ScheduledStudyLocation DcmTagKey(0x0032, 0x1020) +#define DCM_RETIRED_ScheduledStudyLocationAETitle DcmTagKey(0x0032, 0x1021) +#define DCM_RETIRED_ReasonForStudy DcmTagKey(0x0032, 0x1030) +#define DCM_RequestingPhysicianIdentificationSequence DcmTagKey(0x0032, 0x1031) +#define DCM_RequestingPhysician DcmTagKey(0x0032, 0x1032) +#define DCM_RequestingService DcmTagKey(0x0032, 0x1033) +#define DCM_RequestingServiceCodeSequence DcmTagKey(0x0032, 0x1034) +#define DCM_RETIRED_StudyArrivalDate DcmTagKey(0x0032, 0x1040) +#define DCM_RETIRED_StudyArrivalTime DcmTagKey(0x0032, 0x1041) +#define DCM_RETIRED_StudyCompletionDate DcmTagKey(0x0032, 0x1050) +#define DCM_RETIRED_StudyCompletionTime DcmTagKey(0x0032, 0x1051) +#define DCM_RETIRED_StudyComponentStatusID DcmTagKey(0x0032, 0x1055) +#define DCM_RequestedProcedureDescription DcmTagKey(0x0032, 0x1060) +#define DCM_RequestedProcedureCodeSequence DcmTagKey(0x0032, 0x1064) +#define DCM_RequestedContrastAgent DcmTagKey(0x0032, 0x1070) +#define DCM_RETIRED_StudyComments DcmTagKey(0x0032, 0x4000) +#define DCM_ReferencedPatientAliasSequence DcmTagKey(0x0038, 0x0004) +#define DCM_VisitStatusID DcmTagKey(0x0038, 0x0008) +#define DCM_AdmissionID DcmTagKey(0x0038, 0x0010) +#define DCM_RETIRED_IssuerOfAdmissionID DcmTagKey(0x0038, 0x0011) +#define DCM_IssuerOfAdmissionIDSequence DcmTagKey(0x0038, 0x0014) +#define DCM_RouteOfAdmissions DcmTagKey(0x0038, 0x0016) +#define DCM_RETIRED_ScheduledAdmissionDate DcmTagKey(0x0038, 0x001a) +#define DCM_RETIRED_ScheduledAdmissionTime DcmTagKey(0x0038, 0x001b) +#define DCM_RETIRED_ScheduledDischargeDate DcmTagKey(0x0038, 0x001c) +#define DCM_RETIRED_ScheduledDischargeTime DcmTagKey(0x0038, 0x001d) +#define DCM_RETIRED_ScheduledPatientInstitutionResidence DcmTagKey(0x0038, 0x001e) +#define DCM_AdmittingDate DcmTagKey(0x0038, 0x0020) +#define DCM_AdmittingTime DcmTagKey(0x0038, 0x0021) +#define DCM_RETIRED_DischargeDate DcmTagKey(0x0038, 0x0030) +#define DCM_RETIRED_DischargeTime DcmTagKey(0x0038, 0x0032) +#define DCM_RETIRED_DischargeDiagnosisDescription DcmTagKey(0x0038, 0x0040) +#define DCM_RETIRED_DischargeDiagnosisCodeSequence DcmTagKey(0x0038, 0x0044) +#define DCM_SpecialNeeds DcmTagKey(0x0038, 0x0050) +#define DCM_ServiceEpisodeID DcmTagKey(0x0038, 0x0060) +#define DCM_RETIRED_IssuerOfServiceEpisodeID DcmTagKey(0x0038, 0x0061) +#define DCM_ServiceEpisodeDescription DcmTagKey(0x0038, 0x0062) +#define DCM_IssuerOfServiceEpisodeIDSequence DcmTagKey(0x0038, 0x0064) +#define DCM_PertinentDocumentsSequence DcmTagKey(0x0038, 0x0100) +#define DCM_PertinentResourcesSequence DcmTagKey(0x0038, 0x0101) +#define DCM_ResourceDescription DcmTagKey(0x0038, 0x0102) +#define DCM_CurrentPatientLocation DcmTagKey(0x0038, 0x0300) +#define DCM_PatientInstitutionResidence DcmTagKey(0x0038, 0x0400) +#define DCM_PatientState DcmTagKey(0x0038, 0x0500) +#define DCM_PatientClinicalTrialParticipationSequence DcmTagKey(0x0038, 0x0502) +#define DCM_VisitComments DcmTagKey(0x0038, 0x4000) +#define DCM_WaveformOriginality DcmTagKey(0x003a, 0x0004) +#define DCM_NumberOfWaveformChannels DcmTagKey(0x003a, 0x0005) +#define DCM_NumberOfWaveformSamples DcmTagKey(0x003a, 0x0010) +#define DCM_SamplingFrequency DcmTagKey(0x003a, 0x001a) +#define DCM_MultiplexGroupLabel DcmTagKey(0x003a, 0x0020) +#define DCM_ChannelDefinitionSequence DcmTagKey(0x003a, 0x0200) +#define DCM_WaveformChannelNumber DcmTagKey(0x003a, 0x0202) +#define DCM_ChannelLabel DcmTagKey(0x003a, 0x0203) +#define DCM_ChannelStatus DcmTagKey(0x003a, 0x0205) +#define DCM_ChannelSourceSequence DcmTagKey(0x003a, 0x0208) +#define DCM_ChannelSourceModifiersSequence DcmTagKey(0x003a, 0x0209) +#define DCM_SourceWaveformSequence DcmTagKey(0x003a, 0x020a) +#define DCM_ChannelDerivationDescription DcmTagKey(0x003a, 0x020c) +#define DCM_ChannelSensitivity DcmTagKey(0x003a, 0x0210) +#define DCM_ChannelSensitivityUnitsSequence DcmTagKey(0x003a, 0x0211) +#define DCM_ChannelSensitivityCorrectionFactor DcmTagKey(0x003a, 0x0212) +#define DCM_ChannelBaseline DcmTagKey(0x003a, 0x0213) +#define DCM_ChannelTimeSkew DcmTagKey(0x003a, 0x0214) +#define DCM_ChannelSampleSkew DcmTagKey(0x003a, 0x0215) +#define DCM_ChannelOffset DcmTagKey(0x003a, 0x0218) +#define DCM_WaveformBitsStored DcmTagKey(0x003a, 0x021a) +#define DCM_FilterLowFrequency DcmTagKey(0x003a, 0x0220) +#define DCM_FilterHighFrequency DcmTagKey(0x003a, 0x0221) +#define DCM_NotchFilterFrequency DcmTagKey(0x003a, 0x0222) +#define DCM_NotchFilterBandwidth DcmTagKey(0x003a, 0x0223) +#define DCM_WaveformDataDisplayScale DcmTagKey(0x003a, 0x0230) +#define DCM_WaveformDisplayBackgroundCIELabValue DcmTagKey(0x003a, 0x0231) +#define DCM_WaveformPresentationGroupSequence DcmTagKey(0x003a, 0x0240) +#define DCM_PresentationGroupNumber DcmTagKey(0x003a, 0x0241) +#define DCM_ChannelDisplaySequence DcmTagKey(0x003a, 0x0242) +#define DCM_ChannelRecommendedDisplayCIELabValue DcmTagKey(0x003a, 0x0244) +#define DCM_ChannelPosition DcmTagKey(0x003a, 0x0245) +#define DCM_DisplayShadingFlag DcmTagKey(0x003a, 0x0246) +#define DCM_FractionalChannelDisplayScale DcmTagKey(0x003a, 0x0247) +#define DCM_AbsoluteChannelDisplayScale DcmTagKey(0x003a, 0x0248) +#define DCM_MultiplexedAudioChannelsDescriptionCodeSequence DcmTagKey(0x003a, 0x0300) +#define DCM_ChannelIdentificationCode DcmTagKey(0x003a, 0x0301) +#define DCM_ChannelMode DcmTagKey(0x003a, 0x0302) +#define DCM_ScheduledStationAETitle DcmTagKey(0x0040, 0x0001) +#define DCM_ScheduledProcedureStepStartDate DcmTagKey(0x0040, 0x0002) +#define DCM_ScheduledProcedureStepStartTime DcmTagKey(0x0040, 0x0003) +#define DCM_ScheduledProcedureStepEndDate DcmTagKey(0x0040, 0x0004) +#define DCM_ScheduledProcedureStepEndTime DcmTagKey(0x0040, 0x0005) +#define DCM_ScheduledPerformingPhysicianName DcmTagKey(0x0040, 0x0006) +#define DCM_ScheduledProcedureStepDescription DcmTagKey(0x0040, 0x0007) +#define DCM_ScheduledProtocolCodeSequence DcmTagKey(0x0040, 0x0008) +#define DCM_ScheduledProcedureStepID DcmTagKey(0x0040, 0x0009) +#define DCM_StageCodeSequence DcmTagKey(0x0040, 0x000a) +#define DCM_ScheduledPerformingPhysicianIdentificationSequence DcmTagKey(0x0040, 0x000b) +#define DCM_ScheduledStationName DcmTagKey(0x0040, 0x0010) +#define DCM_ScheduledProcedureStepLocation DcmTagKey(0x0040, 0x0011) +#define DCM_PreMedication DcmTagKey(0x0040, 0x0012) +#define DCM_ScheduledProcedureStepStatus DcmTagKey(0x0040, 0x0020) +#define DCM_OrderPlacerIdentifierSequence DcmTagKey(0x0040, 0x0026) +#define DCM_OrderFillerIdentifierSequence DcmTagKey(0x0040, 0x0027) +#define DCM_LocalNamespaceEntityID DcmTagKey(0x0040, 0x0031) +#define DCM_UniversalEntityID DcmTagKey(0x0040, 0x0032) +#define DCM_UniversalEntityIDType DcmTagKey(0x0040, 0x0033) +#define DCM_IdentifierTypeCode DcmTagKey(0x0040, 0x0035) +#define DCM_AssigningFacilitySequence DcmTagKey(0x0040, 0x0036) +#define DCM_AssigningJurisdictionCodeSequence DcmTagKey(0x0040, 0x0039) +#define DCM_AssigningAgencyOrDepartmentCodeSequence DcmTagKey(0x0040, 0x003a) +#define DCM_ScheduledProcedureStepSequence DcmTagKey(0x0040, 0x0100) +#define DCM_ReferencedNonImageCompositeSOPInstanceSequence DcmTagKey(0x0040, 0x0220) +#define DCM_PerformedStationAETitle DcmTagKey(0x0040, 0x0241) +#define DCM_PerformedStationName DcmTagKey(0x0040, 0x0242) +#define DCM_PerformedLocation DcmTagKey(0x0040, 0x0243) +#define DCM_PerformedProcedureStepStartDate DcmTagKey(0x0040, 0x0244) +#define DCM_PerformedProcedureStepStartTime DcmTagKey(0x0040, 0x0245) +#define DCM_PerformedProcedureStepEndDate DcmTagKey(0x0040, 0x0250) +#define DCM_PerformedProcedureStepEndTime DcmTagKey(0x0040, 0x0251) +#define DCM_PerformedProcedureStepStatus DcmTagKey(0x0040, 0x0252) +#define DCM_PerformedProcedureStepID DcmTagKey(0x0040, 0x0253) +#define DCM_PerformedProcedureStepDescription DcmTagKey(0x0040, 0x0254) +#define DCM_PerformedProcedureTypeDescription DcmTagKey(0x0040, 0x0255) +#define DCM_PerformedProtocolCodeSequence DcmTagKey(0x0040, 0x0260) +#define DCM_PerformedProtocolType DcmTagKey(0x0040, 0x0261) +#define DCM_ScheduledStepAttributesSequence DcmTagKey(0x0040, 0x0270) +#define DCM_RequestAttributesSequence DcmTagKey(0x0040, 0x0275) +#define DCM_CommentsOnThePerformedProcedureStep DcmTagKey(0x0040, 0x0280) +#define DCM_PerformedProcedureStepDiscontinuationReasonCodeSequence DcmTagKey(0x0040, 0x0281) +#define DCM_QuantitySequence DcmTagKey(0x0040, 0x0293) +#define DCM_Quantity DcmTagKey(0x0040, 0x0294) +#define DCM_MeasuringUnitsSequence DcmTagKey(0x0040, 0x0295) +#define DCM_BillingItemSequence DcmTagKey(0x0040, 0x0296) +#define DCM_TotalTimeOfFluoroscopy DcmTagKey(0x0040, 0x0300) +#define DCM_TotalNumberOfExposures DcmTagKey(0x0040, 0x0301) +#define DCM_EntranceDose DcmTagKey(0x0040, 0x0302) +#define DCM_ExposedArea DcmTagKey(0x0040, 0x0303) +#define DCM_DistanceSourceToEntrance DcmTagKey(0x0040, 0x0306) +#define DCM_RETIRED_DistanceSourceToSupport DcmTagKey(0x0040, 0x0307) +#define DCM_ExposureDoseSequence DcmTagKey(0x0040, 0x030e) +#define DCM_CommentsOnRadiationDose DcmTagKey(0x0040, 0x0310) +#define DCM_XRayOutput DcmTagKey(0x0040, 0x0312) +#define DCM_HalfValueLayer DcmTagKey(0x0040, 0x0314) +#define DCM_OrganDose DcmTagKey(0x0040, 0x0316) +#define DCM_OrganExposed DcmTagKey(0x0040, 0x0318) +#define DCM_BillingProcedureStepSequence DcmTagKey(0x0040, 0x0320) +#define DCM_FilmConsumptionSequence DcmTagKey(0x0040, 0x0321) +#define DCM_BillingSuppliesAndDevicesSequence DcmTagKey(0x0040, 0x0324) +#define DCM_RETIRED_ReferencedProcedureStepSequence DcmTagKey(0x0040, 0x0330) +#define DCM_PerformedSeriesSequence DcmTagKey(0x0040, 0x0340) +#define DCM_CommentsOnTheScheduledProcedureStep DcmTagKey(0x0040, 0x0400) +#define DCM_ProtocolContextSequence DcmTagKey(0x0040, 0x0440) +#define DCM_ContentItemModifierSequence DcmTagKey(0x0040, 0x0441) +#define DCM_ScheduledSpecimenSequence DcmTagKey(0x0040, 0x0500) +#define DCM_RETIRED_SpecimenAccessionNumber DcmTagKey(0x0040, 0x050a) +#define DCM_ContainerIdentifier DcmTagKey(0x0040, 0x0512) +#define DCM_IssuerOfTheContainerIdentifierSequence DcmTagKey(0x0040, 0x0513) +#define DCM_AlternateContainerIdentifierSequence DcmTagKey(0x0040, 0x0515) +#define DCM_ContainerTypeCodeSequence DcmTagKey(0x0040, 0x0518) +#define DCM_ContainerDescription DcmTagKey(0x0040, 0x051a) +#define DCM_ContainerComponentSequence DcmTagKey(0x0040, 0x0520) +#define DCM_RETIRED_SpecimenSequence DcmTagKey(0x0040, 0x0550) +#define DCM_SpecimenIdentifier DcmTagKey(0x0040, 0x0551) +#define DCM_RETIRED_SpecimenDescriptionSequenceTrial DcmTagKey(0x0040, 0x0552) +#define DCM_RETIRED_SpecimenDescriptionTrial DcmTagKey(0x0040, 0x0553) +#define DCM_SpecimenUID DcmTagKey(0x0040, 0x0554) +#define DCM_AcquisitionContextSequence DcmTagKey(0x0040, 0x0555) +#define DCM_AcquisitionContextDescription DcmTagKey(0x0040, 0x0556) +#define DCM_SpecimenDescriptionSequence DcmTagKey(0x0040, 0x0560) +#define DCM_IssuerOfTheSpecimenIdentifierSequence DcmTagKey(0x0040, 0x0562) +#define DCM_SpecimenTypeCodeSequence DcmTagKey(0x0040, 0x059a) +#define DCM_SpecimenShortDescription DcmTagKey(0x0040, 0x0600) +#define DCM_SpecimenDetailedDescription DcmTagKey(0x0040, 0x0602) +#define DCM_SpecimenPreparationSequence DcmTagKey(0x0040, 0x0610) +#define DCM_SpecimenPreparationStepContentItemSequence DcmTagKey(0x0040, 0x0612) +#define DCM_SpecimenLocalizationContentItemSequence DcmTagKey(0x0040, 0x0620) +#define DCM_RETIRED_SlideIdentifier DcmTagKey(0x0040, 0x06fa) +#define DCM_ImageCenterPointCoordinatesSequence DcmTagKey(0x0040, 0x071a) +#define DCM_XOffsetInSlideCoordinateSystem DcmTagKey(0x0040, 0x072a) +#define DCM_YOffsetInSlideCoordinateSystem DcmTagKey(0x0040, 0x073a) +#define DCM_ZOffsetInSlideCoordinateSystem DcmTagKey(0x0040, 0x074a) +#define DCM_RETIRED_PixelSpacingSequence DcmTagKey(0x0040, 0x08d8) +#define DCM_RETIRED_CoordinateSystemAxisCodeSequence DcmTagKey(0x0040, 0x08da) +#define DCM_MeasurementUnitsCodeSequence DcmTagKey(0x0040, 0x08ea) +#define DCM_RETIRED_VitalStainCodeSequenceTrial DcmTagKey(0x0040, 0x09f8) +#define DCM_RequestedProcedureID DcmTagKey(0x0040, 0x1001) +#define DCM_ReasonForTheRequestedProcedure DcmTagKey(0x0040, 0x1002) +#define DCM_RequestedProcedurePriority DcmTagKey(0x0040, 0x1003) +#define DCM_PatientTransportArrangements DcmTagKey(0x0040, 0x1004) +#define DCM_RequestedProcedureLocation DcmTagKey(0x0040, 0x1005) +#define DCM_RETIRED_PlacerOrderNumberProcedure DcmTagKey(0x0040, 0x1006) +#define DCM_RETIRED_FillerOrderNumberProcedure DcmTagKey(0x0040, 0x1007) +#define DCM_ConfidentialityCode DcmTagKey(0x0040, 0x1008) +#define DCM_ReportingPriority DcmTagKey(0x0040, 0x1009) +#define DCM_ReasonForRequestedProcedureCodeSequence DcmTagKey(0x0040, 0x100a) +#define DCM_NamesOfIntendedRecipientsOfResults DcmTagKey(0x0040, 0x1010) +#define DCM_IntendedRecipientsOfResultsIdentificationSequence DcmTagKey(0x0040, 0x1011) +#define DCM_ReasonForPerformedProcedureCodeSequence DcmTagKey(0x0040, 0x1012) +#define DCM_RETIRED_RequestedProcedureDescriptionTrial DcmTagKey(0x0040, 0x1060) +#define DCM_PersonIdentificationCodeSequence DcmTagKey(0x0040, 0x1101) +#define DCM_PersonAddress DcmTagKey(0x0040, 0x1102) +#define DCM_PersonTelephoneNumbers DcmTagKey(0x0040, 0x1103) +#define DCM_PersonTelecomInformation DcmTagKey(0x0040, 0x1104) +#define DCM_RequestedProcedureComments DcmTagKey(0x0040, 0x1400) +#define DCM_RETIRED_ReasonForTheImagingServiceRequest DcmTagKey(0x0040, 0x2001) +#define DCM_IssueDateOfImagingServiceRequest DcmTagKey(0x0040, 0x2004) +#define DCM_IssueTimeOfImagingServiceRequest DcmTagKey(0x0040, 0x2005) +#define DCM_RETIRED_PlacerOrderNumberImagingServiceRequestRetired DcmTagKey(0x0040, 0x2006) +#define DCM_RETIRED_FillerOrderNumberImagingServiceRequestRetired DcmTagKey(0x0040, 0x2007) +#define DCM_OrderEnteredBy DcmTagKey(0x0040, 0x2008) +#define DCM_OrderEntererLocation DcmTagKey(0x0040, 0x2009) +#define DCM_OrderCallbackPhoneNumber DcmTagKey(0x0040, 0x2010) +#define DCM_OrderCallbackTelecomInformation DcmTagKey(0x0040, 0x2011) +#define DCM_PlacerOrderNumberImagingServiceRequest DcmTagKey(0x0040, 0x2016) +#define DCM_FillerOrderNumberImagingServiceRequest DcmTagKey(0x0040, 0x2017) +#define DCM_ImagingServiceRequestComments DcmTagKey(0x0040, 0x2400) +#define DCM_ConfidentialityConstraintOnPatientDataDescription DcmTagKey(0x0040, 0x3001) +#define DCM_RETIRED_GeneralPurposeScheduledProcedureStepStatus DcmTagKey(0x0040, 0x4001) +#define DCM_RETIRED_GeneralPurposePerformedProcedureStepStatus DcmTagKey(0x0040, 0x4002) +#define DCM_RETIRED_GeneralPurposeScheduledProcedureStepPriority DcmTagKey(0x0040, 0x4003) +#define DCM_RETIRED_ScheduledProcessingApplicationsCodeSequence DcmTagKey(0x0040, 0x4004) +#define DCM_ScheduledProcedureStepStartDateTime DcmTagKey(0x0040, 0x4005) +#define DCM_RETIRED_MultipleCopiesFlag DcmTagKey(0x0040, 0x4006) +#define DCM_PerformedProcessingApplicationsCodeSequence DcmTagKey(0x0040, 0x4007) +#define DCM_HumanPerformerCodeSequence DcmTagKey(0x0040, 0x4009) +#define DCM_ScheduledProcedureStepModificationDateTime DcmTagKey(0x0040, 0x4010) +#define DCM_ExpectedCompletionDateTime DcmTagKey(0x0040, 0x4011) +#define DCM_RETIRED_ResultingGeneralPurposePerformedProcedureStepsSequence DcmTagKey(0x0040, 0x4015) +#define DCM_RETIRED_ReferencedGeneralPurposeScheduledProcedureStepSequence DcmTagKey(0x0040, 0x4016) +#define DCM_ScheduledWorkitemCodeSequence DcmTagKey(0x0040, 0x4018) +#define DCM_PerformedWorkitemCodeSequence DcmTagKey(0x0040, 0x4019) +#define DCM_InputAvailabilityFlag DcmTagKey(0x0040, 0x4020) +#define DCM_InputInformationSequence DcmTagKey(0x0040, 0x4021) +#define DCM_RETIRED_RelevantInformationSequence DcmTagKey(0x0040, 0x4022) +#define DCM_RETIRED_ReferencedGeneralPurposeScheduledProcedureStepTransactionUID DcmTagKey(0x0040, 0x4023) +#define DCM_ScheduledStationNameCodeSequence DcmTagKey(0x0040, 0x4025) +#define DCM_ScheduledStationClassCodeSequence DcmTagKey(0x0040, 0x4026) +#define DCM_ScheduledStationGeographicLocationCodeSequence DcmTagKey(0x0040, 0x4027) +#define DCM_PerformedStationNameCodeSequence DcmTagKey(0x0040, 0x4028) +#define DCM_PerformedStationClassCodeSequence DcmTagKey(0x0040, 0x4029) +#define DCM_PerformedStationGeographicLocationCodeSequence DcmTagKey(0x0040, 0x4030) +#define DCM_RETIRED_RequestedSubsequentWorkitemCodeSequence DcmTagKey(0x0040, 0x4031) +#define DCM_RETIRED_NonDICOMOutputCodeSequence DcmTagKey(0x0040, 0x4032) +#define DCM_OutputInformationSequence DcmTagKey(0x0040, 0x4033) +#define DCM_ScheduledHumanPerformersSequence DcmTagKey(0x0040, 0x4034) +#define DCM_ActualHumanPerformersSequence DcmTagKey(0x0040, 0x4035) +#define DCM_HumanPerformerOrganization DcmTagKey(0x0040, 0x4036) +#define DCM_HumanPerformerName DcmTagKey(0x0040, 0x4037) +#define DCM_RawDataHandling DcmTagKey(0x0040, 0x4040) +#define DCM_InputReadinessState DcmTagKey(0x0040, 0x4041) +#define DCM_PerformedProcedureStepStartDateTime DcmTagKey(0x0040, 0x4050) +#define DCM_PerformedProcedureStepEndDateTime DcmTagKey(0x0040, 0x4051) +#define DCM_ProcedureStepCancellationDateTime DcmTagKey(0x0040, 0x4052) +#define DCM_OutputDestinationSequence DcmTagKey(0x0040, 0x4070) +#define DCM_DICOMStorageSequence DcmTagKey(0x0040, 0x4071) +#define DCM_STOWRSStorageSequence DcmTagKey(0x0040, 0x4072) +#define DCM_StorageURL DcmTagKey(0x0040, 0x4073) +#define DCM_XDSStorageSequence DcmTagKey(0x0040, 0x4074) +#define DCM_EntranceDoseInmGy DcmTagKey(0x0040, 0x8302) +#define DCM_ParametricMapFrameTypeSequence DcmTagKey(0x0040, 0x9092) +#define DCM_ReferencedImageRealWorldValueMappingSequence DcmTagKey(0x0040, 0x9094) +#define DCM_RealWorldValueMappingSequence DcmTagKey(0x0040, 0x9096) +#define DCM_PixelValueMappingCodeSequence DcmTagKey(0x0040, 0x9098) +#define DCM_LUTLabel DcmTagKey(0x0040, 0x9210) +#define DCM_RealWorldValueLastValueMapped DcmTagKey(0x0040, 0x9211) +#define DCM_RealWorldValueLUTData DcmTagKey(0x0040, 0x9212) +#define DCM_DoubleFloatRealWorldValueLastValueMapped DcmTagKey(0x0040, 0x9213) +#define DCM_DoubleFloatRealWorldValueFirstValueMapped DcmTagKey(0x0040, 0x9214) +#define DCM_RealWorldValueFirstValueMapped DcmTagKey(0x0040, 0x9216) +#define DCM_QuantityDefinitionSequence DcmTagKey(0x0040, 0x9220) +#define DCM_RealWorldValueIntercept DcmTagKey(0x0040, 0x9224) +#define DCM_RealWorldValueSlope DcmTagKey(0x0040, 0x9225) +#define DCM_RETIRED_FindingsFlagTrial DcmTagKey(0x0040, 0xa007) +#define DCM_RelationshipType DcmTagKey(0x0040, 0xa010) +#define DCM_RETIRED_FindingsSequenceTrial DcmTagKey(0x0040, 0xa020) +#define DCM_RETIRED_FindingsGroupUIDTrial DcmTagKey(0x0040, 0xa021) +#define DCM_RETIRED_ReferencedFindingsGroupUIDTrial DcmTagKey(0x0040, 0xa022) +#define DCM_RETIRED_FindingsGroupRecordingDateTrial DcmTagKey(0x0040, 0xa023) +#define DCM_RETIRED_FindingsGroupRecordingTimeTrial DcmTagKey(0x0040, 0xa024) +#define DCM_RETIRED_FindingsSourceCategoryCodeSequenceTrial DcmTagKey(0x0040, 0xa026) +#define DCM_VerifyingOrganization DcmTagKey(0x0040, 0xa027) +#define DCM_RETIRED_DocumentingOrganizationIdentifierCodeSequenceTrial DcmTagKey(0x0040, 0xa028) +#define DCM_VerificationDateTime DcmTagKey(0x0040, 0xa030) +#define DCM_ObservationDateTime DcmTagKey(0x0040, 0xa032) +#define DCM_ValueType DcmTagKey(0x0040, 0xa040) +#define DCM_ConceptNameCodeSequence DcmTagKey(0x0040, 0xa043) +#define DCM_RETIRED_MeasurementPrecisionDescriptionTrial DcmTagKey(0x0040, 0xa047) +#define DCM_ContinuityOfContent DcmTagKey(0x0040, 0xa050) +#define DCM_RETIRED_UrgencyOrPriorityAlertsTrial DcmTagKey(0x0040, 0xa057) +#define DCM_RETIRED_SequencingIndicatorTrial DcmTagKey(0x0040, 0xa060) +#define DCM_RETIRED_DocumentIdentifierCodeSequenceTrial DcmTagKey(0x0040, 0xa066) +#define DCM_RETIRED_DocumentAuthorTrial DcmTagKey(0x0040, 0xa067) +#define DCM_RETIRED_DocumentAuthorIdentifierCodeSequenceTrial DcmTagKey(0x0040, 0xa068) +#define DCM_RETIRED_IdentifierCodeSequenceTrial DcmTagKey(0x0040, 0xa070) +#define DCM_VerifyingObserverSequence DcmTagKey(0x0040, 0xa073) +#define DCM_RETIRED_ObjectBinaryIdentifierTrial DcmTagKey(0x0040, 0xa074) +#define DCM_VerifyingObserverName DcmTagKey(0x0040, 0xa075) +#define DCM_RETIRED_DocumentingObserverIdentifierCodeSequenceTrial DcmTagKey(0x0040, 0xa076) +#define DCM_AuthorObserverSequence DcmTagKey(0x0040, 0xa078) +#define DCM_ParticipantSequence DcmTagKey(0x0040, 0xa07a) +#define DCM_CustodialOrganizationSequence DcmTagKey(0x0040, 0xa07c) +#define DCM_ParticipationType DcmTagKey(0x0040, 0xa080) +#define DCM_ParticipationDateTime DcmTagKey(0x0040, 0xa082) +#define DCM_ObserverType DcmTagKey(0x0040, 0xa084) +#define DCM_RETIRED_ProcedureIdentifierCodeSequenceTrial DcmTagKey(0x0040, 0xa085) +#define DCM_VerifyingObserverIdentificationCodeSequence DcmTagKey(0x0040, 0xa088) +#define DCM_RETIRED_ObjectDirectoryBinaryIdentifierTrial DcmTagKey(0x0040, 0xa089) +#define DCM_RETIRED_EquivalentCDADocumentSequence DcmTagKey(0x0040, 0xa090) +#define DCM_ReferencedWaveformChannels DcmTagKey(0x0040, 0xa0b0) +#define DCM_RETIRED_DateOfDocumentOrVerbalTransactionTrial DcmTagKey(0x0040, 0xa110) +#define DCM_RETIRED_TimeOfDocumentCreationOrVerbalTransactionTrial DcmTagKey(0x0040, 0xa112) +#define DCM_DateTime DcmTagKey(0x0040, 0xa120) +#define DCM_Date DcmTagKey(0x0040, 0xa121) +#define DCM_Time DcmTagKey(0x0040, 0xa122) +#define DCM_PersonName DcmTagKey(0x0040, 0xa123) +#define DCM_UID DcmTagKey(0x0040, 0xa124) +#define DCM_RETIRED_ReportStatusIDTrial DcmTagKey(0x0040, 0xa125) +#define DCM_TemporalRangeType DcmTagKey(0x0040, 0xa130) +#define DCM_ReferencedSamplePositions DcmTagKey(0x0040, 0xa132) +#define DCM_ReferencedFrameNumbers DcmTagKey(0x0040, 0xa136) +#define DCM_ReferencedTimeOffsets DcmTagKey(0x0040, 0xa138) +#define DCM_ReferencedDateTime DcmTagKey(0x0040, 0xa13a) +#define DCM_TextValue DcmTagKey(0x0040, 0xa160) +#define DCM_FloatingPointValue DcmTagKey(0x0040, 0xa161) +#define DCM_RationalNumeratorValue DcmTagKey(0x0040, 0xa162) +#define DCM_RationalDenominatorValue DcmTagKey(0x0040, 0xa163) +#define DCM_RETIRED_ObservationCategoryCodeSequenceTrial DcmTagKey(0x0040, 0xa167) +#define DCM_ConceptCodeSequence DcmTagKey(0x0040, 0xa168) +#define DCM_RETIRED_BibliographicCitationTrial DcmTagKey(0x0040, 0xa16a) +#define DCM_PurposeOfReferenceCodeSequence DcmTagKey(0x0040, 0xa170) +#define DCM_ObservationUID DcmTagKey(0x0040, 0xa171) +#define DCM_RETIRED_ReferencedObservationUIDTrial DcmTagKey(0x0040, 0xa172) +#define DCM_RETIRED_ReferencedObservationClassTrial DcmTagKey(0x0040, 0xa173) +#define DCM_RETIRED_ReferencedObjectObservationClassTrial DcmTagKey(0x0040, 0xa174) +#define DCM_AnnotationGroupNumber DcmTagKey(0x0040, 0xa180) +#define DCM_RETIRED_ObservationDateTrial DcmTagKey(0x0040, 0xa192) +#define DCM_RETIRED_ObservationTimeTrial DcmTagKey(0x0040, 0xa193) +#define DCM_RETIRED_MeasurementAutomationTrial DcmTagKey(0x0040, 0xa194) +#define DCM_ModifierCodeSequence DcmTagKey(0x0040, 0xa195) +#define DCM_RETIRED_IdentificationDescriptionTrial DcmTagKey(0x0040, 0xa224) +#define DCM_RETIRED_CoordinatesSetGeometricTypeTrial DcmTagKey(0x0040, 0xa290) +#define DCM_RETIRED_AlgorithmCodeSequenceTrial DcmTagKey(0x0040, 0xa296) +#define DCM_RETIRED_AlgorithmDescriptionTrial DcmTagKey(0x0040, 0xa297) +#define DCM_RETIRED_PixelCoordinatesSetTrial DcmTagKey(0x0040, 0xa29a) +#define DCM_MeasuredValueSequence DcmTagKey(0x0040, 0xa300) +#define DCM_NumericValueQualifierCodeSequence DcmTagKey(0x0040, 0xa301) +#define DCM_RETIRED_CurrentObserverTrial DcmTagKey(0x0040, 0xa307) +#define DCM_NumericValue DcmTagKey(0x0040, 0xa30a) +#define DCM_RETIRED_ReferencedAccessionSequenceTrial DcmTagKey(0x0040, 0xa313) +#define DCM_RETIRED_ReportStatusCommentTrial DcmTagKey(0x0040, 0xa33a) +#define DCM_RETIRED_ProcedureContextSequenceTrial DcmTagKey(0x0040, 0xa340) +#define DCM_RETIRED_VerbalSourceTrial DcmTagKey(0x0040, 0xa352) +#define DCM_RETIRED_AddressTrial DcmTagKey(0x0040, 0xa353) +#define DCM_RETIRED_TelephoneNumberTrial DcmTagKey(0x0040, 0xa354) +#define DCM_RETIRED_VerbalSourceIdentifierCodeSequenceTrial DcmTagKey(0x0040, 0xa358) +#define DCM_PredecessorDocumentsSequence DcmTagKey(0x0040, 0xa360) +#define DCM_ReferencedRequestSequence DcmTagKey(0x0040, 0xa370) +#define DCM_PerformedProcedureCodeSequence DcmTagKey(0x0040, 0xa372) +#define DCM_CurrentRequestedProcedureEvidenceSequence DcmTagKey(0x0040, 0xa375) +#define DCM_RETIRED_ReportDetailSequenceTrial DcmTagKey(0x0040, 0xa380) +#define DCM_PertinentOtherEvidenceSequence DcmTagKey(0x0040, 0xa385) +#define DCM_HL7StructuredDocumentReferenceSequence DcmTagKey(0x0040, 0xa390) +#define DCM_RETIRED_ObservationSubjectUIDTrial DcmTagKey(0x0040, 0xa402) +#define DCM_RETIRED_ObservationSubjectClassTrial DcmTagKey(0x0040, 0xa403) +#define DCM_RETIRED_ObservationSubjectTypeCodeSequenceTrial DcmTagKey(0x0040, 0xa404) +#define DCM_CompletionFlag DcmTagKey(0x0040, 0xa491) +#define DCM_CompletionFlagDescription DcmTagKey(0x0040, 0xa492) +#define DCM_VerificationFlag DcmTagKey(0x0040, 0xa493) +#define DCM_ArchiveRequested DcmTagKey(0x0040, 0xa494) +#define DCM_PreliminaryFlag DcmTagKey(0x0040, 0xa496) +#define DCM_ContentTemplateSequence DcmTagKey(0x0040, 0xa504) +#define DCM_IdenticalDocumentsSequence DcmTagKey(0x0040, 0xa525) +#define DCM_RETIRED_ObservationSubjectContextFlagTrial DcmTagKey(0x0040, 0xa600) +#define DCM_RETIRED_ObserverContextFlagTrial DcmTagKey(0x0040, 0xa601) +#define DCM_RETIRED_ProcedureContextFlagTrial DcmTagKey(0x0040, 0xa603) +#define DCM_ContentSequence DcmTagKey(0x0040, 0xa730) +#define DCM_RETIRED_RelationshipSequenceTrial DcmTagKey(0x0040, 0xa731) +#define DCM_RETIRED_RelationshipTypeCodeSequenceTrial DcmTagKey(0x0040, 0xa732) +#define DCM_RETIRED_LanguageCodeSequenceTrial DcmTagKey(0x0040, 0xa744) +#define DCM_RETIRED_UniformResourceLocatorTrial DcmTagKey(0x0040, 0xa992) +#define DCM_WaveformAnnotationSequence DcmTagKey(0x0040, 0xb020) +#define DCM_TemplateIdentifier DcmTagKey(0x0040, 0xdb00) +#define DCM_RETIRED_TemplateVersion DcmTagKey(0x0040, 0xdb06) +#define DCM_RETIRED_TemplateLocalVersion DcmTagKey(0x0040, 0xdb07) +#define DCM_RETIRED_TemplateExtensionFlag DcmTagKey(0x0040, 0xdb0b) +#define DCM_RETIRED_TemplateExtensionOrganizationUID DcmTagKey(0x0040, 0xdb0c) +#define DCM_RETIRED_TemplateExtensionCreatorUID DcmTagKey(0x0040, 0xdb0d) +#define DCM_ReferencedContentItemIdentifier DcmTagKey(0x0040, 0xdb73) +#define DCM_HL7InstanceIdentifier DcmTagKey(0x0040, 0xe001) +#define DCM_HL7DocumentEffectiveTime DcmTagKey(0x0040, 0xe004) +#define DCM_HL7DocumentTypeCodeSequence DcmTagKey(0x0040, 0xe006) +#define DCM_DocumentClassCodeSequence DcmTagKey(0x0040, 0xe008) +#define DCM_RetrieveURI DcmTagKey(0x0040, 0xe010) +#define DCM_RetrieveLocationUID DcmTagKey(0x0040, 0xe011) +#define DCM_TypeOfInstances DcmTagKey(0x0040, 0xe020) +#define DCM_DICOMRetrievalSequence DcmTagKey(0x0040, 0xe021) +#define DCM_DICOMMediaRetrievalSequence DcmTagKey(0x0040, 0xe022) +#define DCM_WADORetrievalSequence DcmTagKey(0x0040, 0xe023) +#define DCM_XDSRetrievalSequence DcmTagKey(0x0040, 0xe024) +#define DCM_WADORSRetrievalSequence DcmTagKey(0x0040, 0xe025) +#define DCM_RepositoryUniqueID DcmTagKey(0x0040, 0xe030) +#define DCM_HomeCommunityID DcmTagKey(0x0040, 0xe031) +#define DCM_DocumentTitle DcmTagKey(0x0042, 0x0010) +#define DCM_EncapsulatedDocument DcmTagKey(0x0042, 0x0011) +#define DCM_MIMETypeOfEncapsulatedDocument DcmTagKey(0x0042, 0x0012) +#define DCM_SourceInstanceSequence DcmTagKey(0x0042, 0x0013) +#define DCM_ListOfMIMETypes DcmTagKey(0x0042, 0x0014) +#define DCM_ProductPackageIdentifier DcmTagKey(0x0044, 0x0001) +#define DCM_SubstanceAdministrationApproval DcmTagKey(0x0044, 0x0002) +#define DCM_ApprovalStatusFurtherDescription DcmTagKey(0x0044, 0x0003) +#define DCM_ApprovalStatusDateTime DcmTagKey(0x0044, 0x0004) +#define DCM_ProductTypeCodeSequence DcmTagKey(0x0044, 0x0007) +#define DCM_ProductName DcmTagKey(0x0044, 0x0008) +#define DCM_ProductDescription DcmTagKey(0x0044, 0x0009) +#define DCM_ProductLotIdentifier DcmTagKey(0x0044, 0x000a) +#define DCM_ProductExpirationDateTime DcmTagKey(0x0044, 0x000b) +#define DCM_SubstanceAdministrationDateTime DcmTagKey(0x0044, 0x0010) +#define DCM_SubstanceAdministrationNotes DcmTagKey(0x0044, 0x0011) +#define DCM_SubstanceAdministrationDeviceID DcmTagKey(0x0044, 0x0012) +#define DCM_ProductParameterSequence DcmTagKey(0x0044, 0x0013) +#define DCM_SubstanceAdministrationParameterSequence DcmTagKey(0x0044, 0x0019) +#define DCM_LensDescription DcmTagKey(0x0046, 0x0012) +#define DCM_RightLensSequence DcmTagKey(0x0046, 0x0014) +#define DCM_LeftLensSequence DcmTagKey(0x0046, 0x0015) +#define DCM_UnspecifiedLateralityLensSequence DcmTagKey(0x0046, 0x0016) +#define DCM_CylinderSequence DcmTagKey(0x0046, 0x0018) +#define DCM_PrismSequence DcmTagKey(0x0046, 0x0028) +#define DCM_HorizontalPrismPower DcmTagKey(0x0046, 0x0030) +#define DCM_HorizontalPrismBase DcmTagKey(0x0046, 0x0032) +#define DCM_VerticalPrismPower DcmTagKey(0x0046, 0x0034) +#define DCM_VerticalPrismBase DcmTagKey(0x0046, 0x0036) +#define DCM_LensSegmentType DcmTagKey(0x0046, 0x0038) +#define DCM_OpticalTransmittance DcmTagKey(0x0046, 0x0040) +#define DCM_ChannelWidth DcmTagKey(0x0046, 0x0042) +#define DCM_PupilSize DcmTagKey(0x0046, 0x0044) +#define DCM_CornealSize DcmTagKey(0x0046, 0x0046) +#define DCM_AutorefractionRightEyeSequence DcmTagKey(0x0046, 0x0050) +#define DCM_AutorefractionLeftEyeSequence DcmTagKey(0x0046, 0x0052) +#define DCM_DistancePupillaryDistance DcmTagKey(0x0046, 0x0060) +#define DCM_NearPupillaryDistance DcmTagKey(0x0046, 0x0062) +#define DCM_IntermediatePupillaryDistance DcmTagKey(0x0046, 0x0063) +#define DCM_OtherPupillaryDistance DcmTagKey(0x0046, 0x0064) +#define DCM_KeratometryRightEyeSequence DcmTagKey(0x0046, 0x0070) +#define DCM_KeratometryLeftEyeSequence DcmTagKey(0x0046, 0x0071) +#define DCM_SteepKeratometricAxisSequence DcmTagKey(0x0046, 0x0074) +#define DCM_RadiusOfCurvature DcmTagKey(0x0046, 0x0075) +#define DCM_KeratometricPower DcmTagKey(0x0046, 0x0076) +#define DCM_KeratometricAxis DcmTagKey(0x0046, 0x0077) +#define DCM_FlatKeratometricAxisSequence DcmTagKey(0x0046, 0x0080) +#define DCM_BackgroundColor DcmTagKey(0x0046, 0x0092) +#define DCM_Optotype DcmTagKey(0x0046, 0x0094) +#define DCM_OptotypePresentation DcmTagKey(0x0046, 0x0095) +#define DCM_SubjectiveRefractionRightEyeSequence DcmTagKey(0x0046, 0x0097) +#define DCM_SubjectiveRefractionLeftEyeSequence DcmTagKey(0x0046, 0x0098) +#define DCM_AddNearSequence DcmTagKey(0x0046, 0x0100) +#define DCM_AddIntermediateSequence DcmTagKey(0x0046, 0x0101) +#define DCM_AddOtherSequence DcmTagKey(0x0046, 0x0102) +#define DCM_AddPower DcmTagKey(0x0046, 0x0104) +#define DCM_ViewingDistance DcmTagKey(0x0046, 0x0106) +#define DCM_VisualAcuityTypeCodeSequence DcmTagKey(0x0046, 0x0121) +#define DCM_VisualAcuityRightEyeSequence DcmTagKey(0x0046, 0x0122) +#define DCM_VisualAcuityLeftEyeSequence DcmTagKey(0x0046, 0x0123) +#define DCM_VisualAcuityBothEyesOpenSequence DcmTagKey(0x0046, 0x0124) +#define DCM_ViewingDistanceType DcmTagKey(0x0046, 0x0125) +#define DCM_VisualAcuityModifiers DcmTagKey(0x0046, 0x0135) +#define DCM_DecimalVisualAcuity DcmTagKey(0x0046, 0x0137) +#define DCM_OptotypeDetailedDefinition DcmTagKey(0x0046, 0x0139) +#define DCM_ReferencedRefractiveMeasurementsSequence DcmTagKey(0x0046, 0x0145) +#define DCM_SpherePower DcmTagKey(0x0046, 0x0146) +#define DCM_CylinderPower DcmTagKey(0x0046, 0x0147) +#define DCM_CornealTopographySurface DcmTagKey(0x0046, 0x0201) +#define DCM_CornealVertexLocation DcmTagKey(0x0046, 0x0202) +#define DCM_PupilCentroidXCoordinate DcmTagKey(0x0046, 0x0203) +#define DCM_PupilCentroidYCoordinate DcmTagKey(0x0046, 0x0204) +#define DCM_EquivalentPupilRadius DcmTagKey(0x0046, 0x0205) +#define DCM_CornealTopographyMapTypeCodeSequence DcmTagKey(0x0046, 0x0207) +#define DCM_VerticesOfTheOutlineOfPupil DcmTagKey(0x0046, 0x0208) +#define DCM_CornealTopographyMappingNormalsSequence DcmTagKey(0x0046, 0x0210) +#define DCM_MaximumCornealCurvatureSequence DcmTagKey(0x0046, 0x0211) +#define DCM_MaximumCornealCurvature DcmTagKey(0x0046, 0x0212) +#define DCM_MaximumCornealCurvatureLocation DcmTagKey(0x0046, 0x0213) +#define DCM_MinimumKeratometricSequence DcmTagKey(0x0046, 0x0215) +#define DCM_SimulatedKeratometricCylinderSequence DcmTagKey(0x0046, 0x0218) +#define DCM_AverageCornealPower DcmTagKey(0x0046, 0x0220) +#define DCM_CornealISValue DcmTagKey(0x0046, 0x0224) +#define DCM_AnalyzedArea DcmTagKey(0x0046, 0x0227) +#define DCM_SurfaceRegularityIndex DcmTagKey(0x0046, 0x0230) +#define DCM_SurfaceAsymmetryIndex DcmTagKey(0x0046, 0x0232) +#define DCM_CornealEccentricityIndex DcmTagKey(0x0046, 0x0234) +#define DCM_KeratoconusPredictionIndex DcmTagKey(0x0046, 0x0236) +#define DCM_DecimalPotentialVisualAcuity DcmTagKey(0x0046, 0x0238) +#define DCM_CornealTopographyMapQualityEvaluation DcmTagKey(0x0046, 0x0242) +#define DCM_SourceImageCornealProcessedDataSequence DcmTagKey(0x0046, 0x0244) +#define DCM_CornealPointLocation DcmTagKey(0x0046, 0x0247) +#define DCM_CornealPointEstimated DcmTagKey(0x0046, 0x0248) +#define DCM_AxialPower DcmTagKey(0x0046, 0x0249) +#define DCM_TangentialPower DcmTagKey(0x0046, 0x0250) +#define DCM_RefractivePower DcmTagKey(0x0046, 0x0251) +#define DCM_RelativeElevation DcmTagKey(0x0046, 0x0252) +#define DCM_CornealWavefront DcmTagKey(0x0046, 0x0253) +#define DCM_ImagedVolumeWidth DcmTagKey(0x0048, 0x0001) +#define DCM_ImagedVolumeHeight DcmTagKey(0x0048, 0x0002) +#define DCM_ImagedVolumeDepth DcmTagKey(0x0048, 0x0003) +#define DCM_TotalPixelMatrixColumns DcmTagKey(0x0048, 0x0006) +#define DCM_TotalPixelMatrixRows DcmTagKey(0x0048, 0x0007) +#define DCM_TotalPixelMatrixOriginSequence DcmTagKey(0x0048, 0x0008) +#define DCM_SpecimenLabelInImage DcmTagKey(0x0048, 0x0010) +#define DCM_FocusMethod DcmTagKey(0x0048, 0x0011) +#define DCM_ExtendedDepthOfField DcmTagKey(0x0048, 0x0012) +#define DCM_NumberOfFocalPlanes DcmTagKey(0x0048, 0x0013) +#define DCM_DistanceBetweenFocalPlanes DcmTagKey(0x0048, 0x0014) +#define DCM_RecommendedAbsentPixelCIELabValue DcmTagKey(0x0048, 0x0015) +#define DCM_IlluminatorTypeCodeSequence DcmTagKey(0x0048, 0x0100) +#define DCM_ImageOrientationSlide DcmTagKey(0x0048, 0x0102) +#define DCM_OpticalPathSequence DcmTagKey(0x0048, 0x0105) +#define DCM_OpticalPathIdentifier DcmTagKey(0x0048, 0x0106) +#define DCM_OpticalPathDescription DcmTagKey(0x0048, 0x0107) +#define DCM_IlluminationColorCodeSequence DcmTagKey(0x0048, 0x0108) +#define DCM_SpecimenReferenceSequence DcmTagKey(0x0048, 0x0110) +#define DCM_CondenserLensPower DcmTagKey(0x0048, 0x0111) +#define DCM_ObjectiveLensPower DcmTagKey(0x0048, 0x0112) +#define DCM_ObjectiveLensNumericalAperture DcmTagKey(0x0048, 0x0113) +#define DCM_PaletteColorLookupTableSequence DcmTagKey(0x0048, 0x0120) +#define DCM_ReferencedImageNavigationSequence DcmTagKey(0x0048, 0x0200) +#define DCM_TopLeftHandCornerOfLocalizerArea DcmTagKey(0x0048, 0x0201) +#define DCM_BottomRightHandCornerOfLocalizerArea DcmTagKey(0x0048, 0x0202) +#define DCM_OpticalPathIdentificationSequence DcmTagKey(0x0048, 0x0207) +#define DCM_PlanePositionSlideSequence DcmTagKey(0x0048, 0x021a) +#define DCM_ColumnPositionInTotalImagePixelMatrix DcmTagKey(0x0048, 0x021e) +#define DCM_RowPositionInTotalImagePixelMatrix DcmTagKey(0x0048, 0x021f) +#define DCM_PixelOriginInterpretation DcmTagKey(0x0048, 0x0301) +#define DCM_CalibrationImage DcmTagKey(0x0050, 0x0004) +#define DCM_DeviceSequence DcmTagKey(0x0050, 0x0010) +#define DCM_ContainerComponentTypeCodeSequence DcmTagKey(0x0050, 0x0012) +#define DCM_ContainerComponentThickness DcmTagKey(0x0050, 0x0013) +#define DCM_DeviceLength DcmTagKey(0x0050, 0x0014) +#define DCM_ContainerComponentWidth DcmTagKey(0x0050, 0x0015) +#define DCM_DeviceDiameter DcmTagKey(0x0050, 0x0016) +#define DCM_DeviceDiameterUnits DcmTagKey(0x0050, 0x0017) +#define DCM_DeviceVolume DcmTagKey(0x0050, 0x0018) +#define DCM_InterMarkerDistance DcmTagKey(0x0050, 0x0019) +#define DCM_ContainerComponentMaterial DcmTagKey(0x0050, 0x001a) +#define DCM_ContainerComponentID DcmTagKey(0x0050, 0x001b) +#define DCM_ContainerComponentLength DcmTagKey(0x0050, 0x001c) +#define DCM_ContainerComponentDiameter DcmTagKey(0x0050, 0x001d) +#define DCM_ContainerComponentDescription DcmTagKey(0x0050, 0x001e) +#define DCM_DeviceDescription DcmTagKey(0x0050, 0x0020) +#define DCM_ContrastBolusIngredientPercentByVolume DcmTagKey(0x0052, 0x0001) +#define DCM_OCTFocalDistance DcmTagKey(0x0052, 0x0002) +#define DCM_BeamSpotSize DcmTagKey(0x0052, 0x0003) +#define DCM_EffectiveRefractiveIndex DcmTagKey(0x0052, 0x0004) +#define DCM_OCTAcquisitionDomain DcmTagKey(0x0052, 0x0006) +#define DCM_OCTOpticalCenterWavelength DcmTagKey(0x0052, 0x0007) +#define DCM_AxialResolution DcmTagKey(0x0052, 0x0008) +#define DCM_RangingDepth DcmTagKey(0x0052, 0x0009) +#define DCM_ALineRate DcmTagKey(0x0052, 0x0011) +#define DCM_ALinesPerFrame DcmTagKey(0x0052, 0x0012) +#define DCM_CatheterRotationalRate DcmTagKey(0x0052, 0x0013) +#define DCM_ALinePixelSpacing DcmTagKey(0x0052, 0x0014) +#define DCM_ModeOfPercutaneousAccessSequence DcmTagKey(0x0052, 0x0016) +#define DCM_IntravascularOCTFrameTypeSequence DcmTagKey(0x0052, 0x0025) +#define DCM_OCTZOffsetApplied DcmTagKey(0x0052, 0x0026) +#define DCM_IntravascularFrameContentSequence DcmTagKey(0x0052, 0x0027) +#define DCM_IntravascularLongitudinalDistance DcmTagKey(0x0052, 0x0028) +#define DCM_IntravascularOCTFrameContentSequence DcmTagKey(0x0052, 0x0029) +#define DCM_OCTZOffsetCorrection DcmTagKey(0x0052, 0x0030) +#define DCM_CatheterDirectionOfRotation DcmTagKey(0x0052, 0x0031) +#define DCM_SeamLineLocation DcmTagKey(0x0052, 0x0033) +#define DCM_FirstALineLocation DcmTagKey(0x0052, 0x0034) +#define DCM_SeamLineIndex DcmTagKey(0x0052, 0x0036) +#define DCM_NumberOfPaddedALines DcmTagKey(0x0052, 0x0038) +#define DCM_InterpolationType DcmTagKey(0x0052, 0x0039) +#define DCM_RefractiveIndexApplied DcmTagKey(0x0052, 0x003a) +#define DCM_EnergyWindowVector DcmTagKey(0x0054, 0x0010) +#define DCM_NumberOfEnergyWindows DcmTagKey(0x0054, 0x0011) +#define DCM_EnergyWindowInformationSequence DcmTagKey(0x0054, 0x0012) +#define DCM_EnergyWindowRangeSequence DcmTagKey(0x0054, 0x0013) +#define DCM_EnergyWindowLowerLimit DcmTagKey(0x0054, 0x0014) +#define DCM_EnergyWindowUpperLimit DcmTagKey(0x0054, 0x0015) +#define DCM_RadiopharmaceuticalInformationSequence DcmTagKey(0x0054, 0x0016) +#define DCM_ResidualSyringeCounts DcmTagKey(0x0054, 0x0017) +#define DCM_EnergyWindowName DcmTagKey(0x0054, 0x0018) +#define DCM_DetectorVector DcmTagKey(0x0054, 0x0020) +#define DCM_NumberOfDetectors DcmTagKey(0x0054, 0x0021) +#define DCM_DetectorInformationSequence DcmTagKey(0x0054, 0x0022) +#define DCM_PhaseVector DcmTagKey(0x0054, 0x0030) +#define DCM_NumberOfPhases DcmTagKey(0x0054, 0x0031) +#define DCM_PhaseInformationSequence DcmTagKey(0x0054, 0x0032) +#define DCM_NumberOfFramesInPhase DcmTagKey(0x0054, 0x0033) +#define DCM_PhaseDelay DcmTagKey(0x0054, 0x0036) +#define DCM_PauseBetweenFrames DcmTagKey(0x0054, 0x0038) +#define DCM_PhaseDescription DcmTagKey(0x0054, 0x0039) +#define DCM_RotationVector DcmTagKey(0x0054, 0x0050) +#define DCM_NumberOfRotations DcmTagKey(0x0054, 0x0051) +#define DCM_RotationInformationSequence DcmTagKey(0x0054, 0x0052) +#define DCM_NumberOfFramesInRotation DcmTagKey(0x0054, 0x0053) +#define DCM_RRIntervalVector DcmTagKey(0x0054, 0x0060) +#define DCM_NumberOfRRIntervals DcmTagKey(0x0054, 0x0061) +#define DCM_GatedInformationSequence DcmTagKey(0x0054, 0x0062) +#define DCM_DataInformationSequence DcmTagKey(0x0054, 0x0063) +#define DCM_TimeSlotVector DcmTagKey(0x0054, 0x0070) +#define DCM_NumberOfTimeSlots DcmTagKey(0x0054, 0x0071) +#define DCM_TimeSlotInformationSequence DcmTagKey(0x0054, 0x0072) +#define DCM_TimeSlotTime DcmTagKey(0x0054, 0x0073) +#define DCM_SliceVector DcmTagKey(0x0054, 0x0080) +#define DCM_NumberOfSlices DcmTagKey(0x0054, 0x0081) +#define DCM_AngularViewVector DcmTagKey(0x0054, 0x0090) +#define DCM_TimeSliceVector DcmTagKey(0x0054, 0x0100) +#define DCM_NumberOfTimeSlices DcmTagKey(0x0054, 0x0101) +#define DCM_StartAngle DcmTagKey(0x0054, 0x0200) +#define DCM_TypeOfDetectorMotion DcmTagKey(0x0054, 0x0202) +#define DCM_TriggerVector DcmTagKey(0x0054, 0x0210) +#define DCM_NumberOfTriggersInPhase DcmTagKey(0x0054, 0x0211) +#define DCM_ViewCodeSequence DcmTagKey(0x0054, 0x0220) +#define DCM_ViewModifierCodeSequence DcmTagKey(0x0054, 0x0222) +#define DCM_RadionuclideCodeSequence DcmTagKey(0x0054, 0x0300) +#define DCM_AdministrationRouteCodeSequence DcmTagKey(0x0054, 0x0302) +#define DCM_RadiopharmaceuticalCodeSequence DcmTagKey(0x0054, 0x0304) +#define DCM_CalibrationDataSequence DcmTagKey(0x0054, 0x0306) +#define DCM_EnergyWindowNumber DcmTagKey(0x0054, 0x0308) +#define DCM_ImageID DcmTagKey(0x0054, 0x0400) +#define DCM_PatientOrientationCodeSequence DcmTagKey(0x0054, 0x0410) +#define DCM_PatientOrientationModifierCodeSequence DcmTagKey(0x0054, 0x0412) +#define DCM_PatientGantryRelationshipCodeSequence DcmTagKey(0x0054, 0x0414) +#define DCM_SliceProgressionDirection DcmTagKey(0x0054, 0x0500) +#define DCM_ScanProgressionDirection DcmTagKey(0x0054, 0x0501) +#define DCM_SeriesType DcmTagKey(0x0054, 0x1000) +#define DCM_Units DcmTagKey(0x0054, 0x1001) +#define DCM_CountsSource DcmTagKey(0x0054, 0x1002) +#define DCM_ReprojectionMethod DcmTagKey(0x0054, 0x1004) +#define DCM_SUVType DcmTagKey(0x0054, 0x1006) +#define DCM_RandomsCorrectionMethod DcmTagKey(0x0054, 0x1100) +#define DCM_AttenuationCorrectionMethod DcmTagKey(0x0054, 0x1101) +#define DCM_DecayCorrection DcmTagKey(0x0054, 0x1102) +#define DCM_ReconstructionMethod DcmTagKey(0x0054, 0x1103) +#define DCM_DetectorLinesOfResponseUsed DcmTagKey(0x0054, 0x1104) +#define DCM_ScatterCorrectionMethod DcmTagKey(0x0054, 0x1105) +#define DCM_AxialAcceptance DcmTagKey(0x0054, 0x1200) +#define DCM_AxialMash DcmTagKey(0x0054, 0x1201) +#define DCM_TransverseMash DcmTagKey(0x0054, 0x1202) +#define DCM_DetectorElementSize DcmTagKey(0x0054, 0x1203) +#define DCM_CoincidenceWindowWidth DcmTagKey(0x0054, 0x1210) +#define DCM_SecondaryCountsType DcmTagKey(0x0054, 0x1220) +#define DCM_FrameReferenceTime DcmTagKey(0x0054, 0x1300) +#define DCM_PrimaryPromptsCountsAccumulated DcmTagKey(0x0054, 0x1310) +#define DCM_SecondaryCountsAccumulated DcmTagKey(0x0054, 0x1311) +#define DCM_SliceSensitivityFactor DcmTagKey(0x0054, 0x1320) +#define DCM_DecayFactor DcmTagKey(0x0054, 0x1321) +#define DCM_DoseCalibrationFactor DcmTagKey(0x0054, 0x1322) +#define DCM_ScatterFractionFactor DcmTagKey(0x0054, 0x1323) +#define DCM_DeadTimeFactor DcmTagKey(0x0054, 0x1324) +#define DCM_ImageIndex DcmTagKey(0x0054, 0x1330) +#define DCM_RETIRED_CountsIncluded DcmTagKey(0x0054, 0x1400) +#define DCM_RETIRED_DeadTimeCorrectionFlag DcmTagKey(0x0054, 0x1401) +#define DCM_HistogramSequence DcmTagKey(0x0060, 0x3000) +#define DCM_HistogramNumberOfBins DcmTagKey(0x0060, 0x3002) +#define DCM_HistogramFirstBinValue DcmTagKey(0x0060, 0x3004) +#define DCM_HistogramLastBinValue DcmTagKey(0x0060, 0x3006) +#define DCM_HistogramBinWidth DcmTagKey(0x0060, 0x3008) +#define DCM_HistogramExplanation DcmTagKey(0x0060, 0x3010) +#define DCM_HistogramData DcmTagKey(0x0060, 0x3020) +#define DCM_SegmentationType DcmTagKey(0x0062, 0x0001) +#define DCM_SegmentSequence DcmTagKey(0x0062, 0x0002) +#define DCM_SegmentedPropertyCategoryCodeSequence DcmTagKey(0x0062, 0x0003) +#define DCM_SegmentNumber DcmTagKey(0x0062, 0x0004) +#define DCM_SegmentLabel DcmTagKey(0x0062, 0x0005) +#define DCM_SegmentDescription DcmTagKey(0x0062, 0x0006) +#define DCM_SegmentAlgorithmType DcmTagKey(0x0062, 0x0008) +#define DCM_SegmentAlgorithmName DcmTagKey(0x0062, 0x0009) +#define DCM_SegmentIdentificationSequence DcmTagKey(0x0062, 0x000a) +#define DCM_ReferencedSegmentNumber DcmTagKey(0x0062, 0x000b) +#define DCM_RecommendedDisplayGrayscaleValue DcmTagKey(0x0062, 0x000c) +#define DCM_RecommendedDisplayCIELabValue DcmTagKey(0x0062, 0x000d) +#define DCM_MaximumFractionalValue DcmTagKey(0x0062, 0x000e) +#define DCM_SegmentedPropertyTypeCodeSequence DcmTagKey(0x0062, 0x000f) +#define DCM_SegmentationFractionalType DcmTagKey(0x0062, 0x0010) +#define DCM_SegmentedPropertyTypeModifierCodeSequence DcmTagKey(0x0062, 0x0011) +#define DCM_UsedSegmentsSequence DcmTagKey(0x0062, 0x0012) +#define DCM_DeformableRegistrationSequence DcmTagKey(0x0064, 0x0002) +#define DCM_SourceFrameOfReferenceUID DcmTagKey(0x0064, 0x0003) +#define DCM_DeformableRegistrationGridSequence DcmTagKey(0x0064, 0x0005) +#define DCM_GridDimensions DcmTagKey(0x0064, 0x0007) +#define DCM_GridResolution DcmTagKey(0x0064, 0x0008) +#define DCM_VectorGridData DcmTagKey(0x0064, 0x0009) +#define DCM_PreDeformationMatrixRegistrationSequence DcmTagKey(0x0064, 0x000f) +#define DCM_PostDeformationMatrixRegistrationSequence DcmTagKey(0x0064, 0x0010) +#define DCM_NumberOfSurfaces DcmTagKey(0x0066, 0x0001) +#define DCM_SurfaceSequence DcmTagKey(0x0066, 0x0002) +#define DCM_SurfaceNumber DcmTagKey(0x0066, 0x0003) +#define DCM_SurfaceComments DcmTagKey(0x0066, 0x0004) +#define DCM_SurfaceProcessing DcmTagKey(0x0066, 0x0009) +#define DCM_SurfaceProcessingRatio DcmTagKey(0x0066, 0x000a) +#define DCM_SurfaceProcessingDescription DcmTagKey(0x0066, 0x000b) +#define DCM_RecommendedPresentationOpacity DcmTagKey(0x0066, 0x000c) +#define DCM_RecommendedPresentationType DcmTagKey(0x0066, 0x000d) +#define DCM_FiniteVolume DcmTagKey(0x0066, 0x000e) +#define DCM_Manifold DcmTagKey(0x0066, 0x0010) +#define DCM_SurfacePointsSequence DcmTagKey(0x0066, 0x0011) +#define DCM_SurfacePointsNormalsSequence DcmTagKey(0x0066, 0x0012) +#define DCM_SurfaceMeshPrimitivesSequence DcmTagKey(0x0066, 0x0013) +#define DCM_NumberOfSurfacePoints DcmTagKey(0x0066, 0x0015) +#define DCM_PointCoordinatesData DcmTagKey(0x0066, 0x0016) +#define DCM_PointPositionAccuracy DcmTagKey(0x0066, 0x0017) +#define DCM_MeanPointDistance DcmTagKey(0x0066, 0x0018) +#define DCM_MaximumPointDistance DcmTagKey(0x0066, 0x0019) +#define DCM_PointsBoundingBoxCoordinates DcmTagKey(0x0066, 0x001a) +#define DCM_AxisOfRotation DcmTagKey(0x0066, 0x001b) +#define DCM_CenterOfRotation DcmTagKey(0x0066, 0x001c) +#define DCM_NumberOfVectors DcmTagKey(0x0066, 0x001e) +#define DCM_VectorDimensionality DcmTagKey(0x0066, 0x001f) +#define DCM_VectorAccuracy DcmTagKey(0x0066, 0x0020) +#define DCM_VectorCoordinateData DcmTagKey(0x0066, 0x0021) +#define DCM_TrianglePointIndexList DcmTagKey(0x0066, 0x0023) +#define DCM_EdgePointIndexList DcmTagKey(0x0066, 0x0024) +#define DCM_VertexPointIndexList DcmTagKey(0x0066, 0x0025) +#define DCM_TriangleStripSequence DcmTagKey(0x0066, 0x0026) +#define DCM_TriangleFanSequence DcmTagKey(0x0066, 0x0027) +#define DCM_LineSequence DcmTagKey(0x0066, 0x0028) +#define DCM_PrimitivePointIndexList DcmTagKey(0x0066, 0x0029) +#define DCM_SurfaceCount DcmTagKey(0x0066, 0x002a) +#define DCM_ReferencedSurfaceSequence DcmTagKey(0x0066, 0x002b) +#define DCM_ReferencedSurfaceNumber DcmTagKey(0x0066, 0x002c) +#define DCM_SegmentSurfaceGenerationAlgorithmIdentificationSequence DcmTagKey(0x0066, 0x002d) +#define DCM_SegmentSurfaceSourceInstanceSequence DcmTagKey(0x0066, 0x002e) +#define DCM_AlgorithmFamilyCodeSequence DcmTagKey(0x0066, 0x002f) +#define DCM_AlgorithmNameCodeSequence DcmTagKey(0x0066, 0x0030) +#define DCM_AlgorithmVersion DcmTagKey(0x0066, 0x0031) +#define DCM_AlgorithmParameters DcmTagKey(0x0066, 0x0032) +#define DCM_FacetSequence DcmTagKey(0x0066, 0x0034) +#define DCM_SurfaceProcessingAlgorithmIdentificationSequence DcmTagKey(0x0066, 0x0035) +#define DCM_AlgorithmName DcmTagKey(0x0066, 0x0036) +#define DCM_RecommendedPointRadius DcmTagKey(0x0066, 0x0037) +#define DCM_RecommendedLineThickness DcmTagKey(0x0066, 0x0038) +#define DCM_LongPrimitivePointIndexList DcmTagKey(0x0066, 0x0040) +#define DCM_LongTrianglePointIndexList DcmTagKey(0x0066, 0x0041) +#define DCM_LongEdgePointIndexList DcmTagKey(0x0066, 0x0042) +#define DCM_LongVertexPointIndexList DcmTagKey(0x0066, 0x0043) +#define DCM_ImplantSize DcmTagKey(0x0068, 0x6210) +#define DCM_ImplantTemplateVersion DcmTagKey(0x0068, 0x6221) +#define DCM_ReplacedImplantTemplateSequence DcmTagKey(0x0068, 0x6222) +#define DCM_ImplantType DcmTagKey(0x0068, 0x6223) +#define DCM_DerivationImplantTemplateSequence DcmTagKey(0x0068, 0x6224) +#define DCM_OriginalImplantTemplateSequence DcmTagKey(0x0068, 0x6225) +#define DCM_EffectiveDateTime DcmTagKey(0x0068, 0x6226) +#define DCM_ImplantTargetAnatomySequence DcmTagKey(0x0068, 0x6230) +#define DCM_InformationFromManufacturerSequence DcmTagKey(0x0068, 0x6260) +#define DCM_NotificationFromManufacturerSequence DcmTagKey(0x0068, 0x6265) +#define DCM_InformationIssueDateTime DcmTagKey(0x0068, 0x6270) +#define DCM_InformationSummary DcmTagKey(0x0068, 0x6280) +#define DCM_ImplantRegulatoryDisapprovalCodeSequence DcmTagKey(0x0068, 0x62a0) +#define DCM_OverallTemplateSpatialTolerance DcmTagKey(0x0068, 0x62a5) +#define DCM_HPGLDocumentSequence DcmTagKey(0x0068, 0x62c0) +#define DCM_HPGLDocumentID DcmTagKey(0x0068, 0x62d0) +#define DCM_HPGLDocumentLabel DcmTagKey(0x0068, 0x62d5) +#define DCM_ViewOrientationCodeSequence DcmTagKey(0x0068, 0x62e0) +#define DCM_ViewOrientationModifier DcmTagKey(0x0068, 0x62f0) +#define DCM_HPGLDocumentScaling DcmTagKey(0x0068, 0x62f2) +#define DCM_HPGLDocument DcmTagKey(0x0068, 0x6300) +#define DCM_HPGLContourPenNumber DcmTagKey(0x0068, 0x6310) +#define DCM_HPGLPenSequence DcmTagKey(0x0068, 0x6320) +#define DCM_HPGLPenNumber DcmTagKey(0x0068, 0x6330) +#define DCM_HPGLPenLabel DcmTagKey(0x0068, 0x6340) +#define DCM_HPGLPenDescription DcmTagKey(0x0068, 0x6345) +#define DCM_RecommendedRotationPoint DcmTagKey(0x0068, 0x6346) +#define DCM_BoundingRectangle DcmTagKey(0x0068, 0x6347) +#define DCM_ImplantTemplate3DModelSurfaceNumber DcmTagKey(0x0068, 0x6350) +#define DCM_SurfaceModelDescriptionSequence DcmTagKey(0x0068, 0x6360) +#define DCM_SurfaceModelLabel DcmTagKey(0x0068, 0x6380) +#define DCM_SurfaceModelScalingFactor DcmTagKey(0x0068, 0x6390) +#define DCM_MaterialsCodeSequence DcmTagKey(0x0068, 0x63a0) +#define DCM_CoatingMaterialsCodeSequence DcmTagKey(0x0068, 0x63a4) +#define DCM_ImplantTypeCodeSequence DcmTagKey(0x0068, 0x63a8) +#define DCM_FixationMethodCodeSequence DcmTagKey(0x0068, 0x63ac) +#define DCM_MatingFeatureSetsSequence DcmTagKey(0x0068, 0x63b0) +#define DCM_MatingFeatureSetID DcmTagKey(0x0068, 0x63c0) +#define DCM_MatingFeatureSetLabel DcmTagKey(0x0068, 0x63d0) +#define DCM_MatingFeatureSequence DcmTagKey(0x0068, 0x63e0) +#define DCM_MatingFeatureID DcmTagKey(0x0068, 0x63f0) +#define DCM_MatingFeatureDegreeOfFreedomSequence DcmTagKey(0x0068, 0x6400) +#define DCM_DegreeOfFreedomID DcmTagKey(0x0068, 0x6410) +#define DCM_DegreeOfFreedomType DcmTagKey(0x0068, 0x6420) +#define DCM_TwoDMatingFeatureCoordinatesSequence DcmTagKey(0x0068, 0x6430) +#define DCM_ReferencedHPGLDocumentID DcmTagKey(0x0068, 0x6440) +#define DCM_TwoDMatingPoint DcmTagKey(0x0068, 0x6450) +#define DCM_TwoDMatingAxes DcmTagKey(0x0068, 0x6460) +#define DCM_TwoDDegreeOfFreedomSequence DcmTagKey(0x0068, 0x6470) +#define DCM_ThreeDDegreeOfFreedomAxis DcmTagKey(0x0068, 0x6490) +#define DCM_RangeOfFreedom DcmTagKey(0x0068, 0x64a0) +#define DCM_ThreeDMatingPoint DcmTagKey(0x0068, 0x64c0) +#define DCM_ThreeDMatingAxes DcmTagKey(0x0068, 0x64d0) +#define DCM_TwoDDegreeOfFreedomAxis DcmTagKey(0x0068, 0x64f0) +#define DCM_PlanningLandmarkPointSequence DcmTagKey(0x0068, 0x6500) +#define DCM_PlanningLandmarkLineSequence DcmTagKey(0x0068, 0x6510) +#define DCM_PlanningLandmarkPlaneSequence DcmTagKey(0x0068, 0x6520) +#define DCM_PlanningLandmarkID DcmTagKey(0x0068, 0x6530) +#define DCM_PlanningLandmarkDescription DcmTagKey(0x0068, 0x6540) +#define DCM_PlanningLandmarkIdentificationCodeSequence DcmTagKey(0x0068, 0x6545) +#define DCM_TwoDPointCoordinatesSequence DcmTagKey(0x0068, 0x6550) +#define DCM_TwoDPointCoordinates DcmTagKey(0x0068, 0x6560) +#define DCM_ThreeDPointCoordinates DcmTagKey(0x0068, 0x6590) +#define DCM_TwoDLineCoordinatesSequence DcmTagKey(0x0068, 0x65a0) +#define DCM_TwoDLineCoordinates DcmTagKey(0x0068, 0x65b0) +#define DCM_ThreeDLineCoordinates DcmTagKey(0x0068, 0x65d0) +#define DCM_TwoDPlaneCoordinatesSequence DcmTagKey(0x0068, 0x65e0) +#define DCM_TwoDPlaneIntersection DcmTagKey(0x0068, 0x65f0) +#define DCM_ThreeDPlaneOrigin DcmTagKey(0x0068, 0x6610) +#define DCM_ThreeDPlaneNormal DcmTagKey(0x0068, 0x6620) +#define DCM_GraphicAnnotationSequence DcmTagKey(0x0070, 0x0001) +#define DCM_GraphicLayer DcmTagKey(0x0070, 0x0002) +#define DCM_BoundingBoxAnnotationUnits DcmTagKey(0x0070, 0x0003) +#define DCM_AnchorPointAnnotationUnits DcmTagKey(0x0070, 0x0004) +#define DCM_GraphicAnnotationUnits DcmTagKey(0x0070, 0x0005) +#define DCM_UnformattedTextValue DcmTagKey(0x0070, 0x0006) +#define DCM_TextObjectSequence DcmTagKey(0x0070, 0x0008) +#define DCM_GraphicObjectSequence DcmTagKey(0x0070, 0x0009) +#define DCM_BoundingBoxTopLeftHandCorner DcmTagKey(0x0070, 0x0010) +#define DCM_BoundingBoxBottomRightHandCorner DcmTagKey(0x0070, 0x0011) +#define DCM_BoundingBoxTextHorizontalJustification DcmTagKey(0x0070, 0x0012) +#define DCM_AnchorPoint DcmTagKey(0x0070, 0x0014) +#define DCM_AnchorPointVisibility DcmTagKey(0x0070, 0x0015) +#define DCM_GraphicDimensions DcmTagKey(0x0070, 0x0020) +#define DCM_NumberOfGraphicPoints DcmTagKey(0x0070, 0x0021) +#define DCM_GraphicData DcmTagKey(0x0070, 0x0022) +#define DCM_GraphicType DcmTagKey(0x0070, 0x0023) +#define DCM_GraphicFilled DcmTagKey(0x0070, 0x0024) +#define DCM_RETIRED_ImageRotationRetired DcmTagKey(0x0070, 0x0040) +#define DCM_ImageHorizontalFlip DcmTagKey(0x0070, 0x0041) +#define DCM_ImageRotation DcmTagKey(0x0070, 0x0042) +#define DCM_RETIRED_DisplayedAreaTopLeftHandCornerTrial DcmTagKey(0x0070, 0x0050) +#define DCM_RETIRED_DisplayedAreaBottomRightHandCornerTrial DcmTagKey(0x0070, 0x0051) +#define DCM_DisplayedAreaTopLeftHandCorner DcmTagKey(0x0070, 0x0052) +#define DCM_DisplayedAreaBottomRightHandCorner DcmTagKey(0x0070, 0x0053) +#define DCM_DisplayedAreaSelectionSequence DcmTagKey(0x0070, 0x005a) +#define DCM_GraphicLayerSequence DcmTagKey(0x0070, 0x0060) +#define DCM_GraphicLayerOrder DcmTagKey(0x0070, 0x0062) +#define DCM_GraphicLayerRecommendedDisplayGrayscaleValue DcmTagKey(0x0070, 0x0066) +#define DCM_RETIRED_GraphicLayerRecommendedDisplayRGBValue DcmTagKey(0x0070, 0x0067) +#define DCM_GraphicLayerDescription DcmTagKey(0x0070, 0x0068) +#define DCM_ContentLabel DcmTagKey(0x0070, 0x0080) +#define DCM_ContentDescription DcmTagKey(0x0070, 0x0081) +#define DCM_PresentationCreationDate DcmTagKey(0x0070, 0x0082) +#define DCM_PresentationCreationTime DcmTagKey(0x0070, 0x0083) +#define DCM_ContentCreatorName DcmTagKey(0x0070, 0x0084) +#define DCM_ContentCreatorIdentificationCodeSequence DcmTagKey(0x0070, 0x0086) +#define DCM_AlternateContentDescriptionSequence DcmTagKey(0x0070, 0x0087) +#define DCM_PresentationSizeMode DcmTagKey(0x0070, 0x0100) +#define DCM_PresentationPixelSpacing DcmTagKey(0x0070, 0x0101) +#define DCM_PresentationPixelAspectRatio DcmTagKey(0x0070, 0x0102) +#define DCM_PresentationPixelMagnificationRatio DcmTagKey(0x0070, 0x0103) +#define DCM_GraphicGroupLabel DcmTagKey(0x0070, 0x0207) +#define DCM_GraphicGroupDescription DcmTagKey(0x0070, 0x0208) +#define DCM_CompoundGraphicSequence DcmTagKey(0x0070, 0x0209) +#define DCM_CompoundGraphicInstanceID DcmTagKey(0x0070, 0x0226) +#define DCM_FontName DcmTagKey(0x0070, 0x0227) +#define DCM_FontNameType DcmTagKey(0x0070, 0x0228) +#define DCM_CSSFontName DcmTagKey(0x0070, 0x0229) +#define DCM_RotationAngle DcmTagKey(0x0070, 0x0230) +#define DCM_TextStyleSequence DcmTagKey(0x0070, 0x0231) +#define DCM_LineStyleSequence DcmTagKey(0x0070, 0x0232) +#define DCM_FillStyleSequence DcmTagKey(0x0070, 0x0233) +#define DCM_GraphicGroupSequence DcmTagKey(0x0070, 0x0234) +#define DCM_TextColorCIELabValue DcmTagKey(0x0070, 0x0241) +#define DCM_HorizontalAlignment DcmTagKey(0x0070, 0x0242) +#define DCM_VerticalAlignment DcmTagKey(0x0070, 0x0243) +#define DCM_ShadowStyle DcmTagKey(0x0070, 0x0244) +#define DCM_ShadowOffsetX DcmTagKey(0x0070, 0x0245) +#define DCM_ShadowOffsetY DcmTagKey(0x0070, 0x0246) +#define DCM_ShadowColorCIELabValue DcmTagKey(0x0070, 0x0247) +#define DCM_Underlined DcmTagKey(0x0070, 0x0248) +#define DCM_Bold DcmTagKey(0x0070, 0x0249) +#define DCM_Italic DcmTagKey(0x0070, 0x0250) +#define DCM_PatternOnColorCIELabValue DcmTagKey(0x0070, 0x0251) +#define DCM_PatternOffColorCIELabValue DcmTagKey(0x0070, 0x0252) +#define DCM_LineThickness DcmTagKey(0x0070, 0x0253) +#define DCM_LineDashingStyle DcmTagKey(0x0070, 0x0254) +#define DCM_LinePattern DcmTagKey(0x0070, 0x0255) +#define DCM_FillPattern DcmTagKey(0x0070, 0x0256) +#define DCM_FillMode DcmTagKey(0x0070, 0x0257) +#define DCM_ShadowOpacity DcmTagKey(0x0070, 0x0258) +#define DCM_GapLength DcmTagKey(0x0070, 0x0261) +#define DCM_DiameterOfVisibility DcmTagKey(0x0070, 0x0262) +#define DCM_RotationPoint DcmTagKey(0x0070, 0x0273) +#define DCM_TickAlignment DcmTagKey(0x0070, 0x0274) +#define DCM_ShowTickLabel DcmTagKey(0x0070, 0x0278) +#define DCM_TickLabelAlignment DcmTagKey(0x0070, 0x0279) +#define DCM_CompoundGraphicUnits DcmTagKey(0x0070, 0x0282) +#define DCM_PatternOnOpacity DcmTagKey(0x0070, 0x0284) +#define DCM_PatternOffOpacity DcmTagKey(0x0070, 0x0285) +#define DCM_MajorTicksSequence DcmTagKey(0x0070, 0x0287) +#define DCM_TickPosition DcmTagKey(0x0070, 0x0288) +#define DCM_TickLabel DcmTagKey(0x0070, 0x0289) +#define DCM_CompoundGraphicType DcmTagKey(0x0070, 0x0294) +#define DCM_GraphicGroupID DcmTagKey(0x0070, 0x0295) +#define DCM_ShapeType DcmTagKey(0x0070, 0x0306) +#define DCM_RegistrationSequence DcmTagKey(0x0070, 0x0308) +#define DCM_MatrixRegistrationSequence DcmTagKey(0x0070, 0x0309) +#define DCM_MatrixSequence DcmTagKey(0x0070, 0x030a) +#define DCM_FrameOfReferenceTransformationMatrixType DcmTagKey(0x0070, 0x030c) +#define DCM_RegistrationTypeCodeSequence DcmTagKey(0x0070, 0x030d) +#define DCM_FiducialDescription DcmTagKey(0x0070, 0x030f) +#define DCM_FiducialIdentifier DcmTagKey(0x0070, 0x0310) +#define DCM_FiducialIdentifierCodeSequence DcmTagKey(0x0070, 0x0311) +#define DCM_ContourUncertaintyRadius DcmTagKey(0x0070, 0x0312) +#define DCM_UsedFiducialsSequence DcmTagKey(0x0070, 0x0314) +#define DCM_GraphicCoordinatesDataSequence DcmTagKey(0x0070, 0x0318) +#define DCM_FiducialUID DcmTagKey(0x0070, 0x031a) +#define DCM_FiducialSetSequence DcmTagKey(0x0070, 0x031c) +#define DCM_FiducialSequence DcmTagKey(0x0070, 0x031e) +#define DCM_GraphicLayerRecommendedDisplayCIELabValue DcmTagKey(0x0070, 0x0401) +#define DCM_BlendingSequence DcmTagKey(0x0070, 0x0402) +#define DCM_RelativeOpacity DcmTagKey(0x0070, 0x0403) +#define DCM_ReferencedSpatialRegistrationSequence DcmTagKey(0x0070, 0x0404) +#define DCM_BlendingPosition DcmTagKey(0x0070, 0x0405) +#define DCM_PresentationDisplayCollectionUID DcmTagKey(0x0070, 0x1101) +#define DCM_PresentationSequenceCollectionUID DcmTagKey(0x0070, 0x1102) +#define DCM_PresentationSequencePositionIndex DcmTagKey(0x0070, 0x1103) +#define DCM_RenderedImageReferenceSequence DcmTagKey(0x0070, 0x1104) +#define DCM_VolumetricPresentationStateInputSequence DcmTagKey(0x0070, 0x1201) +#define DCM_PresentationInputType DcmTagKey(0x0070, 0x1202) +#define DCM_InputSequencePositionIndex DcmTagKey(0x0070, 0x1203) +#define DCM_Crop DcmTagKey(0x0070, 0x1204) +#define DCM_CroppingSpecificationIndex DcmTagKey(0x0070, 0x1205) +#define DCM_CompositingMethod DcmTagKey(0x0070, 0x1206) +#define DCM_VolumetricPresentationInputNumber DcmTagKey(0x0070, 0x1207) +#define DCM_ImageVolumeGeometry DcmTagKey(0x0070, 0x1208) +#define DCM_VolumeCroppingSequence DcmTagKey(0x0070, 0x1301) +#define DCM_VolumeCroppingMethod DcmTagKey(0x0070, 0x1302) +#define DCM_BoundingBoxCrop DcmTagKey(0x0070, 0x1303) +#define DCM_ObliqueCroppingPlaneSequence DcmTagKey(0x0070, 0x1304) +#define DCM_ObliqueCroppingPlane DcmTagKey(0x0070, 0x1305) +#define DCM_ObliqueCroppingPlaneNormal DcmTagKey(0x0070, 0x1306) +#define DCM_CroppingSpecificationNumber DcmTagKey(0x0070, 0x1309) +#define DCM_MultiPlanarReconstructionStyle DcmTagKey(0x0070, 0x1501) +#define DCM_MPRThicknessType DcmTagKey(0x0070, 0x1502) +#define DCM_MPRSlabThickness DcmTagKey(0x0070, 0x1503) +#define DCM_MPRTopLeftHandCorner DcmTagKey(0x0070, 0x1505) +#define DCM_MPRViewWidthDirection DcmTagKey(0x0070, 0x1507) +#define DCM_MPRViewWidth DcmTagKey(0x0070, 0x1508) +#define DCM_NumberOfVolumetricCurvePoints DcmTagKey(0x0070, 0x150c) +#define DCM_VolumetricCurvePoints DcmTagKey(0x0070, 0x150d) +#define DCM_MPRViewHeightDirection DcmTagKey(0x0070, 0x1511) +#define DCM_MPRViewHeight DcmTagKey(0x0070, 0x1512) +#define DCM_PresentationStateClassificationComponentSequence DcmTagKey(0x0070, 0x1801) +#define DCM_ComponentType DcmTagKey(0x0070, 0x1802) +#define DCM_ComponentInputSequence DcmTagKey(0x0070, 0x1803) +#define DCM_VolumetricPresentationInputIndex DcmTagKey(0x0070, 0x1804) +#define DCM_PresentationStateCompositorComponentSequence DcmTagKey(0x0070, 0x1805) +#define DCM_WeightingTransferFunctionSequence DcmTagKey(0x0070, 0x1806) +#define DCM_WeightingLookupTableDescriptor DcmTagKey(0x0070, 0x1807) +#define DCM_WeightingLookupTableData DcmTagKey(0x0070, 0x1808) +#define DCM_VolumetricAnnotationSequence DcmTagKey(0x0070, 0x1901) +#define DCM_ReferencedStructuredContextSequence DcmTagKey(0x0070, 0x1903) +#define DCM_ReferencedContentItem DcmTagKey(0x0070, 0x1904) +#define DCM_VolumetricPresentationInputAnnotationSequence DcmTagKey(0x0070, 0x1905) +#define DCM_AnnotationClipping DcmTagKey(0x0070, 0x1907) +#define DCM_PresentationAnimationStyle DcmTagKey(0x0070, 0x1a01) +#define DCM_RecommendedAnimationRate DcmTagKey(0x0070, 0x1a03) +#define DCM_AnimationCurveSequence DcmTagKey(0x0070, 0x1a04) +#define DCM_AnimationStepSize DcmTagKey(0x0070, 0x1a05) +#define DCM_HangingProtocolName DcmTagKey(0x0072, 0x0002) +#define DCM_HangingProtocolDescription DcmTagKey(0x0072, 0x0004) +#define DCM_HangingProtocolLevel DcmTagKey(0x0072, 0x0006) +#define DCM_HangingProtocolCreator DcmTagKey(0x0072, 0x0008) +#define DCM_HangingProtocolCreationDateTime DcmTagKey(0x0072, 0x000a) +#define DCM_HangingProtocolDefinitionSequence DcmTagKey(0x0072, 0x000c) +#define DCM_HangingProtocolUserIdentificationCodeSequence DcmTagKey(0x0072, 0x000e) +#define DCM_HangingProtocolUserGroupName DcmTagKey(0x0072, 0x0010) +#define DCM_SourceHangingProtocolSequence DcmTagKey(0x0072, 0x0012) +#define DCM_NumberOfPriorsReferenced DcmTagKey(0x0072, 0x0014) +#define DCM_ImageSetsSequence DcmTagKey(0x0072, 0x0020) +#define DCM_ImageSetSelectorSequence DcmTagKey(0x0072, 0x0022) +#define DCM_ImageSetSelectorUsageFlag DcmTagKey(0x0072, 0x0024) +#define DCM_SelectorAttribute DcmTagKey(0x0072, 0x0026) +#define DCM_SelectorValueNumber DcmTagKey(0x0072, 0x0028) +#define DCM_TimeBasedImageSetsSequence DcmTagKey(0x0072, 0x0030) +#define DCM_ImageSetNumber DcmTagKey(0x0072, 0x0032) +#define DCM_ImageSetSelectorCategory DcmTagKey(0x0072, 0x0034) +#define DCM_RelativeTime DcmTagKey(0x0072, 0x0038) +#define DCM_RelativeTimeUnits DcmTagKey(0x0072, 0x003a) +#define DCM_AbstractPriorValue DcmTagKey(0x0072, 0x003c) +#define DCM_AbstractPriorCodeSequence DcmTagKey(0x0072, 0x003e) +#define DCM_ImageSetLabel DcmTagKey(0x0072, 0x0040) +#define DCM_SelectorAttributeVR DcmTagKey(0x0072, 0x0050) +#define DCM_SelectorSequencePointer DcmTagKey(0x0072, 0x0052) +#define DCM_SelectorSequencePointerPrivateCreator DcmTagKey(0x0072, 0x0054) +#define DCM_SelectorAttributePrivateCreator DcmTagKey(0x0072, 0x0056) +#define DCM_SelectorATValue DcmTagKey(0x0072, 0x0060) +#define DCM_SelectorCSValue DcmTagKey(0x0072, 0x0062) +#define DCM_SelectorISValue DcmTagKey(0x0072, 0x0064) +#define DCM_SelectorLOValue DcmTagKey(0x0072, 0x0066) +#define DCM_SelectorLTValue DcmTagKey(0x0072, 0x0068) +#define DCM_SelectorPNValue DcmTagKey(0x0072, 0x006a) +#define DCM_SelectorSHValue DcmTagKey(0x0072, 0x006c) +#define DCM_SelectorSTValue DcmTagKey(0x0072, 0x006e) +#define DCM_SelectorUTValue DcmTagKey(0x0072, 0x0070) +#define DCM_SelectorDSValue DcmTagKey(0x0072, 0x0072) +#define DCM_SelectorFDValue DcmTagKey(0x0072, 0x0074) +#define DCM_SelectorFLValue DcmTagKey(0x0072, 0x0076) +#define DCM_SelectorULValue DcmTagKey(0x0072, 0x0078) +#define DCM_SelectorUSValue DcmTagKey(0x0072, 0x007a) +#define DCM_SelectorSLValue DcmTagKey(0x0072, 0x007c) +#define DCM_SelectorSSValue DcmTagKey(0x0072, 0x007e) +#define DCM_SelectorUIValue DcmTagKey(0x0072, 0x007f) +#define DCM_SelectorCodeSequenceValue DcmTagKey(0x0072, 0x0080) +#define DCM_NumberOfScreens DcmTagKey(0x0072, 0x0100) +#define DCM_NominalScreenDefinitionSequence DcmTagKey(0x0072, 0x0102) +#define DCM_NumberOfVerticalPixels DcmTagKey(0x0072, 0x0104) +#define DCM_NumberOfHorizontalPixels DcmTagKey(0x0072, 0x0106) +#define DCM_DisplayEnvironmentSpatialPosition DcmTagKey(0x0072, 0x0108) +#define DCM_ScreenMinimumGrayscaleBitDepth DcmTagKey(0x0072, 0x010a) +#define DCM_ScreenMinimumColorBitDepth DcmTagKey(0x0072, 0x010c) +#define DCM_ApplicationMaximumRepaintTime DcmTagKey(0x0072, 0x010e) +#define DCM_DisplaySetsSequence DcmTagKey(0x0072, 0x0200) +#define DCM_DisplaySetNumber DcmTagKey(0x0072, 0x0202) +#define DCM_DisplaySetLabel DcmTagKey(0x0072, 0x0203) +#define DCM_DisplaySetPresentationGroup DcmTagKey(0x0072, 0x0204) +#define DCM_DisplaySetPresentationGroupDescription DcmTagKey(0x0072, 0x0206) +#define DCM_PartialDataDisplayHandling DcmTagKey(0x0072, 0x0208) +#define DCM_SynchronizedScrollingSequence DcmTagKey(0x0072, 0x0210) +#define DCM_DisplaySetScrollingGroup DcmTagKey(0x0072, 0x0212) +#define DCM_NavigationIndicatorSequence DcmTagKey(0x0072, 0x0214) +#define DCM_NavigationDisplaySet DcmTagKey(0x0072, 0x0216) +#define DCM_ReferenceDisplaySets DcmTagKey(0x0072, 0x0218) +#define DCM_ImageBoxesSequence DcmTagKey(0x0072, 0x0300) +#define DCM_ImageBoxNumber DcmTagKey(0x0072, 0x0302) +#define DCM_ImageBoxLayoutType DcmTagKey(0x0072, 0x0304) +#define DCM_ImageBoxTileHorizontalDimension DcmTagKey(0x0072, 0x0306) +#define DCM_ImageBoxTileVerticalDimension DcmTagKey(0x0072, 0x0308) +#define DCM_ImageBoxScrollDirection DcmTagKey(0x0072, 0x0310) +#define DCM_ImageBoxSmallScrollType DcmTagKey(0x0072, 0x0312) +#define DCM_ImageBoxSmallScrollAmount DcmTagKey(0x0072, 0x0314) +#define DCM_ImageBoxLargeScrollType DcmTagKey(0x0072, 0x0316) +#define DCM_ImageBoxLargeScrollAmount DcmTagKey(0x0072, 0x0318) +#define DCM_ImageBoxOverlapPriority DcmTagKey(0x0072, 0x0320) +#define DCM_CineRelativeToRealTime DcmTagKey(0x0072, 0x0330) +#define DCM_FilterOperationsSequence DcmTagKey(0x0072, 0x0400) +#define DCM_FilterByCategory DcmTagKey(0x0072, 0x0402) +#define DCM_FilterByAttributePresence DcmTagKey(0x0072, 0x0404) +#define DCM_FilterByOperator DcmTagKey(0x0072, 0x0406) +#define DCM_StructuredDisplayBackgroundCIELabValue DcmTagKey(0x0072, 0x0420) +#define DCM_EmptyImageBoxCIELabValue DcmTagKey(0x0072, 0x0421) +#define DCM_StructuredDisplayImageBoxSequence DcmTagKey(0x0072, 0x0422) +#define DCM_StructuredDisplayTextBoxSequence DcmTagKey(0x0072, 0x0424) +#define DCM_ReferencedFirstFrameSequence DcmTagKey(0x0072, 0x0427) +#define DCM_ImageBoxSynchronizationSequence DcmTagKey(0x0072, 0x0430) +#define DCM_SynchronizedImageBoxList DcmTagKey(0x0072, 0x0432) +#define DCM_TypeOfSynchronization DcmTagKey(0x0072, 0x0434) +#define DCM_BlendingOperationType DcmTagKey(0x0072, 0x0500) +#define DCM_ReformattingOperationType DcmTagKey(0x0072, 0x0510) +#define DCM_ReformattingThickness DcmTagKey(0x0072, 0x0512) +#define DCM_ReformattingInterval DcmTagKey(0x0072, 0x0514) +#define DCM_ReformattingOperationInitialViewDirection DcmTagKey(0x0072, 0x0516) +#define DCM_ThreeDRenderingType DcmTagKey(0x0072, 0x0520) +#define DCM_SortingOperationsSequence DcmTagKey(0x0072, 0x0600) +#define DCM_SortByCategory DcmTagKey(0x0072, 0x0602) +#define DCM_SortingDirection DcmTagKey(0x0072, 0x0604) +#define DCM_DisplaySetPatientOrientation DcmTagKey(0x0072, 0x0700) +#define DCM_VOIType DcmTagKey(0x0072, 0x0702) +#define DCM_PseudoColorType DcmTagKey(0x0072, 0x0704) +#define DCM_PseudoColorPaletteInstanceReferenceSequence DcmTagKey(0x0072, 0x0705) +#define DCM_ShowGrayscaleInverted DcmTagKey(0x0072, 0x0706) +#define DCM_ShowImageTrueSizeFlag DcmTagKey(0x0072, 0x0710) +#define DCM_ShowGraphicAnnotationFlag DcmTagKey(0x0072, 0x0712) +#define DCM_ShowPatientDemographicsFlag DcmTagKey(0x0072, 0x0714) +#define DCM_ShowAcquisitionTechniquesFlag DcmTagKey(0x0072, 0x0716) +#define DCM_DisplaySetHorizontalJustification DcmTagKey(0x0072, 0x0717) +#define DCM_DisplaySetVerticalJustification DcmTagKey(0x0072, 0x0718) +#define DCM_ContinuationStartMeterset DcmTagKey(0x0074, 0x0120) +#define DCM_ContinuationEndMeterset DcmTagKey(0x0074, 0x0121) +#define DCM_ProcedureStepState DcmTagKey(0x0074, 0x1000) +#define DCM_ProcedureStepProgressInformationSequence DcmTagKey(0x0074, 0x1002) +#define DCM_ProcedureStepProgress DcmTagKey(0x0074, 0x1004) +#define DCM_ProcedureStepProgressDescription DcmTagKey(0x0074, 0x1006) +#define DCM_ProcedureStepCommunicationsURISequence DcmTagKey(0x0074, 0x1008) +#define DCM_ContactURI DcmTagKey(0x0074, 0x100a) +#define DCM_ContactDisplayName DcmTagKey(0x0074, 0x100c) +#define DCM_ProcedureStepDiscontinuationReasonCodeSequence DcmTagKey(0x0074, 0x100e) +#define DCM_BeamTaskSequence DcmTagKey(0x0074, 0x1020) +#define DCM_BeamTaskType DcmTagKey(0x0074, 0x1022) +#define DCM_RETIRED_BeamOrderIndexTrial DcmTagKey(0x0074, 0x1024) +#define DCM_AutosequenceFlag DcmTagKey(0x0074, 0x1025) +#define DCM_TableTopVerticalAdjustedPosition DcmTagKey(0x0074, 0x1026) +#define DCM_TableTopLongitudinalAdjustedPosition DcmTagKey(0x0074, 0x1027) +#define DCM_TableTopLateralAdjustedPosition DcmTagKey(0x0074, 0x1028) +#define DCM_PatientSupportAdjustedAngle DcmTagKey(0x0074, 0x102a) +#define DCM_TableTopEccentricAdjustedAngle DcmTagKey(0x0074, 0x102b) +#define DCM_TableTopPitchAdjustedAngle DcmTagKey(0x0074, 0x102c) +#define DCM_TableTopRollAdjustedAngle DcmTagKey(0x0074, 0x102d) +#define DCM_DeliveryVerificationImageSequence DcmTagKey(0x0074, 0x1030) +#define DCM_VerificationImageTiming DcmTagKey(0x0074, 0x1032) +#define DCM_DoubleExposureFlag DcmTagKey(0x0074, 0x1034) +#define DCM_DoubleExposureOrdering DcmTagKey(0x0074, 0x1036) +#define DCM_RETIRED_DoubleExposureMetersetTrial DcmTagKey(0x0074, 0x1038) +#define DCM_RETIRED_DoubleExposureFieldDeltaTrial DcmTagKey(0x0074, 0x103a) +#define DCM_RelatedReferenceRTImageSequence DcmTagKey(0x0074, 0x1040) +#define DCM_GeneralMachineVerificationSequence DcmTagKey(0x0074, 0x1042) +#define DCM_ConventionalMachineVerificationSequence DcmTagKey(0x0074, 0x1044) +#define DCM_IonMachineVerificationSequence DcmTagKey(0x0074, 0x1046) +#define DCM_FailedAttributesSequence DcmTagKey(0x0074, 0x1048) +#define DCM_OverriddenAttributesSequence DcmTagKey(0x0074, 0x104a) +#define DCM_ConventionalControlPointVerificationSequence DcmTagKey(0x0074, 0x104c) +#define DCM_IonControlPointVerificationSequence DcmTagKey(0x0074, 0x104e) +#define DCM_AttributeOccurrenceSequence DcmTagKey(0x0074, 0x1050) +#define DCM_AttributeOccurrencePointer DcmTagKey(0x0074, 0x1052) +#define DCM_AttributeItemSelector DcmTagKey(0x0074, 0x1054) +#define DCM_AttributeOccurrencePrivateCreator DcmTagKey(0x0074, 0x1056) +#define DCM_SelectorSequencePointerItems DcmTagKey(0x0074, 0x1057) +#define DCM_ScheduledProcedureStepPriority DcmTagKey(0x0074, 0x1200) +#define DCM_WorklistLabel DcmTagKey(0x0074, 0x1202) +#define DCM_ProcedureStepLabel DcmTagKey(0x0074, 0x1204) +#define DCM_ScheduledProcessingParametersSequence DcmTagKey(0x0074, 0x1210) +#define DCM_PerformedProcessingParametersSequence DcmTagKey(0x0074, 0x1212) +#define DCM_UnifiedProcedureStepPerformedProcedureSequence DcmTagKey(0x0074, 0x1216) +#define DCM_RETIRED_RelatedProcedureStepSequence DcmTagKey(0x0074, 0x1220) +#define DCM_RETIRED_ProcedureStepRelationshipType DcmTagKey(0x0074, 0x1222) +#define DCM_ReplacedProcedureStepSequence DcmTagKey(0x0074, 0x1224) +#define DCM_DeletionLock DcmTagKey(0x0074, 0x1230) +#define DCM_ReceivingAE DcmTagKey(0x0074, 0x1234) +#define DCM_RequestingAE DcmTagKey(0x0074, 0x1236) +#define DCM_ReasonForCancellation DcmTagKey(0x0074, 0x1238) +#define DCM_SCPStatus DcmTagKey(0x0074, 0x1242) +#define DCM_SubscriptionListStatus DcmTagKey(0x0074, 0x1244) +#define DCM_UnifiedProcedureStepListStatus DcmTagKey(0x0074, 0x1246) +#define DCM_BeamOrderIndex DcmTagKey(0x0074, 0x1324) +#define DCM_DoubleExposureMeterset DcmTagKey(0x0074, 0x1338) +#define DCM_DoubleExposureFieldDelta DcmTagKey(0x0074, 0x133a) +#define DCM_ImplantAssemblyTemplateName DcmTagKey(0x0076, 0x0001) +#define DCM_ImplantAssemblyTemplateIssuer DcmTagKey(0x0076, 0x0003) +#define DCM_ImplantAssemblyTemplateVersion DcmTagKey(0x0076, 0x0006) +#define DCM_ReplacedImplantAssemblyTemplateSequence DcmTagKey(0x0076, 0x0008) +#define DCM_ImplantAssemblyTemplateType DcmTagKey(0x0076, 0x000a) +#define DCM_OriginalImplantAssemblyTemplateSequence DcmTagKey(0x0076, 0x000c) +#define DCM_DerivationImplantAssemblyTemplateSequence DcmTagKey(0x0076, 0x000e) +#define DCM_ImplantAssemblyTemplateTargetAnatomySequence DcmTagKey(0x0076, 0x0010) +#define DCM_ProcedureTypeCodeSequence DcmTagKey(0x0076, 0x0020) +#define DCM_SurgicalTechnique DcmTagKey(0x0076, 0x0030) +#define DCM_ComponentTypesSequence DcmTagKey(0x0076, 0x0032) +#define DCM_ComponentTypeCodeSequence DcmTagKey(0x0076, 0x0034) +#define DCM_ExclusiveComponentType DcmTagKey(0x0076, 0x0036) +#define DCM_MandatoryComponentType DcmTagKey(0x0076, 0x0038) +#define DCM_ComponentSequence DcmTagKey(0x0076, 0x0040) +#define DCM_ComponentID DcmTagKey(0x0076, 0x0055) +#define DCM_ComponentAssemblySequence DcmTagKey(0x0076, 0x0060) +#define DCM_Component1ReferencedID DcmTagKey(0x0076, 0x0070) +#define DCM_Component1ReferencedMatingFeatureSetID DcmTagKey(0x0076, 0x0080) +#define DCM_Component1ReferencedMatingFeatureID DcmTagKey(0x0076, 0x0090) +#define DCM_Component2ReferencedID DcmTagKey(0x0076, 0x00a0) +#define DCM_Component2ReferencedMatingFeatureSetID DcmTagKey(0x0076, 0x00b0) +#define DCM_Component2ReferencedMatingFeatureID DcmTagKey(0x0076, 0x00c0) +#define DCM_ImplantTemplateGroupName DcmTagKey(0x0078, 0x0001) +#define DCM_ImplantTemplateGroupDescription DcmTagKey(0x0078, 0x0010) +#define DCM_ImplantTemplateGroupIssuer DcmTagKey(0x0078, 0x0020) +#define DCM_ImplantTemplateGroupVersion DcmTagKey(0x0078, 0x0024) +#define DCM_ReplacedImplantTemplateGroupSequence DcmTagKey(0x0078, 0x0026) +#define DCM_ImplantTemplateGroupTargetAnatomySequence DcmTagKey(0x0078, 0x0028) +#define DCM_ImplantTemplateGroupMembersSequence DcmTagKey(0x0078, 0x002a) +#define DCM_ImplantTemplateGroupMemberID DcmTagKey(0x0078, 0x002e) +#define DCM_ThreeDImplantTemplateGroupMemberMatchingPoint DcmTagKey(0x0078, 0x0050) +#define DCM_ThreeDImplantTemplateGroupMemberMatchingAxes DcmTagKey(0x0078, 0x0060) +#define DCM_ImplantTemplateGroupMemberMatching2DCoordinatesSequence DcmTagKey(0x0078, 0x0070) +#define DCM_TwoDImplantTemplateGroupMemberMatchingPoint DcmTagKey(0x0078, 0x0090) +#define DCM_TwoDImplantTemplateGroupMemberMatchingAxes DcmTagKey(0x0078, 0x00a0) +#define DCM_ImplantTemplateGroupVariationDimensionSequence DcmTagKey(0x0078, 0x00b0) +#define DCM_ImplantTemplateGroupVariationDimensionName DcmTagKey(0x0078, 0x00b2) +#define DCM_ImplantTemplateGroupVariationDimensionRankSequence DcmTagKey(0x0078, 0x00b4) +#define DCM_ReferencedImplantTemplateGroupMemberID DcmTagKey(0x0078, 0x00b6) +#define DCM_ImplantTemplateGroupVariationDimensionRank DcmTagKey(0x0078, 0x00b8) +#define DCM_SurfaceScanAcquisitionTypeCodeSequence DcmTagKey(0x0080, 0x0001) +#define DCM_SurfaceScanModeCodeSequence DcmTagKey(0x0080, 0x0002) +#define DCM_RegistrationMethodCodeSequence DcmTagKey(0x0080, 0x0003) +#define DCM_ShotDurationTime DcmTagKey(0x0080, 0x0004) +#define DCM_ShotOffsetTime DcmTagKey(0x0080, 0x0005) +#define DCM_SurfacePointPresentationValueData DcmTagKey(0x0080, 0x0006) +#define DCM_SurfacePointColorCIELabValueData DcmTagKey(0x0080, 0x0007) +#define DCM_UVMappingSequence DcmTagKey(0x0080, 0x0008) +#define DCM_TextureLabel DcmTagKey(0x0080, 0x0009) +#define DCM_UValueData DcmTagKey(0x0080, 0x0010) +#define DCM_VValueData DcmTagKey(0x0080, 0x0011) +#define DCM_ReferencedTextureSequence DcmTagKey(0x0080, 0x0012) +#define DCM_ReferencedSurfaceDataSequence DcmTagKey(0x0080, 0x0013) +#define DCM_StorageMediaFileSetID DcmTagKey(0x0088, 0x0130) +#define DCM_StorageMediaFileSetUID DcmTagKey(0x0088, 0x0140) +#define DCM_IconImageSequence DcmTagKey(0x0088, 0x0200) +#define DCM_RETIRED_TopicTitle DcmTagKey(0x0088, 0x0904) +#define DCM_RETIRED_TopicSubject DcmTagKey(0x0088, 0x0906) +#define DCM_RETIRED_TopicAuthor DcmTagKey(0x0088, 0x0910) +#define DCM_RETIRED_TopicKeywords DcmTagKey(0x0088, 0x0912) +#define DCM_SOPInstanceStatus DcmTagKey(0x0100, 0x0410) +#define DCM_SOPAuthorizationDateTime DcmTagKey(0x0100, 0x0420) +#define DCM_SOPAuthorizationComment DcmTagKey(0x0100, 0x0424) +#define DCM_AuthorizationEquipmentCertificationNumber DcmTagKey(0x0100, 0x0426) +#define DCM_MACIDNumber DcmTagKey(0x0400, 0x0005) +#define DCM_MACCalculationTransferSyntaxUID DcmTagKey(0x0400, 0x0010) +#define DCM_MACAlgorithm DcmTagKey(0x0400, 0x0015) +#define DCM_DataElementsSigned DcmTagKey(0x0400, 0x0020) +#define DCM_DigitalSignatureUID DcmTagKey(0x0400, 0x0100) +#define DCM_DigitalSignatureDateTime DcmTagKey(0x0400, 0x0105) +#define DCM_CertificateType DcmTagKey(0x0400, 0x0110) +#define DCM_CertificateOfSigner DcmTagKey(0x0400, 0x0115) +#define DCM_Signature DcmTagKey(0x0400, 0x0120) +#define DCM_CertifiedTimestampType DcmTagKey(0x0400, 0x0305) +#define DCM_CertifiedTimestamp DcmTagKey(0x0400, 0x0310) +#define DCM_DigitalSignaturePurposeCodeSequence DcmTagKey(0x0400, 0x0401) +#define DCM_ReferencedDigitalSignatureSequence DcmTagKey(0x0400, 0x0402) +#define DCM_ReferencedSOPInstanceMACSequence DcmTagKey(0x0400, 0x0403) +#define DCM_MAC DcmTagKey(0x0400, 0x0404) +#define DCM_EncryptedAttributesSequence DcmTagKey(0x0400, 0x0500) +#define DCM_EncryptedContentTransferSyntaxUID DcmTagKey(0x0400, 0x0510) +#define DCM_EncryptedContent DcmTagKey(0x0400, 0x0520) +#define DCM_ModifiedAttributesSequence DcmTagKey(0x0400, 0x0550) +#define DCM_OriginalAttributesSequence DcmTagKey(0x0400, 0x0561) +#define DCM_AttributeModificationDateTime DcmTagKey(0x0400, 0x0562) +#define DCM_ModifyingSystem DcmTagKey(0x0400, 0x0563) +#define DCM_SourceOfPreviousValues DcmTagKey(0x0400, 0x0564) +#define DCM_ReasonForTheAttributeModification DcmTagKey(0x0400, 0x0565) +#define DCM_RETIRED_EscapeTriplet DcmTagKey(0x1000, 0x0010) +#define DCM_RETIRED_RunLengthTriplet DcmTagKey(0x1000, 0x0011) +#define DCM_RETIRED_HuffmanTableSize DcmTagKey(0x1000, 0x0012) +#define DCM_RETIRED_HuffmanTableTriplet DcmTagKey(0x1000, 0x0013) +#define DCM_RETIRED_ShiftTableSize DcmTagKey(0x1000, 0x0014) +#define DCM_RETIRED_ShiftTableTriplet DcmTagKey(0x1000, 0x0015) +#define DCM_RETIRED_ZonalMap DcmTagKey(0x1010, 0x0004) +#define DCM_NumberOfCopies DcmTagKey(0x2000, 0x0010) +#define DCM_PrinterConfigurationSequence DcmTagKey(0x2000, 0x001e) +#define DCM_PrintPriority DcmTagKey(0x2000, 0x0020) +#define DCM_MediumType DcmTagKey(0x2000, 0x0030) +#define DCM_FilmDestination DcmTagKey(0x2000, 0x0040) +#define DCM_FilmSessionLabel DcmTagKey(0x2000, 0x0050) +#define DCM_MemoryAllocation DcmTagKey(0x2000, 0x0060) +#define DCM_MaximumMemoryAllocation DcmTagKey(0x2000, 0x0061) +#define DCM_RETIRED_ColorImagePrintingFlag DcmTagKey(0x2000, 0x0062) +#define DCM_RETIRED_CollationFlag DcmTagKey(0x2000, 0x0063) +#define DCM_RETIRED_AnnotationFlag DcmTagKey(0x2000, 0x0065) +#define DCM_RETIRED_ImageOverlayFlag DcmTagKey(0x2000, 0x0067) +#define DCM_RETIRED_PresentationLUTFlag DcmTagKey(0x2000, 0x0069) +#define DCM_RETIRED_ImageBoxPresentationLUTFlag DcmTagKey(0x2000, 0x006a) +#define DCM_MemoryBitDepth DcmTagKey(0x2000, 0x00a0) +#define DCM_PrintingBitDepth DcmTagKey(0x2000, 0x00a1) +#define DCM_MediaInstalledSequence DcmTagKey(0x2000, 0x00a2) +#define DCM_OtherMediaAvailableSequence DcmTagKey(0x2000, 0x00a4) +#define DCM_SupportedImageDisplayFormatsSequence DcmTagKey(0x2000, 0x00a8) +#define DCM_ReferencedFilmBoxSequence DcmTagKey(0x2000, 0x0500) +#define DCM_RETIRED_ReferencedStoredPrintSequence DcmTagKey(0x2000, 0x0510) +#define DCM_ImageDisplayFormat DcmTagKey(0x2010, 0x0010) +#define DCM_AnnotationDisplayFormatID DcmTagKey(0x2010, 0x0030) +#define DCM_FilmOrientation DcmTagKey(0x2010, 0x0040) +#define DCM_FilmSizeID DcmTagKey(0x2010, 0x0050) +#define DCM_PrinterResolutionID DcmTagKey(0x2010, 0x0052) +#define DCM_DefaultPrinterResolutionID DcmTagKey(0x2010, 0x0054) +#define DCM_MagnificationType DcmTagKey(0x2010, 0x0060) +#define DCM_SmoothingType DcmTagKey(0x2010, 0x0080) +#define DCM_DefaultMagnificationType DcmTagKey(0x2010, 0x00a6) +#define DCM_OtherMagnificationTypesAvailable DcmTagKey(0x2010, 0x00a7) +#define DCM_DefaultSmoothingType DcmTagKey(0x2010, 0x00a8) +#define DCM_OtherSmoothingTypesAvailable DcmTagKey(0x2010, 0x00a9) +#define DCM_BorderDensity DcmTagKey(0x2010, 0x0100) +#define DCM_EmptyImageDensity DcmTagKey(0x2010, 0x0110) +#define DCM_MinDensity DcmTagKey(0x2010, 0x0120) +#define DCM_MaxDensity DcmTagKey(0x2010, 0x0130) +#define DCM_Trim DcmTagKey(0x2010, 0x0140) +#define DCM_ConfigurationInformation DcmTagKey(0x2010, 0x0150) +#define DCM_ConfigurationInformationDescription DcmTagKey(0x2010, 0x0152) +#define DCM_MaximumCollatedFilms DcmTagKey(0x2010, 0x0154) +#define DCM_Illumination DcmTagKey(0x2010, 0x015e) +#define DCM_ReflectedAmbientLight DcmTagKey(0x2010, 0x0160) +#define DCM_PrinterPixelSpacing DcmTagKey(0x2010, 0x0376) +#define DCM_ReferencedFilmSessionSequence DcmTagKey(0x2010, 0x0500) +#define DCM_ReferencedImageBoxSequence DcmTagKey(0x2010, 0x0510) +#define DCM_ReferencedBasicAnnotationBoxSequence DcmTagKey(0x2010, 0x0520) +#define DCM_ImageBoxPosition DcmTagKey(0x2020, 0x0010) +#define DCM_Polarity DcmTagKey(0x2020, 0x0020) +#define DCM_RequestedImageSize DcmTagKey(0x2020, 0x0030) +#define DCM_RequestedDecimateCropBehavior DcmTagKey(0x2020, 0x0040) +#define DCM_RequestedResolutionID DcmTagKey(0x2020, 0x0050) +#define DCM_RequestedImageSizeFlag DcmTagKey(0x2020, 0x00a0) +#define DCM_DecimateCropResult DcmTagKey(0x2020, 0x00a2) +#define DCM_BasicGrayscaleImageSequence DcmTagKey(0x2020, 0x0110) +#define DCM_BasicColorImageSequence DcmTagKey(0x2020, 0x0111) +#define DCM_RETIRED_ReferencedImageOverlayBoxSequence DcmTagKey(0x2020, 0x0130) +#define DCM_RETIRED_ReferencedVOILUTBoxSequence DcmTagKey(0x2020, 0x0140) +#define DCM_AnnotationPosition DcmTagKey(0x2030, 0x0010) +#define DCM_TextString DcmTagKey(0x2030, 0x0020) +#define DCM_RETIRED_ReferencedOverlayPlaneSequence DcmTagKey(0x2040, 0x0010) +#define DCM_RETIRED_ReferencedOverlayPlaneGroups DcmTagKey(0x2040, 0x0011) +#define DCM_RETIRED_OverlayPixelDataSequence DcmTagKey(0x2040, 0x0020) +#define DCM_RETIRED_OverlayMagnificationType DcmTagKey(0x2040, 0x0060) +#define DCM_RETIRED_OverlaySmoothingType DcmTagKey(0x2040, 0x0070) +#define DCM_RETIRED_OverlayOrImageMagnification DcmTagKey(0x2040, 0x0072) +#define DCM_RETIRED_MagnifyToNumberOfColumns DcmTagKey(0x2040, 0x0074) +#define DCM_RETIRED_OverlayForegroundDensity DcmTagKey(0x2040, 0x0080) +#define DCM_RETIRED_OverlayBackgroundDensity DcmTagKey(0x2040, 0x0082) +#define DCM_RETIRED_OverlayMode DcmTagKey(0x2040, 0x0090) +#define DCM_RETIRED_ThresholdDensity DcmTagKey(0x2040, 0x0100) +#define DCM_RETIRED_ReferencedImageBoxSequenceRetired DcmTagKey(0x2040, 0x0500) +#define DCM_PresentationLUTSequence DcmTagKey(0x2050, 0x0010) +#define DCM_PresentationLUTShape DcmTagKey(0x2050, 0x0020) +#define DCM_ReferencedPresentationLUTSequence DcmTagKey(0x2050, 0x0500) +#define DCM_RETIRED_PrintJobID DcmTagKey(0x2100, 0x0010) +#define DCM_ExecutionStatus DcmTagKey(0x2100, 0x0020) +#define DCM_ExecutionStatusInfo DcmTagKey(0x2100, 0x0030) +#define DCM_CreationDate DcmTagKey(0x2100, 0x0040) +#define DCM_CreationTime DcmTagKey(0x2100, 0x0050) +#define DCM_Originator DcmTagKey(0x2100, 0x0070) +#define DCM_RETIRED_DestinationAE DcmTagKey(0x2100, 0x0140) +#define DCM_OwnerID DcmTagKey(0x2100, 0x0160) +#define DCM_NumberOfFilms DcmTagKey(0x2100, 0x0170) +#define DCM_RETIRED_ReferencedPrintJobSequencePullStoredPrint DcmTagKey(0x2100, 0x0500) +#define DCM_PrinterStatus DcmTagKey(0x2110, 0x0010) +#define DCM_PrinterStatusInfo DcmTagKey(0x2110, 0x0020) +#define DCM_PrinterName DcmTagKey(0x2110, 0x0030) +#define DCM_RETIRED_PrintQueueID DcmTagKey(0x2110, 0x0099) +#define DCM_RETIRED_QueueStatus DcmTagKey(0x2120, 0x0010) +#define DCM_RETIRED_PrintJobDescriptionSequence DcmTagKey(0x2120, 0x0050) +#define DCM_RETIRED_ReferencedPrintJobSequence DcmTagKey(0x2120, 0x0070) +#define DCM_RETIRED_PrintManagementCapabilitiesSequence DcmTagKey(0x2130, 0x0010) +#define DCM_RETIRED_PrinterCharacteristicsSequence DcmTagKey(0x2130, 0x0015) +#define DCM_RETIRED_FilmBoxContentSequence DcmTagKey(0x2130, 0x0030) +#define DCM_RETIRED_ImageBoxContentSequence DcmTagKey(0x2130, 0x0040) +#define DCM_RETIRED_AnnotationContentSequence DcmTagKey(0x2130, 0x0050) +#define DCM_RETIRED_ImageOverlayBoxContentSequence DcmTagKey(0x2130, 0x0060) +#define DCM_RETIRED_PresentationLUTContentSequence DcmTagKey(0x2130, 0x0080) +#define DCM_RETIRED_ProposedStudySequence DcmTagKey(0x2130, 0x00a0) +#define DCM_RETIRED_OriginalImageSequence DcmTagKey(0x2130, 0x00c0) +#define DCM_LabelUsingInformationExtractedFromInstances DcmTagKey(0x2200, 0x0001) +#define DCM_LabelText DcmTagKey(0x2200, 0x0002) +#define DCM_LabelStyleSelection DcmTagKey(0x2200, 0x0003) +#define DCM_MediaDisposition DcmTagKey(0x2200, 0x0004) +#define DCM_BarcodeValue DcmTagKey(0x2200, 0x0005) +#define DCM_BarcodeSymbology DcmTagKey(0x2200, 0x0006) +#define DCM_AllowMediaSplitting DcmTagKey(0x2200, 0x0007) +#define DCM_IncludeNonDICOMObjects DcmTagKey(0x2200, 0x0008) +#define DCM_IncludeDisplayApplication DcmTagKey(0x2200, 0x0009) +#define DCM_PreserveCompositeInstancesAfterMediaCreation DcmTagKey(0x2200, 0x000a) +#define DCM_TotalNumberOfPiecesOfMediaCreated DcmTagKey(0x2200, 0x000b) +#define DCM_RequestedMediaApplicationProfile DcmTagKey(0x2200, 0x000c) +#define DCM_ReferencedStorageMediaSequence DcmTagKey(0x2200, 0x000d) +#define DCM_FailureAttributes DcmTagKey(0x2200, 0x000e) +#define DCM_AllowLossyCompression DcmTagKey(0x2200, 0x000f) +#define DCM_RequestPriority DcmTagKey(0x2200, 0x0020) +#define DCM_RTImageLabel DcmTagKey(0x3002, 0x0002) +#define DCM_RTImageName DcmTagKey(0x3002, 0x0003) +#define DCM_RTImageDescription DcmTagKey(0x3002, 0x0004) +#define DCM_ReportedValuesOrigin DcmTagKey(0x3002, 0x000a) +#define DCM_RTImagePlane DcmTagKey(0x3002, 0x000c) +#define DCM_XRayImageReceptorTranslation DcmTagKey(0x3002, 0x000d) +#define DCM_XRayImageReceptorAngle DcmTagKey(0x3002, 0x000e) +#define DCM_RTImageOrientation DcmTagKey(0x3002, 0x0010) +#define DCM_ImagePlanePixelSpacing DcmTagKey(0x3002, 0x0011) +#define DCM_RTImagePosition DcmTagKey(0x3002, 0x0012) +#define DCM_RadiationMachineName DcmTagKey(0x3002, 0x0020) +#define DCM_RadiationMachineSAD DcmTagKey(0x3002, 0x0022) +#define DCM_RadiationMachineSSD DcmTagKey(0x3002, 0x0024) +#define DCM_RTImageSID DcmTagKey(0x3002, 0x0026) +#define DCM_SourceToReferenceObjectDistance DcmTagKey(0x3002, 0x0028) +#define DCM_FractionNumber DcmTagKey(0x3002, 0x0029) +#define DCM_ExposureSequence DcmTagKey(0x3002, 0x0030) +#define DCM_MetersetExposure DcmTagKey(0x3002, 0x0032) +#define DCM_DiaphragmPosition DcmTagKey(0x3002, 0x0034) +#define DCM_FluenceMapSequence DcmTagKey(0x3002, 0x0040) +#define DCM_FluenceDataSource DcmTagKey(0x3002, 0x0041) +#define DCM_FluenceDataScale DcmTagKey(0x3002, 0x0042) +#define DCM_PrimaryFluenceModeSequence DcmTagKey(0x3002, 0x0050) +#define DCM_FluenceMode DcmTagKey(0x3002, 0x0051) +#define DCM_FluenceModeID DcmTagKey(0x3002, 0x0052) +#define DCM_DVHType DcmTagKey(0x3004, 0x0001) +#define DCM_DoseUnits DcmTagKey(0x3004, 0x0002) +#define DCM_DoseType DcmTagKey(0x3004, 0x0004) +#define DCM_SpatialTransformOfDose DcmTagKey(0x3004, 0x0005) +#define DCM_DoseComment DcmTagKey(0x3004, 0x0006) +#define DCM_NormalizationPoint DcmTagKey(0x3004, 0x0008) +#define DCM_DoseSummationType DcmTagKey(0x3004, 0x000a) +#define DCM_GridFrameOffsetVector DcmTagKey(0x3004, 0x000c) +#define DCM_DoseGridScaling DcmTagKey(0x3004, 0x000e) +#define DCM_RTDoseROISequence DcmTagKey(0x3004, 0x0010) +#define DCM_DoseValue DcmTagKey(0x3004, 0x0012) +#define DCM_TissueHeterogeneityCorrection DcmTagKey(0x3004, 0x0014) +#define DCM_DVHNormalizationPoint DcmTagKey(0x3004, 0x0040) +#define DCM_DVHNormalizationDoseValue DcmTagKey(0x3004, 0x0042) +#define DCM_DVHSequence DcmTagKey(0x3004, 0x0050) +#define DCM_DVHDoseScaling DcmTagKey(0x3004, 0x0052) +#define DCM_DVHVolumeUnits DcmTagKey(0x3004, 0x0054) +#define DCM_DVHNumberOfBins DcmTagKey(0x3004, 0x0056) +#define DCM_DVHData DcmTagKey(0x3004, 0x0058) +#define DCM_DVHReferencedROISequence DcmTagKey(0x3004, 0x0060) +#define DCM_DVHROIContributionType DcmTagKey(0x3004, 0x0062) +#define DCM_DVHMinimumDose DcmTagKey(0x3004, 0x0070) +#define DCM_DVHMaximumDose DcmTagKey(0x3004, 0x0072) +#define DCM_DVHMeanDose DcmTagKey(0x3004, 0x0074) +#define DCM_StructureSetLabel DcmTagKey(0x3006, 0x0002) +#define DCM_StructureSetName DcmTagKey(0x3006, 0x0004) +#define DCM_StructureSetDescription DcmTagKey(0x3006, 0x0006) +#define DCM_StructureSetDate DcmTagKey(0x3006, 0x0008) +#define DCM_StructureSetTime DcmTagKey(0x3006, 0x0009) +#define DCM_ReferencedFrameOfReferenceSequence DcmTagKey(0x3006, 0x0010) +#define DCM_RTReferencedStudySequence DcmTagKey(0x3006, 0x0012) +#define DCM_RTReferencedSeriesSequence DcmTagKey(0x3006, 0x0014) +#define DCM_ContourImageSequence DcmTagKey(0x3006, 0x0016) +#define DCM_PredecessorStructureSetSequence DcmTagKey(0x3006, 0x0018) +#define DCM_StructureSetROISequence DcmTagKey(0x3006, 0x0020) +#define DCM_ROINumber DcmTagKey(0x3006, 0x0022) +#define DCM_ReferencedFrameOfReferenceUID DcmTagKey(0x3006, 0x0024) +#define DCM_ROIName DcmTagKey(0x3006, 0x0026) +#define DCM_ROIDescription DcmTagKey(0x3006, 0x0028) +#define DCM_ROIDisplayColor DcmTagKey(0x3006, 0x002a) +#define DCM_ROIVolume DcmTagKey(0x3006, 0x002c) +#define DCM_RTRelatedROISequence DcmTagKey(0x3006, 0x0030) +#define DCM_RTROIRelationship DcmTagKey(0x3006, 0x0033) +#define DCM_ROIGenerationAlgorithm DcmTagKey(0x3006, 0x0036) +#define DCM_ROIGenerationDescription DcmTagKey(0x3006, 0x0038) +#define DCM_ROIContourSequence DcmTagKey(0x3006, 0x0039) +#define DCM_ContourSequence DcmTagKey(0x3006, 0x0040) +#define DCM_ContourGeometricType DcmTagKey(0x3006, 0x0042) +#define DCM_ContourSlabThickness DcmTagKey(0x3006, 0x0044) +#define DCM_ContourOffsetVector DcmTagKey(0x3006, 0x0045) +#define DCM_NumberOfContourPoints DcmTagKey(0x3006, 0x0046) +#define DCM_ContourNumber DcmTagKey(0x3006, 0x0048) +#define DCM_AttachedContours DcmTagKey(0x3006, 0x0049) +#define DCM_ContourData DcmTagKey(0x3006, 0x0050) +#define DCM_RTROIObservationsSequence DcmTagKey(0x3006, 0x0080) +#define DCM_ObservationNumber DcmTagKey(0x3006, 0x0082) +#define DCM_ReferencedROINumber DcmTagKey(0x3006, 0x0084) +#define DCM_ROIObservationLabel DcmTagKey(0x3006, 0x0085) +#define DCM_RTROIIdentificationCodeSequence DcmTagKey(0x3006, 0x0086) +#define DCM_ROIObservationDescription DcmTagKey(0x3006, 0x0088) +#define DCM_RelatedRTROIObservationsSequence DcmTagKey(0x3006, 0x00a0) +#define DCM_RTROIInterpretedType DcmTagKey(0x3006, 0x00a4) +#define DCM_ROIInterpreter DcmTagKey(0x3006, 0x00a6) +#define DCM_ROIPhysicalPropertiesSequence DcmTagKey(0x3006, 0x00b0) +#define DCM_ROIPhysicalProperty DcmTagKey(0x3006, 0x00b2) +#define DCM_ROIPhysicalPropertyValue DcmTagKey(0x3006, 0x00b4) +#define DCM_ROIElementalCompositionSequence DcmTagKey(0x3006, 0x00b6) +#define DCM_ROIElementalCompositionAtomicNumber DcmTagKey(0x3006, 0x00b7) +#define DCM_ROIElementalCompositionAtomicMassFraction DcmTagKey(0x3006, 0x00b8) +#define DCM_AdditionalRTROIIdentificationCodeSequence DcmTagKey(0x3006, 0x00b9) +#define DCM_RETIRED_FrameOfReferenceRelationshipSequence DcmTagKey(0x3006, 0x00c0) +#define DCM_RETIRED_RelatedFrameOfReferenceUID DcmTagKey(0x3006, 0x00c2) +#define DCM_RETIRED_FrameOfReferenceTransformationType DcmTagKey(0x3006, 0x00c4) +#define DCM_FrameOfReferenceTransformationMatrix DcmTagKey(0x3006, 0x00c6) +#define DCM_FrameOfReferenceTransformationComment DcmTagKey(0x3006, 0x00c8) +#define DCM_MeasuredDoseReferenceSequence DcmTagKey(0x3008, 0x0010) +#define DCM_MeasuredDoseDescription DcmTagKey(0x3008, 0x0012) +#define DCM_MeasuredDoseType DcmTagKey(0x3008, 0x0014) +#define DCM_MeasuredDoseValue DcmTagKey(0x3008, 0x0016) +#define DCM_TreatmentSessionBeamSequence DcmTagKey(0x3008, 0x0020) +#define DCM_TreatmentSessionIonBeamSequence DcmTagKey(0x3008, 0x0021) +#define DCM_CurrentFractionNumber DcmTagKey(0x3008, 0x0022) +#define DCM_TreatmentControlPointDate DcmTagKey(0x3008, 0x0024) +#define DCM_TreatmentControlPointTime DcmTagKey(0x3008, 0x0025) +#define DCM_TreatmentTerminationStatus DcmTagKey(0x3008, 0x002a) +#define DCM_TreatmentTerminationCode DcmTagKey(0x3008, 0x002b) +#define DCM_TreatmentVerificationStatus DcmTagKey(0x3008, 0x002c) +#define DCM_ReferencedTreatmentRecordSequence DcmTagKey(0x3008, 0x0030) +#define DCM_SpecifiedPrimaryMeterset DcmTagKey(0x3008, 0x0032) +#define DCM_SpecifiedSecondaryMeterset DcmTagKey(0x3008, 0x0033) +#define DCM_DeliveredPrimaryMeterset DcmTagKey(0x3008, 0x0036) +#define DCM_DeliveredSecondaryMeterset DcmTagKey(0x3008, 0x0037) +#define DCM_SpecifiedTreatmentTime DcmTagKey(0x3008, 0x003a) +#define DCM_DeliveredTreatmentTime DcmTagKey(0x3008, 0x003b) +#define DCM_ControlPointDeliverySequence DcmTagKey(0x3008, 0x0040) +#define DCM_IonControlPointDeliverySequence DcmTagKey(0x3008, 0x0041) +#define DCM_SpecifiedMeterset DcmTagKey(0x3008, 0x0042) +#define DCM_DeliveredMeterset DcmTagKey(0x3008, 0x0044) +#define DCM_MetersetRateSet DcmTagKey(0x3008, 0x0045) +#define DCM_MetersetRateDelivered DcmTagKey(0x3008, 0x0046) +#define DCM_ScanSpotMetersetsDelivered DcmTagKey(0x3008, 0x0047) +#define DCM_DoseRateDelivered DcmTagKey(0x3008, 0x0048) +#define DCM_TreatmentSummaryCalculatedDoseReferenceSequence DcmTagKey(0x3008, 0x0050) +#define DCM_CumulativeDoseToDoseReference DcmTagKey(0x3008, 0x0052) +#define DCM_FirstTreatmentDate DcmTagKey(0x3008, 0x0054) +#define DCM_MostRecentTreatmentDate DcmTagKey(0x3008, 0x0056) +#define DCM_NumberOfFractionsDelivered DcmTagKey(0x3008, 0x005a) +#define DCM_OverrideSequence DcmTagKey(0x3008, 0x0060) +#define DCM_ParameterSequencePointer DcmTagKey(0x3008, 0x0061) +#define DCM_OverrideParameterPointer DcmTagKey(0x3008, 0x0062) +#define DCM_ParameterItemIndex DcmTagKey(0x3008, 0x0063) +#define DCM_MeasuredDoseReferenceNumber DcmTagKey(0x3008, 0x0064) +#define DCM_ParameterPointer DcmTagKey(0x3008, 0x0065) +#define DCM_OverrideReason DcmTagKey(0x3008, 0x0066) +#define DCM_CorrectedParameterSequence DcmTagKey(0x3008, 0x0068) +#define DCM_CorrectionValue DcmTagKey(0x3008, 0x006a) +#define DCM_CalculatedDoseReferenceSequence DcmTagKey(0x3008, 0x0070) +#define DCM_CalculatedDoseReferenceNumber DcmTagKey(0x3008, 0x0072) +#define DCM_CalculatedDoseReferenceDescription DcmTagKey(0x3008, 0x0074) +#define DCM_CalculatedDoseReferenceDoseValue DcmTagKey(0x3008, 0x0076) +#define DCM_StartMeterset DcmTagKey(0x3008, 0x0078) +#define DCM_EndMeterset DcmTagKey(0x3008, 0x007a) +#define DCM_ReferencedMeasuredDoseReferenceSequence DcmTagKey(0x3008, 0x0080) +#define DCM_ReferencedMeasuredDoseReferenceNumber DcmTagKey(0x3008, 0x0082) +#define DCM_ReferencedCalculatedDoseReferenceSequence DcmTagKey(0x3008, 0x0090) +#define DCM_ReferencedCalculatedDoseReferenceNumber DcmTagKey(0x3008, 0x0092) +#define DCM_BeamLimitingDeviceLeafPairsSequence DcmTagKey(0x3008, 0x00a0) +#define DCM_RecordedWedgeSequence DcmTagKey(0x3008, 0x00b0) +#define DCM_RecordedCompensatorSequence DcmTagKey(0x3008, 0x00c0) +#define DCM_RecordedBlockSequence DcmTagKey(0x3008, 0x00d0) +#define DCM_TreatmentSummaryMeasuredDoseReferenceSequence DcmTagKey(0x3008, 0x00e0) +#define DCM_RecordedSnoutSequence DcmTagKey(0x3008, 0x00f0) +#define DCM_RecordedRangeShifterSequence DcmTagKey(0x3008, 0x00f2) +#define DCM_RecordedLateralSpreadingDeviceSequence DcmTagKey(0x3008, 0x00f4) +#define DCM_RecordedRangeModulatorSequence DcmTagKey(0x3008, 0x00f6) +#define DCM_RecordedSourceSequence DcmTagKey(0x3008, 0x0100) +#define DCM_SourceSerialNumber DcmTagKey(0x3008, 0x0105) +#define DCM_TreatmentSessionApplicationSetupSequence DcmTagKey(0x3008, 0x0110) +#define DCM_ApplicationSetupCheck DcmTagKey(0x3008, 0x0116) +#define DCM_RecordedBrachyAccessoryDeviceSequence DcmTagKey(0x3008, 0x0120) +#define DCM_ReferencedBrachyAccessoryDeviceNumber DcmTagKey(0x3008, 0x0122) +#define DCM_RecordedChannelSequence DcmTagKey(0x3008, 0x0130) +#define DCM_SpecifiedChannelTotalTime DcmTagKey(0x3008, 0x0132) +#define DCM_DeliveredChannelTotalTime DcmTagKey(0x3008, 0x0134) +#define DCM_SpecifiedNumberOfPulses DcmTagKey(0x3008, 0x0136) +#define DCM_DeliveredNumberOfPulses DcmTagKey(0x3008, 0x0138) +#define DCM_SpecifiedPulseRepetitionInterval DcmTagKey(0x3008, 0x013a) +#define DCM_DeliveredPulseRepetitionInterval DcmTagKey(0x3008, 0x013c) +#define DCM_RecordedSourceApplicatorSequence DcmTagKey(0x3008, 0x0140) +#define DCM_ReferencedSourceApplicatorNumber DcmTagKey(0x3008, 0x0142) +#define DCM_RecordedChannelShieldSequence DcmTagKey(0x3008, 0x0150) +#define DCM_ReferencedChannelShieldNumber DcmTagKey(0x3008, 0x0152) +#define DCM_BrachyControlPointDeliveredSequence DcmTagKey(0x3008, 0x0160) +#define DCM_SafePositionExitDate DcmTagKey(0x3008, 0x0162) +#define DCM_SafePositionExitTime DcmTagKey(0x3008, 0x0164) +#define DCM_SafePositionReturnDate DcmTagKey(0x3008, 0x0166) +#define DCM_SafePositionReturnTime DcmTagKey(0x3008, 0x0168) +#define DCM_PulseSpecificBrachyControlPointDeliveredSequence DcmTagKey(0x3008, 0x0171) +#define DCM_PulseNumber DcmTagKey(0x3008, 0x0172) +#define DCM_BrachyPulseControlPointDeliveredSequence DcmTagKey(0x3008, 0x0173) +#define DCM_CurrentTreatmentStatus DcmTagKey(0x3008, 0x0200) +#define DCM_TreatmentStatusComment DcmTagKey(0x3008, 0x0202) +#define DCM_FractionGroupSummarySequence DcmTagKey(0x3008, 0x0220) +#define DCM_ReferencedFractionNumber DcmTagKey(0x3008, 0x0223) +#define DCM_FractionGroupType DcmTagKey(0x3008, 0x0224) +#define DCM_BeamStopperPosition DcmTagKey(0x3008, 0x0230) +#define DCM_FractionStatusSummarySequence DcmTagKey(0x3008, 0x0240) +#define DCM_TreatmentDate DcmTagKey(0x3008, 0x0250) +#define DCM_TreatmentTime DcmTagKey(0x3008, 0x0251) +#define DCM_RTPlanLabel DcmTagKey(0x300a, 0x0002) +#define DCM_RTPlanName DcmTagKey(0x300a, 0x0003) +#define DCM_RTPlanDescription DcmTagKey(0x300a, 0x0004) +#define DCM_RTPlanDate DcmTagKey(0x300a, 0x0006) +#define DCM_RTPlanTime DcmTagKey(0x300a, 0x0007) +#define DCM_TreatmentProtocols DcmTagKey(0x300a, 0x0009) +#define DCM_PlanIntent DcmTagKey(0x300a, 0x000a) +#define DCM_TreatmentSites DcmTagKey(0x300a, 0x000b) +#define DCM_RTPlanGeometry DcmTagKey(0x300a, 0x000c) +#define DCM_PrescriptionDescription DcmTagKey(0x300a, 0x000e) +#define DCM_DoseReferenceSequence DcmTagKey(0x300a, 0x0010) +#define DCM_DoseReferenceNumber DcmTagKey(0x300a, 0x0012) +#define DCM_DoseReferenceUID DcmTagKey(0x300a, 0x0013) +#define DCM_DoseReferenceStructureType DcmTagKey(0x300a, 0x0014) +#define DCM_NominalBeamEnergyUnit DcmTagKey(0x300a, 0x0015) +#define DCM_DoseReferenceDescription DcmTagKey(0x300a, 0x0016) +#define DCM_DoseReferencePointCoordinates DcmTagKey(0x300a, 0x0018) +#define DCM_NominalPriorDose DcmTagKey(0x300a, 0x001a) +#define DCM_DoseReferenceType DcmTagKey(0x300a, 0x0020) +#define DCM_ConstraintWeight DcmTagKey(0x300a, 0x0021) +#define DCM_DeliveryWarningDose DcmTagKey(0x300a, 0x0022) +#define DCM_DeliveryMaximumDose DcmTagKey(0x300a, 0x0023) +#define DCM_TargetMinimumDose DcmTagKey(0x300a, 0x0025) +#define DCM_TargetPrescriptionDose DcmTagKey(0x300a, 0x0026) +#define DCM_TargetMaximumDose DcmTagKey(0x300a, 0x0027) +#define DCM_TargetUnderdoseVolumeFraction DcmTagKey(0x300a, 0x0028) +#define DCM_OrganAtRiskFullVolumeDose DcmTagKey(0x300a, 0x002a) +#define DCM_OrganAtRiskLimitDose DcmTagKey(0x300a, 0x002b) +#define DCM_OrganAtRiskMaximumDose DcmTagKey(0x300a, 0x002c) +#define DCM_OrganAtRiskOverdoseVolumeFraction DcmTagKey(0x300a, 0x002d) +#define DCM_ToleranceTableSequence DcmTagKey(0x300a, 0x0040) +#define DCM_ToleranceTableNumber DcmTagKey(0x300a, 0x0042) +#define DCM_ToleranceTableLabel DcmTagKey(0x300a, 0x0043) +#define DCM_GantryAngleTolerance DcmTagKey(0x300a, 0x0044) +#define DCM_BeamLimitingDeviceAngleTolerance DcmTagKey(0x300a, 0x0046) +#define DCM_BeamLimitingDeviceToleranceSequence DcmTagKey(0x300a, 0x0048) +#define DCM_BeamLimitingDevicePositionTolerance DcmTagKey(0x300a, 0x004a) +#define DCM_SnoutPositionTolerance DcmTagKey(0x300a, 0x004b) +#define DCM_PatientSupportAngleTolerance DcmTagKey(0x300a, 0x004c) +#define DCM_TableTopEccentricAngleTolerance DcmTagKey(0x300a, 0x004e) +#define DCM_TableTopPitchAngleTolerance DcmTagKey(0x300a, 0x004f) +#define DCM_TableTopRollAngleTolerance DcmTagKey(0x300a, 0x0050) +#define DCM_TableTopVerticalPositionTolerance DcmTagKey(0x300a, 0x0051) +#define DCM_TableTopLongitudinalPositionTolerance DcmTagKey(0x300a, 0x0052) +#define DCM_TableTopLateralPositionTolerance DcmTagKey(0x300a, 0x0053) +#define DCM_RTPlanRelationship DcmTagKey(0x300a, 0x0055) +#define DCM_FractionGroupSequence DcmTagKey(0x300a, 0x0070) +#define DCM_FractionGroupNumber DcmTagKey(0x300a, 0x0071) +#define DCM_FractionGroupDescription DcmTagKey(0x300a, 0x0072) +#define DCM_NumberOfFractionsPlanned DcmTagKey(0x300a, 0x0078) +#define DCM_NumberOfFractionPatternDigitsPerDay DcmTagKey(0x300a, 0x0079) +#define DCM_RepeatFractionCycleLength DcmTagKey(0x300a, 0x007a) +#define DCM_FractionPattern DcmTagKey(0x300a, 0x007b) +#define DCM_NumberOfBeams DcmTagKey(0x300a, 0x0080) +#define DCM_BeamDoseSpecificationPoint DcmTagKey(0x300a, 0x0082) +#define DCM_BeamDose DcmTagKey(0x300a, 0x0084) +#define DCM_BeamMeterset DcmTagKey(0x300a, 0x0086) +#define DCM_RETIRED_BeamDosePointDepth DcmTagKey(0x300a, 0x0088) +#define DCM_RETIRED_BeamDosePointEquivalentDepth DcmTagKey(0x300a, 0x0089) +#define DCM_RETIRED_BeamDosePointSSD DcmTagKey(0x300a, 0x008a) +#define DCM_BeamDoseMeaning DcmTagKey(0x300a, 0x008b) +#define DCM_BeamDoseVerificationControlPointSequence DcmTagKey(0x300a, 0x008c) +#define DCM_AverageBeamDosePointDepth DcmTagKey(0x300a, 0x008d) +#define DCM_AverageBeamDosePointEquivalentDepth DcmTagKey(0x300a, 0x008e) +#define DCM_AverageBeamDosePointSSD DcmTagKey(0x300a, 0x008f) +#define DCM_NumberOfBrachyApplicationSetups DcmTagKey(0x300a, 0x00a0) +#define DCM_BrachyApplicationSetupDoseSpecificationPoint DcmTagKey(0x300a, 0x00a2) +#define DCM_BrachyApplicationSetupDose DcmTagKey(0x300a, 0x00a4) +#define DCM_BeamSequence DcmTagKey(0x300a, 0x00b0) +#define DCM_TreatmentMachineName DcmTagKey(0x300a, 0x00b2) +#define DCM_PrimaryDosimeterUnit DcmTagKey(0x300a, 0x00b3) +#define DCM_SourceAxisDistance DcmTagKey(0x300a, 0x00b4) +#define DCM_BeamLimitingDeviceSequence DcmTagKey(0x300a, 0x00b6) +#define DCM_RTBeamLimitingDeviceType DcmTagKey(0x300a, 0x00b8) +#define DCM_SourceToBeamLimitingDeviceDistance DcmTagKey(0x300a, 0x00ba) +#define DCM_IsocenterToBeamLimitingDeviceDistance DcmTagKey(0x300a, 0x00bb) +#define DCM_NumberOfLeafJawPairs DcmTagKey(0x300a, 0x00bc) +#define DCM_LeafPositionBoundaries DcmTagKey(0x300a, 0x00be) +#define DCM_BeamNumber DcmTagKey(0x300a, 0x00c0) +#define DCM_BeamName DcmTagKey(0x300a, 0x00c2) +#define DCM_BeamDescription DcmTagKey(0x300a, 0x00c3) +#define DCM_BeamType DcmTagKey(0x300a, 0x00c4) +#define DCM_BeamDeliveryDurationLimit DcmTagKey(0x300a, 0x00c5) +#define DCM_RadiationType DcmTagKey(0x300a, 0x00c6) +#define DCM_HighDoseTechniqueType DcmTagKey(0x300a, 0x00c7) +#define DCM_ReferenceImageNumber DcmTagKey(0x300a, 0x00c8) +#define DCM_PlannedVerificationImageSequence DcmTagKey(0x300a, 0x00ca) +#define DCM_ImagingDeviceSpecificAcquisitionParameters DcmTagKey(0x300a, 0x00cc) +#define DCM_TreatmentDeliveryType DcmTagKey(0x300a, 0x00ce) +#define DCM_NumberOfWedges DcmTagKey(0x300a, 0x00d0) +#define DCM_WedgeSequence DcmTagKey(0x300a, 0x00d1) +#define DCM_WedgeNumber DcmTagKey(0x300a, 0x00d2) +#define DCM_WedgeType DcmTagKey(0x300a, 0x00d3) +#define DCM_WedgeID DcmTagKey(0x300a, 0x00d4) +#define DCM_WedgeAngle DcmTagKey(0x300a, 0x00d5) +#define DCM_WedgeFactor DcmTagKey(0x300a, 0x00d6) +#define DCM_TotalWedgeTrayWaterEquivalentThickness DcmTagKey(0x300a, 0x00d7) +#define DCM_WedgeOrientation DcmTagKey(0x300a, 0x00d8) +#define DCM_IsocenterToWedgeTrayDistance DcmTagKey(0x300a, 0x00d9) +#define DCM_SourceToWedgeTrayDistance DcmTagKey(0x300a, 0x00da) +#define DCM_WedgeThinEdgePosition DcmTagKey(0x300a, 0x00db) +#define DCM_BolusID DcmTagKey(0x300a, 0x00dc) +#define DCM_BolusDescription DcmTagKey(0x300a, 0x00dd) +#define DCM_EffectiveWedgeAngle DcmTagKey(0x300a, 0x00de) +#define DCM_NumberOfCompensators DcmTagKey(0x300a, 0x00e0) +#define DCM_MaterialID DcmTagKey(0x300a, 0x00e1) +#define DCM_TotalCompensatorTrayFactor DcmTagKey(0x300a, 0x00e2) +#define DCM_CompensatorSequence DcmTagKey(0x300a, 0x00e3) +#define DCM_CompensatorNumber DcmTagKey(0x300a, 0x00e4) +#define DCM_CompensatorID DcmTagKey(0x300a, 0x00e5) +#define DCM_SourceToCompensatorTrayDistance DcmTagKey(0x300a, 0x00e6) +#define DCM_CompensatorRows DcmTagKey(0x300a, 0x00e7) +#define DCM_CompensatorColumns DcmTagKey(0x300a, 0x00e8) +#define DCM_CompensatorPixelSpacing DcmTagKey(0x300a, 0x00e9) +#define DCM_CompensatorPosition DcmTagKey(0x300a, 0x00ea) +#define DCM_CompensatorTransmissionData DcmTagKey(0x300a, 0x00eb) +#define DCM_CompensatorThicknessData DcmTagKey(0x300a, 0x00ec) +#define DCM_NumberOfBoli DcmTagKey(0x300a, 0x00ed) +#define DCM_CompensatorType DcmTagKey(0x300a, 0x00ee) +#define DCM_CompensatorTrayID DcmTagKey(0x300a, 0x00ef) +#define DCM_NumberOfBlocks DcmTagKey(0x300a, 0x00f0) +#define DCM_TotalBlockTrayFactor DcmTagKey(0x300a, 0x00f2) +#define DCM_TotalBlockTrayWaterEquivalentThickness DcmTagKey(0x300a, 0x00f3) +#define DCM_BlockSequence DcmTagKey(0x300a, 0x00f4) +#define DCM_BlockTrayID DcmTagKey(0x300a, 0x00f5) +#define DCM_SourceToBlockTrayDistance DcmTagKey(0x300a, 0x00f6) +#define DCM_IsocenterToBlockTrayDistance DcmTagKey(0x300a, 0x00f7) +#define DCM_BlockType DcmTagKey(0x300a, 0x00f8) +#define DCM_AccessoryCode DcmTagKey(0x300a, 0x00f9) +#define DCM_BlockDivergence DcmTagKey(0x300a, 0x00fa) +#define DCM_BlockMountingPosition DcmTagKey(0x300a, 0x00fb) +#define DCM_BlockNumber DcmTagKey(0x300a, 0x00fc) +#define DCM_BlockName DcmTagKey(0x300a, 0x00fe) +#define DCM_BlockThickness DcmTagKey(0x300a, 0x0100) +#define DCM_BlockTransmission DcmTagKey(0x300a, 0x0102) +#define DCM_BlockNumberOfPoints DcmTagKey(0x300a, 0x0104) +#define DCM_BlockData DcmTagKey(0x300a, 0x0106) +#define DCM_ApplicatorSequence DcmTagKey(0x300a, 0x0107) +#define DCM_ApplicatorID DcmTagKey(0x300a, 0x0108) +#define DCM_ApplicatorType DcmTagKey(0x300a, 0x0109) +#define DCM_ApplicatorDescription DcmTagKey(0x300a, 0x010a) +#define DCM_CumulativeDoseReferenceCoefficient DcmTagKey(0x300a, 0x010c) +#define DCM_FinalCumulativeMetersetWeight DcmTagKey(0x300a, 0x010e) +#define DCM_NumberOfControlPoints DcmTagKey(0x300a, 0x0110) +#define DCM_ControlPointSequence DcmTagKey(0x300a, 0x0111) +#define DCM_ControlPointIndex DcmTagKey(0x300a, 0x0112) +#define DCM_NominalBeamEnergy DcmTagKey(0x300a, 0x0114) +#define DCM_DoseRateSet DcmTagKey(0x300a, 0x0115) +#define DCM_WedgePositionSequence DcmTagKey(0x300a, 0x0116) +#define DCM_WedgePosition DcmTagKey(0x300a, 0x0118) +#define DCM_BeamLimitingDevicePositionSequence DcmTagKey(0x300a, 0x011a) +#define DCM_LeafJawPositions DcmTagKey(0x300a, 0x011c) +#define DCM_GantryAngle DcmTagKey(0x300a, 0x011e) +#define DCM_GantryRotationDirection DcmTagKey(0x300a, 0x011f) +#define DCM_BeamLimitingDeviceAngle DcmTagKey(0x300a, 0x0120) +#define DCM_BeamLimitingDeviceRotationDirection DcmTagKey(0x300a, 0x0121) +#define DCM_PatientSupportAngle DcmTagKey(0x300a, 0x0122) +#define DCM_PatientSupportRotationDirection DcmTagKey(0x300a, 0x0123) +#define DCM_TableTopEccentricAxisDistance DcmTagKey(0x300a, 0x0124) +#define DCM_TableTopEccentricAngle DcmTagKey(0x300a, 0x0125) +#define DCM_TableTopEccentricRotationDirection DcmTagKey(0x300a, 0x0126) +#define DCM_TableTopVerticalPosition DcmTagKey(0x300a, 0x0128) +#define DCM_TableTopLongitudinalPosition DcmTagKey(0x300a, 0x0129) +#define DCM_TableTopLateralPosition DcmTagKey(0x300a, 0x012a) +#define DCM_IsocenterPosition DcmTagKey(0x300a, 0x012c) +#define DCM_SurfaceEntryPoint DcmTagKey(0x300a, 0x012e) +#define DCM_SourceToSurfaceDistance DcmTagKey(0x300a, 0x0130) +#define DCM_AverageBeamDosePointSourceToExternalContourSurfaceDistance DcmTagKey(0x300a, 0x0131) +#define DCM_SourceToExternalContourDistance DcmTagKey(0x300a, 0x0132) +#define DCM_ExternalContourEntryPoint DcmTagKey(0x300a, 0x0133) +#define DCM_CumulativeMetersetWeight DcmTagKey(0x300a, 0x0134) +#define DCM_TableTopPitchAngle DcmTagKey(0x300a, 0x0140) +#define DCM_TableTopPitchRotationDirection DcmTagKey(0x300a, 0x0142) +#define DCM_TableTopRollAngle DcmTagKey(0x300a, 0x0144) +#define DCM_TableTopRollRotationDirection DcmTagKey(0x300a, 0x0146) +#define DCM_HeadFixationAngle DcmTagKey(0x300a, 0x0148) +#define DCM_GantryPitchAngle DcmTagKey(0x300a, 0x014a) +#define DCM_GantryPitchRotationDirection DcmTagKey(0x300a, 0x014c) +#define DCM_GantryPitchAngleTolerance DcmTagKey(0x300a, 0x014e) +#define DCM_PatientSetupSequence DcmTagKey(0x300a, 0x0180) +#define DCM_PatientSetupNumber DcmTagKey(0x300a, 0x0182) +#define DCM_PatientSetupLabel DcmTagKey(0x300a, 0x0183) +#define DCM_PatientAdditionalPosition DcmTagKey(0x300a, 0x0184) +#define DCM_FixationDeviceSequence DcmTagKey(0x300a, 0x0190) +#define DCM_FixationDeviceType DcmTagKey(0x300a, 0x0192) +#define DCM_FixationDeviceLabel DcmTagKey(0x300a, 0x0194) +#define DCM_FixationDeviceDescription DcmTagKey(0x300a, 0x0196) +#define DCM_FixationDevicePosition DcmTagKey(0x300a, 0x0198) +#define DCM_FixationDevicePitchAngle DcmTagKey(0x300a, 0x0199) +#define DCM_FixationDeviceRollAngle DcmTagKey(0x300a, 0x019a) +#define DCM_ShieldingDeviceSequence DcmTagKey(0x300a, 0x01a0) +#define DCM_ShieldingDeviceType DcmTagKey(0x300a, 0x01a2) +#define DCM_ShieldingDeviceLabel DcmTagKey(0x300a, 0x01a4) +#define DCM_ShieldingDeviceDescription DcmTagKey(0x300a, 0x01a6) +#define DCM_ShieldingDevicePosition DcmTagKey(0x300a, 0x01a8) +#define DCM_SetupTechnique DcmTagKey(0x300a, 0x01b0) +#define DCM_SetupTechniqueDescription DcmTagKey(0x300a, 0x01b2) +#define DCM_SetupDeviceSequence DcmTagKey(0x300a, 0x01b4) +#define DCM_SetupDeviceType DcmTagKey(0x300a, 0x01b6) +#define DCM_SetupDeviceLabel DcmTagKey(0x300a, 0x01b8) +#define DCM_SetupDeviceDescription DcmTagKey(0x300a, 0x01ba) +#define DCM_SetupDeviceParameter DcmTagKey(0x300a, 0x01bc) +#define DCM_SetupReferenceDescription DcmTagKey(0x300a, 0x01d0) +#define DCM_TableTopVerticalSetupDisplacement DcmTagKey(0x300a, 0x01d2) +#define DCM_TableTopLongitudinalSetupDisplacement DcmTagKey(0x300a, 0x01d4) +#define DCM_TableTopLateralSetupDisplacement DcmTagKey(0x300a, 0x01d6) +#define DCM_BrachyTreatmentTechnique DcmTagKey(0x300a, 0x0200) +#define DCM_BrachyTreatmentType DcmTagKey(0x300a, 0x0202) +#define DCM_TreatmentMachineSequence DcmTagKey(0x300a, 0x0206) +#define DCM_SourceSequence DcmTagKey(0x300a, 0x0210) +#define DCM_SourceNumber DcmTagKey(0x300a, 0x0212) +#define DCM_SourceType DcmTagKey(0x300a, 0x0214) +#define DCM_SourceManufacturer DcmTagKey(0x300a, 0x0216) +#define DCM_ActiveSourceDiameter DcmTagKey(0x300a, 0x0218) +#define DCM_ActiveSourceLength DcmTagKey(0x300a, 0x021a) +#define DCM_SourceModelID DcmTagKey(0x300a, 0x021b) +#define DCM_SourceDescription DcmTagKey(0x300a, 0x021c) +#define DCM_SourceEncapsulationNominalThickness DcmTagKey(0x300a, 0x0222) +#define DCM_SourceEncapsulationNominalTransmission DcmTagKey(0x300a, 0x0224) +#define DCM_SourceIsotopeName DcmTagKey(0x300a, 0x0226) +#define DCM_SourceIsotopeHalfLife DcmTagKey(0x300a, 0x0228) +#define DCM_SourceStrengthUnits DcmTagKey(0x300a, 0x0229) +#define DCM_ReferenceAirKermaRate DcmTagKey(0x300a, 0x022a) +#define DCM_SourceStrength DcmTagKey(0x300a, 0x022b) +#define DCM_SourceStrengthReferenceDate DcmTagKey(0x300a, 0x022c) +#define DCM_SourceStrengthReferenceTime DcmTagKey(0x300a, 0x022e) +#define DCM_ApplicationSetupSequence DcmTagKey(0x300a, 0x0230) +#define DCM_ApplicationSetupType DcmTagKey(0x300a, 0x0232) +#define DCM_ApplicationSetupNumber DcmTagKey(0x300a, 0x0234) +#define DCM_ApplicationSetupName DcmTagKey(0x300a, 0x0236) +#define DCM_ApplicationSetupManufacturer DcmTagKey(0x300a, 0x0238) +#define DCM_TemplateNumber DcmTagKey(0x300a, 0x0240) +#define DCM_TemplateType DcmTagKey(0x300a, 0x0242) +#define DCM_TemplateName DcmTagKey(0x300a, 0x0244) +#define DCM_TotalReferenceAirKerma DcmTagKey(0x300a, 0x0250) +#define DCM_BrachyAccessoryDeviceSequence DcmTagKey(0x300a, 0x0260) +#define DCM_BrachyAccessoryDeviceNumber DcmTagKey(0x300a, 0x0262) +#define DCM_BrachyAccessoryDeviceID DcmTagKey(0x300a, 0x0263) +#define DCM_BrachyAccessoryDeviceType DcmTagKey(0x300a, 0x0264) +#define DCM_BrachyAccessoryDeviceName DcmTagKey(0x300a, 0x0266) +#define DCM_BrachyAccessoryDeviceNominalThickness DcmTagKey(0x300a, 0x026a) +#define DCM_BrachyAccessoryDeviceNominalTransmission DcmTagKey(0x300a, 0x026c) +#define DCM_ChannelSequence DcmTagKey(0x300a, 0x0280) +#define DCM_ChannelNumber DcmTagKey(0x300a, 0x0282) +#define DCM_ChannelLength DcmTagKey(0x300a, 0x0284) +#define DCM_ChannelTotalTime DcmTagKey(0x300a, 0x0286) +#define DCM_SourceMovementType DcmTagKey(0x300a, 0x0288) +#define DCM_NumberOfPulses DcmTagKey(0x300a, 0x028a) +#define DCM_PulseRepetitionInterval DcmTagKey(0x300a, 0x028c) +#define DCM_SourceApplicatorNumber DcmTagKey(0x300a, 0x0290) +#define DCM_SourceApplicatorID DcmTagKey(0x300a, 0x0291) +#define DCM_SourceApplicatorType DcmTagKey(0x300a, 0x0292) +#define DCM_SourceApplicatorName DcmTagKey(0x300a, 0x0294) +#define DCM_SourceApplicatorLength DcmTagKey(0x300a, 0x0296) +#define DCM_SourceApplicatorManufacturer DcmTagKey(0x300a, 0x0298) +#define DCM_SourceApplicatorWallNominalThickness DcmTagKey(0x300a, 0x029c) +#define DCM_SourceApplicatorWallNominalTransmission DcmTagKey(0x300a, 0x029e) +#define DCM_SourceApplicatorStepSize DcmTagKey(0x300a, 0x02a0) +#define DCM_TransferTubeNumber DcmTagKey(0x300a, 0x02a2) +#define DCM_TransferTubeLength DcmTagKey(0x300a, 0x02a4) +#define DCM_ChannelShieldSequence DcmTagKey(0x300a, 0x02b0) +#define DCM_ChannelShieldNumber DcmTagKey(0x300a, 0x02b2) +#define DCM_ChannelShieldID DcmTagKey(0x300a, 0x02b3) +#define DCM_ChannelShieldName DcmTagKey(0x300a, 0x02b4) +#define DCM_ChannelShieldNominalThickness DcmTagKey(0x300a, 0x02b8) +#define DCM_ChannelShieldNominalTransmission DcmTagKey(0x300a, 0x02ba) +#define DCM_FinalCumulativeTimeWeight DcmTagKey(0x300a, 0x02c8) +#define DCM_BrachyControlPointSequence DcmTagKey(0x300a, 0x02d0) +#define DCM_ControlPointRelativePosition DcmTagKey(0x300a, 0x02d2) +#define DCM_ControlPoint3DPosition DcmTagKey(0x300a, 0x02d4) +#define DCM_CumulativeTimeWeight DcmTagKey(0x300a, 0x02d6) +#define DCM_CompensatorDivergence DcmTagKey(0x300a, 0x02e0) +#define DCM_CompensatorMountingPosition DcmTagKey(0x300a, 0x02e1) +#define DCM_SourceToCompensatorDistance DcmTagKey(0x300a, 0x02e2) +#define DCM_TotalCompensatorTrayWaterEquivalentThickness DcmTagKey(0x300a, 0x02e3) +#define DCM_IsocenterToCompensatorTrayDistance DcmTagKey(0x300a, 0x02e4) +#define DCM_CompensatorColumnOffset DcmTagKey(0x300a, 0x02e5) +#define DCM_IsocenterToCompensatorDistances DcmTagKey(0x300a, 0x02e6) +#define DCM_CompensatorRelativeStoppingPowerRatio DcmTagKey(0x300a, 0x02e7) +#define DCM_CompensatorMillingToolDiameter DcmTagKey(0x300a, 0x02e8) +#define DCM_IonRangeCompensatorSequence DcmTagKey(0x300a, 0x02ea) +#define DCM_CompensatorDescription DcmTagKey(0x300a, 0x02eb) +#define DCM_RadiationMassNumber DcmTagKey(0x300a, 0x0302) +#define DCM_RadiationAtomicNumber DcmTagKey(0x300a, 0x0304) +#define DCM_RadiationChargeState DcmTagKey(0x300a, 0x0306) +#define DCM_ScanMode DcmTagKey(0x300a, 0x0308) +#define DCM_VirtualSourceAxisDistances DcmTagKey(0x300a, 0x030a) +#define DCM_SnoutSequence DcmTagKey(0x300a, 0x030c) +#define DCM_SnoutPosition DcmTagKey(0x300a, 0x030d) +#define DCM_SnoutID DcmTagKey(0x300a, 0x030f) +#define DCM_NumberOfRangeShifters DcmTagKey(0x300a, 0x0312) +#define DCM_RangeShifterSequence DcmTagKey(0x300a, 0x0314) +#define DCM_RangeShifterNumber DcmTagKey(0x300a, 0x0316) +#define DCM_RangeShifterID DcmTagKey(0x300a, 0x0318) +#define DCM_RangeShifterType DcmTagKey(0x300a, 0x0320) +#define DCM_RangeShifterDescription DcmTagKey(0x300a, 0x0322) +#define DCM_NumberOfLateralSpreadingDevices DcmTagKey(0x300a, 0x0330) +#define DCM_LateralSpreadingDeviceSequence DcmTagKey(0x300a, 0x0332) +#define DCM_LateralSpreadingDeviceNumber DcmTagKey(0x300a, 0x0334) +#define DCM_LateralSpreadingDeviceID DcmTagKey(0x300a, 0x0336) +#define DCM_LateralSpreadingDeviceType DcmTagKey(0x300a, 0x0338) +#define DCM_LateralSpreadingDeviceDescription DcmTagKey(0x300a, 0x033a) +#define DCM_LateralSpreadingDeviceWaterEquivalentThickness DcmTagKey(0x300a, 0x033c) +#define DCM_NumberOfRangeModulators DcmTagKey(0x300a, 0x0340) +#define DCM_RangeModulatorSequence DcmTagKey(0x300a, 0x0342) +#define DCM_RangeModulatorNumber DcmTagKey(0x300a, 0x0344) +#define DCM_RangeModulatorID DcmTagKey(0x300a, 0x0346) +#define DCM_RangeModulatorType DcmTagKey(0x300a, 0x0348) +#define DCM_RangeModulatorDescription DcmTagKey(0x300a, 0x034a) +#define DCM_BeamCurrentModulationID DcmTagKey(0x300a, 0x034c) +#define DCM_PatientSupportType DcmTagKey(0x300a, 0x0350) +#define DCM_PatientSupportID DcmTagKey(0x300a, 0x0352) +#define DCM_PatientSupportAccessoryCode DcmTagKey(0x300a, 0x0354) +#define DCM_FixationLightAzimuthalAngle DcmTagKey(0x300a, 0x0356) +#define DCM_FixationLightPolarAngle DcmTagKey(0x300a, 0x0358) +#define DCM_MetersetRate DcmTagKey(0x300a, 0x035a) +#define DCM_RangeShifterSettingsSequence DcmTagKey(0x300a, 0x0360) +#define DCM_RangeShifterSetting DcmTagKey(0x300a, 0x0362) +#define DCM_IsocenterToRangeShifterDistance DcmTagKey(0x300a, 0x0364) +#define DCM_RangeShifterWaterEquivalentThickness DcmTagKey(0x300a, 0x0366) +#define DCM_LateralSpreadingDeviceSettingsSequence DcmTagKey(0x300a, 0x0370) +#define DCM_LateralSpreadingDeviceSetting DcmTagKey(0x300a, 0x0372) +#define DCM_IsocenterToLateralSpreadingDeviceDistance DcmTagKey(0x300a, 0x0374) +#define DCM_RangeModulatorSettingsSequence DcmTagKey(0x300a, 0x0380) +#define DCM_RangeModulatorGatingStartValue DcmTagKey(0x300a, 0x0382) +#define DCM_RangeModulatorGatingStopValue DcmTagKey(0x300a, 0x0384) +#define DCM_RangeModulatorGatingStartWaterEquivalentThickness DcmTagKey(0x300a, 0x0386) +#define DCM_RangeModulatorGatingStopWaterEquivalentThickness DcmTagKey(0x300a, 0x0388) +#define DCM_IsocenterToRangeModulatorDistance DcmTagKey(0x300a, 0x038a) +#define DCM_ScanSpotTuneID DcmTagKey(0x300a, 0x0390) +#define DCM_NumberOfScanSpotPositions DcmTagKey(0x300a, 0x0392) +#define DCM_ScanSpotPositionMap DcmTagKey(0x300a, 0x0394) +#define DCM_ScanSpotMetersetWeights DcmTagKey(0x300a, 0x0396) +#define DCM_ScanningSpotSize DcmTagKey(0x300a, 0x0398) +#define DCM_NumberOfPaintings DcmTagKey(0x300a, 0x039a) +#define DCM_IonToleranceTableSequence DcmTagKey(0x300a, 0x03a0) +#define DCM_IonBeamSequence DcmTagKey(0x300a, 0x03a2) +#define DCM_IonBeamLimitingDeviceSequence DcmTagKey(0x300a, 0x03a4) +#define DCM_IonBlockSequence DcmTagKey(0x300a, 0x03a6) +#define DCM_IonControlPointSequence DcmTagKey(0x300a, 0x03a8) +#define DCM_IonWedgeSequence DcmTagKey(0x300a, 0x03aa) +#define DCM_IonWedgePositionSequence DcmTagKey(0x300a, 0x03ac) +#define DCM_ReferencedSetupImageSequence DcmTagKey(0x300a, 0x0401) +#define DCM_SetupImageComment DcmTagKey(0x300a, 0x0402) +#define DCM_MotionSynchronizationSequence DcmTagKey(0x300a, 0x0410) +#define DCM_ControlPointOrientation DcmTagKey(0x300a, 0x0412) +#define DCM_GeneralAccessorySequence DcmTagKey(0x300a, 0x0420) +#define DCM_GeneralAccessoryID DcmTagKey(0x300a, 0x0421) +#define DCM_GeneralAccessoryDescription DcmTagKey(0x300a, 0x0422) +#define DCM_GeneralAccessoryType DcmTagKey(0x300a, 0x0423) +#define DCM_GeneralAccessoryNumber DcmTagKey(0x300a, 0x0424) +#define DCM_SourceToGeneralAccessoryDistance DcmTagKey(0x300a, 0x0425) +#define DCM_ApplicatorGeometrySequence DcmTagKey(0x300a, 0x0431) +#define DCM_ApplicatorApertureShape DcmTagKey(0x300a, 0x0432) +#define DCM_ApplicatorOpening DcmTagKey(0x300a, 0x0433) +#define DCM_ApplicatorOpeningX DcmTagKey(0x300a, 0x0434) +#define DCM_ApplicatorOpeningY DcmTagKey(0x300a, 0x0435) +#define DCM_SourceToApplicatorMountingPositionDistance DcmTagKey(0x300a, 0x0436) +#define DCM_NumberOfBlockSlabItems DcmTagKey(0x300a, 0x0440) +#define DCM_BlockSlabSequence DcmTagKey(0x300a, 0x0441) +#define DCM_BlockSlabThickness DcmTagKey(0x300a, 0x0442) +#define DCM_BlockSlabNumber DcmTagKey(0x300a, 0x0443) +#define DCM_DeviceMotionControlSequence DcmTagKey(0x300a, 0x0450) +#define DCM_DeviceMotionExecutionMode DcmTagKey(0x300a, 0x0451) +#define DCM_DeviceMotionObservationMode DcmTagKey(0x300a, 0x0452) +#define DCM_DeviceMotionParameterCodeSequence DcmTagKey(0x300a, 0x0453) +#define DCM_ReferencedRTPlanSequence DcmTagKey(0x300c, 0x0002) +#define DCM_ReferencedBeamSequence DcmTagKey(0x300c, 0x0004) +#define DCM_ReferencedBeamNumber DcmTagKey(0x300c, 0x0006) +#define DCM_ReferencedReferenceImageNumber DcmTagKey(0x300c, 0x0007) +#define DCM_StartCumulativeMetersetWeight DcmTagKey(0x300c, 0x0008) +#define DCM_EndCumulativeMetersetWeight DcmTagKey(0x300c, 0x0009) +#define DCM_ReferencedBrachyApplicationSetupSequence DcmTagKey(0x300c, 0x000a) +#define DCM_ReferencedBrachyApplicationSetupNumber DcmTagKey(0x300c, 0x000c) +#define DCM_ReferencedSourceNumber DcmTagKey(0x300c, 0x000e) +#define DCM_ReferencedFractionGroupSequence DcmTagKey(0x300c, 0x0020) +#define DCM_ReferencedFractionGroupNumber DcmTagKey(0x300c, 0x0022) +#define DCM_ReferencedVerificationImageSequence DcmTagKey(0x300c, 0x0040) +#define DCM_ReferencedReferenceImageSequence DcmTagKey(0x300c, 0x0042) +#define DCM_ReferencedDoseReferenceSequence DcmTagKey(0x300c, 0x0050) +#define DCM_ReferencedDoseReferenceNumber DcmTagKey(0x300c, 0x0051) +#define DCM_BrachyReferencedDoseReferenceSequence DcmTagKey(0x300c, 0x0055) +#define DCM_ReferencedStructureSetSequence DcmTagKey(0x300c, 0x0060) +#define DCM_ReferencedPatientSetupNumber DcmTagKey(0x300c, 0x006a) +#define DCM_ReferencedDoseSequence DcmTagKey(0x300c, 0x0080) +#define DCM_ReferencedToleranceTableNumber DcmTagKey(0x300c, 0x00a0) +#define DCM_ReferencedBolusSequence DcmTagKey(0x300c, 0x00b0) +#define DCM_ReferencedWedgeNumber DcmTagKey(0x300c, 0x00c0) +#define DCM_ReferencedCompensatorNumber DcmTagKey(0x300c, 0x00d0) +#define DCM_ReferencedBlockNumber DcmTagKey(0x300c, 0x00e0) +#define DCM_ReferencedControlPointIndex DcmTagKey(0x300c, 0x00f0) +#define DCM_ReferencedControlPointSequence DcmTagKey(0x300c, 0x00f2) +#define DCM_ReferencedStartControlPointIndex DcmTagKey(0x300c, 0x00f4) +#define DCM_ReferencedStopControlPointIndex DcmTagKey(0x300c, 0x00f6) +#define DCM_ReferencedRangeShifterNumber DcmTagKey(0x300c, 0x0100) +#define DCM_ReferencedLateralSpreadingDeviceNumber DcmTagKey(0x300c, 0x0102) +#define DCM_ReferencedRangeModulatorNumber DcmTagKey(0x300c, 0x0104) +#define DCM_OmittedBeamTaskSequence DcmTagKey(0x300c, 0x0111) +#define DCM_ReasonForOmission DcmTagKey(0x300c, 0x0112) +#define DCM_ReasonForOmissionDescription DcmTagKey(0x300c, 0x0113) +#define DCM_ApprovalStatus DcmTagKey(0x300e, 0x0002) +#define DCM_ReviewDate DcmTagKey(0x300e, 0x0004) +#define DCM_ReviewTime DcmTagKey(0x300e, 0x0005) +#define DCM_ReviewerName DcmTagKey(0x300e, 0x0008) +#define DCM_RETIRED_Arbitrary DcmTagKey(0x4000, 0x0010) +#define DCM_RETIRED_TextComments DcmTagKey(0x4000, 0x4000) +#define DCM_RETIRED_ResultsID DcmTagKey(0x4008, 0x0040) +#define DCM_RETIRED_ResultsIDIssuer DcmTagKey(0x4008, 0x0042) +#define DCM_RETIRED_ReferencedInterpretationSequence DcmTagKey(0x4008, 0x0050) +#define DCM_RETIRED_ReportProductionStatusTrial DcmTagKey(0x4008, 0x00ff) +#define DCM_RETIRED_InterpretationRecordedDate DcmTagKey(0x4008, 0x0100) +#define DCM_RETIRED_InterpretationRecordedTime DcmTagKey(0x4008, 0x0101) +#define DCM_RETIRED_InterpretationRecorder DcmTagKey(0x4008, 0x0102) +#define DCM_RETIRED_ReferenceToRecordedSound DcmTagKey(0x4008, 0x0103) +#define DCM_RETIRED_InterpretationTranscriptionDate DcmTagKey(0x4008, 0x0108) +#define DCM_RETIRED_InterpretationTranscriptionTime DcmTagKey(0x4008, 0x0109) +#define DCM_RETIRED_InterpretationTranscriber DcmTagKey(0x4008, 0x010a) +#define DCM_RETIRED_InterpretationText DcmTagKey(0x4008, 0x010b) +#define DCM_RETIRED_InterpretationAuthor DcmTagKey(0x4008, 0x010c) +#define DCM_RETIRED_InterpretationApproverSequence DcmTagKey(0x4008, 0x0111) +#define DCM_RETIRED_InterpretationApprovalDate DcmTagKey(0x4008, 0x0112) +#define DCM_RETIRED_InterpretationApprovalTime DcmTagKey(0x4008, 0x0113) +#define DCM_RETIRED_PhysicianApprovingInterpretation DcmTagKey(0x4008, 0x0114) +#define DCM_RETIRED_InterpretationDiagnosisDescription DcmTagKey(0x4008, 0x0115) +#define DCM_RETIRED_InterpretationDiagnosisCodeSequence DcmTagKey(0x4008, 0x0117) +#define DCM_RETIRED_ResultsDistributionListSequence DcmTagKey(0x4008, 0x0118) +#define DCM_RETIRED_DistributionName DcmTagKey(0x4008, 0x0119) +#define DCM_RETIRED_DistributionAddress DcmTagKey(0x4008, 0x011a) +#define DCM_RETIRED_InterpretationID DcmTagKey(0x4008, 0x0200) +#define DCM_RETIRED_InterpretationIDIssuer DcmTagKey(0x4008, 0x0202) +#define DCM_RETIRED_InterpretationTypeID DcmTagKey(0x4008, 0x0210) +#define DCM_RETIRED_InterpretationStatusID DcmTagKey(0x4008, 0x0212) +#define DCM_RETIRED_Impressions DcmTagKey(0x4008, 0x0300) +#define DCM_RETIRED_ResultsComments DcmTagKey(0x4008, 0x4000) +#define DCM_LowEnergyDetectors DcmTagKey(0x4010, 0x0001) +#define DCM_HighEnergyDetectors DcmTagKey(0x4010, 0x0002) +#define DCM_DetectorGeometrySequence DcmTagKey(0x4010, 0x0004) +#define DCM_ThreatROIVoxelSequence DcmTagKey(0x4010, 0x1001) +#define DCM_ThreatROIBase DcmTagKey(0x4010, 0x1004) +#define DCM_ThreatROIExtents DcmTagKey(0x4010, 0x1005) +#define DCM_ThreatROIBitmap DcmTagKey(0x4010, 0x1006) +#define DCM_RouteSegmentID DcmTagKey(0x4010, 0x1007) +#define DCM_GantryType DcmTagKey(0x4010, 0x1008) +#define DCM_OOIOwnerType DcmTagKey(0x4010, 0x1009) +#define DCM_RouteSegmentSequence DcmTagKey(0x4010, 0x100a) +#define DCM_PotentialThreatObjectID DcmTagKey(0x4010, 0x1010) +#define DCM_ThreatSequence DcmTagKey(0x4010, 0x1011) +#define DCM_ThreatCategory DcmTagKey(0x4010, 0x1012) +#define DCM_ThreatCategoryDescription DcmTagKey(0x4010, 0x1013) +#define DCM_ATDAbilityAssessment DcmTagKey(0x4010, 0x1014) +#define DCM_ATDAssessmentFlag DcmTagKey(0x4010, 0x1015) +#define DCM_ATDAssessmentProbability DcmTagKey(0x4010, 0x1016) +#define DCM_Mass DcmTagKey(0x4010, 0x1017) +#define DCM_Density DcmTagKey(0x4010, 0x1018) +#define DCM_ZEffective DcmTagKey(0x4010, 0x1019) +#define DCM_BoardingPassID DcmTagKey(0x4010, 0x101a) +#define DCM_CenterOfMass DcmTagKey(0x4010, 0x101b) +#define DCM_CenterOfPTO DcmTagKey(0x4010, 0x101c) +#define DCM_BoundingPolygon DcmTagKey(0x4010, 0x101d) +#define DCM_RouteSegmentStartLocationID DcmTagKey(0x4010, 0x101e) +#define DCM_RouteSegmentEndLocationID DcmTagKey(0x4010, 0x101f) +#define DCM_RouteSegmentLocationIDType DcmTagKey(0x4010, 0x1020) +#define DCM_AbortReason DcmTagKey(0x4010, 0x1021) +#define DCM_VolumeOfPTO DcmTagKey(0x4010, 0x1023) +#define DCM_AbortFlag DcmTagKey(0x4010, 0x1024) +#define DCM_RouteSegmentStartTime DcmTagKey(0x4010, 0x1025) +#define DCM_RouteSegmentEndTime DcmTagKey(0x4010, 0x1026) +#define DCM_TDRType DcmTagKey(0x4010, 0x1027) +#define DCM_InternationalRouteSegment DcmTagKey(0x4010, 0x1028) +#define DCM_ThreatDetectionAlgorithmandVersion DcmTagKey(0x4010, 0x1029) +#define DCM_AssignedLocation DcmTagKey(0x4010, 0x102a) +#define DCM_AlarmDecisionTime DcmTagKey(0x4010, 0x102b) +#define DCM_AlarmDecision DcmTagKey(0x4010, 0x1031) +#define DCM_NumberOfTotalObjects DcmTagKey(0x4010, 0x1033) +#define DCM_NumberOfAlarmObjects DcmTagKey(0x4010, 0x1034) +#define DCM_PTORepresentationSequence DcmTagKey(0x4010, 0x1037) +#define DCM_ATDAssessmentSequence DcmTagKey(0x4010, 0x1038) +#define DCM_TIPType DcmTagKey(0x4010, 0x1039) +#define DCM_DICOSVersion DcmTagKey(0x4010, 0x103a) +#define DCM_OOIOwnerCreationTime DcmTagKey(0x4010, 0x1041) +#define DCM_OOIType DcmTagKey(0x4010, 0x1042) +#define DCM_OOISize DcmTagKey(0x4010, 0x1043) +#define DCM_AcquisitionStatus DcmTagKey(0x4010, 0x1044) +#define DCM_BasisMaterialsCodeSequence DcmTagKey(0x4010, 0x1045) +#define DCM_PhantomType DcmTagKey(0x4010, 0x1046) +#define DCM_OOIOwnerSequence DcmTagKey(0x4010, 0x1047) +#define DCM_ScanType DcmTagKey(0x4010, 0x1048) +#define DCM_ItineraryID DcmTagKey(0x4010, 0x1051) +#define DCM_ItineraryIDType DcmTagKey(0x4010, 0x1052) +#define DCM_ItineraryIDAssigningAuthority DcmTagKey(0x4010, 0x1053) +#define DCM_RouteID DcmTagKey(0x4010, 0x1054) +#define DCM_RouteIDAssigningAuthority DcmTagKey(0x4010, 0x1055) +#define DCM_InboundArrivalType DcmTagKey(0x4010, 0x1056) +#define DCM_CarrierID DcmTagKey(0x4010, 0x1058) +#define DCM_CarrierIDAssigningAuthority DcmTagKey(0x4010, 0x1059) +#define DCM_SourceOrientation DcmTagKey(0x4010, 0x1060) +#define DCM_SourcePosition DcmTagKey(0x4010, 0x1061) +#define DCM_BeltHeight DcmTagKey(0x4010, 0x1062) +#define DCM_AlgorithmRoutingCodeSequence DcmTagKey(0x4010, 0x1064) +#define DCM_TransportClassification DcmTagKey(0x4010, 0x1067) +#define DCM_OOITypeDescriptor DcmTagKey(0x4010, 0x1068) +#define DCM_TotalProcessingTime DcmTagKey(0x4010, 0x1069) +#define DCM_DetectorCalibrationData DcmTagKey(0x4010, 0x106c) +#define DCM_AdditionalScreeningPerformed DcmTagKey(0x4010, 0x106d) +#define DCM_AdditionalInspectionSelectionCriteria DcmTagKey(0x4010, 0x106e) +#define DCM_AdditionalInspectionMethodSequence DcmTagKey(0x4010, 0x106f) +#define DCM_AITDeviceType DcmTagKey(0x4010, 0x1070) +#define DCM_QRMeasurementsSequence DcmTagKey(0x4010, 0x1071) +#define DCM_TargetMaterialSequence DcmTagKey(0x4010, 0x1072) +#define DCM_SNRThreshold DcmTagKey(0x4010, 0x1073) +#define DCM_ImageScaleRepresentation DcmTagKey(0x4010, 0x1075) +#define DCM_ReferencedPTOSequence DcmTagKey(0x4010, 0x1076) +#define DCM_ReferencedTDRInstanceSequence DcmTagKey(0x4010, 0x1077) +#define DCM_PTOLocationDescription DcmTagKey(0x4010, 0x1078) +#define DCM_AnomalyLocatorIndicatorSequence DcmTagKey(0x4010, 0x1079) +#define DCM_AnomalyLocatorIndicator DcmTagKey(0x4010, 0x107a) +#define DCM_PTORegionSequence DcmTagKey(0x4010, 0x107b) +#define DCM_InspectionSelectionCriteria DcmTagKey(0x4010, 0x107c) +#define DCM_SecondaryInspectionMethodSequence DcmTagKey(0x4010, 0x107d) +#define DCM_PRCSToRCSOrientation DcmTagKey(0x4010, 0x107e) +#define DCM_MACParametersSequence DcmTagKey(0x4ffe, 0x0001) +#define DCM_SharedFunctionalGroupsSequence DcmTagKey(0x5200, 0x9229) +#define DCM_PerFrameFunctionalGroupsSequence DcmTagKey(0x5200, 0x9230) +#define DCM_WaveformSequence DcmTagKey(0x5400, 0x0100) +#define DCM_ChannelMinimumValue DcmTagKey(0x5400, 0x0110) +#define DCM_ChannelMaximumValue DcmTagKey(0x5400, 0x0112) +#define DCM_WaveformBitsAllocated DcmTagKey(0x5400, 0x1004) +#define DCM_WaveformSampleInterpretation DcmTagKey(0x5400, 0x1006) +#define DCM_WaveformPaddingValue DcmTagKey(0x5400, 0x100a) +#define DCM_WaveformData DcmTagKey(0x5400, 0x1010) +#define DCM_FirstOrderPhaseCorrectionAngle DcmTagKey(0x5600, 0x0010) +#define DCM_SpectroscopyData DcmTagKey(0x5600, 0x0020) +#define DCM_FloatPixelData DcmTagKey(0x7fe0, 0x0008) +#define DCM_DoubleFloatPixelData DcmTagKey(0x7fe0, 0x0009) +#define DCM_PixelData DcmTagKey(0x7fe0, 0x0010) +#define DCM_RETIRED_CoefficientsSDVN DcmTagKey(0x7fe0, 0x0020) +#define DCM_RETIRED_CoefficientsSDHN DcmTagKey(0x7fe0, 0x0030) +#define DCM_RETIRED_CoefficientsSDDN DcmTagKey(0x7fe0, 0x0040) +#define DCM_DigitalSignaturesSequence DcmTagKey(0xfffa, 0xfffa) +#define DCM_DataSetTrailingPadding DcmTagKey(0xfffc, 0xfffc) +#define DCM_Item DcmTagKey(0xfffe, 0xe000) +#define DCM_ItemDelimitationItem DcmTagKey(0xfffe, 0xe00d) +#define DCM_SequenceDelimitationItem DcmTagKey(0xfffe, 0xe0dd) + +/* +** Tags where the group/element can vary (repeating tags). +** Number of entries: 77 +*/ +#define DCM_OverlayRows DcmTagKey(0x6000, 0x0010) /* (0x6000-0x60ff,0x0010) */ +#define DCM_OverlayColumns DcmTagKey(0x6000, 0x0011) /* (0x6000-0x60ff,0x0011) */ +#define DCM_NumberOfFramesInOverlay DcmTagKey(0x6000, 0x0015) /* (0x6000-0x60ff,0x0015) */ +#define DCM_OverlayDescription DcmTagKey(0x6000, 0x0022) /* (0x6000-0x60ff,0x0022) */ +#define DCM_OverlayType DcmTagKey(0x6000, 0x0040) /* (0x6000-0x60ff,0x0040) */ +#define DCM_OverlaySubtype DcmTagKey(0x6000, 0x0045) /* (0x6000-0x60ff,0x0045) */ +#define DCM_OverlayOrigin DcmTagKey(0x6000, 0x0050) /* (0x6000-0x60ff,0x0050) */ +#define DCM_ImageFrameOrigin DcmTagKey(0x6000, 0x0051) /* (0x6000-0x60ff,0x0051) */ +#define DCM_OverlayBitsAllocated DcmTagKey(0x6000, 0x0100) /* (0x6000-0x60ff,0x0100) */ +#define DCM_OverlayBitPosition DcmTagKey(0x6000, 0x0102) /* (0x6000-0x60ff,0x0102) */ +#define DCM_OverlayActivationLayer DcmTagKey(0x6000, 0x1001) /* (0x6000-0x60ff,0x1001) */ +#define DCM_ROIArea DcmTagKey(0x6000, 0x1301) /* (0x6000-0x60ff,0x1301) */ +#define DCM_ROIMean DcmTagKey(0x6000, 0x1302) /* (0x6000-0x60ff,0x1302) */ +#define DCM_ROIStandardDeviation DcmTagKey(0x6000, 0x1303) /* (0x6000-0x60ff,0x1303) */ +#define DCM_OverlayLabel DcmTagKey(0x6000, 0x1500) /* (0x6000-0x60ff,0x1500) */ +#define DCM_OverlayData DcmTagKey(0x6000, 0x3000) /* (0x6000-0x60ff,0x3000) */ +#define DCM_PrivateGroupLength DcmTagKey(0x0009, 0x0000) /* (0x0009-o-0xffff,0x0000) */ +#define DCM_RETIRED_NumberOfPoints DcmTagKey(0x5000, 0x0010) /* (0x5000-0x50ff,0x0010) */ +#define DCM_RETIRED_TypeOfData DcmTagKey(0x5000, 0x0020) /* (0x5000-0x50ff,0x0020) */ +#define DCM_RETIRED_CurveDescription DcmTagKey(0x5000, 0x0022) /* (0x5000-0x50ff,0x0022) */ +#define DCM_RETIRED_AxisUnits DcmTagKey(0x5000, 0x0030) /* (0x5000-0x50ff,0x0030) */ +#define DCM_RETIRED_AxisLabels DcmTagKey(0x5000, 0x0040) /* (0x5000-0x50ff,0x0040) */ +#define DCM_RETIRED_OverlayPlanes DcmTagKey(0x6000, 0x0012) /* (0x6000-0x60ff,0x0012) */ +#define DCM_RETIRED_OverlayPlaneOrigin DcmTagKey(0x6000, 0x0052) /* (0x6000-0x60ff,0x0052) */ +#define DCM_RETIRED_OverlayCompressionCode DcmTagKey(0x6000, 0x0060) /* (0x6000-0x60ff,0x0060) */ +#define DCM_RETIRED_OverlayCompressionOriginator DcmTagKey(0x6000, 0x0061) /* (0x6000-0x60ff,0x0061) */ +#define DCM_RETIRED_OverlayCompressionLabel DcmTagKey(0x6000, 0x0062) /* (0x6000-0x60ff,0x0062) */ +#define DCM_RETIRED_OverlayCompressionDescription DcmTagKey(0x6000, 0x0063) /* (0x6000-0x60ff,0x0063) */ +#define DCM_RETIRED_OverlayCompressionStepPointers DcmTagKey(0x6000, 0x0066) /* (0x6000-0x60ff,0x0066) */ +#define DCM_RETIRED_OverlayRepeatInterval DcmTagKey(0x6000, 0x0068) /* (0x6000-0x60ff,0x0068) */ +#define DCM_RETIRED_OverlayBitsGrouped DcmTagKey(0x6000, 0x0069) /* (0x6000-0x60ff,0x0069) */ +#define DCM_RETIRED_VariablePixelData DcmTagKey(0x7f00, 0x0010) /* (0x7f00-0x7fff,0x0010) */ +#define DCM_RETIRED_VariableNextDataGroup DcmTagKey(0x7f00, 0x0011) /* (0x7f00-0x7fff,0x0011) */ +#define DCM_RETIRED_VariableCoefficientsSDVN DcmTagKey(0x7f00, 0x0020) /* (0x7f00-0x7fff,0x0020) */ +#define DCM_RETIRED_VariableCoefficientsSDHN DcmTagKey(0x7f00, 0x0030) /* (0x7f00-0x7fff,0x0030) */ +#define DCM_RETIRED_VariableCoefficientsSDDN DcmTagKey(0x7f00, 0x0040) /* (0x7f00-0x7fff,0x0040) */ +#define DCM_PrivateCreator DcmTagKey(0x0009, 0x0010) /* (0x0009-o-0xffff,0x0010-u-0x00ff) */ +#define DCM_IllegalGroupLength DcmTagKey(0x0001, 0x0000) /* (0x0001-o-0x0007,0x0000) */ +#define DCM_IllegalPrivateCreator DcmTagKey(0x0001, 0x0010) /* (0x0001-o-0x0007,0x0010-u-0x00ff) */ +#define DCM_GenericGroupLength DcmTagKey(0x0000, 0x0000) /* (0x0000-u-0xffff,0x0000) */ +#define DCM_RETIRED_SourceImageIDs DcmTagKey(0x0020, 0x3100) /* (0x0020,0x3100-0x31ff) */ +#define DCM_RETIRED_CurveDimensions DcmTagKey(0x5000, 0x0005) /* (0x5000-0x50ff,0x0005) */ +#define DCM_RETIRED_DataValueRepresentation DcmTagKey(0x5000, 0x0103) /* (0x5000-0x50ff,0x0103) */ +#define DCM_RETIRED_MinimumCoordinateValue DcmTagKey(0x5000, 0x0104) /* (0x5000-0x50ff,0x0104) */ +#define DCM_RETIRED_MaximumCoordinateValue DcmTagKey(0x5000, 0x0105) /* (0x5000-0x50ff,0x0105) */ +#define DCM_RETIRED_CurveRange DcmTagKey(0x5000, 0x0106) /* (0x5000-0x50ff,0x0106) */ +#define DCM_RETIRED_CurveDataDescriptor DcmTagKey(0x5000, 0x0110) /* (0x5000-0x50ff,0x0110) */ +#define DCM_RETIRED_CoordinateStartValue DcmTagKey(0x5000, 0x0112) /* (0x5000-0x50ff,0x0112) */ +#define DCM_RETIRED_CoordinateStepValue DcmTagKey(0x5000, 0x0114) /* (0x5000-0x50ff,0x0114) */ +#define DCM_RETIRED_CurveActivationLayer DcmTagKey(0x5000, 0x1001) /* (0x5000-0x50ff,0x1001) */ +#define DCM_RETIRED_AudioType DcmTagKey(0x5000, 0x2000) /* (0x5000-0x50ff,0x2000) */ +#define DCM_RETIRED_AudioSampleFormat DcmTagKey(0x5000, 0x2002) /* (0x5000-0x50ff,0x2002) */ +#define DCM_RETIRED_NumberOfChannels DcmTagKey(0x5000, 0x2004) /* (0x5000-0x50ff,0x2004) */ +#define DCM_RETIRED_NumberOfSamples DcmTagKey(0x5000, 0x2006) /* (0x5000-0x50ff,0x2006) */ +#define DCM_RETIRED_SampleRate DcmTagKey(0x5000, 0x2008) /* (0x5000-0x50ff,0x2008) */ +#define DCM_RETIRED_TotalTime DcmTagKey(0x5000, 0x200a) /* (0x5000-0x50ff,0x200a) */ +#define DCM_RETIRED_AudioSampleData DcmTagKey(0x5000, 0x200c) /* (0x5000-0x50ff,0x200c) */ +#define DCM_RETIRED_AudioComments DcmTagKey(0x5000, 0x200e) /* (0x5000-0x50ff,0x200e) */ +#define DCM_RETIRED_CurveLabel DcmTagKey(0x5000, 0x2500) /* (0x5000-0x50ff,0x2500) */ +#define DCM_RETIRED_CurveReferencedOverlaySequence DcmTagKey(0x5000, 0x2600) /* (0x5000-0x50ff,0x2600) */ +#define DCM_RETIRED_CurveReferencedOverlayGroup DcmTagKey(0x5000, 0x2610) /* (0x5000-0x50ff,0x2610) */ +#define DCM_RETIRED_CurveData DcmTagKey(0x5000, 0x3000) /* (0x5000-0x50ff,0x3000) */ +#define DCM_RETIRED_OverlayFormat DcmTagKey(0x6000, 0x0110) /* (0x6000-0x60ff,0x0110) */ +#define DCM_RETIRED_OverlayLocation DcmTagKey(0x6000, 0x0200) /* (0x6000-0x60ff,0x0200) */ +#define DCM_RETIRED_OverlayCodeLabel DcmTagKey(0x6000, 0x0800) /* (0x6000-0x60ff,0x0800) */ +#define DCM_RETIRED_OverlayNumberOfTables DcmTagKey(0x6000, 0x0802) /* (0x6000-0x60ff,0x0802) */ +#define DCM_RETIRED_OverlayCodeTableLocation DcmTagKey(0x6000, 0x0803) /* (0x6000-0x60ff,0x0803) */ +#define DCM_RETIRED_OverlayBitsForCodeWord DcmTagKey(0x6000, 0x0804) /* (0x6000-0x60ff,0x0804) */ +#define DCM_RETIRED_OverlayDescriptorGray DcmTagKey(0x6000, 0x1100) /* (0x6000-0x60ff,0x1100) */ +#define DCM_RETIRED_OverlayDescriptorRed DcmTagKey(0x6000, 0x1101) /* (0x6000-0x60ff,0x1101) */ +#define DCM_RETIRED_OverlayDescriptorGreen DcmTagKey(0x6000, 0x1102) /* (0x6000-0x60ff,0x1102) */ +#define DCM_RETIRED_OverlayDescriptorBlue DcmTagKey(0x6000, 0x1103) /* (0x6000-0x60ff,0x1103) */ +#define DCM_RETIRED_OverlaysGray DcmTagKey(0x6000, 0x1200) /* (0x6000-0x60ff,0x1200) */ +#define DCM_RETIRED_OverlaysRed DcmTagKey(0x6000, 0x1201) /* (0x6000-0x60ff,0x1201) */ +#define DCM_RETIRED_OverlaysGreen DcmTagKey(0x6000, 0x1202) /* (0x6000-0x60ff,0x1202) */ +#define DCM_RETIRED_OverlaysBlue DcmTagKey(0x6000, 0x1203) /* (0x6000-0x60ff,0x1203) */ +#define DCM_RETIRED_OverlayComments DcmTagKey(0x6000, 0x4000) /* (0x6000-0x60ff,0x4000) */ + +#endif /* !DCDEFTAG_H */ diff --git a/dcmdata/include/dcmtk/dcmdata/dcdicdir.h b/dcmdata/include/dcmtk/dcmdata/dcdicdir.h new file mode 100644 index 00000000..f7126019 --- /dev/null +++ b/dcmdata/include/dcmtk/dcmdata/dcdicdir.h @@ -0,0 +1,221 @@ +/* + * + * Copyright (C) 1994-2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Gerd Ehlers, Andreas Barth + * + * Purpose: Interface of class DcmDicomDir + * + */ + +#ifndef DCDICDIR_H +#define DCDICDIR_H + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/ofstd/ofmap.h" +#include "dcmtk/dcmdata/dcdirrec.h" +#include "dcmtk/dcmdata/dcvrulup.h" + + +#define DEFAULT_DICOMDIR_NAME "DICOMDIR" +#define DICOMDIR_BACKUP_SUFFIX ".$$$" +#define DICOMDIR_TEMP_SUFFIX ".tmp" +#define DICOMDIR_DEFAULT_TRANSFERSYNTAX EXS_LittleEndianExplicit + +/** helper structure for item offsets + */ +typedef struct +{ + /// DICOM item containing a directory record + DcmItem *item; + /// offset in file for this item + Uint32 fileOffset; +} ItemOffset; + + +/** this class implements support for DICOMDIR files, which are special DICOM files + * containing a list of directory records, with a logical tree structure being + * implemented through references between records as byte offsets in file. + */ +class DCMTK_DCMDATA_EXPORT DcmDicomDir +{ +public: + /// default constructor + DcmDicomDir(); + + /** constructor + * @param fileName filename to read a DICOMDIR from. If empty, an attempt is + * made to read file DEFAULT_DICOMDIR_NAME ("DICOMDIR"). + * @param fileSetID file set ID of this file set, used only for new DICOMDIRs + */ + DcmDicomDir( const OFFilename &fileName, + const char *fileSetID = NULL ); // only used for new DICOMDIR + + /// destructor. If DICOMDIR was modified, writes new file. + virtual ~DcmDicomDir(); + + /** print all elements of the item to a stream + * @param out output stream + * @param flags optional flag used to customize the output (see DCMTypes::PF_xxx) + * @param level current level of nested items. Used for indentation. + * @param pixelFileName not used + * @param pixelCounter not used + */ + virtual void print(STD_NAMESPACE ostream&out, + const size_t flags = 0, + const int level = 0, + const char *pixelFileName = NULL, + size_t *pixelCounter = NULL); + + /// returns current status flag + virtual OFCondition error(); + + /** returns reference to DICOM file from which DICOMDIR was read. + * Note, this file may be obsolete if the DICOMDIR was modified + * @return reference to DICOM file + */ + virtual DcmFileFormat& getDirFileFormat(); + + /** returns file name from which DICOMDIR was read. + * @return filename of DICOMDIR + */ + virtual const OFFilename &getDirFileName(); + + /// returns root directory record + virtual DcmDirectoryRecord& getRootRecord(); + + /// returns container in which all MRDR (multi-reference directory records) are stored + virtual DcmSequenceOfItems& getMRDRSequence(); + + /** look up directory record for the given referenced file ID (not OS file path) + * @return directory record if found, NULL otherwise + */ + virtual DcmDirectoryRecord* matchFilename( const char *filename ); + + /** look up MRDR for the given referenced file ID (not OS file path). + * If there is none yet, create one. + * @return MRDR for given referenced file ID + */ + virtual DcmDirectoryRecord* matchOrCreateMRDR( const char *filename ); + + /** writes DICOMDIR to file + * @param oxfer must be DICOMDIR_DEFAULT_TRANSFERSYNTAX + * @param enctype encoding type for sequences + * @param glenc encoding type for group lengths + * @return status, EC_Normal if value length is correct, an error code otherwise + */ + virtual OFCondition write( + const E_TransferSyntax oxfer = DICOMDIR_DEFAULT_TRANSFERSYNTAX, + const E_EncodingType enctype = EET_UndefinedLength, + const E_GrpLenEncoding glenc = EGL_withoutGL ); + + /** check the currently stored element value + * @param autocorrect correct value length if OFTrue + * @return status, EC_Normal if value length is correct, an error code otherwise + */ + virtual OFCondition verify( OFBool autocorrect = OFFalse ); + + protected: + + // Manipulation of member variables + OFCondition createNewElements(const char* fileSetID); // in + DcmDataset& getDataset(void); + + // side-effect free methods for manipulation and conversion + DcmSequenceOfItems& getDirRecSeq( DcmDataset &dset ); // inout + DcmUnsignedLongOffset* lookForOffsetElem( DcmObject *obj, // in + const DcmTagKey &offsetTag ); // in + DcmDirectoryRecord* recurseMatchFile( DcmDirectoryRecord* startRec, // in + const char *filename ); // in + DcmDirectoryRecord* searchMatchFile( DcmSequenceOfItems& recSeq, // in + const char *filename ); // in + OFCondition resolveGivenOffsets( DcmObject *startPoint, // inout + const OFMap &itOffsets, // in + const DcmTagKey &offsetTag ); // in + OFCondition resolveAllOffsets( DcmDataset &dset ); // inout + OFCondition linkMRDRtoRecord( DcmDirectoryRecord *dRec ); // inout + OFCondition moveRecordToTree( DcmDirectoryRecord *startRec, // in + DcmSequenceOfItems &fromDirSQ, // inout + DcmDirectoryRecord *toRecord ); // inout + OFCondition moveMRDRbetweenSQs( DcmSequenceOfItems &fromSQ, // in + DcmSequenceOfItems &toDirSQ ); // inout + Uint32 lengthUntilSQ( DcmDataset &dset, // in + E_TransferSyntax oxfer, // in + E_EncodingType enctype ); // in + Uint32 lengthOfRecord( DcmItem *item, // in + E_TransferSyntax oxfer, // in + E_EncodingType enctype ); // in + OFCondition convertGivenPointer( DcmObject *startPoint, // inout + const DcmTagKey &offsetTag ); // in + OFCondition convertAllPointer( DcmDataset &dset, // inout + Uint32 beginOfFileSet, // in + E_TransferSyntax oxfer, // in + E_EncodingType enctype ); // in + OFCondition copyRecordPtrToSQ( DcmDirectoryRecord *record, // in + DcmSequenceOfItems &toDirSQ, // inout + DcmDirectoryRecord **firstRec, // out + DcmDirectoryRecord **lastRec ); // out + OFCondition insertMediaSOPUID( DcmMetaInfo &metaInfo ); // inout + OFCondition countMRDRRefs( DcmDirectoryRecord *startRec, // in + ItemOffset *refCounter, // inout + const unsigned long numCounters ); // in + OFCondition checkMRDRRefCounter( DcmDirectoryRecord *startRec, // in + ItemOffset *refCounter, // inout + const unsigned long numCounters ); // in + + // complete re-organization of the managed directory records (side effect) + OFCondition convertLinearToTree(); + + OFCondition convertTreeToLinear( Uint32 beginOfFileSet, // in + E_TransferSyntax oxfer, // in + E_EncodingType enctype, // in + E_GrpLenEncoding glenc, // in + DcmSequenceOfItems &unresRecs);// inout + + private: + + /// private undefined copy assignment operator + DcmDicomDir &operator=(const DcmDicomDir &); + + /// private undefined copy constructor + DcmDicomDir( const DcmDicomDir &newDir ); + + /// condition flag + OFCondition errorFlag; + + /// file name the DICOMDIR was read from, or DEFAULT_DICOMDIR_NAME + OFFilename dicomDirFileName; + + /** flag indicating whether or not this DICOMDIR has been modified after being read from file. + * If true, the destructor of this class will write the modified DICOMDIR back to file + */ + OFBool modified; + + /// flag indicating whether the DICOM file in DirFile needs to be re-created upon writing + OFBool mustCreateNewDir; + + /** DICOM file into which a DICOMDIR is read first before the logical tree + * structure is created. + */ + DcmFileFormat * DirFile; + + /// root directory record of this DICOMDIR + DcmDirectoryRecord * RootRec; + + /// container in which all MRDR (multi-reference directory records) for this DICOMDIR are kept + DcmSequenceOfItems * MRDRSeq; +}; + +#endif // DCDICDIR_H diff --git a/dcmdata/include/dcmtk/dcmdata/dcdicent.h b/dcmdata/include/dcmtk/dcmdata/dcdicent.h new file mode 100644 index 00000000..e25815c8 --- /dev/null +++ b/dcmdata/include/dcmtk/dcmdata/dcdicent.h @@ -0,0 +1,400 @@ +/* + * + * Copyright (C) 1994-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Andrew Hewett + * + * Purpose: Interface for a dictionary entry in the loadable DICOM data dictionary + * + */ + +#ifndef DCDICENT_H +#define DCDICENT_H + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ +#include "dcmtk/dcmdata/dctagkey.h" +#include "dcmtk/dcmdata/dcvr.h" + +#define INCLUDE_CSTRING /* for strcmp() */ +#include "dcmtk/ofstd/ofstdinc.h" + +/// constant describing an unlimited VM +#define DcmVariableVM -1 + +#define DCM_INRANGE(x,a,b) (((x) >= (a)) && ((x) <= (b))) +#define DCM_IS_ODD(x) (((x) % 2) == 1) +#define DCM_IS_EVEN(x) (((x) % 2) == 0) + + +/** attribute tag group/element range restrictions + */ +enum DcmDictRangeRestriction +{ + /// integer range + DcmDictRange_Unspecified, + + /// odd range + DcmDictRange_Odd, + + /// even range + DcmDictRange_Even +}; + + +/** each object of this class manages one entry of the + * global DICOM data dictionary. + */ +class DCMTK_DCMDATA_EXPORT DcmDictEntry: public DcmTagKey +{ +public: + + /** constructor + * @param g attribute tag group + * @param e attribute tag element + * @param vr value representation + * @param nam attribute name + * @param vmMin lower limit for value multiplicity + * @param vmMax upper limit for value multiplicity, DcmVariableVM for unlimited + * @param vers standard version name, may be NULL + * @param doCopyStrings true if strings should be copied, false if only referenced + * @param pcreator private creator name, may be NULL (for standard tags) + */ + DcmDictEntry(Uint16 g, Uint16 e, DcmVR vr, + const char* nam, int vmMin, int vmMax, + const char* vers, OFBool doCopyStrings, + const char* pcreator); + + /** constructor for repeating tags + * @param g attribute tag group lower limit + * @param e attribute tag element lower limit + * @param ug attribute tag group upper limit + * @param ue attribute tag element upper limit + * @param vr value representation + * @param nam attribute name + * @param vmMin lower limit for value multiplicity + * @param vmMax upper limit for value multiplicity, DcmVariableVM for unlimited + * @param vers standard version name, may be NULL + * @param doCopyStrings true if strings should be copied, false if only referenced + * @param pcreator private creator name, may be NULL (for standard tags) + */ + DcmDictEntry(Uint16 g, Uint16 e, Uint16 ug, Uint16 ue, DcmVR vr, + const char* nam, int vmMin, int vmMax, + const char* vers, OFBool doCopyStrings, + const char* pcreator); + + /// copy constructor + DcmDictEntry(const DcmDictEntry& e); + + /// destructor + ~DcmDictEntry(); + + /* access methods */ + + /// returns VR object by value + DcmVR getVR() const + { + return valueRepresentation; + } + + /// returns VR code + DcmEVR getEVR() const + { + return valueRepresentation.getEVR(); + } + + /// returns standard version string, may be NULL + const char* getStandardVersion() const + { + return standardVersion; + } + + /// returns tag name + const char* getTagName() const + { + return tagName; + } + + /// returns private creator code, may be NULL + const char* getPrivateCreator() const + { + return privateCreator; + } + + /** checks if the private creator code equals the given string + * @param c string to compare with, may be NULL + * @return true if equal, false otherwise + */ + int privateCreatorMatch(const char *c) const + { + return + ( + ((privateCreator == NULL) && (c == NULL)) || + (privateCreator && c && (0 == strcmp(privateCreator, c))) + ); + } + + /** checks if the private creator code of this object matches + * the one of the given object. + * @param arg dictionary entry to compare with + * @return true if private creators are equal, false otherwise + */ + int privateCreatorMatch(const DcmDictEntry& arg) const + { + return privateCreatorMatch(arg.privateCreator); + } + + /// returns lower limit for VM (value multiplicity) + int getVMMin() const + { + return valueMultiplicityMin; + } + + /// returns upper limit for VM (value multiplicity), DcmVariableVM for unlimited + int getVMMax() const + { + return valueMultiplicityMax; + } + + /// returns true if element has a single valid VM value + OFBool isFixedSingleVM() const + { + return ((valueMultiplicityMin != DcmVariableVM) && + (valueMultiplicityMin == valueMultiplicityMax)); + } + + /// returns true if element has a fixed VM range + OFBool isFixedRangeVM() const + { + return ((valueMultiplicityMin != DcmVariableVM) && + (valueMultiplicityMax != DcmVariableVM)); + } + + /// returns true if element has a variable VM range (no upper limit) + OFBool isVariableRangeVM() const + { + return ((valueMultiplicityMin != DcmVariableVM) && + (valueMultiplicityMax == DcmVariableVM)); + } + + /** converts entry into repeating tag entry by defining an upper limit + * for group and element, taken from the given tag key. + * @param key tag key containing upper limit for group and element + */ + void setUpper(const DcmTagKey& key) + { + upperKey = key; + } + + /** converts entry into repeating tag entry by defining an upper limit + * for tag group + * @param ug upper limit for tag group + */ + void setUpperGroup(Uint16 ug) + { + upperKey.setGroup(ug); + } + + /** converts entry into repeating tag entry by defining an upper limit + * for tag element + * @param ue upper limit for tag element + */ + void setUpperElement(Uint16 ue) + { + upperKey.setElement(ue); + } + + /// returns upper limit for tag group + Uint16 getUpperGroup() const + { + return upperKey.getGroup(); + } + + /// returns upper limit for tag element + Uint16 getUpperElement() const + { + return upperKey.getElement(); + } + + /// returns attribute tag as DcmTagKey object by value + DcmTagKey getKey() const + { + return * OFstatic_cast(const DcmTagKey *, this); + } + + /// returns upper limits for attribute tag as DcmTagKey object by value + DcmTagKey getUpperKey() const + { + return upperKey; + } + + /// returns true if entry is has a repeating group + int isRepeatingGroup() const + { + return (getGroup() != getUpperGroup()); + } + + /// returns true if entry is has a repeating element + int isRepeatingElement() const + { + return (getElement() != getUpperElement()); + } + + /// returns true if entry is repeating (group or element) + int isRepeating() const + { + return (isRepeatingGroup() || isRepeatingElement()); + } + + /// returns group range restriction + DcmDictRangeRestriction getGroupRangeRestriction() const + { + return groupRangeRestriction; + } + + /// sets group range restriction + void setGroupRangeRestriction(DcmDictRangeRestriction rr) + { + groupRangeRestriction = rr; + } + + /// returns element range restriction + DcmDictRangeRestriction getElementRangeRestriction() const + { + return elementRangeRestriction; + } + + /// sets element range restriction + void setElementRangeRestriction(DcmDictRangeRestriction rr) + { + elementRangeRestriction = rr; + } + + /* containment */ + + /** checks if the given tag key and private creator code are covered + * by this object. + * @param key tag key + * @param privCreator private creator, may be NULL + * @return true if this entry contains the given tag for the given private creator + */ + int contains(const DcmTagKey& key, const char *privCreator) const /* this contains key */ + { + if ((getGroupRangeRestriction() == DcmDictRange_Even) && + DCM_IS_ODD(key.getGroup())) + return OFFalse; + else if ((getGroupRangeRestriction() == DcmDictRange_Odd) && + DCM_IS_EVEN(key.getGroup())) + return OFFalse; + else if ((getElementRangeRestriction() == DcmDictRange_Even) && + DCM_IS_ODD(key.getElement())) + return OFFalse; + else if ((getElementRangeRestriction() == DcmDictRange_Odd) && + DCM_IS_EVEN(key.getElement())) + return OFFalse; + else if (! privateCreatorMatch(privCreator)) + return OFFalse; + else + { + const OFBool groupMatches=DCM_INRANGE(key.getGroup(), getGroup(), getUpperGroup()); + OFBool found=groupMatches && DCM_INRANGE(key.getElement(), getElement(), getUpperElement()); + if (!found && groupMatches && privCreator) + found=DCM_INRANGE(key.getElement() & 0xFF, getElement(), getUpperElement()); + return found; + } + } + + /** checks if this entry contains the given name + * @param name attribute name, must not be NULL + * @return true if tagName matches the given string + */ + int contains(const char *name) const /* this contains named key */ + { + return !strcmp( tagName, name ); + } + + /* set relations */ + + /** checks if this entry describes a true subset of tag range + * described by the given entry. + * @param e entry to compare with + * @return true if this object is subset of e + */ + int subset(const DcmDictEntry& e) const /* this is a subset of key */ + { + return ( (getGroup() >= e.getGroup()) && + (getUpperGroup() <= e.getUpperGroup()) && + (getElement() >= e.getElement()) && + (getUpperElement() <= e.getUpperElement()) && + privateCreatorMatch(e.privateCreator) + ); + } + + /** checks if this entry describes the same tag range as the given entry. + * @param e entry to compare with + * @return true if objects describe the same tag range + */ + int setEQ(const DcmDictEntry& e) const /* this is set equal to key */ + { + return ( (getGroup() == e.getGroup()) && + (getUpperGroup() == e.getUpperGroup()) && + (getElement() == e.getElement()) && + (getUpperElement() == e.getUpperElement()) && + (getGroupRangeRestriction() == e.getGroupRangeRestriction()) && + (getElementRangeRestriction() == e.getElementRangeRestriction()) && + privateCreatorMatch(e.privateCreator) + ); + } + + /// friend operator<< + friend DCMTK_DCMDATA_EXPORT STD_NAMESPACE ostream& operator<<(STD_NAMESPACE ostream& s, const DcmDictEntry& e); + +private: + + /// private undefined copy assignment operator + DcmDictEntry &operator=(const DcmDictEntry &); + + /** upper limit of repeating group and element (lower limit is inherited + * from DcmTagKey) + */ + DcmTagKey upperKey; + + /// value representation + DcmVR valueRepresentation; + + /// attribute name + const char *tagName; + + /// lower limit for VM + int valueMultiplicityMin; + + /// upper limit for VM + int valueMultiplicityMax; + + /// standard version name, may be NULL + const char *standardVersion; + + /// true if strings are copies (i.e. should be deleted upon destruction) + OFBool stringsAreCopies; + + /// restriction (even, odd, unrestricted) for group range + DcmDictRangeRestriction groupRangeRestriction; + + /// restriction (even, odd, unrestricted) for element range + DcmDictRangeRestriction elementRangeRestriction; + + /// private creator name, may be NULL + const char *privateCreator; +}; + +#endif /* !DCDICENT_H */ diff --git a/dcmdata/include/dcmtk/dcmdata/dcdict.h b/dcmdata/include/dcmtk/dcmdata/dcdict.h new file mode 100644 index 00000000..9ee637d1 --- /dev/null +++ b/dcmdata/include/dcmtk/dcmdata/dcdict.h @@ -0,0 +1,296 @@ +/* + * + * Copyright (C) 1994-2015, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Andrew Hewett + * + * Purpose: Interface for loadable DICOM data dictionary + * + */ + + +#ifndef DCMDICT_H +#define DCMDICT_H + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/ofstd/ofthread.h" +#include "dcmtk/dcmdata/dchashdi.h" + +/// maximum length of a line in the loadable DICOM dictionary +#define DCM_MAXDICTLINESIZE 2048 + +/// maximum number of fields per entry in the loadable DICOM dictionary +#define DCM_MAXDICTFIELDS 6 + +/// environment variable pointing to the data dictionary file +#define DCM_DICT_ENVIRONMENT_VARIABLE "DCMDICTPATH" + +#ifndef DCM_DICT_DEFAULT_PATH +/* +** The default dictionary path is system dependent. It should +** be defined in a configuration file included from "osconfig.h" +*/ +#error "DCM_DICT_DEFAULT_PATH is not defined via osconfig.h" +#endif /* !DCM_DICT_DEFAULT_PATH */ + +#ifndef ENVIRONMENT_PATH_SEPARATOR +#define ENVIRONMENT_PATH_SEPARATOR '\n' /* at least define something unlikely */ +#endif + + +/** this class implements a loadable DICOM Data Dictionary + */ +class DCMTK_DCMDATA_EXPORT DcmDataDictionary +{ +public: + + /** constructor + * @param loadBuiltin flag indicating if a built-in data dictionary + * (if any) should be loaded. + * @param loadExternal flag indicating if an external data dictionary + * should be read from file. + */ + DcmDataDictionary(OFBool loadBuiltin, OFBool loadExternal); + + /// destructor + ~DcmDataDictionary(); + + /** checks if a data dictionary is loaded (excluding the skeleton dictionary) + * @return true if loaded, false if no dictionary is present + */ + OFBool isDictionaryLoaded() const { return dictionaryLoaded; } + + /// returns the number of normal (non-repeating) tag entries + int numberOfNormalTagEntries() const { return hashDict.size(); } + + /// returns the number of repeating tag entries + int numberOfRepeatingTagEntries() const { return OFstatic_cast(int, repDict.size()); } + + /** returns the number of dictionary entries that were loaded + * either from file or from a built-in dictionary or both. + */ + int numberOfEntries() const + { return numberOfNormalTagEntries() + + numberOfRepeatingTagEntries() - skeletonCount; } + + /** returns the number of skeleton entries. The skeleton is a collection + * of dictionary entries which are always present, even if neither internal + * nor external dictionary have been loaded. It contains very basic + * things like item delimitation and sequence delimitation. + */ + int numberOfSkeletonEntries() const { return skeletonCount; } + + /** reload data dictionaries. First, all dictionary entries are deleted. + * @param loadBuiltin flag indicating if a built-in data dictionary + * (if any) should be loaded. + * @param loadExternal flag indicating if an external data dictionary + * should be read from file. + * @return true if reload was successful, false if an error occurred + */ + OFBool reloadDictionaries(OFBool loadBuiltin, OFBool loadExternal); + + /** load a particular dictionary from file. + * @param fileName filename + * @param errorIfAbsent causes the method to return false + * if the file cannot be opened + * @return false if the file contains a parse error or if the file could + * not be opened and errorIfAbsent was set, true otherwise. + */ + OFBool loadDictionary(const char* fileName, OFBool errorIfAbsent = OFTrue); + + /** dictionary lookup for the given tag key and private creator name. + * First the normal tag dictionary is searched. If not found + * then the repeating tag dictionary is searched. + * @param key tag key + * @param privCreator private creator name, may be NULL + */ + const DcmDictEntry* findEntry(const DcmTagKey& key, const char *privCreator) const; + + /** dictionary lookup for the given attribute name. + * First the normal tag dictionary is searched. If not found + * then the repeating tag dictionary is searched. + * Only considers standard attributes (i. e. without private creator) + * @param name attribute name + */ + const DcmDictEntry* findEntry(const char *name) const; + + /// deletes all dictionary entries + void clear(); + + /** adds an entry to the dictionary. Must be allocated via new. + * The entry becomes the property of the dictionary and will be + * deallocated (via delete) upon clear() or dictionary destruction. + * If an equivalent entry already exists it will be replaced by + * the new entry and the old entry deallocated (via delete). + * @param entry pointer to new entry + */ + void addEntry(DcmDictEntry* entry); + + /* Iterators to access the normal and the repeating entries */ + + /// returns an iterator to the start of the normal (non-repeating) dictionary + DcmHashDictIterator normalBegin() { return hashDict.begin(); } + + /// returns an iterator to the end of the normal (non-repeating) dictionary + DcmHashDictIterator normalEnd() { return hashDict.end(); } + + /// returns an iterator to the start of the repeating tag dictionary + DcmDictEntryListIterator repeatingBegin() { return repDict.begin(); } + + /// returns an iterator to the end of the repeating tag dictionary + DcmDictEntryListIterator repeatingEnd() { return repDict.end(); } + +private: + + /** private undefined assignment operator + */ + DcmDataDictionary &operator=(const DcmDataDictionary &); + + /** private undefined copy constructor + */ + DcmDataDictionary(const DcmDataDictionary &); + + /** loads external dictionaries defined via environment variables + * @return true if successful + */ + OFBool loadExternalDictionaries(); + + /** loads a builtin (compiled) data dictionary. + * Depending on which code is in use, this function may not + * do anything. + */ + void loadBuiltinDictionary(); + + /** loads the skeleton dictionary (the bare minimum needed to run) + * @return true if successful + */ + OFBool loadSkeletonDictionary(); + + /** looks up the given directory entry in the two dictionaries. + * @return pointer to entry if found, NULL otherwise + */ + const DcmDictEntry* findEntry(const DcmDictEntry& entry) const; + + /** deletes the given entry from either dictionary + */ + void deleteEntry(const DcmDictEntry& entry); + + + /** dictionary of normal tags + */ + DcmHashDict hashDict; + + /** dictionary of repeating tags + */ + DcmDictEntryList repDict; + + /** the number of skeleton entries + */ + int skeletonCount; + + /** is a dictionary loaded (more than skeleton) + */ + OFBool dictionaryLoaded; + +}; + + +/** global singleton dicom dictionary that is used by DCMTK in order to lookup + * attribute VR, tag names and so on. The dictionary is internally populated + * on first use, if the user accesses it via rdlock() or wrlock(). The + * dictionary allows safe read (shared) and write (exclusive) access from + * multiple threads in parallel. + */ +class DCMTK_DCMDATA_EXPORT GlobalDcmDataDictionary +{ +public: + /** constructor. + */ + GlobalDcmDataDictionary(); + + /** destructor + */ + ~GlobalDcmDataDictionary(); + + /** acquires a read lock and returns a const reference to + * the dictionary. + * @return const reference to dictionary + */ + const DcmDataDictionary& rdlock(); + + /** acquires a write lock and returns a non-const reference + * to the dictionary. + * @return non-const reference to dictionary. + */ + DcmDataDictionary& wrlock(); + + /** unlocks the read or write lock which must have been acquired previously. + */ + void unlock(); + + /** checks if a data dictionary has been loaded. This method acquires and + * releases a read lock. It must not be called with another lock on the + * dictionary being held by the calling thread. + * @return OFTrue if dictionary has been loaded, OFFalse otherwise. + */ + OFBool isDictionaryLoaded(); + + /** erases the contents of the dictionary. This method acquires and + * releases a write lock. It must not be called with another lock on the + * dictionary being held by the calling thread. This method is intended + * as a help for debugging memory leaks. + */ + void clear(); + +private: + /** private undefined assignment operator + */ + GlobalDcmDataDictionary &operator=(const GlobalDcmDataDictionary &); + + /** private undefined copy constructor + */ + GlobalDcmDataDictionary(const GlobalDcmDataDictionary &); + + /** create the data dictionary instance for this class. Used for first + * intialization. The caller must not have dataDictLock locked. + */ + void createDataDict(); + + /** the data dictionary managed by this class + */ + DcmDataDictionary *dataDict; + +#ifdef WITH_THREADS + /** the read/write lock used to protect access from multiple threads + */ + OFReadWriteLock dataDictLock; +#endif +}; + + +/** The Global DICOM Data Dictionary. + * Will be created before main() starts and gets populated on its first use. + * Tries to load a builtin data dictionary (if compiled in). + * Tries to load data dictionaries from files specified by + * the DCMDICTPATH environment variable. If this environment + * variable does not exist then a default file is loaded (if + * it exists). + * It is possible that no data dictionary gets loaded. This + * is likely to cause unexpected behaviour in the dcmdata + * toolkit classes. + */ +extern DCMTK_DCMDATA_EXPORT GlobalDcmDataDictionary dcmDataDict; + +#endif diff --git a/dcmdata/include/dcmtk/dcmdata/dcdirrec.h b/dcmdata/include/dcmtk/dcmdata/dcdirrec.h new file mode 100644 index 00000000..c10b90e5 --- /dev/null +++ b/dcmdata/include/dcmtk/dcmdata/dcdirrec.h @@ -0,0 +1,528 @@ +/* + * + * Copyright (C) 1994-2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Gerd Ehlers, Andreas Barth + * + * Purpose: Interface of class DcmDirectoryRecord + * + */ + +#ifndef DCDIRREC_H +#define DCDIRREC_H + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/dcmdata/dcitem.h" +#include "dcmtk/dcmdata/dcsequen.h" +#include "dcmtk/dcmdata/dcfilefo.h" + + +/// types of directory records in a DICOMDIR +typedef enum { + /// root + ERT_root = 0, + /// curve (retired) + ERT_Curve = 1, + /// film box (retired) + ERT_FilmBox = 2, + /// film session (retired) + ERT_FilmSession = 3, + /// image + ERT_Image = 4, + /// image box (retired) + ERT_ImageBox = 5, + /// interpretation (retired) + ERT_Interpretation = 6, + /// modality LUT (retired) + ERT_ModalityLut = 7, + /// MRDR (retired) + ERT_Mrdr = 8, + /// overlay (retired) + ERT_Overlay = 9, + /// patient + ERT_Patient = 10, + /// print queue (retired) + ERT_PrintQueue = 11, + /// private + ERT_Private = 12, + /// results + ERT_Results = 13, + /// series + ERT_Series = 14, + /// study + ERT_Study = 15, + /// study component (retired) + ERT_StudyComponent = 16, + /// topic (retired) + ERT_Topic = 17, + /// visit (retired) + ERT_Visit = 18, + /// VOI LUT (retired) + ERT_VoiLut = 19, + /// SR document + ERT_SRDocument = 20, + /// presentation state + ERT_Presentation = 21, + /// waveform + ERT_Waveform = 22, + /// RT dose + ERT_RTDose = 23, + /// RT structure set + ERT_RTStructureSet = 24, + /// RT plan + ERT_RTPlan = 25, + /// RT treatment record + ERT_RTTreatRecord = 26, + /// stored print (retired) + ERT_StoredPrint = 27, + /// key object selection document + ERT_KeyObjectDoc = 28, + /// registration + ERT_Registration = 29, + /// fiducial + ERT_Fiducial = 30, + /// raw data + ERT_RawData = 31, + /// spectroscopy + ERT_Spectroscopy = 32, + /// encapsulated document + ERT_EncapDoc = 33, + /// value map + ERT_ValueMap = 34, + /// hanging protocol + ERT_HangingProtocol = 35, + /// stereometric relationships + ERT_Stereometric = 36, + /// HL7 structured document + ERT_HL7StrucDoc = 37, + /// palette + ERT_Palette = 38, + /// surface + ERT_Surface = 39, + /// measurement + ERT_Measurement = 40, + /// implant + ERT_Implant = 41, + /// implant group + ERT_ImplantGroup = 42, + /// implant assembly + ERT_ImplantAssy = 43, + /// plan + ERT_Plan = 44, + /// surface scan + ERT_SurfaceScan = 45 +} E_DirRecType; + + +class DcmDicomDir; + +/** a class representing a directory record dataset in a DICOMDIR. + */ +class DCMTK_DCMDATA_EXPORT DcmDirectoryRecord : public DcmItem +{ + + friend class DcmDicomDir; + +public: + /// default constructor + DcmDirectoryRecord(); + + /** constructor + * @param tag attribute tag + * @param len length of the attribute value + */ + DcmDirectoryRecord(const DcmTag &tag, + const Uint32 len); + + /** constructor + * @param recordType record type + * @param referencedFileID referenced file ID in DICOM format + * @param sourceFileName path to referenced file in operating system specific format + * @param fileFormat fileFormat for sourceFileName, can be NULL + */ + DcmDirectoryRecord(const E_DirRecType recordType, + const char *referencedFileID, // DICOM format with '\\' + const OFFilename &sourceFileName, // OS format + DcmFileFormat* fileFormat = NULL); + + /** constructor + * @param recordTypeName record type as string + * @param referencedFileID referenced file ID in DICOM format + * @param sourceFileName path to referenced file in operating system specific format + * @param fileFormat fileFormat for sourceFileName, can be NULL + */ + DcmDirectoryRecord(const char *recordTypeName, + const char *referencedFileID, // DICOM format with '\\' + const OFFilename &sourceFileName, // OS format + DcmFileFormat* fileFormat = NULL); + + /** copy constructor + * @param oldDirRec element to be copied + */ + DcmDirectoryRecord(const DcmDirectoryRecord &oldDirRec); + + /** assignment operator + * @param obj the directory record to be copied + */ + DcmDirectoryRecord &operator=(const DcmDirectoryRecord &obj); + + /// destructor + virtual ~DcmDirectoryRecord(); + + /** clone method + * @return deep copy of this object + */ + virtual DcmObject *clone() const + { + return new DcmDirectoryRecord(*this); + } + + /** Virtual object copying. This method can be used for DcmObject + * and derived classes to get a deep copy of an object. Internally + * the assignment operator is called if the given DcmObject parameter + * is of the same type as "this" object instance. If not, an error + * is returned. This function permits copying an object by value + * in a virtual way which therefore is different to just calling the + * assignment operator of DcmElement which could result in slicing + * the object. + * @param rhs - [in] The instance to copy from. Has to be of the same + * class type as "this" object + * @return EC_Normal if copying was successful, error otherwise + */ + virtual OFCondition copyFrom(const DcmObject& rhs); + + /** return identifier for this class. Every class derived from this class + * returns a unique value of type enum DcmEVR for this call. This is used + * as a "poor man's RTTI" to correctly identify instances derived from + * this class even on compilers not supporting RTTI. + * @return type identifier of this class + */ + virtual DcmEVR ident() const; + + /// returns current status flag + inline OFCondition error() const { return errorFlag; } + + /** mode specifying whether the SpecificCharacterSet (0008,0005) element should be + * checked by convertCharacterSet() or not, i.e.\ whether this element might be + * present on this dataset-level. + * @return always returns OFTrue, i.e.\ SpecificCharacterSet should be checked + */ + virtual OFBool checkForSpecificCharacterSet() const { return OFTrue; } + + /** convert all element values that are contained in this record and that are + * affected by SpecificCharacterSet from the given source character set to the given + * destination character set. The defined terms for a particular character set can + * be found in the DICOM standard, e.g. "ISO_IR 100" for ISO 8859-1 (Latin 1) or + * "ISO_IR 192" for Unicode in UTF-8. An empty string denotes the default character + * repertoire, which is ASCII (7-bit). If multiple values are given for 'fromCharset' + * (separated by a backslash) code extension techniques are used and escape sequences + * may be encountered in the source string to switch between the specified character + * sets. + * @param fromCharset name of the source character set(s) used for the conversion + * @param toCharset name of the destination character set used for the conversion. + * Only a single value is permitted (i.e. no code extensions). + * @param transliterate mode specifying whether a character that cannot be + * represented in the destination character encoding is approximated through one + * or more characters that look similar to the original one + * @param updateCharset if OFTrue, the SpecificCharacterSet (0008,0005) element is + * updated, i.e.\ the current value is either replaced or a new element is inserted + * or the existing element is deleted. If OFFalse the SpecificCharacterSet element + * remains unchanged. + * @param discardIllegal mode specifying whether characters that cannot be represented + * in the destination character encoding will be silently discarded + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition convertCharacterSet(const OFString &fromCharset, + const OFString &toCharset, + const OFBool transliterate = OFFalse, + const OFBool updateCharset = OFFalse, + const OFBool discardIllegal = OFFalse); + + /** convert all element values that are contained in this record and that are + * affected by SpecificCharacterSet to the given destination character set. If not + * disabled, the source character set is determined automatically from the value of + * the SpecificCharacterSet (0008,0005) element. The defined terms for the + * destination character set can be found in the DICOM standard, e.g. "ISO_IR 100" + * for ISO 8859-1 (Latin 1) or "ISO_IR 192" for Unicode in UTF-8. An empty string + * denotes the default character repertoire, which is ASCII (7-bit). + * @param toCharset name of the destination character set used for the conversion. + * Only a single value is permitted (i.e. no code extensions). + * @param transliterate mode specifying whether a character that cannot be + * represented in the destination character encoding is approximated through one + * or more characters that look similar to the original one + * @param ignoreCharset if OFTrue, the value of SpecificCharacterSet is ignored. + * Also see checkForSpecificCharacterSet(). + * @param discardIllegal mode specifying whether characters that cannot be represented + * in the destination character encoding will be silently discarded + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition convertCharacterSet(const OFString &toCharset, + const OFBool transliterate = OFFalse, + const OFBool ignoreCharset = OFFalse, + const OFBool discardIllegal = OFFalse); + + /** convert all element values that are contained in this record and that are + * affected by SpecificCharacterSet from the currently selected source character + * set to the currently selected destination character set. Since the Basic + * Directory IOD, which specifies the structure and content of a DICOMDIR, does not + * contain the SpecificCharacterSet (0008,0005) element in the main dataset but in + * each directory record, this method also checks for this element and creates a new + * character set converter for the contained data elements (if needed). + * @param converter character set converter to be used to convert the element values + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition convertCharacterSet(DcmSpecificCharacterSet &converter); + + /** print all elements of the item to a stream + * @param out output stream + * @param flags optional flag used to customize the output (see DCMTypes::PF_xxx) + * @param level current level of nested items. Used for indentation. + * @param pixelFileName not used + * @param pixelCounter not used + */ + virtual void print(STD_NAMESPACE ostream&out, + const size_t flags = 0, + const int level = 0, + const char *pixelFileName = NULL, + size_t *pixelCounter = NULL); + + /** This function reads the information of all attributes which + * are captured in the input stream and captures this information + * in elementList. Each attribute is represented as an element + * in this list. If not all information for an attribute could be + * read from the stream, the function returns EC_StreamNotifyClient. + * @param inStream The stream which contains the information. + * @param xfer The transfer syntax which was used to encode + * the information in inStream. + * @param glenc Encoding type for group length; specifies + * what will be done with group length tags. + * @param maxReadLength Maximum read length for reading an attribute value. + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition read(DcmInputStream & inStream, + const E_TransferSyntax xfer, + const E_GrpLenEncoding glenc = EGL_noChange, + const Uint32 maxReadLength = DCM_MaxReadLength); + + /** write object in XML format + * @param out output stream to which the XML document is written + * @param flags optional flag used to customize the output (see DCMTypes::XF_xxx) + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition writeXML(STD_NAMESPACE ostream&out, + const size_t flags = 0); + + + /** check the currently stored element value + * @param autocorrect correct value length if OFTrue + * @return status, EC_Normal if value length is correct, an error code otherwise + */ + virtual OFCondition verify(const OFBool autocorrect = OFFalse); + + /** a complex, stack-based, hierarchical search method. It allows for a search + * for a DICOM object with a given attribute within a given container, + * hierarchically, from a starting position identified through a cursor stack. + * @param xtag the DICOM attribute tag we are searching for + * @param resultStack depending on the search mode (see below), this parameter + * either serves as an input and output parameter, or as an output parameter + * only (the latter being the default). When used as an input parameter, + * the cursor stack defines the start position for the search within a + * hierarchical DICOM dataset. Upon successful return, the stack contains + * the position of the element found, in the form of a pointer to each dataset, + * sequence, item and element from the main dataset down to the found element. + * @param mode search mode, controls how the search stack is handled. + * In the default mode, ESM_fromHere, the stack is ignored on input, and + * the search starts in the object for which this method is called. + * In the other modes, the stack is used both as an input and an output + * parameter and defines the starting point for the search. + * @param searchIntoSub if true, the search will be performed hierarchically descending + * into the sequences and items of the dataset. If false, only the current container + * (sequence or item) will be traversed. + * @return EC_Normal if found, EC_TagNotFound if not found, an error code is something went wrong. + */ + virtual OFCondition search(const DcmTagKey &xtag, // in + DcmStack &resultStack, // inout + E_SearchMode mode = ESM_fromHere, // in + OFBool searchIntoSub = OFTrue); // in + + /// get record type of this directory record + virtual E_DirRecType getRecordType(); + + /** if this directory record references an MRDR (multi-reference directory record), + * return pointer to the MRDR referenced by this object. + * @return pointer to MRDR referenced by this object or NULL of no MRDR referenced + */ + virtual DcmDirectoryRecord* getReferencedMRDR(); + + /** create a reference from this record to an MRDR + * @param mrdr pointer to MRDR + * @return EC_Normal upon success, an error code otherwise + */ + virtual OFCondition assignToMRDR(DcmDirectoryRecord *mrdr ); // in + + /** open a DICOM file and make this directory record into a directory + * record for that DICOM file. The most relevant record keys + * (SOP Class UID, SOP instance UID, Transfer Syntax UID) are inserted + * into the directory record. + * @param referencedFileID referenced file ID in DICOM format + * @param sourceFileName path to file in operating system specific format + * @return EC_Normal upon success, an error code otherwise + */ + virtual OFCondition assignToSOPFile(const char *referencedFileID, + const OFFilename &sourceFileName); + + /// return number of directory records that are child record of this one + virtual unsigned long cardSub() const; + + /** insert a child directory record + * @param dirRec directory record to be inserted. Must be allocated on heap, ownership is + * transferred to this object + * @param where index where to insert object + * @param before flag indicating whether to insert the record before or after the element + * identified by where + * @return EC_Normal upon success, an error code otherwise + */ + virtual OFCondition insertSub(DcmDirectoryRecord* dirRec, + unsigned long where = DCM_EndOfListIndex, + OFBool before = OFFalse); + + /** insert new directory child record at the current position. + * The current position is stored internally in the 'lowerLevelList' member variable. + * @param dirRec new child record to be inserted + * @param before flag indicating whether to insert the record before (OFFalse) or + * after (OFTrue) the current position + * @return status, EC_Normal upon success, an error code otherwise + */ + virtual OFCondition insertSubAtCurrentPos(DcmDirectoryRecord *dirRec, + OFBool before = OFFalse); + + /** access child directory record. Returns a pointer to the object maintained + * as a child, not a copy. + * @param num index, must be < cardSub() + * @return pointer to child directory record or NULL if not found + */ + virtual DcmDirectoryRecord* getSub(const unsigned long num); + + /** get next directory child record starting at a given record + * @param dirRec record to start from (goto first record if NULL) + * @return pointer to next record if successful, NULL otherwise + */ + virtual DcmDirectoryRecord* nextSub(const DcmDirectoryRecord *dirRec); + + /** remove child directory record. If found, the record is not deleted but + * returned to the caller who is responsible for further management of the + * DcmDirectoryRecord object. + * @param num index number of element, must be < cardSub() + * @return pointer to DcmDirectoryRecord if found, NULL otherwise + */ + virtual DcmDirectoryRecord* removeSub(const unsigned long num); + + /** remove child directory record. If found, the record is not deleted but + * returned to the caller who is responsible for further management of the + * DcmDirectoryRecord object. + * @param dirRec pointer to element to be removed from list + * @return pointer to element if found, NULL otherwise + */ + virtual DcmDirectoryRecord* removeSub(DcmDirectoryRecord *dirRec); + + /** remove child directory record and delete file referenced by that record, if any + * @param num index number of element, must be < cardSub() + * @return status, EC_Normal upon success, an error code otherwise + */ + virtual OFCondition deleteSubAndPurgeFile(const unsigned long num); + + /** remove child directory record and delete file referenced by that record, if any + * @param dirRec pointer to element to be removed from list + * @return status, EC_Normal upon success, an error code otherwise + */ + virtual OFCondition deleteSubAndPurgeFile(DcmDirectoryRecord *dirRec); + + /// revert the list of child directory records to default constructed (empty) state + virtual OFCondition clearSub(); + + /** store the filename from which this directory record was read from + * @param fname filename, must not be empty + */ + virtual void setRecordsOriginFile(const OFFilename &fname); + + /// get the filename from which this directory record was read from, empty if not set + virtual const OFFilename &getRecordsOriginFile(); + + /// get the offset in file of this directory record + Uint32 getFileOffset() const; + +protected: + + // side-effect-free conversion routines: + E_DirRecType recordNameToType(const char *recordTypeName); + char* buildFileName(const char *origName, char *destName); + OFCondition checkHierarchy(const E_DirRecType upperRecord, + const E_DirRecType lowerRecord); + + // access to data elements within the Directory Records: + OFCondition setRecordType(E_DirRecType newType); + E_DirRecType lookForRecordType(); + OFCondition setReferencedFileID( const char *referencedFileID); + const char* lookForReferencedFileID(); + DcmDirectoryRecord* lookForReferencedMRDR(); + const char* getReferencedFileName(); // local or in MRDR + OFCondition setRecordInUseFlag(const Uint16 newFlag); + Uint16 lookForRecordInUseFlag(); + Uint32 setFileOffset(Uint32 position); + + // access to MRDR data element: + OFCondition setNumberOfReferences(Uint32 newRefNum); + Uint32 lookForNumberOfReferences(); + Uint32 increaseRefNum(); + Uint32 decreaseRefNum(); + + // misc: + /** Load all necessary info for this directory record. + * @param referencedFileID file ID that is being referenced, may be NULL + * @param sourceFileName filename for the DICOM file, may be empty (unspecified) + * @param fileFormat If not NULL, then this should be the result of loading + * sourceFileName. May only be non-NULL if sourceFileName isn't empty. + */ + OFCondition fillElementsAndReadSOP(const char *referencedFileID, + const OFFilename &sourceFileName, + DcmFileFormat *fileFormat = NULL); + OFCondition masterInsertSub(DcmDirectoryRecord *dirRec, + const unsigned long where = DCM_EndOfListIndex); + OFCondition purgeReferencedFile(); + +private: + + /// filename (path) of the file from which this directory record was read + OFFilename recordsOriginFile; + + /// list of child directory records, kept in a sequence of items + DcmSequenceOfItems *lowerLevelList; + + /// directory record type of this record + E_DirRecType DirRecordType; + + /// pointer to multi-referenced directory record (MRDR) if this record refers to one, NULL otherwise + DcmDirectoryRecord *referencedMRDR; + + /// number of other directory records referring to this one; used for MRDR records + Uint32 numberOfReferences; + + /// byte offset at which the start of this directory record resides in the file from which it was read + Uint32 offsetInFile; + +}; + + +#endif // DCDIRREC_H diff --git a/dcmdata/include/dcmtk/dcmdata/dcelem.h b/dcmdata/include/dcmtk/dcmdata/dcelem.h new file mode 100644 index 00000000..09f1844d --- /dev/null +++ b/dcmdata/include/dcmtk/dcmdata/dcelem.h @@ -0,0 +1,868 @@ +/* + * + * Copyright (C) 1994-2015, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Gerd Ehlers, Andreas Barth + * + * Purpose: Interface of class DcmElement + * + */ + + +#ifndef DCELEM_H +#define DCELEM_H + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/dcmdata/dcobject.h" +#include "dcmtk/ofstd/ofstring.h" + +// forward declarations +class DcmInputStreamFactory; +class DcmFileCache; +class DcmItem; + +/** abstract base class for all DICOM elements + */ +class DCMTK_DCMDATA_EXPORT DcmElement + : public DcmObject +{ + + public: + + /** constructor. + * Create new element from given tag and length. + * @param tag DICOM tag for the new element + * @param len value length for the new element + */ + DcmElement(const DcmTag &tag, + const Uint32 len = 0); + + /** copy constructor + * @param old element to be copied + */ + DcmElement(const DcmElement &old); + + /** destructor + */ + virtual ~DcmElement(); + + /** assignment operator + * @param obj element to be assigned/copied + * @return reference to this object + */ + DcmElement &operator=(const DcmElement &obj); + + /** comparison operator that compares the normalized value of this element + * with a given element of the same type (e.g. an DcmUnsignedShort with a + * DcmUnsignedShort). The tag of the element is also considered as the first + * component that is compared, followed by the object types (VR, i.e. DCMTK'S EVR). + * DcmElement's default implementation does only compare the tag and EVR while + * the derived classes implement the value comparisons by comparing all the + * components that make up the value, preferably in the order declared in + * the object (if applicable). + * @param rhs the right hand side of the comparison + * @return 0 if the object values are equal. + * -1 if either the value of the first component that does not match + * is lower in this object than in rhs, or all compared components match + * but this object has fewer components than rhs. Also returned if rhs + * cannot be casted to this object type. + * 1 if either the value of the first component that does not match + * is greater in this object than in rhs object, or all compared + * components match but the this component is longer. + */ + virtual int compare(const DcmElement& rhs) const =0; + + /** Virtual object copying. This method can be used for DcmObject + * and derived classes to get a deep copy of an object. Internally + * the assignment operator is called if the given DcmObject parameter + * is of the same type as "this" object instance. If not, an error + * is returned. This function permits copying an object by value + * in a virtual way which therefore is different to just calling the + * assignment operator of DcmElement which could result in slicing + * the object. + * @param rhs - [in] The instance to copy from. Has to be of the same + * class type as "this" object + * @return EC_Normal if copying was successful, error otherwise + */ + virtual OFCondition copyFrom(const DcmObject& rhs); + + /** calculate the length of this DICOM element when encoded with the + * given transfer syntax and the given encoding type for sequences. + * For elements, the length includes the length of the tag, length field, + * VR field and the value itself, for items and sequences it returns + * the length of the complete item or sequence including delimitation tags + * if applicable. Never returns undefined length. + * @param xfer transfer syntax for length calculation + * @param enctype sequence encoding type for length calculation + * @return length of DICOM element + */ + virtual Uint32 calcElementLength(const E_TransferSyntax xfer, + const E_EncodingType enctype); + + /** calculate the value length (without attribute tag, VR and length field) + * of this DICOM element when encoded with the given transfer syntax and + * the given encoding type for sequences. Never returns undefined length. + * @param xfer transfer syntax for length calculation + * @param enctype sequence encoding type for length calculation + * @return value length of DICOM element + */ + virtual Uint32 getLength(const E_TransferSyntax /*xfer*/ = EXS_LittleEndianImplicit, + const E_EncodingType /*enctype*/ = EET_UndefinedLength) + { + return getLengthField(); + } + + /** check if this element is a leaf node in a dataset tree. + * All subclasses of DcmElement except for DcmSequenceOfItems + * are leaf nodes, while DcmSequenceOfItems, DcmItem, DcmDataset etc. + * are not. + * @return true if leaf node, false otherwise. + */ + virtual OFBool isLeaf() const { return OFTrue; } + + /** check if value of this element is loaded into main memory + * @return true if value is present in memory, false if value still resides in file + */ + inline OFBool valueLoaded() const { return fValue != NULL || getLengthField() == 0; } + + /** initialize the transfer state of this object. This method must be called + * before this object is written to a stream or read (parsed) from a stream. + */ + virtual void transferInit(); + + /** check if this DICOM object can be encoded in the given transfer syntax. + * @param newXfer transfer syntax in which the DICOM object is to be encoded + * @param oldXfer transfer syntax in which the DICOM object was read or created. + * @return true if object can be encoded in desired transfer syntax, false otherwise. + */ + virtual OFBool canWriteXfer(const E_TransferSyntax newXfer, + const E_TransferSyntax oldXfer); + + /** This function reads the data value of an attribute which is + * captured in the input stream and captures this information + * in this. If not all information for an attribute could be + * read from the stream, the function returns EC_StreamNotifyClient. + * Note that if certain conditions are met, this function does + * not actually load the data value but creates and stores an object + * that enables us to load this information later. + * @param inStream The stream which contains the information. + * @param ixfer The transfer syntax which was used to encode + * the information in inStream. + * @param glenc Encoding type for group length; specifies what + * will be done with group length tags. + * @param maxReadLength Maximum read length for reading an attribute value. + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition read(DcmInputStream &inStream, + const E_TransferSyntax ixfer, + const E_GrpLenEncoding glenc = EGL_noChange, + const Uint32 maxReadLength = DCM_MaxReadLength); + + /** This function writes this element's value to the outstream which was + * passed. When writing information, the byte ordering (little or big endian) + * of the transfer syntax which was passed will be accounted for. In case the + * outstream does not provide enough space for all bytes of the current + * element's value, only a certain part of the value will be written to the + * stream. This element's transfer state indicates if the all bytes of value + * have already been written to the stream (ERW_ready), if the writing is + * still in progress and more bytes need to be written to the stream + * (ERW_inWork) or if the writing of the bytes of this element's value has not + * even begun yet (ERW_init). The member variable fTransferredBytes indicates + * how many bytes (starting from byte 0) of this element's value have already + * been written to the stream. This function will return EC_Normal, if the + * entire value of this element has been written to the stream, it will return + * EC_StreamNotifyClient, if there is no more space in the buffer and _not_ all + * bytes of this element's value have been written, and it will return some + * other (error) value if there was an error. + * @param outStream The stream the information will be written to. + * @param oxfer The transfer syntax which shall be used. + * @param enctype encoding types (undefined or explicit length) (actually unused) + * @param wcache pointer to write cache object, may be NULL + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition write(DcmOutputStream &outStream, + const E_TransferSyntax oxfer, + const E_EncodingType enctype, + DcmWriteCache *wcache); + + /** write object in XML format + * @param out output stream to which the XML document is written + * @param flags optional flag used to customize the output (see DCMTypes::XF_xxx) + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition writeXML(STD_NAMESPACE ostream &out, + const size_t flags = 0); + + /** special write method for creation of digital signatures + * @param outStream DICOM output stream + * @param oxfer output transfer syntax + * @param enctype encoding types (undefined or explicit length) + * @param wcache pointer to write cache object, may be NULL + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition writeSignatureFormat(DcmOutputStream &outStream, + const E_TransferSyntax oxfer, + const E_EncodingType enctype, + DcmWriteCache *wcache); + + /** clear (remove) attribute value + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition clear(); + + /** check whether stored value conforms to the VR and to the specified VM + * @param vm value multiplicity (according to the data dictionary) to be checked for. + * (See DcmElement::checkVM() for a list of valid values.) + * Interpreted as cardinality (number of items) for sequence attributes. + * @param oldFormat support old ACR/NEMA format for certain VRs (DA, TM, PN) if OFTrue + * @return status of the check, EC_Normal if value is correct, an error code otherwise + */ + virtual OFCondition checkValue(const OFString &vm = "1-n", + const OFBool oldFormat = OFFalse); + + /** this method loads all attribute values maintained by this object and + * all sub-objects (in case of a container such as DcmDataset) into memory. + * After a call to this method, the file from which a dataset was read may safely + * be deleted or replaced. For large files, this method may obviously allocate large + * amounts of memory. + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition loadAllDataIntoMemory(); + + // GET operations + + /** retrieve a single value of type Uint8. Requires element to be of corresponding VR, + * otherwise an error is returned. + * @param val value returned in this parameter upon success + * @param pos position in multi-valued attribute, default 0 + * @return EC_Normal upon success, an error code otherwise + */ + virtual OFCondition getUint8(Uint8 &val, const unsigned long pos = 0); + + /** retrieve a single value of type Sint16. Requires element to be of corresponding VR, + * otherwise an error is returned. + * @param val value returned in this parameter upon success + * @param pos position in multi-valued attribute, default 0 + * @return EC_Normal upon success, an error code otherwise + */ + virtual OFCondition getSint16(Sint16 &val, const unsigned long pos = 0); + + /** retrieve a single value of type Uint16. Requires element to be of corresponding VR, + * otherwise an error is returned. + * @param val value returned in this parameter upon success + * @param pos position in multi-valued attribute, default 0 + * @return EC_Normal upon success, an error code otherwise + */ + virtual OFCondition getUint16(Uint16 &val, const unsigned long pos = 0); + + /** retrieve a single value of type Sint32. Requires element to be of corresponding VR, + * otherwise an error is returned. + * @param val value returned in this parameter upon success + * @param pos position in multi-valued attribute, default 0 + * @return EC_Normal upon success, an error code otherwise + */ + virtual OFCondition getSint32(Sint32 &val, const unsigned long pos = 0); + + /** retrieve a single value of type Uint32. Requires element to be of corresponding VR, + * otherwise an error is returned. + * @param val value returned in this parameter upon success + * @param pos position in multi-valued attribute, default 0 + * @return EC_Normal upon success, an error code otherwise + */ + virtual OFCondition getUint32(Uint32 &val, const unsigned long pos = 0); + + /** retrieve a single value of type Float32. Requires element to be of corresponding VR, + * otherwise an error is returned. + * @param val value returned in this parameter upon success + * @param pos position in multi-valued attribute, default 0 + * @return EC_Normal upon success, an error code otherwise + */ + virtual OFCondition getFloat32(Float32 &val, const unsigned long pos = 0); + + /** retrieve a single value of type Float64. Requires element to be of corresponding VR, + * otherwise an error is returned. + * @param val value returned in this parameter upon success + * @param pos position in multi-valued attribute, default 0 + * @return EC_Normal upon success, an error code otherwise + */ + virtual OFCondition getFloat64(Float64 &val, const unsigned long pos = 0); + + /** retrieve a single value of type DcmTagKey. Requires element to be of corresponding VR, + * otherwise an error is returned. + * @param val value returned in this parameter upon success + * @param pos position in multi-valued attribute, default 0 + * @return EC_Normal upon success, an error code otherwise + */ + virtual OFCondition getTagVal(DcmTagKey &val, const unsigned long pos = 0); + + /** retrieve a single value of type string. Requires element to be of corresponding VR, + * otherwise an error is returned. + * @param str value returned in this parameter upon success + * @param pos position in multi-valued attribute + * @param normalize true if string is to be normalized (e.g. trailing space characters to be trimmed) + * @return EC_Normal upon success, an error code otherwise + */ + virtual OFCondition getOFString(OFString &str, + const unsigned long pos, + OFBool normalize = OFTrue); + + /** get entire element value as a character string. + * In case of VM > 1 the individual values are separated by a backslash ('\'). + * This method implements a general approach by concatenating the results of + * getOFString() for each value component. Derived class may implement more + * sophisticated methods. + * @param value variable in which the result value is stored + * @param normalize normalize each element value prior to concatenation + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getOFStringArray(OFString &value, + OFBool normalize = OFTrue); + + /** get a pointer to the element value of the current element as type string. + * Requires element to be of corresponding VR, otherwise an error is returned. + * This method does not copy, but returns a pointer to the element value, + * which remains under control of this object and is valid only until the next + * read, write or put operation. + * @param val pointer to value returned in this parameter upon success + * @return EC_Normal upon success, an error code otherwise + */ + virtual OFCondition getString(char *&val); // for strings + + /** get a pointer to the element value of the current element as type string. + * Requires element to be of corresponding VR, otherwise an error is returned. + * This method does not copy, but returns a pointer to the element value, + * which remains under control of this object and is valid only until the next + * read, write or put operation. + * @param val pointer to value returned in this parameter upon success + * @param len length of the returned value (number of characters) + * @return EC_Normal upon success, an error code otherwise + */ + virtual OFCondition getString(char *&val, + Uint32 &len); + + /** get a pointer to the element value of the current element as type string. + * Requires element to be of corresponding VR, otherwise an error is returned. + * This method does not copy, but returns a pointer to the element value, + * which remains under control of this object and is valid only until the next + * read, write or put operation. + * @param val pointer to value returned in this parameter upon success + * @return EC_Normal upon success, an error code otherwise + */ + virtual OFCondition getUint8Array(Uint8 *&val); // for bytes + + /** get a pointer to the element value of the current element as type Sint16. + * Requires element to be of corresponding VR, otherwise an error is returned. + * This method does not copy, but returns a pointer to the element value, + * which remains under control of this object and is valid only until the next + * read, write or put operation. + * @param val pointer to value returned in this parameter upon success + * @return EC_Normal upon success, an error code otherwise + */ + virtual OFCondition getSint16Array(Sint16 *&val); + + /** get a pointer to the element value of the current element as type Uint16. + * Requires element to be of corresponding VR, otherwise an error is returned. + * This method does not copy, but returns a pointer to the element value, + * which remains under control of this object and is valid only until the next + * read, write or put operation. + * @param val pointer to value returned in this parameter upon success + * @return EC_Normal upon success, an error code otherwise + */ + virtual OFCondition getUint16Array(Uint16 *&val); + + /** get a pointer to the element value of the current element as type Sint32. + * Requires element to be of corresponding VR, otherwise an error is returned. + * This method does not copy, but returns a pointer to the element value, + * which remains under control of this object and is valid only until the next + * read, write or put operation. + * @param val pointer to value returned in this parameter upon success + * @return EC_Normal upon success, an error code otherwise + */ + virtual OFCondition getSint32Array(Sint32 *&val); + + /** get a pointer to the element value of the current element as type Uint32. + * Requires element to be of corresponding VR, otherwise an error is returned. + * This method does not copy, but returns a pointer to the element value, + * which remains under control of this object and is valid only until the next + * read, write or put operation. + * @param val pointer to value returned in this parameter upon success + * @return EC_Normal upon success, an error code otherwise + */ + virtual OFCondition getUint32Array(Uint32 *&val); + + /** get a pointer to the element value of the current element as type Float32. + * Requires element to be of corresponding VR, otherwise an error is returned. + * This method does not copy, but returns a pointer to the element value, + * which remains under control of this object and is valid only until the next + * read, write or put operation. + * @param val pointer to value returned in this parameter upon success + * @return EC_Normal upon success, an error code otherwise + */ + virtual OFCondition getFloat32Array(Float32 *&val); + + /** get a pointer to the element value of the current element as type Float64. + * Requires element to be of corresponding VR, otherwise an error is returned. + * This method does not copy, but returns a pointer to the element value, + * which remains under control of this object and is valid only until the next + * read, write or put operation. + * @param val pointer to value returned in this parameter upon success + * @return EC_Normal upon success, an error code otherwise + */ + virtual OFCondition getFloat64Array(Float64 *&val); + + /** detach the value field from the DICOM element (i.e., this object). + * After detaching the calling part of the application has total control + * over the element value, especially the value must be deleted from the + * heap after use. The DICOM element remains a copy of the value if the + * copy parameter is OFTrue; otherwise the value is erased in the DICOM + * element. + * @param copy if true, copy value field before detaching; if false, do not + * retain a copy. + * @return EC_Normal upon success, an error code otherwise + */ + OFCondition detachValueField(OFBool copy = OFFalse); + + // PUT operations + + /** replace the element value by a copy of the given string (which is possibly + * multi-valued). Requires element to be of corresponding VR, otherwise an error + * is returned. + * @param val new attribute value + * @return EC_Normal upon success, an error code otherwise + */ + virtual OFCondition putOFStringArray(const OFString &val); + + /** replace the element value by a copy of the given string (which is possibly + * multi-valued). Requires element to be of corresponding VR, otherwise an error + * is returned. + * @param val new attribute value + * @return EC_Normal upon success, an error code otherwise + */ + virtual OFCondition putString(const char *val); + + /** replace the element value by a copy of the given string (which is possibly + * multi-valued). Requires element to be of corresponding VR, otherwise an error + * is returned. + * @param val new attribute value + * @param len length of the new attribute value (number of characters) + * @return EC_Normal upon success, an error code otherwise + */ + virtual OFCondition putString(const char *val, + const Uint32 len); + + /** insert into the element value a copy of the given Sint16 value. If the + * attribute is multi-valued, all other values remain untouched. + * Requires element to be of corresponding VR, otherwise an error is returned. + * @param val new value to be inserted + * @param pos position for insert operation. Value: pos <= getVM(), i.e. a value + * can be appended to the end of the current element or inserted within the + * existing value field. + * @return EC_Normal upon success, an error code otherwise + */ + virtual OFCondition putSint16(const Sint16 val, const unsigned long pos = 0); + + /** insert into the element value a copy of the given Uint16 value. If the + * attribute is multi-valued, all other values remain untouched. + * Requires element to be of corresponding VR, otherwise an error is returned. + * @param val new value to be inserted + * @param pos position for insert operation. Value: pos <= getVM(), i.e. a value + * can be appended to the end of the current element or inserted within the + * existing value field. + * @return EC_Normal upon success, an error code otherwise + */ + virtual OFCondition putUint16(const Uint16 val, const unsigned long pos = 0); + + /** insert into the element value a copy of the given Sint32 value. If the + * attribute is multi-valued, all other values remain untouched. + * Requires element to be of corresponding VR, otherwise an error is returned. + * @param val new value to be inserted + * @param pos position for insert operation. Value: pos <= getVM(), i.e. a value + * can be appended to the end of the current element or inserted within the + * existing value field. + * @return EC_Normal upon success, an error code otherwise + */ + virtual OFCondition putSint32(const Sint32 val, const unsigned long pos = 0); + + /** insert into the element value a copy of the given Uint32 value. If the + * attribute is multi-valued, all other values remain untouched. + * Requires element to be of corresponding VR, otherwise an error is returned. + * @param val new value to be inserted + * @param pos position for insert operation. Value: pos <= getVM(), i.e. a value + * can be appended to the end of the current element or inserted within the + * existing value field. + * @return EC_Normal upon success, an error code otherwise + */ + virtual OFCondition putUint32(const Uint32 val, const unsigned long pos = 0); + + /** insert into the element value a copy of the given Float32 value. If the + * attribute is multi-valued, all other values remain untouched. + * Requires element to be of corresponding VR, otherwise an error is returned. + * @param val new value to be inserted + * @param pos position for insert operation. Value: pos <= getVM(), i.e. a value + * can be appended to the end of the current element or inserted within the + * existing value field. + * @return EC_Normal upon success, an error code otherwise + */ + virtual OFCondition putFloat32(const Float32 val, const unsigned long pos = 0); + + /** insert into the element value a copy of the given Float64 value. If the + * attribute is multi-valued, all other values remain untouched. + * Requires element to be of corresponding VR, otherwise an error is returned. + * @param val new value to be inserted + * @param pos position for insert operation. Value: pos <= getVM(), i.e. a value + * can be appended to the end of the current element or inserted within the + * existing value field. + * @return EC_Normal upon success, an error code otherwise + */ + virtual OFCondition putFloat64(const Float64 val, const unsigned long pos = 0); + + /** insert into the element value a copy of the given DcmTagKey value. If the + * attribute is multi-valued, all other values remain untouched. + * Requires element to be of corresponding VR, otherwise an error is returned. + * @param attrTag new value to be inserted + * @param pos position for insert operation. Value: pos <= getVM(), i.e. a value + * can be appended to the end of the current element or inserted within the + * existing value field. + * @return EC_Normal upon success, an error code otherwise + */ + virtual OFCondition putTagVal(const DcmTagKey &attrTag, const unsigned long pos = 0); + + /** replace the element value by a copy of the given Uint8 array (which is possibly multi-valued). + * Requires element to be of corresponding VR, otherwise an error is returned. + * @param vals new attribute value + * @param num number of values in array vals + * @return EC_Normal upon success, an error code otherwise + */ + virtual OFCondition putUint8Array(const Uint8 *vals, const unsigned long num); + + /** replace the element value by a copy of the given Sint16 array (which is possibly multi-valued). + * Requires element to be of corresponding VR, otherwise an error is returned. + * @param vals new attribute value + * @param num number of values in array vals + * @return EC_Normal upon success, an error code otherwise + */ + virtual OFCondition putSint16Array(const Sint16 *vals, const unsigned long num); + + /** replace the element value by a copy of the given Uint16 array (which is possibly multi-valued). + * Requires element to be of corresponding VR, otherwise an error is returned. + * @param vals new attribute value + * @param num number of values in array vals + * @return EC_Normal upon success, an error code otherwise + */ + virtual OFCondition putUint16Array(const Uint16 *vals, const unsigned long num); + + /** replace the element value by a copy of the given Sint32 array (which is possibly multi-valued). + * Requires element to be of corresponding VR, otherwise an error is returned. + * @param vals new attribute value + * @param num number of values in array vals + * @return EC_Normal upon success, an error code otherwise + */ + virtual OFCondition putSint32Array(const Sint32 *vals, const unsigned long num); + + /** replace the element value by a copy of the given Uint32 array (which is possibly multi-valued). + * Requires element to be of corresponding VR, otherwise an error is returned. + * @param vals new attribute value + * @param num number of values in array vals + * @return EC_Normal upon success, an error code otherwise + */ + virtual OFCondition putUint32Array(const Uint32 *vals, const unsigned long num); + + /** replace the element value by a copy of the given Float32 array (which is possibly multi-valued). + * Requires element to be of corresponding VR, otherwise an error is returned. + * @param vals new attribute value + * @param num number of values in array vals + * @return EC_Normal upon success, an error code otherwise + */ + virtual OFCondition putFloat32Array(const Float32 *vals, const unsigned long num); + + /** replace the element value by a copy of the given Float64 array (which is possibly multi-valued). + * Requires element to be of corresponding VR, otherwise an error is returned. + * @param vals new attribute value + * @param num number of values in array vals + * @return EC_Normal upon success, an error code otherwise + */ + virtual OFCondition putFloat64Array(const Float64 *vals, const unsigned long num); + + /** Copy numBytes bytes of data from the attribute value in byteOrder byte order + * to targetBuffer, starting at byte offset offset of the attribute value. + * This method does not cause the complete attribute value to be read into + * main memory. Subsequent calls for the same partial value may cause repeated + * access to file if the attribute value is kept in file. + * @param targetBuffer pointer to target buffer, must not be NULL. + * Buffer size must be at least numBytes bytes. + * @param offset byte offset within the attribute value from where to start + * copying + * @param numBytes number of bytes to copy. + * @param cache file cache object that may be passed to multiple subsequent calls + * to this method for the same file; the file cache will then keep a file + * handle open, thus improving performance. Optional, may be NULL + * @param byteOrder byte order desired byte order of attribute value in memory buffer. + * Default is the local byte order of the machine. + * @return EC_Normal upon success, an error code otherwise + */ + virtual OFCondition getPartialValue(void *targetBuffer, + const Uint32 offset, + Uint32 numBytes, + DcmFileCache *cache = NULL, + E_ByteOrder byteOrder = gLocalByteOrder); + + /** create an empty Uint8 array of given number of bytes and set it. + * All array elements are initialized with a value of 0 (using 'memzero'). + * This method is only applicable to certain VRs, e.g. OB. + * @param numBytes number of bytes (8 bit) to be created + * @param bytes stores the pointer to the resulting buffer + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition createUint8Array(const Uint32 numBytes, Uint8 *&bytes); + + /** create an empty Uint16 array of given number of words and set it. + * All array elements are initialized with a value of 0 (using 'memzero'). + * This method is only applicable to OW data. + * @param numWords number of words (16 bit) to be created + * @param words stores the pointer to the resulting buffer + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition createUint16Array(const Uint32 numWords, Uint16 *&words); + + /** replace the attribute value with the content of the given temporary file. + * The temporary file is not opened/loaded until the attribute value is accessed, + * very much like large attributes that remain in file during a read operation. + * @param factory a factory object that is able to create an input stream + * to the temporary file at the right location. + * @param length attribute value length, in bytes. Must be even length. + * The length is not checked against the real length of the temporary file, + * which might be written or completed after the call to this method. + * @param byteOrder byte order in the temporary file + * @return EC_Normal upon success, an error code otherwise. + */ + virtual OFCondition createValueFromTempFile(DcmInputStreamFactory *factory, + const Uint32 length, + const E_ByteOrder byteOrder); + + /** remove the attribute value from memory if the attribute value can + * be loaded from file when needed again. Otherwise do nothing. + */ + virtual void compact(); + + /** compute uncompressed frame size of a single frame of this image. + * Note that the value returned by this method does not include the pad byte + * to even size needed for a buffer into which a frame is to be loaded. + * @param dataset dataset in which this pixel data element is contained + * @param frameSize frame size in bytes (without padding) returned in this + * parameter upon success + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getUncompressedFrameSize(DcmItem *dataset, + Uint32 &frameSize) const; + + /** access single frame without decompressing or loading a complete + * multi-frame object. The frame is copied into the buffer passed by the caller + * which must be large enough to contain a complete frame. + * @param dataset pointer to DICOM dataset in which this pixel data object is + * located. Used to access rows, columns, samples per pixel etc. + * @param frameNo numer of frame, starting with 0 for the first frame. + * @param startFragment index of the compressed fragment that contains + * all or the first part of the compressed bitstream for the given frameNo. + * Upon successful return this parameter is updated to contain the index + * of the first compressed fragment of the next frame. + * When unknown, zero should be passed. In this case the decompression + * algorithm will try to determine the index by itself, which will always + * work if frames are decompressed in increasing order from first to last, + * but may fail if frames are decompressed in random order, multiple fragments + * per frame and multiple frames are present in the dataset, and the offset + * table is empty. + * @param buffer pointer to buffer allocated by the caller. The buffer + * must be large enough for one frame of this image. + * @param bufSize size of buffer, in bytes + * @param decompressedColorModel upon successful return, the color model + * of the decompressed image (which may be different from the one used + * in the compressed images) is returned in this parameter. + * @param cache file cache object that may be passed to multiple subsequent calls + * to this method for the same file; the file cache will then keep a file + * handle open, thus improving performance. Optional, may be NULL + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getUncompressedFrame(DcmItem *dataset, + Uint32 frameNo, + Uint32 &startFragment, + void *buffer, + Uint32 bufSize, + OFString &decompressedColorModel, + DcmFileCache *cache = NULL); + + /** determine color model of the decompressed image + * @param dataset pointer to DICOM dataset in which this pixel data object + * is located. Used to access photometric interpretation. + * @param decompressedColorModel upon successful return, the color model + * of the decompressed image (which may be different from the one used + * in the compressed images) is returned in this parameter + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getDecompressedColorModel(DcmItem *dataset, + OFString &decompressedColorModel); + + /* --- static helper functions --- */ + + /** scan string value for conformance with given value representation (VR) + * @param value string value to be scanned + * @param vr two-character identifier of the VR to be checked (lower case) + * @param pos position of the first character to be scanned in 'value' + * @param num number of characters to be scanned in 'value' (default: all) + * @return numeric identifier of the VR found, 16 in case of unknown VR + */ + static int scanValue(const OFString &value, + const OFString &vr, + const size_t pos = 0, + const size_t num = OFString_npos); + + /** determine the number of values stored in a string, i.e.\ the value multiplicity (VM) + * @param str character string + * @param len length of the string (number of characters without the trailing NULL byte) + * @return number of values separated by backslash characters in the given string + */ + static unsigned long determineVM(const char *str, + const size_t len); + + /** get the first value stored in the given string. The individual values are separated by + * a backslash. Successive calls of this function allow for extracting all stored values. + * @param str character string + * @param pos position of the first character in the string to search from + * @param len length of the string (number of characters without the trailing NULL byte) + * @param val variable in which the result is stored (empty string in case of error) + * @return position to be used for the next search, identical to 'pos' in case of error + */ + static size_t getValueFromString(const char *str, + const size_t pos, + const size_t len, + OFString &val); + + /** check for correct value multiplicity (VM) + * @param vmNum value multiplicity of the value to be checked. + * For empty values (vmNum=0), the status of the check is always EC_Normal (i.e. no error). + * @param vmStr value multiplicity (according to the data dictionary) to be checked for. + * (valid values: "1", "1-2", "1-3", "1-8", "1-99", "1-n", "2", "2-n", "2-2n", + * "3", "3-n", "3-3n", "4", "5", "5-n", "6", "7", "7-7n", "8", "9", + * "16", "24", "32", "256") + * @return status of the check, EC_ValueMultiplicityViolated in case of error + */ + static OFCondition checkVM(const unsigned long vmNum, + const OFString &vmStr); + + protected: + + /** This function returns this element's value. The returned value corresponds to the + * byte ordering (little or big endian) that was passed. + * @param newByteOrder The byte ordering that shall be accounted + * for (little or big endian). + */ + void *getValue(const E_ByteOrder newByteOrder = gLocalByteOrder); + + /** insert into the element value a copy of the given raw value. If the + * attribute is multi-valued, all other values remain untouched. + * Only works for fixed-size VRs, not for strings. + * @param value new value to be inserted + * @param position position for insert operation. Value: pos <= getVM(), i.e.\ a value + * can be appended to the end of the current element or inserted within the existing + * value field. + * @param num number of bytes for each value in the value field. + * @return EC_Normal upon success, an error code otherwise + */ + OFCondition changeValue(const void *value, // new Value + const Uint32 position, // position in value array + const Uint32 num); // number of new value bytes + + /** replace the element value by a copy of the given raw data block + * @param value new attribute value + * @param length length of new attribute value in bytes + * @return EC_Normal upon success, an error code otherwise + */ + OFCondition putValue(const void *value, // new value + const Uint32 length); // number of new value bytes + + /** create a new, empty value field of given size. + * @param length size of new value field in bytes + * @return EC_Normal if successful, an error code otherwise. + */ + OFCondition createEmptyValue(const Uint32 length); // number of new value bytes + + /** This function reads the data value of an attribute and stores the + * information which was read in this. The information is either read + * from the inStream or (if inStream is NULL) from a different stream + * which was created earlier and which is accessible through the fLoadValue + * member variable. Note that if not all information for an attribute + * could be read from the stream, the function returns EC_StreamNotifyClient. + * @param inStream The stream which contains the information. + * @return status, EC_Normal if successful, an error code otherwise + */ + OFCondition loadValue(DcmInputStream *inStream = NULL); + + /** performs clean-up functions after loading an attribute value into main memory. + * In particular, if dcmEnableAutomaticInputDataCorrection is enabled, silently + * fixes odd length elements. + */ + virtual void postLoadValue(); + + /** This function creates a byte array of Length bytes and returns this + * array. In case Length is odd, an array of Length+1 bytes will be + * created and Length will be increased by 1. + */ + virtual Uint8 *newValueField(); + + /** swaps the content of the value field (if loaded) from big-endian to + * little-endian or back + * @param valueWidth width (in bytes) of each element value + */ + void swapValueField(size_t valueWidth); + + /** write element start tag in XML format + * @param out output stream to which the XML start tag is written + * @param flags flag used to customize the output (not yet used) + * @param attrText extra attribute text to be added to the element tag + */ + virtual void writeXMLStartTag(STD_NAMESPACE ostream &out, + const size_t flags, + const char *attrText = NULL); + + /** write element end tag in XML format + * @param out output stream to which the XML end tag is written + * @param flags flag used to customize the output (not yet used) + */ + virtual void writeXMLEndTag(STD_NAMESPACE ostream &out, + const size_t flags); + + /** return the current byte order of the value field + * @return current byte order of the value field + */ + E_ByteOrder getByteOrder() const { return fByteOrder; } + + /** set the current byte order of the value field + * @param val byte order of the value field + */ + void setByteOrder(E_ByteOrder val) { fByteOrder = val; } + + private: + + /// current byte order of attribute value in memory + E_ByteOrder fByteOrder; + + /// required information to load value later + DcmInputStreamFactory *fLoadValue; + + /// value of the element + Uint8 *fValue; +}; + + +#endif // DCELEM_H diff --git a/dcmdata/include/dcmtk/dcmdata/dcerror.h b/dcmdata/include/dcmtk/dcmdata/dcerror.h new file mode 100644 index 00000000..ad41eaf5 --- /dev/null +++ b/dcmdata/include/dcmtk/dcmdata/dcerror.h @@ -0,0 +1,173 @@ +/* + * + * Copyright (C) 1994-2015, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Andrew Hewett + * + * Purpose: Error handling, codes and strings + * + */ + + +#ifndef DCERROR_H +#define DCERROR_H + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ +#include "dcmtk/ofstd/ofcond.h" /* for OFCondition */ +#include "dcmtk/dcmdata/dcdefine.h" + +// include this file in doxygen documentation + +/** @file dcerror.h + * @brief error handling, codes and strings for the dcmdata module + */ + +/* + * DCMTK module numbers for modules which create their own error codes. + * Module numbers > 1023 are reserved for user code. + */ + +const unsigned short OFM_dcmdata = 1; +const unsigned short OFM_ctndisp = 2; /* retired */ +const unsigned short OFM_dcmimgle = 3; +const unsigned short OFM_dcmimage = 4; +const unsigned short OFM_dcmjpeg = 5; +const unsigned short OFM_dcmnet = 6; +const unsigned short OFM_dcmprint = 7; +const unsigned short OFM_dcmpstat = 8; +const unsigned short OFM_dcmsign = 9; +const unsigned short OFM_dcmsr = 10; +const unsigned short OFM_dcmtls = 11; +const unsigned short OFM_dcmqrdb = 12; +const unsigned short OFM_wlistctn = 13; /* retired */ +const unsigned short OFM_dcmwlm = 14; +const unsigned short OFM_dcmpps = 15; +const unsigned short OFM_dcmdbsup = 16; +const unsigned short OFM_dcmppswm = 17; +const unsigned short OFM_dcmjp2k = 18; +const unsigned short OFM_dcmjpls = 19; +const unsigned short OFM_dcmwave = 20; +const unsigned short OFM_dcmrt = 21; +const unsigned short OFM_dcmloco = 22; +const unsigned short OFM_dcmstcom = 23; +const unsigned short OFM_dcmppscu = 24; +const unsigned short OFM_dcmstscp = 25; +const unsigned short OFM_dcmqrdbx = 26; +const unsigned short OFM_dcmkosel = 27; +const unsigned short OFM_dcmenc = 28; +const unsigned short OFM_dcmiod = 29; +const unsigned short OFM_dcmseg = 30; +const unsigned short OFM_dcmfg = 31; + + +// condition constants + +/** @name condition constants for module dcmdata. + * These constants can be used in addition to the general purpose ones + * defined in module ofstd. + */ +//@{ +/// Invalid tag +extern DCMTK_DCMDATA_EXPORT const OFConditionConst EC_InvalidTag; +/// Tag not found +extern DCMTK_DCMDATA_EXPORT const OFConditionConst EC_TagNotFound; +/// Invalid VR +extern DCMTK_DCMDATA_EXPORT const OFConditionConst EC_InvalidVR; +/// Invalid stream +extern DCMTK_DCMDATA_EXPORT const OFConditionConst EC_InvalidStream; +/// End of stream +extern DCMTK_DCMDATA_EXPORT const OFConditionConst EC_EndOfStream; +/// Corrupted data +extern DCMTK_DCMDATA_EXPORT const OFConditionConst EC_CorruptedData; +/// Illegal call, perhaps wrong parameters +extern DCMTK_DCMDATA_EXPORT const OFConditionConst EC_IllegalCall; +/// Sequence end +extern DCMTK_DCMDATA_EXPORT const OFConditionConst EC_SequEnd; +/// Doubled tag +extern DCMTK_DCMDATA_EXPORT const OFConditionConst EC_DoubledTag; +/// I/O suspension or premature end of stream +extern DCMTK_DCMDATA_EXPORT const OFConditionConst EC_StreamNotifyClient; +/// Stream mode (R/W, random/sequence) is wrong +extern DCMTK_DCMDATA_EXPORT const OFConditionConst EC_WrongStreamMode; +/// Item end +extern DCMTK_DCMDATA_EXPORT const OFConditionConst EC_ItemEnd; +/// Compressed/uncompressed pixel representation not found +extern DCMTK_DCMDATA_EXPORT const OFConditionConst EC_RepresentationNotFound; +/// Pixel representation cannot be changed to requested transfer syntax +extern DCMTK_DCMDATA_EXPORT const OFConditionConst EC_CannotChangeRepresentation; +/// Unsupported compression or encryption +extern DCMTK_DCMDATA_EXPORT const OFConditionConst EC_UnsupportedEncoding; +/// Parser failure: Putback operation failed +extern DCMTK_DCMDATA_EXPORT const OFConditionConst EC_PutbackFailed; +/// Too many compression filters +extern DCMTK_DCMDATA_EXPORT const OFConditionConst EC_DoubleCompressionFilters; +/// Storage media application profile violated +extern DCMTK_DCMDATA_EXPORT const OFConditionConst EC_ApplicationProfileViolated; +/// Invalid offset +extern DCMTK_DCMDATA_EXPORT const OFConditionConst EC_InvalidOffset; +/// Too many bytes requested +extern DCMTK_DCMDATA_EXPORT const OFConditionConst EC_TooManyBytesRequested; +/// Invalid basic offset table +extern DCMTK_DCMDATA_EXPORT const OFConditionConst EC_InvalidBasicOffsetTable; +/// Element length is larger than (explicit) length of surrounding item +extern DCMTK_DCMDATA_EXPORT const OFConditionConst EC_ElemLengthLargerThanItem; +/// File meta information header missing +extern DCMTK_DCMDATA_EXPORT const OFConditionConst EC_FileMetaInfoHeaderMissing; +/// Item or sequence content larger than explicit 32-bit length field permits +extern DCMTK_DCMDATA_EXPORT const OFConditionConst EC_SeqOrItemContentOverflow; +/// Value Representation (VR) violated +extern DCMTK_DCMDATA_EXPORT const OFConditionConst EC_ValueRepresentationViolated; +/// Value Multiplicity (VM) violated +extern DCMTK_DCMDATA_EXPORT const OFConditionConst EC_ValueMultiplicityViolated; +/// Maximum VR length violated +extern DCMTK_DCMDATA_EXPORT const OFConditionConst EC_MaximumLengthViolated; +/// Element length is larger than 16-bit length field permits +extern DCMTK_DCMDATA_EXPORT const OFConditionConst EC_ElemLengthExceeds16BitField; +/// Missing Sequence Delimitation Item while reading a sequence +extern DCMTK_DCMDATA_EXPORT const OFConditionConst EC_SequDelimitationItemMissing; +/// Missing Item Delimitation Item while reading an item +extern DCMTK_DCMDATA_EXPORT const OFConditionConst EC_ItemDelimitationItemMissing; +/// Sequence delimiter occurs before explicit item length is completely read +extern DCMTK_DCMDATA_EXPORT const OFConditionConst EC_PrematureSequDelimitationItem; +/// Invalid DICOMDIR, e.g. corrupted data structures +extern DCMTK_DCMDATA_EXPORT const OFConditionConst EC_InvalidDICOMDIR; +/// Unknown VR, e.g. tag not found in data dictionary +extern DCMTK_DCMDATA_EXPORT const OFConditionConst EC_UnknownVR; +/// Invalid value, e.g. element value has been provided that does not match the VR +extern DCMTK_DCMDATA_EXPORT const OFConditionConst EC_InvalidValue; +/// An expected Item was not found +extern DCMTK_DCMDATA_EXPORT const OFConditionConst EC_ItemNotFound; +/// Given transfersyntax is unknown +extern DCMTK_DCMDATA_EXPORT const OFConditionConst EC_UnknownTransferSyntax; +/// Cannot check +extern DCMTK_DCMDATA_EXPORT const OFConditionConst EC_CannotCheck; +/// Missing value, e.g. element must contain a value but is empty +extern DCMTK_DCMDATA_EXPORT const OFConditionConst EC_MissingValue; +/// Missing attribute +extern DCMTK_DCMDATA_EXPORT const OFConditionConst EC_MissingAttribute; +/// Internal error +extern DCMTK_DCMDATA_EXPORT const OFConditionConst EC_InternalError; +//@} + +// status code constants + +/// error, cannot select specific character set +extern DCMTK_DCMDATA_EXPORT const unsigned short EC_CODE_CannotSelectCharacterSet; +/// error, cannot convert specific character set +extern DCMTK_DCMDATA_EXPORT const unsigned short EC_CODE_CannotConvertCharacterSet; +/// error, cannot convert to XML +extern DCMTK_DCMDATA_EXPORT const unsigned short EC_CODE_CannotConvertToXML; + + +#endif /* !DCERROR_H */ diff --git a/dcmdata/include/dcmtk/dcmdata/dcfcache.h b/dcmdata/include/dcmtk/dcmdata/dcfcache.h new file mode 100644 index 00000000..f8fe3d54 --- /dev/null +++ b/dcmdata/include/dcmtk/dcmdata/dcfcache.h @@ -0,0 +1,111 @@ +/* + * + * Copyright (C) 1994-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Marco Eichelberg + * + * Purpose: file cache facility for DcmElement::getPartialValue + * + */ + +#ifndef DCFCACHE_H +#define DCFCACHE_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/ofstd/offile.h" /* for offile_off_t */ +#include "dcmtk/dcmdata/dcistrma.h" /* for class DcmInputStream */ + +/** This class implements a simple container that stores an input stream, + * the position of that input stream corresponding to the start of a DICOM + * element value field contained in the stream and the current "owner" object. + * It is used to keep a single file handle open during multiple calls to + * DcmElement::getPartialValue(), thus speeding up the reading. + */ +class DCMTK_DCMDATA_EXPORT DcmFileCache +{ +public: + + /// default constructor + DcmFileCache() + : stream_(NULL) + , offset_(0) + , user_(NULL) + { + } + + /// destructor + ~DcmFileCache() + { + delete stream_; + } + + /** checks if the given object is the current user of this cache + * returns true if so, false otherwise + * @param object pointer to "user object" + */ + OFBool isUser(void *object) const + { + return object == user_; + } + + /// returns object to default constructed state + void clear() + { + delete stream_; + stream_ = NULL; + offset_ = 0; + user_ = NULL; + } + + /** initializes the file cache with the given stream object + * and user. + * @param stream stream object + * @param user user object + */ + void init(DcmInputStream *stream, void *user) + { + clear(); + stream_ = stream; + user_ = user; + if (stream_) offset_ = stream_->tell(); + } + + /// return input stream + DcmInputStream *getStream() + { + return stream_; + } + + /// return initial stream offset + offile_off_t getOffset() const { return offset_; } + +private: + + /// private undefined copy constructor + DcmFileCache(const DcmFileCache& arg); + + /// private undefined copy assignment operator + DcmFileCache& operator=(const DcmFileCache& arg); + + /// input stream, may be NULL + DcmInputStream *stream_; + + /// offset within stream for initial position + offile_off_t offset_; + + /// object that currently uses the file cache, i.e. has created the stream + const void *user_; +}; + +#endif diff --git a/dcmdata/include/dcmtk/dcmdata/dcfilefo.h b/dcmdata/include/dcmtk/dcmdata/dcfilefo.h new file mode 100644 index 00000000..6a3e331f --- /dev/null +++ b/dcmdata/include/dcmtk/dcmdata/dcfilefo.h @@ -0,0 +1,461 @@ +/* + * + * Copyright (C) 1994-2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Gerd Ehlers, Andreas Barth + * + * Purpose: Interface of class DcmFileFormat + * + */ + + +#ifndef DCFILEFO_H +#define DCFILEFO_H + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/dcmdata/dcsequen.h" +#include "dcmtk/dcmdata/dcdatset.h" + + +// forward declarations +class DcmMetaInfo; +class DcmInputStream; +class DcmOutputStream; +class DcmRepresentationParameter; + + +/** a class handling the DICOM file format (with meta header) + */ +class DCMTK_DCMDATA_EXPORT DcmFileFormat + : public DcmSequenceOfItems +{ + + public: + + /** default constructor + */ + DcmFileFormat(); + + /** constructor taking an existing dataset for initialization. Depending on the + * parameters, a deep or shallow copy is performed. + * @param dataset the dataset to be inserted into the new DcmFileFormat object. If NULL, + * an empty dataset is created and inserted instead. + * @param deepCopy If OFTrue (default), a deep copy of the dataset is performed. + * Otherwise only the pointer is copied and the ownership + * of the dataset is taken over by the DcmFileFormat object. + */ + DcmFileFormat(DcmDataset *dataset, + OFBool deepCopy = OFTrue); + + /** copy constructor + * @param old element to be copied + */ + DcmFileFormat(const DcmFileFormat &old); + + /** destructor + */ + virtual ~DcmFileFormat(); + + /** assignment operator + * @param obj fileformat to be assigned/copied + * @return reference to this object + */ + DcmFileFormat &operator=(const DcmFileFormat &obj); + + /** clone method + * @return deep copy of this object + */ + virtual DcmObject *clone() const + { + return new DcmFileFormat(*this); + } + + /** Virtual object copying. This method can be used for DcmObject + * and derived classes to get a deep copy of an object. Internally + * the assignment operator is called if the given DcmObject parameter + * is of the same type as "this" object instance. If not, an error + * is returned. This function permits copying an object by value + * in a virtual way which therefore is different to just calling the + * assignment operator of DcmElement which could result in slicing + * the object. + * @param rhs - [in] The instance to copy from. Has to be of the same + * class type as "this" object + * @return EC_Normal if copying was successful, error otherwise + */ + virtual OFCondition copyFrom(const DcmObject& rhs); + + /** get type identifier + * @return type identifier of this class (EVR_fileFormat) + */ + virtual DcmEVR ident() const; + + /** clear file meta information header and dataset + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition clear(); + + /** remove all elements with an invalid group number from the meta information header + * and dataset + */ + virtual void removeInvalidGroups(); + + /** print meta header and dataset to a stream + * @param out output stream + * @param flags optional flag used to customize the output (see DCMTypes::PF_xxx) + * @param level current level of nested items. Used for indentation. + * @param pixelFileName optional filename used to write the raw pixel data file + * @param pixelCounter optional counter used for automatic pixel data filename creation + */ + virtual void print(STD_NAMESPACE ostream&out, + const size_t flags = 0, + const int level = 0, + const char *pixelFileName = NULL, + size_t *pixelCounter = NULL); + + /** make sure that all data elements of the file meta information header are existent + * in metainfo and contain correct values. + * @param oxfer the transfer syntax which shall be used + * @param writeMode flag indicating whether to update the file meta information or not + */ + virtual OFCondition validateMetaInfo(const E_TransferSyntax oxfer, + const E_FileWriteMode writeMode = EWM_fileformat); + + /** get file meta information header part of the fileformat + * @return reference to internally stored file meta information header + */ + DcmMetaInfo *getMetaInfo(); + + /** get dataset part of the fileformat + * @return reference to internally stored dataset + */ + DcmDataset *getDataset(); + + /** get dataset part and remove it from the fileformat. + * Please note that a new, initially empty dataset is also added to the fileformat. + * @return reference to previously stored but now removed dataset + */ + DcmDataset *getAndRemoveDataset(); + + /** calculate the length of this DICOM element when encoded with the + * given transfer syntax and the given encoding type for sequences. + * For elements, the length includes the length of the tag, length field, + * VR field and the value itself, for items and sequences it returns + * the length of the complete item or sequence including delimitation tags + * if applicable. Never returns undefined length. + * @param xfer transfer syntax for length calculation + * @param enctype sequence encoding type for length calculation + * @return length of DICOM element + */ + virtual Uint32 calcElementLength(const E_TransferSyntax xfer, + const E_EncodingType enctype); + + /** check if this DICOM object can be encoded in the given transfer syntax. + * @param newXfer transfer syntax in which the DICOM object is to be encoded + * @param oldXfer transfer syntax in which the DICOM object was read or created. + * @return true if object can be encoded in desired transfer syntax, false otherwise. + */ + virtual OFBool canWriteXfer(const E_TransferSyntax newXfer, + const E_TransferSyntax oldXfer = EXS_Unknown); + + /** read object from a stream. + * @param inStream DICOM input stream + * @param xfer transfer syntax to use when parsing + * @param glenc handling of group length parameters + * @param maxReadLength attribute values larger than this value are skipped + * while parsing and read later upon first access if the stream type supports + * this. + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition read(DcmInputStream &inStream, + const E_TransferSyntax xfer = EXS_Unknown, + const E_GrpLenEncoding glenc = EGL_noChange, + const Uint32 maxReadLength = DCM_MaxReadLength); + + /** write fileformat to a stream + * @param outStream DICOM output stream + * @param oxfer output transfer syntax + * @param enctype encoding types (undefined or explicit length) + * @param wcache pointer to write cache object, may be NULL + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition write(DcmOutputStream &outStream, + const E_TransferSyntax oxfer, + const E_EncodingType enctype, + DcmWriteCache *wcache); + + /** write object to a stream (abstract) + * @param outStream DICOM output stream + * @param oxfer output transfer syntax (EXS_Unknown means use original) + * @param enctype encoding types (undefined or explicit length) + * @param wcache pointer to write cache object, may be NULL + * @param glenc group length encoding + * @param padenc dataset trailing padding encoding + * @param padlen padding structure size for complete file + * @param subPadlen padding structure set for sequence items + * @param instanceLength number of extra bytes added to the item/dataset + * length used when computing the padding. This parameter is for instance + * used to pass the length of the file meta information header from the + * DcmFileFormat to the DcmDataset object. + * @param writeMode write file with or without meta header. Also allows for + * updating the information in the file meta information header. + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition write(DcmOutputStream &outStream, + const E_TransferSyntax oxfer, + const E_EncodingType enctype, + DcmWriteCache *wcache, + const E_GrpLenEncoding glenc, + const E_PaddingEncoding padenc = EPD_noChange, + const Uint32 padlen = 0, + const Uint32 subPadlen = 0, + Uint32 instanceLength = 0, + const E_FileWriteMode writeMode = EWM_fileformat); + + /** write object in XML format. + * The XML declaration (e.g. ) is not written by this function. + * @param out output stream to which the XML document is written + * @param flags optional flag used to customize the output (see DCMTypes::XF_xxx) + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition writeXML(STD_NAMESPACE ostream &out, + const size_t flags = 0); + + /** load object from a DICOM file. + * This method supports DICOM objects stored as a file (with meta header) or as a + * dataset (without meta header). By default, the presence of a meta header is + * detected automatically. + * @param fileName name of the file to load (may contain wide chars if support enabled). + * Since there are various constructors for the OFFilename class, a "char *", "OFString" + * or "wchar_t *" can also be passed directly to this parameter. + * @param readXfer transfer syntax used to read the data (auto detection if EXS_Unknown) + * @param groupLength flag, specifying how to handle the group length tags + * @param maxReadLength maximum number of bytes to be read for an element value. + * Element values with a larger size are not loaded until their value is retrieved + * (with getXXX()) or loadAllDataIntoMemory() is called. + * @param readMode read file with or without meta header, i.e. as a fileformat or a + * dataset. Use ERM_fileOnly in order to force the presence of a meta header. + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition loadFile(const OFFilename &fileName, + const E_TransferSyntax readXfer = EXS_Unknown, + const E_GrpLenEncoding groupLength = EGL_noChange, + const Uint32 maxReadLength = DCM_MaxReadLength, + const E_FileReadMode readMode = ERM_autoDetect); + + /** save object to a DICOM file. + * @param fileName name of the file to save (may contain wide chars if support enabled). + * Since there are various constructors for the OFFilename class, a "char *", "OFString" + * or "wchar_t *" can also be passed directly to this parameter. + * @param writeXfer transfer syntax used to write the data (EXS_Unknown means use original) + * @param encodingType flag, specifying the encoding with undefined or explicit length + * @param groupLength flag, specifying how to handle the group length tags + * @param padEncoding flag, specifying how to handle the padding tags + * @param padLength number of bytes used for the dataset padding (has to be an even number) + * @param subPadLength number of bytes used for the item padding (has to be an even number) + * @param writeMode write file with or without meta header. Also allows for updating the + * information in the file meta information header. + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition saveFile(const OFFilename &fileName, + const E_TransferSyntax writeXfer = EXS_Unknown, + const E_EncodingType encodingType = EET_UndefinedLength, + const E_GrpLenEncoding groupLength = EGL_recalcGL, + const E_PaddingEncoding padEncoding = EPD_noChange, + const Uint32 padLength = 0, + const Uint32 subPadLength = 0, + const E_FileWriteMode writeMode = EWM_fileformat); + + // methods for different pixel representations + + /** select a specific representation (compressed or uncompressed) of the dataset + * and create the representation if needed. This may cause compression or decompression + * to be applied to the pixel data in the dataset. + * @param repType desired transfer syntax + * @param repParam desired representation parameter (e.g. quality factor for lossy compression) + * @return EC_Normal upon success, an error code otherwise. + */ + OFCondition chooseRepresentation(const E_TransferSyntax repType, + const DcmRepresentationParameter *repParam) + { + return getDataset()->chooseRepresentation(repType, repParam); + } + + /** check if all PixelData elements in this dataset have a representation conforming + * to the given transfer syntax and representation parameters (see dcpixel.h for + * definition of "conforming"). + * @param repType desired transfer syntax + * @param repParam desired representation parameter (e.g. quality factor for lossy compression) + * @return true if all pixel elements have the desired representation, false otherwise + */ + OFBool hasRepresentation(const E_TransferSyntax repType, + const DcmRepresentationParameter *repParam) + { + return getDataset()->hasRepresentation(repType, repParam); + } + + /** removes all but the original representation in all pixel data elements + */ + void removeAllButOriginalRepresentations() + { + getDataset()->removeAllButOriginalRepresentations(); + } + + /** removes all but the current representation in all pixel data elements. + * Makes the current representation original. + */ + void removeAllButCurrentRepresentations() + { + getDataset()->removeAllButCurrentRepresentations(); + } + + /** get current file read mode. This mode specifies whether a file is read as a + * fileformat or dataset (without meta header). In addition, the reading can be + * restricted to DICOM files only. + * @return file read mode + */ + E_FileReadMode getReadMode() const + { + return FileReadMode; + } + + /** set current file read mode. This mode specifies whether a file is read as a + * fileformat or dataset (without meta header). In addition, the reading can be + * restricted to DICOM files only. + * @param readMode file read mode to be set + */ + void setReadMode(const E_FileReadMode readMode) + { + FileReadMode = readMode; + } + + /** method inherited from base class that shall not be used for instances of this class. + * Method immediately returns with error code. + * @param item item + * @param where where + * @return always returns EC_IllegalCall. + */ + virtual OFCondition insertItem(DcmItem *item, const unsigned long where = DCM_EndOfListIndex); + + /** method inherited from base class that shall not be used for instances of this class. + * Method immediately returns. + * @param num num + * @return always returns NULL. + */ + virtual DcmItem *remove(const unsigned long num); + + /** method inherited from base class that shall not be used for instances of this class. + * Method immediately returns. + * @param item item + * @return always returns NULL. + */ + virtual DcmItem *remove(DcmItem *item); + + /** convert all element values that are contained in the dataset and that are affected + * by SpecificCharacterSet from the given source character set to the given + * destination character set. The defined terms for a particular character set can + * be found in the DICOM standard, e.g. "ISO_IR 100" for ISO 8859-1 (Latin 1) or + * "ISO_IR 192" for Unicode in UTF-8. An empty string denotes the default character + * repertoire, which is ASCII (7-bit). If multiple values are given for 'fromCharset' + * (separated by a backslash) code extension techniques are used and escape sequences + * may be encountered in the source string to switch between the specified character + * sets. + * @param fromCharset name of the source character set(s) used for the conversion + * @param toCharset name of the destination character set used for the conversion. + * Only a single value is permitted (i.e. no code extensions). + * @param transliterate mode specifying whether a character that cannot be + * represented in the destination character encoding is approximated through one + * or more characters that look similar to the original one + * @param discardIllegal mode specifying whether characters that cannot be represented + * in the destination character encoding will be silently discarded + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition convertCharacterSet(const OFString &fromCharset, + const OFString &toCharset, + const OFBool transliterate = OFFalse, + const OFBool discardIllegal = OFFalse); + + /** convert all element values that are contained in the dataset and that are affected + * by SpecificCharacterSet to the given destination character set. The source + * character set is determined automatically from the value of the + * SpecificCharacterSet (0008,0005) element. The defined terms for the destination + * character set can be found in the DICOM standard, e.g. "ISO_IR 100" for ISO 8859-1 + * (Latin 1) or "ISO_IR 192" for Unicode in UTF-8. An empty string denotes the + * default character repertoire, which is ASCII (7-bit). + * NB: In case of a DICOMDIR, the SpecificCharacterSet in the main dataset is neither + * checked nor updated, since the Basic Directory IOD has no SOP Common Module. + * @param toCharset name of the destination character set used for the conversion. + * Only a single value is permitted (i.e. no code extensions). + * @param transliterate mode specifying whether a character that cannot be + * represented in the destination character encoding is approximated through one + * or more characters that look similar to the original one + * @param discardIllegal mode specifying whether characters that cannot be represented + * in the destination character encoding will be silently discarded + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition convertCharacterSet(const OFString &toCharset, + const OFBool transliterate = OFFalse, + const OFBool discardIllegal = OFFalse); + + /** convert all element values that are contained in the dataset and that are affected + * by SpecificCharacterSet from the currently selected source character set to the + * currently selected destination character set + * @param converter character set converter to be used to convert the element values + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition convertCharacterSet(DcmSpecificCharacterSet &converter); + + /** convert all element values that are contained in the dataset and that are + * affected by SpecificCharacterSet to UTF-8 (Unicode). The value of the + * SpecificCharacterSet (0008,0005) element is updated, set or deleted automatically + * if needed. The transliteration mode is disabled - see convertCharacterSet(). + * NB: In case of a DICOMDIR, the SpecificCharacterSet in the main dataset is neither + * checked nor updated, since the Basic Directory IOD has no SOP Common Module. + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition convertToUTF8(); + + private: + + /** This function checks if a particular data element of the file meta information header is + * existent. If the element is not existent, it will be inserted. Additionally, this function + * makes sure that the corresponding data element will contain a correct value. + * @param metainfo the meta header information + * @param dataset the data set information + * @param atagkey tag of the data element which shall be checked + * @param obj data object from metainfo which represents the data element that shall be checked. + * Equals NULL if this data element is not existent in the meta header information. + * @param oxfer The transfer syntax which shall be used. + * @param writeMode flag indicating whether to update the file meta information or not + * @return EC_Normal if successful, an error code otherwise + */ + static OFCondition checkMetaHeaderValue(DcmMetaInfo *metainfo, + DcmDataset *dataset, + const DcmTagKey &atagkey, + DcmObject *obj, + const E_TransferSyntax oxfer, + const E_FileWriteMode writeMode); + + /** read DCM_TransferSyntaxUID from meta header dataset and return as E_TransferSyntax value + * @param metainfo meta-header dataset + * @return E_TransferSyntax value for DCM_TransferSyntaxUID, EXS_Unknown if not found or unknown + */ + static E_TransferSyntax lookForXfer(DcmMetaInfo *metainfo); + + /// file read mode, specifies whether to read the meta header or not + E_FileReadMode FileReadMode; +}; + + +#endif // DCFILEFO_H diff --git a/dcmdata/include/dcmtk/dcmdata/dcfilter.h b/dcmdata/include/dcmtk/dcmdata/dcfilter.h new file mode 100644 index 00000000..07d31471 --- /dev/null +++ b/dcmdata/include/dcmtk/dcmdata/dcfilter.h @@ -0,0 +1,209 @@ +/* + * + * Copyright (C) 2012-2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Jan Schlamelcher + * + * Purpose: Class for filtering DcmItem objects regarding specific attributes. + * + */ + + +#ifndef DCFILTER_H +#define DCFILTER_H + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/ofstd/ofstring.h" +#include "dcmtk/ofstd/ofalgo.h" +#include "dcmtk/dcmdata/dcfilefo.h" + + +/** Accept or reject DcmItem objects by comparing a specific attribute to a set of values. + * DcmAttributeFilter objects can be used to compare a specific attribute with one or more + * values - or to accept any DcmItem if no attribute is specified. DcmAttributeFilter + * objects can be used like any function taking a DcmItem& or a DcmFileFormat& object as + * parameter and returning a boolean value. + */ +class DCMTK_DCMDATA_EXPORT DcmAttributeFilter +{ + /// all actual filter implementations must inherit this interface. + struct FilterInterface + { + /// enable virtual destructor. + virtual inline ~FilterInterface() {} + + /** apply the actual filter. + * @param value the value to be compared with the range of values. + * @return OFTrue if value matches one element in the range of values, + * OFFalse otherwise. + */ + virtual OFBool apply( const OFString& value ) = 0; + }; + + /** A range-based filter implementation that compares an attribute's value with a + * range of values defined by two iterators. + * @tparam Iterator a type matching the STL's ForwardIterator concept. + */ + template + class IteratorBasedFilter : public FilterInterface + { + public: + /** construct an IteratorBasedFilter object from two iterators. + * @param begin an iterator referring to the first element in the range of values. + * @param end an iterator referring to one past the end in the range of values. + */ + IteratorBasedFilter( const Iterator& begin, const Iterator& end ) + : m_Begin( begin ), m_End( end ) + { + + } + + /// @copydoc FilterInterface::apply + virtual OFBool apply( const OFString& value ) + { + return OFFind( Iterator, const OFString&, m_Begin, m_End, value ) != m_End; + } + + private: + /// disable copy constructor. + IteratorBasedFilter(const IteratorBasedFilter&); + + /// disable copy assignment. + IteratorBasedFilter& operator=(const IteratorBasedFilter&); + + /// an iterator referring to the first element in the range of values. + Iterator const m_Begin; + + /// an iterator referring to one past the end in the range of values. + Iterator const m_End; + }; + + /** helper function to deduce the Iterator type from a container's begin() and end() + * method. + * @tparam Iterator a type matching the STL's ForwardIterator concept. + * @param begin an iterator referring to the first element in the range of values. + * @param end an iterator referring to one past the end in the range of values. + * @return a pointer to a newly created IteratorBasedFilter object. + */ + template + static IteratorBasedFilter* createIteratorBasedFilter( const Iterator& begin, + const Iterator& end ) + { + return new IteratorBasedFilter( begin, end ); + } + +public: + /** construct a DcmAttributeFilter object from two iterators defining the range of + * values. + * @note each value should be comparable with an object of type OFString. + * @tparam Iterator a type matching the STL's ForwardIterator concept. + * @param tag a DcmTagKey object determining which attribute of a DcmItem should be + * compared with the range of values. + * @param begin an iterator referring to the first element in the range of values. + * @param end an iterator referring to one past the end in the range of values. + */ + template + DcmAttributeFilter( const DcmTagKey& tag, const Iterator& begin, const Iterator& end ) + : m_Tag( tag ) + , m_pFilter( createIteratorBasedFilter( begin, end ) ) + { + + } + + /** construct a DcmAttributeFilter object from a container containing the range of + * values. + * @note each value should be comparable with an object of type OFString. + * @tparam Container a class matching the STL's Container concept. + * @param tag a DcmTagKey object determining which attribute of a DcmItem should be + * compared with the range of values. + * @param container a container containing the range of values. + */ + template + DcmAttributeFilter( const DcmTagKey& tag, const Container& container ) + : m_Tag( tag ) + , m_pFilter( createIteratorBasedFilter( container.begin(), container.end() ) ) + { + + } + + /// construct a DcmAttributeFilter object that accepts any DcmItem. + DcmAttributeFilter(); + + /** construct a DcmAttributeFilter object that compares the attribute with one + * specific value. + * @param tag a DcmTagKey object determining which attribute of a DcmItem should be + * compared with the value. + * @param value an OFString that is to be compared with the actual value stored in + * the DcmItem the filter is invoked on. + * + */ + DcmAttributeFilter( const DcmTagKey& tag, const OFString& value ); + + /** construct a DcmAttributeFilter object that compares the attribute with one + * specific value. + * @param tag a DcmTagKey object determining which attribute of a DcmItem should + * be compared with the value. + * @param value a character string that is to be compared with the actual value + * stored in the DcmItem the filter is invoked on. + */ + DcmAttributeFilter( const DcmTagKey& tag, const char* const value ); + + /// free all resources used by this object. + ~DcmAttributeFilter(); + + /** apply the filter on a DcmItem. + * @param item a DcmItem the filter should accept or reject. + * @return OFTrue if the filter accepts the item, OFFalse otherwise. + */ + OFBool apply( DcmItem& item ) const; + + /** convenience function to enable using DcmAttributeFilter as a functor. + * @param item a DcmItem the filter should accept or reject. + * @return OFTrue if the filter accepts the item, OFFalse otherwise. + */ + OFBool operator()( DcmItem& item ) const; + + /** apply the filter on a DICOM file (represented by a DcmFileFormat instance). + * @param dcmfile a DcmFileFormat object the filter should accept or reject. + * @return OFTrue if the filter accepts the DICOM file, OFFalse otherwise. + */ + OFBool apply( DcmFileFormat& dcmfile ) const; + + /** convenience function to enable using DcmAttributeFilter as a functor. + * @param dcmfile a DcmFileFormat object the filter should accept or reject. + * @return OFTrue if the filter accepts the DICOM file, OFFalse otherwise. + */ + OFBool operator()( DcmFileFormat& dcmfile ) const; + +private: + /// Helper class for storing single values in a DcmAttributeFilter. + class SingleValueFilter; + + // disable copy constructor. + DcmAttributeFilter( const DcmAttributeFilter& ); + + // disable copy assignment. + DcmAttributeFilter& operator=( const DcmAttributeFilter& ); + + /** a DcmTagKey object determining which attribute of a DcmItem should be compared + * with the value. + */ + const DcmTagKey m_Tag; + + /// a pointer to the actual filter. + FilterInterface* const m_pFilter; +}; + +#endif // DCFILTER_H diff --git a/dcmdata/include/dcmtk/dcmdata/dchashdi.h b/dcmdata/include/dcmtk/dcmdata/dchashdi.h new file mode 100644 index 00000000..e54fd84d --- /dev/null +++ b/dcmdata/include/dcmtk/dcmdata/dchashdi.h @@ -0,0 +1,304 @@ +/* + * + * Copyright (C) 1994-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Andrew Hewett + * + * Purpose: Hash table interface for DICOM data dictionary + * + */ + +#ifndef DCHASHDI_H +#define DCHASHDI_H + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ +#include "dcmtk/ofstd/oflist.h" +#include "dcmtk/ofstd/ofstream.h" +#include "dcmtk/dcmdata/dcdefine.h" + +class DcmDictEntry; +class DcmTagKey; +class DcmHashDict; + +typedef OFListIterator(DcmDictEntry *) DcmDictEntryListIterator; +typedef OFListConstIterator(DcmDictEntry *) DcmDictEntryListConstIterator; + +/** an ordered list of pointers to DcmDictEntry objects + */ +class DCMTK_DCMDATA_EXPORT DcmDictEntryList +{ +public: + + /// constructor + DcmDictEntryList() : list_() {} + + /// destructor + ~DcmDictEntryList(); + + /// clears list and deletes all entries + void clear(); + + /// @return the number of elements in this list + unsigned int size() const; + + /// @return True if this list is empty + OFBool empty() const; + + /// @return Iterator to the beginning of the list + DcmDictEntryListIterator begin(); + + /// @return Iterator past the end of the list + DcmDictEntryListIterator end(); + + /// @return Iterator to the beginning of the list + DcmDictEntryListConstIterator begin() const; + + /// @return Iterator past the end of the list + DcmDictEntryListConstIterator end() const; + + /** Insert a new element in the list + * @param position Position to insert after + * @param entry Entry to insert + * @return Iterator to the new entry + */ + DcmDictEntryListIterator insert(DcmDictEntryListIterator position, DcmDictEntry *entry); + + /** Remove an element from the list. + * @param entry The entry to remove + */ + void remove(DcmDictEntry *entry); + + /** Append a new entry to the list. + * @param entry The entry to append. + */ + void push_back(DcmDictEntry *entry); + + /** inserts an entry into the list and returns any replaced entry + * @param entry new list entry + * @return replaced list entry or NULL + */ + DcmDictEntry* insertAndReplace(DcmDictEntry* entry); + + /** find an entry in the set + * @param key tag key of the entry to be searched for + * @param privCreator private creator name, may be NULL + * @return pointer to entry (if found), otherwise NULL + */ + DcmDictEntry *find(const DcmTagKey& key, const char *privCreator); + +private: + + /// private undefined copy constructor + DcmDictEntryList(const DcmDictEntryList&); + + /// private undefined copy assignment operator + DcmDictEntryList& operator=(const DcmDictEntryList&); + + /// list of entries + OFList list_; +}; + + +/** iterator class for traversing a DcmHashDict + */ +class DCMTK_DCMDATA_EXPORT DcmHashDictIterator +{ +public: + + /// default constructor + DcmHashDictIterator() + : dict(NULL), hindex(0), iterating(OFFalse), iter() + { init(NULL); } + + /** constructor, creates iterator to existing hash dictionary + * @param d pointer to dictionary + * @param atEnd if true, iterator points after last element + * of hash dictionary, otherwise iterator points to first element + */ + DcmHashDictIterator(const DcmHashDict* d, OFBool atEnd = OFFalse) + : dict(NULL), hindex(0), iterating(OFFalse), iter() + { init(d, atEnd); } + + /// copy constructor + DcmHashDictIterator(const DcmHashDictIterator& i) + : dict(i.dict), hindex(i.hindex), iterating(i.iterating), iter(i.iter) + { } + + /// copy assignment operator + DcmHashDictIterator& operator=(const DcmHashDictIterator& i) + { dict = i.dict; hindex = i.hindex; + iterating = i.iterating; iter = i.iter; return *this; } + + /// comparison equality + OFBool operator==(const DcmHashDictIterator& x) const + { return (hindex == x.hindex) && (iter == x.iter); } + + /// comparison non-equality + OFBool operator!=(const DcmHashDictIterator& x) const + { return !(*this == x); } + + /// dereferencing of iterator + const DcmDictEntry* operator*() const + { return (*iter); } + + /// pre-increment operator + DcmHashDictIterator& operator++() + { stepUp(); return *this; } + + /// post-increment operator + DcmHashDictIterator operator++(int) + { DcmHashDictIterator tmp(*this); stepUp(); return tmp; } + +private: + + /** initializes the iterator + * @param d pointer to hash dictionary, may be NULL + * @param atEnd if true, iterator points after last element + * of hash dictionary, otherwise iterator points to first element + */ + void init(const DcmHashDict *d, OFBool atEnd = OFFalse); + + /** implements increment operator on hash dictionary + */ + void stepUp(); + + /// pointer to the hash dictionary this iterator traverses + const DcmHashDict* dict; + + /// index of current bucket + int hindex; + + /// flag indicating if iter is currently valid + OFBool iterating; + + /// iterator for traversing a bucket in the hash table + DcmDictEntryListIterator iter; +}; + + +/** a hash table of pointers to DcmDictEntry objects + */ +class DCMTK_DCMDATA_EXPORT DcmHashDict +{ + +public: + /// default constructor + DcmHashDict() + : hashTab(NULL), lowestBucket(0), highestBucket(0), entryCount(0) + { _init(); } + + /// destructor + ~DcmHashDict(); + + /** counts total number of entries + * @return number of entries + */ + int size() const { return entryCount; } + + /// clears the hash table of all entries + void clear(); + + /** inserts an entry into hash table (deletes old entry if present) + * @param entry pointer to new entry + */ + void put(DcmDictEntry* entry); + + /** hash table lookup for the given tag key and private creator name + * @param key tag key of the entry to be searched for + * @param privCreator private creator name, may be NULL + * @return pointer to entry (if found), otherwise NULL + */ + const DcmDictEntry* get(const DcmTagKey& key, const char *privCreator) const; + + /** deletes the entry for the given tag and private creator + * @param key tag key of the entry to be deleted + * @param privCreator private creator name, may be NULL + */ + void del(const DcmTagKey& key, const char *privCreator); + + // iterator over the contents of the hash table + friend class DcmHashDictIterator; + + /// returns iterator to start of hash table + DcmHashDictIterator begin() const + { DcmHashDictIterator iter(this); return iter; } + + /// returns iterator to end of hash table + DcmHashDictIterator end() const + { DcmHashDictIterator iter(this, OFTrue); return iter; } + + /// prints some information about hash table bucket utilization + STD_NAMESPACE ostream& loadSummary(STD_NAMESPACE ostream& out); + +private: + + /// private unimplemented copy constructor + DcmHashDict(const DcmHashDict &); + + /// private unimplemented copy assignment operator + DcmHashDict &operator=(const DcmHashDict &); + + /// performs initialization for given hash table size, called from constructor + void _init(); + + /** compute hash value for given tag key + * @param key pointer to tag key + * @param privCreator private creator name, may be NULL + * @return hash value + */ + int hash(const DcmTagKey* key, const char *privCreator) const; + + /** inserts new entry into given list + * @param lst list to add to + * @param entry new element to add, will be deleted upon destruction of the hash table + * @return pointer to replaced element, if any + */ + DcmDictEntry* insertInList(DcmDictEntryList& lst, DcmDictEntry* entry); + + /** removes the entry for the given tag and private creator + * @param lst list to remove from + * @param key tag key of the entry to be removed + * @param privCreator private creator name, may be NULL + * @return pointer to removed element, if any + */ + DcmDictEntry* removeInList(DcmDictEntryList& lst, const DcmTagKey& key, const char *privCreator); + + /** searches entry for the given tag and private creator + * @param lst list to search in + * @param key tag key of the entry to be searched for + * @param privCreator private creator name, may be NULL + * @return pointer to found element, NULL if not found + */ + DcmDictEntry* findInList(DcmDictEntryList& lst, const DcmTagKey& key, const char *privCreator) const; + + /** array of (hash table size) pointers to DcmDictEntryList elements + * implementing the different buckets of the hash table + */ + DcmDictEntryList** hashTab; + + /// number of buckets in hash table + static const int hashTabLength; + + /// index of lowest bucket for which the DcmDictEntryList has been initialized + int lowestBucket; + + /// index of highest bucket for which the DcmDictEntryList has been initialized + int highestBucket; + + /// number of entries in hash table + int entryCount; + +}; + +#endif /* DCHASHDI_H */ diff --git a/dcmdata/include/dcmtk/dcmdata/dcistrma.h b/dcmdata/include/dcmtk/dcmdata/dcistrma.h new file mode 100644 index 00000000..8fc5ce94 --- /dev/null +++ b/dcmdata/include/dcmtk/dcmdata/dcistrma.h @@ -0,0 +1,263 @@ +/* + * + * Copyright (C) 1994-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Marco Eichelberg + * + * Purpose: base classes for input streams + * + */ + +#ifndef DCISTRMA_H +#define DCISTRMA_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/ofstd/oftypes.h" /* for OFBool */ +#include "dcmtk/ofstd/ofcond.h" /* for OFCondition */ +#include "dcmtk/ofstd/offile.h" /* for offile_off_t */ +#include "dcmtk/dcmdata/dcxfer.h" /* for E_StreamCompression */ + +class DcmInputStream; + +/** pure virtual abstract base class for producers, i.e. the initial node + * of a filter chain in an input stream. + */ +class DCMTK_DCMDATA_EXPORT DcmProducer +{ +public: + + /// destructor + virtual ~DcmProducer() + { + } + + /** returns the status of the producer. Unless the status is good, + * the producer will not permit any operation. + * @return status, true if good + */ + virtual OFBool good() const = 0; + + /** returns the status of the producer as an OFCondition object. + * Unless the status is good, the producer will not permit any operation. + * @return status, EC_Normal if good + */ + virtual OFCondition status() const = 0; + + /** returns true if the producer is at the end of stream. + * @return true if end of stream, false otherwise + */ + virtual OFBool eos() = 0; + + /** returns the minimum number of bytes that can be read with the + * next call to read(). The DcmObject read methods rely on avail + * to return a value > 0 if there is no I/O suspension since certain + * data such as tag and length are only read "en bloc", i.e. all + * or nothing. + * @return minimum of data available in producer + */ + virtual offile_off_t avail() = 0; + + /** reads as many bytes as possible into the given block. + * @param buf pointer to memory block, must not be NULL + * @param buflen length of memory block + * @return number of bytes actually read. + */ + virtual offile_off_t read(void *buf, offile_off_t buflen) = 0; + + /** skips over the given number of bytes (or less) + * @param skiplen number of bytes to skip + * @return number of bytes actually skipped. + */ + virtual offile_off_t skip(offile_off_t skiplen) = 0; + + /** resets the stream to the position by the given number of bytes. + * @param num number of bytes to putback. If the putback operation + * fails, the producer status becomes bad. + */ + virtual void putback(offile_off_t num) = 0; + +}; + + +/** pure virtual abstract base class for input filters, i.e. + * intermediate nodes of a filter chain in an input stream. + */ +class DCMTK_DCMDATA_EXPORT DcmInputFilter: public DcmProducer +{ +public: + + /// destructor + virtual ~DcmInputFilter() + { + } + + /** determines the producer from which the filter is supposed + * to read it's input. Once a producer for the input filter has + * been defined, it cannot be changed anymore during the lifetime + * of the object. + * @param producer reference to producer, must not be circular chain + */ + virtual void append(DcmProducer& producer) = 0; +}; + + +/** pure virtual abstract base class for input stream factories, + * i.e. objects that can create a new input stream + */ +class DCMTK_DCMDATA_EXPORT DcmInputStreamFactory +{ +public: + + /// destructor + virtual ~DcmInputStreamFactory() + { + } + + /** create a new input stream object + * @return pointer to new input stream object + */ + virtual DcmInputStream *create() const = 0; + + /** returns a pointer to a copy of this object + */ + virtual DcmInputStreamFactory *clone() const = 0; +}; + + +/** abstract base class for input streams. + */ +class DCMTK_DCMDATA_EXPORT DcmInputStream +{ +public: + + /// destructor + virtual ~DcmInputStream(); + + /** returns the status of the stream. Unless the status is good, + * the stream will not permit any operation. + * @return status, true if good + */ + virtual OFBool good() const; + + /** returns the status of the stream as an OFCondition object. + * Unless the status is good, the stream will not permit any operation. + * @return status, EC_Normal if good + */ + virtual OFCondition status() const; + + /** returns true if the producer is at the end of stream. + * @return true if end of stream, false otherwise + */ + virtual OFBool eos(); + + /** returns the minimum number of bytes that can be read with the + * next call to read(). The DcmObject read methods rely on avail + * to return a value > 0 if there is no I/O suspension since certain + * data such as tag and length are only read "en bloc", i.e. all + * or nothing. + * @return minimum of data available in producer + */ + virtual offile_off_t avail(); + + /** reads as many bytes as possible into the given block. + * @param buf pointer to memory block, must not be NULL + * @param buflen length of memory block + * @return number of bytes actually read. + */ + virtual offile_off_t read(void *buf, offile_off_t buflen); + + /** skips over the given number of bytes (or less) + * @param skiplen number of bytes to skip + * @return number of bytes actually skipped. + */ + virtual offile_off_t skip(offile_off_t skiplen); + + /** returns the total number of bytes read from the stream so far + * @return total number of bytes read from the stream + */ + virtual offile_off_t tell() const; + + /** installs a compression filter for the given stream compression type, + * which should be neither ESC_none nor ESC_unsupported. Once a compression + * filter is active, it cannot be deactivated or replaced during the + * lifetime of the stream. + * @param filterType type of compression filter + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition installCompressionFilter(E_StreamCompression filterType); + + /** creates a new factory object for the current stream + * and stream position. When activated, the factory will be + * able to create new DcmInputStream delivering the same + * data as the current stream. Used to defer loading of + * value fields until accessed. + * If no factory object can be created (e.g. because the + * stream is not seekable), returns NULL. + * @return pointer to new factory object if successful, NULL otherwise. + */ + virtual DcmInputStreamFactory *newFactory() const = 0; + + /** marks the current stream position for a later putback operation, + * overwriting a possibly existing prior putback mark. + * The DcmObject read methods rely on the possibility to putback + * up to 132 bytes for transfer syntax detection, parse error recovery etc. + * Implementations of this class should guarantee a putback capability + * of at least 1 kbyte. + */ + virtual void mark(); + + /** resets the stream to the position previously marked with + * setPutbackMark(). If the putback operation fails (no putback mark + * set or putback buffer exceeded), status of the producer switches to bad. + */ + virtual void putback(); + +protected: + + /** protected constructor, to be called from derived class constructor + * @param initial initial pointer to first node in filter chain + * The pointer is not dereferenced in the constructor, so the + * object pointed to may be initialized later in the subclass + * constructor. + */ + DcmInputStream(DcmProducer *initial); + + /** returns pointer to current producer object + */ + const DcmProducer *currentProducer() const; + +private: + + /// private unimplemented copy constructor + DcmInputStream(const DcmInputStream&); + + /// private unimplemented copy assignment operator + DcmInputStream& operator=(const DcmInputStream&); + + /// pointer to first node in filter chain + DcmProducer *current_; + + /// pointer to compression filter, NULL if no compression + DcmInputFilter *compressionFilter_; + + /// counter for number of bytes read so far + offile_off_t tell_; + + /// putback marker + offile_off_t mark_; +}; + + + +#endif diff --git a/dcmdata/include/dcmtk/dcmdata/dcistrmb.h b/dcmdata/include/dcmtk/dcmdata/dcistrmb.h new file mode 100644 index 00000000..f9cf0b5f --- /dev/null +++ b/dcmdata/include/dcmtk/dcmdata/dcistrmb.h @@ -0,0 +1,201 @@ +/* + * + * Copyright (C) 1994-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Marco Eichelberg + * + * Purpose: DcmInputBufferStream and related classes, + * implements input to blocks of memory as needed in the dcmnet module. + * + */ + +#ifndef DCISTRMB_H +#define DCISTRMB_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmdata/dcistrma.h" + + +/** producer class that reads data from a buffer provided by the caller. + * Used for DICOM network communication. + */ +class DCMTK_DCMDATA_EXPORT DcmBufferProducer: public DcmProducer +{ +public: + /** constructor + */ + DcmBufferProducer(); + + /// destructor + virtual ~DcmBufferProducer(); + + /** returns the status of the producer. Unless the status is good, + * the producer will not permit any operation. + * @return status, true if good + */ + virtual OFBool good() const; + + /** returns the status of the producer as an OFCondition object. + * Unless the status is good, the producer will not permit any operation. + * @return status, EC_Normal if good + */ + virtual OFCondition status() const; + + /** returns true if the producer is at the end of stream. + * @return true if end of stream, false otherwise + */ + virtual OFBool eos(); + + /** returns the minimum number of bytes that can be read with the + * next call to read(). The DcmObject read methods rely on avail + * to return a value > 0 if there is no I/O suspension since certain + * data such as tag and length are only read "en bloc", i.e. all + * or nothing. + * @return minimum of data available in producer + */ + virtual offile_off_t avail(); + + /** reads as many bytes as possible into the given block. + * @param buf pointer to memory block, must not be NULL + * @param buflen length of memory block + * @return number of bytes actually read. + */ + virtual offile_off_t read(void *buf, offile_off_t buflen); + + /** skips over the given number of bytes (or less) + * @param skiplen number of bytes to skip + * @return number of bytes actually skipped. + */ + virtual offile_off_t skip(offile_off_t skiplen); + + /** resets the stream to the position by the given number of bytes. + * @param num number of bytes to putback. If the putback operation + * fails, the producer status becomes bad. + */ + virtual void putback(offile_off_t num); + + /** adds the content of the given buffer to the input stream. + * @param buf buffer from which data is read. Must be allocated + * by caller and remain valid until releaseBuffer() is called + * @param buflen buffer length, must be even number > 0. + */ + virtual void setBuffer(const void *buf, offile_off_t buflen); + + /** releases the current buffer. Should only be called when + * the content of the buffer has been read as far as possible. + * Pending input from the buffer is copied into an internal + * backup buffer if necessary. If an overflow condition + * occurs, the producer status becomes bad. + */ + virtual void releaseBuffer(); + + /** marks the end of stream, i.e. the data provided with the last call + * to setBuffer is the last data available in the stream. + */ + virtual void setEos(); + +private: + + /// private unimplemented copy constructor + DcmBufferProducer(const DcmBufferProducer&); + + /// private unimplemented copy assignment operator + DcmBufferProducer& operator=(const DcmBufferProducer&); + + /// the user buffer we're actually reading from + unsigned char *buffer_; + + /// the backup buffer + unsigned char *backup_; + + /// size of the user buffer, in bytes + offile_off_t bufSize_; + + /// number of bytes read from the user buffer + offile_off_t bufIndex_; + + /// number of bytes read from the backup buffer + offile_off_t backupIndex_; + + /// index of first valid byte in backup buffer, for putback + offile_off_t backupStart_; + + /// status + OFCondition status_; + + /// true if setEos has been called before + OFBool eosflag_; + +}; + + +/** input stream that reads from a buffer of fixed length + * which must be provided by the caller. + */ +class DCMTK_DCMDATA_EXPORT DcmInputBufferStream: public DcmInputStream +{ +public: + /** constructor + */ + DcmInputBufferStream(); + + /// destructor + virtual ~DcmInputBufferStream(); + + /** creates a new factory object for the current stream + * and stream position. When activated, the factory will be + * able to create new DcmInputStream delivering the same + * data as the current stream. Used to defer loading of + * value fields until accessed. + * If no factory object can be created (e.g. because the + * stream is not seekable), returns NULL. + * @return pointer to new factory object if successful, NULL otherwise. + */ + virtual DcmInputStreamFactory *newFactory() const; + + /** adds the content of the given buffer to the input stream. + * @param buf buffer from which data is read. Must be allocated + * by caller and remain valid until releaseBuffer() is called + * @param buflen buffer length, must be even number > 0. + */ + virtual void setBuffer(const void *buf, offile_off_t buflen); + + /** releases the current buffer. Should only be called when + * the content of the buffer has been read as far as possible. + * Pending input from the buffer is copied into an internal + * backup buffer if necessary. If an overflow condition + * occurs, the producer status becomes bad. + */ + virtual void releaseBuffer(); + + /** marks the end of stream, i.e. the data provided with the last call + * to setBuffer is the last data available in the stream. + */ + virtual void setEos(); + +private: + + /// private unimplemented copy constructor + DcmInputBufferStream(const DcmInputBufferStream&); + + /// private unimplemented copy assignment operator + DcmInputBufferStream& operator=(const DcmInputBufferStream&); + + /// the final producer of the filter chain + DcmBufferProducer producer_; + +}; + + +#endif diff --git a/dcmdata/include/dcmtk/dcmdata/dcistrmf.h b/dcmdata/include/dcmtk/dcmdata/dcistrmf.h new file mode 100644 index 00000000..aab2064f --- /dev/null +++ b/dcmdata/include/dcmtk/dcmdata/dcistrmf.h @@ -0,0 +1,299 @@ +/* + * + * Copyright (C) 1994-2012, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Marco Eichelberg + * + * Purpose: DcmInputFileStream and related classes, + * implements streamed input from files. + * + */ + +#ifndef DCISTRMF_H +#define DCISTRMF_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmdata/dcistrma.h" + + +/** producer class that reads data from a plain file. + */ +class DCMTK_DCMDATA_EXPORT DcmFileProducer: public DcmProducer +{ +public: + /** constructor + * @param filename name of file to be opened (may contain wide chars + * if support enabled) + * @param offset byte offset to skip from the start of file + */ + DcmFileProducer(const OFFilename &filename, offile_off_t offset = 0); + + /// destructor + virtual ~DcmFileProducer(); + + /** returns the status of the producer. Unless the status is good, + * the producer will not permit any operation. + * @return status, true if good + */ + virtual OFBool good() const; + + /** returns the status of the producer as an OFCondition object. + * Unless the status is good, the producer will not permit any operation. + * @return status, EC_Normal if good + */ + virtual OFCondition status() const; + + /** returns true if the producer is at the end of stream. + * @return true if end of stream, false otherwise + */ + virtual OFBool eos(); + + /** returns the minimum number of bytes that can be read with the + * next call to read(). The DcmObject read methods rely on avail + * to return a value > 0 if there is no I/O suspension since certain + * data such as tag and length are only read "en bloc", i.e. all + * or nothing. + * @return minimum of data available in producer + */ + virtual offile_off_t avail(); + + /** reads as many bytes as possible into the given block. + * @param buf pointer to memory block, must not be NULL + * @param buflen length of memory block + * @return number of bytes actually read. + */ + virtual offile_off_t read(void *buf, offile_off_t buflen); + + /** skips over the given number of bytes (or less) + * @param skiplen number of bytes to skip + * @return number of bytes actually skipped. + */ + virtual offile_off_t skip(offile_off_t skiplen); + + /** resets the stream to the position by the given number of bytes. + * @param num number of bytes to putback. If the putback operation + * fails, the producer status becomes bad. + */ + virtual void putback(offile_off_t num); + +private: + + /// private unimplemented copy constructor + DcmFileProducer(const DcmFileProducer&); + + /// private unimplemented copy assignment operator + DcmFileProducer& operator=(const DcmFileProducer&); + + /// the file we're actually reading from + OFFile file_; + + /// status + OFCondition status_; + + /// number of bytes in file + offile_off_t size_; +}; + + +/** input stream factory for plain files + */ +class DCMTK_DCMDATA_EXPORT DcmInputFileStreamFactory: public DcmInputStreamFactory +{ +public: + + /** constructor + * @param filename name of file to be opened (may contain wide chars + * if support enabled) + * @param offset byte offset to skip from the start of file + */ + DcmInputFileStreamFactory(const OFFilename &filename, offile_off_t offset); + + /// copy constructor + DcmInputFileStreamFactory(const DcmInputFileStreamFactory &arg); + + /// destructor + virtual ~DcmInputFileStreamFactory(); + + /** create a new input stream object + * @return pointer to new input stream object + */ + virtual DcmInputStream *create() const; + + /** returns a pointer to a copy of this object + */ + virtual DcmInputStreamFactory *clone() const + { + return new DcmInputFileStreamFactory(*this); + } + +private: + + + /// private unimplemented copy assignment operator + DcmInputFileStreamFactory& operator=(const DcmInputFileStreamFactory&); + + /// filename + OFFilename filename_; + + /// offset in file + offile_off_t offset_; + +}; + + +/** input stream that reads from a plain file + */ +class DCMTK_DCMDATA_EXPORT DcmInputFileStream: public DcmInputStream +{ +public: + /** constructor + * @param filename name of file to be opened (may contain wide chars + * if support enabled) + * @param offset byte offset to skip from the start of file + */ + DcmInputFileStream(const OFFilename &filename, offile_off_t offset = 0); + + /// destructor + virtual ~DcmInputFileStream(); + + /** creates a new factory object for the current stream + * and stream position. When activated, the factory will be + * able to create new DcmInputStream delivering the same + * data as the current stream. Used to defer loading of + * value fields until accessed. + * If no factory object can be created (e.g. because the + * stream is not seekable), returns NULL. + * @return pointer to new factory object if successful, NULL otherwise. + */ + virtual DcmInputStreamFactory *newFactory() const; + +private: + + /// private unimplemented copy constructor + DcmInputFileStream(const DcmInputFileStream&); + + /// private unimplemented copy assignment operator + DcmInputFileStream& operator=(const DcmInputFileStream&); + + /// the final producer of the filter chain + DcmFileProducer producer_; + + /// filename + OFFilename filename_; +}; + +/** class that manages the life cycle of a temporary file. + * It maintains a thread-safe reference counter, and when this counter + * is decreased to zero, unlinks (deletes) the file and then the handler + * object itself. + */ +class DCMTK_DCMDATA_EXPORT DcmTempFileHandler +{ +public: + + /** static method that permits creation of instances of + * this class (only) on the heap, never on the stack. + * A newly created instance always has a reference counter of 1. + * @param filename path to temporary file (may contain wide chars + * if support enabled) + */ + static DcmTempFileHandler *newInstance(const OFFilename &filename); + + /** create an input stream that permits reading from the temporary file + * @return pointer to input stream. Note that there is no guarantee + * that the input stream actually permits reading, i.e. the presence of the + * temporary file is not checked. + */ + DcmInputStream *create() const; + + /// increase reference counter for this object + void increaseRefCount(); + + /** decreases reference counter for this object and deletes + * the temporary file and this object if the reference counter becomes zero. + */ + void decreaseRefCount(); + +private: + + /** private constructor. + * Instances of this class are always created through newInstance(). + * @param filename path to temporary file (may contain wide chars + * if support enabled) + */ + DcmTempFileHandler(const OFFilename &filename); + + /** private destructor. Instances of this class + * are always deleted through the reference counting methods + */ + virtual ~DcmTempFileHandler(); + + /// private undefined copy constructor + DcmTempFileHandler(const DcmTempFileHandler& arg); + + /// private undefined copy assignment operator + DcmTempFileHandler& operator=(const DcmTempFileHandler& arg); + + /** number of references to temporary file. + * Default initialized to 1 upon construction of this object + */ + size_t refCount_; + +#ifdef WITH_THREADS + /// mutex for MT-safe reference counting + OFMutex mutex_; +#endif + + /// path to temporary file + OFFilename filename_; +}; + +/** input stream factory for temporary file handlers + */ +class DCMTK_DCMDATA_EXPORT DcmInputTempFileStreamFactory: public DcmInputStreamFactory +{ +public: + + /** constructor + * @param handler pointer to temporary file handler. + * Reference counter of temporary file handler is increased by this operation. + */ + DcmInputTempFileStreamFactory(DcmTempFileHandler *handler); + + /// copy constructor + DcmInputTempFileStreamFactory(const DcmInputTempFileStreamFactory &arg); + + /// destructor, decreases reference counter of temporary file handler + virtual ~DcmInputTempFileStreamFactory(); + + /** create a new input stream object + * @return pointer to new input stream object + */ + virtual DcmInputStream *create() const; + + /** returns a pointer to a copy of this object + */ + virtual DcmInputStreamFactory *clone() const; + +private: + + /// private unimplemented copy assignment operator + DcmInputTempFileStreamFactory& operator=(const DcmInputTempFileStreamFactory&); + + /// handler for temporary file + DcmTempFileHandler *fileHandler_; +}; + + +#endif diff --git a/dcmdata/include/dcmtk/dcmdata/dcistrmz.h b/dcmdata/include/dcmtk/dcmdata/dcistrmz.h new file mode 100644 index 00000000..1c12feaf --- /dev/null +++ b/dcmdata/include/dcmtk/dcmdata/dcistrmz.h @@ -0,0 +1,198 @@ +/* + * + * Copyright (C) 1994-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Marco Eichelberg + * + * Purpose: zlib compression filter for input streams + * + */ + +#ifndef DCISTRMZ_H +#define DCISTRMZ_H + +#include "dcmtk/config/osconfig.h" + +#ifdef WITH_ZLIB + +#include "dcmtk/dcmdata/dcistrma.h" /* for DcmInputFilter */ + +BEGIN_EXTERN_C +#include +END_EXTERN_C + +/** global flag defining the behaviour of the zlib decompressor. + * When true, the input stream is expected to be in deflated ZLIB format + * instead of deflated bitstream format (i.e. RFC 1950 instead of RFC 1951). + * Default is false, i.e. DICOM compliant behavior. + */ +extern DCMTK_DCMDATA_EXPORT OFGlobal dcmZlibExpectRFC1950Encoding; + +/** zlib compression filter for input streams + */ +class DCMTK_DCMDATA_EXPORT DcmZLibInputFilter: public DcmInputFilter +{ +public: + + /// default constructor + DcmZLibInputFilter(); + + /// destructor + virtual ~DcmZLibInputFilter(); + + /** returns the status of the producer. Unless the status is good, + * the producer will not permit any operation. + * @return status, true if good + */ + virtual OFBool good() const; + + /** returns the status of the producer as an OFCondition object. + * Unless the status is good, the producer will not permit any operation. + * @return status, EC_Normal if good + */ + virtual OFCondition status() const; + + /** returns true if the producer is at the end of stream. + * @return true if end of stream, false otherwise + */ + virtual OFBool eos(); + + /** returns the minimum number of bytes that can be read with the + * next call to read(). The DcmObject read methods rely on avail + * to return a value > 0 if there is no I/O suspension since certain + * data such as tag and length are only read "en bloc", i.e. all + * or nothing. + * @return minimum of data available in producer + */ + virtual offile_off_t avail(); + + /** reads as many bytes as possible into the given block. + * @param buf pointer to memory block, must not be NULL + * @param buflen length of memory block + * @return number of bytes actually read. + */ + virtual offile_off_t read(void *buf, offile_off_t buflen); + + /** skips over the given number of bytes (or less) + * @param skiplen number of bytes to skip + * @return number of bytes actually skipped. + */ + virtual offile_off_t skip(offile_off_t skiplen); + + /** resets the stream to the position by the given number of bytes. + * @param num number of bytes to putback. If the putback operation + * fails, the producer status becomes bad. + */ + virtual void putback(offile_off_t num); + + /** determines the producer from which the filter is supposed + * to read it's input. Once a producer for the input filter has + * been defined, it cannot be changed anymore during the lifetime + * of the object. + * @param producer reference to producer, must not be circular chain + */ + virtual void append(DcmProducer& producer); + +private: + + /// private unimplemented copy constructor + DcmZLibInputFilter(const DcmZLibInputFilter&); + + /// private unimplemented copy assignment operator + DcmZLibInputFilter& operator=(const DcmZLibInputFilter&); + + /** reads data from the producer into the input ring buffer + * until the input ring buffer becomes full or the + * producer suspends + * @return number of bytes added to input buffer + */ + offile_off_t fillInputBuffer(); + + /** decompress data into the given output block until + * complete or no more input is available in the input ring buffer. + * does not re-fill the input ring buffer from the producer. + * @param buf pointer to input data + * @param buflen number of bytes in buf + * @return number of bytes processed + */ + offile_off_t decompress(const void *buf, offile_off_t buflen); + + /** reads and decompresses data from the producer + * until the producer suspends or the output ring buffer becomes full. + */ + void fillOutputBuffer(); + + /** writes the content of the output ring buffer + * to the next filter stage until the output ring buffer + * becomes empty or the next filter stage becomes full + */ + void flushOutputBuffer(); + + /** copies as much of the given block of data as possible + * in the input ring buffer + * @param buf pointer to input data + * @param buflen number of bytes in buf + * @return number of bytes copied to input ring buffer + */ + offile_off_t fillInputBuffer(const void *buf, offile_off_t buflen); + + /** feed data from the input ring buffer to the compression + * codec until complete or the output ring buffer becomes full. + * Does not flush the output ring buffer. + * @param finalize true if the content of the input ring buffer + * constitutes the end of the input stream, i.e. the compression codec + * should be forced to flush its internal state. + */ + void compressInputBuffer(OFBool finalize); + + + /// pointer to producer from which compressed input is read + DcmProducer *current_; + + /// pointer to struct z_stream object containing the zlib status + z_streamp zstream_; + + /// status + OFCondition status_; + + /// true if the zlib object has reported Z_STREAM_END + OFBool eos_; + + /// input ring buffer + unsigned char *inputBuf_; + + /// offset of first byte in input ring buffer + offile_off_t inputBufStart_; + + /// number of bytes in input ring buffer + offile_off_t inputBufCount_; + + /// output ring buffer + unsigned char *outputBuf_; + + /// offset of first byte in output ring buffer + offile_off_t outputBufStart_; + + /// number of bytes available for read in output ring buffer + offile_off_t outputBufCount_; + + /// number of putback bytes in output ring buffer + offile_off_t outputBufPutback_; + + /// flag indicating whether or not a pad byte has been appended to the input stream + OFBool padded_; +}; + +#endif +#endif diff --git a/dcmdata/include/dcmtk/dcmdata/dcitem.h b/dcmdata/include/dcmtk/dcmdata/dcitem.h new file mode 100644 index 00000000..3150b55d --- /dev/null +++ b/dcmdata/include/dcmtk/dcmdata/dcitem.h @@ -0,0 +1,1366 @@ +/* + * + * Copyright (C) 1994-2015, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Gerd Ehlers + * + * Purpose: Interface of class DcmItem + * + */ + + +#ifndef DCITEM_H +#define DCITEM_H + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/ofstd/offile.h" /* for offile_off_t */ +#include "dcmtk/dcmdata/dctypes.h" +#include "dcmtk/dcmdata/dcobject.h" +#include "dcmtk/dcmdata/dclist.h" +#include "dcmtk/dcmdata/dcpcache.h" + + +// forward declarations +class DcmSequenceOfItems; +class DcmElement; +class DcmSpecificCharacterSet; + + +/** a class representing a list of DICOM elements in which each + * element has a different tag and elements are maintained in + * increasing order of tags. In particular, a sequence item. + */ +class DCMTK_DCMDATA_EXPORT DcmItem + : public DcmObject +{ + public: + + /** default constructor + */ + DcmItem(); + + /** constructor. + * Create new item from given tag and length. + * @param tag DICOM tag for the new element + * @param len value length for the new element + */ + DcmItem(const DcmTag &tag, + const Uint32 len = 0); + + /** copy constructor + * @param old item to be copied + */ + DcmItem(const DcmItem &old); + + /** assignment operator. Private creator cache is not copied + * as it is also the case for clone(). + * @param the item to be copied + */ + DcmItem &operator=(const DcmItem &obj); + + /** comparison operator that compares the normalized value of this object + * with a given object of the same type. The tag of the element is also + * considered as the first component that is compared, followed by the + * object types (VR, i.e. DCMTK'S EVR) and the comparison of all value + * components of the object, preferrably in the order declared in the + * object (if applicable). For item values that means that all elements + * within the items are compared to each other in ascending tag order. + * This may be an expensive operation. + * @param rhs the right hand side of the comparison + * @return 0 if the object values are equal. + * -1 if either the value of the first component that does not match + * is lower in this object than in rhs, or all compared components match + * but this object has fewer components than rhs. Also returned if rhs + * cannot be casted to this object type. + * 1 if either the value of the first component that does not match + * is greater in this object than in rhs object, or all compared + * components match but the this component is longer. + */ + virtual int compare(const DcmItem& rhs) const; + + /** destructor + */ + virtual ~DcmItem(); + + /** clone method + * @return deep copy of this object + */ + virtual DcmObject *clone() const + { + return new DcmItem(*this); + } + + /** Virtual object copying. This method can be used for DcmObject + * and derived classes to get a deep copy of an object. Internally + * the assignment operator is called if the given DcmObject parameter + * is of the same type as "this" object instance. If not, an error + * is returned. This function permits copying an object by value + * in a virtual way which therefore is different to just calling the + * assignment operator of DcmElement which could result in slicing + * the object. + * @param rhs - [in] The instance to copy from. Has to be of the same + * class type as "this" object + * @return EC_Normal if copying was successful, error otherwise + */ + virtual OFCondition copyFrom(const DcmObject& rhs); + + /** get type identifier + * @return type identifier of this class (EVR_item) + */ + virtual DcmEVR ident() const; + + /** get value multiplicity + * @return always returns 1 (according to the DICOM standard) + */ + virtual unsigned long getVM(); + + /** get cardinality of this item + * @return number of elements in this item + */ + virtual unsigned long card() const; + + /** check if this element is a leaf node in a dataset tree. + * All subclasses of DcmElement except for DcmSequenceOfItems + * are leaf nodes, while DcmSequenceOfItems, DcmItem, DcmDataset etc. + * are not. + * @return true if leaf node, false otherwise. + */ + virtual OFBool isLeaf() const { return OFFalse; } + + /** check if this item is nested in a sequence of items, i.e.\ not a + * top-level or stand-alone item/dataset + * @return true if this item is nested, false otherwise + */ + virtual OFBool isNested() const; + + /** print all elements of the item to a stream + * @param out output stream + * @param flags optional flag used to customize the output (see DCMTypes::PF_xxx) + * @param level current level of nested items. Used for indentation. + * @param pixelFileName not used + * @param pixelCounter not used + */ + virtual void print(STD_NAMESPACE ostream&out, + const size_t flags = 0, + const int level = 0, + const char *pixelFileName = NULL, + size_t *pixelCounter = NULL); + + /** calculate the length of this DICOM element when encoded with the + * given transfer syntax and the given encoding type for sequences. + * For elements, the length includes the length of the tag, length field, + * VR field and the value itself, for items and sequences it returns + * the length of the complete item or sequence including delimitation tags + * if applicable. + * If length encodig is set to be explicit and the total item size is + * larger than the available 32-bit length field, then undefined length + * is returned. If "dcmWriteOversizedSeqsAndItemsImplicit" is disabled, + * also the internal DcmObject errorFlag is set to EC_SeqOrItemContentOverflow + * in case the item content (excluding tag header etc.) is already too + * large. + * @param xfer transfer syntax for length calculation + * @param enctype sequence encoding type for length calculation + * @return length of DICOM element + */ + virtual Uint32 calcElementLength(const E_TransferSyntax xfer, + const E_EncodingType enctype); + + /** calculate the value length (without attribute tag, VR and length field) + * of this DICOM element when encoded with the given transfer syntax and + * the given encoding type for sequences. + * If length encodig is set to be explicit and the item content is larger + * than the available 32-bit length field, then undefined length is + * returned. If "dcmWriteOversizedSeqsAndItemsUndefined" is disabled, + * also the internal DcmObject errorFlag is set to + * EC_SeqOrItemContentOverflow. + * @param xfer transfer syntax for length calculation + * @param enctype sequence encoding type for length calculation + * @return value length of DICOM element + */ + virtual Uint32 getLength(const E_TransferSyntax xfer = EXS_LittleEndianImplicit, + const E_EncodingType enctype = EET_UndefinedLength); + + /** initialize the transfer state of this object. This method must be called + * before this object is written to a stream or read (parsed) from a stream. + */ + virtual void transferInit(); + + /** finalize the transfer state of this object. This method must be called + * when reading/writing this object from/to a stream has been completed. + */ + virtual void transferEnd(); + + /** get parent item of this object, i.e.\ the item/dataset in which the + * surrounding sequence element is stored. + * @return pointer to the parent item of this object (might be NULL) + */ + virtual DcmItem *getParentItem(); + + /** check if this DICOM object can be encoded in the given transfer syntax. + * @param newXfer transfer syntax in which the DICOM object is to be encoded + * @param oldXfer transfer syntax in which the DICOM object was read or created. + * @return true if object can be encoded in desired transfer syntax, false otherwise. + */ + virtual OFBool canWriteXfer(const E_TransferSyntax newXfer, + const E_TransferSyntax oldXfer); + + /** This function reads the information of all attributes which + * are captured in the input stream and captures this information + * in elementList. Each attribute is represented as an element + * in this list. If not all information for an attribute could be + * read from the stream, the function returns EC_StreamNotifyClient. + * @param inStream The stream which contains the information. + * @param ixfer The transfer syntax which was used to encode + * the information in inStream. + * @param glenc Encoding type for group length; specifies + * what will be done with group length tags. + * @param maxReadLength Maximum read length for reading an attribute value. + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition read(DcmInputStream &inStream, + const E_TransferSyntax ixfer, + const E_GrpLenEncoding glenc = EGL_noChange, + const Uint32 maxReadLength = DCM_MaxReadLength); + + /** write object to a stream + * @param outStream DICOM output stream + * @param oxfer output transfer syntax + * @param enctype encoding types (undefined or explicit length) + * @param wcache pointer to write cache object, may be NULL + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition write(DcmOutputStream &outStream, + const E_TransferSyntax oxfer, + const E_EncodingType enctype, + DcmWriteCache *wcache); + + /** write object in XML format + * @param out output stream to which the XML document is written + * @param flags optional flag used to customize the output (see DCMTypes::XF_xxx) + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition writeXML(STD_NAMESPACE ostream&out, + const size_t flags = 0); + + /** special write method for creation of digital signatures + * @param outStream DICOM output stream + * @param oxfer output transfer syntax + * @param enctype encoding types (undefined or explicit length) + * @param wcache pointer to write cache object, may be NULL + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition writeSignatureFormat(DcmOutputStream &outStream, + const E_TransferSyntax oxfer, + const E_EncodingType enctype, + DcmWriteCache *wcache); + + /** returns true if the object contains an element with Unknown VR at any nesting level + * @return true if the object contains an element with Unknown VR, false otherwise + */ + virtual OFBool containsUnknownVR() const; + + /** check if this object contains non-ASCII characters at any nesting level. Please note + * that this check is pretty simple and only works for single-byte character sets that + * do include the 7-bit ASCII codes, e.g. for the ISO 8859 family. In other words: All + * character codes below 128 are considered to be ASCII codes and all others are + * considered to be non-ASCII. + * @param checkAllStrings if true, also check elements with string values not affected + * by SpecificCharacterSet (0008,0005), default: only check PN, LO, LT, SH, ST, UC + * and UT + * @return true if object contains non-ASCII characters, false otherwise + */ + virtual OFBool containsExtendedCharacters(const OFBool checkAllStrings = OFFalse); + + /** check if this object is affected by SpecificCharacterSet at any nesting level. + * In detail, it is checked whether this object contains any data elements that + * according to their VR are affected by the SpecificCharacterSet (0008,0005) + * element. This is true for the following VRs: PN, LO, LT, SH, ST, UC and UT + * @return true if object is affected by SpecificCharacterSet, false otherwise + */ + virtual OFBool isAffectedBySpecificCharacterSet() const; + + /** mode specifying whether the SpecificCharacterSet (0008,0005) element should be + * checked by convertCharacterSet() or not, i.e.\ whether this element might be + * present on this dataset-level. This method is reimplemented in derived classes. + * @return always returns OFFalse, i.e.\ SpecificCharacterSet should not be checked + */ + virtual OFBool checkForSpecificCharacterSet() const { return OFFalse; } + + /** convert all element values that are contained in this item and that are affected + * by SpecificCharacterSet from the given source character set to the given + * destination character set. The defined terms for a particular character set can + * be found in the DICOM standard, e.g. "ISO_IR 100" for ISO 8859-1 (Latin 1) or + * "ISO_IR 192" for Unicode in UTF-8. An empty string denotes the default character + * repertoire, which is ASCII (7-bit). If multiple values are given for 'fromCharset' + * (separated by a backslash) code extension techniques are used and escape sequences + * may be encountered in the source string to switch between the specified character + * sets. + * @param fromCharset name of the source character set(s) used for the conversion + * @param toCharset name of the destination character set used for the conversion. + * Only a single value is permitted (i.e. no code extensions). + * @param transliterate mode specifying whether a character that cannot be + * represented in the destination character encoding is approximated through one + * or more characters that look similar to the original one + * @param updateCharset if OFTrue, the SpecificCharacterSet (0008,0005) element is + * updated, i.e.\ the current value is either replaced or a new element is inserted + * or the existing element is deleted. If OFFalse the SpecificCharacterSet element + * remains unchanged. + * @param discardIllegal mode specifying whether characters that cannot be represented + * in the destination character encoding will be silently discarded + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition convertCharacterSet(const OFString &fromCharset, + const OFString &toCharset, + const OFBool transliterate = OFFalse, + const OFBool updateCharset = OFFalse, + const OFBool discardIllegal = OFFalse); + + /** convert all element values that are contained in this item and that are affected + * by SpecificCharacterSet to the given destination character set. If not disabled, + * the source character set is determined automatically from the value of the + * SpecificCharacterSet (0008,0005) element. The defined terms for the destination + * character set can be found in the DICOM standard, e.g. "ISO_IR 100" for ISO 8859-1 + * (Latin 1) or "ISO_IR 192" for Unicode in UTF-8. An empty string denotes the + * default character repertoire, which is ASCII (7-bit). + * @param toCharset name of the destination character set used for the conversion. + * Only a single value is permitted (i.e. no code extensions). + * @param transliterate mode specifying whether a character that cannot be + * represented in the destination character encoding is approximated through one + * or more characters that look similar to the original one + * @param ignoreCharset if OFTrue, the value of SpecificCharacterSet is ignored. + * Also see checkForSpecificCharacterSet(). + * @param discardIllegal mode specifying whether characters that cannot be represented + * in the destination character encoding will be silently discarded + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition convertCharacterSet(const OFString &toCharset, + const OFBool transliterate = OFFalse, + const OFBool ignoreCharset = OFFalse, + const OFBool discardIllegal = OFFalse); + + /** convert all element values that are contained in this item and that are affected + * by SpecificCharacterSet from the currently selected source character set to the + * currently selected destination character set + * @param converter character set converter to be used to convert the element values + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition convertCharacterSet(DcmSpecificCharacterSet &converter); + + /** convert all element values that are contained in this item and that are affected + * by SpecificCharacterSet to UTF-8 (Unicode). The value of the SpecificCharacterSet + * (0008,0005) element is updated, set or deleted automatically if needed. The + * transliteration mode is disabled - see convertCharacterSet(). + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition convertToUTF8(); + + /** insert a new element into the list of elements maintained by this item. + * The list of elements is always kept in ascending tag order. + * @param elem element to be inserted, must not be contained in this or + * any other item. Will be deleted upon destruction of this item object. + * @param replaceOld if true, this element replaces any other element with + * the same tag which may already be contained in the item. If false, + * insert fails if another element with the same tag is already present. + * @param checkInsertOrder if true, a warning message is sent to the console + * if the element is not inserted at the end of the list. This is used + * in the read() method to detect datasets with out-of-order elements. + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition insert(DcmElement *elem, + OFBool replaceOld = OFFalse, + OFBool checkInsertOrder = OFFalse); + + /** access an element from the item. This method returns a pointer to one + * of the elements in the item, and not a copy. + * @param num index number of element, must be < card() + * @return pointer to element if found, NULL if num >= card() + */ + virtual DcmElement *getElement(const unsigned long num); + + /** this method enables a stack based, depth-first traversal of a complete + * hierarchical DICOM dataset (that is, classes derived from DcmItem or + * DcmSequenceOfItems). With each call of this method, the next object + * in the tree is located and marked on the stack. + * @param stack "cursor" for current position in the dataset. The stack + * will contain a pointer to each dataset, sequence, item and element + * from the main dataset down to the current element, and is updated + * upon each call to this method. An empty stack is equivalent to a stack + * containing a pointer to this object only. + * @param intoSub if true, the nextObject method will perform a hierarchical + * search through the dataset (depth-first), if false, only the current + * container object will be traversed (e.g., all elements of an item + * or all items of a sequence). + * @return EC_Normal if value length is correct, an error code otherwise + */ + virtual OFCondition nextObject(DcmStack &stack, + const OFBool intoSub); + + /** this method is only used in container classes, + * that is, DcmItem and DcmSequenceOfItems. It returns a pointer to the + * next object in the list AFTER the given object. If the caller passes NULL, + * a pointer to the first object in the list is returned. If the given object + * is not found, the given object is the last one in the list or the list is empty, + * NULL is returned. + * @param obj pointer to one object in the container; we are looking for the + * next entry after this one. NULL if looking for the first entry. + * @return pointer to next object in container or NULL if not found + */ + virtual DcmObject *nextInContainer(const DcmObject *obj); + + /** remove element from list. If found, the element is not deleted but + * returned to the caller who is responsible for further management of the + * DcmElement object. + * @param num index number of element, must be < card() + * @return pointer to DcmElement if found, NULL otherwise + */ + virtual DcmElement *remove(const unsigned long num); + + /** remove element from list. If found, the element is not deleted but + * returned to the caller who is responsible for further management of the + * DcmElement object. + * @param elem pointer to element (as type DcmObject *) to be removed from list + * @return pointer to element (as type DcmElement *) if found, NULL otherwise + */ + virtual DcmElement *remove(DcmObject *elem); + + /** remove element from list. If found, the element is not deleted but + * returned to the caller who is responsible for further management of the + * DcmElement object. + * @param tag attribute tag of element to be removed + * @return pointer to DcmElement if found, NULL otherwise + */ + virtual DcmElement *remove(const DcmTagKey &tag); + + /** check if this item is empty + * @param normalize not used for this class + * @return true if item is empty, i.e.\ has no elements, false otherwise + */ + virtual OFBool isEmpty(const OFBool normalize = OFTrue); + + /** clear (remove) all attributes from item and delete them from memory. + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition clear(); + + /** check the currently stored element value + * @param autocorrect correct value length if OFTrue + * @return status, EC_Normal if value length is correct, an error code otherwise + */ + virtual OFCondition verify(const OFBool autocorrect = OFFalse ); + + /** a complex, stack-based, hierarchical search method. It allows for a search + * for a DICOM object with a given attribute within a given container, + * hierarchically, from a starting position identified through a cursor stack. + * @param xtag the DICOM attribute tag we are searching for + * @param resultStack Depending on the search mode (see below), this parameter + * either serves as an input and output parameter, or as an output parameter + * only (the latter being the default). When used as an input parameter, + * the cursor stack defines the start position for the search within a + * hierarchical DICOM dataset. Upon successful return, the stack contains + * the position of the element found, in the form of a pointer to each dataset, + * sequence, item and element from the main dataset down to the found element. + * @param mode search mode, controls how the search stack is handled. + * In the default mode, ESM_fromHere, the stack is ignored on input, and + * the search starts in the object for which this method is called. + * In the other modes, the stack is used both as an input and an output + * parameter and defines the starting point for the search. + * @param searchIntoSub if true, the search will be performed hierarchically descending + * into the sequences and items of the dataset. If false, only the current container + * (sequence or item) will be traversed. + * @return EC_Normal if found, EC_TagNotFound if not found, an error code is something + * went wrong. + */ + virtual OFCondition search(const DcmTagKey &xtag, // in + DcmStack &resultStack, // inout + E_SearchMode mode = ESM_fromHere, // in + OFBool searchIntoSub = OFTrue ); // in + + /** this method loads all attribute values maintained by this object and + * all sub-objects (in case of a container such as DcmDataset) into memory. + * After a call to this method, the file from which a dataset was read may safely + * be deleted or replaced. For large files, this method may obviously allocate large + * amounts of memory. + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition loadAllDataIntoMemory(); + + /** iterate over all elements and remove those element values from memory which exceed + * a given length and which can be loaded from file when needed again. For all other + * elements, nothing is done. + * @param maxLength maximum length (number of bytes) allowed without removing the value + */ + virtual void compactElements(const Uint32 maxLength); + + /** This function takes care of group length and padding elements + * in the current element list according to what is specified in + * glenc and padenc. If required, this function does the following + * two things: + * a) it calculates the group length of all groups which are + * contained in this item and sets the calculated values + * in the corresponding group length elements and + * b) it inserts a corresponding padding element (or, in case + * of sequences: padding elements) with a corresponding correct + * size into the element list. + * @param glenc Encoding type for group length; specifies what shall + * be done with group length tags. + * @param padenc Encoding type for padding; specifies what shall be + * done with padding tags. + * @param xfer The transfer syntax that shall be used. + * @param enctype Encoding type for sequences; specifies how sequences + * will be handled. + * @param padlen The length up to which the dataset shall be padded, + * if padding is desired. + * @param subPadlen For sequences (ie sub elements), the length up to + * which item shall be padded, if padding is desired. + * @param instanceLength Number of extra bytes added to the item/dataset + * length used when computing the padding; this + * parameter is for instance used to pass the length + * of the file meta header from the DcmFileFormat to + * the DcmDataset object. + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition computeGroupLengthAndPadding(const E_GrpLenEncoding glenc, + const E_PaddingEncoding padenc = EPD_noChange, + const E_TransferSyntax xfer = EXS_Unknown, + const E_EncodingType enctype = EET_ExplicitLength, + const Uint32 padlen = 0, + const Uint32 subPadlen = 0, + Uint32 instanceLength = 0); + + + /** check if an element with the given attribute tag exists in the dataset + * @param key tag key to be searched + * @param searchIntoSub if true, do hierarchical search within sequences, + * if false only search through this dataset + * @return true if tag found, false otherwise + */ + OFBool tagExists(const DcmTagKey &key, + OFBool searchIntoSub = OFFalse); + + /** check if an element with the given attribute tag exists in the dataset + * and has a non-empty value + * @param key tag key to be searched + * @param searchIntoSub if true, do hierarchical search within sequences, + * if false only search through this dataset + * @return true if tag found and element non-empty, false otherwise + */ + OFBool tagExistsWithValue(const DcmTagKey &key, + OFBool searchIntoSub = OFFalse); + + /* --- findAndGet functions: find an element and get it or the value, respectively --- */ + + /** find element and get a pointer to it (or copy it). + * Applicable to all DICOM value representations (VR). + * The result variable 'element' is automatically set to NULL if an error occurs. + * @param tagKey DICOM tag specifying the attribute to be searched for + * @param element variable in which the reference to (or copy of) the element is stored + * @param searchIntoSub flag indicating whether to search into sequences or not + * @param createCopy create a copy of the element if true, return a reference otherwise + * @return EC_Normal upon success, an error code otherwise. + */ + OFCondition findAndGetElement(const DcmTagKey &tagKey, + DcmElement *&element, + const OFBool searchIntoSub = OFFalse, + const OFBool createCopy = OFFalse); + + /** find all elements matching a particular tag and return references to them on a stack. + * This functions always performs a deep search (i.e. searches into sequence of items). + * @param tagKey DICOM tag specifying the attribute to be searched for + * @param resultStack stack where references to the elements are stored (added to). + * If no element is found, the stack is not modified (e.g. cleared). + * @return EC_Normal if at least one matching tag is found, an error code otherwise. + */ + OFCondition findAndGetElements(const DcmTagKey &tagKey, + DcmStack &resultStack); + + /** find element and get value as a reference to a C string. NB: The string is not copied! + * Applicable to the following VRs: AE, AS, CS, DA, DS, DT, IS, LO, LT, PN, SH, ST, TM, UC, UI, + * UR, UT + * Since the getString() routine is called internally the resulting string reference represents + * the (possibly multi-valued) value as stored in the dataset, i.e. no normalization is performed. + * The result variable 'value' is automatically set to NULL if an error occurs. + * @param tagKey DICOM tag specifying the attribute to be searched for + * @param value variable in which the reference to the element value is stored (might be NULL) + * @param searchIntoSub flag indicating whether to search into sequences or not + * @return EC_Normal upon success, an error code otherwise. + */ + OFCondition findAndGetString(const DcmTagKey &tagKey, + const char *&value, + const OFBool searchIntoSub = OFFalse); + + /** find element and get value as a reference to a C string. NB: The string is not copied! + * Applicable to the following VRs: AE, AS, CS, DA, DS, DT, IS, LO, LT, PN, SH, ST, TM, UC, UI, + * UR, UT + * Since the getString() routine is called internally the resulting string reference represents + * the (possibly multi-valued) value as stored in the dataset, i.e. no normalization is performed. + * The result variable 'value' is automatically set to NULL and 'length' is set to 0 if an error + * occurs. + * Please note that since the length is returned separately, the string value can contain more + * than one NULL byte. + * @param tagKey DICOM tag specifying the attribute to be searched for + * @param value variable in which the reference to the element value is stored (might be NULL) + * @param length length of the string (number of characters without the trailing NULL byte) + * @param searchIntoSub flag indicating whether to search into sequences or not + * @return EC_Normal upon success, an error code otherwise. + */ + OFCondition findAndGetString(const DcmTagKey &tagKey, + const char *&value, + Uint32 &length, + const OFBool searchIntoSub = OFFalse); + + /** find element and get value as a C++ string (only one component). + * Applicable to the following VRs: AE, AS, AT, CS, DA, DS, DT, FL, FD, IS, LO, LT, OB, OD, OF, + * OW, PN, SH, SL, SS, ST, TM, UC, UI, UL, UR, US, UT + * Since the getOFString() routine is called internally the resulting string is normalized, i.e. + * leading and/or trailing spaces are removed according to the associated value representation, + * or the element value is converted to a character string (for non-string VRs) - see documentation + * in the corresponding header file. + * In contrast to the above and below function only the specified component (see parameter 'pos') + * is returned. The result variable 'value' is automatically set to an empty string if an error + * occurs. + * @param tagKey DICOM tag specifying the attribute to be searched for + * @param value variable in which the element value is stored + * @param pos index of the value in case of multi-valued elements (0..vm-1) + * @param searchIntoSub flag indicating whether to search into sequences or not + * @return EC_Normal upon success, an error code otherwise. + */ + OFCondition findAndGetOFString(const DcmTagKey &tagKey, + OFString &value, + const unsigned long pos = 0, + const OFBool searchIntoSub = OFFalse); + + /** find element and get value as a C++ string (all components). + * Applicable to the following VRs: AE, AS, AT, CS, DA, DS, DT, FL, FD, IS, LO, LT, OB, OD, OF, + * OW, PN, SH, SL, SS, ST, TM, UC, UI, UL, UR, US, UT + * Since the getOFStringArray() routine is called internally the resulting string is normalized, + * i.e. leading and/or trailing spaces are removed according to the associated value representation + * or the element values are converted to character strings (for non-string VRs) - see documentation + * in the corresponding header file. + * The result variable 'value' is automatically set to an empty string if an error occurs. + * @param tagKey DICOM tag specifying the attribute to be searched for + * @param value variable in which the element value is stored + * @param searchIntoSub flag indicating whether to search into sequences or not + * @return EC_Normal upon success, an error code otherwise. + */ + OFCondition findAndGetOFStringArray(const DcmTagKey &tagKey, + OFString &value, + const OFBool searchIntoSub = OFFalse); + + /** find element and get value as an unsigned 8-bit integer. + * Applicable to the following VRs: OB + * The result variable 'value' is automatically set to zero if an error occurs. + * @param tagKey DICOM tag specifying the attribute to be searched for + * @param value variable in which the element value is stored + * @param pos index of the value in case of multi-valued elements (0..vm-1) + * @param searchIntoSub flag indicating whether to search into sequences or not + * @return EC_Normal upon success, an error code otherwise. + */ + OFCondition findAndGetUint8(const DcmTagKey &tagKey, + Uint8 &value, + const unsigned long pos = 0, + const OFBool searchIntoSub = OFFalse); + + /** find element and get value as an array of unsigned 8-bit integers. + * Applicable to the following VRs: OB + * The result variable 'value' is automatically set to NULL if an error occurs. + * @param tagKey DICOM tag specifying the attribute to be searched for + * @param value variable in which the reference to the element value is stored + * @param count stores number of items in the result array (if not NULL) + * @param searchIntoSub flag indicating whether to search into sequences or not + * @return EC_Normal upon success, an error code otherwise. + */ + OFCondition findAndGetUint8Array(const DcmTagKey &tagKey, + const Uint8 *&value, + unsigned long *count = NULL, + const OFBool searchIntoSub = OFFalse); + + /** find element and get value as an unsigned 16-bit integer. + * Applicable to the following VRs: OW, US + * The result variable 'value' is automatically set to zero if an error occurs. + * @param tagKey DICOM tag specifying the attribute to be searched for + * @param value variable in which the element value is stored + * @param pos index of the value in case of multi-valued elements (0..vm-1) + * @param searchIntoSub flag indicating whether to search into sequences or not + * @return EC_Normal upon success, an error code otherwise. + */ + OFCondition findAndGetUint16(const DcmTagKey &tagKey, + Uint16 &value, + const unsigned long pos = 0, + const OFBool searchIntoSub = OFFalse); + + /** find element and get value as an array of unsigned 16-bit integers. + * Applicable to the following VRs: AT, OW, US + * The result variable 'value' is automatically set to NULL if an error occurs. + * @param tagKey DICOM tag specifying the attribute to be searched for + * @param value variable in which the reference to the element value is stored + * @param count stores number of items in the result array (if not NULL) + * @param searchIntoSub flag indicating whether to search into sequences or not + * @return EC_Normal upon success, an error code otherwise. + */ + OFCondition findAndGetUint16Array(const DcmTagKey &tagKey, + const Uint16 *&value, + unsigned long *count = NULL, + const OFBool searchIntoSub = OFFalse); + + /** find element and get value as a signed 16-bit integer. + * Applicable to the following VRs: SS + * The result variable 'value' is automatically set to zero if an error occurs. + * @param tagKey DICOM tag specifying the attribute to be searched for + * @param value variable in which the element value is stored + * @param pos index of the value in case of multi-valued elements (0..vm-1) + * @param searchIntoSub flag indicating whether to search into sequences or not + * @return EC_Normal upon success, an error code otherwise. + */ + OFCondition findAndGetSint16(const DcmTagKey &tagKey, + Sint16 &value, + const unsigned long pos = 0, + const OFBool searchIntoSub = OFFalse); + + /** find element and get value as an array of signed 16-bit integers. + * Applicable to the following VRs: SS + * The result variable 'value' is automatically set to NULL if an error occurs. + * @param tagKey DICOM tag specifying the attribute to be searched for + * @param value variable in which the reference to the element value is stored + * @param count stores number of items in the result array (if not NULL) + * @param searchIntoSub flag indicating whether to search into sequences or not + * @return EC_Normal upon success, an error code otherwise. + */ + OFCondition findAndGetSint16Array(const DcmTagKey &tagKey, + const Sint16 *&value, + unsigned long *count = NULL, + const OFBool searchIntoSub = OFFalse); + + /** find element and get value as an unsigned 32-bit integer. + * Applicable to the following VRs: UL + * The result variable 'value' is automatically set to zero if an error occurs. + * @param tagKey DICOM tag specifying the attribute to be searched for + * @param value variable in which the element value is stored + * @param pos index of the value in case of multi-valued elements (0..vm-1) + * @param searchIntoSub flag indicating whether to search into sequences or not + * @return EC_Normal upon success, an error code otherwise. + */ + OFCondition findAndGetUint32(const DcmTagKey &tagKey, + Uint32 &value, + const unsigned long pos = 0, + const OFBool searchIntoSub = OFFalse); + + /** find element and get value as an array of unsigned 32-bit integers. + * Applicable to the following VRs: UL + * The result variable 'value' is automatically set to NULL if an error occurs. + * @param tagKey DICOM tag specifying the attribute to be searched for + * @param value variable in which the reference to the element value is stored + * @param count stores number of items in the result array (if not NULL) + * @param searchIntoSub flag indicating whether to search into sequences or not + * @return EC_Normal upon success, an error code otherwise. + */ + OFCondition findAndGetUint32Array(const DcmTagKey &tagKey, + const Uint32 *&value, + unsigned long *count = NULL, + const OFBool searchIntoSub = OFFalse); + + /** find element and get value as a signed 32-bit integer. + * Applicable to the following VRs: IS, SL + * The result variable 'value' is automatically set to zero if an error occurs. + * @param tagKey DICOM tag specifying the attribute to be searched for + * @param value variable in which the element value is stored + * @param pos index of the value in case of multi-valued elements (0..vm-1) + * @param searchIntoSub flag indicating whether to search into sequences or not + * @return EC_Normal upon success, an error code otherwise. + */ + OFCondition findAndGetSint32(const DcmTagKey &tagKey, + Sint32 &value, + const unsigned long pos = 0, + const OFBool searchIntoSub = OFFalse); + + /** find element and get value as an array of signed 32-bit integers. + * Applicable to the following VRs: SL + * The result variable 'value' is automatically set to NULL if an error occurs. + * @param tagKey DICOM tag specifying the attribute to be searched for + * @param value variable in which the reference to the element value is stored + * @param count stores number of items in the result array (if not NULL) + * @param searchIntoSub flag indicating whether to search into sequences or not + * @return EC_Normal upon success, an error code otherwise. + */ + OFCondition findAndGetSint32Array(const DcmTagKey &tagKey, + const Sint32 *&value, + unsigned long *count = NULL, + const OFBool searchIntoSub = OFFalse); + + /** find element and get value as a (signed) long integer. + * Applicable to the following VRs: IS, SL, SS, UL, US + * The result variable 'value' is automatically set to zero if an error occurs. + * @param tagKey DICOM tag specifying the attribute to be searched for + * @param value variable in which the element value is stored + * @param pos index of the value in case of multi-valued elements (0..vm-1) + * @param searchIntoSub flag indicating whether to search into sequences or not + * @return EC_Normal upon success, an error code otherwise. + */ + OFCondition findAndGetLongInt(const DcmTagKey &tagKey, + long int &value, + const unsigned long pos = 0, + const OFBool searchIntoSub = OFFalse); + + /** find element and get value as a 32-bit floating point. + * Applicable to the following VRs: FL, OF + * The result variable 'value' is automatically set to zero if an error occurs. + * @param tagKey DICOM tag specifying the attribute to be searched for + * @param value variable in which the element value is stored + * @param pos index of the value in case of multi-valued elements (0..vm-1) + * @param searchIntoSub flag indicating whether to search into sequences or not + * @return EC_Normal upon success, an error code otherwise. + */ + OFCondition findAndGetFloat32(const DcmTagKey &tagKey, + Float32 &value, + const unsigned long pos = 0, + const OFBool searchIntoSub = OFFalse); + + /** find element and get value as an array of 32-bit floating point values. + * Applicable to the following VRs: FL, OF + * The result variable 'value' is automatically set to NULL if an error occurs. + * @param tagKey DICOM tag specifying the attribute to be searched for + * @param value variable in which the reference to the element value is stored + * @param count stores number of items in the result array (if not NULL) + * @param searchIntoSub flag indicating whether to search into sequences or not + * @return EC_Normal upon success, an error code otherwise. + */ + OFCondition findAndGetFloat32Array(const DcmTagKey &tagKey, + const Float32 *&value, + unsigned long *count = NULL, + const OFBool searchIntoSub = OFFalse); + + /** find element and get value as a 64-bit floating point. + * Applicable to the following VRs: DS, FD, OD + * The result variable 'value' is automatically set to zero if an error occurs. + * @param tagKey DICOM tag specifying the attribute to be searched for + * @param value variable in which the element value is stored + * @param pos index of the value in case of multi-valued elements (0..vm-1) + * @param searchIntoSub flag indicating whether to search into sequences or not + * @return EC_Normal upon success, an error code otherwise. + */ + OFCondition findAndGetFloat64(const DcmTagKey &tagKey, + Float64 &value, + const unsigned long pos = 0, + const OFBool searchIntoSub = OFFalse); + + /** find element and get value as an array of 64-bit floating point values. + * Applicable to the following VRs: FD, OD + * The result variable 'value' is automatically set to NULL if an error occurs. + * @param tagKey DICOM tag specifying the attribute to be searched for + * @param value variable in which the reference to the element value is stored + * @param count stores number of items in the result array (if not NULL) + * @param searchIntoSub flag indicating whether to search into sequences or not + * @return EC_Normal upon success, an error code otherwise. + */ + OFCondition findAndGetFloat64Array(const DcmTagKey &tagKey, + const Float64 *&value, + unsigned long *count = NULL, + const OFBool searchIntoSub = OFFalse); + + /** looks up and returns a given sequence. + * Applicable to the following VRs: SQ, (pixelSQ) + * The result variable 'sequence' is automatically set to NULL if an error occurs + * (e.g. if 'seqTagKey' does not refer to a sequence attribute). + * @param seqTagKey DICOM tag specifying the sequence attribute to be searched for + * @param sequence variable in which the reference to (or copy of) the sequence is stored + * @param searchIntoSub flag indicating whether to search into sub-sequences or not + * @param createCopy create a copy of the sequence if true, return a reference otherwise + * @return EC_Normal upon success, an error otherwise. + */ + OFCondition findAndGetSequence(const DcmTagKey &seqTagKey, + DcmSequenceOfItems *&sequence, + const OFBool searchIntoSub = OFFalse, + const OFBool createCopy = OFFalse); + + /** looks up and returns a given sequence item, if it exists. Otherwise sets 'item' + * to NULL and returns EC_TagNotFound (specified sequence does not exist) or + * EC_IllegalParameter (specified item does not exist). Only the top-most level of + * the dataset/item is examined (i.e. no deep-search is performed). + * Applicable to the following VRs: SQ, (pixelSQ) + * @param seqTagKey DICOM tag specifying the sequence attribute to be searched for + * @param item variable in which the reference to (or copy of) the item is stored + * @param itemNum number of the item to be searched for (0..n-1, -1 for last) + * @param createCopy create a copy of the item if true, return a reference otherwise + * @return EC_Normal upon success, an error otherwise. + */ + OFCondition findAndGetSequenceItem(const DcmTagKey &seqTagKey, + DcmItem *&item, + const signed long itemNum = 0, + const OFBool createCopy = OFFalse); + + + /* --- findOrCreate functions: find an element or create a new one --- */ + + /** looks up the given sequence in the current dataset and returns the given item. + * If either the sequence or the item do not exist, they are created. If necessary, + * multiple empty items are inserted. Only the top-most level of the dataset/item + * is examined (i.e. no deep-search is performed). + * Applicable to the following VRs: SQ, (pixelSQ) + * @param seqTag DICOM tag specifying the sequence attribute to be searched for + * (or to be created) + * @param item variable in which the reference to the sequence item is stored + * @param itemNum number of the item to be searched for (0..n-1, -1 for last, + * -2 for append new) + * @return EC_Normal upon success, an error otherwise. + */ + OFCondition findOrCreateSequenceItem(const DcmTag &seqTag, + DcmItem *&item, + const signed long itemNum = 0); + + /* --- findAndXXX functions: find an element and do something with it --- */ + + /** find element, create a copy and insert it into the given destination dataset. + * This functions never performs a deep search (i.e. does not search into sequence + * of items). Empty elements are also copied. However, if the given tag is not + * found in the current dataset, EC_TagNotFound is returned and the destination + * dataset remains unchanged. + * Applicable to all DICOM value representations (VR). + * @param tagKey DICOM tag specifying the attribute to be searched for + * @param destItem destination dataset to which the copied element is inserted + * @param replaceOld flag indicating whether to replace an existing element or not + * @return EC_Normal upon success, an error code otherwise + */ + OFCondition findAndInsertCopyOfElement(const DcmTagKey &tagKey, + DcmItem *destItem, + const OFBool replaceOld = OFTrue); + + /** find element, remove it from the dataset and free the associated memory. + * Applicable to all DICOM value representations (VR). + * @param tagKey DICOM tag specifying the attribute to be searched for + * @param allOccurrences flag indicating whether to delete all occurrences of the + * attribute tag or the first one only (implies 'searchIntoSub' to be true) + * @param searchIntoSub flag indicating whether to search into sequences or not + * @return EC_Normal upon success, an error code otherwise. + */ + OFCondition findAndDeleteElement(const DcmTagKey &tagKey, + const OFBool allOccurrences = OFFalse, + const OFBool searchIntoSub = OFFalse); + + /** looks up the given sequence in the current dataset and deletes the given item. + * Applicable to the following VRs: SQ, (pixelSQ) + * @param seqTagKey DICOM tag specifying the sequence attribute to be searched for + * @param itemNum number of the item to be deleted (0..n-1, -1 for last) + * @return EC_Normal upon success, an error otherwise. + */ + OFCondition findAndDeleteSequenceItem(const DcmTagKey &seqTagKey, + const signed long itemNum); + + + /* --- putAndInsert functions: put value and insert new element --- */ + + /** create a new element, put specified value to it and insert the element into the dataset/item. + * Applicable to the following VRs: AE, AS, AT, CS, DA, DS, DT, FL, FD, IS, LO, LT, OB, OD, OF, + * OW, PN, SH, SL, SS, ST, TM, UC, UI, UL, UR, US, UT + * @param tag DICOM tag specifying the attribute to be created + * @param value string value to be set for the new element (might be empty or NULL) + * @param replaceOld flag indicating whether to replace an existing element or not + * @return EC_Normal upon success, an error code otherwise. + */ + OFCondition putAndInsertString(const DcmTag &tag, + const char *value, + const OFBool replaceOld = OFTrue); + + /** create a new element, put specified value to it and insert the element into the dataset/item. + * Applicable to the following VRs: AE, AS, AT, CS, DA, DS, DT, FL, FD, IS, LO, LT, OB, OD, OF, + * OW, PN, SH, SL, SS, ST, TM, UC, UI, UL, UR, US, UT + * Please note that since the length of the string has to be specified explicitly, the string + * can contain more than one NULL byte. + * @param tag DICOM tag specifying the attribute to be created + * @param value string value to be set for the new element (might be empty or NULL) + * @param length length of the string (number of characters without the trailing NULL byte) + * @param replaceOld flag indicating whether to replace an existing element or not + * @return EC_Normal upon success, an error code otherwise. + */ + OFCondition putAndInsertString(const DcmTag &tag, + const char *value, + const Uint32 length, + const OFBool replaceOld = OFTrue); + + /** create a new element, put specified value to it and insert the element into the dataset/item. + * Applicable to the following VRs: AE, AS, CS, DA, DS, DT, IS, LO, LT, PN, SH, ST, TM, UC, UI, + * UR, UT + * @param tag DICOM tag specifying the attribute to be created + * @param value value to be set for the new element (might be empty) + * @param replaceOld flag indicating whether to replace an existing element or not + * @return EC_Normal upon success, an error code otherwise. + */ + OFCondition putAndInsertOFStringArray(const DcmTag &tag, + const OFString &value, + const OFBool replaceOld = OFTrue); + + /** create a new element, put specified value to it and insert the element into the dataset/item. + * Applicable to the following VRs: OB, ox (polymorph OB/OW or pixel data) + * @param tag DICOM tag specifying the attribute to be created + * @param value value to be set for the new element (might be NULL) + * @param count number of values (= bytes in this case) to be copied from 'value' + * @param replaceOld flag indicating whether to replace an existing element or not + * @return EC_Normal upon success, an error code otherwise. + */ + OFCondition putAndInsertUint8Array(const DcmTag &tag, + const Uint8 *value, + const unsigned long count, + const OFBool replaceOld = OFTrue); + + /** create a new element, put specified value to it and insert the element into the dataset/item. + * Applicable to the following VRs: US, xs (US or SS) + * @param tag DICOM tag specifying the attribute to be created + * @param value value to be set for the new element + * @param pos index of the value to be set (0..vm). A value can be appended to + * the end of or inserted within the existing value field. + * @param replaceOld flag indicating whether to replace an existing element or not + * @return EC_Normal upon success, an error code otherwise. + */ + OFCondition putAndInsertUint16(const DcmTag &tag, + const Uint16 value, + const unsigned long pos = 0, + const OFBool replaceOld = OFTrue); + + /** create a new element, put specified value to it and insert the element into the dataset/item. + * Applicable to the following VRs: AT, OW, US, ox (polymorph OB/OW or pixel data), xs (US or SS) + * @param tag DICOM tag specifying the attribute to be created + * @param value value to be set for the new element (might be NULL) + * @param count number of values (not bytes!) to be copied from 'value' + * @param replaceOld flag indicating whether to replace an existing element or not + * @return EC_Normal upon success, an error code otherwise. + */ + OFCondition putAndInsertUint16Array(const DcmTag &tag, + const Uint16 *value, + const unsigned long count, + const OFBool replaceOld = OFTrue); + + /** create a new element, put specified value to it and insert the element into the dataset/item. + * Applicable to the following VRs: SS, xs (US or SS) + * @param tag DICOM tag specifying the attribute to be created + * @param value value to be set for the new element + * @param pos index of the value to be set (0..vm). A value can be appended to + * the end of or inserted within the existing value field. + * @param replaceOld flag indicating whether to replace an existing element or not + * @return EC_Normal upon success, an error code otherwise. + */ + OFCondition putAndInsertSint16(const DcmTag &tag, + const Sint16 value, + const unsigned long pos = 0, + const OFBool replaceOld = OFTrue); + + /** create a new element, put specified value to it and insert the element into the dataset/item. + * Applicable to the following VRs: SS, xs (US or SS) + * @param tag DICOM tag specifying the attribute to be created + * @param value value to be set for the new element + * @param count number of values (not bytes!) to be copied from 'value' + * @param replaceOld flag indicating whether to replace an existing element or not + * @return EC_Normal upon success, an error code otherwise. + */ + OFCondition putAndInsertSint16Array(const DcmTag &tag, + const Sint16 *value, + const unsigned long count, + const OFBool replaceOld = OFTrue); + + /** create a new element, put specified value to it and insert the element into the dataset/item. + * Applicable to the following VRs: UL + * @param tag DICOM tag specifying the attribute to be created + * @param value value to be set for the new element + * @param pos index of the value to be set (0..vm). A value can be appended to + * the end of or inserted within the existing value field. + * @param replaceOld flag indicating whether to replace an existing element or not + * @return EC_Normal upon success, an error code otherwise. + */ + OFCondition putAndInsertUint32(const DcmTag &tag, + const Uint32 value, + const unsigned long pos = 0, + const OFBool replaceOld = OFTrue); + + /** create a new element, put specified value to it and insert the element into the dataset/item. + * Applicable to the following VRs: SL + * @param tag DICOM tag specifying the attribute to be created + * @param value value to be set for the new element + * @param pos index of the value to be set (0..vm). A value can be appended to + * the end of or inserted within the existing value field. + * @param replaceOld flag indicating whether to replace an existing element or not + * @return EC_Normal upon success, an error code otherwise. + */ + OFCondition putAndInsertSint32(const DcmTag &tag, + const Sint32 value, + const unsigned long pos = 0, + const OFBool replaceOld = OFTrue); + + /** create a new element, put specified value to it and insert the element into the dataset/item. + * Applicable to the following VRs: FL, OF + * @param tag DICOM tag specifying the attribute to be created + * @param value value to be set for the new element + * @param pos index of the value to be set (0..vm). A value can be appended to + * the end of or inserted within the existing value field. + * @param replaceOld flag indicating whether to replace an existing element or not + * @return EC_Normal upon success, an error code otherwise. + */ + OFCondition putAndInsertFloat32(const DcmTag &tag, + const Float32 value, + const unsigned long pos = 0, + const OFBool replaceOld = OFTrue); + + /** create a new element, put specified value to it and insert the element into the dataset/item. + * Applicable to the following VRs: FL, OF + * @param tag DICOM tag specifying the attribute to be created + * @param value value to be set for the new element + * @param count number of values (not bytes!) to be copied from 'value' + * @param replaceOld flag indicating whether to replace an existing element or not + * @return EC_Normal upon success, an error code otherwise. + */ + OFCondition putAndInsertFloat32Array(const DcmTag &tag, + const Float32 *value, + const unsigned long count, + const OFBool replaceOld = OFTrue); + + /** create a new element, put specified value to it and insert the element into the dataset/item. + * Applicable to the following VRs: FD, OD + * @param tag DICOM tag specifying the attribute to be created + * @param value value to be set for the new element + * @param pos index of the value to be set (0..vm). A value can be appended to + * the end of or inserted within the existing value field. + * @param replaceOld flag indicating whether to replace an existing element or not + * @return EC_Normal upon success, an error code otherwise. + */ + OFCondition putAndInsertFloat64(const DcmTag &tag, + const Float64 value, + const unsigned long pos = 0, + const OFBool replaceOld = OFTrue); + + /** create a new element, put specified value to it and insert the element into the dataset/item. + * Applicable to the following VRs: FD, OD + * @param tag DICOM tag specifying the attribute to be created + * @param value value to be set for the new element + * @param count number of values (not bytes!) to be copied from 'value' + * @param replaceOld flag indicating whether to replace an existing element or not + * @return EC_Normal upon success, an error code otherwise. + */ + OFCondition putAndInsertFloat64Array(const DcmTag &tag, + const Float64 *value, + const unsigned long count, + const OFBool replaceOld = OFTrue); + + /** create a new element, put specified value to it and insert the element into the dataset/item. + * Applicable to the following VRs: AT + * @param tag DICOM tag specifying the attribute to be created + * @param value value to be set for the new element + * @param pos index of the value to be set (0..vm). A value can be appended to + * the end of or inserted within the existing value field. + * @param replaceOld flag indicating whether to replace an existing element or not + * @return EC_Normal upon success, an error code otherwise. + */ + OFCondition putAndInsertTagKey(const DcmTag &tag, + const DcmTagKey &value, + const unsigned long pos = 0, + const OFBool replaceOld = OFTrue); + + /* --- insertXXX functions: insert new element --- */ + + /** create a new element (with no value) and insert it into the dataset/item. + * Applicable to the following VRs: AE, AS, AT, CS, DA, DS, DT, FL, FD, IS, LO, LT, OB, OD, OF, + * OW, PN, SH, SL, SQ, SS, ST, TM, UC, UI, UL, UR, US, UT + * @param tag DICOM tag specifying the attribute to be created + * @param replaceOld flag indicating whether to replace an existing element or not + * @return EC_Normal upon success, an error code otherwise. + */ + OFCondition insertEmptyElement(const DcmTag &tag, + const OFBool replaceOld = OFTrue); + + /** looks up the given sequence in the current dataset and inserts the given item. + * If the sequence does not exist, it is created. If necessary, multiple empty items + * are inserted before the specified item position. Only the top-most level of the + * dataset/item is examined (i.e. no deep-search is performed). + * Applicable to the following VRs: SQ, (pixelSQ) + * @param seqTag DICOM tag specifying the sequence attribute to be searched for + * (or to be created) + * @param item item to be inserted into the sequence, must not be contained in this + * or any other sequence. Will be deleted upon destruction of the sequence object. + * @param itemNum position of the item (0..n-1, -1 = before last, -2 = after last) + * @return EC_Normal upon success, an error otherwise (delete 'item' manually!). + */ + OFCondition insertSequenceItem(const DcmTag &seqTag, + DcmItem *item, + const signed long itemNum = -2); + + protected: + + /// the list of elements maintained by this object + DcmList *elementList; + + /** flag used during suspended I/O. Indicates whether the last element + * was completely or only partially read/written during the last call + * to read/write. + */ + OFBool lastElementComplete; + + /** used during reading. Contains the position in the stream where + * the item started (needed for calculating the remaining number of + * bytes available for a fixed-length item). + */ + offile_off_t fStartPosition; + + protected: + + /** This function reads tag and length information from inStream and + * returns this information to the caller. When reading information, + * the transfer syntax which was passed is accounted for. If the + * transfer syntax shows an explicit value representation, the data + * type of this object is also read from the stream. In general, this + * function follows the rules which are specified in the DICOM standard + * (see DICOM standard (year 2000) part 5, section 7) (or the corresponding + * section in a later version of the standard) concerning the encoding + * of a dataset. + * @param inStream The stream which contains the information. + * @param xfer The transfer syntax which was used to encode the + * information in inStream. + * @param tag Contains in the end the tag that was read. + * @param length Contains in the end the length value that was read. + * @param bytesRead Contains in the end the amount of bytes which were + * read from inStream. + * @return status, EC_Normal if successful, an error code otherwise + */ + OFCondition readTagAndLength(DcmInputStream &inStream, // inout + const E_TransferSyntax xfer, // in + DcmTag &tag, // out + Uint32 &length, // out + Uint32 &bytesRead); // out + + /** This function creates a new DcmElement object on the basis of the newTag + * and newLength information which was passed, inserts this new element into + * elementList, reads the actual data value which belongs to this element + * (attribute) from the inStream and also assigns this information to the + * object which was created at the beginning. + * @param inStream The stream which contains the information. + * @param newTag The tag of the element of which the information is + * being read. + * @param newLength The length of the information which is being read. + * @param xfer The transfer syntax which was used to encode the + * information in inStream. + * @param glenc Encoding type for group length. Specifies what will + * be done with group length tags. + * @param maxReadLength Maximum read length for reading the attribute value. + * @return status, EC_Normal if successful, an error code otherwise + */ + OFCondition readSubElement(DcmInputStream &inStream, // inout + DcmTag &newTag, // inout + const Uint32 newLength, // in + const E_TransferSyntax xfer, // in + const E_GrpLenEncoding glenc, // in + const Uint32 maxReadLength = DCM_MaxReadLength); + + /** This function reads the first 6 bytes from the input stream and determines + * the transfer syntax which was used to code the information in the stream. + * The decision is based on two questions: a) Did we encounter a valid tag? + * and b) Do the last 2 bytes which were read from the stream represent a valid + * VR? In certain special cases, where the transfer syntax cannot be determined + * without doubt, we want to guess the most likely transfer syntax (see code). + * @param inStream The stream which contains the coded information. + * @return The transfer syntax which was determined. + */ + E_TransferSyntax checkTransferSyntax(DcmInputStream &inStream); + + /** check whether the given tag requires some special handling regarding the VR + * (i.e.\ in case it is undefined and multiple values are possible). If required, + * the VR of the given element tag is then updated according to the DICOM + * standard, e.g. the VR of PixelPaddingValue (if undefined) is set to 'SS' or + * 'US' depending on the value of PixelRepresentation. + * @param item dataset or item that can be used to lookup other element values + * @param tag tag of the element to be checked and updated (if required) + */ + void checkAndUpdateVR(DcmItem &item, + DcmTag &tag); + + /** update the SpecificCharacterSet (0008,0005) element depending on the given + * parameters. The current value of this element is either replaced or a new + * element is inserted or the existing element is deleted. + * @param status error status of previous operations (might also be updated) + * @param converter character set converter used to convert element values + */ + void updateSpecificCharacterSet(OFCondition &status, + const DcmSpecificCharacterSet &converter); + + + private: + + /** helper function for search(). May only be called if elementList is non-empty. + * Performs hierarchical search for given tag and pushes pointer of sub-element + * on result stack if found + * @param tag tag key to be searched + * @param resultStack upon successful return, pointer to element pushed onto this stack + * @param searchIntoSub flag indicating whether recursive search is desired + * @return EC_Normal if tag found and stack modified, EC_TagNotFound if tag not found + * and stack unmodified + */ + OFCondition searchSubFromHere(const DcmTagKey &tag, // in + DcmStack &resultStack, // inout + OFBool searchIntoSub ); // in + + /** helper function that interprets the given pointer as a pointer to an + * array of two characters and checks whether these two characters form + * a valid standard DICOM VR. + * @param atposition pointer to array of (at least) two bytes interpreted as VR + * @return true if standard VR, false otherwise + */ + static OFBool foundVR(const Uint8* atposition); + + /// cache for private creator tags and names + DcmPrivateTagCache privateCreatorCache; +}; + +// +// SUPPORT FUNCTIONS +// + +/** helper function for DICOM parser. Creates new DICOM element from given attribute tag + * @param newElement pointer to newly created element returned in this parameter upon success, + * NULL pointer otherwise + * @param tag attribute tag of the element to be created + * @param length attribute value length of the element to be created + * @param privateCreatorCache cache object for private creator strings in the current dataset + * @param readAsUN flag indicating whether parser is currently handling a UN element that + * must be read in implicit VR little endian; updated upon return + * @return EC_Normal upon success, an error code otherwise + */ +DCMTK_DCMDATA_EXPORT OFCondition newDicomElement(DcmElement *&newElement, + DcmTag &tag, + const Uint32 length, + DcmPrivateTagCache *privateCreatorCache, + OFBool& readAsUN); + +/** helper function for DICOM parser. Creates new DICOM element from given attribute tag + * @param newElement pointer to newly created element returned in this parameter upon success, + * NULL pointer otherwise + * @param tag attribute tag of the element to be created + * @param length attribute value length of the element to be created + * @return EC_Normal upon success, an error code otherwise + */ +DCMTK_DCMDATA_EXPORT OFCondition newDicomElement(DcmElement *&newElement, + const DcmTag &tag, + const Uint32 length = 0); + +/** helper function for DICOM parser. Creates new DICOM element from given attribute tag + * @param tag attribute tag of the element to be created + * @param length attribute value length of the element to be created + * @return pointer to newly created element returned in this parameter upon success, + * NULL pointer otherwise + */ +DCMTK_DCMDATA_EXPORT DcmElement *newDicomElement(const DcmTag &tag, + const Uint32 length = 0); + +/** helper function for DcmElement::nextObject. + * hierarchically traverses all datasets/items after the position indicated by the call stack + * @param st stack + * @return EC_Normal upon success, an error code otherwise + */ +DCMTK_DCMDATA_EXPORT OFCondition nextUp(DcmStack &st); + + +#endif // DCITEM_H diff --git a/dcmdata/include/dcmtk/dcmdata/dclist.h b/dcmdata/include/dcmtk/dcmdata/dclist.h new file mode 100644 index 00000000..78329af3 --- /dev/null +++ b/dcmdata/include/dcmtk/dcmdata/dclist.h @@ -0,0 +1,187 @@ +/* + * + * Copyright (C) 1994-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Gerd Ehlers + * + * Purpose: generic list class + * + */ + +#ifndef DCLIST_H +#define DCLIST_H + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/ofstd/ofcast.h" +#include "dcmtk/ofstd/oftypes.h" + +#define INCLUDE_CSTDDEF +#define INCLUDE_CSTDLIB +#include "dcmtk/ofstd/ofstdinc.h" +#include "dcmtk/dcmdata/dcobject.h" + +/// index indicating "end of list" +const unsigned long DCM_EndOfListIndex = OFstatic_cast(unsigned long, -1L); + +/** helper class maintaining an entry in a DcmList double-linked list + */ +class DCMTK_DCMDATA_EXPORT DcmListNode +{ + +public: + /** constructor + * @param obj object to be maintained by this list node + */ + DcmListNode( DcmObject *obj ); + + /// destructor + ~DcmListNode(); + + /// return pointer to object maintained by this list node + inline DcmObject *value() { return objNodeValue; } + +private: + friend class DcmList; + + /// pointer to next node in double-linked list + DcmListNode *nextNode; + + /// pointer to previous node in double-linked list + DcmListNode *prevNode; + + /// pointer to DcmObject instance maintained by this list entry + DcmObject *objNodeValue; + + /// private undefined copy constructor + DcmListNode(const DcmListNode &); + + /// private undefined copy assignment operator + DcmListNode &operator=(const DcmListNode &); + +}; + +/// list position indicator +typedef enum +{ + /// at current position in list + ELP_atpos, + + /// at list start + ELP_first, + + /// at list end + ELP_last, + + /// before current list position + ELP_prev, + + /// after current list position + ELP_next +} E_ListPos; + +/** double-linked list class that maintains pointers to DcmObject instances. + * The remove operation does not delete the object pointed to, however, + * the destructor will delete all elements pointed to + */ +class DCMTK_DCMDATA_EXPORT DcmList +{ +public: + /// constructor + DcmList(); + + /// destructor + ~DcmList(); + + /** insert object at end of list + * @param obj pointer to object + * @return pointer to object + */ + DcmObject *append( DcmObject *obj ); + + /** insert object at start of list + * @param obj pointer to object + * @return pointer to object + */ + DcmObject *prepend( DcmObject *obj ); + + /** insert object relative to current position and indicator + * @param obj pointer to object + * @param pos position indicator + * @return pointer to object + */ + DcmObject *insert( DcmObject *obj, + E_ListPos pos = ELP_next ); + + /** remove current entry from list, return element + * @return pointer to removed element, which is not deleted + */ + DcmObject *remove(); + + /** get pointer to element in list at given position + * @param pos position indicator + * @return pointer to object + */ + DcmObject *get( E_ListPos pos = ELP_atpos ); + + /** seek within element in list to given position + * (i.e. set current element to given position) + * @param pos position indicator + * @return pointer to new current object + */ + DcmObject *seek( E_ListPos pos = ELP_next ); + + /** seek within element in list to given element index + * (i.e. set current element to given index) + * @param absolute_position position index < card() + * @return pointer to new current object + */ + DcmObject *seek_to(unsigned long absolute_position); + + /** Remove and delete all elements from list. Thus, the + * elements' memory is also freed by this operation. The list + * is empty after calling this function. + */ + void deleteAllElements(); + + /// return cardinality of list + inline unsigned long card() const { return cardinality; } + + /// return true if list is empty, false otherwise + inline OFBool empty(void) const { return firstNode == NULL; } + + /// return true if current node exists, false otherwise + inline OFBool valid(void) const { return currentNode != NULL; } + +private: + /// pointer to first node in list + DcmListNode *firstNode; + + /// pointer to last node in list + DcmListNode *lastNode; + + /// pointer to current node in list + DcmListNode *currentNode; + + /// number of elements in list + unsigned long cardinality; + + /// private undefined copy constructor + DcmList &operator=(const DcmList &); + + /// private undefined copy assignment operator + DcmList(const DcmList &newList); +}; + +#endif // DCLIST_H diff --git a/dcmdata/include/dcmtk/dcmdata/dcmetinf.h b/dcmdata/include/dcmtk/dcmdata/dcmetinf.h new file mode 100644 index 00000000..63dfff34 --- /dev/null +++ b/dcmdata/include/dcmtk/dcmdata/dcmetinf.h @@ -0,0 +1,254 @@ +/* + * + * Copyright (C) 1994-2013, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Gerd Ehlers, Andreas Barth + * + * Purpose: Interface of class DcmMetaInfo + * + */ + + +#ifndef DCMETINF_H +#define DCMETINF_H + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/dcmdata/dcitem.h" + + +/// magic string identifying DICOM files +#define DCM_Magic "DICM" + +/// length of magic string identifying DICOM files +#define DCM_MagicLen 4 + +/// length of DICOM file preamble, in bytes +#define DCM_PreambleLen 128 + +/// transfer syntax used for encoding DICOM meta-headers +#define META_HEADER_DEFAULT_TRANSFERSYNTAX EXS_LittleEndianExplicit + + +/** a class representing the DICOM file meta information header + */ +class DCMTK_DCMDATA_EXPORT DcmMetaInfo + : public DcmItem +{ + + public: + + /** default constructor + */ + DcmMetaInfo(); + + /** copy constructor + * @param old item to be copied + */ + DcmMetaInfo(const DcmMetaInfo &old); + + /** assignment operator. + * @param the metainfo to be copied + */ + DcmMetaInfo &operator=(const DcmMetaInfo &obj); + + /** destructor + */ + virtual ~DcmMetaInfo(); + + /** clone method + * @return deep copy of this object + */ + virtual DcmObject *clone() const + { + return new DcmMetaInfo(*this); + } + + /** Virtual object copying. This method can be used for DcmObject + * and derived classes to get a deep copy of an object. Internally + * the assignment operator is called if the given DcmObject parameter + * is of the same type as "this" object instance. If not, an error + * is returned. This function permits copying an object by value + * in a virtual way which therefore is different to just calling the + * assignment operator of DcmElement which could result in slicing + * the object. + * @param rhs - [in] The instance to copy from. Has to be of the same + * class type as "this" object + * @return EC_Normal if copying was successful, error otherwise + */ + virtual OFCondition copyFrom(const DcmObject& rhs); + + /** get type identifier + * @return type identifier of this class (EVR_item) + */ + virtual DcmEVR ident() const; + + /** remove all elements with an invalid group number, i.e. everything but 0x0002 + */ + virtual void removeInvalidGroups(); + + /** return the transfer syntax in which this dataset was originally read. + * @return transfer syntax in which this dataset was originally read, EXS_Unknown if the dataset was created in memory + */ + E_TransferSyntax getOriginalXfer() const; + + /** print meta information header to a stream + * @param out output stream + * @param flags optional flag used to customize the output (see DCMTypes::PF_xxx) + * @param level current level of nested items. Used for indentation. + * @param pixelFileName not used + * @param pixelCounter not used + */ + virtual void print(STD_NAMESPACE ostream&out, + const size_t flags = 0, + const int level = 0, + const char *pixelFileName = NULL, + size_t *pixelCounter = NULL); + + /** initialize the transfer state of this object. This method must be called + * before this object is written to a stream or read (parsed) from a stream. + */ + virtual void transferInit(); + + /** finalize the transfer state of this object. This method must be called + * when reading/writing this object from/to a stream has been completed. + */ + virtual void transferEnd(); + + /** calculate the length of this DICOM element when encoded with the + * given transfer syntax and the given encoding type for sequences. + * For elements, the length includes the length of the tag, length field, + * VR field and the value itself, for items and sequences it returns + * the length of the complete item or sequence including delimitation tags + * if applicable. Never returns undefined length. + * @param xfer transfer syntax for length calculation + * @param enctype sequence encoding type for length calculation + * @return length of DICOM element + */ + virtual Uint32 calcElementLength(const E_TransferSyntax xfer, + const E_EncodingType enctype); + + /** read object from a stream. + * @param inStream DICOM input stream + * @param xfer transfer syntax to use when parsing. EXS_Unknown will + * lead to reading the preamble (if any) and parsing + * metaheader using detected transfer syntax, usually + * Explicit VR Little Endian. + * @param glenc handling of group length parameters + * @param maxReadLength attribute values larger than this value are skipped + * while parsing and read later upon first access if the stream type supports + * this. + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition read(DcmInputStream &inStream, + const E_TransferSyntax xfer = EXS_Unknown, + const E_GrpLenEncoding glenc = EGL_noChange, + const Uint32 maxReadLength = DCM_MaxReadLength); + + /** write meta information header to a stream + * @param outStream DICOM output stream + * @param oxfer output transfer syntax + * @param enctype encoding types (undefined or explicit length) + * @param wcache pointer to write cache object, may be NULL + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition write(DcmOutputStream &outStream, + const E_TransferSyntax oxfer, + const E_EncodingType enctype, + DcmWriteCache *wcache); + + /** write object in XML format + * @param out output stream to which the XML document is written + * @param flags optional flag used to customize the output (see DCMTypes::XF_xxx) + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition writeXML(STD_NAMESPACE ostream &out, + const size_t flags = 0); + + /** load object from a DICOM file. If the file preamble is missing, an error is returned. + * @param fileName name of the file to load (may contain wide chars if support enabled). + * Since there are various constructors for the OFFilename class, a "char *", "OFString" + * or "wchar_t *" can also be passed directly to this parameter. + * @param readXfer transfer syntax used to read the data (auto detection if EXS_Unknown) + * @param groupLength flag, specifying how to handle the group length tags + * @param maxReadLength maximum number of bytes to be read for an element value. + * Element values with a larger size are not loaded until their value is retrieved + * (with getXXX()) or loadAllDataIntoMemory() is called. + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition loadFile(const OFFilename &fileName, + const E_TransferSyntax readXfer = EXS_Unknown, + const E_GrpLenEncoding groupLength = EGL_noChange, + const Uint32 maxReadLength = DCM_MaxReadLength); + + + private: + + /// initialize the preamble buffer with 128 zero bytes followed by "DICM" + void setPreamble(); + + /** check if the next 132 bytes in the input stream are a preamble + * followed by the DICOM "magic word" DICM. If so, try to determine + * the transfer syntax of the meta-header and return in parameter + * newxfer. If not, reset stream to start position. + * @param inStream input stream, should be at start position + * @param newxfer as input parameter contains the expected transfer syntax, + * as output parameter returns the real transfer syntax of the + * meta-header as determined heuristically + * @return true if meta-header found and read, false otherwise + */ + OFBool checkAndReadPreamble(DcmInputStream &inStream, + E_TransferSyntax &newxfer); // out + + /** peeks into the input stream and checks whether the next element + * is group 0002, i.e. belongs to the meta-header + * @return true if next element is part of meta-header, false otherwise + */ + OFBool nextTagIsMeta(DcmInputStream &inStream); + + /** read meta-header group length element which is important because + * it tells us where to switch from meta-header transfer syntax to + * dataset transfer syntax. Insert element into dataset + * @param inStream input stream + * @param xfer transfer syntax of meta-header + * @param xtag attribute tag for group length + * @param glenc handling of group length encoding element in dataset + * @param headerLen output parameter; length of meta-header as encoded in group length element + * @param bytesRead output parameter; number of bytes read when reading group length (for counting the remaining number of meta-header bytes) + * @param maxReadLength max read length for elements + * @return EC_Normal if successful, an error code otherwise + */ + OFCondition readGroupLength(DcmInputStream &inStream, // inout + const E_TransferSyntax xfer, // in + const DcmTagKey &xtag, // in + const E_GrpLenEncoding glenc, // in + Uint32 &headerLen, // out + Uint32 &bytesRead, // out + const Uint32 maxReadLength = DCM_MaxReadLength); // in + + /// buffer for 132 byte DICOM file preamble + char filePreamble[DCM_PreambleLen + DCM_MagicLen]; + + /// true if the preamble was read from stream + OFBool preambleUsed; + + /// transfer state of the preamble + E_TransferState fPreambleTransferState; + + /// transfer syntax in which the meta-header was read + E_TransferSyntax Xfer; + +}; + +#endif // DCMETINF_H diff --git a/dcmdata/include/dcmtk/dcmdata/dcobject.h b/dcmdata/include/dcmtk/dcmdata/dcobject.h new file mode 100644 index 00000000..a9a264c3 --- /dev/null +++ b/dcmdata/include/dcmtk/dcmdata/dcobject.h @@ -0,0 +1,769 @@ +/* + * + * Copyright (C) 1994-2012, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Gerd Ehlers + * + * Purpose: + * This file contains the interface to routines which provide + * DICOM object encoding/decoding, search and lookup facilities. + * + */ + + +#ifndef DCOBJECT_H +#define DCOBJECT_H + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/ofstd/ofglobal.h" +#include "dcmtk/dcmdata/dcerror.h" +#include "dcmtk/dcmdata/dcxfer.h" +#include "dcmtk/dcmdata/dctag.h" +#include "dcmtk/dcmdata/dcstack.h" + + +// forward declarations +class DcmItem; +class DcmOutputStream; +class DcmInputStream; +class DcmWriteCache; +class DcmSpecificCharacterSet; + +// Undefined Length Identifier now defined in dctypes.h + +// Maxinum number of read bytes for a Value Element +const Uint32 DCM_MaxReadLength = 4096; + +// Maximum length of tag and length in a DICOM element +const Uint32 DCM_TagInfoLength = 12; + +// Optimum line length if not all data printed +const Uint32 DCM_OptPrintLineLength = 70; + +// Optimum value length if not all data printed +const Uint32 DCM_OptPrintValueLength = 40; + +// Optimum attribute name length (for tree output) +const Uint32 DCM_OptPrintAttributeNameLength = 35; + +/** This flags defines whether automatic correction should be applied to input + * data (e.g. stripping of padding blanks, removal of blanks in UIDs, etc). + * Default is enabled. + */ +extern DCMTK_DCMDATA_EXPORT OFGlobal dcmEnableAutomaticInputDataCorrection; /* default OFTrue */ + +/** This flag defines the handling of illegal odd-length attributes: If flag is + * true, odd lengths are respected (i.e. an odd number of bytes is read from + * the input stream.) After successful reading, padding to even number of bytes + * is enforced by adding a zero pad byte if dcmEnableAutomaticInputDataCorrection + * is true. Otherwise the odd number of bytes remains as read. + * + * If flag is false, old (pre DCMTK 3.5.2) behaviour applies: The length field + * implicitly incremented and an even number of bytes is read from the stream. + */ +extern DCMTK_DCMDATA_EXPORT OFGlobal dcmAcceptOddAttributeLength; /* default OFTrue */ + +/** This flag defines how UN attributes with undefined length are treated + * by the parser when reading. The default is to expect the content of the + * UN element (up to and including the sequence delimitation item) + * to be encoded in Implicit VR Little Endian, as described in CP 246. + * DCMTK expects the attribute to be encoded like a DICOM sequence, i.e. + * the content of each item is parsed as a DICOM dataset. + * If the flag is disabled old (pre DCMTK 3.5.4) behaviour applies: The + * attribute is treated as if it was an Explicit VR SQ element. + * + * Note that the flag only affects the read behaviour but not the write + * behaviour - DCMTK will never write UN elements with undefined length. + */ +extern DCMTK_DCMDATA_EXPORT OFGlobal dcmEnableCP246Support; /* default OFTrue */ + +/** DCMTK releases up to 3.5.3 created a non-conforming byte stream + * as input to the MAC algorithm when creating or verifying digital signatures + * including compressed pixel data (i.e. signatures including attribute + * (7FE0,0010) in an encapsulated transfer syntax). This has been fixed + * in DCMTK 3.5.4, but this flag allows to revert to the old behavior + * in order to create or verify signatures that are compatible with older + * releases. Default is "off" (OFFalse). + */ +extern DCMTK_DCMDATA_EXPORT OFGlobal dcmEnableOldSignatureFormat; /* default OFFalse */ + +/** This flag defines whether the transfer syntax for uncompressed datasets + * is detected automatically. The automatic detection has been introduced + * since there are (incorrectly encoded) DICOM dataset stored with a + * different transfer syntax than specified in the meta header. + */ +extern DCMTK_DCMDATA_EXPORT OFGlobal dcmAutoDetectDatasetXfer; /* default OFFalse */ + +/** This flag defines how non-standard VRs are treated by the parser when + * reading. The default is to treat data element with non-standard VR as + * unknown. If this flag is enabled, the parser will try to read the data + * element with Implicit VR Little Endian transfer syntax. + */ +extern DCMTK_DCMDATA_EXPORT OFGlobal dcmAcceptUnexpectedImplicitEncoding; /* default OFFalse */ + +/** This flag defines how the element's VR is treated by the parser when + * reading from a dataset with explicit VR encoding. By default, the + * VR from the dataset is used. If this flag is enabled and the VR of the + * tag is defined in the data dictionary, the parser will use the VR from + * the data dictionary (and ignore the one from the dataset). This flag is, + * therefore, useful for reading incorrectly encoded DICOM datasets. + */ +extern DCMTK_DCMDATA_EXPORT OFGlobal dcmPreferVRFromDataDictionary; /* default OFFalse */ + +/** This flag defines how the element's length field is interpreted when reading + * from a dataset with explicit VR encoding and the data dictionary doesn't + * agree with the VR from the dataset. By default, the length field is assumed + * to match the size of the VR in the dataset. If this flag is enabled and the + * tag is defined in the data dictionary, the parser will use the size for the + * VR from the data dictionary (and ignore the one from the dataset). This flag + * is, therefore, useful for reading incorrectly encoded DICOM datasets. + */ +extern DCMTK_DCMDATA_EXPORT OFGlobal dcmPreferLengthFieldSizeFromDataDictionary; /* default OFFalse */ + +/** This flag indicates, whether private attributes with implicit transfer + * syntax having a maximum length should be handled as sequences (ignoring + * any dictionary entries for that tag). This can happen, if for example + * a private creator element is illegally inserted with VR SQ + * (undefined length and implicit coding). The parser usually would then + * try to parse the element with VR=LO (private creator) with maximum + * length, which would lead to an error. The default behaviour is to + * rely on the dictionary. + */ +extern DCMTK_DCMDATA_EXPORT OFGlobal dcmReadImplPrivAttribMaxLengthAsSQ; /* default OFFalse */ + +/** This flag indicates, whether parsing errors during reading + * should be ignored, ie whether the parser should try to recover and + * parse the rest of the stream. + * This flag does not work for all parsing errors (at this time) + * making sense but was introduced afterwards. + */ +extern DCMTK_DCMDATA_EXPORT OFGlobal dcmIgnoreParsingErrors; /* default OFFalse */ + +/** This flag indicates, whether parsing should stop after a certain + * element in the stream was parsed. This is especially useful for + * datasets containing garbage at the end, usually after the Pixel + * Data attribute. To prevent the parser for "stumbling" over that + * garbage, it is possible to tell the parser to stop after a + * specific element. The flag is only sensitive to elements on + * dataset level, ie. inside sequence any occurence of the specified + * tag is ignored. Caution: Note that if Pixel Data is chosen + * as stop element, any attributes behind will not be parsed, e. g. + * any digital signature attributes coming after. + * Default is (0xffff,0xffff), which means that the feature is + * disabled. + */ +extern DCMTK_DCMDATA_EXPORT OFGlobal dcmStopParsingAfterElement; /* default OFTrue */ + +/** This flag influences behaviour when writing a dataset with items + * and sequences set to be encoded with explicit length. It is possible + * that the content of a sequence (or item) has an encoded length greater + * than the maximum 32-bit value that can be written to the sequence (item) + * length field. If this flag is enabled (OFTrue) then the encoding of the + * very sequence (item) is switched to undefined length encoding. Any + * contained items (sequences) will be encoded explicitly if possible. + * Default is OFTrue, i.e. encoding is switched to implicit if maximum + * size of length field is exceeded. + */ +extern DCMTK_DCMDATA_EXPORT OFGlobal dcmWriteOversizedSeqsAndItemsUndefined; /* default OFTrue */ + +/** This flag allows for ignoring the value of (0002,0000) File Meta Information + * Group Length which is useful in cases where this value is incorrect. If the + * header length is ignored, the behavior is identical to the case when no value + * is available (i.e. all elements are read as long as the group number is 0x0002). + */ +extern DCMTK_DCMDATA_EXPORT OFGlobal dcmIgnoreFileMetaInformationGroupLength; /* default OFFalse */ + +/** This flag enables the replacement of a wrong delimitation item at the end of + * a sequence or item. This is because there are incorrect systems that write + * a Sequence Delimitation Item (fffe,e0dd) at the end of an item or an Item + * Delimitation Item (fffe,e00d) at the end of a sequence. By default, no + * delimitation items are replaced. + */ +extern DCMTK_DCMDATA_EXPORT OFGlobal dcmReplaceWrongDelimitationItem; /* default OFFalse */ + + +/** Abstract base class for most classes in module dcmdata. As a rule of thumb, + * everything that is either a dataset or that can be identified with a DICOM + * attribute tag is derived from class DcmObject. + */ +class DCMTK_DCMDATA_EXPORT DcmObject +{ + public: + + /** constructor. + * Create new object from given tag and length. + * @param tag DICOM tag for the new element + * @param len value length for the new element + */ + DcmObject(const DcmTag &tag, const Uint32 len = 0); + + /** copy constructor + * @param obj item to be copied + */ + DcmObject(const DcmObject &obj); + + /// destructor + virtual ~DcmObject(); + + /** clone method + * @return deep copy of this object + */ + virtual DcmObject *clone() const = 0; + + /** copy assignment operator + * @param obj object to be copied + * @return reference to this object + */ + DcmObject &operator=(const DcmObject &obj); + + /** Virtual object copying. This method can be used for DcmObject + * and derived classes to get a deep copy of an object. Internally + * the assignment operator is called if the given DcmObject parameter + * is of the same type as "this" object instance. If not, an error + * is returned. This function permits copying an object by value + * in a virtual way which therefore is different to just calling the + * assignment operator of DcmElement which could result in slicing + * the object. + * @param rhs - [in] The instance to copy from. Has to be of the same + * class type as "this" object + * @return EC_Normal if copying was successful, error otherwise + */ + virtual OFCondition copyFrom(const DcmObject &rhs) = 0; + + /** return identifier for this class. Every class derived from this class + * returns a unique value of type enum DcmEVR for this call. This is used + * as a "poor man's RTTI" to correctly identify instances derived from + * this class even on compilers not supporting RTTI. + * @return type identifier of this class + */ + virtual DcmEVR ident() const = 0; + + /** return the value representation assigned to this object. + * If object was read from a stream, this method returns the VR + * that was defined in the stream for this object. It is, therefore, + * possible that the VR does not match the one defined in the data + * dictionary for the tag assigned to this object. + * @return VR of this object + */ + inline DcmEVR getVR() const { return Tag.getEVR(); } + + /** check if this element is a string type, based on the VR. + * Since the check is based on the VR and not on the class, + * the result of this method is not a guarantee that the object + * can be safely casted to one of the string-VR subclasses. + * @return true if this object is a string VR, false otherwise + */ + inline OFBool isaString() const { return Tag.getVR().isaString(); } + + /** check if this element is a leaf node in a dataset tree. + * All subclasses of DcmElement except for DcmSequenceOfItems + * are leaf nodes, while DcmSequenceOfItems, DcmItem, DcmDataset etc. + * are not. + * @return true if leaf node, false otherwise + */ + virtual OFBool isLeaf() const = 0; + + /** check if this element is nested in a sequence of items, i.e.\ not a + * top-level or stand-alone element + * @return true if this element is nested, false otherwise + */ + virtual OFBool isNested() const; + + /** print object to a stream + * @param out output stream + * @param flags optional flag used to customize the output (see DCMTypes::PF_xxx) + * @param level current level of nested items. Used for indentation. + * @param pixelFileName not used (used in certain sub-classes of this class) + * @param pixelCounter not used (used in certain sub-classes of this class) + */ + virtual void print(STD_NAMESPACE ostream &out, + const size_t flags = 0, + const int level = 0, + const char *pixelFileName = NULL, + size_t *pixelCounter = NULL) = 0; + + /** return the current transfer (read/write) state of this object. + * @return transfer state of this object + */ + inline E_TransferState transferState() const { return fTransferState; } + + /** initialize the transfer state of this object. This method must be called + * before this object is written to a stream or read (parsed) from a stream. + */ + virtual void transferInit(void); + + /** finalize the transfer state of this object. This method must be called + * when reading/writing this object from/to a stream has been completed. + */ + virtual void transferEnd(void); + + /** get root dataset/item (top-level) that contains this object. Internally, + * the list of parent pointers is followed in order to find the root. If + * this object has no parent item, a pointer to this object is returned + * instead. + * @return pointer to the root dataset/item (might be NULL) + */ + DcmItem *getRootItem(); + + /** get parent item of this object. In case of a top-level element, this is + * either the main dataset or the file meta-information. In case of a nested + * element, this is the surrounding item. + * @return pointer to the parent item of this object (might be NULL) + */ + virtual DcmItem *getParentItem(); + + /** get parent of this object. If this object is an element that has been + * inserted into a dataset/item, the parent is this particular dataset/item. + * If this object is an item that has been inserted into a sequence, the + * parent is this particular sequence. If this object has not been inserted + * into a dataset/item or sequence, NULL is returned. + * @return pointer to the parent of this object (might be NULL) + */ + inline DcmObject *getParent() { return Parent; } + + /** get parent of this object. If this object is an element that has been + * inserted into a dataset/item, the parent is this particular dataset/item. + * If this object is an item that has been inserted into a sequence, the + * parent is this particular sequence. If this object has not been inserted + * into a dataset/item or sequence, NULL is returned. + * @return pointer to the parent of this object (might be NULL) + */ + inline const DcmObject *getParent() const { return Parent; } + + /** set parent of this object. NULL means no parent. + * NB: This method is used by derived classes for internal purposes only. + */ + inline void setParent(DcmObject *parent) { Parent = parent; } + + /** return the group number of the attribute tag for this object + * @return group number of the attribute tag for this object + */ + inline Uint16 getGTag() const { return Tag.getGTag(); } + + /** return the element number of the attribute tag for this object + * @return element number of the attribute tag for this object + */ + inline Uint16 getETag() const { return Tag.getETag(); } + + /** return const reference to the attribute tag for this object + * @return const reference to the attribute tag for this object + */ + inline const DcmTag &getTag() const { return Tag; } + + /** assign group tag (but not element tag) of the attribute tag for this object. + * This is sometimes useful when creating repeating group elements. + * @param gtag new attribute group tag + */ + inline void setGTag(Uint16 gtag) { Tag.setGroup(gtag); } + + /** assign a new Value Representation (VR) to this object. This operation + * is only supported for very few subclasses derived from this class, + * in particular for classes handling pixel data which may either be + * of OB or OW value representation. + * @param vr value representation + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setVR(DcmEVR /*vr*/) { return EC_IllegalCall; } + + /** return value multiplicity of the current object + * @return value multiplicity of the current object + */ + virtual unsigned long getVM() = 0; + + /** calculate the length of this DICOM element when encoded with the + * given transfer syntax and the given encoding type for sequences. + * For elements, the length includes the length of the tag, length field, + * VR field and the value itself, for items and sequences it returns + * the length of the complete item or sequence including delimitation tags + * if applicable. Never returns undefined length. + * @param xfer transfer syntax for length calculation + * @param enctype sequence encoding type for length calculation + * @return length of DICOM element + */ + virtual Uint32 calcElementLength(const E_TransferSyntax xfer, + const E_EncodingType enctype) = 0; + + /** calculate the value length (without attribute tag, VR and length field) + * of this DICOM element when encoded with the given transfer syntax and + * the given encoding type for sequences. Never returns undefined length. + * @param xfer transfer syntax for length calculation + * @param enctype sequence encoding type for length calculation + * @return value length of DICOM element + */ + virtual Uint32 getLength(const E_TransferSyntax xfer = EXS_LittleEndianImplicit, + const E_EncodingType enctype = EET_UndefinedLength) = 0; + + /** check if this DICOM object can be encoded in the given transfer syntax. + * @param newXfer transfer syntax in which the DICOM object is to be encoded + * @param oldXfer transfer syntax in which the DICOM object was read or created. + * @return true if object can be encoded in desired transfer syntax, false otherwise. + */ + virtual OFBool canWriteXfer(const E_TransferSyntax newXfer, + const E_TransferSyntax oldXfer) = 0; + + /** read object from a stream. + * @param inStream DICOM input stream + * @param ixfer transfer syntax to use when parsing + * @param glenc handling of group length parameters + * @param maxReadLength attribute values larger than this value are skipped + * while parsing and read later upon first access if the stream type supports + * this. + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition read(DcmInputStream &inStream, + const E_TransferSyntax ixfer, + const E_GrpLenEncoding glenc = EGL_noChange, + const Uint32 maxReadLength = DCM_MaxReadLength) = 0; + + /** write object to a stream (abstract) + * @param outStream DICOM output stream + * @param oxfer output transfer syntax + * @param enctype encoding types (undefined or explicit length) + * @param wcache pointer to write cache object, may be NULL + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition write(DcmOutputStream &outStream, + const E_TransferSyntax oxfer, + const E_EncodingType enctype, + DcmWriteCache *wcache) = 0; + + /** write object in XML format to a stream + * @param out output stream to which the XML document is written + * @param flags optional flag used to customize the output (see DCMTypes::XF_xxx) + * @return status, always returns EC_Illegal Call + */ + virtual OFCondition writeXML(STD_NAMESPACE ostream&out, + const size_t flags = 0); + + /** special write method for creation of digital signatures (abstract) + * @param outStream DICOM output stream + * @param oxfer output transfer syntax + * @param enctype encoding types (undefined or explicit length) + * @param wcache pointer to write cache object, may be NULL + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition writeSignatureFormat(DcmOutputStream &outStream, + const E_TransferSyntax oxfer, + const E_EncodingType enctype, + DcmWriteCache *wcache) = 0; + + /** returns true if the current object may be included in a digital signature + * @return true if signable, false otherwise + */ + virtual OFBool isSignable() const; + + /** returns true if the object contains an element with Unknown VR at any nesting level + * @return true if the object contains an element with Unknown VR, false otherwise + */ + virtual OFBool containsUnknownVR() const; + + /** check if this object contains non-ASCII characters + * @param checkAllStrings not used in this class + * @return always returns false, i.e. no extended characters used + */ + virtual OFBool containsExtendedCharacters(const OFBool checkAllStrings = OFFalse); + + /** check if this object is affected by SpecificCharacterSet + * @return always returns false, i.e. not affected by SpecificCharacterSet + */ + virtual OFBool isAffectedBySpecificCharacterSet() const; + + /** convert this object from the currently selected source character set to the + * currently selected destination character set (if affected by SpecificCharacterSet) + * @param converter character set converter to be used to convert the element values + * @return always returns EC_Normal, since there is nothing to do in this base class + */ + virtual OFCondition convertCharacterSet(DcmSpecificCharacterSet &converter); + + /** check if this object is empty + * @param normalize normalize value before checking (ignore non-significant characters) + * @return true if object is empty, i.e. has no value, false otherwise + */ + virtual OFBool isEmpty(const OFBool normalize = OFTrue); + + /** clear (remove) attribute value + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition clear() = 0; + + /** check the currently stored element value + * @param autocorrect correct value length if OFTrue + * @return status, EC_Normal if value length is correct, an error code otherwise + */ + virtual OFCondition verify(const OFBool autocorrect = OFFalse) = 0; + + /** this method is only used in container classes derived from this class, + * that is, DcmItem and DcmSequenceOfItems. It returns a pointer to the + * next object in the list AFTER the given object. If the caller passes NULL, + * a pointer to the first object in the list is returned. If the given object + * is not found, the given object is the last one in the list or the list is empty, + * NULL is returned. + * @param obj pointer to one object in the container; we are looking for the + * next entry after this one. NULL if looking for the first entry. + * @return pointer to next object in container or NULL if not found + */ + virtual DcmObject *nextInContainer(const DcmObject *obj); + + /** this method enables a stack based, depth-first traversal of a complete + * hierarchical DICOM dataset (that is, classes derived from DcmItem or + * DcmSequenceOfItems). With each call of this method, the next object + * in the tree is located and marked on the stack. + * @param stack "cursor" for current position in the dataset. The stack + * will contain a pointer to each dataset, sequence, item and element + * from the main dataset down to the current element, and is updated + * upon each call to this method. An empty stack is equivalent to a stack + * containing a pointer to this object only. + * @param intoSub if true, the nextObject method will perform a hierarchical + * search through the dataset (depth-first), if false, only the current + * container object will be traversed (e.g., all elements of an item + * or all items of a sequence). + * @return EC_Normal if value length is correct, an error code otherwise + */ + virtual OFCondition nextObject(DcmStack &stack, + const OFBool intoSub); + + /** a complex, stack-based, hierarchical search method. It allows for a search + * for a DICOM object with a given attribute within a given container, + * hierarchically, from a starting position identified through a cursor stack. + * @param xtag the DICOM attribute tag we are searching for + * @param resultStack Depending on the search mode (see below), this parameter + * either serves as an input and output parameter, or as an output parameter + * only (the latter being the default). When used as an input parameter, + * the cursor stack defines the start position for the search within a + * hierarchical DICOM dataset. Upon successful return, the stack contains + * the position of the element found, in the form of a pointer to each dataset, + * sequence, item and element from the main dataset down to the found element. + * @param mode search mode, controls how the search stack is handled. + * In the default mode, ESM_fromHere, the stack is ignored on input, and + * the search starts in the object for which this method is called. + * In the other modes, the stack is used both as an input and an output + * parameter and defines the starting point for the search. + * @param searchIntoSub if true, the search will be performed hierarchically descending + * into the sequences and items of the dataset. If false, only the current container + * (sequence or item) will be traversed. + * @return EC_Normal if found, EC_TagNotFound if not found, an error code is something went wrong. + */ + virtual OFCondition search(const DcmTagKey &xtag, + DcmStack &resultStack, + E_SearchMode mode = ESM_fromHere, + OFBool searchIntoSub = OFTrue); + + /** this method loads all attribute values maintained by this object and + * all sub-objects (in case of a container such as DcmDataset) into memory. + * After a call to this method, the file from which a dataset was read may safely + * be deleted or replaced. For large files, this method may obviously allocate large + * amounts of memory. + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition loadAllDataIntoMemory() = 0; + + /** return the current value of the Length field (which is different from the functionality + * of the public getLength method). Only needed for internal purposes and for checker tools + * that verify values against the length field. + * @return current value of length field + */ + Uint32 getLengthField() const { return Length; } + + protected: + + /** print line indentation, e.g. a couple of spaces for each nesting level. + * Depending on the value of 'flags' other visualizations are also possible. + * @param out output stream + * @param flags used to customize the output (see DCMTypes::PF_xxx) + * @param level current level of nested items. Used for indentation. + */ + void printNestingLevel(STD_NAMESPACE ostream &out, + const size_t flags, + const int level); + + /** print beginning of the info line. + * The default output is tag and value representation, though other + * visualizations are possible depending on the value of 'flags'. + * @param out output stream + * @param flags used to customize the output (see DCMTypes::PF_xxx) + * @param level current level of nested items. Used for indentation. + * @param tag optional tag used to print the data element information + */ + void printInfoLineStart(STD_NAMESPACE ostream &out, + const size_t flags, + const int level, + DcmTag *tag = NULL); + + /** print end of the info line. + * The default output is length, value multiplicity and tag name, though + * other visualizations are possible depending on the value of 'flags'. + * @param out output stream + * @param flags used to customize the output (see DCMTypes::PF_xxx) + * @param printedLength number of characters printed after line start. + * Used for padding purposes. + * @param tag optional tag used to print the data element information + */ + void printInfoLineEnd(STD_NAMESPACE ostream &out, + const size_t flags, + const unsigned long printedLength = 0xffffffff /*no padding*/, + DcmTag *tag = NULL); + + /** print given text with element information. + * Calls printInfoLineStart() and printInfoLineEnd() to frame the + * 'info' text. + * @param out output stream + * @param flags used to customize the output (see DCMTypes::PF_xxx) + * @param level current level of nested items. Used for indentation. + * @param info text to be printed + * @param tag optional tag used to print the data element information + * @param isInfo optional flag indicating whether this text is really given for + * informational purposes only. Used to choose the correct output color. + */ + virtual void printInfoLine(STD_NAMESPACE ostream &out, + const size_t flags, + const int level = 0, + const char *info = NULL, + DcmTag *tag = NULL, + const OFBool isInfo = OFTrue); + + /** static helper function that writes a given attribute tag to a binary + * output stream using the byte order indicated by the transfer syntax. + * @param outStream output stream + * @param tag tag to write to the stream + * @param oxfer transfer syntax defining the byte order + * @return EC_Normal if successful, an error code otherwise + */ + static OFCondition writeTag(DcmOutputStream &outStream, + const DcmTag &tag, + const E_TransferSyntax oxfer); + + /** write tag, VR and length field to the given output stream + * @param outStream output stream + * @param oxfer transfer syntax for writing + * @param writtenBytes number of bytes written to stream returned in this parameter + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition writeTagAndLength(DcmOutputStream &outStream, + const E_TransferSyntax oxfer, // in + Uint32 &writtenBytes) const; // out + + /** return the number of bytes needed to serialize the + * tag, VR and length information of the current object using the given + * transfer syntax. + * @param oxfer The transfer syntax used for encoding + * @return number of bytes, may be 8 or 12 depending on VR and transfer syntax. + */ + virtual Uint32 getTagAndLengthSize(const E_TransferSyntax oxfer) const; + + /** return the DICOM attribute tag name for this object. If not known yet, will + * be looked up in the dictionary and cached. Therefore, method is not const. + * @return tag name for this attribute + */ + const char *getTagName() { return Tag.getTagName(); } + + /** set the VR for this attribute + * @param vr new VR for this attribute. + */ + void setTagVR(DcmEVR vr) { Tag.setVR(vr); } + + /** return the current transfer state of this object during serialization/deserialization + * @return current transfer state of this object + */ + E_TransferState getTransferState() const { return fTransferState; } + + /** set the current transfer state of this object during serialization/deserialization + * @param newState new transfer state of this object + */ + void setTransferState(E_TransferState newState) { fTransferState = newState; } + + /** return the number of transferred bytes for this object during serialization/deserialization + * @return number of transferred bytes + */ + Uint32 getTransferredBytes() const { return fTransferredBytes; } + + /** set the number of transferred bytes for this object during serialization/deserialization + * @param val number of transferred bytes + */ + void setTransferredBytes(Uint32 val) { fTransferredBytes = val; } + + /** add to the number of transferred bytes for this object during serialization/deserialization + * @param val number of additional transferred bytes to add to existing value + */ + void incTransferredBytes(Uint32 val) { fTransferredBytes += val; } + + /** set the current value of the Length field + * @param val new value of the Length field + */ + void setLengthField(Uint32 val) { Length = val; } + + public: + + /** helper class to print a DcmObject to an ostream using operator<< + */ + class DCMTK_DCMDATA_EXPORT PrintHelper + { + private: + /** Undefined assignment operator. This is needed to work around a + * compiler warning on VC2008 with the highest warning level. + */ + PrintHelper& operator=(PrintHelper &); + + public: + /** construct a PrintHelper + * @param dcmobj DcmObject you want to print + * @param flags flags to use for DcmObject::print() + * @param level level to use for DcmObject::print() + */ + explicit PrintHelper(DcmObject &dcmobj, size_t flags = 0, int level = 0) + : dcmobj_(dcmobj), flags_(flags), level_(level) + {} + + DcmObject &dcmobj_; + const size_t flags_; + const int level_; + }; + + /* member variables */ + + protected: + + /// error flag for this object. + OFCondition errorFlag; + + private: + + /// the DICOM attribute tag and VR for this object + DcmTag Tag; + + /// the length of this attribute as read from stream, may be undefined length + Uint32 Length; + + /// transfer state during read and write operations + E_TransferState fTransferState; + + /// number of bytes already read/written during transfer + Uint32 fTransferredBytes; + + /// pointer to parent object if contained in a dataset/item (might be NULL) + DcmObject *Parent; + }; // class DcmObject + +/** Print a DcmObject::PrintHelper to an ostream. + * @param stream stream to print to + * @param obj object which will be print()ed + * @return the stream argument + */ +static inline STD_NAMESPACE ostream& operator<<(STD_NAMESPACE ostream &stream, DcmObject::PrintHelper obj) +{ + obj.dcmobj_.print(stream, obj.flags_, obj.level_); + return stream; +} + +#endif // DCOBJECT_H diff --git a/dcmdata/include/dcmtk/dcmdata/dcofsetl.h b/dcmdata/include/dcmtk/dcmdata/dcofsetl.h new file mode 100644 index 00000000..aab2b1d2 --- /dev/null +++ b/dcmdata/include/dcmtk/dcmdata/dcofsetl.h @@ -0,0 +1,33 @@ +/* + * + * Copyright (C) 1994-2010, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Marco Eichelberg + * + * Purpose: definition of class DcmOffsetList + * + */ + +#ifndef DCOFSETL_H +#define DCOFSETL_H + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ +#include "dcmtk/ofstd/oflist.h" /* for class OFList */ + +/** list of Uint32 values which are interpreted as the offsets + * in a Pixel Data offset table + */ +typedef OFList DcmOffsetList; + +#endif diff --git a/dcmdata/include/dcmtk/dcmdata/dcostrma.h b/dcmdata/include/dcmtk/dcmdata/dcostrma.h new file mode 100644 index 00000000..dab197b6 --- /dev/null +++ b/dcmdata/include/dcmtk/dcmdata/dcostrma.h @@ -0,0 +1,205 @@ +/* + * + * Copyright (C) 1994-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Marco Eichelberg + * + * Purpose: base classes for output streams + * + */ + +#ifndef DCOSTRMA_H +#define DCOSTRMA_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/ofstd/oftypes.h" /* for OFBool */ +#include "dcmtk/ofstd/ofcond.h" /* for OFCondition */ +#include "dcmtk/dcmdata/dcxfer.h" /* for E_StreamCompression */ +#include "dcmtk/ofstd/offile.h" /* for offile_off_t */ + +/** pure virtual abstract base class for consumers, i.e. the final node + * of a filter chain in an output stream. + */ +class DCMTK_DCMDATA_EXPORT DcmConsumer +{ +public: + + /// destructor + virtual ~DcmConsumer() + { + } + + /** returns the status of the consumer. Unless the status is good, + * the consumer will not permit any operation. + * @return status, true if good + */ + virtual OFBool good() const = 0; + + /** returns the status of the consumer as an OFCondition object. + * Unless the status is good, the consumer will not permit any operation. + * @return status, EC_Normal if good + */ + virtual OFCondition status() const = 0; + + /** returns true if the consumer is flushed, i.e. has no more data + * pending in it's internal state that needs to be flushed before + * the stream is closed. + * @return true if consumer is flushed, false otherwise + */ + virtual OFBool isFlushed() const = 0; + + /** returns the minimum number of bytes that can be written with the + * next call to write(). The DcmObject write methods rely on avail + * to return a value > 0 if there is no I/O suspension since certain + * data such as tag and length are only written "en bloc", i.e. all + * or nothing. + * @return minimum of space available in consumer + */ + virtual offile_off_t avail() const = 0; + + /** processes as many bytes as possible from the given input block. + * @param buf pointer to memory block, must not be NULL + * @param buflen length of memory block + * @return number of bytes actually processed. + */ + virtual offile_off_t write(const void *buf, offile_off_t buflen) = 0; + + /** instructs the consumer to flush its internal content until + * either the consumer becomes "flushed" or I/O suspension occurs. + * After a call to flush(), a call to write() will produce undefined + * behaviour. + */ + virtual void flush() = 0; +}; + + +/** pure virtual abstract base class for output filters, i.e. + * intermediate nodes of a filter chain in an output stream. + */ +class DCMTK_DCMDATA_EXPORT DcmOutputFilter: public DcmConsumer +{ +public: + + /// destructor + virtual ~DcmOutputFilter() + { + } + + /** determines the consumer to which the filter is supposed + * to write it's output. Once a consumer for the output filter has + * been defined, it cannot be changed anymore during the lifetime + * of the object. + * @param consumer reference to consumer, must not be circular chain + */ + virtual void append(DcmConsumer& consumer) = 0; +}; + + +/** base class for output streams. + * This class cannot be instantiated since the constructor is protected. + */ +class DCMTK_DCMDATA_EXPORT DcmOutputStream +{ +public: + + /// destructor + virtual ~DcmOutputStream(); + + /** returns the status of the stream. Unless the status is good, + * the stream will not permit any operation. + * @return status, true if good + */ + virtual OFBool good() const; + + /** returns the status of the consumer as an OFCondition object. + * Unless the status is good, the consumer will not permit any operation. + * @return status, EC_Normal if good + */ + virtual OFCondition status() const; + + /** returns true if the stream is flushed, i.e. has no more data + * pending in it's internal state that needs to be flushed before + * the stream is closed. + * @return true if stream is flushed, false otherwise + */ + virtual OFBool isFlushed() const; + + /** returns the minimum number of bytes that can be written with the + * next call to write(). The DcmObject write methods rely on avail + * to return a value > 0 if there is no I/O suspension since certain + * data such as tag and length are only written "en bloc", i.e. all + * or nothing. + * @return minimum of space available in stream + */ + virtual offile_off_t avail() const; + + /** processes as many bytes as possible from the given input block. + * @param buf pointer to memory block, must not be NULL + * @param buflen length of memory block + * @return number of bytes actually processed. + */ + virtual offile_off_t write(const void *buf, offile_off_t buflen); + + /** instructs the stream to flush its internal content until + * either the stream becomes "flushed" or I/O suspension occurs. + * After a call to flush(), a call to write() will produce undefined + * behaviour. + */ + virtual void flush(); + + /** returns the total number of bytes written to the stream so far + * @return total number of bytes written to the stream + */ + virtual offile_off_t tell() const; + + /** installs a compression filter for the given stream compression type, + * which should be neither ESC_none nor ESC_unsupported. Once a compression + * filter is active, it cannot be deactivated or replaced during the + * lifetime of the stream. + * @param filterType type of compression filter + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition installCompressionFilter(E_StreamCompression filterType); + +protected: + + /** protected constructor, to be called from derived class constructor + * @param initial initial pointer to first node in filter chain + * The pointer is not dereferenced in the constructor, so the + * object pointed to may be initialized later in the subclass + * constructor. + */ + DcmOutputStream(DcmConsumer *initial); + +private: + + /// private unimplemented copy constructor + DcmOutputStream(const DcmOutputStream&); + + /// private unimplemented copy assignment operator + DcmOutputStream& operator=(const DcmOutputStream&); + + /// pointer to first node in filter chain + DcmConsumer *current_; + + /// pointer to compression filter, NULL if no compression + DcmOutputFilter *compressionFilter_; + + /// counter for number of bytes written so far + offile_off_t tell_; +}; + + + +#endif diff --git a/dcmdata/include/dcmtk/dcmdata/dcostrmb.h b/dcmdata/include/dcmtk/dcmdata/dcostrmb.h new file mode 100644 index 00000000..386d2beb --- /dev/null +++ b/dcmdata/include/dcmtk/dcmdata/dcostrmb.h @@ -0,0 +1,168 @@ +/* + * + * Copyright (C) 1994-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Marco Eichelberg + * + * Purpose: DcmOutputBufferStream and related classes, + * implements output to blocks of memory as needed in the dcmnet module. + * + */ + +#ifndef DCOSTRMB_H +#define DCOSTRMB_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmdata/dcostrma.h" + +/** consumer class that stores data in a buffer provided by the caller. + * Used for DICOM network communication. + */ +class DCMTK_DCMDATA_EXPORT DcmBufferConsumer: public DcmConsumer +{ +public: + + /** constructor + * @param buf buffer in which data is stored. Must be allocated + * by caller and remain valid during the lifetime of this object. + * @param bufLen buffer length, must be even number > 0. + */ + DcmBufferConsumer(void *buf, offile_off_t bufLen); + + /// destructor + virtual ~DcmBufferConsumer(); + + /** returns the status of the consumer. Unless the status is good, + * the consumer will not permit any operation. + * @return status, true if good + */ + virtual OFBool good() const; + + /** returns the status of the consumer as an OFCondition object. + * Unless the status is good, the consumer will not permit any operation. + * @return status, EC_Normal if good + */ + virtual OFCondition status() const; + + /** returns true if the consumer is flushed, i.e. has no more data + * pending in it's internal state that needs to be flushed before + * the stream is closed. + * @return true if consumer is flushed, false otherwise + */ + virtual OFBool isFlushed() const; + + /** returns the minimum number of bytes that can be written with the + * next call to write(). The DcmObject write methods rely on avail + * to return a value > 0 if there is no I/O suspension since certain + * data such as tag and length are only written "en bloc", i.e. all + * or nothing. + * @return minimum of space available in consumer + */ + virtual offile_off_t avail() const; + + /** processes as many bytes as possible from the given input block. + * @param buf pointer to memory block, must not be NULL + * @param buflen length of memory block + * @return number of bytes actually processed. + */ + virtual offile_off_t write(const void *buf, offile_off_t buflen); + + /** instructs the consumer to flush its internal content until + * either the consumer becomes "flushed" or I/O suspension occurs. + * After a call to flush(), a call to write() will produce undefined + * behaviour. + */ + virtual void flush(); + + /** retrieves and flushes the underlying buffer. + * After return of this method, the buffer is considered to have + * been flushed (copied, stored) by the caller and is reused + * by the next write operation. + * @param buffer pointer to user provided buffer returned in this parameter + * @param length number of bytes in buffer returned in this parameter + */ + virtual void flushBuffer(void *& buffer, offile_off_t& length); + + /** query the number of bytes in buffer without flushing it. + * @return number of bytes in buffer. + */ + virtual offile_off_t filled(); + +private: + + /// private unimplemented copy constructor + DcmBufferConsumer(const DcmBufferConsumer&); + + /// private unimplemented copy assignment operator + DcmBufferConsumer& operator=(const DcmBufferConsumer&); + + /// the buffer we're actually writing to + unsigned char *buffer_; + + /// size of the buffer, in bytes + offile_off_t bufSize_; + + /// number of bytes filled in buffer + offile_off_t filled_; + + /// status + OFCondition status_; +}; + + +/** output stream that writes into a buffer of fixed length + * which must be provided by the caller. + */ +class DCMTK_DCMDATA_EXPORT DcmOutputBufferStream: public DcmOutputStream +{ +public: + /** constructor + * @param buf buffer in which data is stored. Must be allocated + * by caller and remain valid during the lifetime of this object. + * @param bufLen buffer length, must be even number > 0. + */ + DcmOutputBufferStream(void *buf, offile_off_t bufLen); + + /// destructor + virtual ~DcmOutputBufferStream(); + + /** retrieves and flushes the underlying buffer. + * After return of this method, the buffer is considered to have + * been flushed (copied, stored) by the caller and is reused + * by the next write operation. + * @param buffer pointer to user provided buffer returned in this parameter + * @param length number of bytes in buffer returned in this parameter + */ + virtual void flushBuffer(void *& buffer, offile_off_t& length); + + /** query the number of bytes in buffer without flushing it. + * @return number of bytes in buffer. + */ + virtual offile_off_t filled(); + +private: + + /// private unimplemented copy constructor + DcmOutputBufferStream(const DcmOutputBufferStream&); + + /// private unimplemented copy assignment operator + DcmOutputBufferStream& operator=(const DcmOutputBufferStream&); + + /// the final consumer of the filter chain + DcmBufferConsumer consumer_; + +}; + + +#endif diff --git a/dcmdata/include/dcmtk/dcmdata/dcostrmf.h b/dcmdata/include/dcmtk/dcmdata/dcostrmf.h new file mode 100644 index 00000000..dff45220 --- /dev/null +++ b/dcmdata/include/dcmtk/dcmdata/dcostrmf.h @@ -0,0 +1,142 @@ +/* + * + * Copyright (C) 1994-2012, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Marco Eichelberg + * + * Purpose: DcmOutputFileStream and related classes, + * implements streamed output to files. + * + */ + +#ifndef DCOSTRMF_H +#define DCOSTRMF_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmdata/dcostrma.h" + +#define INCLUDE_CSTDIO +#include "dcmtk/ofstd/ofstdinc.h" + + +/** consumer class that stores data in a plain file. + */ +class DCMTK_DCMDATA_EXPORT DcmFileConsumer: public DcmConsumer +{ +public: + /** constructor + * @param filename name of file to be created (may contain wide chars + * if support enabled) + */ + DcmFileConsumer(const OFFilename &filename); + + /** constructor + * @param file structure, file must already be open for writing + */ + DcmFileConsumer(FILE *file); + + /// destructor + virtual ~DcmFileConsumer(); + + /** returns the status of the consumer. Unless the status is good, + * the consumer will not permit any operation. + * @return status, true if good + */ + virtual OFBool good() const; + + /** returns the status of the consumer as an OFCondition object. + * Unless the status is good, the consumer will not permit any operation. + * @return status, EC_Normal if good + */ + virtual OFCondition status() const; + + /** returns true if the consumer is flushed, i.e. has no more data + * pending in it's internal state that needs to be flushed before + * the stream is closed. + * @return true if consumer is flushed, false otherwise + */ + virtual OFBool isFlushed() const; + + /** returns the minimum number of bytes that can be written with the + * next call to write(). The DcmObject write methods rely on avail + * to return a value > 0 if there is no I/O suspension since certain + * data such as tag and length are only written "en bloc", i.e. all + * or nothing. + * @return minimum of space available in consumer + */ + virtual offile_off_t avail() const; + + /** processes as many bytes as possible from the given input block. + * @param buf pointer to memory block, must not be NULL + * @param buflen length of memory block + * @return number of bytes actually processed. + */ + virtual offile_off_t write(const void *buf, offile_off_t buflen); + + /** instructs the consumer to flush its internal content until + * either the consumer becomes "flushed" or I/O suspension occurs. + * After a call to flush(), a call to write() will produce undefined + * behaviour. + */ + virtual void flush(); + +private: + + /// private unimplemented copy constructor + DcmFileConsumer(const DcmFileConsumer&); + + /// private unimplemented copy assignment operator + DcmFileConsumer& operator=(const DcmFileConsumer&); + + /// the file we're actually writing to + OFFile file_; + + /// status + OFCondition status_; +}; + + +/** output stream that writes into a plain file + */ +class DCMTK_DCMDATA_EXPORT DcmOutputFileStream: public DcmOutputStream +{ +public: + /** constructor + * @param filename name of file to be created (may contain wide chars + * if support enabled) + */ + DcmOutputFileStream(const OFFilename &filename); + + /** constructor + * @param file structure, file must already be open for writing + */ + DcmOutputFileStream(FILE *file); + + /// destructor + virtual ~DcmOutputFileStream(); + +private: + + /// private unimplemented copy constructor + DcmOutputFileStream(const DcmOutputFileStream&); + + /// private unimplemented copy assignment operator + DcmOutputFileStream& operator=(const DcmOutputFileStream&); + + /// the final consumer of the filter chain + DcmFileConsumer consumer_; +}; + + +#endif diff --git a/dcmdata/include/dcmtk/dcmdata/dcostrmz.h b/dcmdata/include/dcmtk/dcmdata/dcostrmz.h new file mode 100644 index 00000000..32bfa924 --- /dev/null +++ b/dcmdata/include/dcmtk/dcmdata/dcostrmz.h @@ -0,0 +1,179 @@ +/* + * + * Copyright (C) 1994-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Marco Eichelberg + * + * Purpose: zlib compression filter for output streams + * + */ + +#ifndef DCOSTRMZ_H +#define DCOSTRMZ_H + +#include "dcmtk/config/osconfig.h" + +#ifdef WITH_ZLIB + +#include "dcmtk/dcmdata/dcostrma.h" /* for DcmOutputFilter */ + +BEGIN_EXTERN_C +#include +END_EXTERN_C + +/** global flag defining the compression level for zlib (deflate) compression. + * Legal values are 0..9. Default is Z_DEFAULT_COMPRESSION which is defined + * to be 6 for the current zlib implementation. + */ +extern DCMTK_DCMDATA_EXPORT OFGlobal dcmZlibCompressionLevel; + +/** zlib compression filter for output streams + */ +class DCMTK_DCMDATA_EXPORT DcmZLibOutputFilter: public DcmOutputFilter +{ +public: + + /// default constructor + DcmZLibOutputFilter(); + + /// destructor + virtual ~DcmZLibOutputFilter(); + + /** returns the status of the consumer. Unless the status is good, + * the consumer will not permit any operation. + * @return status, true if good + */ + virtual OFBool good() const; + + /** returns the status of the consumer as an OFCondition object. + * Unless the status is good, the consumer will not permit any operation. + * @return status, EC_Normal if good + */ + virtual OFCondition status() const; + + /** returns true if the consumer is flushed, i.e. has no more data + * pending in it's internal state that needs to be flushed before + * the stream is closed. + * @return true if consumer is flushed, false otherwise + */ + virtual OFBool isFlushed() const; + + /** returns the minimum number of bytes that can be written with the + * next call to write(). The DcmObject write methods rely on avail + * to return a value > 0 if there is no I/O suspension since certain + * data such as tag and length are only written "en bloc", i.e. all + * or nothing. + * @return minimum of space available in consumer + */ + virtual offile_off_t avail() const; + + /** processes as many bytes as possible from the given input block. + * @param buf pointer to memory block, must not be NULL + * @param buflen length of memory block + * @return number of bytes actually processed. + */ + virtual offile_off_t write(const void *buf, offile_off_t buflen); + + /** instructs the consumer to flush its internal content until + * either the consumer becomes "flushed" or I/O suspension occurs. + * After a call to flush(), a call to write() will produce undefined + * behaviour. + */ + virtual void flush(); + + /** determines the consumer to which the filter is supposed + * to write it's output. Once a consumer for the output filter has + * been defined, it cannot be changed anymore during the lifetime + * of the object. + * @param consumer reference to consumer, must not be circular chain + */ + virtual void append(DcmConsumer& consumer); + +private: + + /// private unimplemented copy constructor + DcmZLibOutputFilter(const DcmZLibOutputFilter&); + + /// private unimplemented copy assignment operator + DcmZLibOutputFilter& operator=(const DcmZLibOutputFilter&); + + /** writes the content of the output ring buffer + * to the next filter stage until the output ring buffer + * becomes empty or the next filter stage becomes full + */ + void flushOutputBuffer(); + + /** feed data from the given block of data to the compression + * codec until complete or the output ring buffer becomes full. + * Does not flush the output ring buffer. + * @param buf pointer to input data + * @param buflen number of bytes in buf + * @param finalize true if the current block of data constitutes + * the end of the input stream, i.e. the compression codec + * should be forced to flush its internal state. + * @return number of bytes processed + */ + offile_off_t compress(const void *buf, offile_off_t buflen, OFBool finalize); + + /** copies as much of the given block of data as possible + * in the input ring buffer + * @param buf pointer to input data + * @param buflen number of bytes in buf + * @return number of bytes copied to input ring buffer + */ + offile_off_t fillInputBuffer(const void *buf, offile_off_t buflen); + + /** feed data from the input ring buffer to the compression + * codec until complete or the output ring buffer becomes full. + * Does not flush the output ring buffer. + * @param finalize true if the content of the input ring buffer + * constitutes the end of the input stream, i.e. the compression codec + * should be forced to flush its internal state. + */ + void compressInputBuffer(OFBool finalize); + + /// pointer to consumer to which compressed output is written + DcmConsumer *current_; + + /// pointer to struct z_stream object containing the zlib status + z_streamp zstream_; + + /// status + OFCondition status_; + + /// true if the zlib object has reported Z_STREAM_END + OFBool flushed_; + + /// input ring buffer + unsigned char *inputBuf_; + + /// offset of first byte in input ring buffer + offile_off_t inputBufStart_; + + /// number of bytes in input ring buffer + offile_off_t inputBufCount_; + + /// output ring buffer + unsigned char *outputBuf_; + + /// offset of first byte in output ring buffer + offile_off_t outputBufStart_; + + /// number of bytes in output ring buffer + offile_off_t outputBufCount_; + +}; + +#endif +#endif diff --git a/dcmdata/include/dcmtk/dcmdata/dcovlay.h b/dcmdata/include/dcmtk/dcmdata/dcovlay.h new file mode 100644 index 00000000..ae340779 --- /dev/null +++ b/dcmdata/include/dcmtk/dcmdata/dcovlay.h @@ -0,0 +1,109 @@ +/* + * + * Copyright (C) 1994-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Andreas Barth + * + * Purpose: Interface of class DcmOverlayData + * + */ + +#ifndef DCOVLAY_H +#define DCOVLAY_H + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ +#include "dcmtk/dcmdata/dcvrpobw.h" + +/** a class used to represent overlay data (60xx,3000) + */ +class DCMTK_DCMDATA_EXPORT DcmOverlayData : public DcmPolymorphOBOW +{ +public: + + /** constructor + * @param tag attribute tag + * @param len length of the attribute value + */ + DcmOverlayData(const DcmTag &tag, + const Uint32 len = 0) + : DcmPolymorphOBOW(tag, len) + { + } + + /** copy constructor + * @param oldObj element to be copied + */ + DcmOverlayData(const DcmOverlayData &oldObj) + : DcmPolymorphOBOW(oldObj) + { + } + + /** destructor + */ + virtual ~DcmOverlayData() + { + } + + /** copy assignment operator + * @param obj element to be copied + */ + DcmOverlayData &operator=(const DcmOverlayData &obj) + { + DcmPolymorphOBOW::operator=(obj); + return *this; + } + + /** clone method + * @return deep copy of this object + */ + virtual DcmObject *clone() const + { + return new DcmOverlayData(*this); + } + + /** Virtual object copying. This method can be used for DcmObject + * and derived classes to get a deep copy of an object. Internally + * the assignment operator is called if the given DcmObject parameter + * is of the same type as "this" object instance. If not, an error + * is returned. This function permits copying an object by value + * in a virtual way which therefore is different to just calling the + * assignment operator of DcmElement which could result in slicing + * the object. + * @param rhs - [in] The instance to copy from. Has to be of the same + * class type as "this" object + * @return EC_Normal if copying was successful, error otherwise + */ + virtual OFCondition copyFrom(const DcmObject &rhs) + { + if (this != &rhs) + { + if (rhs.ident() != ident()) return EC_IllegalCall; + *this = OFstatic_cast(const DcmOverlayData &, rhs); + } + return EC_Normal; + } + + /** return identifier for this class. Every class derived from this class + * returns a unique value of type enum DcmEVR for this call. This is used + * as a "poor man's RTTI" to correctly identify instances derived from + * this class even on compilers not supporting RTTI. + * @return type identifier of this class + */ + virtual DcmEVR ident() const + { + return EVR_OverlayData; + } +}; + +#endif diff --git a/dcmdata/include/dcmtk/dcmdata/dcpath.h b/dcmdata/include/dcmtk/dcmdata/dcpath.h new file mode 100644 index 00000000..e6a61a6b --- /dev/null +++ b/dcmdata/include/dcmtk/dcmdata/dcpath.h @@ -0,0 +1,520 @@ +/* + * + * Copyright (C) 2008-2012, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Michael Onken + * + * Purpose: Class declarations for accessing DICOM dataset structures (items, + * sequences and leaf elements via string-based path access. + * + */ + +#ifndef DCPATH_H +#define DCPATH_H + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/dcmdata/dcdatset.h" + + +/** Class representing a node in DcmPath. A node contains just + * a pointer to a DcmObject (e.g. a sequence or an item). Additionally + * an item number is stored which also makes sense in case that the + * object pointed to is an item. The item number is necessary because + * when having only a pointer to a DcmItem there is no way to find out + * at which position the item actually has in the surrounding sequence. + */ +class DCMTK_DCMDATA_EXPORT DcmPathNode +{ + +public: + + /** Constructor. Creates empty path node. + */ + DcmPathNode() : m_obj(NULL), m_itemNo(0) {} + + /** Constructor. Creates search node from object pointer and item number. + * @param obj [in] The object the search node points to. The memory of the + * given DICOM object is not handled by the node itself but + * must be handled (i.e. freed) from outside. + * @param itemNo [in] The item number that should be set. Only relevant + * if obj parameter contains an item + */ + DcmPathNode(DcmObject* obj, Uint32 itemNo) : m_obj(obj), m_itemNo(itemNo) {} + + /** Destructor. Nothing to do, the DICOM object is not freed automatically! + */ + ~DcmPathNode() { } + + /// Pointer to object this search node points to + DcmObject* m_obj; + + /// The item number of the item in m_obj; only useful if m_obj is an item + Uint32 m_itemNo; + +private: + + /** Private undefined copy constructor + */ + DcmPathNode(const DcmPathNode& rhs); + + /** Private undefined assignment operator + */ + DcmPathNode& operator=(const DcmPathNode& arg); +}; + + +/** Class representing a path of DICOM objects. A path is a "way" through + * a DICOM dataset, i.e. it starts e.g. with an item, followed by a sequence + * originally contained in this item. The sequence then could be followed by + * another item which is part of the sequence and so on. Thus the path + * should be well-formed, but if it is created manually (e.g. using append()) + * there is no corresponding checking. + */ +class DCMTK_DCMDATA_EXPORT DcmPath +{ + +public: + + /** Constructor, creates an empty search result + */ + DcmPath(); + + /** Constructor, creates a search result from a list of search nodes. + * @param currentPath [in] The list of search nodes representing a + * "path" through a DICOM dataset + */ + DcmPath(const OFList& currentPath); + + /** Appends a search node at the end of the search result path. It is not + * checked whether the resulting path is still valid. + * @param node [in] The node to append. + * + */ + void append(DcmPathNode* node); + + /** Removes last path node from path. Also frees memory of path node + * but does _not_ free memory of the underlying DICOM item or element. + * @return none + */ + void deleteBackNode(); + + /** Returns iterator pointing to first path component. + * @return Iterator to first path node. + */ + OFListIterator(DcmPathNode*) begin(); + + /** Returns last path component. + * @return The last path component, NULL if none exists. + */ + DcmPathNode* back(); + + /** Returns iterator pointing to last path component. + * @return Iterator to last path node. + */ + OFListIterator(DcmPathNode*) end(); + + /** Returns number of path components. + * @return The number of path components + */ + Uint32 size() const; + + /** Returns whether path is empty, ie does not contain any path nodes + * @return OFTrue, if path is empty, OFFalse otherwise + */ + OFBool empty() const; + + /** Returns a string representation of the path, + * e.g.\ "SourceImageSequence[0].ReferencedSOPInstanceUID" + * @return String representing path + */ + OFString toString() const; + + /** Returns whether the path contains tags of a given group. + * Might be useful for looking after (unwanted) meta header tags etc. + * @param groupNo [in] The group number to look for + * @return OFTrue if group number is found in path, OFFalse otherwise + */ + OFBool containsGroup(const Uint16 groupNo) const; + + /** Returns a string representation of each path node separately. + * Tags are represented as numbers surrounded by braces "(gggg,eeee)", + * not dictionary names. Items are represented by a number or wildcard + * in square brackets, eg. "[12]" or "[*]". + * @param path The path to parse into different nodes + * @param result [out] List containing the resulting strings + * @return none + */ + static OFCondition separatePathNodes(const OFString& path, OFList& result); + + /** Helper function for findOrCreatePath(). Parses an item number from + * the beginning of the path string. The item number must be positive, + * starting with 0. + * The path must start like "[itemnumber]...". + * @param path [in/out] The path starting with the item number in square + * brackets, e.g.\ "[3]". The parsed item number and a + * potentially following "." are removed from the path + * @param itemNo [out] The parsed item number. If a wildcard was parsed, + * this output parameter is not set at all. + * @param wasWildcard [out] Is set to OFTrue, if wildcard was parsed + * (instead of concrete item number). + * @return EC_Normal, if concrete item number or wildcard was parsed + */ + static OFCondition parseItemNoFromPath(OFString& path, // inout + Uint32& itemNo, // out + OFBool& wasWildcard); // out + + /** Function that parses a tag from the beginning of a path string. + * The tag has to be either in numeric format, e.g. "(0010,0010)" or + * a dictionary name, e.g. "PatientName". If successful, the + * parsed tag is removed from the path string. + * @param path [in/out] The path string, starting with the attribute + * to parse + * @param tag [out] The tag parsed + * @return EC_Normal if successful, error code otherwise + */ + static OFCondition parseTagFromPath(OFString& path, // inout + DcmTag& tag); // out + + /** Desctructor, cleans up memory of path nodes. Does not delete + * the DcmObjects the nodes point to (this is also not done + * by the desctructor of the path nodes, so the caller is responsible + * for freeing any related DICOM objects. + */ + ~DcmPath(); + +private: + + /// Internal list representing the nodes in the path. + OFList m_path; + + /** Private undefined copy constructor + */ + DcmPath(const DcmPath& rhs); + + /** Private undefined assignment operator + */ + DcmPath& operator=(const DcmPath& arg); +}; + + +class DCMTK_DCMDATA_EXPORT DcmPathProcessor +{ + +public: + + /** Constructor, creates an empty search object. + */ + DcmPathProcessor(); + + /** Sets whether searching/creating paths will support wildcard for + * items. If set to false, any path operation with item wildcard characters + * will return an error. + * @param supported [in] If true, wildcard are enabled (default) + * If false, item wildcard support is disabled. + */ + void setItemWildcardSupport(const OFBool supported); + + + /** Enables (class default: enabled) or disables checking of private + * reservations when inserting private tags. If enabled and a private + * tag is created that has no private reservation, an error is returned. + * If disabled, it is possible to insert private tags that do not have + * a reservation in the corresponding item/dataset. + * @param doChecking [in] OFTrue enables reservation checking, + * OFFalse disables it. + */ + void checkPrivateReservations(const OFBool doChecking); + + /** Checks in item, whether a private reservation for a given + * tag key exists. + * @param item [in] The item to search in + * @param tagKey [in/out] The tag to be checked. + * @param privateCreator [in] The private creator to check for (if known, + * can be left empty) + * @return Return EC_Normal if reservation checking was successful. + * Otherwise an error code is returned. + */ + static OFCondition checkPrivateTagReservation(DcmItem* item, + const DcmTagKey& tagKey, + const OFString& privateCreator = ""); + + /** Checks in item, whether a private reservation for a given + * tag key. If so, a dictionary lookup is performed and the VR and private + * creator of the tag is updated correspondingly. + * @param item [in] The item to search in + * @param tag [in/out] The tag to be checked. Will be updated with VR and + * private creator. + * @param privateCreator [in] The private creator to check for (if known, + * can be left empty) + * @return Return EC_Normal if reservation checking and updating the + * tag was successful. Otherwise an error code is returned. + */ + static OFCondition checkPrivateTagReservation(DcmItem* item, + DcmTag& tag, + const OFString& privateCreator = ""); + + /** Function that allows for finding and/or inserting a hierarchy of items + * and attributes as defined by a path string; also returns a list of + * pointers for each successfully found or inserted paths. Every list + * contains pointers pointing to all the objects along the path + * starting from the object given as parameter. The pointer to the + * starting object will not be part of the result. + * + * In principle, the path string must have the following format (in + * arbitrary depth). Note that for searching a sequence, the example + * below would start with [ITEMNO] instead: + * SEQUENCE[ITEMNO].SEQUENCE[ITEMNO].ATTRIBUTE + * . ITEMNO must be a positive integer starting with 0. + * SEQUENCE and ATTRIBUTE must be a tag, written e.g. + * "(0010,0010)" or as a dictionary name, e.g. "PatientName". If the + * path cannot be fully created (see option createIfNecessary), any + * possibly object changes are reverted. So a path is either fully created + * or no path component is created at all. The result can be obtained + * by calling the getResults() function. + * + * Example: The path + * "ContentSequence[4].(0040,a043)[0].CodeValue" selects the Content + * Sequence in the given object, therein the 5th item, therein the "Concept + * Name Code Sequence" denoted by (0040,a043), therein the first item + * and finally therein the tag "Code Value". + * The resulting object list should (if success is returned) contain + * 1 result, consisting of a list with 5 pointers to 5 objects in the order + * in their logical order as they occur in the path string + * (in total 2 sequences, 2 items, and one leaf attribute). + * @param obj [in] The object to search (or create) a path in + * @param path [in] The path either starting with an attribute (either a + * sequence or a a leaf attribute as a dicitionary name or + * tag) or starting with an item + * @param createIfNecessary [in] If set, all missing objects found + * in the path string are created. If not set, + * only existing paths can be accessed and + * no new attribute or item is created. + * @return EC_Normal if successful, error code otherwise. + */ + OFCondition findOrCreatePath(DcmObject* obj, + const OFString& path, + OFBool createIfNecessary = OFFalse); + + /** Function that allows for deleting elements and items from + * a DICOM object tree. + * In principle, the path string must have the following format (in + * arbitrary depth). Note that for searching in a sequence, the example + * below would start with [ITEMNO] instead: + * SEQUENCE[ITEMNO].SEQUENCE[ITEMNO].ATTRIBUTE + * . ITEMNO must be a positive integer starting with 0. + * SEQUENCE and ATTRIBUTE must be a tag, written e.g. + * "(0010,0010)" or as a dictionary name, e.g. "PatientName". + * + * Example: The path + * "ContentSequence[4].(0040,a043)[0].CodeValue" selects the Content + * Sequence in the given object, therein the 5th item, therein the "Concept + * Name Code Sequence" denoted by (0040,a043), therein the first item + * and finally therein the tag "Code Value". Only "Code Value" will be + * deleted by the function. + * @param obj [in] The object to delete attribute or item from + * @param path [in] The path either starting with an attribute (either a + * sequence or a a leaf attribute as a dicitionary name or + * tag) or starting with an item + * @param numDeleted [out] Number of deleted attributes/items + * @return EC_Normal if successful, error code otherwise. If the desired + * attribute/item was not found, EC_TagNotFound is returned. + */ + OFCondition findOrDeletePath(DcmObject* obj, + const OFString& path, + Uint32& numDeleted); + + /** Returns the results from the search / creation call. + * @param searchResults [out] The resulting paths that were created/searched + * Note that the memory of the search results is freed + * automatically by the destructor and must not be freed + * by the caller. + * @return Number of results returned + */ + Uint32 getResults(OFList& searchResults); + + + /** Helper function that applies a specified "override key" in path syntax + * to the given dataset. The name "override" indicates that these keys have + * higher precedence than identical keys in a request dataset that might + * possibly read from a DICOM query file. + * @param dataset [in/out] the dataset (e.g.\ query keys) the override key is + * applied to. Must be non-NULL. + * @param overrideKey [in] the override key in path syntax (see class DcmPath). + * Also the path can end with a value assignment, e.g. + * "PatientName=Doe^John". An empty (or missing value) will + * not be ignored but will be written as empty to the + * attribute (if not a sequence or item). + * @return EC_Normal if adding was successful, error code otherwise + */ + OFCondition applyPathWithValue(DcmDataset* dataset, + const OFString& overrideKey); + + /** Deconstructor, cleans up memory that was allocated for any + * search results. + */ + ~DcmPathProcessor(); + +protected: + + /** Function that allows for finding and/or inserting a hierarchy of items + * and attributes as defined by a path string; also returns a list of + * pointers for each successfully found or inserted paths. Every list + * contains pointers pointing to all the objects along the path + * starting from the object given as parameter. The pointer to the + * starting object will not be part of the result. + * + * In principle, the path string must have the following format (in + * arbitrary depth). + * SEQUENCE[ITEMNO].SEQUENCE[ITEMNO].ATTRIBUTE + * . ITEMNO must be a positive integer starting with 0. + * SEQUENCE and ATTRIBUTE must be a tag, written e.g. + * "(0010,0010)" or as a dictionary name, e.g. "PatientName". If the + * path cannot be fully created (see option createIfNecessary), any + * possibly object changes are reverted. So a path is either fully created + * or no path component is created at all. The result can be obtained + * by calling the getResults() function. + * + * Example: The path + * "ContentSequence[4].(0040,a043)[0].CodeValue" selects the Content + * Sequence in the given item, therein the 5th item, therein the "Concept + * Name Code Sequence" denoted by (0040,a043), therein the first item + * and finally therein the tag "Code Value". + * The resulting object list should (if success is returned) contain + * 1 result, consisting of a list with 5 pointers to 5 objects in the order + * in their logical order as they occur in the path string + * (in total 2 sequences, 2 items, and one leaf attribute). + * @param item [in] The object to search (or create) a path in + * @param path [in] The path starting with an attribute (either a + * sequence or a a leaf attribute) as a dicitionary name or + * tag. The parsed attribute is removed from the path string. + * @return EC_Normal if successful, error code otherwise. + */ + OFCondition findOrCreateItemPath(DcmItem* item, + OFString& path); + + /** Function that allows for finding and/or inserting a hierarchy of items + * and attributes as defined by a path string; also returns a list of + * pointers for each successfully found or inserted paths. Every list + * contains pointers pointing to all the objects along the path + * starting from the object given as parameter. The pointer to the + * starting object will not be part of the result. + * + * In principle, the path string must have the following format (in + * arbitrary depth). + * [ITEMNO].SEQUENCE[ITEMNO].ATTRIBUTE + * . ITEMNO must be a positive integer starting with 0. + * SEQUENCE and ATTRIBUTE must be a tag, written e.g. + * "(0010,0010)" or as a dictionary name, e.g. "PatientName". If the + * path cannot be fully created (see option createIfNecessary), any + * possibly object changes are reverted. So a path is either fully created + * or no path component is created at all. The result can be obtained + * by calling the getResults() function. + * + * Example: The path + * "[4].(0040,a043)[0].CodeValue" selects the 5th item in the given + * sequence, therein the "Concept Name Code Sequence" denoted by + * (0040,a043), therein the first item and finally therein the + * tag "Code Value". + * The resulting object list should (if success is returned) contain + * 1 result, consisting of a list with 4 pointers to 4 objects in the order + * in their logical order as they occur in the path string + * (in total 1 sequence, 2 items, and one leaf element). + * @param seq [in] The object to search (or create) a path in + * @param path [in] The path starting with an item. The parsed item number + * (e.g. "[0]") is removed from the path string. + * @return EC_Normal if successful, error code otherwise. + */ + OFCondition findOrCreateSequencePath(DcmSequenceOfItems* seq, + OFString& path); + + /** Helper function that looks at the last node in a given path and deletes + * the corresponding DICOM object. Does not delete the path node itself: + * That is done by the calling function, findOrCreateItemPath(). + * @param objSearchedIn [in/out] The object the given path starts in. + * @param path [in/out] The complete path to the DICOM object to delete + * @param toDelete [in/out] The path node to delete. This node must be + * identical to the last node in the path parameter. Also + * the node must represent a DICOM sequence or leaf element, + * not an item. However, because it is isolated already by + * the calling function, it is provided here for convenience. + */ + static OFCondition deleteLastElemFromPath(DcmObject* objSearchedIn, + DcmPath* path, + DcmPathNode* toDelete); + + /** Helper function that looks at the last node in a given path and deletes + * the corresponding DICOM object. Does not delete the path node itself: + * That is done by the calling function, findOrCreateItemPath(). + * @param objSearchedIn [in/out] The object the given path starts in. + * @param path [in/out] The complete path to the DICOM object to delete + * @param toDelete [in/out] The path node to delete. This node must be + * identical to the last node in the path parameter. Also + * the node must represent a DICOM item, not a sequence + * However, because it is isolated already by the calling + * function, it is provided here for convenience. + */ + static OFCondition deleteLastItemFromPath(DcmObject* objSearchedIn, + DcmPath* path, + DcmPathNode* toDelete); + + /** Returns the private reservation tag key for a given private tag + * @param privateKey [in] The private key to calculate reservation tag for + * @return The reservation key. If given key is not private or an error, + * return DCM_UndefinedTagKey. If the given key is a reservation + * itself, it is directly returned. + */ + static DcmTagKey calcPrivateReservationTag(const DcmTagKey& privateKey); + + /** Cleans up memory that was allocated for any search results. + * Called when a new search is started or during object destruction. + * The DICOM data all freed paths and path nodes point to, is not + * touched, i.e. all memory to the DICOM objects pointed to must be + * freed from outside. Processing options like checking for private + * reservations and so on are not reset to default values but + * keep valid. + */ + void clear(); + +private: + + /// Internal list that is during search for keeping track of current path + OFList m_currentPath; + + /// Internal list that represents the search results found + OFList m_results; + + /// Denotes whether missing items/sequences/attributes should be + /// automatically inserted when using findAndCreate routines + OFBool m_createIfNecessary; + + /// If enabled (default), any insertions of private tags will fail, if no + /// corresponding reservation exists in the underlying item + OFBool m_checkPrivateReservations; + + /// Denotes, whether a path is accepted that contains wildcards. + /// If false, then any search containing wildcards will return an error. + OFBool m_itemWildcardsEnabled; + + /** Private undefined copy constructor + */ + DcmPathProcessor(const DcmPathProcessor& rhs); + + /** Private undefined assignment operator + */ + DcmPathProcessor& operator=(const DcmPathProcessor& arg); +}; + + +#endif // DCPATH_H diff --git a/dcmdata/include/dcmtk/dcmdata/dcpcache.h b/dcmdata/include/dcmtk/dcmdata/dcpcache.h new file mode 100644 index 00000000..c1d87cdb --- /dev/null +++ b/dcmdata/include/dcmtk/dcmdata/dcpcache.h @@ -0,0 +1,115 @@ +/* + * + * Copyright (C) 1994-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Marco Eichelberg + * + * Purpose: class DcmPrivateTagCache + * + */ + +#ifndef DCPCACHE_H +#define DCPCACHE_H + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ +#include "dcmtk/ofstd/oftypes.h" /* for OFBool */ +#include "dcmtk/ofstd/oflist.h" /* for OFList */ +#include "dcmtk/ofstd/ofstring.h" /* for OFString */ +#include "dcmtk/dcmdata/dctagkey.h" /* for DcmTagKey */ + +class DcmObject; + +/** class handling one entry of the Private Tag Cache List + */ +class DCMTK_DCMDATA_EXPORT DcmPrivateTagCacheEntry +{ +public: + /** constructor + * @param tk tag key for private creator element + * @param pc private creator name, must not be NULL or empty string + */ + DcmPrivateTagCacheEntry(const DcmTagKey& tk, const char *pc); + + /// destructor + virtual ~DcmPrivateTagCacheEntry(); + + /** returns the private creator name + */ + const char *getPrivateCreator() const; + + /** checks if this element is the private creator for the element + * with the given tag key + * @param tk tag key to check + * @return OFTrue if this element contains the matching private creator, + * OFFalse otherwise. + */ + OFBool isPrivateCreatorFor(const DcmTagKey& tk) const; + +private: + + /// private undefined copy constructor + DcmPrivateTagCacheEntry(const DcmPrivateTagCacheEntry&); + + /// private undefined copy assignment operator + DcmPrivateTagCacheEntry& operator=(const DcmPrivateTagCacheEntry&); + + /// the tag key of the private creator element + DcmTagKey tagKey; + + /// the private creator name + OFString privateCreator; +}; + + +/** this class implements a cache of Private Creator elements + * and corresponding reserved tag numbers. + */ +class DCMTK_DCMDATA_EXPORT DcmPrivateTagCache +{ +public: + /// default constructor + DcmPrivateTagCache(); + + /// destructor + virtual ~DcmPrivateTagCache(); + + /// resets the cache to default-constructed state + void clear(); + + /** looks up the private creator name for the given private tag + * @param tk private tag to check + * @return private creator name if found, NULL otherwise. + */ + const char *findPrivateCreator(const DcmTagKey& tk) const; + + /** updates the private creator cache with the given object. + * If the object points to a private creator element, + * the tag key and creator code are added to the cache. + * Otherwise, the cache remains unmodified. + */ + void updateCache(DcmObject *dobj); + +private: + + /// private undefined copy constructor + DcmPrivateTagCache(const DcmPrivateTagCache&); + + /// private undefined copy assignment operator + DcmPrivateTagCache& operator=(const DcmPrivateTagCache&); + + /// the list + OFList list_; +}; + +#endif diff --git a/dcmdata/include/dcmtk/dcmdata/dcpixel.h b/dcmdata/include/dcmtk/dcmdata/dcpixel.h new file mode 100644 index 00000000..25a296cb --- /dev/null +++ b/dcmdata/include/dcmtk/dcmdata/dcpixel.h @@ -0,0 +1,606 @@ +/* + * + * Copyright (C) 1994-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Andreas Barth + * + * Purpose: Interface of class DcmPixelData + * + */ + +#ifndef DCPIXEL_H +#define DCPIXEL_H + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ +#include "dcmtk/dcmdata/dcvrpobw.h" +#include "dcmtk/ofstd/oflist.h" + +class DcmCodec; +class DcmCodecList; +class DcmItem; +class DcmPixelData; +class DcmPixelSequence; +class DcmRepresentationEntry; +class DcmStack; + +/** abstract base class for codec representation parameter sets. + * A codec parameter set subclass is implemented for each codec and passed to the codec + * by the encode() and decode() routines. It is supposed to contain data that may vary + * between compressed image representations using the same transfer syntax, + * for example the quality factor or compression factor for lossy compression. + */ +class DCMTK_DCMDATA_EXPORT DcmRepresentationParameter +{ +public: + /// default constructor + DcmRepresentationParameter() {} + + /// copy constructor + DcmRepresentationParameter(const DcmRepresentationParameter&) {} + + /// destructor + virtual ~DcmRepresentationParameter() {} + + /** this methods creates a copy of type DcmRepresentationParameter * + * it must be overweritten in every subclass. + * @return copy of this object + */ + virtual DcmRepresentationParameter *clone() const = 0; + + /** returns the class name as string. + * can be used in operator== as poor man's RTTI replacement. + */ + virtual const char *className() const = 0; + + /** compares an object to another DcmRepresentationParameter. + * Implementation must make sure that classes are comparable. + * @param arg representation parameter to compare with + * @return true if equal, false otherwise. + */ + virtual OFBool operator==(const DcmRepresentationParameter &arg) const = 0; +}; + + +/** an object of this class maintains one compression "version" + * of a PixelData element within a DICOM dataset. There can be + * multiple compressed versions in parallel, with different + * transfer syntaxes (compression algorithms) or representation + * parameters (e.g. compression factors). + */ +class DCMTK_DCMDATA_EXPORT DcmRepresentationEntry +{ + /** constructor + * @param rt transfer syntax + * @param rp pointer to representation parameter on heap, + * will be deleted when this object destructs. + * @param pixSeq pointer to pixel sequence on heap, + * will be deleted when this object destructs. + */ + DcmRepresentationEntry( + const E_TransferSyntax rt, + const DcmRepresentationParameter * rp, + DcmPixelSequence * pixSeq); + + /// copy constructor + DcmRepresentationEntry(const DcmRepresentationEntry &oldEntry); + + /// destructor + ~DcmRepresentationEntry(); + + /// comparison operator + OFBool operator==(const DcmRepresentationEntry& x) const; + + /// comparison operator + OFBool operator!=(const DcmRepresentationEntry & x) const + { + return !(*this == x); + } + +private: + /// private undefined copy assignment operator + DcmRepresentationEntry &operator=(const DcmRepresentationEntry &); + + /// transfer syntax + E_TransferSyntax repType; + + /// representation parameter for this pixel sequence + DcmRepresentationParameter * repParam; + + /// the compressed pixel sequence itself + DcmPixelSequence * pixSeq; + + friend class DcmPixelData; +}; + +/// list of DcmRepresentationEntry objects +typedef OFList DcmRepresentationList; + +/// iterator for list of DcmRepresentationEntry objects +typedef OFListIterator(DcmRepresentationEntry *) DcmRepresentationListIterator; + +/// const iterator for list of DcmRepresentationEntry objects +typedef OFListConstIterator(DcmRepresentationEntry *) DcmRepresentationListConstIterator; + +/** The class DcmPixelData stores different pixel representations identified by + * a type (the transfer syntax) and some representation parameters + * The three unencapsulated transfer syntaxes belong to the same pixel + * representation. + * A type (or transfer syntax) conforms to a representation if + * the type and the representation type are equal or both are unencapsulated. + * If this is valid for the representation read or set by chooseRepresentation + * then this representation is the conforming representation. + * else a representation with the default parameter set defined in the + * codec is the conforming representation. + */ +class DCMTK_DCMDATA_EXPORT DcmPixelData : public DcmPolymorphOBOW +{ +private: + friend class DcmRepresentationEntry; + + /// List of representations of pixel data + DcmRepresentationList repList; + + /// Iterator to the last dummy element in representation lis + DcmRepresentationListIterator repListEnd; + + /// Iterator to the original representation. if an uncompressed + /// representation is used the iterator points to repList.end() + DcmRepresentationListIterator original; + + /// current list element for some operations + DcmRepresentationListIterator current; + + /// shows if an unecapsulated representation is stored + OFBool existUnencapsulated; + + /** this flag indicates that this pixel data element will be written + * in uncompressed (defined length) format even if the dataset + * itself is written in a compressed syntax where pixel data is normally + * written in encapsulated (undefined length) format. + * By default this flag is false, unless the dataset was read in an + * encapsulated transfer syntax and this pixel data element was already + * present in uncompressed format. + */ + OFBool alwaysUnencapsulated; + + /// value representation of unencapsulated data + DcmEVR unencapsulatedVR; + + /// in write function: pointer to current pixel sequence + DcmPixelSequence * pixelSeqForWrite; + + /** check if this element should be written unencapsulated, even though an + * encapsulated transfer syntax is used. In other words, this checks if + * this pixel data element is on the main level on the dataset or not. + * @param xfer the transfer syntax that should be used + */ + OFBool writeUnencapsulated(const E_TransferSyntax xfer); + + /** This function removes all pixel representations from the list + * of pixel representations except the one which was passed. Note + * that if parameter leaveInList equals repListEnd, all representations + * will be removed from the list. + * @param leaveInList Iterator to a representation which shall not + * be removed from the list of representations. + */ + void clearRepresentationList( + DcmRepresentationListIterator leaveInList); + + /** find a conforming representation in the list of + * encapsulated representations + */ + OFCondition findConformingEncapsulatedRepresentation( + const DcmXfer & repType, + const DcmRepresentationParameter * repParam, + DcmRepresentationListIterator & result); + + /** find a representation entry and return an iterator to the found entry + * or the next element in the list. The condition returned can be EC_Normal + * if such an entry is found or EC_RepresentationNotFound. The pixSeq + * attribute in findEntry can be NULL, it is not needed for the find + * operation! + */ + OFCondition findRepresentationEntry( + const DcmRepresentationEntry & findEntry, + DcmRepresentationListIterator & result); + + /** insert or replace a representation entry in the list + */ + DcmRepresentationListIterator insertRepresentationEntry( + DcmRepresentationEntry * repEntry); + + /** decode representation to unencapsulated format + */ + OFCondition decode( + const DcmXfer & fromType, + const DcmRepresentationParameter * fromParam, + DcmPixelSequence * fromPixSeq, + DcmStack & pixelStack); + + /** encode to encapsulated format + */ + OFCondition encode( + const DcmXfer & fromType, + const DcmRepresentationParameter * fromParam, + DcmPixelSequence * fromPixSeq, + const DcmXfer & toType, + const DcmRepresentationParameter *toParam, + DcmStack & pixelStack); + + /** set the current VR, which is always OB if the currently selected + * pixel representation is compressed, and may be OB or OW for uncompressed. + */ + void recalcVR() + { + if (current == repList.end()) setTagVR(unencapsulatedVR); + else setTagVR(EVR_OB); + } + +public: + + /** constructor + * @param tag attribute tag + * @param len length of the attribute value + */ + DcmPixelData(const DcmTag & tag, const Uint32 len = 0); + + /** copy constructor + * @param pixelData element to be copied + */ + DcmPixelData(const DcmPixelData & pixelData); + + /// destructor + virtual ~DcmPixelData(); + + /** copy assignment operator + * @param obj element to be copied + */ + DcmPixelData &operator=(const DcmPixelData &obj); + + /** clone method + * @return deep copy of this object + */ + virtual DcmObject *clone() const + { + return new DcmPixelData(*this); + } + + /** Virtual object copying. This method can be used for DcmObject + * and derived classes to get a deep copy of an object. Internally + * the assignment operator is called if the given DcmObject parameter + * is of the same type as "this" object instance. If not, an error + * is returned. This function permits copying an object by value + * in a virtual way which therefore is different to just calling the + * assignment operator of DcmElement which could result in slicing + * the object. + * @param rhs - [in] The instance to copy from. Has to be of the same + * class type as "this" object + * @return EC_Normal if copying was successful, error otherwise + */ + virtual OFCondition copyFrom(const DcmObject& rhs); + + /** set/change the current value representation of the uncompressed image representation, if any + * @param vr new value representation to be set. All VRs except for OW (Other + * Word String) are treated as 8 bit data (OB). This is particularily useful + * for unknown (UN) or unsupported VRs. + * @return status status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setVR(DcmEVR vr); + + /** return identifier for this class. Every class derived from this class + * returns a unique value of type enum DcmEVR for this call. This is used + * as a "poor man's RTTI" to correctly identify instances derived from + * this class even on compilers not supporting RTTI. + * @return type identifier of this class + */ + virtual DcmEVR ident() const { return EVR_PixelData; } + + /** print all elements of the item to a stream + * @param out output stream + * @param flags optional flag used to customize the output (see DCMTypes::PF_xxx) + * @param level current level of nested items. Used for indentation. + * @param pixelFileName optional filename used to write the raw pixel data file + * @param pixelCounter optional counter used for automatic pixel data filename creation + */ + virtual void print(STD_NAMESPACE ostream&out, + const size_t flags = 0, + const int level = 0, + const char *pixelFileName = NULL, + size_t *pixelCounter = NULL); + + /** tests if it is possible to write a specific representation + * Only existing representations are considered, since this + * method does not create a representation. + */ + virtual OFBool canWriteXfer(const E_TransferSyntax newXfer, + const E_TransferSyntax oldXfer); + + /** returns length of representation conforming to the + * transfer syntax with tag, vr, ... It does not create a + * representation. If no conforming representation exists an + * error code is set and 0 returned. + */ + virtual Uint32 calcElementLength(const E_TransferSyntax xfer, + const E_EncodingType enctype); + + /** returns length of representation value field conforming to + * given transfer syntax. It does not create a representation. + * If no conforming representation exists, an error code is set + * and 0 returned. + */ + virtual Uint32 getLength( + const E_TransferSyntax xfer = EXS_LittleEndianImplicit, + const E_EncodingType enctype = EET_UndefinedLength); + + /** initialize the transfer state of this object. This method must be called + * before this object is written to a stream or read (parsed) from a stream. + */ + virtual void transferInit(); + + /** This function reads the data value of a pixel data attribute + * which is captured in the input stream and captures this + * information in this. This function takes into account, if the + * pixel data is captured in native (uncompressed) or encapsulated + * (compressed) format. + * @param inStream The stream which contains the information. + * @param ixfer The transfer syntax which was used to encode the + * information in inStream. + * @param glenc Encoding type for group length; specifies what + * will be done with group length tags. + * @param maxReadLength Maximum read length for reading an attribute value. + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition read(DcmInputStream & inStream, + const E_TransferSyntax ixfer, + const E_GrpLenEncoding glenc = EGL_noChange, + const Uint32 maxReadLength = DCM_MaxReadLength); + + /** writes a representation conforming to the transfer syntax + * It does not create a representation. If no conforming + * representation exists, an error code is returned. + * The written representation is the new current representation + */ + virtual OFCondition write( + DcmOutputStream &outStream, + const E_TransferSyntax oxfer, + const E_EncodingType enctype, + DcmWriteCache *wcache); + + /** write object in XML format + * @param out output stream to which the XML document is written + * @param flags optional flag used to customize the output (see DCMTypes::XF_xxx) + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition writeXML(STD_NAMESPACE ostream&out, + const size_t flags = 0); + + /** special write method for creation of digital signatures + * @param outStream DICOM output stream + * @param oxfer output transfer syntax + * @param enctype encoding types (undefined or explicit length) + * @param wcache pointer to write cache object, may be NULL + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition writeSignatureFormat( + DcmOutputStream &outStream, + const E_TransferSyntax oxfer, + const E_EncodingType enctype, + DcmWriteCache *wcache); + + /** this method loads all attribute values maintained by this object and + * all sub-objects (in case of a container such as DcmDataset) into memory. + * After a call to this method, the file from which a dataset was read may safely + * be deleted or replaced. For large files, this method may obviously allocate large + * amounts of memory. + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition loadAllDataIntoMemory(void); + + + /** finalize the transfer state of this object. This method must be called + * when reading/writing this object from/to a stream has been completed. + */ + virtual void transferEnd(); + + /** test if it is possible to choose the representation in the parameters + */ + OFBool canChooseRepresentation( + const E_TransferSyntax repType, + const DcmRepresentationParameter * repParam); + + /** choose a specific representation. if representation does not exist + * it is created (if possible). + * if repParam is zero, a representation is chosen or created that + * is equal to the default representation parameters + */ + OFCondition chooseRepresentation( + const E_TransferSyntax repType, + const DcmRepresentationParameter * repParam, + DcmStack & stack); + + /** Inserts an original encapsulated representation. current and original + * representations are changed, all old representations are deleted + */ + void putOriginalRepresentation( + const E_TransferSyntax repType, + const DcmRepresentationParameter * repParam, + DcmPixelSequence * pixSeq); + + /**insert an original unencapsulated + * representation. current and original representations are changed, + * all old representations are deleted. The array data is copied. + */ + virtual OFCondition putUint8Array( + const Uint8 * byteValue, + const unsigned long length); + + /** insert an original unencapsulated + * representation. current and original representations are changed, + * all old representations are deleted. The array data is copied. + */ + virtual OFCondition putUint16Array( + const Uint16 * wordValue, + const unsigned long length); + + /** create an empty Uint8 array of given number of words and set it + */ + virtual OFCondition createUint8Array( + const Uint32 numBytes, + Uint8 * & bytes); + + /** create an empty Uint16 array of given number of words and set it + */ + virtual OFCondition createUint16Array( + const Uint32 numWords, + Uint16 * & words); + + /** replace the attribute value with the content of the given temporary file. + * The temporary file is not opened/loaded until the attribute value is accessed, + * very much like large attributes that remain in file during a read operation. + * @param factory a factory object that is able to create an input stream + * to the temporary file at the right location. + * @param length attribute value length, in bytes. Must be even length. + * The length is not checked against the real length of the temporary file, + * which might be written or completed after the call to this method. + * @param byteOrder byte order in the temporary file + * @return EC_Normal upon success, an error code otherwise. + */ + virtual OFCondition createValueFromTempFile( + DcmInputStreamFactory *factory, + const Uint32 length, + const E_ByteOrder byteOrder); + + /** get a specific exisiting Representation, creates no representation + * if repParam is NULL, then the representation conforming to the default + * presentationParameters (defined with the codec) is returned. + */ + OFCondition getEncapsulatedRepresentation( + const E_TransferSyntax repType, + const DcmRepresentationParameter * repParam, + DcmPixelSequence * & pixSeq); + + /** returns the representation identification (key) consisting of + * representation type and parameter of the original representation + */ + void getOriginalRepresentationKey( + E_TransferSyntax & repType, + const DcmRepresentationParameter * & repParam); + + /** returns the representation identification (key) consisting of + * representation type and parameter of the current representation + */ + void getCurrentRepresentationKey( + E_TransferSyntax & repType, + const DcmRepresentationParameter * & repParam); + + /** sets the representation identification parameter of the current + * representation + */ + OFCondition setCurrentRepresentationParameter( + const DcmRepresentationParameter * repParam); + + /** returns if a specific conforming representation exists. + */ + OFBool hasRepresentation( + const E_TransferSyntax repType, + const DcmRepresentationParameter * repParam = NULL); + + /** delete a representation. It is not possible to delete the + * original representation with this method + */ + OFCondition removeRepresentation( + const E_TransferSyntax repType, + const DcmRepresentationParameter * repParam); + + /** removes all but the original representation + */ + void removeAllButOriginalRepresentations(); + + /** removes all but the current representation + * Makes the current representation original + */ + void removeAllButCurrentRepresentations(); + + /** delete original representation and set new original representation. + * If the new representation does not exist, the original one is not + * deleted and an error code returns + */ + OFCondition removeOriginalRepresentation( + const E_TransferSyntax repType, + const DcmRepresentationParameter * repParam); + + /** set or clear the flag that indicates that this pixel data element will be + * written in uncompressed (defined length) format even if the dataset + * itself is written in a compressed syntax where pixel data is normally + * written in encapsulated (undefined length) format. By default this flag + * is false, unless the dataset was read in an encapsulated transfer syntax + * and this pixel data element was already present in uncompressed format. + * This flag should never be enabled for pixel data elements on the main dataset + * level, only for pixel data elements within the icon image sequence or some + * other "private" place. + * @param flag new value of flag + */ + void setNonEncapsulationFlag(OFBool flag); + + /** access single frame without decompressing or loading a complete + * multi-frame object. The frame is copied into the buffer passed by the caller + * which must be large enough to contain a complete frame. + * @param dataset pointer to DICOM dataset in which this pixel data object is + * located. Used to access rows, columns, samples per pixel etc. + * @param frameNo number of frame, starting with 0 for the first frame. + * @param startFragment index of the compressed fragment that contains + * all or the first part of the compressed bitstream for the given frameNo. + * Upon successful return this parameter is updated to contain the index + * of the first compressed fragment of the next frame. + * When unknown, zero should be passed. In this case the decompression + * algorithm will try to determine the index by itself, which will always + * work if frames are decompressed in increasing order from first to last, + * but may fail if frames are decompressed in random order, multiple fragments + * per frame and multiple frames are present in the dataset, and the offset + * table is empty. + * @param buffer pointer to buffer allocated by the caller. The buffer + * must be large enough for one frame of this image. + * @param bufSize size of buffer, in bytes. This number must be even so + * that the data can properly be converted to a different endianness. + * @param decompressedColorModel upon successful return, the color model + * of the decompressed image (which may be different from the one used + * in the compressed images) is returned in this parameter. + * @param cache file cache object that may be passed to multiple subsequent calls + * to this method for the same file; the file cache will then keep a file + * handle open, thus improving performance. Optional, may be NULL + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getUncompressedFrame( + DcmItem *dataset, + Uint32 frameNo, + Uint32& startFragment, + void *buffer, + Uint32 bufSize, + OFString& decompressedColorModel, + DcmFileCache *cache=NULL); + + /** determine color model of the decompressed image + * @param dataset pointer to DICOM dataset in which this pixel data object + * is located. Used to access photometric interpretation. + * @param decompressedColorModel upon successful return, the color model + * of the decompressed image (which may be different from the one used + * in the compressed images) is returned in this parameter + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getDecompressedColorModel( + DcmItem *dataset, + OFString &decompressedColorModel); +}; + +#endif diff --git a/dcmdata/include/dcmtk/dcmdata/dcpixseq.h b/dcmdata/include/dcmtk/dcmdata/dcpixseq.h new file mode 100644 index 00000000..647522b9 --- /dev/null +++ b/dcmdata/include/dcmtk/dcmdata/dcpixseq.h @@ -0,0 +1,291 @@ +/* + * + * Copyright (C) 1994-2015, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Gerd Ehlers, Andreas Barth + * + * Purpose: Interface of class DcmPixelSequence + * + */ + + +#ifndef DCPIXSEQ_H +#define DCPIXSEQ_H + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/dcmdata/dcsequen.h" +#include "dcmtk/dcmdata/dcofsetl.h" /* for class DcmOffsetList */ + + +/* +** Forward declarations +*/ + +class DcmPixelItem; + +/* +** Defines +*/ + +/// macro for the "pixel sequence" tag +#define DCM_PixelSequenceTag (DcmTag(DCM_PixelData, EVR_OB)) + + +/** this class implements a sequence of pixel items, i.e. the data structure DICOM is using + * to store compressed pixel data. The object behaves very much like a sequence, but uses + * the pixel data tag (7FE0,0010) and OB value representation with undefined length, + * and the "items" contained within the sequence are in fact pixel items (class DcmPixelItem) + * that contain no list of DICOM elements but raw compressed pixel data. + */ +class DCMTK_DCMDATA_EXPORT DcmPixelSequence : public DcmSequenceOfItems +{ +public: + + /** constructor + * @param tag attribute tag + * @param len length of the attribute value + */ + DcmPixelSequence(const DcmTag &tag, const Uint32 len = 0); + + /** copy constructor + * @param old element to be copied + */ + DcmPixelSequence(const DcmPixelSequence &old); + + /// destructor + virtual ~DcmPixelSequence(); + + /** copy assignment operator + * @param obj element to be copied + */ + DcmPixelSequence &operator=(const DcmPixelSequence &obj); + + /** clone method + * @return deep copy of this object + */ + virtual DcmObject *clone() const + { + return new DcmPixelSequence(*this); + } + + /** Virtual object copying. This method can be used for DcmObject + * and derived classes to get a deep copy of an object. Internally + * the assignment operator is called if the given DcmObject parameter + * is of the same type as "this" object instance. If not, an error + * is returned. This function permits copying an object by value + * in a virtual way which therefore is different to just calling the + * assignment operator of DcmElement which could result in slicing + * the object. + * @param rhs - [in] The instance to copy from. Has to be of the same + * class type as "this" object + * @return EC_Normal if copying was successful, error otherwise + */ + virtual OFCondition copyFrom(const DcmObject& rhs); + + /** get type identifier + * @return type identifier of this class (EVR_item) + */ + virtual DcmEVR ident(void) const { return EVR_pixelSQ; } + + /** print all elements of the item to a stream + * @param out output stream + * @param flags optional flag used to customize the output (see DCMTypes::PF_xxx) + * @param level current level of nested items. Used for indentation. + * @param pixelFileName optional filename used to write the raw pixel data file + * @param pixelCounter optional counter used for automatic pixel data filename creation + */ + virtual void print(STD_NAMESPACE ostream &out, + const size_t flags = 0, + const int level = 0, + const char *pixelFileName = NULL, + size_t *pixelCounter = NULL); + + /** calculate the length of this DICOM element when encoded with the + * given transfer syntax and the given encoding type for sequences. + * For elements, the length includes the length of the tag, length field, + * VR field and the value itself, for items and sequences it returns + * the length of the complete item or sequence including delimitation tags + * if applicable. Never returns undefined length. + * @param xfer transfer syntax for length calculation + * @param enctype sequence encoding type for length calculation + * @return length of DICOM element + */ + virtual Uint32 calcElementLength(const E_TransferSyntax xfer, + const E_EncodingType enctype); + + /** insert the given pixel item at the given position within the list maintained by this object. + * Ownership of the pixel item, which must be allocated on the heap, is transferred to the pixel sequence. + * @param item pointer to DcmPixelItem instance allocated on the heap, must not be NULL. + * @param where position at which the new item is to be inserted. + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition insert(DcmPixelItem *item, + unsigned long where = DCM_EndOfListIndex); + + /** access a pixel item from the pixel sequence. This method returns a pointer to one + * of the pixel items in the list, and not a copy. + * @param item upon success, a pointer to the selected pixel item is returned in this parameter + * @param num index number of pixel item, must be < card() + * @return pointer to item if found, NULL if num >= card() + */ + virtual OFCondition getItem(DcmPixelItem * &item, + const unsigned long num); + + /** remove pixel item from list. If found, the pixel item is not deleted but + * returned to the caller who is responsible for further management of the + * DcmPixelItem object. + * @param item upon success, a pointer to the removed pixel item is returned in this parameter + * @param num index number of item, must be < card() + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition remove(DcmPixelItem * &item, + const unsigned long num); + + /** remove pixel item from list. Tthe pixel item is not deleted; + * the caller is responsible for further management of the DcmPixelItem object. + * @param item pointer to element to be removed from list + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition remove(DcmPixelItem* item); + + /** changes the transfer syntax of this object to the given one. + * This only works if no transfer syntax was defined so far, or if the new and the old one + * are identical. + * @param newXfer + * @return status, EC_Normal if successful, an error code otherwise + */ + OFCondition changeXfer(const E_TransferSyntax newXfer); + + /** check if this DICOM object can be encoded in the given transfer syntax. + * @param newXfer transfer syntax in which the DICOM object is to be encoded + * @param oldXfer transfer syntax in which the DICOM object was read or created. + * @return true if object can be encoded in desired transfer syntax, false otherwise. + */ + virtual OFBool canWriteXfer(const E_TransferSyntax newXfer, + const E_TransferSyntax oldXfer); + + /** This function reads the information of all attributes which + * are captured in the input stream and captures this information + * in elementList. Each attribute is represented as an element + * in this list. If not all information for an attribute could be + * read from the stream, the function returns EC_StreamNotifyClient. + * @param inStream The stream which contains the information. + * @param ixfer The transfer syntax which was used to encode + * the information in inStream. + * @param glenc Encoding type for group length; specifies + * what will be done with group length tags. + * @param maxReadLength Maximum read length for reading an attribute value. + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition read(DcmInputStream & inStream, + const E_TransferSyntax ixfer, + const E_GrpLenEncoding glenc = EGL_noChange, + const Uint32 maxReadLength = DCM_MaxReadLength); + + /** write object to a stream + * @param outStream DICOM output stream + * @param oxfer output transfer syntax + * @param enctype encoding types (undefined or explicit length) + * @param wcache pointer to write cache object, may be NULL + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition write(DcmOutputStream &outStream, + const E_TransferSyntax oxfer, + const E_EncodingType enctype, + DcmWriteCache *wcache); + + /** write object in XML format + * @param out output stream to which the XML document is written + * @param flags optional flag used to customize the output (see DCMTypes::XF_xxx) + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition writeXML(STD_NAMESPACE ostream &out, + const size_t flags = 0); + + /** special write method for creation of digital signatures + * @param outStream DICOM output stream + * @param oxfer output transfer syntax + * @param enctype encoding types (undefined or explicit length) + * @param wcache pointer to write cache object, may be NULL + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition writeSignatureFormat(DcmOutputStream &outStream, + const E_TransferSyntax oxfer, + const E_EncodingType enctype, + DcmWriteCache *wcache); + + /** appends a single compressed frame to this DICOM pixel sequence + * @param offsetList list containing offset table entries. + * Upon success, an entry is appended to the list. The offset values are always even, + * so it is expected that odd length pixel items are padded later during writing. + * @param compressedData pointer to compressed image data, must not be NULL + * @param compressedLen number of bytes of compressed image data + * @param fragmentSize maximum fragment size (in kbytes) for compression, 0 for unlimited. + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition storeCompressedFrame(DcmOffsetList &offsetList, + Uint8 *compressedData, + Uint32 compressedLen, + Uint32 fragmentSize); + +protected: + + /** helper function for read(). Create sub-object (pixel item) of the + * appropriate type depending on the tag. + * @param newObject upon success, a pointer to the newly created object is returned in this parameter + * @param newTag tag of the sub-object to be created + * @param newLength length of the sub-object to be created + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition makeSubObject(DcmObject * &newObject, // out + const DcmTag &newTag, + const Uint32 newLength); // in + +private: + /** the transfer syntax in which the compressed pixel data maintained by this object + * is encoded. This may very well differ from the transfer syntax of the main dataset + * if this object was created by a compression codec in memory. + */ + E_TransferSyntax Xfer; + + /// method inherited from base class that is useless in this class + virtual OFCondition insert(DcmItem* /*item*/, + unsigned long /*where*/ = DCM_EndOfListIndex, + OFBool /*before*/ = OFFalse) + { + return EC_IllegalCall; + } + + /// method inherited from base class that is useless in this class + virtual DcmItem* getItem(const unsigned long /*num*/) + { + return NULL; + } + + /// method inherited from base class that is useless in this class + virtual DcmItem* remove(const unsigned long /*num*/) + { + return NULL; + } + + /// method inherited from base class that is useless in this class + virtual DcmItem* remove(DcmItem* /*item*/) + { + return NULL; + } + +}; + +#endif // DCPIXSEQ_H diff --git a/dcmdata/include/dcmtk/dcmdata/dcpxitem.h b/dcmdata/include/dcmtk/dcmdata/dcpxitem.h new file mode 100644 index 00000000..45cd6dbc --- /dev/null +++ b/dcmdata/include/dcmtk/dcmdata/dcpxitem.h @@ -0,0 +1,164 @@ +/* + * + * Copyright (C) 1994-2015, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Gerd Ehlers, Andreas Barth + * + * Purpose: Interface of class DcmPixelItem + * + */ + + +#ifndef DCPXITEM_H +#define DCPXITEM_H + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ +#include "dcmtk/dcmdata/dcvrobow.h" +#include "dcmtk/dcmdata/dcofsetl.h" /* for class DcmOffsetList */ + + +/* +** Defines +*/ + +/// macro for the "pixel item" tag +#define DCM_PixelItemTag (DcmTag(DCM_Item, EVR_OB)) + + +/** this class implements a container for a fragment of compressed pixel data. + * Instances of this class use the same attribute tags as sequence items, + * but are maintained within a pixel data element (class DcmPixelSequence) + * with undefined length and contain no DICOM structure, but raw data. + * Therefore, this class is derived from DcmOtherByteOtherWord, the class + * that is used for OB raw data which is handled very similar. + */ +class DCMTK_DCMDATA_EXPORT DcmPixelItem : public DcmOtherByteOtherWord +{ + public: + + /** constructor + * @param tag attribute tag + * @param len length of the attribute value + */ + DcmPixelItem(const DcmTag &tag, const Uint32 len = 0); + + /** copy constructor + * @param old element to be copied + */ + DcmPixelItem(const DcmPixelItem &old); + + /// destructor + virtual ~DcmPixelItem(); + + /** copy assignment operator + * @param obj element to be copied + */ + DcmPixelItem &operator=(const DcmPixelItem &obj) { DcmOtherByteOtherWord::operator=(obj); return *this; } + + /** clone method + * @return deep copy of this object + */ + virtual DcmObject *clone() const + { + return new DcmPixelItem(*this); + } + + /** get type identifier + * @return type identifier of this class (EVR_item) + */ + virtual DcmEVR ident(void) const { return EVR_pixelItem; } + + /** Virtual object copying. This method can be used for DcmObject + * and derived classes to get a deep copy of an object. Internally + * the assignment operator is called if the given DcmObject parameter + * is of the same type as "this" object instance. If not, an error + * is returned. This function permits copying an object by value + * in a virtual way which therefore is different to just calling the + * assignment operator of DcmElement which could result in slicing + * the object. + * @param rhs - [in] The instance to copy from. Has to be of the same + * class type as "this" object + * @return EC_Normal if copying was successful, error otherwise + */ + virtual OFCondition copyFrom(const DcmObject &rhs); + + /** check if this pixel item is nested in a pixel sequence, i.e.\ not a + * top-level or stand-alone item/dataset + * @return true if this item is nested, false otherwise + */ + virtual OFBool isNested() const; + + /** get parent item of this object, i.e.\ the item/dataset in which the + * surrounding pixel sequence is stored. + * @return pointer to the parent item of this object (might be NULL) + */ + virtual DcmItem *getParentItem(); + + /** print all elements of the item to a stream + * @param out output stream + * @param flags optional flag used to customize the output (see DCMTypes::PF_xxx) + * @param level current level of nested items. Used for indentation. + * @param pixelFileName optional filename used to write the raw pixel data file + * @param pixelCounter optional counter used for automatic pixel data filename creation + */ + virtual void print(STD_NAMESPACE ostream &out, + const size_t flags = 0, + const int level = 0, + const char *pixelFileName = NULL, + size_t *pixelCounter = NULL); + + /** creates in this object an offset table for a compressed pixel sequence. + * @param offsetList list of size entries for each individual encoded frame + * provided by the compression codec. All entries are expected to have + * an even value (i.e. the pixel items are padded). + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition createOffsetTable(const DcmOffsetList &offsetList); + + /** write object in XML format + * @param out output stream to which the XML document is written + * @param flags optional flag used to customize the output (see DCMTypes::XF_xxx) + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition writeXML(STD_NAMESPACE ostream &out, + const size_t flags = 0); + + /** special write method for creation of digital signatures + * @param outStream DICOM output stream + * @param oxfer output transfer syntax + * @param enctype encoding types (undefined or explicit length) + * @param wcache pointer to write cache object, may be NULL + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition writeSignatureFormat(DcmOutputStream &outStream, + const E_TransferSyntax oxfer, + const E_EncodingType enctype, + DcmWriteCache *wcache); + + protected: + + /** write tag, VR and length field to the given output stream + * @param outStream output stream + * @param oxfer transfer syntax for writing + * @param writtenBytes number of bytes written to stream returned in this parameter + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition writeTagAndLength(DcmOutputStream &outStream, + const E_TransferSyntax oxfer, + Uint32 &writtenBytes) const; + +}; + + +#endif // DCPXITEM_H diff --git a/dcmdata/include/dcmtk/dcmdata/dcrleccd.h b/dcmdata/include/dcmtk/dcmdata/dcrleccd.h new file mode 100644 index 00000000..435c7bfb --- /dev/null +++ b/dcmdata/include/dcmtk/dcmdata/dcrleccd.h @@ -0,0 +1,180 @@ +/* + * + * Copyright (C) 2002-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Marco Eichelberg + * + * Purpose: decoder codec class for RLE + * + */ + +#ifndef DCRLECCD_H +#define DCRLECCD_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmdata/dccodec.h" /* for class DcmCodec */ + +/** decoder class for RLE. + * This class only supports decompression, it neither implements + * encoding nor transcoding. + */ +class DCMTK_DCMDATA_EXPORT DcmRLECodecDecoder: public DcmCodec +{ +public: + + /// default constructor + DcmRLECodecDecoder(); + + /// destructor + virtual ~DcmRLECodecDecoder(); + + /** decompresses the given pixel sequence and + * stores the result in the given uncompressedPixelData element. + * @param fromRepParam current representation parameter of compressed data, may be NULL + * @param pixSeq compressed pixel sequence + * @param uncompressedPixelData uncompressed pixel data stored in this element + * @param cp codec parameters for this codec + * @param objStack stack pointing to the location of the pixel data + * element in the current dataset. + * @return EC_Normal if successful, an error code otherwise. + */ + virtual OFCondition decode( + const DcmRepresentationParameter * fromRepParam, + DcmPixelSequence * pixSeq, + DcmPolymorphOBOW& uncompressedPixelData, + const DcmCodecParameter * cp, + const DcmStack& objStack) const; + + /** decompresses a single frame from the given pixel sequence and + * stores the result in the given buffer. + * @param fromParam representation parameter of current compressed + * representation, may be NULL. + * @param fromPixSeq compressed pixel sequence + * @param cp codec parameters for this codec + * @param dataset pointer to dataset in which pixel data element is contained + * @param frameNo number of frame, starting with 0 for the first frame + * @param startFragment index of the compressed fragment that contains + * all or the first part of the compressed bitstream for the given frameNo. + * Upon successful return this parameter is updated to contain the index + * of the first compressed fragment of the next frame. + * When unknown, zero should be passed. In this case the decompression + * algorithm will try to determine the index by itself, which will always + * work if frames are decompressed in increasing order from first to last, + * but may fail if frames are decompressed in random order, multiple fragments + * per frame and multiple frames are present in the dataset, and the offset + * table is empty. + * @param buffer pointer to buffer where frame is to be stored + * @param bufSize size of buffer in bytes + * @param decompressedColorModel upon successful return, the color model + * of the decompressed image (which may be different from the one used + * in the compressed images) is returned in this parameter. + * @return EC_Normal if successful, an error code otherwise. + */ + virtual OFCondition decodeFrame( + const DcmRepresentationParameter * fromParam, + DcmPixelSequence * fromPixSeq, + const DcmCodecParameter * cp, + DcmItem *dataset, + Uint32 frameNo, + Uint32& startFragment, + void *buffer, + Uint32 bufSize, + OFString& decompressedColorModel) const; + + /** compresses the given uncompressed DICOM image and stores + * the result in the given pixSeq element. + * @param pixelData pointer to the uncompressed image data in OW format + * and local byte order + * @param length of the pixel data field in bytes + * @param toRepParam representation parameter describing the desired + * compressed representation (e.g. JPEG quality) + * @param pixSeq compressed pixel sequence (pointer to new DcmPixelSequence object + * allocated on heap) returned in this parameter upon success. + * @param cp codec parameters for this codec + * @param objStack stack pointing to the location of the pixel data + * element in the current dataset. + * @return EC_Normal if successful, an error code otherwise. + */ + virtual OFCondition encode( + const Uint16 * pixelData, + const Uint32 length, + const DcmRepresentationParameter * toRepParam, + DcmPixelSequence * & pixSeq, + const DcmCodecParameter *cp, + DcmStack & objStack) const; + + /** transcodes (re-compresses) the given compressed DICOM image and stores + * the result in the given toPixSeq element. + * @param fromRepType current transfer syntax of the compressed image + * @param fromRepParam current representation parameter of compressed data, may be NULL + * @param fromPixSeq compressed pixel sequence + * @param toRepParam representation parameter describing the desired + * new compressed representation (e.g. JPEG quality) + * @param toPixSeq compressed pixel sequence (pointer to new DcmPixelSequence object + * allocated on heap) returned in this parameter upon success. + * @param cp codec parameters for this codec + * @param objStack stack pointing to the location of the pixel data + * element in the current dataset. + * @return EC_Normal if successful, an error code otherwise. + */ + virtual OFCondition encode( + const E_TransferSyntax fromRepType, + const DcmRepresentationParameter * fromRepParam, + DcmPixelSequence * fromPixSeq, + const DcmRepresentationParameter * toRepParam, + DcmPixelSequence * & toPixSeq, + const DcmCodecParameter * cp, + DcmStack & objStack) const; + + /** checks if this codec is able to convert from the + * given current transfer syntax to the given new + * transfer syntax + * @param oldRepType current transfer syntax + * @param newRepType desired new transfer syntax + * @return true if transformation is supported by this codec, false otherwise. + */ + virtual OFBool canChangeCoding( + const E_TransferSyntax oldRepType, + const E_TransferSyntax newRepType) const; + + /** determine color model of the decompressed image + * @param fromParam representation parameter of current compressed + * representation, may be NULL + * @param fromPixSeq compressed pixel sequence + * @param cp codec parameters for this codec + * @param dataset pointer to dataset in which pixel data element is contained + * @param dataset pointer to DICOM dataset in which this pixel data object + * is located. Used to access photometric interpretation. + * @param decompressedColorModel upon successful return, the color model + * of the decompressed image (which may be different from the one used + * in the compressed images) is returned in this parameter + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition determineDecompressedColorModel( + const DcmRepresentationParameter *fromParam, + DcmPixelSequence *fromPixSeq, + const DcmCodecParameter *cp, + DcmItem *dataset, + OFString &decompressedColorModel) const; + +private: + + /// private undefined copy constructor + DcmRLECodecDecoder(const DcmRLECodecDecoder&); + + /// private undefined copy assignment operator + DcmRLECodecDecoder& operator=(const DcmRLECodecDecoder&); +}; + +#endif diff --git a/dcmdata/include/dcmtk/dcmdata/dcrlecce.h b/dcmdata/include/dcmtk/dcmdata/dcrlecce.h new file mode 100644 index 00000000..2b983240 --- /dev/null +++ b/dcmdata/include/dcmtk/dcmdata/dcrlecce.h @@ -0,0 +1,192 @@ +/* + * + * Copyright (C) 2002-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Marco Eichelberg + * + * Purpose: encoder codec class for RLE + * + */ + +#ifndef DCRLECCE_H +#define DCRLECCE_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmdata/dccodec.h" /* for class DcmCodec */ + +class DcmItem; + +/** encoder class for RLE. + * This class only supports compression, it neither implements + * decoding nor transcoding. + */ +class DCMTK_DCMDATA_EXPORT DcmRLECodecEncoder: public DcmCodec +{ +public: + + /// default constructor + DcmRLECodecEncoder(); + + /// destructor + virtual ~DcmRLECodecEncoder(); + + /** decompresses the given pixel sequence and + * stores the result in the given uncompressedPixelData element. + * @param fromRepParam current representation parameter of compressed data, may be NULL + * @param pixSeq compressed pixel sequence + * @param uncompressedPixelData uncompressed pixel data stored in this element + * @param cp codec parameters for this codec + * @param objStack stack pointing to the location of the pixel data + * element in the current dataset. + * @return EC_Normal if successful, an error code otherwise. + */ + virtual OFCondition decode( + const DcmRepresentationParameter * fromRepParam, + DcmPixelSequence * pixSeq, + DcmPolymorphOBOW& uncompressedPixelData, + const DcmCodecParameter * cp, + const DcmStack& objStack) const; + + /** decompresses a single frame from the given pixel sequence and + * stores the result in the given buffer. + * @param fromParam representation parameter of current compressed + * representation, may be NULL. + * @param fromPixSeq compressed pixel sequence + * @param cp codec parameters for this codec + * @param dataset pointer to dataset in which pixel data element is contained + * @param frameNo number of frame, starting with 0 for the first frame + * @param startFragment index of the compressed fragment that contains + * all or the first part of the compressed bitstream for the given frameNo. + * Upon successful return this parameter is updated to contain the index + * of the first compressed fragment of the next frame. + * When unknown, zero should be passed. In this case the decompression + * algorithm will try to determine the index by itself, which will always + * work if frames are decompressed in increasing order from first to last, + * but may fail if frames are decompressed in random order, multiple fragments + * per frame and multiple frames are present in the dataset, and the offset + * table is empty. + * @param buffer pointer to buffer where frame is to be stored + * @param bufSize size of buffer in bytes + * @param decompressedColorModel upon successful return, the color model + * of the decompressed image (which may be different from the one used + * in the compressed images) is returned in this parameter. + * @return EC_Normal if successful, an error code otherwise. + */ + virtual OFCondition decodeFrame( + const DcmRepresentationParameter * fromParam, + DcmPixelSequence * fromPixSeq, + const DcmCodecParameter * cp, + DcmItem *dataset, + Uint32 frameNo, + Uint32& startFragment, + void *buffer, + Uint32 bufSize, + OFString& decompressedColorModel) const; + + /** compresses the given uncompressed DICOM image and stores + * the result in the given pixSeq element. + * @param pixelData pointer to the uncompressed image data in OW format + * and local byte order + * @param length of the pixel data field in bytes + * @param toRepParam representation parameter describing the desired + * compressed representation (e.g. JPEG quality) + * @param pixSeq compressed pixel sequence (pointer to new DcmPixelSequence object + * allocated on heap) returned in this parameter upon success. + * @param cp codec parameters for this codec + * @param objStack stack pointing to the location of the pixel data + * element in the current dataset. + * @return EC_Normal if successful, an error code otherwise. + */ + virtual OFCondition encode( + const Uint16 * pixelData, + const Uint32 length, + const DcmRepresentationParameter * toRepParam, + DcmPixelSequence * & pixSeq, + const DcmCodecParameter *cp, + DcmStack & objStack) const; + + /** transcodes (re-compresses) the given compressed DICOM image and stores + * the result in the given toPixSeq element. + * @param fromRepType current transfer syntax of the compressed image + * @param fromRepParam current representation parameter of compressed data, may be NULL + * @param fromPixSeq compressed pixel sequence + * @param toRepParam representation parameter describing the desired + * new compressed representation (e.g. JPEG quality) + * @param toPixSeq compressed pixel sequence (pointer to new DcmPixelSequence object + * allocated on heap) returned in this parameter upon success. + * @param cp codec parameters for this codec + * @param objStack stack pointing to the location of the pixel data + * element in the current dataset. + * @return EC_Normal if successful, an error code otherwise. + */ + virtual OFCondition encode( + const E_TransferSyntax fromRepType, + const DcmRepresentationParameter * fromRepParam, + DcmPixelSequence * fromPixSeq, + const DcmRepresentationParameter * toRepParam, + DcmPixelSequence * & toPixSeq, + const DcmCodecParameter * cp, + DcmStack & objStack) const; + + /** checks if this codec is able to convert from the + * given current transfer syntax to the given new + * transfer syntax + * @param oldRepType current transfer syntax + * @param newRepType desired new transfer syntax + * @return true if transformation is supported by this codec, false otherwise. + */ + virtual OFBool canChangeCoding( + const E_TransferSyntax oldRepType, + const E_TransferSyntax newRepType) const; + + /** determine color model of the decompressed image + * @param fromParam representation parameter of current compressed + * representation, may be NULL + * @param fromPixSeq compressed pixel sequence + * @param cp codec parameters for this codec + * @param dataset pointer to dataset in which pixel data element is contained + * @param dataset pointer to DICOM dataset in which this pixel data object + * is located. Used to access photometric interpretation. + * @param decompressedColorModel upon successful return, the color model + * of the decompressed image (which may be different from the one used + * in the compressed images) is returned in this parameter + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition determineDecompressedColorModel( + const DcmRepresentationParameter *fromParam, + DcmPixelSequence *fromPixSeq, + const DcmCodecParameter *cp, + DcmItem *dataset, + OFString &decompressedColorModel) const; + +private: + + /// private undefined copy constructor + DcmRLECodecEncoder(const DcmRLECodecEncoder&); + + /// private undefined copy assignment operator + DcmRLECodecEncoder& operator=(const DcmRLECodecEncoder&); + + /** create Derivation Description. + * @param dataset dataset to be modified + * @param ratio image compression ratio. This is the real effective ratio + * between compressed and uncompressed image, i. e. 2.5 means a 2.5:1 compression. + * @return EC_Normal if successful, an error code otherwise + */ + static OFCondition updateDerivationDescription( + DcmItem *dataset, + double ratio); +}; + +#endif diff --git a/dcmdata/include/dcmtk/dcmdata/dcrlecp.h b/dcmdata/include/dcmtk/dcmdata/dcrlecp.h new file mode 100644 index 00000000..1df1279c --- /dev/null +++ b/dcmdata/include/dcmtk/dcmdata/dcrlecp.h @@ -0,0 +1,137 @@ +/* + * + * Copyright (C) 2002-2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Marco Eichelberg + * + * Purpose: codec parameter for RLE + * + */ + +#ifndef DCRLECP_H +#define DCRLECP_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmdata/dccodec.h" /* for DcmCodecParameter */ + +/** codec parameter for RLE codec + */ +class DCMTK_DCMDATA_EXPORT DcmRLECodecParameter: public DcmCodecParameter +{ +public: + + /** constructor. + * @param pCreateSOPInstanceUID true if a new SOP instance UID should be assigned + * upon compression/decompression + * @param pFragmentSize maximum fragment size (in kbytes) for compression, 0 for unlimited. + * Please note that the DICOM standard does not allow for storing the pixel data with + * multiple fragments per frame (when RLE compression is used). So limiting the fragment + * size may result in non-standard conformant DICOM images. + * @param pCreateOffsetTable create offset table during image compression? + * @param pConvertToSC flag indicating whether image should be converted to + * Secondary Capture upon compression + * @param pReverseDecompressionByteOrder flag indicating whether the byte order should + * be reversed upon decompression. Needed to correctly decode some incorrectly encoded + * images with more than one byte per sample. + */ + DcmRLECodecParameter( + OFBool pCreateSOPInstanceUID = OFFalse, + Uint32 pFragmentSize = 0, + OFBool pCreateOffsetTable = OFTrue, + OFBool pConvertToSC = OFFalse, + OFBool pReverseDecompressionByteOrder = OFFalse); + + /// copy constructor + DcmRLECodecParameter(const DcmRLECodecParameter& arg); + + /// destructor + virtual ~DcmRLECodecParameter(); + + /** this methods creates a copy of type DcmCodecParameter * + * it must be overwritten in every subclass. + * @return copy of this object + */ + virtual DcmCodecParameter *clone() const; + + /** returns the class name as string. + * can be used as poor man's RTTI replacement. + */ + virtual const char *className() const; + + /** returns maximum fragment size (in kbytes) for compression, 0 for unlimited. + * @return maximum fragment size for compression + */ + Uint32 getFragmentSize() const + { + return fragmentSize; + } + + /** returns offset table creation flag + * @return offset table creation flag + */ + OFBool getCreateOffsetTable() const + { + return createOffsetTable; + } + + /** returns secondary capture conversion flag + * @return secondary capture conversion flag + */ + OFBool getConvertToSC() const + { + return convertToSC; + } + + /** returns mode for SOP Instance UID creation + * @return mode for SOP Instance UID creation + */ + OFBool getUIDCreation() const + { + return createInstanceUID; + } + + /** returns reverse decompression byte order mode + * @return reverse decompression byte order mode + */ + OFBool getReverseDecompressionByteOrder() const + { + return reverseDecompressionByteOrder; + } + + +private: + + /// private undefined copy assignment operator + DcmRLECodecParameter& operator=(const DcmRLECodecParameter&); + + /// maximum fragment size (in kbytes) for compression, 0 for unlimited. + Uint32 fragmentSize; + + /// create offset table during image compression + OFBool createOffsetTable; + + /// flag indicating whether image should be converted to Secondary Capture upon compression + OFBool convertToSC; + + /// create new Instance UID during compression/decompression? + OFBool createInstanceUID; + + /** enable reverse byte order of RLE segments during decompression, needed to + * decompress certain incorrectly encoded RLE images + */ + OFBool reverseDecompressionByteOrder; +}; + + +#endif diff --git a/dcmdata/include/dcmtk/dcmdata/dcrledec.h b/dcmdata/include/dcmtk/dcmdata/dcrledec.h new file mode 100644 index 00000000..bf792e70 --- /dev/null +++ b/dcmdata/include/dcmtk/dcmdata/dcrledec.h @@ -0,0 +1,264 @@ +/* + * + * Copyright (C) 1994-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Marco Eichelberg + * + * Purpose: RLE decompressor + * + */ + +#ifndef DCRLEDEC_H +#define DCRLEDEC_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmdata/dcerror.h" + +/** this class implements an RLE decompressor conforming to the DICOM standard. + * The class is loosely based on an implementation by Phil Norman + */ +class DCMTK_DCMDATA_EXPORT DcmRLEDecoder +{ +public: + + /** constructor + * @param outputBufferSize size of the output buffer (in bytes) + * to which the RLE codec will write decompressed output. + */ + DcmRLEDecoder(size_t outputBufferSize) + : fail_(0) + , outputBufferSize_(outputBufferSize) + , outputBuffer_(NULL) + , offset_(0) + , suspendInfo_(128) + { + if (outputBufferSize_ == 0) fail_ = 1; + else + { + outputBuffer_ = new unsigned char[outputBufferSize_]; + if (outputBuffer_ == NULL) fail_ = 1; + } + } + + /// destructor + ~DcmRLEDecoder() + { + delete[] outputBuffer_; + } + + /** resets the decoder object to newly constructed state. + * The size and location of the output buffer is not changed. + */ + inline void clear() + { + offset_ = 0; + suspendInfo_ = 128; + if (outputBuffer_) fail_ = 0; + } + + + inline OFCondition decompress(void *compressedData, size_t compressedSize) + { + // we allow a call for zero bytes + if (compressedSize == 0) return EC_Normal; + + OFCondition result = EC_IllegalCall; + + // check parameters passed by caller + if (compressedData == NULL) fail_ = 1; + + if (! fail_) // if fail_ is true, just ignore input + { + result = EC_Normal; + unsigned char ch; + unsigned char nbytes; + unsigned char *cp = OFstatic_cast(unsigned char *, compressedData); + + // check if we suspended last time, clean up + if (suspendInfo_ > 128) + { + // DICOM packbit scheme uses 257 - nbytes to represent replicate runs + nbytes = OFstatic_cast(unsigned char, 257 - suspendInfo_); + + // suspended replicate run. compressedSize cannot be zero now. + suspendInfo_ = 128; + + ch = *cp++; + --compressedSize; + replicate(ch, nbytes); + } + else if (suspendInfo_ < 128) + { + // suspended literal run + nbytes = OFstatic_cast(unsigned char, (suspendInfo_ & 0x7f) + 1); + suspendInfo_ = 128; + if (compressedSize < nbytes) + { + // we're going to suspend again (oops?), prepare everything + suspendInfo_ = OFstatic_cast(unsigned char, nbytes - compressedSize - 1); + nbytes = OFstatic_cast(unsigned char, compressedSize); + result = EC_StreamNotifyClient; + } + + literal(cp, nbytes); + compressedSize -= nbytes; + cp += nbytes; + } + + // continue with ordinary RLE decompression + while (compressedSize && (! fail_)) + { + ch = *cp++; + --compressedSize; + + if (ch & 0x80) + { + // replicate run + if (compressedSize) + { + // DICOM packbit scheme uses 257 - nbytes to represent replicate runs + nbytes = OFstatic_cast(unsigned char, 257 - ch); + ch = *cp++; + --compressedSize; + replicate(ch, nbytes); + } + else + { + // suspension: replicate run but second byte is in next block + suspendInfo_ = ch; + result = EC_StreamNotifyClient; + } + } + else + { + // literal run + nbytes = OFstatic_cast(unsigned char, (ch & 0x7f) + 1); + if (compressedSize < nbytes) + { + // we're going to suspend, prepare everything + suspendInfo_ = OFstatic_cast(unsigned char, nbytes - compressedSize - 1); + nbytes = OFstatic_cast(unsigned char, compressedSize); + result = EC_StreamNotifyClient; + } + + literal(cp, nbytes); + compressedSize -= nbytes; + cp += nbytes; + } + } + + // failure status at this point means output buffer overflow + if (fail_) result = EC_CorruptedData; + } + + return result; + } + + + /** returns the number of bytes written to the output buffer + * @return size of decompressed stream, in bytes + */ + inline size_t size() const + { + return offset_; + } + + /** returns pointer to the output buffer + */ + inline void *getOutputBuffer() const + { + return outputBuffer_; + } + + /** returns true if the RLE compressor has failed (out of memory or output buffer too small). + */ + inline OFBool fail() const + { + if (fail_) return OFTrue; else return OFFalse; + } + +private: + + /// private undefined copy constructor + DcmRLEDecoder(const DcmRLEDecoder&); + + /// private undefined copy assignment operator + DcmRLEDecoder& operator=(const DcmRLEDecoder&); + + + /** this method expands a replicate run + * @param ch value to replicate + * @param nbytes number of repetitions + */ + inline void replicate(unsigned char ch, unsigned char nbytes) + { + if (offset_ + nbytes > outputBufferSize_) + { + // output buffer overflow + fail_ = 1; + nbytes = OFstatic_cast(unsigned char, outputBufferSize_ - offset_); + } + + while (nbytes--) outputBuffer_[offset_++] = ch; + } + + + /** this method expands a literal run + * @param cp pointer to buffer + * @param nbytes number of bytes in buffer + */ + inline void literal(unsigned char *cp, unsigned char nbytes) + { + if (offset_ + nbytes > outputBufferSize_) + { + // output buffer overflow + fail_ = 1; + nbytes = OFstatic_cast(unsigned char, outputBufferSize_ - offset_); + } + + while (nbytes--) outputBuffer_[offset_++] = *cp++; + } + + /* member variables */ + + /** this flag indicates a failure of the RLE codec. Once a failure is + * flagged, the codec will consume all input and not produce any more + * output. + */ + int fail_; + + /** size of output buffer, in bytes + */ + size_t outputBufferSize_; + + /** this member points to a block of size outputBufferSize_ + * (unless fail_ is true). This is the block of data to + * which the decompressed stream is written + */ + unsigned char *outputBuffer_; + + /** contains the number of bytes already written to outputBuffer_. + * Value is always less or equal to outputBufferSize_. + */ + size_t offset_; + + /** contains suspension information. + * If not suspended, contains 128. + * If suspended during a replicate run, contains control byte of repeat run (> 128). + * If suspended during a literal run, contains number of remaining bytes in literal run minus 1 (< 128). + */ + unsigned char suspendInfo_; +}; + +#endif diff --git a/dcmdata/include/dcmtk/dcmdata/dcrledrg.h b/dcmdata/include/dcmtk/dcmdata/dcrledrg.h new file mode 100644 index 00000000..73de0e56 --- /dev/null +++ b/dcmdata/include/dcmtk/dcmdata/dcrledrg.h @@ -0,0 +1,80 @@ +/* + * + * Copyright (C) 2002-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Marco Eichelberg + * + * Purpose: singleton class that registers RLE decoder. + * + */ + +#ifndef DCRLEDRG_H +#define DCRLEDRG_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/ofstd/oftypes.h" /* for OFBool */ +#include "dcmtk/dcmdata/dcdefine.h" + +class DcmRLECodecParameter; +class DcmRLECodecDecoder; + +/** singleton class that registers an RLE decoder. + */ +class DCMTK_DCMDATA_EXPORT DcmRLEDecoderRegistration +{ +public: + /** registers RLE decoder. + * If already registered, call is ignored unless cleanup() has + * been performed before. + * @param pCreateSOPInstanceUID flag indicating whether or not + * a new SOP Instance UID should be assigned upon decompression. + * @param pReverseDecompressionByteOrder flag indicating whether the byte order should + * be reversed upon decompression. Needed to correctly decode some incorrectly encoded + * images with more than one byte per sample. + */ + static void registerCodecs( + OFBool pCreateSOPInstanceUID = OFFalse, + OFBool pReverseDecompressionByteOrder = OFFalse); + + /** deregisters decoder. + * Attention: Must not be called while other threads might still use + * the registered codecs, e.g. because they are currently decoding + * DICOM data sets through dcmdata. + */ + static void cleanup(); + +private: + + /// private undefined copy constructor + DcmRLEDecoderRegistration(const DcmRLEDecoderRegistration&); + + /// private undefined copy assignment operator + DcmRLEDecoderRegistration& operator=(const DcmRLEDecoderRegistration&); + + /// flag indicating whether the decoder is already registered. + static OFBool registered; + + /// pointer to codec parameter + static DcmRLECodecParameter *cp; + + /// pointer to RLE decoder + static DcmRLECodecDecoder *codec; + + // dummy friend declaration to prevent gcc from complaining + // that this class only defines private constructors and has no friends. + friend class DcmRLEDecoderRegistrationDummyFriend; + +}; + +#endif diff --git a/dcmdata/include/dcmtk/dcmdata/dcrleenc.h b/dcmdata/include/dcmtk/dcmdata/dcrleenc.h new file mode 100644 index 00000000..a569e2a1 --- /dev/null +++ b/dcmdata/include/dcmtk/dcmdata/dcrleenc.h @@ -0,0 +1,416 @@ +/* + * + * Copyright (C) 2002-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Marco Eichelberg + * + * Purpose: RLE compressor + * + */ + +#ifndef DCRLEENC_H +#define DCRLEENC_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/ofstd/oflist.h" /* for class OFList<> */ + +#define INCLUDE_CSTRING +#include "dcmtk/ofstd/ofstdinc.h" + +#include "dcmtk/dcmdata/dcdefine.h" + +#define DcmRLEEncoder_BLOCKSIZE 16384 + + +/** abstract class that defines an interface through which + * encoder classes (such as DcmRLEEncoder) may export their + * encoded data + */ +class DCMTK_DCMDATA_EXPORT DcmEncoderOutputStream +{ +public: + /** write the given buffer into the output stream + * @param buf pointer to buffer + * @param bufsize number of bytes in buffer + */ + virtual void write(const unsigned char *buf, size_t bufsize) =0; + + /** Virtual Desctructor + */ + virtual ~DcmEncoderOutputStream() {} + +}; + + +/** this class implements an RLE compressor conforming to the DICOM standard. + * The class is loosely based on an implementation by Phil Norman. + */ +class DCMTK_DCMDATA_EXPORT DcmRLEEncoder +{ +public: + + /** default constructor + * @param doPad if true, RLE codec will pad output data to even number of bytes + */ + DcmRLEEncoder(int doPad) + : fail_(0) + , pad_(doPad) + , currentBlock_(new unsigned char[DcmRLEEncoder_BLOCKSIZE]) + , offset_(0) + , blockList_() + , RLE_buff_(new unsigned char[132]) + , RLE_prev_(-1) + , RLE_pcount_(0) + , RLE_bindex_(1) + { + if ((! RLE_buff_)||(! currentBlock_)) fail_ = 1; + else RLE_buff_[0] = 0; + } + + /// destructor + ~DcmRLEEncoder() + { + delete[] currentBlock_; + delete[] RLE_buff_; + OFListIterator(unsigned char *) first = blockList_.begin(); + OFListIterator(unsigned char *) last = blockList_.end(); + while (first != last) + { + delete[] *first; + first = blockList_.erase(first); + } + } + + /** this method adds one byte to the byte stream to be compressed + * with the RLE compressor. + * @param ch byte to be added + */ + inline void add(unsigned char ch) + { + if (! fail_) // if fail_ is true, just ignore input + { + // if the current byte equals the last byte read + // (which is initialized with the "impossible" value -1), + // just increase the repeat counter + if (OFstatic_cast(int, ch) == RLE_prev_) RLE_pcount_++; + else + { + // byte is different from last byte read. + // flush replicate run if necessary + switch (RLE_pcount_) + { + case 0: + // happens only after construction or flush() + break; + case 2: + // two bytes in repeat buffer. Convert to literal run + RLE_buff_[RLE_bindex_++] = OFstatic_cast(unsigned char, RLE_prev_); + // no break. Fall-through into next case statement is intended. + case 1: + // one (or two) bytes in repeat buffer. Convert to literal run + RLE_buff_[RLE_bindex_++] = OFstatic_cast(unsigned char, RLE_prev_); + break; + default: + // more than two bytes in repeat buffer. Convert to replicate run + if (RLE_bindex_ > 1) + { + // there is a literal run in the buffer that must be flushed + // before the replicate run. Flush literal run now. + RLE_buff_[0] = OFstatic_cast(unsigned char, RLE_bindex_-2); + move(RLE_bindex_); + } + // this is the byte value for the repeat run + RLE_buff_[1] = OFstatic_cast(unsigned char, RLE_prev_); + // write as many repeat runs as necessary + for (; RLE_pcount_>0; RLE_pcount_-=128) + { + // different PackBit schemes exist. The original from which + // this code is derived used 0x80 | (RLE_pcount_ - 1) + // to represent replicate runs. + // DICOM instead uses 257 - RLE_pcount_ + if (RLE_pcount_ > 128) RLE_buff_[0] = 0x81; + else RLE_buff_[0] = OFstatic_cast(unsigned char, 257 - RLE_pcount_); + move(2); + } + // now the buffer is guaranteed to be empty + RLE_buff_[0] = 0; + RLE_bindex_ = 1; + break; + } + + // if we have 128 or more bytes in the literal run, flush buffer + if (RLE_bindex_ > 129) + { + RLE_buff_[0] = 127; + move(129); + RLE_bindex_ -= 128; + if (RLE_bindex_ > 1) + RLE_buff_[1] = RLE_buff_[129]; + if (RLE_bindex_ > 2) + RLE_buff_[2] = RLE_buff_[130]; + } + + // current byte is stored in RLE_prev_, RLE_pcount_ is 1. + RLE_prev_ = ch; + RLE_pcount_ = 1; + } + } + } + + /** this method adds a block of bytes to the byte stream to be + * compressed with the RLE compressor. + * @param buf buffer to be added + * @param bufcount number of bytes in buffer + */ + inline void add(const unsigned char *buf, size_t bufcount) + { + if (buf) + { + while (bufcount--) add(*buf++); + } + } + + /** this method finalizes the compressed RLE stream, i.e. flushes all + * pending literal or repeat runs. This method can be called at any + * time; however, it must be called before size() or write() + * can be used. Intermediate calls should be avoided since they + * possibly decrease the compression ratio. + */ + inline void flush() + { + if (! fail_) // if fail_ is true, do nothing + { + // if there are max 1 bytes in the repeat counter, convert to literal run + if (RLE_pcount_ < 2) + { + for (; RLE_pcount_>0; --RLE_pcount_) RLE_buff_[RLE_bindex_++] = OFstatic_cast(unsigned char, RLE_prev_); + } + + // if we have 128 or more bytes in the literal run, flush buffer + if (RLE_bindex_ > 129) + { + RLE_buff_[0] = 127; + move(129); + RLE_bindex_ -= 128; + if (RLE_bindex_ > 1) + RLE_buff_[1] = RLE_buff_[129]; + if (RLE_bindex_ > 2) + RLE_buff_[2] = RLE_buff_[130]; + } + + // if there is still a literal run in the buffer, flush literal run + if (RLE_bindex_ > 1) + { + RLE_buff_[0] = OFstatic_cast(unsigned char, RLE_bindex_-2); + move(RLE_bindex_); + } + + // if there is a remaining repeat run, flush this one as well + if (RLE_pcount_ >= 2) + { + RLE_buff_[1] = OFstatic_cast(unsigned char, RLE_prev_); + // write as many repeat runs as necessary + for (; RLE_pcount_>0; RLE_pcount_-=128) + { + // different PackBit schemes exist. The original from which + // this code is derived used 0x80 | (RLE_pcount_ - 1) + // to represent replicate runs. + // DICOM instead uses 257 - RLE_pcount_ + if (RLE_pcount_ > 128) RLE_buff_[0] = 0x81; + else RLE_buff_[0] = OFstatic_cast(unsigned char, 257 - RLE_pcount_); + move(2); + } + } + + // now the buffer is guaranteed to be empty, re-initialize + RLE_buff_[0] = 0; + RLE_prev_ = -1; + RLE_pcount_ = 0; + RLE_bindex_ = 1; + } + } + + /** returns the size of compressed RLE stream in bytes. + * The size is guaranteed to be an even number of bytes (padded + * with a trailing zero byte as required by DICOM if necessary). + * This method may only be called after flush() has been executed + * to finalize the compressed stream. + * @return size of compressed stream, in bytes + */ + inline size_t size() const + { + size_t result = blockList_.size() * DcmRLEEncoder_BLOCKSIZE + offset_; + if (pad_ && (result & 1)) result++; // enforce even number of bytes + return result; + } + + /** returns true if the RLE compressor has run out of memory. In this case, + * no output has been created. + */ + inline OFBool fail() const + { + if (fail_) return OFTrue; else return OFFalse; + } + + /** copies the compressed RLE byte stream into a target array of at least + * size() bytes. + * @param target pointer to array of at least size() bytes, must not be NULL. + */ + inline void write(void *target) const + { + if ((!fail_) && target) + { + unsigned char *current = NULL; + unsigned char *target8 = OFstatic_cast(unsigned char *, target); + OFListConstIterator(unsigned char *) first = blockList_.begin(); + OFListConstIterator(unsigned char *) last = blockList_.end(); + while (first != last) + { + current = *first; + memcpy(target8, current, DcmRLEEncoder_BLOCKSIZE); + target8 += DcmRLEEncoder_BLOCKSIZE; + ++first; + } + if (offset_ > 0) + { + memcpy(target8, currentBlock_, offset_); + } + + // pad to even number of bytes if necessary + if (pad_ && ((blockList_.size() * DcmRLEEncoder_BLOCKSIZE + offset_) & 1)) + { + target8 += offset_; + *target8 = 0; + } + } + } + + /** copies the compressed RLE byte stream into an + * output stream + * @param os output stream + */ + inline void write(DcmEncoderOutputStream& os) const + { + if (!fail_) + { + OFListConstIterator(unsigned char *) first = blockList_.begin(); + OFListConstIterator(unsigned char *) last = blockList_.end(); + while (first != last) + { + os.write(*first, DcmRLEEncoder_BLOCKSIZE); + ++first; + } + if (offset_ > 0) + { + os.write(currentBlock_, offset_); + } + + // pad to even number of bytes if necessary + if (pad_ && ((blockList_.size() * DcmRLEEncoder_BLOCKSIZE + offset_) & 1)) + { + unsigned char c = 0; + os.write(&c, 1); + } + } + } + +private: + + /// private undefined copy constructor + DcmRLEEncoder(const DcmRLEEncoder&); + + /// private undefined copy assignment operator + DcmRLEEncoder& operator=(const DcmRLEEncoder&); + + /** this method moves the given number of bytes from buff_ + * to currentBlock_ and "flushes" currentBlock_ to + * blockList_ if necessary. + * @param numberOfBytes number of bytes to copy + */ + inline void move(size_t numberOfBytes) + { + size_t i=0; + while (i < numberOfBytes) + { + if (offset_ == DcmRLEEncoder_BLOCKSIZE) + { + blockList_.push_back(currentBlock_); + currentBlock_ = new unsigned char[DcmRLEEncoder_BLOCKSIZE]; + offset_ = 0; + if (! currentBlock_) // out of memory + { + fail_ = 1; + break; // exit while loop + } + } + currentBlock_[offset_++] = RLE_buff_[i++]; + } + } + + /* member variables */ + + /** this flag indicates a failure of the RLE codec. Once a failure is + * flagged, the codec will consume all input and not produce any more + * output. A failure status can only be caused by an out-of-memory + * condition. + */ + int fail_; + + /** this flag indicates whether the RLE codec must pad encoded + * data to an even number of bytes (as required by DICOM). + * True if padding is required, false otherwise + */ + int pad_; + + /** this member points to a block of size DcmRLEEncoder_BLOCKSIZE + * (unless fail_ is true). This is the current block of data to + * which the RLE stream is written + */ + unsigned char *currentBlock_; + + /** contains the number of bytes already written the the memory + * block pointed to by currentBlock_. Value is always less than + * DcmRLEEncoder_BLOCKSIZE. + */ + size_t offset_; + + /** this member contains a list of memory blocks of size DcmRLEEncoder_BLOCKSIZE + * which already have been filled with encoded RLE data. + * The current block (pointed to by currentBlock_) is not contained in this list. + */ + OFList blockList_; + + /** this member points to a buffer of 132 bytes that is used by the RLE + * encoding algorithm. + */ + unsigned char *RLE_buff_; + + /** value of the last byte fed to the RLE compressor. This byte is not yet + * stored in the RLE_buff_ buffer. + * Type is int because this allows an "impossible" -1 as default value + */ + int RLE_prev_; + + /** repeat counter, for RLE compressor + * may temporarily become negative, guaranteed to be >= 0 between method calls. + */ + int RLE_pcount_; + + /** index of next unused byte in RLE_buff_. + */ + unsigned int RLE_bindex_; + +}; + +#endif diff --git a/dcmdata/include/dcmtk/dcmdata/dcrleerg.h b/dcmdata/include/dcmtk/dcmdata/dcrleerg.h new file mode 100644 index 00000000..859f3b18 --- /dev/null +++ b/dcmdata/include/dcmtk/dcmdata/dcrleerg.h @@ -0,0 +1,84 @@ +/* + * + * Copyright (C) 1994-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Marco Eichelberg + * + * Purpose: singleton class that registers RLE encoder. + * + */ + +#ifndef DCRLEERG_H +#define DCRLEERG_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/ofstd/oftypes.h" /* for OFBool */ +#include "dcmtk/dcmdata/dcdefine.h" + +class DcmRLECodecParameter; +class DcmRLECodecEncoder; + +/** singleton class that registers an RLE encoder. + */ +class DCMTK_DCMDATA_EXPORT DcmRLEEncoderRegistration +{ +public: + + /** registers RLE encoder. + * If already registered, call is ignored unless cleanup() has + * been performed before. + * @param pCreateSOPInstanceUID flag indicating whether or not + * a new SOP Instance UID should be assigned upon compression. + * @param pFragmentSize maximum fragment size (in kbytes) for compression, 0 for unlimited. + * @param pCreateOffsetTable create offset table during image compression? + * @param pConvertToSC flag indicating whether image should be converted to + * Secondary Capture upon compression + */ + static void registerCodecs( + OFBool pCreateSOPInstanceUID = OFFalse, + Uint32 pFragmentSize = 0, + OFBool pCreateOffsetTable = OFTrue, + OFBool pConvertToSC = OFFalse); + + /** deregisters encoder. + * Attention: Must not be called while other threads might still use + * the registered codecs, e.g. because they are currently encoding + * DICOM data sets through dcmdata. + */ + static void cleanup(); + +private: + + /// private undefined copy constructor + DcmRLEEncoderRegistration(const DcmRLEEncoderRegistration&); + + /// private undefined copy assignment operator + DcmRLEEncoderRegistration& operator=(const DcmRLEEncoderRegistration&); + + /// flag indicating whether the encoder is already registered. + static OFBool registered; + + /// pointer to codec parameter + static DcmRLECodecParameter *cp; + + /// pointer to RLE encoder + static DcmRLECodecEncoder *codec; + + // dummy friend declaration to prevent gcc from complaining + // that this class only defines private constructors and has no friends. + friend class DcmRLEEncoderRegistrationDummyFriend; + +}; + +#endif diff --git a/dcmdata/include/dcmtk/dcmdata/dcrlerp.h b/dcmdata/include/dcmtk/dcmdata/dcrlerp.h new file mode 100644 index 00000000..15987acd --- /dev/null +++ b/dcmdata/include/dcmtk/dcmdata/dcrlerp.h @@ -0,0 +1,65 @@ +/* + * + * Copyright (C) 1994-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Marco Eichelberg + * + * Purpose: representation parameter for RLE + * + */ + +#ifndef DCRLERP_H +#define DCRLERP_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmdata/dcpixel.h" /* for class DcmRepresentationParameter */ + +/** representation parameter for RLE. + * This is actually a dummy class since there are no compression + * options in the RLE algorithm. + */ +class DCMTK_DCMDATA_EXPORT DcmRLERepresentationParameter: public DcmRepresentationParameter +{ +public: + + /// constructor + DcmRLERepresentationParameter(); + + /// copy constructor + DcmRLERepresentationParameter(const DcmRLERepresentationParameter& arg); + + /// destructor + virtual ~DcmRLERepresentationParameter(); + + /** this methods creates a copy of type DcmRepresentationParameter * + * it must be overweritten in every subclass. + * @return copy of this object + */ + virtual DcmRepresentationParameter *clone() const; + + /** returns the class name as string. + * can be used in operator== as poor man's RTTI replacement. + */ + virtual const char *className() const; + + /** compares an object to another DcmRepresentationParameter. + * Implementation must make sure that classes are comparable. + * @param arg representation parameter to compare with + * @return true if equal, false otherwise. + */ + virtual OFBool operator==(const DcmRepresentationParameter &arg) const; + +}; + +#endif diff --git a/dcmdata/include/dcmtk/dcmdata/dcsequen.h b/dcmdata/include/dcmtk/dcmdata/dcsequen.h new file mode 100644 index 00000000..b66e8a8c --- /dev/null +++ b/dcmdata/include/dcmtk/dcmdata/dcsequen.h @@ -0,0 +1,606 @@ +/* + * + * Copyright (C) 1994-2015, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Gerd Ehlers, Andreas Barth + * + * Purpose: Interface of class DcmSequenceOfItems + * + */ + + +#ifndef DCSEQUEN_H +#define DCSEQUEN_H + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/ofstd/offile.h" /* for offile_off_t */ +#include "dcmtk/dcmdata/dcelem.h" +#include "dcmtk/dcmdata/dctag.h" +#include "dcmtk/dcmdata/dclist.h" +#include "dcmtk/dcmdata/dcstack.h" + +/** class representing a DICOM Sequence of Items (SQ). + * This class is derived from class DcmElement (and not from DcmObject) despite the fact + * that sequences have no value field as such, they maintain a list of items. However, + * all APIs in class DcmItem and class DcmDataset accept DcmElements. + * This is ugly and causes some DcmElement API methods to be useless with DcmSequence. + */ +class DCMTK_DCMDATA_EXPORT DcmSequenceOfItems : public DcmElement +{ +public: + + /** constructor + * @param tag attribute tag + * @param len length of the attribute value + * @param readAsUN flag indicating whether the sequence should be + * read (interpreted) as a UN element with Implicit VR Little Endian encoding + */ + DcmSequenceOfItems(const DcmTag &tag, + const Uint32 len = 0, + OFBool readAsUN = OFFalse); + + /** copy constructor + * @param oldSeq element to be copied + */ + DcmSequenceOfItems(const DcmSequenceOfItems& oldSeq); + + /// destructor + virtual ~DcmSequenceOfItems(); + + /** copy assignment operator + * @param obj element to be copied + */ + DcmSequenceOfItems &operator=(const DcmSequenceOfItems &obj); + + /** comparison operator that compares the normalized value of this object + * with a given object of the same type. The tag of the element is also + * considered as the first component that is compared, followed by the + * object types (VR, i.e. DCMTK'S EVR) and the comparison of all value + * components of the object, preferrably in the order declared in the + * object (if applicable). For sequences that means that all + * containted items are compared element by element, so this may be + * an expensive operation! + * @param rhs the right hand side of the comparison + * @return 0 if the object values are equal. + * -1 if either the value of the first component that does not match + * is lower in this object than in rhs, or all compared components match + * but this object has fewer components than rhs. Also returned if rhs + * cannot be casted to this object type. + * 1 if either the value of the first component that does not match + * is greater in this object than in rhs object, or all compared + * components match but the this component is longer. + */ + virtual int compare(const DcmElement& rhs) const; + + /// returns current status flag + inline OFCondition error() const { return errorFlag; } + + /** clone method + * @return deep copy of this object + */ + virtual DcmObject *clone() const + { + return new DcmSequenceOfItems(*this); + } + + /** Virtual object copying. This method can be used for DcmObject + * and derived classes to get a deep copy of an object. Internally + * the assignment operator is called if the given DcmObject parameter + * is of the same type as "this" object instance. If not, an error + * is returned. This function permits copying an object by value + * in a virtual way which therefore is different to just calling the + * assignment operator of DcmElement which could result in slicing + * the object. + * @param rhs - [in] The instance to copy from. Has to be of the same + * class type as "this" object + * @return EC_Normal if copying was successful, error otherwise + */ + virtual OFCondition copyFrom(const DcmObject& rhs); + + /** return identifier for this class. Every class derived from this class + * returns a unique value of type enum DcmEVR for this call. This is used + * as a "poor man's RTTI" to correctly identify instances derived from + * this class even on compilers not supporting RTTI. + * @return type identifier of this class + */ + virtual DcmEVR ident() const { return EVR_SQ; } + + /** check if this element is a leaf node in a dataset tree. + * All subclasses of DcmElement except for DcmSequenceOfItems + * are leaf nodes, while DcmSequenceOfItems, DcmItem, DcmDataset etc. + * are not. + * @return true if leaf node, false otherwise. + */ + virtual OFBool isLeaf() const { return OFFalse; } + + /** print object to a stream + * @param out output stream + * @param flags optional flag used to customize the output (see DCMTypes::PF_xxx) + * @param level current level of nested items. Used for indentation. + * @param pixelFileName not used (used in certain sub-classes of this class) + * @param pixelCounter not used (used in certain sub-classes of this class) + */ + virtual void print(STD_NAMESPACE ostream&out, + const size_t flags = 0, + const int level = 0, + const char *pixelFileName = NULL, + size_t *pixelCounter = NULL); + + /** check whether stored value conforms to the VR and to the specified VM + * @param card cardinality (number of items) to be checked for. + * (See DcmElement::checkVM() for a list of valid values.) + * Parameter used to specify the value multiplicity for non-sequence attributes. + * @param oldFormat parameter not used for this VR (only for DA, TM) + * @return status of the check, EC_Normal if value is correct, an error code otherwise + */ + virtual OFCondition checkValue(const OFString &card = "1-n", + const OFBool oldFormat = OFFalse); + + /** get value multiplicity + * @return always returns 1 (according to the DICOM standard) + */ + virtual unsigned long getVM() { return 1L; } + + /** This function takes care of group length and padding elements + * in the current element list according to what is specified in + * glenc and padenc. If required, this function does the following + * two things: + * a) it calculates the group length of all groups which are + * contained in this item and sets the calculated values + * in the corresponding group length elements and + * b) it inserts a corresponding padding element (or, in case + * of sequences: padding elements) with a corresponding correct + * size into the element list. + * @param glenc Encoding type for group length; specifies what shall + * be done with group length tags. + * @param padenc Encoding type for padding; specifies what shall be + * done with padding tags. + * @param xfer The transfer syntax that shall be used. + * @param enctype Encoding type for sequences; specifies how sequences + * will be handled. + * @param padlen The length up to which the dataset shall be padded, + * if padding is desired. + * @param subPadlen For sequences (ie sub elements), the length up to + * which item shall be padded, if padding is desired. + * @param instanceLength Number of extra bytes added to the item/dataset + * length used when computing the padding; this + * parameter is for instance used to pass the length + * of the file meta header from the DcmFileFormat to + * the DcmDataset object. + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition computeGroupLengthAndPadding + (const E_GrpLenEncoding glenc, + const E_PaddingEncoding padenc = EPD_noChange, + const E_TransferSyntax xfer = EXS_Unknown, + const E_EncodingType enctype = EET_ExplicitLength, + const Uint32 padlen = 0, + const Uint32 subPadlen = 0, + Uint32 instanceLength = 0); + + /** calculate the length of this DICOM element when encoded with the + * given transfer syntax and the given encoding type for sequences. + * For elements, the length includes the length of the tag, length field, + * VR field and the value itself, for items and sequences it returns + * the length of the complete item or sequence including delimitation tags + * if applicable. + * If length encodig is set to be explicit and the total sequence size is + * larger than the available 32-bit length field, then undefined length + * is returned. If "dcmWriteOversizedSeqsAndItemsUndefined" is disabled, + * also the internal DcmObject errorFlag is set to EC_SeqOrItemContentOverflow + * in case the sequence content (excluding tag header etc.) is already too + * large. + * @param xfer transfer syntax for length calculation + * @param enctype sequence encoding type for length calculation + * @return length of DICOM element + */ + virtual Uint32 calcElementLength(const E_TransferSyntax xfer, + const E_EncodingType enctype); + + /** calculate the value length (without attribute tag, VR and length field) + * of this DICOM element when encoded with the given transfer syntax and + * the given encoding type for sequences. + * If length encodig is set to be explicit and the total sequence size is + * larger than the available 32-bit length field, then undefined length + * is returned. If "dcmWriteOversizedSeqsAndItemsImplicit" is disabled, + * also the internal DcmObject errorFlag is set to + * EC_SeqOrItemContentOverflow. + * @param xfer transfer syntax for length calculation + * @param enctype sequence encoding type for length calculation + * @return value length of DICOM element + */ + virtual Uint32 getLength(const E_TransferSyntax xfer = EXS_LittleEndianImplicit, + const E_EncodingType enctype = EET_UndefinedLength); + + /** initialize the transfer state of this object. This method must be called + * before this object is written to a stream or read (parsed) from a stream. + */ + virtual void transferInit(); + + /** finalize the transfer state of this object. This method must be called + * when reading/writing this object from/to a stream has been completed. + */ + virtual void transferEnd(); + + /** check if this DICOM object can be encoded in the given transfer syntax. + * @param newXfer transfer syntax in which the DICOM object is to be encoded + * @param oldXfer transfer syntax in which the DICOM object was read or created. + * @return true if object can be encoded in desired transfer syntax, false otherwise. + */ + virtual OFBool canWriteXfer(const E_TransferSyntax oldXfer, + const E_TransferSyntax newXfer); + + /** This function reads the information of all attributes which + * are captured in the input stream and captures this information + * in elementList. Each attribute is represented as an element + * in this list. If not all information for an attribute could be + * read from the stream, the function returns EC_StreamNotifyClient. + * @param inStream The stream which contains the information. + * @param xfer The transfer syntax which was used to encode + * the information in inStream. + * @param glenc Encoding type for group length; specifies + * what will be done with group length tags. + * @param maxReadLength Maximum read length for reading an attribute value. + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition read(DcmInputStream &inStream, + const E_TransferSyntax xfer, + const E_GrpLenEncoding glenc = EGL_noChange, + const Uint32 maxReadLength = DCM_MaxReadLength); + + /** write object to a stream + * @param outStream DICOM output stream + * @param oxfer output transfer syntax + * @param enctype encoding types (undefined or explicit length) + * @param wcache pointer to write cache object, may be NULL + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition write(DcmOutputStream &outStream, + const E_TransferSyntax oxfer, + const E_EncodingType enctype, + DcmWriteCache *wcache); + + /** write object in XML format + * @param out output stream to which the XML document is written + * @param flags optional flag used to customize the output (see DCMTypes::XF_xxx) + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition writeXML(STD_NAMESPACE ostream&out, + const size_t flags = 0); + + /** special write method for creation of digital signatures + * @param outStream DICOM output stream + * @param oxfer output transfer syntax + * @param enctype encoding types (undefined or explicit length) + * @param wcache pointer to write cache object, may be NULL + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition writeSignatureFormat(DcmOutputStream &outStream, + const E_TransferSyntax oxfer, + const E_EncodingType enctype, + DcmWriteCache *wcache); + + /** returns true if the current object may be included in a digital signature + * @return true if signable, false otherwise + */ + virtual OFBool isSignable() const; + + /** returns true if the object contains an element with Unknown VR at any nesting level + * @return true if the object contains an element with Unknown VR, false otherwise + */ + virtual OFBool containsUnknownVR() const; + + /** check if this object contains non-ASCII characters at any nesting level. Please note + * that this check is pretty simple and only works for single-byte character sets that + * do include the 7-bit ASCII codes, e.g. for the ISO 8859 family. In other words: All + * character codes below 128 are considered to be ASCII codes and all others are + * considered to be non-ASCII. + * @param checkAllStrings if true, also check elements with string values not affected + * by SpecificCharacterSet (0008,0005), default: only check PN, LO, LT, SH, ST, UC + * and UT + * @return true if object contains non-ASCII characters, false otherwise + */ + virtual OFBool containsExtendedCharacters(const OFBool checkAllStrings = OFFalse); + + /** check if this object is affected by SpecificCharacterSet at any nesting level. + * In detail, it is checked whether this object contains any data elements that + * according to their VR are affected by the SpecificCharacterSet (0008,0005) + * element. This is true for the following VRs: PN, LO, LT, SH, ST, UC and UT + * @return true if object is affected by SpecificCharacterSet, false otherwise + */ + virtual OFBool isAffectedBySpecificCharacterSet() const; + + /** convert all element values that are contained in this item and that are affected + * by SpecificCharacterSet from the currently selected source character set to the + * currently selected destination character set + * @param converter character set converter to be used to convert the element values + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition convertCharacterSet(DcmSpecificCharacterSet &converter); + + /** get cardinality of this sequence + * @return number of items in this sequence + */ + virtual unsigned long card() const; + + /** insert the given item at the start of the item list maintained by this sequence. + * Ownership of the item, which must be allocated on the heap, is transferred to the sequence. + * @param item pointer to DcmItem instance allocated on the heap, must not be NULL. + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition prepend(DcmItem *item); + + /** insert the given item at the given position within the item list maintained by this sequence. + * Ownership of the item, which must be allocated on the heap, is transferred to the sequence. + * @param item pointer to DcmItem instance allocated on the heap, must not be NULL. + * @param where index of the item after or before which the new item is to be inserted. + * Value must be < card() or equal to DCM_EndOfListIndex. + * @param before indicates whether the new item should be inserted before or after the item + * identified by "where" + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition insert(DcmItem *item, + unsigned long where = DCM_EndOfListIndex, + OFBool before = OFFalse); + + /** insert the given item at the end of the item list maintained by this sequence. + * Ownership of the item, which must be allocated on the heap, is transferred to the sequence. + * @param item pointer to DcmItem instance allocated on the heap, must not be NULL. + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition append(DcmItem *item); + + /** insert new item a current position. + * The current position is stored internally in the 'itemList' member variable. + * @param item new item to be inserted + * @param before flag indicating whether to insert the item before (OFFalse) or + * after (OFTrue) the current position + * @return status, EC_Normal upon success, an error code otherwise + */ + virtual OFCondition insertAtCurrentPos(DcmItem *item, + OFBool before = OFFalse); + + /** access an item from the sequence. This method returns a pointer to one + * of the items in the list, and not a copy. + * @param num index number of item, must be < card() + * @return pointer to item if found, NULL if num >= card() + */ + virtual DcmItem *getItem(const unsigned long num); + + /** this method enables a stack based, depth-first traversal of a complete + * hierarchical DICOM dataset (that is, classes derived from DcmItem or + * DcmSequenceOfItems). With each call of this method, the next object + * in the tree is located and marked on the stack. + * @param stack "cursor" for current position in the dataset. The stack + * will contain a pointer to each dataset, sequence, item and element + * from the main dataset down to the current element, and is updated + * upon each call to this method. An empty stack is equivalent to a stack + * containing a pointer to this object only. + * @param intoSub if true, the nextObject method will perform a hierarchical + * search through the dataset (depth-first), if false, only the current + * container object will be traversed (e.g., all elements of an item + * or all items of a sequence). + * @return EC_Normal if value length is correct, an error code otherwise + */ + virtual OFCondition nextObject(DcmStack &stack, const OFBool intoSub); + + /** this method is only used in container classes, + * that is, DcmItem and DcmSequenceOfItems. It returns a pointer to the + * next object in the list AFTER the given object. If the caller passes NULL, + * a pointer to the first object in the list is returned. If the given object + * is not found, the given object is the last one in the list or the list is empty, + * NULL is returned. + * @param obj pointer to one object in the container; we are looking for the + * next entry after this one. NULL if looking for the first entry. + * @return pointer to next object in container or NULL if not found + */ + virtual DcmObject *nextInContainer(const DcmObject *obj); + + /** remove item from list. If found, the item is not deleted but + * returned to the caller who is responsible for further management of the + * DcmItem object. + * @param num index number of item, must be < card() + * @return pointer to DcmItem if found, NULL otherwise + */ + virtual DcmItem *remove(const unsigned long num); + + /** remove item from list. If found, the item is not deleted but + * returned to the caller who is responsible for further management of the + * DcmItem object. + * @param item pointer to item to be removed from list + * @return pointer to item if found, NULL otherwise + */ + virtual DcmItem *remove(DcmItem *item); + + /** check if this sequence is empty + * @param normalize not used for this class + * @return true if sequence is empty, i.e. has no items, false otherwise + */ + virtual OFBool isEmpty(const OFBool normalize = OFTrue); + + /** clear (remove) attribute value + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition clear(); + + /** check the currently stored element value + * @param autocorrect correct value length if OFTrue + * @return status, EC_Normal if value length is correct, an error code otherwise + */ + virtual OFCondition verify(const OFBool autocorrect = OFFalse); + + /** a complex, stack-based, hierarchical search method. It allows for a search + * for a DICOM object with a given attribute within a given container, + * hierarchically, from a starting position identified through a cursor stack. + * @param xtag the DICOM attribute tag we are searching for + * @param resultStack Depending on the search mode (see below), this parameter + * either serves as an input and output parameter, or as an output parameter + * only (the latter being the default). When used as an input parameter, + * the cursor stack defines the start position for the search within a + * hierarchical DICOM dataset. Upon successful return, the stack contains + * the position of the element found, in the form of a pointer to each dataset, + * sequence, item and element from the main dataset down to the found element. + * @param mode search mode, controls how the search stack is handled. + * In the default mode, ESM_fromHere, the stack is ignored on input, and + * the search starts in the object for which this method is called. + * In the other modes, the stack is used both as an input and an output + * parameter and defines the starting point for the search. + * @param searchIntoSub if true, the search will be performed hierarchically descending + * into the sequences and items of the dataset. If false, only the current container + * (sequence or item) will be traversed. + * @return EC_Normal if found, EC_TagNotFound if not found, an error code is something went wrong. + */ + virtual OFCondition search(const DcmTagKey &xtag, // in + DcmStack &resultStack, // inout + E_SearchMode mode = ESM_fromHere, // in + OFBool searchIntoSub = OFTrue); // in + + /** this method loads all attribute values maintained by this object and + * all sub-objects (in case of a container such as DcmDataset) into memory. + * After a call to this method, the file from which a dataset was read may safely + * be deleted or replaced. For large files, this method may obviously allocate large + * amounts of memory. + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition loadAllDataIntoMemory(void); + + /** Copy numBytes bytes of data from the attribute value in byteOrder byte order + * to targetBuffer, starting at byte offset offset of the attribute value. + * This method does not cause the complete attribute value to be read into + * main memory. Subsequent calls for the same partial value may cause repeated + * access to file if the attribute value is kept in file. + * @param targetBuffer pointer to target buffer, must not be NULL. + * Buffer size must be at least numBytes bytes. + * @param offset byte offset within the attribute value from where to start + * copying + * @param numBytes number of bytes to copy. + * @param cache file cache object that may be passed to multiple subsequent calls + * to this method for the same file; the file cache will then keep a file + * handle open, thus improving performance. Optional, may be NULL + * @param byteOrder byte order desired byte order of attribute value in memory buffer. + * Default is the local byte order of the machine. + * @return EC_Normal upon success, an error code otherwise + */ + virtual OFCondition getPartialValue(void *targetBuffer, + const Uint32 offset, + Uint32 numBytes, + DcmFileCache *cache = NULL, + E_ByteOrder byteOrder = gLocalByteOrder); + +protected: + + /** This function reads tag and length information from inStream and + * returns this information to the caller. When reading information, + * the transfer syntax which was passed is accounted for. If the + * transfer syntax shows an explicit value representation, the data + * type of this object is also read from the stream. In general, this + * function follows the rules which are specified in the DICOM standard + * (see DICOM standard (year 2000) part 5, section 7) (or the corresponding + * section in a later version of the standard) concerning the encoding + * of a dataset. + * @param inStream The stream which contains the information. + * @param xfer The transfer syntax which was used to encode the + * information in inStream. + * @param tag Contains in the end the tag that was read. + * @param length Contains in the end the length value that was read. + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition readTagAndLength(DcmInputStream &inStream, // inout + const E_TransferSyntax xfer, // in + DcmTag &tag, // out + Uint32 &length); // out + + /** helper function for read(). Create sub-object (item, item delimiter or sequence delimiter) of the + * appropriate type depending on the tag. + * @param subObject upon success, a pointer to the newly created object is returned in this parameter + * @param newTag tag of the sub-object to be created + * @param newLength length of the sub-object to be created + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition makeSubObject(DcmObject *&subObject, + const DcmTag &newTag, + const Uint32 newLength); + + /** helper function for read(). Create sub-object (item or pixel item) + * and call read() for this sub-object. + * @param inStream The stream which contains the information. + * @param newTag attribute tag for sub-object + * @param newLength length of the sub-object to be created + * @param xfer The transfer syntax which was used to encode + * the information in inStream. + * @param glenc Encoding type for group length; specifies + * what will be done with group length tags. + * @param maxReadLength Maximum read length for reading an attribute value. + * @return status, EC_Normal if successful, an error code otherwise + */ + OFCondition readSubItem(DcmInputStream &inStream, // inout + const DcmTag &newTag, // in + const Uint32 newLength, // in + const E_TransferSyntax xfer, // in + const E_GrpLenEncoding glenc, // in + const Uint32 maxReadLength = DCM_MaxReadLength); // in + + /** helper function for search(). May only be called if item list is non-empty. + * Performs hierarchical search for given tag and pushes pointer of sub-element + * on result stack if found + * @param tag tag key to be searched + * @param resultStack upon successful return, pointer to element pushed onto this stack + * @param searchIntoSub flag indicating whether recursive search is desired + * @return EC_Normal if tag found and stack modified, EC_TagNotFound if tag not found and stack unmodified + */ + virtual OFCondition searchSubFromHere(const DcmTagKey &tag, // in + DcmStack &resultStack, // inout + const OFBool searchIntoSub); // in + + /// the list of items maintained by this sequence object + DcmList *itemList; + +private: + + /** static helper method used in writeSignatureFormat(). + * This function resembles DcmObject::writeTagAndLength() + * but only writes the tag, VR and reserved field. + * @param outStream stream to write to + * @param tag attribute tag + * @param vr attribute VR as reported by getVR + * @param oxfer output transfer syntax + * @return EC_Normal if successful, an error code otherwise + */ + static OFCondition writeTagAndVR(DcmOutputStream &outStream, + const DcmTag &tag, + DcmEVR vr, + const E_TransferSyntax oxfer); + + /** flag used during suspended I/O. Indicates whether the last item + * was completely or only partially read/written during the last call + * to read/write. + */ + OFBool lastItemComplete; + + /** used during reading. Contains the position in the stream where + * the sequence started (needed for calculating the remaining number of + * bytes available for a fixed-length sequence). + */ + offile_off_t fStartPosition; + + /** true if this sequence has been instantiated while reading an UN element + * with undefined length + */ + OFBool readAsUN_; + +}; + + +#endif // DCSEQUEN_H diff --git a/dcmdata/include/dcmtk/dcmdata/dcspchrs.h b/dcmdata/include/dcmtk/dcmdata/dcspchrs.h new file mode 100644 index 00000000..ca0f36c7 --- /dev/null +++ b/dcmdata/include/dcmtk/dcmdata/dcspchrs.h @@ -0,0 +1,330 @@ +/* + * + * Copyright (C) 2011-2015, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Joerg Riesmeier + * + * Purpose: Class for supporting the Specific Character Set attribute + * + */ + + +#ifndef DCSPCHRS_H +#define DCSPCHRS_H + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/ofstd/ofchrenc.h" +#include "dcmtk/ofstd/ofmap.h" +#include "dcmtk/dcmdata/dcdefine.h" + + +// forward declaration +class DcmItem; + + +/** A class for managing and converting between different DICOM character sets. + * The conversion relies on the OFCharacterEncoding class, which again relies + * on the libiconv toolkit (if available). + * @note Please note that a current limitation is that only a single value is + * allowed for the destination character set (i.e. no code extensions). Of + * course, for the source character set, also multiple values are supported. + */ +class DCMTK_DCMDATA_EXPORT DcmSpecificCharacterSet +{ + + public: + + /** constructor. Initializes the member variables. + */ + DcmSpecificCharacterSet(); + + /** destructor + */ + ~DcmSpecificCharacterSet(); + + /** clear the internal state. This also forgets about the currently + * selected character sets, so selectCharacterSet() has to be called again + * before a string can be converted with convertString(). + */ + void clear(); + + /** get currently selected source DICOM character set(s). Please note that + * the returned string can contain multiple values (defined terms separated + * by a backslash) if code extension techniques are used. Furthermore, + * the returned string is always normalized, i.e. leading and trailing + * spaces have been removed. + * @return currently selected source DICOM character set(s) or an empty + * string if none is selected (identical to ASCII, which is the default) + */ + const OFString &getSourceCharacterSet() const; + + /** get currently selected destination DICOM character set. Please note + * that the returned string, which contains a defined term, is always + * normalized, i.e. leading and trailing spaces have been removed. + * @return currently selected destination DICOM character set or an empty + * string if none is selected (identical to ASCII, which is the default) + */ + const OFString &getDestinationCharacterSet() const; + + /** get currently selected destination encoding, i.e. the name of the + * character set as used by libiconv for the conversion. If code + * extension techniques are used to switch between different character + * encodings, the main/default encoding is returned. + * @return currently selected destination encoding or an empty string if + * none is selected + */ + const OFString &getDestinationEncoding() const; + + /** get mode specifying whether a character that cannot be represented in + * the destination character encoding is approximated through one or more + * characters that look similar to the original one. See + * selectCharacterSet(). + * @return current value of the mode. OFTrue means that the mode is + * enabled, OFFalse means disabled. + */ + OFBool getTransliterationMode() const; + + /** get mode specifying whether characters that cannot be represented in + * the destination character encoding will be silently discarded + * @return current value of the mode. OFTrue means that the mode is + * enabled, OFFalse means disabled. + */ + OFBool getDiscardIllegalSequenceMode() const; + + /** select DICOM character sets for the input and output string, between + * which subsequent calls of convertString() convert. The defined terms + * for a particular character set can be found in the DICOM standard, e.g. + * "ISO_IR 100" for ISO 8859-1 (Latin 1) or "ISO_IR 192" for Unicode in + * UTF-8. An empty string denotes the default character repertoire, which + * is ASCII (7-bit). If multiple values are given for 'fromCharset' + * (separated by a backslash) code extension techniques are used and + * escape sequences may be encountered in the source string to switch + * between the specified character sets. + * @param fromCharset name of the source character set(s) used for the + * input string as given in the DICOM attribute + * Specific Character Set (0008,0005). Leading and + * trailing spaces are removed automatically (if + * present). + * @param toCharset name of the destination character set used for + * the output string. Only a single value is + * permitted (no code extensions). Leading and + * trailing spaces are removed automatically (if + * present). The default value is "ISO_IR 192" + * (Unicode in UTF-8). + * @param transliterate mode specifying whether a character that cannot + * be represented in the destination character + * encoding is approximated through one or more + * characters that look similar to the original + * one. By default, this mode is disabled. + * @param discardIllegal mode specifying whether characters that cannot + * be represented in the destination character + * encoding will be silently discarded. By + * default, this mode is disabled. + * @return status, EC_Normal if successful, an error code otherwise + */ + OFCondition selectCharacterSet(const OFString &fromCharset, + const OFString &toCharset = "ISO_IR 192", + const OFBool transliterate = OFFalse, + const OFBool discardIllegal = OFFalse); + + /** select DICOM character sets for the input and output string, between + * which subsequent calls of convertString() convert. The source + * character set is determined from the DICOM element Specific Character + * Set (0008,0005) stored in the given dataset/item. The defined terms + * for the destination character set can be found in the DICOM standard, + * e.g. "ISO_IR 100" for ISO 8859-1 (Latin 1) or "ISO_IR 192" for Unicode + * in UTF-8. An empty string denotes the default character repertoire, + * which is ASCII (7-bit). If multiple values are found in the Specific + * Character Set element of the given 'dataset' (separated by a backslash) + * code extension techniques are used and escape sequences may be + * encountered in the source string to switch between the specified + * character sets. + * @param dataset DICOM dataset or item from which the source + * character set should be retrieved. If the data + * element Specific Character Set (0008,0005) is + * empty or missing, the default character set + * (i.e. ASCII) is used. + * @param toCharset name of the destination character set used for + * the output string. Only a single value is + * permitted (no code extensions). Leading and + * trailing spaces are removed automatically (if + * present). The default value is "ISO_IR 192" + * (Unicode in UTF-8). + * @param transliterate mode specifying whether a character that cannot + * be represented in the destination character + * encoding is approximated through one or more + * characters that look similar to the original + * one. By default, this mode is disabled. + * @param discardIllegal mode specifying whether characters that cannot + * be represented in the destination character + * encoding will be silently discarded. By + * default, this mode is disabled. + * @return status, EC_Normal if successful, an error code otherwise + */ + OFCondition selectCharacterSet(DcmItem &dataset, + const OFString &toCharset = "ISO_IR 192", + const OFBool transliterate = OFFalse, + const OFBool discardIllegal = OFFalse); + + /** convert the given string from the selected source character set(s) to + * the selected destination character set. That means selectCharacterSet() + * has to be called prior to this method. + * @param fromString input string to be converted (using the currently + * selected source character set) + * @param toString reference to variable where the converted string + * (using the currently selected destination character + * set) is stored + * @param delimiters optional string of characters that are regarded as + * delimiters, i.e.\ when found the character set is + * switched back to the default. CR, LF and FF are + * always regarded as delimiters (see DICOM PS 3.5). + * @return status, EC_Normal if successful, an error code otherwise + */ + OFCondition convertString(const OFString &fromString, + OFString &toString, + const OFString &delimiters = ""); + + /** convert the given string from the selected source character set(s) to + * the selected destination character set. That means selectCharacterSet() + * has to be called prior to this method. Since the length of the input + * string has to be specified explicitly, the string can contain more than + * one NULL byte. + * @param fromString input string to be converted (using the currently + * selected character set) + * @param fromLength length of the input string (number of bytes without + * the trailing NULL byte) + * @param toString reference to variable where the converted string + * (using the currently selected destination character + * set) is stored + * @param delimiters optional string of characters that are regarded as + * delimiters, i.e.\ when found the character set is + * switched back to the default. CR, LF and FF are + * always regarded as delimiters (see DICOM PS 3.5). + * @return status, EC_Normal if successful, an error code otherwise + */ + OFCondition convertString(const char *fromString, + const size_t fromLength, + OFString &toString, + const OFString &delimiters = ""); + + // --- static helper functions --- + + /** check whether the underlying character set conversion library is + * available. If the library is not available, no conversion between + * different character sets will be possible. + * @return OFTrue if the character set conversion library is available, + * OFFalse otherwise + */ + static OFBool isConversionLibraryAvailable(); + + /** count characters in given UTF-8 string and return the resulting number + * of so-called "code points". Please note that invalid UTF-8 encodings + * are not handled properly. ASCII strings (7-bit) are also supported, + * although OFString::length() is probably much faster. + * @param utf8String valid character string with UTF-8 encoding + * @return number of characters (code points) in given UTF-8 string + */ + static size_t countCharactersInUTF8String(const OFString &utf8String); + + + protected: + + /// type definition of a map storing the identifier (key) of a character + /// set and the associated conversion descriptor + typedef OFMap T_DescriptorMap; + + /** determine the destination character encoding (as used by libiconv) from + * the given DICOM defined term (specific character set), and set the + * member variables accordingly. + * @param toCharset name of the destination character set used for the + * output string + * @return status, EC_Normal if successful, an error code otherwise + */ + OFCondition determineDestinationEncoding(const OFString &toCharset); + + /** select a particular DICOM character set without code extensions for + * subsequent conversions. The corresponding DICOM defined term for the + * source character set is determined from the member variable + * 'SourceCharacterSet'. + * @return status, EC_Normal if successful, an error code otherwise + */ + OFCondition selectCharacterSetWithoutCodeExtensions(); + + /** select a particular DICOM character set with code extensions for + * subsequent conversions. The corresponding DICOM defined terms for the + * source character set are determined from the member variable + * 'SourceCharacterSet'. + * @param sourceVM value multiplicity of the member variable + * 'SourceCharacterSet'. Usually, this value has + * already been determined by the calling method. + * @return status, EC_Normal if successful, an error code otherwise + */ + OFCondition selectCharacterSetWithCodeExtensions(const unsigned long sourceVM); + + /** close any currently open character set conversion descriptor(s). + * Afterwards, no conversion descriptor is selected, pretty much like + * after the initialization with the constructor. + */ + void closeConversionDescriptors(); + + /** check whether the given string contains at least one escape character + * (ESC), because it is used for code extension techniques like ISO 2022 + * @param strValue input string to be checked for any escape character + * @param strLength length of the input string + * @return OFTrue if an escape character has been found, OFFalse otherwise + */ + OFBool checkForEscapeCharacter(const char *strValue, + const size_t strLength) const; + + /** convert given string to octal format, i.e.\ all non-ASCII and control + * characters are converted to their octal representation. The total + * length of the string is always limited to a particular maximum (see + * implementation). If the converted string would be longer, it is + * cropped and "..." is appended to indicate this cropping. + * @param strValue input string to be converted and possibly cropped + * @param strLength length of the input string + * @return resulting string in octal format + */ + OFString convertToLengthLimitedOctalString(const char *strValue, + const size_t strLength) const; + + + private: + + // private undefined copy constructor + DcmSpecificCharacterSet(const DcmSpecificCharacterSet &); + + // private undefined assignment operator + DcmSpecificCharacterSet &operator=(const DcmSpecificCharacterSet &); + + /// selected source character set(s) based on one or more DICOM defined terms + OFString SourceCharacterSet; + + /// selected destination character set based on a single DICOM defined term + OFString DestinationCharacterSet; + + /// selected destination encoding based on names supported by the libiconv toolkit + OFString DestinationEncoding; + + /// character encoding converter + OFCharacterEncoding EncodingConverter; + + /// map of character set conversion descriptors + /// (only used if multiple character sets are needed) + T_DescriptorMap ConversionDescriptors; +}; + + +#endif diff --git a/dcmdata/include/dcmtk/dcmdata/dcstack.h b/dcmdata/include/dcmtk/dcmdata/dcstack.h new file mode 100644 index 00000000..beb92277 --- /dev/null +++ b/dcmdata/include/dcmtk/dcmdata/dcstack.h @@ -0,0 +1,152 @@ +/* + * + * Copyright (C) 1994-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Gerd Ehlers + * + * Purpose: stack class + * + */ + +#ifndef DCSTACK_H +#define DCSTACK_H + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ +#include "dcmtk/ofstd/oftypes.h" +#include "dcmtk/dcmdata/dcdefine.h" + +class DcmObject; // forward declaration + + +/** helper class used by DcmStack. Maintains a single stack entry. + */ +class DCMTK_DCMDATA_EXPORT DcmStackNode +{ +public: + /** constructor. + * @param obj object pointer for this stack entry + */ + DcmStackNode(DcmObject *obj); + + /// destructor, non virtual. + ~DcmStackNode(); + + /** return pointer maintained by this entry + * @return object pointer + */ + DcmObject *value() const; + +private: + /// private undefined copy constructor + DcmStackNode(const DcmStackNode &); + + /// private undefined copy assignment operator + DcmStackNode &operator=(const DcmStackNode &); + + /// pointer to next stack entry, NULL if last one + DcmStackNode *link; + + /// pointer to object referenced by this stack entry + DcmObject *objNodeValue; + + /// class DcmStack directly manipulates the pointer chain + friend class DcmStack; +}; + + +/** this class manages a stack of pointers to DcmObject instances. + * The objects pointed to are never touched, e.g. deleted. + */ +class DCMTK_DCMDATA_EXPORT DcmStack +{ +public: + /// default constructor, creates empty stack + DcmStack(); + + /** copy constructor. Only pointers to objects are copied, + * the DcmObject instances are not duplicated. + * @param arg stack to copy from + */ + DcmStack(const DcmStack& arg); + + /// destructor, not virtual. Do not derive from this class. + ~DcmStack(); + + /** copy assignment operator. Only pointers to objects are copied, + * the DcmObject instances are not duplicated. + * @param arg object to assign from + * @return reference to this object + */ + DcmStack& operator=(const DcmStack &arg); + + /** comparison operator, needed for MSVC5. + * @param arg stack to compare to + * @return true if stacks are equal, false otherwise + */ + OFBool operator==(const DcmStack& arg) const; + + /** dummy comparison operator, needed for MSVC5. + * @param arg stack to compare to + * @return true if the cardinality of this stack is smaller than the + * cardinality of arg, or if the cardinality is equal and pointer + * comparison, from the top to the bottom of the stack results + * in a smaller pointer for this stack. + */ + OFBool operator<(const DcmStack& arg) const; + + /** push new pointer do DcmObject instance on stack + * @param obj object pointer to push on stack + * @return pointer passed as obj + */ + DcmObject* push( DcmObject *obj ); + + /** removes uppermost entry from stack and returns it. + * @return uppermost stack entry + */ + DcmObject* pop(); + + /** returns uppermost entry of stack without removing it. + * @returns uppermost stack entry + */ + DcmObject* top() const; + + /** returns n-th element from stack without removing it. + * @return n-th element from stack + */ + DcmObject* elem(const unsigned long number) const; + + /** checks if the stack is empty + * @return true if stack is empty, false otherwise + */ + OFBool empty() const; + + /** returns cardinality (number of entries) of the stack + * @return cardinality of stack + */ + unsigned long card() const; + + /** returns the stack to default-constructed state, i.e. empty state. + */ + void clear(); + +private: + /// pointer to the upmost stack entry, NULL if empty + DcmStackNode *topNode_; + + /// current cardinality of the stack + unsigned long cardinality_; +}; + + +#endif // DCSTACK_H diff --git a/dcmdata/include/dcmtk/dcmdata/dcswap.h b/dcmdata/include/dcmtk/dcmdata/dcswap.h new file mode 100644 index 00000000..563780bd --- /dev/null +++ b/dcmdata/include/dcmtk/dcmdata/dcswap.h @@ -0,0 +1,85 @@ +/* + * + * Copyright (C) 1994-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Andreas Barth + * + * Purpose: byte order functions + * + */ + +#ifndef DCSWAP_H +#define DCSWAP_H + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ +#include "dcmtk/dcmdata/dcerror.h" +#include "dcmtk/dcmdata/dcxfer.h" /* for E_ByteOrder */ + +/** swap block of data from big-endian to little-endian or back if neccessary + * @param newByteOrder desired byte order of data block + * @param oldByteOrder current byte order of data block + * @param value pointer to block of data + * @param byteLength size of data block in bytes + * @param valWidth size of each value in the data block, in bytes + * @return EC_Normal if successful, an error code otherwise + */ +DCMTK_DCMDATA_EXPORT OFCondition swapIfNecessary( + const E_ByteOrder newByteOrder, + const E_ByteOrder oldByteOrder, + void * value, + const Uint32 byteLength, + const size_t valWidth); + +/** swap block of data from big-endian to little-endian or back + * @param value pointer to block of data + * @param byteLength size of data block in bytes + * @param valWidth size of each value in the data block, in bytes + */ +DCMTK_DCMDATA_EXPORT void swapBytes( + void * value, + const Uint32 byteLength, + const size_t valWidth); + +/** swap an Uint16 number from big-endian to little-endian or back + * @param toSwap number to be swapped + * @return swapped number + */ +DCMTK_DCMDATA_EXPORT Uint16 swapShort(const Uint16 toSwap); + +/** swap a sequence of two bytes from big-endian to little-endian or back + * @param toSwap pointer to object to swap + */ +inline void swap2Bytes(Uint8 * toSwap) +// swaps [byte0][byte1] to [byte1][byte0] +{ + Uint8 tmp = toSwap[0]; + toSwap[0] = toSwap[1]; + toSwap[1] = tmp; +} + +/** swap a sequence of four bytes from big-endian to little-endian or back + * @param toSwap pointer to object to swap + */ +inline void swap4Bytes(Uint8 * toSwap) +// swaps [byte0][byte1][byte2][byte3] to [byte3][byte2][byte1][byte0] +{ + Uint8 tmp = toSwap[0]; + toSwap[0] = toSwap[3]; + toSwap[3] = tmp; + tmp = toSwap[1]; + toSwap[1] = toSwap[2]; + toSwap[2] = tmp; +} + +#endif // DCSWAP_H diff --git a/dcmdata/include/dcmtk/dcmdata/dctag.h b/dcmdata/include/dcmtk/dcmdata/dctag.h new file mode 100644 index 00000000..ba1368ee --- /dev/null +++ b/dcmdata/include/dcmtk/dcmdata/dctag.h @@ -0,0 +1,220 @@ +/* + * + * Copyright (C) 1994-2015, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Gerd Ehlers, Andrew Hewett + * + * Purpose: Definition of the class DcmTag + * + */ + +#ifndef DCTAG_H +#define DCTAG_H + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ +#include "dcmtk/ofstd/ofcond.h" +#include "dcmtk/dcmdata/dctagkey.h" +#include "dcmtk/dcmdata/dcvr.h" + +/* +** Defines +*/ + +/// default attribute name for unknown attributes +#define DcmTag_ERROR_TagName "Unknown Tag & Data" + +/// macro for the "item" tag (avoid VR lookup) +#define DCM_ItemTag (DcmTag(DCM_Item, EVR_na)) +/// macro for the "item delimitation item" tag (avoid VR lookup) +#define DCM_ItemDelimitationItemTag (DcmTag(DCM_ItemDelimitationItem, EVR_na)) +/// macro for the "sequence delimitation item" tag (avoid VR lookup) +#define DCM_SequenceDelimitationItemTag (DcmTag(DCM_SequenceDelimitationItem, EVR_na)) +/// macro for the "internal use" tag (an attribute that is never used in DICOM) +#define DCM_InternalUseTag (DcmTag(DcmTagKey(0xfffe, 0xfffe), EVR_UNKNOWN)) + + +/** this class encapsulates an attribute tag (group, element) and a VR. + * It maintains a private creator name for private tags and caches + * the attribute name, once it is looked up in the data dictionary. + * This class maintains the interface to the DICOM data dictionary, + * i.e. performs look-ups of attribute VR and name in the background. + * Therefore, creation of DcmTag element is significantly more expensive + * than creation of simple DcmTagKey objects unless the VR is passed + * in the constructor. + */ +class DCMTK_DCMDATA_EXPORT DcmTag: public DcmTagKey +{ +public: + /// default constructor + DcmTag(); + + /** constructor. + * Initializes group/element from given tag key and performs + * a dictionary lookup for the VR. The lookup also considers + * private tags if the private creator is defined (not NULL). + * @param akey tag key + * @param privCreator private creator code (optional) + */ + DcmTag(const DcmTagKey& akey, const char *privCreator = NULL); + + /** constructor. + * Initializes group/element from given parameters and performs + * a dictionary lookup for the VR. The lookup also considers + * private tags if the private creator is defined (not NULL). + * @param g tag group + * @param e tag element + * @param privCreator private creator code (optional) + */ + DcmTag(Uint16 g, Uint16 e, const char *privCreator = NULL); + + /** constructor. + * Initializes group/element and VR from given parameters. + * No dictionary lookup needed/performed. + * @param akey tag key + * @param avr VR + */ + DcmTag(const DcmTagKey& akey, const DcmVR& avr); + + /** constructor. + * Initializes group/element and VR from given parameters. + * No dictionary lookup needed/performed. + * @param g tag group + * @param e tag element + * @param avr VR + */ + DcmTag(Uint16 g, Uint16 e, const DcmVR& avr); + + /// copy constructor + DcmTag(const DcmTag& tag); + + /// destructor + ~DcmTag(); + + /// copy assignment operator + DcmTag& operator=(const DcmTag& tag); + + /// set specific VR + DcmVR setVR(const DcmVR& avr); + + /// returns VR object by value + DcmVR getVR() const { return vr; } + + /// returns VR code + DcmEVR getEVR() const { return vr.getEVR(); } + + /// returns name of VR + const char* getVRName() const { return vr.getVRName(); } + + /** returns tag group + * @return tag group + */ + Uint16 getGTag() const { return getGroup(); } + + /** returns tag element + * @return tag element + */ + Uint16 getETag() const { return getElement(); } + + /** returns a copy of the tag key by value + * @return copy of tag key, by value + */ + DcmTagKey getXTag() const + { + return * OFstatic_cast(const DcmTagKey *, this); + } + + /** returns name of attribute tag. + * If name has not been accessed before, a dictionary lookup + * under consideration of the current private creator code + * is performed. If no attribute name is found, a default + * name is used. Never returns NULL. + * @return attribute tag name, never NULL. + */ + const char* getTagName(); + + /** returns the current private creator string for this object + * if any, NULL otherwise. + * @return creator code if present, NULL otherwise + */ + const char* getPrivateCreator() const; + + /** assigns a private creator code and deletes a possibly + * cached attribute name since the attribute name could + * change if a different private creator code is used. + * @param privCreator private creator code, may be NULL + */ + void setPrivateCreator(const char *privCreator); + + /** performs a look-up of the VR for the current tag key in the dictionary, + * under consideration of the private creator (if defined). + * If a dictionary entry is found, the VR of this object is copied + * from the dictionary entry, otherwise the VR remains unmodified. + */ + void lookupVRinDictionary(); + + /** returns true if a data element with the given tag and VR + * can be digitally signed, false otherwise + * @return true if signable, false otherwise + */ + OFBool isSignable() const; + + /** returns true if the VR used for writing is "UN" + */ + OFBool isUnknownVR() const; + + /// returns current status flag + OFCondition error() const { return errorFlag; } + + // --- static helper functions --- + + /** convert the given string to a DICOM tag value + * @param name name or tag of the attribute to be searched for. + * If the name of the attribute is given the spelling has to be consistent + * with the spelling used in the data dictionary (e.g. "PatientName"). + * If the tag values are used the format is "gggg,eeee" (i.e. two hexa- + * decimal numbers separated by a comma). + * @param value variable in which the resulting tag value is stored. + * If this functions fails to find the specified tag, this variable + * remains unchanged. + * @return status, EC_Normal upon success, an error code otherwise + */ + static OFCondition findTagFromName(const char *name, + DcmTag &value); +private: + + /** replace tagName with copy of given string + * @param c new tag name + */ + void updateTagName(const char *c); + + /** replace privateCreator with copy of given string + * @param c new private creator + */ + void updatePrivateCreator(const char *c); + + /// VR of this attribute tag + DcmVR vr; + + /// name of this attribute tag, remains NULL unless getTagName() is called + char *tagName; + + /// private creator code, remains NULL unless setPrivateCreator() is called + char *privateCreator; + + /// current error code, EC_Normal if a valid VR for the tag is known + OFCondition errorFlag; + +}; + +#endif /* !DCTAG_H */ diff --git a/dcmdata/include/dcmtk/dcmdata/dctagkey.h b/dcmdata/include/dcmtk/dcmdata/dctagkey.h new file mode 100644 index 00000000..b6275e3e --- /dev/null +++ b/dcmdata/include/dcmtk/dcmdata/dctagkey.h @@ -0,0 +1,419 @@ +/* + * + * Copyright (C) 1994-2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Andrew Hewett + * + * Purpose: Basis class for dicom tags. + * + */ + +#ifndef DCTAGKEY_H +#define DCTAGKEY_H + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/ofstd/ofstream.h" +#include "dcmtk/ofstd/ofstring.h" +#include "dcmtk/dcmdata/dcdefine.h" + +/* +** Defines +*/ + +/// macro for an "undefined" attribute tag that is never used in DICOM +#define DCM_UndefinedTagKey DcmTagKey(0xffff, 0xffff) + +/** class maintaining a attribute tag (group and element number) + */ +class DCMTK_DCMDATA_EXPORT DcmTagKey +{ +public: + + /** default constructor + */ + inline DcmTagKey(); + + /** copy constructor + * @param key [in] The tag key to initialize from + */ + inline DcmTagKey(const DcmTagKey& key); + + /** constructor + * @param g group + * @param e element + */ + inline DcmTagKey(Uint16 g, Uint16 e); + + /** destructor + */ + virtual inline ~DcmTagKey(); + + /** set value to given tag key + * @param key attribute tag to copy + */ + inline void set(const DcmTagKey& key); + + /** set value to given group and element + * @param g group + * @param e element + */ + inline void set(Uint16 g, Uint16 e); + + /** set group to given number + * @param g group + */ + inline void setGroup(Uint16 g); + + /** set element to given number + * @param e element + */ + inline void setElement(Uint16 e); + + /** returns group number + * @return returns the group number of the tag key + */ + inline Uint16 getGroup() const; + + /** returns element number + * @return returns the element number of the tag key + */ + inline Uint16 getElement() const; + + /** returns base tag, i.e. in case of a repeating group tag always the base + * group number 0x5000 (curve) or 0x6000 (overlay) is used. For non-repeating + * group tags "this" tag key is returned. + * @return returns the base tag of the tag key + */ + DcmTagKey getBaseTag() const; + + /** checks whether the tag key is a valid group length element. + * Also calls hasValidGroup(). + * @return returns OFTrue if tag key is a valid group length element + */ + inline OFBool isGroupLength() const; + + /** returns true if the tag key is private, i.e. whether it has an odd group + * number. Also hasValidGroup() is called. + * @return returns OFTrue if group is private and valid. + */ + inline OFBool isPrivate() const; + + /** returns true, if tag is a private reservation tag of the form (gggg,00xx) + * with "gggg" being odd and "xx" in the range of 10 and FF. + * @return returns OFTrue if tag key is a private reservation key + */ + inline OFBool isPrivateReservation() const; + + /** returns true, if group is valid (permitted in DICOM command or data sets). + * Referring to the standard, groups 1, 3, 5, 7 and 0xFFFF are illegal. + * @return returns OFTrue if tag key has a valid group number. + */ + inline OFBool hasValidGroup() const; + + /** generate a simple hash code for this attribute tag. + * Used for fast look-up in the DICOM dictionary. + * @return hash code for this tag + */ + inline Uint32 hash() const; + + /** assignment operator for initializing this tag key from an existing one + * @param key [in] The key to copy from + * @return "this" initialization + */ + inline DcmTagKey& operator = (const DcmTagKey& key); + + /** Comparison operator. Returns true if both group and element number + * are the same. + * @param key key to compare with + * @return true if tag keys are the same + */ + inline int operator == (const DcmTagKey& key) const; + + /** negation operator. Returns true if either group or element number + * are not the same. + * @param key key to compare with + * @return true if tag keys are not the same + */ + inline int operator != (const DcmTagKey& key) const; + + /** 'less than' operator. Returns true if the given tag key is greater + * than "this". + * @param key key to compare with + * @return true if given key is greater than "this" + */ + inline int operator < (const DcmTagKey& key) const; + + /** 'greater than' operator. Returns true if the given tag key is smaller + * than "this". + * @param key key to compare with + * @return true if "this" key is smaller than given one. + */ + inline int operator > (const DcmTagKey& key) const; + + /** 'less or equal' operator. Returns true if the given tag key is greater + * or the same as "this". + * @param key key to compare with + * @return true if given key is greater or the same as "this" + */ + inline int operator <= (const DcmTagKey& key) const; + + /** 'greater or equal' operator. Returns true if the given tag key is + * smaller or equal as "this". + * @param key key to compare with + * @return true if "this" key is smaller or equal to given one. + */ + inline int operator >= (const DcmTagKey& key) const; + + friend DCMTK_DCMDATA_EXPORT STD_NAMESPACE ostream& operator<<(STD_NAMESPACE ostream& s, const DcmTagKey& k); + + /** convert tag key to string having the form "(gggg,eeee)". + * @return the string representation of this tag key + */ + OFString toString() const; + + /** returns true if a data element with the given tag key can + * be digitally signed, false otherwise + * @return true if signable, false otherwise + */ + OFBool isSignableTag() const; + +protected: + + /// less-than operation comparing only group numbers + int groupLT(const DcmTagKey& key) const; + + /// greater-than operation comparing only group numbers + int groupGT(const DcmTagKey& key) const; + + /// comparison operation comparing only group numbers + int groupEQ(const DcmTagKey& key) const; + + /// less-than operation comparing only element numbers + int elementLT(const DcmTagKey& key) const; + + /// greater-than operation comparing only element numbers + int elementGT(const DcmTagKey& key) const; + + /// comparison operation comparing only element numbers + int elementEQ(const DcmTagKey& key) const; + +private: + + /// tag group number + Uint16 group; + /// tag element number + Uint16 element; + +}; + +/** stream output operator for tag keys + * @param s output stream + * @param k tag key + * @return reference to output stream + */ +DCMTK_DCMDATA_EXPORT STD_NAMESPACE ostream& operator<<(STD_NAMESPACE ostream& s, const DcmTagKey& k); + +/* +** inline versions of functions +*/ + +/* constructors and destructor */ + +inline +DcmTagKey::DcmTagKey() + : group(0xffff), + element(0xffff) +{ +} + +inline +DcmTagKey::DcmTagKey(const DcmTagKey& key) + : group(key.group), + element(key.element) +{ +} + +inline +DcmTagKey::DcmTagKey(Uint16 g, Uint16 e) + : group(g), + element(e) +{ +} + +inline +DcmTagKey::~DcmTagKey() +{ +} + +/* access methods */ + +inline void +DcmTagKey::set(const DcmTagKey& key) +{ + group = key.group; + element = key.element; +} + +inline void +DcmTagKey::set(Uint16 g, Uint16 e) +{ + group = g; + element = e; +} + +inline void +DcmTagKey::setGroup(Uint16 g) +{ + group = g; +} + +inline void +DcmTagKey::setElement(Uint16 e) +{ + element = e; +} + +inline Uint16 +DcmTagKey::getGroup() const +{ + return group; +} + +inline Uint16 +DcmTagKey::getElement() const +{ + return element; +} + +inline OFBool +DcmTagKey::isGroupLength() const +{ + return (element == 0) && hasValidGroup(); +} + +inline OFBool +DcmTagKey::isPrivate() const +{ + return ((group & 1) != 0 ) && hasValidGroup(); +} + +inline OFBool +DcmTagKey::isPrivateReservation() const +{ + // private reservation has element number ranging from 0x0010 to 0x00FF + return isPrivate() && (element >= 0x10) && (element <= 0xFF); +} + +inline OFBool +DcmTagKey::hasValidGroup() const +{ + // group numbers 1, 3, 5, 7 and 0xFFFF are illegal in DICOM + if (((group & 1) != 0) && ((group <= 7) || (group == 0xFFFF))) + return OFFalse; + else + return OFTrue; +} + +inline DcmTagKey& +DcmTagKey::operator=(const DcmTagKey& key) +{ + set(key); + return *this; +} + +/* Simple Hash Function */ + +inline Uint32 +DcmTagKey::hash() const +{ + // generate simple hash code + return (((getGroup() << 16) & 0xffff0000) | (getElement() & 0xffff)); +} + +/* Comparisons */ + +inline int +DcmTagKey::groupLT(const DcmTagKey& key) const +{ + return (getGroup() < key.getGroup()); +} + +inline int +DcmTagKey::groupGT(const DcmTagKey& key) const +{ + return (getGroup() > key.getGroup()); +} + +inline int +DcmTagKey::groupEQ(const DcmTagKey& key) const +{ + return getGroup() == key.getGroup(); +} + +inline int +DcmTagKey::elementLT(const DcmTagKey& key) const +{ + return (getElement() < key.getElement()); +} + +inline int +DcmTagKey::elementGT(const DcmTagKey& key) const +{ + return (getElement() > key.getElement()); +} + +inline int +DcmTagKey::elementEQ(const DcmTagKey& key) const +{ + return getElement() == key.getElement(); +} + +inline int +DcmTagKey::operator == (const DcmTagKey& key) const +{ + return ( groupEQ(key) && elementEQ(key) ); +} + +inline int +DcmTagKey::operator != (const DcmTagKey& key) const +{ + return !(*this == key); +} + +inline int +DcmTagKey::operator < (const DcmTagKey& key) const +{ + return (groupLT(key) || (groupEQ(key) && elementLT(key))); +} + +inline int +DcmTagKey::operator > (const DcmTagKey& key) const +{ + return (groupGT(key) || (groupEQ(key) && elementGT(key))); +} + +inline int +DcmTagKey::operator <= (const DcmTagKey& key) const +{ + return (*this < key) || (*this == key); +} + +inline int +DcmTagKey::operator >= (const DcmTagKey& key) const +{ + return (*this > key) || (*this == key); +} + +#endif diff --git a/dcmdata/include/dcmtk/dcmdata/dctk.h b/dcmdata/include/dcmtk/dcmdata/dctk.h new file mode 100644 index 00000000..3d0447d5 --- /dev/null +++ b/dcmdata/include/dcmtk/dcmdata/dctk.h @@ -0,0 +1,101 @@ +/* + * + * Copyright (C) 1994-2015, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Gerd Ehlers + * + * Purpose: include most dcmdata files that are usually required + * + */ + +#ifndef DCTK_H +#define DCTK_H + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +// various headers +#include "dcmtk/dcmdata/dctypes.h" +#include "dcmtk/dcmdata/dcswap.h" +#include "dcmtk/dcmdata/dcistrma.h" +#include "dcmtk/dcmdata/dcostrma.h" +#include "dcmtk/dcmdata/dcvr.h" +#include "dcmtk/dcmdata/dcxfer.h" +#include "dcmtk/dcmdata/dcuid.h" +#include "dcmtk/ofstd/ofdefine.h" + +// tags and dictionary +#include "dcmtk/dcmdata/dctagkey.h" +#include "dcmtk/dcmdata/dctag.h" +#include "dcmtk/dcmdata/dcdicent.h" +#include "dcmtk/dcmdata/dchashdi.h" +#include "dcmtk/dcmdata/dcdict.h" +#include "dcmtk/dcmdata/dcdeftag.h" + +// basis classes +#include "dcmtk/dcmdata/dcobject.h" +#include "dcmtk/dcmdata/dcelem.h" + +// classes for management of sequences and other lists +#include "dcmtk/dcmdata/dcitem.h" +#include "dcmtk/dcmdata/dcmetinf.h" +#include "dcmtk/dcmdata/dcdatset.h" +#include "dcmtk/dcmdata/dcsequen.h" +#include "dcmtk/dcmdata/dcfilefo.h" +#include "dcmtk/dcmdata/dcdicdir.h" +#include "dcmtk/dcmdata/dcpixseq.h" + +// element classes for string management (8-bit) +#include "dcmtk/dcmdata/dcbytstr.h" +#include "dcmtk/dcmdata/dcvrae.h" +#include "dcmtk/dcmdata/dcvras.h" +#include "dcmtk/dcmdata/dcvrcs.h" +#include "dcmtk/dcmdata/dcvrda.h" +#include "dcmtk/dcmdata/dcvrds.h" +#include "dcmtk/dcmdata/dcvrdt.h" +#include "dcmtk/dcmdata/dcvris.h" +#include "dcmtk/dcmdata/dcvrtm.h" +#include "dcmtk/dcmdata/dcvrui.h" +#include "dcmtk/dcmdata/dcvrur.h" + +// element classes for string management (8-bit and/or multi-byte) +#include "dcmtk/dcmdata/dcchrstr.h" +#include "dcmtk/dcmdata/dcvrlo.h" +#include "dcmtk/dcmdata/dcvrlt.h" +#include "dcmtk/dcmdata/dcvrpn.h" +#include "dcmtk/dcmdata/dcvrsh.h" +#include "dcmtk/dcmdata/dcvrst.h" +#include "dcmtk/dcmdata/dcvruc.h" +#include "dcmtk/dcmdata/dcvrut.h" + +// element class for byte and word value representations +#include "dcmtk/dcmdata/dcvrobow.h" +#include "dcmtk/dcmdata/dcpixel.h" +#include "dcmtk/dcmdata/dcovlay.h" + +// element classes for binary value fields +#include "dcmtk/dcmdata/dcvrat.h" +#include "dcmtk/dcmdata/dcvrss.h" +#include "dcmtk/dcmdata/dcvrus.h" +#include "dcmtk/dcmdata/dcvrsl.h" +#include "dcmtk/dcmdata/dcvrul.h" +#include "dcmtk/dcmdata/dcvrulup.h" +#include "dcmtk/dcmdata/dcvrfl.h" +#include "dcmtk/dcmdata/dcvrfd.h" +#include "dcmtk/dcmdata/dcvrof.h" +#include "dcmtk/dcmdata/dcvrod.h" + +// misc supporting tools +#include "dcmtk/dcmdata/cmdlnarg.h" + +#endif /* DCTK_H */ diff --git a/dcmdata/include/dcmtk/dcmdata/dctypes.h b/dcmdata/include/dcmtk/dcmdata/dctypes.h new file mode 100644 index 00000000..f5695915 --- /dev/null +++ b/dcmdata/include/dcmtk/dcmdata/dctypes.h @@ -0,0 +1,240 @@ +/* + * + * Copyright (C) 1994-2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Gerd Ehlers, Andrew Hewett + * + * Purpose: global type and constant definitions + * + */ + + +#ifndef DCTYPES_H +#define DCTYPES_H + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ +#include "dcmtk/oflog/oflog.h" +#include "dcmtk/dcmdata/dcdefine.h" + +#define INCLUDE_CSTDLIB +#include "dcmtk/ofstd/ofstdinc.h" + +BEGIN_EXTERN_C +#ifdef HAVE_SYS_TYPES_H +/* needed e.g. on Solaris for definition of size_t */ +#include +#endif +END_EXTERN_C + +/* +** Logging +*/ + +extern DCMTK_DCMDATA_EXPORT OFLogger DCM_dcmdataLogger; + +#define DCMDATA_TRACE(msg) OFLOG_TRACE(DCM_dcmdataLogger, msg) +#define DCMDATA_DEBUG(msg) OFLOG_DEBUG(DCM_dcmdataLogger, msg) +#define DCMDATA_INFO(msg) OFLOG_INFO(DCM_dcmdataLogger, msg) +#define DCMDATA_WARN(msg) OFLOG_WARN(DCM_dcmdataLogger, msg) +#define DCMDATA_ERROR(msg) OFLOG_ERROR(DCM_dcmdataLogger, msg) +#define DCMDATA_FATAL(msg) OFLOG_FATAL(DCM_dcmdataLogger, msg) + +/* +** Macro Definitions +*/ + +/// XML namespace URI for the dcmtk +#define DCMTK_XML_NAMESPACE_URI "http://dicom.offis.de/dcmtk" +/// XML namespace URI for Native DICOM Model (see DICOM part 19) +#define NATIVE_DICOM_MODEL_XML_NAMESPACE_URI "http://dicom.nema.org/PS3.19/models/NativeDICOM" + +// ANSI escape codes for color output of the print() method +#define DCMDATA_ANSI_ESCAPE_CODE_RESET "\033[0m" +#define DCMDATA_ANSI_ESCAPE_CODE_TAG "\033[22m\033[32m" +#define DCMDATA_ANSI_ESCAPE_CODE_VR "\033[22m\033[31m" +#define DCMDATA_ANSI_ESCAPE_CODE_VALUE "\033[1m\033[37m" +#define DCMDATA_ANSI_ESCAPE_CODE_INFO "\033[1m\033[30m" +#define DCMDATA_ANSI_ESCAPE_CODE_LENGTH "\033[22m\033[36m" +#define DCMDATA_ANSI_ESCAPE_CODE_VM "\033[22m\033[35m" +#define DCMDATA_ANSI_ESCAPE_CODE_NAME "\033[22m\033[33m" +#define DCMDATA_ANSI_ESCAPE_CODE_NAME_1 "\033[1m\033[33m" +#define DCMDATA_ANSI_ESCAPE_CODE_SEQUENCE "\033[22m\033[32m" +#define DCMDATA_ANSI_ESCAPE_CODE_SEQUENCE_1 "\033[1m\033[32m" +#define DCMDATA_ANSI_ESCAPE_CODE_ITEM "\033[1m\033[30m" +#define DCMDATA_ANSI_ESCAPE_CODE_LINE "\033[1m\033[30m" +#define DCMDATA_ANSI_ESCAPE_CODE_COMMENT "\033[1m\033[30m" + + +// include this file in doxygen documentation + +/** @file dctypes.h + * @brief type definitions for the dcmdata module + */ + + +/* +** Enumerated Types +*/ + +/// encoding type for sequences and sequence items +typedef enum { + /// defined length + EET_ExplicitLength = 0, + /// undefined length + EET_UndefinedLength = 1 +} E_EncodingType; + + +/// handling of group length elements when reading/writing a dataset +typedef enum { + /// no change of group length values, WARNING: DO NOT USE THIS VALUE FOR WRITE OPERATIONS + EGL_noChange = 0, + /// remove group length tags + EGL_withoutGL = 1, + /// add group length tags for every group + EGL_withGL = 2, + /// recalculate values for existing group length tags + EGL_recalcGL = 3 +} E_GrpLenEncoding; + +/// handling of dataset trailing padding +typedef enum { + /// no change of padding tags + EPD_noChange = 0, + /// remove all padding tags + EPD_withoutPadding = 1, + /// add padding tags + EPD_withPadding = 2 +} E_PaddingEncoding; + +/// search mode for hierarchical search operations +typedef enum { + /// start search from current object + ESM_fromHere = 0, + /// start search from object pointed to by stack top + ESM_fromStackTop = 1, + /// start search from object following the object pointed to by stack top + ESM_afterStackTop = 2 +} E_SearchMode; + +/// object state during transfer (read/write) operations +typedef enum { + /// object prepared for transfer, no data transferred yet + ERW_init = 0, + /// object transfer completed + ERW_ready = 1, + /// object transfer in progress + ERW_inWork = 2, + /// object not prepared for transfer operation + ERW_notInitialized = 3 +} E_TransferState; + +/// mode for file reading +typedef enum { + /// auto detect: fileformat or dataset + ERM_autoDetect = 0, + /// read as dataset (assume no meta header present) + ERM_dataset = 1, + /// read file format only, refuse if no meta-header + ERM_fileOnly = 2, + /// read meta-header only, do not read the dataset + ERM_metaOnly = 3 +} E_FileReadMode; + +/// mode for file writing +typedef enum { + /// write as fileformat (update only missing information, this is the old behavior) + EWM_fileformat = 0, + /// write as dataset (without meta header) + EWM_dataset = 1, + /// write as fileformat and update required information (e.g. SOP Class/Instance UID) + EWM_updateMeta = 2, + /// write as fileformat and create new meta header (do not retain existing information) + EWM_createNewMeta = 3, + /// write as fileformat but don't update the meta header (please be careful!) + EWM_dontUpdateMeta = 4 +} E_FileWriteMode; + + +/** General purpose class hiding constants from the global namespace. + */ +struct DCMTK_DCMDATA_EXPORT DCMTypes +{ + public: + + /** @name print() flags. + * These flags can be combined and passed to the print() methods. + */ + //@{ + + /// shorten long tag values (e.g. long texts, pixel data) + static const size_t PF_shortenLongTagValues; + + /// show hierarchical tree structure of the dataset + static const size_t PF_showTreeStructure; + + /// do not map well-known UID numbers to UID names (e.g. Transfer Syntax and SOP Class) + static const size_t PF_doNotMapUIDsToNames; + + /// quote non-ASCII string content as XML markup + static const size_t PF_convertToMarkup; + + /// quote non-ASCII string content as octal numbers + static const size_t PF_convertToOctalNumbers; + + /// use ANSI escape codes for output + static const size_t PF_useANSIEscapeCodes; + //@} + + /** @name writeXML() flags. + * These flags can be combined and passed to the writeXML() methods. + */ + //@{ + + /// add document type definition (DTD). DCMTK-specific format only. + static const size_t XF_addDocumentType; + + /// write binary data to XML output file. DCMTK-specific format only. + static const size_t XF_writeBinaryData; + + /// encode binary data as Base64 (MIME). + /// - For the DCMTK-specific format, the default is to use hex numbers. + /// - For the Native DICOM Model, the default is to use a UUID reference. + static const size_t XF_encodeBase64; + + /// use XML namespace URI. The value depends on the selected output format. + static const size_t XF_useXMLNamespace; + + /// embed content of document type definition. DCMTK-specific format only. + static const size_t XF_embedDocumentType; + + /// don't write name of the DICOM data elements. DCMTK-specific format only. + static const size_t XF_omitDataElementName; + + /// convert non-ASCII characters to numeric values. DCMTK-specific format only. + static const size_t XF_convertNonASCII; + + /// write data in "Native DICOM Model" format as defined for Application Hosting (DICOM part 19). + /// The default is to use the DCMTK-specific format. + static const size_t XF_useNativeModel; + + //@} +}; + + +// Undefined Length Identifier +const Uint32 DCM_UndefinedLength = 0xffffffff; + + +#endif /* !DCTYPES_H */ diff --git a/dcmdata/include/dcmtk/dcmdata/dcuid.h b/dcmdata/include/dcmtk/dcmdata/dcuid.h new file mode 100644 index 00000000..53c30b26 --- /dev/null +++ b/dcmdata/include/dcmtk/dcmdata/dcuid.h @@ -0,0 +1,775 @@ +/* + * + * Copyright (C) 1994-2015, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Andrew Hewett + * + * Purpose: + * Definitions of "well known" DICOM Unique Identifiers, + * routines for finding and creating UIDs. + * + */ + +#ifndef DCUID_H +#define DCUID_H + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/ofstd/oftypes.h" +#include "dcmtk/dcmdata/dcdefine.h" + +#define INCLUDE_CSTDLIB +#define INCLUDE_UNISTD +#include "dcmtk/ofstd/ofstdinc.h" + +// include this file in doxygen documentation + +/** @file dcuid.h + * @brief global definitions and functions for UID handling + */ + +/** return the name of a UID. + * Performs a table lookup and returns a pointer to a read-only string. + * @param uid UID string for which the name is to be looked up + * @param defaultValue default to return if UID not known + * @return name string or defaultValue if UID is unknown + */ +DCMTK_DCMDATA_EXPORT const char* dcmFindNameOfUID(const char* uid, const char* defaultValue = NULL); + +/** return the UID of a name. + * Performs a table lookup and returns a pointer to a read-only string. + * @param name name string for which the corresponding UID is to be looked up + * @return UID string or NULL if name is unknown + */ +DCMTK_DCMDATA_EXPORT const char* dcmFindUIDFromName(const char* name); + +/** an array of const strings containing all known Storage SOP Classes + * that fit into the conventional PATIENT-STUDY-SERIES-INSTANCE information + * model, i.e. everything a Storage SCP might want to store in a PACS. + * Special cases such as hanging protocol storage or the Storage SOP Class + * are not included in this list. + * WARNING: This list contains more than 64 entries, i.e. it is not possible + * to use this list to configure the association negotiation behavior of + * a Storage SCU that always proposes two presentation contexts for each + * SOP class. + */ +extern DCMTK_DCMDATA_EXPORT const char* dcmAllStorageSOPClassUIDs[]; + +/// number of entries in dcmAllStorageSOPClassUIDs. +extern DCMTK_DCMDATA_EXPORT const int numberOfAllDcmStorageSOPClassUIDs; + +/** an array of const strings containing all storage SOP classes that + * are proposed by default by those Storage SCU components in DCMTK + * that always propose one presentation context for each SOP class, + * e.g. movescu or dcmqrdb. This list is guaranteed to have at most + * 120 entries (to leave room for FIND/MOVE presentation contexts). + */ +extern DCMTK_DCMDATA_EXPORT const char* dcmLongSCUStorageSOPClassUIDs[]; + +/// number of entries in dcmLongSCUStorageSOPClassUIDs. +extern DCMTK_DCMDATA_EXPORT const int numberOfDcmLongSCUStorageSOPClassUIDs; + +/** an array of const strings containing all storage SOP classes that + * are proposed by default by those Storage SCU components in DCMTK + * that always propose TWO presentation context for each SOP class, + * e.g. storescu. This list is guaranteed to have at most + * 64 entries. + */ +extern DCMTK_DCMDATA_EXPORT const char* dcmShortSCUStorageSOPClassUIDs[]; + +/// number of entries in dcmShortSCUStorageSOPClassUIDs. +extern DCMTK_DCMDATA_EXPORT const int numberOfDcmShortSCUStorageSOPClassUIDs; + +/** returns true if the uid is one of the Storage SOP Classes. + * Performs a table lookup in the dcmAllStorageSOPClassUIDs table. + * @param uid UID string + * @return true if UID is a known Storage SOP Class, false otherwise + */ +DCMTK_DCMDATA_EXPORT OFBool dcmIsaStorageSOPClassUID(const char* uid); + +/** a global constant array of + * string pointers containing the UIDs of all known Image SOP + * Classes. The global variable numberOfDcmImageSOPClassUIDs + * defines the size of the array. + * NOTE: this list represents a subset of the dcmStorageSOPClassUIDs list + */ +extern DCMTK_DCMDATA_EXPORT const char* dcmImageSOPClassUIDs[]; + +/// number of entries in dcmImageSOPClassUIDs +extern DCMTK_DCMDATA_EXPORT const int numberOfDcmImageSOPClassUIDs; + +/** returns true if the uid is one of the Image Storage SOP Classes. + * Performs a table lookup in the dcmImageSOPClassUIDs table. + * @param uid UID string + * @return true if UID is a known Image Storage SOP Class, false otherwise + */ +DCMTK_DCMDATA_EXPORT OFBool dcmIsImageStorageSOPClassUID(const char* uid); + +/** creates a Unique Identifier in uid and returns uid. + * uid must be at least 65 bytes. Care is taken to make sure + * that the generated UID is 64 characters or less. + * If a prefix string is not passed as the second argument a + * default of SITE_INSTANCE_UID_ROOT (see below) will be used. + * Otherwise the supplied prefix string will appear at the beginning + * of uid. + * The UID is created by appending to the prefix the following: + * - the host ID (if obtainable, zero otherwise), + * - the process ID (if obtainable, zero otherwise), + * - the system calendar time, and + * - an accumulating counter for this process. + * @param uid pointer to buffer of 65 or more characters in which the UID is returned + * @param prefix prefix for UID creation + * @return pointer to UID, identical to uid parameter + */ +DCMTK_DCMDATA_EXPORT char *dcmGenerateUniqueIdentifier(char *uid, const char* prefix=NULL); + +/** performs a table lookup and returns a short modality identifier + * that can be used for building file names etc. + * Identifiers are defined for all storage SOP classes. + * Returns 'defaultValue' if no modality identifier found or sopClassUID==NULL. + * @param sopClassUID UID string + * @param defaultValue default to return if UID not known + * @return modality string for modality UID, or defaultValue if not found + */ +DCMTK_DCMDATA_EXPORT const char *dcmSOPClassUIDToModality(const char *sopClassUID, const char *defaultValue = NULL); + +/** performs a table lookup and returns a guessed average + * file size for the given SOP class. + * Average sizes are defined for all storage SOP classes, but may be very far off. + * @param sopClassUID UID string + * @return estimated average size for objects of this SOP class + */ +DCMTK_DCMDATA_EXPORT unsigned long dcmGuessModalityBytes(const char *sopClassUID); + +/* +** String Constants +*/ + +/* +** OFFIS UID is: 1.2.276.0.7230010 +** UID root for OFFIS DCMTK project: 1.2.276.0.7230010.3 +** for OFFIS GO-Kard project: 1.2.276.0.7230010.8 +*/ + +#ifndef PACKAGE_DATE +#error Required compiler definition PACKAGE_DATE undefined +#endif +#ifndef PACKAGE_VERSION +#error Required compiler definition PACKAGE_VERSION undefined +#endif +#ifndef PACKAGE_VERSION_NUMBER +#error Required compiler definition PACKAGE_VERSION_NUMBER undefined +#endif + +// helper macros for version number conversion + +#define PACKAGE_VERSION_NUMBER_TO_STRING_( x ) #x +#define PACKAGE_VERSION_NUMBER_TO_STRING( x ) PACKAGE_VERSION_NUMBER_TO_STRING_( x ) + +/* NOTE: Implementation version name VR=SH may not be longer than 16 chars + * The second name is used to identify files written without dcmdata + * (i.e. using the --bit-preserving switch in various tools) + */ + +/// implementation version name for this version of the toolkit +#define OFFIS_DTK_IMPLEMENTATION_VERSION_NAME "OFFIS_DCMTK_" PACKAGE_VERSION_NUMBER_TO_STRING(PACKAGE_VERSION_NUMBER) + +/// implementation version name for this version of the toolkit, used for files received in "bit preserving" mode +#define OFFIS_DTK_IMPLEMENTATION_VERSION_NAME2 "OFFIS_DCMBP_" PACKAGE_VERSION_NUMBER_TO_STRING(PACKAGE_VERSION_NUMBER) + +/// release date of current toolkit release +#ifdef DCMTK_BUILD_DATE +#define OFFIS_DCMTK_RELEASEDATE DCMTK_BUILD_DATE +#else +#define OFFIS_DCMTK_RELEASEDATE PACKAGE_DATE +#endif + +/// UID root for DCMTK, registered for OFFIS with DIN in Germany +#define OFFIS_UID_ROOT "1.2.276.0.7230010.3" + +/// DCMTK version number for this release +#define OFFIS_DCMTK_VERSION_NUMBER PACKAGE_VERSION_NUMBER + +/// DCMTK version number (as string) for this release +#define OFFIS_DCMTK_VERSION_STRING PACKAGE_VERSION + +/// DCMTK version number suffix string for this release +#define OFFIS_DCMTK_VERSION_SUFFIX PACKAGE_VERSION_SUFFIX + +/// DCMTK version number string including suffix +#define OFFIS_DCMTK_VERSION OFFIS_DCMTK_VERSION_STRING OFFIS_DCMTK_VERSION_SUFFIX + +/// Implementation class UID for this release of the toolkit +#define OFFIS_IMPLEMENTATION_CLASS_UID OFFIS_UID_ROOT ".0." OFFIS_DCMTK_VERSION_STRING + +/// Instance creator UID for this release of the toolkit +#define OFFIS_INSTANCE_CREATOR_UID OFFIS_IMPLEMENTATION_CLASS_UID + +/// private coding scheme UID root for coding schemes generated by OFFIS +#define OFFIS_CODING_SCHEME_UID_ROOT OFFIS_UID_ROOT ".0.0" + +/// private coding scheme version for coding schemes generated by OFFIS +#define OFFIS_CODING_SCHEME_VERSION "1" + +/// private coding scheme UID for coding schemes generated by OFFIS +#define OFFIS_CODING_SCHEME_UID OFFIS_CODING_SCHEME_UID_ROOT "." OFFIS_CODING_SCHEME_VERSION + +/* +** Each site should define its own SITE_UID_ROOT +*/ +#ifndef SITE_UID_ROOT +/// UID root to be used when generating UIDs. By default uses the DCMTK root, but can be replaced at compile time. +#define SITE_UID_ROOT OFFIS_UID_ROOT /* default */ +#endif + +/* +** Useful UID prefixes. These can be whatever you want. +** +** These site UIDs are arbitrary, non-standard, with no meaning +** and can be changed at any time. Do _not_ rely on these values. +** Do _not_ assume any semantics when using these suffixes. +** +*/ + +/// UID root for study instance UIDs +#define SITE_STUDY_UID_ROOT SITE_UID_ROOT ".1.2" + +/// UID root for series instance UIDs +#define SITE_SERIES_UID_ROOT SITE_UID_ROOT ".1.3" + +/// UID root for SOP instance UIDs +#define SITE_INSTANCE_UID_ROOT SITE_UID_ROOT ".1.4" + +/** A private SOP Class UID which is used in a file meta-header when no + * instance of a Storage SOP Class is stored in the file. -- NON-STANDARD + */ +#define UID_PrivateGenericFileSOPClass SITE_UID_ROOT ".1.0.1" + +/// DICOM Defined Standard Application Context UID +#define UID_StandardApplicationContext "1.2.840.10008.3.1.1.1" + +/* +** Defined Transfer Syntax UIDs +*/ + +/// Implicit VR Little Endian: Default Transfer Syntax for DICOM +#define UID_LittleEndianImplicitTransferSyntax "1.2.840.10008.1.2" +/// Explicit VR Little Endian +#define UID_LittleEndianExplicitTransferSyntax "1.2.840.10008.1.2.1" +/// Explicit VR Big Endian - RETIRED +#define UID_BigEndianExplicitTransferSyntax "1.2.840.10008.1.2.2" +/// Deflated Explicit VR Little Endian +#define UID_DeflatedExplicitVRLittleEndianTransferSyntax "1.2.840.10008.1.2.1.99" +/** JPEG Baseline (Process 1): Default Transfer Syntax + * for Lossy JPEG 8 Bit Image Compression + */ +#define UID_JPEGProcess1TransferSyntax "1.2.840.10008.1.2.4.50" +/** JPEG Extended (Process 2 & 4): Default Transfer Syntax + * for Lossy JPEG 12 Bit Image Compression (Process 4 only) + */ +#define UID_JPEGProcess2_4TransferSyntax "1.2.840.10008.1.2.4.51" +/// JPEG Extended (Process 3 & 5) - RETIRED +#define UID_JPEGProcess3_5TransferSyntax "1.2.840.10008.1.2.4.52" +/// JPEG Spectral Selection, Non-Hierarchical (Process 6 & 8) - RETIRED +#define UID_JPEGProcess6_8TransferSyntax "1.2.840.10008.1.2.4.53" +/// JPEG Spectral Selection, Non-Hierarchical (Process 7 & 9) - RETIRED +#define UID_JPEGProcess7_9TransferSyntax "1.2.840.10008.1.2.4.54" +/// JPEG Full Progression, Non-Hierarchical (Process 10 & 12) - RETIRED +#define UID_JPEGProcess10_12TransferSyntax "1.2.840.10008.1.2.4.55" +/// JPEG Full Progression, Non-Hierarchical (Process 11 & 13) - RETIRED +#define UID_JPEGProcess11_13TransferSyntax "1.2.840.10008.1.2.4.56" +/// JPEG Lossless, Non-Hierarchical (Process 14) +#define UID_JPEGProcess14TransferSyntax "1.2.840.10008.1.2.4.57" +/// JPEG Lossless, Non-Hierarchical (Process 15) - RETIRED +#define UID_JPEGProcess15TransferSyntax "1.2.840.10008.1.2.4.58" +/// JPEG Extended, Hierarchical (Process 16 & 18) - RETIRED +#define UID_JPEGProcess16_18TransferSyntax "1.2.840.10008.1.2.4.59" +/// JPEG Extended, Hierarchical (Process 17 & 19) - RETIRED +#define UID_JPEGProcess17_19TransferSyntax "1.2.840.10008.1.2.4.60" +/// JPEG Spectral Selection, Hierarchical (Process 20 & 22) - RETIRED +#define UID_JPEGProcess20_22TransferSyntax "1.2.840.10008.1.2.4.61" +/// JPEG Spectral Selection, Hierarchical (Process 21 & 23) - RETIRED +#define UID_JPEGProcess21_23TransferSyntax "1.2.840.10008.1.2.4.62" +/// JPEG Full Progression, Hierarchical (Process 24 & 26) - RETIRED +#define UID_JPEGProcess24_26TransferSyntax "1.2.840.10008.1.2.4.63" +/// JPEG Full Progression, Hierarchical (Process 25 & 27) - RETIRED +#define UID_JPEGProcess25_27TransferSyntax "1.2.840.10008.1.2.4.64" +/// JPEG Lossless, Hierarchical (Process 28) - RETIRED +#define UID_JPEGProcess28TransferSyntax "1.2.840.10008.1.2.4.65" +/// JPEG Lossless, Hierarchical (Process 29) - RETIRED +#define UID_JPEGProcess29TransferSyntax "1.2.840.10008.1.2.4.66" +/** JPEG Lossless, Non-Hierarchical, First-Order Prediction (Process 14 + * [Selection Value 1]): Default Transfer Syntax for Lossless JPEG Image Compression + */ +#define UID_JPEGProcess14SV1TransferSyntax "1.2.840.10008.1.2.4.70" +/// JPEG-LS Lossless Image Compression +#define UID_JPEGLSLosslessTransferSyntax "1.2.840.10008.1.2.4.80" +/// JPEG-LS Lossy (Near-Lossless) Image Compression +#define UID_JPEGLSLossyTransferSyntax "1.2.840.10008.1.2.4.81" +/// JPEG 2000 Image Compression (Lossless Only) +#define UID_JPEG2000LosslessOnlyTransferSyntax "1.2.840.10008.1.2.4.90" +/// JPEG 2000 Image Compression (Lossless or Lossy) +#define UID_JPEG2000TransferSyntax "1.2.840.10008.1.2.4.91" +/// JPEG 2000 Part 2 Multi-component Image Compression (Lossless Only) +#define UID_JPEG2000Part2MulticomponentImageCompressionLosslessOnlyTransferSyntax "1.2.840.10008.1.2.4.92" +/// JPEG 2000 Part 2 Multi-component Image Compression (Lossless or Lossy) +#define UID_JPEG2000Part2MulticomponentImageCompressionTransferSyntax "1.2.840.10008.1.2.4.93" +/// JPIP Referenced +#define UID_JPIPReferencedTransferSyntax "1.2.840.10008.1.2.4.94" +/// JPIP Referenced Deflate +#define UID_JPIPReferencedDeflateTransferSyntax "1.2.840.10008.1.2.4.95" +/// MPEG2 Main Profile @ Main Level +#define UID_MPEG2MainProfileAtMainLevelTransferSyntax "1.2.840.10008.1.2.4.100" +/// MPEG2 Main Profile @ High Level +#define UID_MPEG2MainProfileAtHighLevelTransferSyntax "1.2.840.10008.1.2.4.101" +/// MPEG-4 AVC/H.264 High Profile / Level 4.1 +#define UID_MPEG4HighProfileLevel4_1TransferSyntax "1.2.840.10008.1.2.4.102" +/// MPEG-4 AVC/H.264 BD-compatible High Profile / Level 4.1 +#define UID_MPEG4BDcompatibleHighProfileLevel4_1TransferSyntax "1.2.840.10008.1.2.4.103" +/// MPEG-4 AVC/H.264 High Profile / Level 4.2 For 2D Video +#define UID_MPEG4HighProfileLevel4_2_For2DVideoTransferSyntax "1.2.840.10008.1.2.4.104" +/// MPEG-4 AVC/H.264 High Profile / Level 4.2 For 3D Video +#define UID_MPEG4HighProfileLevel4_2_For3DVideoTransferSyntax "1.2.840.10008.1.2.4.105" +/// MPEG-4 AVC/H.264 Stereo High Profile / Level 4.2 +#define UID_MPEG4StereoHighProfileLevel4_2TransferSyntax "1.2.840.10008.1.2.4.106" +/// RLE Lossless +#define UID_RLELosslessTransferSyntax "1.2.840.10008.1.2.5" + +/** MIME encapsulation (Supplement 101) is only a pseudo transfer syntax used to + * refer to MIME encapsulated HL7 CDA documents from a DICOMDIR when stored + * on a DICOM storage medium. It is never used for network communication + * or encoding of DICOM objects. + */ +#define UID_RFC2557MIMEEncapsulationTransferSyntax "1.2.840.10008.1.2.6.1" + +/** XML encoding (Supplement 114) is only a pseudo transfer syntax used to refer to + * encapsulated HL7 CDA documents from a DICOMDIR when stored on a DICOM storage + * medium. It is never used for network communication or encoding of DICOM objects. + */ +#define UID_XMLEncodingTransferSyntax "1.2.840.10008.1.2.6.2" + +/* +** Defined SOP Class UIDs according to DICOM standard +*/ + +// Storage +#define UID_RETIRED_StoredPrintStorage "1.2.840.10008.5.1.1.27" +#define UID_RETIRED_HardcopyGrayscaleImageStorage "1.2.840.10008.5.1.1.29" +#define UID_RETIRED_HardcopyColorImageStorage "1.2.840.10008.5.1.1.30" +#define UID_ComputedRadiographyImageStorage "1.2.840.10008.5.1.4.1.1.1" +#define UID_DigitalXRayImageStorageForPresentation "1.2.840.10008.5.1.4.1.1.1.1" +#define UID_DigitalXRayImageStorageForProcessing "1.2.840.10008.5.1.4.1.1.1.1.1" +#define UID_DigitalMammographyXRayImageStorageForPresentation "1.2.840.10008.5.1.4.1.1.1.2" +#define UID_DigitalMammographyXRayImageStorageForProcessing "1.2.840.10008.5.1.4.1.1.1.2.1" +#define UID_DigitalIntraOralXRayImageStorageForPresentation "1.2.840.10008.5.1.4.1.1.1.3" +#define UID_DigitalIntraOralXRayImageStorageForProcessing "1.2.840.10008.5.1.4.1.1.1.3.1" +#define UID_CTImageStorage "1.2.840.10008.5.1.4.1.1.2" +#define UID_EnhancedCTImageStorage "1.2.840.10008.5.1.4.1.1.2.1" +#define UID_LegacyConvertedEnhancedCTImageStorage "1.2.840.10008.5.1.4.1.1.2.2" +#define UID_RETIRED_UltrasoundMultiframeImageStorage "1.2.840.10008.5.1.4.1.1.3" +#define UID_UltrasoundMultiframeImageStorage "1.2.840.10008.5.1.4.1.1.3.1" +#define UID_MRImageStorage "1.2.840.10008.5.1.4.1.1.4" +#define UID_EnhancedMRImageStorage "1.2.840.10008.5.1.4.1.1.4.1" +#define UID_MRSpectroscopyStorage "1.2.840.10008.5.1.4.1.1.4.2" +#define UID_EnhancedMRColorImageStorage "1.2.840.10008.5.1.4.1.1.4.3" +#define UID_LegacyConvertedEnhancedMRImageStorage "1.2.840.10008.5.1.4.1.1.4.4" +#define UID_RETIRED_NuclearMedicineImageStorage "1.2.840.10008.5.1.4.1.1.5" +#define UID_RETIRED_UltrasoundImageStorage "1.2.840.10008.5.1.4.1.1.6" +#define UID_UltrasoundImageStorage "1.2.840.10008.5.1.4.1.1.6.1" +#define UID_EnhancedUSVolumeStorage "1.2.840.10008.5.1.4.1.1.6.2" +#define UID_SecondaryCaptureImageStorage "1.2.840.10008.5.1.4.1.1.7" +#define UID_MultiframeSingleBitSecondaryCaptureImageStorage "1.2.840.10008.5.1.4.1.1.7.1" +#define UID_MultiframeGrayscaleByteSecondaryCaptureImageStorage "1.2.840.10008.5.1.4.1.1.7.2" +#define UID_MultiframeGrayscaleWordSecondaryCaptureImageStorage "1.2.840.10008.5.1.4.1.1.7.3" +#define UID_MultiframeTrueColorSecondaryCaptureImageStorage "1.2.840.10008.5.1.4.1.1.7.4" +#define UID_RETIRED_StandaloneOverlayStorage "1.2.840.10008.5.1.4.1.1.8" +#define UID_RETIRED_StandaloneCurveStorage "1.2.840.10008.5.1.4.1.1.9" +#define UID_TwelveLeadECGWaveformStorage "1.2.840.10008.5.1.4.1.1.9.1.1" +#define UID_GeneralECGWaveformStorage "1.2.840.10008.5.1.4.1.1.9.1.2" +#define UID_AmbulatoryECGWaveformStorage "1.2.840.10008.5.1.4.1.1.9.1.3" +#define UID_HemodynamicWaveformStorage "1.2.840.10008.5.1.4.1.1.9.2.1" +#define UID_CardiacElectrophysiologyWaveformStorage "1.2.840.10008.5.1.4.1.1.9.3.1" +#define UID_BasicVoiceAudioWaveformStorage "1.2.840.10008.5.1.4.1.1.9.4.1" +#define UID_GeneralAudioWaveformStorage "1.2.840.10008.5.1.4.1.1.9.4.2" +#define UID_ArterialPulseWaveformStorage "1.2.840.10008.5.1.4.1.1.9.5.1" +#define UID_RespiratoryWaveformStorage "1.2.840.10008.5.1.4.1.1.9.6.1" +#define UID_RETIRED_StandaloneModalityLUTStorage "1.2.840.10008.5.1.4.1.1.10" +#define UID_RETIRED_StandaloneVOILUTStorage "1.2.840.10008.5.1.4.1.1.11" +#define UID_GrayscaleSoftcopyPresentationStateStorage "1.2.840.10008.5.1.4.1.1.11.1" +#define UID_ColorSoftcopyPresentationStateStorage "1.2.840.10008.5.1.4.1.1.11.2" +#define UID_PseudoColorSoftcopyPresentationStateStorage "1.2.840.10008.5.1.4.1.1.11.3" +#define UID_BlendingSoftcopyPresentationStateStorage "1.2.840.10008.5.1.4.1.1.11.4" +#define UID_XAXRFGrayscaleSoftcopyPresentationStateStorage "1.2.840.10008.5.1.4.1.1.11.5" +#define UID_GrayscalePlanarMPRVolumetricPresentationStateStorage "1.2.840.10008.5.1.4.1.1.11.6" +#define UID_CompositingPlanarMPRVolumetricPresentationStateStorage "1.2.840.10008.5.1.4.1.1.11.7" +#define UID_XRayAngiographicImageStorage "1.2.840.10008.5.1.4.1.1.12.1" +#define UID_EnhancedXAImageStorage "1.2.840.10008.5.1.4.1.1.12.1.1" +#define UID_XRayRadiofluoroscopicImageStorage "1.2.840.10008.5.1.4.1.1.12.2" +#define UID_EnhancedXRFImageStorage "1.2.840.10008.5.1.4.1.1.12.2.1" +#define UID_RETIRED_XRayAngiographicBiPlaneImageStorage "1.2.840.10008.5.1.4.1.1.12.3" +#define UID_XRay3DAngiographicImageStorage "1.2.840.10008.5.1.4.1.1.13.1.1" +#define UID_XRay3DCraniofacialImageStorage "1.2.840.10008.5.1.4.1.1.13.1.2" +#define UID_BreastTomosynthesisImageStorage "1.2.840.10008.5.1.4.1.1.13.1.3" +#define UID_BreastProjectionXRayImageStorageForPresentation "1.2.840.10008.5.1.4.1.1.13.1.4" +#define UID_BreastProjectionXRayImageStorageForProcessing "1.2.840.10008.5.1.4.1.1.13.1.5" +#define UID_IntravascularOpticalCoherenceTomographyImageStorageForPresentation "1.2.840.10008.5.1.4.1.1.14.1" +#define UID_IntravascularOpticalCoherenceTomographyImageStorageForProcessing "1.2.840.10008.5.1.4.1.1.14.2" +#define UID_NuclearMedicineImageStorage "1.2.840.10008.5.1.4.1.1.20" +#define UID_ParametricMapStorage "1.2.840.10008.5.1.4.1.1.30" +#define UID_RawDataStorage "1.2.840.10008.5.1.4.1.1.66" +#define UID_SpatialRegistrationStorage "1.2.840.10008.5.1.4.1.1.66.1" +#define UID_SpatialFiducialsStorage "1.2.840.10008.5.1.4.1.1.66.2" +#define UID_DeformableSpatialRegistrationStorage "1.2.840.10008.5.1.4.1.1.66.3" +#define UID_SegmentationStorage "1.2.840.10008.5.1.4.1.1.66.4" +#define UID_SurfaceSegmentationStorage "1.2.840.10008.5.1.4.1.1.66.5" +#define UID_RealWorldValueMappingStorage "1.2.840.10008.5.1.4.1.1.67" +#define UID_SurfaceScanMeshStorage "1.2.840.10008.5.1.4.1.1.68.1" +#define UID_SurfaceScanPointCloudStorage "1.2.840.10008.5.1.4.1.1.68.2" +#define UID_RETIRED_VLImageStorage "1.2.840.10008.5.1.4.1.1.77.1" +#define UID_VLEndoscopicImageStorage "1.2.840.10008.5.1.4.1.1.77.1.1" +#define UID_VideoEndoscopicImageStorage "1.2.840.10008.5.1.4.1.1.77.1.1.1" +#define UID_VLMicroscopicImageStorage "1.2.840.10008.5.1.4.1.1.77.1.2" +#define UID_VideoMicroscopicImageStorage "1.2.840.10008.5.1.4.1.1.77.1.2.1" +#define UID_VLSlideCoordinatesMicroscopicImageStorage "1.2.840.10008.5.1.4.1.1.77.1.3" +#define UID_VLPhotographicImageStorage "1.2.840.10008.5.1.4.1.1.77.1.4" +#define UID_VideoPhotographicImageStorage "1.2.840.10008.5.1.4.1.1.77.1.4.1" +#define UID_OphthalmicPhotography8BitImageStorage "1.2.840.10008.5.1.4.1.1.77.1.5.1" +#define UID_OphthalmicPhotography16BitImageStorage "1.2.840.10008.5.1.4.1.1.77.1.5.2" +#define UID_StereometricRelationshipStorage "1.2.840.10008.5.1.4.1.1.77.1.5.3" +#define UID_OphthalmicTomographyImageStorage "1.2.840.10008.5.1.4.1.1.77.1.5.4" +#define UID_WideFieldOphthalmicPhotographyStereographicProjectionImageStorage "1.2.840.10008.5.1.4.1.1.77.1.5.5" +#define UID_WideFieldOphthalmicPhotography3DCoordinatesImageStorage "1.2.840.10008.5.1.4.1.1.77.1.5.6" +#define UID_VLWholeSlideMicroscopyImageStorage "1.2.840.10008.5.1.4.1.1.77.1.6" +#define UID_RETIRED_VLMultiFrameImageStorage "1.2.840.10008.5.1.4.1.1.77.2" +#define UID_LensometryMeasurementsStorage "1.2.840.10008.5.1.4.1.1.78.1" +#define UID_AutorefractionMeasurementsStorage "1.2.840.10008.5.1.4.1.1.78.2" +#define UID_KeratometryMeasurementsStorage "1.2.840.10008.5.1.4.1.1.78.3" +#define UID_SubjectiveRefractionMeasurementsStorage "1.2.840.10008.5.1.4.1.1.78.4" +#define UID_VisualAcuityMeasurementsStorage "1.2.840.10008.5.1.4.1.1.78.5" +#define UID_SpectaclePrescriptionReportStorage "1.2.840.10008.5.1.4.1.1.78.6" +#define UID_OphthalmicAxialMeasurementsStorage "1.2.840.10008.5.1.4.1.1.78.7" +#define UID_IntraocularLensCalculationsStorage "1.2.840.10008.5.1.4.1.1.78.8" +#define UID_MacularGridThicknessAndVolumeReportStorage "1.2.840.10008.5.1.4.1.1.79.1" +#define UID_OphthalmicVisualFieldStaticPerimetryMeasurementsStorage "1.2.840.10008.5.1.4.1.1.80.1" +#define UID_OphthalmicThicknessMapStorage "1.2.840.10008.5.1.4.1.1.81.1" +#define UID_CornealTopographyMapStorage "1.2.840.10008.5.1.4.1.1.82.1" +#define UID_BasicTextSRStorage "1.2.840.10008.5.1.4.1.1.88.11" +#define UID_EnhancedSRStorage "1.2.840.10008.5.1.4.1.1.88.22" +#define UID_ComprehensiveSRStorage "1.2.840.10008.5.1.4.1.1.88.33" +#define UID_Comprehensive3DSRStorage "1.2.840.10008.5.1.4.1.1.88.34" +#define UID_ExtensibleSRStorage "1.2.840.10008.5.1.4.1.1.88.35" +#define UID_ProcedureLogStorage "1.2.840.10008.5.1.4.1.1.88.40" +#define UID_MammographyCADSRStorage "1.2.840.10008.5.1.4.1.1.88.50" +#define UID_KeyObjectSelectionDocumentStorage "1.2.840.10008.5.1.4.1.1.88.59" +#define UID_ChestCADSRStorage "1.2.840.10008.5.1.4.1.1.88.65" +#define UID_XRayRadiationDoseSRStorage "1.2.840.10008.5.1.4.1.1.88.67" +#define UID_RadiopharmaceuticalRadiationDoseSRStorage "1.2.840.10008.5.1.4.1.1.88.68" +#define UID_ColonCADSRStorage "1.2.840.10008.5.1.4.1.1.88.69" +#define UID_ImplantationPlanSRDocumentStorage "1.2.840.10008.5.1.4.1.1.88.70" +#define UID_EncapsulatedPDFStorage "1.2.840.10008.5.1.4.1.1.104.1" +#define UID_EncapsulatedCDAStorage "1.2.840.10008.5.1.4.1.1.104.2" +#define UID_PositronEmissionTomographyImageStorage "1.2.840.10008.5.1.4.1.1.128" +#define UID_LegacyConvertedEnhancedPETImageStorage "1.2.840.10008.5.1.4.1.1.128.1" +#define UID_RETIRED_StandalonePETCurveStorage "1.2.840.10008.5.1.4.1.1.129" +#define UID_EnhancedPETImageStorage "1.2.840.10008.5.1.4.1.1.130" +#define UID_BasicStructuredDisplayStorage "1.2.840.10008.5.1.4.1.1.131" +#define UID_RTImageStorage "1.2.840.10008.5.1.4.1.1.481.1" +#define UID_RTDoseStorage "1.2.840.10008.5.1.4.1.1.481.2" +#define UID_RTStructureSetStorage "1.2.840.10008.5.1.4.1.1.481.3" +#define UID_RTBeamsTreatmentRecordStorage "1.2.840.10008.5.1.4.1.1.481.4" +#define UID_RTPlanStorage "1.2.840.10008.5.1.4.1.1.481.5" +#define UID_RTBrachyTreatmentRecordStorage "1.2.840.10008.5.1.4.1.1.481.6" +#define UID_RTTreatmentSummaryRecordStorage "1.2.840.10008.5.1.4.1.1.481.7" +#define UID_RTIonPlanStorage "1.2.840.10008.5.1.4.1.1.481.8" +#define UID_RTIonBeamsTreatmentRecordStorage "1.2.840.10008.5.1.4.1.1.481.9" +#define UID_HangingProtocolStorage "1.2.840.10008.5.1.4.38.1" +#define UID_GenericImplantTemplateStorage "1.2.840.10008.5.1.4.43.1" +#define UID_ImplantAssemblyTemplateStorage "1.2.840.10008.5.1.4.44.1" +#define UID_ImplantTemplateGroupStorage "1.2.840.10008.5.1.4.45.1" + +// DICOMDIR (was UID_BasicDirectoryStorageSOPClass in DCMTK versions prior to 3.5.3) +#define UID_MediaStorageDirectoryStorage "1.2.840.10008.1.3.10" + +// DICOS Storage +#define UID_DICOS_CTImageStorage "1.2.840.10008.5.1.4.1.1.501.1" +#define UID_DICOS_DigitalXRayImageStorageForPresentation "1.2.840.10008.5.1.4.1.1.501.2.1" +#define UID_DICOS_DigitalXRayImageStorageForProcessing "1.2.840.10008.5.1.4.1.1.501.2.2" +#define UID_DICOS_ThreatDetectionReportStorage "1.2.840.10008.5.1.4.1.1.501.3" + +// DICONDE Storage +#define UID_DICONDE_EddyCurrentImageStorage "1.2.840.10008.5.1.4.1.1.601.1" +#define UID_DICONDE_EddyCurrentMultiframeImageStorage "1.2.840.10008.5.1.4.1.1.601.2" + +// Query/Retrieve +#define UID_FINDPatientRootQueryRetrieveInformationModel "1.2.840.10008.5.1.4.1.2.1.1" +#define UID_MOVEPatientRootQueryRetrieveInformationModel "1.2.840.10008.5.1.4.1.2.1.2" +#define UID_GETPatientRootQueryRetrieveInformationModel "1.2.840.10008.5.1.4.1.2.1.3" +#define UID_FINDStudyRootQueryRetrieveInformationModel "1.2.840.10008.5.1.4.1.2.2.1" +#define UID_MOVEStudyRootQueryRetrieveInformationModel "1.2.840.10008.5.1.4.1.2.2.2" +#define UID_GETStudyRootQueryRetrieveInformationModel "1.2.840.10008.5.1.4.1.2.2.3" +#define UID_RETIRED_FINDPatientStudyOnlyQueryRetrieveInformationModel "1.2.840.10008.5.1.4.1.2.3.1" +#define UID_RETIRED_MOVEPatientStudyOnlyQueryRetrieveInformationModel "1.2.840.10008.5.1.4.1.2.3.2" +#define UID_RETIRED_GETPatientStudyOnlyQueryRetrieveInformationModel "1.2.840.10008.5.1.4.1.2.3.3" +#define UID_MOVECompositeInstanceRootRetrieve "1.2.840.10008.5.1.4.1.2.4.2" +#define UID_GETCompositeInstanceRootRetrieve "1.2.840.10008.5.1.4.1.2.4.3" +#define UID_GETCompositeInstanceRetrieveWithoutBulkData "1.2.840.10008.5.1.4.1.2.5.3" + +// Worklist +#define UID_FINDModalityWorklistInformationModel "1.2.840.10008.5.1.4.31" + +// General Purpose Worklist +#define UID_RETIRED_FINDGeneralPurposeWorklistInformationModel "1.2.840.10008.5.1.4.32.1" +#define UID_RETIRED_GeneralPurposeScheduledProcedureStepSOPClass "1.2.840.10008.5.1.4.32.2" +#define UID_RETIRED_GeneralPurposePerformedProcedureStepSOPClass "1.2.840.10008.5.1.4.32.3" +#define UID_RETIRED_GeneralPurposeWorklistManagementMetaSOPClass "1.2.840.10008.5.1.4.32" + +// MPPS +#define UID_ModalityPerformedProcedureStepSOPClass "1.2.840.10008.3.1.2.3.3" +#define UID_ModalityPerformedProcedureStepRetrieveSOPClass "1.2.840.10008.3.1.2.3.4" +#define UID_ModalityPerformedProcedureStepNotificationSOPClass "1.2.840.10008.3.1.2.3.5" + +// Radiotherapy Treatment Delivery +#define UID_RTBeamsDeliveryInstructionStorage "1.2.840.10008.5.1.4.34.7" +#define UID_RTConventionalMachineVerification "1.2.840.10008.5.1.4.34.8" +#define UID_RTIonMachineVerification "1.2.840.10008.5.1.4.34.9" + +// Unified Worklist and Procedure Step +#define UID_UnifiedWorklistAndProcedureStepServiceClass "1.2.840.10008.5.1.4.34.6" +#define UID_UnifiedProcedureStepPushSOPClass "1.2.840.10008.5.1.4.34.6.1" +#define UID_UnifiedProcedureStepWatchSOPClass "1.2.840.10008.5.1.4.34.6.2" +#define UID_UnifiedProcedureStepPullSOPClass "1.2.840.10008.5.1.4.34.6.3" +#define UID_UnifiedProcedureStepEventSOPClass "1.2.840.10008.5.1.4.34.6.4" +#define UID_UPSGlobalSubscriptionSOPInstance "1.2.840.10008.5.1.4.34.5" +#define UID_UPSFilteredGlobalSubscriptionSOPInstance "1.2.840.10008.5.1.4.34.5.1" + +// Storage Commitment +#define UID_StorageCommitmentPushModelSOPClass "1.2.840.10008.1.20.1" +#define UID_StorageCommitmentPushModelSOPInstance "1.2.840.10008.1.20.1.1" +#define UID_RETIRED_StorageCommitmentPullModelSOPClass "1.2.840.10008.1.20.2" +#define UID_RETIRED_StorageCommitmentPullModelSOPInstance "1.2.840.10008.1.20.2.1" + +// Hanging Protocols +#define UID_FINDHangingProtocolInformationModel "1.2.840.10008.5.1.4.38.2" +#define UID_MOVEHangingProtocolInformationModel "1.2.840.10008.5.1.4.38.3" + +// Relevant Patient Information Query +#define UID_GeneralRelevantPatientInformationQuery "1.2.840.10008.5.1.4.37.1" +#define UID_BreastImagingRelevantPatientInformationQuery "1.2.840.10008.5.1.4.37.2" +#define UID_CardiacRelevantPatientInformationQuery "1.2.840.10008.5.1.4.37.3" + +// Color Palette Storage and Query/Retrieve +#define UID_ColorPaletteStorage "1.2.840.10008.5.1.4.39.1" +#define UID_FINDColorPaletteInformationModel "1.2.840.10008.5.1.4.39.2" +#define UID_MOVEColorPaletteInformationModel "1.2.840.10008.5.1.4.39.3" +#define UID_GETColorPaletteInformationModel "1.2.840.10008.5.1.4.39.4" + +// Implant Template Query/Retrieve +#define UID_FINDGenericImplantTemplateInformationModel "1.2.840.10008.5.1.4.43.2" +#define UID_MOVEGenericImplantTemplateInformationModel "1.2.840.10008.5.1.4.43.3" +#define UID_GETGenericImplantTemplateInformationModel "1.2.840.10008.5.1.4.43.4" +#define UID_FINDImplantAssemblyTemplateInformationModel "1.2.840.10008.5.1.4.44.2" +#define UID_MOVEImplantAssemblyTemplateInformationModel "1.2.840.10008.5.1.4.44.3" +#define UID_GETImplantAssemblyTemplateInformationModel "1.2.840.10008.5.1.4.44.4" +#define UID_FINDImplantTemplateGroupInformationModel "1.2.840.10008.5.1.4.45.2" +#define UID_MOVEImplantTemplateGroupInformationModel "1.2.840.10008.5.1.4.45.3" +#define UID_GETImplantTemplateGroupInformationModel "1.2.840.10008.5.1.4.45.4" + +// Print Management +#define UID_BasicFilmSessionSOPClass "1.2.840.10008.5.1.1.1" +#define UID_BasicFilmBoxSOPClass "1.2.840.10008.5.1.1.2" +#define UID_BasicGrayscaleImageBoxSOPClass "1.2.840.10008.5.1.1.4" +#define UID_BasicColorImageBoxSOPClass "1.2.840.10008.5.1.1.4.1" +#define UID_RETIRED_ReferencedImageBoxSOPClass "1.2.840.10008.5.1.1.4.2" +#define UID_BasicGrayscalePrintManagementMetaSOPClass "1.2.840.10008.5.1.1.9" +#define UID_RETIRED_ReferencedGrayscalePrintManagementMetaSOPClass "1.2.840.10008.5.1.1.9.1" +#define UID_PrintJobSOPClass "1.2.840.10008.5.1.1.14" +#define UID_BasicAnnotationBoxSOPClass "1.2.840.10008.5.1.1.15" +#define UID_PrinterSOPClass "1.2.840.10008.5.1.1.16" +#define UID_PrinterConfigurationRetrievalSOPClass "1.2.840.10008.5.1.1.16.376" +#define UID_PrinterSOPInstance "1.2.840.10008.5.1.1.17" +#define UID_PrinterConfigurationRetrievalSOPInstance "1.2.840.10008.5.1.1.17.376" +#define UID_BasicColorPrintManagementMetaSOPClass "1.2.840.10008.5.1.1.18" +#define UID_RETIRED_ReferencedColorPrintManagementMetaSOPClass "1.2.840.10008.5.1.1.18.1" +#define UID_VOILUTBoxSOPClass "1.2.840.10008.5.1.1.22" +#define UID_PresentationLUTSOPClass "1.2.840.10008.5.1.1.23" +#define UID_RETIRED_ImageOverlayBoxSOPClass "1.2.840.10008.5.1.1.24" +#define UID_RETIRED_BasicPrintImageOverlayBoxSOPClass "1.2.840.10008.5.1.1.24.1" +#define UID_RETIRED_PrintQueueSOPInstance "1.2.840.10008.5.1.1.25" +#define UID_RETIRED_PrintQueueManagementSOPClass "1.2.840.10008.5.1.1.26" +#define UID_RETIRED_PullPrintRequestSOPClass "1.2.840.10008.5.1.1.31" +#define UID_RETIRED_PullStoredPrintManagementMetaSOPClass "1.2.840.10008.5.1.1.32" + +// Detached Management +#define UID_RETIRED_DetachedPatientManagementSOPClass "1.2.840.10008.3.1.2.1.1" +#define UID_RETIRED_DetachedPatientManagementMetaSOPClass "1.2.840.10008.3.1.2.1.4" +#define UID_RETIRED_DetachedVisitManagementSOPClass "1.2.840.10008.3.1.2.2.1" +#define UID_RETIRED_DetachedStudyManagementSOPClass "1.2.840.10008.3.1.2.3.1" +#define UID_RETIRED_DetachedResultsManagementSOPClass "1.2.840.10008.3.1.2.5.1" +#define UID_RETIRED_DetachedResultsManagementMetaSOPClass "1.2.840.10008.3.1.2.5.4" +#define UID_RETIRED_DetachedStudyManagementMetaSOPClass "1.2.840.10008.3.1.2.5.5" +#define UID_RETIRED_DetachedInterpretationManagementSOPClass "1.2.840.10008.3.1.2.6.1" + +// Procedure Log +#define UID_ProceduralEventLoggingSOPClass "1.2.840.10008.1.40" +#define UID_ProceduralEventLoggingSOPInstance "1.2.840.10008.1.40.1" + +// Substance Administration +#define UID_SubstanceAdministrationLoggingSOPClass "1.2.840.10008.1.42" +#define UID_SubstanceAdministrationLoggingSOPInstance "1.2.840.10008.1.42.1" +#define UID_ProductCharacteristicsQuerySOPClass "1.2.840.10008.5.1.4.41" +#define UID_SubstanceApprovalQuerySOPClass "1.2.840.10008.5.1.4.42" + +// Media Creation +#define UID_MediaCreationManagementSOPClass "1.2.840.10008.5.1.1.33" + +// SOP Class Relationship Negotiation +#define UID_StorageServiceClass "1.2.840.10008.4.2" + +// Instance Availability Notification +#define UID_InstanceAvailabilityNotificationSOPClass "1.2.840.10008.5.1.4.33" + +// Application Hosting +#define UID_NativeDICOMModel "1.2.840.10008.7.1.1" +#define UID_AbstractMultiDimensionalImageModel "1.2.840.10008.7.1.2" + +// Communication of Display Parameters +#define UID_DisplaySystemSOPClass "1.2.840.10008.5.1.1.40" +#define UID_DisplaySystemSOPInstance "1.2.840.10008.5.1.1.40.1" + +// Other +#define UID_VerificationSOPClass "1.2.840.10008.1.1" +#define UID_RETIRED_BasicStudyContentNotificationSOPClass "1.2.840.10008.1.9" +#define UID_RETIRED_StudyComponentManagementSOPClass "1.2.840.10008.3.1.2.3.2" + +/* +** All other UIDs according to DICOM standard +*/ + +// Mapping Resources +#define UID_DICOMContentMappingResource "1.2.840.10008.8.1.1" + +// Coding Schemes +#define UID_DICOMControlledTerminologyCodingScheme "1.2.840.10008.2.16.4" +#define UID_DICOMUIDRegistryCodingScheme "1.2.840.10008.2.6.1" + +// Configuration Management LDAP UIDs +#define UID_LDAP_dicomDeviceName "1.2.840.10008.15.0.3.1" +#define UID_LDAP_dicomDescription "1.2.840.10008.15.0.3.2" +#define UID_LDAP_dicomManufacturer "1.2.840.10008.15.0.3.3" +#define UID_LDAP_dicomManufacturerModelName "1.2.840.10008.15.0.3.4" +#define UID_LDAP_dicomSoftwareVersion "1.2.840.10008.15.0.3.5" +#define UID_LDAP_dicomVendorData "1.2.840.10008.15.0.3.6" +#define UID_LDAP_dicomAETitle "1.2.840.10008.15.0.3.7" +#define UID_LDAP_dicomNetworkConnectionReference "1.2.840.10008.15.0.3.8" +#define UID_LDAP_dicomApplicationCluster "1.2.840.10008.15.0.3.9" +#define UID_LDAP_dicomAssociationInitiator "1.2.840.10008.15.0.3.10" +#define UID_LDAP_dicomAssociationAcceptor "1.2.840.10008.15.0.3.11" +#define UID_LDAP_dicomHostname "1.2.840.10008.15.0.3.12" +#define UID_LDAP_dicomPort "1.2.840.10008.15.0.3.13" +#define UID_LDAP_dicomSOPClass "1.2.840.10008.15.0.3.14" +#define UID_LDAP_dicomTransferRole "1.2.840.10008.15.0.3.15" +#define UID_LDAP_dicomTransferSyntax "1.2.840.10008.15.0.3.16" +#define UID_LDAP_dicomPrimaryDeviceType "1.2.840.10008.15.0.3.17" +#define UID_LDAP_dicomRelatedDeviceReference "1.2.840.10008.15.0.3.18" +#define UID_LDAP_dicomPreferredCalledAETitle "1.2.840.10008.15.0.3.19" +#define UID_LDAP_dicomTLSCyphersuite "1.2.840.10008.15.0.3.20" +#define UID_LDAP_dicomAuthorizedNodeCertificateReference "1.2.840.10008.15.0.3.21" +#define UID_LDAP_dicomThisNodeCertificateReference "1.2.840.10008.15.0.3.22" +#define UID_LDAP_dicomInstalled "1.2.840.10008.15.0.3.23" +#define UID_LDAP_dicomStationName "1.2.840.10008.15.0.3.24" +#define UID_LDAP_dicomDeviceSerialNumber "1.2.840.10008.15.0.3.25" +#define UID_LDAP_dicomInstitutionName "1.2.840.10008.15.0.3.26" +#define UID_LDAP_dicomInstitutionAddress "1.2.840.10008.15.0.3.27" +#define UID_LDAP_dicomInstitutionDepartmentName "1.2.840.10008.15.0.3.28" +#define UID_LDAP_dicomIssuerOfPatientID "1.2.840.10008.15.0.3.29" +#define UID_LDAP_dicomPreferredCallingAETitle "1.2.840.10008.15.0.3.30" +#define UID_LDAP_dicomSupportedCharacterSet "1.2.840.10008.15.0.3.31" +#define UID_LDAP_dicomConfigurationRoot "1.2.840.10008.15.0.4.1" +#define UID_LDAP_dicomDevicesRoot "1.2.840.10008.15.0.4.2" +#define UID_LDAP_dicomUniqueAETitlesRegistryRoot "1.2.840.10008.15.0.4.3" +#define UID_LDAP_dicomDevice "1.2.840.10008.15.0.4.4" +#define UID_LDAP_dicomNetworkAE "1.2.840.10008.15.0.4.5" +#define UID_LDAP_dicomNetworkConnection "1.2.840.10008.15.0.4.6" +#define UID_LDAP_dicomUniqueAETitle "1.2.840.10008.15.0.4.7" +#define UID_LDAP_dicomTransferCapability "1.2.840.10008.15.0.4.8" + +// UTC Synchronization Frame of Reference +#define UID_UniversalCoordinatedTimeSynchronizationFrameOfReference "1.2.840.10008.15.1.1" + +// Well-known Frame of References +#define UID_TalairachBrainAtlasFrameOfReference "1.2.840.10008.1.4.1.1" +#define UID_SPM2T1FrameOfReference "1.2.840.10008.1.4.1.2" +#define UID_SPM2T2FrameOfReference "1.2.840.10008.1.4.1.3" +#define UID_SPM2PDFrameOfReference "1.2.840.10008.1.4.1.4" +#define UID_SPM2EPIFrameOfReference "1.2.840.10008.1.4.1.5" +#define UID_SPM2FILT1FrameOfReference "1.2.840.10008.1.4.1.6" +#define UID_SPM2PETFrameOfReference "1.2.840.10008.1.4.1.7" +#define UID_SPM2TRANSMFrameOfReference "1.2.840.10008.1.4.1.8" +#define UID_SPM2SPECTFrameOfReference "1.2.840.10008.1.4.1.9" +#define UID_SPM2GRAYFrameOfReference "1.2.840.10008.1.4.1.10" +#define UID_SPM2WHITEFrameOfReference "1.2.840.10008.1.4.1.11" +#define UID_SPM2CSFFrameOfReference "1.2.840.10008.1.4.1.12" +#define UID_SPM2BRAINMASKFrameOfReference "1.2.840.10008.1.4.1.13" +#define UID_SPM2AVG305T1FrameOfReference "1.2.840.10008.1.4.1.14" +#define UID_SPM2AVG152T1FrameOfReference "1.2.840.10008.1.4.1.15" +#define UID_SPM2AVG152T2FrameOfReference "1.2.840.10008.1.4.1.16" +#define UID_SPM2AVG152PDFrameOfReference "1.2.840.10008.1.4.1.17" +#define UID_SPM2SINGLESUBJT1FrameOfReference "1.2.840.10008.1.4.1.18" +#define UID_ICBM452T1FrameOfReference "1.2.840.10008.1.4.2.1" +#define UID_ICBMSingleSubjectMRIFrameOfReference "1.2.840.10008.1.4.2.2" + +// Well-known SOP Instances for Color Palettes +#define UID_HotIronColorPaletteSOPInstance "1.2.840.10008.1.5.1" +#define UID_PETColorPaletteSOPInstance "1.2.840.10008.1.5.2" +#define UID_HotMetalBlueColorPaletteSOPInstance "1.2.840.10008.1.5.3" +#define UID_PET20StepColorPaletteSOPInstance "1.2.840.10008.1.5.4" + +/* +** Private DCMTK UIDs +*/ + +// Private SOP Class UID used to shutdown external network applications +#define UID_PrivateShutdownSOPClass "1.2.276.0.7230010.3.4.1915765545.18030.917282194.0" + + +/* DRAFT SUPPLEMENTS - EXPERIMENTAL USE ONLY */ + +/* + * The following UIDs were defined in "frozen draft for trial implementation" versions + * of various DICOM supplements and are or will be changed before final text. + * Since it is likely that trial implementations exist, we leave the UIDs in the dictionary. + */ + +/* Supplement 23 Frozen Draft (November 1997) */ +#define UID_DRAFT_SRTextStorage "1.2.840.10008.5.1.4.1.1.88.1" +#define UID_DRAFT_SRAudioStorage "1.2.840.10008.5.1.4.1.1.88.2" +#define UID_DRAFT_SRDetailStorage "1.2.840.10008.5.1.4.1.1.88.3" +#define UID_DRAFT_SRComprehensiveStorage "1.2.840.10008.5.1.4.1.1.88.4" + +/* Supplement 30 Draft 08 for Demonstration (October 1997) */ +#define UID_DRAFT_WaveformStorage "1.2.840.10008.5.1.4.1.1.9.1" + +/* Supplement 74 Frozen Draft (October 2007) */ +#define UID_DRAFT_RTBeamsDeliveryInstructionStorage "1.2.840.10008.5.1.4.34.1" +#define UID_DRAFT_RTConventionalMachineVerification "1.2.840.10008.5.1.4.34.2" +#define UID_DRAFT_RTIonMachineVerification "1.2.840.10008.5.1.4.34.3" + +// Supplement 96 Frozen Draft (October 2007), also part of DICOM 2008 and 2009 +#define UID_DRAFT_UnifiedWorklistAndProcedureStepServiceClass "1.2.840.10008.5.1.4.34.4" +#define UID_DRAFT_UnifiedProcedureStepPushSOPClass "1.2.840.10008.5.1.4.34.4.1" +#define UID_DRAFT_UnifiedProcedureStepWatchSOPClass "1.2.840.10008.5.1.4.34.4.2" +#define UID_DRAFT_UnifiedProcedureStepPullSOPClass "1.2.840.10008.5.1.4.34.4.3" +#define UID_DRAFT_UnifiedProcedureStepEventSOPClass "1.2.840.10008.5.1.4.34.4.4" + +#endif /* DCUID_H */ diff --git a/dcmdata/include/dcmtk/dcmdata/dcvr.h b/dcmdata/include/dcmtk/dcmdata/dcvr.h new file mode 100644 index 00000000..11c9e73f --- /dev/null +++ b/dcmdata/include/dcmtk/dcmdata/dcvr.h @@ -0,0 +1,389 @@ +/* + * + * Copyright (C) 1994-2015, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Gerd Ehlers, Andreas Barth, Andrew Hewett + * + * Purpose: Definition of the DcmVR class for Value Representation + * + */ + +#ifndef DCMVR_H +#define DCMVR_H + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ +#include "dcmtk/ofstd/ofglobal.h" +#include "dcmtk/dcmdata/dcdefine.h" + +/** Global flag to enable/disable the generation of VR=UN, which has been + * introduced after the first edition of the DICOM standard (1993). + * If disabled, the VR=OB is used instead. + */ +extern DCMTK_DCMDATA_EXPORT OFGlobal dcmEnableUnknownVRGeneration; /* default OFTrue */ + +/** Global flag to enable/disable the generation of VR=UT, which has been + * introduced after the first edition of the DICOM standard (1993). + * If disabled, the VR=UN (if enabled) or alternatively VR=OB is used. + */ +extern DCMTK_DCMDATA_EXPORT OFGlobal dcmEnableUnlimitedTextVRGeneration; /* default OFTrue */ + +/** Global flag to enable/disable the generation of VR=OF, which has been + * introduced after the first edition of the DICOM standard (1993). + * If disabled, the VR=UN (if enabled) or alternatively VR=OB is used. + */ +extern DCMTK_DCMDATA_EXPORT OFGlobal dcmEnableOtherFloatStringVRGeneration; /* default OFTrue */ + +/** Global flag to enable/disable the generation of VR=OD, which has been + * introduced after the first edition of the DICOM standard (1993). + * If disabled, the VR=UN (if enabled) or alternatively VR=OB is used. + */ +extern DCMTK_DCMDATA_EXPORT OFGlobal dcmEnableOtherDoubleStringVRGeneration; /* default OFTrue */ + +/** Global flag to enable/disable the generation of VR=UR, which has been + * introduced after the first edition of the DICOM standard (1993). + * If disabled, the VR=UT (if enabled), VR=UN (if enabled) or alternatively + * VR=OB is used. + */ +extern DCMTK_DCMDATA_EXPORT OFGlobal dcmEnableUniversalResourceIdentifierOrLocatorVRGeneration; /* default OFTrue */ + +/** Global flag to enable/disable the generation of VR=UC, which has been + * introduced after the first edition of the DICOM standard (1993). + * If disabled, the VR=UN (if enabled) or alternatively VR=OB is used. + */ +extern DCMTK_DCMDATA_EXPORT OFGlobal dcmEnableUnlimitedCharactersVRGeneration; /* default OFTrue */ + +/** Global flag to enable/disable the automatic re-conversion of defined + * length UN elements read in an explicit VR transfer syntax, if the real + * VR is defined in the data dictionary. + */ +extern DCMTK_DCMDATA_EXPORT OFGlobal dcmEnableUnknownVRConversion; /* default OFFalse */ + + +/** Global function that enables the generation of "new" value representations, + * i.e. the ones that have been introduced after the first edition of the DICOM + * standard (1993). See above dcmEnableXXXVRGeneration() flags for details. + */ +DCMTK_DCMDATA_EXPORT void dcmEnableGenerationOfNewVRs(); + +/** Global function that disables the generation of "new" value representations, + * i.e. the ones that have been introduced after the first edition of the DICOM + * standard (1993). See above dcmEnableXXXVRGeneration() flags for details. + */ +DCMTK_DCMDATA_EXPORT void dcmDisableGenerationOfNewVRs(); + + +/* +** VR Enumerations. +** NB: The order of entries has to conform to the order in DcmVRDict (see dcmvr.cc)! +** If not an error message is reported and the program aborts (only in DEBUG mode). +*/ +enum DcmEVR +{ + /// application entity title + EVR_AE, + + /// age string + EVR_AS, + + /// attribute tag + EVR_AT, + + /// code string + EVR_CS, + + /// date string + EVR_DA, + + /// decimal string + EVR_DS, + + /// date time string + EVR_DT, + + /// float single-precision + EVR_FL, + + /// float double-precision + EVR_FD, + + /// integer string + EVR_IS, + + /// long string + EVR_LO, + + /// long text + EVR_LT, + + /// other byte string + EVR_OB, + + /// other double string + EVR_OD, + + /// other float string + EVR_OF, + + /// other word string + EVR_OW, + + /// person name + EVR_PN, + + /// short string + EVR_SH, + + /// signed long + EVR_SL, + + /// sequence of items + EVR_SQ, + + /// signed short + EVR_SS, + + /// short text + EVR_ST, + + /// time string + EVR_TM, + + /// unlimited characters + EVR_UC, + + /// unique identifier + EVR_UI, + + /// unsigned long + EVR_UL, + + /// universal resource identifier or universal resource locator (URI/URL) + EVR_UR, + + /// unsigned short + EVR_US, + + /// unlimited text + EVR_UT, + + /// OB or OW depending on context + EVR_ox, + + /// SS or US depending on context + EVR_xs, + + /// US, SS or OW depending on context, used for LUT Data (thus the name) + EVR_lt, + + /// na="not applicable", for data which has no VR + EVR_na, + + /// up="unsigned pointer", used internally for DICOMDIR support + EVR_up, + + /// used internally for items + EVR_item, + + /// used internally for meta info datasets + EVR_metainfo, + + /// used internally for datasets + EVR_dataset, + + /// used internally for DICOM files + EVR_fileFormat, + + /// used internally for DICOMDIR objects + EVR_dicomDir, + + /// used internally for DICOMDIR records + EVR_dirRecord, + + /// used internally for pixel sequences in a compressed image + EVR_pixelSQ, + + /// used internally for pixel items in a compressed image + EVR_pixelItem, + + /// used internally for elements with unknown VR (encoded with 4-byte length field in explicit VR) + EVR_UNKNOWN, + + /// unknown value representation + EVR_UN, + + /// used internally for uncompressed pixel data + EVR_PixelData, + + /// used internally for overlay data + EVR_OverlayData, + + /// used internally for elements with unknown VR with 2-byte length field in explicit VR + EVR_UNKNOWN2B +}; + + +/** a class representing a DICOM Value Representation + */ +class DCMTK_DCMDATA_EXPORT DcmVR +{ +public: + + /// default constructor + DcmVR() + : vr(EVR_UNKNOWN) + { + } + + /** constructor + * @param evr enumerated VR value + */ + DcmVR(DcmEVR evr) + : vr(EVR_UNKNOWN) + { + // the set method is safeguarded against incorrect passing of integer values + setVR(evr); + } + + /** constructor + * @param vrName symbolic name of value representation + */ + DcmVR(const char* vrName) + : vr(EVR_UNKNOWN) + { + setVR(vrName); + } + + /** copy constructor + * @param avr VR value + */ + DcmVR(const DcmVR& avr) + : vr(avr.vr) + { + } + + /** assign new VR value + * @param evr enumerated VR value + */ + void setVR(DcmEVR evr); + + /** assign new VR value by name + * @param vrName symbolic name of value representation + */ + void setVR(const char* vrName); + + /** assign new VR value + * @param avr VR value + */ + void setVR(const DcmVR& avr) { vr = avr.vr; } + + /** copy assignment operator + * @param arg vr to assign from + */ + DcmVR& operator=(const DcmVR& arg) + { + vr = arg.vr; + return *this; + } + + /** get enumerated VR managed by this object + * @return enumerated VR + */ + DcmEVR getEVR() const { return vr; } + + /** get enumerated standard VR managed by this object. + * If this object manages a non-standard, internal VR such as EVR_ox, + * this method returns the enumerated VR to which the internal VR will + * be mapped when writing the DICOM object. + * + * Please note that some VR, e.g. EVR_pixelItem, won't be written as + * EVR_UNKNOWN, although this method will return that value for them. + * This means that e.g. usesExtendedLengthEncoding() for the returned VR + * might not be correct. + * + * Also note that DcmItem::checkAndUpdateVR() will in some cases influence + * the VR which is written out. + * @return enumerated VR + */ + DcmEVR getValidEVR() const; + + /** get symbolic VR name for this object + * @return VR name string, never NULL + */ + const char* getVRName() const ; + + /** get symbolic standard VR name for this object + * If this object manages a non-standard, internal VR such as EVR_ox, + * this method returns the name of the VR to which the internal VR will + * be mapped when writing the DICOM object. + * @return VR name string, never NULL + */ + const char* getValidVRName() const; + + /** compute the size for non-empty values of this VR. + * For fixed size VRs such as OW, US, SL, the method returns the size + * of each value, in bytes. For variable length VRs (strings), it returns 1. + * For internal VRs it returns 0. + * @return size of values of this VR + */ + size_t getValueWidth() const; + + /** returns true if VR is a standard DICOM VR + * @return true if VR is a standard DICOM VR + */ + OFBool isStandard() const; + + /** returns true if VR is for internal use only + * @return true if VR is for internal use only + */ + OFBool isForInternalUseOnly() const; + + /** returns true if VR represents a string + * @return true if VR represents a string + */ + OFBool isaString() const; + + /** returns true if VR uses an extended length encoding for explicit transfer syntaxes + * @return true if VR uses an extended length encoding for explicit transfer syntaxes + */ + OFBool usesExtendedLengthEncoding() const; + + /** check if VRs are equivalent + * VRs are considered equivalent if equal or if one of them is an internal VR + * and the other one is a possible standard VR to which the internal one maps. + * @param avr VR to compare with + * @return true if VRs are equivalent, false otherwise + */ + OFBool isEquivalent(const DcmVR& avr) const; + + /* minimum and maximum length of a value with this VR + ** (in bytes assuming single byte characters) + */ + + /** return minimum length of a value with this VR (in bytes), assuming single byte characters + * @return minimum length of a value + */ + Uint32 getMinValueLength() const; + + /** return maximum length of a value with this VR (in bytes), assuming single byte characters + * @return maximum length of a value + */ + Uint32 getMaxValueLength() const; + +private: + /// the enumerated VR value + DcmEVR vr; +}; + + +#endif /* !DCMVR_H */ diff --git a/dcmdata/include/dcmtk/dcmdata/dcvrae.h b/dcmdata/include/dcmtk/dcmdata/dcvrae.h new file mode 100644 index 00000000..1c25e81a --- /dev/null +++ b/dcmdata/include/dcmtk/dcmdata/dcvrae.h @@ -0,0 +1,122 @@ +/* + * + * Copyright (C) 1994-2013, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Gerd Ehlers, Andreas Barth + * + * Purpose: Interface of class DcmApplicationEntity + * + */ + + +#ifndef DCVRAE_H +#define DCVRAE_H + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/dcmdata/dcbytstr.h" + + +/** a class representing the DICOM value representation 'Application Entity' (AE) + */ +class DCMTK_DCMDATA_EXPORT DcmApplicationEntity + : public DcmByteString +{ + + public: + + /** constructor. + * Create new element from given tag and length. + * @param tag DICOM tag for the new element + * @param len value length for the new element + */ + DcmApplicationEntity(const DcmTag &tag, + const Uint32 len = 0); + + /** copy constructor + * @param old element to be copied + */ + DcmApplicationEntity(const DcmApplicationEntity &old); + + /** destructor + */ + virtual ~DcmApplicationEntity(); + + /** assignment operator + * @param obj element to be assigned/copied + * @return reference to this object + */ + DcmApplicationEntity &operator=(const DcmApplicationEntity &obj); + + /** clone method + * @return deep copy of this object + */ + virtual DcmObject *clone() const + { + return new DcmApplicationEntity(*this); + } + + /** Virtual object copying. This method can be used for DcmObject + * and derived classes to get a deep copy of an object. Internally + * the assignment operator is called if the given DcmObject parameter + * is of the same type as "this" object instance. If not, an error + * is returned. This function permits copying an object by value + * in a virtual way which therefore is different to just calling the + * assignment operator of DcmElement which could result in slicing + * the object. + * @param rhs - [in] The instance to copy from. Has to be of the same + * class type as "this" object + * @return EC_Normal if copying was successful, error otherwise + */ + virtual OFCondition copyFrom(const DcmObject& rhs); + + /** get element type identifier + * @return type identifier of this class (EVR_AE) + */ + virtual DcmEVR ident() const; + + /** check whether stored value conforms to the VR and to the specified VM + * @param vm value multiplicity (according to the data dictionary) to be checked for. + * (See DcmElement::checkVM() for a list of valid values.) + * @param oldFormat parameter not used for this VR (only for DA, TM) + * @return status of the check, EC_Normal if value is correct, an error code otherwise + */ + virtual OFCondition checkValue(const OFString &vm = "1-n", + const OFBool oldFormat = OFFalse); + + /** get a copy of a particular string component + * @param stringVal variable in which the result value is stored + * @param pos index of the value in case of multi-valued elements (0..vm-1) + * @param normalize delete leading and trailing spaces if OFTrue + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getOFString(OFString &stringVal, + const unsigned long pos, + OFBool normalize = OFTrue); + + /* --- static helper functions --- */ + + /** check whether given string value conforms to the VR "AE" (Application Entity) + * and to the specified VM. + * @param value string value to be checked (possibly multi-valued) + * @param vm value multiplicity (according to the data dictionary) to be checked for. + * (See DcmElement::checkVM() for a list of valid values.) + * @return status of the check, EC_Normal if value is correct, an error code otherwise + */ + static OFCondition checkStringValue(const OFString &value, + const OFString &vm = "1-n"); +}; + + +#endif // DCVRAE_H diff --git a/dcmdata/include/dcmtk/dcmdata/dcvras.h b/dcmdata/include/dcmtk/dcmdata/dcvras.h new file mode 100644 index 00000000..65e96ef5 --- /dev/null +++ b/dcmdata/include/dcmtk/dcmdata/dcvras.h @@ -0,0 +1,112 @@ +/* + * + * Copyright (C) 1994-2013, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Gerd Ehlers, Andreas Barth + * + * Purpose: Interface of class DcmAgeString + * + */ + + +#ifndef DCVRAS_H +#define DCVRAS_H + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/dcmdata/dcbytstr.h" + + +/** a class representing the DICOM value representation 'Age String' (AS) + */ +class DCMTK_DCMDATA_EXPORT DcmAgeString + : public DcmByteString +{ + + public: + + /** constructor. + * Create new element from given tag and length. + * @param tag DICOM tag for the new element + * @param len value length for the new element + */ + DcmAgeString(const DcmTag &tag, + const Uint32 len = 0); + + /** copy constructor + * @param old element to be copied + */ + DcmAgeString(const DcmAgeString &old); + + /** destructor + */ + virtual ~DcmAgeString(void); + + /** assignment operator + * @param obj element to be assigned/copied + * @return reference to this object + */ + DcmAgeString &operator=(const DcmAgeString &obj); + + /** clone method + * @return deep copy of this object + */ + virtual DcmObject *clone() const + { + return new DcmAgeString(*this); + } + + /** Virtual object copying. This method can be used for DcmObject + * and derived classes to get a deep copy of an object. Internally + * the assignment operator is called if the given DcmObject parameter + * is of the same type as "this" object instance. If not, an error + * is returned. This function permits copying an object by value + * in a virtual way which therefore is different to just calling the + * assignment operator of DcmElement which could result in slicing + * the object. + * @param rhs - [in] The instance to copy from. Has to be of the same + * class type as "this" object + * @return EC_Normal if copying was successful, error otherwise + */ + virtual OFCondition copyFrom(const DcmObject& rhs); + + /** get element type identifier + * @return type identifier of this class (EVR_AS) + */ + virtual DcmEVR ident(void) const; + + /** check whether stored value conforms to the VR and to the specified VM + * @param vm value multiplicity (according to the data dictionary) to be checked for. + * (See DcmElement::checkVM() for a list of valid values.) + * @param oldFormat parameter not used for this VR (only for DA, TM) + * @return status of the check, EC_Normal if value is correct, an error code otherwise + */ + virtual OFCondition checkValue(const OFString &vm = "1-n", + const OFBool oldFormat = OFFalse); + + /* --- static helper functions --- */ + + /** check whether given string value conforms to the VR "AS" (Age String) + * and to the specified VM. + * @param value string value to be checked (possibly multi-valued) + * @param vm value multiplicity (according to the data dictionary) to be checked for. + * (See DcmElement::checkVM() for a list of valid values.) + * @return status of the check, EC_Normal if value is correct, an error code otherwise + */ + static OFCondition checkStringValue(const OFString &value, + const OFString &vm = "1-n"); +}; + + +#endif // DCVRAS_H diff --git a/dcmdata/include/dcmtk/dcmdata/dcvrat.h b/dcmdata/include/dcmtk/dcmdata/dcvrat.h new file mode 100644 index 00000000..b07ecc52 --- /dev/null +++ b/dcmdata/include/dcmtk/dcmdata/dcvrat.h @@ -0,0 +1,237 @@ +/* + * + * Copyright (C) 1994-2013, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Gerd Ehlers, Andreas Barth + * + * Purpose: Interface of class DcmAttributeTag + * + */ + + +#ifndef DCVRAT_H +#define DCVRAT_H + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/dcmdata/dcelem.h" + + +/** a class representing the DICOM value representation 'Attribute Tag' (AT) + */ +class DCMTK_DCMDATA_EXPORT DcmAttributeTag + : public DcmElement +{ + + public: + + /** constructor. + * Create new element from given tag and length. + * @param tag DICOM tag for the new element + * @param len value length for the new element + */ + DcmAttributeTag(const DcmTag &tag, + const Uint32 len = 0); + + /** copy constructor + * @param old element to be copied + */ + DcmAttributeTag(const DcmAttributeTag &old); + + /** destructor + */ + virtual ~DcmAttributeTag(); + + /** assignment operator + * @param obj element to be assigned/copied + * @return reference to this object + */ + DcmAttributeTag &operator=(const DcmAttributeTag &obj); + + /** comparison operator that compares the normalized value of this object + * with a given object of the same type. The tag of the element is also + * considered as the first component that is compared, followed by the + * object types (VR, i.e. DCMTK'S EVR) and the comparison of all value + * components of the object, preferrably in the order declared in the + * object (if applicable). + * @param rhs the right hand side of the comparison + * @return 0 if the object values are equal. + * -1 if either the value of the first component that does not match + * is lower in this object than in rhs, or all compared components match + * but this object has fewer components than rhs. Also returned if rhs + * cannot be casted to this object type. + * 1 if either the value of the first component that does not match + * is greater in this object than in rhs object, or all compared + * components match but the this component is longer. + */ + virtual int compare(const DcmElement& rhs) const; + + + /** clone method + * @return deep copy of this object + */ + virtual DcmObject *clone() const + { + return new DcmAttributeTag(*this); + } + + /** Virtual object copying. This method can be used for DcmObject + * and derived classes to get a deep copy of an object. Internally + * the assignment operator is called if the given DcmObject parameter + * is of the same type as "this" object instance. If not, an error + * is returned. This function permits copying an object by value + * in a virtual way which therefore is different to just calling the + * assignment operator of DcmElement which could result in slicing + * the object. + * @param rhs - [in] The instance to copy from. Has to be of the same + * class type as "this" object + * @return EC_Normal if copying was successful, error otherwise + */ + virtual OFCondition copyFrom(const DcmObject& rhs); + + /** get element type identifier + * @return type identifier of this class (EVR_AT) + */ + virtual DcmEVR ident() const; + + /** check whether stored value conforms to the VR and to the specified VM + * @param vm value multiplicity (according to the data dictionary) to be checked for. + * (See DcmElement::checkVM() for a list of valid values.) + * @param oldFormat parameter not used for this VR (only for DA, TM) + * @return status of the check, EC_Normal if value is correct, an error code otherwise + */ + virtual OFCondition checkValue(const OFString &vm = "1-n", + const OFBool oldFormat = OFFalse); + + /** get value multiplicity + * @return number of tag value pairs (group,element) + */ + virtual unsigned long getVM(); + + /** print element to a stream. + * The output format of the value is a backslash separated sequence of group and + * element value pairs, e.g. "(0008,0020)\(0008,0030)" + * @param out output stream + * @param flags optional flag used to customize the output (see DCMTypes::PF_xxx) + * @param level current level of nested items. Used for indentation. + * @param pixelFileName not used + * @param pixelCounter not used + */ + virtual void print(STD_NAMESPACE ostream&out, + const size_t flags = 0, + const int level = 0, + const char *pixelFileName = NULL, + size_t *pixelCounter = NULL); + + /** write object in XML format + * @param out output stream to which the XML document is written + * @param flags optional flag used to customize the output (see DCMTypes::XF_xxx) + * @return status, EC_Normal if successful, an error code otherwise + */ + OFCondition writeXML(STD_NAMESPACE ostream &out, + const size_t flags = 0); + + /** get particular tag value + * @param tagVal reference to result variable (cleared in case of error) + * @param pos index of the value to be retrieved (0..vm-1) + * @return status status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getTagVal(DcmTagKey &tagVal, + const unsigned long pos = 0); + + /** get reference to stored integer data. + * The array entries with an even-numbered index contain the group numbers + * and the odd entries contain the element numbers (see "putUint16Array()"). + * The number of entries is twice as large as the return value of "getVM()". + * @param uintVals reference to result variable + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getUint16Array(Uint16 *&uintVals); + + /** get specified value as a character string. + * The output format is "(gggg,eeee)" where "gggg" is the hexa-decimal group + * number and "eeee" the hexa-decimal element number of the attribute tag. + * @param stringVal variable in which the result value is stored + * @param pos index of the value in case of multi-valued elements (0..vm-1) + * @param normalize not used + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getOFString(OFString &stringVal, + const unsigned long pos, + OFBool normalize = OFTrue); + + /** set particular tag value + * @param tagVal tag value to be set + * @param pos index of the value to be set (0 = first position) + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition putTagVal(const DcmTagKey &tagVal, + const unsigned long pos = 0); + + /** set element value to given integer array data. + * The array entries with an even-numbered index are expected to contain the + * group numbers and the odd entries to contain the element numbers, e.g. + * {0x0008, 0x0020, 0x0008, 0x0030}. This function uses the same format as + * "getUint16Array()". + * @param uintVals unsigned integer data to be set + * @param numUints number of integer values to be set (should be even) + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition putUint16Array(const Uint16 *uintVals, + const unsigned long numUints); + + /** set element value from the given character string. + * The input string is expected to be a backslash separated sequence of + * attribute tags, e.g. "(0008,0020)\(0008,0030)". This is the same format + * as used by "print()". + * @param stringVal input character string + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition putString(const char *stringVal); + + /** set element value from the given character string. + * The input string is expected to be a backslash separated sequence of + * attribute tags, e.g. "(0008,0020)\(0008,0030)". This is the same format + * as used by "print()". + * The length of the string has to be specified explicitly. The string can, therefore, + * also contain more than one NULL byte. + * @param stringVal input character string + * @param stringLen length of the string (number of characters without the trailing + * NULL byte) + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition putString(const char *stringVal, + const Uint32 stringLen); + + /** check the currently stored element value + * @param autocorrect correct value length if OFTrue + * @return status, EC_Normal if value length is correct, an error code otherwise + */ + virtual OFCondition verify(const OFBool autocorrect = OFFalse); + + /* --- static helper functions --- */ + + /** check whether given string value conforms to the VR "AT" (Attribute Tag) + * and to the specified VM. + * @param value string value to be checked (possibly multi-valued) + * @param vm value multiplicity (according to the data dictionary) to be checked for. + * (See DcmElement::checkVM() for a list of valid values.) + * @return status of the check, EC_Normal if value is correct, an error code otherwise + */ + static OFCondition checkStringValue(const OFString &value, + const OFString &vm = "1-n"); +}; + + +#endif // DCVRAT_H diff --git a/dcmdata/include/dcmtk/dcmdata/dcvrcs.h b/dcmdata/include/dcmtk/dcmdata/dcvrcs.h new file mode 100644 index 00000000..295eca3b --- /dev/null +++ b/dcmdata/include/dcmtk/dcmdata/dcvrcs.h @@ -0,0 +1,136 @@ +/* + * + * Copyright (C) 1994-2013, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Gerd Ehlers, Andreas Barth + * + * Purpose: Interface of class DcmCodeString + * + */ + + +#ifndef DCVRCS_H +#define DCVRCS_H + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/dcmdata/dcbytstr.h" + + +/** a class representing the DICOM value representation 'Code String' (CS) + */ +class DCMTK_DCMDATA_EXPORT DcmCodeString + : public DcmByteString +{ + + public: + + /** constructor. + * Create new element from given tag and length. + * @param tag DICOM tag for the new element + * @param len value length for the new element + */ + DcmCodeString(const DcmTag &tag, + const Uint32 len = 0); + + /** copy constructor + * @param old element to be copied + */ + DcmCodeString(const DcmCodeString &old); + + /** destructor + */ + virtual ~DcmCodeString(); + + /** assignment operator + * @param obj element to be assigned/copied + * @return reference to this object + */ + DcmCodeString &operator=(const DcmCodeString &obj); + + /** clone method + * @return deep copy of this object + */ + virtual DcmObject *clone() const + { + return new DcmCodeString(*this); + } + + /** Virtual object copying. This method can be used for DcmObject + * and derived classes to get a deep copy of an object. Internally + * the assignment operator is called if the given DcmObject parameter + * is of the same type as "this" object instance. If not, an error + * is returned. This function permits copying an object by value + * in a virtual way which therefore is different to just calling the + * assignment operator of DcmElement which could result in slicing + * the object. + * @param rhs - [in] The instance to copy from. Has to be of the same + * class type as "this" object + * @return EC_Normal if copying was successful, error otherwise + */ + virtual OFCondition copyFrom(const DcmObject& rhs); + + /** get element type identifier + * @return type identifier of this class (EVR_CS) + */ + virtual DcmEVR ident() const; + + /** check whether stored value conforms to the VR and to the specified VM + * @param vm value multiplicity (according to the data dictionary) to be checked for. + * (See DcmElement::checkVM() for a list of valid values.) + * @param oldFormat parameter not used for this VR (only for DA, TM) + * @return status of the check, EC_Normal if value is correct, an error code otherwise + */ + virtual OFCondition checkValue(const OFString &vm = "1-n", + const OFBool oldFormat = OFFalse); + + /** get a copy of a particular string component + * @param stringVal variable in which the result value is stored + * @param pos index of the value in case of multi-valued elements (0..vm-1) + * @param normalize delete leading and trailing spaces if OFTrue + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getOFString(OFString &stringVal, + const unsigned long pos, + OFBool normalize = OFTrue); + + /* --- static helper functions --- */ + + /** check whether given value conforms to value representation CS (Code String). + * Valid characters are: A-Z, 0-9, _ and ' ' (space). The maximum length is 16. + * NB: This method is only used by the DicomDirInterface class and might be + * replaced by the following method (checkStringValue) in the future. + * @param value string value to be checked (single value only) + * @param pos returns index of first invalid character (0..n-1) if not NULL. + * Points to trailing zero byte (eos) if value is valid. + * @param checkLength check maximum length if OFTrue, ignore length if OFFalse + * @return OFTrue if value is valid, OFFalse otherwise + */ + static OFBool checkVR(const OFString &value, + size_t *pos = NULL, + const OFBool checkLength = OFTrue); + + /** check whether given string value conforms to the VR "CS" (Code String) + * and to the specified VM. + * @param value string value to be checked (possibly multi-valued) + * @param vm value multiplicity (according to the data dictionary) to be checked for. + * (See DcmElement::checkVM() for a list of valid values.) + * @return status of the check, EC_Normal if value is correct, an error code otherwise + */ + static OFCondition checkStringValue(const OFString &value, + const OFString &vm = "1-n"); +}; + + +#endif // DCVRCS_H diff --git a/dcmdata/include/dcmtk/dcmdata/dcvrda.h b/dcmdata/include/dcmtk/dcmdata/dcvrda.h new file mode 100644 index 00000000..928bb57e --- /dev/null +++ b/dcmdata/include/dcmtk/dcmdata/dcvrda.h @@ -0,0 +1,214 @@ +/* + * + * Copyright (C) 1994-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Gerd Ehlers, Andreas Barth, Joerg Riesmeier + * + * Purpose: Interface of class DcmDate + * + */ + +#ifndef DCVRDA_H +#define DCVRDA_H + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/dcmdata/dcbytstr.h" +#include "dcmtk/ofstd/ofdate.h" + + +/** a class representing the DICOM value representation 'Date' (DA) + */ +class DCMTK_DCMDATA_EXPORT DcmDate + : public DcmByteString +{ + + public: + + /** constructor. + * Create new element from given tag and length. + * @param tag DICOM tag for the new element + * @param len value length for the new element + */ + DcmDate(const DcmTag &tag, + const Uint32 len = 0); + + /** copy constructor + * @param old element to be copied + */ + DcmDate(const DcmDate &old); + + /** destructor + */ + virtual ~DcmDate(); + + /** assignment operator + * @param obj element to be assigned/copied + * @return reference to this object + */ + DcmDate &operator=(const DcmDate &obj); + + /** clone method + * @return deep copy of this object + */ + virtual DcmObject *clone() const + { + return new DcmDate(*this); + } + + /** Virtual object copying. This method can be used for DcmObject + * and derived classes to get a deep copy of an object. Internally + * the assignment operator is called if the given DcmObject parameter + * is of the same type as "this" object instance. If not, an error + * is returned. This function permits copying an object by value + * in a virtual way which therefore is different to just calling the + * assignment operator of DcmElement which could result in slicing + * the object. + * @param rhs - [in] The instance to copy from. Has to be of the same + * class type as "this" object + * @return EC_Normal if copying was successful, error otherwise + */ + virtual OFCondition copyFrom(const DcmObject& rhs); + + /** get element type identifier + * @return type identifier of this class (EVR_DA) + */ + virtual DcmEVR ident() const; + + /** check whether stored value conforms to the VR and to the specified VM + * @param vm value multiplicity (according to the data dictionary) to be checked for. + * (See DcmElement::checkVM() for a list of valid values.) + * @param oldFormat support old ACR/NEMA format if OFTrue ('.' as a separator) + * @return status of the check, EC_Normal if value is correct, an error code otherwise + */ + virtual OFCondition checkValue(const OFString &vm = "1-n", + const OFBool oldFormat = OFFalse); + + /** get a copy of a particular string component + * @param stringVal variable in which the result value is stored + * @param pos index of the value in case of multi-valued elements (0..vm-1) + * @param normalize delete trailing spaces if OFTrue + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getOFString(OFString &stringVal, + const unsigned long pos, + OFBool normalize = OFTrue); + + /** set the element value to the current system date. + * The DICOM DA format supported by this function is "YYYYMMDD". If the current + * system date is unavailable the date is set to "19000101" and an error code is + * returned. + * @return EC_Normal upon success, an error code otherwise + */ + OFCondition setCurrentDate(); + + /** set the element value to the given date + * @param dateValue date to be set (should be a valid date) + * @return EC_Normal upon success, an error code otherwise + */ + OFCondition setOFDate(const OFDate &dateValue); + + /** get the current element value in OFDate format. + * Please note that the element value is expected to be in valid DICOM DA format + * ("YYYYMMDD", "YYYY.MM.DD" is also supported for reasons of backward compatibility). + * If this function fails the result variable 'dateValue' is cleared automatically. + * @param dateValue reference to OFDate variable where the result is stored + * @param pos index of the element component in case of value multiplicity (0..vm-1) + * @param supportOldFormat if OFTrue support old (prior V3.0) date format (see above) + * @return EC_Normal upon success, an error code otherwise + */ + OFCondition getOFDate(OFDate &dateValue, + const unsigned long pos = 0, + const OFBool supportOldFormat = OFTrue); + + /** get the current element value in ISO date format. + * The ISO date format supported by this function is "YYYY-MM-DD". Please note + * that the element value is expected to be in valid DICOM DA format ("YYYYMMDD", + * "YYYY.MM.DD" is also supported for reasons of backward compatibility). + * If this function fails or the current element value is empty, the result + * variable 'formattedDate' is cleared automatically. + * @param formattedDate reference to string variable where the result is stored + * @param pos index of the element component in case of value multiplicity (0..vm-1) + * @param supportOldFormat if OFTrue support old (prior V3.0) date format (see above) + * @return EC_Normal upon success, an error code otherwise + */ + OFCondition getISOFormattedDate(OFString &formattedDate, + const unsigned long pos = 0, + const OFBool supportOldFormat = OFTrue); + + /* --- static helper functions --- */ + + /** get the current system date. + * The DICOM DA format supported by this function is "YYYYMMDD". If the current + * system date is unavailable the date is set to "19000101" and an error code is + * returned. + * @param dicomDate reference to string variable where the result is stored + * @return EC_Normal upon success, an error code otherwise + */ + static OFCondition getCurrentDate(OFString &dicomDate); + + /** get the specified OFDate value in DICOM format. + * The DICOM DA format supported by this function is "YYYYMMDD". If the specified + * date is invalid the date is set to "19000101" and an error code is returned. + * @param dateValue date to be converted to DICOM format + * @param dicomDate reference to string variable where the result is stored + * @return EC_Normal upon success, an error code otherwise + */ + static OFCondition getDicomDateFromOFDate(const OFDate &dateValue, + OFString &dicomDate); + + /** get the specified DICOM date value in OFDate format. + * Please note that the specified value is expected to be in valid DICOM DA format + * ("YYYYMMDD", "YYYY.MM.DD" is also supported for reasons of backward compatibility). + * If this function fails, the result variable 'dateValue' is cleared automatically. + * @param dicomDate string value in DICOM DA format to be converted to ISO format. + * An empty string is not regarded as valid input, since the date would be unknown. + * @param dateValue reference to OFDate variable where the result is stored + * @param supportOldFormat if OFTrue support old (prior V3.0) date format (see above) + * @return EC_Normal upon success, an error code otherwise + */ + static OFCondition getOFDateFromString(const OFString &dicomDate, + OFDate &dateValue, + const OFBool supportOldFormat = OFTrue); + + /** get the specified DICOM date value in ISO format. + * The ISO date format supported by this function is "YYYY-MM-DD". Please note + * that the specified value is expected to be in valid DICOM DA format ("YYYYMMDD", + * "YYYY.MM.DD" is also supported for reasons of backward compatibility). + * If this function fails or the specified DICOM date value is empty, the result + * variable 'formattedDate' is cleared automatically. + * @param dicomDate string value in DICOM DA format to be converted to ISO format + * @param formattedDate reference to string variable where the result is stored + * @param supportOldFormat if OFTrue support old (prior V3.0) date format (see above) + * @return EC_Normal upon success, an error code otherwise + */ + static OFCondition getISOFormattedDateFromString(const OFString &dicomDate, + OFString &formattedDate, + const OFBool supportOldFormat = OFTrue); + + /** check whether given string value conforms to the VR "DA" (Date) + * and to the specified VM. + * @param value string value to be checked (possibly multi-valued) + * @param vm value multiplicity (according to the data dictionary) to be checked for. + * (See DcmElement::checkVM() for a list of valid values.) + * @param oldFormat support old ACR/NEMA date format if OFTrue (i.e. with "." delimiters) + * @return status of the check, EC_Normal if value is correct, an error code otherwise + */ + static OFCondition checkStringValue(const OFString &value, + const OFString &vm = "1-n", + const OFBool oldFormat = OFFalse); +}; + + +#endif // DCVRDA_H diff --git a/dcmdata/include/dcmtk/dcmdata/dcvrds.h b/dcmdata/include/dcmtk/dcmdata/dcvrds.h new file mode 100644 index 00000000..211e767d --- /dev/null +++ b/dcmdata/include/dcmtk/dcmdata/dcvrds.h @@ -0,0 +1,150 @@ +/* + * + * Copyright (C) 1994-2013, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Gerd Ehlers, Andreas Barth + * + * Purpose: Interface of class DcmDecimalString + * + */ + + +#ifndef DCVRDS_H +#define DCVRDS_H + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/ofstd/ofvector.h" +#include "dcmtk/dcmdata/dcbytstr.h" + + +/** a class representing the DICOM value representation 'Decimal String' (DS) + */ +class DCMTK_DCMDATA_EXPORT DcmDecimalString + : public DcmByteString +{ + + public: + + /** constructor. + * Create new element from given tag and length. + * @param tag DICOM tag for the new element + * @param len value length for the new element + */ + DcmDecimalString(const DcmTag &tag, + const Uint32 len = 0); + + /** copy constructor + * @param old element to be copied + */ + DcmDecimalString(const DcmDecimalString &old); + + /** destructor + */ + virtual ~DcmDecimalString(); + + /** assignment operator + * @param obj element to be assigned/copied + * @return reference to this object + */ + DcmDecimalString &operator=(const DcmDecimalString &obj); + + /** clone method + * @return deep copy of this object + */ + virtual DcmObject *clone() const + { + return new DcmDecimalString(*this); + } + + /** Virtual object copying. This method can be used for DcmObject + * and derived classes to get a deep copy of an object. Internally + * the assignment operator is called if the given DcmObject parameter + * is of the same type as "this" object instance. If not, an error + * is returned. This function permits copying an object by value + * in a virtual way which therefore is different to just calling the + * assignment operator of DcmElement which could result in slicing + * the object. + * @param rhs - [in] The instance to copy from. Has to be of the same + * class type as "this" object + * @return EC_Normal if copying was successful, error otherwise + */ + virtual OFCondition copyFrom(const DcmObject& rhs); + + /** get element type identifier + * @return type identifier of this class (EVR_DS) + */ + virtual DcmEVR ident() const; + + /** check whether stored value conforms to the VR and to the specified VM + * @param vm value multiplicity (according to the data dictionary) to be checked for. + * (See DcmElement::checkVM() for a list of valid values.) + * @param oldFormat parameter not used for this VR (only for DA, TM) + * @return status of the check, EC_Normal if value is correct, an error code otherwise + */ + virtual OFCondition checkValue(const OFString &vm = "1-n", + const OFBool oldFormat = OFFalse); + + /** get particular float value + * @param doubleVal reference to result variable + * @param pos index of the value to be retrieved (0..vm-1) + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getFloat64(Float64 &doubleVal, + const unsigned long pos = 0); + + /** get stored float values as a vector. + * Please note that only an element value consisting of zero or more spaces is considered + * as being empty and, therefore, results in an empty vector with status ".good()"; use + * isEmpty() before calling this method if you also want to check for other non-significant + * characters (e.g. the backslash). + * @param doubleVals reference to result variable + * (cleared automatically before entries are added) + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getFloat64Vector(OFVector &doubleVals); + + /** get a particular value as a character string + * @param stringVal variable in which the result value is stored + * @param pos index of the value in case of multi-valued elements (0..vm-1) + * @param normalize delete leading and trailing spaces if OFTrue + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getOFString(OFString &stringVal, + const unsigned long pos, + OFBool normalize = OFTrue); + + /** write object in XML format + * @param out output stream to which the XML document is written + * @param flags optional flag used to customize the output (see DCMTypes::XF_xxx) + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition writeXML(STD_NAMESPACE ostream &out, + const size_t flags = 0); + + /* --- static helper functions --- */ + + /** check whether given string value conforms to the VR "DS" (Decimal String) + * and to the specified VM. + * @param value string value to be checked (possibly multi-valued) + * @param vm value multiplicity (according to the data dictionary) to be checked for. + * (See DcmElement::checkVM() for a list of valid values.) + * @return status of the check, EC_Normal if value is correct, an error code otherwise + */ + static OFCondition checkStringValue(const OFString &value, + const OFString &vm = "1-n"); +}; + + +#endif // DCVRDS_H diff --git a/dcmdata/include/dcmtk/dcmdata/dcvrdt.h b/dcmdata/include/dcmtk/dcmdata/dcvrdt.h new file mode 100644 index 00000000..a6522818 --- /dev/null +++ b/dcmdata/include/dcmtk/dcmdata/dcvrdt.h @@ -0,0 +1,270 @@ +/* + * + * Copyright (C) 1994-2015, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Gerd Ehlers, Joerg Riesmeier + * + * Purpose: Interface of class DcmDateTime + * + */ + +#ifndef DCVRDT_H +#define DCVRDT_H + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/dcmdata/dcbytstr.h" +#include "dcmtk/ofstd/ofdatime.h" + + +/** a class representing the DICOM value representation 'Date Time' (DT) + */ +class DCMTK_DCMDATA_EXPORT DcmDateTime + : public DcmByteString +{ + + public: + + /** constructor. + * Create new element from given tag and length. + * @param tag DICOM tag for the new element + * @param len value length for the new element + */ + DcmDateTime(const DcmTag &tag, + const Uint32 len = 0); + + /** copy constructor + * @param old element to be copied + */ + DcmDateTime(const DcmDateTime &old); + + /** destructor + */ + virtual ~DcmDateTime(); + + /** assignment operator + * @param obj element to be assigned/copied + * @return reference to this object + */ + DcmDateTime &operator=(const DcmDateTime &obj); + + /** clone method + * @return deep copy of this object + */ + virtual DcmObject *clone() const + { + return new DcmDateTime(*this); + } + + /** Virtual object copying. This method can be used for DcmObject + * and derived classes to get a deep copy of an object. Internally + * the assignment operator is called if the given DcmObject parameter + * is of the same type as "this" object instance. If not, an error + * is returned. This function permits copying an object by value + * in a virtual way which therefore is different to just calling the + * assignment operator of DcmElement which could result in slicing + * the object. + * @param rhs - [in] The instance to copy from. Has to be of the same + * class type as "this" object + * @return EC_Normal if copying was successful, error otherwise + */ + virtual OFCondition copyFrom(const DcmObject& rhs); + + /** get element type identifier + * @return type identifier of this class (EVR_DT) + */ + virtual DcmEVR ident() const; + + /** check whether stored value conforms to the VR and to the specified VM + * @param vm value multiplicity (according to the data dictionary) to be checked for. + * (See DcmElement::checkVM() for a list of valid values.) + * @param oldFormat parameter not used for this VR (only for DA, TM) + * @return status of the check, EC_Normal if value is correct, an error code otherwise + */ + virtual OFCondition checkValue(const OFString &vm = "1-n", + const OFBool oldFormat = OFFalse); + + /** get a copy of a particular string component + * @param stringValue variable in which the result value is stored + * @param pos index of the value in case of multi-valued elements (0..vm-1) + * @param normalize delete trailing spaces if OFTrue + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getOFString(OFString &stringValue, + const unsigned long pos, + OFBool normalize = OFTrue); + + /** set the element value to the current system date and time. + * The DICOM DT format supported by this function is "YYYYMMDDHHMM[SS[.FFFFFF]][&ZZZZ]" + * where the brackets enclose optional parts. If the current system date/time or parts + * of it are unavailable the corresponding values are set to "0" and an error code is + * returned - in fact, the date is set to "19000101" if unavailable. + * @param seconds add optional seconds ("SS") if OFTrue + * @param fraction add optional fractional part of a second (".FFFFFF") if OFTrue + * (requires parameter 'seconds' to be also OFTrue) + * @param timeZone add optional time zone ("&ZZZZ" where "&" is "+" or "-") if OFTrue. + * The time zone is given as the offset (hours and minutes) from Coordinated Universal + * Time (UTC). + * @return EC_Normal upon success, an error code otherwise + */ + OFCondition setCurrentDateTime(const OFBool seconds = OFTrue, + const OFBool fraction = OFFalse, + const OFBool timeZone = OFFalse); + + /** set the element value to the given date and time + * @param dateTimeValue date to be set (should be a valid date and time) + * @return EC_Normal upon success, an error code otherwise + */ + OFCondition setOFDateTime(const OFDateTime &dateTimeValue); + + /** get the current element value in OFDateTime format. + * Please note that the element value is expected to be in valid DICOM DT format + * ("YYYYMMDD[HH[MM[SS[.FFFFFF]]]][&ZZZZ]"). If the optional time zone ("&ZZZZ") is + * missing the local time zone is used. + * If this function fails the result variable 'dateTimeValue' is cleared automatically. + * @param dateTimeValue reference to OFDateTime variable where the result is stored + * @param pos index of the element component in case of value multiplicity (0..vm-1) + * @return EC_Normal upon success, an error code otherwise + */ + OFCondition getOFDateTime(OFDateTime &dateTimeValue, + const unsigned long pos = 0); + + /** get the current element value in ISO date/time format. + * The ISO date/time format supported by this function is "YYYY-MM-DD[ HH:MM[:SS[.FFFFFF]]] + * [&HH:MM]" where the brackets enclose optional parts. Please note that the element value + * is expected to be in valid DICOM DT format ("YYYYMMDD[HH[MM[SS[.FFFFFF]]]][&ZZZZ]"). + * If this function fails or the current element value is empty, the result variable + * 'formattedDateTime' is cleared automatically. + * @param formattedDateTime reference to string variable where the result is stored + * @param pos index of the element component in case of value multiplicity (0..vm-1) + * @param seconds add optional seconds (":SS") if OFTrue + * @param fraction add optional fractional part of a second (".FFFFFF") if OFTrue + * (requires parameter 'seconds' to be also OFTrue) + * @param timeZone add optional time zone ("&HH:MM" where "&" is "+" or "-") if OFTrue. + * The time zone is given as the offset (hours and minutes) from Coordinated Universal + * Time (UTC). Please note that the formatted time output is not adapted to the local + * time if the time zone is omitted. + * @param createMissingPart if OFTrue create optional parts (seconds, fractional part of + * a seconds and/or time zone) if absent in the element value + * @param dateTimeSeparator separator between ISO date and time value + * @param timeZoneSeparator separator between ISO time value and time zone + * @return EC_Normal upon success, an error code otherwise + */ + OFCondition getISOFormattedDateTime(OFString &formattedDateTime, + const unsigned long pos = 0, + const OFBool seconds = OFTrue, + const OFBool fraction = OFFalse, + const OFBool timeZone = OFTrue, + const OFBool createMissingPart = OFFalse, + const OFString &dateTimeSeparator = " ", + const OFString &timeZoneSeparator = " "); + + /* --- static helper functions --- */ + + /** get the current system date and time. + * The DICOM DT format supported by this function is "YYYYMMDDHHMM[SS[.FFFFFF]][&ZZZZ]" + * where the brackets enclose optional parts. If the current system date/time or parts + * of it are unavailable the corresponding values are set to "0" and an error code is + * returned - in fact, the date is set to "19000101" if unavailable. + * @param dicomDateTime reference to string variable where the result is stored + * @param seconds add optional seconds ("SS") if OFTrue + * @param fraction add optional fractional part of a second (".FFFFFF") if OFTrue + * (requires parameter 'seconds' to be also OFTrue) + * @param timeZone add optional time zone ("&ZZZZ" where "&" is "+" or "-") if OFTrue. + * The time zone is given as the offset (hours and minutes) from Coordinated Universal + * Time (UTC). + * @return EC_Normal upon success, an error code otherwise + */ + static OFCondition getCurrentDateTime(OFString &dicomDateTime, + const OFBool seconds = OFTrue, + const OFBool fraction = OFFalse, + const OFBool timeZone = OFFalse); + + /** get the specified OFDateTime value in DICOM format. + * The DICOM DT format supported by this function is "YYYYMMDDHHMM[SS[.FFFFFF]][&ZZZZ]" + * where the brackets enclose optional parts. If the current system date/time or parts + * of it are unavailable the corresponding values are set to "0" and an error code is + * returned - in fact, the date is set to "19000101" if unavailable. + * @param dateTimeValue date and time to be converted to DICOM format + * @param dicomDateTime reference to string variable where the result is stored + * @param seconds add optional seconds ("SS") if OFTrue + * @param fraction add optional fractional part of a second (".FFFFFF") if OFTrue + * (requires parameter 'seconds' to be also OFTrue) + * @param timeZone add optional time zone ("&ZZZZ" where "&" is "+" or "-") if OFTrue. + * The time zone is given as the offset (hours and minutes) from Coordinated Universal + * Time (UTC). + * @return EC_Normal upon success, an error code otherwise + */ + static OFCondition getDicomDateTimeFromOFDateTime(const OFDateTime &dateTimeValue, + OFString &dicomDateTime, + const OFBool seconds = OFTrue, + const OFBool fraction = OFFalse, + const OFBool timeZone = OFFalse); + + /** get the specified DICOM date and time value in OFDateTime format. + * Please note that the element value is expected to be in valid DICOM DT format + * ("YYYYMMDD[HH[MM[SS[.FFFFFF]]]][&ZZZZ]"). If the optional time zone ("&ZZZZ") is + * missing the local time zone is used. + * If this function fails, the result variable 'dateTimeValue' is cleared automatically. + * @param dicomDateTime string value in DICOM DT format to be converted to ISO format. + * An empty string is not regarded as valid input, since the date/time would be unknown. + * @param dateTimeValue reference to OFDateTime variable where the result is stored + * @return EC_Normal upon success, an error code otherwise + */ + static OFCondition getOFDateTimeFromString(const OFString &dicomDateTime, + OFDateTime &dateTimeValue); + + /** get the specified DICOM datetime value in ISO format. + * The ISO date/time format supported by this function is "YYYY-MM-DD[ HH:MM[:SS[.FFFFFF]]] + * [&HH:MM]" where the brackets enclose optional parts. Please note that the specified + * value is expected to be in valid DICOM DT format ("YYYYMMDD[HH[MM[SS[.FFFFFF]]]][&ZZZZ]"). + * If this function fails or the specified DICOM datetime value is empty, the result + * variable 'formattedDateTime' is cleared automatically. + * @param dicomDateTime string value in DICOM DT format to be converted to ISO format + * @param formattedDateTime reference to string variable where the result is stored + * @param seconds add optional seconds (":SS") if OFTrue + * @param fraction add optional fractional part of a second (".FFFFFF") if OFTrue + * (requires parameter 'seconds' to be also OFTrue) + * @param timeZone add optional time zone ("&HH:MM" where "&" is "+" or "-") if OFTrue. + * The time zone is given as the offset (hours and minutes) from the Coordinated Universal + * Time (UTC). Please note that the formatted time output is not adapted to the local time + * if the time zone is omitted. + * @param createMissingPart if OFTrue create optional parts (seconds, fractional part of + * a seconds and/or time zone) if absent in the element value + * @param dateTimeSeparator separator between ISO date and time value + * @param timeZoneSeparator separator between ISO time value and time zone + * @return EC_Normal upon success, an error code otherwise + */ + static OFCondition getISOFormattedDateTimeFromString(const OFString &dicomDateTime, + OFString &formattedDateTime, + const OFBool seconds = OFTrue, + const OFBool fraction = OFFalse, + const OFBool timeZone = OFTrue, + const OFBool createMissingPart = OFFalse, + const OFString &dateTimeSeparator = " ", + const OFString &timeZoneSeparator = " "); + + /** check whether given string value conforms to the VR "DT" (Date Time) + * and to the specified VM. + * @param value string value to be checked (possibly multi-valued) + * @param vm value multiplicity (according to the data dictionary) to be checked for. + * (See DcmElement::checkVM() for a list of valid values.) + * @return status of the check, EC_Normal if value is correct, an error code otherwise + */ + static OFCondition checkStringValue(const OFString &value, + const OFString &vm = "1-n"); +}; + + +#endif // DCVRDT_H diff --git a/dcmdata/include/dcmtk/dcmdata/dcvrfd.h b/dcmdata/include/dcmtk/dcmdata/dcvrfd.h new file mode 100644 index 00000000..51bceacc --- /dev/null +++ b/dcmdata/include/dcmtk/dcmdata/dcvrfd.h @@ -0,0 +1,208 @@ +/* + * + * Copyright (C) 1994-2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Gerd Ehlers, Andreas Barth + * + * Purpose: Interface of class DcmFloatingPointDouble + * + */ + + +#ifndef DCVRFD_H +#define DCVRFD_H + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/dcmdata/dcelem.h" + + +/** a class representing the DICOM value representation 'Floating Point Double' (FD) + */ +class DCMTK_DCMDATA_EXPORT DcmFloatingPointDouble + : public DcmElement +{ + + public: + + /** constructor. + * Create new element from given tag and length. + * @param tag DICOM tag for the new element + * @param len value length for the new element + */ + DcmFloatingPointDouble(const DcmTag &tag, + const Uint32 len = 0); + + /** copy constructor + * @param old element to be copied + */ + DcmFloatingPointDouble( const DcmFloatingPointDouble &old); + + /** destructor + */ + virtual ~DcmFloatingPointDouble(); + + /** assignment operator + * @param obj element to be assigned/copied + * @return reference to this object + */ + DcmFloatingPointDouble &operator=(const DcmFloatingPointDouble &obj); + + /** comparison operator that compares the normalized value of this object + * with a given object of the same type. The tag of the element is also + * considered as the first component that is compared, followed by the + * object types (VR, i.e. DCMTK'S EVR) and the comparison of all value + * components of the object, preferrably in the order declared in the + * object (if applicable). + * @param rhs the right hand side of the comparison + * @return 0 if the object values are equal. + * -1 if either the value of the first component that does not match + * is lower in this object than in rhs, or all compared components match + * but this object has fewer components than rhs. Also returned if rhs + * cannot be casted to this object type. + * 1 if either the value of the first component that does not match + * is greater in this object than in rhs object, or all compared + * components match but the this component is longer. + */ + virtual int compare(const DcmElement& rhs) const; + + /** clone method + * @return deep copy of this object + */ + virtual DcmObject *clone() const + { + return new DcmFloatingPointDouble(*this); + } + + /** Virtual object copying. This method can be used for DcmObject + * and derived classes to get a deep copy of an object. Internally + * the assignment operator is called if the given DcmObject parameter + * is of the same type as "this" object instance. If not, an error + * is returned. This function permits copying an object by value + * in a virtual way which therefore is different to just calling the + * assignment operator of DcmElement which could result in slicing + * the object. + * @param rhs - [in] The instance to copy from. Has to be of the same + * class type as "this" object + * @return EC_Normal if copying was successful, error otherwise + */ + virtual OFCondition copyFrom(const DcmObject& rhs); + + /** get element type identifier + * @return type identifier of this class (EVR_FD) + */ + virtual DcmEVR ident() const; + + /** check whether stored value conforms to the VR and to the specified VM + * @param vm value multiplicity (according to the data dictionary) to be checked for. + * (See DcmElement::checkVM() for a list of valid values.) + * @param oldFormat parameter not used for this VR (only for DA, TM) + * @return status of the check, EC_Normal if value is correct, an error code otherwise + */ + virtual OFCondition checkValue(const OFString &vm = "1-n", + const OFBool oldFormat = OFFalse); + + /** get value multiplicity + * @return number of currently stored values + */ + virtual unsigned long getVM(); + + /** print element to a stream. + * The output format of the value is a backslash separated sequence of numbers. + * This function uses a variable number of digits for the floating point values + * as created by the OFStandard::ftoa() function by default. + * @param out output stream + * @param flags optional flag used to customize the output (see DCMTypes::PF_xxx) + * @param level current level of nested items. Used for indentation. + * @param pixelFileName not used + * @param pixelCounter not used + */ + virtual void print(STD_NAMESPACE ostream&out, + const size_t flags = 0, + const int level = 0, + const char *pixelFileName = NULL, + size_t *pixelCounter = NULL); + + /** get particular double value + * @param doubleVal reference to result variable (cleared in case of error) + * @param pos index of the value to be retrieved (0..vm-1) + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getFloat64(Float64 &doubleVal, + const unsigned long pos = 0); + + /** get reference to stored double data + * @param doubleVals reference to result variable + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getFloat64Array(Float64 *&doubleVals); + + /** get a particular value as a character string. + * The resulting string contains a variable number of digits as created by + * the OFStandard::ftoa() function by default. + * @param stringVal variable in which the result value is stored + * @param pos index of the value in case of multi-valued elements (0..vm-1) + * @param normalize not used + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getOFString(OFString &stringVal, + const unsigned long pos, + OFBool normalize = OFTrue); + + /** set particular element value to given double + * @param doubleval double precision floating point value to be set + * @param pos index of the value to be set (0 = first position) + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition putFloat64(const Float64 doubleval, + const unsigned long pos = 0); + + /** set element value to given double array data + * @param doubleVals double precision floating point data to be set + * @param numDoubles number of double values to be set + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition putFloat64Array(const Float64 *doubleVals, + const unsigned long numDoubles); + + /** set element value from the given character string. + * The input string is expected to be a backslash separated sequence of + * numeric characters, e.g. "12.3456\1\-123.456\1234.0". + * @param stringVal input character string + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition putString(const char *stringVal); + + /** set element value from the given character string. + * The input string is expected to be a backslash separated sequence of + * numeric characters, e.g. "12.3456\1\-123.456\1234.0". + * The length of the string has to be specified explicitly. The string can, therefore, + * also contain more than one NULL byte. + * @param stringVal input character string + * @param stringLen length of the string (number of characters without the trailing + * NULL byte) + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition putString(const char *stringVal, + const Uint32 stringLen); + + /** check the currently stored element value + * @param autocorrect correct value length if OFTrue + * @return status, EC_Normal if value length is correct, an error code otherwise + */ + virtual OFCondition verify(const OFBool autocorrect = OFFalse); +}; + + +#endif // DCVRFD_H diff --git a/dcmdata/include/dcmtk/dcmdata/dcvrfl.h b/dcmdata/include/dcmtk/dcmdata/dcvrfl.h new file mode 100644 index 00000000..74a67de9 --- /dev/null +++ b/dcmdata/include/dcmtk/dcmdata/dcvrfl.h @@ -0,0 +1,208 @@ +/* + * + * Copyright (C) 1994-2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Gerd Ehlers, Andreas Barth + * + * Purpose: Interface of class DcmFloatingPointSingle + * + */ + + +#ifndef DCVRFL_H +#define DCVRFL_H + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/dcmdata/dcelem.h" + + +/** a class representing the DICOM value representation 'Floating Point Single' (FL) + */ +class DCMTK_DCMDATA_EXPORT DcmFloatingPointSingle + : public DcmElement +{ + + public: + + /** constructor. + * Create new element from given tag and length. + * @param tag DICOM tag for the new element + * @param len value length for the new element + */ + DcmFloatingPointSingle(const DcmTag &tag, + const Uint32 len = 0); + + /** copy constructor + * @param old element to be copied + */ + DcmFloatingPointSingle(const DcmFloatingPointSingle &old); + + /** destructor + */ + virtual ~DcmFloatingPointSingle(); + + /** assignment operator + * @param obj element to be assigned/copied + * @return reference to this object + */ + DcmFloatingPointSingle &operator=(const DcmFloatingPointSingle &obj); + + /** comparison operator that compares the normalized value of this object + * with a given object of the same type. The tag of the element is also + * considered as the first component that is compared, followed by the + * object types (VR, i.e. DCMTK'S EVR) and the comparison of all value + * components of the object, preferrably in the order declared in the + * object (if applicable). + * @param rhs the right hand side of the comparison + * @return 0 if the object values are equal. + * -1 if either the value of the first component that does not match + * is lower in this object than in rhs, or all compared components match + * but this object has fewer components than rhs. Also returned if rhs + * cannot be casted to this object type. + * 1 if either the value of the first component that does not match + * is greater in this object than in rhs object, or all compared + * components match but the this component is longer. + */ + virtual int compare(const DcmElement& rhs) const; + + /** clone method + * @return deep copy of this object + */ + virtual DcmObject *clone() const + { + return new DcmFloatingPointSingle(*this); + } + + /** Virtual object copying. This method can be used for DcmObject + * and derived classes to get a deep copy of an object. Internally + * the assignment operator is called if the given DcmObject parameter + * is of the same type as "this" object instance. If not, an error + * is returned. This function permits copying an object by value + * in a virtual way which therefore is different to just calling the + * assignment operator of DcmElement which could result in slicing + * the object. + * @param rhs - [in] The instance to copy from. Has to be of the same + * class type as "this" object + * @return EC_Normal if copying was successful, error otherwise + */ + virtual OFCondition copyFrom(const DcmObject& rhs); + + /** get element type identifier + * @return type identifier of this class (EVR_FL) + */ + virtual DcmEVR ident(void) const; + + /** check whether stored value conforms to the VR and to the specified VM + * @param vm value multiplicity (according to the data dictionary) to be checked for. + * (See DcmElement::checkVM() for a list of valid values.) + * @param oldFormat parameter not used for this VR (only for DA, TM) + * @return status of the check, EC_Normal if value is correct, an error code otherwise + */ + virtual OFCondition checkValue(const OFString &vm = "1-n", + const OFBool oldFormat = OFFalse); + + /** get value multiplicity + * @return number of currently stored values + */ + virtual unsigned long getVM(); + + /** print element to a stream. + * The output format of the value is a backslash separated sequence of numbers. + * This function uses a variable number of digits for the floating point values + * as created by the OFStandard::ftoa() function by default. + * @param out output stream + * @param flags optional flag used to customize the output (see DCMTypes::PF_xxx) + * @param level current level of nested items. Used for indentation. + * @param pixelFileName not used + * @param pixelCounter not used + */ + virtual void print(STD_NAMESPACE ostream&out, + const size_t flags = 0, + const int level = 0, + const char *pixelFileName = NULL, + size_t *pixelCounter = NULL); + + /** get particular float value + * @param floatVal reference to result variable (cleared in case of error) + * @param pos index of the value to be retrieved (0..vm-1) + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getFloat32(Float32 &floatVal, + const unsigned long pos = 0); + + /** get reference to stored float data + * @param floatVals reference to result variable + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getFloat32Array(Float32 *&floatVals); + + /** get a particular value as a character string. + * The resulting string contains a variable number of digits as created by + * the OFStandard::ftoa() function by default. + * @param stringVal variable in which the result value is stored + * @param pos index of the value in case of multi-valued elements (0..vm-1) + * @param normalize not used + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getOFString(OFString &stringVal, + const unsigned long pos, + OFBool normalize = OFTrue); + + /** set particular element value to given float + * @param floatVal floating point value to be set + * @param pos index of the value to be set (0 = first position) + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition putFloat32(const Float32 floatVal, + const unsigned long pos = 0); + + /** set element value to given float array data + * @param floatVals floating point data to be set + * @param numFloats number of floating point values to be set + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition putFloat32Array(const Float32 *floatVals, + const unsigned long numFloats); + + /** set element value from the given character string. + * The input string is expected to be a backslash separated sequence of + * numeric characters, e.g. "12.3456\1\-123.456\1234.0". + * @param stringVal input character string + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition putString(const char *stringVal); + + /** set element value from the given character string. + * The input string is expected to be a backslash separated sequence of + * numeric characters, e.g. "12.3456\1\-123.456\1234.0". + * The length of the string has to be specified explicitly. The string can, therefore, + * also contain more than one NULL byte. + * @param stringVal input character string + * @param stringLen length of the string (number of characters without the trailing + * NULL byte) + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition putString(const char *stringVal, + const Uint32 stringLen); + + /** check the currently stored element value + * @param autocorrect correct value length if OFTrue + * @return status, EC_Normal if value length is correct, an error code otherwise + */ + virtual OFCondition verify(const OFBool autocorrect = OFFalse); +}; + + +#endif // DCVRFL_H diff --git a/dcmdata/include/dcmtk/dcmdata/dcvris.h b/dcmdata/include/dcmtk/dcmdata/dcvris.h new file mode 100644 index 00000000..3b1c66f8 --- /dev/null +++ b/dcmdata/include/dcmtk/dcmdata/dcvris.h @@ -0,0 +1,129 @@ +/* + * + * Copyright (C) 1994-2013, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Gerd Ehlers, Andreas Barth + * + * Purpose: Interface of class DcmIntegerString + * + */ + +#ifndef DCVRIS_H +#define DCVRIS_H + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/dcmdata/dcbytstr.h" + + +/** a class representing the DICOM value representation 'Integer String' (IS) + */ +class DCMTK_DCMDATA_EXPORT DcmIntegerString + : public DcmByteString +{ + + public: + + /** constructor. + * Create new element from given tag and length. + * @param tag DICOM tag for the new element + * @param len value length for the new element + */ + DcmIntegerString(const DcmTag &tag, + const Uint32 len = 0); + + /** copy constructor + * @param old element to be copied + */ + DcmIntegerString(const DcmIntegerString &old); + + /** destructor + */ + virtual ~DcmIntegerString(); + + /** assignment operator + * @param obj element to be assigned/copied + * @return reference to this object + */ + DcmIntegerString &operator=(const DcmIntegerString &obj); + + /** clone method + * @return deep copy of this object + */ + virtual DcmObject *clone() const + { + return new DcmIntegerString(*this); + } + + /** Virtual object copying. This method can be used for DcmObject + * and derived classes to get a deep copy of an object. Internally + * the assignment operator is called if the given DcmObject parameter + * is of the same type as "this" object instance. If not, an error + * is returned. This function permits copying an object by value + * in a virtual way which therefore is different to just calling the + * assignment operator of DcmElement which could result in slicing + * the object. + * @param rhs - [in] The instance to copy from. Has to be of the same + * class type as "this" object + * @return EC_Normal if copying was successful, error otherwise + */ + virtual OFCondition copyFrom(const DcmObject& rhs); + + /** get element type identifier + * @return type identifier of this class (EVR_IS) + */ + virtual DcmEVR ident() const; + + /** check whether stored value conforms to the VR and to the specified VM + * @param vm value multiplicity (according to the data dictionary) to be checked for. + * (See DcmElement::checkVM() for a list of valid values.) + * @param oldFormat parameter not used for this VR (only for DA, TM) + * @return status of the check, EC_Normal if value is correct, an error code otherwise + */ + virtual OFCondition checkValue(const OFString &vm = "1-n", + const OFBool oldFormat = OFFalse); + + /** get particular integer value + * @param sintVal reference to result variable + * @param pos index of the value to be retrieved (0..vm-1) + * @return status status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getSint32(Sint32 &sintVal, + const unsigned long pos = 0); + + /** get a particular value as a character string + * @param stringVal variable in which the result value is stored + * @param pos index of the value in case of multi-valued elements (0..vm-1) + * @param normalize delete leading and trailing spaces if OFTrue + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getOFString(OFString &stringVal, + const unsigned long pos, + OFBool normalize = OFTrue); + + /* --- static helper functions --- */ + + /** check whether given string value conforms to the VR "IS" (Integer String) + * and to the specified VM. + * @param value string value to be checked (possibly multi-valued) + * @param vm value multiplicity (according to the data dictionary) to be checked for. + * (See DcmElement::checkVM() for a list of valid values.) + * @return status of the check, EC_Normal if value is correct, an error code otherwise + */ + static OFCondition checkStringValue(const OFString &value, + const OFString &vm = "1-n"); +}; + + +#endif // DCVRIS_H diff --git a/dcmdata/include/dcmtk/dcmdata/dcvrlo.h b/dcmdata/include/dcmtk/dcmdata/dcvrlo.h new file mode 100644 index 00000000..e7877c91 --- /dev/null +++ b/dcmdata/include/dcmtk/dcmdata/dcvrlo.h @@ -0,0 +1,125 @@ +/* + * + * Copyright (C) 1994-2013, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Gerd Ehlers, Andreas Barth + * + * Purpose: Interface of class DcmLongString + * + */ + + +#ifndef DCVRLO_H +#define DCVRLO_H + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/dcmdata/dcchrstr.h" + + +/** a class representing the DICOM value representation 'Long String' (LO) + */ +class DCMTK_DCMDATA_EXPORT DcmLongString + : public DcmCharString +{ + + public: + + /** constructor. + * Create new element from given tag and length. + * @param tag DICOM tag for the new element + * @param len value length for the new element + */ + DcmLongString(const DcmTag &tag, + const Uint32 len = 0); + + /** copy constructor + * @param old element to be copied + */ + DcmLongString(const DcmLongString &old); + + /** destructor + */ + virtual ~DcmLongString(); + + /** assignment operator + * @param obj element to be assigned/copied + * @return reference to this object + */ + DcmLongString &operator=(const DcmLongString &obj); + + /** clone method + * @return deep copy of this object + */ + virtual DcmObject *clone() const + { + return new DcmLongString(*this); + } + + /** Virtual object copying. This method can be used for DcmObject + * and derived classes to get a deep copy of an object. Internally + * the assignment operator is called if the given DcmObject parameter + * is of the same type as "this" object instance. If not, an error + * is returned. This function permits copying an object by value + * in a virtual way which therefore is different to just calling the + * assignment operator of DcmElement which could result in slicing + * the object. + * @param rhs - [in] The instance to copy from. Has to be of the same + * class type as "this" object + * @return EC_Normal if copying was successful, error otherwise + */ + virtual OFCondition copyFrom(const DcmObject& rhs); + + /** get element type identifier + * @return type identifier of this class (EVR_LO) + */ + virtual DcmEVR ident() const; + + /** check whether stored value conforms to the VR and to the specified VM + * @param vm value multiplicity (according to the data dictionary) to be checked for. + * (See DcmElement::checkVM() for a list of valid values.) + * @param oldFormat parameter not used for this VR (only for DA, TM) + * @return status of the check, EC_Normal if value is correct, an error code otherwise + */ + virtual OFCondition checkValue(const OFString &vm = "1-n", + const OFBool oldFormat = OFFalse); + + /** get a copy of a particular string component + * @param stringVal variable in which the result value is stored + * @param pos index of the value in case of multi-valued elements (0..vm-1) + * @param normalize delete leading and trailing spaces if OFTrue + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getOFString(OFString &stringVal, + const unsigned long pos, + OFBool normalize = OFTrue); + + /* --- static helper functions --- */ + + /** check whether given string value conforms to the VR "LO" (Long String) + * and to the specified VM. + * @param value string value to be checked (possibly multi-valued) + * @param vm value multiplicity (according to the data dictionary) to be checked for. + * (See DcmElement::checkVM() for a list of valid values.) + * @param charset character set (according to the value of the SpecificCharacterSet + * element) to be used for checking the string value. The default is ASCII (7-bit). + * @return status of the check, EC_Normal if value is correct, an error code otherwise + */ + static OFCondition checkStringValue(const OFString &value, + const OFString &vm = "1-n", + const OFString &charset = ""); +}; + + +#endif // DCVRLO_H diff --git a/dcmdata/include/dcmtk/dcmdata/dcvrlt.h b/dcmdata/include/dcmtk/dcmdata/dcvrlt.h new file mode 100644 index 00000000..108c634c --- /dev/null +++ b/dcmdata/include/dcmtk/dcmdata/dcvrlt.h @@ -0,0 +1,133 @@ +/* + * + * Copyright (C) 1994-2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Gerd Ehlers, Andreas Barth + * + * Purpose: Interface of class DcmLongText + * + */ + +#ifndef DCVRLT_H +#define DCVRLT_H + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/dcmdata/dcchrstr.h" + + +/** a class representing the DICOM value representation 'Long Text' (LT) + */ +class DCMTK_DCMDATA_EXPORT DcmLongText + : public DcmCharString +{ + public: + + /** constructor. + * Create new element from given tag and length. + * @param tag DICOM tag for the new element + * @param len value length for the new element + */ + DcmLongText(const DcmTag &tag, + const Uint32 len = 0); + + /** copy constructor + * @param old element to be copied + */ + DcmLongText(const DcmLongText &old); + + /** destructor + */ + virtual ~DcmLongText(); + + /** assignment operator + * @param obj element to be assigned/copied + * @return reference to this object + */ + DcmLongText &operator=(const DcmLongText &obj); + + /** clone method + * @return deep copy of this object + */ + virtual DcmObject *clone() const + { + return new DcmLongText(*this); + } + + /** Virtual object copying. This method can be used for DcmObject + * and derived classes to get a deep copy of an object. Internally + * the assignment operator is called if the given DcmObject parameter + * is of the same type as "this" object instance. If not, an error + * is returned. This function permits copying an object by value + * in a virtual way which therefore is different to just calling the + * assignment operator of DcmElement which could result in slicing + * the object. + * @param rhs - [in] The instance to copy from. Has to be of the same + * class type as "this" object + * @return EC_Normal if copying was successful, error otherwise + */ + virtual OFCondition copyFrom(const DcmObject& rhs); + + /** get element type identifier + * @return type identifier of this class (EVR_LT) + */ + virtual DcmEVR ident() const; + + /** check whether stored value conforms to the VR and to the specified VM + * @param vm parameter not used for this VR + * @param oldFormat parameter not used for this VR (only for DA, TM) + * @return status of the check, EC_Normal if value is correct, an error code otherwise + */ + virtual OFCondition checkValue(const OFString &vm = "", + const OFBool oldFormat = OFFalse); + + /** get the value multiplicity. + * Since the backslash "\" is not regarded as a separator the value + * multiplicity is always 1. + * @return value multiplicity of the currently stored value + */ + virtual unsigned long getVM(); + + /** get a copy of a particular string component + * @param stringVal variable in which the result value is stored + * @param pos index of the value in case of multi-valued elements (0..vm-1) + * @param normalize delete leading and trailing spaces if OFTrue + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getOFString(OFString &stringVal, + const unsigned long pos, + OFBool normalize = OFTrue); + + /** get the string value (all components) + * @param stringVal string variable in which the result value is stored + * @param normalize remove trailing spaces if OFTrue + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getOFStringArray(OFString &stringVal, + OFBool normalize = OFTrue); + + /* --- static helper functions --- */ + + /** check whether given string value conforms to the VR "LT" (Long Text) + * @param value string value to be checked + * @param charset character set (according to the value of the SpecificCharacterSet + * element) to be used for checking the string value. The default is ASCII (7-bit). + * @return status of the check, EC_Normal if value is correct, an error code otherwise + */ + static OFCondition checkStringValue(const OFString &value, + const OFString &charset = ""); +}; + + +#endif // DCVRLT_H diff --git a/dcmdata/include/dcmtk/dcmdata/dcvrobow.h b/dcmdata/include/dcmtk/dcmdata/dcvrobow.h new file mode 100644 index 00000000..379dec52 --- /dev/null +++ b/dcmdata/include/dcmtk/dcmdata/dcvrobow.h @@ -0,0 +1,345 @@ +/* + * + * Copyright (C) 1994-2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Gerd Ehlers + * + * Purpose: Interface of class DcmOtherByteOtherWord + * + */ + + +#ifndef DCVROBOW_H +#define DCVROBOW_H + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ +#include "dcmtk/dcmdata/dcelem.h" + + +/** a class representing the DICOM value representations 'Other Byte String' (OB) + * and 'Other Word String' (OW) + */ +class DCMTK_DCMDATA_EXPORT DcmOtherByteOtherWord + : public DcmElement +{ + + public: + + /** constructor. + * Create new element from given tag and length. + * @param tag DICOM tag for the new element + * @param len value length for the new element + */ + DcmOtherByteOtherWord(const DcmTag &tag, + const Uint32 len = 0); + + /** copy constructor + * @param old element to be copied + */ + DcmOtherByteOtherWord(const DcmOtherByteOtherWord &old); + + /** comparison operator that compares the normalized value of this object + * with a given object of the same type. The tag of the element is also + * considered as the first component that is compared, followed by the + * object types (VR, i.e. DCMTK'S EVR) and the comparison of all value + * components of the object, preferrably in the order declared in the + * object (if applicable). + * @param rhs the right hand side of the comparison + * @return 0 if the object values are equal. + * -1 if either the value of the first component that does not match + * is lower in this object than in rhs, or all compared components match + * but this object has fewer components than rhs. Also returned if rhs + * cannot be casted to this object type. + * 1 if either the value of the first component that does not match + * is greater in this object than in rhs object, or all compared + * components match but the this component is longer. + */ + virtual int compare(const DcmElement& rhs) const; + + /** destructor + */ + virtual ~DcmOtherByteOtherWord(); + + /** assignment operator + * @param obj element to be assigned/copied + * @return reference to this object + */ + DcmOtherByteOtherWord &operator=(const DcmOtherByteOtherWord &obj); + + /** clone method + * @return deep copy of this object + */ + virtual DcmObject *clone() const + { + return new DcmOtherByteOtherWord(*this); + } + + /** Virtual object copying. This method can be used for DcmObject + * and derived classes to get a deep copy of an object. Internally + * the assignment operator is called if the given DcmObject parameter + * is of the same type as "this" object instance. If not, an error + * is returned. This function permits copying an object by value + * in a virtual way which therefore is different to just calling the + * assignment operator of DcmElement which could result in slicing + * the object. + * @param rhs - [in] The instance to copy from. Has to be of the same + * class type as "this" object + * @return EC_Normal if copying was successful, error otherwise + */ + virtual OFCondition copyFrom(const DcmObject& rhs); + + /** get element type identifier + * @return type identifier of this class + */ + virtual DcmEVR ident() const; + + /** check whether stored value conforms to the VR and to the specified VM + * @param vm parameter not used for this VR + * @param oldFormat parameter not used for this VR (only for DA, TM) + * @return always returns EC_Normal, i.e. currently no checks are performed + */ + virtual OFCondition checkValue(const OFString &vm = "", + const OFBool oldFormat = OFFalse); + + /** get value multiplicity + * @return always returns 1 (according to the DICOM standard) + */ + virtual unsigned long getVM(); + + /** set/change the current value representation + * @param vr new value representation to be set. All VRs except for OW (Other + * Word String) are treated as 8 bit data (OB). This is particularily useful + * for unknown (UN) or unsupported VRs. + * @return status status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setVR(DcmEVR vr); + + /** print the current value to a stream. + * The output format of the binary value is a backslash separated sequence of + * 2- or 4-digit hex numbers, e.g. "00\01\dd" or "0000\7777\aaaa\ffff". + * @param out output stream + * @param flags optional flag used to customize the output (see DCMTypes::PF_xxx) + * @param level current level of nested items. Used for indentation. + * @param pixelFileName not used + * @param pixelCounter not used + */ + virtual void print(STD_NAMESPACE ostream&out, + const size_t flags = 0, + const int level = 0, + const char *pixelFileName = NULL, + size_t *pixelCounter = NULL); + + /** check whether the transfer syntax can be changed as specified + * @param newXfer transfer syntax to be checked + * @param oldXfer not used + * @return OFTrue if transfer syntax can be changed to the new one, OFFalse otherwise + */ + virtual OFBool canWriteXfer(const E_TransferSyntax newXfer, + const E_TransferSyntax oldXfer); + + /** write object to a stream + * @param outStream DICOM output stream + * @param oxfer output transfer syntax + * @param enctype encoding types (undefined or explicit length) + * @param wcache pointer to write cache object, may be NULL + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition write(DcmOutputStream &outStream, + const E_TransferSyntax oxfer, + const E_EncodingType enctype, + DcmWriteCache *wcache); + + /** write object in XML format to a stream + * @param out output stream to which the XML document is written + * @param flags optional flag used to customize the output (see DCMTypes::XF_xxx) + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition writeXML(STD_NAMESPACE ostream&out, + const size_t flags = 0); + + /** special write method for creation of digital signatures + * @param outStream DICOM output stream + * @param oxfer output transfer syntax + * @param enctype encoding types (undefined or explicit length) + * @param wcache pointer to write cache object, may be NULL + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition writeSignatureFormat(DcmOutputStream &outStream, + const E_TransferSyntax oxfer, + const E_EncodingType enctype, + DcmWriteCache *wcache); + + /** get particular 8 bit value. + * This method is only applicable to non-OW data, e.g. OB. + * @param byteVal reference to result variable (cleared in case of error) + * @param pos index of the value to be retrieved (0..vm-1) + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getUint8(Uint8 &byteVal, + const unsigned long pos = 0); + + /** get particular 16 bit value. + * This method is only applicable to OW data. + * @param wordVal reference to result variable (cleared in case of error) + * @param pos index of the value to be retrieved (0..vm-1) + * @return status status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getUint16(Uint16 &wordVal, + const unsigned long pos = 0); + + /** get reference to stored 8 bit data. + * This method is only applicable to non-OW data, e.g. OB. + * @param byteVals reference to result variable + * @return status status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getUint8Array(Uint8 *&byteVals); + + /** get reference to stored 16 bit data. + * This method is only applicable to OW data. + * @param wordVals reference to result variable + * @return status status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getUint16Array(Uint16 *&wordVals); + + /** get a particular value as a character string. + * The numeric value is converted to hex mode, i.e. an 8 bit value is + * represented by 2 characters (00..ff) and a 16 bit value by 4 characters + * (0000..ffff). + * @param stringVal variable in which the result value is stored + * @param pos index of the value in case of multi-valued elements (0..vm-1) + * @param normalize not used + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getOFString(OFString &stringVal, + const unsigned long pos, + OFBool normalize = OFTrue); + + /** get element value as a character string. + * The numeric values are converted to hex mode, i.e. an 8 bit value is + * represented by 2 characters (00..ff) and a 16 bit value by 4 characters + * (0000..ffff). + * In case of VM > 1 the individual values are separated by a backslash ('\'). + * @param stringVal variable in which the result value is stored + * @param normalize not used + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getOFStringArray(OFString &stringVal, + OFBool normalize = OFTrue); + + /** set element value to given 8 bit data. + * This method is only applicable to non-OW data, e.g. OB. + * @param byteValue 8 bit data to be set (copied) + * @param numBytes number of bytes (8 bit) to be set + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition putUint8Array(const Uint8 *byteValue, + const unsigned long numBytes); + + /** set element value to given 16 bit data. + * This method is only applicable to OW data. + * @param wordValue 16 bit data to be set (copied) + * @param numWords number of words (16 bit) to be set. Local byte-ordering + * expected. + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition putUint16Array(const Uint16 *wordValue, + const unsigned long numWords); + + /** create an empty Uint8 array of given number of bytes and set it. + * All array elements are initialized with a value of 0 (using 'memzero'). + * This method is only applicable to non-OW data, e.g. OB. + * @param numBytes number of bytes (8 bit) to be created + * @param bytes stores the pointer to the resulting buffer + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition createUint8Array(const Uint32 numBytes, + Uint8 *&bytes); + + /** create an empty Uint16 array of given number of words and set it. + * All array elements are initialized with a value of 0 (using 'memzero'). + * This method is only applicable to OW data. + * @param numWords number of words (16 bit) to be created + * @param words stores the pointer to the resulting buffer + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition createUint16Array(const Uint32 numWords, + Uint16 *&words); + + /** set element value from the given character string. + * The input string is expected to have the same format as described for + * 'getOFStringArray()' above, i.e. a backslash separated sequence of + * hexa-decimal numbers. + * @param stringVal input character string + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition putString(const char *stringVal); + + /** set element value from the given character string. + * The input string is expected to have the same format as described for + * 'getOFStringArray()' above, i.e. a backslash separated sequence of + * hexa-decimal numbers. + * The length of the string has to be specified explicitly. The string can, therefore, + * also contain more than one NULL byte. + * @param stringVal input character string + * @param stringLen length of the string (number of characters without the + * trailing NULL byte) + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition putString(const char *stringVal, + const Uint32 stringLen); + + /** check the currently stored element value + * @param autocorrect correct value padding (even length) if OFTrue + * @return status, EC_Normal if value length is correct, an error code otherwise + */ + virtual OFCondition verify(const OFBool autocorrect = OFFalse); + + + protected: + + /** method is called after the element value has been loaded. + * Can be used to correct the value before it is used for the first time. + */ + virtual void postLoadValue(); + + /** align the element value to an even length (padding) + * @return status, EC_Normal if successful, an error code otherwise + */ + OFCondition alignValue(); + + /** print pixel data and optionally write it to a binary file. + * Optional pixel data file is always written in little endian byte-ordering. + * @param out output stream + * @param flags optional flag used to customize the output (see DCMTypes::PF_xxx) + * @param level current level of nested items. Used for indentation. + * @param pixelFileName optional filename used to write the raw pixel data file + * @param pixelCounter optional counter used for automatic pixel data filename creation + */ + void printPixel(STD_NAMESPACE ostream&out, + const size_t flags, + const int level, + const char *pixelFileName, + size_t *pixelCounter); + +private: + + /** this flag is used during write operations and indicates that compact() should be + * called once the write operation finishes. + */ + OFBool compactAfterTransfer; + +}; + + +#endif // DCVROBOW_H diff --git a/dcmdata/include/dcmtk/dcmdata/dcvrod.h b/dcmdata/include/dcmtk/dcmdata/dcvrod.h new file mode 100644 index 00000000..a135e318 --- /dev/null +++ b/dcmdata/include/dcmtk/dcmdata/dcvrod.h @@ -0,0 +1,112 @@ +/* + * + * Copyright (C) 2013, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Joerg Riesmeier + * + * Purpose: Interface of class DcmOtherDouble + * + */ + + +#ifndef DCVROD_H +#define DCVROD_H + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/dcmdata/dcvrfd.h" + + +/** a class representing the DICOM value representation 'Other Double String' (OD) + */ +class DCMTK_DCMDATA_EXPORT DcmOtherDouble + : public DcmFloatingPointDouble +{ + + public: + + /** constructor. + * Create new element from given tag and length. + * @param tag DICOM tag for the new element + * @param len value length for the new element + */ + DcmOtherDouble(const DcmTag &tag, + const Uint32 len = 0); + + /** copy constructor + * @param old element to be copied + */ + DcmOtherDouble(const DcmOtherDouble &old); + + /** destructor + */ + virtual ~DcmOtherDouble(); + + /** assignment operator + * @param obj element to be assigned/copied + * @return reference to this object + */ + DcmOtherDouble &operator=(const DcmOtherDouble &obj); + + /** clone method + * @return deep copy of this object + */ + virtual DcmObject *clone() const + { + return new DcmOtherDouble(*this); + } + + /** Virtual object copying. This method can be used for DcmObject + * and derived classes to get a deep copy of an object. Internally + * the assignment operator is called if the given DcmObject parameter + * is of the same type as "this" object instance. If not, an error + * is returned. This function permits copying an object by value + * in a virtual way which therefore is different to just calling the + * assignment operator of DcmElement which could result in slicing + * the object. + * @param rhs - [in] The instance to copy from. Has to be of the same + * class type as "this" object + * @return EC_Normal if copying was successful, error otherwise + */ + virtual OFCondition copyFrom(const DcmObject& rhs); + + /** get element type identifier + * @return type identifier of this class (EVR_OD) + */ + virtual DcmEVR ident() const; + + /** check whether stored value conforms to the VR and to the specified VM + * @param vm parameter not used for this VR + * @param oldFormat parameter not used for this VR (only for DA, TM) + * @return always returns EC_Normal, i.e. currently no checks are performed + */ + virtual OFCondition checkValue(const OFString &vm = "", + const OFBool oldFormat = OFFalse); + + /** get value multiplicity + * @return always returns 1 (according to the DICOM standard) + */ + virtual unsigned long getVM(); + + /** write object in XML format to a stream + * @param out output stream to which the XML document is written + * @param flags optional flag used to customize the output (see DCMTypes::XF_xxx) + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition writeXML(STD_NAMESPACE ostream&out, + const size_t flags = 0); +}; + + +#endif // DCVROD_H diff --git a/dcmdata/include/dcmtk/dcmdata/dcvrof.h b/dcmdata/include/dcmtk/dcmdata/dcvrof.h new file mode 100644 index 00000000..e60df441 --- /dev/null +++ b/dcmdata/include/dcmtk/dcmdata/dcvrof.h @@ -0,0 +1,112 @@ +/* + * + * Copyright (C) 2002-2013, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Joerg Riesmeier + * + * Purpose: Interface of class DcmOtherFloat + * + */ + + +#ifndef DCVROF_H +#define DCVROF_H + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/dcmdata/dcvrfl.h" + + +/** a class representing the DICOM value representation 'Other Float String' (OF) + */ +class DCMTK_DCMDATA_EXPORT DcmOtherFloat + : public DcmFloatingPointSingle +{ + + public: + + /** constructor. + * Create new element from given tag and length. + * @param tag DICOM tag for the new element + * @param len value length for the new element + */ + DcmOtherFloat(const DcmTag &tag, + const Uint32 len = 0); + + /** copy constructor + * @param old element to be copied + */ + DcmOtherFloat(const DcmOtherFloat &old); + + /** destructor + */ + virtual ~DcmOtherFloat(); + + /** assignment operator + * @param obj element to be assigned/copied + * @return reference to this object + */ + DcmOtherFloat &operator=(const DcmOtherFloat &obj); + + /** clone method + * @return deep copy of this object + */ + virtual DcmObject *clone() const + { + return new DcmOtherFloat(*this); + } + + /** Virtual object copying. This method can be used for DcmObject + * and derived classes to get a deep copy of an object. Internally + * the assignment operator is called if the given DcmObject parameter + * is of the same type as "this" object instance. If not, an error + * is returned. This function permits copying an object by value + * in a virtual way which therefore is different to just calling the + * assignment operator of DcmElement which could result in slicing + * the object. + * @param rhs - [in] The instance to copy from. Has to be of the same + * class type as "this" object + * @return EC_Normal if copying was successful, error otherwise + */ + virtual OFCondition copyFrom(const DcmObject& rhs); + + /** get element type identifier + * @return type identifier of this class (EVR_OF) + */ + virtual DcmEVR ident() const; + + /** check whether stored value conforms to the VR and to the specified VM + * @param vm parameter not used for this VR + * @param oldFormat parameter not used for this VR (only for DA, TM) + * @return always returns EC_Normal, i.e. currently no checks are performed + */ + virtual OFCondition checkValue(const OFString &vm = "", + const OFBool oldFormat = OFFalse); + + /** get value multiplicity + * @return always returns 1 (according to the DICOM standard) + */ + virtual unsigned long getVM(); + + /** write object in XML format to a stream + * @param out output stream to which the XML document is written + * @param flags optional flag used to customize the output (see DCMTypes::XF_xxx) + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition writeXML(STD_NAMESPACE ostream&out, + const size_t flags = 0); +}; + + +#endif // DCVROF_H diff --git a/dcmdata/include/dcmtk/dcmdata/dcvrpn.h b/dcmdata/include/dcmtk/dcmdata/dcvrpn.h new file mode 100644 index 00000000..ad42d2c0 --- /dev/null +++ b/dcmdata/include/dcmtk/dcmdata/dcvrpn.h @@ -0,0 +1,293 @@ +/* + * + * Copyright (C) 1994-2013, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Gerd Ehlers, Joerg Riesmeier + * + * Purpose: Interface of class DcmPersonName + * + */ + + +#ifndef DCVRPN_H +#define DCVRPN_H + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/dcmdata/dcchrstr.h" + + +/** a class representing the DICOM value representation 'Person Name' (PN) + */ +class DCMTK_DCMDATA_EXPORT DcmPersonName + : public DcmCharString +{ + + public: + + /** constructor. + * Create new element from given tag and length. + * @param tag DICOM tag for the new element + * @param len value length for the new element + */ + DcmPersonName(const DcmTag &tag, + const Uint32 len = 0); + + /** copy constructor + * @param old element to be copied + */ + DcmPersonName(const DcmPersonName &old); + + /** destructor + */ + virtual ~DcmPersonName(); + + /** assignment operator + * @param obj element to be assigned/copied + * @return reference to this object + */ + DcmPersonName &operator=(const DcmPersonName &obj); + + /** clone method + * @return deep copy of this object + */ + virtual DcmObject *clone() const + { + return new DcmPersonName(*this); + } + + /** Virtual object copying. This method can be used for DcmObject + * and derived classes to get a deep copy of an object. Internally + * the assignment operator is called if the given DcmObject parameter + * is of the same type as "this" object instance. If not, an error + * is returned. This function permits copying an object by value + * in a virtual way which therefore is different to just calling the + * assignment operator of DcmElement which could result in slicing + * the object. + * @param rhs - [in] The instance to copy from. Has to be of the same + * class type as "this" object + * @return EC_Normal if copying was successful, error otherwise + */ + virtual OFCondition copyFrom(const DcmObject& rhs); + + /** get element type identifier + * @return type identifier of this class (EVR_PN) + */ + virtual DcmEVR ident() const; + + /** check whether stored value conforms to the VR and to the specified VM + * @param vm value multiplicity (according to the data dictionary) to be checked for. + * (See DcmElement::checkVM() for a list of valid values.) + * @param oldFormat parameter not used for this VR (only for DA, TM) + * @return status of the check, EC_Normal if value is correct, an error code otherwise + */ + virtual OFCondition checkValue(const OFString &vm = "1-n", + const OFBool oldFormat = OFFalse); + + /** get a copy of a particular string component + * @param stringVal variable in which the result value is stored + * @param pos index of the value in case of multi-valued elements (0..vm-1) + * @param normalize delete leading and trailing spaces if OFTrue + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getOFString(OFString &stringVal, + const unsigned long pos, + OFBool normalize = OFTrue); + + /** get name components from the element value. + * The DICOM PN consists of up to three component groups separated by a "=". The + * supported format is "[CG0[=CG1[=CG2]]]" where the brackets enclose optional + * parts and CG0 is an alphabetic representation, CG1 an ideographic representation, + * and CG2 a phonetic representation of the name. + * Each component group may consist of up to five components separated by a "^". + * The format is "[lastName[^firstName[^middleName[^namePrefix[^nameSuffix]]]]"; + * each component group and each component might be empty. + * If this function fails the result variables are cleared automatically. If the + * format is valid but does not comply with the above described scheme ("=" and "^") + * the full person name is returned in the 'lastName' variable. + * @param lastName reference to string variable where the "last name" is stored + * @param firstName reference to string variable where the "first name" is stored + * @param middleName reference to string variable where the "middle name" is stored + * @param namePrefix reference to string variable where the "name prefix" is stored + * @param nameSuffix reference to string variable where the "name suffix" is stored + * @param pos index of the element component in case of value multiplicity (0..vm-1) + * @param componentGroup index of the component group (0..2) to be used, see above + * @return EC_Normal upon success, an error code otherwise + */ + OFCondition getNameComponents(OFString &lastName, + OFString &firstName, + OFString &middleName, + OFString &namePrefix, + OFString &nameSuffix, + const unsigned long pos = 0, + const unsigned int componentGroup = 0); + + /** get current element value as a formatted/readable name. + * The current element value is expected to be in DICOM PN format as described above. + * The output format is "[namePrefix][ firstName][ middleName][ lastName][, nameSuffix]"; + * the delimiters (" " and ", ") are only inserted if required. + * If this function fails the result variable 'formattedName' is cleared automatically. + * @param formattedName reference to string variable where the result is stored + * @param pos index of the element component in case of value multiplicity (0..vm-1) + * @param componentGroup index of the component group (0..2) to be used, see above + * @return EC_Normal upon success, an error code otherwise + */ + OFCondition getFormattedName(OFString &formattedName, + const unsigned long pos = 0, + const unsigned int componentGroup = 0); + + + /** put element value from specified name components. + * The stored format is "[lastName[^firstName[^middleName[^namePrefix[^nameSuffix]]]]]", + * i.e. a DICOM Person Name (PN). Component groups are not (yet) supported. + * If this function fails the currently stored value is not modified. + * @param lastName reference to string variable where the "last name" is stored + * @param firstName reference to string variable where the "first name" is stored + * @param middleName reference to string variable where the "middle name" is stored + * @param namePrefix reference to string variable where the "name prefix" is stored + * @param nameSuffix reference to string variable where the "name suffix" is stored + * @return EC_Normal upon success, an error code otherwise + */ + OFCondition putNameComponents(const OFString &lastName, + const OFString &firstName, + const OFString &middleName, + const OFString &namePrefix, + const OFString &nameSuffix); + + /** write object in XML format + * @param out output stream to which the XML document is written + * @param flags optional flag used to customize the output (see DCMTypes::XF_xxx) + * @return status, EC_Normal if successful, an error code otherwise + */ + OFCondition writeXML(STD_NAMESPACE ostream &out, + const size_t flags = 0); + + /* --- static helper functions --- */ + + /** get name components from specified DICOM person name. + * The DICOM PN consists of up to three component groups separated by a "=". The + * supported format is "[CG0[=CG1[=CG2]]]" where the brackets enclose optional + * parts and CG0 is an alphabetic representation, CG1 an ideographic representation, + * and CG2 a phonetic representation of the name. + * Each component group may consist of up to five components separated by a "^". + * The format is "[lastName[^firstName[^middleName[^namePrefix[^nameSuffix]]]]"; + * each component group and each component might be empty. + * If this function fails the result variables are cleared automatically. If the + * format is valid but does not comply with the above described scheme ("=" and "^") + * the full person name is returned in the 'lastName' variable. + * @param dicomName string value in DICOM PN format to be split into components + * @param lastName reference to string variable where the "last name" is stored + * @param firstName reference to string variable where the "first name" is stored + * @param middleName reference to string variable where the "middle name" is stored + * @param namePrefix reference to string variable where the "name prefix" is stored + * @param nameSuffix reference to string variable where the "name suffix" is stored + * @param componentGroup index of the component group (0..2) to be used, see above + * @return EC_Normal upon success, an error code otherwise + */ + static OFCondition getNameComponentsFromString(const OFString &dicomName, + OFString &lastName, + OFString &firstName, + OFString &middleName, + OFString &namePrefix, + OFString &nameSuffix, + const unsigned int componentGroup = 0); + + /** get single component group from specified DICOM person name. + * The DICOM PN consists of up to three component groups separated by a "=". The + * supported format is "[CG0[=CG1[=CG2]]]" where the brackets enclose optional + * parts and CG0 is an alphabetic representation, CG1 an ideographic representation, + * and CG2 a phonetic representation of the name. Each component group might be empty. + * The returned component group will contain component delimiters ("^") as they are + * stored within the very component group, i.e. superfluous component delimiters are + * not removed. + * @param allCmpGroups string value in DICOM PN format to component group from + * @param groupNo index of the component group (0..2) to be extracted + * @param cmpGroup reference to string variable where selected component group shall be + * stored + * @return EC_Normal upon success, an error code otherwise. Especially, if a component + * group exists (always for group 0, for group 1 and 2 depending on whether + * corresponding "=" is present) and is empty, EC_Normal is returned. + */ + static OFCondition getComponentGroup(const OFString &allCmpGroups, + const unsigned int groupNo, + OFString &cmpGroup); + + /** get specified DICOM person name as a formatted/readable name. + * The specified 'dicomName' is expected to be in DICOM PN format as described above. + * The output format is "[namePrefix][ firstName][ middleName][ lastName][, nameSuffix]"; + * the delimiters (" " and ", ") are only inserted if required. + * If this function fails the result variable 'formattedName' is cleared automatically. + * @param dicomName string value in DICOM PN format to be converted to readable format + * @param formattedName reference to string variable where the result is stored + * @param componentGroup index of the component group (0..2) to be used, see above + * @return EC_Normal upon success, an error code otherwise + */ + static OFCondition getFormattedNameFromString(const OFString &dicomName, + OFString &formattedName, + const unsigned int componentGroup = 0); + + /** get formatted/readable name from specified name components. + * The output format is "[namePrefix][ firstName][ middleName][ lastName][, nameSuffix]"; + * the delimiters (" " and ", ") are only inserted if required. + * If this function fails the result variable 'formattedName' is cleared automatically. + * @param lastName reference to string variable where the "last name" is stored + * @param firstName reference to string variable where the "first name" is stored + * @param middleName reference to string variable where the "middle name" is stored + * @param namePrefix reference to string variable where the "name prefix" is stored + * @param nameSuffix reference to string variable where the "name suffix" is stored + * @param formattedName reference to string variable where the result is stored + * @return always returns EC_Normal + */ + static OFCondition getFormattedNameFromComponents(const OFString &lastName, + const OFString &firstName, + const OFString &middleName, + const OFString &namePrefix, + const OFString &nameSuffix, + OFString &formattedName); + + /** get DICOM Person Name (PN) from specified name components. + * The output format is "[lastName[^firstName[^middleName[^namePrefix[^nameSuffix]]]]]". + * Component groups are not (yet) supported. + * If this function fails the result variable 'dicomName' is cleared automatically. + * @param lastName reference to string variable where the "last name" is stored + * @param firstName reference to string variable where the "first name" is stored + * @param middleName reference to string variable where the "middle name" is stored + * @param namePrefix reference to string variable where the "name prefix" is stored + * @param nameSuffix reference to string variable where the "name suffix" is stored + * @param dicomName reference to string variable where the result is stored + * @return always returns EC_Normal + */ + static OFCondition getStringFromNameComponents(const OFString &lastName, + const OFString &firstName, + const OFString &middleName, + const OFString &namePrefix, + const OFString &nameSuffix, + OFString &dicomName); + + /** check whether given string value conforms to the VR "PN" (Person Name) + * and to the specified VM. + * @param value string value to be checked (possibly multi-valued) + * @param vm value multiplicity (according to the data dictionary) to be checked for. + * (See DcmElement::checkVM() for a list of valid values.) + * @param charset character set (according to the value of the SpecificCharacterSet + * element) to be used for checking the string value. The default is ASCII (7-bit). + * @return status of the check, EC_Normal if value is correct, an error code otherwise + */ + static OFCondition checkStringValue(const OFString &value, + const OFString &vm = "1-n", + const OFString &charset = ""); +}; + + +#endif // DCVRPN_H diff --git a/dcmdata/include/dcmtk/dcmdata/dcvrpobw.h b/dcmdata/include/dcmtk/dcmdata/dcvrpobw.h new file mode 100644 index 00000000..503c7e4c --- /dev/null +++ b/dcmdata/include/dcmtk/dcmdata/dcvrpobw.h @@ -0,0 +1,225 @@ +/* + * + * Copyright (C) 1994-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Andreas Barth + * + * Purpose: + * Interface of class DcmPolymorphOBOW for Tags that can change their VR + * between OB and OW (e.g. Tag PixelData, OverlayData). This class shall + * not be used directly in applications. No identification exists. + * + */ + +#ifndef DCVRPOBW_H +#define DCVRPOBW_H + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ +#include "dcmtk/dcmdata/dcvrobow.h" + +/** a class representing DICOM elements (such as uncompressed pixel data) that can + * be interpreted either as OB or as OW, i.e. are polymorph. + */ +class DCMTK_DCMDATA_EXPORT DcmPolymorphOBOW : public DcmOtherByteOtherWord +{ +public: + + /** constructor + * @param tag attribute tag + * @param len length of the attribute value + */ + DcmPolymorphOBOW( + const DcmTag & tag, + const Uint32 len = 0); + + /// copy constructor + DcmPolymorphOBOW( + const DcmPolymorphOBOW & old); + + /// destructor + virtual ~DcmPolymorphOBOW(); + + /** copy assignment operator + * @param obj element to be copied + */ + DcmPolymorphOBOW &operator=( + const DcmPolymorphOBOW &obj); + + /** clone method + * @return deep copy of this object + */ + virtual DcmObject *clone() const + { + return new DcmPolymorphOBOW(*this); + } + + /** Virtual object copying. This method can be used for DcmObject + * and derived classes to get a deep copy of an object. Internally + * the assignment operator is called if the given DcmObject parameter + * is of the same type as "this" object instance. If not, an error + * is returned. This function permits copying an object by value + * in a virtual way which therefore is different to just calling the + * assignment operator of DcmElement which could result in slicing + * the object. + * @param rhs - [in] The instance to copy from. Has to be of the same + * class type as "this" object + * @return EC_Normal if copying was successful, error otherwise + */ + virtual OFCondition copyFrom(const DcmObject& rhs); + + /** This function reads the data value of an attribute which is + * captured in the input stream and captures this information + * in this. If not all information for an attribute could be + * read from the stream, the function returns EC_StreamNotifyClient. + * Note that if certain conditions are met, this function does + * not actually load the data value but creates and stores an object + * that enables us to load this information later. + * @param inStream The stream which contains the information. + * @param ixfer The transfer syntax which was used to encode + * the information in inStream. + * @param glenc Encoding type for group length; specifies what + * will be done with group length tags. + * @param maxReadLength Maximum read length for reading an attribute value. + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition read( + DcmInputStream & inStream, + const E_TransferSyntax ixfer, + const E_GrpLenEncoding glenc, + const Uint32 maxReadLength); + + /** This function writes this element's value to the outstream which was + * passed. When writing information, the byte ordering (little or big endian) + * of the transfer syntax which was passed will be accounted for. In case the + * outstream does not provide enough space for all bytes of the current + * element's value, only a certain part of the value will be written to the + * stream. This element's transfer state indicates if the all bytes of value + * have already been written to the stream (ERW_ready), if the writing is + * still in progress and more bytes need to be written to the stream + * (ERW_inWork) or if the writing of the bytes of this element's value has not + * even begun yet (ERW_init). The member variable fTransferredBytes indicates + * how many bytes (starting from byte 0) of this element's value have already + * been written to the stream. This function will return EC_Normal, if the + * entire value of this element has been written to the stream, it will return + * EC_StreamNotifyClient, if there is no more space in the buffer and _not_ all + * bytes of this element's value have been written, and it will return some + * other (error) value if there was an error. + * @param outStream The stream the information will be written to. + * @param oxfer The transfer syntax which shall be used. + * @param enctype encoding types (undefined or explicit length) (actually unused) + * @param wcache pointer to write cache object, may be NULL + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition write( + DcmOutputStream &outStream, + const E_TransferSyntax oxfer, + const E_EncodingType enctype, + DcmWriteCache *wcache); + + /** special write method for creation of digital signatures + * @param outStream DICOM output stream + * @param oxfer output transfer syntax + * @param enctype encoding types (undefined or explicit length) + * @param wcache pointer to write cache object, may be NULL + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition writeSignatureFormat( + DcmOutputStream &outStream, + const E_TransferSyntax oxfer, + const E_EncodingType enctype, + DcmWriteCache *wcache); + + /** initialize the transfer state of this object. This method must be called + * before this object is written to a stream or read (parsed) from a stream. + */ + virtual void transferInit(); + + /** finalize the transfer state of this object. This method must be called + * when reading/writing this object from/to a stream has been completed. + */ + virtual void transferEnd(); + + /** get a pointer to the element value of the current element as type string. + * Requires element to be of corresponding VR, otherwise an error is returned. + * This method does not copy, but returns a pointer to the element value, + * which remains under control of this object and is valid only until the next + * read, write or put operation. + * @param val pointer to value returned in this parameter upon success + * @return EC_Normal upon success, an error code otherwise + */ + virtual OFCondition getUint8Array(Uint8 *&val); // for bytes + + /** get a pointer to the element value of the current element as type Uint16. + * Requires element to be of corresponding VR, otherwise an error is returned. + * This method does not copy, but returns a pointer to the element value, + * which remains under control of this object and is valid only until the next + * read, write or put operation. + * @param val pointer to value returned in this parameter upon success + * @return EC_Normal upon success, an error code otherwise + */ + virtual OFCondition getUint16Array(Uint16 *&val); + + /** replace the element value by a copy of the given Uint8 array (which is possibly multi-valued). + * Requires element to be of corresponding VR, otherwise an error is returned. + * @param vals new attribute value + * @param num number of values in array vals + * @return EC_Normal upon success, an error code otherwise + */ + virtual OFCondition putUint8Array(const Uint8 *vals, const unsigned long num); + + /** replace the element value by a copy of the given Uint16 array (which is possibly multi-valued). + * Requires element to be of corresponding VR, otherwise an error is returned. + * @param vals new attribute value + * @param num number of values in array vals + * @return EC_Normal upon success, an error code otherwise + */ + virtual OFCondition putUint16Array(const Uint16 *vals, const unsigned long num); + + /** create an empty Uint8 array of given number of bytes and set it. + * All array elements are initialized with a value of 0 (using 'memzero'). + * This method is only applicable to certain VRs, e.g. OB. + * @param numBytes number of bytes (8 bit) to be created + * @param bytes stores the pointer to the resulting buffer + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition createUint8Array( + const Uint32 numBytes, + Uint8 * & bytes); + + + /** create an empty Uint16 array of given number of words and set it. + * All array elements are initialized with a value of 0 (using 'memzero'). + * This method is only applicable to OW data. + * @param numWords number of words (16 bit) to be created + * @param words stores the pointer to the resulting buffer + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition createUint16Array( + const Uint32 numWords, + Uint16 * & words); + +private: + + /** this flag is used during write operations in Implicit VR Little Endian + * and notes that the VR has temporarily been changed from OB to OW + * at the beginning to the write operation and needs to be changed back once the + * operation has finished. + */ + OFBool changeVR; + + /// the current VR of value field, which can change over time + DcmEVR currentVR; + +}; +#endif diff --git a/dcmdata/include/dcmtk/dcmdata/dcvrsh.h b/dcmdata/include/dcmtk/dcmdata/dcvrsh.h new file mode 100644 index 00000000..a5956fdd --- /dev/null +++ b/dcmdata/include/dcmtk/dcmdata/dcvrsh.h @@ -0,0 +1,125 @@ +/* + * + * Copyright (C) 1994-2013, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Gerd Ehlers + * + * Purpose: Interface of class DcmShortString + * + */ + + +#ifndef DCVRSH_H +#define DCVRSH_H + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/dcmdata/dcchrstr.h" + + +/** a class representing the DICOM value representation 'Short String' (SH) + */ +class DCMTK_DCMDATA_EXPORT DcmShortString + : public DcmCharString +{ + + public: + + /** constructor. + * Create new element from given tag and length. + * @param tag DICOM tag for the new element + * @param len value length for the new element + */ + DcmShortString(const DcmTag &tag, + const Uint32 len = 0); + + /** copy constructor + * @param old element to be copied + */ + DcmShortString(const DcmShortString &old); + + /** destructor + */ + virtual ~DcmShortString(); + + /** assignment operator + * @param obj element to be assigned/copied + * @return reference to this object + */ + DcmShortString &operator=(const DcmShortString &obj); + + /** clone method + * @return deep copy of this object + */ + virtual DcmObject *clone() const + { + return new DcmShortString(*this); + } + + /** Virtual object copying. This method can be used for DcmObject + * and derived classes to get a deep copy of an object. Internally + * the assignment operator is called if the given DcmObject parameter + * is of the same type as "this" object instance. If not, an error + * is returned. This function permits copying an object by value + * in a virtual way which therefore is different to just calling the + * assignment operator of DcmElement which could result in slicing + * the object. + * @param rhs - [in] The instance to copy from. Has to be of the same + * class type as "this" object + * @return EC_Normal if copying was successful, error otherwise + */ + virtual OFCondition copyFrom(const DcmObject& rhs); + + /** get element type identifier + * @return type identifier of this class (EVR_SH) + */ + virtual DcmEVR ident() const; + + /** check whether stored value conforms to the VR and to the specified VM + * @param vm value multiplicity (according to the data dictionary) to be checked for. + * (See DcmElement::checkVM() for a list of valid values.) + * @param oldFormat parameter not used for this VR (only for DA, TM) + * @return status of the check, EC_Normal if value is correct, an error code otherwise + */ + virtual OFCondition checkValue(const OFString &vm = "1-n", + const OFBool oldFormat = OFFalse); + + /** get a copy of a particular string component + * @param stringVal variable in which the result value is stored + * @param pos index of the value in case of multi-valued elements (0..vm-1) + * @param normalize delete leading and trailing spaces if OFTrue + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getOFString(OFString &stringVal, + const unsigned long pos, + OFBool normalize = OFTrue); + + /* --- static helper functions --- */ + + /** check whether given string value conforms to the VR "SH" (Short String) + * and to the specified VM. + * @param value string value to be checked (possibly multi-valued) + * @param vm value multiplicity (according to the data dictionary) to be checked for. + * (See DcmElement::checkVM() for a list of valid values.) + * @param charset character set (according to the value of the SpecificCharacterSet + * element) to be used for checking the string value. The default is ASCII (7-bit). + * @return status of the check, EC_Normal if value is correct, an error code otherwise + */ + static OFCondition checkStringValue(const OFString &value, + const OFString &vm = "1-n", + const OFString &charset = ""); +}; + + +#endif // DCVRSH_H diff --git a/dcmdata/include/dcmtk/dcmdata/dcvrsl.h b/dcmdata/include/dcmtk/dcmdata/dcvrsl.h new file mode 100644 index 00000000..1e102749 --- /dev/null +++ b/dcmdata/include/dcmtk/dcmdata/dcvrsl.h @@ -0,0 +1,205 @@ +/* + * + * Copyright (C) 1994-2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Gerd Ehlers, Andreas Barth + * + * Purpose: Interface of class DcmSignedLong + * + */ + + +#ifndef DCVRSL_H +#define DCVRSL_H + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/dcmdata/dcelem.h" + + +/** a class representing the DICOM value representation 'Signed Long' (SL) + */ +class DCMTK_DCMDATA_EXPORT DcmSignedLong + : public DcmElement +{ + + public: + + /** constructor. + * Create new element from given tag and length. + * @param tag DICOM tag for the new element + * @param len value length for the new element + */ + DcmSignedLong(const DcmTag &tag, + const Uint32 len = 0); + + /** copy constructor + * @param old element to be copied + */ + DcmSignedLong(const DcmSignedLong &old); + + /** destructor + */ + virtual ~DcmSignedLong(); + + /** assignment operator + * @param obj element to be assigned/copied + * @return reference to this object + */ + DcmSignedLong &operator=(const DcmSignedLong &obj); + + /** comparison operator that compares the normalized value of this object + * with a given object of the same type. The tag of the element is also + * considered as the first component that is compared, followed by the + * object types (VR, i.e. DCMTK'S EVR) and the comparison of all value + * components of the object, preferrably in the order declared in the + * object (if applicable). + * @param rhs the right hand side of the comparison + * @return 0 if the object values are equal. + * -1 if either the value of the first component that does not match + * is lower in this object than in rhs, or all compared components match + * but this object has fewer components than rhs. Also returned if rhs + * cannot be casted to this object type. + * 1 if either the value of the first component that does not match + * is greater in this object than in rhs object, or all compared + * components match but the this component is longer. + */ + virtual int compare(const DcmElement& rhs) const; + + /** clone method + * @return deep copy of this object + */ + virtual DcmObject *clone() const + { + return new DcmSignedLong(*this); + } + + /** Virtual object copying. This method can be used for DcmObject + * and derived classes to get a deep copy of an object. Internally + * the assignment operator is called if the given DcmObject parameter + * is of the same type as "this" object instance. If not, an error + * is returned. This function permits copying an object by value + * in a virtual way which therefore is different to just calling the + * assignment operator of DcmElement which could result in slicing + * the object. + * @param rhs - [in] The instance to copy from. Has to be of the same + * class type as "this" object + * @return EC_Normal if copying was successful, error otherwise + */ + virtual OFCondition copyFrom(const DcmObject& rhs); + + /** get element type identifier + * @return type identifier of this class (EVR_SL) + */ + virtual DcmEVR ident() const; + + /** check whether stored value conforms to the VR and to the specified VM + * @param vm value multiplicity (according to the data dictionary) to be checked for. + * (See DcmElement::checkVM() for a list of valid values.) + * @param oldFormat parameter not used for this VR (only for DA, TM) + * @return status of the check, EC_Normal if value is correct, an error code otherwise + */ + virtual OFCondition checkValue(const OFString &vm = "1-n", + const OFBool oldFormat = OFFalse); + + /** get value multiplicity + * @return number of currently stored values + */ + virtual unsigned long getVM(); + + /** print element to a stream. + * The output format of the value is a backslash separated sequence of numbers. + * @param out output stream + * @param flags optional flag used to customize the output (see DCMTypes::PF_xxx) + * @param level current level of nested items. Used for indentation. + * @param pixelFileName not used + * @param pixelCounter not used + */ + virtual void print(STD_NAMESPACE ostream&out, + const size_t flags = 0, + const int level = 0, + const char *pixelFileName = NULL, + size_t *pixelCounter = NULL); + + /** get particular integer value + * @param sintVal reference to result variable (cleared in case of error) + * @param pos index of the value to be retrieved (0..vm-1) + * @return status status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getSint32(Sint32 &sintVal, + const unsigned long pos = 0); + + /** get reference to stored integer data. + * The number of entries can be determined by "getVM()". + * @param sintVals reference to result variable + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getSint32Array(Sint32 *&sintVals); + + /** get particular value as a character string + * @param stringVal variable in which the result value is stored + * @param pos index of the value in case of multi-valued elements (0..vm-1) + * @param normalize not used + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getOFString(OFString &stringVal, + const unsigned long pos, + OFBool normalize = OFTrue); + + /** set particular element value to given integer + * @param sintVal signed integer value to be set + * @param pos index of the value to be set (0 = first position) + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition putSint32(const Sint32 sintVal, + const unsigned long pos = 0); + + /** set element value to given integer array data + * @param sintVals signed integer data to be set + * @param numSints number of integer values to be set + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition putSint32Array(const Sint32 *sintVals, + const unsigned long numSints); + + /** set element value from the given character string. + * The input string is expected to be a backslash separated sequence of + * numeric characters, e.g. "-333\-22\-1\0\1\22\333". + * @param stringVal input character string + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition putString(const char *stringVal); + + /** set element value from the given character string. + * The input string is expected to be a backslash separated sequence of + * numeric characters, e.g. "-333\-22\-1\0\1\22\333". + * The length of the string has to be specified explicitly. The string can, therefore, + * also contain more than one NULL byte. + * @param stringVal input character string + * @param stringLen length of the string (number of characters without the trailing + * NULL byte) + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition putString(const char *stringVal, + const Uint32 stringLen); + + /** check the currently stored element value + * @param autocorrect correct value length if OFTrue + * @return status, EC_Normal if value length is correct, an error code otherwise + */ + virtual OFCondition verify(const OFBool autocorrect = OFFalse); +}; + + +#endif // DCVRSL_H diff --git a/dcmdata/include/dcmtk/dcmdata/dcvrss.h b/dcmdata/include/dcmtk/dcmdata/dcvrss.h new file mode 100644 index 00000000..859446a1 --- /dev/null +++ b/dcmdata/include/dcmtk/dcmdata/dcvrss.h @@ -0,0 +1,205 @@ +/* + * + * Copyright (C) 1994-2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Gerd Ehlers, Andreas Barth + * + * Purpose: Interface of class DcmSignedShort + * + */ + + +#ifndef DCVRSS_H +#define DCVRSS_H + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/dcmdata/dcelem.h" + + +/** a class representing the DICOM value representation 'Signed Short' (SS) + */ +class DCMTK_DCMDATA_EXPORT DcmSignedShort + : public DcmElement +{ + + public: + + /** constructor. + * Create new element from given tag and length. + * @param tag DICOM tag for the new element + * @param len value length for the new element + */ + DcmSignedShort(const DcmTag &tag, + const Uint32 len = 0); + + /** copy constructor + * @param old element to be copied + */ + DcmSignedShort(const DcmSignedShort &old); + + /** destructor + */ + virtual ~DcmSignedShort(); + + /** comparison operator that compares the normalized value of this object + * with a given object of the same type. The tag of the element is also + * considered as the first component that is compared, followed by the + * object types (VR, i.e. DCMTK'S EVR) and the comparison of all value + * components of the object, preferrably in the order declared in the + * object (if applicable). + * @param rhs the right hand side of the comparison + * @return 0 if the object values are equal. + * -1 if either the value of the first component that does not match + * is lower in this object than in rhs, or all compared components match + * but this object has fewer components than rhs. Also returned if rhs + * cannot be casted to this object type. + * 1 if either the value of the first component that does not match + * is greater in this object than in rhs object, or all compared + * components match but the this component is longer. + */ + virtual int compare(const DcmElement& rhs) const; + + /** assignment operator + * @param obj element to be assigned/copied + * @return reference to this object + */ + DcmSignedShort &operator=(const DcmSignedShort &obj); + + /** clone method + * @return deep copy of this object + */ + virtual DcmObject *clone() const + { + return new DcmSignedShort(*this); + } + + /** Virtual object copying. This method can be used for DcmObject + * and derived classes to get a deep copy of an object. Internally + * the assignment operator is called if the given DcmObject parameter + * is of the same type as "this" object instance. If not, an error + * is returned. This function permits copying an object by value + * in a virtual way which therefore is different to just calling the + * assignment operator of DcmElement which could result in slicing + * the object. + * @param rhs - [in] The instance to copy from. Has to be of the same + * class type as "this" object + * @return EC_Normal if copying was successful, error otherwise + */ + virtual OFCondition copyFrom(const DcmObject& rhs); + + /** get element type identifier + * @return type identifier of this class (EVR_SS) + */ + virtual DcmEVR ident() const; + + /** check whether stored value conforms to the VR and to the specified VM + * @param vm value multiplicity (according to the data dictionary) to be checked for. + * (See DcmElement::checkVM() for a list of valid values.) + * @param oldFormat parameter not used for this VR (only for DA, TM) + * @return status of the check, EC_Normal if value is correct, an error code otherwise + */ + virtual OFCondition checkValue(const OFString &vm = "1-n", + const OFBool oldFormat = OFFalse); + + /** get value multiplicity. + * The number of entries can be determined by "getVM()". + * @return number of currently stored values + */ + virtual unsigned long getVM(); + + /** print element to a stream. + * The output format of the value is a backslash separated sequence of numbers. + * @param out output stream + * @param flags optional flag used to customize the output (see DCMTypes::PF_xxx) + * @param level current level of nested items. Used for indentation. + * @param pixelFileName not used + * @param pixelCounter not used + */ + virtual void print(STD_NAMESPACE ostream&out, + const size_t flags = 0, + const int level = 0, + const char *pixelFileName = NULL, + size_t *pixelCounter = NULL); + + /** get particular integer value + * @param sintVal reference to result variable (cleared in case of error) + * @param pos index of the value to be retrieved (0..vm-1) + * @return status status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getSint16(Sint16 &sintVal, + const unsigned long pos = 0); + + /** get reference to stored integer data + * @param sintVals reference to result variable + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getSint16Array(Sint16 *&sintVals); + + /** get particular value as a character string + * @param stringVal variable in which the result value is stored + * @param pos index of the value in case of multi-valued elements (0..vm-1) + * @param normalize not used + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getOFString(OFString &stringVal, + const unsigned long pos, + OFBool normalize = OFTrue); + + /** set particular element value to given integer + * @param sintVal signed integer value to be set + * @param pos index of the value to be set (0 = first position) + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition putSint16(const Sint16 sintVal, + const unsigned long pos = 0); + + /** set element value to given integer array data + * @param sintVals signed integer data to be set + * @param numSints number of integer values to be set + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition putSint16Array(const Sint16 *sintVals, + const unsigned long numSints); + + /** set element value from the given character string. + * The input string is expected to be a backslash separated sequence of + * numeric characters, e.g. "-333\-22\-1\0\1\22\333". + * @param stringVal input character string + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition putString(const char *stringVal); + + /** set element value from the given character string. + * The input string is expected to be a backslash separated sequence of + * numeric characters, e.g. "-333\-22\-1\0\1\22\333". + * The length of the string has to be specified explicitly. The string can, therefore, + * also contain more than one NULL byte. + * @param stringVal input character string + * @param stringLen length of the string (number of characters without the trailing + * NULL byte) + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition putString(const char *stringVal, + const Uint32 stringLen); + + /** check the currently stored element value + * @param autocorrect correct value length if OFTrue + * @return status, EC_Normal if value length is correct, an error code otherwise + */ + virtual OFCondition verify(const OFBool autocorrect = OFFalse); +}; + + +#endif // DCVRSS_H diff --git a/dcmdata/include/dcmtk/dcmdata/dcvrst.h b/dcmdata/include/dcmtk/dcmdata/dcvrst.h new file mode 100644 index 00000000..0595756e --- /dev/null +++ b/dcmdata/include/dcmtk/dcmdata/dcvrst.h @@ -0,0 +1,134 @@ +/* + * + * Copyright (C) 1994-2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Gerd Ehlers + * + * Purpose: Interface of class DcmShortText + * + */ + + +#ifndef DCVRST_H +#define DCVRST_H + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/dcmdata/dcchrstr.h" + + +/** a class representing the DICOM value representation 'Short Text' (ST) + */ +class DCMTK_DCMDATA_EXPORT DcmShortText + : public DcmCharString +{ + public: + + /** constructor. + * Create new element from given tag and length. + * @param tag DICOM tag for the new element + * @param len value length for the new element + */ + DcmShortText(const DcmTag &tag, + const Uint32 len = 0); + + /** copy constructor + * @param old element to be copied + */ + DcmShortText(const DcmShortText &old ); + + /** destructor + */ + virtual ~DcmShortText(); + + /** assignment operator + * @param obj element to be assigned/copied + * @return reference to this object + */ + DcmShortText &operator=(const DcmShortText &obj); + + /** clone method + * @return deep copy of this object + */ + virtual DcmObject *clone() const + { + return new DcmShortText(*this); + } + + /** Virtual object copying. This method can be used for DcmObject + * and derived classes to get a deep copy of an object. Internally + * the assignment operator is called if the given DcmObject parameter + * is of the same type as "this" object instance. If not, an error + * is returned. This function permits copying an object by value + * in a virtual way which therefore is different to just calling the + * assignment operator of DcmElement which could result in slicing + * the object. + * @param rhs - [in] The instance to copy from. Has to be of the same + * class type as "this" object + * @return EC_Normal if copying was successful, error otherwise + */ + virtual OFCondition copyFrom(const DcmObject& rhs); + + /** get element type identifier + * @return type identifier of this class (EVR_ST) + */ + virtual DcmEVR ident() const; + + /** check whether stored value conforms to the VR and to the specified VM + * @param vm parameter not used for this VR + * @param oldFormat parameter not used for this VR (only for DA, TM) + * @return status of the check, EC_Normal if value is correct, an error code otherwise + */ + virtual OFCondition checkValue(const OFString &vm = "", + const OFBool oldFormat = OFFalse); + + /** get the value multiplicity. + * Since the backslash "\" is not regarded as a separator the value + * multiplicity is always 1. + * @return value multiplicity of the currently stored value + */ + virtual unsigned long getVM(); + + /** get a copy of a particular string component + * @param stringVal variable in which the result value is stored + * @param pos index of the value in case of multi-valued elements (0..vm-1) + * @param normalize delete leading and trailing spaces if OFTrue + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getOFString(OFString &stringVal, + const unsigned long pos, + OFBool normalize = OFTrue); + + /** get the string value (all components) + * @param stringVal string variable in which the result value is stored + * @param normalize remove trailing spaces if OFTrue + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getOFStringArray(OFString &stringVal, + OFBool normalize = OFTrue); + + /* --- static helper functions --- */ + + /** check whether given string value conforms to the VR "ST" (Short Text) + * @param value string value to be checked + * @param charset character set (according to the value of the SpecificCharacterSet + * element) to be used for checking the string value. The default is ASCII (7-bit). + * @return status of the check, EC_Normal if value is correct, an error code otherwise + */ + static OFCondition checkStringValue(const OFString &value, + const OFString &charset = ""); +}; + + +#endif // DCVRST_H diff --git a/dcmdata/include/dcmtk/dcmdata/dcvrtm.h b/dcmdata/include/dcmtk/dcmdata/dcvrtm.h new file mode 100644 index 00000000..cb62fd4f --- /dev/null +++ b/dcmdata/include/dcmtk/dcmdata/dcvrtm.h @@ -0,0 +1,273 @@ +/* + * + * Copyright (C) 1994-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Gerd Ehlers, Joerg Riesmeier + * + * Purpose: Interface of class DcmTime + * + */ + +#ifndef DCVRTM_H +#define DCVRTM_H + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/dcmdata/dctypes.h" +#include "dcmtk/dcmdata/dcbytstr.h" +#include "dcmtk/ofstd/oftime.h" + + +/** a class representing the DICOM value representation 'Time' (TM) + */ +class DCMTK_DCMDATA_EXPORT DcmTime + : public DcmByteString +{ + + public: + + /** constructor. + * Create new element from given tag and length. + * @param tag DICOM tag for the new element + * @param len value length for the new element + */ + DcmTime(const DcmTag &tag, + const Uint32 len = 0); + + /** copy constructor + * @param old element to be copied + */ + DcmTime(const DcmTime &old); + + /** destructor + */ + virtual ~DcmTime(); + + /** assignment operator + * @param obj element to be assigned/copied + * @return reference to this object + */ + DcmTime &operator=(const DcmTime &obj); + + /** clone method + * @return deep copy of this object + */ + virtual DcmObject *clone() const + { + return new DcmTime(*this); + } + + /** Virtual object copying. This method can be used for DcmObject + * and derived classes to get a deep copy of an object. Internally + * the assignment operator is called if the given DcmObject parameter + * is of the same type as "this" object instance. If not, an error + * is returned. This function permits copying an object by value + * in a virtual way which therefore is different to just calling the + * assignment operator of DcmElement which could result in slicing + * the object. + * @param rhs - [in] The instance to copy from. Has to be of the same + * class type as "this" object + * @return EC_Normal if copying was successful, error otherwise + */ + virtual OFCondition copyFrom(const DcmObject& rhs); + + /** get element type identifier + * @return type identifier of this class (EVR_TM) + */ + virtual DcmEVR ident() const; + + /** check whether stored value conforms to the VR and to the specified VM + * @param vm value multiplicity (according to the data dictionary) to be checked for. + * (See DcmElement::checkVM() for a list of valid values.) + * @param oldFormat support old ACR/NEMA format if OFTrue (':' as a separator) + * @return status of the check, EC_Normal if value is correct, an error code otherwise + */ + virtual OFCondition checkValue(const OFString &vm = "1-n", + const OFBool oldFormat = OFFalse); + + /** get a copy of a particular string component + * @param stringValue variable in which the result value is stored + * @param pos index of the value in case of multi-valued elements (0..vm-1) + * @param normalize delete trailing spaces if OFTrue + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getOFString(OFString &stringValue, + const unsigned long pos, + OFBool normalize = OFTrue); + + /** set the element value to the current system time. + * The DICOM TM format supported by this function is "HHMM[SS[.FFFFFF]]" where + * the brackets enclose optional parts. If the current system time or parts of it + * are unavailable the corresponding values are set to "0" and an error code is + * returned. + * @param seconds add optional seconds ("SS") if OFTrue + * @param fraction add optional fractional part of a second (".FFFFFF") if OFTrue + * (requires parameter 'seconds' to be also OFTrue) + * @return EC_Normal upon success, an error code otherwise + */ + OFCondition setCurrentTime(const OFBool seconds = OFTrue, + const OFBool fraction = OFFalse); + + /** set the element value to the given time + * @param timeValue time to be set (should be a valid time) + * @return EC_Normal upon success, an error code otherwise + */ + OFCondition setOFTime(const OFTime &timeValue); + + /** get the current element value in OFTime format. + * Please note that the element value is expected to be in valid DICOM TM format + * ("[HH[MM[SS[.FFFFFF]]]]", "[HH[:MM[:SS[.FFFFFF]]]]" is also supported for reasons + * of backward compatibility). Since there is no time zone for the DICOM TM format + * local time is assumed (the time zone of 'timeValue' is set automatically). + * If this function fails the result variable 'timeValue' is cleared automatically. + * @param timeValue reference to OFTime variable where the result is stored + * @param pos index of the element component in case of value multiplicity (0..vm-1) + * @param supportOldFormat if OFTrue support old (prior V3.0) time format (see above) + * @return EC_Normal upon success, an error code otherwise + */ + OFCondition getOFTime(OFTime &timeValue, + const unsigned long pos = 0, + const OFBool supportOldFormat = OFTrue); + + /** get the current element value in ISO time format. + * The ISO time format supported by this function is "HH:MM[:SS[.FFFFFF]]" + * where the brackets enclose optional parts. Please note that the element value + * is expected to be in valid DICOM TM format ("[HH[MM[SS[.FFFFFF]]]]", + * "[HH[:MM[:SS[.FFFFFF]]]]" is also supported for reasons of backward compatibility). + * If this function fails or the current element value is empty, the result variable + * 'formattedTime' is cleared automatically. Please note that if the "Timezone Offset + * From UTC" attribute (0008,0201) is present, it applies to all TM attributes in the + * object. However, the time zone is not taken into account for the creation of the + * ISO formatted time. See also "getTimeZoneFromString()" below. + * @param formattedTime reference to string variable where the result is stored + * @param pos index of the element component in case of value multiplicity (0..vm-1) + * @param seconds add optional seconds (":SS") if OFTrue + * @param fraction add optional fractional part of a second (".FFFFFF") if OFTrue + * (requires parameter 'seconds' to be also OFTrue) + * @param createMissingPart if OFTrue create optional parts (seconds and/or fractional + * part of a seconds) if absent in the element value + * @param supportOldFormat if OFTrue support old (prior V3.0) time format (see above) + * @return EC_Normal upon success, an error code otherwise + */ + OFCondition getISOFormattedTime(OFString &formattedTime, + const unsigned long pos = 0, + const OFBool seconds = OFTrue, + const OFBool fraction = OFFalse, + const OFBool createMissingPart = OFFalse, + const OFBool supportOldFormat = OFTrue); + + /* --- static helper functions --- */ + + /** get the current system time. + * The DICOM TM format supported by this function is "HHMM[SS[.FFFFFF]]" where + * the brackets enclose optional parts. If the current system time or parts of it + * are unavailable the corresponding values are set to "0" and an error code is + * returned. + * @param dicomTime reference to string variable where the result is stored + * @param seconds add optional seconds ("SS") if OFTrue + * @param fraction add optional fractional part of a second (".FFFFFF") if OFTrue + * (requires parameter 'seconds' to be also OFTrue) + * @return EC_Normal upon success, an error code otherwise + */ + static OFCondition getCurrentTime(OFString &dicomTime, + const OFBool seconds = OFTrue, + const OFBool fraction = OFFalse); + + /** get the specified OFTime value in DICOM format. + * The DICOM TM format supported by this function is "HHMM[SS[.FFFFFF]]" where + * the brackets enclose optional parts. If the current system time or parts of it + * are unavailable the corresponding values are set to "0" and an error code is + * returned. + * @param timeValue time to be converted to DICOM format + * @param dicomTime reference to string variable where the result is stored + * @param seconds add optional seconds ("SS") if OFTrue + * @param fraction add optional fractional part of a second (".FFFFFF") if OFTrue + * (requires parameter 'seconds' to be also OFTrue) + * @return EC_Normal upon success, an error code otherwise + */ + static OFCondition getDicomTimeFromOFTime(const OFTime &timeValue, + OFString &dicomTime, + const OFBool seconds = OFTrue, + const OFBool fraction = OFFalse); + + /** get the specified DICOM time value in OFTime format. + * Please note that the element value is expected to be in valid DICOM TM format + * ("[HH[MM[SS[.FFFFFF]]]]", "[HH[:MM[:SS[.FFFFFF]]]]" is also supported for reasons + * of backward compatibility). Since there is no time zone for the DICOM TM format + * local time is assumed (the time zone of 'timeValue' is set automatically). + * If this function fails the result variable 'timeValue' is cleared automatically. + * @param dicomTime string value in DICOM TM format to be converted to ISO format. + * An empty string is not regarded as valid input, since the time would be unknown. + * @param timeValue reference to OFTime variable where the result is stored + * @param supportOldFormat if OFTrue support old (prior V3.0) time format (see above) + * @return EC_Normal upon success, an error code otherwise + */ + static OFCondition getOFTimeFromString(const OFString &dicomTime, + OFTime &timeValue, + const OFBool supportOldFormat = OFTrue); + + /** get the specified DICOM time value in ISO format. + * The ISO time format supported by this function is "HH:MM[:SS[.FFFFFF]]" where the + * brackets enclose optional parts. Please note that the specified value is expected + * to be in valid DICOM TM format ("[HH[MM[SS[.FFFFFF]]]]", "[HH[:MM[:SS[.FFFFFF]]]]" + * is also supported for reasons of backward compatibility). If this function fails + * or the specified DICOM time value is empty, the result variable 'formattedTime' + * is cleared automatically. + * @param dicomTime string value in DICOM TM format to be converted to ISO format + * @param formattedTime reference to string variable where the result is stored + * @param seconds add optional seconds (":SS") if OFTrue + * @param fraction add optional fractional part of a second (".FFFFFF") if OFTrue + * (requires parameter 'seconds' to be also OFTrue) + * @param createMissingPart if OFTrue create optional parts (seconds and/or fractional + * part of a seconds) if absent in the DICOM TM value + * @param supportOldFormat if OFTrue support old (prior V3.0) time format (see above) + * @return EC_Normal upon success, an error code otherwise + */ + static OFCondition getISOFormattedTimeFromString(const OFString &dicomTime, + OFString &formattedTime, + const OFBool seconds = OFTrue, + const OFBool fraction = OFFalse, + const OFBool createMissingPart = OFFalse, + const OFBool supportOldFormat = OFTrue); + + /** get the specified DICOM time zone in number of hours format + * DICOM standard states that if the "Timezone Offset From UTC" attribute (0008,0201) is + * present it applies to all TM attributes in the object. This functions allows to convert + * the DICOM format ("&ZZZZ" where "&" is "+" or "-" and "ZZZZ" hours and minutes) to a + * floating point value, e.g. "+1.0" means plus one hour and "-2.5" minus two and a half + * hour, i.e. 2 hours and 30 minutes. + * The resulting 'timeZone' value can be used in conjuction with a OFTime object to convert + * the time to different time zones (e.g. to local time or UTC). + * @param dicomTimeZone string value in DICOM format ("&ZZZZ") to be converted + * @param timeZone reference to floating point variable where the resulting UTC offset is stored + * @return EC_Normal upon success, an error code otherwise + */ + static OFCondition getTimeZoneFromString(const OFString &dicomTimeZone, + double &timeZone); + + /** check whether given string value conforms to the VR "TM" (Time) + * and to the specified VM. + * @param value string value to be checked (possibly multi-valued) + * @param vm value multiplicity (according to the data dictionary) to be checked for. + * (See DcmElement::checkVM() for a list of valid values.) + * @param oldFormat support old ACR/NEMA time format if OFTrue (i.e. with ":" and "." delimiters) + * @return status of the check, EC_Normal if value is correct, an error code otherwise + */ + static OFCondition checkStringValue(const OFString &value, + const OFString &vm = "1-n", + const OFBool oldFormat = OFFalse); +}; + + +#endif // DCVRTM_H diff --git a/dcmdata/include/dcmtk/dcmdata/dcvruc.h b/dcmdata/include/dcmtk/dcmdata/dcvruc.h new file mode 100644 index 00000000..97f18277 --- /dev/null +++ b/dcmdata/include/dcmtk/dcmdata/dcvruc.h @@ -0,0 +1,124 @@ +/* + * + * Copyright (C) 2015, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Joerg Riesmeier + * + * Purpose: Interface of class DcmUnlimitedCharacters + * + */ + + +#ifndef DCVRUC_H +#define DCVRUC_H + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/dcmdata/dctypes.h" +#include "dcmtk/dcmdata/dcchrstr.h" + + +/** a class representing the DICOM value representation 'Unlimited Characters' (UC) + */ +class DCMTK_DCMDATA_EXPORT DcmUnlimitedCharacters + : public DcmCharString +{ + + public: + + /** constructor + * @param tag attribute tag + * @param len length of the attribute value + */ + DcmUnlimitedCharacters(const DcmTag &tag, + const Uint32 len = 0); + + /** copy constructor + * @param old element to be copied + */ + DcmUnlimitedCharacters(const DcmUnlimitedCharacters &old); + + /** destructor + */ + virtual ~DcmUnlimitedCharacters(); + + /** copy assignment operator + * @param obj element to be copied + */ + DcmUnlimitedCharacters &operator=(const DcmUnlimitedCharacters &obj); + + /** clone method + * @return deep copy of this object + */ + virtual DcmObject *clone() const + { + return new DcmUnlimitedCharacters(*this); + } + + /** Virtual object copying. This method can be used for DcmObject + * and derived classes to get a deep copy of an object. Internally + * the assignment operator is called if the given DcmObject parameter + * is of the same type as "this" object instance. If not, an error + * is returned. This function permits copying an object by value + * in a virtual way which therefore is different to just calling the + * assignment operator of DcmElement which could result in slicing + * the object. + * @param rhs - [in] The instance to copy from. Has to be of the same + * class type as "this" object + * @return EC_Normal if copying was successful, error otherwise + */ + virtual OFCondition copyFrom(const DcmObject& rhs); + + /** get element type identifier + * @return type identifier of this class (EVR_UC) + */ + virtual DcmEVR ident() const; + + /** check whether stored value conforms to the VR and to the specified VM + * @param vm value multiplicity (according to the data dictionary) to be checked for. + * (See DcmElement::checkVM() for a list of valid values.) + * @param oldFormat parameter not used for this VR (only for DA, TM) + * @return status of the check, EC_Normal if value is correct, an error code otherwise + */ + virtual OFCondition checkValue(const OFString &vm = "", + const OFBool oldFormat = OFFalse); + + /** get a copy of a particular string component + * @param stringVal variable in which the result value is stored + * @param pos index of the value in case of multi-valued elements (0..vm-1) + * @param normalize delete leading and trailing spaces if OFTrue + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getOFString(OFString &stringVal, + const unsigned long pos, + OFBool normalize = OFTrue); + + /* --- static helper functions --- */ + + /** check whether given string value conforms to the VR "UC" (Unlimited Characters) + * and to the specified VM. + * @param value string value to be checked + * @param vm value multiplicity (according to the data dictionary) to be checked for. + * (See DcmElement::checkVM() for a list of valid values.) + * @param charset character set (according to the value of the SpecificCharacterSet + * element) to be used for checking the string value. The default is ASCII (7-bit). + * @return status of the check, EC_Normal if value is correct, an error code otherwise + */ + static OFCondition checkStringValue(const OFString &value, + const OFString &vm = "1-n", + const OFString &charset = ""); +}; + + +#endif // DCVRUC_H diff --git a/dcmdata/include/dcmtk/dcmdata/dcvrui.h b/dcmdata/include/dcmtk/dcmdata/dcvrui.h new file mode 100644 index 00000000..eba453f9 --- /dev/null +++ b/dcmdata/include/dcmtk/dcmdata/dcvrui.h @@ -0,0 +1,175 @@ +/* + * + * Copyright (C) 1994-2013, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Gerd Ehlers, Andreas Barth + * + * Purpose: Interface of class DcmUniqueIdentifier + * + */ + +#ifndef DCVRUI_H +#define DCVRUI_H + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/dcmdata/dcbytstr.h" + + +/** a class representing the DICOM value representation 'Unique Identifier' (UI) + */ +class DCMTK_DCMDATA_EXPORT DcmUniqueIdentifier + : public DcmByteString +{ + + public: + + /** constructor. + * Create new element from given tag and length. + * @param tag DICOM tag for the new element + * @param len value length for the new element + */ + DcmUniqueIdentifier(const DcmTag &tag, + const Uint32 len = 0); + + /** copy constructor + * @param old element to be copied + */ + DcmUniqueIdentifier(const DcmUniqueIdentifier &old); + + /** destructor + */ + virtual ~DcmUniqueIdentifier(); + + /** assignment operator + * @param obj element to be assigned/copied + * @return reference to this object + */ + DcmUniqueIdentifier &operator=(const DcmUniqueIdentifier &obj); + + /** clone method + * @return deep copy of this object + */ + virtual DcmObject *clone() const + { + return new DcmUniqueIdentifier(*this); + } + + /** Virtual object copying. This method can be used for DcmObject + * and derived classes to get a deep copy of an object. Internally + * the assignment operator is called if the given DcmObject parameter + * is of the same type as "this" object instance. If not, an error + * is returned. This function permits copying an object by value + * in a virtual way which therefore is different to just calling the + * assignment operator of DcmElement which could result in slicing + * the object. + * @param rhs - [in] The instance to copy from. Has to be of the same + * class type as "this" object + * @return EC_Normal if copying was successful, error otherwise + */ + virtual OFCondition copyFrom(const DcmObject& rhs); + + /** get element type identifier + * @return type identifier of this class (EVR_UI) + */ + virtual DcmEVR ident() const; + + /** check whether stored value conforms to the VR and to the specified VM + * @param vm value multiplicity (according to the data dictionary) to be checked for. + * (See DcmElement::checkVM() for a list of valid values.) + * @param oldFormat parameter not used for this VR (only for DA, TM) + * @return status of the check, EC_Normal if value is correct, an error code otherwise + */ + virtual OFCondition checkValue(const OFString &vm = "1-n", + const OFBool oldFormat = OFFalse); + + /** print element to a stream. + * The output format of the value is a backslash separated sequence of string + * components. In case of a single component the UID number is mapped to the + * corresponding UID name (using "dcmFindNameOfUID()") if available. A "=" is + * used as a prefix to distinguish the UID name from the UID number. + * NB: This mapping of UID names only works for single-valued strings. + * @param out output stream + * @param flags optional flag used to customize the output (see DCMTypes::PF_xxx) + * @param level current level of nested items. Used for indentation. + * @param pixelFileName not used + * @param pixelCounter not used + */ + virtual void print(STD_NAMESPACE ostream&out, + const size_t flags = 0, + const int level = 0, + const char *pixelFileName = NULL, + size_t *pixelCounter = NULL); + + /** get a copy of a particular string component + * @param stringVal variable in which the result value is stored + * @param pos index of the value in case of multi-valued elements (0..vm-1) + * @param normalize delete trailing NULL-byte(s) if OFTrue + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getOFString(OFString &stringVal, + const unsigned long pos, + OFBool normalize = OFTrue); + + /** set element value from the given character string. + * If the string starts with a "=" the subsequent characters are interpreted as a + * UID name and mapped to the corresponding UID number (using "dcmFindUIDFromName()") + * if possible. Otherwise the leading "=" is removed. + * NB: This mapping of UID names only works for single-valued input strings. + * @param stringVal input character string (possibly multi-valued) + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition putString(const char *stringVal); + + /** set element value from the given character string. + * If the string starts with a "=" the subsequent characters are interpreted as a + * UID name and mapped to the corresponding UID number (using "dcmFindUIDFromName()") + * if possible. Otherwise the leading "=" is removed. + * NB: This mapping of UID names only works for single-valued input strings. + * The length of the string has to be specified explicitly. The string can, therefore, + * also contain more than one NULL byte. + * @param stringVal input character string (possibly multi-valued) + * @param stringLen length of the string (number of characters without the trailing + * NULL byte) + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition putString(const char *stringVal, + const Uint32 stringLen); + + /* --- static helper functions --- */ + + /** check whether given string value conforms to the VR "UI" (Unique Identifier) + * and to the specified VM. + * @param value string value to be checked (possibly multi-valued) + * @param vm value multiplicity (according to the data dictionary) to be checked for. + * (See DcmElement::checkVM() for a list of valid values.) + * @return status of the check, EC_Normal if value is correct, an error code otherwise + */ + static OFCondition checkStringValue(const OFString &value, + const OFString &vm = "1-n"); + + protected: + + /** convert currently stored string value to internal representation. + * It removes any leading, embedded and trailing space character and recomputes + * the string length. This manipulation attempts to correct problems with + * incorrectly encoded UIDs which have been observed in some images. + * @param length number of characters of the string value (optional) + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition makeMachineByteString(const Uint32 length = 0); +}; + + +#endif // DCVRUI_H diff --git a/dcmdata/include/dcmtk/dcmdata/dcvrul.h b/dcmdata/include/dcmtk/dcmdata/dcvrul.h new file mode 100644 index 00000000..39eae5e8 --- /dev/null +++ b/dcmdata/include/dcmtk/dcmdata/dcvrul.h @@ -0,0 +1,205 @@ +/* + * + * Copyright (C) 1994-2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Gerd Ehlers, Andreas Barth + * + * Purpose: Interface of class DcmUnsignedLong + * + */ + + +#ifndef DCVRUL_H +#define DCVRUL_H + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/dcmdata/dcelem.h" + + +/** a class representing the DICOM value representation 'Unsigned Long' (UL) + */ +class DCMTK_DCMDATA_EXPORT DcmUnsignedLong + : public DcmElement +{ + + public: + + /** constructor. + * Create new element from given tag and length. + * @param tag DICOM tag for the new element + * @param len value length for the new element + */ + DcmUnsignedLong(const DcmTag &tag, + const Uint32 len = 0); + + /** copy constructor + * @param old element to be copied + */ + DcmUnsignedLong(const DcmUnsignedLong &old); + + /** destructor + */ + virtual ~DcmUnsignedLong(); + + /** assignment operator + * @param obj element to be assigned/copied + * @return reference to this object + */ + DcmUnsignedLong &operator=(const DcmUnsignedLong &obj); + + /** comparison operator that compares the normalized value of this object + * with a given object of the same type. The tag of the element is also + * considered as the first component that is compared, followed by the + * object types (VR, i.e. DCMTK'S EVR) and the comparison of all value + * components of the object, preferrably in the order declared in the + * object (if applicable). + * @param rhs the right hand side of the comparison + * @return 0 if the object values are equal. + * -1 if either the value of the first component that does not match + * is lower in this object than in rhs, or all compared components match + * but this object has fewer components than rhs. Also returned if rhs + * cannot be casted to this object type. + * 1 if either the value of the first component that does not match + * is greater in this object than in rhs object, or all compared + * components match but the this component is longer. + */ + virtual int compare(const DcmElement& rhs) const; + + /** clone method + * @return deep copy of this object + */ + virtual DcmObject *clone() const + { + return new DcmUnsignedLong(*this); + } + + /** Virtual object copying. This method can be used for DcmObject + * and derived classes to get a deep copy of an object. Internally + * the assignment operator is called if the given DcmObject parameter + * is of the same type as "this" object instance. If not, an error + * is returned. This function permits copying an object by value + * in a virtual way which therefore is different to just calling the + * assignment operator of DcmElement which could result in slicing + * the object. + * @param rhs - [in] The instance to copy from. Has to be of the same + * class type as "this" object + * @return EC_Normal if copying was successful, error otherwise + */ + virtual OFCondition copyFrom(const DcmObject& rhs); + + /** get element type identifier + * @return type identifier of this class (EVR_UL) + */ + virtual DcmEVR ident() const; + + /** check whether stored value conforms to the VR and to the specified VM + * @param vm value multiplicity (according to the data dictionary) to be checked for. + * (See DcmElement::checkVM() for a list of valid values.) + * @param oldFormat parameter not used for this VR (only for DA, TM) + * @return status of the check, EC_Normal if value is correct, an error code otherwise + */ + virtual OFCondition checkValue(const OFString &vm = "1-n", + const OFBool oldFormat = OFFalse); + + /** get value multiplicity + * @return number of currently stored values + */ + virtual unsigned long getVM(); + + /** print element to a stream. + * The output format of the value is a backslash separated sequence of numbers. + * @param out output stream + * @param flags optional flag used to customize the output (see DCMTypes::PF_xxx) + * @param level current level of nested items. Used for indentation. + * @param pixelFileName not used + * @param pixelCounter not used + */ + virtual void print(STD_NAMESPACE ostream&out, + const size_t flags = 0, + const int level = 0, + const char *pixelFileName = NULL, + size_t *pixelCounter = NULL); + + /** get particular integer value + * @param uintVal reference to result variable (cleared in case of error) + * @param pos index of the value to be retrieved (0..vm-1) + * @return status status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getUint32(Uint32 &uintVal, + const unsigned long pos = 0); + + /** get reference to stored integer data. + * The number of entries can be determined by "getVM()". + * @param uintVals reference to result variable + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getUint32Array(Uint32 *&uintVals); + + /** get particular value as a character string + * @param stringVal variable in which the result value is stored + * @param pos index of the value in case of multi-valued elements (0..vm-1) + * @param normalize not used + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getOFString(OFString &stringVal, + const unsigned long pos, + OFBool normalize = OFTrue); + + /** set particular element value to given integer + * @param uintVal unsigned integer value to be set + * @param pos index of the value to be set (0 = first position) + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition putUint32(const Uint32 uintVal, + const unsigned long pos = 0); + + /** set element value to given integer array data + * @param uintVals unsigned integer data to be set + * @param numUints number of integer values to be set + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition putUint32Array(const Uint32 *uintVals, + const unsigned long numUints); + + /** set element value from the given character string. + * The input string is expected to be a backslash separated sequence of + * numeric characters, e.g. "1\22\333\4444\55555\666666\7777777". + * @param stringVal input character string + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition putString(const char *stringVal); + + /** set element value from the given character string. + * The input string is expected to be a backslash separated sequence of + * numeric characters, e.g. "1\22\333\4444\55555\666666\7777777". + * The length of the string has to be specified explicitly. The string can, therefore, + * also contain more than one NULL byte. + * @param stringVal input character string + * @param stringLen length of the string (number of characters without the trailing + * NULL byte) + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition putString(const char *stringVal, + const Uint32 stringLen); + + /** check the currently stored element value + * @param autocorrect correct value length if OFTrue + * @return status, EC_Normal if value length is correct, an error code otherwise + */ + virtual OFCondition verify(const OFBool autocorrect = OFFalse); +}; + + +#endif // DCVRUL_H diff --git a/dcmdata/include/dcmtk/dcmdata/dcvrulup.h b/dcmdata/include/dcmtk/dcmdata/dcvrulup.h new file mode 100644 index 00000000..c2c2de2e --- /dev/null +++ b/dcmdata/include/dcmtk/dcmdata/dcvrulup.h @@ -0,0 +1,117 @@ +/* + * + * Copyright (C) 1994-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Gerd Ehlers, Andreas Barth + * + * Purpose: Interface of class DcmUnsignedLongOffset + * + */ + + +#ifndef DCVRULUP_H +#define DCVRULUP_H + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/dcmdata/dcvrul.h" + + +/** a class used for DICOMDIR byte offsets + */ +class DCMTK_DCMDATA_EXPORT DcmUnsignedLongOffset + : public DcmUnsignedLong +{ + + public: + + /** constructor. + * Create new element from given tag and length. + * @param tag DICOM tag for the new element + * @param len value length for the new element + */ + DcmUnsignedLongOffset(const DcmTag &tag, + const Uint32 len = 0); + + /** copy constructor + * @param old element to be copied + */ + DcmUnsignedLongOffset(const DcmUnsignedLongOffset &old); + + /** destructor + */ + virtual ~DcmUnsignedLongOffset(); + + /** assignment operator. + * @param the offset to be copied + */ + DcmUnsignedLongOffset &operator=(const DcmUnsignedLongOffset &); + + /** clone method + * @return deep copy of this object + */ + virtual DcmObject *clone() const + { + return new DcmUnsignedLongOffset(*this); + } + + /** Virtual object copying. This method can be used for DcmObject + * and derived classes to get a deep copy of an object. Internally + * the assignment operator is called if the given DcmObject parameter + * is of the same type as "this" object instance. If not, an error + * is returned. This function permits copying an object by value + * in a virtual way which therefore is different to just calling the + * assignment operator of DcmElement which could result in slicing + * the object. + * @param rhs - [in] The instance to copy from. Has to be of the same + * class type as "this" object + * @return EC_Normal if copying was successful, error otherwise + */ + virtual OFCondition copyFrom(const DcmObject& rhs); + + /** get element type identifier + * @return type identifier of this class (internal type: EVR_up) + */ + virtual DcmEVR ident() const; + + /** clear the currently stored value + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition clear(); + + /** get stored object reference + * @return pointer to the currently referenced object (might be NULL) + */ + virtual DcmObject *getNextRecord(); + + /** set stored object reference + * @param record pointer to the object to be referenced + * @return pointer to the newly referenced object (might be NULL) + */ + virtual DcmObject *setNextRecord(DcmObject *record); + + /** check the currently stored element value + * @param autocorrect correct value length if OFTrue + * @return status, EC_Normal if value length is correct, an error code otherwise + */ + virtual OFCondition verify(const OFBool autocorrect = OFFalse); + + private: + + /// pointer to the referenced object. NULL means that no object is referenced. + DcmObject *nextRecord; +}; + + +#endif // DCVRUSUP_H diff --git a/dcmdata/include/dcmtk/dcmdata/dcvrur.h b/dcmdata/include/dcmtk/dcmdata/dcvrur.h new file mode 100644 index 00000000..95aed31e --- /dev/null +++ b/dcmdata/include/dcmtk/dcmdata/dcvrur.h @@ -0,0 +1,133 @@ +/* + * + * Copyright (C) 2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Joerg Riesmeier + * + * Purpose: Interface of class DcmUniversalResourceIdentifierOrLocator + * + */ + + +#ifndef DCVRUR_H +#define DCVRUR_H + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/dcmdata/dctypes.h" +#include "dcmtk/dcmdata/dcbytstr.h" + + +/** a class representing the DICOM value representation 'Universal Resource Identifier or + * Universal Resource Locator (URI/URL)' (UR) + */ +class DCMTK_DCMDATA_EXPORT DcmUniversalResourceIdentifierOrLocator + : public DcmByteString +{ + + public: + + /** constructor + * @param tag attribute tag + * @param len length of the attribute value + */ + DcmUniversalResourceIdentifierOrLocator(const DcmTag &tag, + const Uint32 len = 0); + + /** copy constructor + * @param old element to be copied + */ + DcmUniversalResourceIdentifierOrLocator(const DcmUniversalResourceIdentifierOrLocator &old); + + /** destructor + */ + virtual ~DcmUniversalResourceIdentifierOrLocator(); + + /** copy assignment operator + * @param obj element to be copied + */ + DcmUniversalResourceIdentifierOrLocator &operator=(const DcmUniversalResourceIdentifierOrLocator &obj); + + /** clone method + * @return deep copy of this object + */ + virtual DcmObject *clone() const + { + return new DcmUniversalResourceIdentifierOrLocator(*this); + } + + /** Virtual object copying. This method can be used for DcmObject + * and derived classes to get a deep copy of an object. Internally + * the assignment operator is called if the given DcmObject parameter + * is of the same type as "this" object instance. If not, an error + * is returned. This function permits copying an object by value + * in a virtual way which therefore is different to just calling the + * assignment operator of DcmElement which could result in slicing + * the object. + * @param rhs - [in] The instance to copy from. Has to be of the same + * class type as "this" object + * @return EC_Normal if copying was successful, error otherwise + */ + virtual OFCondition copyFrom(const DcmObject& rhs); + + /** get element type identifier + * @return type identifier of this class (EVR_UR) + */ + virtual DcmEVR ident() const; + + /** check whether stored value conforms to the VR and to the specified VM + * @param vm parameter not used for this VR + * @param oldFormat parameter not used for this VR (only for DA, TM) + * @return status of the check, EC_Normal if value is correct, an error code otherwise + */ + virtual OFCondition checkValue(const OFString &vm = "", + const OFBool oldFormat = OFFalse); + + /** get the value multiplicity. + * Since the backslash "\" is not regarded as a separator the value + * multiplicity is always 1. + * @return value multiplicity of the currently stored value + */ + virtual unsigned long getVM(); + + /** get a copy of a particular string component + * @param stringVal variable in which the result value is stored + * @param pos index of the value in case of multi-valued elements (0..vm-1) + * @param normalize delete leading and trailing spaces if OFTrue + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getOFString(OFString &stringVal, + const unsigned long pos, + OFBool normalize = OFTrue); + + /** get the string value (all components) + * @param stringVal string variable in which the result value is stored + * @param normalize remove trailing spaces if OFTrue + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getOFStringArray(OFString &stringVal, + OFBool normalize = OFTrue); + + /* --- static helper functions --- */ + + /** check whether given string value conforms to the VR "UR" (Universal Resource Identifier + * or Universal Resource Locator, URI/URL) + * @param value string value to be checked + * @return status of the check, EC_Normal if value is correct, an error code otherwise + */ + static OFCondition checkStringValue(const OFString &value); +}; + + +#endif // DCVRUR_H diff --git a/dcmdata/include/dcmtk/dcmdata/dcvrus.h b/dcmdata/include/dcmtk/dcmdata/dcvrus.h new file mode 100644 index 00000000..a4853949 --- /dev/null +++ b/dcmdata/include/dcmtk/dcmdata/dcvrus.h @@ -0,0 +1,205 @@ +/* + * + * Copyright (C) 1994-2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Gerd Ehlers, Andreas Barth + * + * Purpose: Interface of class DcmUnsignedShort + * + */ + + +#ifndef DCVRUS_H +#define DCVRUS_H + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/dcmdata/dcelem.h" + + +/** a class representing the DICOM value representation 'Unsigned Short' (US) + */ +class DCMTK_DCMDATA_EXPORT DcmUnsignedShort + : public DcmElement +{ + + public: + + /** constructor. + * Create new element from given tag and length. + * @param tag DICOM tag for the new element + * @param len value length for the new element + */ + DcmUnsignedShort(const DcmTag &tag, + const Uint32 len = 0); + + /** copy constructor + * @param old element to be copied + */ + DcmUnsignedShort(const DcmUnsignedShort &old); + + /** comparison operator that compares the normalized value of this object + * with a given object of the same type. The tag of the element is also + * considered as the first component that is compared, followed by the + * object types (VR, i.e. DCMTK'S EVR) and the comparison of all value + * components of the object, preferrably in the order declared in the + * object (if applicable). + * @param rhs the right hand side of the comparison + * @return 0 if the object values are equal. + * -1 if either the value of the first component that does not match + * is lower in this object than in rhs, or all compared components match + * but this object has fewer components than rhs. Also returned if rhs + * cannot be casted to this object type. + * 1 if either the value of the first component that does not match + * is greater in this object than in rhs object, or all compared + * components match but the this component is longer. + */ + virtual int compare(const DcmElement& rhs) const; + + /** destructor + */ + virtual ~DcmUnsignedShort(); + + /** assignment operator + * @param obj element to be assigned/copied + * @return reference to this object + */ + DcmUnsignedShort &operator=(const DcmUnsignedShort &obj); + + /** clone method + * @return deep copy of this object + */ + virtual DcmObject *clone() const + { + return new DcmUnsignedShort(*this); + } + + /** Virtual object copying. This method can be used for DcmObject + * and derived classes to get a deep copy of an object. Internally + * the assignment operator is called if the given DcmObject parameter + * is of the same type as "this" object instance. If not, an error + * is returned. This function permits copying an object by value + * in a virtual way which therefore is different to just calling the + * assignment operator of DcmElement which could result in slicing + * the object. + * @param rhs - [in] The instance to copy from. Has to be of the same + * class type as "this" object + * @return EC_Normal if copying was successful, error otherwise + */ + virtual OFCondition copyFrom(const DcmObject& rhs); + + /** get element type identifier + * @return type identifier of this class (EVR_US) + */ + virtual DcmEVR ident() const; + + /** check whether stored value conforms to the VR and to the specified VM + * @param vm value multiplicity (according to the data dictionary) to be checked for. + * (See DcmElement::checkVM() for a list of valid values.) + * @param oldFormat parameter not used for this VR (only for DA, TM) + * @return status of the check, EC_Normal if value is correct, an error code otherwise + */ + virtual OFCondition checkValue(const OFString &vm = "1-n", + const OFBool oldFormat = OFFalse); + + /** get value multiplicity + * @return number of currently stored values + */ + virtual unsigned long getVM(); + + /** print element to a stream. + * The output format of the value is a backslash separated sequence of numbers. + * @param out output stream + * @param flags optional flag used to customize the output (see DCMTypes::PF_xxx) + * @param level current level of nested items. Used for indentation. + * @param pixelFileName not used + * @param pixelCounter not used + */ + virtual void print(STD_NAMESPACE ostream&out, + const size_t flags = 0, + const int level = 0, + const char *pixelFileName = NULL, + size_t *pixelCounter = NULL); + + /** get particular integer value + * @param uintVal reference to result variable (cleared in case of error) + * @param pos index of the value to be retrieved (0..vm-1) + * @return status status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getUint16(Uint16 &uintVal, + const unsigned long pos = 0); + + /** get reference to stored integer data. + * The number of entries can be determined by "getVM()". + * @param uintVals reference to result variable + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getUint16Array(Uint16 *&uintVals); + + /** get particular value as a character string + * @param stringVal variable in which the result value is stored + * @param pos index of the value in case of multi-valued elements (0..vm-1) + * @param normalize not used + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getOFString(OFString &stringVal, + const unsigned long pos, + OFBool normalize = OFTrue); + + /** set particular element value to given integer + * @param uintVal unsigned integer value to be set + * @param pos index of the value to be set (0 = first position) + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition putUint16(const Uint16 uintVal, + const unsigned long pos = 0); + + /** set element value to given integer array data + * @param uintVals unsigned integer data to be set + * @param numUints number of integer values to be set + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition putUint16Array(const Uint16 *uintVals, + const unsigned long numUints); + + /** set element value from the given character string. + * The input string is expected to be a backslash separated sequence of + * numeric characters, e.g. "1\22\333\4444\55555". + * @param stringVal input character string + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition putString(const char *stringVal); + + /** set element value from the given character string. + * The input string is expected to be a backslash separated sequence of + * numeric characters, e.g. "1\22\333\4444\55555". + * The length of the string has to be specified explicitly. The string can, therefore, + * also contain more than one NULL byte. + * @param stringVal input character string + * @param stringLen length of the string (number of characters without the trailing + * NULL byte) + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition putString(const char *stringVal, + const Uint32 stringLen); + + /** check the currently stored element value + * @param autocorrect correct value length if OFTrue + * @return status, EC_Normal if value length is correct, an error code otherwise + */ + virtual OFCondition verify(const OFBool autocorrect = OFFalse); +}; + + +#endif // DCVRUS_H diff --git a/dcmdata/include/dcmtk/dcmdata/dcvrut.h b/dcmdata/include/dcmtk/dcmdata/dcvrut.h new file mode 100644 index 00000000..5ed25d46 --- /dev/null +++ b/dcmdata/include/dcmtk/dcmdata/dcvrut.h @@ -0,0 +1,134 @@ +/* + * + * Copyright (C) 1994-2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Andrew Hewett + * + * Purpose: Interface of class DcmUnlimitedText + * + */ + + +#ifndef DCVRUT_H +#define DCVRUT_H + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/dcmdata/dctypes.h" +#include "dcmtk/dcmdata/dcchrstr.h" + + +/** a class representing the DICOM value representation 'Unlimited Text' (UT) + */ +class DCMTK_DCMDATA_EXPORT DcmUnlimitedText + : public DcmCharString +{ + + public: + + /** constructor + * @param tag attribute tag + * @param len length of the attribute value + */ + DcmUnlimitedText(const DcmTag &tag, + const Uint32 len = 0); + + /** copy constructor + * @param old element to be copied + */ + DcmUnlimitedText(const DcmUnlimitedText &old); + + /** destructor + */ + virtual ~DcmUnlimitedText(); + + /** copy assignment operator + * @param obj element to be copied + */ + DcmUnlimitedText &operator=(const DcmUnlimitedText &obj); + + /** clone method + * @return deep copy of this object + */ + virtual DcmObject *clone() const + { + return new DcmUnlimitedText(*this); + } + + /** Virtual object copying. This method can be used for DcmObject + * and derived classes to get a deep copy of an object. Internally + * the assignment operator is called if the given DcmObject parameter + * is of the same type as "this" object instance. If not, an error + * is returned. This function permits copying an object by value + * in a virtual way which therefore is different to just calling the + * assignment operator of DcmElement which could result in slicing + * the object. + * @param rhs - [in] The instance to copy from. Has to be of the same + * class type as "this" object + * @return EC_Normal if copying was successful, error otherwise + */ + virtual OFCondition copyFrom(const DcmObject& rhs); + + /** get element type identifier + * @return type identifier of this class (EVR_UT) + */ + virtual DcmEVR ident() const; + + /** check whether stored value conforms to the VR and to the specified VM + * @param vm parameter not used for this VR + * @param oldFormat parameter not used for this VR (only for DA, TM) + * @return status of the check, EC_Normal if value is correct, an error code otherwise + */ + virtual OFCondition checkValue(const OFString &vm = "", + const OFBool oldFormat = OFFalse); + + /** get the value multiplicity. + * Since the backslash "\" is not regarded as a separator the value + * multiplicity is always 1. + * @return value multiplicity of the currently stored value + */ + virtual unsigned long getVM(); + + /** get a copy of a particular string component + * @param stringVal variable in which the result value is stored + * @param pos index of the value in case of multi-valued elements (0..vm-1) + * @param normalize delete leading and trailing spaces if OFTrue + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getOFString(OFString &stringVal, + const unsigned long pos, + OFBool normalize = OFTrue); + + /** get the string value (all components) + * @param stringVal string variable in which the result value is stored + * @param normalize remove trailing spaces if OFTrue + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getOFStringArray(OFString &stringVal, + OFBool normalize = OFTrue); + + /* --- static helper functions --- */ + + /** check whether given string value conforms to the VR "UT" (Unlimited Text) + * @param value string value to be checked + * @param charset character set (according to the value of the SpecificCharacterSet + * element) to be used for checking the string value. The default is ASCII (7-bit). + * @return status of the check, EC_Normal if value is correct, an error code otherwise + */ + static OFCondition checkStringValue(const OFString &value, + const OFString &charset = ""); +}; + + +#endif // DCVRUT_H diff --git a/dcmdata/include/dcmtk/dcmdata/dcwcache.h b/dcmdata/include/dcmtk/dcmdata/dcwcache.h new file mode 100644 index 00000000..e5ec08da --- /dev/null +++ b/dcmdata/include/dcmtk/dcmdata/dcwcache.h @@ -0,0 +1,136 @@ +/* + * + * Copyright (C) 2007-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Marco Eichelberg + * + * Purpose: file cache facility for DcmElement::getPartialValue + * + */ + + +#ifndef DCWCACHE_H +#define DCWCACHE_H + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/ofstd/oftypes.h" /* for Uint8 */ +#include "dcmtk/dcmdata/dcfcache.h" /* for class DcmFileCache */ + +class DcmElement; +class DcmOutputStream; + +#define DcmWriteCacheBufsize 65536 /* buffer size, in bytes */ + +/** This class implements a buffering mechanism that is used when writing large + * elements that reside in file into an output stream. DcmElement::getPartialValue + * is used to fill the buffer maintained by this class, and the buffer content + * is then copied to the output stream. The intermediate buffer is necessary + * because both DcmElement::getPartialValue and DcmOutputStream::write expect + * a buffer to write to and read from, respectively. + */ +class DCMTK_DCMDATA_EXPORT DcmWriteCache +{ +public: + + /// default constructor. Construction is cheap (no allocation of memory block). + DcmWriteCache() + : fcache_() + , buf_(NULL) + , owner_(NULL) + , offset_(0) + , numBytes_(0) + , capacity_(0) + , fieldLength_(0) + , fieldOffset_(0) + , byteOrder_(EBO_unknown) + { + } + + /// destructor + ~DcmWriteCache() + { + delete[] buf_; + } + + /** initialize the buffer maintained by this class. Can safely be called multiple times. + * @param owner current "owner" (DcmElement instance using this buffer) + * @param fieldLength number of bytes of user data in DICOM element + * @param bytesTransferred number of bytes of user data in DICOM element that have already been transferred + * @param byteOrder byteOrder desired byte order in buffer + */ + void init(void *owner, Uint32 fieldLength, Uint32 bytesTransferred, E_ByteOrder byteOrder); + + /** check whether the buffer is currently empty + * @return true if buffer is empty, false otherwise + */ + OFBool bufferIsEmpty() const { return (numBytes_ == 0); } + + /** return the number of bytes of user data currently in buffer + * @return number of bytes of user data currently in buffer + */ + Uint32 contentLength() const { return numBytes_; } + + /** fill buffer from given DICOM element if buffer is currently empty. + * This method uses DcmElement::getPartialValue to fill the buffer from the given + * DICOM element at the given offset (which is updated to reflect the number of bytes + * read into the buffer). + * @param elem DICOM element to read from + * @return EC_Normal if successful, an error code otherwise + */ + OFCondition fillBuffer(DcmElement& elem); + + /** write buffer content to output stream + * @param outStream output stream to write to + * @return number of bytes written + */ + Uint32 writeBuffer(DcmOutputStream &outStream); + +private: + + /// private undefined copy constructor + DcmWriteCache(const DcmWriteCache& arg); + + /// private undefined copy assignment operator + DcmWriteCache& operator=(const DcmWriteCache& arg); + + /// file cache object + DcmFileCache fcache_; + + /// write buffer + Uint8 *buf_; + + /// current "owner" (DcmElement instance using this buffer) + void *owner_; + + /// offset within buffer to first byte + Uint32 offset_; + + /// number of user data bytes currently in buffer + Uint32 numBytes_; + + /// buffer size in bytes + Uint32 capacity_; + + /// length of the current DICOM element, in bytes + Uint32 fieldLength_; + + /// offset within the current DICOM element, in bytes + Uint32 fieldOffset_; + + /// current output byte order + E_ByteOrder byteOrder_; +}; + +#endif diff --git a/dcmdata/include/dcmtk/dcmdata/dcxfer.h b/dcmdata/include/dcmtk/dcmdata/dcxfer.h new file mode 100644 index 00000000..8e99e84b --- /dev/null +++ b/dcmdata/include/dcmtk/dcmdata/dcxfer.h @@ -0,0 +1,324 @@ +/* + * + * Copyright (C) 1994-2015, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Gerd Ehlers + * + * Purpose: Handling of transfer syntaxes + * + */ + +#ifndef DCXFER_H +#define DCXFER_H + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ +#include "dcmtk/dcmdata/dctypes.h" +#include "dcmtk/dcmdata/dcvr.h" + +/** enumeration of all DICOM transfer syntaxes known to the toolkit + */ +typedef enum { + /// unknown transfer syntax or dataset created in-memory + EXS_Unknown = -1, + /// Implicit VR Little Endian + EXS_LittleEndianImplicit = 0, + /// Implicit VR Big Endian (pseudo transfer syntax that does not really exist) + EXS_BigEndianImplicit = 1, + /// Explicit VR Little Endian + EXS_LittleEndianExplicit = 2, + /// Explicit VR Big Endian + EXS_BigEndianExplicit = 3, + /// JPEG Baseline (lossy) + EXS_JPEGProcess1 = 4, + /// JPEG Extended Sequential (lossy, 8/12 bit) + EXS_JPEGProcess2_4 = 5, + /// JPEG Extended Sequential (lossy, 8/12 bit), arithmetic coding + EXS_JPEGProcess3_5 = 6, + /// JPEG Spectral Selection, Non-Hierarchical (lossy, 8/12 bit) + EXS_JPEGProcess6_8 = 7, + /// JPEG Spectral Selection, Non-Hierarchical (lossy, 8/12 bit), arithmetic coding + EXS_JPEGProcess7_9 = 8, + /// JPEG Full Progression, Non-Hierarchical (lossy, 8/12 bit) + EXS_JPEGProcess10_12 = 9, + /// JPEG Full Progression, Non-Hierarchical (lossy, 8/12 bit), arithmetic coding + EXS_JPEGProcess11_13 = 10, + /// JPEG Lossless with any selection value + EXS_JPEGProcess14 = 11, + /// JPEG Lossless with any selection value, arithmetic coding + EXS_JPEGProcess15 = 12, + /// JPEG Extended Sequential, Hierarchical (lossy, 8/12 bit) + EXS_JPEGProcess16_18 = 13, + /// JPEG Extended Sequential, Hierarchical (lossy, 8/12 bit), arithmetic coding + EXS_JPEGProcess17_19 = 14, + /// JPEG Spectral Selection, Hierarchical (lossy, 8/12 bit) + EXS_JPEGProcess20_22 = 15, + /// JPEG Spectral Selection, Hierarchical (lossy, 8/12 bit), arithmetic coding + EXS_JPEGProcess21_23 = 16, + /// JPEG Full Progression, Hierarchical (lossy, 8/12 bit) + EXS_JPEGProcess24_26 = 17, + /// JPEG Full Progression, Hierarchical (lossy, 8/12 bit), arithmetic coding + EXS_JPEGProcess25_27 = 18, + /// JPEG Lossless, Hierarchical + EXS_JPEGProcess28 = 19, + /// JPEG Lossless, Hierarchical, arithmetic coding + EXS_JPEGProcess29 = 20, + /// JPEG Lossless, Selection Value 1 + EXS_JPEGProcess14SV1 = 21, + /// Run Length Encoding (lossless) + EXS_RLELossless = 22, + /// JPEG-LS (lossless) + EXS_JPEGLSLossless = 23, + /// JPEG-LS (lossless or near-lossless mode) + EXS_JPEGLSLossy = 24, + /// Deflated Explicit VR Little Endian + EXS_DeflatedLittleEndianExplicit = 25, + /// JPEG 2000 (lossless) + EXS_JPEG2000LosslessOnly = 26, + /// JPEG 2000 (lossless or lossy) + EXS_JPEG2000 = 27, + /// MPEG2 Main Profile at Main Level + EXS_MPEG2MainProfileAtMainLevel = 28, + /// MPEG2 Main Profile at High Level + EXS_MPEG2MainProfileAtHighLevel = 29, + /// MPEG4 High Profile / Level 4.1 + EXS_MPEG4HighProfileLevel4_1 = 30, + /// MPEG4 BD-compatible High Profile / Level 4.1 + EXS_MPEG4BDcompatibleHighProfileLevel4_1 = 31, + /// MPEG4 High Profile / Level 4.2 For 2D Video + EXS_MPEG4HighProfileLevel4_2_For2DVideo = 32, + /// MPEG4 High Profile / Level 4.2 For 3D Video + EXS_MPEG4HighProfileLevel4_2_For3DVideo = 33, + /// MPEG4 Stereo High Profile / Level 4.2 + EXS_MPEG4StereoHighProfileLevel4_2 = 34, + /// JPEG 2000 part 2 multi-component extensions (lossless) + EXS_JPEG2000MulticomponentLosslessOnly = 35, + /// JPEG 2000 part 2 multi-component extensions (lossless or lossy) + EXS_JPEG2000Multicomponent = 36, + /// JPIP Referenced + EXS_JPIPReferenced = 37, + /// JPIP Referenced Deflate + EXS_JPIPReferencedDeflate = 38 +} E_TransferSyntax; + +/** enumeration of byte orders + */ +typedef enum { + /// unknown + EBO_unknown = 0, + + /// little endian + EBO_LittleEndian = 1, + + /// big endian + EBO_BigEndian = 2 +} E_ByteOrder; + +/** enumeration of VR encoding options + */ +typedef enum { + /// implicit VR encoding + EVT_Implicit = 0, + + /// explicit VR encoding + EVT_Explicit = 1 +} E_VRType; + +/** enumeration of pixel data encapsulation options + */ +typedef enum { + /// pixel data not encapsulated + EJE_NotEncapsulated = 0, + + /// pixel data encapsulated + EJE_Encapsulated = 1 +} E_JPEGEncapsulated; + +/** enumeration of stream compression techniques + */ +typedef enum +{ + /// no stream compression + ESC_none = 0 + /// unsupported stream compression + , ESC_unsupported = 1 +#ifdef WITH_ZLIB + /// zlib stream compression + , ESC_zlib = 2 +#endif +} E_StreamCompression; + + +/** a class that allows for a lookup of Transfer Syntax properties and readable descriptions + */ +class DCMTK_DCMDATA_EXPORT DcmXfer +{ +public: + /** constructor + * @param xfer transfer syntax enum + */ + DcmXfer( E_TransferSyntax xfer ); + + /** constructor + * @param xferName_xferID transfer syntax name as string + */ + DcmXfer( const char *xferName_xferID ); + + /// copy constructor + DcmXfer( const DcmXfer &newXfer ); + + /// destructor + ~DcmXfer(); + + /// assignment operator for transfer syntax enum + DcmXfer & operator = ( const E_TransferSyntax xfer ); + + /// copy assignment operator + DcmXfer & operator = ( const DcmXfer &newtag ); + + /// return transfer syntax enum for this transfer syntax + inline E_TransferSyntax getXfer() const { return xferSyn; } + + /// return byte order for this transfer syntax + inline E_ByteOrder getByteOrder() const { return byteOrder; } + + /// return name string for this transfer syntax + inline const char* getXferName() const { return xferName; } + + /// return UID string for this transfer syntax + inline const char* getXferID() const { return xferID; } + + /// return true if transfer syntax is little endian, false otherwise + inline OFBool isLittleEndian() const + { + return byteOrder == EBO_LittleEndian; + } + + /// return true if transfer syntax is big endian, false otherwise + inline OFBool isBigEndian() const { return byteOrder == EBO_BigEndian; } + + /// return true if transfer syntax is implicit VR, false otherwise + inline OFBool isImplicitVR() const { return vrType == EVT_Implicit; } + + /// return true if transfer syntax is explicit VR, false otherwise + inline OFBool isExplicitVR() const { return vrType == EVT_Explicit; } + + /// return true if transfer syntax is encapsulated, false otherwise + inline OFBool isEncapsulated() const + { + return encapsulated == EJE_Encapsulated; + } + + /// return true if transfer syntax is native (non-encapsulated), false otherwise + inline OFBool isNotEncapsulated() const + { + return encapsulated == EJE_NotEncapsulated; + } + + /** return 8-bit JPEG process ID for this transfer syntax. + * Lossy JPEG transfer syntaxes support two alternative JPEG encoding processes - 8 and 12 bits. + * When called for a non-JPEG transfer syntax, returns 0. + * @return 8-bit JPEG process ID + */ + inline Uint32 getJPEGProcess8Bit() const { return JPEGProcess8; } + + /** return 12-bit JPEG process ID for this transfer syntax. + * Lossy JPEG transfer syntaxes support two alternative JPEG encoding processes - 8 and 12 bits. + * When called for a non-JPEG transfer syntax, returns 0. + * @return 12-bit JPEG process ID + */ + inline Uint32 getJPEGProcess12Bit() const { return JPEGProcess12;} + + /** check whether transfer syntax uses a lossy compression + * @return true if transfer syntax uses a lossy compression, false otherwise + */ + inline OFBool isLossy() const + { + return lossy; + } + + /** check whether transfer syntax uses a lossless compression or no compression + * @return true if transfer syntax uses a lossless compression or no compression, + * false otherwise + */ + inline OFBool isLossless() const + { + return !lossy; + } + + /** check whether transfer syntax is retired + * @return true if transfer syntax is retired, false otherwise + */ + inline OFBool isRetired() const + { + return retired; + } + + /** get stream compression type for this transfer syntax + * @return stream compression type for this transfer syntax + */ + inline E_StreamCompression getStreamCompression() const + { + return streamCompression; + } + + /** return the number of bytes needed to describe the tag, length, VR + * and any reserved fields for this transfer syntax when encoding the + * specified VR. + * @param evr value representation to be encoded in this transfer syntax + * @return number of bytes needed + */ + Uint32 sizeofTagHeader(DcmEVR evr) const; + +private: + /// transfer syntax UID + const char *xferID; + + /// transfer syntax name + const char *xferName; + + /// transfer syntax enum + E_TransferSyntax xferSyn; + + /// transfer syntax byte order + E_ByteOrder byteOrder; + + /// transfer syntax VR encoding (implicit/explicit) + E_VRType vrType; + + /// transfer syntax encapsulated or native + E_JPEGEncapsulated encapsulated; + + /// 8-bit lossy JPEG process ID for this transfer syntax, 0 if not applicable + Uint32 JPEGProcess8; + + /// 12-bit lossy JPEG process ID for this transfer syntax, 0 if not applicable + Uint32 JPEGProcess12; + + /// flag indicating whether this transfer syntax uses a lossy compression + OFBool lossy; + + /// flag indicating whether this transfer syntax has been retired from DICOM + OFBool retired; + + /// transfer syntax stream compression type + E_StreamCompression streamCompression; +}; + +/** global constant describing the byte order on the machine the application + * is currently executing on. This is runtime and not compile time information + * because of "fat" binaries that can be executed on multiple CPU types (e.g. NeXTStep) + */ +extern DCMTK_DCMDATA_EXPORT const E_ByteOrder gLocalByteOrder; + +#endif // DCXFER_H diff --git a/dcmdata/include/dcmtk/dcmdata/libi2d/i2d.h b/dcmdata/include/dcmtk/dcmdata/libi2d/i2d.h new file mode 100644 index 00000000..cb1fb08a --- /dev/null +++ b/dcmdata/include/dcmtk/dcmdata/libi2d/i2d.h @@ -0,0 +1,263 @@ +/* + * + * Copyright (C) 2001-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Michael Onken + * + * Purpose: Class to control conversion of image format to DICOM + * + */ + +#ifndef I2D_H +#define I2D_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmdata/libi2d/i2doutpl.h" +#include "dcmtk/dcmdata/libi2d/i2dimgs.h" +#include "dcmtk/dcmdata/dcpixel.h" + +class DCMTK_I2D_EXPORT Image2Dcm +{ + +public: + + /** Constructor, initializes command line options + * @return none + */ + Image2Dcm(); + + /** Start the conversion. Needs a fully configured input plugin + * and a fully configured output plugin to operate. Returns + * a dataset with the resulting DICOM object. + * @param inputPlug - [in] The input plugin to read pixel data + * @param outPlug - [in] The output plugin for specific SOP class output + * @param resultDset - [out] The DICOM object resulting from the conversion + * @param proposedTS - [out] The proposed transfer syntax (needed e. g. + * by JPEG input plugin) + * @return EC_Normal, if successfull, error otherwise + */ + OFCondition convert(I2DImgSource *inputPlug, + I2DOutputPlug *outPlug, + DcmDataset*& resultDset, + E_TransferSyntax& proposedTS); + + /** Sets a DICOM file that should serve as a template for the resulting + * DICOM object. Only the dataset of the given file is imported. + * @param file - [in] The filename of the template DICOM file + * @return none + */ + void setTemplateFile(const OFString& file); + + /** Set file from which patient/study/series data should be imported from. + * @param file - [in] The DICOM file to read from + * @return none + */ + void setSeriesFrom(const OFString& file); + + /** Set file from which patient/study/series data should be imported from. + * @param file - [in] The DICOM file to read from + * @return none + */ + void setStudyFrom(const OFString& file); + + /** Enables/Disables incrementing instance number taken over from DICOM file. + * This can either be a the study/series file or the template file + * provided. + * @param incInstNo - [in] If true, the instance number will be incremented + * @return none + */ + void setIncrementInstanceNumber(OFBool incInstNo); + + /** Enables/disables autotmatic insertion of the value "ISO_IR100" as + * a value for the Specific Character Set attribute. If disabled, + * no value is inserted for Specifific Character Set but instead + * must be provided by other means (see setTemplateFile(), setSeriesFrom(), + * setStudyFrom(), setOverrideKeys()). The insertion is applied after + * loading the (optional) template file; the value might be overwritten + * by the value copied by setStudy/Series/OverrideKeys. + * @param insertLatin1 - [in] Enable/disable insertion of Iso Latin 1 + * @return none; + */ + void setISOLatin1(OFBool insertLatin1); + + /** Specifies some attributes that should be inserted after conversion. + * They will override any identical attributes already existing in the + * converted result DICOM object. The override keys are applied at the very + * end of the conversion and do not undergoe any validity checking. + * @param ovkeys [in] override keys that can be tags, dictionary names + * and paths (see DcmPath for syntax). Also it is + * permitted to set a value if appropriate, e. g. + * "PatientName=Doe^John" would be a valid override + * key. + * @return none + */ + void setOverrideKeys(const OFList& ovkeys); + + /** Enable/Disable basic validity checks for output dataset + * @param doChecks - [in] OFTrue enables checking, OFFalse turns it off. + * @param insertMissingType2 - [in] If true (default), missing type 2 + * attributes are inserted automatically + * @param inventMissingType1 - [in] If true , missing type 1 + * attributes are inserted automatically with a predefined + * value (if possible). An existing empty type 1 attribute is + * assigned a value, too. + * @return none + */ + void setValidityChecking(OFBool doChecks, + OFBool insertMissingType2 = OFTrue, + OFBool inventMissingType1 = OFTrue); + + /** Destructor, frees plugin memory + * @return none + */ + ~Image2Dcm(); + +protected: + + /** Cleans up template for future insertion of pixel data information, ie + * generally removes attributes from image pixel module + * @param targetDset - [out] The dataset that should be cleand up + * @return none + */ + void cleanupTemplate(DcmDataset *targetDset); + + /** Parses patient/study/series level attributes from file as defined + * on command line and fills internal attributes accordingly. + * @param targetDset - [out] The dataset to write the attributes to + * @return EC_Normal, if successful, error otherwise + */ + OFCondition applyStudyOrSeriesFromFile(DcmDataset *targetDset); + + /** Increments instance number in given dataset + * @param targetDset - [in/out] Dataset to increment instance number in + * @return EC_Normal, if successful, error otherwise + */ + OFCondition incrementInstanceNumber(DcmDataset *targetDset); + + /** Generates and inserts missing UIDs, ie UIDs not taken over + * from --dataset-from --study from and --series-from options + * @param dset - [in] The dataset to write the UIDs to + * @return EC_Normal, if successful, error otherwise + */ + OFCondition generateUIDs(DcmDataset *dset); + + /** Reads pixel data and corresponding attributes like rows etc. from image + * file and inserts them into dataset. + * @param imageSource - [in] The input plugin that actually reads the pixel data + * @param dset - [out] The dataset to export the pixel data attributes to + * @param outputTS - [out] The proposed transfex syntax of the dataset + * @return EC_Normal, if successful, error otherwise + */ + OFCondition readAndInsertPixelData( I2DImgSource* imageSource, + DcmDataset* dset, + E_TransferSyntax& outputTS); + + /** Do some completeness / validity checks. Should be called when + * dataset is completed and is about to be saved. + * @param dataset - [in] The dataset to check + * @return Error string if error occurs, empty string otherwise + */ + OFString isValid(DcmDataset& dataset) const; + + /** Copy override keys over existing keys in given dataset. + * @param outputDset - [out] dataset to which the override keys are copied + * @return Error code if error occurs, EC_Normal otherwise + */ + OFCondition applyOverrideKeys(DcmDataset *outputDset); + + /** Inserts "ISO_IR100" in the attribute "Specific Character Set". + * Overwrites any existing value. + * @param outputDset - [out] The dataset to write to + * @return EC_Normal if insertion is successfull, error code otherwise + */ + OFCondition insertLatin1(DcmDataset *outputDset); + + /** Check whether given type 1 attribute is present and has a length > 0. + * @param key - [in] The attribute tag check + * @param targetDset - [out] targetDset + * @param defaultValue - [in] value to be inserted if attribute is missing + * (needs invent option for type 1 attributes enabled) + * @return A string with an error message if attribute is not present + * or has length of 0 + */ + OFString checkAndInventType1Attrib(const DcmTagKey& key, + DcmDataset* targetDset, + const OFString& defaultValue = "") const; + + + /** Inserts an empty element with the given tag into a dataset + * @param key - [in] The attribute tag to check + * @param targetDset - [out] targetDset + * @return A string with an error message if attribute is not present + * nor gets inserted automatically (see m_inventMissingType2Attribs) + */ + OFString checkAndInventType2Attrib(const DcmTagKey& key, + DcmDataset* targetDset) const; + +private: + + /** Correctly inserts encapsulated pixel data. + * @param dset [in] - The dataset to which we should add this. + * @param pixData [in] - The data to add. + * @param length [in] - The length of pixData. + * @param outputTS [in] - The output transfer syntax to be used + * @return EC_Normal, if successfull, error otherwise. + */ + OFCondition insertEncapsulatedPixelData(DcmDataset* dset, + char *pixData, + Uint32 length, + const E_TransferSyntax& outputTS) const; + + /* Attributes for writing DICOM dataset */ + + /// These attributes are applied to the dataset after conversion + /// (and are not checked by the isValid() function) + OFList m_overrideKeys; + + /// If not empty, the DICOM file specified in this variable is used + /// as a base for the DICOM image file to be created, ie. all attributes + /// are taken over from this template file + OFString m_templateFile; + + /// If true, patient and study data is read from file + OFBool m_readStudyLevel; + + /// If true, patient, study and series data is read from file + OFBool m_readSeriesLevel; + + /// File to read study and series from + OFString m_studySeriesFile; + + /// If true, Instance Number ist read from file and incremented by 1 + OFBool m_incInstNoFromFile; + + /// If true, some simple attribute checks (missing type 2 attributes or + /// missing type 1 values) are omitted + OFBool m_disableAttribChecks; + + /// If true, missing type 2 elements are inserted automatically (empty value). + /// Enabled per default. + OFBool m_inventMissingType2Attribs; + + /// If true, missing type 1 elements are inserted automatically with a + /// predefined value, if possible. Disabled per default. + OFBool m_inventMissingType1Attribs; + + /// If enabled, ISO_IR100 (ISO Latin 1) is inserted as a standard value + /// for attribute "Specific Character Set". Insertion takes place after + /// loading (optional) template file. + OFBool m_insertLatin1; +}; + +#endif // I2D_H diff --git a/dcmdata/include/dcmtk/dcmdata/libi2d/i2dbmps.h b/dcmdata/include/dcmtk/dcmdata/libi2d/i2dbmps.h new file mode 100644 index 00000000..4db84793 --- /dev/null +++ b/dcmdata/include/dcmtk/dcmdata/libi2d/i2dbmps.h @@ -0,0 +1,227 @@ +/* + * + * Copyright (C) 2009-2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Uli Schlachter + * + * Purpose: Class to extract pixel data and meta information from BMP file + * + */ + +#ifndef I2DBMPS_H +#define I2DBMPS_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmdata/libi2d/i2dimgs.h" +#include "dcmtk/ofstd/offile.h" + +/** This is a I2DImgSource implementation that can parse BMP files and convert + * them into DICOM images. + */ +class DCMTK_I2D_EXPORT I2DBmpSource : public I2DImgSource +{ + +public: + + /** Constructor, initializes member variables + * @return none + */ + I2DBmpSource(); + + /** Returns format of input image. For this class "BMP" is returned. + * @return Returns format of input image, i.e. "BMP". + */ + OFString inputFormat() const; + + /** Extracts the raw BMP pixel data stream from a BMP file and returns some + * further information about this pixel data. Raw means that any header + * information is removed from the BMP stream. + * This function allocates memory for the pixel data returned to the user. + * The caller of this function is responsible for deleting the memory buffer. + * @param rows - [out] Rows of image + * @param cols - [out] Columns of image + * @param samplesPerPixel - [out] Number of components per pixel + * @param photoMetrInt - [out] The DICOM color model used for the compressed data + * @param bitsAlloc - [out] Bits Allocated for one sample + * @param bitsStored - [out] Bits Stored, Number of bits actually stored within + * Bits Allocated + * @param highBit - [out] High Bit, Highest stored in bit within Bits Allocated + * @param pixelRepr - [out] Pixel Representation (0=unsigned, 1=signed) + * @param planConf - [out] Planar Configuration + * @param pixAspectH - [out] Horizontal value of pixel aspect ratio + * @param pixAspectV - [out] Vertical value of pixel aspect ratio + * @param pixData - [out] Pointer to the pixel data in BMP Interchange Format + * @param length - [out] Length of pixel data + * @param ts - [out] The transfer syntax imposed by the imported pixel pixel data + * @return EC_Normal, if successful, error otherwise + */ + OFCondition readPixelData( Uint16& rows, + Uint16& cols, + Uint16& samplesPerPixel, + OFString& photoMetrInt, + Uint16& bitsAlloc, + Uint16& bitsStored, + Uint16& highBit, + Uint16& pixelRepr, + Uint16& planConf, + Uint16& pixAspectH, + Uint16& pixAspectV, + char*& pixData, + Uint32& length, + E_TransferSyntax& ts); + + /** After reading of pixel data, this function can be used for getting + * information about lossy compression parameters. + * @param srcEncodingLossy - [out] Always returns OFFalse (i.e. lossless) + * @param srcLossyComprMethod - [out] Unused parameter + * @return EC_Normal if information is available, error otherwise + */ + virtual OFCondition getLossyComprInfo(OFBool& srcEncodingLossy, + OFString& /* srcLossyComprMethod */) const + { + srcEncodingLossy = OFFalse; + return EC_Normal; + } + + /** Destructor, frees some memory. + * @return none + */ + virtual ~I2DBmpSource(); + +protected: + + /** Opens the BMP file specified by the given filename. + * @param filename - [in] The file to be opened + * @return EC_Normal, if successful, error otherwise + */ + OFCondition openFile(const OFString& filename); + + /** Closes BMP file. + * @return none + */ + void closeFile(); + + /** Reads and checks the BMP file header. + * @param offset - [out] Offset to the BMP data from beginning of file + * @return EC_Normal, if successful, error otherwise + */ + OFCondition readFileHeader(Uint32 &offset); + + /** Reads and checks the BMP bitmap header. + * After this function, the current read position is just after the + * header. That is, at the beginning of the color palette. + * @param width - [out] width of the image in pixel + * @param height - [out] height of the image in pixel + * @param isTopDown - [out] OFTrue if this is a top down bitmap + * (height was read as negative value). OFFalse otherwise. + * @param bpp - [out] bits per pixel of the image. + * @param colors - [out] number of entries in color table. + * @return EC_Normal, if successful, error otherwise + */ + OFCondition readBitmapHeader(Uint16 &width /*out*/, + Uint16 &height /*out*/, + Uint16 &bpp /*out*/, + OFBool &isTopDown /*out*/, + Uint16 &colors /*out*/); + + /** Read the color palette from the file. + * @param colors - [in] number of colors to read + * @param palette - [out] the read color palette is stored here + * @return EC_Normal, if successful, error otherwise + */ + OFCondition readColorPalette(Uint16 colors, + Uint32*& palette); + + /** Read the bitmap data. + * This assumes the current read position is at the start of the image data. + * @param width - [in] width of the image in pixel + * @param height - [in] height of the image in pixel + * @param bpp - [in] Image's bits per pixel. + * @param isTopDown - [in] If true, this is a top down bitmap + * @param colors - [in] Number of color palette entries + * @param palette - [in] Color palette + * @param pixData - [out] Image data + * @param length - [out] Length of data + * @return EC_Normal, if successful, error otherwise + */ + OFCondition readBitmapData(const Uint16 width, + const Uint16 height, + const Uint16 bpp, + const OFBool isTopDown, + const Uint16 colors, + const Uint32* palette, + char*& pixData /*out*/, + Uint32& length /*out*/); + + /** Parse a single 24bpp or 32bpp row of BMP data. + * @param row - [in] The row of data to parse. + * @param width - [in] The length in pixel of the row. + * @param bpp - [in] The number of bits per pixel. + * @param pixData - [out] The buffer to write the data to (in "RGB" format). + * @return EC_Normal, if successful, error otherwise + */ + OFCondition parse24_32BppRow(const Uint8 *row, + const Uint16 width, + const int bpp, + char *pixData /*out*/) const; + + /** Parse a single 16bpp row of BMP data. + * @param row - [in] The row of data to parse. + * @param width - [in] The length in pixel of the row. + * @param pixData - [out] The buffer to write the data to (in "RGB" format). + * @return EC_Normal, if successful, error otherwise + */ + OFCondition parse16BppRow(const Uint8 *row, + const Uint16 width, + char *pixData /*out*/) const; + + /** Parse a single 1, 4 or 8bpp row of BMP data. + * @param row - [in] The row of data to parse. + * @param width - [in] The length in pixel of the row. + * @param bpp - [in] The number of bits per pixel. + * @param colors - [in] The number of entries in the color palette. + * @param palette - [in] The color palette to use. + * @param pixData - [out] The buffer to write the data to (in "RGB" format). + * @return EC_Normal, if successful, error otherwise + */ + OFCondition parseIndexedColorRow(const Uint8 *row, + const Uint16 width, + const int bpp, + const Uint16 colors, + const Uint32* palette, + char *pixData /*out*/) const; + + /** Read 4 bytes from the byte stream and interpret it as a signed integer. + * @param result - [out] The result + * @return 0, if successful, EOF if rest of stream does not contain enough bytes + */ + int readLong(Sint32& result); + + /** Read 4 bytes from the byte stream. + * @param result - [out] The result + * @return 0, if successful, EOF if rest of stream does not contain enough bytes + */ + int readDWord(Uint32& result); + + /** Read 2 bytes from the byte stream. + * @param result - [out] The result + * @return 0, if successful, EOF if rest of stream does not contain enough bytes + */ + int readWord(Uint16& result); + + /// The BMP file, if opened + OFFile bmpFile; +}; + +#endif // I2DBMPS_H diff --git a/dcmdata/include/dcmtk/dcmdata/libi2d/i2define.h b/dcmdata/include/dcmtk/dcmdata/libi2d/i2define.h new file mode 100644 index 00000000..9f485644 --- /dev/null +++ b/dcmdata/include/dcmtk/dcmdata/libi2d/i2define.h @@ -0,0 +1,38 @@ +/* + * + * Copyright (C) 2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Uli Schlachter + * + * Purpose: Contains preprocessor definitions + * + */ + + +#ifndef I2DEFINE_H +#define I2DEFINE_H + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/ofstd/ofdefine.h" + + +#ifdef i2d_EXPORTS +#define DCMTK_I2D_EXPORT DCMTK_DECL_EXPORT +#else +#define DCMTK_I2D_EXPORT DCMTK_DECL_IMPORT +#endif + + +#endif // DCDEFINE_H diff --git a/dcmdata/include/dcmtk/dcmdata/libi2d/i2dimgs.h b/dcmdata/include/dcmtk/dcmdata/libi2d/i2dimgs.h new file mode 100644 index 00000000..83b3b555 --- /dev/null +++ b/dcmdata/include/dcmtk/dcmdata/libi2d/i2dimgs.h @@ -0,0 +1,117 @@ +/* + * + * Copyright (C) 2007-2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Michael Onken + * + * Purpose: Base Class for plugins extracting pixel data from standard + * image files + * + */ + +#ifndef I2DIMGS_H +#define I2DIMGS_H + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/ofstd/ofcond.h" +#include "dcmtk/dcmdata/dcxfer.h" +#include "dcmtk/dcmdata/libi2d/i2define.h" + +/** Base Class for plugins extracting pixel data from standard image files + */ +class DCMTK_I2D_EXPORT I2DImgSource +{ + +public: + + /** Constructor + */ + I2DImgSource() : m_imageFile() {} + + /** Returns identifier for the image input format the plugin imports. + * @return A short identifier of the input format + */ + virtual OFString inputFormat() const = 0; + + /** Extracts the raw pixel data stream from image file and returns some further + * information about this pixel data. + * This function allocates memory for the pixel data returned to the user. + * The caller of this function is responsible for deleting the memory buffer + * @param rows - [out] Rows of image + * @param cols - [out] Columns of image + * @param samplesPerPixel - [out] Number of components per pixel + * @param photoMetrInt - [out] The DICOM color model used for the compressed data + * @param bitsAlloc - [out] Bits Allocated for one sample + * @param bitsStored - [out] Bits Stored, number of bits stored within Bits Allocated + * @param highBit - [out] High Bit, highest bit position set within Bits Allocated + * @param pixelRepr - [out] Pixel Representation (0=unsigned, 1=signed) + * @param planConf - [out] Planar Configuration + * @param pixAspectH - [out] Horizontal value of pixel aspect ratio + * @param pixAspectV - [out] Vertical value of pixel aspect ratio + * @param pixData - [out] Pointer to the pixel data + * @param length - [out] Length of pixel data + * @param ts - [out] The transfer syntax imposed by the imported pixel pixel data + * @return EC_Normal, if successful, error otherwise + */ + virtual OFCondition readPixelData( Uint16& rows, + Uint16& cols, + Uint16& samplesPerPixel, + OFString& photoMetrInt, + Uint16& bitsAlloc, + Uint16& bitsStored, + Uint16& highBit, + Uint16& pixelRepr, + Uint16& planConf, + Uint16& pixAspectH, + Uint16& pixAspectV, + char*& pixData, + Uint32& length, + E_TransferSyntax& ts) =0; + + /** After reading of pixel data, this function can be used for getting + * information about lossy compression parameters. + * @param srcEncodingLossy - [out] Denotes, whether the encoding of the pixel + * data read was lossy (OFTrue) or lossless (OFFalse) + * @param srcLossyComprMethod - [out] Denotes the lossy compression method used + * in source if there is one (srcEncodingLossy = OFTrue). + * Should use defined terms of attribute Lossy + * Compression Method. + * @return EC_Normal if information is available, error otherwise + */ + virtual OFCondition getLossyComprInfo(OFBool& srcEncodingLossy, + OFString& srcLossyComprMethod) const = 0; + + /** Sets the input image file to read. + * @param filename - [in] The filename of the image input file + * @return none + */ + void setImageFile(const OFString& filename) { m_imageFile = filename; }; + + /** Returns the input image file that currently associated with plugin + * @return The filename of the image input file + */ + OFString getImageFile() { return m_imageFile; }; + + /** Virtual Destructor + */ + virtual ~I2DImgSource() {} + +protected: + + /// The input file + OFString m_imageFile; +}; + +#endif // I2DIMGS_H diff --git a/dcmdata/include/dcmtk/dcmdata/libi2d/i2djpgs.h b/dcmdata/include/dcmtk/dcmdata/libi2d/i2djpgs.h new file mode 100644 index 00000000..4e4d4040 --- /dev/null +++ b/dcmdata/include/dcmtk/dcmdata/libi2d/i2djpgs.h @@ -0,0 +1,353 @@ +/* + * + * Copyright (C) 2007-2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Michael Onken + * + * Purpose: Class to extract pixel data and meta information from JPEG file + * + */ + +#ifndef I2DJPGS_H +#define I2DJPGS_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/ofstd/offile.h" +#include "dcmtk/ofstd/oflist.h" +#include "dcmtk/dcmdata/libi2d/i2dimgs.h" + +/** + * JPEG markers consist of one or more 0xFF bytes, followed by a marker code byte + * (which is not an FF). This enum lists the second byte of all these markers. + * @note RESn markers are not fully listed, but only the first (RES0) and the + * last (RESN) + */ +enum E_JPGMARKER { E_JPGMARKER_SOF0 = 0xC0, E_JPGMARKER_SOF1 = 0xC1, E_JPGMARKER_SOF2 = 0xC2, + E_JPGMARKER_SOF3 = 0xC3, /*C4 and CC are not SOF markers,*/ E_JPGMARKER_SOF5 = 0xC5, + E_JPGMARKER_SOF6 = 0xC6, E_JPGMARKER_SOF7 = 0xC7, E_JPGMARKER_JPG = 0xC8, + E_JPGMARKER_SOF9 = 0xC9, E_JPGMARKER_SOF10 = 0xCA, E_JPGMARKER_SOF11 = 0xCB, + E_JPGMARKER_SOF13 = 0xCD, E_JPGMARKER_SOF14 = 0xCE, E_JPGMARKER_SOF15 = 0xCF, + E_JPGMARKER_DHT = 0xC4, E_JPGMARKER_DAC = 0xCC, E_JPGMARKER_RST0 = 0xD0, + E_JPGMARKER_RST1 = 0xD1, E_JPGMARKER_RST2 = 0xD2, E_JPGMARKER_RST3 = 0xD3, + E_JPGMARKER_RST4 = 0xD4, E_JPGMARKER_RST5 = 0xD5, E_JPGMARKER_RST6 = 0xD6, + E_JPGMARKER_RST7 = 0xD7, E_JPGMARKER_SOI = 0xD8, E_JPGMARKER_EOI = 0xD9, + E_JPGMARKER_SOS = 0xDA, E_JPGMARKER_DQT = 0xDB, E_JPGMARKER_DNL = 0xDC, + E_JPGMARKER_DRI = 0xDD, E_JPGMARKER_DHP = 0xDE, E_JPGMARKER_EXP = 0xDF, + E_JPGMARKER_APP0 = 0xE0, E_JPGMARKER_APP1 = 0xE1, E_JPGMARKER_APP2 = 0xE2, + E_JPGMARKER_APP3 = 0xE3, E_JPGMARKER_APP4 = 0xE4, E_JPGMARKER_APP5 = 0xE5, + E_JPGMARKER_APP6 = 0xE6, E_JPGMARKER_APP7 = 0xE7, E_JPGMARKER_APP8 = 0xE8, + E_JPGMARKER_APP9 = 0xE9, E_JPGMARKER_APP10 = 0xEA, E_JPGMARKER_APP11 = 0xEB, + E_JPGMARKER_APP12 = 0xEC, E_JPGMARKER_APP13 = 0xED, E_JPGMARKER_APP14 = 0xEE, + E_JPGMARKER_APP15 = 0xEF, E_JPGMARKER_JPGN0 = 0xF0, E_JPGMARKER_JPGN1 = 0xF1, + E_JPGMARKER_JPGN2 = 0xF2, E_JPGMARKER_JPGN3 = 0xF3, E_JPGMARKER_JPGN4 = 0xF4, + E_JPGMARKER_JPGN5 = 0xF5, E_JPGMARKER_JPGN6 = 0xF6, E_JPGMARKER_JPGN7 = 0xF7, + E_JPGMARKER_JPGN8 = 0xF8, E_JPGMARKER_JPGN9 = 0xF9, E_JPGMARKER_JPGN10 = 0xFA, + E_JPGMARKER_JPGN11 = 0xFB, E_JPGMARKER_JPGN12 = 0xFC, E_JPGMARKER_JPGN13 = 0xFD, + E_JPGMARKER_COM = 0xFE, E_JPGMARKER_TEM = 0x01, E_JPGMARKER_RES0 = 0x02, + E_JPGMARKER_RESN = 0xBF }; + +/** + * Struct that represents a marker in a JPEG file, i.e. it consists + * of the byte position of the marker and the marker code itself + */ +struct DCMTK_I2D_EXPORT JPEGFileMapEntry { + /// The byte position of the marker + offile_off_t bytePos; + /// The marker byte itself + E_JPGMARKER marker; +}; + + +/** This is a I2DImgSource implementation that can parse JPEG files and convert + * them into DICOM images. + */ +class DCMTK_I2D_EXPORT I2DJpegSource : public I2DImgSource +{ + +public: + + /** Constructor, initializes member variables + * @return none + */ + I2DJpegSource(); + + /** Returns format of input image. For this class "JPEG" is returned. + * @return Returns format of input image, i.e. "JPEG". + */ + OFString inputFormat() const; + + /** Extracts the raw JPEG pixel data stream from a JPEG file and returns some + * further information about this pixel data. Raw means here that all APP + * markers (e.g. JFIF information) are removed from the JPEG stream. + * The pixel data returned is a JPEG stream in JPEG interchange format. + * This function allocates memory for the pixel data returned to the user. + * The caller of this function is responsible for deleting the memory buffer. + * @param rows - [out] Rows of image + * @param cols - [out] Columns of image + * @param samplesPerPixel - [out] Number of components per pixel + * @param photoMetrInt - [out] The DICOM color model used for the compressed data + * @param bitsAlloc - [out] Bits Allocated for one sample + * @param bitsStored - [out] Bits Stored, Number of bits actually stored within + * Bits Allocated + * @param highBit - [out] High Bit, Highest stored in bit within Bits Allocated + * @param pixelRepr - [out] Pixel Representation (0=unsigned, 1=signed) + * @param planConf - [out] Planar Configuration + * @param pixAspectH - [out] Horizontal value of pixel aspect ratio + * @param pixAspectV - [out] Vertical value of pixel aspect ratio + * @param pixData - [out] Pointer to the pixel data in JPEG Interchange Format + * (but without APPx markers). + * @param length - [out] Length of pixel data + * @param ts - [out] The transfer syntax imposed by the imported pixel pixel + * data. This is necessary for the JPEG importer that needs + * to report which TS must be used for the imported JPEG data + * (ie. baseline, progressive, ...). + * @return EC_Normal, if successful, error otherwise + */ + OFCondition readPixelData( Uint16& rows, + Uint16& cols, + Uint16& samplesPerPixel, + OFString& photoMetrInt, + Uint16& bitsAlloc, + Uint16& bitsStored, + Uint16& highBit, + Uint16& pixelRepr, + Uint16& planConf, + Uint16& pixAspectH, + Uint16& pixAspectV, + char*& pixData, + Uint32& length, + E_TransferSyntax& ts); + + /** After reading of pixel data, this function can be used for getting + * information about lossy compression parameters. + * @param srcEncodingLossy - [out] Denotes, whether the encoding of the pixel + * data read was lossy (OFTrue) or lossless (OFFalse) + * @param srcLossyComprMethod - [out] Denotes the lossy compression method used + * in source if there is one (srcEncodingLossy = OFTrue). + * Should use defined terms of attribute Lossy + * Compression Method. + * @return EC_Normal if information is available, error otherwise + */ + OFCondition getLossyComprInfo(OFBool& srcEncodingLossy, + OFString& srcLossyComprMethod) const; + + /** Enable/Disable support for Extended Sequential JPEG Coding + * @param enabled - [in] OFTrue: support Extended Sequential, + * OFFalse: do not support + * @return none + */ + void setExtSeqSupport(const OFBool enabled); + + /** Enable/Disable support for Progressive JPEG Coding + * @param enabled - [in] OFTrue: support Extended Sequential, + * OFFalse: do not support + * @return none + */ + void setProgrSupport(const OFBool enabled); + + /** If enabled, conversion will only take place if JFIF data could be found + * and evaluated. Many digital cameras do not provide a JFIF header, so this + * is disabled by default. + */ + void setInsistOnJFIF(const OFBool enabled); + + /** If enabled, APPn markers (except JFIF!) are also copied to the output file. + * This can cause a huge speedup because instead of parsing the whole + * JPEG file (for finding any APPn markers) the parsing stops after finding + * the SOFn marker (which is relevant for extracting width/height and so on. + * Default: false + * @param enabled - [in] OFTrue: copy APPn, OFFalse: cut off APPn info + * @return none + */ + void setKeepAPPn(const OFBool enabled); + + /** Returns a string representation of a JPEG marker code. + * @param marker - [in] The marker to be converted + * @return A string representation of the marker + */ + static OFString jpegMarkerToString(const E_JPGMARKER& marker); + + /** Destructor, frees some memory. + * @return none + */ + ~I2DJpegSource(); + +protected: + + /** Opens the JPEG file specified by the given filename. + * @param filename - [in] The file to be opened + * @return EC_Normal, if successful, error otherwise + */ + OFCondition openFile(const OFString& filename); + + /** Closes JPEG file. + * @return A string representation of the marker + */ + void closeFile(); + + /** Function that scans a JPEG file and creates a "file map" which + * includes all JPEG markers and their byte positions in the file. + * @return EC_Normal, if successful, error otherwise + */ + OFCondition createJPEGFileMap(); + + /** Dump the internal JPEG file map to a given stream. The file map + * lists JPEG markers and their position in the bitstream found in the JPEG + * file + * @return none + */ + void debugDumpJPEGFileMap() const; + + /** Get image parameters as found at given SOF marker of the JPEG image. + * @param entry - [in] This specifies the marker and the byte position of the + * SOF marker + * @param imageWidth - [out] The width of the image + * @param imageHeight - [out] The height of the image + * @param samplesPerPixel - [out] Number of components per pixel + * @param bitsPerSample - [out] Number of bits per pixel component + * @return EC_Normal, if successful, error otherwise + */ + OFCondition getSOFImageParameters( const JPEGFileMapEntry& entry, + Uint16& imageWidth, + Uint16& imageHeight, + Uint16& samplesPerPixel, + Uint16& bitsPerSample); + + /** Get JPEG parameters as found at given JFIF marker of the JPEG image. + * @param entry - [in] This specifies the marker and the byte position of the + * JFIF marker + * @param jfifVersion - [out] The JFIF version of the JFIF data + * @param pixelAspectH - [out] The horizontal pixel aspect ratio + * @param pixelAspectV - [out] The vertical pixel aspect ratio + * @param unit - [out] The contents of the pixel aspect ratio unit field + * @return EC_Normal, if successful, error otherwise + */ + OFCondition getJFIFImageParameters( const JPEGFileMapEntry& entry, + Uint16& jfifVersion, + Uint16& pixelAspectH, + Uint16& pixelAspectV, + Uint16& unit); + + /** Check, whether a given JPEG image marker (SOFn) is supported by + * this plugin + * @param jpegEncoding - [in] Image marker that should be tested + * @return EC_Normal, marker is supported, error otherwise + */ + OFCondition isJPEGEncodingSupported(const E_JPGMARKER& jpegEncoding) const; + + + /** Returns if possible the DICOM transfer syntax matching the coding of the + * JPEG data. + * @param jpegEncoding - [in] Image marker that should be tested + * @return EC_Normal, marker is supported, error otherwise + */ + static E_TransferSyntax associatedTS(const E_JPGMARKER& jpegEncoding); + + /** Returns true if marker is one of the RST0 to RST7 markers + * @param jpegEncoding - [in] Image marker that should be tested + * @return OFTrue, if marker is RST0 to RST7, OFFalse otherwise + */ + static OFBool isRSTMarker(const E_JPGMARKER& jpegEncoding); + + /** Returns true if marker is one of the SOF0 to SOF15 markers + * @param jpegEncoding - [in] Image marker that should be tested + * @return OFTrue, if marker is SOF0 to SOF15, OFFalse otherwise + */ + static OFBool isSOFMarker(const E_JPGMARKER& jpegEncoding); + + + /** Extract raw JPEG stream (i.e. without APPn markers) from JPEG file. + * @param pixelData - [out] The resulting JPEG stream + * @param pixLength - [out] The length of the resulting stream + * @return EC_Normal, if successful, error otherwise + */ + OFCondition extractRawJPEGStream(char*& pixelData, + Uint32& pixLength); + + /** Copies JPEG stream (with APPn markers, excluding JFIF) from JPEG file. + * @param pixelData - [out] The resulting JPEG stream + * @param pixLength - [out] The length of the resulting stream + * @return EC_Normal, if successful, error otherwise + */ + OFCondition copyJPEGStream(char*& pixelData, + Uint32& pixLength); + + /** Skips one marker while scanning through the JPEG file stream. + * @return EC_Normal, if successful, error otherwise + */ + OFCondition skipVariable(); + + /** Tries to read the SOI marker. + * @param result - [out] The code of the SOI marker if successful (0xD8) + * @return EC_Normal, if successful, error otherwise + */ + OFCondition firstMarker(E_JPGMARKER& result); + + /** Tries to find the next JPEG marker in underlying file stream. + * @param lastWasSOSMarker - [in] Denotes, whether the last marker read + * before was the SOS (start of scan) marker. This is needed to + * ignore non-marker 0xFF occurrences in the compressed data. + * @param result - [out] The result marker + * @return EC_Normal, if successful, error otherwise + */ + OFCondition nextMarker(const OFBool& lastWasSOSMarker, + E_JPGMARKER& result); + + /** Read 2 bytes from the byte stream. + * @param result - [out] The result + * @return 0, if successful, EOF if rest of stream does not contain enough bytes + */ + inline int read2Bytes(Uint16& result); + + /** Read 1 byte from the byte stream. + * @param result - [out] The result + * @return 0, if successful, EOF if rest of stream does not contain enough bytes + */ + inline int read1Byte(Uint8& result); + + /** Deletes internal JPEG file map and frees memory. + * @return none + */ + void clearMap(); + + /// JPEG file map. This map includes all JPEG markers and their byte positions + /// in the JPEG file. + OFList m_jpegFileMap; + + /// The JPEG file, if opened + OFFile jpegFile; + + /// If true, JPEGs with progressive coding are not supported + OFBool m_disableProgrTs; + + /// If true, JPEGs with extended sequential coding are not supported + OFBool m_disableExtSeqTs; + + /// If true, conversion will only work if JFIF header can be found. + /// Default: false + OFBool m_insistOnJFIF; + + /// If true, APPn markers (except JFIF!) are also copied to the output file. + /// This can cause a huge speedup because instead of parsing the whole + /// JPEG file (for finding any APPn markers) the parsing stops after finding + /// the SOFn marker (which is relevant for extracting width/height and so on. + /// Default: false + OFBool m_keepAPPn; + + /// After reading pixel data, this denotes whether the source + /// data is already lossy compressed + OFBool m_lossyCompressed; +}; + +#endif // I2DJPGS_H diff --git a/dcmdata/include/dcmtk/dcmdata/libi2d/i2doutpl.h b/dcmdata/include/dcmtk/dcmdata/libi2d/i2doutpl.h new file mode 100644 index 00000000..c3d8d4cf --- /dev/null +++ b/dcmdata/include/dcmtk/dcmdata/libi2d/i2doutpl.h @@ -0,0 +1,222 @@ +/* + * + * Copyright (C) 2001-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Michael Onken + * + * Purpose: Base class for converter from image file to DICOM + * + */ + +#ifndef I2DOUTPL_H +#define I2DOUTPL_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmdata/dcdatset.h" +#include "dcmtk/dcmdata/dcelem.h" +#include "dcmtk/oflog/oflog.h" +#include "dcmtk/dcmdata/libi2d/i2define.h" + + +extern DCMTK_I2D_EXPORT OFLogger DCM_dcmdataLibi2dLogger; + +#define DCMDATA_LIBI2D_TRACE(msg) OFLOG_TRACE(DCM_dcmdataLibi2dLogger, msg) +#define DCMDATA_LIBI2D_DEBUG(msg) OFLOG_DEBUG(DCM_dcmdataLibi2dLogger, msg) +#define DCMDATA_LIBI2D_INFO(msg) OFLOG_INFO(DCM_dcmdataLibi2dLogger, msg) +#define DCMDATA_LIBI2D_WARN(msg) OFLOG_WARN(DCM_dcmdataLibi2dLogger, msg) +#define DCMDATA_LIBI2D_ERROR(msg) OFLOG_ERROR(DCM_dcmdataLibi2dLogger, msg) +#define DCMDATA_LIBI2D_FATAL(msg) OFLOG_FATAL(DCM_dcmdataLibi2dLogger, msg) + + +class DCMTK_I2D_EXPORT I2DOutputPlug +{ + +public: + + /** Constructor, initializes member variables + * @return none + */ + I2DOutputPlug() : m_doAttribChecking(OFTrue), m_inventMissingType2Attribs(OFTrue), + m_inventMissingType1Attribs(OFTrue) + {}; + + /** Virtual function that returns a short name of the plugin. + * @return The name of the plugin + */ + virtual OFString ident() =0; + + /** Virtual function that returns the Storage SOP class UID, the plugin writes. + * @param suppSOPs - [out] List containing supported output SOP classes + * @return String containing the Storage SOP class UID + */ + virtual void supportedSOPClassUIDs(OFList& suppSOPs) =0; + + /** Outputs SOP class specific information into dataset + * @param dataset - [in/out] Dataset to write to + * @return EC_Normal if successful, error otherwise + */ + virtual OFCondition convert(DcmDataset &dataset) const =0; + + /** Do some completeness / validity checks. Should be called when + * dataset is completed and is about to be saved. + * @param dataset - [in] The dataset to check + * @return Error string if error occurs, empty string otherwise + */ + virtual OFString isValid(DcmDataset& dataset) const = 0; + + /** Destructor + * @return none + */ + virtual ~I2DOutputPlug() {}; + + /** Enable/Disable basic validity checks for output dataset + * @param doChecks - [in] OFTrue enables checking, OFFalse turns it off. + * @param insertMissingType2 - [in] If true (default), missing type 2 + * attributes are inserted automatically + * @param inventMissingType1 - [in] If true (default), missing type 1 + * attributes are inserted automatically with a predefined + * value (if possible). An existing empty type 1 attribute is + * assigned a value, too. + * @return none + */ + virtual void setValidityChecking(OFBool doChecks, + OFBool insertMissingType2 = OFTrue, + OFBool inventMissingType1 = OFTrue) + { + m_doAttribChecking = doChecks; + m_inventMissingType2Attribs = insertMissingType2; + m_inventMissingType1Attribs = inventMissingType1; + }; + +protected: + + /** Checks whether a given tag exists in a dataset and provides a non-empty + * value. If not, the tag is inserted (if enabled) and a default value is + * inserted. + * @param key - [in] The tag to be checked/inserted + * @param targetDset - [in/out] The dataset to search (and insert) in + * @param defaultValue - [in] The default value to set + * @return Error string, which is empty if no error occurs. + */ + virtual OFString checkAndInventType1Attrib(const DcmTagKey& key, + DcmDataset* targetDset, + const OFString& defaultValue ="") const + { + OFBool exists = targetDset->tagExists(key); + if (!exists && !m_inventMissingType1Attribs) + { + OFString err = "I2DOutputPlug: Missing type 1 attribute: "; err += DcmTag(key).getTagName(); err += "\n"; + return err; + } + DcmElement *elem; + OFCondition cond = targetDset->findAndGetElement(key, elem); + if (cond.bad() || !elem || (elem->getLength() == 0)) + { + if (!m_inventMissingType1Attribs) + { + OFString err; + err += "I2DOutputPlug: Empty value for type 1 attribute: "; + err += DcmTag(key).getTagName(); + err += "\n"; + return err; + } + //holds element to insert in item + elem = NULL; + DcmTag tag(key); OFBool wasError = OFFalse; + //if dicom element could be created, insert in to item and modify to value + if ( newDicomElement(elem, tag).good()) + { + if (targetDset->insert(elem, OFTrue).good()) + { + if (elem->putString(defaultValue.c_str()).good()) + { + DCMDATA_LIBI2D_DEBUG("I2DOutputPlug: Inserting missing type 1 attribute: " << tag.getTagName() << " with value " << defaultValue); + } else wasError = OFTrue; + } else wasError = OFTrue; + } else wasError = OFTrue; + if (wasError) + { + OFString err = "Unable to insert type 1 attribute "; + err += tag.getTagName(); err += " with value "; err += defaultValue; err += "\n"; + return err; + } + } + return ""; + }; + + + /** Checks whether a given tag exists in a dataset (can be empty) + * If not, the tag is inserted (if enabled) with empty value. + * @param key - [in] The tag to be checked/inserted + * @param targetDset - [in/out] The dataset to search (and insert) in + * @return Error string, which is empty if no error occurs. + */ + virtual OFString checkAndInventType2Attrib(const DcmTagKey& key, + DcmDataset* targetDset, + const OFString& defaultValue ="") const + { + OFString err; + OFBool exists = targetDset->tagExists(key); + if (!exists) + { + if (m_inventMissingType2Attribs) + { + //holds element to insert in item + DcmElement *elem = NULL; + DcmTag tag(key); OFBool wasError = OFFalse; + //if dicom element could be created, insert in to item and modify to value + if ( newDicomElement(elem, tag).good()) + { + if (targetDset->insert(elem, OFTrue).good()) + { + OFCondition result; + if (!defaultValue.empty()) // only insert value if not empty(e. g. empty type 2 sequences) + { + result = elem->putString(defaultValue.c_str()); + } + if (result.good()) + { + DCMDATA_LIBI2D_DEBUG("I2DOutputPlug: Inserting missing type 2 attribute: " << tag.getTagName() << " with value " << (defaultValue.empty() ? "" : defaultValue)); + } else wasError = OFTrue; + } else wasError = OFTrue; + } else wasError = OFTrue; + if (wasError) + { + err += "Unable to insert type 2 attribute "; err += tag.getTagName(); err += " with value "; err += defaultValue; err += "\n"; + } + } + else + { + err = "Image2Dcm: Missing type 2 attribute: "; err += DcmTag(key).getTagName(); err += "\n"; + return err; + } + } + return err; + }; + + /// if enabled, some simple attribute checking is performed + /// default: enabled (OFTrue) + OFBool m_doAttribChecking; + + /// if enabled, missing type 2 attributes in the dataset are added automatically. + /// default: enabled (OFTrue) + OFBool m_inventMissingType2Attribs; + + /// if enbled, missing type 1 attributes are inserted and filled with a + /// predefined value. Default: disabled (OFFalse) + OFBool m_inventMissingType1Attribs; + +}; + +#endif // #ifndef I2DOUTPL_H diff --git a/dcmdata/include/dcmtk/dcmdata/libi2d/i2dplnsc.h b/dcmdata/include/dcmtk/dcmdata/libi2d/i2dplnsc.h new file mode 100644 index 00000000..7980201e --- /dev/null +++ b/dcmdata/include/dcmtk/dcmdata/libi2d/i2dplnsc.h @@ -0,0 +1,108 @@ +/* + * + * Copyright (C) 2001-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Michael Onken + * + * Purpose: Class for conversion of image file into new DICOM SC Image IODs + * + */ + +#ifndef I2DPLNSC_H +#define I2DPLNSC_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmdata/libi2d/i2doutpl.h" + +class DCMTK_I2D_EXPORT I2DOutputPlugNewSC : public I2DOutputPlug +{ + +public: + + /** Constructor, initializes member variables with standard values + * @return none + */ + I2DOutputPlugNewSC(); + + /** Virtual function that returns a short name of the plugin. + * @return The name of the plugin + */ + virtual OFString ident(); + + /** Overwrites function from base class. Returns the Storage SOP class + * written by this plugin + * @param suppSOPs - [out] List of UIDs representing the supported SOP + * classes supported by this plugin. + * @return none + */ + virtual void supportedSOPClassUIDs(OFList& suppSOPs); + + /** Outputs SOP class specific information into dataset + * @param dataset - [in/out] Dataset to write to + * @return EC_Normal if successful, error otherwise + */ + virtual OFCondition convert(DcmDataset &dataset) const; + + /** Do some completeness / validity checks. Should be called when + * dataset is completed and is about to be saved. + * @param dataset - [in] The dataset to check + * @return Error string if error occurs, empty string otherwise + */ + virtual OFString isValid(DcmDataset& dataset) const; + + /** Virtual Destructor, clean up memory + * @return none + */ + virtual ~I2DOutputPlugNewSC(); + +protected: + + /** Inserts attributes for Multi-frame Module + * @param targetDataset - [in/out] The dataset to write to + * @return EC_Normal if insertion was successfull, error code otherwise + */ + virtual OFCondition insertMultiFrameAttribs(DcmDataset* targetDataset) const; + + /** Inserts attributes Rescale Slope/Intercept/Type, which have to be + * written (1C) if color model is MONOCHROME2 and BitsStored > 1. + * @param targetDataset - [out] The dataset to write to + * @return EC_Normal if insertion was successfull, error code otherwise + */ + virtual OFCondition insertSCMultiFrameAttribs(DcmDataset *targetDataset) const; + + /** Checks whether Image Pixel module attributes conform to the + * specification of a a 1 bit Secondary Capture object. + * @param dataset - [in] The dataset to check + * @return EC_Normal, if everything is fine, error code otherwise + */ + virtual OFCondition handle1BitSC(DcmDataset *dataset) const; + + /** Checks whether Image Pixel module attributes conform to the + * specification of a a 8 bit Secondary Capture object. + * @param dataset - [in] The dataset to check + * @return EC_Normal, if everything is fine, error code otherwise + */ + virtual OFCondition handle8BitSC(DcmDataset *dataset) const; + + /** Checks whether Image Pixel module attributes conform to the + * specification of a a 16 bit Secondary Capture object. + * @param dataset - [in] The dataset to check + * @return EC_Normal, if everything is fine, error code otherwise + */ + virtual OFCondition handle16BitSC(DcmDataset *dataset) const; + + +}; + +#endif // I2DPLNSC_H diff --git a/dcmdata/include/dcmtk/dcmdata/libi2d/i2dplsc.h b/dcmdata/include/dcmtk/dcmdata/libi2d/i2dplsc.h new file mode 100644 index 00000000..875caaf8 --- /dev/null +++ b/dcmdata/include/dcmtk/dcmdata/libi2d/i2dplsc.h @@ -0,0 +1,71 @@ +/* + * + * Copyright (C) 2001-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Michael Onken + * + * Purpose: Class for conversion of image file into DICOM SC Image Storage + * + */ + +#ifndef I2DPLSC_H +#define I2DPLSC_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmdata/libi2d/i2doutpl.h" + +class DCMTK_I2D_EXPORT I2DOutputPlugSC : public I2DOutputPlug +{ + +public: + + /** Constructor, initializes member variables with standard values + * @return none + */ + I2DOutputPlugSC(); + + /** Virtual function that returns a short name of the plugin. + * @return The name of the plugin + */ + virtual OFString ident(); + + /** Overwrites function from base class. Returns the Storage SOP class + * written by this plugin + * @param suppSOPs - [out] List of UIDS representing SOP classes supported + * by this plugin + * @return none + */ + virtual void supportedSOPClassUIDs(OFList& suppSOPs); + + /** Outputs SOP class specific information into dataset + * @param dataset - [in/out] Dataset to write to + * @return EC_Normal if successful, error otherwise + */ + virtual OFCondition convert(DcmDataset &dataset) const; + + /** Do some completeness / validity checks. Should be called when + * dataset is completed and is about to be saved. + * @param dataset - [in] The dataset to check + * @return Error string if error occurs, empty string otherwise + */ + virtual OFString isValid(DcmDataset& dataset) const; + + /** Virtual Destructor, clean up memory + * @return none + */ + virtual ~I2DOutputPlugSC(); + +}; + +#endif // I2DPLSC_H diff --git a/dcmdata/include/dcmtk/dcmdata/libi2d/i2dplvlp.h b/dcmdata/include/dcmtk/dcmdata/libi2d/i2dplvlp.h new file mode 100644 index 00000000..40f96aec --- /dev/null +++ b/dcmdata/include/dcmtk/dcmdata/libi2d/i2dplvlp.h @@ -0,0 +1,71 @@ +/* + * + * Copyright (C) 2001-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Michael Onken + * + * Purpose: Class for conversion of image file into DICOM SC Image Storage + * + */ + +#ifndef I2DPLVLP_H +#define I2DPLVLP_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmdata/libi2d/i2doutpl.h" + +class DCMTK_I2D_EXPORT I2DOutputPlugVLP : public I2DOutputPlug +{ + +public: + + /** Constructor, initializes member variables with standard values + * @return none + */ + I2DOutputPlugVLP(); + + /** Virtual function that returns a short name of the plugin. + * @return The name of the plugin + */ + virtual OFString ident(); + + /** Overwrites function from base class. Returns the Storage SOP class + * written by this plugin + * @param suppSOPs - [out] List of UIDs representing SOP classes supported by + * this plugin + * @return A string holding the Storage SOP class written by this plugin + */ + virtual void supportedSOPClassUIDs(OFList& suppSOPs); + + /** Outputs SOP class specific information into dataset + * @param dataset - [in/out] Dataset to write to + * @return EC_Normal if successful, error otherwise + */ + virtual OFCondition convert(DcmDataset &dataset) const; + + /** Do some completeness / validity checks. Should be called when + * dataset is completed and is about to be saved. + * @param dataset - [in] The dataset to check + * @return Error string if error occurs, empty string else + */ + virtual OFString isValid(DcmDataset& dataset) const; + + /** Virtual Destructor, clean up memory + * @return none + */ + virtual ~I2DOutputPlugVLP(); + +}; + +#endif // I2DPLVLP_H diff --git a/dcmdata/include/dcmtk/dcmdata/vrscan.h b/dcmdata/include/dcmtk/dcmdata/vrscan.h new file mode 100644 index 00000000..d0bce8e4 --- /dev/null +++ b/dcmdata/include/dcmtk/dcmdata/vrscan.h @@ -0,0 +1,40 @@ +/* + * + * Copyright (C) 2010-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Uli Schlachter + * + * Purpose: Interface to the VR scanner. + * + */ + + +#ifndef VRSCAN_H +#define VRSCAN_H + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/ofstd/ofstring.h" + +#include "dcmtk/dcmdata/dcdefine.h" + +class DCMTK_DCMDATA_EXPORT vrscan +{ +public: + static int scan(const OFString& vr, const OFString& value); +private: + static char* makeBuffer(const OFString& vr, const OFString& value, size_t& size); +}; + +#endif // VRSCAN_H diff --git a/dcmdata/libi2d/CMakeLists.txt b/dcmdata/libi2d/CMakeLists.txt new file mode 100644 index 00000000..4d66fc42 --- /dev/null +++ b/dcmdata/libi2d/CMakeLists.txt @@ -0,0 +1,4 @@ +# create library from source files +DCMTK_ADD_LIBRARY(i2d i2d i2dplvlp i2djpgs i2dbmps i2dplsc i2dplnsc) + +DCMTK_TARGET_LINK_MODULES(i2d dcmdata) diff --git a/dcmdata/libi2d/Makefile.dep b/dcmdata/libi2d/Makefile.dep new file mode 100644 index 00000000..950b0c96 --- /dev/null +++ b/dcmdata/libi2d/Makefile.dep @@ -0,0 +1,317 @@ +i2d.o: i2d.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmdata/libi2d/i2d.h \ + ../include/dcmtk/dcmdata/libi2d/i2doutpl.h \ + ../include/dcmtk/dcmdata/dcdatset.h ../include/dcmtk/dcmdata/dcitem.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../include/dcmtk/dcmdata/dcdefine.h ../include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../include/dcmtk/dcmdata/dcerror.h ../include/dcmtk/dcmdata/dcxfer.h \ + ../include/dcmtk/dcmdata/dcvr.h ../include/dcmtk/dcmdata/dctag.h \ + ../include/dcmtk/dcmdata/dctagkey.h ../include/dcmtk/dcmdata/dcstack.h \ + ../include/dcmtk/dcmdata/dclist.h ../include/dcmtk/dcmdata/dcpcache.h \ + ../include/dcmtk/dcmdata/dcelem.h \ + ../include/dcmtk/dcmdata/libi2d/i2define.h \ + ../include/dcmtk/dcmdata/libi2d/i2dimgs.h \ + ../include/dcmtk/dcmdata/dcpixel.h ../include/dcmtk/dcmdata/dcvrpobw.h \ + ../include/dcmtk/dcmdata/dcvrobow.h ../include/dcmtk/dcmdata/dcpxitem.h \ + ../include/dcmtk/dcmdata/dcofsetl.h ../include/dcmtk/dcmdata/dcfilefo.h \ + ../include/dcmtk/dcmdata/dcsequen.h ../include/dcmtk/dcmdata/dcdeftag.h \ + ../include/dcmtk/dcmdata/dcuid.h ../include/dcmtk/dcmdata/dcpixseq.h \ + ../include/dcmtk/dcmdata/dcpath.h +i2dbmps.o: i2dbmps.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmdata/libi2d/i2dbmps.h \ + ../include/dcmtk/dcmdata/libi2d/i2dimgs.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../include/dcmtk/dcmdata/dcxfer.h ../include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../include/dcmtk/dcmdata/dcdefine.h ../include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../include/dcmtk/dcmdata/libi2d/i2define.h \ + ../include/dcmtk/dcmdata/dcerror.h \ + ../include/dcmtk/dcmdata/libi2d/i2doutpl.h \ + ../include/dcmtk/dcmdata/dcdatset.h ../include/dcmtk/dcmdata/dcitem.h \ + ../include/dcmtk/dcmdata/dcobject.h ../include/dcmtk/dcmdata/dctag.h \ + ../include/dcmtk/dcmdata/dctagkey.h ../include/dcmtk/dcmdata/dcstack.h \ + ../include/dcmtk/dcmdata/dclist.h ../include/dcmtk/dcmdata/dcpcache.h \ + ../include/dcmtk/dcmdata/dcelem.h +i2djpgs.o: i2djpgs.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmdata/libi2d/i2djpgs.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../include/dcmtk/dcmdata/libi2d/i2dimgs.h \ + ../include/dcmtk/dcmdata/dcxfer.h ../include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../include/dcmtk/dcmdata/dcdefine.h ../include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../include/dcmtk/dcmdata/libi2d/i2define.h \ + ../include/dcmtk/dcmdata/libi2d/i2doutpl.h \ + ../include/dcmtk/dcmdata/dcdatset.h ../include/dcmtk/dcmdata/dcitem.h \ + ../include/dcmtk/dcmdata/dcobject.h ../include/dcmtk/dcmdata/dcerror.h \ + ../include/dcmtk/dcmdata/dctag.h ../include/dcmtk/dcmdata/dctagkey.h \ + ../include/dcmtk/dcmdata/dcstack.h ../include/dcmtk/dcmdata/dclist.h \ + ../include/dcmtk/dcmdata/dcpcache.h ../include/dcmtk/dcmdata/dcelem.h +i2dplnsc.o: i2dplnsc.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmdata/libi2d/i2dplnsc.h \ + ../include/dcmtk/dcmdata/libi2d/i2doutpl.h \ + ../include/dcmtk/dcmdata/dcdatset.h ../include/dcmtk/dcmdata/dcitem.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../include/dcmtk/dcmdata/dcdefine.h ../include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../include/dcmtk/dcmdata/dcerror.h ../include/dcmtk/dcmdata/dcxfer.h \ + ../include/dcmtk/dcmdata/dcvr.h ../include/dcmtk/dcmdata/dctag.h \ + ../include/dcmtk/dcmdata/dctagkey.h ../include/dcmtk/dcmdata/dcstack.h \ + ../include/dcmtk/dcmdata/dclist.h ../include/dcmtk/dcmdata/dcpcache.h \ + ../include/dcmtk/dcmdata/dcelem.h \ + ../include/dcmtk/dcmdata/libi2d/i2define.h \ + ../include/dcmtk/dcmdata/dcdeftag.h ../include/dcmtk/dcmdata/dcuid.h +i2dplsc.o: i2dplsc.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmdata/libi2d/i2dplsc.h \ + ../include/dcmtk/dcmdata/libi2d/i2doutpl.h \ + ../include/dcmtk/dcmdata/dcdatset.h ../include/dcmtk/dcmdata/dcitem.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../include/dcmtk/dcmdata/dcdefine.h ../include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../include/dcmtk/dcmdata/dcerror.h ../include/dcmtk/dcmdata/dcxfer.h \ + ../include/dcmtk/dcmdata/dcvr.h ../include/dcmtk/dcmdata/dctag.h \ + ../include/dcmtk/dcmdata/dctagkey.h ../include/dcmtk/dcmdata/dcstack.h \ + ../include/dcmtk/dcmdata/dclist.h ../include/dcmtk/dcmdata/dcpcache.h \ + ../include/dcmtk/dcmdata/dcelem.h \ + ../include/dcmtk/dcmdata/libi2d/i2define.h \ + ../include/dcmtk/dcmdata/dcdeftag.h ../include/dcmtk/dcmdata/dcuid.h +i2dplvlp.o: i2dplvlp.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmdata/libi2d/i2dplvlp.h \ + ../include/dcmtk/dcmdata/libi2d/i2doutpl.h \ + ../include/dcmtk/dcmdata/dcdatset.h ../include/dcmtk/dcmdata/dcitem.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../include/dcmtk/dcmdata/dcdefine.h ../include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../include/dcmtk/dcmdata/dcerror.h ../include/dcmtk/dcmdata/dcxfer.h \ + ../include/dcmtk/dcmdata/dcvr.h ../include/dcmtk/dcmdata/dctag.h \ + ../include/dcmtk/dcmdata/dctagkey.h ../include/dcmtk/dcmdata/dcstack.h \ + ../include/dcmtk/dcmdata/dclist.h ../include/dcmtk/dcmdata/dcpcache.h \ + ../include/dcmtk/dcmdata/dcelem.h \ + ../include/dcmtk/dcmdata/libi2d/i2define.h \ + ../include/dcmtk/dcmdata/dcdeftag.h ../include/dcmtk/dcmdata/dcuid.h diff --git a/dcmdata/libi2d/Makefile.in b/dcmdata/libi2d/Makefile.in new file mode 100644 index 00000000..eaecdbdf --- /dev/null +++ b/dcmdata/libi2d/Makefile.in @@ -0,0 +1,56 @@ +# +# Makefile for dcmdata/libi2d +# + +@SET_MAKE@ + +SHELL = /bin/sh +VPATH = @srcdir@:@top_srcdir@/include:@top_srcdir@/@configdir@/include +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +configdir = @top_srcdir@/@configdir@ + +include $(configdir)/@common_makefile@ + +ofstddir = $(top_srcdir)/../ofstd +oflogdir = $(top_srcdir)/../oflog +dcmdatadir = $(top_srcdir)/../dcmdata + +LOCALINCLUDES = -I$(ofstddir)/include -I$(dcmdatadir)/include -I$(oflogdir)/include +LOCALDEFS = + +objs = i2d.o i2dplvlp.o i2djpgs.o i2dbmps.o i2dplsc.o i2dplnsc.o + +library = libi2d.$(LIBEXT) + + +all: $(library) + +install: $(library) + $(configdir)/mkinstalldirs $(DESTDIR)$(libdir) + $(INSTALL_DATA) $(library) $(DESTDIR)$(libdir)/$(library) + $(RANLIB) $(DESTDIR)$(libdir)/$(library) + + +install-lib: $(library) + $(configdir)/mkinstalldirs $(DESTDIR)$(libdir) + $(INSTALL_DATA) $(library) $(DESTDIR)$(libdir)/$(library) + $(RANLIB) $(DESTDIR)$(libdir)/$(library) + + +$(library): $(objs) + $(AR) $(ARFLAGS) $@ $(objs) + $(RANLIB) $@ + + +clean: + rm -f $(objs) $(library) $(TRASH) + +distclean: + rm -f $(objs) $(library) $(DISTTRASH) + + +dependencies: + $(CXX) -MM $(defines) $(includes) $(CPPFLAGS) $(CXXFLAGS) *.cc > $(DEP) + +include $(DEP) diff --git a/dcmdata/libi2d/i2d.cc b/dcmdata/libi2d/i2d.cc new file mode 100644 index 00000000..89adf213 --- /dev/null +++ b/dcmdata/libi2d/i2d.cc @@ -0,0 +1,733 @@ +/* + * + * Copyright (C) 2007-2015, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Michael Onken + * + * Purpose: Implements utility for converting standard image formats to DICOM + * + */ + + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/dcmdata/libi2d/i2d.h" +#include "dcmtk/dcmdata/dcpxitem.h" +#include "dcmtk/dcmdata/dcfilefo.h" /* for DcmFileFormat */ +#include "dcmtk/dcmdata/dcdeftag.h" /* for DCM_ defines */ +#include "dcmtk/dcmdata/dcuid.h" /* for SITE_SERIES_UID_ROOT */ +#include "dcmtk/dcmdata/dcpixseq.h" /* for DcmPixelSequence */ +#include "dcmtk/dcmdata/dcpath.h" /* for override keys */ + +OFLogger DCM_dcmdataLibi2dLogger = OFLog::getLogger("dcmtk.dcmdata.libi2d"); + + +Image2Dcm::Image2Dcm() : m_overrideKeys(), m_templateFile(""), + m_readStudyLevel(OFFalse), m_readSeriesLevel(OFFalse), m_studySeriesFile(), + m_incInstNoFromFile(OFFalse), m_disableAttribChecks(OFFalse), + m_inventMissingType2Attribs(OFTrue), m_inventMissingType1Attribs(OFFalse), + m_insertLatin1(OFTrue) +{ + +} + + +OFCondition Image2Dcm::convert(I2DImgSource *inputPlug, + I2DOutputPlug *outPlug, + DcmDataset*& resultDset, + E_TransferSyntax& proposedTS) + +{ + if (!inputPlug || !outPlug) + return EC_IllegalParameter; + + OFCondition cond; + DCMDATA_LIBI2D_DEBUG("Image2Dcm: Starting conversion of file: " << inputPlug->getImageFile()); + + // If specified, copy DICOM template file to export file + if (!m_templateFile.empty()) + { + DcmFileFormat dcmff; + cond = dcmff.loadFile(m_templateFile.c_str()); + if (cond.bad()) + return cond; + // remove problematic attributes from dataset + cleanupTemplate(dcmff.getDataset()); + // copy from input file + resultDset = new DcmDataset(*(dcmff.getDataset())); + } + else // otherwise, start with an empty DICOM file + resultDset = new DcmDataset(); + if (!resultDset) + return EC_MemoryExhausted; + + // Read patient and study or series information if desired and write to export file + if (m_readStudyLevel || m_readSeriesLevel) + { + cond = applyStudyOrSeriesFromFile(resultDset); + if (cond.bad()) + { + delete resultDset; resultDset = NULL; + return cond; + } + } + + // Increment instance number + if (m_incInstNoFromFile) + { + cond = incrementInstanceNumber(resultDset); + if (cond.bad()) + { + delete resultDset; resultDset = NULL; + return cond; + } + } + + // Insert Latin 1 as standard character set if desired + if (m_insertLatin1) + cond = insertLatin1(resultDset); + if (cond.bad()) + return cond; + + // Generate and insert UIDs as necessary + generateUIDs(resultDset); + + // Read and insert pixel data + cond = readAndInsertPixelData(inputPlug, resultDset, proposedTS); + if (cond.bad()) + { + delete resultDset; resultDset = NULL; + return cond; + } + + // Insert Lossy Image Compression and Lossy Image Compression Method attributes if necessary + OFBool srcIsLossy = OFFalse; OFString comprMethod; + if (inputPlug->getLossyComprInfo(srcIsLossy, comprMethod).good()) //TODO) + { + if (srcIsLossy) + { + cond = resultDset->putAndInsertOFStringArray(DCM_LossyImageCompression, "01"); + if (cond.good() && !comprMethod.empty()) + cond = resultDset->putAndInsertOFStringArray(DCM_LossyImageCompressionMethod, comprMethod); + if (cond.bad()) return makeOFCondition(OFM_dcmdata, 18, OF_error, "Unable to write attribute Lossy Image Compression and/or Lossy Image Compression Method to result dataset"); + } + } + else + DCMDATA_LIBI2D_DEBUG("Image2Dcm: No information regarding lossy compression available"); + + // Insert SOP Class specific attributes (and values) + cond = outPlug->convert(*resultDset); + if (cond.bad()) + { + delete resultDset; resultDset = NULL; + return cond; + } + + // At last, apply override keys on dataset + applyOverrideKeys(resultDset); + + // Do some very basic attribute checking (e. g. existence (type 2) and values (type 1)) + if (!m_disableAttribChecks) + { + OFString err; + err = isValid(*resultDset); + err += outPlug->isValid(*resultDset); + if (!err.empty()) + { + delete resultDset; resultDset = NULL; + return makeOFCondition(OFM_dcmdata, 18, OF_error, err.c_str()); + } + } + + return EC_Normal; +} + + +OFCondition Image2Dcm::insertLatin1(DcmDataset *outputDset) +{ + if (outputDset == NULL) + return EC_IllegalParameter; + return outputDset->putAndInsertString(DCM_SpecificCharacterSet, "ISO_IR 100"); +} + + +void Image2Dcm::cleanupTemplate(DcmDataset *targetDset) +{ + if (!targetDset) + return; + // Remove any existing image pixel module attribute + targetDset->findAndDeleteElement(DCM_PixelDataProviderURL); + targetDset->findAndDeleteElement(DCM_PhotometricInterpretation); + targetDset->findAndDeleteElement(DCM_SamplesPerPixel); + targetDset->findAndDeleteElement(DCM_Rows); + targetDset->findAndDeleteElement(DCM_Columns); + targetDset->findAndDeleteElement(DCM_BitsAllocated); + targetDset->findAndDeleteElement(DCM_BitsStored); + targetDset->findAndDeleteElement(DCM_HighBit); + targetDset->findAndDeleteElement(DCM_PixelRepresentation); + targetDset->findAndDeleteElement(DCM_PixelData); + targetDset->findAndDeleteElement(DCM_PlanarConfiguration); + targetDset->findAndDeleteElement(DCM_PixelAspectRatio); + targetDset->findAndDeleteElement(DCM_SmallestImagePixelValue); + targetDset->findAndDeleteElement(DCM_LargestImagePixelValue); + targetDset->findAndDeleteElement(DCM_RedPaletteColorLookupTableDescriptor); + targetDset->findAndDeleteElement(DCM_GreenPaletteColorLookupTableDescriptor); + targetDset->findAndDeleteElement(DCM_BluePaletteColorLookupTableDescriptor); + targetDset->findAndDeleteElement(DCM_RedPaletteColorLookupTableData); + targetDset->findAndDeleteElement(DCM_GreenPaletteColorLookupTableData); + targetDset->findAndDeleteElement(DCM_BluePaletteColorLookupTableData); + targetDset->findAndDeleteElement(DCM_ICCProfile); + // Remove SOP Class / Instance information + targetDset->findAndDeleteElement(DCM_SOPClassUID); + targetDset->findAndDeleteElement(DCM_SOPInstanceUID); + +} + + +OFCondition Image2Dcm::applyStudyOrSeriesFromFile(DcmDataset *targetDset) +{ + DCMDATA_LIBI2D_DEBUG("Image2Dcm: Applying study and/or series information from file"); + if ( (!m_readSeriesLevel && !m_readStudyLevel) || m_studySeriesFile.empty() ) + return EC_IllegalCall; + DcmFileFormat dcmff; + OFString errMsg; + OFCondition cond; + + // Open DICOM file to read patient/study/series information from + cond = dcmff.loadFile(m_studySeriesFile.c_str()); + if (cond.bad()) + { + errMsg = "Error: Unable to open study / series file "; errMsg += m_studySeriesFile; + return makeOFCondition(OFM_dcmdata, 18, OF_error, errMsg.c_str()); + } + + DcmDataset *srcDset = NULL; + srcDset = dcmff.getDataset(); + if (srcDset == NULL) + return EC_IllegalCall; + + // Patient level attributes (type 2 - if value cannot be read, insert empty value + OFString value; + srcDset->findAndGetOFString(DCM_PatientName, value); + cond = targetDset->putAndInsertOFStringArray(DCM_PatientName, value); + if (cond.bad()) + return makeOFCondition(OFM_dcmdata, 18, OF_error, "Unable to write Patient's Name to file"); + value.clear(); + + srcDset->findAndGetOFString(DCM_PatientID, value); + cond = targetDset->putAndInsertOFStringArray(DCM_PatientID, value); + if (cond.bad()) + return makeOFCondition(OFM_dcmdata, 18, OF_error, "Unable to write Patient ID to file"); + value.clear(); + + srcDset->findAndGetOFString(DCM_PatientSex, value); + cond = targetDset->putAndInsertOFStringArray(DCM_PatientSex, value); + if (cond.bad()) + return makeOFCondition(OFM_dcmdata, 18, OF_error, "Unable to write Patient's Sex to file"); + value.clear(); + + srcDset->findAndGetOFString(DCM_PatientBirthDate, value); + cond = targetDset->putAndInsertOFStringArray(DCM_PatientBirthDate, value); + if (cond.bad()) + return makeOFCondition(OFM_dcmdata, 18, OF_error, "Unable to write Patient's Birth Date to file"); + value.clear(); + + srcDset->findAndGetOFString(DCM_SpecificCharacterSet, value); + cond = targetDset->putAndInsertOFStringArray(DCM_SpecificCharacterSet, value); + if (cond.bad()) + return makeOFCondition(OFM_dcmdata, 18, OF_error, "Unable to write Specific Character Set to file"); + value.clear(); + + // Study level attributes (type 2 except Study Instance UID) + cond = srcDset->findAndGetOFString(DCM_StudyInstanceUID, value); + if (cond.bad()) + return makeOFCondition(OFM_dcmdata, 18, OF_error, "Unable to read Study Instance UID (type 1) from file"); + cond = targetDset->putAndInsertOFStringArray(DCM_StudyInstanceUID, value); + if (cond.bad()) + return makeOFCondition(OFM_dcmdata, 18, OF_error, "Unable to write Study Instance UID to file"); + value.clear(); + + srcDset->findAndGetOFString(DCM_StudyDate, value); + cond = targetDset->putAndInsertOFStringArray(DCM_StudyDate, value); + if (cond.bad()) + return makeOFCondition(OFM_dcmdata, 18, OF_error, "Unable to write Study Date to file"); + value.clear(); + + srcDset->findAndGetOFString(DCM_StudyTime, value); + cond = targetDset->putAndInsertOFStringArray(DCM_StudyTime, value); + if (cond.bad()) + return makeOFCondition(OFM_dcmdata, 18, OF_error, "Unable to write Study Time to file"); + value.clear(); + + srcDset->findAndGetOFString(DCM_ReferringPhysicianName, value); + cond = targetDset->putAndInsertOFStringArray(DCM_ReferringPhysicianName, value); + if (cond.bad()) + return makeOFCondition(OFM_dcmdata, 18, OF_error, "Unable to write Referring Physician's Name to file"); + value.clear(); + + srcDset->findAndGetOFString(DCM_StudyID, value); + cond = targetDset->putAndInsertOFStringArray(DCM_StudyID, value); + if (cond.bad()) + return makeOFCondition(OFM_dcmdata, 18, OF_error, "Unable to write Study ID to file"); + value.clear(); + + srcDset->findAndGetOFString(DCM_AccessionNumber, value); + cond = targetDset->putAndInsertOFStringArray(DCM_AccessionNumber, value); + if (cond.bad()) + return makeOFCondition(OFM_dcmdata, 18, OF_error, "Unable to trite Accession Number to file"); + value.clear(); + + // Series Level attributes (type 2 except Series Instance UID which is type 1) + if (m_readSeriesLevel) + { + // General Series Module attributes + cond = srcDset->findAndGetOFString(DCM_SeriesInstanceUID, value); + if (cond.bad()) + return makeOFCondition(OFM_dcmdata, 18, OF_error, "Unable to read Series Instance UID (type 1) from file"); + cond = targetDset->putAndInsertOFStringArray(DCM_SeriesInstanceUID, value); + if (cond.bad()) + return makeOFCondition(OFM_dcmdata, 18, OF_error, "Unable to write Series Instance UID to file"); + value.clear(); + + srcDset->findAndGetOFString(DCM_SeriesNumber, value); + cond = targetDset->putAndInsertOFStringArray(DCM_SeriesNumber, value); + if (cond.bad()) + return makeOFCondition(OFM_dcmdata, 18, OF_error, "Unable to write Series Number to file"); + value.clear(); + + // General Equipment Module attributes + srcDset->findAndGetOFString(DCM_Manufacturer, value); + cond = targetDset->putAndInsertOFStringArray(DCM_Manufacturer, value); + if (cond.bad()) + return makeOFCondition(OFM_dcmdata, 18, OF_error, "Unable to write Manufacturer to file"); + value.clear(); + } + + return EC_Normal; +} + + +OFCondition Image2Dcm::incrementInstanceNumber(DcmDataset *targetDset) +{ + // Read and increment Instance Number if desired + if (m_incInstNoFromFile) + { + DCMDATA_LIBI2D_DEBUG("Image2Dcm: Trying to read and increment instance number"); + Sint32 instanceNumber; + if ( targetDset->findAndGetSint32(DCM_InstanceNumber, instanceNumber).good() ) + { + instanceNumber++; + char buf[100]; + sprintf(buf, "%ld", OFstatic_cast(long, instanceNumber)); + OFCondition cond = targetDset->putAndInsertOFStringArray(DCM_InstanceNumber, buf); + if (cond.bad()) + return makeOFCondition(OFM_dcmdata, 18, OF_error, "Unable write Instance Number to dataset"); + } + else + return makeOFCondition(OFM_dcmdata, 18, OF_error, "Unable to read Instance Number from dataset"); + } + return EC_Normal; +} + + +OFCondition Image2Dcm::generateUIDs(DcmDataset *dset) +{ + OFString value; + OFCondition cond; + + DCMDATA_LIBI2D_DEBUG("Image2Dcm: Generate and insert new UIDs if necessary"); + // Generate and write Series Instance UID if not already present + if (!m_readSeriesLevel) + { + cond = dset->findAndGetOFString(DCM_SeriesInstanceUID, value); + if (cond.bad() || value.empty()) + { + char newUID[100]; + dcmGenerateUniqueIdentifier(newUID, SITE_SERIES_UID_ROOT); + cond = dset->putAndInsertOFStringArray(DCM_SeriesInstanceUID, newUID); + if (cond.bad()) + return makeOFCondition(OFM_dcmdata, 18, OF_error, "Unable to write Series Instance UID to file"); + } + value.clear(); + } + + // Generate and write Study Instance UID if not already present + if (!m_readStudyLevel) + { + cond = dset->findAndGetOFString(DCM_StudyInstanceUID, value); + if (cond.bad() || value.empty()) + { + char newUID[100]; + dcmGenerateUniqueIdentifier(newUID, SITE_STUDY_UID_ROOT); + cond = dset->putAndInsertOFStringArray(DCM_StudyInstanceUID, newUID); + if (cond.bad()) + return makeOFCondition(OFM_dcmdata, 18, OF_error, "Unable to write Study Instance UID to file"); + } + value.clear(); + } + + // Generate SOP Instance UID if not already present + cond = dset->findAndGetOFString(DCM_SOPInstanceUID, value); + if (cond.bad() || value.empty()) + { + char newUID[100]; + dcmGenerateUniqueIdentifier(newUID, SITE_INSTANCE_UID_ROOT); + cond = dset->putAndInsertOFStringArray(DCM_SOPInstanceUID, newUID); + if (cond.bad()) + return makeOFCondition(OFM_dcmdata, 18, OF_error, "Unable to write SOP Instance UID to file"); + } + + return EC_Normal; +} + + +void Image2Dcm::setISOLatin1(OFBool insLatin1) +{ + m_insertLatin1 = insLatin1; +} + + +OFCondition Image2Dcm::insertEncapsulatedPixelData(DcmDataset* dset, + char *pixData, + Uint32 length, + const E_TransferSyntax& outputTS) const +{ + OFCondition cond; + + DCMDATA_LIBI2D_DEBUG("Image2Dcm: Storing imported pixel data to DICOM file"); + // create initial pixel sequence + DcmPixelSequence* pixelSequence = new DcmPixelSequence(DCM_PixelSequenceTag); + if (pixelSequence == NULL) + return EC_MemoryExhausted; + + // insert empty offset table into sequence + DcmPixelItem *offsetTable = new DcmPixelItem(DCM_PixelItemTag); + if (offsetTable == NULL) + { + delete pixelSequence; pixelSequence = NULL; + return EC_MemoryExhausted; + } + cond = pixelSequence->insert(offsetTable); + if (cond.bad()) + { + delete offsetTable; offsetTable = NULL; + delete pixelSequence; pixelSequence = NULL; + return cond; + } + + // store compressed frame into pixel sequence + DcmOffsetList dummyList; + cond = pixelSequence->storeCompressedFrame(dummyList, OFreinterpret_cast(Uint8*,pixData), length, 0); + // storeCompressedFrame(..) does a deep copy, so the pixData memory can be freed now + delete[] pixData; + if (cond.bad()) + { + delete pixelSequence; pixelSequence = NULL; + return cond; + } + + // insert pixel data attribute incorporating pixel sequence into dataset + DcmPixelData *pixelData = new DcmPixelData(DCM_PixelData); + if (pixelData == NULL) + { + delete pixelSequence; pixelSequence = NULL; + return EC_MemoryExhausted; + } + /* tell pixel data element that this is the original presentation of the pixel data + * pixel data and how it compressed + */ + pixelData->putOriginalRepresentation(outputTS, NULL, pixelSequence); + cond = dset->insert(pixelData); + if (cond.bad()) + { + delete pixelData; pixelData = NULL; // also deletes contained pixel sequence + return cond; + } + + return EC_Normal; +} + + +OFCondition Image2Dcm::readAndInsertPixelData(I2DImgSource* imgSource, + DcmDataset* dset, + E_TransferSyntax& outputTS) +{ + Uint16 samplesPerPixel, rows, cols, bitsAlloc, bitsStored, highBit, pixelRepr, planConf; + Uint16 pixAspectH =1; Uint16 pixAspectV = 1; + OFString photoMetrInt; + outputTS = EXS_Unknown; + char* pixData = NULL; + Uint32 length; + + OFCondition cond = imgSource->readPixelData(rows, cols, + samplesPerPixel, photoMetrInt, bitsAlloc, bitsStored, highBit, pixelRepr, + planConf, pixAspectH, pixAspectV, pixData, length, outputTS); + + if (cond.bad()) + return cond; + + DcmXfer transport(outputTS); + if (transport.isEncapsulated()) + insertEncapsulatedPixelData(dset, pixData, length, outputTS); + else + { + /* Not encapsulated */ + dset->putAndInsertUint8Array(DCM_PixelData, OFreinterpret_cast(Uint8*, pixData), length); + delete[] pixData; + } + + DCMDATA_LIBI2D_DEBUG("Image2Dcm: Inserting Image Pixel module information"); + + cond = dset->putAndInsertUint16(DCM_SamplesPerPixel, samplesPerPixel); + if (cond.bad()) + return cond; + + cond = dset->putAndInsertOFStringArray(DCM_PhotometricInterpretation, photoMetrInt); + if (cond.bad()) + return cond; + + // Should only be written if Samples per Pixel > 1 + if (samplesPerPixel > 1) + { + cond = dset->putAndInsertUint16(DCM_PlanarConfiguration, planConf); + if (cond.bad()) + return cond; + } + + cond = dset->putAndInsertUint16(DCM_Rows, rows); + if (cond.bad()) + return cond; + + cond = dset->putAndInsertUint16(DCM_Columns, cols); + if (cond.bad()) + return cond; + + cond = dset->putAndInsertUint16(DCM_BitsAllocated, bitsAlloc); + if (cond.bad()) + return cond; + + cond = dset->putAndInsertUint16(DCM_BitsStored, bitsStored); + if (cond.bad()) + return cond; + + cond = dset->putAndInsertUint16(DCM_HighBit, highBit); + if (cond.bad()) + return cond; + + if ( pixAspectH != pixAspectV ) + { + char buf[200]; + int err = sprintf(buf, "%u\\%u", pixAspectV, pixAspectH); + if (err == -1) return EC_IllegalCall; + cond = dset->putAndInsertOFStringArray(DCM_PixelAspectRatio, buf); + if (cond.bad()) + return cond; + } + + return dset->putAndInsertUint16(DCM_PixelRepresentation, pixelRepr); +} + + +OFString Image2Dcm::isValid(DcmDataset& dset) const +{ + DCMDATA_LIBI2D_DEBUG("Image2Dcm: Checking validity of DICOM output dataset"); + OFString dummy, err; OFCondition cond; + // General Patient module attributes + err += checkAndInventType2Attrib(DCM_PatientName, &dset); + err += checkAndInventType2Attrib(DCM_PatientSex, &dset); + err += checkAndInventType2Attrib(DCM_PatientBirthDate, &dset); + err += checkAndInventType2Attrib(DCM_PatientID, &dset); + + // General Study module attributes + err += checkAndInventType1Attrib(DCM_StudyInstanceUID, &dset); + err += checkAndInventType2Attrib(DCM_StudyDate, &dset); + err += checkAndInventType2Attrib(DCM_StudyTime, &dset); + err += checkAndInventType2Attrib(DCM_ReferringPhysicianName, &dset); + err += checkAndInventType2Attrib(DCM_StudyID, &dset); + err += checkAndInventType2Attrib(DCM_AccessionNumber, &dset); + + // General Series module attributes + err += checkAndInventType1Attrib(DCM_SeriesInstanceUID, &dset); + err += checkAndInventType2Attrib(DCM_SeriesNumber, &dset); + err += checkAndInventType2Attrib(DCM_InstanceNumber, &dset); + + // General Image module attributes + /* Patient Orientation is of type 2C and must be written if not + Image Orientation (Patient) (0020,0037) and Image Position (Patient) + are required for the IOD. The current output IODs (SC, new SC, VLP) + therefore need Patient Orientation. Make sure any new output plugin + takes care about this attribute + */ + err += checkAndInventType2Attrib(DCM_PatientOrientation, &dset); + + // Image Pixel Module + err += checkAndInventType1Attrib(DCM_Rows, &dset); + err += checkAndInventType1Attrib(DCM_Columns, &dset); + err += checkAndInventType1Attrib(DCM_SamplesPerPixel, &dset); + err += checkAndInventType1Attrib(DCM_PhotometricInterpretation, &dset); + err += checkAndInventType1Attrib(DCM_BitsAllocated, &dset); + err += checkAndInventType1Attrib(DCM_BitsStored, &dset); + err += checkAndInventType1Attrib(DCM_HighBit, &dset); + err += checkAndInventType1Attrib(DCM_PixelRepresentation, &dset); + err += checkAndInventType1Attrib(DCM_SOPInstanceUID, &dset); + + return err; +} + + + +void Image2Dcm::setSeriesFrom(const OFString& file) +{ + m_readSeriesLevel = OFTrue; + m_studySeriesFile = file; +} + + +void Image2Dcm::setStudyFrom(const OFString& file) +{ + m_readStudyLevel = OFTrue; + m_studySeriesFile = file; +} + + +void Image2Dcm::setValidityChecking(OFBool doChecks, + OFBool insertMissingType2, + OFBool inventMissingType1) +{ + m_disableAttribChecks = !doChecks; + m_inventMissingType2Attribs = insertMissingType2; + m_inventMissingType1Attribs = inventMissingType1; +} + + +void Image2Dcm::setTemplateFile(const OFString& file) +{ + m_templateFile = file; +} + + + +void Image2Dcm::setIncrementInstanceNumber(OFBool incInstNo) +{ + m_incInstNoFromFile = incInstNo; +} + + +void Image2Dcm::setOverrideKeys(const OFList& ovkeys) +{ + OFListConstIterator(OFString) it = ovkeys.begin(); + OFListConstIterator(OFString) end = ovkeys.end(); + while (it != end) + { + m_overrideKeys.push_back(*it); + it++; + } +} + + +OFCondition Image2Dcm::applyOverrideKeys(DcmDataset *outputDset) + +{ + /* replace specific keys by those in overrideKeys, copied from findscu */ + OFListConstIterator(OFString) path = m_overrideKeys.begin(); + OFListConstIterator(OFString) endOfList = m_overrideKeys.end(); + OFCondition cond; + DcmPathProcessor proc; + while (path != endOfList) + { + cond = proc.applyPathWithValue(outputDset, *path); + if (cond.bad()) { + OFString err; + err += "Bad override key/path: "; err += *path; err += ": "; err += cond.text(); + return makeOFCondition(OFM_dcmdata, 18, OF_error, err.c_str()); + } + path++; + } + return cond; +} + + +OFString Image2Dcm::checkAndInventType1Attrib(const DcmTagKey& key, + DcmDataset* targetDset, + const OFString& defaultValue) const +{ + OFBool exists = targetDset->tagExists(key); + if (!exists) + { + OFString err = "Image2Dcm: Missing type 1 attribute: "; err += DcmTag(key).getTagName(); err += "\n"; + return err; + } + DcmElement *elem; + OFCondition cond = targetDset->findAndGetElement(key, elem); + if (cond.bad() || !elem || (elem->getLength() == 0)) + { + if (!m_inventMissingType1Attribs) + { + OFString err = "Image2Dcm: Empty value for type 1 attribute: "; + err += DcmTag(key).getTagName(); + err += "\n"; + return err; + } + // holds element to insert in item + elem = NULL; + DcmTag tag(key); OFBool wasError = OFFalse; + // if DICOM element could be created, insert in to item and modify to value + if ( newDicomElement(elem, tag).good()) + { + if (targetDset->insert(elem, OFTrue).good()) + { + if (elem->putString(defaultValue.c_str()).good()) + { + DCMDATA_LIBI2D_DEBUG("Image2Dcm: Inserting missing type 1 attribute " << tag.getTagName() + << " with value " << defaultValue); + } else wasError = OFTrue; + } else wasError = OFTrue; + } else wasError = OFTrue; + if (wasError) + { + OFString err = "Unable to insert type 1 attribute "; err += tag.getTagName(); err += " with value "; err += defaultValue; err += "\n"; + return err; + } + } + return ""; +} + + +OFString Image2Dcm::checkAndInventType2Attrib(const DcmTagKey& key, + DcmDataset* targetDset) const +{ + OFString err; + OFBool exists = targetDset->tagExists(key); + if (!exists) + { + if (m_inventMissingType2Attribs) + { + DcmTag tag(key); + DCMDATA_LIBI2D_DEBUG("Image2Dcm: Inserting missing type 2 attribute: " << tag.getTagName()); + targetDset->insertEmptyElement(tag); + } + else + { + err = "Image2Dcm: Missing type 2 attribute: "; err += DcmTag(key).getTagName(); err += "\n"; + return err; + } + } + return err; +} + + +Image2Dcm::~Image2Dcm() +{ + DCMDATA_LIBI2D_DEBUG("Freeing memory"); +} diff --git a/dcmdata/libi2d/i2dbmps.cc b/dcmdata/libi2d/i2dbmps.cc new file mode 100644 index 00000000..02a88366 --- /dev/null +++ b/dcmdata/libi2d/i2dbmps.cc @@ -0,0 +1,617 @@ +/* + * + * Copyright (C) 2009-2013, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Uli Schlachter + * + * Purpose: Class to extract pixel data and meta information from BMP file + * + */ + + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmdata/libi2d/i2dbmps.h" +#include "dcmtk/dcmdata/dcerror.h" +#include "dcmtk/dcmdata/libi2d/i2doutpl.h" + +#ifndef UINT16_MAX +/// Maximum value a Uint16 can hold +#define UINT16_MAX 65535 +#endif + +I2DBmpSource::I2DBmpSource() : bmpFile() +{ + DCMDATA_LIBI2D_DEBUG("I2DBmpSource: Plugin instantiated"); +} + + +OFString I2DBmpSource::inputFormat() const +{ + return "BMP"; +} + + +OFCondition I2DBmpSource::openFile(const OFString &filename) +{ + DCMDATA_LIBI2D_DEBUG("I2DBmpSource: Opening BMP file: " << filename); + OFCondition cond; + if (filename.empty()) + return makeOFCondition(OFM_dcmdata, 18, OF_error, "No BMP filename specified"); + + // Try to open BMP file + if ((bmpFile.fopen(filename.c_str(), "rb")) == OFFalse) + return makeOFCondition(OFM_dcmdata, 18, OF_error, "Unable to open BMP file"); + + return cond; +} + + +OFCondition I2DBmpSource::readPixelData(Uint16& rows, + Uint16& cols, + Uint16& samplesPerPixel, + OFString& photoMetrInt, + Uint16& bitsAlloc, + Uint16& bitsStored, + Uint16& highBit, + Uint16& pixelRepr, + Uint16& planConf, + Uint16& pixAspectH, + Uint16& pixAspectV, + char*& pixData, + Uint32& length, + E_TransferSyntax &ts) +{ + DCMDATA_LIBI2D_DEBUG("I2DBmpSource: Importing BMP pixel data"); + OFCondition cond = openFile(m_imageFile); + // return error if file is not open + if (cond.bad()) + { + closeFile(); + return cond; + } + + /* Read both file headers */ + Uint32 dataOffset; + cond = readFileHeader(dataOffset); + if (cond.bad()) + { + closeFile(); + return cond; + } + + Uint16 width, height; + Uint16 bpp, colors; + OFBool isTopDown = OFFalse; /* Most BMPs are stored bottom-up */ + cond = readBitmapHeader(width, height, bpp, isTopDown, colors); + if (cond.bad()) + { + closeFile(); + return cond; + } + + Uint32 *palette = NULL; + cond = readColorPalette(colors, palette); + if (cond.bad()) + { + closeFile(); + return cond; + } + + /* Now jump to the bitmap data... */ + if (bmpFile.fseek(dataOffset, SEEK_SET) != 0) + return EC_EndOfStream; + + /* ...and read the "real" image data */ + char *data; + Uint32 data_length; + cond = readBitmapData(width, height, bpp, isTopDown, colors, palette, data, data_length); + + if (palette) + delete[] palette; + + if (cond.bad()) + { + closeFile(); + return cond; + } + + /* Now we got all the info that we need, return it to caller */ + + rows = height; + cols = width; + samplesPerPixel = 3; /* 24 bpp */ + + bitsAlloc = 8; + bitsStored = 8; + highBit = 7; + photoMetrInt = "RGB"; + planConf = 0; /* For each pixel we save rgb in that order */ + pixData = data; + length = data_length; + pixAspectH = pixAspectV = 1; + pixelRepr = 0; + ts = EXS_LittleEndianExplicit; + + return cond; +} + + +OFCondition I2DBmpSource::readFileHeader(Uint32 &offset) +{ + Uint16 magic; + if (readWord(magic) != 0) + return EC_EndOfStream; + + /* ASCII "BM", decimal 19778 */ + if (magic != 19778) + return makeOFCondition(OFM_dcmdata, 18, OF_error, "Not a BMP file - invalid header"); + + /* Skip over two uninteresting entries */ + if (bmpFile.fseek(8, SEEK_CUR) != 0) + return makeOFCondition(OFM_dcmdata, 18, OF_error, "Not a BMP file - invalid header"); + + if (readDWord(offset) != 0) + return EC_EndOfStream; + + DCMDATA_LIBI2D_DEBUG("I2DBmpSource: BMP data at file offset: " << offset); + + return EC_Normal; +} + + +OFCondition I2DBmpSource::readBitmapHeader(Uint16 &width, + Uint16 &height, + Uint16 &bpp, + OFBool &isTopDown, + Uint16 &colors) +{ + Uint16 tmp_word; + Uint32 tmp_dword; + + /* 40 is the size of the bitmap info header */ + if (readDWord(tmp_dword) != 0 || tmp_dword != 40) + return makeOFCondition(OFM_dcmdata, 18, OF_error, "Not a BMP file - invalid bitmap header"); + + Sint32 tmp_width, tmp_height; + if (readLong(tmp_width) != 0) + return EC_EndOfStream; + + if (readLong(tmp_height) != 0) + return EC_EndOfStream; + + if (tmp_height < 0) /* Is this a top down bitmap? */ + { + isTopDown = OFTrue; + tmp_height = -tmp_height; + } + else + isTopDown = OFFalse; + height = OFstatic_cast(Uint16, tmp_height); + + // Check if we got a valid value here which fits into a Uint16 + // (height < 0 can happen because -(INT_MIN) == INT_MIN). + if (tmp_height <= 0 || tmp_height > UINT16_MAX) + return makeOFCondition(OFM_dcmdata, 18, OF_error, "Unsupported BMP file - height too large or zero"); + + if (tmp_width < 0) /* Width also can be signed, but no semantic */ + { + tmp_width = -tmp_width; + } + width = OFstatic_cast(Uint16, tmp_width); + if (tmp_width <= 0 || tmp_width > UINT16_MAX) + return makeOFCondition(OFM_dcmdata, 18, OF_error, "Unsupported BMP file - width too large or zero"); + + /* Some older standards used this, always 1 for BMP (number of planes) */ + if (readWord(tmp_word) != 0 || tmp_word != 1) + return makeOFCondition(OFM_dcmdata, 18, OF_error, "Not a BMP file - invalid number of planes"); + + /* Color depth in bpp */ + if (readWord(tmp_word) != 0) + return EC_EndOfStream; + bpp = tmp_word; + DCMDATA_LIBI2D_DEBUG("I2DBmpSource: BMP bpp: " << OFstatic_cast(int, bpp)); + + /* Compression info */ + if (readDWord(tmp_dword) != 0) + return EC_EndOfStream; + /* We don't support compressed BMPs */ + if (tmp_dword != 0) + return makeOFCondition(OFM_dcmdata, 18, OF_error, "Unsupported BMP file - compressed"); + + /* We don't care about the next three fields of the bitmap info header: + * DWord: Size of image data or 0 (yes, that's what the standard says!). + * Long: Horizontal resolution in pixel per meter, mostly set to 0. + * Long: Vertical resolution in pixel per meter, mostly set to 0: + */ + if (bmpFile.fseek(12, SEEK_CUR) != 0) + return EC_EndOfStream; + + /* Number of entries in color table, 0 means "use default" */ + if (readDWord(tmp_dword) != 0) + return EC_EndOfStream; + + /* A BMP file can only have 256 color table entries */ + if (tmp_dword > 256) + return makeOFCondition(OFM_dcmdata, 18, OF_error, "invalid BMP file - color table too big"); + + colors = OFstatic_cast(Uint16, tmp_dword); + if (colors == 0) { + // In this case, 1, 4 and 8 bpp get 2**bpp colors in the color table, + // others get no color table at all. + switch (bpp) { + case 1: + colors = 2; + break; + case 4: + colors = 16; + break; + case 8: + colors = 256; + break; + default: + colors = 0; + break; + } + } + + /* Skip another uninteresting entry (number of important colors) */ + if (bmpFile.fseek(4, SEEK_CUR) != 0) + return EC_EndOfStream; + + DCMDATA_LIBI2D_DEBUG("I2DBmpSource: BMP width: " << width); + DCMDATA_LIBI2D_DEBUG("I2DBmpSource: BMP height: " << height); + DCMDATA_LIBI2D_DEBUG("I2DBmpSource: BMP stored as top down: " << (isTopDown ? "Yes" : "No")); + DCMDATA_LIBI2D_DEBUG("I2DBmpSource: Colortable entries: " << colors); + + return EC_Normal; +} + + +OFCondition I2DBmpSource::readColorPalette(Uint16 colors, + Uint32*& palette) +{ + if (colors == 0) + // Nothing to do; + return EC_Normal; + + if (colors > 256) + // BMPs can not have more than 256 color table entries + return EC_IllegalCall; + + // Read the color palette + palette = new Uint32[colors]; + for (int i = 0; i < colors; i++) { + Uint32 tmp; + + // Each item is 32-bit BGRx entry, this function reads that data + if (readDWord(tmp) != 0) { + delete[] palette; + palette = NULL; + return EC_EndOfStream; + } + + // Converting this BGRx into RGB is done elsewhere + palette[i] = tmp; + } + + return EC_Normal; +} + + +OFCondition I2DBmpSource::readBitmapData(const Uint16 width, + const Uint16 height, + const Uint16 bpp, + const OFBool isTopDown, + const Uint16 colors, + const Uint32* palette, + char*& pixData, + Uint32& length) +{ + /* row_length = width * bits_per_pixel / 8 bits_per_byte. + row_length must be rounded *up* to a 4-byte boundary: + row_length = (row_length + 3) & ~3 + */ + + const Uint32 row_length = ((width * bpp + 31) / 32) * 4; + Uint8 *row_data; + Uint32 y; + Sint32 direction; + Uint32 max; + + // "palette" may only be NULL if colors is 0 and vice versa + if ((palette == NULL) != (colors == 0)) + return EC_IllegalCall; + + // These bit depths always need a color palette + if (colors == 0 && (bpp == 1 || bpp == 4 || bpp == 8)) + return makeOFCondition(OFM_dcmdata, 18, OF_error, "invalid BMP file - missing color palette"); + + if (isTopDown) + { + /* This is a top-down BMP, we start at the first row and work our way down */ + y = 1; + direction = 1; + max = height + 1; + } + else + { + /* Bottom-up BMP, we start with the last row and work our way up */ + y = height; + direction = -1; + max = 0; + } + + length = width * height * 3; + + DCMDATA_LIBI2D_DEBUG("I2DBmpSource: Starting to read bitmap data"); + + row_data = new Uint8[row_length]; + pixData = new char[length]; + + if (!row_data || !pixData) + { + delete[] row_data; + delete[] pixData; + return EC_MemoryExhausted; + } + + /* Go through each row of the image */ + for (; y != max; y += direction) + { + /* Calculate posData for this line, it is the index of the first byte for + * this line. ( -1 because we start at index 1, but C at index 0) + */ + Uint32 posData = (y - 1) * width * 3; + + if (bmpFile.fread(row_data, 1, row_length) < row_length) + { + delete[] row_data; + delete[] pixData; + return EC_EndOfStream; + } + + OFCondition cond; + switch (bpp) + { + case 1: + case 4: + case 8: + cond = parseIndexedColorRow(row_data, width, bpp, colors, palette, &pixData[posData]); + break; + case 16: + cond = parse16BppRow(row_data, width, &pixData[posData]); + break; + case 24: + case 32: + cond = parse24_32BppRow(row_data, width, bpp, &pixData[posData]); + break; + default: + cond = makeOFCondition(OFM_dcmdata, 18, OF_error, "unsupported BMP file - invalid bpp"); + break; + } + if (cond.bad()) + { + delete[] row_data; + delete[] pixData; + return cond; + } + } + + DCMDATA_LIBI2D_DEBUG("I2DBmpSource: Done reading bitmap data"); + + delete[] row_data; + + return EC_Normal; +} + + +OFCondition I2DBmpSource::parse24_32BppRow(const Uint8 *row, + const Uint16 width, + const int bpp, + char *pixData) const +{ + /* We now must convert this line of the bmp file into the kind of data that + * our caller expects. Each pixel consists of three bytes: blue, green, red + * (notice the order!) pixel value. We convert this into "standard" RGB. + */ + Uint32 x; + Uint32 pos_a = 0; + Uint32 pos_b = 0; + + /* 32bpp images really are 24bpp images with a null byte prepended in front of + * each pixel. Some apps use that as an alpha channel, but that's not allowed. + */ + int offset = 0; + if (bpp == 32) + offset = 1; + + for (x = 0; x < width; x++) + { + Uint8 r = row[pos_a + 2]; + Uint8 g = row[pos_a + 1]; + Uint8 b = row[pos_a]; + + pixData[pos_b] = r; + pixData[pos_b + 1] = g; + pixData[pos_b + 2] = b; + + pos_a += 3 + offset; + pos_b += 3; + } + return EC_Normal; +} + + +OFCondition I2DBmpSource::parse16BppRow(const Uint8 *row, + const Uint16 width, + char *pixData) const +{ + /* We now must convert this line of the bmp file into the kind of data that + * our caller expects. Each pixel consists of three bytes: blue, green, red + * (notice the order!) pixel value. We convert this into "standard" RGB. + */ + Uint32 x; + Uint32 pos = 0; + + for (x = 0; x < width; x++) + { + // Assemble one pixel value from the input data + Uint16 pixel = 0; + pixel = OFstatic_cast(Uint16, pixel | (row[2*x + 1] << 8)); + pixel = OFstatic_cast(Uint16, pixel | row[2*x + 0]); + + // Each colors has 5 bit, we convert that into 8 bit + Uint8 r = OFstatic_cast(Uint8, (pixel >> 10) << 3); + Uint8 g = OFstatic_cast(Uint8, (pixel >> 5) << 3); + Uint8 b = OFstatic_cast(Uint8, (pixel >> 0) << 3); + + pixData[pos] = r; + pixData[pos + 1] = g; + pixData[pos + 2] = b; + + pos += 3; + } + return EC_Normal; +} + + +OFCondition I2DBmpSource::parseIndexedColorRow(const Uint8 *row, + const Uint16 width, + const int bpp, + const Uint16 colors, + const Uint32* palette, + char *pixData /*out*/) const +{ + // data that is still left from reading the last pixel + Uint8 data = 0; + // Number of valid bits in data + Uint8 bitsLeft = 0; + + Uint32 pos = 0; + Uint32 pos_input = 0; + for (Uint32 x = 0; x < width; x++) + { + // Check if we need to go to the next byte of input data + if (bitsLeft == 0) + { + bitsLeft = 8; + data = row[pos_input++]; + } + + // Get the left-most bpp bits from data + Uint8 index = OFstatic_cast(Uint8, data >> (bitsLeft - bpp)); + // The right-most bpp bits in "index" now contain the data we want, + // clear all the higher bits. + // (1 << bpp) gives us in binary: 00001000 (with bpp zero bits) if we + // substract 1, only the right-most bpp bits will be 1. + index = OFstatic_cast(Uint8, index & ((1 << bpp) - 1)); + bitsLeft = OFstatic_cast(Uint8, bitsLeft - bpp); + + // Check if we are still in the color palette + if (index >= colors) + return makeOFCondition(OFM_dcmdata, 18, OF_error, "unsupported BMP file - access beyond end of color table"); + + // Get the colors + Uint32 pixel = palette[index]; + + // And save it in the resulting image, this implicitly converts the BGR we + // got from the color table into RGB. + pixData[pos] = OFstatic_cast(Uint8, pixel >> 16); + pixData[pos + 1] = OFstatic_cast(Uint8, pixel >> 8); + pixData[pos + 2] = OFstatic_cast(Uint8, pixel >> 0); + + pos += 3; + } + return EC_Normal; +} + + +/* Read 2 bytes, convert to unsigned int */ +/* All 2-byte quantities in BMP are little-endian */ +int I2DBmpSource::readWord(Uint16& result) +{ + int c1, c2; + c1 = bmpFile.fgetc(); + if (c1 == EOF) + return EOF; + c2 = bmpFile.fgetc(); + if (c2 == EOF) + return EOF; + result = OFstatic_cast(Uint16, (OFstatic_cast(Uint16, c2) << 8) + OFstatic_cast(Uint16, c1)); + return 0; +} + + +/* Read 4 bytes, convert to unsigned int */ +/* All 4-byte quantities in BMP are little-endian */ +int I2DBmpSource::readDWord(Uint32& result) +{ + int c1, c2, c3, c4; + c1 = bmpFile.fgetc(); + if (c1 == EOF) + return EOF; + c2 = bmpFile.fgetc(); + if (c2 == EOF) + return EOF; + c3 = bmpFile.fgetc(); + if (c3 == EOF) + return EOF; + c4 = bmpFile.fgetc(); + if (c4 == EOF) + return EOF; + result = (OFstatic_cast(Uint32, c4) << 24) + + (OFstatic_cast(Uint32, c3) << 16) + + (OFstatic_cast(Uint32, c2) << 8) + + OFstatic_cast(Uint32, c1); + return 0; +} + + +int I2DBmpSource::readLong(Sint32& result) +{ + Uint32 tmp; + + /* First read, it as a "normal" double word */ + if (readDWord(tmp) != 0) + return EOF; + + /* tmp is a two's complement (signed integer) and we have to convert it into that */ + if (tmp & (1UL << 31)) + { + /* If the highest bit is set, it is a negative number, convert it */ + result = -(OFstatic_cast(Sint32, ~(tmp - 1))); + } + else + { + /* It is a positive number, no conversion necessary */ + result = tmp; + } + + return 0; +} + + +// closes underlying BMP file +void I2DBmpSource::closeFile() +{ + bmpFile.fclose(); +} + + +// close file and free dynamically allocated memory +I2DBmpSource::~I2DBmpSource() +{ + DCMDATA_LIBI2D_DEBUG("I2DBmpSource: Closing BMP file and cleaning up memory"); + closeFile(); +} diff --git a/dcmdata/libi2d/i2djpgs.cc b/dcmdata/libi2d/i2djpgs.cc new file mode 100644 index 00000000..bad687b6 --- /dev/null +++ b/dcmdata/libi2d/i2djpgs.cc @@ -0,0 +1,899 @@ +/* + * + * Copyright (C) 2007-2013, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Michael Onken + * + * Purpose: Class to extract pixel data and meta information from JPEG file + * + */ + + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmdata/libi2d/i2djpgs.h" +#include "dcmtk/dcmdata/libi2d/i2doutpl.h" +#include "dcmtk/dcmdata/dcerror.h" + +I2DJpegSource::I2DJpegSource() : m_jpegFileMap(), jpegFile(), + m_disableProgrTs(OFFalse), m_disableExtSeqTs(OFFalse), m_insistOnJFIF(OFFalse), + m_keepAPPn(OFFalse), m_lossyCompressed(OFTrue) +{ + DCMDATA_LIBI2D_DEBUG("I2DJpegSource: Plugin instantiated"); +} + + +OFString I2DJpegSource::inputFormat() const +{ + return "JPEG"; +} + +OFCondition I2DJpegSource::openFile(const OFString &filename) +{ + DCMDATA_LIBI2D_DEBUG("I2DJpegSource: Opening JPEG file: " << filename); + OFCondition cond; + if (filename.empty()) + return makeOFCondition(OFM_dcmdata, 18, OF_error, "No JPEG filename specified"); + + // Try to open JPEG file + if ((jpegFile.fopen(filename.c_str(), "rb")) == OFFalse) + return makeOFCondition(OFM_dcmdata, 18, OF_error, "Unable to open JPEG file"); + + return cond; +} + + +void I2DJpegSource::setExtSeqSupport(const OFBool enabled) +{ + m_disableExtSeqTs = !enabled; +} + + +void I2DJpegSource::setProgrSupport(const OFBool enabled) +{ + m_disableProgrTs = !enabled; +} + + +void I2DJpegSource::setInsistOnJFIF(const OFBool enabled) +{ + m_insistOnJFIF = enabled; +} + + +void I2DJpegSource::setKeepAPPn(const OFBool enabled) +{ + m_keepAPPn = enabled; +} + + +OFCondition I2DJpegSource::readPixelData(Uint16& rows, + Uint16& cols, + Uint16& samplesPerPixel, + OFString& photoMetrInt, + Uint16& bitsAlloc, + Uint16& bitsStored, + Uint16& highBit, + Uint16& pixelRepr, + Uint16& planConf, + Uint16& pixAspectH, + Uint16& pixAspectV, + char*& pixData, + Uint32& length, + E_TransferSyntax &ts) +{ + DCMDATA_LIBI2D_DEBUG("I2DJpegSource: Importing JPEG pixel data"); + OFCondition cond = openFile(m_imageFile); + // return error if file is not open + if (cond.bad()) + { + closeFile(); + return cond; + } + // Create "map" with byte positions of all JPEG markers in JPEG file + cond = createJPEGFileMap(); + if (cond.bad()) + { + clearMap(); + closeFile(); + return cond; + } + + // Check for image data in file (look for SOF marker) + E_JPGMARKER jpegEncoding; + OFListIterator(JPEGFileMapEntry*) entry = m_jpegFileMap.begin(); + while (entry != m_jpegFileMap.end()) + { + if ( isSOFMarker((*entry)->marker) ) + { + jpegEncoding = OFstatic_cast(E_JPGMARKER, (*entry)->marker); + break; + } + entry++; + } + if (entry == m_jpegFileMap.end()) + { + closeFile(); + return makeOFCondition(OFM_dcmdata, 18, OF_error, "No image data found in JPEG file"); + } + + // Reject arithmetic and hierarchical (differential) encodings (not supported) + cond = isJPEGEncodingSupported(jpegEncoding); + if (cond.bad()) + { + closeFile(); + return cond; + } + + // Get transfer syntax associated with the given JPEG encoding + ts = associatedTS(jpegEncoding); + + // Extract width, height, samples per pixel, bits per sample + Uint16 width, height, spp, bps; + cond = getSOFImageParameters(**entry, width, height, spp, bps); + if (cond.bad()) + { + closeFile(); + return cond; + } + + // Return error if invalid image attributes were found + if (height == 0 || width == 0) + { + closeFile(); + return makeOFCondition(OFM_dcmdata, 18, OF_error, "Invalid image size (width or height = 0)"); + } + + // Examine JFIF information (version, horizontal and vertical aspect ratio, aspect ratio units. + Uint16 jfifVersion, unit; + Uint16 aspectH = 1; + Uint16 aspectV = 1; + entry = m_jpegFileMap.begin(); + while (entry != m_jpegFileMap.end()) + { + if ( (*entry)->marker == E_JPGMARKER_APP0 ) + break; + entry++; + } + if ( entry == m_jpegFileMap.end()) + { + if (!m_insistOnJFIF) + { + DCMDATA_LIBI2D_DEBUG("I2DJpegSource: Ignoring missing JFIF header"); + } + else + { + closeFile(); + return makeOFCondition(OFM_dcmdata, 18, OF_error, "No JFIF information found in JPEG file"); + } + } + else + cond = getJFIFImageParameters(**entry, jfifVersion, aspectH, aspectV, unit); + if (cond.bad()) + { + if (!m_insistOnJFIF) + { + DCMDATA_LIBI2D_DEBUG("I2DJpegSource: Ignoring errors while evaluating JFIF data"); + } + else + { + closeFile(); + return cond; + } + } + pixAspectH = aspectH; + pixAspectV = aspectV; + + // Collect information needed for image pixel module + rows = height; + cols = width; + samplesPerPixel = spp; + bitsAlloc = bps; + bitsStored = bitsAlloc; + highBit = OFstatic_cast(Uint16, bitsStored - 1); + if (samplesPerPixel == 1) + photoMetrInt = "MONOCHROME2"; + else if (samplesPerPixel == 3) + photoMetrInt = "YBR_FULL_422"; + else + return makeOFCondition(OFM_dcmdata, 18, OF_error, "For JPEG data, Samples per Pixel must be 1 or 3"); + // Planar Configuration and Pixel Representation is always 0 for JPEG data + planConf = 0; + pixelRepr = 0; + + Uint32 tLength = 0; + char* tPixelData = NULL; + // Keep all APPx info (however, JFIF is always removed) + if (m_keepAPPn) + cond = copyJPEGStream(tPixelData, tLength); + // Cut off all APPx information from JPEG and get raw JPEG bit stream into memory + else + cond = extractRawJPEGStream(tPixelData, tLength); + if (cond.bad()) + { + closeFile(); + return cond; + } + length = tLength; + pixData = tPixelData; + return cond; +} + + +OFCondition I2DJpegSource::getLossyComprInfo(OFBool& srcEncodingLossy, + OFString& srcLossyComprMethod) const +{ + if (m_lossyCompressed) + { + srcEncodingLossy = OFTrue; + srcLossyComprMethod = "ISO_10918_1"; // Defined term for JPEG Lossy Compression + } + else + { + // (will never get here, no lossless input supported so far) + srcEncodingLossy = OFFalse; + } + return EC_Normal; +} + + +OFCondition I2DJpegSource::getSOFImageParameters( const JPEGFileMapEntry& entry, + Uint16& imageWidth, + Uint16& imageHeight, + Uint16& samplesPerPixel, + Uint16& bitsPerSample) +{ + DCMDATA_LIBI2D_DEBUG("I2DJpegSource: Examining JPEG SOF image parameters"); + if ( (entry.marker < E_JPGMARKER_SOF0) || (entry.marker > E_JPGMARKER_SOF15) ) + return EC_IllegalCall; + Uint16 length; + Uint16 image_height, image_width; + Uint8 data_precision, num_components; + int result; + + // seek to the given SOFn marker + + jpegFile.fseek(entry.bytePos, SEEK_SET); + result = read2Bytes(length); /* usual parameter length count */ + if (result == EOF) + return makeOFCondition(OFM_dcmdata, 18, OF_error, "Premature EOF in JPEG file"); + + // read values + + result = read1Byte(data_precision); + if (result == EOF) + return makeOFCondition(OFM_dcmdata, 18, OF_error, "Premature EOF in JPEG file"); + + result = read2Bytes(image_height); + if (result == EOF) + return makeOFCondition(OFM_dcmdata, 18, OF_error, "Premature EOF in JPEG file"); + + result = read2Bytes(image_width); + if (result == EOF) + return makeOFCondition(OFM_dcmdata, 18, OF_error, "Premature EOF in JPEG file"); + + result = read1Byte(num_components); + if (result == EOF) + return makeOFCondition(OFM_dcmdata, 18, OF_error, "Premature EOF in JPEG file"); + + imageWidth = image_width; + imageHeight = image_height; + samplesPerPixel = num_components; + bitsPerSample = data_precision; + + DCMDATA_LIBI2D_DEBUG("I2DJpegSource: Dumping JPEG SOF image parameters:"); + DCMDATA_LIBI2D_DEBUG("I2DJpegSource: Image Width: " << image_width); + DCMDATA_LIBI2D_DEBUG("I2DJpegSource: Image Height: " << image_height); + DCMDATA_LIBI2D_DEBUG("I2DJpegSource: Number of Components: " << OFstatic_cast(unsigned int, num_components)); + DCMDATA_LIBI2D_DEBUG("I2DJpegSource: Data Precision: " << OFstatic_cast(unsigned int, data_precision)); + + if (length != OFstatic_cast(unsigned int, 8 + num_components * 3)) + return makeOFCondition(OFM_dcmdata, 18, OF_error, "Bogus SOF marker length"); + + return EC_Normal; +} + + +// ignores thumbnail data +OFCondition I2DJpegSource::getJFIFImageParameters( const JPEGFileMapEntry& entry, + Uint16& jfifVersion, + Uint16& pixelAspectH, + Uint16& pixelAspectV, + Uint16& unit) +{ + DCMDATA_LIBI2D_DEBUG("I2DJpegSource: Examining JFIF information"); + if (entry.marker != E_JPGMARKER_APP0) + return EC_IllegalCall; + Uint16 jv, pah, pav, unt; + + // go to specified byte position and read on to value field + Uint16 length; + jpegFile.fseek(entry.bytePos, SEEK_SET); + int result = read2Bytes(length); /* usual parameter length count */ + if (result == EOF) + return makeOFCondition(OFM_dcmdata, 18, OF_error, "Premature EOF in JPEG file"); + + // read and check the 5 byte "JFIF" marker value (X'4A', X'46', X'49', X'46', X'00') + Uint16 twoBytes; + result = read2Bytes(twoBytes); + if ( (result == EOF) || (twoBytes != 0x4a46) ) + return makeOFCondition(OFM_dcmdata, 18, OF_error, "Invalid JFIF marker or JFIF marker not found"); + result = read2Bytes(twoBytes); + if ( (result == EOF) || (twoBytes != 0x4946) ) + return makeOFCondition(OFM_dcmdata, 18, OF_error, "Invalid JFIF marker or JFIF marker not found"); + Uint8 oneByte; + result = read1Byte(oneByte); + if ( (result == EOF)|| (oneByte != 0x00) ) + return makeOFCondition(OFM_dcmdata, 18, OF_error, "Invalid JFIF marker or JFIF marker not found"); + + // read JFIF version + result = read2Bytes(twoBytes); + if (result == EOF) + return makeOFCondition(OFM_dcmdata, 18, OF_error, "Premature EOF in JPEG file"); + jv = twoBytes; + + // read pixel aspect ratio unit + result = read1Byte(oneByte); + if ( (result == EOF) || (oneByte > 2) ) + return makeOFCondition(OFM_dcmdata, 18, OF_error, "Premature EOF in JPEG file"); + unt = oneByte; + + // read horizontal aspect ratio (XDensity) + result = read2Bytes(twoBytes); + if (result == EOF) + return makeOFCondition(OFM_dcmdata, 18, OF_error, "Premature EOF in JPEG file"); + pah = twoBytes; + + // read vertical aspect ratio (YDensity) + result = read2Bytes(twoBytes); + if (result == EOF) + return makeOFCondition(OFM_dcmdata, 18, OF_error, "Premature EOF in JPEG file"); + pav = twoBytes; + + // prepare return values and return + jfifVersion = jv; + pixelAspectH = pah; + pixelAspectV = pav; + unit = unt; + + DCMDATA_LIBI2D_DEBUG("I2DJpegSource: Dumping some JFIF image parameters:"); + DCMDATA_LIBI2D_DEBUG("I2DJpegSource: JFIF version: " << jfifVersion); + DCMDATA_LIBI2D_DEBUG("I2DJpegSource: Horizontal Pixel Aspect Ratio " << pixelAspectH); + DCMDATA_LIBI2D_DEBUG("I2DJpegSource: Vertical Pixel Aspect Ratio: " << pixelAspectV); + DCMDATA_LIBI2D_DEBUG("I2DJpegSource: Units: " << unit); + + return EC_Normal; +} + + +OFCondition I2DJpegSource::copyJPEGStream(char*& pixelData, + Uint32& pixLength) +{ + DCMDATA_LIBI2D_DEBUG("I2DJpegSource: Copying JPEG data from JPEG file"); + /* Calculate length of total stream as found in the file + * Therefore, look at byte positions from SOI and EOI marker */ + + offile_off_t bytePosJFIF = 0; + offile_off_t bytePosAfterJFIF = 0; + int marker = 0; + + // determine file size + offile_off_t result = jpegFile.fseek(0, SEEK_END); + if (result != 0) + return EC_IllegalParameter; + offile_off_t filesize = jpegFile.ftell(); + + // Only pixel data up to 2^32 bytes is supported (DICOM) and maximum size for "new" operator = size_t + + if ( ( OFstatic_cast(unsigned long, filesize) > OFstatic_cast(unsigned long, 4294967294UL) ) || + ( OFstatic_cast(unsigned long, filesize) > OFstatic_cast(unsigned long, OFstatic_cast(size_t, -1) ) ) ) + { + DCMDATA_LIBI2D_ERROR("I2DJpegSource: JPEG file length longer than 2^32 bytes (or larger than size_t capacity), aborting"); + return EC_MemoryExhausted; + } + + // get position of JFIF section and SOI marker + OFListIterator(JPEGFileMapEntry*) entry = m_jpegFileMap.begin(); + while (entry != m_jpegFileMap.end()) + { + marker = (*entry)->marker; + if ( marker == E_JPGMARKER_APP0 ) + { + DCMDATA_LIBI2D_DEBUG("I2DJpegSource: Skipping application segment APP0"); + bytePosJFIF = (*entry)->bytePos - 1; // include first byte of marker (FF) + entry++; + bytePosAfterJFIF = (*entry)->bytePos - 1; // include first byte (FF) of marker after APPn + break; + } + entry++; + } + + // Go to starting position (SOI marker) of JPEG stream data + jpegFile.fseek(0, SEEK_SET); + + // Allocate buffer for raw JPEG data + pixLength = OFstatic_cast(Uint32, filesize - (bytePosAfterJFIF - bytePosJFIF)); + pixelData = new char[pixLength]; + char *currBufferPos = pixelData; + + // exclude JFIF if present + if (bytePosJFIF != 0) + { + // read from SOI to JFIF + result = jpegFile.fread (currBufferPos, 1, 2); + if (result != 2) + return EC_IllegalCall; + currBufferPos += 2; + // read from end of JFIF to end of file + jpegFile.fseek(bytePosAfterJFIF - 1, SEEK_SET); // -1 because offsets start with 0 + result = jpegFile.fread (currBufferPos, 1, OFstatic_cast(size_t, filesize - bytePosAfterJFIF + 1)); + if (result != filesize - bytePosAfterJFIF + 1) + return EC_IllegalCall; + } + else // otherwise copy everything starting with SOI marker + { + result = jpegFile.fread (currBufferPos, 1, OFstatic_cast(size_t, filesize)); + if (result != filesize) + return EC_IllegalCall; + } + return EC_Normal; +} + + +// expects valid JPEG stream (especially exactly one SOI and one EOI marker) +OFCondition I2DJpegSource::extractRawJPEGStream(char*& pixelData, + Uint32& pixLength) +{ + DCMDATA_LIBI2D_DEBUG("I2DJpegSource: Extracting JPEG data from JPEG file"); + OFCondition cond; + int marker = 0; + Uint16 length; + + /* Calculate length of total stream as found in the file + * Therefore, look at byte positions from SOI and EOI marker and + * and exclude all APPn markers in calculation + */ + + offile_off_t bytePosSOI = 0; + offile_off_t bytePosEOI = 0; + offile_off_t totalAPPSize = 0; + OFList appPosAndLengths; + + OFListIterator(JPEGFileMapEntry*) entry = m_jpegFileMap.begin(); + while (entry != m_jpegFileMap.end()) + { + marker = (*entry)->marker; + + if (marker == E_JPGMARKER_SOI) + { + bytePosSOI = (*entry)->bytePos; + // Subtract one byte for the preceding 0xFF of the SOI-Marker + bytePosSOI -= 1; + } + else if (marker == E_JPGMARKER_EOI) + { + bytePosEOI = (*entry)->bytePos; + // No need to subtract / add bytes + break; + } + else if (marker >= E_JPGMARKER_APP0 && marker <= E_JPGMARKER_APP15) + { + DCMDATA_LIBI2D_DEBUG("I2DJpegSource: Skipping application segment APP" << (marker - E_JPGMARKER_APP0)); + jpegFile.fseek((*entry)->bytePos - jpegFile.ftell(), SEEK_CUR); + int result = read2Bytes( length); + if (result == EOF) + { + jpegFile.fclose(); + return makeOFCondition(OFM_dcmdata, 18, OF_error, "Premature EOF in JPEG file"); + } + // remember pos and length of APP data so we don't need a second "scan" for that + appPosAndLengths.push_back( (*entry)->bytePos - 1 ); // -1 for FF of marker + appPosAndLengths.push_back( length ); + // add length of marker value to total APP size + totalAPPSize += length; + // add the marker length itself to total APP size + totalAPPSize += 2; + } + // Advance to next segment + entry++; + } + + if ( (entry == m_jpegFileMap.end()) || (bytePosSOI == 0) || (bytePosEOI == 0)) // at least end marker was not found + return EC_IllegalCall; + + offile_off_t rawStreamSize = bytePosEOI - bytePosSOI - totalAPPSize; + // Start position n and endpos. m results in a total amount of m-n+1 bytes + rawStreamSize++; + + // Allocate buffer for raw JPEG data + // Only pixel data up to 2^32 bytes is supported (DICOM) + if ( ( OFstatic_cast(unsigned long, rawStreamSize) > OFstatic_cast(unsigned long, 4294967294UL) ) || + ( OFstatic_cast(unsigned long, rawStreamSize) > OFstatic_cast(unsigned long, OFstatic_cast(size_t, -1) ) ) ) + { + DCMDATA_LIBI2D_ERROR("I2DJpegSource: Raw JPEG stream length longer than 2^32 bytes (or larger than size_t capacity), aborting"); + return EC_MemoryExhausted; + } + pixelData = new char[OFstatic_cast(size_t, rawStreamSize)]; + // keep track of current write position in memory buffer + char *currBufferPos = pixelData; + + // Go to starting position (SOI marker) of JPEG stream data + jpegFile.fseek(bytePosSOI-1, SEEK_SET); + + /* Copy everything but leave out APP segments + */ + OFBool finished = OFFalse; + offile_off_t endOfBlock = 0; offile_off_t startOfNextBlock = 0; + while (!finished) + { + // determine position of the next block to be read + if ( appPosAndLengths.size() != 0) + { + // we have some APP blocks left + endOfBlock = appPosAndLengths.front() - 1; + appPosAndLengths.pop_front(); + startOfNextBlock = endOfBlock + appPosAndLengths.front() + 2; // +2 for marker + appPosAndLengths.pop_front(); + } + else // we can read to the end + { + endOfBlock = bytePosEOI; + finished = OFTrue; + } + // read block + offile_off_t blockSize = endOfBlock - jpegFile.ftell(); + size_t result = jpegFile.fread (currBufferPos, 1, OFstatic_cast(size_t, blockSize)); + if (result != OFstatic_cast(size_t, blockSize)) + return EC_IllegalCall; + // prepare for reading next block + if (!finished) + { + jpegFile.fseek(startOfNextBlock, SEEK_SET); + currBufferPos += blockSize; + } + } + // update result variable + pixLength = OFstatic_cast(Uint32, rawStreamSize); + + return cond; +} + + +OFCondition I2DJpegSource::createJPEGFileMap() +{ + DCMDATA_LIBI2D_DEBUG("I2DJpegSource: Examing JPEG file and creating map of JPEG markers"); + // clear any old data + clearMap(); + E_JPGMARKER marker; + JPEGFileMapEntry *entry = NULL; + OFBool lastWasSOSMarker = OFFalse; + OFCondition cond; + + /* Expect SOI at start of file */ + E_JPGMARKER first = E_JPGMARKER(); + cond = firstMarker(first); + if (cond.bad()) + return cond; + entry = new JPEGFileMapEntry(); + entry->bytePos = jpegFile.ftell(); + entry->marker = first; + m_jpegFileMap.push_back(entry); + + if (first != E_JPGMARKER_SOI) + return makeOFCondition(OFM_dcmdata, 18, OF_error, "I2DJpegSource: SOI marker not found at beginning of JPEG stream"); + + /* Scan miscellaneous markers until we reach EOI */ + while (cond.good()) + { + cond = nextMarker(lastWasSOSMarker, marker); + if (cond.good()) + { + entry = new JPEGFileMapEntry(); + entry->bytePos = jpegFile.ftell(); + entry->marker = marker; + m_jpegFileMap.push_back(entry); + if (marker == E_JPGMARKER_SOS) + { + // FIXME: reset this to OFFalse after the next marker? + lastWasSOSMarker = OFTrue; + } + else if (marker == E_JPGMARKER_EOI) + { + // End of file reached + cond = EC_Normal; + break; + } + else if ( isSOFMarker(marker) && m_keepAPPn ) + { + cond = EC_Normal; + break; + } + if ( !isRSTMarker(marker) ) // RST marker does not have a length that could be used for skipping + skipVariable(); + } + } /* end loop */ + debugDumpJPEGFileMap(); + return cond; +} + + +OFBool I2DJpegSource::isRSTMarker(const E_JPGMARKER& marker) +{ + return ((marker >= E_JPGMARKER_RST0) && (marker <= E_JPGMARKER_RST7)); +} + + +OFBool I2DJpegSource::isSOFMarker(const E_JPGMARKER& marker) +{ + return ( (marker >= E_JPGMARKER_SOF0) && (marker <= E_JPGMARKER_SOF15) + && (marker != E_JPGMARKER_DHT) && (marker != E_JPGMARKER_DAC)); +} + + +OFString I2DJpegSource::jpegMarkerToString(const E_JPGMARKER& marker) +{ + switch (marker) + { + case(E_JPGMARKER_SOF0) : return "SOF0: Baseline DCT"; break; + case(E_JPGMARKER_SOF1) : return "SOF1: Extended sequential DCT"; break; + case(E_JPGMARKER_SOF2) : return "SOF2: Progressive DCT"; break; + case(E_JPGMARKER_SOF3) : return "SOF3: Lossless (sequential)"; break; + case(E_JPGMARKER_SOF5) : return "SOF5: Differential sequential DCT"; break; + case(E_JPGMARKER_SOF6) : return "SOF6: Differential progressive DCT"; break; + case(E_JPGMARKER_SOF7) : return "SOF7: Differential lossless (sequential)"; break; + case(E_JPGMARKER_JPG) : return "JPG: JPEG extension"; break; + case(E_JPGMARKER_SOF9) : return "SOF9: Extended sequential DCT"; break; + case(E_JPGMARKER_SOF10) : return "SOF10: Progressive DCT"; break; + case(E_JPGMARKER_SOF11) : return "SOF11: Lossless (sequential)"; break; + case(E_JPGMARKER_SOF13) : return "SOF13: Differential sequential DCT"; break; + case(E_JPGMARKER_SOF14) : return "SOF14: Differential progressive DCT"; break; + case(E_JPGMARKER_SOF15) : return "SOF15: Differential lossless (sequential)"; break; + case(E_JPGMARKER_DHT) : return "DHT: Huffman table(s)"; break; + case(E_JPGMARKER_DAC) : return "DAC: Arithmetic coding conditioning(s)"; break; + case(E_JPGMARKER_SOI) : return "SOI: Start of image"; break; + case(E_JPGMARKER_EOI) : return "EOI: End of image"; break; + case(E_JPGMARKER_SOS) : return "SOS: Start of scan"; break; + case(E_JPGMARKER_DQT) : return "DQT: Quantization table(s)"; break; + case(E_JPGMARKER_DNL) : return "DNL: Number of lines"; break; + case(E_JPGMARKER_DRI) : return "DRI: Define restart interval"; break; + case(E_JPGMARKER_DHP) : return "DHP: Hierarchical progression"; break; + case(E_JPGMARKER_EXP) : return "EXP: Expand reference component(s)"; break; + case(E_JPGMARKER_COM) : return "COM: Comment"; break; + case(E_JPGMARKER_TEM) : return "TEM: For temporary private use in arithmetic coding"; break; + + default: + if ((marker >= E_JPGMARKER_RST0) && (marker <= E_JPGMARKER_RST7)) {return "RSTn: Restart interval termination"; break;} + if ((marker >= E_JPGMARKER_APP0) && (marker <= E_JPGMARKER_APP15)) {return "APPn: Application segment"; break;} + if ((marker >= E_JPGMARKER_JPGN0) && (marker <= E_JPGMARKER_JPGN13)) {return "JPGn: JPEG extension"; break;} + if ((marker >= E_JPGMARKER_RES0) && (marker <= E_JPGMARKER_RESN)) {return "RESn"; break;} + } + OFString msg = "UNKNOWN MARKER :"; + char hexNo[10]; + sprintf(hexNo,"%x2", marker); + msg += hexNo; + return msg; +} + + +/* Read one byte, testing for EOF */ +int I2DJpegSource::read1Byte(Uint8& result) +{ + register int c; + c = jpegFile.fgetc(); + if (c == EOF) + return EOF; + result = OFstatic_cast(Uint8, c); + return 0; +} + + +/* Read 2 bytes, convert to unsigned int */ +/* All 2-byte quantities in JPEG markers are MSB first */ +int I2DJpegSource::read2Bytes(Uint16& result) +{ + int c1, c2; + c1 = jpegFile.fgetc(); + if (c1 == EOF) + return EOF; + c2 = jpegFile.fgetc(); + if (c2 == EOF) + return EOF; + result = OFstatic_cast(Uint16, ((OFstatic_cast(Uint16, c1)) << 8) + OFstatic_cast(Uint16, c2)); + return 0; +} + + + +/* + * Find the next JPEG marker and return its marker code. + * We expect at least one FF byte, possibly more if the compressor used FFs + * to pad the file. + * There could also be non-FF garbage between markers. The treatment of such + * garbage is unspecified; we choose to skip over it but emit a warning msg. + */ + +OFCondition I2DJpegSource::nextMarker(const OFBool& lastWasSOSMarker, + E_JPGMARKER& result) +{ + Uint8 c; + int discarded_bytes = 0; + int oneByte; + + do { + /* Find 0xFF byte; count and skip any non-FFs. */ + oneByte = read1Byte(c); + if (oneByte == EOF) + return makeOFCondition(OFM_dcmdata, 18, OF_error, "Premature EOF in JPEG file"); + + while (c != 0xFF) + { + if (!lastWasSOSMarker) + discarded_bytes++; + oneByte = read1Byte(c); + if (oneByte == EOF) + return makeOFCondition(OFM_dcmdata, 18, OF_error, "Premature EOF in JPEG file"); + } + /* Get marker code byte, swallowing any duplicate FF bytes. Extra FFs + * are legal as pad bytes, so don't count them in discarded_bytes. + */ + do { + oneByte = read1Byte(c); + if (oneByte == EOF) + return makeOFCondition(OFM_dcmdata, 18, OF_error, "Premature EOF in JPEG file"); + } while (c == 0xFF); + } while (lastWasSOSMarker && c == 0x00); + + if (discarded_bytes != 0) { + DCMDATA_LIBI2D_WARN("garbage data found in JPEG file"); + } + result = OFstatic_cast(E_JPGMARKER, c); + return EC_Normal; +} + + +/* + * Read the initial marker, which should be SOI. + * For a JFIF file, the first two bytes of the file should be literally + * 0xFF M_SOI. + */ + +OFCondition I2DJpegSource::firstMarker(E_JPGMARKER& result) +{ + Uint8 c1, c2; + + c1 = OFstatic_cast(Uint8, jpegFile.fgetc()); + c2 = OFstatic_cast(Uint8, jpegFile.fgetc()); + if (c1 != 0xFF || c2 != E_JPGMARKER_SOI) { + return makeOFCondition(OFM_dcmdata, 18, OF_error, "Not a JPEG file"); + } + result = OFstatic_cast(E_JPGMARKER, c2); + return EC_Normal; +} + +/* + * Most types of marker are followed by a variable-length parameter segment. + * This routine skips over the parameters for any marker we don't otherwise + * want to process. + * Note that we MUST skip the parameter segment explicitly in order not to + * be fooled by 0xFF bytes that might appear within the parameter segment; + * such bytes do NOT introduce new markers. + */ + +OFCondition I2DJpegSource::skipVariable() +/* Skip over an unknown or uninteresting variable-length marker */ +{ + Uint16 length; + + /* Get the marker parameter length count */ + int result = read2Bytes(length); + if (result == EOF) + return makeOFCondition(OFM_dcmdata, 18, OF_error, "Premature EOF in JPEG file"); + /* Length includes itself, so must be at least 2 */ + if (length < 2) + return makeOFCondition(OFM_dcmdata, 18, OF_error, "Erroneous JPEG marker length"); + length = OFstatic_cast(Uint16, length - 2); + /* Skip over the remaining bytes */ + jpegFile.fseek(length, SEEK_CUR); + return EC_Normal; +} + + +OFCondition I2DJpegSource::isJPEGEncodingSupported(const E_JPGMARKER& jpegEncoding) const +{ + DCMDATA_LIBI2D_DEBUG("I2DJpegSource: Checking whether JPEG encoding is supported"); + DCMDATA_LIBI2D_DEBUG("I2DJpegSource: Encoding: " << jpegMarkerToString(jpegEncoding)); + switch (jpegEncoding) + { + case E_JPGMARKER_SOF0: // Baseline + return EC_Normal; + case E_JPGMARKER_SOF1: // Extended sequential + if (!m_disableExtSeqTs) + return EC_Normal; + else + return makeOFCondition(OFM_dcmdata, 18, OF_error, "Unable to convert: Extended sequential JPEG coding found but support disabled"); + case E_JPGMARKER_SOF2: // Progressive + if (!m_disableProgrTs) + return EC_Normal; + else + return makeOFCondition(OFM_dcmdata, 18, OF_error, "Unable to convert: Progressive JPEG coding found but disabled"); + // SOF3: Lossless, SOF5-7: Hierarchical (differential), SOF9-15: Arithmetic coding, all other + default: + OFString errMsg("JPEG data with encoding: '"); + errMsg += jpegMarkerToString(jpegEncoding); + errMsg += "' not supported"; + return makeOFCondition(OFM_dcmdata, 18, OF_error, errMsg.c_str()); + } + return EC_Normal; +} + + +E_TransferSyntax I2DJpegSource::associatedTS(const E_JPGMARKER& jpegEncoding) +{ + switch (jpegEncoding) + { + case E_JPGMARKER_SOF0: // Baseline + return EXS_JPEGProcess1; + case E_JPGMARKER_SOF1: // Extended Sequential + return EXS_JPEGProcess2_4; + case E_JPGMARKER_SOF2: // Progressive + return EXS_JPEGProcess10_12; + default: + return EXS_Unknown; + } +} + + +void I2DJpegSource::debugDumpJPEGFileMap() const +{ + if (!DCM_dcmdataLibi2dLogger.isEnabledFor(OFLogger::DEBUG_LOG_LEVEL)) + return; + + DCMDATA_LIBI2D_DEBUG("I2DJpegSource: Dumping JPEG marker file map:"); + if (m_keepAPPn) + DCMDATA_LIBI2D_DEBUG("I2DJpegSource: Keep APPn option enabled, any markers after SOFn marker will not be dumped"); + OFListConstIterator(JPEGFileMapEntry*) it= m_jpegFileMap.begin(); + while (it != m_jpegFileMap.end()) + { + DCMDATA_LIBI2D_DEBUG("I2DJpegSource: Byte Position: 0x" + << STD_NAMESPACE hex << STD_NAMESPACE setw(8) << STD_NAMESPACE setfill('0') + /* need to cast bytePos to unsigned long to keep VC6 happy */ + << OFstatic_cast(unsigned long, (*it)->bytePos) <<" | Marker: " << jpegMarkerToString( (*it)->marker)); + it++; + } +} + +void I2DJpegSource::clearMap() +{ + // free memory of each map entry and remove them all from list + JPEGFileMapEntry *entry = NULL; + while (m_jpegFileMap.size() != 0) + { + entry = m_jpegFileMap.front(); + m_jpegFileMap.pop_front(); + delete entry; entry = NULL; + } +} + +// closes underlying JPEG file +void I2DJpegSource::closeFile() +{ + jpegFile.fclose(); +} + +// close file and free dynamically allocated memory +I2DJpegSource::~I2DJpegSource() +{ + DCMDATA_LIBI2D_DEBUG("I2DJpegSource: Closing JPEG file and cleaning up memory"); + closeFile(); + clearMap(); +} diff --git a/dcmdata/libi2d/i2dplnsc.cc b/dcmdata/libi2d/i2dplnsc.cc new file mode 100644 index 00000000..72bb0f7e --- /dev/null +++ b/dcmdata/libi2d/i2dplnsc.cc @@ -0,0 +1,260 @@ +/* + * + * Copyright (C) 2001-2010, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Michael Onken + * + * Purpose: Implements conversion from image into new DICOM SC IODs + * + */ + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/dcmdata/libi2d/i2dplnsc.h" +#include "dcmtk/dcmdata/dcdeftag.h" /* for DCM_ defines */ +#include "dcmtk/dcmdata/dcuid.h" /* for UID_ defines */ +#include "dcmtk/dcmdata/libi2d/i2doutpl.h" + + +I2DOutputPlugNewSC::I2DOutputPlugNewSC() +{ + DCMDATA_LIBI2D_DEBUG("I2DOutputPlugNewSC: Output plugin for new Multiframe Secondary Capture SOPs initialized"); +} + + +OFString I2DOutputPlugNewSC::ident() +{ + return "New Secondary Capture Image SOP Classes"; +} + + +void I2DOutputPlugNewSC::supportedSOPClassUIDs(OFList& suppSOPs) +{ + suppSOPs.push_back(UID_MultiframeSingleBitSecondaryCaptureImageStorage); + suppSOPs.push_back(UID_MultiframeGrayscaleByteSecondaryCaptureImageStorage); + suppSOPs.push_back(UID_MultiframeGrayscaleWordSecondaryCaptureImageStorage); + suppSOPs.push_back(UID_MultiframeTrueColorSecondaryCaptureImageStorage); +} + + + +OFCondition I2DOutputPlugNewSC::convert(DcmDataset &dataset) const +{ + DCMDATA_LIBI2D_DEBUG("I2DOutputPlugNewSC: Inserting new Multiframe SC specific attributes"); + + // Find out which of the new SC SOP Class UIDs to use + OFString sopUID, photInt; Uint16 bitsAllocated; + OFCondition cond = dataset.findAndGetUint16(DCM_BitsAllocated, bitsAllocated); + if (cond.bad()) + return makeOFCondition(OFM_dcmdata, 18, OF_error, "I2DOutputPlugNewSC: Unable to determine correct SOP class due to missing Image Pixel module information"); + cond = dataset.findAndGetOFStringArray(DCM_PhotometricInterpretation, photInt); + + if (bitsAllocated == 1) + cond = handle1BitSC(&dataset); + else if (bitsAllocated == 8) + cond = handle8BitSC(&dataset); + else if (bitsAllocated == 16) + cond = handle16BitSC(&dataset); + else + cond = makeOFCondition(OFM_dcmdata, 18, OF_error, "I2DOutputPlugNewSC: Bits Allocated needs a value of 1, 8 or 16 for conversion"); + + cond = insertMultiFrameAttribs(&dataset); + return cond; +} + +OFString I2DOutputPlugNewSC::isValid(DcmDataset& dataset) const +{ + OFString err; + // Just return if checking was disabled + if (!m_doAttribChecking) + return err; + + DCMDATA_LIBI2D_DEBUG("I2DOutputPlugNewSC: Checking new Multiframe SC specific attributes"); + // WSD="Workstation", found in most Secondary Capture files + err += checkAndInventType1Attrib(DCM_ConversionType, &dataset, "WSD"); + // As a default we do not expect the image to have burnt in annotations + err += checkAndInventType1Attrib(DCM_BurnedInAnnotation, &dataset, "NO"); + + return err; +} + + +OFCondition I2DOutputPlugNewSC::insertMultiFrameAttribs(DcmDataset* targetDataset) const +{ + if (!targetDataset) + return EC_IllegalParameter; + + // We only support 1 image Multi-frames so far + return targetDataset->putAndInsertOFStringArray(DCM_NumberOfFrames, "1"); + // Frame Increment pointer is set later in the more specific SC Multi-frame Image context +} + + +OFCondition I2DOutputPlugNewSC::handle1BitSC(DcmDataset *dataset) const +{ + if (!dataset) + return EC_IllegalParameter; + + OFCondition cond; Uint16 u16 = 0; OFString str; + cond = dataset->findAndGetOFStringArray(DCM_PhotometricInterpretation, str); + if (cond.bad() || (str != "MONOCHROME2")) + return makeOFCondition(OFM_dcmdata, 18, OF_error, "I2DOutputPlugNewSC: Photometric interpretation does not fit SOP class"); + + cond = dataset->findAndGetUint16(DCM_SamplesPerPixel, u16); + if (cond.bad() || (u16 != 1)) + return makeOFCondition(OFM_dcmdata, 18, OF_error, "I2DOutputPlugNewSC: Samples Per Pixel does not fit SOP class"); + + cond = dataset->findAndGetUint16(DCM_BitsStored, u16); + if (cond.bad() || (u16 != 1)) + return makeOFCondition(OFM_dcmdata, 18, OF_error, "I2DOutputPlugNewSC: Bits Stored does not fit SOP class"); + + cond = dataset->findAndGetUint16(DCM_HighBit, u16); + if (cond.bad() || (u16 != 0)) + return makeOFCondition(OFM_dcmdata, 18, OF_error, "I2DOutputPlugNewSC: High Bit does not fit SOP class"); + + cond = dataset->findAndGetUint16(DCM_PixelRepresentation, u16); + if (cond.bad() || (u16 != 0)) + return makeOFCondition(OFM_dcmdata, 18, OF_error, "I2DOutputPlugNewSC: Pixel Representation does not fit SOP class"); + + cond = dataset->putAndInsertOFStringArray(DCM_SOPClassUID, UID_MultiframeSingleBitSecondaryCaptureImageStorage); + return cond; +} + + +OFCondition I2DOutputPlugNewSC::handle8BitSC(DcmDataset *dataset) const +{ + if (!dataset) + return EC_IllegalParameter; + + OFCondition cond; Uint16 u16 = 0; OFString str; + cond = dataset->findAndGetOFStringArray(DCM_PhotometricInterpretation, str); + if (cond.bad()) + return makeOFCondition(OFM_dcmdata, 18, OF_error, "I2DOutputPlugNewSC: Photometric interpretation not set for Pixel Data"); + if (str == "MONOCHROME2") // Mult-Frame Grayscale Byte SC Image + { + cond = dataset->findAndGetUint16(DCM_SamplesPerPixel, u16); + if (cond.bad() || (u16 != 1)) + return makeOFCondition(OFM_dcmdata, 18, OF_error, "I2DOutputPlugNewSC: Samples Per Pixel does not fit SOP class"); + + cond = dataset->findAndGetUint16(DCM_BitsStored, u16); + if (cond.bad() || (u16 != 8)) + return makeOFCondition(OFM_dcmdata, 18, OF_error, "I2DOutputPlugNewSC: Bits Stored does not fit SOP class"); + + cond = dataset->findAndGetUint16(DCM_HighBit, u16); + if (cond.bad() || (u16 != 7)) + return makeOFCondition(OFM_dcmdata, 18, OF_error, "I2DOutputPlugNewSC: High Bit does not fit SOP class"); + + cond = dataset->findAndGetUint16(DCM_PixelRepresentation, u16); + if (cond.bad() || (u16 != 0)) + return makeOFCondition(OFM_dcmdata, 18, OF_error, "I2DOutputPlugNewSC: Pixel Representation does not fit SOP class"); + // For MONOCHROME2 and Bits Stored > 1, rescale slope/intercept/type have to be inserted + cond = insertSCMultiFrameAttribs(dataset); + // Insert SOP Class UID + if (cond.good()) + cond = dataset->putAndInsertOFStringArray(DCM_SOPClassUID, UID_MultiframeGrayscaleByteSecondaryCaptureImageStorage); + } + else if ((str == "YBR_FULL_422") || (str == "RGB")) // Mult-Frame True Color Byte SC Image + { + cond = dataset->findAndGetUint16(DCM_SamplesPerPixel, u16); + if (cond.bad() || (u16 != 3)) + return makeOFCondition(OFM_dcmdata, 18, OF_error, "I2DOutputPlugNewSC: Samples Per Pixel does not fit SOP class"); + + cond = dataset->findAndGetUint16(DCM_BitsStored, u16); + if (cond.bad() || (u16 != 8)) + return makeOFCondition(OFM_dcmdata, 18, OF_error, "I2DOutputPlugNewSC: Bits Stored does not fit SOP class"); + + cond = dataset->findAndGetUint16(DCM_HighBit, u16); + if (cond.bad() || (u16 != 7)) + return makeOFCondition(OFM_dcmdata, 18, OF_error, "I2DOutputPlugNewSC: High Bit does not fit SOP class"); + + cond = dataset->findAndGetUint16(DCM_PixelRepresentation, u16); + if (cond.bad() || (u16 != 0)) + return makeOFCondition(OFM_dcmdata, 18, OF_error, "I2DOutputPlugNewSC: Pixel Representation does not fit SOP class"); + + if (str == "RGB") // For RGB, Planar Configuration must be present and set to 0 + { + cond = dataset->findAndGetUint16(DCM_PlanarConfiguration, u16); + if (cond.bad() || (u16 != 0)) + return makeOFCondition(OFM_dcmdata, 18, OF_error, "I2DOutputPlugNewSC: Planar Configuration does not fit SOP class"); + } + // Insert SOP Class UID + if (cond.good()) + cond = dataset->putAndInsertOFStringArray(DCM_SOPClassUID, UID_MultiframeTrueColorSecondaryCaptureImageStorage); + } + else + return makeOFCondition(OFM_dcmdata, 18, OF_error, "I2DOutputPlugNewSC: Photometric interpretation does not fit SOP class"); + + return cond; +} + + +OFCondition I2DOutputPlugNewSC::handle16BitSC(DcmDataset *dataset) const +{ + if (!dataset) + return EC_IllegalParameter; + + OFCondition cond; Uint16 u16 = 0; OFString str; + cond = dataset->findAndGetOFStringArray(DCM_PhotometricInterpretation, str); + if (cond.bad() || (str != "MONOCHROME2")) + return makeOFCondition(OFM_dcmdata, 18, OF_error, "I2DOutputPlugNewSC: Photometric interpretation does not fit SOP class"); + + cond = dataset->findAndGetUint16(DCM_SamplesPerPixel, u16); + if (cond.bad() || (u16 != 1)) + return makeOFCondition(OFM_dcmdata, 18, OF_error, "I2DOutputPlugNewSC: Samples Per Pixel does not fit SOP class"); + + Uint16 bitsStored; + cond = dataset->findAndGetUint16(DCM_BitsStored, bitsStored); + if (cond.bad() || (bitsStored >= 16) || (bitsStored <9) ) + return makeOFCondition(OFM_dcmdata, 18, OF_error, "I2DOutputPlugNewSC: Bits Stored does not fit SOP class"); + + cond = dataset->findAndGetUint16(DCM_HighBit, u16); + if (cond.bad() || (u16 != bitsStored -1)) + return makeOFCondition(OFM_dcmdata, 18, OF_error, "I2DOutputPlugNewSC: High Bit does not fit SOP class"); + + cond = dataset->findAndGetUint16(DCM_PixelRepresentation, u16); + if (cond.bad() || (u16 != 0)) + return makeOFCondition(OFM_dcmdata, 18, OF_error, "I2DOutputPlugNewSC: Pixel Representation does not fit SOP class"); + + // Insert SOP Class UID + cond = dataset->putAndInsertOFStringArray(DCM_SOPClassUID, UID_MultiframeGrayscaleWordSecondaryCaptureImageStorage); + // For MONOCHROME2 and Bits Stored > 1, rescale slope/intercept/type have to be inserted + if (cond.good()) + cond = insertSCMultiFrameAttribs(dataset); + return cond; +} + + +OFCondition I2DOutputPlugNewSC::insertSCMultiFrameAttribs(DcmDataset *targetDataset) const +{ + OFCondition cond; + // Rescale Intercept, set to 0 (constant enumerated value) + cond = targetDataset->putAndInsertOFStringArray(DCM_RescaleIntercept, "0"); + // Rescale Slope, set to 1 (constant enumerated value) + if (cond.good()) + cond = targetDataset->putAndInsertOFStringArray(DCM_RescaleSlope, "1"); + // Rescale type, set to unspecified "US" (constant enumerated value) + if (cond.good()) + cond = targetDataset->putAndInsertOFStringArray(DCM_RescaleType, "US"); + // Rescale type, set to unspecified "IDENTITY" (constant enumerated value) + if (cond.good()) + cond = targetDataset->putAndInsertOFStringArray(DCM_PresentationLUTShape, "IDENTITY"); + else + return makeOFCondition(OFM_dcmdata, 18, OF_error, "I2DOutputPlugNewSC: Unable to insert attributes for Rescale Slope/Intercept/Type"); + return EC_Normal; +} + + +I2DOutputPlugNewSC::~I2DOutputPlugNewSC() +{ +} diff --git a/dcmdata/libi2d/i2dplsc.cc b/dcmdata/libi2d/i2dplsc.cc new file mode 100644 index 00000000..203dff77 --- /dev/null +++ b/dcmdata/libi2d/i2dplsc.cc @@ -0,0 +1,72 @@ +/* + * + * Copyright (C) 2001-2010, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Michael Onken + * + * Purpose: Implements conversion from image into DICOM SC IOD + * + */ + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/dcmdata/libi2d/i2dplsc.h" +#include "dcmtk/dcmdata/libi2d/i2doutpl.h" +#include "dcmtk/dcmdata/dcdeftag.h" /* for DCM_ defines */ +#include "dcmtk/dcmdata/dcuid.h" /* for UID_ defines */ + + +I2DOutputPlugSC::I2DOutputPlugSC() +{ + DCMDATA_LIBI2D_DEBUG("I2DOutputPlugSC: Output plugin for Secondary Capture initialized"); +} + +OFString I2DOutputPlugSC::ident() +{ + return "Secondary Capture Image SOP Class"; +} + +void I2DOutputPlugSC::supportedSOPClassUIDs(OFList& suppSOPs) +{ + suppSOPs.push_back(UID_SecondaryCaptureImageStorage); +} + + +OFCondition I2DOutputPlugSC::convert(DcmDataset &dataset) const +{ + DCMDATA_LIBI2D_DEBUG("I2DOutputPlugSC: Inserting SC specific attributes"); + OFCondition cond; + cond = dataset.putAndInsertOFStringArray(DCM_SOPClassUID, UID_SecondaryCaptureImageStorage); + + return EC_Normal; +} + + +OFString I2DOutputPlugSC::isValid(DcmDataset& dataset) const +{ + OFString err; + // Just return if checking was disabled + if (!m_doAttribChecking) + return err; + + DCMDATA_LIBI2D_DEBUG("I2DOutputPlugSC: Checking SC specific attributes"); + err += checkAndInventType1Attrib(DCM_ConversionType, &dataset, "WSD"); // WSD="Workstation" + + return err; +} + + +I2DOutputPlugSC::~I2DOutputPlugSC() +{ +} diff --git a/dcmdata/libi2d/i2dplvlp.cc b/dcmdata/libi2d/i2dplvlp.cc new file mode 100644 index 00000000..536acba4 --- /dev/null +++ b/dcmdata/libi2d/i2dplvlp.cc @@ -0,0 +1,85 @@ +/* + * + * Copyright (C) 2001-2010, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Michael Onken + * + * Purpose: Implements conversion from image into DICOM Visible Light Photography IOD + * + */ + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/dcmdata/libi2d/i2dplvlp.h" +#include "dcmtk/dcmdata/dcdeftag.h" /* for DCM_ defines */ +#include "dcmtk/dcmdata/dcuid.h" /* for UID_ defines */ + + +I2DOutputPlugVLP::I2DOutputPlugVLP() +{ + DCMDATA_LIBI2D_DEBUG("I2DOutputPlugVLP: Output plugin for VLP initialized"); +} + +OFString I2DOutputPlugVLP::ident() +{ + return "Visible Light Photographic Image SOP Class"; +} + +void I2DOutputPlugVLP::supportedSOPClassUIDs(OFList& suppSOPs) +{ + suppSOPs.push_back(UID_VLPhotographicImageStorage); +} + + +OFCondition I2DOutputPlugVLP::convert(DcmDataset &dataset) const +{ + DCMDATA_LIBI2D_DEBUG("I2DOutputPlugVLP: Inserting VLP specific attributes"); + OFCondition cond; + cond = dataset.putAndInsertOFStringArray(DCM_SOPClassUID, UID_VLPhotographicImageStorage); + if (cond.bad()) + return makeOFCondition(OFM_dcmdata, 18, OF_error, "Unable to insert SOP class into dataset"); + + cond = dataset.putAndInsertOFStringArray(DCM_Modality, "XC"); + if (cond.bad()) + return makeOFCondition(OFM_dcmdata, 18, OF_error, "Unable to insert Modality (XC) into dataset"); + + return EC_Normal; +} + + +OFString I2DOutputPlugVLP::isValid(DcmDataset& dataset) const +{ + OFString err; + // Just return if checking was disabled + if (!m_doAttribChecking) + return err; + + DCMDATA_LIBI2D_DEBUG("I2DOutputPlugVLP: Checking VLP specific attributes for validity"); + // Acquisition Context Module + err = checkAndInventType2Attrib(DCM_AcquisitionContextSequence, &dataset); + + // General Equipment Module + err += checkAndInventType2Attrib(DCM_Manufacturer, &dataset); + + // VL Image Module + err += checkAndInventType1Attrib(DCM_ImageType, &dataset, "DERIVED\\SECONDARY"); + err += checkAndInventType2Attrib(DCM_LossyImageCompression, &dataset); + + return err; +} + + +I2DOutputPlugVLP::~I2DOutputPlugVLP() +{ +} diff --git a/dcmdata/libsrc/CMakeLists.txt b/dcmdata/libsrc/CMakeLists.txt new file mode 100644 index 00000000..02d16bc7 --- /dev/null +++ b/dcmdata/libsrc/CMakeLists.txt @@ -0,0 +1,49 @@ +# create library from source files + +DCMTK_ADD_LIBRARY(dcmdata + cmdlnarg dcbytstr dcchrstr dccodec dcdatset dcdatutl dcddirif dcdicdir dcdicent + dcdict dcdictbi dcdirrec dcelem dcerror dcfilefo dcfilter dchashdi dcistrma + dcistrmb dcistrmf dcistrmz dcitem dclist dcmetinf dcobject dcostrma dcostrmb + dcostrmf dcostrmz dcpath dcpcache dcpixel dcpixseq dcpxitem dcrleccd dcrlecce + dcrlecp dcrledrg dcrleerg dcrlerp dcsequen dcspchrs dcstack dcswap dctag + dctagkey dctypes dcuid dcvr dcvrae dcvras dcvrat dcvrcs dcvrda dcvrds dcvrdt + dcvrfd dcvrfl dcvris dcvrlo dcvrlt dcvrobow dcvrod dcvrof dcvrpn dcvrpobw dcvrsh + dcvrsl dcvrss dcvrst dcvrtm dcvruc dcvrui dcvrul dcvrulup dcvrur dcvrus dcvrut + dcwcache dcxfer vrscan vrscanl) + +DCMTK_TARGET_LINK_MODULES(dcmdata ofstd oflog) +DCMTK_TARGET_LINK_LIBRARIES(dcmdata ${ZLIB_LIBS}) + +# Various dictionary-related commands +SET(DICOMDIC "${dcmdata_SOURCE_DIR}/data/dicom.dic") +SET(PRIVATEDIC "${dcmdata_SOURCE_DIR}/data/private.dic") +SET(DICTIONARIES "${DICOMDIC}" "${PRIVATEDIC}") + +IF(BUILD_APPS) + # don't use DCMTK_ADD_EXECUTABLE() since we don't want to install the files + ADD_EXECUTABLE(mkdictbi EXCLUDE_FROM_ALL mkdictbi dctagkey dcdicent dcdict dcvr dchashdi cmdlnarg dctypes) + ADD_EXECUTABLE(mkdeftag EXCLUDE_FROM_ALL mkdeftag dctagkey dcdicent dcdict dcvr dchashdi cmdlnarg dctypes) + # workaround for Visual Studio to disable dll storage specifiers when linking directly into the executable. + # this is needed since the built-in dictionary code is created by the tools below and thus those tools + # statically link the few required dcmdata source files instead of linking to dcmdata as a whole. + SET_TARGET_PROPERTIES(mkdictbi mkdeftag PROPERTIES COMPILE_DEFINITIONS "DCMDATA_BUILD_DICTIONARY") +ENDIF(BUILD_APPS) +DCMTK_TARGET_LINK_MODULES(mkdictbi ofstd oflog) +DCMTK_TARGET_LINK_MODULES(mkdeftag ofstd oflog) + +ADD_CUSTOM_TARGET(updatedeftag + COMMAND mkdeftag -o ${dcmdata_SOURCE_DIR}/include/dcmtk/dcmdata/dcdeftag.h ${DICTIONARIES} + DEPENDS mkdeftag + WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" + COMMENT "Generate a new include file of defined tags") + +ADD_CUSTOM_TARGET(updatebuiltindict + COMMAND mkdictbi -o dcdictbi.cc ${DICTIONARIES} + DEPENDS mkdictbi + WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" + COMMENT "Generate a builtin data dictionary") + +ADD_CUSTOM_TARGET(mkvrscan + COMMAND flex -8 --header-file=vrscanl.h --outfile=vrscanl.c vrscanl.l + WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" + COMMENT "Generate vrscanl.c and vrscanl.h") diff --git a/dcmdata/libsrc/Makefile.dep b/dcmdata/libsrc/Makefile.dep new file mode 100644 index 00000000..6d182f23 --- /dev/null +++ b/dcmdata/libsrc/Makefile.dep @@ -0,0 +1,3763 @@ +cmdlnarg.o: cmdlnarg.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmdata/cmdlnarg.h ../include/dcmtk/dcmdata/dcdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h +dcbytstr.o: dcbytstr.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../include/dcmtk/dcmdata/dcbytstr.h ../include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../include/dcmtk/dcmdata/dcdefine.h ../include/dcmtk/dcmdata/dcelem.h \ + ../include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../include/dcmtk/dcmdata/dcerror.h ../include/dcmtk/dcmdata/dcxfer.h \ + ../include/dcmtk/dcmdata/dcvr.h ../include/dcmtk/dcmdata/dctag.h \ + ../include/dcmtk/dcmdata/dctagkey.h ../include/dcmtk/dcmdata/dcstack.h +dcchrstr.o: dcchrstr.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmdata/dcspchrs.h \ + ../../ofstd/include/dcmtk/ofstd/ofchrenc.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../include/dcmtk/dcmdata/dcdefine.h ../include/dcmtk/dcmdata/dcitem.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../include/dcmtk/dcmdata/dcerror.h ../include/dcmtk/dcmdata/dcxfer.h \ + ../include/dcmtk/dcmdata/dcvr.h ../include/dcmtk/dcmdata/dctag.h \ + ../include/dcmtk/dcmdata/dctagkey.h ../include/dcmtk/dcmdata/dcstack.h \ + ../include/dcmtk/dcmdata/dclist.h ../include/dcmtk/dcmdata/dcpcache.h \ + ../include/dcmtk/dcmdata/dcdeftag.h ../include/dcmtk/dcmdata/dcchrstr.h \ + ../include/dcmtk/dcmdata/dcbytstr.h ../include/dcmtk/dcmdata/dcelem.h +dccodec.o: dccodec.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmdata/dccodec.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../include/dcmtk/dcmdata/dcdefine.h ../include/dcmtk/dcmdata/dcxfer.h \ + ../include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../include/dcmtk/dcmdata/dcdeftag.h ../include/dcmtk/dcmdata/dctagkey.h \ + ../include/dcmtk/dcmdata/dcuid.h ../include/dcmtk/dcmdata/dcitem.h \ + ../include/dcmtk/dcmdata/dcobject.h ../include/dcmtk/dcmdata/dcerror.h \ + ../include/dcmtk/dcmdata/dctag.h ../include/dcmtk/dcmdata/dcstack.h \ + ../include/dcmtk/dcmdata/dclist.h ../include/dcmtk/dcmdata/dcpcache.h \ + ../include/dcmtk/dcmdata/dcsequen.h ../include/dcmtk/dcmdata/dcelem.h \ + ../include/dcmtk/dcmdata/dcpixseq.h ../include/dcmtk/dcmdata/dcofsetl.h \ + ../include/dcmtk/dcmdata/dcpxitem.h ../include/dcmtk/dcmdata/dcvrobow.h \ + ../include/dcmtk/dcmdata/dcswap.h ../include/dcmtk/dcmdata/dcvrui.h \ + ../include/dcmtk/dcmdata/dcbytstr.h +dcdatset.o: dcdatset.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstack.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../include/dcmtk/dcmdata/dcdatset.h ../include/dcmtk/dcmdata/dcitem.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../include/dcmtk/dcmdata/dcdefine.h ../include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../include/dcmtk/dcmdata/dcerror.h ../include/dcmtk/dcmdata/dcxfer.h \ + ../include/dcmtk/dcmdata/dcvr.h ../include/dcmtk/dcmdata/dctag.h \ + ../include/dcmtk/dcmdata/dctagkey.h ../include/dcmtk/dcmdata/dcstack.h \ + ../include/dcmtk/dcmdata/dclist.h ../include/dcmtk/dcmdata/dcpcache.h \ + ../include/dcmtk/dcmdata/dcvrus.h ../include/dcmtk/dcmdata/dcelem.h \ + ../include/dcmtk/dcmdata/dcpixel.h ../include/dcmtk/dcmdata/dcvrpobw.h \ + ../include/dcmtk/dcmdata/dcvrobow.h ../include/dcmtk/dcmdata/dcdeftag.h \ + ../include/dcmtk/dcmdata/dcostrma.h ../include/dcmtk/dcmdata/dcostrmf.h \ + ../include/dcmtk/dcmdata/dcistrma.h ../include/dcmtk/dcmdata/dcistrmf.h \ + ../include/dcmtk/dcmdata/dcwcache.h ../include/dcmtk/dcmdata/dcfcache.h +dcdatutl.o: dcdatutl.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmdata/dcdatutl.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../include/dcmtk/dcmdata/dcdefine.h ../include/dcmtk/dcmdata/dcxfer.h \ + ../include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h ../include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../include/dcmtk/dcmdata/dcdatset.h ../include/dcmtk/dcmdata/dcitem.h \ + ../include/dcmtk/dcmdata/dcobject.h ../include/dcmtk/dcmdata/dcerror.h \ + ../include/dcmtk/dcmdata/dctag.h ../include/dcmtk/dcmdata/dctagkey.h \ + ../include/dcmtk/dcmdata/dcstack.h ../include/dcmtk/dcmdata/dclist.h \ + ../include/dcmtk/dcmdata/dcpcache.h ../include/dcmtk/dcmdata/dcdeftag.h \ + ../include/dcmtk/dcmdata/dcmetinf.h ../include/dcmtk/dcmdata/dcfilefo.h \ + ../include/dcmtk/dcmdata/dcsequen.h ../include/dcmtk/dcmdata/dcelem.h +dcddirif.o: dcddirif.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../include/dcmtk/dcmdata/dcddirif.h ../include/dcmtk/dcmdata/dcdicdir.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../include/dcmtk/dcmdata/dcdirrec.h ../include/dcmtk/dcmdata/dcitem.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../include/dcmtk/dcmdata/dcdefine.h ../include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../include/dcmtk/dcmdata/dcerror.h ../include/dcmtk/dcmdata/dcxfer.h \ + ../include/dcmtk/dcmdata/dcvr.h ../include/dcmtk/dcmdata/dctag.h \ + ../include/dcmtk/dcmdata/dctagkey.h ../include/dcmtk/dcmdata/dcstack.h \ + ../include/dcmtk/dcmdata/dclist.h ../include/dcmtk/dcmdata/dcpcache.h \ + ../include/dcmtk/dcmdata/dcsequen.h ../include/dcmtk/dcmdata/dcelem.h \ + ../include/dcmtk/dcmdata/dcfilefo.h ../include/dcmtk/dcmdata/dcdatset.h \ + ../include/dcmtk/dcmdata/dcvrulup.h ../include/dcmtk/dcmdata/dcvrul.h \ + ../include/dcmtk/dcmdata/dcdeftag.h ../include/dcmtk/dcmdata/dcuid.h \ + ../include/dcmtk/dcmdata/dccodec.h ../include/dcmtk/dcmdata/dcmetinf.h \ + ../include/dcmtk/dcmdata/dcpixel.h ../include/dcmtk/dcmdata/dcvrpobw.h \ + ../include/dcmtk/dcmdata/dcvrobow.h ../include/dcmtk/dcmdata/dcpxitem.h \ + ../include/dcmtk/dcmdata/dcofsetl.h ../include/dcmtk/dcmdata/dcpixseq.h \ + ../include/dcmtk/dcmdata/dcvrcs.h ../include/dcmtk/dcmdata/dcbytstr.h \ + ../include/dcmtk/dcmdata/dcvrda.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../include/dcmtk/dcmdata/dcvrtm.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../../ofstd/include/dcmtk/ofstd/ofbmanip.h +dcdicdir.o: dcdicdir.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../include/dcmtk/dcmdata/dcdicdir.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../include/dcmtk/dcmdata/dcdirrec.h ../include/dcmtk/dcmdata/dcitem.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../include/dcmtk/dcmdata/dcdefine.h ../include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../include/dcmtk/dcmdata/dcerror.h ../include/dcmtk/dcmdata/dcxfer.h \ + ../include/dcmtk/dcmdata/dcvr.h ../include/dcmtk/dcmdata/dctag.h \ + ../include/dcmtk/dcmdata/dctagkey.h ../include/dcmtk/dcmdata/dcstack.h \ + ../include/dcmtk/dcmdata/dclist.h ../include/dcmtk/dcmdata/dcpcache.h \ + ../include/dcmtk/dcmdata/dcsequen.h ../include/dcmtk/dcmdata/dcelem.h \ + ../include/dcmtk/dcmdata/dcfilefo.h ../include/dcmtk/dcmdata/dcdatset.h \ + ../include/dcmtk/dcmdata/dcvrulup.h ../include/dcmtk/dcmdata/dcvrul.h \ + ../include/dcmtk/dcmdata/dcuid.h ../include/dcmtk/dcmdata/dcdeftag.h \ + ../include/dcmtk/dcmdata/dcostrma.h ../include/dcmtk/dcmdata/dcostrmf.h \ + ../include/dcmtk/dcmdata/dcistrmf.h ../include/dcmtk/dcmdata/dcistrma.h \ + ../include/dcmtk/dcmdata/dcvrcs.h ../include/dcmtk/dcmdata/dcbytstr.h \ + ../include/dcmtk/dcmdata/dcvrus.h ../include/dcmtk/dcmdata/dcmetinf.h \ + ../include/dcmtk/dcmdata/dcwcache.h ../include/dcmtk/dcmdata/dcfcache.h \ + ../include/dcmtk/dcmdata/dcvrui.h +dcdicent.o: dcdicent.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../include/dcmtk/dcmdata/dcdicent.h ../include/dcmtk/dcmdata/dctagkey.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../include/dcmtk/dcmdata/dcdefine.h ../include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h +dcdict.o: dcdict.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../include/dcmtk/dcmdata/dcdict.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../include/dcmtk/dcmdata/dchashdi.h ../include/dcmtk/dcmdata/dcdefine.h \ + ../include/dcmtk/dcmdata/dcdicent.h ../include/dcmtk/dcmdata/dctagkey.h \ + ../include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h +dcdictbi.o: dcdictbi.cc ../include/dcmtk/dcmdata/dcdict.h \ + ../../config/include/dcmtk/config/osconfig.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../include/dcmtk/dcmdata/dchashdi.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../include/dcmtk/dcmdata/dcdefine.h +dcdirrec.o: dcdirrec.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../include/dcmtk/dcmdata/dcdirrec.h ../include/dcmtk/dcmdata/dcitem.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../include/dcmtk/dcmdata/dcdefine.h ../include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../include/dcmtk/dcmdata/dcerror.h ../include/dcmtk/dcmdata/dcxfer.h \ + ../include/dcmtk/dcmdata/dcvr.h ../include/dcmtk/dcmdata/dctag.h \ + ../include/dcmtk/dcmdata/dctagkey.h ../include/dcmtk/dcmdata/dcstack.h \ + ../include/dcmtk/dcmdata/dclist.h ../include/dcmtk/dcmdata/dcpcache.h \ + ../include/dcmtk/dcmdata/dcsequen.h ../include/dcmtk/dcmdata/dcelem.h \ + ../include/dcmtk/dcmdata/dcfilefo.h ../include/dcmtk/dcmdata/dcdatset.h \ + ../include/dcmtk/dcmdata/dctk.h ../include/dcmtk/dcmdata/dcswap.h \ + ../include/dcmtk/dcmdata/dcistrma.h ../include/dcmtk/dcmdata/dcostrma.h \ + ../include/dcmtk/dcmdata/dcuid.h ../include/dcmtk/dcmdata/dcdicent.h \ + ../include/dcmtk/dcmdata/dchashdi.h ../include/dcmtk/dcmdata/dcdict.h \ + ../include/dcmtk/dcmdata/dcdeftag.h ../include/dcmtk/dcmdata/dcmetinf.h \ + ../include/dcmtk/dcmdata/dcdicdir.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../include/dcmtk/dcmdata/dcvrulup.h ../include/dcmtk/dcmdata/dcvrul.h \ + ../include/dcmtk/dcmdata/dcpixseq.h ../include/dcmtk/dcmdata/dcofsetl.h \ + ../include/dcmtk/dcmdata/dcbytstr.h ../include/dcmtk/dcmdata/dcvrae.h \ + ../include/dcmtk/dcmdata/dcvras.h ../include/dcmtk/dcmdata/dcvrcs.h \ + ../include/dcmtk/dcmdata/dcvrda.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../include/dcmtk/dcmdata/dcvrds.h ../include/dcmtk/dcmdata/dcvrdt.h \ + ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../include/dcmtk/dcmdata/dcvris.h ../include/dcmtk/dcmdata/dcvrtm.h \ + ../include/dcmtk/dcmdata/dcvrui.h ../include/dcmtk/dcmdata/dcvrur.h \ + ../include/dcmtk/dcmdata/dcchrstr.h ../include/dcmtk/dcmdata/dcvrlo.h \ + ../include/dcmtk/dcmdata/dcvrlt.h ../include/dcmtk/dcmdata/dcvrpn.h \ + ../include/dcmtk/dcmdata/dcvrsh.h ../include/dcmtk/dcmdata/dcvrst.h \ + ../include/dcmtk/dcmdata/dcvruc.h ../include/dcmtk/dcmdata/dcvrut.h \ + ../include/dcmtk/dcmdata/dcvrobow.h ../include/dcmtk/dcmdata/dcpixel.h \ + ../include/dcmtk/dcmdata/dcvrpobw.h ../include/dcmtk/dcmdata/dcovlay.h \ + ../include/dcmtk/dcmdata/dcvrat.h ../include/dcmtk/dcmdata/dcvrss.h \ + ../include/dcmtk/dcmdata/dcvrus.h ../include/dcmtk/dcmdata/dcvrsl.h \ + ../include/dcmtk/dcmdata/dcvrfl.h ../include/dcmtk/dcmdata/dcvrfd.h \ + ../include/dcmtk/dcmdata/dcvrof.h ../include/dcmtk/dcmdata/dcvrod.h \ + ../include/dcmtk/dcmdata/cmdlnarg.h ../include/dcmtk/dcmdata/dcspchrs.h \ + ../../ofstd/include/dcmtk/ofstd/ofchrenc.h +dcelem.o: dcelem.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../include/dcmtk/dcmdata/dcelem.h ../include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../include/dcmtk/dcmdata/dcerror.h ../include/dcmtk/dcmdata/dcdefine.h \ + ../include/dcmtk/dcmdata/dcxfer.h ../include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h ../include/dcmtk/dcmdata/dcvr.h \ + ../include/dcmtk/dcmdata/dctag.h ../include/dcmtk/dcmdata/dctagkey.h \ + ../include/dcmtk/dcmdata/dcstack.h ../include/dcmtk/dcmdata/dcswap.h \ + ../include/dcmtk/dcmdata/dcistrma.h ../include/dcmtk/dcmdata/dcostrma.h \ + ../include/dcmtk/dcmdata/dcfcache.h ../include/dcmtk/dcmdata/dcwcache.h \ + ../include/dcmtk/dcmdata/dcitem.h ../include/dcmtk/dcmdata/dclist.h \ + ../include/dcmtk/dcmdata/dcpcache.h ../include/dcmtk/dcmdata/dcdeftag.h \ + ../include/dcmtk/dcmdata/vrscan.h ../include/dcmtk/dcmdata/dcpath.h \ + ../include/dcmtk/dcmdata/dcdatset.h +dcerror.o: dcerror.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmdata/dcerror.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../include/dcmtk/dcmdata/dcdefine.h +dcfilefo.o: dcfilefo.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../include/dcmtk/dcmdata/dcfilefo.h ../include/dcmtk/dcmdata/dcsequen.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../include/dcmtk/dcmdata/dcelem.h ../include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../include/dcmtk/dcmdata/dcerror.h ../include/dcmtk/dcmdata/dcdefine.h \ + ../include/dcmtk/dcmdata/dcxfer.h ../include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../include/dcmtk/dcmdata/dcvr.h ../include/dcmtk/dcmdata/dctag.h \ + ../include/dcmtk/dcmdata/dctagkey.h ../include/dcmtk/dcmdata/dcstack.h \ + ../include/dcmtk/dcmdata/dclist.h ../include/dcmtk/dcmdata/dcdatset.h \ + ../include/dcmtk/dcmdata/dcitem.h ../include/dcmtk/dcmdata/dcpcache.h \ + ../include/dcmtk/dcmdata/dcvrobow.h ../include/dcmtk/dcmdata/dcvrui.h \ + ../include/dcmtk/dcmdata/dcbytstr.h ../include/dcmtk/dcmdata/dcvrul.h \ + ../include/dcmtk/dcmdata/dcvrus.h ../include/dcmtk/dcmdata/dcvrae.h \ + ../include/dcmtk/dcmdata/dcvrsh.h ../include/dcmtk/dcmdata/dcchrstr.h \ + ../include/dcmtk/dcmdata/dcmetinf.h ../include/dcmtk/dcmdata/dcdeftag.h \ + ../include/dcmtk/dcmdata/dcuid.h ../include/dcmtk/dcmdata/dcostrma.h \ + ../include/dcmtk/dcmdata/dcostrmf.h ../include/dcmtk/dcmdata/dcistrma.h \ + ../include/dcmtk/dcmdata/dcistrmf.h ../include/dcmtk/dcmdata/dcwcache.h \ + ../include/dcmtk/dcmdata/dcfcache.h +dcfilter.o: dcfilter.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmdata/dcfilter.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofalgo.h \ + ../include/dcmtk/dcmdata/dcfilefo.h ../include/dcmtk/dcmdata/dcsequen.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../include/dcmtk/dcmdata/dcelem.h ../include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../include/dcmtk/dcmdata/dcerror.h ../include/dcmtk/dcmdata/dcdefine.h \ + ../include/dcmtk/dcmdata/dcxfer.h ../include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../include/dcmtk/dcmdata/dcvr.h ../include/dcmtk/dcmdata/dctag.h \ + ../include/dcmtk/dcmdata/dctagkey.h ../include/dcmtk/dcmdata/dcstack.h \ + ../include/dcmtk/dcmdata/dclist.h ../include/dcmtk/dcmdata/dcdatset.h \ + ../include/dcmtk/dcmdata/dcitem.h ../include/dcmtk/dcmdata/dcpcache.h +dchashdi.o: dchashdi.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmdata/dchashdi.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../include/dcmtk/dcmdata/dcdefine.h ../include/dcmtk/dcmdata/dcdicent.h \ + ../include/dcmtk/dcmdata/dctagkey.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h +dcistrma.o: dcistrma.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmdata/dcistrma.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../include/dcmtk/dcmdata/dcxfer.h ../include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../include/dcmtk/dcmdata/dcdefine.h ../include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../include/dcmtk/dcmdata/dcistrmz.h ../include/dcmtk/dcmdata/dcerror.h +dcistrmb.o: dcistrmb.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmdata/dcistrmb.h ../include/dcmtk/dcmdata/dcistrma.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../include/dcmtk/dcmdata/dcxfer.h ../include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../include/dcmtk/dcmdata/dcdefine.h ../include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../include/dcmtk/dcmdata/dcerror.h +dcistrmf.o: dcistrmf.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmdata/dcistrmf.h ../include/dcmtk/dcmdata/dcistrma.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../include/dcmtk/dcmdata/dcxfer.h ../include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../include/dcmtk/dcmdata/dcdefine.h ../include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../include/dcmtk/dcmdata/dcerror.h +dcistrmz.o: dcistrmz.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmdata/dcistrmz.h ../include/dcmtk/dcmdata/dcistrma.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../include/dcmtk/dcmdata/dcxfer.h ../include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../include/dcmtk/dcmdata/dcdefine.h ../include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../include/dcmtk/dcmdata/dcerror.h +dcitem.o: dcitem.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../include/dcmtk/dcmdata/dcitem.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../include/dcmtk/dcmdata/dcdefine.h ../include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../include/dcmtk/dcmdata/dcerror.h ../include/dcmtk/dcmdata/dcxfer.h \ + ../include/dcmtk/dcmdata/dcvr.h ../include/dcmtk/dcmdata/dctag.h \ + ../include/dcmtk/dcmdata/dctagkey.h ../include/dcmtk/dcmdata/dcstack.h \ + ../include/dcmtk/dcmdata/dclist.h ../include/dcmtk/dcmdata/dcpcache.h \ + ../include/dcmtk/dcmdata/dcdeftag.h ../include/dcmtk/dcmdata/dcistrma.h \ + ../include/dcmtk/dcmdata/dcostrma.h ../include/dcmtk/dcmdata/dcovlay.h \ + ../include/dcmtk/dcmdata/dcvrpobw.h ../include/dcmtk/dcmdata/dcvrobow.h \ + ../include/dcmtk/dcmdata/dcelem.h ../include/dcmtk/dcmdata/dcpixel.h \ + ../include/dcmtk/dcmdata/dcsequen.h ../include/dcmtk/dcmdata/dcswap.h \ + ../include/dcmtk/dcmdata/dcvrae.h ../include/dcmtk/dcmdata/dcbytstr.h \ + ../include/dcmtk/dcmdata/dcvras.h ../include/dcmtk/dcmdata/dcvrat.h \ + ../include/dcmtk/dcmdata/dcvrcs.h ../include/dcmtk/dcmdata/dcvrda.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../include/dcmtk/dcmdata/dcvrds.h ../include/dcmtk/dcmdata/dcvrdt.h \ + ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../include/dcmtk/dcmdata/dcvrfd.h ../include/dcmtk/dcmdata/dcvrfl.h \ + ../include/dcmtk/dcmdata/dcvris.h ../include/dcmtk/dcmdata/dcvrlo.h \ + ../include/dcmtk/dcmdata/dcchrstr.h ../include/dcmtk/dcmdata/dcvrlt.h \ + ../include/dcmtk/dcmdata/dcvrod.h ../include/dcmtk/dcmdata/dcvrof.h \ + ../include/dcmtk/dcmdata/dcvrpn.h ../include/dcmtk/dcmdata/dcvrsh.h \ + ../include/dcmtk/dcmdata/dcvrsl.h ../include/dcmtk/dcmdata/dcvrss.h \ + ../include/dcmtk/dcmdata/dcvrst.h ../include/dcmtk/dcmdata/dcvrtm.h \ + ../include/dcmtk/dcmdata/dcvruc.h ../include/dcmtk/dcmdata/dcvrui.h \ + ../include/dcmtk/dcmdata/dcvrul.h ../include/dcmtk/dcmdata/dcvrulup.h \ + ../include/dcmtk/dcmdata/dcvrur.h ../include/dcmtk/dcmdata/dcvrus.h \ + ../include/dcmtk/dcmdata/dcvrut.h ../include/dcmtk/dcmdata/dcspchrs.h \ + ../../ofstd/include/dcmtk/ofstd/ofchrenc.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h +dclist.o: dclist.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../include/dcmtk/dcmdata/dclist.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../include/dcmtk/dcmdata/dcerror.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../include/dcmtk/dcmdata/dcdefine.h ../include/dcmtk/dcmdata/dcxfer.h \ + ../include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../include/dcmtk/dcmdata/dcvr.h ../include/dcmtk/dcmdata/dctag.h \ + ../include/dcmtk/dcmdata/dctagkey.h ../include/dcmtk/dcmdata/dcstack.h +dcmetinf.o: dcmetinf.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../include/dcmtk/dcmdata/dcmetinf.h ../include/dcmtk/dcmdata/dcitem.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../include/dcmtk/dcmdata/dcdefine.h ../include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../include/dcmtk/dcmdata/dcerror.h ../include/dcmtk/dcmdata/dcxfer.h \ + ../include/dcmtk/dcmdata/dcvr.h ../include/dcmtk/dcmdata/dctag.h \ + ../include/dcmtk/dcmdata/dctagkey.h ../include/dcmtk/dcmdata/dcstack.h \ + ../include/dcmtk/dcmdata/dclist.h ../include/dcmtk/dcmdata/dcpcache.h \ + ../include/dcmtk/dcmdata/dcvrul.h ../include/dcmtk/dcmdata/dcelem.h \ + ../include/dcmtk/dcmdata/dcdeftag.h ../include/dcmtk/dcmdata/dcistrma.h \ + ../include/dcmtk/dcmdata/dcistrmf.h ../include/dcmtk/dcmdata/dcostrma.h +dcobject.o: dcobject.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../include/dcmtk/dcmdata/dcerror.h ../include/dcmtk/dcmdata/dcdefine.h \ + ../include/dcmtk/dcmdata/dcxfer.h ../include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h ../include/dcmtk/dcmdata/dcvr.h \ + ../include/dcmtk/dcmdata/dctag.h ../include/dcmtk/dcmdata/dctagkey.h \ + ../include/dcmtk/dcmdata/dcstack.h ../include/dcmtk/dcmdata/dcdeftag.h \ + ../include/dcmtk/dcmdata/dcswap.h ../include/dcmtk/dcmdata/dcistrma.h \ + ../include/dcmtk/dcmdata/dcostrma.h +dcostrma.o: dcostrma.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmdata/dcostrma.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../include/dcmtk/dcmdata/dcxfer.h ../include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../include/dcmtk/dcmdata/dcdefine.h ../include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../include/dcmtk/dcmdata/dcostrmz.h ../include/dcmtk/dcmdata/dcerror.h +dcostrmb.o: dcostrmb.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmdata/dcostrmb.h ../include/dcmtk/dcmdata/dcostrma.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../include/dcmtk/dcmdata/dcxfer.h ../include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../include/dcmtk/dcmdata/dcdefine.h ../include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../include/dcmtk/dcmdata/dcerror.h +dcostrmf.o: dcostrmf.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmdata/dcostrmf.h ../include/dcmtk/dcmdata/dcostrma.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../include/dcmtk/dcmdata/dcxfer.h ../include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../include/dcmtk/dcmdata/dcdefine.h ../include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../include/dcmtk/dcmdata/dcerror.h +dcostrmz.o: dcostrmz.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmdata/dcostrmz.h ../include/dcmtk/dcmdata/dcostrma.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../include/dcmtk/dcmdata/dcxfer.h ../include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../include/dcmtk/dcmdata/dcdefine.h ../include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../include/dcmtk/dcmdata/dcerror.h +dcpath.o: dcpath.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmdata/dcpath.h ../include/dcmtk/dcmdata/dcdatset.h \ + ../include/dcmtk/dcmdata/dcitem.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../include/dcmtk/dcmdata/dcdefine.h ../include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../include/dcmtk/dcmdata/dcerror.h ../include/dcmtk/dcmdata/dcxfer.h \ + ../include/dcmtk/dcmdata/dcvr.h ../include/dcmtk/dcmdata/dctag.h \ + ../include/dcmtk/dcmdata/dctagkey.h ../include/dcmtk/dcmdata/dcstack.h \ + ../include/dcmtk/dcmdata/dclist.h ../include/dcmtk/dcmdata/dcpcache.h \ + ../include/dcmtk/dcmdata/dcsequen.h ../include/dcmtk/dcmdata/dcelem.h +dcpcache.o: dcpcache.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmdata/dcpcache.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../include/dcmtk/dcmdata/dctagkey.h ../include/dcmtk/dcmdata/dcdefine.h \ + ../include/dcmtk/dcmdata/dcelem.h ../include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../include/dcmtk/dcmdata/dcerror.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../include/dcmtk/dcmdata/dcxfer.h ../include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../include/dcmtk/dcmdata/dcvr.h ../include/dcmtk/dcmdata/dctag.h \ + ../include/dcmtk/dcmdata/dcstack.h +dcpixel.o: dcpixel.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmdata/dcpixel.h ../include/dcmtk/dcmdata/dcvrpobw.h \ + ../include/dcmtk/dcmdata/dcvrobow.h ../include/dcmtk/dcmdata/dcelem.h \ + ../include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../include/dcmtk/dcmdata/dcerror.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../include/dcmtk/dcmdata/dcdefine.h ../include/dcmtk/dcmdata/dcxfer.h \ + ../include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../include/dcmtk/dcmdata/dcvr.h ../include/dcmtk/dcmdata/dctag.h \ + ../include/dcmtk/dcmdata/dctagkey.h ../include/dcmtk/dcmdata/dcstack.h \ + ../include/dcmtk/dcmdata/dccodec.h ../include/dcmtk/dcmdata/dcpixseq.h \ + ../include/dcmtk/dcmdata/dcsequen.h ../include/dcmtk/dcmdata/dclist.h \ + ../include/dcmtk/dcmdata/dcofsetl.h ../include/dcmtk/dcmdata/dcdeftag.h \ + ../include/dcmtk/dcmdata/dcitem.h ../include/dcmtk/dcmdata/dcpcache.h +dcpixseq.o: dcpixseq.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofuuid.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../include/dcmtk/dcmdata/dcpixseq.h ../include/dcmtk/dcmdata/dcsequen.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../include/dcmtk/dcmdata/dcelem.h ../include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../include/dcmtk/dcmdata/dcerror.h ../include/dcmtk/dcmdata/dcdefine.h \ + ../include/dcmtk/dcmdata/dcxfer.h ../include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../include/dcmtk/dcmdata/dcvr.h ../include/dcmtk/dcmdata/dctag.h \ + ../include/dcmtk/dcmdata/dctagkey.h ../include/dcmtk/dcmdata/dcstack.h \ + ../include/dcmtk/dcmdata/dclist.h ../include/dcmtk/dcmdata/dcofsetl.h \ + ../include/dcmtk/dcmdata/dcpxitem.h ../include/dcmtk/dcmdata/dcvrobow.h \ + ../include/dcmtk/dcmdata/dcitem.h ../include/dcmtk/dcmdata/dcpcache.h \ + ../include/dcmtk/dcmdata/dcdeftag.h +dcpxitem.o: dcpxitem.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../include/dcmtk/dcmdata/dcpxitem.h ../include/dcmtk/dcmdata/dcvrobow.h \ + ../include/dcmtk/dcmdata/dcelem.h ../include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../include/dcmtk/dcmdata/dcerror.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../include/dcmtk/dcmdata/dcdefine.h ../include/dcmtk/dcmdata/dcxfer.h \ + ../include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../include/dcmtk/dcmdata/dcvr.h ../include/dcmtk/dcmdata/dctag.h \ + ../include/dcmtk/dcmdata/dctagkey.h ../include/dcmtk/dcmdata/dcstack.h \ + ../include/dcmtk/dcmdata/dcofsetl.h ../include/dcmtk/dcmdata/dcswap.h \ + ../include/dcmtk/dcmdata/dcistrma.h ../include/dcmtk/dcmdata/dcostrma.h \ + ../include/dcmtk/dcmdata/dcwcache.h ../include/dcmtk/dcmdata/dcfcache.h +dcrleccd.o: dcrleccd.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmdata/dcrleccd.h ../include/dcmtk/dcmdata/dccodec.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../include/dcmtk/dcmdata/dcdefine.h ../include/dcmtk/dcmdata/dcxfer.h \ + ../include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../include/dcmtk/dcmdata/dcrlecp.h ../include/dcmtk/dcmdata/dcrledec.h \ + ../include/dcmtk/dcmdata/dcerror.h ../include/dcmtk/dcmdata/dcdatset.h \ + ../include/dcmtk/dcmdata/dcitem.h ../include/dcmtk/dcmdata/dcobject.h \ + ../include/dcmtk/dcmdata/dctag.h ../include/dcmtk/dcmdata/dctagkey.h \ + ../include/dcmtk/dcmdata/dcstack.h ../include/dcmtk/dcmdata/dclist.h \ + ../include/dcmtk/dcmdata/dcpcache.h ../include/dcmtk/dcmdata/dcdeftag.h \ + ../include/dcmtk/dcmdata/dcpixseq.h ../include/dcmtk/dcmdata/dcsequen.h \ + ../include/dcmtk/dcmdata/dcelem.h ../include/dcmtk/dcmdata/dcofsetl.h \ + ../include/dcmtk/dcmdata/dcpxitem.h ../include/dcmtk/dcmdata/dcvrobow.h \ + ../include/dcmtk/dcmdata/dcvrpobw.h ../include/dcmtk/dcmdata/dcswap.h \ + ../include/dcmtk/dcmdata/dcuid.h +dcrlecce.o: dcrlecce.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmdata/dcrlecce.h ../include/dcmtk/dcmdata/dccodec.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../include/dcmtk/dcmdata/dcdefine.h ../include/dcmtk/dcmdata/dcxfer.h \ + ../include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../include/dcmtk/dcmdata/dcrleenc.h ../include/dcmtk/dcmdata/dcrlecp.h \ + ../include/dcmtk/dcmdata/dcdeftag.h ../include/dcmtk/dcmdata/dctagkey.h \ + ../include/dcmtk/dcmdata/dcpixseq.h ../include/dcmtk/dcmdata/dcsequen.h \ + ../include/dcmtk/dcmdata/dcelem.h ../include/dcmtk/dcmdata/dcobject.h \ + ../include/dcmtk/dcmdata/dcerror.h ../include/dcmtk/dcmdata/dctag.h \ + ../include/dcmtk/dcmdata/dcstack.h ../include/dcmtk/dcmdata/dclist.h \ + ../include/dcmtk/dcmdata/dcofsetl.h ../include/dcmtk/dcmdata/dcpxitem.h \ + ../include/dcmtk/dcmdata/dcvrobow.h ../include/dcmtk/dcmdata/dcswap.h \ + ../include/dcmtk/dcmdata/dcitem.h ../include/dcmtk/dcmdata/dcpcache.h +dcrlecp.o: dcrlecp.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmdata/dcrlecp.h ../include/dcmtk/dcmdata/dccodec.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../include/dcmtk/dcmdata/dcdefine.h ../include/dcmtk/dcmdata/dcxfer.h \ + ../include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h +dcrledrg.o: dcrledrg.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmdata/dcrledrg.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../include/dcmtk/dcmdata/dcdefine.h ../include/dcmtk/dcmdata/dccodec.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../include/dcmtk/dcmdata/dcxfer.h ../include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../include/dcmtk/dcmdata/dcrleccd.h ../include/dcmtk/dcmdata/dcrlecp.h +dcrleerg.o: dcrleerg.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmdata/dcrleerg.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../include/dcmtk/dcmdata/dcdefine.h ../include/dcmtk/dcmdata/dccodec.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../include/dcmtk/dcmdata/dcxfer.h ../include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../include/dcmtk/dcmdata/dcrlecce.h ../include/dcmtk/dcmdata/dcrlecp.h +dcrlerp.o: dcrlerp.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmdata/dcrlerp.h ../include/dcmtk/dcmdata/dcpixel.h \ + ../include/dcmtk/dcmdata/dcvrpobw.h ../include/dcmtk/dcmdata/dcvrobow.h \ + ../include/dcmtk/dcmdata/dcelem.h ../include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../include/dcmtk/dcmdata/dcerror.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../include/dcmtk/dcmdata/dcdefine.h ../include/dcmtk/dcmdata/dcxfer.h \ + ../include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../include/dcmtk/dcmdata/dcvr.h ../include/dcmtk/dcmdata/dctag.h \ + ../include/dcmtk/dcmdata/dctagkey.h ../include/dcmtk/dcmdata/dcstack.h +dcsequen.o: dcsequen.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../include/dcmtk/dcmdata/dcsequen.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../include/dcmtk/dcmdata/dcelem.h ../include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../include/dcmtk/dcmdata/dcerror.h ../include/dcmtk/dcmdata/dcdefine.h \ + ../include/dcmtk/dcmdata/dcxfer.h ../include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../include/dcmtk/dcmdata/dcvr.h ../include/dcmtk/dcmdata/dctag.h \ + ../include/dcmtk/dcmdata/dctagkey.h ../include/dcmtk/dcmdata/dcstack.h \ + ../include/dcmtk/dcmdata/dclist.h ../include/dcmtk/dcmdata/dcitem.h \ + ../include/dcmtk/dcmdata/dcpcache.h ../include/dcmtk/dcmdata/dcdirrec.h \ + ../include/dcmtk/dcmdata/dcfilefo.h ../include/dcmtk/dcmdata/dcdatset.h \ + ../include/dcmtk/dcmdata/dcpxitem.h ../include/dcmtk/dcmdata/dcvrobow.h \ + ../include/dcmtk/dcmdata/dcofsetl.h ../include/dcmtk/dcmdata/dcswap.h \ + ../include/dcmtk/dcmdata/dcmetinf.h ../include/dcmtk/dcmdata/dcdeftag.h \ + ../include/dcmtk/dcmdata/dcistrma.h ../include/dcmtk/dcmdata/dcostrma.h +dcspchrs.o: dcspchrs.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmdata/dcspchrs.h \ + ../../ofstd/include/dcmtk/ofstd/ofchrenc.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../include/dcmtk/dcmdata/dcdefine.h ../include/dcmtk/dcmdata/dcitem.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../include/dcmtk/dcmdata/dcerror.h ../include/dcmtk/dcmdata/dcxfer.h \ + ../include/dcmtk/dcmdata/dcvr.h ../include/dcmtk/dcmdata/dctag.h \ + ../include/dcmtk/dcmdata/dctagkey.h ../include/dcmtk/dcmdata/dcstack.h \ + ../include/dcmtk/dcmdata/dclist.h ../include/dcmtk/dcmdata/dcpcache.h \ + ../include/dcmtk/dcmdata/dcbytstr.h ../include/dcmtk/dcmdata/dcelem.h \ + ../include/dcmtk/dcmdata/dcdeftag.h +dcstack.o: dcstack.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../include/dcmtk/dcmdata/dcstack.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../include/dcmtk/dcmdata/dcdefine.h +dcswap.o: dcswap.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmdata/dcswap.h ../include/dcmtk/dcmdata/dcerror.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../include/dcmtk/dcmdata/dcdefine.h ../include/dcmtk/dcmdata/dcxfer.h \ + ../include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h +dctag.o: dctag.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmdata/dctag.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../include/dcmtk/dcmdata/dctagkey.h ../include/dcmtk/dcmdata/dcdefine.h \ + ../include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../include/dcmtk/dcmdata/dcerror.h ../include/dcmtk/dcmdata/dcdict.h \ + ../include/dcmtk/dcmdata/dchashdi.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../include/dcmtk/dcmdata/dcdicent.h +dctagkey.o: dctagkey.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmdata/dctagkey.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../include/dcmtk/dcmdata/dcdefine.h +dctypes.o: dctypes.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../include/dcmtk/dcmdata/dcdefine.h +dcuid.o: dcuid.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../include/dcmtk/dcmdata/dcuid.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../include/dcmtk/dcmdata/dcdefine.h ../include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../ofstd/include/dcmtk/ofstd/ofcrc32.h \ + ../../ofstd/include/dcmtk/ofstd/ofnetdb.h +dcvr.o: dcvr.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../include/dcmtk/dcmdata/dcdefine.h ../include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h +dcvrae.o: dcvrae.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmdata/dcvrae.h ../include/dcmtk/dcmdata/dcbytstr.h \ + ../include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../include/dcmtk/dcmdata/dcdefine.h ../include/dcmtk/dcmdata/dcelem.h \ + ../include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../include/dcmtk/dcmdata/dcerror.h ../include/dcmtk/dcmdata/dcxfer.h \ + ../include/dcmtk/dcmdata/dcvr.h ../include/dcmtk/dcmdata/dctag.h \ + ../include/dcmtk/dcmdata/dctagkey.h ../include/dcmtk/dcmdata/dcstack.h +dcvras.o: dcvras.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmdata/dcvras.h ../include/dcmtk/dcmdata/dcbytstr.h \ + ../include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../include/dcmtk/dcmdata/dcdefine.h ../include/dcmtk/dcmdata/dcelem.h \ + ../include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../include/dcmtk/dcmdata/dcerror.h ../include/dcmtk/dcmdata/dcxfer.h \ + ../include/dcmtk/dcmdata/dcvr.h ../include/dcmtk/dcmdata/dctag.h \ + ../include/dcmtk/dcmdata/dctagkey.h ../include/dcmtk/dcmdata/dcstack.h +dcvrat.o: dcvrat.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../include/dcmtk/dcmdata/dcvrat.h ../include/dcmtk/dcmdata/dcelem.h \ + ../include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../include/dcmtk/dcmdata/dcerror.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../include/dcmtk/dcmdata/dcdefine.h ../include/dcmtk/dcmdata/dcxfer.h \ + ../include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../include/dcmtk/dcmdata/dcvr.h ../include/dcmtk/dcmdata/dctag.h \ + ../include/dcmtk/dcmdata/dctagkey.h ../include/dcmtk/dcmdata/dcstack.h +dcvrcs.o: dcvrcs.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../include/dcmtk/dcmdata/dcvrcs.h ../include/dcmtk/dcmdata/dcbytstr.h \ + ../include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../include/dcmtk/dcmdata/dcdefine.h ../include/dcmtk/dcmdata/dcelem.h \ + ../include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../include/dcmtk/dcmdata/dcerror.h ../include/dcmtk/dcmdata/dcxfer.h \ + ../include/dcmtk/dcmdata/dcvr.h ../include/dcmtk/dcmdata/dctag.h \ + ../include/dcmtk/dcmdata/dctagkey.h ../include/dcmtk/dcmdata/dcstack.h +dcvrda.o: dcvrda.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmdata/dcvrda.h ../include/dcmtk/dcmdata/dcbytstr.h \ + ../include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../include/dcmtk/dcmdata/dcdefine.h ../include/dcmtk/dcmdata/dcelem.h \ + ../include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../include/dcmtk/dcmdata/dcerror.h ../include/dcmtk/dcmdata/dcxfer.h \ + ../include/dcmtk/dcmdata/dcvr.h ../include/dcmtk/dcmdata/dctag.h \ + ../include/dcmtk/dcmdata/dctagkey.h ../include/dcmtk/dcmdata/dcstack.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h +dcvrds.o: dcvrds.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmdata/dcvrds.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../include/dcmtk/dcmdata/dcbytstr.h ../include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../include/dcmtk/dcmdata/dcdefine.h ../include/dcmtk/dcmdata/dcelem.h \ + ../include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../include/dcmtk/dcmdata/dcerror.h ../include/dcmtk/dcmdata/dcxfer.h \ + ../include/dcmtk/dcmdata/dcvr.h ../include/dcmtk/dcmdata/dctag.h \ + ../include/dcmtk/dcmdata/dctagkey.h ../include/dcmtk/dcmdata/dcstack.h +dcvrdt.o: dcvrdt.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmdata/dcvrdt.h ../include/dcmtk/dcmdata/dcbytstr.h \ + ../include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../include/dcmtk/dcmdata/dcdefine.h ../include/dcmtk/dcmdata/dcelem.h \ + ../include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../include/dcmtk/dcmdata/dcerror.h ../include/dcmtk/dcmdata/dcxfer.h \ + ../include/dcmtk/dcmdata/dcvr.h ../include/dcmtk/dcmdata/dctag.h \ + ../include/dcmtk/dcmdata/dctagkey.h ../include/dcmtk/dcmdata/dcstack.h \ + ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../include/dcmtk/dcmdata/dcvrda.h ../include/dcmtk/dcmdata/dcvrtm.h +dcvrfd.o: dcvrfd.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../include/dcmtk/dcmdata/dcvrfd.h ../include/dcmtk/dcmdata/dcelem.h \ + ../include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../include/dcmtk/dcmdata/dcerror.h ../include/dcmtk/dcmdata/dcdefine.h \ + ../include/dcmtk/dcmdata/dcxfer.h ../include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h ../include/dcmtk/dcmdata/dcvr.h \ + ../include/dcmtk/dcmdata/dctag.h ../include/dcmtk/dcmdata/dctagkey.h \ + ../include/dcmtk/dcmdata/dcstack.h +dcvrfl.o: dcvrfl.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../include/dcmtk/dcmdata/dcvrfl.h ../include/dcmtk/dcmdata/dcelem.h \ + ../include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../include/dcmtk/dcmdata/dcerror.h ../include/dcmtk/dcmdata/dcdefine.h \ + ../include/dcmtk/dcmdata/dcxfer.h ../include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h ../include/dcmtk/dcmdata/dcvr.h \ + ../include/dcmtk/dcmdata/dctag.h ../include/dcmtk/dcmdata/dctagkey.h \ + ../include/dcmtk/dcmdata/dcstack.h +dcvris.o: dcvris.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmdata/dcvris.h ../include/dcmtk/dcmdata/dcbytstr.h \ + ../include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../include/dcmtk/dcmdata/dcdefine.h ../include/dcmtk/dcmdata/dcelem.h \ + ../include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../include/dcmtk/dcmdata/dcerror.h ../include/dcmtk/dcmdata/dcxfer.h \ + ../include/dcmtk/dcmdata/dcvr.h ../include/dcmtk/dcmdata/dctag.h \ + ../include/dcmtk/dcmdata/dctagkey.h ../include/dcmtk/dcmdata/dcstack.h +dcvrlo.o: dcvrlo.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmdata/dcvrlo.h ../include/dcmtk/dcmdata/dcchrstr.h \ + ../include/dcmtk/dcmdata/dcbytstr.h ../include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../include/dcmtk/dcmdata/dcdefine.h ../include/dcmtk/dcmdata/dcelem.h \ + ../include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../include/dcmtk/dcmdata/dcerror.h ../include/dcmtk/dcmdata/dcxfer.h \ + ../include/dcmtk/dcmdata/dcvr.h ../include/dcmtk/dcmdata/dctag.h \ + ../include/dcmtk/dcmdata/dctagkey.h ../include/dcmtk/dcmdata/dcstack.h +dcvrlt.o: dcvrlt.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmdata/dcvrlt.h ../include/dcmtk/dcmdata/dcchrstr.h \ + ../include/dcmtk/dcmdata/dcbytstr.h ../include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../include/dcmtk/dcmdata/dcdefine.h ../include/dcmtk/dcmdata/dcelem.h \ + ../include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../include/dcmtk/dcmdata/dcerror.h ../include/dcmtk/dcmdata/dcxfer.h \ + ../include/dcmtk/dcmdata/dcvr.h ../include/dcmtk/dcmdata/dctag.h \ + ../include/dcmtk/dcmdata/dctagkey.h ../include/dcmtk/dcmdata/dcstack.h +dcvrobow.o: dcvrobow.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../ofstd/include/dcmtk/ofstd/ofuuid.h \ + ../include/dcmtk/dcmdata/dcvrobow.h ../include/dcmtk/dcmdata/dcelem.h \ + ../include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../include/dcmtk/dcmdata/dcerror.h ../include/dcmtk/dcmdata/dcdefine.h \ + ../include/dcmtk/dcmdata/dcxfer.h ../include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h ../include/dcmtk/dcmdata/dcvr.h \ + ../include/dcmtk/dcmdata/dctag.h ../include/dcmtk/dcmdata/dctagkey.h \ + ../include/dcmtk/dcmdata/dcstack.h ../include/dcmtk/dcmdata/dcdeftag.h \ + ../include/dcmtk/dcmdata/dcswap.h ../include/dcmtk/dcmdata/dcuid.h +dcvrod.o: dcvrod.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../ofstd/include/dcmtk/ofstd/ofuuid.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../include/dcmtk/dcmdata/dcvrod.h ../include/dcmtk/dcmdata/dcvrfd.h \ + ../include/dcmtk/dcmdata/dcelem.h ../include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../include/dcmtk/dcmdata/dcerror.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../include/dcmtk/dcmdata/dcdefine.h ../include/dcmtk/dcmdata/dcxfer.h \ + ../include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../include/dcmtk/dcmdata/dcvr.h ../include/dcmtk/dcmdata/dctag.h \ + ../include/dcmtk/dcmdata/dctagkey.h ../include/dcmtk/dcmdata/dcstack.h \ + ../include/dcmtk/dcmdata/dcswap.h ../include/dcmtk/dcmdata/dcuid.h +dcvrof.o: dcvrof.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../ofstd/include/dcmtk/ofstd/ofuuid.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../include/dcmtk/dcmdata/dcvrof.h ../include/dcmtk/dcmdata/dcvrfl.h \ + ../include/dcmtk/dcmdata/dcelem.h ../include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../include/dcmtk/dcmdata/dcerror.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../include/dcmtk/dcmdata/dcdefine.h ../include/dcmtk/dcmdata/dcxfer.h \ + ../include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../include/dcmtk/dcmdata/dcvr.h ../include/dcmtk/dcmdata/dctag.h \ + ../include/dcmtk/dcmdata/dctagkey.h ../include/dcmtk/dcmdata/dcstack.h \ + ../include/dcmtk/dcmdata/dcswap.h ../include/dcmtk/dcmdata/dcuid.h +dcvrpn.o: dcvrpn.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmdata/dcvrpn.h ../include/dcmtk/dcmdata/dcchrstr.h \ + ../include/dcmtk/dcmdata/dcbytstr.h ../include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../include/dcmtk/dcmdata/dcdefine.h ../include/dcmtk/dcmdata/dcelem.h \ + ../include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../include/dcmtk/dcmdata/dcerror.h ../include/dcmtk/dcmdata/dcxfer.h \ + ../include/dcmtk/dcmdata/dcvr.h ../include/dcmtk/dcmdata/dctag.h \ + ../include/dcmtk/dcmdata/dctagkey.h ../include/dcmtk/dcmdata/dcstack.h +dcvrpobw.o: dcvrpobw.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmdata/dcvrpobw.h ../include/dcmtk/dcmdata/dcvrobow.h \ + ../include/dcmtk/dcmdata/dcelem.h ../include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../include/dcmtk/dcmdata/dcerror.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../include/dcmtk/dcmdata/dcdefine.h ../include/dcmtk/dcmdata/dcxfer.h \ + ../include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../include/dcmtk/dcmdata/dcvr.h ../include/dcmtk/dcmdata/dctag.h \ + ../include/dcmtk/dcmdata/dctagkey.h ../include/dcmtk/dcmdata/dcstack.h +dcvrsh.o: dcvrsh.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmdata/dcvrsh.h ../include/dcmtk/dcmdata/dcchrstr.h \ + ../include/dcmtk/dcmdata/dcbytstr.h ../include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../include/dcmtk/dcmdata/dcdefine.h ../include/dcmtk/dcmdata/dcelem.h \ + ../include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../include/dcmtk/dcmdata/dcerror.h ../include/dcmtk/dcmdata/dcxfer.h \ + ../include/dcmtk/dcmdata/dcvr.h ../include/dcmtk/dcmdata/dctag.h \ + ../include/dcmtk/dcmdata/dctagkey.h ../include/dcmtk/dcmdata/dcstack.h +dcvrsl.o: dcvrsl.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../include/dcmtk/dcmdata/dcvrsl.h ../include/dcmtk/dcmdata/dcelem.h \ + ../include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../include/dcmtk/dcmdata/dcerror.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../include/dcmtk/dcmdata/dcdefine.h ../include/dcmtk/dcmdata/dcxfer.h \ + ../include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../include/dcmtk/dcmdata/dcvr.h ../include/dcmtk/dcmdata/dctag.h \ + ../include/dcmtk/dcmdata/dctagkey.h ../include/dcmtk/dcmdata/dcstack.h +dcvrss.o: dcvrss.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../include/dcmtk/dcmdata/dcvrss.h ../include/dcmtk/dcmdata/dcelem.h \ + ../include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../include/dcmtk/dcmdata/dcerror.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../include/dcmtk/dcmdata/dcdefine.h ../include/dcmtk/dcmdata/dcxfer.h \ + ../include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../include/dcmtk/dcmdata/dcvr.h ../include/dcmtk/dcmdata/dctag.h \ + ../include/dcmtk/dcmdata/dctagkey.h ../include/dcmtk/dcmdata/dcstack.h +dcvrst.o: dcvrst.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmdata/dcvrst.h ../include/dcmtk/dcmdata/dcchrstr.h \ + ../include/dcmtk/dcmdata/dcbytstr.h ../include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../include/dcmtk/dcmdata/dcdefine.h ../include/dcmtk/dcmdata/dcelem.h \ + ../include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../include/dcmtk/dcmdata/dcerror.h ../include/dcmtk/dcmdata/dcxfer.h \ + ../include/dcmtk/dcmdata/dcvr.h ../include/dcmtk/dcmdata/dctag.h \ + ../include/dcmtk/dcmdata/dctagkey.h ../include/dcmtk/dcmdata/dcstack.h +dcvrtm.o: dcvrtm.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmdata/dcvrtm.h ../include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../include/dcmtk/dcmdata/dcdefine.h ../include/dcmtk/dcmdata/dcbytstr.h \ + ../include/dcmtk/dcmdata/dcelem.h ../include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../include/dcmtk/dcmdata/dcerror.h ../include/dcmtk/dcmdata/dcxfer.h \ + ../include/dcmtk/dcmdata/dcvr.h ../include/dcmtk/dcmdata/dctag.h \ + ../include/dcmtk/dcmdata/dctagkey.h ../include/dcmtk/dcmdata/dcstack.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h +dcvruc.o: dcvruc.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmdata/dcvruc.h ../include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../include/dcmtk/dcmdata/dcdefine.h ../include/dcmtk/dcmdata/dcchrstr.h \ + ../include/dcmtk/dcmdata/dcbytstr.h ../include/dcmtk/dcmdata/dcelem.h \ + ../include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../include/dcmtk/dcmdata/dcerror.h ../include/dcmtk/dcmdata/dcxfer.h \ + ../include/dcmtk/dcmdata/dcvr.h ../include/dcmtk/dcmdata/dctag.h \ + ../include/dcmtk/dcmdata/dctagkey.h ../include/dcmtk/dcmdata/dcstack.h +dcvrui.o: dcvrui.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../include/dcmtk/dcmdata/dcvrui.h ../include/dcmtk/dcmdata/dcbytstr.h \ + ../include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../include/dcmtk/dcmdata/dcdefine.h ../include/dcmtk/dcmdata/dcelem.h \ + ../include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../include/dcmtk/dcmdata/dcerror.h ../include/dcmtk/dcmdata/dcxfer.h \ + ../include/dcmtk/dcmdata/dcvr.h ../include/dcmtk/dcmdata/dctag.h \ + ../include/dcmtk/dcmdata/dctagkey.h ../include/dcmtk/dcmdata/dcstack.h \ + ../include/dcmtk/dcmdata/dcuid.h +dcvrul.o: dcvrul.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../include/dcmtk/dcmdata/dcvrul.h ../include/dcmtk/dcmdata/dcelem.h \ + ../include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../include/dcmtk/dcmdata/dcerror.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../include/dcmtk/dcmdata/dcdefine.h ../include/dcmtk/dcmdata/dcxfer.h \ + ../include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../include/dcmtk/dcmdata/dcvr.h ../include/dcmtk/dcmdata/dctag.h \ + ../include/dcmtk/dcmdata/dctagkey.h ../include/dcmtk/dcmdata/dcstack.h +dcvrulup.o: dcvrulup.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmdata/dcvrulup.h ../include/dcmtk/dcmdata/dcvrul.h \ + ../include/dcmtk/dcmdata/dcelem.h ../include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../include/dcmtk/dcmdata/dcerror.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../include/dcmtk/dcmdata/dcdefine.h ../include/dcmtk/dcmdata/dcxfer.h \ + ../include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../include/dcmtk/dcmdata/dcvr.h ../include/dcmtk/dcmdata/dctag.h \ + ../include/dcmtk/dcmdata/dctagkey.h ../include/dcmtk/dcmdata/dcstack.h +dcvrur.o: dcvrur.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmdata/dcvrur.h ../include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../include/dcmtk/dcmdata/dcdefine.h ../include/dcmtk/dcmdata/dcbytstr.h \ + ../include/dcmtk/dcmdata/dcelem.h ../include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../include/dcmtk/dcmdata/dcerror.h ../include/dcmtk/dcmdata/dcxfer.h \ + ../include/dcmtk/dcmdata/dcvr.h ../include/dcmtk/dcmdata/dctag.h \ + ../include/dcmtk/dcmdata/dctagkey.h ../include/dcmtk/dcmdata/dcstack.h +dcvrus.o: dcvrus.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../include/dcmtk/dcmdata/dcvrus.h ../include/dcmtk/dcmdata/dcelem.h \ + ../include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../include/dcmtk/dcmdata/dcerror.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../include/dcmtk/dcmdata/dcdefine.h ../include/dcmtk/dcmdata/dcxfer.h \ + ../include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../include/dcmtk/dcmdata/dcvr.h ../include/dcmtk/dcmdata/dctag.h \ + ../include/dcmtk/dcmdata/dctagkey.h ../include/dcmtk/dcmdata/dcstack.h +dcvrut.o: dcvrut.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmdata/dcvrut.h ../include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../include/dcmtk/dcmdata/dcdefine.h ../include/dcmtk/dcmdata/dcchrstr.h \ + ../include/dcmtk/dcmdata/dcbytstr.h ../include/dcmtk/dcmdata/dcelem.h \ + ../include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../include/dcmtk/dcmdata/dcerror.h ../include/dcmtk/dcmdata/dcxfer.h \ + ../include/dcmtk/dcmdata/dcvr.h ../include/dcmtk/dcmdata/dctag.h \ + ../include/dcmtk/dcmdata/dctagkey.h ../include/dcmtk/dcmdata/dcstack.h +dcwcache.o: dcwcache.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmdata/dcwcache.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../include/dcmtk/dcmdata/dcfcache.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../include/dcmtk/dcmdata/dcistrma.h ../include/dcmtk/dcmdata/dcxfer.h \ + ../include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../include/dcmtk/dcmdata/dcdefine.h ../include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../include/dcmtk/dcmdata/dcelem.h ../include/dcmtk/dcmdata/dcobject.h \ + ../include/dcmtk/dcmdata/dcerror.h ../include/dcmtk/dcmdata/dctag.h \ + ../include/dcmtk/dcmdata/dctagkey.h ../include/dcmtk/dcmdata/dcstack.h \ + ../include/dcmtk/dcmdata/dcostrma.h +dcxfer.o: dcxfer.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmdata/dcxfer.h ../include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../include/dcmtk/dcmdata/dcdefine.h ../include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../include/dcmtk/dcmdata/dcuid.h +mkdeftag.o: mkdeftag.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmdata/dcdict.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../include/dcmtk/dcmdata/dchashdi.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../include/dcmtk/dcmdata/dcdefine.h ../include/dcmtk/dcmdata/cmdlnarg.h \ + ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../include/dcmtk/dcmdata/dcdicent.h ../include/dcmtk/dcmdata/dctagkey.h \ + ../include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h +mkdictbi.o: mkdictbi.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmdata/dcdict.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../include/dcmtk/dcmdata/dchashdi.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../include/dcmtk/dcmdata/dcdefine.h ../include/dcmtk/dcmdata/cmdlnarg.h \ + ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../include/dcmtk/dcmdata/dcdicent.h ../include/dcmtk/dcmdata/dctagkey.h \ + ../include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h +vrscan.o: vrscan.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmdata/vrscan.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../include/dcmtk/dcmdata/dcdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofbmanip.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h vrscani.h vrscanl.h diff --git a/dcmdata/libsrc/Makefile.in b/dcmdata/libsrc/Makefile.in new file mode 100644 index 00000000..ab80da90 --- /dev/null +++ b/dcmdata/libsrc/Makefile.in @@ -0,0 +1,110 @@ +# +# Makefile for dcmdata/libsrc +# + +@SET_MAKE@ + +SHELL = /bin/sh +VPATH = @srcdir@:@top_srcdir@/include:@top_srcdir@/@configdir@/include +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +configdir = @top_srcdir@/@configdir@ + +include $(configdir)/@common_makefile@ + +ofstddir = $(top_srcdir)/../ofstd +oflogdir = $(top_srcdir)/../oflog + +LOCALINCLUDES = -I$(ofstddir)/include -I$(oflogdir)/include +LIBDIRS = -L$(ofstddir)/libsrc -L$(oflogdir)/libsrc +LOCALLIBS = -loflog -lofstd $(ICONVLIBS) +LOCALDEFS = + +# clear environment variable in the scope of this makefile +DCMDICTPATH = + +# Special defines for the Library, define them in LOCALDEFS +# DICOMDIR_WITHOUT_BACKUP +# no Backup for DICOMDIR files. default: not defined +# PRINT_REPLACED_DICTIONARY_ENTRIES +# dump duplicate entries in the data dictionary to stderr + +dicomdic = $(top_srcdir)/data/dicom.dic +privatedic = $(top_srcdir)/data/private.dic + +# Dictionary objects for building the helper tools mkdeftag and mkdictbi +dict_tools_objs = dctagkey.o dcdicent.o dcdict.o dcvr.o dchashdi.o + +objs = dcpixseq.o dcpxitem.o dcuid.o dcerror.o \ + dcstack.o dclist.o dcswap.o dctag.o dcxfer.o \ + dcobject.o dcelem.o dcitem.o dcmetinf.o dcdatset.o dcdatutl.o dcspchrs.o \ + dcsequen.o dcfilefo.o dcbytstr.o dcpixel.o dcvrae.o dcvras.o dcvrcs.o \ + dccodec.o dcvrda.o dcvrds.o dcvrdt.o dcvris.o dcvrtm.o dcvrui.o \ + dcchrstr.o dcvrlo.o dcvrlt.o dcvrpn.o dcvrsh.o dcvrst.o dcvrobow.o \ + dcvrat.o dcvrss.o dcvrus.o dcvrsl.o dcvrul.o dcvrulup.o dcvrfl.o \ + dcvrfd.o dcvrpobw.o dcvrof.o dcvrod.o dcdirrec.o dcdicdir.o \ + dcrleccd.o dcrlecce.o dcrlecp.o dcrlerp.o dcrledrg.o dcrleerg.o \ + dcdictbi.o dctagkey.o dcdicent.o dcdict.o dcvr.o dchashdi.o cmdlnarg.o \ + dcvrut.o dcvrur.o dcvruc.o dctypes.o dcpcache.o dcddirif.o dcistrma.o \ + dcistrmb.o dcistrmf.o dcistrmz.o dcostrma.o dcostrmb.o dcostrmf.o \ + dcostrmz.o dcwcache.o dcpath.o vrscan.o vrscanl.o dcfilter.o + +support_objs = mkdeftag.o mkdictbi.o +support_progs = mkdeftag mkdictbi + +# Extra objects needed by support_progs +support_progs_objs = cmdlnarg.o dctypes.o + +library = libdcmdata.$(LIBEXT) + + +all: $(library) + +install: install-lib install-support + +install-lib: $(library) + $(configdir)/mkinstalldirs $(DESTDIR)$(libdir) + $(INSTALL_DATA) $(library) $(DESTDIR)$(libdir)/$(library) + $(RANLIB) $(DESTDIR)$(libdir)/$(library) + + +$(library): $(objs) + $(AR) $(ARFLAGS) $@ $(objs) + $(RANLIB) $@ + +mkdeftag: mkdeftag.o $(dict_tools_objs) $(support_progs_objs) + $(CXX) $(CXXFLAGS) $(LIBDIRS) $(LDFLAGS) -o $@ $@.o $(dict_tools_objs) $(support_progs_objs) $(LOCALLIBS) $(LIBS) + +mkdictbi: mkdictbi.o $(dict_tools_objs) $(support_progs_objs) + $(CXX) $(CXXFLAGS) $(LIBDIRS) $(LDFLAGS) -o $@ $@.o $(dict_tools_objs) $(support_progs_objs) $(LOCALLIBS) $(LIBS) + +mkvrscan: + flex -8 --header-file=vrscanl.h --outfile=vrscanl.c vrscanl.l + + +# Generate a new include file of defined tags + +updatedeftag: mkdeftag $(dicomdic) $(privatedic) + `pwd`/mkdeftag -o $(top_srcdir)/include/dcmtk/dcmdata/dcdeftag.h $(dicomdic) $(privatedic) + +# Generate a builtin data dictionary from $(dicomdic) and $(privatedic) + +updatebuiltindict: mkdictbi $(dicomdic) $(privatedic) + `pwd`/mkdictbi $(dicomdic) $(privatedic) > dcdictbi.cc + + +# Clean-up + +clean: + rm -f $(support_progs) $(support_objs) $(objs) $(library) $(TRASH) + +distclean: clean + rm -f $(DISTTRASH) + + +# Dependencies + +dependencies: + $(CXX) -MM $(defines) $(includes) $(CPPFLAGS) $(CXXFLAGS) *.cc > $(DEP) + +include $(DEP) diff --git a/dcmdata/libsrc/cmdlnarg.cc b/dcmdata/libsrc/cmdlnarg.cc new file mode 100644 index 00000000..1580391b --- /dev/null +++ b/dcmdata/libsrc/cmdlnarg.cc @@ -0,0 +1,171 @@ +/* + * + * Copyright (C) 1996-2012, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Andrew Hewett + * + * Purpose: Provide prototype of command line argument gathering routine + * for OS environments which cannot pass arguments on the command line. + * + */ + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/dcmdata/cmdlnarg.h" +#include "dcmtk/dcmdata/dctypes.h" + +/* +** prepareCmdLineArgs +** +** Should do nothing on Unix OS's. +** On other OS's (e.g. MacOS with CW6) allows command line arguments +** to be input from the standard input. +*/ + +#ifdef HAVE_EMPTY_ARGC_ARGV + +#define INCLUDE_CSTDLIB +#define INCLUDE_CSTDIO +#define INCLUDE_CSTRING +#include "dcmtk/ofstd/ofstdinc.h" + +#include "dcmtk/ofstd/ofstream.h" + +void prepareCmdLineArgs(int& argc, char* argv[], + const char* progname) +{ + const int bufsize = 2024; + char buf[bufsize]; + char arg[1024]; + + argv[0] = new char[strlen(progname)+1]; + strcpy(argv[0], progname); + argc = 1; + + ofConsole.lockCout() << "CmdLineArgs-> "; + ofConsole.unlockCout(); + cin.getline(buf, bufsize); + + istringstream is(buf); + + arg[0] = '\0'; + while (is.good()) { + is >> arg; + if (strlen(arg) > 0) { + argv[argc] = new char[strlen(arg)+1]; + strcpy(argv[argc], arg); + argc++; + } + arg[0] = '\0'; + } +} + +#else // HAVE_EMPTY_ARGC_ARGV + +#define INCLUDE_CSTDLIB +#define INCLUDE_CSTDIO +#define INCLUDE_CSTRING +#include "dcmtk/ofstd/ofstdinc.h" + +#ifdef HAVE_IO_H +#include +#endif + +BEGIN_EXTERN_C +#ifdef HAVE_FCNTL_H +#include /* for O_BINARY */ +#endif +END_EXTERN_C + +#include "dcmtk/ofstd/ofstd.h" +#include "dcmtk/ofstd/ofstream.h" + +void prepareCmdLineArgs(int& /* argc */, char** /* argv */, + const char* /* progname */) +{ +#ifdef _WIN32 +#ifndef DCMTK_GUI +#ifndef __CYGWIN__ + /* Map stderr onto stdout (cannot redirect stderr under Windows). + * Remove any buffering (windows uses a 2k buffer for stdout when not + * writing to the console. since dcmtk uses mixed stdout, stderr + * cout and cerr, this results in _very_ mixed up output). + */ + + /* first of all, check whether stderr and stdout file descriptors are + * already the same, e.g. from a previous call of this function + */ + if (fileno(stderr) != fileno(stdout)) + { + /* duplicate the stderr file descriptor to be the same as stdout */ + close(fileno(stderr)); + int fderr = dup(fileno(stdout)); + if (fderr != fileno(stderr)) + { + char buf[256]; + DCMDATA_ERROR("INTERNAL ERROR: cannot map stderr to stdout: " + << OFStandard::strerror(errno, buf, sizeof(buf))); + } + } + +#ifndef NO_IOS_BASE_ASSIGN + /* make cout refer to cerr. This does not work with all iostream implementations :-( */ + cout = cerr; +#endif + + /* make stdout the same as stderr */ + *stdout = *stderr; + +#ifdef USE_BINARY_MODE_FOR_STDOUT_ON_WINDOWS + /* use binary mode for stdout in order to be more consistent with common Unix behavior */ + setmode(fileno(stdout), O_BINARY); +#endif + +#ifndef __BORLANDC__ /* setvbuf on stdout/stderr does not work with Borland C++ */ + /* make sure the buffering is removed */ + if (setvbuf(stdout, NULL, _IONBF, 0 ) != 0 ) + { + char buf[256]; + DCMDATA_ERROR("INTERNAL ERROR: cannot unbuffer stdout: " + << OFStandard::strerror(errno, buf, sizeof(buf))); + } + if (setvbuf(stderr, NULL, _IONBF, 0 ) != 0 ) + { + char buf[256]; + DCMDATA_ERROR("INTERNAL ERROR: cannot unbuffer stderr: " + << OFStandard::strerror(errno, buf, sizeof(buf))); + } +#endif /* __BORLANDC__ */ +#endif +#endif +#endif + + /* no need to process the arguments */ +} + + +#ifdef HAVE_WINDOWS_H + +void prepareCmdLineArgs(int& argc, wchar_t** /* argv */, + const char* progname) +{ + // value of parameters is ignored anyway + char** argv = NULL; + prepareCmdLineArgs(argc, argv, progname); +} + +#endif // HAVE_WINDOWS_H + + +#endif // HAVE_EMPTY_ARGC_ARGV diff --git a/dcmdata/libsrc/dcbytstr.cc b/dcmdata/libsrc/dcbytstr.cc new file mode 100644 index 00000000..1a471be5 --- /dev/null +++ b/dcmdata/libsrc/dcbytstr.cc @@ -0,0 +1,870 @@ +/* + * + * Copyright (C) 1994-2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Gerd Ehlers, Andreas Barth + * + * Purpose: Implementation of class DcmByteString + * + */ + + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ +#include "dcmtk/ofstd/ofstream.h" +#include "dcmtk/ofstd/ofstring.h" +#include "dcmtk/ofstd/ofstd.h" +#include "dcmtk/dcmdata/dcbytstr.h" +#include "dcmtk/dcmdata/dcvr.h" + +#define INCLUDE_CSTDLIB +#define INCLUDE_CSTDIO +#define INCLUDE_CSTRING +#define INCLUDE_NEW +#include "dcmtk/ofstd/ofstdinc.h" + + +// global flags + +OFGlobal dcmEnableVRCheckerForStringValues(OFTrue); + + +// global function to get a particular component of a DICOM string +OFCondition getStringPart(OFString &result, + const char *str, + const unsigned long len, + const unsigned long pos) +{ + OFCondition l_error = EC_Normal; + /* check string parameter */ + if (str != NULL) + { + /* search for beginning of specified string component */ + unsigned long i = 0; + unsigned long curPos = 0; + while ((curPos < pos) && (i++ < len)) + { + if (*str++ == '\\') + curPos++; + } + /* if found ... */ + if (curPos == pos) + { + /* search for end of specified string component */ + const char *p = str; + while ((*p != '\\') && (i++ < len)) + p++; + /* check whether string component is non-empty */ + if (p - str > 0) + result.assign(str, p - str); + else + result.clear(); + } else { + /* specified component index not found in string */ + l_error = EC_IllegalParameter; + } + } else + l_error = EC_IllegalParameter; + return l_error; +} + + +// ******************************** + + +DcmByteString::DcmByteString(const DcmTag &tag, + const Uint32 len) + : DcmElement(tag, len), + paddingChar(' '), + maxLength(DCM_UndefinedLength), + realLength(len), + fStringMode(DCM_UnknownString), + nonSignificantChars() +{ +} + + +DcmByteString::DcmByteString(const DcmByteString &old) + : DcmElement(old), + paddingChar(old.paddingChar), + maxLength(old.maxLength), + realLength(old.realLength), + fStringMode(old.fStringMode), + nonSignificantChars(old.nonSignificantChars) +{ +} + + +DcmByteString::~DcmByteString() +{ +} + + +DcmByteString &DcmByteString::operator=(const DcmByteString &obj) +{ + if (this != &obj) + { + DcmElement::operator=(obj); + + /* copy member variables */ + paddingChar = obj.paddingChar; + maxLength = obj.maxLength; + realLength = obj.realLength; + fStringMode = obj.fStringMode; + nonSignificantChars = obj.nonSignificantChars; + } + return *this; +} + + +int DcmByteString::compare(const DcmElement& rhs) const +{ + int result = DcmElement::compare(rhs); + if (result != 0) + { + return result; + } + + /* cast away constness (dcmdata is not const correct...) */ + DcmByteString* myThis = NULL; + DcmByteString* myRhs = NULL; + myThis = OFconst_cast(DcmByteString*, this); + myRhs = OFstatic_cast(DcmByteString*, OFconst_cast(DcmElement*, &rhs)); + + /* iterate over all components and test equality */ + unsigned long thisVM = myThis->getVM(); + for (unsigned long count = 0; count < thisVM; count++) + { + OFString val; + if (myThis->getOFString(val, count).good()) + { + OFString rhsVal; + if (myRhs->getOFString(rhsVal, count).good()) + { + int result = val.compare(rhsVal); + if (result != 0) + { + return result; + } + } + else + { + break; // values equal until this point (rhs shorter) + } + } + } + + /* we get here if all values are equal. Now look at the number of components. */ + unsigned long rhsVM = myRhs->getVM(); + if (thisVM < rhsVM) + { + return -1; + } + else if (thisVM > rhsVM) + { + return 1; + } + + /* all values as well as VM equal: objects are equal */ + return 0; +} + + + + +OFCondition DcmByteString::copyFrom(const DcmObject& rhs) +{ + if (this != &rhs) + { + if (rhs.ident() != ident()) return EC_IllegalCall; + *this = OFstatic_cast(const DcmByteString &, rhs); + } + return EC_Normal; +} + + +// ******************************** + + +DcmEVR DcmByteString::ident() const +{ + /* valid type identifier is set by derived classes */ + return EVR_UNKNOWN; +} + + +unsigned long DcmByteString::getVM() +{ + char *str = NULL; + Uint32 len = 0; + /* get stored string value */ + getString(str, len); + /* and determine the VM */ + return DcmElement::determineVM(str, len); +} + + +OFCondition DcmByteString::clear() +{ + /* call inherited method */ + errorFlag = DcmElement::clear(); + /* set string representation to unknown */ + fStringMode = DCM_UnknownString; + realLength = 0; + return errorFlag; +} + + +Uint32 DcmByteString::getRealLength() +{ + /* convert string to internal representation (if required) */ + if (fStringMode != DCM_MachineString) + { + /* strips non-significant trailing spaces (padding) and determines 'realLength' */ + makeMachineByteString(); + } + /* string length of the internal representation */ + return realLength; +} + + +Uint32 DcmByteString::getLength(const E_TransferSyntax /*xfer*/, + const E_EncodingType /*enctype*/) +{ + /* convert string to DICOM representation, i.e. add padding if required */ + makeDicomByteString(); + /* DICOM value length is always an even number */ + return getLengthField(); +} + + +// ******************************** + +void DcmByteString::print(STD_NAMESPACE ostream& out, + const size_t flags, + const int level, + const char * /*pixelFileName*/, + size_t * /*pixelCounter*/) +{ + if (valueLoaded()) + { + /* get string data */ + char *stringVal = NULL; + Uint32 stringLen = 0; + getString(stringVal, stringLen); + if ((stringVal != NULL) && (stringLen > 0)) + { + /* print line start with tag and VR */ + printInfoLineStart(out, flags, level); + out << '['; + + OFString outString; + /* do not create more output than actually needed */ + const size_t outStrLen = (flags & DCMTypes::PF_shortenLongTagValues) ? DCM_OptPrintLineLength : 0 /* all characters */; + /* check whether string has to be converted to markup or octal representation */ + if (flags & DCMTypes::PF_convertToMarkup) + { + OFString inString(stringVal, stringLen); + OFStandard::convertToMarkupString(inString, outString, OFTrue, OFStandard::MM_XML, OFFalse, outStrLen); + } + else if (flags & DCMTypes::PF_convertToOctalNumbers) + { + OFString inString(stringVal, stringLen); + OFStandard::convertToOctalString(inString, outString, outStrLen); + } else { + /* check whether we need the full string or the prefix only */ + if ((outStrLen == 0) || (outStrLen > stringLen)) + outString.assign(stringVal, stringLen); + else + outString.assign(stringVal, outStrLen); + } + + size_t printedLength = outString.length() + 2 /* for enclosing brackets */; + + /* check whether full value text should be printed */ + if ((flags & DCMTypes::PF_shortenLongTagValues) && (printedLength > DCM_OptPrintLineLength)) + { + /* truncate value text and append "..." */ + outString.erase(DCM_OptPrintLineLength - 4); + out << outString << "..."; + printedLength = DCM_OptPrintLineLength; + } else + out << outString << ']'; + + /* print line end with length, VM and tag name */ + printInfoLineEnd(out, flags, OFstatic_cast(unsigned long, printedLength)); + } else + printInfoLine(out, flags, level, "(no value available)"); + } else + printInfoLine(out, flags, level, "(not loaded)"); +} + + +// ******************************** + + +OFCondition DcmByteString::write(DcmOutputStream &outStream, + const E_TransferSyntax oxfer, + const E_EncodingType enctype, + DcmWriteCache *wcache) +{ + if (getTransferState() == ERW_notInitialized) + errorFlag = EC_IllegalCall; + else + { + /* convert string value to DICOM representation and call inherited method */ + if (getTransferState() == ERW_init) + makeDicomByteString(); + + errorFlag = DcmElement::write(outStream, oxfer, enctype, wcache); + } + return errorFlag; +} + + +OFCondition DcmByteString::writeSignatureFormat(DcmOutputStream &outStream, + const E_TransferSyntax oxfer, + const E_EncodingType enctype, + DcmWriteCache *wcache) +{ + if (getTransferState() == ERW_notInitialized) + errorFlag = EC_IllegalCall; + else + { + /* convert string value to DICOM representation and call inherited method */ + if (getTransferState() == ERW_init) + makeDicomByteString(); + errorFlag = DcmElement::writeSignatureFormat(outStream, oxfer, enctype, wcache); + } + return errorFlag; +} + + +// ******************************** + + +OFCondition DcmByteString::getOFString(OFString &stringVal, + const unsigned long pos, + OFBool /*normalize*/) +{ + /* check given string position index */ + if (pos >= getVM()) + { + /* treat an empty string as a special case */ + if (pos == 0) + { + errorFlag = EC_Normal; + stringVal.clear(); + } else + errorFlag = EC_IllegalParameter; + } else { + /* get string data */ + char *str = NULL; + Uint32 len = 0; + errorFlag = getString(str, len); + /* check whether string value is present */ + if ((str != NULL) && (len > 0)) + { + /* extract specified string component */ + errorFlag = getStringPart(stringVal, str, len, pos); + } else + stringVal.clear(); + } + return errorFlag; +} + + +OFCondition DcmByteString::getOFStringArray(OFString &stringVal, + OFBool normalize) +{ + /* check whether time-consuming normalization is really needed */ + if (normalize) + errorFlag = DcmElement::getOFStringArray(stringVal, normalize); + else + errorFlag = getStringValue(stringVal); + return errorFlag; +} + + +OFCondition DcmByteString::getStringValue(OFString &stringVal) +{ + char *str = NULL; + Uint32 len = 0; + errorFlag = getString(str, len); + /* check whether string value is present */ + if ((str != NULL) && (len > 0)) + stringVal.assign(str, len); + else + stringVal.clear(); + return errorFlag; +} + + +OFCondition DcmByteString::getString(char *&stringVal) +{ + errorFlag = EC_Normal; + /* get string data */ + stringVal = OFstatic_cast(char *, getValue()); + /* convert to internal string representation (without padding) if required */ + if ((stringVal != NULL) && (fStringMode != DCM_MachineString)) + makeMachineByteString(); + return errorFlag; +} + + +OFCondition DcmByteString::getString(char *&stringVal, + Uint32 &stringLen) +{ + /* get string data */ + errorFlag = getString(stringVal); + /* return the real length of the value */ + stringLen = realLength; + return errorFlag; +} + + +// ******************************** + + +OFCondition DcmByteString::putString(const char *stringVal) +{ + /* determine length of the string value */ + const size_t stringLen = (stringVal != NULL) ? strlen(stringVal) : 0; + /* call the real function */ + return putString(stringVal, OFstatic_cast(Uint32, stringLen)); +} + + +OFCondition DcmByteString::putString(const char *stringVal, + const Uint32 stringLen) +{ + errorFlag = EC_Normal; + /* check for an empty string parameter */ + if ((stringVal != NULL) && (stringLen > 0)) + putValue(stringVal, stringLen); + else + putValue(NULL, 0); + /* make sure that extra padding is removed from the string */ + fStringMode = DCM_UnknownString; + makeMachineByteString(stringLen); + return errorFlag; +} + + +// ******************************** + + +OFCondition DcmByteString::makeDicomByteString() +{ + /* get string data */ + char *value = NULL; + errorFlag = getString(value); + if (value != NULL) + { + /* check for odd length */ + if (realLength & 1) + { + /* if so add a padding character */ + setLengthField(realLength + 1); + value[realLength] = paddingChar; + } else if (realLength < getLengthField()) + setLengthField(realLength); + /* terminate string (removes additional trailing padding characters) */ + value[getLengthField()] = '\0'; + } + /* current string representation is now the DICOM one */ + fStringMode = DCM_DicomString; + return errorFlag; +} + + +OFCondition DcmByteString::makeMachineByteString(const Uint32 length) +{ + errorFlag = EC_Normal; + /* get string data */ + char *value = OFstatic_cast(char *, getValue()); + if (value != NULL) + { + /* check whether string representation is not the internal one */ + if (fStringMode != DCM_MachineString) + { + /* determine initial string length */ + realLength = (length == 0) ? getLengthField() : length; + /* remove all trailing spaces if automatic input data correction is enabled */ + if (dcmEnableAutomaticInputDataCorrection.get()) + { + /* + ** This code removes extra padding characters at the end of a ByteString. + ** Trailing padding can cause problems when comparing strings. This kind + ** of padding is non-significant for all string-based value representations. + */ + if (realLength > 0) + { + size_t i = OFstatic_cast(size_t, realLength); + while ((i > 0) && (value[i - 1] == paddingChar)) + value[--i] = '\0'; + realLength = OFstatic_cast(Uint32, i); + } + } + } + } else + realLength = 0; + /* current string representation is now the internal one */ + fStringMode = DCM_MachineString; + return errorFlag; +} + + +// ******************************** + + +Uint8 *DcmByteString::newValueField() +{ + Uint8 *value = NULL; + Uint32 lengthField = getLengthField(); + /* check for odd length (in case of a protocol error) */ + if (lengthField & 1) + { + if (lengthField == DCM_UndefinedLength) + { + /* Print an error message when private attribute states to have an odd length + * equal to the maximum length, because we are not able then to make this value even (+1) + * which would an overflow on some systems as well as being illegal in DICOM + */ + DCMDATA_WARN("DcmByteString: Element " << getTagName() << " " << getTag() + << " has odd maximum length (" << DCM_UndefinedLength << ") and therefore is not loaded"); + errorFlag = EC_CorruptedData; + return NULL; + } + /* allocate space for extra padding character (required for the DICOM representation of the string) */ +#ifdef HAVE_STD__NOTHROW + // we want to use a non-throwing new here if available. + // If the allocation fails, we report an EC_MemoryExhausted error + // back to the caller. + value = new (std::nothrow) Uint8[lengthField + 2]; +#else + /* make sure that the pointer is set to NULL in case of error */ + try + { + value = new Uint8[lengthField + 2]; + } + catch (STD_NAMESPACE bad_alloc const &) + { + value = NULL; + } +#endif + + /* terminate string after real length */ + if (value != NULL) + value[lengthField] = 0; + /* enforce old (pre DCMTK 3.5.2) behaviour? */ + if (!dcmAcceptOddAttributeLength.get()) + { + /* make length even */ + lengthField++; + setLengthField(lengthField); + } + } else { + /* length is even, but we need an extra byte for the terminating 0 byte */ +#ifdef HAVE_STD__NOTHROW + // we want to use a non-throwing new here if available. + // If the allocation fails, we report an EC_MemoryExhausted error + // back to the caller. + value = new (std::nothrow) Uint8[lengthField + 1]; +#else + /* make sure that the pointer is set to NULL in case of error */ + try + { + value = new Uint8[lengthField + 1]; + } + catch (STD_NAMESPACE bad_alloc const &) + { + value = NULL; + } +#endif + } + /* make sure that the string is properly terminated by a 0 byte */ + if (value != NULL) + value[lengthField] = 0; + else + errorFlag = EC_MemoryExhausted; + return value; +} + + +// ******************************** + + +void DcmByteString::postLoadValue() +{ + /* initially, after loading an attribute the string mode is unknown */ + fStringMode = DCM_UnknownString; + /* correct value length if automatic input data correction is enabled */ + if (dcmEnableAutomaticInputDataCorrection.get()) + { + /* check for odd length */ + if (getLengthField() & 1) + { + // newValueField always allocates an even number of bytes and sets + // the pad byte to zero, so we can safely increase Length here. + setLengthField(getLengthField() + 1); + } + } +} + + +// ******************************** + + +OFCondition DcmByteString::verify(const OFBool autocorrect) +{ + char *str = NULL; + Uint32 len = 0; + /* get string data */ + errorFlag = getString(str, len); + /* check for non-empty string */ + if ((str != NULL) && (len > 0)) + { + /* check whether there is anything to verify at all */ + if (maxLength != DCM_UndefinedLength) + { + /* TODO: is it really a good idea to create a copy of the string? */ + OFString value(str, len); + size_t posStart = 0; + unsigned long vmNum = 0; + /* check all string components */ + while (posStart != OFString_npos) + { + ++vmNum; + /* search for next component separator */ + size_t posEnd = value.find('\\', posStart); + const size_t fieldLen = (posEnd == OFString_npos) ? value.length() - posStart : posEnd - posStart; + /* check size limit for each string component */ + if (fieldLen > maxLength) + { + DCMDATA_DEBUG("DcmByteString::verify() Maximum length violated in element " + << getTagName() << " " << getTag() << " value " << vmNum << ": " << fieldLen + << " bytes found but only " << maxLength << " bytes allowed"); + errorFlag = EC_MaximumLengthViolated; + if (autocorrect) + { + const size_t excess = fieldLen - maxLength; + DCMDATA_DEBUG("DcmByteString::verify() Removing " << excess + << " bytes from the end of value " << vmNum); + /* erase excessive part of the string component */ + value.erase(posStart + maxLength, excess); + /* correct the position end marker */ + posEnd -= excess; + } + } + posStart = (posEnd == OFString_npos) ? posEnd : posEnd + 1; + } + /* replace current string value if auto correction is enabled */ + if (autocorrect && errorFlag.bad()) + { + putOFStringArray(value); + /* the above method also sets 'errorFlag', so we need to assign the error code again */ + errorFlag = EC_MaximumLengthViolated; + } + } + } + /* report a debug message if an error occurred */ + if (errorFlag.bad()) + { + DCMDATA_WARN("DcmByteString: One or more illegal values in element " + << getTagName() << " " << getTag() << " with VM=" << getVM()); + } + return errorFlag; +} + + +OFBool DcmByteString::containsExtendedCharacters(const OFBool checkAllStrings) +{ + /* only check if parameter is true since derived VRs are not affected + by the attribute SpecificCharacterSet (0008,0005) */ + if (checkAllStrings) + { + char *str = NULL; + Uint32 len = 0; + /* determine length in order to support possibly embedded NULL bytes */ + if (getString(str, len).good() && (str != NULL)) + { + const char *p = str; + for (Uint32 i = 0; i < len; i++) + { + /* check for 8 bit characters */ + if (OFstatic_cast(unsigned char, *p++) > 127) + return OFTrue; + } + } + } + return OFFalse; +} + + +OFBool DcmByteString::isAffectedBySpecificCharacterSet() const +{ + return OFFalse; +} + + +// ******************************** + + +OFBool DcmByteString::isEmpty(const OFBool normalize) +{ + OFBool result = OFFalse; + if (normalize && !nonSignificantChars.empty()) + { + OFString value; + DcmByteString::getStringValue(value); + /* check whether string value consists of non-significant characters only */ + result = (value.find_first_not_of(nonSignificantChars) == OFString_npos); + } else + result = DcmObject::isEmpty(normalize); + return result; +} + + +// ******************************** + + +// global function for normalizing a DICOM string +void normalizeString(OFString &string, + const OFBool multiPart, + const OFBool leading, + const OFBool trailing, + const char paddingChar) +{ + /* check for non-empty string */ + if (!string.empty()) + { + size_t partindex = 0; + size_t offset = 0; + size_t len = string.length(); + while (partindex < len) + { + // remove leading spaces in every part of the string + if (leading) + { + offset = 0; + while ((partindex + offset < len) && (string[partindex + offset] == paddingChar)) + offset++; + if (offset > 0) + string.erase(partindex, offset); + } + len = string.length(); + // compute begin to the next separator index! + if (multiPart) + { + partindex = string.find('\\', partindex); + if (partindex == OFString_npos) + partindex = len; + } else + partindex = len; + // remove trailing spaces in every part of the string + if (trailing && partindex) + { + offset = partindex - 1; + while ((offset > 0) && (string[offset] == paddingChar)) + offset--; + if (offset != partindex - 1) + { + if (string[offset] == ' ') + { + string.erase(offset, partindex - offset); + partindex = offset; + } else { + string.erase(offset + 1, partindex - offset - 1); + partindex = offset + 1; + } + } + } + len = string.length(); + if (partindex != len) + ++partindex; + } + } +} + + +// ******************************** + + +OFCondition DcmByteString::checkStringValue(const OFString &value, + const OFString &vm, + const OFString &vr, + const int vrID, + const size_t maxLen, + const OFString &charset) +{ + OFCondition result = EC_Normal; + const size_t valLen = value.length(); + if (valLen > 0) + { + /* do we need to search for value components at all? */ + if (vm.empty()) + { + /* check value length (if a maximum is specified) */ + if ((maxLen > 0) && (value.length() > maxLen)) + result = EC_MaximumLengthViolated; + else if (dcmEnableVRCheckerForStringValues.get()) + { + /* currently, the VR checker only supports ASCII and Latin-1 */ + if (charset.empty() || (charset == "ISO_IR 6") || (charset == "ISO_IR 100")) + { + /* check value representation */ + if (DcmElement::scanValue(value, vr) != vrID) + result = EC_ValueRepresentationViolated; + } + } + } else { + size_t posStart = 0; + unsigned long vmNum = 0; + /* iterate over all value components */ + while (posStart != OFString_npos) + { + ++vmNum; + /* search for next component separator */ + const size_t posEnd = value.find('\\', posStart); + const size_t length = (posEnd == OFString_npos) ? valLen - posStart : posEnd - posStart; + /* check length of current value component */ + if ((maxLen > 0) && (length > maxLen)) + { + result = EC_MaximumLengthViolated; + break; + } + else if (dcmEnableVRCheckerForStringValues.get()) + { + /* currently, the VR checker only supports ASCII and Latin-1 */ + if (charset.empty() || (charset == "ISO_IR 6") || (charset == "ISO_IR 100")) + { + /* check value representation */ + if (DcmElement::scanValue(value, vr, posStart, length) != vrID) + { + result = EC_ValueRepresentationViolated; + break; + } + } + } + posStart = (posEnd == OFString_npos) ? posEnd : posEnd + 1; + } + if (result.good()) + { + /* check value multiplicity */ + result = DcmElement::checkVM(vmNum, vm); + } + } + } + return result; +} diff --git a/dcmdata/libsrc/dcchrstr.cc b/dcmdata/libsrc/dcchrstr.cc new file mode 100644 index 00000000..8b27925a --- /dev/null +++ b/dcmdata/libsrc/dcchrstr.cc @@ -0,0 +1,231 @@ +/* + * + * Copyright (C) 1994-2015, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Andreas Barth + * + * Purpose: Implementation of class DcmCharString + * + */ + + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/dcmdata/dcspchrs.h" /* for class DcmSpecificCharacterSet */ +#include "dcmtk/dcmdata/dcitem.h" /* for class DcmItem */ +#include "dcmtk/dcmdata/dcdeftag.h" /* for tag definitions */ + +// +// This implementation does not support 16 bit character sets. Since 8 bit +// character sets are supported by the class DcmByteString the class +// DcmCharString is derived from DcmByteString without any extensions. +// No special implementation is necessary. +// +// If the extension for > 8 bit character sets will be implemented this class +// must be derived directly from DcmElement. This class is designed to support +// the value representations (LO, LT, PN, SH, ST, UC and UT). They are a problem +// because their value width (1, 2, ... bytes) is specified by the element +// SpecificCharacterSet (0008, 0005) and an implementation must support +// different value widths that cannot be derived from the value representation. +// + + +#include "dcmtk/dcmdata/dcchrstr.h" + + +DcmCharString::DcmCharString(const DcmTag &tag, const Uint32 len) + : DcmByteString(tag, len), + delimiterChars() +{ +} + +DcmCharString::DcmCharString(const DcmCharString &old) + : DcmByteString(old), + delimiterChars(old.delimiterChars) +{ +} + +DcmCharString::~DcmCharString(void) +{ +} + + +DcmCharString &DcmCharString::operator=(const DcmCharString &obj) +{ + if (this != &obj) + { + DcmByteString::operator=(obj); + + /* copy member variables */ + delimiterChars = obj.delimiterChars; + } + return *this; +} + + +OFCondition DcmCharString::copyFrom(const DcmObject& rhs) +{ + if (this != &rhs) + { + if (rhs.ident() != ident()) return EC_IllegalCall; + *this = OFstatic_cast(const DcmCharString &, rhs); + } + return EC_Normal; +} + + +// ******************************** + + +OFCondition DcmCharString::verify(const OFBool autocorrect) +{ + const Uint32 maxLen = getMaxLength(); + char *str = NULL; + Uint32 len = 0; + /* get string data */ + errorFlag = getString(str, len); + /* check for non-empty string */ + if ((str != NULL) && (len > 0)) + { + /* check whether there is anything to verify at all */ + if (maxLen != DCM_UndefinedLength) + { + /* TODO: is it really a good idea to create a copy of the string? */ + OFString value(str, len); + size_t posStart = 0; + unsigned long vmNum = 0; + /* check all string components */ + while (posStart != OFString_npos) + { + ++vmNum; + /* search for next component separator */ + const size_t posEnd = value.find('\\', posStart); + const size_t fieldLen = (posEnd == OFString_npos) ? value.length() - posStart : posEnd - posStart; + /* check size limit for each string component */ + if (fieldLen > maxLen) + { + DCMDATA_DEBUG("DcmCharString::verify() maximum length violated in element " + << getTagName() << " " << getTag() << " value " << vmNum << ": " + << fieldLen << " bytes found but only " << maxLen << " characters allowed"); + errorFlag = EC_MaximumLengthViolated; + if (autocorrect) + { + /* We are currently not removing any characters since we do not know + * whether a character consists of one or more bytes. This will be + * fixed in a future version. + */ + DCMDATA_DEBUG("DcmCharString::verify() not correcting value length since " + << "multi-byte character sets are not yet supported, so cannot decide"); + } + } + posStart = (posEnd == OFString_npos) ? posEnd : posEnd + 1; + } + } + } + /* report a debug message if an error occurred */ + if (errorFlag.bad()) + { + DCMDATA_WARN("DcmCharString: One or more illegal values in element " + << getTagName() << " " << getTag() << " with VM=" << getVM()); + /* do not return with an error since we do not know whether there really is a violation */ + errorFlag = EC_Normal; + } + return errorFlag; +} + + +OFBool DcmCharString::containsExtendedCharacters(const OFBool /*checkAllStrings*/) +{ + char *str = NULL; + Uint32 len = 0; + /* determine length in order to support possibly embedded NULL bytes */ + if (getString(str, len).good() && (str != NULL)) + { + const char *p = str; + for (Uint32 i = 0; i < len; i++) + { + /* check for 8 bit characters */ + if (OFstatic_cast(unsigned char, *p++) > 127) + return OFTrue; + } + } + return OFFalse; +} + + +OFBool DcmCharString::isAffectedBySpecificCharacterSet() const +{ + return OFTrue; +} + + +OFCondition DcmCharString::convertCharacterSet(DcmSpecificCharacterSet &converter) +{ + char *str = NULL; + Uint32 len = 0; + OFCondition status = getString(str, len); + // do nothing if string value is empty + if (status.good() && (str != NULL) && (len > 0)) + { + OFString resultStr; + // convert string to selected character string and replace the element value + status = converter.convertString(str, len, resultStr, delimiterChars); + if (status.good()) + { + // check whether the value has changed during the conversion (slows down the process?) + if (OFString(str, len) != resultStr) + { + DCMDATA_TRACE("DcmCharString::convertCharacterSet() updating value of element " + << getTagName() << " " << getTag() << " after the conversion to " + << converter.getDestinationEncoding() << " encoding"); + // update the element value + status = putOFStringArray(resultStr); + } else { + DCMDATA_TRACE("DcmCharString::convertCharacterSet() not updating value of element " + << getTagName() << " " << getTag() << " because the value has not changed"); + } + } + } + return status; +} + + +// ******************************** + + +OFCondition DcmCharString::getSpecificCharacterSet(OFString &charset) +{ + OFCondition status = EC_CorruptedData; + // start with current dataset-level + DcmItem *item = getParentItem(); + while ((item != NULL) && status.bad()) + { + // check whether the attribute SpecificCharacterSet should be present at all + if (item->checkForSpecificCharacterSet()) + { + // by default, the string components are normalized (i.e. padding is removed) + status = item->findAndGetOFStringArray(DCM_SpecificCharacterSet, charset); + } + // if element could not be found, go one level up + if (status.bad()) + item = item->getParentItem(); + } + // output some debug information + if (status.good()) + { + DCMDATA_TRACE("DcmCharString::getSpecificCharacterSet() element " << getTagName() + << " " << getTag() << " uses character set \"" << charset << "\""); + } + return status; +} diff --git a/dcmdata/libsrc/dccodec.cc b/dcmdata/libsrc/dccodec.cc new file mode 100644 index 00000000..aa64799b --- /dev/null +++ b/dcmdata/libsrc/dccodec.cc @@ -0,0 +1,645 @@ +/* + * + * Copyright (C) 1997-2010, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Andreas Barth + * + * Purpose: abstract class DcmCodec and the class DcmCodecStruct + * + */ + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ +#include "dcmtk/dcmdata/dccodec.h" +#include "dcmtk/ofstd/oflist.h" +#include "dcmtk/ofstd/ofthread.h" +#include "dcmtk/dcmdata/dcdeftag.h" /* for tag constants */ +#include "dcmtk/dcmdata/dcuid.h" /* for dcmGenerateUniqueIdentifer()*/ +#include "dcmtk/dcmdata/dcitem.h" /* for class DcmItem */ +#include "dcmtk/dcmdata/dcsequen.h" /* for DcmSequenceOfItems */ +#include "dcmtk/dcmdata/dcpixseq.h" /* for DcmPixelSequence */ +#include "dcmtk/dcmdata/dcpxitem.h" /* for DcmPixelItem */ +#include "dcmtk/dcmdata/dcswap.h" /* for swapIfNecessary */ +#include "dcmtk/dcmdata/dcvrui.h" /* for DcmUniqueIdentifier */ + +// static member variables +OFList DcmCodecList::registeredCodecs; + +#ifdef WITH_THREADS +OFReadWriteLock DcmCodecList::codecLock; +#endif + +/* --------------------------------------------------------------- */ + +// DcmCodec static helper methods + +OFCondition DcmCodec::insertStringIfMissing(DcmItem *dataset, const DcmTagKey& tag, const char *val) +{ + DcmStack stack; + if ((dataset->search(tag, stack, ESM_fromHere, OFFalse)).bad()) + { + return dataset->putAndInsertString(tag, val, OFTrue); + } + return EC_Normal; +} + + +OFCondition DcmCodec::convertToSecondaryCapture(DcmItem *dataset) +{ + if (dataset == NULL) return EC_IllegalCall; + + OFCondition result = EC_Normal; + char buf[70]; + + // SOP Class UID - always replace + if (result.good()) result = dataset->putAndInsertString(DCM_SOPClassUID, UID_SecondaryCaptureImageStorage); + + // SOP Instance UID - only insert if missing. + dcmGenerateUniqueIdentifier(buf); + if (result.good()) result = insertStringIfMissing(dataset, DCM_SOPInstanceUID, buf); + + // Type 1 attributes - insert with value if missing + dcmGenerateUniqueIdentifier(buf, SITE_STUDY_UID_ROOT); + if (result.good()) result = insertStringIfMissing(dataset, DCM_StudyInstanceUID, buf); + dcmGenerateUniqueIdentifier(buf, SITE_SERIES_UID_ROOT); + if (result.good()) result = insertStringIfMissing(dataset, DCM_SeriesInstanceUID, buf); + if (result.good()) result = insertStringIfMissing(dataset, DCM_ConversionType, "WSD"); + if (result.good()) result = insertStringIfMissing(dataset, DCM_Modality, "OT"); + + // Type 2 attributes - insert without value if missing + if (result.good()) result = insertStringIfMissing(dataset, DCM_PatientName, NULL); + if (result.good()) result = insertStringIfMissing(dataset, DCM_PatientID, NULL); + if (result.good()) result = insertStringIfMissing(dataset, DCM_PatientBirthDate, NULL); + if (result.good()) result = insertStringIfMissing(dataset, DCM_PatientSex, NULL); + if (result.good()) result = insertStringIfMissing(dataset, DCM_PatientOrientation, NULL); + if (result.good()) result = insertStringIfMissing(dataset, DCM_StudyDate, NULL); + if (result.good()) result = insertStringIfMissing(dataset, DCM_StudyTime, NULL); + if (result.good()) result = insertStringIfMissing(dataset, DCM_ReferringPhysicianName, NULL); + if (result.good()) result = insertStringIfMissing(dataset, DCM_StudyID, NULL); + if (result.good()) result = insertStringIfMissing(dataset, DCM_AccessionNumber, NULL); + if (result.good()) result = insertStringIfMissing(dataset, DCM_SeriesNumber, NULL); + if (result.good()) result = insertStringIfMissing(dataset, DCM_InstanceNumber, NULL); + + return result; +} + + +OFCondition DcmCodec::insertCodeSequence( + DcmItem *dataset, + const DcmTagKey &tagKey, + const char *codingSchemeDesignator, + const char *codeValue, + const char *codeMeaning) +{ + if (dataset == NULL || codingSchemeDesignator == NULL || + codeValue == NULL || codeMeaning == NULL) return EC_IllegalCall; + + OFCondition result = EC_Normal; + DcmSequenceOfItems *dseq = new DcmSequenceOfItems(tagKey); + if (dseq) + { + DcmItem *ditem = new DcmItem(); + if (ditem) + { + dseq->insert(ditem); + result = ditem->putAndInsertString(DCM_CodingSchemeDesignator, codingSchemeDesignator); + if (result.good()) result = ditem->putAndInsertString(DCM_CodeValue, codeValue); + if (result.good()) result = ditem->putAndInsertString(DCM_CodeMeaning, codeMeaning); + } else result = EC_MemoryExhausted; + + // insert sequence into dataset if everything went well + if (result.good()) dataset->insert(dseq, OFTrue /*replaceOld*/); else delete dseq; + } else result = EC_MemoryExhausted; + + return result; +} + + +OFCondition DcmCodec::newInstance( + DcmItem *dataset, + const char *purposeOfReferenceCodingScheme, + const char *purposeOfReferenceCodeValue, + const char *purposeOfReferenceCodeMeaning) +{ + if (dataset == NULL) return EC_IllegalCall; + OFCondition result = EC_Normal; + + // look up current SOP Class UID and SOP Instance UID + const char *classUID = NULL; + const char *instanceUID = NULL; + + // search for existing SOP Class UID / SOP Instance UID + OFCondition tempResult = dataset->findAndGetString(DCM_SOPClassUID, classUID); + if (tempResult.good()) tempResult = dataset->findAndGetString(DCM_SOPInstanceUID, instanceUID); + if (tempResult.good() && classUID && instanceUID) + { + // create source image sequence + DcmSequenceOfItems *dseq = new DcmSequenceOfItems(DCM_SourceImageSequence); + if (dseq) + { + DcmItem *ditem = new DcmItem(); + if (ditem) + { + dseq->insert(ditem); + DcmElement *elem1 = new DcmUniqueIdentifier(DCM_ReferencedSOPClassUID); + if (elem1) + { + result = elem1->putString(classUID); + ditem->insert(elem1, OFTrue /*replaceOld*/); + if (result.good()) + { + DcmElement *elem2 = new DcmUniqueIdentifier(DCM_ReferencedSOPInstanceUID); + if (elem2) + { + result = elem2->putString(instanceUID); + ditem->insert(elem2, OFTrue /*replaceOld*/); + } else result = EC_MemoryExhausted; + } + } else result = EC_MemoryExhausted; + + if (result.good() && purposeOfReferenceCodingScheme && + purposeOfReferenceCodeValue && purposeOfReferenceCodeMeaning) + { + // add purpose of reference code sequence + result = DcmCodec::insertCodeSequence(ditem, DCM_PurposeOfReferenceCodeSequence, + purposeOfReferenceCodingScheme, purposeOfReferenceCodeValue, purposeOfReferenceCodeMeaning); + } + } else result = EC_MemoryExhausted; + if (result.good()) dataset->insert(dseq, OFTrue); else delete dseq; + } else result = EC_MemoryExhausted; + } + + // create new SOP instance UID + if (result.good()) + { + char new_uid[100]; + DcmElement *elem = new DcmUniqueIdentifier(DCM_SOPInstanceUID); + if (elem) + { + if (EC_Normal == (result = elem->putString(dcmGenerateUniqueIdentifier(new_uid)))) + dataset->insert(elem, OFTrue); // replace SOP Instance UID + else delete elem; + } else result = EC_MemoryExhausted; + } + + return result; +} + + +OFCondition DcmCodec::updateImageType(DcmItem *dataset) +{ + if (dataset == NULL) return EC_IllegalCall; + + DcmStack stack; + OFString imageType("DERIVED"); + OFString a; + + /* find existing Image Type element */ + OFCondition status = dataset->search(DCM_ImageType, stack, ESM_fromHere, OFFalse); + if (status.good()) + { + DcmElement *elem = OFstatic_cast(DcmElement *, stack.top()); + unsigned long pos = 1; + + // append old image type information beginning with second entry + while ((elem->getOFString(a, pos++)).good()) + { + imageType += "\\"; + imageType += a; + } + } + + // insert new Image Type, replace old value + return dataset->putAndInsertString(DCM_ImageType, imageType.c_str(), OFTrue); +} + + +OFCondition DcmCodec::determineStartFragment( + Uint32 frameNo, + Sint32 numberOfFrames, + DcmPixelSequence * fromPixSeq, + Uint32& currentItem) +{ + Uint32 numberOfFragments = OFstatic_cast(Uint32, fromPixSeq->card()); + if (numberOfFrames < 1 || numberOfFragments <= OFstatic_cast(Uint32, numberOfFrames) || frameNo >= OFstatic_cast(Uint32, numberOfFrames)) return EC_IllegalCall; + + if (frameNo == 0) + { + // simple case: first frame is always at second fragment + currentItem = 1; + return EC_Normal; + } + + if (numberOfFragments == OFstatic_cast(Uint32, numberOfFrames) + 1) + { + // standard case: there is one fragment per frame. + currentItem = frameNo + 1; + return EC_Normal; + } + + // non-standard case: multiple fragments per frame. + // We now try to consult the offset table. + DcmPixelItem *pixItem = NULL; + Uint8 * rawOffsetTable = NULL; + + // get first pixel item, i.e. the fragment containing the offset table + OFCondition result = fromPixSeq->getItem(pixItem, 0); + if (result.good()) + { + Uint32 tableLength = pixItem->getLength(); + result = pixItem->getUint8Array(rawOffsetTable); + if (result.good()) + { + // check if the offset table has the right size: 4 bytes for each frame (not fragment!) + if (tableLength != 4* OFstatic_cast(Uint32, numberOfFrames)) return EC_IllegalCall; + + // byte swap offset table into local byte order. In file, the offset table is always in little endian + swapIfNecessary(gLocalByteOrder, EBO_LittleEndian, rawOffsetTable, tableLength, sizeof(Uint32)); + + // cast offset table to Uint32. + Uint32 *offsetTable = OFreinterpret_cast(Uint32 *, rawOffsetTable); + + // now access offset of the frame we're looking for + Uint32 offset = offsetTable[frameNo]; + + // OK, now let's look if we can find a fragment that actually corresponds to that offset. + // In counter we compute the offset for each frame by adding all fragment lenghts + Uint32 counter = 0; + // now iterate over all fragments except the index table. The start of the first fragment + // is defined as zero. + for (Uint32 idx = 1; idx < numberOfFragments; ++idx) + { + if (counter == offset) + { + // hooray, we are lucky. We have found the fragment we're looking for + currentItem = idx; + return EC_Normal; + } + + // access pixel item in order to determine its length + result = fromPixSeq->getItem(pixItem, idx); + if (result.bad()) return result; + + // add pixel item length plus 8 bytes overhead for the item tag and length field + counter += pixItem->getLength() + 8; + } + + // bad luck. We have not found a fragment corresponding to the offset in the offset table. + // Either we cannot correctly add numbers, or they cannot :-) + return EC_TagNotFound; + } + } + return result; +} + + +/* --------------------------------------------------------------- */ + +DcmCodecList::DcmCodecList( + const DcmCodec *aCodec, + const DcmRepresentationParameter *aDefaultRepParam, + const DcmCodecParameter *aCodecParameter) +: codec(aCodec) +, defaultRepParam(aDefaultRepParam) +, codecParameter(aCodecParameter) +{ +} + +DcmCodecList::~DcmCodecList() +{ +} + +OFCondition DcmCodecList::registerCodec( + const DcmCodec *aCodec, + const DcmRepresentationParameter *aDefaultRepParam, + const DcmCodecParameter *aCodecParameter) +{ + if ((aCodec == NULL)||(aCodecParameter == NULL)) return EC_IllegalParameter; +#ifdef WITH_THREADS + if (! codecLock.initialized()) return EC_IllegalCall; // should never happen +#endif + + // acquire write lock on codec list. Will block if some codec is currently active. + OFCondition result = EC_Normal; +#ifdef WITH_THREADS + OFReadWriteLocker locker(codecLock); + if (0 == locker.wrlock()) + { +#endif + DcmCodecList *listEntry = new DcmCodecList(aCodec, aDefaultRepParam, aCodecParameter); + if (listEntry) + { + // prevent codec from being registered twice + OFListIterator(DcmCodecList *) first = registeredCodecs.begin(); + OFListIterator(DcmCodecList *) last = registeredCodecs.end(); + while (first != last) + { + if ((*first)->codec == aCodec) + { + // this codec is already registered. + first = last; + result = EC_IllegalCall; + } else ++first; + } + if (result.good()) registeredCodecs.push_back(listEntry); else delete listEntry; + } else result = EC_MemoryExhausted; +#ifdef WITH_THREADS + } else result = EC_IllegalCall; +#endif + return result; +} + +OFCondition DcmCodecList::deregisterCodec(const DcmCodec *aCodec) +{ + if (aCodec == NULL) return EC_IllegalParameter; +#ifdef WITH_THREADS + if (! codecLock.initialized()) return EC_IllegalCall; // should never happen +#endif + // acquire write lock on codec list. Will block if some codec is currently active. + OFCondition result = EC_Normal; + +#ifdef WITH_THREADS + OFReadWriteLocker locker(codecLock); + if (0 == locker.wrlock()) + { +#endif + OFListIterator(DcmCodecList *) first = registeredCodecs.begin(); + OFListIterator(DcmCodecList *) last = registeredCodecs.end(); + while (first != last) + { + if ((*first)->codec == aCodec) + { + delete *first; + first = registeredCodecs.erase(first); + } else ++first; + } +#ifdef WITH_THREADS + } else result = EC_IllegalCall; +#endif + return result; +} + +OFCondition DcmCodecList::updateCodecParameter( + const DcmCodec *aCodec, + const DcmCodecParameter *aCodecParameter) +{ + if ((aCodec == NULL)||(aCodecParameter == NULL)) return EC_IllegalParameter; +#ifdef WITH_THREADS + if (! codecLock.initialized()) return EC_IllegalCall; // should never happen +#endif + // acquire write lock on codec list. Will block if some codec is currently active. + OFCondition result = EC_Normal; + +#ifdef WITH_THREADS + OFReadWriteLocker locker(codecLock); + if (0 == locker.wrlock()) + { +#endif + OFListIterator(DcmCodecList *) first = registeredCodecs.begin(); + OFListIterator(DcmCodecList *) last = registeredCodecs.end(); + while (first != last) + { + if ((*first)->codec == aCodec) (*first)->codecParameter = aCodecParameter; + ++first; + } +#ifdef WITH_THREADS + } else result = EC_IllegalCall; +#endif + return result; +} + + +OFCondition DcmCodecList::decode( + const DcmXfer & fromType, + const DcmRepresentationParameter * fromParam, + DcmPixelSequence * fromPixSeq, + DcmPolymorphOBOW& uncompressedPixelData, + DcmStack & pixelStack) +{ +#ifdef WITH_THREADS + if (! codecLock.initialized()) return EC_IllegalCall; // should never happen +#endif + OFCondition result = EC_CannotChangeRepresentation; + + // acquire write lock on codec list. Will block if some write lock is currently active. +#ifdef WITH_THREADS + OFReadWriteLocker locker(codecLock); + if (0 == locker.rdlock()) + { +#endif + E_TransferSyntax fromXfer = fromType.getXfer(); + OFListIterator(DcmCodecList *) first = registeredCodecs.begin(); + OFListIterator(DcmCodecList *) last = registeredCodecs.end(); + while (first != last) + { + if ((*first)->codec->canChangeCoding(fromXfer, EXS_LittleEndianExplicit)) + { + result = (*first)->codec->decode(fromParam, fromPixSeq, uncompressedPixelData, (*first)->codecParameter, pixelStack); + first = last; + } else ++first; + } +#ifdef WITH_THREADS + } else result = EC_IllegalCall; +#endif + return result; +} + + +OFCondition DcmCodecList::decodeFrame( + const DcmXfer & fromType, + const DcmRepresentationParameter * fromParam, + DcmPixelSequence * fromPixSeq, + DcmItem *dataset, + Uint32 frameNo, + Uint32& startFragment, + void *buffer, + Uint32 bufSize, + OFString& decompressedColorModel) +{ +#ifdef WITH_THREADS + if (! codecLock.initialized()) return EC_IllegalCall; // should never happen +#endif + OFCondition result = EC_CannotChangeRepresentation; + + // acquire write lock on codec list. Will block if some write lock is currently active. +#ifdef WITH_THREADS + OFReadWriteLocker locker(codecLock); + if (0 == locker.rdlock()) + { +#endif + E_TransferSyntax fromXfer = fromType.getXfer(); + OFListIterator(DcmCodecList *) first = registeredCodecs.begin(); + OFListIterator(DcmCodecList *) last = registeredCodecs.end(); + while (first != last) + { + if ((*first)->codec->canChangeCoding(fromXfer, EXS_LittleEndianExplicit)) + { + result = (*first)->codec->decodeFrame(fromParam, fromPixSeq, (*first)->codecParameter, + dataset, frameNo, startFragment, buffer, bufSize, decompressedColorModel); + first = last; + } else ++first; + } +#ifdef WITH_THREADS + } else result = EC_IllegalCall; +#endif + return result; +} + + +OFCondition DcmCodecList::encode( + const E_TransferSyntax fromRepType, + const DcmRepresentationParameter * fromParam, + DcmPixelSequence * fromPixSeq, + const E_TransferSyntax toRepType, + const DcmRepresentationParameter * toRepParam, + DcmPixelSequence * & toPixSeq, + DcmStack & pixelStack) +{ + toPixSeq = NULL; +#ifdef WITH_THREADS + if (! codecLock.initialized()) return EC_IllegalCall; // should never happen +#endif + OFCondition result = EC_CannotChangeRepresentation; + + // acquire write lock on codec list. Will block if some write lock is currently active. +#ifdef WITH_THREADS + OFReadWriteLocker locker(codecLock); + if (0 == locker.rdlock()) + { +#endif + OFListIterator(DcmCodecList *) first = registeredCodecs.begin(); + OFListIterator(DcmCodecList *) last = registeredCodecs.end(); + while (first != last) + { + if ((*first)->codec->canChangeCoding(fromRepType, toRepType)) + { + if (!toRepParam) toRepParam = (*first)->defaultRepParam; + result = (*first)->codec->encode(fromRepType, fromParam, fromPixSeq, + toRepParam, toPixSeq, (*first)->codecParameter, pixelStack); + first = last; + } else ++first; + } +#ifdef WITH_THREADS + } else result = EC_IllegalCall; +#endif + + return result; +} + +OFCondition DcmCodecList::encode( + const E_TransferSyntax fromRepType, + const Uint16 * pixelData, + const Uint32 length, + const E_TransferSyntax toRepType, + const DcmRepresentationParameter * toRepParam, + DcmPixelSequence * & toPixSeq, + DcmStack & pixelStack) +{ + toPixSeq = NULL; +#ifdef WITH_THREADS + if (! codecLock.initialized()) return EC_IllegalCall; // should never happen +#endif + OFCondition result = EC_CannotChangeRepresentation; + + // acquire write lock on codec list. Will block if some write lock is currently active. +#ifdef WITH_THREADS + OFReadWriteLocker locker(codecLock); + if (0 == locker.rdlock()) + { +#endif + OFListIterator(DcmCodecList *) first = registeredCodecs.begin(); + OFListIterator(DcmCodecList *) last = registeredCodecs.end(); + while (first != last) + { + if ((*first)->codec->canChangeCoding(fromRepType, toRepType)) + { + if (!toRepParam) toRepParam = (*first)->defaultRepParam; + result = (*first)->codec->encode(pixelData, length, toRepParam, toPixSeq, + (*first)->codecParameter, pixelStack); + first = last; + } else ++first; + } +#ifdef WITH_THREADS + } else result = EC_IllegalCall; +#endif + + return result; +} + +OFBool DcmCodecList::canChangeCoding( + const E_TransferSyntax fromRepType, + const E_TransferSyntax toRepType) +{ +#ifdef WITH_THREADS + if (! codecLock.initialized()) return OFFalse; // should never happen +#endif + OFBool result = OFFalse; + + // acquire write lock on codec list. Will block if some write lock is currently active. +#ifdef WITH_THREADS + OFReadWriteLocker locker(codecLock); + if (0 == locker.rdlock()) + { +#endif + OFListIterator(DcmCodecList *) first = registeredCodecs.begin(); + OFListIterator(DcmCodecList *) last = registeredCodecs.end(); + while (first != last) + { + if ((*first)->codec->canChangeCoding(fromRepType, toRepType)) + { + result = OFTrue; + first = last; + } else ++first; + } +#ifdef WITH_THREADS + } +#endif + + return result; +} + +OFCondition DcmCodecList::determineDecompressedColorModel( + const DcmXfer &fromType, + const DcmRepresentationParameter *fromParam, + DcmPixelSequence *fromPixSeq, + DcmItem *dataset, + OFString &decompressedColorModel) +{ +#ifdef WITH_THREADS + if (! codecLock.initialized()) return EC_IllegalCall; // should never happen +#endif + OFCondition result = EC_CannotChangeRepresentation; + + // acquire write lock on codec list. Will block if some write lock is currently active. +#ifdef WITH_THREADS + OFReadWriteLocker locker(codecLock); + if (0 == locker.rdlock()) + { +#endif + E_TransferSyntax fromXfer = fromType.getXfer(); + OFListIterator(DcmCodecList *) first = registeredCodecs.begin(); + OFListIterator(DcmCodecList *) last = registeredCodecs.end(); + while (first != last) + { + if ((*first)->codec->canChangeCoding(fromXfer, EXS_LittleEndianExplicit)) + { + result = (*first)->codec->determineDecompressedColorModel(fromParam, fromPixSeq, (*first)->codecParameter, + dataset, decompressedColorModel); + first = last; + } else ++first; + } +#ifdef WITH_THREADS + } else result = EC_IllegalCall; +#endif + return result; +} diff --git a/dcmdata/libsrc/dcdatset.cc b/dcmdata/libsrc/dcdatset.cc new file mode 100644 index 00000000..99d227e4 --- /dev/null +++ b/dcmdata/libsrc/dcdatset.cc @@ -0,0 +1,761 @@ +/* + * + * Copyright (C) 1994-2015, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Gerd Ehlers, Andreas Barth + * + * Purpose: Implementation of class DcmDataset + * + */ + + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#define INCLUDE_CSTDLIB +#define INCLUDE_CSTDIO +#define INCLUDE_CSTRING +#include "dcmtk/ofstd/ofstdinc.h" + +#include "dcmtk/ofstd/ofstream.h" +#include "dcmtk/ofstd/ofstack.h" +#include "dcmtk/ofstd/ofstd.h" + +#include "dcmtk/dcmdata/dcdatset.h" +#include "dcmtk/dcmdata/dcxfer.h" +#include "dcmtk/dcmdata/dcvrus.h" +#include "dcmtk/dcmdata/dcpixel.h" +#include "dcmtk/dcmdata/dcdeftag.h" +#include "dcmtk/dcmdata/dcostrma.h" /* for class DcmOutputStream */ +#include "dcmtk/dcmdata/dcostrmf.h" /* for class DcmOutputFileStream */ +#include "dcmtk/dcmdata/dcistrma.h" /* for class DcmInputStream */ +#include "dcmtk/dcmdata/dcistrmf.h" /* for class DcmInputFileStream */ +#include "dcmtk/dcmdata/dcwcache.h" /* for class DcmWriteCache */ + + +// ******************************** + + +DcmDataset::DcmDataset() + : DcmItem(DCM_ItemTag, DCM_UndefinedLength), + OriginalXfer(EXS_Unknown), + // the default transfer syntax is explicit VR with local endianness + CurrentXfer((gLocalByteOrder == EBO_BigEndian) ? EXS_BigEndianExplicit : EXS_LittleEndianExplicit) +{ +} + + +DcmDataset& DcmDataset::operator=(const DcmDataset& obj) +{ + if (this != &obj) + { + // copy parent's member variables + DcmItem::operator=(obj); + // copy DcmDataset's member variables + OriginalXfer = obj.OriginalXfer; + CurrentXfer = obj.CurrentXfer; + } + return *this; +} + + +DcmDataset::DcmDataset(const DcmDataset &old) + : DcmItem(old), + OriginalXfer(old.OriginalXfer), + CurrentXfer(old.CurrentXfer) +{ +} + + +OFCondition DcmDataset::copyFrom(const DcmObject& rhs) +{ + if (this != &rhs) + { + if (rhs.ident() != ident()) return EC_IllegalCall; + *this = OFstatic_cast(const DcmDataset &, rhs); + } + return EC_Normal; +} + + +DcmDataset::~DcmDataset() +{ +} + + +// ******************************** + + +OFCondition DcmDataset::clear() +{ + OFCondition result = DcmItem::clear(); + // TODO: should we also reset OriginalXfer and CurrentXfer? + setLengthField(DCM_UndefinedLength); + return result; +} + +DcmEVR DcmDataset::ident() const +{ + return EVR_dataset; +} + + +E_TransferSyntax DcmDataset::getOriginalXfer() const +{ + return OriginalXfer; +} + + +E_TransferSyntax DcmDataset::getCurrentXfer() const +{ + return CurrentXfer; +} + + +void DcmDataset::updateOriginalXfer() +{ + DcmStack resultStack; + /* Check for pixel data element on main dataset level only. */ + /* Icon images and other nested pixel data elements are not checked. */ + if (search(DCM_PixelData, resultStack, ESM_fromHere, OFFalse).good()) + { + if (resultStack.top()->ident() == EVR_PixelData) + { + /* determine the transfer syntax of the original and current representation */ + E_TransferSyntax repType = EXS_Unknown; + const DcmRepresentationParameter *repParam = NULL; + DcmPixelData *pixelData = OFstatic_cast(DcmPixelData *, resultStack.top()); + pixelData->getOriginalRepresentationKey(OriginalXfer, repParam); + pixelData->getCurrentRepresentationKey(repType, repParam); + /* check whether we also need to change the current transfer syntax */ + if (repType == EXS_LittleEndianExplicit /* default */) + { + /* only change the value if not already uncompressed */ + if ((CurrentXfer != EXS_LittleEndianImplicit) && + (CurrentXfer != EXS_LittleEndianExplicit) && + (CurrentXfer != EXS_BigEndianExplicit)) + { + CurrentXfer = repType; + } + } + else if (repType != EXS_Unknown) + { + CurrentXfer = repType; + } + } else { + /* something is fishy with the pixel data element (wrong class) */ + DCMDATA_WARN("DcmDataset: Wrong class for pixel data element, cannot update original transfer syntax"); + } + } + /* if no pixel data was found, update only in case of unknown representation */ + else + { + if (OriginalXfer == EXS_Unknown) + { + /* this is also the default in DcmPixelData::getOriginalRepresentationKey() */ + OriginalXfer = EXS_LittleEndianExplicit; + } + if (CurrentXfer == EXS_Unknown) + { + /* this is also the default in DcmPixelData::getCurrentRepresentationKey() */ + CurrentXfer = EXS_LittleEndianExplicit; + } + } +} + + +void DcmDataset::removeInvalidGroups(const OFBool cmdSet) +{ + DcmStack stack; + DcmObject *object = NULL; + /* check for data or command set */ + if (cmdSet) + { + /* iterate over all elements */ + while (nextObject(stack, OFTrue).good()) + { + object = stack.top(); + /* in command sets, only group 0x0000 is allowed */ + if (object->getGTag() != 0x0000) + { + DCMDATA_DEBUG("DcmDataset::removeInvalidGroups() removing element " + << object->getTag() << " from command set"); + stack.pop(); + /* remove element from command set and free memory */ + delete OFstatic_cast(DcmItem *, stack.top())->remove(object); + } + } + } else { + /* iterate over all elements */ + while (nextObject(stack, OFTrue).good()) + { + object = stack.top(); + /* in data sets, group 0x0000 to 0x0003, 0x0005, 0x0007 and 0xFFFF are not allowed */ + if ((object->getGTag() == 0x0000) || (object->getGTag() == 0x0002) || + !object->getTag().hasValidGroup()) + { + DCMDATA_DEBUG("DcmDataset::removeInvalidGroups() removing element " + << object->getTag() << " from data set"); + stack.pop(); + /* remove element from data set and free memory */ + delete OFstatic_cast(DcmItem *, stack.top())->remove(object); + } + /* in sequence items, also group 0x0006 is not allowed */ + else if ((stack.card() > 2) && (object->getGTag() == 0x0006)) + { + DCMDATA_DEBUG("DcmDataset::removeInvalidGroups() removing element " + << object->getTag() << " from sequence item"); + stack.pop(); + /* remove element from data set and free memory */ + delete OFstatic_cast(DcmItem *, stack.top())->remove(object); + } + } + } +} + + +// ******************************** + + +Uint32 DcmDataset::calcElementLength(const E_TransferSyntax xfer, + const E_EncodingType enctype) +{ + return DcmItem::getLength(xfer, enctype); +} + + +// ******************************** + + +OFBool DcmDataset::canWriteXfer(const E_TransferSyntax newXfer, + const E_TransferSyntax oldXfer) +{ + if (newXfer == EXS_Unknown) + return OFFalse; + + /* Check stream compression for this transfer syntax */ + DcmXfer xf(newXfer); + if (xf.getStreamCompression() == ESC_unsupported) + return OFFalse; + + return DcmItem::canWriteXfer(newXfer, (OriginalXfer == EXS_Unknown) ? oldXfer : OriginalXfer); +} + + +// ******************************** + + +void DcmDataset::print(STD_NAMESPACE ostream&out, + const size_t flags, + const int level, + const char *pixelFileName, + size_t *pixelCounter) +{ + out << OFendl; + if (flags & DCMTypes::PF_useANSIEscapeCodes) + out << DCMDATA_ANSI_ESCAPE_CODE_COMMENT; + printNestingLevel(out, flags, level); + out << "# Dicom-Data-Set" << OFendl; + if (flags & DCMTypes::PF_useANSIEscapeCodes) + out << DCMDATA_ANSI_ESCAPE_CODE_COMMENT; + printNestingLevel(out, flags, level); + out << "# Used TransferSyntax: " << DcmXfer(CurrentXfer).getXferName(); + if (flags & DCMTypes::PF_useANSIEscapeCodes) + out << DCMDATA_ANSI_ESCAPE_CODE_RESET; + out << OFendl; + if (!elementList->empty()) + { + DcmObject *dO; + elementList->seek(ELP_first); + do { + dO = elementList->get(); + dO->print(out, flags, level + 1, pixelFileName, pixelCounter); + } while (elementList->seek(ELP_next)); + } +} + + +// ******************************** + + +OFCondition DcmDataset::writeXML(STD_NAMESPACE ostream &out, + const size_t flags) +{ + /* the Native DICOM Model as defined for Application Hosting needs special handling */ + if (flags & DCMTypes::XF_useNativeModel) + { + /* write XML start tag */ + out << "" << OFendl; + } else { + /* DCMTK-specific output format (default) */ + OFString xmlString; + DcmXfer xfer(CurrentXfer); + /* write XML start tag */ + out << "" << OFendl; + } + /* write dataset content */ + if (!elementList->empty()) + { + /* write content of all children */ + DcmObject *dO; + elementList->seek(ELP_first); + do { + dO = elementList->get(); + dO->writeXML(out, flags & ~DCMTypes::XF_useXMLNamespace); + } while (elementList->seek(ELP_next)); + } + /* write XML end tag (depending on output format) */ + if (flags & DCMTypes::XF_useNativeModel) + { + out << "" << OFendl; + } else { + out << "" << OFendl; + } + /* always report success */ + return EC_Normal; +} + + +// ******************************** + + +OFCondition DcmDataset::read(DcmInputStream &inStream, + const E_TransferSyntax xfer, + const E_GrpLenEncoding glenc, + const Uint32 maxReadLength) +{ + /* check if the stream variable reported an error */ + errorFlag = inStream.status(); + /* if the stream did not report an error but the stream */ + /* is empty, set the error flag correspondingly */ + if (errorFlag.good() && inStream.eos()) + errorFlag = EC_EndOfStream; + /* else if the stream did not report an error but the transfer */ + /* state does not equal ERW_ready, go ahead and do something */ + else if (errorFlag.good() && getTransferState() != ERW_ready) + { + /* if the transfer state is ERW_init, go ahead and check the transfer syntax which was passed */ + if (getTransferState() == ERW_init) + { + if (dcmAutoDetectDatasetXfer.get()) + { + DCMDATA_DEBUG("DcmDataset::read() automatic detection of transfer syntax is enabled"); + /* To support incorrectly encoded datasets detect the transfer syntax from the stream. */ + /* This is possible for given unknown and plain big or little endian transfer syntaxes. */ + switch (xfer) + { + case EXS_Unknown: + case EXS_LittleEndianImplicit: + case EXS_LittleEndianExplicit: + case EXS_BigEndianExplicit: + case EXS_BigEndianImplicit: + DCMDATA_DEBUG("DcmDataset::read() trying to detect transfer syntax of uncompressed dataset"); + OriginalXfer = checkTransferSyntax(inStream); + if ((xfer != EXS_Unknown) && (OriginalXfer != xfer)) + DCMDATA_WARN("DcmDataset: Wrong transfer syntax specified, detecting from dataset"); + break; + default: + DCMDATA_DEBUG("DcmDataset::read() dataset seems to be compressed, so transfer syntax is not detected"); + OriginalXfer = xfer; + break; + } + } + else /* default behavior */ + { + /* If the transfer syntax which was passed equals EXS_Unknown we want to */ + /* determine the transfer syntax from the information in the stream itself. */ + /* If the transfer syntax is given, we want to use it. */ + if (xfer == EXS_Unknown) + { + DCMDATA_DEBUG("DcmDataset::read() trying to detect transfer syntax of dataset (because it is unknown)"); + OriginalXfer = checkTransferSyntax(inStream); + } else + OriginalXfer = xfer; + } + /* dump information on debug level */ + DCMDATA_DEBUG("DcmDataset::read() TransferSyntax=\"" + << DcmXfer(OriginalXfer).getXferName() << "\""); + CurrentXfer = OriginalXfer; + /* check stream compression for this transfer syntax */ + DcmXfer xf(OriginalXfer); + E_StreamCompression sc = xf.getStreamCompression(); + switch (sc) + { + case ESC_none: + // nothing to do + break; + case ESC_unsupported: + // stream compressed transfer syntax that we cannot create; bail out. + if (errorFlag.good()) + errorFlag = EC_UnsupportedEncoding; + break; + default: + // supported stream compressed transfer syntax, install filter + errorFlag = inStream.installCompressionFilter(sc); + break; + } + } + /* pass processing the task to class DcmItem */ + if (errorFlag.good()) + errorFlag = DcmItem::read(inStream, OriginalXfer, glenc, maxReadLength); + } + + /* if the error flag shows ok or that the end of the stream was encountered, */ + /* we have read information for this particular data set or command; in this */ + /* case, we need to do something for the current dataset object */ + if (errorFlag.good() || errorFlag == EC_EndOfStream) + { + /* set the error flag to ok */ + errorFlag = EC_Normal; + + /* take care of group length (according to what is specified */ + /* in glenc) and padding elements (don't change anything) */ + computeGroupLengthAndPadding(glenc, EPD_noChange, OriginalXfer); + + /* and set the transfer state to ERW_ready to indicate that the data set is complete */ + setTransferState(ERW_ready); + } + + /* dump information if required */ + DCMDATA_TRACE("DcmDataset::read() returns error = " << errorFlag.text()); + + /* return result flag */ + return errorFlag; +} + + +// ******************************** + + +OFCondition DcmDataset::write( + DcmOutputStream &outStream, + const E_TransferSyntax oxfer, + const E_EncodingType enctype /* = EET_UndefinedLength */, + DcmWriteCache *wcache) +{ + return write(outStream, oxfer, enctype, wcache, EGL_recalcGL); +} + + +OFCondition DcmDataset::write(DcmOutputStream &outStream, + const E_TransferSyntax oxfer, + const E_EncodingType enctype, + DcmWriteCache *wcache, + const E_GrpLenEncoding glenc, + const E_PaddingEncoding padenc, + const Uint32 padlen, + const Uint32 subPadlen, + Uint32 instanceLength) +{ + /* if the transfer state of this is not initialized, this is an illegal call */ + if (getTransferState() == ERW_notInitialized) + errorFlag = EC_IllegalCall; + else + { + /* check if the stream reported an error so far; if not, we can go ahead and write some data to it */ + errorFlag = outStream.status(); + + if (errorFlag.good() && getTransferState() != ERW_ready) + { + /* Determine the transfer syntax which shall be used. Either we use the one which was passed, */ + /* or (if it's an unknown transfer syntax) we use the one which is contained in OriginalXfer. */ + E_TransferSyntax newXfer = oxfer; + if (newXfer == EXS_Unknown) + newXfer = OriginalXfer; + + /* if this function was called for the first time for the dataset object, the transferState is still */ + /* set to ERW_init. In this case, we need to take care of group length and padding elements according */ + /* to the strategies which are specified in glenc and padenc. Additionally, we need to set the element */ + /* list pointer of this data set to the fist element and we need to set the transfer state to ERW_inWork */ + /* so that this scenario will only be executed once for this data set object. */ + if (getTransferState() == ERW_init) + { + + /* Check stream compression for this transfer syntax */ + DcmXfer xf(newXfer); + E_StreamCompression sc = xf.getStreamCompression(); + switch (sc) + { + case ESC_none: + // nothing to do + break; + case ESC_unsupported: + // stream compressed transfer syntax that we cannot create; bail out. + if (errorFlag.good()) + errorFlag = EC_UnsupportedEncoding; + break; + default: + // supported stream compressed transfer syntax, install filter + errorFlag = outStream.installCompressionFilter(sc); + break; + } + + /* take care of group length and padding elements, according to what is specified in glenc and padenc */ + computeGroupLengthAndPadding(glenc, padenc, newXfer, enctype, padlen, subPadlen, instanceLength); + elementList->seek(ELP_first); + setTransferState(ERW_inWork); + } + + /* if the transfer state is set to ERW_inWork, we need to write the information which */ + /* is included in this data set's element list into the buffer which was passed. */ + if (getTransferState() == ERW_inWork) + { + // Remember that elementList->get() can be NULL if buffer was full after + // writing the last item but before writing the sequence delimitation. + if (!elementList->empty() && (elementList->get() != NULL)) + { + /* as long as everything is ok, go through all elements of this data */ + /* set and write the corresponding information to the buffer */ + DcmObject *dO; + do + { + dO = elementList->get(); + errorFlag = dO->write(outStream, newXfer, enctype, wcache); + } while (errorFlag.good() && elementList->seek(ELP_next)); + } + + /* if all the information in this has been written to the */ + /* buffer set this data set's transfer state to ERW_ready */ + if (errorFlag.good()) + { + setTransferState(ERW_ready); + CurrentXfer = newXfer; + } + } + } + } + + /* return the corresponding result value */ + return errorFlag; +} + + +// ******************************** + + +OFCondition DcmDataset::writeSignatureFormat(DcmOutputStream &outStream, + const E_TransferSyntax oxfer, + const E_EncodingType enctype, + DcmWriteCache *wcache) +{ + if (getTransferState() == ERW_notInitialized) + errorFlag = EC_IllegalCall; + else + { + E_TransferSyntax newXfer = oxfer; + if (newXfer == EXS_Unknown) + newXfer = OriginalXfer; + + errorFlag = outStream.status(); + if (errorFlag.good() && getTransferState() != ERW_ready) + { + if (getTransferState() == ERW_init) + { + computeGroupLengthAndPadding(EGL_recalcGL, EPD_noChange, newXfer, enctype, 0, 0, 0); + elementList->seek(ELP_first); + setTransferState(ERW_inWork); + } + if (getTransferState() == ERW_inWork) + { + // elementList->get() can be NULL if buffer was full after + // writing the last item but before writing the sequence delimitation. + if (!elementList->empty() && (elementList->get() != NULL)) + { + DcmObject *dO; + do { + dO = elementList->get(); + errorFlag = dO->writeSignatureFormat(outStream, newXfer, enctype, wcache); + } while (errorFlag.good() && elementList->seek(ELP_next)); + } + if (errorFlag.good()) + { + setTransferState(ERW_ready); + CurrentXfer = newXfer; + } + } + } + } + return errorFlag; +} + + +// ******************************** + + +OFCondition DcmDataset::loadFile(const OFFilename &fileName, + const E_TransferSyntax readXfer, + const E_GrpLenEncoding groupLength, + const Uint32 maxReadLength) +{ + OFCondition l_error = EC_InvalidFilename; + /* check parameters first */ + if (!fileName.isEmpty()) + { + /* open file for input */ + DcmInputFileStream fileStream(fileName); + + /* check stream status */ + l_error = fileStream.status(); + + if (l_error.good()) + { + /* clear this object */ + l_error = clear(); + if (l_error.good()) + { + /* read data from file */ + transferInit(); + l_error = read(fileStream, readXfer, groupLength, maxReadLength); + transferEnd(); + } + } + } + return l_error; +} + + +OFCondition DcmDataset::saveFile(const OFFilename &fileName, + const E_TransferSyntax writeXfer, + const E_EncodingType encodingType, + const E_GrpLenEncoding groupLength, + const E_PaddingEncoding padEncoding, + const Uint32 padLength, + const Uint32 subPadLength) +{ + OFCondition l_error = EC_InvalidFilename; + /* check parameters first */ + if (!fileName.isEmpty()) + { + DcmWriteCache wcache; + /* open file for output */ + DcmOutputFileStream fileStream(fileName); + + /* check stream status */ + l_error = fileStream.status(); + if (l_error.good()) + { + /* write data to file */ + transferInit(); + l_error = write(fileStream, writeXfer, encodingType, &wcache, groupLength, padEncoding, padLength, subPadLength); + transferEnd(); + } + } + return l_error; +} + + +// ******************************** + + +OFCondition DcmDataset::chooseRepresentation(const E_TransferSyntax repType, + const DcmRepresentationParameter *repParam) +{ + OFCondition l_error = EC_Normal; + OFStack pixelStack; + + DcmStack resultStack; + resultStack.push(this); + // in a first step, search for all PixelData elements in this dataset + while (search(DCM_PixelData, resultStack, ESM_afterStackTop, OFTrue).good() && l_error.good()) + { + + if (resultStack.top()->ident() == EVR_PixelData) + { + DcmPixelData *pixelData = OFstatic_cast(DcmPixelData *, resultStack.top()); + if (!pixelData->canChooseRepresentation(repType, repParam)) + l_error = EC_CannotChangeRepresentation; + pixelStack.push(resultStack); + } else { + /* something is fishy with the pixel data element (wrong class) */ + DCMDATA_ERROR("DcmDataset: Wrong class for pixel data element, cannot change representation"); + l_error = EC_CannotChangeRepresentation; + } + } + // then call the method doing the real work for all these elements + while (l_error.good() && (pixelStack.size() > 0)) + { + l_error = OFstatic_cast(DcmPixelData *, pixelStack.top().top())-> + chooseRepresentation(repType, repParam, pixelStack.top()); + +#ifdef PIXELSTACK_MEMORY_LEAK_WORKAROUND + // on certain platforms there seems to be a memory leak + // at this point since for some reason pixelStack.pop does + // not completely destruct the DcmStack object taken from the stack. + // The following work-around should solve this issue. + pixelStack.top().clear(); +#endif + + pixelStack.pop(); + } + // store current transfer syntax (if conversion was successfully) + if (l_error.good()) + CurrentXfer = repType; + return l_error; +} + + +OFBool DcmDataset::hasRepresentation(const E_TransferSyntax repType, + const DcmRepresentationParameter *repParam) +{ + OFBool result = OFTrue; + DcmStack resultStack; + + while(search(DCM_PixelData, resultStack, ESM_afterStackTop, OFTrue).good() && result) + { + if (resultStack.top()->ident() == EVR_PixelData) + { + DcmPixelData *pixelData = OFstatic_cast(DcmPixelData *, resultStack.top()); + result = pixelData->hasRepresentation(repType, repParam); + } + else + result = OFFalse; + } + return result; +} + + +void DcmDataset::removeAllButCurrentRepresentations() +{ + DcmStack resultStack; + + while(search(DCM_PixelData, resultStack, ESM_afterStackTop, OFTrue).good()) + { + if (resultStack.top()->ident() == EVR_PixelData) + { + DcmPixelData *pixelData = OFstatic_cast(DcmPixelData *, resultStack.top()); + pixelData->removeAllButCurrentRepresentations(); + } + } +} + + +void DcmDataset::removeAllButOriginalRepresentations() +{ + DcmStack resultStack; + + while(search(DCM_PixelData, resultStack, ESM_afterStackTop, OFTrue).good()) + { + if (resultStack.top()->ident() == EVR_PixelData) + { + DcmPixelData *pixelData = OFstatic_cast(DcmPixelData *, resultStack.top()); + pixelData->removeAllButOriginalRepresentations(); + } + } +} diff --git a/dcmdata/libsrc/dcdatutl.cc b/dcmdata/libsrc/dcdatutl.cc new file mode 100644 index 00000000..01214ed1 --- /dev/null +++ b/dcmdata/libsrc/dcdatutl.cc @@ -0,0 +1,135 @@ +/* + * + * Copyright (C) 2015, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmiod + * + * Author: Michael Onken + * + * Purpose: Static helper functionality for dcmdata module + * + */ + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ +#include "dcmtk/dcmdata/dcdatutl.h" +#include "dcmtk/dcmdata/dctypes.h" +#include "dcmtk/dcmdata/dcdeftag.h" +#include "dcmtk/dcmdata/dcmetinf.h" +#include "dcmtk/dcmdata/dcfilefo.h" + +// --- static helpers --- + + +OFCondition DcmDataUtil::getSOPInstanceFromFile(const OFString &filename, + OFString &sopClassUID, + OFString &sopInstanceUID, + OFString &transferSyntaxUID, + const E_FileReadMode readMode) +{ + OFCondition status = EC_IllegalParameter; + if (!filename.empty()) + { + DCMDATA_DEBUG("getting SOP Class UID, SOP Instance UID and Transfer Syntax UID from DICOM file"); + sopClassUID.clear(); + sopInstanceUID.clear(); + transferSyntaxUID.clear(); + // prefer to load file meta information header only (since this is more efficient) + if (readMode != ERM_dataset) + { + DcmMetaInfo metaInfo; + status = metaInfo.loadFile(filename.c_str()); + if (status.good()) + { + // try to get the UIDs from the meta-header + DCMDATA_DEBUG("trying to get SOP Class UID, SOP Instance UID and Transfer Syntax UID from meta-header"); + metaInfo.findAndGetOFStringArray(DCM_MediaStorageSOPClassUID, sopClassUID); + metaInfo.findAndGetOFStringArray(DCM_MediaStorageSOPInstanceUID, sopInstanceUID); + metaInfo.findAndGetOFStringArray(DCM_TransferSyntaxUID, transferSyntaxUID); + } + } + // alternatively, get UIDs from the dataset (if required and desired) + if ((readMode != ERM_fileOnly) && (readMode != ERM_metaOnly)) + { + if (sopClassUID.empty() || sopInstanceUID.empty()) + DCMDATA_DEBUG("no SOP Class UID and/or SOP Instance UID found in meta-header, checking dataset instead"); + if (status.bad() || sopClassUID.empty() || sopInstanceUID.empty() || transferSyntaxUID.empty()) + { + DcmFileFormat fileformat; + status = fileformat.loadFile(filename.c_str(), EXS_Unknown, EGL_noChange, 256 /* maxReadLength */, readMode); + if (status.good()) + { + DcmDataset *dataset = fileformat.getDataset(); + if (dataset != NULL) + { + if (sopClassUID.empty()) + dataset->findAndGetOFStringArray(DCM_SOPClassUID, sopClassUID); + if (sopInstanceUID.empty()) + dataset->findAndGetOFStringArray(DCM_SOPInstanceUID, sopInstanceUID); + if (transferSyntaxUID.empty()) + { + DCMDATA_DEBUG("no Transfer Syntax UID found in meta-header, trying to determine from dataset instead"); + // empty string in case of unknown/unsupported transfer syntax + transferSyntaxUID = DcmXfer(dataset->getOriginalXfer()).getXferID(); + } + } + } + } + } + } + return status; +} + + +OFCondition DcmDataUtil::getSOPInstanceFromDataset(DcmDataset *dataset, + const E_TransferSyntax datasetXfer, + OFString &sopClassUID, + OFString &sopInstanceUID, + OFString &transferSyntaxUID) +{ + OFCondition status = EC_IllegalParameter; + // check for invalid dataset pointer + if (dataset != NULL) + { + DCMDATA_DEBUG("getting SOP Class UID, SOP Instance UID and Transfer Syntax UID from DICOM dataset"); + sopClassUID.clear(); + sopInstanceUID.clear(); + transferSyntaxUID.clear(); + // check for correct class type + if (dataset->ident() == EVR_dataset) + { + // try to determine the transfer syntax of the dataset + E_TransferSyntax xfer = datasetXfer; + if (xfer == EXS_Unknown) + xfer = dataset->getOriginalXfer(); + if (xfer == EXS_Unknown) + { + // update the internally stored transfer syntax based on the pixel data (if any) + dataset->updateOriginalXfer(); + xfer = dataset->getOriginalXfer(); + } + if (xfer != EXS_Unknown) + { + status = EC_Normal; + // store UID of the transfers syntax in result variable + transferSyntaxUID = DcmXfer(xfer).getXferID(); + // get other UIDs directly from the dataset + dataset->findAndGetOFStringArray(DCM_SOPClassUID, sopClassUID); + dataset->findAndGetOFStringArray(DCM_SOPInstanceUID, sopInstanceUID); + } else { + DCMDATA_DEBUG("unable to determine transfer syntax from dataset"); + status = EC_UnknownTransferSyntax; + } + } else + status = EC_CorruptedData; + } + return status; +} diff --git a/dcmdata/libsrc/dcddirif.cc b/dcmdata/libsrc/dcddirif.cc new file mode 100644 index 00000000..b038410b --- /dev/null +++ b/dcmdata/libsrc/dcddirif.cc @@ -0,0 +1,5646 @@ +/* + * + * Copyright (C) 2002-2015, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Joerg Riesmeier + * + * Purpose: Interface class for simplified creation of a DICOMDIR + * + */ + + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#define INCLUDE_CSTDIO +#define INCLUDE_CCTYPE +#define INCLUDE_CERRNO +#include "dcmtk/ofstd/ofstdinc.h" + +#include "dcmtk/dcmdata/dcddirif.h" +#include "dcmtk/dcmdata/dcdeftag.h" +#include "dcmtk/dcmdata/dcuid.h" +#include "dcmtk/dcmdata/dccodec.h" +#include "dcmtk/dcmdata/dcmetinf.h" /* for class DcmMetaInfo */ +#include "dcmtk/dcmdata/dcpixel.h" /* for class DcmPixelData */ +#include "dcmtk/dcmdata/dcpxitem.h" /* for class DcmPixelItem */ +#include "dcmtk/dcmdata/dcpixseq.h" /* for class DcmPixelSequence */ +#include "dcmtk/dcmdata/dcvrcs.h" /* for class DcmCodeString */ +#include "dcmtk/dcmdata/dcvrda.h" /* for class DcmDate */ +#include "dcmtk/dcmdata/dcvrtm.h" /* for class DcmTime */ + +#include "dcmtk/ofstd/ofstd.h" +#include "dcmtk/ofstd/ofstream.h" +#include "dcmtk/ofstd/ofbmanip.h" /* for class OFBitmanipTemplate */ +#include "dcmtk/ofstd/ofcast.h" + + +/*-------------------------* + * constant declarations * + *-------------------------*/ + +// an ISO 9660 format only allows 8 characters in file name +#define MAX_FNAME_COMPONENT_SIZE 8 +// DICOM only allows max 8 path components in a file name +#define MAX_FNAME_COMPONENTS 8 +// max. number of characters printed for string values in a warning message +#define MAX_PRINT_LENGTH 64 +// filename extension for a backup file +#define FNAME_BACKUP_EXTENSION ".BAK" +// prefix used to automatically create patient IDs (+ 6 digits) +#define AUTO_PATIENTID_PREFIX "DCMTKPAT" +// prefix used to automatically create study IDs (+ 6 digits) +#define AUTO_STUDYID_PREFIX "DCMTKSTUDY" + + +/*------------------------* + * forward declarations * + *------------------------*/ + +static OFBool compareSQAttributes(DcmSequenceOfItems *seq1, + DcmSequenceOfItems *seq2, + OFString &reason); + + +/*--------------------------* + * local helper functions * + *--------------------------*/ + +// count number of filename components +static int componentCount(const OFString &filename, + const char separator = PATH_SEPARATOR) +{ + const size_t length = filename.length(); + int count = (length > 0) ? 1 : 0; + for (size_t i = 0; i < length; i++) + { + if (filename.at(i) == separator) + count++; + } + return count; +} + + +// check whether filename component size is within allowed range +static OFBool isComponentTooLarge(const OFString &filename, + const size_t componentLimit, + const OFBool mapFilenames, + const char separator = PATH_SEPARATOR) +{ + OFBool result = OFFalse; + const size_t length = filename.length(); + if (length > 0) + { + size_t pos1 = 0; + size_t pos2 = filename.find(separator); + while (pos2 != OFString_npos) + { + /* check whether component length is within limit */ + if (pos2 - pos1 > componentLimit) + { + result = OFTrue; + break; + } + pos1 = pos2 + 1; + pos2 = filename.find(separator, pos1); + } + if (!result) + { + /* check last component: disregard trailing point */ + if (mapFilenames && (filename.at(length - 1) == '.')) + pos1++; + if (length - pos1 > componentLimit) + result = OFTrue; + } + } + return result; +} + + +// check whether filename contains invalid characters (and locate the first one) +static OFBool locateInvalidFilenameChars(const OFString &filename, + size_t &invalidChar, + const OFBool mapFilenames, + const char separator = PATH_SEPARATOR) +{ + unsigned char c; + size_t i = 0; + size_t length = filename.length(); + /* disregard trailing point */ + if (mapFilenames && (length > 0) && (filename.at(length - 1) == '.')) + length--; + /* iterate over all characters */ + for (i = 0; i < length; i++) + { + c = filename.at(i); + if ((c == '_') || isdigit(c) || (c == separator) || + (isalpha(c) && (isupper(c) || (islower(c) && mapFilenames)))) + { + /* all ok */ + } + else if ((c != '\\') || (separator != '\\')) + { + /* invalid character */ + break; + } + } + /* return position of first invalid character (eos if all valid) */ + invalidChar = i; + /* OFTrue in case of any invalid character */ + return (i != length); +} + + +// massage filename into DICOM format (DOS conventions for path separators, uppercase characters) +static OFString &hostToDicomFilename(const OFString &hostFilename, + OFString &dicomFilename) +{ + dicomFilename.clear(); + const size_t length = hostFilename.length(); + dicomFilename.reserve(length); + for (size_t i = 0; i < length; i++) + { + const unsigned char c = hostFilename.at(i); + if (c == PATH_SEPARATOR) + { + /* the PATH_SEPARATOR depends on the OS (see ) */ + dicomFilename += '\\'; + } + else if (isalpha(c)) + { + /* filenames in DICOM must always be in uppercase */ + dicomFilename += OFstatic_cast(char, toupper(c)); + } + else if (isdigit(c) || (c == '_') || (c == '\\')) + { + /* only characters, digits, underscore and backslash (path separator) allowed */ + dicomFilename += c; + } + } + return dicomFilename; +} + + +/* Massage filename into machine format (replace DOS conventions for path separators) */ +static OFString &dicomToHostFilename(const OFString &dicomFilename, + OFString &hostFilename, + OFBool mapToLower = OFFalse) +{ + hostFilename.clear(); + const size_t length = dicomFilename.length(); + hostFilename.reserve(length); + for (size_t i = 0; i < length; i++) + { + const unsigned char c = dicomFilename.at(i); + /* the PATH_SEPARATOR depends on the OS (see ) */ + if (c == '\\') + hostFilename += PATH_SEPARATOR; + else if (mapToLower) + hostFilename += OFstatic_cast(char, tolower(c)); + else + hostFilename += c; + } + return hostFilename; +} + + +// check whether given DICOM file exists +static OFBool locateDicomFile(const OFString &dicomFilename, + OFString &hostFilename) +{ + dicomToHostFilename(dicomFilename, hostFilename); + OFBool result = OFStandard::fileExists(hostFilename); + if (!result) + { + /* trailing period */ + hostFilename += '.'; + result = OFStandard::fileExists(hostFilename); + } + if (!result) + { + /* lowercase */ + dicomToHostFilename(dicomFilename, hostFilename, OFTrue /*mapToLower*/); + result = OFStandard::fileExists(hostFilename); + if (!result) + { + /* lowercase with trailing period */ + hostFilename += '.'; + result = OFStandard::fileExists(hostFilename); + } + } + if (!result) + { + /* DICOM file not found */ + hostFilename.clear(); + } + return result; +} + + +// compare two strings (empty strings are always regarded as unequal) +static OFBool compare(const OFString &string1, + const OFString &string2) +{ + if (string1.empty() || string2.empty()) + return OFFalse; + return (string1.compare(string2) == 0) ? OFTrue : OFFalse; +} + + +// construct tag name from given object +static OFString &constructTagName(DcmObject *object, + OFString &tagName) +{ + if (object != NULL) + { + DcmTag tag = object->getTag(); + tagName = tag.getTagName(); + // use tag name only if not equal to DcmTag_ERROR_TagName + if (compare(tagName, DcmTag_ERROR_TagName)) + { + char buffer[32]; + sprintf(buffer, "(0x%04x,0x%04x)", tag.getGTag(), tag.getETag()); + tagName = buffer; + } + } else + tagName = "(NULL)"; + return tagName; +} + + +// construct tag name from given object and sequence +static OFString &constructTagNameWithSQ(DcmObject *object, + DcmSequenceOfItems *fromSequence, + const unsigned long itemNumber, + OFString &tagName) +{ + OFString tempStr; + if (fromSequence != NULL) + { + /* create text */ + OFOStringStream oss; + oss << constructTagName(fromSequence, tempStr) << "[" << itemNumber << "]" << OFStringStream_ends; + OFSTRINGSTREAM_GETSTR(oss, tmpString) + tagName = tmpString; + OFSTRINGSTREAM_FREESTR(tmpString) + /* append "." for tag name */ + if (object != NULL) + tagName += '.'; + } else + tagName.clear(); + if (object != NULL) + tagName += constructTagName(object, tempStr); + else if (tagName.empty()) + tagName = "(NULL)"; + return tagName; +} + + +// construct text message of two differing numerical values +static OFString &constructDifferentNumbersText(const unsigned long number1, + const unsigned long number2, + OFString &textValue) +{ + textValue.clear(); + /* create message text */ + OFOStringStream oss; + oss << number1 << " != " << number2 << OFStringStream_ends; + OFSTRINGSTREAM_GETSTR(oss, tmpString) + textValue = tmpString; + OFSTRINGSTREAM_FREESTR(tmpString) + return textValue; +} + + +// compare given element values and report any deviation +static OFBool compareAttributes(DcmElement *elem1, + DcmElement *elem2, + DcmSequenceOfItems *fromSequence, + unsigned long itemNumber, + OFString &reason) +{ + reason.clear(); + OFString tmpString; + /* check whether elements are valid */ + if (elem1 != NULL) + { + if (elem2 != NULL) + { + /* check whether tags are equal */ + if (elem1->getTag().getXTag() == elem2->getTag().getXTag()) + { + DcmVR vr1(elem1->getVR()); + DcmVR vr2(elem2->getVR()); + /* are the VRs the same? */ + if (vr1.getEVR() == vr2.getEVR()) + { + const unsigned long length1 = elem1->getLength(); + const unsigned long length2 = elem2->getLength(); + /* are the lengths the same? */ + if (length1 == length2) + { + /* are the contents the same? */ + if (length1 > 0) + { + if (vr1.getEVR() == EVR_SQ) + { + /* compare embedded sequences recursively */ + compareSQAttributes(OFstatic_cast(DcmSequenceOfItems *, elem1), + OFstatic_cast(DcmSequenceOfItems *, elem2), reason); + } else { + /* everything else is regarded as a string, might be useful to check binary data separately though */ + OFString value1, value2; + /* compare string value from dataset and record */ + if (elem1->getOFStringArray(value1).good() && elem2->getOFStringArray(value2).good()) + { + if (!compare(value1, value2)) + { + reason = "different values: "; + /* print differing values */ + if ((value1.length() < MAX_PRINT_LENGTH) && (value2.length() < MAX_PRINT_LENGTH)) + reason += "\"" + value1 + "\" != \"" + value2 + "\" "; + reason += "(" + constructTagNameWithSQ(elem1, fromSequence, itemNumber, tmpString) + ")"; + } + } + } + } + } else { + reason = "different value lengths: " + constructDifferentNumbersText(length1, length2, tmpString); + reason += " (" + constructTagNameWithSQ(elem1, fromSequence, itemNumber, tmpString) + ")"; + } + } else + reason = "different VRs: " + OFString(vr1.getVRName()) + " != " + vr2.getVRName() + + " (" + constructTagNameWithSQ(elem1, fromSequence, itemNumber, tmpString) + ")"; + } else + reason = "INTERNAL ERROR: different attributes: " + + constructTagNameWithSQ(elem1, fromSequence, itemNumber, tmpString) + " != " + + constructTagNameWithSQ(elem2, fromSequence, itemNumber, tmpString); + } else + reason = "missing attribute: " + constructTagNameWithSQ(elem2, fromSequence, itemNumber, tmpString); + } else + reason = "missing attribute: " + constructTagNameWithSQ(elem1, fromSequence, itemNumber, tmpString); + /* non-empty reason variable indicates an error */ + return reason.empty(); +} + + +// compare given items for equivalence and report any deviation +static OFBool compareItems(DcmItem *item1, + DcmItem *item2, + DcmSequenceOfItems *fromSequence, + const unsigned long itemNumber, + OFString &reason) +{ + reason.clear(); + OFString tmpString; + /* check whether items are valid */ + if ((item1 != NULL) && (item2 != NULL)) + { + const unsigned long card1 = item1->card(); + const unsigned long card2 = item2->card(); + /* check whether number of attributes is identical */ + if (card1 == card2) + { + unsigned long i = 0; + OFBool first = OFTrue; + DcmStack stack1, stack2; + /* check whether attributes are equal */ + while (item1->nextObject(stack1, first).good() && item2->nextObject(stack2, first).good()) + { + if (!compareAttributes(OFstatic_cast(DcmElement *, stack1.top()), OFstatic_cast(DcmElement *, stack2.top()), fromSequence, i++, reason)) + break; + first = OFFalse; + } + } else { + reason = "different number of attributes in item: " + constructDifferentNumbersText(card1, card2, tmpString); + reason += " (" + constructTagNameWithSQ(NULL /*object*/, fromSequence, itemNumber, tmpString) + ")"; + } + } else + reason = "missing item: " + constructTagNameWithSQ(NULL /*object*/, fromSequence, itemNumber, tmpString); + /* non-empty reason variable indicates an error */ + return reason.empty(); +} + + +// compare given sequences for equivalence and report any deviation +static OFBool compareSQAttributes(DcmSequenceOfItems *seq1, + DcmSequenceOfItems *seq2, + OFString &reason) +{ + reason.clear(); + OFString tmpString; + /* check whether sequences are valid */ + if (seq1 != NULL) + { + if (seq2 != NULL) + { + /* check whether tags are equal */ + if (seq1->getTag().getXTag() == seq2->getTag().getXTag()) + { + const unsigned long card1 = seq1->card(); + const unsigned long card2 = seq2->card(); + /* check whether number of items is identical */ + if (card1 == card2) + { + unsigned long i = 0; + OFBool first = OFTrue; + DcmStack stack1, stack2; + /* check whether items are equal */ + while (seq1->nextObject(stack1, first).good() && seq2->nextObject(stack2, first).good()) + { + if (!compareItems(OFstatic_cast(DcmItem *, stack1.top()), OFstatic_cast(DcmItem *, stack2.top()), seq1, i++, reason)) + break; + first = OFFalse; + } + } else { + reason = "different number of items in sequence: " + constructDifferentNumbersText(card1, card2, tmpString); + reason += " (" + constructTagName(seq1, tmpString) + ")"; + } + } else + reason = "INTERNAL ERROR: different sequences: " + constructTagName(seq1, tmpString) + " != " + + constructTagName(seq2, tmpString); + } else + reason = "missing sequence: " + constructTagName(seq2, tmpString); + } else + reason = "missing sequence: " + constructTagName(seq1, tmpString); + /* non-empty reason variable indicates an error */ + return reason.empty(); +} + + +// get directory record name from type (static) +OFString DicomDirInterface::recordTypeToName(const E_DirRecType recordType) +{ + const char *recordName = NULL; + switch (recordType) + { + case ERT_root: + recordName = "Root"; + break; + case ERT_Curve: + recordName = "Curve"; + break; + case ERT_FilmBox: + recordName = "FilmBox"; + break; + case ERT_FilmSession: + recordName = "FilmSession"; + break; + case ERT_Image: + recordName = "Image"; + break; + case ERT_ImageBox: + recordName = "ImageBox"; + break; + case ERT_Interpretation: + recordName = "Interpretation"; + break; + case ERT_ModalityLut: + recordName = "ModalityLUT"; + break; + case ERT_Mrdr: + recordName = "MRDR"; + break; + case ERT_Overlay: + recordName = "Overlay"; + break; + case ERT_Patient: + recordName = "Patient"; + break; + case ERT_PrintQueue: + recordName = "PrintQueue"; + break; + case ERT_Private: + recordName = "Private"; + break; + case ERT_Results: + recordName = "Results"; + break; + case ERT_Series: + recordName = "Series"; + break; + case ERT_Study: + recordName = "Study"; + break; + case ERT_StudyComponent: + recordName = "StudyComponent"; + break; + case ERT_Topic: + recordName = "Topic"; + break; + case ERT_Visit: + recordName = "Visit"; + break; + case ERT_VoiLut: + recordName = "VOILUT"; + break; + case ERT_SRDocument: + recordName = "SRDocument"; + break; + case ERT_Presentation: + recordName = "Presentation"; + break; + case ERT_Waveform: + recordName = "Waveform"; + break; + case ERT_RTDose: + recordName = "RTDose"; + break; + case ERT_RTStructureSet: + recordName = "RTStructureSet"; + break; + case ERT_RTPlan: + recordName = "RTPlan"; + break; + case ERT_RTTreatRecord: + recordName = "RTTreatRecord"; + break; + case ERT_StoredPrint: + recordName = "StoredPrint"; + break; + case ERT_KeyObjectDoc: + recordName = "KeyObjectDoc"; + break; + case ERT_Registration: + recordName = "Registration"; + break; + case ERT_Fiducial: + recordName = "Fiducial"; + break; + case ERT_RawData: + recordName = "RawData"; + break; + case ERT_Spectroscopy: + recordName = "Spectroscopy"; + break; + case ERT_EncapDoc: + recordName = "EncapDoc"; + break; + case ERT_ValueMap: + recordName = "ValueMap"; + break; + case ERT_HangingProtocol: + recordName = "HangingProtocol"; + break; + case ERT_Stereometric: + recordName = "Stereometric"; + break; + case ERT_HL7StrucDoc: + recordName = "HL7StrucDoc"; + break; + case ERT_Palette: + recordName = "Palette"; + break; + case ERT_Surface: + recordName = "Surface"; + break; + case ERT_Measurement: + recordName = "Measurement"; + break; + case ERT_Implant: + recordName = "Implant"; + break; + case ERT_ImplantGroup: + recordName = "ImplantGroup"; + break; + case ERT_ImplantAssy: + recordName = "ImplantAssy"; + break; + case ERT_Plan: + recordName = "Plan"; + break; + case ERT_SurfaceScan: + recordName = "SurfaceScan"; + break; + default: + recordName = "(unknown-directory-record-type)"; + break; + } + return recordName; +} + + +// get record type from SOP class +static E_DirRecType sopClassToRecordType(const OFString &sopClass) +{ + /* default: image SOP class */ + E_DirRecType result = ERT_Image; + /* check whether any non-image SOP class */ + if (compare(sopClass, UID_RETIRED_StandaloneOverlayStorage)) + result = ERT_Overlay; + else if (compare(sopClass, UID_RETIRED_StandaloneModalityLUTStorage)) + result = ERT_ModalityLut; + else if (compare(sopClass, UID_RETIRED_StandaloneVOILUTStorage)) + result = ERT_VoiLut; + else if (compare(sopClass, UID_RETIRED_StandaloneCurveStorage) || + compare(sopClass, UID_RETIRED_StandalonePETCurveStorage)) + { + result = ERT_Curve; + } + else if (compare(sopClass, UID_BasicTextSRStorage) || + compare(sopClass, UID_EnhancedSRStorage) || + compare(sopClass, UID_ComprehensiveSRStorage) || + compare(sopClass, UID_Comprehensive3DSRStorage) || + compare(sopClass, UID_ExtensibleSRStorage) || + compare(sopClass, UID_ProcedureLogStorage) || + compare(sopClass, UID_MammographyCADSRStorage) || + compare(sopClass, UID_ChestCADSRStorage) || + compare(sopClass, UID_ColonCADSRStorage) || + compare(sopClass, UID_XRayRadiationDoseSRStorage) || + compare(sopClass, UID_RadiopharmaceuticalRadiationDoseSRStorage) || + compare(sopClass, UID_SpectaclePrescriptionReportStorage) || + compare(sopClass, UID_MacularGridThicknessAndVolumeReportStorage) || + compare(sopClass, UID_ImplantationPlanSRDocumentStorage)) + { + result = ERT_SRDocument; + } + else if (compare(sopClass, UID_GrayscaleSoftcopyPresentationStateStorage) || + compare(sopClass, UID_ColorSoftcopyPresentationStateStorage) || + compare(sopClass, UID_PseudoColorSoftcopyPresentationStateStorage) || + compare(sopClass, UID_BlendingSoftcopyPresentationStateStorage) || + compare(sopClass, UID_XAXRFGrayscaleSoftcopyPresentationStateStorage) || + compare(sopClass, UID_GrayscalePlanarMPRVolumetricPresentationStateStorage) || + compare(sopClass, UID_CompositingPlanarMPRVolumetricPresentationStateStorage) || + compare(sopClass, UID_BasicStructuredDisplayStorage)) + { + result = ERT_Presentation; + } + else if (compare(sopClass, UID_TwelveLeadECGWaveformStorage) || + compare(sopClass, UID_GeneralECGWaveformStorage) || + compare(sopClass, UID_AmbulatoryECGWaveformStorage) || + compare(sopClass, UID_HemodynamicWaveformStorage) || + compare(sopClass, UID_CardiacElectrophysiologyWaveformStorage) || + compare(sopClass, UID_BasicVoiceAudioWaveformStorage) || + compare(sopClass, UID_GeneralAudioWaveformStorage) || + compare(sopClass, UID_ArterialPulseWaveformStorage) || + compare(sopClass, UID_RespiratoryWaveformStorage)) + { + result = ERT_Waveform; + } + else if (compare(sopClass, UID_RTDoseStorage)) + result = ERT_RTDose; + else if (compare(sopClass, UID_RTStructureSetStorage)) + result = ERT_RTStructureSet; + else if (compare(sopClass, UID_RTPlanStorage) || + compare(sopClass, UID_RTIonPlanStorage)) + { + result = ERT_RTPlan; + } + else if (compare(sopClass, UID_RTBeamsTreatmentRecordStorage) || + compare(sopClass, UID_RTBrachyTreatmentRecordStorage) || + compare(sopClass, UID_RTTreatmentSummaryRecordStorage) || + compare(sopClass, UID_RTIonBeamsTreatmentRecordStorage)) + { + result = ERT_RTTreatRecord; + } + else if (compare(sopClass, UID_RETIRED_StoredPrintStorage)) + result = ERT_StoredPrint; + else if (compare(sopClass, UID_KeyObjectSelectionDocumentStorage)) + result = ERT_KeyObjectDoc; + else if (compare(sopClass, UID_SpatialRegistrationStorage) || + compare(sopClass, UID_DeformableSpatialRegistrationStorage)) + { + result = ERT_Registration; + } + else if (compare(sopClass, UID_SpatialFiducialsStorage)) + result = ERT_Fiducial; + else if (compare(sopClass, UID_RawDataStorage)) + result = ERT_RawData; + else if (compare(sopClass, UID_MRSpectroscopyStorage)) + result = ERT_Spectroscopy; + else if (compare(sopClass, UID_EncapsulatedPDFStorage) || + compare(sopClass, UID_EncapsulatedCDAStorage)) + { + result = ERT_EncapDoc; + } + else if (compare(sopClass, UID_RealWorldValueMappingStorage)) + result = ERT_ValueMap; + else if (compare(sopClass, UID_HangingProtocolStorage)) + result = ERT_HangingProtocol; + else if (compare(sopClass, UID_StereometricRelationshipStorage)) + result = ERT_Stereometric; + else if (compare(sopClass, UID_ColorPaletteStorage)) + result = ERT_Palette; + else if (compare(sopClass, UID_SurfaceSegmentationStorage)) + result = ERT_Surface; + else if (compare(sopClass, UID_LensometryMeasurementsStorage) || + compare(sopClass, UID_AutorefractionMeasurementsStorage) || + compare(sopClass, UID_KeratometryMeasurementsStorage) || + compare(sopClass, UID_SubjectiveRefractionMeasurementsStorage) || + compare(sopClass, UID_VisualAcuityMeasurementsStorage) || + compare(sopClass, UID_OphthalmicAxialMeasurementsStorage) || + compare(sopClass, UID_IntraocularLensCalculationsStorage) || + compare(sopClass, UID_OphthalmicVisualFieldStaticPerimetryMeasurementsStorage)) + { + result = ERT_Measurement; + } + else if (compare(sopClass, UID_GenericImplantTemplateStorage)) + result = ERT_Implant; + else if (compare(sopClass, UID_ImplantTemplateGroupStorage)) + result = ERT_ImplantGroup; + else if (compare(sopClass, UID_ImplantAssemblyTemplateStorage)) + result = ERT_ImplantAssy; + else if (compare(sopClass, UID_RTBeamsDeliveryInstructionStorage)) + result = ERT_Plan; + else if (compare(sopClass, UID_SurfaceScanMeshStorage) || + compare(sopClass, UID_SurfaceScanPointCloudStorage)) + { + result = ERT_SurfaceScan; + } + return result; +} + + +// get unique key for the given record type +static DcmTagKey getRecordUniqueKey(const E_DirRecType recordType) +{ + /* default for all other record types */ + DcmTagKey result = DCM_ReferencedSOPInstanceUIDInFile; + /* special cases: patient, study, series */ + if (recordType == ERT_Patient) + result = DCM_PatientID; + else if (recordType == ERT_Study) + result = DCM_StudyInstanceUID; + else if (recordType == ERT_Series) + result = DCM_SeriesInstanceUID; + return result; +} + + +// copy content items which modify the concept name of the document root +static void addConceptModContentItems(DcmDirectoryRecord *record, + DcmItem *dataset) +{ + /* Content Sequence, type 1C (see DICOM part 3) + "Contains the Target Content Items that modify the Concept Name + Code Sequence of the root Content Item (Document Title). + Required if the root Content Item is the Source Content Item of + HAS CONCEPT MOD relationships." + */ + if ((record != NULL) && (dataset != NULL)) + { + OFString tmpString; + signed long i = 0; + DcmItem *ditem = NULL; + /* create new ContentSequence */ + DcmSequenceOfItems *newSeq = new DcmSequenceOfItems(DCM_ContentSequence); + if (newSeq != NULL) + { + do { + /* get sequence item (not very efficient, but it works) */ + if (dataset->findAndGetSequenceItem(DCM_ContentSequence, ditem, i++).good()) + { + /* check RelationshipType */ + if (ditem->findAndGetOFString(DCM_RelationshipType, tmpString).good() && + (tmpString.compare("HAS CONCEPT MOD") == 0)) + { + /* copy content item */ + DcmItem *newItem = new DcmItem(*ditem); + if (newItem != NULL) + { + if (newSeq->append(newItem).bad()) + delete newItem; + } + } + } + } while (ditem != NULL); + /* try to insert content sequence into record (if not empty) */ + if ((newSeq->card() == 0) || (record->insert(newSeq, OFTrue /*replaceOld*/).bad())) + delete newSeq; + } + } +} + + +// copy relevant attributes from the blending sequence +static void addBlendingSequence(DcmDirectoryRecord *record, + DcmItem *dataset) +{ + if ((record != NULL) && (dataset != NULL)) + { + /* make sure that the sequence is really present in the original dataset */ + if (dataset->tagExistsWithValue(DCM_BlendingSequence)) + { + signed long i = 0; + DcmItem *ditem = NULL; + /* create new BlendingSequence */ + DcmSequenceOfItems *newSeq = new DcmSequenceOfItems(DCM_BlendingSequence); + if (newSeq != NULL) + { + do { + /* get sequence item (not very efficient, but it works) */ + if (dataset->findAndGetSequenceItem(DCM_BlendingSequence, ditem, i++).good()) + { + DcmItem *newItem = new DcmItem(); + if (newItem != NULL) + { + if (newSeq->append(newItem).good()) + { + ditem->findAndInsertCopyOfElement(DCM_StudyInstanceUID, newItem); + ditem->findAndInsertCopyOfElement(DCM_ReferencedSeriesSequence, newItem); + } else + delete newItem; + } + } + } while ((ditem != NULL) && (i <= 2)); // terminate after two items + /* try to insert blending sequence into record (if not empty) */ + if ((newSeq->card() == 0) || (record->insert(newSeq, OFTrue /*replaceOld*/).bad())) + delete newSeq; + } + } + } +} + + +// insert child record into the parent's list based on the numeric value of the criterionKey +static OFCondition insertWithISCriterion(DcmDirectoryRecord *parent, + DcmDirectoryRecord *child, + const DcmTagKey &criterionKey) +{ + OFCondition result = EC_IllegalParameter; + /* check parameters first */ + if ((parent != NULL) && (child != NULL)) + { + OFBool found = OFFalse; + Sint32 childNumber = 0; + Sint32 parentNumber = 0; + /* retrieve numeric value */ + result = child->findAndGetSint32(criterionKey, childNumber); + /* if available search for proper position */ + if (result.good()) + { + DcmDirectoryRecord *record = NULL; + /* iterate over all records in the parent list */ + while (!found && ((record = parent->nextSub(record)) != NULL)) + { + /* check for proper position */ + if (record->findAndGetSint32(criterionKey, parentNumber).good() && (parentNumber > childNumber)) + found = OFTrue; + } + } + /* insert child record at determined position */ + if (found) + result = parent->insertSubAtCurrentPos(child, OFTrue /*before*/); + else /* or append at the end of the list */ + result = parent->insertSub(child); + } + return result; +} + + +// insert child record sorted under the parent record +static OFCondition insertSortedUnder(DcmDirectoryRecord *parent, + DcmDirectoryRecord *child) +{ + OFCondition result = EC_IllegalParameter; + /* check parameters first */ + if ((parent != NULL) && (child != NULL)) + { + switch (child->getRecordType()) + { + case ERT_Image: + /* try to insert based on Image/InstanceNumber */ + result = insertWithISCriterion(parent, child, DCM_InstanceNumber); + break; + case ERT_Overlay: + /* try to insert based on OverlayNumber */ + result = insertWithISCriterion(parent, child, DCM_RETIRED_OverlayNumber); + break; + case ERT_Curve: + /* try to insert based on CurveNumber */ + result = insertWithISCriterion(parent, child, DCM_RETIRED_CurveNumber); + break; + case ERT_ModalityLut: + case ERT_VoiLut: + /* try to insert based on LUTNumber */ + result = insertWithISCriterion(parent, child, DCM_RETIRED_LUTNumber); + break; + case ERT_SRDocument: + case ERT_Presentation: + case ERT_Waveform: + case ERT_RTDose: + case ERT_RTStructureSet: + case ERT_RTPlan: + case ERT_RTTreatRecord: + case ERT_StoredPrint: + case ERT_KeyObjectDoc: + case ERT_Registration: + case ERT_Fiducial: + case ERT_RawData: + case ERT_Spectroscopy: + case ERT_EncapDoc: + case ERT_ValueMap: + case ERT_Surface: + case ERT_Measurement: + case ERT_SurfaceScan: + /* try to insert based on InstanceNumber */ + result = insertWithISCriterion(parent, child, DCM_InstanceNumber); + break; + case ERT_Series: + /* try to insert based on SeriesNumber */ + result = insertWithISCriterion(parent, child, DCM_SeriesNumber); + break; + case ERT_Stereometric: + case ERT_Plan: + /* no InstanceNumber or the like */ + default: + /* append */ + result = parent->insertSub(child); + break; + } + } + return result; +} + + +// create alternative study date if absent in dataset +static OFString &alternativeStudyDate(DcmItem *dataset, + OFString &result) +{ + if (dataset != NULL) + { + /* use another date if present */ + if (dataset->findAndGetOFStringArray(DCM_SeriesDate, result).bad() || result.empty()) + { + if (dataset->findAndGetOFStringArray(DCM_AcquisitionDate, result).bad() || result.empty()) + { + if (dataset->findAndGetOFStringArray(DCM_ContentDate, result).bad() || result.empty()) + { + /* use current date, "19000101" in case of error */ + DcmDate::getCurrentDate(result); + } + } + } + } else + result.clear(); + return result; +} + + +// create alternative study time if absent in dataset +static OFString &alternativeStudyTime(DcmItem *dataset, + OFString &result) +{ + if (dataset != NULL) + { + /* use another time if present */ + if (dataset->findAndGetOFStringArray(DCM_SeriesTime, result).bad() || result.empty()) + { + if (dataset->findAndGetOFStringArray(DCM_AcquisitionTime, result).bad() || result.empty()) + { + if (dataset->findAndGetOFStringArray(DCM_ContentTime, result).bad() || result.empty()) + { + /* use current time, "0000" in case of error */ + DcmTime::getCurrentTime(result); + } + } + } + } else + result.clear(); + return result; +} + + +// check whether given SOP Class UID belongs to a multi-frame composite IOD +// (not sure whether all these IODs should really be treated as "movies"?) +static OFBool isMultiframeStorageSOPClass(const OFString &sopClassUID) +{ + return compare(sopClassUID, UID_BreastProjectionXRayImageStorageForPresentation) || + compare(sopClassUID, UID_BreastProjectionXRayImageStorageForProcessing) || + compare(sopClassUID, UID_BreastTomosynthesisImageStorage) || + compare(sopClassUID, UID_EnhancedCTImageStorage) || + compare(sopClassUID, UID_EnhancedMRColorImageStorage) || + compare(sopClassUID, UID_EnhancedMRImageStorage) || + compare(sopClassUID, UID_EnhancedPETImageStorage) || + compare(sopClassUID, UID_EnhancedUSVolumeStorage) || + compare(sopClassUID, UID_EnhancedXAImageStorage) || + compare(sopClassUID, UID_EnhancedXRFImageStorage) || + compare(sopClassUID, UID_IntravascularOpticalCoherenceTomographyImageStorageForPresentation) || + compare(sopClassUID, UID_IntravascularOpticalCoherenceTomographyImageStorageForProcessing) || + compare(sopClassUID, UID_MultiframeGrayscaleByteSecondaryCaptureImageStorage) || + compare(sopClassUID, UID_MultiframeGrayscaleWordSecondaryCaptureImageStorage) || + compare(sopClassUID, UID_MultiframeSingleBitSecondaryCaptureImageStorage) || + compare(sopClassUID, UID_MultiframeTrueColorSecondaryCaptureImageStorage) || + compare(sopClassUID, UID_NuclearMedicineImageStorage) || + compare(sopClassUID, UID_OphthalmicPhotography16BitImageStorage) || + compare(sopClassUID, UID_OphthalmicPhotography8BitImageStorage) || + compare(sopClassUID, UID_OphthalmicTomographyImageStorage) || + compare(sopClassUID, UID_ParametricMapStorage) || + compare(sopClassUID, UID_RTDoseStorage) || + compare(sopClassUID, UID_RTImageStorage) || + compare(sopClassUID, UID_UltrasoundMultiframeImageStorage) || + compare(sopClassUID, UID_VideoEndoscopicImageStorage) || + compare(sopClassUID, UID_VideoMicroscopicImageStorage) || + compare(sopClassUID, UID_VideoPhotographicImageStorage) || +// in fact, the following IOD is a multi-frame image but the individual frames are rather "tiles" +// compare(sopClassUID, UID_VLWholeSlideMicroscopyImageStorage) || + compare(sopClassUID, UID_WideFieldOphthalmicPhotographyStereographicProjectionImageStorage) || + compare(sopClassUID, UID_WideFieldOphthalmicPhotography3DCoordinatesImageStorage) || + compare(sopClassUID, UID_XRay3DAngiographicImageStorage) || + compare(sopClassUID, UID_XRay3DCraniofacialImageStorage) || + compare(sopClassUID, UID_XRayAngiographicImageStorage) || + compare(sopClassUID, UID_XRayRadiofluoroscopicImageStorage); +} + + +/*------------------* + * implementation * + *------------------*/ + +// constructor +DicomDirInterface::DicomDirInterface() + : DicomDir(NULL), + ImagePlugin(NULL), + ApplicationProfile(AP_Default), + BackupMode(OFTrue), + AbortMode(OFFalse), + MapFilenamesMode(OFFalse), + InventMode(OFFalse), + InventPatientIDMode(OFFalse), + RetiredSOPClassSupport(OFFalse), + EncodingCheck(OFTrue), + ResolutionCheck(OFTrue), + TransferSyntaxCheck(OFTrue), + FileFormatCheck(OFTrue), + ConsistencyCheck(OFTrue), + IconImageMode(OFFalse), + FilesetUpdateMode(OFFalse), + BackupFilename(), + BackupCreated(OFFalse), + IconSize(64), + IconPrefix(), + DefaultIcon(), + RLESupport(OFFalse), + JPEGSupport(OFFalse), + JP2KSupport(OFFalse), + AutoPatientNumber(0), + AutoStudyNumber(0), + AutoSeriesNumber(0), + AutoInstanceNumber(1), + AutoOverlayNumber(1), + AutoLutNumber(1), + AutoCurveNumber(1) +{ + /* check whether (possibly required) RLE/JPEG/JP2K decoders are registered */ + RLESupport = DcmCodecList::canChangeCoding(EXS_RLELossless, EXS_LittleEndianExplicit); + JPEGSupport = DcmCodecList::canChangeCoding(EXS_JPEGProcess1, EXS_LittleEndianExplicit) && + DcmCodecList::canChangeCoding(EXS_JPEGProcess14SV1, EXS_LittleEndianExplicit); + JP2KSupport = DcmCodecList::canChangeCoding(EXS_JPEG2000LosslessOnly, EXS_LittleEndianExplicit) && + DcmCodecList::canChangeCoding(EXS_JPEG2000, EXS_LittleEndianExplicit); +} + + +// destructor +DicomDirInterface::~DicomDirInterface() +{ + /* reset object to its initial state (free memory) */ + cleanup(); +} + + +// cleanup the object, i.e. free all memory +void DicomDirInterface::cleanup() +{ + /* free all allocated memory */ + delete DicomDir; + /* invalidate references */ + DicomDir = NULL; +} + + +// check whether the current DICOMDIR object is valid +OFBool DicomDirInterface::isDicomDirValid() const +{ + /* tbd: might add more sophisticated checks later on, e.g. some application + * profiles do not not allow for DICOMDIRs with no directory information. + */ + return (DicomDir != NULL); +} + + +// create a backup of the specified file +void DicomDirInterface::createDicomDirBackup(const OFFilename &filename) +{ + /* check whether DICOMDIR already exists */ + if (OFStandard::fileExists(filename)) + { + /* rename existing DICOMDIR */ + OFStandard::appendFilenameExtension(BackupFilename, filename, FNAME_BACKUP_EXTENSION); + /* delete old backup file (if any) */ + deleteDicomDirBackup(); + DCMDATA_INFO("creating DICOMDIR backup: " << BackupFilename); + /* create backup file */ + if (copyFile(filename, BackupFilename)) + BackupCreated = OFTrue; + else + DCMDATA_ERROR("cannot create backup of: " << filename); + } +} + + +// delete backup file if one has been created +void DicomDirInterface::deleteDicomDirBackup() +{ + /* if a backup of the DICOMDIR exists */ + if (OFStandard::fileExists(BackupFilename)) + { + if (BackupCreated) + DCMDATA_INFO("deleting DICOMDIR backup: " << BackupFilename); + else + DCMDATA_INFO("deleting old DICOMDIR backup: " << BackupFilename); + /* delete the backup file */ + OFStandard::deleteFile(BackupFilename); + } + /* reset status variable */ + BackupCreated = OFFalse; +} + + +// create a new DICOMDIR object, i.e. replace any previously existing 'filename' +OFCondition DicomDirInterface::createNewDicomDir(const E_ApplicationProfile profile, + const OFFilename &filename, + const OFString &filesetID) +{ + OFCondition result = EC_IllegalParameter; + if (!filename.isEmpty() && checkFilesetID(filesetID)) + { + FilesetUpdateMode = OFFalse; + /* first remove any existing DICOMDIR from memory */ + cleanup(); + /* then create a backup if a DICOMDIR file already exists */ + if (OFStandard::fileExists(filename)) + { + if (BackupMode) + createDicomDirBackup(filename); + /* and delete it because otherwise DcmDicomDir will parse it + and try to append to existing records */ + OFStandard::deleteFile(filename); + } + /* select new application profile */ + result = selectApplicationProfile(profile); + if (result.good()) + { + DCMDATA_INFO("creating DICOMDIR file using " << getProfileName(ApplicationProfile) + << " profile: " << filename); + /* finally, create a new DICOMDIR object */ + DicomDir = new DcmDicomDir(filename, filesetID.c_str()); + if (DicomDir != NULL) + result = DicomDir->error(); + else + result = EC_MemoryExhausted; + } + } + return result; +} + + +// create a DICOMDIR based on an existing one, i.e. append the new entries +OFCondition DicomDirInterface::appendToDicomDir(const E_ApplicationProfile profile, + const OFFilename &filename) +{ + OFCondition result = EC_IllegalParameter; + if (!filename.isEmpty()) + { + FilesetUpdateMode = OFFalse; + /* first remove any existing DICOMDIR from memory */ + cleanup(); + /* then check whether DICOMDIR file already exists */ + if (OFStandard::fileExists(filename)) + { + /* then create a backup if required */ + if (BackupMode) + createDicomDirBackup(filename); + /* select new application profile */ + result = selectApplicationProfile(profile); + if (result.good()) + { + DCMDATA_INFO("appending to DICOMDIR file using " << getProfileName(ApplicationProfile) + << " profile: " << filename); + /* finally, create a DICOMDIR object based on the existing file */ + DicomDir = new DcmDicomDir(filename); + if (DicomDir != NULL) + result = DicomDir->error(); + else + result = EC_MemoryExhausted; + } + } else { + /* create error message "No such file or directory" from error code */ + char buffer[255]; + const char *text = OFStandard::strerror(ENOENT, buffer, 255); + if ((text == NULL) || (text[0] == '\0')) + text = "(unknown error code)"; + /* error code 18 is reserved for file read error messages (see dcerror.cc) */ + result = makeOFCondition(OFM_dcmdata, 18, OF_error, text); + /* report an error */ + DCMDATA_ERROR(result.text() << ": cannot append to file: " << filename); + } + } + return result; +} + + +// create a DICOMDIR based on an existing one, i.e. append new and update existing entries +OFCondition DicomDirInterface::updateDicomDir(const E_ApplicationProfile profile, + const OFFilename &filename) +{ + OFCondition result = EC_IllegalParameter; + if (!filename.isEmpty()) + { + FilesetUpdateMode = OFTrue; + /* first remove any existing DICOMDIR from memory */ + cleanup(); + /* then check whether DICOMDIR file already exists */ + if (OFStandard::fileExists(filename)) + { + /* then create a backup if required */ + if (BackupMode) + createDicomDirBackup(filename); + /* select new application profile */ + result = selectApplicationProfile(profile); + if (result.good()) + { + DCMDATA_INFO("updating DICOMDIR file using " << getProfileName(ApplicationProfile) + << " profile: " << filename); + /* finally, create a DICOMDIR object based on the existing file */ + DicomDir = new DcmDicomDir(filename); + if (DicomDir != NULL) + result = DicomDir->error(); + else + result = EC_MemoryExhausted; + } + } else { + /* create error message "No such file or directory" from error code */ + char buffer[255]; + const char *text = OFStandard::strerror(ENOENT, buffer, 255); + if ((text == NULL) || (text[0] == '\0')) + text = "(unknown error code)"; + /* error code 18 is reserved for file read error messages (see dcerror.cc) */ + result = makeOFCondition(OFM_dcmdata, 18, OF_error, text); + /* report an error */ + DCMDATA_ERROR(result.text() << ": cannot update file: " << filename); + } + } + return result; +} + + +// write the current DICOMDIR object to file +OFCondition DicomDirInterface::writeDicomDir(const E_EncodingType encodingType, + const E_GrpLenEncoding groupLength) +{ + OFCondition result = EC_InvalidDICOMDIR; + /* check whether DICOMDIR object is valid */ + if (isDicomDirValid()) + { + DCMDATA_INFO("writing file: " << DicomDir->getDirFileName()); + /* write DICOMDIR as Little Endian Explicit as required by the standard */ + result = DicomDir->write(DICOMDIR_DEFAULT_TRANSFERSYNTAX, encodingType, groupLength); + /* delete backup copy in case the new file could be written without any errors */ + if (result.good()) + deleteDicomDirBackup(); + else { + /* report an error */ + DCMDATA_ERROR(result.text() << ": writing file: " << DicomDir->getDirFileName()); + } + } + return result; +} + + +// check whether the specified filename conforms to the DICOM standard requirements +OFBool DicomDirInterface::isFilenameValid(const OFFilename &filename, + const OFBool allowEmpty) +{ + OFBool result = OFTrue; + /* get 8-bit version of the stored string */ + const char *fname = filename.getCharPointer(); + /* check for empty filename */ + if ((fname == NULL) || (fname[0] == '\0')) + { + if (!allowEmpty) + { + DCMDATA_ERROR(" not allowed as filename"); + result = OFFalse; + } + } else { + size_t invalidChar = 0; + /* check whether the file name path is ok and in local format */ + if ((fname[0] == PATH_SEPARATOR) /* absolute path? */ || + locateInvalidFilenameChars(fname, invalidChar, MapFilenamesMode)) + { + DCMDATA_ERROR("invalid character(s) in filename: " << fname << OFendl + << OFString(34 /*message*/ + invalidChar, ' ') << "^"); + result = OFFalse; + } + /* ensure that the maximum number of components is not being exceeded */ + if (componentCount(fname) > MAX_FNAME_COMPONENTS) + { + DCMDATA_ERROR("too many path components (max " << MAX_FNAME_COMPONENTS + << ") in filename: " << fname); + result = OFFalse; + } + /* ensure that each component is not too large */ + if (isComponentTooLarge(fname, MAX_FNAME_COMPONENT_SIZE, MapFilenamesMode)) + { + /* create error message */ + DCMDATA_ERROR("component too large (max " << MAX_FNAME_COMPONENT_SIZE + << " characters) in filename: " << fname); + result = OFFalse; + } + } + return result; +} + + +// check whether the specified character set is defined in the DICOM standard +OFBool DicomDirInterface::isCharsetValid(const char *charset) +{ + OFBool result = OFTrue; + /* empty charset is also valid */ + if ((charset != NULL) && (charset[0] != '\0')) + { + /* check for valid charset */ + result = (strcmp(charset, "ISO_IR 100") == 0) || + (strcmp(charset, "ISO_IR 101") == 0) || + (strcmp(charset, "ISO_IR 109") == 0) || + (strcmp(charset, "ISO_IR 110") == 0) || + (strcmp(charset, "ISO_IR 144") == 0) || + (strcmp(charset, "ISO_IR 127") == 0) || + (strcmp(charset, "ISO_IR 126") == 0) || + (strcmp(charset, "ISO_IR 138") == 0) || + (strcmp(charset, "ISO_IR 148") == 0) || + (strcmp(charset, "ISO_IR 166") == 0) || + (strcmp(charset, "ISO_IR 13") == 0) || + (strcmp(charset, "ISO_IR 192") == 0); + if (!result) + DCMDATA_ERROR("unknown character set for file-set descriptor: " << charset); + } + return result; +} + + +// check the given file (dataset) regarding SOP class and transfer syntax +OFCondition DicomDirInterface::checkSOPClassAndXfer(DcmMetaInfo *metainfo, + DcmItem *dataset, + const OFFilename &filename) +{ + OFCondition result = EC_IllegalParameter; + if ((metainfo != NULL) && (dataset != NULL) && !filename.isEmpty()) + { + /* is sop class ok? */ + OFString mediaSOPClassUID; + if (metainfo->findAndGetOFStringArray(DCM_MediaStorageSOPClassUID, mediaSOPClassUID).bad()) + { + DCMDATA_ERROR("MediaStorageSOPClassUID missing in file meta information: " << filename); + result = EC_TagNotFound; + } else { + /* check if the SOP Class is a known storage SOP class (an image, overlay, curve, etc.) */ + OFBool found = OFFalse; + OFString expectedTransferSyntax = UID_LittleEndianExplicitTransferSyntax; + switch (ApplicationProfile) + { + case AP_MPEG2MPatMLDVD: + expectedTransferSyntax = UID_MPEG2MainProfileAtMainLevelTransferSyntax; + /* multi-frame composite IODs only! */ + found = isMultiframeStorageSOPClass(mediaSOPClassUID); + break; + case AP_BasicCardiac: + if (compare(mediaSOPClassUID, UID_XRayAngiographicImageStorage)) + { + expectedTransferSyntax = UID_JPEGProcess14SV1TransferSyntax; + found = OFTrue; + } + else if (RetiredSOPClassSupport) + { + /* the following SOP class has been retired with DICOM 2006: */ + found = compare(mediaSOPClassUID, UID_RETIRED_DetachedPatientManagementSOPClass); + } + break; + case AP_XrayAngiographic: + case AP_XrayAngiographicDVD: + if (compare(mediaSOPClassUID, UID_XRayAngiographicImageStorage)) + { + /* JPEG lossy compression only allowed for DVD media (checked later) */ + if (ApplicationProfile == AP_XrayAngiographic) + expectedTransferSyntax = UID_JPEGProcess14SV1TransferSyntax; + found = OFTrue; + } else { + found = compare(mediaSOPClassUID, UID_SecondaryCaptureImageStorage) || + compare(mediaSOPClassUID, UID_GrayscaleSoftcopyPresentationStateStorage); + if (!found && RetiredSOPClassSupport) + { + /* the following SOP classes have been retired with DICOM 2004: */ + found = compare(mediaSOPClassUID, UID_RETIRED_StandaloneOverlayStorage) || + compare(mediaSOPClassUID, UID_RETIRED_StandaloneCurveStorage) || + compare(mediaSOPClassUID, UID_RETIRED_DetachedPatientManagementSOPClass); + } + } + break; + case AP_DentalRadiograph: + found = compare(mediaSOPClassUID, UID_DigitalIntraOralXRayImageStorageForPresentation) || + compare(mediaSOPClassUID, UID_DigitalXRayImageStorageForPresentation) || + compare(mediaSOPClassUID, UID_BasicStructuredDisplayStorage) || + compare(mediaSOPClassUID, UID_GrayscaleSoftcopyPresentationStateStorage); + break; + case AP_CTandMR: + /* transfer syntax needs to be checked later */ + found = compare(mediaSOPClassUID, UID_CTImageStorage) || + compare(mediaSOPClassUID, UID_MRImageStorage) || + compare(mediaSOPClassUID, UID_SecondaryCaptureImageStorage) || + /* the following SOP classes have been added with CP-1182 */ + compare(mediaSOPClassUID, UID_GrayscaleSoftcopyPresentationStateStorage) || + compare(mediaSOPClassUID, UID_XRayRadiationDoseSRStorage); + if (!found && RetiredSOPClassSupport) + { + /* the following SOP class has been retired with DICOM 2004: */ + found = compare(mediaSOPClassUID, UID_RETIRED_DetachedPatientManagementSOPClass); + } + break; + case AP_UltrasoundIDSF: + case AP_UltrasoundSCSF: + case AP_UltrasoundCCSF: + /* transfer syntax needs to be checked later */ + found = compare(mediaSOPClassUID, UID_UltrasoundImageStorage); + break; + case AP_UltrasoundIDMF: + case AP_UltrasoundSCMF: + case AP_UltrasoundCCMF: + /* transfer syntax needs to be checked later */ + found = compare(mediaSOPClassUID, UID_UltrasoundImageStorage) || + compare(mediaSOPClassUID, UID_UltrasoundMultiframeImageStorage); + break; + case AP_TwelveLeadECG: + found = compare(mediaSOPClassUID, UID_TwelveLeadECGWaveformStorage); + break; + case AP_HemodynamicWaveform: + found = compare(mediaSOPClassUID, UID_HemodynamicWaveformStorage); + break; + case AP_GeneralPurpose: + case AP_GeneralPurposeDVDJPEG: + case AP_GeneralPurposeDVDJPEG2000: + case AP_GeneralPurposeBDJPEG: + case AP_GeneralPurposeBDJPEG2000: + case AP_GeneralPurposeBDMPEG2MPatML: + case AP_GeneralPurposeBDMPEG2MPatHL: + case AP_GeneralPurposeBDMPEG4HPatLV41: + case AP_GeneralPurposeBDMPEG4HPatLV41BD: + case AP_USBandFlashJPEG: + case AP_USBandFlashJPEG2000: + case AP_GeneralPurposeMIME: + default: + { + /* specify expected transfer syntax for the BD profiles (multi-frame IODs only) */ + if (ApplicationProfile == AP_GeneralPurposeBDMPEG2MPatML) + expectedTransferSyntax = UID_MPEG2MainProfileAtMainLevelTransferSyntax; + else if (ApplicationProfile == AP_GeneralPurposeBDMPEG2MPatHL) + expectedTransferSyntax = UID_MPEG2MainProfileAtHighLevelTransferSyntax; + else if (ApplicationProfile == AP_GeneralPurposeBDMPEG4HPatLV41) + expectedTransferSyntax = UID_MPEG4HighProfileLevel4_1TransferSyntax; + else if (ApplicationProfile == AP_GeneralPurposeBDMPEG4HPatLV41BD) + expectedTransferSyntax = UID_MPEG4BDcompatibleHighProfileLevel4_1TransferSyntax; + /* is it an image ? */ + for (int i = 0; i < numberOfDcmImageSOPClassUIDs && !found; i++) + found = compare(mediaSOPClassUID, dcmImageSOPClassUIDs[i]); + /* is it one of the RT SOP Classes? */ + if (!found) + { + found = compare(mediaSOPClassUID, UID_RTDoseStorage) || + compare(mediaSOPClassUID, UID_RTStructureSetStorage) || + compare(mediaSOPClassUID, UID_RTBeamsTreatmentRecordStorage) || + compare(mediaSOPClassUID, UID_RTPlanStorage) || + compare(mediaSOPClassUID, UID_RTBrachyTreatmentRecordStorage) || + compare(mediaSOPClassUID, UID_RTTreatmentSummaryRecordStorage) || + compare(mediaSOPClassUID, UID_RTIonPlanStorage) || + compare(mediaSOPClassUID, UID_RTIonBeamsTreatmentRecordStorage); + } + /* is it one of the structured reporting SOP Classes? */ + if (!found) + { + found = compare(mediaSOPClassUID, UID_BasicTextSRStorage) || + compare(mediaSOPClassUID, UID_EnhancedSRStorage) || + compare(mediaSOPClassUID, UID_ComprehensiveSRStorage) || + compare(mediaSOPClassUID, UID_Comprehensive3DSRStorage) || + compare(mediaSOPClassUID, UID_ExtensibleSRStorage) || + compare(mediaSOPClassUID, UID_ProcedureLogStorage) || + compare(mediaSOPClassUID, UID_MammographyCADSRStorage) || + compare(mediaSOPClassUID, UID_ChestCADSRStorage) || + compare(mediaSOPClassUID, UID_ColonCADSRStorage) || + compare(mediaSOPClassUID, UID_XRayRadiationDoseSRStorage) || + compare(mediaSOPClassUID, UID_RadiopharmaceuticalRadiationDoseSRStorage) || + compare(mediaSOPClassUID, UID_SpectaclePrescriptionReportStorage) || + compare(mediaSOPClassUID, UID_MacularGridThicknessAndVolumeReportStorage) || + compare(mediaSOPClassUID, UID_ImplantationPlanSRDocumentStorage); + } + /* is it one of the waveform SOP Classes? */ + if (!found) + { + found = compare(mediaSOPClassUID, UID_TwelveLeadECGWaveformStorage) || + compare(mediaSOPClassUID, UID_GeneralECGWaveformStorage) || + compare(mediaSOPClassUID, UID_AmbulatoryECGWaveformStorage) || + compare(mediaSOPClassUID, UID_HemodynamicWaveformStorage) || + compare(mediaSOPClassUID, UID_CardiacElectrophysiologyWaveformStorage) || + compare(mediaSOPClassUID, UID_BasicVoiceAudioWaveformStorage) || + compare(mediaSOPClassUID, UID_GeneralAudioWaveformStorage) || + compare(mediaSOPClassUID, UID_ArterialPulseWaveformStorage) || + compare(mediaSOPClassUID, UID_RespiratoryWaveformStorage); + } + /* is it one of the presentation state SOP Classes? */ + if (!found) + { + found = compare(mediaSOPClassUID, UID_GrayscaleSoftcopyPresentationStateStorage) || + compare(mediaSOPClassUID, UID_ColorSoftcopyPresentationStateStorage) || + compare(mediaSOPClassUID, UID_PseudoColorSoftcopyPresentationStateStorage) || + compare(mediaSOPClassUID, UID_BlendingSoftcopyPresentationStateStorage) || + compare(mediaSOPClassUID, UID_XAXRFGrayscaleSoftcopyPresentationStateStorage) || + compare(mediaSOPClassUID, UID_GrayscalePlanarMPRVolumetricPresentationStateStorage) || + compare(mediaSOPClassUID, UID_CompositingPlanarMPRVolumetricPresentationStateStorage) || + compare(mediaSOPClassUID, UID_BasicStructuredDisplayStorage); + } + /* is it one of the encapsulated document SOP Classes? */ + if (!found) + { + found = compare(mediaSOPClassUID, UID_EncapsulatedPDFStorage) || + compare(mediaSOPClassUID, UID_EncapsulatedCDAStorage); + } + /* is it one of the spatial registration SOP Classes? */ + if (!found) + { + found = compare(mediaSOPClassUID, UID_SpatialRegistrationStorage) || + compare(mediaSOPClassUID, UID_SpatialFiducialsStorage) || + compare(mediaSOPClassUID, UID_DeformableSpatialRegistrationStorage); + } + /* is it one of the segmentation SOP Classes? */ + if (!found) + { + found = compare(mediaSOPClassUID, UID_SegmentationStorage) || // will be mapped to IMAGE record + compare(mediaSOPClassUID, UID_SurfaceSegmentationStorage); + } + /* is it one of the measurement SOP Classes? */ + if (!found) + { + found = compare(mediaSOPClassUID, UID_LensometryMeasurementsStorage) || + compare(mediaSOPClassUID, UID_AutorefractionMeasurementsStorage) || + compare(mediaSOPClassUID, UID_KeratometryMeasurementsStorage) || + compare(mediaSOPClassUID, UID_SubjectiveRefractionMeasurementsStorage) || + compare(mediaSOPClassUID, UID_VisualAcuityMeasurementsStorage) || + compare(mediaSOPClassUID, UID_OphthalmicAxialMeasurementsStorage) || + compare(mediaSOPClassUID, UID_IntraocularLensCalculationsStorage) || + compare(mediaSOPClassUID, UID_OphthalmicVisualFieldStaticPerimetryMeasurementsStorage); + } + /* is it one of the implant SOP Classes? */ + if (!found) + { + found = compare(mediaSOPClassUID, UID_GenericImplantTemplateStorage) || + compare(mediaSOPClassUID, UID_ImplantAssemblyTemplateStorage) || + compare(mediaSOPClassUID, UID_ImplantTemplateGroupStorage); + } + /* is it one of the surface scan SOP Classes? */ + if (!found) + { + found = compare(mediaSOPClassUID, UID_SurfaceScanMeshStorage) || + compare(mediaSOPClassUID, UID_SurfaceScanPointCloudStorage); + } + /* is it any other SOP class? */ + if (!found) + { + found = compare(mediaSOPClassUID, UID_KeyObjectSelectionDocumentStorage) || + compare(mediaSOPClassUID, UID_RawDataStorage) || + compare(mediaSOPClassUID, UID_MRSpectroscopyStorage) || + compare(mediaSOPClassUID, UID_RealWorldValueMappingStorage) || + compare(mediaSOPClassUID, UID_HangingProtocolStorage) || + compare(mediaSOPClassUID, UID_StereometricRelationshipStorage) || + compare(mediaSOPClassUID, UID_ColorPaletteStorage); + } + /* the following SOP classes have been retired with previous editions of the DICOM standard */ + if (!found && RetiredSOPClassSupport) + { + found = compare(mediaSOPClassUID, UID_RETIRED_StoredPrintStorage) || + compare(mediaSOPClassUID, UID_RETIRED_StandaloneOverlayStorage) || + compare(mediaSOPClassUID, UID_RETIRED_StandaloneCurveStorage) || + compare(mediaSOPClassUID, UID_RETIRED_StandaloneModalityLUTStorage) || + compare(mediaSOPClassUID, UID_RETIRED_StandaloneVOILUTStorage) || + compare(mediaSOPClassUID, UID_RETIRED_StandalonePETCurveStorage); + if (!found && (ApplicationProfile == AP_GeneralPurpose)) + { + /* a detached patient mgmt sop class is also ok */ + found = compare(mediaSOPClassUID, UID_RETIRED_DetachedPatientManagementSOPClass); + } + } + } + } + if (found) + result = EC_Normal; + else + { + OFString sopClassName = dcmFindNameOfUID(mediaSOPClassUID.c_str(), ""); + if (sopClassName.empty()) + sopClassName = mediaSOPClassUID; + DCMDATA_ERROR("invalid SOP class (" << sopClassName << ") for " << getProfileName(ApplicationProfile) + << " profile: " << filename); + result = EC_ApplicationProfileViolated; + } + if (result.good()) + { + /* is transfer syntax ok? */ + OFString transferSyntax; + if (metainfo->findAndGetOFStringArray(DCM_TransferSyntaxUID, transferSyntax).bad()) + { + DCMDATA_ERROR("TransferSyntaxUID missing in file meta information: " << filename); + result = EC_TagNotFound; + } + /* is transfer syntax supported */ + if (result.good()) + { + /* RLE compression */ + if (compare(transferSyntax, UID_RLELosslessTransferSyntax)) + { + if (!RLESupport && IconImageMode) + { + DCMDATA_ERROR("RLE compression not supported: " << filename); + result = EC_CannotChangeRepresentation; + } + } + /* JPEG compression */ + if (compare(transferSyntax, UID_JPEGProcess14SV1TransferSyntax) || + compare(transferSyntax, UID_JPEGProcess1TransferSyntax)) + { + if (!JPEGSupport && IconImageMode) + { + DCMDATA_ERROR("JPEG compression not supported: " << filename); + result = EC_CannotChangeRepresentation; + } + } + /* JPEG 2000 compression */ + if (compare(transferSyntax, UID_JPEG2000LosslessOnlyTransferSyntax) || + compare(transferSyntax, UID_JPEG2000TransferSyntax)) + { + if (!JP2KSupport && IconImageMode) + { + DCMDATA_ERROR("JPEG 2000 compression not supported: " << filename); + result = EC_CannotChangeRepresentation; + } + } + } + /* compare expected and actual transfer syntax */ + if (result.good()) + { + const OFString xferName = dcmFindNameOfUID(transferSyntax.c_str(), ""); + switch (ApplicationProfile) + { + case AP_GeneralPurposeMIME: + /* accept all transfer syntaxes */ + break; + case AP_GeneralPurposeDVDJPEG: + case AP_GeneralPurposeBDJPEG: + case AP_USBandFlashJPEG: + /* need to check multiple transfer syntaxes */ + found = compare(transferSyntax, UID_LittleEndianExplicitTransferSyntax) || + compare(transferSyntax, UID_JPEGProcess14SV1TransferSyntax) || + compare(transferSyntax, UID_JPEGProcess1TransferSyntax) || + compare(transferSyntax, UID_JPEGProcess2_4TransferSyntax); + if (!found) + { + const OFString expXferName1 = dcmFindNameOfUID(UID_LittleEndianExplicitTransferSyntax, ""); + const OFString expXferName2 = dcmFindNameOfUID(UID_JPEGProcess14SV1TransferSyntax, ""); + const OFString expXferName3 = dcmFindNameOfUID(UID_JPEGProcess1TransferSyntax, ""); + const OFString expXferName4 = dcmFindNameOfUID(UID_JPEGProcess2_4TransferSyntax, ""); + /* create error message */ + OFOStringStream oss; + oss << expXferName1 << ", " << expXferName2 << ", " << expXferName3 << " or " + << expXferName4 << " expected but " << xferName << " found: " << filename + << OFStringStream_ends; + OFSTRINGSTREAM_GETSTR(oss, tmpString) + if (TransferSyntaxCheck) + { + DCMDATA_ERROR(tmpString); + result = EC_ApplicationProfileViolated; + } else + DCMDATA_WARN(tmpString); + OFSTRINGSTREAM_FREESTR(tmpString) + } + break; + case AP_GeneralPurposeDVDJPEG2000: + case AP_GeneralPurposeBDJPEG2000: + case AP_USBandFlashJPEG2000: + /* need to check multiple transfer syntaxes */ + found = compare(transferSyntax, UID_LittleEndianExplicitTransferSyntax) || + compare(transferSyntax, UID_JPEG2000LosslessOnlyTransferSyntax) || + compare(transferSyntax, UID_JPEG2000TransferSyntax); + if (!found) + { + const OFString expXferName1 = dcmFindNameOfUID(UID_LittleEndianExplicitTransferSyntax, ""); + const OFString expXferName2 = dcmFindNameOfUID(UID_JPEG2000LosslessOnlyTransferSyntax, ""); + const OFString expXferName3 = dcmFindNameOfUID(UID_JPEG2000TransferSyntax, ""); + /* create error message */ + OFOStringStream oss; + oss << expXferName1 << ", " << expXferName2 << " or " << expXferName3 + << " expected but " << xferName << " found: " << filename << OFStringStream_ends; + OFSTRINGSTREAM_GETSTR(oss, tmpString) + if (TransferSyntaxCheck) + { + DCMDATA_ERROR(tmpString); + result = EC_ApplicationProfileViolated; + } else + DCMDATA_WARN(tmpString); + OFSTRINGSTREAM_FREESTR(tmpString) + } + break; + case AP_GeneralPurposeBDMPEG2MPatML: + case AP_GeneralPurposeBDMPEG2MPatHL: + case AP_GeneralPurposeBDMPEG4HPatLV41: + case AP_GeneralPurposeBDMPEG4HPatLV41BD: + /* compare with expected transfer syntax */ + found = compare(transferSyntax, expectedTransferSyntax); + if (found) + { + /* check for multi-frame composite IOD */ + if (!isMultiframeStorageSOPClass(mediaSOPClassUID)) + { + /* create error message */ + OFOStringStream oss; + oss << xferName << " only for multi-frame composite IODs: " << filename + << OFStringStream_ends; + OFSTRINGSTREAM_GETSTR(oss, tmpString) + if (TransferSyntaxCheck) + { + DCMDATA_ERROR(tmpString); + result = EC_ApplicationProfileViolated; + } else + DCMDATA_WARN(tmpString); + OFSTRINGSTREAM_FREESTR(tmpString) + } + } else { + found = compare(transferSyntax, UID_LittleEndianExplicitTransferSyntax); + /* create error message */ + OFOStringStream oss; + /* check for multi-frame composite IOD */ + if (isMultiframeStorageSOPClass(mediaSOPClassUID)) + { + const OFString expXferName1 = dcmFindNameOfUID(UID_LittleEndianExplicitTransferSyntax, ""); + const OFString expXferName2 = dcmFindNameOfUID(expectedTransferSyntax.c_str(), ""); + oss << expXferName1 << " or " << expXferName2 << " expected but " << xferName + << " found: " << filename << OFStringStream_ends; + } else { + const OFString expXferName = dcmFindNameOfUID(UID_LittleEndianExplicitTransferSyntax, ""); + oss << expXferName << " expected but " << xferName << " found: " << filename + << OFStringStream_ends; + } + OFSTRINGSTREAM_GETSTR(oss, tmpString) + if (TransferSyntaxCheck) + { + DCMDATA_ERROR(tmpString); + result = EC_ApplicationProfileViolated; + } else + DCMDATA_WARN(tmpString); + OFSTRINGSTREAM_FREESTR(tmpString) + } + break; + case AP_XrayAngiographicDVD: + if (compare(mediaSOPClassUID, UID_XRayAngiographicImageStorage)) + { + /* need to check multiple transfer syntaxes */ + found = compare(transferSyntax, UID_JPEGProcess14SV1TransferSyntax) || + compare(transferSyntax, UID_JPEGProcess1TransferSyntax) || + compare(transferSyntax, UID_JPEGProcess2_4TransferSyntax); + if (!found) + { + const OFString expXferName1 = dcmFindNameOfUID(UID_JPEGProcess14SV1TransferSyntax, ""); + const OFString expXferName2 = dcmFindNameOfUID(UID_JPEGProcess1TransferSyntax, ""); + const OFString expXferName3 = dcmFindNameOfUID(UID_JPEGProcess2_4TransferSyntax, ""); + /* create error message */ + OFOStringStream oss; + oss << expXferName1 << ", " << expXferName2 << " or " << expXferName3 + << " expected but " << xferName << " found: " << filename << OFStringStream_ends; + OFSTRINGSTREAM_GETSTR(oss, tmpString) + if (TransferSyntaxCheck) + { + DCMDATA_ERROR(tmpString); + result = EC_ApplicationProfileViolated; + } else + DCMDATA_WARN(tmpString); + OFSTRINGSTREAM_FREESTR(tmpString) + } + } + break; + case AP_CTandMR: + { + const OFBool isImage = compare(mediaSOPClassUID, UID_CTImageStorage) || + compare(mediaSOPClassUID, UID_MRImageStorage) || + compare(mediaSOPClassUID, UID_SecondaryCaptureImageStorage); + /* need to check multiple transfer syntaxes (JPEG only allowed for images) */ + found = compare(transferSyntax, UID_LittleEndianExplicitTransferSyntax) || + (compare(transferSyntax, UID_JPEGProcess14SV1TransferSyntax) && isImage); + if (!found) + { + const OFString expXferName1 = dcmFindNameOfUID(UID_LittleEndianExplicitTransferSyntax, ""); + const OFString expXferName2 = dcmFindNameOfUID(UID_JPEGProcess14SV1TransferSyntax, ""); + /* create error message */ + OFOStringStream oss; + if (isImage) + { + oss << expXferName1 << " or " << expXferName2 << " expected but " << xferName + << " found: " << filename << OFStringStream_ends; + } else { + oss << expXferName1 << " expected but " << xferName << " found: " << filename + << OFStringStream_ends; + } + OFSTRINGSTREAM_GETSTR(oss, tmpString) + if (TransferSyntaxCheck) + { + DCMDATA_ERROR(tmpString); + result = EC_ApplicationProfileViolated; + } else + DCMDATA_WARN(tmpString); + OFSTRINGSTREAM_FREESTR(tmpString) + } + } + break; + case AP_UltrasoundIDSF: + case AP_UltrasoundSCSF: + case AP_UltrasoundCCSF: + case AP_UltrasoundIDMF: + case AP_UltrasoundSCMF: + case AP_UltrasoundCCMF: + /* need to check multiple transfer syntaxes */ + found = compare(transferSyntax, UID_LittleEndianExplicitTransferSyntax) || + compare(transferSyntax, UID_RLELosslessTransferSyntax) || + compare(transferSyntax, UID_JPEGProcess1TransferSyntax); + if (!found) + { + const OFString expXferName1 = dcmFindNameOfUID(UID_LittleEndianExplicitTransferSyntax, ""); + const OFString expXferName2 = dcmFindNameOfUID(UID_RLELosslessTransferSyntax, ""); + const OFString expXferName3 = dcmFindNameOfUID(UID_JPEGProcess1TransferSyntax, ""); + /* create error message */ + OFOStringStream oss; + oss << expXferName1 << ", " << expXferName2 << " or " << expXferName3 + << " expected but " << xferName << " found: " << filename + << OFStringStream_ends; + OFSTRINGSTREAM_GETSTR(oss, tmpString) + if (TransferSyntaxCheck) + { + DCMDATA_ERROR(tmpString); + result = EC_ApplicationProfileViolated; + } else + DCMDATA_WARN(tmpString); + OFSTRINGSTREAM_FREESTR(tmpString) + } + break; + case AP_GeneralPurpose: + case AP_MPEG2MPatMLDVD: + case AP_BasicCardiac: + case AP_XrayAngiographic: + case AP_DentalRadiograph: + case AP_TwelveLeadECG: + case AP_HemodynamicWaveform: + default: + { + /* compare with expected transfer syntax */ + found = compare(transferSyntax, expectedTransferSyntax); + if (!found) + { + const OFString expXferName = dcmFindNameOfUID(expectedTransferSyntax.c_str(), + expectedTransferSyntax.c_str() /*defaultValue*/); + /* create error message */ + OFOStringStream oss; + oss << expXferName << " expected but " << xferName << " found: " << filename + << OFStringStream_ends; + OFSTRINGSTREAM_GETSTR(oss, tmpString) + if (TransferSyntaxCheck) + { + DCMDATA_ERROR(tmpString); + result = EC_ApplicationProfileViolated; + } else + DCMDATA_WARN(tmpString); + OFSTRINGSTREAM_FREESTR(tmpString) + } + } + } + } + } + } + } + return result; +} + + +// check whether dataset conforms to basic cardiac application profile +OFCondition DicomDirInterface::checkBasicCardiacAttributes(DcmItem *dataset, + const OFFilename &filename) +{ + OFCondition result = EC_Normal; + if (!checkExistsWithStringValue(dataset, DCM_Modality, "XA", filename)) + result = EC_ApplicationProfileViolated; + if (!checkExistsWithMinMaxValue(dataset, DCM_Rows, 1, 512, filename, ResolutionCheck)) + result = EC_ApplicationProfileViolated; + if (!checkExistsWithMinMaxValue(dataset, DCM_Columns, 1, 512, filename, ResolutionCheck)) + result = EC_ApplicationProfileViolated; + if (!checkExistsWithIntegerValue(dataset, DCM_BitsAllocated, 8, filename, EncodingCheck)) + result = EC_ApplicationProfileViolated; + if (!checkExistsWithIntegerValue(dataset, DCM_BitsStored, 8, filename, EncodingCheck)) + result = EC_ApplicationProfileViolated; + /* overlay data, if present, shall be encoded in OverlayData (60XX,3000) */ + for (Uint16 grp = 0x6000; grp < 0x601f; grp = OFstatic_cast(Uint16, grp + 2)) + { + /* check minimum number of attributes required for an overlay plane to be displayed */ + if (dataset->tagExistsWithValue(DcmTagKey(grp, DCM_OverlayRows.getElement())) && + dataset->tagExistsWithValue(DcmTagKey(grp, DCM_OverlayColumns.getElement())) && + dataset->tagExistsWithValue(DcmTagKey(grp, DCM_OverlayBitsAllocated.getElement())) && + dataset->tagExistsWithValue(DcmTagKey(grp, DCM_OverlayBitPosition.getElement())) && + !dataset->tagExistsWithValue(DcmTagKey(grp, DCM_OverlayData.getElement()))) + { + DCMDATA_ERROR("embedded overlay data present in group 0x" << STD_NAMESPACE hex << grp + << ", file: " << filename); + result = EC_ApplicationProfileViolated; + } + } + return result; +} + + +// check whether dataset conforms to xray angiographic application profile +OFCondition DicomDirInterface::checkXrayAngiographicAttributes(DcmItem *dataset, + const OFString &sopClass, + const OFFilename &filename) +{ + OFCondition result = EC_Normal; + /* requirements depend on SOP class */ + if (compare(sopClass, UID_XRayAngiographicImageStorage)) + { + /* a XA image */ + if (!checkExistsWithStringValue(dataset, DCM_Modality, "XA", filename)) + result = EC_ApplicationProfileViolated; + if (!checkExistsWithMinMaxValue(dataset, DCM_Rows, 1, 1024, filename, ResolutionCheck)) + result = EC_ApplicationProfileViolated; + if (!checkExistsWithMinMaxValue(dataset, DCM_Columns, 1, 1024, filename, ResolutionCheck)) + result = EC_ApplicationProfileViolated; + if (!checkExistsWithValue(dataset, DCM_BitsStored, filename)) + result = EC_InvalidTag; + else + { + long bs; + dataset->findAndGetLongInt(DCM_BitsStored, bs); + if ((bs != 8) && (bs != 10) && (bs != 12)) + { + /* report an error or a warning */ + printUnexpectedValueMessage(DCM_BitsStored, filename, EncodingCheck); + if (EncodingCheck) + result = EC_ApplicationProfileViolated; + } + } + } + else if (compare(sopClass, UID_SecondaryCaptureImageStorage)) + { + /* a SC image */ + if (!checkExistsWithMinMaxValue(dataset, DCM_Rows, 1, 1024, filename, ResolutionCheck)) + result = EC_ApplicationProfileViolated; + if (!checkExistsWithMinMaxValue(dataset, DCM_Columns, 1, 1024, filename, ResolutionCheck)) + result = EC_ApplicationProfileViolated; + if (!checkExistsWithIntegerValue(dataset, DCM_SamplesPerPixel, 1, filename)) + result = EC_ApplicationProfileViolated; + if (!checkExistsWithStringValue(dataset, DCM_PhotometricInterpretation, "MONOCHROME2", filename)) + result = EC_ApplicationProfileViolated; + if (!checkExistsWithIntegerValue(dataset, DCM_BitsAllocated, 8, filename, EncodingCheck)) + result = EC_ApplicationProfileViolated; + if (!checkExistsWithIntegerValue(dataset, DCM_BitsStored, 8, filename, EncodingCheck)) + result = EC_ApplicationProfileViolated; + if (!checkExistsWithIntegerValue(dataset, DCM_HighBit, 7, filename, EncodingCheck)) + result = EC_ApplicationProfileViolated; + if (!checkExistsWithIntegerValue(dataset, DCM_PixelRepresentation, 0, filename)) + result = EC_ApplicationProfileViolated; + /* check whether any overlay is present */ + for (Uint16 grp = 0x6000; grp < 0x601f; grp = OFstatic_cast(Uint16, grp + 2)) + { + /* check minimum number of attributes required for an overlay plane to be displayed */ + if (dataset->tagExistsWithValue(DcmTagKey(grp, DCM_OverlayRows.getElement())) && + dataset->tagExistsWithValue(DcmTagKey(grp, DCM_OverlayColumns.getElement())) && + dataset->tagExistsWithValue(DcmTagKey(grp, DCM_OverlayBitsAllocated.getElement())) && + dataset->tagExistsWithValue(DcmTagKey(grp, DCM_OverlayBitPosition.getElement()))) + { + /* create error message */ + DCMDATA_ERROR("overlay group 0x" << STD_NAMESPACE hex << grp + << " present in file: " << filename); + result = EC_ApplicationProfileViolated; + } + } + } else /* wrong SOP class */ + result = EC_ApplicationProfileViolated; + return result; +} + + +// check whether dataset conforms to dental radiograph application profile +OFCondition DicomDirInterface::checkDentalRadiographAttributes(DcmItem *dataset, + const OFFilename &filename) +{ + OFCondition result = EC_Normal; + /* check presence of type 2 elements */ + if (!checkExists(dataset, DCM_InstitutionName, filename) || + !checkExists(dataset, DCM_ManufacturerModelName, filename) || + !checkExists(dataset, DCM_DetectorID, filename) || + !checkExists(dataset, DCM_DetectorManufacturerName, filename) || + !checkExists(dataset, DCM_DetectorManufacturerModelName, filename)) + { + result = EC_TagNotFound; + } + /* check for value constraints */ + else if (!checkExistsWithValue(dataset, DCM_BitsAllocated, filename) || + !checkExistsWithValue(dataset, DCM_BitsStored, filename)) + { + result = EC_InvalidTag; + } else { + long bs; + dataset->findAndGetLongInt(DCM_BitsStored, bs); + if ((bs != 8) && (bs != 10) && (bs != 12) && (bs != 16)) + { + /* report an error or a warning */ + printUnexpectedValueMessage(DCM_BitsStored, filename, EncodingCheck); + if (EncodingCheck) + result = EC_ApplicationProfileViolated; + } + long ba; + dataset->findAndGetLongInt(DCM_BitsAllocated, ba); + if (((bs == 8) && (ba != 8)) || ((bs != 8) && (ba != 16))) + { + /* report an error or a warning */ + printUnexpectedValueMessage(DCM_BitsAllocated, filename, EncodingCheck); + if (EncodingCheck) + result = EC_ApplicationProfileViolated; + } + } + return result; +} + + +// check whether dataset conforms to ct and mr application profile +OFCondition DicomDirInterface::checkCTandMRAttributes(DcmItem *dataset, + const OFString &sopClass, + const OFFilename &filename) +{ + OFCondition result = EC_Normal; + /* check presence of type 1 elements */ + if (!checkExistsWithValue(dataset, DCM_Rows, filename) || + !checkExistsWithValue(dataset, DCM_Columns, filename)) + { + result = EC_InvalidTag; + } + /* requirements depend on SOP class */ + if (compare(sopClass, UID_CTImageStorage)) + { + /* a CT image */ + if (!checkExistsWithStringValue(dataset, DCM_Modality, "CT", filename)) + result = EC_ApplicationProfileViolated; + if (!checkExistsWithStringValue(dataset, DCM_PhotometricInterpretation, "MONOCHROME2", filename)) + result = EC_ApplicationProfileViolated; + } + else if (compare(sopClass, UID_MRImageStorage)) + { + /* a MR image */ + if (!checkExistsWithStringValue(dataset, DCM_Modality, "MR", filename)) + result = EC_ApplicationProfileViolated; + if (!checkExistsWithStringValue(dataset, DCM_PhotometricInterpretation, "MONOCHROME2", filename)) + result = EC_ApplicationProfileViolated; + if (!checkExistsWithValue(dataset, DCM_BitsStored, filename) || + !checkExistsWithValue(dataset, DCM_HighBit, filename)) + { + result = EC_InvalidTag; + } else { + long bs; + dataset->findAndGetLongInt(DCM_BitsStored, bs); + if ((bs != 8) && (bs != 12) && (bs != 16)) + { + /* report an error or a warning */ + printUnexpectedValueMessage(DCM_BitsStored, filename, EncodingCheck); + if (EncodingCheck) + result = EC_ApplicationProfileViolated; + } + long hb; + dataset->findAndGetLongInt(DCM_HighBit, hb); + if (hb != bs - 1) + { + /* report an error or a warning */ + printUnexpectedValueMessage(DCM_HighBit, filename, EncodingCheck); + if (EncodingCheck) + result = EC_ApplicationProfileViolated; + } + } + } + else if (compare(sopClass, UID_SecondaryCaptureImageStorage)) + { + /* a SC image */ + if (!checkExistsWithIntegerValue(dataset, DCM_SamplesPerPixel, 1, filename)) + result = EC_ApplicationProfileViolated; + if (!checkExists(dataset, DCM_PhotometricInterpretation, filename)) + { + OFString pi; + dataset->findAndGetOFStringArray(DCM_PhotometricInterpretation, pi); + if (compare(pi, "MONOCHROME2")) + { + if (!checkExistsWithValue(dataset, DCM_BitsAllocated, filename) || + !checkExistsWithValue(dataset, DCM_BitsStored, filename) || + !checkExistsWithValue(dataset, DCM_HighBit, filename)) + { + result = EC_InvalidTag; + } else { + long ba; + dataset->findAndGetLongInt(DCM_BitsAllocated, ba); + if ((ba != 8) && (ba != 16)) + { + /* report an error or a warning */ + printUnexpectedValueMessage(DCM_BitsAllocated, filename, EncodingCheck); + if (EncodingCheck) + result = EC_ApplicationProfileViolated; + } + long bs; + dataset->findAndGetLongInt(DCM_BitsStored, bs); + if (bs != ba) + { + /* report an error or a warning */ + printUnexpectedValueMessage(DCM_BitsStored, filename, EncodingCheck); + if (EncodingCheck) + result = EC_ApplicationProfileViolated; + } + long hb; + dataset->findAndGetLongInt(DCM_HighBit, hb); + if (hb != bs - 1) + { + /* report an error or a warning */ + printUnexpectedValueMessage(DCM_HighBit, filename, EncodingCheck); + if (EncodingCheck) + result = EC_ApplicationProfileViolated; + } + } + } + else if (compare(pi, "PALETTE COLOR")) + { + if (!checkExistsWithIntegerValue(dataset, DCM_BitsAllocated, 8, filename)) + result = EC_ApplicationProfileViolated; + if (!checkExistsWithIntegerValue(dataset, DCM_BitsStored, 8, filename)) + result = EC_ApplicationProfileViolated; + if (!checkExistsWithIntegerValue(dataset, DCM_HighBit, 7, filename)) + result = EC_ApplicationProfileViolated; + } else { + /* report an error */ + printUnexpectedValueMessage(DCM_PhotometricInterpretation, filename); + result = EC_ApplicationProfileViolated; + } + } + } else /* wrong SOP class */ + result = EC_ApplicationProfileViolated; + return result; +} + + +// check whether dataset conforms to one of the ultrasound application profiles +OFCondition DicomDirInterface::checkUltrasoundAttributes(DcmItem *dataset, + const OFString &transferSyntax, + const OFFilename &filename) +{ + OFCondition result = EC_Normal; + /* a US image */ + if (!checkExistsWithValue(dataset, DCM_PhotometricInterpretation, filename)) + result = EC_InvalidTag; + else + { + OFString pi; + /* check photometric interpretation */ + getStringFromDataset(dataset, DCM_PhotometricInterpretation, pi); + const OFBool uncompressed = compare(transferSyntax, UID_LittleEndianExplicitTransferSyntax); + const OFBool rle_lossless = compare(transferSyntax, UID_RLELosslessTransferSyntax); + const OFBool jpeg_lossy = compare(transferSyntax, UID_JPEGProcess1TransferSyntax); + OFBool valid = (compare(pi, "MONOCHROME2") && (uncompressed || rle_lossless)) || + (compare(pi, "RGB") && (uncompressed || rle_lossless)) || + (compare(pi, "PALETTE COLOR") && (uncompressed || rle_lossless)) || + (compare(pi, "YBR_FULL") && rle_lossless) || + (compare(pi, "YBR_FULL_422") && (uncompressed || jpeg_lossy)) || + (compare(pi, "YBR_PARTIAL_422") && (uncompressed || jpeg_lossy)); + if (!valid) + { + /* report an error */ + printUnexpectedValueMessage(DCM_PhotometricInterpretation, filename); + result = EC_ApplicationProfileViolated; + } + } + if ((ApplicationProfile == AP_UltrasoundSCSF) || + (ApplicationProfile == AP_UltrasoundCCSF) || + (ApplicationProfile == AP_UltrasoundSCMF) || + (ApplicationProfile == AP_UltrasoundCCMF)) + { + /* check for US region calibration module (SC and CC profiles) */ + OFBool ok = OFTrue; + unsigned long i = 0; + /* iterate over all sequence items */ + DcmItem *ditem = NULL; + while (ok && dataset->findAndGetSequenceItem(DCM_SequenceOfUltrasoundRegions, ditem, i).good()) + { + ok &= checkExistsWithValue(ditem, DCM_RegionLocationMinX0, filename); + ok &= checkExistsWithValue(ditem, DCM_RegionLocationMinY0, filename); + ok &= checkExistsWithValue(ditem, DCM_RegionLocationMaxX1, filename); + ok &= checkExistsWithValue(ditem, DCM_RegionLocationMaxY1, filename); + ok &= checkExistsWithValue(ditem, DCM_PhysicalUnitsXDirection, filename); + ok &= checkExistsWithValue(ditem, DCM_PhysicalUnitsYDirection, filename); + ok &= checkExistsWithValue(ditem, DCM_PhysicalDeltaX, filename); + ok &= checkExistsWithValue(ditem, DCM_PhysicalDeltaY, filename); + ok &= checkExistsWithValue(ditem, DCM_RegionSpatialFormat, filename); + ok &= checkExistsWithValue(ditem, DCM_RegionDataType, filename); + ok &= checkExistsWithValue(ditem, DCM_RegionFlags, filename); + if ((ApplicationProfile == AP_UltrasoundCCSF) || + (ApplicationProfile == AP_UltrasoundCCMF)) + { + /* check for pixel component organization (CC profile) */ + if (checkExistsWithValue(ditem, DCM_PixelComponentOrganization, filename)) + { + ok &= checkExistsWithValue(ditem, DCM_PixelComponentPhysicalUnits, filename); + ok &= checkExistsWithValue(ditem, DCM_PixelComponentDataType, filename); + long pco; + dataset->findAndGetLongInt(DCM_PixelComponentOrganization, pco); + if (pco == 0) + { + /* pixel component organization: bit aligned positions */ + ok &= checkExistsWithValue(ditem, DCM_PixelComponentMask, filename); + ok &= checkExistsWithValue(ditem, DCM_NumberOfTableBreakPoints, filename); + ok &= checkExistsWithValue(ditem, DCM_TableOfXBreakPoints, filename); + ok &= checkExistsWithValue(ditem, DCM_TableOfYBreakPoints, filename); + } else if (pco == 1) + { + /* pixel component organization: ranges */ + ok &= checkExistsWithValue(ditem, DCM_PixelComponentRangeStart, filename); + ok &= checkExistsWithValue(ditem, DCM_PixelComponentRangeStop, filename); + ok &= checkExistsWithValue(ditem, DCM_NumberOfTableBreakPoints, filename); + ok &= checkExistsWithValue(ditem, DCM_TableOfXBreakPoints, filename); + ok &= checkExistsWithValue(ditem, DCM_TableOfYBreakPoints, filename); + } else if (pco == 2) + { + /* pixel component organization: table look up */ + ok &= checkExistsWithValue(ditem, DCM_NumberOfTableEntries, filename); + ok &= checkExistsWithValue(ditem, DCM_TableOfPixelValues, filename); + ok &= checkExistsWithValue(ditem, DCM_TableOfParameterValues, filename); + } else { + /* report an error */ + printUnexpectedValueMessage(DCM_PixelComponentOrganization, filename); + ok = OFFalse; + } + } else + ok = OFFalse; + } + i++; + } + if (ok) + { + if (i == 0) + { + /* no item found, sequence seems to be empty */ + printRequiredAttributeMessage(DCM_SequenceOfUltrasoundRegions, filename); + result = EC_ApplicationProfileViolated; + } + } else { + /* report any error within the 'while' loop as an violation of the application profile */ + result = EC_ApplicationProfileViolated; + } + } + return result; +} + + +// check the given file (dataset) for mandatory attributes +OFCondition DicomDirInterface::checkMandatoryAttributes(DcmMetaInfo *metainfo, + DcmItem *dataset, + const OFFilename &filename) +{ + OFCondition result = EC_IllegalParameter; + if ((metainfo != NULL) && (dataset != NULL)) + { + /* are mandatory attributes for DICOMDIR available and valued? */ + result = EC_Normal; + /* get the transfer syntax and SOP class + (cannot fail, after checkSOPClassAndXfer has been passed) */ + OFString transferSyntax; + OFString mediaSOPClassUID; + metainfo->findAndGetOFStringArray(DCM_TransferSyntaxUID, transferSyntax); + metainfo->findAndGetOFStringArray(DCM_MediaStorageSOPClassUID, mediaSOPClassUID); + E_DirRecType recordType = sopClassToRecordType(mediaSOPClassUID); + /* hanging protocol, palette and implant files are handled separately */ + if (recordType == ERT_HangingProtocol) + { + /* check whether all type 1 elements are really present */ + if (!checkExistsWithValue(dataset, DCM_HangingProtocolName, filename)) + result = EC_InvalidTag; + if (!checkExistsWithValue(dataset, DCM_HangingProtocolDescription, filename)) + result = EC_InvalidTag; + if (!checkExistsWithValue(dataset, DCM_HangingProtocolLevel, filename)) + result = EC_InvalidTag; + if (!checkExistsWithValue(dataset, DCM_HangingProtocolCreator, filename)) + result = EC_InvalidTag; + if (!checkExistsWithValue(dataset, DCM_HangingProtocolCreationDateTime, filename)) + result = EC_InvalidTag; + if (!checkExistsWithValue(dataset, DCM_HangingProtocolDefinitionSequence, filename)) + result = EC_InvalidTag; + if (!checkExistsWithValue(dataset, DCM_NumberOfPriorsReferenced, filename)) + result = EC_InvalidTag; + } + else if (recordType == ERT_Palette) + { + /* check whether all type 1 elements are really present */ + if (!checkExistsWithValue(dataset, DCM_ContentLabel, filename)) + result = EC_InvalidTag; + } + else if (recordType == ERT_Implant) + { + /* check whether all type 1 elements are really present */ + if (!checkExistsWithValue(dataset, DCM_Manufacturer, filename)) + result = EC_InvalidTag; + if (!checkExistsWithValue(dataset, DCM_ImplantName, filename)) + result = EC_InvalidTag; + if (!checkExistsWithValue(dataset, DCM_ImplantPartNumber, filename)) + result = EC_InvalidTag; + } + else if (recordType == ERT_ImplantGroup) + { + /* check whether all type 1 elements are really present */ + if (!checkExistsWithValue(dataset, DCM_ImplantAssemblyTemplateName, filename)) + result = EC_InvalidTag; + if (!checkExistsWithValue(dataset, DCM_ImplantAssemblyTemplateIssuer, filename)) + result = EC_InvalidTag; + if (!checkExistsWithValue(dataset, DCM_ProcedureTypeCodeSequence, filename)) + result = EC_InvalidTag; + } + else if (recordType == ERT_ImplantAssy) + { + /* check whether all type 1 elements are really present */ + if (!checkExistsWithValue(dataset, DCM_ImplantTemplateGroupName, filename)) + result = EC_InvalidTag; + if (!checkExistsWithValue(dataset, DCM_ImplantTemplateGroupIssuer, filename)) + result = EC_InvalidTag; + } else { + /* PatientID is type 1 in DICOMDIR and type 2 in images */ + if (!InventMode) + { + if (!checkExistsWithValue(dataset, DCM_PatientID, filename)) + result = EC_InvalidTag; + } + /* PatientName is type 2 in DICOMDIR and images */ + if (!checkExists(dataset, DCM_PatientName, filename)) + result = EC_TagNotFound; + /* StudyDate is type 1 in DICOMDIR and type 2 in images */ + if (!InventMode) + { + if (!checkExistsWithValue(dataset, DCM_StudyDate, filename)) + result = EC_InvalidTag; + } + /* StudyTime is type 1 in DICOMDIR and type 2 in images */ + if (!InventMode) + { + if (!checkExistsWithValue(dataset, DCM_StudyTime, filename)) + result = EC_InvalidTag; + } + /* StudyDescription is type 2 in DICOMDIR and type 3 in images. + We can create an empty attribute in the directory + */ + /* StudyInstanceUID is type 1 in DICOMDIR and images */ + if (!checkExistsWithValue(dataset, DCM_StudyInstanceUID, filename)) + result = EC_InvalidTag; + /* StudyID is type 1 in DICOMDIR and type 2 in images */ + if (!InventMode) + { + if (!checkExistsWithValue(dataset, DCM_StudyID, filename)) + result = EC_InvalidTag; + } + /* AccessionNumber is type 2 in DICOMDIR and type 3 in images + We can create an empty attribute in the directory + */ + /* Modality is type 1 in DICOMDIR and type 1 in images */ + if (!checkExistsWithValue(dataset, DCM_Modality, filename)) + result = EC_InvalidTag; + /* SeriesInstanceUID is type 1 in DICOMDIR and type 1 in images */ + if (!checkExistsWithValue(dataset, DCM_SeriesInstanceUID, filename)) + result = EC_InvalidTag; + /* SeriesNumber is type 1 in DICOMDIR and type 2 in images */ + if (!InventMode) + { + if (!checkExistsWithValue(dataset, DCM_SeriesNumber, filename)) + result = EC_InvalidTag; + } + /* image and other numbers are type 1 in DICOMDIR but type 2 in images */ + /* (basically, check whether all type 1 elements are really present) */ + switch (recordType) + { + case ERT_Overlay: + if (!InventMode) + { + if (!checkExistsWithValue(dataset, DCM_RETIRED_OverlayNumber, filename)) + result = EC_InvalidTag; + } + break; + case ERT_ModalityLut: + if (!InventMode) + { + if (!checkExistsWithValue(dataset, DCM_RETIRED_LUTNumber, filename)) + result = EC_InvalidTag; + } + break; + case ERT_VoiLut: + if (!InventMode) + { + if (!checkExistsWithValue(dataset, DCM_RETIRED_LUTNumber, filename)) + result = EC_InvalidTag; + } + break; + case ERT_Curve: + if (!InventMode) + { + if (!checkExistsWithValue(dataset, DCM_RETIRED_CurveNumber, filename)) + result = EC_InvalidTag; + } + break; + case ERT_SRDocument: + if (!checkExistsWithValue(dataset, DCM_InstanceNumber, filename)) + result = EC_InvalidTag; + if (!checkExistsWithValue(dataset, DCM_CompletionFlag, filename)) + result = EC_InvalidTag; + if (!checkExistsWithValue(dataset, DCM_VerificationFlag, filename)) + result = EC_InvalidTag; + if (!checkExistsWithValue(dataset, DCM_ContentDate, filename)) + result = EC_InvalidTag; + if (!checkExistsWithValue(dataset, DCM_ContentTime, filename)) + result = EC_InvalidTag; + if (!checkExistsWithValue(dataset, DCM_ConceptNameCodeSequence, filename)) + result = EC_InvalidTag; + { + OFString tmpString; + if (compare(getStringFromDataset(dataset, DCM_VerificationFlag, tmpString), "VERIFIED")) + { + /* VerificationDateTime is required if verification flag is VERIFIED, + retrieve most recent (= last) entry from VerifyingObserverSequence */ + DcmItem *ditem = NULL; + OFCondition l_status = dataset->findAndGetSequenceItem(DCM_VerifyingObserverSequence, ditem, -1 /*last*/); + if (l_status.good()) + { + if (!checkExistsWithValue(ditem, DCM_VerificationDateTime, filename)) + result = EC_InvalidTag; + } else + result = l_status; + } + } + break; + case ERT_Presentation: + if (!checkExistsWithValue(dataset, DCM_InstanceNumber, filename)) + result = EC_InvalidTag; + if (!checkExistsWithValue(dataset, DCM_ContentLabel, filename)) + result = EC_InvalidTag; + if (!checkExistsWithValue(dataset, DCM_PresentationCreationDate, filename)) + result = EC_InvalidTag; + if (!checkExistsWithValue(dataset, DCM_PresentationCreationTime, filename)) + result = EC_InvalidTag; + break; + case ERT_Waveform: + if (!checkExistsWithValue(dataset, DCM_InstanceNumber, filename)) + result = EC_InvalidTag; + if (!checkExistsWithValue(dataset, DCM_ContentDate, filename)) + result = EC_InvalidTag; + if (!checkExistsWithValue(dataset, DCM_ContentTime, filename)) + result = EC_InvalidTag; + break; + case ERT_RTDose: + if (!InventMode) + { + if (!checkExistsWithValue(dataset, DCM_InstanceNumber, filename)) + result = EC_InvalidTag; + } + if (!checkExistsWithValue(dataset, DCM_DoseSummationType, filename)) + result = EC_InvalidTag; + break; + case ERT_RTStructureSet: + if (!InventMode) + { + if (!checkExistsWithValue(dataset, DCM_InstanceNumber, filename)) + result = EC_InvalidTag; + } + if (!checkExistsWithValue(dataset, DCM_StructureSetLabel, filename)) + result = EC_InvalidTag; + break; + case ERT_RTPlan: + if (!InventMode) + { + if (!checkExistsWithValue(dataset, DCM_InstanceNumber, filename)) + result = EC_InvalidTag; + } + if (!checkExistsWithValue(dataset, DCM_RTPlanLabel, filename)) + result = EC_InvalidTag; + break; + case ERT_RTTreatRecord: + if (!checkExistsWithValue(dataset, DCM_InstanceNumber, filename)) + result = EC_InvalidTag; + break; + case ERT_StoredPrint: + /* (nothing to do) */ + break; + case ERT_KeyObjectDoc: + if (!checkExistsWithValue(dataset, DCM_InstanceNumber, filename)) + result = EC_InvalidTag; + if (!checkExistsWithValue(dataset, DCM_ContentDate, filename)) + result = EC_InvalidTag; + if (!checkExistsWithValue(dataset, DCM_ContentTime, filename)) + result = EC_InvalidTag; + if (!checkExistsWithValue(dataset, DCM_ConceptNameCodeSequence, filename)) + result = EC_InvalidTag; + break; + case ERT_RawData: + if (!checkExistsWithValue(dataset, DCM_ContentDate, filename)) + result = EC_InvalidTag; + if (!checkExistsWithValue(dataset, DCM_ContentTime, filename)) + result = EC_InvalidTag; + /* InstanceNumber is type 2 in IOD and directory record! */ + break; + case ERT_Spectroscopy: + if (!checkExistsWithValue(dataset, DCM_InstanceNumber, filename)) + result = EC_InvalidTag; + if (!checkExistsWithValue(dataset, DCM_ImageType, filename)) + result = EC_InvalidTag; + if (!checkExistsWithValue(dataset, DCM_ContentDate, filename)) + result = EC_InvalidTag; + if (!checkExistsWithValue(dataset, DCM_ContentTime, filename)) + result = EC_InvalidTag; + if (!checkExistsWithValue(dataset, DCM_NumberOfFrames, filename)) + result = EC_InvalidTag; + if (!checkExistsWithValue(dataset, DCM_Rows, filename)) + result = EC_InvalidTag; + if (!checkExistsWithValue(dataset, DCM_Columns, filename)) + result = EC_InvalidTag; + if (!checkExistsWithValue(dataset, DCM_DataPointRows, filename)) + result = EC_InvalidTag; + if (!checkExistsWithValue(dataset, DCM_DataPointColumns, filename)) + result = EC_InvalidTag; + break; + case ERT_EncapDoc: + if (!checkExistsWithValue(dataset, DCM_InstanceNumber, filename)) + result = EC_InvalidTag; + if (!checkExistsWithValue(dataset, DCM_MIMETypeOfEncapsulatedDocument, filename)) + result = EC_InvalidTag; + break; + case ERT_Stereometric: + case ERT_Plan: + /* nothing to check */ + break; + case ERT_Registration: + case ERT_Fiducial: + case ERT_ValueMap: + case ERT_Surface: + case ERT_Measurement: + if (!checkExistsWithValue(dataset, DCM_InstanceNumber, filename)) + result = EC_InvalidTag; + if (!checkExistsWithValue(dataset, DCM_ContentDate, filename)) + result = EC_InvalidTag; + if (!checkExistsWithValue(dataset, DCM_ContentTime, filename)) + result = EC_InvalidTag; + if (!checkExistsWithValue(dataset, DCM_ContentLabel, filename)) + result = EC_InvalidTag; + break; + case ERT_SurfaceScan: + if (!checkExistsWithValue(dataset, DCM_ContentDate, filename)) + result = EC_InvalidTag; + if (!checkExistsWithValue(dataset, DCM_ContentTime, filename)) + result = EC_InvalidTag; + break; + case ERT_Image: + default: + { + OFCondition l_status = EC_Normal; + /* it can only be an image */ + if (!InventMode) + { + if (!checkExistsWithValue(dataset, DCM_InstanceNumber, filename)) + result = EC_InvalidTag; + } + /* check profile specific requirements */ + if ((ApplicationProfile == AP_GeneralPurposeDVDJPEG) || + (ApplicationProfile == AP_GeneralPurposeDVDJPEG2000) || + (ApplicationProfile == AP_GeneralPurposeBDJPEG) || + (ApplicationProfile == AP_GeneralPurposeBDJPEG2000) || + (ApplicationProfile == AP_GeneralPurposeBDMPEG2MPatML) || + (ApplicationProfile == AP_GeneralPurposeBDMPEG2MPatHL) || + (ApplicationProfile == AP_GeneralPurposeBDMPEG4HPatLV41) || + (ApplicationProfile == AP_GeneralPurposeBDMPEG4HPatLV41BD) || + (ApplicationProfile == AP_USBandFlashJPEG) || + (ApplicationProfile == AP_USBandFlashJPEG2000) || + (ApplicationProfile == AP_MPEG2MPatMLDVD)) + { + /* check presence of type 1 elements */ + if (!checkExistsWithValue(dataset, DCM_Rows, filename) || + !checkExistsWithValue(dataset, DCM_Columns, filename)) + { + result = EC_InvalidTag; + } + } + else if (ApplicationProfile == AP_BasicCardiac) + l_status = checkBasicCardiacAttributes(dataset, filename); + else if ((ApplicationProfile == AP_XrayAngiographic) || (ApplicationProfile == AP_XrayAngiographicDVD)) + l_status = checkXrayAngiographicAttributes(dataset, mediaSOPClassUID, filename); + else if (ApplicationProfile == AP_DentalRadiograph) + l_status = checkDentalRadiographAttributes(dataset, filename); + else if (ApplicationProfile == AP_CTandMR) + l_status = checkCTandMRAttributes(dataset, mediaSOPClassUID, filename); + else if ((ApplicationProfile == AP_UltrasoundIDSF) || + (ApplicationProfile == AP_UltrasoundSCSF) || + (ApplicationProfile == AP_UltrasoundCCSF) || + (ApplicationProfile == AP_UltrasoundIDMF) || + (ApplicationProfile == AP_UltrasoundSCMF) || + (ApplicationProfile == AP_UltrasoundCCMF)) + { + l_status = checkUltrasoundAttributes(dataset, transferSyntax, filename); + } + /* set final result status (if everything else was ok) */ + if (result.good()) + result = l_status; + } + } + } + } + return result; +} + + +// select specified application profile and adapt certain settings +OFCondition DicomDirInterface::selectApplicationProfile(const E_ApplicationProfile profile) +{ + OFCondition result = EC_Normal; + /* special handling for particular profiles */ + if ((ApplicationProfile == AP_BasicCardiac) || + (ApplicationProfile == AP_XrayAngiographic) || + (ApplicationProfile == AP_XrayAngiographicDVD)) + { + /* check for JPEG image support */ + if (!JPEGSupport) + result = EC_IllegalCall; + } + /* store new profile */ + if (result.good()) + ApplicationProfile = profile; + return result; +} + + +// check whether DICOM file is suitable for a DICOMDIR of the specified application profile +OFCondition DicomDirInterface::checkDicomFile(const OFFilename &filename, + const OFFilename &directory, + const OFBool checkFilename) +{ + /* define file format object for the DICOM file to be loaded */ + DcmFileFormat fileformat; + /* call the "real" function */ + return loadAndCheckDicomFile(filename, directory, fileformat, checkFilename); +} + + +// load DICOM file and check whether it is suitable for a DICOMDIR of the specified application profile +OFCondition DicomDirInterface::loadAndCheckDicomFile(const OFFilename &filename, + const OFFilename &directory, + DcmFileFormat &fileformat, + const OFBool checkFilename) +{ + OFCondition result = EC_IllegalParameter; + /* create fully qualified pathname of the DICOM file to be added */ + OFFilename pathname; + OFStandard::combineDirAndFilename(pathname, directory, filename, OFTrue /*allowEmptyDirName*/); + DCMDATA_INFO("checking file: " << pathname); + /* check filename (if not disabled) */ + if (!checkFilename || isFilenameValid(filename)) + { + /* load DICOM file */ + result = fileformat.loadFile(pathname); + if (result.good()) + { + /* check for correct part 10 file format */ + DcmMetaInfo *metainfo = fileformat.getMetaInfo(); + DcmDataset *dataset = fileformat.getDataset(); + if ((metainfo == NULL) || (metainfo->card() == 0)) + { + /* create error message */ + OFOStringStream oss; + oss << "file not in part 10 format (no file meta information): " << filename + << OFStringStream_ends; + OFSTRINGSTREAM_GETSTR(oss, tmpString) + /* file meta information is required */ + if (FileFormatCheck) + { + DCMDATA_ERROR(tmpString); + result = EC_FileMetaInfoHeaderMissing; + } else { + DCMDATA_WARN(tmpString); + /* add missing file meta information */ + if (dataset != NULL) + fileformat.validateMetaInfo(dataset->getOriginalXfer()); + } + OFSTRINGSTREAM_FREESTR(tmpString) + } + /* check for empty dataset */ + if ((dataset == NULL) || (dataset->card() == 0)) + { + DCMDATA_ERROR("file contains no data (no dataset): " << filename); + result = EC_CorruptedData; + } + /* only proceed if previous checks have been passed */ + if (result.good()) + { + /* check for SOP class and transfer syntax */ + result = checkSOPClassAndXfer(metainfo, dataset, filename); + if (result.good()) + { + /* check for mandatory attributes */ + if (checkMandatoryAttributes(metainfo, dataset, filename).bad()) + result = EC_ApplicationProfileViolated; + } + } + } else { + /* report an error */ + DCMDATA_ERROR(result.text() << ": reading file: " << filename); + } + } + return result; +} + + +// check whether given record matches dataset +OFBool DicomDirInterface::recordMatchesDataset(DcmDirectoryRecord *record, + DcmItem *dataset) +{ + OFBool result = OFFalse; + if ((record != NULL) && (dataset != NULL)) + { + OFString recordString, datasetString; + /* check matching depending on record type */ + switch (record->getRecordType()) + { + case ERT_Patient: + if (checkExistsWithValue(dataset, DCM_PatientID)) + { + OFString patientID; + /* PatientID is the primary key */ + result = compare(getStringFromDataset(record, DCM_PatientID, patientID), + getStringFromDataset(dataset, DCM_PatientID, datasetString)); + /* optional: check whether PatientName also matches */ + if (result && !compare(getStringFromDataset(record, DCM_PatientName, recordString), + getStringFromDataset(dataset, DCM_PatientName, datasetString))) + { + if (InventPatientIDMode) + { + DCMDATA_WARN("PatientName inconsistent for PatientID: " << patientID); + /* remove current patient ID, will be replaced later */ + dataset->putAndInsertString(DCM_PatientID, ""); + result = OFFalse; + } + } + } else { + /* if there is no value for PatientID in the dataset try using the PatientName */ + result = compare(getStringFromDataset(record, DCM_PatientName, recordString), + getStringFromDataset(dataset, DCM_PatientName, datasetString)); + } + break; + case ERT_Study: + if (checkExistsWithValue(record, DCM_StudyInstanceUID)) + { + result = compare(getStringFromDataset(record, DCM_StudyInstanceUID, recordString), + getStringFromDataset(dataset, DCM_StudyInstanceUID, datasetString)); + } else { + /* the Study Instance UID can be in the referenced file instead */ + OFString refFilename; + if (!getStringFromDataset(record, DCM_ReferencedFileID, refFilename).empty()) + { + OFString hostFilename; + if (locateDicomFile(refFilename, hostFilename)) + { + result = compare(getStringFromFile(hostFilename, DCM_StudyInstanceUID, recordString), + getStringFromDataset(dataset, DCM_StudyInstanceUID, datasetString)); + } else + DCMDATA_ERROR("cannot locate referenced file: " << refFilename); + } + } + break; + case ERT_Series: + result = compare(getStringFromDataset(record, DCM_SeriesInstanceUID, recordString), + getStringFromDataset(dataset, DCM_SeriesInstanceUID, datasetString)); + break; + case ERT_Image: + case ERT_Overlay: + case ERT_Curve: + case ERT_ModalityLut: + case ERT_VoiLut: + case ERT_SRDocument: + case ERT_Presentation: + case ERT_Waveform: + case ERT_RTDose: + case ERT_RTStructureSet: + case ERT_RTPlan: + case ERT_RTTreatRecord: + case ERT_StoredPrint: + case ERT_KeyObjectDoc: + case ERT_Registration: + case ERT_Fiducial: + case ERT_RawData: + case ERT_Spectroscopy: + case ERT_EncapDoc: + case ERT_ValueMap: + case ERT_HangingProtocol: + case ERT_Stereometric: + case ERT_Palette: + case ERT_Surface: + case ERT_Measurement: + case ERT_Implant: + case ERT_ImplantGroup: + case ERT_ImplantAssy: + case ERT_Plan: + case ERT_SurfaceScan: + /* The attribute ReferencedSOPInstanceUID is automatically + * put into a Directory Record when a filename is present. + */ + result = compare(getStringFromDataset(record, DCM_ReferencedSOPInstanceUIDInFile, recordString), + getStringFromDataset(dataset, DCM_SOPInstanceUID, datasetString)); + break; + default: + DCMDATA_ERROR("record type not yet implemented"); + break; + } + } + return result; +} + + +// search for a given record +DcmDirectoryRecord *DicomDirInterface::findExistingRecord(DcmDirectoryRecord *parent, + const E_DirRecType recordType, + DcmItem* dataset) +{ + OFBool found = OFFalse; + DcmDirectoryRecord *record = NULL; + if (parent != NULL) + { + /* iterate over all records */ + while (!found && ((record = parent->nextSub(record)) != NULL)) + { + if (record->getRecordType() == recordType) + found = recordMatchesDataset(record, dataset); + } + } + return (found) ? record : NULL; +} + + +// create or update patient record and copy required values from dataset +DcmDirectoryRecord *DicomDirInterface::buildPatientRecord(DcmDirectoryRecord *record, + DcmFileFormat *fileformat, + const OFFilename &sourceFilename) +{ + /* create new patient record */ + if (record == NULL) + record = new DcmDirectoryRecord(ERT_Patient, NULL, sourceFilename, fileformat); + if (record != NULL) + { + /* check whether new record is ok */ + if (record->error().good()) + { + DcmDataset *dataset = fileformat->getDataset(); + /* use type 1C instead of 1 in order to avoid unwanted overwriting */ + copyElementType1C(dataset, DCM_PatientID, record, sourceFilename); + copyElementType2(dataset, DCM_PatientName, record, sourceFilename); + if ((ApplicationProfile == AP_GeneralPurposeDVDJPEG) || + (ApplicationProfile == AP_GeneralPurposeDVDJPEG2000) || + (ApplicationProfile == AP_GeneralPurposeBDJPEG) || + (ApplicationProfile == AP_GeneralPurposeBDJPEG2000) || + (ApplicationProfile == AP_GeneralPurposeBDMPEG2MPatML) || + (ApplicationProfile == AP_GeneralPurposeBDMPEG2MPatHL) || + (ApplicationProfile == AP_GeneralPurposeBDMPEG4HPatLV41) || + (ApplicationProfile == AP_GeneralPurposeBDMPEG4HPatLV41BD) || + (ApplicationProfile == AP_USBandFlashJPEG) || + (ApplicationProfile == AP_USBandFlashJPEG2000) || + (ApplicationProfile == AP_MPEG2MPatMLDVD)) + { + /* additional type 1C keys specified by specific profiles */ + copyElementType1C(dataset, DCM_PatientBirthDate, record, sourceFilename); + copyElementType1C(dataset, DCM_PatientSex, record, sourceFilename); + } + else if ((ApplicationProfile == AP_BasicCardiac) || + (ApplicationProfile == AP_XrayAngiographic) || + (ApplicationProfile == AP_XrayAngiographicDVD)) + { + /* additional type 2 keys specified by specific profiles */ + copyElementType2(dataset, DCM_PatientBirthDate, record, sourceFilename); + copyElementType2(dataset, DCM_PatientSex, record, sourceFilename); + } + } else { + printRecordErrorMessage(record->error(), ERT_Patient, "create"); + /* free memory */ + delete record; + record = NULL; + } + } else + DCMDATA_ERROR("out of memory (creating patient record)"); + return record; +} + + +// create or update study record and copy required values from dataset +DcmDirectoryRecord *DicomDirInterface::buildStudyRecord(DcmDirectoryRecord *record, + DcmFileFormat *fileformat, + const OFFilename &sourceFilename) +{ + /* create new study record */ + if (record == NULL) + record = new DcmDirectoryRecord(ERT_Study, NULL, sourceFilename, fileformat); + if (record != NULL) + { + /* check whether new record is ok */ + if (record->error().good()) + { + DcmDataset *dataset = fileformat->getDataset(); + OFString tmpString; + /* copy attribute values from dataset to study record */ + copyStringWithDefault(dataset, DCM_StudyDate, record, sourceFilename, alternativeStudyDate(dataset, tmpString).c_str(), OFTrue /*printWarning*/); + copyStringWithDefault(dataset, DCM_StudyTime, record, sourceFilename, alternativeStudyTime(dataset, tmpString).c_str(), OFTrue /*printWarning*/); + copyElementType2(dataset, DCM_StudyDescription, record, sourceFilename); + copyElementType1(dataset, DCM_StudyInstanceUID, record, sourceFilename); + /* use type 1C instead of 1 in order to avoid unwanted overwriting */ + copyElementType1C(dataset, DCM_StudyID, record, sourceFilename); + copyElementType2(dataset, DCM_AccessionNumber, record, sourceFilename); + } else { + printRecordErrorMessage(record->error(), ERT_Study, "create"); + /* free memory */ + delete record; + record = NULL; + } + } else + DCMDATA_ERROR("out of memory (creating study record)"); + return record; +} + + +// create or update series record and copy required values from dataset +DcmDirectoryRecord *DicomDirInterface::buildSeriesRecord(DcmDirectoryRecord *record, + DcmFileFormat *fileformat, + const OFFilename &sourceFilename) +{ + /* create new series record */ + if (record == NULL) + record = new DcmDirectoryRecord(ERT_Series, NULL, sourceFilename, fileformat); + if (record != NULL) + { + /* check whether new record is ok */ + if (record->error().good()) + { + DcmDataset *dataset = fileformat->getDataset(); + /* copy attribute values from dataset to series record */ + copyElementType1(dataset, DCM_Modality, record, sourceFilename); + copyElementType1(dataset, DCM_SeriesInstanceUID, record, sourceFilename); + /* use type 1C instead of 1 in order to avoid unwanted overwriting */ + copyElementType1C(dataset, DCM_SeriesNumber, record, sourceFilename); + if ((ApplicationProfile == AP_GeneralPurposeDVDJPEG) || + (ApplicationProfile == AP_GeneralPurposeDVDJPEG2000) || + (ApplicationProfile == AP_GeneralPurposeBDJPEG) || + (ApplicationProfile == AP_GeneralPurposeBDJPEG2000) || + (ApplicationProfile == AP_GeneralPurposeBDMPEG2MPatML) || + (ApplicationProfile == AP_GeneralPurposeBDMPEG2MPatHL) || + (ApplicationProfile == AP_GeneralPurposeBDMPEG4HPatLV41) || + (ApplicationProfile == AP_GeneralPurposeBDMPEG4HPatLV41BD) || + (ApplicationProfile == AP_USBandFlashJPEG) || + (ApplicationProfile == AP_USBandFlashJPEG2000) || + (ApplicationProfile == AP_MPEG2MPatMLDVD)) + { + /* additional type 1C keys specified by specific profiles */ + copyElementType1C(dataset, DCM_InstitutionName, record, sourceFilename); + copyElementType1C(dataset, DCM_InstitutionAddress, record, sourceFilename); + copyElementType1C(dataset, DCM_PerformingPhysicianName, record, sourceFilename); + } + else if ((ApplicationProfile == AP_BasicCardiac) || + (ApplicationProfile == AP_XrayAngiographic) || + (ApplicationProfile == AP_XrayAngiographicDVD)) + { + /* additional type 2 keys specified by specific profiles (type 1C or 3 in file) */ + copyStringWithDefault(dataset, DCM_InstitutionName, record, sourceFilename); + copyStringWithDefault(dataset, DCM_InstitutionAddress, record, sourceFilename); + copyStringWithDefault(dataset, DCM_PerformingPhysicianName, record, sourceFilename); + } + } else { + printRecordErrorMessage(record->error(), ERT_Series, "create"); + /* free memory */ + delete record; + record = NULL; + } + } else + DCMDATA_ERROR("out of memory (creating series record)"); + return record; +} + + +// create or update overlay record and copy required values from dataset +DcmDirectoryRecord *DicomDirInterface::buildOverlayRecord(DcmDirectoryRecord *record, + DcmFileFormat *fileformat, + const OFString &referencedFileID, + const OFFilename &sourceFilename) +{ + /* create new overlay record */ + if (record == NULL) + record = new DcmDirectoryRecord(ERT_Overlay, referencedFileID.c_str(), sourceFilename, fileformat); + if (record != NULL) + { + /* check whether new record is ok */ + if (record->error().good()) + { + DcmDataset *dataset = fileformat->getDataset(); + /* copy attribute values from dataset to overlay record */ + copyElementType1(dataset, DCM_RETIRED_OverlayNumber, record, sourceFilename); + } else { + printRecordErrorMessage(record->error(), ERT_Overlay, "create"); + /* free memory */ + delete record; + record = NULL; + } + } else + printRecordErrorMessage(EC_MemoryExhausted, ERT_Overlay, "create"); + return record; +} + + +// create or update modality lut record and copy required values from dataset +DcmDirectoryRecord *DicomDirInterface::buildModalityLutRecord(DcmDirectoryRecord *record, + DcmFileFormat *fileformat, + const OFString &referencedFileID, + const OFFilename &sourceFilename) +{ + /* create new modality lut record */ + if (record == NULL) + record = new DcmDirectoryRecord(ERT_ModalityLut, referencedFileID.c_str(), sourceFilename, fileformat); + if (record != NULL) + { + /* check whether new record is ok */ + if (record->error().good()) + { + DcmDataset *dataset = fileformat->getDataset(); + /* copy attribute values from dataset to modality lut record */ + copyElementType1(dataset, DCM_RETIRED_LUTNumber, record, sourceFilename); + } else { + printRecordErrorMessage(record->error(), ERT_ModalityLut, "create"); + /* free memory */ + delete record; + record = NULL; + } + } else + printRecordErrorMessage(EC_MemoryExhausted, ERT_ModalityLut, "create"); + return record; +} + + +// create or update voi lut record and copy required values from dataset +DcmDirectoryRecord *DicomDirInterface::buildVoiLutRecord(DcmDirectoryRecord *record, + DcmFileFormat *fileformat, + const OFString &referencedFileID, + const OFFilename &sourceFilename) +{ + /* create new voi lut record */ + if (record == NULL) + record = new DcmDirectoryRecord(ERT_VoiLut, referencedFileID.c_str(), sourceFilename, fileformat); + if (record != NULL) + { + /* check whether new record is ok */ + if (record->error().good()) + { + DcmDataset *dataset = fileformat->getDataset(); + /* copy attribute values from dataset to voi lut record */ + copyElementType1(dataset, DCM_RETIRED_LUTNumber, record, sourceFilename); + } else { + printRecordErrorMessage(record->error(), ERT_VoiLut, "create"); + /* free memory */ + delete record; + record = NULL; + } + } else + printRecordErrorMessage(EC_MemoryExhausted, ERT_VoiLut, "create"); + return record; +} + + +// create or update curve record and copy required values from dataset +DcmDirectoryRecord *DicomDirInterface::buildCurveRecord(DcmDirectoryRecord *record, + DcmFileFormat *fileformat, + const OFString &referencedFileID, + const OFFilename &sourceFilename) +{ + /* create new curve record */ + if (record == NULL) + record = new DcmDirectoryRecord(ERT_Curve, referencedFileID.c_str(), sourceFilename, fileformat); + if (record != NULL) + { + /* check whether new record is ok */ + if (record->error().good()) + { + DcmDataset *dataset = fileformat->getDataset(); + /* copy attribute values from dataset to curve record */ + copyElementType1(dataset, DCM_RETIRED_CurveNumber, record, sourceFilename); + } else { + printRecordErrorMessage(record->error(), ERT_Curve, "create"); + /* free memory */ + delete record; + record = NULL; + } + } else + printRecordErrorMessage(EC_MemoryExhausted, ERT_Curve, "create"); + return record; +} + + +// create or update structure reporting record and copy required values from dataset +DcmDirectoryRecord *DicomDirInterface::buildStructReportRecord(DcmDirectoryRecord *record, + DcmFileFormat *fileformat, + const OFString &referencedFileID, + const OFFilename &sourceFilename) +{ + /* create new struct report record */ + if (record == NULL) + record = new DcmDirectoryRecord(ERT_SRDocument, referencedFileID.c_str(), sourceFilename, fileformat); + if (record != NULL) + { + /* check whether new record is ok */ + if (record->error().good()) + { + DcmDataset *dataset = fileformat->getDataset(); + OFString tmpString; + /* copy attribute values from dataset to struct report record */ + copyElementType1(dataset, DCM_InstanceNumber, record, sourceFilename); + copyElementType1(dataset, DCM_CompletionFlag, record, sourceFilename); + copyElementType1(dataset, DCM_VerificationFlag, record, sourceFilename); + copyElementType1(dataset, DCM_ContentDate, record, sourceFilename); + copyElementType1(dataset, DCM_ContentTime, record, sourceFilename); + if (compare(getStringFromDataset(dataset, DCM_VerificationFlag, tmpString), "VERIFIED")) + { + /* VerificationDateTime is required if verification flag is VERIFIED, + retrieve most recent (= last) entry from VerifyingObserverSequence */ + DcmItem *ditem = NULL; + OFCondition status = dataset->findAndGetSequenceItem(DCM_VerifyingObserverSequence, ditem, -1 /*last*/); + if (status.good()) + copyElementType1(ditem, DCM_VerificationDateTime, record, sourceFilename); + else + printAttributeErrorMessage(DCM_VerifyingObserverSequence, status, "retrieve"); + } + copyElementType1(dataset, DCM_ConceptNameCodeSequence, record, sourceFilename); + addConceptModContentItems(record, dataset); + } else { + printRecordErrorMessage(record->error(), ERT_SRDocument, "create"); + /* free memory */ + delete record; + record = NULL; + } + } else + printRecordErrorMessage(EC_MemoryExhausted, ERT_SRDocument, "create"); + return record; +} + + +// create or update presentation state record and copy required values from dataset +DcmDirectoryRecord *DicomDirInterface::buildPresentationRecord(DcmDirectoryRecord *record, + DcmFileFormat *fileformat, + const OFString &referencedFileID, + const OFFilename &sourceFilename) +{ + /* create new presentation record */ + if (record == NULL) + record = new DcmDirectoryRecord(ERT_Presentation, referencedFileID.c_str(), sourceFilename, fileformat); + if (record != NULL) + { + /* check whether new record is ok */ + if (record->error().good()) + { + DcmDataset *dataset = fileformat->getDataset(); + /* copy attribute values from dataset to presentation record */ + copyElementType1(dataset, DCM_InstanceNumber, record, sourceFilename); + copyElementType1(dataset, DCM_ContentLabel, record, sourceFilename); + copyElementType2(dataset, DCM_ContentDescription, record, sourceFilename); + copyElementType1(dataset, DCM_PresentationCreationDate, record, sourceFilename); + copyElementType1(dataset, DCM_PresentationCreationTime, record, sourceFilename); + copyElementType2(dataset, DCM_ContentCreatorName, record, sourceFilename); + copyElementType1C(dataset, DCM_ReferencedSeriesSequence, record, sourceFilename); + addBlendingSequence(record, dataset); + } else { + printRecordErrorMessage(record->error(), ERT_Presentation, "create"); + /* free memory */ + delete record; + record = NULL; + } + } else + printRecordErrorMessage(EC_MemoryExhausted, ERT_Presentation, "create"); + return record; +} + + +// create or update waveform record and copy required values from dataset +DcmDirectoryRecord *DicomDirInterface::buildWaveformRecord(DcmDirectoryRecord *record, + DcmFileFormat *fileformat, + const OFString &referencedFileID, + const OFFilename &sourceFilename) +{ + /* create new waveform record */ + if (record == NULL) + record = new DcmDirectoryRecord(ERT_Waveform, referencedFileID.c_str(), sourceFilename, fileformat); + if (record != NULL) + { + /* check whether new record is ok */ + if (record->error().good()) + { + DcmDataset *dataset = fileformat->getDataset(); + /* copy attribute values from dataset to waveform record */ + copyElementType1(dataset, DCM_InstanceNumber, record, sourceFilename); + copyElementType1(dataset, DCM_ContentDate, record, sourceFilename); + copyElementType1(dataset, DCM_ContentTime, record, sourceFilename); + } else { + printRecordErrorMessage(record->error(), ERT_Waveform, "create"); + /* free memory */ + delete record; + record = NULL; + } + } else + printRecordErrorMessage(EC_MemoryExhausted, ERT_Waveform, "create"); + return record; +} + + +// create or update rt dose record and copy required values from dataset +DcmDirectoryRecord *DicomDirInterface::buildRTDoseRecord(DcmDirectoryRecord *record, + DcmFileFormat *fileformat, + const OFString &referencedFileID, + const OFFilename &sourceFilename) +{ + /* create new rt dose record */ + if (record == NULL) + record = new DcmDirectoryRecord(ERT_RTDose, referencedFileID.c_str(), sourceFilename, fileformat); + if (record != NULL) + { + /* check whether new record is ok */ + if (record->error().good()) + { + DcmDataset *dataset = fileformat->getDataset(); + /* copy attribute values from dataset to rt dose record */ + copyElementType1(dataset, DCM_InstanceNumber, record, sourceFilename); + copyElementType1(dataset, DCM_DoseSummationType, record, sourceFilename); + copyElementType3(dataset, DCM_DoseComment, record, sourceFilename); + /* copy existing icon image (if present) */ + copyElementType3(dataset, DCM_IconImageSequence, record, sourceFilename); + } else { + printRecordErrorMessage(record->error(), ERT_RTDose, "create"); + /* free memory */ + delete record; + record = NULL; + } + } else + printRecordErrorMessage(EC_MemoryExhausted, ERT_RTDose, "create"); + return record; +} + + +// create or update rt structure set record and copy required values from dataset +DcmDirectoryRecord *DicomDirInterface::buildRTStructureSetRecord(DcmDirectoryRecord *record, + DcmFileFormat *fileformat, + const OFString &referencedFileID, + const OFFilename &sourceFilename) +{ + /* create new rt structure set record */ + if (record == NULL) + record = new DcmDirectoryRecord(ERT_RTStructureSet, referencedFileID.c_str(), sourceFilename, fileformat); + if (record != NULL) + { + /* check whether new record is ok */ + if (record->error().good()) + { + DcmDataset *dataset = fileformat->getDataset(); + /* copy attribute values from dataset to rt structure set record */ + copyElementType1(dataset, DCM_InstanceNumber, record, sourceFilename); + copyElementType1(dataset, DCM_StructureSetLabel, record, sourceFilename); + copyElementType2(dataset, DCM_StructureSetDate, record, sourceFilename); + copyElementType2(dataset, DCM_StructureSetTime, record, sourceFilename); + } else { + printRecordErrorMessage(record->error(), ERT_RTStructureSet, "create"); + /* free memory */ + delete record; + record = NULL; + } + } else + printRecordErrorMessage(EC_MemoryExhausted, ERT_RTStructureSet, "create"); + return record; +} + + +// create or update rt plan record and copy required values from dataset +DcmDirectoryRecord *DicomDirInterface::buildRTPlanRecord(DcmDirectoryRecord *record, + DcmFileFormat *fileformat, + const OFString &referencedFileID, + const OFFilename &sourceFilename) +{ + /* create new rt plan record */ + if (record == NULL) + record = new DcmDirectoryRecord(ERT_RTPlan, referencedFileID.c_str(), sourceFilename, fileformat); + if (record != NULL) + { + /* check whether new record is ok */ + if (record->error().good()) + { + DcmDataset *dataset = fileformat->getDataset(); + /* copy attribute values from dataset to rt plan record */ + copyElementType1(dataset, DCM_InstanceNumber, record, sourceFilename); + copyElementType1(dataset, DCM_RTPlanLabel, record, sourceFilename); + copyElementType2(dataset, DCM_RTPlanDate, record, sourceFilename); + copyElementType2(dataset, DCM_RTPlanTime, record, sourceFilename); + } else { + printRecordErrorMessage(record->error(), ERT_RTPlan, "create"); + /* free memory */ + delete record; + record = NULL; + } + } else + printRecordErrorMessage(EC_MemoryExhausted, ERT_RTPlan, "create"); + return record; +} + + +// create or update rt treatment record and copy required values from dataset +DcmDirectoryRecord *DicomDirInterface::buildRTTreatmentRecord(DcmDirectoryRecord *record, + DcmFileFormat *fileformat, + const OFString &referencedFileID, + const OFFilename &sourceFilename) +{ + /* create new rt treatment record */ + if (record == NULL) + record = new DcmDirectoryRecord(ERT_RTTreatRecord, referencedFileID.c_str(), sourceFilename, fileformat); + if (record != NULL) + { + /* check whether new record is ok */ + if (record->error().good()) + { + DcmDataset *dataset = fileformat->getDataset(); + /* copy attribute values from dataset to rt treatment record */ + copyElementType1(dataset, DCM_InstanceNumber, record, sourceFilename); + copyElementType2(dataset, DCM_TreatmentDate, record, sourceFilename); + copyElementType2(dataset, DCM_TreatmentTime, record, sourceFilename); + } else { + printRecordErrorMessage(record->error(), ERT_RTTreatRecord, "create"); + /* free memory */ + delete record; + record = NULL; + } + } else + printRecordErrorMessage(EC_MemoryExhausted, ERT_RTTreatRecord, "create"); + return record; +} + + +// create or update stored print record and copy required values from dataset +DcmDirectoryRecord *DicomDirInterface::buildStoredPrintRecord(DcmDirectoryRecord *record, + DcmFileFormat *fileformat, + const OFString &referencedFileID, + const OFFilename &sourceFilename) +{ + /* create new stored print record */ + if (record == NULL) + record = new DcmDirectoryRecord(ERT_StoredPrint, referencedFileID.c_str(), sourceFilename, fileformat); + if (record != NULL) + { + /* check whether new record is ok */ + if (record->error().good()) + { + DcmDataset *dataset = fileformat->getDataset(); + /* copy attribute values from dataset to stored print record */ + copyElementType2(dataset, DCM_InstanceNumber, record, sourceFilename); + /* IconImageSequence (type 3) is not created for the referenced images */ + } else { + printRecordErrorMessage(record->error(), ERT_StoredPrint, "create"); + /* free memory */ + delete record; + record = NULL; + } + } else + printRecordErrorMessage(EC_MemoryExhausted, ERT_StoredPrint, "create"); + return record; +} + + +// create or update key object doc record and copy required values from dataset +DcmDirectoryRecord *DicomDirInterface::buildKeyObjectDocRecord(DcmDirectoryRecord *record, + DcmFileFormat *fileformat, + const OFString &referencedFileID, + const OFFilename &sourceFilename) +{ + /* create new key object doc record */ + if (record == NULL) + record = new DcmDirectoryRecord(ERT_KeyObjectDoc, referencedFileID.c_str(), sourceFilename, fileformat); + if (record != NULL) + { + /* check whether new record is ok */ + if (record->error().good()) + { + DcmDataset *dataset = fileformat->getDataset(); + /* copy attribute values from dataset to key object doc record */ + copyElementType1(dataset, DCM_InstanceNumber, record, sourceFilename); + copyElementType1(dataset, DCM_ContentDate, record, sourceFilename); + copyElementType1(dataset, DCM_ContentTime, record, sourceFilename); + copyElementType1(dataset, DCM_ConceptNameCodeSequence, record, sourceFilename); + addConceptModContentItems(record, dataset); + } else { + printRecordErrorMessage(record->error(), ERT_KeyObjectDoc, "create"); + /* free memory */ + delete record; + record = NULL; + } + } else + printRecordErrorMessage(EC_MemoryExhausted, ERT_KeyObjectDoc, "create"); + return record; +} + + +// create or update registration record and copy required values from dataset +DcmDirectoryRecord *DicomDirInterface::buildRegistrationRecord(DcmDirectoryRecord *record, + DcmFileFormat *fileformat, + const OFString &referencedFileID, + const OFFilename &sourceFilename) +{ + /* create new registration record */ + if (record == NULL) + record = new DcmDirectoryRecord(ERT_Registration, referencedFileID.c_str(), sourceFilename, fileformat); + if (record != NULL) + { + /* check whether new record is ok */ + if (record->error().good()) + { + DcmDataset *dataset = fileformat->getDataset(); + /* copy attribute values from dataset to registration record */ + copyElementType1(dataset, DCM_ContentDate, record, sourceFilename); + copyElementType1(dataset, DCM_ContentTime, record, sourceFilename); + copyElementType1(dataset, DCM_InstanceNumber, record, sourceFilename); + copyElementType1(dataset, DCM_ContentLabel, record, sourceFilename); + copyElementType2(dataset, DCM_ContentDescription, record, sourceFilename); + copyElementType2(dataset, DCM_ContentCreatorName, record, sourceFilename); + } else { + printRecordErrorMessage(record->error(), ERT_Registration, "create"); + /* free memory */ + delete record; + record = NULL; + } + } else + printRecordErrorMessage(EC_MemoryExhausted, ERT_Registration, "create"); + return record; +} + + +// create or update fiducial record and copy required values from dataset +DcmDirectoryRecord *DicomDirInterface::buildFiducialRecord(DcmDirectoryRecord *record, + DcmFileFormat *fileformat, + const OFString &referencedFileID, + const OFFilename &sourceFilename) +{ + /* create new fiducial record */ + if (record == NULL) + record = new DcmDirectoryRecord(ERT_Fiducial, referencedFileID.c_str(), sourceFilename, fileformat); + if (record != NULL) + { + /* check whether new record is ok */ + if (record->error().good()) + { + DcmDataset *dataset = fileformat->getDataset(); + /* copy attribute values from dataset to fiducial record */ + copyElementType1(dataset, DCM_ContentDate, record, sourceFilename); + copyElementType1(dataset, DCM_ContentTime, record, sourceFilename); + copyElementType1(dataset, DCM_InstanceNumber, record, sourceFilename); + copyElementType1(dataset, DCM_ContentLabel, record, sourceFilename); + copyElementType2(dataset, DCM_ContentDescription, record, sourceFilename); + copyElementType2(dataset, DCM_ContentCreatorName, record, sourceFilename); + } else { + printRecordErrorMessage(record->error(), ERT_Fiducial, "create"); + /* free memory */ + delete record; + record = NULL; + } + } else + printRecordErrorMessage(EC_MemoryExhausted, ERT_Fiducial, "create"); + return record; +} + + +// create or update raw data record and copy required values from dataset +DcmDirectoryRecord *DicomDirInterface::buildRawDataRecord(DcmDirectoryRecord *record, + DcmFileFormat *fileformat, + const OFString &referencedFileID, + const OFFilename &sourceFilename) +{ + /* create new raw data record */ + if (record == NULL) + record = new DcmDirectoryRecord(ERT_RawData, referencedFileID.c_str(), sourceFilename, fileformat); + if (record != NULL) + { + /* check whether new record is ok */ + if (record->error().good()) + { + DcmDataset *dataset = fileformat->getDataset(); + /* copy attribute values from dataset to raw data record */ + copyElementType1(dataset, DCM_ContentDate, record, sourceFilename); + copyElementType1(dataset, DCM_ContentTime, record, sourceFilename); + copyElementType2(dataset, DCM_InstanceNumber, record, sourceFilename); + /* IconImageSequence (type 3) is not created for the raw data */ + } else { + printRecordErrorMessage(record->error(), ERT_RawData, "create"); + /* free memory */ + delete record; + record = NULL; + } + } else + printRecordErrorMessage(EC_MemoryExhausted, ERT_RawData, "create"); + return record; +} + + +// create or update spectroscopy record and copy required values from dataset +DcmDirectoryRecord *DicomDirInterface::buildSpectroscopyRecord(DcmDirectoryRecord *record, + DcmFileFormat *fileformat, + const OFString &referencedFileID, + const OFFilename &sourceFilename) +{ + /* create new spectroscopy record */ + if (record == NULL) + record = new DcmDirectoryRecord(ERT_Spectroscopy, referencedFileID.c_str(), sourceFilename, fileformat); + if (record != NULL) + { + /* check whether new record is ok */ + if (record->error().good()) + { + DcmDataset *dataset = fileformat->getDataset(); + /* copy attribute values from dataset to spectroscopy record */ + copyElementType1(dataset, DCM_ImageType, record, sourceFilename); + copyElementType1(dataset, DCM_ContentDate, record, sourceFilename); + copyElementType1(dataset, DCM_ContentTime, record, sourceFilename); + copyElementType1(dataset, DCM_InstanceNumber, record, sourceFilename); + copyElementType1C(dataset, DCM_ReferencedImageEvidenceSequence, record, sourceFilename); + copyElementType1(dataset, DCM_NumberOfFrames, record, sourceFilename); + copyElementType1(dataset, DCM_Rows, record, sourceFilename); + copyElementType1(dataset, DCM_Columns, record, sourceFilename); + copyElementType1(dataset, DCM_DataPointRows, record, sourceFilename); + copyElementType1(dataset, DCM_DataPointColumns, record, sourceFilename); + /* IconImageSequence (type 3) is not created for the spectroscopy data */ + /* application profile specific attributes */ + if ((ApplicationProfile == AP_GeneralPurposeDVDJPEG) || + (ApplicationProfile == AP_GeneralPurposeDVDJPEG2000) || + (ApplicationProfile == AP_GeneralPurposeBDJPEG) || + (ApplicationProfile == AP_GeneralPurposeBDJPEG2000) || + (ApplicationProfile == AP_GeneralPurposeBDMPEG2MPatML) || + (ApplicationProfile == AP_GeneralPurposeBDMPEG2MPatHL) || + (ApplicationProfile == AP_GeneralPurposeBDMPEG4HPatLV41) || + (ApplicationProfile == AP_GeneralPurposeBDMPEG4HPatLV41BD) || + (ApplicationProfile == AP_USBandFlashJPEG) || + (ApplicationProfile == AP_USBandFlashJPEG2000)) + { + copyElementType1(dataset, DCM_Rows, record, sourceFilename); + copyElementType1(dataset, DCM_Columns, record, sourceFilename); + copyElementType1C(dataset, DCM_FrameOfReferenceUID, record, sourceFilename); + copyElementType1C(dataset, DCM_SynchronizationFrameOfReferenceUID, record, sourceFilename); + copyElementType1C(dataset, DCM_NumberOfFrames, record, sourceFilename); + copyElementType1C(dataset, DCM_AcquisitionTimeSynchronized, record, sourceFilename); + copyElementType1C(dataset, DCM_AcquisitionDateTime, record, sourceFilename); + // also need to examine functional groups for the following attributes + copyElementType1CFromDatasetOrSequenceItem(dataset, DCM_ReferencedImageSequence, DCM_SharedFunctionalGroupsSequence, record, sourceFilename); + copyElementType1CFromDatasetOrSequenceItem(dataset, DCM_ImagePositionPatient, DCM_SharedFunctionalGroupsSequence, record, sourceFilename); + copyElementType1CFromDatasetOrSequenceItem(dataset, DCM_ImageOrientationPatient, DCM_SharedFunctionalGroupsSequence, record, sourceFilename); + copyElementType1CFromDatasetOrSequenceItem(dataset, DCM_PixelSpacing, DCM_SharedFunctionalGroupsSequence, record, sourceFilename); + } + } else { + printRecordErrorMessage(record->error(), ERT_Spectroscopy, "create"); + /* free memory */ + delete record; + record = NULL; + } + } else + printRecordErrorMessage(EC_MemoryExhausted, ERT_Spectroscopy, "create"); + return record; +} + + +// create or update encap doc record and copy required values from dataset +DcmDirectoryRecord *DicomDirInterface::buildEncapDocRecord(DcmDirectoryRecord *record, + DcmFileFormat *fileformat, + const OFString &referencedFileID, + const OFFilename &sourceFilename) +{ + /* create new encap doc record */ + if (record == NULL) + record = new DcmDirectoryRecord(ERT_EncapDoc, referencedFileID.c_str(), sourceFilename, fileformat); + if (record != NULL) + { + /* check whether new record is ok */ + if (record->error().good()) + { + DcmDataset *dataset = fileformat->getDataset(); + /* copy attribute values from dataset to encap doc record */ + copyElementType2(dataset, DCM_ContentDate, record, sourceFilename); + copyElementType2(dataset, DCM_ContentTime, record, sourceFilename); + copyElementType1(dataset, DCM_InstanceNumber, record, sourceFilename); + copyElementType2(dataset, DCM_DocumentTitle, record, sourceFilename); + /* required if encapsulated document is an HL7 Structured Document */ + copyElementType1C(dataset, DCM_HL7InstanceIdentifier, record, sourceFilename); + /* baseline context group 7020 is not checked */ + copyElementType2(dataset, DCM_ConceptNameCodeSequence, record, sourceFilename); + copyElementType1(dataset, DCM_MIMETypeOfEncapsulatedDocument, record, sourceFilename); + } else { + printRecordErrorMessage(record->error(), ERT_EncapDoc, "create"); + /* free memory */ + delete record; + record = NULL; + } + } else + printRecordErrorMessage(EC_MemoryExhausted, ERT_RawData, "create"); + return record; +} + + +// create or update value map record and copy required values from dataset +DcmDirectoryRecord *DicomDirInterface::buildValueMapRecord(DcmDirectoryRecord *record, + DcmFileFormat *fileformat, + const OFString &referencedFileID, + const OFFilename &sourceFilename) +{ + /* create new value map record */ + if (record == NULL) + record = new DcmDirectoryRecord(ERT_ValueMap, referencedFileID.c_str(), sourceFilename, fileformat); + if (record != NULL) + { + /* check whether new record is ok */ + if (record->error().good()) + { + DcmDataset *dataset = fileformat->getDataset(); + /* copy attribute values from dataset to value map record */ + copyElementType1(dataset, DCM_ContentDate, record, sourceFilename); + copyElementType1(dataset, DCM_ContentTime, record, sourceFilename); + copyElementType1(dataset, DCM_InstanceNumber, record, sourceFilename); + copyElementType1(dataset, DCM_ContentLabel, record, sourceFilename); + copyElementType2(dataset, DCM_ContentDescription, record, sourceFilename); + copyElementType2(dataset, DCM_ContentCreatorName, record, sourceFilename); + } else { + printRecordErrorMessage(record->error(), ERT_ValueMap, "create"); + /* free memory */ + delete record; + record = NULL; + } + } else + printRecordErrorMessage(EC_MemoryExhausted, ERT_ValueMap, "create"); + return record; +} + + +// create or update hanging protocol record and copy required values from dataset +DcmDirectoryRecord *DicomDirInterface::buildHangingProtocolRecord(DcmDirectoryRecord *record, + DcmFileFormat *fileformat, + const OFString &referencedFileID, + const OFFilename &sourceFilename) +{ + /* create new hanging protocol record */ + if (record == NULL) + record = new DcmDirectoryRecord(ERT_HangingProtocol, referencedFileID.c_str(), sourceFilename, fileformat); + if (record != NULL) + { + /* check whether new record is ok */ + if (record->error().good()) + { + DcmDataset *dataset = fileformat->getDataset(); + copyElementType1(dataset, DCM_HangingProtocolName, record, sourceFilename); + copyElementType1(dataset, DCM_HangingProtocolDescription, record, sourceFilename); + copyElementType1(dataset, DCM_HangingProtocolLevel, record, sourceFilename); + copyElementType1(dataset, DCM_HangingProtocolCreator, record, sourceFilename); + copyElementType1(dataset, DCM_HangingProtocolCreationDateTime, record, sourceFilename); + // open issue: shall we do further checks on the sequence content? + copyElementType1(dataset, DCM_HangingProtocolDefinitionSequence, record, sourceFilename); + copyElementType1(dataset, DCM_NumberOfPriorsReferenced, record, sourceFilename); + copyElementType2(dataset, DCM_HangingProtocolUserIdentificationCodeSequence, record, sourceFilename); + } else { + printRecordErrorMessage(record->error(), ERT_HangingProtocol, "create"); + /* free memory */ + delete record; + record = NULL; + } + } else + DCMDATA_ERROR("out of memory (creating patient record)"); + return record; +} + + +// create or update stereometric record and copy required values from dataset +DcmDirectoryRecord *DicomDirInterface::buildStereometricRecord(DcmDirectoryRecord *record, + DcmFileFormat *fileformat, + const OFString &referencedFileID, + const OFFilename &sourceFilename) +{ + /* create new value map record */ + if (record == NULL) + record = new DcmDirectoryRecord(ERT_Stereometric, referencedFileID.c_str(), sourceFilename, fileformat); + if (record != NULL) + { + /* check whether new record is ok */ + if (record->error().good()) + { + /* nothing to do */ + } else { + printRecordErrorMessage(record->error(), ERT_Stereometric, "create"); + /* free memory */ + delete record; + record = NULL; + } + } else + printRecordErrorMessage(EC_MemoryExhausted, ERT_Stereometric, "create"); + return record; +} + + +// create or update palette record and copy required values from dataset +DcmDirectoryRecord *DicomDirInterface::buildPaletteRecord(DcmDirectoryRecord *record, + DcmFileFormat *fileformat, + const OFString &referencedFileID, + const OFFilename &sourceFilename) +{ + /* create new palette record */ + if (record == NULL) + record = new DcmDirectoryRecord(ERT_Palette, referencedFileID.c_str(), sourceFilename, fileformat); + if (record != NULL) + { + /* check whether new record is ok */ + if (record->error().good()) + { + DcmDataset *dataset = fileformat->getDataset(); + /* copy attribute values from dataset to palette record */ + copyElementType1(dataset, DCM_ContentLabel, record, sourceFilename); + copyElementType2(dataset, DCM_ContentDescription, record, sourceFilename); + } else { + printRecordErrorMessage(record->error(), ERT_Palette, "create"); + /* free memory */ + delete record; + record = NULL; + } + } else + printRecordErrorMessage(EC_MemoryExhausted, ERT_Palette, "create"); + return record; +} + + +// create or update surface record and copy required values from dataset +DcmDirectoryRecord *DicomDirInterface::buildSurfaceRecord(DcmDirectoryRecord *record, + DcmFileFormat *fileformat, + const OFString &referencedFileID, + const OFFilename &sourceFilename) +{ + /* create new surface record */ + if (record == NULL) + record = new DcmDirectoryRecord(ERT_Surface, referencedFileID.c_str(), sourceFilename, fileformat); + if (record != NULL) + { + /* check whether new record is ok */ + if (record->error().good()) + { + DcmDataset *dataset = fileformat->getDataset(); + /* copy attribute values from dataset to surface record */ + copyElementType1(dataset, DCM_ContentDate, record, sourceFilename); + copyElementType1(dataset, DCM_ContentTime, record, sourceFilename); + copyElementType1(dataset, DCM_InstanceNumber, record, sourceFilename); + copyElementType1(dataset, DCM_ContentLabel, record, sourceFilename); + copyElementType2(dataset, DCM_ContentDescription, record, sourceFilename); + copyElementType2(dataset, DCM_ContentCreatorName, record, sourceFilename); + } else { + printRecordErrorMessage(record->error(), ERT_Surface, "create"); + /* free memory */ + delete record; + record = NULL; + } + } else + printRecordErrorMessage(EC_MemoryExhausted, ERT_Surface, "create"); + return record; +} + + +// create or update measurement record and copy required values from dataset +DcmDirectoryRecord *DicomDirInterface::buildMeasurementRecord(DcmDirectoryRecord *record, + DcmFileFormat *fileformat, + const OFString &referencedFileID, + const OFFilename &sourceFilename) +{ + /* create new measurement record */ + if (record == NULL) + record = new DcmDirectoryRecord(ERT_Measurement, referencedFileID.c_str(), sourceFilename, fileformat); + if (record != NULL) + { + /* check whether new record is ok */ + if (record->error().good()) + { + DcmDataset *dataset = fileformat->getDataset(); + /* copy attribute values from dataset to measurement record */ + copyElementType1(dataset, DCM_ContentDate, record, sourceFilename); + copyElementType1(dataset, DCM_ContentTime, record, sourceFilename); + copyElementType1(dataset, DCM_InstanceNumber, record, sourceFilename); + copyElementType1(dataset, DCM_ContentLabel, record, sourceFilename); + copyElementType2(dataset, DCM_ContentDescription, record, sourceFilename); + copyElementType2(dataset, DCM_ContentCreatorName, record, sourceFilename); + } else { + printRecordErrorMessage(record->error(), ERT_Measurement, "create"); + /* free memory */ + delete record; + record = NULL; + } + } else + printRecordErrorMessage(EC_MemoryExhausted, ERT_Measurement, "create"); + return record; +} + + +// create or update implant record and copy required values from dataset +DcmDirectoryRecord *DicomDirInterface::buildImplantRecord(DcmDirectoryRecord *record, + DcmFileFormat *fileformat, + const OFString &referencedFileID, + const OFFilename &sourceFilename) +{ + /* create new implant record */ + if (record == NULL) + record = new DcmDirectoryRecord(ERT_Implant, referencedFileID.c_str(), sourceFilename, fileformat); + if (record != NULL) + { + /* check whether new record is ok */ + if (record->error().good()) + { + DcmDataset *dataset = fileformat->getDataset(); + /* copy attribute values from dataset to implant record */ + copyElementType1(dataset, DCM_Manufacturer, record, sourceFilename); + copyElementType1(dataset, DCM_ImplantName, record, sourceFilename); + copyElementType1C(dataset, DCM_ImplantSize, record, sourceFilename); + copyElementType1(dataset, DCM_ImplantPartNumber, record, sourceFilename); + } else { + printRecordErrorMessage(record->error(), ERT_Implant, "create"); + /* free memory */ + delete record; + record = NULL; + } + } else + printRecordErrorMessage(EC_MemoryExhausted, ERT_Implant, "create"); + return record; +} + + +// create or update implant group record and copy required values from dataset +DcmDirectoryRecord *DicomDirInterface::buildImplantGroupRecord(DcmDirectoryRecord *record, + DcmFileFormat *fileformat, + const OFString &referencedFileID, + const OFFilename &sourceFilename) +{ + /* create new implant group record */ + if (record == NULL) + record = new DcmDirectoryRecord(ERT_ImplantGroup, referencedFileID.c_str(), sourceFilename, fileformat); + if (record != NULL) + { + /* check whether new record is ok */ + if (record->error().good()) + { + DcmDataset *dataset = fileformat->getDataset(); + /* copy attribute values from dataset to implant group record */ + copyElementType1(dataset, DCM_ImplantAssemblyTemplateName, record, sourceFilename); + copyElementType1(dataset, DCM_ImplantAssemblyTemplateIssuer, record, sourceFilename); + copyElementType1(dataset, DCM_ProcedureTypeCodeSequence, record, sourceFilename); + } else { + printRecordErrorMessage(record->error(), ERT_ImplantGroup, "create"); + /* free memory */ + delete record; + record = NULL; + } + } else + printRecordErrorMessage(EC_MemoryExhausted, ERT_ImplantGroup, "create"); + return record; +} + + +// create or update implant assy record and copy required values from dataset +DcmDirectoryRecord *DicomDirInterface::buildImplantAssyRecord(DcmDirectoryRecord *record, + DcmFileFormat *fileformat, + const OFString &referencedFileID, + const OFFilename &sourceFilename) +{ + /* create new implant assy record */ + if (record == NULL) + record = new DcmDirectoryRecord(ERT_ImplantAssy, referencedFileID.c_str(), sourceFilename, fileformat); + if (record != NULL) + { + /* check whether new record is ok */ + if (record->error().good()) + { + DcmDataset *dataset = fileformat->getDataset(); + /* copy attribute values from dataset to implant assy record */ + copyElementType1(dataset, DCM_ImplantTemplateGroupName, record, sourceFilename); + copyElementType3(dataset, DCM_ImplantTemplateGroupDescription, record, sourceFilename); + copyElementType1(dataset, DCM_ImplantTemplateGroupIssuer, record, sourceFilename); + } else { + printRecordErrorMessage(record->error(), ERT_ImplantAssy, "create"); + /* free memory */ + delete record; + record = NULL; + } + } else + printRecordErrorMessage(EC_MemoryExhausted, ERT_ImplantAssy, "create"); + return record; +} + + +// create or update plan record and copy required values from dataset +DcmDirectoryRecord *DicomDirInterface::buildPlanRecord(DcmDirectoryRecord *record, + DcmFileFormat *fileformat, + const OFString &referencedFileID, + const OFFilename &sourceFilename) +{ + /* create new plan record */ + if (record == NULL) + record = new DcmDirectoryRecord(ERT_Plan, referencedFileID.c_str(), sourceFilename, fileformat); + if (record != NULL) + { + /* check whether new record is ok */ + if (record->error().good()) + { + /* nothing to do */ + } else { + printRecordErrorMessage(record->error(), ERT_Plan, "create"); + /* free memory */ + delete record; + record = NULL; + } + } else + printRecordErrorMessage(EC_MemoryExhausted, ERT_Plan, "create"); + return record; +} + + +// create or update surface scan record and copy required values from dataset +DcmDirectoryRecord *DicomDirInterface::buildSurfaceScanRecord(DcmDirectoryRecord *record, + DcmFileFormat *fileformat, + const OFString &referencedFileID, + const OFFilename &sourceFilename) +{ + /* create new surface scan record */ + if (record == NULL) + record = new DcmDirectoryRecord(ERT_SurfaceScan, referencedFileID.c_str(), sourceFilename, fileformat); + if (record != NULL) + { + /* check whether new record is ok */ + if (record->error().good()) + { + DcmDataset *dataset = fileformat->getDataset(); + /* copy attribute values from dataset to surface scan record */ + copyElementType1(dataset, DCM_ContentDate, record, sourceFilename); + copyElementType1(dataset, DCM_ContentTime, record, sourceFilename); + } else { + printRecordErrorMessage(record->error(), ERT_SurfaceScan, "create"); + /* free memory */ + delete record; + record = NULL; + } + } else + printRecordErrorMessage(EC_MemoryExhausted, ERT_SurfaceScan, "create"); + return record; +} + + +// create or update image record and copy required values from dataset +DcmDirectoryRecord *DicomDirInterface::buildImageRecord(DcmDirectoryRecord *record, + DcmFileFormat *fileformat, + const OFString &referencedFileID, + const OFFilename &sourceFilename) +{ + /* create new image record */ + if (record == NULL) + record = new DcmDirectoryRecord(ERT_Image, referencedFileID.c_str(), sourceFilename, fileformat); + if (record != NULL) + { + /* check whether new record is ok */ + if (record->error().good()) + { + DcmDataset *dataset = fileformat->getDataset(); + OFBool iconImage = IconImageMode; + unsigned int iconSize = (IconSize == 0) ? 64 : IconSize; + /* Icon Image Sequence required for particular profiles */ + OFBool iconRequired = OFFalse; + /* copy attribute values from dataset to image record */ + copyElementType1(dataset, DCM_InstanceNumber, record, sourceFilename); + /* application profile specific attributes */ + switch (ApplicationProfile) + { + case AP_GeneralPurpose: + copyElementType1C(dataset, DCM_ImageType, record, sourceFilename); + copyElementType1C(dataset, DCM_ReferencedImageSequence, record, sourceFilename); + break; + case AP_GeneralPurposeDVDJPEG: + case AP_GeneralPurposeDVDJPEG2000: + case AP_GeneralPurposeBDJPEG: + case AP_GeneralPurposeBDJPEG2000: + case AP_GeneralPurposeBDMPEG2MPatML: + case AP_GeneralPurposeBDMPEG2MPatHL: + case AP_GeneralPurposeBDMPEG4HPatLV41: + case AP_GeneralPurposeBDMPEG4HPatLV41BD: + case AP_USBandFlashJPEG: + case AP_USBandFlashJPEG2000: + copyElementType1(dataset, DCM_Rows, record, sourceFilename); + copyElementType1(dataset, DCM_Columns, record, sourceFilename); + copyElementType1C(dataset, DCM_ImageType, record, sourceFilename); + copyElementType1C(dataset, DCM_CalibrationImage, record, sourceFilename); + copyElementType1C(dataset, DCM_LossyImageCompressionRatio, record, sourceFilename); + copyElementType1C(dataset, DCM_FrameOfReferenceUID, record, sourceFilename); + copyElementType1C(dataset, DCM_SynchronizationFrameOfReferenceUID, record, sourceFilename); + copyElementType1C(dataset, DCM_NumberOfFrames, record, sourceFilename); + copyElementType1C(dataset, DCM_AcquisitionTimeSynchronized, record, sourceFilename); + copyElementType1C(dataset, DCM_AcquisitionDateTime, record, sourceFilename); + // also need to examine functional groups for the following attributes + copyElementType1CFromDatasetOrSequenceItem(dataset, DCM_ReferencedImageSequence, DCM_SharedFunctionalGroupsSequence, record, sourceFilename); + copyElementType1CFromDatasetOrSequenceItem(dataset, DCM_ImagePositionPatient, DCM_SharedFunctionalGroupsSequence, record, sourceFilename); + copyElementType1CFromDatasetOrSequenceItem(dataset, DCM_ImageOrientationPatient, DCM_SharedFunctionalGroupsSequence, record, sourceFilename); + copyElementType1CFromDatasetOrSequenceItem(dataset, DCM_PixelSpacing, DCM_SharedFunctionalGroupsSequence, record, sourceFilename); + break; + case AP_MPEG2MPatMLDVD: + copyElementType1(dataset, DCM_Rows, record, sourceFilename); + copyElementType1(dataset, DCM_Columns, record, sourceFilename); + copyElementType1C(dataset, DCM_ImageType, record, sourceFilename); + copyElementType1C(dataset, DCM_LossyImageCompressionRatio, record, sourceFilename); + break; + case AP_XrayAngiographic: + case AP_XrayAngiographicDVD: + copyElementType1C(dataset, DCM_LossyImageCompressionRatio, record, sourceFilename); + case AP_BasicCardiac: + { + OFString tmpString; + OFBool xaImage = compare(getStringFromDataset(dataset, DCM_SOPClassUID, tmpString), UID_XRayAngiographicImageStorage); + if (xaImage) + { + /* type 1C: required for XA images (type 1 for Basic Cardiac Profile) */ + copyElementType1(dataset, DCM_ImageType, record, sourceFilename); + /* type 1C: required if ImageType value 3 is "BIPLANE A" or "BIPLANE B" */ + getStringComponentFromDataset(dataset, DCM_ImageType, tmpString, 2); + if (compare(tmpString, "BIPLANE A") || compare(tmpString, "BIPLANE B")) + copyElementType1(dataset, DCM_ReferencedImageSequence, record, sourceFilename); + } + /* additional type 2 keys specified by specific profiles (type 3 in image IOD) */ + copyStringWithDefault(dataset, DCM_CalibrationImage, record, sourceFilename); + /* icon images */ + iconImage = OFTrue; + iconRequired = OFTrue; + iconSize = 128; + } + break; + case AP_CTandMR: + copyElementType1(dataset, DCM_Rows, record, sourceFilename); + copyElementType1(dataset, DCM_Columns, record, sourceFilename); + copyElementType1C(dataset, DCM_ReferencedImageSequence, record, sourceFilename); + copyElementType1C(dataset, DCM_ImagePositionPatient, record, sourceFilename); + copyElementType1C(dataset, DCM_ImageOrientationPatient, record, sourceFilename); + copyElementType1C(dataset, DCM_FrameOfReferenceUID, record, sourceFilename); + copyElementType1C(dataset, DCM_PixelSpacing, record, sourceFilename); + /* icon images */ + iconImage = OFTrue; + iconSize = 64; + break; + default: + /* no additional keys */ + break; + } + /* create icon images */ + if (iconImage) + { + OFCondition status = addIconImage(record, dataset, iconSize, sourceFilename); + if (status.bad()) + { + /* report error or warning */ + if (iconRequired) + DCMDATA_ERROR("cannot create IconImageSequence"); + else + DCMDATA_WARN("cannot create IconImageSequence"); + } + } + } else { + printRecordErrorMessage(record->error(), ERT_Series, "create"); + /* free memory */ + delete record; + record = NULL; + } + } else + DCMDATA_ERROR("out of memory (creating image record)"); + return record; +} + + +// create icon image from PGM file +OFBool DicomDirInterface::getIconFromFile(const OFFilename &filename, + Uint8 *pixel, + const unsigned long count, + const unsigned int width, + const unsigned int height) +{ + OFBool result = OFFalse; + /* check buffer and size */ + if (!filename.isEmpty() && (pixel != NULL) && (count >= width * height)) + { + /* open specified file */ + OFFile file; + if (file.fopen(filename, "rb")) + { + /* according to the pgm format no line should be longer than 70 characters */ + const int maxline = 256; + char line[maxline]; + /* read magic number */ + if ((file.fgets(line, maxline) != NULL) && (strcmp(line, "P5\n") == 0)) + { + OFBool corrupt = OFTrue; + if ((file.fgets(line, maxline) != NULL) && (line[0] != '\0')) + { + unsigned int pgmWidth, pgmHeight = 0; + /* skip optional comment line and get width and height */ + if (((*line != '#') || (file.fgets(line, maxline) != NULL)) && + (sscanf(line, "%u %u", &pgmWidth, &pgmHeight) > 0) && (pgmWidth > 0) && (pgmHeight > 0)) + { + unsigned int pgmMax = 0; + /* get maximum gray value */ + if ((file.fgets(line, maxline) != NULL) && (sscanf(line, "%u", &pgmMax) > 0) && (pgmMax == 255)) + { + const unsigned long pgmSize = pgmWidth * pgmHeight; + Uint8 *pgmData = new Uint8[pgmSize]; + if (pgmData != NULL) + { + /* get pgm image data */ + if (file.fread(pgmData, sizeof(Uint8), OFstatic_cast(size_t, pgmSize)) == pgmSize) + { + /* if already scaled, just copy the bitmap */ + if ((width == pgmWidth) && (height == pgmHeight) && (count == pgmSize)) + { + OFBitmanipTemplate::copyMem(pgmData, pixel, count); + result = OFTrue; + } + else if (ImagePlugin != NULL) + { + /* scale image to requested size */ + result = ImagePlugin->scaleData(pgmData, pgmWidth, pgmHeight, pixel, width, height); + } + if (!result) + DCMDATA_ERROR("cannot scale external icon, no image support available"); + corrupt = OFFalse; + } + /* free memory */ + delete[] pgmData; + } else { + DCMDATA_ERROR(OFCondition(EC_MemoryExhausted).text() << ": cannot allocate memory for pgm pixel data"); + /* avoid double reporting of error message */ + corrupt = OFFalse; + } + } + } + } + if (corrupt) + DCMDATA_ERROR("corrupt file format for external icon (not pgm binary)"); + } else + DCMDATA_ERROR("wrong file format for external icon (pgm required)"); + } else + DCMDATA_ERROR("cannot open file for external icon: " << filename); + } + return result; +} + + +// create icon image from DICOM dataset +OFBool DicomDirInterface::getIconFromDataset(DcmItem *dataset, + Uint8 *pixel, + const unsigned long count, + const unsigned int width, + const unsigned int height) +{ + OFBool result = OFFalse; + /* check parameters (incl. availability of image plugin) */ + if ((ImagePlugin != NULL) && (dataset != NULL) && (pixel != NULL) && (count >= width * height)) + { + /* choose representative frame */ + long fCount, frame; + dataset->findAndGetLongInt(DCM_NumberOfFrames, fCount); + dataset->findAndGetLongInt(DCM_RepresentativeFrameNumber, frame); + if (fCount <= 0) + fCount = 1; + if (frame <= 0) + { + if (fCount > 3) + frame = fCount / 3; // recommended in PS3.11 + else + frame = 1; + } else if (frame > fCount) + frame = fCount; + /* scale image (if required) and retrieve pixel data from dataset */ + result = ImagePlugin->scaleImage(dataset, pixel, count, OFstatic_cast(unsigned long, frame), + width, height, (fCount == 1) /*decompressAll*/); + } + return result; +} + + +// add icon image sequence to record +OFCondition DicomDirInterface::addIconImage(DcmDirectoryRecord *record, + DcmItem *dataset, + const unsigned int size, + const OFFilename &sourceFilename) +{ + OFCondition result = EC_IllegalParameter; + /* check parameters first */ + if ((record != NULL) && (dataset != NULL)) + { + DcmItem *ditem = NULL; + /* create icon image sequence with one item */ + result = record->findOrCreateSequenceItem(DCM_IconImageSequence, ditem); + if (result.good()) + { + const unsigned int width = size; + const unsigned int height = size; + const unsigned long count = width * height; + /* Image Pixel Module */ + ditem->putAndInsertUint16(DCM_SamplesPerPixel, 1); + ditem->putAndInsertString(DCM_PhotometricInterpretation, "MONOCHROME2"); + ditem->putAndInsertUint16(DCM_Rows, OFstatic_cast(Uint16, height)); + ditem->putAndInsertUint16(DCM_Columns, OFstatic_cast(Uint16, width)); + ditem->putAndInsertUint16(DCM_BitsAllocated, 8); + ditem->putAndInsertUint16(DCM_BitsStored, 8); + ditem->putAndInsertUint16(DCM_HighBit, 7); + ditem->putAndInsertUint16(DCM_PixelRepresentation, 0); + /* Pixel Data */ + Uint8 *pixel = new Uint8[count]; + if (pixel != NULL) + { + OFBool iconOk = OFFalse; + /* prefix for external icons specified? */ + if (!IconPrefix.isEmpty()) + { + /* try to load external pgm icon */ + OFFilename filename; + OFStandard::appendFilenameExtension(filename, IconPrefix, sourceFilename); + iconOk = getIconFromFile(filename, pixel, count, width, height); + } else { + /* try to create icon from dataset */ + iconOk = getIconFromDataset(dataset, pixel, count, width, height); + if (!iconOk) + DCMDATA_WARN("cannot create monochrome icon from image file, using default"); + } + /* could not create icon so far: use default icon (if specified) */ + if (!iconOk && !DefaultIcon.isEmpty()) + iconOk = getIconFromFile(DefaultIcon, pixel, count, width, height); + /* default not available: use black image */ + if (!iconOk) + OFBitmanipTemplate::zeroMem(pixel, count); + /* create Pixel Data element and set pixel data */ + result = ditem->putAndInsertUint8Array(DCM_PixelData, pixel, count); + /* free pixel data after it has been copied */ + delete[] pixel; + } else + result = EC_MemoryExhausted; + /* remove entire icon image sequence in case of error */ + if (result.bad()) + record->findAndDeleteElement(DCM_IconImageSequence); + } + } + return result; +} + + +// add child record to a given parent record +DcmDirectoryRecord *DicomDirInterface::addRecord(DcmDirectoryRecord *parent, + const E_DirRecType recordType, + DcmFileFormat *fileformat, + const OFString &referencedFileID, + const OFFilename &sourceFilename) +{ + DcmDirectoryRecord *record = NULL; + DcmDataset *dataset = fileformat->getDataset(); + if (parent != NULL) + { + /* check whether record already exists */ + DcmDirectoryRecord *oldRecord = record = findExistingRecord(parent, recordType, dataset); + if ((record == NULL) || FilesetUpdateMode) + { + /* in case an existing record is updated */ + if (record != NULL) + { + /* perform some consistency checks for instance records */ + if ((recordType != ERT_Patient) && (recordType != ERT_Study) && (recordType != ERT_Series)) + { + if (!checkReferencedSOPInstance(record, dataset, referencedFileID, sourceFilename)) + return NULL; + } + } + /* create a new one or update existing record */ + switch (recordType) + { + case ERT_Patient: + record = buildPatientRecord(record, fileformat, sourceFilename); + break; + case ERT_Study: + record = buildStudyRecord(record, fileformat, sourceFilename); + break; + case ERT_Series: + record = buildSeriesRecord(record, fileformat, sourceFilename); + break; + case ERT_Overlay: + record = buildOverlayRecord(record, fileformat, referencedFileID, sourceFilename); + break; + case ERT_ModalityLut: + record = buildModalityLutRecord(record, fileformat, referencedFileID, sourceFilename); + break; + case ERT_VoiLut: + record = buildVoiLutRecord(record, fileformat, referencedFileID, sourceFilename); + break; + case ERT_Curve: + record = buildCurveRecord(record, fileformat, referencedFileID, sourceFilename); + break; + case ERT_SRDocument: + record = buildStructReportRecord(record, fileformat, referencedFileID, sourceFilename); + break; + case ERT_Presentation: + record = buildPresentationRecord(record, fileformat, referencedFileID, sourceFilename); + break; + case ERT_Waveform: + record = buildWaveformRecord(record, fileformat, referencedFileID, sourceFilename); + break; + case ERT_RTDose: + record = buildRTDoseRecord(record, fileformat, referencedFileID, sourceFilename); + break; + case ERT_RTStructureSet: + record = buildRTStructureSetRecord(record, fileformat, referencedFileID, sourceFilename); + break; + case ERT_RTPlan: + record = buildRTPlanRecord(record, fileformat, referencedFileID, sourceFilename); + break; + case ERT_RTTreatRecord: + record = buildRTTreatmentRecord(record, fileformat, referencedFileID, sourceFilename); + break; + case ERT_StoredPrint: + record = buildStoredPrintRecord(record, fileformat, referencedFileID, sourceFilename); + break; + case ERT_KeyObjectDoc: + record = buildKeyObjectDocRecord(record, fileformat, referencedFileID, sourceFilename); + break; + case ERT_Registration: + record = buildRegistrationRecord(record, fileformat, referencedFileID, sourceFilename); + break; + case ERT_Fiducial: + record = buildFiducialRecord(record, fileformat, referencedFileID, sourceFilename); + break; + case ERT_RawData: + record = buildRawDataRecord(record, fileformat, referencedFileID, sourceFilename); + break; + case ERT_Spectroscopy: + record = buildSpectroscopyRecord(record, fileformat, referencedFileID, sourceFilename); + break; + case ERT_EncapDoc: + record = buildEncapDocRecord(record, fileformat, referencedFileID, sourceFilename); + break; + case ERT_ValueMap: + record = buildValueMapRecord(record, fileformat, referencedFileID, sourceFilename); + break; + case ERT_HangingProtocol: + record = buildHangingProtocolRecord(record, fileformat, referencedFileID, sourceFilename); + break; + case ERT_Stereometric: + record = buildStereometricRecord(record, fileformat, referencedFileID, sourceFilename); + break; + case ERT_Palette: + record = buildPaletteRecord(record, fileformat, referencedFileID, sourceFilename); + break; + case ERT_Surface: + record = buildSurfaceRecord(record, fileformat, referencedFileID, sourceFilename); + break; + case ERT_Measurement: + record = buildMeasurementRecord(record, fileformat, referencedFileID, sourceFilename); + break; + case ERT_Implant: + record = buildImplantRecord(record, fileformat, referencedFileID, sourceFilename); + break; + case ERT_ImplantGroup: + record = buildImplantGroupRecord(record, fileformat, referencedFileID, sourceFilename); + break; + case ERT_ImplantAssy: + record = buildImplantAssyRecord(record, fileformat, referencedFileID, sourceFilename); + break; + case ERT_Plan: + record = buildPlanRecord(record, fileformat, referencedFileID, sourceFilename); + break; + case ERT_SurfaceScan: + record = buildSurfaceScanRecord(record, fileformat, referencedFileID, sourceFilename); + break; + default: + /* it can only be an image */ + record = buildImageRecord(record, fileformat, referencedFileID, sourceFilename); + } + if (record != NULL) + { + /* type 1C: required if an extended character set is used in one of the record keys */ + if (record->isAffectedBySpecificCharacterSet()) + copyElementType1C(dataset, DCM_SpecificCharacterSet, record, sourceFilename); + /* in case a new record has been created */ + if (record != oldRecord) + { + /* insert it below parent record */ + OFCondition status = insertSortedUnder(parent, record); + if (status.bad()) + { + printRecordErrorMessage(status, recordType, "insert"); + /* free memory */ + delete record; + record = NULL; + } + } + } + } else { + /* instance record is already referenced by the DICOMDIR */ + if ((recordType != ERT_Patient) && (recordType != ERT_Study) && (recordType != ERT_Series)) + { + /* create warning message */ + DCMDATA_WARN("file " << sourceFilename << ": directory record for this SOP instance already exists"); + } + /* perform consistency check */ + if (ConsistencyCheck) + { + /* abort on any inconsistency */ + if (warnAboutInconsistentAttributes(record, dataset, sourceFilename, AbortMode) && AbortMode) + return NULL; + } + } + if (record != NULL) + { + /* check whether instance is already listed */ + if (record->getRecordsOriginFile().isEmpty()) + record->setRecordsOriginFile(sourceFilename); + } + } + return record; +} + + +// check referenced SOP instance for consistency with a new directory record +OFBool DicomDirInterface::checkReferencedSOPInstance(DcmDirectoryRecord *record, + DcmItem *dataset, + const OFString &referencedFileID, + const OFFilename &sourceFilename) +{ + OFBool result = OFTrue; + if ((record != NULL) && (dataset != NULL)) + { + OFString refFileID; + /* check referenced file ID */ + if (record->findAndGetOFStringArray(DCM_ReferencedFileID, refFileID).good() && + !compare(refFileID, referencedFileID)) + { + /* create error message */ + DCMDATA_ERROR("file " << sourceFilename << ": SOP instance already referenced " + << "with different file ID (" << refFileID << ")"); + result = OFFalse; + } + /* check SOP class UID */ + if (!compareStringAttributes(dataset, DCM_SOPClassUID, record, DCM_ReferencedSOPClassUIDInFile, sourceFilename, OFTrue /*errorMsg*/)) + result = OFFalse; + } + return result; +} + + +// invent missing attributes on root level (and below) +void DicomDirInterface::inventMissingAttributes(DcmDirectoryRecord *parent, + const OFBool recurse) +{ + if (parent != NULL) + { + DcmDirectoryRecord *record = NULL; + /* iterate over all child records */ + while ((record = parent->nextSub(record)) != NULL) + { + /* only check patient records */ + if (record->getRecordType() == ERT_Patient) + { + if (!record->tagExistsWithValue(DCM_PatientID)) + setDefaultValue(record, DCM_PatientID, AutoPatientNumber++, AUTO_PATIENTID_PREFIX); + if (recurse) + inventMissingStudyLevelAttributes(record); + } + } + } +} + + +// invent missing attributes on study level (and below) +void DicomDirInterface::inventMissingStudyLevelAttributes(DcmDirectoryRecord *parent) +{ + if (parent != NULL) + { + DcmDirectoryRecord *record = NULL; + /* iterate over all child records */ + while ((record = parent->nextSub(record)) != NULL) + { + if (!record->tagExistsWithValue(DCM_StudyID)) + setDefaultValue(record, DCM_StudyID, AutoStudyNumber++, AUTO_STUDYID_PREFIX); + inventMissingSeriesLevelAttributes(record); + } + } +} + + +// invent missing attributes on series level (and below) +void DicomDirInterface::inventMissingSeriesLevelAttributes(DcmDirectoryRecord *parent) +{ + if (parent != NULL) + { + DcmDirectoryRecord *record = NULL; + /* iterate over all child records */ + while ((record = parent->nextSub(record)) != NULL) + { + if (!record->tagExistsWithValue(DCM_SeriesNumber)) + setDefaultValue(record, DCM_SeriesNumber, AutoSeriesNumber++); + inventMissingInstanceLevelAttributes(record); + } + } +} + + +// invent missing attributes on instance level (and below) +void DicomDirInterface::inventMissingInstanceLevelAttributes(DcmDirectoryRecord *parent) +{ + if (parent != NULL) + { + DcmDirectoryRecord *record = NULL; + /* iterate over all child records */ + while ((record = parent->nextSub(record)) != NULL) + { + switch (record->getRecordType()) + { + case ERT_Image: + case ERT_RTDose: + case ERT_RTStructureSet: + case ERT_RTPlan: + case ERT_StoredPrint: + case ERT_Surface: + if (!record->tagExistsWithValue(DCM_InstanceNumber)) + setDefaultValue(record, DCM_InstanceNumber, AutoInstanceNumber++); + break; + case ERT_Overlay: + if (!record->tagExistsWithValue(DCM_RETIRED_OverlayNumber)) + setDefaultValue(record, DCM_RETIRED_OverlayNumber, AutoOverlayNumber++); + break; + case ERT_ModalityLut: + case ERT_VoiLut: + if (!record->tagExistsWithValue(DCM_RETIRED_LUTNumber)) + setDefaultValue(record, DCM_RETIRED_LUTNumber, AutoLutNumber++); + break; + case ERT_Curve: + if (!record->tagExistsWithValue(DCM_RETIRED_CurveNumber)) + setDefaultValue(record, DCM_RETIRED_CurveNumber, AutoCurveNumber++); + break; + case ERT_SRDocument: + case ERT_Presentation: + case ERT_Waveform: + case ERT_RTTreatRecord: + case ERT_KeyObjectDoc: + case ERT_Registration: + case ERT_Fiducial: + case ERT_RawData: + case ERT_Spectroscopy: + case ERT_EncapDoc: + case ERT_ValueMap: + case ERT_Stereometric: + case ERT_Measurement: + case ERT_Plan: + case ERT_SurfaceScan: + /* nothing to do */ + break; + default: + /* should never happen */ + break; + } + } + } +} + + +// add DICOM file to the current DICOMDIR object +OFCondition DicomDirInterface::addDicomFile(const OFFilename &filename, + const OFFilename &directory) +{ + OFCondition result = EC_IllegalParameter; + /* first, make sure that a DICOMDIR object exists */ + if (DicomDir != NULL) + { + /* create fully qualified pathname of the DICOM file to be added */ + OFFilename pathname; + OFStandard::combineDirAndFilename(pathname, directory, filename, OFTrue /*allowEmptyDirName*/); + /* then check the file name, load the file and check the content */ + DcmFileFormat fileformat; + result = loadAndCheckDicomFile(filename, directory, fileformat, OFTrue /*checkFilename*/); + if (result.good()) + { + DCMDATA_INFO("adding file: " << pathname); + /* start creating the DICOMDIR directory structure */ + DcmDirectoryRecord *rootRecord = &(DicomDir->getRootRecord()); + DcmMetaInfo *metainfo = fileformat.getMetaInfo(); + /* massage filename into DICOM format (DOS conventions for path separators, uppercase) */ + OFString fileID; + hostToDicomFilename(OFSTRING_GUARD(filename.getCharPointer()), fileID); + /* what kind of object (SOP Class) is stored in the file */ + OFString sopClass; + metainfo->findAndGetOFString(DCM_MediaStorageSOPClassUID, sopClass); + /* if hanging protocol, palette or implant file then attach it to the root record and stop */ + if (compare(sopClass, UID_HangingProtocolStorage)) + { + /* add a hanging protocol record below the root */ + if (addRecord(rootRecord, ERT_HangingProtocol, &fileformat, fileID, pathname) == NULL) + result = EC_CorruptedData; + } + else if (compare(sopClass, UID_ColorPaletteStorage)) + { + /* add a palette record below the root */ + if (addRecord(rootRecord, ERT_Palette, &fileformat, fileID, pathname) == NULL) + result = EC_CorruptedData; + } + else if (compare(sopClass, UID_GenericImplantTemplateStorage)) + { + /* add an implant record below the root */ + if (addRecord(rootRecord, ERT_Implant, &fileformat, fileID, pathname) == NULL) + result = EC_CorruptedData; + } + else if (compare(sopClass, UID_ImplantAssemblyTemplateStorage)) + { + /* add an implant group record below the root */ + if (addRecord(rootRecord, ERT_ImplantGroup, &fileformat, fileID, pathname) == NULL) + result = EC_CorruptedData; + } + else if (compare(sopClass, UID_ImplantTemplateGroupStorage)) + { + /* add an implant assy record below the root */ + if (addRecord(rootRecord, ERT_ImplantAssy, &fileformat, fileID, pathname) == NULL) + result = EC_CorruptedData; + } else { + /* add a patient record below the root */ + DcmDirectoryRecord *patientRecord = addRecord(rootRecord, ERT_Patient, &fileformat, fileID, pathname); + if (patientRecord != NULL) + { + /* if patient management file then attach it to patient record and stop */ + if (compare(sopClass, UID_RETIRED_DetachedPatientManagementMetaSOPClass)) + { + result = patientRecord->assignToSOPFile(fileID.c_str(), pathname); + DCMDATA_ERROR(result.text() << ": cannot assign patient record to file: " << pathname); + } else { + /* add a study record below the current patient record */ + DcmDirectoryRecord *studyRecord = addRecord(patientRecord, ERT_Study, &fileformat, fileID, pathname);; + if (studyRecord != NULL) + { + /* add a series record below the current study record */ + DcmDirectoryRecord *seriesRecord = addRecord(studyRecord, ERT_Series, &fileformat, fileID, pathname);; + if (seriesRecord != NULL) + { + /* add one of the instance record below the current series record */ + if (addRecord(seriesRecord, sopClassToRecordType(sopClass), &fileformat, fileID, pathname) == NULL) + result = EC_CorruptedData; + } else + result = EC_CorruptedData; + } else + result = EC_CorruptedData; + } + } else + result = EC_CorruptedData; + /* invent missing attributes on all levels or PatientID only */ + if (InventMode) + inventMissingAttributes(rootRecord); + else if (InventPatientIDMode) + inventMissingAttributes(rootRecord, OFFalse /*recurse*/); + } + } + } + return result; +} + + +// set the file-set descriptor and character set +OFCondition DicomDirInterface::setFilesetDescriptor(const char *filename, + const char *charset) +{ + OFCondition result = EC_IllegalCall; + if (DicomDir != NULL) + { + /* check filename and character set */ + if (isFilenameValid(filename, OFTrue /*allowEmpty*/) && isCharsetValid(charset)) + { + /* get dataset of the current DICOMDIR */ + DcmDataset *dataset = DicomDir->getDirFileFormat().getDataset(); + if (dataset != NULL) + { + /* set FileSetDescriptorFileID */ + if ((filename == NULL) || (filename[0] == '\0')) + { + /* remove attribute from the dataset */ + dataset->findAndDeleteElement(DCM_FileSetDescriptorFileID); + dataset->findAndDeleteElement(DCM_SpecificCharacterSetOfFileSetDescriptorFile); + result = EC_Normal; + } else { + /* massage filename into DICOM format (DOS conventions for path separators, uppercase) */ + OFString fileID; + hostToDicomFilename(filename, fileID); + /* replace attribute value */ + result = dataset->putAndInsertString(DCM_FileSetDescriptorFileID, fileID.c_str()); + if (result.good()) + { + /* set SpecificCharacterSetOfFileSetDescriptorFile */ + if ((charset == NULL) || (charset[0] == '\0')) + { + /* remove attribute from the dataset */ + dataset->findAndDeleteElement(DCM_SpecificCharacterSetOfFileSetDescriptorFile); + result = EC_Normal; + } else { + /* replace attribute value */ + result = dataset->putAndInsertString(DCM_SpecificCharacterSetOfFileSetDescriptorFile, charset); + } + } + } + } + } else + result = EC_IllegalParameter; + // tbd: check whether file exists? + } + return result; +} + + +// set size of icon images (width and height in pixels) +OFCondition DicomDirInterface::setIconSize(const unsigned int size) +{ + OFCondition result = EC_IllegalParameter; + /* check valid range */ + if ((size > 0) && (size <= 256)) + { + IconSize = size; + result = EC_Normal; + } + return result; +} + + +// set filename prefix for icon images (if not retrieved from DICOM image) +OFCondition DicomDirInterface::setIconPrefix(const OFFilename &prefix) +{ + IconPrefix = prefix; + return EC_Normal; +} + + +// set filename for default image icon which is used in case of error +OFCondition DicomDirInterface::setDefaultIcon(const OFFilename &filename) +{ + DefaultIcon = filename; + return EC_Normal; +} + + +// enable/disable the abort mode, i.e. abort on first inconsistent file (otherwise warn) +OFBool DicomDirInterface::enableAbortMode(const OFBool newMode) +{ + /* save current mode */ + OFBool oldMode = AbortMode; + /* set new mode */ + AbortMode = newMode; + /* return old mode */ + return oldMode; +} + + +// enable/disable filename mapping mode, i.e. whether non-conforming filename are adjusted automatically +OFBool DicomDirInterface::enableMapFilenamesMode(const OFBool newMode) +{ + /* save current mode */ + OFBool oldMode = MapFilenamesMode; + /* set new mode */ + MapFilenamesMode = newMode; + /* return old mode */ + return oldMode; +} + + +// enable/disable invent mode, i.e. whether missing attribute values are invented +OFBool DicomDirInterface::enableInventMode(const OFBool newMode) +{ + /* save current mode */ + OFBool oldMode = InventMode; + /* set new mode */ + InventMode = newMode; + /* return old mode */ + return oldMode; +} + + +// enable/disable invent patient ID mode, i.e. whether missing patient ID is invented +OFBool DicomDirInterface::enableInventPatientIDMode(const OFBool newMode) +{ + /* save current mode */ + OFBool oldMode = InventPatientIDMode; + /* set new mode */ + InventPatientIDMode = newMode; + /* return old mode */ + return oldMode; +} + + +// enable/disable retired SOP class support, i.e. whether retired SOP classes are supported +OFBool DicomDirInterface::enableRetiredSOPClassSupport(const OFBool newMode) +{ + /* save current mode */ + OFBool oldMode = RetiredSOPClassSupport; + /* set new mode */ + RetiredSOPClassSupport = newMode; + /* return old mode */ + return oldMode; +} + + +// enable/disable icon image mode, i.e. whether to create icon images +OFBool DicomDirInterface::enableIconImageMode(const OFBool newMode) +{ + /* save current mode */ + OFBool oldMode = IconImageMode; + /* set new mode */ + IconImageMode = newMode; + /* return old mode */ + return oldMode; +} + + +// enable/disable the backup mode, i.e. whether to create a backup of the DICOMDIR +OFBool DicomDirInterface::disableBackupMode(const OFBool newMode) +{ + /* save current mode */ + OFBool oldMode = BackupMode; + /* set new mode */ + BackupMode = newMode; + /* return old mode */ + return oldMode; +} + + +// enable/disable pixel encoding check, i.e. whether the pixel encoding is checked +// for particular application profiles +OFBool DicomDirInterface::disableEncodingCheck(const OFBool newMode) +{ + /* save current mode */ + OFBool oldMode = EncodingCheck; + /* set new mode */ + EncodingCheck = newMode; + /* return old mode */ + return oldMode; +} + + +// enable/disable resolution check, i.e. whether the spatial resolution is checked +// for particular application profiles +OFBool DicomDirInterface::disableResolutionCheck(const OFBool newMode) +{ + /* save current mode */ + OFBool oldMode = ResolutionCheck; + /* set new mode */ + ResolutionCheck = newMode; + /* return old mode */ + return oldMode; +} + + +// enable/disable transfer syntax check, i.e. whether the transfer syntax is checked +// for particular application profiles +OFBool DicomDirInterface::disableTransferSyntaxCheck(const OFBool newMode) +{ + /* save current mode */ + OFBool oldMode = TransferSyntaxCheck; + /* set new mode */ + TransferSyntaxCheck = newMode; + /* return old mode */ + return oldMode; +} + + +// enable/disable DICOM file format check, i.e. whether the file is checked for the +// presence of the file meta information (according to DICOM part 10) +OFBool DicomDirInterface::disableFileFormatCheck(const OFBool newMode) +{ + /* save current mode */ + OFBool oldMode = FileFormatCheck; + /* set new mode */ + FileFormatCheck = newMode; + /* return old mode */ + return oldMode; +} + + +// enable/disable consistency check, i.e. whether the file is checked for consistency +// with the directory record +OFBool DicomDirInterface::disableConsistencyCheck(const OFBool newMode) +{ + /* save current mode */ + OFBool oldMode = ConsistencyCheck; + /* set new mode */ + ConsistencyCheck = newMode; + /* return old mode */ + return oldMode; +} + + +// add support for DicomImage class(es) - required for icon images +OFBool DicomDirInterface::addImageSupport(DicomDirImagePlugin *plugin) +{ + // store pointer to plugin + ImagePlugin = plugin; + return (ImagePlugin != NULL); +} + + +// print an error message to the console (stderr) that the value of the given tag is unexpected +void DicomDirInterface::printUnexpectedValueMessage(const DcmTagKey &key, + const OFFilename &filename, + const OFBool errorMsg) +{ + OFString str; + if (!filename.isEmpty()) + { + str = " in file: "; + str += OFSTRING_GUARD(filename.getCharPointer()); + } + if (errorMsg) + { + DCMDATA_ERROR("attribute " << DcmTag(key).getTagName() << " " << key + << " has other value than expected" << str); + } else { + DCMDATA_WARN("attribute " << DcmTag(key).getTagName() << " " << key + << " has other value than expected" << str); + } +} + + +// print an error message to the console (stderr) that a required attribute is missing/empty +void DicomDirInterface::printRequiredAttributeMessage(const DcmTagKey &key, + const OFFilename &filename, + const OFBool emptyMsg) +{ + OFString str; + if (!filename.isEmpty()) + { + str = " in file: "; + str += OFSTRING_GUARD(filename.getCharPointer()); + } + DCMDATA_ERROR("required attribute " << DcmTag(key).getTagName() << " " << key << " " + << (emptyMsg ? "empty" : "missing") << str); +} + + +// print an error message to the console (stderr) that something went wrong with an attribute +void DicomDirInterface::printAttributeErrorMessage(const DcmTagKey &key, + const OFCondition &error, + const char *operation) +{ + if (error.bad()) + { + OFString str; + if (operation != NULL) + { + str = "cannot "; + str += operation; + str += " "; + } + DCMDATA_ERROR(error.text() << ": " << str << DcmTag(key).getTagName() << " " << key); + } +} + + +// print an error message to the console (stderr) that something went wrong with a given record +void DicomDirInterface::printRecordErrorMessage(const OFCondition &error, + const E_DirRecType recordType, + const char *operation) +{ + if (error.bad()) + { + OFString str; + if (operation != NULL) + { + str = "cannot "; + str += operation; + str += " "; + } + DCMDATA_ERROR(error.text() << ": " << str << recordTypeToName(recordType) << " directory record"); + } +} + + +// return the name of the specified application profile +const char *DicomDirInterface::getProfileName(const E_ApplicationProfile profile) +{ + const char *result = ""; + switch(profile) + { + case AP_GeneralPurpose: + result = "STD-GEN-CD/DVD-RAM"; + break; + case AP_GeneralPurposeDVDJPEG: + result = "STD-GEN-DVD-JPEG"; + break; + case AP_GeneralPurposeDVDJPEG2000: + result = "STD-GEN-DVD-J2K"; + break; + case AP_GeneralPurposeBDJPEG: + result = "STD-GEN-BD-JPEG"; + break; + case AP_GeneralPurposeBDJPEG2000: + result = "STD-GEN-BD-J2K"; + break; + case AP_GeneralPurposeBDMPEG2MPatML: + result = "STD-GEN-BD-MPEG2-MPML"; + break; + case AP_GeneralPurposeBDMPEG2MPatHL: + result = "STD-GEN-BD-MPEG2-MPHL"; + break; + case AP_GeneralPurposeBDMPEG4HPatLV41: + result = "STD-GEN-BD-MPEG4-HPLV41"; + break; + case AP_GeneralPurposeBDMPEG4HPatLV41BD: + result = "STD-GEN-BD-MPEG4-HPLV41BD"; + break; + case AP_USBandFlashJPEG: + result = "STD-GEN-USB/MMC/CF/SD-JPEG"; + break; + case AP_USBandFlashJPEG2000: + result = "STD-GEN-USB/MMC/CF/SD-J2K"; + break; + case AP_GeneralPurposeMIME: + result = "STD-GEN-MIME"; + break; + case AP_MPEG2MPatMLDVD: + result = "STD-DVD-MPEG2-MPML"; + break; + case AP_BasicCardiac: + result = "STD-XABC-CD"; + break; + case AP_XrayAngiographic: + result = "STD-XA1K-CD"; + break; + case AP_XrayAngiographicDVD: + result = "STD-XA1K-DVD"; + break; + case AP_DentalRadiograph: + result = "STD-DEN-CD"; + break; + case AP_CTandMR: + result = "STD-CTMR-xxxx"; + break; + case AP_UltrasoundIDSF: + result = "STD-US-ID-SF-xxxx"; + break; + case AP_UltrasoundSCSF: + result = "STD-US-SC-SF-xxxx"; + break; + case AP_UltrasoundCCSF: + result = "STD-US-CC-SF-xxxx"; + break; + case AP_UltrasoundIDMF: + result = "STD-US-ID-MF-xxxx"; + break; + case AP_UltrasoundSCMF: + result = "STD-US-SC-MF-xxxx"; + break; + case AP_UltrasoundCCMF: + result = "STD-US-CC-MF-xxxx"; + break; + case AP_TwelveLeadECG: + result = "STD-WVFM-ECG-FD"; + break; + case AP_HemodynamicWaveform: + result = "STD-WVFM-HD-FD"; + break; + } + return result; +} + + +// copy contents of specified file +OFBool DicomDirInterface::copyFile(const OFFilename &fromFilename, + const OFFilename &toFilename) +{ + OFBool result = OFStandard::copyFile(fromFilename, toFilename); + /* check for errors */ + if (!result) + { + /* create error message from error code */ + char buffer[255]; + DCMDATA_ERROR("copying files: " << fromFilename << " to " << toFilename + << ": " << OFStandard::strerror(errno, buffer, 255)); + } + return result; +} + + +// see if all the attributes in record match the values in dataset +OFBool DicomDirInterface::warnAboutInconsistentAttributes(DcmDirectoryRecord *record, + DcmItem *dataset, + const OFFilename &sourceFilename, + const OFBool abortCheck) +{ + OFBool result = OFFalse; + /* check parameters first */ + if ((record != NULL) && (dataset != NULL)) + { + result = OFTrue; // default: no inconsistency + DcmTagKey tag; + DcmStack stack; + OFBool first = OFTrue; + DcmElement *delem = NULL; + /* iterate over all record elements */ + while (record->nextObject(stack, first).good() && (result || !abortCheck)) + { + delem = OFstatic_cast(DcmElement *, stack.top()); + if ((delem != NULL) && (delem->getLength() > 0)) + { + /* record attribute has a value */ + tag = delem->getTag().getXTag(); + if (dataset->tagExistsWithValue(tag)) + { + if (delem->getTag().getEVR() == EVR_SQ) + { + /* do not check particular sequences (because they will always deviate) */ + if ((delem->getTag() != DCM_ContentSequence) && (delem->getTag() != DCM_BlendingSequence)) + result &= compareSequenceAttributes(dataset, tag, record, sourceFilename); + } else { + /* everything else can be compared as a string */ + result &= compareStringAttributes(dataset, tag, record, tag, sourceFilename); + } + } + } + first = OFFalse; + } + } + if (!result & abortCheck) + DCMDATA_ERROR("aborting on first inconsistent file: " << sourceFilename); + /* return OFTrue in case of any inconsistency */ + return !result; +} + + +// check whether given file-set ID is valid +OFBool DicomDirInterface::checkFilesetID(const OFString &filesetID) +{ + OFBool result = OFTrue; + if (!filesetID.empty()) + { + size_t invalidChar = 0; + /* are the characters ok? */ + if (!DcmCodeString::checkVR(filesetID, &invalidChar, OFFalse /*checkLength*/)) + { + /* create error message */ + DCMDATA_ERROR("invalid character(s) in file-set ID: " << filesetID << OFendl + << OFString(37 /*message*/ + invalidChar, ' ') << "^"); + result = OFFalse; + } + /* ensure that file-set ID is not too large */ + if (isComponentTooLarge(filesetID, OFstatic_cast(size_t, DcmVR(EVR_CS).getMaxValueLength()), MapFilenamesMode)) + { + DCMDATA_ERROR("file-set ID too large: " << filesetID); + result = OFFalse; + } + } + return result; +} + + +// check whether specified tag exists in the dataset +OFBool DicomDirInterface::checkExists(DcmItem *dataset, + const DcmTagKey &key, + const OFFilename &filename) +{ + /* check whether tag exists */ + OFBool result = OFFalse; + if (dataset != NULL) + { + result = dataset->tagExists(key); + if (!result && !filename.isEmpty()) + { + /* report an error */ + printRequiredAttributeMessage(key, filename); + } + } + return result; +} + + +// check whether specified tag exists with a value in the dataset +OFBool DicomDirInterface::checkExistsWithValue(DcmItem *dataset, + const DcmTagKey &key, + const OFFilename &filename) +{ + /* first, check whether tag exists, and report an error if not */ + OFBool result = checkExists(dataset, key, filename); + if (result) + { + /* then check whether tag has a value (is non-empty) */ + result = dataset->tagExistsWithValue(key); + if (!result && !filename.isEmpty()) + { + /* report an error */ + printRequiredAttributeMessage(key, filename, OFTrue /*emptyMsg*/); + } + } + return result; +} + + +// check whether specified tag exists in the dataset and has the expected string value +OFBool DicomDirInterface::checkExistsWithStringValue(DcmItem *dataset, + const DcmTagKey &key, + const OFString &value, + const OFFilename &filename) +{ + /* first, check whether tag exists, and report an error if not */ + OFBool result = checkExists(dataset, key, filename); + if (result) + { + OFString str; + /* retrieve the string value from the element */ + dataset->findAndGetOFStringArray(key, str); + /* compare with expected value */ + result = compare(str, value); + if (!result && !filename.isEmpty()) + { + /* report an error */ + printUnexpectedValueMessage(key, filename); + } + } + return result; +} + + +// check whether specified tag exists in the dataset and has the expected integer value +OFBool DicomDirInterface::checkExistsWithIntegerValue(DcmItem *dataset, + const DcmTagKey &key, + const long value, + const OFFilename &filename, + const OFBool reject) +{ + /* first, check whether tag exists, and report an error if not */ + OFBool result = checkExists(dataset, key, filename); + if (result) + { + long i; + /* retrieve the integer value from the element */ + dataset->findAndGetLongInt(key, i); + /* compare with expected value */ + result = (i == value); + if (!result) + { + if (!filename.isEmpty()) + { + /* report an error or a warning */ + printUnexpectedValueMessage(key, filename, reject /*errorMsg*/); + } + /* do not reject invalid values */ + if (!reject) + result = OFTrue; + } + } + return result; +} + + +// check whether specified tag exists in the dataset and has an integer value in the expected range +OFBool DicomDirInterface::checkExistsWithMinMaxValue(DcmItem *dataset, + const DcmTagKey &key, + const long min, + const long max, + const OFFilename &filename, + const OFBool reject) +{ + /* first, check whether tag exists, and report an error if not */ + OFBool result = checkExists(dataset, key, filename); + if (result) + { + long i; + /* retrieve the integer value from the element */ + dataset->findAndGetLongInt(key, i); + /* compare with expected value range */ + result = (i >= min) && (i <= max); + if (!result) + { + if (!filename.isEmpty()) + { + /* report an error or a warning */ + printUnexpectedValueMessage(key, filename, reject /*errorMsg*/); + } + /* do not reject invalid values */ + if (!reject) + result = OFTrue; + } + } + return result; +} + + +// get string value from dataset and report an error (if any) +OFString &DicomDirInterface::getStringFromDataset(DcmItem *dataset, + const DcmTagKey &key, + OFString &result, + OFBool searchIntoSub) +{ + result.clear(); + if (dataset != NULL) + { + /* get string value from dataset and report if tag is missing */ + OFCondition status = dataset->findAndGetOFStringArray(key, result, searchIntoSub); + printAttributeErrorMessage(key, status, "retrieve"); + } + return result; +} + + +// get string value component from dataset and report an error (if any) +OFString &DicomDirInterface::getStringComponentFromDataset(DcmItem *dataset, + const DcmTagKey &key, + OFString &result, + const unsigned long pos, + OFBool searchIntoSub) +{ + result.clear(); + if (dataset != NULL) + { + /* get string value component from dataset and report if tag or component is missing */ + OFCondition status = dataset->findAndGetOFString(key, result, pos, searchIntoSub); + if (status.bad()) + { + DCMDATA_ERROR(status.text() << ": cannot retrieve value " << (pos + 1) + << " of " << DcmTag(key).getTagName() << " " << key); + } + } + return result; +} + + +// get string value from file and report an error (if any) +OFString &DicomDirInterface::getStringFromFile(const OFFilename &filename, + const DcmTagKey &key, + OFString &result, + OFBool searchIntoSub) +{ + result.clear(); + if (!filename.isEmpty()) + { + DcmFileFormat fileformat; + DCMDATA_INFO("investigating file: " << filename); + /* load specified file */ + OFCondition status = fileformat.loadFile(filename); + /* retrieve string value from dataset */ + if (status.good()) + getStringFromDataset(fileformat.getDataset(), key, result, searchIntoSub); + else + DCMDATA_ERROR(status.text() << ": reading file: " << filename); + } + return result; +} + + +// copy element from given dataset to directory record +void DicomDirInterface::copyElement(DcmItem *dataset, + const DcmTagKey &key, + DcmDirectoryRecord *record, + const OFFilename &sourceFilename, + const OFBool optional, + const OFBool copyEmpty) +{ + if ((dataset != NULL) && (record != NULL)) + { + /* check whether tag exists in source dataset (if optional) */ + if (!optional || (copyEmpty && dataset->tagExists(key)) || dataset->tagExistsWithValue(key)) + { + DcmElement *delem = NULL; + /* get copy of element from source dataset */ + OFCondition status = dataset->findAndGetElement(key, delem, OFFalse /*searchIntoSub*/, OFTrue /*createCopy*/); + if (status.good()) + { + /* ... and insert it into the destination dataset (record) */ + status = record->insert(delem, OFTrue /*replaceOld*/); + if (status.good()) + { + DcmTag tag(key); + /* check for correct VR in the dataset */ + if (delem->getVR() != tag.getEVR()) + { + /* create warning message */ + DCMDATA_WARN("file " << sourceFilename << ": possibly wrong VR: " + << tag.getTagName() << " " << key << " with " + << DcmVR(delem->getVR()).getVRName() << " found, expected " + << tag.getVRName() << " instead"); + } + } else + delete delem; + } else if (status == EC_TagNotFound) + status = record->insertEmptyElement(key); + printAttributeErrorMessage(key, status, "insert"); + } + } +} + + +// copy element from given dataset or first item of the given sequence to directory record +void DicomDirInterface::copyElementType1CFromDatasetOrSequenceItem(DcmItem *dataset, + const DcmTagKey &elementKey, + const DcmTagKey &sequenceKey, + DcmDirectoryRecord *record, + const OFFilename &sourceFilename) +{ + if ((dataset != NULL) && (record != NULL)) + { + DcmElement *delem = NULL; + OFCondition status = EC_IllegalCall; + /* check whether tag exists in given dataset */ + if (dataset->tagExistsWithValue(elementKey)) + { + /* get copy of element from given dataset */ + status = dataset->findAndGetElement(elementKey, delem, OFFalse /*searchIntoSub*/, OFTrue /*createCopy*/); + } else { + /* alternatively, check whether tag exists in first item of the given sequence element */ + DcmItem *ditem = NULL; + if (dataset->findAndGetSequenceItem(sequenceKey, ditem, 0).good()) + { + /* get copy of element from sequence item (on arbitrary nesting level) */ + status = ditem->findAndGetElement(elementKey, delem, OFTrue /*searchIntoSub*/, OFTrue /*createCopy*/); + } + } + /* check whether element could be found */ + if (delem != NULL) + { + if (status.good() && !delem->isEmpty()) + { + /* ... and insert it into the destination dataset (record) */ + status = record->insert(delem, OFTrue /*replaceOld*/); + if (status.good()) + { + DcmTag tag(elementKey); + /* check for correct VR in the dataset */ + if (delem->getVR() != tag.getEVR()) + { + /* create warning message */ + DCMDATA_WARN("file " << sourceFilename << ": possibly wrong VR: " + << tag.getTagName() << " " << elementKey << " with " + << DcmVR(delem->getVR()).getVRName() << " found, expected " + << tag.getVRName() << " instead"); + } + } else + delete delem; + } else + delete delem; + printAttributeErrorMessage(elementKey, status, "insert"); + } + } +} + + +// copy optional string value from dataset to directory record +void DicomDirInterface::copyStringWithDefault(DcmItem *dataset, + const DcmTagKey &key, + DcmDirectoryRecord *record, + const OFFilename &sourceFilename, + const char *defaultValue, + const OFBool printWarning) +{ + if ((dataset != NULL) && (record != NULL)) + { + OFCondition status = EC_Normal; + if (dataset->tagExistsWithValue(key)) + { + OFString stringValue; + /* retrieve string value from source dataset and put it into the destination dataset */ + status = record->putAndInsertOFStringArray(key, getStringFromDataset(dataset, key, stringValue)); + } else { + if (printWarning && (defaultValue != NULL)) + { + /* create warning message */ + DCMDATA_WARN("file " << sourceFilename << ": " << DcmTag(key).getTagName() << " " + << key << " missing, using alternative: " << defaultValue); + } + /* put default value */ + status = record->putAndInsertString(key, defaultValue); + } + printAttributeErrorMessage(key, status, "insert"); + } +} + + +// compare string attributes from dataset and record and report any deviation +OFBool DicomDirInterface::compareStringAttributes(DcmItem *dataset, + const DcmTagKey &datKey, + DcmDirectoryRecord *record, + const DcmTagKey &recKey, + const OFFilename &sourceFilename, + const OFBool errorMsg) +{ + OFBool result = OFFalse; + /* check parameters first */ + if ((dataset != NULL) && (record != NULL)) + { + OFString datasetString, recordString; + /* compare string value from dataset and record */ + result = compare(getStringFromDataset(dataset, datKey, datasetString), + getStringFromDataset(record, recKey, recordString)); + if (!result) + { + OFString uniqueString; + OFFilename originFilename = record->getRecordsOriginFile(); + const DcmTagKey uniqueKey = getRecordUniqueKey(record->getRecordType()); + getStringFromDataset(record, uniqueKey, uniqueString); + if (originFilename.isEmpty()) + originFilename = ""; + /* create warning message */ + OFOStringStream oss; + oss << "file inconsistent with existing DICOMDIR record" << OFendl; + oss << " " << recordTypeToName(record->getRecordType()) << " Record [Key: " + << DcmTag(uniqueKey).getTagName() << " " << uniqueKey << "=\"" << uniqueString << "\"]" << OFendl; + oss << " Existing Record (origin: " << originFilename << ") defines: " << OFendl; + oss << " " << DcmTag(recKey).getTagName() << " " << recKey << "=\"" << recordString << "\"" << OFendl; + oss << " File (" << sourceFilename << ") defines:" << OFendl; + oss << " " << DcmTag(datKey).getTagName() << " " << datKey << "=\"" << datasetString << "\"" << OFendl; + oss << OFStringStream_ends; + OFSTRINGSTREAM_GETSTR(oss, tmpString) + if (errorMsg) + DCMDATA_ERROR(tmpString); + else + DCMDATA_WARN(tmpString); + OFSTRINGSTREAM_FREESTR(tmpString) + } + } + return result; +} + + +// compare sequence attributes from dataset and record and report any deviation +OFBool DicomDirInterface::compareSequenceAttributes(DcmItem *dataset, + DcmTagKey &key, + DcmDirectoryRecord *record, + const OFFilename &sourceFilename) +{ + OFBool result = OFFalse; + /* check parameters first */ + if ((dataset != NULL) && (record != NULL)) + { + DcmSequenceOfItems *seq1, *seq2; + /* compare sequence value from dataset and record */ + if (record->findAndGetSequence(key, seq1).good() && + dataset->findAndGetSequence(key, seq2).good()) + { + OFString reason; + result = compareSQAttributes(seq1, seq2, reason); + if (!result) + { + OFString uniqueString; + OFFilename originFilename = record->getRecordsOriginFile(); + const DcmTagKey uniqueKey = getRecordUniqueKey(record->getRecordType()); + getStringFromDataset(record, uniqueKey, uniqueString); + if (originFilename.isEmpty()) + originFilename = ""; + /* create warning message */ + DCMDATA_WARN("file inconsistent with existing DICOMDIR record" << OFendl + << " " << recordTypeToName(record->getRecordType()) << " Record [Key: " + << DcmTag(uniqueKey).getTagName() << " " << uniqueKey << "=\"" << uniqueString << "\"]" << OFendl + << " Reason: " << reason << OFendl + << " Existing Record (origin: " << originFilename << ") defines: " << OFendl + << DcmObject::PrintHelper(*seq1, 0, 4 /* indent */) + << " File (" << sourceFilename << ") defines:" << OFendl + << DcmObject::PrintHelper(*seq2, 0, 4 /* indent */)); + } + } + } + return result; +} + + +// set the specified default value (number or prefix and number) to the given tag +void DicomDirInterface::setDefaultValue(DcmDirectoryRecord *record, + const DcmTagKey &key, + const unsigned long number, + const char *prefix) +{ + if (record != NULL) + { + char buffer[64]; + if (prefix != NULL) + { + /* use at most 10 chars from prefix */ + OFStandard::strlcpy(buffer, prefix, 10 + 1); + /* append a 6 digits number */ + sprintf(buffer + strlen(buffer), "%06lu", number); + } else { + /* create a number string only */ + sprintf(buffer, "%lu", number); + } + record->putAndInsertString(key, buffer); + /* create warning message */ + DCMDATA_WARN(recordTypeToName(record->getRecordType()) << " Record (origin: " + << record->getRecordsOriginFile() << ") inventing " << DcmTag(key).getTagName() + << ": " << buffer); + } +} diff --git a/dcmdata/libsrc/dcdicdir.cc b/dcmdata/libsrc/dcdicdir.cc new file mode 100644 index 00000000..64759e3b --- /dev/null +++ b/dcmdata/libsrc/dcdicdir.cc @@ -0,0 +1,1271 @@ +/* + * + * Copyright (C) 1994-2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Gerd Ehlers, Andreas Barth + * + * Purpose: class DcmDicomDir + * + */ + + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#define INCLUDE_CSTDLIB +#define INCLUDE_CSTDIO +#define INCLUDE_CERRNO +#define INCLUDE_LIBC +#define INCLUDE_UNISTD +#include "dcmtk/ofstd/ofstdinc.h" + +#ifdef HAVE_UNIX_H +#if defined(macintosh) && defined (HAVE_WINSOCK_H) +/* unix.h defines timeval incompatible with winsock.h */ +#define timeval _UNWANTED_timeval +#endif +#include /* for unlink() under Metrowerks C++ (Macintosh) */ +#undef timeval +#endif + +#include "dcmtk/ofstd/ofstream.h" +#include "dcmtk/ofstd/ofdefine.h" +#include "dcmtk/dcmdata/dcdicdir.h" +#include "dcmtk/dcmdata/dcuid.h" +#include "dcmtk/dcmdata/dcdirrec.h" +#include "dcmtk/dcmdata/dcxfer.h" +#include "dcmtk/dcmdata/dcdeftag.h" +#include "dcmtk/dcmdata/dcostrma.h" /* for class DcmOutputStream */ +#include "dcmtk/dcmdata/dcostrmf.h" /* for class DcmOutputFileStream */ +#include "dcmtk/dcmdata/dcistrmf.h" /* for class DcmInputFileStream */ +#include "dcmtk/dcmdata/dcvrcs.h" +#include "dcmtk/dcmdata/dcvrus.h" +#include "dcmtk/dcmdata/dcmetinf.h" +#include "dcmtk/ofstd/ofstd.h" +#include "dcmtk/dcmdata/dcwcache.h" /* for class DcmWriteCache */ +#include "dcmtk/dcmdata/dcvrui.h" /* for class DcmUniqueIdentifier */ + +#ifndef O_BINARY +#define O_BINARY 0 /* only Windows has O_BINARY */ +#endif + + +// ******************************** + + +DcmDicomDir::DcmDicomDir() + : errorFlag(EC_Normal), + dicomDirFileName(), + modified(OFFalse), + mustCreateNewDir(OFFalse), + DirFile(new DcmFileFormat()), + RootRec(NULL), + MRDRSeq(NULL) +{ + dicomDirFileName.set(DEFAULT_DICOMDIR_NAME); + + OFCondition cond = DirFile->loadFile(dicomDirFileName); + if (cond.bad()) + { + delete DirFile; // clean up file format object + DirFile = new DcmFileFormat(); + mustCreateNewDir = OFTrue; + } + + createNewElements( "" ); // create missing data elements + RootRec = new DcmDirectoryRecord( ERT_root, NULL, OFFilename()); + DcmTag mrdrSeqTag( DCM_DirectoryRecordSequence ); + MRDRSeq = new DcmSequenceOfItems( mrdrSeqTag ); + + errorFlag = convertLinearToTree(); +} + + +// ******************************** + + +DcmDicomDir::DcmDicomDir(const OFFilename &fileName, const char *fileSetID) + : errorFlag(EC_Normal), + dicomDirFileName(), + modified(OFFalse), + mustCreateNewDir(OFFalse), + DirFile(new DcmFileFormat()), + RootRec(NULL), + MRDRSeq(NULL) +{ + if ( fileName.isEmpty() ) + dicomDirFileName.set(DEFAULT_DICOMDIR_NAME); + else + dicomDirFileName = fileName; + + OFCondition cond = DirFile->loadFile(dicomDirFileName); + if (cond.bad()) + { + delete DirFile; // clean up file format object + DirFile = new DcmFileFormat(); + mustCreateNewDir = OFTrue; + } + + createNewElements( fileSetID ); // create missing data elements + RootRec = new DcmDirectoryRecord( ERT_root, NULL, OFFilename()); + DcmTag mrdrSeqTag( DCM_DirectoryRecordSequence ); + MRDRSeq = new DcmSequenceOfItems( mrdrSeqTag ); + + errorFlag = convertLinearToTree(); +} + + +// ******************************** + + +/* This copy constructor implementation is untested + */ +DcmDicomDir::DcmDicomDir( const DcmDicomDir & old ) + : errorFlag(old.errorFlag), + dicomDirFileName(old.dicomDirFileName), + modified(old.modified), + mustCreateNewDir(old.mustCreateNewDir), + DirFile(new DcmFileFormat(*old.DirFile)), + RootRec(new DcmDirectoryRecord(*old.RootRec)), + MRDRSeq(new DcmSequenceOfItems(*old.MRDRSeq)) +{ +} + + +// ******************************** + + +DcmDicomDir::~DcmDicomDir() +{ + if (modified) + write(); + + delete DirFile; + delete RootRec; + delete MRDRSeq; +} + + +// ******************************** + +/* + creates required data elements. Only called by the constructors. +*/ + +OFCondition DcmDicomDir::createNewElements( const char* fileSetID ) +{ + OFCondition l_error = EC_Normal; + DcmUnsignedLongOffset *uloP; + DcmUnsignedShort *usP; + DcmCodeString *csP; + DcmDataset &dset = getDataset(); // guaranteed to exist + + DcmTag fileIDTag( DCM_FileSetID ); + csP = new DcmCodeString( fileIDTag ); // (0004,1130) + if ( fileSetID != NULL && *fileSetID != '\0' ) + csP->putString( fileSetID ); + if ( dset.insert( csP, OFFalse ) != EC_Normal ) + delete csP; + + // not created or inserted: // (0004,1141) + // (0004,1142) + + DcmTag firstRecTag( DCM_OffsetOfTheFirstDirectoryRecordOfTheRootDirectoryEntity ); + uloP = new DcmUnsignedLongOffset( firstRecTag ); // (0004,1200) + uloP->putUint32(Uint32(0)); + if ( dset.insert( uloP, OFFalse ) != EC_Normal ) + delete uloP; + + DcmTag lastRecTag( DCM_OffsetOfTheLastDirectoryRecordOfTheRootDirectoryEntity ); + uloP = new DcmUnsignedLongOffset( lastRecTag ); // (0004,1202) + uloP->putUint32(Uint32(0)); + if ( dset.insert( uloP, OFFalse ) != EC_Normal ) + delete uloP; + + DcmTag fileConsTag( DCM_FileSetConsistencyFlag ); + usP = new DcmUnsignedShort( fileConsTag ); // (0004,1212) + usP->putUint16(Uint16(0x0000)); + dset.insert( usP, OFTrue ); + return l_error; +} + + +// ******************************** + + +DcmDataset& DcmDicomDir::getDataset() +{ + if ( DirFile == NULL ) + DirFile = new DcmFileFormat(); + DcmDataset *localDataset = DirFile->getDataset(); + + if ( localDataset == NULL ) + { + errorFlag = EC_CorruptedData; + DCMDATA_ERROR("DcmDicomDir::getDataset() Missing Dataset in DICOMDIR File. Must create new DICOMDIR file."); + if ( DirFile != NULL ) + delete DirFile; + DirFile = new DcmFileFormat(); + localDataset = DirFile->getDataset(); + } + return *localDataset; // must exist, otherwise error in DcmFileFormat +} + + +// ******************************** + + +DcmSequenceOfItems& DcmDicomDir::getDirRecSeq( DcmDataset &dset ) +{ + DcmSequenceOfItems *localDirRecSeq = NULL; + DcmStack stack; + if ( dset.search( DCM_DirectoryRecordSequence, stack, ESM_fromHere, OFFalse ) == EC_Normal ) + { + if ( stack.top()->ident() == EVR_SQ ) + localDirRecSeq = OFstatic_cast(DcmSequenceOfItems *, stack.top()); + } + + if ( localDirRecSeq == NULL ) + { + errorFlag = EC_CorruptedData; + if ( !mustCreateNewDir ) + { + DCMDATA_WARN("DcmDicomDir::getDirRecSeq() Missing Directory Record Sequence. Must create new one."); + } + DcmTag dirSeqTag( DCM_DirectoryRecordSequence ); // (0004,1220) + localDirRecSeq = new DcmSequenceOfItems( dirSeqTag ); + dset.insert( localDirRecSeq, OFTrue ); + } + return *localDirRecSeq; // must exist, otherwise memory exhausted +} + + +// ******************************** + + +DcmUnsignedLongOffset* DcmDicomDir::lookForOffsetElem( DcmObject *obj, + const DcmTagKey &offsetTag ) +{ + DcmUnsignedLongOffset *offElem = NULL; + if ( obj != NULL ) + { + DcmStack stack; + if ( obj->search( offsetTag, stack, ESM_fromHere, OFFalse ) == EC_Normal ) + { + if ( stack.top()->ident() == EVR_up ) + { + offElem = OFstatic_cast(DcmUnsignedLongOffset *, stack.top()); +#ifdef DEBUG + Uint32 l_uint = 0; + offElem->getUint32(l_uint); + DCMDATA_TRACE("DcmDicomDir::lookForOffsetElem() Offset Element " + << offElem->getTag() << " offs=0x" + << STD_NAMESPACE hex << STD_NAMESPACE setfill('0') + << STD_NAMESPACE setw(8) << l_uint + << " p=" << OFstatic_cast(void *, offElem) + << " l=" << offElem->getNextRecord()); +#endif + } + } + } + return offElem; +} + + +// ******************************** + + +OFCondition DcmDicomDir::resolveGivenOffsets( DcmObject *startPoint, + const OFMap &itOffsets, + const DcmTagKey &offsetTag ) +{ + OFCondition l_error = EC_Normal; + if ( startPoint != NULL ) + { + DcmStack stack; + Uint32 offset; + for (;;) + { + l_error = startPoint->nextObject(stack, OFTrue); + if (l_error.bad()) + break; + + DcmObject *cur = stack.top(); + if (cur->ident() != EVR_up || cur->getTag() != offsetTag) + continue; + + DcmUnsignedLongOffset *offElem = OFstatic_cast(DcmUnsignedLongOffset *, cur); + l_error = offElem->getUint32(offset); + + /* an offset of 0 means that no directory record is referenced */ + if (l_error.good() && (offset > 0)) + { + OFMap::const_iterator it = itOffsets.find(offset); + if (it != itOffsets.end()) + { + offElem->setNextRecord(it->second); + } else { + DCMDATA_WARN("DcmDicomDir::resolveGivenOffsets() Cannot resolve offset " << offset); + /* FIXME: obviously, this error code is never returned but always ignored!? */ + l_error = EC_InvalidOffset; + } + } + } + } + + return l_error; +} + + +// ******************************** + + +OFCondition DcmDicomDir::resolveAllOffsets( DcmDataset &dset ) // inout +{ + OFCondition l_error = EC_Normal; + DcmObject *obj = NULL; + DcmDirectoryRecord *rec = NULL; + DcmSequenceOfItems &localDirRecSeq = getDirRecSeq( dset ); + unsigned long maxitems = localDirRecSeq.card(); + OFMap itOffsets; + + for (unsigned long i = 0; i < maxitems; i++ ) + { + obj = localDirRecSeq.nextInContainer(obj); + rec = OFstatic_cast(DcmDirectoryRecord *, obj); + long filePos = rec->getFileOffset(); + itOffsets[ OFstatic_cast(Uint32, filePos) ] = rec; + DCMDATA_DEBUG("DcmDicomDir::resolveAllOffsets() Item Offset [" << i << "] = 0x" + << STD_NAMESPACE hex << STD_NAMESPACE setfill('0') << STD_NAMESPACE setw(8) << filePos); + } + resolveGivenOffsets( &dset, itOffsets, + DCM_OffsetOfTheFirstDirectoryRecordOfTheRootDirectoryEntity ); + resolveGivenOffsets( &dset, itOffsets, + DCM_OffsetOfTheLastDirectoryRecordOfTheRootDirectoryEntity ); + + resolveGivenOffsets( &localDirRecSeq, itOffsets, + DCM_OffsetOfTheNextDirectoryRecord ); + resolveGivenOffsets( &localDirRecSeq, itOffsets, + DCM_OffsetOfReferencedLowerLevelDirectoryEntity ); + resolveGivenOffsets( &localDirRecSeq, itOffsets, + DCM_RETIRED_MRDRDirectoryRecordOffset ); + + return l_error; +} + + +// ******************************** + + +OFCondition DcmDicomDir::linkMRDRtoRecord( DcmDirectoryRecord *dRec ) +{ + OFCondition l_error = EC_Normal; + + if ( dRec != NULL ) + { + // enter referenced MRDR into protected attribute: + // only works since DcmDicomDir is a friend class of DcmDirectoryRecord + dRec->referencedMRDR = dRec->lookForReferencedMRDR(); + } + + return l_error; +} + + +// ******************************** + + +OFCondition DcmDicomDir::moveRecordToTree( DcmDirectoryRecord *startRec, + DcmSequenceOfItems &fromDirSQ, + DcmDirectoryRecord *toRecord ) +{ + OFCondition l_error = EC_Normal; + + if (toRecord == NULL) + l_error = EC_IllegalCall; + else + { + while ( startRec != NULL ) + { + DcmDirectoryRecord *lowerRec = NULL; + DcmDirectoryRecord *nextRec = NULL; + + DcmUnsignedLongOffset *offElem; + offElem = lookForOffsetElem( startRec, DCM_OffsetOfReferencedLowerLevelDirectoryEntity ); + if ( offElem != NULL ) + lowerRec = OFstatic_cast(DcmDirectoryRecord *, offElem->getNextRecord()); + offElem = lookForOffsetElem( startRec, DCM_OffsetOfTheNextDirectoryRecord ); + if ( offElem != NULL ) + nextRec = OFstatic_cast(DcmDirectoryRecord *, offElem->getNextRecord()); + + DCMDATA_TRACE("DcmDicomDir::moveRecordToTree() Record " + << startRec->getTag() + << " p=" << OFstatic_cast(void *, startRec) + << " has lower=" << OFstatic_cast(void *, lowerRec) + << " and next=" << OFstatic_cast(void *, nextRec) << " Record"); + + linkMRDRtoRecord( startRec ); + + // use protected method for insertion without type check: + if ( toRecord->masterInsertSub( startRec ) == EC_Normal ) + { + // only works since friend class + DcmItem *dit = fromDirSQ.remove( startRec ); + if ( dit == NULL ) + { + DCMDATA_ERROR("DcmDicomDir::moveRecordToTree() DirRecord is part of unknown Sequence"); + } + } + else + { + DCMDATA_ERROR("DcmDicomDir::moveRecordToTree() Cannot insert DirRecord (=NULL?)"); + } + moveRecordToTree( lowerRec, fromDirSQ, startRec ); + + // We handled this record, now move on to the next one on this level. + // The next while-loop iteration does the equivalent of the following: + // moveRecordToTree( nextRec, fromDirSQ, toRecord ); + startRec = nextRec; + } + } + + return l_error; +} + + +// ******************************** + + +OFCondition DcmDicomDir::moveMRDRbetweenSQs( DcmSequenceOfItems &fromSQ, + DcmSequenceOfItems &toSQ ) +{ + OFCondition l_error = EC_Normal; + + unsigned long num = fromSQ.card(); + for (unsigned long i = 0, j = 0; i < num; i++) + { + DcmDirectoryRecord *dRec; + dRec = OFstatic_cast(DcmDirectoryRecord *, fromSQ.getItem( j )); + if (dRec != NULL && dRec->getRecordType() == ERT_Mrdr) + { + toSQ.insert( dRec ); + fromSQ.remove( j ); + } else + j++; + } + + return l_error; +} + + +// ******************************** + + +OFCondition DcmDicomDir::convertLinearToTree() +{ + DcmDataset &dset = getDataset(); // guaranteed to exist + DcmSequenceOfItems &localDirRecSeq = getDirRecSeq( dset ); + OFCondition l_error = resolveAllOffsets( dset ); + + // search for first directory record: + DcmDirectoryRecord *firstRootRecord = NULL; + DcmUnsignedLongOffset *offElem = lookForOffsetElem( &dset, DCM_OffsetOfTheFirstDirectoryRecordOfTheRootDirectoryEntity ); + if ( offElem != NULL ) + firstRootRecord = OFstatic_cast(DcmDirectoryRecord *, offElem->getNextRecord()); + + // create tree structure from flat record list: + moveRecordToTree( firstRootRecord, localDirRecSeq, &getRootRecord() ); + + // move MRDRs from localDirRecSeq to global MRDRSeq: + moveMRDRbetweenSQs( localDirRecSeq, getMRDRSequence() ); + + // dissolve MRDR references for all remaining items + for (unsigned long i = localDirRecSeq.card(); i > 0; i-- ) + linkMRDRtoRecord( OFstatic_cast(DcmDirectoryRecord *, localDirRecSeq.getItem(i-1)) ); + + return l_error; +} + + +// ******************************** +// ******************************** + + +Uint32 DcmDicomDir::lengthUntilSQ(DcmDataset &dset, + E_TransferSyntax oxfer, + E_EncodingType enctype ) +{ + Uint32 templen = 0L; + unsigned long num = dset.card(); + for (unsigned long i = 0; i < num; i++ ) + { + DcmObject *dO = dset.getElement( i ); + + DcmXfer xf(oxfer); + templen += xf.sizeofTagHeader(dO->getVR()); + + if ( dO->getTag().getXTag() == DCM_DirectoryRecordSequence ) + break; + + Uint32 sublength = dO->getLength( oxfer, enctype ); + templen += sublength; + if ( sublength==DCM_UndefinedLength ) + { + DcmVR subvr( dO->getVR() ); + DCMDATA_WARN("DcmDicomDir::lengthUntilSQ() Sub element \"" << subvr.getVRName() << "\" has undefined Length"); + } + + if ( dO->getVR() == EVR_SQ && enctype == EET_UndefinedLength ) + templen += 8; // for ItemDelimitationItem + + } + DCMDATA_TRACE("DcmDicomDir::lengthUntilSQ() Length of Dataset until SQ=" << templen); + + return templen; +} + + +// ******************************** + + +Uint32 DcmDicomDir::lengthOfRecord( DcmItem *item, + E_TransferSyntax oxfer, + E_EncodingType enctype ) +{ + Uint32 templen = 0; + if ( item != NULL ) + { + templen = item->getLength( oxfer, enctype ); + + templen += 8; // for Tag and Length + + if ( enctype == EET_UndefinedLength ) + templen += 8; // for ItemDelimitationItem + } + return templen; +} + + +// ******************************** + + +OFCondition DcmDicomDir::convertGivenPointer( DcmObject *startPoint, + const DcmTagKey &offsetTag ) +{ + OFCondition l_error = EC_Normal; + if ( startPoint != NULL ) + { + DcmStack stack; + for (;;) + { + l_error = startPoint->nextObject(stack, OFTrue); + if (l_error.bad()) + break; + + DcmObject *cur = stack.top(); + if (cur->ident() != EVR_up || cur->getTag() != offsetTag) + continue; + + DcmUnsignedLongOffset *offElem = OFstatic_cast(DcmUnsignedLongOffset *, cur); + DcmObject *obj = offElem->getNextRecord(); + if (obj != NULL) + offElem->putUint32(OFstatic_cast(DcmDirectoryRecord *, obj)->getFileOffset()); + else + offElem->putUint32(0); + } + } + + return l_error; +} + + +// ******************************** + + +OFCondition DcmDicomDir::convertAllPointer( DcmDataset &dset, // inout + Uint32 beginOfDataSet, // in + E_TransferSyntax oxfer, // in + E_EncodingType enctype ) // in +{ + OFCondition l_error = EC_Normal; + DcmObject *obj = NULL; + DcmDirectoryRecord *rec = NULL; + DcmSequenceOfItems &localDirRecSeq = getDirRecSeq( dset ); + Uint32 offs_Item1 = beginOfDataSet + lengthUntilSQ( dset, oxfer, enctype ); + unsigned long num = localDirRecSeq.card(); + + Uint32 item_pos = offs_Item1; + for (unsigned long i = 0; i < num; i++ ) + { + obj = localDirRecSeq.nextInContainer(obj); + rec = OFstatic_cast(DcmDirectoryRecord *, obj); + rec->setFileOffset( item_pos ); + item_pos = lengthOfRecord( rec, oxfer, enctype ) + item_pos; + } + + /* calling convertGivenPointer() requires that the above for-loop has been run through */ + OFCondition e1 = convertGivenPointer( &dset, DCM_OffsetOfTheFirstDirectoryRecordOfTheRootDirectoryEntity ); + OFCondition e2 = convertGivenPointer( &dset, DCM_OffsetOfTheLastDirectoryRecordOfTheRootDirectoryEntity ); + + OFCondition e3 = convertGivenPointer( &localDirRecSeq, DCM_OffsetOfTheNextDirectoryRecord ); + OFCondition e4 = convertGivenPointer( &localDirRecSeq, DCM_OffsetOfReferencedLowerLevelDirectoryEntity ); + OFCondition e5 = convertGivenPointer( &localDirRecSeq, DCM_RETIRED_MRDRDirectoryRecordOffset ); + + if ( e1 == EC_InvalidVR || e2 == EC_InvalidVR || e3 == EC_InvalidVR || e4 == EC_InvalidVR || e5 == EC_InvalidVR ) + l_error = EC_InvalidVR; + + return l_error; +} + + +// ******************************** + + +OFCondition DcmDicomDir::copyRecordPtrToSQ( DcmDirectoryRecord *record, + DcmSequenceOfItems &toDirSQ, + DcmDirectoryRecord **firstRec, + DcmDirectoryRecord **lastRec ) +{ + DcmDirectoryRecord *nextRec = NULL; + DcmDirectoryRecord *lastReturnItem = NULL; + + if ( record != NULL ) + { + unsigned long lastIndex = record->cardSub(); + for (unsigned long i = lastIndex; i > 0; i-- ) + { + DCMDATA_DEBUG("DcmDicomDir::copyRecordPtrToSQ() Testing sub record no. " << i << " of " << lastIndex); + + DcmDirectoryRecord *subRecord = record->getSub( i-1 ); + + if ( subRecord != NULL ) + { + DcmUnsignedLongOffset *uloP; + if ( i == lastIndex ) + lastReturnItem = subRecord; // memorize last item + // adjust nextPointer + DcmTag nextRecTag( DCM_OffsetOfTheNextDirectoryRecord ); + uloP = new DcmUnsignedLongOffset( nextRecTag ); + uloP->putUint32(Uint32(0)); + uloP->setNextRecord( nextRec ); + subRecord->insert( uloP, OFTrue ); +#ifdef DEBUG + Uint32 l_uint = 0; + uloP->getUint32(l_uint); + DCMDATA_TRACE("DcmDicomDir::copyRecordPtrToSQ() Next Offset Element " + << uloP->getTag() << " offs=0x" << STD_NAMESPACE hex + << STD_NAMESPACE setfill('0') << STD_NAMESPACE setw(8) << l_uint + << " p=" << OFstatic_cast(void *, uloP) + << " next=" << OFstatic_cast(void *, nextRec)); +#endif + copyRecordPtrToSQ( subRecord, toDirSQ, firstRec, lastRec ); + + // adjust lowerPointer + DcmTag lowerRefTag( DCM_OffsetOfReferencedLowerLevelDirectoryEntity ); + uloP = new DcmUnsignedLongOffset( lowerRefTag ); + uloP->putUint32(Uint32(0)); + uloP->setNextRecord( *firstRec ); + subRecord->insert( uloP, OFTrue ); +#ifdef DEBUG + uloP->getUint32(l_uint); + DCMDATA_TRACE("DcmDicomDir::copyRecordPtrToSQ() Lower Offset Element " + << uloP->getTag() << " offs=0x" << STD_NAMESPACE hex + << STD_NAMESPACE setfill('0') << STD_NAMESPACE setw(8) << l_uint + << " p=" << OFstatic_cast(void *, uloP) + << " lower=" << OFstatic_cast(void *, *firstRec)); +#endif + + /* insert at beginning */ + toDirSQ.prepend( subRecord ); + + nextRec = subRecord; + } + } // for ( i ... + } + if ( lastRec != NULL ) + *lastRec = lastReturnItem; + // points to first record of subordinate level + if ( firstRec != NULL ) + *firstRec = nextRec; + return EC_Normal; +} + + +// ******************************** + + +OFCondition DcmDicomDir::convertTreeToLinear(Uint32 beginOfDataSet, + E_TransferSyntax oxfer, + E_EncodingType enctype, + E_GrpLenEncoding glenc, + DcmSequenceOfItems &unresRecs ) +{ + OFCondition l_error = EC_Normal; + DcmDataset &dset = getDataset(); // guaranteed to exist + DcmSequenceOfItems &localDirRecSeq = getDirRecSeq( dset ); + + // copy items to which no pointer exists to a temporary list + unsigned long numUnresItems = localDirRecSeq.card(); + for (unsigned long i = numUnresItems; i > 0; i-- ) + { + DCMDATA_DEBUG("DcmDicomDir::convertTreeToLinear() Copy pointer of unresolved Record no. " + << i << " of " << numUnresItems << " to unresRecsSeq:"); + unresRecs.insert( localDirRecSeq.getItem(i-1), 0 ); + } + + // convert items back into the root directory entity: + DcmDirectoryRecord *firstRootRecord[1], *lastRootRecord[1]; + copyRecordPtrToSQ( &getRootRecord(), localDirRecSeq, firstRootRecord, lastRootRecord ); + + // set pointer to first directory record: + DcmUnsignedLongOffset *offElem = lookForOffsetElem( &dset, DCM_OffsetOfTheFirstDirectoryRecordOfTheRootDirectoryEntity ); + if ( offElem != NULL ) + offElem->setNextRecord( *firstRootRecord ); + + // set pointer to last directory record: + offElem = lookForOffsetElem( &dset, DCM_OffsetOfTheLastDirectoryRecordOfTheRootDirectoryEntity ); + if ( offElem != NULL ) + offElem->setNextRecord( *lastRootRecord ); + + // copy MRDRs in localDirRecSeq + unsigned long numMRDRItems = getMRDRSequence().card(); + for (unsigned long j = numMRDRItems; j > 0; j-- ) + { + DCMDATA_DEBUG("DcmDicomDir::convertTreeToLinear() Copy pointer of MRDR no. " << j << " of " + << numUnresItems << " to localDirRecSeq:"); + localDirRecSeq.insert( getMRDRSequence().getItem(j-1), 0 ); + } + + // compute group lengths before computing byte offsets + dset.computeGroupLengthAndPadding(glenc, EPD_noChange, oxfer, enctype); + + // convert maximum twice + if ( convertAllPointer( dset, beginOfDataSet, oxfer, enctype ) == EC_InvalidVR ) + if ( convertAllPointer( dset, beginOfDataSet, oxfer, enctype ) == EC_InvalidVR ) + { + DCMDATA_ERROR("DcmDicomDir: There are some incorrect Offsets in file " << dicomDirFileName); + l_error = EC_CorruptedData; + } + return l_error; +} + + +// ******************************** + + +OFCondition DcmDicomDir::insertMediaSOPUID( DcmMetaInfo &metaInfo ) // inout +{ + OFCondition l_error = EC_Normal; + DcmTag medSOPClassTag( DCM_MediaStorageSOPClassUID ); + DcmUniqueIdentifier *mediaStorageSOPClassUID = new DcmUniqueIdentifier( medSOPClassTag ); + const char* valueUID = UID_MediaStorageDirectoryStorage; + mediaStorageSOPClassUID->putString( valueUID ); + metaInfo.insert( mediaStorageSOPClassUID, OFTrue ); + return l_error; +} + + +// ******************************** + + +void DcmDicomDir::print(STD_NAMESPACE ostream&out, + const size_t flags, + const int level, + const char *pixelFileName, + size_t *pixelCounter) +{ + int i; + for ( i=0; iprint(out, flags, 1, pixelFileName, pixelCounter); // friend class + + out << OFendl; + for ( i=0; icardSub(); + for (unsigned long i = 0; i < lastIndex; i++ ) + { + DcmDirectoryRecord *subRecord = startRec->getSub( i ); + const char* subName = subRecord->lookForReferencedFileID(); // friend + + if ( subName != NULL && !strcmp( filename, subName ) ) + { + DCMDATA_DEBUG("DcmDicomDir::recurseMatchFile() Record p=" << OFstatic_cast(void *, subRecord) + << " with matching filename [" << subName << "] found"); + retRec = subRecord; + break; + } + else + retRec = recurseMatchFile( subRecord, filename ); + } + } + return retRec; +} + + +// ******************************** + + +DcmDirectoryRecord* DcmDicomDir::searchMatchFile( DcmSequenceOfItems& recSeq, + const char *filename ) +{ + DcmDirectoryRecord* retRec = NULL; + if ( filename != NULL && *filename != '\0' ) + { + unsigned long lastIndex = recSeq.card(); + for (unsigned long i = 0; i < lastIndex; i++ ) + { + DcmDirectoryRecord *record; + record = OFstatic_cast(DcmDirectoryRecord *, recSeq.getItem( i )); + const char* subName = record->lookForReferencedFileID(); // friend + + if ( subName != NULL && !strcmp( filename, subName ) ) + { + DCMDATA_DEBUG("DcmDicomDir::searchMatchFile() Record p=" << OFstatic_cast(void *, record) + << " with matching filename [" << subName << "] found"); + retRec = record; + break; + } + } + } + + return retRec; +} + + +// ******************************** + + +DcmDirectoryRecord* DcmDicomDir::matchFilename( const char *filename ) +{ + DcmDirectoryRecord* retRec = NULL; + if ( filename != NULL && *filename != '\0' ) + { + retRec = recurseMatchFile( &getRootRecord(), filename ); + if ( retRec == NULL ) + { + retRec = searchMatchFile( getMRDRSequence(), filename ); + if ( retRec == NULL ) + { + DcmDataset &dset = getDataset(); + retRec = searchMatchFile( getDirRecSeq(dset), filename ); + } + } + } + if (retRec == NULL) + { + DCMDATA_DEBUG("DcmDicomDir::matchFilename() No Record with matching filename [" + << filename << "] found"); + } + return retRec; +} + + +// ******************************** + + +DcmDirectoryRecord* DcmDicomDir::matchOrCreateMRDR( const char *filename ) +{ + DcmDirectoryRecord* newMRDR = NULL; + DcmDirectoryRecord* matchRec = matchFilename( filename ); + if ( matchRec != NULL ) + { + if ( matchRec->getRecordType() == ERT_Mrdr ) + newMRDR = matchRec; + else if ( matchRec->getRecordType() != ERT_root ) + { + newMRDR = new DcmDirectoryRecord( ERT_Mrdr, filename, OFFilename()); + if ( matchRec->assignToMRDR( newMRDR ) != EC_IllegalCall ) + getMRDRSequence().insert( newMRDR ); + else + { + delete newMRDR; + newMRDR = NULL; + DCMDATA_ERROR("DcmDicomDir: Internal ERROR: Can't Create MRDR"); + } + if (newMRDR != NULL) + { + DCMDATA_DEBUG("DcmDicomDir::matchOrCreateMRDR() New MRDR p=" << OFstatic_cast(void *, newMRDR) + << " with matching filename [" << filename << "] created, original Record p=" + << OFstatic_cast(void *, matchRec) << " with same filename modified"); + } + modified = OFTrue; + } + } + if (newMRDR == NULL) + DCMDATA_WARN("DcmDicomDir::matchOrCreateMRDR() No MRDR with matching filename [" << filename << "] found"); + + return newMRDR; +} + + +// ******************************** +// ******************************** + + +OFCondition DcmDicomDir::write(const E_TransferSyntax oxfer, + const E_EncodingType enctype, + const E_GrpLenEncoding glenc) +{ + if (oxfer != DICOMDIR_DEFAULT_TRANSFERSYNTAX) + { + DCMDATA_ERROR("DcmDicomDir::write() Wrong TransferSyntax used, only LittleEndianExplicit allowed"); + } + errorFlag = EC_Normal; + E_TransferSyntax outxfer = DICOMDIR_DEFAULT_TRANSFERSYNTAX; + + // create a temporary file based on the DICOMDIR filename + OFFilename tempFilename; + OFStandard::appendFilenameExtension(tempFilename, dicomDirFileName, DICOMDIR_TEMP_SUFFIX); + + DcmOutputFileStream *outStream = new DcmOutputFileStream(tempFilename); + if (! outStream->good()) + { + DCMDATA_ERROR("DcmDicomDir: Cannot create DICOMDIR temporary file: " << tempFilename); + errorFlag = outStream->status(); + delete outStream; + return errorFlag; + } + + DcmDataset &dset = getDataset(); // guaranteed to exist + DcmMetaInfo &metainfo = *(getDirFileFormat().getMetaInfo()); + DcmSequenceOfItems &localDirRecSeq = getDirRecSeq(dset); + DcmTag unresSeqTag(DCM_DirectoryRecordSequence); + DcmSequenceOfItems localUnresRecs(unresSeqTag); + + // insert Media Stored SOP Class UID + insertMediaSOPUID(metainfo); + + getDirFileFormat().validateMetaInfo(outxfer); + + { + // it is important that the cache object is destroyed before the file is renamed! + // Therefore, the variable declaration is "encapsulated" in curly brackets. + DcmWriteCache wcache; + + metainfo.transferInit(); + metainfo.write(*outStream, META_HEADER_DEFAULT_TRANSFERSYNTAX, enctype, &wcache); + metainfo.transferEnd(); + + Uint32 beginOfDataset = OFstatic_cast(Uint32, outStream->tell()); + + // convert to writable format + errorFlag = convertTreeToLinear(beginOfDataset, outxfer, enctype, glenc, localUnresRecs); + + dset.transferInit(); + // do not calculate GroupLength and Padding twice! + dset.write(*outStream, outxfer, enctype, &wcache, EGL_noChange); + dset.transferEnd(); + } + + // outStream is closed here + delete outStream; + + OFFilename backupFilename; + if (!mustCreateNewDir) + { +#ifndef DICOMDIR_WITHOUT_BACKUP + // create a temporary backup of the existing DICOMDIR + OFStandard::appendFilenameExtension(backupFilename, dicomDirFileName, DICOMDIR_BACKUP_SUFFIX); + OFStandard::deleteFile(backupFilename); + if (errorFlag == EC_Normal) + { + if (!OFStandard::renameFile(dicomDirFileName, backupFilename)) + { + char buf[256]; + const char *text = OFStandard::strerror(errno, buf, sizeof(buf)); + if (text == NULL) text = "(unknown error code)"; + errorFlag = makeOFCondition(OFM_dcmdata, 19, OF_error, text); + } + } +#else + if (!OFStandard::deleteFile(dicomDirFileName)) + { + char buf[256]; + const char *text = OFStandard::strerror(errno, buf, sizeof(buf)); + if (text == NULL) text = "(unknown error code)"; + errorFlag = makeOFCondition(OFM_dcmdata, 19, OF_error, text); + } +#endif + } + + if (errorFlag == EC_Normal && !OFStandard::renameFile(tempFilename, dicomDirFileName)) + { + char buf[256]; + const char *text = OFStandard::strerror(errno, buf, sizeof(buf)); + if (text == NULL) text = "(unknown error code)"; + errorFlag = makeOFCondition(OFM_dcmdata, 19, OF_error, text); + } + + modified = OFFalse; + + if (errorFlag == EC_Normal) { + // remove temporary backup (if any) + OFStandard::deleteFile(backupFilename); + } + + // remove all records from sequence localDirRecSeq + while (localDirRecSeq.card() > 0) + localDirRecSeq.remove(OFstatic_cast(unsigned long, 0)); + + // move records to which no pointer exists back + while (localUnresRecs.card() > 0) + { + DcmItem *unresRecord = + localUnresRecs.remove(OFstatic_cast(unsigned long, 0)); + localDirRecSeq.insert(unresRecord); + } + return errorFlag; +} + + +// ******************************** +// ******************************** + + +OFCondition DcmDicomDir::countMRDRRefs( DcmDirectoryRecord *startRec, + ItemOffset *refCounter, + const unsigned long numCounters ) +{ + OFCondition l_error = EC_Normal; + if ( refCounter == NULL ) + l_error = EC_IllegalCall; + else if ( startRec != NULL ) + { + unsigned long lastIndex = startRec->cardSub(); + for (unsigned long i = 0; i < lastIndex; i++ ) + { + DcmDirectoryRecord *subRecord = startRec->getSub( i ); + DcmDirectoryRecord *refMRDR = subRecord->lookForReferencedMRDR(); + // friend class + if ( refMRDR != NULL ) + { + unsigned long j; + for ( j = 0; j < numCounters; j++ ) + { + if ( refMRDR == refCounter[ j ].item ) + { + ++refCounter[ j ].fileOffset; // Reference counter + break; + } + } + DCMDATA_DEBUG("DcmDicomDir::countMRDRRefs() MRDR p=" << OFstatic_cast(void *, refMRDR) + << " found, which is " << refMRDR->numberOfReferences << " times referenced and " + << j << " times counted"); + } + countMRDRRefs( subRecord, refCounter, numCounters ); + } + } + return l_error; +} + + +// ******************************** + + +OFCondition DcmDicomDir::checkMRDRRefCounter( DcmDirectoryRecord *startRec, + ItemOffset *refCounter, + const unsigned long numCounters ) +{ + OFCondition l_error = EC_Normal; + if ( refCounter == NULL ) + l_error = EC_IllegalCall; + else if ( startRec != NULL ) + { + unsigned long lastIndex = startRec->cardSub(); + for (unsigned long i = 0; i < lastIndex; i++ ) + { + DcmDirectoryRecord *subRecord = startRec->getSub( i ); + DcmDirectoryRecord *refMRDR = subRecord->lookForReferencedMRDR(); + // friend class + if ( refMRDR != NULL ) + { + unsigned long j; + for ( j = 0; j < numCounters; j++ ) + { + if ( refMRDR == refCounter[ j ].item ) + { + ++refCounter[ j ].fileOffset; // reference counter + break; + } + } + DCMDATA_DEBUG("DcmDicomDir::checkMRDRRefCounter() MRDR p=" << OFstatic_cast(void *, refMRDR) + << " found, which is " << refMRDR->numberOfReferences << " times referenced and " + << j << " times counted"); + } + OFCondition err1 = checkMRDRRefCounter( subRecord, refCounter, numCounters ); + if ( l_error == EC_Normal && err1 != EC_Normal ) + l_error = err1; // the first error counts + } + } + return l_error; +} + + +// ******************************** + +/* GERMAN COMMENT - PLEASE IGNORE + + Strategie fuer verify (mit autocorrect==OFTrue): + - lege Tabelle an mit Zeigern auf MRDRs und Referenzzaehlern mit der Groesse + getDirRecSeq( getDataset() ).card() + getMRDRSequence().card() + - durchlaufe den Record-Baum und erhoehe bei jedem Auftreten eines + MRDR-Verweises, den entsprechenden Zaehler in obiger Tabelle + - setze in allen MRDRs, auf die laut Tabelle kein Verweis existiert, das + activation flag auf INAKTIV +PENDING: + - ueberpruefe fuer alle inaktiven MRDRs, ob deren referenzierte Dateien + von keinem anderen Record referenziert werden und loesche dann + gegebenenfalls die Dateien + - loesche alle inaktiven MRDRs aus der Sequenz getMRDRSequence() + - uebertrage alle aktiven MRDRs aus der Sequenz getDirRecSeq( getDataset() ) + in die Sequenz getMRDRSequence() + - loesche die gesamte Sequenz getDirRecSeq( getDataset() ), unter Inkaufnahme + eines Datenverlustes: es kann nicht automatisch entschieden werden, an + welche Position innerhalb der Record-Hierearchie die zu loeschenden + Records eingefuegt werden muessen +*/ + +OFCondition DcmDicomDir::verify( OFBool autocorrect ) +{ + errorFlag = EC_Normal; + DcmSequenceOfItems &localDirRecSeq = getDirRecSeq(getDataset()); + unsigned long maxMRDRs = localDirRecSeq.card() + getMRDRSequence().card(); + ItemOffset *refCounter = new ItemOffset[ maxMRDRs ]; + + // create MRDR table for MRDRs from MRDRSeq and from DirRecSeq: + unsigned long i; + for ( i = 0; i < getMRDRSequence().card(); i++ ) + { + DcmDirectoryRecord *rec; + rec = OFstatic_cast(DcmDirectoryRecord *, getMRDRSequence().getItem( i )); + refCounter[i].item = rec; + refCounter[i].fileOffset = 0L; + } + for (unsigned long j = 0; j < localDirRecSeq.card() && i < maxMRDRs; j++ ) + { + DcmDirectoryRecord *rec; + rec = OFstatic_cast(DcmDirectoryRecord *, localDirRecSeq.getItem( j )); + if ( rec->getRecordType() == ERT_Mrdr ) + { + refCounter[i].item = rec; + refCounter[i].fileOffset = 0L; + i++; + } + } +// maxMRDRs = i; // adjust table size to real value + + // count number of references for each MRDR + countMRDRRefs( &getRootRecord(), refCounter, maxMRDRs ); + + // check stored reference counters for correctness + OFCondition err3 = EC_Normal; + for (unsigned long k = 0; k < maxMRDRs; k++ ) + { + DcmDirectoryRecord *refMRDR = OFstatic_cast(DcmDirectoryRecord *, refCounter[k].item); + Uint32 refNum = refMRDR->lookForNumberOfReferences(); // friend + if ( refCounter[k].fileOffset != refNum ) + { + DCMDATA_ERROR("DcmDicomDir::verify() Reference counter of MRDR p=" << OFstatic_cast(void *, refMRDR) + << " has incorrect value=" << refNum << " (must be " << refCounter[k].fileOffset << ")"); + if (refCounter[k].fileOffset==refMRDR->numberOfReferences) + DCMDATA_ERROR("but internal record class value numberOfReferences is correct"); + + if ( autocorrect ) // correct reference counter, friend + refMRDR->setNumberOfReferences( refCounter[k].fileOffset ); + else + err3 = EC_CorruptedData; + } + // set inactivation flag for MRDRs without reference + if ( autocorrect && refCounter[k].fileOffset == 0L ) + refMRDR->setRecordInUseFlag( 0xffff ); + } + + delete[] refCounter; + OFCondition err1 = getDirFileFormat().verify( autocorrect ); + OFCondition err2 = getRootRecord().verify( OFFalse ); // no automatic correction + if ( errorFlag == EC_Normal && ( err1 != EC_Normal || err2 != EC_Normal || err3 != EC_Normal ) ) + errorFlag = EC_CorruptedData; + return errorFlag; +} diff --git a/dcmdata/libsrc/dcdicent.cc b/dcmdata/libsrc/dcdicent.cc new file mode 100644 index 00000000..bff230de --- /dev/null +++ b/dcmdata/libsrc/dcdicent.cc @@ -0,0 +1,174 @@ +/* + * + * Copyright (C) 1994-2010, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Andrew Hewett + * + * Purpose: a dictionary entry in the loadable DICOM data dictionary + * + */ + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#define INCLUDE_CSTDIO +#define INCLUDE_CSTRING +#include "dcmtk/ofstd/ofstdinc.h" + +#include "dcmtk/dcmdata/dcdicent.h" + +/* +** DcmDictEntry member functions +*/ + +static +char* strdup_new(const char* str) +{ + char* s = NULL; + if (str != NULL) { + s = new char[strlen(str)+1]; + strcpy(s, str); + } + return s; +} + +DcmDictEntry::DcmDictEntry(Uint16 g, Uint16 e, DcmVR vr, + const char* nam, int vmMin, int vmMax, + const char* vers, OFBool doCopyStrings, + const char* pcreator) + : DcmTagKey(g,e), + upperKey(), + valueRepresentation(EVR_UNKNOWN), + tagName(nam), + valueMultiplicityMin(vmMin), + valueMultiplicityMax(vmMax), + standardVersion(vers), + stringsAreCopies(doCopyStrings), + groupRangeRestriction(DcmDictRange_Unspecified), + elementRangeRestriction(DcmDictRange_Unspecified), + privateCreator(pcreator) +{ + upperKey.set(g,e); /* default: make upper key same as normal key */ + valueRepresentation.setVR(vr); + if (doCopyStrings) { + tagName = strdup_new(nam); + standardVersion = strdup_new(vers); + privateCreator = strdup_new(pcreator); + } +} + +DcmDictEntry::DcmDictEntry(Uint16 g, Uint16 e, Uint16 ug, Uint16 ue, DcmVR vr, + const char* nam, int vmMin, int vmMax, + const char* vers, OFBool doCopyStrings, + const char* pcreator) + : DcmTagKey(g,e), + upperKey(), + valueRepresentation(EVR_UNKNOWN), + tagName(nam), + valueMultiplicityMin(vmMin), + valueMultiplicityMax(vmMax), + standardVersion(vers), + stringsAreCopies(doCopyStrings), + groupRangeRestriction(DcmDictRange_Unspecified), + elementRangeRestriction(DcmDictRange_Unspecified), + privateCreator(pcreator) +{ + upperKey.set(ug, ue); + valueRepresentation.setVR(vr); + if (doCopyStrings) { + tagName = strdup_new(nam); + standardVersion = strdup_new(vers); + privateCreator = strdup_new(pcreator); + } +} + +DcmDictEntry::DcmDictEntry(const DcmDictEntry& e) + : DcmTagKey(e), + upperKey(e.upperKey), + valueRepresentation(e.valueRepresentation), + tagName(e.tagName), + valueMultiplicityMin(e.valueMultiplicityMin), + valueMultiplicityMax(e.valueMultiplicityMax), + standardVersion(e.standardVersion), + stringsAreCopies(e.stringsAreCopies), + groupRangeRestriction(e.groupRangeRestriction), + elementRangeRestriction(e.elementRangeRestriction), + privateCreator(e.privateCreator) +{ + if (stringsAreCopies) + { + tagName = strdup_new(e.tagName); + standardVersion = strdup_new(e.standardVersion); + privateCreator = strdup_new(e.privateCreator); + } +} + + +DcmDictEntry::~DcmDictEntry() +{ + if (stringsAreCopies) { + /* we have allocated them so it is ok to deallocate them */ + delete[] OFconst_cast(char *, tagName); + delete[] OFconst_cast(char *, standardVersion); + delete[] OFconst_cast(char *, privateCreator); + } +} + +/* +** DcmDictEntry friend functions +*/ + +STD_NAMESPACE ostream& operator<<(STD_NAMESPACE ostream& s, const DcmDictEntry& e) { + + const DcmDictEntry* ep = &e; + if (ep == NULL) { + s << "(nil)"; + return s; + } + + char tagBuf[16]; + + sprintf(tagBuf, "(%04x", e.getGroup()); + s << tagBuf; + if (e.isRepeatingGroup()) { + sprintf(tagBuf, "-%04x", e.getUpperGroup()); + s << tagBuf; + } + sprintf(tagBuf, ",%04x", e.getElement()); + s << tagBuf; + if (e.isRepeatingElement()) { + sprintf(tagBuf, "-%04x", e.getUpperElement()); + s << tagBuf; + } + s << ")"; + + + s << " " << e.getVR().getVRName() << " \"" << e.getTagName() << "\" "; + if (e.isFixedSingleVM()) { + s << "vm=" << e.getVMMax() << " "; + } else if (e.isVariableRangeVM()) { + s << "vm=" << e.getVMMin() << "-n "; + } else if (e.isFixedRangeVM()){ + s << "vm=" << e.getVMMin() << "-" << e.getVMMax() << " "; + } else { + s << "vm=?(" << e.getVMMin() << "-" << e.getVMMax() << ")? "; + } + if (e.getStandardVersion() != NULL) { + s << " Version=\"" << e.getStandardVersion() << "\" "; + } + if (e.getPrivateCreator() != NULL) { + s << " priv=\"" << e.getPrivateCreator() << "\" "; + } + + return s; +} diff --git a/dcmdata/libsrc/dcdict.cc b/dcmdata/libsrc/dcdict.cc new file mode 100644 index 00000000..da19a668 --- /dev/null +++ b/dcmdata/libsrc/dcdict.cc @@ -0,0 +1,878 @@ +/* + * + * Copyright (C) 1994-2015, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Andrew Hewett + * + * Purpose: loadable DICOM data dictionary + * + */ + + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/ofstd/ofstd.h" +#include "dcmtk/dcmdata/dcdict.h" +#include "dcmtk/ofstd/ofdefine.h" +#include "dcmtk/dcmdata/dcdicent.h" +#include "dcmtk/dcmdata/dctypes.h" + +#define INCLUDE_CSTDLIB +#define INCLUDE_CSTDIO +#define INCLUDE_CSTRING +#define INCLUDE_CCTYPE +#include "dcmtk/ofstd/ofstdinc.h" + +/* +** The separator character between fields in the data dictionary file(s) +*/ +#define DCM_DICT_FIELD_SEPARATOR_CHAR '\t' + +/* +** Comment character for the data dictionary file(s) +*/ +#define DCM_DICT_COMMENT_CHAR '#' + +/* +** THE Global DICOM Data Dictionary +*/ + +GlobalDcmDataDictionary dcmDataDict; + + +/* +** Member Functions +*/ + +static DcmDictEntry* +makeSkelEntry(Uint16 group, Uint16 element, + Uint16 upperGroup, Uint16 upperElement, + DcmEVR evr, const char* tagName, int vmMin, int vmMax, + const char* standardVersion, + DcmDictRangeRestriction groupRestriction, + DcmDictRangeRestriction elementRestriction, + const char* privCreator) +{ + DcmDictEntry* e = NULL; + e = new DcmDictEntry(group, element, upperGroup, upperElement, evr, + tagName, vmMin, vmMax, standardVersion, OFFalse, privCreator); + if (e != NULL) { + e->setGroupRangeRestriction(groupRestriction); + e->setElementRangeRestriction(elementRestriction); + } + return e; +} + + +OFBool DcmDataDictionary::loadSkeletonDictionary() +{ + /* + ** We need to know about Group Lengths to compute them + */ + DcmDictEntry* e = NULL; + e = makeSkelEntry(0x0000, 0x0000, 0xffff, 0x0000, + EVR_UL, "GenericGroupLength", 1, 1, "GENERIC", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL); + addEntry(e); + + /* + ** We need to know about Items and Delimitation Items to parse + ** (and construct) sequences. + */ + e = makeSkelEntry(0xfffe, 0xe000, 0xfffe, 0xe000, + EVR_na, "Item", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL); + addEntry(e); + e = makeSkelEntry(0xfffe, 0xe00d, 0xfffe, 0xe00d, + EVR_na, "ItemDelimitationItem", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL); + addEntry(e); + e = makeSkelEntry(0xfffe, 0xe0dd, 0xfffe, 0xe0dd, + EVR_na, "SequenceDelimitationItem", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, NULL); + addEntry(e); + + skeletonCount = numberOfEntries(); + return OFTrue; +} + + +DcmDataDictionary::DcmDataDictionary(OFBool loadBuiltin, OFBool loadExternal) + : hashDict(), + repDict(), + skeletonCount(0), + dictionaryLoaded(OFFalse) +{ + reloadDictionaries(loadBuiltin, loadExternal); +} + +DcmDataDictionary::~DcmDataDictionary() +{ + clear(); +} + + +void DcmDataDictionary::clear() +{ + hashDict.clear(); + repDict.clear(); + skeletonCount = 0; + dictionaryLoaded = OFFalse; +} + + +static void +stripWhitespace(char* s) +{ + if (s) + { + register unsigned char c; + register unsigned char *t; + register unsigned char *p; + t=p=OFreinterpret_cast(unsigned char *, s); + while ((c = *t++)) if (!isspace(c)) *p++ = c; + *p = '\0'; + } +} + +static char* +stripTrailingWhitespace(char* s) +{ + if (s == NULL) return s; + for + ( + char* it = s + strlen(s) - 1; + it >= s && isspace(OFstatic_cast(unsigned char, *it)); + *it-- = '\0' + ); + return s; +} + +static void +stripLeadingWhitespace(char* s) +{ + if (s) + { + register unsigned char c; + register unsigned char *t; + register unsigned char *p; + t=p=OFreinterpret_cast(unsigned char *, s); + while (isspace(*t)) t++; + while ((c = *t++)) *p++ = c; + *p = '\0'; + } +} + +static OFBool +parseVMField(char* vmField, int& vmMin, int& vmMax) +{ + OFBool ok = OFTrue; + char c = 0; + int dummy = 0; + + /* strip any whitespace */ + stripWhitespace(vmField); + + if (sscanf(vmField, "%d-%d%c", &vmMin, &dummy, &c) == 3) { + /* treat "2-2n" like "2-n" for the moment */ + if ((c == 'n') || (c == 'N')) { + vmMax = DcmVariableVM; + } else { + ok = OFFalse; + } + } else if (sscanf(vmField, "%d-%d", &vmMin, &vmMax) == 2) { + /* range VM (e.g. "2-6") */ + } else if (sscanf(vmField, "%d-%c", &vmMin, &c) == 2) { + if ((c == 'n') || (c == 'N')) { + vmMax = DcmVariableVM; + } else { + ok = OFFalse; + } + } else if (sscanf(vmField, "%d%c", &vmMin, &c) == 2) { + /* treat "2n" like "2-n" for the moment */ + if ((c == 'n') || (c == 'N')) { + vmMax = DcmVariableVM; + } else { + ok = OFFalse; + } + } else if (sscanf(vmField, "%d", &vmMin) == 1) { + /* fixed VM */ + vmMax = vmMin; + } else if (sscanf(vmField, "%c", &c) == 1) { + /* treat "n" like "1-n" */ + if ((c == 'n') || (c == 'N')) { + vmMin = 1; + vmMax = DcmVariableVM; + } else { + ok = OFFalse; + } + } else { + ok = OFFalse; + } + return ok; +} + +static int +splitFields(const char* line, char* fields[], int maxFields, char splitChar) +{ + const char *p; + int foundFields = 0; + size_t len; + + do { +#ifdef __BORLANDC__ + // Borland Builder expects a non-const argument + p = strchr(OFconst_cast(char *, line), splitChar); +#else + p = strchr(line, splitChar); +#endif + if (p == NULL) { + len = strlen(line); + } else { + len = p - line; + } + fields[foundFields] = OFstatic_cast(char *, malloc(len + 1)); + strncpy(fields[foundFields], line, len); + fields[foundFields][len] = '\0'; + foundFields++; + line = p + 1; + } while ((foundFields < maxFields) && (p != NULL)); + + return foundFields; +} + +static OFBool +parseTagPart(char *s, unsigned int& l, unsigned int& h, + DcmDictRangeRestriction& r) +{ + OFBool ok = OFTrue; + char restrictor = ' '; + + r = DcmDictRange_Unspecified; /* by default */ + + if (sscanf(s, "%x-%c-%x", &l, &restrictor, &h) == 3) { + switch (restrictor) { + case 'o': + case 'O': + r = DcmDictRange_Odd; + break; + case 'e': + case 'E': + r = DcmDictRange_Even; + break; + case 'u': + case 'U': + r = DcmDictRange_Unspecified; + break; + default: + DCMDATA_ERROR("DcmDataDictionary: Unknown range restrictor: " << restrictor); + ok = OFFalse; + break; + } + } else if (sscanf(s, "%x-%x", &l, &h) == 2) { + r = DcmDictRange_Even; /* by default */ + } else if (sscanf(s, "%x", &l) == 1) { + h = l; + } else { + ok = OFFalse; + } + return ok; +} + +static OFBool +parseWholeTagField(char* s, DcmTagKey& key, + DcmTagKey& upperKey, + DcmDictRangeRestriction& groupRestriction, + DcmDictRangeRestriction& elementRestriction, + char *&privCreator) +{ + unsigned int gl, gh, el, eh; + groupRestriction = DcmDictRange_Unspecified; + elementRestriction = DcmDictRange_Unspecified; + + stripLeadingWhitespace(s); + stripTrailingWhitespace(s); + + char gs[64]; + char es[64]; + char pc[64]; + size_t slen = strlen(s); + + if (s[0] != '(') return OFFalse; + if (s[slen - 1] != ')') return OFFalse; + if (strchr(s, ',') == NULL) return OFFalse; + + /* separate the group and element parts */ + int i = 1; /* after the '(' */ + int gi = 0; + for (; s[i] != ',' && s[i] != '\0'; i++) + { + gs[gi] = s[i]; + gi++; + } + gs[gi] = '\0'; + + if (s[i] == '\0') return OFFalse; /* element part missing */ + i++; /* after the ',' */ + + stripLeadingWhitespace(s + i); + + int pi = 0; + if (s[i] == '\"') /* private creator */ + { + i++; // skip opening quotation mark + for (; s[i] != '\"' && s[i] != '\0'; i++) pc[pi++] = s[i]; + pc[pi] = '\0'; + if (s[i] == '\0') return OFFalse; /* closing quotation mark missing */ + i++; + stripLeadingWhitespace(s + i); + if (s[i] != ',') return OFFalse; /* element part missing */ + i++; /* after the ',' */ + } + + int ei = 0; + for (; s[i] != ')' && s[i] != '\0'; i++) { + es[ei] = s[i]; + ei++; + } + es[ei] = '\0'; + + /* parse the tag parts into their components */ + stripWhitespace(gs); + if (parseTagPart(gs, gl, gh, groupRestriction) == OFFalse) + return OFFalse; + + stripWhitespace(es); + if (parseTagPart(es, el, eh, elementRestriction) == OFFalse) + return OFFalse; + + if (pi > 0) + { + // copy private creator name + privCreator = new char[strlen(pc) + 1]; // deleted by caller + if (privCreator) strcpy(privCreator,pc); + } + + key.set(OFstatic_cast(unsigned short, gl), OFstatic_cast(unsigned short, el)); + upperKey.set(OFstatic_cast(unsigned short, gh), OFstatic_cast(unsigned short, eh)); + + return OFTrue; +} + +static OFBool +onlyWhitespace(const char* s) +{ + size_t len = strlen(s); + int charsFound = OFFalse; + + for (size_t i = 0; (!charsFound) && (i < len); ++i) { + charsFound = !isspace(OFstatic_cast(unsigned char, s[i])); + } + return (!charsFound)? (OFTrue) : (OFFalse); +} + +static char* +getLine(char* line, int maxLineLen, FILE* f) +{ + char* s; + + s = fgets(line, maxLineLen, f); + + /* strip any trailing white space */ + stripTrailingWhitespace(line); + + return s; +} + +static OFBool +isaCommentLine(const char* s) +{ + OFBool isComment = OFFalse; /* assumption */ + size_t len = strlen(s); + size_t i = 0; + for (i = 0; i < len && isspace(OFstatic_cast(unsigned char, s[i])); ++i) /*loop*/; + isComment = (s[i] == DCM_DICT_COMMENT_CHAR); + return isComment; +} + +OFBool +DcmDataDictionary::reloadDictionaries(OFBool loadBuiltin, OFBool loadExternal) +{ + OFBool result = OFTrue; + clear(); + loadSkeletonDictionary(); + if (loadBuiltin) { + loadBuiltinDictionary(); + dictionaryLoaded = (numberOfEntries() > skeletonCount); + if (!dictionaryLoaded) result = OFFalse; + } + if (loadExternal) { + if (loadExternalDictionaries()) + dictionaryLoaded = OFTrue; + else + result = OFFalse; + } + return result; +} + +OFBool +DcmDataDictionary::loadDictionary(const char* fileName, OFBool errorIfAbsent) +{ + + char lineBuf[DCM_MAXDICTLINESIZE + 1]; + FILE* f = NULL; + int lineNumber = 0; + char* lineFields[DCM_MAXDICTFIELDS + 1]; + int fieldsPresent; + DcmDictEntry* e; + int errorsEncountered = 0; + OFBool errorOnThisLine = OFFalse; + int i; + + DcmTagKey key, upperKey; + DcmDictRangeRestriction groupRestriction = DcmDictRange_Unspecified; + DcmDictRangeRestriction elementRestriction = DcmDictRange_Unspecified; + DcmVR vr; + char* vrName; + char* tagName; + char* privCreator; + int vmMin, vmMax = 1; + const char* standardVersion; + + /* first, check whether 'fileName' really points to a file (and not to a directory or the like) */ + if (!OFStandard::fileExists(fileName) || (f = fopen(fileName, "r")) == NULL) { + if (errorIfAbsent) { + DCMDATA_ERROR("DcmDataDictionary: Cannot open file: " << fileName); + } + return OFFalse; + } + + DCMDATA_DEBUG("DcmDataDictionary: Loading file: " << fileName); + + while (getLine(lineBuf, DCM_MAXDICTLINESIZE, f)) { + lineNumber++; + + if (onlyWhitespace(lineBuf)) { + continue; /* ignore this line */ + } + if (isaCommentLine(lineBuf)) { + continue; /* ignore this line */ + } + + errorOnThisLine = OFFalse; + + /* fields are tab separated */ + fieldsPresent = splitFields(lineBuf, lineFields, + DCM_MAXDICTFIELDS, + DCM_DICT_FIELD_SEPARATOR_CHAR); + + /* initialize dict entry fields */ + vrName = NULL; + tagName = NULL; + privCreator = NULL; + vmMin = vmMax = 1; + standardVersion = "DICOM"; + + switch (fieldsPresent) { + case 0: + case 1: + case 2: + DCMDATA_ERROR("DcmDataDictionary: "<< fileName << ": " + << "too few fields (line " << lineNumber << ")"); + errorOnThisLine = OFTrue; + break; + default: + DCMDATA_ERROR("DcmDataDictionary: " << fileName << ": " + << "too many fields (line " << lineNumber << "): "); + errorOnThisLine = OFTrue; + break; + case 5: + stripWhitespace(lineFields[4]); + standardVersion = lineFields[4]; + /* drop through to next case label */ + case 4: + /* the VM field is present */ + if (!parseVMField(lineFields[3], vmMin, vmMax)) { + DCMDATA_ERROR("DcmDataDictionary: " << fileName << ": " + << "bad VM field (line " << lineNumber << "): " << lineFields[3]); + errorOnThisLine = OFTrue; + } + /* drop through to next case label */ + case 3: + if (!parseWholeTagField(lineFields[0], key, upperKey, + groupRestriction, elementRestriction, privCreator)) + { + DCMDATA_ERROR("DcmDataDictionary: " << fileName << ": " + << "bad Tag field (line " << lineNumber << "): " << lineFields[0]); + errorOnThisLine = OFTrue; + } else { + /* all is OK */ + vrName = lineFields[1]; + stripWhitespace(vrName); + + tagName = lineFields[2]; + stripWhitespace(tagName); + } + } + + if (!errorOnThisLine) { + /* check the VR Field */ + vr.setVR(vrName); + if (vr.getEVR() == EVR_UNKNOWN) { + DCMDATA_ERROR("DcmDataDictionary: " << fileName << ": " + << "bad VR field (line " << lineNumber << "): " << vrName); + errorOnThisLine = OFTrue; + } + } + + if (!errorOnThisLine) { + e = new DcmDictEntry( + key.getGroup(), key.getElement(), + upperKey.getGroup(), upperKey.getElement(), + vr, tagName, vmMin, vmMax, standardVersion, OFTrue, + privCreator); + + e->setGroupRangeRestriction(groupRestriction); + e->setElementRangeRestriction(elementRestriction); + addEntry(e); + } + + for (i = 0; i < fieldsPresent; i++) { + free(lineFields[i]); + lineFields[i] = NULL; + } + + delete[] privCreator; + + if (errorOnThisLine) { + errorsEncountered++; + } + } + + fclose(f); + + /* return OFFalse in case of errors and set internal state accordingly */ + if (errorsEncountered == 0) { + dictionaryLoaded = OFTrue; + return OFTrue; + } + else { + dictionaryLoaded = OFFalse; + return OFFalse; + } +} + +#ifndef HAVE_GETENV + +static +char* getenv() { + return NULL; +} + +#endif /* !HAVE_GETENV */ + + + +OFBool +DcmDataDictionary::loadExternalDictionaries() +{ + const char* env = NULL; + size_t len; + int sepCnt = 0; + OFBool msgIfDictAbsent = OFTrue; + OFBool loadFailed = OFFalse; + + env = getenv(DCM_DICT_ENVIRONMENT_VARIABLE); + if ((env == NULL) || (strlen(env) == 0)) { + env = DCM_DICT_DEFAULT_PATH; + msgIfDictAbsent = OFFalse; + } + + if ((env != NULL) && (strlen(env) != 0)) { + len = strlen(env); + for (size_t i = 0; i < len; ++i) { + if (env[i] == ENVIRONMENT_PATH_SEPARATOR) { + sepCnt++; + } + } + + if (sepCnt == 0) { + if (!loadDictionary(env, msgIfDictAbsent)) { + return OFFalse; + } + } else { + char** dictArray; + + dictArray = OFstatic_cast(char **, malloc((sepCnt + 1) * sizeof(char*))); + + int ndicts = splitFields(env, dictArray, sepCnt + 1, + ENVIRONMENT_PATH_SEPARATOR); + + for (int ii = 0; ii < ndicts; ii++) { + if ((dictArray[ii] != NULL) && (strlen(dictArray[ii]) > 0)) { + if (!loadDictionary(dictArray[ii], msgIfDictAbsent)) { + loadFailed = OFTrue; + } + } + free(dictArray[ii]); + } + free(dictArray); + } + } + + return (loadFailed) ? (OFFalse) : (OFTrue); +} + + +void +DcmDataDictionary::addEntry(DcmDictEntry* e) +{ + if (e->isRepeating()) { + /* + * Find the best position in repeating tag list + * Existing entries are replaced if the ranges and repetition + * constraints are the same. + * If a range represents a subset of an existing range then it + * will be placed before it in the list. This ensures that a + * search will find the subset rather than the superset. + * Otherwise entries are appended to the end of the list. + */ + OFBool inserted = OFFalse; + + DcmDictEntryListIterator iter(repDict.begin()); + DcmDictEntryListIterator last(repDict.end()); + for (; !inserted && iter != last; ++iter) { + if (e->setEQ(**iter)) { + /* replace the old entry with the new */ + DcmDictEntry *old = *iter; + *iter = e; +#ifdef PRINT_REPLACED_DICTIONARY_ENTRIES + DCMDATA_WARN("replacing " << *old); +#endif + delete old; + inserted = OFTrue; + } else if (e->subset(**iter)) { + /* e is a subset of the current list position, insert before */ + repDict.insert(iter, e); + inserted = OFTrue; + } + } + if (!inserted) { + /* insert at end */ + repDict.push_back(e); + inserted = OFTrue; + } + } else { + hashDict.put(e); + } +} + +void +DcmDataDictionary::deleteEntry(const DcmDictEntry& entry) +{ + DcmDictEntry* e = NULL; + e = OFconst_cast(DcmDictEntry *, findEntry(entry)); + if (e != NULL) { + if (e->isRepeating()) { + repDict.remove(e); + delete e; + } else { + hashDict.del(entry.getKey(), entry.getPrivateCreator()); + } + } +} + +const DcmDictEntry* +DcmDataDictionary::findEntry(const DcmDictEntry& entry) const +{ + const DcmDictEntry* e = NULL; + + if (entry.isRepeating()) { + OFBool found = OFFalse; + DcmDictEntryListConstIterator iter(repDict.begin()); + DcmDictEntryListConstIterator last(repDict.end()); + for (; !found && iter != last; ++iter) { + if (entry.setEQ(**iter)) { + found = OFTrue; + e = *iter; + } + } + } else { + e = hashDict.get(entry, entry.getPrivateCreator()); + } + return e; +} + +const DcmDictEntry* +DcmDataDictionary::findEntry(const DcmTagKey& key, const char *privCreator) const +{ + /* search first in the normal tags dictionary and if not found + * then search in the repeating tags list. + */ + const DcmDictEntry* e = NULL; + + e = hashDict.get(key, privCreator); + if (e == NULL) { + /* search in the repeating tags dictionary */ + OFBool found = OFFalse; + DcmDictEntryListConstIterator iter(repDict.begin()); + DcmDictEntryListConstIterator last(repDict.end()); + for (; !found && iter != last; ++iter) { + if ((*iter)->contains(key, privCreator)) { + found = OFTrue; + e = *iter; + } + } + } + return e; +} + +const DcmDictEntry* +DcmDataDictionary::findEntry(const char *name) const +{ + const DcmDictEntry* e = NULL; + const DcmDictEntry* ePrivate = NULL; + + /* search first in the normal tags dictionary and if not found + * then search in the repeating tags list. + */ + DcmHashDictIterator iter; + for (iter = hashDict.begin(); (e == NULL) && (iter != hashDict.end()); ++iter) { + if ((*iter)->contains(name)) { + e = *iter; + if (e->getGroup() % 2) + { + /* tag is a private tag - continue search to be sure to find non-private keys first */ + if (!ePrivate) ePrivate = e; + e = NULL; + } + } + } + + if (e == NULL) { + /* search in the repeating tags dictionary */ + OFBool found = OFFalse; + DcmDictEntryListConstIterator iter2(repDict.begin()); + DcmDictEntryListConstIterator last(repDict.end()); + for (; !found && iter2 != last; ++iter2) { + if ((*iter2)->contains(name)) { + found = OFTrue; + e = *iter2; + } + } + } + + if (e == NULL && ePrivate != NULL) { + /* no standard key found - use the first private key found */ + e = ePrivate; + } + + return e; +} + + +/* ================================================================== */ + + +GlobalDcmDataDictionary::GlobalDcmDataDictionary() + : dataDict(NULL) +#ifdef WITH_THREADS + , dataDictLock() +#endif +{ +} + +GlobalDcmDataDictionary::~GlobalDcmDataDictionary() +{ + /* No threads may be active any more, so no locking needed */ + delete dataDict; +} + +void GlobalDcmDataDictionary::createDataDict() +{ + /* Make sure only one thread tries to initialize the dictionary */ +#ifdef WITH_THREADS + dataDictLock.wrlock(); +#endif +#ifdef DONT_LOAD_EXTERNAL_DICTIONARIES + const OFBool loadExternal = OFFalse; +#else + const OFBool loadExternal = OFTrue; +#endif + /* Make sure no other thread managed to create the dictionary + * before we got our write lock. */ + if (!dataDict) + dataDict = new DcmDataDictionary(OFTrue /*loadBuiltin*/, loadExternal); +#ifdef WITH_THREADS + dataDictLock.unlock(); +#endif +} + +const DcmDataDictionary& GlobalDcmDataDictionary::rdlock() +{ +#ifdef WITH_THREADS + dataDictLock.rdlock(); +#endif + if (!dataDict) + { + /* dataDictLock must not be locked during createDataDict() */ +#ifdef WITH_THREADS + dataDictLock.unlock(); +#endif + createDataDict(); +#ifdef WITH_THREADS + dataDictLock.rdlock(); +#endif + } + return *dataDict; +} + +DcmDataDictionary& GlobalDcmDataDictionary::wrlock() +{ +#ifdef WITH_THREADS + dataDictLock.wrlock(); +#endif + if (!dataDict) + { + /* dataDictLock must not be locked during createDataDict() */ +#ifdef WITH_THREADS + dataDictLock.unlock(); +#endif + createDataDict(); +#ifdef WITH_THREADS + dataDictLock.wrlock(); +#endif + } + return *dataDict; +} + +void GlobalDcmDataDictionary::unlock() +{ +#ifdef WITH_THREADS + dataDictLock.unlock(); +#endif +} + +OFBool GlobalDcmDataDictionary::isDictionaryLoaded() +{ + OFBool result = rdlock().isDictionaryLoaded(); + unlock(); + return result; +} + +void GlobalDcmDataDictionary::clear() +{ + wrlock().clear(); + unlock(); +} diff --git a/dcmdata/libsrc/dcdictbi.cc b/dcmdata/libsrc/dcdictbi.cc new file mode 100644 index 00000000..e858ec4b --- /dev/null +++ b/dcmdata/libsrc/dcdictbi.cc @@ -0,0 +1,27598 @@ +/* +** DO NOT EDIT THIS FILE !!! +** It was generated automatically by: +** +** User: joergr +** Host: thinkpad +** Date: 2015-09-18 11:18:13 +** Prog: /home/joergr/Source/dcmtk-full/public/dcmdata/libsrc/mkdictbi +** +** From: ../data/dicom.dic +** ../data/private.dic +** +*/ + +#include "dcmtk/dcmdata/dcdict.h" +#ifdef ENABLE_BUILTIN_DICTIONARY +#include "dcmtk/dcmdata/dcdicent.h" + +struct DBI_SimpleEntry { + Uint16 group; + Uint16 element; + Uint16 upperGroup; + Uint16 upperElement; + DcmEVR evr; + const char* tagName; + int vmMin; + int vmMax; + const char* standardVersion; + DcmDictRangeRestriction groupRestriction; + DcmDictRangeRestriction elementRestriction; + const char* privateCreator; +}; + +static const DBI_SimpleEntry simpleBuiltinDict[] = { + { 0x0000, 0x0000, 0x0000, 0x0000, + EVR_UL, "CommandGroupLength", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0000, 0x0001, 0x0000, 0x0001, + EVR_UL, "RETIRED_CommandLengthToEnd", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0000, 0x0002, 0x0000, 0x0002, + EVR_UI, "AffectedSOPClassUID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0000, 0x0003, 0x0000, 0x0003, + EVR_UI, "RequestedSOPClassUID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0000, 0x0010, 0x0000, 0x0010, + EVR_SH, "RETIRED_CommandRecognitionCode", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0000, 0x0100, 0x0000, 0x0100, + EVR_US, "CommandField", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0000, 0x0110, 0x0000, 0x0110, + EVR_US, "MessageID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0000, 0x0120, 0x0000, 0x0120, + EVR_US, "MessageIDBeingRespondedTo", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0000, 0x0200, 0x0000, 0x0200, + EVR_AE, "RETIRED_Initiator", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0000, 0x0300, 0x0000, 0x0300, + EVR_AE, "RETIRED_Receiver", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0000, 0x0400, 0x0000, 0x0400, + EVR_AE, "RETIRED_FindLocation", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0000, 0x0600, 0x0000, 0x0600, + EVR_AE, "MoveDestination", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0000, 0x0700, 0x0000, 0x0700, + EVR_US, "Priority", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0000, 0x0800, 0x0000, 0x0800, + EVR_US, "CommandDataSetType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0000, 0x0850, 0x0000, 0x0850, + EVR_US, "RETIRED_NumberOfMatches", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0000, 0x0860, 0x0000, 0x0860, + EVR_US, "RETIRED_ResponseSequenceNumber", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0000, 0x0900, 0x0000, 0x0900, + EVR_US, "Status", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0000, 0x0901, 0x0000, 0x0901, + EVR_AT, "OffendingElement", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0000, 0x0902, 0x0000, 0x0902, + EVR_LO, "ErrorComment", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0000, 0x0903, 0x0000, 0x0903, + EVR_US, "ErrorID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0000, 0x1000, 0x0000, 0x1000, + EVR_UI, "AffectedSOPInstanceUID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0000, 0x1001, 0x0000, 0x1001, + EVR_UI, "RequestedSOPInstanceUID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0000, 0x1002, 0x0000, 0x1002, + EVR_US, "EventTypeID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0000, 0x1005, 0x0000, 0x1005, + EVR_AT, "AttributeIdentifierList", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0000, 0x1008, 0x0000, 0x1008, + EVR_US, "ActionTypeID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0000, 0x1020, 0x0000, 0x1020, + EVR_US, "NumberOfRemainingSuboperations", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0000, 0x1021, 0x0000, 0x1021, + EVR_US, "NumberOfCompletedSuboperations", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0000, 0x1022, 0x0000, 0x1022, + EVR_US, "NumberOfFailedSuboperations", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0000, 0x1023, 0x0000, 0x1023, + EVR_US, "NumberOfWarningSuboperations", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0000, 0x1030, 0x0000, 0x1030, + EVR_AE, "MoveOriginatorApplicationEntityTitle", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0000, 0x1031, 0x0000, 0x1031, + EVR_US, "MoveOriginatorMessageID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0000, 0x4000, 0x0000, 0x4000, + EVR_LT, "RETIRED_DialogReceiver", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0000, 0x4010, 0x0000, 0x4010, + EVR_LT, "RETIRED_TerminalType", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0000, 0x5010, 0x0000, 0x5010, + EVR_SH, "RETIRED_MessageSetID", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0000, 0x5020, 0x0000, 0x5020, + EVR_SH, "RETIRED_EndMessageID", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0000, 0x5110, 0x0000, 0x5110, + EVR_LT, "RETIRED_DisplayFormat", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0000, 0x5120, 0x0000, 0x5120, + EVR_LT, "RETIRED_PagePositionID", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0000, 0x5130, 0x0000, 0x5130, + EVR_CS, "RETIRED_TextFormatID", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0000, 0x5140, 0x0000, 0x5140, + EVR_CS, "RETIRED_NormalReverse", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0000, 0x5150, 0x0000, 0x5150, + EVR_CS, "RETIRED_AddGrayScale", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0000, 0x5160, 0x0000, 0x5160, + EVR_CS, "RETIRED_Borders", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0000, 0x5170, 0x0000, 0x5170, + EVR_IS, "RETIRED_Copies", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0000, 0x5180, 0x0000, 0x5180, + EVR_CS, "RETIRED_CommandMagnificationType", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0000, 0x5190, 0x0000, 0x5190, + EVR_CS, "RETIRED_Erase", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0000, 0x51a0, 0x0000, 0x51a0, + EVR_CS, "RETIRED_Print", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0000, 0x51b0, 0x0000, 0x51b0, + EVR_US, "RETIRED_Overlays", 1, -1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0002, 0x0000, 0x0002, 0x0000, + EVR_UL, "FileMetaInformationGroupLength", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0002, 0x0001, 0x0002, 0x0001, + EVR_OB, "FileMetaInformationVersion", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0002, 0x0002, 0x0002, 0x0002, + EVR_UI, "MediaStorageSOPClassUID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0002, 0x0003, 0x0002, 0x0003, + EVR_UI, "MediaStorageSOPInstanceUID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0002, 0x0010, 0x0002, 0x0010, + EVR_UI, "TransferSyntaxUID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0002, 0x0012, 0x0002, 0x0012, + EVR_UI, "ImplementationClassUID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0002, 0x0013, 0x0002, 0x0013, + EVR_SH, "ImplementationVersionName", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0002, 0x0016, 0x0002, 0x0016, + EVR_AE, "SourceApplicationEntityTitle", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0002, 0x0017, 0x0002, 0x0017, + EVR_AE, "SendingApplicationEntityTitle", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0002, 0x0018, 0x0002, 0x0018, + EVR_AE, "ReceivingApplicationEntityTitle", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0002, 0x0100, 0x0002, 0x0100, + EVR_UI, "PrivateInformationCreatorUID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0002, 0x0102, 0x0002, 0x0102, + EVR_OB, "PrivateInformation", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } +#ifdef ENABLE_PRIVATE_TAGS + , { 0x0003, 0x0000, 0x0003, 0x0000, + EVR_US, "Unknown", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "AEGIS_DICOM_2.00" } + , { 0x0003, 0x0008, 0x0003, 0x0008, + EVR_US, "ISICommandField", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS ISI" } + , { 0x0003, 0x0011, 0x0003, 0x0011, + EVR_US, "AttachIDApplicationCode", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS ISI" } + , { 0x0003, 0x0012, 0x0003, 0x0012, + EVR_UL, "AttachIDMessageCount", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS ISI" } + , { 0x0003, 0x0013, 0x0003, 0x0013, + EVR_DA, "AttachIDDate", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS ISI" } + , { 0x0003, 0x0014, 0x0003, 0x0014, + EVR_TM, "AttachIDTime", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS ISI" } + , { 0x0003, 0x0020, 0x0003, 0x0020, + EVR_US, "MessageType", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS ISI" } + , { 0x0003, 0x0030, 0x0003, 0x0030, + EVR_DA, "MaxWaitingDate", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS ISI" } + , { 0x0003, 0x0031, 0x0003, 0x0031, + EVR_TM, "MaxWaitingTime", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS ISI" } +#endif + , { 0x0004, 0x1130, 0x0004, 0x1130, + EVR_CS, "FileSetID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0004, 0x1141, 0x0004, 0x1141, + EVR_CS, "FileSetDescriptorFileID", 1, 8, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0004, 0x1142, 0x0004, 0x1142, + EVR_CS, "SpecificCharacterSetOfFileSetDescriptorFile", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0004, 0x1200, 0x0004, 0x1200, + EVR_up, "OffsetOfTheFirstDirectoryRecordOfTheRootDirectoryEntity", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0004, 0x1202, 0x0004, 0x1202, + EVR_up, "OffsetOfTheLastDirectoryRecordOfTheRootDirectoryEntity", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0004, 0x1212, 0x0004, 0x1212, + EVR_US, "FileSetConsistencyFlag", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0004, 0x1220, 0x0004, 0x1220, + EVR_SQ, "DirectoryRecordSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0004, 0x1400, 0x0004, 0x1400, + EVR_up, "OffsetOfTheNextDirectoryRecord", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0004, 0x1410, 0x0004, 0x1410, + EVR_US, "RecordInUseFlag", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0004, 0x1420, 0x0004, 0x1420, + EVR_up, "OffsetOfReferencedLowerLevelDirectoryEntity", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0004, 0x1430, 0x0004, 0x1430, + EVR_CS, "DirectoryRecordType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0004, 0x1432, 0x0004, 0x1432, + EVR_UI, "PrivateRecordUID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0004, 0x1500, 0x0004, 0x1500, + EVR_CS, "ReferencedFileID", 1, 8, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0004, 0x1504, 0x0004, 0x1504, + EVR_up, "RETIRED_MRDRDirectoryRecordOffset", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0004, 0x1510, 0x0004, 0x1510, + EVR_UI, "ReferencedSOPClassUIDInFile", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0004, 0x1511, 0x0004, 0x1511, + EVR_UI, "ReferencedSOPInstanceUIDInFile", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0004, 0x1512, 0x0004, 0x1512, + EVR_UI, "ReferencedTransferSyntaxUIDInFile", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0004, 0x151a, 0x0004, 0x151a, + EVR_UI, "ReferencedRelatedGeneralSOPClassUIDInFile", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0004, 0x1600, 0x0004, 0x1600, + EVR_UL, "RETIRED_NumberOfReferences", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } +#ifdef ENABLE_PRIVATE_TAGS + , { 0x0005, 0x0000, 0x0005, 0x0000, + EVR_US, "Unknown", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "AEGIS_DICOM_2.00" } +#endif + , { 0x0008, 0x0001, 0x0008, 0x0001, + EVR_UL, "RETIRED_LengthToEnd", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x0005, 0x0008, 0x0005, + EVR_CS, "SpecificCharacterSet", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x0006, 0x0008, 0x0006, + EVR_SQ, "LanguageCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x0008, 0x0008, 0x0008, + EVR_CS, "ImageType", 2, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x0010, 0x0008, 0x0010, + EVR_SH, "RETIRED_RecognitionCode", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x0012, 0x0008, 0x0012, + EVR_DA, "InstanceCreationDate", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x0013, 0x0008, 0x0013, + EVR_TM, "InstanceCreationTime", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x0014, 0x0008, 0x0014, + EVR_UI, "InstanceCreatorUID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x0015, 0x0008, 0x0015, + EVR_DT, "InstanceCoercionDateTime", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x0016, 0x0008, 0x0016, + EVR_UI, "SOPClassUID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x0018, 0x0008, 0x0018, + EVR_UI, "SOPInstanceUID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x001a, 0x0008, 0x001a, + EVR_UI, "RelatedGeneralSOPClassUID", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x001b, 0x0008, 0x001b, + EVR_UI, "OriginalSpecializedSOPClassUID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x0020, 0x0008, 0x0020, + EVR_DA, "StudyDate", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x0021, 0x0008, 0x0021, + EVR_DA, "SeriesDate", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x0022, 0x0008, 0x0022, + EVR_DA, "AcquisitionDate", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x0023, 0x0008, 0x0023, + EVR_DA, "ContentDate", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x0024, 0x0008, 0x0024, + EVR_DA, "RETIRED_OverlayDate", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x0025, 0x0008, 0x0025, + EVR_DA, "RETIRED_CurveDate", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x002a, 0x0008, 0x002a, + EVR_DT, "AcquisitionDateTime", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x0030, 0x0008, 0x0030, + EVR_TM, "StudyTime", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x0031, 0x0008, 0x0031, + EVR_TM, "SeriesTime", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x0032, 0x0008, 0x0032, + EVR_TM, "AcquisitionTime", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x0033, 0x0008, 0x0033, + EVR_TM, "ContentTime", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x0034, 0x0008, 0x0034, + EVR_TM, "RETIRED_OverlayTime", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x0035, 0x0008, 0x0035, + EVR_TM, "RETIRED_CurveTime", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x0040, 0x0008, 0x0040, + EVR_US, "RETIRED_DataSetType", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x0041, 0x0008, 0x0041, + EVR_LO, "RETIRED_DataSetSubtype", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x0042, 0x0008, 0x0042, + EVR_CS, "RETIRED_NuclearMedicineSeriesType", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x0050, 0x0008, 0x0050, + EVR_SH, "AccessionNumber", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x0051, 0x0008, 0x0051, + EVR_SQ, "IssuerOfAccessionNumberSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x0052, 0x0008, 0x0052, + EVR_CS, "QueryRetrieveLevel", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x0053, 0x0008, 0x0053, + EVR_CS, "QueryRetrieveView", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x0054, 0x0008, 0x0054, + EVR_AE, "RetrieveAETitle", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x0056, 0x0008, 0x0056, + EVR_CS, "InstanceAvailability", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x0058, 0x0008, 0x0058, + EVR_UI, "FailedSOPInstanceUIDList", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x0060, 0x0008, 0x0060, + EVR_CS, "Modality", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x0061, 0x0008, 0x0061, + EVR_CS, "ModalitiesInStudy", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x0062, 0x0008, 0x0062, + EVR_UI, "SOPClassesInStudy", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x0064, 0x0008, 0x0064, + EVR_CS, "ConversionType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x0068, 0x0008, 0x0068, + EVR_CS, "PresentationIntentType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x0070, 0x0008, 0x0070, + EVR_LO, "Manufacturer", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x0080, 0x0008, 0x0080, + EVR_LO, "InstitutionName", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x0081, 0x0008, 0x0081, + EVR_ST, "InstitutionAddress", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x0082, 0x0008, 0x0082, + EVR_SQ, "InstitutionCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x0090, 0x0008, 0x0090, + EVR_PN, "ReferringPhysicianName", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x0092, 0x0008, 0x0092, + EVR_ST, "ReferringPhysicianAddress", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x0094, 0x0008, 0x0094, + EVR_SH, "ReferringPhysicianTelephoneNumbers", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x0096, 0x0008, 0x0096, + EVR_SQ, "ReferringPhysicianIdentificationSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x009c, 0x0008, 0x009c, + EVR_PN, "ConsultingPhysicianName", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x009d, 0x0008, 0x009d, + EVR_SQ, "ConsultingPhysicianIdentificationSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x0100, 0x0008, 0x0100, + EVR_SH, "CodeValue", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x0101, 0x0008, 0x0101, + EVR_LO, "ExtendedCodeValue", 1, 1, "DICOM/DICOS", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x0102, 0x0008, 0x0102, + EVR_SH, "CodingSchemeDesignator", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x0103, 0x0008, 0x0103, + EVR_SH, "CodingSchemeVersion", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x0104, 0x0008, 0x0104, + EVR_LO, "CodeMeaning", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x0105, 0x0008, 0x0105, + EVR_CS, "MappingResource", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x0106, 0x0008, 0x0106, + EVR_DT, "ContextGroupVersion", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x0107, 0x0008, 0x0107, + EVR_DT, "ContextGroupLocalVersion", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x0108, 0x0008, 0x0108, + EVR_LT, "ExtendedCodeMeaning", 1, 1, "DICOM/DICOS", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x010b, 0x0008, 0x010b, + EVR_CS, "ContextGroupExtensionFlag", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x010c, 0x0008, 0x010c, + EVR_UI, "CodingSchemeUID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x010d, 0x0008, 0x010d, + EVR_UI, "ContextGroupExtensionCreatorUID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x010f, 0x0008, 0x010f, + EVR_CS, "ContextIdentifier", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x0110, 0x0008, 0x0110, + EVR_SQ, "CodingSchemeIdentificationSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x0112, 0x0008, 0x0112, + EVR_LO, "CodingSchemeRegistry", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x0114, 0x0008, 0x0114, + EVR_ST, "CodingSchemeExternalID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x0115, 0x0008, 0x0115, + EVR_ST, "CodingSchemeName", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x0116, 0x0008, 0x0116, + EVR_ST, "CodingSchemeResponsibleOrganization", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x0117, 0x0008, 0x0117, + EVR_UI, "ContextUID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x0118, 0x0008, 0x0118, + EVR_UI, "MappingResourceUID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x0119, 0x0008, 0x0119, + EVR_UC, "LongCodeValue", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x0120, 0x0008, 0x0120, + EVR_UR, "URNCodeValue", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x0121, 0x0008, 0x0121, + EVR_SQ, "EquivalentCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x0201, 0x0008, 0x0201, + EVR_SH, "TimezoneOffsetFromUTC", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x0300, 0x0008, 0x0300, + EVR_SQ, "PrivateDataElementCharacteristicsSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x0301, 0x0008, 0x0301, + EVR_US, "PrivateGroupReference", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x0302, 0x0008, 0x0302, + EVR_LO, "PrivateCreatorReference", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x0303, 0x0008, 0x0303, + EVR_CS, "BlockIdentifyingInformationStatus", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x0304, 0x0008, 0x0304, + EVR_US, "NonidentifyingPrivateElements", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x0305, 0x0008, 0x0305, + EVR_SQ, "DeidentificationActionSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x0306, 0x0008, 0x0306, + EVR_US, "IdentifyingPrivateElements", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x0307, 0x0008, 0x0307, + EVR_CS, "DeidentificationAction", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x1000, 0x0008, 0x1000, + EVR_AE, "RETIRED_NetworkID", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x1010, 0x0008, 0x1010, + EVR_SH, "StationName", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x1030, 0x0008, 0x1030, + EVR_LO, "StudyDescription", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x1032, 0x0008, 0x1032, + EVR_SQ, "ProcedureCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x103e, 0x0008, 0x103e, + EVR_LO, "SeriesDescription", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x103f, 0x0008, 0x103f, + EVR_SQ, "SeriesDescriptionCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x1040, 0x0008, 0x1040, + EVR_LO, "InstitutionalDepartmentName", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x1048, 0x0008, 0x1048, + EVR_PN, "PhysiciansOfRecord", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x1049, 0x0008, 0x1049, + EVR_SQ, "PhysiciansOfRecordIdentificationSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x1050, 0x0008, 0x1050, + EVR_PN, "PerformingPhysicianName", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x1052, 0x0008, 0x1052, + EVR_SQ, "PerformingPhysicianIdentificationSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x1060, 0x0008, 0x1060, + EVR_PN, "NameOfPhysiciansReadingStudy", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x1062, 0x0008, 0x1062, + EVR_SQ, "PhysiciansReadingStudyIdentificationSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x1070, 0x0008, 0x1070, + EVR_PN, "OperatorsName", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x1072, 0x0008, 0x1072, + EVR_SQ, "OperatorIdentificationSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x1080, 0x0008, 0x1080, + EVR_LO, "AdmittingDiagnosesDescription", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x1084, 0x0008, 0x1084, + EVR_SQ, "AdmittingDiagnosesCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x1090, 0x0008, 0x1090, + EVR_LO, "ManufacturerModelName", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x1100, 0x0008, 0x1100, + EVR_SQ, "RETIRED_ReferencedResultsSequence", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x1110, 0x0008, 0x1110, + EVR_SQ, "ReferencedStudySequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x1111, 0x0008, 0x1111, + EVR_SQ, "ReferencedPerformedProcedureStepSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x1115, 0x0008, 0x1115, + EVR_SQ, "ReferencedSeriesSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x1120, 0x0008, 0x1120, + EVR_SQ, "ReferencedPatientSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x1125, 0x0008, 0x1125, + EVR_SQ, "ReferencedVisitSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x1130, 0x0008, 0x1130, + EVR_SQ, "RETIRED_ReferencedOverlaySequence", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x1134, 0x0008, 0x1134, + EVR_SQ, "ReferencedStereometricInstanceSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x113a, 0x0008, 0x113a, + EVR_SQ, "ReferencedWaveformSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x1140, 0x0008, 0x1140, + EVR_SQ, "ReferencedImageSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x1145, 0x0008, 0x1145, + EVR_SQ, "RETIRED_ReferencedCurveSequence", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x114a, 0x0008, 0x114a, + EVR_SQ, "ReferencedInstanceSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x114b, 0x0008, 0x114b, + EVR_SQ, "ReferencedRealWorldValueMappingInstanceSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x1150, 0x0008, 0x1150, + EVR_UI, "ReferencedSOPClassUID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x1155, 0x0008, 0x1155, + EVR_UI, "ReferencedSOPInstanceUID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x115a, 0x0008, 0x115a, + EVR_UI, "SOPClassesSupported", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x1160, 0x0008, 0x1160, + EVR_IS, "ReferencedFrameNumber", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x1161, 0x0008, 0x1161, + EVR_UL, "SimpleFrameList", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x1162, 0x0008, 0x1162, + EVR_UL, "CalculatedFrameList", 3, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x1163, 0x0008, 0x1163, + EVR_FD, "TimeRange", 2, 2, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x1164, 0x0008, 0x1164, + EVR_SQ, "FrameExtractionSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x1167, 0x0008, 0x1167, + EVR_UI, "MultiFrameSourceSOPInstanceUID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x1190, 0x0008, 0x1190, + EVR_UR, "RetrieveURL", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x1195, 0x0008, 0x1195, + EVR_UI, "TransactionUID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x1196, 0x0008, 0x1196, + EVR_US, "WarningReason", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x1197, 0x0008, 0x1197, + EVR_US, "FailureReason", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x1198, 0x0008, 0x1198, + EVR_SQ, "FailedSOPSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x1199, 0x0008, 0x1199, + EVR_SQ, "ReferencedSOPSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x1200, 0x0008, 0x1200, + EVR_SQ, "StudiesContainingOtherReferencedInstancesSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x1250, 0x0008, 0x1250, + EVR_SQ, "RelatedSeriesSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x2110, 0x0008, 0x2110, + EVR_CS, "RETIRED_LossyImageCompressionRetired", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x2111, 0x0008, 0x2111, + EVR_ST, "DerivationDescription", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x2112, 0x0008, 0x2112, + EVR_SQ, "SourceImageSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x2120, 0x0008, 0x2120, + EVR_SH, "StageName", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x2122, 0x0008, 0x2122, + EVR_IS, "StageNumber", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x2124, 0x0008, 0x2124, + EVR_IS, "NumberOfStages", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x2127, 0x0008, 0x2127, + EVR_SH, "ViewName", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x2128, 0x0008, 0x2128, + EVR_IS, "ViewNumber", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x2129, 0x0008, 0x2129, + EVR_IS, "NumberOfEventTimers", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x212a, 0x0008, 0x212a, + EVR_IS, "NumberOfViewsInStage", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x2130, 0x0008, 0x2130, + EVR_DS, "EventElapsedTimes", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x2132, 0x0008, 0x2132, + EVR_LO, "EventTimerNames", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x2133, 0x0008, 0x2133, + EVR_SQ, "EventTimerSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x2134, 0x0008, 0x2134, + EVR_FD, "EventTimeOffset", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x2135, 0x0008, 0x2135, + EVR_SQ, "EventCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x2142, 0x0008, 0x2142, + EVR_IS, "StartTrim", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x2143, 0x0008, 0x2143, + EVR_IS, "StopTrim", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x2144, 0x0008, 0x2144, + EVR_IS, "RecommendedDisplayFrameRate", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x2200, 0x0008, 0x2200, + EVR_CS, "RETIRED_TransducerPosition", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x2204, 0x0008, 0x2204, + EVR_CS, "RETIRED_TransducerOrientation", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x2208, 0x0008, 0x2208, + EVR_CS, "RETIRED_AnatomicStructure", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x2218, 0x0008, 0x2218, + EVR_SQ, "AnatomicRegionSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x2220, 0x0008, 0x2220, + EVR_SQ, "AnatomicRegionModifierSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x2228, 0x0008, 0x2228, + EVR_SQ, "PrimaryAnatomicStructureSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x2229, 0x0008, 0x2229, + EVR_SQ, "AnatomicStructureSpaceOrRegionSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x2230, 0x0008, 0x2230, + EVR_SQ, "PrimaryAnatomicStructureModifierSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x2240, 0x0008, 0x2240, + EVR_SQ, "RETIRED_TransducerPositionSequence", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x2242, 0x0008, 0x2242, + EVR_SQ, "RETIRED_TransducerPositionModifierSequence", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x2244, 0x0008, 0x2244, + EVR_SQ, "RETIRED_TransducerOrientationSequence", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x2246, 0x0008, 0x2246, + EVR_SQ, "RETIRED_TransducerOrientationModifierSequence", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x2251, 0x0008, 0x2251, + EVR_SQ, "RETIRED_AnatomicStructureSpaceOrRegionCodeSequenceTrial", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x2253, 0x0008, 0x2253, + EVR_SQ, "RETIRED_AnatomicPortalOfEntranceCodeSequenceTrial", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x2255, 0x0008, 0x2255, + EVR_SQ, "RETIRED_AnatomicApproachDirectionCodeSequenceTrial", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x2256, 0x0008, 0x2256, + EVR_ST, "RETIRED_AnatomicPerspectiveDescriptionTrial", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x2257, 0x0008, 0x2257, + EVR_SQ, "RETIRED_AnatomicPerspectiveCodeSequenceTrial", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x2258, 0x0008, 0x2258, + EVR_ST, "RETIRED_AnatomicLocationOfExaminingInstrumentDescriptionTrial", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x2259, 0x0008, 0x2259, + EVR_SQ, "RETIRED_AnatomicLocationOfExaminingInstrumentCodeSequenceTrial", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x225a, 0x0008, 0x225a, + EVR_SQ, "RETIRED_AnatomicStructureSpaceOrRegionModifierCodeSequenceTrial", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x225c, 0x0008, 0x225c, + EVR_SQ, "RETIRED_OnAxisBackgroundAnatomicStructureCodeSequenceTrial", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x3001, 0x0008, 0x3001, + EVR_SQ, "AlternateRepresentationSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x3010, 0x0008, 0x3010, + EVR_UI, "IrradiationEventUID", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x3011, 0x0008, 0x3011, + EVR_SQ, "SourceIrradiationEventSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x3012, 0x0008, 0x3012, + EVR_UI, "RadiopharmaceuticalAdministrationEventUID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x4000, 0x0008, 0x4000, + EVR_LT, "RETIRED_IdentifyingComments", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x9007, 0x0008, 0x9007, + EVR_CS, "FrameType", 4, 4, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x9092, 0x0008, 0x9092, + EVR_SQ, "ReferencedImageEvidenceSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x9121, 0x0008, 0x9121, + EVR_SQ, "ReferencedRawDataSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x9123, 0x0008, 0x9123, + EVR_UI, "CreatorVersionUID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x9124, 0x0008, 0x9124, + EVR_SQ, "DerivationImageSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x9154, 0x0008, 0x9154, + EVR_SQ, "SourceImageEvidenceSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x9205, 0x0008, 0x9205, + EVR_CS, "PixelPresentation", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x9206, 0x0008, 0x9206, + EVR_CS, "VolumetricProperties", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x9207, 0x0008, 0x9207, + EVR_CS, "VolumeBasedCalculationTechnique", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x9208, 0x0008, 0x9208, + EVR_CS, "ComplexImageComponent", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x9209, 0x0008, 0x9209, + EVR_CS, "AcquisitionContrast", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x9215, 0x0008, 0x9215, + EVR_SQ, "DerivationCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x9237, 0x0008, 0x9237, + EVR_SQ, "ReferencedPresentationStateSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x9410, 0x0008, 0x9410, + EVR_SQ, "ReferencedOtherPlaneSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x9458, 0x0008, 0x9458, + EVR_SQ, "FrameDisplaySequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x9459, 0x0008, 0x9459, + EVR_FL, "RecommendedDisplayFrameRateInFloat", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0008, 0x9460, 0x0008, 0x9460, + EVR_CS, "SkipFrameRangeFlag", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } +#ifdef ENABLE_PRIVATE_TAGS + , { 0x0009, 0x0000, 0x0009, 0x0000, + EVR_US, "Unknown", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "AEGIS_DICOM_2.00" } + , { 0x0009, 0x0000, 0x0009, 0x0000, + EVR_LT, "DataObjectRecognitionCode", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1" } + , { 0x0009, 0x0000, 0x0009, 0x0000, + EVR_IS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "ACUSON" } + , { 0x0009, 0x0000, 0x0009, 0x0000, + EVR_LT, "OriginalFileName", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PAPYRUS" } + , { 0x0009, 0x0000, 0x0009, 0x0000, + EVR_DS, "NumberOfMeasurements", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CM VA0 CMS" } + , { 0x0009, 0x0000, 0x0009, 0x0000, + EVR_SQ, "AnonymizerUIDMap", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "DCMTK_ANONYMIZER" } + , { 0x0009, 0x0000, 0x0009, 0x0000, + EVR_OB, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "MERGE TECHNOLOGIES, INC." } + , { 0x0009, 0x0000, 0x0009, 0x0000, + EVR_UL, "FileLocation", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "CARDIO-D.R. 1.0" } + , { 0x0009, 0x0000, 0x0009, 0x0000, + EVR_LO, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P-GV-CT Release 1" } + , { 0x0009, 0x0001, 0x0009, 0x0001, + EVR_LT, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "TOSHIBA_MEC_1.0" } + , { 0x0009, 0x0001, 0x0009, 0x0001, + EVR_IS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "ACUSON" } + , { 0x0009, 0x0001, 0x0009, 0x0001, + EVR_UN, "RISPatientInfoIMGEF", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS ISI" } + , { 0x0009, 0x0001, 0x0009, 0x0001, + EVR_US, "SIENETCommandField", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIENET" } + , { 0x0009, 0x0001, 0x0009, 0x0001, + EVR_UN, "CRHeaderInformation", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "FFP DATA" } + , { 0x0009, 0x0001, 0x0009, 0x0001, + EVR_UL, "FileSize", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "CARDIO-D.R. 1.0" } + , { 0x0009, 0x0001, 0x0009, 0x0001, + EVR_LO, "FullFidelity", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_IDEN_01" } + , { 0x0009, 0x0001, 0x0009, 0x0001, + EVR_UN, "SIENETGeneralPurposeIMGEF", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "ISI" } + , { 0x0009, 0x0002, 0x0009, 0x0002, + EVR_US, "Unknown", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "TOSHIBA_MEC_1.0" } + , { 0x0009, 0x0002, 0x0009, 0x0002, + EVR_UN, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "ACUSON" } + , { 0x0009, 0x0002, 0x0009, 0x0002, + EVR_SH, "SuiteId", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_IDEN_01" } + , { 0x0009, 0x0003, 0x0009, 0x0003, + EVR_US, "Unknown", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "TOSHIBA_MEC_1.0" } + , { 0x0009, 0x0003, 0x0009, 0x0003, + EVR_UN, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "ACUSON" } + , { 0x0009, 0x0004, 0x0009, 0x0004, + EVR_US, "Unknown", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "TOSHIBA_MEC_1.0" } + , { 0x0009, 0x0004, 0x0009, 0x0004, + EVR_LO, "ImageDataConsistence", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1" } + , { 0x0009, 0x0004, 0x0009, 0x0004, + EVR_UN, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "ACUSON" } + , { 0x0009, 0x0004, 0x0009, 0x0004, + EVR_SH, "ImageControlUnit", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "FDMS 1.0" } + , { 0x0009, 0x0004, 0x0009, 0x0004, + EVR_SH, "ProductId", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_IDEN_01" } + , { 0x0009, 0x0005, 0x0009, 0x0005, + EVR_UN, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "ACUSON" } + , { 0x0009, 0x0005, 0x0009, 0x0005, + EVR_OW, "ImageUID", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "FDMS 1.0" } + , { 0x0009, 0x0006, 0x0009, 0x0006, + EVR_UN, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "ACUSON" } + , { 0x0009, 0x0006, 0x0009, 0x0006, + EVR_OW, "RouteImageUID", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "FDMS 1.0" } + , { 0x0009, 0x0007, 0x0009, 0x0007, + EVR_UN, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "ACUSON" } + , { 0x0009, 0x0008, 0x0009, 0x0008, + EVR_CS, "ExposureChannel", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "INTEGRIS 1.0" } + , { 0x0009, 0x0008, 0x0009, 0x0008, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1" } + , { 0x0009, 0x0008, 0x0009, 0x0008, + EVR_LT, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "ACUSON" } + , { 0x0009, 0x0008, 0x0009, 0x0008, + EVR_UL, "ImageDisplayInformationVersionNo", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "FDMS 1.0" } + , { 0x0009, 0x0009, 0x0009, 0x0009, + EVR_LT, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "ACUSON" } + , { 0x0009, 0x0009, 0x0009, 0x0009, + EVR_UL, "PatientInformationVersionNo", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "FDMS 1.0" } + , { 0x0009, 0x000a, 0x0009, 0x000a, + EVR_IS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "ACUSON" } + , { 0x0009, 0x000b, 0x0009, 0x000b, + EVR_IS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "ACUSON" } + , { 0x0009, 0x000c, 0x0009, 0x000c, + EVR_IS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "ACUSON" } + , { 0x0009, 0x000c, 0x0009, 0x000c, + EVR_OW, "FilmUID", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "FDMS 1.0" } + , { 0x0009, 0x000d, 0x0009, 0x000d, + EVR_IS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "ACUSON" } + , { 0x0009, 0x000e, 0x0009, 0x000e, + EVR_IS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "ACUSON" } + , { 0x0009, 0x000f, 0x0009, 0x000f, + EVR_UN, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "ACUSON" } + , { 0x0009, 0x0010, 0x0009, 0x0010, + EVR_LT, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CT VA0 IDE" } + , { 0x0009, 0x0010, 0x0009, 0x0010, + EVR_LO, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "AGFA" } + , { 0x0009, 0x0010, 0x0009, 0x0010, + EVR_LO, "Comments", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI" } + , { 0x0009, 0x0010, 0x0009, 0x0010, + EVR_IS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "ACUSON" } + , { 0x0009, 0x0010, 0x0009, 0x0010, + EVR_CS, "ExposureUnitTypeCode", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "FDMS 1.0" } + , { 0x0009, 0x0010, 0x0009, 0x0010, + EVR_LT, "OriginalFileLocation", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PAPYRUS" } + , { 0x0009, 0x0010, 0x0009, 0x0010, + EVR_LT, "StorageMode", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CM VA0 CMS" } + , { 0x0009, 0x0010, 0x0009, 0x0010, + EVR_LT, "GeneratorIdentificationLabel", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CM VA0 LAB" } + , { 0x0009, 0x0010, 0x0009, 0x0010, + EVR_UI, "AnonymizerUIDKey", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "DCMTK_ANONYMIZER" } + , { 0x0009, 0x0010, 0x0009, 0x0010, + EVR_UN, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS DICOM" } + , { 0x0009, 0x0010, 0x0009, 0x0010, + EVR_LT, "Comments", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI RELEASE 1" } + , { 0x0009, 0x0010, 0x0009, 0x0010, + EVR_LO, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_GENIE_1" } + , { 0x0009, 0x0010, 0x0009, 0x0010, + EVR_LT, "Comments", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI Release 1" } + , { 0x0009, 0x0010, 0x0009, 0x0010, + EVR_LO, "RecognitionCode", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MED" } + , { 0x0009, 0x0010, 0x0009, 0x0010, + EVR_LO, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P-GV-CT Release 1" } + , { 0x0009, 0x0010, 0x0009, 0x0010, + EVR_LO, "SPIRelease", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR" } + , { 0x0009, 0x0011, 0x0009, 0x0011, + EVR_LO, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "AGFA" } + , { 0x0009, 0x0011, 0x0009, 0x0011, + EVR_UN, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "ACUSON" } + , { 0x0009, 0x0011, 0x0009, 0x0011, + EVR_LT, "GantryIdentificationLabel", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CM VA0 LAB" } + , { 0x0009, 0x0011, 0x0009, 0x0011, + EVR_SL, "StudyFlags", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_GENIE_1" } + , { 0x0009, 0x0012, 0x0009, 0x0012, + EVR_LO, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1" } + , { 0x0009, 0x0012, 0x0009, 0x0012, + EVR_IS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "ACUSON" } + , { 0x0009, 0x0012, 0x0009, 0x0012, + EVR_UL, "EvaluationMaskImage", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CM VA0 CMS" } + , { 0x0009, 0x0012, 0x0009, 0x0012, + EVR_LT, "X-RayTubeIdentificationLabel", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CM VA0 LAB" } + , { 0x0009, 0x0012, 0x0009, 0x0012, + EVR_LT, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS DICOM" } + , { 0x0009, 0x0012, 0x0009, 0x0012, + EVR_SL, "StudyType", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_GENIE_1" } + , { 0x0009, 0x0012, 0x0009, 0x0012, + EVR_LO, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR" } + , { 0x0009, 0x0013, 0x0009, 0x0013, + EVR_LO, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "AGFA" } + , { 0x0009, 0x0013, 0x0009, 0x0013, + EVR_IS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "ACUSON" } + , { 0x0009, 0x0013, 0x0009, 0x0013, + EVR_LT, "DetectorIdentificationLabel", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CM VA0 LAB" } + , { 0x0009, 0x0014, 0x0009, 0x0014, + EVR_LO, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "AGFA" } + , { 0x0009, 0x0014, 0x0009, 0x0014, + EVR_LT, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "ACUSON" } + , { 0x0009, 0x0014, 0x0009, 0x0014, + EVR_LT, "ReceiverPLA", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIENET" } + , { 0x0009, 0x0014, 0x0009, 0x0014, + EVR_LT, "DASIdentificationLabel", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CM VA0 LAB" } + , { 0x0009, 0x0015, 0x0009, 0x0015, + EVR_LO, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "AGFA" } + , { 0x0009, 0x0015, 0x0009, 0x0015, + EVR_LO, "UniqueIdentifier", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1" } + , { 0x0009, 0x0015, 0x0009, 0x0015, + EVR_LO, "SPIImageUID", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI" } + , { 0x0009, 0x0015, 0x0009, 0x0015, + EVR_UN, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "ACUSON" } + , { 0x0009, 0x0015, 0x0009, 0x0015, + EVR_LT, "SMIIdentificationLabel", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CM VA0 LAB" } + , { 0x0009, 0x0015, 0x0009, 0x0015, + EVR_LO, "SPIImageUID", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI RELEASE 1" } + , { 0x0009, 0x0015, 0x0009, 0x0015, + EVR_LO, "SPIImageUID", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI Release 1" } + , { 0x0009, 0x0016, 0x0009, 0x0016, + EVR_LO, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1" } + , { 0x0009, 0x0016, 0x0009, 0x0016, + EVR_US, "TransferPriority", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIENET" } + , { 0x0009, 0x0016, 0x0009, 0x0016, + EVR_LT, "CPUIdentificationLabel", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CM VA0 LAB" } + , { 0x0009, 0x0017, 0x0009, 0x0017, + EVR_LT, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_IDEN_01" } + , { 0x0009, 0x0018, 0x0009, 0x0018, + EVR_LO, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1" } + , { 0x0009, 0x0018, 0x0009, 0x0018, + EVR_LT, "DataSetIdentifier", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PAPYRUS" } + , { 0x0009, 0x001a, 0x0009, 0x001a, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_IDEN_01" } + , { 0x0009, 0x001e, 0x0009, 0x001e, + EVR_UI, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_GENIE_1" } + , { 0x0009, 0x0020, 0x0009, 0x0020, + EVR_LT, "HeaderVersion", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CM VA0 LAB" } + , { 0x0009, 0x0020, 0x0009, 0x0020, + EVR_UI, "AnonymizerUIDValue", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "DCMTK_ANONYMIZER" } + , { 0x0009, 0x0020, 0x0009, 0x0020, + EVR_LT, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CT VA0 ORI" } + , { 0x0009, 0x0020, 0x0009, 0x0020, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_IDEN_01" } + , { 0x0009, 0x0020, 0x0009, 0x0020, + EVR_LO, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_GENIE_1" } + , { 0x0009, 0x0020, 0x0009, 0x0020, + EVR_LO, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P-GV-CT Release 1" } + , { 0x0009, 0x0021, 0x0009, 0x0021, + EVR_LT, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1" } + , { 0x0009, 0x0021, 0x0009, 0x0021, + EVR_SL, "SeriesFlags", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_GENIE_1" } + , { 0x0009, 0x0022, 0x0009, 0x0022, + EVR_SH, "UserOrientation", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_GENIE_1" } + , { 0x0009, 0x0023, 0x0009, 0x0023, + EVR_SL, "InitiationType", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_GENIE_1" } + , { 0x0009, 0x0024, 0x0009, 0x0024, + EVR_DS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0009, 0x0024, 0x0009, 0x0024, + EVR_SL, "InitiationDelay", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_GENIE_1" } + , { 0x0009, 0x0025, 0x0009, 0x0025, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0009, 0x0025, 0x0009, 0x0025, + EVR_SL, "InitiationCountRate", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_GENIE_1" } + , { 0x0009, 0x0026, 0x0009, 0x0026, + EVR_DA, "LastMoveDate", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CM VA0 CMS" } + , { 0x0009, 0x0026, 0x0009, 0x0026, + EVR_SL, "NumberEnergySets", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_GENIE_1" } + , { 0x0009, 0x0027, 0x0009, 0x0027, + EVR_TM, "LastMoveTime", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CM VA0 CMS" } + , { 0x0009, 0x0027, 0x0009, 0x0027, + EVR_SL, "ImageActualDate", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_IDEN_01" } + , { 0x0009, 0x0027, 0x0009, 0x0027, + EVR_SL, "NumberDetectors", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_GENIE_1" } + , { 0x0009, 0x0029, 0x0009, 0x0029, + EVR_LT, "ActualUser", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIENET" } + , { 0x0009, 0x0029, 0x0009, 0x0029, + EVR_SL, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_GENIE_1" } + , { 0x0009, 0x002a, 0x0009, 0x002a, + EVR_SL, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_GENIE_1" } + , { 0x0009, 0x002c, 0x0009, 0x002c, + EVR_LO, "SeriesComments", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_GENIE_1" } + , { 0x0009, 0x002d, 0x0009, 0x002d, + EVR_SL, "TrackBeatAverage", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_GENIE_1" } + , { 0x0009, 0x002e, 0x0009, 0x002e, + EVR_FD, "DistancePrescribed", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_GENIE_1" } + , { 0x0009, 0x002f, 0x0009, 0x002f, + EVR_LT, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_IDEN_01" } + , { 0x0009, 0x0030, 0x0009, 0x0030, + EVR_LT, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CT VA0 IDE" } + , { 0x0009, 0x0030, 0x0009, 0x0030, + EVR_SQ, "AnonymizerPatientIDMap", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "DCMTK_ANONYMIZER" } + , { 0x0009, 0x0030, 0x0009, 0x0030, + EVR_LT, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CT VA0 ORI" } + , { 0x0009, 0x0030, 0x0009, 0x0030, + EVR_SH, "ServiceId", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_IDEN_01" } + , { 0x0009, 0x0030, 0x0009, 0x0030, + EVR_LO, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_GENIE_1" } + , { 0x0009, 0x0030, 0x0009, 0x0030, + EVR_UL, "ByteOffsetOfOriginalHeader", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MED" } + , { 0x0009, 0x0030, 0x0009, 0x0030, + EVR_LO, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P-GV-CT Release 1" } + , { 0x0009, 0x0031, 0x0009, 0x0031, + EVR_LT, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CT VA0 IDE" } + , { 0x0009, 0x0031, 0x0009, 0x0031, + EVR_LT, "PACSUniqueIdentifier", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1" } + , { 0x0009, 0x0031, 0x0009, 0x0031, + EVR_SH, "MobileLocationNumber", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_IDEN_01" } + , { 0x0009, 0x0031, 0x0009, 0x0031, + EVR_UL, "LengthOfOriginalHeader", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MED" } + , { 0x0009, 0x0032, 0x0009, 0x0032, + EVR_LT, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CT VA0 IDE" } + , { 0x0009, 0x0032, 0x0009, 0x0032, + EVR_TM, "ExposureStartTime", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "INTEGRIS 1.0" } + , { 0x0009, 0x0034, 0x0009, 0x0034, + EVR_LT, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CT VA0 IDE" } + , { 0x0009, 0x0034, 0x0009, 0x0034, + EVR_LT, "ClusterUniqueIdentifier", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1" } + , { 0x0009, 0x0035, 0x0009, 0x0035, + EVR_SL, "GantryLocusType", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_GENIE_1" } + , { 0x0009, 0x0037, 0x0009, 0x0037, + EVR_SL, "StartingHeartRate", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_GENIE_1" } + , { 0x0009, 0x0038, 0x0009, 0x0038, + EVR_LT, "SystemUniqueIdentifier", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1" } + , { 0x0009, 0x0038, 0x0009, 0x0038, + EVR_SL, "RRWindowWidth", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_GENIE_1" } + , { 0x0009, 0x0039, 0x0009, 0x0039, + EVR_LT, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1" } + , { 0x0009, 0x0039, 0x0009, 0x0039, + EVR_SL, "RRWindowOffset", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_GENIE_1" } + , { 0x0009, 0x003a, 0x0009, 0x003a, + EVR_SL, "PercentCycleImaged", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_GENIE_1" } + , { 0x0009, 0x003e, 0x0009, 0x003e, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0009, 0x003f, 0x0009, 0x003f, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0009, 0x0040, 0x0009, 0x0040, + EVR_LT, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CT VA0 IDE" } + , { 0x0009, 0x0040, 0x0009, 0x0040, + EVR_US, "DataObjectType", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI" } + , { 0x0009, 0x0040, 0x0009, 0x0040, + EVR_LO, "AnonymizerPatientIDKey", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "DCMTK_ANONYMIZER" } + , { 0x0009, 0x0040, 0x0009, 0x0040, + EVR_SQ, "AlternateImageSequence", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "CARDIO-D.R. 1.0" } + , { 0x0009, 0x0040, 0x0009, 0x0040, + EVR_LO, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_GENIE_1" } + , { 0x0009, 0x0040, 0x0009, 0x0040, + EVR_US, "DataObjectType", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI RELEASE 1" } + , { 0x0009, 0x0040, 0x0009, 0x0040, + EVR_US, "DataObjectType", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI Release 1" } + , { 0x0009, 0x0040, 0x0009, 0x0040, + EVR_LO, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P-GV-CT Release 1" } + , { 0x0009, 0x0040, 0x0009, 0x0040, + EVR_UL, "ByteOffsetOfPixelmatrix", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MED" } + , { 0x0009, 0x0041, 0x0009, 0x0041, + EVR_LT, "DataObjectSubtype", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI" } + , { 0x0009, 0x0041, 0x0009, 0x0041, + EVR_SL, "PatientFlags", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_GENIE_1" } + , { 0x0009, 0x0041, 0x0009, 0x0041, + EVR_LO, "DataObjectSubtype", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI RELEASE 1" } + , { 0x0009, 0x0041, 0x0009, 0x0041, + EVR_LO, "DataObjectSubtype", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI Release 1" } + , { 0x0009, 0x0041, 0x0009, 0x0041, + EVR_UL, "LengthOfPixelmatrixInBytes", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MED" } + , { 0x0009, 0x0042, 0x0009, 0x0042, + EVR_LT, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CT VA0 IDE" } + , { 0x0009, 0x0042, 0x0009, 0x0042, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0009, 0x0042, 0x0009, 0x0042, + EVR_DA, "PatientCreationDate", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_GENIE_1" } + , { 0x0009, 0x0043, 0x0009, 0x0043, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0009, 0x0043, 0x0009, 0x0043, + EVR_TM, "PatientCreationTime", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_GENIE_1" } + , { 0x0009, 0x0050, 0x0009, 0x0050, + EVR_LT, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CT VA0 IDE" } + , { 0x0009, 0x0050, 0x0009, 0x0050, + EVR_LO, "AnonymizerPatientIDValue", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "DCMTK_ANONYMIZER" } + , { 0x0009, 0x0050, 0x0009, 0x0050, + EVR_LO, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P-GV-CT Release 1" } + , { 0x0009, 0x0050, 0x0009, 0x0050, + EVR_LT, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MED" } + , { 0x0009, 0x0051, 0x0009, 0x0051, + EVR_LT, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CT VA0 IDE" } + , { 0x0009, 0x0051, 0x0009, 0x0051, + EVR_LT, "StudyUniqueIdentifier", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1" } + , { 0x0009, 0x0051, 0x0009, 0x0051, + EVR_LT, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MED" } + , { 0x0009, 0x0060, 0x0009, 0x0060, + EVR_LO, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P-GV-CT Release 1" } + , { 0x0009, 0x0061, 0x0009, 0x0061, + EVR_LT, "SeriesUniqueIdentifier", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1" } + , { 0x0009, 0x0070, 0x0009, 0x0070, + EVR_LO, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P-GV-CT Release 1" } + , { 0x0009, 0x0075, 0x0009, 0x0075, + EVR_LO, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P-GV-CT Release 1" } + , { 0x0009, 0x0080, 0x0009, 0x0080, + EVR_LO, "KanjiHospitalName", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "FDMS 1.0" } + , { 0x0009, 0x0080, 0x0009, 0x0080, + EVR_LO, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P-GV-CT Release 1" } + , { 0x0009, 0x0090, 0x0009, 0x0090, + EVR_ST, "DistributionCode", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "FDMS 1.0" } + , { 0x0009, 0x0090, 0x0009, 0x0090, + EVR_LO, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P-GV-CT Release 1" } + , { 0x0009, 0x0091, 0x0009, 0x0091, + EVR_LT, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1" } + , { 0x0009, 0x0092, 0x0009, 0x0092, + EVR_SH, "KanjiDepartmentName", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "FDMS 1.0" } + , { 0x0009, 0x00c0, 0x0009, 0x00c0, + EVR_LT, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1;1" } + , { 0x0009, 0x00c1, 0x0009, 0x00c1, + EVR_LT, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1;1" } + , { 0x0009, 0x00e2, 0x0009, 0x00e2, + EVR_LT, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_IDEN_01" } + , { 0x0009, 0x00e3, 0x0009, 0x00e3, + EVR_UI, "EquipmentUID", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_IDEN_01" } + , { 0x0009, 0x00e6, 0x0009, 0x00e6, + EVR_SH, "GenesisVersionNow", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_IDEN_01" } + , { 0x0009, 0x00e7, 0x0009, 0x00e7, + EVR_UL, "ExamRecordChecksum", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_IDEN_01" } + , { 0x0009, 0x00e8, 0x0009, 0x00e8, + EVR_UL, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_IDEN_01" } + , { 0x0009, 0x00e9, 0x0009, 0x00e9, + EVR_SL, "ActualSeriesDataTimeStamp", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_IDEN_01" } + , { 0x0009, 0x00f0, 0x0009, 0x00f0, + EVR_CS, "BlackeningProcessFlag", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "FDMS 1.0" } + , { 0x0009, 0x00f2, 0x0009, 0x00f2, + EVR_LT, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1" } + , { 0x0009, 0x00f3, 0x0009, 0x00f3, + EVR_UN, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1" } + , { 0x0009, 0x00f4, 0x0009, 0x00f4, + EVR_LT, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1" } + , { 0x0009, 0x00f5, 0x0009, 0x00f5, + EVR_UN, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1" } + , { 0x0009, 0x00f5, 0x0009, 0x00f5, + EVR_LT, "PDMEFIDPlaceholder", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MED" } + , { 0x0009, 0x00f6, 0x0009, 0x00f6, + EVR_LT, "PDMDataObjectTypeExtension", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MED" } + , { 0x0009, 0x00f7, 0x0009, 0x00f7, + EVR_LT, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1" } + , { 0x0009, 0x00f8, 0x0009, 0x00f8, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0009, 0x00fb, 0x0009, 0x00fb, + EVR_IS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } +#endif + , { 0x0010, 0x0010, 0x0010, 0x0010, + EVR_PN, "PatientName", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0010, 0x0020, 0x0010, 0x0020, + EVR_LO, "PatientID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0010, 0x0021, 0x0010, 0x0021, + EVR_LO, "IssuerOfPatientID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0010, 0x0022, 0x0010, 0x0022, + EVR_CS, "TypeOfPatientID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0010, 0x0024, 0x0010, 0x0024, + EVR_SQ, "IssuerOfPatientIDQualifiersSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0010, 0x0030, 0x0010, 0x0030, + EVR_DA, "PatientBirthDate", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0010, 0x0032, 0x0010, 0x0032, + EVR_TM, "PatientBirthTime", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0010, 0x0040, 0x0010, 0x0040, + EVR_CS, "PatientSex", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0010, 0x0050, 0x0010, 0x0050, + EVR_SQ, "PatientInsurancePlanCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0010, 0x0101, 0x0010, 0x0101, + EVR_SQ, "PatientPrimaryLanguageCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0010, 0x0102, 0x0010, 0x0102, + EVR_SQ, "PatientPrimaryLanguageModifierCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0010, 0x0200, 0x0010, 0x0200, + EVR_CS, "QualityControlSubject", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0010, 0x0201, 0x0010, 0x0201, + EVR_SQ, "QualityControlSubjectTypeCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0010, 0x1000, 0x0010, 0x1000, + EVR_LO, "OtherPatientIDs", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0010, 0x1001, 0x0010, 0x1001, + EVR_PN, "OtherPatientNames", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0010, 0x1002, 0x0010, 0x1002, + EVR_SQ, "OtherPatientIDsSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0010, 0x1005, 0x0010, 0x1005, + EVR_PN, "PatientBirthName", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0010, 0x1010, 0x0010, 0x1010, + EVR_AS, "PatientAge", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0010, 0x1020, 0x0010, 0x1020, + EVR_DS, "PatientSize", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0010, 0x1021, 0x0010, 0x1021, + EVR_SQ, "PatientSizeCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0010, 0x1030, 0x0010, 0x1030, + EVR_DS, "PatientWeight", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0010, 0x1040, 0x0010, 0x1040, + EVR_LO, "PatientAddress", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0010, 0x1050, 0x0010, 0x1050, + EVR_LO, "RETIRED_InsurancePlanIdentification", 1, -1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0010, 0x1060, 0x0010, 0x1060, + EVR_PN, "PatientMotherBirthName", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0010, 0x1080, 0x0010, 0x1080, + EVR_LO, "MilitaryRank", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0010, 0x1081, 0x0010, 0x1081, + EVR_LO, "BranchOfService", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0010, 0x1090, 0x0010, 0x1090, + EVR_LO, "MedicalRecordLocator", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0010, 0x1100, 0x0010, 0x1100, + EVR_SQ, "ReferencedPatientPhotoSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0010, 0x2000, 0x0010, 0x2000, + EVR_LO, "MedicalAlerts", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0010, 0x2110, 0x0010, 0x2110, + EVR_LO, "Allergies", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0010, 0x2150, 0x0010, 0x2150, + EVR_LO, "CountryOfResidence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0010, 0x2152, 0x0010, 0x2152, + EVR_LO, "RegionOfResidence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0010, 0x2154, 0x0010, 0x2154, + EVR_SH, "PatientTelephoneNumbers", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0010, 0x2155, 0x0010, 0x2155, + EVR_LT, "PatientTelecomInformation", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0010, 0x2160, 0x0010, 0x2160, + EVR_SH, "EthnicGroup", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0010, 0x2180, 0x0010, 0x2180, + EVR_SH, "Occupation", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0010, 0x21a0, 0x0010, 0x21a0, + EVR_CS, "SmokingStatus", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0010, 0x21b0, 0x0010, 0x21b0, + EVR_LT, "AdditionalPatientHistory", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0010, 0x21c0, 0x0010, 0x21c0, + EVR_US, "PregnancyStatus", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0010, 0x21d0, 0x0010, 0x21d0, + EVR_DA, "LastMenstrualDate", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0010, 0x21f0, 0x0010, 0x21f0, + EVR_LO, "PatientReligiousPreference", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0010, 0x2201, 0x0010, 0x2201, + EVR_LO, "PatientSpeciesDescription", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0010, 0x2202, 0x0010, 0x2202, + EVR_SQ, "PatientSpeciesCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0010, 0x2203, 0x0010, 0x2203, + EVR_CS, "PatientSexNeutered", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0010, 0x2210, 0x0010, 0x2210, + EVR_CS, "AnatomicalOrientationType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0010, 0x2292, 0x0010, 0x2292, + EVR_LO, "PatientBreedDescription", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0010, 0x2293, 0x0010, 0x2293, + EVR_SQ, "PatientBreedCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0010, 0x2294, 0x0010, 0x2294, + EVR_SQ, "BreedRegistrationSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0010, 0x2295, 0x0010, 0x2295, + EVR_LO, "BreedRegistrationNumber", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0010, 0x2296, 0x0010, 0x2296, + EVR_SQ, "BreedRegistryCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0010, 0x2297, 0x0010, 0x2297, + EVR_PN, "ResponsiblePerson", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0010, 0x2298, 0x0010, 0x2298, + EVR_CS, "ResponsiblePersonRole", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0010, 0x2299, 0x0010, 0x2299, + EVR_LO, "ResponsibleOrganization", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0010, 0x4000, 0x0010, 0x4000, + EVR_LT, "PatientComments", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0010, 0x9431, 0x0010, 0x9431, + EVR_FL, "ExaminedBodyThickness", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } +#ifdef ENABLE_PRIVATE_TAGS + , { 0x0011, 0x0001, 0x0011, 0x0001, + EVR_LT, "PatientDOB", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "DLX_PATNT_01" } + , { 0x0011, 0x0001, 0x0011, 0x0001, + EVR_LT, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "TOSHIBA_MEC_1.0" } + , { 0x0011, 0x0002, 0x0011, 0x0002, + EVR_US, "Unknown", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "TOSHIBA_MEC_1.0" } + , { 0x0011, 0x0003, 0x0011, 0x0003, + EVR_LT, "PatientUID", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS ISI" } + , { 0x0011, 0x0004, 0x0011, 0x0004, + EVR_LT, "PatientID", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS ISI" } + , { 0x0011, 0x000a, 0x0011, 0x000a, + EVR_SL, "SeriesType", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_GENIE_1" } + , { 0x0011, 0x000a, 0x0011, 0x000a, + EVR_LT, "CaseID", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS ISI" } + , { 0x0011, 0x000a, 0x0011, 0x000a, + EVR_LT, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CM VA0 CMS" } + , { 0x0011, 0x000b, 0x0011, 0x000b, + EVR_SL, "EffectiveSeriesDuration", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_GENIE_1" } + , { 0x0011, 0x000c, 0x0011, 0x000c, + EVR_SL, "NumBeats", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_GENIE_1" } + , { 0x0011, 0x000d, 0x0011, 0x000d, + EVR_LO, "RadioNuclideName", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_GENIE_1" } + , { 0x0011, 0x0010, 0x0011, 0x0010, + EVR_LO, "Organ", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI RELEASE 1" } + , { 0x0011, 0x0010, 0x0011, 0x0010, + EVR_LO, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_GENIE_1" } + , { 0x0011, 0x0010, 0x0011, 0x0010, + EVR_LO, "Organ", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI Release 1" } + , { 0x0011, 0x0010, 0x0011, 0x0010, + EVR_LT, "PatientEntryID", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1" } + , { 0x0011, 0x0010, 0x0011, 0x0010, + EVR_LT, "Organ", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI" } + , { 0x0011, 0x0010, 0x0011, 0x0010, + EVR_LT, "PatientUID", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RIS" } + , { 0x0011, 0x0010, 0x0011, 0x0010, + EVR_DA, "RegistrationDate", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CM VA0 CMS" } + , { 0x0011, 0x0010, 0x0011, 0x0010, + EVR_SS, "PatientStatus", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PATI_01" } + , { 0x0011, 0x0011, 0x0011, 0x0011, + EVR_LT, "PatientID", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RIS" } + , { 0x0011, 0x0011, 0x0011, 0x0011, + EVR_TM, "RegistrationTime", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CM VA0 CMS" } + , { 0x0011, 0x0012, 0x0011, 0x0012, + EVR_LO, "DatasetName", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_GENIE_1" } + , { 0x0011, 0x0013, 0x0011, 0x0013, + EVR_SL, "DatasetType", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_GENIE_1" } + , { 0x0011, 0x0015, 0x0011, 0x0015, + EVR_LO, "AllergyIndication", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI RELEASE 1" } + , { 0x0011, 0x0015, 0x0011, 0x0015, + EVR_SL, "DetectorNumber", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_GENIE_1" } + , { 0x0011, 0x0015, 0x0011, 0x0015, + EVR_LO, "AllergyIndication", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI Release 1" } + , { 0x0011, 0x0015, 0x0011, 0x0015, + EVR_LT, "AllergyIndication", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI" } + , { 0x0011, 0x0016, 0x0011, 0x0016, + EVR_SL, "EnergyNumber", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_GENIE_1" } + , { 0x0011, 0x0017, 0x0011, 0x0017, + EVR_SL, "RRIntervalWindowNumber", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_GENIE_1" } + , { 0x0011, 0x0018, 0x0011, 0x0018, + EVR_SL, "MGBinNumber", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_GENIE_1" } + , { 0x0011, 0x0018, 0x0011, 0x0018, + EVR_LT, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 2;1" } + , { 0x0011, 0x0019, 0x0011, 0x0019, + EVR_FD, "RadiusOfRotation", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_GENIE_1" } + , { 0x0011, 0x001a, 0x0011, 0x001a, + EVR_SL, "DetectorCountZone", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_GENIE_1" } + , { 0x0011, 0x001b, 0x0011, 0x001b, + EVR_SL, "NumEnergyWindows", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_GENIE_1" } + , { 0x0011, 0x001c, 0x0011, 0x001c, + EVR_SL, "EnergyOffset", 4, 4, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_GENIE_1" } + , { 0x0011, 0x001d, 0x0011, 0x001d, + EVR_SL, "EnergyRange", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_GENIE_1" } + , { 0x0011, 0x001f, 0x0011, 0x001f, + EVR_SL, "ImageOrientation", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_GENIE_1" } + , { 0x0011, 0x0020, 0x0011, 0x0020, + EVR_LO, "Pregnancy", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI RELEASE 1" } + , { 0x0011, 0x0020, 0x0011, 0x0020, + EVR_SL, "FluoroTimer", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA GEN" } + , { 0x0011, 0x0020, 0x0011, 0x0020, + EVR_LO, "Pregnancy", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI Release 1" } + , { 0x0011, 0x0020, 0x0011, 0x0020, + EVR_LT, "Pregnancy", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI" } + , { 0x0011, 0x0020, 0x0011, 0x0020, + EVR_DA, "PatientRegistrationDate", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RIS" } + , { 0x0011, 0x0021, 0x0011, 0x0021, + EVR_UN, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1" } + , { 0x0011, 0x0021, 0x0011, 0x0021, + EVR_TM, "PatientRegistrationTime", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RIS" } + , { 0x0011, 0x0022, 0x0011, 0x0022, + EVR_UN, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1" } + , { 0x0011, 0x0022, 0x0011, 0x0022, + EVR_LT, "RequestID", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS ISI" } + , { 0x0011, 0x0022, 0x0011, 0x0022, + EVR_LT, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CM VA0 CMS" } + , { 0x0011, 0x0023, 0x0011, 0x0023, + EVR_SL, "UseFOVMask", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_GENIE_1" } + , { 0x0011, 0x0023, 0x0011, 0x0023, + EVR_LT, "ExaminationUID", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS ISI" } + , { 0x0011, 0x0023, 0x0011, 0x0023, + EVR_DS, "UsedPatientWeight", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CM VA0 CMS" } + , { 0x0011, 0x0024, 0x0011, 0x0024, + EVR_SL, "FOVMaskYCutoffAngle", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_GENIE_1" } + , { 0x0011, 0x0025, 0x0011, 0x0025, + EVR_SL, "PtopDoseAreaProduct", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA GEN" } + , { 0x0011, 0x0025, 0x0011, 0x0025, + EVR_SL, "FOVMaskCutoffAngle", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_GENIE_1" } + , { 0x0011, 0x0026, 0x0011, 0x0026, + EVR_SL, "PtopTotalSkinDose", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA GEN" } + , { 0x0011, 0x0026, 0x0011, 0x0026, + EVR_SL, "TableOrientation", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_GENIE_1" } + , { 0x0011, 0x0027, 0x0011, 0x0027, + EVR_SL, "ROITopLeft", 2, 2, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_GENIE_1" } + , { 0x0011, 0x0028, 0x0011, 0x0028, + EVR_SL, "ROIBottomRight", 2, 2, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_GENIE_1" } + , { 0x0011, 0x0028, 0x0011, 0x0028, + EVR_SL, "FluoroTimerB", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE B" } + , { 0x0011, 0x0028, 0x0011, 0x0028, + EVR_SL, "FluoroTimerA", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0011, 0x0029, 0x0011, 0x0029, + EVR_SL, "FluoroSkinDoseB", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE B" } + , { 0x0011, 0x0029, 0x0011, 0x0029, + EVR_SL, "FluoroSkinDoseA", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0011, 0x002a, 0x0011, 0x002a, + EVR_SL, "TotalSkinDoseB", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE B" } + , { 0x0011, 0x002a, 0x0011, 0x002a, + EVR_SL, "TotalSkinDoseA", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0011, 0x002b, 0x0011, 0x002b, + EVR_SL, "FluoroDoseAreaProductB", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE B" } + , { 0x0011, 0x002b, 0x0011, 0x002b, + EVR_SL, "FluoroDoseAreaProductA", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0011, 0x002c, 0x0011, 0x002c, + EVR_SL, "TotalDoseAreaProductB", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE B" } + , { 0x0011, 0x002c, 0x0011, 0x002c, + EVR_SL, "TotalDoseAreaProductA", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0011, 0x0030, 0x0011, 0x0030, + EVR_LT, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA GEN" } + , { 0x0011, 0x0030, 0x0011, 0x0030, + EVR_LO, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_GENIE_1" } + , { 0x0011, 0x0030, 0x0011, 0x0030, + EVR_LT, "PatientnameRIS", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RIS" } + , { 0x0011, 0x0031, 0x0011, 0x0031, + EVR_UN, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1" } + , { 0x0011, 0x0031, 0x0011, 0x0031, + EVR_LT, "PatientprenameRIS", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RIS" } + , { 0x0011, 0x0032, 0x0011, 0x0032, + EVR_UN, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1" } + , { 0x0011, 0x0033, 0x0011, 0x0033, + EVR_LO, "EnergyCorrectName", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_GENIE_1" } + , { 0x0011, 0x0034, 0x0011, 0x0034, + EVR_LO, "SpatialCorrectName", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_GENIE_1" } + , { 0x0011, 0x0035, 0x0011, 0x0035, + EVR_LO, "PatientInitialPuckCounter", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA GEN" } + , { 0x0011, 0x0035, 0x0011, 0x0035, + EVR_LO, "TuningCalibName", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_GENIE_1" } + , { 0x0011, 0x0036, 0x0011, 0x0036, + EVR_LO, "UniformityCorrectName", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_GENIE_1" } + , { 0x0011, 0x0037, 0x0011, 0x0037, + EVR_LO, "AcquisitionSpecificCorrectName", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_GENIE_1" } + , { 0x0011, 0x0038, 0x0011, 0x0038, + EVR_SL, "ByteOrder", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_GENIE_1" } + , { 0x0011, 0x003a, 0x0011, 0x003a, + EVR_SL, "PictureFormat", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_GENIE_1" } + , { 0x0011, 0x003b, 0x0011, 0x003b, + EVR_FD, "PixelScale", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_GENIE_1" } + , { 0x0011, 0x003c, 0x0011, 0x003c, + EVR_FD, "PixelOffset", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_GENIE_1" } + , { 0x0011, 0x003e, 0x0011, 0x003e, + EVR_SL, "FOVShape", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_GENIE_1" } + , { 0x0011, 0x003f, 0x0011, 0x003f, + EVR_SL, "DatasetFlags", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_GENIE_1" } + , { 0x0011, 0x0040, 0x0011, 0x0040, + EVR_SS, "SPIDataObjectType", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA GEN" } + , { 0x0011, 0x0040, 0x0011, 0x0040, + EVR_LT, "PatientHospitalStatus", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RIS" } + , { 0x0011, 0x0040, 0x0011, 0x0040, + EVR_IS, "OrganCode", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CM VA0 CMS" } + , { 0x0011, 0x0041, 0x0011, 0x0041, + EVR_LT, "MedicalAlerts", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RIS" } + , { 0x0011, 0x0042, 0x0011, 0x0042, + EVR_LT, "ContrastAllergies", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RIS" } + , { 0x0011, 0x0044, 0x0011, 0x0044, + EVR_FD, "ThresholdCenter", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_GENIE_1" } + , { 0x0011, 0x0045, 0x0011, 0x0045, + EVR_FD, "ThresholdWidth", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_GENIE_1" } + , { 0x0011, 0x0046, 0x0011, 0x0046, + EVR_SL, "InterpolationType", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_GENIE_1" } + , { 0x0011, 0x0055, 0x0011, 0x0055, + EVR_FD, "Period", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_GENIE_1" } + , { 0x0011, 0x0056, 0x0011, 0x0056, + EVR_FD, "ElapsedTime", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_GENIE_1" } + , { 0x0011, 0x00a1, 0x0011, 0x00a1, + EVR_DA, "PatientRegistrationDate", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS ISI" } + , { 0x0011, 0x00a2, 0x0011, 0x00a2, + EVR_TM, "PatientRegistrationTime", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS ISI" } + , { 0x0011, 0x00b0, 0x0011, 0x00b0, + EVR_LT, "PatientLastName", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS ISI" } + , { 0x0011, 0x00b2, 0x0011, 0x00b2, + EVR_LT, "PatientFirstName", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS ISI" } + , { 0x0011, 0x00b4, 0x0011, 0x00b4, + EVR_LT, "PatientHospitalStatus", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS ISI" } + , { 0x0011, 0x00bc, 0x0011, 0x00bc, + EVR_TM, "CurrentLocationTime", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS ISI" } + , { 0x0011, 0x00c0, 0x0011, 0x00c0, + EVR_LT, "PatientInsuranceStatus", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS ISI" } + , { 0x0011, 0x00d0, 0x0011, 0x00d0, + EVR_LT, "PatientBillingType", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS ISI" } + , { 0x0011, 0x00d2, 0x0011, 0x00d2, + EVR_LT, "PatientBillingAddress", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS ISI" } +#endif + , { 0x0012, 0x0010, 0x0012, 0x0010, + EVR_LO, "ClinicalTrialSponsorName", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0012, 0x0020, 0x0012, 0x0020, + EVR_LO, "ClinicalTrialProtocolID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0012, 0x0021, 0x0012, 0x0021, + EVR_LO, "ClinicalTrialProtocolName", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0012, 0x0030, 0x0012, 0x0030, + EVR_LO, "ClinicalTrialSiteID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0012, 0x0031, 0x0012, 0x0031, + EVR_LO, "ClinicalTrialSiteName", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0012, 0x0040, 0x0012, 0x0040, + EVR_LO, "ClinicalTrialSubjectID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0012, 0x0042, 0x0012, 0x0042, + EVR_LO, "ClinicalTrialSubjectReadingID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0012, 0x0050, 0x0012, 0x0050, + EVR_LO, "ClinicalTrialTimePointID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0012, 0x0051, 0x0012, 0x0051, + EVR_ST, "ClinicalTrialTimePointDescription", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0012, 0x0060, 0x0012, 0x0060, + EVR_LO, "ClinicalTrialCoordinatingCenterName", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0012, 0x0062, 0x0012, 0x0062, + EVR_CS, "PatientIdentityRemoved", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0012, 0x0063, 0x0012, 0x0063, + EVR_LO, "DeidentificationMethod", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0012, 0x0064, 0x0012, 0x0064, + EVR_SQ, "DeidentificationMethodCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0012, 0x0071, 0x0012, 0x0071, + EVR_LO, "ClinicalTrialSeriesID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0012, 0x0072, 0x0012, 0x0072, + EVR_LO, "ClinicalTrialSeriesDescription", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0012, 0x0081, 0x0012, 0x0081, + EVR_LO, "ClinicalTrialProtocolEthicsCommitteeName", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0012, 0x0082, 0x0012, 0x0082, + EVR_LO, "ClinicalTrialProtocolEthicsCommitteeApprovalNumber", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0012, 0x0083, 0x0012, 0x0083, + EVR_SQ, "ConsentForClinicalTrialUseSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0012, 0x0084, 0x0012, 0x0084, + EVR_CS, "DistributionType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0012, 0x0085, 0x0012, 0x0085, + EVR_CS, "ConsentForDistributionFlag", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } +#ifdef ENABLE_PRIVATE_TAGS + , { 0x0013, 0x0000, 0x0013, 0x0000, + EVR_LT, "ModifyingPhysician", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CM VA0 CMS" } + , { 0x0013, 0x0010, 0x0013, 0x0010, + EVR_FD, "DigitalFOV", 2, 2, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_GENIE_1" } + , { 0x0013, 0x0010, 0x0013, 0x0010, + EVR_DA, "ModificationDate", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CM VA0 CMS" } + , { 0x0013, 0x0011, 0x0013, 0x0011, + EVR_SL, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_GENIE_1" } + , { 0x0013, 0x0012, 0x0013, 0x0012, + EVR_SL, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_GENIE_1" } + , { 0x0013, 0x0012, 0x0013, 0x0012, + EVR_TM, "ModificationTime", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CM VA0 CMS" } + , { 0x0013, 0x0016, 0x0013, 0x0016, + EVR_SL, "AutoTrackPeak", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_GENIE_1" } + , { 0x0013, 0x0017, 0x0013, 0x0017, + EVR_SL, "AutoTrackWidth", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_GENIE_1" } + , { 0x0013, 0x0018, 0x0013, 0x0018, + EVR_FD, "TransmissionScanTime", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_GENIE_1" } + , { 0x0013, 0x0019, 0x0013, 0x0019, + EVR_FD, "TransmissionMaskWidth", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_GENIE_1" } + , { 0x0013, 0x001a, 0x0013, 0x001a, + EVR_FD, "CopperAttenuatorThickness", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_GENIE_1" } + , { 0x0013, 0x001c, 0x0013, 0x001c, + EVR_FD, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_GENIE_1" } + , { 0x0013, 0x001d, 0x0013, 0x001d, + EVR_FD, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_GENIE_1" } + , { 0x0013, 0x001e, 0x0013, 0x001e, + EVR_FD, "TomoViewOffset", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_GENIE_1" } + , { 0x0013, 0x0020, 0x0013, 0x0020, + EVR_LO, "PatientName", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CM VA0 CMS" } + , { 0x0013, 0x0022, 0x0013, 0x0022, + EVR_LO, "PatientId", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CM VA0 CMS" } + , { 0x0013, 0x0026, 0x0013, 0x0026, + EVR_LT, "StudyComments", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_GENIE_1" } + , { 0x0013, 0x0030, 0x0013, 0x0030, + EVR_DA, "PatientBirthdate", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CM VA0 CMS" } + , { 0x0013, 0x0031, 0x0013, 0x0031, + EVR_DS, "PatientWeight", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CM VA0 CMS" } + , { 0x0013, 0x0032, 0x0013, 0x0032, + EVR_LT, "PatientsMaidenName", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CM VA0 CMS" } + , { 0x0013, 0x0033, 0x0013, 0x0033, + EVR_LT, "ReferringPhysician", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CM VA0 CMS" } + , { 0x0013, 0x0034, 0x0013, 0x0034, + EVR_LT, "AdmittingDiagnosis", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CM VA0 CMS" } + , { 0x0013, 0x0035, 0x0013, 0x0035, + EVR_LO, "PatientSex", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CM VA0 CMS" } + , { 0x0013, 0x0040, 0x0013, 0x0040, + EVR_LO, "ProcedureDescription", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CM VA0 CMS" } + , { 0x0013, 0x0042, 0x0013, 0x0042, + EVR_LO, "RestDirection", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CM VA0 CMS" } + , { 0x0013, 0x0044, 0x0013, 0x0044, + EVR_LO, "PatientPosition", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CM VA0 CMS" } + , { 0x0013, 0x0046, 0x0013, 0x0046, + EVR_LT, "ViewDirection", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CM VA0 CMS" } + , { 0x0013, 0x0050, 0x0013, 0x0050, + EVR_LT, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CM VA0 CMS" } + , { 0x0013, 0x0051, 0x0013, 0x0051, + EVR_LT, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CM VA0 CMS" } + , { 0x0013, 0x0052, 0x0013, 0x0052, + EVR_LT, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CM VA0 CMS" } + , { 0x0013, 0x0053, 0x0013, 0x0053, + EVR_LT, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CM VA0 CMS" } + , { 0x0013, 0x0054, 0x0013, 0x0054, + EVR_LT, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CM VA0 CMS" } + , { 0x0013, 0x0055, 0x0013, 0x0055, + EVR_LT, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CM VA0 CMS" } + , { 0x0013, 0x0056, 0x0013, 0x0056, + EVR_LT, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CM VA0 CMS" } +#endif + , { 0x0014, 0x0023, 0x0014, 0x0023, + EVR_ST, "RETIRED_CADFileFormat", 1, -1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x0024, 0x0014, 0x0024, + EVR_ST, "RETIRED_ComponentReferenceSystem", 1, -1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x0025, 0x0014, 0x0025, + EVR_ST, "ComponentManufacturingProcedure", 1, -1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x0028, 0x0014, 0x0028, + EVR_ST, "ComponentManufacturer", 1, -1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x0030, 0x0014, 0x0030, + EVR_DS, "MaterialThickness", 1, -1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x0032, 0x0014, 0x0032, + EVR_DS, "MaterialPipeDiameter", 1, -1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x0034, 0x0014, 0x0034, + EVR_DS, "MaterialIsolationDiameter", 1, -1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x0042, 0x0014, 0x0042, + EVR_ST, "MaterialGrade", 1, -1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x0044, 0x0014, 0x0044, + EVR_ST, "MaterialPropertiesDescription", 1, -1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x0045, 0x0014, 0x0045, + EVR_ST, "RETIRED_MaterialPropertiesFileFormatRetired", 1, -1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x0046, 0x0014, 0x0046, + EVR_LT, "MaterialNotes", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x0050, 0x0014, 0x0050, + EVR_CS, "ComponentShape", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x0052, 0x0014, 0x0052, + EVR_CS, "CurvatureType", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x0054, 0x0014, 0x0054, + EVR_DS, "OuterDiameter", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x0056, 0x0014, 0x0056, + EVR_DS, "InnerDiameter", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x1010, 0x0014, 0x1010, + EVR_ST, "ActualEnvironmentalConditions", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x1020, 0x0014, 0x1020, + EVR_DA, "ExpiryDate", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x1040, 0x0014, 0x1040, + EVR_ST, "EnvironmentalConditions", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x2002, 0x0014, 0x2002, + EVR_SQ, "EvaluatorSequence", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x2004, 0x0014, 0x2004, + EVR_IS, "EvaluatorNumber", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x2006, 0x0014, 0x2006, + EVR_PN, "EvaluatorName", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x2008, 0x0014, 0x2008, + EVR_IS, "EvaluationAttempt", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x2012, 0x0014, 0x2012, + EVR_SQ, "IndicationSequence", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x2014, 0x0014, 0x2014, + EVR_IS, "IndicationNumber", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x2016, 0x0014, 0x2016, + EVR_SH, "IndicationLabel", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x2018, 0x0014, 0x2018, + EVR_ST, "IndicationDescription", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x201a, 0x0014, 0x201a, + EVR_CS, "IndicationType", 1, -1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x201c, 0x0014, 0x201c, + EVR_CS, "IndicationDisposition", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x201e, 0x0014, 0x201e, + EVR_SQ, "IndicationROISequence", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x2030, 0x0014, 0x2030, + EVR_SQ, "IndicationPhysicalPropertySequence", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x2032, 0x0014, 0x2032, + EVR_SH, "PropertyLabel", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x2202, 0x0014, 0x2202, + EVR_IS, "CoordinateSystemNumberOfAxes", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x2204, 0x0014, 0x2204, + EVR_SQ, "CoordinateSystemAxesSequence", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x2206, 0x0014, 0x2206, + EVR_ST, "CoordinateSystemAxisDescription", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x2208, 0x0014, 0x2208, + EVR_CS, "CoordinateSystemDataSetMapping", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x220a, 0x0014, 0x220a, + EVR_IS, "CoordinateSystemAxisNumber", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x220c, 0x0014, 0x220c, + EVR_CS, "CoordinateSystemAxisType", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x220e, 0x0014, 0x220e, + EVR_CS, "CoordinateSystemAxisUnits", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x2210, 0x0014, 0x2210, + EVR_OB, "CoordinateSystemAxisValues", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x2220, 0x0014, 0x2220, + EVR_SQ, "CoordinateSystemTransformSequence", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x2222, 0x0014, 0x2222, + EVR_ST, "TransformDescription", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x2224, 0x0014, 0x2224, + EVR_IS, "TransformNumberOfAxes", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x2226, 0x0014, 0x2226, + EVR_IS, "TransformOrderOfAxes", 1, -1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x2228, 0x0014, 0x2228, + EVR_CS, "TransformedAxisUnits", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x222a, 0x0014, 0x222a, + EVR_DS, "CoordinateSystemTransformRotationAndScaleMatrix", 1, -1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x222c, 0x0014, 0x222c, + EVR_DS, "CoordinateSystemTransformTranslationMatrix", 1, -1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x3011, 0x0014, 0x3011, + EVR_DS, "InternalDetectorFrameTime", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x3012, 0x0014, 0x3012, + EVR_DS, "NumberOfFramesIntegrated", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x3020, 0x0014, 0x3020, + EVR_SQ, "DetectorTemperatureSequence", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x3022, 0x0014, 0x3022, + EVR_ST, "SensorName", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x3024, 0x0014, 0x3024, + EVR_DS, "HorizontalOffsetOfSensor", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x3026, 0x0014, 0x3026, + EVR_DS, "VerticalOffsetOfSensor", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x3028, 0x0014, 0x3028, + EVR_DS, "SensorTemperature", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x3040, 0x0014, 0x3040, + EVR_SQ, "DarkCurrentSequence", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x3050, 0x0014, 0x3050, + EVR_ox, "DarkCurrentCounts", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x3060, 0x0014, 0x3060, + EVR_SQ, "GainCorrectionReferenceSequence", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x3070, 0x0014, 0x3070, + EVR_ox, "AirCounts", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x3071, 0x0014, 0x3071, + EVR_DS, "KVUsedInGainCalibration", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x3072, 0x0014, 0x3072, + EVR_DS, "MAUsedInGainCalibration", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x3073, 0x0014, 0x3073, + EVR_DS, "NumberOfFramesUsedForIntegration", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x3074, 0x0014, 0x3074, + EVR_LO, "FilterMaterialUsedInGainCalibration", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x3075, 0x0014, 0x3075, + EVR_DS, "FilterThicknessUsedInGainCalibration", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x3076, 0x0014, 0x3076, + EVR_DA, "DateOfGainCalibration", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x3077, 0x0014, 0x3077, + EVR_TM, "TimeOfGainCalibration", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x3080, 0x0014, 0x3080, + EVR_OB, "BadPixelImage", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x3099, 0x0014, 0x3099, + EVR_LT, "CalibrationNotes", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x4002, 0x0014, 0x4002, + EVR_SQ, "PulserEquipmentSequence", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x4004, 0x0014, 0x4004, + EVR_CS, "PulserType", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x4006, 0x0014, 0x4006, + EVR_LT, "PulserNotes", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x4008, 0x0014, 0x4008, + EVR_SQ, "ReceiverEquipmentSequence", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x400a, 0x0014, 0x400a, + EVR_CS, "AmplifierType", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x400c, 0x0014, 0x400c, + EVR_LT, "ReceiverNotes", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x400e, 0x0014, 0x400e, + EVR_SQ, "PreAmplifierEquipmentSequence", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x400f, 0x0014, 0x400f, + EVR_LT, "PreAmplifierNotes", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x4010, 0x0014, 0x4010, + EVR_SQ, "TransmitTransducerSequence", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x4011, 0x0014, 0x4011, + EVR_SQ, "ReceiveTransducerSequence", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x4012, 0x0014, 0x4012, + EVR_US, "NumberOfElements", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x4013, 0x0014, 0x4013, + EVR_CS, "ElementShape", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x4014, 0x0014, 0x4014, + EVR_DS, "ElementDimensionA", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x4015, 0x0014, 0x4015, + EVR_DS, "ElementDimensionB", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x4016, 0x0014, 0x4016, + EVR_DS, "ElementPitchA", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x4017, 0x0014, 0x4017, + EVR_DS, "MeasuredBeamDimensionA", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x4018, 0x0014, 0x4018, + EVR_DS, "MeasuredBeamDimensionB", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x4019, 0x0014, 0x4019, + EVR_DS, "LocationOfMeasuredBeamDiameter", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x401a, 0x0014, 0x401a, + EVR_DS, "NominalFrequency", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x401b, 0x0014, 0x401b, + EVR_DS, "MeasuredCenterFrequency", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x401c, 0x0014, 0x401c, + EVR_DS, "MeasuredBandwidth", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x401d, 0x0014, 0x401d, + EVR_DS, "ElementPitchB", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x4020, 0x0014, 0x4020, + EVR_SQ, "PulserSettingsSequence", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x4022, 0x0014, 0x4022, + EVR_DS, "PulseWidth", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x4024, 0x0014, 0x4024, + EVR_DS, "ExcitationFrequency", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x4026, 0x0014, 0x4026, + EVR_CS, "ModulationType", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x4028, 0x0014, 0x4028, + EVR_DS, "Damping", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x4030, 0x0014, 0x4030, + EVR_SQ, "ReceiverSettingsSequence", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x4031, 0x0014, 0x4031, + EVR_DS, "AcquiredSoundpathLength", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x4032, 0x0014, 0x4032, + EVR_CS, "AcquisitionCompressionType", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x4033, 0x0014, 0x4033, + EVR_IS, "AcquisitionSampleSize", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x4034, 0x0014, 0x4034, + EVR_DS, "RectifierSmoothing", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x4035, 0x0014, 0x4035, + EVR_SQ, "DACSequence", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x4036, 0x0014, 0x4036, + EVR_CS, "DACType", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x4038, 0x0014, 0x4038, + EVR_DS, "DACGainPoints", 1, -1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x403a, 0x0014, 0x403a, + EVR_DS, "DACTimePoints", 1, -1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x403c, 0x0014, 0x403c, + EVR_DS, "DACAmplitude", 1, -1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x4040, 0x0014, 0x4040, + EVR_SQ, "PreAmplifierSettingsSequence", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x4050, 0x0014, 0x4050, + EVR_SQ, "TransmitTransducerSettingsSequence", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x4051, 0x0014, 0x4051, + EVR_SQ, "ReceiveTransducerSettingsSequence", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x4052, 0x0014, 0x4052, + EVR_DS, "IncidentAngle", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x4054, 0x0014, 0x4054, + EVR_ST, "CouplingTechnique", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x4056, 0x0014, 0x4056, + EVR_ST, "CouplingMedium", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x4057, 0x0014, 0x4057, + EVR_DS, "CouplingVelocity", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x4058, 0x0014, 0x4058, + EVR_DS, "ProbeCenterLocationX", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x4059, 0x0014, 0x4059, + EVR_DS, "ProbeCenterLocationZ", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x405a, 0x0014, 0x405a, + EVR_DS, "SoundPathLength", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x405c, 0x0014, 0x405c, + EVR_ST, "DelayLawIdentifier", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x4060, 0x0014, 0x4060, + EVR_SQ, "GateSettingsSequence", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x4062, 0x0014, 0x4062, + EVR_DS, "GateThreshold", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x4064, 0x0014, 0x4064, + EVR_DS, "VelocityOfSound", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x4070, 0x0014, 0x4070, + EVR_SQ, "CalibrationSettingsSequence", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x4072, 0x0014, 0x4072, + EVR_ST, "CalibrationProcedure", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x4074, 0x0014, 0x4074, + EVR_SH, "ProcedureVersion", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x4076, 0x0014, 0x4076, + EVR_DA, "ProcedureCreationDate", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x4078, 0x0014, 0x4078, + EVR_DA, "ProcedureExpirationDate", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x407a, 0x0014, 0x407a, + EVR_DA, "ProcedureLastModifiedDate", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x407c, 0x0014, 0x407c, + EVR_TM, "CalibrationTime", 1, -1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x407e, 0x0014, 0x407e, + EVR_DA, "CalibrationDate", 1, -1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x4080, 0x0014, 0x4080, + EVR_SQ, "ProbeDriveEquipmentSequence", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x4081, 0x0014, 0x4081, + EVR_CS, "DriveType", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x4082, 0x0014, 0x4082, + EVR_LT, "ProbeDriveNotes", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x4083, 0x0014, 0x4083, + EVR_SQ, "DriveProbeSequence", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x4084, 0x0014, 0x4084, + EVR_DS, "ProbeInductance", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x4085, 0x0014, 0x4085, + EVR_DS, "ProbeResistance", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x4086, 0x0014, 0x4086, + EVR_SQ, "ReceiveProbeSequence", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x4087, 0x0014, 0x4087, + EVR_SQ, "ProbeDriveSettingsSequence", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x4088, 0x0014, 0x4088, + EVR_DS, "BridgeResistors", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x4089, 0x0014, 0x4089, + EVR_DS, "ProbeOrientationAngle", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x408b, 0x0014, 0x408b, + EVR_DS, "UserSelectedGainY", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x408c, 0x0014, 0x408c, + EVR_DS, "UserSelectedPhase", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x408d, 0x0014, 0x408d, + EVR_DS, "UserSelectedOffsetX", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x408e, 0x0014, 0x408e, + EVR_DS, "UserSelectedOffsetY", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x4091, 0x0014, 0x4091, + EVR_SQ, "ChannelSettingsSequence", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x4092, 0x0014, 0x4092, + EVR_DS, "ChannelThreshold", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x409a, 0x0014, 0x409a, + EVR_SQ, "ScannerSettingsSequence", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x409b, 0x0014, 0x409b, + EVR_ST, "ScanProcedure", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x409c, 0x0014, 0x409c, + EVR_DS, "TranslationRateX", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x409d, 0x0014, 0x409d, + EVR_DS, "TranslationRateY", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x409f, 0x0014, 0x409f, + EVR_DS, "ChannelOverlap", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x40a0, 0x0014, 0x40a0, + EVR_LO, "ImageQualityIndicatorType", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x40a1, 0x0014, 0x40a1, + EVR_LO, "ImageQualityIndicatorMaterial", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x40a2, 0x0014, 0x40a2, + EVR_LO, "ImageQualityIndicatorSize", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x5002, 0x0014, 0x5002, + EVR_IS, "LINACEnergy", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x5004, 0x0014, 0x5004, + EVR_IS, "LINACOutput", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x5100, 0x0014, 0x5100, + EVR_US, "ActiveAperture", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x5101, 0x0014, 0x5101, + EVR_DS, "TotalAperture", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x5102, 0x0014, 0x5102, + EVR_DS, "ApertureElevation", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x5103, 0x0014, 0x5103, + EVR_DS, "MainLobeAngle", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x5104, 0x0014, 0x5104, + EVR_DS, "MainRoofAngle", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x5105, 0x0014, 0x5105, + EVR_CS, "ConnectorType", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x5106, 0x0014, 0x5106, + EVR_SH, "WedgeModelNumber", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x5107, 0x0014, 0x5107, + EVR_DS, "WedgeAngleFloat", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x5108, 0x0014, 0x5108, + EVR_DS, "WedgeRoofAngle", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x5109, 0x0014, 0x5109, + EVR_CS, "WedgeElement1Position", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x510a, 0x0014, 0x510a, + EVR_DS, "WedgeMaterialVelocity", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x510b, 0x0014, 0x510b, + EVR_SH, "WedgeMaterial", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x510c, 0x0014, 0x510c, + EVR_DS, "WedgeOffsetZ", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x510d, 0x0014, 0x510d, + EVR_DS, "WedgeOriginOffsetX", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x510e, 0x0014, 0x510e, + EVR_DS, "WedgeTimeDelay", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x510f, 0x0014, 0x510f, + EVR_SH, "WedgeName", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x5110, 0x0014, 0x5110, + EVR_SH, "WedgeManufacturerName", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x5111, 0x0014, 0x5111, + EVR_LO, "WedgeDescription", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x5112, 0x0014, 0x5112, + EVR_DS, "NominalBeamAngle", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x5113, 0x0014, 0x5113, + EVR_DS, "WedgeOffsetX", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x5114, 0x0014, 0x5114, + EVR_DS, "WedgeOffsetY", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x5115, 0x0014, 0x5115, + EVR_DS, "WedgeTotalLength", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x5116, 0x0014, 0x5116, + EVR_DS, "WedgeInContactLength", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x5117, 0x0014, 0x5117, + EVR_DS, "WedgeFrontGap", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x5118, 0x0014, 0x5118, + EVR_DS, "WedgeTotalHeight", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x5119, 0x0014, 0x5119, + EVR_DS, "WedgeFrontHeight", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x511a, 0x0014, 0x511a, + EVR_DS, "WedgeRearHeight", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x511b, 0x0014, 0x511b, + EVR_DS, "WedgeTotalWidth", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x511c, 0x0014, 0x511c, + EVR_DS, "WedgeInContactWidth", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x511d, 0x0014, 0x511d, + EVR_DS, "WedgeChamferHeight", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x511e, 0x0014, 0x511e, + EVR_CS, "WedgeCurve", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0014, 0x511f, 0x0014, 0x511f, + EVR_DS, "RadiusAlongWedge", 1, 1, "DICOM/DICONDE", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } +#ifdef ENABLE_PRIVATE_TAGS + , { 0x0015, 0x0001, 0x0015, 0x0001, + EVR_DS, "StenosisCalibrationRatio", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "DLX_EXAMS_01" } + , { 0x0015, 0x0002, 0x0015, 0x0002, + EVR_DS, "StenosisMagnification", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "DLX_EXAMS_01" } + , { 0x0015, 0x0003, 0x0015, 0x0003, + EVR_DS, "CardiacCalibrationRatio", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "DLX_EXAMS_01" } + , { 0x0017, 0x0000, 0x0017, 0x0000, + EVR_LO, "ExtendedBodyPart", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SVISION" } + , { 0x0017, 0x0010, 0x0017, 0x0010, + EVR_LO, "ExtendedViewPosition", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SVISION" } + , { 0x0017, 0x00f0, 0x0017, 0x00f0, + EVR_IS, "ImagesSOPClass", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SVISION" } +#endif + , { 0x0018, 0x0010, 0x0018, 0x0010, + EVR_LO, "ContrastBolusAgent", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x0012, 0x0018, 0x0012, + EVR_SQ, "ContrastBolusAgentSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x0013, 0x0018, 0x0013, + EVR_FL, "ContrastBolusT1Relaxivity", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x0014, 0x0018, 0x0014, + EVR_SQ, "ContrastBolusAdministrationRouteSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x0015, 0x0018, 0x0015, + EVR_CS, "BodyPartExamined", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x0020, 0x0018, 0x0020, + EVR_CS, "ScanningSequence", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x0021, 0x0018, 0x0021, + EVR_CS, "SequenceVariant", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x0022, 0x0018, 0x0022, + EVR_CS, "ScanOptions", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x0023, 0x0018, 0x0023, + EVR_CS, "MRAcquisitionType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x0024, 0x0018, 0x0024, + EVR_SH, "SequenceName", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x0025, 0x0018, 0x0025, + EVR_CS, "AngioFlag", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x0026, 0x0018, 0x0026, + EVR_SQ, "InterventionDrugInformationSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x0027, 0x0018, 0x0027, + EVR_TM, "InterventionDrugStopTime", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x0028, 0x0018, 0x0028, + EVR_DS, "InterventionDrugDose", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x0029, 0x0018, 0x0029, + EVR_SQ, "InterventionDrugCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x002a, 0x0018, 0x002a, + EVR_SQ, "AdditionalDrugSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x0030, 0x0018, 0x0030, + EVR_LO, "RETIRED_Radionuclide", 1, -1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x0031, 0x0018, 0x0031, + EVR_LO, "Radiopharmaceutical", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x0032, 0x0018, 0x0032, + EVR_DS, "RETIRED_EnergyWindowCenterline", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x0033, 0x0018, 0x0033, + EVR_DS, "RETIRED_EnergyWindowTotalWidth", 1, -1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x0034, 0x0018, 0x0034, + EVR_LO, "InterventionDrugName", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x0035, 0x0018, 0x0035, + EVR_TM, "InterventionDrugStartTime", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x0036, 0x0018, 0x0036, + EVR_SQ, "InterventionSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x0037, 0x0018, 0x0037, + EVR_CS, "RETIRED_TherapyType", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x0038, 0x0018, 0x0038, + EVR_CS, "InterventionStatus", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x0039, 0x0018, 0x0039, + EVR_CS, "RETIRED_TherapyDescription", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x003a, 0x0018, 0x003a, + EVR_ST, "InterventionDescription", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x0040, 0x0018, 0x0040, + EVR_IS, "CineRate", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x0042, 0x0018, 0x0042, + EVR_CS, "InitialCineRunState", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x0050, 0x0018, 0x0050, + EVR_DS, "SliceThickness", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x0060, 0x0018, 0x0060, + EVR_DS, "KVP", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x0070, 0x0018, 0x0070, + EVR_IS, "CountsAccumulated", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x0071, 0x0018, 0x0071, + EVR_CS, "AcquisitionTerminationCondition", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x0072, 0x0018, 0x0072, + EVR_DS, "EffectiveDuration", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x0073, 0x0018, 0x0073, + EVR_CS, "AcquisitionStartCondition", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x0074, 0x0018, 0x0074, + EVR_IS, "AcquisitionStartConditionData", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x0075, 0x0018, 0x0075, + EVR_IS, "AcquisitionTerminationConditionData", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x0080, 0x0018, 0x0080, + EVR_DS, "RepetitionTime", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x0081, 0x0018, 0x0081, + EVR_DS, "EchoTime", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x0082, 0x0018, 0x0082, + EVR_DS, "InversionTime", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x0083, 0x0018, 0x0083, + EVR_DS, "NumberOfAverages", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x0084, 0x0018, 0x0084, + EVR_DS, "ImagingFrequency", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x0085, 0x0018, 0x0085, + EVR_SH, "ImagedNucleus", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x0086, 0x0018, 0x0086, + EVR_IS, "EchoNumbers", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x0087, 0x0018, 0x0087, + EVR_DS, "MagneticFieldStrength", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x0088, 0x0018, 0x0088, + EVR_DS, "SpacingBetweenSlices", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x0089, 0x0018, 0x0089, + EVR_IS, "NumberOfPhaseEncodingSteps", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x0090, 0x0018, 0x0090, + EVR_DS, "DataCollectionDiameter", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x0091, 0x0018, 0x0091, + EVR_IS, "EchoTrainLength", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x0093, 0x0018, 0x0093, + EVR_DS, "PercentSampling", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x0094, 0x0018, 0x0094, + EVR_DS, "PercentPhaseFieldOfView", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x0095, 0x0018, 0x0095, + EVR_DS, "PixelBandwidth", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1000, 0x0018, 0x1000, + EVR_LO, "DeviceSerialNumber", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1002, 0x0018, 0x1002, + EVR_UI, "DeviceUID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1003, 0x0018, 0x1003, + EVR_LO, "DeviceID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1004, 0x0018, 0x1004, + EVR_LO, "PlateID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1005, 0x0018, 0x1005, + EVR_LO, "GeneratorID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1006, 0x0018, 0x1006, + EVR_LO, "GridID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1007, 0x0018, 0x1007, + EVR_LO, "CassetteID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1008, 0x0018, 0x1008, + EVR_LO, "GantryID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1010, 0x0018, 0x1010, + EVR_LO, "SecondaryCaptureDeviceID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1011, 0x0018, 0x1011, + EVR_LO, "RETIRED_HardcopyCreationDeviceID", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1012, 0x0018, 0x1012, + EVR_DA, "DateOfSecondaryCapture", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1014, 0x0018, 0x1014, + EVR_TM, "TimeOfSecondaryCapture", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1016, 0x0018, 0x1016, + EVR_LO, "SecondaryCaptureDeviceManufacturer", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1017, 0x0018, 0x1017, + EVR_LO, "RETIRED_HardcopyDeviceManufacturer", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1018, 0x0018, 0x1018, + EVR_LO, "SecondaryCaptureDeviceManufacturerModelName", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1019, 0x0018, 0x1019, + EVR_LO, "SecondaryCaptureDeviceSoftwareVersions", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x101a, 0x0018, 0x101a, + EVR_LO, "RETIRED_HardcopyDeviceSoftwareVersion", 1, -1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x101b, 0x0018, 0x101b, + EVR_LO, "RETIRED_HardcopyDeviceManufacturerModelName", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1020, 0x0018, 0x1020, + EVR_LO, "SoftwareVersions", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1022, 0x0018, 0x1022, + EVR_SH, "VideoImageFormatAcquired", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1023, 0x0018, 0x1023, + EVR_LO, "DigitalImageFormatAcquired", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1030, 0x0018, 0x1030, + EVR_LO, "ProtocolName", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1040, 0x0018, 0x1040, + EVR_LO, "ContrastBolusRoute", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1041, 0x0018, 0x1041, + EVR_DS, "ContrastBolusVolume", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1042, 0x0018, 0x1042, + EVR_TM, "ContrastBolusStartTime", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1043, 0x0018, 0x1043, + EVR_TM, "ContrastBolusStopTime", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1044, 0x0018, 0x1044, + EVR_DS, "ContrastBolusTotalDose", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1045, 0x0018, 0x1045, + EVR_IS, "SyringeCounts", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1046, 0x0018, 0x1046, + EVR_DS, "ContrastFlowRate", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1047, 0x0018, 0x1047, + EVR_DS, "ContrastFlowDuration", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1048, 0x0018, 0x1048, + EVR_CS, "ContrastBolusIngredient", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1049, 0x0018, 0x1049, + EVR_DS, "ContrastBolusIngredientConcentration", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1050, 0x0018, 0x1050, + EVR_DS, "SpatialResolution", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1060, 0x0018, 0x1060, + EVR_DS, "TriggerTime", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1061, 0x0018, 0x1061, + EVR_LO, "TriggerSourceOrType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1062, 0x0018, 0x1062, + EVR_IS, "NominalInterval", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1063, 0x0018, 0x1063, + EVR_DS, "FrameTime", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1064, 0x0018, 0x1064, + EVR_LO, "CardiacFramingType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1065, 0x0018, 0x1065, + EVR_DS, "FrameTimeVector", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1066, 0x0018, 0x1066, + EVR_DS, "FrameDelay", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1067, 0x0018, 0x1067, + EVR_DS, "ImageTriggerDelay", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1068, 0x0018, 0x1068, + EVR_DS, "MultiplexGroupTimeOffset", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1069, 0x0018, 0x1069, + EVR_DS, "TriggerTimeOffset", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x106a, 0x0018, 0x106a, + EVR_CS, "SynchronizationTrigger", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x106c, 0x0018, 0x106c, + EVR_US, "SynchronizationChannel", 2, 2, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x106e, 0x0018, 0x106e, + EVR_UL, "TriggerSamplePosition", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1070, 0x0018, 0x1070, + EVR_LO, "RadiopharmaceuticalRoute", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1071, 0x0018, 0x1071, + EVR_DS, "RadiopharmaceuticalVolume", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1072, 0x0018, 0x1072, + EVR_TM, "RadiopharmaceuticalStartTime", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1073, 0x0018, 0x1073, + EVR_TM, "RadiopharmaceuticalStopTime", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1074, 0x0018, 0x1074, + EVR_DS, "RadionuclideTotalDose", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1075, 0x0018, 0x1075, + EVR_DS, "RadionuclideHalfLife", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1076, 0x0018, 0x1076, + EVR_DS, "RadionuclidePositronFraction", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1077, 0x0018, 0x1077, + EVR_DS, "RadiopharmaceuticalSpecificActivity", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1078, 0x0018, 0x1078, + EVR_DT, "RadiopharmaceuticalStartDateTime", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1079, 0x0018, 0x1079, + EVR_DT, "RadiopharmaceuticalStopDateTime", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1080, 0x0018, 0x1080, + EVR_CS, "BeatRejectionFlag", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1081, 0x0018, 0x1081, + EVR_IS, "LowRRValue", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1082, 0x0018, 0x1082, + EVR_IS, "HighRRValue", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1083, 0x0018, 0x1083, + EVR_IS, "IntervalsAcquired", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1084, 0x0018, 0x1084, + EVR_IS, "IntervalsRejected", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1085, 0x0018, 0x1085, + EVR_LO, "PVCRejection", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1086, 0x0018, 0x1086, + EVR_IS, "SkipBeats", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1088, 0x0018, 0x1088, + EVR_IS, "HeartRate", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1090, 0x0018, 0x1090, + EVR_IS, "CardiacNumberOfImages", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1094, 0x0018, 0x1094, + EVR_IS, "TriggerWindow", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1100, 0x0018, 0x1100, + EVR_DS, "ReconstructionDiameter", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1110, 0x0018, 0x1110, + EVR_DS, "DistanceSourceToDetector", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1111, 0x0018, 0x1111, + EVR_DS, "DistanceSourceToPatient", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1114, 0x0018, 0x1114, + EVR_DS, "EstimatedRadiographicMagnificationFactor", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1120, 0x0018, 0x1120, + EVR_DS, "GantryDetectorTilt", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1121, 0x0018, 0x1121, + EVR_DS, "GantryDetectorSlew", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1130, 0x0018, 0x1130, + EVR_DS, "TableHeight", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1131, 0x0018, 0x1131, + EVR_DS, "TableTraverse", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1134, 0x0018, 0x1134, + EVR_CS, "TableMotion", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1135, 0x0018, 0x1135, + EVR_DS, "TableVerticalIncrement", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1136, 0x0018, 0x1136, + EVR_DS, "TableLateralIncrement", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1137, 0x0018, 0x1137, + EVR_DS, "TableLongitudinalIncrement", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1138, 0x0018, 0x1138, + EVR_DS, "TableAngle", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x113a, 0x0018, 0x113a, + EVR_CS, "TableType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1140, 0x0018, 0x1140, + EVR_CS, "RotationDirection", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1141, 0x0018, 0x1141, + EVR_DS, "RETIRED_AngularPosition", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1142, 0x0018, 0x1142, + EVR_DS, "RadialPosition", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1143, 0x0018, 0x1143, + EVR_DS, "ScanArc", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1144, 0x0018, 0x1144, + EVR_DS, "AngularStep", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1145, 0x0018, 0x1145, + EVR_DS, "CenterOfRotationOffset", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1146, 0x0018, 0x1146, + EVR_DS, "RETIRED_RotationOffset", 1, -1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1147, 0x0018, 0x1147, + EVR_CS, "FieldOfViewShape", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1149, 0x0018, 0x1149, + EVR_IS, "FieldOfViewDimensions", 1, 2, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1150, 0x0018, 0x1150, + EVR_IS, "ExposureTime", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1151, 0x0018, 0x1151, + EVR_IS, "XRayTubeCurrent", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1152, 0x0018, 0x1152, + EVR_IS, "Exposure", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1153, 0x0018, 0x1153, + EVR_IS, "ExposureInuAs", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1154, 0x0018, 0x1154, + EVR_DS, "AveragePulseWidth", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1155, 0x0018, 0x1155, + EVR_CS, "RadiationSetting", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1156, 0x0018, 0x1156, + EVR_CS, "RectificationType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x115a, 0x0018, 0x115a, + EVR_CS, "RadiationMode", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x115e, 0x0018, 0x115e, + EVR_DS, "ImageAndFluoroscopyAreaDoseProduct", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1160, 0x0018, 0x1160, + EVR_SH, "FilterType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1161, 0x0018, 0x1161, + EVR_LO, "TypeOfFilters", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1162, 0x0018, 0x1162, + EVR_DS, "IntensifierSize", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1164, 0x0018, 0x1164, + EVR_DS, "ImagerPixelSpacing", 2, 2, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1166, 0x0018, 0x1166, + EVR_CS, "Grid", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1170, 0x0018, 0x1170, + EVR_IS, "GeneratorPower", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1180, 0x0018, 0x1180, + EVR_SH, "CollimatorGridName", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1181, 0x0018, 0x1181, + EVR_CS, "CollimatorType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1182, 0x0018, 0x1182, + EVR_IS, "FocalDistance", 1, 2, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1183, 0x0018, 0x1183, + EVR_DS, "XFocusCenter", 1, 2, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1184, 0x0018, 0x1184, + EVR_DS, "YFocusCenter", 1, 2, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1190, 0x0018, 0x1190, + EVR_DS, "FocalSpots", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1191, 0x0018, 0x1191, + EVR_CS, "AnodeTargetMaterial", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x11a0, 0x0018, 0x11a0, + EVR_DS, "BodyPartThickness", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x11a2, 0x0018, 0x11a2, + EVR_DS, "CompressionForce", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x11a4, 0x0018, 0x11a4, + EVR_LO, "PaddleDescription", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1200, 0x0018, 0x1200, + EVR_DA, "DateOfLastCalibration", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1201, 0x0018, 0x1201, + EVR_TM, "TimeOfLastCalibration", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1202, 0x0018, 0x1202, + EVR_DT, "DateTimeOfLastCalibration", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1210, 0x0018, 0x1210, + EVR_SH, "ConvolutionKernel", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1240, 0x0018, 0x1240, + EVR_IS, "RETIRED_UpperLowerPixelValues", 1, -1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1242, 0x0018, 0x1242, + EVR_IS, "ActualFrameDuration", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1243, 0x0018, 0x1243, + EVR_IS, "CountRate", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1244, 0x0018, 0x1244, + EVR_US, "PreferredPlaybackSequencing", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1250, 0x0018, 0x1250, + EVR_SH, "ReceiveCoilName", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1251, 0x0018, 0x1251, + EVR_SH, "TransmitCoilName", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1260, 0x0018, 0x1260, + EVR_SH, "PlateType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1261, 0x0018, 0x1261, + EVR_LO, "PhosphorType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1300, 0x0018, 0x1300, + EVR_DS, "ScanVelocity", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1301, 0x0018, 0x1301, + EVR_CS, "WholeBodyTechnique", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1302, 0x0018, 0x1302, + EVR_IS, "ScanLength", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1310, 0x0018, 0x1310, + EVR_US, "AcquisitionMatrix", 4, 4, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1312, 0x0018, 0x1312, + EVR_CS, "InPlanePhaseEncodingDirection", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1314, 0x0018, 0x1314, + EVR_DS, "FlipAngle", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1315, 0x0018, 0x1315, + EVR_CS, "VariableFlipAngleFlag", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1316, 0x0018, 0x1316, + EVR_DS, "SAR", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1318, 0x0018, 0x1318, + EVR_DS, "dBdt", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1320, 0x0018, 0x1320, + EVR_FL, "B1rms", 1, 1, "CP_1461", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1400, 0x0018, 0x1400, + EVR_LO, "AcquisitionDeviceProcessingDescription", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1401, 0x0018, 0x1401, + EVR_LO, "AcquisitionDeviceProcessingCode", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1402, 0x0018, 0x1402, + EVR_CS, "CassetteOrientation", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1403, 0x0018, 0x1403, + EVR_CS, "CassetteSize", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1404, 0x0018, 0x1404, + EVR_US, "ExposuresOnPlate", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1405, 0x0018, 0x1405, + EVR_IS, "RelativeXRayExposure", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1411, 0x0018, 0x1411, + EVR_DS, "ExposureIndex", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1412, 0x0018, 0x1412, + EVR_DS, "TargetExposureIndex", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1413, 0x0018, 0x1413, + EVR_DS, "DeviationIndex", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1450, 0x0018, 0x1450, + EVR_DS, "ColumnAngulation", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1460, 0x0018, 0x1460, + EVR_DS, "TomoLayerHeight", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1470, 0x0018, 0x1470, + EVR_DS, "TomoAngle", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1480, 0x0018, 0x1480, + EVR_DS, "TomoTime", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1490, 0x0018, 0x1490, + EVR_CS, "TomoType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1491, 0x0018, 0x1491, + EVR_CS, "TomoClass", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1495, 0x0018, 0x1495, + EVR_IS, "NumberOfTomosynthesisSourceImages", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1500, 0x0018, 0x1500, + EVR_CS, "PositionerMotion", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1508, 0x0018, 0x1508, + EVR_CS, "PositionerType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1510, 0x0018, 0x1510, + EVR_DS, "PositionerPrimaryAngle", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1511, 0x0018, 0x1511, + EVR_DS, "PositionerSecondaryAngle", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1520, 0x0018, 0x1520, + EVR_DS, "PositionerPrimaryAngleIncrement", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1521, 0x0018, 0x1521, + EVR_DS, "PositionerSecondaryAngleIncrement", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1530, 0x0018, 0x1530, + EVR_DS, "DetectorPrimaryAngle", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1531, 0x0018, 0x1531, + EVR_DS, "DetectorSecondaryAngle", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1600, 0x0018, 0x1600, + EVR_CS, "ShutterShape", 1, 3, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1602, 0x0018, 0x1602, + EVR_IS, "ShutterLeftVerticalEdge", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1604, 0x0018, 0x1604, + EVR_IS, "ShutterRightVerticalEdge", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1606, 0x0018, 0x1606, + EVR_IS, "ShutterUpperHorizontalEdge", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1608, 0x0018, 0x1608, + EVR_IS, "ShutterLowerHorizontalEdge", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1610, 0x0018, 0x1610, + EVR_IS, "CenterOfCircularShutter", 2, 2, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1612, 0x0018, 0x1612, + EVR_IS, "RadiusOfCircularShutter", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1620, 0x0018, 0x1620, + EVR_IS, "VerticesOfThePolygonalShutter", 2, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1622, 0x0018, 0x1622, + EVR_US, "ShutterPresentationValue", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1623, 0x0018, 0x1623, + EVR_US, "ShutterOverlayGroup", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1624, 0x0018, 0x1624, + EVR_US, "ShutterPresentationColorCIELabValue", 3, 3, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1700, 0x0018, 0x1700, + EVR_CS, "CollimatorShape", 1, 3, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1702, 0x0018, 0x1702, + EVR_IS, "CollimatorLeftVerticalEdge", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1704, 0x0018, 0x1704, + EVR_IS, "CollimatorRightVerticalEdge", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1706, 0x0018, 0x1706, + EVR_IS, "CollimatorUpperHorizontalEdge", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1708, 0x0018, 0x1708, + EVR_IS, "CollimatorLowerHorizontalEdge", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1710, 0x0018, 0x1710, + EVR_IS, "CenterOfCircularCollimator", 2, 2, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1712, 0x0018, 0x1712, + EVR_IS, "RadiusOfCircularCollimator", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1720, 0x0018, 0x1720, + EVR_IS, "VerticesOfThePolygonalCollimator", 2, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1800, 0x0018, 0x1800, + EVR_CS, "AcquisitionTimeSynchronized", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1801, 0x0018, 0x1801, + EVR_SH, "TimeSource", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1802, 0x0018, 0x1802, + EVR_CS, "TimeDistributionProtocol", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x1803, 0x0018, 0x1803, + EVR_LO, "NTPSourceAddress", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x2001, 0x0018, 0x2001, + EVR_IS, "PageNumberVector", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x2002, 0x0018, 0x2002, + EVR_SH, "FrameLabelVector", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x2003, 0x0018, 0x2003, + EVR_DS, "FramePrimaryAngleVector", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x2004, 0x0018, 0x2004, + EVR_DS, "FrameSecondaryAngleVector", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x2005, 0x0018, 0x2005, + EVR_DS, "SliceLocationVector", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x2006, 0x0018, 0x2006, + EVR_SH, "DisplayWindowLabelVector", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x2010, 0x0018, 0x2010, + EVR_DS, "NominalScannedPixelSpacing", 2, 2, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x2020, 0x0018, 0x2020, + EVR_CS, "DigitizingDeviceTransportDirection", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x2030, 0x0018, 0x2030, + EVR_DS, "RotationOfScannedFilm", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x2041, 0x0018, 0x2041, + EVR_SQ, "BiopsyTargetSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x2042, 0x0018, 0x2042, + EVR_UI, "TargetUID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x2043, 0x0018, 0x2043, + EVR_FL, "LocalizingCursorPosition", 2, 2, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x2044, 0x0018, 0x2044, + EVR_FL, "CalculatedTargetPosition", 3, 3, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x2045, 0x0018, 0x2045, + EVR_SH, "TargetLabel", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x2046, 0x0018, 0x2046, + EVR_FL, "DisplayedZValue", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x3100, 0x0018, 0x3100, + EVR_CS, "IVUSAcquisition", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x3101, 0x0018, 0x3101, + EVR_DS, "IVUSPullbackRate", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x3102, 0x0018, 0x3102, + EVR_DS, "IVUSGatedRate", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x3103, 0x0018, 0x3103, + EVR_IS, "IVUSPullbackStartFrameNumber", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x3104, 0x0018, 0x3104, + EVR_IS, "IVUSPullbackStopFrameNumber", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x3105, 0x0018, 0x3105, + EVR_IS, "LesionNumber", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x4000, 0x0018, 0x4000, + EVR_LT, "RETIRED_AcquisitionComments", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x5000, 0x0018, 0x5000, + EVR_SH, "OutputPower", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x5010, 0x0018, 0x5010, + EVR_LO, "TransducerData", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x5012, 0x0018, 0x5012, + EVR_DS, "FocusDepth", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x5020, 0x0018, 0x5020, + EVR_LO, "ProcessingFunction", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x5021, 0x0018, 0x5021, + EVR_LO, "RETIRED_PostprocessingFunction", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x5022, 0x0018, 0x5022, + EVR_DS, "MechanicalIndex", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x5024, 0x0018, 0x5024, + EVR_DS, "BoneThermalIndex", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x5026, 0x0018, 0x5026, + EVR_DS, "CranialThermalIndex", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x5027, 0x0018, 0x5027, + EVR_DS, "SoftTissueThermalIndex", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x5028, 0x0018, 0x5028, + EVR_DS, "SoftTissueFocusThermalIndex", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x5029, 0x0018, 0x5029, + EVR_DS, "SoftTissueSurfaceThermalIndex", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x5030, 0x0018, 0x5030, + EVR_DS, "RETIRED_DynamicRange", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x5040, 0x0018, 0x5040, + EVR_DS, "RETIRED_TotalGain", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x5050, 0x0018, 0x5050, + EVR_IS, "DepthOfScanField", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x5100, 0x0018, 0x5100, + EVR_CS, "PatientPosition", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x5101, 0x0018, 0x5101, + EVR_CS, "ViewPosition", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x5104, 0x0018, 0x5104, + EVR_SQ, "ProjectionEponymousNameCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x5210, 0x0018, 0x5210, + EVR_DS, "RETIRED_ImageTransformationMatrix", 6, 6, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x5212, 0x0018, 0x5212, + EVR_DS, "RETIRED_ImageTranslationVector", 3, 3, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x6000, 0x0018, 0x6000, + EVR_DS, "Sensitivity", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x6011, 0x0018, 0x6011, + EVR_SQ, "SequenceOfUltrasoundRegions", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x6012, 0x0018, 0x6012, + EVR_US, "RegionSpatialFormat", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x6014, 0x0018, 0x6014, + EVR_US, "RegionDataType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x6016, 0x0018, 0x6016, + EVR_UL, "RegionFlags", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x6018, 0x0018, 0x6018, + EVR_UL, "RegionLocationMinX0", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x601a, 0x0018, 0x601a, + EVR_UL, "RegionLocationMinY0", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x601c, 0x0018, 0x601c, + EVR_UL, "RegionLocationMaxX1", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x601e, 0x0018, 0x601e, + EVR_UL, "RegionLocationMaxY1", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x6020, 0x0018, 0x6020, + EVR_SL, "ReferencePixelX0", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x6022, 0x0018, 0x6022, + EVR_SL, "ReferencePixelY0", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x6024, 0x0018, 0x6024, + EVR_US, "PhysicalUnitsXDirection", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x6026, 0x0018, 0x6026, + EVR_US, "PhysicalUnitsYDirection", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x6028, 0x0018, 0x6028, + EVR_FD, "ReferencePixelPhysicalValueX", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x602a, 0x0018, 0x602a, + EVR_FD, "ReferencePixelPhysicalValueY", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x602c, 0x0018, 0x602c, + EVR_FD, "PhysicalDeltaX", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x602e, 0x0018, 0x602e, + EVR_FD, "PhysicalDeltaY", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x6030, 0x0018, 0x6030, + EVR_UL, "TransducerFrequency", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x6031, 0x0018, 0x6031, + EVR_CS, "TransducerType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x6032, 0x0018, 0x6032, + EVR_UL, "PulseRepetitionFrequency", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x6034, 0x0018, 0x6034, + EVR_FD, "DopplerCorrectionAngle", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x6036, 0x0018, 0x6036, + EVR_FD, "SteeringAngle", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x6038, 0x0018, 0x6038, + EVR_UL, "RETIRED_DopplerSampleVolumeXPositionRetired", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x6039, 0x0018, 0x6039, + EVR_SL, "DopplerSampleVolumeXPosition", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x603a, 0x0018, 0x603a, + EVR_UL, "RETIRED_DopplerSampleVolumeYPositionRetired", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x603b, 0x0018, 0x603b, + EVR_SL, "DopplerSampleVolumeYPosition", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x603c, 0x0018, 0x603c, + EVR_UL, "RETIRED_TMLinePositionX0Retired", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x603d, 0x0018, 0x603d, + EVR_SL, "TMLinePositionX0", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x603e, 0x0018, 0x603e, + EVR_UL, "RETIRED_TMLinePositionY0Retired", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x603f, 0x0018, 0x603f, + EVR_SL, "TMLinePositionY0", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x6040, 0x0018, 0x6040, + EVR_UL, "RETIRED_TMLinePositionX1Retired", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x6041, 0x0018, 0x6041, + EVR_SL, "TMLinePositionX1", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x6042, 0x0018, 0x6042, + EVR_UL, "RETIRED_TMLinePositionY1Retired", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x6043, 0x0018, 0x6043, + EVR_SL, "TMLinePositionY1", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x6044, 0x0018, 0x6044, + EVR_US, "PixelComponentOrganization", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x6046, 0x0018, 0x6046, + EVR_UL, "PixelComponentMask", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x6048, 0x0018, 0x6048, + EVR_UL, "PixelComponentRangeStart", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x604a, 0x0018, 0x604a, + EVR_UL, "PixelComponentRangeStop", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x604c, 0x0018, 0x604c, + EVR_US, "PixelComponentPhysicalUnits", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x604e, 0x0018, 0x604e, + EVR_US, "PixelComponentDataType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x6050, 0x0018, 0x6050, + EVR_UL, "NumberOfTableBreakPoints", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x6052, 0x0018, 0x6052, + EVR_UL, "TableOfXBreakPoints", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x6054, 0x0018, 0x6054, + EVR_FD, "TableOfYBreakPoints", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x6056, 0x0018, 0x6056, + EVR_UL, "NumberOfTableEntries", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x6058, 0x0018, 0x6058, + EVR_UL, "TableOfPixelValues", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x605a, 0x0018, 0x605a, + EVR_FL, "TableOfParameterValues", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x6060, 0x0018, 0x6060, + EVR_FL, "RWaveTimeVector", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x7000, 0x0018, 0x7000, + EVR_CS, "DetectorConditionsNominalFlag", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x7001, 0x0018, 0x7001, + EVR_DS, "DetectorTemperature", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x7004, 0x0018, 0x7004, + EVR_CS, "DetectorType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x7005, 0x0018, 0x7005, + EVR_CS, "DetectorConfiguration", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x7006, 0x0018, 0x7006, + EVR_LT, "DetectorDescription", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x7008, 0x0018, 0x7008, + EVR_LT, "DetectorMode", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x700a, 0x0018, 0x700a, + EVR_SH, "DetectorID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x700c, 0x0018, 0x700c, + EVR_DA, "DateOfLastDetectorCalibration", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x700e, 0x0018, 0x700e, + EVR_TM, "TimeOfLastDetectorCalibration", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x7010, 0x0018, 0x7010, + EVR_IS, "ExposuresOnDetectorSinceLastCalibration", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x7011, 0x0018, 0x7011, + EVR_IS, "ExposuresOnDetectorSinceManufactured", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x7012, 0x0018, 0x7012, + EVR_DS, "DetectorTimeSinceLastExposure", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x7014, 0x0018, 0x7014, + EVR_DS, "DetectorActiveTime", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x7016, 0x0018, 0x7016, + EVR_DS, "DetectorActivationOffsetFromExposure", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x701a, 0x0018, 0x701a, + EVR_DS, "DetectorBinning", 2, 2, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x7020, 0x0018, 0x7020, + EVR_DS, "DetectorElementPhysicalSize", 2, 2, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x7022, 0x0018, 0x7022, + EVR_DS, "DetectorElementSpacing", 2, 2, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x7024, 0x0018, 0x7024, + EVR_CS, "DetectorActiveShape", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x7026, 0x0018, 0x7026, + EVR_DS, "DetectorActiveDimensions", 1, 2, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x7028, 0x0018, 0x7028, + EVR_DS, "DetectorActiveOrigin", 2, 2, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x702a, 0x0018, 0x702a, + EVR_LO, "DetectorManufacturerName", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x702b, 0x0018, 0x702b, + EVR_LO, "DetectorManufacturerModelName", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x7030, 0x0018, 0x7030, + EVR_DS, "FieldOfViewOrigin", 2, 2, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x7032, 0x0018, 0x7032, + EVR_DS, "FieldOfViewRotation", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x7034, 0x0018, 0x7034, + EVR_CS, "FieldOfViewHorizontalFlip", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x7036, 0x0018, 0x7036, + EVR_FL, "PixelDataAreaOriginRelativeToFOV", 2, 2, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x7038, 0x0018, 0x7038, + EVR_FL, "PixelDataAreaRotationAngleRelativeToFOV", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x7040, 0x0018, 0x7040, + EVR_LT, "GridAbsorbingMaterial", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x7041, 0x0018, 0x7041, + EVR_LT, "GridSpacingMaterial", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x7042, 0x0018, 0x7042, + EVR_DS, "GridThickness", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x7044, 0x0018, 0x7044, + EVR_DS, "GridPitch", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x7046, 0x0018, 0x7046, + EVR_IS, "GridAspectRatio", 2, 2, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x7048, 0x0018, 0x7048, + EVR_DS, "GridPeriod", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x704c, 0x0018, 0x704c, + EVR_DS, "GridFocalDistance", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x7050, 0x0018, 0x7050, + EVR_CS, "FilterMaterial", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x7052, 0x0018, 0x7052, + EVR_DS, "FilterThicknessMinimum", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x7054, 0x0018, 0x7054, + EVR_DS, "FilterThicknessMaximum", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x7056, 0x0018, 0x7056, + EVR_FL, "FilterBeamPathLengthMinimum", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x7058, 0x0018, 0x7058, + EVR_FL, "FilterBeamPathLengthMaximum", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x7060, 0x0018, 0x7060, + EVR_CS, "ExposureControlMode", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x7062, 0x0018, 0x7062, + EVR_LT, "ExposureControlModeDescription", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x7064, 0x0018, 0x7064, + EVR_CS, "ExposureStatus", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x7065, 0x0018, 0x7065, + EVR_DS, "PhototimerSetting", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x8150, 0x0018, 0x8150, + EVR_DS, "ExposureTimeInuS", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x8151, 0x0018, 0x8151, + EVR_DS, "XRayTubeCurrentInuA", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9004, 0x0018, 0x9004, + EVR_CS, "ContentQualification", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9005, 0x0018, 0x9005, + EVR_SH, "PulseSequenceName", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9006, 0x0018, 0x9006, + EVR_SQ, "MRImagingModifierSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9008, 0x0018, 0x9008, + EVR_CS, "EchoPulseSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9009, 0x0018, 0x9009, + EVR_CS, "InversionRecovery", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9010, 0x0018, 0x9010, + EVR_CS, "FlowCompensation", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9011, 0x0018, 0x9011, + EVR_CS, "MultipleSpinEcho", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9012, 0x0018, 0x9012, + EVR_CS, "MultiPlanarExcitation", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9014, 0x0018, 0x9014, + EVR_CS, "PhaseContrast", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9015, 0x0018, 0x9015, + EVR_CS, "TimeOfFlightContrast", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9016, 0x0018, 0x9016, + EVR_CS, "Spoiling", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9017, 0x0018, 0x9017, + EVR_CS, "SteadyStatePulseSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9018, 0x0018, 0x9018, + EVR_CS, "EchoPlanarPulseSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9019, 0x0018, 0x9019, + EVR_FD, "TagAngleFirstAxis", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9020, 0x0018, 0x9020, + EVR_CS, "MagnetizationTransfer", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9021, 0x0018, 0x9021, + EVR_CS, "T2Preparation", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9022, 0x0018, 0x9022, + EVR_CS, "BloodSignalNulling", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9024, 0x0018, 0x9024, + EVR_CS, "SaturationRecovery", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9025, 0x0018, 0x9025, + EVR_CS, "SpectrallySelectedSuppression", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9026, 0x0018, 0x9026, + EVR_CS, "SpectrallySelectedExcitation", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9027, 0x0018, 0x9027, + EVR_CS, "SpatialPresaturation", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9028, 0x0018, 0x9028, + EVR_CS, "Tagging", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9029, 0x0018, 0x9029, + EVR_CS, "OversamplingPhase", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9030, 0x0018, 0x9030, + EVR_FD, "TagSpacingFirstDimension", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9032, 0x0018, 0x9032, + EVR_CS, "GeometryOfKSpaceTraversal", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9033, 0x0018, 0x9033, + EVR_CS, "SegmentedKSpaceTraversal", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9034, 0x0018, 0x9034, + EVR_CS, "RectilinearPhaseEncodeReordering", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9035, 0x0018, 0x9035, + EVR_FD, "TagThickness", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9036, 0x0018, 0x9036, + EVR_CS, "PartialFourierDirection", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9037, 0x0018, 0x9037, + EVR_CS, "CardiacSynchronizationTechnique", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9041, 0x0018, 0x9041, + EVR_LO, "ReceiveCoilManufacturerName", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9042, 0x0018, 0x9042, + EVR_SQ, "MRReceiveCoilSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9043, 0x0018, 0x9043, + EVR_CS, "ReceiveCoilType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9044, 0x0018, 0x9044, + EVR_CS, "QuadratureReceiveCoil", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9045, 0x0018, 0x9045, + EVR_SQ, "MultiCoilDefinitionSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9046, 0x0018, 0x9046, + EVR_LO, "MultiCoilConfiguration", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9047, 0x0018, 0x9047, + EVR_SH, "MultiCoilElementName", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9048, 0x0018, 0x9048, + EVR_CS, "MultiCoilElementUsed", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9049, 0x0018, 0x9049, + EVR_SQ, "MRTransmitCoilSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9050, 0x0018, 0x9050, + EVR_LO, "TransmitCoilManufacturerName", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9051, 0x0018, 0x9051, + EVR_CS, "TransmitCoilType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9052, 0x0018, 0x9052, + EVR_FD, "SpectralWidth", 1, 2, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9053, 0x0018, 0x9053, + EVR_FD, "ChemicalShiftReference", 1, 2, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9054, 0x0018, 0x9054, + EVR_CS, "VolumeLocalizationTechnique", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9058, 0x0018, 0x9058, + EVR_US, "MRAcquisitionFrequencyEncodingSteps", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9059, 0x0018, 0x9059, + EVR_CS, "Decoupling", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9060, 0x0018, 0x9060, + EVR_CS, "DecoupledNucleus", 1, 2, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9061, 0x0018, 0x9061, + EVR_FD, "DecouplingFrequency", 1, 2, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9062, 0x0018, 0x9062, + EVR_CS, "DecouplingMethod", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9063, 0x0018, 0x9063, + EVR_FD, "DecouplingChemicalShiftReference", 1, 2, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9064, 0x0018, 0x9064, + EVR_CS, "KSpaceFiltering", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9065, 0x0018, 0x9065, + EVR_CS, "TimeDomainFiltering", 1, 2, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9066, 0x0018, 0x9066, + EVR_US, "NumberOfZeroFills", 1, 2, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9067, 0x0018, 0x9067, + EVR_CS, "BaselineCorrection", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9069, 0x0018, 0x9069, + EVR_FD, "ParallelReductionFactorInPlane", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9070, 0x0018, 0x9070, + EVR_FD, "CardiacRRIntervalSpecified", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9073, 0x0018, 0x9073, + EVR_FD, "AcquisitionDuration", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9074, 0x0018, 0x9074, + EVR_DT, "FrameAcquisitionDateTime", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9075, 0x0018, 0x9075, + EVR_CS, "DiffusionDirectionality", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9076, 0x0018, 0x9076, + EVR_SQ, "DiffusionGradientDirectionSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9077, 0x0018, 0x9077, + EVR_CS, "ParallelAcquisition", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9078, 0x0018, 0x9078, + EVR_CS, "ParallelAcquisitionTechnique", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9079, 0x0018, 0x9079, + EVR_FD, "InversionTimes", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9080, 0x0018, 0x9080, + EVR_ST, "MetaboliteMapDescription", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9081, 0x0018, 0x9081, + EVR_CS, "PartialFourier", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9082, 0x0018, 0x9082, + EVR_FD, "EffectiveEchoTime", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9083, 0x0018, 0x9083, + EVR_SQ, "MetaboliteMapCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9084, 0x0018, 0x9084, + EVR_SQ, "ChemicalShiftSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9085, 0x0018, 0x9085, + EVR_CS, "CardiacSignalSource", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9087, 0x0018, 0x9087, + EVR_FD, "DiffusionBValue", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9089, 0x0018, 0x9089, + EVR_FD, "DiffusionGradientOrientation", 3, 3, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9090, 0x0018, 0x9090, + EVR_FD, "VelocityEncodingDirection", 3, 3, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9091, 0x0018, 0x9091, + EVR_FD, "VelocityEncodingMinimumValue", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9092, 0x0018, 0x9092, + EVR_SQ, "VelocityEncodingAcquisitionSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9093, 0x0018, 0x9093, + EVR_US, "NumberOfKSpaceTrajectories", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9094, 0x0018, 0x9094, + EVR_CS, "CoverageOfKSpace", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9095, 0x0018, 0x9095, + EVR_UL, "SpectroscopyAcquisitionPhaseRows", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9096, 0x0018, 0x9096, + EVR_FD, "RETIRED_ParallelReductionFactorInPlaneRetired", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9098, 0x0018, 0x9098, + EVR_FD, "TransmitterFrequency", 1, 2, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9100, 0x0018, 0x9100, + EVR_CS, "ResonantNucleus", 1, 2, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9101, 0x0018, 0x9101, + EVR_CS, "FrequencyCorrection", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9103, 0x0018, 0x9103, + EVR_SQ, "MRSpectroscopyFOVGeometrySequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9104, 0x0018, 0x9104, + EVR_FD, "SlabThickness", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9105, 0x0018, 0x9105, + EVR_FD, "SlabOrientation", 3, 3, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9106, 0x0018, 0x9106, + EVR_FD, "MidSlabPosition", 3, 3, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9107, 0x0018, 0x9107, + EVR_SQ, "MRSpatialSaturationSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9112, 0x0018, 0x9112, + EVR_SQ, "MRTimingAndRelatedParametersSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9114, 0x0018, 0x9114, + EVR_SQ, "MREchoSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9115, 0x0018, 0x9115, + EVR_SQ, "MRModifierSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9117, 0x0018, 0x9117, + EVR_SQ, "MRDiffusionSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9118, 0x0018, 0x9118, + EVR_SQ, "CardiacSynchronizationSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9119, 0x0018, 0x9119, + EVR_SQ, "MRAveragesSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9125, 0x0018, 0x9125, + EVR_SQ, "MRFOVGeometrySequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9126, 0x0018, 0x9126, + EVR_SQ, "VolumeLocalizationSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9127, 0x0018, 0x9127, + EVR_UL, "SpectroscopyAcquisitionDataColumns", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9147, 0x0018, 0x9147, + EVR_CS, "DiffusionAnisotropyType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9151, 0x0018, 0x9151, + EVR_DT, "FrameReferenceDateTime", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9152, 0x0018, 0x9152, + EVR_SQ, "MRMetaboliteMapSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9155, 0x0018, 0x9155, + EVR_FD, "ParallelReductionFactorOutOfPlane", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9159, 0x0018, 0x9159, + EVR_UL, "SpectroscopyAcquisitionOutOfPlanePhaseSteps", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9166, 0x0018, 0x9166, + EVR_CS, "RETIRED_BulkMotionStatus", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9168, 0x0018, 0x9168, + EVR_FD, "ParallelReductionFactorSecondInPlane", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9169, 0x0018, 0x9169, + EVR_CS, "CardiacBeatRejectionTechnique", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9170, 0x0018, 0x9170, + EVR_CS, "RespiratoryMotionCompensationTechnique", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9171, 0x0018, 0x9171, + EVR_CS, "RespiratorySignalSource", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9172, 0x0018, 0x9172, + EVR_CS, "BulkMotionCompensationTechnique", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9173, 0x0018, 0x9173, + EVR_CS, "BulkMotionSignalSource", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9174, 0x0018, 0x9174, + EVR_CS, "ApplicableSafetyStandardAgency", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9175, 0x0018, 0x9175, + EVR_LO, "ApplicableSafetyStandardDescription", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9176, 0x0018, 0x9176, + EVR_SQ, "OperatingModeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9177, 0x0018, 0x9177, + EVR_CS, "OperatingModeType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9178, 0x0018, 0x9178, + EVR_CS, "OperatingMode", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9179, 0x0018, 0x9179, + EVR_CS, "SpecificAbsorptionRateDefinition", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9180, 0x0018, 0x9180, + EVR_CS, "GradientOutputType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9181, 0x0018, 0x9181, + EVR_FD, "SpecificAbsorptionRateValue", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9182, 0x0018, 0x9182, + EVR_FD, "GradientOutput", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9183, 0x0018, 0x9183, + EVR_CS, "FlowCompensationDirection", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9184, 0x0018, 0x9184, + EVR_FD, "TaggingDelay", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9185, 0x0018, 0x9185, + EVR_ST, "RespiratoryMotionCompensationTechniqueDescription", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9186, 0x0018, 0x9186, + EVR_SH, "RespiratorySignalSourceID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9195, 0x0018, 0x9195, + EVR_FD, "RETIRED_ChemicalShiftMinimumIntegrationLimitInHz", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9196, 0x0018, 0x9196, + EVR_FD, "RETIRED_ChemicalShiftMaximumIntegrationLimitInHz", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9197, 0x0018, 0x9197, + EVR_SQ, "MRVelocityEncodingSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9198, 0x0018, 0x9198, + EVR_CS, "FirstOrderPhaseCorrection", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9199, 0x0018, 0x9199, + EVR_CS, "WaterReferencedPhaseCorrection", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9200, 0x0018, 0x9200, + EVR_CS, "MRSpectroscopyAcquisitionType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9214, 0x0018, 0x9214, + EVR_CS, "RespiratoryCyclePosition", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9217, 0x0018, 0x9217, + EVR_FD, "VelocityEncodingMaximumValue", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9218, 0x0018, 0x9218, + EVR_FD, "TagSpacingSecondDimension", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9219, 0x0018, 0x9219, + EVR_SS, "TagAngleSecondAxis", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9220, 0x0018, 0x9220, + EVR_FD, "FrameAcquisitionDuration", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9226, 0x0018, 0x9226, + EVR_SQ, "MRImageFrameTypeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9227, 0x0018, 0x9227, + EVR_SQ, "MRSpectroscopyFrameTypeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9231, 0x0018, 0x9231, + EVR_US, "MRAcquisitionPhaseEncodingStepsInPlane", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9232, 0x0018, 0x9232, + EVR_US, "MRAcquisitionPhaseEncodingStepsOutOfPlane", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9234, 0x0018, 0x9234, + EVR_UL, "SpectroscopyAcquisitionPhaseColumns", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9236, 0x0018, 0x9236, + EVR_CS, "CardiacCyclePosition", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9239, 0x0018, 0x9239, + EVR_SQ, "SpecificAbsorptionRateSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9240, 0x0018, 0x9240, + EVR_US, "RFEchoTrainLength", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9241, 0x0018, 0x9241, + EVR_US, "GradientEchoTrainLength", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9250, 0x0018, 0x9250, + EVR_CS, "ArterialSpinLabelingContrast", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9251, 0x0018, 0x9251, + EVR_SQ, "MRArterialSpinLabelingSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9252, 0x0018, 0x9252, + EVR_LO, "ASLTechniqueDescription", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9253, 0x0018, 0x9253, + EVR_US, "ASLSlabNumber", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9254, 0x0018, 0x9254, + EVR_FD, "ASLSlabThickness", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9255, 0x0018, 0x9255, + EVR_FD, "ASLSlabOrientation", 3, 3, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9256, 0x0018, 0x9256, + EVR_FD, "ASLMidSlabPosition", 3, 3, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9257, 0x0018, 0x9257, + EVR_CS, "ASLContext", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9258, 0x0018, 0x9258, + EVR_UL, "ASLPulseTrainDuration", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9259, 0x0018, 0x9259, + EVR_CS, "ASLCrusherFlag", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x925a, 0x0018, 0x925a, + EVR_FD, "ASLCrusherFlowLimit", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x925b, 0x0018, 0x925b, + EVR_LO, "ASLCrusherDescription", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x925c, 0x0018, 0x925c, + EVR_CS, "ASLBolusCutoffFlag", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x925d, 0x0018, 0x925d, + EVR_SQ, "ASLBolusCutoffTimingSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x925e, 0x0018, 0x925e, + EVR_LO, "ASLBolusCutoffTechnique", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x925f, 0x0018, 0x925f, + EVR_UL, "ASLBolusCutoffDelayTime", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9260, 0x0018, 0x9260, + EVR_SQ, "ASLSlabSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9295, 0x0018, 0x9295, + EVR_FD, "ChemicalShiftMinimumIntegrationLimitInppm", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9296, 0x0018, 0x9296, + EVR_FD, "ChemicalShiftMaximumIntegrationLimitInppm", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9297, 0x0018, 0x9297, + EVR_CS, "WaterReferenceAcquisition", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9298, 0x0018, 0x9298, + EVR_IS, "EchoPeakPosition", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9301, 0x0018, 0x9301, + EVR_SQ, "CTAcquisitionTypeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9302, 0x0018, 0x9302, + EVR_CS, "AcquisitionType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9303, 0x0018, 0x9303, + EVR_FD, "TubeAngle", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9304, 0x0018, 0x9304, + EVR_SQ, "CTAcquisitionDetailsSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9305, 0x0018, 0x9305, + EVR_FD, "RevolutionTime", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9306, 0x0018, 0x9306, + EVR_FD, "SingleCollimationWidth", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9307, 0x0018, 0x9307, + EVR_FD, "TotalCollimationWidth", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9308, 0x0018, 0x9308, + EVR_SQ, "CTTableDynamicsSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9309, 0x0018, 0x9309, + EVR_FD, "TableSpeed", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9310, 0x0018, 0x9310, + EVR_FD, "TableFeedPerRotation", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9311, 0x0018, 0x9311, + EVR_FD, "SpiralPitchFactor", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9312, 0x0018, 0x9312, + EVR_SQ, "CTGeometrySequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9313, 0x0018, 0x9313, + EVR_FD, "DataCollectionCenterPatient", 3, 3, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9314, 0x0018, 0x9314, + EVR_SQ, "CTReconstructionSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9315, 0x0018, 0x9315, + EVR_CS, "ReconstructionAlgorithm", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9316, 0x0018, 0x9316, + EVR_CS, "ConvolutionKernelGroup", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9317, 0x0018, 0x9317, + EVR_FD, "ReconstructionFieldOfView", 2, 2, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9318, 0x0018, 0x9318, + EVR_FD, "ReconstructionTargetCenterPatient", 3, 3, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9319, 0x0018, 0x9319, + EVR_FD, "ReconstructionAngle", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9320, 0x0018, 0x9320, + EVR_SH, "ImageFilter", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9321, 0x0018, 0x9321, + EVR_SQ, "CTExposureSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9322, 0x0018, 0x9322, + EVR_FD, "ReconstructionPixelSpacing", 2, 2, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9323, 0x0018, 0x9323, + EVR_CS, "ExposureModulationType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9324, 0x0018, 0x9324, + EVR_FD, "EstimatedDoseSaving", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9325, 0x0018, 0x9325, + EVR_SQ, "CTXRayDetailsSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9326, 0x0018, 0x9326, + EVR_SQ, "CTPositionSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9327, 0x0018, 0x9327, + EVR_FD, "TablePosition", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9328, 0x0018, 0x9328, + EVR_FD, "ExposureTimeInms", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9329, 0x0018, 0x9329, + EVR_SQ, "CTImageFrameTypeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9330, 0x0018, 0x9330, + EVR_FD, "XRayTubeCurrentInmA", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9332, 0x0018, 0x9332, + EVR_FD, "ExposureInmAs", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9333, 0x0018, 0x9333, + EVR_CS, "ConstantVolumeFlag", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9334, 0x0018, 0x9334, + EVR_CS, "FluoroscopyFlag", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9335, 0x0018, 0x9335, + EVR_FD, "DistanceSourceToDataCollectionCenter", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9337, 0x0018, 0x9337, + EVR_US, "ContrastBolusAgentNumber", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9338, 0x0018, 0x9338, + EVR_SQ, "ContrastBolusIngredientCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9340, 0x0018, 0x9340, + EVR_SQ, "ContrastAdministrationProfileSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9341, 0x0018, 0x9341, + EVR_SQ, "ContrastBolusUsageSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9342, 0x0018, 0x9342, + EVR_CS, "ContrastBolusAgentAdministered", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9343, 0x0018, 0x9343, + EVR_CS, "ContrastBolusAgentDetected", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9344, 0x0018, 0x9344, + EVR_CS, "ContrastBolusAgentPhase", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9345, 0x0018, 0x9345, + EVR_FD, "CTDIvol", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9346, 0x0018, 0x9346, + EVR_SQ, "CTDIPhantomTypeCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9351, 0x0018, 0x9351, + EVR_FL, "CalciumScoringMassFactorPatient", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9352, 0x0018, 0x9352, + EVR_FL, "CalciumScoringMassFactorDevice", 3, 3, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9353, 0x0018, 0x9353, + EVR_FL, "EnergyWeightingFactor", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9360, 0x0018, 0x9360, + EVR_SQ, "CTAdditionalXRaySourceSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9401, 0x0018, 0x9401, + EVR_SQ, "ProjectionPixelCalibrationSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9402, 0x0018, 0x9402, + EVR_FL, "DistanceSourceToIsocenter", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9403, 0x0018, 0x9403, + EVR_FL, "DistanceObjectToTableTop", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9404, 0x0018, 0x9404, + EVR_FL, "ObjectPixelSpacingInCenterOfBeam", 2, 2, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9405, 0x0018, 0x9405, + EVR_SQ, "PositionerPositionSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9406, 0x0018, 0x9406, + EVR_SQ, "TablePositionSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9407, 0x0018, 0x9407, + EVR_SQ, "CollimatorShapeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9410, 0x0018, 0x9410, + EVR_CS, "PlanesInAcquisition", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9412, 0x0018, 0x9412, + EVR_SQ, "XAXRFFrameCharacteristicsSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9417, 0x0018, 0x9417, + EVR_SQ, "FrameAcquisitionSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9420, 0x0018, 0x9420, + EVR_CS, "XRayReceptorType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9423, 0x0018, 0x9423, + EVR_LO, "AcquisitionProtocolName", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9424, 0x0018, 0x9424, + EVR_LT, "AcquisitionProtocolDescription", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9425, 0x0018, 0x9425, + EVR_CS, "ContrastBolusIngredientOpaque", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9426, 0x0018, 0x9426, + EVR_FL, "DistanceReceptorPlaneToDetectorHousing", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9427, 0x0018, 0x9427, + EVR_CS, "IntensifierActiveShape", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9428, 0x0018, 0x9428, + EVR_FL, "IntensifierActiveDimensions", 1, 2, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9429, 0x0018, 0x9429, + EVR_FL, "PhysicalDetectorSize", 2, 2, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9430, 0x0018, 0x9430, + EVR_FL, "PositionOfIsocenterProjection", 2, 2, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9432, 0x0018, 0x9432, + EVR_SQ, "FieldOfViewSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9433, 0x0018, 0x9433, + EVR_LO, "FieldOfViewDescription", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9434, 0x0018, 0x9434, + EVR_SQ, "ExposureControlSensingRegionsSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9435, 0x0018, 0x9435, + EVR_CS, "ExposureControlSensingRegionShape", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9436, 0x0018, 0x9436, + EVR_SS, "ExposureControlSensingRegionLeftVerticalEdge", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9437, 0x0018, 0x9437, + EVR_SS, "ExposureControlSensingRegionRightVerticalEdge", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9438, 0x0018, 0x9438, + EVR_SS, "ExposureControlSensingRegionUpperHorizontalEdge", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9439, 0x0018, 0x9439, + EVR_SS, "ExposureControlSensingRegionLowerHorizontalEdge", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9440, 0x0018, 0x9440, + EVR_SS, "CenterOfCircularExposureControlSensingRegion", 2, 2, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9441, 0x0018, 0x9441, + EVR_US, "RadiusOfCircularExposureControlSensingRegion", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9442, 0x0018, 0x9442, + EVR_SS, "VerticesOfThePolygonalExposureControlSensingRegion", 2, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9447, 0x0018, 0x9447, + EVR_FL, "ColumnAngulationPatient", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9449, 0x0018, 0x9449, + EVR_FL, "BeamAngle", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9451, 0x0018, 0x9451, + EVR_SQ, "FrameDetectorParametersSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9452, 0x0018, 0x9452, + EVR_FL, "CalculatedAnatomyThickness", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9455, 0x0018, 0x9455, + EVR_SQ, "CalibrationSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9456, 0x0018, 0x9456, + EVR_SQ, "ObjectThicknessSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9457, 0x0018, 0x9457, + EVR_CS, "PlaneIdentification", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9461, 0x0018, 0x9461, + EVR_FL, "FieldOfViewDimensionsInFloat", 1, 2, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9462, 0x0018, 0x9462, + EVR_SQ, "IsocenterReferenceSystemSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9463, 0x0018, 0x9463, + EVR_FL, "PositionerIsocenterPrimaryAngle", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9464, 0x0018, 0x9464, + EVR_FL, "PositionerIsocenterSecondaryAngle", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9465, 0x0018, 0x9465, + EVR_FL, "PositionerIsocenterDetectorRotationAngle", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9466, 0x0018, 0x9466, + EVR_FL, "TableXPositionToIsocenter", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9467, 0x0018, 0x9467, + EVR_FL, "TableYPositionToIsocenter", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9468, 0x0018, 0x9468, + EVR_FL, "TableZPositionToIsocenter", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9469, 0x0018, 0x9469, + EVR_FL, "TableHorizontalRotationAngle", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9470, 0x0018, 0x9470, + EVR_FL, "TableHeadTiltAngle", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9471, 0x0018, 0x9471, + EVR_FL, "TableCradleTiltAngle", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9472, 0x0018, 0x9472, + EVR_SQ, "FrameDisplayShutterSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9473, 0x0018, 0x9473, + EVR_FL, "AcquiredImageAreaDoseProduct", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9474, 0x0018, 0x9474, + EVR_CS, "CArmPositionerTabletopRelationship", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9476, 0x0018, 0x9476, + EVR_SQ, "XRayGeometrySequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9477, 0x0018, 0x9477, + EVR_SQ, "IrradiationEventIdentificationSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9504, 0x0018, 0x9504, + EVR_SQ, "XRay3DFrameTypeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9506, 0x0018, 0x9506, + EVR_SQ, "ContributingSourcesSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9507, 0x0018, 0x9507, + EVR_SQ, "XRay3DAcquisitionSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9508, 0x0018, 0x9508, + EVR_FL, "PrimaryPositionerScanArc", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9509, 0x0018, 0x9509, + EVR_FL, "SecondaryPositionerScanArc", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9510, 0x0018, 0x9510, + EVR_FL, "PrimaryPositionerScanStartAngle", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9511, 0x0018, 0x9511, + EVR_FL, "SecondaryPositionerScanStartAngle", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9514, 0x0018, 0x9514, + EVR_FL, "PrimaryPositionerIncrement", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9515, 0x0018, 0x9515, + EVR_FL, "SecondaryPositionerIncrement", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9516, 0x0018, 0x9516, + EVR_DT, "StartAcquisitionDateTime", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9517, 0x0018, 0x9517, + EVR_DT, "EndAcquisitionDateTime", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9518, 0x0018, 0x9518, + EVR_SS, "PrimaryPositionerIncrementSign", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9519, 0x0018, 0x9519, + EVR_SS, "SecondaryPositionerIncrementSign", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9524, 0x0018, 0x9524, + EVR_LO, "ApplicationName", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9525, 0x0018, 0x9525, + EVR_LO, "ApplicationVersion", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9526, 0x0018, 0x9526, + EVR_LO, "ApplicationManufacturer", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9527, 0x0018, 0x9527, + EVR_CS, "AlgorithmType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9528, 0x0018, 0x9528, + EVR_LO, "AlgorithmDescription", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9530, 0x0018, 0x9530, + EVR_SQ, "XRay3DReconstructionSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9531, 0x0018, 0x9531, + EVR_LO, "ReconstructionDescription", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9538, 0x0018, 0x9538, + EVR_SQ, "PerProjectionAcquisitionSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9541, 0x0018, 0x9541, + EVR_SQ, "DetectorPositionSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9542, 0x0018, 0x9542, + EVR_SQ, "XRayAcquisitionDoseSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9543, 0x0018, 0x9543, + EVR_FD, "XRaySourceIsocenterPrimaryAngle", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9544, 0x0018, 0x9544, + EVR_FD, "XRaySourceIsocenterSecondaryAngle", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9545, 0x0018, 0x9545, + EVR_FD, "BreastSupportIsocenterPrimaryAngle", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9546, 0x0018, 0x9546, + EVR_FD, "BreastSupportIsocenterSecondaryAngle", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9547, 0x0018, 0x9547, + EVR_FD, "BreastSupportXPositionToIsocenter", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9548, 0x0018, 0x9548, + EVR_FD, "BreastSupportYPositionToIsocenter", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9549, 0x0018, 0x9549, + EVR_FD, "BreastSupportZPositionToIsocenter", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9550, 0x0018, 0x9550, + EVR_FD, "DetectorIsocenterPrimaryAngle", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9551, 0x0018, 0x9551, + EVR_FD, "DetectorIsocenterSecondaryAngle", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9552, 0x0018, 0x9552, + EVR_FD, "DetectorXPositionToIsocenter", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9553, 0x0018, 0x9553, + EVR_FD, "DetectorYPositionToIsocenter", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9554, 0x0018, 0x9554, + EVR_FD, "DetectorZPositionToIsocenter", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9555, 0x0018, 0x9555, + EVR_SQ, "XRayGridSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9556, 0x0018, 0x9556, + EVR_SQ, "XRayFilterSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9557, 0x0018, 0x9557, + EVR_FD, "DetectorActiveAreaTLHCPosition", 3, 3, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9558, 0x0018, 0x9558, + EVR_FD, "DetectorActiveAreaOrientation", 6, 6, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9559, 0x0018, 0x9559, + EVR_CS, "PositionerPrimaryAngleDirection", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9601, 0x0018, 0x9601, + EVR_SQ, "DiffusionBMatrixSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9602, 0x0018, 0x9602, + EVR_FD, "DiffusionBValueXX", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9603, 0x0018, 0x9603, + EVR_FD, "DiffusionBValueXY", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9604, 0x0018, 0x9604, + EVR_FD, "DiffusionBValueXZ", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9605, 0x0018, 0x9605, + EVR_FD, "DiffusionBValueYY", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9606, 0x0018, 0x9606, + EVR_FD, "DiffusionBValueYZ", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9607, 0x0018, 0x9607, + EVR_FD, "DiffusionBValueZZ", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9701, 0x0018, 0x9701, + EVR_DT, "DecayCorrectionDateTime", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9715, 0x0018, 0x9715, + EVR_FD, "StartDensityThreshold", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9716, 0x0018, 0x9716, + EVR_FD, "StartRelativeDensityDifferenceThreshold", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9717, 0x0018, 0x9717, + EVR_FD, "StartCardiacTriggerCountThreshold", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9718, 0x0018, 0x9718, + EVR_FD, "StartRespiratoryTriggerCountThreshold", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9719, 0x0018, 0x9719, + EVR_FD, "TerminationCountsThreshold", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9720, 0x0018, 0x9720, + EVR_FD, "TerminationDensityThreshold", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9721, 0x0018, 0x9721, + EVR_FD, "TerminationRelativeDensityThreshold", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9722, 0x0018, 0x9722, + EVR_FD, "TerminationTimeThreshold", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9723, 0x0018, 0x9723, + EVR_FD, "TerminationCardiacTriggerCountThreshold", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9724, 0x0018, 0x9724, + EVR_FD, "TerminationRespiratoryTriggerCountThreshold", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9725, 0x0018, 0x9725, + EVR_CS, "DetectorGeometry", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9726, 0x0018, 0x9726, + EVR_FD, "TransverseDetectorSeparation", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9727, 0x0018, 0x9727, + EVR_FD, "AxialDetectorDimension", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9729, 0x0018, 0x9729, + EVR_US, "RadiopharmaceuticalAgentNumber", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9732, 0x0018, 0x9732, + EVR_SQ, "PETFrameAcquisitionSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9733, 0x0018, 0x9733, + EVR_SQ, "PETDetectorMotionDetailsSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9734, 0x0018, 0x9734, + EVR_SQ, "PETTableDynamicsSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9735, 0x0018, 0x9735, + EVR_SQ, "PETPositionSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9736, 0x0018, 0x9736, + EVR_SQ, "PETFrameCorrectionFactorsSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9737, 0x0018, 0x9737, + EVR_SQ, "RadiopharmaceuticalUsageSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9738, 0x0018, 0x9738, + EVR_CS, "AttenuationCorrectionSource", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9739, 0x0018, 0x9739, + EVR_US, "NumberOfIterations", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9740, 0x0018, 0x9740, + EVR_US, "NumberOfSubsets", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9749, 0x0018, 0x9749, + EVR_SQ, "PETReconstructionSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9751, 0x0018, 0x9751, + EVR_SQ, "PETFrameTypeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9755, 0x0018, 0x9755, + EVR_CS, "TimeOfFlightInformationUsed", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9756, 0x0018, 0x9756, + EVR_CS, "ReconstructionType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9758, 0x0018, 0x9758, + EVR_CS, "DecayCorrected", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9759, 0x0018, 0x9759, + EVR_CS, "AttenuationCorrected", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9760, 0x0018, 0x9760, + EVR_CS, "ScatterCorrected", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9761, 0x0018, 0x9761, + EVR_CS, "DeadTimeCorrected", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9762, 0x0018, 0x9762, + EVR_CS, "GantryMotionCorrected", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9763, 0x0018, 0x9763, + EVR_CS, "PatientMotionCorrected", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9764, 0x0018, 0x9764, + EVR_CS, "CountLossNormalizationCorrected", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9765, 0x0018, 0x9765, + EVR_CS, "RandomsCorrected", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9766, 0x0018, 0x9766, + EVR_CS, "NonUniformRadialSamplingCorrected", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9767, 0x0018, 0x9767, + EVR_CS, "SensitivityCalibrated", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9768, 0x0018, 0x9768, + EVR_CS, "DetectorNormalizationCorrection", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9769, 0x0018, 0x9769, + EVR_CS, "IterativeReconstructionMethod", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9770, 0x0018, 0x9770, + EVR_CS, "AttenuationCorrectionTemporalRelationship", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9771, 0x0018, 0x9771, + EVR_SQ, "PatientPhysiologicalStateSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9772, 0x0018, 0x9772, + EVR_SQ, "PatientPhysiologicalStateCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9801, 0x0018, 0x9801, + EVR_FD, "DepthsOfFocus", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9803, 0x0018, 0x9803, + EVR_SQ, "ExcludedIntervalsSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9804, 0x0018, 0x9804, + EVR_DT, "ExclusionStartDateTime", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9805, 0x0018, 0x9805, + EVR_FD, "ExclusionDuration", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9806, 0x0018, 0x9806, + EVR_SQ, "USImageDescriptionSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9807, 0x0018, 0x9807, + EVR_SQ, "ImageDataTypeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9808, 0x0018, 0x9808, + EVR_CS, "DataType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9809, 0x0018, 0x9809, + EVR_SQ, "TransducerScanPatternCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x980b, 0x0018, 0x980b, + EVR_CS, "AliasedDataType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x980c, 0x0018, 0x980c, + EVR_CS, "PositionMeasuringDeviceUsed", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x980d, 0x0018, 0x980d, + EVR_SQ, "TransducerGeometryCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x980e, 0x0018, 0x980e, + EVR_SQ, "TransducerBeamSteeringCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x980f, 0x0018, 0x980f, + EVR_SQ, "TransducerApplicationCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0x9810, 0x0018, 0x9810, + EVR_xs, "ZeroVelocityPixelValue", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0xa001, 0x0018, 0xa001, + EVR_SQ, "ContributingEquipmentSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0xa002, 0x0018, 0xa002, + EVR_DT, "ContributionDateTime", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0018, 0xa003, 0x0018, 0xa003, + EVR_ST, "ContributionDescription", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } +#ifdef ENABLE_PRIVATE_TAGS + , { 0x0019, 0x0000, 0x0019, 0x0000, + EVR_CS, "ImageBlankingShape", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "CARDIO-D.R. 1.0" } + , { 0x0019, 0x0000, 0x0019, 0x0000, + EVR_UN, "PhysiologicalDataType", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1;1" } + , { 0x0019, 0x0000, 0x0019, 0x0000, + EVR_US, "Unknown", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "AEGIS_DICOM_2.00" } + , { 0x0019, 0x0000, 0x0019, 0x0000, + EVR_UN, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1" } + , { 0x0019, 0x0000, 0x0019, 0x0000, + EVR_IS, "AECField", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SVISION" } + , { 0x0019, 0x0000, 0x0019, 0x0000, + EVR_LO, "APRName", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "INTEGRIS 1.0" } + , { 0x0019, 0x0000, 0x0019, 0x0000, + EVR_US, "ReviewMode", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS SMS-AX VIEW 1.0" } + , { 0x0019, 0x0001, 0x0019, 0x0001, + EVR_DS, "AngleValueLArm", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "DLX_SERIE_01" } + , { 0x0019, 0x0001, 0x0019, 0x0001, + EVR_UN, "PhysiologicalDataChannelAndKind", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1;1" } + , { 0x0019, 0x0001, 0x0019, 0x0001, + EVR_LT, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x0001, 0x0019, 0x0001, + EVR_UN, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1" } + , { 0x0019, 0x0001, 0x0019, 0x0001, + EVR_IS, "AECFilmScreen", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SVISION" } + , { 0x0019, 0x0001, 0x0019, 0x0001, + EVR_US, "AnatomicalBackgroundPercent", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS SMS-AX VIEW 1.0" } + , { 0x0019, 0x0001, 0x0019, 0x0001, + EVR_US, "Unknown", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "TOSHIBA_MEC_1.0" } + , { 0x0019, 0x0001, 0x0019, 0x0001, + EVR_IS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "TOSHIBA_MEC_CT_1.0" } + , { 0x0019, 0x0001, 0x0019, 0x0001, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR SPECTRO;1" } + , { 0x0019, 0x0002, 0x0019, 0x0002, + EVR_DS, "AngleValuePArm", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "DLX_SERIE_01" } + , { 0x0019, 0x0002, 0x0019, 0x0002, + EVR_IS, "ImageBlankingLeftVerticalEdge", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "CARDIO-D.R. 1.0" } + , { 0x0019, 0x0002, 0x0019, 0x0002, + EVR_US, "SampleBitsAllocated", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1;1" } + , { 0x0019, 0x0002, 0x0019, 0x0002, + EVR_SL, "NumberOfCellsInDetector", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x0002, 0x0019, 0x0002, + EVR_UN, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1" } + , { 0x0019, 0x0002, 0x0019, 0x0002, + EVR_IS, "AECDensity", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SVISION" } + , { 0x0019, 0x0002, 0x0019, 0x0002, + EVR_US, "NumberOfPhases", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS SMS-AX VIEW 1.0" } + , { 0x0019, 0x0002, 0x0019, 0x0002, + EVR_US, "Unknown", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "TOSHIBA_MEC_1.0" } + , { 0x0019, 0x0002, 0x0019, 0x0002, + EVR_IS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "TOSHIBA_MEC_CT_1.0" } + , { 0x0019, 0x0002, 0x0019, 0x0002, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR SPECTRO;1" } + , { 0x0019, 0x0003, 0x0019, 0x0003, + EVR_DS, "AngleValueCArm", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "DLX_SERIE_01" } + , { 0x0019, 0x0003, 0x0019, 0x0003, + EVR_US, "SampleBitsStored", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1;1" } + , { 0x0019, 0x0003, 0x0019, 0x0003, + EVR_DS, "CellNumberAtTheta", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x0003, 0x0019, 0x0003, + EVR_US, "ApplyAnatomicalBackground", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS SMS-AX VIEW 1.0" } + , { 0x0019, 0x0003, 0x0019, 0x0003, + EVR_US, "Unknown", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "TOSHIBA_MEC_CT_1.0" } + , { 0x0019, 0x0003, 0x0019, 0x0003, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR SPECTRO;1" } + , { 0x0019, 0x0004, 0x0019, 0x0004, + EVR_CS, "AngleLabelLArm", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "DLX_SERIE_01" } + , { 0x0019, 0x0004, 0x0019, 0x0004, + EVR_IS, "ImageBlankingRightVerticalEdge", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "CARDIO-D.R. 1.0" } + , { 0x0019, 0x0004, 0x0019, 0x0004, + EVR_US, "SampleHighBit", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1;1" } + , { 0x0019, 0x0004, 0x0019, 0x0004, + EVR_DS, "CellSpacing", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x0004, 0x0019, 0x0004, + EVR_SS, "PixelShiftArray", 4, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS SMS-AX VIEW 1.0" } + , { 0x0019, 0x0004, 0x0019, 0x0004, + EVR_LT, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "TOSHIBA_MEC_CT_1.0" } + , { 0x0019, 0x0004, 0x0019, 0x0004, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR SPECTRO;1" } + , { 0x0019, 0x0005, 0x0019, 0x0005, + EVR_CS, "AngleLabelPArm", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "DLX_SERIE_01" } + , { 0x0019, 0x0005, 0x0019, 0x0005, + EVR_US, "SampleRepresentation", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1;1" } + , { 0x0019, 0x0005, 0x0019, 0x0005, + EVR_LT, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x0005, 0x0019, 0x0005, + EVR_US, "Brightness", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS SMS-AX VIEW 1.0" } + , { 0x0019, 0x0005, 0x0019, 0x0005, + EVR_LT, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "TOSHIBA_MEC_CT_1.0" } + , { 0x0019, 0x0005, 0x0019, 0x0005, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR SPECTRO;1" } + , { 0x0019, 0x0006, 0x0019, 0x0006, + EVR_CS, "AngleLabelCArm", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "DLX_SERIE_01" } + , { 0x0019, 0x0006, 0x0019, 0x0006, + EVR_IS, "ImageBlankingUpperHorizontalEdge", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "CARDIO-D.R. 1.0" } + , { 0x0019, 0x0006, 0x0019, 0x0006, + EVR_UN, "SmallestSampleValue", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1;1" } + , { 0x0019, 0x0006, 0x0019, 0x0006, + EVR_UN, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x0006, 0x0019, 0x0006, + EVR_US, "Contrast", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS SMS-AX VIEW 1.0" } + , { 0x0019, 0x0006, 0x0019, 0x0006, + EVR_US, "Unknown", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "TOSHIBA_MEC_CT_1.0" } + , { 0x0019, 0x0006, 0x0019, 0x0006, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR SPECTRO;1" } + , { 0x0019, 0x0007, 0x0019, 0x0007, + EVR_ST, "ProcedureName", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "DLX_SERIE_01" } + , { 0x0019, 0x0007, 0x0019, 0x0007, + EVR_UN, "LargestSampleValue", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1;1" } + , { 0x0019, 0x0007, 0x0019, 0x0007, + EVR_US, "Enabled", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS SMS-AX VIEW 1.0" } + , { 0x0019, 0x0007, 0x0019, 0x0007, + EVR_US, "Unknown", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "TOSHIBA_MEC_CT_1.0" } + , { 0x0019, 0x0007, 0x0019, 0x0007, + EVR_IS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR SPECTRO;1" } + , { 0x0019, 0x0008, 0x0019, 0x0008, + EVR_ST, "ExamName", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "DLX_SERIE_01" } + , { 0x0019, 0x0008, 0x0019, 0x0008, + EVR_IS, "ImageBlankingLowerHorizontalEdge", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "CARDIO-D.R. 1.0" } + , { 0x0019, 0x0008, 0x0019, 0x0008, + EVR_UN, "NumberOfSamples", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1;1" } + , { 0x0019, 0x0008, 0x0019, 0x0008, + EVR_IS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P-GV-CT Release 1" } + , { 0x0019, 0x0008, 0x0019, 0x0008, + EVR_US, "NativeEdgeEnhancementPercentGain", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS SMS-AX VIEW 1.0" } + , { 0x0019, 0x0008, 0x0019, 0x0008, + EVR_LT, "OrientationHeadFeet", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "TOSHIBA_MEC_CT_1.0" } + , { 0x0019, 0x0008, 0x0019, 0x0008, + EVR_IS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR SPECTRO;1" } + , { 0x0019, 0x0009, 0x0019, 0x0009, + EVR_SH, "PatientSize", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "DLX_SERIE_01" } + , { 0x0019, 0x0009, 0x0019, 0x0009, + EVR_DS, "MainMagneticField", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/LAST" } + , { 0x0019, 0x0009, 0x0019, 0x0009, + EVR_UN, "SampleData", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1;1" } + , { 0x0019, 0x0009, 0x0019, 0x0009, + EVR_IS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P-GV-CT Release 1" } + , { 0x0019, 0x0009, 0x0019, 0x0009, + EVR_SS, "NativeEdgeEnhancementLUTIndex", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS SMS-AX VIEW 1.0" } + , { 0x0019, 0x0009, 0x0019, 0x0009, + EVR_LT, "ViewDirection", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "TOSHIBA_MEC_CT_1.0" } + , { 0x0019, 0x0009, 0x0019, 0x0009, + EVR_IS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR SPECTRO;1" } + , { 0x0019, 0x000a, 0x0019, 0x000a, + EVR_IS, "RecordView", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "DLX_SERIE_01" } + , { 0x0019, 0x000a, 0x0019, 0x000a, + EVR_UN, "SampleRate", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1;1" } + , { 0x0019, 0x000a, 0x0019, 0x000a, + EVR_IS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P-GV-CT Release 1" } + , { 0x0019, 0x000a, 0x0019, 0x000a, + EVR_SS, "NativeEdgeEnhancementKernelSize", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS SMS-AX VIEW 1.0" } + , { 0x0019, 0x000a, 0x0019, 0x000a, + EVR_LT, "OrientationSupineProne", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "TOSHIBA_MEC_CT_1.0" } + , { 0x0019, 0x000b, 0x0019, 0x000b, + EVR_US, "SubtrEdgeEnhancementPercentGain", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS SMS-AX VIEW 1.0" } + , { 0x0019, 0x000b, 0x0019, 0x000b, + EVR_DS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "TOSHIBA_MEC_CT_1.0" } + , { 0x0019, 0x000c, 0x0019, 0x000c, + EVR_SS, "SubtrEdgeEnhancementLUTIndex", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS SMS-AX VIEW 1.0" } + , { 0x0019, 0x000c, 0x0019, 0x000c, + EVR_US, "Unknown", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "TOSHIBA_MEC_CT_1.0" } + , { 0x0019, 0x000d, 0x0019, 0x000d, + EVR_SS, "SubtrEdgeEnhancementKernelSize", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS SMS-AX VIEW 1.0" } + , { 0x0019, 0x000d, 0x0019, 0x000d, + EVR_TM, "Time", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "TOSHIBA_MEC_CT_1.0" } + , { 0x0019, 0x000e, 0x0019, 0x000e, + EVR_IS, "FlowCompensation", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/LAST" } + , { 0x0019, 0x000e, 0x0019, 0x000e, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x000e, 0x0019, 0x000e, + EVR_US, "FadePercent", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS SMS-AX VIEW 1.0" } + , { 0x0019, 0x000e, 0x0019, 0x000e, + EVR_DS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "TOSHIBA_MEC_CT_1.0" } + , { 0x0019, 0x000f, 0x0019, 0x000f, + EVR_DS, "HorizontalFrameOfReference", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x000f, 0x0019, 0x000f, + EVR_US, "FlippedBeforeLateralityApplied", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS SMS-AX VIEW 1.0" } + , { 0x0019, 0x0010, 0x0019, 0x0010, + EVR_LT, "MeasurementMode", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS DLR.01" } + , { 0x0019, 0x0010, 0x0019, 0x0010, + EVR_LT, "VideoBeamBoost", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P-XSB-DCI Release 1" } + , { 0x0019, 0x0010, 0x0019, 0x0010, + EVR_UN, "ECGTimeMapDataBitsAllocated", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P-Private-DCI Release 1" } + , { 0x0019, 0x0010, 0x0019, 0x0010, + EVR_DS, "InjectorDelay", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "DLX_SERIE_01" } + , { 0x0019, 0x0010, 0x0019, 0x0010, + EVR_IS, "CenterOfCircularImageBlanking", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "CARDIO-D.R. 1.0" } + , { 0x0019, 0x0010, 0x0019, 0x0010, + EVR_UN, "PhysiologicalDataType2", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1;1" } + , { 0x0019, 0x0010, 0x0019, 0x0010, + EVR_LO, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P-GV-CT Release 1" } + , { 0x0019, 0x0010, 0x0019, 0x0010, + EVR_US, "MainsFrequency", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1" } + , { 0x0019, 0x0010, 0x0019, 0x0010, + EVR_IS, "PatientThickness", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SVISION" } + , { 0x0019, 0x0010, 0x0019, 0x0010, + EVR_US, "ApplyFade", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS SMS-AX VIEW 1.0" } + , { 0x0019, 0x0010, 0x0019, 0x0010, + EVR_DS, "SourceSideCollimatorAperture", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CT VA0 GEN" } + , { 0x0019, 0x0010, 0x0019, 0x0010, + EVR_DS, "DistanceSourceToSourceSideCollimator", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CT VA0 COAD" } + , { 0x0019, 0x0010, 0x0019, 0x0010, + EVR_ST, "CRImageParamsCommon", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "1.2.840.113681" } + , { 0x0019, 0x0010, 0x0019, 0x0010, + EVR_IS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR SPECTRO;1" } + , { 0x0019, 0x0010, 0x0019, 0x0010, + EVR_DS, "NetFrequency", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CM VA0 CMS" } + , { 0x0019, 0x0010, 0x0019, 0x0010, + EVR_LT, "ParameterFileName", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CM VA0 ACQU" } + , { 0x0019, 0x0010, 0x0019, 0x0010, + EVR_DS, "TotalMeasurementTimeNominal", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 GEN" } + , { 0x0019, 0x0011, 0x0019, 0x0011, + EVR_LT, "ImageType", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS DLR.01" } + , { 0x0019, 0x0011, 0x0019, 0x0011, + EVR_US, "ChannelGeneratingVideoSync", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P-XSB-DCI Release 1" } + , { 0x0019, 0x0011, 0x0019, 0x0011, + EVR_UN, "ECGTimeMapDataBitsStored", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P-Private-DCI Release 1" } + , { 0x0019, 0x0011, 0x0019, 0x0011, + EVR_CS, "AutoInject", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "DLX_SERIE_01" } + , { 0x0019, 0x0011, 0x0019, 0x0011, + EVR_UN, "PhysiologicalDataChannelAndKind2", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1;1" } + , { 0x0019, 0x0011, 0x0019, 0x0011, + EVR_SS, "SeriesContrast", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x0011, 0x0019, 0x0011, + EVR_IS, "ChemicalShiftNumber", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS-MR-1" } + , { 0x0019, 0x0011, 0x0019, 0x0011, + EVR_DS, "DetectorSideCollimatorAperture", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CT VA0 GEN" } + , { 0x0019, 0x0011, 0x0019, 0x0011, + EVR_DS, "DistanceSourceToDetectorSideCollimator", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CT VA0 COAD" } + , { 0x0019, 0x0011, 0x0019, 0x0011, + EVR_ST, "CRImageIPParamsSingle", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "1.2.840.113681" } + , { 0x0019, 0x0011, 0x0019, 0x0011, + EVR_LO, "SequenceFileName", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CM VA0 ACQU" } + , { 0x0019, 0x0011, 0x0019, 0x0011, + EVR_DS, "TotalMeasurementTimeCurrent", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 GEN" } + , { 0x0019, 0x0012, 0x0019, 0x0012, + EVR_US, "VideoGain", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P-XSB-DCI Release 1" } + , { 0x0019, 0x0012, 0x0019, 0x0012, + EVR_UN, "ECGTimeMapDataHighBit", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P-Private-DCI Release 1" } + , { 0x0019, 0x0012, 0x0019, 0x0012, + EVR_IS, "RadiusOfCircularImageBlanking", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "CARDIO-D.R. 1.0" } + , { 0x0019, 0x0012, 0x0019, 0x0012, + EVR_US, "SampleBitsAllocated2", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1;1" } + , { 0x0019, 0x0012, 0x0019, 0x0012, + EVR_SS, "LastPseq", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x0012, 0x0019, 0x0012, + EVR_IS, "PhaseNumber", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS-MR-1" } + , { 0x0019, 0x0012, 0x0019, 0x0012, + EVR_US, "Zoom", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS SMS-AX VIEW 1.0" } + , { 0x0019, 0x0012, 0x0019, 0x0012, + EVR_DS, "MagneticFieldStrength", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 COAD" } + , { 0x0019, 0x0012, 0x0019, 0x0012, + EVR_ST, "CRImageIPParamsLeft", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "1.2.840.113681" } + , { 0x0019, 0x0012, 0x0019, 0x0012, + EVR_IS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR SPECTRO;1" } + , { 0x0019, 0x0012, 0x0019, 0x0012, + EVR_LT, "SequenceFileOwner", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CM VA0 ACQU" } + , { 0x0019, 0x0012, 0x0019, 0x0012, + EVR_DS, "StartDelayTime", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 GEN" } + , { 0x0019, 0x0013, 0x0019, 0x0013, + EVR_US, "VideoOffset", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P-XSB-DCI Release 1" } + , { 0x0019, 0x0013, 0x0019, 0x0013, + EVR_UN, "ECGTimeMapDataRepresentation", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P-Private-DCI Release 1" } + , { 0x0019, 0x0013, 0x0019, 0x0013, + EVR_US, "SampleBitsStored2", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1;1" } + , { 0x0019, 0x0013, 0x0019, 0x0013, + EVR_SS, "StartNumberForBaseline", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x0013, 0x0019, 0x0013, + EVR_SS, "PanX", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS SMS-AX VIEW 1.0" } + , { 0x0019, 0x0013, 0x0019, 0x0013, + EVR_ST, "CRImageIPParamsRight", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "1.2.840.113681" } + , { 0x0019, 0x0013, 0x0019, 0x0013, + EVR_IS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR SPECTRO;1" } + , { 0x0019, 0x0013, 0x0019, 0x0013, + EVR_LT, "SequenceDescription", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CM VA0 ACQU" } + , { 0x0019, 0x0013, 0x0019, 0x0013, + EVR_DS, "DwellTime", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 GEN" } + , { 0x0019, 0x0014, 0x0019, 0x0014, + EVR_UN, "ECGTimeMapDataSmallestDataValue", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P-Private-DCI Release 1" } + , { 0x0019, 0x0014, 0x0019, 0x0014, + EVR_IS, "AcquisitionMode", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "DLX_SERIE_01" } + , { 0x0019, 0x0014, 0x0019, 0x0014, + EVR_US, "SampleHighBit2", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1;1" } + , { 0x0019, 0x0014, 0x0019, 0x0014, + EVR_SS, "EndNumberForBaseline", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x0014, 0x0019, 0x0014, + EVR_SS, "PanY", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS SMS-AX VIEW 1.0" } + , { 0x0019, 0x0014, 0x0019, 0x0014, + EVR_DS, "ADCVoltage", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 COAD" } + , { 0x0019, 0x0014, 0x0019, 0x0014, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR SPECTRO;1" } + , { 0x0019, 0x0014, 0x0019, 0x0014, + EVR_LT, "EPIFileName", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CM VA0 ACQU" } + , { 0x0019, 0x0014, 0x0019, 0x0014, + EVR_IS, "NumberOfPhases", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 GEN" } + , { 0x0019, 0x0015, 0x0019, 0x0015, + EVR_LT, "SoftwareVersion", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS DLR.01" } + , { 0x0019, 0x0015, 0x0019, 0x0015, + EVR_UN, "ECGTimeMapDataLargestDataValue", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P-Private-DCI Release 1" } + , { 0x0019, 0x0015, 0x0019, 0x0015, + EVR_CS, "CameraRotationEnabled", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "DLX_SERIE_01" } + , { 0x0019, 0x0015, 0x0019, 0x0015, + EVR_LT, "OfflineUID", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x0015, 0x0019, 0x0015, + EVR_US, "SampleRepresentation2", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1;1" } + , { 0x0019, 0x0015, 0x0019, 0x0015, + EVR_SS, "StartNumberForEnhancedScans", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x0015, 0x0019, 0x0015, + EVR_SS, "NativeEdgeEnhancementAdvPercGain", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS SMS-AX VIEW 1.0" } + , { 0x0019, 0x0015, 0x0019, 0x0015, + EVR_LO, "AcquiredPlane", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA GEN" } + , { 0x0019, 0x0015, 0x0019, 0x0015, + EVR_LO, "KanjiBodyPartForExposure", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "FDMS 1.0" } + , { 0x0019, 0x0015, 0x0019, 0x0015, + EVR_US, "Unknown", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR SPECTRO;1" } + , { 0x0019, 0x0016, 0x0019, 0x0016, + EVR_UN, "ECGTimeMapDataNumberOfDataValues", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P-Private-DCI Release 1" } + , { 0x0019, 0x0016, 0x0019, 0x0016, + EVR_CS, "ReverseSweep", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "DLX_SERIE_01" } + , { 0x0019, 0x0016, 0x0019, 0x0016, + EVR_UN, "SmallestSampleValue2", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1;1" } + , { 0x0019, 0x0016, 0x0019, 0x0016, + EVR_SS, "EndNumberForEnhancedScans", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x0016, 0x0019, 0x0016, + EVR_SS, "SubtrEdgeEnhancementAdvPercGain", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS SMS-AX VIEW 1.0" } + , { 0x0019, 0x0016, 0x0019, 0x0016, + EVR_DS, "ADCOffset", 2, 2, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 COAD" } + , { 0x0019, 0x0016, 0x0019, 0x0016, + EVR_IS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR SPECTRO;1" } + , { 0x0019, 0x0016, 0x0019, 0x0016, + EVR_UL, "SequenceControlMask", 2, 2, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 GEN" } + , { 0x0019, 0x0017, 0x0019, 0x0017, + EVR_UN, "ECGTimeMapData", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P-Private-DCI Release 1" } + , { 0x0019, 0x0017, 0x0019, 0x0017, + EVR_IS, "SpatialFilterStrength", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "DLX_SERIE_01" } + , { 0x0019, 0x0017, 0x0019, 0x0017, + EVR_UN, "LargestSampleValue2", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1;1" } + , { 0x0019, 0x0017, 0x0019, 0x0017, + EVR_SS, "SeriesPlane", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x0017, 0x0019, 0x0017, + EVR_US, "InvertFlag", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS SMS-AX VIEW 1.0" } + , { 0x0019, 0x0017, 0x0019, 0x0017, + EVR_IS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR SPECTRO;1" } + , { 0x0019, 0x0018, 0x0019, 0x0018, + EVR_IS, "ZoomFactor", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "DLX_SERIE_01" } + , { 0x0019, 0x0018, 0x0019, 0x0018, + EVR_SS, "Internal", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x0018, 0x0019, 0x0018, + EVR_UN, "NumberOfSamples2", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1;1" } + , { 0x0019, 0x0018, 0x0019, 0x0018, + EVR_LO, "FirstScanRAS", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x0018, 0x0019, 0x0018, + EVR_IS, "BeamDistance", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SVISION" } + , { 0x0019, 0x0018, 0x0019, 0x0018, + EVR_UN, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR SPECTRO;1" } + , { 0x0019, 0x0018, 0x0019, 0x0018, + EVR_SS, "Internal", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE B" } + , { 0x0019, 0x0018, 0x0019, 0x0018, + EVR_UL, "MeasurementStatusMask", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 GEN" } + , { 0x0019, 0x0019, 0x0019, 0x0019, + EVR_IS, "XZoomCenter", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "DLX_SERIE_01" } + , { 0x0019, 0x0019, 0x0019, 0x0019, + EVR_SS, "Internal", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x0019, 0x0019, 0x0019, + EVR_UN, "SampleData2", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1;1" } + , { 0x0019, 0x0019, 0x0019, 0x0019, + EVR_DS, "FirstScanLocation", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x0019, 0x0019, 0x0019, + EVR_SS, "Internal", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE B" } + , { 0x0019, 0x001a, 0x0019, 0x001a, + EVR_IS, "YZoomCenter", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "DLX_SERIE_01" } + , { 0x0019, 0x001a, 0x0019, 0x001a, + EVR_SS, "Internal", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x001a, 0x0019, 0x001a, + EVR_UN, "SampleRate2", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1;1" } + , { 0x0019, 0x001a, 0x0019, 0x001a, + EVR_LO, "LastScanRAS", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x001a, 0x0019, 0x001a, + EVR_OB, "Quant1KOverlay", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS SMS-AX VIEW 1.0" } + , { 0x0019, 0x001a, 0x0019, 0x001a, + EVR_SS, "Internal", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE B" } + , { 0x0019, 0x001b, 0x0019, 0x001b, + EVR_DS, "Focus", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "DLX_SERIE_01" } + , { 0x0019, 0x001b, 0x0019, 0x001b, + EVR_SS, "Internal", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x001b, 0x0019, 0x001b, + EVR_DS, "LastScanLocation", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x001b, 0x0019, 0x001b, + EVR_US, "OriginalResolution", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS SMS-AX VIEW 1.0" } + , { 0x0019, 0x001b, 0x0019, 0x001b, + EVR_SS, "Internal", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE B" } + , { 0x0019, 0x001c, 0x0019, 0x001c, + EVR_CS, "Dose", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "DLX_SERIE_01" } + , { 0x0019, 0x001c, 0x0019, 0x001c, + EVR_SS, "Internal", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x001c, 0x0019, 0x001c, + EVR_DS, "AutoWindowCenter", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS SMS-AX VIEW 1.0" } + , { 0x0019, 0x001c, 0x0019, 0x001c, + EVR_SS, "Internal", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE B" } + , { 0x0019, 0x001d, 0x0019, 0x001d, + EVR_IS, "SideMark", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "DLX_SERIE_01" } + , { 0x0019, 0x001d, 0x0019, 0x001d, + EVR_SS, "Internal", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x001d, 0x0019, 0x001d, + EVR_DS, "AutoWindowWidth", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS SMS-AX VIEW 1.0" } + , { 0x0019, 0x001d, 0x0019, 0x001d, + EVR_SS, "Internal", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE B" } + , { 0x0019, 0x001e, 0x0019, 0x001e, + EVR_IS, "PercentageLandscape", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "DLX_SERIE_01" } + , { 0x0019, 0x001e, 0x0019, 0x001e, + EVR_SS, "Internal", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x001e, 0x0019, 0x001e, + EVR_DS, "DisplayFieldOfView", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x001e, 0x0019, 0x001e, + EVR_SS, "Internal", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE B" } + , { 0x0019, 0x001f, 0x0019, 0x001f, + EVR_DS, "ExposureDuration", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "DLX_SERIE_01" } + , { 0x0019, 0x001f, 0x0019, 0x001f, + EVR_SS, "Internal", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x001f, 0x0019, 0x001f, + EVR_SS, "DefaultTableIsoCenterHeight", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA GEN" } + , { 0x0019, 0x001f, 0x0019, 0x001f, + EVR_SS, "Internal", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE B" } + , { 0x0019, 0x0020, 0x0019, 0x0020, + EVR_LT, "MPMCode", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS DLR.01" } + , { 0x0019, 0x0020, 0x0019, 0x0020, + EVR_DS, "RTDDataCompressionFactor", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P-XSB-DCI Release 1" } + , { 0x0019, 0x0020, 0x0019, 0x0020, + EVR_SS, "SystemCalibFactorPlaneA", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x0020, 0x0019, 0x0020, + EVR_DS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x0020, 0x0019, 0x0020, + EVR_TM, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P-GV-CT Release 1" } + , { 0x0019, 0x0020, 0x0019, 0x0020, + EVR_IS, "WorkstationNumber", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SVISION" } + , { 0x0019, 0x0020, 0x0019, 0x0020, + EVR_DS, "TransmitterAmplitude", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 COAD" } + , { 0x0019, 0x0020, 0x0019, 0x0020, + EVR_DS, "ExposureTime", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CT VA0 GEN" } + , { 0x0019, 0x0020, 0x0019, 0x0020, + EVR_IS, "NumberOfPossibleChannels", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CT VA0 COAD" } + , { 0x0019, 0x0020, 0x0019, 0x0020, + EVR_SL, "SceneFlag", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA GEN" } + , { 0x0019, 0x0020, 0x0019, 0x0020, + EVR_IS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR SPECTRO;1" } + , { 0x0019, 0x0020, 0x0019, 0x0020, + EVR_LT, "MeasurementMode", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CM VA0 CMS" } + , { 0x0019, 0x0020, 0x0019, 0x0020, + EVR_SL, "SystemCalibFactorPlaneB", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE B" } + , { 0x0019, 0x0020, 0x0019, 0x0020, + EVR_IS, "NumberOfFourierLinesNominal", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 GEN" } + , { 0x0019, 0x0021, 0x0019, 0x0021, + EVR_LT, "Latitude", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS DLR.01" } + , { 0x0019, 0x0021, 0x0019, 0x0021, + EVR_IS, "NumberOfTransmitterAmplitudes", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 COAD" } + , { 0x0019, 0x0021, 0x0019, 0x0021, + EVR_DS, "ExposureCurrent", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CT VA0 GEN" } + , { 0x0019, 0x0021, 0x0019, 0x0021, + EVR_IS, "MeanChannelNumber", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CT VA0 COAD" } + , { 0x0019, 0x0021, 0x0019, 0x0021, + EVR_IS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR SPECTRO;1" } + , { 0x0019, 0x0021, 0x0019, 0x0021, + EVR_IS, "NumberOfFourierLinesCurrent", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 GEN" } + , { 0x0019, 0x0022, 0x0019, 0x0022, + EVR_LT, "Sensitivity", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS DLR.01" } + , { 0x0019, 0x0022, 0x0019, 0x0022, + EVR_SS, "XRayParameterSetNo", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x0022, 0x0019, 0x0022, + EVR_UN, "RouteAET", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "DIDI TO PCR 1.1" } + , { 0x0019, 0x0022, 0x0019, 0x0022, + EVR_DS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x0022, 0x0019, 0x0022, + EVR_DS, "TransmitterAttenuator", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 COAD" } + , { 0x0019, 0x0022, 0x0019, 0x0022, + EVR_DS, "DetectorSpacing", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CT VA0 COAD" } + , { 0x0019, 0x0022, 0x0019, 0x0022, + EVR_SL, "RefPhotofileFlag", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA GEN" } + , { 0x0019, 0x0022, 0x0019, 0x0022, + EVR_IS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR SPECTRO;1" } + , { 0x0019, 0x0022, 0x0019, 0x0022, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE B" } + , { 0x0019, 0x0023, 0x0019, 0x0023, + EVR_LT, "EDR", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS DLR.01" } + , { 0x0019, 0x0023, 0x0019, 0x0023, + EVR_DS, "PCRPrintScale", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "DIDI TO PCR 1.1" } + , { 0x0019, 0x0023, 0x0019, 0x0023, + EVR_DS, "TableSpeed", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x0023, 0x0019, 0x0023, + EVR_DS, "DetectorCenter", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CT VA0 COAD" } + , { 0x0019, 0x0023, 0x0019, 0x0023, + EVR_IS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR SPECTRO;1" } + , { 0x0019, 0x0024, 0x0019, 0x0024, + EVR_LT, "LFix", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS DLR.01" } + , { 0x0019, 0x0024, 0x0019, 0x0024, + EVR_SS, "XRaySystem", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x0024, 0x0019, 0x0024, + EVR_UN, "PCRPrintJobEnd", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "DIDI TO PCR 1.1" } + , { 0x0019, 0x0024, 0x0019, 0x0024, + EVR_DS, "MidScanTime", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x0024, 0x0019, 0x0024, + EVR_DS, "TransmitterCalibration", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 COAD" } + , { 0x0019, 0x0024, 0x0019, 0x0024, + EVR_DS, "ReadingIntegrationTime", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CT VA0 COAD" } + , { 0x0019, 0x0024, 0x0019, 0x0024, + EVR_LO, "SceneName", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA GEN" } + , { 0x0019, 0x0024, 0x0019, 0x0024, + EVR_IS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR SPECTRO;1" } + , { 0x0019, 0x0024, 0x0019, 0x0024, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE B" } + , { 0x0019, 0x0025, 0x0019, 0x0025, + EVR_LT, "SFix", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS DLR.01" } + , { 0x0019, 0x0025, 0x0019, 0x0025, + EVR_IS, "PCRNoFilmCopies", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "DIDI TO PCR 1.1" } + , { 0x0019, 0x0025, 0x0019, 0x0025, + EVR_SS, "MidScanFlag", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x0025, 0x0019, 0x0025, + EVR_LT, "OriginalPixelDataQuality", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1" } + , { 0x0019, 0x0025, 0x0019, 0x0025, + EVR_DS, "KVPGeneratorPowerCurrent", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CT VA0 GEN" } + , { 0x0019, 0x0025, 0x0019, 0x0025, + EVR_IS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR SPECTRO;1" } + , { 0x0019, 0x0026, 0x0019, 0x0026, + EVR_LT, "PresetMode", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS DLR.01" } + , { 0x0019, 0x0026, 0x0019, 0x0026, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x0026, 0x0019, 0x0026, + EVR_IS, "PCRFilmLayoutPosition", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "DIDI TO PCR 1.1" } + , { 0x0019, 0x0026, 0x0019, 0x0026, + EVR_SL, "DegreesOfAzimuth", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x0026, 0x0019, 0x0026, + EVR_DS, "TransmitterReference", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 COAD" } + , { 0x0019, 0x0026, 0x0019, 0x0026, + EVR_DS, "GeneratorVoltage", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CT VA0 GEN" } + , { 0x0019, 0x0026, 0x0019, 0x0026, + EVR_SS, "AcquisitionIndex", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA GEN" } + , { 0x0019, 0x0026, 0x0019, 0x0026, + EVR_IS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR SPECTRO;1" } + , { 0x0019, 0x0026, 0x0019, 0x0026, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE B" } + , { 0x0019, 0x0026, 0x0019, 0x0026, + EVR_IS, "NumberOfFourierLinesAfterZero", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 GEN" } + , { 0x0019, 0x0027, 0x0019, 0x0027, + EVR_LT, "Region", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS DLR.01" } + , { 0x0019, 0x0027, 0x0019, 0x0027, + EVR_UN, "PCRPrintReportName", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "DIDI TO PCR 1.1" } + , { 0x0019, 0x0027, 0x0019, 0x0027, + EVR_DS, "GantryPeriod", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x0027, 0x0019, 0x0027, + EVR_IS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR SPECTRO;1" } + , { 0x0019, 0x0028, 0x0019, 0x0028, + EVR_LT, "Subregion", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS DLR.01" } + , { 0x0019, 0x0028, 0x0019, 0x0028, + EVR_SS, "AcquiredDisplayMode", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x0028, 0x0019, 0x0028, + EVR_IS, "TubeNumber", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SVISION" } + , { 0x0019, 0x0028, 0x0019, 0x0028, + EVR_SS, "MixedPulseMode", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA GEN" } + , { 0x0019, 0x0028, 0x0019, 0x0028, + EVR_IS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR SPECTRO;1" } + , { 0x0019, 0x0028, 0x0019, 0x0028, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE B" } + , { 0x0019, 0x0028, 0x0019, 0x0028, + EVR_IS, "FirstMeasuredFourierLine", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 GEN" } + , { 0x0019, 0x0029, 0x0019, 0x0029, + EVR_IS, "Unknown", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR SPECTRO;1" } + , { 0x0019, 0x002a, 0x0019, 0x002a, + EVR_SS, "AcquisitionDelay", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x002a, 0x0019, 0x002a, + EVR_DS, "XrayOnPosition", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x002a, 0x0019, 0x002a, + EVR_SS, "NoOfPositions", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA GEN" } + , { 0x0019, 0x002a, 0x0019, 0x002a, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE B" } + , { 0x0019, 0x002b, 0x0019, 0x002b, + EVR_DS, "XrayOffPosition", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x002c, 0x0019, 0x002c, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x002c, 0x0019, 0x002c, + EVR_SL, "NumberOfTriggers", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x002c, 0x0019, 0x002c, + EVR_SS, "NoOfPhases", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA GEN" } + , { 0x0019, 0x002c, 0x0019, 0x002c, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE B" } + , { 0x0019, 0x002d, 0x0019, 0x002d, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x002e, 0x0019, 0x002e, + EVR_SS, "MaxFramesLimit", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x002e, 0x0019, 0x002e, + EVR_DS, "AngleOfFirstView", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x002e, 0x0019, 0x002e, + EVR_SS, "FrameRateForPositions", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA GEN" } + , { 0x0019, 0x002e, 0x0019, 0x002e, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE B" } + , { 0x0019, 0x002f, 0x0019, 0x002f, + EVR_DS, "TriggerFrequency", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x0030, 0x0019, 0x0030, + EVR_LT, "Orientation", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS DLR.01" } + , { 0x0019, 0x0030, 0x0019, 0x0030, + EVR_US, "MaximumFrameSizeNIU", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x0030, 0x0019, 0x0030, + EVR_UL, "MaximumImageFrameSize", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "CARDIO-D.R. 1.0" } + , { 0x0019, 0x0030, 0x0019, 0x0030, + EVR_LO, "CREDRMode", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GE ??? From Adantage Review CS" } + , { 0x0019, 0x0030, 0x0019, 0x0030, + EVR_IS, "BuckyGrid", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SVISION" } + , { 0x0019, 0x0030, 0x0019, 0x0030, + EVR_US, "ECGTriggering", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1" } + , { 0x0019, 0x0030, 0x0019, 0x0030, + EVR_DS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P-Private_ICS Release 1" } + , { 0x0019, 0x0030, 0x0019, 0x0030, + EVR_SS, "NoOfFramesForPositions", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA GEN" } + , { 0x0019, 0x0030, 0x0019, 0x0030, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P-PCR Release 2" } + , { 0x0019, 0x0030, 0x0019, 0x0030, + EVR_LT, "CalculationMode", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CM VA0 CMS" } + , { 0x0019, 0x0030, 0x0019, 0x0030, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE B" } + , { 0x0019, 0x0030, 0x0019, 0x0030, + EVR_IS, "AcquisitionColumns", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 GEN" } + , { 0x0019, 0x0031, 0x0019, 0x0031, + EVR_LT, "MarkOnFilm", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS DLR.01" } + , { 0x0019, 0x0031, 0x0019, 0x0031, + EVR_UN, "ECG1Offset", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1" } + , { 0x0019, 0x0031, 0x0019, 0x0031, + EVR_LO, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P-Private_ICS Release 1" } + , { 0x0019, 0x0031, 0x0019, 0x0031, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR SPECTRO;1" } + , { 0x0019, 0x0031, 0x0019, 0x0031, + EVR_IS, "ReconstructionColumns", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 GEN" } + , { 0x0019, 0x0032, 0x0019, 0x0032, + EVR_LT, "RotationOnDRC", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS DLR.01" } + , { 0x0019, 0x0032, 0x0019, 0x0032, + EVR_SS, "SubtractedFilterType", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x0032, 0x0019, 0x0032, + EVR_UN, "ECG2Offset1", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1" } + , { 0x0019, 0x0032, 0x0019, 0x0032, + EVR_SS, "SteppingDirection", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA GEN" } + , { 0x0019, 0x0032, 0x0019, 0x0032, + EVR_LO, "KanjiMenuName", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "FDMS 1.0" } + , { 0x0019, 0x0032, 0x0019, 0x0032, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR SPECTRO;1" } + , { 0x0019, 0x0032, 0x0019, 0x0032, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE B" } + , { 0x0019, 0x0033, 0x0019, 0x0033, + EVR_UN, "ECG2Offset2", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1" } + , { 0x0019, 0x0034, 0x0019, 0x0034, + EVR_SS, "FilterFactorNative", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x0034, 0x0019, 0x0034, + EVR_IS, "Focus", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SVISION" } + , { 0x0019, 0x0034, 0x0019, 0x0034, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA GEN" } + , { 0x0019, 0x0034, 0x0019, 0x0034, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE B" } + , { 0x0019, 0x0036, 0x0019, 0x0036, + EVR_SS, "AnatomicBackgroundFactor", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x0036, 0x0019, 0x0036, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA GEN" } + , { 0x0019, 0x0036, 0x0019, 0x0036, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE B" } + , { 0x0019, 0x0038, 0x0019, 0x0038, + EVR_SS, "WindowUpperLimitNative", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x0038, 0x0019, 0x0038, + EVR_IS, "Child", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SVISION" } + , { 0x0019, 0x0038, 0x0019, 0x0038, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA GEN" } + , { 0x0019, 0x0038, 0x0019, 0x0038, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE B" } + , { 0x0019, 0x0039, 0x0019, 0x0039, + EVR_SS, "AxialType", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GE_GENESIS_REV3.0" } + , { 0x0019, 0x0039, 0x0019, 0x0039, + EVR_SS, "ScanFOVType", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x003a, 0x0019, 0x003a, + EVR_SS, "WindowLowerLimitNative", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x003a, 0x0019, 0x003a, + EVR_IS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x003a, 0x0019, 0x003a, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA GEN" } + , { 0x0019, 0x003a, 0x0019, 0x003a, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE B" } + , { 0x0019, 0x003b, 0x0019, 0x003b, + EVR_LT, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x003c, 0x0019, 0x003c, + EVR_SS, "WindowBrightnessPhase1", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x003c, 0x0019, 0x003c, + EVR_UN, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x003c, 0x0019, 0x003c, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA GEN" } + , { 0x0019, 0x003c, 0x0019, 0x003c, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE B" } + , { 0x0019, 0x003e, 0x0019, 0x003e, + EVR_SS, "WindowBrightnessPhase2", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x003e, 0x0019, 0x003e, + EVR_UN, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x003e, 0x0019, 0x003e, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA GEN" } + , { 0x0019, 0x003e, 0x0019, 0x003e, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE B" } + , { 0x0019, 0x003f, 0x0019, 0x003f, + EVR_UN, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x0040, 0x0019, 0x0040, + EVR_LT, "ReaderType", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS DLR.01" } + , { 0x0019, 0x0040, 0x0019, 0x0040, + EVR_SS, "WindowContrastPhase1", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x0040, 0x0019, 0x0040, + EVR_SS, "StatReconFlag", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x0040, 0x0019, 0x0040, + EVR_LO, "CRLatitude", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GE ??? From Adantage Review CS" } + , { 0x0019, 0x0040, 0x0019, 0x0040, + EVR_DS, "FrameRate", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "INTEGRIS 1.0" } + , { 0x0019, 0x0040, 0x0019, 0x0040, + EVR_IS, "CollimatorDistanceX", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SVISION" } + , { 0x0019, 0x0040, 0x0019, 0x0040, + EVR_UL, "MasterControlMask", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CT VA0 GEN" } + , { 0x0019, 0x0040, 0x0019, 0x0040, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA GEN" } + , { 0x0019, 0x0040, 0x0019, 0x0040, + EVR_CS, "ImageProcessingType", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "FDMS 1.0" } + , { 0x0019, 0x0040, 0x0019, 0x0040, + EVR_IS, "ArrayCoilElementNumber", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 GEN" } + , { 0x0019, 0x0040, 0x0019, 0x0040, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE B" } + , { 0x0019, 0x0041, 0x0019, 0x0041, + EVR_LT, "SubModality", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS DLR.01" } + , { 0x0019, 0x0041, 0x0019, 0x0041, + EVR_SS, "ComputeType", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x0041, 0x0019, 0x0041, + EVR_IS, "CollimatorDistanceY", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SVISION" } + , { 0x0019, 0x0041, 0x0019, 0x0041, + EVR_LT, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR SPECTRO;1" } + , { 0x0019, 0x0041, 0x0019, 0x0041, + EVR_UL, "ArrayCoilElementSelectMask", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 GEN" } + , { 0x0019, 0x0042, 0x0019, 0x0042, + EVR_LT, "ReaderSerialNumber", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS DLR.01" } + , { 0x0019, 0x0042, 0x0019, 0x0042, + EVR_SS, "WindowContrastPhase2", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x0042, 0x0019, 0x0042, + EVR_SS, "SegmentNumber", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x0042, 0x0019, 0x0042, + EVR_US, "ProcessingMask", 5, 5, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CT VA0 GEN" } + , { 0x0019, 0x0042, 0x0019, 0x0042, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA GEN" } + , { 0x0019, 0x0042, 0x0019, 0x0042, + EVR_IS, "Unknown", 2, 2, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR SPECTRO;1" } + , { 0x0019, 0x0042, 0x0019, 0x0042, + EVR_UL, "ArrayCoilElementDataMask", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 GEN" } + , { 0x0019, 0x0042, 0x0019, 0x0042, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE B" } + , { 0x0019, 0x0043, 0x0019, 0x0043, + EVR_SS, "TotalSegmentsRequested", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x0043, 0x0019, 0x0043, + EVR_IS, "Unknown", 2, 2, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR SPECTRO;1" } + , { 0x0019, 0x0043, 0x0019, 0x0043, + EVR_IS, "ArrayCoilElementToADCConnect", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 GEN" } + , { 0x0019, 0x0044, 0x0019, 0x0044, + EVR_SS, "FilterFactorSub", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x0044, 0x0019, 0x0044, + EVR_DS, "InterscanDelay", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x0044, 0x0019, 0x0044, + EVR_US, "Unknown", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CT VA0 GEN" } + , { 0x0019, 0x0044, 0x0019, 0x0044, + EVR_SS, "ImageTransferDelay", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA GEN" } + , { 0x0019, 0x0044, 0x0019, 0x0044, + EVR_DS, "ArrayCoilElementNoiseLevel", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 GEN" } + , { 0x0019, 0x0044, 0x0019, 0x0044, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE B" } + , { 0x0019, 0x0045, 0x0019, 0x0045, + EVR_US, "Unknown", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CT VA0 GEN" } + , { 0x0019, 0x0045, 0x0019, 0x0045, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR SPECTRO;1" } + , { 0x0019, 0x0045, 0x0019, 0x0045, + EVR_IS, "ArrayCoilADCPairNumber", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 GEN" } + , { 0x0019, 0x0046, 0x0019, 0x0046, + EVR_SS, "PeakOpacified", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x0046, 0x0019, 0x0046, + EVR_SL, "InversFlag", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA GEN" } + , { 0x0019, 0x0046, 0x0019, 0x0046, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR SPECTRO;1" } + , { 0x0019, 0x0046, 0x0019, 0x0046, + EVR_UL, "ArrayCoilCombinationMask", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 GEN" } + , { 0x0019, 0x0046, 0x0019, 0x0046, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE B" } + , { 0x0019, 0x0047, 0x0019, 0x0047, + EVR_SS, "ViewCompressionFactor", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x0047, 0x0019, 0x0047, + EVR_IS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR SPECTRO;1" } + , { 0x0019, 0x0048, 0x0019, 0x0048, + EVR_SL, "MaskFrame", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x0048, 0x0019, 0x0048, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x0048, 0x0019, 0x0048, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA GEN" } + , { 0x0019, 0x0048, 0x0019, 0x0048, + EVR_IS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR SPECTRO;1" } + , { 0x0019, 0x0048, 0x0019, 0x0048, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE B" } + , { 0x0019, 0x0049, 0x0019, 0x0049, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x0049, 0x0019, 0x0049, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR SPECTRO;1" } + , { 0x0019, 0x004a, 0x0019, 0x004a, + EVR_SL, "BIHFrame", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x004a, 0x0019, 0x004a, + EVR_SS, "TotalNumberOfRefChannels", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x004a, 0x0019, 0x004a, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA GEN" } + , { 0x0019, 0x004a, 0x0019, 0x004a, + EVR_US, "Unknown", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE B" } + , { 0x0019, 0x004b, 0x0019, 0x004b, + EVR_SL, "DataSizeForScanData", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x004c, 0x0019, 0x004c, + EVR_SS, "CentBeamAngulationCaudCran", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x004c, 0x0019, 0x004c, + EVR_SS, "BlankingCircleDiameter", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA GEN" } + , { 0x0019, 0x004c, 0x0019, 0x004c, + EVR_US, "Unknown", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE B" } + , { 0x0019, 0x004e, 0x0019, 0x004e, + EVR_SS, "CentBeamAngulationLRAnterior", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x004e, 0x0019, 0x004e, + EVR_US, "Unknown", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE B" } + , { 0x0019, 0x0050, 0x0019, 0x0050, + EVR_LT, "CassetteScale", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS DLR.01" } + , { 0x0019, 0x0050, 0x0019, 0x0050, + EVR_SS, "LongitudinalPosition", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x0050, 0x0019, 0x0050, + EVR_LO, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P-GV-CT Release 1" } + , { 0x0019, 0x0050, 0x0019, 0x0050, + EVR_US, "VideoScanMode", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1" } + , { 0x0019, 0x0050, 0x0019, 0x0050, + EVR_LO, "CRGroupNumber", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GE ??? From Adantage Review CS" } + , { 0x0019, 0x0050, 0x0019, 0x0050, + EVR_IS, "CentralBeamHeight", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SVISION" } + , { 0x0019, 0x0050, 0x0019, 0x0050, + EVR_DS, "ReceiverTotalGain", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 COAD" } + , { 0x0019, 0x0050, 0x0019, 0x0050, + EVR_SL, "StandDataValid", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA GEN" } + , { 0x0019, 0x0050, 0x0019, 0x0050, + EVR_DS, "DetectorAlignment", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CT VA0 COAD" } + , { 0x0019, 0x0050, 0x0019, 0x0050, + EVR_CS, "EDRMode", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "FDMS 1.0" } + , { 0x0019, 0x0050, 0x0019, 0x0050, + EVR_IS, "NoiseLevel", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CM VA0 CMS" } + , { 0x0019, 0x0050, 0x0019, 0x0050, + EVR_UN, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR SPECTRO;1" } + , { 0x0019, 0x0050, 0x0019, 0x0050, + EVR_IS, "NumberOfAverages", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 GEN" } + , { 0x0019, 0x0050, 0x0019, 0x0050, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE B" } + , { 0x0019, 0x0051, 0x0019, 0x0051, + EVR_LT, "CassetteMatrix", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS DLR.01" } + , { 0x0019, 0x0051, 0x0019, 0x0051, + EVR_US, "VideoLineRate", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1" } + , { 0x0019, 0x0051, 0x0019, 0x0051, + EVR_DS, "ReceiverAmplifierGain", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 COAD" } + , { 0x0019, 0x0052, 0x0019, 0x0052, + EVR_LT, "CassetteSubmatrix", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS DLR.01" } + , { 0x0019, 0x0052, 0x0019, 0x0052, + EVR_SS, "SideOffset", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x0052, 0x0019, 0x0052, + EVR_SS, "ReconPostProcessingFlag", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x0052, 0x0019, 0x0052, + EVR_DS, "ReceiverPreamplifierGain", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 COAD" } + , { 0x0019, 0x0052, 0x0019, 0x0052, + EVR_SS, "TableTilt", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA GEN" } + , { 0x0019, 0x0052, 0x0019, 0x0052, + EVR_DS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CT VA0 COAD" } + , { 0x0019, 0x0052, 0x0019, 0x0052, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE B" } + , { 0x0019, 0x0053, 0x0019, 0x0053, + EVR_LT, "Barcode", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS DLR.01" } + , { 0x0019, 0x0054, 0x0019, 0x0054, + EVR_SS, "IsoCenterHeight", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x0054, 0x0019, 0x0054, + EVR_UN, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x0054, 0x0019, 0x0054, + EVR_DS, "ReceiverCableAttenuation", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 COAD" } + , { 0x0019, 0x0054, 0x0019, 0x0054, + EVR_SS, "TableAxisRotation", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA GEN" } + , { 0x0019, 0x0054, 0x0019, 0x0054, + EVR_DS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CT VA0 COAD" } + , { 0x0019, 0x0054, 0x0019, 0x0054, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE B" } + , { 0x0019, 0x0055, 0x0019, 0x0055, + EVR_DS, "ReceiverReferenceGain", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 COAD" } + , { 0x0019, 0x0056, 0x0019, 0x0056, + EVR_SS, "ImageTwist", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x0056, 0x0019, 0x0056, + EVR_DS, "ReceiverFilterFrequency", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 COAD" } + , { 0x0019, 0x0056, 0x0019, 0x0056, + EVR_SS, "TableLongitudalPosition", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA GEN" } + , { 0x0019, 0x0056, 0x0019, 0x0056, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE B" } + , { 0x0019, 0x0057, 0x0019, 0x0057, + EVR_SS, "CTWaterNumber", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x0058, 0x0019, 0x0058, + EVR_SS, "SourceImageDistance", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x0058, 0x0019, 0x0058, + EVR_SS, "CTBoneNumber", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x0058, 0x0019, 0x0058, + EVR_SS, "TableSideOffset", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA GEN" } + , { 0x0019, 0x0058, 0x0019, 0x0058, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE B" } + , { 0x0019, 0x005a, 0x0019, 0x005a, + EVR_SS, "MechanicalMagnificationFactor", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x005a, 0x0019, 0x005a, + EVR_FL, "AcquisitionDuration", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x005a, 0x0019, 0x005a, + EVR_SS, "TableIsoCenterHeight", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA GEN" } + , { 0x0019, 0x005a, 0x0019, 0x005a, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE B" } + , { 0x0019, 0x005c, 0x0019, 0x005c, + EVR_SL, "CalibrationFlag", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x005c, 0x0019, 0x005c, + EVR_UN, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA GEN" } + , { 0x0019, 0x005c, 0x0019, 0x005c, + EVR_US, "Unknown", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE B" } + , { 0x0019, 0x005d, 0x0019, 0x005d, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x005e, 0x0019, 0x005e, + EVR_SL, "CalibrationAngleCranCaud", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x005e, 0x0019, 0x005e, + EVR_SL, "NumberOfChannels1To512", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x005e, 0x0019, 0x005e, + EVR_SL, "CollimationDataValid", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA GEN" } + , { 0x0019, 0x005e, 0x0019, 0x005e, + EVR_US, "Unknown", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE B" } + , { 0x0019, 0x005f, 0x0019, 0x005f, + EVR_SL, "IncrementBetweenChannels", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x0060, 0x0019, 0x0060, + EVR_LT, "ContrastType", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS DLR.01" } + , { 0x0019, 0x0060, 0x0019, 0x0060, + EVR_SL, "CalibrationAngleRAOLAO", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x0060, 0x0019, 0x0060, + EVR_SL, "StartingView", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x0060, 0x0019, 0x0060, + EVR_DS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P-GV-CT Release 1" } + , { 0x0019, 0x0060, 0x0019, 0x0060, + EVR_US, "XrayTechnique", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1" } + , { 0x0019, 0x0060, 0x0019, 0x0060, + EVR_IS, "BuckyAngle", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SVISION" } + , { 0x0019, 0x0060, 0x0019, 0x0060, + EVR_DS, "ReconstructionScaleFactor", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 COAD" } + , { 0x0019, 0x0060, 0x0019, 0x0060, + EVR_SL, "PeriSequenceNo", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA GEN" } + , { 0x0019, 0x0060, 0x0019, 0x0060, + EVR_DS, "FocusAlignment", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CT VA0 COAD" } + , { 0x0019, 0x0060, 0x0019, 0x0060, + EVR_SH, "RadiographersCode", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "FDMS 1.0" } + , { 0x0019, 0x0060, 0x0019, 0x0060, + EVR_IS, "NumberOfDataBytes", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CM VA0 CMS" } + , { 0x0019, 0x0060, 0x0019, 0x0060, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR SPECTRO;1" } + , { 0x0019, 0x0060, 0x0019, 0x0060, + EVR_DS, "FlipAngle", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 GEN" } + , { 0x0019, 0x0060, 0x0019, 0x0060, + EVR_US, "Unknown", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE B" } + , { 0x0019, 0x0061, 0x0019, 0x0061, + EVR_LT, "RotationAmount", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS DLR.01" } + , { 0x0019, 0x0061, 0x0019, 0x0061, + EVR_SL, "NumberOfViews", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x0061, 0x0019, 0x0061, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P-GV-CT Release 1" } + , { 0x0019, 0x0061, 0x0019, 0x0061, + EVR_DS, "ImageIdentifierFromat", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1" } + , { 0x0019, 0x0061, 0x0019, 0x0061, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR SPECTRO;1" } + , { 0x0019, 0x0062, 0x0019, 0x0062, + EVR_LT, "RotationCenter", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS DLR.01" } + , { 0x0019, 0x0062, 0x0019, 0x0062, + EVR_SL, "CalibrationTableToFloorDist", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x0062, 0x0019, 0x0062, + EVR_SL, "IncrementBetweenViews", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x0062, 0x0019, 0x0062, + EVR_US, "IrisDiaphragm", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1" } + , { 0x0019, 0x0062, 0x0019, 0x0062, + EVR_IS, "NumberOfVirtuellChannels", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CT VA0 GEN" } + , { 0x0019, 0x0062, 0x0019, 0x0062, + EVR_DS, "ReferenceScaleFactor", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 COAD" } + , { 0x0019, 0x0062, 0x0019, 0x0062, + EVR_SL, "PeriTotalScenes", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA GEN" } + , { 0x0019, 0x0062, 0x0019, 0x0062, + EVR_US, "Unknown", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE B" } + , { 0x0019, 0x0063, 0x0019, 0x0063, + EVR_LT, "DensityShift", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS DLR.01" } + , { 0x0019, 0x0063, 0x0019, 0x0063, + EVR_LO, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P-GV-CT Release 1" } + , { 0x0019, 0x0063, 0x0019, 0x0063, + EVR_CS, "Filter", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1" } + , { 0x0019, 0x0064, 0x0019, 0x0064, + EVR_US, "FrequencyRank", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS DLR.01" } + , { 0x0019, 0x0064, 0x0019, 0x0064, + EVR_SL, "CalibrationIsocenterToFloorDist", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x0064, 0x0019, 0x0064, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P-GV-CT Release 1" } + , { 0x0019, 0x0064, 0x0019, 0x0064, + EVR_CS, "CineParallel", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1" } + , { 0x0019, 0x0064, 0x0019, 0x0064, + EVR_SL, "PeriOverlapTop", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA GEN" } + , { 0x0019, 0x0064, 0x0019, 0x0064, + EVR_US, "Unknown", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE B" } + , { 0x0019, 0x0065, 0x0019, 0x0065, + EVR_LT, "FrequencyEnhancement", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS DLR.01" } + , { 0x0019, 0x0065, 0x0019, 0x0065, + EVR_IS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P-GV-CT Release 1" } + , { 0x0019, 0x0065, 0x0019, 0x0065, + EVR_CS, "CineMaster", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1" } + , { 0x0019, 0x0065, 0x0019, 0x0065, + EVR_UL, "FocalSpotDeflectionAmplitude", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CT VA0 COAD" } + , { 0x0019, 0x0066, 0x0019, 0x0066, + EVR_LT, "FrequencyType", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS DLR.01" } + , { 0x0019, 0x0066, 0x0019, 0x0066, + EVR_SL, "CalibrationIsocenterToSourceDist", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x0066, 0x0019, 0x0066, + EVR_SL, "PeriOverlapBottom", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA GEN" } + , { 0x0019, 0x0066, 0x0019, 0x0066, + EVR_UL, "FocalSpotDeflectionPhase", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CT VA0 COAD" } + , { 0x0019, 0x0066, 0x0019, 0x0066, + EVR_US, "Unknown", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE B" } + , { 0x0019, 0x0067, 0x0019, 0x0067, + EVR_LT, "KernelLength", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS DLR.01" } + , { 0x0019, 0x0067, 0x0019, 0x0067, + EVR_UL, "FocalSpotDeflectionOffset", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CT VA0 COAD" } + , { 0x0019, 0x0068, 0x0019, 0x0068, + EVR_UL, "KernelMode", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS DLR.01" } + , { 0x0019, 0x0068, 0x0019, 0x0068, + EVR_SL, "CalibrationSourceToII", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x0068, 0x0019, 0x0068, + EVR_IS, "CArmAngle", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SVISION" } + , { 0x0019, 0x0068, 0x0019, 0x0068, + EVR_SL, "RawImageNumber", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA GEN" } + , { 0x0019, 0x0068, 0x0019, 0x0068, + EVR_US, "Unknown", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE B" } + , { 0x0019, 0x0069, 0x0019, 0x0069, + EVR_UL, "ConvolutionMode", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS DLR.01" } + , { 0x0019, 0x0069, 0x0019, 0x0069, + EVR_IS, "CollimatorAngle", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SVISION" } + , { 0x0019, 0x006a, 0x0019, 0x006a, + EVR_SL, "CalibrationIIZoom", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x006a, 0x0019, 0x006a, + EVR_SS, "DependantOnNumberOfViewsProcessed", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x006a, 0x0019, 0x006a, + EVR_SL, "XRayDataValid", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA GEN" } + , { 0x0019, 0x006a, 0x0019, 0x006a, + EVR_US, "Unknown", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE B" } + , { 0x0019, 0x006b, 0x0019, 0x006b, + EVR_SS, "FieldOfViewInDetectorCells", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x006c, 0x0019, 0x006c, + EVR_SL, "CalibrationIIField", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x006c, 0x0019, 0x006c, + EVR_US, "Unknown", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE B" } + , { 0x0019, 0x006e, 0x0019, 0x006e, + EVR_SL, "CalibrationFactor", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x006e, 0x0019, 0x006e, + EVR_US, "Unknown", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE B" } + , { 0x0019, 0x0070, 0x0019, 0x0070, + EVR_LT, "PLASource", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS DLR.01" } + , { 0x0019, 0x0070, 0x0019, 0x0070, + EVR_SL, "CalibrationObjectToImageDistance", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x0070, 0x0019, 0x0070, + EVR_UN, "RADProtocolPrinter", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "DIDI TO PCR 1.1" } + , { 0x0019, 0x0070, 0x0019, 0x0070, + EVR_SS, "ValueOfBackProjectionButton", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x0070, 0x0019, 0x0070, + EVR_LT, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P-GV-CT Release 1" } + , { 0x0019, 0x0070, 0x0019, 0x0070, + EVR_LO, "CRImageSerialNumber", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GE ??? From Adantage Review CS" } + , { 0x0019, 0x0070, 0x0019, 0x0070, + EVR_US, "ExposureChannel", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1" } + , { 0x0019, 0x0070, 0x0019, 0x0070, + EVR_IS, "FilterNumber", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SVISION" } + , { 0x0019, 0x0070, 0x0019, 0x0070, + EVR_IS, "NumberOfReadings", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CT VA0 GEN" } + , { 0x0019, 0x0070, 0x0019, 0x0070, + EVR_DS, "PhaseGradientAmplitude", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 COAD" } + , { 0x0019, 0x0070, 0x0019, 0x0070, + EVR_US, "Unknown", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA GEN" } + , { 0x0019, 0x0070, 0x0019, 0x0070, + EVR_DS, "WaterScalingFactor", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CT VA0 COAD" } + , { 0x0019, 0x0070, 0x0019, 0x0070, + EVR_IS, "SplitExposureFormat", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "FDMS 1.0" } + , { 0x0019, 0x0070, 0x0019, 0x0070, + EVR_UN, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR SPECTRO;1" } + , { 0x0019, 0x0070, 0x0019, 0x0070, + EVR_IS, "NumberOfPrescans", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 GEN" } + , { 0x0019, 0x0070, 0x0019, 0x0070, + EVR_US, "Unknown", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE B" } + , { 0x0019, 0x0071, 0x0019, 0x0071, + EVR_LT, "PLADestination", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS DLR.01" } + , { 0x0019, 0x0071, 0x0019, 0x0071, + EVR_UN, "RADProtocolMedium", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "DIDI TO PCR 1.1" } + , { 0x0019, 0x0071, 0x0019, 0x0071, + EVR_SS, "SetIfFatqEstimatesWereUsed", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x0071, 0x0019, 0x0071, + EVR_UN, "ExposureChannelFirstImage", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1" } + , { 0x0019, 0x0071, 0x0019, 0x0071, + EVR_LT, "Unknown", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CT VA0 GEN" } + , { 0x0019, 0x0071, 0x0019, 0x0071, + EVR_DS, "ReadoutGradientAmplitude", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 COAD" } + , { 0x0019, 0x0071, 0x0019, 0x0071, + EVR_DS, "InterpolationFactor", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CT VA0 COAD" } + , { 0x0019, 0x0071, 0x0019, 0x0071, + EVR_IS, "NoOfSplitExposureFrames", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "FDMS 1.0" } + , { 0x0019, 0x0071, 0x0019, 0x0071, + EVR_IS, "Unknown", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR SPECTRO;1" } + , { 0x0019, 0x0072, 0x0019, 0x0072, + EVR_SL, "CalibrationSystemFactor", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x0072, 0x0019, 0x0072, + EVR_DS, "ZChannelAvgOverViews", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x0072, 0x0019, 0x0072, + EVR_US, "ProcessingChannel", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1" } + , { 0x0019, 0x0072, 0x0019, 0x0072, + EVR_DS, "SelectionGradientAmplitude", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 COAD" } + , { 0x0019, 0x0072, 0x0019, 0x0072, + EVR_US, "Unknown", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA GEN" } + , { 0x0019, 0x0072, 0x0019, 0x0072, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR SPECTRO;1" } + , { 0x0019, 0x0072, 0x0019, 0x0072, + EVR_UN, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE B" } + , { 0x0019, 0x0073, 0x0019, 0x0073, + EVR_DS, "AvgOfLeftRefChannelsOverViews", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x0073, 0x0019, 0x0073, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR SPECTRO;1" } + , { 0x0019, 0x0074, 0x0019, 0x0074, + EVR_SL, "CalibrationSystemCorrection", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x0074, 0x0019, 0x0074, + EVR_DS, "MaxLeftChannelOverViews", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x0074, 0x0019, 0x0074, + EVR_LO, "FilterMaterial1", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SVISION" } + , { 0x0019, 0x0074, 0x0019, 0x0074, + EVR_IS, "NumberOfProjections", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CT VA0 GEN" } + , { 0x0019, 0x0074, 0x0019, 0x0074, + EVR_US, "Unknown", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA GEN" } + , { 0x0019, 0x0074, 0x0019, 0x0074, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR SPECTRO;1" } + , { 0x0019, 0x0074, 0x0019, 0x0074, + EVR_UN, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE B" } + , { 0x0019, 0x0075, 0x0019, 0x0075, + EVR_LT, "UIDOriginalImage", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS DLR.01" } + , { 0x0019, 0x0075, 0x0019, 0x0075, + EVR_DS, "AvgOfRightRefChannelsOverViews", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x0075, 0x0019, 0x0075, + EVR_LO, "FilterMaterial2", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SVISION" } + , { 0x0019, 0x0075, 0x0019, 0x0075, + EVR_IS, "NumberOfBytes", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CT VA0 GEN" } + , { 0x0019, 0x0076, 0x0019, 0x0076, + EVR_LT, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS DLR.01" } + , { 0x0019, 0x0076, 0x0019, 0x0076, + EVR_SL, "CalibrationSystemIIFormats", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x0076, 0x0019, 0x0076, + EVR_DS, "MaxRightChannelOverViews", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x0076, 0x0019, 0x0076, + EVR_SL, "FillingAverageFactor", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA GEN" } + , { 0x0019, 0x0076, 0x0019, 0x0076, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR SPECTRO;1" } + , { 0x0019, 0x0076, 0x0019, 0x0076, + EVR_UN, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE B" } + , { 0x0019, 0x0077, 0x0019, 0x0077, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR SPECTRO;1" } + , { 0x0019, 0x0078, 0x0019, 0x0078, + EVR_SL, "CalibrationGantryDataValid", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x0078, 0x0019, 0x0078, + EVR_DS, "FilterThickness1", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SVISION" } + , { 0x0019, 0x0078, 0x0019, 0x0078, + EVR_US, "Unknown", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA GEN" } + , { 0x0019, 0x0078, 0x0019, 0x0078, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR SPECTRO;1" } + , { 0x0019, 0x0078, 0x0019, 0x0078, + EVR_US, "Unknown", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE B" } + , { 0x0019, 0x0079, 0x0019, 0x0079, + EVR_DS, "FilterThickness2", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SVISION" } + , { 0x0019, 0x0079, 0x0019, 0x0079, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR SPECTRO;1" } + , { 0x0019, 0x007a, 0x0019, 0x007a, + EVR_SS, "CollimatorSquareBreadth", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x007a, 0x0019, 0x007a, + EVR_US, "Unknown", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA GEN" } + , { 0x0019, 0x007a, 0x0019, 0x007a, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE B" } + , { 0x0019, 0x007c, 0x0019, 0x007c, + EVR_SS, "CollimatorSquareHeight", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x007c, 0x0019, 0x007c, + EVR_US, "Unknown", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA GEN" } + , { 0x0019, 0x007c, 0x0019, 0x007c, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE B" } + , { 0x0019, 0x007d, 0x0019, 0x007d, + EVR_DS, "SecondEcho", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x007e, 0x0019, 0x007e, + EVR_SS, "CollimatorSquareDiameter", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x007e, 0x0019, 0x007e, + EVR_SS, "NumberOfEchos", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x007e, 0x0019, 0x007e, + EVR_US, "Unknown", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA GEN" } + , { 0x0019, 0x007e, 0x0019, 0x007e, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE B" } + , { 0x0019, 0x007f, 0x0019, 0x007f, + EVR_DS, "TableDelta", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x0080, 0x0019, 0x0080, + EVR_SS, "CollimaterFingerTurnAngle", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x0080, 0x0019, 0x0080, + EVR_LO, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P-GV-CT Release 1" } + , { 0x0019, 0x0080, 0x0019, 0x0080, + EVR_DS, "AcquisitionDelay", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1" } + , { 0x0019, 0x0080, 0x0019, 0x0080, + EVR_IS, "BuckyFormat", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SVISION" } + , { 0x0019, 0x0080, 0x0019, 0x0080, + EVR_LO, "CRBarCodeNumber", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GE ??? From Adantage Review CS" } + , { 0x0019, 0x0080, 0x0019, 0x0080, + EVR_DS, "GradientDelayTime", 3, 3, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 COAD" } + , { 0x0019, 0x0080, 0x0019, 0x0080, + EVR_LT, "ReconstructionAlgorithmSet", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CT VA0 GEN" } + , { 0x0019, 0x0080, 0x0019, 0x0080, + EVR_LT, "PatientRegion", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CT VA0 COAD" } + , { 0x0019, 0x0080, 0x0019, 0x0080, + EVR_US, "Unknown", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA GEN" } + , { 0x0019, 0x0080, 0x0019, 0x0080, + EVR_IS, "ReadingPositionSpecification", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "FDMS 1.0" } + , { 0x0019, 0x0080, 0x0019, 0x0080, + EVR_IS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR SPECTRO;1" } + , { 0x0019, 0x0080, 0x0019, 0x0080, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE B" } + , { 0x0019, 0x0080, 0x0019, 0x0080, + EVR_LT, "ReaderHeader", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS DLR.01" } + , { 0x0019, 0x0081, 0x0019, 0x0081, + EVR_SS, "Contiguous", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x0081, 0x0019, 0x0081, + EVR_LO, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P-GV-CT Release 1" } + , { 0x0019, 0x0081, 0x0019, 0x0081, + EVR_UN, "RelativeImageTime", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1" } + , { 0x0019, 0x0081, 0x0019, 0x0081, + EVR_IS, "ObjectPosition", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SVISION" } + , { 0x0019, 0x0081, 0x0019, 0x0081, + EVR_LT, "ReconstructionAlgorithmIndex", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CT VA0 GEN" } + , { 0x0019, 0x0081, 0x0019, 0x0081, + EVR_IS, "ReadingSensitivityCenter", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "FDMS 1.0" } + , { 0x0019, 0x0081, 0x0019, 0x0081, + EVR_LT, "FilterTypeForRawData", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 GEN" } + , { 0x0019, 0x0082, 0x0019, 0x0082, + EVR_SS, "CollimaterFingerPosition", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x0082, 0x0019, 0x0082, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x0082, 0x0019, 0x0082, + EVR_DS, "TotalGradientDelayTime", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 COAD" } + , { 0x0019, 0x0082, 0x0019, 0x0082, + EVR_LT, "RegenerationSoftwareVersion", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CT VA0 GEN" } + , { 0x0019, 0x0082, 0x0019, 0x0082, + EVR_LT, "PatientPhaseOfLife", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CT VA0 COAD" } + , { 0x0019, 0x0082, 0x0019, 0x0082, + EVR_US, "Unknown", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA GEN" } + , { 0x0019, 0x0082, 0x0019, 0x0082, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE B" } + , { 0x0019, 0x0082, 0x0019, 0x0082, + EVR_DS, "FilterParameterForRawData", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 GEN" } + , { 0x0019, 0x0083, 0x0019, 0x0083, + EVR_DS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x0083, 0x0019, 0x0083, + EVR_LT, "FilterTypeForImageData", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 GEN" } + , { 0x0019, 0x0084, 0x0019, 0x0084, + EVR_SS, "CollimaterDiaphragmTurnAngle", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x0084, 0x0019, 0x0084, + EVR_DS, "PeakSAR", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x0084, 0x0019, 0x0084, + EVR_US, "Unknown", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA GEN" } + , { 0x0019, 0x0084, 0x0019, 0x0084, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE B" } + , { 0x0019, 0x0084, 0x0019, 0x0084, + EVR_DS, "FilterParameterForImageData", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 GEN" } + , { 0x0019, 0x0085, 0x0019, 0x0085, + EVR_SS, "MonitorSAR", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x0085, 0x0019, 0x0085, + EVR_LT, "FilterTypeForPhaseCorrection", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 GEN" } + , { 0x0019, 0x0086, 0x0019, 0x0086, + EVR_SS, "CollimaterDiaphragmPosition1", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x0086, 0x0019, 0x0086, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x0086, 0x0019, 0x0086, + EVR_US, "Unknown", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA GEN" } + , { 0x0019, 0x0086, 0x0019, 0x0086, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE B" } + , { 0x0019, 0x0086, 0x0019, 0x0086, + EVR_DS, "FilterParameterForPhaseCorrection", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 GEN" } + , { 0x0019, 0x0087, 0x0019, 0x0087, + EVR_DS, "CardiacRepetitionTime", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x0087, 0x0019, 0x0087, + EVR_LT, "NormalizationFilterTypeForImageData", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 GEN" } + , { 0x0019, 0x0088, 0x0019, 0x0088, + EVR_SS, "CollimaterDiaphragmPosition2", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x0088, 0x0019, 0x0088, + EVR_SS, "ImagesPerCardiacCycle", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x0088, 0x0019, 0x0088, + EVR_DS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CT VA0 GEN" } + , { 0x0019, 0x0088, 0x0019, 0x0088, + EVR_US, "Unknown", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA GEN" } + , { 0x0019, 0x0088, 0x0019, 0x0088, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE B" } + , { 0x0019, 0x0088, 0x0019, 0x0088, + EVR_DS, "NormalizationFilterParameterForImageData", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 GEN" } + , { 0x0019, 0x008a, 0x0019, 0x008a, + EVR_SS, "CollimaterDiaphragmMode", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x008a, 0x0019, 0x008a, + EVR_SS, "ActualReceiveGainAnalog", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x008a, 0x0019, 0x008a, + EVR_US, "Unknown", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA GEN" } + , { 0x0019, 0x008a, 0x0019, 0x008a, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE B" } + , { 0x0019, 0x008b, 0x0019, 0x008b, + EVR_SS, "ActualReceiveGainDigital", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x008c, 0x0019, 0x008c, + EVR_SS, "CollimaterBeamLimitBreadth", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x008c, 0x0019, 0x008c, + EVR_US, "Unknown", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA GEN" } + , { 0x0019, 0x008c, 0x0019, 0x008c, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE B" } + , { 0x0019, 0x008d, 0x0019, 0x008d, + EVR_DS, "DelayAfterTrigger", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x008e, 0x0019, 0x008e, + EVR_SS, "CollimaterBeamLimitHeight", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x008e, 0x0019, 0x008e, + EVR_US, "Unknown", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA GEN" } + , { 0x0019, 0x008e, 0x0019, 0x008e, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE B" } + , { 0x0019, 0x008f, 0x0019, 0x008f, + EVR_SS, "SwapPhaseFrequency", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GE_GENESIS_REV3.0" } + , { 0x0019, 0x008f, 0x0019, 0x008f, + EVR_SS, "SwapPhaseFrequency", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x0090, 0x0019, 0x0090, + EVR_SS, "CollimaterBeamLimitDiameter", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x0090, 0x0019, 0x0090, + EVR_LO, "UnprocessedFlag", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "DIDI TO PCR 1.1" } + , { 0x0019, 0x0090, 0x0019, 0x0090, + EVR_SS, "PauseInterval", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x0090, 0x0019, 0x0090, + EVR_LO, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P-GV-CT Release 1" } + , { 0x0019, 0x0090, 0x0019, 0x0090, + EVR_CS, "VideoWhiteCompression", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1" } + , { 0x0019, 0x0090, 0x0019, 0x0090, + EVR_LO, "CRFilmOutputExposures", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GE ??? From Adantage Review CS" } + , { 0x0019, 0x0090, 0x0019, 0x0090, + EVR_LO, "DeskCommand", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SVISION" } + , { 0x0019, 0x0090, 0x0019, 0x0090, + EVR_LT, "SensitivityCorrectionLabel", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 COAD" } + , { 0x0019, 0x0090, 0x0019, 0x0090, + EVR_DS, "OsteoOffset", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CT VA0 COAD" } + , { 0x0019, 0x0090, 0x0019, 0x0090, + EVR_SH, "FilmAnnotationCharacterString1", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "FDMS 1.0" } + , { 0x0019, 0x0090, 0x0019, 0x0090, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE B" } + , { 0x0019, 0x0090, 0x0019, 0x0090, + EVR_IS, "NumberOfSaturationRegions", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 GEN" } + , { 0x0019, 0x0090, 0x0019, 0x0090, + EVR_LT, "PLAOfSecondaryDestination", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS DLR.01" } + , { 0x0019, 0x0091, 0x0019, 0x0091, + EVR_UN, "KeyValues", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "DIDI TO PCR 1.1" } + , { 0x0019, 0x0091, 0x0019, 0x0091, + EVR_DS, "PulseTime", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x0091, 0x0019, 0x0091, + EVR_DS, "SaturationPhaseEncodingVectorCoronalComponent", 6, 6, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 COAD" } + , { 0x0019, 0x0091, 0x0019, 0x0091, + EVR_SH, "FilmAnnotationCharacterString2", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "FDMS 1.0" } + , { 0x0019, 0x0091, 0x0019, 0x0091, + EVR_DS, "SaturationPhaseEncodingVectorSagittalComponent", 6, 6, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 GEN" } + , { 0x0019, 0x0092, 0x0019, 0x0092, + EVR_SS, "X-RayControlMOde", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x0092, 0x0019, 0x0092, + EVR_UN, "DestinationPostprocessingFunction", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "DIDI TO PCR 1.1" } + , { 0x0019, 0x0092, 0x0019, 0x0092, + EVR_SL, "SliceOffsetOnFrequencyAxis", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x0092, 0x0019, 0x0092, + EVR_DS, "SaturationReadoutVectorCoronalComponent", 6, 6, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 COAD" } + , { 0x0019, 0x0092, 0x0019, 0x0092, + EVR_DS, "OsteoRegressionLineSlope", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CT VA0 COAD" } + , { 0x0019, 0x0092, 0x0019, 0x0092, + EVR_US, "Unknown", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA GEN" } + , { 0x0019, 0x0092, 0x0019, 0x0092, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE B" } + , { 0x0019, 0x0092, 0x0019, 0x0092, + EVR_DS, "SaturationReadoutVectorSagittalComponent", 6, 6, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 GEN" } + , { 0x0019, 0x0093, 0x0019, 0x0093, + EVR_DS, "CenterFrequency", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x0093, 0x0019, 0x0093, + EVR_DS, "OsteoRegressionLineIntercept", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CT VA0 COAD" } + , { 0x0019, 0x0093, 0x0019, 0x0093, + EVR_DS, "EPIStimulationMonitorMode", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 GEN" } + , { 0x0019, 0x0094, 0x0019, 0x0094, + EVR_SS, "X-RaySystem", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x0094, 0x0019, 0x0094, + EVR_SS, "TransmitGain", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x0094, 0x0019, 0x0094, + EVR_DS, "OsteoStandardizationCode", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CT VA0 COAD" } + , { 0x0019, 0x0094, 0x0019, 0x0094, + EVR_US, "Unknown", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA GEN" } + , { 0x0019, 0x0094, 0x0019, 0x0094, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE B" } + , { 0x0019, 0x0094, 0x0019, 0x0094, + EVR_DS, "ImageRotationAngle", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 GEN" } + , { 0x0019, 0x0095, 0x0019, 0x0095, + EVR_SS, "AnalogReceiverGain", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x0096, 0x0019, 0x0096, + EVR_SS, "FocalSpot", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x0096, 0x0019, 0x0096, + EVR_SS, "DigitalReceiverGain", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x0096, 0x0019, 0x0096, + EVR_IS, "OsteoPhantomNumber", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CT VA0 COAD" } + , { 0x0019, 0x0096, 0x0019, 0x0096, + EVR_US, "Unknown", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA GEN" } + , { 0x0019, 0x0096, 0x0019, 0x0096, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE B" } + , { 0x0019, 0x0096, 0x0019, 0x0096, + EVR_UL, "CoilIDMask", 3, 3, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 GEN" } + , { 0x0019, 0x0097, 0x0019, 0x0097, + EVR_SL, "BitmapDefiningCVs", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x0097, 0x0019, 0x0097, + EVR_UL, "CoilClassMask", 2, 2, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 GEN" } + , { 0x0019, 0x0098, 0x0019, 0x0098, + EVR_SS, "ExposureControl", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x0098, 0x0019, 0x0098, + EVR_SS, "CenterFrequencyMethod", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x0098, 0x0019, 0x0098, + EVR_US, "Unknown", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA GEN" } + , { 0x0019, 0x0098, 0x0019, 0x0098, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE B" } + , { 0x0019, 0x0098, 0x0019, 0x0098, + EVR_DS, "CoilPosition", 3, 3, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 GEN" } + , { 0x0019, 0x0099, 0x0019, 0x0099, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x009a, 0x0019, 0x009a, + EVR_SL, "XRayVoltage", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x009a, 0x0019, 0x009a, + EVR_US, "Unknown", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA GEN" } + , { 0x0019, 0x009a, 0x0019, 0x009a, + EVR_US, "Unknown", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE B" } + , { 0x0019, 0x009b, 0x0019, 0x009b, + EVR_SS, "PulseSequenceMode", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x009c, 0x0019, 0x009c, + EVR_SL, "XRayCurrent", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x009c, 0x0019, 0x009c, + EVR_SS, "PulseSequenceName", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GE_GENESIS_REV3.0" } + , { 0x0019, 0x009c, 0x0019, 0x009c, + EVR_LO, "PulseSequenceName", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x009c, 0x0019, 0x009c, + EVR_SL, "IntensifierLevelCalibrationFactor", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA GEN" } + , { 0x0019, 0x009c, 0x0019, 0x009c, + EVR_US, "Unknown", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE B" } + , { 0x0019, 0x009d, 0x0019, 0x009d, + EVR_DT, "PulseSequenceDate", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x009e, 0x0019, 0x009e, + EVR_SL, "XRayCurrentTimeProduct", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x009e, 0x0019, 0x009e, + EVR_LO, "InternalPulseSequenceName", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x009e, 0x0019, 0x009e, + EVR_SL, "NativeReviewFlag", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA GEN" } + , { 0x0019, 0x009e, 0x0019, 0x009e, + EVR_US, "Unknown", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE B" } + , { 0x0019, 0x009f, 0x0019, 0x009f, + EVR_SS, "CoilType", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GE_GENESIS_REV3.0" } + , { 0x0019, 0x009f, 0x0019, 0x009f, + EVR_SS, "TransmittingCoil", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x00a0, 0x0019, 0x00a0, + EVR_SL, "XRayPulseTime", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x00a0, 0x0019, 0x00a0, + EVR_UN, "Version", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "DIDI TO PCR 1.1" } + , { 0x0019, 0x00a0, 0x0019, 0x00a0, + EVR_SS, "SurfaceCoilType", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x00a0, 0x0019, 0x00a0, + EVR_LO, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P-GV-CT Release 1" } + , { 0x0019, 0x00a0, 0x0019, 0x00a0, + EVR_DS, "ExtendedExposureTime", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SVISION" } + , { 0x0019, 0x00a0, 0x0019, 0x00a0, + EVR_US, "Angulation", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1" } + , { 0x0019, 0x00a0, 0x0019, 0x00a0, + EVR_US, "RFWatchdogMask", 3, 3, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 COAD" } + , { 0x0019, 0x00a0, 0x0019, 0x00a0, + EVR_US, "Unknown", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE B" } + , { 0x0019, 0x00a0, 0x0019, 0x00a0, + EVR_DS, "EPIReconstructionPhase", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 GEN" } + , { 0x0019, 0x00a0, 0x0019, 0x00a0, + EVR_DS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS DLR.01" } + , { 0x0019, 0x00a1, 0x0019, 0x00a1, + EVR_UN, "RangingMode", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "DIDI TO PCR 1.1" } + , { 0x0019, 0x00a1, 0x0019, 0x00a1, + EVR_SS, "ExtremityCoilFlag", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x00a1, 0x0019, 0x00a1, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P-GV-CT Release 1" } + , { 0x0019, 0x00a1, 0x0019, 0x00a1, + EVR_DS, "ActualExposureTime", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SVISION" } + , { 0x0019, 0x00a1, 0x0019, 0x00a1, + EVR_US, "Rotation", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1" } + , { 0x0019, 0x00a1, 0x0019, 0x00a1, + EVR_DS, "EPIReconstructionSlope", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 COAD" } + , { 0x0019, 0x00a1, 0x0019, 0x00a1, + EVR_DS, "EPIReconstructionSlope", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 GEN" } + , { 0x0019, 0x00a1, 0x0019, 0x00a1, + EVR_DS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS DLR.01" } + , { 0x0019, 0x00a2, 0x0019, 0x00a2, + EVR_SL, "XRaySceneTimeFluoroClock", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x00a2, 0x0019, 0x00a2, + EVR_UN, "AbdomenBrightness", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "DIDI TO PCR 1.1" } + , { 0x0019, 0x00a2, 0x0019, 0x00a2, + EVR_SL, "RawDataRunNumber", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x00a2, 0x0019, 0x00a2, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P-GV-CT Release 1" } + , { 0x0019, 0x00a2, 0x0019, 0x00a2, + EVR_DS, "RFPowerErrorIndicator", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 COAD" } + , { 0x0019, 0x00a2, 0x0019, 0x00a2, + EVR_SL, "SceneNumber", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA GEN" } + , { 0x0019, 0x00a2, 0x0019, 0x00a2, + EVR_US, "Unknown", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE B" } + , { 0x0019, 0x00a3, 0x0019, 0x00a3, + EVR_UN, "FixedBrightness", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "DIDI TO PCR 1.1" } + , { 0x0019, 0x00a3, 0x0019, 0x00a3, + EVR_UL, "CalibratedFieldStrength", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x00a3, 0x0019, 0x00a3, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P-GV-CT Release 1" } + , { 0x0019, 0x00a3, 0x0019, 0x00a3, + EVR_US, "Unknown", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CT VA0 COAD" } + , { 0x0019, 0x00a4, 0x0019, 0x00a4, + EVR_SS, "MaximumPulseRate", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x00a4, 0x0019, 0x00a4, + EVR_SS, "SATFatWaterBone", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GE_GENESIS_REV3.0" } + , { 0x0019, 0x00a4, 0x0019, 0x00a4, + EVR_UN, "DetailContrast", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "DIDI TO PCR 1.1" } + , { 0x0019, 0x00a4, 0x0019, 0x00a4, + EVR_SS, "SATFatWaterBone", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x00a4, 0x0019, 0x00a4, + EVR_DS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CT VA0 COAD" } + , { 0x0019, 0x00a4, 0x0019, 0x00a4, + EVR_SS, "AcquisitionMode", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA GEN" } + , { 0x0019, 0x00a4, 0x0019, 0x00a4, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE B" } + , { 0x0019, 0x00a5, 0x0019, 0x00a5, + EVR_UN, "ContrastBalance", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "DIDI TO PCR 1.1" } + , { 0x0019, 0x00a5, 0x0019, 0x00a5, + EVR_DS, "ReceiveBandwidth", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x00a5, 0x0019, 0x00a5, + EVR_DS, "SpecificAbsorptionRateWholeBody", 3, 3, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 COAD" } + , { 0x0019, 0x00a5, 0x0019, 0x00a5, + EVR_DS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CT VA0 COAD" } + , { 0x0019, 0x00a5, 0x0019, 0x00a5, + EVR_SS, "AcquisitonFrameRate", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA GEN" } + , { 0x0019, 0x00a6, 0x0019, 0x00a6, + EVR_SS, "PulsesPerScene", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x00a6, 0x0019, 0x00a6, + EVR_UN, "StructureBoost", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "DIDI TO PCR 1.1" } + , { 0x0019, 0x00a6, 0x0019, 0x00a6, + EVR_DS, "SpecificEnergyDose", 3, 3, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 COAD" } + , { 0x0019, 0x00a6, 0x0019, 0x00a6, + EVR_US, "Unknown", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CT VA0 COAD" } + , { 0x0019, 0x00a6, 0x0019, 0x00a6, + EVR_SL, "ECGFlag", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA GEN" } + , { 0x0019, 0x00a6, 0x0019, 0x00a6, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE B" } + , { 0x0019, 0x00a7, 0x0019, 0x00a7, + EVR_UN, "StructurePreference", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "DIDI TO PCR 1.1" } + , { 0x0019, 0x00a7, 0x0019, 0x00a7, + EVR_DS, "UserData", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x00a7, 0x0019, 0x00a7, + EVR_US, "Unknown", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CT VA0 COAD" } + , { 0x0019, 0x00a7, 0x0019, 0x00a7, + EVR_SL, "AdditionalSceneData", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA GEN" } + , { 0x0019, 0x00a8, 0x0019, 0x00a8, + EVR_SL, "DoseAreaProductOfScene", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x00a8, 0x0019, 0x00a8, + EVR_UN, "NoiseRobustness", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "DIDI TO PCR 1.1" } + , { 0x0019, 0x00a8, 0x0019, 0x00a8, + EVR_DS, "UserData", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x00a8, 0x0019, 0x00a8, + EVR_DS, "ExtendedXRayTubeCurrent", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SVISION" } + , { 0x0019, 0x00a8, 0x0019, 0x00a8, + EVR_US, "Unknown", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CT VA0 COAD" } + , { 0x0019, 0x00a8, 0x0019, 0x00a8, + EVR_SL, "FileCopyFlag", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA GEN" } + , { 0x0019, 0x00a8, 0x0019, 0x00a8, + EVR_US, "Unknown", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE B" } + , { 0x0019, 0x00a9, 0x0019, 0x00a9, + EVR_UN, "NoiseDoseLimit", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "DIDI TO PCR 1.1" } + , { 0x0019, 0x00a9, 0x0019, 0x00a9, + EVR_DS, "UserData", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x00a9, 0x0019, 0x00a9, + EVR_DS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CT VA0 COAD" } + , { 0x0019, 0x00a9, 0x0019, 0x00a9, + EVR_SL, "PhlebovisionFlag", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA GEN" } + , { 0x0019, 0x00aa, 0x0019, 0x00aa, + EVR_SS, "Dose", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x00aa, 0x0019, 0x00aa, + EVR_UN, "NoiseDoseStep", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "DIDI TO PCR 1.1" } + , { 0x0019, 0x00aa, 0x0019, 0x00aa, + EVR_DS, "UserData", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x00aa, 0x0019, 0x00aa, + EVR_LT, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CT VA0 COAD" } + , { 0x0019, 0x00aa, 0x0019, 0x00aa, + EVR_SL, "Co2Flag", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA GEN" } + , { 0x0019, 0x00aa, 0x0019, 0x00aa, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE B" } + , { 0x0019, 0x00ab, 0x0019, 0x00ab, + EVR_UN, "NoiseFrequencyLimit", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "DIDI TO PCR 1.1" } + , { 0x0019, 0x00ab, 0x0019, 0x00ab, + EVR_DS, "UserData", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x00ab, 0x0019, 0x00ab, + EVR_DS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CT VA0 COAD" } + , { 0x0019, 0x00ab, 0x0019, 0x00ab, + EVR_SS, "MaxSpeed", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA GEN" } + , { 0x0019, 0x00ac, 0x0019, 0x00ac, + EVR_SS, "DoseRate", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x00ac, 0x0019, 0x00ac, + EVR_UN, "WeakContrastLimit", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "DIDI TO PCR 1.1" } + , { 0x0019, 0x00ac, 0x0019, 0x00ac, + EVR_DS, "UserData", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x00ac, 0x0019, 0x00ac, + EVR_DS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CT VA0 COAD" } + , { 0x0019, 0x00ac, 0x0019, 0x00ac, + EVR_SS, "StepWidth", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA GEN" } + , { 0x0019, 0x00ac, 0x0019, 0x00ac, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE B" } + , { 0x0019, 0x00ad, 0x0019, 0x00ad, + EVR_UN, "StrongContrastLimit", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "DIDI TO PCR 1.1" } + , { 0x0019, 0x00ad, 0x0019, 0x00ad, + EVR_DS, "UserData", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x00ad, 0x0019, 0x00ad, + EVR_DS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CT VA0 COAD" } + , { 0x0019, 0x00ad, 0x0019, 0x00ad, + EVR_SL, "DigitalAcquisitionZoom", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA GEN" } + , { 0x0019, 0x00ae, 0x0019, 0x00ae, + EVR_SL, "IIToCoverDistance", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x00ae, 0x0019, 0x00ae, + EVR_UN, "StructureBoostOffset", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "DIDI TO PCR 1.1" } + , { 0x0019, 0x00ae, 0x0019, 0x00ae, + EVR_DS, "UserData", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x00ae, 0x0019, 0x00ae, + EVR_DS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CT VA0 COAD" } + , { 0x0019, 0x00af, 0x0019, 0x00af, + EVR_UN, "SmoothGain", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "DIDI TO PCR 1.1" } + , { 0x0019, 0x00af, 0x0019, 0x00af, + EVR_DS, "UserData", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x00af, 0x0019, 0x00af, + EVR_DS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CT VA0 COAD" } + , { 0x0019, 0x00b0, 0x0019, 0x00b0, + EVR_SS, "LastFramePhase1", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x00b0, 0x0019, 0x00b0, + EVR_UN, "MeasureField1", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "DIDI TO PCR 1.1" } + , { 0x0019, 0x00b0, 0x0019, 0x00b0, + EVR_DS, "UserData", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x00b0, 0x0019, 0x00b0, + EVR_LO, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P-GV-CT Release 1" } + , { 0x0019, 0x00b0, 0x0019, 0x00b0, + EVR_UL, "AdjustmentStatusMask", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 COAD" } + , { 0x0019, 0x00b0, 0x0019, 0x00b0, + EVR_DS, "FeedPerRotation", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CT VA0 COAD" } + , { 0x0019, 0x00b1, 0x0019, 0x00b1, + EVR_SS, "FrameRatePhase1", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x00b1, 0x0019, 0x00b1, + EVR_IS, "MinimumRRInterval", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/LAST" } + , { 0x0019, 0x00b1, 0x0019, 0x00b1, + EVR_UN, "MeasureField2", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "DIDI TO PCR 1.1" } + , { 0x0019, 0x00b1, 0x0019, 0x00b1, + EVR_DS, "UserData", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x00b1, 0x0019, 0x00b1, + EVR_LO, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P-GV-CT Release 1" } + , { 0x0019, 0x00b2, 0x0019, 0x00b2, + EVR_SS, "LastFramePhase2", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x00b2, 0x0019, 0x00b2, + EVR_IS, "MaximumRRInterval", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/LAST" } + , { 0x0019, 0x00b2, 0x0019, 0x00b2, + EVR_UN, "KeyPercentile1", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "DIDI TO PCR 1.1" } + , { 0x0019, 0x00b2, 0x0019, 0x00b2, + EVR_DS, "UserData", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x00b3, 0x0019, 0x00b3, + EVR_SS, "FrameRatePhase2", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x00b3, 0x0019, 0x00b3, + EVR_IS, "NumberOfRejections", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/LAST" } + , { 0x0019, 0x00b3, 0x0019, 0x00b3, + EVR_UN, "KeyPercentile2", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "DIDI TO PCR 1.1" } + , { 0x0019, 0x00b3, 0x0019, 0x00b3, + EVR_DS, "UserData", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x00b4, 0x0019, 0x00b4, + EVR_SS, "LastFramePhase3", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x00b4, 0x0019, 0x00b4, + EVR_IS, "NumberOfRRIntervals", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/LAST" } + , { 0x0019, 0x00b4, 0x0019, 0x00b4, + EVR_UN, "DensityLUT", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "DIDI TO PCR 1.1" } + , { 0x0019, 0x00b4, 0x0019, 0x00b4, + EVR_DS, "UserData", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x00b5, 0x0019, 0x00b5, + EVR_SS, "FrameRatePhase3", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x00b5, 0x0019, 0x00b5, + EVR_IS, "ArrhythmiaRejection", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/LAST" } + , { 0x0019, 0x00b5, 0x0019, 0x00b5, + EVR_UN, "Brightness", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "DIDI TO PCR 1.1" } + , { 0x0019, 0x00b5, 0x0019, 0x00b5, + EVR_DS, "UserData", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x00b6, 0x0019, 0x00b6, + EVR_SS, "LastFramePhase4", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x00b6, 0x0019, 0x00b6, + EVR_UN, "Gamma", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "DIDI TO PCR 1.1" } + , { 0x0019, 0x00b6, 0x0019, 0x00b6, + EVR_DS, "UserData", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x00b7, 0x0019, 0x00b7, + EVR_SS, "FrameRatePhase4", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x00b7, 0x0019, 0x00b7, + EVR_DS, "UserData", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x00b8, 0x0019, 0x00b8, + EVR_SS, "GammaOfNativeImage", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x00b8, 0x0019, 0x00b8, + EVR_DS, "UserData", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x00b9, 0x0019, 0x00b9, + EVR_SS, "GammaOfTVSystem", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x00b9, 0x0019, 0x00b9, + EVR_DS, "UserData", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x00ba, 0x0019, 0x00ba, + EVR_DS, "UserData", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x00bb, 0x0019, 0x00bb, + EVR_SL, "PixelshiftX", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x00bb, 0x0019, 0x00bb, + EVR_DS, "UserData", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x00bc, 0x0019, 0x00bc, + EVR_SL, "PixelshiftY", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x00bc, 0x0019, 0x00bc, + EVR_DS, "UserData", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x00bd, 0x0019, 0x00bd, + EVR_SL, "MaskAverageFactor", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x00bd, 0x0019, 0x00bd, + EVR_DS, "UserData", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x00bd, 0x0019, 0x00bd, + EVR_IS, "PulmoTriggerLevel", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CT VA0 COAD" } + , { 0x0019, 0x00be, 0x0019, 0x00be, + EVR_SL, "BlankingCircleFlag", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x00be, 0x0019, 0x00be, + EVR_DS, "ProjectionAngle", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x00be, 0x0019, 0x00be, + EVR_DS, "ExpiratoricReserveVolume", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CT VA0 COAD" } + , { 0x0019, 0x00bf, 0x0019, 0x00bf, + EVR_SL, "CircleRowStart", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x00bf, 0x0019, 0x00bf, + EVR_DS, "VitalCapacity", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CT VA0 COAD" } + , { 0x0019, 0x00c0, 0x0019, 0x00c0, + EVR_DS, "Unknown", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/LAST" } + , { 0x0019, 0x00c0, 0x0019, 0x00c0, + EVR_SL, "CircleRowEnd", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x00c0, 0x0019, 0x00c0, + EVR_SS, "BitmapOfSATSelections", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GE_GENESIS_REV3.0" } + , { 0x0019, 0x00c0, 0x0019, 0x00c0, + EVR_SS, "SaturationPlanes", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x00c0, 0x0019, 0x00c0, + EVR_DS, "PulmoWater", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CT VA0 COAD" } + , { 0x0019, 0x00c1, 0x0019, 0x00c1, + EVR_SL, "CircleColumnStart", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x00c1, 0x0019, 0x00c1, + EVR_SS, "SurfaceCoilIntensityCorrectionFlag", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GE_GENESIS_REV3.0" } + , { 0x0019, 0x00c1, 0x0019, 0x00c1, + EVR_SS, "SurfaceCoilIntensityCorrectionFlag", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x00c1, 0x0019, 0x00c1, + EVR_DS, "EPICapacity", 6, 6, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 COAD" } + , { 0x0019, 0x00c1, 0x0019, 0x00c1, + EVR_DS, "PulmoAir", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CT VA0 COAD" } + , { 0x0019, 0x00c2, 0x0019, 0x00c2, + EVR_SL, "CircleColumnEnd", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x00c2, 0x0019, 0x00c2, + EVR_SS, "SATLocationR", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x00c2, 0x0019, 0x00c2, + EVR_DS, "EPIInductance", 3, 3, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 COAD" } + , { 0x0019, 0x00c2, 0x0019, 0x00c2, + EVR_DA, "PulmoDate", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CT VA0 COAD" } + , { 0x0019, 0x00c3, 0x0019, 0x00c3, + EVR_SL, "CircleDiameter", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x00c3, 0x0019, 0x00c3, + EVR_SS, "SATLocationL", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x00c3, 0x0019, 0x00c3, + EVR_IS, "EPISwitchConfigurationCode", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 COAD" } + , { 0x0019, 0x00c3, 0x0019, 0x00c3, + EVR_TM, "PulmoTime", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CT VA0 COAD" } + , { 0x0019, 0x00c4, 0x0019, 0x00c4, + EVR_SL, "RectangularCollimaterFlag", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x00c4, 0x0019, 0x00c4, + EVR_SS, "SATLocationA", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x00c4, 0x0019, 0x00c4, + EVR_IS, "EPISwitchHardwareCode", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 COAD" } + , { 0x0019, 0x00c5, 0x0019, 0x00c5, + EVR_SL, "RectangleRowStart", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x00c5, 0x0019, 0x00c5, + EVR_SS, "SATLocationP", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x00c5, 0x0019, 0x00c5, + EVR_DS, "EPISwitchDelayTime", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 COAD" } + , { 0x0019, 0x00c6, 0x0019, 0x00c6, + EVR_IS, "CycledMultipleSlice", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/LAST" } + , { 0x0019, 0x00c6, 0x0019, 0x00c6, + EVR_SL, "RectangleRowEnd", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x00c6, 0x0019, 0x00c6, + EVR_SS, "SATLocationH", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x00c7, 0x0019, 0x00c7, + EVR_SL, "RectangleColumnStart", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x00c7, 0x0019, 0x00c7, + EVR_SS, "SATLocationF", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x00c8, 0x0019, 0x00c8, + EVR_SL, "RectangleColumnEnd", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x00c8, 0x0019, 0x00c8, + EVR_SS, "SATThicknessRL", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x00c9, 0x0019, 0x00c9, + EVR_SL, "RectangleAngulation", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x00c9, 0x0019, 0x00c9, + EVR_SS, "SATThicknessAP", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x00ca, 0x0019, 0x00ca, + EVR_SL, "IrisCollimatorFlag", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x00ca, 0x0019, 0x00ca, + EVR_SS, "SATThicknessHF", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x00cb, 0x0019, 0x00cb, + EVR_SL, "IrisRowStart", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x00cb, 0x0019, 0x00cb, + EVR_SS, "PhaseContrastFlowAxis", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GE_GENESIS_REV3.0" } + , { 0x0019, 0x00cb, 0x0019, 0x00cb, + EVR_SS, "PrescribedFlowAxis", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x00cc, 0x0019, 0x00cc, + EVR_SL, "IrisRowEnd", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x00cc, 0x0019, 0x00cc, + EVR_SS, "PhaseContrastVelocityEncoding", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GE_GENESIS_REV3.0" } + , { 0x0019, 0x00cc, 0x0019, 0x00cc, + EVR_SS, "VelocityEncoding", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x00cd, 0x0019, 0x00cd, + EVR_SL, "IrisColumnStart", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x00cd, 0x0019, 0x00cd, + EVR_SS, "ThicknessDisclaimer", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x00ce, 0x0019, 0x00ce, + EVR_IS, "REST", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/LAST" } + , { 0x0019, 0x00ce, 0x0019, 0x00ce, + EVR_SL, "IrisColumnEnd", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x00ce, 0x0019, 0x00ce, + EVR_SS, "PrescanType", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x00cf, 0x0019, 0x00cf, + EVR_SL, "IrisAngulation", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x00cf, 0x0019, 0x00cf, + EVR_SS, "PrescanStatus", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x00d0, 0x0019, 0x00d0, + EVR_SH, "RawDataType", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x00d1, 0x0019, 0x00d1, + EVR_SS, "NumberOfFramesPlane", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x00d1, 0x0019, 0x00d1, + EVR_DS, "FlowSensitivity", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 COAD" } + , { 0x0019, 0x00d2, 0x0019, 0x00d2, + EVR_SS, "Internal", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x00d2, 0x0019, 0x00d2, + EVR_SS, "ProjectionAlgorithm", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x00d2, 0x0019, 0x00d2, + EVR_LT, "CalculationSubmode", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 COAD" } + , { 0x0019, 0x00d3, 0x0019, 0x00d3, + EVR_SS, "Internal", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x00d3, 0x0019, 0x00d3, + EVR_SH, "ProjectionAlgorithm", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x00d3, 0x0019, 0x00d3, + EVR_DS, "FieldOfViewRatio", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 COAD" } + , { 0x0019, 0x00d4, 0x0019, 0x00d4, + EVR_SS, "Internal", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x00d4, 0x0019, 0x00d4, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x00d4, 0x0019, 0x00d4, + EVR_IS, "BaseRawMatrixSize", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 COAD" } + , { 0x0019, 0x00d5, 0x0019, 0x00d5, + EVR_DS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/LAST" } + , { 0x0019, 0x00d5, 0x0019, 0x00d5, + EVR_SS, "Internal", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x00d5, 0x0019, 0x00d5, + EVR_SS, "FractionalEcho", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GE_GENESIS_REV3.0" } + , { 0x0019, 0x00d5, 0x0019, 0x00d5, + EVR_SS, "FractionalEcho", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x00d5, 0x0019, 0x00d5, + EVR_IS, "2DOversamplingLines", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 COAD" } + , { 0x0019, 0x00d6, 0x0019, 0x00d6, + EVR_IS, "FourierInterpolation", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/LAST" } + , { 0x0019, 0x00d6, 0x0019, 0x00d6, + EVR_SS, "Internal", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x00d6, 0x0019, 0x00d6, + EVR_SS, "PrepPulse", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x00d6, 0x0019, 0x00d6, + EVR_IS, "3DPhaseOversamplingPartitions", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 COAD" } + , { 0x0019, 0x00d7, 0x0019, 0x00d7, + EVR_SS, "Internal", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x00d7, 0x0019, 0x00d7, + EVR_SS, "CardiacPhases", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x00d7, 0x0019, 0x00d7, + EVR_IS, "EchoLinePosition", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 COAD" } + , { 0x0019, 0x00d8, 0x0019, 0x00d8, + EVR_SS, "Internal", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x00d8, 0x0019, 0x00d8, + EVR_SS, "VariableEchoFlag", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GE_GENESIS_REV3.0" } + , { 0x0019, 0x00d8, 0x0019, 0x00d8, + EVR_SS, "VariableEchoFlag", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x00d8, 0x0019, 0x00d8, + EVR_IS, "EchoColumnPosition", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 COAD" } + , { 0x0019, 0x00d9, 0x0019, 0x00d9, + EVR_IS, "Unknown", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/LAST" } + , { 0x0019, 0x00d9, 0x0019, 0x00d9, + EVR_SS, "Internal", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x00d9, 0x0019, 0x00d9, + EVR_DS, "ConcatenatedSat", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GE_GENESIS_REV3.0" } + , { 0x0019, 0x00d9, 0x0019, 0x00d9, + EVR_DS, "ConcatenatedSAT", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x00d9, 0x0019, 0x00d9, + EVR_IS, "LinesPerSegment", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 COAD" } + , { 0x0019, 0x00da, 0x0019, 0x00da, + EVR_SS, "Internal", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x00da, 0x0019, 0x00da, + EVR_SS, "ReferenceChannelUsed", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x00da, 0x0019, 0x00da, + EVR_LT, "PhaseCodingDirection", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 COAD" } + , { 0x0019, 0x00db, 0x0019, 0x00db, + EVR_SS, "Internal", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x00db, 0x0019, 0x00db, + EVR_DS, "BackProjectorCoefficient", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x00dc, 0x0019, 0x00dc, + EVR_SS, "Internal", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x00dc, 0x0019, 0x00dc, + EVR_SS, "PrimarySpeedCorrectionUsed", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x00dd, 0x0019, 0x00dd, + EVR_SL, "AnatomicBackground", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x00dd, 0x0019, 0x00dd, + EVR_SS, "OverrangeCorrectionUsed", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x00de, 0x0019, 0x00de, + EVR_SL, "AutoWindowBase", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x00de, 0x0019, 0x00de, + EVR_DS, "DynamicZAlphaValue", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x00df, 0x0019, 0x00df, + EVR_SS, "Internal", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x00df, 0x0019, 0x00df, + EVR_DS, "UserData", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x00e0, 0x0019, 0x00e0, + EVR_IS, "Prepulse", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/LAST" } + , { 0x0019, 0x00e0, 0x0019, 0x00e0, + EVR_SL, "Internal", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA PLANE A" } + , { 0x0019, 0x00e0, 0x0019, 0x00e0, + EVR_DS, "UserData", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x00e1, 0x0019, 0x00e1, + EVR_DS, "PrepulseDelay", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/LAST" } + , { 0x0019, 0x00e1, 0x0019, 0x00e1, + EVR_DS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x00e2, 0x0019, 0x00e2, + EVR_IS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/LAST" } + , { 0x0019, 0x00e2, 0x0019, 0x00e2, + EVR_DS, "VelocityEncodeScale", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x00e3, 0x0019, 0x00e3, + EVR_DS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/LAST" } + , { 0x0019, 0x00e3, 0x0019, 0x00e3, + EVR_LT, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x00e4, 0x0019, 0x00e4, + EVR_LT, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x00e5, 0x0019, 0x00e5, + EVR_IS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x00e6, 0x0019, 0x00e6, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x00e8, 0x0019, 0x00e8, + EVR_DS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x00e9, 0x0019, 0x00e9, + EVR_DS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x00eb, 0x0019, 0x00eb, + EVR_DS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x00ec, 0x0019, 0x00ec, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x00f0, 0x0019, 0x00f0, + EVR_LT, "WSProtocolString1", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/LAST" } + , { 0x0019, 0x00f0, 0x0019, 0x00f0, + EVR_UN, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x00f1, 0x0019, 0x00f1, + EVR_LT, "WSProtocolString2", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/LAST" } + , { 0x0019, 0x00f1, 0x0019, 0x00f1, + EVR_LT, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x00f2, 0x0019, 0x00f2, + EVR_LT, "WSProtocolString3", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/LAST" } + , { 0x0019, 0x00f2, 0x0019, 0x00f2, + EVR_SS, "NumberOfPhases", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GE_GENESIS_REV3.0" } + , { 0x0019, 0x00f2, 0x0019, 0x00f2, + EVR_SS, "FastPhases", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x00f3, 0x0019, 0x00f3, + EVR_LT, "WSProtocolString4", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/LAST" } + , { 0x0019, 0x00f3, 0x0019, 0x00f3, + EVR_LT, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x00f4, 0x0019, 0x00f4, + EVR_LT, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x00f9, 0x0019, 0x00f9, + EVR_DS, "TransmitGain", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACQU_01" } + , { 0x0019, 0x00ff, 0x0019, 0x00ff, + EVR_SS, "Internal", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA GEN" } + , { 0x0019, 0x1000, 0x0019, 0x1000, + EVR_DS, "FieldOfView", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR R5.5/PART" } + , { 0x0019, 0x1000, 0x0019, 0x1000, + EVR_DS, "FieldOfView", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR R5.6/PART" } + , { 0x0019, 0x1000, 0x0019, 0x1000, + EVR_DS, "FieldOfView", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/PART" } + , { 0x0019, 0x1005, 0x0019, 0x1005, + EVR_DS, "CCAngulation", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/PART" } + , { 0x0019, 0x1006, 0x0019, 0x1006, + EVR_DS, "APAngulation", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/PART" } + , { 0x0019, 0x1007, 0x0019, 0x1007, + EVR_DS, "LRAngulation", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/PART" } + , { 0x0019, 0x1008, 0x0019, 0x1008, + EVR_IS, "PatientPosition", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/PART" } + , { 0x0019, 0x1009, 0x0019, 0x1009, + EVR_IS, "PatientOrientation", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/PART" } + , { 0x0019, 0x100a, 0x0019, 0x100a, + EVR_IS, "SliceOrientation", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/PART" } + , { 0x0019, 0x100b, 0x0019, 0x100b, + EVR_DS, "LROffcenter", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/PART" } + , { 0x0019, 0x100c, 0x0019, 0x100c, + EVR_DS, "CCOffcenter", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/PART" } + , { 0x0019, 0x100d, 0x0019, 0x100d, + EVR_DS, "APOffcenter", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/PART" } + , { 0x0019, 0x100e, 0x0019, 0x100e, + EVR_DS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/PART" } + , { 0x0019, 0x100f, 0x0019, 0x100f, + EVR_IS, "NumberOfSlices", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/PART" } + , { 0x0019, 0x1010, 0x0019, 0x1010, + EVR_DS, "SliceFactor", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/PART" } + , { 0x0019, 0x1011, 0x0019, 0x1011, + EVR_DS, "EchoTimes", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/PART" } + , { 0x0019, 0x1015, 0x0019, 0x1015, + EVR_IS, "DynamicStudy", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/PART" } + , { 0x0019, 0x1018, 0x0019, 0x1018, + EVR_DS, "HeartbeatInterval", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/PART" } + , { 0x0019, 0x1019, 0x0019, 0x1019, + EVR_DS, "RepetitionTimeFFE", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/PART" } + , { 0x0019, 0x101a, 0x0019, 0x101a, + EVR_DS, "FFEFlipAngle", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/PART" } + , { 0x0019, 0x101b, 0x0019, 0x101b, + EVR_IS, "NumberOfScans", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/PART" } + , { 0x0019, 0x1021, 0x0019, 0x1021, + EVR_DS, "Unknown", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/PART" } + , { 0x0019, 0x1022, 0x0019, 0x1022, + EVR_DS, "DynamicScanTimeBegin", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/PART" } + , { 0x0019, 0x1024, 0x0019, 0x1024, + EVR_IS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/PART" } + , { 0x0019, 0x1064, 0x0019, 0x1064, + EVR_DS, "RepetitionTimeSE", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/PART" } + , { 0x0019, 0x1065, 0x0019, 0x1065, + EVR_DS, "RepetitionTimeIR", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/PART" } + , { 0x0019, 0x1069, 0x0019, 0x1069, + EVR_IS, "NumberOfPhases", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/PART" } + , { 0x0019, 0x106a, 0x0019, 0x106a, + EVR_IS, "CardiacFrequency", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/PART" } + , { 0x0019, 0x106b, 0x0019, 0x106b, + EVR_DS, "InversionDelay", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/PART" } + , { 0x0019, 0x106c, 0x0019, 0x106c, + EVR_DS, "GateDelay", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/PART" } + , { 0x0019, 0x106d, 0x0019, 0x106d, + EVR_DS, "GateWidth", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/PART" } + , { 0x0019, 0x106e, 0x0019, 0x106e, + EVR_DS, "TriggerDelayTime", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/PART" } + , { 0x0019, 0x1080, 0x0019, 0x1080, + EVR_IS, "NumberOfChemicalShifts", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/PART" } + , { 0x0019, 0x1081, 0x0019, 0x1081, + EVR_DS, "ChemicalShift", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/PART" } + , { 0x0019, 0x1084, 0x0019, 0x1084, + EVR_IS, "NumberOfRows", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/PART" } + , { 0x0019, 0x1085, 0x0019, 0x1085, + EVR_IS, "NumberOfSamples", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/PART" } + , { 0x0019, 0x1094, 0x0019, 0x1094, + EVR_LO, "MagnetizationTransferContrast", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/PART" } + , { 0x0019, 0x1095, 0x0019, 0x1095, + EVR_LO, "SpectralPresaturationWithInversionRecovery", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/PART" } + , { 0x0019, 0x1096, 0x0019, 0x1096, + EVR_IS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/PART" } + , { 0x0019, 0x1097, 0x0019, 0x1097, + EVR_LO, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/PART" } + , { 0x0019, 0x10a0, 0x0019, 0x10a0, + EVR_IS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/PART" } + , { 0x0019, 0x10a1, 0x0019, 0x10a1, + EVR_DS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/PART" } + , { 0x0019, 0x10a3, 0x0019, 0x10a3, + EVR_DS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/PART" } + , { 0x0019, 0x10a4, 0x0019, 0x10a4, + EVR_CS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/PART" } + , { 0x0019, 0x10c8, 0x0019, 0x10c8, + EVR_IS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/PART" } + , { 0x0019, 0x10c9, 0x0019, 0x10c9, + EVR_IS, "FoldoverDirectionTransverse", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/PART" } + , { 0x0019, 0x10ca, 0x0019, 0x10ca, + EVR_IS, "FoldoverDirectionSagittal", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/PART" } + , { 0x0019, 0x10cb, 0x0019, 0x10cb, + EVR_IS, "FoldoverDirectionCoronal", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/PART" } + , { 0x0019, 0x10cc, 0x0019, 0x10cc, + EVR_IS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/PART" } + , { 0x0019, 0x10cd, 0x0019, 0x10cd, + EVR_IS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/PART" } + , { 0x0019, 0x10ce, 0x0019, 0x10ce, + EVR_IS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/PART" } + , { 0x0019, 0x10cf, 0x0019, 0x10cf, + EVR_IS, "NumberOfEchoes", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/PART" } + , { 0x0019, 0x10d0, 0x0019, 0x10d0, + EVR_IS, "ScanResolution", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/PART" } + , { 0x0019, 0x10d2, 0x0019, 0x10d2, + EVR_LO, "WaterFatShift", 2, 2, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/PART" } + , { 0x0019, 0x10d4, 0x0019, 0x10d4, + EVR_IS, "ArtifactReduction", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/PART" } + , { 0x0019, 0x10d5, 0x0019, 0x10d5, + EVR_IS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/PART" } + , { 0x0019, 0x10d6, 0x0019, 0x10d6, + EVR_IS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/PART" } + , { 0x0019, 0x10d7, 0x0019, 0x10d7, + EVR_DS, "ScanPercentage", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/PART" } + , { 0x0019, 0x10d8, 0x0019, 0x10d8, + EVR_IS, "Halfscan", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/PART" } + , { 0x0019, 0x10d9, 0x0019, 0x10d9, + EVR_IS, "EPIFactor", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/PART" } + , { 0x0019, 0x10da, 0x0019, 0x10da, + EVR_IS, "TurboFactor", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/PART" } + , { 0x0019, 0x10db, 0x0019, 0x10db, + EVR_IS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/PART" } + , { 0x0019, 0x10e0, 0x0019, 0x10e0, + EVR_IS, "PercentageOfScanCompleted", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/PART" } + , { 0x0019, 0x10e1, 0x0019, 0x10e1, + EVR_IS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/PART" } + , { 0x0019, 0x1100, 0x0019, 0x1100, + EVR_IS, "NumberOfStacks", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/PART" } + , { 0x0019, 0x1101, 0x0019, 0x1101, + EVR_IS, "StackType", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/PART" } + , { 0x0019, 0x1102, 0x0019, 0x1102, + EVR_IS, "Unknown", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/PART" } + , { 0x0019, 0x110b, 0x0019, 0x110b, + EVR_DS, "LROffcenter", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/PART" } + , { 0x0019, 0x110c, 0x0019, 0x110c, + EVR_DS, "CCOffcenter", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/PART" } + , { 0x0019, 0x110d, 0x0019, 0x110d, + EVR_DS, "APOffcenter", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/PART" } + , { 0x0019, 0x1145, 0x0019, 0x1145, + EVR_IS, "ReconstructionResolution", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/PART" } + , { 0x0019, 0x11fc, 0x0019, 0x11fc, + EVR_IS, "ResonanceFrequency", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/PART" } + , { 0x0019, 0x12c0, 0x0019, 0x12c0, + EVR_DS, "TriggerDelayTimes", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/PART" } + , { 0x0019, 0x12e0, 0x0019, 0x12e0, + EVR_IS, "PrepulseType", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/PART" } + , { 0x0019, 0x12e1, 0x0019, 0x12e1, + EVR_DS, "PrepulseDelay", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/PART" } + , { 0x0019, 0x12e3, 0x0019, 0x12e3, + EVR_DS, "PhaseContrastVelocity", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/PART" } +#endif + , { 0x0020, 0x000d, 0x0020, 0x000d, + EVR_UI, "StudyInstanceUID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x000e, 0x0020, 0x000e, + EVR_UI, "SeriesInstanceUID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x0010, 0x0020, 0x0010, + EVR_SH, "StudyID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x0011, 0x0020, 0x0011, + EVR_IS, "SeriesNumber", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x0012, 0x0020, 0x0012, + EVR_IS, "AcquisitionNumber", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x0013, 0x0020, 0x0013, + EVR_IS, "InstanceNumber", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x0014, 0x0020, 0x0014, + EVR_IS, "RETIRED_IsotopeNumber", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x0015, 0x0020, 0x0015, + EVR_IS, "RETIRED_PhaseNumber", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x0016, 0x0020, 0x0016, + EVR_IS, "RETIRED_IntervalNumber", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x0017, 0x0020, 0x0017, + EVR_IS, "RETIRED_TimeSlotNumber", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x0018, 0x0020, 0x0018, + EVR_IS, "RETIRED_AngleNumber", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x0019, 0x0020, 0x0019, + EVR_IS, "ItemNumber", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x0020, 0x0020, 0x0020, + EVR_CS, "PatientOrientation", 2, 2, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x0022, 0x0020, 0x0022, + EVR_IS, "RETIRED_OverlayNumber", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x0024, 0x0020, 0x0024, + EVR_IS, "RETIRED_CurveNumber", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x0026, 0x0020, 0x0026, + EVR_IS, "RETIRED_LUTNumber", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x0030, 0x0020, 0x0030, + EVR_DS, "RETIRED_ImagePosition", 3, 3, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x0032, 0x0020, 0x0032, + EVR_DS, "ImagePositionPatient", 3, 3, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x0035, 0x0020, 0x0035, + EVR_DS, "RETIRED_ImageOrientation", 6, 6, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x0037, 0x0020, 0x0037, + EVR_DS, "ImageOrientationPatient", 6, 6, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x0050, 0x0020, 0x0050, + EVR_DS, "RETIRED_Location", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x0052, 0x0020, 0x0052, + EVR_UI, "FrameOfReferenceUID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x0060, 0x0020, 0x0060, + EVR_CS, "Laterality", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x0062, 0x0020, 0x0062, + EVR_CS, "ImageLaterality", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x0070, 0x0020, 0x0070, + EVR_LO, "RETIRED_ImageGeometryType", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x0080, 0x0020, 0x0080, + EVR_CS, "RETIRED_MaskingImage", 1, -1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x00aa, 0x0020, 0x00aa, + EVR_IS, "RETIRED_ReportNumber", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x0100, 0x0020, 0x0100, + EVR_IS, "TemporalPositionIdentifier", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x0105, 0x0020, 0x0105, + EVR_IS, "NumberOfTemporalPositions", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x0110, 0x0020, 0x0110, + EVR_DS, "TemporalResolution", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x0200, 0x0020, 0x0200, + EVR_UI, "SynchronizationFrameOfReferenceUID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x0242, 0x0020, 0x0242, + EVR_UI, "SOPInstanceUIDOfConcatenationSource", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x1000, 0x0020, 0x1000, + EVR_IS, "RETIRED_SeriesInStudy", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x1001, 0x0020, 0x1001, + EVR_IS, "RETIRED_AcquisitionsInSeries", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x1002, 0x0020, 0x1002, + EVR_IS, "ImagesInAcquisition", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x1003, 0x0020, 0x1003, + EVR_IS, "RETIRED_ImagesInSeries", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x1004, 0x0020, 0x1004, + EVR_IS, "RETIRED_AcquisitionsInStudy", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x1005, 0x0020, 0x1005, + EVR_IS, "RETIRED_ImagesInStudy", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x1020, 0x0020, 0x1020, + EVR_LO, "RETIRED_Reference", 1, -1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x1040, 0x0020, 0x1040, + EVR_LO, "PositionReferenceIndicator", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x1041, 0x0020, 0x1041, + EVR_DS, "SliceLocation", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x1070, 0x0020, 0x1070, + EVR_IS, "RETIRED_OtherStudyNumbers", 1, -1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x1200, 0x0020, 0x1200, + EVR_IS, "NumberOfPatientRelatedStudies", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x1202, 0x0020, 0x1202, + EVR_IS, "NumberOfPatientRelatedSeries", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x1204, 0x0020, 0x1204, + EVR_IS, "NumberOfPatientRelatedInstances", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x1206, 0x0020, 0x1206, + EVR_IS, "NumberOfStudyRelatedSeries", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x1208, 0x0020, 0x1208, + EVR_IS, "NumberOfStudyRelatedInstances", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x1209, 0x0020, 0x1209, + EVR_IS, "NumberOfSeriesRelatedInstances", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x3401, 0x0020, 0x3401, + EVR_CS, "RETIRED_ModifyingDeviceID", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x3402, 0x0020, 0x3402, + EVR_CS, "RETIRED_ModifiedImageID", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x3403, 0x0020, 0x3403, + EVR_DA, "RETIRED_ModifiedImageDate", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x3404, 0x0020, 0x3404, + EVR_LO, "RETIRED_ModifyingDeviceManufacturer", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x3405, 0x0020, 0x3405, + EVR_TM, "RETIRED_ModifiedImageTime", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x3406, 0x0020, 0x3406, + EVR_LO, "RETIRED_ModifiedImageDescription", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x4000, 0x0020, 0x4000, + EVR_LT, "ImageComments", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x5000, 0x0020, 0x5000, + EVR_AT, "RETIRED_OriginalImageIdentification", 1, -1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x5002, 0x0020, 0x5002, + EVR_LO, "RETIRED_OriginalImageIdentificationNomenclature", 1, -1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x9056, 0x0020, 0x9056, + EVR_SH, "StackID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x9057, 0x0020, 0x9057, + EVR_UL, "InStackPositionNumber", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x9071, 0x0020, 0x9071, + EVR_SQ, "FrameAnatomySequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x9072, 0x0020, 0x9072, + EVR_CS, "FrameLaterality", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x9111, 0x0020, 0x9111, + EVR_SQ, "FrameContentSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x9113, 0x0020, 0x9113, + EVR_SQ, "PlanePositionSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x9116, 0x0020, 0x9116, + EVR_SQ, "PlaneOrientationSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x9128, 0x0020, 0x9128, + EVR_UL, "TemporalPositionIndex", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x9153, 0x0020, 0x9153, + EVR_FD, "NominalCardiacTriggerDelayTime", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x9154, 0x0020, 0x9154, + EVR_FL, "NominalCardiacTriggerTimePriorToRPeak", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x9155, 0x0020, 0x9155, + EVR_FL, "ActualCardiacTriggerTimePriorToRPeak", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x9156, 0x0020, 0x9156, + EVR_US, "FrameAcquisitionNumber", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x9157, 0x0020, 0x9157, + EVR_UL, "DimensionIndexValues", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x9158, 0x0020, 0x9158, + EVR_LT, "FrameComments", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x9161, 0x0020, 0x9161, + EVR_UI, "ConcatenationUID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x9162, 0x0020, 0x9162, + EVR_US, "InConcatenationNumber", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x9163, 0x0020, 0x9163, + EVR_US, "InConcatenationTotalNumber", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x9164, 0x0020, 0x9164, + EVR_UI, "DimensionOrganizationUID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x9165, 0x0020, 0x9165, + EVR_AT, "DimensionIndexPointer", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x9167, 0x0020, 0x9167, + EVR_AT, "FunctionalGroupPointer", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x9170, 0x0020, 0x9170, + EVR_SQ, "UnassignedSharedConvertedAttributesSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x9171, 0x0020, 0x9171, + EVR_SQ, "UnassignedPerFrameConvertedAttributesSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x9172, 0x0020, 0x9172, + EVR_SQ, "ConversionSourceAttributesSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x9213, 0x0020, 0x9213, + EVR_LO, "DimensionIndexPrivateCreator", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x9221, 0x0020, 0x9221, + EVR_SQ, "DimensionOrganizationSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x9222, 0x0020, 0x9222, + EVR_SQ, "DimensionIndexSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x9228, 0x0020, 0x9228, + EVR_UL, "ConcatenationFrameOffsetNumber", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x9238, 0x0020, 0x9238, + EVR_LO, "FunctionalGroupPrivateCreator", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x9241, 0x0020, 0x9241, + EVR_FL, "NominalPercentageOfCardiacPhase", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x9245, 0x0020, 0x9245, + EVR_FL, "NominalPercentageOfRespiratoryPhase", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x9246, 0x0020, 0x9246, + EVR_FL, "StartingRespiratoryAmplitude", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x9247, 0x0020, 0x9247, + EVR_CS, "StartingRespiratoryPhase", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x9248, 0x0020, 0x9248, + EVR_FL, "EndingRespiratoryAmplitude", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x9249, 0x0020, 0x9249, + EVR_CS, "EndingRespiratoryPhase", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x9250, 0x0020, 0x9250, + EVR_CS, "RespiratoryTriggerType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x9251, 0x0020, 0x9251, + EVR_FD, "RRIntervalTimeNominal", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x9252, 0x0020, 0x9252, + EVR_FD, "ActualCardiacTriggerDelayTime", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x9253, 0x0020, 0x9253, + EVR_SQ, "RespiratorySynchronizationSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x9254, 0x0020, 0x9254, + EVR_FD, "RespiratoryIntervalTime", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x9255, 0x0020, 0x9255, + EVR_FD, "NominalRespiratoryTriggerDelayTime", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x9256, 0x0020, 0x9256, + EVR_FD, "RespiratoryTriggerDelayThreshold", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x9257, 0x0020, 0x9257, + EVR_FD, "ActualRespiratoryTriggerDelayTime", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x9301, 0x0020, 0x9301, + EVR_FD, "ImagePositionVolume", 3, 3, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x9302, 0x0020, 0x9302, + EVR_FD, "ImageOrientationVolume", 6, 6, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x9307, 0x0020, 0x9307, + EVR_CS, "UltrasoundAcquisitionGeometry", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x9308, 0x0020, 0x9308, + EVR_FD, "ApexPosition", 3, 3, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x9309, 0x0020, 0x9309, + EVR_FD, "VolumeToTransducerMappingMatrix", 16, 16, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x930a, 0x0020, 0x930a, + EVR_FD, "VolumeToTableMappingMatrix", 16, 16, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x930b, 0x0020, 0x930b, + EVR_CS, "VolumeToTransducerRelationship", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x930c, 0x0020, 0x930c, + EVR_CS, "PatientFrameOfReferenceSource", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x930d, 0x0020, 0x930d, + EVR_FD, "TemporalPositionTimeOffset", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x930e, 0x0020, 0x930e, + EVR_SQ, "PlanePositionVolumeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x930f, 0x0020, 0x930f, + EVR_SQ, "PlaneOrientationVolumeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x9310, 0x0020, 0x9310, + EVR_SQ, "TemporalPositionSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x9311, 0x0020, 0x9311, + EVR_CS, "DimensionOrganizationType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x9312, 0x0020, 0x9312, + EVR_UI, "VolumeFrameOfReferenceUID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x9313, 0x0020, 0x9313, + EVR_UI, "TableFrameOfReferenceUID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x9421, 0x0020, 0x9421, + EVR_LO, "DimensionDescriptionLabel", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x9450, 0x0020, 0x9450, + EVR_SQ, "PatientOrientationInFrameSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x9453, 0x0020, 0x9453, + EVR_LO, "FrameLabel", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x9518, 0x0020, 0x9518, + EVR_US, "AcquisitionIndex", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x9529, 0x0020, 0x9529, + EVR_SQ, "ContributingSOPInstancesReferenceSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x9536, 0x0020, 0x9536, + EVR_US, "ReconstructionIndex", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } +#ifdef ENABLE_PRIVATE_TAGS + , { 0x0021, 0x0000, 0x0021, 0x0000, + EVR_IS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/LAST" } + , { 0x0021, 0x0000, 0x0021, 0x0000, + EVR_LT, "WindowOfImagesID", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P-Private-CWS Release 1" } + , { 0x0021, 0x0000, 0x0021, 0x0000, + EVR_DS, "NoiseReduction", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SVISION" } + , { 0x0021, 0x0000, 0x0021, 0x0000, + EVR_LT, "SequenceType", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 RAW" } + , { 0x0021, 0x0000, 0x0021, 0x0000, + EVR_US, "AcquisitionType", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS SMS-AX ACQ 1.0" } + , { 0x0021, 0x0001, 0x0021, 0x0001, + EVR_CS, "WindowOfImagesType", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P-Private-CWS Release 1" } + , { 0x0021, 0x0001, 0x0021, 0x0001, + EVR_IS, "ReconstructionNumber", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS-MR-1" } + , { 0x0021, 0x0001, 0x0021, 0x0001, + EVR_DS, "ContrastAmplification", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SVISION" } + , { 0x0021, 0x0001, 0x0021, 0x0001, + EVR_US, "Unknown", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "TOSHIBA_MEC_1.0" } + , { 0x0021, 0x0001, 0x0021, 0x0001, + EVR_IS, "VectorSizeOriginal", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 RAW" } + , { 0x0021, 0x0001, 0x0021, 0x0001, + EVR_US, "AcquisitionMode", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS SMS-AX ACQ 1.0" } + , { 0x0021, 0x0002, 0x0021, 0x0002, + EVR_IS, "WindowOfImagesScope", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P-Private-CWS Release 1" } + , { 0x0021, 0x0002, 0x0021, 0x0002, + EVR_IS, "SliceNumber", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS-MR-1" } + , { 0x0021, 0x0002, 0x0021, 0x0002, + EVR_DS, "EdgeContrastBoosting", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SVISION" } + , { 0x0021, 0x0002, 0x0021, 0x0002, + EVR_US, "Unknown", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "TOSHIBA_MEC_1.0" } + , { 0x0021, 0x0002, 0x0021, 0x0002, + EVR_IS, "VectorSizeExtended", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 RAW" } + , { 0x0021, 0x0002, 0x0021, 0x0002, + EVR_US, "FootswitchIndex", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS SMS-AX ACQ 1.0" } + , { 0x0021, 0x0003, 0x0021, 0x0003, + EVR_SS, "SeriesFromWhichPrescribed", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_RELA_01" } + , { 0x0021, 0x0003, 0x0021, 0x0003, + EVR_DS, "LatitudeReduction", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SVISION" } + , { 0x0021, 0x0003, 0x0021, 0x0003, + EVR_US, "Unknown", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "TOSHIBA_MEC_1.0" } + , { 0x0021, 0x0003, 0x0021, 0x0003, + EVR_DS, "AcquiredSpectralRange", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 RAW" } + , { 0x0021, 0x0003, 0x0021, 0x0003, + EVR_US, "AcquisitionRoom", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS SMS-AX ACQ 1.0" } + , { 0x0021, 0x0004, 0x0021, 0x0004, + EVR_DS, "VOIPosition", 3, 3, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 RAW" } + , { 0x0021, 0x0004, 0x0021, 0x0004, + EVR_SL, "CurrentTimeProduct", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS SMS-AX ACQ 1.0" } + , { 0x0021, 0x0005, 0x0021, 0x0005, + EVR_SH, "GenesisVersionNow", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_RELA_01" } + , { 0x0021, 0x0005, 0x0021, 0x0005, + EVR_DS, "VOISize", 3, 3, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 RAW" } + , { 0x0021, 0x0005, 0x0021, 0x0005, + EVR_SL, "Dose", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS SMS-AX ACQ 1.0" } + , { 0x0021, 0x0006, 0x0021, 0x0006, + EVR_IS, "CSIMatrixSizeOriginal", 3, 3, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 RAW" } + , { 0x0021, 0x0006, 0x0021, 0x0006, + EVR_SL, "SkinDosePercent", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS SMS-AX ACQ 1.0" } + , { 0x0021, 0x0007, 0x0021, 0x0007, + EVR_UL, "SeriesRecordChecksum", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_RELA_01" } + , { 0x0021, 0x0007, 0x0021, 0x0007, + EVR_IS, "CSIMatrixSizeExtended", 3, 3, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 RAW" } + , { 0x0021, 0x0007, 0x0021, 0x0007, + EVR_SL, "SkinDoseAccumulation", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS SMS-AX ACQ 1.0" } + , { 0x0021, 0x0008, 0x0021, 0x0008, + EVR_DS, "SpatialGridShift", 3, 3, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 RAW" } + , { 0x0021, 0x0008, 0x0021, 0x0008, + EVR_SL, "SkinDoseRate", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS SMS-AX ACQ 1.0" } + , { 0x0021, 0x0009, 0x0021, 0x0009, + EVR_DS, "SignalLimitsMinimum", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 RAW" } + , { 0x0021, 0x000a, 0x0021, 0x000a, + EVR_UL, "CopperFilter", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS SMS-AX ACQ 1.0" } + , { 0x0021, 0x000b, 0x0021, 0x000b, + EVR_US, "MeasuringField", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS SMS-AX ACQ 1.0" } + , { 0x0021, 0x000c, 0x0021, 0x000c, + EVR_SS, "PostBlankingCircle", 3, 3, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS SMS-AX ACQ 1.0" } + , { 0x0021, 0x000d, 0x0021, 0x000d, + EVR_SS, "DynaAngles", 2, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS SMS-AX ACQ 1.0" } + , { 0x0021, 0x000e, 0x0021, 0x000e, + EVR_SS, "TotalSteps", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS SMS-AX ACQ 1.0" } + , { 0x0021, 0x000f, 0x0021, 0x000f, + EVR_SL, "DynaXRayInfo", 3, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS SMS-AX ACQ 1.0" } + , { 0x0021, 0x0010, 0x0021, 0x0010, + EVR_IS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/LAST" } + , { 0x0021, 0x0010, 0x0021, 0x0010, + EVR_UL, "CreationMask", 2, 2, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CT VA0 RAW" } + , { 0x0021, 0x0010, 0x0021, 0x0010, + EVR_LO, "FindRangeAlgorithm", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SVISION" } + , { 0x0021, 0x0010, 0x0021, 0x0010, + EVR_IS, "RotationAngle", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CT VA0 GEN" } + , { 0x0021, 0x0010, 0x0021, 0x0010, + EVR_DS, "Zoom", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MED" } + , { 0x0021, 0x0010, 0x0021, 0x0010, + EVR_DS, "SignalLimitsMaximum", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 RAW" } + , { 0x0021, 0x0010, 0x0021, 0x0010, + EVR_CS, "FCRImageID", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "FDMS 1.0" } + , { 0x0021, 0x0010, 0x0021, 0x0010, + EVR_US, "ModalityLUTInputGamma", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS SMS-AX ACQ 1.0" } + , { 0x0021, 0x0011, 0x0021, 0x0011, + EVR_DS, "ThresholdCAlgorithm", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SVISION" } + , { 0x0021, 0x0011, 0x0021, 0x0011, + EVR_IS, "StartAngle", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CT VA0 GEN" } + , { 0x0021, 0x0011, 0x0021, 0x0011, + EVR_DS, "Target", 2, 2, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MED" } + , { 0x0021, 0x0011, 0x0021, 0x0011, + EVR_DS, "SpecInfoMask", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 RAW" } + , { 0x0021, 0x0011, 0x0021, 0x0011, + EVR_US, "ModalityLUTOutputGamma", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS SMS-AX ACQ 1.0" } + , { 0x0021, 0x0012, 0x0021, 0x0012, + EVR_IS, "ExposureNumber", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "INTEGRIS 1.0" } + , { 0x0021, 0x0012, 0x0021, 0x0012, + EVR_LT, "SeriesUniqueIdentifier", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1" } + , { 0x0021, 0x0012, 0x0021, 0x0012, + EVR_IS, "TubeAngle", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MED" } + , { 0x0021, 0x0012, 0x0021, 0x0012, + EVR_DS, "EPITimeRateOfChangeOfMagnitude", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 RAW" } + , { 0x0021, 0x0012, 0x0021, 0x0012, + EVR_OB, "SH_STPAR", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS SMS-AX ACQ 1.0" } + , { 0x0021, 0x0013, 0x0021, 0x0013, + EVR_IS, "ImageSequenceNumber", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "CARDIO-D.R. 1.0" } + , { 0x0021, 0x0013, 0x0021, 0x0013, + EVR_DS, "EPITimeRateOfChangeOfXComponent", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 RAW" } + , { 0x0021, 0x0013, 0x0021, 0x0013, + EVR_US, "AcquisitionZoom", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS SMS-AX ACQ 1.0" } + , { 0x0021, 0x0014, 0x0021, 0x0014, + EVR_LT, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1" } + , { 0x0021, 0x0014, 0x0021, 0x0014, + EVR_DS, "EPITimeRateOfChangeOfYComponent", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 RAW" } + , { 0x0021, 0x0014, 0x0021, 0x0014, + EVR_SS, "DynaAngulationStepWidth", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS SMS-AX ACQ 1.0" } + , { 0x0021, 0x0015, 0x0021, 0x0015, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_RELA_01" } + , { 0x0021, 0x0015, 0x0021, 0x0015, + EVR_SS, "ImagesInStudy", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA GEN" } + , { 0x0021, 0x0015, 0x0021, 0x0015, + EVR_DS, "EPITimeRateOfChangeOfZComponent", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 RAW" } + , { 0x0021, 0x0015, 0x0021, 0x0015, + EVR_US, "Harmonization", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS SMS-AX ACQ 1.0" } + , { 0x0021, 0x0016, 0x0021, 0x0016, + EVR_SS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_RELA_01" } + , { 0x0021, 0x0016, 0x0021, 0x0016, + EVR_DS, "EPITimeRateOfChangeLegalLimit1", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 RAW" } + , { 0x0021, 0x0016, 0x0021, 0x0016, + EVR_US, "DRSingleFlag", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS SMS-AX ACQ 1.0" } + , { 0x0021, 0x0017, 0x0021, 0x0017, + EVR_DS, "EPIOperationModeFlag", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 RAW" } + , { 0x0021, 0x0017, 0x0021, 0x0017, + EVR_SL, "SourceToIsocenter", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS SMS-AX ACQ 1.0" } + , { 0x0021, 0x0018, 0x0021, 0x0018, + EVR_SH, "GenesisVersionNow", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_RELA_01" } + , { 0x0021, 0x0018, 0x0021, 0x0018, + EVR_DS, "EPIFieldCalculationSafetyFactor", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 RAW" } + , { 0x0021, 0x0018, 0x0021, 0x0018, + EVR_US, "PressureData", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS SMS-AX ACQ 1.0" } + , { 0x0021, 0x0019, 0x0021, 0x0019, + EVR_UL, "AcqReconRecordChecksum", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_RELA_01" } + , { 0x0021, 0x0019, 0x0021, 0x0019, + EVR_DS, "EPILegalLimit1OfChangeValue", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 RAW" } + , { 0x0021, 0x0019, 0x0021, 0x0019, + EVR_SL, "ECGIndexArray", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS SMS-AX ACQ 1.0" } + , { 0x0021, 0x001a, 0x0021, 0x001a, + EVR_US, "FDFlag", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS SMS-AX ACQ 1.0" } + , { 0x0021, 0x001b, 0x0021, 0x001b, + EVR_OB, "SH_ZOOM", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS SMS-AX ACQ 1.0" } + , { 0x0021, 0x001c, 0x0021, 0x001c, + EVR_OB, "SH_COLPAR", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS SMS-AX ACQ 1.0" } + , { 0x0021, 0x001d, 0x0021, 0x001d, + EVR_US, "K_Factor", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS SMS-AX ACQ 1.0" } + , { 0x0021, 0x001e, 0x0021, 0x001e, + EVR_US, "EVE", 8, 8, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS SMS-AX ACQ 1.0" } + , { 0x0021, 0x001f, 0x0021, 0x001f, + EVR_SL, "TotalSceneTime", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS SMS-AX ACQ 1.0" } + , { 0x0021, 0x0020, 0x0021, 0x0020, + EVR_DS, "FoV", 2, 2, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CM VA0 CMS" } + , { 0x0021, 0x0020, 0x0021, 0x0020, + EVR_LO, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P-GV-CT Release 1" } + , { 0x0021, 0x0020, 0x0021, 0x0020, + EVR_IS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/LAST" } + , { 0x0021, 0x0020, 0x0021, 0x0020, + EVR_UL, "EvaluationMask", 2, 2, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CT VA0 RAW" } + , { 0x0021, 0x0020, 0x0021, 0x0020, + EVR_DS, "TableStartLocation", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_RELA_01" } + , { 0x0021, 0x0020, 0x0021, 0x0020, + EVR_LO, "SensometricCurve", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SVISION" } + , { 0x0021, 0x0020, 0x0021, 0x0020, + EVR_US, "Unknown", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CT VA0 GEN" } + , { 0x0021, 0x0020, 0x0021, 0x0020, + EVR_SS, "ScenesInStudy", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA GEN" } + , { 0x0021, 0x0020, 0x0021, 0x0020, + EVR_US, "ROIMask", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MED" } + , { 0x0021, 0x0020, 0x0021, 0x0020, + EVR_DS, "EPILegalLimit2OfChangeValue", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 RAW" } + , { 0x0021, 0x0020, 0x0021, 0x0020, + EVR_IS, "PhaseCorrectionRowsSequence", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 GEN" } + , { 0x0021, 0x0020, 0x0021, 0x0020, + EVR_US, "RestoreFlag", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS SMS-AX ACQ 1.0" } + , { 0x0021, 0x0021, 0x0021, 0x0021, + EVR_DS, "SliceGap", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/LAST" } + , { 0x0021, 0x0021, 0x0021, 0x0021, + EVR_DS, "EPIRiseTime", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 RAW" } + , { 0x0021, 0x0021, 0x0021, 0x0021, + EVR_IS, "PhaseCorrectionColumnsSequence", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 GEN" } + , { 0x0021, 0x0021, 0x0021, 0x0021, + EVR_US, "StandMovementFlag", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS SMS-AX ACQ 1.0" } + , { 0x0021, 0x0022, 0x0021, 0x0022, + EVR_DS, "ImageMagnificationFactor", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CM VA0 CMS" } + , { 0x0021, 0x0022, 0x0021, 0x0022, + EVR_DS, "StackRadialAngle", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/LAST" } + , { 0x0021, 0x0022, 0x0021, 0x0022, + EVR_IS, "PhaseCorrectionRowsReconstruction", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 GEN" } + , { 0x0021, 0x0022, 0x0021, 0x0022, + EVR_US, "FDRows", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS SMS-AX ACQ 1.0" } + , { 0x0021, 0x0023, 0x0021, 0x0023, + EVR_US, "FDColumns", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS SMS-AX ACQ 1.0" } + , { 0x0021, 0x0024, 0x0021, 0x0024, + EVR_DS, "ImageScrollOffset", 2, 2, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CM VA0 CMS" } + , { 0x0021, 0x0024, 0x0021, 0x0024, + EVR_IS, "PhaseCorrectionColumnsReconstruction", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 GEN" } + , { 0x0021, 0x0024, 0x0021, 0x0024, + EVR_US, "TableMovementFlag", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS SMS-AX ACQ 1.0" } + , { 0x0021, 0x0025, 0x0021, 0x0025, + EVR_SS, "ImagesInPhotofile", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA GEN" } + , { 0x0021, 0x0025, 0x0021, 0x0025, + EVR_LO, "OriginalOrganProgramName", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS SMS-AX ACQ 1.0" } + , { 0x0021, 0x0026, 0x0021, 0x0026, + EVR_IS, "ImagePixelOffset", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CM VA0 CMS" } + , { 0x0021, 0x0026, 0x0021, 0x0026, + EVR_DS, "CrispyXPIFilter", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS SMS-AX ACQ 1.0" } + , { 0x0021, 0x0027, 0x0021, 0x0027, + EVR_SS, "PlaneBImagesExist", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA GEN" } + , { 0x0021, 0x0028, 0x0021, 0x0028, + EVR_SS, "NoOf2MBChunks", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA GEN" } + , { 0x0021, 0x0030, 0x0021, 0x0030, + EVR_LT, "ViewDirection", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CM VA0 CMS" } + , { 0x0021, 0x0030, 0x0021, 0x0030, + EVR_DS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P-GV-CT Release 1" } + , { 0x0021, 0x0030, 0x0021, 0x0030, + EVR_US, "ExtendedProcessingMask", 7, 7, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CT VA0 RAW" } + , { 0x0021, 0x0030, 0x0021, 0x0030, + EVR_DS, "LowerWindowOffset", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SVISION" } + , { 0x0021, 0x0030, 0x0021, 0x0030, + EVR_IS, "TopogramTubePosition", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CT VA0 GEN" } + , { 0x0021, 0x0030, 0x0021, 0x0030, + EVR_SS, "ImagesInAllScenes", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA GEN" } + , { 0x0021, 0x0030, 0x0021, 0x0030, + EVR_DS, "ArrayCoilADCOffset", 16, 16, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 RAW" } + , { 0x0021, 0x0030, 0x0021, 0x0030, + EVR_IS, "NumberOf3DRawPartitionsNominal", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 GEN" } + , { 0x0021, 0x0030, 0x0021, 0x0030, + EVR_CS, "SetNo", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "FDMS 1.0" } + , { 0x0021, 0x0031, 0x0021, 0x0031, + EVR_DS, "UpperWindowOffset", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SVISION" } + , { 0x0021, 0x0031, 0x0021, 0x0031, + EVR_DS, "ArrayCoilPreamplifierGain", 16, 16, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 RAW" } + , { 0x0021, 0x0031, 0x0021, 0x0031, + EVR_IS, "NumberOf3DRawPartitionsCurrent", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 GEN" } + , { 0x0021, 0x0032, 0x0021, 0x0032, + EVR_CS, "PatientRestDirection", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CM VA0 CMS" } + , { 0x0021, 0x0032, 0x0021, 0x0032, + EVR_DS, "LengthOfTopogram", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CT VA0 GEN" } + , { 0x0021, 0x0034, 0x0021, 0x0034, + EVR_DS, "TopogramCorrectionFactor", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CT VA0 GEN" } + , { 0x0021, 0x0034, 0x0021, 0x0034, + EVR_IS, "NumberOf3DImagePartitions", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 GEN" } + , { 0x0021, 0x0035, 0x0021, 0x0035, + EVR_SS, "SeriesFromWhichPrescribed", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_RELA_01" } + , { 0x0021, 0x0036, 0x0021, 0x0036, + EVR_SS, "ImageFromWhichPrescribed", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_RELA_01" } + , { 0x0021, 0x0036, 0x0021, 0x0036, + EVR_DS, "MaximumTablePosition", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CT VA0 GEN" } + , { 0x0021, 0x0036, 0x0021, 0x0036, + EVR_IS, "Actual3DImagePartitionNumber", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 GEN" } + , { 0x0021, 0x0037, 0x0021, 0x0037, + EVR_SS, "ScreenFormat", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_RELA_01" } + , { 0x0021, 0x0039, 0x0021, 0x0039, + EVR_DS, "SlabThickness", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 GEN" } + , { 0x0021, 0x0040, 0x0021, 0x0040, + EVR_LO, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P-GV-CT Release 1" } + , { 0x0021, 0x0040, 0x0021, 0x0040, + EVR_US, "Unknown", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CT VA0 RAW" } + , { 0x0021, 0x0040, 0x0021, 0x0040, + EVR_IS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P-Private_CDS Release 1" } + , { 0x0021, 0x0040, 0x0021, 0x0040, + EVR_SS, "ArchiveSWInternalVersion", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RA GEN" } + , { 0x0021, 0x0040, 0x0021, 0x0040, + EVR_IS, "TableMoveDirectionCode", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CT VA0 GEN" } + , { 0x0021, 0x0040, 0x0021, 0x0040, + EVR_DS, "MinPrintableDensity", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SVISION" } + , { 0x0021, 0x0040, 0x0021, 0x0040, + EVR_IS, "NumberOfSlicesNominal", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 GEN" } + , { 0x0021, 0x0040, 0x0021, 0x0040, + EVR_IS, "ImageNoInTheSet", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "FDMS 1.0" } + , { 0x0021, 0x0041, 0x0021, 0x0041, + EVR_US, "Unknown", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CT VA0 RAW" } + , { 0x0021, 0x0041, 0x0021, 0x0041, + EVR_DS, "MaxPrintableDensity", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SVISION" } + , { 0x0021, 0x0041, 0x0021, 0x0041, + EVR_IS, "NumberOfSlicesCurrent", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 GEN" } + , { 0x0021, 0x0042, 0x0021, 0x0042, + EVR_US, "Unknown", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CT VA0 RAW" } + , { 0x0021, 0x0042, 0x0021, 0x0042, + EVR_IS, "CurrentSliceNumber", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 GEN" } + , { 0x0021, 0x0043, 0x0021, 0x0043, + EVR_US, "Unknown", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CT VA0 RAW" } + , { 0x0021, 0x0043, 0x0021, 0x0043, + EVR_IS, "CurrentGroupNumber", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 GEN" } + , { 0x0021, 0x0044, 0x0021, 0x0044, + EVR_US, "Unknown", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CT VA0 RAW" } + , { 0x0021, 0x0044, 0x0021, 0x0044, + EVR_DS, "CurrentSliceDistanceFactor", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 GEN" } + , { 0x0021, 0x0045, 0x0021, 0x0045, + EVR_IS, "VOIStartRow", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CT VA0 GEN" } + , { 0x0021, 0x0045, 0x0021, 0x0045, + EVR_IS, "MIPStartRow", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 GEN" } + , { 0x0021, 0x0046, 0x0021, 0x0046, + EVR_IS, "VOIStopRow", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CT VA0 GEN" } + , { 0x0021, 0x0046, 0x0021, 0x0046, + EVR_IS, "MIPStopRow", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 GEN" } + , { 0x0021, 0x0047, 0x0021, 0x0047, + EVR_IS, "VOIStartColumn", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CT VA0 GEN" } + , { 0x0021, 0x0047, 0x0021, 0x0047, + EVR_IS, "MIPStartColumn", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 GEN" } + , { 0x0021, 0x0048, 0x0021, 0x0048, + EVR_IS, "VOIStopColumn", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CT VA0 GEN" } + , { 0x0021, 0x0048, 0x0021, 0x0048, + EVR_IS, "MIPStartColumn", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 GEN" } + , { 0x0021, 0x0049, 0x0021, 0x0049, + EVR_IS, "VOIStartSlice", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CT VA0 GEN" } + , { 0x0021, 0x0049, 0x0021, 0x0049, + EVR_IS, "MIPStartSliceName=", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 GEN" } + , { 0x0021, 0x004a, 0x0021, 0x004a, + EVR_LO, "AnatomicalReferenceForScout", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_RELA_01" } + , { 0x0021, 0x004a, 0x0021, 0x004a, + EVR_IS, "VOIStopSlice", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CT VA0 GEN" } + , { 0x0021, 0x004a, 0x0021, 0x004a, + EVR_IS, "MIPStartSlice", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 GEN" } + , { 0x0021, 0x004e, 0x0021, 0x004e, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_RELA_01" } + , { 0x0021, 0x004f, 0x0021, 0x004f, + EVR_SS, "LocationsInAcquisition", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_RELA_01" } + , { 0x0021, 0x004f, 0x0021, 0x004f, + EVR_LT, "OrderofSlices", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 GEN" } + , { 0x0021, 0x0050, 0x0021, 0x0050, + EVR_LO, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P-GV-CT Release 1" } + , { 0x0021, 0x0050, 0x0021, 0x0050, + EVR_LT, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CT VA0 RAW" } + , { 0x0021, 0x0050, 0x0021, 0x0050, + EVR_SS, "GraphicallyPrescribed", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_RELA_01" } + , { 0x0021, 0x0050, 0x0021, 0x0050, + EVR_IS, "VectorStartRow", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CT VA0 GEN" } + , { 0x0021, 0x0050, 0x0021, 0x0050, + EVR_LT, "SaturationType", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 RAW" } + , { 0x0021, 0x0050, 0x0021, 0x0050, + EVR_US, "SignalMask", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 GEN" } + , { 0x0021, 0x0050, 0x0021, 0x0050, + EVR_CS, "PairProcessingInformation", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "FDMS 1.0" } + , { 0x0021, 0x0051, 0x0021, 0x0051, + EVR_DS, "RotationFromSourceXRot", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_RELA_01" } + , { 0x0021, 0x0051, 0x0021, 0x0051, + EVR_IS, "VectorRowStep", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CT VA0 GEN" } + , { 0x0021, 0x0051, 0x0021, 0x0051, + EVR_DS, "SaturationNormalVector", 3, 3, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 RAW" } + , { 0x0021, 0x0052, 0x0021, 0x0052, + EVR_DS, "RotationFromSourceYRot", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_RELA_01" } + , { 0x0021, 0x0052, 0x0021, 0x0052, + EVR_IS, "VectorStartColumn", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CT VA0 GEN" } + , { 0x0021, 0x0052, 0x0021, 0x0052, + EVR_DS, "SaturationPositionVector", 3, 3, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 RAW" } + , { 0x0021, 0x0052, 0x0021, 0x0052, + EVR_DS, "DelayAfterTrigger", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 GEN" } + , { 0x0021, 0x0053, 0x0021, 0x0053, + EVR_DS, "RotationFromSourceZRot", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_RELA_01" } + , { 0x0021, 0x0053, 0x0021, 0x0053, + EVR_IS, "VectorColumnStep", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CT VA0 GEN" } + , { 0x0021, 0x0053, 0x0021, 0x0053, + EVR_DS, "SaturationThickness", 6, 6, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 RAW" } + , { 0x0021, 0x0053, 0x0021, 0x0053, + EVR_IS, "RRInterval", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 GEN" } + , { 0x0021, 0x0054, 0x0021, 0x0054, + EVR_SH, "ImagePosition", 3, 3, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_RELA_01" } + , { 0x0021, 0x0054, 0x0021, 0x0054, + EVR_DS, "SaturationWidth", 6, 6, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 RAW" } + , { 0x0021, 0x0054, 0x0021, 0x0054, + EVR_DS, "NumberOfTriggerPulses", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 GEN" } + , { 0x0021, 0x0055, 0x0021, 0x0055, + EVR_SH, "ImageOrientation", 6, 6, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_RELA_01" } + , { 0x0021, 0x0055, 0x0021, 0x0055, + EVR_DS, "SaturationDistance", 6, 6, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 RAW" } + , { 0x0021, 0x0056, 0x0021, 0x0056, + EVR_SL, "IntegerSlop", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_RELA_01" } + , { 0x0021, 0x0056, 0x0021, 0x0056, + EVR_DS, "RepetitionTimeEffective", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 GEN" } + , { 0x0021, 0x0057, 0x0021, 0x0057, + EVR_SL, "IntegerSlop", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_RELA_01" } + , { 0x0021, 0x0057, 0x0021, 0x0057, + EVR_LT, "GatePhase", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 GEN" } + , { 0x0021, 0x0058, 0x0021, 0x0058, + EVR_SL, "IntegerSlop", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_RELA_01" } + , { 0x0021, 0x0058, 0x0021, 0x0058, + EVR_DS, "GateThreshold", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 GEN" } + , { 0x0021, 0x0059, 0x0021, 0x0059, + EVR_SL, "IntegerSlop", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_RELA_01" } + , { 0x0021, 0x0059, 0x0021, 0x0059, + EVR_DS, "GatedRatio", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 GEN" } + , { 0x0021, 0x005a, 0x0021, 0x005a, + EVR_SL, "IntegerSlop", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_RELA_01" } + , { 0x0021, 0x005b, 0x0021, 0x005b, + EVR_DS, "FloatSlop", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_RELA_01" } + , { 0x0021, 0x005c, 0x0021, 0x005c, + EVR_DS, "FloatSlop", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_RELA_01" } + , { 0x0021, 0x005d, 0x0021, 0x005d, + EVR_DS, "FloatSlop", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_RELA_01" } + , { 0x0021, 0x005e, 0x0021, 0x005e, + EVR_DS, "FloatSlop", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_RELA_01" } + , { 0x0021, 0x005f, 0x0021, 0x005f, + EVR_DS, "FloatSlop", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_RELA_01" } + , { 0x0021, 0x0060, 0x0021, 0x0060, + EVR_DS, "ImagePosition", 3, 3, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CM VA0 CMS" } + , { 0x0021, 0x0060, 0x0021, 0x0060, + EVR_DS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P-GV-CT Release 1" } + , { 0x0021, 0x0060, 0x0021, 0x0060, + EVR_IS, "RangeTypeCode", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CT VA0 GEN" } + , { 0x0021, 0x0060, 0x0021, 0x0060, + EVR_IS, "NumberOfInterpolatedImages", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 GEN" } + , { 0x0021, 0x0061, 0x0021, 0x0061, + EVR_DS, "ImageNormal", 3, 3, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CM VA0 CMS" } + , { 0x0021, 0x0062, 0x0021, 0x0062, + EVR_IS, "ReferenceTypeCode", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CT VA0 GEN" } + , { 0x0021, 0x0063, 0x0021, 0x0063, + EVR_DS, "ImageDistance", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CM VA0 CMS" } + , { 0x0021, 0x0065, 0x0021, 0x0065, + EVR_US, "ImagePositioningHistoryMask", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CM VA0 CMS" } + , { 0x0021, 0x006a, 0x0021, 0x006a, + EVR_DS, "ImageRow", 3, 3, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CM VA0 CMS" } + , { 0x0021, 0x006b, 0x0021, 0x006b, + EVR_DS, "ImageColumn", 3, 3, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CM VA0 CMS" } + , { 0x0021, 0x0070, 0x0021, 0x0070, + EVR_LT, "PatientOrientationSet1", 3, 3, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CM VA0 CMS" } + , { 0x0021, 0x0070, 0x0021, 0x0070, + EVR_DS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P-GV-CT Release 1" } + , { 0x0021, 0x0070, 0x0021, 0x0070, + EVR_LT, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_RELA_01" } + , { 0x0021, 0x0070, 0x0021, 0x0070, + EVR_DS, "ObjectOrientation", 3, 3, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CT VA0 GEN" } + , { 0x0021, 0x0070, 0x0021, 0x0070, + EVR_IS, "NumberOfEchoes", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 GEN" } + , { 0x0021, 0x0071, 0x0021, 0x0071, + EVR_LT, "PatientOrientationSet2", 3, 3, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CM VA0 CMS" } + , { 0x0021, 0x0071, 0x0021, 0x0071, + EVR_LT, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_RELA_01" } + , { 0x0021, 0x0072, 0x0021, 0x0072, + EVR_DS, "LightOrientation", 3, 3, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CT VA0 GEN" } + , { 0x0021, 0x0072, 0x0021, 0x0072, + EVR_DS, "SecondEchoTime", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 GEN" } + , { 0x0021, 0x0073, 0x0021, 0x0073, + EVR_DS, "SecondRepetitionTime", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 GEN" } + , { 0x0021, 0x0075, 0x0021, 0x0075, + EVR_DS, "LightBrightness", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CT VA0 GEN" } + , { 0x0021, 0x0076, 0x0021, 0x0076, + EVR_DS, "LightContrast", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CT VA0 GEN" } + , { 0x0021, 0x007a, 0x0021, 0x007a, + EVR_IS, "OverlayThreshold", 2, 2, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CT VA0 GEN" } + , { 0x0021, 0x007b, 0x0021, 0x007b, + EVR_IS, "SurfaceThreshold", 2, 2, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CT VA0 GEN" } + , { 0x0021, 0x007c, 0x0021, 0x007c, + EVR_IS, "GreyScaleThreshold", 2, 2, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CT VA0 GEN" } + , { 0x0021, 0x0080, 0x0021, 0x0080, + EVR_LT, "StudyName", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CM VA0 CMS" } + , { 0x0021, 0x0080, 0x0021, 0x0080, + EVR_DS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P-GV-CT Release 1" } + , { 0x0021, 0x0080, 0x0021, 0x0080, + EVR_OB, "EquipmentTypeSpecificInformation", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "FDMS 1.0" } + , { 0x0021, 0x0080, 0x0021, 0x0080, + EVR_IS, "CardiacCode", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 GEN" } + , { 0x0021, 0x0081, 0x0021, 0x0081, + EVR_DS, "AutoWindowLevelAlpha", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_RELA_01" } + , { 0x0021, 0x0082, 0x0021, 0x0082, + EVR_LT, "StudyType", 3, 3, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CM VA0 CMS" } + , { 0x0021, 0x0082, 0x0021, 0x0082, + EVR_DS, "AutoWindowLevelBeta", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_RELA_01" } + , { 0x0021, 0x0083, 0x0021, 0x0083, + EVR_DS, "AutoWindowLevelWindow", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_RELA_01" } + , { 0x0021, 0x0084, 0x0021, 0x0084, + EVR_DS, "AutoWindowLevelLevel", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_RELA_01" } + , { 0x0021, 0x0090, 0x0021, 0x0090, + EVR_DS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P-GV-CT Release 1" } + , { 0x0021, 0x0090, 0x0021, 0x0090, + EVR_SS, "TubeFocalSpotPosition", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_RELA_01" } + , { 0x0021, 0x0090, 0x0021, 0x0090, + EVR_DS, "Brightness", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SVISION" } + , { 0x0021, 0x0091, 0x0021, 0x0091, + EVR_SS, "BiopsyPosition", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_RELA_01" } + , { 0x0021, 0x0091, 0x0021, 0x0091, + EVR_DS, "Contrast", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SVISION" } + , { 0x0021, 0x0091, 0x0021, 0x0091, + EVR_DS, "SaturationPhaseEncodingVectorTransverseComponent", 6, 6, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 GEN" } + , { 0x0021, 0x0092, 0x0021, 0x0092, + EVR_FL, "BiopsyTLocation", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_RELA_01" } + , { 0x0021, 0x0092, 0x0021, 0x0092, + EVR_DS, "ShapeFactor", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SVISION" } + , { 0x0021, 0x0092, 0x0021, 0x0092, + EVR_DS, "SaturationReadoutVectorTransverseComponent", 6, 6, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 GEN" } + , { 0x0021, 0x0093, 0x0021, 0x0093, + EVR_FL, "BiopsyRefLocation", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_RELA_01" } + , { 0x0021, 0x0093, 0x0021, 0x0093, + EVR_DS, "EPIChangeValueOfMagnitude", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 GEN" } + , { 0x0021, 0x0094, 0x0021, 0x0094, + EVR_DS, "EPIChangeValueOfXComponent", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 GEN" } + , { 0x0021, 0x0095, 0x0021, 0x0095, + EVR_DS, "EPIChangeValueOfYComponent", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 GEN" } + , { 0x0021, 0x0096, 0x0021, 0x0096, + EVR_DS, "EPIChangeValueOfZComponent", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MR VA0 GEN" } + , { 0x0021, 0x00a0, 0x0021, 0x00a0, + EVR_DS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CT VA0 GEN" } + , { 0x0021, 0x00a0, 0x0021, 0x00a0, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P-GV-CT Release 1" } + , { 0x0021, 0x00a1, 0x0021, 0x00a1, + EVR_DS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P-GV-CT Release 1" } + , { 0x0021, 0x00a2, 0x0021, 0x00a2, + EVR_LT, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CT VA0 GEN" } + , { 0x0021, 0x00a2, 0x0021, 0x00a2, + EVR_DS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P-GV-CT Release 1" } + , { 0x0021, 0x00a3, 0x0021, 0x00a3, + EVR_LT, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P-GV-CT Release 1" } + , { 0x0021, 0x00a4, 0x0021, 0x00a4, + EVR_LT, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P-GV-CT Release 1" } + , { 0x0021, 0x00a7, 0x0021, 0x00a7, + EVR_LT, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CT VA0 GEN" } + , { 0x0021, 0x00b0, 0x0021, 0x00b0, + EVR_LO, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P-GV-CT Release 1" } + , { 0x0021, 0x00c0, 0x0021, 0x00c0, + EVR_LO, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P-GV-CT Release 1" } + , { 0x0021, 0x1000, 0x0021, 0x1000, + EVR_IS, "ReconstructionNumber", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/PART" } + , { 0x0021, 0x1010, 0x0021, 0x1010, + EVR_IS, "ImageType", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/PART" } + , { 0x0021, 0x1020, 0x0021, 0x1020, + EVR_IS, "SliceNumber", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/PART" } + , { 0x0021, 0x1030, 0x0021, 0x1030, + EVR_IS, "EchoNumber", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/PART" } + , { 0x0021, 0x1031, 0x0021, 0x1031, + EVR_DS, "PatientReferenceID", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/PART" } + , { 0x0021, 0x1035, 0x0021, 0x1035, + EVR_IS, "ChemicalShiftNumber", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/PART" } + , { 0x0021, 0x1040, 0x0021, 0x1040, + EVR_IS, "PhaseNumber", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/PART" } + , { 0x0021, 0x1050, 0x0021, 0x1050, + EVR_IS, "DynamicScanNumber", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/PART" } + , { 0x0021, 0x1060, 0x0021, 0x1060, + EVR_IS, "NumberOfRowsInObject", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/PART" } + , { 0x0021, 0x1061, 0x0021, 0x1061, + EVR_IS, "RowNumber", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/PART" } + , { 0x0021, 0x1062, 0x0021, 0x1062, + EVR_IS, "Unknown", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/PART" } + , { 0x0021, 0x1100, 0x0021, 0x1100, + EVR_DA, "ScanDate", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/PART" } + , { 0x0021, 0x1110, 0x0021, 0x1110, + EVR_TM, "ScanTime", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/PART" } + , { 0x0021, 0x1221, 0x0021, 0x1221, + EVR_IS, "SliceGap", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/PART" } +#endif + , { 0x0022, 0x0001, 0x0022, 0x0001, + EVR_US, "LightPathFilterPassThroughWavelength", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x0002, 0x0022, 0x0002, + EVR_US, "LightPathFilterPassBand", 2, 2, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x0003, 0x0022, 0x0003, + EVR_US, "ImagePathFilterPassThroughWavelength", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x0004, 0x0022, 0x0004, + EVR_US, "ImagePathFilterPassBand", 2, 2, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x0005, 0x0022, 0x0005, + EVR_CS, "PatientEyeMovementCommanded", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x0006, 0x0022, 0x0006, + EVR_SQ, "PatientEyeMovementCommandCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x0007, 0x0022, 0x0007, + EVR_FL, "SphericalLensPower", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x0008, 0x0022, 0x0008, + EVR_FL, "CylinderLensPower", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x0009, 0x0022, 0x0009, + EVR_FL, "CylinderAxis", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x000a, 0x0022, 0x000a, + EVR_FL, "EmmetropicMagnification", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x000b, 0x0022, 0x000b, + EVR_FL, "IntraOcularPressure", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x000c, 0x0022, 0x000c, + EVR_FL, "HorizontalFieldOfView", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x000d, 0x0022, 0x000d, + EVR_CS, "PupilDilated", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x000e, 0x0022, 0x000e, + EVR_FL, "DegreeOfDilation", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x0010, 0x0022, 0x0010, + EVR_FL, "StereoBaselineAngle", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x0011, 0x0022, 0x0011, + EVR_FL, "StereoBaselineDisplacement", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x0012, 0x0022, 0x0012, + EVR_FL, "StereoHorizontalPixelOffset", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x0013, 0x0022, 0x0013, + EVR_FL, "StereoVerticalPixelOffset", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x0014, 0x0022, 0x0014, + EVR_FL, "StereoRotation", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x0015, 0x0022, 0x0015, + EVR_SQ, "AcquisitionDeviceTypeCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x0016, 0x0022, 0x0016, + EVR_SQ, "IlluminationTypeCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x0017, 0x0022, 0x0017, + EVR_SQ, "LightPathFilterTypeStackCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x0018, 0x0022, 0x0018, + EVR_SQ, "ImagePathFilterTypeStackCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x0019, 0x0022, 0x0019, + EVR_SQ, "LensesCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x001a, 0x0022, 0x001a, + EVR_SQ, "ChannelDescriptionCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x001b, 0x0022, 0x001b, + EVR_SQ, "RefractiveStateSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x001c, 0x0022, 0x001c, + EVR_SQ, "MydriaticAgentCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x001d, 0x0022, 0x001d, + EVR_SQ, "RelativeImagePositionCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x001e, 0x0022, 0x001e, + EVR_FL, "CameraAngleOfView", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x0020, 0x0022, 0x0020, + EVR_SQ, "StereoPairsSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x0021, 0x0022, 0x0021, + EVR_SQ, "LeftImageSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x0022, 0x0022, 0x0022, + EVR_SQ, "RightImageSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x0028, 0x0022, 0x0028, + EVR_CS, "StereoPairsPresent", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x0030, 0x0022, 0x0030, + EVR_FL, "AxialLengthOfTheEye", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x0031, 0x0022, 0x0031, + EVR_SQ, "OphthalmicFrameLocationSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x0032, 0x0022, 0x0032, + EVR_FL, "ReferenceCoordinates", 2, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x0035, 0x0022, 0x0035, + EVR_FL, "DepthSpatialResolution", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x0036, 0x0022, 0x0036, + EVR_FL, "MaximumDepthDistortion", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x0037, 0x0022, 0x0037, + EVR_FL, "AlongScanSpatialResolution", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x0038, 0x0022, 0x0038, + EVR_FL, "MaximumAlongScanDistortion", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x0039, 0x0022, 0x0039, + EVR_CS, "OphthalmicImageOrientation", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x0041, 0x0022, 0x0041, + EVR_FL, "DepthOfTransverseImage", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x0042, 0x0022, 0x0042, + EVR_SQ, "MydriaticAgentConcentrationUnitsSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x0048, 0x0022, 0x0048, + EVR_FL, "AcrossScanSpatialResolution", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x0049, 0x0022, 0x0049, + EVR_FL, "MaximumAcrossScanDistortion", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x004e, 0x0022, 0x004e, + EVR_DS, "MydriaticAgentConcentration", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x0055, 0x0022, 0x0055, + EVR_FL, "IlluminationWaveLength", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x0056, 0x0022, 0x0056, + EVR_FL, "IlluminationPower", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x0057, 0x0022, 0x0057, + EVR_FL, "IlluminationBandwidth", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x0058, 0x0022, 0x0058, + EVR_SQ, "MydriaticAgentSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x1007, 0x0022, 0x1007, + EVR_SQ, "OphthalmicAxialMeasurementsRightEyeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x1008, 0x0022, 0x1008, + EVR_SQ, "OphthalmicAxialMeasurementsLeftEyeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x1009, 0x0022, 0x1009, + EVR_CS, "OphthalmicAxialMeasurementsDeviceType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x1010, 0x0022, 0x1010, + EVR_CS, "OphthalmicAxialLengthMeasurementsType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x1012, 0x0022, 0x1012, + EVR_SQ, "OphthalmicAxialLengthSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x1019, 0x0022, 0x1019, + EVR_FL, "OphthalmicAxialLength", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x1024, 0x0022, 0x1024, + EVR_SQ, "LensStatusCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x1025, 0x0022, 0x1025, + EVR_SQ, "VitreousStatusCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x1028, 0x0022, 0x1028, + EVR_SQ, "IOLFormulaCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x1029, 0x0022, 0x1029, + EVR_LO, "IOLFormulaDetail", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x1033, 0x0022, 0x1033, + EVR_FL, "KeratometerIndex", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x1035, 0x0022, 0x1035, + EVR_SQ, "SourceOfOphthalmicAxialLengthCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x1037, 0x0022, 0x1037, + EVR_FL, "TargetRefraction", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x1039, 0x0022, 0x1039, + EVR_CS, "RefractiveProcedureOccurred", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x1040, 0x0022, 0x1040, + EVR_SQ, "RefractiveSurgeryTypeCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x1044, 0x0022, 0x1044, + EVR_SQ, "OphthalmicUltrasoundMethodCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x1050, 0x0022, 0x1050, + EVR_SQ, "OphthalmicAxialLengthMeasurementsSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x1053, 0x0022, 0x1053, + EVR_FL, "IOLPower", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x1054, 0x0022, 0x1054, + EVR_FL, "PredictedRefractiveError", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x1059, 0x0022, 0x1059, + EVR_FL, "OphthalmicAxialLengthVelocity", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x1065, 0x0022, 0x1065, + EVR_LO, "LensStatusDescription", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x1066, 0x0022, 0x1066, + EVR_LO, "VitreousStatusDescription", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x1090, 0x0022, 0x1090, + EVR_SQ, "IOLPowerSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x1092, 0x0022, 0x1092, + EVR_SQ, "LensConstantSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x1093, 0x0022, 0x1093, + EVR_LO, "IOLManufacturer", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x1094, 0x0022, 0x1094, + EVR_LO, "RETIRED_LensConstantDescription", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x1095, 0x0022, 0x1095, + EVR_LO, "ImplantName", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x1096, 0x0022, 0x1096, + EVR_SQ, "KeratometryMeasurementTypeCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x1097, 0x0022, 0x1097, + EVR_LO, "ImplantPartNumber", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x1100, 0x0022, 0x1100, + EVR_SQ, "ReferencedOphthalmicAxialMeasurementsSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x1101, 0x0022, 0x1101, + EVR_SQ, "OphthalmicAxialLengthMeasurementsSegmentNameCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x1103, 0x0022, 0x1103, + EVR_SQ, "RefractiveErrorBeforeRefractiveSurgeryCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x1121, 0x0022, 0x1121, + EVR_FL, "IOLPowerForExactEmmetropia", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x1122, 0x0022, 0x1122, + EVR_FL, "IOLPowerForExactTargetRefraction", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x1125, 0x0022, 0x1125, + EVR_SQ, "AnteriorChamberDepthDefinitionCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x1127, 0x0022, 0x1127, + EVR_SQ, "LensThicknessSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x1128, 0x0022, 0x1128, + EVR_SQ, "AnteriorChamberDepthSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x1130, 0x0022, 0x1130, + EVR_FL, "LensThickness", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x1131, 0x0022, 0x1131, + EVR_FL, "AnteriorChamberDepth", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x1132, 0x0022, 0x1132, + EVR_SQ, "SourceOfLensThicknessDataCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x1133, 0x0022, 0x1133, + EVR_SQ, "SourceOfAnteriorChamberDepthDataCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x1134, 0x0022, 0x1134, + EVR_SQ, "SourceOfRefractiveMeasurementsSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x1135, 0x0022, 0x1135, + EVR_SQ, "SourceOfRefractiveMeasurementsCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x1140, 0x0022, 0x1140, + EVR_CS, "OphthalmicAxialLengthMeasurementModified", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x1150, 0x0022, 0x1150, + EVR_SQ, "OphthalmicAxialLengthDataSourceCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x1153, 0x0022, 0x1153, + EVR_SQ, "RETIRED_OphthalmicAxialLengthAcquisitionMethodCodeSequence", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x1155, 0x0022, 0x1155, + EVR_FL, "SignalToNoiseRatio", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x1159, 0x0022, 0x1159, + EVR_LO, "OphthalmicAxialLengthDataSourceDescription", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x1210, 0x0022, 0x1210, + EVR_SQ, "OphthalmicAxialLengthMeasurementsTotalLengthSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x1211, 0x0022, 0x1211, + EVR_SQ, "OphthalmicAxialLengthMeasurementsSegmentalLengthSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x1212, 0x0022, 0x1212, + EVR_SQ, "OphthalmicAxialLengthMeasurementsLengthSummationSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x1220, 0x0022, 0x1220, + EVR_SQ, "UltrasoundOphthalmicAxialLengthMeasurementsSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x1225, 0x0022, 0x1225, + EVR_SQ, "OpticalOphthalmicAxialLengthMeasurementsSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x1230, 0x0022, 0x1230, + EVR_SQ, "UltrasoundSelectedOphthalmicAxialLengthSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x1250, 0x0022, 0x1250, + EVR_SQ, "OphthalmicAxialLengthSelectionMethodCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x1255, 0x0022, 0x1255, + EVR_SQ, "OpticalSelectedOphthalmicAxialLengthSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x1257, 0x0022, 0x1257, + EVR_SQ, "SelectedSegmentalOphthalmicAxialLengthSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x1260, 0x0022, 0x1260, + EVR_SQ, "SelectedTotalOphthalmicAxialLengthSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x1262, 0x0022, 0x1262, + EVR_SQ, "OphthalmicAxialLengthQualityMetricSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x1265, 0x0022, 0x1265, + EVR_SQ, "RETIRED_OphthalmicAxialLengthQualityMetricTypeCodeSequence", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x1273, 0x0022, 0x1273, + EVR_LO, "RETIRED_OphthalmicAxialLengthQualityMetricTypeDescription", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x1300, 0x0022, 0x1300, + EVR_SQ, "IntraocularLensCalculationsRightEyeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x1310, 0x0022, 0x1310, + EVR_SQ, "IntraocularLensCalculationsLeftEyeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x1330, 0x0022, 0x1330, + EVR_SQ, "ReferencedOphthalmicAxialLengthMeasurementQCImageSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x1415, 0x0022, 0x1415, + EVR_CS, "OphthalmicMappingDeviceType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x1420, 0x0022, 0x1420, + EVR_SQ, "AcquisitionMethodCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x1423, 0x0022, 0x1423, + EVR_SQ, "AcquisitionMethodAlgorithmSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x1436, 0x0022, 0x1436, + EVR_SQ, "OphthalmicThicknessMapTypeCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x1443, 0x0022, 0x1443, + EVR_SQ, "OphthalmicThicknessMappingNormalsSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x1445, 0x0022, 0x1445, + EVR_SQ, "RetinalThicknessDefinitionCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x1450, 0x0022, 0x1450, + EVR_SQ, "PixelValueMappingToCodedConceptSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x1452, 0x0022, 0x1452, + EVR_xs, "MappedPixelValue", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x1454, 0x0022, 0x1454, + EVR_LO, "PixelValueMappingExplanation", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x1458, 0x0022, 0x1458, + EVR_SQ, "OphthalmicThicknessMapQualityThresholdSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x1460, 0x0022, 0x1460, + EVR_FL, "OphthalmicThicknessMapThresholdQualityRating", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x1463, 0x0022, 0x1463, + EVR_FL, "AnatomicStructureReferencePoint", 2, 2, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x1465, 0x0022, 0x1465, + EVR_SQ, "RegistrationToLocalizerSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x1466, 0x0022, 0x1466, + EVR_CS, "RegisteredLocalizerUnits", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x1467, 0x0022, 0x1467, + EVR_FL, "RegisteredLocalizerTopLeftHandCorner", 2, 2, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x1468, 0x0022, 0x1468, + EVR_FL, "RegisteredLocalizerBottomRightHandCorner", 2, 2, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x1470, 0x0022, 0x1470, + EVR_SQ, "OphthalmicThicknessMapQualityRatingSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x1472, 0x0022, 0x1472, + EVR_SQ, "RelevantOPTAttributesSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x1512, 0x0022, 0x1512, + EVR_SQ, "TransformationMethodCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x1513, 0x0022, 0x1513, + EVR_SQ, "TransformationAlgorithmSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x1515, 0x0022, 0x1515, + EVR_CS, "OphthalmicAxialLengthMethod", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x1517, 0x0022, 0x1517, + EVR_FL, "OphthalmicFOV", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x1518, 0x0022, 0x1518, + EVR_SQ, "TwoDimensionalToThreeDimensionalMapSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x1525, 0x0022, 0x1525, + EVR_SQ, "WideFieldOphthalmicPhotographyQualityRatingSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x1526, 0x0022, 0x1526, + EVR_SQ, "WideFieldOphthalmicPhotographyQualityThresholdSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x1527, 0x0022, 0x1527, + EVR_FL, "WideFieldOphthalmicPhotographyThresholdQualityRating", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x1528, 0x0022, 0x1528, + EVR_FL, "XCoordinatesCenterPixelViewAngle", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x1529, 0x0022, 0x1529, + EVR_FL, "YCoordinatesCenterPixelViewAngle", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x1530, 0x0022, 0x1530, + EVR_UL, "NumberOfMapPoints", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0022, 0x1531, 0x0022, 0x1531, + EVR_OF, "TwoDimensionalToThreeDimensionalMapData", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } +#ifdef ENABLE_PRIVATE_TAGS + , { 0x0023, 0x0000, 0x0023, 0x0000, + EVR_DS, "CRDRE", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACRQA_2.0 BLOCK3" } + , { 0x0023, 0x0000, 0x0023, 0x0000, + EVR_DS, "CRDRE", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACRQA_1.0 BLOCK3" } + , { 0x0023, 0x0000, 0x0023, 0x0000, + EVR_LO, "ImageLaterality", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SVISION" } + , { 0x0023, 0x0000, 0x0023, 0x0000, + EVR_DS, "HorizontalCalibrationPixelSize", 2, 2, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS SMS-AX QUANT 1.0" } + , { 0x0023, 0x0000, 0x0023, 0x0000, + EVR_LO, "CRExposureMenuCode", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACRQA_2.0 BLOCK1" } + , { 0x0023, 0x0000, 0x0023, 0x0000, + EVR_LO, "CRExposureMenuCode", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACRQA_1.0 BLOCK1" } + , { 0x0023, 0x0000, 0x0023, 0x0000, + EVR_US, "CRSShift", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACRQA_2.0 BLOCK2" } + , { 0x0023, 0x0000, 0x0023, 0x0000, + EVR_US, "CRSShift", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACRQA_1.0 BLOCK2" } + , { 0x0023, 0x0001, 0x0023, 0x0001, + EVR_IS, "LetterPosition", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SVISION" } + , { 0x0023, 0x0001, 0x0023, 0x0001, + EVR_DS, "VerticalCalibrationPixelSize", 2, 2, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS SMS-AX QUANT 1.0" } + , { 0x0023, 0x0001, 0x0023, 0x0001, + EVR_SL, "NumberOfSeriesInStudy", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_STDY_01" } + , { 0x0023, 0x0002, 0x0023, 0x0002, + EVR_IS, "BurnedInAnnotation", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SVISION" } + , { 0x0023, 0x0002, 0x0023, 0x0002, + EVR_LO, "CalibrationObject", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS SMS-AX QUANT 1.0" } + , { 0x0023, 0x0002, 0x0023, 0x0002, + EVR_SL, "NumberOfUnarchivedSeries", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_STDY_01" } + , { 0x0023, 0x0003, 0x0023, 0x0003, + EVR_LO, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SVISION" } + , { 0x0023, 0x0003, 0x0023, 0x0003, + EVR_DS, "CalibrationObjectSize", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS SMS-AX QUANT 1.0" } + , { 0x0023, 0x0004, 0x0023, 0x0004, + EVR_LO, "CalibrationMethod", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS SMS-AX QUANT 1.0" } + , { 0x0023, 0x0005, 0x0023, 0x0005, + EVR_ST, "Filename", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS SMS-AX QUANT 1.0" } + , { 0x0023, 0x0006, 0x0023, 0x0006, + EVR_IS, "FrameNumber", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS SMS-AX QUANT 1.0" } + , { 0x0023, 0x0007, 0x0023, 0x0007, + EVR_IS, "CalibrationFactorMultiplicity", 2, 2, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS SMS-AX QUANT 1.0" } + , { 0x0023, 0x0008, 0x0023, 0x0008, + EVR_IS, "CalibrationTODValue", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS SMS-AX QUANT 1.0" } + , { 0x0023, 0x000d, 0x0023, 0x000d, + EVR_UI, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 2;1" } + , { 0x0023, 0x000e, 0x0023, 0x000e, + EVR_UI, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 2;1" } + , { 0x0023, 0x0010, 0x0023, 0x0010, + EVR_US, "CRDRN", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACRQA_2.0 BLOCK3" } + , { 0x0023, 0x0010, 0x0023, 0x0010, + EVR_US, "CRDRN", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACRQA_1.0 BLOCK3" } + , { 0x0023, 0x0010, 0x0023, 0x0010, + EVR_SS, "ReferenceImageField", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_STDY_01" } + , { 0x0023, 0x0010, 0x0023, 0x0010, + EVR_SQ, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "FDMS 1.0" } + , { 0x0023, 0x0010, 0x0023, 0x0010, + EVR_LO, "CRExposureMenuString", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACRQA_2.0 BLOCK1" } + , { 0x0023, 0x0010, 0x0023, 0x0010, + EVR_LO, "CRExposureMenuString", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACRQA_1.0 BLOCK1" } + , { 0x0023, 0x0010, 0x0023, 0x0010, + EVR_LO, "CRCShift", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACRQA_2.0 BLOCK2" } + , { 0x0023, 0x0010, 0x0023, 0x0010, + EVR_DS, "CRCShift", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACRQA_1.0 BLOCK2" } + , { 0x0023, 0x0020, 0x0023, 0x0020, + EVR_DS, "CRORE", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACRQA_2.0 BLOCK3" } + , { 0x0023, 0x0020, 0x0023, 0x0020, + EVR_DS, "CRORE", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACRQA_1.0 BLOCK3" } + , { 0x0023, 0x0020, 0x0023, 0x0020, + EVR_SQ, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "FDMS 1.0" } + , { 0x0023, 0x0020, 0x0023, 0x0020, + EVR_LO, "CREDRMode", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACRQA_2.0 BLOCK1" } + , { 0x0023, 0x0020, 0x0023, 0x0020, + EVR_LO, "CREDRMode", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACRQA_1.0 BLOCK1" } + , { 0x0023, 0x0020, 0x0023, 0x0020, + EVR_LO, "CRGT", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACRQA_2.0 BLOCK2" } + , { 0x0023, 0x0020, 0x0023, 0x0020, + EVR_DS, "CRGT", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACRQA_1.0 BLOCK2" } + , { 0x0023, 0x0030, 0x0023, 0x0030, + EVR_US, "CRORN", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACRQA_2.0 BLOCK3" } + , { 0x0023, 0x0030, 0x0023, 0x0030, + EVR_US, "CRORN", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACRQA_1.0 BLOCK3" } + , { 0x0023, 0x0030, 0x0023, 0x0030, + EVR_SQ, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "FDMS 1.0" } + , { 0x0023, 0x0030, 0x0023, 0x0030, + EVR_LO, "CRLatitude", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACRQA_2.0 BLOCK1" } + , { 0x0023, 0x0030, 0x0023, 0x0030, + EVR_LO, "CRLatitude", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACRQA_1.0 BLOCK1" } + , { 0x0023, 0x0030, 0x0023, 0x0030, + EVR_DS, "CRGA", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACRQA_2.0 BLOCK2" } + , { 0x0023, 0x0030, 0x0023, 0x0030, + EVR_DS, "CRGA", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACRQA_1.0 BLOCK2" } + , { 0x0023, 0x0040, 0x0023, 0x0040, + EVR_US, "CRORD", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACRQA_2.0 BLOCK3" } + , { 0x0023, 0x0040, 0x0023, 0x0040, + EVR_US, "CRORD", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACRQA_1.0 BLOCK3" } + , { 0x0023, 0x0040, 0x0023, 0x0040, + EVR_LO, "CRGroupNumber", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACRQA_2.0 BLOCK1" } + , { 0x0023, 0x0040, 0x0023, 0x0040, + EVR_LO, "CRGroupNumber", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACRQA_1.0 BLOCK1" } + , { 0x0023, 0x0040, 0x0023, 0x0040, + EVR_DS, "CRGC", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACRQA_2.0 BLOCK2" } + , { 0x0023, 0x0040, 0x0023, 0x0040, + EVR_DS, "CRGC", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACRQA_1.0 BLOCK2" } + , { 0x0023, 0x0050, 0x0023, 0x0050, + EVR_LO, "CRCassetteSize", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACRQA_2.0 BLOCK3" } + , { 0x0023, 0x0050, 0x0023, 0x0050, + EVR_LO, "CRCassetteSize", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACRQA_1.0 BLOCK3" } + , { 0x0023, 0x0050, 0x0023, 0x0050, + EVR_SS, "SummaryImage", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_STDY_01" } + , { 0x0023, 0x0050, 0x0023, 0x0050, + EVR_US, "CRImageSerialNumber", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACRQA_2.0 BLOCK1" } + , { 0x0023, 0x0050, 0x0023, 0x0050, + EVR_US, "CRImageSerialNumber", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACRQA_1.0 BLOCK1" } + , { 0x0023, 0x0050, 0x0023, 0x0050, + EVR_DS, "CRGS", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACRQA_2.0 BLOCK2" } + , { 0x0023, 0x0050, 0x0023, 0x0050, + EVR_DS, "CRGS", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACRQA_1.0 BLOCK2" } + , { 0x0023, 0x0060, 0x0023, 0x0060, + EVR_LO, "CRMachineID", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACRQA_2.0 BLOCK3" } + , { 0x0023, 0x0060, 0x0023, 0x0060, + EVR_LO, "CRMachineID", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACRQA_1.0 BLOCK3" } + , { 0x0023, 0x0060, 0x0023, 0x0060, + EVR_LO, "CRBarCodeNumber", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACRQA_2.0 BLOCK1" } + , { 0x0023, 0x0060, 0x0023, 0x0060, + EVR_LO, "CRBarCodeNumber", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACRQA_1.0 BLOCK1" } + , { 0x0023, 0x0060, 0x0023, 0x0060, + EVR_LO, "CRRT", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACRQA_2.0 BLOCK2" } + , { 0x0023, 0x0060, 0x0023, 0x0060, + EVR_DS, "CRRT", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACRQA_1.0 BLOCK2" } + , { 0x0023, 0x0070, 0x0023, 0x0070, + EVR_LO, "CRMachineType", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACRQA_2.0 BLOCK3" } + , { 0x0023, 0x0070, 0x0023, 0x0070, + EVR_LO, "CRMachineType", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACRQA_1.0 BLOCK3" } + , { 0x0023, 0x0070, 0x0023, 0x0070, + EVR_FD, "StartTimeSecsInFirstAxial", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_STDY_01" } + , { 0x0023, 0x0070, 0x0023, 0x0070, + EVR_LO, "CRFilmOutputExposure", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACRQA_2.0 BLOCK1" } + , { 0x0023, 0x0070, 0x0023, 0x0070, + EVR_LO, "CRFilmOutputExposure", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACRQA_1.0 BLOCK1" } + , { 0x0023, 0x0070, 0x0023, 0x0070, + EVR_DS, "CRRE", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACRQA_2.0 BLOCK2" } + , { 0x0023, 0x0070, 0x0023, 0x0070, + EVR_DS, "CRRE", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACRQA_1.0 BLOCK2" } + , { 0x0023, 0x0074, 0x0023, 0x0074, + EVR_SL, "NumberOfUpdatesToHeader", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_STDY_01" } + , { 0x0023, 0x007d, 0x0023, 0x007d, + EVR_SS, "IndicatesIfStudyHasCompleteInfo", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_STDY_01" } + , { 0x0023, 0x0080, 0x0023, 0x0080, + EVR_LO, "CRFilmFormat", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACRQA_2.0 BLOCK1" } + , { 0x0023, 0x0080, 0x0023, 0x0080, + EVR_LO, "CRFilmFormat", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACRQA_1.0 BLOCK1" } + , { 0x0023, 0x0080, 0x0023, 0x0080, + EVR_US, "CRRN", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACRQA_2.0 BLOCK2" } + , { 0x0023, 0x0080, 0x0023, 0x0080, + EVR_US, "CRRN", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACRQA_1.0 BLOCK2" } + , { 0x0023, 0x0080, 0x0023, 0x0080, + EVR_LO, "CRTechnicianCode", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACRQA_2.0 BLOCK3" } + , { 0x0023, 0x0080, 0x0023, 0x0080, + EVR_LO, "CRTechnicianCode", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACRQA_1.0 BLOCK3" } + , { 0x0023, 0x0090, 0x0023, 0x0090, + EVR_LO, "CRSShiftString", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACRQA_2.0 BLOCK1" } + , { 0x0023, 0x0090, 0x0023, 0x0090, + EVR_LO, "CRSShiftString", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACRQA_1.0 BLOCK1" } + , { 0x0023, 0x0090, 0x0023, 0x0090, + EVR_DS, "CRDRT", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACRQA_2.0 BLOCK2" } + , { 0x0023, 0x0090, 0x0023, 0x0090, + EVR_DS, "CRDRT", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACRQA_1.0 BLOCK2" } + , { 0x0023, 0x0090, 0x0023, 0x0090, + EVR_LO, "CREnergySubtractionParameters", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACRQA_2.0 BLOCK3" } + , { 0x0023, 0x0090, 0x0023, 0x0090, + EVR_LO, "CREnergySubtractionParameters", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACRQA_1.0 BLOCK3" } + , { 0x0023, 0x00f0, 0x0023, 0x00f0, + EVR_IS, "ImageSOPClass", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SVISION" } + , { 0x0023, 0x00f0, 0x0023, 0x00f0, + EVR_LO, "CRDistributionCode", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACRQA_2.0 BLOCK3" } + , { 0x0023, 0x00ff, 0x0023, 0x00ff, + EVR_US, "CRShuttersApplied", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ACRQA_2.0 BLOCK3" } +#endif + , { 0x0024, 0x0010, 0x0024, 0x0010, + EVR_FL, "VisualFieldHorizontalExtent", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0024, 0x0011, 0x0024, 0x0011, + EVR_FL, "VisualFieldVerticalExtent", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0024, 0x0012, 0x0024, 0x0012, + EVR_CS, "VisualFieldShape", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0024, 0x0016, 0x0024, 0x0016, + EVR_SQ, "ScreeningTestModeCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0024, 0x0018, 0x0024, 0x0018, + EVR_FL, "MaximumStimulusLuminance", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0024, 0x0020, 0x0024, 0x0020, + EVR_FL, "BackgroundLuminance", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0024, 0x0021, 0x0024, 0x0021, + EVR_SQ, "StimulusColorCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0024, 0x0024, 0x0024, 0x0024, + EVR_SQ, "BackgroundIlluminationColorCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0024, 0x0025, 0x0024, 0x0025, + EVR_FL, "StimulusArea", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0024, 0x0028, 0x0024, 0x0028, + EVR_FL, "StimulusPresentationTime", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0024, 0x0032, 0x0024, 0x0032, + EVR_SQ, "FixationSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0024, 0x0033, 0x0024, 0x0033, + EVR_SQ, "FixationMonitoringCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0024, 0x0034, 0x0024, 0x0034, + EVR_SQ, "VisualFieldCatchTrialSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0024, 0x0035, 0x0024, 0x0035, + EVR_US, "FixationCheckedQuantity", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0024, 0x0036, 0x0024, 0x0036, + EVR_US, "PatientNotProperlyFixatedQuantity", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0024, 0x0037, 0x0024, 0x0037, + EVR_CS, "PresentedVisualStimuliDataFlag", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0024, 0x0038, 0x0024, 0x0038, + EVR_US, "NumberOfVisualStimuli", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0024, 0x0039, 0x0024, 0x0039, + EVR_CS, "ExcessiveFixationLossesDataFlag", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0024, 0x0040, 0x0024, 0x0040, + EVR_CS, "ExcessiveFixationLosses", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0024, 0x0042, 0x0024, 0x0042, + EVR_US, "StimuliRetestingQuantity", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0024, 0x0044, 0x0024, 0x0044, + EVR_LT, "CommentsOnPatientPerformanceOfVisualField", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0024, 0x0045, 0x0024, 0x0045, + EVR_CS, "FalseNegativesEstimateFlag", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0024, 0x0046, 0x0024, 0x0046, + EVR_FL, "FalseNegativesEstimate", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0024, 0x0048, 0x0024, 0x0048, + EVR_US, "NegativeCatchTrialsQuantity", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0024, 0x0050, 0x0024, 0x0050, + EVR_US, "FalseNegativesQuantity", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0024, 0x0051, 0x0024, 0x0051, + EVR_CS, "ExcessiveFalseNegativesDataFlag", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0024, 0x0052, 0x0024, 0x0052, + EVR_CS, "ExcessiveFalseNegatives", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0024, 0x0053, 0x0024, 0x0053, + EVR_CS, "FalsePositivesEstimateFlag", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0024, 0x0054, 0x0024, 0x0054, + EVR_FL, "FalsePositivesEstimate", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0024, 0x0055, 0x0024, 0x0055, + EVR_CS, "CatchTrialsDataFlag", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0024, 0x0056, 0x0024, 0x0056, + EVR_US, "PositiveCatchTrialsQuantity", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0024, 0x0057, 0x0024, 0x0057, + EVR_CS, "TestPointNormalsDataFlag", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0024, 0x0058, 0x0024, 0x0058, + EVR_SQ, "TestPointNormalsSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0024, 0x0059, 0x0024, 0x0059, + EVR_CS, "GlobalDeviationProbabilityNormalsFlag", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0024, 0x0060, 0x0024, 0x0060, + EVR_US, "FalsePositivesQuantity", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0024, 0x0061, 0x0024, 0x0061, + EVR_CS, "ExcessiveFalsePositivesDataFlag", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0024, 0x0062, 0x0024, 0x0062, + EVR_CS, "ExcessiveFalsePositives", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0024, 0x0063, 0x0024, 0x0063, + EVR_CS, "VisualFieldTestNormalsFlag", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0024, 0x0064, 0x0024, 0x0064, + EVR_SQ, "ResultsNormalsSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0024, 0x0065, 0x0024, 0x0065, + EVR_SQ, "AgeCorrectedSensitivityDeviationAlgorithmSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0024, 0x0066, 0x0024, 0x0066, + EVR_FL, "GlobalDeviationFromNormal", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0024, 0x0067, 0x0024, 0x0067, + EVR_SQ, "GeneralizedDefectSensitivityDeviationAlgorithmSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0024, 0x0068, 0x0024, 0x0068, + EVR_FL, "LocalizedDeviationFromNormal", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0024, 0x0069, 0x0024, 0x0069, + EVR_LO, "PatientReliabilityIndicator", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0024, 0x0070, 0x0024, 0x0070, + EVR_FL, "VisualFieldMeanSensitivity", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0024, 0x0071, 0x0024, 0x0071, + EVR_FL, "GlobalDeviationProbability", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0024, 0x0072, 0x0024, 0x0072, + EVR_CS, "LocalDeviationProbabilityNormalsFlag", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0024, 0x0073, 0x0024, 0x0073, + EVR_FL, "LocalizedDeviationProbability", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0024, 0x0074, 0x0024, 0x0074, + EVR_CS, "ShortTermFluctuationCalculated", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0024, 0x0075, 0x0024, 0x0075, + EVR_FL, "ShortTermFluctuation", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0024, 0x0076, 0x0024, 0x0076, + EVR_CS, "ShortTermFluctuationProbabilityCalculated", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0024, 0x0077, 0x0024, 0x0077, + EVR_FL, "ShortTermFluctuationProbability", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0024, 0x0078, 0x0024, 0x0078, + EVR_CS, "CorrectedLocalizedDeviationFromNormalCalculated", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0024, 0x0079, 0x0024, 0x0079, + EVR_FL, "CorrectedLocalizedDeviationFromNormal", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0024, 0x0080, 0x0024, 0x0080, + EVR_CS, "CorrectedLocalizedDeviationFromNormalProbabilityCalculated", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0024, 0x0081, 0x0024, 0x0081, + EVR_FL, "CorrectedLocalizedDeviationFromNormalProbability", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0024, 0x0083, 0x0024, 0x0083, + EVR_SQ, "GlobalDeviationProbabilitySequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0024, 0x0085, 0x0024, 0x0085, + EVR_SQ, "LocalizedDeviationProbabilitySequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0024, 0x0086, 0x0024, 0x0086, + EVR_CS, "FovealSensitivityMeasured", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0024, 0x0087, 0x0024, 0x0087, + EVR_FL, "FovealSensitivity", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0024, 0x0088, 0x0024, 0x0088, + EVR_FL, "VisualFieldTestDuration", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0024, 0x0089, 0x0024, 0x0089, + EVR_SQ, "VisualFieldTestPointSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0024, 0x0090, 0x0024, 0x0090, + EVR_FL, "VisualFieldTestPointXCoordinate", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0024, 0x0091, 0x0024, 0x0091, + EVR_FL, "VisualFieldTestPointYCoordinate", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0024, 0x0092, 0x0024, 0x0092, + EVR_FL, "AgeCorrectedSensitivityDeviationValue", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0024, 0x0093, 0x0024, 0x0093, + EVR_CS, "StimulusResults", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0024, 0x0094, 0x0024, 0x0094, + EVR_FL, "SensitivityValue", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0024, 0x0095, 0x0024, 0x0095, + EVR_CS, "RetestStimulusSeen", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0024, 0x0096, 0x0024, 0x0096, + EVR_FL, "RetestSensitivityValue", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0024, 0x0097, 0x0024, 0x0097, + EVR_SQ, "VisualFieldTestPointNormalsSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0024, 0x0098, 0x0024, 0x0098, + EVR_FL, "QuantifiedDefect", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0024, 0x0100, 0x0024, 0x0100, + EVR_FL, "AgeCorrectedSensitivityDeviationProbabilityValue", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0024, 0x0102, 0x0024, 0x0102, + EVR_CS, "GeneralizedDefectCorrectedSensitivityDeviationFlag", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0024, 0x0103, 0x0024, 0x0103, + EVR_FL, "GeneralizedDefectCorrectedSensitivityDeviationValue", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0024, 0x0104, 0x0024, 0x0104, + EVR_FL, "GeneralizedDefectCorrectedSensitivityDeviationProbabilityValue", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0024, 0x0105, 0x0024, 0x0105, + EVR_FL, "MinimumSensitivityValue", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0024, 0x0106, 0x0024, 0x0106, + EVR_CS, "BlindSpotLocalized", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0024, 0x0107, 0x0024, 0x0107, + EVR_FL, "BlindSpotXCoordinate", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0024, 0x0108, 0x0024, 0x0108, + EVR_FL, "BlindSpotYCoordinate", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0024, 0x0110, 0x0024, 0x0110, + EVR_SQ, "VisualAcuityMeasurementSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0024, 0x0112, 0x0024, 0x0112, + EVR_SQ, "RefractiveParametersUsedOnPatientSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0024, 0x0113, 0x0024, 0x0113, + EVR_CS, "MeasurementLaterality", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0024, 0x0114, 0x0024, 0x0114, + EVR_SQ, "OphthalmicPatientClinicalInformationLeftEyeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0024, 0x0115, 0x0024, 0x0115, + EVR_SQ, "OphthalmicPatientClinicalInformationRightEyeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0024, 0x0117, 0x0024, 0x0117, + EVR_CS, "FovealPointNormativeDataFlag", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0024, 0x0118, 0x0024, 0x0118, + EVR_FL, "FovealPointProbabilityValue", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0024, 0x0120, 0x0024, 0x0120, + EVR_CS, "ScreeningBaselineMeasured", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0024, 0x0122, 0x0024, 0x0122, + EVR_SQ, "ScreeningBaselineMeasuredSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0024, 0x0124, 0x0024, 0x0124, + EVR_CS, "ScreeningBaselineType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0024, 0x0126, 0x0024, 0x0126, + EVR_FL, "ScreeningBaselineValue", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0024, 0x0202, 0x0024, 0x0202, + EVR_LO, "AlgorithmSource", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0024, 0x0306, 0x0024, 0x0306, + EVR_LO, "DataSetName", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0024, 0x0307, 0x0024, 0x0307, + EVR_LO, "DataSetVersion", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0024, 0x0308, 0x0024, 0x0308, + EVR_LO, "DataSetSource", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0024, 0x0309, 0x0024, 0x0309, + EVR_LO, "DataSetDescription", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0024, 0x0317, 0x0024, 0x0317, + EVR_SQ, "VisualFieldTestReliabilityGlobalIndexSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0024, 0x0320, 0x0024, 0x0320, + EVR_SQ, "VisualFieldGlobalResultsIndexSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0024, 0x0325, 0x0024, 0x0325, + EVR_SQ, "DataObservationSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0024, 0x0338, 0x0024, 0x0338, + EVR_CS, "IndexNormalsFlag", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0024, 0x0341, 0x0024, 0x0341, + EVR_FL, "IndexProbability", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0024, 0x0344, 0x0024, 0x0344, + EVR_SQ, "IndexProbabilitySequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } +#ifdef ENABLE_PRIVATE_TAGS + , { 0x0025, 0x0000, 0x0025, 0x0000, + EVR_IS, "OriginalImage", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SVISION" } + , { 0x0025, 0x0000, 0x0025, 0x0000, + EVR_US, "ViewNative", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS SMS-AX ORIGINAL IMAGE INFO 1.0" } + , { 0x0025, 0x0001, 0x0025, 0x0001, + EVR_IS, "NotProcessedImage", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SVISION" } + , { 0x0025, 0x0001, 0x0025, 0x0001, + EVR_US, "OriginalSeriesNumber", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS SMS-AX ORIGINAL IMAGE INFO 1.0" } + , { 0x0025, 0x0002, 0x0025, 0x0002, + EVR_IS, "CutOutImage", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SVISION" } + , { 0x0025, 0x0002, 0x0025, 0x0002, + EVR_US, "OriginalImageNumber", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS SMS-AX ORIGINAL IMAGE INFO 1.0" } + , { 0x0025, 0x0003, 0x0025, 0x0003, + EVR_IS, "DuplicatedImage", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SVISION" } + , { 0x0025, 0x0003, 0x0025, 0x0003, + EVR_US, "WinCenter", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS SMS-AX ORIGINAL IMAGE INFO 1.0" } + , { 0x0025, 0x0004, 0x0025, 0x0004, + EVR_IS, "StoredImage", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SVISION" } + , { 0x0025, 0x0004, 0x0025, 0x0004, + EVR_US, "WinWidth", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS SMS-AX ORIGINAL IMAGE INFO 1.0" } + , { 0x0025, 0x0005, 0x0025, 0x0005, + EVR_IS, "RetrievedImage", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SVISION" } + , { 0x0025, 0x0005, 0x0025, 0x0005, + EVR_US, "WinBrightness", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS SMS-AX ORIGINAL IMAGE INFO 1.0" } + , { 0x0025, 0x0006, 0x0025, 0x0006, + EVR_IS, "RemoteImage", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SVISION" } + , { 0x0025, 0x0006, 0x0025, 0x0006, + EVR_US, "WinContrast", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS SMS-AX ORIGINAL IMAGE INFO 1.0" } + , { 0x0025, 0x0006, 0x0025, 0x0006, + EVR_SS, "LastPulseSequenceUsed", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_SERS_01" } + , { 0x0025, 0x0007, 0x0025, 0x0007, + EVR_IS, "MediaStoredImage", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SVISION" } + , { 0x0025, 0x0007, 0x0025, 0x0007, + EVR_US, "OriginalFrameNumber", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS SMS-AX ORIGINAL IMAGE INFO 1.0" } + , { 0x0025, 0x0007, 0x0025, 0x0007, + EVR_SL, "ImagesInSeries", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_SERS_01" } + , { 0x0025, 0x0008, 0x0025, 0x0008, + EVR_IS, "ImageState", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SVISION" } + , { 0x0025, 0x0008, 0x0025, 0x0008, + EVR_US, "OriginalMaskFrameNumber", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS SMS-AX ORIGINAL IMAGE INFO 1.0" } + , { 0x0025, 0x0009, 0x0025, 0x0009, + EVR_US, "Opac", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS SMS-AX ORIGINAL IMAGE INFO 1.0" } + , { 0x0025, 0x000a, 0x0025, 0x000a, + EVR_US, "OriginalNumberOfFrames", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS SMS-AX ORIGINAL IMAGE INFO 1.0" } + , { 0x0025, 0x000b, 0x0025, 0x000b, + EVR_DS, "OriginalSceneDuration", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS SMS-AX ORIGINAL IMAGE INFO 1.0" } + , { 0x0025, 0x000c, 0x0025, 0x000c, + EVR_LO, "IdentifierLOID", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS SMS-AX ORIGINAL IMAGE INFO 1.0" } + , { 0x0025, 0x000d, 0x0025, 0x000d, + EVR_SS, "OriginalSceneVFRInfo", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS SMS-AX ORIGINAL IMAGE INFO 1.0" } + , { 0x0025, 0x000e, 0x0025, 0x000e, + EVR_SS, "OriginalFrameECGPosition", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS SMS-AX ORIGINAL IMAGE INFO 1.0" } + , { 0x0025, 0x000f, 0x0025, 0x000f, + EVR_SS, "OriginalECG1stFrameOffset_retired", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS SMS-AX ORIGINAL IMAGE INFO 1.0" } + , { 0x0025, 0x0010, 0x0025, 0x0010, + EVR_US, "RelativeLightEmissionAmountSk", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "FDMS 1.0" } + , { 0x0025, 0x0010, 0x0025, 0x0010, + EVR_SS, "ZoomFlag", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS SMS-AX ORIGINAL IMAGE INFO 1.0" } + , { 0x0025, 0x0010, 0x0025, 0x0010, + EVR_SL, "LandmarkCounter", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_SERS_01" } + , { 0x0025, 0x0011, 0x0025, 0x0011, + EVR_US, "TermOfCorrectionForEachIPTypeSt", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "FDMS 1.0" } + , { 0x0025, 0x0011, 0x0025, 0x0011, + EVR_US, "Flex", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS SMS-AX ORIGINAL IMAGE INFO 1.0" } + , { 0x0025, 0x0011, 0x0025, 0x0011, + EVR_SS, "NumberOfAcquisitions", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_SERS_01" } + , { 0x0025, 0x0012, 0x0025, 0x0012, + EVR_US, "ReadingGainGp", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "FDMS 1.0" } + , { 0x0025, 0x0012, 0x0025, 0x0012, + EVR_US, "NumberOfMaskFrames", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS SMS-AX ORIGINAL IMAGE INFO 1.0" } + , { 0x0025, 0x0013, 0x0025, 0x0013, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "FDMS 1.0" } + , { 0x0025, 0x0013, 0x0025, 0x0013, + EVR_US, "NumberOfFillFrames", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS SMS-AX ORIGINAL IMAGE INFO 1.0" } + , { 0x0025, 0x0014, 0x0025, 0x0014, + EVR_US, "SeriesNumber", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS SMS-AX ORIGINAL IMAGE INFO 1.0" } + , { 0x0025, 0x0014, 0x0025, 0x0014, + EVR_SL, "IndicatesNumberOfUpdatesToHeader", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_SERS_01" } + , { 0x0025, 0x0015, 0x0025, 0x0015, + EVR_CS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "FDMS 1.0" } + , { 0x0025, 0x0015, 0x0025, 0x0015, + EVR_IS, "ImageNumber", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS SMS-AX ORIGINAL IMAGE INFO 1.0" } + , { 0x0025, 0x0017, 0x0025, 0x0017, + EVR_SL, "SeriesCompleteFlag", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_SERS_01" } + , { 0x0025, 0x0018, 0x0025, 0x0018, + EVR_SL, "NumberOfImagesArchived", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_SERS_01" } + , { 0x0025, 0x0019, 0x0025, 0x0019, + EVR_SL, "LastImageNumberUsed", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_SERS_01" } + , { 0x0025, 0x001a, 0x0025, 0x001a, + EVR_SH, "PrimaryReceiverSuiteAndHost", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_SERS_01" } + , { 0x0025, 0x0020, 0x0025, 0x0020, + EVR_LO, "SourceImageFile", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SVISION" } + , { 0x0025, 0x0020, 0x0025, 0x0020, + EVR_US, "Unknown", 2, 2, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "FDMS 1.0" } + , { 0x0025, 0x0021, 0x0025, 0x0021, + EVR_UI, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SVISION" } + , { 0x0025, 0x0021, 0x0025, 0x0021, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "FDMS 1.0" } + , { 0x0025, 0x0030, 0x0025, 0x0030, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "FDMS 1.0" } + , { 0x0025, 0x0031, 0x0025, 0x0031, + EVR_SS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "FDMS 1.0" } + , { 0x0025, 0x0032, 0x0025, 0x0032, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "FDMS 1.0" } + , { 0x0025, 0x0033, 0x0025, 0x0033, + EVR_SS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "FDMS 1.0" } + , { 0x0025, 0x0034, 0x0025, 0x0034, + EVR_SS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "FDMS 1.0" } + , { 0x0025, 0x0040, 0x0025, 0x0040, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "FDMS 1.0" } + , { 0x0025, 0x0041, 0x0025, 0x0041, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "FDMS 1.0" } + , { 0x0025, 0x0042, 0x0025, 0x0042, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "FDMS 1.0" } + , { 0x0025, 0x0043, 0x0025, 0x0043, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "FDMS 1.0" } + , { 0x0025, 0x0050, 0x0025, 0x0050, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "FDMS 1.0" } + , { 0x0025, 0x0051, 0x0025, 0x0051, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "FDMS 1.0" } + , { 0x0025, 0x0052, 0x0025, 0x0052, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "FDMS 1.0" } + , { 0x0025, 0x0053, 0x0025, 0x0053, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "FDMS 1.0" } + , { 0x0025, 0x0060, 0x0025, 0x0060, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "FDMS 1.0" } + , { 0x0025, 0x0061, 0x0025, 0x0061, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "FDMS 1.0" } + , { 0x0025, 0x0062, 0x0025, 0x0062, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "FDMS 1.0" } + , { 0x0025, 0x0063, 0x0025, 0x0063, + EVR_CS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "FDMS 1.0" } + , { 0x0025, 0x0070, 0x0025, 0x0070, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "FDMS 1.0" } + , { 0x0025, 0x0071, 0x0025, 0x0071, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "FDMS 1.0" } + , { 0x0025, 0x0072, 0x0025, 0x0072, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "FDMS 1.0" } + , { 0x0025, 0x0073, 0x0025, 0x0073, + EVR_US, "Unknown", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "FDMS 1.0" } + , { 0x0025, 0x0074, 0x0025, 0x0074, + EVR_US, "Unknown", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "FDMS 1.0" } + , { 0x0025, 0x0080, 0x0025, 0x0080, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "FDMS 1.0" } + , { 0x0025, 0x0081, 0x0025, 0x0081, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "FDMS 1.0" } + , { 0x0025, 0x0082, 0x0025, 0x0082, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "FDMS 1.0" } + , { 0x0025, 0x0083, 0x0025, 0x0083, + EVR_US, "Unknown", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "FDMS 1.0" } + , { 0x0025, 0x0084, 0x0025, 0x0084, + EVR_US, "Unknown", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "FDMS 1.0" } + , { 0x0025, 0x0090, 0x0025, 0x0090, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "FDMS 1.0" } + , { 0x0025, 0x0091, 0x0025, 0x0091, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "FDMS 1.0" } + , { 0x0025, 0x0092, 0x0025, 0x0092, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "FDMS 1.0" } + , { 0x0025, 0x0093, 0x0025, 0x0093, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "FDMS 1.0" } + , { 0x0025, 0x0094, 0x0025, 0x0094, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "FDMS 1.0" } + , { 0x0025, 0x0095, 0x0025, 0x0095, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "FDMS 1.0" } + , { 0x0025, 0x0096, 0x0025, 0x0096, + EVR_CS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "FDMS 1.0" } + , { 0x0025, 0x00a0, 0x0025, 0x00a0, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "FDMS 1.0" } + , { 0x0025, 0x00a1, 0x0025, 0x00a1, + EVR_SS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "FDMS 1.0" } + , { 0x0025, 0x00a2, 0x0025, 0x00a2, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "FDMS 1.0" } + , { 0x0025, 0x00a3, 0x0025, 0x00a3, + EVR_SS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "FDMS 1.0" } + , { 0x0025, 0x1010, 0x0025, 0x1010, + EVR_LO, "WorkspaceID", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "CMR42 CIRCLECVI" } + , { 0x0025, 0x1020, 0x0025, 0x1020, + EVR_LO, "WorkspaceTimeString", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "CMR42 CIRCLECVI" } + , { 0x0025, 0x1030, 0x0025, 0x1030, + EVR_OB, "WorkspaceStream", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "CMR42 CIRCLECVI" } + , { 0x0027, 0x0000, 0x0027, 0x0000, + EVR_IS, "NumberOfSeries", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SVISION" } + , { 0x0027, 0x0000, 0x0027, 0x0000, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/LAST" } + , { 0x0027, 0x0001, 0x0027, 0x0001, + EVR_IS, "NumberOfStudies", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SVISION" } + , { 0x0027, 0x0006, 0x0027, 0x0006, + EVR_SL, "ImageArchiveFlag", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_IMAG_01" } + , { 0x0027, 0x0010, 0x0027, 0x0010, + EVR_DT, "OldestSeries", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SVISION" } + , { 0x0027, 0x0010, 0x0027, 0x0010, + EVR_SQ, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "FDMS 1.0" } + , { 0x0027, 0x0010, 0x0027, 0x0010, + EVR_SS, "ScoutType", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_IMAG_01" } + , { 0x0027, 0x0011, 0x0027, 0x0011, + EVR_DT, "NewestSeries", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SVISION" } + , { 0x0027, 0x0011, 0x0027, 0x0011, + EVR_US, "Unknown", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/LAST" } + , { 0x0027, 0x0012, 0x0027, 0x0012, + EVR_DT, "OldestStudy", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SVISION" } + , { 0x0027, 0x0012, 0x0027, 0x0012, + EVR_DS, "Unknown", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/LAST" } + , { 0x0027, 0x0013, 0x0027, 0x0013, + EVR_DT, "NewestStudy", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SVISION" } + , { 0x0027, 0x0013, 0x0027, 0x0013, + EVR_DS, "Unknown", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/LAST" } + , { 0x0027, 0x0014, 0x0027, 0x0014, + EVR_DS, "Unknown", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/LAST" } + , { 0x0027, 0x0015, 0x0027, 0x0015, + EVR_DS, "Unknown", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/LAST" } + , { 0x0027, 0x0016, 0x0027, 0x0016, + EVR_LO, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/LAST" } + , { 0x0027, 0x001c, 0x0027, 0x001c, + EVR_SL, "VmaMamp", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_IMAG_01" } + , { 0x0027, 0x001d, 0x0027, 0x001d, + EVR_SS, "VmaPhase", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_IMAG_01" } + , { 0x0027, 0x001e, 0x0027, 0x001e, + EVR_SL, "VmaMod", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_IMAG_01" } + , { 0x0027, 0x001f, 0x0027, 0x001f, + EVR_SL, "VmaClip", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_IMAG_01" } + , { 0x0027, 0x0020, 0x0027, 0x0020, + EVR_SQ, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "FDMS 1.0" } + , { 0x0027, 0x0020, 0x0027, 0x0020, + EVR_SS, "SmartScanOnOffFlag", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_IMAG_01" } + , { 0x0027, 0x0030, 0x0027, 0x0030, + EVR_SQ, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "FDMS 1.0" } + , { 0x0027, 0x0030, 0x0027, 0x0030, + EVR_SH, "ForeignImageRevision", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_IMAG_01" } + , { 0x0027, 0x0031, 0x0027, 0x0031, + EVR_SS, "ImagingMode", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_IMAG_01" } + , { 0x0027, 0x0032, 0x0027, 0x0032, + EVR_SS, "PulseSequence", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_IMAG_01" } + , { 0x0027, 0x0033, 0x0027, 0x0033, + EVR_SL, "ImagingOptions", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_IMAG_01" } + , { 0x0027, 0x0035, 0x0027, 0x0035, + EVR_SS, "PlaneType", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_IMAG_01" } + , { 0x0027, 0x0036, 0x0027, 0x0036, + EVR_SL, "ObliquePlane", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_IMAG_01" } + , { 0x0027, 0x0040, 0x0027, 0x0040, + EVR_SQ, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "FDMS 1.0" } + , { 0x0027, 0x0040, 0x0027, 0x0040, + EVR_SH, "RASLetterOfImageLocation", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_IMAG_01" } + , { 0x0027, 0x0041, 0x0027, 0x0041, + EVR_FL, "ImageLocation", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_IMAG_01" } + , { 0x0027, 0x0042, 0x0027, 0x0042, + EVR_FL, "CenterRCoordOfPlaneImage", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_IMAG_01" } + , { 0x0027, 0x0043, 0x0027, 0x0043, + EVR_FL, "CenterACoordOfPlaneImage", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_IMAG_01" } + , { 0x0027, 0x0044, 0x0027, 0x0044, + EVR_FL, "CenterSCoordOfPlaneImage", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_IMAG_01" } + , { 0x0027, 0x0045, 0x0027, 0x0045, + EVR_FL, "NormalRCoord", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_IMAG_01" } + , { 0x0027, 0x0046, 0x0027, 0x0046, + EVR_FL, "NormalACoord", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_IMAG_01" } + , { 0x0027, 0x0047, 0x0027, 0x0047, + EVR_FL, "NormalSCoord", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_IMAG_01" } + , { 0x0027, 0x0048, 0x0027, 0x0048, + EVR_FL, "RCoordOfTopRightCorner", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_IMAG_01" } + , { 0x0027, 0x0049, 0x0027, 0x0049, + EVR_FL, "ACoordOfTopRightCorner", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_IMAG_01" } + , { 0x0027, 0x004a, 0x0027, 0x004a, + EVR_FL, "SCoordOfTopRightCorner", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_IMAG_01" } + , { 0x0027, 0x004b, 0x0027, 0x004b, + EVR_FL, "RCoordOfBottomRightCorner", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_IMAG_01" } + , { 0x0027, 0x004c, 0x0027, 0x004c, + EVR_FL, "ACoordOfBottomRightCorner", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_IMAG_01" } + , { 0x0027, 0x004d, 0x0027, 0x004d, + EVR_FL, "SCoordOfBottomRightCorner", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_IMAG_01" } + , { 0x0027, 0x0050, 0x0027, 0x0050, + EVR_SQ, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "FDMS 1.0" } + , { 0x0027, 0x0050, 0x0027, 0x0050, + EVR_FL, "TableStartLocation", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_IMAG_01" } + , { 0x0027, 0x0051, 0x0027, 0x0051, + EVR_FL, "TableEndLocation", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_IMAG_01" } + , { 0x0027, 0x0052, 0x0027, 0x0052, + EVR_SH, "RASLetterForSideOfImage", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_IMAG_01" } + , { 0x0027, 0x0053, 0x0027, 0x0053, + EVR_SH, "RASLetterForAnteriorPosterior", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_IMAG_01" } + , { 0x0027, 0x0054, 0x0027, 0x0054, + EVR_SH, "RASLetterForScoutStartLoc", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_IMAG_01" } + , { 0x0027, 0x0055, 0x0027, 0x0055, + EVR_SH, "RASLetterForScoutEndLoc", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_IMAG_01" } + , { 0x0027, 0x0060, 0x0027, 0x0060, + EVR_SQ, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "FDMS 1.0" } + , { 0x0027, 0x0060, 0x0027, 0x0060, + EVR_FL, "ImageDimensionX", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_IMAG_01" } + , { 0x0027, 0x0061, 0x0027, 0x0061, + EVR_FL, "ImageDimensionY", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_IMAG_01" } + , { 0x0027, 0x0062, 0x0027, 0x0062, + EVR_FL, "NumberOfExcitations", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_IMAG_01" } + , { 0x0027, 0x0070, 0x0027, 0x0070, + EVR_SQ, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "FDMS 1.0" } + , { 0x0027, 0x0080, 0x0027, 0x0080, + EVR_SQ, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "FDMS 1.0" } + , { 0x0027, 0x00a0, 0x0027, 0x00a0, + EVR_IS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "FDMS 1.0" } + , { 0x0027, 0x00a1, 0x0027, 0x00a1, + EVR_CS, "Unknown", 2, 2, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "FDMS 1.0" } + , { 0x0027, 0x00a2, 0x0027, 0x00a2, + EVR_CS, "Unknown", 2, 2, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "FDMS 1.0" } + , { 0x0027, 0x00a3, 0x0027, 0x00a3, + EVR_SS, "Unknown", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "FDMS 1.0" } +#endif + , { 0x0028, 0x0002, 0x0028, 0x0002, + EVR_US, "SamplesPerPixel", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x0003, 0x0028, 0x0003, + EVR_US, "SamplesPerPixelUsed", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x0004, 0x0028, 0x0004, + EVR_CS, "PhotometricInterpretation", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x0005, 0x0028, 0x0005, + EVR_US, "RETIRED_ImageDimensions", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x0006, 0x0028, 0x0006, + EVR_US, "PlanarConfiguration", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x0008, 0x0028, 0x0008, + EVR_IS, "NumberOfFrames", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x0009, 0x0028, 0x0009, + EVR_AT, "FrameIncrementPointer", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x000a, 0x0028, 0x000a, + EVR_AT, "FrameDimensionPointer", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x0010, 0x0028, 0x0010, + EVR_US, "Rows", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x0011, 0x0028, 0x0011, + EVR_US, "Columns", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x0012, 0x0028, 0x0012, + EVR_US, "RETIRED_Planes", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x0014, 0x0028, 0x0014, + EVR_US, "UltrasoundColorDataPresent", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x0030, 0x0028, 0x0030, + EVR_DS, "PixelSpacing", 2, 2, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x0031, 0x0028, 0x0031, + EVR_DS, "ZoomFactor", 2, 2, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x0032, 0x0028, 0x0032, + EVR_DS, "ZoomCenter", 2, 2, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x0034, 0x0028, 0x0034, + EVR_IS, "PixelAspectRatio", 2, 2, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x0040, 0x0028, 0x0040, + EVR_CS, "RETIRED_ImageFormat", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x0050, 0x0028, 0x0050, + EVR_LO, "RETIRED_ManipulatedImage", 1, -1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x0051, 0x0028, 0x0051, + EVR_CS, "CorrectedImage", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x005f, 0x0028, 0x005f, + EVR_LO, "RETIRED_CompressionRecognitionCode", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x0060, 0x0028, 0x0060, + EVR_CS, "RETIRED_CompressionCode", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x0061, 0x0028, 0x0061, + EVR_SH, "RETIRED_CompressionOriginator", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x0062, 0x0028, 0x0062, + EVR_LO, "RETIRED_CompressionLabel", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x0063, 0x0028, 0x0063, + EVR_SH, "RETIRED_CompressionDescription", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x0065, 0x0028, 0x0065, + EVR_CS, "RETIRED_CompressionSequence", 1, -1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x0066, 0x0028, 0x0066, + EVR_AT, "RETIRED_CompressionStepPointers", 1, -1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x0068, 0x0028, 0x0068, + EVR_US, "RETIRED_RepeatInterval", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x0069, 0x0028, 0x0069, + EVR_US, "RETIRED_BitsGrouped", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x0070, 0x0028, 0x0070, + EVR_US, "RETIRED_PerimeterTable", 1, -1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x0071, 0x0028, 0x0071, + EVR_xs, "RETIRED_PerimeterValue", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x0080, 0x0028, 0x0080, + EVR_US, "RETIRED_PredictorRows", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x0081, 0x0028, 0x0081, + EVR_US, "RETIRED_PredictorColumns", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x0082, 0x0028, 0x0082, + EVR_US, "RETIRED_PredictorConstants", 1, -1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x0090, 0x0028, 0x0090, + EVR_CS, "RETIRED_BlockedPixels", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x0091, 0x0028, 0x0091, + EVR_US, "RETIRED_BlockRows", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x0092, 0x0028, 0x0092, + EVR_US, "RETIRED_BlockColumns", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x0093, 0x0028, 0x0093, + EVR_US, "RETIRED_RowOverlap", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x0094, 0x0028, 0x0094, + EVR_US, "RETIRED_ColumnOverlap", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x0100, 0x0028, 0x0100, + EVR_US, "BitsAllocated", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x0101, 0x0028, 0x0101, + EVR_US, "BitsStored", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x0102, 0x0028, 0x0102, + EVR_US, "HighBit", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x0103, 0x0028, 0x0103, + EVR_US, "PixelRepresentation", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x0104, 0x0028, 0x0104, + EVR_xs, "RETIRED_SmallestValidPixelValue", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x0105, 0x0028, 0x0105, + EVR_xs, "RETIRED_LargestValidPixelValue", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x0106, 0x0028, 0x0106, + EVR_xs, "SmallestImagePixelValue", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x0107, 0x0028, 0x0107, + EVR_xs, "LargestImagePixelValue", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x0108, 0x0028, 0x0108, + EVR_xs, "SmallestPixelValueInSeries", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x0109, 0x0028, 0x0109, + EVR_xs, "LargestPixelValueInSeries", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x0110, 0x0028, 0x0110, + EVR_xs, "RETIRED_SmallestImagePixelValueInPlane", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x0111, 0x0028, 0x0111, + EVR_xs, "RETIRED_LargestImagePixelValueInPlane", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x0120, 0x0028, 0x0120, + EVR_xs, "PixelPaddingValue", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x0121, 0x0028, 0x0121, + EVR_xs, "PixelPaddingRangeLimit", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x0122, 0x0028, 0x0122, + EVR_FL, "FloatPixelPaddingValue", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x0123, 0x0028, 0x0123, + EVR_FD, "DoubleFloatPixelPaddingValue", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x0124, 0x0028, 0x0124, + EVR_FL, "FloatPixelPaddingRangeLimit", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x0125, 0x0028, 0x0125, + EVR_FD, "DoubleFloatPixelPaddingRangeLimit", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x0200, 0x0028, 0x0200, + EVR_US, "RETIRED_ImageLocation", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x0300, 0x0028, 0x0300, + EVR_CS, "QualityControlImage", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x0301, 0x0028, 0x0301, + EVR_CS, "BurnedInAnnotation", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x0302, 0x0028, 0x0302, + EVR_CS, "RecognizableVisualFeatures", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x0303, 0x0028, 0x0303, + EVR_CS, "LongitudinalTemporalInformationModified", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x0304, 0x0028, 0x0304, + EVR_UI, "ReferencedColorPaletteInstanceUID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x0400, 0x0028, 0x0400, + EVR_LO, "RETIRED_TransformLabel", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x0401, 0x0028, 0x0401, + EVR_LO, "RETIRED_TransformVersionNumber", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x0402, 0x0028, 0x0402, + EVR_US, "RETIRED_NumberOfTransformSteps", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x0403, 0x0028, 0x0403, + EVR_LO, "RETIRED_SequenceOfCompressedData", 1, -1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x0404, 0x0028, 0x0404, + EVR_AT, "RETIRED_DetailsOfCoefficients", 1, -1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x0410, 0x0028, 0x0410, + EVR_US, "RETIRED_RowsForNthOrderCoefficients", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x0411, 0x0028, 0x0411, + EVR_US, "RETIRED_ColumnsForNthOrderCoefficients", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x0412, 0x0028, 0x0412, + EVR_LO, "RETIRED_CoefficientCoding", 1, -1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x0413, 0x0028, 0x0413, + EVR_AT, "RETIRED_CoefficientCodingPointers", 1, -1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x0700, 0x0028, 0x0700, + EVR_LO, "RETIRED_DCTLabel", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x0701, 0x0028, 0x0701, + EVR_CS, "RETIRED_DataBlockDescription", 1, -1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x0702, 0x0028, 0x0702, + EVR_AT, "RETIRED_DataBlock", 1, -1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x0710, 0x0028, 0x0710, + EVR_US, "RETIRED_NormalizationFactorFormat", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x0720, 0x0028, 0x0720, + EVR_US, "RETIRED_ZonalMapNumberFormat", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x0721, 0x0028, 0x0721, + EVR_AT, "RETIRED_ZonalMapLocation", 1, -1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x0722, 0x0028, 0x0722, + EVR_US, "RETIRED_ZonalMapFormat", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x0730, 0x0028, 0x0730, + EVR_US, "RETIRED_AdaptiveMapFormat", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x0740, 0x0028, 0x0740, + EVR_US, "RETIRED_CodeNumberFormat", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x0800, 0x0028, 0x0800, + EVR_CS, "RETIRED_CodeLabel", 1, -1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x0802, 0x0028, 0x0802, + EVR_US, "RETIRED_NumberOfTables", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x0803, 0x0028, 0x0803, + EVR_AT, "RETIRED_CodeTableLocation", 1, -1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x0804, 0x0028, 0x0804, + EVR_US, "RETIRED_BitsForCodeWord", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x0808, 0x0028, 0x0808, + EVR_AT, "RETIRED_ImageDataLocation", 1, -1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x0a02, 0x0028, 0x0a02, + EVR_CS, "PixelSpacingCalibrationType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x0a04, 0x0028, 0x0a04, + EVR_LO, "PixelSpacingCalibrationDescription", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x1040, 0x0028, 0x1040, + EVR_CS, "PixelIntensityRelationship", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x1041, 0x0028, 0x1041, + EVR_SS, "PixelIntensityRelationshipSign", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x1050, 0x0028, 0x1050, + EVR_DS, "WindowCenter", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x1051, 0x0028, 0x1051, + EVR_DS, "WindowWidth", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x1052, 0x0028, 0x1052, + EVR_DS, "RescaleIntercept", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x1053, 0x0028, 0x1053, + EVR_DS, "RescaleSlope", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x1054, 0x0028, 0x1054, + EVR_LO, "RescaleType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x1055, 0x0028, 0x1055, + EVR_LO, "WindowCenterWidthExplanation", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x1056, 0x0028, 0x1056, + EVR_CS, "VOILUTFunction", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x1080, 0x0028, 0x1080, + EVR_CS, "RETIRED_GrayScale", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x1090, 0x0028, 0x1090, + EVR_CS, "RecommendedViewingMode", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x1100, 0x0028, 0x1100, + EVR_xs, "RETIRED_GrayLookupTableDescriptor", 3, 3, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x1101, 0x0028, 0x1101, + EVR_xs, "RedPaletteColorLookupTableDescriptor", 3, 3, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x1102, 0x0028, 0x1102, + EVR_xs, "GreenPaletteColorLookupTableDescriptor", 3, 3, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x1103, 0x0028, 0x1103, + EVR_xs, "BluePaletteColorLookupTableDescriptor", 3, 3, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x1104, 0x0028, 0x1104, + EVR_US, "AlphaPaletteColorLookupTableDescriptor", 3, 3, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x1111, 0x0028, 0x1111, + EVR_xs, "RETIRED_LargeRedPaletteColorLookupTableDescriptor", 4, 4, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x1112, 0x0028, 0x1112, + EVR_xs, "RETIRED_LargeGreenPaletteColorLookupTableDescriptor", 4, 4, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x1113, 0x0028, 0x1113, + EVR_xs, "RETIRED_LargeBluePaletteColorLookupTableDescriptor", 4, 4, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x1199, 0x0028, 0x1199, + EVR_UI, "PaletteColorLookupTableUID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x1200, 0x0028, 0x1200, + EVR_lt, "RETIRED_GrayLookupTableData", 1, -1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x1201, 0x0028, 0x1201, + EVR_OW, "RedPaletteColorLookupTableData", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x1202, 0x0028, 0x1202, + EVR_OW, "GreenPaletteColorLookupTableData", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x1203, 0x0028, 0x1203, + EVR_OW, "BluePaletteColorLookupTableData", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x1204, 0x0028, 0x1204, + EVR_OW, "AlphaPaletteColorLookupTableData", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x1211, 0x0028, 0x1211, + EVR_OW, "RETIRED_LargeRedPaletteColorLookupTableData", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x1212, 0x0028, 0x1212, + EVR_OW, "RETIRED_LargeGreenPaletteColorLookupTableData", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x1213, 0x0028, 0x1213, + EVR_OW, "RETIRED_LargeBluePaletteColorLookupTableData", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x1214, 0x0028, 0x1214, + EVR_UI, "RETIRED_LargePaletteColorLookupTableUID", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x1221, 0x0028, 0x1221, + EVR_OW, "SegmentedRedPaletteColorLookupTableData", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x1222, 0x0028, 0x1222, + EVR_OW, "SegmentedGreenPaletteColorLookupTableData", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x1223, 0x0028, 0x1223, + EVR_OW, "SegmentedBluePaletteColorLookupTableData", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x1224, 0x0028, 0x1224, + EVR_OW, "SegmentedAlphaPaletteColorLookupTableData", 1, 1, "Supplement_156", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x1300, 0x0028, 0x1300, + EVR_CS, "BreastImplantPresent", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x1350, 0x0028, 0x1350, + EVR_CS, "PartialView", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x1351, 0x0028, 0x1351, + EVR_ST, "PartialViewDescription", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x1352, 0x0028, 0x1352, + EVR_SQ, "PartialViewCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x135a, 0x0028, 0x135a, + EVR_CS, "SpatialLocationsPreserved", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x1401, 0x0028, 0x1401, + EVR_SQ, "DataFrameAssignmentSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x1402, 0x0028, 0x1402, + EVR_CS, "DataPathAssignment", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x1403, 0x0028, 0x1403, + EVR_US, "BitsMappedToColorLookupTable", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x1404, 0x0028, 0x1404, + EVR_SQ, "BlendingLUT1Sequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x1405, 0x0028, 0x1405, + EVR_CS, "BlendingLUT1TransferFunction", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x1406, 0x0028, 0x1406, + EVR_FD, "BlendingWeightConstant", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x1407, 0x0028, 0x1407, + EVR_US, "BlendingLookupTableDescriptor", 3, 3, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x1408, 0x0028, 0x1408, + EVR_OW, "BlendingLookupTableData", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x140b, 0x0028, 0x140b, + EVR_SQ, "EnhancedPaletteColorLookupTableSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x140c, 0x0028, 0x140c, + EVR_SQ, "BlendingLUT2Sequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x140d, 0x0028, 0x140d, + EVR_CS, "BlendingLUT2TransferFunction", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x140e, 0x0028, 0x140e, + EVR_CS, "DataPathID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x140f, 0x0028, 0x140f, + EVR_CS, "RGBLUTTransferFunction", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x1410, 0x0028, 0x1410, + EVR_CS, "AlphaLUTTransferFunction", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x2000, 0x0028, 0x2000, + EVR_OB, "ICCProfile", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x2002, 0x0028, 0x2002, + EVR_CS, "ColorSpace", 1, 1, "CP_1454", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x2110, 0x0028, 0x2110, + EVR_CS, "LossyImageCompression", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x2112, 0x0028, 0x2112, + EVR_DS, "LossyImageCompressionRatio", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x2114, 0x0028, 0x2114, + EVR_CS, "LossyImageCompressionMethod", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x3000, 0x0028, 0x3000, + EVR_SQ, "ModalityLUTSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x3002, 0x0028, 0x3002, + EVR_xs, "LUTDescriptor", 3, 3, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x3003, 0x0028, 0x3003, + EVR_LO, "LUTExplanation", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x3004, 0x0028, 0x3004, + EVR_LO, "ModalityLUTType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x3006, 0x0028, 0x3006, + EVR_lt, "LUTData", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x3010, 0x0028, 0x3010, + EVR_SQ, "VOILUTSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x3110, 0x0028, 0x3110, + EVR_SQ, "SoftcopyVOILUTSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x4000, 0x0028, 0x4000, + EVR_LT, "RETIRED_ImagePresentationComments", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x5000, 0x0028, 0x5000, + EVR_SQ, "RETIRED_BiPlaneAcquisitionSequence", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x6010, 0x0028, 0x6010, + EVR_US, "RepresentativeFrameNumber", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x6020, 0x0028, 0x6020, + EVR_US, "FrameNumbersOfInterest", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x6022, 0x0028, 0x6022, + EVR_LO, "FrameOfInterestDescription", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x6023, 0x0028, 0x6023, + EVR_CS, "FrameOfInterestType", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x6030, 0x0028, 0x6030, + EVR_US, "RETIRED_MaskPointers", 1, -1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x6040, 0x0028, 0x6040, + EVR_US, "RWavePointer", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x6100, 0x0028, 0x6100, + EVR_SQ, "MaskSubtractionSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x6101, 0x0028, 0x6101, + EVR_CS, "MaskOperation", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x6102, 0x0028, 0x6102, + EVR_US, "ApplicableFrameRange", 2, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x6110, 0x0028, 0x6110, + EVR_US, "MaskFrameNumbers", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x6112, 0x0028, 0x6112, + EVR_US, "ContrastFrameAveraging", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x6114, 0x0028, 0x6114, + EVR_FL, "MaskSubPixelShift", 2, 2, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x6120, 0x0028, 0x6120, + EVR_SS, "TIDOffset", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x6190, 0x0028, 0x6190, + EVR_ST, "MaskOperationExplanation", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x7000, 0x0028, 0x7000, + EVR_SQ, "EquipmentAdministratorSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x7001, 0x0028, 0x7001, + EVR_US, "NumberOfDisplaySubsystems", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x7002, 0x0028, 0x7002, + EVR_US, "CurrentConfigurationID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x7003, 0x0028, 0x7003, + EVR_US, "DisplaySubsystemID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x7004, 0x0028, 0x7004, + EVR_SH, "DisplaySubsystemName", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x7005, 0x0028, 0x7005, + EVR_LO, "DisplaySubsystemDescription", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x7006, 0x0028, 0x7006, + EVR_CS, "SystemStatus", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x7007, 0x0028, 0x7007, + EVR_LO, "SystemStatusComment", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x7008, 0x0028, 0x7008, + EVR_SQ, "TargetLuminanceCharacteristicsSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x7009, 0x0028, 0x7009, + EVR_US, "LuminanceCharacteristicsID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x700a, 0x0028, 0x700a, + EVR_SQ, "DisplaySubsystemConfigurationSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x700b, 0x0028, 0x700b, + EVR_US, "ConfigurationID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x700c, 0x0028, 0x700c, + EVR_SH, "ConfigurationName", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x700d, 0x0028, 0x700d, + EVR_LO, "ConfigurationDescription", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x700e, 0x0028, 0x700e, + EVR_US, "ReferencedTargetLuminanceCharacteristicsID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x700f, 0x0028, 0x700f, + EVR_SQ, "QAResultsSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x7010, 0x0028, 0x7010, + EVR_SQ, "DisplaySubsystemQAResultsSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x7011, 0x0028, 0x7011, + EVR_SQ, "ConfigurationQAResultsSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x7012, 0x0028, 0x7012, + EVR_SQ, "MeasurementEquipmentSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x7013, 0x0028, 0x7013, + EVR_CS, "MeasurementFunctions", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x7014, 0x0028, 0x7014, + EVR_CS, "MeasurementEquipmentType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x7015, 0x0028, 0x7015, + EVR_SQ, "VisualEvaluationResultSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x7016, 0x0028, 0x7016, + EVR_SQ, "DisplayCalibrationResultSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x7017, 0x0028, 0x7017, + EVR_US, "DDLValue", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x7018, 0x0028, 0x7018, + EVR_FL, "CIExyWhitePoint", 2, 2, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x7019, 0x0028, 0x7019, + EVR_CS, "DisplayFunctionType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x701a, 0x0028, 0x701a, + EVR_FL, "GammaValue", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x701b, 0x0028, 0x701b, + EVR_US, "NumberOfLuminancePoints", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x701c, 0x0028, 0x701c, + EVR_SQ, "LuminanceResponseSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x701d, 0x0028, 0x701d, + EVR_FL, "TargetMinimumLuminance", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x701e, 0x0028, 0x701e, + EVR_FL, "TargetMaximumLuminance", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x701f, 0x0028, 0x701f, + EVR_FL, "LuminanceValue", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x7020, 0x0028, 0x7020, + EVR_LO, "LuminanceResponseDescription", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x7021, 0x0028, 0x7021, + EVR_CS, "WhitePointFlag", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x7022, 0x0028, 0x7022, + EVR_SQ, "DisplayDeviceTypeCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x7023, 0x0028, 0x7023, + EVR_SQ, "DisplaySubsystemSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x7024, 0x0028, 0x7024, + EVR_SQ, "LuminanceResultSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x7025, 0x0028, 0x7025, + EVR_CS, "AmbientLightValueSource", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x7026, 0x0028, 0x7026, + EVR_CS, "MeasuredCharacteristics", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x7027, 0x0028, 0x7027, + EVR_SQ, "LuminanceUniformityResultSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x7028, 0x0028, 0x7028, + EVR_SQ, "VisualEvaluationTestSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x7029, 0x0028, 0x7029, + EVR_CS, "TestResult", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x702a, 0x0028, 0x702a, + EVR_LO, "TestResultComment", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x702b, 0x0028, 0x702b, + EVR_CS, "TestImageValidation", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x702c, 0x0028, 0x702c, + EVR_SQ, "TestPatternCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x702d, 0x0028, 0x702d, + EVR_SQ, "MeasurementPatternCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x702e, 0x0028, 0x702e, + EVR_SQ, "VisualEvaluationMethodCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x7fe0, 0x0028, 0x7fe0, + EVR_UR, "PixelDataProviderURL", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x9001, 0x0028, 0x9001, + EVR_UL, "DataPointRows", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x9002, 0x0028, 0x9002, + EVR_UL, "DataPointColumns", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x9003, 0x0028, 0x9003, + EVR_CS, "SignalDomainColumns", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x9099, 0x0028, 0x9099, + EVR_US, "RETIRED_LargestMonochromePixelValue", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x9108, 0x0028, 0x9108, + EVR_CS, "DataRepresentation", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x9110, 0x0028, 0x9110, + EVR_SQ, "PixelMeasuresSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x9132, 0x0028, 0x9132, + EVR_SQ, "FrameVOILUTSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x9145, 0x0028, 0x9145, + EVR_SQ, "PixelValueTransformationSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x9235, 0x0028, 0x9235, + EVR_CS, "SignalDomainRows", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x9411, 0x0028, 0x9411, + EVR_FL, "DisplayFilterPercentage", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x9415, 0x0028, 0x9415, + EVR_SQ, "FramePixelShiftSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x9416, 0x0028, 0x9416, + EVR_US, "SubtractionItemID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x9422, 0x0028, 0x9422, + EVR_SQ, "PixelIntensityRelationshipLUTSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x9443, 0x0028, 0x9443, + EVR_SQ, "FramePixelDataPropertiesSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x9444, 0x0028, 0x9444, + EVR_CS, "GeometricalProperties", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x9445, 0x0028, 0x9445, + EVR_FL, "GeometricMaximumDistortion", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x9446, 0x0028, 0x9446, + EVR_CS, "ImageProcessingApplied", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x9454, 0x0028, 0x9454, + EVR_CS, "MaskSelectionMode", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x9474, 0x0028, 0x9474, + EVR_CS, "LUTFunction", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x9478, 0x0028, 0x9478, + EVR_FL, "MaskVisibilityPercentage", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x9501, 0x0028, 0x9501, + EVR_SQ, "PixelShiftSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x9502, 0x0028, 0x9502, + EVR_SQ, "RegionPixelShiftSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x9503, 0x0028, 0x9503, + EVR_SS, "VerticesOfTheRegion", 2, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x9505, 0x0028, 0x9505, + EVR_SQ, "MultiFramePresentationSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x9506, 0x0028, 0x9506, + EVR_US, "PixelShiftFrameRange", 2, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x9507, 0x0028, 0x9507, + EVR_US, "LUTFrameRange", 2, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x9520, 0x0028, 0x9520, + EVR_DS, "ImageToEquipmentMappingMatrix", 16, 16, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0028, 0x9537, 0x0028, 0x9537, + EVR_CS, "EquipmentCoordinateSystemIdentification", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } +#ifdef ENABLE_PRIVATE_TAGS + , { 0x0029, 0x0000, 0x0029, 0x0000, + EVR_LT, "ImageEnhancementID", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1;3" } + , { 0x0029, 0x0000, 0x0029, 0x0000, + EVR_LT, "SubtractionMaskID", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1;2" } + , { 0x0029, 0x0000, 0x0029, 0x0000, + EVR_SL, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P-Private_ICS Release 1;1" } + , { 0x0029, 0x0000, 0x0029, 0x0000, + EVR_DS, "Unknown", 2, 2, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/PART" } + , { 0x0029, 0x0000, 0x0029, 0x0000, + EVR_SQ, "EdgeEnhancementSequence", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "CARDIO-D.R. 1.0" } + , { 0x0029, 0x0000, 0x0029, 0x0000, + EVR_UI, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Silhouette Graphics Export V1.0" } + , { 0x0029, 0x0000, 0x0029, 0x0000, + EVR_UN, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P-Private_CDS Release 1" } + , { 0x0029, 0x0000, 0x0029, 0x0000, + EVR_LT, "ZoomID", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1;1" } + , { 0x0029, 0x0000, 0x0029, 0x0000, + EVR_FD, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P-Private_ICS Release 1;2" } + , { 0x0029, 0x0000, 0x0029, 0x0000, + EVR_US, "Unknown", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "AEGIS_DICOM_2.00" } + , { 0x0029, 0x0000, 0x0029, 0x0000, + EVR_DS, "Unknown", 4, 4, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1" } + , { 0x0029, 0x0001, 0x0029, 0x0001, + EVR_LT, "ImageEnhancement", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1;3" } + , { 0x0029, 0x0001, 0x0029, 0x0001, + EVR_US, "ConvolutionKernelSize", 2, 2, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "CARDIO-D.R. 1.0" } + , { 0x0029, 0x0001, 0x0029, 0x0001, + EVR_DS, "ZoomRectangle", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1;1" } + , { 0x0029, 0x0001, 0x0029, 0x0001, + EVR_FD, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P-Private_ICS Release 1;2" } + , { 0x0029, 0x0001, 0x0029, 0x0001, + EVR_FD, "ImageCompressionFraction", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "INTELERAD MEDICAL SYSTEMS" } + , { 0x0029, 0x0002, 0x0029, 0x0002, + EVR_LT, "ConvolutionID", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1;3" } + , { 0x0029, 0x0002, 0x0029, 0x0002, + EVR_DS, "ConvolutionKernelCoefficients", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "CARDIO-D.R. 1.0" } + , { 0x0029, 0x0002, 0x0029, 0x0002, + EVR_SQ, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P-Private_ICS Release 1;4" } + , { 0x0029, 0x0002, 0x0029, 0x0002, + EVR_FD, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P-Private_ICS Release 1;2" } + , { 0x0029, 0x0002, 0x0029, 0x0002, + EVR_FD, "ImageQuality", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "INTELERAD MEDICAL SYSTEMS" } + , { 0x0029, 0x0003, 0x0029, 0x0003, + EVR_LT, "ConvolutionType", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1;3" } + , { 0x0029, 0x0003, 0x0029, 0x0003, + EVR_DS, "EdgeEnhancementGain", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "CARDIO-D.R. 1.0" } + , { 0x0029, 0x0003, 0x0029, 0x0003, + EVR_DS, "ZoomFactor", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1;1" } + , { 0x0029, 0x0003, 0x0029, 0x0003, + EVR_SL, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P-Private_ICS Release 1;2" } + , { 0x0029, 0x0003, 0x0029, 0x0003, + EVR_FD, "ImageBytesTransferred", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "INTELERAD MEDICAL SYSTEMS" } + , { 0x0029, 0x0004, 0x0029, 0x0004, + EVR_LT, "ConvolutionKernelSizeID", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1;3" } + , { 0x0029, 0x0004, 0x0029, 0x0004, + EVR_UN, "MaskingFunction", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1;2" } + , { 0x0029, 0x0004, 0x0029, 0x0004, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/PART" } + , { 0x0029, 0x0004, 0x0029, 0x0004, + EVR_LT, "PhotometricInterpretation", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MED DISPLAY" } + , { 0x0029, 0x0004, 0x0029, 0x0004, + EVR_US, "ZoomFunction", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1;1" } + , { 0x0029, 0x0004, 0x0029, 0x0004, + EVR_SL, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P-Private_ICS Release 1;2" } + , { 0x0029, 0x0004, 0x0029, 0x0004, + EVR_SL, "LowerRangeOfPixels", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_IMPS_01" } + , { 0x0029, 0x0005, 0x0029, 0x0005, + EVR_US, "ConvolutionKernelSize", 2, 2, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1;3" } + , { 0x0029, 0x0005, 0x0029, 0x0005, + EVR_FL, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P-Private_ICS Release 1;1" } + , { 0x0029, 0x0005, 0x0029, 0x0005, + EVR_SL, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P-Private_ICS Release 1;2" } + , { 0x0029, 0x0005, 0x0029, 0x0005, + EVR_DS, "LowerRangeOfPixels", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_IMPS_01" } + , { 0x0029, 0x0006, 0x0029, 0x0006, + EVR_US, "ConvolutionKernel", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1;3" } + , { 0x0029, 0x0006, 0x0029, 0x0006, + EVR_FL, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P-Private_ICS Release 1;1" } + , { 0x0029, 0x0006, 0x0029, 0x0006, + EVR_DS, "LowerRangeOfPixels", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_IMPS_01" } + , { 0x0029, 0x0007, 0x0029, 0x0007, + EVR_SL, "LowerRangeOfPixels", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_IMPS_01" } + , { 0x0029, 0x0008, 0x0029, 0x0008, + EVR_SQ, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P-Private_ICS Release 1" } + , { 0x0029, 0x0008, 0x0029, 0x0008, + EVR_CS, "CSAImageHeaderType", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CSA HEADER" } + , { 0x0029, 0x0008, 0x0029, 0x0008, + EVR_CS, "CSADataType", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CSA NON-IMAGE" } + , { 0x0029, 0x0008, 0x0029, 0x0008, + EVR_CS, "MEDCOMOOGType", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MEDCOM OOG" } + , { 0x0029, 0x0008, 0x0029, 0x0008, + EVR_SH, "LowerRangeOfPixels", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_IMPS_01" } + , { 0x0029, 0x0008, 0x0029, 0x0008, + EVR_IS, "NumberOfExposureResults", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "INTEGRIS 1.0" } + , { 0x0029, 0x0008, 0x0029, 0x0008, + EVR_CS, "MedComHeaderType", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MEDCOM HEADER" } + , { 0x0029, 0x0009, 0x0029, 0x0009, + EVR_LO, "CSAImageHeaderVersion", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CSA HEADER" } + , { 0x0029, 0x0009, 0x0029, 0x0009, + EVR_LO, "CSADataVersion", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CSA NON-IMAGE" } + , { 0x0029, 0x0009, 0x0029, 0x0009, + EVR_LO, "MEDCOMOOGVersion", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MEDCOM OOG" } + , { 0x0029, 0x0009, 0x0029, 0x0009, + EVR_SH, "LowerRangeOfPixels", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_IMPS_01" } + , { 0x0029, 0x0009, 0x0029, 0x0009, + EVR_LO, "MedComHeaderVersion", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MEDCOM HEADER" } + , { 0x0029, 0x000a, 0x0029, 0x000a, + EVR_SS, "LowerRangeOfPixels", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_IMPS_01" } + , { 0x0029, 0x000c, 0x0029, 0x000c, + EVR_DS, "EnhancementGain", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1;3" } + , { 0x0029, 0x000c, 0x0029, 0x000c, + EVR_UN, "ProprietaryMaskingParameters", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1;2" } + , { 0x0029, 0x000e, 0x0029, 0x000e, + EVR_CS, "ZoomEnableStatus", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1;1" } + , { 0x0029, 0x000f, 0x0029, 0x000f, + EVR_SQ, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P-Private_ICS Release 1" } + , { 0x0029, 0x000f, 0x0029, 0x000f, + EVR_CS, "ZoomSelectStatus", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1;1" } + , { 0x0029, 0x0010, 0x0029, 0x0010, + EVR_LT, "Commentline", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "CAMTRONICS" } + , { 0x0029, 0x0010, 0x0029, 0x0010, + EVR_LT, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "CAMTRONICS IP" } + , { 0x0029, 0x0010, 0x0029, 0x0010, + EVR_SQ, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P-Private_ICS Release 1" } + , { 0x0029, 0x0010, 0x0029, 0x0010, + EVR_DS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/PART" } + , { 0x0029, 0x0010, 0x0029, 0x0010, + EVR_US, "ListOfGroupNumbers", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MED HG" } + , { 0x0029, 0x0010, 0x0029, 0x0010, + EVR_LT, "WindowStyle", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CM VA0 CMS" } + , { 0x0029, 0x0010, 0x0029, 0x0010, + EVR_OB, "CSAImageHeaderInfo", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CSA HEADER" } + , { 0x0029, 0x0010, 0x0029, 0x0010, + EVR_US, "RowsOfSubmatrix", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MED DISPLAY" } + , { 0x0029, 0x0010, 0x0029, 0x0010, + EVR_OB, "CSADataInfo", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CSA NON-IMAGE" } + , { 0x0029, 0x0010, 0x0029, 0x0010, + EVR_LO, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P-GV-CT Release 1" } + , { 0x0029, 0x0010, 0x0029, 0x0010, + EVR_OB, "MEDCOMOOGInfo", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MEDCOM OOG" } + , { 0x0029, 0x0010, 0x0029, 0x0010, + EVR_OB, "MedComHeaderInfo", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MEDCOM HEADER" } + , { 0x0029, 0x0010, 0x0029, 0x0010, + EVR_DS, "FPMin", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/LAST" } + , { 0x0029, 0x0010, 0x0029, 0x0010, + EVR_SH, "J2cParameterType", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "INTELERAD MEDICAL SYSTEMS" } + , { 0x0029, 0x0010, 0x0029, 0x0010, + EVR_US, "ListOfGroupNumbers", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MED MG" } + , { 0x0029, 0x0011, 0x0029, 0x0011, + EVR_IS, "LineName", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Silhouette Line V1.0" } + , { 0x0029, 0x0011, 0x0029, 0x0011, + EVR_DS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/PART" } + , { 0x0029, 0x0011, 0x0029, 0x0011, + EVR_LT, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CM VA0 CMS" } + , { 0x0029, 0x0011, 0x0029, 0x0011, + EVR_US, "ColumnsOfSubmatrix", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MED DISPLAY" } + , { 0x0029, 0x0011, 0x0029, 0x0011, + EVR_IS, "ROIName", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Silhouette ROI V1.0" } + , { 0x0029, 0x0011, 0x0029, 0x0011, + EVR_IS, "AnnotationName", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Silhouette Annot V1.0" } + , { 0x0029, 0x0011, 0x0029, 0x0011, + EVR_US, "J2cPixelRepresentation", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "INTELERAD MEDICAL SYSTEMS" } + , { 0x0029, 0x0012, 0x0029, 0x0012, + EVR_LT, "LineNameFont", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Silhouette Line V1.0" } + , { 0x0029, 0x0012, 0x0029, 0x0012, + EVR_LT, "ROINameFont", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Silhouette ROI V1.0" } + , { 0x0029, 0x0012, 0x0029, 0x0012, + EVR_LT, "AnnotationFont", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Silhouette Annot V1.0" } + , { 0x0029, 0x0012, 0x0029, 0x0012, + EVR_US, "J2cBitsAllocated", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "INTELERAD MEDICAL SYSTEMS" } + , { 0x0029, 0x0013, 0x0029, 0x0013, + EVR_UL, "LineNameDisplay", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Silhouette Line V1.0" } + , { 0x0029, 0x0013, 0x0029, 0x0013, + EVR_UL, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Silhouette V1.0" } + , { 0x0029, 0x0013, 0x0029, 0x0013, + EVR_LT, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CM VA0 CMS" } + , { 0x0029, 0x0013, 0x0029, 0x0013, + EVR_LT, "ROINormalColor", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Silhouette ROI V1.0" } + , { 0x0029, 0x0013, 0x0029, 0x0013, + EVR_LT, "AnnotationTextForegroundColor", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Silhouette Annot V1.0" } + , { 0x0029, 0x0013, 0x0029, 0x0013, + EVR_US, "J2cPixelShiftValue", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "INTELERAD MEDICAL SYSTEMS" } + , { 0x0029, 0x0014, 0x0029, 0x0014, + EVR_LT, "LineNormalColor", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Silhouette Line V1.0" } + , { 0x0029, 0x0014, 0x0029, 0x0014, + EVR_UL, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Silhouette V1.0" } + , { 0x0029, 0x0014, 0x0029, 0x0014, + EVR_UL, "ROIFillPattern", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Silhouette ROI V1.0" } + , { 0x0029, 0x0014, 0x0029, 0x0014, + EVR_LT, "AnnotationTextBackgroundColor", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Silhouette Annot V1.0" } + , { 0x0029, 0x0014, 0x0029, 0x0014, + EVR_US, "J2cPlanarConfiguration", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "INTELERAD MEDICAL SYSTEMS" } + , { 0x0029, 0x0015, 0x0029, 0x0015, + EVR_UL, "LineType", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Silhouette Line V1.0" } + , { 0x0029, 0x0015, 0x0029, 0x0015, + EVR_LT, "ListOfShadowOwnerCodes", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MED HG" } + , { 0x0029, 0x0015, 0x0029, 0x0015, + EVR_UL, "ROIBpSeg", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Silhouette ROI V1.0" } + , { 0x0029, 0x0015, 0x0029, 0x0015, + EVR_UL, "AnnotationTextBackingMode", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Silhouette Annot V1.0" } + , { 0x0029, 0x0015, 0x0029, 0x0015, + EVR_SL, "LowerRangeOfPixels", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_IMPS_01" } + , { 0x0029, 0x0015, 0x0029, 0x0015, + EVR_DS, "J2cRescaleIntercept", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "INTELERAD MEDICAL SYSTEMS" } + , { 0x0029, 0x0015, 0x0029, 0x0015, + EVR_LT, "ListOfShadowOwnerCodes", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MED MG" } + , { 0x0029, 0x0016, 0x0029, 0x0016, + EVR_UL, "LineThickness", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Silhouette Line V1.0" } + , { 0x0029, 0x0016, 0x0029, 0x0016, + EVR_UN, "ROIBpSegPairs", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Silhouette ROI V1.0" } + , { 0x0029, 0x0016, 0x0029, 0x0016, + EVR_UL, "AnnotationTextJustification", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Silhouette Annot V1.0" } + , { 0x0029, 0x0016, 0x0029, 0x0016, + EVR_SL, "LowerRangeOfPixels", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_IMPS_01" } + , { 0x0029, 0x0017, 0x0029, 0x0017, + EVR_UL, "LineStyle", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Silhouette Line V1.0" } + , { 0x0029, 0x0017, 0x0029, 0x0017, + EVR_UN, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Silhouette V1.0" } + , { 0x0029, 0x0017, 0x0029, 0x0017, + EVR_UL, "ROISeedSpace", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Silhouette ROI V1.0" } + , { 0x0029, 0x0017, 0x0029, 0x0017, + EVR_UL, "AnnotationTextLocation", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Silhouette Annot V1.0" } + , { 0x0029, 0x0017, 0x0029, 0x0017, + EVR_SL, "LowerRangeOfPixels", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_IMPS_01" } + , { 0x0029, 0x0018, 0x0029, 0x0018, + EVR_UL, "LineDashLength", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Silhouette Line V1.0" } + , { 0x0029, 0x0018, 0x0029, 0x0018, + EVR_UN, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Silhouette V1.0" } + , { 0x0029, 0x0018, 0x0029, 0x0018, + EVR_CS, "CSASeriesHeaderType", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CSA HEADER" } + , { 0x0029, 0x0018, 0x0029, 0x0018, + EVR_UN, "ROISeeds", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Silhouette ROI V1.0" } + , { 0x0029, 0x0018, 0x0029, 0x0018, + EVR_LT, "AnnotationTextString", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Silhouette Annot V1.0" } + , { 0x0029, 0x0018, 0x0029, 0x0018, + EVR_SL, "UpperRangeOfPixels", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_IMPS_01" } + , { 0x0029, 0x0019, 0x0029, 0x0019, + EVR_UL, "LineInteractivity", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Silhouette Line V1.0" } + , { 0x0029, 0x0019, 0x0029, 0x0019, + EVR_UL, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Silhouette V1.0" } + , { 0x0029, 0x0019, 0x0029, 0x0019, + EVR_LO, "CSASeriesHeaderVersion", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CSA HEADER" } + , { 0x0029, 0x0019, 0x0029, 0x0019, + EVR_UL, "ROILineThickness", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Silhouette ROI V1.0" } + , { 0x0029, 0x0019, 0x0029, 0x0019, + EVR_UL, "AnnotationTextAttachMode", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Silhouette Annot V1.0" } + , { 0x0029, 0x001a, 0x0029, 0x001a, + EVR_UN, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Silhouette V1.0" } + , { 0x0029, 0x001a, 0x0029, 0x001a, + EVR_SL, "LengthOfTotalHeaderInBytes", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_IMPS_01" } + , { 0x0029, 0x001b, 0x0029, 0x001b, + EVR_SQ, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P-Private_ICS Release 1" } + , { 0x0029, 0x001b, 0x0029, 0x001b, + EVR_UL, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Silhouette V1.0" } + , { 0x0029, 0x001c, 0x0029, 0x001c, + EVR_SQ, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P-Private_ICS Release 1" } + , { 0x0029, 0x001c, 0x0029, 0x001c, + EVR_UL, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Silhouette V1.0" } + , { 0x0029, 0x001d, 0x0029, 0x001d, + EVR_UN, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Silhouette V1.0" } + , { 0x0029, 0x001e, 0x0029, 0x001e, + EVR_CS, "ImageEnhancementEnableStatus", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1;3" } + , { 0x0029, 0x001e, 0x0029, 0x001e, + EVR_CS, "SubtractionMaskEnableStatus", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1;2" } + , { 0x0029, 0x001e, 0x0029, 0x001e, + EVR_UN, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Silhouette V1.0" } + , { 0x0029, 0x001f, 0x0029, 0x001f, + EVR_CS, "ImageEnhancementSelectStatus", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1;3" } + , { 0x0029, 0x001f, 0x0029, 0x001f, + EVR_CS, "SubtractionMaskSelectStatus", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1;2" } + , { 0x0029, 0x0020, 0x0029, 0x0020, + EVR_DS, "PixelAspectRatio", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1" } + , { 0x0029, 0x0020, 0x0029, 0x0020, + EVR_DS, "EdgeEnhancementCoefficient", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "CAMTRONICS" } + , { 0x0029, 0x0020, 0x0029, 0x0020, + EVR_UN, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "CAMTRONICS IP" } + , { 0x0029, 0x0020, 0x0029, 0x0020, + EVR_LT, "LineMeasurementColor", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Silhouette Line V1.0" } + , { 0x0029, 0x0020, 0x0029, 0x0020, + EVR_FL, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P-Private_ICS Release 1;1" } + , { 0x0029, 0x0020, 0x0029, 0x0020, + EVR_CS, "ImageScanningDirection", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "FDMS 1.0" } + , { 0x0029, 0x0020, 0x0029, 0x0020, + EVR_LO, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/PART" } + , { 0x0029, 0x0020, 0x0029, 0x0020, + EVR_US, "ListOfElementNumbers", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MED HG" } + , { 0x0029, 0x0020, 0x0029, 0x0020, + EVR_LT, "PixelQualityCode", 3, 3, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CM VA0 CMS" } + , { 0x0029, 0x0020, 0x0029, 0x0020, + EVR_OB, "CSASeriesHeaderInfo", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CSA HEADER" } + , { 0x0029, 0x0020, 0x0029, 0x0020, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MED DISPLAY" } + , { 0x0029, 0x0020, 0x0029, 0x0020, + EVR_UL, "ROILineStyle", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Silhouette ROI V1.0" } + , { 0x0029, 0x0020, 0x0029, 0x0020, + EVR_UL, "AnnotationTextCursorMode", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Silhouette Annot V1.0" } + , { 0x0029, 0x0020, 0x0029, 0x0020, + EVR_LO, "PixelDataMD5SumPerFrame", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "INTELERAD MEDICAL SYSTEMS" } + , { 0x0029, 0x0020, 0x0029, 0x0020, + EVR_OB, "MedComHistoryInformation", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MEDCOM HEADER" } + , { 0x0029, 0x0020, 0x0029, 0x0020, + EVR_DS, "FPMax", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/LAST" } + , { 0x0029, 0x0020, 0x0029, 0x0020, + EVR_US, "ListOfElementNumbers", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MED MG" } + , { 0x0029, 0x0021, 0x0029, 0x0021, + EVR_LT, "LineMeasurementFont", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Silhouette Line V1.0" } + , { 0x0029, 0x0021, 0x0029, 0x0021, + EVR_SQ, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P-Private_ICS Release 1" } + , { 0x0029, 0x0021, 0x0029, 0x0021, + EVR_FL, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P-Private_ICS Release 1;1" } + , { 0x0029, 0x0021, 0x0029, 0x0021, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Silhouette V1.0" } + , { 0x0029, 0x0021, 0x0029, 0x0021, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MED DISPLAY" } + , { 0x0029, 0x0021, 0x0029, 0x0021, + EVR_UL, "ROILineDashLength", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Silhouette ROI V1.0" } + , { 0x0029, 0x0021, 0x0029, 0x0021, + EVR_UL, "AnnotationTextShadowOffsetX", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Silhouette Annot V1.0" } + , { 0x0029, 0x0021, 0x0029, 0x0021, + EVR_US, "HistogramPercentileLabels", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "INTELERAD MEDICAL SYSTEMS" } + , { 0x0029, 0x0022, 0x0029, 0x0022, + EVR_UL, "LineMeasurementDashLength", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Silhouette Line V1.0" } + , { 0x0029, 0x0022, 0x0029, 0x0022, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Silhouette V1.0" } + , { 0x0029, 0x0022, 0x0029, 0x0022, + EVR_IS, "PixelQualityValue", 3, 3, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CM VA0 CMS" } + , { 0x0029, 0x0022, 0x0029, 0x0022, + EVR_UL, "ROIInteractivity", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Silhouette ROI V1.0" } + , { 0x0029, 0x0022, 0x0029, 0x0022, + EVR_UL, "AnnotationTextShadowOffsetY", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Silhouette Annot V1.0" } + , { 0x0029, 0x0022, 0x0029, 0x0022, + EVR_FD, "HistogramPercentileValues", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "INTELERAD MEDICAL SYSTEMS" } + , { 0x0029, 0x0023, 0x0029, 0x0023, + EVR_UL, "LinePointSpace", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Silhouette Line V1.0" } + , { 0x0029, 0x0023, 0x0029, 0x0023, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Silhouette V1.0" } + , { 0x0029, 0x0023, 0x0029, 0x0023, + EVR_UL, "ROINamePosition", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Silhouette ROI V1.0" } + , { 0x0029, 0x0023, 0x0029, 0x0023, + EVR_LT, "AnnotationLineColor", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Silhouette Annot V1.0" } + , { 0x0029, 0x0024, 0x0029, 0x0024, + EVR_FD, "LinePoints", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Silhouette Line V1.0" } + , { 0x0029, 0x0024, 0x0029, 0x0024, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Silhouette V1.0" } + , { 0x0029, 0x0024, 0x0029, 0x0024, + EVR_UL, "ROINameDisplay", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Silhouette ROI V1.0" } + , { 0x0029, 0x0024, 0x0029, 0x0024, + EVR_UL, "AnnotationLineThickness", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Silhouette Annot V1.0" } + , { 0x0029, 0x0025, 0x0029, 0x0025, + EVR_UL, "LineControlPointSize", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Silhouette Line V1.0" } + , { 0x0029, 0x0025, 0x0029, 0x0025, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Silhouette V1.0" } + , { 0x0029, 0x0025, 0x0029, 0x0025, + EVR_LT, "ROILabel", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Silhouette ROI V1.0" } + , { 0x0029, 0x0025, 0x0029, 0x0025, + EVR_UL, "AnnotationLineType", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Silhouette Annot V1.0" } + , { 0x0029, 0x0025, 0x0029, 0x0025, + EVR_LO, "ProcessedPixelDataQuality", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1" } + , { 0x0029, 0x0026, 0x0029, 0x0026, + EVR_UL, "LineControlPointSpace", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Silhouette Line V1.0" } + , { 0x0029, 0x0026, 0x0029, 0x0026, + EVR_UL, "ROIShape", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Silhouette ROI V1.0" } + , { 0x0029, 0x0026, 0x0029, 0x0026, + EVR_UL, "AnnotationLineStyle", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Silhouette Annot V1.0" } + , { 0x0029, 0x0026, 0x0029, 0x0026, + EVR_SS, "VersionOfHeaderStructure", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_IMPS_01" } + , { 0x0029, 0x0027, 0x0029, 0x0027, + EVR_FD, "LineControlPoints", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Silhouette Line V1.0" } + , { 0x0029, 0x0027, 0x0029, 0x0027, + EVR_UN, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Silhouette V1.0" } + , { 0x0029, 0x0027, 0x0029, 0x0027, + EVR_FD, "ROIShapeTilt", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Silhouette ROI V1.0" } + , { 0x0029, 0x0027, 0x0029, 0x0027, + EVR_UL, "AnnotationLineDashLength", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Silhouette Annot V1.0" } + , { 0x0029, 0x0028, 0x0029, 0x0028, + EVR_LT, "LineLabel", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Silhouette Line V1.0" } + , { 0x0029, 0x0028, 0x0029, 0x0028, + EVR_UN, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Silhouette V1.0" } + , { 0x0029, 0x0028, 0x0029, 0x0028, + EVR_UL, "ROIShapePointsCount", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Silhouette ROI V1.0" } + , { 0x0029, 0x0028, 0x0029, 0x0028, + EVR_UL, "AnnotationLineAttachMode", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Silhouette Annot V1.0" } + , { 0x0029, 0x0029, 0x0029, 0x0029, + EVR_UL, "LineDontSave", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Silhouette Line V1.0" } + , { 0x0029, 0x0029, 0x0029, 0x0029, + EVR_UN, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Silhouette V1.0" } + , { 0x0029, 0x0029, 0x0029, 0x0029, + EVR_UL, "ROIShapePointsSpace", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Silhouette ROI V1.0" } + , { 0x0029, 0x0029, 0x0029, 0x0029, + EVR_UL, "AnnotationLinePointCount", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Silhouette Annot V1.0" } + , { 0x0029, 0x0030, 0x0029, 0x0030, + EVR_LT, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1" } + , { 0x0029, 0x0030, 0x0029, 0x0030, + EVR_UN, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "CAMTRONICS IP" } + , { 0x0029, 0x0030, 0x0029, 0x0030, + EVR_CS, "ExtendedReadingSizeValue", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "FDMS 1.0" } + , { 0x0029, 0x0030, 0x0029, 0x0030, + EVR_UN, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Silhouette V1.0" } + , { 0x0029, 0x0030, 0x0029, 0x0030, + EVR_US, "ListOfTotalDisplayLength", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MED HG" } + , { 0x0029, 0x0030, 0x0029, 0x0030, + EVR_FD, "ROIShapePoints", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Silhouette ROI V1.0" } + , { 0x0029, 0x0030, 0x0029, 0x0030, + EVR_UL, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P-GV-CT Release 1" } + , { 0x0029, 0x0030, 0x0029, 0x0030, + EVR_FD, "AnnotationLinePoints", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Silhouette Annot V1.0" } + , { 0x0029, 0x0030, 0x0029, 0x0030, + EVR_DS, "ScaledMinimum", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/LAST" } + , { 0x0029, 0x0030, 0x0029, 0x0030, + EVR_US, "ListOfTotalDisplayLength", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MED MG" } + , { 0x0029, 0x0031, 0x0029, 0x0031, + EVR_DS, "Unknown", 2, 2, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/PART" } + , { 0x0029, 0x0031, 0x0029, 0x0031, + EVR_UL, "ROIShapeControlPointsCount", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Silhouette ROI V1.0" } + , { 0x0029, 0x0031, 0x0029, 0x0031, + EVR_UL, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P-GV-CT Release 1" } + , { 0x0029, 0x0031, 0x0029, 0x0031, + EVR_US, "Unknown", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "DIGISCAN IMAGE" } + , { 0x0029, 0x0031, 0x0029, 0x0031, + EVR_UL, "AnnotationLineControlSize", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Silhouette Annot V1.0" } + , { 0x0029, 0x0031, 0x0029, 0x0031, + EVR_LO, "PMTFInformation1", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MEDCOM HEADER" } + , { 0x0029, 0x0032, 0x0029, 0x0032, + EVR_DS, "Unknown", 2, 2, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/PART" } + , { 0x0029, 0x0032, 0x0029, 0x0032, + EVR_UL, "ROIShapeControlPointsSpace", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Silhouette ROI V1.0" } + , { 0x0029, 0x0032, 0x0029, 0x0032, + EVR_UL, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P-GV-CT Release 1" } + , { 0x0029, 0x0032, 0x0029, 0x0032, + EVR_US, "Unknown", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "DIGISCAN IMAGE" } + , { 0x0029, 0x0032, 0x0029, 0x0032, + EVR_LT, "AnnotationMarkerColor", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Silhouette Annot V1.0" } + , { 0x0029, 0x0032, 0x0029, 0x0032, + EVR_UL, "PMTFInformation2", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MEDCOM HEADER" } + , { 0x0029, 0x0033, 0x0029, 0x0033, + EVR_FD, "ROIShapeControlPoints", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Silhouette ROI V1.0" } + , { 0x0029, 0x0033, 0x0029, 0x0033, + EVR_UL, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P-GV-CT Release 1" } + , { 0x0029, 0x0033, 0x0029, 0x0033, + EVR_LT, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "DIGISCAN IMAGE" } + , { 0x0029, 0x0033, 0x0029, 0x0033, + EVR_UL, "AnnotationMarkerType", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Silhouette Annot V1.0" } + , { 0x0029, 0x0033, 0x0029, 0x0033, + EVR_UL, "PMTFInformation3", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MEDCOM HEADER" } + , { 0x0029, 0x0034, 0x0029, 0x0034, + EVR_US, "MagnificationReductionRatio", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "FDMS 1.0" } + , { 0x0029, 0x0034, 0x0029, 0x0034, + EVR_UL, "ROIDontSave", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Silhouette ROI V1.0" } + , { 0x0029, 0x0034, 0x0029, 0x0034, + EVR_LT, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "DIGISCAN IMAGE" } + , { 0x0029, 0x0034, 0x0029, 0x0034, + EVR_UL, "AnnotationMarkerSize", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Silhouette Annot V1.0" } + , { 0x0029, 0x0034, 0x0029, 0x0034, + EVR_SL, "AdvantageCompOverflow", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_IMPS_01" } + , { 0x0029, 0x0034, 0x0029, 0x0034, + EVR_CS, "PMTFInformation4", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MEDCOM HEADER" } + , { 0x0029, 0x0035, 0x0029, 0x0035, + EVR_FD, "AnnotationMarkerLocation", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Silhouette Annot V1.0" } + , { 0x0029, 0x0035, 0x0029, 0x0035, + EVR_SL, "AdvantageCompUnderflow", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_IMPS_01" } + , { 0x0029, 0x0035, 0x0029, 0x0035, + EVR_UL, "PMTFInformation5", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MEDCOM HEADER" } + , { 0x0029, 0x0036, 0x0029, 0x0036, + EVR_UL, "AnnotationMarkerAttachMode", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Silhouette Annot V1.0" } + , { 0x0029, 0x0037, 0x0029, 0x0037, + EVR_LT, "AnnotationGeomColor", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Silhouette Annot V1.0" } + , { 0x0029, 0x0038, 0x0029, 0x0038, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1" } + , { 0x0029, 0x0038, 0x0029, 0x0038, + EVR_UL, "AnnotationGeomThickness", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Silhouette Annot V1.0" } + , { 0x0029, 0x0039, 0x0029, 0x0039, + EVR_UL, "AnnotationGeomLineStyle", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Silhouette Annot V1.0" } + , { 0x0029, 0x0040, 0x0029, 0x0040, + EVR_UN, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "CAMTRONICS IP" } + , { 0x0029, 0x0040, 0x0029, 0x0040, + EVR_LT, "ListOfDisplayPrefix", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MED HG" } + , { 0x0029, 0x0040, 0x0029, 0x0040, + EVR_LT, "MagnifyingGlassID", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1;1" } + , { 0x0029, 0x0040, 0x0029, 0x0040, + EVR_UL, "AnnotationGeomDashLength", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Silhouette Annot V1.0" } + , { 0x0029, 0x0040, 0x0029, 0x0040, + EVR_SQ, "ApplicationHeaderSequence", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MEDCOM HEADER" } + , { 0x0029, 0x0040, 0x0029, 0x0040, + EVR_DS, "ScaledMaximum", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/LAST" } + , { 0x0029, 0x0040, 0x0029, 0x0040, + EVR_LT, "ListOfDisplayPrefix", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MED MG" } + , { 0x0029, 0x0041, 0x0029, 0x0041, + EVR_SQ, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Silhouette Sequence Ids V1.0" } + , { 0x0029, 0x0041, 0x0029, 0x0041, + EVR_DS, "MagnifyingGlassRectangle", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1;1" } + , { 0x0029, 0x0041, 0x0029, 0x0041, + EVR_UL, "AnnotationGeomFillPattern", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Silhouette Annot V1.0" } + , { 0x0029, 0x0041, 0x0029, 0x0041, + EVR_CS, "ApplicationHeaderType", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MEDCOM HEADER" } + , { 0x0029, 0x0042, 0x0029, 0x0042, + EVR_SQ, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Silhouette Sequence Ids V1.0" } + , { 0x0029, 0x0042, 0x0029, 0x0042, + EVR_UL, "AnnotationInteractivity", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Silhouette Annot V1.0" } + , { 0x0029, 0x0042, 0x0029, 0x0042, + EVR_LO, "ApplicationHeaderID", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MEDCOM HEADER" } + , { 0x0029, 0x0043, 0x0029, 0x0043, + EVR_SQ, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P-Private_ICS Release 1" } + , { 0x0029, 0x0043, 0x0029, 0x0043, + EVR_SQ, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Silhouette Sequence Ids V1.0" } + , { 0x0029, 0x0043, 0x0029, 0x0043, + EVR_DS, "MagnifyingGlassFactor", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1;1" } + , { 0x0029, 0x0043, 0x0029, 0x0043, + EVR_FD, "AnnotationArrowLength", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Silhouette Annot V1.0" } + , { 0x0029, 0x0043, 0x0029, 0x0043, + EVR_LO, "ApplicationHeaderVersion", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MEDCOM HEADER" } + , { 0x0029, 0x0044, 0x0029, 0x0044, + EVR_SQ, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P-Private_ICS Release 1" } + , { 0x0029, 0x0044, 0x0029, 0x0044, + EVR_CS, "LineDensityCode", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "FDMS 1.0" } + , { 0x0029, 0x0044, 0x0029, 0x0044, + EVR_US, "MagnifyingGlassFunction", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1;1" } + , { 0x0029, 0x0044, 0x0029, 0x0044, + EVR_FD, "AnnotationArrowAngle", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Silhouette Annot V1.0" } + , { 0x0029, 0x0044, 0x0029, 0x0044, + EVR_OB, "ApplicationHeaderInfo", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MEDCOM HEADER" } + , { 0x0029, 0x0045, 0x0029, 0x0045, + EVR_UL, "AnnotationDontSave", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Silhouette Annot V1.0" } + , { 0x0029, 0x004c, 0x0029, 0x004c, + EVR_SQ, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P-Private_ICS Release 1" } + , { 0x0029, 0x004e, 0x0029, 0x004e, + EVR_CS, "MagnifyingGlassEnableStatus", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1;1" } + , { 0x0029, 0x004f, 0x0029, 0x004f, + EVR_CS, "MagnifyingGlassSelectStatus", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1;1" } + , { 0x0029, 0x0050, 0x0029, 0x0050, + EVR_LT, "SceneText", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "CAMTRONICS" } + , { 0x0029, 0x0050, 0x0029, 0x0050, + EVR_CS, "DataCompressionCode", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "FDMS 1.0" } + , { 0x0029, 0x0050, 0x0029, 0x0050, + EVR_LT, "ArchiveCode", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CM VA0 CMS" } + , { 0x0029, 0x0050, 0x0029, 0x0050, + EVR_LT, "ListOfDisplayPostfix", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MED HG" } + , { 0x0029, 0x0050, 0x0029, 0x0050, + EVR_US, "OriginOfSubmatrix", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MED DISPLAY" } + , { 0x0029, 0x0050, 0x0029, 0x0050, + EVR_CS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P-Private_ICS Release 1;5" } + , { 0x0029, 0x0050, 0x0029, 0x0050, + EVR_LO, "WorkflowControlFlags", 8, 8, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MEDCOM HEADER" } + , { 0x0029, 0x0050, 0x0029, 0x0050, + EVR_DS, "WindowMinimum", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/LAST" } + , { 0x0029, 0x0050, 0x0029, 0x0050, + EVR_LT, "ListOfDisplayPostfix", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MED MG" } + , { 0x0029, 0x0051, 0x0029, 0x0051, + EVR_LT, "ExposureCode", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CM VA0 CMS" } + , { 0x0029, 0x0051, 0x0029, 0x0051, + EVR_CS, "ArchiveManagementFlagKeepOnline", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MEDCOM HEADER" } + , { 0x0029, 0x0052, 0x0029, 0x0052, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Silhouette V1.0" } + , { 0x0029, 0x0052, 0x0029, 0x0052, + EVR_LT, "SortCode", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CM VA0 CMS" } + , { 0x0029, 0x0052, 0x0029, 0x0052, + EVR_CS, "ArchiveManagementFlagDoNotArchive", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MEDCOM HEADER" } + , { 0x0029, 0x0053, 0x0029, 0x0053, + EVR_LT, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Silhouette V1.0" } + , { 0x0029, 0x0053, 0x0029, 0x0053, + EVR_LT, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CM VA0 CMS" } + , { 0x0029, 0x0053, 0x0029, 0x0053, + EVR_CS, "ImageLocationStatus", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MEDCOM HEADER" } + , { 0x0029, 0x0054, 0x0029, 0x0054, + EVR_UN, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Silhouette V1.0" } + , { 0x0029, 0x0054, 0x0029, 0x0054, + EVR_DS, "EstimatedRetrieveTime", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MEDCOM HEADER" } + , { 0x0029, 0x0055, 0x0029, 0x0055, + EVR_LT, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Silhouette V1.0" } + , { 0x0029, 0x0055, 0x0029, 0x0055, + EVR_CS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P-Private_ICS Release 1;5" } + , { 0x0029, 0x0055, 0x0029, 0x0055, + EVR_DS, "DataSizeOfRetrievedImages", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MEDCOM HEADER" } + , { 0x0029, 0x0056, 0x0029, 0x0056, + EVR_LT, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Silhouette V1.0" } + , { 0x0029, 0x0057, 0x0029, 0x0057, + EVR_UN, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Silhouette V1.0" } + , { 0x0029, 0x0060, 0x0029, 0x0060, + EVR_LT, "ImageText", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "CAMTRONICS" } + , { 0x0029, 0x0060, 0x0029, 0x0060, + EVR_LT, "CompressionAlgorithm", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI Release 1" } + , { 0x0029, 0x0060, 0x0029, 0x0060, + EVR_LT, "Splash", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CM VA0 CMS" } + , { 0x0029, 0x0060, 0x0029, 0x0060, + EVR_US, "ListOfTextPosition", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MED HG" } + , { 0x0029, 0x0060, 0x0029, 0x0060, + EVR_LT, "CompressionAlgorithm", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI" } + , { 0x0029, 0x0060, 0x0029, 0x0060, + EVR_LO, "SeriesWorkflowStatus", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MEDCOM HEADER2" } + , { 0x0029, 0x0060, 0x0029, 0x0060, + EVR_DS, "WindowMaximum", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/LAST" } + , { 0x0029, 0x0060, 0x0029, 0x0060, + EVR_LT, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1" } + , { 0x0029, 0x0060, 0x0029, 0x0060, + EVR_LT, "CompressionAlgorithm", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI RELEASE 1" } + , { 0x0029, 0x0060, 0x0029, 0x0060, + EVR_US, "ListOfTextPosition", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MED MG" } + , { 0x0029, 0x0061, 0x0029, 0x0061, + EVR_IS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/LAST" } + , { 0x0029, 0x0061, 0x0029, 0x0061, + EVR_LT, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1" } + , { 0x0029, 0x0067, 0x0029, 0x0067, + EVR_LO, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P-Private_ICS Release 1" } + , { 0x0029, 0x0067, 0x0029, 0x0067, + EVR_LT, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1" } + , { 0x0029, 0x0068, 0x0029, 0x0068, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P-Private_ICS Release 1" } + , { 0x0029, 0x006a, 0x0029, 0x006a, + EVR_LO, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P-Private_ICS Release 1" } + , { 0x0029, 0x006b, 0x0029, 0x006b, + EVR_US, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P-Private_ICS Release 1" } + , { 0x0029, 0x0070, 0x0029, 0x0070, + EVR_IS, "PixelShiftHorizontal", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "CAMTRONICS" } + , { 0x0029, 0x0070, 0x0029, 0x0070, + EVR_IS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "ISG shadow" } + , { 0x0029, 0x0070, 0x0029, 0x0070, + EVR_LT, "ListOfTextConcatenation", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MED HG" } + , { 0x0029, 0x0070, 0x0029, 0x0070, + EVR_SQ, "SiemensLinkSequence", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MEDCOM HEADER" } + , { 0x0029, 0x0070, 0x0029, 0x0070, + EVR_DS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/LAST" } + , { 0x0029, 0x0070, 0x0029, 0x0070, + EVR_LT, "ListOfTextConcatenation", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MED MG" } + , { 0x0029, 0x0070, 0x0029, 0x0070, + EVR_LT, "WindowID", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1" } + , { 0x0029, 0x0071, 0x0029, 0x0071, + EVR_AT, "ReferencedTag", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MEDCOM HEADER" } + , { 0x0029, 0x0071, 0x0029, 0x0071, + EVR_DS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/LAST" } + , { 0x0029, 0x0071, 0x0029, 0x0071, + EVR_CS, "VideoInvertSubtracted", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1" } + , { 0x0029, 0x0072, 0x0029, 0x0072, + EVR_IS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/LAST" } + , { 0x0029, 0x0072, 0x0029, 0x0072, + EVR_CS, "ReferencedTagType", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MEDCOM HEADER" } + , { 0x0029, 0x0072, 0x0029, 0x0072, + EVR_CS, "VideoInvertNonsubtracted", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1" } + , { 0x0029, 0x0073, 0x0029, 0x0073, + EVR_UL, "ReferencedValueLength", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MEDCOM HEADER" } + , { 0x0029, 0x0074, 0x0029, 0x0074, + EVR_CS, "ReferencedObjectDeviceType", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MEDCOM HEADER" } + , { 0x0029, 0x0075, 0x0029, 0x0075, + EVR_OB, "ReferencedObjectDeviceLocation", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MEDCOM HEADER" } + , { 0x0029, 0x0076, 0x0029, 0x0076, + EVR_OB, "ReferencedObjectDeviceID", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MEDCOM HEADER" } + , { 0x0029, 0x0077, 0x0029, 0x0077, + EVR_CS, "WindowSelectStatus", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1" } + , { 0x0029, 0x0078, 0x0029, 0x0078, + EVR_LT, "ECGDisplayPrintingID", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1" } + , { 0x0029, 0x0079, 0x0029, 0x0079, + EVR_CS, "ECGDisplayPrinting", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1" } + , { 0x0029, 0x007e, 0x0029, 0x007e, + EVR_CS, "ECGDisplayPrintingEnableStatus", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1" } + , { 0x0029, 0x007f, 0x0029, 0x007f, + EVR_CS, "ECGDisplayPrintingSelectStatus", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1" } + , { 0x0029, 0x0080, 0x0029, 0x0080, + EVR_IS, "PixelShiftVertical", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "CAMTRONICS" } + , { 0x0029, 0x0080, 0x0029, 0x0080, + EVR_IS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "ISG shadow" } + , { 0x0029, 0x0080, 0x0029, 0x0080, + EVR_LO, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P-GV-CT Release 1" } + , { 0x0029, 0x0080, 0x0029, 0x0080, + EVR_IS, "ViewCenter", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/LAST" } + , { 0x0029, 0x0080, 0x0029, 0x0080, + EVR_LT, "PhysiologicalDisplayID", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1" } + , { 0x0029, 0x0081, 0x0029, 0x0081, + EVR_IS, "ViewSize", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/LAST" } + , { 0x0029, 0x0081, 0x0029, 0x0081, + EVR_US, "PreferredPhysiologicalChannelDisplay", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1" } + , { 0x0029, 0x0082, 0x0029, 0x0082, + EVR_IS, "ViewZoom", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/LAST" } + , { 0x0029, 0x0083, 0x0029, 0x0083, + EVR_IS, "ViewTransform", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/LAST" } + , { 0x0029, 0x008e, 0x0029, 0x008e, + EVR_CS, "PhysiologicalDisplayEnableStatus", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1" } + , { 0x0029, 0x008f, 0x0029, 0x008f, + EVR_CS, "PhysiologicalDisplaySelectStatus", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1" } + , { 0x0029, 0x0090, 0x0029, 0x0090, + EVR_IS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "CAMTRONICS" } + , { 0x0029, 0x0090, 0x0029, 0x0090, + EVR_IS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "ISG shadow" } + , { 0x0029, 0x0090, 0x0029, 0x0090, + EVR_LO, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P-GV-CT Release 1" } + , { 0x0029, 0x0099, 0x0029, 0x0099, + EVR_LT, "ShutterType", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MED DISPLAY" } + , { 0x0029, 0x009a, 0x0029, 0x009a, + EVR_SQ, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P-Private_ICS Release 1;4" } + , { 0x0029, 0x00a0, 0x0029, 0x00a0, + EVR_US, "RowsOfRectangularShutter", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MED DISPLAY" } + , { 0x0029, 0x00a1, 0x0029, 0x00a1, + EVR_US, "ColumnsOfRectangularShutter", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MED DISPLAY" } + , { 0x0029, 0x00a2, 0x0029, 0x00a2, + EVR_US, "OriginOfRectangularShutter", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MED DISPLAY" } + , { 0x0029, 0x00b0, 0x0029, 0x00b0, + EVR_US, "RadiusOfCircularShutter", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MED DISPLAY" } + , { 0x0029, 0x00b2, 0x0029, 0x00b2, + EVR_US, "OriginOfCircularShutter", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MED DISPLAY" } + , { 0x0029, 0x00c0, 0x0029, 0x00c0, + EVR_LT, "FunctionalShutterID", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1" } + , { 0x0029, 0x00c0, 0x0029, 0x00c0, + EVR_SQ, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P-Private_ICS Release 1;3" } + , { 0x0029, 0x00c1, 0x0029, 0x00c1, + EVR_US, "ContourOfIrregularShutter", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MED DISPLAY" } + , { 0x0029, 0x00c1, 0x0029, 0x00c1, + EVR_US, "FieldOfShutter", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1" } + , { 0x0029, 0x00c1, 0x0029, 0x00c1, + EVR_SQ, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P-Private_ICS Release 1;3" } + , { 0x0029, 0x00c2, 0x0029, 0x00c2, + EVR_SQ, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P-Private_ICS Release 1;3" } + , { 0x0029, 0x00c3, 0x0029, 0x00c3, + EVR_IS, "ScanResolution", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/PART" } + , { 0x0029, 0x00c3, 0x0029, 0x00c3, + EVR_SQ, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P-Private_ICS Release 1;3" } + , { 0x0029, 0x00c4, 0x0029, 0x00c4, + EVR_IS, "FieldOfView", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/PART" } + , { 0x0029, 0x00c4, 0x0029, 0x00c4, + EVR_SQ, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P-Private_ICS Release 1;3" } + , { 0x0029, 0x00c5, 0x0029, 0x00c5, + EVR_LT, "FieldOfShutterRectangle", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1" } + , { 0x0029, 0x00c5, 0x0029, 0x00c5, + EVR_SQ, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P-Private_ICS Release 1;3" } + , { 0x0029, 0x00cd, 0x0029, 0x00cd, + EVR_SQ, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P-Private_ICS Release 1;1" } + , { 0x0029, 0x00ce, 0x0029, 0x00ce, + EVR_CS, "ShutterEnableStatus", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1" } + , { 0x0029, 0x00cf, 0x0029, 0x00cf, + EVR_CS, "ShutterSelectStatus", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1" } + , { 0x0029, 0x00d0, 0x0029, 0x00d0, + EVR_IS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P-GV-CT Release 1" } + , { 0x0029, 0x00d1, 0x0029, 0x00d1, + EVR_IS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P-GV-CT Release 1" } + , { 0x0029, 0x00d5, 0x0029, 0x00d5, + EVR_LT, "SliceThickness", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/PART" } + , { 0x0029, 0x00e0, 0x0029, 0x00e0, + EVR_SQ, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P-Private_ICS Release 1;4" } + , { 0x0029, 0x1010, 0x0029, 0x1010, + EVR_OB, "OriginalMeasuringData", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "OCULUS Optikgeraete GmbH" } + , { 0x0029, 0x1012, 0x0029, 0x1012, + EVR_UL, "OriginalMeasuringDataLength", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "OCULUS Optikgeraete GmbH" } + , { 0x0029, 0x1020, 0x0029, 0x1020, + EVR_OB, "OriginalMeasuringRawData", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "OCULUS Optikgeraete GmbH" } + , { 0x0029, 0x1022, 0x0029, 0x1022, + EVR_UL, "OriginalMeasuringRawDataLength", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "OCULUS Optikgeraete GmbH" } + , { 0x0031, 0x0000, 0x0031, 0x0000, + EVR_CS, "StudyStatus", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "AGFA PACS Archive Mirroring 1.0" } + , { 0x0031, 0x0001, 0x0031, 0x0001, + EVR_UL, "DateTimeVerified", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "AGFA PACS Archive Mirroring 1.0" } + , { 0x0031, 0x0010, 0x0031, 0x0010, + EVR_LT, "RequestUID", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RIS" } + , { 0x0031, 0x0012, 0x0031, 0x0012, + EVR_LT, "ExaminationReason", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS ISI" } + , { 0x0031, 0x0030, 0x0031, 0x0030, + EVR_DA, "RequestedDate", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS ISI" } + , { 0x0031, 0x0032, 0x0031, 0x0032, + EVR_TM, "WorklistRequestStartTime", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS ISI" } + , { 0x0031, 0x0033, 0x0031, 0x0033, + EVR_TM, "WorklistRequestEndTime", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS ISI" } + , { 0x0031, 0x0045, 0x0031, 0x0045, + EVR_LT, "RequestingPhysician", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RIS" } + , { 0x0031, 0x004a, 0x0031, 0x004a, + EVR_TM, "RequestedTime", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS ISI" } + , { 0x0031, 0x0050, 0x0031, 0x0050, + EVR_LT, "RequestedPhysician", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RIS" } + , { 0x0031, 0x0080, 0x0031, 0x0080, + EVR_LT, "RequestedLocation", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS ISI" } +#endif + , { 0x0032, 0x000a, 0x0032, 0x000a, + EVR_CS, "RETIRED_StudyStatusID", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0032, 0x000c, 0x0032, 0x000c, + EVR_CS, "RETIRED_StudyPriorityID", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0032, 0x0012, 0x0032, 0x0012, + EVR_LO, "RETIRED_StudyIDIssuer", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0032, 0x0032, 0x0032, 0x0032, + EVR_DA, "RETIRED_StudyVerifiedDate", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0032, 0x0033, 0x0032, 0x0033, + EVR_TM, "RETIRED_StudyVerifiedTime", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0032, 0x0034, 0x0032, 0x0034, + EVR_DA, "RETIRED_StudyReadDate", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0032, 0x0035, 0x0032, 0x0035, + EVR_TM, "RETIRED_StudyReadTime", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0032, 0x1000, 0x0032, 0x1000, + EVR_DA, "RETIRED_ScheduledStudyStartDate", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0032, 0x1001, 0x0032, 0x1001, + EVR_TM, "RETIRED_ScheduledStudyStartTime", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0032, 0x1010, 0x0032, 0x1010, + EVR_DA, "RETIRED_ScheduledStudyStopDate", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0032, 0x1011, 0x0032, 0x1011, + EVR_TM, "RETIRED_ScheduledStudyStopTime", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0032, 0x1020, 0x0032, 0x1020, + EVR_LO, "RETIRED_ScheduledStudyLocation", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0032, 0x1021, 0x0032, 0x1021, + EVR_AE, "RETIRED_ScheduledStudyLocationAETitle", 1, -1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0032, 0x1030, 0x0032, 0x1030, + EVR_LO, "RETIRED_ReasonForStudy", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0032, 0x1031, 0x0032, 0x1031, + EVR_SQ, "RequestingPhysicianIdentificationSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0032, 0x1032, 0x0032, 0x1032, + EVR_PN, "RequestingPhysician", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0032, 0x1033, 0x0032, 0x1033, + EVR_LO, "RequestingService", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0032, 0x1034, 0x0032, 0x1034, + EVR_SQ, "RequestingServiceCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0032, 0x1040, 0x0032, 0x1040, + EVR_DA, "RETIRED_StudyArrivalDate", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0032, 0x1041, 0x0032, 0x1041, + EVR_TM, "RETIRED_StudyArrivalTime", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0032, 0x1050, 0x0032, 0x1050, + EVR_DA, "RETIRED_StudyCompletionDate", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0032, 0x1051, 0x0032, 0x1051, + EVR_TM, "RETIRED_StudyCompletionTime", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0032, 0x1055, 0x0032, 0x1055, + EVR_CS, "RETIRED_StudyComponentStatusID", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0032, 0x1060, 0x0032, 0x1060, + EVR_LO, "RequestedProcedureDescription", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0032, 0x1064, 0x0032, 0x1064, + EVR_SQ, "RequestedProcedureCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0032, 0x1070, 0x0032, 0x1070, + EVR_LO, "RequestedContrastAgent", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0032, 0x4000, 0x0032, 0x4000, + EVR_LT, "RETIRED_StudyComments", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } +#ifdef ENABLE_PRIVATE_TAGS + , { 0x0033, 0x0001, 0x0033, 0x0001, + EVR_UN, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_GNHD_01" } + , { 0x0033, 0x0002, 0x0033, 0x0002, + EVR_UN, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_CTHD_01" } + , { 0x0033, 0x0002, 0x0033, 0x0002, + EVR_UN, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_GNHD_01" } + , { 0x0033, 0x0005, 0x0033, 0x0005, + EVR_UN, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_YMHD_01" } + , { 0x0033, 0x0006, 0x0033, 0x0006, + EVR_UN, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_YMHD_01" } + , { 0x0033, 0x0010, 0x0033, 0x0010, + EVR_LT, "PatientStudyUID", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS RIS" } + , { 0x0037, 0x0010, 0x0037, 0x0010, + EVR_LO, "ReferringDepartment", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_DRS_1" } + , { 0x0037, 0x0020, 0x0037, 0x0020, + EVR_US, "ScreenNumber", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_DRS_1" } + , { 0x0037, 0x0040, 0x0037, 0x0040, + EVR_SH, "LeftOrientation", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_DRS_1" } + , { 0x0037, 0x0042, 0x0037, 0x0042, + EVR_SH, "RightOrientation", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_DRS_1" } + , { 0x0037, 0x0050, 0x0037, 0x0050, + EVR_CS, "Inversion", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_DRS_1" } + , { 0x0037, 0x0060, 0x0037, 0x0060, + EVR_US, "DSA", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_DRS_1" } +#endif + , { 0x0038, 0x0004, 0x0038, 0x0004, + EVR_SQ, "ReferencedPatientAliasSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0038, 0x0008, 0x0038, 0x0008, + EVR_CS, "VisitStatusID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0038, 0x0010, 0x0038, 0x0010, + EVR_LO, "AdmissionID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0038, 0x0011, 0x0038, 0x0011, + EVR_LO, "RETIRED_IssuerOfAdmissionID", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0038, 0x0014, 0x0038, 0x0014, + EVR_SQ, "IssuerOfAdmissionIDSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0038, 0x0016, 0x0038, 0x0016, + EVR_LO, "RouteOfAdmissions", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0038, 0x001a, 0x0038, 0x001a, + EVR_DA, "RETIRED_ScheduledAdmissionDate", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0038, 0x001b, 0x0038, 0x001b, + EVR_TM, "RETIRED_ScheduledAdmissionTime", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0038, 0x001c, 0x0038, 0x001c, + EVR_DA, "RETIRED_ScheduledDischargeDate", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0038, 0x001d, 0x0038, 0x001d, + EVR_TM, "RETIRED_ScheduledDischargeTime", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0038, 0x001e, 0x0038, 0x001e, + EVR_LO, "RETIRED_ScheduledPatientInstitutionResidence", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0038, 0x0020, 0x0038, 0x0020, + EVR_DA, "AdmittingDate", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0038, 0x0021, 0x0038, 0x0021, + EVR_TM, "AdmittingTime", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0038, 0x0030, 0x0038, 0x0030, + EVR_DA, "RETIRED_DischargeDate", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0038, 0x0032, 0x0038, 0x0032, + EVR_TM, "RETIRED_DischargeTime", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0038, 0x0040, 0x0038, 0x0040, + EVR_LO, "RETIRED_DischargeDiagnosisDescription", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0038, 0x0044, 0x0038, 0x0044, + EVR_SQ, "RETIRED_DischargeDiagnosisCodeSequence", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0038, 0x0050, 0x0038, 0x0050, + EVR_LO, "SpecialNeeds", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0038, 0x0060, 0x0038, 0x0060, + EVR_LO, "ServiceEpisodeID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0038, 0x0061, 0x0038, 0x0061, + EVR_LO, "RETIRED_IssuerOfServiceEpisodeID", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0038, 0x0062, 0x0038, 0x0062, + EVR_LO, "ServiceEpisodeDescription", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0038, 0x0064, 0x0038, 0x0064, + EVR_SQ, "IssuerOfServiceEpisodeIDSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0038, 0x0100, 0x0038, 0x0100, + EVR_SQ, "PertinentDocumentsSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0038, 0x0101, 0x0038, 0x0101, + EVR_SQ, "PertinentResourcesSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0038, 0x0102, 0x0038, 0x0102, + EVR_LO, "ResourceDescription", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0038, 0x0300, 0x0038, 0x0300, + EVR_LO, "CurrentPatientLocation", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0038, 0x0400, 0x0038, 0x0400, + EVR_LO, "PatientInstitutionResidence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0038, 0x0500, 0x0038, 0x0500, + EVR_LO, "PatientState", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0038, 0x0502, 0x0038, 0x0502, + EVR_SQ, "PatientClinicalTrialParticipationSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0038, 0x4000, 0x0038, 0x4000, + EVR_LT, "VisitComments", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } +#ifdef ENABLE_PRIVATE_TAGS + , { 0x0039, 0x0080, 0x0039, 0x0080, + EVR_IS, "PrivateEntityNumber", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ADWSoft_DPO" } + , { 0x0039, 0x0085, 0x0039, 0x0085, + EVR_DA, "PrivateEntityDate", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ADWSoft_DPO" } + , { 0x0039, 0x0090, 0x0039, 0x0090, + EVR_TM, "PrivateEntityTime", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ADWSoft_DPO" } + , { 0x0039, 0x0095, 0x0039, 0x0095, + EVR_LO, "PrivateEntityLaunchCommand", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ADWSoft_DPO" } + , { 0x0039, 0x00aa, 0x0039, 0x00aa, + EVR_CS, "PrivateEntityType", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ADWSoft_DPO" } +#endif + , { 0x003a, 0x0004, 0x003a, 0x0004, + EVR_CS, "WaveformOriginality", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x003a, 0x0005, 0x003a, 0x0005, + EVR_US, "NumberOfWaveformChannels", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x003a, 0x0010, 0x003a, 0x0010, + EVR_UL, "NumberOfWaveformSamples", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x003a, 0x001a, 0x003a, 0x001a, + EVR_DS, "SamplingFrequency", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x003a, 0x0020, 0x003a, 0x0020, + EVR_SH, "MultiplexGroupLabel", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x003a, 0x0200, 0x003a, 0x0200, + EVR_SQ, "ChannelDefinitionSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x003a, 0x0202, 0x003a, 0x0202, + EVR_IS, "WaveformChannelNumber", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x003a, 0x0203, 0x003a, 0x0203, + EVR_SH, "ChannelLabel", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x003a, 0x0205, 0x003a, 0x0205, + EVR_CS, "ChannelStatus", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x003a, 0x0208, 0x003a, 0x0208, + EVR_SQ, "ChannelSourceSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x003a, 0x0209, 0x003a, 0x0209, + EVR_SQ, "ChannelSourceModifiersSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x003a, 0x020a, 0x003a, 0x020a, + EVR_SQ, "SourceWaveformSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x003a, 0x020c, 0x003a, 0x020c, + EVR_LO, "ChannelDerivationDescription", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x003a, 0x0210, 0x003a, 0x0210, + EVR_DS, "ChannelSensitivity", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x003a, 0x0211, 0x003a, 0x0211, + EVR_SQ, "ChannelSensitivityUnitsSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x003a, 0x0212, 0x003a, 0x0212, + EVR_DS, "ChannelSensitivityCorrectionFactor", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x003a, 0x0213, 0x003a, 0x0213, + EVR_DS, "ChannelBaseline", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x003a, 0x0214, 0x003a, 0x0214, + EVR_DS, "ChannelTimeSkew", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x003a, 0x0215, 0x003a, 0x0215, + EVR_DS, "ChannelSampleSkew", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x003a, 0x0218, 0x003a, 0x0218, + EVR_DS, "ChannelOffset", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x003a, 0x021a, 0x003a, 0x021a, + EVR_US, "WaveformBitsStored", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x003a, 0x0220, 0x003a, 0x0220, + EVR_DS, "FilterLowFrequency", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x003a, 0x0221, 0x003a, 0x0221, + EVR_DS, "FilterHighFrequency", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x003a, 0x0222, 0x003a, 0x0222, + EVR_DS, "NotchFilterFrequency", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x003a, 0x0223, 0x003a, 0x0223, + EVR_DS, "NotchFilterBandwidth", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x003a, 0x0230, 0x003a, 0x0230, + EVR_FL, "WaveformDataDisplayScale", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x003a, 0x0231, 0x003a, 0x0231, + EVR_US, "WaveformDisplayBackgroundCIELabValue", 3, 3, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x003a, 0x0240, 0x003a, 0x0240, + EVR_SQ, "WaveformPresentationGroupSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x003a, 0x0241, 0x003a, 0x0241, + EVR_US, "PresentationGroupNumber", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x003a, 0x0242, 0x003a, 0x0242, + EVR_SQ, "ChannelDisplaySequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x003a, 0x0244, 0x003a, 0x0244, + EVR_US, "ChannelRecommendedDisplayCIELabValue", 3, 3, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x003a, 0x0245, 0x003a, 0x0245, + EVR_FL, "ChannelPosition", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x003a, 0x0246, 0x003a, 0x0246, + EVR_CS, "DisplayShadingFlag", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x003a, 0x0247, 0x003a, 0x0247, + EVR_FL, "FractionalChannelDisplayScale", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x003a, 0x0248, 0x003a, 0x0248, + EVR_FL, "AbsoluteChannelDisplayScale", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x003a, 0x0300, 0x003a, 0x0300, + EVR_SQ, "MultiplexedAudioChannelsDescriptionCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x003a, 0x0301, 0x003a, 0x0301, + EVR_IS, "ChannelIdentificationCode", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x003a, 0x0302, 0x003a, 0x0302, + EVR_CS, "ChannelMode", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x0001, 0x0040, 0x0001, + EVR_AE, "ScheduledStationAETitle", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x0002, 0x0040, 0x0002, + EVR_DA, "ScheduledProcedureStepStartDate", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x0003, 0x0040, 0x0003, + EVR_TM, "ScheduledProcedureStepStartTime", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x0004, 0x0040, 0x0004, + EVR_DA, "ScheduledProcedureStepEndDate", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x0005, 0x0040, 0x0005, + EVR_TM, "ScheduledProcedureStepEndTime", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x0006, 0x0040, 0x0006, + EVR_PN, "ScheduledPerformingPhysicianName", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x0007, 0x0040, 0x0007, + EVR_LO, "ScheduledProcedureStepDescription", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x0008, 0x0040, 0x0008, + EVR_SQ, "ScheduledProtocolCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x0009, 0x0040, 0x0009, + EVR_SH, "ScheduledProcedureStepID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x000a, 0x0040, 0x000a, + EVR_SQ, "StageCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x000b, 0x0040, 0x000b, + EVR_SQ, "ScheduledPerformingPhysicianIdentificationSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x0010, 0x0040, 0x0010, + EVR_SH, "ScheduledStationName", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x0011, 0x0040, 0x0011, + EVR_SH, "ScheduledProcedureStepLocation", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x0012, 0x0040, 0x0012, + EVR_LO, "PreMedication", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x0020, 0x0040, 0x0020, + EVR_CS, "ScheduledProcedureStepStatus", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x0026, 0x0040, 0x0026, + EVR_SQ, "OrderPlacerIdentifierSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x0027, 0x0040, 0x0027, + EVR_SQ, "OrderFillerIdentifierSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x0031, 0x0040, 0x0031, + EVR_UT, "LocalNamespaceEntityID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x0032, 0x0040, 0x0032, + EVR_UT, "UniversalEntityID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x0033, 0x0040, 0x0033, + EVR_CS, "UniversalEntityIDType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x0035, 0x0040, 0x0035, + EVR_CS, "IdentifierTypeCode", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x0036, 0x0040, 0x0036, + EVR_SQ, "AssigningFacilitySequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x0039, 0x0040, 0x0039, + EVR_SQ, "AssigningJurisdictionCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x003a, 0x0040, 0x003a, + EVR_SQ, "AssigningAgencyOrDepartmentCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x0100, 0x0040, 0x0100, + EVR_SQ, "ScheduledProcedureStepSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x0220, 0x0040, 0x0220, + EVR_SQ, "ReferencedNonImageCompositeSOPInstanceSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x0241, 0x0040, 0x0241, + EVR_AE, "PerformedStationAETitle", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x0242, 0x0040, 0x0242, + EVR_SH, "PerformedStationName", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x0243, 0x0040, 0x0243, + EVR_SH, "PerformedLocation", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x0244, 0x0040, 0x0244, + EVR_DA, "PerformedProcedureStepStartDate", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x0245, 0x0040, 0x0245, + EVR_TM, "PerformedProcedureStepStartTime", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x0250, 0x0040, 0x0250, + EVR_DA, "PerformedProcedureStepEndDate", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x0251, 0x0040, 0x0251, + EVR_TM, "PerformedProcedureStepEndTime", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x0252, 0x0040, 0x0252, + EVR_CS, "PerformedProcedureStepStatus", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x0253, 0x0040, 0x0253, + EVR_SH, "PerformedProcedureStepID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x0254, 0x0040, 0x0254, + EVR_LO, "PerformedProcedureStepDescription", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x0255, 0x0040, 0x0255, + EVR_LO, "PerformedProcedureTypeDescription", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x0260, 0x0040, 0x0260, + EVR_SQ, "PerformedProtocolCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x0261, 0x0040, 0x0261, + EVR_CS, "PerformedProtocolType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x0270, 0x0040, 0x0270, + EVR_SQ, "ScheduledStepAttributesSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x0275, 0x0040, 0x0275, + EVR_SQ, "RequestAttributesSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x0280, 0x0040, 0x0280, + EVR_ST, "CommentsOnThePerformedProcedureStep", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x0281, 0x0040, 0x0281, + EVR_SQ, "PerformedProcedureStepDiscontinuationReasonCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x0293, 0x0040, 0x0293, + EVR_SQ, "QuantitySequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x0294, 0x0040, 0x0294, + EVR_DS, "Quantity", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x0295, 0x0040, 0x0295, + EVR_SQ, "MeasuringUnitsSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x0296, 0x0040, 0x0296, + EVR_SQ, "BillingItemSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x0300, 0x0040, 0x0300, + EVR_US, "TotalTimeOfFluoroscopy", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x0301, 0x0040, 0x0301, + EVR_US, "TotalNumberOfExposures", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x0302, 0x0040, 0x0302, + EVR_US, "EntranceDose", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x0303, 0x0040, 0x0303, + EVR_US, "ExposedArea", 1, 2, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x0306, 0x0040, 0x0306, + EVR_DS, "DistanceSourceToEntrance", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x0307, 0x0040, 0x0307, + EVR_DS, "RETIRED_DistanceSourceToSupport", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x030e, 0x0040, 0x030e, + EVR_SQ, "ExposureDoseSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x0310, 0x0040, 0x0310, + EVR_ST, "CommentsOnRadiationDose", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x0312, 0x0040, 0x0312, + EVR_DS, "XRayOutput", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x0314, 0x0040, 0x0314, + EVR_DS, "HalfValueLayer", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x0316, 0x0040, 0x0316, + EVR_DS, "OrganDose", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x0318, 0x0040, 0x0318, + EVR_CS, "OrganExposed", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x0320, 0x0040, 0x0320, + EVR_SQ, "BillingProcedureStepSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x0321, 0x0040, 0x0321, + EVR_SQ, "FilmConsumptionSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x0324, 0x0040, 0x0324, + EVR_SQ, "BillingSuppliesAndDevicesSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x0330, 0x0040, 0x0330, + EVR_SQ, "RETIRED_ReferencedProcedureStepSequence", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x0340, 0x0040, 0x0340, + EVR_SQ, "PerformedSeriesSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x0400, 0x0040, 0x0400, + EVR_LT, "CommentsOnTheScheduledProcedureStep", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x0440, 0x0040, 0x0440, + EVR_SQ, "ProtocolContextSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x0441, 0x0040, 0x0441, + EVR_SQ, "ContentItemModifierSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x0500, 0x0040, 0x0500, + EVR_SQ, "ScheduledSpecimenSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x050a, 0x0040, 0x050a, + EVR_LO, "RETIRED_SpecimenAccessionNumber", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x0512, 0x0040, 0x0512, + EVR_LO, "ContainerIdentifier", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x0513, 0x0040, 0x0513, + EVR_SQ, "IssuerOfTheContainerIdentifierSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x0515, 0x0040, 0x0515, + EVR_SQ, "AlternateContainerIdentifierSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x0518, 0x0040, 0x0518, + EVR_SQ, "ContainerTypeCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x051a, 0x0040, 0x051a, + EVR_LO, "ContainerDescription", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x0520, 0x0040, 0x0520, + EVR_SQ, "ContainerComponentSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x0550, 0x0040, 0x0550, + EVR_SQ, "RETIRED_SpecimenSequence", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x0551, 0x0040, 0x0551, + EVR_LO, "SpecimenIdentifier", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x0552, 0x0040, 0x0552, + EVR_SQ, "RETIRED_SpecimenDescriptionSequenceTrial", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x0553, 0x0040, 0x0553, + EVR_ST, "RETIRED_SpecimenDescriptionTrial", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x0554, 0x0040, 0x0554, + EVR_UI, "SpecimenUID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x0555, 0x0040, 0x0555, + EVR_SQ, "AcquisitionContextSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x0556, 0x0040, 0x0556, + EVR_ST, "AcquisitionContextDescription", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x0560, 0x0040, 0x0560, + EVR_SQ, "SpecimenDescriptionSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x0562, 0x0040, 0x0562, + EVR_SQ, "IssuerOfTheSpecimenIdentifierSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x059a, 0x0040, 0x059a, + EVR_SQ, "SpecimenTypeCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x0600, 0x0040, 0x0600, + EVR_LO, "SpecimenShortDescription", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x0602, 0x0040, 0x0602, + EVR_UT, "SpecimenDetailedDescription", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x0610, 0x0040, 0x0610, + EVR_SQ, "SpecimenPreparationSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x0612, 0x0040, 0x0612, + EVR_SQ, "SpecimenPreparationStepContentItemSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x0620, 0x0040, 0x0620, + EVR_SQ, "SpecimenLocalizationContentItemSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x06fa, 0x0040, 0x06fa, + EVR_LO, "RETIRED_SlideIdentifier", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x071a, 0x0040, 0x071a, + EVR_SQ, "ImageCenterPointCoordinatesSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x072a, 0x0040, 0x072a, + EVR_DS, "XOffsetInSlideCoordinateSystem", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x073a, 0x0040, 0x073a, + EVR_DS, "YOffsetInSlideCoordinateSystem", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x074a, 0x0040, 0x074a, + EVR_DS, "ZOffsetInSlideCoordinateSystem", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x08d8, 0x0040, 0x08d8, + EVR_SQ, "RETIRED_PixelSpacingSequence", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x08da, 0x0040, 0x08da, + EVR_SQ, "RETIRED_CoordinateSystemAxisCodeSequence", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x08ea, 0x0040, 0x08ea, + EVR_SQ, "MeasurementUnitsCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x09f8, 0x0040, 0x09f8, + EVR_SQ, "RETIRED_VitalStainCodeSequenceTrial", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x1001, 0x0040, 0x1001, + EVR_SH, "RequestedProcedureID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x1002, 0x0040, 0x1002, + EVR_LO, "ReasonForTheRequestedProcedure", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x1003, 0x0040, 0x1003, + EVR_SH, "RequestedProcedurePriority", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x1004, 0x0040, 0x1004, + EVR_LO, "PatientTransportArrangements", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x1005, 0x0040, 0x1005, + EVR_LO, "RequestedProcedureLocation", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x1006, 0x0040, 0x1006, + EVR_SH, "RETIRED_PlacerOrderNumberProcedure", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x1007, 0x0040, 0x1007, + EVR_SH, "RETIRED_FillerOrderNumberProcedure", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x1008, 0x0040, 0x1008, + EVR_LO, "ConfidentialityCode", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x1009, 0x0040, 0x1009, + EVR_SH, "ReportingPriority", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x100a, 0x0040, 0x100a, + EVR_SQ, "ReasonForRequestedProcedureCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x1010, 0x0040, 0x1010, + EVR_PN, "NamesOfIntendedRecipientsOfResults", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x1011, 0x0040, 0x1011, + EVR_SQ, "IntendedRecipientsOfResultsIdentificationSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x1012, 0x0040, 0x1012, + EVR_SQ, "ReasonForPerformedProcedureCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x1060, 0x0040, 0x1060, + EVR_LO, "RETIRED_RequestedProcedureDescriptionTrial", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x1101, 0x0040, 0x1101, + EVR_SQ, "PersonIdentificationCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x1102, 0x0040, 0x1102, + EVR_ST, "PersonAddress", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x1103, 0x0040, 0x1103, + EVR_LO, "PersonTelephoneNumbers", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x1104, 0x0040, 0x1104, + EVR_LT, "PersonTelecomInformation", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x1400, 0x0040, 0x1400, + EVR_LT, "RequestedProcedureComments", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x2001, 0x0040, 0x2001, + EVR_LO, "RETIRED_ReasonForTheImagingServiceRequest", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x2004, 0x0040, 0x2004, + EVR_DA, "IssueDateOfImagingServiceRequest", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x2005, 0x0040, 0x2005, + EVR_TM, "IssueTimeOfImagingServiceRequest", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x2006, 0x0040, 0x2006, + EVR_SH, "RETIRED_PlacerOrderNumberImagingServiceRequestRetired", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x2007, 0x0040, 0x2007, + EVR_SH, "RETIRED_FillerOrderNumberImagingServiceRequestRetired", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x2008, 0x0040, 0x2008, + EVR_PN, "OrderEnteredBy", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x2009, 0x0040, 0x2009, + EVR_SH, "OrderEntererLocation", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x2010, 0x0040, 0x2010, + EVR_SH, "OrderCallbackPhoneNumber", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x2011, 0x0040, 0x2011, + EVR_LT, "OrderCallbackTelecomInformation", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x2016, 0x0040, 0x2016, + EVR_LO, "PlacerOrderNumberImagingServiceRequest", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x2017, 0x0040, 0x2017, + EVR_LO, "FillerOrderNumberImagingServiceRequest", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x2400, 0x0040, 0x2400, + EVR_LT, "ImagingServiceRequestComments", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x3001, 0x0040, 0x3001, + EVR_LO, "ConfidentialityConstraintOnPatientDataDescription", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x4001, 0x0040, 0x4001, + EVR_CS, "RETIRED_GeneralPurposeScheduledProcedureStepStatus", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x4002, 0x0040, 0x4002, + EVR_CS, "RETIRED_GeneralPurposePerformedProcedureStepStatus", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x4003, 0x0040, 0x4003, + EVR_CS, "RETIRED_GeneralPurposeScheduledProcedureStepPriority", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x4004, 0x0040, 0x4004, + EVR_SQ, "RETIRED_ScheduledProcessingApplicationsCodeSequence", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x4005, 0x0040, 0x4005, + EVR_DT, "ScheduledProcedureStepStartDateTime", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x4006, 0x0040, 0x4006, + EVR_CS, "RETIRED_MultipleCopiesFlag", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x4007, 0x0040, 0x4007, + EVR_SQ, "PerformedProcessingApplicationsCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x4009, 0x0040, 0x4009, + EVR_SQ, "HumanPerformerCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x4010, 0x0040, 0x4010, + EVR_DT, "ScheduledProcedureStepModificationDateTime", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x4011, 0x0040, 0x4011, + EVR_DT, "ExpectedCompletionDateTime", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x4015, 0x0040, 0x4015, + EVR_SQ, "RETIRED_ResultingGeneralPurposePerformedProcedureStepsSequence", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x4016, 0x0040, 0x4016, + EVR_SQ, "RETIRED_ReferencedGeneralPurposeScheduledProcedureStepSequence", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x4018, 0x0040, 0x4018, + EVR_SQ, "ScheduledWorkitemCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x4019, 0x0040, 0x4019, + EVR_SQ, "PerformedWorkitemCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x4020, 0x0040, 0x4020, + EVR_CS, "InputAvailabilityFlag", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x4021, 0x0040, 0x4021, + EVR_SQ, "InputInformationSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x4022, 0x0040, 0x4022, + EVR_SQ, "RETIRED_RelevantInformationSequence", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x4023, 0x0040, 0x4023, + EVR_UI, "RETIRED_ReferencedGeneralPurposeScheduledProcedureStepTransactionUID", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x4025, 0x0040, 0x4025, + EVR_SQ, "ScheduledStationNameCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x4026, 0x0040, 0x4026, + EVR_SQ, "ScheduledStationClassCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x4027, 0x0040, 0x4027, + EVR_SQ, "ScheduledStationGeographicLocationCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x4028, 0x0040, 0x4028, + EVR_SQ, "PerformedStationNameCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x4029, 0x0040, 0x4029, + EVR_SQ, "PerformedStationClassCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x4030, 0x0040, 0x4030, + EVR_SQ, "PerformedStationGeographicLocationCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x4031, 0x0040, 0x4031, + EVR_SQ, "RETIRED_RequestedSubsequentWorkitemCodeSequence", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x4032, 0x0040, 0x4032, + EVR_SQ, "RETIRED_NonDICOMOutputCodeSequence", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x4033, 0x0040, 0x4033, + EVR_SQ, "OutputInformationSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x4034, 0x0040, 0x4034, + EVR_SQ, "ScheduledHumanPerformersSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x4035, 0x0040, 0x4035, + EVR_SQ, "ActualHumanPerformersSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x4036, 0x0040, 0x4036, + EVR_LO, "HumanPerformerOrganization", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x4037, 0x0040, 0x4037, + EVR_PN, "HumanPerformerName", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x4040, 0x0040, 0x4040, + EVR_CS, "RawDataHandling", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x4041, 0x0040, 0x4041, + EVR_CS, "InputReadinessState", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x4050, 0x0040, 0x4050, + EVR_DT, "PerformedProcedureStepStartDateTime", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x4051, 0x0040, 0x4051, + EVR_DT, "PerformedProcedureStepEndDateTime", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x4052, 0x0040, 0x4052, + EVR_DT, "ProcedureStepCancellationDateTime", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x4070, 0x0040, 0x4070, + EVR_SQ, "OutputDestinationSequence", 1, 1, "CP_1441", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x4071, 0x0040, 0x4071, + EVR_SQ, "DICOMStorageSequence", 1, 1, "CP_1441", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x4072, 0x0040, 0x4072, + EVR_SQ, "STOWRSStorageSequence", 1, 1, "CP_1441", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x4073, 0x0040, 0x4073, + EVR_UR, "StorageURL", 1, 1, "CP_1441", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x4074, 0x0040, 0x4074, + EVR_SQ, "XDSStorageSequence", 1, 1, "CP_1441", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x8302, 0x0040, 0x8302, + EVR_DS, "EntranceDoseInmGy", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x9092, 0x0040, 0x9092, + EVR_SQ, "ParametricMapFrameTypeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x9094, 0x0040, 0x9094, + EVR_SQ, "ReferencedImageRealWorldValueMappingSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x9096, 0x0040, 0x9096, + EVR_SQ, "RealWorldValueMappingSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x9098, 0x0040, 0x9098, + EVR_SQ, "PixelValueMappingCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x9210, 0x0040, 0x9210, + EVR_SH, "LUTLabel", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x9211, 0x0040, 0x9211, + EVR_xs, "RealWorldValueLastValueMapped", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x9212, 0x0040, 0x9212, + EVR_FD, "RealWorldValueLUTData", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x9213, 0x0040, 0x9213, + EVR_FD, "DoubleFloatRealWorldValueLastValueMapped", 1, 1, "CP_1458", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x9214, 0x0040, 0x9214, + EVR_FD, "DoubleFloatRealWorldValueFirstValueMapped", 1, 1, "CP_1458", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x9216, 0x0040, 0x9216, + EVR_xs, "RealWorldValueFirstValueMapped", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x9220, 0x0040, 0x9220, + EVR_SQ, "QuantityDefinitionSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x9224, 0x0040, 0x9224, + EVR_FD, "RealWorldValueIntercept", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0x9225, 0x0040, 0x9225, + EVR_FD, "RealWorldValueSlope", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xa007, 0x0040, 0xa007, + EVR_CS, "RETIRED_FindingsFlagTrial", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xa010, 0x0040, 0xa010, + EVR_CS, "RelationshipType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xa020, 0x0040, 0xa020, + EVR_SQ, "RETIRED_FindingsSequenceTrial", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xa021, 0x0040, 0xa021, + EVR_UI, "RETIRED_FindingsGroupUIDTrial", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xa022, 0x0040, 0xa022, + EVR_UI, "RETIRED_ReferencedFindingsGroupUIDTrial", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xa023, 0x0040, 0xa023, + EVR_DA, "RETIRED_FindingsGroupRecordingDateTrial", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xa024, 0x0040, 0xa024, + EVR_TM, "RETIRED_FindingsGroupRecordingTimeTrial", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xa026, 0x0040, 0xa026, + EVR_SQ, "RETIRED_FindingsSourceCategoryCodeSequenceTrial", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xa027, 0x0040, 0xa027, + EVR_LO, "VerifyingOrganization", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xa028, 0x0040, 0xa028, + EVR_SQ, "RETIRED_DocumentingOrganizationIdentifierCodeSequenceTrial", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xa030, 0x0040, 0xa030, + EVR_DT, "VerificationDateTime", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xa032, 0x0040, 0xa032, + EVR_DT, "ObservationDateTime", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xa040, 0x0040, 0xa040, + EVR_CS, "ValueType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xa043, 0x0040, 0xa043, + EVR_SQ, "ConceptNameCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xa047, 0x0040, 0xa047, + EVR_LO, "RETIRED_MeasurementPrecisionDescriptionTrial", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xa050, 0x0040, 0xa050, + EVR_CS, "ContinuityOfContent", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xa057, 0x0040, 0xa057, + EVR_CS, "RETIRED_UrgencyOrPriorityAlertsTrial", 1, -1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xa060, 0x0040, 0xa060, + EVR_LO, "RETIRED_SequencingIndicatorTrial", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xa066, 0x0040, 0xa066, + EVR_SQ, "RETIRED_DocumentIdentifierCodeSequenceTrial", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xa067, 0x0040, 0xa067, + EVR_PN, "RETIRED_DocumentAuthorTrial", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xa068, 0x0040, 0xa068, + EVR_SQ, "RETIRED_DocumentAuthorIdentifierCodeSequenceTrial", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xa070, 0x0040, 0xa070, + EVR_SQ, "RETIRED_IdentifierCodeSequenceTrial", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xa073, 0x0040, 0xa073, + EVR_SQ, "VerifyingObserverSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xa074, 0x0040, 0xa074, + EVR_OB, "RETIRED_ObjectBinaryIdentifierTrial", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xa075, 0x0040, 0xa075, + EVR_PN, "VerifyingObserverName", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xa076, 0x0040, 0xa076, + EVR_SQ, "RETIRED_DocumentingObserverIdentifierCodeSequenceTrial", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xa078, 0x0040, 0xa078, + EVR_SQ, "AuthorObserverSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xa07a, 0x0040, 0xa07a, + EVR_SQ, "ParticipantSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xa07c, 0x0040, 0xa07c, + EVR_SQ, "CustodialOrganizationSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xa080, 0x0040, 0xa080, + EVR_CS, "ParticipationType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xa082, 0x0040, 0xa082, + EVR_DT, "ParticipationDateTime", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xa084, 0x0040, 0xa084, + EVR_CS, "ObserverType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xa085, 0x0040, 0xa085, + EVR_SQ, "RETIRED_ProcedureIdentifierCodeSequenceTrial", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xa088, 0x0040, 0xa088, + EVR_SQ, "VerifyingObserverIdentificationCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xa089, 0x0040, 0xa089, + EVR_OB, "RETIRED_ObjectDirectoryBinaryIdentifierTrial", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xa090, 0x0040, 0xa090, + EVR_SQ, "RETIRED_EquivalentCDADocumentSequence", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xa0b0, 0x0040, 0xa0b0, + EVR_US, "ReferencedWaveformChannels", 2, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xa110, 0x0040, 0xa110, + EVR_DA, "RETIRED_DateOfDocumentOrVerbalTransactionTrial", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xa112, 0x0040, 0xa112, + EVR_TM, "RETIRED_TimeOfDocumentCreationOrVerbalTransactionTrial", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xa120, 0x0040, 0xa120, + EVR_DT, "DateTime", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xa121, 0x0040, 0xa121, + EVR_DA, "Date", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xa122, 0x0040, 0xa122, + EVR_TM, "Time", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xa123, 0x0040, 0xa123, + EVR_PN, "PersonName", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xa124, 0x0040, 0xa124, + EVR_UI, "UID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xa125, 0x0040, 0xa125, + EVR_CS, "RETIRED_ReportStatusIDTrial", 2, 2, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xa130, 0x0040, 0xa130, + EVR_CS, "TemporalRangeType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xa132, 0x0040, 0xa132, + EVR_UL, "ReferencedSamplePositions", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xa136, 0x0040, 0xa136, + EVR_US, "ReferencedFrameNumbers", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xa138, 0x0040, 0xa138, + EVR_DS, "ReferencedTimeOffsets", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xa13a, 0x0040, 0xa13a, + EVR_DT, "ReferencedDateTime", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xa160, 0x0040, 0xa160, + EVR_UT, "TextValue", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xa161, 0x0040, 0xa161, + EVR_FD, "FloatingPointValue", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xa162, 0x0040, 0xa162, + EVR_SL, "RationalNumeratorValue", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xa163, 0x0040, 0xa163, + EVR_UL, "RationalDenominatorValue", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xa167, 0x0040, 0xa167, + EVR_SQ, "RETIRED_ObservationCategoryCodeSequenceTrial", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xa168, 0x0040, 0xa168, + EVR_SQ, "ConceptCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xa16a, 0x0040, 0xa16a, + EVR_ST, "RETIRED_BibliographicCitationTrial", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xa170, 0x0040, 0xa170, + EVR_SQ, "PurposeOfReferenceCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xa171, 0x0040, 0xa171, + EVR_UI, "ObservationUID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xa172, 0x0040, 0xa172, + EVR_UI, "RETIRED_ReferencedObservationUIDTrial", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xa173, 0x0040, 0xa173, + EVR_CS, "RETIRED_ReferencedObservationClassTrial", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xa174, 0x0040, 0xa174, + EVR_CS, "RETIRED_ReferencedObjectObservationClassTrial", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xa180, 0x0040, 0xa180, + EVR_US, "AnnotationGroupNumber", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xa192, 0x0040, 0xa192, + EVR_DA, "RETIRED_ObservationDateTrial", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xa193, 0x0040, 0xa193, + EVR_TM, "RETIRED_ObservationTimeTrial", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xa194, 0x0040, 0xa194, + EVR_CS, "RETIRED_MeasurementAutomationTrial", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xa195, 0x0040, 0xa195, + EVR_SQ, "ModifierCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xa224, 0x0040, 0xa224, + EVR_ST, "RETIRED_IdentificationDescriptionTrial", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xa290, 0x0040, 0xa290, + EVR_CS, "RETIRED_CoordinatesSetGeometricTypeTrial", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xa296, 0x0040, 0xa296, + EVR_SQ, "RETIRED_AlgorithmCodeSequenceTrial", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xa297, 0x0040, 0xa297, + EVR_ST, "RETIRED_AlgorithmDescriptionTrial", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xa29a, 0x0040, 0xa29a, + EVR_SL, "RETIRED_PixelCoordinatesSetTrial", 2, -1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xa300, 0x0040, 0xa300, + EVR_SQ, "MeasuredValueSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xa301, 0x0040, 0xa301, + EVR_SQ, "NumericValueQualifierCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xa307, 0x0040, 0xa307, + EVR_PN, "RETIRED_CurrentObserverTrial", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xa30a, 0x0040, 0xa30a, + EVR_DS, "NumericValue", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xa313, 0x0040, 0xa313, + EVR_SQ, "RETIRED_ReferencedAccessionSequenceTrial", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xa33a, 0x0040, 0xa33a, + EVR_ST, "RETIRED_ReportStatusCommentTrial", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xa340, 0x0040, 0xa340, + EVR_SQ, "RETIRED_ProcedureContextSequenceTrial", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xa352, 0x0040, 0xa352, + EVR_PN, "RETIRED_VerbalSourceTrial", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xa353, 0x0040, 0xa353, + EVR_ST, "RETIRED_AddressTrial", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xa354, 0x0040, 0xa354, + EVR_LO, "RETIRED_TelephoneNumberTrial", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xa358, 0x0040, 0xa358, + EVR_SQ, "RETIRED_VerbalSourceIdentifierCodeSequenceTrial", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xa360, 0x0040, 0xa360, + EVR_SQ, "PredecessorDocumentsSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xa370, 0x0040, 0xa370, + EVR_SQ, "ReferencedRequestSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xa372, 0x0040, 0xa372, + EVR_SQ, "PerformedProcedureCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xa375, 0x0040, 0xa375, + EVR_SQ, "CurrentRequestedProcedureEvidenceSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xa380, 0x0040, 0xa380, + EVR_SQ, "RETIRED_ReportDetailSequenceTrial", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xa385, 0x0040, 0xa385, + EVR_SQ, "PertinentOtherEvidenceSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xa390, 0x0040, 0xa390, + EVR_SQ, "HL7StructuredDocumentReferenceSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xa402, 0x0040, 0xa402, + EVR_UI, "RETIRED_ObservationSubjectUIDTrial", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xa403, 0x0040, 0xa403, + EVR_CS, "RETIRED_ObservationSubjectClassTrial", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xa404, 0x0040, 0xa404, + EVR_SQ, "RETIRED_ObservationSubjectTypeCodeSequenceTrial", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xa491, 0x0040, 0xa491, + EVR_CS, "CompletionFlag", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xa492, 0x0040, 0xa492, + EVR_LO, "CompletionFlagDescription", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xa493, 0x0040, 0xa493, + EVR_CS, "VerificationFlag", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xa494, 0x0040, 0xa494, + EVR_CS, "ArchiveRequested", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xa496, 0x0040, 0xa496, + EVR_CS, "PreliminaryFlag", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xa504, 0x0040, 0xa504, + EVR_SQ, "ContentTemplateSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xa525, 0x0040, 0xa525, + EVR_SQ, "IdenticalDocumentsSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xa600, 0x0040, 0xa600, + EVR_CS, "RETIRED_ObservationSubjectContextFlagTrial", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xa601, 0x0040, 0xa601, + EVR_CS, "RETIRED_ObserverContextFlagTrial", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xa603, 0x0040, 0xa603, + EVR_CS, "RETIRED_ProcedureContextFlagTrial", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xa730, 0x0040, 0xa730, + EVR_SQ, "ContentSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xa731, 0x0040, 0xa731, + EVR_SQ, "RETIRED_RelationshipSequenceTrial", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xa732, 0x0040, 0xa732, + EVR_SQ, "RETIRED_RelationshipTypeCodeSequenceTrial", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xa744, 0x0040, 0xa744, + EVR_SQ, "RETIRED_LanguageCodeSequenceTrial", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xa992, 0x0040, 0xa992, + EVR_ST, "RETIRED_UniformResourceLocatorTrial", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xb020, 0x0040, 0xb020, + EVR_SQ, "WaveformAnnotationSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xdb00, 0x0040, 0xdb00, + EVR_CS, "TemplateIdentifier", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xdb06, 0x0040, 0xdb06, + EVR_DT, "RETIRED_TemplateVersion", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xdb07, 0x0040, 0xdb07, + EVR_DT, "RETIRED_TemplateLocalVersion", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xdb0b, 0x0040, 0xdb0b, + EVR_CS, "RETIRED_TemplateExtensionFlag", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xdb0c, 0x0040, 0xdb0c, + EVR_UI, "RETIRED_TemplateExtensionOrganizationUID", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xdb0d, 0x0040, 0xdb0d, + EVR_UI, "RETIRED_TemplateExtensionCreatorUID", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xdb73, 0x0040, 0xdb73, + EVR_UL, "ReferencedContentItemIdentifier", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xe001, 0x0040, 0xe001, + EVR_ST, "HL7InstanceIdentifier", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xe004, 0x0040, 0xe004, + EVR_DT, "HL7DocumentEffectiveTime", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xe006, 0x0040, 0xe006, + EVR_SQ, "HL7DocumentTypeCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xe008, 0x0040, 0xe008, + EVR_SQ, "DocumentClassCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xe010, 0x0040, 0xe010, + EVR_UR, "RetrieveURI", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xe011, 0x0040, 0xe011, + EVR_UI, "RetrieveLocationUID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xe020, 0x0040, 0xe020, + EVR_CS, "TypeOfInstances", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xe021, 0x0040, 0xe021, + EVR_SQ, "DICOMRetrievalSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xe022, 0x0040, 0xe022, + EVR_SQ, "DICOMMediaRetrievalSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xe023, 0x0040, 0xe023, + EVR_SQ, "WADORetrievalSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xe024, 0x0040, 0xe024, + EVR_SQ, "XDSRetrievalSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xe025, 0x0040, 0xe025, + EVR_SQ, "WADORSRetrievalSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xe030, 0x0040, 0xe030, + EVR_UI, "RepositoryUniqueID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0040, 0xe031, 0x0040, 0xe031, + EVR_UI, "HomeCommunityID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } +#ifdef ENABLE_PRIVATE_TAGS + , { 0x0041, 0x0000, 0x0041, 0x0000, + EVR_LT, "PapyrusComments", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PAPYRUS 3.0" } + , { 0x0041, 0x0000, 0x0041, 0x0000, + EVR_LT, "PapyrusComments", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PAPYRUS" } + , { 0x0041, 0x0010, 0x0041, 0x0010, + EVR_SQ, "PointerSequence", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PAPYRUS 3.0" } + , { 0x0041, 0x0010, 0x0041, 0x0010, + EVR_US, "FolderType", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PAPYRUS" } + , { 0x0041, 0x0010, 0x0041, 0x0010, + EVR_US, "NumberOfHardcopies", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS DLR.01" } + , { 0x0041, 0x0011, 0x0041, 0x0011, + EVR_UL, "ImagePointer", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PAPYRUS 3.0" } + , { 0x0041, 0x0011, 0x0041, 0x0011, + EVR_LT, "PatientFolderDataSetID", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PAPYRUS" } + , { 0x0041, 0x0012, 0x0041, 0x0012, + EVR_UL, "PixelOffset", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PAPYRUS 3.0" } + , { 0x0041, 0x0013, 0x0041, 0x0013, + EVR_SQ, "ImageIdentifierSequence", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PAPYRUS 3.0" } + , { 0x0041, 0x0014, 0x0041, 0x0014, + EVR_SQ, "ExternalFileReferenceSequence", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PAPYRUS 3.0" } + , { 0x0041, 0x0015, 0x0041, 0x0015, + EVR_US, "NumberOfImages", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PAPYRUS 3.0" } + , { 0x0041, 0x0020, 0x0041, 0x0020, + EVR_LT, "FolderName", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PAPYRUS" } + , { 0x0041, 0x0020, 0x0041, 0x0020, + EVR_LT, "FilmFormat", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS DLR.01" } + , { 0x0041, 0x0020, 0x0041, 0x0020, + EVR_FL, "AccumulatedFluoroscopyDose", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "INTEGRIS 1.0" } + , { 0x0041, 0x0021, 0x0041, 0x0021, + EVR_UI, "ReferencedSOPClassUID", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PAPYRUS 3.0" } + , { 0x0041, 0x0022, 0x0041, 0x0022, + EVR_UI, "ReferencedSOPInstanceUID", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PAPYRUS 3.0" } + , { 0x0041, 0x0030, 0x0041, 0x0030, + EVR_DA, "CreationDate", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PAPYRUS" } + , { 0x0041, 0x0030, 0x0041, 0x0030, + EVR_LT, "FilmSize", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS DLR.01" } + , { 0x0041, 0x0030, 0x0041, 0x0030, + EVR_FL, "AccumulatedExposureDose", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "INTEGRIS 1.0" } + , { 0x0041, 0x0031, 0x0041, 0x0031, + EVR_LT, "ReferencedFileName", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PAPYRUS 3.0" } + , { 0x0041, 0x0031, 0x0041, 0x0031, + EVR_LT, "FullFilmFormat", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS DLR.01" } + , { 0x0041, 0x0032, 0x0041, 0x0032, + EVR_LT, "ReferencedFilePath", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PAPYRUS 3.0" } + , { 0x0041, 0x0032, 0x0041, 0x0032, + EVR_TM, "CreationTime", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PAPYRUS" } + , { 0x0041, 0x0034, 0x0041, 0x0034, + EVR_DA, "ModifiedDate", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PAPYRUS" } + , { 0x0041, 0x0036, 0x0041, 0x0036, + EVR_TM, "ModifiedTime", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PAPYRUS" } + , { 0x0041, 0x0040, 0x0041, 0x0040, + EVR_LT, "OwnerName", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PAPYRUS" } + , { 0x0041, 0x0040, 0x0041, 0x0040, + EVR_FL, "TotalDose", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "INTEGRIS 1.0" } + , { 0x0041, 0x0041, 0x0041, 0x0041, + EVR_UI, "ReferencedImageSOPClassUID", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PAPYRUS 3.0" } + , { 0x0041, 0x0041, 0x0041, 0x0041, + EVR_FL, "TotalNumberOfFrames", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "INTEGRIS 1.0" } + , { 0x0041, 0x0042, 0x0041, 0x0042, + EVR_UI, "ReferencedImageSOPInstanceUID", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PAPYRUS 3.0" } + , { 0x0041, 0x0050, 0x0041, 0x0050, + EVR_SQ, "ImageSequence", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PAPYRUS 3.0" } + , { 0x0041, 0x0050, 0x0041, 0x0050, + EVR_LT, "FolderStatus", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PAPYRUS" } + , { 0x0041, 0x0050, 0x0041, 0x0050, + EVR_SQ, "ExposureInformationSequence", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "INTEGRIS 1.0" } + , { 0x0041, 0x0060, 0x0041, 0x0060, + EVR_UL, "NumberOfImages", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PAPYRUS" } + , { 0x0041, 0x0062, 0x0041, 0x0062, + EVR_UL, "NumberOfOther", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PAPYRUS" } + , { 0x0041, 0x00a0, 0x0041, 0x00a0, + EVR_LT, "ExternalFolderElementDSID", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PAPYRUS" } + , { 0x0041, 0x00a1, 0x0041, 0x00a1, + EVR_US, "ExternalFolderElementDataSetType", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PAPYRUS" } + , { 0x0041, 0x00a2, 0x0041, 0x00a2, + EVR_LT, "ExternalFolderElementFileLocation", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PAPYRUS" } + , { 0x0041, 0x00a3, 0x0041, 0x00a3, + EVR_UL, "ExternalFolderElementLength", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PAPYRUS" } + , { 0x0041, 0x00b0, 0x0041, 0x00b0, + EVR_LT, "InternalFolderElementDSID", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PAPYRUS" } + , { 0x0041, 0x00b1, 0x0041, 0x00b1, + EVR_US, "InternalFolderElementDataSetType", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PAPYRUS" } + , { 0x0041, 0x00b2, 0x0041, 0x00b2, + EVR_UL, "InternalOffsetToDataSet", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PAPYRUS" } + , { 0x0041, 0x00b3, 0x0041, 0x00b3, + EVR_UL, "InternalOffsetToImage", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PAPYRUS" } +#endif + , { 0x0042, 0x0010, 0x0042, 0x0010, + EVR_ST, "DocumentTitle", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0042, 0x0011, 0x0042, 0x0011, + EVR_OB, "EncapsulatedDocument", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0042, 0x0012, 0x0042, 0x0012, + EVR_LO, "MIMETypeOfEncapsulatedDocument", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0042, 0x0013, 0x0042, 0x0013, + EVR_SQ, "SourceInstanceSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0042, 0x0014, 0x0042, 0x0014, + EVR_LO, "ListOfMIMETypes", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } +#ifdef ENABLE_PRIVATE_TAGS + , { 0x0043, 0x0001, 0x0043, 0x0001, + EVR_SS, "BitmapOfPrescanOptions", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x0002, 0x0043, 0x0002, + EVR_SS, "GradientOffsetInX", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x0003, 0x0043, 0x0003, + EVR_SS, "GradientOffsetInY", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x0004, 0x0043, 0x0004, + EVR_SS, "GradientOffsetInZ", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x0005, 0x0043, 0x0005, + EVR_SS, "ImageIsOriginalOrUnoriginal", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x0006, 0x0043, 0x0006, + EVR_SS, "NumberOfEPIShots", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x0007, 0x0043, 0x0007, + EVR_SS, "ViewsPerSegment", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x0008, 0x0043, 0x0008, + EVR_SS, "RespiratoryRateInBPM", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x0009, 0x0043, 0x0009, + EVR_SS, "RespiratoryTriggerPoint", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x000a, 0x0043, 0x000a, + EVR_SS, "TypeOfReceiverUsed", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x000b, 0x0043, 0x000b, + EVR_DS, "PeakRateOfChangeOfGradientField", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x000c, 0x0043, 0x000c, + EVR_DS, "LimitsInUnitsOfPercent", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x000d, 0x0043, 0x000d, + EVR_DS, "PSDEstimatedLimit", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x000e, 0x0043, 0x000e, + EVR_DS, "PSDEstimatedLimitInTeslaPerSecond", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x000f, 0x0043, 0x000f, + EVR_DS, "SARAvgHead", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x0010, 0x0043, 0x0010, + EVR_US, "WindowValue", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x0011, 0x0043, 0x0011, + EVR_US, "TotalInputViews", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x0012, 0x0043, 0x0012, + EVR_SS, "XrayChain", 3, 3, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x0013, 0x0043, 0x0013, + EVR_SS, "ReconKernelParameters", 5, 5, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x0014, 0x0043, 0x0014, + EVR_SS, "CalibrationParameters", 3, 3, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x0015, 0x0043, 0x0015, + EVR_SS, "TotalOutputViews", 3, 3, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x0016, 0x0043, 0x0016, + EVR_SS, "NumberOfOverranges", 5, 5, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x0017, 0x0043, 0x0017, + EVR_DS, "IBHImageScaleFactors", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x0018, 0x0043, 0x0018, + EVR_DS, "BBHCoefficients", 3, 3, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x0019, 0x0043, 0x0019, + EVR_SS, "NumberOfBBHChainsToBlend", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x001a, 0x0043, 0x001a, + EVR_SL, "StartingChannelNumber", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x001b, 0x0043, 0x001b, + EVR_SS, "PPScanParameters", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x001c, 0x0043, 0x001c, + EVR_SS, "GEImageIntegrity", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x001d, 0x0043, 0x001d, + EVR_SS, "LevelValue", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x001e, 0x0043, 0x001e, + EVR_DS, "DeltaStartTime", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GE_GENESIS_REV3.0" } + , { 0x0043, 0x001e, 0x0043, 0x001e, + EVR_DS, "DeltaStartTime", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x001f, 0x0043, 0x001f, + EVR_SL, "MaxOverrangesInAView", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x0020, 0x0043, 0x0020, + EVR_DS, "AvgOverrangesAllViews", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x0021, 0x0043, 0x0021, + EVR_SS, "CorrectedAfterglowTerms", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x0025, 0x0043, 0x0025, + EVR_SS, "ReferenceChannels", 6, 6, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x0026, 0x0043, 0x0026, + EVR_US, "NoViewsRefChannelsBlocked", 6, 6, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x0027, 0x0043, 0x0027, + EVR_SH, "ScanPitchRatio", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GE_GENESIS_REV3.0" } + , { 0x0043, 0x0027, 0x0043, 0x0027, + EVR_SH, "ScanPitchRatio", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x0028, 0x0043, 0x0028, + EVR_OB, "UniqueImageIdentifier", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x0029, 0x0043, 0x0029, + EVR_OB, "HistogramTables", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x002a, 0x0043, 0x002a, + EVR_OB, "UserDefinedData", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x002b, 0x0043, 0x002b, + EVR_SS, "PrivateScanOptions", 4, 4, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x002c, 0x0043, 0x002c, + EVR_SS, "EffectiveEchoSpacing", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x002d, 0x0043, 0x002d, + EVR_SH, "StringSlopField1", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x002e, 0x0043, 0x002e, + EVR_SH, "StringSlopField2", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x002f, 0x0043, 0x002f, + EVR_SS, "RawDataType", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x0030, 0x0043, 0x0030, + EVR_SS, "RawDataType", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x0031, 0x0043, 0x0031, + EVR_DS, "RACoordOfTargetReconCentre", 2, 2, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x0032, 0x0043, 0x0032, + EVR_SS, "RawDataType", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x0033, 0x0043, 0x0033, + EVR_FL, "NegScanSpacing", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x0034, 0x0043, 0x0034, + EVR_IS, "OffsetFrequency", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x0035, 0x0043, 0x0035, + EVR_UL, "UserUsageTag", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x0036, 0x0043, 0x0036, + EVR_UL, "UserFillMapMSW", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x0037, 0x0043, 0x0037, + EVR_UL, "UserFillMapLSW", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x0038, 0x0043, 0x0038, + EVR_FL, "User25ToUser48", 24, 24, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x0039, 0x0043, 0x0039, + EVR_IS, "SlopInteger6ToSlopInteger9", 4, 4, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x0040, 0x0043, 0x0040, + EVR_FL, "TriggerOnPosition", 4, 4, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x0041, 0x0043, 0x0041, + EVR_FL, "DegreeOfRotation", 4, 4, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x0042, 0x0043, 0x0042, + EVR_SL, "DASTriggerSource", 4, 4, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x0043, 0x0043, 0x0043, + EVR_SL, "DASFpaGain", 4, 4, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x0044, 0x0043, 0x0044, + EVR_SL, "DASOutputSource", 4, 4, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x0045, 0x0043, 0x0045, + EVR_SL, "DASAdInput", 4, 4, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x0046, 0x0043, 0x0046, + EVR_SL, "DASCalMode", 4, 4, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x0047, 0x0043, 0x0047, + EVR_SL, "DASCalFrequency", 4, 4, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x0048, 0x0043, 0x0048, + EVR_SL, "DASRegXm", 4, 4, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x0049, 0x0043, 0x0049, + EVR_SL, "DASAutoZero", 4, 4, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x004a, 0x0043, 0x004a, + EVR_SS, "StartingChannelOfView", 4, 4, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x004b, 0x0043, 0x004b, + EVR_SL, "DASXmPattern", 4, 4, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x004c, 0x0043, 0x004c, + EVR_SS, "TGGCTriggerMode", 4, 4, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x004d, 0x0043, 0x004d, + EVR_FL, "StartScanToXrayOnDelay", 4, 4, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x004e, 0x0043, 0x004e, + EVR_FL, "DurationOfXrayOn", 4, 4, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x0060, 0x0043, 0x0060, + EVR_IS, "SlopInteger10ToSlopInteger17", 8, 8, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x0061, 0x0043, 0x0061, + EVR_UI, "ScannerStudyEntityUID", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x0062, 0x0043, 0x0062, + EVR_SH, "ScannerStudyID", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x006f, 0x0043, 0x006f, + EVR_DS, "ScannerTableEntry", 3, 3, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x0070, 0x0043, 0x0070, + EVR_LO, "ParadigmName", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x0071, 0x0043, 0x0071, + EVR_ST, "ParadigmDescription", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x0072, 0x0043, 0x0072, + EVR_UI, "ParadigmUID", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x0073, 0x0043, 0x0073, + EVR_US, "ExperimentType", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x0074, 0x0043, 0x0074, + EVR_US, "NumberOfRestVolumes", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x0075, 0x0043, 0x0075, + EVR_US, "NumberOfActiveVolumes", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x0076, 0x0043, 0x0076, + EVR_US, "NumberOfDummyScans", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x0077, 0x0043, 0x0077, + EVR_SH, "ApplicationName", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x0078, 0x0043, 0x0078, + EVR_SH, "ApplicationVersion", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x0079, 0x0043, 0x0079, + EVR_US, "SlicesPerVolume", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x007a, 0x0043, 0x007a, + EVR_US, "ExpectedTimePoints", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x007b, 0x0043, 0x007b, + EVR_FL, "RegressorValues", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x007c, 0x0043, 0x007c, + EVR_FL, "DelayAfterSliceGroup", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x007d, 0x0043, 0x007d, + EVR_US, "ReconModeFlagWord", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x007e, 0x0043, 0x007e, + EVR_LO, "PACCSpecificInformation", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x007f, 0x0043, 0x007f, + EVR_DS, "EDWIScaleFactor", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x0080, 0x0043, 0x0080, + EVR_LO, "CoilIDData", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x0081, 0x0043, 0x0081, + EVR_LO, "GECoilName", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x0082, 0x0043, 0x0082, + EVR_LO, "SystemConfigurationInformation", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x0083, 0x0043, 0x0083, + EVR_DS, "AssetRFactors", 1, 2, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x0084, 0x0043, 0x0084, + EVR_LO, "AdditionalAssetData", 5, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x0085, 0x0043, 0x0085, + EVR_UT, "DebugDataTextFormat", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x0086, 0x0043, 0x0086, + EVR_OB, "DebugDataBinaryFormat", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x0087, 0x0043, 0x0087, + EVR_UT, "ScannerSoftwareVersionLongForm", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x0088, 0x0043, 0x0088, + EVR_UI, "PUREAcquisitionCalibrationSeriesUID", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x0089, 0x0043, 0x0089, + EVR_LO, "GoverningBodydBdtAndSARDefinition", 3, 3, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x008a, 0x0043, 0x008a, + EVR_CS, "PrivateInPlanePhaseEncodingDirection", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x008b, 0x0043, 0x008b, + EVR_OB, "FMRIBinaryDataBlock", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x008c, 0x0043, 0x008c, + EVR_DS, "VoxelLocation", 6, 6, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x008d, 0x0043, 0x008d, + EVR_DS, "SATBandLocations", 7, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x008e, 0x0043, 0x008e, + EVR_DS, "SpectroPrescanValues", 3, 3, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x008f, 0x0043, 0x008f, + EVR_DS, "SpectroParameters", 3, 3, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x0090, 0x0043, 0x0090, + EVR_LO, "SARDefinition", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x0091, 0x0043, 0x0091, + EVR_DS, "SARValue", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x0092, 0x0043, 0x0092, + EVR_LO, "ImageErrorText", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x0093, 0x0043, 0x0093, + EVR_DS, "SpectroQuantitationValues", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x0094, 0x0043, 0x0094, + EVR_DS, "SpectroRatioValues", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x0095, 0x0043, 0x0095, + EVR_LO, "PrescanReuseString", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x0096, 0x0043, 0x0096, + EVR_CS, "ContentQualification", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x0097, 0x0043, 0x0097, + EVR_LO, "ImageFilteringParameters", 9, 9, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x0098, 0x0043, 0x0098, + EVR_UI, "ASSETAcquisitionCalibrationSeriesUID", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x0099, 0x0043, 0x0099, + EVR_LO, "ExtendedOptions", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x009a, 0x0043, 0x009a, + EVR_IS, "RxStackIdentification", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x009b, 0x0043, 0x009b, + EVR_DS, "NPWFactor", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x009c, 0x0043, 0x009c, + EVR_OB, "ResearchTag1", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x009d, 0x0043, 0x009d, + EVR_OB, "ResearchTag2", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x009e, 0x0043, 0x009e, + EVR_OB, "ResearchTag3", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } + , { 0x0043, 0x009f, 0x0043, 0x009f, + EVR_OB, "ResearchTag4", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_PARM_01" } +#endif + , { 0x0044, 0x0001, 0x0044, 0x0001, + EVR_ST, "ProductPackageIdentifier", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0044, 0x0002, 0x0044, 0x0002, + EVR_CS, "SubstanceAdministrationApproval", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0044, 0x0003, 0x0044, 0x0003, + EVR_LT, "ApprovalStatusFurtherDescription", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0044, 0x0004, 0x0044, 0x0004, + EVR_DT, "ApprovalStatusDateTime", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0044, 0x0007, 0x0044, 0x0007, + EVR_SQ, "ProductTypeCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0044, 0x0008, 0x0044, 0x0008, + EVR_LO, "ProductName", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0044, 0x0009, 0x0044, 0x0009, + EVR_LT, "ProductDescription", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0044, 0x000a, 0x0044, 0x000a, + EVR_LO, "ProductLotIdentifier", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0044, 0x000b, 0x0044, 0x000b, + EVR_DT, "ProductExpirationDateTime", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0044, 0x0010, 0x0044, 0x0010, + EVR_DT, "SubstanceAdministrationDateTime", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0044, 0x0011, 0x0044, 0x0011, + EVR_LO, "SubstanceAdministrationNotes", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0044, 0x0012, 0x0044, 0x0012, + EVR_LO, "SubstanceAdministrationDeviceID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0044, 0x0013, 0x0044, 0x0013, + EVR_SQ, "ProductParameterSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0044, 0x0019, 0x0044, 0x0019, + EVR_SQ, "SubstanceAdministrationParameterSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } +#ifdef ENABLE_PRIVATE_TAGS + , { 0x0045, 0x0004, 0x0045, 0x0004, + EVR_CS, "AES", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_SENO_02" } + , { 0x0045, 0x0006, 0x0045, 0x0006, + EVR_DS, "Angulation", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_SENO_02" } + , { 0x0045, 0x0009, 0x0045, 0x0009, + EVR_DS, "RealMagnificationFactor", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_SENO_02" } + , { 0x0045, 0x000b, 0x0045, 0x000b, + EVR_CS, "SenographType", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_SENO_02" } + , { 0x0045, 0x000c, 0x0045, 0x000c, + EVR_DS, "IntegrationTime", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_SENO_02" } + , { 0x0045, 0x000d, 0x0045, 0x000d, + EVR_DS, "ROIOriginXY", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_SENO_02" } + , { 0x0045, 0x0011, 0x0045, 0x0011, + EVR_DS, "ReceptorSizeCmXY", 2, 2, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_SENO_02" } + , { 0x0045, 0x0012, 0x0045, 0x0012, + EVR_IS, "ReceptorSizePixelsXY", 2, 2, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_SENO_02" } + , { 0x0045, 0x0013, 0x0045, 0x0013, + EVR_ST, "Screen", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_SENO_02" } + , { 0x0045, 0x0014, 0x0045, 0x0014, + EVR_DS, "PixelPitchMicrons", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_SENO_02" } + , { 0x0045, 0x0015, 0x0045, 0x0015, + EVR_IS, "PixelDepthBits", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_SENO_02" } + , { 0x0045, 0x0016, 0x0045, 0x0016, + EVR_IS, "BinningFactorXY", 2, 2, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_SENO_02" } + , { 0x0045, 0x001b, 0x0045, 0x001b, + EVR_CS, "ClinicalView", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_SENO_02" } + , { 0x0045, 0x001d, 0x0045, 0x001d, + EVR_DS, "MeanOfRawGrayLevels", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_SENO_02" } + , { 0x0045, 0x001e, 0x0045, 0x001e, + EVR_DS, "MeanOfOffsetGrayLevels", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_SENO_02" } + , { 0x0045, 0x001f, 0x0045, 0x001f, + EVR_DS, "MeanOfCorrectedGrayLevels", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_SENO_02" } + , { 0x0045, 0x0020, 0x0045, 0x0020, + EVR_DS, "MeanOfRegionGrayLevels", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_SENO_02" } + , { 0x0045, 0x0021, 0x0045, 0x0021, + EVR_DS, "MeanOfLogRegionGrayLevels", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_SENO_02" } + , { 0x0045, 0x0022, 0x0045, 0x0022, + EVR_DS, "StandardDeviationOfRawGrayLevels", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_SENO_02" } + , { 0x0045, 0x0023, 0x0045, 0x0023, + EVR_DS, "StandardDeviationOfCorrectedGrayLevels", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_SENO_02" } + , { 0x0045, 0x0024, 0x0045, 0x0024, + EVR_DS, "StandardDeviationOfRegionGrayLevels", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_SENO_02" } + , { 0x0045, 0x0025, 0x0045, 0x0025, + EVR_DS, "StandardDeviationOfLogRegionGrayLevels", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_SENO_02" } + , { 0x0045, 0x0026, 0x0045, 0x0026, + EVR_OB, "MAOBuffer", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_SENO_02" } + , { 0x0045, 0x0027, 0x0045, 0x0027, + EVR_IS, "SetNumber", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_SENO_02" } + , { 0x0045, 0x0028, 0x0045, 0x0028, + EVR_CS, "WindowingType", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_SENO_02" } + , { 0x0045, 0x0029, 0x0045, 0x0029, + EVR_DS, "WindowingParameters", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_SENO_02" } + , { 0x0045, 0x002a, 0x0045, 0x002a, + EVR_IS, "CrosshairCursorXCoordinates", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_SENO_02" } + , { 0x0045, 0x002b, 0x0045, 0x002b, + EVR_IS, "CrosshairCursorYCoordinates", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_SENO_02" } + , { 0x0045, 0x0039, 0x0045, 0x0039, + EVR_US, "VignetteRows", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_SENO_02" } + , { 0x0045, 0x003a, 0x0045, 0x003a, + EVR_US, "VignetteColumns", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_SENO_02" } + , { 0x0045, 0x003b, 0x0045, 0x003b, + EVR_US, "VignetteBitsAllocated", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_SENO_02" } + , { 0x0045, 0x003c, 0x0045, 0x003c, + EVR_US, "VignetteBitsStored", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_SENO_02" } + , { 0x0045, 0x003d, 0x0045, 0x003d, + EVR_US, "VignetteHighBit", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_SENO_02" } + , { 0x0045, 0x003e, 0x0045, 0x003e, + EVR_US, "VignettePixelRepresentation", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_SENO_02" } + , { 0x0045, 0x003f, 0x0045, 0x003f, + EVR_OB, "VignettePixelData", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_SENO_02" } +#endif + , { 0x0046, 0x0012, 0x0046, 0x0012, + EVR_LO, "LensDescription", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0046, 0x0014, 0x0046, 0x0014, + EVR_SQ, "RightLensSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0046, 0x0015, 0x0046, 0x0015, + EVR_SQ, "LeftLensSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0046, 0x0016, 0x0046, 0x0016, + EVR_SQ, "UnspecifiedLateralityLensSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0046, 0x0018, 0x0046, 0x0018, + EVR_SQ, "CylinderSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0046, 0x0028, 0x0046, 0x0028, + EVR_SQ, "PrismSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0046, 0x0030, 0x0046, 0x0030, + EVR_FD, "HorizontalPrismPower", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0046, 0x0032, 0x0046, 0x0032, + EVR_CS, "HorizontalPrismBase", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0046, 0x0034, 0x0046, 0x0034, + EVR_FD, "VerticalPrismPower", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0046, 0x0036, 0x0046, 0x0036, + EVR_CS, "VerticalPrismBase", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0046, 0x0038, 0x0046, 0x0038, + EVR_CS, "LensSegmentType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0046, 0x0040, 0x0046, 0x0040, + EVR_FD, "OpticalTransmittance", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0046, 0x0042, 0x0046, 0x0042, + EVR_FD, "ChannelWidth", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0046, 0x0044, 0x0046, 0x0044, + EVR_FD, "PupilSize", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0046, 0x0046, 0x0046, 0x0046, + EVR_FD, "CornealSize", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0046, 0x0050, 0x0046, 0x0050, + EVR_SQ, "AutorefractionRightEyeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0046, 0x0052, 0x0046, 0x0052, + EVR_SQ, "AutorefractionLeftEyeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0046, 0x0060, 0x0046, 0x0060, + EVR_FD, "DistancePupillaryDistance", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0046, 0x0062, 0x0046, 0x0062, + EVR_FD, "NearPupillaryDistance", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0046, 0x0063, 0x0046, 0x0063, + EVR_FD, "IntermediatePupillaryDistance", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0046, 0x0064, 0x0046, 0x0064, + EVR_FD, "OtherPupillaryDistance", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0046, 0x0070, 0x0046, 0x0070, + EVR_SQ, "KeratometryRightEyeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0046, 0x0071, 0x0046, 0x0071, + EVR_SQ, "KeratometryLeftEyeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0046, 0x0074, 0x0046, 0x0074, + EVR_SQ, "SteepKeratometricAxisSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0046, 0x0075, 0x0046, 0x0075, + EVR_FD, "RadiusOfCurvature", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0046, 0x0076, 0x0046, 0x0076, + EVR_FD, "KeratometricPower", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0046, 0x0077, 0x0046, 0x0077, + EVR_FD, "KeratometricAxis", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0046, 0x0080, 0x0046, 0x0080, + EVR_SQ, "FlatKeratometricAxisSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0046, 0x0092, 0x0046, 0x0092, + EVR_CS, "BackgroundColor", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0046, 0x0094, 0x0046, 0x0094, + EVR_CS, "Optotype", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0046, 0x0095, 0x0046, 0x0095, + EVR_CS, "OptotypePresentation", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0046, 0x0097, 0x0046, 0x0097, + EVR_SQ, "SubjectiveRefractionRightEyeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0046, 0x0098, 0x0046, 0x0098, + EVR_SQ, "SubjectiveRefractionLeftEyeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0046, 0x0100, 0x0046, 0x0100, + EVR_SQ, "AddNearSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0046, 0x0101, 0x0046, 0x0101, + EVR_SQ, "AddIntermediateSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0046, 0x0102, 0x0046, 0x0102, + EVR_SQ, "AddOtherSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0046, 0x0104, 0x0046, 0x0104, + EVR_FD, "AddPower", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0046, 0x0106, 0x0046, 0x0106, + EVR_FD, "ViewingDistance", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0046, 0x0121, 0x0046, 0x0121, + EVR_SQ, "VisualAcuityTypeCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0046, 0x0122, 0x0046, 0x0122, + EVR_SQ, "VisualAcuityRightEyeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0046, 0x0123, 0x0046, 0x0123, + EVR_SQ, "VisualAcuityLeftEyeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0046, 0x0124, 0x0046, 0x0124, + EVR_SQ, "VisualAcuityBothEyesOpenSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0046, 0x0125, 0x0046, 0x0125, + EVR_CS, "ViewingDistanceType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0046, 0x0135, 0x0046, 0x0135, + EVR_SS, "VisualAcuityModifiers", 2, 2, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0046, 0x0137, 0x0046, 0x0137, + EVR_FD, "DecimalVisualAcuity", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0046, 0x0139, 0x0046, 0x0139, + EVR_LO, "OptotypeDetailedDefinition", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0046, 0x0145, 0x0046, 0x0145, + EVR_SQ, "ReferencedRefractiveMeasurementsSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0046, 0x0146, 0x0046, 0x0146, + EVR_FD, "SpherePower", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0046, 0x0147, 0x0046, 0x0147, + EVR_FD, "CylinderPower", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0046, 0x0201, 0x0046, 0x0201, + EVR_CS, "CornealTopographySurface", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0046, 0x0202, 0x0046, 0x0202, + EVR_FL, "CornealVertexLocation", 2, 2, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0046, 0x0203, 0x0046, 0x0203, + EVR_FL, "PupilCentroidXCoordinate", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0046, 0x0204, 0x0046, 0x0204, + EVR_FL, "PupilCentroidYCoordinate", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0046, 0x0205, 0x0046, 0x0205, + EVR_FL, "EquivalentPupilRadius", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0046, 0x0207, 0x0046, 0x0207, + EVR_SQ, "CornealTopographyMapTypeCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0046, 0x0208, 0x0046, 0x0208, + EVR_IS, "VerticesOfTheOutlineOfPupil", 2, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0046, 0x0210, 0x0046, 0x0210, + EVR_SQ, "CornealTopographyMappingNormalsSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0046, 0x0211, 0x0046, 0x0211, + EVR_SQ, "MaximumCornealCurvatureSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0046, 0x0212, 0x0046, 0x0212, + EVR_FL, "MaximumCornealCurvature", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0046, 0x0213, 0x0046, 0x0213, + EVR_FL, "MaximumCornealCurvatureLocation", 2, 2, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0046, 0x0215, 0x0046, 0x0215, + EVR_SQ, "MinimumKeratometricSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0046, 0x0218, 0x0046, 0x0218, + EVR_SQ, "SimulatedKeratometricCylinderSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0046, 0x0220, 0x0046, 0x0220, + EVR_FL, "AverageCornealPower", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0046, 0x0224, 0x0046, 0x0224, + EVR_FL, "CornealISValue", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0046, 0x0227, 0x0046, 0x0227, + EVR_FL, "AnalyzedArea", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0046, 0x0230, 0x0046, 0x0230, + EVR_FL, "SurfaceRegularityIndex", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0046, 0x0232, 0x0046, 0x0232, + EVR_FL, "SurfaceAsymmetryIndex", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0046, 0x0234, 0x0046, 0x0234, + EVR_FL, "CornealEccentricityIndex", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0046, 0x0236, 0x0046, 0x0236, + EVR_FL, "KeratoconusPredictionIndex", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0046, 0x0238, 0x0046, 0x0238, + EVR_FL, "DecimalPotentialVisualAcuity", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0046, 0x0242, 0x0046, 0x0242, + EVR_CS, "CornealTopographyMapQualityEvaluation", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0046, 0x0244, 0x0046, 0x0244, + EVR_SQ, "SourceImageCornealProcessedDataSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0046, 0x0247, 0x0046, 0x0247, + EVR_FL, "CornealPointLocation", 3, 3, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0046, 0x0248, 0x0046, 0x0248, + EVR_CS, "CornealPointEstimated", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0046, 0x0249, 0x0046, 0x0249, + EVR_FL, "AxialPower", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0046, 0x0250, 0x0046, 0x0250, + EVR_FL, "TangentialPower", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0046, 0x0251, 0x0046, 0x0251, + EVR_FL, "RefractivePower", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0046, 0x0252, 0x0046, 0x0252, + EVR_FL, "RelativeElevation", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0046, 0x0253, 0x0046, 0x0253, + EVR_FL, "CornealWavefront", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } +#ifdef ENABLE_PRIVATE_TAGS + , { 0x0047, 0x0001, 0x0047, 0x0001, + EVR_SQ, "ReconstructionParametersSequence", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ADWSoft_3D1" } + , { 0x0047, 0x0050, 0x0047, 0x0050, + EVR_UL, "VolumeVoxelCount", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ADWSoft_3D1" } + , { 0x0047, 0x0051, 0x0047, 0x0051, + EVR_UL, "VolumeSegmentCount", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ADWSoft_3D1" } + , { 0x0047, 0x0053, 0x0047, 0x0053, + EVR_US, "VolumeSliceSize", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ADWSoft_3D1" } + , { 0x0047, 0x0054, 0x0047, 0x0054, + EVR_US, "VolumeSliceCount", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ADWSoft_3D1" } + , { 0x0047, 0x0055, 0x0047, 0x0055, + EVR_SL, "VolumeThresholdValue", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ADWSoft_3D1" } + , { 0x0047, 0x0057, 0x0047, 0x0057, + EVR_DS, "VolumeVoxelRatio", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ADWSoft_3D1" } + , { 0x0047, 0x0058, 0x0047, 0x0058, + EVR_DS, "VolumeVoxelSize", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ADWSoft_3D1" } + , { 0x0047, 0x0059, 0x0047, 0x0059, + EVR_US, "VolumeZPositionSize", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ADWSoft_3D1" } + , { 0x0047, 0x0060, 0x0047, 0x0060, + EVR_DS, "VolumeBaseLine", 9, 9, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ADWSoft_3D1" } + , { 0x0047, 0x0061, 0x0047, 0x0061, + EVR_DS, "VolumeCenterPoint", 3, 3, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ADWSoft_3D1" } + , { 0x0047, 0x0063, 0x0047, 0x0063, + EVR_SL, "VolumeSkewBase", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ADWSoft_3D1" } + , { 0x0047, 0x0064, 0x0047, 0x0064, + EVR_DS, "VolumeRegistrationTransformRotationMatrix", 9, 9, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ADWSoft_3D1" } + , { 0x0047, 0x0065, 0x0047, 0x0065, + EVR_DS, "VolumeRegistrationTransformTranslationVector", 3, 3, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ADWSoft_3D1" } + , { 0x0047, 0x0070, 0x0047, 0x0070, + EVR_DS, "KVPList", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ADWSoft_3D1" } + , { 0x0047, 0x0071, 0x0047, 0x0071, + EVR_IS, "XRayTubeCurrentList", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ADWSoft_3D1" } + , { 0x0047, 0x0072, 0x0047, 0x0072, + EVR_IS, "ExposureList", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ADWSoft_3D1" } + , { 0x0047, 0x0080, 0x0047, 0x0080, + EVR_LO, "AcquisitionDLXIdentifier", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ADWSoft_3D1" } + , { 0x0047, 0x0085, 0x0047, 0x0085, + EVR_SQ, "AcquisitionDLX2DSeriesSequence", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ADWSoft_3D1" } + , { 0x0047, 0x0089, 0x0047, 0x0089, + EVR_DS, "ContrastAgentVolumeList", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ADWSoft_3D1" } + , { 0x0047, 0x008a, 0x0047, 0x008a, + EVR_US, "NumberOfInjections", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ADWSoft_3D1" } + , { 0x0047, 0x008b, 0x0047, 0x008b, + EVR_US, "FrameCount", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ADWSoft_3D1" } + , { 0x0047, 0x0091, 0x0047, 0x0091, + EVR_LO, "XA3DReconstructionAlgorithmName", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ADWSoft_3D1" } + , { 0x0047, 0x0092, 0x0047, 0x0092, + EVR_CS, "XA3DReconstructionAlgorithmVersion", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ADWSoft_3D1" } + , { 0x0047, 0x0093, 0x0047, 0x0093, + EVR_DA, "DLXCalibrationDate", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ADWSoft_3D1" } + , { 0x0047, 0x0094, 0x0047, 0x0094, + EVR_TM, "DLXCalibrationTime", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ADWSoft_3D1" } + , { 0x0047, 0x0095, 0x0047, 0x0095, + EVR_CS, "DLXCalibrationStatus", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ADWSoft_3D1" } + , { 0x0047, 0x0096, 0x0047, 0x0096, + EVR_IS, "UsedFrames", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ADWSoft_3D1" } + , { 0x0047, 0x0098, 0x0047, 0x0098, + EVR_US, "TransformCount", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ADWSoft_3D1" } + , { 0x0047, 0x0099, 0x0047, 0x0099, + EVR_SQ, "TransformSequence", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ADWSoft_3D1" } + , { 0x0047, 0x009a, 0x0047, 0x009a, + EVR_DS, "TransformRotationMatrix", 9, 9, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ADWSoft_3D1" } + , { 0x0047, 0x009b, 0x0047, 0x009b, + EVR_DS, "TransformTranslationVector", 3, 3, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ADWSoft_3D1" } + , { 0x0047, 0x009c, 0x0047, 0x009c, + EVR_LO, "TransformLabel", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ADWSoft_3D1" } + , { 0x0047, 0x00b0, 0x0047, 0x00b0, + EVR_SQ, "WireframeList", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ADWSoft_3D1" } + , { 0x0047, 0x00b1, 0x0047, 0x00b1, + EVR_US, "WireframeCount", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ADWSoft_3D1" } + , { 0x0047, 0x00b2, 0x0047, 0x00b2, + EVR_US, "LocationSystem", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ADWSoft_3D1" } + , { 0x0047, 0x00b5, 0x0047, 0x00b5, + EVR_LO, "WireframeName", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ADWSoft_3D1" } + , { 0x0047, 0x00b6, 0x0047, 0x00b6, + EVR_LO, "WireframeGroupName", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ADWSoft_3D1" } + , { 0x0047, 0x00b7, 0x0047, 0x00b7, + EVR_LO, "WireframeColor", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ADWSoft_3D1" } + , { 0x0047, 0x00b8, 0x0047, 0x00b8, + EVR_SL, "WireframeAttributes", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ADWSoft_3D1" } + , { 0x0047, 0x00b9, 0x0047, 0x00b9, + EVR_SL, "WireframePointCount", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ADWSoft_3D1" } + , { 0x0047, 0x00ba, 0x0047, 0x00ba, + EVR_SL, "WireframeTimestamp", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ADWSoft_3D1" } + , { 0x0047, 0x00bb, 0x0047, 0x00bb, + EVR_SQ, "WireframePointList", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ADWSoft_3D1" } + , { 0x0047, 0x00bc, 0x0047, 0x00bc, + EVR_DS, "WireframePointsCoordinates", 3, 3, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ADWSoft_3D1" } + , { 0x0047, 0x00c0, 0x0047, 0x00c0, + EVR_DS, "VolumeUpperLeftHighCornerRAS", 3, 3, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ADWSoft_3D1" } + , { 0x0047, 0x00c1, 0x0047, 0x00c1, + EVR_DS, "VolumeSliceToRASRotationMatrix", 9, 9, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ADWSoft_3D1" } + , { 0x0047, 0x00c2, 0x0047, 0x00c2, + EVR_DS, "VolumeUpperLeftHighCornerTLOC", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ADWSoft_3D1" } + , { 0x0047, 0x00d1, 0x0047, 0x00d1, + EVR_OB, "VolumeSegmentList", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ADWSoft_3D1" } + , { 0x0047, 0x00d2, 0x0047, 0x00d2, + EVR_OB, "VolumeGradientList", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ADWSoft_3D1" } + , { 0x0047, 0x00d3, 0x0047, 0x00d3, + EVR_OB, "VolumeDensityList", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ADWSoft_3D1" } + , { 0x0047, 0x00d4, 0x0047, 0x00d4, + EVR_OB, "VolumeZPositionList", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ADWSoft_3D1" } + , { 0x0047, 0x00d5, 0x0047, 0x00d5, + EVR_OB, "VolumeOriginalIndexList", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "GEMS_ADWSoft_3D1" } +#endif + , { 0x0048, 0x0001, 0x0048, 0x0001, + EVR_FL, "ImagedVolumeWidth", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0048, 0x0002, 0x0048, 0x0002, + EVR_FL, "ImagedVolumeHeight", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0048, 0x0003, 0x0048, 0x0003, + EVR_FL, "ImagedVolumeDepth", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0048, 0x0006, 0x0048, 0x0006, + EVR_UL, "TotalPixelMatrixColumns", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0048, 0x0007, 0x0048, 0x0007, + EVR_UL, "TotalPixelMatrixRows", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0048, 0x0008, 0x0048, 0x0008, + EVR_SQ, "TotalPixelMatrixOriginSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0048, 0x0010, 0x0048, 0x0010, + EVR_CS, "SpecimenLabelInImage", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0048, 0x0011, 0x0048, 0x0011, + EVR_CS, "FocusMethod", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0048, 0x0012, 0x0048, 0x0012, + EVR_CS, "ExtendedDepthOfField", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0048, 0x0013, 0x0048, 0x0013, + EVR_US, "NumberOfFocalPlanes", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0048, 0x0014, 0x0048, 0x0014, + EVR_FL, "DistanceBetweenFocalPlanes", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0048, 0x0015, 0x0048, 0x0015, + EVR_US, "RecommendedAbsentPixelCIELabValue", 3, 3, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0048, 0x0100, 0x0048, 0x0100, + EVR_SQ, "IlluminatorTypeCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0048, 0x0102, 0x0048, 0x0102, + EVR_DS, "ImageOrientationSlide", 6, 6, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0048, 0x0105, 0x0048, 0x0105, + EVR_SQ, "OpticalPathSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0048, 0x0106, 0x0048, 0x0106, + EVR_SH, "OpticalPathIdentifier", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0048, 0x0107, 0x0048, 0x0107, + EVR_ST, "OpticalPathDescription", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0048, 0x0108, 0x0048, 0x0108, + EVR_SQ, "IlluminationColorCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0048, 0x0110, 0x0048, 0x0110, + EVR_SQ, "SpecimenReferenceSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0048, 0x0111, 0x0048, 0x0111, + EVR_DS, "CondenserLensPower", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0048, 0x0112, 0x0048, 0x0112, + EVR_DS, "ObjectiveLensPower", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0048, 0x0113, 0x0048, 0x0113, + EVR_DS, "ObjectiveLensNumericalAperture", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0048, 0x0120, 0x0048, 0x0120, + EVR_SQ, "PaletteColorLookupTableSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0048, 0x0200, 0x0048, 0x0200, + EVR_SQ, "ReferencedImageNavigationSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0048, 0x0201, 0x0048, 0x0201, + EVR_US, "TopLeftHandCornerOfLocalizerArea", 2, 2, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0048, 0x0202, 0x0048, 0x0202, + EVR_US, "BottomRightHandCornerOfLocalizerArea", 2, 2, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0048, 0x0207, 0x0048, 0x0207, + EVR_SQ, "OpticalPathIdentificationSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0048, 0x021a, 0x0048, 0x021a, + EVR_SQ, "PlanePositionSlideSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0048, 0x021e, 0x0048, 0x021e, + EVR_SL, "ColumnPositionInTotalImagePixelMatrix", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0048, 0x021f, 0x0048, 0x021f, + EVR_SL, "RowPositionInTotalImagePixelMatrix", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0048, 0x0301, 0x0048, 0x0301, + EVR_CS, "PixelOriginInterpretation", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0050, 0x0004, 0x0050, 0x0004, + EVR_CS, "CalibrationImage", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0050, 0x0010, 0x0050, 0x0010, + EVR_SQ, "DeviceSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0050, 0x0012, 0x0050, 0x0012, + EVR_SQ, "ContainerComponentTypeCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0050, 0x0013, 0x0050, 0x0013, + EVR_FD, "ContainerComponentThickness", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0050, 0x0014, 0x0050, 0x0014, + EVR_DS, "DeviceLength", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0050, 0x0015, 0x0050, 0x0015, + EVR_FD, "ContainerComponentWidth", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0050, 0x0016, 0x0050, 0x0016, + EVR_DS, "DeviceDiameter", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0050, 0x0017, 0x0050, 0x0017, + EVR_CS, "DeviceDiameterUnits", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0050, 0x0018, 0x0050, 0x0018, + EVR_DS, "DeviceVolume", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0050, 0x0019, 0x0050, 0x0019, + EVR_DS, "InterMarkerDistance", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0050, 0x001a, 0x0050, 0x001a, + EVR_CS, "ContainerComponentMaterial", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0050, 0x001b, 0x0050, 0x001b, + EVR_LO, "ContainerComponentID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0050, 0x001c, 0x0050, 0x001c, + EVR_FD, "ContainerComponentLength", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0050, 0x001d, 0x0050, 0x001d, + EVR_FD, "ContainerComponentDiameter", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0050, 0x001e, 0x0050, 0x001e, + EVR_LO, "ContainerComponentDescription", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0050, 0x0020, 0x0050, 0x0020, + EVR_LO, "DeviceDescription", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } +#ifdef ENABLE_PRIVATE_TAGS + , { 0x0051, 0x0010, 0x0051, 0x0010, + EVR_LT, "ImageText", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CM VA0 CMS" } +#endif + , { 0x0052, 0x0001, 0x0052, 0x0001, + EVR_FL, "ContrastBolusIngredientPercentByVolume", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0052, 0x0002, 0x0052, 0x0002, + EVR_FD, "OCTFocalDistance", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0052, 0x0003, 0x0052, 0x0003, + EVR_FD, "BeamSpotSize", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0052, 0x0004, 0x0052, 0x0004, + EVR_FD, "EffectiveRefractiveIndex", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0052, 0x0006, 0x0052, 0x0006, + EVR_CS, "OCTAcquisitionDomain", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0052, 0x0007, 0x0052, 0x0007, + EVR_FD, "OCTOpticalCenterWavelength", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0052, 0x0008, 0x0052, 0x0008, + EVR_FD, "AxialResolution", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0052, 0x0009, 0x0052, 0x0009, + EVR_FD, "RangingDepth", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0052, 0x0011, 0x0052, 0x0011, + EVR_FD, "ALineRate", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0052, 0x0012, 0x0052, 0x0012, + EVR_US, "ALinesPerFrame", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0052, 0x0013, 0x0052, 0x0013, + EVR_FD, "CatheterRotationalRate", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0052, 0x0014, 0x0052, 0x0014, + EVR_FD, "ALinePixelSpacing", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0052, 0x0016, 0x0052, 0x0016, + EVR_SQ, "ModeOfPercutaneousAccessSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0052, 0x0025, 0x0052, 0x0025, + EVR_SQ, "IntravascularOCTFrameTypeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0052, 0x0026, 0x0052, 0x0026, + EVR_CS, "OCTZOffsetApplied", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0052, 0x0027, 0x0052, 0x0027, + EVR_SQ, "IntravascularFrameContentSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0052, 0x0028, 0x0052, 0x0028, + EVR_FD, "IntravascularLongitudinalDistance", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0052, 0x0029, 0x0052, 0x0029, + EVR_SQ, "IntravascularOCTFrameContentSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0052, 0x0030, 0x0052, 0x0030, + EVR_SS, "OCTZOffsetCorrection", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0052, 0x0031, 0x0052, 0x0031, + EVR_CS, "CatheterDirectionOfRotation", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0052, 0x0033, 0x0052, 0x0033, + EVR_FD, "SeamLineLocation", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0052, 0x0034, 0x0052, 0x0034, + EVR_FD, "FirstALineLocation", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0052, 0x0036, 0x0052, 0x0036, + EVR_US, "SeamLineIndex", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0052, 0x0038, 0x0052, 0x0038, + EVR_US, "NumberOfPaddedALines", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0052, 0x0039, 0x0052, 0x0039, + EVR_CS, "InterpolationType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0052, 0x003a, 0x0052, 0x003a, + EVR_CS, "RefractiveIndexApplied", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0054, 0x0010, 0x0054, 0x0010, + EVR_US, "EnergyWindowVector", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0054, 0x0011, 0x0054, 0x0011, + EVR_US, "NumberOfEnergyWindows", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0054, 0x0012, 0x0054, 0x0012, + EVR_SQ, "EnergyWindowInformationSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0054, 0x0013, 0x0054, 0x0013, + EVR_SQ, "EnergyWindowRangeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0054, 0x0014, 0x0054, 0x0014, + EVR_DS, "EnergyWindowLowerLimit", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0054, 0x0015, 0x0054, 0x0015, + EVR_DS, "EnergyWindowUpperLimit", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0054, 0x0016, 0x0054, 0x0016, + EVR_SQ, "RadiopharmaceuticalInformationSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0054, 0x0017, 0x0054, 0x0017, + EVR_IS, "ResidualSyringeCounts", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0054, 0x0018, 0x0054, 0x0018, + EVR_SH, "EnergyWindowName", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0054, 0x0020, 0x0054, 0x0020, + EVR_US, "DetectorVector", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0054, 0x0021, 0x0054, 0x0021, + EVR_US, "NumberOfDetectors", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0054, 0x0022, 0x0054, 0x0022, + EVR_SQ, "DetectorInformationSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0054, 0x0030, 0x0054, 0x0030, + EVR_US, "PhaseVector", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0054, 0x0031, 0x0054, 0x0031, + EVR_US, "NumberOfPhases", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0054, 0x0032, 0x0054, 0x0032, + EVR_SQ, "PhaseInformationSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0054, 0x0033, 0x0054, 0x0033, + EVR_US, "NumberOfFramesInPhase", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0054, 0x0036, 0x0054, 0x0036, + EVR_IS, "PhaseDelay", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0054, 0x0038, 0x0054, 0x0038, + EVR_IS, "PauseBetweenFrames", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0054, 0x0039, 0x0054, 0x0039, + EVR_CS, "PhaseDescription", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0054, 0x0050, 0x0054, 0x0050, + EVR_US, "RotationVector", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0054, 0x0051, 0x0054, 0x0051, + EVR_US, "NumberOfRotations", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0054, 0x0052, 0x0054, 0x0052, + EVR_SQ, "RotationInformationSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0054, 0x0053, 0x0054, 0x0053, + EVR_US, "NumberOfFramesInRotation", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0054, 0x0060, 0x0054, 0x0060, + EVR_US, "RRIntervalVector", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0054, 0x0061, 0x0054, 0x0061, + EVR_US, "NumberOfRRIntervals", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0054, 0x0062, 0x0054, 0x0062, + EVR_SQ, "GatedInformationSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0054, 0x0063, 0x0054, 0x0063, + EVR_SQ, "DataInformationSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0054, 0x0070, 0x0054, 0x0070, + EVR_US, "TimeSlotVector", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0054, 0x0071, 0x0054, 0x0071, + EVR_US, "NumberOfTimeSlots", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0054, 0x0072, 0x0054, 0x0072, + EVR_SQ, "TimeSlotInformationSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0054, 0x0073, 0x0054, 0x0073, + EVR_DS, "TimeSlotTime", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0054, 0x0080, 0x0054, 0x0080, + EVR_US, "SliceVector", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0054, 0x0081, 0x0054, 0x0081, + EVR_US, "NumberOfSlices", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0054, 0x0090, 0x0054, 0x0090, + EVR_US, "AngularViewVector", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0054, 0x0100, 0x0054, 0x0100, + EVR_US, "TimeSliceVector", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0054, 0x0101, 0x0054, 0x0101, + EVR_US, "NumberOfTimeSlices", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0054, 0x0200, 0x0054, 0x0200, + EVR_DS, "StartAngle", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0054, 0x0202, 0x0054, 0x0202, + EVR_CS, "TypeOfDetectorMotion", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0054, 0x0210, 0x0054, 0x0210, + EVR_IS, "TriggerVector", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0054, 0x0211, 0x0054, 0x0211, + EVR_US, "NumberOfTriggersInPhase", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0054, 0x0220, 0x0054, 0x0220, + EVR_SQ, "ViewCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0054, 0x0222, 0x0054, 0x0222, + EVR_SQ, "ViewModifierCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0054, 0x0300, 0x0054, 0x0300, + EVR_SQ, "RadionuclideCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0054, 0x0302, 0x0054, 0x0302, + EVR_SQ, "AdministrationRouteCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0054, 0x0304, 0x0054, 0x0304, + EVR_SQ, "RadiopharmaceuticalCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0054, 0x0306, 0x0054, 0x0306, + EVR_SQ, "CalibrationDataSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0054, 0x0308, 0x0054, 0x0308, + EVR_US, "EnergyWindowNumber", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0054, 0x0400, 0x0054, 0x0400, + EVR_SH, "ImageID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0054, 0x0410, 0x0054, 0x0410, + EVR_SQ, "PatientOrientationCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0054, 0x0412, 0x0054, 0x0412, + EVR_SQ, "PatientOrientationModifierCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0054, 0x0414, 0x0054, 0x0414, + EVR_SQ, "PatientGantryRelationshipCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0054, 0x0500, 0x0054, 0x0500, + EVR_CS, "SliceProgressionDirection", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0054, 0x0501, 0x0054, 0x0501, + EVR_CS, "ScanProgressionDirection", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0054, 0x1000, 0x0054, 0x1000, + EVR_CS, "SeriesType", 2, 2, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0054, 0x1001, 0x0054, 0x1001, + EVR_CS, "Units", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0054, 0x1002, 0x0054, 0x1002, + EVR_CS, "CountsSource", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0054, 0x1004, 0x0054, 0x1004, + EVR_CS, "ReprojectionMethod", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0054, 0x1006, 0x0054, 0x1006, + EVR_CS, "SUVType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0054, 0x1100, 0x0054, 0x1100, + EVR_CS, "RandomsCorrectionMethod", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0054, 0x1101, 0x0054, 0x1101, + EVR_LO, "AttenuationCorrectionMethod", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0054, 0x1102, 0x0054, 0x1102, + EVR_CS, "DecayCorrection", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0054, 0x1103, 0x0054, 0x1103, + EVR_LO, "ReconstructionMethod", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0054, 0x1104, 0x0054, 0x1104, + EVR_LO, "DetectorLinesOfResponseUsed", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0054, 0x1105, 0x0054, 0x1105, + EVR_LO, "ScatterCorrectionMethod", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0054, 0x1200, 0x0054, 0x1200, + EVR_DS, "AxialAcceptance", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0054, 0x1201, 0x0054, 0x1201, + EVR_IS, "AxialMash", 2, 2, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0054, 0x1202, 0x0054, 0x1202, + EVR_IS, "TransverseMash", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0054, 0x1203, 0x0054, 0x1203, + EVR_DS, "DetectorElementSize", 2, 2, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0054, 0x1210, 0x0054, 0x1210, + EVR_DS, "CoincidenceWindowWidth", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0054, 0x1220, 0x0054, 0x1220, + EVR_CS, "SecondaryCountsType", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0054, 0x1300, 0x0054, 0x1300, + EVR_DS, "FrameReferenceTime", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0054, 0x1310, 0x0054, 0x1310, + EVR_IS, "PrimaryPromptsCountsAccumulated", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0054, 0x1311, 0x0054, 0x1311, + EVR_IS, "SecondaryCountsAccumulated", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0054, 0x1320, 0x0054, 0x1320, + EVR_DS, "SliceSensitivityFactor", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0054, 0x1321, 0x0054, 0x1321, + EVR_DS, "DecayFactor", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0054, 0x1322, 0x0054, 0x1322, + EVR_DS, "DoseCalibrationFactor", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0054, 0x1323, 0x0054, 0x1323, + EVR_DS, "ScatterFractionFactor", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0054, 0x1324, 0x0054, 0x1324, + EVR_DS, "DeadTimeFactor", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0054, 0x1330, 0x0054, 0x1330, + EVR_US, "ImageIndex", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0054, 0x1400, 0x0054, 0x1400, + EVR_CS, "RETIRED_CountsIncluded", 1, -1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0054, 0x1401, 0x0054, 0x1401, + EVR_CS, "RETIRED_DeadTimeCorrectionFlag", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } +#ifdef ENABLE_PRIVATE_TAGS + , { 0x0055, 0x0046, 0x0055, 0x0046, + EVR_LT, "CurrentWard", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS ISI" } +#endif + , { 0x0060, 0x3000, 0x0060, 0x3000, + EVR_SQ, "HistogramSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0060, 0x3002, 0x0060, 0x3002, + EVR_US, "HistogramNumberOfBins", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0060, 0x3004, 0x0060, 0x3004, + EVR_xs, "HistogramFirstBinValue", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0060, 0x3006, 0x0060, 0x3006, + EVR_xs, "HistogramLastBinValue", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0060, 0x3008, 0x0060, 0x3008, + EVR_US, "HistogramBinWidth", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0060, 0x3010, 0x0060, 0x3010, + EVR_LO, "HistogramExplanation", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0060, 0x3020, 0x0060, 0x3020, + EVR_UL, "HistogramData", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0062, 0x0001, 0x0062, 0x0001, + EVR_CS, "SegmentationType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0062, 0x0002, 0x0062, 0x0002, + EVR_SQ, "SegmentSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0062, 0x0003, 0x0062, 0x0003, + EVR_SQ, "SegmentedPropertyCategoryCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0062, 0x0004, 0x0062, 0x0004, + EVR_US, "SegmentNumber", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0062, 0x0005, 0x0062, 0x0005, + EVR_LO, "SegmentLabel", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0062, 0x0006, 0x0062, 0x0006, + EVR_ST, "SegmentDescription", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0062, 0x0008, 0x0062, 0x0008, + EVR_CS, "SegmentAlgorithmType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0062, 0x0009, 0x0062, 0x0009, + EVR_LO, "SegmentAlgorithmName", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0062, 0x000a, 0x0062, 0x000a, + EVR_SQ, "SegmentIdentificationSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0062, 0x000b, 0x0062, 0x000b, + EVR_US, "ReferencedSegmentNumber", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0062, 0x000c, 0x0062, 0x000c, + EVR_US, "RecommendedDisplayGrayscaleValue", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0062, 0x000d, 0x0062, 0x000d, + EVR_US, "RecommendedDisplayCIELabValue", 3, 3, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0062, 0x000e, 0x0062, 0x000e, + EVR_US, "MaximumFractionalValue", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0062, 0x000f, 0x0062, 0x000f, + EVR_SQ, "SegmentedPropertyTypeCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0062, 0x0010, 0x0062, 0x0010, + EVR_CS, "SegmentationFractionalType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0062, 0x0011, 0x0062, 0x0011, + EVR_SQ, "SegmentedPropertyTypeModifierCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0062, 0x0012, 0x0062, 0x0012, + EVR_SQ, "UsedSegmentsSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0064, 0x0002, 0x0064, 0x0002, + EVR_SQ, "DeformableRegistrationSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0064, 0x0003, 0x0064, 0x0003, + EVR_UI, "SourceFrameOfReferenceUID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0064, 0x0005, 0x0064, 0x0005, + EVR_SQ, "DeformableRegistrationGridSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0064, 0x0007, 0x0064, 0x0007, + EVR_UL, "GridDimensions", 3, 3, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0064, 0x0008, 0x0064, 0x0008, + EVR_FD, "GridResolution", 3, 3, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0064, 0x0009, 0x0064, 0x0009, + EVR_OF, "VectorGridData", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0064, 0x000f, 0x0064, 0x000f, + EVR_SQ, "PreDeformationMatrixRegistrationSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0064, 0x0010, 0x0064, 0x0010, + EVR_SQ, "PostDeformationMatrixRegistrationSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0066, 0x0001, 0x0066, 0x0001, + EVR_UL, "NumberOfSurfaces", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0066, 0x0002, 0x0066, 0x0002, + EVR_SQ, "SurfaceSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0066, 0x0003, 0x0066, 0x0003, + EVR_UL, "SurfaceNumber", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0066, 0x0004, 0x0066, 0x0004, + EVR_LT, "SurfaceComments", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0066, 0x0009, 0x0066, 0x0009, + EVR_CS, "SurfaceProcessing", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0066, 0x000a, 0x0066, 0x000a, + EVR_FL, "SurfaceProcessingRatio", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0066, 0x000b, 0x0066, 0x000b, + EVR_LO, "SurfaceProcessingDescription", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0066, 0x000c, 0x0066, 0x000c, + EVR_FL, "RecommendedPresentationOpacity", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0066, 0x000d, 0x0066, 0x000d, + EVR_CS, "RecommendedPresentationType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0066, 0x000e, 0x0066, 0x000e, + EVR_CS, "FiniteVolume", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0066, 0x0010, 0x0066, 0x0010, + EVR_CS, "Manifold", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0066, 0x0011, 0x0066, 0x0011, + EVR_SQ, "SurfacePointsSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0066, 0x0012, 0x0066, 0x0012, + EVR_SQ, "SurfacePointsNormalsSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0066, 0x0013, 0x0066, 0x0013, + EVR_SQ, "SurfaceMeshPrimitivesSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0066, 0x0015, 0x0066, 0x0015, + EVR_UL, "NumberOfSurfacePoints", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0066, 0x0016, 0x0066, 0x0016, + EVR_OF, "PointCoordinatesData", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0066, 0x0017, 0x0066, 0x0017, + EVR_FL, "PointPositionAccuracy", 3, 3, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0066, 0x0018, 0x0066, 0x0018, + EVR_FL, "MeanPointDistance", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0066, 0x0019, 0x0066, 0x0019, + EVR_FL, "MaximumPointDistance", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0066, 0x001a, 0x0066, 0x001a, + EVR_FL, "PointsBoundingBoxCoordinates", 6, 6, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0066, 0x001b, 0x0066, 0x001b, + EVR_FL, "AxisOfRotation", 3, 3, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0066, 0x001c, 0x0066, 0x001c, + EVR_FL, "CenterOfRotation", 3, 3, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0066, 0x001e, 0x0066, 0x001e, + EVR_UL, "NumberOfVectors", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0066, 0x001f, 0x0066, 0x001f, + EVR_US, "VectorDimensionality", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0066, 0x0020, 0x0066, 0x0020, + EVR_FL, "VectorAccuracy", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0066, 0x0021, 0x0066, 0x0021, + EVR_OF, "VectorCoordinateData", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0066, 0x0023, 0x0066, 0x0023, + EVR_OW, "TrianglePointIndexList", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0066, 0x0024, 0x0066, 0x0024, + EVR_OW, "EdgePointIndexList", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0066, 0x0025, 0x0066, 0x0025, + EVR_OW, "VertexPointIndexList", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0066, 0x0026, 0x0066, 0x0026, + EVR_SQ, "TriangleStripSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0066, 0x0027, 0x0066, 0x0027, + EVR_SQ, "TriangleFanSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0066, 0x0028, 0x0066, 0x0028, + EVR_SQ, "LineSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0066, 0x0029, 0x0066, 0x0029, + EVR_OW, "PrimitivePointIndexList", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0066, 0x002a, 0x0066, 0x002a, + EVR_UL, "SurfaceCount", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0066, 0x002b, 0x0066, 0x002b, + EVR_SQ, "ReferencedSurfaceSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0066, 0x002c, 0x0066, 0x002c, + EVR_UL, "ReferencedSurfaceNumber", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0066, 0x002d, 0x0066, 0x002d, + EVR_SQ, "SegmentSurfaceGenerationAlgorithmIdentificationSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0066, 0x002e, 0x0066, 0x002e, + EVR_SQ, "SegmentSurfaceSourceInstanceSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0066, 0x002f, 0x0066, 0x002f, + EVR_SQ, "AlgorithmFamilyCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0066, 0x0030, 0x0066, 0x0030, + EVR_SQ, "AlgorithmNameCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0066, 0x0031, 0x0066, 0x0031, + EVR_LO, "AlgorithmVersion", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0066, 0x0032, 0x0066, 0x0032, + EVR_LT, "AlgorithmParameters", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0066, 0x0034, 0x0066, 0x0034, + EVR_SQ, "FacetSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0066, 0x0035, 0x0066, 0x0035, + EVR_SQ, "SurfaceProcessingAlgorithmIdentificationSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0066, 0x0036, 0x0066, 0x0036, + EVR_LO, "AlgorithmName", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0066, 0x0037, 0x0066, 0x0037, + EVR_FL, "RecommendedPointRadius", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0066, 0x0038, 0x0066, 0x0038, + EVR_FL, "RecommendedLineThickness", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0066, 0x0040, 0x0066, 0x0040, + EVR_UL, "LongPrimitivePointIndexList", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0066, 0x0041, 0x0066, 0x0041, + EVR_UL, "LongTrianglePointIndexList", 3, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0066, 0x0042, 0x0066, 0x0042, + EVR_UL, "LongEdgePointIndexList", 2, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0066, 0x0043, 0x0066, 0x0043, + EVR_UL, "LongVertexPointIndexList", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0068, 0x6210, 0x0068, 0x6210, + EVR_LO, "ImplantSize", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0068, 0x6221, 0x0068, 0x6221, + EVR_LO, "ImplantTemplateVersion", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0068, 0x6222, 0x0068, 0x6222, + EVR_SQ, "ReplacedImplantTemplateSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0068, 0x6223, 0x0068, 0x6223, + EVR_CS, "ImplantType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0068, 0x6224, 0x0068, 0x6224, + EVR_SQ, "DerivationImplantTemplateSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0068, 0x6225, 0x0068, 0x6225, + EVR_SQ, "OriginalImplantTemplateSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0068, 0x6226, 0x0068, 0x6226, + EVR_DT, "EffectiveDateTime", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0068, 0x6230, 0x0068, 0x6230, + EVR_SQ, "ImplantTargetAnatomySequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0068, 0x6260, 0x0068, 0x6260, + EVR_SQ, "InformationFromManufacturerSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0068, 0x6265, 0x0068, 0x6265, + EVR_SQ, "NotificationFromManufacturerSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0068, 0x6270, 0x0068, 0x6270, + EVR_DT, "InformationIssueDateTime", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0068, 0x6280, 0x0068, 0x6280, + EVR_ST, "InformationSummary", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0068, 0x62a0, 0x0068, 0x62a0, + EVR_SQ, "ImplantRegulatoryDisapprovalCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0068, 0x62a5, 0x0068, 0x62a5, + EVR_FD, "OverallTemplateSpatialTolerance", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0068, 0x62c0, 0x0068, 0x62c0, + EVR_SQ, "HPGLDocumentSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0068, 0x62d0, 0x0068, 0x62d0, + EVR_US, "HPGLDocumentID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0068, 0x62d5, 0x0068, 0x62d5, + EVR_LO, "HPGLDocumentLabel", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0068, 0x62e0, 0x0068, 0x62e0, + EVR_SQ, "ViewOrientationCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0068, 0x62f0, 0x0068, 0x62f0, + EVR_FD, "ViewOrientationModifier", 9, 9, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0068, 0x62f2, 0x0068, 0x62f2, + EVR_FD, "HPGLDocumentScaling", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0068, 0x6300, 0x0068, 0x6300, + EVR_OB, "HPGLDocument", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0068, 0x6310, 0x0068, 0x6310, + EVR_US, "HPGLContourPenNumber", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0068, 0x6320, 0x0068, 0x6320, + EVR_SQ, "HPGLPenSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0068, 0x6330, 0x0068, 0x6330, + EVR_US, "HPGLPenNumber", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0068, 0x6340, 0x0068, 0x6340, + EVR_LO, "HPGLPenLabel", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0068, 0x6345, 0x0068, 0x6345, + EVR_ST, "HPGLPenDescription", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0068, 0x6346, 0x0068, 0x6346, + EVR_FD, "RecommendedRotationPoint", 2, 2, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0068, 0x6347, 0x0068, 0x6347, + EVR_FD, "BoundingRectangle", 4, 4, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0068, 0x6350, 0x0068, 0x6350, + EVR_US, "ImplantTemplate3DModelSurfaceNumber", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0068, 0x6360, 0x0068, 0x6360, + EVR_SQ, "SurfaceModelDescriptionSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0068, 0x6380, 0x0068, 0x6380, + EVR_LO, "SurfaceModelLabel", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0068, 0x6390, 0x0068, 0x6390, + EVR_FD, "SurfaceModelScalingFactor", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0068, 0x63a0, 0x0068, 0x63a0, + EVR_SQ, "MaterialsCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0068, 0x63a4, 0x0068, 0x63a4, + EVR_SQ, "CoatingMaterialsCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0068, 0x63a8, 0x0068, 0x63a8, + EVR_SQ, "ImplantTypeCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0068, 0x63ac, 0x0068, 0x63ac, + EVR_SQ, "FixationMethodCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0068, 0x63b0, 0x0068, 0x63b0, + EVR_SQ, "MatingFeatureSetsSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0068, 0x63c0, 0x0068, 0x63c0, + EVR_US, "MatingFeatureSetID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0068, 0x63d0, 0x0068, 0x63d0, + EVR_LO, "MatingFeatureSetLabel", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0068, 0x63e0, 0x0068, 0x63e0, + EVR_SQ, "MatingFeatureSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0068, 0x63f0, 0x0068, 0x63f0, + EVR_US, "MatingFeatureID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0068, 0x6400, 0x0068, 0x6400, + EVR_SQ, "MatingFeatureDegreeOfFreedomSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0068, 0x6410, 0x0068, 0x6410, + EVR_US, "DegreeOfFreedomID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0068, 0x6420, 0x0068, 0x6420, + EVR_CS, "DegreeOfFreedomType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0068, 0x6430, 0x0068, 0x6430, + EVR_SQ, "TwoDMatingFeatureCoordinatesSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0068, 0x6440, 0x0068, 0x6440, + EVR_US, "ReferencedHPGLDocumentID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0068, 0x6450, 0x0068, 0x6450, + EVR_FD, "TwoDMatingPoint", 2, 2, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0068, 0x6460, 0x0068, 0x6460, + EVR_FD, "TwoDMatingAxes", 4, 4, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0068, 0x6470, 0x0068, 0x6470, + EVR_SQ, "TwoDDegreeOfFreedomSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0068, 0x6490, 0x0068, 0x6490, + EVR_FD, "ThreeDDegreeOfFreedomAxis", 3, 3, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0068, 0x64a0, 0x0068, 0x64a0, + EVR_FD, "RangeOfFreedom", 2, 2, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0068, 0x64c0, 0x0068, 0x64c0, + EVR_FD, "ThreeDMatingPoint", 3, 3, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0068, 0x64d0, 0x0068, 0x64d0, + EVR_FD, "ThreeDMatingAxes", 9, 9, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0068, 0x64f0, 0x0068, 0x64f0, + EVR_FD, "TwoDDegreeOfFreedomAxis", 3, 3, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0068, 0x6500, 0x0068, 0x6500, + EVR_SQ, "PlanningLandmarkPointSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0068, 0x6510, 0x0068, 0x6510, + EVR_SQ, "PlanningLandmarkLineSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0068, 0x6520, 0x0068, 0x6520, + EVR_SQ, "PlanningLandmarkPlaneSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0068, 0x6530, 0x0068, 0x6530, + EVR_US, "PlanningLandmarkID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0068, 0x6540, 0x0068, 0x6540, + EVR_LO, "PlanningLandmarkDescription", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0068, 0x6545, 0x0068, 0x6545, + EVR_SQ, "PlanningLandmarkIdentificationCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0068, 0x6550, 0x0068, 0x6550, + EVR_SQ, "TwoDPointCoordinatesSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0068, 0x6560, 0x0068, 0x6560, + EVR_FD, "TwoDPointCoordinates", 2, 2, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0068, 0x6590, 0x0068, 0x6590, + EVR_FD, "ThreeDPointCoordinates", 3, 3, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0068, 0x65a0, 0x0068, 0x65a0, + EVR_SQ, "TwoDLineCoordinatesSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0068, 0x65b0, 0x0068, 0x65b0, + EVR_FD, "TwoDLineCoordinates", 4, 4, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0068, 0x65d0, 0x0068, 0x65d0, + EVR_FD, "ThreeDLineCoordinates", 6, 6, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0068, 0x65e0, 0x0068, 0x65e0, + EVR_SQ, "TwoDPlaneCoordinatesSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0068, 0x65f0, 0x0068, 0x65f0, + EVR_FD, "TwoDPlaneIntersection", 4, 4, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0068, 0x6610, 0x0068, 0x6610, + EVR_FD, "ThreeDPlaneOrigin", 3, 3, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0068, 0x6620, 0x0068, 0x6620, + EVR_FD, "ThreeDPlaneNormal", 3, 3, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x0001, 0x0070, 0x0001, + EVR_SQ, "GraphicAnnotationSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x0002, 0x0070, 0x0002, + EVR_CS, "GraphicLayer", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x0003, 0x0070, 0x0003, + EVR_CS, "BoundingBoxAnnotationUnits", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x0004, 0x0070, 0x0004, + EVR_CS, "AnchorPointAnnotationUnits", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x0005, 0x0070, 0x0005, + EVR_CS, "GraphicAnnotationUnits", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x0006, 0x0070, 0x0006, + EVR_ST, "UnformattedTextValue", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x0008, 0x0070, 0x0008, + EVR_SQ, "TextObjectSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x0009, 0x0070, 0x0009, + EVR_SQ, "GraphicObjectSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x0010, 0x0070, 0x0010, + EVR_FL, "BoundingBoxTopLeftHandCorner", 2, 2, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x0011, 0x0070, 0x0011, + EVR_FL, "BoundingBoxBottomRightHandCorner", 2, 2, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x0012, 0x0070, 0x0012, + EVR_CS, "BoundingBoxTextHorizontalJustification", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x0014, 0x0070, 0x0014, + EVR_FL, "AnchorPoint", 2, 2, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x0015, 0x0070, 0x0015, + EVR_CS, "AnchorPointVisibility", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x0020, 0x0070, 0x0020, + EVR_US, "GraphicDimensions", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x0021, 0x0070, 0x0021, + EVR_US, "NumberOfGraphicPoints", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x0022, 0x0070, 0x0022, + EVR_FL, "GraphicData", 2, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x0023, 0x0070, 0x0023, + EVR_CS, "GraphicType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x0024, 0x0070, 0x0024, + EVR_CS, "GraphicFilled", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x0040, 0x0070, 0x0040, + EVR_IS, "RETIRED_ImageRotationRetired", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x0041, 0x0070, 0x0041, + EVR_CS, "ImageHorizontalFlip", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x0042, 0x0070, 0x0042, + EVR_US, "ImageRotation", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x0050, 0x0070, 0x0050, + EVR_US, "RETIRED_DisplayedAreaTopLeftHandCornerTrial", 2, 2, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x0051, 0x0070, 0x0051, + EVR_US, "RETIRED_DisplayedAreaBottomRightHandCornerTrial", 2, 2, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x0052, 0x0070, 0x0052, + EVR_SL, "DisplayedAreaTopLeftHandCorner", 2, 2, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x0053, 0x0070, 0x0053, + EVR_SL, "DisplayedAreaBottomRightHandCorner", 2, 2, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x005a, 0x0070, 0x005a, + EVR_SQ, "DisplayedAreaSelectionSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x0060, 0x0070, 0x0060, + EVR_SQ, "GraphicLayerSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x0062, 0x0070, 0x0062, + EVR_IS, "GraphicLayerOrder", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x0066, 0x0070, 0x0066, + EVR_US, "GraphicLayerRecommendedDisplayGrayscaleValue", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x0067, 0x0070, 0x0067, + EVR_US, "RETIRED_GraphicLayerRecommendedDisplayRGBValue", 3, 3, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x0068, 0x0070, 0x0068, + EVR_LO, "GraphicLayerDescription", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x0080, 0x0070, 0x0080, + EVR_CS, "ContentLabel", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x0081, 0x0070, 0x0081, + EVR_LO, "ContentDescription", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x0082, 0x0070, 0x0082, + EVR_DA, "PresentationCreationDate", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x0083, 0x0070, 0x0083, + EVR_TM, "PresentationCreationTime", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x0084, 0x0070, 0x0084, + EVR_PN, "ContentCreatorName", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x0086, 0x0070, 0x0086, + EVR_SQ, "ContentCreatorIdentificationCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x0087, 0x0070, 0x0087, + EVR_SQ, "AlternateContentDescriptionSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x0100, 0x0070, 0x0100, + EVR_CS, "PresentationSizeMode", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x0101, 0x0070, 0x0101, + EVR_DS, "PresentationPixelSpacing", 2, 2, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x0102, 0x0070, 0x0102, + EVR_IS, "PresentationPixelAspectRatio", 2, 2, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x0103, 0x0070, 0x0103, + EVR_FL, "PresentationPixelMagnificationRatio", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x0207, 0x0070, 0x0207, + EVR_LO, "GraphicGroupLabel", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x0208, 0x0070, 0x0208, + EVR_ST, "GraphicGroupDescription", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x0209, 0x0070, 0x0209, + EVR_SQ, "CompoundGraphicSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x0226, 0x0070, 0x0226, + EVR_UL, "CompoundGraphicInstanceID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x0227, 0x0070, 0x0227, + EVR_LO, "FontName", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x0228, 0x0070, 0x0228, + EVR_CS, "FontNameType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x0229, 0x0070, 0x0229, + EVR_LO, "CSSFontName", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x0230, 0x0070, 0x0230, + EVR_FD, "RotationAngle", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x0231, 0x0070, 0x0231, + EVR_SQ, "TextStyleSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x0232, 0x0070, 0x0232, + EVR_SQ, "LineStyleSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x0233, 0x0070, 0x0233, + EVR_SQ, "FillStyleSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x0234, 0x0070, 0x0234, + EVR_SQ, "GraphicGroupSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x0241, 0x0070, 0x0241, + EVR_US, "TextColorCIELabValue", 3, 3, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x0242, 0x0070, 0x0242, + EVR_CS, "HorizontalAlignment", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x0243, 0x0070, 0x0243, + EVR_CS, "VerticalAlignment", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x0244, 0x0070, 0x0244, + EVR_CS, "ShadowStyle", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x0245, 0x0070, 0x0245, + EVR_FL, "ShadowOffsetX", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x0246, 0x0070, 0x0246, + EVR_FL, "ShadowOffsetY", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x0247, 0x0070, 0x0247, + EVR_US, "ShadowColorCIELabValue", 3, 3, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x0248, 0x0070, 0x0248, + EVR_CS, "Underlined", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x0249, 0x0070, 0x0249, + EVR_CS, "Bold", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x0250, 0x0070, 0x0250, + EVR_CS, "Italic", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x0251, 0x0070, 0x0251, + EVR_US, "PatternOnColorCIELabValue", 3, 3, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x0252, 0x0070, 0x0252, + EVR_US, "PatternOffColorCIELabValue", 3, 3, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x0253, 0x0070, 0x0253, + EVR_FL, "LineThickness", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x0254, 0x0070, 0x0254, + EVR_CS, "LineDashingStyle", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x0255, 0x0070, 0x0255, + EVR_UL, "LinePattern", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x0256, 0x0070, 0x0256, + EVR_OB, "FillPattern", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x0257, 0x0070, 0x0257, + EVR_CS, "FillMode", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x0258, 0x0070, 0x0258, + EVR_FL, "ShadowOpacity", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x0261, 0x0070, 0x0261, + EVR_FL, "GapLength", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x0262, 0x0070, 0x0262, + EVR_FL, "DiameterOfVisibility", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x0273, 0x0070, 0x0273, + EVR_FL, "RotationPoint", 2, 2, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x0274, 0x0070, 0x0274, + EVR_CS, "TickAlignment", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x0278, 0x0070, 0x0278, + EVR_CS, "ShowTickLabel", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x0279, 0x0070, 0x0279, + EVR_CS, "TickLabelAlignment", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x0282, 0x0070, 0x0282, + EVR_CS, "CompoundGraphicUnits", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x0284, 0x0070, 0x0284, + EVR_FL, "PatternOnOpacity", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x0285, 0x0070, 0x0285, + EVR_FL, "PatternOffOpacity", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x0287, 0x0070, 0x0287, + EVR_SQ, "MajorTicksSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x0288, 0x0070, 0x0288, + EVR_FL, "TickPosition", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x0289, 0x0070, 0x0289, + EVR_SH, "TickLabel", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x0294, 0x0070, 0x0294, + EVR_CS, "CompoundGraphicType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x0295, 0x0070, 0x0295, + EVR_UL, "GraphicGroupID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x0306, 0x0070, 0x0306, + EVR_CS, "ShapeType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x0308, 0x0070, 0x0308, + EVR_SQ, "RegistrationSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x0309, 0x0070, 0x0309, + EVR_SQ, "MatrixRegistrationSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x030a, 0x0070, 0x030a, + EVR_SQ, "MatrixSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x030c, 0x0070, 0x030c, + EVR_CS, "FrameOfReferenceTransformationMatrixType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x030d, 0x0070, 0x030d, + EVR_SQ, "RegistrationTypeCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x030f, 0x0070, 0x030f, + EVR_ST, "FiducialDescription", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x0310, 0x0070, 0x0310, + EVR_SH, "FiducialIdentifier", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x0311, 0x0070, 0x0311, + EVR_SQ, "FiducialIdentifierCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x0312, 0x0070, 0x0312, + EVR_FD, "ContourUncertaintyRadius", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x0314, 0x0070, 0x0314, + EVR_SQ, "UsedFiducialsSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x0318, 0x0070, 0x0318, + EVR_SQ, "GraphicCoordinatesDataSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x031a, 0x0070, 0x031a, + EVR_UI, "FiducialUID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x031c, 0x0070, 0x031c, + EVR_SQ, "FiducialSetSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x031e, 0x0070, 0x031e, + EVR_SQ, "FiducialSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x0401, 0x0070, 0x0401, + EVR_US, "GraphicLayerRecommendedDisplayCIELabValue", 3, 3, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x0402, 0x0070, 0x0402, + EVR_SQ, "BlendingSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x0403, 0x0070, 0x0403, + EVR_FL, "RelativeOpacity", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x0404, 0x0070, 0x0404, + EVR_SQ, "ReferencedSpatialRegistrationSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x0405, 0x0070, 0x0405, + EVR_CS, "BlendingPosition", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x1101, 0x0070, 0x1101, + EVR_UI, "PresentationDisplayCollectionUID", 1, 1, "Supplement_156", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x1102, 0x0070, 0x1102, + EVR_UI, "PresentationSequenceCollectionUID", 1, 1, "Supplement_156", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x1103, 0x0070, 0x1103, + EVR_US, "PresentationSequencePositionIndex", 1, 1, "Supplement_156", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x1104, 0x0070, 0x1104, + EVR_SQ, "RenderedImageReferenceSequence", 1, 1, "Supplement_156", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x1201, 0x0070, 0x1201, + EVR_SQ, "VolumetricPresentationStateInputSequence", 1, 1, "Supplement_156", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x1202, 0x0070, 0x1202, + EVR_CS, "PresentationInputType", 1, 1, "Supplement_156", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x1203, 0x0070, 0x1203, + EVR_US, "InputSequencePositionIndex", 1, 1, "Supplement_156", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x1204, 0x0070, 0x1204, + EVR_CS, "Crop", 1, 1, "Supplement_156", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x1205, 0x0070, 0x1205, + EVR_US, "CroppingSpecificationIndex", 1, -1, "Supplement_156", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x1206, 0x0070, 0x1206, + EVR_CS, "CompositingMethod", 1, 1, "Supplement_156", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x1207, 0x0070, 0x1207, + EVR_US, "VolumetricPresentationInputNumber", 1, 1, "Supplement_156", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x1208, 0x0070, 0x1208, + EVR_CS, "ImageVolumeGeometry", 1, 1, "Supplement_156", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x1301, 0x0070, 0x1301, + EVR_SQ, "VolumeCroppingSequence", 1, 1, "Supplement_156", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x1302, 0x0070, 0x1302, + EVR_CS, "VolumeCroppingMethod", 1, 1, "Supplement_156", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x1303, 0x0070, 0x1303, + EVR_FD, "BoundingBoxCrop", 6, 6, "Supplement_156", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x1304, 0x0070, 0x1304, + EVR_SQ, "ObliqueCroppingPlaneSequence", 1, 1, "Supplement_156", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x1305, 0x0070, 0x1305, + EVR_FD, "ObliqueCroppingPlane", 4, 4, "Supplement_156", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x1306, 0x0070, 0x1306, + EVR_FD, "ObliqueCroppingPlaneNormal", 3, 3, "Supplement_156", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x1309, 0x0070, 0x1309, + EVR_US, "CroppingSpecificationNumber", 1, 1, "Supplement_156", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x1501, 0x0070, 0x1501, + EVR_CS, "MultiPlanarReconstructionStyle", 1, 1, "Supplement_156", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x1502, 0x0070, 0x1502, + EVR_CS, "MPRThicknessType", 1, 1, "Supplement_156", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x1503, 0x0070, 0x1503, + EVR_FD, "MPRSlabThickness", 1, 1, "Supplement_156", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x1505, 0x0070, 0x1505, + EVR_FD, "MPRTopLeftHandCorner", 3, 3, "Supplement_156", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x1507, 0x0070, 0x1507, + EVR_FD, "MPRViewWidthDirection", 3, 3, "Supplement_156", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x1508, 0x0070, 0x1508, + EVR_FD, "MPRViewWidth", 1, 1, "Supplement_156", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x150c, 0x0070, 0x150c, + EVR_FL, "NumberOfVolumetricCurvePoints", 1, 1, "Supplement_156", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x150d, 0x0070, 0x150d, + EVR_OD, "VolumetricCurvePoints", 1, 1, "Supplement_156", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x1511, 0x0070, 0x1511, + EVR_FD, "MPRViewHeightDirection", 3, 3, "Supplement_156", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x1512, 0x0070, 0x1512, + EVR_FD, "MPRViewHeight", 1, 1, "Supplement_156", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x1801, 0x0070, 0x1801, + EVR_SQ, "PresentationStateClassificationComponentSequence", 1, 1, "Supplement_156", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x1802, 0x0070, 0x1802, + EVR_CS, "ComponentType", 1, 1, "Supplement_156", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x1803, 0x0070, 0x1803, + EVR_SQ, "ComponentInputSequence", 1, 1, "Supplement_156", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x1804, 0x0070, 0x1804, + EVR_US, "VolumetricPresentationInputIndex", 1, 1, "Supplement_156", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x1805, 0x0070, 0x1805, + EVR_SQ, "PresentationStateCompositorComponentSequence", 1, 1, "Supplement_156", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x1806, 0x0070, 0x1806, + EVR_SQ, "WeightingTransferFunctionSequence", 1, 1, "Supplement_156", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x1807, 0x0070, 0x1807, + EVR_US, "WeightingLookupTableDescriptor", 3, 3, "Supplement_156", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x1808, 0x0070, 0x1808, + EVR_OB, "WeightingLookupTableData", 1, 1, "Supplement_156", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x1901, 0x0070, 0x1901, + EVR_SQ, "VolumetricAnnotationSequence", 1, 1, "Supplement_156", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x1903, 0x0070, 0x1903, + EVR_SQ, "ReferencedStructuredContextSequence", 1, 1, "Supplement_156", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x1904, 0x0070, 0x1904, + EVR_UI, "ReferencedContentItem", 1, 1, "Supplement_156", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x1905, 0x0070, 0x1905, + EVR_SQ, "VolumetricPresentationInputAnnotationSequence", 1, 1, "Supplement_156", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x1907, 0x0070, 0x1907, + EVR_CS, "AnnotationClipping", 1, 1, "Supplement_156", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x1a01, 0x0070, 0x1a01, + EVR_CS, "PresentationAnimationStyle", 1, 1, "Supplement_156", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x1a03, 0x0070, 0x1a03, + EVR_FD, "RecommendedAnimationRate", 1, 1, "Supplement_156", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x1a04, 0x0070, 0x1a04, + EVR_SQ, "AnimationCurveSequence", 1, 1, "Supplement_156", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0070, 0x1a05, 0x0070, 0x1a05, + EVR_FD, "AnimationStepSize", 1, 1, "Supplement_156", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0072, 0x0002, 0x0072, 0x0002, + EVR_SH, "HangingProtocolName", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0072, 0x0004, 0x0072, 0x0004, + EVR_LO, "HangingProtocolDescription", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0072, 0x0006, 0x0072, 0x0006, + EVR_CS, "HangingProtocolLevel", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0072, 0x0008, 0x0072, 0x0008, + EVR_LO, "HangingProtocolCreator", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0072, 0x000a, 0x0072, 0x000a, + EVR_DT, "HangingProtocolCreationDateTime", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0072, 0x000c, 0x0072, 0x000c, + EVR_SQ, "HangingProtocolDefinitionSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0072, 0x000e, 0x0072, 0x000e, + EVR_SQ, "HangingProtocolUserIdentificationCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0072, 0x0010, 0x0072, 0x0010, + EVR_LO, "HangingProtocolUserGroupName", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0072, 0x0012, 0x0072, 0x0012, + EVR_SQ, "SourceHangingProtocolSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0072, 0x0014, 0x0072, 0x0014, + EVR_US, "NumberOfPriorsReferenced", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0072, 0x0020, 0x0072, 0x0020, + EVR_SQ, "ImageSetsSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0072, 0x0022, 0x0072, 0x0022, + EVR_SQ, "ImageSetSelectorSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0072, 0x0024, 0x0072, 0x0024, + EVR_CS, "ImageSetSelectorUsageFlag", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0072, 0x0026, 0x0072, 0x0026, + EVR_AT, "SelectorAttribute", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0072, 0x0028, 0x0072, 0x0028, + EVR_US, "SelectorValueNumber", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0072, 0x0030, 0x0072, 0x0030, + EVR_SQ, "TimeBasedImageSetsSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0072, 0x0032, 0x0072, 0x0032, + EVR_US, "ImageSetNumber", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0072, 0x0034, 0x0072, 0x0034, + EVR_CS, "ImageSetSelectorCategory", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0072, 0x0038, 0x0072, 0x0038, + EVR_US, "RelativeTime", 2, 2, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0072, 0x003a, 0x0072, 0x003a, + EVR_CS, "RelativeTimeUnits", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0072, 0x003c, 0x0072, 0x003c, + EVR_SS, "AbstractPriorValue", 2, 2, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0072, 0x003e, 0x0072, 0x003e, + EVR_SQ, "AbstractPriorCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0072, 0x0040, 0x0072, 0x0040, + EVR_LO, "ImageSetLabel", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0072, 0x0050, 0x0072, 0x0050, + EVR_CS, "SelectorAttributeVR", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0072, 0x0052, 0x0072, 0x0052, + EVR_AT, "SelectorSequencePointer", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0072, 0x0054, 0x0072, 0x0054, + EVR_LO, "SelectorSequencePointerPrivateCreator", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0072, 0x0056, 0x0072, 0x0056, + EVR_LO, "SelectorAttributePrivateCreator", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0072, 0x0060, 0x0072, 0x0060, + EVR_AT, "SelectorATValue", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0072, 0x0062, 0x0072, 0x0062, + EVR_CS, "SelectorCSValue", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0072, 0x0064, 0x0072, 0x0064, + EVR_IS, "SelectorISValue", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0072, 0x0066, 0x0072, 0x0066, + EVR_LO, "SelectorLOValue", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0072, 0x0068, 0x0072, 0x0068, + EVR_LT, "SelectorLTValue", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0072, 0x006a, 0x0072, 0x006a, + EVR_PN, "SelectorPNValue", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0072, 0x006c, 0x0072, 0x006c, + EVR_SH, "SelectorSHValue", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0072, 0x006e, 0x0072, 0x006e, + EVR_ST, "SelectorSTValue", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0072, 0x0070, 0x0072, 0x0070, + EVR_UT, "SelectorUTValue", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0072, 0x0072, 0x0072, 0x0072, + EVR_DS, "SelectorDSValue", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0072, 0x0074, 0x0072, 0x0074, + EVR_FD, "SelectorFDValue", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0072, 0x0076, 0x0072, 0x0076, + EVR_FL, "SelectorFLValue", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0072, 0x0078, 0x0072, 0x0078, + EVR_UL, "SelectorULValue", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0072, 0x007a, 0x0072, 0x007a, + EVR_US, "SelectorUSValue", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0072, 0x007c, 0x0072, 0x007c, + EVR_SL, "SelectorSLValue", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0072, 0x007e, 0x0072, 0x007e, + EVR_SS, "SelectorSSValue", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0072, 0x007f, 0x0072, 0x007f, + EVR_UI, "SelectorUIValue", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0072, 0x0080, 0x0072, 0x0080, + EVR_SQ, "SelectorCodeSequenceValue", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0072, 0x0100, 0x0072, 0x0100, + EVR_US, "NumberOfScreens", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0072, 0x0102, 0x0072, 0x0102, + EVR_SQ, "NominalScreenDefinitionSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0072, 0x0104, 0x0072, 0x0104, + EVR_US, "NumberOfVerticalPixels", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0072, 0x0106, 0x0072, 0x0106, + EVR_US, "NumberOfHorizontalPixels", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0072, 0x0108, 0x0072, 0x0108, + EVR_FD, "DisplayEnvironmentSpatialPosition", 4, 4, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0072, 0x010a, 0x0072, 0x010a, + EVR_US, "ScreenMinimumGrayscaleBitDepth", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0072, 0x010c, 0x0072, 0x010c, + EVR_US, "ScreenMinimumColorBitDepth", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0072, 0x010e, 0x0072, 0x010e, + EVR_US, "ApplicationMaximumRepaintTime", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0072, 0x0200, 0x0072, 0x0200, + EVR_SQ, "DisplaySetsSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0072, 0x0202, 0x0072, 0x0202, + EVR_US, "DisplaySetNumber", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0072, 0x0203, 0x0072, 0x0203, + EVR_LO, "DisplaySetLabel", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0072, 0x0204, 0x0072, 0x0204, + EVR_US, "DisplaySetPresentationGroup", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0072, 0x0206, 0x0072, 0x0206, + EVR_LO, "DisplaySetPresentationGroupDescription", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0072, 0x0208, 0x0072, 0x0208, + EVR_CS, "PartialDataDisplayHandling", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0072, 0x0210, 0x0072, 0x0210, + EVR_SQ, "SynchronizedScrollingSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0072, 0x0212, 0x0072, 0x0212, + EVR_US, "DisplaySetScrollingGroup", 2, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0072, 0x0214, 0x0072, 0x0214, + EVR_SQ, "NavigationIndicatorSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0072, 0x0216, 0x0072, 0x0216, + EVR_US, "NavigationDisplaySet", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0072, 0x0218, 0x0072, 0x0218, + EVR_US, "ReferenceDisplaySets", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0072, 0x0300, 0x0072, 0x0300, + EVR_SQ, "ImageBoxesSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0072, 0x0302, 0x0072, 0x0302, + EVR_US, "ImageBoxNumber", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0072, 0x0304, 0x0072, 0x0304, + EVR_CS, "ImageBoxLayoutType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0072, 0x0306, 0x0072, 0x0306, + EVR_US, "ImageBoxTileHorizontalDimension", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0072, 0x0308, 0x0072, 0x0308, + EVR_US, "ImageBoxTileVerticalDimension", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0072, 0x0310, 0x0072, 0x0310, + EVR_CS, "ImageBoxScrollDirection", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0072, 0x0312, 0x0072, 0x0312, + EVR_CS, "ImageBoxSmallScrollType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0072, 0x0314, 0x0072, 0x0314, + EVR_US, "ImageBoxSmallScrollAmount", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0072, 0x0316, 0x0072, 0x0316, + EVR_CS, "ImageBoxLargeScrollType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0072, 0x0318, 0x0072, 0x0318, + EVR_US, "ImageBoxLargeScrollAmount", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0072, 0x0320, 0x0072, 0x0320, + EVR_US, "ImageBoxOverlapPriority", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0072, 0x0330, 0x0072, 0x0330, + EVR_FD, "CineRelativeToRealTime", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0072, 0x0400, 0x0072, 0x0400, + EVR_SQ, "FilterOperationsSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0072, 0x0402, 0x0072, 0x0402, + EVR_CS, "FilterByCategory", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0072, 0x0404, 0x0072, 0x0404, + EVR_CS, "FilterByAttributePresence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0072, 0x0406, 0x0072, 0x0406, + EVR_CS, "FilterByOperator", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0072, 0x0420, 0x0072, 0x0420, + EVR_US, "StructuredDisplayBackgroundCIELabValue", 3, 3, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0072, 0x0421, 0x0072, 0x0421, + EVR_US, "EmptyImageBoxCIELabValue", 3, 3, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0072, 0x0422, 0x0072, 0x0422, + EVR_SQ, "StructuredDisplayImageBoxSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0072, 0x0424, 0x0072, 0x0424, + EVR_SQ, "StructuredDisplayTextBoxSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0072, 0x0427, 0x0072, 0x0427, + EVR_SQ, "ReferencedFirstFrameSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0072, 0x0430, 0x0072, 0x0430, + EVR_SQ, "ImageBoxSynchronizationSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0072, 0x0432, 0x0072, 0x0432, + EVR_US, "SynchronizedImageBoxList", 2, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0072, 0x0434, 0x0072, 0x0434, + EVR_CS, "TypeOfSynchronization", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0072, 0x0500, 0x0072, 0x0500, + EVR_CS, "BlendingOperationType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0072, 0x0510, 0x0072, 0x0510, + EVR_CS, "ReformattingOperationType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0072, 0x0512, 0x0072, 0x0512, + EVR_FD, "ReformattingThickness", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0072, 0x0514, 0x0072, 0x0514, + EVR_FD, "ReformattingInterval", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0072, 0x0516, 0x0072, 0x0516, + EVR_CS, "ReformattingOperationInitialViewDirection", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0072, 0x0520, 0x0072, 0x0520, + EVR_CS, "ThreeDRenderingType", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0072, 0x0600, 0x0072, 0x0600, + EVR_SQ, "SortingOperationsSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0072, 0x0602, 0x0072, 0x0602, + EVR_CS, "SortByCategory", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0072, 0x0604, 0x0072, 0x0604, + EVR_CS, "SortingDirection", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0072, 0x0700, 0x0072, 0x0700, + EVR_CS, "DisplaySetPatientOrientation", 2, 2, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0072, 0x0702, 0x0072, 0x0702, + EVR_CS, "VOIType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0072, 0x0704, 0x0072, 0x0704, + EVR_CS, "PseudoColorType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0072, 0x0705, 0x0072, 0x0705, + EVR_SQ, "PseudoColorPaletteInstanceReferenceSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0072, 0x0706, 0x0072, 0x0706, + EVR_CS, "ShowGrayscaleInverted", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0072, 0x0710, 0x0072, 0x0710, + EVR_CS, "ShowImageTrueSizeFlag", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0072, 0x0712, 0x0072, 0x0712, + EVR_CS, "ShowGraphicAnnotationFlag", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0072, 0x0714, 0x0072, 0x0714, + EVR_CS, "ShowPatientDemographicsFlag", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0072, 0x0716, 0x0072, 0x0716, + EVR_CS, "ShowAcquisitionTechniquesFlag", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0072, 0x0717, 0x0072, 0x0717, + EVR_CS, "DisplaySetHorizontalJustification", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0072, 0x0718, 0x0072, 0x0718, + EVR_CS, "DisplaySetVerticalJustification", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0074, 0x0120, 0x0074, 0x0120, + EVR_FD, "ContinuationStartMeterset", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0074, 0x0121, 0x0074, 0x0121, + EVR_FD, "ContinuationEndMeterset", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0074, 0x1000, 0x0074, 0x1000, + EVR_CS, "ProcedureStepState", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0074, 0x1002, 0x0074, 0x1002, + EVR_SQ, "ProcedureStepProgressInformationSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0074, 0x1004, 0x0074, 0x1004, + EVR_DS, "ProcedureStepProgress", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0074, 0x1006, 0x0074, 0x1006, + EVR_ST, "ProcedureStepProgressDescription", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0074, 0x1008, 0x0074, 0x1008, + EVR_SQ, "ProcedureStepCommunicationsURISequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0074, 0x100a, 0x0074, 0x100a, + EVR_UR, "ContactURI", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0074, 0x100c, 0x0074, 0x100c, + EVR_LO, "ContactDisplayName", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0074, 0x100e, 0x0074, 0x100e, + EVR_SQ, "ProcedureStepDiscontinuationReasonCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0074, 0x1020, 0x0074, 0x1020, + EVR_SQ, "BeamTaskSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0074, 0x1022, 0x0074, 0x1022, + EVR_CS, "BeamTaskType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0074, 0x1024, 0x0074, 0x1024, + EVR_IS, "RETIRED_BeamOrderIndexTrial", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0074, 0x1025, 0x0074, 0x1025, + EVR_CS, "AutosequenceFlag", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0074, 0x1026, 0x0074, 0x1026, + EVR_FD, "TableTopVerticalAdjustedPosition", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0074, 0x1027, 0x0074, 0x1027, + EVR_FD, "TableTopLongitudinalAdjustedPosition", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0074, 0x1028, 0x0074, 0x1028, + EVR_FD, "TableTopLateralAdjustedPosition", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0074, 0x102a, 0x0074, 0x102a, + EVR_FD, "PatientSupportAdjustedAngle", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0074, 0x102b, 0x0074, 0x102b, + EVR_FD, "TableTopEccentricAdjustedAngle", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0074, 0x102c, 0x0074, 0x102c, + EVR_FD, "TableTopPitchAdjustedAngle", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0074, 0x102d, 0x0074, 0x102d, + EVR_FD, "TableTopRollAdjustedAngle", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0074, 0x1030, 0x0074, 0x1030, + EVR_SQ, "DeliveryVerificationImageSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0074, 0x1032, 0x0074, 0x1032, + EVR_CS, "VerificationImageTiming", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0074, 0x1034, 0x0074, 0x1034, + EVR_CS, "DoubleExposureFlag", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0074, 0x1036, 0x0074, 0x1036, + EVR_CS, "DoubleExposureOrdering", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0074, 0x1038, 0x0074, 0x1038, + EVR_DS, "RETIRED_DoubleExposureMetersetTrial", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0074, 0x103a, 0x0074, 0x103a, + EVR_DS, "RETIRED_DoubleExposureFieldDeltaTrial", 4, 4, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0074, 0x1040, 0x0074, 0x1040, + EVR_SQ, "RelatedReferenceRTImageSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0074, 0x1042, 0x0074, 0x1042, + EVR_SQ, "GeneralMachineVerificationSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0074, 0x1044, 0x0074, 0x1044, + EVR_SQ, "ConventionalMachineVerificationSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0074, 0x1046, 0x0074, 0x1046, + EVR_SQ, "IonMachineVerificationSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0074, 0x1048, 0x0074, 0x1048, + EVR_SQ, "FailedAttributesSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0074, 0x104a, 0x0074, 0x104a, + EVR_SQ, "OverriddenAttributesSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0074, 0x104c, 0x0074, 0x104c, + EVR_SQ, "ConventionalControlPointVerificationSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0074, 0x104e, 0x0074, 0x104e, + EVR_SQ, "IonControlPointVerificationSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0074, 0x1050, 0x0074, 0x1050, + EVR_SQ, "AttributeOccurrenceSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0074, 0x1052, 0x0074, 0x1052, + EVR_AT, "AttributeOccurrencePointer", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0074, 0x1054, 0x0074, 0x1054, + EVR_UL, "AttributeItemSelector", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0074, 0x1056, 0x0074, 0x1056, + EVR_LO, "AttributeOccurrencePrivateCreator", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0074, 0x1057, 0x0074, 0x1057, + EVR_IS, "SelectorSequencePointerItems", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0074, 0x1200, 0x0074, 0x1200, + EVR_CS, "ScheduledProcedureStepPriority", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0074, 0x1202, 0x0074, 0x1202, + EVR_LO, "WorklistLabel", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0074, 0x1204, 0x0074, 0x1204, + EVR_LO, "ProcedureStepLabel", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0074, 0x1210, 0x0074, 0x1210, + EVR_SQ, "ScheduledProcessingParametersSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0074, 0x1212, 0x0074, 0x1212, + EVR_SQ, "PerformedProcessingParametersSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0074, 0x1216, 0x0074, 0x1216, + EVR_SQ, "UnifiedProcedureStepPerformedProcedureSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0074, 0x1220, 0x0074, 0x1220, + EVR_SQ, "RETIRED_RelatedProcedureStepSequence", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0074, 0x1222, 0x0074, 0x1222, + EVR_LO, "RETIRED_ProcedureStepRelationshipType", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0074, 0x1224, 0x0074, 0x1224, + EVR_SQ, "ReplacedProcedureStepSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0074, 0x1230, 0x0074, 0x1230, + EVR_LO, "DeletionLock", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0074, 0x1234, 0x0074, 0x1234, + EVR_AE, "ReceivingAE", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0074, 0x1236, 0x0074, 0x1236, + EVR_AE, "RequestingAE", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0074, 0x1238, 0x0074, 0x1238, + EVR_LT, "ReasonForCancellation", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0074, 0x1242, 0x0074, 0x1242, + EVR_CS, "SCPStatus", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0074, 0x1244, 0x0074, 0x1244, + EVR_CS, "SubscriptionListStatus", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0074, 0x1246, 0x0074, 0x1246, + EVR_CS, "UnifiedProcedureStepListStatus", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0074, 0x1324, 0x0074, 0x1324, + EVR_UL, "BeamOrderIndex", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0074, 0x1338, 0x0074, 0x1338, + EVR_FD, "DoubleExposureMeterset", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0074, 0x133a, 0x0074, 0x133a, + EVR_FD, "DoubleExposureFieldDelta", 4, 4, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0076, 0x0001, 0x0076, 0x0001, + EVR_LO, "ImplantAssemblyTemplateName", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0076, 0x0003, 0x0076, 0x0003, + EVR_LO, "ImplantAssemblyTemplateIssuer", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0076, 0x0006, 0x0076, 0x0006, + EVR_LO, "ImplantAssemblyTemplateVersion", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0076, 0x0008, 0x0076, 0x0008, + EVR_SQ, "ReplacedImplantAssemblyTemplateSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0076, 0x000a, 0x0076, 0x000a, + EVR_CS, "ImplantAssemblyTemplateType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0076, 0x000c, 0x0076, 0x000c, + EVR_SQ, "OriginalImplantAssemblyTemplateSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0076, 0x000e, 0x0076, 0x000e, + EVR_SQ, "DerivationImplantAssemblyTemplateSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0076, 0x0010, 0x0076, 0x0010, + EVR_SQ, "ImplantAssemblyTemplateTargetAnatomySequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0076, 0x0020, 0x0076, 0x0020, + EVR_SQ, "ProcedureTypeCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0076, 0x0030, 0x0076, 0x0030, + EVR_LO, "SurgicalTechnique", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0076, 0x0032, 0x0076, 0x0032, + EVR_SQ, "ComponentTypesSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0076, 0x0034, 0x0076, 0x0034, + EVR_CS, "ComponentTypeCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0076, 0x0036, 0x0076, 0x0036, + EVR_CS, "ExclusiveComponentType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0076, 0x0038, 0x0076, 0x0038, + EVR_CS, "MandatoryComponentType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0076, 0x0040, 0x0076, 0x0040, + EVR_SQ, "ComponentSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0076, 0x0055, 0x0076, 0x0055, + EVR_US, "ComponentID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0076, 0x0060, 0x0076, 0x0060, + EVR_SQ, "ComponentAssemblySequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0076, 0x0070, 0x0076, 0x0070, + EVR_US, "Component1ReferencedID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0076, 0x0080, 0x0076, 0x0080, + EVR_US, "Component1ReferencedMatingFeatureSetID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0076, 0x0090, 0x0076, 0x0090, + EVR_US, "Component1ReferencedMatingFeatureID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0076, 0x00a0, 0x0076, 0x00a0, + EVR_US, "Component2ReferencedID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0076, 0x00b0, 0x0076, 0x00b0, + EVR_US, "Component2ReferencedMatingFeatureSetID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0076, 0x00c0, 0x0076, 0x00c0, + EVR_US, "Component2ReferencedMatingFeatureID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0078, 0x0001, 0x0078, 0x0001, + EVR_LO, "ImplantTemplateGroupName", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0078, 0x0010, 0x0078, 0x0010, + EVR_ST, "ImplantTemplateGroupDescription", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0078, 0x0020, 0x0078, 0x0020, + EVR_LO, "ImplantTemplateGroupIssuer", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0078, 0x0024, 0x0078, 0x0024, + EVR_LO, "ImplantTemplateGroupVersion", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0078, 0x0026, 0x0078, 0x0026, + EVR_SQ, "ReplacedImplantTemplateGroupSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0078, 0x0028, 0x0078, 0x0028, + EVR_SQ, "ImplantTemplateGroupTargetAnatomySequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0078, 0x002a, 0x0078, 0x002a, + EVR_SQ, "ImplantTemplateGroupMembersSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0078, 0x002e, 0x0078, 0x002e, + EVR_US, "ImplantTemplateGroupMemberID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0078, 0x0050, 0x0078, 0x0050, + EVR_FD, "ThreeDImplantTemplateGroupMemberMatchingPoint", 3, 3, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0078, 0x0060, 0x0078, 0x0060, + EVR_FD, "ThreeDImplantTemplateGroupMemberMatchingAxes", 9, 9, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0078, 0x0070, 0x0078, 0x0070, + EVR_SQ, "ImplantTemplateGroupMemberMatching2DCoordinatesSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0078, 0x0090, 0x0078, 0x0090, + EVR_FD, "TwoDImplantTemplateGroupMemberMatchingPoint", 2, 2, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0078, 0x00a0, 0x0078, 0x00a0, + EVR_FD, "TwoDImplantTemplateGroupMemberMatchingAxes", 4, 4, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0078, 0x00b0, 0x0078, 0x00b0, + EVR_SQ, "ImplantTemplateGroupVariationDimensionSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0078, 0x00b2, 0x0078, 0x00b2, + EVR_LO, "ImplantTemplateGroupVariationDimensionName", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0078, 0x00b4, 0x0078, 0x00b4, + EVR_SQ, "ImplantTemplateGroupVariationDimensionRankSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0078, 0x00b6, 0x0078, 0x00b6, + EVR_US, "ReferencedImplantTemplateGroupMemberID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0078, 0x00b8, 0x0078, 0x00b8, + EVR_US, "ImplantTemplateGroupVariationDimensionRank", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0080, 0x0001, 0x0080, 0x0001, + EVR_SQ, "SurfaceScanAcquisitionTypeCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0080, 0x0002, 0x0080, 0x0002, + EVR_SQ, "SurfaceScanModeCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0080, 0x0003, 0x0080, 0x0003, + EVR_SQ, "RegistrationMethodCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0080, 0x0004, 0x0080, 0x0004, + EVR_FD, "ShotDurationTime", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0080, 0x0005, 0x0080, 0x0005, + EVR_FD, "ShotOffsetTime", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0080, 0x0006, 0x0080, 0x0006, + EVR_US, "SurfacePointPresentationValueData", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0080, 0x0007, 0x0080, 0x0007, + EVR_US, "SurfacePointColorCIELabValueData", 3, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0080, 0x0008, 0x0080, 0x0008, + EVR_SQ, "UVMappingSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0080, 0x0009, 0x0080, 0x0009, + EVR_SH, "TextureLabel", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0080, 0x0010, 0x0080, 0x0010, + EVR_OF, "UValueData", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0080, 0x0011, 0x0080, 0x0011, + EVR_OF, "VValueData", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0080, 0x0012, 0x0080, 0x0012, + EVR_SQ, "ReferencedTextureSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0080, 0x0013, 0x0080, 0x0013, + EVR_SQ, "ReferencedSurfaceDataSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } +#ifdef ENABLE_PRIVATE_TAGS + , { 0x0087, 0x0010, 0x0087, 0x0010, + EVR_CS, "MediaType", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "1.2.840.113708.794.1.1.2.0" } + , { 0x0087, 0x0020, 0x0087, 0x0020, + EVR_CS, "MediaLocation", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "1.2.840.113708.794.1.1.2.0" } + , { 0x0087, 0x0050, 0x0087, 0x0050, + EVR_IS, "EstimatedRetrieveTime", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "1.2.840.113708.794.1.1.2.0" } +#endif + , { 0x0088, 0x0130, 0x0088, 0x0130, + EVR_SH, "StorageMediaFileSetID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0088, 0x0140, 0x0088, 0x0140, + EVR_UI, "StorageMediaFileSetUID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0088, 0x0200, 0x0088, 0x0200, + EVR_SQ, "IconImageSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0088, 0x0904, 0x0088, 0x0904, + EVR_LO, "RETIRED_TopicTitle", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0088, 0x0906, 0x0088, 0x0906, + EVR_ST, "RETIRED_TopicSubject", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0088, 0x0910, 0x0088, 0x0910, + EVR_LO, "RETIRED_TopicAuthor", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0088, 0x0912, 0x0088, 0x0912, + EVR_LO, "RETIRED_TopicKeywords", 1, 32, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } +#ifdef ENABLE_PRIVATE_TAGS + , { 0x0089, 0x0010, 0x0089, 0x0010, + EVR_SQ, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "DIDI TO PCR 1.1" } + , { 0x0095, 0x0001, 0x0095, 0x0001, + EVR_LT, "ExaminationFolderID", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIENET" } + , { 0x0095, 0x0004, 0x0095, 0x0004, + EVR_UL, "FolderReportedStatus", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIENET" } + , { 0x0095, 0x0005, 0x0095, 0x0005, + EVR_LT, "FolderReportingRadiologist", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIENET" } + , { 0x0095, 0x0007, 0x0095, 0x0007, + EVR_LT, "SIENETISAPLA", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIENET" } + , { 0x0099, 0x0002, 0x0099, 0x0002, + EVR_UL, "DataObjectAttributes", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIENET" } + , { 0x00e1, 0x0001, 0x00e1, 0x0001, + EVR_US, "DataDictionaryVersion", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "ELSCINT1" } + , { 0x00e1, 0x0014, 0x00e1, 0x0014, + EVR_LT, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "ELSCINT1" } + , { 0x00e1, 0x0022, 0x00e1, 0x0022, + EVR_DS, "Unknown", 2, 2, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "ELSCINT1" } + , { 0x00e1, 0x0023, 0x00e1, 0x0023, + EVR_DS, "Unknown", 2, 2, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "ELSCINT1" } + , { 0x00e1, 0x0024, 0x00e1, 0x0024, + EVR_LT, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "ELSCINT1" } + , { 0x00e1, 0x0025, 0x00e1, 0x0025, + EVR_LT, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "ELSCINT1" } + , { 0x00e1, 0x0040, 0x00e1, 0x0040, + EVR_SH, "OffsetFromCTMRImages", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "ELSCINT1" } +#endif + , { 0x0100, 0x0410, 0x0100, 0x0410, + EVR_CS, "SOPInstanceStatus", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0100, 0x0420, 0x0100, 0x0420, + EVR_DT, "SOPAuthorizationDateTime", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0100, 0x0424, 0x0100, 0x0424, + EVR_LT, "SOPAuthorizationComment", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0100, 0x0426, 0x0100, 0x0426, + EVR_LO, "AuthorizationEquipmentCertificationNumber", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } +#ifdef ENABLE_PRIVATE_TAGS + , { 0x0135, 0x0010, 0x0135, 0x0010, + EVR_LO, "UltrasoundScannerName", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SONOWAND AS" } + , { 0x0135, 0x0011, 0x0135, 0x0011, + EVR_LO, "TransducerSerial", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SONOWAND AS" } + , { 0x0135, 0x0012, 0x0135, 0x0012, + EVR_LO, "ProbeApplication", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SONOWAND AS" } + , { 0x0193, 0x0002, 0x0193, 0x0002, + EVR_DS, "RISKey", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS ISI" } + , { 0x0307, 0x0001, 0x0307, 0x0001, + EVR_UN, "RISWorklistIMGEF", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS ISI" } + , { 0x0309, 0x0001, 0x0309, 0x0001, + EVR_UN, "RISReportIMGEF", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS ISI" } +#endif + , { 0x0400, 0x0005, 0x0400, 0x0005, + EVR_US, "MACIDNumber", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0400, 0x0010, 0x0400, 0x0010, + EVR_UI, "MACCalculationTransferSyntaxUID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0400, 0x0015, 0x0400, 0x0015, + EVR_CS, "MACAlgorithm", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0400, 0x0020, 0x0400, 0x0020, + EVR_AT, "DataElementsSigned", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0400, 0x0100, 0x0400, 0x0100, + EVR_UI, "DigitalSignatureUID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0400, 0x0105, 0x0400, 0x0105, + EVR_DT, "DigitalSignatureDateTime", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0400, 0x0110, 0x0400, 0x0110, + EVR_CS, "CertificateType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0400, 0x0115, 0x0400, 0x0115, + EVR_OB, "CertificateOfSigner", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0400, 0x0120, 0x0400, 0x0120, + EVR_OB, "Signature", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0400, 0x0305, 0x0400, 0x0305, + EVR_CS, "CertifiedTimestampType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0400, 0x0310, 0x0400, 0x0310, + EVR_OB, "CertifiedTimestamp", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0400, 0x0401, 0x0400, 0x0401, + EVR_SQ, "DigitalSignaturePurposeCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0400, 0x0402, 0x0400, 0x0402, + EVR_SQ, "ReferencedDigitalSignatureSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0400, 0x0403, 0x0400, 0x0403, + EVR_SQ, "ReferencedSOPInstanceMACSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0400, 0x0404, 0x0400, 0x0404, + EVR_OB, "MAC", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0400, 0x0500, 0x0400, 0x0500, + EVR_SQ, "EncryptedAttributesSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0400, 0x0510, 0x0400, 0x0510, + EVR_UI, "EncryptedContentTransferSyntaxUID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0400, 0x0520, 0x0400, 0x0520, + EVR_OB, "EncryptedContent", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0400, 0x0550, 0x0400, 0x0550, + EVR_SQ, "ModifiedAttributesSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0400, 0x0561, 0x0400, 0x0561, + EVR_SQ, "OriginalAttributesSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0400, 0x0562, 0x0400, 0x0562, + EVR_DT, "AttributeModificationDateTime", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0400, 0x0563, 0x0400, 0x0563, + EVR_LO, "ModifyingSystem", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0400, 0x0564, 0x0400, 0x0564, + EVR_LO, "SourceOfPreviousValues", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0400, 0x0565, 0x0400, 0x0565, + EVR_CS, "ReasonForTheAttributeModification", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } +#ifdef ENABLE_PRIVATE_TAGS + , { 0x0601, 0x0000, 0x0601, 0x0000, + EVR_SH, "ImplementationVersion", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "ELSCINT1" } + , { 0x0601, 0x0020, 0x0601, 0x0020, + EVR_DS, "RelativeTablePosition", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "ELSCINT1" } + , { 0x0601, 0x0021, 0x0601, 0x0021, + EVR_DS, "RelativeTableHeight", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "ELSCINT1" } + , { 0x0601, 0x0030, 0x0601, 0x0030, + EVR_SH, "SurviewDirection", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "ELSCINT1" } + , { 0x0601, 0x0031, 0x0601, 0x0031, + EVR_DS, "SurviewLength", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "ELSCINT1" } + , { 0x0601, 0x0050, 0x0601, 0x0050, + EVR_SH, "ImageViewType", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "ELSCINT1" } + , { 0x0601, 0x0070, 0x0601, 0x0070, + EVR_DS, "BatchNumber", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "ELSCINT1" } + , { 0x0601, 0x0071, 0x0601, 0x0071, + EVR_DS, "BatchSize", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "ELSCINT1" } + , { 0x0601, 0x0072, 0x0601, 0x0072, + EVR_DS, "BatchSliceNumber", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "ELSCINT1" } +#endif + , { 0x1000, 0x0010, 0x1000, 0x0010, + EVR_US, "RETIRED_EscapeTriplet", 3, 3, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x1000, 0x0011, 0x1000, 0x0011, + EVR_US, "RETIRED_RunLengthTriplet", 3, 3, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x1000, 0x0012, 0x1000, 0x0012, + EVR_US, "RETIRED_HuffmanTableSize", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x1000, 0x0013, 0x1000, 0x0013, + EVR_US, "RETIRED_HuffmanTableTriplet", 3, 3, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x1000, 0x0014, 0x1000, 0x0014, + EVR_US, "RETIRED_ShiftTableSize", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x1000, 0x0015, 0x1000, 0x0015, + EVR_US, "RETIRED_ShiftTableTriplet", 3, 3, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x1010, 0x0004, 0x1010, 0x0004, + EVR_US, "RETIRED_ZonalMap", 1, -1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } +#ifdef ENABLE_PRIVATE_TAGS + , { 0x1369, 0x0000, 0x1369, 0x0000, + EVR_US, "Unknown", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "AEGIS_DICOM_2.00" } +#endif + , { 0x2000, 0x0010, 0x2000, 0x0010, + EVR_IS, "NumberOfCopies", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x2000, 0x001e, 0x2000, 0x001e, + EVR_SQ, "PrinterConfigurationSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x2000, 0x0020, 0x2000, 0x0020, + EVR_CS, "PrintPriority", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x2000, 0x0030, 0x2000, 0x0030, + EVR_CS, "MediumType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x2000, 0x0040, 0x2000, 0x0040, + EVR_CS, "FilmDestination", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x2000, 0x0050, 0x2000, 0x0050, + EVR_LO, "FilmSessionLabel", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x2000, 0x0060, 0x2000, 0x0060, + EVR_IS, "MemoryAllocation", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x2000, 0x0061, 0x2000, 0x0061, + EVR_IS, "MaximumMemoryAllocation", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x2000, 0x0062, 0x2000, 0x0062, + EVR_CS, "RETIRED_ColorImagePrintingFlag", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x2000, 0x0063, 0x2000, 0x0063, + EVR_CS, "RETIRED_CollationFlag", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x2000, 0x0065, 0x2000, 0x0065, + EVR_CS, "RETIRED_AnnotationFlag", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x2000, 0x0067, 0x2000, 0x0067, + EVR_CS, "RETIRED_ImageOverlayFlag", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x2000, 0x0069, 0x2000, 0x0069, + EVR_CS, "RETIRED_PresentationLUTFlag", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x2000, 0x006a, 0x2000, 0x006a, + EVR_CS, "RETIRED_ImageBoxPresentationLUTFlag", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x2000, 0x00a0, 0x2000, 0x00a0, + EVR_US, "MemoryBitDepth", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x2000, 0x00a1, 0x2000, 0x00a1, + EVR_US, "PrintingBitDepth", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x2000, 0x00a2, 0x2000, 0x00a2, + EVR_SQ, "MediaInstalledSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x2000, 0x00a4, 0x2000, 0x00a4, + EVR_SQ, "OtherMediaAvailableSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x2000, 0x00a8, 0x2000, 0x00a8, + EVR_SQ, "SupportedImageDisplayFormatsSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x2000, 0x0500, 0x2000, 0x0500, + EVR_SQ, "ReferencedFilmBoxSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x2000, 0x0510, 0x2000, 0x0510, + EVR_SQ, "RETIRED_ReferencedStoredPrintSequence", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } +#ifdef ENABLE_PRIVATE_TAGS + , { 0x2001, 0x0001, 0x2001, 0x0001, + EVR_FL, "ChemicalShift", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Philips Imaging DD 001" } + , { 0x2001, 0x0001, 0x2001, 0x0001, + EVR_FL, "ChemicalShift", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS IMAGING DD 001" } + , { 0x2001, 0x0002, 0x2001, 0x0002, + EVR_IS, "ChemicalShiftNumberMR", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Philips Imaging DD 001" } + , { 0x2001, 0x0002, 0x2001, 0x0002, + EVR_IS, "ChemicalShiftNumberMR", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS IMAGING DD 001" } + , { 0x2001, 0x0003, 0x2001, 0x0003, + EVR_FL, "DiffusionBFactor", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Philips Imaging DD 001" } + , { 0x2001, 0x0003, 0x2001, 0x0003, + EVR_FL, "DiffusionBFactor", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS IMAGING DD 001" } + , { 0x2001, 0x0004, 0x2001, 0x0004, + EVR_CS, "DiffusionDirection", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Philips Imaging DD 001" } + , { 0x2001, 0x0004, 0x2001, 0x0004, + EVR_CS, "DiffusionDirection", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS IMAGING DD 001" } + , { 0x2001, 0x0006, 0x2001, 0x0006, + EVR_CS, "ImageEnhanced", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Philips Imaging DD 001" } + , { 0x2001, 0x0006, 0x2001, 0x0006, + EVR_CS, "ImageEnhanced", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS IMAGING DD 001" } + , { 0x2001, 0x0007, 0x2001, 0x0007, + EVR_CS, "ImageTypeEDES", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Philips Imaging DD 001" } + , { 0x2001, 0x0007, 0x2001, 0x0007, + EVR_CS, "ImageTypeEDES", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS IMAGING DD 001" } + , { 0x2001, 0x0008, 0x2001, 0x0008, + EVR_IS, "PhaseNumber", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Philips Imaging DD 001" } + , { 0x2001, 0x0008, 0x2001, 0x0008, + EVR_IS, "PhaseNumber", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS IMAGING DD 001" } + , { 0x2001, 0x0009, 0x2001, 0x0009, + EVR_FL, "ImagePrepulseDelay", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Philips Imaging DD 001" } + , { 0x2001, 0x0009, 0x2001, 0x0009, + EVR_FL, "ImagePrepulseDelay", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS IMAGING DD 001" } + , { 0x2001, 0x000a, 0x2001, 0x000a, + EVR_IS, "SliceNumberMR", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Philips Imaging DD 001" } + , { 0x2001, 0x000a, 0x2001, 0x000a, + EVR_IS, "SliceNumberMR", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS IMAGING DD 001" } + , { 0x2001, 0x000b, 0x2001, 0x000b, + EVR_CS, "SliceOrientation", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Philips Imaging DD 001" } + , { 0x2001, 0x000b, 0x2001, 0x000b, + EVR_CS, "SliceOrientation", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS IMAGING DD 001" } + , { 0x2001, 0x000c, 0x2001, 0x000c, + EVR_CS, "ArrhythmiaRejection", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Philips Imaging DD 001" } + , { 0x2001, 0x000c, 0x2001, 0x000c, + EVR_CS, "ArrhythmiaRejection", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS IMAGING DD 001" } + , { 0x2001, 0x000e, 0x2001, 0x000e, + EVR_CS, "CardiacCycled", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Philips Imaging DD 001" } + , { 0x2001, 0x000e, 0x2001, 0x000e, + EVR_CS, "CardiacCycled", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS IMAGING DD 001" } + , { 0x2001, 0x000f, 0x2001, 0x000f, + EVR_SS, "CardiacGateWidth", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Philips Imaging DD 001" } + , { 0x2001, 0x000f, 0x2001, 0x000f, + EVR_SS, "CardiacGateWidth", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS IMAGING DD 001" } + , { 0x2001, 0x0010, 0x2001, 0x0010, + EVR_CS, "CardiacSync", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Philips Imaging DD 001" } + , { 0x2001, 0x0010, 0x2001, 0x0010, + EVR_CS, "CardiacSync", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS IMAGING DD 001" } + , { 0x2001, 0x0011, 0x2001, 0x0011, + EVR_FL, "DiffusionEchoTime", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Philips Imaging DD 001" } + , { 0x2001, 0x0011, 0x2001, 0x0011, + EVR_FL, "DiffusionEchoTime", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS IMAGING DD 001" } + , { 0x2001, 0x0012, 0x2001, 0x0012, + EVR_CS, "DynamicSeries", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Philips Imaging DD 001" } + , { 0x2001, 0x0012, 0x2001, 0x0012, + EVR_CS, "DynamicSeries", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS IMAGING DD 001" } + , { 0x2001, 0x0013, 0x2001, 0x0013, + EVR_SL, "EPIFactor", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Philips Imaging DD 001" } + , { 0x2001, 0x0013, 0x2001, 0x0013, + EVR_SL, "EPIFactor", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS IMAGING DD 001" } + , { 0x2001, 0x0014, 0x2001, 0x0014, + EVR_SL, "NumberOfEchoes", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Philips Imaging DD 001" } + , { 0x2001, 0x0014, 0x2001, 0x0014, + EVR_SL, "NumberOfEchoes", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS IMAGING DD 001" } + , { 0x2001, 0x0015, 0x2001, 0x0015, + EVR_SS, "NumberOfLocations", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Philips Imaging DD 001" } + , { 0x2001, 0x0015, 0x2001, 0x0015, + EVR_SS, "NumberOfLocations", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS IMAGING DD 001" } + , { 0x2001, 0x0016, 0x2001, 0x0016, + EVR_SS, "NumberOfPCDirections", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Philips Imaging DD 001" } + , { 0x2001, 0x0016, 0x2001, 0x0016, + EVR_SS, "NumberOfPCDirections", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS IMAGING DD 001" } + , { 0x2001, 0x0017, 0x2001, 0x0017, + EVR_SL, "NumberOfPhasesMR", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Philips Imaging DD 001" } + , { 0x2001, 0x0017, 0x2001, 0x0017, + EVR_SL, "NumberOfPhasesMR", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS IMAGING DD 001" } + , { 0x2001, 0x0018, 0x2001, 0x0018, + EVR_SL, "NumberOfSlicesMR", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Philips Imaging DD 001" } + , { 0x2001, 0x0018, 0x2001, 0x0018, + EVR_SL, "NumberOfSlicesMR", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS IMAGING DD 001" } + , { 0x2001, 0x0019, 0x2001, 0x0019, + EVR_CS, "PartialMatrixScanned", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Philips Imaging DD 001" } + , { 0x2001, 0x0019, 0x2001, 0x0019, + EVR_CS, "PartialMatrixScanned", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS IMAGING DD 001" } + , { 0x2001, 0x001a, 0x2001, 0x001a, + EVR_FL, "PCVelocity", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Philips Imaging DD 001" } + , { 0x2001, 0x001a, 0x2001, 0x001a, + EVR_FL, "PCVelocity", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS IMAGING DD 001" } + , { 0x2001, 0x001b, 0x2001, 0x001b, + EVR_FL, "PrepulseDelay", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Philips Imaging DD 001" } + , { 0x2001, 0x001b, 0x2001, 0x001b, + EVR_FL, "PrepulseDelay", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS IMAGING DD 001" } + , { 0x2001, 0x001c, 0x2001, 0x001c, + EVR_CS, "PrepulseType", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Philips Imaging DD 001" } + , { 0x2001, 0x001c, 0x2001, 0x001c, + EVR_CS, "PrepulseType", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS IMAGING DD 001" } + , { 0x2001, 0x001d, 0x2001, 0x001d, + EVR_IS, "ReconstructionNumberMR", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Philips Imaging DD 001" } + , { 0x2001, 0x001d, 0x2001, 0x001d, + EVR_IS, "ReconstructionNumberMR", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS IMAGING DD 001" } + , { 0x2001, 0x001f, 0x2001, 0x001f, + EVR_CS, "RespirationSync", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Philips Imaging DD 001" } + , { 0x2001, 0x001f, 0x2001, 0x001f, + EVR_CS, "RespirationSync", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS IMAGING DD 001" } + , { 0x2001, 0x0020, 0x2001, 0x0020, + EVR_LO, "ScanningTechnique", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Philips Imaging DD 001" } + , { 0x2001, 0x0020, 0x2001, 0x0020, + EVR_LO, "ScanningTechnique", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS IMAGING DD 001" } + , { 0x2001, 0x0021, 0x2001, 0x0021, + EVR_CS, "SPIR", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Philips Imaging DD 001" } + , { 0x2001, 0x0021, 0x2001, 0x0021, + EVR_CS, "SPIR", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS IMAGING DD 001" } + , { 0x2001, 0x0022, 0x2001, 0x0022, + EVR_FL, "WaterFatShift", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Philips Imaging DD 001" } + , { 0x2001, 0x0022, 0x2001, 0x0022, + EVR_FL, "WaterFatShift", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS IMAGING DD 001" } + , { 0x2001, 0x0023, 0x2001, 0x0023, + EVR_DS, "FlipAnglePhilips", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Philips Imaging DD 001" } + , { 0x2001, 0x0023, 0x2001, 0x0023, + EVR_DS, "FlipAnglePhilips", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS IMAGING DD 001" } + , { 0x2001, 0x0024, 0x2001, 0x0024, + EVR_CS, "SeriesIsInteractive", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Philips Imaging DD 001" } + , { 0x2001, 0x0024, 0x2001, 0x0024, + EVR_CS, "SeriesIsInteractive", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS IMAGING DD 001" } + , { 0x2001, 0x0025, 0x2001, 0x0025, + EVR_SH, "EchoTimeDisplayMR", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Philips Imaging DD 001" } + , { 0x2001, 0x0025, 0x2001, 0x0025, + EVR_SH, "EchoTimeDisplayMR", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS IMAGING DD 001" } + , { 0x2001, 0x0026, 0x2001, 0x0026, + EVR_CS, "PresentationStateSubtractionActive", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Philips Imaging DD 001" } + , { 0x2001, 0x0026, 0x2001, 0x0026, + EVR_CS, "PresentationStateSubtractionActive", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS IMAGING DD 001" } + , { 0x2001, 0x002d, 0x2001, 0x002d, + EVR_SS, "StackNumberOfSlices", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Philips Imaging DD 001" } + , { 0x2001, 0x002d, 0x2001, 0x002d, + EVR_SS, "StackNumberOfSlices", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS IMAGING DD 001" } + , { 0x2001, 0x0032, 0x2001, 0x0032, + EVR_FL, "StackRadialAngle", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Philips Imaging DD 001" } + , { 0x2001, 0x0032, 0x2001, 0x0032, + EVR_FL, "StackRadialAngle", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS IMAGING DD 001" } + , { 0x2001, 0x0033, 0x2001, 0x0033, + EVR_CS, "StackRadialAxis", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Philips Imaging DD 001" } + , { 0x2001, 0x0033, 0x2001, 0x0033, + EVR_CS, "StackRadialAxis", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS IMAGING DD 001" } + , { 0x2001, 0x0035, 0x2001, 0x0035, + EVR_SS, "StackSliceNumber", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Philips Imaging DD 001" } + , { 0x2001, 0x0035, 0x2001, 0x0035, + EVR_SS, "StackSliceNumber", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS IMAGING DD 001" } + , { 0x2001, 0x0036, 0x2001, 0x0036, + EVR_CS, "StackType", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Philips Imaging DD 001" } + , { 0x2001, 0x0036, 0x2001, 0x0036, + EVR_CS, "StackType", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS IMAGING DD 001" } + , { 0x2001, 0x003f, 0x2001, 0x003f, + EVR_CS, "ZoomMode", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Philips Imaging DD 001" } + , { 0x2001, 0x003f, 0x2001, 0x003f, + EVR_CS, "ZoomMode", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS IMAGING DD 001" } + , { 0x2001, 0x0058, 0x2001, 0x0058, + EVR_UL, "ContrastTransferTaste", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Philips Imaging DD 001" } + , { 0x2001, 0x0058, 0x2001, 0x0058, + EVR_UL, "ContrastTransferTaste", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS IMAGING DD 001" } + , { 0x2001, 0x005f, 0x2001, 0x005f, + EVR_SQ, "StackSequence", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Philips Imaging DD 001" } + , { 0x2001, 0x005f, 0x2001, 0x005f, + EVR_SQ, "StackSequence", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS IMAGING DD 001" } + , { 0x2001, 0x0060, 0x2001, 0x0060, + EVR_SL, "NumberOfStacks", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Philips Imaging DD 001" } + , { 0x2001, 0x0060, 0x2001, 0x0060, + EVR_SL, "NumberOfStacks", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS IMAGING DD 001" } + , { 0x2001, 0x0061, 0x2001, 0x0061, + EVR_CS, "SeriesTransmitted", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Philips Imaging DD 001" } + , { 0x2001, 0x0061, 0x2001, 0x0061, + EVR_CS, "SeriesTransmitted", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS IMAGING DD 001" } + , { 0x2001, 0x0062, 0x2001, 0x0062, + EVR_CS, "SeriesCommitted", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Philips Imaging DD 001" } + , { 0x2001, 0x0062, 0x2001, 0x0062, + EVR_CS, "SeriesCommitted", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS IMAGING DD 001" } + , { 0x2001, 0x0063, 0x2001, 0x0063, + EVR_CS, "ExaminationSource", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Philips Imaging DD 001" } + , { 0x2001, 0x0063, 0x2001, 0x0063, + EVR_CS, "ExaminationSource", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS IMAGING DD 001" } + , { 0x2001, 0x0067, 0x2001, 0x0067, + EVR_CS, "LinearPresentationGLTrafoShapeSub", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Philips Imaging DD 001" } + , { 0x2001, 0x0067, 0x2001, 0x0067, + EVR_CS, "LinearPresentationGLTrafoShapeSub", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS IMAGING DD 001" } + , { 0x2001, 0x0077, 0x2001, 0x0077, + EVR_CS, "GLTrafoType", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Philips Imaging DD 001" } + , { 0x2001, 0x0077, 0x2001, 0x0077, + EVR_CS, "GLTrafoType", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS IMAGING DD 001" } + , { 0x2001, 0x007b, 0x2001, 0x007b, + EVR_IS, "AcquisitionNumber", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Philips Imaging DD 001" } + , { 0x2001, 0x007b, 0x2001, 0x007b, + EVR_IS, "AcquisitionNumber", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS IMAGING DD 001" } + , { 0x2001, 0x0081, 0x2001, 0x0081, + EVR_IS, "NumberOfDynamicScans", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Philips Imaging DD 001" } + , { 0x2001, 0x0081, 0x2001, 0x0081, + EVR_IS, "NumberOfDynamicScans", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS IMAGING DD 001" } + , { 0x2001, 0x009f, 0x2001, 0x009f, + EVR_US, "PixelProcessingKernelSize", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Philips Imaging DD 001" } + , { 0x2001, 0x009f, 0x2001, 0x009f, + EVR_US, "PixelProcessingKernelSize", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS IMAGING DD 001" } + , { 0x2001, 0x00a1, 0x2001, 0x00a1, + EVR_CS, "IsRawImage", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Philips Imaging DD 001" } + , { 0x2001, 0x00a1, 0x2001, 0x00a1, + EVR_CS, "IsRawImage", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS IMAGING DD 001" } + , { 0x2001, 0x00f1, 0x2001, 0x00f1, + EVR_FL, "ProspectiveMotionCorrection", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Philips Imaging DD 001" } + , { 0x2001, 0x00f1, 0x2001, 0x00f1, + EVR_FL, "ProspectiveMotionCorrection", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS IMAGING DD 001" } + , { 0x2001, 0x00f2, 0x2001, 0x00f2, + EVR_FL, "RetrospectiveMotionCorrection", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Philips Imaging DD 001" } + , { 0x2001, 0x00f2, 0x2001, 0x00f2, + EVR_FL, "RetrospectiveMotionCorrection", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS IMAGING DD 001" } + , { 0x2005, 0x0002, 0x2005, 0x0002, + EVR_SQ, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Philips MR Imaging DD 005" } + , { 0x2005, 0x0005, 0x2005, 0x0005, + EVR_CS, "SynergyReconstructionType", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Philips MR Imaging DD 001" } + , { 0x2005, 0x0005, 0x2005, 0x0005, + EVR_CS, "SynergyReconstructionType", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR IMAGING DD 001" } + , { 0x2005, 0x001e, 0x2005, 0x001e, + EVR_SH, "MIPProtocol", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Philips MR Imaging DD 001" } + , { 0x2005, 0x001e, 0x2005, 0x001e, + EVR_SH, "MIPProtocol", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR IMAGING DD 001" } + , { 0x2005, 0x001f, 0x2005, 0x001f, + EVR_SH, "MPRProtocol", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Philips MR Imaging DD 001" } + , { 0x2005, 0x001f, 0x2005, 0x001f, + EVR_SH, "MPRProtocol", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR IMAGING DD 001" } + , { 0x2005, 0x0020, 0x2005, 0x0020, + EVR_SL, "NumberOfChemicalShifts", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Philips MR Imaging DD 001" } + , { 0x2005, 0x0020, 0x2005, 0x0020, + EVR_SL, "NumberOfChemicalShifts", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR IMAGING DD 001" } + , { 0x2005, 0x002d, 0x2005, 0x002d, + EVR_SS, "NumberOfStackSlices", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Philips MR Imaging DD 001" } + , { 0x2005, 0x002d, 0x2005, 0x002d, + EVR_SS, "NumberOfStackSlices", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR IMAGING DD 001" } + , { 0x2005, 0x0083, 0x2005, 0x0083, + EVR_SQ, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Philips MR Imaging DD 001" } + , { 0x2005, 0x0083, 0x2005, 0x0083, + EVR_SQ, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR IMAGING DD 001" } + , { 0x2005, 0x00a1, 0x2005, 0x00a1, + EVR_CS, "SyncraScanType", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Philips MR Imaging DD 001" } + , { 0x2005, 0x00a1, 0x2005, 0x00a1, + EVR_CS, "SyncraScanType", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR IMAGING DD 001" } + , { 0x2005, 0x00b0, 0x2005, 0x00b0, + EVR_FL, "DiffusionDirectionRL", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Philips MR Imaging DD 001" } + , { 0x2005, 0x00b0, 0x2005, 0x00b0, + EVR_FL, "DiffusionDirectionRL", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR IMAGING DD 001" } + , { 0x2005, 0x00b1, 0x2005, 0x00b1, + EVR_FL, "DiffusionDirectionAP", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Philips MR Imaging DD 001" } + , { 0x2005, 0x00b1, 0x2005, 0x00b1, + EVR_FL, "DiffusionDirectionAP", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR IMAGING DD 001" } + , { 0x2005, 0x00b2, 0x2005, 0x00b2, + EVR_FL, "DiffusionDirectionFH", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Philips MR Imaging DD 001" } + , { 0x2005, 0x00b2, 0x2005, 0x00b2, + EVR_FL, "DiffusionDirectionFH", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR IMAGING DD 001" } +#endif + , { 0x2010, 0x0010, 0x2010, 0x0010, + EVR_ST, "ImageDisplayFormat", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x2010, 0x0030, 0x2010, 0x0030, + EVR_CS, "AnnotationDisplayFormatID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x2010, 0x0040, 0x2010, 0x0040, + EVR_CS, "FilmOrientation", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x2010, 0x0050, 0x2010, 0x0050, + EVR_CS, "FilmSizeID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x2010, 0x0052, 0x2010, 0x0052, + EVR_CS, "PrinterResolutionID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x2010, 0x0054, 0x2010, 0x0054, + EVR_CS, "DefaultPrinterResolutionID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x2010, 0x0060, 0x2010, 0x0060, + EVR_CS, "MagnificationType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x2010, 0x0080, 0x2010, 0x0080, + EVR_CS, "SmoothingType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x2010, 0x00a6, 0x2010, 0x00a6, + EVR_CS, "DefaultMagnificationType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x2010, 0x00a7, 0x2010, 0x00a7, + EVR_CS, "OtherMagnificationTypesAvailable", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x2010, 0x00a8, 0x2010, 0x00a8, + EVR_CS, "DefaultSmoothingType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x2010, 0x00a9, 0x2010, 0x00a9, + EVR_CS, "OtherSmoothingTypesAvailable", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x2010, 0x0100, 0x2010, 0x0100, + EVR_CS, "BorderDensity", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x2010, 0x0110, 0x2010, 0x0110, + EVR_CS, "EmptyImageDensity", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x2010, 0x0120, 0x2010, 0x0120, + EVR_US, "MinDensity", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x2010, 0x0130, 0x2010, 0x0130, + EVR_US, "MaxDensity", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x2010, 0x0140, 0x2010, 0x0140, + EVR_CS, "Trim", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x2010, 0x0150, 0x2010, 0x0150, + EVR_ST, "ConfigurationInformation", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x2010, 0x0152, 0x2010, 0x0152, + EVR_LT, "ConfigurationInformationDescription", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x2010, 0x0154, 0x2010, 0x0154, + EVR_IS, "MaximumCollatedFilms", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x2010, 0x015e, 0x2010, 0x015e, + EVR_US, "Illumination", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x2010, 0x0160, 0x2010, 0x0160, + EVR_US, "ReflectedAmbientLight", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x2010, 0x0376, 0x2010, 0x0376, + EVR_DS, "PrinterPixelSpacing", 2, 2, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x2010, 0x0500, 0x2010, 0x0500, + EVR_SQ, "ReferencedFilmSessionSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x2010, 0x0510, 0x2010, 0x0510, + EVR_SQ, "ReferencedImageBoxSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x2010, 0x0520, 0x2010, 0x0520, + EVR_SQ, "ReferencedBasicAnnotationBoxSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } +#ifdef ENABLE_PRIVATE_TAGS + , { 0x2011, 0x0011, 0x2011, 0x0011, + EVR_CS, "ImagePositionSpecifyingFlag", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "FDMS 1.0" } +#endif + , { 0x2020, 0x0010, 0x2020, 0x0010, + EVR_US, "ImageBoxPosition", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x2020, 0x0020, 0x2020, 0x0020, + EVR_CS, "Polarity", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x2020, 0x0030, 0x2020, 0x0030, + EVR_DS, "RequestedImageSize", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x2020, 0x0040, 0x2020, 0x0040, + EVR_CS, "RequestedDecimateCropBehavior", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x2020, 0x0050, 0x2020, 0x0050, + EVR_CS, "RequestedResolutionID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x2020, 0x00a0, 0x2020, 0x00a0, + EVR_CS, "RequestedImageSizeFlag", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x2020, 0x00a2, 0x2020, 0x00a2, + EVR_CS, "DecimateCropResult", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x2020, 0x0110, 0x2020, 0x0110, + EVR_SQ, "BasicGrayscaleImageSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x2020, 0x0111, 0x2020, 0x0111, + EVR_SQ, "BasicColorImageSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x2020, 0x0130, 0x2020, 0x0130, + EVR_SQ, "RETIRED_ReferencedImageOverlayBoxSequence", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x2020, 0x0140, 0x2020, 0x0140, + EVR_SQ, "RETIRED_ReferencedVOILUTBoxSequence", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x2030, 0x0010, 0x2030, 0x0010, + EVR_US, "AnnotationPosition", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x2030, 0x0020, 0x2030, 0x0020, + EVR_LO, "TextString", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x2040, 0x0010, 0x2040, 0x0010, + EVR_SQ, "RETIRED_ReferencedOverlayPlaneSequence", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x2040, 0x0011, 0x2040, 0x0011, + EVR_US, "RETIRED_ReferencedOverlayPlaneGroups", 1, 99, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x2040, 0x0020, 0x2040, 0x0020, + EVR_SQ, "RETIRED_OverlayPixelDataSequence", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x2040, 0x0060, 0x2040, 0x0060, + EVR_CS, "RETIRED_OverlayMagnificationType", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x2040, 0x0070, 0x2040, 0x0070, + EVR_CS, "RETIRED_OverlaySmoothingType", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x2040, 0x0072, 0x2040, 0x0072, + EVR_CS, "RETIRED_OverlayOrImageMagnification", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x2040, 0x0074, 0x2040, 0x0074, + EVR_US, "RETIRED_MagnifyToNumberOfColumns", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x2040, 0x0080, 0x2040, 0x0080, + EVR_CS, "RETIRED_OverlayForegroundDensity", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x2040, 0x0082, 0x2040, 0x0082, + EVR_CS, "RETIRED_OverlayBackgroundDensity", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x2040, 0x0090, 0x2040, 0x0090, + EVR_CS, "RETIRED_OverlayMode", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x2040, 0x0100, 0x2040, 0x0100, + EVR_CS, "RETIRED_ThresholdDensity", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x2040, 0x0500, 0x2040, 0x0500, + EVR_SQ, "RETIRED_ReferencedImageBoxSequenceRetired", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x2050, 0x0010, 0x2050, 0x0010, + EVR_SQ, "PresentationLUTSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x2050, 0x0020, 0x2050, 0x0020, + EVR_CS, "PresentationLUTShape", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x2050, 0x0500, 0x2050, 0x0500, + EVR_SQ, "ReferencedPresentationLUTSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x2100, 0x0010, 0x2100, 0x0010, + EVR_SH, "RETIRED_PrintJobID", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x2100, 0x0020, 0x2100, 0x0020, + EVR_CS, "ExecutionStatus", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x2100, 0x0030, 0x2100, 0x0030, + EVR_CS, "ExecutionStatusInfo", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x2100, 0x0040, 0x2100, 0x0040, + EVR_DA, "CreationDate", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x2100, 0x0050, 0x2100, 0x0050, + EVR_TM, "CreationTime", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x2100, 0x0070, 0x2100, 0x0070, + EVR_AE, "Originator", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x2100, 0x0140, 0x2100, 0x0140, + EVR_AE, "RETIRED_DestinationAE", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x2100, 0x0160, 0x2100, 0x0160, + EVR_SH, "OwnerID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x2100, 0x0170, 0x2100, 0x0170, + EVR_IS, "NumberOfFilms", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x2100, 0x0500, 0x2100, 0x0500, + EVR_SQ, "RETIRED_ReferencedPrintJobSequencePullStoredPrint", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x2110, 0x0010, 0x2110, 0x0010, + EVR_CS, "PrinterStatus", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x2110, 0x0020, 0x2110, 0x0020, + EVR_CS, "PrinterStatusInfo", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x2110, 0x0030, 0x2110, 0x0030, + EVR_LO, "PrinterName", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x2110, 0x0099, 0x2110, 0x0099, + EVR_SH, "RETIRED_PrintQueueID", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x2120, 0x0010, 0x2120, 0x0010, + EVR_CS, "RETIRED_QueueStatus", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x2120, 0x0050, 0x2120, 0x0050, + EVR_SQ, "RETIRED_PrintJobDescriptionSequence", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x2120, 0x0070, 0x2120, 0x0070, + EVR_SQ, "RETIRED_ReferencedPrintJobSequence", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x2130, 0x0010, 0x2130, 0x0010, + EVR_SQ, "RETIRED_PrintManagementCapabilitiesSequence", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x2130, 0x0015, 0x2130, 0x0015, + EVR_SQ, "RETIRED_PrinterCharacteristicsSequence", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x2130, 0x0030, 0x2130, 0x0030, + EVR_SQ, "RETIRED_FilmBoxContentSequence", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x2130, 0x0040, 0x2130, 0x0040, + EVR_SQ, "RETIRED_ImageBoxContentSequence", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x2130, 0x0050, 0x2130, 0x0050, + EVR_SQ, "RETIRED_AnnotationContentSequence", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x2130, 0x0060, 0x2130, 0x0060, + EVR_SQ, "RETIRED_ImageOverlayBoxContentSequence", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x2130, 0x0080, 0x2130, 0x0080, + EVR_SQ, "RETIRED_PresentationLUTContentSequence", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x2130, 0x00a0, 0x2130, 0x00a0, + EVR_SQ, "RETIRED_ProposedStudySequence", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x2130, 0x00c0, 0x2130, 0x00c0, + EVR_SQ, "RETIRED_OriginalImageSequence", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x2200, 0x0001, 0x2200, 0x0001, + EVR_CS, "LabelUsingInformationExtractedFromInstances", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x2200, 0x0002, 0x2200, 0x0002, + EVR_UT, "LabelText", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x2200, 0x0003, 0x2200, 0x0003, + EVR_CS, "LabelStyleSelection", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x2200, 0x0004, 0x2200, 0x0004, + EVR_LT, "MediaDisposition", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x2200, 0x0005, 0x2200, 0x0005, + EVR_LT, "BarcodeValue", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x2200, 0x0006, 0x2200, 0x0006, + EVR_CS, "BarcodeSymbology", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x2200, 0x0007, 0x2200, 0x0007, + EVR_CS, "AllowMediaSplitting", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x2200, 0x0008, 0x2200, 0x0008, + EVR_CS, "IncludeNonDICOMObjects", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x2200, 0x0009, 0x2200, 0x0009, + EVR_CS, "IncludeDisplayApplication", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x2200, 0x000a, 0x2200, 0x000a, + EVR_CS, "PreserveCompositeInstancesAfterMediaCreation", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x2200, 0x000b, 0x2200, 0x000b, + EVR_US, "TotalNumberOfPiecesOfMediaCreated", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x2200, 0x000c, 0x2200, 0x000c, + EVR_LO, "RequestedMediaApplicationProfile", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x2200, 0x000d, 0x2200, 0x000d, + EVR_SQ, "ReferencedStorageMediaSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x2200, 0x000e, 0x2200, 0x000e, + EVR_AT, "FailureAttributes", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x2200, 0x000f, 0x2200, 0x000f, + EVR_CS, "AllowLossyCompression", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x2200, 0x0020, 0x2200, 0x0020, + EVR_CS, "RequestPriority", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3002, 0x0002, 0x3002, 0x0002, + EVR_SH, "RTImageLabel", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3002, 0x0003, 0x3002, 0x0003, + EVR_LO, "RTImageName", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3002, 0x0004, 0x3002, 0x0004, + EVR_ST, "RTImageDescription", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3002, 0x000a, 0x3002, 0x000a, + EVR_CS, "ReportedValuesOrigin", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3002, 0x000c, 0x3002, 0x000c, + EVR_CS, "RTImagePlane", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3002, 0x000d, 0x3002, 0x000d, + EVR_DS, "XRayImageReceptorTranslation", 3, 3, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3002, 0x000e, 0x3002, 0x000e, + EVR_DS, "XRayImageReceptorAngle", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3002, 0x0010, 0x3002, 0x0010, + EVR_DS, "RTImageOrientation", 6, 6, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3002, 0x0011, 0x3002, 0x0011, + EVR_DS, "ImagePlanePixelSpacing", 2, 2, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3002, 0x0012, 0x3002, 0x0012, + EVR_DS, "RTImagePosition", 2, 2, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3002, 0x0020, 0x3002, 0x0020, + EVR_SH, "RadiationMachineName", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3002, 0x0022, 0x3002, 0x0022, + EVR_DS, "RadiationMachineSAD", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3002, 0x0024, 0x3002, 0x0024, + EVR_DS, "RadiationMachineSSD", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3002, 0x0026, 0x3002, 0x0026, + EVR_DS, "RTImageSID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3002, 0x0028, 0x3002, 0x0028, + EVR_DS, "SourceToReferenceObjectDistance", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3002, 0x0029, 0x3002, 0x0029, + EVR_IS, "FractionNumber", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3002, 0x0030, 0x3002, 0x0030, + EVR_SQ, "ExposureSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3002, 0x0032, 0x3002, 0x0032, + EVR_DS, "MetersetExposure", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3002, 0x0034, 0x3002, 0x0034, + EVR_DS, "DiaphragmPosition", 4, 4, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3002, 0x0040, 0x3002, 0x0040, + EVR_SQ, "FluenceMapSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3002, 0x0041, 0x3002, 0x0041, + EVR_CS, "FluenceDataSource", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3002, 0x0042, 0x3002, 0x0042, + EVR_DS, "FluenceDataScale", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3002, 0x0050, 0x3002, 0x0050, + EVR_SQ, "PrimaryFluenceModeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3002, 0x0051, 0x3002, 0x0051, + EVR_CS, "FluenceMode", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3002, 0x0052, 0x3002, 0x0052, + EVR_SH, "FluenceModeID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3004, 0x0001, 0x3004, 0x0001, + EVR_CS, "DVHType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3004, 0x0002, 0x3004, 0x0002, + EVR_CS, "DoseUnits", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3004, 0x0004, 0x3004, 0x0004, + EVR_CS, "DoseType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3004, 0x0005, 0x3004, 0x0005, + EVR_CS, "SpatialTransformOfDose", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3004, 0x0006, 0x3004, 0x0006, + EVR_LO, "DoseComment", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3004, 0x0008, 0x3004, 0x0008, + EVR_DS, "NormalizationPoint", 3, 3, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3004, 0x000a, 0x3004, 0x000a, + EVR_CS, "DoseSummationType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3004, 0x000c, 0x3004, 0x000c, + EVR_DS, "GridFrameOffsetVector", 2, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3004, 0x000e, 0x3004, 0x000e, + EVR_DS, "DoseGridScaling", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3004, 0x0010, 0x3004, 0x0010, + EVR_SQ, "RTDoseROISequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3004, 0x0012, 0x3004, 0x0012, + EVR_DS, "DoseValue", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3004, 0x0014, 0x3004, 0x0014, + EVR_CS, "TissueHeterogeneityCorrection", 1, 3, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3004, 0x0040, 0x3004, 0x0040, + EVR_DS, "DVHNormalizationPoint", 3, 3, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3004, 0x0042, 0x3004, 0x0042, + EVR_DS, "DVHNormalizationDoseValue", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3004, 0x0050, 0x3004, 0x0050, + EVR_SQ, "DVHSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3004, 0x0052, 0x3004, 0x0052, + EVR_DS, "DVHDoseScaling", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3004, 0x0054, 0x3004, 0x0054, + EVR_CS, "DVHVolumeUnits", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3004, 0x0056, 0x3004, 0x0056, + EVR_IS, "DVHNumberOfBins", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3004, 0x0058, 0x3004, 0x0058, + EVR_DS, "DVHData", 2, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3004, 0x0060, 0x3004, 0x0060, + EVR_SQ, "DVHReferencedROISequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3004, 0x0062, 0x3004, 0x0062, + EVR_CS, "DVHROIContributionType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3004, 0x0070, 0x3004, 0x0070, + EVR_DS, "DVHMinimumDose", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3004, 0x0072, 0x3004, 0x0072, + EVR_DS, "DVHMaximumDose", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3004, 0x0074, 0x3004, 0x0074, + EVR_DS, "DVHMeanDose", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3006, 0x0002, 0x3006, 0x0002, + EVR_SH, "StructureSetLabel", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3006, 0x0004, 0x3006, 0x0004, + EVR_LO, "StructureSetName", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3006, 0x0006, 0x3006, 0x0006, + EVR_ST, "StructureSetDescription", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3006, 0x0008, 0x3006, 0x0008, + EVR_DA, "StructureSetDate", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3006, 0x0009, 0x3006, 0x0009, + EVR_TM, "StructureSetTime", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3006, 0x0010, 0x3006, 0x0010, + EVR_SQ, "ReferencedFrameOfReferenceSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3006, 0x0012, 0x3006, 0x0012, + EVR_SQ, "RTReferencedStudySequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3006, 0x0014, 0x3006, 0x0014, + EVR_SQ, "RTReferencedSeriesSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3006, 0x0016, 0x3006, 0x0016, + EVR_SQ, "ContourImageSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3006, 0x0018, 0x3006, 0x0018, + EVR_SQ, "PredecessorStructureSetSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3006, 0x0020, 0x3006, 0x0020, + EVR_SQ, "StructureSetROISequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3006, 0x0022, 0x3006, 0x0022, + EVR_IS, "ROINumber", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3006, 0x0024, 0x3006, 0x0024, + EVR_UI, "ReferencedFrameOfReferenceUID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3006, 0x0026, 0x3006, 0x0026, + EVR_LO, "ROIName", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3006, 0x0028, 0x3006, 0x0028, + EVR_ST, "ROIDescription", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3006, 0x002a, 0x3006, 0x002a, + EVR_IS, "ROIDisplayColor", 3, 3, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3006, 0x002c, 0x3006, 0x002c, + EVR_DS, "ROIVolume", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3006, 0x0030, 0x3006, 0x0030, + EVR_SQ, "RTRelatedROISequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3006, 0x0033, 0x3006, 0x0033, + EVR_CS, "RTROIRelationship", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3006, 0x0036, 0x3006, 0x0036, + EVR_CS, "ROIGenerationAlgorithm", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3006, 0x0038, 0x3006, 0x0038, + EVR_LO, "ROIGenerationDescription", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3006, 0x0039, 0x3006, 0x0039, + EVR_SQ, "ROIContourSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3006, 0x0040, 0x3006, 0x0040, + EVR_SQ, "ContourSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3006, 0x0042, 0x3006, 0x0042, + EVR_CS, "ContourGeometricType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3006, 0x0044, 0x3006, 0x0044, + EVR_DS, "ContourSlabThickness", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3006, 0x0045, 0x3006, 0x0045, + EVR_DS, "ContourOffsetVector", 3, 3, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3006, 0x0046, 0x3006, 0x0046, + EVR_IS, "NumberOfContourPoints", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3006, 0x0048, 0x3006, 0x0048, + EVR_IS, "ContourNumber", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3006, 0x0049, 0x3006, 0x0049, + EVR_IS, "AttachedContours", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3006, 0x0050, 0x3006, 0x0050, + EVR_DS, "ContourData", 3, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3006, 0x0080, 0x3006, 0x0080, + EVR_SQ, "RTROIObservationsSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3006, 0x0082, 0x3006, 0x0082, + EVR_IS, "ObservationNumber", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3006, 0x0084, 0x3006, 0x0084, + EVR_IS, "ReferencedROINumber", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3006, 0x0085, 0x3006, 0x0085, + EVR_SH, "ROIObservationLabel", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3006, 0x0086, 0x3006, 0x0086, + EVR_SQ, "RTROIIdentificationCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3006, 0x0088, 0x3006, 0x0088, + EVR_ST, "ROIObservationDescription", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3006, 0x00a0, 0x3006, 0x00a0, + EVR_SQ, "RelatedRTROIObservationsSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3006, 0x00a4, 0x3006, 0x00a4, + EVR_CS, "RTROIInterpretedType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3006, 0x00a6, 0x3006, 0x00a6, + EVR_PN, "ROIInterpreter", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3006, 0x00b0, 0x3006, 0x00b0, + EVR_SQ, "ROIPhysicalPropertiesSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3006, 0x00b2, 0x3006, 0x00b2, + EVR_CS, "ROIPhysicalProperty", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3006, 0x00b4, 0x3006, 0x00b4, + EVR_DS, "ROIPhysicalPropertyValue", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3006, 0x00b6, 0x3006, 0x00b6, + EVR_SQ, "ROIElementalCompositionSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3006, 0x00b7, 0x3006, 0x00b7, + EVR_US, "ROIElementalCompositionAtomicNumber", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3006, 0x00b8, 0x3006, 0x00b8, + EVR_FL, "ROIElementalCompositionAtomicMassFraction", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3006, 0x00b9, 0x3006, 0x00b9, + EVR_SQ, "AdditionalRTROIIdentificationCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3006, 0x00c0, 0x3006, 0x00c0, + EVR_SQ, "RETIRED_FrameOfReferenceRelationshipSequence", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3006, 0x00c2, 0x3006, 0x00c2, + EVR_UI, "RETIRED_RelatedFrameOfReferenceUID", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3006, 0x00c4, 0x3006, 0x00c4, + EVR_CS, "RETIRED_FrameOfReferenceTransformationType", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3006, 0x00c6, 0x3006, 0x00c6, + EVR_DS, "FrameOfReferenceTransformationMatrix", 16, 16, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3006, 0x00c8, 0x3006, 0x00c8, + EVR_LO, "FrameOfReferenceTransformationComment", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3008, 0x0010, 0x3008, 0x0010, + EVR_SQ, "MeasuredDoseReferenceSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3008, 0x0012, 0x3008, 0x0012, + EVR_ST, "MeasuredDoseDescription", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3008, 0x0014, 0x3008, 0x0014, + EVR_CS, "MeasuredDoseType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3008, 0x0016, 0x3008, 0x0016, + EVR_DS, "MeasuredDoseValue", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3008, 0x0020, 0x3008, 0x0020, + EVR_SQ, "TreatmentSessionBeamSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3008, 0x0021, 0x3008, 0x0021, + EVR_SQ, "TreatmentSessionIonBeamSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3008, 0x0022, 0x3008, 0x0022, + EVR_IS, "CurrentFractionNumber", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3008, 0x0024, 0x3008, 0x0024, + EVR_DA, "TreatmentControlPointDate", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3008, 0x0025, 0x3008, 0x0025, + EVR_TM, "TreatmentControlPointTime", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3008, 0x002a, 0x3008, 0x002a, + EVR_CS, "TreatmentTerminationStatus", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3008, 0x002b, 0x3008, 0x002b, + EVR_SH, "TreatmentTerminationCode", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3008, 0x002c, 0x3008, 0x002c, + EVR_CS, "TreatmentVerificationStatus", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3008, 0x0030, 0x3008, 0x0030, + EVR_SQ, "ReferencedTreatmentRecordSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3008, 0x0032, 0x3008, 0x0032, + EVR_DS, "SpecifiedPrimaryMeterset", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3008, 0x0033, 0x3008, 0x0033, + EVR_DS, "SpecifiedSecondaryMeterset", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3008, 0x0036, 0x3008, 0x0036, + EVR_DS, "DeliveredPrimaryMeterset", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3008, 0x0037, 0x3008, 0x0037, + EVR_DS, "DeliveredSecondaryMeterset", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3008, 0x003a, 0x3008, 0x003a, + EVR_DS, "SpecifiedTreatmentTime", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3008, 0x003b, 0x3008, 0x003b, + EVR_DS, "DeliveredTreatmentTime", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3008, 0x0040, 0x3008, 0x0040, + EVR_SQ, "ControlPointDeliverySequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3008, 0x0041, 0x3008, 0x0041, + EVR_SQ, "IonControlPointDeliverySequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3008, 0x0042, 0x3008, 0x0042, + EVR_DS, "SpecifiedMeterset", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3008, 0x0044, 0x3008, 0x0044, + EVR_DS, "DeliveredMeterset", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3008, 0x0045, 0x3008, 0x0045, + EVR_FL, "MetersetRateSet", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3008, 0x0046, 0x3008, 0x0046, + EVR_FL, "MetersetRateDelivered", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3008, 0x0047, 0x3008, 0x0047, + EVR_FL, "ScanSpotMetersetsDelivered", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3008, 0x0048, 0x3008, 0x0048, + EVR_DS, "DoseRateDelivered", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3008, 0x0050, 0x3008, 0x0050, + EVR_SQ, "TreatmentSummaryCalculatedDoseReferenceSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3008, 0x0052, 0x3008, 0x0052, + EVR_DS, "CumulativeDoseToDoseReference", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3008, 0x0054, 0x3008, 0x0054, + EVR_DA, "FirstTreatmentDate", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3008, 0x0056, 0x3008, 0x0056, + EVR_DA, "MostRecentTreatmentDate", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3008, 0x005a, 0x3008, 0x005a, + EVR_IS, "NumberOfFractionsDelivered", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3008, 0x0060, 0x3008, 0x0060, + EVR_SQ, "OverrideSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3008, 0x0061, 0x3008, 0x0061, + EVR_AT, "ParameterSequencePointer", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3008, 0x0062, 0x3008, 0x0062, + EVR_AT, "OverrideParameterPointer", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3008, 0x0063, 0x3008, 0x0063, + EVR_IS, "ParameterItemIndex", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3008, 0x0064, 0x3008, 0x0064, + EVR_IS, "MeasuredDoseReferenceNumber", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3008, 0x0065, 0x3008, 0x0065, + EVR_AT, "ParameterPointer", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3008, 0x0066, 0x3008, 0x0066, + EVR_ST, "OverrideReason", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3008, 0x0068, 0x3008, 0x0068, + EVR_SQ, "CorrectedParameterSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3008, 0x006a, 0x3008, 0x006a, + EVR_FL, "CorrectionValue", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3008, 0x0070, 0x3008, 0x0070, + EVR_SQ, "CalculatedDoseReferenceSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3008, 0x0072, 0x3008, 0x0072, + EVR_IS, "CalculatedDoseReferenceNumber", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3008, 0x0074, 0x3008, 0x0074, + EVR_ST, "CalculatedDoseReferenceDescription", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3008, 0x0076, 0x3008, 0x0076, + EVR_DS, "CalculatedDoseReferenceDoseValue", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3008, 0x0078, 0x3008, 0x0078, + EVR_DS, "StartMeterset", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3008, 0x007a, 0x3008, 0x007a, + EVR_DS, "EndMeterset", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3008, 0x0080, 0x3008, 0x0080, + EVR_SQ, "ReferencedMeasuredDoseReferenceSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3008, 0x0082, 0x3008, 0x0082, + EVR_IS, "ReferencedMeasuredDoseReferenceNumber", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3008, 0x0090, 0x3008, 0x0090, + EVR_SQ, "ReferencedCalculatedDoseReferenceSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3008, 0x0092, 0x3008, 0x0092, + EVR_IS, "ReferencedCalculatedDoseReferenceNumber", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3008, 0x00a0, 0x3008, 0x00a0, + EVR_SQ, "BeamLimitingDeviceLeafPairsSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3008, 0x00b0, 0x3008, 0x00b0, + EVR_SQ, "RecordedWedgeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3008, 0x00c0, 0x3008, 0x00c0, + EVR_SQ, "RecordedCompensatorSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3008, 0x00d0, 0x3008, 0x00d0, + EVR_SQ, "RecordedBlockSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3008, 0x00e0, 0x3008, 0x00e0, + EVR_SQ, "TreatmentSummaryMeasuredDoseReferenceSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3008, 0x00f0, 0x3008, 0x00f0, + EVR_SQ, "RecordedSnoutSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3008, 0x00f2, 0x3008, 0x00f2, + EVR_SQ, "RecordedRangeShifterSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3008, 0x00f4, 0x3008, 0x00f4, + EVR_SQ, "RecordedLateralSpreadingDeviceSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3008, 0x00f6, 0x3008, 0x00f6, + EVR_SQ, "RecordedRangeModulatorSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3008, 0x0100, 0x3008, 0x0100, + EVR_SQ, "RecordedSourceSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3008, 0x0105, 0x3008, 0x0105, + EVR_LO, "SourceSerialNumber", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3008, 0x0110, 0x3008, 0x0110, + EVR_SQ, "TreatmentSessionApplicationSetupSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3008, 0x0116, 0x3008, 0x0116, + EVR_CS, "ApplicationSetupCheck", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3008, 0x0120, 0x3008, 0x0120, + EVR_SQ, "RecordedBrachyAccessoryDeviceSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3008, 0x0122, 0x3008, 0x0122, + EVR_IS, "ReferencedBrachyAccessoryDeviceNumber", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3008, 0x0130, 0x3008, 0x0130, + EVR_SQ, "RecordedChannelSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3008, 0x0132, 0x3008, 0x0132, + EVR_DS, "SpecifiedChannelTotalTime", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3008, 0x0134, 0x3008, 0x0134, + EVR_DS, "DeliveredChannelTotalTime", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3008, 0x0136, 0x3008, 0x0136, + EVR_IS, "SpecifiedNumberOfPulses", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3008, 0x0138, 0x3008, 0x0138, + EVR_IS, "DeliveredNumberOfPulses", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3008, 0x013a, 0x3008, 0x013a, + EVR_DS, "SpecifiedPulseRepetitionInterval", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3008, 0x013c, 0x3008, 0x013c, + EVR_DS, "DeliveredPulseRepetitionInterval", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3008, 0x0140, 0x3008, 0x0140, + EVR_SQ, "RecordedSourceApplicatorSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3008, 0x0142, 0x3008, 0x0142, + EVR_IS, "ReferencedSourceApplicatorNumber", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3008, 0x0150, 0x3008, 0x0150, + EVR_SQ, "RecordedChannelShieldSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3008, 0x0152, 0x3008, 0x0152, + EVR_IS, "ReferencedChannelShieldNumber", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3008, 0x0160, 0x3008, 0x0160, + EVR_SQ, "BrachyControlPointDeliveredSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3008, 0x0162, 0x3008, 0x0162, + EVR_DA, "SafePositionExitDate", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3008, 0x0164, 0x3008, 0x0164, + EVR_TM, "SafePositionExitTime", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3008, 0x0166, 0x3008, 0x0166, + EVR_DA, "SafePositionReturnDate", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3008, 0x0168, 0x3008, 0x0168, + EVR_TM, "SafePositionReturnTime", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3008, 0x0171, 0x3008, 0x0171, + EVR_SQ, "PulseSpecificBrachyControlPointDeliveredSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3008, 0x0172, 0x3008, 0x0172, + EVR_US, "PulseNumber", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3008, 0x0173, 0x3008, 0x0173, + EVR_SQ, "BrachyPulseControlPointDeliveredSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3008, 0x0200, 0x3008, 0x0200, + EVR_CS, "CurrentTreatmentStatus", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3008, 0x0202, 0x3008, 0x0202, + EVR_ST, "TreatmentStatusComment", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3008, 0x0220, 0x3008, 0x0220, + EVR_SQ, "FractionGroupSummarySequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3008, 0x0223, 0x3008, 0x0223, + EVR_IS, "ReferencedFractionNumber", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3008, 0x0224, 0x3008, 0x0224, + EVR_CS, "FractionGroupType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3008, 0x0230, 0x3008, 0x0230, + EVR_CS, "BeamStopperPosition", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3008, 0x0240, 0x3008, 0x0240, + EVR_SQ, "FractionStatusSummarySequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3008, 0x0250, 0x3008, 0x0250, + EVR_DA, "TreatmentDate", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x3008, 0x0251, 0x3008, 0x0251, + EVR_TM, "TreatmentTime", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0002, 0x300a, 0x0002, + EVR_SH, "RTPlanLabel", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0003, 0x300a, 0x0003, + EVR_LO, "RTPlanName", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0004, 0x300a, 0x0004, + EVR_ST, "RTPlanDescription", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0006, 0x300a, 0x0006, + EVR_DA, "RTPlanDate", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0007, 0x300a, 0x0007, + EVR_TM, "RTPlanTime", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0009, 0x300a, 0x0009, + EVR_LO, "TreatmentProtocols", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x000a, 0x300a, 0x000a, + EVR_CS, "PlanIntent", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x000b, 0x300a, 0x000b, + EVR_LO, "TreatmentSites", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x000c, 0x300a, 0x000c, + EVR_CS, "RTPlanGeometry", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x000e, 0x300a, 0x000e, + EVR_ST, "PrescriptionDescription", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0010, 0x300a, 0x0010, + EVR_SQ, "DoseReferenceSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0012, 0x300a, 0x0012, + EVR_IS, "DoseReferenceNumber", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0013, 0x300a, 0x0013, + EVR_UI, "DoseReferenceUID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0014, 0x300a, 0x0014, + EVR_CS, "DoseReferenceStructureType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0015, 0x300a, 0x0015, + EVR_CS, "NominalBeamEnergyUnit", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0016, 0x300a, 0x0016, + EVR_LO, "DoseReferenceDescription", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0018, 0x300a, 0x0018, + EVR_DS, "DoseReferencePointCoordinates", 3, 3, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x001a, 0x300a, 0x001a, + EVR_DS, "NominalPriorDose", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0020, 0x300a, 0x0020, + EVR_CS, "DoseReferenceType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0021, 0x300a, 0x0021, + EVR_DS, "ConstraintWeight", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0022, 0x300a, 0x0022, + EVR_DS, "DeliveryWarningDose", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0023, 0x300a, 0x0023, + EVR_DS, "DeliveryMaximumDose", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0025, 0x300a, 0x0025, + EVR_DS, "TargetMinimumDose", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0026, 0x300a, 0x0026, + EVR_DS, "TargetPrescriptionDose", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0027, 0x300a, 0x0027, + EVR_DS, "TargetMaximumDose", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0028, 0x300a, 0x0028, + EVR_DS, "TargetUnderdoseVolumeFraction", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x002a, 0x300a, 0x002a, + EVR_DS, "OrganAtRiskFullVolumeDose", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x002b, 0x300a, 0x002b, + EVR_DS, "OrganAtRiskLimitDose", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x002c, 0x300a, 0x002c, + EVR_DS, "OrganAtRiskMaximumDose", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x002d, 0x300a, 0x002d, + EVR_DS, "OrganAtRiskOverdoseVolumeFraction", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0040, 0x300a, 0x0040, + EVR_SQ, "ToleranceTableSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0042, 0x300a, 0x0042, + EVR_IS, "ToleranceTableNumber", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0043, 0x300a, 0x0043, + EVR_SH, "ToleranceTableLabel", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0044, 0x300a, 0x0044, + EVR_DS, "GantryAngleTolerance", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0046, 0x300a, 0x0046, + EVR_DS, "BeamLimitingDeviceAngleTolerance", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0048, 0x300a, 0x0048, + EVR_SQ, "BeamLimitingDeviceToleranceSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x004a, 0x300a, 0x004a, + EVR_DS, "BeamLimitingDevicePositionTolerance", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x004b, 0x300a, 0x004b, + EVR_FL, "SnoutPositionTolerance", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x004c, 0x300a, 0x004c, + EVR_DS, "PatientSupportAngleTolerance", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x004e, 0x300a, 0x004e, + EVR_DS, "TableTopEccentricAngleTolerance", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x004f, 0x300a, 0x004f, + EVR_FL, "TableTopPitchAngleTolerance", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0050, 0x300a, 0x0050, + EVR_FL, "TableTopRollAngleTolerance", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0051, 0x300a, 0x0051, + EVR_DS, "TableTopVerticalPositionTolerance", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0052, 0x300a, 0x0052, + EVR_DS, "TableTopLongitudinalPositionTolerance", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0053, 0x300a, 0x0053, + EVR_DS, "TableTopLateralPositionTolerance", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0055, 0x300a, 0x0055, + EVR_CS, "RTPlanRelationship", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0070, 0x300a, 0x0070, + EVR_SQ, "FractionGroupSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0071, 0x300a, 0x0071, + EVR_IS, "FractionGroupNumber", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0072, 0x300a, 0x0072, + EVR_LO, "FractionGroupDescription", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0078, 0x300a, 0x0078, + EVR_IS, "NumberOfFractionsPlanned", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0079, 0x300a, 0x0079, + EVR_IS, "NumberOfFractionPatternDigitsPerDay", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x007a, 0x300a, 0x007a, + EVR_IS, "RepeatFractionCycleLength", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x007b, 0x300a, 0x007b, + EVR_LT, "FractionPattern", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0080, 0x300a, 0x0080, + EVR_IS, "NumberOfBeams", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0082, 0x300a, 0x0082, + EVR_DS, "BeamDoseSpecificationPoint", 3, 3, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0084, 0x300a, 0x0084, + EVR_DS, "BeamDose", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0086, 0x300a, 0x0086, + EVR_DS, "BeamMeterset", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0088, 0x300a, 0x0088, + EVR_FL, "RETIRED_BeamDosePointDepth", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0089, 0x300a, 0x0089, + EVR_FL, "RETIRED_BeamDosePointEquivalentDepth", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x008a, 0x300a, 0x008a, + EVR_FL, "RETIRED_BeamDosePointSSD", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x008b, 0x300a, 0x008b, + EVR_CS, "BeamDoseMeaning", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x008c, 0x300a, 0x008c, + EVR_SQ, "BeamDoseVerificationControlPointSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x008d, 0x300a, 0x008d, + EVR_FL, "AverageBeamDosePointDepth", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x008e, 0x300a, 0x008e, + EVR_FL, "AverageBeamDosePointEquivalentDepth", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x008f, 0x300a, 0x008f, + EVR_FL, "AverageBeamDosePointSSD", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x00a0, 0x300a, 0x00a0, + EVR_IS, "NumberOfBrachyApplicationSetups", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x00a2, 0x300a, 0x00a2, + EVR_DS, "BrachyApplicationSetupDoseSpecificationPoint", 3, 3, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x00a4, 0x300a, 0x00a4, + EVR_DS, "BrachyApplicationSetupDose", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x00b0, 0x300a, 0x00b0, + EVR_SQ, "BeamSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x00b2, 0x300a, 0x00b2, + EVR_SH, "TreatmentMachineName", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x00b3, 0x300a, 0x00b3, + EVR_CS, "PrimaryDosimeterUnit", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x00b4, 0x300a, 0x00b4, + EVR_DS, "SourceAxisDistance", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x00b6, 0x300a, 0x00b6, + EVR_SQ, "BeamLimitingDeviceSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x00b8, 0x300a, 0x00b8, + EVR_CS, "RTBeamLimitingDeviceType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x00ba, 0x300a, 0x00ba, + EVR_DS, "SourceToBeamLimitingDeviceDistance", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x00bb, 0x300a, 0x00bb, + EVR_FL, "IsocenterToBeamLimitingDeviceDistance", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x00bc, 0x300a, 0x00bc, + EVR_IS, "NumberOfLeafJawPairs", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x00be, 0x300a, 0x00be, + EVR_DS, "LeafPositionBoundaries", 3, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x00c0, 0x300a, 0x00c0, + EVR_IS, "BeamNumber", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x00c2, 0x300a, 0x00c2, + EVR_LO, "BeamName", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x00c3, 0x300a, 0x00c3, + EVR_ST, "BeamDescription", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x00c4, 0x300a, 0x00c4, + EVR_CS, "BeamType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x00c5, 0x300a, 0x00c5, + EVR_FD, "BeamDeliveryDurationLimit", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x00c6, 0x300a, 0x00c6, + EVR_CS, "RadiationType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x00c7, 0x300a, 0x00c7, + EVR_CS, "HighDoseTechniqueType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x00c8, 0x300a, 0x00c8, + EVR_IS, "ReferenceImageNumber", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x00ca, 0x300a, 0x00ca, + EVR_SQ, "PlannedVerificationImageSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x00cc, 0x300a, 0x00cc, + EVR_LO, "ImagingDeviceSpecificAcquisitionParameters", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x00ce, 0x300a, 0x00ce, + EVR_CS, "TreatmentDeliveryType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x00d0, 0x300a, 0x00d0, + EVR_IS, "NumberOfWedges", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x00d1, 0x300a, 0x00d1, + EVR_SQ, "WedgeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x00d2, 0x300a, 0x00d2, + EVR_IS, "WedgeNumber", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x00d3, 0x300a, 0x00d3, + EVR_CS, "WedgeType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x00d4, 0x300a, 0x00d4, + EVR_SH, "WedgeID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x00d5, 0x300a, 0x00d5, + EVR_IS, "WedgeAngle", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x00d6, 0x300a, 0x00d6, + EVR_DS, "WedgeFactor", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x00d7, 0x300a, 0x00d7, + EVR_FL, "TotalWedgeTrayWaterEquivalentThickness", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x00d8, 0x300a, 0x00d8, + EVR_DS, "WedgeOrientation", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x00d9, 0x300a, 0x00d9, + EVR_FL, "IsocenterToWedgeTrayDistance", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x00da, 0x300a, 0x00da, + EVR_DS, "SourceToWedgeTrayDistance", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x00db, 0x300a, 0x00db, + EVR_FL, "WedgeThinEdgePosition", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x00dc, 0x300a, 0x00dc, + EVR_SH, "BolusID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x00dd, 0x300a, 0x00dd, + EVR_ST, "BolusDescription", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x00de, 0x300a, 0x00de, + EVR_DS, "EffectiveWedgeAngle", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x00e0, 0x300a, 0x00e0, + EVR_IS, "NumberOfCompensators", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x00e1, 0x300a, 0x00e1, + EVR_SH, "MaterialID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x00e2, 0x300a, 0x00e2, + EVR_DS, "TotalCompensatorTrayFactor", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x00e3, 0x300a, 0x00e3, + EVR_SQ, "CompensatorSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x00e4, 0x300a, 0x00e4, + EVR_IS, "CompensatorNumber", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x00e5, 0x300a, 0x00e5, + EVR_SH, "CompensatorID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x00e6, 0x300a, 0x00e6, + EVR_DS, "SourceToCompensatorTrayDistance", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x00e7, 0x300a, 0x00e7, + EVR_IS, "CompensatorRows", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x00e8, 0x300a, 0x00e8, + EVR_IS, "CompensatorColumns", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x00e9, 0x300a, 0x00e9, + EVR_DS, "CompensatorPixelSpacing", 2, 2, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x00ea, 0x300a, 0x00ea, + EVR_DS, "CompensatorPosition", 2, 2, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x00eb, 0x300a, 0x00eb, + EVR_DS, "CompensatorTransmissionData", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x00ec, 0x300a, 0x00ec, + EVR_DS, "CompensatorThicknessData", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x00ed, 0x300a, 0x00ed, + EVR_IS, "NumberOfBoli", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x00ee, 0x300a, 0x00ee, + EVR_CS, "CompensatorType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x00ef, 0x300a, 0x00ef, + EVR_SH, "CompensatorTrayID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x00f0, 0x300a, 0x00f0, + EVR_IS, "NumberOfBlocks", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x00f2, 0x300a, 0x00f2, + EVR_DS, "TotalBlockTrayFactor", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x00f3, 0x300a, 0x00f3, + EVR_FL, "TotalBlockTrayWaterEquivalentThickness", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x00f4, 0x300a, 0x00f4, + EVR_SQ, "BlockSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x00f5, 0x300a, 0x00f5, + EVR_SH, "BlockTrayID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x00f6, 0x300a, 0x00f6, + EVR_DS, "SourceToBlockTrayDistance", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x00f7, 0x300a, 0x00f7, + EVR_FL, "IsocenterToBlockTrayDistance", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x00f8, 0x300a, 0x00f8, + EVR_CS, "BlockType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x00f9, 0x300a, 0x00f9, + EVR_LO, "AccessoryCode", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x00fa, 0x300a, 0x00fa, + EVR_CS, "BlockDivergence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x00fb, 0x300a, 0x00fb, + EVR_CS, "BlockMountingPosition", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x00fc, 0x300a, 0x00fc, + EVR_IS, "BlockNumber", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x00fe, 0x300a, 0x00fe, + EVR_LO, "BlockName", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0100, 0x300a, 0x0100, + EVR_DS, "BlockThickness", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0102, 0x300a, 0x0102, + EVR_DS, "BlockTransmission", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0104, 0x300a, 0x0104, + EVR_IS, "BlockNumberOfPoints", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0106, 0x300a, 0x0106, + EVR_DS, "BlockData", 2, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0107, 0x300a, 0x0107, + EVR_SQ, "ApplicatorSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0108, 0x300a, 0x0108, + EVR_SH, "ApplicatorID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0109, 0x300a, 0x0109, + EVR_CS, "ApplicatorType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x010a, 0x300a, 0x010a, + EVR_LO, "ApplicatorDescription", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x010c, 0x300a, 0x010c, + EVR_DS, "CumulativeDoseReferenceCoefficient", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x010e, 0x300a, 0x010e, + EVR_DS, "FinalCumulativeMetersetWeight", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0110, 0x300a, 0x0110, + EVR_IS, "NumberOfControlPoints", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0111, 0x300a, 0x0111, + EVR_SQ, "ControlPointSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0112, 0x300a, 0x0112, + EVR_IS, "ControlPointIndex", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0114, 0x300a, 0x0114, + EVR_DS, "NominalBeamEnergy", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0115, 0x300a, 0x0115, + EVR_DS, "DoseRateSet", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0116, 0x300a, 0x0116, + EVR_SQ, "WedgePositionSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0118, 0x300a, 0x0118, + EVR_CS, "WedgePosition", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x011a, 0x300a, 0x011a, + EVR_SQ, "BeamLimitingDevicePositionSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x011c, 0x300a, 0x011c, + EVR_DS, "LeafJawPositions", 2, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x011e, 0x300a, 0x011e, + EVR_DS, "GantryAngle", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x011f, 0x300a, 0x011f, + EVR_CS, "GantryRotationDirection", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0120, 0x300a, 0x0120, + EVR_DS, "BeamLimitingDeviceAngle", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0121, 0x300a, 0x0121, + EVR_CS, "BeamLimitingDeviceRotationDirection", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0122, 0x300a, 0x0122, + EVR_DS, "PatientSupportAngle", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0123, 0x300a, 0x0123, + EVR_CS, "PatientSupportRotationDirection", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0124, 0x300a, 0x0124, + EVR_DS, "TableTopEccentricAxisDistance", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0125, 0x300a, 0x0125, + EVR_DS, "TableTopEccentricAngle", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0126, 0x300a, 0x0126, + EVR_CS, "TableTopEccentricRotationDirection", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0128, 0x300a, 0x0128, + EVR_DS, "TableTopVerticalPosition", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0129, 0x300a, 0x0129, + EVR_DS, "TableTopLongitudinalPosition", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x012a, 0x300a, 0x012a, + EVR_DS, "TableTopLateralPosition", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x012c, 0x300a, 0x012c, + EVR_DS, "IsocenterPosition", 3, 3, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x012e, 0x300a, 0x012e, + EVR_DS, "SurfaceEntryPoint", 3, 3, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0130, 0x300a, 0x0130, + EVR_DS, "SourceToSurfaceDistance", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0131, 0x300a, 0x0131, + EVR_FL, "AverageBeamDosePointSourceToExternalContourSurfaceDistance", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0132, 0x300a, 0x0132, + EVR_FL, "SourceToExternalContourDistance", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0133, 0x300a, 0x0133, + EVR_FL, "ExternalContourEntryPoint", 3, 3, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0134, 0x300a, 0x0134, + EVR_DS, "CumulativeMetersetWeight", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0140, 0x300a, 0x0140, + EVR_FL, "TableTopPitchAngle", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0142, 0x300a, 0x0142, + EVR_CS, "TableTopPitchRotationDirection", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0144, 0x300a, 0x0144, + EVR_FL, "TableTopRollAngle", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0146, 0x300a, 0x0146, + EVR_CS, "TableTopRollRotationDirection", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0148, 0x300a, 0x0148, + EVR_FL, "HeadFixationAngle", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x014a, 0x300a, 0x014a, + EVR_FL, "GantryPitchAngle", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x014c, 0x300a, 0x014c, + EVR_CS, "GantryPitchRotationDirection", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x014e, 0x300a, 0x014e, + EVR_FL, "GantryPitchAngleTolerance", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0180, 0x300a, 0x0180, + EVR_SQ, "PatientSetupSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0182, 0x300a, 0x0182, + EVR_IS, "PatientSetupNumber", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0183, 0x300a, 0x0183, + EVR_LO, "PatientSetupLabel", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0184, 0x300a, 0x0184, + EVR_LO, "PatientAdditionalPosition", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0190, 0x300a, 0x0190, + EVR_SQ, "FixationDeviceSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0192, 0x300a, 0x0192, + EVR_CS, "FixationDeviceType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0194, 0x300a, 0x0194, + EVR_SH, "FixationDeviceLabel", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0196, 0x300a, 0x0196, + EVR_ST, "FixationDeviceDescription", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0198, 0x300a, 0x0198, + EVR_SH, "FixationDevicePosition", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0199, 0x300a, 0x0199, + EVR_FL, "FixationDevicePitchAngle", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x019a, 0x300a, 0x019a, + EVR_FL, "FixationDeviceRollAngle", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x01a0, 0x300a, 0x01a0, + EVR_SQ, "ShieldingDeviceSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x01a2, 0x300a, 0x01a2, + EVR_CS, "ShieldingDeviceType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x01a4, 0x300a, 0x01a4, + EVR_SH, "ShieldingDeviceLabel", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x01a6, 0x300a, 0x01a6, + EVR_ST, "ShieldingDeviceDescription", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x01a8, 0x300a, 0x01a8, + EVR_SH, "ShieldingDevicePosition", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x01b0, 0x300a, 0x01b0, + EVR_CS, "SetupTechnique", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x01b2, 0x300a, 0x01b2, + EVR_ST, "SetupTechniqueDescription", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x01b4, 0x300a, 0x01b4, + EVR_SQ, "SetupDeviceSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x01b6, 0x300a, 0x01b6, + EVR_CS, "SetupDeviceType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x01b8, 0x300a, 0x01b8, + EVR_SH, "SetupDeviceLabel", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x01ba, 0x300a, 0x01ba, + EVR_ST, "SetupDeviceDescription", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x01bc, 0x300a, 0x01bc, + EVR_DS, "SetupDeviceParameter", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x01d0, 0x300a, 0x01d0, + EVR_ST, "SetupReferenceDescription", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x01d2, 0x300a, 0x01d2, + EVR_DS, "TableTopVerticalSetupDisplacement", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x01d4, 0x300a, 0x01d4, + EVR_DS, "TableTopLongitudinalSetupDisplacement", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x01d6, 0x300a, 0x01d6, + EVR_DS, "TableTopLateralSetupDisplacement", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0200, 0x300a, 0x0200, + EVR_CS, "BrachyTreatmentTechnique", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0202, 0x300a, 0x0202, + EVR_CS, "BrachyTreatmentType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0206, 0x300a, 0x0206, + EVR_SQ, "TreatmentMachineSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0210, 0x300a, 0x0210, + EVR_SQ, "SourceSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0212, 0x300a, 0x0212, + EVR_IS, "SourceNumber", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0214, 0x300a, 0x0214, + EVR_CS, "SourceType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0216, 0x300a, 0x0216, + EVR_LO, "SourceManufacturer", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0218, 0x300a, 0x0218, + EVR_DS, "ActiveSourceDiameter", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x021a, 0x300a, 0x021a, + EVR_DS, "ActiveSourceLength", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x021b, 0x300a, 0x021b, + EVR_SH, "SourceModelID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x021c, 0x300a, 0x021c, + EVR_LO, "SourceDescription", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0222, 0x300a, 0x0222, + EVR_DS, "SourceEncapsulationNominalThickness", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0224, 0x300a, 0x0224, + EVR_DS, "SourceEncapsulationNominalTransmission", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0226, 0x300a, 0x0226, + EVR_LO, "SourceIsotopeName", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0228, 0x300a, 0x0228, + EVR_DS, "SourceIsotopeHalfLife", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0229, 0x300a, 0x0229, + EVR_CS, "SourceStrengthUnits", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x022a, 0x300a, 0x022a, + EVR_DS, "ReferenceAirKermaRate", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x022b, 0x300a, 0x022b, + EVR_DS, "SourceStrength", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x022c, 0x300a, 0x022c, + EVR_DA, "SourceStrengthReferenceDate", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x022e, 0x300a, 0x022e, + EVR_TM, "SourceStrengthReferenceTime", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0230, 0x300a, 0x0230, + EVR_SQ, "ApplicationSetupSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0232, 0x300a, 0x0232, + EVR_CS, "ApplicationSetupType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0234, 0x300a, 0x0234, + EVR_IS, "ApplicationSetupNumber", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0236, 0x300a, 0x0236, + EVR_LO, "ApplicationSetupName", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0238, 0x300a, 0x0238, + EVR_LO, "ApplicationSetupManufacturer", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0240, 0x300a, 0x0240, + EVR_IS, "TemplateNumber", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0242, 0x300a, 0x0242, + EVR_SH, "TemplateType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0244, 0x300a, 0x0244, + EVR_LO, "TemplateName", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0250, 0x300a, 0x0250, + EVR_DS, "TotalReferenceAirKerma", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0260, 0x300a, 0x0260, + EVR_SQ, "BrachyAccessoryDeviceSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0262, 0x300a, 0x0262, + EVR_IS, "BrachyAccessoryDeviceNumber", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0263, 0x300a, 0x0263, + EVR_SH, "BrachyAccessoryDeviceID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0264, 0x300a, 0x0264, + EVR_CS, "BrachyAccessoryDeviceType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0266, 0x300a, 0x0266, + EVR_LO, "BrachyAccessoryDeviceName", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x026a, 0x300a, 0x026a, + EVR_DS, "BrachyAccessoryDeviceNominalThickness", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x026c, 0x300a, 0x026c, + EVR_DS, "BrachyAccessoryDeviceNominalTransmission", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0280, 0x300a, 0x0280, + EVR_SQ, "ChannelSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0282, 0x300a, 0x0282, + EVR_IS, "ChannelNumber", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0284, 0x300a, 0x0284, + EVR_DS, "ChannelLength", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0286, 0x300a, 0x0286, + EVR_DS, "ChannelTotalTime", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0288, 0x300a, 0x0288, + EVR_CS, "SourceMovementType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x028a, 0x300a, 0x028a, + EVR_IS, "NumberOfPulses", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x028c, 0x300a, 0x028c, + EVR_DS, "PulseRepetitionInterval", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0290, 0x300a, 0x0290, + EVR_IS, "SourceApplicatorNumber", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0291, 0x300a, 0x0291, + EVR_SH, "SourceApplicatorID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0292, 0x300a, 0x0292, + EVR_CS, "SourceApplicatorType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0294, 0x300a, 0x0294, + EVR_LO, "SourceApplicatorName", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0296, 0x300a, 0x0296, + EVR_DS, "SourceApplicatorLength", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0298, 0x300a, 0x0298, + EVR_LO, "SourceApplicatorManufacturer", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x029c, 0x300a, 0x029c, + EVR_DS, "SourceApplicatorWallNominalThickness", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x029e, 0x300a, 0x029e, + EVR_DS, "SourceApplicatorWallNominalTransmission", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x02a0, 0x300a, 0x02a0, + EVR_DS, "SourceApplicatorStepSize", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x02a2, 0x300a, 0x02a2, + EVR_IS, "TransferTubeNumber", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x02a4, 0x300a, 0x02a4, + EVR_DS, "TransferTubeLength", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x02b0, 0x300a, 0x02b0, + EVR_SQ, "ChannelShieldSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x02b2, 0x300a, 0x02b2, + EVR_IS, "ChannelShieldNumber", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x02b3, 0x300a, 0x02b3, + EVR_SH, "ChannelShieldID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x02b4, 0x300a, 0x02b4, + EVR_LO, "ChannelShieldName", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x02b8, 0x300a, 0x02b8, + EVR_DS, "ChannelShieldNominalThickness", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x02ba, 0x300a, 0x02ba, + EVR_DS, "ChannelShieldNominalTransmission", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x02c8, 0x300a, 0x02c8, + EVR_DS, "FinalCumulativeTimeWeight", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x02d0, 0x300a, 0x02d0, + EVR_SQ, "BrachyControlPointSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x02d2, 0x300a, 0x02d2, + EVR_DS, "ControlPointRelativePosition", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x02d4, 0x300a, 0x02d4, + EVR_DS, "ControlPoint3DPosition", 3, 3, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x02d6, 0x300a, 0x02d6, + EVR_DS, "CumulativeTimeWeight", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x02e0, 0x300a, 0x02e0, + EVR_CS, "CompensatorDivergence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x02e1, 0x300a, 0x02e1, + EVR_CS, "CompensatorMountingPosition", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x02e2, 0x300a, 0x02e2, + EVR_DS, "SourceToCompensatorDistance", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x02e3, 0x300a, 0x02e3, + EVR_FL, "TotalCompensatorTrayWaterEquivalentThickness", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x02e4, 0x300a, 0x02e4, + EVR_FL, "IsocenterToCompensatorTrayDistance", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x02e5, 0x300a, 0x02e5, + EVR_FL, "CompensatorColumnOffset", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x02e6, 0x300a, 0x02e6, + EVR_FL, "IsocenterToCompensatorDistances", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x02e7, 0x300a, 0x02e7, + EVR_FL, "CompensatorRelativeStoppingPowerRatio", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x02e8, 0x300a, 0x02e8, + EVR_FL, "CompensatorMillingToolDiameter", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x02ea, 0x300a, 0x02ea, + EVR_SQ, "IonRangeCompensatorSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x02eb, 0x300a, 0x02eb, + EVR_LT, "CompensatorDescription", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0302, 0x300a, 0x0302, + EVR_IS, "RadiationMassNumber", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0304, 0x300a, 0x0304, + EVR_IS, "RadiationAtomicNumber", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0306, 0x300a, 0x0306, + EVR_SS, "RadiationChargeState", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0308, 0x300a, 0x0308, + EVR_CS, "ScanMode", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x030a, 0x300a, 0x030a, + EVR_FL, "VirtualSourceAxisDistances", 2, 2, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x030c, 0x300a, 0x030c, + EVR_SQ, "SnoutSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x030d, 0x300a, 0x030d, + EVR_FL, "SnoutPosition", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x030f, 0x300a, 0x030f, + EVR_SH, "SnoutID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0312, 0x300a, 0x0312, + EVR_IS, "NumberOfRangeShifters", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0314, 0x300a, 0x0314, + EVR_SQ, "RangeShifterSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0316, 0x300a, 0x0316, + EVR_IS, "RangeShifterNumber", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0318, 0x300a, 0x0318, + EVR_SH, "RangeShifterID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0320, 0x300a, 0x0320, + EVR_CS, "RangeShifterType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0322, 0x300a, 0x0322, + EVR_LO, "RangeShifterDescription", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0330, 0x300a, 0x0330, + EVR_IS, "NumberOfLateralSpreadingDevices", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0332, 0x300a, 0x0332, + EVR_SQ, "LateralSpreadingDeviceSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0334, 0x300a, 0x0334, + EVR_IS, "LateralSpreadingDeviceNumber", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0336, 0x300a, 0x0336, + EVR_SH, "LateralSpreadingDeviceID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0338, 0x300a, 0x0338, + EVR_CS, "LateralSpreadingDeviceType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x033a, 0x300a, 0x033a, + EVR_LO, "LateralSpreadingDeviceDescription", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x033c, 0x300a, 0x033c, + EVR_FL, "LateralSpreadingDeviceWaterEquivalentThickness", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0340, 0x300a, 0x0340, + EVR_IS, "NumberOfRangeModulators", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0342, 0x300a, 0x0342, + EVR_SQ, "RangeModulatorSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0344, 0x300a, 0x0344, + EVR_IS, "RangeModulatorNumber", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0346, 0x300a, 0x0346, + EVR_SH, "RangeModulatorID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0348, 0x300a, 0x0348, + EVR_CS, "RangeModulatorType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x034a, 0x300a, 0x034a, + EVR_LO, "RangeModulatorDescription", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x034c, 0x300a, 0x034c, + EVR_SH, "BeamCurrentModulationID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0350, 0x300a, 0x0350, + EVR_CS, "PatientSupportType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0352, 0x300a, 0x0352, + EVR_SH, "PatientSupportID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0354, 0x300a, 0x0354, + EVR_LO, "PatientSupportAccessoryCode", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0356, 0x300a, 0x0356, + EVR_FL, "FixationLightAzimuthalAngle", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0358, 0x300a, 0x0358, + EVR_FL, "FixationLightPolarAngle", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x035a, 0x300a, 0x035a, + EVR_FL, "MetersetRate", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0360, 0x300a, 0x0360, + EVR_SQ, "RangeShifterSettingsSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0362, 0x300a, 0x0362, + EVR_LO, "RangeShifterSetting", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0364, 0x300a, 0x0364, + EVR_FL, "IsocenterToRangeShifterDistance", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0366, 0x300a, 0x0366, + EVR_FL, "RangeShifterWaterEquivalentThickness", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0370, 0x300a, 0x0370, + EVR_SQ, "LateralSpreadingDeviceSettingsSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0372, 0x300a, 0x0372, + EVR_LO, "LateralSpreadingDeviceSetting", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0374, 0x300a, 0x0374, + EVR_FL, "IsocenterToLateralSpreadingDeviceDistance", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0380, 0x300a, 0x0380, + EVR_SQ, "RangeModulatorSettingsSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0382, 0x300a, 0x0382, + EVR_FL, "RangeModulatorGatingStartValue", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0384, 0x300a, 0x0384, + EVR_FL, "RangeModulatorGatingStopValue", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0386, 0x300a, 0x0386, + EVR_FL, "RangeModulatorGatingStartWaterEquivalentThickness", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0388, 0x300a, 0x0388, + EVR_FL, "RangeModulatorGatingStopWaterEquivalentThickness", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x038a, 0x300a, 0x038a, + EVR_FL, "IsocenterToRangeModulatorDistance", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0390, 0x300a, 0x0390, + EVR_SH, "ScanSpotTuneID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0392, 0x300a, 0x0392, + EVR_IS, "NumberOfScanSpotPositions", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0394, 0x300a, 0x0394, + EVR_FL, "ScanSpotPositionMap", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0396, 0x300a, 0x0396, + EVR_FL, "ScanSpotMetersetWeights", 1, -1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0398, 0x300a, 0x0398, + EVR_FL, "ScanningSpotSize", 2, 2, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x039a, 0x300a, 0x039a, + EVR_IS, "NumberOfPaintings", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x03a0, 0x300a, 0x03a0, + EVR_SQ, "IonToleranceTableSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x03a2, 0x300a, 0x03a2, + EVR_SQ, "IonBeamSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x03a4, 0x300a, 0x03a4, + EVR_SQ, "IonBeamLimitingDeviceSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x03a6, 0x300a, 0x03a6, + EVR_SQ, "IonBlockSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x03a8, 0x300a, 0x03a8, + EVR_SQ, "IonControlPointSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x03aa, 0x300a, 0x03aa, + EVR_SQ, "IonWedgeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x03ac, 0x300a, 0x03ac, + EVR_SQ, "IonWedgePositionSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0401, 0x300a, 0x0401, + EVR_SQ, "ReferencedSetupImageSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0402, 0x300a, 0x0402, + EVR_ST, "SetupImageComment", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0410, 0x300a, 0x0410, + EVR_SQ, "MotionSynchronizationSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0412, 0x300a, 0x0412, + EVR_FL, "ControlPointOrientation", 3, 3, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0420, 0x300a, 0x0420, + EVR_SQ, "GeneralAccessorySequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0421, 0x300a, 0x0421, + EVR_SH, "GeneralAccessoryID", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0422, 0x300a, 0x0422, + EVR_ST, "GeneralAccessoryDescription", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0423, 0x300a, 0x0423, + EVR_CS, "GeneralAccessoryType", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0424, 0x300a, 0x0424, + EVR_IS, "GeneralAccessoryNumber", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0425, 0x300a, 0x0425, + EVR_FL, "SourceToGeneralAccessoryDistance", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0431, 0x300a, 0x0431, + EVR_SQ, "ApplicatorGeometrySequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0432, 0x300a, 0x0432, + EVR_CS, "ApplicatorApertureShape", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0433, 0x300a, 0x0433, + EVR_FL, "ApplicatorOpening", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0434, 0x300a, 0x0434, + EVR_FL, "ApplicatorOpeningX", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0435, 0x300a, 0x0435, + EVR_FL, "ApplicatorOpeningY", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0436, 0x300a, 0x0436, + EVR_FL, "SourceToApplicatorMountingPositionDistance", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0440, 0x300a, 0x0440, + EVR_IS, "NumberOfBlockSlabItems", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0441, 0x300a, 0x0441, + EVR_SQ, "BlockSlabSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0442, 0x300a, 0x0442, + EVR_DS, "BlockSlabThickness", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0443, 0x300a, 0x0443, + EVR_US, "BlockSlabNumber", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0450, 0x300a, 0x0450, + EVR_SQ, "DeviceMotionControlSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0451, 0x300a, 0x0451, + EVR_CS, "DeviceMotionExecutionMode", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0452, 0x300a, 0x0452, + EVR_CS, "DeviceMotionObservationMode", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300a, 0x0453, 0x300a, 0x0453, + EVR_SQ, "DeviceMotionParameterCodeSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300c, 0x0002, 0x300c, 0x0002, + EVR_SQ, "ReferencedRTPlanSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300c, 0x0004, 0x300c, 0x0004, + EVR_SQ, "ReferencedBeamSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300c, 0x0006, 0x300c, 0x0006, + EVR_IS, "ReferencedBeamNumber", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300c, 0x0007, 0x300c, 0x0007, + EVR_IS, "ReferencedReferenceImageNumber", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300c, 0x0008, 0x300c, 0x0008, + EVR_DS, "StartCumulativeMetersetWeight", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300c, 0x0009, 0x300c, 0x0009, + EVR_DS, "EndCumulativeMetersetWeight", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300c, 0x000a, 0x300c, 0x000a, + EVR_SQ, "ReferencedBrachyApplicationSetupSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300c, 0x000c, 0x300c, 0x000c, + EVR_IS, "ReferencedBrachyApplicationSetupNumber", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300c, 0x000e, 0x300c, 0x000e, + EVR_IS, "ReferencedSourceNumber", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300c, 0x0020, 0x300c, 0x0020, + EVR_SQ, "ReferencedFractionGroupSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300c, 0x0022, 0x300c, 0x0022, + EVR_IS, "ReferencedFractionGroupNumber", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300c, 0x0040, 0x300c, 0x0040, + EVR_SQ, "ReferencedVerificationImageSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300c, 0x0042, 0x300c, 0x0042, + EVR_SQ, "ReferencedReferenceImageSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300c, 0x0050, 0x300c, 0x0050, + EVR_SQ, "ReferencedDoseReferenceSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300c, 0x0051, 0x300c, 0x0051, + EVR_IS, "ReferencedDoseReferenceNumber", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300c, 0x0055, 0x300c, 0x0055, + EVR_SQ, "BrachyReferencedDoseReferenceSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300c, 0x0060, 0x300c, 0x0060, + EVR_SQ, "ReferencedStructureSetSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300c, 0x006a, 0x300c, 0x006a, + EVR_IS, "ReferencedPatientSetupNumber", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300c, 0x0080, 0x300c, 0x0080, + EVR_SQ, "ReferencedDoseSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300c, 0x00a0, 0x300c, 0x00a0, + EVR_IS, "ReferencedToleranceTableNumber", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300c, 0x00b0, 0x300c, 0x00b0, + EVR_SQ, "ReferencedBolusSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300c, 0x00c0, 0x300c, 0x00c0, + EVR_IS, "ReferencedWedgeNumber", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300c, 0x00d0, 0x300c, 0x00d0, + EVR_IS, "ReferencedCompensatorNumber", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300c, 0x00e0, 0x300c, 0x00e0, + EVR_IS, "ReferencedBlockNumber", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300c, 0x00f0, 0x300c, 0x00f0, + EVR_IS, "ReferencedControlPointIndex", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300c, 0x00f2, 0x300c, 0x00f2, + EVR_SQ, "ReferencedControlPointSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300c, 0x00f4, 0x300c, 0x00f4, + EVR_IS, "ReferencedStartControlPointIndex", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300c, 0x00f6, 0x300c, 0x00f6, + EVR_IS, "ReferencedStopControlPointIndex", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300c, 0x0100, 0x300c, 0x0100, + EVR_IS, "ReferencedRangeShifterNumber", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300c, 0x0102, 0x300c, 0x0102, + EVR_IS, "ReferencedLateralSpreadingDeviceNumber", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300c, 0x0104, 0x300c, 0x0104, + EVR_IS, "ReferencedRangeModulatorNumber", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300c, 0x0111, 0x300c, 0x0111, + EVR_SQ, "OmittedBeamTaskSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300c, 0x0112, 0x300c, 0x0112, + EVR_CS, "ReasonForOmission", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300c, 0x0113, 0x300c, 0x0113, + EVR_LO, "ReasonForOmissionDescription", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300e, 0x0002, 0x300e, 0x0002, + EVR_CS, "ApprovalStatus", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300e, 0x0004, 0x300e, 0x0004, + EVR_DA, "ReviewDate", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300e, 0x0005, 0x300e, 0x0005, + EVR_TM, "ReviewTime", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x300e, 0x0008, 0x300e, 0x0008, + EVR_PN, "ReviewerName", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } +#ifdef ENABLE_PRIVATE_TAGS + , { 0x3f01, 0x0001, 0x3f01, 0x0001, + EVR_LO, "InstitutionCode", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "INTELERAD MEDICAL SYSTEMS" } + , { 0x3f01, 0x0002, 0x3f01, 0x0002, + EVR_LO, "RoutedTransferAE", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "INTELERAD MEDICAL SYSTEMS" } + , { 0x3f01, 0x0003, 0x3f01, 0x0003, + EVR_LO, "SourceAE", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "INTELERAD MEDICAL SYSTEMS" } + , { 0x3f01, 0x0004, 0x3f01, 0x0004, + EVR_SH, "DeferredValidation", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "INTELERAD MEDICAL SYSTEMS" } + , { 0x3f01, 0x0005, 0x3f01, 0x0005, + EVR_LO, "SeriesOwner", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "INTELERAD MEDICAL SYSTEMS" } + , { 0x3f01, 0x0006, 0x3f01, 0x0006, + EVR_LO, "OrderGroupNumber", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "INTELERAD MEDICAL SYSTEMS" } + , { 0x3f01, 0x0007, 0x3f01, 0x0007, + EVR_SH, "StrippedPixelData", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "INTELERAD MEDICAL SYSTEMS" } + , { 0x3f01, 0x0008, 0x3f01, 0x0008, + EVR_SH, "PendingMoveRequest", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "INTELERAD MEDICAL SYSTEMS" } +#endif + , { 0x4000, 0x0010, 0x4000, 0x0010, + EVR_LT, "RETIRED_Arbitrary", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x4000, 0x4000, 0x4000, 0x4000, + EVR_LT, "RETIRED_TextComments", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x4008, 0x0040, 0x4008, 0x0040, + EVR_SH, "RETIRED_ResultsID", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x4008, 0x0042, 0x4008, 0x0042, + EVR_LO, "RETIRED_ResultsIDIssuer", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x4008, 0x0050, 0x4008, 0x0050, + EVR_SQ, "RETIRED_ReferencedInterpretationSequence", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x4008, 0x00ff, 0x4008, 0x00ff, + EVR_CS, "RETIRED_ReportProductionStatusTrial", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x4008, 0x0100, 0x4008, 0x0100, + EVR_DA, "RETIRED_InterpretationRecordedDate", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x4008, 0x0101, 0x4008, 0x0101, + EVR_TM, "RETIRED_InterpretationRecordedTime", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x4008, 0x0102, 0x4008, 0x0102, + EVR_PN, "RETIRED_InterpretationRecorder", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x4008, 0x0103, 0x4008, 0x0103, + EVR_LO, "RETIRED_ReferenceToRecordedSound", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x4008, 0x0108, 0x4008, 0x0108, + EVR_DA, "RETIRED_InterpretationTranscriptionDate", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x4008, 0x0109, 0x4008, 0x0109, + EVR_TM, "RETIRED_InterpretationTranscriptionTime", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x4008, 0x010a, 0x4008, 0x010a, + EVR_PN, "RETIRED_InterpretationTranscriber", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x4008, 0x010b, 0x4008, 0x010b, + EVR_ST, "RETIRED_InterpretationText", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x4008, 0x010c, 0x4008, 0x010c, + EVR_PN, "RETIRED_InterpretationAuthor", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x4008, 0x0111, 0x4008, 0x0111, + EVR_SQ, "RETIRED_InterpretationApproverSequence", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x4008, 0x0112, 0x4008, 0x0112, + EVR_DA, "RETIRED_InterpretationApprovalDate", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x4008, 0x0113, 0x4008, 0x0113, + EVR_TM, "RETIRED_InterpretationApprovalTime", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x4008, 0x0114, 0x4008, 0x0114, + EVR_PN, "RETIRED_PhysicianApprovingInterpretation", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x4008, 0x0115, 0x4008, 0x0115, + EVR_LT, "RETIRED_InterpretationDiagnosisDescription", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x4008, 0x0117, 0x4008, 0x0117, + EVR_SQ, "RETIRED_InterpretationDiagnosisCodeSequence", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x4008, 0x0118, 0x4008, 0x0118, + EVR_SQ, "RETIRED_ResultsDistributionListSequence", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x4008, 0x0119, 0x4008, 0x0119, + EVR_PN, "RETIRED_DistributionName", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x4008, 0x011a, 0x4008, 0x011a, + EVR_LO, "RETIRED_DistributionAddress", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x4008, 0x0200, 0x4008, 0x0200, + EVR_SH, "RETIRED_InterpretationID", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x4008, 0x0202, 0x4008, 0x0202, + EVR_LO, "RETIRED_InterpretationIDIssuer", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x4008, 0x0210, 0x4008, 0x0210, + EVR_CS, "RETIRED_InterpretationTypeID", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x4008, 0x0212, 0x4008, 0x0212, + EVR_CS, "RETIRED_InterpretationStatusID", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x4008, 0x0300, 0x4008, 0x0300, + EVR_ST, "RETIRED_Impressions", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x4008, 0x4000, 0x4008, 0x4000, + EVR_ST, "RETIRED_ResultsComments", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } +#ifdef ENABLE_PRIVATE_TAGS + , { 0x4009, 0x0001, 0x4009, 0x0001, + EVR_LT, "ReportID", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS ISI" } + , { 0x4009, 0x0020, 0x4009, 0x0020, + EVR_LT, "ReportStatus", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS ISI" } + , { 0x4009, 0x0030, 0x4009, 0x0030, + EVR_DA, "ReportCreationDate", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS ISI" } + , { 0x4009, 0x0070, 0x4009, 0x0070, + EVR_LT, "ReportApprovingPhysician", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS ISI" } + , { 0x4009, 0x00e0, 0x4009, 0x00e0, + EVR_LT, "ReportText", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS ISI" } + , { 0x4009, 0x00e1, 0x4009, 0x00e1, + EVR_LT, "ReportAuthor", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS ISI" } + , { 0x4009, 0x00e3, 0x4009, 0x00e3, + EVR_LT, "ReportingRadiologist", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS ISI" } +#endif + , { 0x4010, 0x0001, 0x4010, 0x0001, + EVR_CS, "LowEnergyDetectors", 1, 1, "DICOM/DICOS", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x4010, 0x0002, 0x4010, 0x0002, + EVR_CS, "HighEnergyDetectors", 1, 1, "DICOM/DICOS", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x4010, 0x0004, 0x4010, 0x0004, + EVR_SQ, "DetectorGeometrySequence", 1, 1, "DICOM/DICOS", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x4010, 0x1001, 0x4010, 0x1001, + EVR_SQ, "ThreatROIVoxelSequence", 1, 1, "DICOM/DICOS", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x4010, 0x1004, 0x4010, 0x1004, + EVR_FL, "ThreatROIBase", 3, 3, "DICOM/DICOS", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x4010, 0x1005, 0x4010, 0x1005, + EVR_FL, "ThreatROIExtents", 3, 3, "DICOM/DICOS", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x4010, 0x1006, 0x4010, 0x1006, + EVR_OB, "ThreatROIBitmap", 1, 1, "DICOM/DICOS", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x4010, 0x1007, 0x4010, 0x1007, + EVR_SH, "RouteSegmentID", 1, 1, "DICOM/DICOS", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x4010, 0x1008, 0x4010, 0x1008, + EVR_CS, "GantryType", 1, 1, "DICOM/DICOS", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x4010, 0x1009, 0x4010, 0x1009, + EVR_CS, "OOIOwnerType", 1, 1, "DICOM/DICOS", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x4010, 0x100a, 0x4010, 0x100a, + EVR_SQ, "RouteSegmentSequence", 1, 1, "DICOM/DICOS", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x4010, 0x1010, 0x4010, 0x1010, + EVR_US, "PotentialThreatObjectID", 1, 1, "DICOM/DICOS", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x4010, 0x1011, 0x4010, 0x1011, + EVR_SQ, "ThreatSequence", 1, 1, "DICOM/DICOS", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x4010, 0x1012, 0x4010, 0x1012, + EVR_CS, "ThreatCategory", 1, 1, "DICOM/DICOS", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x4010, 0x1013, 0x4010, 0x1013, + EVR_LT, "ThreatCategoryDescription", 1, 1, "DICOM/DICOS", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x4010, 0x1014, 0x4010, 0x1014, + EVR_CS, "ATDAbilityAssessment", 1, 1, "DICOM/DICOS", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x4010, 0x1015, 0x4010, 0x1015, + EVR_CS, "ATDAssessmentFlag", 1, 1, "DICOM/DICOS", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x4010, 0x1016, 0x4010, 0x1016, + EVR_FL, "ATDAssessmentProbability", 1, 1, "DICOM/DICOS", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x4010, 0x1017, 0x4010, 0x1017, + EVR_FL, "Mass", 1, 1, "DICOM/DICOS", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x4010, 0x1018, 0x4010, 0x1018, + EVR_FL, "Density", 1, 1, "DICOM/DICOS", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x4010, 0x1019, 0x4010, 0x1019, + EVR_FL, "ZEffective", 1, 1, "DICOM/DICOS", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x4010, 0x101a, 0x4010, 0x101a, + EVR_SH, "BoardingPassID", 1, 1, "DICOM/DICOS", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x4010, 0x101b, 0x4010, 0x101b, + EVR_FL, "CenterOfMass", 3, 3, "DICOM/DICOS", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x4010, 0x101c, 0x4010, 0x101c, + EVR_FL, "CenterOfPTO", 3, 3, "DICOM/DICOS", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x4010, 0x101d, 0x4010, 0x101d, + EVR_FL, "BoundingPolygon", 6, -1, "DICOM/DICOS", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x4010, 0x101e, 0x4010, 0x101e, + EVR_SH, "RouteSegmentStartLocationID", 1, 1, "DICOM/DICOS", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x4010, 0x101f, 0x4010, 0x101f, + EVR_SH, "RouteSegmentEndLocationID", 1, 1, "DICOM/DICOS", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x4010, 0x1020, 0x4010, 0x1020, + EVR_CS, "RouteSegmentLocationIDType", 1, 1, "DICOM/DICOS", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x4010, 0x1021, 0x4010, 0x1021, + EVR_CS, "AbortReason", 1, -1, "DICOM/DICOS", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x4010, 0x1023, 0x4010, 0x1023, + EVR_FL, "VolumeOfPTO", 1, 1, "DICOM/DICOS", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x4010, 0x1024, 0x4010, 0x1024, + EVR_CS, "AbortFlag", 1, 1, "DICOM/DICOS", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x4010, 0x1025, 0x4010, 0x1025, + EVR_DT, "RouteSegmentStartTime", 1, 1, "DICOM/DICOS", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x4010, 0x1026, 0x4010, 0x1026, + EVR_DT, "RouteSegmentEndTime", 1, 1, "DICOM/DICOS", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x4010, 0x1027, 0x4010, 0x1027, + EVR_CS, "TDRType", 1, 1, "DICOM/DICOS", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x4010, 0x1028, 0x4010, 0x1028, + EVR_CS, "InternationalRouteSegment", 1, 1, "DICOM/DICOS", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x4010, 0x1029, 0x4010, 0x1029, + EVR_LO, "ThreatDetectionAlgorithmandVersion", 1, -1, "DICOM/DICOS", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x4010, 0x102a, 0x4010, 0x102a, + EVR_SH, "AssignedLocation", 1, 1, "DICOM/DICOS", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x4010, 0x102b, 0x4010, 0x102b, + EVR_DT, "AlarmDecisionTime", 1, 1, "DICOM/DICOS", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x4010, 0x1031, 0x4010, 0x1031, + EVR_CS, "AlarmDecision", 1, 1, "DICOM/DICOS", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x4010, 0x1033, 0x4010, 0x1033, + EVR_US, "NumberOfTotalObjects", 1, 1, "DICOM/DICOS", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x4010, 0x1034, 0x4010, 0x1034, + EVR_US, "NumberOfAlarmObjects", 1, 1, "DICOM/DICOS", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x4010, 0x1037, 0x4010, 0x1037, + EVR_SQ, "PTORepresentationSequence", 1, 1, "DICOM/DICOS", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x4010, 0x1038, 0x4010, 0x1038, + EVR_SQ, "ATDAssessmentSequence", 1, 1, "DICOM/DICOS", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x4010, 0x1039, 0x4010, 0x1039, + EVR_CS, "TIPType", 1, 1, "DICOM/DICOS", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x4010, 0x103a, 0x4010, 0x103a, + EVR_CS, "DICOSVersion", 1, 1, "DICOM/DICOS", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x4010, 0x1041, 0x4010, 0x1041, + EVR_DT, "OOIOwnerCreationTime", 1, 1, "DICOM/DICOS", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x4010, 0x1042, 0x4010, 0x1042, + EVR_CS, "OOIType", 1, 1, "DICOM/DICOS", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x4010, 0x1043, 0x4010, 0x1043, + EVR_FL, "OOISize", 3, 3, "DICOM/DICOS", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x4010, 0x1044, 0x4010, 0x1044, + EVR_CS, "AcquisitionStatus", 1, 1, "DICOM/DICOS", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x4010, 0x1045, 0x4010, 0x1045, + EVR_SQ, "BasisMaterialsCodeSequence", 1, 1, "DICOM/DICOS", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x4010, 0x1046, 0x4010, 0x1046, + EVR_CS, "PhantomType", 1, 1, "DICOM/DICOS", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x4010, 0x1047, 0x4010, 0x1047, + EVR_SQ, "OOIOwnerSequence", 1, 1, "DICOM/DICOS", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x4010, 0x1048, 0x4010, 0x1048, + EVR_CS, "ScanType", 1, 1, "DICOM/DICOS", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x4010, 0x1051, 0x4010, 0x1051, + EVR_LO, "ItineraryID", 1, 1, "DICOM/DICOS", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x4010, 0x1052, 0x4010, 0x1052, + EVR_SH, "ItineraryIDType", 1, 1, "DICOM/DICOS", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x4010, 0x1053, 0x4010, 0x1053, + EVR_LO, "ItineraryIDAssigningAuthority", 1, 1, "DICOM/DICOS", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x4010, 0x1054, 0x4010, 0x1054, + EVR_SH, "RouteID", 1, 1, "DICOM/DICOS", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x4010, 0x1055, 0x4010, 0x1055, + EVR_SH, "RouteIDAssigningAuthority", 1, 1, "DICOM/DICOS", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x4010, 0x1056, 0x4010, 0x1056, + EVR_CS, "InboundArrivalType", 1, 1, "DICOM/DICOS", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x4010, 0x1058, 0x4010, 0x1058, + EVR_SH, "CarrierID", 1, 1, "DICOM/DICOS", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x4010, 0x1059, 0x4010, 0x1059, + EVR_CS, "CarrierIDAssigningAuthority", 1, 1, "DICOM/DICOS", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x4010, 0x1060, 0x4010, 0x1060, + EVR_FL, "SourceOrientation", 3, 3, "DICOM/DICOS", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x4010, 0x1061, 0x4010, 0x1061, + EVR_FL, "SourcePosition", 3, 3, "DICOM/DICOS", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x4010, 0x1062, 0x4010, 0x1062, + EVR_FL, "BeltHeight", 1, 1, "DICOM/DICOS", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x4010, 0x1064, 0x4010, 0x1064, + EVR_SQ, "AlgorithmRoutingCodeSequence", 1, 1, "DICOM/DICOS", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x4010, 0x1067, 0x4010, 0x1067, + EVR_CS, "TransportClassification", 1, 1, "DICOM/DICOS", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x4010, 0x1068, 0x4010, 0x1068, + EVR_LT, "OOITypeDescriptor", 1, 1, "DICOM/DICOS", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x4010, 0x1069, 0x4010, 0x1069, + EVR_FL, "TotalProcessingTime", 1, 1, "DICOM/DICOS", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x4010, 0x106c, 0x4010, 0x106c, + EVR_OB, "DetectorCalibrationData", 1, 1, "DICOM/DICOS", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x4010, 0x106d, 0x4010, 0x106d, + EVR_CS, "AdditionalScreeningPerformed", 1, 1, "DICOM/DICOS", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x4010, 0x106e, 0x4010, 0x106e, + EVR_CS, "AdditionalInspectionSelectionCriteria", 1, 1, "DICOM/DICOS", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x4010, 0x106f, 0x4010, 0x106f, + EVR_SQ, "AdditionalInspectionMethodSequence", 1, 1, "DICOM/DICOS", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x4010, 0x1070, 0x4010, 0x1070, + EVR_CS, "AITDeviceType", 1, 1, "DICOM/DICOS", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x4010, 0x1071, 0x4010, 0x1071, + EVR_SQ, "QRMeasurementsSequence", 1, 1, "DICOM/DICOS", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x4010, 0x1072, 0x4010, 0x1072, + EVR_SQ, "TargetMaterialSequence", 1, 1, "DICOM/DICOS", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x4010, 0x1073, 0x4010, 0x1073, + EVR_FD, "SNRThreshold", 1, 1, "DICOM/DICOS", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x4010, 0x1075, 0x4010, 0x1075, + EVR_DS, "ImageScaleRepresentation", 1, 1, "DICOM/DICOS", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x4010, 0x1076, 0x4010, 0x1076, + EVR_SQ, "ReferencedPTOSequence", 1, 1, "DICOM/DICOS", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x4010, 0x1077, 0x4010, 0x1077, + EVR_SQ, "ReferencedTDRInstanceSequence", 1, 1, "DICOM/DICOS", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x4010, 0x1078, 0x4010, 0x1078, + EVR_ST, "PTOLocationDescription", 1, 1, "DICOM/DICOS", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x4010, 0x1079, 0x4010, 0x1079, + EVR_SQ, "AnomalyLocatorIndicatorSequence", 1, 1, "DICOM/DICOS", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x4010, 0x107a, 0x4010, 0x107a, + EVR_FL, "AnomalyLocatorIndicator", 3, 3, "DICOM/DICOS", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x4010, 0x107b, 0x4010, 0x107b, + EVR_SQ, "PTORegionSequence", 1, 1, "DICOM/DICOS", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x4010, 0x107c, 0x4010, 0x107c, + EVR_CS, "InspectionSelectionCriteria", 1, 1, "DICOM/DICOS", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x4010, 0x107d, 0x4010, 0x107d, + EVR_SQ, "SecondaryInspectionMethodSequence", 1, 1, "DICOM/DICOS", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x4010, 0x107e, 0x4010, 0x107e, + EVR_DS, "PRCSToRCSOrientation", 6, 6, "DICOM/DICOS", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x4ffe, 0x0001, 0x4ffe, 0x0001, + EVR_SQ, "MACParametersSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } +#ifdef ENABLE_PRIVATE_TAGS + , { 0x50f1, 0x0006, 0x50f1, 0x0006, + EVR_CS, "EnergySubtractionParam", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "FDMS 1.0" } + , { 0x50f1, 0x0007, 0x50f1, 0x0007, + EVR_CS, "SubtractionRegistrationResult", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "FDMS 1.0" } + , { 0x50f1, 0x0008, 0x50f1, 0x0008, + EVR_CS, "EnergySubtractionParam2", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "FDMS 1.0" } + , { 0x50f1, 0x0009, 0x50f1, 0x0009, + EVR_SL, "AfinConversionCoefficient", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "FDMS 1.0" } + , { 0x50f1, 0x0010, 0x50f1, 0x0010, + EVR_CS, "FilmOutputFormat", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "FDMS 1.0" } + , { 0x50f1, 0x0020, 0x50f1, 0x0020, + EVR_CS, "ImageProcessingModificationFlag", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "FDMS 1.0" } +#endif + , { 0x5200, 0x9229, 0x5200, 0x9229, + EVR_SQ, "SharedFunctionalGroupsSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x5200, 0x9230, 0x5200, 0x9230, + EVR_SQ, "PerFrameFunctionalGroupsSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x5400, 0x0100, 0x5400, 0x0100, + EVR_SQ, "WaveformSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x5400, 0x0110, 0x5400, 0x0110, + EVR_ox, "ChannelMinimumValue", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x5400, 0x0112, 0x5400, 0x0112, + EVR_ox, "ChannelMaximumValue", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x5400, 0x1004, 0x5400, 0x1004, + EVR_US, "WaveformBitsAllocated", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x5400, 0x1006, 0x5400, 0x1006, + EVR_CS, "WaveformSampleInterpretation", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x5400, 0x100a, 0x5400, 0x100a, + EVR_ox, "WaveformPaddingValue", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x5400, 0x1010, 0x5400, 0x1010, + EVR_ox, "WaveformData", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x5600, 0x0010, 0x5600, 0x0010, + EVR_OF, "FirstOrderPhaseCorrectionAngle", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x5600, 0x0020, 0x5600, 0x0020, + EVR_OF, "SpectroscopyData", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } +#ifdef ENABLE_PRIVATE_TAGS + , { 0x6001, 0x0000, 0x6001, 0x0000, + EVR_LT, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "PHILIPS MR/LAST" } + , { 0x6021, 0x0000, 0x6021, 0x0000, + EVR_LT, "ImageGraphicsFormatCode", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CM VA0 CMS" } + , { 0x6021, 0x0000, 0x6021, 0x0000, + EVR_LT, "OsteoContourComment", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CT VA0 OST" } + , { 0x6021, 0x0010, 0x6021, 0x0010, + EVR_LT, "ImageGraphics", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CM VA0 CMS" } + , { 0x6021, 0x0010, 0x6021, 0x0010, + EVR_US, "OsteoContourBuffer", 256, 256, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CT VA0 OST" } + , { 0x7001, 0x0001, 0x7001, 0x0001, + EVR_UI, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Picker NM Private Group" } + , { 0x7001, 0x0002, 0x7001, 0x0002, + EVR_OB, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "Picker NM Private Group" } + , { 0x7001, 0x0010, 0x7001, 0x0010, + EVR_LT, "Dummy", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MED" } + , { 0x7003, 0x0010, 0x7003, 0x0010, + EVR_LT, "Header", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MED" } + , { 0x7005, 0x0010, 0x7005, 0x0010, + EVR_LT, "Dummy", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS MED" } +#endif + , { 0x7fe0, 0x0008, 0x7fe0, 0x0008, + EVR_OF, "FloatPixelData", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x7fe0, 0x0009, 0x7fe0, 0x0009, + EVR_OD, "DoubleFloatPixelData", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x7fe0, 0x0010, 0x7fe0, 0x0010, + EVR_ox, "PixelData", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x7fe0, 0x0020, 0x7fe0, 0x0020, + EVR_OW, "RETIRED_CoefficientsSDVN", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x7fe0, 0x0030, 0x7fe0, 0x0030, + EVR_OW, "RETIRED_CoefficientsSDHN", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x7fe0, 0x0040, 0x7fe0, 0x0040, + EVR_OW, "RETIRED_CoefficientsSDDN", 1, 1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } +#ifdef ENABLE_PRIVATE_TAGS + , { 0x7fe1, 0x0000, 0x7fe1, 0x0000, + EVR_OB, "BinaryData", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CM VA0 CMS" } + , { 0x7fe1, 0x0010, 0x7fe1, 0x0010, + EVR_OB, "CSAData", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS CSA NON-IMAGE" } + , { 0x7fe1, 0x0010, 0x7fe1, 0x0010, + EVR_ox, "PixelData", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SPI-P Release 1" } + , { 0x7fe3, 0x0000, 0x7fe3, 0x0000, + EVR_LT, "ImageGraphicsFormatCode", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS NUMARIS II" } + , { 0x7fe3, 0x0010, 0x7fe3, 0x0010, + EVR_OB, "ImageGraphics", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS NUMARIS II" } + , { 0x7fe3, 0x0020, 0x7fe3, 0x0020, + EVR_OB, "ImageGraphicsDummy", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "SIEMENS NUMARIS II" } + , { 0x7ff1, 0x0001, 0x7ff1, 0x0001, + EVR_US, "Unknown", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "TOSHIBA_MEC_1.0" } + , { 0x7ff1, 0x0001, 0x7ff1, 0x0001, + EVR_US, "Unknown", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "TOSHIBA_MEC_CT_1.0" } + , { 0x7ff1, 0x0002, 0x7ff1, 0x0002, + EVR_US, "Unknown", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "TOSHIBA_MEC_1.0" } + , { 0x7ff1, 0x0002, 0x7ff1, 0x0002, + EVR_US, "Unknown", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "TOSHIBA_MEC_CT_1.0" } + , { 0x7ff1, 0x0003, 0x7ff1, 0x0003, + EVR_US, "Unknown", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "TOSHIBA_MEC_1.0" } + , { 0x7ff1, 0x0003, 0x7ff1, 0x0003, + EVR_IS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "TOSHIBA_MEC_CT_1.0" } + , { 0x7ff1, 0x0004, 0x7ff1, 0x0004, + EVR_IS, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "TOSHIBA_MEC_CT_1.0" } + , { 0x7ff1, 0x0005, 0x7ff1, 0x0005, + EVR_US, "Unknown", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "TOSHIBA_MEC_CT_1.0" } + , { 0x7ff1, 0x0007, 0x7ff1, 0x0007, + EVR_US, "Unknown", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "TOSHIBA_MEC_CT_1.0" } + , { 0x7ff1, 0x0008, 0x7ff1, 0x0008, + EVR_US, "Unknown", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "TOSHIBA_MEC_CT_1.0" } + , { 0x7ff1, 0x0009, 0x7ff1, 0x0009, + EVR_US, "Unknown", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "TOSHIBA_MEC_CT_1.0" } + , { 0x7ff1, 0x000a, 0x7ff1, 0x000a, + EVR_LT, "Unknown", 1, 1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "TOSHIBA_MEC_CT_1.0" } + , { 0x7ff1, 0x000b, 0x7ff1, 0x000b, + EVR_US, "Unknown", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "TOSHIBA_MEC_CT_1.0" } + , { 0x7ff1, 0x000c, 0x7ff1, 0x000c, + EVR_US, "Unknown", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "TOSHIBA_MEC_CT_1.0" } + , { 0x7ff1, 0x000d, 0x7ff1, 0x000d, + EVR_US, "Unknown", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "TOSHIBA_MEC_CT_1.0" } + , { 0x7ff1, 0x0010, 0x7ff1, 0x0010, + EVR_US, "Unknown", 1, -1, "PrivateTag", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + "TOSHIBA_MEC_1.0" } +#endif + , { 0xfffa, 0xfffa, 0xfffa, 0xfffa, + EVR_SQ, "DigitalSignaturesSequence", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0xfffc, 0xfffc, 0xfffc, 0xfffc, + EVR_OB, "DataSetTrailingPadding", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0xfffe, 0xe000, 0xfffe, 0xe000, + EVR_na, "Item", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0xfffe, 0xe00d, 0xfffe, 0xe00d, + EVR_na, "ItemDelimitationItem", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0xfffe, 0xe0dd, 0xfffe, 0xe0dd, + EVR_na, "SequenceDelimitationItem", 1, 1, "DICOM", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x6000, 0x0010, 0x60ff, 0x0010, + EVR_US, "OverlayRows", 1, 1, "DICOM", + DcmDictRange_Even, DcmDictRange_Unspecified, + NULL } + , { 0x6000, 0x0011, 0x60ff, 0x0011, + EVR_US, "OverlayColumns", 1, 1, "DICOM", + DcmDictRange_Even, DcmDictRange_Unspecified, + NULL } + , { 0x6000, 0x0015, 0x60ff, 0x0015, + EVR_IS, "NumberOfFramesInOverlay", 1, 1, "DICOM", + DcmDictRange_Even, DcmDictRange_Unspecified, + NULL } + , { 0x6000, 0x0022, 0x60ff, 0x0022, + EVR_LO, "OverlayDescription", 1, 1, "DICOM", + DcmDictRange_Even, DcmDictRange_Unspecified, + NULL } + , { 0x6000, 0x0040, 0x60ff, 0x0040, + EVR_CS, "OverlayType", 1, 1, "DICOM", + DcmDictRange_Even, DcmDictRange_Unspecified, + NULL } + , { 0x6000, 0x0045, 0x60ff, 0x0045, + EVR_LO, "OverlaySubtype", 1, 1, "DICOM", + DcmDictRange_Even, DcmDictRange_Unspecified, + NULL } + , { 0x6000, 0x0050, 0x60ff, 0x0050, + EVR_SS, "OverlayOrigin", 2, 2, "DICOM", + DcmDictRange_Even, DcmDictRange_Unspecified, + NULL } + , { 0x6000, 0x0051, 0x60ff, 0x0051, + EVR_US, "ImageFrameOrigin", 1, 1, "DICOM", + DcmDictRange_Even, DcmDictRange_Unspecified, + NULL } + , { 0x6000, 0x0100, 0x60ff, 0x0100, + EVR_US, "OverlayBitsAllocated", 1, 1, "DICOM", + DcmDictRange_Even, DcmDictRange_Unspecified, + NULL } + , { 0x6000, 0x0102, 0x60ff, 0x0102, + EVR_US, "OverlayBitPosition", 1, 1, "DICOM", + DcmDictRange_Even, DcmDictRange_Unspecified, + NULL } + , { 0x6000, 0x1001, 0x60ff, 0x1001, + EVR_CS, "OverlayActivationLayer", 1, 1, "DICOM", + DcmDictRange_Even, DcmDictRange_Unspecified, + NULL } + , { 0x6000, 0x1301, 0x60ff, 0x1301, + EVR_IS, "ROIArea", 1, 1, "DICOM", + DcmDictRange_Even, DcmDictRange_Unspecified, + NULL } + , { 0x6000, 0x1302, 0x60ff, 0x1302, + EVR_DS, "ROIMean", 1, 1, "DICOM", + DcmDictRange_Even, DcmDictRange_Unspecified, + NULL } + , { 0x6000, 0x1303, 0x60ff, 0x1303, + EVR_DS, "ROIStandardDeviation", 1, 1, "DICOM", + DcmDictRange_Even, DcmDictRange_Unspecified, + NULL } + , { 0x6000, 0x1500, 0x60ff, 0x1500, + EVR_LO, "OverlayLabel", 1, 1, "DICOM", + DcmDictRange_Even, DcmDictRange_Unspecified, + NULL } + , { 0x6000, 0x3000, 0x60ff, 0x3000, + EVR_ox, "OverlayData", 1, 1, "DICOM", + DcmDictRange_Even, DcmDictRange_Unspecified, + NULL } + , { 0x0009, 0x0000, 0xffff, 0x0000, + EVR_UL, "PrivateGroupLength", 1, 1, "PRIVATE", + DcmDictRange_Odd, DcmDictRange_Unspecified, + NULL } + , { 0x5000, 0x0010, 0x50ff, 0x0010, + EVR_US, "RETIRED_NumberOfPoints", 1, 1, "DICOM/retired", + DcmDictRange_Even, DcmDictRange_Unspecified, + NULL } + , { 0x5000, 0x0020, 0x50ff, 0x0020, + EVR_CS, "RETIRED_TypeOfData", 1, 1, "DICOM/retired", + DcmDictRange_Even, DcmDictRange_Unspecified, + NULL } + , { 0x5000, 0x0022, 0x50ff, 0x0022, + EVR_LO, "RETIRED_CurveDescription", 1, 1, "DICOM/retired", + DcmDictRange_Even, DcmDictRange_Unspecified, + NULL } + , { 0x5000, 0x0030, 0x50ff, 0x0030, + EVR_SH, "RETIRED_AxisUnits", 1, -1, "DICOM/retired", + DcmDictRange_Even, DcmDictRange_Unspecified, + NULL } + , { 0x5000, 0x0040, 0x50ff, 0x0040, + EVR_SH, "RETIRED_AxisLabels", 1, -1, "DICOM/retired", + DcmDictRange_Even, DcmDictRange_Unspecified, + NULL } + , { 0x6000, 0x0012, 0x60ff, 0x0012, + EVR_US, "RETIRED_OverlayPlanes", 1, 1, "DICOM/retired", + DcmDictRange_Even, DcmDictRange_Unspecified, + NULL } + , { 0x6000, 0x0052, 0x60ff, 0x0052, + EVR_US, "RETIRED_OverlayPlaneOrigin", 1, 1, "DICOM/retired", + DcmDictRange_Even, DcmDictRange_Unspecified, + NULL } + , { 0x6000, 0x0060, 0x60ff, 0x0060, + EVR_CS, "RETIRED_OverlayCompressionCode", 1, 1, "DICOM/retired", + DcmDictRange_Even, DcmDictRange_Unspecified, + NULL } + , { 0x6000, 0x0061, 0x60ff, 0x0061, + EVR_SH, "RETIRED_OverlayCompressionOriginator", 1, 1, "DICOM/retired", + DcmDictRange_Even, DcmDictRange_Unspecified, + NULL } + , { 0x6000, 0x0062, 0x60ff, 0x0062, + EVR_SH, "RETIRED_OverlayCompressionLabel", 1, 1, "DICOM/retired", + DcmDictRange_Even, DcmDictRange_Unspecified, + NULL } + , { 0x6000, 0x0063, 0x60ff, 0x0063, + EVR_CS, "RETIRED_OverlayCompressionDescription", 1, 1, "DICOM/retired", + DcmDictRange_Even, DcmDictRange_Unspecified, + NULL } + , { 0x6000, 0x0066, 0x60ff, 0x0066, + EVR_AT, "RETIRED_OverlayCompressionStepPointers", 1, -1, "DICOM/retired", + DcmDictRange_Even, DcmDictRange_Unspecified, + NULL } + , { 0x6000, 0x0068, 0x60ff, 0x0068, + EVR_US, "RETIRED_OverlayRepeatInterval", 1, 1, "DICOM/retired", + DcmDictRange_Even, DcmDictRange_Unspecified, + NULL } + , { 0x6000, 0x0069, 0x60ff, 0x0069, + EVR_US, "RETIRED_OverlayBitsGrouped", 1, 1, "DICOM/retired", + DcmDictRange_Even, DcmDictRange_Unspecified, + NULL } + , { 0x7f00, 0x0010, 0x7fff, 0x0010, + EVR_ox, "RETIRED_VariablePixelData", 1, 1, "DICOM/retired", + DcmDictRange_Even, DcmDictRange_Unspecified, + NULL } + , { 0x7f00, 0x0011, 0x7fff, 0x0011, + EVR_US, "RETIRED_VariableNextDataGroup", 1, 1, "DICOM/retired", + DcmDictRange_Even, DcmDictRange_Unspecified, + NULL } + , { 0x7f00, 0x0020, 0x7fff, 0x0020, + EVR_OW, "RETIRED_VariableCoefficientsSDVN", 1, 1, "DICOM/retired", + DcmDictRange_Even, DcmDictRange_Unspecified, + NULL } + , { 0x7f00, 0x0030, 0x7fff, 0x0030, + EVR_OW, "RETIRED_VariableCoefficientsSDHN", 1, 1, "DICOM/retired", + DcmDictRange_Even, DcmDictRange_Unspecified, + NULL } + , { 0x7f00, 0x0040, 0x7fff, 0x0040, + EVR_OW, "RETIRED_VariableCoefficientsSDDN", 1, 1, "DICOM/retired", + DcmDictRange_Even, DcmDictRange_Unspecified, + NULL } + , { 0x0009, 0x0010, 0xffff, 0x00ff, + EVR_LO, "PrivateCreator", 1, 1, "PRIVATE", + DcmDictRange_Odd, DcmDictRange_Unspecified, + NULL } + , { 0x0001, 0x0000, 0x0007, 0x0000, + EVR_UL, "IllegalGroupLength", 1, 1, "ILLEGAL", + DcmDictRange_Odd, DcmDictRange_Unspecified, + NULL } + , { 0x0001, 0x0010, 0x0007, 0x00ff, + EVR_LO, "IllegalPrivateCreator", 1, 1, "ILLEGAL", + DcmDictRange_Odd, DcmDictRange_Unspecified, + NULL } + , { 0x0000, 0x0000, 0xffff, 0x0000, + EVR_UL, "GenericGroupLength", 1, 1, "GENERIC", + DcmDictRange_Unspecified, DcmDictRange_Unspecified, + NULL } + , { 0x0020, 0x3100, 0x0020, 0x31ff, + EVR_CS, "RETIRED_SourceImageIDs", 1, -1, "DICOM/retired", + DcmDictRange_Unspecified, DcmDictRange_Even, + NULL } + , { 0x5000, 0x0005, 0x50ff, 0x0005, + EVR_US, "RETIRED_CurveDimensions", 1, 1, "DICOM/retired", + DcmDictRange_Even, DcmDictRange_Unspecified, + NULL } + , { 0x5000, 0x0103, 0x50ff, 0x0103, + EVR_US, "RETIRED_DataValueRepresentation", 1, 1, "DICOM/retired", + DcmDictRange_Even, DcmDictRange_Unspecified, + NULL } + , { 0x5000, 0x0104, 0x50ff, 0x0104, + EVR_US, "RETIRED_MinimumCoordinateValue", 1, -1, "DICOM/retired", + DcmDictRange_Even, DcmDictRange_Unspecified, + NULL } + , { 0x5000, 0x0105, 0x50ff, 0x0105, + EVR_US, "RETIRED_MaximumCoordinateValue", 1, -1, "DICOM/retired", + DcmDictRange_Even, DcmDictRange_Unspecified, + NULL } + , { 0x5000, 0x0106, 0x50ff, 0x0106, + EVR_SH, "RETIRED_CurveRange", 1, -1, "DICOM/retired", + DcmDictRange_Even, DcmDictRange_Unspecified, + NULL } + , { 0x5000, 0x0110, 0x50ff, 0x0110, + EVR_US, "RETIRED_CurveDataDescriptor", 1, -1, "DICOM/retired", + DcmDictRange_Even, DcmDictRange_Unspecified, + NULL } + , { 0x5000, 0x0112, 0x50ff, 0x0112, + EVR_US, "RETIRED_CoordinateStartValue", 1, -1, "DICOM/retired", + DcmDictRange_Even, DcmDictRange_Unspecified, + NULL } + , { 0x5000, 0x0114, 0x50ff, 0x0114, + EVR_US, "RETIRED_CoordinateStepValue", 1, -1, "DICOM/retired", + DcmDictRange_Even, DcmDictRange_Unspecified, + NULL } + , { 0x5000, 0x1001, 0x50ff, 0x1001, + EVR_CS, "RETIRED_CurveActivationLayer", 1, 1, "DICOM/retired", + DcmDictRange_Even, DcmDictRange_Unspecified, + NULL } + , { 0x5000, 0x2000, 0x50ff, 0x2000, + EVR_US, "RETIRED_AudioType", 1, 1, "DICOM/retired", + DcmDictRange_Even, DcmDictRange_Unspecified, + NULL } + , { 0x5000, 0x2002, 0x50ff, 0x2002, + EVR_US, "RETIRED_AudioSampleFormat", 1, 1, "DICOM/retired", + DcmDictRange_Even, DcmDictRange_Unspecified, + NULL } + , { 0x5000, 0x2004, 0x50ff, 0x2004, + EVR_US, "RETIRED_NumberOfChannels", 1, 1, "DICOM/retired", + DcmDictRange_Even, DcmDictRange_Unspecified, + NULL } + , { 0x5000, 0x2006, 0x50ff, 0x2006, + EVR_UL, "RETIRED_NumberOfSamples", 1, 1, "DICOM/retired", + DcmDictRange_Even, DcmDictRange_Unspecified, + NULL } + , { 0x5000, 0x2008, 0x50ff, 0x2008, + EVR_UL, "RETIRED_SampleRate", 1, 1, "DICOM/retired", + DcmDictRange_Even, DcmDictRange_Unspecified, + NULL } + , { 0x5000, 0x200a, 0x50ff, 0x200a, + EVR_UL, "RETIRED_TotalTime", 1, 1, "DICOM/retired", + DcmDictRange_Even, DcmDictRange_Unspecified, + NULL } + , { 0x5000, 0x200c, 0x50ff, 0x200c, + EVR_ox, "RETIRED_AudioSampleData", 1, 1, "DICOM/retired", + DcmDictRange_Even, DcmDictRange_Unspecified, + NULL } + , { 0x5000, 0x200e, 0x50ff, 0x200e, + EVR_LT, "RETIRED_AudioComments", 1, 1, "DICOM/retired", + DcmDictRange_Even, DcmDictRange_Unspecified, + NULL } + , { 0x5000, 0x2500, 0x50ff, 0x2500, + EVR_LO, "RETIRED_CurveLabel", 1, 1, "DICOM/retired", + DcmDictRange_Even, DcmDictRange_Unspecified, + NULL } + , { 0x5000, 0x2600, 0x50ff, 0x2600, + EVR_SQ, "RETIRED_CurveReferencedOverlaySequence", 1, 1, "DICOM/retired", + DcmDictRange_Even, DcmDictRange_Unspecified, + NULL } + , { 0x5000, 0x2610, 0x50ff, 0x2610, + EVR_US, "RETIRED_CurveReferencedOverlayGroup", 1, 1, "DICOM/retired", + DcmDictRange_Even, DcmDictRange_Unspecified, + NULL } + , { 0x5000, 0x3000, 0x50ff, 0x3000, + EVR_ox, "RETIRED_CurveData", 1, 1, "DICOM/retired", + DcmDictRange_Even, DcmDictRange_Unspecified, + NULL } + , { 0x6000, 0x0110, 0x60ff, 0x0110, + EVR_CS, "RETIRED_OverlayFormat", 1, 1, "DICOM/retired", + DcmDictRange_Even, DcmDictRange_Unspecified, + NULL } + , { 0x6000, 0x0200, 0x60ff, 0x0200, + EVR_US, "RETIRED_OverlayLocation", 1, 1, "DICOM/retired", + DcmDictRange_Even, DcmDictRange_Unspecified, + NULL } + , { 0x6000, 0x0800, 0x60ff, 0x0800, + EVR_CS, "RETIRED_OverlayCodeLabel", 1, -1, "DICOM/retired", + DcmDictRange_Even, DcmDictRange_Unspecified, + NULL } + , { 0x6000, 0x0802, 0x60ff, 0x0802, + EVR_US, "RETIRED_OverlayNumberOfTables", 1, 1, "DICOM/retired", + DcmDictRange_Even, DcmDictRange_Unspecified, + NULL } + , { 0x6000, 0x0803, 0x60ff, 0x0803, + EVR_AT, "RETIRED_OverlayCodeTableLocation", 1, -1, "DICOM/retired", + DcmDictRange_Even, DcmDictRange_Unspecified, + NULL } + , { 0x6000, 0x0804, 0x60ff, 0x0804, + EVR_US, "RETIRED_OverlayBitsForCodeWord", 1, 1, "DICOM/retired", + DcmDictRange_Even, DcmDictRange_Unspecified, + NULL } + , { 0x6000, 0x1100, 0x60ff, 0x1100, + EVR_US, "RETIRED_OverlayDescriptorGray", 1, 1, "DICOM/retired", + DcmDictRange_Even, DcmDictRange_Unspecified, + NULL } + , { 0x6000, 0x1101, 0x60ff, 0x1101, + EVR_US, "RETIRED_OverlayDescriptorRed", 1, 1, "DICOM/retired", + DcmDictRange_Even, DcmDictRange_Unspecified, + NULL } + , { 0x6000, 0x1102, 0x60ff, 0x1102, + EVR_US, "RETIRED_OverlayDescriptorGreen", 1, 1, "DICOM/retired", + DcmDictRange_Even, DcmDictRange_Unspecified, + NULL } + , { 0x6000, 0x1103, 0x60ff, 0x1103, + EVR_US, "RETIRED_OverlayDescriptorBlue", 1, 1, "DICOM/retired", + DcmDictRange_Even, DcmDictRange_Unspecified, + NULL } + , { 0x6000, 0x1200, 0x60ff, 0x1200, + EVR_US, "RETIRED_OverlaysGray", 1, -1, "DICOM/retired", + DcmDictRange_Even, DcmDictRange_Unspecified, + NULL } + , { 0x6000, 0x1201, 0x60ff, 0x1201, + EVR_US, "RETIRED_OverlaysRed", 1, -1, "DICOM/retired", + DcmDictRange_Even, DcmDictRange_Unspecified, + NULL } + , { 0x6000, 0x1202, 0x60ff, 0x1202, + EVR_US, "RETIRED_OverlaysGreen", 1, -1, "DICOM/retired", + DcmDictRange_Even, DcmDictRange_Unspecified, + NULL } + , { 0x6000, 0x1203, 0x60ff, 0x1203, + EVR_US, "RETIRED_OverlaysBlue", 1, -1, "DICOM/retired", + DcmDictRange_Even, DcmDictRange_Unspecified, + NULL } + , { 0x6000, 0x4000, 0x60ff, 0x4000, + EVR_LT, "RETIRED_OverlayComments", 1, 1, "DICOM/retired", + DcmDictRange_Even, DcmDictRange_Unspecified, + NULL } +#ifdef ENABLE_PRIVATE_TAGS + , { 0x7001, 0x0004, 0x70ff, 0x0004, + EVR_ST, "TextAnnotation", 1, 1, "PrivateTag", + DcmDictRange_Odd, DcmDictRange_Unspecified, + "DLX_ANNOT_01" } + , { 0x7001, 0x0005, 0x70ff, 0x0005, + EVR_IS, "Box", 2, 2, "PrivateTag", + DcmDictRange_Odd, DcmDictRange_Unspecified, + "DLX_ANNOT_01" } + , { 0x7001, 0x0007, 0x70ff, 0x0007, + EVR_IS, "ArrowEnd", 2, 2, "PrivateTag", + DcmDictRange_Odd, DcmDictRange_Unspecified, + "DLX_ANNOT_01" } + , { 0x6001, 0x0001, 0x60ff, 0x0001, + EVR_US, "GrayPaletteColorLookupTableDescriptor", 3, 3, "PrivateTag", + DcmDictRange_Odd, DcmDictRange_Unspecified, + "DLX_LKUP_01" } + , { 0x6001, 0x0002, 0x60ff, 0x0002, + EVR_US, "GrayPaletteColorLookupTableData", 1, 1, "PrivateTag", + DcmDictRange_Odd, DcmDictRange_Unspecified, + "DLX_LKUP_01" } + , { 0x6001, 0x0000, 0x60ff, 0x0000, + EVR_IS, "OverlayID", 1, 1, "PrivateTag", + DcmDictRange_Odd, DcmDictRange_Unspecified, + "PAPYRUS 3.0" } + , { 0x6001, 0x0001, 0x60ff, 0x0001, + EVR_LT, "LinkedOverlays", 1, -1, "PrivateTag", + DcmDictRange_Odd, DcmDictRange_Unspecified, + "PAPYRUS 3.0" } + , { 0x6001, 0x0010, 0x60ff, 0x0010, + EVR_US, "OverlayRows", 1, 1, "PrivateTag", + DcmDictRange_Odd, DcmDictRange_Unspecified, + "PAPYRUS 3.0" } + , { 0x6001, 0x0011, 0x60ff, 0x0011, + EVR_US, "OverlayColumns", 1, 1, "PrivateTag", + DcmDictRange_Odd, DcmDictRange_Unspecified, + "PAPYRUS 3.0" } + , { 0x6001, 0x0040, 0x60ff, 0x0040, + EVR_LO, "OverlayType", 1, 1, "PrivateTag", + DcmDictRange_Odd, DcmDictRange_Unspecified, + "PAPYRUS 3.0" } + , { 0x6001, 0x0050, 0x60ff, 0x0050, + EVR_US, "OverlayOrigin", 1, -1, "PrivateTag", + DcmDictRange_Odd, DcmDictRange_Unspecified, + "PAPYRUS 3.0" } + , { 0x6001, 0x0060, 0x60ff, 0x0060, + EVR_LO, "Editable", 1, 1, "PrivateTag", + DcmDictRange_Odd, DcmDictRange_Unspecified, + "PAPYRUS 3.0" } + , { 0x6001, 0x0070, 0x60ff, 0x0070, + EVR_LO, "OverlayFont", 1, 1, "PrivateTag", + DcmDictRange_Odd, DcmDictRange_Unspecified, + "PAPYRUS 3.0" } + , { 0x6001, 0x0072, 0x60ff, 0x0072, + EVR_LO, "OverlayStyle", 1, 1, "PrivateTag", + DcmDictRange_Odd, DcmDictRange_Unspecified, + "PAPYRUS 3.0" } + , { 0x6001, 0x0074, 0x60ff, 0x0074, + EVR_US, "OverlayFontSize", 1, 1, "PrivateTag", + DcmDictRange_Odd, DcmDictRange_Unspecified, + "PAPYRUS 3.0" } + , { 0x6001, 0x0076, 0x60ff, 0x0076, + EVR_LO, "OverlayColor", 1, 1, "PrivateTag", + DcmDictRange_Odd, DcmDictRange_Unspecified, + "PAPYRUS 3.0" } + , { 0x6001, 0x0078, 0x60ff, 0x0078, + EVR_US, "ShadowSize", 1, 1, "PrivateTag", + DcmDictRange_Odd, DcmDictRange_Unspecified, + "PAPYRUS 3.0" } + , { 0x6001, 0x0080, 0x60ff, 0x0080, + EVR_LO, "FillPattern", 1, 1, "PrivateTag", + DcmDictRange_Odd, DcmDictRange_Unspecified, + "PAPYRUS 3.0" } + , { 0x6001, 0x0082, 0x60ff, 0x0082, + EVR_US, "OverlayPenSize", 1, 1, "PrivateTag", + DcmDictRange_Odd, DcmDictRange_Unspecified, + "PAPYRUS 3.0" } + , { 0x6001, 0x00a0, 0x60ff, 0x00a0, + EVR_LO, "Label", 1, 1, "PrivateTag", + DcmDictRange_Odd, DcmDictRange_Unspecified, + "PAPYRUS 3.0" } + , { 0x6001, 0x00a2, 0x60ff, 0x00a2, + EVR_LT, "PostItText", 1, 1, "PrivateTag", + DcmDictRange_Odd, DcmDictRange_Unspecified, + "PAPYRUS 3.0" } + , { 0x6001, 0x00a4, 0x60ff, 0x00a4, + EVR_US, "AnchorPoint", 2, 2, "PrivateTag", + DcmDictRange_Odd, DcmDictRange_Unspecified, + "PAPYRUS 3.0" } + , { 0x6001, 0x00b0, 0x60ff, 0x00b0, + EVR_LO, "ROIType", 1, 1, "PrivateTag", + DcmDictRange_Odd, DcmDictRange_Unspecified, + "PAPYRUS 3.0" } + , { 0x6001, 0x00b2, 0x60ff, 0x00b2, + EVR_LT, "AttachedAnnotation", 1, 1, "PrivateTag", + DcmDictRange_Odd, DcmDictRange_Unspecified, + "PAPYRUS 3.0" } + , { 0x6001, 0x00ba, 0x60ff, 0x00ba, + EVR_US, "ContourPoints", 1, -1, "PrivateTag", + DcmDictRange_Odd, DcmDictRange_Unspecified, + "PAPYRUS 3.0" } + , { 0x6001, 0x00bc, 0x60ff, 0x00bc, + EVR_US, "MaskData", 1, -1, "PrivateTag", + DcmDictRange_Odd, DcmDictRange_Unspecified, + "PAPYRUS 3.0" } + , { 0x6001, 0x00c0, 0x60ff, 0x00c0, + EVR_SQ, "UINOverlaySequence", 1, 1, "PrivateTag", + DcmDictRange_Odd, DcmDictRange_Unspecified, + "PAPYRUS 3.0" } +#endif + +}; + +static const size_t simpleBuiltinDict_count = + sizeof(simpleBuiltinDict)/sizeof(DBI_SimpleEntry); + + +void +DcmDataDictionary::loadBuiltinDictionary() +{ + DcmDictEntry* e = NULL; + const DBI_SimpleEntry *b = simpleBuiltinDict; + for (size_t i=0; igroup, b->element, + b->upperGroup, b->upperElement, b->evr, + b->tagName, b->vmMin, b->vmMax, + b->standardVersion, OFFalse, b->privateCreator); + e->setGroupRangeRestriction(b->groupRestriction); + e->setElementRangeRestriction(b->elementRestriction); + addEntry(e); + } +} + + +#else // WITH_BUILTIN_DICTIONARY +void +DcmDataDictionary::loadBuiltinDictionary() +{ +/* + ** Empty Stub. + ** + ** We don't want a populated built-in data dictionary. In order to enable it, + ** define WITH_BUILTIN_DICTIONARY. To re-create the builtin dictionary from + ** a textfile like dicom.dic, use dcmdata/libsrc/mkdictbi. +*/ +} + +#endif // WITH_BUILTIN_DICTIONARY + diff --git a/dcmdata/libsrc/dcdirrec.cc b/dcmdata/libsrc/dcdirrec.cc new file mode 100644 index 00000000..cad9da7c --- /dev/null +++ b/dcmdata/libsrc/dcdirrec.cc @@ -0,0 +1,1613 @@ +/* + * + * Copyright (C) 1994-2015, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Gerd Ehlers, Andreas Barth + * + * Purpose: Implementation of class DcmDirectoryRecord + * + */ + + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#define INCLUDE_CSTDLIB +#define INCLUDE_CSTDIO +#define INCLUDE_CSTRING +#define INCLUDE_CERRNO +#define INCLUDE_CCTYPE +#define INCLUDE_LIBC +#define INCLUDE_UNISTD +#include "dcmtk/ofstd/ofstdinc.h" + +#include "dcmtk/ofstd/ofstream.h" +#include "dcmtk/ofstd/ofcast.h" + +#include "dcmtk/dcmdata/dcdirrec.h" +#include "dcmtk/dcmdata/dctk.h" +#include "dcmtk/dcmdata/dcxfer.h" +#include "dcmtk/dcmdata/dcvr.h" +#include "dcmtk/dcmdata/dcvrus.h" +#include "dcmtk/dcmdata/dcspchrs.h" + +#ifdef HAVE_UNIX_H +#if defined(macintosh) && defined (HAVE_WINSOCK_H) +/* unix.h defines timeval incompatible with winsock.h */ +#define timeval _UNWANTED_timeval +#endif +#include /* for unlink() under Metrowerks C++ (Macintosh) */ +#undef timeval +#endif + + +// ******************************** + + +static const char *DRTypeNames[] = +{ + "root", + "CURVE", + "FILM BOX", + "FILM SESSION", + "IMAGE", + "IMAGE BOX", + "INTERPRETATION", + "MODALITY LUT", + "MRDR", + "OVERLAY", + "PATIENT", + "PRINT QUEUE", + "PRIVATE", + "RESULTS", + "SERIES", + "STUDY", + "STUDY COMPONENT", + "TOPIC", + "VISIT", + "VOI LUT", + "SR DOCUMENT", /* was "STRUCT REPORT" in old frozen draft */ + "PRESENTATION", + "WAVEFORM", + "RT DOSE", + "RT STRUCTURE SET", + "RT PLAN", + "RT TREAT RECORD", + "STORED PRINT", + "KEY OBJECT DOC", + "REGISTRATION", + "FIDUCIAL", + "RAW DATA", + "SPECTROSCOPY", + "ENCAP DOC", + "VALUE MAP", + "HANGING PROTOCOL", + "STEREOMETRIC", + "HL7 STRUC DOC", + "PALETTE", + "SURFACE", + "MEASUREMENT", + "IMPLANT", + "IMPLANT GROUP", + "IMPLANT ASSY", + "PLAN", + "SURFACE SCAN" +}; + +static const short DIM_OF_DRTypeNames = OFstatic_cast(short, (sizeof(DRTypeNames) / sizeof(DRTypeNames[0]))); + + +// ******************************** + + +DcmDirectoryRecord::DcmDirectoryRecord() + : DcmItem(DCM_ItemTag), + recordsOriginFile(), + lowerLevelList(new DcmSequenceOfItems(DCM_DirectoryRecordSequence)), + DirRecordType(ERT_Private), + referencedMRDR(NULL), + numberOfReferences(0), + offsetInFile(0) +{ +} + + +// ******************************** + + +DcmDirectoryRecord::DcmDirectoryRecord(const DcmTag &tag, + const Uint32 len) + : DcmItem(tag, len), + recordsOriginFile(), + lowerLevelList(new DcmSequenceOfItems(DCM_DirectoryRecordSequence)), + DirRecordType(ERT_Private), + referencedMRDR(NULL), + numberOfReferences(0), + offsetInFile(0) +{ +} + + +// ******************************** + + +DcmDirectoryRecord::DcmDirectoryRecord(const E_DirRecType recordType, + const char *referencedFileID, + const OFFilename &sourceFilename, + DcmFileFormat *fileFormat) + : DcmItem(DCM_ItemTag), + recordsOriginFile(), + lowerLevelList(new DcmSequenceOfItems(DCM_DirectoryRecordSequence)), + DirRecordType(recordType), + referencedMRDR(NULL), + numberOfReferences(0), + offsetInFile(0) +{ + setRecordsOriginFile(sourceFilename); + + if (DirRecordType != ERT_root) + errorFlag = fillElementsAndReadSOP(referencedFileID, sourceFilename, fileFormat); +} + + +// ******************************** + + +DcmDirectoryRecord::DcmDirectoryRecord(const char *recordTypeName, + const char *referencedFileID, + const OFFilename &sourceFilename, + DcmFileFormat *fileFormat) + : DcmItem(DCM_ItemTag), + recordsOriginFile(), + lowerLevelList(new DcmSequenceOfItems(DCM_DirectoryRecordSequence)), + DirRecordType(ERT_Private), + referencedMRDR(NULL), + numberOfReferences(0), + offsetInFile(0) +{ + DirRecordType = recordNameToType(recordTypeName); + setRecordsOriginFile(sourceFilename); + + if (DirRecordType != ERT_root) + errorFlag = fillElementsAndReadSOP(referencedFileID, sourceFilename, fileFormat); +} + + +// ******************************** + + +DcmDirectoryRecord::DcmDirectoryRecord(const DcmDirectoryRecord &old) + : DcmItem(old), + recordsOriginFile(old.recordsOriginFile), + lowerLevelList(new DcmSequenceOfItems(*old.lowerLevelList)), + DirRecordType(old.DirRecordType), + referencedMRDR(old.referencedMRDR), // copies a pointer! + numberOfReferences(old.numberOfReferences), + offsetInFile(old.offsetInFile) +{ +} + + +// ******************************** + + +DcmDirectoryRecord& DcmDirectoryRecord::operator=(const DcmDirectoryRecord& obj) +{ + if (this != &obj) + { + // copy parent's member variables + DcmItem::operator=(obj); + // copy DcmDirectoryRecords' member variables + recordsOriginFile = obj.recordsOriginFile; + lowerLevelList = new DcmSequenceOfItems(*obj.lowerLevelList); + DirRecordType = obj.DirRecordType; + referencedMRDR = obj.referencedMRDR; // copies a pointer! + numberOfReferences = obj.numberOfReferences; + offsetInFile = obj.offsetInFile; + } + return *this; +} + + +// ******************************** + + +OFCondition DcmDirectoryRecord::copyFrom(const DcmObject& rhs) +{ + if (this != &rhs) + { + if (rhs.ident() != ident()) return EC_IllegalCall; + *this = OFstatic_cast(const DcmDirectoryRecord &, rhs); + } + return EC_Normal; +} + + +// ******************************** + + +DcmDirectoryRecord::~DcmDirectoryRecord() +{ + delete lowerLevelList; +} + + +// ******************************** + + +E_DirRecType DcmDirectoryRecord::recordNameToType(const char *recordTypeName) +{ + E_DirRecType recType = ERT_Private; + if (recordTypeName != NULL) + { + short i = 0; + while (i < DIM_OF_DRTypeNames && strcmp(DRTypeNames[i], recordTypeName) != 0) + i++; + + if (i < DIM_OF_DRTypeNames && strcmp(DRTypeNames[i], recordTypeName) == 0) + recType = OFstatic_cast(E_DirRecType, i); + else if (strcmp(recordTypeName,"STRUCT REPORT") == 0) + recType = ERT_SRDocument; // we recognize the old name as well + DCMDATA_TRACE("DcmDirectoryRecord::recordNameToType() input char*=\"" << recordTypeName + << "\" output enum=" << recType); + } + return recType; +} + + +// ******************************** + + +char *DcmDirectoryRecord::buildFileName(const char *origName, + char *destName) +{ + const char *from = origName; + char *to = destName; + char c; + char lastchar = '\0'; + while ((c = *from++) != 0) + { + if (c == '\\') + { + if (lastchar != '\\') // eliminate double '\\' + *to++ = PATH_SEPARATOR; + } else { + *to++ = c; + } + lastchar = c; + } + *to = '\0'; + + /* + ** Some OS's append a '.' to the filename of a ISO9660 filesystem. + ** If the filename does not exist then try appending a '.' + */ + FILE* f = NULL; + if ((f = fopen(destName, "rb")) != NULL) + { + fclose(f); + } else { + char* newname = new char[strlen(destName) + 2]; + strcpy(newname, destName); + strcat(newname, "."); + if ((f = fopen(newname, "rb")) != NULL) + { + fclose(f); + strcpy(destName, newname); + } else { + /* we cannot find the file. let the caller deal with this */ + } + delete[] newname; + } + return destName; +} + + +// ******************************** + + +OFCondition DcmDirectoryRecord::checkHierarchy(const E_DirRecType upperRecord, + const E_DirRecType lowerRecord) +{ + OFCondition l_error = EC_IllegalCall; + switch (upperRecord) + { + case ERT_root: + switch (lowerRecord) + { + case ERT_Patient: + case ERT_PrintQueue: + case ERT_Topic: + case ERT_HangingProtocol: + case ERT_Palette: + case ERT_Implant: + case ERT_ImplantGroup: + case ERT_ImplantAssy: + case ERT_Private: + l_error = EC_Normal; + break; + default: + l_error = EC_IllegalCall; + break; + } + break; + case ERT_FilmBox: + switch (lowerRecord) + { + case ERT_ImageBox: + case ERT_Private: + l_error = EC_Normal; + break; + default: + l_error = EC_IllegalCall; + break; + } + break; + case ERT_FilmSession: + switch (lowerRecord) + { + case ERT_FilmBox: + case ERT_Private: + l_error = EC_Normal; + break; + default: + l_error = EC_IllegalCall; + break; + } + break; + case ERT_Patient: + switch (lowerRecord) + { + case ERT_Study: + case ERT_HL7StrucDoc: + case ERT_Private: + l_error = EC_Normal; + break; + default: + l_error = EC_IllegalCall; + break; + } + break; + case ERT_PrintQueue: + switch (lowerRecord) + { + case ERT_FilmSession: + case ERT_Private: + l_error = EC_Normal; + break; + default: + l_error = EC_IllegalCall; + break; + } + break; + case ERT_Results: + switch (lowerRecord) + { + case ERT_Interpretation: + case ERT_Private: + l_error = EC_Normal; + break; + default: + l_error = EC_IllegalCall; + break; + } + break; + case ERT_Series: + switch (lowerRecord) + { + case ERT_Curve: + case ERT_Image: + case ERT_ModalityLut: + case ERT_Overlay: + case ERT_VoiLut: + case ERT_SRDocument: + case ERT_Presentation: + case ERT_Waveform: + case ERT_RTDose: + case ERT_RTStructureSet: + case ERT_RTPlan: + case ERT_RTTreatRecord: + case ERT_StoredPrint: + case ERT_KeyObjectDoc: + case ERT_Registration: + case ERT_Fiducial: + case ERT_RawData: + case ERT_Spectroscopy: + case ERT_EncapDoc: + case ERT_ValueMap: + case ERT_Stereometric: + case ERT_Surface: + case ERT_Measurement: + case ERT_Plan: + case ERT_SurfaceScan: + case ERT_Private: + l_error = EC_Normal; + break; + default: + l_error = EC_IllegalCall; + break; + } + break; + case ERT_Study: + switch (lowerRecord) + { + case ERT_FilmSession: + case ERT_Results: + case ERT_Series: + case ERT_StudyComponent: + case ERT_Visit: + case ERT_Private: + l_error = EC_Normal; + break; + default: + l_error = EC_IllegalCall; + break; + } + break; + case ERT_Topic: + switch (lowerRecord) + { + case ERT_Curve: + case ERT_FilmSession: + case ERT_Image: + case ERT_ModalityLut: + case ERT_Overlay: + case ERT_Series: + case ERT_Study: + case ERT_VoiLut: + case ERT_SRDocument: + case ERT_Presentation: + case ERT_Waveform: + case ERT_RTDose: + case ERT_RTStructureSet: + case ERT_RTPlan: + case ERT_RTTreatRecord: + case ERT_StoredPrint: + case ERT_KeyObjectDoc: + case ERT_Registration: + case ERT_Fiducial: + case ERT_RawData: + case ERT_Spectroscopy: + case ERT_Private: + l_error = EC_Normal; + break; + default: + l_error = EC_IllegalCall; + break; + } + break; + case ERT_Mrdr: + l_error = EC_IllegalCall; + break; + case ERT_Curve: + case ERT_Image: + case ERT_ImageBox: + case ERT_Interpretation: + case ERT_ModalityLut: + case ERT_Overlay: + case ERT_StudyComponent: + case ERT_Visit: + case ERT_VoiLut: + case ERT_SRDocument: + case ERT_Presentation: + case ERT_Waveform: + case ERT_RTDose: + case ERT_RTStructureSet: + case ERT_RTPlan: + case ERT_RTTreatRecord: + case ERT_StoredPrint: + case ERT_KeyObjectDoc: + case ERT_Registration: + case ERT_Fiducial: + case ERT_RawData: + case ERT_Spectroscopy: + case ERT_EncapDoc: + case ERT_ValueMap: + case ERT_HangingProtocol: + case ERT_Stereometric: + case ERT_HL7StrucDoc: + case ERT_Palette: + case ERT_Surface: + case ERT_Measurement: + case ERT_Implant: + case ERT_ImplantGroup: + case ERT_ImplantAssy: + case ERT_Plan: + case ERT_SurfaceScan: + case ERT_Private: + switch (lowerRecord) + { + case ERT_Private: + l_error = EC_Normal; + break; + default: + l_error = EC_IllegalCall; + break; + } + break; + default: + l_error = EC_Normal; + break; + } + return l_error; +} + + +// ******************************** + + +OFCondition DcmDirectoryRecord::setRecordType(E_DirRecType newType) +{ + OFCondition l_error = EC_Normal; + + DcmTag dirRecTag(DCM_DirectoryRecordType); + DcmCodeString *csP = new DcmCodeString(dirRecTag); + csP->putString(DRTypeNames[newType]); + insert(csP, OFTrue); + + return l_error; +} + + +// ******************************** + + + +E_DirRecType DcmDirectoryRecord::lookForRecordType() +{ + E_DirRecType localType = ERT_Private; + if (!elementList->empty()) + { + DcmStack stack; + if (search(DCM_DirectoryRecordType, stack, ESM_fromHere, OFFalse).good()) + { + if (stack.top()->ident() == EVR_CS) + { + char *recName = NULL; + DcmCodeString *recType = OFstatic_cast(DcmCodeString *, stack.top()); + recType->verify(OFTrue); // force dealignment + recType->getString(recName); + localType = recordNameToType(recName); + + DCMDATA_TRACE("DcmDirectoryRecord::lookForRecordType() RecordType Element " + << recType->getTag() << " Type = " << DRTypeNames[DirRecordType]); + } + } + } + return localType; +} + + +// ******************************** + +static void hostToDicomFilename(char *fname) +{ + /* + ** Massage filename into dicom format. + ** Eliminate any invalid characters. + ** Most commonly there is a '.' at the end of a filename. + */ + size_t len = strlen(fname); + int k = 0; + unsigned char c = '\0'; + for (size_t i = 0; i < len; ++i) + { + c = OFstatic_cast(unsigned char, fname[i]); + /* the PATH_SEPARATOR depends on the OS (see ) */ + if (c == PATH_SEPARATOR) + { + fname[k++] = '\\'; + } else if (isalpha(c) || isdigit(c) || (c == '_') || (c == '\\')) { + /* filenames in DICOM must always be in uppercase */ + fname[k++] = OFstatic_cast(char, toupper(c)); + } + } + fname[k] = '\0'; +} + + +OFCondition DcmDirectoryRecord::setReferencedFileID(const char *referencedFileID) +{ + OFCondition l_error = EC_Normal; + + char* newFname = new char[strlen(referencedFileID) + 1]; + strcpy(newFname, referencedFileID); + hostToDicomFilename(newFname); + + DcmTag refFileTag(DCM_ReferencedFileID); + DcmCodeString *csP = new DcmCodeString(refFileTag); + if (referencedFileID != NULL) + csP->putString(newFname); + insert(csP, OFTrue); + + delete[] newFname; + return l_error; +} + + +// ******************************** + + +const char *DcmDirectoryRecord::lookForReferencedFileID() +{ + char *localFile = NULL; + if (!elementList->empty()) + { + DcmStack stack; + if (search(DCM_ReferencedFileID, stack, ESM_fromHere, OFFalse).good()) + { + if (stack.top()->ident() == EVR_CS) + { + DcmCodeString *refFile = OFstatic_cast(DcmCodeString *, stack.top()); + refFile->verify(OFTrue); // force dealignment + refFile->getString(localFile); + if (localFile != NULL && *localFile == '\0') + localFile = NULL; + } + } + } + DCMDATA_TRACE("DcmDirectoryRecord::lookForReferencedFileID() ReferencedFileID = " + << ((localFile) ? localFile : "")); + + return localFile; +} + + +// ******************************** + + +DcmDirectoryRecord *DcmDirectoryRecord::lookForReferencedMRDR() +{ + DcmDirectoryRecord *localMRDR = NULL; + if (!elementList->empty()) + { + DcmStack stack; + if (search(DCM_RETIRED_MRDRDirectoryRecordOffset, stack, ESM_fromHere, OFFalse).good()) + { + if (stack.top()->ident() == EVR_up) + { + DcmUnsignedLongOffset *offElem; + offElem = OFstatic_cast(DcmUnsignedLongOffset *, stack.top()); + localMRDR = OFstatic_cast(DcmDirectoryRecord *, offElem->getNextRecord()); +#ifdef DEBUG + Uint32 l_uint = 0; + offElem->getUint32(l_uint); + DCMDATA_TRACE("DcmDirectoryRecord::lookForReferencedMRDR() MRDR Offset Element " + << offElem->getTag() << " offs=0x" + << STD_NAMESPACE hex << STD_NAMESPACE setfill('0') + << STD_NAMESPACE setw(8) << l_uint + << " p=" << OFstatic_cast(void *, offElem) + << " n=" << OFstatic_cast(void *, localMRDR)); +#endif + } + } + } + if (localMRDR == NULL) + DCMDATA_TRACE("DcmDirectoryRecord::lookForReferencedMRDR() no ReferencedMRDR found"); + + return localMRDR; +} + + +// ******************************** + + +const char *DcmDirectoryRecord::getReferencedFileName() +{ + const char *localFile = NULL; + if (referencedMRDR != NULL) + localFile = referencedMRDR->lookForReferencedFileID(); + else + localFile = lookForReferencedFileID(); + return localFile; +} + + +// ******************************** + + +OFCondition DcmDirectoryRecord::setRecordInUseFlag(const Uint16 newFlag) +{ + OFCondition l_error = EC_Normal; + + DcmTag recInUseTag(DCM_RecordInUseFlag); + DcmUnsignedShort *usP = new DcmUnsignedShort(recInUseTag); + usP->putUint16(newFlag); + insert(usP, OFTrue); + + return l_error; +} + + +// ******************************** + + +Uint16 DcmDirectoryRecord::lookForRecordInUseFlag() +{ + Uint16 localFlag = Uint16(0xffff); // default value: record is in use + if (!elementList->empty()) + { + DcmStack stack; + if (search(DCM_RecordInUseFlag, stack, ESM_fromHere, OFFalse).good()) + { + if (stack.top()->ident() == EVR_US) + errorFlag = OFstatic_cast(DcmUnsignedShort *, stack.top())->getUint16(localFlag); + } + } + return localFlag; +} + + +// ******************************** + + +Uint32 DcmDirectoryRecord::getFileOffset() const +{ + return offsetInFile; +} + + +// ******************************** + + +Uint32 DcmDirectoryRecord::setFileOffset(Uint32 position) +{ + offsetInFile = position; + return position; +} + + +// ******************************** + + +OFCondition DcmDirectoryRecord::setNumberOfReferences(Uint32 newRefNum) +{ + OFCondition l_error = EC_Normal; + if (DirRecordType == ERT_Mrdr) + { + // insert new value + DcmTag numRefTag(DCM_RETIRED_NumberOfReferences); + DcmUnsignedLong *newUL = new DcmUnsignedLong(numRefTag); + newUL->putUint32(newRefNum); + insert(newUL, OFTrue); + } else { + errorFlag = EC_IllegalCall; + DCMDATA_ERROR("illegal usage of DcmDirectoryRecord::setNumberOfReferences() - RecordType must be MRDR"); + } + return l_error; +} + + +// ******************************** + + +Uint32 DcmDirectoryRecord::lookForNumberOfReferences() +{ + Uint32 localRefNum = 0L; + if (!elementList->empty()) + { + DcmStack stack; + if (search(DCM_RETIRED_NumberOfReferences, stack, ESM_fromHere, OFFalse).good()) + { + if (stack.top()->ident() == EVR_UL) + errorFlag = OFstatic_cast(DcmUnsignedLong *, stack.top())->getUint32(localRefNum); + } + } + return localRefNum; +} + + +// ******************************** + + +Uint32 DcmDirectoryRecord::increaseRefNum() +{ + if (DirRecordType == ERT_Mrdr) + { + if (numberOfReferences == 0L) + setRecordInUseFlag(0xffff); // activate record + numberOfReferences++; + errorFlag = setNumberOfReferences(numberOfReferences); + } else { + errorFlag = EC_IllegalCall; + DCMDATA_ERROR("illegal usage of DcmDirectoryRecord::increaseRefNum() - RecordType must be MRDR"); + } + return numberOfReferences; +} + + +// ******************************** + + +Uint32 DcmDirectoryRecord::decreaseRefNum() +{ + if (DirRecordType == ERT_Mrdr) + { + if (numberOfReferences > 0) + { + numberOfReferences--; + if (numberOfReferences == 0L) + setRecordInUseFlag(0x0000); // deactivate record + errorFlag = setNumberOfReferences(numberOfReferences); + } else { + errorFlag = EC_IllegalCall; + DCMDATA_WARN("DcmDirectoryRecord::decreaseRefNum() attempt to decrease value lower than zero"); + } + } else { + errorFlag = EC_IllegalCall; + DCMDATA_ERROR("illegal usage of DcmDirectoryRecord::decreaseRefNum() - RecordType must be MRDR"); + } + return numberOfReferences; +} + + + +// ******************************** + +// --- IGNORE THE FOLLOWING GERMAN COMMENT --- +// +// Es werden alle Datenelemente gemaess Tabelle B.3.2.2-1 DICOM part 10 +// erzeugt. +// Wird ein gueltiger Dateiname (referencedFileID) fuer eine SOP-Instanz +// uebergeben, so werden alle benoetigten keys aus dieser Datei ausgelesen: +// Das Datenelement MRDRDirectoryRecordOffset entfaellt. +// directFromFile == OFTrue +// +// Ist referencedFileID ein NULL-Zeiger, so wird versucht, die keys indirekt +// ueber den referenzierten MRDR zu besorgen. +// Das Datenelement ReferencedFileID bekommt die Laenge 0. +// indirectViaMRDR == OFTrue +// +// Existiert kein Verweis auf einen MRDR, so wird davon ausgegangen, das auch +// keine SOP-Instanz mit dem aktuellen Directory Record verknuepft werden soll: +// Die Datenelemente ReferencedFileID, MRDRDirectoryRecordOffset, +// ReferencedSOPClassUIDinFile und ReferencedSOPInstanceUIDinFile entfallen. +// !directFromFile && !indirectViaMRDR +// + +OFCondition DcmDirectoryRecord::fillElementsAndReadSOP(const char *referencedFileID, + const OFFilename &sourceFileName, + DcmFileFormat *fileFormat) +{ + OFCondition l_error = EC_Normal; + OFFilename fileName; + DcmFileFormat *refFile = NULL; + /* This variable is only set if we created our own DcmFileFormat instance */ + DcmFileFormat *ownFile = NULL; + + if (fileFormat != NULL && sourceFileName.isEmpty()) + return EC_IllegalCall; + + OFBool directFromFile = OFFalse; + OFBool indirectViaMRDR = OFFalse; + if (referencedFileID != NULL && *referencedFileID != '\0') + directFromFile = OFTrue; + else if (DirRecordType != ERT_Mrdr && referencedMRDR != NULL) // illegal for MRDR + { + indirectViaMRDR = OFTrue; + referencedFileID = referencedMRDR->lookForReferencedFileID(); + } + + if (referencedFileID != NULL && *referencedFileID != '\0') + { + if (sourceFileName.isEmpty()) + { + /* create a new source filename */ + char *newname = new char[strlen(referencedFileID) + 2]; + buildFileName(referencedFileID, newname); + fileName.set(newname); + delete[] newname; + } else { + /* just copy the source filename */ + fileName = sourceFileName; + } + + if (DirRecordType != ERT_Mrdr) + { + if (fileFormat) + { + DCMDATA_TRACE("DcmDirectoryRecord::fillElementsAndReadSOP(): Using existing file format for \"" << fileName << "\"."); + refFile = fileFormat; + } else { + DCMDATA_TRACE("DcmDirectoryRecord::fillElementsAndReadSOP(): Load file \"" << fileName << "\" because our caller didn't do so."); + ownFile = new DcmFileFormat(); + l_error = ownFile->loadFile(fileName); + refFile = ownFile; + if (l_error.bad()) + { + DCMDATA_ERROR("DcmDirectoryRecord::fillElementsAndReadSOP(): DicomFile \"" + << fileName << "\" not found"); + directFromFile = OFFalse; + indirectViaMRDR = OFFalse; + } + } + } + } else { + directFromFile = OFFalse; + indirectViaMRDR = OFFalse; + } + + DcmStack stack; + DcmUnsignedLongOffset *uloP; + DcmUniqueIdentifier *uiP; + + DcmTag nextOffTag(DCM_OffsetOfTheNextDirectoryRecord); // (0004,1400) + uloP = new DcmUnsignedLongOffset(nextOffTag); + uloP->putUint32(Uint32(0)); + if (insert(uloP, OFFalse).bad()) + delete uloP; + + setRecordInUseFlag(0xffff); // (0004,1410) + + DcmTag lowerOffTag(DCM_OffsetOfReferencedLowerLevelDirectoryEntity); + uloP = new DcmUnsignedLongOffset(lowerOffTag); // (0004,1420) + uloP->putUint32(Uint32(0)); + if (insert(uloP, OFFalse).bad()) + delete uloP; + + setRecordType(DirRecordType); // (0004,1430) + + DcmTag privRecTag(DCM_PrivateRecordUID); // (0004,1432) + if (DirRecordType == ERT_Private) + { + uiP = new DcmUniqueIdentifier(privRecTag); + if (insert(uiP, OFFalse).bad()) + delete uiP; + } else + delete remove(privRecTag); + + if (directFromFile) // (0004,1500) + setReferencedFileID(referencedFileID); + else + { + DcmTag refFileTag(DCM_ReferencedFileID); + delete remove(refFileTag); + } + + DcmTag mrdrOffTag(DCM_RETIRED_MRDRDirectoryRecordOffset); // (0004,1504) + if (indirectViaMRDR) + { + // create pointer attribute to MRDR + DcmUnsignedLongOffset *uloP2 = new DcmUnsignedLongOffset(mrdrOffTag); + uloP2->putUint32(Uint32(0)); + uloP2->setNextRecord(referencedMRDR); + insert(uloP2, OFTrue); + } else + delete remove(mrdrOffTag); + + DcmTag refSOPClassTag(DCM_ReferencedSOPClassUIDInFile); + DcmTag refSOPInstTag(DCM_ReferencedSOPInstanceUIDInFile); + DcmTag refFileXferTag(DCM_ReferencedTransferSyntaxUIDInFile); + + if (DirRecordType != ERT_Mrdr && (directFromFile || indirectViaMRDR)) + { + if (refFile == NULL) + { + DCMDATA_ERROR("Internal ERROR in DcmDirectoryRecord::fillElementsAndReadSOP()"); + } + uiP = new DcmUniqueIdentifier(refSOPClassTag); // (0004,1510) + if (refFile->search(DCM_SOPClassUID, stack).good()) + { + char *uid = NULL; + OFstatic_cast(DcmUniqueIdentifier *, stack.top())->getString(uid); + uiP->putString(uid); + } else { + DCMDATA_ERROR("DcmDirectoryRecord::fillElementsAndReadSOP(): " + << "can't find SOPClassUID in Dataset: " << fileName); + l_error = EC_CorruptedData; + } + insert(uiP, OFTrue); + + uiP = new DcmUniqueIdentifier(refSOPInstTag); // (0004,1511) + if (refFile->search(DCM_SOPInstanceUID, stack).good() || refFile->search(DCM_MediaStorageSOPInstanceUID, stack).good()) + { + char *uid = NULL; + OFstatic_cast(DcmUniqueIdentifier *, stack.top())->getString(uid); + uiP->putString(uid); + } else { + DCMDATA_ERROR("DcmDirectoryRecord::fillElementsAndReadSOP(): " + << "can't find SOPInstanceUID neither in Dataset or MetaInfo of file: " << fileName); + l_error = EC_CorruptedData; + } + insert(uiP, OFTrue); + + uiP = new DcmUniqueIdentifier(refFileXferTag); // (0004,1512) + if (refFile->search(DCM_TransferSyntaxUID, stack).good()) + { + char *uid = NULL; + OFstatic_cast(DcmUniqueIdentifier *, stack.top())->getString(uid); + uiP->putString(uid); + } else { + DCMDATA_ERROR("DcmDirectoryRecord::fillElementsAndReadSOP(): " + << "can't find TransferSyntaxUID in MetaInfo of file: " << fileName); + l_error = EC_CorruptedData; + } + insert(uiP, OFTrue); + } + else // not only in this case: if (DirRecordType == ERT_Mrdr) + { + // remove SOP UIDs from Directory Record + delete remove(refSOPClassTag); + delete remove(refSOPInstTag); + delete remove(refFileXferTag); + } + + delete ownFile; + + return l_error; +} + + +// ******************************** + + +OFCondition DcmDirectoryRecord::masterInsertSub(DcmDirectoryRecord *dirRec, + const unsigned long where) +{ + // insert without type check + errorFlag = lowerLevelList->insert(dirRec, where); + return errorFlag; +} + + +// ******************************** + + +OFCondition DcmDirectoryRecord::purgeReferencedFile() +{ + OFCondition l_error = EC_Normal; + if (DirRecordType != ERT_root) + { + char *localFileName = NULL; + + // remove filename from directory record + const char *fileName = lookForReferencedFileID(); + if (fileName != NULL) + { + localFileName = new char[strlen(fileName) + 2]; + buildFileName(fileName, localFileName); + setReferencedFileID(NULL); + } + + DCMDATA_DEBUG("DcmDirectoryRecord::purgeReferencedFile() trying to purge file " + << localFileName << " from file system"); + + if (localFileName != NULL) + { // filename exists + if (unlink(localFileName) != 0) + { + char buf[256]; + const char *text = OFStandard::strerror(errno, buf, sizeof(buf)); + if (text == NULL) text = "(unknown error code)"; + errorFlag = makeOFCondition(OFM_dcmdata, 19, OF_error, text); + } + delete[] localFileName; + } else { // no referenced file exists + // do nothing + } + } else + l_error = EC_IllegalCall; + + return l_error; +} + + +// ******************************** +// ******** public methods ******** +// ******************************** + + +DcmEVR DcmDirectoryRecord::ident() const +{ + return EVR_dirRecord; +} + + +// ******************************** + + +OFCondition DcmDirectoryRecord::convertCharacterSet(const OFString &fromCharset, + const OFString &toCharset, + const OFBool transliterate, + const OFBool updateCharset, + const OFBool discardIllegal) +{ + // call the method of the base class; this method is only needed to avoid a compiler warning + return DcmItem::convertCharacterSet(fromCharset, toCharset, transliterate, updateCharset, discardIllegal); +} + + +OFCondition DcmDirectoryRecord::convertCharacterSet(const OFString &toCharset, + const OFBool transliterate, + const OFBool ignoreCharset, + const OFBool discardIllegal) +{ + // call the method of the base class; this method is only needed to avoid a compiler warning + return DcmItem::convertCharacterSet(toCharset, transliterate, ignoreCharset, discardIllegal); +} + + +OFCondition DcmDirectoryRecord::convertCharacterSet(DcmSpecificCharacterSet &converter) +{ + DCMDATA_DEBUG("DcmDirectoryRecord::convertCharacterSet() processing directory record with offset " + << getFileOffset()); + // handle special case of DICOMDIR: the Specific Character Set (0008,0005) + // can be specified individually for each directory record (i.e. item) + OFCondition status = EC_Normal; + OFString fromCharset; + const OFString toCharset = converter.getDestinationCharacterSet(); + // determine value of Specific Character Set (0008,0005) if present in this item + if (findAndGetOFStringArray(DCM_SpecificCharacterSet, fromCharset, OFFalse /*searchIntoSub*/).good() && + (fromCharset != converter.getSourceCharacterSet())) + { + DcmSpecificCharacterSet newConverter; + // create a new character set converter + DCMDATA_DEBUG("DcmDirectoryRecord::convertCharacterSet() creating a new character set converter for '" + << fromCharset << "'" << (fromCharset.empty() ? " (ASCII)" : "") << " to '" + << toCharset << "'" << (toCharset.empty() ? " (ASCII)" : "")); + // select source and destination character set, use same transliteration mode + status = newConverter.selectCharacterSet(fromCharset, toCharset, converter.getTransliterationMode(), converter.getDiscardIllegalSequenceMode()); + if (status.good()) + { + // convert all affected element values in the item with the new converter + status = DcmItem::convertCharacterSet(newConverter); + // update the Specific Character Set (0008,0005) element + updateSpecificCharacterSet(status, newConverter); + } + } else { + // no Specific Character Set attribute or the same character set, + // so proceed with the given converter + status = DcmItem::convertCharacterSet(converter); + } + return status; +} + + +// ******************************** + + +void DcmDirectoryRecord::print(STD_NAMESPACE ostream&out, + const size_t flags, + const int level, + const char *pixelFileName, + size_t *pixelCounter) +{ + if (flags & DCMTypes::PF_showTreeStructure) + { + /* print record line */ + OFOStringStream oss; + oss << "\"Directory Record\" (offset=$" + << getFileOffset() << ")" << OFStringStream_ends; + OFSTRINGSTREAM_GETSTR(oss, tmpString) + printInfoLine(out, flags, level, tmpString); + OFSTRINGSTREAM_FREESTR(tmpString) + /* print item content */ + if (!elementList->empty()) + { + DcmObject *dO; + elementList->seek(ELP_first); + do { + dO = elementList->get(); + dO->print(out, flags, level + 1, pixelFileName, pixelCounter); + } while (elementList->seek(ELP_next)); + } + if (lowerLevelList->card() > 0) + lowerLevelList->print(out, flags, level + 1); + } else { + /* print record start line */ + OFOStringStream oss; + oss << "\"Directory Record\" " << DRTypeNames[DirRecordType] + << " #=" << card() << OFStringStream_ends; + OFSTRINGSTREAM_GETSTR(oss, tmpString) + printInfoLine(out, flags, level, tmpString); + OFSTRINGSTREAM_FREESTR(tmpString) + /* print record comment line */ + if (flags & DCMTypes::PF_useANSIEscapeCodes) + out << DCMDATA_ANSI_ESCAPE_CODE_INFO; + printNestingLevel(out, flags, level); + out << "# offset=$" << getFileOffset(); + if (referencedMRDR != NULL) + out << " refMRDR=$" << referencedMRDR->getFileOffset(); + if (DirRecordType == ERT_Mrdr) + out << " refCount=" << numberOfReferences; + const char *refFile = getReferencedFileName(); + if (refFile != NULL) + out << " refFileID=\"" << refFile << "\""; + if (flags & DCMTypes::PF_useANSIEscapeCodes) + out << DCMDATA_ANSI_ESCAPE_CODE_RESET; + out << OFendl; + /* print item content */ + if (!elementList->empty()) + { + DcmObject *dO; + elementList->seek(ELP_first); + do { + dO = elementList->get(); + dO->print(out, flags, level + 1, pixelFileName, pixelCounter); + } while (elementList->seek(ELP_next)); + } + if (lowerLevelList->card() > 0) + lowerLevelList->print(out, flags, level + 1); + /* print record end line */ + DcmTag delimItemTag(DCM_ItemDelimitationItemTag); + if (getLengthField() == DCM_UndefinedLength) + printInfoLine(out, flags, level, "\"ItemDelimitationItem\"", &delimItemTag); + else + printInfoLine(out, flags, level, "\"ItemDelimitationItem for re-encoding\"", &delimItemTag); + } +} + + +// ******************************** + + +OFCondition DcmDirectoryRecord::writeXML(STD_NAMESPACE ostream &out, + const size_t flags) +{ + if (flags & DCMTypes::XF_useNativeModel) + { + /* in Native DICOM Model, there is no concept of a DICOMDIR */ + return makeOFCondition(OFM_dcmdata, EC_CODE_CannotConvertToXML, OF_error, + "Cannot convert Directory Record to Native DICOM Model"); + } else { + /* XML start tag for "item" */ + out << "" << OFendl; + /* write item content */ + if (!elementList->empty()) + { + /* write content of all children */ + DcmObject *dO; + elementList->seek(ELP_first); + do { + dO = elementList->get(); + dO->writeXML(out, flags); + } while (elementList->seek(ELP_next)); + } + if (lowerLevelList->card() > 0) + lowerLevelList->writeXML(out, flags); + /* XML end tag for "item" */ + out << "" << OFendl; + /* always report success */ + return EC_Normal; + } +} + + +// ******************************** + + +OFCondition DcmDirectoryRecord::read(DcmInputStream &inStream, + const E_TransferSyntax xfer, + const E_GrpLenEncoding glenc, + const Uint32 maxReadLength) +{ + if (getTransferState() == ERW_notInitialized) + errorFlag = EC_IllegalCall; + else + { + if (getTransferState() != ERW_ready) + { + DcmXfer xferSyn(xfer); + errorFlag = DcmItem::read(inStream, xfer, glenc, maxReadLength); + /* + ** Remember the actual file offset for this Directory Record. + ** Compute by subtracting the Item header (tag & length fields) + ** from the start position of data within the Item (fStartPosition). + ** fStartPosition is set in DcmItem::read(...) + ** offsetInFile is used in the print(...) method. + */ + offsetInFile = OFstatic_cast(Uint32, fStartPosition) - xferSyn.sizeofTagHeader(getTag().getEVR()); + } + + if (getTransferState() == ERW_ready && DirRecordType == ERT_Private) // minimizes multiple evaluation + { + DirRecordType = lookForRecordType(); + if (DirRecordType == ERT_Mrdr) + numberOfReferences = lookForNumberOfReferences(); + } + } + return errorFlag; +} + + +// ******************************** + + +OFCondition DcmDirectoryRecord::verify(const OFBool autocorrect) +{ + OFCondition err1 = EC_Normal; + OFCondition err2 = EC_Normal; + errorFlag = EC_Normal; + if (autocorrect == OFTrue && DirRecordType != ERT_root) + errorFlag = fillElementsAndReadSOP(getReferencedFileName(), ""); + + err1 = DcmItem::verify(autocorrect); + err2 = lowerLevelList->verify(autocorrect); + if (errorFlag.good() && (err1.bad() || err2.bad())) + errorFlag = EC_CorruptedData; + return errorFlag; +} + + +// ******************************** + + +OFCondition DcmDirectoryRecord::search(const DcmTagKey &tag, + DcmStack &resultStack, + E_SearchMode mode, + OFBool searchIntoSub) +{ + OFCondition l_error = DcmItem::search(tag, resultStack, mode, searchIntoSub); + if (l_error.bad()) + { + if (mode != ESM_afterStackTop || resultStack.top() == this) + resultStack.push(lowerLevelList); + l_error = lowerLevelList->search(tag, resultStack, mode, searchIntoSub); + if (l_error.bad()) + resultStack.pop(); + } + return l_error; +} + + +// ******************************** + + +E_DirRecType DcmDirectoryRecord::getRecordType() +{ + return DirRecordType; +} + + +// ******************************** + + +DcmDirectoryRecord* DcmDirectoryRecord::getReferencedMRDR() +{ + return referencedMRDR; +} + + +// ******************************** + + +OFCondition DcmDirectoryRecord::assignToSOPFile(const char *referencedFileID, + const OFFilename &sourceFileName) +{ + errorFlag = EC_Normal; + + if (DirRecordType != ERT_root) + { + DCMDATA_DEBUG("DcmDirectoryRecord::assignToSOPFile() old Referenced File ID was " + << getReferencedFileName()); + DCMDATA_DEBUG("new Referenced File ID is " << referencedFileID); + + // update against the old reference counter + if (referencedMRDR != NULL) + referencedMRDR->decreaseRefNum(); + referencedMRDR = NULL; + + errorFlag = fillElementsAndReadSOP(referencedFileID, sourceFileName); + } else + errorFlag = EC_IllegalCall; + return errorFlag; +} + + +// ******************************** + + +OFCondition DcmDirectoryRecord::assignToMRDR(DcmDirectoryRecord *mrdr) +{ + errorFlag = EC_Normal; + if (DirRecordType != ERT_root + && mrdr != NULL // new MRDR available + && mrdr != referencedMRDR // old MRDR != new MRDR + ) + { + DCMDATA_DEBUG("DcmDirectoryRecord::assignToMRDR() old Referenced File ID was " + << getReferencedFileName()); + DCMDATA_DEBUG("new Referenced File ID is " << mrdr->lookForReferencedFileID()); + + // set internal pointer to mrdr and update against the old value + if (referencedMRDR != NULL) + referencedMRDR->decreaseRefNum(); + referencedMRDR = mrdr; + + // increase reference counter in referencedMRDR by one + referencedMRDR->increaseRefNum(); + + // set length of Referenced File ID to zero and fill data elements + errorFlag = fillElementsAndReadSOP(NULL, ""); + } else + errorFlag = EC_IllegalCall; + + return errorFlag; +} + + +// ******************************** + + +unsigned long DcmDirectoryRecord::cardSub() const +{ + return lowerLevelList->card(); +} + + +// ******************************** + + +OFCondition DcmDirectoryRecord::insertSub(DcmDirectoryRecord *dirRec, + unsigned long where, + OFBool before) +{ + if (dirRec != NULL) + { + if (checkHierarchy(DirRecordType, dirRec->DirRecordType).good()) + errorFlag = lowerLevelList->insert(dirRec, where, before); + else + { + errorFlag = EC_IllegalCall; + DCMDATA_DEBUG("DcmDirectoryRecord::insertSub() dcdirrec: (" + << DRTypeNames[getRecordType()] << " -> " + << DRTypeNames[dirRec->getRecordType()] << ") hierarchy not allowed"); + } + } + return errorFlag; +} + + +// ******************************** + + +OFCondition DcmDirectoryRecord::insertSubAtCurrentPos(DcmDirectoryRecord *dirRec, + OFBool before) +{ + if (dirRec != NULL) + { + if (checkHierarchy(DirRecordType, dirRec->DirRecordType).good()) + errorFlag = lowerLevelList->insertAtCurrentPos(dirRec, before); + else { + errorFlag = EC_IllegalCall; + DCMDATA_DEBUG("DcmDirectoryRecord::insertSubAtCurrentPos() dcdirrec: (" + << DRTypeNames[getRecordType()] << " -> " << DRTypeNames[dirRec->getRecordType()] + << ") hierarchy not allowed"); + } + } + return errorFlag; +} + + +// ******************************** + + +DcmDirectoryRecord *DcmDirectoryRecord::getSub(const unsigned long num) +{ + DcmDirectoryRecord *retRec = OFstatic_cast(DcmDirectoryRecord *, lowerLevelList->getItem(num)); + errorFlag = lowerLevelList->error(); + return retRec; +} + + +// ******************************** + + +DcmDirectoryRecord *DcmDirectoryRecord::nextSub(const DcmDirectoryRecord *dirRec) +{ + DcmDirectoryRecord *retRec = OFstatic_cast(DcmDirectoryRecord *, lowerLevelList->nextInContainer(dirRec)); + errorFlag = lowerLevelList->error(); + return retRec; +} + + +// ******************************** + + +DcmDirectoryRecord* DcmDirectoryRecord::removeSub(const unsigned long num) +{ + DcmDirectoryRecord *retRec = OFstatic_cast(DcmDirectoryRecord *, lowerLevelList->remove(num)); + errorFlag = lowerLevelList->error(); + return retRec; +} + + +// ******************************** + + +DcmDirectoryRecord* DcmDirectoryRecord::removeSub(DcmDirectoryRecord *dirRec) +{ + DcmDirectoryRecord *retRec = OFstatic_cast(DcmDirectoryRecord *, lowerLevelList->remove(dirRec)); + errorFlag = lowerLevelList->error(); + return retRec; +} + + +// ******************************** + + +OFCondition DcmDirectoryRecord::deleteSubAndPurgeFile(const unsigned long num) +{ + DcmDirectoryRecord *subDirRec = OFstatic_cast(DcmDirectoryRecord *, lowerLevelList->remove(num)); + errorFlag = lowerLevelList->error(); + if (subDirRec != NULL) + { + DcmDirectoryRecord *localSubRefMRDR = subDirRec->getReferencedMRDR(); + + if (localSubRefMRDR != NULL) + { // file is referenced (indirect) + localSubRefMRDR->decreaseRefNum(); + } else // remove file directly + errorFlag = subDirRec->purgeReferencedFile(); + + DCMDATA_DEBUG("DcmDirectoryRecord::deleteSubAndPurgeFile() now purging lower records:"); + + while (subDirRec->cardSub() > 0) // remove all sub sub records + subDirRec->deleteSubAndPurgeFile(OFstatic_cast(unsigned long, 0)); + delete subDirRec; // remove sub directory record + } + return errorFlag; +} + + +// ******************************** + + +OFCondition DcmDirectoryRecord::deleteSubAndPurgeFile(DcmDirectoryRecord *dirRec) +{ + DcmDirectoryRecord *subDirRec = OFstatic_cast(DcmDirectoryRecord *, lowerLevelList->remove(dirRec)); + errorFlag = lowerLevelList->error(); + if (subDirRec != NULL) + { + DcmDirectoryRecord *localSubRefMRDR = subDirRec->getReferencedMRDR(); + + if (localSubRefMRDR != NULL) + { // file is referenced (indirect) + localSubRefMRDR->decreaseRefNum(); + } else // remove file directly + errorFlag = subDirRec->purgeReferencedFile(); + + DCMDATA_DEBUG("DcmDirectoryRecord::deleteSubAndPurgeFile() now purging lower records:"); + + while (subDirRec->cardSub() > 0) // remove all sub sub records + subDirRec->deleteSubAndPurgeFile(OFstatic_cast(unsigned long, 0)); + delete subDirRec; // remove sub directory record + } + return errorFlag; +} + + +OFCondition DcmDirectoryRecord::clearSub() +{ + errorFlag = lowerLevelList->clear(); + return errorFlag; +} + + +void DcmDirectoryRecord::setRecordsOriginFile(const OFFilename &fname) +{ + recordsOriginFile = fname; +} + +const OFFilename &DcmDirectoryRecord::getRecordsOriginFile() +{ + return recordsOriginFile; +} diff --git a/dcmdata/libsrc/dcelem.cc b/dcmdata/libsrc/dcelem.cc new file mode 100644 index 00000000..b1b67632 --- /dev/null +++ b/dcmdata/libsrc/dcelem.cc @@ -0,0 +1,2048 @@ +/* + * + * Copyright (C) 1994-2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Gerd Ehlers, Andreas Barth + * + * Purpose: Implementation of class DcmElement + * + */ + + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#define INCLUDE_NEW +#define INCLUDE_CSTDLIB +#define INCLUDE_CSTRING +#include "dcmtk/ofstd/ofstdinc.h" + +#include "dcmtk/ofstd/ofdefine.h" + +#include "dcmtk/ofstd/ofstd.h" +#include "dcmtk/ofstd/ofstream.h" +#include "dcmtk/dcmdata/dcelem.h" +#include "dcmtk/dcmdata/dcobject.h" +#include "dcmtk/dcmdata/dcswap.h" +#include "dcmtk/dcmdata/dcistrma.h" /* for class DcmInputStream */ +#include "dcmtk/dcmdata/dcostrma.h" /* for class DcmOutputStream */ +#include "dcmtk/dcmdata/dcfcache.h" /* for class DcmFileCache */ +#include "dcmtk/dcmdata/dcwcache.h" /* for class DcmWriteCache */ +#include "dcmtk/dcmdata/dcitem.h" +#include "dcmtk/dcmdata/dcdeftag.h" +#include "dcmtk/dcmdata/vrscan.h" +#include "dcmtk/dcmdata/dcpath.h" + +#define SWAPBUFFER_SIZE 16 /* sufficient for all DICOM VRs as per the 2007 edition */ + +// +// CLASS DcmElement +// + +DcmElement::DcmElement(const DcmTag &tag, + const Uint32 len) + : DcmObject(tag, len), + fByteOrder(gLocalByteOrder), + fLoadValue(NULL), + fValue(NULL) +{ +} + + +DcmElement::DcmElement(const DcmElement &elem) + : DcmObject(elem), + fByteOrder(elem.fByteOrder), + fLoadValue(NULL), + fValue(NULL) +{ + if (elem.fValue) + { + DcmVR vr(elem.getVR()); + const unsigned short pad = (vr.isaString()) ? OFstatic_cast(unsigned short, 1) : OFstatic_cast(unsigned short, 0); + + // The next lines are a special version of newValueField(). + // newValueField() cannot be used because it is virtual and it does + // not allocate enough bytes for strings. The number of pad bytes + // is added to the Length for this purpose. + if (getLengthField() & 1) + { +#ifdef HAVE_STD__NOTHROW + // we want to use a non-throwing new here if available + // If the allocation fails, we report an EC_MemoryExhausted error + // back to the caller. + fValue = new (std::nothrow) Uint8[getLengthField() + 1 + pad]; // protocol error: odd value length +#else + /* make sure that the pointer is set to NULL in case of error */ + try + { + fValue = new Uint8[getLengthField() + 1 + pad]; // protocol error: odd value length + } + catch (STD_NAMESPACE bad_alloc const &) + { + fValue = NULL; + } +#endif + if (fValue) + fValue[getLengthField()] = 0; + setLengthField(getLengthField() + 1); // make Length even + } + else + { +#ifdef HAVE_STD__NOTHROW + // we want to use a non-throwing new here if available. + // If the allocation fails, we report an EC_MemoryExhausted error + // back to the caller. + fValue = new (std::nothrow) Uint8[getLengthField() + pad]; +#else + /* make sure that the pointer is set to NULL in case of error */ + try + { + fValue = new Uint8[getLengthField() + pad]; + } + catch (STD_NAMESPACE bad_alloc const &) + { + fValue = NULL; + } +#endif + } + + if (!fValue) + errorFlag = EC_MemoryExhausted; + + if (pad && fValue) + fValue[getLengthField()] = 0; + + if (fValue) + memcpy(fValue, elem.fValue, size_t(getLengthField() + pad)); + } + + if (elem.fLoadValue) + fLoadValue = elem.fLoadValue->clone(); +} + + +DcmElement &DcmElement::operator=(const DcmElement &obj) +{ + if (this != &obj) + { +#if defined(HAVE_STD__NOTHROW) && defined(HAVE_NOTHROW_DELETE) + // if created with the nothrow version it must also be deleted with + // the nothrow version else memory error. + operator delete[] (fValue, std::nothrow); +#else + delete[] fValue; +#endif + delete fLoadValue; + fLoadValue = NULL; + fValue = NULL; + + DcmObject::operator=(obj); + fByteOrder = obj.fByteOrder; + + if (obj.fValue) + { + DcmVR vr(obj.getVR()); + const unsigned short pad = (vr.isaString()) ? OFstatic_cast(unsigned short, 1) : OFstatic_cast(unsigned short, 0); + + // The next lines are a special version of newValueField(). + // newValueField() cannot be used because it is virtual and it does + // not allocate enough bytes for strings. The number of pad bytes + // is added to the Length for this purpose. + + if (getLengthField() & 1) + { +#ifdef HAVE_STD__NOTHROW + // we want to use a non-throwing new here if available. + // If the allocation fails, we report an EC_MemoryExhausted error + // back to the caller. + fValue = new (std::nothrow) Uint8[getLengthField() + 1 + pad]; // protocol error: odd value length +#else + /* make sure that the pointer is set to NULL in case of error */ + try + { + fValue = new Uint8[getLengthField() + 1 + pad]; // protocol error: odd value length + } + catch (STD_NAMESPACE bad_alloc const &) + { + fValue = NULL; + } +#endif + if (fValue) + fValue[getLengthField()] = 0; + setLengthField(getLengthField() + 1); // make Length even + } + else + { +#ifdef HAVE_STD__NOTHROW + // we want to use a non-throwing new here if available. + // If the allocation fails, we report an EC_MemoryExhausted error + // back to the caller. + fValue = new (std::nothrow) Uint8[getLengthField() + pad]; +#else + /* make sure that the pointer is set to NULL in case of error */ + try + { + fValue = new Uint8[getLengthField() + pad]; + } + catch (STD_NAMESPACE bad_alloc const &) + { + fValue = NULL; + } +#endif + } + + if (!fValue) + errorFlag = EC_MemoryExhausted; + + if (pad && fValue) + fValue[getLengthField()] = 0; + if (fValue) + memcpy(fValue, obj.fValue, size_t(getLengthField()+pad)); + } + + if (obj.fLoadValue) + fLoadValue = obj.fLoadValue->clone(); + + } + return *this; +} + + +int DcmElement::compare(const DcmElement& rhs) const +{ + if (this == &rhs) + return 0; + + DcmElement* myThis = OFconst_cast(DcmElement*, this); + DcmElement* myRhs = OFconst_cast(DcmElement*, &rhs); + + DcmTagKey thisKey = (*myThis).getTag().getXTag(); + DcmTagKey rhsKey = (*myRhs).getTag().getXTag(); + + if ( thisKey > rhsKey ) + { + return 1; + } + else if (thisKey < rhsKey) + { + return -1; + } + + if ( this->ident() != rhs.ident() ) + return -1; + + return 0; +} + + +OFCondition DcmElement::copyFrom(const DcmObject& rhs) +{ + if (this != &rhs) + { + if (rhs.ident() != ident()) return EC_IllegalCall; + *this = OFstatic_cast(const DcmElement &, rhs); + } + return EC_Normal; +} + + +DcmElement::~DcmElement() +{ +#if defined(HAVE_STD__NOTHROW) && defined(HAVE_NOTHROW_DELETE) + // if created with the nothrow version it must also be deleted with + // the nothrow version else memory error. + operator delete[] (fValue, std::nothrow); +#else + delete[] fValue; +#endif + delete fLoadValue; +} + + +// ******************************** + + +OFCondition DcmElement::clear() +{ + errorFlag = EC_Normal; +#if defined(HAVE_STD__NOTHROW) && defined(HAVE_NOTHROW_DELETE) + // if created with the nothrow version it must also be deleted with + // the nothrow version else memory error. + operator delete[] (fValue, std::nothrow); +#else + delete[] fValue; +#endif + fValue = NULL; + delete fLoadValue; + fLoadValue = NULL; + setLengthField(0); + return errorFlag; +} + + +OFCondition DcmElement::checkValue(const OFString & /*vm*/, + const OFBool /*oldFormat*/) +{ + return EC_IllegalCall; +} + + +// ******************************** + + +Uint32 DcmElement::calcElementLength(const E_TransferSyntax xfer, + const E_EncodingType enctype) +{ + DcmXfer xferSyn(xfer); + DcmEVR vr = getVR(); + /* These don't use extended length encoding, but when writing, they are + * converted to EVR_UN which does use extended length encoding. + * (EVR_na should never happen here, it's just handled for completeness) */ + if (vr == EVR_UNKNOWN2B || vr == EVR_na) + vr = EVR_UN; + const Uint32 headerLength = xferSyn.sizeofTagHeader(vr); + const Uint32 elemLength = getLength(xfer, enctype); + if (OFStandard::check32BitAddOverflow(headerLength, elemLength)) + return DCM_UndefinedLength; + else + return headerLength + elemLength; +} + + +OFBool DcmElement::canWriteXfer(const E_TransferSyntax newXfer, + const E_TransferSyntax /*oldXfer*/) +{ + OFBool canWrite = (newXfer != EXS_Unknown); + if (canWrite) + { + /* check whether element value exceeds length field (in case of 16 bit) */ + if (DcmXfer(newXfer).isExplicitVR() && !DcmVR(getVR()).usesExtendedLengthEncoding()) + { + const Uint32 length = getLength(newXfer); + if (length > 0xffff) + { + DCMDATA_DEBUG("DcmElement::canWriteXfer() Length of element " << getTagName() << " " << getTag() + << " exceeds maximum of 16-bit length field (" << length << " > 65535 bytes)"); + canWrite = OFFalse; + } + } + } + return canWrite; +} + + +OFCondition DcmElement::detachValueField(OFBool copy) +{ + OFCondition l_error = EC_Normal; + if (getLengthField() != 0) + { + if (copy) + { + if (!fValue) + l_error = loadValue(); + if (l_error.good()) + { + Uint8 * newValue; +#ifdef HAVE_STD__NOTHROW + // we want to use a non-throwing new here if available + newValue = new (std::nothrow) Uint8[getLengthField()]; +#else + /* make sure that the pointer is set to NULL in case of error */ + try + { + newValue = new Uint8[getLengthField()]; + } + catch (STD_NAMESPACE bad_alloc const &) + { + newValue = NULL; + } +#endif + if (newValue) + { + memcpy(newValue, fValue, size_t(getLengthField())); + fValue = newValue; + } else { + /* the copy could not be created, so return an error */ + l_error = EC_MemoryExhausted; + } + } + } else { + fValue = NULL; + setLengthField(0); + } + } + return l_error; +} + + +// ******************************** + + +OFCondition DcmElement::getUint8(Uint8 & /*val*/, + const unsigned long /*pos*/) +{ + errorFlag = EC_IllegalCall; + return errorFlag; +} + + +OFCondition DcmElement::getSint16(Sint16 & /*val*/, + const unsigned long /*pos*/) +{ + errorFlag = EC_IllegalCall; + return errorFlag; +} + + +OFCondition DcmElement::getUint16(Uint16 & /*val*/, + const unsigned long /*pos*/) +{ + errorFlag = EC_IllegalCall; + return errorFlag; +} + + +OFCondition DcmElement::getSint32(Sint32 & /*val*/, + const unsigned long /*pos*/) +{ + errorFlag = EC_IllegalCall; + return errorFlag; +} + + +OFCondition DcmElement::getUint32(Uint32 & /*val*/, + const unsigned long /*pos*/) +{ + errorFlag = EC_IllegalCall; + return errorFlag; +} + + +OFCondition DcmElement::getFloat32(Float32 & /*val*/, + const unsigned long /*pos*/) +{ + errorFlag = EC_IllegalCall; + return errorFlag; +} + + +OFCondition DcmElement::getFloat64(Float64 & /*val*/, + const unsigned long /*pos*/) +{ + errorFlag = EC_IllegalCall; + return errorFlag; +} + + +OFCondition DcmElement::getTagVal(DcmTagKey & /*val*/, + const unsigned long /*pos*/) +{ + errorFlag = EC_IllegalCall; + return errorFlag; +} + + +OFCondition DcmElement::getOFString(OFString & /*val*/, + const unsigned long /*pos*/, + OFBool /*normalize*/) +{ + errorFlag = EC_IllegalCall; + return errorFlag; +} + + +OFCondition DcmElement::getString(char * & /*val*/) +{ + errorFlag = EC_IllegalCall; + return errorFlag; +} + + +OFCondition DcmElement::getString(char * & /*val*/, + Uint32 & /*len*/) +{ + errorFlag = EC_IllegalCall; + return errorFlag; +} + + +OFCondition DcmElement::getOFStringArray(OFString &value, + OFBool normalize) +{ + /* this is a general implementation which is only used when the derived + VR class does not reimplement it + */ + errorFlag = EC_Normal; + const unsigned long count = getVM(); + /* initialize result string */ + value.clear(); + if (count > 0) + { + OFString string; + unsigned long i = 0; + /* reserve number of bytes expected (heuristic) */ + value.reserve(OFstatic_cast(unsigned int, getLength())); + /* iterate over all values and convert them to a character string */ + while ((i < count) && (errorFlag = getOFString(string, i, normalize)).good()) + { + if (i > 0) + value += '\\'; + /* append current value to the result string */ + value += string; + i++; + } + } + return errorFlag; +} + + +OFCondition DcmElement::getUint8Array(Uint8 * & /*val*/) +{ + errorFlag = EC_IllegalCall; + return errorFlag; +} + + +OFCondition DcmElement::getSint16Array(Sint16 * & /*val*/) +{ + errorFlag = EC_IllegalCall; + return errorFlag; +} + + +OFCondition DcmElement::getUint16Array(Uint16 * & /*val*/) +{ + errorFlag = EC_IllegalCall; + return errorFlag; +} + + +OFCondition DcmElement::getSint32Array(Sint32 * & /*val*/) +{ + errorFlag = EC_IllegalCall; + return errorFlag; +} + + +OFCondition DcmElement::getUint32Array(Uint32 * & /*val*/) +{ + errorFlag = EC_IllegalCall; + return errorFlag; +} + + +OFCondition DcmElement::getFloat32Array(Float32 * & /*val*/) +{ + errorFlag = EC_IllegalCall; + return errorFlag; +} + + +OFCondition DcmElement::getFloat64Array(Float64 * & /*val*/) +{ + errorFlag = EC_IllegalCall; + return errorFlag; +} + + +void *DcmElement::getValue(const E_ByteOrder newByteOrder) +{ + /* initialize return value */ + Uint8 * value = NULL; + /* if the byte ordering is unknown, this is an illegal call */ + if (newByteOrder == EBO_unknown) + errorFlag = EC_IllegalCall; + else + { + /* in case this call is not illegal, we need to do something. First of all, set the error flag to ok */ + errorFlag = EC_Normal; + /* do something only if the length of this element's value does not equal (i.e. is greater than) 0 */ + if (getLengthField() != 0) + { + /* if the value has not yet been loaded, do so now */ + if (!fValue) + errorFlag = loadValue(); + /* if everything is ok */ + if (errorFlag.good()) + { + /* if this element's value's byte ordering does not correspond to the */ + /* desired byte ordering, we need to rearrange this value's bytes and */ + /* set its byte order indicator variable correspondingly */ + if (newByteOrder != fByteOrder) + { + swapIfNecessary(newByteOrder, fByteOrder, fValue, + getLengthField(), getTag().getVR().getValueWidth()); + fByteOrder = newByteOrder; + } + /* if everything is ok, assign the current value to the result variable */ + if (errorFlag.good()) + value = fValue; + } + } + } + /* return result */ + return value; +} + + +// ******************************** + + +OFCondition DcmElement::loadAllDataIntoMemory() +{ + errorFlag = EC_Normal; + if (!fValue && (getLengthField() != 0)) + errorFlag = loadValue(); + return errorFlag; +} + + +OFCondition DcmElement::loadValue(DcmInputStream *inStream) +{ + /* initialize return value */ + errorFlag = EC_Normal; + /* only if the length of this element does not equal 0, read information */ + if (getLengthField() != 0) + { + DcmInputStream *readStream = inStream; + OFBool isStreamNew = OFFalse; + + // if the NULL pointer was passed (i.e. we're not in the middle of + // a read() cycle, and fValue is NULL (i.e. the attribute value still + // remains in file and fLoadValue is not NULL (i.e. we know how to + // load the value from that file, then let's do it.. + if (!readStream && fLoadValue && !fValue) + { + /* we need to read information from the stream which is */ + /* accessible through fLoadValue. Hence, reassign readStream */ + readStream = fLoadValue->create(); + + isStreamNew = OFTrue; + + /* reset number of transferred bytes to zero */ + setTransferredBytes(0); + } + /* if we have a stream from which we can read */ + if (readStream) + { + /* check if the stream reported an error */ + errorFlag = readStream->status(); + /* if we encountered the end of the stream, set the error flag correspondingly */ + if (errorFlag.good() && readStream->eos()) + errorFlag = EC_EndOfStream; + /* if we did not encounter the end of the stream and no error occurred so far, go ahead */ + else if (errorFlag.good()) + { + /* if the object which holds this element's value does not yet exist, create it */ + if (!fValue) + fValue = newValueField(); /* also set errorFlag in case of error */ + + /* if object could be created (i.e. we have an object which can be used to capture this element's */ + /* value) we need to read a certain amount of bytes from the stream */ + if (fValue) + { + /* determine how many bytes shall be read from the stream */ + const Uint32 readLength = getLengthField() - getTransferredBytes(); + + /* read a corresponding amount of bytes from the stream, store the information in fValue */ + /* increase the counter that counts how many bytes were actually read */ + incTransferredBytes(OFstatic_cast(Uint32, readStream->read(&fValue[getTransferredBytes()], readLength))); + + /* if we have read all the bytes which make up this element's value */ + if (getLengthField() == getTransferredBytes()) + { + /* call a function which performs certain operations on the information which was read */ + postLoadValue(); + errorFlag = EC_Normal; + } + /* else set the return value correspondingly */ + else if (readStream->eos()) + { + errorFlag = EC_InvalidStream; // premature end of stream + DCMDATA_ERROR("DcmElement: " << getTagName() << " " << getTag() + << " larger (" << getLengthField() << ") than remaining bytes (" + << getTransferredBytes() << ") in file, premature end of stream"); + } + else + errorFlag = EC_StreamNotifyClient; + } + } + /* if we created the stream from which information was read in this */ + /* function, we need to we need to delete this object here as well */ + if (isStreamNew) + delete readStream; + } + } + /* return result value */ + return errorFlag; +} + + +// ******************************** + + +Uint8 *DcmElement::newValueField() +{ + Uint8 * value; + /* if this element's length is odd */ + Uint32 lengthField = getLengthField(); + if (lengthField & 1) + { + if (lengthField == DCM_UndefinedLength) + { + /* Print an error message when private attribute states to have an odd length + * equal to the maximum length, because we are not able then to make this value even (+1) + * which would an overflow on some systems as well as being illegal in DICOM + */ + DCMDATA_ERROR("DcmElement: " << getTagName() << " " << getTag() + << " has odd maximum length (" << DCM_UndefinedLength << ") and therefore is not loaded"); + errorFlag = EC_CorruptedData; + return NULL; + } + /* create an array of Length+1 bytes */ +#ifdef HAVE_STD__NOTHROW + // we want to use a non-throwing new here if available. + // If the allocation fails, we report an EC_MemoryExhausted error + // back to the caller. + value = new (std::nothrow) Uint8[lengthField + 1]; // protocol error: odd value length +#else + /* make sure that the pointer is set to NULL in case of error */ + try + { + value = new Uint8[lengthField + 1]; // protocol error: odd value length + } + catch (STD_NAMESPACE bad_alloc const &) + { + value = NULL; + } +#endif + /* if creation was successful, set last byte to 0 (in order to initialize this byte) */ + /* (no value will be assigned to this byte later, since Length was odd) */ + if (value) + value[lengthField] = 0; + /* enforce old (pre DCMTK 3.5.2) behaviour ? */ + if (!dcmAcceptOddAttributeLength.get()) + { + lengthField++; + setLengthField(lengthField); // make Length even + } + } + /* if this element's length is even, create a corresponding array of Length bytes */ + else +#ifdef HAVE_STD__NOTHROW + // we want to use a non-throwing new here if available. + // If the allocation fails, we report an EC_MemoryExhausted error + // back to the caller. + value = new (std::nothrow) Uint8[lengthField]; +#else + /* make sure that the pointer is set to NULL in case of error */ + try + { + value = new Uint8[lengthField]; + } + catch (STD_NAMESPACE bad_alloc const &) + { + value = NULL; + } +#endif + /* if creation was not successful set member error flag correspondingly */ + if (!value) + errorFlag = EC_MemoryExhausted; + /* return byte array */ + return value; +} + + +// ******************************** + + +void DcmElement::postLoadValue() +{ + if (dcmEnableAutomaticInputDataCorrection.get()) + { + // newValueField always allocates an even number of bytes + // and sets the pad byte to zero, so we can safely increase Length here + if (getLengthField() & 1) + setLengthField(getLengthField() + 1); // make Length even + } +} + + +// ******************************** + + +OFCondition DcmElement::changeValue(const void *value, + const Uint32 position, + const Uint32 num) +{ + errorFlag = EC_Normal; + // check for invalid parameter values + if (position % num != 0 || getLengthField() % num != 0 || position > getLengthField()) + errorFlag = EC_IllegalCall; + else if (position == getLengthField()) + { + // append value + if (getLengthField() == 0) + { + errorFlag = putValue(value, num); + } else { + // load value (if not loaded yet) + if (!fValue) + errorFlag = loadValue(); + if (errorFlag.good()) + { + Uint8 * newValue; + // allocate new memory for value +#ifdef HAVE_STD__NOTHROW + // we want to use a non-throwing new here if available. + // If the allocation fails, we report an EC_MemoryExhausted error + // back to the caller. + newValue = new (std::nothrow) Uint8[getLengthField() + num]; +#else + /* make sure that the pointer is set to NULL in case of error */ + try + { + newValue = new Uint8[getLengthField() + num]; + } + catch (STD_NAMESPACE bad_alloc const &) + { + newValue = NULL; + } +#endif + if (!newValue) + errorFlag = EC_MemoryExhausted; + if (errorFlag.good()) + { + // swap to local byte order + swapIfNecessary(gLocalByteOrder, fByteOrder, fValue, + getLengthField(), getTag().getVR().getValueWidth()); + fByteOrder = gLocalByteOrder; + // copy old value in the beginning of new value + memcpy(newValue, fValue, size_t(getLengthField())); + // copy value passed as a parameter to the end + memcpy(&newValue[getLengthField()], OFstatic_cast(const Uint8 *, value), size_t(num)); +#if defined(HAVE_STD__NOTHROW) && defined(HAVE_NOTHROW_DELETE) + // if created with the nothrow version it must also be deleted with + // the nothrow version else memory error. + operator delete[] (fValue, std::nothrow); +#else + delete[] fValue; +#endif + fValue = newValue; + setLengthField(getLengthField() + num); + } else + errorFlag = EC_MemoryExhausted; + } + } + } else { + // swap to local byte order + swapIfNecessary(gLocalByteOrder, fByteOrder, fValue, + getLengthField(), getTag().getVR().getValueWidth()); + // copy value at given position + memcpy(&fValue[position], OFstatic_cast(const Uint8 *, value), size_t(num)); + fByteOrder = gLocalByteOrder; + } + return errorFlag; +} + + +// ******************************** + + +OFCondition DcmElement::putOFStringArray(const OFString &val) +{ + /* sets the value of a complete (possibly multi-valued) string attribute */ + return putString(val.c_str(), OFstatic_cast(Uint32, val.length())); +} + + +OFCondition DcmElement::putString(const char * /*val*/) +{ + errorFlag = EC_IllegalCall; + return errorFlag; +} + + +OFCondition DcmElement::putString(const char * /*val*/, + const Uint32 /*len*/) +{ + errorFlag = EC_IllegalCall; + return errorFlag; +} + + +OFCondition DcmElement::putSint16(const Sint16 /*val*/, + const unsigned long /*pos*/) +{ + errorFlag = EC_IllegalCall; + return errorFlag; +} + + +OFCondition DcmElement::putUint16(const Uint16 /*val*/, + const unsigned long /*pos*/) +{ + errorFlag = EC_IllegalCall; + return errorFlag; +} + + +OFCondition DcmElement::putSint32(const Sint32 /*val*/, + const unsigned long /*pos*/) +{ + errorFlag = EC_IllegalCall; + return errorFlag; +} + + +OFCondition DcmElement::putUint32(const Uint32 /*val*/, + const unsigned long /*pos*/) +{ + errorFlag = EC_IllegalCall; + return errorFlag; +} + + +OFCondition DcmElement::putFloat32(const Float32 /*val*/, + const unsigned long /*pos*/) +{ + errorFlag = EC_IllegalCall; + return errorFlag; +} + + +OFCondition DcmElement::putFloat64(const Float64 /*val*/, + const unsigned long /*pos*/) +{ + errorFlag = EC_IllegalCall; + return errorFlag; +} + + +OFCondition DcmElement::putTagVal(const DcmTagKey & /*val*/, + const unsigned long /*pos*/) +{ + errorFlag = EC_IllegalCall; + return errorFlag; +} + + +OFCondition DcmElement::putUint8Array(const Uint8 * /*val*/, + const unsigned long /*num*/) +{ + errorFlag = EC_IllegalCall; + return errorFlag; +} + + +OFCondition DcmElement::putSint16Array(const Sint16 * /*val*/, + const unsigned long /*num*/) +{ + errorFlag = EC_IllegalCall; + return errorFlag; +} + + +OFCondition DcmElement::putUint16Array(const Uint16 * /*val*/, + const unsigned long /*num*/) +{ + errorFlag = EC_IllegalCall; + return errorFlag; +} + + +OFCondition DcmElement::putSint32Array(const Sint32 * /*val*/, + const unsigned long /*num*/) +{ + errorFlag = EC_IllegalCall; + return errorFlag; +} + + +OFCondition DcmElement::putUint32Array(const Uint32 * /*val*/, + const unsigned long /*num*/) +{ + errorFlag = EC_IllegalCall; + return errorFlag; +} + + +OFCondition DcmElement::putFloat32Array(const Float32 * /*val*/, + const unsigned long /*num*/) +{ + errorFlag = EC_IllegalCall; + return errorFlag; +} + + +OFCondition DcmElement::putFloat64Array(const Float64 * /*val*/, + const unsigned long /*num*/) +{ + errorFlag = EC_IllegalCall; + return errorFlag; +} + + +OFCondition DcmElement::putValue(const void * newValue, + const Uint32 length) +{ + errorFlag = EC_Normal; + + if (fValue) + { +#if defined(HAVE_STD__NOTHROW) && defined(HAVE_NOTHROW_DELETE) + // if created with the nothrow version it must also be deleted with + // the nothrow version else memory error. + operator delete[] (fValue, std::nothrow); +#else + delete[] fValue; +#endif + } + fValue = NULL; + + if (fLoadValue) + delete fLoadValue; + fLoadValue = NULL; + + setLengthField(length); + + if (length != 0) + { + fValue = newValueField(); + + // newValueField always allocates an even number of bytes + // and sets the pad byte to zero, so we can safely increase Length here + if (getLengthField() & 1) + setLengthField(getLengthField() + 1); // make Length even + + // copy length (which may be odd), not Length (which is always even) + if (fValue) + memcpy(fValue, newValue, size_t(length)); + else + errorFlag = EC_MemoryExhausted; + } + fByteOrder = gLocalByteOrder; + return errorFlag; +} + + +// ******************************** + + +OFCondition DcmElement::createUint8Array(const Uint32 /*numBytes*/, + Uint8 *& /*bytes*/) +{ + errorFlag = EC_IllegalCall; + return errorFlag; +} + + +OFCondition DcmElement::createUint16Array(const Uint32 /*numWords*/, + Uint16 *& /*bytes*/) +{ + errorFlag = EC_IllegalCall; + return errorFlag; +} + + +// ******************************** + + +OFCondition DcmElement::createEmptyValue(const Uint32 length) +{ + errorFlag = EC_Normal; + if (fValue) + { +#if defined(HAVE_STD__NOTHROW) && defined(HAVE_NOTHROW_DELETE) + // if created with the nothrow version it must also be deleted with + // the nothrow version else memory error. + operator delete[] (fValue, std::nothrow); +#else + delete[] fValue; +#endif + } + fValue = NULL; + if (fLoadValue) + delete fLoadValue; + fLoadValue = NULL; + setLengthField(length); + + if (length != 0) + { + fValue = newValueField(); + // newValueField always allocates an even number of bytes + // and sets the pad byte to zero, so we can safely increase Length here + if (getLengthField() & 1) + setLengthField(getLengthField() + 1); // make Length even + + // initialize bytes (which may be odd), not Length (which is always even) + if (fValue) + memzero(fValue, size_t(length)); + else + errorFlag = EC_MemoryExhausted; + } + fByteOrder = gLocalByteOrder; + return errorFlag; +} + + +// ******************************** + + +OFCondition DcmElement::read(DcmInputStream &inStream, + const E_TransferSyntax ixfer, + const E_GrpLenEncoding /*glenc*/, + const Uint32 maxReadLength) +{ + /* if this element's transfer state shows ERW_notInitialized, this is an illegal call */ + if (getTransferState() == ERW_notInitialized) + errorFlag = EC_IllegalCall; + else + { + /* if this is not an illegal call, go ahead and create a DcmXfer */ + /* object based on the transfer syntax which was passed */ + DcmXfer inXfer(ixfer); + /* determine the transfer syntax's byte ordering */ + fByteOrder = inXfer.getByteOrder(); + /* check if the stream reported an error */ + errorFlag = inStream.status(); + /* if we encountered the end of the stream, set the error flag correspondingly */ + if (errorFlag.good() && inStream.eos()) + { + errorFlag = EC_EndOfStream; // not handled as parsing error by caller + /* Network can never report EOS at this point, so we are in a file + * and no bytes are left for reading. This is only valid if + * the announced length of the current value is 0 and we are in the + * last element of the dataset (e.g. Pixel Data) otherwise it must be an error */ + if (getLengthField() > 0) + { + /* Return error code if we are are not ignoring parsing errors */ + if (!dcmIgnoreParsingErrors.get()) + errorFlag = EC_StreamNotifyClient; + /* In any case, make sure that calling the load value routine on this + * element will fail later. For that, create the stream factory that + * the load routine will use. Otherwise it would not realize + * that there is a problem */ + delete fLoadValue; + fLoadValue = inStream.newFactory(); + /* Print an error message when too few bytes are available in the file in order to + * distinguish this problem from any other generic "InvalidStream" problem. */ + DCMDATA_ERROR("DcmElement: " << getTagName() << " " << getTag() + << " larger (" << getLengthField() << ") than remaining bytes in file"); + } + } + /* if we did not encounter the end of the stream and no error occurred so far, go ahead */ + else if (errorFlag.good()) + { + /* if the transfer state is ERW_init, we need to prepare */ + /* the reading of this element's value from the stream */ + if (getTransferState() == ERW_init) + { + /* if the Length of this element's value is greater than the amount of bytes we */ + /* can read from the stream and if the stream has random access, we want to create */ + /* a DcmInputStreamFactory object that enables us to read this element's value later. */ + /* This new object will be stored (together with the position where we have to start */ + /* reading the value) in the member variable fLoadValue. */ + if (getLengthField() > maxReadLength) + { + /* try to create a stream factory to read the value later */ + delete fLoadValue; + fLoadValue = inStream.newFactory(); + + if (fLoadValue) + { + offile_off_t skipped = inStream.skip(getLengthField()); + if (skipped < getLengthField()) + { + /* If desired, specific parser errors will be ignored */ + if (dcmIgnoreParsingErrors.get()) + errorFlag = EC_Normal; + else + errorFlag = EC_StreamNotifyClient; + /* Print an error message when too few bytes are available in the file in order to + * distinguish this problem from any other generic "InvalidStream" problem. */ + DCMDATA_ERROR("DcmElement: " << getTagName() << " " << getTag() + << " larger (" << getLengthField() << ") than remaining bytes in file"); + } + } + } + /* if there is already a value for this element, delete this value */ +#if defined(HAVE_STD__NOTHROW) && defined(HAVE_NOTHROW_DELETE) + // if created with the nothrow version it must also be deleted with + // the nothrow version else memory error. + operator delete[] (fValue, std::nothrow); +#else + delete[] fValue; +#endif + /* set the transfer state to ERW_inWork */ + setTransferState(ERW_inWork); + } + /* if the transfer state is ERW_inWork and we are not supposed */ + /* to read this element's value later, read the value now */ + if (getTransferState() == ERW_inWork && !fLoadValue) + errorFlag = loadValue(&inStream); + /* if the amount of transferred bytes equals the Length of this element */ + /* or the object which contains information to read the value of this */ + /* element later is existent, set the transfer state to ERW_ready */ + if (getTransferredBytes() == getLengthField() || fLoadValue) + setTransferState(ERW_ready); + } + } + + /* return result value */ + return errorFlag; +} + + +// ******************************** + + +void DcmElement::swapValueField(size_t valueWidth) +{ + if (getLengthField() != 0) + { + if (!fValue) + errorFlag = loadValue(); + + if (errorFlag.good()) + swapBytes(fValue, getLengthField(), valueWidth); + } +} + + +// ******************************** + + +void DcmElement::transferInit() +{ + DcmObject::transferInit(); + setTransferredBytes(0); +} + + +// ******************************** + +OFCondition DcmElement::write(DcmOutputStream &outStream, + const E_TransferSyntax oxfer, + const E_EncodingType /*enctype*/, + DcmWriteCache *wcache) +{ + DcmWriteCache wcache2; + + /* In case the transfer state is not initialized, this is an illegal call */ + if (getTransferState() == ERW_notInitialized) + errorFlag = EC_IllegalCall; + else + { + /* if this is not an illegal call, we need to do something. First */ + /* of all, check the error state of the stream that was passed */ + /* only do something if the error state of the stream is ok */ + errorFlag = outStream.status(); + if (errorFlag.good()) + { + /* create an object that represents the transfer syntax */ + DcmXfer outXfer(oxfer); + + /* pointer to element value if value resides in memory or old-style + * write behaviour is active (i.e. everything loaded into memory upon write) + */ + Uint8 *value = NULL; + OFBool accessPossible = OFFalse; + + /* check that we actually do have access to the element's value. + * If the element is unaccessible (which would mean that the value resides + * in file and access to the file fails), write an empty element with + * zero length. + */ + if (getLengthField() > 0) + { + if (valueLoaded()) + { + /* get this element's value. Mind the byte ordering (little */ + /* or big endian) of the transfer syntax which shall be used */ + value = OFstatic_cast(Uint8 *, getValue(outXfer.getByteOrder())); + if (value) accessPossible = OFTrue; + } + else + { + /* Use local cache object if needed. This may cause those bytes + * that are read but not written because the output stream stalls to + * be read again, and the file from being re-opened next time. + * Therefore, this case should be avoided. + */ + if (!wcache) wcache = &wcache2; + + /* initialize cache object. This is safe even if the object was already initialized */ + wcache->init(this, getLengthField(), getTransferredBytes(), outXfer.getByteOrder()); + + /* access first block of element content */ + errorFlag = wcache->fillBuffer(*this); + + /* check that everything worked and the buffer is non-empty now */ + accessPossible = errorFlag.good() && (! wcache->bufferIsEmpty()); + } + } + + /* if this element's transfer state is ERW_init (i.e. it has not yet been written to */ + /* the stream) and if the outstream provides enough space for tag and length information */ + /* write tag and length information to it, do something */ + if (getTransferState() == ERW_init) + { + /* first compare with DCM_TagInfoLength (12). If there is not enough space + * in the buffer, check if the buffer is still sufficient for the requirements + * of this element, which may need only 8 instead of 12 bytes. + */ + if ((outStream.avail() >= DCM_TagInfoLength) || + (outStream.avail() >= getTagAndLengthSize(oxfer))) + { + /* if there is no value, Length (member variable) shall be set to 0 */ + if (! accessPossible) setLengthField(0); + + /* remember how many bytes have been written to the stream, currently none so far */ + Uint32 writtenBytes = 0; + + /* write tag and length information (and possibly also data type information) to the stream, */ + /* mind the transfer syntax and remember the amount of bytes that have been written */ + errorFlag = writeTagAndLength(outStream, oxfer, writtenBytes); + + /* if the writing was successful, set this element's transfer */ + /* state to ERW_inWork and the amount of transferred bytes to 0 */ + if (errorFlag.good()) + { + setTransferState(ERW_inWork); + setTransferredBytes(0); + } + } else errorFlag = EC_StreamNotifyClient; + } + + /* if there is a value that has to be written to the stream */ + /* and if this element's transfer state is ERW_inWork */ + if (accessPossible && getTransferState() == ERW_inWork) + { + Uint32 len = 0; + if (valueLoaded()) + { + /* write as many bytes as possible to the stream starting at value[getTransferredBytes()] */ + /* (note that the bytes value[0] to value[getTransferredBytes()-1] have already been */ + /* written to the stream) */ + len = OFstatic_cast(Uint32, outStream.write(&value[getTransferredBytes()], getLengthField() - getTransferredBytes())); + + /* increase the amount of bytes which have been transfered correspondingly */ + incTransferredBytes(len); + + /* see if there is something fishy with the stream */ + errorFlag = outStream.status(); + } + else + { + Uint32 buflen = 0; + OFBool done = getTransferredBytes() == getLengthField(); + while (! done) + { + // re-fill buffer from file if empty + errorFlag = wcache->fillBuffer(*this); + buflen = wcache->contentLength(); + + if (errorFlag.good()) + { + // write as many bytes from cache buffer to stream as possible + len = wcache->writeBuffer(outStream); + + /* increase the amount of bytes which have been transfered correspondingly */ + incTransferredBytes(len); + + /* see if there is something fishy with the stream */ + errorFlag = outStream.status(); + } + + // stop writing if something went wrong, we were unable to send all of the buffer content + // (which indicates that the output stream needs to be flushed, or everything was sent out. + done = errorFlag.bad() || (len < buflen) || (getTransferredBytes() == getLengthField()); + } + } + + /* if the amount of transferred bytes equals the length of the element's value, the */ + /* entire value has been written to the stream. Thus, this element's transfer state */ + /* has to be set to ERW_ready. If this is not the case but the error flag still shows */ + /* an ok value, there was no more space in the stream and a corresponding return value */ + /* has to be set. (Isn't the "else if" part superfluous?!?) */ + if (getLengthField() == getTransferredBytes()) setTransferState(ERW_ready); + else if (errorFlag.good()) errorFlag = EC_StreamNotifyClient; + + } + } + } + /* return result value */ + return errorFlag; +} + + +OFCondition DcmElement::writeSignatureFormat(DcmOutputStream &outStream, + const E_TransferSyntax oxfer, + const E_EncodingType enctype, + DcmWriteCache *wcache) +{ + // for normal DICOM elements (everything except sequences), the data + // stream used for digital signature creation or verification is + // identical to the stream used for network communication or media + // storage. + return write(outStream, oxfer, enctype, wcache); +} + + +// ******************************** + + +void DcmElement::writeXMLStartTag(STD_NAMESPACE ostream &out, + const size_t flags, + const char *attrText) +{ + OFString xmlString; + DcmVR vr(getTag().getVR()); + DcmTag tag = getTag(); + const OFBool isPrivate = tag.isPrivate(); + + /* write XML start tag for attribute */ + if (flags & DCMTypes::XF_useNativeModel) + { + out << "" << OFendl; + } else { + /* value multiplicity = 1..n */ + out << " vm=\"" << getVM() << "\""; + /* value length in bytes = 0..max */ + out << " len=\"" << getLengthField() << "\""; + /* tag name (if known and not suppressed) */ + if (!(flags & DCMTypes::XF_omitDataElementName)) + out << " name=\"" << OFStandard::convertToMarkupString(getTagName(), xmlString) << "\""; + /* value loaded = no (or absent)*/ + if (!valueLoaded()) + out << " loaded=\"no\""; + /* write additional attributes (if any) */ + if ((attrText != NULL) && (attrText[0] != '\0')) + out << " " << attrText; + /* close XML start tag */ + out << ">"; + } +} + + +void DcmElement::writeXMLEndTag(STD_NAMESPACE ostream &out, + const size_t flags) +{ + /* write standardized XML end tag for all element types */ + if (flags & DCMTypes::XF_useNativeModel) + out << "" << OFendl; + else + out << "" << OFendl; +} + + +OFCondition DcmElement::writeXML(STD_NAMESPACE ostream &out, + const size_t flags) +{ + /* do not output group length elements in Native DICOM Model + * (as per PS 3.19 section A.1.1, introduced with Supplement 166) */ + if (!(flags & DCMTypes::XF_useNativeModel) || !getTag().isGroupLength()) + { + /* write XML start tag */ + writeXMLStartTag(out, flags); + OFString value; + const OFBool convertNonASCII = (flags & DCMTypes::XF_convertNonASCII) > 0; + if (flags & DCMTypes::XF_useNativeModel) + { + /* write element value (if non-empty) */ + if (!isEmpty()) + { + const unsigned long vm = getVM(); + for (unsigned long valNo = 0; valNo < vm; valNo++) + { + if (getOFString(value, valNo).good()) + { + out << ""; + /* check whether conversion to XML markup string is required */ + if (OFStandard::checkForMarkupConversion(value, convertNonASCII)) + OFStandard::convertToMarkupStream(out, value, convertNonASCII); + else + out << value; + out << "" << OFendl; + } + } + } + } else { + /* write element value (only if loaded) */ + if (valueLoaded()) + { + if (getOFStringArray(value).good()) + { + /* check whether conversion to XML markup string is required */ + if (OFStandard::checkForMarkupConversion(value, convertNonASCII)) + OFStandard::convertToMarkupStream(out, value, convertNonASCII); + else + out << value; + } + } + } + /* write XML end tag */ + writeXMLEndTag(out, flags); + } + /* always report success */ + return EC_Normal; +} + + +// ******************************** + + +OFCondition DcmElement::getPartialValue(void *targetBuffer, + const Uint32 offset, + Uint32 numBytes, + DcmFileCache *cache, + E_ByteOrder byteOrder) +{ + // check integrity of parameters passed to this method + if (targetBuffer == NULL) return EC_IllegalCall; + + // if the user has only requested zero bytes, we immediately return + if (numBytes == 0) return EC_Normal; + + // offset must always be less than attribute length (unless offset, + // attribute length and numBytes are all zero, a case that was + // handled above). + if (offset >= getLengthField()) return EC_InvalidOffset; + + // check if the caller is trying to read past the end of the value field + if (numBytes > (getLengthField() - offset)) return EC_TooManyBytesRequested; + + // check if the value is already in memory + if (valueLoaded()) + { + // the attribute value is already in memory. + // change internal byte order of the attribute value to the desired byte order. + // This should only happen once for multiple calls to this method since the + // caller will hopefully always request the same byte order. + char *value = OFstatic_cast(char *, getValue(byteOrder)); + if (value) + { + memcpy(targetBuffer, value + offset, numBytes); + } + else + { + // this should never happen because valueLoaded() returned true, but + // we don't want to dereference a NULL pointer anyway + return EC_IllegalCall; + } + } + else + { + // the value is not in memory. We should directly read from file and + // also consider byte order. + + // since the value is not in memory, fLoadValue should exist. Check anyway. + if (! fLoadValue) return EC_IllegalCall; + + // make sure we have a file cache object + DcmFileCache defaultcache; // automatic object, creation is cheap. + if (cache == NULL) cache = &defaultcache; + + // the stream from which we will read the attribute value + DcmInputStream *readStream = NULL; + + // check if we need to seek to a position in file earlier than + // the one specified by the user in order to correctly swap according + // to the VR. + size_t valueWidth = getTag().getVR().getValueWidth(); + + // we need to cast the target buffer to something we can increment bytewise + char *targetBufferChar = OFreinterpret_cast(char *, targetBuffer); + + // the swap buffer should be large enough to keep one value of the current VR + unsigned char swapBuffer[SWAPBUFFER_SIZE]; + if (valueWidth > SWAPBUFFER_SIZE) return EC_IllegalCall; + + // seekoffset is the number of bytes we need to skip from the beginning of the + // value field to the point where we will start reading. This is always at the + // start of a new value of a multi-valued attribute. + Uint32 partialvalue = 0; + const Uint32 partialoffset = OFstatic_cast(Uint32, offset % valueWidth); + const offile_off_t seekoffset = offset - partialoffset; + + // check if cache already contains the stream we're looking for + if (cache->isUser(this)) + { + readStream = cache->getStream(); + + // since we cannot seek back in the stream (only forward), check if the stream + // is already past our needed start position + if (readStream->tell() - cache->getOffset() > seekoffset) + { + readStream = NULL; + } + } + + // initialize the cache with new stream + if (!readStream) + { + readStream = fLoadValue->create(); + + // check that read stream is non-NULL + if (readStream == NULL) return EC_InvalidStream; + + // check that stream status is OK + if (readStream->status().bad()) return readStream->status(); + + cache->init(readStream, this); + } + + // now skip bytes from our current position in file to where we + // want to start reading. + offile_off_t remainingBytesToSkip = seekoffset - (readStream->tell() - cache->getOffset()); + offile_off_t skipResult; + + while (remainingBytesToSkip) + { + skipResult = readStream->skip(remainingBytesToSkip); + if (skipResult == 0) return EC_InvalidStream; // error while skipping + remainingBytesToSkip -= skipResult; + } + + // check if the first few bytes we want to read are "in the middle" of one value + // of a multi-valued attribute. In that case we need to read the complete value, + // swap it and then copy only the last bytes in desired byte order. + if (partialoffset > 0) + { + // we possibly want to reset the stream to this point later + readStream->mark(); + + // compute the number of bytes we need to copy from the first attributes + partialvalue = OFstatic_cast(Uint32, valueWidth - partialoffset); + + // we need to read a single data element into the swap buffer + if (valueWidth != OFstatic_cast(size_t, readStream->read(swapBuffer, valueWidth))) + return EC_InvalidStream; + + // swap to desired byte order. fByteOrder contains the byte order in file. + swapIfNecessary(byteOrder, fByteOrder, swapBuffer, OFstatic_cast(Uint32, valueWidth), valueWidth); + + // copy to target buffer and adjust values + if (partialvalue > numBytes) + { + memcpy(targetBufferChar, &swapBuffer[partialoffset], numBytes); + targetBufferChar += numBytes; + numBytes = 0; + + // Reset stream to position marked before, since we have not copied the complete value + readStream->putback(); + } + else + { + memcpy(targetBufferChar, &swapBuffer[partialoffset], partialvalue); + targetBufferChar += partialvalue; + numBytes -= partialvalue; + } + } + + // now read the main block of data directly into the target buffer + partialvalue = OFstatic_cast(Uint32, numBytes % valueWidth); + const Uint32 bytesToRead = numBytes - partialvalue; + + if (bytesToRead > 0) + { + // here we read the main block of data + if (bytesToRead != readStream->read(targetBufferChar, bytesToRead)) + return EC_InvalidStream; + + // swap to desired byte order. fByteOrder contains the byte order in file. + swapIfNecessary(byteOrder, fByteOrder, targetBufferChar, bytesToRead, valueWidth); + + // adjust pointer to target buffer + targetBufferChar += bytesToRead; + } + + // check if the last few bytes we want to read are only a partial value. + // In that case we need to read the complete value, swap it and then copy + // only the first few bytes in desired byte order. + if (partialvalue > 0) + { + OFBool appendDuplicateByte = OFFalse; + size_t partialBytesToRead = valueWidth; + + // we want to reset the stream to this point later + readStream->mark(); + + if (readStream->tell() + valueWidth > getLengthField()) { + // We are trying to read past the end of the value. We already made sure + // above that the requested range fits completely into the element's + // size, so this must mean that the length is not a multiple of the VR's + // value width. + // We allow this for OW and error out on all other VRs. + if (getTag().getVR().getValidEVR() == EVR_OW) + { + DCMDATA_WARN("DcmElement: Trying to read past end of value, duplicating last byte"); + appendDuplicateByte = OFTrue; + // This is 2 for OW, but we know that only 1 byte of data is available + partialBytesToRead--; + } + else + { + // This would read the beginning of the next element from the stream, + // possibly hitting the end of stream. + DCMDATA_ERROR("DcmElement: Trying to read past end of value"); + return EC_InvalidStream; + } + } + + // we need to read a single data element into the swap buffer + if (partialBytesToRead != OFstatic_cast(size_t, readStream->read(swapBuffer, partialBytesToRead))) + return EC_InvalidStream; + + if (appendDuplicateByte) + swapBuffer[partialBytesToRead] = swapBuffer[partialBytesToRead - 1]; + + // swap to desired byte order. fByteOrder contains the byte order in file. + swapIfNecessary(byteOrder, fByteOrder, swapBuffer, OFstatic_cast(Uint32, valueWidth), valueWidth); + + // copy to target buffer and adjust values + memcpy(targetBufferChar, swapBuffer, partialvalue); + + // finally reset stream to position marked before + readStream->putback(); + } + } + + // done. + return EC_Normal; +} + + +void DcmElement::compact() +{ + if (fLoadValue && fValue) + { + DCMDATA_DEBUG("DcmElement::compact() removed element value of " << getTag() + << " with " << getTransferredBytes() << " bytes"); + delete[] fValue; + fValue = NULL; + setTransferredBytes(0); + } +} + + +OFCondition DcmElement::createValueFromTempFile(DcmInputStreamFactory *factory, + const Uint32 length, + const E_ByteOrder byteOrder) +{ + if (factory && !(length & 1)) + { +#if defined(HAVE_STD__NOTHROW) && defined(HAVE_NOTHROW_DELETE) + // if created with the nothrow version it must also be deleted with + // the nothrow version else memory error. + operator delete[] (fValue, std::nothrow); +#else + delete[] fValue; +#endif + fValue = 0; + delete fLoadValue; + fLoadValue = factory; + fByteOrder = byteOrder; + setLengthField(length); + return EC_Normal; + } + else return EC_IllegalCall; +} + + +OFCondition DcmElement::getUncompressedFrameSize(DcmItem *dataset, + Uint32 &frameSize) const +{ + if (dataset == NULL) return EC_IllegalCall; + Uint16 rows = 0; + Uint16 cols = 0; + Uint16 samplesPerPixel = 0; + Uint16 bitsAllocated = 0; + // retrieve values from dataset + OFCondition result = EC_Normal; + if (result.good()) result = dataset->findAndGetUint16(DCM_Columns, cols); + if (result.good()) result = dataset->findAndGetUint16(DCM_Rows, rows); + if (result.good()) result = dataset->findAndGetUint16(DCM_SamplesPerPixel, samplesPerPixel); + if (result.good()) result = dataset->findAndGetUint16(DCM_BitsAllocated, bitsAllocated); + + // compute frame size + if ((bitsAllocated % 8) == 0) + { + const Uint16 bytesAllocated = bitsAllocated / 8; + frameSize = bytesAllocated * rows * cols * samplesPerPixel; + } + else + { + /* need to split calculation in order to avoid integer overflow for large pixel data */ + const Uint32 v1 = rows * cols * samplesPerPixel; + const Uint32 v2 = (bitsAllocated / 8) * v1; + const Uint32 v3 = ((bitsAllocated % 8) * v1 + 7) / 8; +// # old code: frameSize = (bitsAllocated * rows * cols * samplesPerPixel + 7) / 8; + frameSize = v2 + v3; + } + + return result; +} + + +OFCondition DcmElement::getUncompressedFrame(DcmItem * /* dataset */ , + Uint32 /* frameNo */ , + Uint32& /* startFragment */ , + void * /* buffer */ , + Uint32 /* bufSize */ , + OFString& /* decompressedColorModel */ , + DcmFileCache * /* cache */ ) +{ + return EC_IllegalCall; +} + + +OFCondition DcmElement::getDecompressedColorModel(DcmItem * /* dataset */, + OFString & /* decompressedColorModel */) +{ + return EC_IllegalCall; +} + + +// ******************************** + + +int DcmElement::scanValue(const OFString &value, + const OFString &vr, + const size_t pos, + const size_t num) +{ + // Only create a copy of the string if we have to, this could be a lot of data + if (pos == 0 && (num == OFString_npos || num >= value.length())) + return vrscan::scan(vr, value); + + // construct input string to be scanned + OFString realValue(value, pos, num); + return vrscan::scan(vr, realValue); +} + + +unsigned long DcmElement::determineVM(const char *str, + const size_t len) +{ + unsigned long vm = 0; + // check for non-empty string + if ((str != NULL) && (len > 0)) + { + // count number of delimiters (plus 1) + vm = 1; + const char *p = str; + for (size_t i = 0; i < len; i++) + { + if (*p++ == '\\') + vm++; + } + } + return vm; +} + + +size_t DcmElement::getValueFromString(const char *str, + const size_t pos, + const size_t len, + OFString &val) +{ + size_t newPos = pos; + // check for non-empty string or invalid start position + if ((str != NULL) && (len > 0) && (pos < len)) + { + // start at given position + const char *p = str + pos; + // search for next backslash (if any) + while ((newPos++ < len) && (*p != '\\')) + p++; + // extract selected value from string + val.assign(str + pos, newPos - pos - 1); + } else + val.clear(); + return newPos; +} + + +OFCondition DcmElement::checkVM(const unsigned long vmNum, + const OFString &vmStr) +{ + OFCondition result = EC_Normal; + // only check non-empty values + if (vmNum > 0) + { + if (vmStr == "1") + { + if (vmNum != 1) result = EC_ValueMultiplicityViolated; + } + else if (vmStr == "1-2") + { + if (vmNum > 2) result = EC_ValueMultiplicityViolated; + } + else if (vmStr == "1-3") + { + if (vmNum > 3) result = EC_ValueMultiplicityViolated; + } + else if (vmStr == "1-8") + { + if (vmNum > 8) result = EC_ValueMultiplicityViolated; + } + else if (vmStr == "1-99") + { + if (vmNum > 99) result = EC_ValueMultiplicityViolated; + } + else if (vmStr == "2") + { + if (vmNum != 2) result = EC_ValueMultiplicityViolated; + } + else if (vmStr == "2-n") + { + if (vmNum < 2) result = EC_ValueMultiplicityViolated; + } + else if (vmStr == "2-2n") + { + if ((vmNum % 2) != 0) result = EC_ValueMultiplicityViolated; + } + else if (vmStr == "3") + { + if (vmNum != 3) result = EC_ValueMultiplicityViolated; + } + else if (vmStr == "3-n") + { + if (vmNum < 3) result = EC_ValueMultiplicityViolated; + } + else if (vmStr == "3-3n") + { + if ((vmNum % 3) != 0) result = EC_ValueMultiplicityViolated; + } + else if (vmStr == "4") + { + if (vmNum != 4) result = EC_ValueMultiplicityViolated; + } + else if (vmStr == "5") + { + if (vmNum != 5) result = EC_ValueMultiplicityViolated; + } + else if (vmStr == "5-n") + { + if (vmNum < 5) result = EC_ValueMultiplicityViolated; + } + else if (vmStr == "6") + { + if (vmNum != 6) result = EC_ValueMultiplicityViolated; + } + else if (vmStr == "7") + { + if (vmNum != 7) result = EC_ValueMultiplicityViolated; + } + else if (vmStr == "7-7n") + { + if ((vmNum % 7) != 0) result = EC_ValueMultiplicityViolated; + } + else if (vmStr == "8") + { + if (vmNum != 8) result = EC_ValueMultiplicityViolated; + } + else if (vmStr == "9") + { + if (vmNum != 9) result = EC_ValueMultiplicityViolated; + } + else if (vmStr == "16") + { + if (vmNum != 16) result = EC_ValueMultiplicityViolated; + } + else if (vmStr == "24") + { + if (vmNum != 24) result = EC_ValueMultiplicityViolated; + } + else if (vmStr == "32") + { + if (vmNum != 32) result = EC_ValueMultiplicityViolated; + } + else if (vmStr == "256") + { + if (vmNum != 256) result = EC_ValueMultiplicityViolated; + } + else if ( (vmStr != "1-n") && (vmStr != "0-n") ) + { + // given value of 'vmStr' not (yet) supported + result = EC_IllegalParameter; + } + } + return result; +} diff --git a/dcmdata/libsrc/dcerror.cc b/dcmdata/libsrc/dcerror.cc new file mode 100644 index 00000000..e0afd612 --- /dev/null +++ b/dcmdata/libsrc/dcerror.cc @@ -0,0 +1,82 @@ +/* + * + * Copyright (C) 1994-2015, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Andrew Hewett + * + * Purpose: Error handling, codes and strings + * + */ + + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/dcmdata/dcerror.h" + +makeOFConditionConst(EC_InvalidTag, OFM_dcmdata, 1, OF_error, "Invalid tag" ); +makeOFConditionConst(EC_TagNotFound, OFM_dcmdata, 2, OF_error, "Tag not found" ); +makeOFConditionConst(EC_InvalidVR, OFM_dcmdata, 3, OF_error, "Invalid VR" ); +makeOFConditionConst(EC_InvalidStream, OFM_dcmdata, 4, OF_error, "Invalid stream" ); +makeOFConditionConst(EC_EndOfStream, OFM_dcmdata, 5, OF_error, "End of stream" ); +makeOFConditionConst(EC_CorruptedData, OFM_dcmdata, 6, OF_error, "Corrupted data" ); +makeOFConditionConst(EC_IllegalCall, OFM_dcmdata, 7, OF_error, "Illegal call, perhaps wrong parameters" ); +makeOFConditionConst(EC_SequEnd, OFM_dcmdata, 8, OF_error, "Sequence end" ); +makeOFConditionConst(EC_DoubledTag, OFM_dcmdata, 9, OF_error, "Doubled tag" ); +makeOFConditionConst(EC_StreamNotifyClient, OFM_dcmdata, 10, OF_error, "I/O suspension or premature end of stream" ); +makeOFConditionConst(EC_WrongStreamMode, OFM_dcmdata, 11, OF_error, "Mode (R/W, random/sequence) is wrong" ); +makeOFConditionConst(EC_ItemEnd, OFM_dcmdata, 12, OF_error, "Item end" ); +makeOFConditionConst(EC_RepresentationNotFound, OFM_dcmdata, 13, OF_error, "Pixel representation not found" ); +makeOFConditionConst(EC_CannotChangeRepresentation, OFM_dcmdata, 14, OF_error, "Pixel representation cannot be changed" ); +makeOFConditionConst(EC_UnsupportedEncoding, OFM_dcmdata, 15, OF_error, "Unsupported compression or encryption" ); +// error code 16 is reserved for zlib-related error messages +makeOFConditionConst(EC_PutbackFailed, OFM_dcmdata, 17, OF_error, "Parser failure: Putback operation failed" ); +// error code 18 is reserved for file read error messages +// error code 19 is reserved for file write error messages +makeOFConditionConst(EC_DoubleCompressionFilters, OFM_dcmdata, 20, OF_error, "Too many compression filters" ); +makeOFConditionConst(EC_ApplicationProfileViolated, OFM_dcmdata, 21, OF_error, "Storage media application profile violated" ); +// error code 22 is reserved for dcmodify error messages +makeOFConditionConst(EC_InvalidOffset, OFM_dcmdata, 23, OF_error, "Invalid offset" ); +makeOFConditionConst(EC_TooManyBytesRequested, OFM_dcmdata, 24, OF_error, "Too many bytes requested" ); +// error code 25 is reserved for tag path parsing error messages +makeOFConditionConst(EC_InvalidBasicOffsetTable, OFM_dcmdata, 26, OF_error, "Invalid basic offset table" ); +makeOFConditionConst(EC_ElemLengthLargerThanItem, OFM_dcmdata, 27, OF_error, "Length of element larger than explicit length of surrounding item" ); +makeOFConditionConst(EC_FileMetaInfoHeaderMissing, OFM_dcmdata, 28, OF_error, "File meta information header missing" ); +makeOFConditionConst(EC_SeqOrItemContentOverflow, OFM_dcmdata, 29, OF_error, "Item or sequence content exceeds maximum of 32-bit length field"); +makeOFConditionConst(EC_ValueRepresentationViolated, OFM_dcmdata, 30, OF_error, "Value Representation violated" ); +makeOFConditionConst(EC_ValueMultiplicityViolated, OFM_dcmdata, 31, OF_error, "Value Multiplicity violated" ); +makeOFConditionConst(EC_MaximumLengthViolated, OFM_dcmdata, 32, OF_error, "Maximum VR length violated" ); +makeOFConditionConst(EC_ElemLengthExceeds16BitField, OFM_dcmdata, 33, OF_error, "Length of element value exceeds maximum of 16-bit length field" ); +makeOFConditionConst(EC_SequDelimitationItemMissing, OFM_dcmdata, 34, OF_error, "Sequence Delimitation Item missing" ); +// error codes 35..36 are reserved for specific character set error messages (see below) +// error code 37 is reserved for XML conversion error messages (see below) +makeOFConditionConst(EC_ItemDelimitationItemMissing, OFM_dcmdata, 38, OF_error, "Item Delimitation Item missing" ); +makeOFConditionConst(EC_PrematureSequDelimitationItem, OFM_dcmdata, 39, OF_error, "Sequence Delimitation Item occurred before Item was completely read" ); +makeOFConditionConst(EC_InvalidDICOMDIR, OFM_dcmdata, 40, OF_error, "Invalid DICOMDIR" ); +makeOFConditionConst(EC_UnknownVR, OFM_dcmdata, 41, OF_error, "Unknown VR: Tag not found in data dictionary" ); +makeOFConditionConst(EC_InvalidValue, OFM_dcmdata, 42, OF_error, "Invalid Value"); +makeOFConditionConst(EC_ItemNotFound, OFM_dcmdata, 43, OF_error, "Item not found"); +makeOFConditionConst(EC_UnknownTransferSyntax, OFM_dcmdata, 44, OF_error, "Unknown Transfer Syntax"); +makeOFConditionConst(EC_CannotCheck, OFM_dcmdata, 45, OF_error, "Cannot perform check"); +makeOFConditionConst(EC_MissingValue, OFM_dcmdata, 46, OF_error, "Missing value"); +makeOFConditionConst(EC_MissingAttribute, OFM_dcmdata, 47, OF_error, "Missing attribute"); +makeOFConditionConst(EC_InternalError, OFM_dcmdata, 48, OF_error, "Internal error"); + +const unsigned short EC_CODE_CannotSelectCharacterSet = 35; +const unsigned short EC_CODE_CannotConvertCharacterSet = 36; +const unsigned short EC_CODE_CannotConvertToXML = 37; + +const char *dcmErrorConditionToString(OFCondition cond) +{ + return cond.text(); +} diff --git a/dcmdata/libsrc/dcfilefo.cc b/dcmdata/libsrc/dcfilefo.cc new file mode 100644 index 00000000..322c96a3 --- /dev/null +++ b/dcmdata/libsrc/dcfilefo.cc @@ -0,0 +1,1050 @@ +/* + * + * Copyright (C) 1994-2015, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Gerd Ehlers, Andreas Barth + * + * Purpose: class DcmFileFormat + * + */ + + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#define INCLUDE_CSTDLIB +#define INCLUDE_CSTDIO +#define INCLUDE_CSTRING +#define INCLUDE_CTIME +#define INCLUDE_UNISTD +#include "dcmtk/ofstd/ofstdinc.h" + +#include "dcmtk/ofstd/ofstream.h" +#include "dcmtk/dcmdata/dcfilefo.h" +#include "dcmtk/dcmdata/dcitem.h" +#include "dcmtk/dcmdata/dcxfer.h" +#include "dcmtk/dcmdata/dcvrobow.h" +#include "dcmtk/dcmdata/dcvrui.h" +#include "dcmtk/dcmdata/dcvrul.h" +#include "dcmtk/dcmdata/dcvrus.h" +#include "dcmtk/dcmdata/dcvrae.h" +#include "dcmtk/dcmdata/dcvrsh.h" +#include "dcmtk/dcmdata/dcmetinf.h" + +#include "dcmtk/dcmdata/dcdeftag.h" +#include "dcmtk/dcmdata/dcuid.h" +#include "dcmtk/dcmdata/dcostrma.h" /* for class DcmOutputStream */ +#include "dcmtk/dcmdata/dcostrmf.h" /* for class DcmOutputFileStream */ +#include "dcmtk/dcmdata/dcistrma.h" /* for class DcmInputStream */ +#include "dcmtk/dcmdata/dcistrmf.h" /* for class DcmInputFileStream */ +#include "dcmtk/dcmdata/dcwcache.h" /* for class DcmWriteCache */ + + +// ******************************** + + +DcmFileFormat::DcmFileFormat() + : DcmSequenceOfItems(DCM_InternalUseTag), + FileReadMode(ERM_autoDetect) +{ + DcmMetaInfo *MetaInfo = new DcmMetaInfo(); + DcmSequenceOfItems::itemList->insert(MetaInfo); + MetaInfo->setParent(this); + + DcmDataset *Dataset = new DcmDataset(); + DcmSequenceOfItems::itemList->insert(Dataset); + Dataset->setParent(this); +} + + +DcmFileFormat::DcmFileFormat(DcmDataset *dataset, + OFBool deepCopy) + : DcmSequenceOfItems(DCM_InternalUseTag), + FileReadMode(ERM_autoDetect) +{ + DcmMetaInfo *MetaInfo = new DcmMetaInfo(); + DcmSequenceOfItems::itemList->insert(MetaInfo); + MetaInfo->setParent(this); + + DcmDataset* insertion; + if (dataset == NULL) + { + insertion = new DcmDataset(); + } + else if (deepCopy) + { + insertion = new DcmDataset(*dataset); + } + else // shallow copy + { + insertion = dataset; + } + insertion->setParent(this); + DcmSequenceOfItems::itemList->insert(insertion); +} + + +DcmFileFormat::DcmFileFormat(const DcmFileFormat &old) + : DcmSequenceOfItems(old), + FileReadMode(old.FileReadMode) +{ +} + + +OFCondition DcmFileFormat::copyFrom(const DcmObject& rhs) +{ + if (this != &rhs) + { + if (rhs.ident() != ident()) return EC_IllegalCall; + *this = OFstatic_cast(const DcmFileFormat &, rhs); + } + return EC_Normal; +} + + +DcmFileFormat::~DcmFileFormat() +{ +} + + +DcmFileFormat &DcmFileFormat::operator=(const DcmFileFormat &obj) +{ + if (this != &obj) + { + DcmSequenceOfItems::operator=(obj); + FileReadMode = obj.FileReadMode; + } + + return *this; +} + + +// ******************************** + + +DcmEVR DcmFileFormat::ident() const +{ + return EVR_fileFormat; +} + + +// ******************************** + + +void DcmFileFormat::print(STD_NAMESPACE ostream &out, + const size_t flags, + const int level, + const char *pixelFileName, + size_t *pixelCounter) +{ + out << OFendl; + if (flags & DCMTypes::PF_useANSIEscapeCodes) + out << DCMDATA_ANSI_ESCAPE_CODE_COMMENT; + printNestingLevel(out, flags, level); + out << "# Dicom-File-Format"; + if (flags & DCMTypes::PF_useANSIEscapeCodes) + out << DCMDATA_ANSI_ESCAPE_CODE_RESET; + out << OFendl; + if (!itemList->empty()) + { + DcmObject *dO; + itemList->seek(ELP_first); + do { + dO = itemList->get(); + dO->print(out, flags, level, pixelFileName, pixelCounter); + } while (itemList->seek(ELP_next)); + } else { + if (flags & DCMTypes::PF_useANSIEscapeCodes) + out << DCMDATA_ANSI_ESCAPE_CODE_COMMENT; + printNestingLevel(out, flags, level); + out << "# Dicom-File-Format has been erased"; + if (flags & DCMTypes::PF_useANSIEscapeCodes) + out << DCMDATA_ANSI_ESCAPE_CODE_RESET; + out << OFendl; + } +} + + +// ******************************** + + +OFCondition DcmFileFormat::writeXML(STD_NAMESPACE ostream &out, + const size_t flags) +{ + if (flags & DCMTypes::XF_useNativeModel) + { + /* in Native DICOM Model, there is no concept of a "file format" */ + DcmDataset *dset = getDataset(); + if (dset != NULL) + { + /* write content of dataset */ + return dset->writeXML(out, flags); + } else { + return makeOFCondition(OFM_dcmdata, EC_CODE_CannotConvertToXML, OF_error, + "Cannot convert to Native DICOM Model: No dataset present"); + } + } else { + OFCondition result = EC_CorruptedData; + /* XML start tag for "file-format" */ + out << "" << OFendl; + /* write content of file meta information and dataset */ + if (!itemList->empty()) + { + /* write content of all children */ + DcmObject *dO; + itemList->seek(ELP_first); + do { + dO = itemList->get(); + dO->writeXML(out, flags & ~DCMTypes::XF_useXMLNamespace); + } while (itemList->seek(ELP_next)); + result = EC_Normal; + } + /* XML end tag for "file-format" */ + out << "" << OFendl; + return result; + } +} + + +// ******************************** + + +OFCondition DcmFileFormat::checkMetaHeaderValue(DcmMetaInfo *metainfo, + DcmDataset *dataset, + const DcmTagKey &atagkey, + DcmObject *obj, + const E_TransferSyntax oxfer, + const E_FileWriteMode writeMode) + /* + * This function checks if a particular data element of the file meta information header is + * existent. If the element is not existent, it will be inserted. Additionally, this function + * makes sure that the corresponding data element will contain a correct value. + * + * Parameters: + * metainfo - [in] The meta header information. + * dataset - [in] The data set information. + * atagkey - [in] Tag of the data element which shall be checked. + * obj - [in] Data object from metainfo which represents the data element that shall be checked. + * Equals NULL, if this data element is not existent in the meta header information. + * oxfer - [in] The transfer syntax which shall be used. + * writeMode - [in] Flag indicating whether to update the file meta information or not. + */ +{ + /* initialize result value */ + OFCondition l_error = EC_Normal; + + /* if there is meta header information and also data set information, do something */ + if ((metainfo != NULL) && (dataset != NULL)) + { + /* initialize variables */ + DcmStack stack; + DcmTag tag(atagkey); + if (obj != NULL) + tag = obj->getTag(); + + DcmTagKey xtag = tag.getXTag(); + DcmElement *elem = OFstatic_cast(DcmElement *, obj); + + /* go ahead and scrutinize one particular data element (depending on xtag) */ + if (xtag == DCM_FileMetaInformationGroupLength) // (0002,0000) + { + if (elem == NULL) + { + elem = new DcmUnsignedLong(tag); + metainfo->insert(elem, OFTrue); + } + Uint32 temp = 0; + if ((elem->getLength() == 0) && (elem->ident() == EVR_UL)) + OFstatic_cast(DcmUnsignedLong *, elem)->putUint32Array(&temp, 1); + // the calculation of actual group length value is contained in validateMetaInfo() + } + else if (xtag == DCM_FileMetaInformationVersion) // (0002,0001) + { + if (elem == NULL) + { + elem = new DcmOtherByteOtherWord(tag); + metainfo->insert(elem, OFTrue); + } + // supported version of this implementation: 00\01 + Uint8 version[2] = {0, 1}; + if ((elem->getLength() == 0) && (elem->ident() == EVR_OB)) + OFstatic_cast(DcmOtherByteOtherWord *, elem)->putUint8Array(version, 2); + + // check version of meta header + Uint8 *currVers = NULL; + l_error = OFstatic_cast(DcmOtherByteOtherWord *, elem)->getUint8Array(currVers); + if (l_error.good() && (currVers != NULL)) + { + // the version information is stored in a bit field + if (((currVers[0] & version[0] & 0xff) == version[0]) && + ((currVers[1] & version[1] & 0xff) == version[1])) + { + DCMDATA_DEBUG("DcmFileFormat::checkMetaHeaderValue() Version of MetaHeader is ok: 0x" + << STD_NAMESPACE hex << STD_NAMESPACE setfill('0') + << STD_NAMESPACE setw(2) << OFstatic_cast(int, currVers[0]) + << STD_NAMESPACE setw(2) << OFstatic_cast(int, currVers[1])); + } else { + DCMDATA_WARN ("DcmFileFormat: Unknown Version of MetaHeader detected: 0x" + << STD_NAMESPACE hex << STD_NAMESPACE setfill('0') + << STD_NAMESPACE setw(2) << OFstatic_cast(int, currVers[0]) + << STD_NAMESPACE setw(2) << OFstatic_cast(int, currVers[1]) + << ", supported: 0x" + << STD_NAMESPACE setw(2) << OFstatic_cast(int, version[0]) + << STD_NAMESPACE setw(2) << OFstatic_cast(int, version[1])); + } + } else { + DCMDATA_ERROR("DcmFileFormat: Cannot determine Version of MetaHeader"); + } + } + else if (xtag == DCM_MediaStorageSOPClassUID) // (0002,0002) + { + if (elem == NULL) + { + elem = new DcmUniqueIdentifier(tag); + metainfo->insert(elem, OFTrue); + } + if (elem->ident() == EVR_UI) + { + if ((writeMode == EWM_updateMeta) || (elem->getLength() == 0)) + { + if (dataset->search(DCM_SOPClassUID, stack).good()) + { + char *uid = NULL; + l_error = OFstatic_cast(DcmUniqueIdentifier *, stack.top())->getString(uid); + OFstatic_cast(DcmUniqueIdentifier *, elem)->putString(uid); + DCMDATA_DEBUG("DcmFileFormat::checkMetaHeaderValue() use SOPClassUID [" << uid << "] from Dataset"); + } + else if (elem->getLength() == 0) + { + OFstatic_cast(DcmUniqueIdentifier *, elem)->putString(UID_PrivateGenericFileSOPClass); + DCMDATA_DEBUG("DcmFileFormat::checkMetaHeaderValue() no SOPClassUID in Dataset, using PrivateGenericFileSOPClass"); + } + } + else if (DCM_dcmdataLogger.isEnabledFor(OFLogger::WARN_LOG_LEVEL)) + { + // check whether UID in meta-header is identical to the one in the dataset + if (dataset->search(DCM_SOPClassUID, stack).good()) + { + OFString uidDataset, uidMetaHeader; + OFstatic_cast(DcmUniqueIdentifier *, stack.top())->getOFStringArray(uidDataset); + OFstatic_cast(DcmUniqueIdentifier *, elem)->getOFStringArray(uidMetaHeader); + if (uidDataset != uidMetaHeader) + { + DCMDATA_WARN("DcmFileFormat: Value of SOPClassUID in MetaHeader and Dataset is different"); + DCMDATA_DEBUG("DcmFileFormat::checkMetaHeaderValue() value of MediaStorageSOPClassUID (MetaHeader) [" << uidMetaHeader << "]"); + DCMDATA_DEBUG("DcmFileFormat::checkMetaHeaderValue() value of SOPClassUID (Dataset) [" << uidDataset << "]"); + } + } + } + } + } + else if (xtag == DCM_MediaStorageSOPInstanceUID) // (0002,0003) + { + if (elem == NULL) + { + elem = new DcmUniqueIdentifier(tag); + metainfo->insert(elem, OFTrue); + } + if (elem->ident() == EVR_UI) + { + if ((writeMode == EWM_updateMeta) || (elem->getLength() == 0)) + { + if (dataset->search(DCM_SOPInstanceUID, stack).good()) + { + char* uid = NULL; + l_error = OFstatic_cast(DcmUniqueIdentifier *, stack.top())->getString(uid); + OFstatic_cast(DcmUniqueIdentifier *, elem)->putString(uid); + DCMDATA_DEBUG("DcmFileFormat::checkMetaHeaderValue() use SOPInstanceUID [" << uid << "] from Dataset"); + } + else if (elem->getLength() == 0) + { + char uid[128]; + dcmGenerateUniqueIdentifier(uid); // from dcuid.h + OFstatic_cast(DcmUniqueIdentifier *, elem)->putString(uid); + DCMDATA_DEBUG("DcmFileFormat::checkMetaHeaderValue() use new generated SOPInstanceUID [" << uid << "]"); + } + } + else if (DCM_dcmdataLogger.isEnabledFor(OFLogger::WARN_LOG_LEVEL)) + { + // check whether UID in meta-header is identical to the one in the dataset + if (dataset->search(DCM_SOPInstanceUID, stack).good()) + { + OFString uidDataset, uidMetaHeader; + OFstatic_cast(DcmUniqueIdentifier *, stack.top())->getOFStringArray(uidDataset); + OFstatic_cast(DcmUniqueIdentifier *, elem)->getOFStringArray(uidMetaHeader); + if (uidDataset != uidMetaHeader) + { + DCMDATA_WARN("DcmFileFormat: Value of SOPInstanceUID in MetaHeader and Dataset is different"); + DCMDATA_DEBUG("DcmFileFormat::checkMetaHeaderValue() value of MediaStorageSOPInstanceUID (MetaHeader) [" << uidMetaHeader << "]"); + DCMDATA_DEBUG("DcmFileFormat::checkMetaHeaderValue() value of SOPInstanceUID (Dataset) [" << uidDataset << "]"); + } + } + } + } + } + else if (xtag == DCM_TransferSyntaxUID) // (0002,0010) + { + if (elem == NULL) + { + elem = new DcmUniqueIdentifier(tag); + metainfo->insert(elem, OFTrue); + } + if (elem->ident() == EVR_UI) + { +#ifdef DEBUG + char * uidtmp = NULL; + OFstatic_cast(DcmUniqueIdentifier *, elem)->getString(uidtmp); + if (uidtmp != NULL) + DCMDATA_DEBUG("DcmFileFormat::checkMetaHeaderValue() found old TransferSyntaxUID [" << uidtmp << "]"); +#endif + DcmXfer dcXfer(oxfer); + const char *uid = dcXfer.getXferID(); + elem->putString(uid); + DCMDATA_DEBUG("DcmFileFormat::checkMetaHeaderValue() use new TransferSyntaxUID [" + << dcXfer.getXferName() << "] on writing following Dataset"); + } + } + else if (xtag == DCM_ImplementationClassUID) // (0002,0012) + { + if (elem == NULL) + { + elem = new DcmUniqueIdentifier(tag); + metainfo->insert(elem, OFTrue); + } + if (elem->ident() == EVR_UI) + { + const char *uid = OFFIS_IMPLEMENTATION_CLASS_UID; + OFstatic_cast(DcmUniqueIdentifier *, elem)->putString(uid); + } + + } + else if (xtag == DCM_ImplementationVersionName) // (0002,0013) + { + if (elem == NULL) + { + elem = new DcmShortString(tag); + metainfo->insert(elem, OFTrue); + } + if (elem->ident() == EVR_SH) + { + const char *uid = OFFIS_DTK_IMPLEMENTATION_VERSION_NAME; + OFstatic_cast(DcmShortString *, elem)->putString(uid); + } + + } + else if (xtag == DCM_SourceApplicationEntityTitle) // (0002,0016) + { + if (elem == NULL) + { + elem = new DcmApplicationEntity(tag); + metainfo->insert(elem, OFTrue); + } + DCMDATA_ERROR("DcmFileFormat: Don't know how to handle SourceApplicationEntityTitle"); + } + else if (xtag == DCM_PrivateInformationCreatorUID) // (0002,0100) + { + if (elem == NULL) + { + elem = new DcmUniqueIdentifier(tag); + metainfo->insert(elem, OFTrue); + } + DCMDATA_ERROR("DcmFileFormat: Don't know how to handle PrivateInformationCreatorUID"); + } + else if (xtag == DCM_PrivateInformation) // (0002,0102) + { + if (elem == NULL) + { + elem = new DcmOtherByteOtherWord(tag); + metainfo->insert(elem, OFTrue); + } + DCMDATA_WARN("DcmFileFormat: Don't know how to handle PrivateInformation"); + } else { + DCMDATA_WARN("DcmFileFormat: Don't know how to handle " << tag.getTagName()); + } + + /* if at this point elem still equals NULL, something is fishy */ + if (elem == NULL) + l_error = EC_InvalidVR; + } else { + /* (i.e. there is either no meta header information or no data set information */ + l_error = EC_IllegalCall; + } + + /* return result value */ + return l_error; +} + + +// ******************************** + + +OFCondition DcmFileFormat::validateMetaInfo(const E_TransferSyntax oxfer, + const E_FileWriteMode writeMode) + /* + * This function makes sure that all data elements of the meta header information are existent + * in metainfo and contain correct values. + * + * Parameters: + * oxfer - [in] The transfer syntax which shall be used. + * writeMode - [in] Flag indicating whether to update the file meta information or not. + */ +{ + /* initialize some variables */ + OFCondition l_error = EC_Normal; + DcmMetaInfo *metinf = getMetaInfo(); + DcmDataset *datset = getDataset(); + + /* if there is meta header information and data set information, do something */ + if (metinf != NULL && datset != NULL) + { + if (writeMode == EWM_dontUpdateMeta) + { + DCMDATA_WARN("DcmFileFormat: Meta Information Header is not updated!"); + } else { + /* start with empty file meta information */ + if (writeMode == EWM_createNewMeta) + metinf->clear(); + + /* in the following, we want to make sure all elements of the meta header */ + /* are existent in metinf and contain correct values */ + DcmStack stack; + + /* DCM_FileMetaInformationGroupLength */ + metinf->search(DCM_FileMetaInformationGroupLength, stack, ESM_fromHere, OFFalse); + checkMetaHeaderValue(metinf, datset, DCM_FileMetaInformationGroupLength, stack.top(), oxfer, writeMode); + + /* DCM_FileMetaInformationVersion */ + metinf->search(DCM_FileMetaInformationVersion, stack, ESM_fromHere, OFFalse); + checkMetaHeaderValue(metinf, datset, DCM_FileMetaInformationVersion, stack.top(), oxfer, writeMode); + + /* DCM_MediaStorageSOPClassUID */ + metinf->search(DCM_MediaStorageSOPClassUID, stack, ESM_fromHere, OFFalse); + checkMetaHeaderValue(metinf, datset, DCM_MediaStorageSOPClassUID, stack.top(), oxfer, writeMode); + + /* DCM_MediaStorageSOPInstanceUID */ + metinf->search(DCM_MediaStorageSOPInstanceUID, stack, ESM_fromHere, OFFalse); + checkMetaHeaderValue(metinf, datset, DCM_MediaStorageSOPInstanceUID, stack.top(), oxfer, writeMode); + + /* DCM_TransferSyntaxUID */ + metinf->search(DCM_TransferSyntaxUID, stack, ESM_fromHere, OFFalse); + checkMetaHeaderValue(metinf, datset, DCM_TransferSyntaxUID, stack.top(), oxfer, writeMode); + + /* DCM_ImplementationClassUID */ + metinf->search(DCM_ImplementationClassUID, stack, ESM_fromHere, OFFalse); + checkMetaHeaderValue(metinf, datset, DCM_ImplementationClassUID, stack.top(), oxfer, writeMode); + + /* DCM_ImplementationVersionName */ + metinf->search(DCM_ImplementationVersionName, stack, ESM_fromHere, OFFalse); + checkMetaHeaderValue(metinf, datset, DCM_ImplementationVersionName, stack.top(), oxfer, writeMode); + + /* dump some information if required */ + DCMDATA_DEBUG("DcmFileFormat::validateMetaInfo() found " << metinf->card() << " Elements in DcmMetaInfo 'metinf'"); + + /* calculate new GroupLength for meta header */ + if (metinf->computeGroupLengthAndPadding(EGL_withGL, EPD_noChange, + META_HEADER_DEFAULT_TRANSFERSYNTAX, EET_UndefinedLength).bad()) + { + DCMDATA_ERROR("DcmFileFormat: Group length of Meta Information Header not adapted"); + } + } + } else { + /* (i.e. there is either no meta header information or no data set information, or both are missing) */ + l_error = EC_CorruptedData; + } + + /* return result value */ + return l_error; +} + + + +// ******************************** + + +E_TransferSyntax DcmFileFormat::lookForXfer(DcmMetaInfo *metainfo) +{ + E_TransferSyntax newxfer = EXS_Unknown; + DcmStack stack; + /* check whether meta header is present (and non-empty, i.e. contains elements) */ + if (metainfo && !metainfo->isEmpty()) + { + if (metainfo->search(DCM_TransferSyntaxUID, stack).good()) + { + DcmUniqueIdentifier *xferUI = OFstatic_cast(DcmUniqueIdentifier *, stack.top()); + if (xferUI->getTag().getXTag() == DCM_TransferSyntaxUID) + { + char *xferid = NULL; + xferUI->getString(xferid); + DcmXfer localXfer(xferid); // decode to E_TransferSyntax + newxfer = localXfer.getXfer(); + DCMDATA_TRACE("DcmFileFormat::lookForXfer() TransferSyntax=\"" + << localXfer.getXferName() << "\" in MetaInfo"); + } + } else { + /* there is no transfer syntax UID element in the meta header */ + DCMDATA_DEBUG("DcmFileFormat::lookForXfer() no TransferSyntax in MetaInfo"); + } + } else { + /* no meta header present at all (or it is empty, i.e. contains no elements) */ + DCMDATA_DEBUG("DcmFileFormat::lookForXfer() no MetaInfo found"); + } + return newxfer; +} + + +// ******************************** + + +Uint32 DcmFileFormat::calcElementLength(const E_TransferSyntax xfer, + const E_EncodingType enctype) +{ + return getMetaInfo()->calcElementLength(xfer, enctype) + + getDataset()->calcElementLength(xfer, enctype); +} + + +// ******************************** + + +OFBool DcmFileFormat::canWriteXfer(const E_TransferSyntax newXfer, + const E_TransferSyntax oldXfer) +{ + DcmDataset *dataset = getDataset(); + + if (dataset) + return dataset->canWriteXfer(newXfer, oldXfer); + else + return OFFalse; +} + + +// ******************************** + + +OFCondition DcmFileFormat::read(DcmInputStream &inStream, + const E_TransferSyntax xfer, + const E_GrpLenEncoding glenc, + const Uint32 maxReadLength) + +{ + if (getTransferState() == ERW_notInitialized) + errorFlag = EC_IllegalCall; + else + { + errorFlag = inStream.status(); + + E_TransferSyntax newxfer = xfer; + DcmDataset *dataset = NULL; + + if (errorFlag.good() && inStream.eos()) + errorFlag = EC_EndOfStream; + else if (errorFlag.good() && getTransferState() != ERW_ready) + { + // the new data is added to the end + itemList->seek(ELP_last); + + DcmMetaInfo *metaInfo = getMetaInfo(); + if (metaInfo == NULL && getTransferState() == ERW_init) + { + metaInfo = new DcmMetaInfo(); + itemList->insert(metaInfo, ELP_first); + // remember the parent + metaInfo->setParent(this); + } + if (metaInfo && metaInfo->transferState() != ERW_ready) + { + // do read meta header not in given transfer syntax (always Little Endian Explicit) + errorFlag = metaInfo->read(inStream, EXS_Unknown, glenc, maxReadLength); + } + + // determine xfer from tag (0002,0010) in the meta header + newxfer = lookForXfer(metaInfo); + if ((FileReadMode == ERM_fileOnly) || (FileReadMode == ERM_metaOnly)) + { + // reject file if no meta header present + if (errorFlag.good() && (newxfer == EXS_Unknown)) + errorFlag = EC_FileMetaInfoHeaderMissing; + } + if (errorFlag.good() && (!metaInfo || metaInfo->transferState() == ERW_ready)) + { + dataset = getDataset(); + if (dataset == NULL && getTransferState() == ERW_init) + { + dataset = new DcmDataset(); + itemList->seek (ELP_first); + itemList->insert(dataset, ELP_next); + // remember the parent + dataset->setParent(this); + } + // check whether to read the dataset at all + if (FileReadMode != ERM_metaOnly) + { + if (dataset && dataset->transferState() != ERW_ready) + { + errorFlag = dataset->read(inStream, newxfer, glenc, maxReadLength); + } + } + } + } + if (getTransferState() == ERW_init) + setTransferState(ERW_inWork); + + if (dataset && dataset->transferState() == ERW_ready) + setTransferState(ERW_ready); + } + return errorFlag; +} // DcmFileFormat::read() + + +// ******************************** + + +OFCondition DcmFileFormat::write(DcmOutputStream &outStream, + const E_TransferSyntax oxfer, + const E_EncodingType enctype, + DcmWriteCache *wcache) +{ + return write(outStream, oxfer, enctype, wcache, EGL_recalcGL, EPD_noChange); +} + + +OFCondition DcmFileFormat::write(DcmOutputStream &outStream, + const E_TransferSyntax oxfer, + const E_EncodingType enctype, + DcmWriteCache *wcache, + const E_GrpLenEncoding glenc, + const E_PaddingEncoding padenc, + const Uint32 padlen, + const Uint32 subPadlen, + Uint32 instanceLength, + const E_FileWriteMode writeMode) + /* + * This function writes data values which are contained in this to the stream which is + * passed as first argument. With regard to the writing of information, the other parameters + * which are passed are accounted for. The function will return EC_Normal, if the information + * from all elements of this data set has been written to the buffer, and it will return some + * other (error) value if there was an error. + * + * Parameters: + * outStream - [inout] The stream that the information will be written to. + * oxfer - [in] The transfer syntax which shall be used. + * enctype - [in] Encoding type for sequences. Specifies how sequences will be handled. + * glenc - [in] Encoding type for group length. Specifies what will be done with group length tags. + * padenc - [in] Encoding type for padding. Specifies what will be done with padding tags. + * padlen - [in] The length up to which the dataset shall be padded, if padding is desired. + * subPadlen - [in] For sequences (i.e. sub elements), the length up to which item shall be padded, + * if padding is desired. + * instanceLength - [in] Number of extra bytes added to the item/dataset length used when computing the + * padding. This parameter is for instance used to pass the length of the file meta + * header from the DcmFileFormat to the DcmDataset object. + * writeMode - [in] Write file with or without meta header. Also allows for updating the information + * in the file meta information header. + */ +{ + /* if the transfer state of this is not initialized, this is an illegal call */ + if (getTransferState() == ERW_notInitialized) + errorFlag = EC_IllegalCall; + else + { + /* if this is not an illegal call, do something */ + + /* assign data set and the meta information header to local variables */ + DcmDataset *dataset = getDataset(); + DcmMetaInfo *metainfo = getMetaInfo(); + /* Determine the transfer syntax which shall be used. Either we use the one which was passed, */ + /* or (if it's an unknown transfer syntax) we use the data set's original transfer syntax. */ + E_TransferSyntax outxfer = oxfer; + if (outxfer == EXS_Unknown && dataset) + outxfer = dataset->getOriginalXfer(); + /* check if the stream reported an error so far */ + errorFlag = outStream.status(); + /* check if we can actually write data to the stream; in certain cases we cannot. */ + if (outxfer == EXS_Unknown || outxfer == EXS_BigEndianImplicit) + errorFlag = EC_IllegalCall; + else if (itemList->empty()) + errorFlag = EC_CorruptedData; + else if (errorFlag.good() && getTransferState() != ERW_ready) + { + /* in this case we can write data to the stream */ + + /* if this function was called for the first time for the dataset object, the transferState is */ + /* still set to ERW_init. In this case, we need to validate the meta header information, set the */ + /* item list pointer to the fist element and we need to set the transfer state to ERW_inWork. */ + if (getTransferState() == ERW_init) + { + validateMetaInfo(outxfer, writeMode); + itemList->seek(ELP_first); + setTransferState(ERW_inWork); + } + /* if the transfer state is set to ERW_inWork, we need to write the */ + /* information which is included in this to the buffer which was passed. */ + if (getTransferState() == ERW_inWork) + { + /* write meta header information */ + errorFlag = metainfo->write(outStream, outxfer, enctype, wcache); + /* recalculate the instance length */ + instanceLength += metainfo->calcElementLength(outxfer, enctype); + /* if everything is ok, write the data set */ + if (errorFlag.good()) + errorFlag = dataset->write(outStream, outxfer, enctype, wcache, glenc, padenc, padlen, + subPadlen, instanceLength); + /* if everything is ok, set the transfer state to ERW_ready */ + if (errorFlag.good()) + setTransferState(ERW_ready); + } + } + /* in case the transfer syntax which shall be used is indeed the */ + /* BigEndianImplicit transfer syntax dump some error information */ + if (outxfer == EXS_BigEndianImplicit) + DCMDATA_ERROR("DcmFileFormat: Illegal TransferSyntax (BigEndianImplicit) used in write method"); + } + /* return result value */ + return errorFlag; +} + + +// ******************************** + + +OFCondition DcmFileFormat::loadFile(const OFFilename &fileName, + const E_TransferSyntax readXfer, + const E_GrpLenEncoding groupLength, + const Uint32 maxReadLength, + const E_FileReadMode readMode) +{ + if (readMode == ERM_dataset) + return getDataset()->loadFile(fileName, readXfer, groupLength, maxReadLength); + + OFCondition l_error = EC_InvalidFilename; + /* check parameters first */ + if (!fileName.isEmpty()) + { + /* open file for input */ + DcmInputFileStream fileStream(fileName); + /* check stream status */ + l_error = fileStream.status(); + if (l_error.good()) + { + /* clear this object */ + l_error = clear(); + if (l_error.good()) + { + /* save old value */ + const E_FileReadMode oldMode = FileReadMode; + FileReadMode = readMode; + /* read data from file */ + transferInit(); + l_error = read(fileStream, readXfer, groupLength, maxReadLength); + transferEnd(); + /* restore old value */ + FileReadMode = oldMode; + } + } + } + return l_error; +} + + +OFCondition DcmFileFormat::saveFile(const OFFilename &fileName, + const E_TransferSyntax writeXfer, + const E_EncodingType encodingType, + const E_GrpLenEncoding groupLength, + const E_PaddingEncoding padEncoding, + const Uint32 padLength, + const Uint32 subPadLength, + const E_FileWriteMode writeMode) +{ + if (writeMode == EWM_dataset) + { + return getDataset()->saveFile(fileName, writeXfer, encodingType, groupLength, + padEncoding, padLength, subPadLength); + } + OFCondition l_error = EC_InvalidFilename; + /* check parameters first */ + if (!fileName.isEmpty()) + { + DcmWriteCache wcache; + + /* open file for output */ + DcmOutputFileStream fileStream(fileName); + + /* check stream status */ + l_error = fileStream.status(); + if (l_error.good()) + { + /* write data to file */ + transferInit(); + l_error = write(fileStream, writeXfer, encodingType, &wcache, groupLength, + padEncoding, padLength, subPadLength, 0 /*instanceLength*/, writeMode); + transferEnd(); + } + } + return l_error; +} + + +// ******************************** + + +OFCondition DcmFileFormat::insertItem(DcmItem * /*item*/, + const unsigned long /*where*/) +{ + DCMDATA_WARN("Illegal call of DcmFileFormat::insert(DcmItem *, unsigned long)"); + errorFlag = EC_IllegalCall; + return errorFlag; +} + + +// ******************************** + + +void DcmFileFormat::removeInvalidGroups() +{ + getMetaInfo()->removeInvalidGroups(); + getDataset()->removeInvalidGroups(); +} + + +// ******************************** + + +DcmItem *DcmFileFormat::remove(const unsigned long /*num*/) +{ + DCMDATA_WARN("Illegal call of DcmFileFormat::remove(unsigned long)"); + errorFlag = EC_IllegalCall; + return NULL; +} + + +// ******************************** + + +DcmItem *DcmFileFormat::remove(DcmItem* /*item*/) +{ + DCMDATA_WARN("Illegal call of DcmFileFormat::remove(DcmItem *)"); + errorFlag = EC_IllegalCall; + return NULL; +} + + +// ******************************** + + +OFCondition DcmFileFormat::clear() +{ + getMetaInfo()->clear(); + return getDataset()->clear(); +} + + +// ******************************** + + +DcmMetaInfo *DcmFileFormat::getMetaInfo() +{ + errorFlag = EC_Normal; + DcmMetaInfo *meta = NULL; + if (itemList->seek_to(0) != NULL && itemList->get()->ident() == EVR_metainfo) + meta = OFstatic_cast(DcmMetaInfo *, itemList->get()); + else + errorFlag = EC_IllegalCall; + return meta; +} + + +// ******************************** + + +DcmDataset *DcmFileFormat::getDataset() +{ + errorFlag = EC_Normal; + DcmDataset *data = NULL; + if (itemList->seek_to(1) != NULL && itemList->get()->ident() == EVR_dataset) + data = OFstatic_cast(DcmDataset *, itemList->get()); + else + errorFlag = EC_IllegalCall; + return data; +} + + +// ******************************** + + +DcmDataset *DcmFileFormat::getAndRemoveDataset() +{ + errorFlag = EC_Normal; + DcmDataset *data = NULL; + if (itemList->seek_to(1) != NULL && itemList->get()->ident() == EVR_dataset) + { + data = OFstatic_cast(DcmDataset *, itemList->remove()); + // forget about the parent + data->setParent(NULL); + DcmDataset *Dataset = new DcmDataset(); + DcmSequenceOfItems::itemList->insert(Dataset, ELP_last); + // remember the parent + Dataset->setParent(this); + } + else + errorFlag = EC_IllegalCall; + return data; +} + + +// ******************************** + + +OFCondition DcmFileFormat::convertCharacterSet(const OFString &fromCharset, + const OFString &toCharset, + const OFBool transliterate, + const OFBool discardIllegal) +{ + // convert the dataset associated with this object + return getDataset()->convertCharacterSet(fromCharset, toCharset, transliterate, discardIllegal); +} + + +OFCondition DcmFileFormat::convertCharacterSet(const OFString &toCharset, + const OFBool transliterate, + const OFBool discardIllegal) +{ + OFString sopClass; + OFBool ignoreCharset = OFFalse; + // check whether this dataset belongs to a DICOMDIR, + // because the Basic Directory IOD has no SOP Common Module + if (getMetaInfo()->findAndGetOFString(DCM_MediaStorageSOPClassUID, sopClass).good() && + (sopClass == UID_MediaStorageDirectoryStorage)) + { + DCMDATA_DEBUG("DcmFileFormat::convertCharacterSet() according to the value of MediaStorageSOPClassUID " + << DCM_MediaStorageSOPClassUID << " this is a DICOMDIR, which has no SOP Common Module"); + ignoreCharset = OFTrue; + } + // usually, we check for Specific Character Set (0008,0005) element in the dataset + return getDataset()->convertCharacterSet(toCharset, transliterate, ignoreCharset, discardIllegal); +} + + +OFCondition DcmFileFormat::convertCharacterSet(DcmSpecificCharacterSet &converter) +{ + // convert the dataset associated with this object + return getDataset()->convertCharacterSet(converter); +} + + +OFCondition DcmFileFormat::convertToUTF8() +{ + // the DICOM defined term "ISO_IR 192" is used for "UTF-8" + return convertCharacterSet("ISO_IR 192", OFFalse /*transliterate*/); +} diff --git a/dcmdata/libsrc/dcfilter.cc b/dcmdata/libsrc/dcfilter.cc new file mode 100644 index 00000000..001a1019 --- /dev/null +++ b/dcmdata/libsrc/dcfilter.cc @@ -0,0 +1,94 @@ +/* + * + * Copyright (C) 2012, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Jan Schlamelcher + * + * Purpose: Implementation of DcmAttributeFilter + * + */ + + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/dcmdata/dcfilter.h" + + +class DcmAttributeFilter::SingleValueFilter : public FilterInterface +{ +public: + SingleValueFilter( const OFString& value ) + : m_Value( value ) + { + + } + + virtual OFBool apply( const OFString& value ) + { + return m_Value == value; + } + +private: + const OFString m_Value; +}; + +DcmAttributeFilter::DcmAttributeFilter() +: m_Tag(), m_pFilter( NULL ) +{ + +} + +DcmAttributeFilter::DcmAttributeFilter( const DcmTagKey& tag, const OFString& value ) +: m_Tag( tag ), m_pFilter( new SingleValueFilter( value ) ) +{ + +} + +DcmAttributeFilter::DcmAttributeFilter( const DcmTagKey& tag, const char* const value ) +: m_Tag( tag ), m_pFilter( new SingleValueFilter( value ) ) +{ + +} + +DcmAttributeFilter::~DcmAttributeFilter() +{ + delete m_pFilter; +} + +OFBool DcmAttributeFilter::apply( DcmItem& item ) const +{ + if( m_pFilter ) + { + OFString value; + return item.findAndGetOFStringArray( m_Tag, value ).good() + && m_pFilter->apply( value ); + } + else return true; +} + +OFBool DcmAttributeFilter::operator()( DcmItem& item ) const +{ + return apply( item ); +} + +OFBool DcmAttributeFilter::apply( DcmFileFormat& dcmfile ) const +{ + DcmDataset* const dataset = dcmfile.getDataset(); + return dataset && apply( *dataset ); +} + +OFBool DcmAttributeFilter::operator()( DcmFileFormat& dcmfile ) const +{ + return apply( dcmfile ); +} diff --git a/dcmdata/libsrc/dchashdi.cc b/dcmdata/libsrc/dchashdi.cc new file mode 100644 index 00000000..010b9f62 --- /dev/null +++ b/dcmdata/libsrc/dchashdi.cc @@ -0,0 +1,410 @@ +/* + * + * Copyright (C) 1997-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Andrew Hewett + * + * Purpose: Hash table interface for DICOM data dictionary + * + */ + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ +#include "dcmtk/dcmdata/dchashdi.h" +#include "dcmtk/dcmdata/dcdicent.h" +#include "dcmtk/dcmdata/dctypes.h" + +#define INCLUDE_CSTDIO +#define INCLUDE_CASSERT +#include "dcmtk/ofstd/ofstdinc.h" + +/* +** DcmDictEntryList +*/ + +DcmDictEntryList::~DcmDictEntryList() +{ + clear(); +} + +void +DcmDictEntryList::clear() +{ + while (!empty()) { + delete list_.front(); + list_.pop_front(); + } +} + +DcmDictEntry* +DcmDictEntryList::insertAndReplace(DcmDictEntry* entry) +{ + if (empty()) { + list_.push_front(entry); + } else { + DcmDictEntryListIterator iter(begin()); + DcmDictEntryListIterator last(end()); + Uint32 eHash = entry->hash(); + Uint32 iterHash = 0; + // insert smallest first + for (iter = begin(); iter != last; ++iter) { + iterHash = (*iter)->hash(); + if (eHash == iterHash) + { + if (entry->privateCreatorMatch(**iter)) + { + // entry is already there so replace it + DcmDictEntry* oldEntry = *iter; + *iter = entry; + return oldEntry; + } + else + { + // insert before listEntry + insert(iter, entry); + return NULL; + } + } + else if (eHash < iterHash) + { + // insert before listEntry + insert(iter, entry); + return NULL; + } + } + // add to end + push_back(entry); + } + return NULL; +} + + +DcmDictEntry *DcmDictEntryList::find(const DcmTagKey& key, const char *privCreator) +{ + if (!empty()) { + DcmDictEntryListIterator iter; + DcmDictEntryListIterator last = end(); + Uint32 kHash = key.hash(); + Uint32 iterHash = 0; + for (iter = begin(); iter != last; ++iter) { + iterHash = (*iter)->hash(); + if ((iterHash == kHash) && (*iter)->privateCreatorMatch(privCreator)) + { + return *iter; + } else if (iterHash > kHash) { + return NULL; // not there + } + } + } + return NULL; +} + +unsigned int +DcmDictEntryList::size() const +{ + return OFstatic_cast(unsigned int, list_.size()); +} + +OFBool +DcmDictEntryList::empty() const +{ + return list_.empty(); +} + +DcmDictEntryListIterator +DcmDictEntryList::begin() +{ + return list_.begin(); +} + +DcmDictEntryListIterator +DcmDictEntryList::end() +{ + return list_.end(); +} + +DcmDictEntryListConstIterator +DcmDictEntryList::begin() const +{ + return list_.begin(); +} + +DcmDictEntryListConstIterator +DcmDictEntryList::end() const +{ + return list_.end(); +} + +DcmDictEntryListIterator +DcmDictEntryList::insert(DcmDictEntryListIterator position, DcmDictEntry *entry) +{ + return list_.insert(position, entry); +} + +void +DcmDictEntryList::remove(DcmDictEntry *entry) +{ + list_.remove(entry); +} + +void +DcmDictEntryList::push_back(DcmDictEntry *entry) +{ + list_.push_back(entry); +} + +/* +** DcmHashDictIterator +*/ + +void +DcmHashDictIterator::init(const DcmHashDict* d, OFBool atEnd) +{ + dict = d; + hindex = 0; + iterating = OFFalse; + if (dict != NULL) { + if (atEnd || dict->size() == 0) { + hindex = dict->highestBucket; + if (dict->size() > 0) { + iter = dict->hashTab[hindex]->end(); + iterating = OFTrue; + } + } else { + hindex = dict->lowestBucket; + iter = dict->hashTab[hindex]->begin(); + iterating = OFTrue; + } + } +} + +void +DcmHashDictIterator::stepUp() +{ + assert(dict != NULL); + + while (hindex <= dict->highestBucket) { + DcmDictEntryList* bucket = dict->hashTab[hindex]; + if (bucket == NULL) { + if (hindex == dict->highestBucket) + return; /* We reached the end of the dictionary */ + hindex++; // move on to next bucket + iterating = OFFalse; + } else { + if (!iterating) { + iter = bucket->begin(); + iterating = OFTrue; + if (iter != bucket->end()) { + return; /* we have found the next one */ + } + } + if (iter == bucket->end()) { + if (hindex == dict->highestBucket) + return; /* We reached the end of the dictionary */ + iterating = OFFalse; + hindex++; + } else { + ++iter; + if (iter != bucket->end()) { + return; /* we have found the next one */ + } + } + } + } +} + + +/* +** DcmHashDict +*/ + +// This number shouldn't have any small factors, so that +// DcmHashDict::hash() produces fewer collisions. +const int DcmHashDict::hashTabLength = 2011; + +void +DcmHashDict::_init() +{ + hashTab = new DcmDictEntryList*[hashTabLength]; + assert(hashTab != NULL); + for (int i=0; ihash(); + + // If there is a private creator, hash that in, too + for (; privCreator != NULL && *privCreator != '\0'; privCreator++) { + h ^= *privCreator << ((++i & 3) << 3); + } + + // This 'hash function' only works well if hashTabLength is prime + int res = h % hashTabLength; + + assert((res >= 0) && (res < hashTabLength)); + + return res; +} + +DcmDictEntry* +DcmHashDict::insertInList(DcmDictEntryList& l, DcmDictEntry* entry) +{ + return l.insertAndReplace(entry); +} + +void +DcmHashDict::put(DcmDictEntry* entry) +{ + int idx = hash(entry, entry->getPrivateCreator()); + + DcmDictEntryList* bucket = hashTab[idx]; + // if there is no bucket then create one + if (bucket == NULL) { + bucket = new DcmDictEntryList; + assert(bucket != NULL); + hashTab[idx] = bucket; + } + + DcmDictEntry* old = insertInList(*bucket, entry); + if (old != NULL) { + /* an old entry has been replaced */ +#ifdef PRINT_REPLACED_DICTIONARY_ENTRIES + DCMDATA_WARN("replacing " << *old); +#endif + delete old; + } else { + entryCount++; + } + + lowestBucket = (lowestBucketidx)?(highestBucket):(idx); +} + +DcmDictEntry *DcmHashDict::findInList(DcmDictEntryList& l, const DcmTagKey& key, const char *privCreator) const +{ + return l.find(key, privCreator); +} + +const DcmDictEntry* +DcmHashDict::get(const DcmTagKey& key, const char *privCreator) const +{ + const DcmDictEntry* entry = NULL; + + // first we look for an entry that exactly matches the given tag key + Uint32 idx = hash(&key, privCreator); + DcmDictEntryList* bucket = hashTab[idx]; + if (bucket) entry = findInList(*bucket, key, privCreator); + + if ((entry == NULL) && privCreator) + { + // As a second guess, we look for a private tag with flexible element number. + DcmTagKey tk(key.getGroup(), OFstatic_cast(unsigned short, key.getElement() & 0xff)); + idx = hash(&tk, privCreator); + bucket = hashTab[idx]; + if (bucket) entry = findInList(*bucket, tk, privCreator); + } + + return entry; +} + +DcmDictEntry* +DcmHashDict::removeInList(DcmDictEntryList& l, const DcmTagKey& key, const char *privCreator) +{ + DcmDictEntry* entry = findInList(l, key, privCreator); + l.remove(entry); // does not delete entry + return entry; +} + +void +DcmHashDict::del(const DcmTagKey& key, const char *privCreator) +{ + Uint32 idx = hash(&key, privCreator); + + DcmDictEntryList* bucket = hashTab[idx]; + if (bucket != NULL) { + DcmDictEntry* entry = removeInList(*bucket, key, privCreator); + delete entry; + } +} + +STD_NAMESPACE ostream& +DcmHashDict::loadSummary(STD_NAMESPACE ostream& out) +{ + out << "DcmHashDict: size=" << hashTabLength << + ", total entries=" << size() << OFendl; + DcmDictEntryList* bucket = NULL; + int largestBucket = 0; + for (int i=0; isize()) > largestBucket) { + largestBucket = bucket->size(); + } + } + } + + for (int j=0; jsize() << " entries" << OFendl; + } + } + out << "Bucket Sizes" << OFendl; + int n, x, k, l_size; + for (x=0; x<=largestBucket; x++) { + n = 0; + for (k=0; ksize(); + } + if (l_size == x) { + n++; + } + } + out << " entries{" << x << "}: " << n << " buckets" << OFendl; + } + + return out; +} diff --git a/dcmdata/libsrc/dcistrma.cc b/dcmdata/libsrc/dcistrma.cc new file mode 100644 index 00000000..b61a79b7 --- /dev/null +++ b/dcmdata/libsrc/dcistrma.cc @@ -0,0 +1,125 @@ +/* + * + * Copyright (C) 1994-2010, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Marco Eichelberg + * + * Purpose: base classes for input streams + * + */ + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmdata/dcistrma.h" +#include "dcmtk/dcmdata/dcistrmz.h" /* for DcmZLibInputFilter */ +#include "dcmtk/dcmdata/dcerror.h" /* for EC_IllegalCall */ + +DcmInputStream::DcmInputStream(DcmProducer *initial) +: current_(initial) +, compressionFilter_(NULL) +, tell_(0) +, mark_(0) +{ +} + +DcmInputStream::~DcmInputStream() +{ + // we cannot access the stream anymore at this point because the + // producer has most probably already been deleted. + delete compressionFilter_; +} + +OFBool DcmInputStream::good() const +{ + return current_->good(); +} + +OFCondition DcmInputStream::status() const +{ + return current_->status(); +} + +OFBool DcmInputStream::eos() +{ + return current_->eos(); +} + +offile_off_t DcmInputStream::avail() +{ + return current_->avail(); +} + +offile_off_t DcmInputStream::read(void *buf, offile_off_t buflen) +{ + offile_off_t result = current_->read(buf, buflen); + tell_ += result; + return result; +} + +offile_off_t DcmInputStream::skip(offile_off_t skiplen) +{ + offile_off_t result = current_->skip(skiplen); + tell_ += result; + return result; +} + +offile_off_t DcmInputStream::tell() const +{ + return tell_; +} + +void DcmInputStream::mark() +{ + mark_ = tell_; +} + +void DcmInputStream::putback() +{ + current_->putback(tell_ - mark_); + tell_ = mark_; +} + +const DcmProducer *DcmInputStream::currentProducer() const +{ + return current_; +} + +OFCondition DcmInputStream::installCompressionFilter(E_StreamCompression filterType) +{ + OFCondition result = EC_Normal; + if (compressionFilter_) result = EC_DoubleCompressionFilters; + else + { + switch (filterType) + { +#ifdef WITH_ZLIB + case ESC_zlib: + compressionFilter_ = new DcmZLibInputFilter(); + if (compressionFilter_) + { + compressionFilter_->append(*current_); + // feed the compression engine with data from the producer + compressionFilter_->skip(0); + current_ = compressionFilter_; + } else result = EC_MemoryExhausted; + break; +#endif + case ESC_none: + case ESC_unsupported: + result = EC_UnsupportedEncoding; + break; + } + } + + return result; +} diff --git a/dcmdata/libsrc/dcistrmb.cc b/dcmdata/libsrc/dcistrmb.cc new file mode 100644 index 00000000..2132a604 --- /dev/null +++ b/dcmdata/libsrc/dcistrmb.cc @@ -0,0 +1,326 @@ +/* + * + * Copyright (C) 2002-2010, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Marco Eichelberg + * + * Purpose: DcmInputBufferStream and related classes, + * implements input to blocks of memory as needed in the dcmnet module. + * + */ + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmdata/dcistrmb.h" +#include "dcmtk/dcmdata/dcerror.h" + +#define DCMBUFFERPRODUCER_BUFSIZE 1024 + +DcmBufferProducer::DcmBufferProducer() +: DcmProducer() +, buffer_(NULL) +, backup_(new unsigned char[DCMBUFFERPRODUCER_BUFSIZE]) +, bufSize_(0) +, bufIndex_(0) +, backupIndex_(DCMBUFFERPRODUCER_BUFSIZE) +, backupStart_(DCMBUFFERPRODUCER_BUFSIZE) +, status_(EC_Normal) +, eosflag_(OFFalse) +{ + if (!backup_) status_ = EC_MemoryExhausted; +} + + +DcmBufferProducer::~DcmBufferProducer() +{ + delete[] backup_; +} + + +OFBool DcmBufferProducer::good() const +{ + return status_.good(); +} + +OFCondition DcmBufferProducer::status() const +{ + return status_; +} + +OFBool DcmBufferProducer::eos() +{ + // end of stream is true if the user has called setEos() before + // and there is no more data available in the current buffer. + // We also flag end of stream if the status is bad. + return (eosflag_ && (avail() == 0)) || (!status_.good()); +} + + +offile_off_t DcmBufferProducer::avail() +{ + if (status_.good()) + { + // in the backup buffer, we have (DCMBUFFERPRODUCER_BUFSIZE - backupIndex_) + // bytes available. In the user buffer, we have (bufSize_ - bufIndex_). + return DCMBUFFERPRODUCER_BUFSIZE + bufSize_ - bufIndex_ - backupIndex_; + } + else return 0; +} + + +offile_off_t DcmBufferProducer::read(void *buf, offile_off_t buflen) +{ + offile_off_t result = 0; + if (status_.good() && buflen && buf) + { + unsigned char *target = OFstatic_cast(unsigned char *, buf); + if (backupIndex_ < DCMBUFFERPRODUCER_BUFSIZE) + { + // we have data in the backup buffer, read first + result = DCMBUFFERPRODUCER_BUFSIZE - backupIndex_; + if (result > buflen) result = buflen; + memcpy(target, backup_ + backupIndex_, OFstatic_cast(size_t, result)); + backupIndex_ += result; + target += result; + buflen -= result; + } + + if (buflen && bufSize_) + { + // read data from user buffer + offile_off_t numbytes = bufSize_ - bufIndex_; + if (numbytes > buflen) numbytes = buflen; + memcpy(target, buffer_ + bufIndex_, OFstatic_cast(size_t, numbytes)); + bufIndex_ += numbytes; + result += numbytes; + } + } + return result; +} + + +offile_off_t DcmBufferProducer::skip(offile_off_t skiplen) +{ + offile_off_t result = 0; + if (status_.good() && skiplen) + { + if (backupIndex_ < DCMBUFFERPRODUCER_BUFSIZE) + { + // we have data in the backup buffer, skip first + result = DCMBUFFERPRODUCER_BUFSIZE - backupIndex_; + if (result > skiplen) result = skiplen; + backupIndex_ += result; + skiplen -= result; + } + + if (skiplen && bufSize_) + { + // skip data from user buffer + offile_off_t skipbytes = bufSize_ - bufIndex_; + if (skipbytes > skiplen) skipbytes = skiplen; + bufIndex_ += skipbytes; + result += skipbytes; + } + } + return result; +} + +void DcmBufferProducer::putback(offile_off_t num) +{ + if (status_.good() && num) + { + if (bufSize_ && bufIndex_) + { + // since bufIndex_ > 0, data has already been read from the user buffer. + // This means we should putback in the user buffer first, and only + // if this is not sufficient we also touch the backup buffer. + if (num > bufIndex_) + { + num -= bufIndex_; + bufIndex_ = 0; + } + else + { + bufIndex_ -= num; + num = 0; + } + } + + if (num && (backupIndex_ > backupStart_)) + { + // there is still a number of bytes to putback, and we have data in the + // backup buffer, so we can actually putback something there. + // This will cause the next read operation to read from the backup + // buffer first and only then access the user buffer. + if (num > (backupIndex_ - backupStart_)) + { + num -= backupIndex_ - backupStart_; + backupIndex_ = backupStart_; + } + else + { + backupIndex_ -= num; + num = 0; + } + } + + if (num) + { + // we didn't manage to execute the putback request because there was + // not enough data available in both buffers. Producer failure. + status_ = EC_PutbackFailed; + } + } +} + +void DcmBufferProducer::setBuffer(const void *buf, offile_off_t buflen) +{ + if (status_.good()) + { + if (buffer_ || eosflag_) + { + // error: attempt to set new buffer without calling releaseBuffer before + // or after calling setEos. + status_ = EC_IllegalCall; + } + else if (buf && buflen) + { + buffer_ = OFstatic_cast(unsigned char *, OFconst_cast(void *, buf)); + bufSize_ = buflen; + bufIndex_ = 0; + } + } +} + +void DcmBufferProducer::releaseBuffer() +{ + // releaseBuffer() might be called multiple times, so buffer_ could already be NULL. + if (status_.good() && buffer_) + { + // compute the least number of bytes that we have to store in the backup buffer + offile_off_t numBytes = bufSize_ - bufIndex_; + + if (numBytes > backupIndex_) + { + // number of bytes is larger than free space in backup buffer; fail. + status_ = EC_IllegalCall; + } + else + { + // if number of bytes is smaller than free space in backup buffer, make as large as possible + if (numBytes < backupIndex_) + { + numBytes = (backupIndex_ < bufSize_) ? backupIndex_ : bufSize_; + } + + // if number of bytes is smaller than backup buffer, move old + // data in backup buffer to keep older data available for putback operations + if (numBytes < DCMBUFFERPRODUCER_BUFSIZE) + { + // move (DCMBUFFERPRODUCER_BUFSIZE - numBytes) bytes from end of backup buffer + // to start of backup buffer. Everything else will be overwritten from the + // user buffer. + memmove(backup_, backup_ + numBytes, OFstatic_cast(size_t, DCMBUFFERPRODUCER_BUFSIZE - numBytes)); + + // adjust backupStart_ + if (backupStart_ < numBytes) backupStart_ = 0; else backupStart_ -= numBytes; + } + else + { + // the backup buffer will be filled completely from the user buffer + backupStart_ = 0; + } + + // copy (numBytes) bytes from the end of the user buffer to the end of the backup buffer + memcpy(backup_ + DCMBUFFERPRODUCER_BUFSIZE - numBytes, buffer_ + bufSize_ - numBytes, OFstatic_cast(size_t, numBytes)); + + // adjust backupIndex_ + if (backupIndex_ == DCMBUFFERPRODUCER_BUFSIZE) + { + // there was no unread data in the backup buffer before. + // backupIndex_ only depends on the number of unread bytes in the user buffer. + // we know that (bufSize_ - bufIndex_ < DCMBUFFERPRODUCER_BUFSIZE) because this was tested before. + backupIndex_ = DCMBUFFERPRODUCER_BUFSIZE + bufIndex_ - bufSize_; + } + else + { + // there was unread data in the backup buffer before. + // This implies that all of the user buffer is unread and the complete user + // buffer fits into the free space in the backup buffer, because otherwise + // we would not have got this far. + // Adjust backupIndex_ by the number of bytes we have moved the content of the backup buffer. + backupIndex_ -= numBytes; + } + + // release user buffer + buffer_ = NULL; + bufSize_ = 0; + bufIndex_ = 0; + } + } + + // the number of bytes that can be putback after this operation depends + // on the size of the backup buffer and on the number of unread bytes + // in both buffers at the time of the releaseBuffer() operation. + // If the user only calls releaseBuffer() when most data has been read + // from the buffer, we should be able to putback almost 1K. +} + +void DcmBufferProducer::setEos() +{ + eosflag_ = OFTrue; +} + +/* ======================================================================= */ + +DcmInputBufferStream::DcmInputBufferStream() +: DcmInputStream(&producer_) // safe because DcmInputStream only stores pointer +, producer_() +{ +} + +DcmInputBufferStream::~DcmInputBufferStream() +{ +#ifdef DEBUG + if ((!eos()) && (avail() > 0)) + { + DCMDATA_WARN("closing unflushed DcmInputBufferStream, loss of data!"); + } +#endif +} + +DcmInputStreamFactory *DcmInputBufferStream::newFactory() const +{ + // we don't support delayed loading from buffer streams + return NULL; +} + +void DcmInputBufferStream::setBuffer(const void *buf, offile_off_t buflen) +{ + producer_.setBuffer(buf, buflen); + + // if there is a compression filter, the following call will + // cause it to feed the compression engine with data from the + // new buffer. + skip(0); +} + +void DcmInputBufferStream::releaseBuffer() +{ + producer_.releaseBuffer(); +} + +void DcmInputBufferStream::setEos() +{ + producer_.setEos(); +} diff --git a/dcmdata/libsrc/dcistrmf.cc b/dcmdata/libsrc/dcistrmf.cc new file mode 100644 index 00000000..61dba66b --- /dev/null +++ b/dcmdata/libsrc/dcistrmf.cc @@ -0,0 +1,259 @@ +/* + * + * Copyright (C) 2002-2012, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Marco Eichelberg + * + * Purpose: DcmInputFileStream and related classes, + * implements streamed input from files. + * + */ + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmdata/dcistrmf.h" +#include "dcmtk/dcmdata/dcerror.h" + +#define INCLUDE_CSTDIO +#define INCLUDE_CERRNO +#include "dcmtk/ofstd/ofstdinc.h" + + +DcmFileProducer::DcmFileProducer(const OFFilename &filename, offile_off_t offset) +: DcmProducer() +, file_() +, status_(EC_Normal) +, size_(0) +{ + if (file_.fopen(filename, "rb")) + { + // Get number of bytes in file + file_.fseek(0L, SEEK_END); + size_ = file_.ftell(); + if (0 != file_.fseek(offset, SEEK_SET)) + { + OFString s("(unknown error code)"); + file_.getLastErrorString(s); + status_ = makeOFCondition(OFM_dcmdata, 18, OF_error, s.c_str()); + } + } + else + { + OFString s("(unknown error code)"); + file_.getLastErrorString(s); + status_ = makeOFCondition(OFM_dcmdata, 18, OF_error, s.c_str()); + } +} + +DcmFileProducer::~DcmFileProducer() +{ +} + +OFBool DcmFileProducer::good() const +{ + return status_.good(); +} + +OFCondition DcmFileProducer::status() const +{ + return status_; +} + +OFBool DcmFileProducer::eos() +{ + if (file_.open()) + { + return (file_.eof() || (size_ == file_.ftell())); + } + else return OFTrue; +} + +offile_off_t DcmFileProducer::avail() +{ + if (file_.open()) return size_ - file_.ftell(); else return 0; +} + +offile_off_t DcmFileProducer::read(void *buf, offile_off_t buflen) +{ + offile_off_t result = 0; + if (status_.good() && file_.open() && buf && buflen) + { + result = file_.fread(buf, 1, OFstatic_cast(size_t, buflen)); + } + return result; +} + +offile_off_t DcmFileProducer::skip(offile_off_t skiplen) +{ + offile_off_t result = 0; + if (status_.good() && file_.open() && skiplen) + { + offile_off_t pos = file_.ftell(); + result = (size_ - pos < skiplen) ? (size_ - pos) : skiplen; + if (file_.fseek(result, SEEK_CUR)) + { + OFString s("(unknown error code)"); + file_.getLastErrorString(s); + status_ = makeOFCondition(OFM_dcmdata, 18, OF_error, s.c_str()); + } + } + return result; +} + +void DcmFileProducer::putback(offile_off_t num) +{ + if (status_.good() && file_.open() && num) + { + offile_off_t pos = file_.ftell(); + if (num <= pos) + { + if (file_.fseek(-num, SEEK_CUR)) + { + OFString s("(unknown error code)"); + file_.getLastErrorString(s); + status_ = makeOFCondition(OFM_dcmdata, 18, OF_error, s.c_str()); + } + } + else status_ = EC_PutbackFailed; // tried to putback before start of file + } +} + + +/* ======================================================================= */ + +DcmInputFileStreamFactory::DcmInputFileStreamFactory(const OFFilename &filename, offile_off_t offset) +: DcmInputStreamFactory() +, filename_(filename) +, offset_(offset) +{ +} + +DcmInputFileStreamFactory::DcmInputFileStreamFactory(const DcmInputFileStreamFactory& arg) +: DcmInputStreamFactory(arg) +, filename_(arg.filename_) +, offset_(arg.offset_) +{ +} + +DcmInputFileStreamFactory::~DcmInputFileStreamFactory() +{ +} + +DcmInputStream *DcmInputFileStreamFactory::create() const +{ + return new DcmInputFileStream(filename_, offset_); +} + +/* ======================================================================= */ + +DcmInputFileStream::DcmInputFileStream(const OFFilename &filename, offile_off_t offset) +: DcmInputStream(&producer_) // safe because DcmInputStream only stores pointer +, producer_(filename, offset) +, filename_(filename) +{ +} + +DcmInputFileStream::~DcmInputFileStream() +{ +} + +DcmInputStreamFactory *DcmInputFileStream::newFactory() const +{ + DcmInputStreamFactory *result = NULL; + if (currentProducer() == &producer_) + { + // no filter installed, can create factory object + result = new DcmInputFileStreamFactory(filename_, tell()); + } + return result; +} + +/* ======================================================================= */ + +DcmInputStream *DcmTempFileHandler::create() const +{ + return new DcmInputFileStream(filename_, 0); +} + +DcmTempFileHandler::DcmTempFileHandler(const OFFilename &filename) +#ifdef WITH_THREADS +: refCount_(1), mutex_(), filename_(filename) +#else +: refCount_(1), filename_(filename) +#endif +{ +} + +DcmTempFileHandler::~DcmTempFileHandler() +{ + OFStandard::deleteFile(filename_); +} + +DcmTempFileHandler *DcmTempFileHandler::newInstance(const OFFilename &filename) +{ + return new DcmTempFileHandler(filename); +} + +void DcmTempFileHandler::increaseRefCount() +{ +#ifdef WITH_THREADS + mutex_.lock(); +#endif + ++refCount_; +#ifdef WITH_THREADS + mutex_.unlock(); +#endif +} + +void DcmTempFileHandler::decreaseRefCount() +{ +#ifdef WITH_THREADS + mutex_.lock(); +#endif + size_t result = --refCount_; +#ifdef WITH_THREADS + mutex_.unlock(); +#endif + if (result == 0) delete this; +} + +/* ======================================================================= */ + +DcmInputTempFileStreamFactory::DcmInputTempFileStreamFactory(DcmTempFileHandler *handler) +: DcmInputStreamFactory() +, fileHandler_(handler) +{ + fileHandler_->increaseRefCount(); +} + +DcmInputTempFileStreamFactory::DcmInputTempFileStreamFactory(const DcmInputTempFileStreamFactory &arg) +: DcmInputStreamFactory(arg) +, fileHandler_(arg.fileHandler_) +{ + fileHandler_->increaseRefCount(); +} + +DcmInputTempFileStreamFactory::~DcmInputTempFileStreamFactory() +{ + fileHandler_->decreaseRefCount(); +} + +DcmInputStream *DcmInputTempFileStreamFactory::create() const +{ + return fileHandler_->create(); +} + +DcmInputStreamFactory *DcmInputTempFileStreamFactory::clone() const +{ + return new DcmInputTempFileStreamFactory(*this); +} diff --git a/dcmdata/libsrc/dcistrmz.cc b/dcmdata/libsrc/dcistrmz.cc new file mode 100644 index 00000000..0a6a6fd9 --- /dev/null +++ b/dcmdata/libsrc/dcistrmz.cc @@ -0,0 +1,432 @@ +/* + * + * Copyright (C) 2002-2010, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Marco Eichelberg + * + * Purpose: zlib compression filter for input streams + * + */ + +#include "dcmtk/config/osconfig.h" + +#ifdef WITH_ZLIB + +#include "dcmtk/dcmdata/dcistrmz.h" +#include "dcmtk/dcmdata/dcerror.h" + +#define DCMZLIBINPUTFILTER_BUFSIZE 4096 +#define DCMZLIBINPUTFILTER_PUTBACKSIZE 1024 + +OFGlobal dcmZlibExpectRFC1950Encoding(OFFalse); + +// helper methods to fix old-style casts warnings +BEGIN_EXTERN_C +static int OFinflateInit(z_stream* const stream) +{ + return inflateInit(stream); +} + +static int OFinflateInit2(z_stream* const stream) +{ + return inflateInit2(stream, -MAX_WBITS); +} +END_EXTERN_C + +DcmZLibInputFilter::DcmZLibInputFilter() +: DcmInputFilter() +, current_(NULL) +, zstream_(new z_stream) +, status_(EC_MemoryExhausted) +, eos_(OFFalse) +, inputBuf_(new unsigned char[DCMZLIBINPUTFILTER_BUFSIZE]) +, inputBufStart_(0) +, inputBufCount_(0) +, outputBuf_(new unsigned char[DCMZLIBINPUTFILTER_BUFSIZE]) +, outputBufStart_(0) +, outputBufCount_(0) +, outputBufPutback_(0) +, padded_(OFFalse) +{ + if (zstream_ && inputBuf_ && outputBuf_) + { + zstream_->zalloc = Z_NULL; + zstream_->zfree = Z_NULL; + zstream_->opaque = Z_NULL; + zstream_->next_in = Z_NULL; + zstream_->avail_in = 0; + + if (dcmZlibExpectRFC1950Encoding.get()) + { + /* expect non-standard bitstream *with* zlib header + * This is easy because it is the normal zlib format anyway. + */ + if (Z_OK == OFinflateInit(zstream_)) + status_ = EC_Normal; + else + { + OFString etext = "ZLib Error: "; + if (zstream_->msg) etext += zstream_->msg; + status_ = makeOFCondition(OFM_dcmdata, 16, OF_error, etext.c_str()); + } + } + else + { + /* windowBits is passed < 0 to tell that there is no zlib header. + * Note that in this case inflate *requires* an extra "dummy" byte + * after the compressed stream in order to complete decompression and + * return Z_STREAM_END. + */ + if (Z_OK == OFinflateInit2(zstream_)) + status_ = EC_Normal; + else + { + OFString etext = "ZLib Error: "; + if (zstream_->msg) etext += zstream_->msg; + status_ = makeOFCondition(OFM_dcmdata, 16, OF_error, etext.c_str()); + } + } + } +} + +DcmZLibInputFilter::~DcmZLibInputFilter() +{ + if (zstream_) + { + inflateEnd(zstream_); // discards any unprocessed input and does not flush any pending output + delete zstream_; + } + delete[] inputBuf_; + delete[] outputBuf_; +} + +OFBool DcmZLibInputFilter::good() const +{ + return status_.good(); +} + +OFCondition DcmZLibInputFilter::status() const +{ + return status_; +} + +OFBool DcmZLibInputFilter::eos() +{ + if (status_.bad() || (current_ == NULL)) return OFTrue; + + // there may be trailing garbage after the compressed stream. + // we report eos if the decompressor has reported Z_STREAM_END + // and the output buffer is empty. + return (outputBufCount_ == 0) && eos_; +} + +offile_off_t DcmZLibInputFilter::avail() +{ + if (status_.good()) return outputBufCount_; else return 0; +} + +offile_off_t DcmZLibInputFilter::read(void *buf, offile_off_t buflen) +{ + if (status_.bad() || (current_ == NULL) || (buf == NULL)) return 0; + unsigned char *target = OFstatic_cast(unsigned char *, buf); + offile_off_t offset = 0; + offile_off_t availBytes = 0; + offile_off_t result = 0; + do + { + // copy bytes from output buffer to user provided block of data + if (outputBufCount_) + { + // determine next block of data in output buffer + offset = outputBufStart_ + outputBufPutback_; + if (offset >= DCMZLIBINPUTFILTER_BUFSIZE) offset -= DCMZLIBINPUTFILTER_BUFSIZE; + + availBytes = outputBufCount_; + if (offset + availBytes > DCMZLIBINPUTFILTER_BUFSIZE) availBytes = DCMZLIBINPUTFILTER_BUFSIZE - offset; + if (availBytes > buflen) availBytes = buflen; + + if (availBytes) memcpy(target, outputBuf_ + offset, OFstatic_cast(size_t, availBytes)); + target += availBytes; + result += availBytes; + buflen -= availBytes; + + // adjust pointers + outputBufPutback_ += availBytes; + outputBufCount_ -= availBytes; + if (outputBufPutback_ > DCMZLIBINPUTFILTER_PUTBACKSIZE) + { + outputBufStart_ += outputBufPutback_ - DCMZLIBINPUTFILTER_PUTBACKSIZE; + if (outputBufStart_ >= DCMZLIBINPUTFILTER_BUFSIZE) outputBufStart_ -= DCMZLIBINPUTFILTER_BUFSIZE; + outputBufPutback_ = DCMZLIBINPUTFILTER_PUTBACKSIZE; + } + } + + // refill output buffer + fillOutputBuffer(); + } while (buflen && outputBufCount_); + + // we're either done or the output buffer is empty because of producer suspension + return result; +} + +offile_off_t DcmZLibInputFilter::skip(offile_off_t skiplen) +{ + if (status_.bad() || (current_ == NULL)) return 0; + offile_off_t offset = 0; + offile_off_t availBytes = 0; + offile_off_t result = 0; + do + { + // copy bytes from output buffer to user provided block of data + if (outputBufCount_) + { + // determine next block of data in output buffer + offset = outputBufStart_ + outputBufPutback_; + if (offset >= DCMZLIBINPUTFILTER_BUFSIZE) offset -= DCMZLIBINPUTFILTER_BUFSIZE; + + availBytes = outputBufCount_; + if (offset + availBytes > DCMZLIBINPUTFILTER_BUFSIZE) availBytes = DCMZLIBINPUTFILTER_BUFSIZE - offset; + if (availBytes > skiplen) availBytes = skiplen; + result += availBytes; + skiplen -= availBytes; + + // adjust pointers + outputBufPutback_ += availBytes; + outputBufCount_ -= availBytes; + if (outputBufPutback_ > DCMZLIBINPUTFILTER_PUTBACKSIZE) + { + outputBufStart_ += outputBufPutback_ - DCMZLIBINPUTFILTER_PUTBACKSIZE; + outputBufPutback_ = DCMZLIBINPUTFILTER_PUTBACKSIZE; + if (outputBufStart_ >= DCMZLIBINPUTFILTER_BUFSIZE) outputBufStart_ -= DCMZLIBINPUTFILTER_BUFSIZE; + } + } + + // refill output buffer + fillOutputBuffer(); + } while (skiplen && outputBufCount_); + + // we're either done or the output buffer is empty because of producer suspension + return result; +} + +void DcmZLibInputFilter::putback(offile_off_t num) +{ + if (num > outputBufPutback_) status_ = EC_PutbackFailed; + else + { + outputBufPutback_ -= num; + outputBufCount_ += num; + } +} + +void DcmZLibInputFilter::append(DcmProducer& producer) +{ + current_ = &producer; +} + +offile_off_t DcmZLibInputFilter::fillInputBuffer() +{ + offile_off_t result = 0; + if (status_.good() && current_ && (inputBufCount_ < DCMZLIBINPUTFILTER_BUFSIZE)) + { + + // use first part of input buffer + if (inputBufStart_ + inputBufCount_ < DCMZLIBINPUTFILTER_BUFSIZE) + { + result = current_->read(inputBuf_ + inputBufStart_ + inputBufCount_, + DCMZLIBINPUTFILTER_BUFSIZE - (inputBufStart_ + inputBufCount_)); + + inputBufCount_ += result; + + if (result == 0) + { + if (current_->eos() && !padded_) + { + // producer has signalled eos, now append zero pad byte that makes + // zlib recognize the end of stream when no zlib header is present + *(inputBuf_ + inputBufStart_ + inputBufCount_) = 0; + inputBufCount_++; + padded_ = OFTrue; + } + return result; // producer suspension + } + } + + // use second part of input buffer + if (inputBufCount_ < DCMZLIBINPUTFILTER_BUFSIZE && + inputBufStart_ + inputBufCount_ >= DCMZLIBINPUTFILTER_BUFSIZE) + { + offile_off_t result2 = current_->read(inputBuf_ + (inputBufStart_ + inputBufCount_ - DCMZLIBINPUTFILTER_BUFSIZE), + DCMZLIBINPUTFILTER_BUFSIZE - inputBufCount_); + + inputBufCount_ += result2; + result += result2; + + if (result2 == 0 && current_->eos() && !padded_) + { + // producer has signalled eos, now append zero pad byte that makes + // zlib recognize the end of stream when no zlib header is present + *(inputBuf_ + inputBufStart_ + inputBufCount_ - DCMZLIBINPUTFILTER_BUFSIZE) = 0; + inputBufCount_++; + padded_ = OFTrue; + } + } + } + return result; +} + + +offile_off_t DcmZLibInputFilter::decompress(const void *buf, offile_off_t buflen) +{ + offile_off_t result = 0; + + zstream_->next_out = OFstatic_cast(Bytef *, OFconst_cast(void *, buf)); + zstream_->avail_out = OFstatic_cast(uInt, buflen); + int astatus; + + // decompress from inputBufStart_ to end of data or end of buffer, whatever comes first + offile_off_t numBytes = (inputBufStart_ + inputBufCount_ > DCMZLIBINPUTFILTER_BUFSIZE) ? + (DCMZLIBINPUTFILTER_BUFSIZE - inputBufStart_) : inputBufCount_ ; + + if (numBytes || buflen) + { + zstream_->next_in = OFstatic_cast(Bytef *, inputBuf_ + inputBufStart_); + zstream_->avail_in = OFstatic_cast(uInt, numBytes); + astatus = inflate(zstream_, 0); + + if (astatus == Z_OK || astatus == Z_BUF_ERROR) { /* everything OK */ } + else if (astatus == Z_STREAM_END) + { +#ifdef DEBUG + if (!eos_) + { + offile_off_t count = inputBufCount_ - (numBytes - OFstatic_cast(offile_off_t, zstream_->avail_in)); + if (count > 2) + { + /* we silently ignore up to two trailing bytes after the end of the + * deflated stream. One byte has been added by ourselves to make sure + * zlib detects eos, another one might be the padding necessary for + * odd length zlib streams transmitted through a DICOM network + * (where PDVs always have even length). + * Everything else generates a warning. + */ + DCMDATA_WARN("zlib: " << OFstatic_cast(ulong, count-1) << " pending input bytes in buffer."); + } + } +#endif + eos_ = OFTrue; + } + else + { + OFString etext = "ZLib Error: "; + if (zstream_->msg) etext += zstream_->msg; + status_ = makeOFCondition(OFM_dcmdata, 16, OF_error, etext.c_str()); + } + + // adjust counters + inputBufStart_ += numBytes - OFstatic_cast(offile_off_t, zstream_->avail_in); + inputBufCount_ -= numBytes - OFstatic_cast(offile_off_t, zstream_->avail_in); + + if (inputBufStart_ == DCMZLIBINPUTFILTER_BUFSIZE) + { + // wrapped around + inputBufStart_ = 0; + + // now flush to end of data + if (inputBufCount_ && (zstream_->avail_out > 0)) + { + zstream_->next_in = OFstatic_cast(Bytef *, inputBuf_); + zstream_->avail_in = OFstatic_cast(uInt, inputBufCount_); + astatus = inflate(zstream_, 0); + + if (astatus == Z_OK || astatus == Z_BUF_ERROR) { /* everything OK */ } + else if (astatus == Z_STREAM_END) + { +#ifdef DEBUG + if (!eos_) + { + offile_off_t count = OFstatic_cast(offile_off_t, zstream_->avail_in); + if (count > 2) + { + /* we silently ignore up to two trailing bytes after the end of the + * deflated stream. One byte has been added by ourselves to make sure + * zlib detects eos, another one might be the padding necessary for + * odd length zlib streams transmitted through a DICOM network + * (where PDVs always have even length). + * Everything else generates a warning. + */ + DCMDATA_WARN("zlib: " << OFstatic_cast(ulong, count-1) << " pending input bytes in buffer."); + } + } +#endif + eos_ = OFTrue; + } + else + { + OFString etext = "ZLib Error: "; + if (zstream_->msg) etext += zstream_->msg; + status_ = makeOFCondition(OFM_dcmdata, 16, OF_error, etext.c_str()); + } + + // adjust counters + inputBufStart_ += inputBufCount_ - OFstatic_cast(offile_off_t, zstream_->avail_in); + inputBufCount_ = OFstatic_cast(offile_off_t, zstream_->avail_in); + + } + } + + // reset buffer start to make things faster + if (inputBufCount_ == 0) inputBufStart_ = 0; + + // compute result + result = buflen - OFstatic_cast(offile_off_t, zstream_->avail_out); + } + return result; +} + +void DcmZLibInputFilter::fillOutputBuffer() +{ + offile_off_t inputBytes = 0; + offile_off_t outputBytes = 0; + offile_off_t offset = 0; + offile_off_t availBytes = 0; + do + { + inputBytes = fillInputBuffer(); + + // determine next block of free space in output buffer + offset = outputBufStart_ + outputBufPutback_ + outputBufCount_; + if (offset >= DCMZLIBINPUTFILTER_BUFSIZE) offset -= DCMZLIBINPUTFILTER_BUFSIZE; + + availBytes = DCMZLIBINPUTFILTER_BUFSIZE - (outputBufPutback_ + outputBufCount_); + if (offset + availBytes > DCMZLIBINPUTFILTER_BUFSIZE) availBytes = DCMZLIBINPUTFILTER_BUFSIZE - offset; + + // decompress to output buffer + outputBytes = decompress(outputBuf_ + offset, availBytes); + outputBufCount_ += outputBytes; + } + while (inputBytes || outputBytes); +} + +#else /* WITH_ZLIB */ + +/* make sure that the object file is not completely empty if compiled + * without zlib because some linkers might fail otherwise. + */ +void dcistrmz_dummy_function() +{ + return; +} + +#endif /* WITH_ZLIB */ diff --git a/dcmdata/libsrc/dcitem.cc b/dcmdata/libsrc/dcitem.cc new file mode 100644 index 00000000..2e55c64c --- /dev/null +++ b/dcmdata/libsrc/dcitem.cc @@ -0,0 +1,4333 @@ +/* + * + * Copyright (C) 1994-2015, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Gerd Ehlers + * + * Purpose: class DcmItem + * + */ + + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#define INCLUDE_CSTDLIB +#define INCLUDE_CSTDIO +#define INCLUDE_CSTRING +#define INCLUDE_CCTYPE +#include "dcmtk/ofstd/ofstdinc.h" + +#include "dcmtk/dcmdata/dcitem.h" +#include "dcmtk/ofstd/ofdefine.h" /* for memzero() */ +#include "dcmtk/dcmdata/dcdeftag.h" /* for name constants */ +#include "dcmtk/dcmdata/dcistrma.h" /* for class DcmInputStream */ +#include "dcmtk/dcmdata/dcobject.h" +#include "dcmtk/dcmdata/dcostrma.h" /* for class DcmOutputStream */ +#include "dcmtk/dcmdata/dcovlay.h" +#include "dcmtk/dcmdata/dcpixel.h" +#include "dcmtk/dcmdata/dcsequen.h" +#include "dcmtk/dcmdata/dcswap.h" +#include "dcmtk/dcmdata/dcvr.h" +#include "dcmtk/dcmdata/dcvrae.h" +#include "dcmtk/dcmdata/dcvras.h" +#include "dcmtk/dcmdata/dcvrat.h" +#include "dcmtk/dcmdata/dcvrcs.h" +#include "dcmtk/dcmdata/dcvrda.h" +#include "dcmtk/dcmdata/dcvrds.h" +#include "dcmtk/dcmdata/dcvrdt.h" +#include "dcmtk/dcmdata/dcvrfd.h" +#include "dcmtk/dcmdata/dcvrfl.h" +#include "dcmtk/dcmdata/dcvris.h" +#include "dcmtk/dcmdata/dcvrlo.h" +#include "dcmtk/dcmdata/dcvrlt.h" +#include "dcmtk/dcmdata/dcvrobow.h" +#include "dcmtk/dcmdata/dcvrod.h" +#include "dcmtk/dcmdata/dcvrof.h" +#include "dcmtk/dcmdata/dcvrpn.h" +#include "dcmtk/dcmdata/dcvrsh.h" +#include "dcmtk/dcmdata/dcvrsl.h" +#include "dcmtk/dcmdata/dcvrss.h" +#include "dcmtk/dcmdata/dcvrst.h" +#include "dcmtk/dcmdata/dcvrtm.h" +#include "dcmtk/dcmdata/dcvruc.h" +#include "dcmtk/dcmdata/dcvrui.h" +#include "dcmtk/dcmdata/dcvrul.h" +#include "dcmtk/dcmdata/dcvrulup.h" +#include "dcmtk/dcmdata/dcvrur.h" +#include "dcmtk/dcmdata/dcvrus.h" +#include "dcmtk/dcmdata/dcvrut.h" +#include "dcmtk/dcmdata/dcxfer.h" +#include "dcmtk/dcmdata/dcspchrs.h" /* for class DcmSpecificCharacterSet */ + +#include "dcmtk/ofstd/ofstream.h" +#include "dcmtk/ofstd/ofstring.h" +#include "dcmtk/ofstd/ofcast.h" +#include "dcmtk/ofstd/ofstd.h" + + +// ******************************** + + +DcmItem::DcmItem() + : DcmObject(DCM_ItemTag), + elementList(NULL), + lastElementComplete(OFTrue), + fStartPosition(0), + privateCreatorCache() +{ + elementList = new DcmList; +} + + +DcmItem::DcmItem(const DcmTag &tag, + const Uint32 len) + : DcmObject(tag, len), + elementList(NULL), + lastElementComplete(OFTrue), + fStartPosition(0), + privateCreatorCache() +{ + elementList = new DcmList; +} + + +DcmItem::DcmItem(const DcmItem &old) + : DcmObject(old), + elementList(new DcmList), + lastElementComplete(old.lastElementComplete), + fStartPosition(old.fStartPosition), + privateCreatorCache() +{ + if (!old.elementList->empty()) + { + elementList->seek(ELP_first); + old.elementList->seek(ELP_first); + do + { + DcmObject *dO = old.elementList->get()->clone(); + elementList->insert(dO, ELP_next); + // remember the parent + dO->setParent(this); + } while (old.elementList->seek(ELP_next)); + } +} + + +DcmItem& DcmItem::operator=(const DcmItem& obj) +{ + if (this != &obj) + { + // copy parent's member variables + DcmObject::operator=(obj); + + // delete any existing elements + elementList->deleteAllElements(); + + // copy DcmItem's member variables + lastElementComplete = obj.lastElementComplete; + fStartPosition = obj.fStartPosition; + if (!obj.elementList->empty()) + { + elementList->seek(ELP_first); + obj.elementList->seek(ELP_first); + do + { + DcmObject *dO = obj.elementList->get()->clone(); + elementList->insert(dO, ELP_next); + // remember the parent + dO->setParent(this); + } while (obj.elementList->seek(ELP_next)); + } + } + return *this; +} + + +int DcmItem::compare(const DcmItem& rhs) const +{ + if (this == &rhs) + return 0; + + // cast away constness (dcmdata is not const correct...) + DcmItem* myThis = NULL; + DcmItem* myRhs = NULL; + myThis = OFconst_cast(DcmItem*, this); + myRhs = OFconst_cast(DcmItem*, &rhs); + + // iterate over all items and test equality + unsigned long thisVM = myThis->card(); + for (unsigned long count = 0; count < thisVM; count++) + { + DcmElement* val = myThis->getElement(count); + if (val) + { + DcmElement* rhsVal = myRhs->getElement(count); + if (rhsVal) + { + int result = val->compare(*rhsVal); + if (val != 0) + { + return result; + } + // otherwise they are equal, continue comparison + } + else + { + break; // values equal until this point (rhs shorter) + } + } + } + + // we get here if all values are equal. Now look at the + // number of components + unsigned long rhsVM = myRhs->card(); + if (thisVM < rhsVM) + { + return -1; + } + else if (thisVM > rhsVM) + { + return 1; + } + + // all values as well as VM equal: objects are equal + return 0; +} + + +OFCondition DcmItem::copyFrom(const DcmObject& rhs) +{ + if (this != &rhs) + { + if (rhs.ident() != ident()) return EC_IllegalCall; + *this = OFstatic_cast(const DcmItem &, rhs); + } + return EC_Normal; +} + + +DcmItem::~DcmItem() +{ + elementList->deleteAllElements(); + delete elementList; +} + + +// ******************************** + + +OFBool DcmItem::foundVR(const Uint8* atposition) +{ + const Uint8 c1 = atposition[0]; + const Uint8 c2 = atposition[1]; + OFBool valid = OFFalse; + + if (isalpha(c1) && isalpha(c2)) + { + Uint8 vrName[3]; + vrName[0] = c1; + vrName[1] = c2; + vrName[2] = '\0'; + + /* is this VR name a standard VR descriptor */ + DcmVR vr( OFreinterpret_cast(const char*, &vrName[0] ) ); + valid = vr.isStandard(); + } else { + /* cannot be a valid VR name since non-characters */ + valid = OFFalse; + } + return valid; +} + + +// ******************************** + + +E_TransferSyntax DcmItem::checkTransferSyntax(DcmInputStream &inStream) +{ + E_TransferSyntax transferSyntax; + Uint8 tagAndVR[6]; + + /* we need 6 bytes, if there is less available we can't do much */ + if (inStream.avail() < 6) + return EXS_LittleEndianExplicit; + + /* read 6 bytes from the input stream (try to read tag and VR (data type)) */ + inStream.mark(); + inStream.read(tagAndVR, 6); // check tag & VR + inStream.putback(); + + /* create two tag variables (one for little, one for big */ + /* endian) in order to figure out, if there is a valid tag */ + const Uint8 c1 = tagAndVR[0]; + const Uint8 c2 = tagAndVR[1]; + const Uint8 c3 = tagAndVR[2]; + const Uint8 c4 = tagAndVR[3]; + const Uint16 t1 = OFstatic_cast(unsigned short, (c1 & 0xff) + ((c2 & 0xff) << 8)); // explicit little endian + const Uint16 t2 = OFstatic_cast(unsigned short, (c3 & 0xff) + ((c4 & 0xff) << 8)); // conversion + DcmTag taglittle(t1, t2); + DcmTag tagbig(swapShort(t1), swapShort(t2)); + + /* now we want to determine the transfer syntax which was used to code the information in the stream. */ + /* The decision is based on two questions: a) Did we encounter a valid tag? and b) Do the last 2 bytes */ + /* which were read from the stream represent a valid VR? In certain special cases, where the transfer */ + /* cannot be determined without doubt, we want to guess the most probable transfer syntax. */ + + /* if both tag variables show an error, we encountered an invalid tag */ + if ((taglittle.error().bad()) && (tagbig.error().bad())) + { + /* in case we encountered an invalid tag, we want to assume that the used transfer syntax */ + /* is a little endian transfer syntax. Now we have to figure out, if it is an implicit or */ + /* explicit transfer syntax. Hence, check if the last 2 bytes represent a valid VR. */ + if (foundVR(&tagAndVR[4])) + { + /* if the last 2 bytes represent a valid VR, we assume that the used */ + /* transfer syntax is the little endian explicit transfer syntax. */ + transferSyntax = EXS_LittleEndianExplicit; + } else { + /* if the last 2 bytes did not represent a valid VR, we assume that the */ + /* used transfer syntax is the little endian implicit transfer syntax. */ + transferSyntax = EXS_LittleEndianImplicit; + } + } + /* if at least one tag variable did not show an error, we encountered a valid tag */ + else + { + /* in case we encountered a valid tag, we want to figure out, if it is an implicit or */ + /* explicit transfer syntax. Hence, check if the last 2 bytes represent a valid VR. */ + if (foundVR(&tagAndVR[4])) + { + /* having figured out that the last 2 bytes represent a valid */ + /* VR, we need to find out which of the two tags was valid */ + if (taglittle.error().bad()) + { + /* if the litte endian tag was invalid, the transfer syntax is big endian explicit */ + transferSyntax = EXS_BigEndianExplicit; + } + else if (tagbig.error().bad()) + { + /* if the big endian tag was invalid, the transfer syntax is little endian explicit */ + transferSyntax = EXS_LittleEndianExplicit; + } else { + /* if both tags were valid, we take a look at the group numbers. Since */ + /* group 0008 is much more probable than group 0800 for the first tag */ + /* we specify the following: */ + if ((taglittle.getGTag() > 0xff)&&(tagbig.getGTag() <= 0xff)) transferSyntax = EXS_BigEndianExplicit; + else transferSyntax = EXS_LittleEndianExplicit; + } + } else { + /* having figured out that the last 2 bytes do not represent a */ + /* valid VR, we need to find out which of the two tags was valid */ + if (taglittle.error().bad()) + { + /* if the litte endian tag was invalid, the transfer syntax is big endian implicit */ + transferSyntax = EXS_BigEndianImplicit; + } + else if (tagbig.error().bad()) + { + /* if the big endian tag was invalid, the transfer syntax is little endian implicit */ + transferSyntax = EXS_LittleEndianImplicit; + } else { + /* if both tags were valid, we take a look at the group numbers. Since */ + /* group 0008 is much more probable than group 0800 for the first tag */ + /* we specify the following: */ + if ((taglittle.getGTag() > 0xff)&&(tagbig.getGTag() <= 0xff)) transferSyntax = EXS_BigEndianImplicit; + else transferSyntax = EXS_LittleEndianImplicit; + } + } + } + + /* return determined transfer syntax */ + return transferSyntax; +} + + +// ******************************** + + +void DcmItem::checkAndUpdateVR(DcmItem &item, + DcmTag &tag) +{ + /* handle special cases where the VR can be determined by some other element values */ + if (((tag == DCM_WaveformData) || (tag == DCM_WaveformPaddingValue)) && (tag.getEVR() == EVR_ox)) + { + /* case 1 (WaveformData and others): see section 8.3 in PS 3.5 */ + Uint16 bitsAlloc; + if (item.findAndGetUint16(DCM_WaveformBitsAllocated, bitsAlloc).good()) + { + if (bitsAlloc == 8) + { + DCMDATA_DEBUG("DcmItem::checkAndUpdateVR() setting undefined VR of " + << tag.getTagName() << " " << tag << " to 'OB' because WaveformBitsAllocated " + << DCM_WaveformBitsAllocated << " has a value of 8"); + tag.setVR(EVR_OB); + } else { + DCMDATA_DEBUG("DcmItem::checkAndUpdateVR() setting undefined VR of " + << tag.getTagName() << " " << tag << " to 'OW' because WaveformBitsAllocated " + << DCM_WaveformBitsAllocated << " has a value that is different from 8"); + tag.setVR(EVR_OW); + } + } + } + else if (((tag == DCM_PixelPaddingValue) || (tag == DCM_PixelPaddingRangeLimit) || + (tag == DCM_HistogramFirstBinValue) || (tag == DCM_HistogramLastBinValue) || + (tag == DCM_ZeroVelocityPixelValue)) && (tag.getEVR() == EVR_xs)) + { + /* case 2 (PixelPaddingValue and others): see section C.7.5.1, C.7.6.16.x and C.11.5 in PS 3.3 */ + Uint16 pixelRep; + if (item.findAndGetUint16(DCM_PixelRepresentation, pixelRep).good()) + { + if (pixelRep == 0x0001) + { + DCMDATA_DEBUG("DcmItem::checkAndUpdateVR() setting undefined VR of " << tag.getTagName() + << " " << tag << " to 'SS' because PixelRepresentation " + << DCM_PixelRepresentation << " has a value of 1"); + tag.setVR(EVR_SS); + } else { + DCMDATA_DEBUG("DcmItem::checkAndUpdateVR() setting undefined VR of " << tag.getTagName() + << " " << tag << " to 'US' because PixelRepresentation " + << DCM_PixelRepresentation << " has a value that is different from 1"); + tag.setVR(EVR_US); + } + } + } + else if (((tag.getBaseTag() == DCM_OverlayData) || (tag == DCM_PixelData)) && (tag.getEVR() == EVR_ox)) + { + /* case 3 (OverlayData and PixelData): see section 8.1.2 and 8.2 in PS 3.5 */ + DCMDATA_DEBUG("DcmItem::checkAndUpdateVR() setting undefined VR of " + << tag.getTagName() << " " << tag << " to 'OW'"); + tag.setVR(EVR_OW); + } + else if ((tag.getBaseTag() == DCM_RETIRED_CurveData) && (tag.getEVR() == EVR_ox)) + { + /* case 4 (CurveData): see section A.1 in PS 3.5-2004 */ + DCMDATA_DEBUG("DcmItem::checkAndUpdateVR() setting undefined VR of " + << tag.getTagName() << " " << tag << " to 'OB'"); + tag.setVR(EVR_OB); + } +} + + +// ******************************** + + +DcmEVR DcmItem::ident() const +{ + return EVR_item; +} + + +unsigned long DcmItem::getVM() +{ + return 1; +} + + +// ******************************** + +void DcmItem::print(STD_NAMESPACE ostream &out, + const size_t flags, + const int level, + const char *pixelFileName, + size_t *pixelCounter) +{ + if (flags & DCMTypes::PF_showTreeStructure) + { + /* print item line with empty text */ + printInfoLine(out, flags, level); + /* print item content */ + if (!elementList->empty()) + { + DcmObject *dO; + elementList->seek(ELP_first); + do { + dO = elementList->get(); + dO->print(out, flags, level + 1, pixelFileName, pixelCounter); + } while (elementList->seek(ELP_next)); + } + } else { + /* print item start line */ + OFOStringStream oss; + oss << "(Item with "; + if (getLengthField() == DCM_UndefinedLength) + oss << "undefined"; + else + oss << "explicit"; + oss << " length #=" << card() << ")" << OFStringStream_ends; + OFSTRINGSTREAM_GETSTR(oss, tmpString) + printInfoLine(out, flags, level, tmpString); + OFSTRINGSTREAM_FREESTR(tmpString) + /* print item content */ + if (!elementList->empty()) + { + DcmObject *dO; + elementList->seek(ELP_first); + do { + dO = elementList->get(); + dO->print(out, flags, level + 1, pixelFileName, pixelCounter); + } while (elementList->seek(ELP_next)); + } + /* print item end line */ + DcmTag delimItemTag(DCM_ItemDelimitationItemTag); + if (getLengthField() == DCM_UndefinedLength) + printInfoLine(out, flags, level, "(ItemDelimitationItem)", &delimItemTag); + else + printInfoLine(out, flags, level, "(ItemDelimitationItem for re-encoding)", &delimItemTag); + } +} + + +// ******************************** + + +OFCondition DcmItem::writeXML(STD_NAMESPACE ostream &out, + const size_t flags) +{ + if (!(flags & DCMTypes::XF_useNativeModel)) + { + /* XML start tag for "item" */ + out << "" << OFendl; + } + /* write item content */ + if (!elementList->empty()) + { + /* write content of all children */ + DcmObject *dO; + elementList->seek(ELP_first); + do { + dO = elementList->get(); + dO->writeXML(out, flags); + } while (elementList->seek(ELP_next)); + } + if (!(flags & DCMTypes::XF_useNativeModel)) + { + /* XML end tag for "item" */ + out << "" << OFendl; + } + /* always report success */ + return EC_Normal; +} + + +// ******************************** + + +OFBool DcmItem::canWriteXfer(const E_TransferSyntax newXfer, + const E_TransferSyntax oldXfer) +{ + OFBool canWrite = OFTrue; + if (newXfer == EXS_Unknown) + canWrite = OFFalse; + else if (!elementList->empty()) + { + DcmObject *dO; + elementList->seek(ELP_first); + do { + dO = elementList->get(); + canWrite = dO->canWriteXfer(newXfer, oldXfer); + } while (elementList->seek(ELP_next) && canWrite); + } + return canWrite; +} + + +// ******************************** + + +Uint32 DcmItem::calcElementLength(const E_TransferSyntax xfer, + const E_EncodingType enctype) +{ + Uint32 itemlen = 0; + DcmXfer xferSyn(xfer); + /* Length of item's start header */ + Uint32 headersize = xferSyn.sizeofTagHeader(getVR()); + /* Length of item's content, i.e. contained elements */ + itemlen = getLength(xfer, enctype); + /* Since the item's total length can exceed the maximum length of 32 bit, it is + * always necessary to check for overflows. The approach taken is not elegant + * but should work... + */ + if ( (itemlen == DCM_UndefinedLength) || OFStandard::check32BitAddOverflow(itemlen, headersize) ) + return DCM_UndefinedLength; + itemlen += xferSyn.sizeofTagHeader(getVR()); + if (enctype == EET_UndefinedLength) // add bytes for closing item tag marker if necessary + { + if (OFStandard::check32BitAddOverflow(itemlen, 8)) + return DCM_UndefinedLength; + else + itemlen += 8; + } + return itemlen; +} + + +// ******************************** + + +Uint32 DcmItem::getLength(const E_TransferSyntax xfer, + const E_EncodingType enctype) +{ + Uint32 itemlen = 0; + Uint32 sublen = 0; + if (!elementList->empty()) + { + DcmObject *dO; + elementList->seek(ELP_first); + do { + dO = elementList->get(); + sublen = dO->calcElementLength(xfer, enctype); + /* explicit length: be sure that total size of contained elements fits into item's + 32 Bit length field. If not, switch encoding automatically to undefined + length for this item. Nevertheless, any contained elements will be + written with explicit length if possible. + */ + if ( (enctype == EET_ExplicitLength) && OFStandard::check32BitAddOverflow(sublen, itemlen) ) + { + if (dcmWriteOversizedSeqsAndItemsUndefined.get()) + { + DCMDATA_WARN("DcmItem: Explicit length of item exceeds 32-Bit length field, " + << "trying to encode with undefined length"); + } + else + { + DCMDATA_WARN("DcmItem: Explicit length of item exceeds 32-Bit length field, " + << "aborting write"); + errorFlag = EC_SeqOrItemContentOverflow; + } + return DCM_UndefinedLength; + } + else + itemlen += sublen; + } while (elementList->seek(ELP_next)); + } + return itemlen; +} + + +// ******************************** + + +OFCondition DcmItem::computeGroupLengthAndPadding(const E_GrpLenEncoding glenc, + const E_PaddingEncoding padenc, + const E_TransferSyntax xfer, + const E_EncodingType enctype, + const Uint32 padlen, + const Uint32 subPadlen, + Uint32 instanceLength) +{ + /* if certain conditions are met, this is considered to be an illegal call. */ + if ((padenc == EPD_withPadding && (padlen % 2 || subPadlen % 2)) || + ((glenc == EGL_recalcGL || glenc == EGL_withGL || + padenc == EPD_withPadding) && xfer == EXS_Unknown)) + return EC_IllegalCall; + + /* if the caller specified that group length tags and padding */ + /* tags are not supposed to be changed, there is nothing to do. */ + if (glenc == EGL_noChange && padenc == EPD_noChange) + return EC_Normal; + + /* if we get to this point, we need to do something. First of all, set the error indicator to normal. */ + OFCondition l_error = EC_Normal; + /* collects group length elements that cannot be calculated due to length field overflows */ + OFList exceededGroupLengthElems; + + /* if there are elements in this item... */ + if (!elementList->empty()) + { + /* initialize some variables */ + DcmObject *dO; + OFBool beginning = OFTrue; + Uint16 lastGrp = 0x0000; + Uint16 actGrp; + DcmUnsignedLong * actGLElem = NULL; + DcmUnsignedLong * paddingGL = NULL; + Uint32 grplen = 0; + DcmXfer xferSyn(xfer); + Uint32 sublen = 0; + OFBool groupLengthExceeded = OFFalse; + + /* determine the current seek mode and set the list pointer to the first element */ + E_ListPos seekmode = ELP_next; + elementList->seek(ELP_first); + + /* start a loop: we want to go through all elements as long as everything is okay */ + do + { + /* set the seek mode to "next" again, in case it has been modified in the last iteration */ + seekmode = ELP_next; + + /* get the current element and assign it to a local variable */ + dO = elementList->get(); + + /* if the current element is a sequence, compute group length and padding for the sub sequence */ + if (dO->getVR() == EVR_SQ) + { + // add size of sequence header + Uint32 templen = instanceLength + xferSyn.sizeofTagHeader(EVR_SQ); + // call computeGroupLengthAndPadding for all contained items + l_error = OFstatic_cast(DcmSequenceOfItems *, dO)->computeGroupLengthAndPadding + (glenc, padenc, xfer, enctype, subPadlen, subPadlen, templen); + } + + /* if everything is ok so far */ + if (l_error.good()) + { + /* in case one of the following two conditions is met */ + /* (i) the caller specified that we want to add or remove group length elements and the current */ + /* element's tag shows that it is a group length element (tag's element number equals 0x0000) */ + /* (ii) the caller specified that we want to add or remove padding elements and the current */ + /* element's tag shows that it is a padding element (tag is (0xfffc,0xfffc) */ + /* then we want to delete the current (group length or padding) element */ + if (((glenc == EGL_withGL || glenc == EGL_withoutGL) && dO->getETag() == 0x0000) || + (padenc != EPD_noChange && dO->getTag() == DCM_DataSetTrailingPadding)) + { + delete elementList->remove(); + seekmode = ELP_atpos; // remove advances 1 element forward -> make next seek() work + dO = NULL; + } + /* if the above mentioned conditions are not met but the caller specified that we want to add group */ + /* length tags for every group or that we want to recalculate values for existing group length tags */ + else if (glenc == EGL_withGL || glenc == EGL_recalcGL) + { + /* we need to determine the current element's group number */ + actGrp = dO->getGTag(); + + /* and if the group number is different from the last remembered group number or */ + /* if this id the very first element that is treated then we've found a new group */ + if (actGrp != lastGrp || beginning) // new Group found + { + /* set beginning to false in order to specify that the */ + /* very first element has already been treated */ + beginning = OFFalse; + + /* if the current element is a group length element and its data type */ + /* is not UL replace this element with one that has a UL datatype since */ + /* group length elements are supposed to have this data type */ + if (dO->getETag() == 0x0000 && dO->ident() != EVR_UL) + { + delete elementList->remove(); + DcmTag tagUL(actGrp, 0x0000, EVR_UL); + DcmUnsignedLong *dUL = new DcmUnsignedLong(tagUL); + elementList->insert(dUL, ELP_prev); + dO = dUL; + // remember the parent + dO->setParent(this); + DCMDATA_WARN("DcmItem: Group Length with VR other than UL found, corrected"); + } + /* if the above mentioned condition is not met but the caller specified */ + /* that we want to add group length elements, we need to add such an element */ + else if (glenc == EGL_withGL) + { + // Create GroupLength element + DcmTag tagUL(actGrp, 0x0000, EVR_UL); + DcmUnsignedLong *dUL = new DcmUnsignedLong(tagUL); + // insert new GroupLength element + elementList->insert(dUL, ELP_prev); + dO = dUL; + // remember the parent + dO->setParent(this); + } + + /* in case we want to add padding elements and the current element is a */ + /* padding element we want to remember the padding element so that the */ + /* group length of this element can be stored later */ + if (padenc == EPD_withPadding && actGrp == 0xfffc) + paddingGL = OFstatic_cast(DcmUnsignedLong *, dO); + + /* if actGLElem contains a valid pointer it was set in one of the last iterations */ + /* to the group length element of the last group. We need to write the current computed */ + /* group length value to this element. Exception: If group length exceeds maximum possible */ + /* value, than remove group length element instead of setting it */ + if (actGLElem != NULL) + { + if (!groupLengthExceeded) + { + // do not use putUint32() in order to make sure that the resulting VM is really 1 + actGLElem->putUint32Array(&grplen, 1); + DCMDATA_DEBUG("DcmItem::computeGroupLengthAndPadding() Length of Group 0x" + << STD_NAMESPACE hex << STD_NAMESPACE setfill('0') + << STD_NAMESPACE setw(4) << actGLElem->getGTag() + << STD_NAMESPACE dec << STD_NAMESPACE setfill(' ') + << " len=" << grplen); + } + else + { + DCMDATA_WARN("DcmItem: Group length of group 0x" + << STD_NAMESPACE hex << STD_NAMESPACE setfill('0') + << STD_NAMESPACE setw(4) << actGLElem->getGTag() + << " exceeds 32-Bit length field. " + << "Cannot calculate/write group length for this group."); + exceededGroupLengthElems.push_back(actGLElem); + groupLengthExceeded = OFFalse; + } + } + + /* set the group length value to 0 since it is the beginning of the new group */ + grplen = 0; + + /* if the current element is a group length element, remember its address for later */ + /* (we need to assign the group length value to this element in a subsequent iteration) */ + /* in case the current element (at the beginning of the group) is not a group length */ + /* element, set the actGLElem pointer to NULL. */ + if (dO->getETag() == 0x0000) + actGLElem = OFstatic_cast(DcmUnsignedLong *, dO); + else + actGLElem = NULL; + } + /* if this is not a new group, calculate the element's length and add it */ + /* to the currently computed group length value. If group length is larger */ + /* than group length field permits, set flag to not add group length for this group */ + else + { + sublen = dO->calcElementLength(xfer, enctype); + // test for 32-bit overflow return value + if ((sublen == DCM_UndefinedLength) || OFStandard::check32BitAddOverflow(sublen, grplen)) + { + groupLengthExceeded = OFTrue; + } + else + { + grplen += sublen; + } + } + + /* remember the current element's group number so that it is possible to */ + /* figure out if a new group is treated in the following iteration */ + lastGrp = actGrp; + } + } + } while (l_error.good() && elementList->seek(seekmode)); + + /* if there was no error and the caller specified that we want to add or recalculate */ + /* group length tags and if actGLElem has a valid value, we need to add the above */ + /* computed group length value to the last group's group length element. Exception: */ + /* If group length exceeds maximum possible value, remove group length element and */ + /* i.e. do not write it for this group. */ + if (l_error.good() && (glenc == EGL_withGL || glenc == EGL_recalcGL) && actGLElem) + { + if (groupLengthExceeded) + { + exceededGroupLengthElems.push_back(actGLElem); + } + else + { + actGLElem->putUint32(grplen); + } + } + + /* if the caller specified that we want to add padding elements and */ + /* if the length up to which shall be padded does not equal 0 we might */ + /* have to add a padding element */ + if (padenc == EPD_withPadding && padlen) + { + /* calculate how much space the entire padding element is supposed to occupy */ + Uint32 padding; + if (ident() == EVR_dataset) + { + instanceLength += calcElementLength(xfer, enctype); + padding = padlen - (instanceLength % padlen); + } else + padding = padlen - (getLength(xfer, enctype) % padlen); + + /* if now padding does not equal padlen we need to create a padding element. (if both values are equal */ + /* the element does have the exact required padlen length and does not need a padding element.) */ + if (padding != padlen) + { + /* Create new padding element */ + DcmOtherByteOtherWord * paddingEl = new DcmOtherByteOtherWord(DCM_DataSetTrailingPadding); + + /* calculate the length of the new element */ + Uint32 tmplen = paddingEl->calcElementLength(xfer, enctype); + + /* in case padding is smaller than the header of the padding element, we */ + /* need to increase padding (the value which specifies how much space the */ + /* entire padding element is supposed to occupy) until it is no longer smaller */ + while (tmplen > padding) + padding += padlen; + + /* determine the amount of bytes that have to be added to the */ + /* padding element so that it has the correct size */ + padding -= tmplen; + + /* create an array of a corresponding size and set the array fields */ + Uint8 * padBytes = new Uint8[padding]; + memzero(padBytes, size_t(padding)); + + /* set information in the above created padding element (size and actual value) */ + paddingEl->putUint8Array(padBytes, padding); + + /* delete the above created array */ + delete[] padBytes; + + /* insert the padding element into this */ + insert(paddingEl); + + /* finally we need to update the group length for the padding element if it exists */ + if (paddingGL) + { + Uint32 len; + paddingGL->getUint32(len); + len += paddingEl->calcElementLength(xfer, enctype); + paddingGL->putUint32(len); + } + } + } + } + /* delete invalid group length elements from item. Cannot be done in */ + /* above while loop because then elementList iterator is invalidated */ + const size_t numElems = exceededGroupLengthElems.size(); + for (size_t i = 0; i < numElems; i++) + { + delete remove(exceededGroupLengthElems.front()); + exceededGroupLengthElems.pop_front(); + } + + return l_error; +} + + +// ******************************** + + +OFCondition DcmItem::readTagAndLength(DcmInputStream &inStream, + const E_TransferSyntax xfer, + DcmTag &tag, + Uint32 &length, + Uint32 &bytesRead) +{ + OFCondition l_error = EC_Normal; + Uint32 valueLength = 0; + Uint16 groupTag = 0xffff; + Uint16 elementTag = 0xffff; + + /* create a DcmXfer object based on the transfer syntax which was passed */ + DcmXfer xferSyn(xfer); + +#ifdef DEBUG + /* dump some information if required */ + DCMDATA_TRACE("DcmItem::readTagAndLength() TransferSyntax=\"" << xferSyn.getXferName() << "\""); +#endif + + /* bail out if at end of stream */ + if (inStream.eos()) + return EC_EndOfStream; + + /* check if either 4 (for implicit transfer syntaxes) or 6 (for explicit transfer */ + /* syntaxes) bytes are available in (i.e. can be read from) inStream. if an error */ + /* occurred while performing this check return this error */ + if (inStream.avail() < (xferSyn.isExplicitVR() ? 6u:4u)) + return EC_StreamNotifyClient; + + /* determine the byte ordering of the transfer syntax which was passed; */ + /* if the byte ordering is unknown, this is an illegal call. */ + const E_ByteOrder byteOrder = xferSyn.getByteOrder(); + if (byteOrder == EBO_unknown) + return EC_IllegalCall; + + /* read tag information (4 bytes) from inStream and create a corresponding DcmTag object */ + inStream.mark(); + inStream.read(&groupTag, 2); + inStream.read(&elementTag, 2); + swapIfNecessary(gLocalByteOrder, byteOrder, &groupTag, 2, 2); + swapIfNecessary(gLocalByteOrder, byteOrder, &elementTag, 2, 2); + // tag has been read + bytesRead = 4; + DcmTag newTag(groupTag, elementTag); + DcmEVR newEVR = newTag.getEVR(); + // check whether tag is private + OFBool isPrivate = groupTag & 1; + + /* if the transfer syntax which was passed is an explicit VR syntax and if the current */ + /* item is not a delimitation item (note that delimitation items do not have a VR), go */ + /* ahead and read 2 bytes from inStream. These 2 bytes contain this item's VR value. */ + if (xferSyn.isExplicitVR() && (newEVR != EVR_na)) + { + char vrstr[3]; + vrstr[2] = '\0'; + + /* read 2 bytes */ + inStream.read(vrstr, 2); + + /* create a corresponding DcmVR object */ + DcmVR vr(vrstr); + + /* if the VR which was read is not a standard VR, print a warning */ + if (!vr.isStandard()) + { + OFOStringStream oss; + oss << "DcmItem: Non-standard VR '" + << ((OFstatic_cast(unsigned char, vrstr[0]) < 32) ? ' ' : vrstr[0]) + << ((OFstatic_cast(unsigned char, vrstr[1]) < 32) ? ' ' : vrstr[1]) << "' (" + << STD_NAMESPACE hex << STD_NAMESPACE setfill('0') + << STD_NAMESPACE setw(2) << OFstatic_cast(unsigned int, vrstr[0] & 0xff) << "\\" + << STD_NAMESPACE setw(2) << OFstatic_cast(unsigned int, vrstr[1] & 0xff) + << ") encountered while parsing element " << newTag << OFStringStream_ends; + OFSTRINGSTREAM_GETSTR(oss, tmpString) + /* encoding of this data element might be wrong, try to correct it */ + if (dcmAcceptUnexpectedImplicitEncoding.get()) + { + DCMDATA_WARN(tmpString << ", trying again with Implicit VR Little Endian"); + /* put back read bytes to input stream ... */ + inStream.putback(); + bytesRead = 0; + /* ... and retry with Implicit VR Little Endian transfer syntax */ + return readTagAndLength(inStream, EXS_LittleEndianImplicit, tag, length, bytesRead); + } else { + DCMDATA_WARN(tmpString << ", assuming " << (vr.usesExtendedLengthEncoding() ? "4" : "2") + << " byte length field"); + } + OFSTRINGSTREAM_FREESTR(tmpString) + + /* workaround: handle known issue with non-standard VR "OX" for PixelData element */ + if ((newTag == DCM_PixelData) && (strncmp(vrstr, "OX", 2) == 0)) + { + DCMDATA_WARN("DcmItem: Non-standard VR 'OX' is known to be wrongly used for PixelData " << newTag + << ", setting VR to 'OW'"); + vr.setVR(EVR_OW); + } + } + + /* the VR in the dataset might be wrong, so the user can decide to ignore it */ + if (dcmPreferVRFromDataDictionary.get() && (newEVR != EVR_UNKNOWN) && (newEVR != EVR_UNKNOWN2B)) + { + if (newEVR != vr.getEVR()) + { + /* ignore explicit VR in dataset if tag is defined in data dictionary */ + DCMDATA_DEBUG("DcmItem::readTagAndLength() ignoring explicit VR in dataset (" + << vr.getVRName() << ") for element " << newTag + << ", using the one from data dictionary (" << newTag.getVRName() << ")"); + } + } else { + /* set the VR which was read in the above created tag object */ + newTag.setVR(vr); + } + + if (!dcmPreferLengthFieldSizeFromDataDictionary.get() || newEVR == EVR_UNKNOWN || newEVR == EVR_UNKNOWN2B) { + /* determine VR read from dataset, because this VR specifies the number of bytes for the length-field */ + newEVR = vr.getEVR(); + } else { + /* use the VR from the dictionary for deciding the length of the length field */ + } + + /* increase counter by 2 */ + bytesRead += 2; + } + + /* special handling for private elements */ + if (isPrivate && (newTag.getElement() >= 0x1000)) + { + const char *pc = privateCreatorCache.findPrivateCreator(newTag); + if (pc) + { + // we have a private creator for this element + newTag.setPrivateCreator(pc); + + if (xferSyn.isImplicitVR()) + { + // try to update VR from dictionary now that private creator is known + newTag.lookupVRinDictionary(); + // also update the VR + newEVR = newTag.getEVR(); + } + } + } + + /* the next thing we want to do is read the value in the length field from inStream. */ + /* determine if there is a corresponding amount of bytes (for the length field) still */ + /* available in inStream. If not, return an error. */ + if (inStream.avail() < xferSyn.sizeofTagHeader(newEVR) - bytesRead) + { + inStream.putback(); // the UnsetPutbackMark is in readSubElement + bytesRead = 0; + l_error = EC_StreamNotifyClient; + return l_error; + } + + /* read the value in the length field. In some cases, it is 4 bytes wide, in other */ + /* cases only 2 bytes (see DICOM standard part 5, section 7.1.1) */ + if (xferSyn.isImplicitVR() || newEVR == EVR_na) // note that delimitation items don't have a VR + { + inStream.read(&valueLength, 4); // length field is 4 bytes wide + swapIfNecessary(gLocalByteOrder, byteOrder, &valueLength, 4, 4); + bytesRead += 4; + } else { // the transfer syntax is explicit VR + DcmVR vr(newEVR); + if (vr.usesExtendedLengthEncoding()) + { + Uint16 reserved; + inStream.read(&reserved, 2); // 2 reserved bytes + inStream.read(&valueLength, 4); // length field is 4 bytes wide + swapIfNecessary(gLocalByteOrder, byteOrder, &valueLength, 4, 4); + bytesRead += 6; + } else { + Uint16 tmpValueLength; + inStream.read(&tmpValueLength, 2); // length field is 2 bytes wide + swapIfNecessary(gLocalByteOrder, byteOrder, &tmpValueLength, 2, 2); + bytesRead += 2; + valueLength = tmpValueLength; + } + } + /* if the value in length is odd, print an error message */ + if ( (valueLength & 1) && (valueLength != DCM_UndefinedLength) ) + { + DCMDATA_WARN("DcmItem: Length of element " << newTag << " is odd"); + } + + /* if desired, handle private attributes with maximum length as VR SQ */ + if (isPrivate && dcmReadImplPrivAttribMaxLengthAsSQ.get() && (valueLength == DCM_UndefinedLength)) + { + /* re-set tag to be a sequence and also delete private creator cache */ + newTag.setVR(EVR_SQ); + newTag.setPrivateCreator(""); + } + + /* if desired, check if length is greater than length of surrounding item */ + const Uint32 valueLengthItem = getLengthField(); + if ((ident() == EVR_item /* e.g. meta info would have length 0 */) && + (valueLengthItem != DCM_UndefinedLength /* this does not work in undefined length items */) && + (valueLength != DCM_UndefinedLength) /* Also, do not check sequences with undefined length 0xFFFFFFFF */ + ) + { + const offile_off_t remainingItemBytes = valueLengthItem - (inStream.tell() - fStartPosition); + /* is the explicit item length too small to cover the full value of the element value length to be read? */ + if (remainingItemBytes < 0) + { + DCMDATA_WARN("DcmItem: Explicit item length (" << valueLengthItem << " bytes) too large for the elements contained in the item"); + /* if the next tag is the sequence delimiter item, we can adapt to the situation */ + if (newTag.getXTag() == DCM_SequenceDelimitationItem) + { + DCMDATA_WARN("DcmItem: Sequence delimitation occured before all bytes announced by explicit item length could be read"); + l_error = EC_PrematureSequDelimitationItem; + /* rewind to start of sequence delimiter which is read in a regular way */ + /* by DcmSequenceOfItems later (if error is ignored in DcmItem::read()) */ + inStream.putback(); + } + } + else if (valueLength > remainingItemBytes) + { + DCMDATA_WARN("DcmItem: Element " << newTag.getTagName() << " " << newTag + << " larger (" << valueLength << ") than remaining bytes (" + /* need to cast remainingItemBytes to unsigned long because VC6 cannot print offile_off_t (int64_t). */ + << OFstatic_cast(unsigned long, remainingItemBytes) << ") of surrounding item"); + l_error = EC_ElemLengthLargerThanItem; + } + } + + /* assign values to out parameter */ + length = valueLength; + tag = newTag; + + /* return return value */ + return l_error; +} + + +// ******************************** + + +OFCondition DcmItem::readSubElement(DcmInputStream &inStream, + DcmTag &newTag, + const Uint32 newLength, + const E_TransferSyntax xfer, + const E_GrpLenEncoding glenc, + const Uint32 maxReadLength) +{ + DcmElement *subElem = NULL; + + /* create a new DcmElement* object with corresponding tag and */ + /* length; the object will be accessible through subElem */ + OFBool readAsUN = OFFalse; + OFCondition l_error = newDicomElement(subElem, newTag, newLength, &privateCreatorCache, readAsUN); + + /* if no error occurred and subElem does not equal NULL, go ahead */ + if (l_error.good() && subElem != NULL) + { + // inStream.UnsetPutbackMark(); // not needed anymore with new stream architecture + + /* insert the new element into the (sorted) element list and */ + /* assign information which was read from the inStream to it */ + subElem->transferInit(); + /* we need to read the content of the attribute, no matter if */ + /* inserting the attribute succeeds or fails */ + l_error = subElem->read(inStream, (readAsUN ? EXS_LittleEndianImplicit : xfer), glenc, maxReadLength); + // try to insert element into item. Note that + // "elementList->insert(subElem, ELP_next)" would be faster, + // but this is better since this insert-function creates a + // sorted element list. + // We insert the element even if subElem->read() reported an error + // because otherwise I/O suspension would fail. + OFCondition temp_error = insert(subElem, OFFalse, OFTrue); + + if (temp_error.bad()) + { + // produce diagnostics + DCMDATA_WARN("DcmItem: Element " << newTag + << " found twice in one dataset/item, ignoring second entry"); + delete subElem; + } + } + /* else if an error occurred, try to recover from this error */ + else if (l_error == EC_InvalidTag) + { + /* This is the second putback operation on the putback mark in */ + /* readTagAndLength but it is impossible that both can be executed */ + /* without setting the Mark twice. */ + inStream.putback(); + DCMDATA_WARN("DcmItem: Parse error while parsing element " << newTag); + } + else if (l_error != EC_ItemEnd) + { + // inStream.UnsetPutbackMark(); // not needed anymore with new stream architecture + + // dump some information if required + if (dcmIgnoreParsingErrors.get() || (dcmReplaceWrongDelimitationItem.get() && (l_error == EC_SequEnd))) + { + DCMDATA_WARN("DcmItem: Parse error in sequence item, found " << newTag + << " instead of item delimiter " << DCM_ItemDelimitationItem); + } else { + DCMDATA_ERROR("DcmItem: Parse error in sequence item, found " << newTag + << " instead of item delimiter " << DCM_ItemDelimitationItem); + } + // some systems use the wrong delimitation item at the end of a sequence + if (dcmReplaceWrongDelimitationItem.get() && (l_error == EC_SequEnd)) + { + DCMDATA_DEBUG("DcmItem::readSubItem() replacing wrong sequence delimiter " + << DCM_SequenceDelimitationItem << " by item delimiter " + << DCM_ItemDelimitationItem << " because it is expected here"); + l_error = EC_ItemEnd; + } else { + DCMDATA_DEBUG("DcmItem::readSubElement() cannot create Sub Element " << newTag); + // treat this incorrect encoding as an error + if (!dcmIgnoreParsingErrors.get()) + l_error = EC_ItemDelimitationItemMissing; + } + } else { + // inStream.UnsetPutbackMark(); // not needed anymore with new stream architecture + } + + /* dump some information if required */ + DCMDATA_TRACE("DcmItem::readSubItem() returns error = " << l_error.text()); + /* return result value */ + return l_error; +} + + +// ******************************** + + +OFCondition DcmItem::read(DcmInputStream & inStream, + const E_TransferSyntax xfer, + const E_GrpLenEncoding glenc, + const Uint32 maxReadLength) +{ + /* check if this is an illegal call; if so set the error flag and do nothing, else go ahead */ + if (getTransferState() == ERW_notInitialized) + { + errorFlag = EC_IllegalCall; + return errorFlag; + } + + /* figure out if the stream reported an error */ + errorFlag = inStream.status(); + /* if the stream reported an error or if it is the end of the */ + /* stream, set the error flag correspondingly; else go ahead */ + if (errorFlag.good() && inStream.eos()) + errorFlag = EC_EndOfStream; + else if (errorFlag.good() && getTransferState() != ERW_ready) + { + /* if the transfer state of this item is ERW_init, get its start */ + /* position in the stream and set the transfer state to ERW_inWork */ + if (getTransferState() == ERW_init) + { + fStartPosition = inStream.tell(); // start position of this item + setTransferState(ERW_inWork); + } + DcmTag newTag; + OFBool readStopElem = OFFalse; + /* start a loop in order to read all elements (attributes) which are contained in the inStream */ + while (inStream.good() && (getTransferredBytes() < getLengthField() || !lastElementComplete) && !readStopElem) + { + /* initialize variables */ + Uint32 newValueLength = 0; + Uint32 bytes_tagAndLen = 0; + /* if the reading of the last element was complete, go ahead and read the next element */ + if (lastElementComplete) + { + /* read this element's tag and length information */ + /* (and possibly also VR information) from the inStream */ + errorFlag = readTagAndLength(inStream, xfer, newTag, newValueLength, bytes_tagAndLen); + /* increase counter correspondingly */ + incTransferredBytes(bytes_tagAndLen); + + /* if desired, try to ignore parse error -> skip item */ + if ((errorFlag == EC_ElemLengthLargerThanItem) && dcmIgnoreParsingErrors.get()) + { + DCMDATA_WARN("DcmItem: Element " << newTag.getTagName() << " " << newTag + << " too large, trying to skip over rest of item"); + /* we can call getLengthField because error does only occur for explicit length items */ + const offile_off_t bytesToSkip = getLengthField() - bytes_tagAndLen; + if (bytesToSkip > inStream.avail()) // no chance to recover + break; + inStream.skip(bytesToSkip); + errorFlag = EC_Normal; + } + /* if desired, accept premature sequence delimitation item and continue as if item has been completely read. */ + /* The stream position has been rewound to the start position of the sequence end */ + /* delimiter tag in order to let DcmSequenceOfItems handle the delimiter in the reading routine. */ + else if ( (errorFlag == EC_PrematureSequDelimitationItem) && dcmIgnoreParsingErrors.get() ) + { + DCMDATA_WARN("DcmItem: Sequence delimitation occured before all bytes announced by explicit item length could be read" + << ", trying to continue as if item was completely read"); + errorFlag = EC_ItemEnd; // make sure that error code leads to normal return from item reading loop + break; // we are completed with the item since sequence is closed + } + else /* continue with normal case: parse rest of element */ + { + /* if there was an error while we were reading from the stream, terminate the while-loop */ + /* (note that if the last element had been read from the inStream in the last iteration, */ + /* another iteration will be started, and of course then readTagAndLength(...) above will */ + /* return that it encountered the end of the stream. It is only then (and here) when the */ + /* while loop will be terminated.) */ + if (errorFlag.bad()) + break; + /* If we get to this point, we just started reading the first part */ + /* of an element; hence, lastElementComplete is not longer true */ + lastElementComplete = OFFalse; + /* in case of implicit VR, check whether the "default VR" is really appropriate */ + if (DcmXfer(xfer).isImplicitVR()) + checkAndUpdateVR(*this, newTag); + /* read the actual data value which belongs to this element */ + /* (attribute) and insert this information into the elementList */ + errorFlag = readSubElement(inStream, newTag, newValueLength, xfer, glenc, maxReadLength); + /* if reading was successful, we read the entire data value information */ + /* for this element; hence lastElementComplete is true again */ + if (errorFlag.good()) + lastElementComplete = OFTrue; + } + } else + { + /* if lastElementComplete is false, we have only read the current element's */ + /* tag and length (and possibly VR) information as well as maybe some data */ + /* data value information. We need to continue reading the data value */ + /* information for this particular element. */ + errorFlag = elementList->get()->read(inStream, xfer, glenc, maxReadLength); + /* if reading was successful, we read the entire information */ + /* for this element; hence lastElementComplete is true */ + if (errorFlag.good()) + lastElementComplete = OFTrue; + } + /* remember how many bytes were read */ + setTransferredBytes(OFstatic_cast(Uint32, inStream.tell() - fStartPosition)); + if (errorFlag.good()) + { + // If we completed one element, update the private tag cache. + if (lastElementComplete) + { + privateCreatorCache.updateCache(elementList->get()); + // evaluate option for skipping rest of dataset + if ( (dcmStopParsingAfterElement.get() != DCM_UndefinedTagKey) && + (dcmStopParsingAfterElement.get() == elementList->get()->getTag()) && + ident() == EVR_dataset) + { + DCMDATA_WARN("DcmItem: Element " << newTag.getTagName() << " " << newTag + << " encountered, skipping rest of dataset"); + readStopElem = OFTrue; + } + } + } else + break; // if some error was encountered terminate the while-loop + } //while + + /* determine an appropriate result value; note that if the above called read function */ + /* encountered the end of the stream before all information for this element could be */ + /* read from the stream, the errorFlag has already been set to EC_StreamNotifyClient. */ + if (errorFlag.good()) + { + // if stop element was read or end of stream occurs, tell parser end of stream is reached + if (readStopElem || inStream.eos()) + errorFlag = EC_EndOfStream; + // if all bytes could be read or last element read could not be completed, set to error + else if ((getTransferredBytes() < getLengthField() || !lastElementComplete)) + errorFlag = EC_StreamNotifyClient; + } + } // else errorFlag + /* modify the result value: three kinds of special error codes do not count as an error */ + if (errorFlag == EC_ItemEnd || errorFlag == EC_EndOfStream) + errorFlag = EC_Normal; + else if (errorFlag == EC_SequEnd) + { + if (dcmIgnoreParsingErrors.get()) + { + /* do not treat the missing delimiter as an error */ + errorFlag = EC_Normal; + } else + errorFlag = EC_ItemDelimitationItemMissing; + } + + /* if at this point the error flag indicates success, the item has */ + /* been read completely; hence, set the transfer state to ERW_ready. */ + /* Note that all information for this element could be read from the */ + /* stream, the errorFlag is still set to EC_StreamNotifyClient. */ + if (errorFlag.good()) + setTransferState(ERW_ready); + + /* dump information if required */ + DCMDATA_TRACE("DcmItem::read() returns error = " << errorFlag.text()); + + /* return result value */ + return errorFlag; +} + + +// ******************************** + + +OFCondition DcmItem::write(DcmOutputStream &outStream, + const E_TransferSyntax oxfer, + const E_EncodingType enctype, + DcmWriteCache *wcache) +{ + if (getTransferState() == ERW_notInitialized) + errorFlag = EC_IllegalCall; + else + { + errorFlag = outStream.status(); + if (errorFlag.good() && getTransferState() != ERW_ready) + { + if (getTransferState() == ERW_init) + { + if (outStream.avail() >= 8) + { + if (enctype == EET_ExplicitLength) + setLengthField(getLength(oxfer, enctype)); + else + setLengthField(DCM_UndefinedLength); + if (errorFlag == EC_SeqOrItemContentOverflow) + return errorFlag; + errorFlag = writeTag(outStream, getTag(), oxfer); + Uint32 valueLength = getLengthField(); + DcmXfer outXfer(oxfer); + const E_ByteOrder oByteOrder = outXfer.getByteOrder(); + if (oByteOrder == EBO_unknown) return EC_IllegalCall; + swapIfNecessary(oByteOrder, gLocalByteOrder, &valueLength, 4, 4); + outStream.write(&valueLength, 4); // 4 bytes length + elementList->seek(ELP_first); + setTransferState(ERW_inWork); + } else + errorFlag = EC_StreamNotifyClient; + } + if (getTransferState() == ERW_inWork) + { + // elementList->get() can be NULL if buffer was full after + // writing the last item but before writing the sequence delimitation. + if (!elementList->empty() && (elementList->get() != NULL)) + { + DcmObject *dO = NULL; + do + { + dO = elementList->get(); + if (dO->transferState() != ERW_ready) + errorFlag = dO->write(outStream, oxfer, enctype, wcache); + } while (errorFlag.good() && elementList->seek(ELP_next)); + } + if (errorFlag.good()) + { + setTransferState(ERW_ready); + if (getLengthField() == DCM_UndefinedLength) + { + if (outStream.avail() >= 8) + { + // write Item delimitation + DcmTag delim(DCM_ItemDelimitationItemTag); + errorFlag = writeTag(outStream, delim, oxfer); + Uint32 delimLen = 0L; + outStream.write(&delimLen, 4); // 4 bytes length + } + else + { + // Every subelement of the item is written but it + // is not possible to write the delimitation item into the buffer. + errorFlag = EC_StreamNotifyClient; + setTransferState(ERW_inWork); + } + } + } + } + } + } + return errorFlag; +} + + +// ******************************** + + +OFCondition DcmItem::writeSignatureFormat(DcmOutputStream &outStream, + const E_TransferSyntax oxfer, + const E_EncodingType enctype, + DcmWriteCache *wcache) +{ + if (getTransferState() == ERW_notInitialized) + errorFlag = EC_IllegalCall; + else + { + errorFlag = outStream.status(); + if (errorFlag.good() && getTransferState() != ERW_ready) + { + if (getTransferState() == ERW_init) + { + if (outStream.avail() >= 4) + { + if (enctype == EET_ExplicitLength) + setLengthField(getLength(oxfer, enctype)); + else + setLengthField(DCM_UndefinedLength); + errorFlag = writeTag(outStream, getTag(), oxfer); + /* we don't write the item length */ + elementList->seek(ELP_first); + setTransferState(ERW_inWork); + } else + errorFlag = EC_StreamNotifyClient; + } + if (getTransferState() == ERW_inWork) + { + // elementList->get() can be NULL if buffer was full after + // writing the last item but before writing the sequence delimitation. + if (!elementList->empty() && (elementList->get() != NULL)) + { + DcmObject *dO = NULL; + do + { + dO = elementList->get(); + if (dO->transferState() != ERW_ready) + errorFlag = dO->writeSignatureFormat(outStream, oxfer, enctype, wcache); + } while (errorFlag.good() && elementList->seek(ELP_next)); + } + if (errorFlag.good()) + { + setTransferState(ERW_ready); + /* we don't write an item delimitation even if the item has undefined length */ + } + } + } + } + return errorFlag; +} + + +// ******************************** + + +OFBool DcmItem::isNested() const +{ + OFBool nested = OFFalse; + if (getParent() != NULL) + { + // check for surrounding structure of sequence of items + const DcmEVR parentIdent = getParent()->ident(); + if ((parentIdent == EVR_SQ) || (parentIdent == EVR_pixelSQ)) + nested = OFTrue; + } + return nested; +} + + +DcmItem *DcmItem::getParentItem() +{ + DcmItem *parentItem = NULL; + if (getParent() != NULL) + { + // make sure that the direct parent has the correct type + const DcmEVR parentIdent = getParent()->ident(); + if ((parentIdent == EVR_SQ) || (parentIdent == EVR_pixelSQ)) + { + DcmObject *parent = getParent()->getParent(); + if (parent != NULL) + { + // make sure that it is really a class derived from DcmItem + switch (parent->ident()) + { + case EVR_metainfo: + case EVR_dataset: + case EVR_item: + case EVR_dirRecord: + parentItem = OFreinterpret_cast(DcmItem *, parent); + break; + default: + DCMDATA_DEBUG("DcmItem::getParentItem() Parent object has wrong class identifier: " + << OFstatic_cast(int, parent->ident()) + << " (" << DcmVR(parent->ident()).getVRName() << ")"); + break; + } + } + // When our parent is a fileformat, we should be a dataset or a metainfo. + // In these cases, there really is no parent item, so no message. + } else if (parentIdent != EVR_fileFormat) { + DCMDATA_DEBUG("DcmItem::getParentItem() Direct parent object is not a sequence element"); + } + } + return parentItem; +} + + +// ******************************** + + +void DcmItem::transferInit() +{ + DcmObject::transferInit(); + fStartPosition = 0; + lastElementComplete = OFTrue; + privateCreatorCache.clear(); + if (!elementList->empty()) + { + elementList->seek(ELP_first); + do { + elementList->get()->transferInit(); + } while (elementList->seek(ELP_next)); + } +} + + +void DcmItem::transferEnd() +{ + DcmObject::transferEnd(); + privateCreatorCache.clear(); + if (!elementList->empty()) + { + elementList->seek(ELP_first); + do { + elementList->get()->transferEnd(); + } while (elementList->seek(ELP_next)); + } +} + + +// ******************************** + + +unsigned long DcmItem::card() const +{ + return elementList->card(); +} + + +// ******************************** + + +OFCondition DcmItem::insert(DcmElement *elem, + OFBool replaceOld, + OFBool checkInsertOrder) +{ + /* initialize error flag with ok */ + errorFlag = EC_Normal; + /* do something only if the pointer which was passed does not equal NULL */ + if (elem != NULL) + { + DcmElement *dE; + E_ListPos seekmode = ELP_last; + /* iterate through elementList (from the last element to the first) */ + do { + /* get current element from elementList */ + dE = OFstatic_cast(DcmElement *, elementList->seek(seekmode)); + /* if there is no element, i.e. elementList is empty */ + if (dE == NULL) + { + /* insert new element at the beginning of elementList */ + elementList->insert(elem, ELP_first); + if (checkInsertOrder) + { + // check if we have inserted at the end of the list + if (elem != OFstatic_cast(DcmElement *, elementList->seek(ELP_last))) + { + // produce diagnostics + DCMDATA_WARN("DcmItem: Dataset not in ascending tag order, at element " << elem->getTag()); + } + } + /* dump some information if required */ + DCMDATA_TRACE("DcmItem::insert() Element " << elem->getTag() + << " VR=\"" << DcmVR(elem->getVR()).getVRName() << "\" inserted at beginning"); + /* check whether the new element already has a parent */ + if (elem->getParent() != NULL) + { + DCMDATA_DEBUG("DcmItem::insert() Element " << elem->getTag() << " already has a parent: " + << elem->getParent()->getTag() << " VR=" << DcmVR(elem->getParent()->getVR()).getVRName()); + } + /* remember the parent (i.e. the surrounding item/dataset) */ + elem->setParent(this); + /* terminate do-while-loop */ + break; + } + /* else if the new element's tag is greater than the current element's tag */ + /* (i.e. we have found the position where the new element shall be inserted) */ + else if (elem->getTag() > dE->getTag()) + { + /* insert the new element after the current element */ + elementList->insert(elem, ELP_next); + if (checkInsertOrder) + { + // check if we have inserted at the end of the list + if (elem != OFstatic_cast(DcmElement *, elementList->seek(ELP_last))) + { + // produce diagnostics + DCMDATA_WARN("DcmItem: Dataset not in ascending tag order, at element " << elem->getTag()); + } + } + /* dump some information if required */ + DCMDATA_TRACE("DcmItem::insert() Element " << elem->getTag() + << " VR=\"" << DcmVR(elem->getVR()).getVRName() << "\" inserted"); + /* check whether the new element already has a parent */ + if (elem->getParent() != NULL) + { + DCMDATA_DEBUG("DcmItem::insert() Element " << elem->getTag() << " already has a parent: " + << elem->getParent()->getTag() << " VR=" << DcmVR(elem->getParent()->getVR()).getVRName()); + } + /* remember the parent (i.e. the surrounding item/dataset) */ + elem->setParent(this); + /* terminate do-while-loop */ + break; + } + /* else if the current element and the new element show the same tag */ + else if (elem->getTag() == dE->getTag()) + { + /* if new and current element are not identical */ + if (elem != dE) + { + /* if the current (old) element shall be replaced */ + if (replaceOld) + { + /* remove current element from list */ + DcmObject *remObj = elementList->remove(); + + /* now the following holds: remObj == dE and elementList */ + /* points to the element after the former current element. */ + + /* if the pointer to the removed object does not */ + /* equal NULL (the usual case), delete this object */ + /* and dump some information if required */ + if (remObj != NULL) + { + /* dump some information if required */ + DCMDATA_TRACE("DcmItem::insert() Element " << remObj->getTag() + << " VR=\"" << DcmVR(remObj->getVR()).getVRName() + << "\" p=" << OFstatic_cast(void *, remObj) << " removed and deleted"); + delete remObj; + } + /* insert the new element before the current element */ + elementList->insert(elem, ELP_prev); + /* dump some information if required */ + DCMDATA_TRACE("DcmItem::insert() Element " << elem->getTag() + << " VR=\"" << DcmVR(elem->getVR()).getVRName() + << "\" p=" << OFstatic_cast(void *, elem) << " replaced older one"); + /* check whether the new element already has a parent */ + if (elem->getParent() != NULL) + { + DCMDATA_DEBUG("DcmItem::insert() Element " << elem->getTag() << " already has a parent: " + << elem->getParent()->getTag() << " VR=" << DcmVR(elem->getParent()->getVR()).getVRName()); + } + /* remember the parent (i.e. the surrounding item/dataset) */ + elem->setParent(this); + } // if (replaceOld) + /* or else, i.e. the current element shall not be replaced by the new element */ + else { + /* set the error flag correspondingly; we do not */ + /* allow two elements with the same tag in elementList */ + errorFlag = EC_DoubledTag; + } // if (!replaceOld) + } // if (elem != dE) + /* if the new and the current element are identical, the caller tries to insert */ + /* one element twice. Most probably an application error. */ + else { + errorFlag = EC_DoubledTag; + } + /* terminate do-while-loop */ + break; + } + /* set the seek mode to "get the previous element" */ + seekmode = ELP_prev; + } while (dE); + } + /* if the pointer which was passed equals NULL, this is an illegal call */ + else + errorFlag = EC_IllegalCall; + /* return result value */ + return errorFlag; +} + + +// ******************************** + + +DcmElement *DcmItem::getElement(const unsigned long num) +{ + errorFlag = EC_Normal; + DcmElement *elem; + elem = OFstatic_cast(DcmElement *, elementList->seek_to(num)); + /* reads element from list */ + if (elem == NULL) + errorFlag = EC_IllegalCall; + return elem; +} + + +// ******************************** + + +DcmObject *DcmItem::nextInContainer(const DcmObject *obj) +{ + if (!obj) + return elementList->get(ELP_first); + else + { + if (elementList->get() != obj) + { + for(DcmObject * search_obj = elementList->seek(ELP_first); + search_obj && search_obj != obj; + search_obj = elementList->seek(ELP_next) + ) { + /* do nothing, just keep iterating */ + } + } + return elementList->seek(ELP_next); + } +} + + +// ******************************** + + +OFCondition DcmItem::nextObject(DcmStack &stack, + const OFBool intoSub) +{ + OFCondition l_error = EC_Normal; + DcmObject * container = NULL; + DcmObject * obj = NULL; + DcmObject * result = NULL; + OFBool examSub = intoSub; + + if (stack.empty()) + { + stack.push(this); + examSub = OFTrue; + } + + obj = stack.top(); + if (obj->isLeaf() || !intoSub) + { + stack.pop(); + if (stack.card() > 0) + { + container = stack.top(); + result = container->nextInContainer(obj); + } + } else if (examSub) + result = obj->nextInContainer(NULL); + + if (result) + stack.push(result); + else if (intoSub) + l_error = nextUp(stack); + else + l_error = EC_SequEnd; + + return l_error; +} + + +// ******************************** + + +DcmElement *DcmItem::remove(const unsigned long num) +{ + errorFlag = EC_Normal; + DcmElement *elem; + elem = OFstatic_cast(DcmElement *, elementList->seek_to(num)); + // read element from list + if (elem != NULL) + { + elementList->remove(); // removes element from list but does not delete it + elem->setParent(NULL); // forget about the parent + } else + errorFlag = EC_IllegalCall; + return elem; +} + + +// ******************************** + + +DcmElement *DcmItem::remove(DcmObject *elem) +{ + errorFlag = EC_IllegalCall; + if (!elementList->empty() && elem != NULL) + { + DcmObject *dO; + elementList->seek(ELP_first); + do { + dO = elementList->get(); + if (dO == elem) + { + elementList->remove(); // removes element from list but does not delete it + elem->setParent(NULL); // forget about the parent + errorFlag = EC_Normal; + break; + } + } while (elementList->seek(ELP_next)); + } + if (errorFlag == EC_IllegalCall) + return NULL; + else + return OFstatic_cast(DcmElement *, elem); +} + + +// ******************************** + + +DcmElement *DcmItem::remove(const DcmTagKey &tag) +{ + errorFlag = EC_TagNotFound; + DcmObject *dO = NULL; + if (!elementList->empty()) + { + elementList->seek(ELP_first); + do { + dO = elementList->get(); + if (dO->getTag() == tag) + { + elementList->remove(); // removes element from list but does not delete it + dO->setParent(NULL); // forget about the parent + errorFlag = EC_Normal; + break; + } + } while (elementList->seek(ELP_next)); + } + + if (errorFlag == EC_TagNotFound) + return NULL; + else + return OFstatic_cast(DcmElement *, dO); +} + + +// ******************************** + + +OFCondition DcmItem::clear() +{ + errorFlag = EC_Normal; + // remove all elements from item and delete them from memory + elementList->deleteAllElements(); + setLengthField(0); + + return errorFlag; +} + + +OFBool DcmItem::isEmpty(const OFBool /*normalize*/) +{ + return elementList->empty(); +} + + +// ******************************** + + +OFCondition DcmItem::verify(const OFBool autocorrect) +{ + errorFlag = EC_Normal; + if (!elementList->empty()) + { + DcmObject *dO; + elementList->seek(ELP_first); + do { + dO = elementList->get(); + if (dO->verify(autocorrect).bad()) + errorFlag = EC_CorruptedData; + } while (elementList->seek(ELP_next)); + } + if (autocorrect) + setLengthField(getLength()); + return errorFlag; +} + + +// ******************************** + +// Precondition: elementList is non-empty! +// Result: - return EC_Normal; +// push element pointer on resultStack +// - return EC_TagNotFound; +// resultStack unmodified +// Search again: push pointer of sub-element on resultStack and +// start sub-search + +OFCondition DcmItem::searchSubFromHere(const DcmTagKey &tag, + DcmStack &resultStack, + OFBool searchIntoSub) +{ + DcmObject *dO; + OFCondition l_error = EC_TagNotFound; + if (!elementList->empty()) + { + elementList->seek(ELP_first); + do { + dO = elementList->get(); + if (searchIntoSub) + { + resultStack.push(dO); + if (dO->getTag() == tag) + l_error = EC_Normal; + else + l_error = dO->search(tag, resultStack, ESM_fromStackTop, OFTrue); + if (l_error.bad()) + resultStack.pop(); + } else { + if (dO->getTag() == tag) + { + resultStack.push(dO); + l_error = EC_Normal; + } + } + } while (l_error.bad() && elementList->seek(ELP_next)); + if (l_error==EC_Normal && dO->getTag()==tag) + { + DCMDATA_TRACE("DcmItem::searchSubFromHere() Element " << tag << " found"); + } + } + return l_error; +} + + +// ******************************** + + +OFCondition DcmItem::search(const DcmTagKey &tag, + DcmStack &resultStack, + E_SearchMode mode, + OFBool searchIntoSub) +{ + DcmObject *dO = NULL; + OFCondition l_error = EC_TagNotFound; + if (mode == ESM_afterStackTop && resultStack.top() == this) + { + l_error = searchSubFromHere(tag, resultStack, searchIntoSub); + } + else if (!elementList->empty()) + { + if (mode == ESM_fromHere || resultStack.empty()) + { + resultStack.clear(); + l_error = searchSubFromHere(tag, resultStack, searchIntoSub); + } + else if (mode == ESM_fromStackTop) + { + dO = resultStack.top(); + if (dO == this) + l_error = searchSubFromHere(tag, resultStack, searchIntoSub); + else + { // gehe direkt zu Sub-Baum und suche dort weiter + l_error = dO->search(tag, resultStack, mode, searchIntoSub); +// The next two lines destroy the stack->so delete them +// if (l_error.bad()) // raeumt nur die oberste Stackebene +// resultStack.pop(); // ab; der Rest ist unveraendert + } + } + else if (mode == ESM_afterStackTop && searchIntoSub) + { + // resultStack enthaelt Zielinformationen: + // - stelle Zustand der letzen Suche in den einzelnen Suchroutinen + // wieder her + // - finde Position von dO in Baum-Struktur + // 1. suche eigenen Stack-Eintrag + // - bei Fehlschlag Suche beenden + // 2. nehme naechsthoeheren Eintrag dnO + // 3. stelle eigene Liste auf Position von dnO + // 4. starte Suche ab dnO + + unsigned long i = resultStack.card(); + while (i > 0 && (dO = resultStack.elem(i-1)) != this) + { + i--; + } + if (dO != this && resultStack.card() > 0) + { // oberste Ebene steht nie in resultStack + i = resultStack.card()+1;// zeige jetzt auf hoechste Ebene+1 + dO = this; // Treffer der hoechsten Ebene! + } + if (dO == this) + { + if (i == 1) // habe resultStack.top() gefunden + l_error = EC_TagNotFound; // markiere als kein Treffer, s.o. + else // siehe oben + { + E_SearchMode submode = mode; + OFBool searchNode = OFTrue; + DcmObject *dnO; + dnO = resultStack.elem(i - 2); // Knoten der naechsten Ebene + elementList->seek(ELP_first); + do { + dO = elementList->get(); + searchNode = searchNode ? (dO != dnO) : OFFalse; + if (!searchNode) + { // suche jetzt weiter + if (submode == ESM_fromStackTop) + resultStack.push(dO); // Stack aktualisieren + if (submode == ESM_fromStackTop && dO->getTag() == tag) + l_error = EC_Normal; + else + l_error = dO->search(tag, resultStack, submode, OFTrue); + if (l_error.bad()) + resultStack.pop(); + else + break; + submode = ESM_fromStackTop; // ab hier normale Suche + } + } while (elementList->seek(ELP_next)); + } + } else + l_error = EC_IllegalCall; + } // (mode == ESM_afterStackTop + else + l_error = EC_IllegalCall; + } + return l_error; +} + + +// ******************************** + + +OFCondition DcmItem::loadAllDataIntoMemory() +{ + OFCondition l_error = EC_Normal; + if (!elementList->empty()) + { + elementList->seek(ELP_first); + do { + OFCondition err = EC_Normal; + DcmObject *dO = elementList->get(); + if ((err = dO->loadAllDataIntoMemory()).bad()) + l_error = err; + } while (elementList->seek(ELP_next)); + } + return l_error; +} + + +// ******************************** + + +void DcmItem::compactElements(const Uint32 maxLength) +{ + DcmStack stack; + DcmObject *object = NULL; + /* iterate over all elements */ + while (nextObject(stack, OFTrue).good()) + { + object = stack.top(); + // compact element if maximum length is exceeded + if (object->isLeaf() && (object->getLength() > maxLength)) + OFstatic_cast(DcmElement *, object)->compact(); + } +} + + +// ******************************** + +// Support functions + +OFCondition newDicomElement(DcmElement *&newElement, + const DcmTag &tag, + const Uint32 length) +{ + DcmTag newTag(tag); + OFBool readAsUN = OFFalse; + return newDicomElement(newElement, newTag, length, NULL, readAsUN); +} + +DcmElement *newDicomElement(const DcmTag &tag, + const Uint32 length) +{ + DcmElement *newElement = NULL; + newDicomElement(newElement, tag, length); + return newElement; +} + + +// ******************************** + + +OFCondition newDicomElement(DcmElement *&newElement, + DcmTag &tag, + const Uint32 length, + DcmPrivateTagCache *privateCreatorCache, + OFBool& readAsUN) +{ + /* initialize variables */ + OFCondition l_error = EC_Normal; + newElement = NULL; + DcmEVR evr = tag.getEVR(); + readAsUN = OFFalse; + + /* revert UN elements with finite length back to known VR if possible */ + if ((evr == EVR_UN) && (length != DCM_UndefinedLength) && dcmEnableUnknownVRConversion.get()) + { + /* look up VR in data dictionary */ + DcmTag newTag(tag.getGroup(), tag.getElement()); + + /* special handling for private elements */ + if (privateCreatorCache && (newTag.getGroup() & 1) && (newTag.getElement() >= 0x1000)) + { + const char *pc = privateCreatorCache->findPrivateCreator(newTag); + if (pc != NULL) + { + // we have a private creator for this element + newTag.setPrivateCreator(pc); + newTag.lookupVRinDictionary(); + } + } + + /* update VR for tag, set "readAsUN" flag that makes sure the element value + * is read in Little Endian Implicit VR (i.e. the UN encoding) + */ + if (newTag.getEVR() != EVR_UNKNOWN) + { + tag.setVR(newTag.getVR()); + evr = tag.getEVR(); + readAsUN = OFTrue; + } + } + + /* depending on the VR of the tag which was passed, create the new object */ + switch (evr) + { + // byte strings: + case EVR_AE : + newElement = new DcmApplicationEntity(tag, length); + break; + case EVR_AS : + newElement = new DcmAgeString(tag, length); + break; + case EVR_CS : + newElement = new DcmCodeString(tag, length); + break; + case EVR_DA : + newElement = new DcmDate(tag, length); + break; + case EVR_DS : + newElement = new DcmDecimalString(tag, length); + break; + case EVR_DT : + newElement = new DcmDateTime(tag, length); + break; + case EVR_IS : + newElement = new DcmIntegerString(tag, length); + break; + case EVR_TM : + newElement = new DcmTime(tag, length); + break; + case EVR_UI : + newElement = new DcmUniqueIdentifier(tag, length); + break; + case EVR_UR: + newElement = new DcmUniversalResourceIdentifierOrLocator(tag, length); + break; + + // character strings: + case EVR_LO : + newElement = new DcmLongString(tag, length); + break; + case EVR_LT : + newElement = new DcmLongText(tag, length); + break; + case EVR_PN : + newElement = new DcmPersonName(tag, length); + break; + case EVR_SH : + newElement = new DcmShortString(tag, length); + break; + case EVR_ST : + newElement = new DcmShortText(tag, length); + break; + case EVR_UC: + newElement = new DcmUnlimitedCharacters(tag, length); + break; + case EVR_UT: + newElement = new DcmUnlimitedText(tag, length); + break; + + // dependent on byte order: + case EVR_AT : + newElement = new DcmAttributeTag(tag, length); + break; + case EVR_SS : + newElement = new DcmSignedShort(tag, length); + break; + case EVR_xs : // according to DICOM standard + case EVR_US : + newElement = new DcmUnsignedShort(tag, length); + break; + case EVR_SL : + newElement = new DcmSignedLong(tag, length); + break; + case EVR_up : // for (0004,eeee) according to DICOM standard + case EVR_UL : + { + // generate tag with VR from dictionary! + DcmTag ulupTag(tag.getXTag()); + if (ulupTag.getEVR() == EVR_up) + newElement = new DcmUnsignedLongOffset(ulupTag, length); + else + newElement = new DcmUnsignedLong(tag, length); + } + break; + case EVR_FL : + newElement = new DcmFloatingPointSingle(tag, length); + break; + case EVR_FD : + newElement = new DcmFloatingPointDouble(tag, length); + break; + case EVR_OF : + newElement = new DcmOtherFloat(tag, length); + break; + case EVR_OD : + newElement = new DcmOtherDouble(tag, length); + break; + + // sequences and items: + case EVR_SQ : + newElement = new DcmSequenceOfItems(tag, length); + break; + case EVR_na : + if (tag.getXTag() == DCM_Item) + l_error = EC_InvalidTag; + else if (tag.getXTag() == DCM_SequenceDelimitationItem) + l_error = EC_SequEnd; + else if (tag.getXTag() == DCM_ItemDelimitationItem) + l_error = EC_ItemEnd; + else + l_error = EC_InvalidTag; + break; + + // pixel sequences (EVR_pixelSQ) are handled through class DcmPixelData + // and should never appear here. + + // unclear 8 or 16 bit: + case EVR_ox : + if (tag == DCM_PixelData) + newElement = new DcmPixelData(tag, length); + else if (tag.getBaseTag() == DCM_OverlayData) + newElement = new DcmOverlayData(tag, length); + else + /* we don't know this element's real transfer syntax, so we just + * use the defaults of class DcmOtherByteOtherWord and let the + * application handle it. + */ + newElement = new DcmOtherByteOtherWord(tag, length); + break; + + case EVR_lt : + newElement = new DcmOtherByteOtherWord(tag, length); + break; + + case EVR_OB : + case EVR_OW : + if (tag == DCM_PixelData) + newElement = new DcmPixelData(tag, length); + else if (tag.getBaseTag() == DCM_OverlayData) + newElement = new DcmOverlayData(tag, length); + else + if (length == DCM_UndefinedLength) + { + // The attribute is OB or OW but is encoded with undefined + // length. Assume it is really a sequence so that we can + // catch the sequence delimitation item. + newElement = new DcmSequenceOfItems(tag, length); + } else { + newElement = new DcmOtherByteOtherWord(tag, length); + } + break; + + // read unknown types as byte string: + case EVR_UNKNOWN : + case EVR_UNKNOWN2B : + case EVR_UN : + default : + if (length == DCM_UndefinedLength) + { + // The attribute VR is UN with undefined length. Assume it is really + // a sequence so that we can catch the sequence delimitation item. + DcmTag newTag(tag); + newTag.setVR(DcmVR(EVR_SQ)); // on writing we will handle this element as SQ, not UN + if (dcmEnableCP246Support.get()) + { + DCMDATA_WARN("Found element " << newTag << " with VR UN and undefined length, " + << "reading a sequence with transfer syntax LittleEndianImplicit (CP-246)"); + } else { + DCMDATA_WARN("Found element " << newTag << " with VR UN and undefined length"); + } + newElement = new DcmSequenceOfItems(newTag, length, dcmEnableCP246Support.get()); + } else { + // defined length UN element, treat like OB + newElement = new DcmOtherByteOtherWord(tag, length); + } + break; + } + + /* check for valid element pointer */ + if (l_error.good() && (newElement == NULL)) + l_error = EC_MemoryExhausted; + + /* return result value */ + return l_error; +} + + +OFCondition nextUp(DcmStack &stack) +{ + DcmObject *oldContainer = stack.pop(); + if (oldContainer->isLeaf()) + return EC_IllegalCall; + else if (!stack.empty()) + { + DcmObject *container = stack.top(); + DcmObject *result = container->nextInContainer(oldContainer); + if (result) + { + stack.push(result); + return EC_Normal; + } + else + return nextUp(stack); + } + return EC_TagNotFound; +} + + +/* +** Simple tests for existence +*/ + +OFBool DcmItem::tagExists(const DcmTagKey &key, + OFBool searchIntoSub) +{ + DcmStack stack; + + OFCondition ec = search(key, stack, ESM_fromHere, searchIntoSub); + return (ec.good()); +} + + +OFBool DcmItem::tagExistsWithValue(const DcmTagKey &key, + OFBool searchIntoSub) +{ + DcmStack stack; + OFBool result = OFFalse; + + if (search(key, stack, ESM_fromHere, searchIntoSub).good()) + { + DcmElement *elem = OFstatic_cast(DcmElement *, stack.top()); + if (elem != NULL) + result = !(elem->isEmpty()); + } + + return result; +} + + +// ******************************** + +/* --- findAndGet functions: find an element and get it or the value, respectively --- */ + +OFCondition DcmItem::findAndGetElement(const DcmTagKey &tagKey, + DcmElement *&element, + const OFBool searchIntoSub, + const OFBool createCopy) +{ + DcmStack stack; + /* find the element */ + OFCondition status = search(tagKey, stack, ESM_fromHere, searchIntoSub); + if (status.good()) + { + element = OFstatic_cast(DcmElement *, stack.top()); + /* should never happen but ... */ + if (element == NULL) + status = EC_CorruptedData; + else if (createCopy) + { + /* create a copy of the element */ + element = OFstatic_cast(DcmElement *, element->clone()); + if (element == NULL) + status = EC_MemoryExhausted; + } + } else { + /* reset element pointer */ + element = NULL; + } + return status; +} + + +OFCondition DcmItem::findAndGetElements(const DcmTagKey &tagKey, + DcmStack &resultStack) +{ + OFCondition status = EC_TagNotFound; + DcmStack stack; + DcmObject *object = NULL; + /* iterate over all elements */ + while (nextObject(stack, OFTrue).good()) + { + /* get element */ + object = stack.top(); + if (object->getTag() == tagKey) + { + /* add it to the result stack */ + resultStack.push(object); + status = EC_Normal; + } + } + return status; +} + + +OFCondition DcmItem::findAndGetString(const DcmTagKey& tagKey, + const char *&value, + const OFBool searchIntoSub) +{ + DcmElement *elem; + /* find the element */ + OFCondition status = findAndGetElement(tagKey, elem, searchIntoSub); + if (status.good()) + { + /* get the value */ + status = elem->getString(OFconst_cast(char *&, value)); + } + /* reset value */ + if (status.bad()) + value = NULL; + return status; +} + + +OFCondition DcmItem::findAndGetString(const DcmTagKey& tagKey, + const char *&value, + Uint32 &length, + const OFBool searchIntoSub) +{ + DcmElement *elem; + /* find the element */ + OFCondition status = findAndGetElement(tagKey, elem, searchIntoSub); + if (status.good()) + { + /* get the value */ + status = elem->getString(OFconst_cast(char *&, value), length); + } + /* reset values */ + if (status.bad()) + { + value = NULL; + length = 0; + } + return status; +} + + +OFCondition DcmItem::findAndGetOFString(const DcmTagKey& tagKey, + OFString &value, + const unsigned long pos, + const OFBool searchIntoSub) +{ + DcmElement *elem; + /* find the element */ + OFCondition status = findAndGetElement(tagKey, elem, searchIntoSub); + if (status.good()) + { + /* get the value */ + status = elem->getOFString(value, pos); + } + /* reset value */ + if (status.bad()) + value.clear(); + return status; +} + + +OFCondition DcmItem::findAndGetOFStringArray(const DcmTagKey& tagKey, + OFString &value, + const OFBool searchIntoSub) +{ + DcmElement *elem; + /* find the element */ + OFCondition status = findAndGetElement(tagKey, elem, searchIntoSub); + if (status.good()) + { + /* get the value */ + status = elem->getOFStringArray(value); + } + /* reset value */ + if (status.bad()) + value.clear(); + return status; +} + + +OFCondition DcmItem::findAndGetUint8(const DcmTagKey& tagKey, + Uint8 &value, + const unsigned long pos, + const OFBool searchIntoSub) +{ + DcmElement *elem; + /* find the element */ + OFCondition status = findAndGetElement(tagKey, elem, searchIntoSub); + if (status.good()) + { + /* get the value */ + status = elem->getUint8(value, pos); + } + /* reset value */ + if (status.bad()) + value = 0; + return status; +} + + +OFCondition DcmItem::findAndGetUint8Array(const DcmTagKey& tagKey, + const Uint8 *&value, + unsigned long *count, + const OFBool searchIntoSub) +{ + DcmElement *elem; + /* find the element */ + OFCondition status = findAndGetElement(tagKey, elem, searchIntoSub); + if (status.good()) + { + /* get the value */ + Uint8 *array = NULL; + status = elem->getUint8Array(array); + value = array; + } + /* set optional count parameter */ + if (count != NULL) + { + if (status.good()) + *count = elem->getLength() / OFstatic_cast(unsigned long, sizeof(Uint8)); + else + *count = 0; + } + /* reset value */ + if (status.bad()) + value = NULL; + return status; +} + + +OFCondition DcmItem::findAndGetUint16(const DcmTagKey& tagKey, + Uint16 &value, + const unsigned long pos, + const OFBool searchIntoSub) +{ + DcmElement *elem; + /* find the element */ + OFCondition status = findAndGetElement(tagKey, elem, searchIntoSub); + if (status.good()) + { + /* get the value */ + status = elem->getUint16(value, pos); + } + /* reset value */ + if (status.bad()) + value = 0; + return status; +} + + +OFCondition DcmItem::findAndGetUint16Array(const DcmTagKey& tagKey, + const Uint16 *&value, + unsigned long *count, + const OFBool searchIntoSub) +{ + DcmElement *elem; + /* find the element */ + OFCondition status = findAndGetElement(tagKey, elem, searchIntoSub); + if (status.good()) + { + /* get the value */ + Uint16 *array = NULL; + status = elem->getUint16Array(array); + value = array; + } + /* set optional count parameter */ + if (count != NULL) + { + if (status.good()) + *count = elem->getLength() / OFstatic_cast(unsigned long, sizeof(Uint16)); + else + *count = 0; + } + /* reset value */ + if (status.bad()) + value = NULL; + return status; +} + + +OFCondition DcmItem::findAndGetSint16(const DcmTagKey& tagKey, + Sint16 &value, + const unsigned long pos, + const OFBool searchIntoSub) +{ + DcmElement *elem; + /* find the element */ + OFCondition status = findAndGetElement(tagKey, elem, searchIntoSub); + if (status.good()) + { + /* get the value */ + status = elem->getSint16(value, pos); + } + /* reset value */ + if (status.bad()) + value = 0; + return status; +} + + +OFCondition DcmItem::findAndGetSint16Array(const DcmTagKey& tagKey, + const Sint16 *&value, + unsigned long *count, + const OFBool searchIntoSub) +{ + DcmElement *elem; + /* find the element */ + OFCondition status = findAndGetElement(tagKey, elem, searchIntoSub); + if (status.good()) + { + /* get the value */ + Sint16 *array = NULL; + status = elem->getSint16Array(array); + value = array; + } + /* set optional count parameter */ + if (count != NULL) + { + if (status.good()) + *count = elem->getLength() / OFstatic_cast(unsigned long, sizeof(Sint16)); + else + *count = 0; + } + /* reset value */ + if (status.bad()) + value = NULL; + return status; +} + + +OFCondition DcmItem::findAndGetUint32(const DcmTagKey& tagKey, + Uint32 &value, + const unsigned long pos, + const OFBool searchIntoSub) +{ + DcmElement *elem; + /* find the element */ + OFCondition status = findAndGetElement(tagKey, elem, searchIntoSub); + if (status.good()) + { + /* get the value */ + status = elem->getUint32(value, pos); + } + /* reset value */ + if (status.bad()) + value = 0; + return status; +} + + +OFCondition DcmItem::findAndGetUint32Array(const DcmTagKey& tagKey, + const Uint32 *&value, + unsigned long *count, + const OFBool searchIntoSub) +{ + DcmElement *elem; + /* find the element */ + OFCondition status = findAndGetElement(tagKey, elem, searchIntoSub); + if (status.good()) + { + /* get the value */ + Uint32 *array = NULL; + status = elem->getUint32Array(array); + value = array; + } + /* set optional count parameter */ + if (count != NULL) + { + if (status.good()) + *count = elem->getLength() / OFstatic_cast(unsigned long, sizeof(Uint32)); + else + *count = 0; + } + /* reset value */ + if (status.bad()) + value = NULL; + return status; +} + + +OFCondition DcmItem::findAndGetSint32(const DcmTagKey& tagKey, + Sint32 &value, + const unsigned long pos, + const OFBool searchIntoSub) +{ + DcmElement *elem; + /* find the element */ + OFCondition status = findAndGetElement(tagKey, elem, searchIntoSub); + if (status.good()) + { + /* get the value */ + status = elem->getSint32(value, pos); + } + /* reset value */ + if (status.bad()) + value = 0; + return status; +} + + +OFCondition DcmItem::findAndGetSint32Array(const DcmTagKey& tagKey, + const Sint32 *&value, + unsigned long *count, + const OFBool searchIntoSub) +{ + DcmElement *elem; + /* find the element */ + OFCondition status = findAndGetElement(tagKey, elem, searchIntoSub); + if (status.good()) + { + /* get the value */ + Sint32 *array = NULL; + status = elem->getSint32Array(array); + value = array; + } + /* set optional count parameter */ + if (count != NULL) + { + if (status.good()) + *count = elem->getLength() / OFstatic_cast(unsigned long, sizeof(Sint32)); + else + *count = 0; + } + /* reset value */ + if (status.bad()) + value = NULL; + return status; +} + + +OFCondition DcmItem::findAndGetLongInt(const DcmTagKey& tagKey, + long int &value, + const unsigned long pos, + const OFBool searchIntoSub) +{ + DcmElement *elem; + /* find the element */ + OFCondition status = findAndGetElement(tagKey, elem, searchIntoSub); + if (status.good()) + { + /* distinguish supported VRs */ + switch (elem->ident()) + { + case EVR_UL: + case EVR_up: + Uint32 ul; + status = elem->getUint32(ul, pos); + value = OFstatic_cast(long int, ul); + break; + case EVR_SL: + case EVR_IS: + Sint32 sl; + status = elem->getSint32(sl, pos); + value = OFstatic_cast(long int, sl); + break; + case EVR_US: + case EVR_xs: + case EVR_lt: + Uint16 us; + status = elem->getUint16(us, pos); + value = OFstatic_cast(long int, us); + break; + case EVR_SS: + Sint16 ss; + status = elem->getSint16(ss, pos); + value = OFstatic_cast(long int, ss); + break; + default: + status = EC_IllegalCall; + break; + } + } + /* reset value */ + if (status.bad()) + value = 0; + return status; +} + + +OFCondition DcmItem::findAndGetFloat32(const DcmTagKey& tagKey, + Float32 &value, + const unsigned long pos, + const OFBool searchIntoSub) +{ + DcmElement *elem; + /* find the element */ + OFCondition status = findAndGetElement(tagKey, elem, searchIntoSub); + if (status.good()) + { + /* get the value */ + status = elem->getFloat32(value, pos); + } + /* reset value */ + if (status.bad()) + value = 0; + return status; +} + + +OFCondition DcmItem::findAndGetFloat32Array(const DcmTagKey& tagKey, + const Float32 *&value, + unsigned long *count, + const OFBool searchIntoSub) +{ + DcmElement *elem; + /* find the element */ + OFCondition status = findAndGetElement(tagKey, elem, searchIntoSub); + if (status.good()) + { + /* get the value */ + Float32 *array = NULL; + status = elem->getFloat32Array(array); + value = array; + } + /* set optional count parameter */ + if (count != NULL) + { + if (status.good()) + *count = elem->getLength() / OFstatic_cast(unsigned long, sizeof(Float32)); + else + *count = 0; + } + /* reset value */ + if (status.bad()) + value = NULL; + return status; +} + + +OFCondition DcmItem::findAndGetFloat64(const DcmTagKey& tagKey, + Float64 &value, + const unsigned long pos, + const OFBool searchIntoSub) +{ + DcmElement *elem; + /* find the element */ + OFCondition status = findAndGetElement(tagKey, elem, searchIntoSub); + if (status.good()) + { + /* get the value */ + status = elem->getFloat64(value, pos); + } + /* reset value */ + if (status.bad()) + value = 0; + return status; +} + + +OFCondition DcmItem::findAndGetFloat64Array(const DcmTagKey& tagKey, + const Float64 *&value, + unsigned long *count, + const OFBool searchIntoSub) +{ + DcmElement *elem; + /* find the element */ + OFCondition status = findAndGetElement(tagKey, elem, searchIntoSub); + if (status.good()) + { + /* get the value */ + Float64 *array = NULL; + status = elem->getFloat64Array(array); + value = array; + } + /* set optional count parameter */ + if (count != NULL) + { + if (status.good()) + *count = elem->getLength() / OFstatic_cast(unsigned long, sizeof(Float64)); + else + *count = 0; + } + /* reset value */ + if (status.bad()) + value = NULL; + return status; +} + + +OFCondition DcmItem::findAndGetSequence(const DcmTagKey &seqTagKey, + DcmSequenceOfItems *&sequence, + const OFBool searchIntoSub, + const OFBool createCopy) +{ + DcmStack stack; + /* find the element */ + OFCondition status = search(seqTagKey, stack, ESM_fromHere, searchIntoSub); + if (status.good()) + { + DcmElement *delem = OFstatic_cast(DcmElement *, stack.top()); + /* should never happen but ... */ + if (delem == NULL) + status = EC_CorruptedData; + /* check for correct VR */ + else if ((delem->ident() == EVR_SQ) || (delem->ident() == EVR_pixelSQ)) + { + sequence = OFstatic_cast(DcmSequenceOfItems *, delem); + /* create a copy of the sequence? */ + if (createCopy) + { + sequence = OFstatic_cast(DcmSequenceOfItems *, sequence->clone()); + if (sequence == NULL) + status = EC_MemoryExhausted; + } + } else + status = EC_InvalidVR; + } + if (status.bad()) + { + /* reset sequence pointer */ + sequence = NULL; + } + return status; +} + + +OFCondition DcmItem::findAndGetSequenceItem(const DcmTagKey &seqTagKey, + DcmItem *&item, + const signed long itemNum, + const OFBool createCopy) +{ + DcmStack stack; + /* find sequence */ + OFCondition status = search(seqTagKey, stack, ESM_fromHere, OFFalse /*searchIntoSub*/); + if (status.good()) + { + /* get element */ + DcmElement *delem = OFstatic_cast(DcmElement *, stack.top()); + if (delem != NULL) + { + /* check VR */ + if ((delem->ident() == EVR_SQ) || (delem->ident() == EVR_pixelSQ)) + { + DcmSequenceOfItems *sequence = OFstatic_cast(DcmSequenceOfItems *, delem); + const unsigned long count = sequence->card(); + /* empty sequence? */ + if (count > 0) + { + /* get last item */ + if (itemNum == -1) + item = sequence->getItem(count - 1); + /* get specified item */ + else if ((itemNum >= 0) && (OFstatic_cast(unsigned long, itemNum) < count)) + item = sequence->getItem(OFstatic_cast(unsigned long, itemNum)); + /* invalid item number */ + else + status = EC_IllegalParameter; + /* create a copy of the item? */ + if (createCopy) + { + if (status.good() && (item != NULL)) + { + item = OFstatic_cast(DcmItem *, item->clone()); + if (item == NULL) + status = EC_MemoryExhausted; + } + } + } else + status = EC_IllegalParameter; + } else + status = EC_InvalidVR; + } else + status = EC_CorruptedData; + } + /* reset item value */ + if (status.bad()) + item = NULL; + else if (item == NULL) + status = EC_IllegalCall; + return status; +} + + +// ******************************** + +/* --- findOrCreate functions: find an element or create a new one --- */ + +OFCondition DcmItem::findOrCreateSequenceItem(const DcmTag& seqTag, + DcmItem *&item, + const signed long itemNum) +{ + DcmStack stack; + /* find sequence */ + OFCondition status = search(seqTag, stack, ESM_fromHere, OFFalse /*searchIntoSub*/); + DcmSequenceOfItems *sequence = NULL; + /* sequence found? */ + if (status.good()) + { + /* get element */ + DcmElement *delem = OFstatic_cast(DcmElement *, stack.top()); + if (delem != NULL) + { + /* check VR */ + if ((delem->ident() == EVR_SQ) || (delem->ident() == EVR_pixelSQ)) + sequence = OFstatic_cast(DcmSequenceOfItems *, delem); + else + status = EC_InvalidVR; + } else + status = EC_CorruptedData; + } else { + /* create new sequence element */ + sequence = new DcmSequenceOfItems(seqTag); + if (sequence != NULL) + { + /* insert into item/dataset */ + status = insert(sequence, OFTrue /*replaceOld*/); + if (status.bad()) + delete sequence; + } else + status = EC_MemoryExhausted; + } + if (status.good()) + { + if (sequence != NULL) + { + const unsigned long count = sequence->card(); + /* existing item? */ + if ((count > 0) && (itemNum >= -1) && (itemNum < OFstatic_cast(signed long, count))) + { + if (itemNum == -1) + { + /* get last item */ + item = sequence->getItem(count - 1); + } else { + /* get specified item */ + item = sequence->getItem(OFstatic_cast(unsigned long, itemNum)); + } + /* create new item(s) */ + } else { + unsigned long i = 0; + /* create empty trailing items if required */ + const unsigned long itemCount = (itemNum > OFstatic_cast(signed long, count)) ? (itemNum - count + 1) : 1; + while ((i < itemCount) && status.good()) + { + item = new DcmItem(); + if (item != NULL) + { + /* append new item to end of sequence */ + status = sequence->append(item); + if (status.bad()) + delete item; + } else + status = EC_MemoryExhausted; + i++; + } + } + } else + status = EC_IllegalCall; + } + /* reset item value */ + if (status.bad()) + item = NULL; + else if (item == NULL) + status = EC_IllegalCall; + return status; +} + + +// ******************************** + + +/* --- findAndXXX functions: find an element and do something with it --- */ + +OFCondition DcmItem::findAndInsertCopyOfElement(const DcmTagKey &tagKey, + DcmItem *destItem, + const OFBool replaceOld) +{ + OFCondition status = EC_IllegalParameter; + if (destItem != NULL) + { + DcmElement *delem = NULL; + /* get copy of element from current dataset */ + status = findAndGetElement(tagKey, delem, OFFalse /*searchIntoSub*/, OFTrue /*createCopy*/); + if (status.good()) + { + /* ... and insert it into the destination dataset */ + status = destItem->insert(delem, replaceOld); + if (status.bad()) + delete delem; + } + } + return status; +} + + +OFCondition DcmItem::findAndDeleteElement(const DcmTagKey &tagKey, + const OFBool allOccurrences, + const OFBool searchIntoSub) +{ + OFCondition status = EC_TagNotFound; + DcmStack stack; + DcmObject *object = NULL; + OFBool intoSub = OFTrue; + /* iterate over all elements */ + while (nextObject(stack, intoSub).good()) + { + /* get element */ + object = stack.top(); + if (object->getTag() == tagKey) + { + stack.pop(); + /* remove element from dataset and free memory */ + delete OFstatic_cast(DcmItem *, stack.top())->remove(object); + status = EC_Normal; + /* delete only the first element? */ + if (!allOccurrences) + break; + } + intoSub = searchIntoSub || allOccurrences; + } + return status; +} + + +OFCondition DcmItem::findAndDeleteSequenceItem(const DcmTagKey &seqTagKey, + const signed long itemNum) +{ + DcmStack stack; + /* find sequence */ + OFCondition status = search(seqTagKey, stack, ESM_fromHere, OFFalse /*searchIntoSub*/); + if (status.good()) + { + /* get element */ + DcmElement *delem = OFstatic_cast(DcmElement *, stack.top()); + if (delem != NULL) + { + /* check VR */ + if ((delem->ident() == EVR_SQ) || (delem->ident() == EVR_pixelSQ)) + { + DcmSequenceOfItems *sequence = OFstatic_cast(DcmSequenceOfItems *, delem); + const unsigned long count = sequence->card(); + /* last item? */ + if (itemNum == -1) + delete sequence->remove(count - 1); + /* valid item? */ + else if ((itemNum >= 0) && (OFstatic_cast(unsigned long, itemNum) < count)) + delete sequence->remove(OFstatic_cast(unsigned long, itemNum)); + else + status = EC_IllegalParameter; + } else + status = EC_InvalidVR; + } else + status = EC_CorruptedData; + } + return status; +} + + +// ******************************** + +/* --- putAndInsert functions: put value and insert new element --- */ + +OFCondition DcmItem::putAndInsertString(const DcmTag& tag, + const char *value, + const OFBool replaceOld) +{ + /* determine length of the string value */ + const Uint32 length = (value != NULL) ? OFstatic_cast(Uint32, strlen(value)) : 0; + /* call the real function */ + return putAndInsertString(tag, value, length, replaceOld); +} + + +OFCondition DcmItem::putAndInsertString(const DcmTag& tag, + const char *value, + const Uint32 length, + const OFBool replaceOld) +{ + OFCondition status = EC_Normal; + /* create new element */ + DcmElement *elem = NULL; + switch(tag.getEVR()) + { + case EVR_AE: + elem = new DcmApplicationEntity(tag); + break; + case EVR_AS: + elem = new DcmAgeString(tag); + break; + case EVR_AT: + elem = new DcmAttributeTag(tag); + break; + case EVR_CS: + elem = new DcmCodeString(tag); + break; + case EVR_DA: + elem = new DcmDate(tag); + break; + case EVR_DS: + elem = new DcmDecimalString(tag); + break; + case EVR_DT: + elem = new DcmDateTime(tag); + break; + case EVR_FL: + elem = new DcmFloatingPointSingle(tag); + break; + case EVR_FD: + elem = new DcmFloatingPointDouble(tag); + break; + case EVR_IS: + elem = new DcmIntegerString(tag); + break; + case EVR_LO: + elem = new DcmLongString(tag); + break; + case EVR_LT: + elem = new DcmLongText(tag); + break; + case EVR_OB: + case EVR_OW: + elem = new DcmOtherByteOtherWord(tag); + break; + case EVR_OD: + elem = new DcmOtherDouble(tag); + break; + case EVR_OF: + elem = new DcmOtherFloat(tag); + break; + case EVR_PN: + elem = new DcmPersonName(tag); + break; + case EVR_SH: + elem = new DcmShortString(tag); + break; + case EVR_SL: + elem = new DcmSignedLong(tag); + break; + case EVR_SS: + elem = new DcmSignedShort(tag); + break; + case EVR_ST: + elem = new DcmShortText(tag); + break; + case EVR_TM: + elem = new DcmTime(tag); + break; + case EVR_UC: + elem = new DcmUnlimitedCharacters(tag); + break; + case EVR_UI: + elem = new DcmUniqueIdentifier(tag); + break; + case EVR_UL: + elem = new DcmUnsignedLong(tag); + break; + case EVR_UR: + elem = new DcmUniversalResourceIdentifierOrLocator(tag); + break; + case EVR_US: + elem = new DcmUnsignedShort(tag); + break; + case EVR_UT: + elem = new DcmUnlimitedText(tag); + break; + case EVR_UNKNOWN: + /* Unknown VR, e.g. tag not found in data dictionary */ + status = EC_UnknownVR; + break; + default: + status = EC_IllegalCall; + break; + } + if (elem != NULL) + { + /* put value */ + status = elem->putString(value, length); + /* insert into dataset/item */ + if (status.good()) + status = insert(elem, replaceOld); + /* could not be inserted, therefore, delete it immediately */ + if (status.bad()) + delete elem; + } else if (status.good()) + status = EC_MemoryExhausted; + return status; +} + + +OFCondition DcmItem::putAndInsertOFStringArray(const DcmTag& tag, + const OFString &value, + const OFBool replaceOld) +{ + OFCondition status = EC_Normal; + /* create new element */ + DcmElement *elem = NULL; + switch(tag.getEVR()) + { + case EVR_AE: + elem = new DcmApplicationEntity(tag); + break; + case EVR_AS: + elem = new DcmAgeString(tag); + break; + case EVR_CS: + elem = new DcmCodeString(tag); + break; + case EVR_DA: + elem = new DcmDate(tag); + break; + case EVR_DS: + elem = new DcmDecimalString(tag); + break; + case EVR_DT: + elem = new DcmDateTime(tag); + break; + case EVR_IS: + elem = new DcmIntegerString(tag); + break; + case EVR_LO: + elem = new DcmLongString(tag); + break; + case EVR_LT: + elem = new DcmLongText(tag); + break; + case EVR_PN: + elem = new DcmPersonName(tag); + break; + case EVR_SH: + elem = new DcmShortString(tag); + break; + case EVR_ST: + elem = new DcmShortText(tag); + break; + case EVR_TM: + elem = new DcmTime(tag); + break; + case EVR_UC: + elem = new DcmUnlimitedCharacters(tag); + break; + case EVR_UI: + elem = new DcmUniqueIdentifier(tag); + break; + case EVR_UR: + elem = new DcmUniversalResourceIdentifierOrLocator(tag); + break; + case EVR_UT: + elem = new DcmUnlimitedText(tag); + break; + case EVR_UNKNOWN: + /* Unknown VR, e.g. tag not found in data dictionary */ + status = EC_UnknownVR; + break; + default: + status = EC_IllegalCall; + break; + } + if (elem != NULL) + { + /* put value */ + status = elem->putOFStringArray(value); + /* insert into dataset/item */ + if (status.good()) + status = insert(elem, replaceOld); + /* could not be inserted, therefore, delete it immediately */ + if (status.bad()) + delete elem; + } else if (status.good()) + status = EC_MemoryExhausted; + return status; +} + + +OFCondition DcmItem::putAndInsertUint8Array(const DcmTag& tag, + const Uint8 *value, + const unsigned long count, + const OFBool replaceOld) +{ + OFCondition status = EC_Normal; + /* create new element */ + DcmElement *elem = NULL; + switch(tag.getEVR()) + { + case EVR_OB: + elem = new DcmOtherByteOtherWord(tag); + break; + case EVR_ox: + /* special handling for Pixel Data */ + if (tag == DCM_PixelData) + { + elem = new DcmPixelData(tag); + if (elem != NULL) + elem->setVR(EVR_OB); + } else + elem = new DcmPolymorphOBOW(tag); + break; + case EVR_UNKNOWN: + /* Unknown VR, e.g. tag not found in data dictionary */ + status = EC_UnknownVR; + break; + default: + status = EC_IllegalCall; + break; + } + if (elem != NULL) + { + /* put value */ + status = elem->putUint8Array(value, count); + /* insert into dataset/item */ + if (status.good()) + status = insert(elem, replaceOld); + /* could not be inserted, therefore, delete it immediately */ + if (status.bad()) + delete elem; + } else if (status.good()) + status = EC_MemoryExhausted; + return status; +} + + +OFCondition DcmItem::putAndInsertUint16(const DcmTag& tag, + const Uint16 value, + const unsigned long pos, + const OFBool replaceOld) +{ + OFCondition status = EC_Normal; + /* create new element */ + DcmElement *elem = NULL; + switch(tag.getEVR()) + { + case EVR_US: + elem = new DcmUnsignedShort(tag); + break; + case EVR_lt: + case EVR_xs: + /* special handling */ + elem = new DcmUnsignedShort(DcmTag(tag, EVR_US)); + break; + case EVR_UNKNOWN: + /* Unknown VR, e.g. tag not found in data dictionary */ + status = EC_UnknownVR; + break; + default: + status = EC_IllegalCall; + break; + } + if (elem != NULL) + { + /* put value */ + status = elem->putUint16(value, pos); + /* insert into dataset/item */ + if (status.good()) + status = insert(elem, replaceOld); + /* could not be inserted, therefore, delete it immediately */ + if (status.bad()) + delete elem; + } else if (status.good()) + status = EC_MemoryExhausted; + return status; +} + + +OFCondition DcmItem::putAndInsertUint16Array(const DcmTag& tag, + const Uint16 *value, + const unsigned long count, + const OFBool replaceOld) +{ + OFCondition status = EC_Normal; + /* create new element */ + DcmElement *elem = NULL; + switch(tag.getEVR()) + { + case EVR_AT: + elem = new DcmAttributeTag(tag); + break; + case EVR_lt: + case EVR_OW: + elem = new DcmOtherByteOtherWord(tag); + break; + case EVR_US: + elem = new DcmUnsignedShort(tag); + break; + case EVR_ox: + /* special handling */ + if (tag == DCM_PixelData) + elem = new DcmPixelData(tag); + else + elem = new DcmPolymorphOBOW(tag); + break; + case EVR_xs: + /* special handling */ + elem = new DcmUnsignedShort(DcmTag(tag, EVR_US)); + break; + case EVR_UNKNOWN: + /* Unknown VR, e.g. tag not found in data dictionary */ + status = EC_UnknownVR; + break; + default: + status = EC_IllegalCall; + break; + } + if (elem != NULL) + { + /* put value */ + status = elem->putUint16Array(value, count); + /* insert into dataset/item */ + if (status.good()) + status = insert(elem, replaceOld); + /* could not be inserted, therefore, delete it immediately */ + if (status.bad()) + delete elem; + } else if (status.good()) + status = EC_MemoryExhausted; + return status; +} + + +OFCondition DcmItem::putAndInsertSint16(const DcmTag& tag, + const Sint16 value, + const unsigned long pos, + const OFBool replaceOld) +{ + OFCondition status = EC_Normal; + /* create new element */ + DcmElement *elem = NULL; + switch(tag.getEVR()) + { + case EVR_SS: + elem = new DcmSignedShort(tag); + break; + case EVR_lt: + case EVR_xs: + /* special handling */ + elem = new DcmSignedShort(DcmTag(tag, EVR_SS)); + break; + case EVR_UNKNOWN: + /* Unknown VR, e.g. tag not found in data dictionary */ + status = EC_UnknownVR; + break; + default: + status = EC_IllegalCall; + break; + } + if (elem != NULL) + { + /* put value */ + status = elem->putSint16(value, pos); + /* insert into dataset/item */ + if (status.good()) + status = insert(elem, replaceOld); + /* could not be inserted, therefore, delete it immediately */ + if (status.bad()) + delete elem; + } else if (status.good()) + status = EC_MemoryExhausted; + return status; +} + + +OFCondition DcmItem::putAndInsertSint16Array(const DcmTag& tag, + const Sint16 *value, + const unsigned long count, + const OFBool replaceOld) +{ + OFCondition status = EC_Normal; + /* create new element */ + DcmElement *elem = NULL; + switch(tag.getEVR()) + { + case EVR_SS: + elem = new DcmSignedShort(tag); + break; + case EVR_lt: + case EVR_xs: + /* special handling */ + elem = new DcmSignedShort(DcmTag(tag, EVR_SS)); + break; + case EVR_UNKNOWN: + /* Unknown VR, e.g. tag not found in data dictionary */ + status = EC_UnknownVR; + break; + default: + status = EC_IllegalCall; + break; + } + if (elem != NULL) + { + /* put value */ + status = elem->putSint16Array(value, count); + /* insert into dataset/item */ + if (status.good()) + status = insert(elem, replaceOld); + /* could not be inserted, therefore, delete it immediately */ + if (status.bad()) + delete elem; + } else if (status.good()) + status = EC_MemoryExhausted; + return status; +} + + +OFCondition DcmItem::putAndInsertUint32(const DcmTag& tag, + const Uint32 value, + const unsigned long pos, + const OFBool replaceOld) +{ + OFCondition status = EC_Normal; + /* create new element */ + DcmElement *elem = NULL; + switch(tag.getEVR()) + { + case EVR_UL: + elem = new DcmUnsignedLong(tag); + break; + case EVR_UNKNOWN: + /* Unknown VR, e.g. tag not found in data dictionary */ + status = EC_UnknownVR; + break; + default: + status = EC_IllegalCall; + break; + } + if (elem != NULL) + { + /* put value */ + status = elem->putUint32(value, pos); + /* insert into dataset/item */ + if (status.good()) + status = insert(elem, replaceOld); + /* could not be inserted, therefore, delete it immediately */ + if (status.bad()) + delete elem; + } else if (status.good()) + status = EC_MemoryExhausted; + return status; +} + + +OFCondition DcmItem::putAndInsertSint32(const DcmTag& tag, + const Sint32 value, + const unsigned long pos, + const OFBool replaceOld) +{ + OFCondition status = EC_Normal; + /* create new element */ + DcmElement *elem = NULL; + switch(tag.getEVR()) + { + case EVR_SL: + elem = new DcmSignedLong(tag); + break; + case EVR_UNKNOWN: + /* Unknown VR, e.g. tag not found in data dictionary */ + status = EC_UnknownVR; + break; + default: + status = EC_IllegalCall; + break; + } + if (elem != NULL) + { + /* put value */ + status = elem->putSint32(value, pos); + /* insert into dataset/item */ + if (status.good()) + status = insert(elem, replaceOld); + /* could not be inserted, therefore, delete it immediately */ + if (status.bad()) + delete elem; + } else if (status.good()) + status = EC_MemoryExhausted; + return status; +} + + +OFCondition DcmItem::putAndInsertFloat32(const DcmTag& tag, + const Float32 value, + const unsigned long pos, + const OFBool replaceOld) +{ + OFCondition status = EC_Normal; + /* create new element */ + DcmElement *elem = NULL; + switch(tag.getEVR()) + { + case EVR_FL: + elem = new DcmFloatingPointSingle(tag); + break; + case EVR_OF: + elem = new DcmOtherFloat(tag); + break; + case EVR_UNKNOWN: + /* Unknown VR, e.g. tag not found in data dictionary */ + status = EC_UnknownVR; + break; + default: + status = EC_IllegalCall; + break; + } + if (elem != NULL) + { + /* put value */ + status = elem->putFloat32(value, pos); + /* insert into dataset/item */ + if (status.good()) + status = insert(elem, replaceOld); + /* could not be inserted, therefore, delete it immediately */ + if (status.bad()) + delete elem; + } else if (status.good()) + status = EC_MemoryExhausted; + return status; +} + + +OFCondition DcmItem::putAndInsertFloat32Array(const DcmTag& tag, + const Float32 *value, + const unsigned long count, + const OFBool replaceOld) +{ + OFCondition status = EC_Normal; + /* create new element */ + DcmElement *elem = NULL; + switch(tag.getEVR()) + { + case EVR_FL: + elem = new DcmFloatingPointSingle(tag); + break; + case EVR_OF: + elem = new DcmOtherFloat(tag); + break; + case EVR_UNKNOWN: + /* Unknown VR, e.g. tag not found in data dictionary */ + status = EC_UnknownVR; + break; + default: + status = EC_IllegalCall; + break; + } + if (elem != NULL) + { + /* put value */ + status = elem->putFloat32Array(value, count); + /* insert into dataset/item */ + if (status.good()) + status = insert(elem, replaceOld); + /* could not be inserted, therefore, delete it immediately */ + if (status.bad()) + delete elem; + } else if (status.good()) + status = EC_MemoryExhausted; + return status; +} + + +OFCondition DcmItem::putAndInsertFloat64(const DcmTag& tag, + const Float64 value, + const unsigned long pos, + const OFBool replaceOld) +{ + OFCondition status = EC_Normal; + /* create new element */ + DcmElement *elem = NULL; + switch(tag.getEVR()) + { + case EVR_FD: + elem = new DcmFloatingPointDouble(tag); + break; + case EVR_OD: + elem = new DcmOtherDouble(tag); + break; + case EVR_UNKNOWN: + /* Unknown VR, e.g. tag not found in data dictionary */ + status = EC_UnknownVR; + break; + default: + status = EC_IllegalCall; + break; + } + if (elem != NULL) + { + /* put value */ + status = elem->putFloat64(value, pos); + /* insert into dataset/item */ + if (status.good()) + status = insert(elem, replaceOld); + /* could not be inserted, therefore, delete it immediately */ + if (status.bad()) + delete elem; + } else if (status.good()) + status = EC_MemoryExhausted; + return status; +} + + +OFCondition DcmItem::putAndInsertFloat64Array(const DcmTag& tag, + const Float64 *value, + const unsigned long count, + const OFBool replaceOld) +{ + OFCondition status = EC_Normal; + /* create new element */ + DcmElement *elem = NULL; + switch(tag.getEVR()) + { + case EVR_FD: + elem = new DcmFloatingPointDouble(tag); + break; + case EVR_OD: + elem = new DcmOtherDouble(tag); + break; + case EVR_UNKNOWN: + /* Unknown VR, e.g. tag not found in data dictionary */ + status = EC_UnknownVR; + break; + default: + status = EC_IllegalCall; + break; + } + if (elem != NULL) + { + /* put value */ + status = elem->putFloat64Array(value, count); + /* insert into dataset/item */ + if (status.good()) + status = insert(elem, replaceOld); + /* could not be inserted, therefore, delete it immediately */ + if (status.bad()) + delete elem; + } else if (status.good()) + status = EC_MemoryExhausted; + return status; +} + + +OFCondition DcmItem::putAndInsertTagKey(const DcmTag& tag, + const DcmTagKey &value, + const unsigned long pos, + const OFBool replaceOld) +{ + OFCondition status = EC_Normal; + /* create new element */ + DcmElement *elem = NULL; + switch(tag.getEVR()) + { + case EVR_AT: + elem = new DcmAttributeTag(tag); + break; + case EVR_UNKNOWN: + /* Unknown VR, e.g. tag not found in data dictionary */ + status = EC_UnknownVR; + break; + default: + status = EC_IllegalCall; + break; + } + if (elem != NULL) + { + /* put value */ + status = elem->putTagVal(value, pos); + /* insert into dataset/item */ + if (status.good()) + status = insert(elem, replaceOld); + /* could not be inserted, therefore, delete it immediately */ + if (status.bad()) + delete elem; + } else if (status.good()) + status = EC_MemoryExhausted; + return status; +} + + +// ******************************** + + +OFCondition DcmItem::insertEmptyElement(const DcmTag& tag, + const OFBool replaceOld) +{ + OFCondition status = EC_Normal; + /* create new element */ + DcmElement *elem = NULL; + switch(tag.getEVR()) + { + case EVR_AE: + elem = new DcmApplicationEntity(tag); + break; + case EVR_AS: + elem = new DcmAgeString(tag); + break; + case EVR_AT: + elem = new DcmAttributeTag(tag); + break; + case EVR_CS: + elem = new DcmCodeString(tag); + break; + case EVR_DA: + elem = new DcmDate(tag); + break; + case EVR_DS: + elem = new DcmDecimalString(tag); + break; + case EVR_DT: + elem = new DcmDateTime(tag); + break; + case EVR_FL: + elem = new DcmFloatingPointSingle(tag); + break; + case EVR_FD: + elem = new DcmFloatingPointDouble(tag); + break; + case EVR_IS: + elem = new DcmIntegerString(tag); + break; + case EVR_LO: + elem = new DcmLongString(tag); + break; + case EVR_LT: + elem = new DcmLongText(tag); + break; + case EVR_OB: + case EVR_OW: + elem = new DcmOtherByteOtherWord(tag); + break; + case EVR_OD: + elem = new DcmOtherDouble(tag); + break; + case EVR_OF: + elem = new DcmOtherFloat(tag); + break; + case EVR_PN: + elem = new DcmPersonName(tag); + break; + case EVR_SH: + elem = new DcmShortString(tag); + break; + case EVR_SL: + elem = new DcmSignedLong(tag); + break; + case EVR_SQ: + elem = new DcmSequenceOfItems(tag); + break; + case EVR_SS: + elem = new DcmSignedShort(tag); + break; + case EVR_ST: + elem = new DcmShortText(tag); + break; + case EVR_TM: + elem = new DcmTime(tag); + break; + case EVR_UC: + elem = new DcmUnlimitedCharacters(tag); + break; + case EVR_UI: + elem = new DcmUniqueIdentifier(tag); + break; + case EVR_UL: + elem = new DcmUnsignedLong(tag); + break; + case EVR_UR: + elem = new DcmUniversalResourceIdentifierOrLocator(tag); + break; + case EVR_US: + elem = new DcmUnsignedShort(tag); + break; + case EVR_UT: + elem = new DcmUnlimitedText(tag); + break; + case EVR_UNKNOWN: + /* Unknown VR, e.g. tag not found in data dictionary */ + status = EC_UnknownVR; + break; + default: + status = EC_IllegalCall; + break; + } + if (elem != NULL) + { + /* insert new element into dataset/item */ + status = insert(elem, replaceOld); + /* could not be inserted, therefore, delete it immediately */ + if (status.bad()) + delete elem; + } else if (status.good()) + status = EC_MemoryExhausted; + return status; +} + + +OFCondition DcmItem::insertSequenceItem(const DcmTag &seqTag, + DcmItem *item, + const signed long itemNum) +{ + OFCondition status = EC_IllegalParameter; + if (item != NULL) + { + DcmStack stack; + /* find sequence */ + status = search(seqTag, stack, ESM_fromHere, OFFalse /*searchIntoSub*/); + DcmSequenceOfItems *sequence = NULL; + /* sequence found? */ + if (status.good()) + { + /* get element */ + DcmElement *delem = OFstatic_cast(DcmElement *, stack.top()); + if (delem != NULL) + { + /* check VR */ + if ((delem->ident() == EVR_SQ) || (delem->ident() == EVR_pixelSQ)) + sequence = OFstatic_cast(DcmSequenceOfItems *, delem); + else + status = EC_InvalidVR; + } else + status = EC_CorruptedData; + } else { + /* create new sequence element */ + sequence = new DcmSequenceOfItems(seqTag); + if (sequence != NULL) + { + /* insert into item/dataset */ + status = insert(sequence, OFTrue /*replaceOld*/); + if (status.bad()) + delete sequence; + } else + status = EC_MemoryExhausted; + } + if (status.good()) + { + if (sequence != NULL) + { + const unsigned long count = sequence->card(); + /* 'itemNum' specifies and existing item? */ + if ((count > 0) && (itemNum >= -1) && (itemNum < OFstatic_cast(signed long, count))) + { + if (itemNum == -1) + { + /* insert given item before last entry */ + status = sequence->insert(item, count - 1, OFTrue /*before*/); + } else { + /* insert given item before specified entry */ + status = sequence->insert(item, OFstatic_cast(unsigned long, itemNum), OFTrue /*before*/); + } + /* create empty item(s) and append */ + } else { + DcmItem *newItem = NULL; + unsigned long i = 0; + /* create empty trailing items if required */ + const unsigned long itemCount = (itemNum > OFstatic_cast(signed long, count)) ? (itemNum - count) : 0; + while ((i < itemCount) && status.good()) + { + newItem = new DcmItem(); + if (newItem != NULL) + { + /* append new item to end of sequence */ + status = sequence->append(newItem); + if (status.bad()) + delete newItem; + } else + status = EC_MemoryExhausted; + i++; + } + /* append given item to end of sequence */ + status = sequence->append(item); + } + } else + status = EC_IllegalCall; + } + } + return status; +} + + +// ******************************** + + +OFBool DcmItem::containsUnknownVR() const +{ + if (!elementList->empty()) + { + elementList->seek(ELP_first); + do { + if (elementList->get()->containsUnknownVR()) + return OFTrue; + } while (elementList->seek(ELP_next)); + } + return OFFalse; +} + + +OFBool DcmItem::containsExtendedCharacters(const OFBool checkAllStrings) +{ + if (!elementList->empty()) + { + elementList->seek(ELP_first); + do { + if (elementList->get()->containsExtendedCharacters(checkAllStrings)) + return OFTrue; + } while (elementList->seek(ELP_next)); + } + return OFFalse; +} + + +OFBool DcmItem::isAffectedBySpecificCharacterSet() const +{ + if (!elementList->empty()) + { + elementList->seek(ELP_first); + do { + if (elementList->get()->isAffectedBySpecificCharacterSet()) + return OFTrue; + } while (elementList->seek(ELP_next)); + } + return OFFalse; +} + + +// ******************************** + + +void DcmItem::updateSpecificCharacterSet(OFCondition &status, + const DcmSpecificCharacterSet &converter) +{ + const OFString encoding = converter.getDestinationEncoding(); + if (status.good()) + { + // check whether the attribute Specific Character Set (0008,0005) should be present at all + if (checkForSpecificCharacterSet()) + { + const OFString toCharset = converter.getDestinationCharacterSet(); + // check for default character set (ASCII), also make sure that the value "ISO_IR 6" is never used + // in a dataset; open question: should we also check for non-ASCII characters in the element value? + if (toCharset.empty() || (toCharset == "ISO_IR 6")) + { + // delete Specific Character Set (0008,0005) data element (type 1C) + if (findAndDeleteElement(DCM_SpecificCharacterSet, OFFalse /*allOccurrences*/, OFFalse /*searchIntoSub*/).good()) + { + DCMDATA_DEBUG("DcmItem::convertCharacterSet() deleted element SpecificCharacterSet " + << DCM_SpecificCharacterSet << " during the conversion to " << encoding << " encoding"); + } + } else { + DCMDATA_DEBUG("DcmItem::convertCharacterSet() updating value of element SpecificCharacterSet " + << DCM_SpecificCharacterSet << " to '" << toCharset << "'"); + // update/set value of Specific Character Set (0008,0005) if needed + status = putAndInsertOFStringArray(DCM_SpecificCharacterSet, toCharset); + } + } else { + // otherwise delete it (if present) + if (findAndDeleteElement(DCM_SpecificCharacterSet, OFFalse /*allOccurrences*/, OFFalse /*searchIntoSub*/).good()) + { + DCMDATA_WARN("DcmItem: Deleted element SpecificCharacterSet " << DCM_SpecificCharacterSet + << " during the conversion to " << encoding << " encoding"); + } + } + } else { + // an error occurred in a previous processing step + DCMDATA_WARN("DcmItem: An error occurred during the conversion to " << encoding << " encoding, " + << "the value of SpecificCharacterSet " << DCM_SpecificCharacterSet << " is not updated"); + } +} + + +OFCondition DcmItem::convertCharacterSet(const OFString &fromCharset, + const OFString &toCharset, + const OFBool transliterate, + const OFBool updateCharset, + const OFBool discardIllegal) +{ + OFCondition status = EC_Normal; + // if the item is empty, there is nothing to do + if (!elementList->empty()) + { + DcmSpecificCharacterSet converter; + // create a new character set converter + DCMDATA_DEBUG("DcmItem::convertCharacterSet() creating a new character set converter for '" + << fromCharset << "'" << (fromCharset.empty() ? " (ASCII)" : "") << " to '" + << toCharset << "'" << (toCharset.empty() ? " (ASCII)" : "")); + // select source and destination character set + status = converter.selectCharacterSet(fromCharset, toCharset, transliterate, discardIllegal); + if (status.good()) + { + // convert all affected element values in the item + status = convertCharacterSet(converter); + if (updateCharset) + { + // update the Specific Character Set (0008,0005) element + updateSpecificCharacterSet(status, converter); + } + } + } + return status; +} + + +OFCondition DcmItem::convertCharacterSet(const OFString &toCharset, + const OFBool transliterate, + const OFBool ignoreCharset, + const OFBool discardIllegal) +{ + OFString fromCharset; + // check whether this item can contain the attribute SpecificCharacterSet (0008,0005) + if (checkForSpecificCharacterSet() && !ignoreCharset) + { + // determine value of Specific Character Set (0008,0005) if present in this item + findAndGetOFStringArray(DCM_SpecificCharacterSet, fromCharset, OFFalse /*searchIntoSub*/); + } + // do the real work, if Specific Character Set is missing or empty use the default (ASCII) + return convertCharacterSet(fromCharset, toCharset, transliterate, !ignoreCharset /*updateCharset*/, discardIllegal); +} + + +OFCondition DcmItem::convertCharacterSet(DcmSpecificCharacterSet &converter) +{ + OFCondition status = EC_Normal; + // if the item is empty, there is nothing to do + if (!elementList->empty()) + { + // iterate over all data elements in this item and convert the strings + elementList->seek(ELP_first); + do { + status = elementList->get()->convertCharacterSet(converter); + } while (status.good() && elementList->seek(ELP_next)); + } + return status; +} + + +OFCondition DcmItem::convertToUTF8() +{ + // the DICOM defined term "ISO_IR 192" is used for "UTF-8" + return convertCharacterSet("ISO_IR 192", OFFalse /*transliterate*/); +} diff --git a/dcmdata/libsrc/dclist.cc b/dcmdata/libsrc/dclist.cc new file mode 100644 index 00000000..d859672d --- /dev/null +++ b/dcmdata/libsrc/dclist.cc @@ -0,0 +1,295 @@ +/* + * + * Copyright (C) 1994-2010, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Gerd Ehlers + * + * Purpose: generic list class + * + */ + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/ofstd/ofstream.h" +#include "dcmtk/dcmdata/dclist.h" + + +// ***************************************** +// *** DcmListNode ************************* +// ***************************************** + + +DcmListNode::DcmListNode( DcmObject *obj ) + : nextNode(NULL), + prevNode(NULL), + objNodeValue(obj) +{ +} + + +// ******************************** + + +DcmListNode::~DcmListNode() +{ +} + + +// ***************************************** +// *** DcmList ***************************** +// ***************************************** + + +DcmList::DcmList() + : firstNode(NULL), + lastNode(NULL), + currentNode(NULL), + cardinality(0) +{ +} + + +// ******************************** + + +DcmList::~DcmList() +{ + if ( !DcmList::empty() ) // list is not empty ! + { + lastNode->nextNode = NULL; // set to 0 for safety reasons + do { + DcmListNode *temp = firstNode; + firstNode = firstNode->nextNode; + // delete temp->objNodeValue;; // dangerous! + delete temp; + } while ( firstNode != NULL ); + currentNode = firstNode = lastNode = NULL; + } +} + + +// ******************************** + + +DcmObject *DcmList::append( DcmObject *obj ) +{ + if ( obj != NULL ) + { + if ( DcmList::empty() ) // list is empty ! + currentNode = firstNode = lastNode = new DcmListNode(obj); + else + { + DcmListNode *node = new DcmListNode(obj); + lastNode->nextNode = node; + node->prevNode = lastNode; + currentNode = lastNode = node; + } + cardinality++; + } // obj == NULL + return obj; +} + + +// ******************************** + + +DcmObject *DcmList::prepend( DcmObject *obj ) +{ + if ( obj != NULL ) + { + if ( DcmList::empty() ) // list is empty ! + currentNode = firstNode = lastNode = new DcmListNode(obj); + else + { + DcmListNode *node = new DcmListNode(obj); + node->nextNode = firstNode; + firstNode->prevNode = node; + currentNode = firstNode = node; + } + cardinality++; + } // obj == NULL + return obj; +} + + +// ******************************** + + +DcmObject *DcmList::insert( DcmObject *obj, E_ListPos pos ) +{ + if ( obj != NULL ) + { + if ( DcmList::empty() ) // list is empty ! + { + currentNode = firstNode = lastNode = new DcmListNode(obj); + cardinality++; + } + else { + if ( pos==ELP_last ) + DcmList::append( obj ); // cardinality++; + else if ( pos==ELP_first ) + DcmList::prepend( obj ); // cardinality++; + else if ( !DcmList::valid() ) + // set current node to the end if there is no predecessor or + // there are successors to be determined + DcmList::append( obj ); // cardinality++; + else if ( pos == ELP_prev ) // insert before current node + { + DcmListNode *node = new DcmListNode(obj); + if ( currentNode->prevNode == NULL ) + firstNode = node; // insert at the beginning + else + currentNode->prevNode->nextNode = node; + node->prevNode = currentNode->prevNode; + node->nextNode = currentNode; + currentNode->prevNode = node; + currentNode = node; + cardinality++; + } + else //( pos==ELP_next || pos==ELP_atpos ) + // insert after current node + { + DcmListNode *node = new DcmListNode(obj); + if ( currentNode->nextNode == NULL ) + lastNode = node; // append to the end + else + currentNode->nextNode->prevNode = node; + node->nextNode = currentNode->nextNode; + node->prevNode = currentNode; + currentNode->nextNode = node; + currentNode = node; + cardinality++; + } + } + } // obj == NULL + return obj; +} + + +// ******************************** + + +DcmObject *DcmList::remove() +{ + DcmObject *tempobj; + DcmListNode *tempnode; + + if ( DcmList::empty() ) // list is empty ! + return NULL; + else if ( !DcmList::valid() ) + return NULL; // current node is 0 + else + { + tempnode = currentNode; + + if ( currentNode->prevNode == NULL ) + firstNode = currentNode->nextNode; // delete first element + else + currentNode->prevNode->nextNode = currentNode->nextNode; + + if ( currentNode->nextNode == NULL ) + lastNode = currentNode->prevNode; // delete last element + else + currentNode->nextNode->prevNode = currentNode->prevNode; + + currentNode = currentNode->nextNode; + tempobj = tempnode->value(); + delete tempnode; + cardinality--; + return tempobj; + } +} + + +// ******************************** + + +DcmObject *DcmList::get( E_ListPos pos ) +{ + return seek( pos ); +} + + +// ******************************** + + +DcmObject *DcmList::seek( E_ListPos pos ) +{ + switch (pos) + { + case ELP_first : + currentNode = firstNode; + break; + case ELP_last : + currentNode = lastNode; + break; + case ELP_prev : + if ( DcmList::valid() ) + currentNode = currentNode->prevNode; + break; + case ELP_next : + if ( DcmList::valid() ) + currentNode = currentNode->nextNode; + break; + default: + break; + } + return DcmList::valid() ? currentNode->value() : NULL; +} + + +// ******************************** + + +DcmObject *DcmList::seek_to(unsigned long absolute_position) +{ + const unsigned long tmppos = absolute_position < cardinality ? absolute_position : cardinality; + seek( ELP_first ); + for (unsigned long i = 0; i < tmppos; i++) + seek( ELP_next ); + return get( ELP_atpos ); +} + + +// ******************************** + + +void DcmList::deleteAllElements() +{ + unsigned long numElements = cardinality; + DcmListNode* tmpNode = NULL; + DcmObject* tmpObject = NULL; + // delete all elements + for (unsigned long i = 0; i < numElements; i++) + { + // always select first node so no search is necessary + tmpNode = firstNode; + // clear value of node + tmpObject = tmpNode->value(); + if (tmpObject != NULL) + { + // delete load of selected list node + delete tmpObject; + tmpObject = NULL; + } + firstNode = tmpNode->nextNode; + // delete the list node itself + delete tmpNode; + } + // reset all attributes for later use + firstNode = NULL; + lastNode = NULL; + currentNode = NULL; + cardinality = 0; +} diff --git a/dcmdata/libsrc/dcmetinf.cc b/dcmdata/libsrc/dcmetinf.cc new file mode 100644 index 00000000..d9d3659c --- /dev/null +++ b/dcmdata/libsrc/dcmetinf.cc @@ -0,0 +1,630 @@ +/* + * + * Copyright (C) 1994-2015, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Gerd Ehlers, Andreas Barth + * + * Purpose: Implementation of class DcmMetaInfo + * + */ + + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#define INCLUDE_CSTDLIB +#define INCLUDE_CSTRING +#include "dcmtk/ofstd/ofstdinc.h" + +#include "dcmtk/ofstd/ofstream.h" +#include "dcmtk/ofstd/ofstd.h" + +#include "dcmtk/dcmdata/dcmetinf.h" +#include "dcmtk/dcmdata/dcitem.h" +#include "dcmtk/dcmdata/dcxfer.h" +#include "dcmtk/dcmdata/dcvrul.h" +#include "dcmtk/dcmdata/dcdeftag.h" +#include "dcmtk/ofstd/ofdefine.h" +#include "dcmtk/dcmdata/dcistrma.h" /* for class DcmInputStream */ +#include "dcmtk/dcmdata/dcistrmf.h" /* for class DcmInputFileStream */ +#include "dcmtk/dcmdata/dcostrma.h" /* for class DcmOutputStream */ + + +const Uint32 DCM_GroupLengthElementLength = 12; + + +// ******************************** + + +DcmMetaInfo::DcmMetaInfo() + : DcmItem(DCM_ItemTag), + preambleUsed(OFFalse), + fPreambleTransferState(ERW_init), + Xfer(META_HEADER_DEFAULT_TRANSFERSYNTAX) +{ + setPreamble(); +} + + +DcmMetaInfo::DcmMetaInfo(const DcmMetaInfo &old) + : DcmItem(old), + preambleUsed(old.preambleUsed), + fPreambleTransferState(ERW_init), + Xfer(old.Xfer) +{ + memcpy(filePreamble, old.filePreamble, 128); +} + + +DcmMetaInfo& DcmMetaInfo::operator=(const DcmMetaInfo& obj) +{ + if (this != &obj) + { + // copy parent's member variables + DcmItem::operator=(obj); + // copy DcmMetaInfo's member variables + preambleUsed = obj.preambleUsed; + fPreambleTransferState = obj.fPreambleTransferState; + Xfer = obj.Xfer; + memcpy(filePreamble, obj.filePreamble, 128); + } + return *this; +} + + +OFCondition DcmMetaInfo::copyFrom(const DcmObject& rhs) +{ + if (this != &rhs) + { + if (rhs.ident() != ident()) return EC_IllegalCall; + *this = OFstatic_cast(const DcmMetaInfo &, rhs); + } + return EC_Normal; +} + + +DcmMetaInfo::~DcmMetaInfo() +{ +} + + +// ******************************** + + +DcmEVR DcmMetaInfo::ident() const +{ + return EVR_metainfo; +} + + +E_TransferSyntax DcmMetaInfo::getOriginalXfer() const +{ + return Xfer; +} + + +void DcmMetaInfo::removeInvalidGroups() +{ + DcmStack stack; + DcmObject *object = NULL; + /* iterate over all elements */ + while (nextObject(stack, OFTrue).good()) + { + object = stack.top(); + /* delete invalid elements */ + if (object->getGTag() != 0x0002) + { + DCMDATA_DEBUG("DcmMetaInfo::removeInvalidGroups() removing element " + << object->getTag() << " from meta header"); + stack.pop(); + /* remove element from meta information header and free memory */ + delete OFstatic_cast(DcmItem *, stack.top())->remove(object); + } + } +} + + +// ******************************** + + +void DcmMetaInfo::print(STD_NAMESPACE ostream&out, + const size_t flags, + const int level, + const char *pixelFileName, + size_t *pixelCounter) +{ + out << OFendl; + if (flags & DCMTypes::PF_useANSIEscapeCodes) + out << DCMDATA_ANSI_ESCAPE_CODE_COMMENT; + printNestingLevel(out, flags, level); + out << "# Dicom-Meta-Information-Header" << OFendl; + if (flags & DCMTypes::PF_useANSIEscapeCodes) + out << DCMDATA_ANSI_ESCAPE_CODE_COMMENT; + printNestingLevel(out, flags, level); + out << "# Used TransferSyntax: " << DcmXfer(Xfer).getXferName(); + if (flags & DCMTypes::PF_useANSIEscapeCodes) + out << DCMDATA_ANSI_ESCAPE_CODE_RESET; + out << OFendl; + if (!elementList->empty()) + { + DcmObject *dO; + elementList->seek(ELP_first); + do { + dO = elementList->get(); + dO->print(out, flags, level + 1, pixelFileName, pixelCounter); + } while (elementList->seek(ELP_next)); + } +} + + +// ******************************** + + +OFCondition DcmMetaInfo::writeXML(STD_NAMESPACE ostream &out, + const size_t flags) +{ + if (flags & DCMTypes::XF_useNativeModel) + { + /* in Native DICOM Model, there is no concept of a "file format" */ + return makeOFCondition(OFM_dcmdata, EC_CODE_CannotConvertToXML, OF_error, + "Cannot convert File Meta Information to Native DICOM Model"); + } else { + OFString xmlString; + DcmXfer xfer(Xfer); + /* XML start tag for "meta-header" */ + out << "" << OFendl; + /* write content of file meta information */ + if (!elementList->empty()) + { + /* write content of all children */ + DcmObject *dO; + elementList->seek(ELP_first); + do + { + dO = elementList->get(); + dO->writeXML(out, flags); + } while (elementList->seek(ELP_next)); + } + /* XML end tag for "meta-header" */ + out << "" << OFendl; + /* always report success */ + return EC_Normal; + } +} + + +// ******************************** + + +void DcmMetaInfo::setPreamble() +{ + memzero(filePreamble, sizeof(filePreamble)); + preambleUsed = OFFalse; +} + + +// ******************************** + + +OFBool DcmMetaInfo::checkAndReadPreamble(DcmInputStream &inStream, + E_TransferSyntax &newxfer) +{ + if (fPreambleTransferState == ERW_init) + { + inStream.mark(); + fPreambleTransferState = ERW_inWork; + } + // by default, we assume that there is no preamble + OFBool hasPreamble = OFFalse; + if (fPreambleTransferState == ERW_inWork) + { + const Uint32 preambleLen = DCM_PreambleLen + DCM_MagicLen; + const Uint32 readLen = preambleLen - getTransferredBytes(); + if (readLen > 0) + incTransferredBytes(OFstatic_cast(Uint32, inStream.read(&filePreamble[getTransferredBytes()], readLen))); + // file too short, no preamble + if (inStream.eos() && getTransferredBytes() != preambleLen) + { + inStream.putback(); + DCMDATA_TRACE("DcmMetaInfo::checkAndReadPreamble() No Preamble available: File too short (" + << preambleLen << ") < " << DCM_PreambleLen + DCM_MagicLen << " bytes"); + this -> setPreamble(); + fPreambleTransferState = ERW_ready; + } + // check preamble and DICOM prefix + else if (getTransferredBytes() == preambleLen) + { + // set prefix to appropriate position + char *prefix = filePreamble + DCM_PreambleLen; + if (memcmp(prefix, DCM_Magic, DCM_MagicLen) == 0) + { + // preamble present + hasPreamble = OFTrue; + // inStream.UnsetPutbackMark(); // not needed anymore with new stream architecture + } else { + // no preamble + this -> setPreamble(); + inStream.putback(); + } + fPreambleTransferState = ERW_ready; + } else + errorFlag = EC_StreamNotifyClient; + } + + if (fPreambleTransferState == ERW_ready) + { + E_TransferSyntax tmpXfer = checkTransferSyntax(inStream); + DcmXfer tmpXferSyn(tmpXfer); + DcmXfer xferSyn(newxfer); + // check determined transfer syntax + if ((tmpXferSyn.isExplicitVR() && xferSyn.isImplicitVR()) || + (tmpXferSyn.isImplicitVR() && xferSyn.isExplicitVR()) || + xferSyn.getXfer() == EXS_Unknown) + { + // use determined transfer syntax + newxfer = tmpXferSyn.getXfer(); + if (xferSyn.getXfer() != EXS_Unknown) + DCMDATA_WARN("DcmMetaInfo: TransferSyntax of MetaInfo is other than expected"); + } else + newxfer = xferSyn.getXfer(); + } + if (hasPreamble) + { + DCMDATA_TRACE("DcmMetaInfo::checkAndReadPreamble() Preamble = 0x" + << STD_NAMESPACE hex << STD_NAMESPACE setfill('0') + << STD_NAMESPACE setw(4) << OFstatic_cast(Uint32, *filePreamble)); + DCMDATA_DEBUG("DcmMetaInfo::checkAndReadPreamble() TransferSyntax=\"" + << DcmXfer(newxfer).getXferName() << "\""); + } else + DCMDATA_TRACE("DcmMetaInfo::checkAndReadPreamble() No Preambel found"); + + return hasPreamble; +} + + +// ******************************** + + +OFBool DcmMetaInfo::nextTagIsMeta(DcmInputStream &inStream) +{ + char testbytes[2]; + inStream.mark(); + inStream.read(testbytes, 2); + inStream.putback(); + // check for group 0x0002 only + return (testbytes[0] == 0x02 && testbytes[1] == 0x00) || (testbytes[0] == 0x00 && testbytes[1] == 0x02); +} + + +// ******************************** + + +Uint32 DcmMetaInfo::calcElementLength(const E_TransferSyntax /*xfer*/, + const E_EncodingType enctype) +{ + Uint32 metaLength = DcmItem::getLength(META_HEADER_DEFAULT_TRANSFERSYNTAX, enctype); + metaLength += DCM_PreambleLen + DCM_MagicLen; + return metaLength; +} + + +// ******************************** + + +OFCondition DcmMetaInfo::readGroupLength(DcmInputStream &inStream, + const E_TransferSyntax xfer, + const DcmTagKey &xtag, + const E_GrpLenEncoding glenc, + Uint32 &headerLen, + Uint32 &bytesRead, + const Uint32 maxReadLength) +{ + OFCondition l_error = EC_TagNotFound; + E_TransferSyntax newxfer = xfer; + bytesRead = 0; + headerLen = 0; + if (nextTagIsMeta(inStream)) + { + DcmTag newTag; + Uint32 newValueLength = 0; + Uint32 bytes_tagAndLen = 0; + l_error = DcmItem::readTagAndLength(inStream, newxfer, newTag, newValueLength, bytes_tagAndLen); + bytesRead += bytes_tagAndLen; + if (l_error.good() && !inStream.good()) + l_error = inStream.status(); + if (l_error.good()) + { + l_error = DcmItem::readSubElement(inStream, newTag, newValueLength, newxfer, glenc, maxReadLength); + bytesRead += newValueLength; + if (l_error.good() && newTag.getXTag() == xtag && elementList->get() != NULL && newValueLength > 0) + { + l_error = (OFstatic_cast(DcmUnsignedLong *, elementList->get()))->getUint32(headerLen); + DCMDATA_TRACE("DcmMetaInfo::readGroupLength() Group Length of File Meta Header = " << headerLen + bytesRead); + } else { + l_error = EC_CorruptedData; + DCMDATA_WARN("DcmMetaInfo: No Group Length available in Meta Information Header"); + } + } + } + + DCMDATA_TRACE("DcmMetaInfo::readGroupLength() returns error = " << l_error.text()); + return l_error; +} + + +// ******************************** + + +OFCondition DcmMetaInfo::read(DcmInputStream &inStream, + const E_TransferSyntax xfer, + const E_GrpLenEncoding glenc, + const Uint32 maxReadLength) +{ + if (fPreambleTransferState == ERW_notInitialized || getTransferState() == ERW_notInitialized) + errorFlag = EC_IllegalCall; + else + { + Xfer = xfer; + E_TransferSyntax newxfer = xfer; + // figure out if the stream reported an error + errorFlag = inStream.status(); + if (errorFlag.good() && inStream.eos()) + errorFlag = EC_EndOfStream; + else if (errorFlag.good() && getTransferState() != ERW_ready) + { + if (getTransferState() == ERW_init && fPreambleTransferState != ERW_ready) + { + if (xfer == EXS_Unknown) + preambleUsed = checkAndReadPreamble(inStream, newxfer); + else + newxfer = xfer; + if (fPreambleTransferState == ERW_ready) + { + Xfer = newxfer; // store parameter transfer syntax + setTransferState(ERW_inWork); + setTransferredBytes(0); + fStartPosition = inStream.tell(); + setLengthField(0); + } + } + if (getTransferState() == ERW_inWork && getLengthField() == 0) + { + if (inStream.avail() < OFstatic_cast(offile_off_t, DCM_GroupLengthElementLength)) + errorFlag = EC_StreamNotifyClient; + else + { + Uint32 headerLength = 0; + Uint32 bytesRead = 0; + errorFlag = readGroupLength(inStream, newxfer, DCM_FileMetaInformationGroupLength, glenc, + headerLength, bytesRead, maxReadLength); + + setTransferredBytes(bytesRead); + + if (errorFlag.good()) + { + /* FileMetaInformationGroupLength (0002,0000) is present but should be ignored */ + if (dcmIgnoreFileMetaInformationGroupLength.get()) + { + DCMDATA_WARN("DcmMetaInfo: Ignoring Group Length of Meta Information Header"); + setLengthField(DCM_UndefinedLength); + } else + setLengthField(headerLength + getTransferredBytes()); + } else + setLengthField(DCM_UndefinedLength); + } + } +#ifdef REJECT_FILE_IF_META_GROUP_LENGTH_ABSENT + // this is the old behaviour up to DCMTK 3.5.3: fail with EC_CorruptedData error code + // if the file meta header group length (0002,0000) is absent. + if (getTransferState() == ERW_inWork && getLengthField() != 0 && errorFlag.good()) + { +#else + // new behaviour: accept file without meta header group length, determine end of + // meta header based on heuristic that checks for group 0002 tags. + if (getTransferState() == ERW_inWork && getLengthField() != 0 && (errorFlag.good() || + ((errorFlag == EC_CorruptedData) && (getLengthField() == DCM_UndefinedLength)))) + { + // start with "no error" in order to handle meta-header with only one data element + errorFlag = EC_Normal; +#endif + while (inStream.good() && !inStream.eos() && + ((getLengthField() < DCM_UndefinedLength && getTransferredBytes() < getLengthField()) || + (getLengthField() == DCM_UndefinedLength && nextTagIsMeta(inStream)) || + !lastElementComplete)) + { + DcmTag newTag; + Uint32 newValueLength = 0; + Uint32 bytes_tagAndLen = 0; + if (lastElementComplete) + { + errorFlag = DcmItem::readTagAndLength(inStream, newxfer, newTag, newValueLength, bytes_tagAndLen); + incTransferredBytes(bytes_tagAndLen); + if (errorFlag != EC_Normal) + break; // terminate while loop + lastElementComplete = OFFalse; + errorFlag = DcmItem::readSubElement(inStream, newTag, newValueLength, newxfer, glenc, maxReadLength); + if (errorFlag.good()) + lastElementComplete = OFTrue; + /* check for valid meta-header elements */ + if (newTag.getGroup() != 0x0002) + DCMDATA_WARN("DcmMetaInfo: Invalid Element " << newTag << " found in Meta Information Header"); + } else { + errorFlag = elementList->get()->read(inStream, xfer, glenc, maxReadLength); + if (errorFlag.good()) + lastElementComplete = OFTrue; + } + setTransferredBytes(OFstatic_cast(Uint32, inStream.tell() - fStartPosition)); + if (errorFlag.bad()) + break; // terminate while loop + + } //while + } + if (errorFlag == EC_TagNotFound || errorFlag == EC_EndOfStream) + { + errorFlag = EC_Normal; // there is no meta header + Xfer = EXS_Unknown; + } else if (errorFlag == EC_ItemEnd) + errorFlag = EC_Normal; + if (errorFlag.good()) + { + if (getLengthField() != DCM_UndefinedLength && getTransferredBytes() != getLengthField()) + DCMDATA_WARN("DcmMetaInfo: Group Length of Meta Information Header has incorrect value"); + setTransferState(ERW_ready); // MetaInfo is complete + } + } + } + return errorFlag; +} // DcmMetaInfo::read() + + +// ******************************** + + +void DcmMetaInfo::transferInit() +{ + DcmItem::transferInit(); + fPreambleTransferState = ERW_init; +} + + +// ******************************** + + +void DcmMetaInfo::transferEnd() +{ + DcmItem::transferEnd(); + fPreambleTransferState = ERW_notInitialized; +} + + +// ******************************** + + +OFCondition DcmMetaInfo::write( + DcmOutputStream &outStream, + const E_TransferSyntax /*oxfer*/, + const E_EncodingType enctype, + DcmWriteCache *wcache) + /* + * This function writes all data elements which make up the meta header to the stream. + * For a specification of the elements that make up the meta header see DICOM standard + * (year 2000) part 10, section 7.1)) or the corresponding section in a later version of + * the standard). + * + * Parameters: + * outStream - [inout] The stream that the information will be written to. + * oxfer - [in] The transfer syntax which shall be used. (is not necessary since the meta header + * shall always be encoded in the explicit VR little endian transfer syntax) + * enctype - [in] Encoding type for sequences. Specifies how sequences will be handled. + */ +{ + /* if the transfer state of this is not initialized, this is an illegal call */ + if (getTransferState() == ERW_notInitialized) + errorFlag = EC_IllegalCall; + else + { + /* if this is not an illegal call, do something */ + + /* determine the (default) transfer syntax which shall be used (always explicit VR little endian) */ + E_TransferSyntax outxfer = META_HEADER_DEFAULT_TRANSFERSYNTAX; + /* check if the stream reported an error so far */ + errorFlag = outStream.status(); + /* if the stream did not report any error and the transfer state is ERW_ready, */ + /* go ahead and write the meta header information to the out stream */ + if (errorFlag.good() && getTransferState() != ERW_ready) + { + /* if some particular conditions are met we need to write the file preamble (128 byte wide) and */ + /* the DICOM prefix "DICM" to the stream. Always check if there is enough space in the stream and */ + /* set the transfer state of certain elements to indicate that they have already been written. */ + if (getTransferState() == ERW_init) + { + if (preambleUsed || !elementList->empty()) + { + if (fPreambleTransferState == ERW_init) + { + incTransferredBytes(OFstatic_cast(Uint32, outStream.write(&filePreamble[getTransferredBytes()], + DCM_PreambleLen - getTransferredBytes()))); + if (getTransferredBytes() != DCM_PreambleLen) + errorFlag = EC_StreamNotifyClient; + else + fPreambleTransferState = ERW_inWork; + } + if (fPreambleTransferState == ERW_inWork && outStream.avail() >= 4) + { + outStream.write(DCM_Magic, 4); + fPreambleTransferState = ERW_ready; + setTransferState(ERW_inWork); + elementList->seek(ELP_first); + } else + errorFlag = EC_StreamNotifyClient; + } + } + /* if the file preamble and the DICOM prefix have been written, go */ + /* ahead and write the meta header's data elements to the stream. */ + /* (note that at this point elementList->get() should never be NULL, */ + /* but lets play the game safe here...) */ + if (!elementList->empty() && (getTransferState() == ERW_inWork) && (elementList->get() != NULL)) + { + DcmObject *dO; + /* iterate over the list of data elements and write them to the stream */ + do { + dO = elementList->get(); + errorFlag = dO->write(outStream, outxfer, enctype, wcache); + } while (errorFlag.good() && elementList->seek(ELP_next)); + } + /* if the error flag equals ok and the transfer state equals ERW_inWork, all data elements of the meta */ + /* header have been written to the stream. Indicate this by setting the transfer state to ERW_ready */ + if (errorFlag.good() && getTransferState() == ERW_inWork) + setTransferState(ERW_ready); + } + } + /* return result value */ + return errorFlag; +} + + +// ******************************** + + +OFCondition DcmMetaInfo::loadFile(const OFFilename &fileName, + const E_TransferSyntax readXfer, + const E_GrpLenEncoding groupLength, + const Uint32 maxReadLength) +{ + OFCondition l_error = EC_InvalidFilename; + /* check parameters first */ + if (!fileName.isEmpty()) + { + /* open file for input */ + DcmInputFileStream fileStream(fileName); + /* check stream status */ + l_error = fileStream.status(); + if (l_error.good()) + { + /* clear this object */ + l_error = clear(); + if (l_error.good()) + { + /* read data from file */ + transferInit(); + l_error = read(fileStream, readXfer, groupLength, maxReadLength); + transferEnd(); + /* make sure that the file preamble is present */ + if (l_error.good() && !preambleUsed) + l_error = EC_FileMetaInfoHeaderMissing; + } + } + } + return l_error; +} diff --git a/dcmdata/libsrc/dcobject.cc b/dcmdata/libsrc/dcobject.cc new file mode 100644 index 00000000..ad169296 --- /dev/null +++ b/dcmdata/libsrc/dcobject.cc @@ -0,0 +1,610 @@ +/* + * + * Copyright (C) 1994-2012, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Gerd Ehlers, Andreas Barth + * + * Purpose: + * This file contains the interface to routines which provide + * DICOM object encoding/decoding, search and lookup facilities. + * + */ + + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/ofstd/ofstd.h" +#include "dcmtk/ofstd/ofstream.h" +#include "dcmtk/dcmdata/dcobject.h" +#include "dcmtk/dcmdata/dcdeftag.h" +#include "dcmtk/dcmdata/dcvr.h" +#include "dcmtk/dcmdata/dcxfer.h" +#include "dcmtk/dcmdata/dcswap.h" +#include "dcmtk/dcmdata/dcistrma.h" /* for class DcmInputStream */ +#include "dcmtk/dcmdata/dcostrma.h" /* for class DcmOutputStream */ + +#define INCLUDE_CSTDIO +#define INCLUDE_IOMANIP +#include "dcmtk/ofstd/ofstdinc.h" + + +// global flags + +OFGlobal dcmEnableAutomaticInputDataCorrection(OFTrue); +OFGlobal dcmAcceptOddAttributeLength(OFTrue); +OFGlobal dcmEnableCP246Support(OFTrue); +OFGlobal dcmEnableOldSignatureFormat(OFFalse); +OFGlobal dcmAutoDetectDatasetXfer(OFFalse); +OFGlobal dcmAcceptUnexpectedImplicitEncoding(OFFalse); +OFGlobal dcmPreferVRFromDataDictionary(OFFalse); +OFGlobal dcmPreferLengthFieldSizeFromDataDictionary(OFFalse); +OFGlobal dcmReadImplPrivAttribMaxLengthAsSQ(OFFalse); +OFGlobal dcmIgnoreParsingErrors(OFFalse); +OFGlobal dcmStopParsingAfterElement(DCM_UndefinedTagKey); // (0xffff,0xffff) +OFGlobal dcmWriteOversizedSeqsAndItemsUndefined(OFTrue); +OFGlobal dcmIgnoreFileMetaInformationGroupLength(OFFalse); +OFGlobal dcmReplaceWrongDelimitationItem(OFFalse); + + +// ****** public methods ********************************** + + +DcmObject::DcmObject(const DcmTag &tag, + const Uint32 len) +: errorFlag(EC_Normal) +, Tag(tag) +, Length(len) +, fTransferState(ERW_init) +, fTransferredBytes(0) +, Parent(NULL) +{ +} + + +DcmObject::DcmObject(const DcmObject &obj) +: errorFlag(obj.errorFlag) +, Tag(obj.Tag) +, Length(obj.Length) +, fTransferState(obj.fTransferState) +, fTransferredBytes(obj.fTransferredBytes) +, Parent(NULL) +{ +} + + +DcmObject::~DcmObject() +{ +} + + +DcmObject &DcmObject::operator=(const DcmObject &obj) +{ + if (this != &obj) + { + Tag = obj.Tag; + Length = obj.Length; + errorFlag = obj.errorFlag; + fTransferState = obj.fTransferState; + fTransferredBytes = obj.fTransferredBytes; + Parent = NULL; + } + return *this; +} + + +// ******************************** + + +void DcmObject::transferInit() +{ + fTransferState = ERW_init; + fTransferredBytes = 0; +} + + +void DcmObject::transferEnd() +{ + fTransferState = ERW_notInitialized; +} + + +// ******************************** + + +OFBool DcmObject::isNested() const +{ + OFBool nested = OFFalse; + if (Parent != NULL) + { + // check for surrounding structure of item and sequence + DcmEVR parentIdent = Parent->ident(); + if ((parentIdent == EVR_item) || (parentIdent == EVR_dirRecord)) + { + if (Parent->getParent() != NULL) + { + parentIdent = Parent->getParent()->ident(); + if ((parentIdent == EVR_SQ) || (parentIdent == EVR_pixelSQ)) + nested = OFTrue; + } + } + } + return nested; +} + + +DcmItem *DcmObject::getRootItem() +{ + DcmItem *rootItem = NULL; + DcmObject *parent = this; + // search for the root object + do { + // stop at top-level dataset/item + if ((parent->getParent() == NULL) || (parent->getParent()->ident() == EVR_fileFormat)) + break; + parent = parent->getParent(); + } while (parent != NULL); + if (parent != NULL) + { + // make sure that it is really a class derived from DcmItem + switch (parent->ident()) + { + case EVR_metainfo: + case EVR_dataset: + case EVR_item: + case EVR_dirRecord: + rootItem = OFreinterpret_cast(DcmItem *, parent); + break; + default: + // Don't generate a message when there is no root + if (this != parent) + { + DCMDATA_DEBUG("DcmObject::getRootItem() Root object has wrong class identifier: " + << OFstatic_cast(int, parent->ident()) + << " (" << DcmVR(parent->ident()).getVRName() << ")"); + } + break; + } + } + return rootItem; +} + + +DcmItem *DcmObject::getParentItem() +{ + DcmItem *parentItem = NULL; + if (Parent != NULL) + { + // make sure that it is really a class derived from DcmItem + switch (Parent->ident()) + { + case EVR_metainfo: + case EVR_dataset: + case EVR_item: + case EVR_dirRecord: + parentItem = OFreinterpret_cast(DcmItem *, Parent); + break; + default: + DCMDATA_DEBUG("DcmObject::getParentItem() Parent object has wrong class identifier: " + << OFstatic_cast(int, Parent->ident()) + << " (" << DcmVR(Parent->ident()).getVRName() << ")"); + break; + } + } + return parentItem; +} + + +// ******************************** + + +DcmObject *DcmObject::nextInContainer(const DcmObject * /*obj*/) +{ + return NULL; +} + + +OFCondition DcmObject::nextObject(DcmStack & /*stack*/, + const OFBool /*intoSub*/) +{ + return EC_TagNotFound; +} + + +// ******************************** + + +OFCondition DcmObject::search(const DcmTagKey &/*tag*/, + DcmStack &/*resultStack*/, + E_SearchMode /*mode*/, + OFBool /*searchIntoSub*/) +{ + return EC_TagNotFound; +} + + +// ******************************** + + +OFCondition DcmObject::writeXML(STD_NAMESPACE ostream& /*out*/, + const size_t /*flags*/) +{ + return EC_IllegalCall; +} + +// *********************************************************** +// ****** protected methods ********************************** +// *********************************************************** + + +void DcmObject::printNestingLevel(STD_NAMESPACE ostream&out, + const size_t flags, + const int level) +{ + if (flags & DCMTypes::PF_showTreeStructure) + { + if (flags & DCMTypes::PF_useANSIEscapeCodes) + out << DCMDATA_ANSI_ESCAPE_CODE_LINE; + /* show vertical bar for the tree structure */ + for (int i = 1; i < level; i++) + out << "| "; + } else { + /* show nesting level */ + for (int i = 1; i < level; i++) + out << " "; + } +} + + +void DcmObject::printInfoLineStart(STD_NAMESPACE ostream &out, + const size_t flags, + const int level, + DcmTag *tag) +{ + /* default: use object's tag */ + if (tag == NULL) + tag = &Tag; + DcmVR vr(tag->getVR()); + /* show nesting level */ + printNestingLevel(out, flags, level); + if (flags & DCMTypes::PF_showTreeStructure) + { + if (flags & DCMTypes::PF_useANSIEscapeCodes) + { + if (*tag == DCM_Item) + out << DCMDATA_ANSI_ESCAPE_CODE_ITEM; + else if ((vr.getEVR() == EVR_SQ) || (vr.getEVR() == EVR_pixelSQ)) + { + if (level == 1) + out << DCMDATA_ANSI_ESCAPE_CODE_SEQUENCE_1; + else + out << DCMDATA_ANSI_ESCAPE_CODE_SEQUENCE; + } else if (level == 1) + out << DCMDATA_ANSI_ESCAPE_CODE_NAME_1; + else + out << DCMDATA_ANSI_ESCAPE_CODE_NAME; + } + /* print tag name */ + out << tag->getTagName() << ' '; + /* add padding spaces if required */ + const STD_NAMESPACE ptrdiff_t padLength = DCM_OptPrintAttributeNameLength - strlen(tag->getTagName()) - 2 * level; + if (padLength > 0) + out << OFString(OFstatic_cast(size_t, padLength), ' '); + } else { + if (flags & DCMTypes::PF_useANSIEscapeCodes) + out << DCMDATA_ANSI_ESCAPE_CODE_TAG; + /* print line start: tag */ + out << *tag << " "; + if (flags & DCMTypes::PF_useANSIEscapeCodes) + out << DCMDATA_ANSI_ESCAPE_CODE_VR; + /* print line start: VR */ + out << vr.getVRName() << " " + << STD_NAMESPACE dec << STD_NAMESPACE setfill(' '); + } + /* set color for subsequent element value */ + if (flags & DCMTypes::PF_useANSIEscapeCodes) + out << DCMDATA_ANSI_ESCAPE_CODE_VALUE; +} + + +void DcmObject::printInfoLineEnd(STD_NAMESPACE ostream &out, + const size_t flags, + const unsigned long printedLength, + DcmTag *tag) +{ + unsigned long vm = 0; + unsigned long length = 0; + /* default: use object's tag, VM and length */ + if (tag == NULL) + { + tag = &Tag; + vm = getVM(); + length = Length; + } + if (!(flags & DCMTypes::PF_showTreeStructure)) + { + /* fill with spaces if necessary */ + if (printedLength < DCM_OptPrintValueLength) + out << OFString(OFstatic_cast(size_t, DCM_OptPrintValueLength - printedLength), ' '); + if (flags & DCMTypes::PF_useANSIEscapeCodes) + out << DCMDATA_ANSI_ESCAPE_CODE_COMMENT; + out << " # "; + /* print line end: length */ + if (flags & DCMTypes::PF_useANSIEscapeCodes) + out << DCMDATA_ANSI_ESCAPE_CODE_LENGTH; + if (length == DCM_UndefinedLength) + out << "u/l"; // means "undefined/length" + else + out << STD_NAMESPACE setw(3) << length; + if (flags & DCMTypes::PF_useANSIEscapeCodes) + out << DCMDATA_ANSI_ESCAPE_CODE_COMMENT; + out << ","; + /* print line end: VM */ + if (flags & DCMTypes::PF_useANSIEscapeCodes) + out << DCMDATA_ANSI_ESCAPE_CODE_VM; + out << STD_NAMESPACE setw(2) << vm << " "; + /* print line end: name */ + if (flags & DCMTypes::PF_useANSIEscapeCodes) + out << DCMDATA_ANSI_ESCAPE_CODE_NAME; + out << tag->getTagName(); + } + /* reset all colors and styles */ + if (flags & DCMTypes::PF_useANSIEscapeCodes) + out << DCMDATA_ANSI_ESCAPE_CODE_RESET; + /* finish the current line */ + out << OFendl; +} + + +void DcmObject::printInfoLine(STD_NAMESPACE ostream &out, + const size_t flags, + const int level, + const char *info, + DcmTag *tag, + const OFBool isInfo) +{ + /* print tag and VR */ + printInfoLineStart(out, flags, level, tag); + /* check whether info text fits into the limit */ + size_t printedLength = 0; + /* check for valid info text */ + if (info != NULL) + { + if (isInfo && (flags & DCMTypes::PF_useANSIEscapeCodes)) + out << DCMDATA_ANSI_ESCAPE_CODE_INFO; + /* check info text length */ + printedLength = strlen(info); + if (printedLength > DCM_OptPrintValueLength) + { + /* check whether full info text should be printed */ + if ((flags & DCMTypes::PF_shortenLongTagValues) && (printedLength > DCM_OptPrintLineLength)) + { + char output[DCM_OptPrintLineLength + 1]; + /* truncate info text and append "..." */ + OFStandard::strlcpy(output, info, OFstatic_cast(size_t, DCM_OptPrintLineLength) - 3 /* for "..." */ + 1); + OFStandard::strlcat(output, "...", OFstatic_cast(size_t, DCM_OptPrintLineLength) + 1); + out << output; + printedLength = DCM_OptPrintLineLength; + } else + out << info; + } else + out << info; + } + /* print length, VM and tag name */ + printInfoLineEnd(out, flags, OFstatic_cast(unsigned long, printedLength), tag); +} + + +// ******************************** + + +OFCondition DcmObject::writeTag(DcmOutputStream &outStream, + const DcmTag &tag, + const E_TransferSyntax oxfer) + /* + * This function writes the tag information which was passed to the stream. When + * writing information, the transfer syntax which was passed is accounted for. + * + * Parameters: + * outStream - [out] The stream that the information will be written to. + * tag - [in] The tag which shall be written. + * oxfer - [in] The transfer syntax which shall be used. + */ +{ + /* create an object which represents the transfer syntax */ + DcmXfer outXfer(oxfer); + /* determine the byte ordering */ + const E_ByteOrder outByteOrder = outXfer.getByteOrder(); + /* if the byte ordering is unknown, this is an illegal call (return error) */ + if (outByteOrder == EBO_unknown) + return EC_IllegalCall; + /* determine the group number, mind the transfer syntax and */ + /* write the group number value (2 bytes) to the stream */ + Uint16 groupTag = tag.getGTag(); + swapIfNecessary(outByteOrder, gLocalByteOrder, &groupTag, 2, 2); + outStream.write(&groupTag, 2); + /* determine the element number, mind the transfer syntax and */ + /* write the element number value (2 bytes) to the stream */ + Uint16 elementTag = tag.getETag(); // 2 byte length; + swapIfNecessary(outByteOrder, gLocalByteOrder, &elementTag, 2, 2); + outStream.write(&elementTag, 2); + /* if the stream reports an error return this error, else return ok */ + return outStream.status(); +} + + +Uint32 DcmObject::getTagAndLengthSize(const E_TransferSyntax oxfer) const +{ + /* create an object which represents the transfer syntax */ + DcmXfer oxferSyn(oxfer); + + if (oxferSyn.isExplicitVR()) + { + /* map "UN" to "OB" if generation of "UN" is disabled */ + DcmVR outvr(getTag().getVR().getValidEVR()); + + if (outvr.usesExtendedLengthEncoding()) + { + return 12; + } + } + return 8; +} + + +OFCondition DcmObject::writeTagAndLength(DcmOutputStream &outStream, + const E_TransferSyntax oxfer, + Uint32 &writtenBytes) const + /* + * This function writes this DICOM object's tag and length information to the stream. When + * writing information, the transfer syntax which was passed is accounted for. If the transfer + * syntax shows an explicit value representation, the data type of this object is also written + * to the stream. In general, this function follows the rules which are specified in the DICOM + * standard (see DICOM standard part 5, section 7) concerning the encoding of a data set which + * shall be transmitted. + * + * Parameters: + * outStream - [out] The stream that the information will be written to. + * oxfer - [in] The transfer syntax which shall be used. + * writtenBytes - [out] Contains in the end the amount of bytes which have been written to the stream. + */ +{ + /* check the error status of the stream. If it is not ok, nothing can be done */ + OFCondition l_error = outStream.status(); + if (l_error.bad()) + { + writtenBytes = 0; + } else { + /* if the stream is ok, we need to do something */ + + /* write the tag information (a total of 4 bytes, group number and element */ + /* number) to the stream. Mind the transfer syntax's byte ordering. */ + l_error = writeTag(outStream, getTag(), oxfer); + writtenBytes = 4; + + /* create an object which represents the transfer syntax */ + DcmXfer oxferSyn(oxfer); + + /* determine the byte ordering */ + const E_ByteOrder oByteOrder = oxferSyn.getByteOrder(); + + /* if the byte ordering is unknown, this is an illegal call (return error) */ + if (oByteOrder == EBO_unknown) + return EC_IllegalCall; + + /* if the transfer syntax is one with explicit value representation */ + /* this value's data type also has to be written to the stream. Do so */ + /* and also write the length information to the stream. */ + if (oxferSyn.isExplicitVR()) + { + /* Create an object that represents this object's data type */ + DcmVR myvr(getVR()); + + /* getValidEVR() will convert datatype "UN" to "OB" if generation of "UN" is disabled */ + DcmEVR vr = myvr.getValidEVR(); + + /* get name of data type */ + const char *vrname = myvr.getValidVRName(); + + /* write data type name to the stream (a total of 2 bytes) */ + outStream.write(vrname, 2); + writtenBytes += 2; + + /* create another data type object on the basis of the above created object */ + DcmVR outvr(vr); + + /* in case we are dealing with a transfer syntax with explicit VR (see if above) */ + /* and the actual VR uses extended length encoding (see DICOM standard part 5, */ + /* section 7.1.2) we have to add 2 reserved bytes (set to a value of 00H) to the */ + /* data type field and the actual length field is 4 bytes wide. Write the */ + /* corresponding information to the stream. */ + if (outvr.usesExtendedLengthEncoding()) + { + Uint16 reserved = 0; + outStream.write(&reserved, 2); // write 2 reserved bytes to stream + Uint32 valueLength = Length; // determine length + swapIfNecessary(oByteOrder, gLocalByteOrder, &valueLength, 4, 4); // mind transfer syntax + outStream.write(&valueLength, 4); // write length, 4 bytes wide + writtenBytes += 6; // remember that 6 bytes were written in total + } + /* in case that we are dealing with a transfer syntax with explicit VR (see if above) and */ + /* the actual VR does not use extended length encoding (see DICOM standard part 5, section */ + /* 7.1.2) we do not have to add reserved bytes to the data type field and the actual length */ + /* is 2 bytes wide. Write the corresponding information to the stream. But, make sure that */ + /* the length really fits into the 2-byte field ... */ + else if (Length <= 0xffff) + { + Uint16 valueLength = OFstatic_cast(Uint16, Length); // determine length (cast to 16 bit) + swapIfNecessary(oByteOrder, gLocalByteOrder, &valueLength, 2, 2); // mind transfer syntax + outStream.write(&valueLength, 2); // write length, 2 bytes wide + writtenBytes += 2; // remember that 2 bytes were written in total + } + /* ... if not, report an error message and return an error code. */ + else { + DcmTag tag(Tag); + DCMDATA_ERROR("DcmObject: Length of element " << tag.getTagName() << " " << tag + << " exceeds maximum of 16-bit length field"); + l_error = EC_ElemLengthExceeds16BitField; + } + } + /* if the transfer syntax is one with implicit value representation this value's data type */ + /* does not have to be written to the stream. Only the length information has to be written */ + /* to the stream. According to the DICOM standard the length field is in this case always 4 */ + /* byte wide. (see DICOM standard part 5, section 7.1.2) */ + else { + Uint32 valueLength = Length; // determine length + swapIfNecessary(oByteOrder, gLocalByteOrder, &valueLength, 4, 4); // mind transfer syntax + outStream.write(&valueLength, 4); // write length, 4 bytes wide + writtenBytes += 4; // remember that 4 bytes were written in total + } + } + + /* return result */ + return l_error; +} + + +OFBool DcmObject::isSignable() const +{ + return Tag.isSignable(); +} + + +OFBool DcmObject::containsUnknownVR() const +{ + return Tag.isUnknownVR(); +} + + +OFBool DcmObject::containsExtendedCharacters(const OFBool /*checkAllStrings*/) +{ + return OFFalse; +} + + +OFBool DcmObject::isAffectedBySpecificCharacterSet() const +{ + return OFFalse; +} + + +OFCondition DcmObject::convertCharacterSet(DcmSpecificCharacterSet & /*converter*/) +{ + return EC_Normal; +} + + +OFBool DcmObject::isEmpty(const OFBool /*normalize*/) +{ + return (Length == 0); +} diff --git a/dcmdata/libsrc/dcostrma.cc b/dcmdata/libsrc/dcostrma.cc new file mode 100644 index 00000000..44fdb0a4 --- /dev/null +++ b/dcmdata/libsrc/dcostrma.cc @@ -0,0 +1,103 @@ +/* + * + * Copyright (C) 1994-2010, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Marco Eichelberg + * + * Purpose: base classes for output streams + * + */ + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmdata/dcostrma.h" +#include "dcmtk/dcmdata/dcostrmz.h" /* for DcmZLibOutputFilter */ +#include "dcmtk/dcmdata/dcerror.h" /* for EC_IllegalCall */ + +DcmOutputStream::DcmOutputStream(DcmConsumer *initial) +: current_(initial) +, compressionFilter_(NULL) +, tell_(0) +{ +} + +DcmOutputStream::~DcmOutputStream() +{ + // we cannot access the stream anymore at this point because the + // consumer has most probably already been deleted. + delete compressionFilter_; +} + +OFCondition DcmOutputStream::installCompressionFilter(E_StreamCompression filterType) +{ + OFCondition result = EC_Normal; + if (compressionFilter_) result = EC_DoubleCompressionFilters; + else + { + switch (filterType) + { +#ifdef WITH_ZLIB + case ESC_zlib: + compressionFilter_ = new DcmZLibOutputFilter(); + if (compressionFilter_) + { + compressionFilter_->append(*current_); + current_ = compressionFilter_; + } else result = EC_MemoryExhausted; + break; +#endif + case ESC_none: + case ESC_unsupported: + result = EC_UnsupportedEncoding; + break; + } + } + return result; +} + +OFBool DcmOutputStream::good() const +{ + return current_->good(); +} + +OFCondition DcmOutputStream::status() const +{ + return current_->status(); +} + +OFBool DcmOutputStream::isFlushed() const +{ + return current_->isFlushed(); +} + +offile_off_t DcmOutputStream::avail() const +{ + return current_->avail(); +} + +offile_off_t DcmOutputStream::write(const void *buf, offile_off_t buflen) +{ + offile_off_t result = current_->write(buf, buflen); + tell_ += result; + return result; +} + +void DcmOutputStream::flush() +{ + current_->flush(); +} + +offile_off_t DcmOutputStream::tell() const +{ + return tell_; +} diff --git a/dcmdata/libsrc/dcostrmb.cc b/dcmdata/libsrc/dcostrmb.cc new file mode 100644 index 00000000..2d32e990 --- /dev/null +++ b/dcmdata/libsrc/dcostrmb.cc @@ -0,0 +1,118 @@ +/* + * + * Copyright (C) 2002-2010, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Marco Eichelberg + * + * Purpose: DcmOutputBufferStream and related classes, + * implements output to blocks of memory as needed in the dcmnet module. + * + */ + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmdata/dcostrmb.h" +#include "dcmtk/dcmdata/dcerror.h" + + +DcmBufferConsumer::DcmBufferConsumer(void *buf, offile_off_t bufLen) +: DcmConsumer() +, buffer_(OFstatic_cast(unsigned char *, buf)) +, bufSize_(bufLen) +, filled_(0) +, status_(EC_Normal) +{ + if ((buffer_ == NULL) || (bufSize_ == 0)) status_ = EC_IllegalCall; +} + +DcmBufferConsumer::~DcmBufferConsumer() +{ +} + +OFBool DcmBufferConsumer::good() const +{ + return status_.good(); +} + +OFCondition DcmBufferConsumer::status() const +{ + return status_; +} + +OFBool DcmBufferConsumer::isFlushed() const +{ + return (filled_ == 0); +} + +offile_off_t DcmBufferConsumer::avail() const +{ + return bufSize_ - filled_; +} + +offile_off_t DcmBufferConsumer::write(const void *buf, offile_off_t buflen) +{ + offile_off_t result = 0; + if (status_.good() && buf && buflen) + { + result = bufSize_ - filled_; + if (result > buflen) result = buflen; + memcpy(buffer_+ filled_, buf, OFstatic_cast(size_t, result)); + filled_ += result; + } + return result; +} + +void DcmBufferConsumer::flush() +{ + // nothing to flush +} + +void DcmBufferConsumer::flushBuffer(void *& buffer, offile_off_t& length) +{ + buffer = buffer_; + length = filled_; + filled_ = 0; +} + +offile_off_t DcmBufferConsumer::filled() +{ + return filled_; +} + +/* ======================================================================= */ + +DcmOutputBufferStream::DcmOutputBufferStream(void *buf, offile_off_t bufLen) +: DcmOutputStream(&consumer_) // safe because DcmOutputStream only stores pointer +, consumer_(buf, bufLen) +{ +} + +DcmOutputBufferStream::~DcmOutputBufferStream() +{ +#ifdef DEBUG + if (! isFlushed()) + { + DCMDATA_WARN("DcmOutputBufferStream: Closing unflushed DcmOutputBufferStream, loss of data!"); + } +#endif +} + +void DcmOutputBufferStream::flushBuffer(void *& buffer, offile_off_t& length) +{ + consumer_.flushBuffer(buffer, length); +} + +offile_off_t DcmOutputBufferStream::filled() +{ + return consumer_.filled(); +} diff --git a/dcmdata/libsrc/dcostrmf.cc b/dcmdata/libsrc/dcostrmf.cc new file mode 100644 index 00000000..d440c845 --- /dev/null +++ b/dcmdata/libsrc/dcostrmf.cc @@ -0,0 +1,147 @@ +/* + * + * Copyright (C) 2002-2012, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Marco Eichelberg + * + * Purpose: DcmOutputFileStream and related classes, + * implements streamed output to files. + * + */ + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmdata/dcostrmf.h" +#include "dcmtk/dcmdata/dcerror.h" + +#define INCLUDE_CSTDIO +#define INCLUDE_CERRNO +#include "dcmtk/ofstd/ofstdinc.h" + + +DcmFileConsumer::DcmFileConsumer(const OFFilename &filename) +: DcmConsumer() +, file_() +, status_(EC_Normal) +{ + if (!file_.fopen(filename, "wb")) + { + char buf[256]; + const char *text = OFStandard::strerror(errno, buf, sizeof(buf)); + if (text == NULL) text = "(unknown error code)"; + status_ = makeOFCondition(OFM_dcmdata, 19, OF_error, text); + } +} + +DcmFileConsumer::DcmFileConsumer(FILE *file) +: DcmConsumer() +, file_(file) +, status_(EC_Normal) +{ +} + +DcmFileConsumer::~DcmFileConsumer() +{ + file_.fclose(); +} + +OFBool DcmFileConsumer::good() const +{ + return status_.good(); +} + +OFCondition DcmFileConsumer::status() const +{ + return status_; +} + +OFBool DcmFileConsumer::isFlushed() const +{ + return OFTrue; +} + +offile_off_t DcmFileConsumer::avail() const +{ + // since we cannot report "unlimited", let's claim that we can still write 2GB. + // Note that offile_off_t is a signed type. + return 2147483647L; +} + +offile_off_t DcmFileConsumer::write(const void *buf, offile_off_t buflen) +{ + offile_off_t result = 0; + if (status_.good() && file_.open() && buf && buflen) + { +#ifdef WRITE_VERY_LARGE_CHUNKS + /* This is the old behaviour prior to DCMTK 3.5.5 */ + result = OFstatic_cast(offile_off_t, file_.fwrite(buf, 1, OFstatic_cast(size_t, buflen))); +#else + /* On Windows (at least for some versions of MSVC), calls to fwrite() for more than + * 67,076,095 bytes (a bit less than 64 MByte) fail if we're writing to a network + * share. See MSDN KB899149. As a workaround, we always write in chunks of + * 32M which should hardly negatively affect performance. + */ +#define DcmFileConsumer_MAX_CHUNK_SIZE 33554432 /* 32 MByte */ + offile_off_t written; + const char *buf2 = OFstatic_cast(const char *, buf); + while (buflen > DcmFileConsumer_MAX_CHUNK_SIZE) + { + written = OFstatic_cast(offile_off_t, file_.fwrite(buf2, 1, DcmFileConsumer_MAX_CHUNK_SIZE)); + result += written; + buf2 += written; + + // if we have not written a complete chunk, there is problem; bail out + if (written == DcmFileConsumer_MAX_CHUNK_SIZE) buflen -= DcmFileConsumer_MAX_CHUNK_SIZE; else buflen = 0; + } + + // last call to fwrite if the file size is not a multiple of DcmFileConsumer_MAX_CHUNK_SIZE + if (buflen) + { + written = OFstatic_cast(offile_off_t, file_.fwrite(buf2, 1, OFstatic_cast(size_t, buflen))); + result += written; + } +#endif + } + return result; +} + +void DcmFileConsumer::flush() +{ + // nothing to flush +} + +/* ======================================================================= */ + +DcmOutputFileStream::DcmOutputFileStream(const OFFilename &filename) +: DcmOutputStream(&consumer_) // safe because DcmOutputStream only stores pointer +, consumer_(filename) +{ +} + +DcmOutputFileStream::DcmOutputFileStream(FILE *file) +: DcmOutputStream(&consumer_) // safe because DcmOutputStream only stores pointer +, consumer_(file) +{ +} + +DcmOutputFileStream::~DcmOutputFileStream() +{ + // last attempt to flush stream before file is closed + flush(); +#ifdef DEBUG + if (! isFlushed()) + { + DCMDATA_WARN("closing unflushed DcmOutputFileStream, loss of data!"); + } +#endif +} diff --git a/dcmdata/libsrc/dcostrmz.cc b/dcmdata/libsrc/dcostrmz.cc new file mode 100644 index 00000000..da63b564 --- /dev/null +++ b/dcmdata/libsrc/dcostrmz.cc @@ -0,0 +1,359 @@ +/* + * + * Copyright (C) 2002-2010, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Marco Eichelberg + * + * Purpose: zlib compression filter for output streams + * + */ + +#include "dcmtk/config/osconfig.h" + +#ifdef WITH_ZLIB + +#include "dcmtk/dcmdata/dcostrmz.h" +#include "dcmtk/dcmdata/dcerror.h" + +#define DCMZLIBOUTPUTFILTER_BUFSIZE 4096 + +/* taken from zutil.h */ +#if MAX_MEM_LEVEL >= 8 +#define DEF_MEM_LEVEL 8 +#else +#define DEF_MEM_LEVEL MAX_MEM_LEVEL +#endif + +OFGlobal dcmZlibCompressionLevel(Z_DEFAULT_COMPRESSION); + +// helper method to fix old-style casts warnings +BEGIN_EXTERN_C +static int OFdeflateInit(z_stream* const stream, int level) +{ +#ifdef ZLIB_ENCODE_RFC1950_HEADER + /* create deflated ZLIB format instead of deflated bitstream format + * (i.e. RFC 1950 instead of RFC 1951). + * THE RESULTING BITSTREAM IS NOT DICOM COMPLIANT! + * Use only for testing, and use with care. + */ + return deflateInit(stream, level); +#else + /* windowBits is passed < 0 to suppress zlib header */ + return deflateInit2(stream, level, Z_DEFLATED, -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY); +#endif +} +END_EXTERN_C + +DcmZLibOutputFilter::DcmZLibOutputFilter() +: DcmOutputFilter() +, current_(NULL) +, zstream_(new z_stream) +, status_(EC_MemoryExhausted) +, flushed_(OFFalse) +, inputBuf_(new unsigned char[DCMZLIBOUTPUTFILTER_BUFSIZE]) +, inputBufStart_(0) +, inputBufCount_(0) +, outputBuf_(new unsigned char[DCMZLIBOUTPUTFILTER_BUFSIZE]) +, outputBufStart_(0) +, outputBufCount_(0) +{ + if (zstream_ && inputBuf_ && outputBuf_) + { + zstream_->zalloc = Z_NULL; + zstream_->zfree = Z_NULL; + zstream_->opaque = Z_NULL; + if (Z_OK == OFdeflateInit(zstream_, dcmZlibCompressionLevel.get())) + status_ = EC_Normal; + else + { + OFString etext = "ZLib Error: "; + if (zstream_->msg) etext += zstream_->msg; + status_ = makeOFCondition(OFM_dcmdata, 16, OF_error, etext.c_str()); + } + } +} + +DcmZLibOutputFilter::~DcmZLibOutputFilter() +{ + if (zstream_) + { + deflateEnd(zstream_); // discards any unprocessed input and does not flush any pending output + delete zstream_; + } + delete[] inputBuf_; + delete[] outputBuf_; +} + + +OFBool DcmZLibOutputFilter::good() const +{ + return status_.good(); +} + +OFCondition DcmZLibOutputFilter::status() const +{ + return status_; +} + +OFBool DcmZLibOutputFilter::isFlushed() const +{ + if (status_.bad() || (current_ == NULL)) return OFTrue; + return (inputBufCount_ == 0) && (outputBufCount_ == 0) && flushed_ && current_->isFlushed(); +} + + +offile_off_t DcmZLibOutputFilter::avail() const +{ + // compute number of bytes available in input buffer + if (status_.good() ) return DCMZLIBOUTPUTFILTER_BUFSIZE - inputBufCount_; + else return 0; +} + +void DcmZLibOutputFilter::flushOutputBuffer() +{ + if (outputBufCount_) + { + // flush from outputBufStart_ to end of data or end of buffer, whatever comes first + offile_off_t numBytes = (outputBufStart_ + outputBufCount_ > DCMZLIBOUTPUTFILTER_BUFSIZE) ? + (DCMZLIBOUTPUTFILTER_BUFSIZE - outputBufStart_) : outputBufCount_ ; + + offile_off_t written = current_->write(outputBuf_ + outputBufStart_, numBytes); + + // adjust counters + outputBufCount_ -= written; + outputBufStart_ += written; + + if (outputBufStart_ == DCMZLIBOUTPUTFILTER_BUFSIZE) + { + // wrapped around + outputBufStart_ = 0; + + // now flush to end of data + if (outputBufCount_ && written) + { + written = current_->write(outputBuf_, outputBufCount_); + + // adjust counters + outputBufCount_ -= written; + outputBufStart_ += written; + } + } + + // reset buffer start to make things faster + if (outputBufCount_ == 0) outputBufStart_ = 0; + } +} + +offile_off_t DcmZLibOutputFilter::fillInputBuffer(const void *buf, offile_off_t buflen) +{ + offile_off_t result = 0; + if (buf && buflen && inputBufCount_ < DCMZLIBOUTPUTFILTER_BUFSIZE) + { + + const unsigned char *data = OFstatic_cast(const unsigned char *, buf); + + // use first part of input buffer + if (inputBufStart_ + inputBufCount_ < DCMZLIBOUTPUTFILTER_BUFSIZE) + { + result = DCMZLIBOUTPUTFILTER_BUFSIZE - (inputBufStart_ + inputBufCount_); + if (result > buflen) result = buflen; + + memcpy(inputBuf_ + inputBufStart_ + inputBufCount_, data, OFstatic_cast(size_t, result)); + inputBufCount_ += result; + data += result; + buflen -= result; + } + + // use second part of input buffer + if (buflen && (inputBufCount_ < DCMZLIBOUTPUTFILTER_BUFSIZE) && + inputBufStart_ + inputBufCount_ >= DCMZLIBOUTPUTFILTER_BUFSIZE) + { + offile_off_t len = DCMZLIBOUTPUTFILTER_BUFSIZE - inputBufCount_; + if (len > buflen) len = buflen; + + memcpy(inputBuf_ + (inputBufStart_ + inputBufCount_ - DCMZLIBOUTPUTFILTER_BUFSIZE), data, OFstatic_cast(size_t, len)); + + inputBufCount_ += len; + result += len; + } + } + return result; +} + +void DcmZLibOutputFilter::compressInputBuffer(OFBool finalize) +{ + if (inputBufCount_ || finalize) + { + // flush from inputBufStart_ to end of data or end of buffer, whatever comes first + offile_off_t numBytes = (inputBufStart_ + inputBufCount_ > DCMZLIBOUTPUTFILTER_BUFSIZE) ? + (DCMZLIBOUTPUTFILTER_BUFSIZE - inputBufStart_) : inputBufCount_ ; + + offile_off_t written = compress(inputBuf_ + inputBufStart_, numBytes, finalize); + + // adjust counters + inputBufCount_ -= written; + inputBufStart_ += written; + + if (inputBufStart_ == DCMZLIBOUTPUTFILTER_BUFSIZE) + { + // wrapped around + inputBufStart_ = 0; + + // now flush to end of data + if (inputBufCount_ && written) + { + written = compress(inputBuf_, inputBufCount_, finalize); + + // adjust counters + inputBufCount_ -= written; + inputBufStart_ += written; + } + } + + // reset buffer start to make things faster + if (inputBufCount_ == 0) inputBufStart_ = 0; + } +} + +offile_off_t DcmZLibOutputFilter::compress(const void *buf, offile_off_t buflen, OFBool finalize) +{ + offile_off_t result = 0; + if (outputBufCount_ < DCMZLIBOUTPUTFILTER_BUFSIZE) + { + zstream_->next_in = OFstatic_cast(Bytef *, OFconst_cast(void *, buf)); + zstream_->avail_in = OFstatic_cast(uInt, buflen); + int zstatus; + + // use first part of output buffer + if (outputBufStart_ + outputBufCount_ < DCMZLIBOUTPUTFILTER_BUFSIZE) + { + zstream_->next_out = OFstatic_cast(Bytef *, outputBuf_ + outputBufStart_ + outputBufCount_); + zstream_->avail_out = OFstatic_cast(uInt, DCMZLIBOUTPUTFILTER_BUFSIZE - (outputBufStart_ + outputBufCount_)); + zstatus = deflate(zstream_, (finalize ? Z_FINISH : 0)); + + if (zstatus == Z_OK || zstatus == Z_BUF_ERROR) { /* everything OK */ } + else if (zstatus == Z_STREAM_END) flushed_ = OFTrue; + else + { + OFString etext = "ZLib Error: "; + if (zstream_->msg) etext += zstream_->msg; + status_ = makeOFCondition(OFM_dcmdata, 16, OF_error, etext.c_str()); + } + + outputBufCount_ = DCMZLIBOUTPUTFILTER_BUFSIZE - outputBufStart_ - OFstatic_cast(offile_off_t, zstream_->avail_out); + } + + // use second part of output buffer + if ((outputBufCount_ < DCMZLIBOUTPUTFILTER_BUFSIZE) && + outputBufStart_ + outputBufCount_ >= DCMZLIBOUTPUTFILTER_BUFSIZE) + { + zstream_->next_out = OFstatic_cast(Bytef *, outputBuf_ + (outputBufStart_ + outputBufCount_ - DCMZLIBOUTPUTFILTER_BUFSIZE)); + zstream_->avail_out = OFstatic_cast(uInt, DCMZLIBOUTPUTFILTER_BUFSIZE - outputBufCount_); + zstatus = deflate(zstream_, (finalize ? Z_FINISH : 0)); + + if (zstatus == Z_OK || zstatus == Z_BUF_ERROR) { /* everything OK */ } + else if (zstatus == Z_STREAM_END) flushed_ = OFTrue; + else + { + OFString etext = "ZLib Error: "; + if (zstream_->msg) etext += zstream_->msg; + status_ = makeOFCondition(OFM_dcmdata, 16, OF_error, etext.c_str()); + } + + outputBufCount_ = DCMZLIBOUTPUTFILTER_BUFSIZE - OFstatic_cast(offile_off_t, zstream_->avail_out); + } + + result = (buflen - OFstatic_cast(offile_off_t, zstream_->avail_in)); + } + return result; +} + +offile_off_t DcmZLibOutputFilter::write(const void *buf, offile_off_t buflen) +{ + if (status_.bad() || (current_ == NULL)) return 0; + + // flush output buffer if necessary + if (outputBufCount_ == DCMZLIBOUTPUTFILTER_BUFSIZE) flushOutputBuffer(); + + // compress pending input from input buffer + while (status_.good() && inputBufCount_ > 0 && outputBufCount_ < DCMZLIBOUTPUTFILTER_BUFSIZE) + { + compressInputBuffer(OFFalse); + if (outputBufCount_ == DCMZLIBOUTPUTFILTER_BUFSIZE) flushOutputBuffer(); + } + + const unsigned char *data = OFstatic_cast(const unsigned char *, buf); + offile_off_t result = 0; + + // compress user data only if input buffer is empty + if (inputBufCount_ == 0) + { + while (status_.good() && (buflen > result) && outputBufCount_ < DCMZLIBOUTPUTFILTER_BUFSIZE) + { + result += compress(data+result, buflen-result, OFFalse); + if (outputBufCount_ == DCMZLIBOUTPUTFILTER_BUFSIZE) flushOutputBuffer(); + } + } + + // finally stuff as much into the input buffer as possible + result += fillInputBuffer(data+result, buflen-result); + + // total number of bytes consumed from input + return result; +} + + +void DcmZLibOutputFilter::flush() +{ + if (status_.good() && current_) + { + // flush output buffer first + if (outputBufCount_ == DCMZLIBOUTPUTFILTER_BUFSIZE) flushOutputBuffer(); + + // compress pending input from input buffer + while (status_.good() && inputBufCount_ > 0 && outputBufCount_ < DCMZLIBOUTPUTFILTER_BUFSIZE) + { + compressInputBuffer(OFTrue); + if (outputBufCount_ == DCMZLIBOUTPUTFILTER_BUFSIZE) flushOutputBuffer(); + } + + while (status_.good() && (! flushed_) && outputBufCount_ < DCMZLIBOUTPUTFILTER_BUFSIZE) + { + // create output from compression engine until end of compressed stream + compress(NULL, 0, OFTrue); + if (outputBufCount_ == DCMZLIBOUTPUTFILTER_BUFSIZE) flushOutputBuffer(); + } + + // final attempt to flush output buffer + if (outputBufCount_ > 0) flushOutputBuffer(); + } +} + + +void DcmZLibOutputFilter::append(DcmConsumer& consumer) +{ + current_ = &consumer; +} + +#else /* WITH_ZLIB */ + +/* make sure that the object file is not completely empty if compiled + * without zlib because some linkers might fail otherwise. + */ +void dcostrmz_dummy_function() +{ + return; +} + +#endif /* WITH_ZLIB */ diff --git a/dcmdata/libsrc/dcpath.cc b/dcmdata/libsrc/dcpath.cc new file mode 100644 index 00000000..e2f6a631 --- /dev/null +++ b/dcmdata/libsrc/dcpath.cc @@ -0,0 +1,941 @@ +/* + * + * Copyright (C) 2008-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Michael Onken + * + * Purpose: Class definitions for accessing DICOM dataset structures (items, + * sequences and leaf elements via string-based path access. + * + */ + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/dcmdata/dcpath.h" +#include "dcmtk/dcmdata/dcsequen.h" + + +/*******************************************************************/ +/* Implementation of class DcmPath */ +/*******************************************************************/ + +// Constructor +DcmPath::DcmPath() : + m_path() +{ +} + + +// Construct from existing path (kind of copy constructor) +DcmPath::DcmPath(const OFList& currentPath) : + m_path() +{ + OFListConstIterator(DcmPathNode*) it = currentPath.begin(); + OFListConstIterator(DcmPathNode*) endOfPath = currentPath.end(); + while (it != endOfPath) + { + m_path.push_back(new DcmPathNode( (*it)->m_obj, (*it)->m_itemNo )); + it++; + } +} + + +// Append a node to the path +void DcmPath::append(DcmPathNode* node) +{ + if (node != NULL) + m_path.push_back(node); // do any validity checking? +} + + +// Deletes last node from the path and frees corresponding memory +void DcmPath::deleteBackNode() +{ + DcmPathNode* node = m_path.back(); + m_path.pop_back(); + if (node) + { + delete node; node = NULL; + } +} + + +// Returns iterator to first element of the path +OFListIterator(DcmPathNode*) DcmPath::begin() +{ + return m_path.begin(); +} + + +// Returns iterator to last element of the path +DcmPathNode* DcmPath::back() +{ + return m_path.back(); +} + +// Returns iterator to the end of path, ie. dummy after actual last element +OFListIterator(DcmPathNode*) DcmPath::end() +{ + return m_path.end(); +} + + +// Returns number of path nodes in the path +Uint32 DcmPath::size() const +{ + return OFstatic_cast(Uint32, m_path.size()); +} + + +// Returns true if path is empty, ie. number of path nodes is zero +OFBool DcmPath::empty() const +{ + return (m_path.size() == 0); +} + + +// Returns string representation of the path +OFString DcmPath::toString() const +{ + OFListConstIterator(DcmPathNode*) it = m_path.begin(); + OFListConstIterator(DcmPathNode*) endOfList = m_path.end(); + OFString pathStr; DcmEVR vr; DcmObject* obj; + char buf[500]; + while (it != endOfList) + { + if ( ((*it) == NULL) || ((*it)->m_obj == NULL) ) + return "Invalid search result"; + obj = (*it)->m_obj; + vr = obj->ident(); + if ((vr == EVR_SQ) || ( obj->isLeaf()) ) + { + pathStr.append( OFconst_cast(DcmTag*, &obj->getTag())->getTagName() ); + it++; + } + else if ( (vr == EVR_item) || (vr == EVR_dataset) ) + { +#if SIZEOF_LONG == 8 + sprintf(buf, "[%u]", (*it)->m_itemNo); +#else + sprintf(buf, "[%lu]", (*it)->m_itemNo); +#endif + pathStr.append(buf); + it++; + if (it != endOfList) pathStr.append("."); + } + else + { + pathStr.append(""); + it++; + } + } + return pathStr; +} + + +// Checks whether a specific group number is used in the path's path nodes +OFBool DcmPath::containsGroup(const Uint16 groupNo) const +{ + OFListConstIterator(DcmPathNode*) it = m_path.begin(); + OFListConstIterator(DcmPathNode*) endOfList = m_path.end(); + while (it != endOfList) + { + DcmPathNode* node = *it; + if ( (node == NULL) || (node->m_obj == NULL) ) return OFFalse; + if (node->m_obj->getGTag() == groupNo) return OFTrue; + it++; + } + return OFFalse; +} + + +// Helper function for findOrCreatePath(). Parses item no from start of string +OFCondition DcmPath::parseItemNoFromPath(OFString& path, // inout + Uint32& itemNo, // out + OFBool& wasWildcard) // out +{ + wasWildcard = OFFalse; + itemNo = 0; + // check whether there is an item to parse + size_t closePos = path.find_first_of(']', 0); + if ( (closePos != OFString_npos) && (path[0] == '[') ) + { + long int parsedNo; + // try parsing item number; parsing for %lu would cause overflows in case of negative numbers + int parsed = sscanf(path.c_str(), "[%ld]", &parsedNo); + if (parsed == 1) + { + if (parsedNo < 0) + { + OFString errMsg = "Negative item number (not permitted) at beginning of path: "; errMsg += path; + return makeOFCondition(OFM_dcmdata, 25, OF_error, errMsg.c_str()); + } + itemNo = OFstatic_cast(Uint32, parsedNo); + if (closePos + 1 < path.length()) // if end of path not reached, cut off "." + closePos ++; + path.erase(0, closePos + 1); // remove item from path + return EC_Normal; + } + char aChar; + parsed = sscanf(path.c_str(), "[%c]", &aChar); + if ( (parsed == 1) && (aChar =='*') ) + { + wasWildcard = OFTrue; + if (closePos + 1 < path.length()) // if end of path not reached, cut off "." + closePos ++; + path.erase(0, closePos + 1); // remove item from path + return EC_Normal; + } + } + OFString errMsg = "Unable to parse item number at beginning of path: "; errMsg += path; + return makeOFCondition(OFM_dcmdata, 25, OF_error, errMsg.c_str()); +} + + +// Function that parses a tag from the beginning of a path string. +OFCondition DcmPath::parseTagFromPath(OFString& path, // inout + DcmTag& tag) // out +{ + OFCondition result; + size_t pos = OFString_npos; + + // In case we have a tag "(gggg,xxxx)" + if ( path[0] == '(') + { + pos = path.find_first_of(')', 0); + if (pos != OFString_npos) + result = DcmTag::findTagFromName(path.substr(1, pos - 1).c_str() /* "gggg,eeee" */, tag); + else + { + OFString errMsg("Unable to parse tag at beginning of path: "); errMsg += path; + return makeOFCondition(OFM_dcmdata, 25, OF_error, errMsg.c_str()); + } + pos++; // also cut off closing bracket + } + // otherwise we could have a dictionary name + else + { + // maybe an item follows + pos = path.find_first_of('[', 0); + if (pos == OFString_npos) + result = DcmTag::findTagFromName(path.c_str(), tag); // check full path + else + result = DcmTag::findTagFromName(path.substr(0, pos).c_str(), tag); // parse path up to "[" char + } + // construct error message if necessary and return + if (result.bad()) + { + OFString errMsg("Unable to parse tag/dictionary name at beginning of path: "); errMsg += path; + return makeOFCondition(OFM_dcmdata, 25, OF_error, errMsg.c_str()); + } + // else remove parsed tag from path and return success + else + path.erase(0, pos); + return EC_Normal; +} + + +// Destructor, frees memory of path nodes (but not of underlying DICOM objects) +DcmPath::~DcmPath() +{ + // free dynamically allocated memory + while (m_path.size() != 0) + { + DcmPathNode* node = m_path.front(); + delete node; node = NULL; + m_path.pop_front(); + } +} + + +// Seperate a string path into the different nodes +OFCondition DcmPath::separatePathNodes(const OFString& path, + OFList& result) +{ + OFString pathStr(path); + OFCondition status = EC_Normal; + OFBool nextIsItem = OFTrue; + Uint32 itemNo = 0; + OFBool isWildcard = OFFalse; + + // initialize parsing loop + if (!pathStr.empty()) + { + if (pathStr[0] != '[') + nextIsItem = OFFalse; + } + + char buf[100]; + // parse node for node and only stop if error occurs or parsing completes + while ( !pathStr.empty() ) + { + if (nextIsItem) + { + status = parseItemNoFromPath(pathStr, itemNo, isWildcard); + if (status.bad()) return status; + if (isWildcard) + result.push_back("[*]"); + else + { +#if SIZEOF_LONG == 8 + if (sprintf(buf, "[%u]", itemNo) < 2) return EC_IllegalParameter; +#else + if (sprintf(buf, "[%lu]", itemNo) < 2) return EC_IllegalParameter; +#endif + result.push_back(buf); + } + nextIsItem = OFFalse; + } + else + { + DcmTag tag; + status = parseTagFromPath(pathStr, tag); + if (status.bad()) + return status; + if (sprintf(buf, "(%04X,%04X)", tag.getGroup(), tag.getElement()) != 11) + return EC_IllegalParameter; + result.push_back(buf); + nextIsItem = OFTrue; + } + } + return status; +} + + +/*******************************************************************/ +/* Implementation of class DcmPathProcessor */ +/*******************************************************************/ + + +// Constructor, constructs an empty path processor +DcmPathProcessor::DcmPathProcessor() : + m_currentPath(), + m_results(), + m_createIfNecessary(OFFalse), + m_checkPrivateReservations(OFTrue), + m_itemWildcardsEnabled(OFTrue) +{ +} + + +// enables (class default:enabled) or disables checking of private reservations +void DcmPathProcessor::checkPrivateReservations(const OFBool doChecking) +{ + m_checkPrivateReservations = doChecking; +} + + +// enables (class default:enabled) or disables support for item wildcards +void DcmPathProcessor::setItemWildcardSupport(const OFBool supported) +{ + m_itemWildcardsEnabled = supported; +} + + +// Permits finding and creating DICOM object hierarchies based on a path string +OFCondition DcmPathProcessor::findOrCreatePath(DcmObject* obj, + const OFString& path, + OFBool createIfNecessary) +{ + // check input parameters + if ( (obj == NULL) || path.empty()) + return EC_IllegalParameter; + + if (!m_itemWildcardsEnabled) + { + if (path.find('*') != OFString_npos) + { + return makeOFCondition(OFM_dcmdata, 25, OF_error, "Item wildcard '*' found in path but wildcards disabled"); + } + } + clear(); + m_createIfNecessary = createIfNecessary; + + // do real work in private member functions + OFString pathCopy = path; + if ((obj->ident() == EVR_item) || (obj->ident() == EVR_dataset)) + return findOrCreateItemPath(OFstatic_cast(DcmItem*, obj), pathCopy); + else if (obj->ident() == EVR_SQ) + return findOrCreateSequencePath(OFstatic_cast(DcmSequenceOfItems*, obj), pathCopy); + else + return EC_IllegalParameter; +} + + +// Permits deleting DICOM object hierarchies based on a path string +OFCondition DcmPathProcessor::findOrDeletePath(DcmObject* obj, + const OFString& path, + Uint32& numDeleted) +{ + // check input parameters + if ( (obj == NULL) || path.empty()) + return EC_IllegalParameter; + numDeleted = 0; + if (!m_itemWildcardsEnabled) + { + if (path.find('*') != OFString_npos) + { + return makeOFCondition(OFM_dcmdata, 25, OF_error, "Item wildcard '*' found in path but wildcards disabled"); + } + } + + // search + m_createIfNecessary = OFFalse; + OFString pathCopy = path; + OFCondition result; + clear(); + if ((obj->ident() == EVR_item) || (obj->ident() == EVR_dataset)) + result = findOrCreateItemPath(OFstatic_cast(DcmItem*, obj), pathCopy); + else if (obj->ident() == EVR_SQ) + result = findOrCreateSequencePath(OFstatic_cast(DcmSequenceOfItems*, obj), pathCopy); + else + return EC_IllegalParameter; + if (result.bad()) return result; + + // check results + OFList resultPaths; + Uint32 numPaths = getResults(resultPaths); + if (numPaths == 0) return EC_IllegalCall; // should never happen at this point + OFListIterator(DcmPath*) pathIt = resultPaths.begin(); + OFListIterator(DcmPath*) endIt = resultPaths.end(); + while (pathIt != endIt) + { + // get last item/element from path which should be deleted + DcmPathNode* nodeToDelete = (*pathIt)->back(); + if ( (nodeToDelete == NULL) || (nodeToDelete->m_obj == NULL) ) return EC_IllegalCall; + + // if it's not an item, delete element from item. + // deletes DICOM content of node but not node itself (done later) + if (nodeToDelete->m_obj->ident() != EVR_item) + { + result = deleteLastElemFromPath(obj, *pathIt, nodeToDelete); + } + // otherwise we need to delete an item from a sequence + else + { + result = deleteLastItemFromPath(obj, *pathIt, nodeToDelete); + } + if (result.bad()) return result; + // if success, remove node from path and clear node memory + (*pathIt)->deleteBackNode(); + numDeleted++; + pathIt++; + } + return result; +} + + +// Get results of a an operation started before (e. g. findOrCreatePath()) +Uint32 DcmPathProcessor::getResults(OFList& searchResults) +{ + if (m_results.size() > 0) + { + // explicitely copy (shallow) + OFListIterator(DcmPath*) it = m_results.begin(); + while (it != m_results.end()) + { + searchResults.push_back(*it); + it++; + } + } + return OFstatic_cast(Uint32, m_results.size()); +} + +// applies a string path (optionally with value) to a dataset +OFCondition DcmPathProcessor::applyPathWithValue(DcmDataset* dataset, + const OFString& overrideKey) +{ + if (dataset == NULL) return EC_IllegalCall; + if (overrideKey.empty()) return EC_Normal; + OFString path = overrideKey; + OFString value; + size_t pos = path.find('='); + // separate tag from value if there is one + if (pos != OFString_npos) + { + value = path.substr(pos + 1); // value now contains value + path.erase(pos); // pure path without value + } + clear(); + + // create path + OFCondition result = findOrCreatePath(dataset, path, OFTrue /* create if necessary */); + if (result.bad()) + return result; + + // prepare for value insertion + OFListConstIterator(DcmPath*) it = m_results.begin(); + OFListConstIterator(DcmPath*) endList = m_results.end(); + DcmPathNode* last = (*it)->back(); + if (last == NULL) return EC_IllegalCall; + // if value is specified, be sure path does not end with item + if ( !last->m_obj->isLeaf() ) + { + if (value.empty()) + return EC_Normal; + else + return makeOFCondition(OFM_dcmdata, 25, OF_error, "Cannot insert value into path ending with item or sequence"); + } + // insert value into each element affected by path + while (it != endList) + { + last = (*it)->back(); + if (last == NULL) return EC_IllegalCall; + DcmElement* elem = OFstatic_cast(DcmElement*, last->m_obj); + if (elem == NULL) return EC_IllegalCall; + result = elem->putString(value.c_str()); + if (result.bad()) + break; + it++; + } + return result; +} + + +// Resets status (including results) of DcmPathProcessor and frees corresponding memory +void DcmPathProcessor::clear() +{ + while (m_results.size() != 0) + { + DcmPath* result = m_results.front(); + if (result != NULL) + { + delete result; + result = NULL; + } + m_results.pop_front(); + } + + while (m_currentPath.size() != 0) + { + DcmPathNode* node = m_currentPath.front(); + if (node != NULL) + { + delete node; + node = NULL; + } + m_currentPath.pop_front(); + } + +} + + +// Destructor, frees memory by calling clear() +DcmPathProcessor::~DcmPathProcessor() +{ + clear(); +} + + +/* protected helper functions */ + +// Helper function that deletes last DICOM element from a path from the DICOM hierarchy +OFCondition DcmPathProcessor::deleteLastElemFromPath(DcmObject* objSearchedIn, + DcmPath* path, + DcmPathNode* toDelete) +{ + // item containing the element to delete + DcmItem* containingItem = NULL; + if ( path->size() == 1) + { + // if we have only a single elem in path, given object must be cont. item + if ( (objSearchedIn->ident() != EVR_item) && (objSearchedIn->ident() != EVR_dataset) ) + return makeOFCondition(OFM_dcmdata, 25, OF_error, "Cannot search leaf element in object being not an item"); + containingItem = OFstatic_cast(DcmItem*, objSearchedIn); + } + else + { + // get containing item from path which is the penultimate in the path + OFListIterator(DcmPathNode*) temp = path->end(); + temp--; temp--; + if (*temp == NULL) return EC_IllegalCall; // never happens here... + if ( (*temp)->m_obj == NULL ) return EC_IllegalCall; + if ( (*temp)->m_obj->ident() != EVR_item) // (no test for dataset needed) + return makeOFCondition(OFM_dcmdata, 25, OF_error, "Cannot search leaf element in object being not an item"); + containingItem = OFstatic_cast(DcmItem*, (*temp)->m_obj); + } + if (containingItem == NULL) return EC_IllegalCall; + OFCondition result = containingItem->findAndDeleteElement(toDelete->m_obj->getTag(), OFFalse, OFFalse); + return result; +} + + +// Helper function that deletes last DICOM item from a path from the DICOM hierarchy +OFCondition DcmPathProcessor::deleteLastItemFromPath(DcmObject* objSearchedIn, + DcmPath* path, + DcmPathNode* toDelete) +{ + DcmSequenceOfItems* containingSeq = NULL; + if ( path->size() == 1) + { + // if we have only a single elem in path, given object must be cont. item + if (objSearchedIn->ident() != EVR_SQ) + return makeOFCondition(OFM_dcmdata, 25, OF_error, "Cannot search item in object being not a sequence"); + containingSeq = OFstatic_cast(DcmSequenceOfItems*, objSearchedIn); + } + else + { + // get containing item from path which is the penultimate in the path + OFListIterator(DcmPathNode*) temp = path->end(); + temp--; temp--; + if (*temp == NULL) return EC_IllegalCall; // never happens here... + if ( (*temp)->m_obj == NULL ) return EC_IllegalCall; + if ( (*temp)->m_obj->ident() != EVR_SQ) + return makeOFCondition(OFM_dcmdata, 25, OF_error, "Cannot search item in object being not a sequence"); + containingSeq = OFstatic_cast(DcmSequenceOfItems*, (*temp)->m_obj); + } + if (containingSeq == NULL ) return EC_IllegalCall; + DcmItem* item2BDeleted = containingSeq->remove(OFstatic_cast(DcmItem*, toDelete->m_obj)); + if ( item2BDeleted == NULL ) + return EC_IllegalCall; // should not happen here... + delete item2BDeleted; item2BDeleted = NULL; + return EC_Normal; +} + + +// Helper function that does work for findOrCreatePath() +OFCondition DcmPathProcessor::findOrCreateItemPath(DcmItem* item, + OFString& path) +{ + if (item == NULL) + return EC_IllegalParameter; + + if (path.empty()) + return EC_IllegalParameter; + + OFString restPath(path); + OFCondition status = EC_Normal; + DcmTag tag; + OFString privCreator; + OFBool newlyCreated = OFFalse; // denotes whether an element was created + DcmElement* elem = NULL; + DcmPath* currentResult = NULL; + + // parse tag + status = DcmPath::parseTagFromPath(restPath, tag); + if (status.bad()) + return status; + + // insert element or sequence + if ( !(item->tagExists(tag)) ) // do not to overwrite existing tags + { + if (m_createIfNecessary) + { + // private tags needs special handling, e. g. checking reservation + if (tag.isPrivate() && m_checkPrivateReservations) + { + status = checkPrivateTagReservation(item, tag); + if (status.bad()) return status; + } + elem = newDicomElement(tag); + if (elem == NULL) + return EC_IllegalCall; + status = item->insert(elem, OFTrue); + if (status.bad()) + { + delete elem; elem = NULL; + return status; + } + newlyCreated = OFTrue; + } + else + return EC_TagNotFound; + } + + // get element + status = item->findAndGetElement(tag, elem); + if (status.bad()) + return EC_CorruptedData; // should not happen + + // start recursion if element was a sequence + if (tag.getEVR() == EVR_SQ) + { + DcmSequenceOfItems* seq = NULL; + seq = OFstatic_cast(DcmSequenceOfItems*, elem); + if (!seq) + status = EC_IllegalCall; // should not happen + else + { + // if sequence could be inserted and there is nothing more to do: add current path to results and return success + if (restPath.empty()) + { + currentResult = new DcmPath(m_currentPath); + currentResult->append(new DcmPathNode(elem,0)); + m_results.push_back(currentResult); + return EC_Normal; + } + // start recursion if there is path left + DcmPathNode* node = new DcmPathNode(seq, 0); + m_currentPath.push_back(node); + status = findOrCreateSequencePath(seq, restPath); + m_currentPath.pop_back(); // avoid side effects + delete node; + } + } + else if (restPath.empty()) // we inserted a leaf element: path must be completed + { + // add element and add current path to overall results; then return success + currentResult = new DcmPath(m_currentPath); + currentResult->append(new DcmPathNode(elem, 0)); + m_results.push_back(currentResult); + return EC_Normal; + } + else // we inserted a leaf element but there is path left -> error + status = makeOFCondition(OFM_dcmdata, 25, OF_error, "Invalid Path: Non-sequence tag found with rest path following"); + + // in case of errors: delete result path copy and delete DICOM element if it was newly created + if ( status.bad() && (elem != NULL) ) + { + m_results.remove(currentResult); // remove from search result + if (currentResult) + { + delete currentResult; + currentResult = NULL; + } + if (newlyCreated) // only delete from this dataset and memory if newly created ("undo") + { + if (item->findAndDeleteElement(tag).bad()) + delete elem; // delete manually if not found in dataset + } + elem = NULL; + } + return status; +} + + +// Helper function that does work for findOrCreatePath() +OFCondition DcmPathProcessor::findOrCreateSequencePath(DcmSequenceOfItems* seq, + OFString& path) +{ + if (seq == NULL) + return EC_IllegalParameter; + + // prepare variables + OFString restPath(path); + OFCondition status = EC_Normal; + DcmItem* resultItem = NULL; + Uint32 itemNo = 0; + Uint32 newlyCreated = 0; // number of items created (appended) (only non-wildcard mode) + Uint32 newPathsCreated = 0; // wildcard mode: number of paths found + + // parse item number + OFBool isWildcard = OFFalse; + status = DcmPath::parseItemNoFromPath(restPath, itemNo, isWildcard); + if (status.bad()) + return status; + + // wildcard code: add result path for every matching item + if (isWildcard) + { + // if there are no items -> no results are found + Uint32 numItems = OFstatic_cast(Uint32, seq->card()); + if (numItems == 0) + { + if (!m_createIfNecessary) + return EC_TagNotFound; + else + return makeOFCondition(OFM_dcmdata, 25, OF_error, "Cannot insert unspecified number (wildcard) of items into sequence"); + } + + // copy every item to result + for (itemNo = 0; itemNo < numItems; itemNo++) + { + DcmItem* oneItem = seq->getItem(itemNo); + /* if we found an item that matches, copy current result path, then + add the item found and finally start recursive search for + that item. + */ + if (oneItem != NULL) + { + // if the item was the last thing to parse, add list to results and return + if (restPath.empty()) + { + DcmPathNode* itemNode = new DcmPathNode(oneItem, itemNo); + DcmPath* currentResult = new DcmPath(m_currentPath); + currentResult->append(itemNode); + m_results.push_back(currentResult); + newPathsCreated++; + } + // else there is path left: continue searching in the new item + else + { + DcmPathNode* itemNode = new DcmPathNode(oneItem, itemNo); + m_currentPath.push_back(itemNode); + status = findOrCreateItemPath(oneItem, restPath); + m_currentPath.pop_back(); // avoid side effects + delete itemNode; itemNode = NULL; + if (status.bad()) // we did not find the path in that item + { + if (status != EC_TagNotFound) + return status; + } + else + { + newPathsCreated++; + } + } + } + else // should be possible to get every item, however... + return EC_IllegalCall; + } + // if there was at least one result, success can be returned + if (newPathsCreated != 0) + { + return EC_Normal; + } + else + return EC_TagNotFound; + } + + + /* no wildcard, just select single item or create it if necessary */ + + // if item already exists, just grab a reference + if (itemNo < seq->card()) + resultItem = seq->getItem(itemNo); + // if item does not exist, create new if desired + else if (m_createIfNecessary) + { + // create and insert items until desired item count is reached + while ( (seq->card() <= itemNo) || (status.bad()) ) + { + resultItem = new DcmItem(); + if (!resultItem) return EC_MemoryExhausted; + status = seq->insert(resultItem); + if (status.bad()) + delete resultItem; + else + newlyCreated++; + } + } + // item does not exist and should not be created newly, return "path not found" + else + return EC_TagNotFound; + + // at this point, the item has been obtained and everyhthing is fine so far + + // finding/creating the path was successful. now check whether there is more to do + if (!restPath.empty()) + { + // push new item to result path and continue + DcmPathNode* itemNode = new DcmPathNode(resultItem, itemNo); + m_currentPath.push_back(itemNode); + status = findOrCreateItemPath(resultItem, restPath); + m_currentPath.pop_back(); // avoid side effects to input parameter + delete itemNode; itemNode = NULL; + // in case of no success, delete any items that were newly created and return error + if (status.bad()) + { + for (Uint32 i=newlyCreated; i > 0; i--) + { + DcmItem* todelete = seq->remove(i - 1); + if (todelete != NULL) + { + delete todelete; + todelete = NULL; + } + } + return status; + } + } + else // finally everything was successful + { + DcmPathNode* itemNode = new DcmPathNode(resultItem, itemNo); + m_currentPath.push_back(itemNode); + m_results.push_back(new DcmPath(m_currentPath)); + m_currentPath.pop_back(); // avoid side effects + delete itemNode; itemNode = NULL; + status = EC_Normal; + } + return status; +} + + +DcmTagKey DcmPathProcessor::calcPrivateReservationTag(const DcmTagKey &privateKey) +{ + DcmTagKey reservationTag(0xFFFF, 0xFFFF); + // if not a private key is given return "error" + if (!privateKey.isPrivate()) + return reservationTag; + // if the private key given is already a reservation key, return it + if (privateKey.isPrivateReservation()) + return privateKey; + + // Calculate corresponding private creator element + Uint16 elemNo = privateKey.getElement(); + // Get yz from given element number wxyz, groups stays the same + elemNo = OFstatic_cast(Uint16, elemNo >> 8); + reservationTag.setGroup(privateKey.getGroup()); + reservationTag.setElement(elemNo); + return reservationTag; +} + + +OFCondition DcmPathProcessor::checkPrivateTagReservation(DcmItem* item, + const DcmTagKey& tagKey, + const OFString& privateCreator) +{ + // if this is already a private reservation, there is nothing to do + if (!tagKey.isPrivateReservation()) + { + DcmTagKey reservationKey = calcPrivateReservationTag(tagKey); + if (reservationKey == DCM_UndefinedTagKey) + { + OFString msg("Unable to compute private reservation for tag: "); msg += tagKey.toString(); + return makeOFCondition(OFM_dcmdata, 25, OF_error, msg.c_str()); + } + if (!item->tagExists(reservationKey)) + { + OFString msg("Private reservation missing for tag: "); msg += tagKey.toString(); + return makeOFCondition(OFM_dcmdata, 25, OF_error, msg.c_str()); + } + else + { + // set private creator for new element + OFString actualPrivateCreator; + if (item->findAndGetOFString(reservationKey, actualPrivateCreator).bad() || (actualPrivateCreator.empty())) + { + OFString msg = "Invalid or empty private creator tag: "; msg += reservationKey.toString(); + return makeOFCondition(OFM_dcmdata, 25, OF_error, msg.c_str()); + } + else if (!privateCreator.empty()) + { + // check whether private creator is correct + if (actualPrivateCreator != privateCreator) + { + OFString msg = "Private creator string ("; msg += actualPrivateCreator; msg += ") other than expected ( "; msg += privateCreator; msg += privateCreator; + return makeOFCondition(OFM_dcmdata, 25, OF_error, msg.c_str()); + } + } + } + } + return EC_Normal; +} + + + +OFCondition DcmPathProcessor::checkPrivateTagReservation(DcmItem* item /* in */, + DcmTag& tag /* inout */, + const OFString& privateCreator) +{ + OFCondition result = checkPrivateTagReservation(item, tag.getXTag(), privateCreator); + if (result.good()) + { + // tell tag its private creator and VR + tag.setPrivateCreator(privateCreator.c_str()); + tag.lookupVRinDictionary(); // not done automatically when saving + } + return result; +} + diff --git a/dcmdata/libsrc/dcpcache.cc b/dcmdata/libsrc/dcpcache.cc new file mode 100644 index 00000000..918bf56b --- /dev/null +++ b/dcmdata/libsrc/dcpcache.cc @@ -0,0 +1,106 @@ +/* + * + * Copyright (C) 2002-2010, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: ofstd + * + * Author: Marco Eichelberg + * + * Purpose: general purpose 32-bit CRC in C++ + * Code is based on the CRC32 implementation (C)1986 Gary S. Brown + * + */ + + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ +#include "dcmtk/dcmdata/dcpcache.h" +#include "dcmtk/dcmdata/dcelem.h" /* for DcmElement, DcmObject */ + +DcmPrivateTagCacheEntry::DcmPrivateTagCacheEntry(const DcmTagKey& tk, const char *pc) +: tagKey(tk) +, privateCreator(pc) +{ +} + + +DcmPrivateTagCacheEntry::~DcmPrivateTagCacheEntry() +{ +} + + +const char *DcmPrivateTagCacheEntry::getPrivateCreator() const +{ + return privateCreator.c_str(); +} + + +OFBool DcmPrivateTagCacheEntry::isPrivateCreatorFor(const DcmTagKey& tk) const +{ + return (tagKey.getGroup() == tk.getGroup()) && + ((tagKey.getElement() << 8) == (tk.getElement() & 0xff00)); +} + +/* ======================================================================= */ + +DcmPrivateTagCache::DcmPrivateTagCache() +: list_() +{ +} + + +DcmPrivateTagCache::~DcmPrivateTagCache() +{ + clear(); +} + + +void DcmPrivateTagCache::clear() +{ + OFListIterator(DcmPrivateTagCacheEntry *) first = list_.begin(); + OFListIterator(DcmPrivateTagCacheEntry *) last = list_.end(); + while (first != last) + { + delete (*first); + first = list_.erase(first); + } +} + + +const char *DcmPrivateTagCache::findPrivateCreator(const DcmTagKey& tk) const +{ + OFListConstIterator(DcmPrivateTagCacheEntry *) first = list_.begin(); + OFListConstIterator(DcmPrivateTagCacheEntry *) last = list_.end(); + while (first != last) + { + if ((*first)->isPrivateCreatorFor(tk)) return (*first)->getPrivateCreator(); + ++first; + } + return NULL; +} + + +void DcmPrivateTagCache::updateCache(DcmObject *dobj) +{ + if (dobj) + { + const DcmTag& tag = dobj->getTag(); + if (dobj->isLeaf() && (tag.getGTag() & 1) && (tag.getETag() <= 0xff) && (tag.getETag() >= 0x10)) + { + // dobj is DcmElement containing private creator + char *c = NULL; + if ((OFstatic_cast(DcmElement *, dobj)->getString(c)).good() && c) + { + list_.push_back(new DcmPrivateTagCacheEntry(tag, c)); + } + } + } +} diff --git a/dcmdata/libsrc/dcpixel.cc b/dcmdata/libsrc/dcpixel.cc new file mode 100644 index 00000000..6e9b82ff --- /dev/null +++ b/dcmdata/libsrc/dcpixel.cc @@ -0,0 +1,1150 @@ +/* + * + * Copyright (C) 1997-2010, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Andreas Barth + * + * Purpose: class DcmPixelData + * + */ + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ +#include "dcmtk/dcmdata/dcpixel.h" +#include "dcmtk/dcmdata/dccodec.h" +#include "dcmtk/dcmdata/dcpixseq.h" +#include "dcmtk/dcmdata/dcdeftag.h" +#include "dcmtk/dcmdata/dcitem.h" + +// +// class DcmRepresentationEntry +// + +DcmRepresentationEntry::DcmRepresentationEntry( + const E_TransferSyntax rt, + const DcmRepresentationParameter *rp, + DcmPixelSequence * ps) + : repType(rt), + repParam(NULL), + pixSeq(ps) +{ + if (rp) + repParam = rp->clone(); +} + +DcmRepresentationEntry::DcmRepresentationEntry( + const DcmRepresentationEntry & oldEntry) + : repType(oldEntry.repType), + repParam(NULL), + pixSeq(NULL) +{ + if (oldEntry.repParam) + repParam = oldEntry.repParam->clone(); + pixSeq = new DcmPixelSequence(*(oldEntry.pixSeq)); +} + +DcmRepresentationEntry::~DcmRepresentationEntry() +{ + delete repParam; + delete pixSeq; +} + +OFBool +DcmRepresentationEntry::operator==(const DcmRepresentationEntry & x) const +{ + return (repType == x.repType) && + ((x.repParam == NULL && repParam == NULL) || + ((x.repParam != NULL) && (repParam != NULL) && (*(x.repParam) == *repParam))); +} + +// +// class DcmPixelData +// + +// Constructors / Deconstructors + +DcmPixelData::DcmPixelData( + const DcmTag & tag, + const Uint32 len) + : DcmPolymorphOBOW(tag, len), + repList(), + repListEnd(), + original(), + current(), + existUnencapsulated(OFFalse), + alwaysUnencapsulated(OFFalse), + unencapsulatedVR(EVR_UNKNOWN), + pixelSeqForWrite(NULL) +{ + repListEnd = repList.end(); + current = original = repListEnd; + if (getTag().getEVR() == EVR_ox) setTagVR(EVR_OW); + unencapsulatedVR = getTag().getEVR(); + recalcVR(); +} + +DcmPixelData::DcmPixelData( + const DcmPixelData & oldPixelData) + : DcmPolymorphOBOW(oldPixelData), + repList(), + repListEnd(), + original(), + current(), + existUnencapsulated(oldPixelData.existUnencapsulated), + alwaysUnencapsulated(oldPixelData.alwaysUnencapsulated), + unencapsulatedVR(oldPixelData.unencapsulatedVR), + pixelSeqForWrite(NULL) +{ + repListEnd = repList.end(); + original = repListEnd; + current = original; + recalcVR(); + DcmRepresentationListConstIterator oldEnd(oldPixelData.repList.end()); + for (DcmRepresentationListConstIterator it(oldPixelData.repList.begin()); + it != oldEnd; + ++it) + { + DcmRepresentationEntry * repEnt = new DcmRepresentationEntry(**it); + repList.push_back(repEnt); + if (it == oldPixelData.original) + original = --repList.end(); + + if (it == oldPixelData.current) + { + current = --repList.end(); + recalcVR(); + } + } +} + + +DcmPixelData::~DcmPixelData() +{ + for (DcmRepresentationListIterator it(repList.begin()); + it != repListEnd; + ++it) + { + delete *it; + *it = NULL; + } +} + +DcmPixelData &DcmPixelData::operator=(const DcmPixelData &obj) +{ + if (this != &obj) + { + DcmPolymorphOBOW::operator=(obj); + existUnencapsulated = obj.existUnencapsulated; + alwaysUnencapsulated = obj.alwaysUnencapsulated; + unencapsulatedVR = obj.unencapsulatedVR; + pixelSeqForWrite = NULL; + repList.clear(); + repListEnd = repList.end(); + original = repListEnd; + current = original; + recalcVR(); + DcmRepresentationListConstIterator oldEnd(obj.repList.end()); + DcmRepresentationListConstIterator it(obj.repList.begin()); + while (it != oldEnd) + { + DcmRepresentationEntry *repEnt = new DcmRepresentationEntry(**it); + repList.push_back(repEnt); + if (it == obj.original) original = --repList.end(); + if (it == current) + { + current = --repList.end(); + recalcVR(); + } + ++it; + } + + } + return *this; +} + + +OFCondition DcmPixelData::copyFrom(const DcmObject& rhs) +{ + if (this != &rhs) + { + if (rhs.ident() != ident()) return EC_IllegalCall; + *this = OFstatic_cast(const DcmPixelData &, rhs); + } + return EC_Normal; +} + + +// methods in alphabetical order + +Uint32 +DcmPixelData::calcElementLength( + const E_TransferSyntax xfer, + const E_EncodingType enctype) +{ + DcmXfer xferSyn(xfer); + errorFlag = EC_Normal; + Uint32 elementLength = 0; + + if (xferSyn.isEncapsulated() && (! writeUnencapsulated(xfer))) + { + DcmRepresentationListIterator found; + errorFlag = + findConformingEncapsulatedRepresentation(xfer, NULL, found); + if (errorFlag == EC_Normal) + elementLength = (*found)->pixSeq->calcElementLength(xfer, enctype); + } + else if (existUnencapsulated) + elementLength = DcmPolymorphOBOW::calcElementLength(xfer, enctype); + else + errorFlag = EC_RepresentationNotFound; + + return elementLength; +} + + +OFBool +DcmPixelData::canChooseRepresentation( + const E_TransferSyntax repType, + const DcmRepresentationParameter * repParam) +{ + OFBool result = OFFalse; + DcmXfer toType(repType); + + const DcmRepresentationEntry findEntry(repType, repParam, NULL); + DcmRepresentationListIterator resultIt(repListEnd); + if ((!toType.isEncapsulated() && existUnencapsulated) || + (toType.isEncapsulated() && writeUnencapsulated(repType) && existUnencapsulated) || + (toType.isEncapsulated() && findRepresentationEntry(findEntry, resultIt) == EC_Normal)) + { + // representation found + result = OFTrue; + } + else + { + // representation not found, check if we have a codec that can create the + // desired representation. + if (original == repListEnd) + { + result = DcmCodecList::canChangeCoding(EXS_LittleEndianExplicit, toType.getXfer()); + } + else if (toType.isEncapsulated()) + { + result = DcmCodecList::canChangeCoding(EXS_LittleEndianExplicit, toType.getXfer()); + + if (!result) + { + // direct transcoding is not possible. Check if we can decode and then encode. + result = canChooseRepresentation(EXS_LittleEndianExplicit, NULL); + if (result) result = DcmCodecList::canChangeCoding(EXS_LittleEndianExplicit, toType.getXfer()); + } + } + else + { + result = DcmCodecList::canChangeCoding((*original)->repType, EXS_LittleEndianExplicit); + } + } + return result; +} + +OFBool +DcmPixelData::canWriteXfer( + const E_TransferSyntax newXfer, + const E_TransferSyntax /*oldXfer*/) +{ + DcmXfer newXferSyn(newXfer); + DcmRepresentationListIterator found; + OFBool result = existUnencapsulated && (!newXferSyn.isEncapsulated() || writeUnencapsulated(newXfer)); + + if (!result && newXferSyn.isEncapsulated()) + result = (findConformingEncapsulatedRepresentation(newXferSyn, NULL, found) == EC_Normal); + return result; +} + +OFCondition +DcmPixelData::chooseRepresentation( + const E_TransferSyntax repType, + const DcmRepresentationParameter * repParam, + DcmStack & pixelStack) +{ + OFCondition l_error = EC_CannotChangeRepresentation; + DcmXfer toType(repType); + + const DcmRepresentationEntry findEntry(repType, repParam, NULL); + DcmRepresentationListIterator result(repListEnd); + if ((!toType.isEncapsulated() && existUnencapsulated) || + (toType.isEncapsulated() && findRepresentationEntry(findEntry, result) == EC_Normal)) + { + // representation found + current = result; + recalcVR(); + l_error = EC_Normal; + } + else + { + if (original == repListEnd) + l_error = encode(EXS_LittleEndianExplicit, NULL, NULL, + toType, repParam, pixelStack); + else if (toType.isEncapsulated()) + l_error = encode((*original)->repType, (*original)->repParam, + (*original)->pixSeq, toType, repParam, pixelStack); + else + l_error = decode((*original)->repType, (*original)->repParam, + (*original)->pixSeq, pixelStack); + } + if (l_error.bad() && toType.isEncapsulated() && existUnencapsulated && writeUnencapsulated(repType)) + // Encoding failed so this will be written out unencapsulated + l_error = EC_Normal; + return l_error; +} + + +void +DcmPixelData::clearRepresentationList( + DcmRepresentationListIterator leaveInList) +{ + /* define iterators to go through all representations in the list */ + DcmRepresentationListIterator it(repList.begin()); + DcmRepresentationListIterator del; + + /* as long as we have not encountered the end of the */ + /* representation list, go through all representations */ + while (it != repListEnd) + { + /* if this representation shall not be left in the list */ + if (it != leaveInList) + { + /* delete representation and move it to the next representation */ + delete *it; + del = it++; + repList.erase(del); + } + /* else leave this representation in the list and just go to the next */ + else + ++it; + } +} + +OFCondition +DcmPixelData::decode( + const DcmXfer & fromType, + const DcmRepresentationParameter * fromParam, + DcmPixelSequence * fromPixSeq, + DcmStack & pixelStack) +{ + if (existUnencapsulated) return EC_Normal; + OFCondition l_error = DcmCodecList::decode(fromType, fromParam, fromPixSeq, *this, pixelStack); + if (l_error.good()) + { + existUnencapsulated = OFTrue; + current = repListEnd; + setVR(EVR_OW); + recalcVR(); + } + else + { + DcmPolymorphOBOW::putUint16Array(NULL,0); + existUnencapsulated = OFFalse; + } + return l_error; +} + + + +OFCondition +DcmPixelData::encode( + const DcmXfer & fromType, + const DcmRepresentationParameter * fromParam, + DcmPixelSequence * fromPixSeq, + const DcmXfer & toType, + const DcmRepresentationParameter *toParam, + DcmStack & pixelStack) +{ + OFCondition l_error = EC_CannotChangeRepresentation; + if (toType.isEncapsulated()) + { + DcmPixelSequence * toPixSeq = NULL; + if (fromType.isEncapsulated()) + { + l_error = DcmCodecList::encode(fromType.getXfer(), fromParam, fromPixSeq, + toType.getXfer(), toParam, toPixSeq, pixelStack); + } + else + { + Uint16 * pixelData; + l_error = DcmPolymorphOBOW::getUint16Array(pixelData); + Uint32 length = DcmPolymorphOBOW::getLength(); + if (l_error == EC_Normal) + { + l_error = DcmCodecList::encode(fromType.getXfer(), pixelData, length, + toType.getXfer(), toParam, toPixSeq, pixelStack); + } + } + + if (l_error.good()) + { + current = insertRepresentationEntry( + new DcmRepresentationEntry(toType.getXfer(), toParam, toPixSeq)); + recalcVR(); + } else delete toPixSeq; + + // if it was possible to convert one encapsulated syntax into + // another directly try it using decoding and encoding! + if (l_error.bad() && fromType.isEncapsulated()) + { + l_error = decode(fromType, fromParam, fromPixSeq, pixelStack); + if (l_error.good()) l_error = encode(EXS_LittleEndianExplicit, NULL, NULL, toType, toParam, pixelStack); + } + } + return l_error; +} + +OFCondition +DcmPixelData::findRepresentationEntry( + const DcmRepresentationEntry & findEntry, + DcmRepresentationListIterator & result) +{ + result = repList.begin(); + while(result != repListEnd && + (*result)->repType < findEntry.repType) + ++result; + + DcmRepresentationListIterator it(result); + + while(it != repListEnd && **it != findEntry) + ++it; + if (it == repListEnd || **it != findEntry) + return EC_RepresentationNotFound; + else + { + result = it; + return EC_Normal; + } +} + + +OFCondition +DcmPixelData::findConformingEncapsulatedRepresentation( + const DcmXfer & repTypeSyn, + const DcmRepresentationParameter * repParam, + DcmRepresentationListIterator & result) +{ + E_TransferSyntax repType = repTypeSyn.getXfer(); + result = repListEnd; + OFCondition l_error = EC_RepresentationNotFound; + // we are looking for an encapsulated representation + // of this pixel data element which meets both + // the transfer syntax and (if given) the representation + // parameter (i.e. quality factor for lossy JPEG). + if (repTypeSyn.isEncapsulated()) + { + // first we check the current (active) representation if any. + if ((current != repListEnd) && ((*current)->repType == repType) && + ((repParam==NULL) || (((*current)->repParam != NULL)&&(*(*current)->repParam == *repParam)))) + { + result = current; + l_error = EC_Normal; + } + else + { + // now we check all representations + DcmRepresentationListIterator it(repList.begin()); + OFBool found = OFFalse; + while (!found && (it != repListEnd)) + { + if ((*it)->repType == repType) + { + if ((repParam == NULL) || (((*it)->repParam != NULL)&&(*(*it)->repParam == *repParam))) + { + // repParam is NULL or matches the one we are comparing with + found = OFTrue; + result = it; + l_error = EC_Normal; + } else ++it; + } else ++it; + } + } + } + return l_error; +} + + +OFCondition +DcmPixelData::getEncapsulatedRepresentation( + const E_TransferSyntax repType, + const DcmRepresentationParameter * repParam, + DcmPixelSequence * & pixSeq) +{ + DcmRepresentationListIterator found; + DcmRepresentationEntry findEntry(repType, repParam, NULL); + if (findRepresentationEntry(findEntry, found) == EC_Normal) + { + pixSeq = (*found)->pixSeq; + return EC_Normal; + } + + return EC_RepresentationNotFound; +} + + +OFBool +DcmPixelData::hasRepresentation( + const E_TransferSyntax repType, + const DcmRepresentationParameter * repParam) +{ + DcmXfer repTypeSyn(repType); + DcmRepresentationListIterator found; + if (!repTypeSyn.isEncapsulated() && existUnencapsulated) + return OFTrue; + else if (repTypeSyn.isEncapsulated()) + return findConformingEncapsulatedRepresentation(repTypeSyn, repParam, found).good(); + return OFFalse; +} + + +Uint32 +DcmPixelData::getLength(const E_TransferSyntax xfer, + const E_EncodingType enctype) +{ + DcmXfer xferSyn(xfer); + errorFlag = EC_Normal; + Uint32 valueLength = 0; + + if (xferSyn.isEncapsulated() && !writeUnencapsulated(xfer)) + { + DcmRepresentationListIterator foundEntry; + errorFlag = findConformingEncapsulatedRepresentation( + xferSyn, NULL, foundEntry); + if (errorFlag == EC_Normal) + valueLength = (*foundEntry)->pixSeq->getLength(xfer, enctype); + } + else if (existUnencapsulated) + valueLength = DcmPolymorphOBOW::getLength(xfer, enctype); + else + errorFlag = EC_RepresentationNotFound; + + return valueLength; +} + + +void +DcmPixelData::getCurrentRepresentationKey( + E_TransferSyntax & repType, + const DcmRepresentationParameter * & repParam) +{ + if (current != repListEnd) + { + repType = (*current)->repType; + repParam = (*current)->repParam; + } + else + { + repType = EXS_LittleEndianExplicit; + repParam = NULL; + } +} + +void +DcmPixelData::getOriginalRepresentationKey( + E_TransferSyntax & repType, + const DcmRepresentationParameter * & repParam) +{ + if (original != repListEnd) + { + repType = (*original)->repType; + repParam = (*original)->repParam; + } + else + { + repType = EXS_LittleEndianExplicit; + repParam = NULL; + } +} + +DcmRepresentationListIterator +DcmPixelData::insertRepresentationEntry( + DcmRepresentationEntry * repEntry) +{ + DcmRepresentationListIterator insertedEntry; + DcmRepresentationListIterator result; + if (findRepresentationEntry(*repEntry, result).good()) + { + // this type of representation entry was already present in the list + if (repEntry != *result) + { + insertedEntry = repList.insert(result, repEntry); + + // delete old entry from representation list + delete *result; + repList.erase(result); + } + } + else + insertedEntry = repList.insert(result,repEntry); + return insertedEntry; +} + +void +DcmPixelData::print( + STD_NAMESPACE ostream&out, + const size_t flags, + const int level, + const char *pixelFileName, + size_t *pixelCounter) +{ + if (current == repListEnd) + printPixel(out, flags, level, pixelFileName, pixelCounter); + else + (*current)->pixSeq->print(out, flags, level, pixelFileName, pixelCounter); +} + +OFCondition +DcmPixelData::putUint8Array( + const Uint8 * byteValue, + const unsigned long length) +{ + // clear RepresentationList + clearRepresentationList(repListEnd); + OFCondition l_error = DcmPolymorphOBOW::putUint8Array(byteValue, length); + original = current = repListEnd; + recalcVR(); + existUnencapsulated = OFTrue; + return l_error; +} + +OFCondition +DcmPixelData::putUint16Array( + const Uint16 * wordValue, + const unsigned long length) +{ + // clear RepresentationList + clearRepresentationList(repListEnd); + OFCondition l_error = DcmPolymorphOBOW::putUint16Array(wordValue, length); + original = current = repListEnd; + recalcVR(); + existUnencapsulated = OFTrue; + return l_error; +} + +OFCondition +DcmPixelData::createUint8Array( + const Uint32 numBytes, + Uint8 * & bytes) +{ + OFCondition l_error = DcmPolymorphOBOW::createUint8Array(numBytes, bytes); + existUnencapsulated = OFTrue; + return l_error; +} + +OFCondition +DcmPixelData::createUint16Array( + const Uint32 numWords, + Uint16 * & words) +{ + OFCondition l_error = DcmPolymorphOBOW::createUint16Array(numWords, words); + existUnencapsulated = OFTrue; + return l_error; +} + +OFCondition +DcmPixelData::createValueFromTempFile( + DcmInputStreamFactory *factory, + const Uint32 length, + const E_ByteOrder byteOrder) +{ + OFCondition l_error = DcmPolymorphOBOW::createValueFromTempFile(factory, length, byteOrder); + existUnencapsulated = OFTrue; + return l_error; +} + +void +DcmPixelData::putOriginalRepresentation( + const E_TransferSyntax repType, + const DcmRepresentationParameter * repParam, + DcmPixelSequence * pixSeq) +{ + // delete RepresentationList + clearRepresentationList(repListEnd); + // delete unencapsulated representation + DcmPolymorphOBOW::putUint16Array(NULL,0); + existUnencapsulated = OFFalse; + // insert new Representation + current = original = insertRepresentationEntry( + new DcmRepresentationEntry(repType, repParam, pixSeq)); + recalcVR(); +} + +OFCondition +DcmPixelData::read( + DcmInputStream & inStream, + const E_TransferSyntax ixfer, + const E_GrpLenEncoding glenc, + const Uint32 maxReadLength) +{ + /* if this element's transfer state shows ERW_notInitialized, this is an illegal call */ + if (getTransferState() == ERW_notInitialized) + errorFlag = EC_IllegalCall; + else + { + /* if this is not an illegal call, go ahead */ + + /* if the transfer state is ERW_init, we need to prepare the reading of the pixel */ + /* data from the stream: remove all representations from the representation list. */ + if (getTransferState() == ERW_init) + clearRepresentationList(repListEnd); + + /* create a DcmXfer object based on the transfer syntax which was passed */ + DcmXfer ixferSyn(ixfer); + + /* determine if the pixel data is captured in native (uncompressed) or encapsulated + * (compressed) format. We only derive this information from the length field + * which is set to undefined length for encapsulated data because even in + * compressed transfer syntaxes the Icon Image Sequence may contain an + * uncompressed image. + */ + if (getLengthField() == DCM_UndefinedLength) + { + /* the pixel data is captured in encapsulated (compressed) format */ + + /* if the transfer state is ERW_init, we need to prepare */ + /* the reading of the pixel data from the stream. */ + if (getTransferState() == ERW_init) + { + current = insertRepresentationEntry( + new DcmRepresentationEntry( + ixfer, NULL, new DcmPixelSequence(getTag(), getLengthField()))); + recalcVR(); + original = current; + existUnencapsulated = OFFalse; + setTransferState(ERW_inWork); + + if (! ixferSyn.isEncapsulated()) + { + /* Special case: we have encountered a compressed image + * although we're decoding an uncompressed transfer syntax. + * This could be a compressed image stored without meta-header. + * For now, we just accept the data element; however, any attempt + * to write the dataset will fail because no suitable decoder + * is known. + */ + } + } + + /* conduct the reading process */ + errorFlag = + (*current)->pixSeq->read(inStream, ixfer, glenc, maxReadLength); + + /* if the errorFlag equals EC_Normal, all pixel data has been */ + /* read; hence, the transfer state has to be set to ERW_ready */ + if (errorFlag == EC_Normal) + setTransferState(ERW_ready); + } + else + { + /* the pixel data is captured in native (uncompressed) format */ + + /* if the transfer state is ERW_init, we need to prepare */ + /* the reading of the pixel data from the stream. */ + if (getTransferState() == ERW_init) + { + current = original = repListEnd; + unencapsulatedVR = getTag().getEVR(); + recalcVR(); + existUnencapsulated = OFTrue; + + if (ixferSyn.isEncapsulated()) + { + /* Special case: we have encountered an uncompressed image + * although we're decoding an encapsulated transfer syntax. + * This is probably an icon image. + */ + alwaysUnencapsulated = OFTrue; + } + } + + /* conduct the reading process */ + errorFlag = + DcmPolymorphOBOW::read(inStream, ixfer, glenc, maxReadLength); + } + } + + /* return result value */ + return errorFlag; +} + + +void +DcmPixelData::removeAllButCurrentRepresentations() +{ + clearRepresentationList(current); + if (current != repListEnd && existUnencapsulated) + { + DcmPolymorphOBOW::putUint16Array(NULL,0); + existUnencapsulated = OFFalse; + } + original = current; +} + + +void +DcmPixelData::removeAllButOriginalRepresentations() +{ + clearRepresentationList(original); + if (original != repListEnd && existUnencapsulated) + { + DcmPolymorphOBOW::putUint16Array(NULL,0); + existUnencapsulated = OFFalse; + } + current = original; + recalcVR(); +} + +OFCondition +DcmPixelData::removeOriginalRepresentation( + const E_TransferSyntax repType, + const DcmRepresentationParameter * repParam) +{ + OFCondition l_error = EC_Normal; + DcmXfer repTypeSyn(repType); + + if (!repTypeSyn.isEncapsulated()) + { + if (original != repListEnd) + { + if (current == original) + { + current = repListEnd; + recalcVR(); + } + repList.erase(original); + original = repListEnd; + } + else + l_error = EC_IllegalCall; + } + else + { + DcmRepresentationListIterator result; + DcmRepresentationEntry findEntry(repType, repParam, NULL); + if (findRepresentationEntry(findEntry, result) == EC_Normal) + { + if (result != original) + { + if (current == original) + { + current = result; + recalcVR(); + } + if (original == repListEnd) + { + DcmPolymorphOBOW::putUint16Array(NULL, 0); + existUnencapsulated = OFFalse; + } + else + repList.erase(original); + original = result; + } + else + l_error = EC_IllegalCall; + } + else + l_error = EC_RepresentationNotFound; + } + return l_error; +} + +OFCondition +DcmPixelData::removeRepresentation( + const E_TransferSyntax repType, + const DcmRepresentationParameter * repParam) +{ + OFCondition l_error = EC_Normal; + DcmXfer repTypeSyn(repType); + + if (!repTypeSyn.isEncapsulated()) + { + if (original != repListEnd && existUnencapsulated) + { + DcmPolymorphOBOW::putUint16Array(NULL, 0); + existUnencapsulated = OFFalse; + } + else + l_error = EC_CannotChangeRepresentation; + } + else + { + DcmRepresentationListIterator result; + DcmRepresentationEntry findEntry(repType, repParam, NULL); + if (findRepresentationEntry(findEntry, result) == EC_Normal) + { + if (original != result) + repList.erase(result); + else l_error = EC_CannotChangeRepresentation; + } + else + l_error = EC_RepresentationNotFound; + } + return l_error; +} + + +OFCondition +DcmPixelData::setCurrentRepresentationParameter( + const DcmRepresentationParameter * repParam) +{ + if (current != repListEnd) + { + if (repParam == NULL) + (*current)->repParam = NULL; + else + (*current)->repParam = repParam->clone(); + return EC_Normal; + } + return EC_RepresentationNotFound; +} + +OFCondition +DcmPixelData::setVR(DcmEVR vr) +{ + unencapsulatedVR = vr; + return DcmPolymorphOBOW::setVR(vr); +} + +void +DcmPixelData::transferEnd() +{ + DcmPolymorphOBOW::transferEnd(); + for (DcmRepresentationListIterator it(repList.begin()); + it != repListEnd; + ++it) + (*it)->pixSeq->transferEnd(); +} + +void +DcmPixelData::transferInit() +{ + DcmPolymorphOBOW::transferInit(); + for (DcmRepresentationListIterator it(repList.begin()); + it != repListEnd; + ++it) + (*it)->pixSeq->transferInit(); +} + +OFCondition DcmPixelData::write( + DcmOutputStream &outStream, + const E_TransferSyntax oxfer, + const E_EncodingType enctype, + DcmWriteCache *wcache) +{ + errorFlag = EC_Normal; + if (getTransferState() == ERW_notInitialized) errorFlag = EC_IllegalCall; + else + { + DcmXfer xferSyn(oxfer); + if (xferSyn.isEncapsulated() && (! writeUnencapsulated(oxfer))) + { + if (getTransferState() == ERW_init) + { + DcmRepresentationListIterator found; + errorFlag = findConformingEncapsulatedRepresentation(xferSyn, NULL, found); + if (errorFlag == EC_Normal) + { + current = found; + recalcVR(); + pixelSeqForWrite = (*found)->pixSeq; + setTransferState(ERW_inWork); + } + } + if (errorFlag == EC_Normal && pixelSeqForWrite) errorFlag = pixelSeqForWrite->write(outStream, oxfer, enctype, wcache); + if (errorFlag == EC_Normal) setTransferState(ERW_ready); + } + else if (existUnencapsulated) + { + current = repListEnd; + recalcVR(); + errorFlag = DcmPolymorphOBOW::write(outStream, oxfer, enctype, wcache); + } + else if (getValue() == NULL) + { + errorFlag = DcmPolymorphOBOW::write(outStream, oxfer, enctype, wcache); + } else errorFlag = EC_RepresentationNotFound; + } + return errorFlag; +} + +OFCondition DcmPixelData::writeXML( + STD_NAMESPACE ostream&out, + const size_t flags) +{ + if (current == repListEnd) + { + errorFlag = DcmPolymorphOBOW::writeXML(out, flags); + } else { + /* pixel sequence (encapsulated data) */ + errorFlag = (*current)->pixSeq->writeXML(out, flags); + } + return errorFlag; +} + +OFCondition DcmPixelData::writeSignatureFormat( + DcmOutputStream &outStream, + const E_TransferSyntax oxfer, + const E_EncodingType enctype, + DcmWriteCache *wcache) +{ + errorFlag = EC_Normal; + if (getTransferState() == ERW_notInitialized) errorFlag = EC_IllegalCall; + else if (getTag().isSignable()) + { + DcmXfer xferSyn(oxfer); + if (xferSyn.isEncapsulated() && (! writeUnencapsulated(oxfer))) + { + if (getTransferState() == ERW_init) + { + DcmRepresentationListIterator found; + errorFlag = findConformingEncapsulatedRepresentation(xferSyn, NULL, found); + if (errorFlag == EC_Normal) + { + current = found; + recalcVR(); + pixelSeqForWrite = (*found)->pixSeq; + setTransferState(ERW_inWork); + } + } + if (errorFlag == EC_Normal && pixelSeqForWrite) errorFlag = pixelSeqForWrite->writeSignatureFormat(outStream, oxfer, enctype, wcache); + if (errorFlag == EC_Normal) setTransferState(ERW_ready); + } + else if (existUnencapsulated) + { + current = repListEnd; + recalcVR(); + errorFlag = DcmPolymorphOBOW::writeSignatureFormat(outStream, oxfer, enctype, wcache); + } + else if (getValue() == NULL) + { + errorFlag = DcmPolymorphOBOW::writeSignatureFormat(outStream, oxfer, enctype, wcache); + } else errorFlag = EC_RepresentationNotFound; + } else errorFlag = EC_Normal; + return errorFlag; +} + +OFCondition DcmPixelData::loadAllDataIntoMemory(void) +{ + if (current == repListEnd) + return DcmElement::loadAllDataIntoMemory(); + else + return (*current)->pixSeq->loadAllDataIntoMemory(); +} + +void DcmPixelData::setNonEncapsulationFlag(OFBool flag) +{ + alwaysUnencapsulated = flag; +} + +OFCondition DcmPixelData::getUncompressedFrame( + DcmItem *dataset, + Uint32 frameNo, + Uint32& startFragment, + void *buffer, + Uint32 bufSize, + OFString& decompressedColorModel, + DcmFileCache *cache) +{ + if ((dataset == NULL) || (buffer == NULL)) return EC_IllegalCall; + + Sint32 numberOfFrames = 1; + dataset->findAndGetSint32(DCM_NumberOfFrames, numberOfFrames); // don't fail if absent + if (numberOfFrames < 1) numberOfFrames = 1; + + Uint32 frameSize; + OFCondition result = getUncompressedFrameSize(dataset, frameSize); + if (result.bad()) return result; + + // determine the minimum buffer size, which may be frame size plus one pad byte if frame size is odd. + // We need this extra byte, because the image might be in a different + // endianness than our host cpu. In this case the decoder will swap + // the data to the host byte order which could overflow the buffer. + Uint32 minBufSize = frameSize; + if (minBufSize & 1) ++minBufSize; + + if (bufSize < minBufSize) return EC_IllegalCall; + + // check frame number + if (frameNo >= OFstatic_cast(Uint32, numberOfFrames)) return EC_IllegalCall; + + if (existUnencapsulated) + { + // we already have an uncompressed version of the pixel data + // either in memory or in file. We can directly access this using + // DcmElement::getPartialValue. + result = getPartialValue(buffer, frameNo * frameSize, frameSize, cache); + if (result.good()) result = dataset->findAndGetOFString(DCM_PhotometricInterpretation, decompressedColorModel); + } + else + { + // we only have a compressed version of the pixel data. + // Identify a codec for decompressing the frame. + result = DcmCodecList::decodeFrame( + (*original)->repType, (*original)->repParam, (*original)->pixSeq, + dataset, frameNo, startFragment, buffer, bufSize, decompressedColorModel); + } + return result; +} + + +OFCondition DcmPixelData::getDecompressedColorModel( + DcmItem *dataset, + OFString &decompressedColorModel) +{ + OFCondition result = EC_IllegalCall; + if (dataset != NULL) + { + if (existUnencapsulated) + { + // we already have an uncompressed version of the pixel data either in memory or in file, + // so just retrieve the color model from the given dataset + result = dataset->findAndGetOFString(DCM_PhotometricInterpretation, decompressedColorModel); + } else { + // we only have a compressed version of the pixel data. + // Identify a codec for determining the color model. + result = DcmCodecList::determineDecompressedColorModel( + (*original)->repType, (*original)->repParam, (*original)->pixSeq, + dataset, decompressedColorModel); + } + } + return result; +} + +OFBool DcmPixelData::writeUnencapsulated(const E_TransferSyntax xfer) +{ + // There are three cases under which a dataset is written out + // unencapsulated: + // + // - It was already read unencapsulated (handled via alwaysUnencapsulated) + // - We were told to do so (handled via alwaysUnencapsulated) + // - This is not the pixel data element on the main level and it exists + // unencapsulated. + + if (alwaysUnencapsulated) + return OFTrue; + if (DcmXfer(xfer).isEncapsulated()) { + DcmRepresentationListIterator found; + OFCondition cond = findConformingEncapsulatedRepresentation(xfer, NULL, found); + if (cond.good()) { + // We found a suitable encapsulated representation, so encapsulate + // this element in the output. + return OFFalse; + } + } + + return existUnencapsulated && isNested(); +} diff --git a/dcmdata/libsrc/dcpixseq.cc b/dcmdata/libsrc/dcpixseq.cc new file mode 100644 index 00000000..374e8b16 --- /dev/null +++ b/dcmdata/libsrc/dcpixseq.cc @@ -0,0 +1,431 @@ +/* + * + * Copyright (C) 1994-2015, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Gerd Ehlers, Andreas Barth + * + * Purpose: Implementation of class DcmPixelSequence + * + */ + + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#define INCLUDE_CSTDLIB +#define INCLUDE_CSTDIO +#include "dcmtk/ofstd/ofstdinc.h" + +#include "dcmtk/ofstd/ofstream.h" +#include "dcmtk/ofstd/ofuuid.h" + +#include "dcmtk/dcmdata/dcpixseq.h" +#include "dcmtk/dcmdata/dcpxitem.h" +#include "dcmtk/dcmdata/dcitem.h" +#include "dcmtk/dcmdata/dcvr.h" + +#include "dcmtk/dcmdata/dcdeftag.h" + + +// ******************************** + + +DcmPixelSequence::DcmPixelSequence(const DcmTag &tag, + const Uint32 len) + : DcmSequenceOfItems(tag, len), + Xfer(EXS_Unknown) +{ + setTagVR(EVR_OB); + setLengthField(DCM_UndefinedLength); // pixel sequences always use undefined length +} + + +DcmPixelSequence::DcmPixelSequence(const DcmPixelSequence &old) + : DcmSequenceOfItems(old), + Xfer(old.Xfer) +{ + /* everything gets handled in DcmSequenceOfItems constructor */ +} + + +DcmPixelSequence::~DcmPixelSequence() +{ +} + + +DcmPixelSequence &DcmPixelSequence::operator=(const DcmPixelSequence &obj) +{ + if (this != &obj) + { + DcmSequenceOfItems::operator=(obj); + Xfer = obj.Xfer; + } + return *this; +} + + +OFCondition DcmPixelSequence::copyFrom(const DcmObject& rhs) +{ + if (this != &rhs) + { + if (rhs.ident() != ident()) return EC_IllegalCall; + *this = OFstatic_cast(const DcmPixelSequence &, rhs); + } + return EC_Normal; +} + +// ******************************** + + +void DcmPixelSequence::print(STD_NAMESPACE ostream &out, + const size_t flags, + const int level, + const char *pixelFileName, + size_t *pixelCounter) +{ + /* print pixel sequence start line */ + if (flags & DCMTypes::PF_showTreeStructure) + { + /* empty text */ + printInfoLine(out, flags, level); + /* print pixel sequence content */ + if (!itemList->empty()) + { + /* print pixel items */ + DcmObject *dO; + itemList->seek(ELP_first); + do { + dO = itemList->get(); + dO->print(out, flags, level + 1, pixelFileName, pixelCounter); + } while (itemList->seek(ELP_next)); + } + } else { + OFOStringStream oss; + oss << "(PixelSequence "; + if (getLengthField() != DCM_UndefinedLength) + oss << "with explicit length "; + oss << "#=" << card() << ")" << OFStringStream_ends; + OFSTRINGSTREAM_GETSTR(oss, tmpString) + printInfoLine(out, flags, level, tmpString); + OFSTRINGSTREAM_FREESTR(tmpString) + /* print pixel sequence content */ + if (!itemList->empty()) + { + DcmObject *dO; + itemList->seek(ELP_first); + do { + dO = itemList->get(); + dO->print(out, flags, level + 1, pixelFileName, pixelCounter); + } while (itemList->seek(ELP_next)); + } + /* print pixel sequence end line */ + DcmTag delimItemTag(DCM_SequenceDelimitationItemTag); + if (getLengthField() == DCM_UndefinedLength) + printInfoLine(out, flags, level, "(SequenceDelimitationItem)", &delimItemTag); + else + printInfoLine(out, flags, level, "(SequenceDelimitationItem for re-encod.)", &delimItemTag); + } +} + + +// ******************************** + + +OFCondition DcmPixelSequence::writeXML(STD_NAMESPACE ostream &out, + const size_t flags) +{ + OFCondition l_error = EC_Normal; + if (flags & DCMTypes::XF_useNativeModel) + { + /* write XML start tag */ + writeXMLStartTag(out, flags); + /* for an empty value field, we do not need to do anything */ + if (getLengthField() > 0) + { + /* encode binary data as Base64 */ + if (flags & DCMTypes::XF_encodeBase64) + { + out << ""; + Uint8 *byteValues = OFstatic_cast(Uint8 *, getValue()); + OFStandard::encodeBase64(out, byteValues, OFstatic_cast(size_t, getLengthField())); + out << "" << OFendl; + } else { + /* generate a new UID but the binary data is not (yet) written. */ + OFUUID uuid; + out << "" << OFendl; + } + } + /* write XML end tag */ + writeXMLEndTag(out, flags); + } else { + /* the DCMTK-specific XML format requires no special handling */ + l_error = DcmSequenceOfItems::writeXML(out, flags); + } + return l_error; +} + + +// ******************************** + + +Uint32 DcmPixelSequence::calcElementLength(const E_TransferSyntax xfer, + const E_EncodingType enctype) +{ + // add 8 bytes for Sequence Delimitation Tag which always exists for Pixel Sequences + return DcmElement::calcElementLength(xfer, enctype) + 8; +} + + +// ******************************** + + +OFCondition DcmPixelSequence::makeSubObject(DcmObject *&subObject, + const DcmTag &newTag, + const Uint32 newLength) +{ + OFCondition l_error = EC_Normal; + DcmObject *newObject = NULL; + + switch (newTag.getEVR()) + { + case EVR_na: + if (newTag.getXTag() == DCM_Item) + newObject = new DcmPixelItem(newTag, newLength); + else if (newTag.getXTag() == DCM_SequenceDelimitationItem) + l_error = EC_SequEnd; + else if (newTag.getXTag() == DCM_ItemDelimitationItem) + l_error = EC_ItemEnd; + else + l_error = EC_InvalidTag; + break; + + default: + newObject = new DcmPixelItem(newTag, newLength); + l_error = EC_CorruptedData; + break; + } + + subObject = newObject; + return l_error; +} + + +// ******************************** + + +OFCondition DcmPixelSequence::insert(DcmPixelItem *item, + unsigned long where) +{ + errorFlag = EC_Normal; + if (item != NULL) + { + itemList->seek_to(where); + itemList->insert(item); + if (where < itemList->card()) + DCMDATA_TRACE("DcmPixelSequence::insert() Item at position " << where << " inserted"); + if (where >= itemList->card()) + DCMDATA_TRACE("DcmPixelSequence::insert() Item at last position inserted"); + // check whether the new item already has a parent + if (item->getParent() != NULL) + { + DCMDATA_DEBUG("DcmPixelSequence::insert() PixelItem already has a parent: " + << item->getParent()->getTag() << " VR=" << DcmVR(item->getParent()->getVR()).getVRName()); + } + // remember the parent (i.e. the surrounding sequence) + item->setParent(this); + } else + errorFlag = EC_IllegalCall; + return errorFlag; +} + + +// ******************************** + + +OFCondition DcmPixelSequence::getItem(DcmPixelItem *&item, + const unsigned long num) +{ + errorFlag = EC_Normal; + item = OFstatic_cast(DcmPixelItem*, itemList->seek_to(num)); // read item from list + if (item == NULL) + errorFlag = EC_IllegalCall; + return errorFlag; +} + + +// ******************************** + + +OFCondition DcmPixelSequence::remove(DcmPixelItem *&item, + const unsigned long num) +{ + errorFlag = EC_Normal; + item = OFstatic_cast(DcmPixelItem*, itemList->seek_to(num)); // read item from list + if (item != NULL) + { + itemList->remove(); + item->setParent(NULL); // forget about the parent + } else + errorFlag = EC_IllegalCall; + return errorFlag; +} + + +// ******************************** + + +OFCondition DcmPixelSequence::remove(DcmPixelItem *item) +{ + errorFlag = EC_IllegalCall; + if (!itemList->empty() && item != NULL) + { + DcmObject *dO; + itemList->seek(ELP_first); + do { + dO = itemList->get(); + if (dO == item) + { + itemList->remove(); // remove element from list, but do no delete it + item->setParent(NULL); // forget about the parent + errorFlag = EC_Normal; + break; + } + } while (itemList->seek(ELP_next)); + } + return errorFlag; +} + + +// ******************************** + + +OFCondition DcmPixelSequence::changeXfer(const E_TransferSyntax newXfer) +{ + if (Xfer == EXS_Unknown || canWriteXfer(newXfer, Xfer)) + { + Xfer = newXfer; + return EC_Normal; + } else + return EC_IllegalCall; +} + + +// ******************************** + + +OFBool DcmPixelSequence::canWriteXfer(const E_TransferSyntax newXfer, + const E_TransferSyntax oldXfer) +{ + DcmXfer newXferSyn(newXfer); + + return newXferSyn.isEncapsulated() && newXfer == oldXfer && oldXfer == Xfer; +} + + +// ******************************** + + +OFCondition DcmPixelSequence::read(DcmInputStream &inStream, + const E_TransferSyntax ixfer, + const E_GrpLenEncoding glenc, + const Uint32 maxReadLength) +{ + OFCondition l_error = changeXfer(ixfer); + if (l_error.good()) + return DcmSequenceOfItems::read(inStream, ixfer, glenc, maxReadLength); + + return l_error; +} + + +// ******************************** + + +OFCondition DcmPixelSequence::write(DcmOutputStream &outStream, + const E_TransferSyntax oxfer, + const E_EncodingType /*enctype*/, + DcmWriteCache *wcache) +{ + OFCondition l_error = changeXfer(oxfer); + if (l_error.good()) + return DcmSequenceOfItems::write(outStream, oxfer, EET_UndefinedLength, wcache); + + return l_error; +} + + +// ******************************** + + +OFCondition DcmPixelSequence::writeSignatureFormat(DcmOutputStream &outStream, + const E_TransferSyntax oxfer, + const E_EncodingType /*enctype*/, + DcmWriteCache *wcache) +{ + OFCondition l_error = changeXfer(oxfer); + if (l_error.good()) + return DcmSequenceOfItems::writeSignatureFormat(outStream, oxfer, EET_UndefinedLength, wcache); + + return l_error; +} + + +OFCondition DcmPixelSequence::storeCompressedFrame(DcmOffsetList &offsetList, + Uint8 *compressedData, + Uint32 compressedLen, + Uint32 fragmentSize) +{ + if (compressedData == NULL) + return EC_IllegalCall; + + OFCondition result = EC_Normal; + if (fragmentSize >= 0x400000) + fragmentSize = 0; // prevent overflow + else + fragmentSize <<= 10; // unit is kbytes + if (fragmentSize == 0) + fragmentSize = compressedLen; + + Uint32 offset = 0; + Uint32 currentSize = 0; + Uint32 numFragments = 0; + DcmPixelItem *fragment = NULL; + + while ((offset < compressedLen) && (result.good())) + { + fragment = new DcmPixelItem(DCM_PixelItemTag); + if (fragment == NULL) + result = EC_MemoryExhausted; + else + { + insert(fragment); + numFragments++; + currentSize = fragmentSize; + if (offset + currentSize > compressedLen) + currentSize = compressedLen - offset; + // if currentSize is odd this will be fixed during DcmOtherByteOtherWord::write() + result = fragment->putUint8Array(compressedData + offset, currentSize); + if (result.good()) + offset += currentSize; + } + } + + currentSize = offset + (numFragments << 3); // 8 bytes extra for each item header + // odd frame size requires padding, i.e. last fragment uses odd length pixel item + if (currentSize & 1) + currentSize++; + offsetList.push_back(currentSize); + return result; +} diff --git a/dcmdata/libsrc/dcpxitem.cc b/dcmdata/libsrc/dcpxitem.cc new file mode 100644 index 00000000..f7714946 --- /dev/null +++ b/dcmdata/libsrc/dcpxitem.cc @@ -0,0 +1,419 @@ +/* + * + * Copyright (C) 1994-2012, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Gerd Ehlers, Andreas Barth + * + * Purpose: Implementation of class DcmPixelItem + * + */ + + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#define INCLUDE_CSTDLIB +#define INCLUDE_CSTDIO +#define INCLUDE_CSTRING +#include "dcmtk/ofstd/ofstdinc.h" + +#include "dcmtk/ofstd/ofstream.h" +#include "dcmtk/dcmdata/dcpxitem.h" +#include "dcmtk/dcmdata/dcswap.h" +#include "dcmtk/ofstd/ofstring.h" +#include "dcmtk/ofstd/ofstd.h" +#include "dcmtk/dcmdata/dcistrma.h" /* for class DcmInputStream */ +#include "dcmtk/dcmdata/dcostrma.h" /* for class DcmOutputStream */ +#include "dcmtk/dcmdata/dcwcache.h" /* for class DcmWriteCache */ + + +// ******************************** + + +DcmPixelItem::DcmPixelItem(const DcmTag &tag, + const Uint32 len) + : DcmOtherByteOtherWord(tag, len) +{ + setTagVR(EVR_pixelItem); +} + + +DcmPixelItem::DcmPixelItem(const DcmPixelItem &old) + : DcmOtherByteOtherWord(old) +{ +} + + +OFCondition DcmPixelItem::copyFrom(const DcmObject &rhs) +{ + if (this != &rhs) + { + if (rhs.ident() != ident()) return EC_IllegalCall; + *this = OFstatic_cast(const DcmPixelItem &, rhs); + } + return EC_Normal; +} + + +DcmPixelItem::~DcmPixelItem() +{ +} + + +// ******************************** + + +OFBool DcmPixelItem::isNested() const +{ + OFBool nested = OFFalse; + if (getParent() != NULL) + { + // check for surrounding structure of a pixel sequence + if ((getParent()->ident() == EVR_pixelSQ)) + nested = OFTrue; + } + return nested; +} + + +DcmItem *DcmPixelItem::getParentItem() +{ + DcmItem *parentItem = NULL; + if (getParent() != NULL) + { + // make sure that the direct parent has the correct type + if (getParent()->ident() == EVR_pixelSQ) + { + DcmObject *parent = getParent()->getParent(); + if (parent != NULL) + { + // make sure that it is really a class derived from DcmItem + switch (parent->ident()) + { + case EVR_metainfo: + case EVR_dataset: + case EVR_item: + case EVR_dirRecord: + parentItem = OFreinterpret_cast(DcmItem *, parent); + break; + default: + DCMDATA_DEBUG("DcmPixelItem::getParentItem() Parent object has wrong class identifier: " + << OFstatic_cast(int, parent->ident()) + << " (" << DcmVR(parent->ident()).getVRName() << ")"); + break; + } + } + } else { + DCMDATA_DEBUG("DcmPixelItem::getParentItem() Direct parent object is not a pixel sequence"); + } + } + return parentItem; +} + + +// ******************************** + + +OFCondition DcmPixelItem::writeTagAndLength(DcmOutputStream &outStream, + const E_TransferSyntax oxfer, + Uint32 &writtenBytes) const +{ + OFCondition l_error = outStream.status(); + if (l_error.good()) + { + /* write tag information */ + l_error = writeTag(outStream, getTag(), oxfer); + writtenBytes = 4; + /* prepare to write the value field */ + Uint32 valueLength = getLengthField(); + DcmXfer outXfer(oxfer); + /* check byte-ordering */ + const E_ByteOrder oByteOrder = outXfer.getByteOrder(); + if (oByteOrder == EBO_unknown) + { + return EC_IllegalCall; + } + swapIfNecessary(oByteOrder, gLocalByteOrder, &valueLength, 4, 4); + // availability of four bytes space in output buffer + // has been checked by caller. + writtenBytes += OFstatic_cast(Uint32, outStream.write(&valueLength, 4)); + } else + writtenBytes = 0; + return l_error; +} + + +void DcmPixelItem::print(STD_NAMESPACE ostream &out, + const size_t flags, + const int level, + const char *pixelFileName, + size_t *pixelCounter) +{ + /* call inherited method */ + printPixel(out, flags, level, pixelFileName, pixelCounter); +} + + +OFCondition DcmPixelItem::createOffsetTable(const DcmOffsetList &offsetList) +{ + OFCondition result = EC_Normal; + + size_t numEntries = offsetList.size(); + if (numEntries > 0) + { + Uint32 current = 0; + Uint32 *array = new Uint32[numEntries]; + if (array) + { + DCMDATA_DEBUG("DcmPixelItem: creating offset table with " << numEntries << " entries"); + OFListConstIterator(Uint32) first = offsetList.begin(); + OFListConstIterator(Uint32) last = offsetList.end(); + unsigned long idx = 0; + while ((first != last) && result.good()) + { + // check for odd offset values, should never happen at this point + if (current & 1) + { + DCMDATA_WARN("DcmPixelItem: odd frame size (" << current << ") found for frame #" + << (idx + 1) << ", cannot create offset table"); + result = EC_InvalidBasicOffsetTable; + } else { + array[idx++] = current; + current += *first; + ++first; + } + } + if (result.good()) + { + result = swapIfNecessary(EBO_LittleEndian, gLocalByteOrder, array, OFstatic_cast(Uint32, numEntries * sizeof(Uint32)), sizeof(Uint32)); + if (result.good()) + result = putUint8Array(OFreinterpret_cast(Uint8 *, array), OFstatic_cast(unsigned long, numEntries * sizeof(Uint32))); + } + delete[] array; + } else + result = EC_MemoryExhausted; + } + return result; +} + + +OFCondition DcmPixelItem::writeXML(STD_NAMESPACE ostream&out, + const size_t flags) +{ + /* XML start tag for "item" */ + out << ""; + /* write element value (if loaded) */ + if (valueLoaded() && (flags & DCMTypes::XF_writeBinaryData)) + { + /* encode binary data as Base64 */ + if (flags & DCMTypes::XF_encodeBase64) + { + /* pixel items always contain 8 bit data, therefore, byte swapping not required */ + OFStandard::encodeBase64(out, OFstatic_cast(Uint8 *, getValue()), OFstatic_cast(size_t, getLengthField())); + } else { + /* get and check 8 bit data */ + Uint8 *byteValues = NULL; + if (getUint8Array(byteValues).good() && (byteValues != NULL)) + { + const unsigned long count = getLengthField(); + out << STD_NAMESPACE hex << STD_NAMESPACE setfill('0'); + /* print byte values in hex mode */ + out << STD_NAMESPACE setw(2) << OFstatic_cast(int, *(byteValues++)); + for (unsigned long i = 1; i < count; i++) + out << "\\" << STD_NAMESPACE setw(2) << OFstatic_cast(int, *(byteValues++)); + /* reset i/o manipulators */ + out << STD_NAMESPACE dec << STD_NAMESPACE setfill(' '); + } + } + } + /* XML end tag for "item" */ + out << "" << OFendl; + /* always report success */ + return EC_Normal; +} + + +OFCondition DcmPixelItem::writeSignatureFormat( + DcmOutputStream &outStream, + const E_TransferSyntax oxfer, + const E_EncodingType enctype, + DcmWriteCache *wcache) +{ + if (dcmEnableOldSignatureFormat.get()) + { + /* Old signature format as created by DCMTK releases previous to 3.5.4. + * This is non-conformant because it includes the item length in pixel items. + */ + return DcmOtherByteOtherWord::writeSignatureFormat(outStream, oxfer, enctype, wcache); + } + else + { + DcmWriteCache wcache2; + + /* In case the transfer state is not initialized, this is an illegal call */ + if (getTransferState() == ERW_notInitialized) + errorFlag = EC_IllegalCall; + else + { + /* if this is not an illegal call, we need to do something. First */ + /* of all, check the error state of the stream that was passed */ + /* only do something if the error state of the stream is ok */ + errorFlag = outStream.status(); + if (errorFlag.good()) + { + /* create an object that represents the transfer syntax */ + DcmXfer outXfer(oxfer); + + /* pointer to element value if value resides in memory or old-style + * write behaviour is active (i.e. everything loaded into memory upon write + */ + Uint8 *value = NULL; + OFBool accessPossible = OFFalse; + + /* check that we actually do have access to the element's value. + * If the element is unaccessible (which would mean that the value resides + * in file and access to the file fails), write an empty element with + * zero length. + */ + if (getLengthField() > 0) + { + if (valueLoaded()) + { + /* get this element's value. Mind the byte ordering (little */ + /* or big endian) of the transfer syntax which shall be used */ + value = OFstatic_cast(Uint8 *, getValue(outXfer.getByteOrder())); + if (value) accessPossible = OFTrue; + } + else + { + /* Use local cache object if needed. This may cause those bytes + * that are read but not written because the output stream stalls to + * be read again, and the file from being re-opened next time. + * Therefore, this case should be avoided. + */ + if (!wcache) wcache = &wcache2; + + /* initialize cache object. This is safe even if the object was already initialized */ + wcache->init(this, getLengthField(), getTransferredBytes(), outXfer.getByteOrder()); + + /* access first block of element content */ + errorFlag = wcache->fillBuffer(*this); + + /* check that everything worked and the buffer is non-empty now */ + accessPossible = errorFlag.good() && (! wcache->bufferIsEmpty()); + } + } + + /* if this element's transfer state is ERW_init (i.e. it has not yet been written to */ + /* the stream) and if the outstream provides enough space for tag and length information */ + /* write tag and length information to it, do something */ + if (getTransferState() == ERW_init) + { + /* first compare with DCM_TagInfoLength (12). If there is not enough space + * in the buffer, check if the buffer is still sufficient for the requirements + * of this element, which may need only 8 instead of 12 bytes. + */ + if (outStream.avail() >= 4) + { + /* if there is no value, Length (member variable) shall be set to 0 */ + if (! accessPossible) setLengthField(0); + + /* write tag and length information (and possibly also data type information) to the stream, */ + /* mind the transfer syntax and remember the amount of bytes that have been written */ + errorFlag = writeTag(outStream, getTag(), oxfer); + + /* if the writing was successful, set this element's transfer */ + /* state to ERW_inWork and the amount of transferred bytes to 0 */ + if (errorFlag.good()) + { + setTransferState(ERW_inWork); + setTransferredBytes(0); + } + } else + errorFlag = EC_StreamNotifyClient; + } + /* if there is a value that has to be written to the stream */ + /* and if this element's transfer state is ERW_inWork */ + if (accessPossible && getTransferState() == ERW_inWork) + { + + Uint32 len = 0; + if (valueLoaded()) + { + /* write as many bytes as possible to the stream starting at value[getTransferredBytes()] */ + /* (note that the bytes value[0] to value[getTransferredBytes()-1] have already been */ + /* written to the stream) */ + len = OFstatic_cast(Uint32, outStream.write(&value[getTransferredBytes()], getLengthField() - getTransferredBytes())); + + /* increase the amount of bytes which have been transfered correspondingly */ + incTransferredBytes(len); + + /* see if there is something fishy with the stream */ + errorFlag = outStream.status(); + } + else + { + Uint32 buflen = 0; + OFBool done = getTransferredBytes() == getLengthField(); + while (! done) + { + // re-fill buffer from file if empty + errorFlag = wcache->fillBuffer(*this); + buflen = wcache->contentLength(); + + if (errorFlag.good()) + { + // write as many bytes from cache buffer to stream as possible + len = wcache->writeBuffer(outStream); + + /* increase the amount of bytes which have been transfered correspondingly */ + incTransferredBytes(len); + + /* see if there is something fishy with the stream */ + errorFlag = outStream.status(); + } + + // stop writing if something went wrong, we were unable to send all of the buffer content + // (which indicates that the output stream needs to be flushed, or everything was sent out. + done = errorFlag.bad() || (len < buflen) || (getTransferredBytes() == getLengthField()); + } + } + + /* if the amount of transferred bytes equals the length of the element's value, the */ + /* entire value has been written to the stream. Thus, this element's transfer state */ + /* has to be set to ERW_ready. If this is not the case but the error flag still shows */ + /* an ok value, there was no more space in the stream and a corresponding return value */ + /* has to be set. (Isn't the "else if" part superfluous?!?) */ + if (getLengthField() == getTransferredBytes()) setTransferState(ERW_ready); + else if (errorFlag.good()) errorFlag = EC_StreamNotifyClient; + } + } + } + } + + /* return result value */ + return errorFlag; +} diff --git a/dcmdata/libsrc/dcrleccd.cc b/dcmdata/libsrc/dcrleccd.cc new file mode 100644 index 00000000..1b194f7c --- /dev/null +++ b/dcmdata/libsrc/dcrleccd.cc @@ -0,0 +1,692 @@ +/* + * + * Copyright (C) 2002-2010, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Marco Eichelberg + * + * Purpose: decoder codec class for RLE + * + */ + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmdata/dcrleccd.h" + +// dcmdata includes +#include "dcmtk/dcmdata/dcrlecp.h" /* for class DcmRLECodecParameter */ +#include "dcmtk/dcmdata/dcrledec.h" /* for class DcmRLEDecoder */ +#include "dcmtk/dcmdata/dcdatset.h" /* for class DcmDataset */ +#include "dcmtk/dcmdata/dcdeftag.h" /* for tag constants */ +#include "dcmtk/dcmdata/dcpixseq.h" /* for class DcmPixelSequence */ +#include "dcmtk/dcmdata/dcpxitem.h" /* for class DcmPixelItem */ +#include "dcmtk/dcmdata/dcvrpobw.h" /* for class DcmPolymorphOBOW */ +#include "dcmtk/dcmdata/dcswap.h" /* for swapIfNecessary() */ +#include "dcmtk/dcmdata/dcuid.h" /* for dcmGenerateUniqueIdentifer()*/ + + +DcmRLECodecDecoder::DcmRLECodecDecoder() +: DcmCodec() +{ +} + + +DcmRLECodecDecoder::~DcmRLECodecDecoder() +{ +} + + +OFBool DcmRLECodecDecoder::canChangeCoding( + const E_TransferSyntax oldRepType, + const E_TransferSyntax newRepType) const +{ + E_TransferSyntax myXfer = EXS_RLELossless; + DcmXfer newRep(newRepType); + if (newRep.isNotEncapsulated() && (oldRepType == myXfer)) return OFTrue; // decompress requested + + // we don't support re-coding for now. + return OFFalse; +} + + +OFCondition DcmRLECodecDecoder::decode( + const DcmRepresentationParameter * /* fromRepParam */, + DcmPixelSequence * pixSeq, + DcmPolymorphOBOW& uncompressedPixelData, + const DcmCodecParameter * cp, + const DcmStack& objStack) const +{ + OFCondition result = EC_Normal; + + // assume we can cast the codec parameter to what we need + const DcmRLECodecParameter *djcp = OFstatic_cast(const DcmRLECodecParameter *, cp); + + OFBool enableReverseByteOrder = djcp->getReverseDecompressionByteOrder(); + + DcmStack localStack(objStack); + (void)localStack.pop(); // pop pixel data element from stack + DcmObject *dataset = localStack.pop(); // this is the item in which the pixel data is located + if ((!dataset)||((dataset->ident()!= EVR_dataset) && (dataset->ident()!= EVR_item))) result = EC_InvalidTag; + else + { + Uint16 imageSamplesPerPixel = 0; + Uint16 imageRows = 0; + Uint16 imageColumns = 0; + Sint32 imageFrames = 1; + Uint16 imageBitsAllocated = 0; + Uint16 imageBytesAllocated = 0; + Uint16 imagePlanarConfiguration = 0; + Uint32 rleHeader[16]; + DcmItem *ditem = OFstatic_cast(DcmItem *, dataset); + OFBool numberOfFramesPresent = OFFalse; + + if (result.good()) result = ditem->findAndGetUint16(DCM_SamplesPerPixel, imageSamplesPerPixel); + if (result.good()) result = ditem->findAndGetUint16(DCM_Rows, imageRows); + if (result.good()) result = ditem->findAndGetUint16(DCM_Columns, imageColumns); + if (result.good()) result = ditem->findAndGetUint16(DCM_BitsAllocated, imageBitsAllocated); + if (result.good()) + { + imageBytesAllocated = OFstatic_cast(Uint16, imageBitsAllocated / 8); + if ((imageBitsAllocated < 8)||(imageBitsAllocated % 8 != 0)) result = EC_CannotChangeRepresentation; + } + if (result.good() && (imageSamplesPerPixel > 1)) + { + result = ditem->findAndGetUint16(DCM_PlanarConfiguration, imagePlanarConfiguration); + } + + // number of frames is an optional attribute - we don't mind if it isn't present. + if (result.good()) + { + if (ditem->findAndGetSint32(DCM_NumberOfFrames, imageFrames).good()) numberOfFramesPresent = OFTrue; + } + + if (imageFrames >= OFstatic_cast(Sint32, pixSeq->card())) + imageFrames = OFstatic_cast(Sint32, pixSeq->card()) - 1; // limit number of frames to number of pixel items - 1 + if (imageFrames < 1) + imageFrames = 1; // default in case the number of frames attribute is absent or contains garbage + + if (result.good()) + { + DcmPixelItem *pixItem = NULL; + Uint8 * rleData = NULL; + const size_t bytesPerStripe = imageColumns * imageRows; + + DcmRLEDecoder rledecoder(bytesPerStripe); + if (rledecoder.fail()) result = EC_MemoryExhausted; // RLE decoder failed to initialize + else + { + size_t frameSize = imageBytesAllocated * imageRows * imageColumns * imageSamplesPerPixel; + size_t totalSize = frameSize * imageFrames; + if (totalSize & 1) totalSize++; // align on 16-bit word boundary + Uint16 *imageData16 = NULL; + Sint32 currentFrame = 0; + Uint32 currentItem = 1; // ignore offset table + Uint32 numberOfStripes = 0; + Uint32 fragmentLength = 0; + Uint32 i; + + result = uncompressedPixelData.createUint16Array(OFstatic_cast(Uint32, totalSize/sizeof(Uint16)), imageData16); + if (result.good()) + { + Uint8 *imageData8 = OFreinterpret_cast(Uint8 *, imageData16); + + while ((currentFrame < imageFrames) && result.good()) + { + DCMDATA_DEBUG("RLE decoder processes frame " << currentFrame); + DCMDATA_DEBUG("RLE decoder processes pixel item " << currentItem); + // get first pixel item of this frame + result = pixSeq->getItem(pixItem, currentItem++); + if (result.good()) + { + fragmentLength = pixItem->getLength(); + result = pixItem->getUint8Array(rleData); + if (result.good()) + { + // we require that the RLE header must be completely + // contained in the first fragment; otherwise bail out + if (fragmentLength < 64) result = EC_CannotChangeRepresentation; + } + } + + if (result.good()) + { + // copy RLE header to buffer and adjust byte order + memcpy(rleHeader, rleData, 64); + swapIfNecessary(gLocalByteOrder, EBO_LittleEndian, rleHeader, 16*OFstatic_cast(Uint32, sizeof(Uint32)), sizeof(Uint32)); + + // determine number of stripes. + numberOfStripes = rleHeader[0]; + + // check that number of stripes in RLE header matches our expectation + if ((numberOfStripes < 1) || (numberOfStripes > 15) || + (numberOfStripes != OFstatic_cast(Uint32, imageBytesAllocated) * imageSamplesPerPixel)) + result = EC_CannotChangeRepresentation; + } + + if (result.good()) + { + // this variable keeps the number of bytes we have processed + // for the current frame in earlier pixel fragments + Uint32 fragmentOffset = 0; + + // this variable keeps the current position within the current fragment + Uint32 byteOffset = 0; + + OFBool lastStripe = OFFalse; + Uint32 inputBytes = 0; + + // pointers for buffer copy operations + Uint8 *outputBuffer = NULL; + Uint8 *pixelPointer = NULL; + + // byte offset for first sample in frame + Uint32 sampleOffset = 0; + + // byte offset between samples + Uint32 offsetBetweenSamples = 0; + + // temporary variables + Uint32 sample = 0; + Uint32 byte = 0; + register Uint32 pixel = 0; + + // for each stripe in stripe set + for (i=0; (i fragmentLength) && result.good()) + { + DCMDATA_DEBUG("RLE decoder processes pixel item " << currentItem); + result = pixSeq->getItem(pixItem, currentItem++); + if (result.good()) + { + byteOffset -= fragmentLength; + fragmentOffset += fragmentLength; + fragmentLength = pixItem->getLength(); + result = pixItem->getUint8Array(rleData); + } + } + } + + // byteOffset now points to the first byte of the new RLE stripe + // check if the current stripe is the last one for this frame + if (i+1 == numberOfStripes) lastStripe = OFTrue; else lastStripe = OFFalse; + + if (lastStripe) + { + // the last stripe needs special handling because we cannot use the + // offset table to determine the number of bytes to feed to the codec + // if the RLE data is split in multiple fragments. We need to feed + // data fragment by fragment until the RLE codec has produced + // sufficient output. + while ((rledecoder.size() < bytesPerStripe) && result.good()) + { + // feed complete remaining content of fragment to RLE codec and + // switch to next fragment + result = rledecoder.decompress(rleData + byteOffset, OFstatic_cast(size_t, fragmentLength - byteOffset)); + + // special handling for zero pad byte at the end of the RLE stream + // which results in an EC_StreamNotifyClient return code + // or trailing garbage data which results in EC_CorruptedData + if (rledecoder.size() == bytesPerStripe) result = EC_Normal; + + // Check if we're already done. If yes, don't change fragment + if (result.good() || result == EC_StreamNotifyClient) + { + if (rledecoder.size() < bytesPerStripe) + { + DCMDATA_WARN("RLE decoder is finished but has produced insufficient data for this stripe, will continue with next pixel item"); + DCMDATA_DEBUG("RLE decoder processes pixel item " << currentItem); + result = pixSeq->getItem(pixItem, currentItem++); + if (result.good()) + { + byteOffset = 0; + fragmentOffset += fragmentLength; + fragmentLength = pixItem->getLength(); + result = pixItem->getUint8Array(rleData); + } + } + else byteOffset = fragmentLength; + } + } /* while */ + } + else + { + // not the last stripe. We can use the offset table to determine + // the number of bytes to feed to the RLE codec. + inputBytes = rleHeader[i+2]; + if (inputBytes < rleHeader[i+1]) result = EC_CannotChangeRepresentation; + else + { + inputBytes -= rleHeader[i+1]; // number of bytes to feed to codec + while ((inputBytes > (fragmentLength - byteOffset)) && result.good()) + { + // feed complete remaining content of fragment to RLE codec and + // switch to next fragment + result = rledecoder.decompress(rleData + byteOffset, OFstatic_cast(size_t, fragmentLength - byteOffset)); + + if (result.good() || result == EC_StreamNotifyClient) + { + DCMDATA_DEBUG("RLE decoder processes pixel item " << currentItem); + result = pixSeq->getItem(pixItem, currentItem++); + } + if (result.good()) + { + inputBytes -= fragmentLength - byteOffset; + byteOffset = 0; + fragmentOffset += fragmentLength; + fragmentLength = pixItem->getLength(); + result = pixItem->getUint8Array(rleData); + } + } /* while */ + + // last fragment for this RLE stripe + result = rledecoder.decompress(rleData + byteOffset, OFstatic_cast(size_t, inputBytes)); + + // special handling for zero pad byte at the end of the RLE stream + // which results in an EC_StreamNotifyClient return code + // or trailing garbage data which results in EC_CorruptedData + if (rledecoder.size() == bytesPerStripe) result = EC_Normal; + + byteOffset += inputBytes; + } + } + + // make sure the RLE decoder has produced the right amount of data + if (result.good() && (rledecoder.size() != bytesPerStripe)) + { + DCMDATA_ERROR("RLE decoder is finished but has produced insufficient data for this stripe"); + result = EC_CannotChangeRepresentation; + } + + // distribute decompressed bytes into output image array + if (result.good()) + { + // which sample and byte are we currently compressing? + sample = i / imageBytesAllocated; + byte = i % imageBytesAllocated; + + // raw buffer containing bytesPerStripe bytes of uncompressed data + outputBuffer = OFstatic_cast(Uint8 *, rledecoder.getOutputBuffer()); + + // compute byte offsets + if (imagePlanarConfiguration == 0) + { + sampleOffset = sample * imageBytesAllocated; + offsetBetweenSamples = imageSamplesPerPixel * imageBytesAllocated; + } + else + { + sampleOffset = sample * imageBytesAllocated * imageColumns * imageRows; + offsetBetweenSamples = imageBytesAllocated; + } + + // initialize pointer to output data + if (enableReverseByteOrder) + { + // assume incorrect LSB to MSB order of RLE segments as produced by some tools + pixelPointer = imageData8 + sampleOffset + byte; + } + else + { + pixelPointer = imageData8 + sampleOffset + imageBytesAllocated - byte - 1; + } + + // loop through all pixels of the frame + for (pixel = 0; pixel < bytesPerStripe; ++pixel) + { + *pixelPointer = *outputBuffer++; + pixelPointer += offsetBetweenSamples; + } + } + } /* for */ + } + + // advance by one frame + if (result.good()) + { + currentFrame++; + imageData8 += frameSize; + } + + } /* while still frames to process */ + + // adjust byte order for uncompressed image to little endian + swapIfNecessary(EBO_LittleEndian, gLocalByteOrder, imageData16, OFstatic_cast(Uint32, totalSize), sizeof(Uint16)); + + // Number of Frames might have changed in case the previous value was wrong + if (result.good() && (numberOfFramesPresent || (imageFrames > 1))) + { + char numBuf[20]; + sprintf(numBuf, "%ld", OFstatic_cast(long, imageFrames)); + result = OFstatic_cast(DcmItem *, dataset)->putAndInsertString(DCM_NumberOfFrames, numBuf); + } + } + } + } + + // the following operations do not affect the Image Pixel Module + // but other modules such as SOP Common. We only perform these + // changes if we're on the main level of the dataset, + // which should always identify itself as dataset, not as item. + if (dataset->ident() == EVR_dataset) + { + // create new SOP instance UID if codec parameters require so + if (result.good() && djcp->getUIDCreation()) result = + DcmCodec::newInstance(OFstatic_cast(DcmItem *, dataset), NULL, NULL, NULL); + } + } + return result; +} + + +OFCondition DcmRLECodecDecoder::decodeFrame( + const DcmRepresentationParameter * /* fromParam */, + DcmPixelSequence * fromPixSeq, + const DcmCodecParameter * cp, + DcmItem *dataset, + Uint32 frameNo, + Uint32& startFragment, + void *buffer, + Uint32 bufSize, + OFString& decompressedColorModel) const +{ + OFCondition result = EC_Normal; + + // assume we can cast the codec parameter to what we need + const DcmRLECodecParameter *djcp = OFstatic_cast(const DcmRLECodecParameter *, cp); + + OFBool enableReverseByteOrder = djcp->getReverseDecompressionByteOrder(); + + if ((!dataset)||((dataset->ident()!= EVR_dataset) && (dataset->ident()!= EVR_item))) return EC_InvalidTag; + + Uint16 imageSamplesPerPixel = 0; + Uint16 imageRows = 0; + Uint16 imageColumns = 0; + Sint32 imageFrames = 1; + Uint16 imageBitsAllocated = 0; + Uint16 imageBytesAllocated = 0; + Uint16 imagePlanarConfiguration = 0; + Uint32 rleHeader[16]; + OFString photometricInterpretation; + DcmItem *ditem = OFstatic_cast(DcmItem *, dataset); + + if (result.good()) result = ditem->findAndGetUint16(DCM_SamplesPerPixel, imageSamplesPerPixel); + if (result.good()) result = ditem->findAndGetUint16(DCM_Rows, imageRows); + if (result.good()) result = ditem->findAndGetUint16(DCM_Columns, imageColumns); + if (result.good()) result = ditem->findAndGetUint16(DCM_BitsAllocated, imageBitsAllocated); + if (result.good()) result = dataset->findAndGetOFString(DCM_PhotometricInterpretation, photometricInterpretation); + if (result.good()) + { + imageBytesAllocated = OFstatic_cast(Uint16, imageBitsAllocated / 8); + if ((imageBitsAllocated < 8)||(imageBitsAllocated % 8 != 0)) return EC_CannotChangeRepresentation; + } + if (result.good() && (imageSamplesPerPixel > 1)) + { + result = ditem->findAndGetUint16(DCM_PlanarConfiguration, imagePlanarConfiguration); + } + + // number of frames is an optional attribute - we don't mind if it isn't present. + if (result.good()) (void) ditem->findAndGetSint32(DCM_NumberOfFrames, imageFrames); + if (imageFrames < 1) imageFrames = 1; // default in case this attribute contains garbage + + if (result.bad()) + return result; + + DcmPixelItem *pixItem = NULL; + Uint8 * rleData = NULL; + const size_t bytesPerStripe = imageColumns * imageRows; + Uint32 numberOfStripes = 0; + Uint32 fragmentLength = 0; + Uint32 i; + Uint32 frameSize = imageBytesAllocated * imageRows * imageColumns * imageSamplesPerPixel; + + if (frameSize > bufSize) return EC_IllegalCall; + + DcmRLEDecoder rledecoder(bytesPerStripe); + if (rledecoder.fail()) return EC_MemoryExhausted; // RLE decoder failed to initialize + + DCMDATA_DEBUG("RLE decoder processes frame " << frameNo); + + // determine the corresponding item (first fragment) for this frame + Uint32 currentItem = startFragment; + + // if the user has provided this information, we trust him. + // If the user has passed a zero, try to find out ourselves. + if (currentItem == 0 && result.good()) + { + result = determineStartFragment(frameNo, imageFrames, fromPixSeq, currentItem); + if (result.bad()) + return result; + } + + DCMDATA_DEBUG("RLE decoder processes pixel item " << currentItem); + // now access and decompress the frame starting at the item we have identified + result = fromPixSeq->getItem(pixItem, currentItem); + if (result.bad()) + return result; + + fragmentLength = pixItem->getLength(); + result = pixItem->getUint8Array(rleData); + if (result.bad()) + return result; + + // copy RLE header to buffer and adjust byte order + memcpy(rleHeader, rleData, 64); + swapIfNecessary(gLocalByteOrder, EBO_LittleEndian, rleHeader, OFstatic_cast(Uint32, 16*sizeof(Uint32)), sizeof(Uint32)); + + // determine number of stripes. + numberOfStripes = rleHeader[0]; + + // check that number of stripes in RLE header matches our expectation + if ((numberOfStripes < 1) || (numberOfStripes > 15) || (numberOfStripes != OFstatic_cast(Uint32, imageBytesAllocated) * imageSamplesPerPixel)) + return EC_CannotChangeRepresentation; + + // this variable keeps the current position within the current fragment + Uint32 byteOffset = 0; + + OFBool lastStripe = OFFalse; + Uint32 inputBytes = 0; + + // pointers for buffer copy operations + Uint8 *outputBuffer = NULL; + Uint8 *pixelPointer = NULL; + Uint16 *imageData16 = OFreinterpret_cast(Uint16 *, buffer); + Uint8 *imageData8 = OFreinterpret_cast(Uint8 *, buffer); + + // byte offset for first sample in frame + Uint32 sampleOffset = 0; + + // byte offset between samples + Uint32 offsetBetweenSamples = 0; + + // temporary variables + Uint32 sample = 0; + Uint32 byte = 0; + register Uint32 pixel = 0; + size_t bytesToDecode; + + // for each stripe in stripe set + for (i = 0; i < numberOfStripes; ++i) + { + // reset RLE codec + rledecoder.clear(); + + // adjust start point for RLE stripe + byteOffset = rleHeader[i+1]; + + // byteOffset now points to the first byte of the new RLE stripe + // check if the current stripe is the last one for this frame + if (i+1 == numberOfStripes) lastStripe = OFTrue; else lastStripe = OFFalse; + + if (lastStripe) + { + // the last stripe needs special handling because we cannot use the + // offset table to determine the number of bytes to feed to the codec + // if the RLE data is split in multiple fragments. We need to feed + // data fragment by fragment until the RLE codec has produced + // sufficient output. + bytesToDecode = OFstatic_cast(size_t, fragmentLength - byteOffset); + } + else + { + // not the last stripe. We can use the offset table to determine + // the number of bytes to feed to the RLE codec. + inputBytes = rleHeader[i+2]; + if (inputBytes < rleHeader[i+1]) return EC_CannotChangeRepresentation; + + inputBytes -= rleHeader[i+1]; // number of bytes to feed to codec + + bytesToDecode = OFstatic_cast(size_t, inputBytes); + } + + // last fragment for this RLE stripe + result = rledecoder.decompress(rleData + byteOffset, bytesToDecode); + + // special handling for zero pad byte at the end of the RLE stream + // which results in an EC_StreamNotifyClient return code + // or trailing garbage data which results in EC_CorruptedData + if (rledecoder.size() == bytesPerStripe) result = EC_Normal; + + byteOffset += inputBytes; + + // copy the decoded stuff over to the buffer here... + // make sure the RLE decoder has produced the right amount of data + if (lastStripe && (rledecoder.size() < bytesPerStripe)) + { + // stream ended premature? report a warning and continue + if (result == EC_StreamNotifyClient) + { + DCMDATA_WARN("RLE decoder is finished but has produced insufficient data for this stripe, filling remaining pixels"); + result = EC_Normal; + } + } + else if (rledecoder.size() != bytesPerStripe) + { + DCMDATA_ERROR("RLE decoder is finished but has produced insufficient data for this stripe"); + return EC_CannotChangeRepresentation; + } + + // distribute decompressed bytes into output image array + // which sample and byte are we currently decompressing? + sample = i / imageBytesAllocated; + byte = i % imageBytesAllocated; + + // raw buffer containing bytesPerStripe bytes of uncompressed data + outputBuffer = OFstatic_cast(Uint8 *, rledecoder.getOutputBuffer()); + + // compute byte offsets + if (imagePlanarConfiguration == 0) + { + sampleOffset = sample * imageBytesAllocated; + offsetBetweenSamples = imageSamplesPerPixel * imageBytesAllocated; + } + else + { + sampleOffset = sample * imageBytesAllocated * imageColumns * imageRows; + offsetBetweenSamples = imageBytesAllocated; + } + + // initialize pointer to output data + if (enableReverseByteOrder) + { + // assume incorrect LSB to MSB order of RLE segments as produced by some tools + pixelPointer = imageData8 + sampleOffset + byte; + } + else + { + pixelPointer = imageData8 + sampleOffset + imageBytesAllocated - byte - 1; + } + + // copy the pixel data that was decoded + const size_t decoderSize = rledecoder.size(); + for (pixel = 0; pixel < decoderSize; ++pixel) + { + *pixelPointer = *outputBuffer++; + pixelPointer += offsetBetweenSamples; + } + // and fill the remainder of the image with copies of the last decoded pixel + const Uint8 lastPixelValue = *(outputBuffer - 1); + for (pixel = OFstatic_cast(Uint32, decoderSize); pixel < bytesPerStripe; ++pixel) + { + *pixelPointer = lastPixelValue; + pixelPointer += offsetBetweenSamples; + } + } + + /* remove used fragment from memory */ + pixItem->compact(); // there should only be one... + + if (result.good()) + { + // compression was successful. Now update output parameters + startFragment = currentItem + 1; + decompressedColorModel = photometricInterpretation; + } + + // adjust byte order for uncompressed image to little endian + swapIfNecessary(EBO_LittleEndian, gLocalByteOrder, imageData16, frameSize, sizeof(Uint16)); + + return result; +} + + +OFCondition DcmRLECodecDecoder::encode( + const Uint16 * /* pixelData */, + const Uint32 /* length */, + const DcmRepresentationParameter * /* toRepParam */, + DcmPixelSequence * & /* pixSeq */, + const DcmCodecParameter * /* cp */, + DcmStack & /* objStack */) const +{ + // we are a decoder only + return EC_IllegalCall; +} + + +OFCondition DcmRLECodecDecoder::encode( + const E_TransferSyntax /* fromRepType */, + const DcmRepresentationParameter * /* fromRepParam */, + DcmPixelSequence * /* fromPixSeq */, + const DcmRepresentationParameter * /* toRepParam */, + DcmPixelSequence * & /* toPixSeq */, + const DcmCodecParameter * /* cp */, + DcmStack & /* objStack */) const +{ + // we don't support re-coding for now. + return EC_IllegalCall; +} + + +OFCondition DcmRLECodecDecoder::determineDecompressedColorModel( + const DcmRepresentationParameter * /* fromParam */, + DcmPixelSequence * /* fromPixSeq */, + const DcmCodecParameter * /* cp */, + DcmItem *dataset, + OFString &decompressedColorModel) const +{ + OFCondition result = EC_InvalidTag; + if ((dataset != NULL ) && ((dataset->ident() == EVR_dataset) || (dataset->ident() == EVR_item))) + { + // retrieve color model from given dataset + result = dataset->findAndGetOFString(DCM_PhotometricInterpretation, decompressedColorModel); + } + return result; +} diff --git a/dcmdata/libsrc/dcrlecce.cc b/dcmdata/libsrc/dcrlecce.cc new file mode 100644 index 00000000..16b6c069 --- /dev/null +++ b/dcmdata/libsrc/dcrlecce.cc @@ -0,0 +1,436 @@ +/* + * + * Copyright (C) 2002-2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Marco Eichelberg + * + * Purpose: encoder codec class for RLE + * + */ + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmdata/dcrlecce.h" + +#include "dcmtk/dcmdata/dcrleenc.h" /* for class DcmRLEEncoder */ +#include "dcmtk/dcmdata/dcrlecp.h" /* for class DcmRLECodecParameter */ +#include "dcmtk/dcmdata/dcdeftag.h" /* for tag constants */ +#include "dcmtk/dcmdata/dcpixseq.h" /* for class DcmPixelSequence */ +#include "dcmtk/dcmdata/dcpxitem.h" /* for class DcmPixelItem */ +#include "dcmtk/dcmdata/dcswap.h" /* for swapIfNecessary */ +#include "dcmtk/dcmdata/dcitem.h" +#include "dcmtk/ofstd/ofstd.h" + +#define INCLUDE_CSTDIO +#include "dcmtk/ofstd/ofstdinc.h" + + +typedef OFList DcmRLEEncoderList; +typedef OFListIterator(DcmRLEEncoder *) DcmRLEEncoderListIterator; + + +// ======================================================================= + +DcmRLECodecEncoder::DcmRLECodecEncoder() +: DcmCodec() +{ +} + + +DcmRLECodecEncoder::~DcmRLECodecEncoder() +{ +} + + +OFBool DcmRLECodecEncoder::canChangeCoding( + const E_TransferSyntax oldRepType, + const E_TransferSyntax newRepType) const +{ + E_TransferSyntax myXfer = EXS_RLELossless; + DcmXfer newRep(newRepType); + DcmXfer oldRep(oldRepType); + if (oldRep.isNotEncapsulated() && (newRepType == myXfer)) return OFTrue; // compress requested + + // we don't support re-coding for now. + return OFFalse; +} + + +OFCondition DcmRLECodecEncoder::decode( + const DcmRepresentationParameter * /* fromRepParam */, + DcmPixelSequence * /* pixSeq */, + DcmPolymorphOBOW& /* uncompressedPixelData */, + const DcmCodecParameter * /* cp */, + const DcmStack& /* objStack */) const +{ + // we are an encoder only + return EC_IllegalCall; +} + + +OFCondition DcmRLECodecEncoder::decodeFrame( + const DcmRepresentationParameter * /* fromParam */ , + DcmPixelSequence * /* fromPixSeq */ , + const DcmCodecParameter * /* cp */ , + DcmItem * /* dataset */ , + Uint32 /* frameNo */ , + Uint32& /* startFragment */ , + void * /* buffer */ , + Uint32 /* bufSize */ , + OFString& /* decompressedColorModel */ ) const +{ + // we are an encoder only + return EC_IllegalCall; +} + + +OFCondition DcmRLECodecEncoder::encode( + const E_TransferSyntax /* fromRepType */, + const DcmRepresentationParameter * /* fromRepParam */, + DcmPixelSequence * /* fromPixSeq */, + const DcmRepresentationParameter * /* toRepParam */, + DcmPixelSequence * & /* toPixSeq */, + const DcmCodecParameter * /* cp */, + DcmStack & /* objStack */) const +{ + // we don't support re-coding for now. + return EC_IllegalCall; +} + + +OFCondition DcmRLECodecEncoder::encode( + const Uint16 *pixelData, + const Uint32 length, + const DcmRepresentationParameter * /* toRepParam */ , + DcmPixelSequence * & pixSeq, + const DcmCodecParameter *cp, + DcmStack & objStack) const +{ + OFCondition result = EC_Normal; + + // assume we can cast the codec parameter to what we need + const DcmRLECodecParameter *djcp = OFstatic_cast(const DcmRLECodecParameter *, cp); + DcmStack localStack(objStack); + (void)localStack.pop(); // pop pixel data element from stack + DcmObject *dataset = localStack.pop(); // this is the item in which the pixel data is located + Uint8 *pixelData8 = OFreinterpret_cast(Uint8 *, OFconst_cast(Uint16 *, pixelData)); + Uint8 *pixelPointer = NULL; + DcmOffsetList offsetList; + DcmRLEEncoderList rleEncoderList; + DcmRLEEncoderListIterator first = rleEncoderList.begin(); + DcmRLEEncoderListIterator last = rleEncoderList.end(); + Uint32 rleHeader[16]; + Uint32 i; + OFBool byteSwapped = OFFalse; // true if we have byte-swapped the original pixel data + + if ((!dataset)||((dataset->ident()!= EVR_dataset) && (dataset->ident()!= EVR_item))) result = EC_InvalidTag; + else + { + DcmItem *ditem = OFstatic_cast(DcmItem *, dataset); + Uint16 bitsAllocated = 0; + Uint16 bytesAllocated = 0; + Uint16 samplesPerPixel = 0; + Uint16 planarConfiguration = 0; + Uint16 columns = 0; + Uint16 rows = 0; + Sint32 numberOfFrames = 1; + Uint32 numberOfStripes = 0; + Uint32 compressedSize = 0; + + result = ditem->findAndGetUint16(DCM_BitsAllocated, bitsAllocated); + if (result.good()) result = ditem->findAndGetUint16(DCM_SamplesPerPixel, samplesPerPixel); + if (result.good()) result = ditem->findAndGetUint16(DCM_Columns, columns); + if (result.good()) result = ditem->findAndGetUint16(DCM_Rows, rows); + if (result.good()) + { + result = ditem->findAndGetSint32(DCM_NumberOfFrames, numberOfFrames); + if (result.bad() || numberOfFrames < 1) numberOfFrames = 1; + result = EC_Normal; + } + if (result.good() && (samplesPerPixel > 1)) + { + result = ditem->findAndGetUint16(DCM_PlanarConfiguration, planarConfiguration); + } + + if (result.good()) + { + // check if bitsAllocated is a multiple of 8 - we don't handle anything else + bytesAllocated = OFstatic_cast(Uint16, bitsAllocated / 8); + if ((bitsAllocated < 8)||(bitsAllocated % 8 != 0)) result = EC_CannotChangeRepresentation; + + // make sure that all the descriptive attributes have sensible values + if ((columns < 1)||(rows < 1)||(samplesPerPixel < 1)) result = EC_CannotChangeRepresentation; + + // an RLE stripe set can have at most 15 stripes, i.e. 15 bytes allocated per pixel + numberOfStripes = bytesAllocated * samplesPerPixel; + if (numberOfStripes > 15) result = EC_CannotChangeRepresentation; + + // make sure that we have at least as many bytes of pixel data as we expect + if (numberOfStripes * columns * rows * numberOfFrames > length) result = EC_CannotChangeRepresentation; + } + + DcmPixelSequence *pixelSequence = NULL; + DcmPixelItem *offsetTable = NULL; + + // create initial pixel sequence + if (result.good()) + { + pixelSequence = new DcmPixelSequence(DCM_PixelSequenceTag); + if (pixelSequence == NULL) result = EC_MemoryExhausted; + else + { + // create empty offset table + offsetTable = new DcmPixelItem(DCM_PixelItemTag); + if (offsetTable == NULL) result = EC_MemoryExhausted; + else pixelSequence->insert(offsetTable); + } + } + + // byte swap pixel data to little endian + if (gLocalByteOrder == EBO_BigEndian) + { + swapIfNecessary(EBO_LittleEndian, gLocalByteOrder, OFstatic_cast(void *, OFconst_cast(Uint16 *, pixelData)), length, sizeof(Uint16)); + } + + // create RLE stripe sets + if (result.good()) + { + const Uint32 bytesPerStripe = columns * rows; + const Uint32 frameSize = columns * rows * samplesPerPixel * bytesAllocated; + Uint32 frameOffset = 0; + Uint32 sampleOffset = 0; + Uint32 offsetBetweenSamples = 0; + Uint32 sample = 0; + Uint32 byte = 0; + register Uint32 pixel = 0; + register Uint32 columnCounter = 0; + + DcmRLEEncoder *rleEncoder = NULL; + Uint32 rleSize = 0; + Uint8 *rleData = NULL; + Uint8 *rleData2 = NULL; + + // warn about (possibly) non-standard fragmentation + if (djcp->getFragmentSize() > 0) + DCMDATA_WARN("DcmRLECodecEncoder: limiting the fragment size may result in non-standard conformant encoding"); + + // compute byte offset between samples + if (planarConfiguration == 0) + offsetBetweenSamples = samplesPerPixel * bytesAllocated; + else offsetBetweenSamples = bytesAllocated; + + // loop through all frames of the image + for (Uint32 currentFrame = 0; ((currentFrame < OFstatic_cast(Uint32, numberOfFrames)) && result.good()); currentFrame++) + { + // offset to start of frame, in bytes + frameOffset = frameSize * currentFrame; + + // loop through all samples of one frame + for (sample = 0; sample < samplesPerPixel; sample++) + { + // compute byte offset for first sample in frame + if (planarConfiguration == 0) + sampleOffset = sample * bytesAllocated; + else sampleOffset = sample * bytesAllocated * columns * rows; + + // loop through the bytes of one sample + for (byte = 0; byte < bytesAllocated; byte++) + { + pixelPointer = pixelData8 + frameOffset + sampleOffset + bytesAllocated - byte - 1; + + // initialize new RLE codec for this stripe + rleEncoder = new DcmRLEEncoder(1 /* DICOM padding required */); + if (rleEncoder) + { + rleEncoderList.push_back(rleEncoder); + columnCounter = columns; + + // loop through all pixels of the frame + for (pixel = 0; pixel < bytesPerStripe; ++pixel) + { + rleEncoder->add(*pixelPointer); + + // enforce DICOM rule that "Each row of the image shall be encoded + // separately and not cross a row boundary." + // (see DICOM part 5 section G.3.1) + if (--columnCounter == 0) + { + rleEncoder->flush(); + columnCounter = columns; + } + pixelPointer += offsetBetweenSamples; + } + + rleEncoder->flush(); + if (rleEncoder->fail()) result = EC_MemoryExhausted; + } else result = EC_MemoryExhausted; + } + } + + // store frame and erase RLE codec list + if (result.good() && (rleEncoderList.size() > 0) && (rleEncoderList.size() < 16)) + { + // compute size of compressed frame including RLE header + // and populate RLE header + for (i=0; i<16; i++) rleHeader[i] = 0; + rleHeader[0] = OFstatic_cast(Uint32, rleEncoderList.size()); + rleSize = 64; + i = 1; + first = rleEncoderList.begin(); + while (first != last) + { + rleHeader[i++] = rleSize; + rleSize += OFstatic_cast(Uint32, (*first)->size()); + ++first; + } + + // allocate buffer for compressed frame + rleData = new Uint8[rleSize]; + + if (rleData) + { + // copy RLE header to compressed frame buffer + swapIfNecessary(EBO_LittleEndian, gLocalByteOrder, rleHeader, OFstatic_cast(Uint32, 16*sizeof(Uint32)), sizeof(Uint32)); + memcpy(rleData, rleHeader, 64); + + // store RLE stripe sets in compressed frame buffer + rleData2 = rleData + 64; + first = rleEncoderList.begin(); + while (first != last) + { + (*first)->write(rleData2); + rleData2 += (*first)->size(); + delete *first; + first = rleEncoderList.erase(first); + } + + // store compressed frame, breaking into segments if necessary + result = pixelSequence->storeCompressedFrame(offsetList, rleData, rleSize, djcp->getFragmentSize()); + compressedSize += rleSize; + + // erase buffer for compressed frame + delete[] rleData; + } else result = EC_MemoryExhausted; + } + else + { + // erase RLE codec list + first = rleEncoderList.begin(); + while (first != last) + { + delete *first; + first = rleEncoderList.erase(first); + } + if (result.good()) result = EC_CannotChangeRepresentation; + } + + } + + } + + // store pixel sequence if everything went well. + if (result.good()) pixSeq = pixelSequence; + else + { + delete pixelSequence; + pixSeq = NULL; + } + + if ((result.good()) && (djcp->getCreateOffsetTable())) + { + // create offset table + result = offsetTable->createOffsetTable(offsetList); + } + + // the following operations do not affect the Image Pixel Module + // but other modules such as SOP Common. We only perform these + // changes if we're on the main level of the dataset, + // which should always identify itself as dataset, not as item. + if (dataset->ident() == EVR_dataset) + { + if (result.good()) + { + // create new UID if mode is true or if we're converting to Secondary Capture + if (djcp->getConvertToSC() || djcp->getUIDCreation()) + { + result = DcmCodec::newInstance(OFstatic_cast(DcmItem *, dataset), "DCM", "121320", "Uncompressed predecessor"); + + // set image type to DERIVED + if (result.good()) result = updateImageType(OFstatic_cast(DcmItem *, dataset)); + + // update derivation description + if (result.good()) + { + // compute original image size in bytes, ignoring any padding bits. + double compressionRatio = 0.0; + if (compressedSize > 0) compressionRatio = (OFstatic_cast(double, columns * rows * bitsAllocated * OFstatic_cast(Uint32, numberOfFrames) * samplesPerPixel) / 8.0) / compressedSize; + result = updateDerivationDescription(OFstatic_cast(DcmItem *, dataset), compressionRatio); + } + } + } + + // convert to Secondary Capture if requested by user. + // This method creates a new SOP class UID, so it should be executed + // after the call to newInstance() which creates a Source Image Sequence. + if (result.good() && djcp->getConvertToSC()) result = DcmCodec::convertToSecondaryCapture(OFstatic_cast(DcmItem *, dataset)); + } + } + + // byte swap pixel data back to local endian if necessary + if (byteSwapped) + { + swapIfNecessary(gLocalByteOrder, EBO_LittleEndian, OFstatic_cast(void *, OFconst_cast(Uint16 *, pixelData)), length, sizeof(Uint16)); + } + return result; +} + + +OFCondition DcmRLECodecEncoder::updateDerivationDescription( + DcmItem *dataset, + double ratio) +{ + char buf[32]; + + // create new Derivation Description + OFString derivationDescription = "Lossless RLE compression, compression ratio "; + OFStandard::ftoa(buf, sizeof(buf), ratio, OFStandard::ftoa_uppercase, 0, 5); + derivationDescription += buf; + + // append old Derivation Description, if any + const char *oldDerivation = NULL; + if ((dataset->findAndGetString(DCM_DerivationDescription, oldDerivation)).good() && oldDerivation) + { + derivationDescription += " ["; + derivationDescription += oldDerivation; + derivationDescription += "]"; + if (derivationDescription.length() > 1024) + { + // ST is limited to 1024 characters, cut off tail + derivationDescription.erase(1020); + derivationDescription += "...]"; + } + } + + return dataset->putAndInsertString(DCM_DerivationDescription, derivationDescription.c_str()); +} + + +OFCondition DcmRLECodecEncoder::determineDecompressedColorModel( + const DcmRepresentationParameter * /* fromParam */, + DcmPixelSequence * /* fromPixSeq */, + const DcmCodecParameter * /* cp */, + DcmItem * /* dataset */, + OFString & /* decompressedColorModel */) const +{ + return EC_IllegalCall; +} diff --git a/dcmdata/libsrc/dcrlecp.cc b/dcmdata/libsrc/dcrlecp.cc new file mode 100644 index 00000000..192a98af --- /dev/null +++ b/dcmdata/libsrc/dcrlecp.cc @@ -0,0 +1,63 @@ +/* + * + * Copyright (C) 1994-2010, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Marco Eichelberg + * + * Purpose: codec parameter for RLE + * + */ + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmdata/dcrlecp.h" + +DcmRLECodecParameter::DcmRLECodecParameter( + OFBool pCreateSOPInstanceUID, + Uint32 pFragmentSize, + OFBool pCreateOffsetTable, + OFBool pConvertToSC, + OFBool pReverseDecompressionByteOrder) +: DcmCodecParameter() +, fragmentSize(pFragmentSize) +, createOffsetTable(pCreateOffsetTable) +, convertToSC(pConvertToSC) +, createInstanceUID(pCreateSOPInstanceUID) +, reverseDecompressionByteOrder(pReverseDecompressionByteOrder) +{ +} + + +DcmRLECodecParameter::DcmRLECodecParameter(const DcmRLECodecParameter& arg) +: DcmCodecParameter(arg) +, fragmentSize(arg.fragmentSize) +, createOffsetTable(arg.createOffsetTable) +, convertToSC(arg.convertToSC) +, createInstanceUID(arg.createInstanceUID) +, reverseDecompressionByteOrder(arg.reverseDecompressionByteOrder) +{ +} + +DcmRLECodecParameter::~DcmRLECodecParameter() +{ +} + +DcmCodecParameter *DcmRLECodecParameter::clone() const +{ + return new DcmRLECodecParameter(*this); +} + +const char *DcmRLECodecParameter::className() const +{ + return "DcmRLECodecParameter"; +} diff --git a/dcmdata/libsrc/dcrledrg.cc b/dcmdata/libsrc/dcrledrg.cc new file mode 100644 index 00000000..439efd48 --- /dev/null +++ b/dcmdata/libsrc/dcrledrg.cc @@ -0,0 +1,68 @@ +/* + * + * Copyright (C) 1994-2010, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Marco Eichelberg + * + * Purpose: singleton class that registers RLE decoder. + * + */ + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmdata/dcrledrg.h" + +#include "dcmtk/dcmdata/dccodec.h" /* for DcmCodecStruct */ +#include "dcmtk/dcmdata/dcrleccd.h" /* for class DcmRLECodecDecoder */ +#include "dcmtk/dcmdata/dcrlecp.h" /* for class DcmRLECodecParameter */ + +// initialization of static members +OFBool DcmRLEDecoderRegistration::registered = OFFalse; +DcmRLECodecParameter *DcmRLEDecoderRegistration::cp = NULL; +DcmRLECodecDecoder *DcmRLEDecoderRegistration::codec = NULL; + +void DcmRLEDecoderRegistration::registerCodecs( + OFBool pCreateSOPInstanceUID, + OFBool pReverseDecompressionByteOrder) +{ + if (! registered) + { + cp = new DcmRLECodecParameter( + pCreateSOPInstanceUID, + 0, OFTrue, OFFalse, + pReverseDecompressionByteOrder); + + if (cp) + { + codec = new DcmRLECodecDecoder(); + if (codec) DcmCodecList::registerCodec(codec, NULL, cp); + registered = OFTrue; + } + } +} + +void DcmRLEDecoderRegistration::cleanup() +{ + if (registered) + { + DcmCodecList::deregisterCodec(codec); + delete codec; + delete cp; + registered = OFFalse; +#ifdef DEBUG + // not needed but useful for debugging purposes + codec = NULL; + cp = NULL; +#endif + } +} diff --git a/dcmdata/libsrc/dcrleerg.cc b/dcmdata/libsrc/dcrleerg.cc new file mode 100644 index 00000000..c86d1b4e --- /dev/null +++ b/dcmdata/libsrc/dcrleerg.cc @@ -0,0 +1,72 @@ +/* + * + * Copyright (C) 1994-2010, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Marco Eichelberg + * + * Purpose: singleton class that registers RLE encoder. + * + */ + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmdata/dcrleerg.h" + +#include "dcmtk/dcmdata/dccodec.h" /* for DcmCodecStruct */ +#include "dcmtk/dcmdata/dcrlecce.h" /* for class DcmRLECodecEncoder */ +#include "dcmtk/dcmdata/dcrlecp.h" /* for class DcmRLECodecParameter */ + +// initialization of static members +OFBool DcmRLEEncoderRegistration::registered = OFFalse; +DcmRLECodecParameter *DcmRLEEncoderRegistration::cp = NULL; +DcmRLECodecEncoder *DcmRLEEncoderRegistration::codec = NULL; + +void DcmRLEEncoderRegistration::registerCodecs( + OFBool pCreateSOPInstanceUID, + Uint32 pFragmentSize, + OFBool pCreateOffsetTable, + OFBool pConvertToSC) +{ + if (! registered) + { + cp = new DcmRLECodecParameter( + pCreateSOPInstanceUID, + pFragmentSize, + pCreateOffsetTable, + pConvertToSC); + + if (cp) + { + codec = new DcmRLECodecEncoder(); + if (codec) DcmCodecList::registerCodec(codec, NULL, cp); + registered = OFTrue; + } + } +} + +void DcmRLEEncoderRegistration::cleanup() +{ + if (registered) + { + DcmCodecList::deregisterCodec(codec); + delete codec; + delete cp; + registered = OFFalse; +#ifdef DEBUG + // not needed but useful for debugging purposes + codec = NULL; + cp = NULL; +#endif + + } +} diff --git a/dcmdata/libsrc/dcrlerp.cc b/dcmdata/libsrc/dcrlerp.cc new file mode 100644 index 00000000..a3cd50ed --- /dev/null +++ b/dcmdata/libsrc/dcrlerp.cc @@ -0,0 +1,59 @@ +/* + * + * Copyright (C) 1994-2010, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Marco Eichelberg + * + * Purpose: representation parameter for RLE + * + */ + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmdata/dcrlerp.h" + + +DcmRLERepresentationParameter::DcmRLERepresentationParameter() +: DcmRepresentationParameter() +{ +} + +DcmRLERepresentationParameter::DcmRLERepresentationParameter(const DcmRLERepresentationParameter& arg) +: DcmRepresentationParameter(arg) +{ +} + +DcmRLERepresentationParameter::~DcmRLERepresentationParameter() +{ +} + +DcmRepresentationParameter *DcmRLERepresentationParameter::clone() const +{ + return new DcmRLERepresentationParameter(*this); +} + +const char *DcmRLERepresentationParameter::className() const +{ + return "DcmRLERepresentationParameter"; +} + +OFBool DcmRLERepresentationParameter::operator==(const DcmRepresentationParameter &arg) const +{ + const char *argname = arg.className(); + if (argname) + { + OFString argstring(argname); + if (argstring == className()) return OFTrue; + } + return OFFalse; +} diff --git a/dcmdata/libsrc/dcsequen.cc b/dcmdata/libsrc/dcsequen.cc new file mode 100644 index 00000000..b4c77d3f --- /dev/null +++ b/dcmdata/libsrc/dcsequen.cc @@ -0,0 +1,1472 @@ +/* + * + * Copyright (C) 1994-2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Gerd Ehlers, Andreas Barth + * + * Purpose: Implementation of class DcmSequenceOfItems + * + */ + + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#define INCLUDE_CSTDLIB +#define INCLUDE_CSTDIO +#include "dcmtk/ofstd/ofstdinc.h" + +#include "dcmtk/ofstd/ofstream.h" +#include "dcmtk/ofstd/ofstd.h" +#include "dcmtk/ofstd/ofcast.h" + +#include "dcmtk/dcmdata/dcsequen.h" +#include "dcmtk/dcmdata/dcitem.h" +#include "dcmtk/dcmdata/dcdirrec.h" +#include "dcmtk/dcmdata/dcvr.h" +#include "dcmtk/dcmdata/dcpxitem.h" +#include "dcmtk/dcmdata/dcswap.h" +#include "dcmtk/dcmdata/dcmetinf.h" +#include "dcmtk/dcmdata/dcdeftag.h" +#include "dcmtk/dcmdata/dcistrma.h" /* for class DcmInputStream */ +#include "dcmtk/dcmdata/dcostrma.h" /* for class DcmOutputStream */ + + +// ******************************** + + +DcmSequenceOfItems::DcmSequenceOfItems( + const DcmTag &tag, + const Uint32 len, + OFBool readAsUN) +: DcmElement(tag, len), + itemList(new DcmList), + lastItemComplete(OFTrue), + fStartPosition(0), + readAsUN_(readAsUN) +{ +} + + +// ******************************** + + +DcmSequenceOfItems::DcmSequenceOfItems(const DcmSequenceOfItems &old) + : DcmElement(old), + itemList(new DcmList), + lastItemComplete(old.lastItemComplete), + fStartPosition(old.fStartPosition), + readAsUN_(old.readAsUN_) +{ + if (!old.itemList->empty()) + { + itemList->seek(ELP_first); + old.itemList->seek(ELP_first); + do + { + DcmObject *dO = old.itemList->get()->clone(); + itemList->insert(dO, ELP_next); + // remember the parent + dO->setParent(this); + } while (old.itemList->seek(ELP_next)); + } +} + + +// ******************************** + + +DcmSequenceOfItems::~DcmSequenceOfItems() +{ + itemList->deleteAllElements(); + delete itemList; +} + + +// ******************************** + + +DcmSequenceOfItems &DcmSequenceOfItems::operator=(const DcmSequenceOfItems &obj) +{ + if (this != &obj) + { + DcmElement::operator=(obj); + lastItemComplete = obj.lastItemComplete; + fStartPosition = obj.fStartPosition; + readAsUN_ = obj.readAsUN_; + + // DcmList has no copy constructor. Need to copy ourselves. + DcmList *newList = new DcmList; + if (newList) + { + switch (obj.ident()) + { + case EVR_SQ: + case EVR_pixelSQ: + case EVR_fileFormat: + if (!obj.itemList->empty()) + { + DcmObject *oldDO; + DcmObject *newDO; + newList->seek(ELP_first); + obj.itemList->seek(ELP_first); + do { + oldDO = obj.itemList->get(); + switch (oldDO->ident()) + { + case EVR_item: + newDO = new DcmItem(*OFstatic_cast(DcmItem *, oldDO)); + break; + case EVR_pixelItem: + newDO = new DcmPixelItem(*OFstatic_cast(DcmPixelItem *, oldDO)); + break; + case EVR_metainfo: + newDO = new DcmMetaInfo(*OFstatic_cast(DcmMetaInfo *, oldDO)); + break; + case EVR_dataset: + newDO = new DcmDataset(*OFstatic_cast(DcmDataset *, oldDO)); + break; + default: + newDO = new DcmItem(oldDO->getTag()); + DCMDATA_WARN("DcmSequenceOfItems: Non-item element " << oldDO->getTag() << " found"); + break; + } + newList->insert(newDO, ELP_next); + // remember the parent + newDO->setParent(this); + } while (obj.itemList->seek(ELP_next)); + } + break; + default: + // wrong use of assignment operator, should never happen + break; + } + } + // be sure to clear memory of former elements not in use any more... + itemList->deleteAllElements(); + // ...and delete the list itself + delete itemList; + itemList = newList; + } + return *this; +} + + +// ******************************** + + +OFCondition DcmSequenceOfItems::copyFrom(const DcmObject& rhs) +{ + if (this != &rhs) + { + if (rhs.ident() != ident()) return EC_IllegalCall; + *this = OFstatic_cast(const DcmSequenceOfItems &, rhs); + } + return EC_Normal; +} + + +// ******************************** + + +int DcmSequenceOfItems::compare(const DcmElement& rhs) const +{ + int result = DcmElement::compare(rhs); + if (result != 0) + { + return result; + } + + /* cast away constness (dcmdata is not const correct...) */ + DcmSequenceOfItems* myThis = NULL; + DcmSequenceOfItems* myRhs = NULL; + myThis = OFconst_cast(DcmSequenceOfItems*, this); + myRhs = OFstatic_cast(DcmSequenceOfItems*, OFconst_cast(DcmElement*, &rhs)); + + /* iterate over all items and test equality */ + unsigned long thisVM = myThis->card(); + for (unsigned long count = 0; count < thisVM; count++) + { + DcmItem* val = myThis->getItem(count); + if (val) + { + DcmItem* rhsVal = myRhs->getItem(count); + if (rhsVal) + { + int result = val->compare(*rhsVal); + if (result != 0) + { + return result; + } + } + else + { + break; // values equal until this point (rhs shorter) + } + } + } + + /* we get here if all values are equal. Now look at the number of components. */ + unsigned long rhsVM = myRhs->card(); + if (thisVM < rhsVM) + { + return -1; + } + else if (thisVM > rhsVM) + { + return 1; + } + + /* all values as well as VM equal: objects are equal */ + return 0; +} + + +// ******************************** + + +OFCondition DcmSequenceOfItems::checkValue(const OFString &cardinality, + const OFBool /*oldFormat*/) +{ + /* check cardinality (number of items) only */ + return DcmElement::checkVM(this->card(), cardinality); +} + + +// ******************************** + + +void DcmSequenceOfItems::print(STD_NAMESPACE ostream&out, + const size_t flags, + const int level, + const char *pixelFileName, + size_t *pixelCounter) +{ + /* print sequence start line */ + if (flags & DCMTypes::PF_showTreeStructure) + { + /* empty text */ + printInfoLine(out, flags, level); + /* print sequence content */ + if (!itemList->empty()) + { + /* print all items contained in the sequence */ + DcmObject *dO; + itemList->seek(ELP_first); + do { + dO = itemList->get(); + dO->print(out, flags, level + 1, pixelFileName, pixelCounter); + } while (itemList->seek(ELP_next)); + } + } else { + OFOStringStream oss; + oss << "(Sequence with "; + if (getLengthField() == DCM_UndefinedLength) + oss << "undefined"; + else + oss << "explicit"; + oss << " length #=" << card() << ")" << OFStringStream_ends; + OFSTRINGSTREAM_GETSTR(oss, tmpString) + printInfoLine(out, flags, level, tmpString); + OFSTRINGSTREAM_FREESTR(tmpString) + /* print sequence content */ + if (!itemList->empty()) + { + DcmObject *dO; + itemList->seek(ELP_first); + do { + dO = itemList->get(); + dO->print(out, flags, level + 1, pixelFileName, pixelCounter); + } while (itemList->seek(ELP_next)); + } + /* print sequence end line */ + DcmTag delimItemTag(DCM_SequenceDelimitationItemTag); + if (getLengthField() == DCM_UndefinedLength) + printInfoLine(out, flags, level, "(SequenceDelimitationItem)", &delimItemTag); + else + printInfoLine(out, flags, level, "(SequenceDelimitationItem for re-encod.)", &delimItemTag); + } +} + + +// ******************************** + + +OFCondition DcmSequenceOfItems::writeXML(STD_NAMESPACE ostream&out, + const size_t flags) +{ + if (flags & DCMTypes::XF_useNativeModel) + { + /* use common method from DcmElement to write start tag */ + DcmElement::writeXMLStartTag(out, flags); + /* write sequence content */ + if (!itemList->empty()) + { + unsigned long itemNo = 1; + /* write content of all children */ + DcmObject *dO; + itemList->seek(ELP_first); + do + { + out << "" << OFendl; + dO = itemList->get(); + dO->writeXML(out, flags); + out << "" << OFendl; + } while (itemList->seek(ELP_next)); + } + /* use common method from DcmElement to write end tag */ + DcmElement::writeXMLEndTag(out, flags); + } else { + OFString xmlString; + DcmVR vr(getTag().getVR()); + /* XML start tag for "sequence" */ + out << "" << OFendl; + /* write sequence content */ + if (!itemList->empty()) + { + /* write content of all children */ + DcmObject *dO; + itemList->seek(ELP_first); + do + { + dO = itemList->get(); + dO->writeXML(out, flags); + } while (itemList->seek(ELP_next)); + } + /* XML end tag for "sequence" */ + out << "" << OFendl; + } + /* always report success */ + return EC_Normal; +} + + +// ******************************** + + +OFBool DcmSequenceOfItems::canWriteXfer(const E_TransferSyntax newXfer, + const E_TransferSyntax oldXfer) +{ + OFBool canWrite = OFTrue; + + if (newXfer == EXS_Unknown) + canWrite = OFFalse; + else if (!itemList->empty()) + { + DcmObject *dO; + itemList->seek(ELP_first); + do + { + dO = itemList->get(); + canWrite = dO -> canWriteXfer(newXfer, oldXfer); + } while (itemList->seek(ELP_next) && canWrite); + } + + return canWrite; +} + + +// ******************************** + + +Uint32 DcmSequenceOfItems::calcElementLength(const E_TransferSyntax xfer, + const E_EncodingType enctype) +{ + /* Get length of sequence header + sequence content (will call DcmSequenceOfItems::getLength()) */ + Uint32 seqlen = DcmElement::calcElementLength(xfer, enctype); + if (seqlen == DCM_UndefinedLength) + return DCM_UndefinedLength; + if (enctype == EET_UndefinedLength) + { + if (OFStandard::check32BitAddOverflow(seqlen, 8)) + return DCM_UndefinedLength; + else + seqlen += 8; // for Sequence Delimitation Tag + } + return seqlen; +} + + +// ******************************** + + +Uint32 DcmSequenceOfItems::getLength(const E_TransferSyntax xfer, + const E_EncodingType enctype) +{ + Uint32 seqlen = 0; + Uint32 sublen = 0; + if (!itemList->empty()) + { + DcmItem *dI; + itemList->seek(ELP_first); + do { + dI = OFstatic_cast(DcmItem *, itemList->get()); + sublen = dI->calcElementLength(xfer, enctype); + /* explicit length: be sure that total size of contained elements fits into sequence's + 32 Bit length field. If not, switch encoding automatically to undefined + length for this sequence. Nevertheless, any contained items will be + written with explicit length if possible. + */ + if ( (enctype == EET_ExplicitLength) && OFStandard::check32BitAddOverflow(seqlen, sublen) ) + { + if (dcmWriteOversizedSeqsAndItemsUndefined.get()) + { + DCMDATA_WARN("DcmSequenceOfItems: Explicit length of sequence " << getTagName() << " " << getTag() + << " exceeds 32-bit length field, trying to treat it as undefined length instead"); + } + else + { + DCMDATA_WARN("DcmSequenceOfItems: Explicit length of sequence " << getTagName() << " " << getTag() + << " exceeds 32-bit length field, writing with explicit length will not be possible"); + errorFlag = EC_SeqOrItemContentOverflow; + } + return DCM_UndefinedLength; + } + seqlen += sublen; + } while (itemList->seek(ELP_next)); + } + return seqlen; +} + + +// ******************************** + + +OFCondition DcmSequenceOfItems::computeGroupLengthAndPadding(const E_GrpLenEncoding glenc, + const E_PaddingEncoding padenc, + const E_TransferSyntax xfer, + const E_EncodingType enctype, + const Uint32 padlen, + const Uint32 subPadlen, + Uint32 instanceLength) +{ + OFCondition l_error = EC_Normal; + + if (!itemList->empty()) + { + itemList->seek(ELP_first); + do { + DcmItem *dO = OFstatic_cast(DcmItem *, itemList->get()); + l_error = dO->computeGroupLengthAndPadding + (glenc, padenc, xfer, enctype, padlen, subPadlen, instanceLength); + } while (l_error.good() && itemList->seek(ELP_next)); + } + return l_error; +} + + +// ******************************** + + +OFCondition DcmSequenceOfItems::makeSubObject(DcmObject *&subObject, + const DcmTag &newTag, + const Uint32 newLength) +{ + OFCondition l_error = EC_Normal; + DcmItem *subItem = NULL; + + switch (newTag.getEVR()) + { + case EVR_na: + if (newTag.getXTag() == DCM_Item) + { + if (getTag().getXTag() == DCM_DirectoryRecordSequence) + subItem = new DcmDirectoryRecord(newTag, newLength); + else + subItem = new DcmItem(newTag, newLength); + } + else if (newTag.getXTag() == DCM_SequenceDelimitationItem) + l_error = EC_SequEnd; + else if (newTag.getXTag() == DCM_ItemDelimitationItem) + l_error = EC_ItemEnd; + else + l_error = EC_InvalidTag; + break; + + default: + subItem = new DcmItem(newTag, newLength); + l_error = EC_CorruptedData; + break; + } + subObject = subItem; + return l_error; +} + + +// ******************************** + + +OFCondition DcmSequenceOfItems::readTagAndLength(DcmInputStream &inStream, + const E_TransferSyntax xfer, + DcmTag &tag, + Uint32 &length) +{ + Uint16 groupTag = 0xffff; + Uint16 elementTag = 0xffff; + + OFCondition l_error = EC_Normal; + if (inStream.avail() < 8) + l_error = EC_StreamNotifyClient; + + if (l_error.good()) + { + DcmXfer iXfer(xfer); + const E_ByteOrder iByteOrder = iXfer.getByteOrder(); + if (iByteOrder == EBO_unknown) + return EC_IllegalCall; + inStream.mark(); + inStream.read(&groupTag, 2); + inStream.read(&elementTag, 2); + swapIfNecessary(gLocalByteOrder, iByteOrder, &groupTag, 2, 2); + swapIfNecessary(gLocalByteOrder, iByteOrder, &elementTag, 2, 2); + // tag has been read + + DcmTag newTag(groupTag, elementTag); + + Uint32 valueLength = 0; + inStream.read(&valueLength, 4); + swapIfNecessary(gLocalByteOrder, iByteOrder, &valueLength, 4, 4); + if ((valueLength & 1) && (valueLength != DCM_UndefinedLength)) + { + DCMDATA_WARN("DcmSequenceOfItems: Length of item in sequence " + << getTagName() << " " << getTag() << " is odd"); + } + length = valueLength; + tag = newTag; // return value: assignment-operator + } + + if (l_error.bad()) + DCMDATA_TRACE("DcmSequenceOfItems::readTagAndLength() returns error = " << l_error.text()); + return l_error; +} + + +// ******************************** + + +OFCondition DcmSequenceOfItems::readSubItem(DcmInputStream &inStream, + const DcmTag &newTag, + const Uint32 newLength, + const E_TransferSyntax xfer, + const E_GrpLenEncoding glenc, + const Uint32 maxReadLength) +{ + // For DcmSequenceOfItems, subObject is always inherited from DcmItem. + // For DcmPixelSequence, subObject is always inherited from DcmPixelItem. + DcmObject *subObject = NULL; + OFCondition l_error = makeSubObject(subObject, newTag, newLength); + if (l_error.good() && (subObject != NULL)) + { + // inStream.UnsetPutbackMark(); // not needed anymore with new stream architecture + itemList->insert(subObject, ELP_next); + // dump some information if required + DCMDATA_TRACE("DcmSequenceOfItems::readSubItem() Sub Item " << newTag << " inserted"); + // remember the parent (i.e. the surrounding sequence) + subObject->setParent(this); + // read sub-item + l_error = subObject->read(inStream, xfer, glenc, maxReadLength); + // prevent subObject from getting deleted + return l_error; + } + else if (l_error == EC_InvalidTag) // try to recover parsing + { + inStream.putback(); + // dump some information if required + DCMDATA_WARN("DcmSequenceOfItems: Parse error in sequence " << getTag() << ", found " + << newTag << " instead of item tag " << DCM_Item); + } + else if (l_error != EC_SequEnd) + { + // dump some information if required + if (dcmIgnoreParsingErrors.get() || (dcmReplaceWrongDelimitationItem.get() && (l_error == EC_ItemEnd))) + { + DCMDATA_WARN("DcmSequenceOfItems: Parse error in sequence " << getTag() << ", found " + << newTag << " instead of sequence delimiter " << DCM_SequenceDelimitationItem); + } else { + DCMDATA_ERROR("DcmSequenceOfItems: Parse error in sequence " << getTag() << ", found " + << newTag << " instead of sequence delimiter " << DCM_SequenceDelimitationItem); + } + // some systems use the wrong delimitation item at the end of a sequence + if (dcmReplaceWrongDelimitationItem.get() && (l_error == EC_ItemEnd)) + { + DCMDATA_DEBUG("DcmSequenceOfItems::readSubItem() replacing wrong item delimiter " + << DCM_ItemDelimitationItem << " by sequence delimiter " + << DCM_SequenceDelimitationItem << " because it is expected here"); + l_error = EC_SequEnd; + } else { + DCMDATA_DEBUG("DcmSequenceOfItems::readSubItem() cannot create Sub Item " << newTag); + // treat this incorrect encoding as an error + if (!dcmIgnoreParsingErrors.get()) + l_error = EC_SequDelimitationItemMissing; + } + } else { + // inStream.UnsetPutbackMark(); // not needed anymore with new stream architecture + } + + if (subObject) + delete subObject; // only executed if makeSubObject() has returned an error + // dump some information if required + DCMDATA_TRACE("DcmSequenceOfItems::readSubItem() returns error = " << l_error.text()); + return l_error; +} + + +// ******************************** + + +OFCondition DcmSequenceOfItems::read(DcmInputStream &inStream, + const E_TransferSyntax xfer, + const E_GrpLenEncoding glenc, + const Uint32 maxReadLength) +{ + if (getTransferState() == ERW_notInitialized) + errorFlag = EC_IllegalCall; + else + { + errorFlag = inStream.status(); + + if (errorFlag.good() && inStream.eos()) + errorFlag = EC_EndOfStream; + else if (errorFlag.good() && (getTransferState() != ERW_ready)) + { + if (getTransferState() == ERW_init) + { + fStartPosition = inStream.tell(); // Position Sequence-Value + setTransferState(ERW_inWork); + } + + E_TransferSyntax readxfer = readAsUN_ ? EXS_LittleEndianImplicit : xfer; + + itemList->seek(ELP_last); // append data at end + while (inStream.good() && ((getTransferredBytes() < getLengthField()) || !lastItemComplete)) + { + DcmTag newTag; + Uint32 newValueLength = 0; + + if (lastItemComplete) + { + if (inStream.eos()) + { + DCMDATA_WARN("DcmSequenceOfItems: Reached end of stream before the end of sequence " + << getTagName() << " " << getTag()); + if (dcmIgnoreParsingErrors.get()) + { + /* "Invent" a SequenceDelimitationItem. + * This will be turned into EC_Normal below. */ + errorFlag = EC_SequEnd; + } + else + errorFlag = EC_SequDelimitationItemMissing; + break; + } + + errorFlag = readTagAndLength(inStream, readxfer, newTag, newValueLength); + + if (errorFlag.bad()) + break; // finish while loop + else + incTransferredBytes(8); + + lastItemComplete = OFFalse; + errorFlag = readSubItem(inStream, newTag, newValueLength, readxfer, glenc, maxReadLength); + if (errorFlag.good()) + lastItemComplete = OFTrue; + } + else + { + errorFlag = itemList->get()->read(inStream, readxfer, glenc, maxReadLength); + if (errorFlag.good()) + lastItemComplete = OFTrue; + } + setTransferredBytes(OFstatic_cast(Uint32, inStream.tell() - fStartPosition)); + + if (errorFlag.bad()) + break; + + } //while + if (((getTransferredBytes() < getLengthField()) || !lastItemComplete) && errorFlag.good()) + errorFlag = EC_StreamNotifyClient; + } // else errorFlag + + if (errorFlag == EC_SequEnd) + errorFlag = EC_Normal; + if (errorFlag.good()) + setTransferState(ERW_ready); // sequence is complete + } + // dump information if required + DCMDATA_TRACE("DcmSequenceOfItems::read() returns error = " << errorFlag.text()); + return errorFlag; +} + + +// ******************************** + +OFCondition DcmSequenceOfItems::write(DcmOutputStream &outStream, + const E_TransferSyntax oxfer, + const E_EncodingType enctype, + DcmWriteCache *wcache) +{ + if (getTransferState() == ERW_notInitialized) + errorFlag = EC_IllegalCall; + else + { + errorFlag = outStream.status(); + if (errorFlag.good() && (getTransferState() != ERW_ready)) + { + if (getTransferState() == ERW_init) + { + /* first compare with DCM_TagInfoLength (12). If there is not enough space + * in the buffer, check if the buffer is still sufficient for the requirements + * of this element, which may need only 8 instead of 12 bytes. + */ + if ((outStream.avail() >= DCM_TagInfoLength) || + (outStream.avail() >= getTagAndLengthSize(oxfer))) + { + if (enctype == EET_ExplicitLength) + setLengthField(getLength(oxfer, enctype)); + else + setLengthField(DCM_UndefinedLength); + if (errorFlag == EC_SeqOrItemContentOverflow) + return EC_SeqOrItemContentOverflow; + Uint32 written_bytes = 0; + errorFlag = writeTagAndLength(outStream, oxfer, written_bytes); + if (errorFlag.good()) + { + setTransferState(ERW_inWork); + itemList->seek(ELP_first); + } + } else + errorFlag = EC_StreamNotifyClient; + } + if (getTransferState() == ERW_inWork) + { + // itemList->get() can be NULL if buffer was full after + // writing the last item but before writing the sequence delimitation. + if (!itemList->empty() && (itemList->get() != NULL)) + { + DcmObject *dO; + do + { + dO = itemList->get(); + if (dO->transferState() != ERW_ready) + errorFlag = dO->write(outStream, oxfer, enctype, wcache); + } while (errorFlag.good() && itemList->seek(ELP_next)); + } + if (errorFlag.good()) + { + setTransferState(ERW_ready); + if (getLengthField() == DCM_UndefinedLength) + { + if (outStream.avail() >= 8) + { + // write sequence delimitation item + const DcmTag delim(DCM_SequenceDelimitationItemTag); + errorFlag = writeTag(outStream, delim, oxfer); + Uint32 delimLen = 0L; + outStream.write(&delimLen, 4); // 4 bytes length + } else { + // the complete sequence is written but it + // is not possible to write the delimitation item into the buffer. + errorFlag = EC_StreamNotifyClient; + setTransferState(ERW_inWork); + } + } + } + } + } + } + return errorFlag; +} + +// ******************************** + + +OFCondition DcmSequenceOfItems::writeTagAndVR(DcmOutputStream &outStream, + const DcmTag &tag, + DcmEVR vr, + const E_TransferSyntax oxfer) +{ + OFCondition l_error = outStream.status(); + if (l_error.good()) + { + /* write the tag information (a total of 4 bytes, group number and element */ + /* number) to the stream. Mind the transfer syntax's byte ordering. */ + l_error = writeTag(outStream, tag, oxfer); + /* create an object which represents the transfer syntax */ + DcmXfer oxferSyn(oxfer); + /* if the transfer syntax is one with explicit value representation */ + /* this value's data type also has to be written to the stream. Do so */ + /* and also write the length information to the stream. */ + if (oxferSyn.isExplicitVR()) + { + /* Create an object that represents this object's data type */ + DcmVR myvr(vr); + /* get name of data type */ + const char *vrname = myvr.getValidVRName(); + /* write data type name to the stream (a total of 2 bytes) */ + outStream.write(vrname, 2); + /* create another data type object on the basis of the above created object */ + DcmVR outvr(myvr.getValidEVR()); + /* in case we are dealing with a transfer syntax with explicit VR (see if above) */ + /* and the actual VR uses extended length encoding (see DICOM standard (year 2000) */ + /* part 5, section 7.1.2) (or the corresponding section in a later version of the */ + /* standard) we have to add 2 reserved bytes (set to a value of 00H) to the data */ + /* type field and the actual length field is 4 bytes wide. Write the corresponding */ + /* information to the stream. */ + if (outvr.usesExtendedLengthEncoding()) + { + Uint16 reserved = 0; + outStream.write(&reserved, 2); // write 2 reserved bytes to stream + } + } + } + /* return result */ + return l_error; +} + + +OFCondition DcmSequenceOfItems::writeSignatureFormat(DcmOutputStream &outStream, + const E_TransferSyntax oxfer, + const E_EncodingType enctype, + DcmWriteCache *wcache) +{ + if (getTransferState() == ERW_notInitialized) + errorFlag = EC_IllegalCall; + else + { + errorFlag = outStream.status(); + if (errorFlag.good() && (getTransferState() != ERW_ready)) + { + if (getTransferState() == ERW_init) + { + /* first compare with DCM_TagInfoLength (12). If there is not enough space + * in the buffer, check if the buffer is still sufficient for the requirements + * of this element, which may need only 8 instead of 12 bytes. + */ + if ((outStream.avail() >= DCM_TagInfoLength) || + (outStream.avail() >= getTagAndLengthSize(oxfer))) + { + if (enctype == EET_ExplicitLength) + setLengthField(getLength(oxfer, enctype)); + else + setLengthField(DCM_UndefinedLength); + errorFlag = writeTagAndVR(outStream, getTag(), getVR(), oxfer); + /* we don't write the sequence length */ + if (errorFlag.good()) + { + setTransferState(ERW_inWork); + itemList->seek(ELP_first); + } + } else + errorFlag = EC_StreamNotifyClient; + } + if (getTransferState() == ERW_inWork) + { + // itemList->get() can be NULL if buffer was full after + // writing the last item but before writing the sequence delimitation. + if (!itemList->empty() && (itemList->get() != NULL)) + { + DcmObject *dO; + do { + dO = itemList->get(); + if (dO->transferState() != ERW_ready) + errorFlag = dO->writeSignatureFormat(outStream, oxfer, enctype, wcache); + } while (errorFlag.good() && itemList->seek(ELP_next)); + } + if (errorFlag.good()) + { + setTransferState(ERW_ready); + /* we always write a sequence delimitation item tag, but no length */ + if (outStream.avail() >= 4) + { + // write sequence delimitation item + const DcmTag delim(DCM_SequenceDelimitationItemTag); + errorFlag = writeTag(outStream, delim, oxfer); + } else { + // Every subelement of the item was written but it + // is not possible to write the delimitation item + // into the buffer. + setTransferState(ERW_inWork); + errorFlag = EC_StreamNotifyClient; + } + } + } + } + } + return errorFlag; +} + + +// ******************************** + + +void DcmSequenceOfItems::transferInit() +{ + DcmObject::transferInit(); + fStartPosition = 0; + lastItemComplete = OFTrue; + if (!itemList->empty()) + { + itemList->seek(ELP_first); + do { + itemList->get()->transferInit(); + } while (itemList->seek(ELP_next)); + } +} + + +// ******************************** + + +void DcmSequenceOfItems::transferEnd() +{ + DcmObject::transferEnd(); + if (!itemList->empty()) + { + itemList->seek(ELP_first); + do { + itemList->get()->transferEnd(); + } while (itemList->seek(ELP_next)); + } +} + + +// ******************************** + + +unsigned long DcmSequenceOfItems::card() const +{ + return itemList->card(); +} + + +// ******************************** + + +OFCondition DcmSequenceOfItems::prepend(DcmItem *item) +{ + errorFlag = EC_Normal; + if (item != NULL) + { + itemList->prepend(item); + // remember the parent (i.e. the surrounding sequence) + item->setParent(this); + } else + errorFlag = EC_IllegalCall; + + return errorFlag; +} + + +// ******************************** + + +OFCondition DcmSequenceOfItems::insert(DcmItem *item, + unsigned long where, + OFBool before) +{ + errorFlag = EC_Normal; + if (item != NULL) + { + itemList->seek_to(where); + // insert before or after "where" + E_ListPos whichSide = (before) ? (ELP_prev) : (ELP_next); + itemList->insert(item, whichSide); + if (where == DCM_EndOfListIndex) + { + DCMDATA_TRACE("DcmSequenceOfItems::insert() Item inserted " + << (before ? "before" : "after") << " last position"); + } else { + DCMDATA_TRACE("DcmSequenceOfItems::insert() Item inserted " + << (before ? "before" : "after") << " position " << where); + } + // check whether the new item already has a parent + if (item->getParent() != NULL) + { + DCMDATA_DEBUG("DcmSequenceOfItems::insert() Item already has a parent: " + << item->getParent()->getTag() << " VR=" << DcmVR(item->getParent()->getVR()).getVRName()); + } + // remember the parent (i.e. the surrounding sequence) + item->setParent(this); + } else + errorFlag = EC_IllegalCall; + return errorFlag; +} + + +// ******************************** + + +OFCondition DcmSequenceOfItems::insertAtCurrentPos(DcmItem *item, + OFBool before) +{ + errorFlag = EC_Normal; + if (item != NULL) + { + // insert before or after current position + E_ListPos whichSide = (before) ? (ELP_prev) : (ELP_next); + itemList->insert(item, whichSide); + // check whether the new item already has a parent + if (item->getParent() != NULL) + { + DCMDATA_DEBUG("DcmSequenceOfItems::insertAtCurrentPos() Item already has a parent: " + << item->getParent()->getTag() << " VR=" << DcmVR(item->getParent()->getVR()).getVRName()); + } + // remember the parent (i.e. the surrounding sequence) + item->setParent(this); + } else + errorFlag = EC_IllegalCall; + return errorFlag; +} + + +// ******************************** + + +OFCondition DcmSequenceOfItems::append(DcmItem *item) +{ + errorFlag = EC_Normal; + if (item != NULL) + { + itemList->append(item); + // check whether the new item already has a parent + if (item->getParent() != NULL) + { + DCMDATA_DEBUG("DcmSequenceOfItems::append() Item already has a parent: " + << item->getParent()->getTag() << " VR=" << DcmVR(item->getParent()->getVR()).getVRName()); + } + // remember the parent (i.e. the surrounding sequence) + item->setParent(this); + } else + errorFlag = EC_IllegalCall; + return errorFlag; +} + + +// ******************************** + + +DcmItem* DcmSequenceOfItems::getItem(const unsigned long num) +{ + errorFlag = EC_Normal; + DcmItem *item; + item = OFstatic_cast(DcmItem *, itemList->seek_to(num)); // read item from list + if (item == NULL) + errorFlag = EC_IllegalCall; + return item; +} + + +// ******************************** + + +DcmObject *DcmSequenceOfItems::nextInContainer(const DcmObject *obj) +{ + if (!obj) + return itemList->get(ELP_first); + else + { + if (itemList->get() != obj) + { + for (DcmObject *search_obj = itemList -> seek(ELP_first); + search_obj && (search_obj != obj); + search_obj = itemList -> seek(ELP_next) + ) + { /* do nothing */ } + } + return itemList -> seek(ELP_next); + } +} + + +// ******************************** + + +OFCondition DcmSequenceOfItems::nextObject(DcmStack &stack, + const OFBool intoSub) +{ + OFCondition l_error = EC_Normal; + DcmObject *container = NULL; + DcmObject *obj = NULL; + DcmObject *result = NULL; + OFBool examSub = intoSub; + + if (stack.empty()) + { + stack.push(this); + examSub = OFTrue; + } + + obj = stack.top(); + if (obj->isLeaf() || !intoSub) + { + stack.pop(); + if (stack.card() > 0) + { + container = stack.top(); + result = container -> nextInContainer(obj); + } + } else if (examSub) + result = obj -> nextInContainer(NULL); + + if (result) + stack.push(result); + else if (intoSub) + l_error = nextUp(stack); + else + l_error = EC_SequEnd; + + return l_error; +} + + +// ******************************** + + +DcmItem *DcmSequenceOfItems::remove(const unsigned long num) +{ + errorFlag = EC_Normal; + DcmItem *item; + item = OFstatic_cast(DcmItem *, itemList->seek_to(num)); // read item from list + if (item != NULL) + { + itemList->remove(); + item->setParent(NULL); // forget about the parent + } else + errorFlag = EC_IllegalCall; + return item; +} + + +// ******************************** + + +DcmItem *DcmSequenceOfItems::remove(DcmItem *item) +{ + DcmItem *retItem = NULL; + errorFlag = EC_IllegalCall; + if (!itemList->empty() && (item != NULL)) + { + DcmObject *dO; + itemList->seek(ELP_first); + do { + dO = itemList->get(); + if (dO == item) + { + itemList->remove(); // removes element from list but does not delete it + item->setParent(NULL); // forget about the parent + errorFlag = EC_Normal; + break; + } + } while (itemList->seek(ELP_next)); + } + if (errorFlag == EC_IllegalCall) + retItem = NULL; + else + retItem = item; + return retItem; +} + + +// ******************************** + + +OFCondition DcmSequenceOfItems::clear() +{ + errorFlag = EC_Normal; + // remove all items from sequence and delete them from memory + itemList->deleteAllElements(); + setLengthField(0); + return errorFlag; +} + + +OFBool DcmSequenceOfItems::isEmpty(const OFBool /*normalize*/) +{ + return itemList->empty(); +} + + +// ******************************** + + +OFCondition DcmSequenceOfItems::verify(const OFBool autocorrect) +{ + errorFlag = EC_Normal; + if (!itemList->empty()) + { + DcmObject *dO; + itemList->seek(ELP_first); + do { + dO = itemList->get(); + if (dO->verify(autocorrect).bad()) + errorFlag = EC_CorruptedData; + } while (itemList->seek(ELP_next)); + } + if (autocorrect == OFTrue) + setLengthField(getLength()); + + return errorFlag; +} + + +/* + * precondition: itemList not empty. + * result: + * - element pointer on resultStack if return value is EC_Normal + * - unmodified resultStack if return value is EC_TagNotFound + * continue search: push pointer to sub-element onto resultStack and start sub-search + */ + +OFCondition DcmSequenceOfItems::searchSubFromHere(const DcmTagKey &tag, + DcmStack &resultStack, + const OFBool searchIntoSub) +{ + DcmObject *dO; + OFCondition l_error = EC_TagNotFound; + if (!itemList->empty()) + { + itemList->seek(ELP_first); + do { + dO = itemList->get(); + if (searchIntoSub) + { + resultStack.push(dO); + if (tag == dO->getTag()) + l_error = EC_Normal; + else + l_error = dO->search(tag, resultStack, ESM_fromStackTop, OFTrue); + if (l_error.bad()) + resultStack.pop(); + } else { + if (tag == dO->getTag()) + { + resultStack.push(dO); + l_error = EC_Normal; + } + } + } while (l_error.bad() && itemList->seek(ELP_next)); + } + return l_error; +} + + +// ******************************** + + +OFCondition DcmSequenceOfItems::search(const DcmTagKey &tag, + DcmStack &resultStack, + E_SearchMode mode, + OFBool searchIntoSub) +{ + DcmObject *dO = NULL; + OFCondition l_error = EC_TagNotFound; + if ((mode == ESM_afterStackTop) && (resultStack.top() == this)) + { + l_error = searchSubFromHere(tag, resultStack, searchIntoSub); + } + else if (!itemList->empty()) + { + if ((mode == ESM_fromHere) || resultStack.empty()) + { + resultStack.clear(); + l_error = searchSubFromHere(tag, resultStack, searchIntoSub); + } + else if (mode == ESM_fromStackTop) + { + dO = resultStack.top(); + if (dO == this) + l_error = searchSubFromHere(tag, resultStack, searchIntoSub); + else + { // continue directly in sub-tree + l_error = dO->search(tag, resultStack, mode, searchIntoSub); +// The next two lines destroy the stack, delete them +// if (l_error.bad()) +// resultStack.pop(); + } + } + else if ((mode == ESM_afterStackTop) && searchIntoSub) + { + // resultStack contains additional information: + // - restore state of the last search in each search routine + // - find position of dO in tree structure + // 1. search for own stack entry + // - in case of failure terminate search + // 2. take next upper entry dnO + // 3. set own list to position of dnO + // 4. restart search from dnO + + unsigned long i = resultStack.card(); + while ((i > 0) && ((dO = resultStack.elem(i-1)) != this)) + { + i--; + } + if ((dO != this) && (resultStack.card() > 0)) + { // highest level is never in resultStack + i = resultStack.card()+1; // now points to highest level +1 + dO = this; // match in highest level + } + if (dO == this) + { + if (i == 1) // resultStack.top() found + l_error = EC_TagNotFound; // don't mark as match, see above + else + { + E_SearchMode submode = mode; + OFBool searchNode = OFTrue; + DcmObject *dnO; + dnO = resultStack.elem(i-2); // node of next level + itemList->seek(ELP_first); + do { + dO = itemList->get(); + searchNode = searchNode ? (dO != dnO) : OFFalse; + if (!searchNode) + { // continue search + if (submode == ESM_fromStackTop) + resultStack.push(dO); // update stack + if ((submode == ESM_fromStackTop) && (tag == dO->getTag())) + l_error = EC_Normal; + else + l_error = dO->search(tag, resultStack, submode, OFTrue); + if (l_error.bad()) + resultStack.pop(); + else + break; + submode = ESM_fromStackTop; // normal search from here + } + } while (itemList->seek(ELP_next)); + } + } else // probably never reached + l_error = EC_IllegalCall; + } // (mode == ESM_afterStackTop + else + l_error = EC_IllegalCall; + } + return l_error; +} + + +// ******************************** + + +OFCondition DcmSequenceOfItems::loadAllDataIntoMemory() +{ + OFCondition l_error = EC_Normal; + if (!itemList->empty()) + { + itemList->seek(ELP_first); + do { + OFCondition err = EC_Normal; + DcmObject *dO = itemList->get(); + if ((err = dO->loadAllDataIntoMemory()).bad()) + l_error = err; + } while (itemList->seek(ELP_next)); + } + return l_error; +} + + +// ******************************** + + +OFBool DcmSequenceOfItems::isSignable() const +{ + // a sequence is signable if the tag and VR doesn't prevent signing + // and if none of the items contains a UN element + return DcmElement::isSignable() && !containsUnknownVR(); +} + + +OFBool DcmSequenceOfItems::containsUnknownVR() const +{ + if (!itemList->empty()) + { + itemList->seek(ELP_first); + do { + if (itemList->get()->containsUnknownVR()) + return OFTrue; + } while (itemList->seek(ELP_next)); + } + return OFFalse; +} + + +OFBool DcmSequenceOfItems::containsExtendedCharacters(const OFBool checkAllStrings) +{ + if (!itemList->empty()) + { + itemList->seek(ELP_first); + do { + if (itemList->get()->containsExtendedCharacters(checkAllStrings)) + return OFTrue; + } while (itemList->seek(ELP_next)); + } + return OFFalse; +} + + +OFBool DcmSequenceOfItems::isAffectedBySpecificCharacterSet() const +{ + if (!itemList->empty()) + { + itemList->seek(ELP_first); + do { + if (itemList->get()->isAffectedBySpecificCharacterSet()) + return OFTrue; + } while (itemList->seek(ELP_next)); + } + return OFFalse; +} + + +OFCondition DcmSequenceOfItems::convertCharacterSet(DcmSpecificCharacterSet &converter) +{ + OFCondition status = EC_Normal; + if (!itemList->empty()) + { + // iterate over all items in this sequence and convert the string elements + itemList->seek(ELP_first); + do { + status = itemList->get()->convertCharacterSet(converter); + } while (status.good() && itemList->seek(ELP_next)); + } + return status; +} + + +OFCondition DcmSequenceOfItems::getPartialValue(void * /* targetBuffer */, + const Uint32 /* offset */, + Uint32 /* numBytes */, + DcmFileCache * /* cache */, + E_ByteOrder /* byteOrder */) +{ + // cannot use getPartialValue() with class DcmSequenceOfItems or derived classes + return EC_IllegalCall; +} diff --git a/dcmdata/libsrc/dcspchrs.cc b/dcmdata/libsrc/dcspchrs.cc new file mode 100644 index 00000000..8520355d --- /dev/null +++ b/dcmdata/libsrc/dcspchrs.cc @@ -0,0 +1,789 @@ +/* + * + * Copyright (C) 2011-2015, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Joerg Riesmeier + * + * Purpose: Class for supporting the Specific Character Set attribute + * + */ + + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/dcmdata/dcspchrs.h" +#include "dcmtk/dcmdata/dcitem.h" +#include "dcmtk/dcmdata/dcbytstr.h" +#include "dcmtk/dcmdata/dcdeftag.h" +#include "dcmtk/ofstd/ofstream.h" +#include "dcmtk/ofstd/ofstd.h" + + +#define MAX_OUTPUT_STRING_LENGTH 60 + + +/*------------------* + * implementation * + *------------------*/ + +DcmSpecificCharacterSet::DcmSpecificCharacterSet() + : SourceCharacterSet(), + DestinationCharacterSet(), + DestinationEncoding(), + EncodingConverter(), + ConversionDescriptors() +{ +} + + +DcmSpecificCharacterSet::~DcmSpecificCharacterSet() +{ + // this frees all previously allocated resources + closeConversionDescriptors(); +} + + +void DcmSpecificCharacterSet::clear() +{ + // this also clears all other member variables + closeConversionDescriptors(); +} + + +const OFString &DcmSpecificCharacterSet::getSourceCharacterSet() const +{ + return SourceCharacterSet; +} + + +const OFString &DcmSpecificCharacterSet::getDestinationCharacterSet() const +{ + return DestinationCharacterSet; +} + + +const OFString &DcmSpecificCharacterSet::getDestinationEncoding() const +{ + return DestinationEncoding; +} + + +OFBool DcmSpecificCharacterSet::getTransliterationMode() const +{ + return EncodingConverter.getTransliterationMode(); +} + + +OFBool DcmSpecificCharacterSet::getDiscardIllegalSequenceMode() const +{ + return EncodingConverter.getDiscardIllegalSequenceMode(); +} + + +OFCondition DcmSpecificCharacterSet::selectCharacterSet(const OFString &fromCharset, + const OFString &toCharset, + const OFBool transliterate, + const OFBool discardIllegal) +{ + // first, make sure that all conversion descriptors are closed + closeConversionDescriptors(); + // determine the destination encoding (and check whether it is supported at all) + OFCondition status = determineDestinationEncoding(toCharset); + if (status.good()) + { + // normalize the given string (original VR is "CS" with VM "1-n") + SourceCharacterSet = fromCharset; + normalizeString(SourceCharacterSet, MULTIPART, DELETE_LEADING, DELETE_TRAILING); + // check whether it is multi-valued + const unsigned long sourceVM = DcmElement::determineVM(SourceCharacterSet.c_str(), SourceCharacterSet.length()); + if (sourceVM == 0) + { + // no character set specified, use ASCII + status = EncodingConverter.selectEncoding("ASCII", DestinationEncoding); + // output some useful debug information + if (status.good()) + { + DCMDATA_DEBUG("DcmSpecificCharacterSet: Selected character set '' (ASCII) " + << "for the conversion to " << DestinationEncoding); + } + } + else if (sourceVM == 1) + { + // a single character set specified (no code extensions) + status = selectCharacterSetWithoutCodeExtensions(); + } else { + // multiple character sets specified (code extensions used) + status = selectCharacterSetWithCodeExtensions(sourceVM); + } + // enable or disable the transliteration mode + if (status.good()) + { + status = EncodingConverter.setTransliterationMode(transliterate); + if (status.good()) + { + // output some useful debug information + if (transliterate) + { + DCMDATA_DEBUG("DcmSpecificCharacterSet: Enabled transliteration mode, " + << "i.e. the approximation of similar looking characters will be used"); + } else { + DCMDATA_DEBUG("DcmSpecificCharacterSet: Disabled transliteration mode, " + << "i.e. the approximation of similar looking characters will not be used"); + } + } + } + // enable or disable the discard illegal sequence mode + if (status.good()) + { + status = EncodingConverter.setDiscardIllegalSequenceMode(discardIllegal); + if (status.good()) + { + // output some useful debug information + if (discardIllegal) + { + DCMDATA_DEBUG("DcmSpecificCharacterSet: Enabled 'discard illegal sequence' mode, " + << "i.e. non-representable characters will be discarded"); + } else { + DCMDATA_DEBUG("DcmSpecificCharacterSet: Disabled 'discard illegal sequence' mode, " + << "i.e. non-representable characters will not be discarded"); + } + } + } + } + return status; +} + + +OFCondition DcmSpecificCharacterSet::selectCharacterSet(DcmItem &dataset, + const OFString &toCharset, + const OFBool transliterate, + const OFBool discardIllegal) +{ + OFString fromCharset; + // check whether Specific Character Set (0008,0005) is present in the given item/dataset + dataset.findAndGetOFStringArray(DCM_SpecificCharacterSet, fromCharset, OFFalse /*searchIntoSub*/); + // if missing or empty, the default character set (ASCII) will be used + return selectCharacterSet(fromCharset, toCharset, transliterate, discardIllegal); +} + + +OFCondition DcmSpecificCharacterSet::determineDestinationEncoding(const OFString &toCharset) +{ + OFCondition status = EC_Normal; + // normalize the given string (original VR is "CS" with VM "1-n", but we only support VM "1") + DestinationCharacterSet = toCharset; + normalizeString(DestinationCharacterSet, !MULTIPART, DELETE_LEADING, DELETE_TRAILING); + // there should only be a single character set specified (no code extensions) + if (DestinationCharacterSet.empty()) // ASCII (no value) + DestinationEncoding = "ASCII"; + else if (DestinationCharacterSet == "ISO_IR 6") // ASCII + { + DCMDATA_WARN("DcmSpecificCharacterSet: 'ISO_IR 6' is not a defined term in DICOM, " + << "will be treated as an empty value (ASCII)"); + DestinationCharacterSet.clear(); + DestinationEncoding = "ASCII"; + } + else if (DestinationCharacterSet == "ISO_IR 100") // Latin alphabet No. 1 + DestinationEncoding = "ISO-8859-1"; + else if (DestinationCharacterSet == "ISO_IR 101") // Latin alphabet No. 2 + DestinationEncoding = "ISO-8859-2"; + else if (DestinationCharacterSet == "ISO_IR 109") // Latin alphabet No. 3 + DestinationEncoding = "ISO-8859-3"; + else if (DestinationCharacterSet == "ISO_IR 110") // Latin alphabet No. 4 + DestinationEncoding = "ISO-8859-4"; + else if (DestinationCharacterSet == "ISO_IR 144") // Cyrillic + DestinationEncoding = "ISO-8859-5"; + else if (DestinationCharacterSet == "ISO_IR 127") // Arabic + DestinationEncoding = "ISO-8859-6"; + else if (DestinationCharacterSet == "ISO_IR 126") // Greek + DestinationEncoding = "ISO-8859-7"; + else if (DestinationCharacterSet == "ISO_IR 138") // Hebrew + DestinationEncoding = "ISO-8859-8"; + else if (DestinationCharacterSet == "ISO_IR 148") // Latin alphabet No. 5 + DestinationEncoding = "ISO-8859-9"; + else if (DestinationCharacterSet == "ISO_IR 13") // Japanese + DestinationEncoding = "JIS_X0201"; // - "ISO-IR-13" is not supported by libiconv + else if (DestinationCharacterSet == "ISO_IR 166") // Thai + DestinationEncoding = "ISO-IR-166"; + else if (DestinationCharacterSet == "ISO_IR 192") // Unicode in UTF-8 (multi-byte) + DestinationEncoding = "UTF-8"; + else if (DestinationCharacterSet == "GB18030") // Chinese (multi-byte) + DestinationEncoding = "GB18030"; + else if (DestinationCharacterSet == "GBK") // Chinese (multi-byte, subset of GB18030) + DestinationEncoding = "GBK"; + else { + DestinationEncoding.clear(); + // create an appropriate error code + OFOStringStream stream; + stream << "Cannot select destination character set: SpecificCharacterSet (0008,0005) value '" + << DestinationCharacterSet << "' not supported" << OFStringStream_ends; + OFSTRINGSTREAM_GETOFSTRING(stream, message) + status = makeOFCondition(OFM_dcmdata, EC_CODE_CannotSelectCharacterSet, OF_error, message.c_str()); + } + return status; +} + + +OFCondition DcmSpecificCharacterSet::selectCharacterSetWithoutCodeExtensions() +{ + OFCondition status = EC_Normal; + // a single character set specified (no code extensions) + OFString fromEncoding; + if (SourceCharacterSet == "ISO_IR 6") // ASCII + { + DCMDATA_WARN("DcmSpecificCharacterSet: 'ISO_IR 6' is not a defined term in DICOM, " + << "will be treated as an empty value (ASCII)"); + SourceCharacterSet.clear(); + fromEncoding = "ASCII"; + } + else if (SourceCharacterSet == "ISO_IR 100") // Latin alphabet No. 1 + fromEncoding = "ISO-8859-1"; + else if (SourceCharacterSet == "ISO_IR 101") // Latin alphabet No. 2 + fromEncoding = "ISO-8859-2"; + else if (SourceCharacterSet == "ISO_IR 109") // Latin alphabet No. 3 + fromEncoding = "ISO-8859-3"; + else if (SourceCharacterSet == "ISO_IR 110") // Latin alphabet No. 4 + fromEncoding = "ISO-8859-4"; + else if (SourceCharacterSet == "ISO_IR 144") // Cyrillic + fromEncoding = "ISO-8859-5"; + else if (SourceCharacterSet == "ISO_IR 127") // Arabic + fromEncoding = "ISO-8859-6"; + else if (SourceCharacterSet == "ISO_IR 126") // Greek + fromEncoding = "ISO-8859-7"; + else if (SourceCharacterSet == "ISO_IR 138") // Hebrew + fromEncoding = "ISO-8859-8"; + else if (SourceCharacterSet == "ISO_IR 148") // Latin alphabet No. 5 + fromEncoding = "ISO-8859-9"; + else if (SourceCharacterSet == "ISO_IR 13") // Japanese + fromEncoding = "JIS_X0201"; // - "ISO-IR-13" is not supported by libiconv + else if (SourceCharacterSet == "ISO_IR 166") // Thai + fromEncoding = "ISO-IR-166"; + else if (SourceCharacterSet == "ISO_IR 192") // Unicode in UTF-8 (multi-byte) + fromEncoding = "UTF-8"; + else if (SourceCharacterSet == "GB18030") // Chinese (multi-byte) + fromEncoding = "GB18030"; + else if (SourceCharacterSet == "GBK") // Chinese (multi-byte, subset of GB18030) + fromEncoding = "GBK"; + else { + // create an appropriate error code + OFOStringStream stream; + stream << "Cannot select source character set: SpecificCharacterSet (0008,0005) value '" + << SourceCharacterSet << "' not supported" << OFStringStream_ends; + OFSTRINGSTREAM_GETOFSTRING(stream, message) + status = makeOFCondition(OFM_dcmdata, EC_CODE_CannotSelectCharacterSet, OF_error, message.c_str()); + } + // check whether an appropriate character encoding has been found + if (!fromEncoding.empty()) + { + status = EncodingConverter.selectEncoding(fromEncoding, DestinationEncoding); + // output some useful debug information + if (status.good()) + { + DCMDATA_DEBUG("DcmSpecificCharacterSet: Selected character set '" << SourceCharacterSet + << "' (" << fromEncoding << ") for the conversion to " << DestinationEncoding); + } + } + return status; +} + + +OFCondition DcmSpecificCharacterSet::selectCharacterSetWithCodeExtensions(const unsigned long sourceVM) +{ + // first, check whether multiple character sets are specified (i.e. code extensions used) + if (sourceVM <= 1) + return EC_IllegalCall; + // then proceed with the real work + OFCondition status = EC_Normal; + size_t pos = 0; + OFBool needsASCII = OFFalse; + OFBool notFirstValue = OFFalse; + OFString definedTerm; + OFCharacterEncoding::T_Descriptor descriptor; + unsigned long i = 0; + while ((i < sourceVM) && status.good()) + { + // extract single value from string (separated by a backslash) + pos = DcmElement::getValueFromString(SourceCharacterSet.c_str(), pos, SourceCharacterSet.length(), definedTerm); + if (definedTerm.empty() && (i == 0)) // assuming ASCII (according to DICOM PS 3.5) + definedTerm = "ISO 2022 IR 6"; + // determine character encoding from DICOM defined term + OFString encodingName; + if (definedTerm == "ISO 2022 IR 6") // ASCII + encodingName = "ASCII"; + else if (definedTerm == "ISO 2022 IR 100") // Latin alphabet No. 1 + { + encodingName = "ISO-8859-1"; + needsASCII = OFTrue; + } + else if (definedTerm == "ISO 2022 IR 101") // Latin alphabet No. 2 + { + encodingName = "ISO-8859-2"; + needsASCII = OFTrue; + } + else if (definedTerm == "ISO 2022 IR 109") // Latin alphabet No. 3 + { + encodingName = "ISO-8859-3"; + needsASCII = OFTrue; + } + else if (definedTerm == "ISO 2022 IR 110") // Latin alphabet No. 4 + { + encodingName = "ISO-8859-4"; + needsASCII = OFTrue; + } + else if (definedTerm == "ISO 2022 IR 144") // Cyrillic + { + encodingName = "ISO-8859-5"; + needsASCII = OFTrue; + } + else if (definedTerm == "ISO 2022 IR 127") // Arabic + { + encodingName = "ISO-8859-6"; + needsASCII = OFTrue; + } + else if (definedTerm == "ISO 2022 IR 126") // Greek + { + encodingName = "ISO-8859-7"; + needsASCII = OFTrue; + } + else if (definedTerm == "ISO 2022 IR 138") // Hebrew + { + encodingName = "ISO-8859-8"; + needsASCII = OFTrue; + } + else if (definedTerm == "ISO 2022 IR 148") // Latin alphabet No. 5 + { + encodingName = "ISO-8859-9"; + needsASCII = OFTrue; + } + else if (definedTerm == "ISO 2022 IR 13") // Japanese + { + encodingName = "JIS_X0201"; // - "ISO-IR-13" is not supported by libiconv + } + else if (definedTerm == "ISO 2022 IR 166") // Thai + { + encodingName = "ISO-IR-166"; + needsASCII = OFTrue; + } + else if (definedTerm == "ISO 2022 IR 87") // Japanese (multi-byte) + { + encodingName = "ISO-IR-87"; + notFirstValue = OFTrue; + } + else if (definedTerm == "ISO 2022 IR 159") // Japanese (multi-byte) + { + encodingName = "ISO-IR-159"; + notFirstValue = OFTrue; + } + else if (definedTerm == "ISO 2022 IR 149") // Korean (multi-byte) + { + encodingName = "EUC-KR"; // - is this mapping really correct? + notFirstValue = OFTrue; // "ISO-IR-149" does not work with the sample from DICOM PS 3.5 + } + else if (definedTerm == "ISO 2022 IR 58") // Simplified Chinese (multi-byte) + { + encodingName = "GB2312"; // - should work, but not tested yet! + notFirstValue = OFTrue; + } + else { + // create an appropriate error code + OFOStringStream stream; + stream << "Cannot select source character set: SpecificCharacterSet (0008,0005) value " << (i + 1) + << " of " << sourceVM << " '" << definedTerm << "' not supported" << OFStringStream_ends; + OFSTRINGSTREAM_GETOFSTRING(stream, message) + status = makeOFCondition(OFM_dcmdata, EC_CODE_CannotSelectCharacterSet, OF_error, message.c_str()); + } + // check whether character set is allowed as the default (first value) + if ((i == 0) && notFirstValue) + { + OFOStringStream stream; + stream << "Cannot select source character set: '" << definedTerm << "' is not a allowed " + << "as the first value in SpecificCharacterSet (0008,0005)" << OFStringStream_ends; + OFSTRINGSTREAM_GETOFSTRING(stream, message) + status = makeOFCondition(OFM_dcmdata, EC_CODE_CannotSelectCharacterSet, OF_error, message.c_str()); + } + // add descriptor to the map using the defined term as a key + if (status.good() && !encodingName.empty()) + { + // but first check whether this encoding has already been added before + if (ConversionDescriptors.find(definedTerm) == ConversionDescriptors.end()) + { + status = EncodingConverter.openDescriptor(descriptor, encodingName, DestinationEncoding); + if (status.good()) + { + ConversionDescriptors[definedTerm] = descriptor; + // output some useful debug information + DCMDATA_DEBUG("DcmSpecificCharacterSet: Added character set '" << definedTerm + << "' (" << encodingName << ") for the conversion to " << DestinationEncoding); + // also remember the default descriptor, which refers to the first character set + if (i == 0) + { + EncodingConverter.ConversionDescriptor = descriptor; + DCMDATA_TRACE("DcmSpecificCharacterSet: Also selected this character set " + << "(i.e. '" << definedTerm << "') as the default one"); + } + } + } else { + DCMDATA_WARN("DcmSpecificCharacterSet: '" << definedTerm << "' is defined more than once " + << "in SpecificCharacterSet (0008,0005), ignoring the duplicate definition"); + } + } + ++i; + } + if (status.good()) + { + // add ASCII to the map if needed but not already there + if (needsASCII && (ConversionDescriptors.find("ISO 2022 IR 6") == ConversionDescriptors.end())) + { + status = EncodingConverter.openDescriptor(descriptor, "ASCII", DestinationEncoding); + if (status.good()) + { + ConversionDescriptors["ISO 2022 IR 6"] = descriptor; + // output some useful debug information + DCMDATA_DEBUG("DcmSpecificCharacterSet: Added character set 'ISO 2022 IR 6' (ASCII) " + << "for the conversion to " << DestinationEncoding + << " (because it is needed for one or more of the previously added character sets)"); + } + } + } + return status; +} + + +OFCondition DcmSpecificCharacterSet::convertString(const OFString &fromString, + OFString &toString, + const OFString &delimiters) +{ + // call the real method converting the given string + return convertString(fromString.c_str(), fromString.length(), toString, delimiters); +} + + +OFCondition DcmSpecificCharacterSet::convertString(const char *fromString, + const size_t fromLength, + OFString &toString, + const OFString &delimiters) +{ + OFCondition status = EC_Normal; + // check whether there are any code extensions at all + if ((ConversionDescriptors.size() == 0) || !checkForEscapeCharacter(fromString, fromLength)) + { + DCMDATA_DEBUG("DcmSpecificCharacterSet: Converting '" + << convertToLengthLimitedOctalString(fromString, fromLength) << "'"); + // no code extensions according to ISO 2022 used - this is the simple case + status = EncodingConverter.convertString(fromString, fromLength, toString, OFTrue /*clearMode*/); + } else { + if (delimiters.empty()) + { + DCMDATA_DEBUG("DcmSpecificCharacterSet: Converting '" + << convertToLengthLimitedOctalString(fromString, fromLength) + << "' (with code extensions)"); + } else { + DCMDATA_DEBUG("DcmSpecificCharacterSet: Converting '" + << convertToLengthLimitedOctalString(fromString, fromLength) + << "' (with code extensions and delimiters '" << delimiters << "')"); + } + // code extensions according to ISO 2022 used, so we need to check for + // particular escape sequences in order to switch between character sets + toString.clear(); + size_t pos = 0; + // check whether '=' is a delimiter, as it is used in PN values + OFBool isFirstGroup = (delimiters.find('=') != OFString_npos); + // by default, we expect that '^' and '=' (i.e. their ASCII codes) are valid PN delimiters + // (this implies that the default character set is not "ISO 2022 IR 87" or "ISO 2022 IR 159") + OFBool checkPNDelimiters = OFTrue; + const char *firstChar = fromString; + const char *currentChar = fromString; + // initially, use the default descriptor + OFCharacterEncoding::T_Descriptor descriptor = EncodingConverter.ConversionDescriptor; + DCMDATA_TRACE(" Starting with the default character set"); + // iterate over all characters of the string (as long as there is no error) + while ((pos < fromLength) && status.good()) + { + const char c0 = *currentChar++; + // check for characters ESC, HT, LF, FF, CR or any other specified delimiter + // (the PN delimiters '^' and '=' require the default character set or ASCII) + const OFBool isEscape = (c0 == '\033'); + const OFBool isDelimiter = (c0 == '\011') || (c0 == '\012') || (c0 == '\014') || (c0 == '\015') || + ((delimiters.find(c0) != OFString_npos) && (((c0 != '^') && (c0 != '=')) || checkPNDelimiters)); + if (isEscape || isDelimiter) + { + // convert the sub-string (before the delimiter) with the current character set + const size_t convertLength = currentChar - firstChar - 1; + if (convertLength > 0) + { + // output some debug information + DCMDATA_TRACE(" Converting sub-string '" + << convertToLengthLimitedOctalString(firstChar, convertLength) << "'"); + status = EncodingConverter.convertString(descriptor, firstChar, convertLength, toString, OFFalse /*clearMode*/); + if (status.bad()) + DCMDATA_TRACE(" -> ERROR: " << status.text()); + } + // check whether this was the first component group of a PN value + if (isDelimiter && (c0 == '=')) + isFirstGroup = OFFalse; + } + // the ESC character is used to explicitly switch between character sets + if (isEscape) + { + // report a warning as this is a violation of DICOM PS 3.5 Section 6.2.1 + if (isFirstGroup) + { + DCMDATA_WARN("DcmSpecificCharacterSet: Escape sequences shall not be used " + << "in the first component group of a Person Name (PN), using them anyway"); + } + // we need at least two more characters to determine the new character set + size_t escLength = 2; + if (pos + escLength < fromLength) + { + OFString key; + const char c1 = *currentChar++; + const char c2 = *currentChar++; + char c3 = '\0'; + if ((c1 == 0x28) && (c2 == 0x42)) // ASCII + key = "ISO 2022 IR 6"; + else if ((c1 == 0x2d) && (c2 == 0x41)) // Latin alphabet No. 1 + key = "ISO 2022 IR 100"; + else if ((c1 == 0x2d) && (c2 == 0x42)) // Latin alphabet No. 2 + key = "ISO 2022 IR 101"; + else if ((c1 == 0x2d) && (c2 == 0x43)) // Latin alphabet No. 3 + key = "ISO 2022 IR 109"; + else if ((c1 == 0x2d) && (c2 == 0x44)) // Latin alphabet No. 4 + key = "ISO 2022 IR 110"; + else if ((c1 == 0x2d) && (c2 == 0x4c)) // Cyrillic + key = "ISO 2022 IR 144"; + else if ((c1 == 0x2d) && (c2 == 0x47)) // Arabic + key = "ISO 2022 IR 127"; + else if ((c1 == 0x2d) && (c2 == 0x46)) // Greek + key = "ISO 2022 IR 126"; + else if ((c1 == 0x2d) && (c2 == 0x48)) // Hebrew + key = "ISO 2022 IR 138"; + else if ((c1 == 0x2d) && (c2 == 0x4d)) // Latin alphabet No. 5 + key = "ISO 2022 IR 148"; + else if ((c1 == 0x29) && (c2 == 0x49)) // Japanese + key = "ISO 2022 IR 13"; + else if ((c1 == 0x28) && (c2 == 0x4a)) // Japanese - is this really correct? + key = "ISO 2022 IR 13"; + else if ((c1 == 0x2d) && (c2 == 0x54)) // Thai + key = "ISO 2022 IR 166"; + else if ((c1 == 0x24) && (c2 == 0x42)) // Japanese (multi-byte) + key = "ISO 2022 IR 87"; + else if ((c1 == 0x24) && (c2 == 0x28)) // Japanese (multi-byte) + { + escLength = 3; + // do we still have another character in the string? + if (pos + escLength < fromLength) + { + c3 = *currentChar++; + if (c3 == 0x44) + key = "ISO 2022 IR 159"; + } + } + else if ((c1 == 0x24) && (c2 == 0x29)) // might be Korean or Chinese + { + escLength = 3; + // do we still have another character in the string? + if (pos + escLength < fromLength) + { + c3 = *currentChar++; + if (c3 == 0x43) // Korean (multi-byte) + key = "ISO 2022 IR 149"; + else if (c3 == 0x41) // Simplified Chinese (multi-byte) + key = "ISO 2022 IR 58"; + } + } + // check whether a valid escape sequence has been found + if (key.empty()) + { + OFOStringStream stream; + stream << "Cannot convert character set: Illegal escape sequence 'ESC " + << STD_NAMESPACE dec << STD_NAMESPACE setfill('0') + << STD_NAMESPACE setw(2) << OFstatic_cast(int, c1 >> 4) << "/" + << STD_NAMESPACE setw(2) << OFstatic_cast(int, c1 & 0x0f) << " " + << STD_NAMESPACE setw(2) << OFstatic_cast(int, c2 >> 4) << "/" + << STD_NAMESPACE setw(2) << OFstatic_cast(int, c2 & 0x0f); + if (escLength == 3) + { + stream << " " << STD_NAMESPACE setw(2) << OFstatic_cast(int, c3 >> 4) << "/" + << STD_NAMESPACE setw(2) << OFstatic_cast(int, c3 & 0x0f); + } + stream << "' found" << OFStringStream_ends; + OFSTRINGSTREAM_GETOFSTRING(stream, message) + status = makeOFCondition(OFM_dcmdata, EC_CODE_CannotConvertCharacterSet, OF_error, message.c_str()); + } + if (status.good()) + { + DCMDATA_TRACE(" Switching to character set '" << key << "'"); + T_DescriptorMap::const_iterator iter = ConversionDescriptors.find(key); + // check whether the descriptor was found in the map, i.e. properly declared in (0008,0005) + if (iter != ConversionDescriptors.end()) + { + descriptor = iter->second; + // special case: these Japanese character sets replace the ASCII part (G0 code area), + // so according to DICOM PS 3.5 Section 6.2.1 an explicit switch to the default is required + checkPNDelimiters = (key != "ISO 2022 IR 87") && (key != "ISO 2022 IR 159"); + } else { + OFOStringStream stream; + stream << "Cannot convert character set: Escape sequence refers to character set '" << key << "' that " + "was not declared in SpecificCharacterSet (0008,0005)" << OFStringStream_ends; + OFSTRINGSTREAM_GETOFSTRING(stream, message) + status = makeOFCondition(OFM_dcmdata, EC_CODE_CannotConvertCharacterSet, OF_error, message.c_str()); + } + } + pos += escLength; + } + // check whether the escape sequence was complete + if (status.good() && (pos >= fromLength)) + { + OFOStringStream stream; + stream << "Cannot convert character set: Incomplete escape sequence (" << (escLength + 1) + << " bytes expected) at the end of the string to be converted" << OFStringStream_ends; + OFSTRINGSTREAM_GETOFSTRING(stream, message) + status = makeOFCondition(OFM_dcmdata, EC_CODE_CannotConvertCharacterSet, OF_error, message.c_str()); + } + // do not copy the escape sequence to the output + firstChar = currentChar; + } + // the LF, FF, CR character or other delimiters (depending on the VR) also cause a switch + else if (isDelimiter) + { + // output some debug information + DCMDATA_TRACE(" Appending delimiter '" + << convertToLengthLimitedOctalString(currentChar - 1 /* identical to c0 */, 1) + << "' to the output"); + // don't forget to append the delimiter + toString += c0; + // use the default descriptor again (see DICOM PS 3.5) + if (descriptor != EncodingConverter.ConversionDescriptor) + { + DCMDATA_TRACE(" Switching back to the default character set (because a delimiter was found)"); + descriptor = EncodingConverter.ConversionDescriptor; + checkPNDelimiters = OFTrue; + } + // start new sub-string after delimiter + firstChar = currentChar; + } + ++pos; + } + if (status.good()) + { + // convert any remaining characters from the input string + const size_t convertLength = currentChar - firstChar; + if (convertLength > 0) + { + // output some debug information + DCMDATA_TRACE(" Converting remaining sub-string '" + << convertToLengthLimitedOctalString(firstChar, convertLength) << "'"); + status = EncodingConverter.convertString(descriptor, firstChar, convertLength, toString, OFFalse /*clearMode*/); + if (status.bad()) + DCMDATA_TRACE(" -> ERROR: " << status.text()); + } + } + } + if (status.good()) + { + // finally, output some debug information + if (DestinationEncoding == "UTF-8") + { + // output code points only in case of UTF-8 output + DCMDATA_TRACE("Converted result in " << DestinationEncoding << " is '" + << convertToLengthLimitedOctalString(toString.c_str(), toString.length()) << "' (" + << countCharactersInUTF8String(toString) << " code points)"); + } else { + DCMDATA_TRACE("Converted result in " << DestinationEncoding << " is '" + << convertToLengthLimitedOctalString(toString.c_str(), toString.length()) << "'"); + } + } + return status; +} + + +OFBool DcmSpecificCharacterSet::isConversionLibraryAvailable() +{ + // just call the appropriate function from the underlying class + return OFCharacterEncoding::isLibraryAvailable(); +} + + +size_t DcmSpecificCharacterSet::countCharactersInUTF8String(const OFString &utf8String) +{ + // just call the appropriate function from the underlying class + return OFCharacterEncoding::countCharactersInUTF8String(utf8String); +} + + +void DcmSpecificCharacterSet::closeConversionDescriptors() +{ + T_DescriptorMap::iterator iter = ConversionDescriptors.begin(); + T_DescriptorMap::const_iterator last = ConversionDescriptors.end(); + // iterate over the map of conversion descriptors + while (iter != last) + { + // make sure that the default descriptor is not closed multiple times + if (iter->second != EncodingConverter.ConversionDescriptor) + { + // and close the descriptor + if (EncodingConverter.closeDescriptor(iter->second).bad()) + { + DCMDATA_ERROR("DcmSpecificCharacterSet: Cannot close previously allocated " + << "conversion descriptor for '" << iter->first << "'"); + } + } + ++iter; + } + // clear the map + ConversionDescriptors.clear(); + // and close the default descriptor + if (EncodingConverter.closeDescriptor(EncodingConverter.ConversionDescriptor).bad()) + DCMDATA_ERROR("DcmSpecificCharacterSet: Cannot close currently selected conversion descriptor"); + // also clear the various character set and encoding name variables + SourceCharacterSet.clear(); + DestinationCharacterSet.clear(); + DestinationEncoding.clear(); +} + + +OFBool DcmSpecificCharacterSet::checkForEscapeCharacter(const char *strValue, + const size_t strLength) const +{ + OFBool result = OFFalse; + // iterate over the string of characters + for (size_t pos = 0; pos < strLength; ++pos) + { + // and search for the first ESC character + if (*strValue++ == '\033') + { + // then return with "true" + result = OFTrue; + break; + } + } + return result; +} + + +OFString DcmSpecificCharacterSet::convertToLengthLimitedOctalString(const char *strValue, + const size_t strLength) const +{ + OFString octalString; + // convert given string to octal representation, allow one character more than the maximum ... + OFStandard::convertToOctalString(OFString(strValue, strLength), octalString, MAX_OUTPUT_STRING_LENGTH + 1); + // ... in order to determine whether trailing dots should be added, i.e. the string was cropped + if (octalString.length() > MAX_OUTPUT_STRING_LENGTH) + { + octalString.erase(MAX_OUTPUT_STRING_LENGTH); + octalString.append("..."); + } + // return string by-value (in order to avoid another parameter) + return octalString; +} diff --git a/dcmdata/libsrc/dcstack.cc b/dcmdata/libsrc/dcstack.cc new file mode 100644 index 00000000..eba49a2f --- /dev/null +++ b/dcmdata/libsrc/dcstack.cc @@ -0,0 +1,263 @@ +/* + * + * Copyright (C) 1994-2010, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Gerd Ehlers + * + * Purpose: stack class + * + */ + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#define INCLUDE_CSTDLIB +#include "dcmtk/ofstd/ofstdinc.h" +#include "dcmtk/ofstd/ofcast.h" +#include "dcmtk/ofstd/ofstream.h" +#include "dcmtk/dcmdata/dcstack.h" + + +// ************************************************ +// *** DcmStackNode() ***************************** +// ************************************************ + + +DcmStackNode::DcmStackNode( DcmObject *obj ) + : link(NULL), + objNodeValue(obj) +{ +} + + +// ******************************** + + +DcmStackNode::~DcmStackNode() +{ +} + + +// ******************************** + + +DcmObject* DcmStackNode::value() const +{ + return objNodeValue; +} + + + +// ************************************************ +// *** DcmStack() ********************************* +// ************************************************ + + +DcmStack::DcmStack() + : topNode_(NULL), + cardinality_(0) +{ +} + + +// ************************************************ + + +DcmStack::DcmStack( const DcmStack & oldStack) + : topNode_(NULL), + cardinality_(oldStack.cardinality_) +{ + if (cardinality_) + { + topNode_ = new DcmStackNode(oldStack.topNode_->objNodeValue); + DcmStackNode * oldPtr = oldStack.topNode_->link; + DcmStackNode * newPtr = topNode_; + while (oldPtr) + { + newPtr->link = new DcmStackNode(oldPtr->objNodeValue); + oldPtr = oldPtr->link; + newPtr = newPtr->link; + } + } +} + + +// ******************************** + + +DcmStack::~DcmStack() +{ + clear(); +} + + +// ******************************** + + +void DcmStack::clear() +{ + DcmStackNode *node; + while (topNode_ != NULL) + { + node = topNode_; + topNode_ = topNode_->link; + delete node; + } + cardinality_ = 0; +} + + +// ******************************** + + +DcmObject* DcmStack::push( DcmObject *obj ) +{ + if ( obj != NULL ) + { + DcmStackNode *node = new DcmStackNode( obj ); + node->link = topNode_; + topNode_ = node; + cardinality_++; + } + return obj; +} + + +// ******************************** + + +DcmObject* DcmStack::pop() +{ + DcmObject *obj; + DcmStackNode *node; + if ( topNode_ != NULL ) + { + obj = topNode_->value(); + node = topNode_; + topNode_ = topNode_->link; + delete node; + cardinality_--; + } + else + obj = NULL; + return obj; +} + + +// ******************************** + + +DcmObject* DcmStack::elem(const unsigned long number) const +{ + unsigned long num = number; + DcmObject *obj; + DcmStackNode *node = topNode_; + while ( num-- > 0 && node != NULL ) + node = node->link; + + if ( node != NULL ) + obj = node->value(); + else + obj = NULL; + return obj; +} + + +// ******************************** + + +DcmObject* DcmStack::top() const +{ + DcmObject *obj; + if ( topNode_ != NULL ) + obj = topNode_->value(); + else + obj = NULL; + return obj; +} + + +// ******************************** + + +unsigned long DcmStack::card() const +{ + return cardinality_; +} + + +// ******************************** + + +OFBool DcmStack::empty() const +{ + return OFstatic_cast(OFBool, topNode_ == NULL ); +} + + +DcmStack& DcmStack::operator=(const DcmStack& arg) +{ + if (this != &arg) + { + clear(); + cardinality_ = arg.cardinality_; + if (cardinality_) + { + topNode_ = new DcmStackNode(arg.topNode_->objNodeValue); + DcmStackNode * oldPtr = arg.topNode_->link; + DcmStackNode * newPtr = topNode_; + while (oldPtr) + { + newPtr->link = new DcmStackNode(oldPtr->objNodeValue); + oldPtr = oldPtr->link; + newPtr = newPtr->link; + } + } + } + return *this; +} + + +OFBool DcmStack::operator<(const DcmStack& arg) const +{ + if (cardinality_ < arg.cardinality_) return OFTrue; + if (cardinality_ > arg.cardinality_) return OFFalse; + + // cardinality_ is equal. Now walk through stack and do pointer arithmetics + DcmStackNode * thisPtr = topNode_; + DcmStackNode * argPtr = arg.topNode_; + while (thisPtr) + { + if (thisPtr->objNodeValue < argPtr->objNodeValue) return OFTrue; + if (thisPtr->objNodeValue > argPtr->objNodeValue) return OFFalse; + thisPtr = thisPtr->link; + argPtr = argPtr->link; + } + return OFFalse; // stacks are equal +} + + +OFBool DcmStack::operator==(const DcmStack& arg) const +{ + if (cardinality_ != arg.cardinality_) return OFFalse; + + DcmStackNode * thisPtr = topNode_; + DcmStackNode * argPtr = arg.topNode_; + while (thisPtr) + { + if (thisPtr->objNodeValue != argPtr->objNodeValue) return OFFalse; + thisPtr = thisPtr->link; + argPtr = argPtr->link; + } + return OFTrue; +} diff --git a/dcmdata/libsrc/dcswap.cc b/dcmdata/libsrc/dcswap.cc new file mode 100644 index 00000000..0116a92c --- /dev/null +++ b/dcmdata/libsrc/dcswap.cc @@ -0,0 +1,134 @@ +/* + * + * Copyright (C) 1994-2012, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Andreas Barth + * + * Purpose: byte order functions + * + */ + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ +#include "dcmtk/dcmdata/dcswap.h" + +OFCondition swapIfNecessary(const E_ByteOrder newByteOrder, + const E_ByteOrder oldByteOrder, + void * value, const Uint32 byteLength, + const size_t valWidth) + /* + * This function swaps byteLength bytes in value if newByteOrder and oldByteOrder + * differ from each other. In case bytes have to be swapped, these bytes are seperated + * in valWidth elements which will be swapped seperately. + * + * Parameters: + * newByteOrder - [in] The new byte ordering (little or big endian). + * oldByteOrder - [in] The current old byte ordering (little or big endian). + * value - [in] Array that contains the actual bytes which might have to be swapped. + * byteLength - [in] Length of the above array. + * valWidth - [in] Specifies how many bytes shall be treated together as one element. + */ +{ + /* if the two byte orderings are unknown this is an illegal call */ + if (oldByteOrder != EBO_unknown && newByteOrder != EBO_unknown) + { + /* and if they differ from each other and valWidth is not 1 */ + if (oldByteOrder != newByteOrder && valWidth != 1) + { + /* in case the array length equals valWidth and only 2 or 4 bytes have to be swapped */ + /* we can swiftly swap these bytes by calling the corresponding functions. If this is */ + /* not the case we have to call a more sophisticated function. */ + if (byteLength == valWidth) + { + if (valWidth == 2) + swap2Bytes(OFstatic_cast(Uint8 *, value)); + else if (valWidth == 4) + swap4Bytes(OFstatic_cast(Uint8 *, value)); + else + swapBytes(value, byteLength, valWidth); + } + else + swapBytes(value, byteLength, valWidth); + } + return EC_Normal; + } + return EC_IllegalCall; +} + + + +void swapBytes(void * value, const Uint32 byteLength, + const size_t valWidth) + /* + * This function swaps byteLength bytes in value. These bytes are seperated + * in valWidth elements which will be swapped seperately. + * + * Parameters: + * value - [in] Array that contains the actual bytes which might have to be swapped. + * byteLength - [in] Length of the above array. + * valWidth - [in] Specifies how many bytes shall be treated together as one element. + */ +{ + /* use register (if available) to increase speed */ + register Uint8 save; + + /* in case valWidth equals 2, swap correspondingly */ + if (valWidth == 2) + { + register Uint8 *first = &OFstatic_cast(Uint8*, value)[0]; + register Uint8 *second = &OFstatic_cast(Uint8*, value)[1]; + register Uint32 times = byteLength / 2; + while(times--) + { + save = *first; + *first = *second; + *second = save; + first += 2; + second += 2; + } + } + /* if valWidth is greater than 2, swap correspondingly */ + else if (valWidth > 2) + { + register size_t i; + const size_t halfWidth = valWidth / 2; + const size_t offset = valWidth - 1; + register Uint8 *start; + register Uint8 *end; + + Uint32 times = OFstatic_cast(Uint32, byteLength / valWidth); + Uint8 *base = OFstatic_cast(Uint8 *, value); + + while (times--) + { + i = halfWidth; + start = base; + end = base+offset; + while (i--) + { + save = *start; + *start++ = *end; + *end-- = save; + } + base += valWidth; + } + } +} + + +Uint16 swapShort(const Uint16 toSwap) +{ + Uint8 *swapped = OFreinterpret_cast(Uint8 *, OFconst_cast(Uint16 *, &toSwap)); + swap2Bytes(swapped); + return *OFreinterpret_cast(Uint16*, swapped); +} diff --git a/dcmdata/libsrc/dctag.cc b/dcmdata/libsrc/dctag.cc new file mode 100644 index 00000000..56e57c76 --- /dev/null +++ b/dcmdata/libsrc/dctag.cc @@ -0,0 +1,268 @@ +/* + * + * Copyright (C) 1994-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Gerd Ehlers, Andrew Hewett + * + * Purpose: class DcmTag + * + */ + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ +#include "dcmtk/dcmdata/dctag.h" +#include "dcmtk/dcmdata/dcerror.h" /* for dcmdata error constants */ +#include "dcmtk/dcmdata/dcdict.h" +#include "dcmtk/dcmdata/dcdicent.h" + +#define INCLUDE_CSTDIO +#define INCLUDE_CSTRING +#include "dcmtk/ofstd/ofstdinc.h" + + +DcmTag::DcmTag() + : vr(EVR_UNKNOWN), + tagName(NULL), + privateCreator(NULL), + errorFlag(EC_InvalidTag) +{ +} + +DcmTag::DcmTag(const DcmTagKey& akey, const char *privCreator) + : DcmTagKey(akey), + vr(EVR_UNKNOWN), + tagName(NULL), + privateCreator(NULL), + errorFlag(EC_InvalidTag) +{ + if (privCreator) + updatePrivateCreator(privCreator); + lookupVRinDictionary(); +} + +DcmTag::DcmTag(Uint16 g, Uint16 e, const char *privCreator) + : DcmTagKey(g, e), + vr(EVR_UNKNOWN), + tagName(NULL), + privateCreator(NULL), + errorFlag(EC_InvalidTag) +{ + if (privCreator) + updatePrivateCreator(privCreator); + lookupVRinDictionary(); +} + +DcmTag::DcmTag(const DcmTagKey& akey, const DcmVR& avr) + : DcmTagKey(akey), + vr(avr), + tagName(NULL), + privateCreator(NULL), + errorFlag(EC_Normal) +{ +} + +DcmTag::DcmTag(Uint16 g, Uint16 e, const DcmVR& avr) + : DcmTagKey(g, e), + vr(avr), + tagName(NULL), + privateCreator(NULL), + errorFlag(EC_Normal) +{ +} + +DcmTag::DcmTag(const DcmTag& tag) + : DcmTagKey(tag), + vr(tag.vr), + tagName(NULL), + privateCreator(NULL), + errorFlag(tag.errorFlag) +{ + updateTagName(tag.tagName); + updatePrivateCreator(tag.privateCreator); +} + + +// ******************************** + + +DcmTag::~DcmTag() +{ + delete[] tagName; + delete[] privateCreator; +} + + +// ******************************** + + +DcmTag& DcmTag::operator=(const DcmTag& tag) +{ + if (this != &tag) + { + updateTagName(tag.tagName); + updatePrivateCreator(tag.privateCreator); + DcmTagKey::set(tag); + vr = tag.vr; + errorFlag = tag.errorFlag; + } + return *this; +} + +// ******************************** + +void DcmTag::lookupVRinDictionary() +{ + const DcmDataDictionary& globalDataDict = dcmDataDict.rdlock(); + const DcmDictEntry *dictRef = globalDataDict.findEntry(*this, privateCreator); + if (dictRef) + { + vr = dictRef->getVR(); + errorFlag = EC_Normal; + } + dcmDataDict.unlock(); +} + +// ******************************** + + +DcmVR DcmTag::setVR(const DcmVR& avr) // resolve ambiguous VR +{ + vr = avr; + + if (vr.getEVR() == EVR_UNKNOWN) + { + errorFlag = EC_InvalidVR; + } else { + errorFlag = EC_Normal; + } + return vr; +} + + +const char *DcmTag::getTagName() +{ + if (tagName) + return tagName; + + const char *newTagName = NULL; + const DcmDataDictionary& globalDataDict = dcmDataDict.rdlock(); + const DcmDictEntry *dictRef = globalDataDict.findEntry(*this, privateCreator); + if (dictRef) + newTagName=dictRef->getTagName(); + if (newTagName == NULL) + newTagName = DcmTag_ERROR_TagName; + updateTagName(newTagName); + dcmDataDict.unlock(); + + if (tagName) + return tagName; + return DcmTag_ERROR_TagName; +} + +OFBool DcmTag::isSignable() const +{ + OFBool result = isSignableTag(); + if (result) + result = !isUnknownVR(); + return result; +} + +OFBool DcmTag::isUnknownVR() const +{ + OFBool result = OFFalse; + switch (vr.getValidEVR()) // this is the VR we're going to write in explicit VR + { + case EVR_UNKNOWN: + case EVR_UNKNOWN2B: + case EVR_UN: + result = OFTrue; + break; + default: + /* nothing */ + break; + } + return result; +} + + +OFCondition DcmTag::findTagFromName(const char *name, DcmTag &value) +{ + OFCondition result = EC_IllegalParameter; + /* check parameters first */ + if ((name != NULL) && (strlen(name) > 0)) + { + result = EC_Normal; + unsigned int grp = 0xffff; + unsigned int elm = 0xffff; + /* check whether tag name has format 'gggg,eeee' */ + if (sscanf(name, "%x,%x", &grp, &elm) == 2) + { + /* store resulting tag value */ + value.set(OFstatic_cast(Uint16, grp), OFstatic_cast(Uint16, elm)); + value.lookupVRinDictionary(); + } else { + /* it is a name: look up in the dictionary */ + const DcmDataDictionary &globalDataDict = dcmDataDict.rdlock(); + const DcmDictEntry *dicent = globalDataDict.findEntry(name); + /* store resulting tag value */ + if (dicent != NULL) + { + value.set(dicent->getKey()); + value.setVR(dicent->getVR()); + } + else + result = EC_TagNotFound; + dcmDataDict.unlock(); + } + } + return result; +} + + +const char* DcmTag::getPrivateCreator() const +{ + return privateCreator; +} + +void DcmTag::setPrivateCreator(const char *privCreator) +{ + // a new private creator code probably changes the name + // of the tag. Enforce new dictionary lookup the next time + // getTagName() is called. + updateTagName(NULL); + updatePrivateCreator(privCreator); +} + +void DcmTag::updateTagName(const char *c) +{ + delete[] tagName; + if (c) + { + tagName = new char[strlen(c) + 1]; + if (tagName) + strcpy(tagName, c); + } else + tagName = NULL; +} + +void DcmTag::updatePrivateCreator(const char *c) +{ + delete[] privateCreator; + if (c) + { + privateCreator = new char[strlen(c) + 1]; + if (privateCreator) + strcpy(privateCreator, c); + } else + privateCreator = NULL; +} diff --git a/dcmdata/libsrc/dctagkey.cc b/dcmdata/libsrc/dctagkey.cc new file mode 100644 index 00000000..28492e6a --- /dev/null +++ b/dcmdata/libsrc/dctagkey.cc @@ -0,0 +1,94 @@ +/* + * + * Copyright (C) 1994-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Andrew Hewett + * + * Purpose: Basis class for dicom tags. + * + */ + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ +#include "dcmtk/dcmdata/dctagkey.h" + +#define INCLUDE_CSTDIO +#define INCLUDE_CSTRING +#include "dcmtk/ofstd/ofstdinc.h" + +/* + * DcmTagKey member functions + */ + +DcmTagKey DcmTagKey::getBaseTag() const +{ + // make sure that the group number is even (i.e. a standard tag). We also + // accept more than 16 repeating groups because of known real-world examples. + const Uint16 baseGroup = group & 0xFF01; + // check for curve or overlay repeating group + if ((baseGroup == 0x5000) || (baseGroup == 0x6000)) + return DcmTagKey(baseGroup, element); + else + return *this; +} + + +OFString DcmTagKey::toString() const +{ + char tagBuf[16]; + + if (group == 0xffff && element == 0xffff) + { + strcpy(tagBuf, "(\?\?\?\?,\?\?\?\?)"); // prevent trigraph expansion in string constant + } else { + sprintf(tagBuf, "(%04x,%04x)", OFstatic_cast(unsigned, group), OFstatic_cast(unsigned, element)); + } + return tagBuf; +} + + +OFBool DcmTagKey::isSignableTag() const +{ + //no group length tags (element number of 0000) + if (element == 0) return OFFalse; + + // no Length to End Tag + if ((group == 0x0008)&&(element==0x0001)) return OFFalse; + + //no tags with group number less than 0008 + if (group < 8) return OFFalse; + + //no tags from group FFFA (digital signatures sequence) + if (group == 0xfffa) return OFFalse; + + // no MAC Parameters sequence + if ((group == 0x4ffe)&&(element==0x0001)) return OFFalse; + + //no Data Set trailing Padding + if ((group == 0xfffc)&&(element==0xfffc)) return OFFalse; + + //no Sequence or Item Delimitation Tag + if ((group == 0xfffe)&&((element==0xe00d)||(element==0xe0dd))) return OFFalse; + + return OFTrue; +} + +/* +** DcmTagKey friend functions +*/ + +STD_NAMESPACE ostream& operator<<(STD_NAMESPACE ostream& s, const DcmTagKey& k) +{ + s << k.toString(); + return s; +} diff --git a/dcmdata/libsrc/dctypes.cc b/dcmdata/libsrc/dctypes.cc new file mode 100644 index 00000000..561dcdd3 --- /dev/null +++ b/dcmdata/libsrc/dctypes.cc @@ -0,0 +1,45 @@ +/* + * + * Copyright (C) 2002-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Joerg Riesmeier + * + * Purpose: global type and constant definitions + * + */ + + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/dcmdata/dctypes.h" + +OFLogger DCM_dcmdataLogger = OFLog::getLogger("dcmtk.dcmdata"); + +/* print flags */ +const size_t DCMTypes::PF_shortenLongTagValues = 1 << 0; +const size_t DCMTypes::PF_showTreeStructure = 1 << 1; +const size_t DCMTypes::PF_doNotMapUIDsToNames = 1 << 2; +const size_t DCMTypes::PF_convertToMarkup = 1 << 3; +const size_t DCMTypes::PF_convertToOctalNumbers = 1 << 4; +const size_t DCMTypes::PF_useANSIEscapeCodes = 1 << 5; + +/* writeXML flags */ +const size_t DCMTypes::XF_addDocumentType = 1 << 0; +const size_t DCMTypes::XF_writeBinaryData = 1 << 1; +const size_t DCMTypes::XF_encodeBase64 = 1 << 2; +const size_t DCMTypes::XF_useXMLNamespace = 1 << 3; +const size_t DCMTypes::XF_embedDocumentType = 1 << 4; +const size_t DCMTypes::XF_omitDataElementName = 1 << 5; +const size_t DCMTypes::XF_convertNonASCII = 1 << 6; +const size_t DCMTypes::XF_useNativeModel = 1 << 7; diff --git a/dcmdata/libsrc/dcuid.cc b/dcmdata/libsrc/dcuid.cc new file mode 100644 index 00000000..fbb75c0f --- /dev/null +++ b/dcmdata/libsrc/dcuid.cc @@ -0,0 +1,1767 @@ +/* + * + * Copyright (C) 1994-2015, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Andrew Hewett + * + * Purpose: + * Definitions of "well known" DICOM Unique Identifiers, + * routines for finding and creating UIDs. + * + */ + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#ifdef HAVE_WINDOWS_H +#include /* this includes either winsock.h or winsock2.h */ +#else +#ifdef HAVE_WINSOCK_H +#include /* include winsock.h directly i.e. on MacOS */ +#endif +#endif + +#define INCLUDE_CSTDLIB +#define INCLUDE_CSTDIO +#define INCLUDE_CSTRING +#define INCLUDE_CTIME +#define INCLUDE_LIBC +#define INCLUDE_UNISTD +#include "dcmtk/ofstd/ofstdinc.h" + +BEGIN_EXTERN_C +#ifdef HAVE_SYS_TIME_H +#include +#endif +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_SYS_SOCKET_H +#ifndef DCOMPAT_SYS_SOCKET_H_ +#define DCOMPAT_SYS_SOCKET_H_ +/* some systems don't protect sys/socket.h (e.g. DEC Ultrix) */ +#include +#endif +#endif +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif +#ifdef HAVE_NETDB_H +#include +#endif + +#ifndef HAVE_WINDOWS_H +#ifndef HAVE_PROTOTYPE_GETTIMEOFDAY + /* Ultrix has gettimeofday() but no prototype in the header files */ + int gettimeofday(struct timeval *tp, void *); +#endif +#endif + +END_EXTERN_C + +#include "dcmtk/ofstd/ofstream.h" +#include "dcmtk/dcmdata/dcuid.h" +#include "dcmtk/dcmdata/dctypes.h" +#include "dcmtk/ofstd/ofthread.h" +#include "dcmtk/ofstd/ofcrc32.h" +#include "dcmtk/ofstd/ofdefine.h" +#include "dcmtk/ofstd/ofstd.h" +#include "dcmtk/ofstd/ofnetdb.h" + +struct UIDNameMap { + const char* uid; + const char* name; +}; + +// +// It is very important that the names of the UIDs may not use the following +// characters: space ( ) [ ], = < > + +static const UIDNameMap uidNameMap[] = { + + { UID_StandardApplicationContext, "StandardApplicationContext" }, + + // Transfer Syntax + { UID_LittleEndianImplicitTransferSyntax, "LittleEndianImplicit" }, + { UID_LittleEndianExplicitTransferSyntax, "LittleEndianExplicit" }, + { UID_BigEndianExplicitTransferSyntax, "BigEndianExplicit" }, + { UID_JPEGProcess1TransferSyntax, "JPEGBaseline" }, + { UID_JPEGProcess2_4TransferSyntax, "JPEGExtended:Process2+4" }, + { UID_JPEGProcess3_5TransferSyntax, "JPEGExtended:Process3+5" }, + { UID_JPEGProcess6_8TransferSyntax, "JPEGSpectralSelection:Non-hierarchical:Process6+8" }, + { UID_JPEGProcess7_9TransferSyntax, "JPEGSpectralSelection:Non-hierarchical:Process7+9" }, + { UID_JPEGProcess10_12TransferSyntax, "JPEGFullProgression:Non-hierarchical:Process10+12" }, + { UID_JPEGProcess11_13TransferSyntax, "JPEGFullProgression:Non-hierarchical:Process11+13" }, + { UID_JPEGProcess14TransferSyntax, "JPEGLossless:Non-hierarchical:Process14" }, + { UID_JPEGProcess15TransferSyntax, "JPEGLossless:Non-hierarchical:Process15" }, + { UID_JPEGProcess16_18TransferSyntax, "JPEGExtended:Hierarchical:Process16+18" }, + { UID_JPEGProcess17_19TransferSyntax, "JPEGExtended:Hierarchical:Process17+19" }, + { UID_JPEGProcess20_22TransferSyntax, "JPEGSpectralSelection:Hierarchical:Process20+22" }, + { UID_JPEGProcess21_23TransferSyntax, "JPEGSpectralSelection:Hierarchical:Process21+23" }, + { UID_JPEGProcess24_26TransferSyntax, "JPEGFullProgression:Hierarchical:Process24+26" }, + { UID_JPEGProcess25_27TransferSyntax, "JPEGFullProgression:Hierarchical:Process25+27" }, + { UID_JPEGProcess28TransferSyntax, "JPEGLossless:Hierarchical:Process28" }, + { UID_JPEGProcess29TransferSyntax, "JPEGLossless:Hierarchical:Process29" }, + { UID_JPEGProcess14SV1TransferSyntax, "JPEGLossless:Non-hierarchical-1stOrderPrediction" }, + { UID_JPEGLSLosslessTransferSyntax, "JPEGLSLossless" }, + { UID_JPEGLSLossyTransferSyntax, "JPEGLSLossy" }, + { UID_RLELosslessTransferSyntax, "RLELossless" }, + { UID_DeflatedExplicitVRLittleEndianTransferSyntax, "DeflatedLittleEndianExplicit" }, + { UID_JPEG2000LosslessOnlyTransferSyntax, "JPEG2000LosslessOnly" }, + { UID_JPEG2000TransferSyntax, "JPEG2000" }, + { UID_MPEG2MainProfileAtMainLevelTransferSyntax, "MPEG2MainProfile@MainLevel" }, + { UID_MPEG2MainProfileAtHighLevelTransferSyntax, "MPEG2MainProfile@HighLevel" }, + { UID_MPEG4HighProfileLevel4_1TransferSyntax, "MPEG4HighProfile/Level4.1" }, + { UID_MPEG4BDcompatibleHighProfileLevel4_1TransferSyntax, "MPEG4BDcompatibleHighProfile/Level4.1" }, + { UID_MPEG4HighProfileLevel4_2_For2DVideoTransferSyntax, "MPEG4HighProfile/Level4.2For2DVideo" }, + { UID_MPEG4HighProfileLevel4_2_For3DVideoTransferSyntax, "MPEG4HighProfile/Level4.2For3DVideo" }, + { UID_MPEG4StereoHighProfileLevel4_2TransferSyntax, "MPEG4StereoHighProfile/Level4.2" }, + { UID_JPEG2000Part2MulticomponentImageCompressionLosslessOnlyTransferSyntax, "JPEG2000MulticomponentLosslessOnly" }, + { UID_JPEG2000Part2MulticomponentImageCompressionTransferSyntax, "JPEG2000Multicomponent" }, + { UID_JPIPReferencedTransferSyntax, "JPIPReferenced" }, + { UID_JPIPReferencedDeflateTransferSyntax, "JPIPReferencedDeflate" }, + { UID_RFC2557MIMEEncapsulationTransferSyntax, "RFC2557MIMEEncapsulation" }, + { UID_XMLEncodingTransferSyntax, "XMLEncoding" }, + + // Storage + { UID_AmbulatoryECGWaveformStorage, "AmbulatoryECGWaveformStorage" }, + { UID_ArterialPulseWaveformStorage, "ArterialPulseWaveformStorage" }, + { UID_AutorefractionMeasurementsStorage, "AutorefractionMeasurementsStorage" }, + { UID_BasicStructuredDisplayStorage, "BasicStructuredDisplayStorage" }, + { UID_BasicTextSRStorage, "BasicTextSRStorage" }, + { UID_BasicVoiceAudioWaveformStorage, "BasicVoiceAudioWaveformStorage" }, + { UID_BlendingSoftcopyPresentationStateStorage, "BlendingSoftcopyPresentationStateStorage" }, + { UID_BreastProjectionXRayImageStorageForPresentation, "BreastProjectionXRayImageStorageForPresentation" }, + { UID_BreastProjectionXRayImageStorageForProcessing, "BreastProjectionXRayImageStorageForProcessing" }, + { UID_BreastTomosynthesisImageStorage, "BreastTomosynthesisImageStorage" }, + { UID_CardiacElectrophysiologyWaveformStorage, "CardiacElectrophysiologyWaveformStorage" }, + { UID_ChestCADSRStorage, "ChestCADSRStorage" }, + { UID_ColonCADSRStorage, "ColonCADSRStorage" }, + { UID_ColorSoftcopyPresentationStateStorage, "ColorSoftcopyPresentationStateStorage" }, + { UID_CompositingPlanarMPRVolumetricPresentationStateStorage, "CompositingPlanarMPRVolumetricPresentationStateStorage" }, + { UID_Comprehensive3DSRStorage, "Comprehensive3DSRStorage" }, + { UID_ComprehensiveSRStorage, "ComprehensiveSRStorage" }, + { UID_ComputedRadiographyImageStorage, "ComputedRadiographyImageStorage" }, + { UID_CornealTopographyMapStorage, "CornealTopographyMapStorage" }, + { UID_CTImageStorage, "CTImageStorage" }, + { UID_DeformableSpatialRegistrationStorage, "DeformableSpatialRegistrationStorage" }, + { UID_DigitalIntraOralXRayImageStorageForPresentation, "DigitalIntraOralXRayImageStorageForPresentation" }, + { UID_DigitalIntraOralXRayImageStorageForProcessing, "DigitalIntraOralXRayImageStorageForProcessing" }, + { UID_DigitalMammographyXRayImageStorageForPresentation, "DigitalMammographyXRayImageStorageForPresentation" }, + { UID_DigitalMammographyXRayImageStorageForProcessing, "DigitalMammographyXRayImageStorageForProcessing" }, + { UID_DigitalXRayImageStorageForPresentation, "DigitalXRayImageStorageForPresentation" }, + { UID_DigitalXRayImageStorageForProcessing, "DigitalXRayImageStorageForProcessing" }, + { UID_EncapsulatedCDAStorage, "EncapsulatedCDAStorage" }, + { UID_EncapsulatedPDFStorage, "EncapsulatedPDFStorage" }, + { UID_EnhancedCTImageStorage, "EnhancedCTImageStorage" }, + { UID_EnhancedMRColorImageStorage, "EnhancedMRColorImageStorage" }, + { UID_EnhancedMRImageStorage, "EnhancedMRImageStorage" }, + { UID_EnhancedPETImageStorage, "EnhancedPETImageStorage" }, + { UID_EnhancedSRStorage, "EnhancedSRStorage" }, + { UID_EnhancedUSVolumeStorage, "EnhancedUSVolumeStorage" }, + { UID_EnhancedXAImageStorage, "EnhancedXAImageStorage" }, + { UID_EnhancedXRFImageStorage, "EnhancedXRFImageStorage" }, + { UID_ExtensibleSRStorage, "ExtensibleSRStorage" }, + { UID_GeneralAudioWaveformStorage, "GeneralAudioWaveformStorage" }, + { UID_GeneralECGWaveformStorage, "GeneralECGWaveformStorage" }, + { UID_GenericImplantTemplateStorage, "GenericImplantTemplateStorage" }, + { UID_GrayscalePlanarMPRVolumetricPresentationStateStorage, "GrayscalePlanarMPRVolumetricPresentationStateStorage" }, + { UID_GrayscaleSoftcopyPresentationStateStorage, "GrayscaleSoftcopyPresentationStateStorage" }, + { UID_HangingProtocolStorage, "HangingProtocolStorage" }, + { UID_HemodynamicWaveformStorage, "HemodynamicWaveformStorage" }, + { UID_ImplantAssemblyTemplateStorage, "ImplantAssemblyTemplateStorage" }, + { UID_ImplantationPlanSRDocumentStorage, "ImplantationPlanSRDocumentStorage" }, + { UID_ImplantTemplateGroupStorage, "ImplantTemplateGroupStorage" }, + { UID_IntraocularLensCalculationsStorage, "IntraocularLensCalculationsStorage" }, + { UID_IntravascularOpticalCoherenceTomographyImageStorageForPresentation, "IntravascularOpticalCoherenceTomographyImageStorageForPresentation" }, + { UID_IntravascularOpticalCoherenceTomographyImageStorageForProcessing, "IntravascularOpticalCoherenceTomographyImageStorageForProcessing" }, + { UID_KeratometryMeasurementsStorage, "KeratometryMeasurementsStorage" }, + { UID_KeyObjectSelectionDocumentStorage, "KeyObjectSelectionDocumentStorage" }, + { UID_LegacyConvertedEnhancedCTImageStorage, "LegacyConvertedEnhancedCTImageStorage" }, + { UID_LegacyConvertedEnhancedMRImageStorage, "LegacyConvertedEnhancedMRImageStorage" }, + { UID_LegacyConvertedEnhancedPETImageStorage, "LegacyConvertedEnhancedPETImageStorage" }, + { UID_LensometryMeasurementsStorage, "LensometryMeasurementsStorage" }, + { UID_MacularGridThicknessAndVolumeReportStorage, "MacularGridThicknessAndVolumeReportStorage" }, + { UID_MammographyCADSRStorage, "MammographyCADSRStorage" }, + { UID_MediaStorageDirectoryStorage, "MediaStorageDirectoryStorage" }, + { UID_MRImageStorage, "MRImageStorage" }, + { UID_MRSpectroscopyStorage, "MRSpectroscopyStorage" }, + { UID_MultiframeGrayscaleByteSecondaryCaptureImageStorage, "MultiframeGrayscaleByteSecondaryCaptureImageStorage" }, + { UID_MultiframeGrayscaleWordSecondaryCaptureImageStorage, "MultiframeGrayscaleWordSecondaryCaptureImageStorage" }, + { UID_MultiframeSingleBitSecondaryCaptureImageStorage, "MultiframeSingleBitSecondaryCaptureImageStorage" }, + { UID_MultiframeTrueColorSecondaryCaptureImageStorage, "MultiframeTrueColorSecondaryCaptureImageStorage" }, + { UID_NuclearMedicineImageStorage, "NuclearMedicineImageStorage" }, + { UID_OphthalmicAxialMeasurementsStorage, "OphthalmicAxialMeasurementsStorage" }, + { UID_OphthalmicPhotography16BitImageStorage, "OphthalmicPhotography16BitImageStorage" }, + { UID_OphthalmicPhotography8BitImageStorage, "OphthalmicPhotography8BitImageStorage" }, + { UID_OphthalmicThicknessMapStorage, "OphthalmicThicknessMapStorage" }, + { UID_OphthalmicTomographyImageStorage, "OphthalmicTomographyImageStorage" }, + { UID_OphthalmicVisualFieldStaticPerimetryMeasurementsStorage, "OphthalmicVisualFieldStaticPerimetryMeasurementsStorage" }, + { UID_ParametricMapStorage, "ParametricMapStorage" }, + { UID_PositronEmissionTomographyImageStorage, "PositronEmissionTomographyImageStorage" }, + { UID_ProcedureLogStorage, "ProcedureLogStorage" }, + { UID_PseudoColorSoftcopyPresentationStateStorage, "PseudoColorSoftcopyPresentationStateStorage" }, + { UID_RadiopharmaceuticalRadiationDoseSRStorage, "RadiopharmaceuticalRadiationDoseSRStorage" }, + { UID_RawDataStorage, "RawDataStorage" }, + { UID_RealWorldValueMappingStorage, "RealWorldValueMappingStorage" }, + { UID_RespiratoryWaveformStorage, "RespiratoryWaveformStorage" }, + { UID_RTBeamsTreatmentRecordStorage, "RTBeamsTreatmentRecordStorage" }, + { UID_RTBrachyTreatmentRecordStorage, "RTBrachyTreatmentRecordStorage" }, + { UID_RTDoseStorage, "RTDoseStorage" }, + { UID_RTImageStorage, "RTImageStorage" }, + { UID_RTIonBeamsTreatmentRecordStorage, "RTIonBeamsTreatmentRecordStorage" }, + { UID_RTIonPlanStorage, "RTIonPlanStorage" }, + { UID_RTPlanStorage, "RTPlanStorage" }, + { UID_RTStructureSetStorage, "RTStructureSetStorage" }, + { UID_RTTreatmentSummaryRecordStorage, "RTTreatmentSummaryRecordStorage" }, + { UID_SecondaryCaptureImageStorage, "SecondaryCaptureImageStorage" }, + { UID_SegmentationStorage, "SegmentationStorage" }, + { UID_SpatialFiducialsStorage, "SpatialFiducialsStorage" }, + { UID_SpatialRegistrationStorage, "SpatialRegistrationStorage" }, + { UID_SpectaclePrescriptionReportStorage, "SpectaclePrescriptionReportStorage" }, + { UID_StereometricRelationshipStorage, "StereometricRelationshipStorage" }, + { UID_SubjectiveRefractionMeasurementsStorage, "SubjectiveRefractionMeasurementsStorage" }, + { UID_SurfaceScanMeshStorage, "SurfaceScanMeshStorage" }, + { UID_SurfaceScanPointCloudStorage, "SurfaceScanPointCloudStorage" }, + { UID_SurfaceSegmentationStorage, "SurfaceSegmentationStorage" }, + { UID_TwelveLeadECGWaveformStorage, "TwelveLeadECGWaveformStorage" }, + { UID_UltrasoundImageStorage, "UltrasoundImageStorage" }, + { UID_UltrasoundMultiframeImageStorage, "UltrasoundMultiframeImageStorage" }, + { UID_VideoEndoscopicImageStorage, "VideoEndoscopicImageStorage" }, + { UID_VideoMicroscopicImageStorage, "VideoMicroscopicImageStorage" }, + { UID_VideoPhotographicImageStorage, "VideoPhotographicImageStorage" }, + { UID_VisualAcuityMeasurementsStorage, "VisualAcuityMeasurementsStorage" }, + { UID_VLEndoscopicImageStorage, "VLEndoscopicImageStorage" }, + { UID_VLMicroscopicImageStorage, "VLMicroscopicImageStorage" }, + { UID_VLPhotographicImageStorage, "VLPhotographicImageStorage" }, + { UID_VLSlideCoordinatesMicroscopicImageStorage, "VLSlideCoordinatesMicroscopicImageStorage" }, + { UID_VLWholeSlideMicroscopyImageStorage, "VLWholeSlideMicroscopyImageStorage" }, + { UID_WideFieldOphthalmicPhotographyStereographicProjectionImageStorage, "WideFieldOphthalmicPhotographyStereographicProjectionImageStorage" }, + { UID_WideFieldOphthalmicPhotography3DCoordinatesImageStorage, "OphthalmicPhotography3DCoordinatesImageStorage" }, + { UID_XAXRFGrayscaleSoftcopyPresentationStateStorage, "XAXRFGrayscaleSoftcopyPresentationStateStorage" }, + { UID_XRay3DAngiographicImageStorage, "XRay3DAngiographicImageStorage" }, + { UID_XRay3DCraniofacialImageStorage, "XRay3DCraniofacialImageStorage" }, + { UID_XRayAngiographicImageStorage, "XRayAngiographicImageStorage" }, + { UID_XRayRadiationDoseSRStorage, "XRayRadiationDoseSRStorage" }, + { UID_XRayRadiofluoroscopicImageStorage, "XRayRadiofluoroscopicImageStorage" }, + // Storage (retired) + { UID_RETIRED_HardcopyColorImageStorage, "RETIRED_HardcopyColorImageStorage" }, + { UID_RETIRED_HardcopyGrayscaleImageStorage, "RETIRED_HardcopyGrayscaleImageStorage" }, + { UID_RETIRED_NuclearMedicineImageStorage, "RETIRED_NuclearMedicineImageStorage" }, + { UID_RETIRED_StandaloneCurveStorage, "RETIRED_StandaloneCurveStorage" }, + { UID_RETIRED_StandaloneModalityLUTStorage, "RETIRED_StandaloneModalityLUTStorage" }, + { UID_RETIRED_StandaloneOverlayStorage, "RETIRED_StandaloneOverlayStorage" }, + { UID_RETIRED_StandalonePETCurveStorage, "RETIRED_StandalonePETCurveStorage" }, + { UID_RETIRED_StandaloneVOILUTStorage, "RETIRED_StandaloneVOILUTStorage" }, + { UID_RETIRED_StoredPrintStorage, "RETIRED_StoredPrintStorage" }, + { UID_RETIRED_UltrasoundImageStorage, "RETIRED_UltrasoundImageStorage" }, + { UID_RETIRED_UltrasoundMultiframeImageStorage, "RETIRED_UltrasoundMultiframeImageStorage" }, + { UID_RETIRED_VLImageStorage, "RETIRED_VLImageStorage" }, + { UID_RETIRED_VLMultiFrameImageStorage, "RETIRED_VLMultiFrameImageStorage" }, + { UID_RETIRED_XRayAngiographicBiPlaneImageStorage, "RETIRED_XRayAngiographicBiPlaneImageStorage" }, + // Storage (DICOS) + { UID_DICOS_CTImageStorage, "DICOS_CTImageStorage" }, + { UID_DICOS_DigitalXRayImageStorageForPresentation, "DICOS_DigitalXRayImageStorageForPresentation" }, + { UID_DICOS_DigitalXRayImageStorageForProcessing, "DICOS_DigitalXRayImageStorageForProcessing" }, + { UID_DICOS_ThreatDetectionReportStorage, "DICOS_ThreatDetectionReportStorage" }, + // Storage (DICONDE) + { UID_DICONDE_EddyCurrentImageStorage, "DICONDE_EddyCurrentImageStorage" }, + { UID_DICONDE_EddyCurrentMultiframeImageStorage, "DICONDE_EddyCurrentMultiframeImageStorage" }, + + // Query/Retrieve + { UID_FINDPatientRootQueryRetrieveInformationModel, "FINDPatientRootQueryRetrieveInformationModel" }, + { UID_FINDStudyRootQueryRetrieveInformationModel, "FINDStudyRootQueryRetrieveInformationModel" }, + { UID_GETPatientRootQueryRetrieveInformationModel, "GETPatientRootQueryRetrieveInformationModel" }, + { UID_GETStudyRootQueryRetrieveInformationModel, "GETStudyRootQueryRetrieveInformationModel" }, + { UID_MOVEPatientRootQueryRetrieveInformationModel, "MOVEPatientRootQueryRetrieveInformationModel" }, + { UID_MOVEStudyRootQueryRetrieveInformationModel, "MOVEStudyRootQueryRetrieveInformationModel" }, + { UID_RETIRED_FINDPatientStudyOnlyQueryRetrieveInformationModel, "RETIRED_FINDPatientStudyOnlyQueryRetrieveInformationModel" }, + { UID_GETCompositeInstanceRetrieveWithoutBulkData, "GETCompositeInstanceRetrieveWithoutBulkData" }, + { UID_GETCompositeInstanceRootRetrieve, "GETCompositeInstanceRootRetrieve" }, + { UID_RETIRED_GETPatientStudyOnlyQueryRetrieveInformationModel, "RETIRED_GETPatientStudyOnlyQueryRetrieveInformationModel" }, + { UID_MOVECompositeInstanceRootRetrieve, "MOVECompositeInstanceRootRetrieve" }, + { UID_RETIRED_MOVEPatientStudyOnlyQueryRetrieveInformationModel, "RETIRED_MOVEPatientStudyOnlyQueryRetrieveInformationModel" }, + + // Worklist + { UID_FINDModalityWorklistInformationModel, "FINDModalityWorklistInformationModel" }, + + // General Purpose Worklist + { UID_RETIRED_FINDGeneralPurposeWorklistInformationModel, "RETIRED_FINDGeneralPurposeWorklistInformationModel" }, + { UID_RETIRED_GeneralPurposePerformedProcedureStepSOPClass, "RETIRED_GeneralPurposePerformedProcedureStepSOPClass" }, + { UID_RETIRED_GeneralPurposeScheduledProcedureStepSOPClass, "RETIRED_GeneralPurposeScheduledProcedureStepSOPClass" }, + { UID_RETIRED_GeneralPurposeWorklistManagementMetaSOPClass, "RETIRED_GeneralPurposeWorklistManagementMetaSOPClass" }, + + // MPPS + { UID_ModalityPerformedProcedureStepNotificationSOPClass, "ModalityPerformedProcedureStepNotificationSOPClass" }, + { UID_ModalityPerformedProcedureStepRetrieveSOPClass, "ModalityPerformedProcedureStepRetrieveSOPClass" }, + { UID_ModalityPerformedProcedureStepSOPClass, "ModalityPerformedProcedureStepSOPClass" }, + + // Radiotherapy Treatment Delivery + { UID_RTBeamsDeliveryInstructionStorage, "RTBeamsDeliveryInstructionStorage" }, + { UID_RTConventionalMachineVerification, "RTConventionalMachineVerification" }, + { UID_RTIonMachineVerification, "RTIonMachineVerification" }, + + // Unified Worklist and Procedure Step + { UID_UnifiedWorklistAndProcedureStepServiceClass, "UnifiedWorklistAndProcedureStepServiceClass" }, + { UID_UnifiedProcedureStepPushSOPClass, "UnifiedProcedureStepPushSOPClass" }, + { UID_UnifiedProcedureStepWatchSOPClass, "UnifiedProcedureStepWatchSOPClass" }, + { UID_UnifiedProcedureStepPullSOPClass, "UnifiedProcedureStepPullSOPClass" }, + { UID_UnifiedProcedureStepEventSOPClass, "UnifiedProcedureStepEventSOPClass" }, + { UID_UPSGlobalSubscriptionSOPInstance, "UPSGlobalSubscriptionSOPInstance" }, + { UID_UPSFilteredGlobalSubscriptionSOPInstance, "UPSFilteredGlobalSubscriptionSOPInstance" }, + + // Storage Commitment + { UID_RETIRED_StorageCommitmentPullModelSOPClass, "RETIRED_StorageCommitmentPullModelSOPClass" }, + { UID_RETIRED_StorageCommitmentPullModelSOPInstance, "RETIRED_StorageCommitmentPullModelSOPInstance" }, + { UID_StorageCommitmentPushModelSOPClass, "StorageCommitmentPushModelSOPClass" }, + { UID_StorageCommitmentPushModelSOPInstance, "StorageCommitmentPushModelSOPInstance" }, + + // Hanging Protocols + { UID_FINDHangingProtocolInformationModel, "FINDHangingProtocolInformationModel" }, + { UID_MOVEHangingProtocolInformationModel, "MOVEHangingProtocolInformationModel" }, + + // Relevant Patient Information Query + { UID_BreastImagingRelevantPatientInformationQuery, "BreastImagingRelevantPatientInformationQuery" }, + { UID_CardiacRelevantPatientInformationQuery, "CardiacRelevantPatientInformationQuery" }, + { UID_GeneralRelevantPatientInformationQuery, "GeneralRelevantPatientInformationQuery" }, + + // Color Palette Storage and Query/Retrieve + { UID_ColorPaletteStorage, "ColorPaletteStorage" }, + { UID_FINDColorPaletteInformationModel, "FINDColorPaletteInformationModel" }, + { UID_MOVEColorPaletteInformationModel, "MOVEColorPaletteInformationModel" }, + { UID_GETColorPaletteInformationModel, "GETColorPaletteInformationModel" }, + + // Implant Template Query/Retrieve + { UID_FINDGenericImplantTemplateInformationModel, "FINDGenericImplantTemplateInformationModel" }, + { UID_MOVEGenericImplantTemplateInformationModel, "MOVEGenericImplantTemplateInformationModel" }, + { UID_GETGenericImplantTemplateInformationModel, "GETGenericImplantTemplateInformationModel" }, + { UID_FINDImplantAssemblyTemplateInformationModel, "FINDImplantAssemblyTemplateInformationModel" }, + { UID_MOVEImplantAssemblyTemplateInformationModel, "MOVEImplantAssemblyTemplateInformationModel" }, + { UID_GETImplantAssemblyTemplateInformationModel, "GETImplantAssemblyTemplateInformationModel" }, + { UID_FINDImplantTemplateGroupInformationModel, "FINDImplantTemplateGroupInformationModel" }, + { UID_MOVEImplantTemplateGroupInformationModel, "MOVEImplantTemplateGroupInformationModel" }, + { UID_GETImplantTemplateGroupInformationModel, "GETImplantTemplateGroupInformationModel" }, + + // Print + { UID_BasicAnnotationBoxSOPClass, "BasicAnnotationBoxSOPClass" }, + { UID_BasicColorImageBoxSOPClass, "BasicColorImageBoxSOPClass" }, + { UID_BasicColorPrintManagementMetaSOPClass, "BasicColorPrintManagementMetaSOPClass" }, + { UID_BasicFilmBoxSOPClass, "BasicFilmBoxSOPClass" }, + { UID_BasicFilmSessionSOPClass, "BasicFilmSessionSOPClass" }, + { UID_BasicGrayscaleImageBoxSOPClass, "BasicGrayscaleImageBoxSOPClass" }, + { UID_BasicGrayscalePrintManagementMetaSOPClass, "BasicGrayscalePrintManagementMetaSOPClass" }, + { UID_PresentationLUTSOPClass, "PresentationLUTSOPClass" }, + { UID_PrintJobSOPClass, "PrintJobSOPClass" }, + { UID_PrinterConfigurationRetrievalSOPClass, "PrinterConfigurationRetrievalSOPClass" }, + { UID_PrinterConfigurationRetrievalSOPInstance, "PrinterConfigurationRetrievalSOPInstance" }, + { UID_PrinterSOPClass, "PrinterSOPClass" }, + { UID_PrinterSOPInstance, "PrinterSOPInstance" }, + { UID_RETIRED_BasicPrintImageOverlayBoxSOPClass, "RETIRED_BasicPrintImageOverlayBoxSOPClass" }, + { UID_RETIRED_ImageOverlayBoxSOPClass, "RETIRED_ImageOverlayBoxSOPClass" }, + { UID_RETIRED_PrintQueueManagementSOPClass, "RETIRED_PrintQueueManagementSOPClass" }, + { UID_RETIRED_PrintQueueSOPInstance, "RETIRED_PrintQueueSOPInstance" }, + { UID_RETIRED_PullPrintRequestSOPClass, "RETIRED_PullPrintRequestSOPClass" }, + { UID_RETIRED_PullStoredPrintManagementMetaSOPClass, "RETIRED_PullStoredPrintManagementMetaSOPClass" }, + { UID_RETIRED_ReferencedColorPrintManagementMetaSOPClass, "RETIRED_ReferencedColorPrintManagementMetaSOPClass" }, + { UID_RETIRED_ReferencedGrayscalePrintManagementMetaSOPClass, "RETIRED_ReferencedGrayscalePrintManagementMetaSOPClass" }, + { UID_RETIRED_ReferencedImageBoxSOPClass, "RETIRED_ReferencedImageBoxSOPClass" }, + { UID_VOILUTBoxSOPClass, "VOILUTBoxSOPClass" }, + + // Detached Management + { UID_RETIRED_DetachedInterpretationManagementSOPClass, "RETIRED_DetachedInterpretationManagementSOPClass" }, + { UID_RETIRED_DetachedPatientManagementMetaSOPClass, "RETIRED_DetachedPatientManagementMetaSOPClass" }, + { UID_RETIRED_DetachedPatientManagementSOPClass, "RETIRED_DetachedPatientManagementSOPClass" }, + { UID_RETIRED_DetachedResultsManagementMetaSOPClass, "RETIRED_DetachedResultsManagementMetaSOPClass" }, + { UID_RETIRED_DetachedResultsManagementSOPClass, "RETIRED_DetachedResultsManagementSOPClass" }, + { UID_RETIRED_DetachedStudyManagementMetaSOPClass, "RETIRED_DetachedStudyManagementMetaSOPClass" }, + { UID_RETIRED_DetachedStudyManagementSOPClass, "RETIRED_DetachedStudyManagementSOPClass" }, + { UID_RETIRED_DetachedVisitManagementSOPClass, "RETIRED_DetachedVisitManagementSOPClass" }, + + // Procedure Log + { UID_ProceduralEventLoggingSOPClass, "ProceduralEventLoggingSOPClass" }, + { UID_ProceduralEventLoggingSOPInstance, "ProceduralEventLoggingSOPInstance" }, + + // Substance Administration + { UID_SubstanceAdministrationLoggingSOPClass, "SubstanceAdministrationLoggingSOPClass" }, + { UID_SubstanceAdministrationLoggingSOPInstance, "SubstanceAdministrationLoggingSOPInstance" }, + { UID_ProductCharacteristicsQuerySOPClass, "ProductCharacteristicsQuerySOPClass" }, + { UID_SubstanceApprovalQuerySOPClass, "SubstanceApprovalQuerySOPClass" }, + + // Media Creation + { UID_MediaCreationManagementSOPClass, "MediaCreationManagementSOPClass" }, + + // SOP Class Relationship Negotiation + { UID_StorageServiceClass, "StorageServiceClass" }, + + // Instance Availability Notification + { UID_InstanceAvailabilityNotificationSOPClass, "InstanceAvailabilityNotificationSOPClass" }, + + // Application Hosting + { UID_NativeDICOMModel, "NativeDICOMModel" }, + { UID_AbstractMultiDimensionalImageModel, "AbstractMultiDimensionalImageModel" }, + + // Communication of Display Parameters + { UID_DisplaySystemSOPClass, "DisplaySystemSOPClass" }, + { UID_DisplaySystemSOPInstance, "DisplaySystemSOPInstance" }, + + // Other + { UID_RETIRED_BasicStudyContentNotificationSOPClass, "RETIRED_BasicStudyContentNotificationSOPClass" }, + { UID_RETIRED_StudyComponentManagementSOPClass, "RETIRED_StudyComponentManagementSOPClass" }, + { UID_VerificationSOPClass, "VerificationSOPClass" }, + + // Mapping Resources + { UID_DICOMContentMappingResource, "DICOMContentMappingResource" }, + + // Coding Schemes + { UID_DICOMControlledTerminologyCodingScheme, "DICOMControlledTerminologyCodingScheme" }, + { UID_DICOMUIDRegistryCodingScheme, "DICOMUIDRegistryCodingScheme" }, + + // Configuration Management LDAP UIDs + { UID_LDAP_dicomAETitle, "LDAP_dicomAETitle" }, + { UID_LDAP_dicomApplicationCluster, "LDAP_dicomApplicationCluster" }, + { UID_LDAP_dicomAssociationAcceptor, "LDAP_dicomAssociationAcceptor" }, + { UID_LDAP_dicomAssociationInitiator, "LDAP_dicomAssociationInitiator" }, + { UID_LDAP_dicomAuthorizedNodeCertificateReference, "LDAP_dicomAuthorizedNodeCertificateReference" }, + { UID_LDAP_dicomConfigurationRoot, "LDAP_dicomConfigurationRoot" }, + { UID_LDAP_dicomDescription, "LDAP_dicomDescription" }, + { UID_LDAP_dicomDevice, "LDAP_dicomDevice" }, + { UID_LDAP_dicomDeviceName, "LDAP_dicomDeviceName" }, + { UID_LDAP_dicomDeviceSerialNumber, "LDAP_dicomDeviceSerialNumber" }, + { UID_LDAP_dicomDevicesRoot, "LDAP_dicomDevicesRoot" }, + { UID_LDAP_dicomHostname, "LDAP_dicomHostname" }, + { UID_LDAP_dicomInstalled, "LDAP_dicomInstalled" }, + { UID_LDAP_dicomInstitutionAddress, "LDAP_dicomInstitutionAddress" }, + { UID_LDAP_dicomInstitutionDepartmentName, "LDAP_dicomInstitutionDepartmentName" }, + { UID_LDAP_dicomInstitutionName, "LDAP_dicomInstitutionName" }, + { UID_LDAP_dicomIssuerOfPatientID, "LDAP_dicomIssuerOfPatientID" }, + { UID_LDAP_dicomManufacturer, "LDAP_dicomManufacturer" }, + { UID_LDAP_dicomManufacturerModelName, "LDAP_dicomManufacturerModelName" }, + { UID_LDAP_dicomNetworkAE, "LDAP_dicomNetworkAE" }, + { UID_LDAP_dicomNetworkConnection, "LDAP_dicomNetworkConnection" }, + { UID_LDAP_dicomNetworkConnectionReference, "LDAP_dicomNetworkConnectionReference" }, + { UID_LDAP_dicomPort, "LDAP_dicomPort" }, + { UID_LDAP_dicomPreferredCalledAETitle, "LDAP_dicomPreferredCalledAETitle" }, + { UID_LDAP_dicomPreferredCallingAETitle, "LDAP_dicomPreferredCallingAETitle" }, + { UID_LDAP_dicomPrimaryDeviceType, "LDAP_dicomPrimaryDeviceType" }, + { UID_LDAP_dicomRelatedDeviceReference, "LDAP_dicomRelatedDeviceReference" }, + { UID_LDAP_dicomSOPClass, "LDAP_dicomSOPClass" }, + { UID_LDAP_dicomSoftwareVersion, "LDAP_dicomSoftwareVersion" }, + { UID_LDAP_dicomStationName, "LDAP_dicomStationName" }, + { UID_LDAP_dicomSupportedCharacterSet, "LDAP_dicomSupportedCharacterSet" }, + { UID_LDAP_dicomTLSCyphersuite, "LDAP_dicomTLSCyphersuite" }, + { UID_LDAP_dicomThisNodeCertificateReference, "LDAP_dicomThisNodeCertificateReference" }, + { UID_LDAP_dicomTransferCapability, "LDAP_dicomTransferCapability" }, + { UID_LDAP_dicomTransferRole, "LDAP_dicomTransferRole" }, + { UID_LDAP_dicomTransferSyntax, "LDAP_dicomTransferSyntax" }, + { UID_LDAP_dicomUniqueAETitle, "LDAP_dicomUniqueAETitle" }, + { UID_LDAP_dicomUniqueAETitlesRegistryRoot, "LDAP_dicomUniqueAETitlesRegistryRoot" }, + { UID_LDAP_dicomVendorData, "LDAP_dicomVendorData" }, + + // Well-known Frame of References + { UID_ICBM452T1FrameOfReference, "ICBM452T1FrameOfReference" }, + { UID_ICBMSingleSubjectMRIFrameOfReference, "ICBMSingleSubjectMRIFrameOfReference" }, + { UID_SPM2AVG152PDFrameOfReference, "SPM2AVG152PDFrameOfReference" }, + { UID_SPM2AVG152T1FrameOfReference, "SPM2AVG152T1FrameOfReference" }, + { UID_SPM2AVG152T2FrameOfReference, "SPM2AVG152T2FrameOfReference" }, + { UID_SPM2AVG305T1FrameOfReference, "SPM2AVG305T1FrameOfReference" }, + { UID_SPM2BRAINMASKFrameOfReference, "SPM2BRAINMASKFrameOfReference" }, + { UID_SPM2CSFFrameOfReference, "SPM2CSFFrameOfReference" }, + { UID_SPM2EPIFrameOfReference, "SPM2EPIFrameOfReference" }, + { UID_SPM2FILT1FrameOfReference, "SPM2FILT1FrameOfReference" }, + { UID_SPM2GRAYFrameOfReference, "SPM2GRAYFrameOfReference" }, + { UID_SPM2PDFrameOfReference, "SPM2PDFrameOfReference" }, + { UID_SPM2PETFrameOfReference, "SPM2PETFrameOfReference" }, + { UID_SPM2SINGLESUBJT1FrameOfReference, "SPM2SINGLESUBJT1FrameOfReference" }, + { UID_SPM2SPECTFrameOfReference, "SPM2SPECTFrameOfReference" }, + { UID_SPM2T1FrameOfReference, "SPM2T1FrameOfReference" }, + { UID_SPM2T2FrameOfReference, "SPM2T2FrameOfReference" }, + { UID_SPM2TRANSMFrameOfReference, "SPM2TRANSMFrameOfReference" }, + { UID_SPM2WHITEFrameOfReference, "SPM2WHITEFrameOfReference" }, + { UID_TalairachBrainAtlasFrameOfReference, "TalairachBrainAtlasFrameOfReference" }, + + // UTC Synchronization Frame of Reference + { UID_UniversalCoordinatedTimeSynchronizationFrameOfReference, "UniversalCoordinatedTimeSynchronizationFrameOfReference" }, + + // Well-known SOP Instances for Color Palettes + { UID_HotIronColorPaletteSOPInstance, "HotIronColorPaletteSOPInstance" }, + { UID_HotMetalBlueColorPaletteSOPInstance, "HotMetalBlueColorPaletteSOPInstance" }, + { UID_PET20StepColorPaletteSOPInstance, "PET20StepColorPaletteSOPInstance" }, + { UID_PETColorPaletteSOPInstance, "PETColorPaletteSOPInstance" }, + + // Draft Supplements + { UID_DRAFT_RTBeamsDeliveryInstructionStorage, "DRAFT_RTBeamsDeliveryInstructionStorage" }, + { UID_DRAFT_RTConventionalMachineVerification, "DRAFT_RTConventionalMachineVerification" }, + { UID_DRAFT_RTIonMachineVerification, "DRAFT_RTIonMachineVerification" }, + { UID_DRAFT_SRAudioStorage, "DRAFT_SRAudioStorage" }, + { UID_DRAFT_SRComprehensiveStorage, "DRAFT_SRComprehensiveStorage" }, + { UID_DRAFT_SRDetailStorage, "DRAFT_SRDetailStorage" }, + { UID_DRAFT_SRTextStorage, "DRAFT_SRTextStorage" }, + { UID_DRAFT_WaveformStorage, "DRAFT_WaveformStorage" }, + { UID_DRAFT_UnifiedWorklistAndProcedureStepServiceClass, "DRAFT_UnifiedWorklistAndProcedureStepServiceClass" }, + { UID_DRAFT_UnifiedProcedureStepPushSOPClass, "DRAFT_UnifiedProcedureStepPushSOPClass" }, + { UID_DRAFT_UnifiedProcedureStepWatchSOPClass, "DRAFT_UnifiedProcedureStepWatchSOPClass" }, + { UID_DRAFT_UnifiedProcedureStepPullSOPClass, "DRAFT_UnifiedProcedureStepPullSOPClass" }, + { UID_DRAFT_UnifiedProcedureStepEventSOPClass, "DRAFT_UnifiedProcedureStepEventSOPClass" }, + + { NULL, NULL } +}; + +static const int uidNameMap_size = OFstatic_cast(int, sizeof(uidNameMap) / sizeof(UIDNameMap)); + + +/** an array of const strings containing all known Storage SOP Classes + * that fit into the conventional PATIENT-STUDY-SERIES-INSTANCE information + * model, i.e. everything a Storage SCP might want to store in a PACS. + * Special cases such as hanging protocol storage or the Storage SOP Class + * are not included in this list. + * + * THIS LIST CONTAINS ALL STORAGE SOP CLASSES INCLUDING RETIRED ONES + * AND IS (MUCH) LARGER THAN 64 ENTRIES. + */ + +const char* dcmAllStorageSOPClassUIDs[] = { + UID_AmbulatoryECGWaveformStorage, + UID_ArterialPulseWaveformStorage, + UID_AutorefractionMeasurementsStorage, + UID_BasicStructuredDisplayStorage, + UID_BasicTextSRStorage, + UID_BasicVoiceAudioWaveformStorage, + UID_BlendingSoftcopyPresentationStateStorage, + UID_BreastProjectionXRayImageStorageForPresentation, + UID_BreastProjectionXRayImageStorageForProcessing, + UID_BreastTomosynthesisImageStorage, + UID_CardiacElectrophysiologyWaveformStorage, + UID_ChestCADSRStorage, + UID_ColonCADSRStorage, + UID_ColorSoftcopyPresentationStateStorage, + UID_CompositingPlanarMPRVolumetricPresentationStateStorage, + UID_Comprehensive3DSRStorage, + UID_ComprehensiveSRStorage, + UID_ComputedRadiographyImageStorage, + UID_CornealTopographyMapStorage, + UID_CTImageStorage, + UID_DeformableSpatialRegistrationStorage, + UID_DigitalIntraOralXRayImageStorageForPresentation, + UID_DigitalIntraOralXRayImageStorageForProcessing, + UID_DigitalMammographyXRayImageStorageForPresentation, + UID_DigitalMammographyXRayImageStorageForProcessing, + UID_DigitalXRayImageStorageForPresentation, + UID_DigitalXRayImageStorageForProcessing, + UID_EncapsulatedCDAStorage, + UID_EncapsulatedPDFStorage, + UID_EnhancedCTImageStorage, + UID_EnhancedMRColorImageStorage, + UID_EnhancedMRImageStorage, + UID_EnhancedPETImageStorage, + UID_EnhancedSRStorage, + UID_EnhancedUSVolumeStorage, + UID_EnhancedXAImageStorage, + UID_EnhancedXRFImageStorage, + UID_ExtensibleSRStorage, + UID_GeneralAudioWaveformStorage, + UID_GeneralECGWaveformStorage, + UID_GenericImplantTemplateStorage, + UID_GrayscalePlanarMPRVolumetricPresentationStateStorage, + UID_GrayscaleSoftcopyPresentationStateStorage, + UID_HemodynamicWaveformStorage, + UID_ImplantAssemblyTemplateStorage, + UID_ImplantationPlanSRDocumentStorage, + UID_ImplantTemplateGroupStorage, + UID_IntraocularLensCalculationsStorage, + UID_IntravascularOpticalCoherenceTomographyImageStorageForPresentation, + UID_IntravascularOpticalCoherenceTomographyImageStorageForProcessing, + UID_KeratometryMeasurementsStorage, + UID_KeyObjectSelectionDocumentStorage, + UID_LegacyConvertedEnhancedCTImageStorage, + UID_LegacyConvertedEnhancedMRImageStorage, + UID_LegacyConvertedEnhancedPETImageStorage, + UID_LensometryMeasurementsStorage, + UID_MacularGridThicknessAndVolumeReportStorage, + UID_MammographyCADSRStorage, + UID_MRImageStorage, + UID_MRSpectroscopyStorage, + UID_MultiframeGrayscaleByteSecondaryCaptureImageStorage, + UID_MultiframeGrayscaleWordSecondaryCaptureImageStorage, + UID_MultiframeSingleBitSecondaryCaptureImageStorage, + UID_MultiframeTrueColorSecondaryCaptureImageStorage, + UID_NuclearMedicineImageStorage, + UID_OphthalmicAxialMeasurementsStorage, + UID_OphthalmicPhotography16BitImageStorage, + UID_OphthalmicPhotography8BitImageStorage, + UID_OphthalmicThicknessMapStorage, + UID_OphthalmicTomographyImageStorage, + UID_OphthalmicVisualFieldStaticPerimetryMeasurementsStorage, + UID_ParametricMapStorage, + UID_PositronEmissionTomographyImageStorage, + UID_ProcedureLogStorage, + UID_PseudoColorSoftcopyPresentationStateStorage, + UID_RadiopharmaceuticalRadiationDoseSRStorage, + UID_RawDataStorage, + UID_RealWorldValueMappingStorage, + UID_RespiratoryWaveformStorage, + UID_RTBeamsDeliveryInstructionStorage, + UID_RTBeamsTreatmentRecordStorage, + UID_RTBrachyTreatmentRecordStorage, + UID_RTDoseStorage, + UID_RTImageStorage, + UID_RTIonBeamsTreatmentRecordStorage, + UID_RTIonPlanStorage, + UID_RTPlanStorage, + UID_RTStructureSetStorage, + UID_RTTreatmentSummaryRecordStorage, + UID_SecondaryCaptureImageStorage, + UID_SegmentationStorage, + UID_SpatialFiducialsStorage, + UID_SpatialRegistrationStorage, + UID_SpectaclePrescriptionReportStorage, + UID_StereometricRelationshipStorage, + UID_SubjectiveRefractionMeasurementsStorage, + UID_SurfaceScanMeshStorage, + UID_SurfaceScanPointCloudStorage, + UID_SurfaceSegmentationStorage, + UID_TwelveLeadECGWaveformStorage, + UID_UltrasoundImageStorage, + UID_UltrasoundMultiframeImageStorage, + UID_VideoEndoscopicImageStorage, + UID_VideoMicroscopicImageStorage, + UID_VideoPhotographicImageStorage, + UID_VisualAcuityMeasurementsStorage, + UID_VLEndoscopicImageStorage, + UID_VLMicroscopicImageStorage, + UID_VLPhotographicImageStorage, + UID_VLSlideCoordinatesMicroscopicImageStorage, + UID_VLWholeSlideMicroscopyImageStorage, + UID_WideFieldOphthalmicPhotographyStereographicProjectionImageStorage, + UID_WideFieldOphthalmicPhotography3DCoordinatesImageStorage, + UID_XAXRFGrayscaleSoftcopyPresentationStateStorage, + UID_XRay3DAngiographicImageStorage, + UID_XRay3DCraniofacialImageStorage, + UID_XRayAngiographicImageStorage, + UID_XRayRadiationDoseSRStorage, + UID_XRayRadiofluoroscopicImageStorage, + // retired + UID_RETIRED_HardcopyColorImageStorage, + UID_RETIRED_HardcopyGrayscaleImageStorage, + UID_RETIRED_NuclearMedicineImageStorage, + UID_RETIRED_StandaloneCurveStorage, + UID_RETIRED_StandaloneModalityLUTStorage, + UID_RETIRED_StandaloneOverlayStorage, + UID_RETIRED_StandalonePETCurveStorage, + UID_RETIRED_StandaloneVOILUTStorage, + UID_RETIRED_StoredPrintStorage, + UID_RETIRED_UltrasoundImageStorage, + UID_RETIRED_UltrasoundMultiframeImageStorage, + UID_RETIRED_VLImageStorage, + UID_RETIRED_VLMultiFrameImageStorage, + UID_RETIRED_XRayAngiographicBiPlaneImageStorage, + // draft + UID_DRAFT_SRAudioStorage, + UID_DRAFT_SRComprehensiveStorage, + UID_DRAFT_SRDetailStorage, + UID_DRAFT_SRTextStorage, + UID_DRAFT_WaveformStorage, + UID_DRAFT_RTBeamsDeliveryInstructionStorage, + // DICOS + UID_DICOS_CTImageStorage, + UID_DICOS_DigitalXRayImageStorageForPresentation, + UID_DICOS_DigitalXRayImageStorageForProcessing, + UID_DICOS_ThreatDetectionReportStorage, + // DICONDE + UID_DICONDE_EddyCurrentImageStorage, + UID_DICONDE_EddyCurrentMultiframeImageStorage, + NULL +}; + +const int numberOfAllDcmStorageSOPClassUIDs = OFstatic_cast(int, sizeof(dcmAllStorageSOPClassUIDs) / sizeof(const char*) - 1); + + +/* an array of const strings containing all storage SOP classes that + * are proposed by default by those Storage SCU components in DCMTK + * that always propose one presentation context for each SOP class, + * e.g. movescu or dcmqrdb. This list is guaranteed to have at most + * 120 entries (currently: 120) to leave enough room for FIND/MOVE + * presentation contexts. + */ +const char* dcmLongSCUStorageSOPClassUIDs[] = { + UID_AmbulatoryECGWaveformStorage, + UID_ArterialPulseWaveformStorage, + UID_AutorefractionMeasurementsStorage, + UID_BasicStructuredDisplayStorage, + UID_BasicTextSRStorage, + UID_BasicVoiceAudioWaveformStorage, + UID_BlendingSoftcopyPresentationStateStorage, + UID_BreastTomosynthesisImageStorage, + UID_CardiacElectrophysiologyWaveformStorage, + UID_ChestCADSRStorage, + UID_ColonCADSRStorage, + UID_ColorSoftcopyPresentationStateStorage, + UID_Comprehensive3DSRStorage, + UID_ComprehensiveSRStorage, + UID_ComputedRadiographyImageStorage, + UID_CTImageStorage, + UID_DeformableSpatialRegistrationStorage, + UID_DigitalIntraOralXRayImageStorageForPresentation, + UID_DigitalIntraOralXRayImageStorageForProcessing, + UID_DigitalMammographyXRayImageStorageForPresentation, + UID_DigitalMammographyXRayImageStorageForProcessing, + UID_DigitalXRayImageStorageForPresentation, + UID_DigitalXRayImageStorageForProcessing, + UID_EncapsulatedCDAStorage, + UID_EncapsulatedPDFStorage, + UID_EnhancedCTImageStorage, + UID_EnhancedMRColorImageStorage, + UID_EnhancedMRImageStorage, + UID_EnhancedPETImageStorage, + UID_EnhancedSRStorage, + UID_EnhancedUSVolumeStorage, + UID_EnhancedXAImageStorage, + UID_EnhancedXRFImageStorage, + UID_GeneralAudioWaveformStorage, + UID_GeneralECGWaveformStorage, + UID_GenericImplantTemplateStorage, + UID_GrayscaleSoftcopyPresentationStateStorage, + UID_HemodynamicWaveformStorage, + UID_ImplantAssemblyTemplateStorage, + UID_ImplantationPlanSRDocumentStorage, + UID_ImplantTemplateGroupStorage, + UID_IntraocularLensCalculationsStorage, + UID_IntravascularOpticalCoherenceTomographyImageStorageForPresentation, + UID_IntravascularOpticalCoherenceTomographyImageStorageForProcessing, + UID_KeratometryMeasurementsStorage, + UID_KeyObjectSelectionDocumentStorage, + UID_LensometryMeasurementsStorage, + UID_MacularGridThicknessAndVolumeReportStorage, + UID_MammographyCADSRStorage, + UID_MRImageStorage, + UID_MRSpectroscopyStorage, + UID_MultiframeGrayscaleByteSecondaryCaptureImageStorage, + UID_MultiframeGrayscaleWordSecondaryCaptureImageStorage, + UID_MultiframeSingleBitSecondaryCaptureImageStorage, + UID_MultiframeTrueColorSecondaryCaptureImageStorage, + UID_NuclearMedicineImageStorage, + UID_OphthalmicAxialMeasurementsStorage, + UID_OphthalmicPhotography16BitImageStorage, + UID_OphthalmicPhotography8BitImageStorage, + UID_OphthalmicThicknessMapStorage, + UID_OphthalmicTomographyImageStorage, + UID_OphthalmicVisualFieldStaticPerimetryMeasurementsStorage, + UID_PositronEmissionTomographyImageStorage, + UID_ProcedureLogStorage, + UID_PseudoColorSoftcopyPresentationStateStorage, + UID_RawDataStorage, + UID_RealWorldValueMappingStorage, + UID_RespiratoryWaveformStorage, + UID_RTBeamsDeliveryInstructionStorage, + UID_RTBeamsTreatmentRecordStorage, + UID_RTBrachyTreatmentRecordStorage, + UID_RTDoseStorage, + UID_RTImageStorage, + UID_RTIonBeamsTreatmentRecordStorage, + UID_RTIonPlanStorage, + UID_RTPlanStorage, + UID_RTStructureSetStorage, + UID_RTTreatmentSummaryRecordStorage, + UID_SecondaryCaptureImageStorage, + UID_SegmentationStorage, + UID_SpatialFiducialsStorage, + UID_SpatialRegistrationStorage, + UID_SpectaclePrescriptionReportStorage, + UID_StereometricRelationshipStorage, + UID_SubjectiveRefractionMeasurementsStorage, + UID_SurfaceScanMeshStorage, + UID_SurfaceScanPointCloudStorage, + UID_SurfaceSegmentationStorage, + UID_TwelveLeadECGWaveformStorage, + UID_UltrasoundImageStorage, + UID_UltrasoundMultiframeImageStorage, + UID_VideoEndoscopicImageStorage, + UID_VideoMicroscopicImageStorage, + UID_VideoPhotographicImageStorage, + UID_VisualAcuityMeasurementsStorage, + UID_VLEndoscopicImageStorage, + UID_VLMicroscopicImageStorage, + UID_VLPhotographicImageStorage, + UID_VLSlideCoordinatesMicroscopicImageStorage, + UID_VLWholeSlideMicroscopyImageStorage, + UID_XAXRFGrayscaleSoftcopyPresentationStateStorage, + UID_XRay3DAngiographicImageStorage, + UID_XRay3DCraniofacialImageStorage, + UID_XRayAngiographicImageStorage, + UID_XRayRadiationDoseSRStorage, + UID_XRayRadiofluoroscopicImageStorage, + // recently approved +// UID_BreastProjectionXRayImageStorageForPresentation, +// UID_BreastProjectionXRayImageStorageForProcessing, +// UID_CompositingPlanarMPRVolumetricPresentationStateStorage +// UID_CornealTopographyMapStorage, +// UID_ExtensibleSRStorage, +// UID_GrayscalePlanarMPRVolumetricPresentationStateStorage +// UID_LegacyConvertedEnhancedCTImageStorage, +// UID_LegacyConvertedEnhancedMRImageStorage, +// UID_LegacyConvertedEnhancedPETImageStorage, +// UID_ParametricMapStorage, +// UID_RadiopharmaceuticalRadiationDoseSRStorage, +// UID_WideFieldOphthalmicPhotographyStereographicProjectionImageStorage, +// UID_WideFieldOphthalmicPhotography3DCoordinatesImageStorage, + // retired + UID_RETIRED_HardcopyColorImageStorage, + UID_RETIRED_HardcopyGrayscaleImageStorage, + UID_RETIRED_NuclearMedicineImageStorage, + UID_RETIRED_StandaloneCurveStorage, + UID_RETIRED_StandaloneModalityLUTStorage, + UID_RETIRED_StandaloneOverlayStorage, + UID_RETIRED_StandalonePETCurveStorage, + UID_RETIRED_StandaloneVOILUTStorage, + UID_RETIRED_StoredPrintStorage, + UID_RETIRED_UltrasoundImageStorage, + UID_RETIRED_UltrasoundMultiframeImageStorage, + UID_RETIRED_VLImageStorage, + UID_RETIRED_VLMultiFrameImageStorage, + UID_RETIRED_XRayAngiographicBiPlaneImageStorage, + // draft +// UID_DRAFT_RTBeamsDeliveryInstructionStorage, +// UID_DRAFT_SRAudioStorage, +// UID_DRAFT_SRComprehensiveStorage, +// UID_DRAFT_SRDetailStorage, +// UID_DRAFT_SRTextStorage, +// UID_DRAFT_WaveformStorage, + // DICOS +// UID_DICOS_CTImageStorage, +// UID_DICOS_DigitalXRayImageStorageForPresentation, +// UID_DICOS_DigitalXRayImageStorageForProcessing, +// UID_DICOS_ThreatDetectionReportStorage, + // DICONDE +// UID_DICONDE_EddyCurrentImageStorage, +// UID_DICONDE_EddyCurrentMultiframeImageStorage, + NULL +}; + +const int numberOfDcmLongSCUStorageSOPClassUIDs = OFstatic_cast(int, sizeof(dcmLongSCUStorageSOPClassUIDs) / sizeof(const char*) - 1); + + +/** an array of const strings containing all storage SOP classes that + * are proposed by default by those Storage SCU components in DCMTK + * that always propose TWO presentation context for each SOP class, + * e.g. storescu. This list is guaranteed to have at most 64 entries. + */ +const char* dcmShortSCUStorageSOPClassUIDs[] = { + /* This list *must* be limited to 64 SOP classes or less (currently: 64). + * If we have more than 64 storage transfer syntaxes, tools such as + * storescu will fail because they attempt to negotiate two presentation + * contexts for each SOP class, and there is a total limit of 128 contexts + * for one association. + * Because of this limitation, all draft and retired storage SOP classes + * are removed from this list. We have also omitted support for some + * recently approved SOP classes. + * UID_MediaStorageDirectoryStorage should not be present in this list. + */ + UID_AmbulatoryECGWaveformStorage, + UID_BasicTextSRStorage, + UID_BasicVoiceAudioWaveformStorage, + UID_BlendingSoftcopyPresentationStateStorage, + UID_CardiacElectrophysiologyWaveformStorage, + UID_ChestCADSRStorage, + UID_ColonCADSRStorage, + UID_ColorSoftcopyPresentationStateStorage, + UID_ComprehensiveSRStorage, + UID_ComputedRadiographyImageStorage, + UID_CTImageStorage, + UID_DigitalIntraOralXRayImageStorageForPresentation, + UID_DigitalIntraOralXRayImageStorageForProcessing, + UID_DigitalMammographyXRayImageStorageForPresentation, + UID_DigitalMammographyXRayImageStorageForProcessing, + UID_DigitalXRayImageStorageForPresentation, + UID_DigitalXRayImageStorageForProcessing, + UID_EncapsulatedPDFStorage, + UID_EnhancedCTImageStorage, + UID_EnhancedMRImageStorage, + UID_EnhancedSRStorage, + UID_EnhancedXAImageStorage, + UID_EnhancedXRFImageStorage, + UID_GeneralECGWaveformStorage, + UID_GrayscaleSoftcopyPresentationStateStorage, + UID_HemodynamicWaveformStorage, + UID_KeyObjectSelectionDocumentStorage, + UID_MammographyCADSRStorage, + UID_MRImageStorage, + UID_MRSpectroscopyStorage, + UID_MultiframeGrayscaleByteSecondaryCaptureImageStorage, + UID_MultiframeGrayscaleWordSecondaryCaptureImageStorage, + UID_MultiframeSingleBitSecondaryCaptureImageStorage, + UID_MultiframeTrueColorSecondaryCaptureImageStorage, + UID_NuclearMedicineImageStorage, + UID_OphthalmicPhotography16BitImageStorage, + UID_OphthalmicPhotography8BitImageStorage, + UID_OphthalmicTomographyImageStorage, + UID_PositronEmissionTomographyImageStorage, + UID_ProcedureLogStorage, + UID_PseudoColorSoftcopyPresentationStateStorage, + UID_RawDataStorage, + UID_RealWorldValueMappingStorage, + UID_RTBeamsTreatmentRecordStorage, + UID_RTBrachyTreatmentRecordStorage, + UID_RTDoseStorage, + UID_RTImageStorage, + UID_RTPlanStorage, + UID_RTStructureSetStorage, + UID_RTTreatmentSummaryRecordStorage, + UID_SecondaryCaptureImageStorage, + UID_SpatialFiducialsStorage, + UID_SpatialRegistrationStorage, + UID_StereometricRelationshipStorage, + UID_TwelveLeadECGWaveformStorage, + UID_UltrasoundImageStorage, + UID_UltrasoundMultiframeImageStorage, + UID_VLEndoscopicImageStorage, + UID_VLMicroscopicImageStorage, + UID_VLPhotographicImageStorage, + UID_VLSlideCoordinatesMicroscopicImageStorage, + UID_XRayAngiographicImageStorage, + UID_XRayRadiationDoseSRStorage, + UID_XRayRadiofluoroscopicImageStorage, + NULL +}; + +const int numberOfDcmShortSCUStorageSOPClassUIDs = OFstatic_cast(int, sizeof(dcmShortSCUStorageSOPClassUIDs) / sizeof(const char*) - 1); + + +/* +** The global variable dcmImageSOPClassUIDs is an array of +** string pointers containing the UIDs of all known Image SOP +** Classes. The instances of SOP Classes in this list can be +** referenced from DICOMDIR IMAGE records. +** +** The dcmgpdir/dcmmkdir program uses this list to determine +** what kind of objects can be referenced from IMAGE records. +** Be _very_ careful when adding SOP Classes to this list!! +** +** The global variable numberOfDcmImageSOPClassUIDs defines the +** size of the array. +*/ +const char* dcmImageSOPClassUIDs[] = { + UID_BreastProjectionXRayImageStorageForPresentation, + UID_BreastProjectionXRayImageStorageForProcessing, + UID_BreastTomosynthesisImageStorage, + UID_ComputedRadiographyImageStorage, + UID_CTImageStorage, + UID_CornealTopographyMapStorage, + UID_DigitalIntraOralXRayImageStorageForPresentation, + UID_DigitalIntraOralXRayImageStorageForProcessing, + UID_DigitalMammographyXRayImageStorageForPresentation, + UID_DigitalMammographyXRayImageStorageForProcessing, + UID_DigitalXRayImageStorageForPresentation, + UID_DigitalXRayImageStorageForProcessing, + UID_EnhancedCTImageStorage, + UID_EnhancedMRColorImageStorage, + UID_EnhancedMRImageStorage, + UID_EnhancedPETImageStorage, + UID_EnhancedUSVolumeStorage, + UID_EnhancedXAImageStorage, + UID_EnhancedXRFImageStorage, + UID_IntravascularOpticalCoherenceTomographyImageStorageForPresentation, + UID_IntravascularOpticalCoherenceTomographyImageStorageForProcessing, + UID_LegacyConvertedEnhancedCTImageStorage, + UID_LegacyConvertedEnhancedMRImageStorage, + UID_LegacyConvertedEnhancedPETImageStorage, + UID_MRImageStorage, + UID_MultiframeGrayscaleByteSecondaryCaptureImageStorage, + UID_MultiframeGrayscaleWordSecondaryCaptureImageStorage, + UID_MultiframeSingleBitSecondaryCaptureImageStorage, + UID_MultiframeTrueColorSecondaryCaptureImageStorage, + UID_NuclearMedicineImageStorage, + UID_OphthalmicPhotography16BitImageStorage, + UID_OphthalmicPhotography8BitImageStorage, + UID_OphthalmicThicknessMapStorage, + UID_OphthalmicTomographyImageStorage, + UID_ParametricMapStorage, + UID_PositronEmissionTomographyImageStorage, + UID_RTImageStorage, + UID_SecondaryCaptureImageStorage, + UID_UltrasoundImageStorage, + UID_UltrasoundMultiframeImageStorage, + UID_VideoEndoscopicImageStorage, + UID_VideoMicroscopicImageStorage, + UID_VideoPhotographicImageStorage, + UID_VLEndoscopicImageStorage, + UID_VLMicroscopicImageStorage, + UID_VLPhotographicImageStorage, + UID_VLSlideCoordinatesMicroscopicImageStorage, + UID_VLWholeSlideMicroscopyImageStorage, + UID_WideFieldOphthalmicPhotographyStereographicProjectionImageStorage, + UID_WideFieldOphthalmicPhotography3DCoordinatesImageStorage, + UID_XRay3DAngiographicImageStorage, + UID_XRay3DCraniofacialImageStorage, + UID_XRayAngiographicImageStorage, + UID_XRayRadiofluoroscopicImageStorage, + // retired + UID_RETIRED_HardcopyColorImageStorage, + UID_RETIRED_HardcopyGrayscaleImageStorage, + UID_RETIRED_NuclearMedicineImageStorage, + UID_RETIRED_UltrasoundImageStorage, + UID_RETIRED_UltrasoundMultiframeImageStorage, + UID_RETIRED_VLImageStorage, + UID_RETIRED_VLMultiFrameImageStorage, + UID_RETIRED_XRayAngiographicBiPlaneImageStorage, + // DICOS + UID_DICOS_CTImageStorage, + UID_DICOS_DigitalXRayImageStorageForPresentation, + UID_DICOS_DigitalXRayImageStorageForProcessing, + // DICONDE + UID_DICONDE_EddyCurrentImageStorage, + UID_DICONDE_EddyCurrentMultiframeImageStorage, + NULL +}; + +const int numberOfDcmImageSOPClassUIDs = OFstatic_cast(int, sizeof(dcmImageSOPClassUIDs) / sizeof(const char*) - 1); + + +typedef struct { + const char *sopClass; + const char *modality; + unsigned long averageSize; /* can be way, way out */ +} DcmModalityTable; + +/* +** The modalities table defines a short character code for each +** Storage SOP Class for use in filenames. +** It also gives a typical size for each SOP Instance. This will +** usually be way out, but is useful in user interfaces to give an +** idea of progress when receiving an image (C-STORE does not indicate +** the size of an image being transmitted). +*/ +static const DcmModalityTable modalities[] = { + { UID_AmbulatoryECGWaveformStorage, "ECA", 4096 }, + { UID_ArterialPulseWaveformStorage, "WVa", 4096 }, + { UID_AutorefractionMeasurementsStorage, "OPa", 4096 }, + { UID_BasicStructuredDisplayStorage, "SD", 4096 }, + { UID_BasicTextSRStorage, "SRt", 4096 }, + { UID_BasicVoiceAudioWaveformStorage, "AUV", 4096 }, + { UID_BlendingSoftcopyPresentationStateStorage, "PSb", 4096 }, + { UID_BreastProjectionXRayImageStorageForPresentation, "BX", 4096 * 4096 * 2 }, + { UID_BreastProjectionXRayImageStorageForProcessing, "BP", 4096 * 4096 * 2 }, + { UID_BreastTomosynthesisImageStorage, "BT", 4096 * 4096 * 2 }, + { UID_CardiacElectrophysiologyWaveformStorage, "WVc", 4096 }, + { UID_ChestCADSRStorage, "SRh", 4096 }, + { UID_ColonCADSRStorage, "SRo", 4096 }, + { UID_ColorSoftcopyPresentationStateStorage, "PSc", 4096 }, + { UID_CompositingPlanarMPRVolumetricPresentationStateStorage, "VPc", 4096 }, + { UID_Comprehensive3DSRStorage, "SR3", 4096 }, + { UID_ComprehensiveSRStorage, "SRc", 4096 }, + { UID_ComputedRadiographyImageStorage, "CR", 2048 * 2048 * 2 }, + { UID_CornealTopographyMapStorage, "CM", 512 * 512 }, + { UID_CTImageStorage, "CT", 512 * 512 * 2 }, + { UID_DeformableSpatialRegistrationStorage, "RGd", 4096 }, + { UID_DigitalIntraOralXRayImageStorageForPresentation, "DXo", 1024 * 1024 * 2 }, + { UID_DigitalIntraOralXRayImageStorageForProcessing, "DPo", 1024 * 1024 * 2 }, + { UID_DigitalMammographyXRayImageStorageForPresentation, "DXm", 4096 * 4096 * 2 }, + { UID_DigitalMammographyXRayImageStorageForProcessing, "DPm", 4096 * 4096 * 2 }, + { UID_DigitalXRayImageStorageForPresentation, "DX", 2048 * 2048 * 2 }, + { UID_DigitalXRayImageStorageForProcessing, "DP", 2048 * 2048 * 2 }, + { UID_EncapsulatedCDAStorage, "CDA", 4096 }, + { UID_EncapsulatedPDFStorage, "PDF", 1024 * 1024 }, + { UID_EnhancedCTImageStorage, "CTe", 256 * 512 * 512 }, + { UID_EnhancedMRColorImageStorage, "MRc", 256 * 512 * 512 * 3 }, + { UID_EnhancedMRImageStorage, "MRe", 256 * 512 * 512 }, + { UID_EnhancedPETImageStorage, "PIe", 512 * 512 * 2 }, + { UID_EnhancedSRStorage, "SRe", 4096 }, + { UID_EnhancedUSVolumeStorage, "USe", 512 * 512 }, + { UID_EnhancedXAImageStorage, "XAe", 256 * 512 * 512 }, + { UID_EnhancedXRFImageStorage, "RFe", 256 * 512 * 512 }, + { UID_ExtensibleSRStorage, "SRx", 4096 }, + { UID_GeneralAudioWaveformStorage, "AUG", 4096 }, + { UID_GeneralECGWaveformStorage, "ECG", 4096 }, + { UID_GenericImplantTemplateStorage, "IT", 4096 }, + { UID_GrayscalePlanarMPRVolumetricPresentationStateStorage, "VPg", 4096 }, + { UID_GrayscaleSoftcopyPresentationStateStorage, "PSg", 4096 }, + { UID_HemodynamicWaveformStorage, "WVh", 4096 }, + { UID_ImplantAssemblyTemplateStorage, "ITa", 4096 }, + { UID_ImplantationPlanSRDocumentStorage, "SRi", 4096 }, + { UID_ImplantTemplateGroupStorage, "ITg", 4096 }, + { UID_IntraocularLensCalculationsStorage, "OPc", 4096 }, + { UID_IntravascularOpticalCoherenceTomographyImageStorageForPresentation, "OCt", 512 * 512 }, + { UID_IntravascularOpticalCoherenceTomographyImageStorageForProcessing, "OCp", 512 * 512 }, + { UID_KeratometryMeasurementsStorage, "OPk", 4096 }, + { UID_KeyObjectSelectionDocumentStorage, "KO", 4096 }, + { UID_LegacyConvertedEnhancedCTImageStorage, "CTl", 512 * 512 * 2 }, + { UID_LegacyConvertedEnhancedMRImageStorage, "MRl", 256 * 256 * 2 }, + { UID_LegacyConvertedEnhancedPETImageStorage, "PIl", 512 * 512 * 2 }, + { UID_LensometryMeasurementsStorage, "OPl", 4096 }, + { UID_MacularGridThicknessAndVolumeReportStorage, "SRg", 4096 }, + { UID_MammographyCADSRStorage, "SRm", 4096 }, + { UID_MRImageStorage, "MR", 256 * 256 * 2 }, + { UID_MRSpectroscopyStorage, "MRs", 256 * 512 * 512 }, + { UID_MultiframeGrayscaleByteSecondaryCaptureImageStorage, "SCb", 512 * 512 }, + { UID_MultiframeGrayscaleWordSecondaryCaptureImageStorage, "SCw", 512 * 512 * 2 }, + { UID_MultiframeSingleBitSecondaryCaptureImageStorage, "SCs", 1024 * 1024 }, /* roughly an A4 300dpi scan */ + { UID_MultiframeTrueColorSecondaryCaptureImageStorage, "SCc", 512 * 512 * 3 }, + { UID_NuclearMedicineImageStorage, "NM", 64 * 64 * 2 }, + { UID_OphthalmicAxialMeasurementsStorage, "OPx", 4096 }, + { UID_OphthalmicPhotography16BitImageStorage, "OPw", 768 * 576 * 6 }, + { UID_OphthalmicPhotography8BitImageStorage, "OPb", 768 * 576 * 3 }, + { UID_OphthalmicThicknessMapStorage, "OPm", 768 * 576 }, + { UID_OphthalmicTomographyImageStorage, "OPt", 768 * 576 * 3 }, + { UID_OphthalmicVisualFieldStaticPerimetryMeasurementsStorage, "OPp", 4096 }, + { UID_ParametricMapStorage, "PM", 256 * 256 * 4 }, + { UID_PositronEmissionTomographyImageStorage, "PI", 512 * 512 * 2 }, + { UID_ProcedureLogStorage, "SRp", 4096 }, + { UID_PseudoColorSoftcopyPresentationStateStorage, "PSp", 4096 }, + { UID_RadiopharmaceuticalRadiationDoseSRStorage, "SRr", 4096 }, + { UID_RawDataStorage, "RAW", 512 * 512 * 256 }, + { UID_RealWorldValueMappingStorage, "RWM", 4096 }, + { UID_RespiratoryWaveformStorage, "WVr", 4096 }, + { UID_RTBeamsDeliveryInstructionStorage, "RTd", 4096 }, + { UID_RTBeamsTreatmentRecordStorage, "RTb", 4096 }, + { UID_RTBrachyTreatmentRecordStorage, "RTr", 4096 }, + { UID_RTDoseStorage, "RD", 4096 }, + { UID_RTImageStorage, "RI", 4096 }, + { UID_RTIonBeamsTreatmentRecordStorage, "RTi", 4096 }, + { UID_RTIonPlanStorage, "RPi", 4096 }, + { UID_RTPlanStorage, "RP" , 4096 }, + { UID_RTStructureSetStorage, "RS", 4096 }, + { UID_RTTreatmentSummaryRecordStorage, "RTs", 4096 }, + { UID_SecondaryCaptureImageStorage, "SC", 512 * 512 * 2 }, + { UID_SegmentationStorage, "SG", 4096 }, + { UID_SpatialFiducialsStorage, "FID", 4096 }, + { UID_SpatialRegistrationStorage, "RGs", 4096 }, + { UID_SpectaclePrescriptionReportStorage, "SRs", 4096 }, + { UID_StereometricRelationshipStorage, "OPr", 4096 }, + { UID_SubjectiveRefractionMeasurementsStorage, "OPs", 4096 }, + { UID_SurfaceScanMeshStorage, "SSm", 4096 }, + { UID_SurfaceScanPointCloudStorage, "SSp", 4096 }, + { UID_SurfaceSegmentationStorage, "SGs", 4096 }, + { UID_TwelveLeadECGWaveformStorage, "TLE", 4096 }, + { UID_UltrasoundImageStorage, "US", 512 * 512 }, + { UID_UltrasoundMultiframeImageStorage, "USm", 512 * 512 }, + { UID_VideoEndoscopicImageStorage, "VVe", 768 * 576 * 3 }, + { UID_VideoMicroscopicImageStorage, "VVm", 768 * 576 * 3 }, + { UID_VideoPhotographicImageStorage, "VVp", 768 * 576 * 3 }, + { UID_VisualAcuityMeasurementsStorage, "OPv", 4096 }, + { UID_VLEndoscopicImageStorage, "VLe", 768 * 576 * 3 }, + { UID_VLMicroscopicImageStorage, "VLm", 768 * 576 * 3 }, + { UID_VLPhotographicImageStorage, "VLp", 768 * 576 * 3 }, + { UID_VLSlideCoordinatesMicroscopicImageStorage, "VLs", 768 * 576 * 3 }, + { UID_VLWholeSlideMicroscopyImageStorage, "VLw", 10000 * 10000 * 3}, + { UID_WideFieldOphthalmicPhotographyStereographicProjectionImageStorage, "OWs", 768 * 576 * 3 }, + { UID_WideFieldOphthalmicPhotography3DCoordinatesImageStorage, "OW3", 768 * 576 * 3 }, + { UID_XAXRFGrayscaleSoftcopyPresentationStateStorage, "PSx", 4096 }, + { UID_XRay3DAngiographicImageStorage, "XA3", 256 * 512 * 512 }, + { UID_XRay3DCraniofacialImageStorage, "XC3", 256 * 512 * 512 }, + { UID_XRayAngiographicImageStorage, "XA", 256 * 512 * 512 }, + { UID_XRayRadiationDoseSRStorage, "SRd", 4096 }, + { UID_XRayRadiofluoroscopicImageStorage, "RF", 256 * 512 * 512 }, + // retired + { UID_RETIRED_HardcopyColorImageStorage, "HC", 4096 }, + { UID_RETIRED_HardcopyGrayscaleImageStorage, "HG", 4096 }, + { UID_RETIRED_NuclearMedicineImageStorage, "NMr", 64 * 64 * 2 }, + { UID_RETIRED_StandaloneCurveStorage, "CV", 4096 }, + { UID_RETIRED_StandaloneModalityLUTStorage, "ML", 4096 * 2 }, + { UID_RETIRED_StandaloneOverlayStorage, "OV", 512 * 512 }, + { UID_RETIRED_StandalonePETCurveStorage, "PC", 4096 }, + { UID_RETIRED_StandaloneVOILUTStorage, "VO", 4096 * 2 }, + { UID_RETIRED_StoredPrintStorage, "SP", 4096 }, + { UID_RETIRED_UltrasoundImageStorage, "USr", 512 * 512 }, + { UID_RETIRED_UltrasoundMultiframeImageStorage, "USf", 512 * 512 }, + { UID_RETIRED_VLImageStorage, "VLr", 768 * 576 * 3 }, + { UID_RETIRED_VLMultiFrameImageStorage, "VMr", 768 * 576 * 3 }, + { UID_RETIRED_XRayAngiographicBiPlaneImageStorage, "XB", 512 * 512 * 2 }, + // draft + { UID_DRAFT_RTBeamsDeliveryInstructionStorage, "RBd", 4096 }, + { UID_DRAFT_SRAudioStorage, "SR_", 4096 }, /* was "SRw" */ + { UID_DRAFT_SRComprehensiveStorage, "SR_", 4096 }, /* was "SRx" */ + { UID_DRAFT_SRDetailStorage, "SR_", 4096 }, /* was "SRy" */ + { UID_DRAFT_SRTextStorage, "SR_", 4096 }, /* was "SRz" */ + { UID_DRAFT_WaveformStorage, "WVd", 4096 }, + // DICOS + { UID_DICOS_CTImageStorage, "CTs", 512 * 512 * 2 }, + { UID_DICOS_DigitalXRayImageStorageForPresentation, "DXs", 2048 * 2048 * 2 }, + { UID_DICOS_DigitalXRayImageStorageForProcessing, "DPs", 2048 * 2048 * 2 }, + { UID_DICOS_ThreatDetectionReportStorage, "TDR", 4096 }, + // DICONDE + { UID_DICONDE_EddyCurrentImageStorage, "EC", 512 * 512 }, + { UID_DICONDE_EddyCurrentMultiframeImageStorage, "ECm", 512 * 512 } +}; + +static const int numberOfDcmModalityTableEntries = OFstatic_cast(int, sizeof(modalities) / sizeof(DcmModalityTable)); + + +/* + * Public Function Prototypes + */ + + +const char *dcmSOPClassUIDToModality(const char *sopClassUID, + const char *defaultValue) +{ + if (sopClassUID == NULL) return NULL; + /* check for known SOP class */ + for (int i = 0; i < numberOfDcmModalityTableEntries; i++) + { + if (strcmp(modalities[i].sopClass, sopClassUID) == 0) return modalities[i].modality; + } + /* SOP class not found */ + return defaultValue; +} + +unsigned long dcmGuessModalityBytes(const char *sopClassUID) +{ + unsigned long nbytes = 1048576; /* default: 1 MByte */ + + if (sopClassUID == NULL) return nbytes; + + int found=0; + for (int i = 0; (!found && (i < numberOfDcmModalityTableEntries)); i++) + { + found = (strcmp(modalities[i].sopClass, sopClassUID) == 0); + if (found) nbytes = modalities[i].averageSize; + } + + return nbytes; +} + + +/* +** dcmFindNameOfUID(const char* uid) +** Return the name of a UID. +** Performs a table lookup and returns a pointer to a read-only string. +** Returns defaultValue of the UID is not known. +*/ + +const char* +dcmFindNameOfUID(const char* uid, const char* defaultValue) +{ + if (uid == NULL) return defaultValue; + for (int i = 0; i < uidNameMap_size; i++) { + if (uidNameMap[i].uid != NULL && strcmp(uid, uidNameMap[i].uid) == 0) { + return uidNameMap[i].name; + } + } + return defaultValue; +} + +// +// dcmFindUIDFromName(const char* name) +// Return the UID of a name. +// Performs a table lookup and returns a pointer to a read-only string. +// Returns NULL of the name is not known. +// + +const char* +dcmFindUIDFromName(const char* name) +{ + if (name == NULL) return NULL; + for(int i = 0; i < uidNameMap_size; i++) + { + if (uidNameMap[i].name != NULL && strcmp(name, uidNameMap[i].name) == 0) + return uidNameMap[i].uid; + } + return NULL; +} + + +/* +** dcmIsaStorageSOPClassUID(const char* uid) +** Returns true if the uid is one of the Storage SOP Classes. +** Performs a table lookup in the dcmAllStorageSOPClassUIDs table. +*/ +OFBool +dcmIsaStorageSOPClassUID(const char* uid) +{ + if (uid == NULL) return OFFalse; + for (int i = 0; i < numberOfAllDcmStorageSOPClassUIDs; i++) { + if (dcmAllStorageSOPClassUIDs[i] != NULL && strcmp(uid, dcmAllStorageSOPClassUIDs[i]) == 0) { + return OFTrue; + } + } + return OFFalse; +} + + +/* +** dcmIsImageStorageSOPClassUID(const char* uid) +** Returns true if the uid is one of the Image Storage SOP Classes. +** Performs a table lookup in the dcmImageSOPClassUIDs table. +*/ +OFBool +dcmIsImageStorageSOPClassUID(const char* uid) +{ + if (uid == NULL) return OFFalse; + for (int i = 0; i < numberOfDcmImageSOPClassUIDs; i++) { + if (dcmImageSOPClassUIDs[i] != NULL && strcmp(uid, dcmImageSOPClassUIDs[i]) == 0) { + return OFTrue; + } + } + return OFFalse; +} + +// ******************************** + +#ifndef HAVE_GETHOSTID +#if defined(HAVE_SYSINFO) && defined(HAVE_SYS_SYSTEMINFO_H) + +#include +static long gethostid(void) +{ + char buf[256]; + if (sysinfo(SI_HW_SERIAL, buf, 128) == -1) { + DCMDATA_FATAL("sysinfo: " << OFStandard::strerror(errno, buf, sizeof(buf))); + exit(1); + } +#ifdef HAVE_STRTOUL + return(strtoul(buf, NULL, 0)); +#else + long result; + sscanf(buf, "%ld", &result); + return result; +#endif +} + +#else // !HAVE_SYSINFO + +/* +** There is no implementation of gethostid() and we cannot implement it in +** terms of sysinfo() so define a workaround. +*/ +#if (defined(HAVE_GETHOSTNAME) && defined(HAVE_GETHOSTBYNAME)) || defined(HAVE_WINDOWS_H) + +// 16K should be large enough to handle everything pointed to by a struct hostent +#define GETHOSTBYNAME_R_BUFSIZE 16384 + +/* On Windows systems specify a routine to determine the MAC address of the Ethernet adapter */ +/* Special handling for MinGW which does not yet (as of MinGW 2.0) support snmp.h */ +#if defined(HAVE_WINDOWS_H) && !defined(__MINGW32__) + +#include + +// Visual C++ prior to version 6 declared different type names +// in , so we need to define a mapping +#if _MSC_VER < 1200 +typedef RFC1157VarBind SnmpVarBind; +typedef RFC1157VarBindList SnmpVarBindList; +typedef AsnInteger AsnInteger32; +#define SNMP_PDU_GETNEXT ASN_RFC1157_GETNEXTREQUEST +#endif + + +typedef int(WINAPI *pSnmpUtilOidCpy) ( + OUT AsnObjectIdentifier *pOidDst, + IN AsnObjectIdentifier *pOidSrc); + +typedef int(WINAPI *pSnmpUtilOidNCmp) ( + IN AsnObjectIdentifier *pOid1, + IN AsnObjectIdentifier *pOid2, + IN UINT nSubIds); + +typedef void(WINAPI *pSnmpUtilVarBindFree) ( + IN OUT SnmpVarBind *pVb); + +typedef bool(WINAPI *pSnmpExtensionInit) ( + IN DWORD dwTimeZeroReference, + OUT HANDLE *hPollForTrapEvent, + OUT AsnObjectIdentifier *supportedView); + +typedef bool(WINAPI *pSnmpExtensionTrap) ( + OUT AsnObjectIdentifier *enterprise, + OUT AsnInteger32 *genericTrap, + OUT AsnInteger32 *specificTrap, + OUT AsnTimeticks *timeStamp, + OUT SnmpVarBindList *variableBindings); + +typedef bool(WINAPI *pSnmpExtensionQuery) ( + IN BYTE requestType, + IN OUT SnmpVarBindList *variableBindings, + OUT AsnInteger32 *errorStatus, + OUT AsnInteger32 *errorIndex); + +typedef bool(WINAPI *pSnmpExtensionInitEx) ( + OUT AsnObjectIdentifier *supportedView); + +typedef struct _ASTAT_ +{ + ADAPTER_STATUS adapt; + NAME_BUFFER NameBuff[30]; +} ASTAT, *PASTAT; + +/* get the MAC address of the (first) Ethernet adapter (6 bytes) */ +static unsigned char *getMACAddress(unsigned char buffer[6]) +{ + OFBool success = OFFalse; + /* init return variable */ + memzero(buffer, 6 * sizeof(unsigned char)); + NCB ncb; + memzero(&ncb, sizeof(ncb)); + /* reset the LAN adapter */ + ncb.ncb_command = NCBRESET; + /* it is considered bad practice to hardcode the LANA number (should enumerate + adapters first), but at least this approach also works on Windows 9x */ + ncb.ncb_lana_num = 0; + if (Netbios(&ncb) == NRC_GOODRET) + { + ASTAT Adapter; + /* prepare to get the adapter status block */ + memzero(&ncb, sizeof(ncb)); + ncb.ncb_command = NCBASTAT; + /* it is considered bad practice to hardcode the LANA number (should enumerate + adapters first), but at least this approach also works on Windows 9x */ + ncb.ncb_lana_num = 0; + strcpy((char *)ncb.ncb_callname, "*"); + ncb.ncb_buffer = (unsigned char *)&Adapter; + ncb.ncb_length = sizeof(Adapter); + /* get the adapter's info */ + if (Netbios(&ncb) == 0) + { + /* store the MAC address */ + buffer[0] = Adapter.adapt.adapter_address[0]; + buffer[1] = Adapter.adapt.adapter_address[1]; + buffer[2] = Adapter.adapt.adapter_address[2]; + buffer[3] = Adapter.adapt.adapter_address[3]; + buffer[4] = Adapter.adapt.adapter_address[4]; + buffer[5] = Adapter.adapt.adapter_address[5]; + success = OFTrue; + } + } + /* check whether NetBIOS routines succeeded, if not try the SNMP approach */ + if (!success) + { + HINSTANCE m_hInst1, m_hInst2; + /* load the "SNMP Utility Library" dll and get the addresses of the functions necessary */ + m_hInst1 = LoadLibrary("snmpapi.dll"); + if (m_hInst1 >= (HINSTANCE)HINSTANCE_ERROR) + { + pSnmpUtilOidCpy m_Copy = (pSnmpUtilOidCpy)GetProcAddress(m_hInst1, "SnmpUtilOidCpy"); + pSnmpUtilOidNCmp m_Compare = (pSnmpUtilOidNCmp)GetProcAddress(m_hInst1, "SnmpUtilOidNCmp"); + pSnmpUtilVarBindFree m_BindFree = (pSnmpUtilVarBindFree)GetProcAddress(m_hInst1, "SnmpUtilVarBindFree"); + /* load the "SNMP Internet MIB" dll and get the addresses of the functions necessary */ + m_hInst2 = LoadLibrary("inetmib1.dll"); + if (m_hInst2 >= (HINSTANCE)HINSTANCE_ERROR) + { + HANDLE PollForTrapEvent; + AsnObjectIdentifier SupportedView; + UINT OID_ifEntryType[] = {1, 3, 6, 1, 2, 1, 2, 2, 1, 3}; + UINT OID_ifEntryNum[] = {1, 3, 6, 1, 2, 1, 2, 1}; + UINT OID_ipMACEntAddr[] = {1, 3, 6, 1, 2, 1, 2, 2, 1, 6}; + AsnObjectIdentifier MIB_ifMACEntAddr = {sizeof(OID_ipMACEntAddr) / sizeof(UINT), OID_ipMACEntAddr}; + AsnObjectIdentifier MIB_ifEntryType = {sizeof(OID_ifEntryType) / sizeof(UINT), OID_ifEntryType}; + AsnObjectIdentifier MIB_ifEntryNum = {sizeof(OID_ifEntryNum) / sizeof(UINT), OID_ifEntryNum}; + SnmpVarBindList varBindList; + SnmpVarBind varBind[2]; + AsnInteger32 errorStatus; + AsnInteger32 errorIndex; + AsnObjectIdentifier MIB_NULL = {0, 0}; + int ret; + int dtmp; + int j = 0; + pSnmpExtensionInit m_Init = (pSnmpExtensionInit)GetProcAddress(m_hInst2, "SnmpExtensionInit"); + /* pSnmpExtensionInitEx m_InitEx = (pSnmpExtensionInitEx)GetProcAddress(m_hInst2, "SnmpExtensionInitEx"); */ + pSnmpExtensionQuery m_Query = (pSnmpExtensionQuery)GetProcAddress(m_hInst2, "SnmpExtensionQuery"); + /* pSnmpExtensionTrap m_Trap = (pSnmpExtensionTrap)GetProcAddress(m_hInst2, "SnmpExtensionTrap"); */ + m_Init(GetTickCount(), &PollForTrapEvent, &SupportedView); + /* initialize the variable list to be retrieved by m_Query */ + varBindList.list = varBind; + varBind[0].name = MIB_NULL; + varBind[1].name = MIB_NULL; + /* copy in the OID to find the number of entries in the interface table */ + varBindList.len = 1; /* only retrieving one item */ + m_Copy(&varBind[0].name, &MIB_ifEntryNum); + ret = m_Query(SNMP_PDU_GETNEXT, &varBindList, &errorStatus, &errorIndex); + varBindList.len = 2; + /* copy in the OID of ifType, the type of interface */ + m_Copy(&varBind[0].name, &MIB_ifEntryType); + /* copy in the OID of ifPhysAddress, the address */ + m_Copy(&varBind[1].name, &MIB_ifMACEntAddr); + do { + /* Submit the query. Responses will be loaded into varBindList. + We can expect this call to succeed a # of times corresponding + to the # of adapters reported to be in the system */ + ret = m_Query(SNMP_PDU_GETNEXT, &varBindList, &errorStatus, &errorIndex); + if (!ret) + ret = 1; + else + { + /* confirm that the proper type has been returned */ + ret = m_Compare(&varBind[0].name, &MIB_ifEntryType, MIB_ifEntryType.idLength); + } + if (!ret) + { + j++; + dtmp = varBind[0].value.asnValue.number; + /* type 6 describes ethernet interfaces */ + if (dtmp == 6) + { + /* confirm that we have an address here */ + ret = m_Compare(&varBind[1].name, &MIB_ifMACEntAddr,MIB_ifMACEntAddr.idLength); + if ((!ret) && (varBind[1].value.asnValue.address.stream != NULL)) + { + if ((varBind[1].value.asnValue.address.stream[0] == 0x44) && + (varBind[1].value.asnValue.address.stream[1] == 0x45) && + (varBind[1].value.asnValue.address.stream[2] == 0x53) && + (varBind[1].value.asnValue.address.stream[3] == 0x54) && + (varBind[1].value.asnValue.address.stream[4] == 0x00)) + { + /* ignore all dial-up networking adapters */ + continue; + } + if ((varBind[1].value.asnValue.address.stream[0] == 0x00) && + (varBind[1].value.asnValue.address.stream[1] == 0x00) && + (varBind[1].value.asnValue.address.stream[2] == 0x00) && + (varBind[1].value.asnValue.address.stream[3] == 0x00) && + (varBind[1].value.asnValue.address.stream[4] == 0x00) && + (varBind[1].value.asnValue.address.stream[5] == 0x00)) + { + /* ignore NULL addresses returned by other network interfaces */ + continue; + } + /* store the MAC address */ + buffer[0] = varBind[1].value.asnValue.address.stream[0]; + buffer[1] = varBind[1].value.asnValue.address.stream[1]; + buffer[2] = varBind[1].value.asnValue.address.stream[2]; + buffer[3] = varBind[1].value.asnValue.address.stream[3]; + buffer[4] = varBind[1].value.asnValue.address.stream[4]; + buffer[5] = varBind[1].value.asnValue.address.stream[5]; + ret = 1; // we found an address -> exit + } + } + } + } while (!ret); /* Stop only on an error. An error will occur when we + go exhaust the list of interfaces to be examined */ + FreeLibrary(m_hInst2); + /* free the bindings */ + m_BindFree(&varBind[0]); + m_BindFree(&varBind[1]); + } + FreeLibrary(m_hInst1); + } + } + return buffer; +} +#endif + +#ifdef HAVE_PROTOTYPE_GETHOSTID +/* CW10 has a prototype but no implementation (gethostid() is already declared extern */ +long gethostid(void) +#else +static long gethostid(void) +#endif +{ + long result = 0; +#if (defined(HAVE_GETHOSTNAME) && defined(HAVE_GETHOSTBYNAME)) || defined(HAVE_WINDOWS_H) + char name[1024]; + char **p = NULL; + struct in_addr in; +#ifdef HAVE_WINSOCK_H + WSAData winSockData; + /* we need at least version 1.1 */ + WORD winSockVersionNeeded = MAKEWORD(1, 1); + WSAStartup(winSockVersionNeeded, &winSockData); +#endif + /* + ** Define the hostid to be the system's main TCP/IP address. + ** This is not perfect but it is better than nothing (i.e. using zero) + */ + if (gethostname(name, 1024) == 0) + { + if (OFStandard::OFHostent hent = OFStandard::getHostByName(name)) + { + if (!hent.h_addr_list.empty()) + { + memcpy(&in.s_addr, hent.h_addr_list.front().c_str(), sizeof(in.s_addr)); + result = OFstatic_cast(long, in.s_addr); + } + } + } +#ifdef HAVE_WINSOCK_H + WSACleanup(); +#endif +#endif /* defined(HAVE_GETHOSTNAME) && defined(HAVE_GETHOSTBYNAME) */ +/* on Windows systems determine some system specific information (e.g. MAC address) */ +#ifdef HAVE_WINDOWS_H + OFCRC32 crc; + /* get some processor specific information in addition to the MAC address */ + SYSTEM_INFO systemInfo; + GetSystemInfo(&systemInfo); + /* get volume information of the system drive */ + char systemDrive[MAX_PATH]; + DWORD serialNumber = 0; + if (GetSystemDirectory(systemDrive, OFstatic_cast(UINT, sizeof(systemDrive))) >= 0) + { + /* check for proper pathname */ + if ((strlen(systemDrive) >= 3) && (systemDrive[1] == ':') && (systemDrive[2] == '\\')) + { + /* truncate the pathname directly after the drive specification */ + systemDrive[3] = 0; + if (!GetVolumeInformation(systemDrive, NULL, 0, &serialNumber, NULL, NULL, NULL, 0)) + serialNumber = 0; + } + } + /* concatenate the host specific elements and compute a 32-bit checksum */ + crc.addBlock(&result /*ip address*/, OFstatic_cast(unsigned long, sizeof(result))); +#ifndef __MINGW32__ + /* on MinGW, getMacAddress() is not yet available. */ + unsigned char buffer[6]; + crc.addBlock(getMACAddress(buffer), sizeof(buffer)); +#endif + crc.addBlock(&serialNumber, OFstatic_cast(unsigned long, sizeof(serialNumber))); + crc.addBlock(&systemInfo.wProcessorLevel, OFstatic_cast(unsigned long, sizeof(systemInfo.wProcessorLevel))); + crc.addBlock(&systemInfo.wProcessorRevision, OFstatic_cast(unsigned long, sizeof(systemInfo.wProcessorRevision))); + crc.addBlock(&systemInfo.dwProcessorType, OFstatic_cast(unsigned long, sizeof(systemInfo.dwProcessorType))); + result = OFstatic_cast(long, crc.getCRC32()); +#endif + /* 'artificial' hostid: on Windows system a CRC32 checksum over some host specific + information (e.g. MAC address), the 4 bytes TCP/IP address otherwise. + */ + return result; +} + +#else // !(defined(HAVE_GETHOSTNAME) && defined(HAVE_GETHOSTBYNAME)) +/* +** last chance workaround if there is no other way +*/ +#ifdef HAVE_PROTOTYPE_GETHOSTID +/* CW10 has a prototype but no implementation (gethostid() is already declared extern */ +long gethostid(void) { return 0; } +#else +static long gethostid(void) { return 0; } +#endif +#endif // !(defined(HAVE_GETHOSTNAME) && defined(HAVE_GETHOSTBYNAME)) + +#endif // !HAVE_SYSINFO +#else // HAVE_GETHOSTID +#ifndef HAVE_PROTOTYPE_GETHOSTID +extern "C" { +long gethostid(void); +} +#endif // !HAVE_PROTOTYPE_GETHOSTID +#endif // HAVE_GETHOSTID + +// ******************************** + +/* + * Global variable storing the return value of gethostid(). + * Since the variable is not declared in the header file it can only be used + * within this source file. Any access to or modification of its value is + * protected by a mutex (see dcmGenerateUniqueIdentifier()). + */ + +static unsigned long hostIdentifier = 0; + + +/* +** char* generateUniqueIdentifier(char* buf) +** Creates a Unique Identifier in buf and returns buf. +** buf must be at least 65 bytes. +*/ + + +#ifdef WITH_THREADS +static OFMutex uidCounterMutex; // mutex protecting access to counterOfCurrentUID and hostIdentifier +#endif + +static unsigned int counterOfCurrentUID = 0; + +static const unsigned int maxUIDLen = 64; /* A UID may be 64 chars or less */ + +static void +initCounterOfCurrentUID() +{ + /* Code taken from oftime.cc */ +#ifdef HAVE_WINDOWS_H + /* Windows: no microseconds available, use milliseconds instead */ + SYSTEMTIME timebuf; + GetSystemTime(&timebuf); + counterOfCurrentUID = timebuf.wMilliseconds; /* This is in the range 0 - 999 */ +#else /* Unix */ + struct timeval tv; + if (gettimeofday(&tv, NULL) == 0) + counterOfCurrentUID = OFstatic_cast(Uint32, tv.tv_usec); /* This is in the range 0 - 999999 */ +#endif + /* Do not ever use "0" for the counter */ + counterOfCurrentUID++; +} + + +static char* +stripTrailing(char* s, char c) +{ + if (s == NULL) return s; + for + ( + char* it = s + strlen(s) - 1; + it >= s && *it == c; + *it-- = '\0' + ); + return s; +} + +static void +addUIDComponent(char* uid, const char* s) +{ + /* copy into UID as much of the contents of s as possible */ + if (OFStandard::strlcat(uid, s, maxUIDLen + 1) >= maxUIDLen + 1) // maxUIDLen+1 because strlcat() wants the size of the buffer, not the permitted number of characters. + { + DCMDATA_WARN("Truncated UID in dcmGenerateUniqueIdentifier(), SITE_UID_ROOT too long?"); + } + stripTrailing(uid, '.'); +} + +inline static unsigned long +forcePositive(long i) +{ + return (i < 0) ? OFstatic_cast(unsigned long, -i) : OFstatic_cast(unsigned long, i); +} + +char* dcmGenerateUniqueIdentifier(char* uid, const char* prefix) +{ + char buf[128]; /* be very safe */ + + uid[0] = '\0'; /* initialize */ + +#ifdef WITH_THREADS + uidCounterMutex.lock(); +#endif + if (hostIdentifier == 0) + { + /* On 64-bit Linux, the "32-bit identifier" returned by gethostid() is + sign-extended to a 64-bit long, so we need to blank the upper 32 bits */ + hostIdentifier = OFstatic_cast(unsigned long, gethostid() & 0xffffffff); + } + if (counterOfCurrentUID == 0) + initCounterOfCurrentUID(); + + unsigned int counter = counterOfCurrentUID++; +#ifdef WITH_THREADS + uidCounterMutex.unlock(); +#endif + + if (prefix != NULL ) { + addUIDComponent(uid, prefix); + } else { + addUIDComponent(uid, SITE_INSTANCE_UID_ROOT); + } + + sprintf(buf, ".%lu", hostIdentifier); + addUIDComponent(uid, buf); + + sprintf(buf, ".%lu", forcePositive(OFStandard::getProcessID())); + addUIDComponent(uid, buf); + + sprintf(buf, ".%lu", forcePositive(OFstatic_cast(long, time(NULL)))); + addUIDComponent(uid, buf); + + sprintf(buf, ".%u", counter); + + addUIDComponent(uid, buf); + + return uid; +} diff --git a/dcmdata/libsrc/dcvr.cc b/dcmdata/libsrc/dcvr.cc new file mode 100644 index 00000000..c09a4eae --- /dev/null +++ b/dcmdata/libsrc/dcvr.cc @@ -0,0 +1,438 @@ +/* + * + * Copyright (C) 1994-2015, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Gerd Ehlers, Andreas Barth, Andrew Hewett + * + * Purpose: class DcmVR: Value Representation + * + * + */ + + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ +#include "dcmtk/dcmdata/dcvr.h" +#include "dcmtk/dcmdata/dctypes.h" + +#define INCLUDE_CSTDLIB +#define INCLUDE_CSTRING +#include "dcmtk/ofstd/ofstdinc.h" + +/* +** global flags +*/ +OFGlobal dcmEnableUnknownVRGeneration(OFTrue); +OFGlobal dcmEnableUnlimitedTextVRGeneration(OFTrue); +OFGlobal dcmEnableOtherFloatStringVRGeneration(OFTrue); +OFGlobal dcmEnableOtherDoubleStringVRGeneration(OFTrue); +OFGlobal dcmEnableUniversalResourceIdentifierOrLocatorVRGeneration(OFTrue); +OFGlobal dcmEnableUnlimitedCharactersVRGeneration(OFTrue); +OFGlobal dcmEnableUnknownVRConversion(OFFalse); + +/* +** global functions +*/ +void dcmEnableGenerationOfNewVRs() +{ + dcmEnableUnknownVRGeneration.set(OFTrue); + dcmEnableUnlimitedTextVRGeneration.set(OFTrue); + dcmEnableOtherFloatStringVRGeneration.set(OFTrue); + dcmEnableOtherDoubleStringVRGeneration.set(OFTrue); + dcmEnableUniversalResourceIdentifierOrLocatorVRGeneration.set(OFTrue); + dcmEnableUnlimitedCharactersVRGeneration.set(OFTrue); +} + +void dcmDisableGenerationOfNewVRs() +{ + dcmEnableUnknownVRGeneration.set(OFFalse); + dcmEnableUnlimitedTextVRGeneration.set(OFFalse); + dcmEnableOtherFloatStringVRGeneration.set(OFFalse); + dcmEnableOtherDoubleStringVRGeneration.set(OFFalse); + dcmEnableUniversalResourceIdentifierOrLocatorVRGeneration.set(OFFalse); + dcmEnableUnlimitedCharactersVRGeneration.set(OFFalse); +} + + +/* +** VR property table +*/ + +#define DCMVR_PROP_NONE 0x00 +#define DCMVR_PROP_NONSTANDARD 0x01 +#define DCMVR_PROP_INTERNAL 0x02 +#define DCMVR_PROP_EXTENDEDLENGTHENCODING 0x04 +#define DCMVR_PROP_ISASTRING 0x08 + +struct DcmVREntry { + DcmEVR vr; // Enumeration Value of Value representation + const char* vrName; // Name of Value representation + size_t fValWidth; // Length of minimal unit, used for swapping + int propertyFlags; // Normal, internal, non-standard vr + Uint32 minValueLength; // Minimum length of a single value (bytes) + Uint32 maxValueLength; // Maximum length of a single value (bytes) +}; + + +static const DcmVREntry DcmVRDict[] = { + + { EVR_AE, "AE", sizeof(char), DCMVR_PROP_ISASTRING, 0, 16 }, + { EVR_AS, "AS", sizeof(char), DCMVR_PROP_ISASTRING, 4, 4 }, + { EVR_AT, "AT", sizeof(Uint16), DCMVR_PROP_NONE, 4, 4 }, + { EVR_CS, "CS", sizeof(char), DCMVR_PROP_ISASTRING, 0, 16 }, + { EVR_DA, "DA", sizeof(char), DCMVR_PROP_ISASTRING, 8, 10 }, + { EVR_DS, "DS", sizeof(char), DCMVR_PROP_ISASTRING, 0, 16 }, + { EVR_DT, "DT", sizeof(char), DCMVR_PROP_ISASTRING, 0, 26}, + { EVR_FL, "FL", sizeof(Float32), DCMVR_PROP_NONE, 4, 4 }, + { EVR_FD, "FD", sizeof(Float64), DCMVR_PROP_NONE, 8, 8 }, + { EVR_IS, "IS", sizeof(char), DCMVR_PROP_ISASTRING, 0, 12 }, + { EVR_LO, "LO", sizeof(char), DCMVR_PROP_ISASTRING, 0, 64 }, + { EVR_LT, "LT", sizeof(char), DCMVR_PROP_ISASTRING, 0, 10240 }, + { EVR_OB, "OB", sizeof(Uint8), DCMVR_PROP_EXTENDEDLENGTHENCODING, 0, DCM_UndefinedLength }, + { EVR_OD, "OD", sizeof(Float64), DCMVR_PROP_EXTENDEDLENGTHENCODING, 0, DCM_UndefinedLength }, + { EVR_OF, "OF", sizeof(Float32), DCMVR_PROP_EXTENDEDLENGTHENCODING, 0, DCM_UndefinedLength }, + { EVR_OW, "OW", sizeof(Uint16), DCMVR_PROP_EXTENDEDLENGTHENCODING, 0, DCM_UndefinedLength }, + { EVR_PN, "PN", sizeof(char), DCMVR_PROP_ISASTRING, 0, 64 }, + { EVR_SH, "SH", sizeof(char), DCMVR_PROP_ISASTRING, 0, 16 }, + { EVR_SL, "SL", sizeof(Sint32), DCMVR_PROP_NONE, 4, 4 }, + { EVR_SQ, "SQ", 0, DCMVR_PROP_EXTENDEDLENGTHENCODING, 0, DCM_UndefinedLength }, + { EVR_SS, "SS", sizeof(Sint16), DCMVR_PROP_NONE, 2, 2 }, + { EVR_ST, "ST", sizeof(char), DCMVR_PROP_ISASTRING, 0, 1024 }, + { EVR_TM, "TM", sizeof(char), DCMVR_PROP_ISASTRING, 0, 16 }, + { EVR_UC, "UC", sizeof(char), DCMVR_PROP_ISASTRING|DCMVR_PROP_EXTENDEDLENGTHENCODING, 0, DCM_UndefinedLength }, + { EVR_UI, "UI", sizeof(char), DCMVR_PROP_ISASTRING, 0, 64 }, + { EVR_UL, "UL", sizeof(Uint32), DCMVR_PROP_NONE, 4, 4 }, + { EVR_UR, "UR", sizeof(char), DCMVR_PROP_ISASTRING|DCMVR_PROP_EXTENDEDLENGTHENCODING, 0, DCM_UndefinedLength }, + { EVR_US, "US", sizeof(Uint16), DCMVR_PROP_NONE, 2, 2 }, + { EVR_UT, "UT", sizeof(char), DCMVR_PROP_ISASTRING|DCMVR_PROP_EXTENDEDLENGTHENCODING, 0, DCM_UndefinedLength }, + { EVR_ox, "ox", sizeof(Uint8), DCMVR_PROP_NONSTANDARD | DCMVR_PROP_EXTENDEDLENGTHENCODING, 0, DCM_UndefinedLength }, + { EVR_xs, "xs", sizeof(Uint16), DCMVR_PROP_NONSTANDARD, 2, 2 }, + { EVR_lt, "lt", sizeof(Uint16), DCMVR_PROP_NONSTANDARD | DCMVR_PROP_EXTENDEDLENGTHENCODING, 0, DCM_UndefinedLength }, + { EVR_na, "na", 0, DCMVR_PROP_NONSTANDARD, 0, 0 }, + { EVR_up, "up", sizeof(Uint32), DCMVR_PROP_NONSTANDARD, 4, 4 }, + + /* unique prefixes have been "invented" for the following internal VRs */ + { EVR_item, "it_EVR_item", 0, + DCMVR_PROP_NONSTANDARD | DCMVR_PROP_INTERNAL, 0, 0 }, + { EVR_metainfo, "mi_EVR_metainfo", 0, + DCMVR_PROP_NONSTANDARD | DCMVR_PROP_INTERNAL, 0, 0 }, + { EVR_dataset, "ds_EVR_dataset", 0, + DCMVR_PROP_NONSTANDARD | DCMVR_PROP_INTERNAL, 0, 0 }, + { EVR_fileFormat, "ff_EVR_fileFormat", 0, + DCMVR_PROP_NONSTANDARD | DCMVR_PROP_INTERNAL, 0, 0 }, + { EVR_dicomDir, "dd_EVR_dicomDir", 0, + DCMVR_PROP_NONSTANDARD | DCMVR_PROP_INTERNAL, 0, 0 }, + { EVR_dirRecord, "dr_EVR_dirRecord", 0, + DCMVR_PROP_NONSTANDARD | DCMVR_PROP_INTERNAL, 0, 0 }, + + { EVR_pixelSQ, "ps_EVR_pixelSQ", sizeof(Uint8), + DCMVR_PROP_NONSTANDARD | DCMVR_PROP_INTERNAL, 0, DCM_UndefinedLength }, + /* Moved from internal use to non standard only: necessary to distinguish from "normal" OB */ + { EVR_pixelItem, "pi", sizeof(Uint8), + DCMVR_PROP_NONSTANDARD, 0, DCM_UndefinedLength }, + + { EVR_UNKNOWN, "??", sizeof(Uint8), /* EVR_UNKNOWN (i.e. "future" VRs) should be mapped to UN or OB */ + DCMVR_PROP_NONSTANDARD | DCMVR_PROP_INTERNAL | DCMVR_PROP_EXTENDEDLENGTHENCODING, 0, DCM_UndefinedLength }, + + /* Unknown Value Representation */ + { EVR_UN, "UN", sizeof(Uint8), DCMVR_PROP_EXTENDEDLENGTHENCODING, 0, DCM_UndefinedLength }, + + /* Pixel Data - only used in ident() */ + { EVR_PixelData, "PixelData", 0, DCMVR_PROP_INTERNAL, 0, DCM_UndefinedLength }, + /* Overlay Data - only used in ident() */ + { EVR_OverlayData, "OverlayData", 0, DCMVR_PROP_INTERNAL, 0, DCM_UndefinedLength }, + + { EVR_UNKNOWN2B, "??", sizeof(Uint8), /* illegal VRs, we assume no extended length coding */ + DCMVR_PROP_NONSTANDARD | DCMVR_PROP_INTERNAL, 0, DCM_UndefinedLength }, + +}; + +static const int DcmVRDict_DIM = OFstatic_cast(int, sizeof(DcmVRDict) / sizeof(DcmVREntry)); + + +/* +** Check the consistency of the DcmVRDict +*/ + +#ifdef DEBUG + +#include "dcmtk/ofstd/ofstream.h" + +class DcmVRDict_checker { +private: + int error_found; +public: + DcmVRDict_checker(); +}; + +DcmVRDict_checker::DcmVRDict_checker() + : error_found(OFFalse) +{ + for (int i = 0; i < DcmVRDict_DIM; i++) { + if (DcmVRDict[i].vr != i) { + error_found = OFTrue; + DCMDATA_FATAL("DcmVRDict: Internal ERROR: inconsistent indexing: " << DcmVRDict[i].vrName); + abort(); + } + } +} + +const DcmVRDict_checker DcmVRDict_startup_check(); + +#endif + +/* +** DcmVR member functions +*/ + +void +DcmVR::setVR(DcmEVR evr) +{ + if ((OFstatic_cast(int, evr) >= 0) && (OFstatic_cast(int, evr) < DcmVRDict_DIM)) { + vr = evr; + } else { + vr = EVR_UNKNOWN; + } +} + +void +DcmVR::setVR(const char* vrName) +{ + vr = EVR_UNKNOWN; /* default */ + if (vrName != NULL) + { + int found = OFFalse; + int i = 0; + for (i = 0; (!found && (i < DcmVRDict_DIM)); i++) + { + if (strncmp(vrName, DcmVRDict[i].vrName, 2) == 0) + { + found = OFTrue; + vr = DcmVRDict[i].vr; + } + } + /* Workaround: There have been reports of systems transmitting + * illegal VR strings in explicit VR (i.e. "??") without using + * extended length fields. This is particularly bad because the + * DICOM committee has announced that all future VRs will use + * extended length. In order to distinguish between these two + * variants, we treat all unknown VRs consisting of uppercase + * letters as "real" future VRs (and thus assume extended length). + * All other VR strings are treated as "illegal" VRs. + */ + register char c1 = *vrName; + register char c2 = (c1) ? (*(vrName + 1)) : ('\0'); + if ((c1 == '?') && (c2 == '?')) vr = EVR_UNKNOWN2B; + if (!found && ((c1 < 'A') || (c1 > 'Z') || (c2 < 'A') || (c2 > 'Z'))) vr = EVR_UNKNOWN2B; + } +} + +DcmEVR +DcmVR::getValidEVR() const +{ + DcmEVR evr = EVR_UNKNOWN; + + if (isStandard()) { + evr = vr; + } else { + switch (vr) { + case EVR_up: + evr = EVR_UL; + break; + case EVR_xs: + evr = EVR_US; + break; + case EVR_lt: + evr = EVR_OW; + break; + case EVR_ox: + case EVR_pixelSQ: + evr = EVR_OB; + break; + default: + evr = EVR_UN; /* handle as Unknown VR */ + break; + } + } + + /* + ** If the generation of post-1993 VRs is not globally enabled then use OB instead. + ** We may not want to generate these "new" VRs if other software cannot handle it. + */ + DcmEVR oldVR = evr; + switch (evr) { + case EVR_UN: + if (!dcmEnableUnknownVRGeneration.get()) + evr = EVR_OB; /* handle UN as if OB */ + break; + case EVR_UT: + if (!dcmEnableUnlimitedTextVRGeneration.get()) + { + if (dcmEnableUnknownVRGeneration.get()) + evr = EVR_UN; /* handle UT as if UN */ + else + evr = EVR_OB; /* handle UT as if OB */ + } + break; + case EVR_OF: + if (!dcmEnableOtherFloatStringVRGeneration.get()) + { + if (dcmEnableUnknownVRGeneration.get()) + evr = EVR_UN; /* handle OF as if UN */ + else + evr = EVR_OB; /* handle OF as if OB */ + } + break; + case EVR_OD: + if (!dcmEnableOtherDoubleStringVRGeneration.get()) + { + if (dcmEnableUnknownVRGeneration.get()) + evr = EVR_UN; /* handle OD as if UN */ + else + evr = EVR_OB; /* handle OD as if OB */ + } + break; + case EVR_UR: + if (!dcmEnableUniversalResourceIdentifierOrLocatorVRGeneration.get()) + { + if (dcmEnableUnlimitedTextVRGeneration.get()) + evr = EVR_UT; /* handle UR as if UT */ + else if (dcmEnableUnknownVRGeneration.get()) + evr = EVR_UN; /* handle UR as if UN */ + else + evr = EVR_OB; /* handle UR as if OB */ + } + break; + case EVR_UC: + if (!dcmEnableUnlimitedCharactersVRGeneration.get()) + { + if (dcmEnableUnknownVRGeneration.get()) + evr = EVR_UN; /* handle UC as if UN */ + else + evr = EVR_OB; /* handle UC as if OB */ + } + break; + default: + /* in all other cases, do nothing */ + break; + } + if (oldVR != evr) + { + DCMDATA_TRACE("DcmVR::getValidEVR() VR=\"" << DcmVR(oldVR).getVRName() + << "\" replaced by \"" << DcmVR(evr).getVRName() << "\" since support is disabled"); + } + + return evr; +} + +size_t +DcmVR::getValueWidth(void) const +{ + return DcmVRDict[vr].fValWidth; +} + + +const char* +DcmVR::getVRName() const +{ + return DcmVRDict[vr].vrName; +} + +const char* +DcmVR::getValidVRName() const +{ + DcmVR avr(getValidEVR()); + return avr.getVRName(); +} + +OFBool +DcmVR::isStandard() const +{ + return (DcmVRDict[vr].propertyFlags & DCMVR_PROP_NONSTANDARD) ? OFFalse : OFTrue; +} + +OFBool +DcmVR::isForInternalUseOnly() const +{ + return (DcmVRDict[vr].propertyFlags & DCMVR_PROP_INTERNAL) ? OFTrue : OFFalse; +} + +/* returns true if VR represents a string */ +OFBool +DcmVR::isaString() const +{ + return (DcmVRDict[vr].propertyFlags & DCMVR_PROP_ISASTRING) ? OFTrue : OFFalse; +} + +/* + * returns true if VR uses an extended length encoding + * for explicit transfer syntaxes + */ +OFBool +DcmVR::usesExtendedLengthEncoding() const +{ + return (DcmVRDict[vr].propertyFlags & DCMVR_PROP_EXTENDEDLENGTHENCODING) ? OFTrue : OFFalse; +} + +Uint32 +DcmVR::getMinValueLength() const +{ + return (DcmVRDict[vr].minValueLength); +} + +Uint32 +DcmVR::getMaxValueLength() const +{ + return (DcmVRDict[vr].maxValueLength); +} + +/* returns true if the VR is equivalent */ +OFBool +DcmVR::isEquivalent(const DcmVR& avr) const +{ + DcmEVR evr = avr.getEVR(); + if (vr == evr) return OFTrue; + + OFBool result = OFFalse; + switch (vr) + { + case EVR_ox: + result = (evr == EVR_OB || evr == EVR_OW); + break; + case EVR_lt: + result = (evr == EVR_OW || evr == EVR_US || evr == EVR_SS); + break; + case EVR_OB: + result = (evr == EVR_ox); + break; + case EVR_OW: + result = (evr == EVR_ox || evr == EVR_lt); + break; + case EVR_up: + result = (evr == EVR_UL); + break; + case EVR_UL: + result = (evr == EVR_up); + break; + case EVR_xs: + result = (evr == EVR_SS || evr == EVR_US); + break; + case EVR_SS: + case EVR_US: + result = (evr == EVR_xs || evr == EVR_lt); + break; + default: + break; + } + return result; +} diff --git a/dcmdata/libsrc/dcvrae.cc b/dcmdata/libsrc/dcvrae.cc new file mode 100644 index 00000000..8d247acf --- /dev/null +++ b/dcmdata/libsrc/dcvrae.cc @@ -0,0 +1,115 @@ +/* + * + * Copyright (C) 1994-2010, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Gerd Ehlers, Andreas Barth + * + * Purpose: Implementation of class DcmApplicationEntity + * + */ + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/dcmdata/dcvrae.h" + + +#define MAX_AE_LENGTH 16 + + +// ******************************** + + +DcmApplicationEntity::DcmApplicationEntity(const DcmTag &tag, + const Uint32 len) + : DcmByteString(tag, len) +{ + setMaxLength(MAX_AE_LENGTH); + setNonSignificantChars(" \\"); +} + + +DcmApplicationEntity::DcmApplicationEntity(const DcmApplicationEntity &old) + : DcmByteString(old) +{ +} + + +DcmApplicationEntity::~DcmApplicationEntity() +{ +} + + +DcmApplicationEntity &DcmApplicationEntity::operator=(const DcmApplicationEntity &obj) +{ + DcmByteString::operator=(obj); + return *this; +} + + +OFCondition DcmApplicationEntity::copyFrom(const DcmObject& rhs) +{ + if (this != &rhs) + { + if (rhs.ident() != ident()) return EC_IllegalCall; + *this = OFstatic_cast(const DcmApplicationEntity &, rhs); + } + return EC_Normal; +} + + +// ******************************** + + +DcmEVR DcmApplicationEntity::ident() const +{ + return EVR_AE; +} + + +OFCondition DcmApplicationEntity::checkValue(const OFString &vm, + const OFBool /*oldFormat*/) +{ + OFString strVal; + /* get "raw value" without any modifications (if possible) */ + OFCondition l_error = getStringValue(strVal); + if (l_error.good()) + l_error = DcmApplicationEntity::checkStringValue(strVal, vm); + return l_error; +} + + +// ******************************** + + +OFCondition DcmApplicationEntity::getOFString(OFString &stringVal, + const unsigned long pos, + OFBool normalize) +{ + /* call inherited method */ + OFCondition l_error = DcmByteString::getOFString(stringVal, pos, normalize); + /* normalize string if required */ + if (l_error.good() && normalize) + normalizeString(stringVal, !MULTIPART, DELETE_LEADING, DELETE_TRAILING); + return l_error; +} + + +// ******************************** + + +OFCondition DcmApplicationEntity::checkStringValue(const OFString &value, + const OFString &vm) +{ + return DcmByteString::checkStringValue(value, vm, "ae", 13, MAX_AE_LENGTH); +} diff --git a/dcmdata/libsrc/dcvras.cc b/dcmdata/libsrc/dcvras.cc new file mode 100644 index 00000000..13d25d31 --- /dev/null +++ b/dcmdata/libsrc/dcvras.cc @@ -0,0 +1,95 @@ +/* + * + * Copyright (C) 1994-2010, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Gerd Ehlers, Andreas Barth + * + * Purpose: Implementation of class DcmAgeString + * + */ + + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/dcmdata/dcvras.h" + + +// ******************************** + + +DcmAgeString::DcmAgeString(const DcmTag &tag, + const Uint32 len) + : DcmByteString(tag, len) +{ + setMaxLength(4); +} + + +DcmAgeString::DcmAgeString(const DcmAgeString &old) + : DcmByteString(old) +{ +} + + +DcmAgeString::~DcmAgeString() +{ +} + +DcmAgeString &DcmAgeString::operator=(const DcmAgeString &obj) +{ + DcmByteString::operator=(obj); + return *this; +} + + +OFCondition DcmAgeString::copyFrom(const DcmObject& rhs) +{ + if (this != &rhs) + { + if (rhs.ident() != ident()) return EC_IllegalCall; + *this = OFstatic_cast(const DcmAgeString &, rhs); + } + return EC_Normal; +} + + +// ******************************** + + +DcmEVR DcmAgeString::ident() const +{ + return EVR_AS; +} + + +OFCondition DcmAgeString::checkValue(const OFString &vm, + const OFBool /*oldFormat*/) +{ + OFString strVal; + /* get "raw value" without any modifications (if possible) */ + OFCondition l_error = getStringValue(strVal); + if (l_error.good()) + l_error = DcmAgeString::checkStringValue(strVal, vm); + return l_error; +} + + +// ******************************** + + +OFCondition DcmAgeString::checkStringValue(const OFString &value, + const OFString &vm) +{ + return DcmByteString::checkStringValue(value, vm, "as", 1); +} diff --git a/dcmdata/libsrc/dcvrat.cc b/dcmdata/libsrc/dcvrat.cc new file mode 100644 index 00000000..32c44220 --- /dev/null +++ b/dcmdata/libsrc/dcvrat.cc @@ -0,0 +1,405 @@ +/* + * + * Copyright (C) 1994-2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Gerd Ehlers, Andreas Barth + * + * Purpose: Implementation of class DcmAttributeTag + * + */ + + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ +#include "dcmtk/ofstd/ofstream.h" +#include "dcmtk/dcmdata/dcvrat.h" + +#define INCLUDE_CSTDIO +#define INCLUDE_CSTRING +#include "dcmtk/ofstd/ofstdinc.h" + + +// ******************************** + + +DcmAttributeTag::DcmAttributeTag(const DcmTag &tag, + const Uint32 len) + : DcmElement(tag, len) +{ +} + + +DcmAttributeTag::DcmAttributeTag(const DcmAttributeTag &old) + : DcmElement(old) +{ +} + + +DcmAttributeTag::~DcmAttributeTag() +{ +} + + +DcmAttributeTag &DcmAttributeTag::operator=(const DcmAttributeTag &obj) +{ + DcmElement::operator=(obj); + return *this; +} + + +int DcmAttributeTag::compare(const DcmElement& rhs) const +{ + int result = DcmElement::compare(rhs); + if (result != 0) + { + return result; + } + + /* cast away constness (dcmdata is not const correct...) */ + DcmAttributeTag* myThis = NULL; + DcmAttributeTag* myRhs = NULL; + myThis = OFconst_cast(DcmAttributeTag*, this); + myRhs = OFstatic_cast(DcmAttributeTag*, OFconst_cast(DcmElement*, &rhs)); + + /* iterate over all components and test equality */ + unsigned long thisVM = myThis->getVM(); + for (unsigned long count = 0; count < thisVM; count++) + { + DcmTagKey val; + if (myThis->getTagVal(val, count).good()) + { + DcmTagKey rhsVal; + if (myRhs->getTagVal(rhsVal, count).good()) + { + if (val > rhsVal) + { + return 1; + } + else if (val < rhsVal) + { + return -1; + } + /* otherwise they are equal, continue comparison */ + } + else + { + break; // values equal until this point (rhs shorter) + } + } + } + + /* we get here if all values are equal. Now look at the number of components. */ + unsigned long rhsVM = myRhs->getVM(); + if (thisVM < rhsVM) + { + return -1; + } + else if (thisVM > rhsVM) + { + return 1; + } + + /* all values as well as VM equal: objects are equal */ + return 0; +} + + +OFCondition DcmAttributeTag::copyFrom(const DcmObject& rhs) +{ + if (this != &rhs) + { + if (rhs.ident() != ident()) return EC_IllegalCall; + *this = OFstatic_cast(const DcmAttributeTag &, rhs); + } + return EC_Normal; +} + + +// ******************************** + + +DcmEVR DcmAttributeTag::ident() const +{ + return EVR_AT; +} + + +OFCondition DcmAttributeTag::checkValue(const OFString &vm, + const OFBool /*oldFormat*/) +{ + /* check VM only, further checks on the attribute tags could be added later */ + return DcmElement::checkVM(getVM(), vm); +} + + +unsigned long DcmAttributeTag::getVM() +{ + /* attribute tags store pairs of 16 bit values */ + return OFstatic_cast(unsigned long, getLengthField() / (2 * sizeof(Uint16))); +} + + +// ******************************** + + +void DcmAttributeTag::print(STD_NAMESPACE ostream& out, + const size_t flags, + const int level, + const char * /*pixelFileName*/, + size_t * /*pixelCounter*/) +{ + if (valueLoaded()) + { + /* get unsigned integer data */ + Uint16 *uintVals; + errorFlag = getUint16Array(uintVals); + const unsigned long count = getVM(); + if ((uintVals != NULL) && (count > 0)) + { + /* determine number of values to be printed */ + unsigned long expectedLength = count * (11 + 1) - 1; + const unsigned long printCount = + ((expectedLength > DCM_OptPrintLineLength) && (flags & DCMTypes::PF_shortenLongTagValues)) ? + (DCM_OptPrintLineLength - 3 /* for "..." */ + 1) / (11 /* (gggg,eeee) */ + 1 /* for "\" */) : count; + unsigned long printedLength = printCount * (11 + 1) - 1; + /* print line start with tag and VR */ + printInfoLineStart(out, flags, level); + /* print multiple values */ + if (printCount > 0) + { + out << STD_NAMESPACE hex << STD_NAMESPACE setfill('0'); + /* print tag values (group,element) in hex mode */ + out << '(' << STD_NAMESPACE setw(4) << (*(uintVals++)); + out << ',' << STD_NAMESPACE setw(4) << (*(uintVals++)) << ')'; + for (unsigned long i = 1; i < printCount; i++) + { + out << "\\" << '(' << STD_NAMESPACE setw(4) << (*(uintVals++)); + out << ',' << STD_NAMESPACE setw(4) << (*(uintVals++)) << ')'; + } + /* reset i/o manipulators */ + out << STD_NAMESPACE dec << STD_NAMESPACE setfill(' '); + } + /* print trailing "..." if data has been truncated */ + if (printCount < count) + { + out << "..."; + printedLength += 3; + } + /* print line end with length, VM and tag name */ + printInfoLineEnd(out, flags, printedLength); + } else + printInfoLine(out, flags, level, "(no value available)"); + } else + printInfoLine(out, flags, level, "(not loaded)"); +} + + +// ******************************** + + +OFCondition DcmAttributeTag::writeXML(STD_NAMESPACE ostream &out, + const size_t flags) +{ + /* AT requires special handling in the Native DICOM Model format */ + if (flags & DCMTypes::XF_useNativeModel) + { + /* write normal XML start tag */ + DcmElement::writeXMLStartTag(out, flags); + /* get unsigned integer data */ + Uint16 *uintVals; + getUint16Array(uintVals); + const unsigned long vm = getVM(); + /* check for empty/invalid value */ + if ((uintVals != NULL) && (vm > 0)) + { + out << STD_NAMESPACE uppercase << STD_NAMESPACE setfill('0'); + /* print tag values "ggggeeee" in hex mode (upper case!) */ + for (unsigned long valNo = 0; valNo < vm; valNo++) + { + out << ""; + out << STD_NAMESPACE hex << STD_NAMESPACE setw(4) << (*(uintVals++)); + out << STD_NAMESPACE setw(4) << (*(uintVals++)) << STD_NAMESPACE dec; + out << "" << OFendl; + } + /* reset i/o manipulators */ + out << STD_NAMESPACE nouppercase << STD_NAMESPACE setfill(' '); + } + /* write normal XML end tag */ + DcmElement::writeXMLEndTag(out, flags); + /* always report success */ + return EC_Normal; + } else { + /* DCMTK-specific format does not require anything special */ + return DcmElement::writeXML(out, flags); + } +} + + +// ******************************** + + +OFCondition DcmAttributeTag::getTagVal(DcmTagKey &tagVal, + const unsigned long pos) +{ + /* get unsigned integer data */ + Uint16 *uintValues; + errorFlag = getUint16Array(uintValues); + /* check data before returning */ + if (errorFlag.good()) + { + if (uintValues == NULL) + errorFlag = EC_IllegalCall; + else if (pos >= getVM()) + errorFlag = EC_IllegalParameter; + else + tagVal.set(uintValues[2 * pos] /*group*/, uintValues[2 * pos + 1] /*element*/); + } + /* clear value in case of error */ + if (errorFlag.bad()) + tagVal = DcmTagKey(); + return errorFlag; +} + + +OFCondition DcmAttributeTag::getUint16Array(Uint16 *&uintVals) +{ + uintVals = OFstatic_cast(Uint16 *, getValue()); + return errorFlag; +} + + +// ******************************** + + +OFCondition DcmAttributeTag::getOFString(OFString &stringVal, + const unsigned long pos, + OFBool /*normalize*/) +{ + DcmTagKey tagVal; + /* get the specified tag value */ + errorFlag = getTagVal(tagVal, pos); + if (errorFlag.good()) + { + /* ... and convert it to a character string */ + char buffer[32]; + sprintf(buffer, "(%4.4x,%4.4x)", tagVal.getGroup(), tagVal.getElement()); + /* assign result */ + stringVal = buffer; + } + return errorFlag; +} + + +// ******************************** + + +OFCondition DcmAttributeTag::putTagVal(const DcmTagKey &tagVal, + const unsigned long pos) +{ + /* create tag data */ + Uint16 uintVals[2]; + uintVals[0] = tagVal.getGroup(); + uintVals[1] = tagVal.getElement(); + /* change element value */ + errorFlag = changeValue(uintVals, OFstatic_cast(Uint32, 2 * sizeof(Uint16) * OFstatic_cast(size_t, pos)), 2 * OFstatic_cast(Uint32, sizeof(Uint16))); + return errorFlag; +} + + +OFCondition DcmAttributeTag::putUint16Array(const Uint16 *uintVals, + const unsigned long numUints) +{ + errorFlag = EC_Normal; + if (numUints > 0) + { + /* check for valid data */ + if (uintVals != NULL) + errorFlag = putValue(uintVals, OFstatic_cast(Uint32, 2 * sizeof(Uint16) * OFstatic_cast(size_t, numUints))); + else + errorFlag = EC_CorruptedData; + } else + errorFlag = putValue(NULL, 0); + return errorFlag; +} + + +// ******************************** + + +OFCondition DcmAttributeTag::putString(const char *stringVal) +{ + /* determine length of the string value */ + const size_t stringLen = (stringVal != NULL) ? strlen(stringVal) : 0; + /* call the real function */ + return putString(stringVal, OFstatic_cast(Uint32, stringLen)); +} + + +OFCondition DcmAttributeTag::putString(const char *stringVal, + const Uint32 stringLen) +{ + errorFlag = EC_Normal; + /* determine VM of the string */ + unsigned long vm = DcmElement::determineVM(stringVal, stringLen); + if (vm > 0) + { + Uint16 * field = new Uint16[2 * vm]; + OFString value; + size_t pos = 0; + /* retrieve attribute tag data from character string */ + for (unsigned long i = 0; (i < 2 * vm) && errorFlag.good(); i += 2) + { + /* get specified value from multi-valued string */ + pos = DcmElement::getValueFromString(stringVal, pos, stringLen, value); + if (value.empty() || sscanf(value.c_str(), "(%hx,%hx)", &field[i], &field[i + 1]) != 2) + errorFlag = EC_CorruptedData; + } + /* set binary data as the element value */ + if (errorFlag.good()) + errorFlag = putUint16Array(field, vm); + /* delete temporary buffer */ + delete[] field; + } else + putValue(NULL, 0); + return errorFlag; +} + + +// ******************************** + + +OFCondition DcmAttributeTag::verify(const OFBool autocorrect) +{ + /* check for valid value length */ + if (getLengthField() % (2 * sizeof(Uint16)) != 0) + { + errorFlag = EC_CorruptedData; + if (autocorrect) + { + /* strip to valid length */ + setLengthField(getLengthField() - (getLengthField() % (2* OFstatic_cast(Uint32, sizeof(Uint16))))); + } + } else + errorFlag = EC_Normal; + return errorFlag; +} + + +// ******************************** + + +OFCondition DcmAttributeTag::checkStringValue(const OFString &value, + const OFString &vm) +{ + return DcmElement::checkVM(DcmElement::determineVM(value.c_str(), value.length()), vm); +} diff --git a/dcmdata/libsrc/dcvrcs.cc b/dcmdata/libsrc/dcvrcs.cc new file mode 100644 index 00000000..c7718c78 --- /dev/null +++ b/dcmdata/libsrc/dcvrcs.cc @@ -0,0 +1,144 @@ +/* + * + * Copyright (C) 1994-2010, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Gerd Ehlers, Andreas Barth + * + * Purpose: class DcmCodeString + * + */ + + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#define INCLUDE_CCTYPE +#include "dcmtk/ofstd/ofstdinc.h" + +#include "dcmtk/dcmdata/dcvrcs.h" + + +#define MAX_CS_LENGTH 16 + + +// ******************************** + + +DcmCodeString::DcmCodeString(const DcmTag &tag, + const Uint32 len) + : DcmByteString(tag, len) +{ + setMaxLength(MAX_CS_LENGTH); + setNonSignificantChars(" \\"); +} + + +DcmCodeString::DcmCodeString(const DcmCodeString &old) + : DcmByteString(old) +{ +} + + +DcmCodeString::~DcmCodeString() +{ +} + + +DcmCodeString &DcmCodeString::operator=(const DcmCodeString &obj) +{ + DcmByteString::operator=(obj); + return *this; +} + + +OFCondition DcmCodeString::copyFrom(const DcmObject& rhs) +{ + if (this != &rhs) + { + if (rhs.ident() != ident()) return EC_IllegalCall; + *this = OFstatic_cast(const DcmCodeString &, rhs); + } + return EC_Normal; +} + + +// ******************************** + + +DcmEVR DcmCodeString::ident() const +{ + return EVR_CS; +} + + +OFCondition DcmCodeString::checkValue(const OFString &vm, + const OFBool /*oldFormat*/) +{ + OFString strVal; + /* get "raw value" without any modifications (if possible) */ + OFCondition l_error = getStringValue(strVal); + if (l_error.good()) + l_error = DcmCodeString::checkStringValue(strVal, vm); + return l_error; +} + + +// ******************************** + + +OFCondition DcmCodeString::getOFString(OFString &stringVal, + const unsigned long pos, + OFBool normalize) +{ + OFCondition l_error = DcmByteString::getOFString(stringVal, pos, normalize); + if (l_error.good() && normalize) + normalizeString(stringVal, !MULTIPART, DELETE_LEADING, DELETE_TRAILING); + return l_error; +} + + +// ******************************** + + +OFBool DcmCodeString::checkVR(const OFString &value, + size_t *pos, + const OFBool checkLength) +{ + unsigned char c; + size_t i; + const size_t length = value.length(); + const size_t maxlen = (length < MAX_CS_LENGTH) || (!checkLength) ? length : MAX_CS_LENGTH; + /* iterate over all characters (up to the maximum) */ + for (i = 0; i < maxlen; i++) + { + c = value.at(i); + /* check for valid CS character: A-Z, 0-9, _ and ' ' (space) */ + if ((c != ' ') && (c != '_') && !isdigit(c) && !(isalpha(c) && isupper(c))) + break; + } + /* return position of first invalid character (eos if all valid) */ + if (pos != NULL) + *pos = i; + /* OFFalse in case of any invalid character */ + return (i == length); +} + + +// ******************************** + + +OFCondition DcmCodeString::checkStringValue(const OFString &value, + const OFString &vm) +{ + return DcmByteString::checkStringValue(value, vm, "cs", 10, MAX_CS_LENGTH); +} diff --git a/dcmdata/libsrc/dcvrda.cc b/dcmdata/libsrc/dcvrda.cc new file mode 100644 index 00000000..4da50b54 --- /dev/null +++ b/dcmdata/libsrc/dcvrda.cc @@ -0,0 +1,296 @@ +/* + * + * Copyright (C) 1994-2015, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Gerd Ehlers, Andreas Barth, Joerg Riesmeier + * + * Purpose: Implementation of class DcmDate + * + */ + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/dcmdata/dcvrda.h" + +#define INCLUDE_CSTDIO +#include "dcmtk/ofstd/ofstdinc.h" + + +// ******************************** + + +DcmDate::DcmDate(const DcmTag &tag, + const Uint32 len) + : DcmByteString(tag, len) +{ + setMaxLength(10); + setNonSignificantChars("\\"); +} + + +DcmDate::DcmDate(const DcmDate &old) + : DcmByteString(old) +{ +} + + +DcmDate::~DcmDate() +{ +} + + +DcmDate &DcmDate::operator=(const DcmDate &obj) +{ + DcmByteString::operator=(obj); + return *this; +} + + +OFCondition DcmDate::copyFrom(const DcmObject& rhs) +{ + if (this != &rhs) + { + if (rhs.ident() != ident()) return EC_IllegalCall; + *this = OFstatic_cast(const DcmDate &, rhs); + } + return EC_Normal; +} + + + +// ******************************** + + +DcmEVR DcmDate::ident() const +{ + return EVR_DA; +} + + +OFCondition DcmDate::checkValue(const OFString &vm, + const OFBool oldFormat) +{ + OFString strVal; + /* get "raw value" without any modifications (if possible) */ + OFCondition l_error = getStringValue(strVal); + if (l_error.good()) + l_error = DcmDate::checkStringValue(strVal, vm, oldFormat); + return l_error; +} + + +// ******************************** + + +OFCondition DcmDate::getOFString(OFString &stringVal, + const unsigned long pos, + OFBool normalize) +{ + OFCondition l_error = DcmByteString::getOFString(stringVal, pos, normalize); + if (l_error.good() && normalize) + normalizeString(stringVal, !MULTIPART, !DELETE_LEADING, DELETE_TRAILING); + return l_error; +} + + +// ******************************** + + +OFCondition DcmDate::getOFDate(OFDate &dateValue, + const unsigned long pos, + const OFBool supportOldFormat) +{ + OFString dicomDate; + /* convert the current element value to OFDate format */ + OFCondition l_error = getOFString(dicomDate, pos); + if (l_error.good()) + l_error = getOFDateFromString(dicomDate, dateValue, supportOldFormat); + else + dateValue.clear(); + return l_error; +} + + +OFCondition DcmDate::getISOFormattedDate(OFString &formattedDate, + const unsigned long pos, + const OFBool supportOldFormat) +{ + OFString dicomDate; + /* get current element value and convert to ISO formatted date */ + OFCondition l_error = getOFString(dicomDate, pos); + if (l_error.good()) + l_error = getISOFormattedDateFromString(dicomDate, formattedDate, supportOldFormat); + else + formattedDate.clear(); + return l_error; +} + + +OFCondition DcmDate::setCurrentDate() +{ + OFString dicomDate; + /* set the element value to the current system date */ + OFCondition l_error = getCurrentDate(dicomDate); + if (l_error.good()) + l_error = putOFStringArray(dicomDate); + return l_error; +} + + +OFCondition DcmDate::setOFDate(const OFDate &dateValue) +{ + OFString dicomDate; + /* convert OFDate value to DICOM DA format and set the element value */ + OFCondition l_error = getDicomDateFromOFDate(dateValue, dicomDate); + if (l_error.good()) + l_error = putOFStringArray(dicomDate); + return l_error; +} + + +// ******************************** + + +OFCondition DcmDate::getCurrentDate(OFString &dicomDate) +{ + OFCondition l_error = EC_IllegalCall; + OFDate dateValue; + /* get the current system date */ + if (dateValue.setCurrentDate()) + { + /* format: YYYYMMDD */ + if (dateValue.getISOFormattedDate(dicomDate, OFFalse /*showDelimiter*/)) + l_error = EC_Normal; + } + /* set default date if an error occurred */ + if (l_error.bad()) + { + /* format: YYYYMMDD */ + dicomDate = "19000101"; + } + return l_error; +} + + +OFCondition DcmDate::getDicomDateFromOFDate(const OFDate &dateValue, + OFString &dicomDate) +{ + OFCondition l_error = EC_IllegalParameter; + /* convert OFDate value to DICOM DA format */ + if (dateValue.getISOFormattedDate(dicomDate, OFFalse /*showDelimiter*/)) + l_error = EC_Normal; + return l_error; +} + + +OFCondition DcmDate::getOFDateFromString(const OFString &dicomDate, + OFDate &dateValue, + const OFBool supportOldFormat) +{ + OFCondition l_error = EC_IllegalParameter; + /* clear result variable */ + dateValue.clear(); + /* fixed length (8 or 10 bytes) required by DICOM part 5 */ + if ((dicomDate.length() == 8) && (dicomDate.find('.') == OFString_npos)) + { + unsigned int year, month, day; + /* extract components from date string */ + if (sscanf(dicomDate.c_str(), "%04u%02u%02u", &year, &month, &day) == 3) + { + if (dateValue.setDate(year, month, day)) + l_error = EC_Normal; + } + } + /* old prior V3.0 version of VR=DA: YYYY.MM.DD */ + else if (supportOldFormat && (dicomDate.length() == 10) && (dicomDate[4] == '.') && (dicomDate[7] == '.')) + { + unsigned int year, month, day; + /* extract components from date string */ + if (sscanf(dicomDate.c_str(), "%04u.%02u.%02u", &year, &month, &day) == 3) + { + if (dateValue.setDate(year, month, day)) + l_error = EC_Normal; + } + } + return l_error; +} + + +OFCondition DcmDate::getISOFormattedDateFromString(const OFString &dicomDate, + OFString &formattedDate, + const OFBool supportOldFormat) +{ + OFCondition l_error = EC_Normal; + if (!dicomDate.empty()) + { + OFDate dateValue; + /* convert string to OFDate */ + l_error = getOFDateFromString(dicomDate, dateValue, supportOldFormat); + if (l_error.good()) + { + /* convert OFDate to ISO formatted date */ + if (!dateValue.getISOFormattedDate(formattedDate)) + l_error = EC_CorruptedData; + } + /* clear the result variable in case of error */ + if (l_error.bad()) + formattedDate.clear(); + } else { + /* input string is empty, so is the result string */ + formattedDate.clear(); + } + return l_error; +} + + +// ******************************** + + +OFCondition DcmDate::checkStringValue(const OFString &value, + const OFString &vm, + const OFBool oldFormat) +{ + OFCondition result = EC_Normal; + const size_t valLen = value.length(); + if (valLen > 0) + { + size_t posStart = 0; + unsigned long vmNum = 0; + /* iterate over all value components */ + while (posStart != OFString_npos) + { + ++vmNum; + /* search for next component separator */ + const size_t posEnd = value.find('\\', posStart); + const size_t length = (posEnd == OFString_npos) ? valLen - posStart : posEnd - posStart; + if (dcmEnableVRCheckerForStringValues.get()) + { + /* check value representation */ + const int vrID = DcmElement::scanValue(value, "da", posStart, length); + if ((vrID != 2) && (!oldFormat || (vrID != 3)) && (vrID != 17)) + { + result = EC_ValueRepresentationViolated; + break; + } + } + posStart = (posEnd == OFString_npos) ? posEnd : posEnd + 1; + } + if (result.good() && !vm.empty()) + { + /* check value multiplicity */ + result = DcmElement::checkVM(vmNum, vm); + } + } + return result; +} diff --git a/dcmdata/libsrc/dcvrds.cc b/dcmdata/libsrc/dcvrds.cc new file mode 100644 index 00000000..937f946d --- /dev/null +++ b/dcmdata/libsrc/dcvrds.cc @@ -0,0 +1,227 @@ +/* + * + * Copyright (C) 1994-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Gerd Ehlers, Andreas Barth + * + * Purpose: Implementation of class DcmDecimalString + * + */ + + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/dcmdata/dcvrds.h" +#include "dcmtk/ofstd/ofstring.h" +#include "dcmtk/ofstd/ofstd.h" + + +#define MAX_DS_LENGTH 16 + + +// ******************************** + + +DcmDecimalString::DcmDecimalString(const DcmTag &tag, + const Uint32 len) + : DcmByteString(tag, len) +{ + setMaxLength(MAX_DS_LENGTH); + setNonSignificantChars(" \\"); +} + + +DcmDecimalString::DcmDecimalString(const DcmDecimalString &old) + : DcmByteString(old) +{ +} + + +DcmDecimalString::~DcmDecimalString() +{ +} + + +DcmDecimalString &DcmDecimalString::operator=(const DcmDecimalString &obj) +{ + DcmByteString::operator=(obj); + return *this; +} + + +OFCondition DcmDecimalString::copyFrom(const DcmObject& rhs) +{ + if (this != &rhs) + { + if (rhs.ident() != ident()) return EC_IllegalCall; + *this = OFstatic_cast(const DcmDecimalString &, rhs); + } + return EC_Normal; +} + + +// ******************************** + + +DcmEVR DcmDecimalString::ident() const +{ + return EVR_DS; +} + + +OFCondition DcmDecimalString::checkValue(const OFString &vm, + const OFBool /*oldFormat*/) +{ + OFString strVal; + /* get "raw value" without any modifications (if possible) */ + OFCondition l_error = getStringValue(strVal); + if (l_error.good()) + l_error = DcmDecimalString::checkStringValue(strVal, vm); + return l_error; +} + + +// ******************************** + + +OFCondition DcmDecimalString::getFloat64(Float64 &doubleVal, + const unsigned long pos) +{ + /* get decimal string value */ + OFString str; + OFCondition l_error = getOFString(str, pos, OFTrue /*normalize*/); + if (l_error.good()) + { + OFBool success = OFFalse; + /* convert string to float value */ + doubleVal = OFStandard::atof(str.c_str(), &success); + if (!success) + l_error = EC_CorruptedData; + } + return l_error; +} + + +OFCondition DcmDecimalString::getFloat64Vector(OFVector &doubleVals) +{ + /* get stored value */ + char *strVal = NULL; + Uint32 strLen = 0; + OFCondition l_error = getString(strVal, strLen); + /* clear result variable */ + doubleVals.clear(); + if (l_error.good() && (strVal != NULL)) + { + /* determine number of stored values */ + const unsigned long vm = getVM(); + if (vm > 0) + { + Float64 doubleVal; + OFString doubleStr; + char *p = strVal; + OFBool success = OFFalse; + /* avoid memory re-allocations by specifying the expected size */ + doubleVals.reserve(vm); + /* iterate over the string value and search for delimiters */ + for (Uint32 i = 0; i <= strLen; i++) + { + if ((i == strLen) || (*p == '\\')) + { + /* extract single value and convert it to floating point */ + doubleStr.assign(strVal, p - strVal); + doubleVal = OFStandard::atof(doubleStr.c_str(), &success); + if (success) + { + /* store floating point value in result variable */ + doubleVals.push_back(doubleVal); + strVal = p + 1; + } + else + { + l_error = EC_CorruptedData; + break; + } + } + ++p; + } + } + } + return l_error; +} + + +// ******************************** + + +OFCondition DcmDecimalString::getOFString(OFString &stringVal, + const unsigned long pos, + OFBool normalize) +{ + /* call inherited method */ + OFCondition l_error = DcmByteString::getOFString(stringVal, pos); + /* normalize string if required */ + if (l_error.good() && normalize) + normalizeString(stringVal, !MULTIPART, DELETE_LEADING, DELETE_TRAILING); + return l_error; +} + + +// ******************************** + + +OFCondition DcmDecimalString::writeXML(STD_NAMESPACE ostream &out, + const size_t flags) +{ + if (flags & DCMTypes::XF_useNativeModel) + { + /* for the Native DICOM Model output, we do not need any specific DS handling */ + return DcmElement::writeXML(out, flags); + } else { + /* XML start tag: */ + writeXMLStartTag(out, flags); + /* write element value (if loaded) */ + if (valueLoaded()) + { + /* get string data (without normalization) */ + char *value = NULL; + Uint32 length = 0; + getString(value, length); + if ((value != NULL) && (length > 0)) + { + /* explicitly convert to OFString because of possible NULL bytes */ + OFString stringVal(value, length); + const OFBool convertNonASCII = (flags & DCMTypes::XF_convertNonASCII) > 0; + /* check whether conversion to XML markup string is required */ + if (OFStandard::checkForMarkupConversion(stringVal, convertNonASCII)) + OFStandard::convertToMarkupStream(out, stringVal, convertNonASCII); + else + out << value; + } + } + /* XML end tag: */ + writeXMLEndTag(out, flags); + /* always report success */ + return EC_Normal; + } +} + + +// ******************************** + + +OFCondition DcmDecimalString::checkStringValue(const OFString &value, + const OFString &vm) +{ + return DcmByteString::checkStringValue(value, vm, "ds", 6, MAX_DS_LENGTH); +} diff --git a/dcmdata/libsrc/dcvrdt.cc b/dcmdata/libsrc/dcvrdt.cc new file mode 100644 index 00000000..160c1c1c --- /dev/null +++ b/dcmdata/libsrc/dcvrdt.cc @@ -0,0 +1,380 @@ +/* + * + * Copyright (C) 1994-2015, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Gerd Ehlers, Andreas Barth, Joerg Riesmeier + * + * Purpose: Implementation of class DcmDateTime + * + */ + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/dcmdata/dcvrdt.h" +#include "dcmtk/dcmdata/dcvrda.h" +#include "dcmtk/dcmdata/dcvrtm.h" +#include "dcmtk/ofstd/ofstring.h" +#include "dcmtk/ofstd/ofstd.h" + +#define INCLUDE_CSTDIO +#include "dcmtk/ofstd/ofstdinc.h" + + +#define MAX_DT_LENGTH 26 + + +// ******************************** + + +DcmDateTime::DcmDateTime(const DcmTag &tag, + const Uint32 len) + : DcmByteString(tag, len) +{ + setMaxLength(MAX_DT_LENGTH); + setNonSignificantChars(" \\"); +} + +DcmDateTime::DcmDateTime(const DcmDateTime &old) + : DcmByteString(old) +{ +} + + +DcmDateTime::~DcmDateTime() +{ +} + + +DcmDateTime &DcmDateTime::operator=(const DcmDateTime &obj) +{ + DcmByteString::operator=(obj); + return *this; +} + + +OFCondition DcmDateTime::copyFrom(const DcmObject& rhs) +{ + if (this != &rhs) + { + if (rhs.ident() != ident()) return EC_IllegalCall; + *this = OFstatic_cast(const DcmDateTime &, rhs); + } + return EC_Normal; +} + +// ******************************** + + +DcmEVR DcmDateTime::ident() const +{ + return EVR_DT; +} + + +OFCondition DcmDateTime::checkValue(const OFString &vm, + const OFBool /*oldFormat*/) +{ + OFString strVal; + /* get "raw value" without any modifications (if possible) */ + OFCondition l_error = getStringValue(strVal); + if (l_error.good()) + l_error = DcmDateTime::checkStringValue(strVal, vm); + return l_error; +} + + +// ******************************** + + +OFCondition DcmDateTime::getOFString(OFString &stringVal, + const unsigned long pos, + OFBool normalize) +{ + OFCondition l_error = DcmByteString::getOFString(stringVal, pos, normalize); + if (l_error.good() && normalize) + normalizeString(stringVal, !MULTIPART, !DELETE_LEADING, DELETE_TRAILING); + return l_error; +} + + +// ******************************** + + +OFCondition DcmDateTime::getOFDateTime(OFDateTime &dateTimeValue, + const unsigned long pos) +{ + OFString dicomDateTime; + /* convert the current element value to OFDateTime format */ + OFCondition l_error = getOFString(dicomDateTime, pos); + if (l_error.good()) + l_error = getOFDateTimeFromString(dicomDateTime, dateTimeValue); + else + dateTimeValue.clear(); + return l_error; +} + + +OFCondition DcmDateTime::getISOFormattedDateTime(OFString &formattedDateTime, + const unsigned long pos, + const OFBool seconds, + const OFBool fraction, + const OFBool timeZone, + const OFBool createMissingPart, + const OFString &dateTimeSeparator, + const OFString &timeZoneSeparator) +{ + OFString dicomDateTime; + /* get current element value and convert to ISO formatted date/time */ + OFCondition l_error = getOFString(dicomDateTime, pos); + if (l_error.good()) + { + l_error = getISOFormattedDateTimeFromString(dicomDateTime, formattedDateTime, seconds, fraction, + timeZone, createMissingPart, dateTimeSeparator, timeZoneSeparator); + } else + formattedDateTime.clear(); + return l_error; +} + + +OFCondition DcmDateTime::setCurrentDateTime(const OFBool seconds, + const OFBool fraction, + const OFBool timeZone) +{ + OFString dicomDateTime; + OFCondition l_error = getCurrentDateTime(dicomDateTime, seconds, fraction, timeZone); + if (l_error.good()) + l_error = putOFStringArray(dicomDateTime); + return l_error; +} + + +OFCondition DcmDateTime::setOFDateTime(const OFDateTime &dateTimeValue) +{ + OFString dicomDateTime; + /* convert OFDateTime value to DICOM DT format and set the element value */ + OFCondition l_error = getDicomDateTimeFromOFDateTime(dateTimeValue, dicomDateTime); + if (l_error.good()) + l_error = putOFStringArray(dicomDateTime); + return l_error; +} + + +// ******************************** + + +OFCondition DcmDateTime::getCurrentDateTime(OFString &dicomDateTime, + const OFBool seconds, + const OFBool fraction, + const OFBool timeZone) +{ + OFCondition l_error = EC_IllegalCall; + OFDateTime dateTimeValue; + /* get the current system time */ + if (dateTimeValue.setCurrentDateTime()) + { + /* format: YYYYMMDDHHMM[SS[.FFFFFF]] */ + if (dateTimeValue.getISOFormattedDateTime(dicomDateTime, seconds, fraction, timeZone, OFFalse /*showDelimiter*/)) + l_error = EC_Normal; + } + /* set default date/time if an error occurred */ + if (l_error.bad()) + { + /* format: YYYYMMDDHHMM */ + dicomDateTime = "190001010000"; + if (seconds) + { + /* format: SS */ + dicomDateTime += "00"; + if (fraction) + { + /* format: .FFFFFF */ + dicomDateTime += ".000000"; + } + } + if (timeZone) + { + /* format: CHHMM */ + dicomDateTime += "+0000"; + } + } + return l_error; +} + + +OFCondition DcmDateTime::getDicomDateTimeFromOFDateTime(const OFDateTime &dateTimeValue, + OFString &dicomDateTime, + const OFBool seconds, + const OFBool fraction, + const OFBool timeZone) +{ + OFCondition l_error = EC_IllegalParameter; + /* convert OFDateTime value to DICOM DT format */ + if (dateTimeValue.getISOFormattedDateTime(dicomDateTime, seconds, fraction, timeZone, OFFalse /*showDelimiter*/)) + l_error = EC_Normal; + return l_error; +} + + +OFCondition DcmDateTime::getOFDateTimeFromString(const OFString &dicomDateTime, + OFDateTime &dateTimeValue) +{ + OFCondition l_error = EC_IllegalParameter; + /* clear result variable */ + dateTimeValue.clear(); + /* minimal check for valid format: YYYYMMDD */ + if (dicomDateTime.length() >= 8) + { + OFString string; + unsigned int year, month, day; + unsigned int hour = 0; + unsigned int minute = 0; + double second = 0; + double timeZone = 0; + /* check whether optional time zone is present and extract the value if so */ + if (DcmTime::getTimeZoneFromString(dicomDateTime.substr(dicomDateTime.length() - 5), timeZone).good()) + string = dicomDateTime.substr(0, dicomDateTime.length() - 5); + else + { + string = dicomDateTime; + /* no time zone specified, therefore, use the local one */ + timeZone = OFTime::getLocalTimeZone(); + } + /* extract remaining components from date/time string: YYYYMMDDHHMM[SS[.FFFFFF]] */ + /* scan seconds using OFStandard::atof to avoid locale issues */ + if (sscanf(string.c_str(), "%04u%02u%02u%02u%02u", &year, &month, &day, &hour, &minute) >= 3) + { + if (string.length() > 12) + { + string.erase(0, 12); + second = OFStandard::atof(string.c_str()); + } + if (dateTimeValue.setDateTime(year, month, day, hour, minute, second, timeZone)) + l_error = EC_Normal; + } + } + return l_error; +} + + +OFCondition DcmDateTime::getISOFormattedDateTimeFromString(const OFString &dicomDateTime, + OFString &formattedDateTime, + const OFBool seconds, + const OFBool fraction, + const OFBool timeZone, + const OFBool createMissingPart, + const OFString &dateTimeSeparator, + const OFString &timeZoneSeparator) +{ + OFCondition l_error = EC_Normal; + const size_t length = dicomDateTime.length(); + /* minimum DT format: YYYYMMDD */ + if (length >= 8) + { + OFString timeString; + OFDate dateValue; + /* get formatted date: YYYY-MM-DD */ + l_error = DcmDate::getOFDateFromString(dicomDateTime.substr(0, 8), dateValue, OFFalse /*supportOldFormat*/); + if (l_error.good()) + { + dateValue.getISOFormattedDate(formattedDateTime); + /* get formatted time: [HH[:MM[:SS[.FFFFFF]]]] */ + const size_t posSign = dicomDateTime.find_first_of("+-", 8); + OFString dicomTime = (posSign != OFString_npos) ? dicomDateTime.substr(8, posSign - 8) : dicomDateTime.substr(8); + l_error = DcmTime::getISOFormattedTimeFromString(dicomTime, timeString, seconds, fraction, createMissingPart, OFFalse /*supportOldFormat*/); + if (l_error.good() && !timeString.empty()) + { + /* add time string with separator */ + formattedDateTime += dateTimeSeparator; + formattedDateTime += timeString; + /* add optional time zone: [+/-HH:MM] */ + if (timeZone) + { + /* check whether optional time zone is present: &ZZZZ */ + if ((posSign != OFString_npos) && (length >= posSign + 5)) + { + formattedDateTime += timeZoneSeparator; + formattedDateTime += dicomDateTime[posSign]; + formattedDateTime += dicomDateTime.substr(posSign + 1, 2); + formattedDateTime += ":"; + formattedDateTime += dicomDateTime.substr(posSign + 3, 2); + } + else if (createMissingPart) + { + formattedDateTime += timeZoneSeparator; + formattedDateTime += "+00:00"; + } + } + } + } + } + else if (length == 0) + { + /* an empty input string is no error ... */ + formattedDateTime.clear(); + } else { + /* ... but all other formats are (if not handled before) */ + l_error = EC_IllegalParameter; + } + /* clear result variable in case of error */ + if (l_error.bad()) + formattedDateTime.clear(); + return l_error; +} + + +// ******************************** + + +OFCondition DcmDateTime::checkStringValue(const OFString &value, + const OFString &vm) +{ + OFCondition result = EC_Normal; + const size_t valLen = value.length(); + if (valLen > 0) + { + size_t posStart = 0; + unsigned long vmNum = 0; + /* iterate over all value components */ + while (posStart != OFString_npos) + { + ++vmNum; + /* search for next component separator */ + const size_t posEnd = value.find('\\', posStart); + const size_t length = (posEnd == OFString_npos) ? valLen - posStart : posEnd - posStart; + /* check length of current value component */ + if (length > MAX_DT_LENGTH) + { + result = EC_MaximumLengthViolated; + break; + } + else if (dcmEnableVRCheckerForStringValues.get()) + { + /* check value representation */ + const int vrID = DcmElement::scanValue(value, "dt", posStart, length); + if ((vrID != 7) && (vrID != 18)) + { + result = EC_ValueRepresentationViolated; + break; + } + } + posStart = (posEnd == OFString_npos) ? posEnd : posEnd + 1; + } + if (result.good() && !vm.empty()) + { + /* check value multiplicity */ + result = DcmElement::checkVM(vmNum, vm); + } + } + return result; +} diff --git a/dcmdata/libsrc/dcvrfd.cc b/dcmdata/libsrc/dcvrfd.cc new file mode 100644 index 00000000..307e920c --- /dev/null +++ b/dcmdata/libsrc/dcvrfd.cc @@ -0,0 +1,362 @@ +/* + * + * Copyright (C) 1994-2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Gerd Ehlers, Andreas Barth + * + * Purpose: Implementation of class DcmFloatingPointDouble + * + */ + + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/ofstd/ofstream.h" +#include "dcmtk/ofstd/ofstd.h" +#include "dcmtk/dcmdata/dcvrfd.h" + +#define INCLUDE_CSTDIO +#define INCLUDE_CSTRING +#include "dcmtk/ofstd/ofstdinc.h" + + +// ******************************** + + +DcmFloatingPointDouble::DcmFloatingPointDouble(const DcmTag &tag, + const Uint32 len) + : DcmElement(tag, len) +{ +} + + +DcmFloatingPointDouble::DcmFloatingPointDouble(const DcmFloatingPointDouble &old) + : DcmElement(old) +{ +} + + +DcmFloatingPointDouble::~DcmFloatingPointDouble() +{ +} + + +DcmFloatingPointDouble &DcmFloatingPointDouble::operator=(const DcmFloatingPointDouble &obj) +{ + DcmElement::operator=(obj); + return *this; +} + + +int DcmFloatingPointDouble::compare(const DcmElement& rhs) const +{ + int result = DcmElement::compare(rhs); + if (result != 0) + { + return result; + } + + /* cast away constness (dcmdata is not const correct...) */ + DcmFloatingPointDouble* myThis = NULL; + DcmFloatingPointDouble* myRhs = NULL; + myThis = OFconst_cast(DcmFloatingPointDouble*, this); + myRhs = OFstatic_cast(DcmFloatingPointDouble*, OFconst_cast(DcmElement*, &rhs)); + + /* iterate over all components and test equality */ + unsigned long thisVM = myThis->getVM(); + for (unsigned long count = 0; count < thisVM; count++) + { + Float64 val = 0; + if (myThis->getFloat64(val, count).good()) + { + Float64 rhsVal = 0; + if (myRhs->getFloat64(rhsVal, count).good()) + { + if (val > rhsVal) + { + return 1; + } + else if (val < rhsVal) + { + return -1; + } + } + else + { + break; // values equal until this point (rhs shorter) + } + } + } + + /* we get here if all values are equal. Now look at the number of components */ + unsigned long rhsVM = myRhs->getVM(); + if (thisVM < rhsVM) + { + return -1; + } + else if (thisVM > rhsVM) + { + return 1; + } + + /* all values as well as VM equal: objects are equal */ + return 0; +} + + +OFCondition DcmFloatingPointDouble::copyFrom(const DcmObject& rhs) +{ + if (this != &rhs) + { + if (rhs.ident() != ident()) return EC_IllegalCall; + *this = OFstatic_cast(const DcmFloatingPointDouble &, rhs); + } + return EC_Normal; +} + + +// ******************************** + + +DcmEVR DcmFloatingPointDouble::ident() const +{ + return EVR_FD; +} + + +OFCondition DcmFloatingPointDouble::checkValue(const OFString &vm, + const OFBool /*oldFormat*/) +{ + /* check VM only, further checks on the floating point values could be added later */ + return DcmElement::checkVM(getVM(), vm); +} + + +unsigned long DcmFloatingPointDouble::getVM() +{ + return getLengthField() / OFstatic_cast(unsigned long, sizeof(Float64)); +} + + +// ******************************** + + +void DcmFloatingPointDouble::print(STD_NAMESPACE ostream&out, + const size_t flags, + const int level, + const char * /*pixelFileName*/, + size_t * /*pixelCounter*/) +{ + if (valueLoaded()) + { + /* get double data */ + Float64 *doubleVals; + errorFlag = getFloat64Array(doubleVals); + if (doubleVals != NULL) + { + const unsigned long count = getVM(); + const unsigned long maxLength = (flags & DCMTypes::PF_shortenLongTagValues) ? + DCM_OptPrintLineLength : OFstatic_cast(unsigned long, -1) /*unlimited*/; + unsigned long printedLength = 0; + unsigned long newLength = 0; + char buffer[64]; + /* print line start with tag and VR */ + printInfoLineStart(out, flags, level); + /* print multiple values */ + for (unsigned int i = 0; i < count; i++, doubleVals++) + { + /* check whether first value is printed (omit delimiter) */ + if (i == 0) + OFStandard::ftoa(buffer, sizeof(buffer), *doubleVals, 0, 0, 17 /* DBL_DIG + 2 for DICOM FD */); + else + { + buffer[0] = '\\'; + OFStandard::ftoa(buffer + 1, sizeof(buffer) - 1, *doubleVals, 0, 0, 17 /* DBL_DIG + 2 for DICOM FD */); + } + /* check whether current value sticks to the length limit */ + newLength = printedLength + OFstatic_cast(unsigned long, strlen(buffer)); + if ((newLength <= maxLength) && ((i + 1 == count) || (newLength + 3 <= maxLength))) + { + out << buffer; + printedLength = newLength; + } else { + /* check whether output has been truncated */ + if (i + 1 < count) + { + out << "..."; + printedLength += 3; + } + break; + } + } + /* print line end with length, VM and tag name */ + printInfoLineEnd(out, flags, printedLength); + } else + printInfoLine(out, flags, level, "(no value available)" ); + } else + printInfoLine(out, flags, level, "(not loaded)" ); +} + + +// ******************************** + + +OFCondition DcmFloatingPointDouble::getFloat64(Float64 &doubleVal, + const unsigned long pos) +{ + /* get double data */ + Float64 *doubleValues = NULL; + errorFlag = getFloat64Array(doubleValues); + /* check data before returning */ + if (errorFlag.good()) + { + if (doubleValues == NULL) + errorFlag = EC_IllegalCall; + else if (pos >= getVM()) + errorFlag = EC_IllegalParameter; + else + doubleVal = doubleValues[pos]; + } + /* clear value in case of error */ + if (errorFlag.bad()) + doubleVal = 0; + return errorFlag; +} + + +OFCondition DcmFloatingPointDouble::getFloat64Array(Float64 *&doubleVals) +{ + doubleVals = OFstatic_cast(Float64 *, getValue()); + return errorFlag; +} + + +// ******************************** + + +OFCondition DcmFloatingPointDouble::getOFString(OFString &stringVal, + const unsigned long pos, + OFBool /*normalize*/) +{ + Float64 doubleVal; + /* get the specified numeric value */ + errorFlag = getFloat64(doubleVal, pos); + if (errorFlag.good()) + { + /* ... and convert it to a character string */ + char buffer[64]; + OFStandard::ftoa(buffer, sizeof(buffer), doubleVal, 0, 0, 17 /* DBL_DIG + 2 for DICOM FD */); + /* assign result */ + stringVal = buffer; + } + return errorFlag; +} + + +// ******************************** + + +OFCondition DcmFloatingPointDouble::putFloat64(const Float64 doubleVal, + const unsigned long pos) +{ + Float64 val = doubleVal; + errorFlag = changeValue(&val, OFstatic_cast(Uint32, sizeof(Float64) * pos), OFstatic_cast(Uint32, sizeof(Float64))); + return errorFlag; +} + + +OFCondition DcmFloatingPointDouble::putFloat64Array(const Float64 *doubleVals, + const unsigned long numDoubles) +{ + errorFlag = EC_Normal; + if (numDoubles > 0) + { + /* check for valid data */ + if (doubleVals != NULL) + errorFlag = putValue(doubleVals, OFstatic_cast(Uint32, sizeof(Float64) * OFstatic_cast(size_t, numDoubles))); + else + errorFlag = EC_CorruptedData; + } else + putValue(NULL, 0); + + return errorFlag; +} + + +// ******************************** + + +OFCondition DcmFloatingPointDouble::putString(const char *stringVal) +{ + /* determine length of the string value */ + const size_t stringLen = (stringVal != NULL) ? strlen(stringVal) : 0; + /* call the real function */ + return putString(stringVal, OFstatic_cast(Uint32, stringLen)); +} + + +OFCondition DcmFloatingPointDouble::putString(const char *stringVal, + const Uint32 stringLen) +{ + errorFlag = EC_Normal; + /* determine VM of the string */ + const unsigned long vm = DcmElement::determineVM(stringVal, stringLen); + if (vm > 0) + { + Float64 *field = new Float64[vm]; + OFBool success = OFFalse; + OFString value; + size_t pos = 0; + /* retrieve double data from character string */ + for (unsigned long i = 0; (i < vm) && errorFlag.good(); i++) + { + /* get specified value from multi-valued string */ + pos = DcmElement::getValueFromString(stringVal, pos, stringLen, value); + if (!value.empty()) + { + field[i] = OFStandard::atof(value.c_str(), &success); + if (!success) + errorFlag = EC_CorruptedData; + } else + errorFlag = EC_CorruptedData; + } + /* set binary data as the element value */ + if (errorFlag == EC_Normal) + errorFlag = putFloat64Array(field, vm); + /* delete temporary buffer */ + delete[] field; + } else + putValue(NULL, 0); + return errorFlag; +} + + +// ******************************** + + +OFCondition DcmFloatingPointDouble::verify(const OFBool autocorrect) +{ + /* check for valid value length */ + if (getLengthField() % (sizeof(Float64)) != 0) + { + errorFlag = EC_CorruptedData; + if (autocorrect) + { + /* strip to valid length */ + setLengthField(getLengthField() - (getLengthField() % OFstatic_cast(Uint32, sizeof(Float64)))); + } + } else + errorFlag = EC_Normal; + return errorFlag; +} diff --git a/dcmdata/libsrc/dcvrfl.cc b/dcmdata/libsrc/dcvrfl.cc new file mode 100644 index 00000000..cd2a388f --- /dev/null +++ b/dcmdata/libsrc/dcvrfl.cc @@ -0,0 +1,363 @@ +/* + * + * Copyright (C) 1994-2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Gerd Ehlers, Andreas Barth + * + * Purpose: Implementation of class DcmFloatingPointSingle + * + */ + + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/ofstd/ofstream.h" +#include "dcmtk/ofstd/ofstd.h" +#include "dcmtk/dcmdata/dcvrfl.h" + +#define INCLUDE_CSTDIO +#define INCLUDE_CSTRING +#include "dcmtk/ofstd/ofstdinc.h" + + +// ******************************** + + +DcmFloatingPointSingle::DcmFloatingPointSingle(const DcmTag &tag, + const Uint32 len) + : DcmElement(tag, len) +{ +} + + +DcmFloatingPointSingle::DcmFloatingPointSingle(const DcmFloatingPointSingle &old) + : DcmElement(old) +{ +} + + +DcmFloatingPointSingle::~DcmFloatingPointSingle() +{ +} + + +DcmFloatingPointSingle &DcmFloatingPointSingle::operator=(const DcmFloatingPointSingle &obj) +{ + DcmElement::operator=(obj); + return *this; +} + + +int DcmFloatingPointSingle::compare(const DcmElement& rhs) const +{ + int result = DcmElement::compare(rhs); + if (result != 0) + { + return result; + } + + /* cast away constness (dcmdata is not const correct...) */ + DcmFloatingPointSingle* myThis = NULL; + DcmFloatingPointSingle* myRhs = NULL; + myThis = OFconst_cast(DcmFloatingPointSingle*, this); + myRhs = OFstatic_cast(DcmFloatingPointSingle*, OFconst_cast(DcmElement*, &rhs)); + + // iterate over all components and test equality */ + unsigned long thisVM = myThis->getVM(); + for (unsigned long count = 0; count < thisVM; count++) + { + Float32 val = 0; + if (myThis->getFloat32(val, count).good()) + { + Float32 rhsVal = 0; + if (myRhs->getFloat32(rhsVal, count).good()) + { + if (val > rhsVal) + { + return 1; + } + else if (val < rhsVal) + { + return -1; + } + } + else + { + break; // values equal until this point (rhs shorter) + } + } + } + + /* we get here if all values are equal. Now look at the number of components. */ + unsigned long rhsVM = myRhs->getVM(); + if (thisVM < rhsVM) + { + return -1; + } + else if (thisVM > rhsVM) + { + return 1; + } + + /* all values as well as VM equal: objects are equal */ + return 0; +} + + + +OFCondition DcmFloatingPointSingle::copyFrom(const DcmObject& rhs) +{ + if (this != &rhs) + { + if (rhs.ident() != ident()) return EC_IllegalCall; + *this = OFstatic_cast(const DcmFloatingPointSingle &, rhs); + } + return EC_Normal; +} + + +// ******************************** + + +DcmEVR DcmFloatingPointSingle::ident() const +{ + return EVR_FL; +} + + +OFCondition DcmFloatingPointSingle::checkValue(const OFString &vm, + const OFBool /*oldFormat*/) +{ + /* check VM only, further checks on the floating point values could be added later */ + return DcmElement::checkVM(getVM(), vm); +} + + +unsigned long DcmFloatingPointSingle::getVM() +{ + return getLengthField() / OFstatic_cast(unsigned long, sizeof(Float32)); +} + + +// ******************************** + + +void DcmFloatingPointSingle::print(STD_NAMESPACE ostream&out, + const size_t flags, + const int level, + const char * /*pixelFileName*/, + size_t * /*pixelCounter*/) +{ + if (valueLoaded()) + { + /* get float data */ + Float32 *floatVals; + errorFlag = getFloat32Array(floatVals); + if (floatVals != NULL) + { + const unsigned long count = getLengthField() / OFstatic_cast(unsigned long, sizeof(Float32)) /* do not use getVM()! */; + const unsigned long maxLength = (flags & DCMTypes::PF_shortenLongTagValues) ? + DCM_OptPrintLineLength : OFstatic_cast(unsigned long, -1); + unsigned long printedLength = 0; + unsigned long newLength = 0; + char buffer[64]; + /* print line start with tag and VR */ + printInfoLineStart(out, flags, level); + /* print multiple values */ + for (unsigned int i = 0; i < count; i++, floatVals++) + { + /* check whether first value is printed (omit delimiter) */ + if (i == 0) + OFStandard::ftoa(buffer, sizeof(buffer), *floatVals, 0, 0, 8 /* FLT_DIG + 2 for DICOM FL */); + else + { + buffer[0] = '\\'; + OFStandard::ftoa(buffer + 1, sizeof(buffer) - 1, *floatVals, 0, 0, 8 /* FLT_DIG + 2 for DICOM FL */); + } + /* check whether current value sticks to the length limit */ + newLength = printedLength + OFstatic_cast(unsigned long, strlen(buffer)); + if ((newLength <= maxLength) && ((i + 1 == count) || (newLength + 3 <= maxLength))) + { + out << buffer; + printedLength = newLength; + } else { + /* check whether output has been truncated */ + if (i + 1 < count) + { + out << "..."; + printedLength += 3; + } + break; + } + } + /* print line end with length, VM and tag name */ + printInfoLineEnd(out, flags, printedLength); + } else + printInfoLine(out, flags, level, "(no value available)" ); + } else + printInfoLine(out, flags, level, "(not loaded)" ); +} + + +// ******************************** + + +OFCondition DcmFloatingPointSingle::getFloat32(Float32 &floatVal, + const unsigned long pos) +{ + /* get float data */ + Float32 *floatValues = NULL; + errorFlag = getFloat32Array(floatValues); + /* check data before returning */ + if (errorFlag.good()) + { + if (floatValues == NULL) + errorFlag = EC_IllegalCall; + else if (pos >= getLengthField() / sizeof(Float32) /* do not use getVM()! */) + errorFlag = EC_IllegalParameter; + else + floatVal = floatValues[pos]; + } + /* clear value in case of error */ + if (errorFlag.bad()) + floatVal = 0; + return errorFlag; +} + + +OFCondition DcmFloatingPointSingle::getFloat32Array(Float32 *&floatVals) +{ + floatVals = OFstatic_cast(Float32 *, getValue()); + return errorFlag; +} + + +// ******************************** + + +OFCondition DcmFloatingPointSingle::getOFString(OFString &value, + const unsigned long pos, + OFBool /*normalize*/) +{ + Float32 floatVal; + /* get the specified numeric value */ + errorFlag = getFloat32(floatVal, pos); + if (errorFlag.good()) + { + /* ... and convert it to a character string */ + char buffer[64]; + OFStandard::ftoa(buffer, sizeof(buffer), floatVal, 0, 0, 8 /* FLT_DIG + 2 for DICOM FL */); + /* assign result */ + value = buffer; + } + return errorFlag; +} + + +// ******************************** + + +OFCondition DcmFloatingPointSingle::putFloat32(const Float32 floatVal, + const unsigned long pos) +{ + Float32 val = floatVal; + errorFlag = changeValue(&val, OFstatic_cast(Uint32, sizeof(Float32) * pos), OFstatic_cast(Uint32, sizeof(Float32))); + return errorFlag; +} + + +OFCondition DcmFloatingPointSingle::putFloat32Array(const Float32 *floatVals, + const unsigned long numFloats) +{ + errorFlag = EC_Normal; + if (numFloats > 0) + { + /* check for valid float data */ + if (floatVals != NULL) + errorFlag = putValue(floatVals, OFstatic_cast(Uint32, sizeof(Float32) * OFstatic_cast(size_t, numFloats))); + else + errorFlag = EC_CorruptedData; + } else + putValue(NULL, 0); + + return errorFlag; +} + + +// ******************************** + + +OFCondition DcmFloatingPointSingle::putString(const char *stringVal) +{ + /* determine length of the string value */ + const size_t stringLen = (stringVal != NULL) ? strlen(stringVal) : 0; + /* call the real function */ + return putString(stringVal, OFstatic_cast(Uint32, stringLen)); +} + + +OFCondition DcmFloatingPointSingle::putString(const char *stringVal, + const Uint32 stringLen) +{ + errorFlag = EC_Normal; + /* determine VM of the string */ + const unsigned long vm = DcmElement::determineVM(stringVal, stringLen); + if (vm > 0) + { + Float32 *field = new Float32[vm]; + OFBool success = OFFalse; + OFString value; + size_t pos = 0; + /* retrieve float data from character string */ + for (unsigned long i = 0; (i < vm) && errorFlag.good(); i++) + { + /* get specified value from multi-valued string */ + pos = DcmElement::getValueFromString(stringVal, pos, stringLen, value); + if (!value.empty()) + { + field[i] = OFstatic_cast(Float32, OFStandard::atof(value.c_str(), &success)); + if (!success) + errorFlag = EC_CorruptedData; + } else + errorFlag = EC_CorruptedData; + } + /* set binary data as the element value */ + if (errorFlag.good()) + errorFlag = putFloat32Array(field, vm); + /* delete temporary buffer */ + delete[] field; + } else + errorFlag = putValue(NULL, 0); + return errorFlag; +} + + +// ******************************** + + +OFCondition DcmFloatingPointSingle::verify(const OFBool autocorrect) +{ + /* check for valid value length */ + if (getLengthField() % (sizeof(Float32)) != 0) + { + errorFlag = EC_CorruptedData; + if (autocorrect) + { + /* strip to valid length */ + setLengthField(getLengthField() - (getLengthField() % OFstatic_cast(Uint32, sizeof(Float32)))); + } + } else + errorFlag = EC_Normal; + return errorFlag; +} diff --git a/dcmdata/libsrc/dcvris.cc b/dcmdata/libsrc/dcvris.cc new file mode 100644 index 00000000..941775b3 --- /dev/null +++ b/dcmdata/libsrc/dcvris.cc @@ -0,0 +1,142 @@ +/* + * + * Copyright (C) 1994-2010, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Gerd Ehlers, Andreas Barth + * + * Purpose: Implementation of class DcmIntegerString + * + */ + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/dcmdata/dcvris.h" +#include "dcmtk/ofstd/ofstring.h" + +#define INCLUDE_CSTDIO +#include "dcmtk/ofstd/ofstdinc.h" + + +#define MAX_IS_LENGTH 12 + + +// ******************************** + + +DcmIntegerString::DcmIntegerString(const DcmTag &tag, + const Uint32 len) + : DcmByteString(tag, len) +{ + setMaxLength(MAX_IS_LENGTH); + setNonSignificantChars(" \\"); +} + + +DcmIntegerString::DcmIntegerString(const DcmIntegerString &old) + : DcmByteString(old) +{ +} + + +DcmIntegerString::~DcmIntegerString() +{ +} + + +DcmIntegerString &DcmIntegerString::operator=(const DcmIntegerString &obj) +{ + DcmByteString::operator=(obj); + return *this; +} + + +OFCondition DcmIntegerString::copyFrom(const DcmObject& rhs) +{ + if (this != &rhs) + { + if (rhs.ident() != ident()) return EC_IllegalCall; + *this = OFstatic_cast(const DcmIntegerString &, rhs); + } + return EC_Normal; +} + + +// ******************************** + + +DcmEVR DcmIntegerString::ident() const +{ + return EVR_IS; +} + + +OFCondition DcmIntegerString::checkValue(const OFString &vm, + const OFBool /*oldFormat*/) +{ + OFString strVal; + /* get "raw value" without any modifications (if possible) */ + OFCondition l_error = getStringValue(strVal); + if (l_error.good()) + l_error = DcmIntegerString::checkStringValue(strVal, vm); + return l_error; +} + + +// ******************************** + + +OFCondition DcmIntegerString::getSint32(Sint32 &sintVal, + const unsigned long pos) +{ + /* get integer string value */ + OFString str; + OFCondition l_error = getOFString(str, pos, OFTrue); + if (l_error.good()) + { + /* convert string to integer value */ +#if SIZEOF_LONG == 8 + if (sscanf(str.c_str(), "%d", &sintVal) != 1) +#else + if (sscanf(str.c_str(), "%ld", &sintVal) != 1) +#endif + l_error = EC_CorruptedData; + } + return l_error; +} + + +// ******************************** + + +OFCondition DcmIntegerString::getOFString(OFString &stringVal, + const unsigned long pos, + OFBool normalize) +{ + /* call inherited method */ + OFCondition l_error = DcmByteString::getOFString(stringVal, pos, normalize); + /* normalize string if required */ + if (l_error.good() && normalize) + normalizeString(stringVal, !MULTIPART, DELETE_LEADING, DELETE_TRAILING); + return l_error; +} + + +// ******************************** + + +OFCondition DcmIntegerString::checkStringValue(const OFString &value, + const OFString &vm) +{ + return DcmByteString::checkStringValue(value, vm, "is", 8, MAX_IS_LENGTH); +} diff --git a/dcmdata/libsrc/dcvrlo.cc b/dcmdata/libsrc/dcvrlo.cc new file mode 100644 index 00000000..5d200174 --- /dev/null +++ b/dcmdata/libsrc/dcvrlo.cc @@ -0,0 +1,118 @@ +/* + * + * Copyright (C) 1994-2013, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Gerd Ehlers, Andreas Barth + * + * Purpose: Implementation class DcmLongString + * + */ + + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/dcmdata/dcvrlo.h" + + +// ******************************** + + +DcmLongString::DcmLongString(const DcmTag &tag, + const Uint32 len) + : DcmCharString(tag, len) +{ + setMaxLength(64); + setNonSignificantChars(" \\"); + setDelimiterChars("\\"); +} + + +DcmLongString::DcmLongString(const DcmLongString &old) + : DcmCharString(old) +{ +} + + +DcmLongString::~DcmLongString() +{ +} + + +DcmLongString &DcmLongString::operator=(const DcmLongString &obj) +{ + DcmCharString::operator=(obj); + return *this; +} + + +OFCondition DcmLongString::copyFrom(const DcmObject& rhs) +{ + if (this != &rhs) + { + if (rhs.ident() != ident()) return EC_IllegalCall; + *this = OFstatic_cast(const DcmLongString &, rhs); + } + return EC_Normal; +} + + +// ******************************** + + +DcmEVR DcmLongString::ident() const +{ + return EVR_LO; +} + + +OFCondition DcmLongString::checkValue(const OFString &vm, + const OFBool /*oldFormat*/) +{ + OFString strVal; + /* get "raw value" without any modifications (if possible) */ + OFCondition l_error = getStringValue(strVal); + if (l_error.good()) + { + OFString charset; + /* try to determine the value of the SpecificCharacterSet element */ + getSpecificCharacterSet(charset); + l_error = DcmLongString::checkStringValue(strVal, vm, charset); + } + return l_error; +} + + +// ******************************** + + +OFCondition DcmLongString::getOFString(OFString &stringVal, + const unsigned long pos, + OFBool normalize) +{ + OFCondition l_error = DcmCharString::getOFString(stringVal, pos, normalize); + if (l_error.good() && normalize) + normalizeString(stringVal, !MULTIPART, DELETE_LEADING, DELETE_TRAILING); + return l_error; +} + + +// ******************************** + + +OFCondition DcmLongString::checkStringValue(const OFString &value, + const OFString &vm, + const OFString &charset) +{ + return DcmByteString::checkStringValue(value, vm, "lo", 12, 0 /* maxLen: no check */, charset); +} diff --git a/dcmdata/libsrc/dcvrlt.cc b/dcmdata/libsrc/dcvrlt.cc new file mode 100644 index 00000000..6c1969b1 --- /dev/null +++ b/dcmdata/libsrc/dcvrlt.cc @@ -0,0 +1,131 @@ +/* + * + * Copyright (C) 1994-2013, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Gerd Ehlers, Andreas Barth + * + * Purpose: Implementation of class DcmLongText + * + */ + + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/dcmdata/dcvrlt.h" + + +// ******************************** + + +DcmLongText::DcmLongText(const DcmTag &tag, + const Uint32 len) + : DcmCharString(tag, len) +{ + setMaxLength(10240); +} + + +DcmLongText::DcmLongText(const DcmLongText& old) + : DcmCharString(old) +{ +} + + +DcmLongText::~DcmLongText() +{ +} + + +DcmLongText &DcmLongText::operator=(const DcmLongText &obj) +{ + DcmCharString::operator=(obj); + return *this; +} + + +OFCondition DcmLongText::copyFrom(const DcmObject& rhs) +{ + if (this != &rhs) + { + if (rhs.ident() != ident()) return EC_IllegalCall; + *this = OFstatic_cast(const DcmLongText &, rhs); + } + return EC_Normal; +} + + +// ******************************** + + +DcmEVR DcmLongText::ident() const +{ + return EVR_LT; +} + + +OFCondition DcmLongText::checkValue(const OFString & /*vm*/, + const OFBool /*oldFormat*/) +{ + OFString strVal; + /* get "raw value" without any modifications (if possible) */ + OFCondition l_error = getStringValue(strVal); + if (l_error.good()) + { + OFString charset; + /* try to determine the value of the SpecificCharacterSet element */ + getSpecificCharacterSet(charset); + l_error = DcmLongText::checkStringValue(strVal, charset); + } + return l_error; +} + + +unsigned long DcmLongText::getVM() +{ + /* value multiplicity is 1 for non-empty string, 0 otherwise */ + return (getRealLength() > 0) ? 1 : 0; +} + + +// ******************************** + + +OFCondition DcmLongText::getOFString(OFString &stringVal, + const unsigned long /*pos*/, + OFBool normalize) +{ + /* treat backslash as a normal character */ + return getOFStringArray(stringVal, normalize); +} + + +OFCondition DcmLongText::getOFStringArray(OFString &stringVal, + OFBool normalize) +{ + /* get string value without handling the "\" as a delimiter */ + OFCondition l_error = getStringValue(stringVal); + if (l_error.good() && normalize) + normalizeString(stringVal, !MULTIPART, !DELETE_LEADING, DELETE_TRAILING); + return l_error; +} + + +// ******************************** + + +OFCondition DcmLongText::checkStringValue(const OFString &value, + const OFString &charset) +{ + return DcmByteString::checkStringValue(value, "" /* vm */, "lt", 14, 0 /* maxLen: no check */, charset); +} diff --git a/dcmdata/libsrc/dcvrobow.cc b/dcmdata/libsrc/dcvrobow.cc new file mode 100644 index 00000000..3818d345 --- /dev/null +++ b/dcmdata/libsrc/dcvrobow.cc @@ -0,0 +1,815 @@ +/* + * + * Copyright (C) 1994-2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Gerd Ehlers, Andreas Barth + * + * Purpose: Implementation of class DcmOtherByteOtherWord + * + */ + + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/ofstd/ofstd.h" +#include "dcmtk/ofstd/ofstream.h" +#include "dcmtk/ofstd/ofuuid.h" + +#include "dcmtk/dcmdata/dcvrobow.h" +#include "dcmtk/dcmdata/dcdeftag.h" +#include "dcmtk/dcmdata/dcswap.h" +#include "dcmtk/dcmdata/dcuid.h" /* for UID generation */ + +#define INCLUDE_CSTDIO +#define INCLUDE_CSTDLIB +#define INCLUDE_CSTRING +#include "dcmtk/ofstd/ofstdinc.h" + + +// ******************************** + + +DcmOtherByteOtherWord::DcmOtherByteOtherWord(const DcmTag &tag, + const Uint32 len) +: DcmElement(tag, len) +, compactAfterTransfer(OFFalse) +{ +} + + +DcmOtherByteOtherWord::DcmOtherByteOtherWord(const DcmOtherByteOtherWord &old) +: DcmElement(old) +, compactAfterTransfer(old.compactAfterTransfer) +{ +} + + +DcmOtherByteOtherWord::~DcmOtherByteOtherWord() +{ +} + + +DcmOtherByteOtherWord &DcmOtherByteOtherWord::operator=(const DcmOtherByteOtherWord &obj) +{ + DcmElement::operator=(obj); + compactAfterTransfer = obj.compactAfterTransfer; + return *this; +} + + +int DcmOtherByteOtherWord::compare(const DcmElement& rhs) const +{ + int result = DcmElement::compare(rhs); + if (result != 0) + { + return result; + } + + /* cast away constness (dcmdata is not const correct...) */ + DcmOtherByteOtherWord* myThis = NULL; + DcmOtherByteOtherWord* myRhs = NULL; + myThis = OFconst_cast(DcmOtherByteOtherWord*, this); + myRhs = OFstatic_cast(DcmOtherByteOtherWord*, OFconst_cast(DcmElement*, &rhs)); + + unsigned long thisLength = myThis->getLength(); + unsigned long rhsLength= myRhs->getLength(); + Uint8* thisData = OFstatic_cast(Uint8*, myThis->getValue()); + Uint8* rhsData = OFstatic_cast(Uint8*, myRhs->getValue()); + unsigned long maxLength = (thisLength > rhsLength) ? rhsLength : thisLength; + /* iterate over all components and test equality */ + for (unsigned long count = 0; count < maxLength; count++) + { + if (thisData[count] > rhsData[count]) + { + return 1; + } + else if (thisData[count] < rhsData[count]) + { + return -1; + } + /* otherwise they are equal, continue comparison */ + } + + /* we get here if all values are equal. Now look at the number of components. */ + if (thisLength < rhsLength) + { + return -1; + } + else if (thisLength > rhsLength) + { + return 1; + } + + /* all values as well as VM equal: objects are equal */ + return 0; +} + + +OFCondition DcmOtherByteOtherWord::copyFrom(const DcmObject& rhs) +{ + if (this != &rhs) + { + if (rhs.ident() != ident()) return EC_IllegalCall; + *this = OFstatic_cast(const DcmOtherByteOtherWord &, rhs); + } + return EC_Normal; +} + + +// ******************************** + + +DcmEVR DcmOtherByteOtherWord::ident() const +{ + return getTag().getEVR(); +} + + +OFCondition DcmOtherByteOtherWord::checkValue(const OFString & /*vm*/, + const OFBool /*oldFormat*/) +{ + /* currently no checks are performed */ + return EC_Normal; +} + + +unsigned long DcmOtherByteOtherWord::getVM() +{ + /* value multiplicity for OB/OW is defined as 1 */ + return 1; +} + + +OFCondition DcmOtherByteOtherWord::setVR(DcmEVR vr) +{ + setTagVR(vr); + return EC_Normal; +} + + +// ******************************** + + +void DcmOtherByteOtherWord::print(STD_NAMESPACE ostream&out, + const size_t flags, + const int level, + const char * /*pixelFileName*/, + size_t * /*pixelCounter*/) +{ + if (valueLoaded()) + { + const DcmEVR evr = getTag().getEVR(); + Uint16 *wordValues = NULL; + Uint8 *byteValues = NULL; + /* get 8 or 16 bit data respectively */ + if (evr == EVR_OW || evr == EVR_lt) + errorFlag = getUint16Array(wordValues); + else + errorFlag = getUint8Array(byteValues); + /* check data */ + if ((wordValues != NULL) || (byteValues != NULL)) + { + /* determine number of values to be printed */ + const unsigned int vrSize = (evr == EVR_OW || evr == EVR_lt) ? 4 : 2; + const unsigned long count = (evr == EVR_OW || evr == EVR_lt) ? (getLengthField() / 2) : getLengthField(); + unsigned long expectedLength = count * (vrSize + 1) - 1; + const unsigned long printCount = + ((expectedLength > DCM_OptPrintLineLength) && (flags & DCMTypes::PF_shortenLongTagValues)) ? + (DCM_OptPrintLineLength - 3 /* for "..." */ + 1 /* for last "\" */) / (vrSize + 1) : count; + unsigned long printedLength = printCount * (vrSize + 1) - 1; + /* print line start with tag and VR */ + printInfoLineStart(out, flags, level); + /* print multiple values */ + if (printCount > 0) + { + out << STD_NAMESPACE hex << STD_NAMESPACE setfill('0'); + if (evr == EVR_OW || evr == EVR_lt) + { + /* print word values in hex mode */ + out << STD_NAMESPACE setw(vrSize) << (*(wordValues++)); + for (unsigned long i = 1; i < printCount; i++) + out << "\\" << STD_NAMESPACE setw(vrSize) << (*(wordValues++)); + } else { + /* print byte values in hex mode */ + out << STD_NAMESPACE setw(vrSize) << OFstatic_cast(int, *(byteValues++)); + for (unsigned long i = 1; i < printCount; i++) + out << "\\" << STD_NAMESPACE setw(vrSize) << OFstatic_cast(int, *(byteValues++)); + } + /* reset i/o manipulators */ + out << STD_NAMESPACE dec << STD_NAMESPACE setfill(' '); + } + /* print trailing "..." if data has been truncated */ + if (printCount < count) + { + out << "..."; + printedLength += 3; + } + /* print line end with length, VM and tag name */ + printInfoLineEnd(out, flags, printedLength); + } else + printInfoLine(out, flags, level, "(no value available)"); + } else + printInfoLine(out, flags, level, "(not loaded)"); +} + + +void DcmOtherByteOtherWord::printPixel(STD_NAMESPACE ostream&out, + const size_t flags, + const int level, + const char *pixelFileName, + size_t *pixelCounter) +{ + if (pixelFileName != NULL) + { + /* create filename for pixel data file */ + OFString fname = pixelFileName; + fname += "."; + if (pixelCounter != NULL) + { + char num[20]; + sprintf(num, "%ld", OFstatic_cast(long, (*pixelCounter)++)); + fname += num; + } + fname += ".raw"; + /* create reference to pixel data file in dump output */ + OFString str = "="; + str += fname; + printInfoLine(out, flags, level, str.c_str(), NULL /*tag*/, OFFalse /*isInfo*/); + /* check whether pixel data file already exists */ + if (!OFStandard::fileExists(fname)) + { + /* create binary file for pixel data */ + FILE *file = fopen(fname.c_str(), "wb"); + if (file != NULL) + { + if (getTag().getEVR() == EVR_OW || getTag().getEVR() == EVR_lt) + { + /* write 16 bit data in little endian byte-order */ + Uint16 *data = NULL; + getUint16Array(data); + if (data != NULL) + { + swapIfNecessary(EBO_LittleEndian, gLocalByteOrder, data, getLengthField(), sizeof(Uint16)); + setByteOrder(EBO_LittleEndian); + fwrite(data, sizeof(Uint16), OFstatic_cast(size_t, getLengthField() / sizeof(Uint16)), file); + } + } else { + Uint8 *data = NULL; + getUint8Array(data); + if (data != NULL) + fwrite(data, sizeof(Uint8), OFstatic_cast(size_t, getLengthField()), file); + } + fclose(file); + } else { + DCMDATA_WARN("DcmOtherByteOtherWord: Can't open output file for pixel data: " << fname); + } + } else { + DCMDATA_WARN("DcmOtherByteOtherWord: Output file for pixel data already exists, skipping: " << fname); + } + } else + DcmOtherByteOtherWord::print(out, flags, level, pixelFileName, pixelCounter); +} + + +// ******************************** + + +OFCondition DcmOtherByteOtherWord::alignValue() +{ + errorFlag = EC_Normal; + if ((getTag().getEVR() != EVR_OW && getTag().getEVR() != EVR_lt) && (getLengthField() > 0) && ((getLengthField() & 1) != 0)) + { + // We have an odd number of bytes. This should never happen and is certainly not allowed in DICOM. + // To fix this problem, we will add a zero pad byte at the end of the value field. + // This requires us to load the value field into memory, which may very well be a problem + // if this is part of a very large multi-frame object. + Uint8 *bytes = OFstatic_cast(Uint8 *, getValue(getByteOrder())); + + // getValue() could call loadValue() which then calls postLoadValue() + // which in turn calls this function again. Thus, we have to make sure + // that the length field is still odd after getValue() returns. + if (bytes && (getLengthField() & 1) != 0) + { + // newValueField always allocates an even number of bytes + // and sets the pad byte to zero, so we can safely increase Length here + setLengthField(getLengthField() + 1); + } + } + return errorFlag; +} + + +void DcmOtherByteOtherWord::postLoadValue() +{ + if (dcmEnableAutomaticInputDataCorrection.get()) + alignValue(); +} + + +// ******************************** + + +OFCondition DcmOtherByteOtherWord::putUint8Array(const Uint8 *byteValue, + const unsigned long numBytes) +{ + errorFlag = EC_Normal; + if (numBytes > 0) + { + /* check for valid 8 bit data */ + if ((byteValue != NULL) && (getTag().getEVR() != EVR_OW && getTag().getEVR() != EVR_lt)) + { + errorFlag = putValue(byteValue, OFstatic_cast(Uint32, sizeof(Uint8) * OFstatic_cast(size_t, numBytes))); + alignValue(); + } else + errorFlag = EC_CorruptedData; + } else + putValue(NULL, 0); + return errorFlag; +} + + +OFCondition DcmOtherByteOtherWord::putUint16Array(const Uint16 *wordValue, + const unsigned long numWords) +{ + errorFlag = EC_Normal; + if (numWords > 0) + { + /* check for valid 16 bit data */ + if ((wordValue != NULL) && (getTag().getEVR() == EVR_OW || getTag().getEVR() == EVR_lt)) + errorFlag = putValue(wordValue, OFstatic_cast(Uint32, sizeof(Uint16) * OFstatic_cast(size_t, numWords))); + else + errorFlag = EC_CorruptedData; + } else + errorFlag = putValue(NULL, 0); + return errorFlag; +} + + +// ******************************** + + +OFCondition DcmOtherByteOtherWord::createUint8Array(const Uint32 numBytes, + Uint8 *&bytes) +{ + /* check value representation */ + if ((getTag().getEVR() != EVR_OW) && (getTag().getEVR() != EVR_lt)) + errorFlag = createEmptyValue(OFstatic_cast(Uint32, sizeof(Uint8) * OFstatic_cast(size_t, numBytes))); + else + errorFlag = EC_CorruptedData; + if (errorFlag.good()) + bytes = OFstatic_cast(Uint8 *, this->getValue()); + else + bytes = NULL; + return errorFlag; +} + + +OFCondition DcmOtherByteOtherWord::createUint16Array(const Uint32 numWords, + Uint16 *&words) +{ + /* check value representation */ + if ((getTag().getEVR() == EVR_OW) || (getTag().getEVR() == EVR_lt)) + errorFlag = createEmptyValue(OFstatic_cast(Uint32, sizeof(Uint16) * OFstatic_cast(size_t, numWords))); + else + errorFlag = EC_CorruptedData; + if (errorFlag.good()) + words = OFstatic_cast(Uint16 *, this->getValue()); + else + words = NULL; + return errorFlag; +} + + +// ******************************** + + +OFCondition DcmOtherByteOtherWord::putString(const char *stringVal) +{ + /* determine length of the string value */ + const size_t stringLen = (stringVal != NULL) ? strlen(stringVal) : 0; + /* call the real function */ + return putString(stringVal, OFstatic_cast(Uint32, stringLen)); +} + + +OFCondition DcmOtherByteOtherWord::putString(const char *stringVal, + const Uint32 stringLen) +{ + errorFlag = EC_Normal; + /* determine VM of the string */ + unsigned long vm = DcmElement::determineVM(stringVal, stringLen); + if (vm > 0) + { + const DcmEVR evr = getTag().getEVR(); + Uint8 *byteField = NULL; + Uint16 *wordField = NULL; + /* create new value field */ + if (evr == EVR_OW || evr == EVR_lt) + wordField = new Uint16[vm]; + else + byteField = new Uint8[vm]; + Uint16 intVal = 0; + OFString value; + size_t pos = 0; + /* retrieve binary data from hexa-decimal string */ + for (unsigned long i = 0; (i < vm) && errorFlag.good(); i++) + { + /* get specified value from multi-valued string */ + pos = DcmElement::getValueFromString(stringVal, pos, stringLen, value); + if (!value.empty()) + { + /* integer overflow is currently not checked! */ + if (sscanf(value.c_str(), "%hx", &intVal) != 1) + errorFlag = EC_CorruptedData; + else if (evr == EVR_OW || evr == EVR_lt) + wordField[i] = OFstatic_cast(Uint16, intVal); + else + byteField[i] = OFstatic_cast(Uint8, intVal); + } else + errorFlag = EC_CorruptedData; + } + /* set binary data as the element value */ + if (errorFlag.good()) + { + if (evr == EVR_OW || evr == EVR_lt) + errorFlag = putUint16Array(wordField, vm); + else + errorFlag = putUint8Array(byteField, vm); + } + /* delete temporary buffers */ + delete[] byteField; + delete[] wordField; + } else + putValue(NULL, 0); + return errorFlag; +} + + +// ******************************** + + +OFCondition DcmOtherByteOtherWord::getUint8(Uint8 &byteVal, + const unsigned long pos) +{ + /* get 8 bit data */ + Uint8 *uintValues = NULL; + errorFlag = getUint8Array(uintValues); + /* check data before returning */ + if (errorFlag.good()) + { + if (uintValues == NULL) + errorFlag = EC_IllegalCall; + else if (pos >= getLength() /*bytes*/) + errorFlag = EC_IllegalParameter; + else + byteVal = uintValues[pos]; + } + /* clear value in case of error */ + if (errorFlag.bad()) + byteVal = 0; + return errorFlag; +} + + +OFCondition DcmOtherByteOtherWord::getUint8Array(Uint8 *&byteVals) +{ + errorFlag = EC_Normal; + if (getTag().getEVR() != EVR_OW && getTag().getEVR() != EVR_lt) + byteVals = OFstatic_cast(Uint8 *, getValue()); + else + errorFlag = EC_IllegalCall; + return errorFlag; +} + + +// ******************************** + + +OFCondition DcmOtherByteOtherWord::getUint16(Uint16 &wordVal, + const unsigned long pos) +{ + Uint16 *uintValues = NULL; + errorFlag = getUint16Array(uintValues); + /* check data before returning */ + if (errorFlag.good()) + { + if (uintValues == NULL) + errorFlag = EC_IllegalCall; + else if (pos >= getLength() / sizeof(Uint16) /*words*/) + errorFlag = EC_IllegalParameter; + else + wordVal = uintValues[pos]; + } + /* clear value in case of error */ + if (errorFlag.bad()) + wordVal = 0; + return errorFlag; +} + + +OFCondition DcmOtherByteOtherWord::getUint16Array(Uint16 *&wordVals) +{ + errorFlag = EC_Normal; + if (getTag().getEVR() == EVR_OW || getTag().getEVR() == EVR_lt) + wordVals = OFstatic_cast(Uint16 *, getValue()); + else + errorFlag = EC_IllegalCall; + return errorFlag; +} + + +// ******************************** + + +OFCondition DcmOtherByteOtherWord::getOFString(OFString &stringVal, + const unsigned long pos, + OFBool /*normalize*/) +{ + if (getTag().getEVR() == EVR_OW || getTag().getEVR() == EVR_lt) + { + Uint16 uint16Val; + /* get the specified numeric value (16 bit) */ + errorFlag = getUint16(uint16Val, pos); + if (errorFlag.good()) + { + /* ... and convert it to a character string (hex mode) */ + char buffer[32]; + sprintf(buffer, "%4.4hx", uint16Val); + /* assign result */ + stringVal = buffer; + } + } else { + Uint8 uint8Val; + /* get the specified numeric value (8 bit) */ + errorFlag = getUint8(uint8Val, pos); + if (errorFlag.good()) + { + /* ... and convert it to a character string (hex mode) */ + char buffer[32]; + sprintf(buffer, "%2.2hx", OFstatic_cast(unsigned short, uint8Val)); + /* assign result */ + stringVal = buffer; + } + } + return errorFlag; +} + + +OFCondition DcmOtherByteOtherWord::getOFStringArray(OFString &stringVal, + OFBool /*normalize*/) +{ + if (getTag().getEVR() == EVR_OW || getTag().getEVR() == EVR_lt) + { + /* get array of 16 bit values */ + Uint16 *uint16Vals = OFstatic_cast(Uint16 *, getValue()); + const size_t count = OFstatic_cast(size_t, getLength() / sizeof(Uint16)); + if ((uint16Vals != NULL) && (count > 0)) + { + OFOStringStream stream; + /* output first value in hexadecimal format */ + stream << STD_NAMESPACE hex << STD_NAMESPACE setfill('0') + << STD_NAMESPACE setw(4) << *(uint16Vals++); + /* for all other array elements ... */ + for (size_t i = 1; i < count; i++) + stream << "\\" << STD_NAMESPACE setw(4) << *(uint16Vals++); + stream << OFStringStream_ends; + /* convert string stream into a character string */ + OFSTRINGSTREAM_GETSTR(stream, buffer_str) + stringVal.assign(buffer_str); + OFSTRINGSTREAM_FREESTR(buffer_str) + errorFlag = EC_Normal; + } else + errorFlag = EC_IllegalCall; + } else { + /* get array of 8 bit values */ + Uint8 *uint8Vals = OFstatic_cast(Uint8 *, getValue()); + const size_t count = OFstatic_cast(size_t, getLength()); + if ((uint8Vals != NULL) && (count > 0)) + { + OFOStringStream stream; + /* output first value in hexadecimal format */ + stream << STD_NAMESPACE hex << STD_NAMESPACE setfill('0') + << STD_NAMESPACE setw(2) << OFstatic_cast(int, *(uint8Vals++)); + /* for all other array elements ... */ + for (size_t i = 1; i < count; i++) + stream << "\\" << STD_NAMESPACE setw(2) << OFstatic_cast(int, *(uint8Vals++)); + stream << OFStringStream_ends; + /* convert string stream into a character string */ + OFSTRINGSTREAM_GETSTR(stream, buffer_str) + stringVal.assign(buffer_str); + OFSTRINGSTREAM_FREESTR(buffer_str) + errorFlag = EC_Normal; + } else + errorFlag = EC_IllegalCall; + } + return errorFlag; +} + + +// ******************************** + + +OFCondition DcmOtherByteOtherWord::verify(const OFBool autocorrect) +{ + errorFlag = EC_Normal; + if (autocorrect) + errorFlag = alignValue(); + return errorFlag; +} + + +// ******************************** + + +OFBool DcmOtherByteOtherWord::canWriteXfer(const E_TransferSyntax newXfer, + const E_TransferSyntax /*oldXfer*/) +{ + DcmXfer newXferSyn(newXfer); + return (getTag() != DCM_PixelData) || !newXferSyn.isEncapsulated(); +} + + +// ******************************** + + +OFCondition DcmOtherByteOtherWord::write( + DcmOutputStream &outStream, + const E_TransferSyntax oxfer, + const E_EncodingType enctype, + DcmWriteCache *wcache) +{ + if (getTransferState() == ERW_notInitialized) + errorFlag = EC_IllegalCall; + else + { + if (getTransferState() == ERW_init) + { + // if the attribute value is in file, we should call compact() if the write + // operation causes the value to be loaded into main memory, which can happen + // for odd length attributes. + compactAfterTransfer = ! valueLoaded(); + + // this call may cause the attribute to be loaded into memory + alignValue(); + } + + // call inherited method + errorFlag = DcmElement::write(outStream, oxfer, enctype, wcache); + } + + // if the write operation has completed successfully, call compact if the + // attribute value resided in file prior to the write operation. + if (errorFlag.good() && compactAfterTransfer) compact(); + + // return error status + return errorFlag; +} + + +OFCondition DcmOtherByteOtherWord::writeSignatureFormat( + DcmOutputStream &outStream, + const E_TransferSyntax oxfer, + const E_EncodingType enctype, + DcmWriteCache *wcache) +{ + if (getTransferState() == ERW_notInitialized) + errorFlag = EC_IllegalCall; + else + { + if (getTransferState() == ERW_init) + { + // if the attribute value is in file, we should call compact() if the write + // operation causes the value to be loaded into main memory, which can happen + // for odd length attributes. + compactAfterTransfer = ! valueLoaded(); + + // this call may cause the attribute to be loaded into memory + alignValue(); + } + + // call inherited method + errorFlag = DcmElement::writeSignatureFormat(outStream, oxfer, enctype, wcache); + } + + // if the write operation has completed successfully, call compact if the + // attribute value resided in file prior to the write operation. + if (errorFlag.good() && compactAfterTransfer) compact(); + + // return error status + return errorFlag; +} + + +// ******************************** + + +OFCondition DcmOtherByteOtherWord::writeXML(STD_NAMESPACE ostream &out, + const size_t flags) +{ + /* OB/OW data requires special handling in the Native DICOM Model format */ + if (flags & DCMTypes::XF_useNativeModel) + { + /* write XML start tag */ + writeXMLStartTag(out, flags); + /* for an empty value field, we do not need to do anything */ + if (getLengthField() > 0) + { + /* encode binary data as Base64 */ + if (flags & DCMTypes::XF_encodeBase64) + { + const DcmEVR evr = getTag().getEVR(); + out << ""; + Uint8 *byteValues = OFstatic_cast(Uint8 *, getValue()); + if ((evr == EVR_OW) || (evr == EVR_lt)) + { + /* Base64 encoder requires big endian input data */ + swapIfNecessary(EBO_BigEndian, gLocalByteOrder, byteValues, getLengthField(), sizeof(Uint16)); + /* update the byte order indicator variable correspondingly */ + setByteOrder(EBO_BigEndian); + } + OFStandard::encodeBase64(out, byteValues, OFstatic_cast(size_t, getLengthField())); + out << "" << OFendl; + } else { + /* generate a new UID but the binary data is not (yet) written. */ + OFUUID uuid; + out << "" << OFendl; + } + } + /* write XML end tag */ + writeXMLEndTag(out, flags); + } else { + /* XML start tag: */ + if (!(flags & DCMTypes::XF_writeBinaryData)) + writeXMLStartTag(out, flags, "binary=\"hidden\""); + else if (flags & DCMTypes::XF_encodeBase64) + writeXMLStartTag(out, flags, "binary=\"base64\""); + else + writeXMLStartTag(out, flags, "binary=\"yes\""); + /* write element value (if loaded) */ + if (valueLoaded() && (flags & DCMTypes::XF_writeBinaryData)) + { + const DcmEVR evr = getTag().getEVR(); + /* encode binary data as Base64 */ + if (flags & DCMTypes::XF_encodeBase64) + { + Uint8 *byteValues = OFstatic_cast(Uint8 *, getValue()); + if ((evr == EVR_OW) || (evr == EVR_lt)) + { + /* Base64 encoder requires big endian input data */ + swapIfNecessary(EBO_BigEndian, gLocalByteOrder, byteValues, getLengthField(), sizeof(Uint16)); + /* update the byte order indicator variable correspondingly */ + setByteOrder(EBO_BigEndian); + } + OFStandard::encodeBase64(out, byteValues, OFstatic_cast(size_t, getLengthField())); + } else { + if ((evr == EVR_OW) || (evr == EVR_lt)) + { + /* get and check 16 bit data */ + Uint16 *wordValues = NULL; + if (getUint16Array(wordValues).good() && (wordValues != NULL)) + { + const unsigned long count = getLengthField() / OFstatic_cast(unsigned long, sizeof(Uint16)); + out << STD_NAMESPACE hex << STD_NAMESPACE setfill('0'); + /* print word values in hex mode */ + out << STD_NAMESPACE setw(4) << (*(wordValues++)); + for (unsigned long i = 1; i < count; i++) + out << "\\" << STD_NAMESPACE setw(4) << (*(wordValues++)); + /* reset i/o manipulators */ + out << STD_NAMESPACE dec << STD_NAMESPACE setfill(' '); + } + } else { + /* get and check 8 bit data */ + Uint8 *byteValues = NULL; + if (getUint8Array(byteValues).good() && (byteValues != NULL)) + { + const unsigned long count = getLengthField(); + out << STD_NAMESPACE hex << STD_NAMESPACE setfill('0'); + /* print byte values in hex mode */ + out << STD_NAMESPACE setw(2) << OFstatic_cast(int, *(byteValues++)); + for (unsigned long i = 1; i < count; i++) + out << "\\" << STD_NAMESPACE setw(2) << OFstatic_cast(int, *(byteValues++)); + /* reset i/o manipulators */ + out << STD_NAMESPACE dec << STD_NAMESPACE setfill(' '); + } + } + } + } + /* XML end tag: */ + writeXMLEndTag(out, flags); + } + /* always report success */ + return EC_Normal; +} diff --git a/dcmdata/libsrc/dcvrod.cc b/dcmdata/libsrc/dcvrod.cc new file mode 100644 index 00000000..8200617d --- /dev/null +++ b/dcmdata/libsrc/dcvrod.cc @@ -0,0 +1,154 @@ +/* + * + * Copyright (C) 2013, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Joerg Riesmeier + * + * Purpose: Implementation of class DcmOtherDouble + * + */ + + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/ofstd/ofuuid.h" + +#include "dcmtk/dcmdata/dcvrod.h" +#include "dcmtk/dcmdata/dcvrfd.h" +#include "dcmtk/dcmdata/dcswap.h" +#include "dcmtk/dcmdata/dcuid.h" /* for UID generation */ + + +// ******************************** + + +DcmOtherDouble::DcmOtherDouble(const DcmTag &tag, + const Uint32 len) + : DcmFloatingPointDouble(tag, len) +{ +} + + +DcmOtherDouble::DcmOtherDouble(const DcmOtherDouble &old) + : DcmFloatingPointDouble(old) +{ +} + + +DcmOtherDouble::~DcmOtherDouble() +{ +} + + +DcmOtherDouble &DcmOtherDouble::operator=(const DcmOtherDouble &obj) +{ + DcmFloatingPointDouble::operator=(obj); + return *this; +} + + +OFCondition DcmOtherDouble::copyFrom(const DcmObject& rhs) +{ + if (this != &rhs) + { + if (rhs.ident() != ident()) return EC_IllegalCall; + *this = OFstatic_cast(const DcmOtherDouble &, rhs); + } + return EC_Normal; +} + + +// ******************************** + + +DcmEVR DcmOtherDouble::ident() const +{ + return EVR_OD; +} + + +OFCondition DcmOtherDouble::checkValue(const OFString & /*vm*/, + const OFBool /*oldFormat*/) +{ + /* currently no checks are performed */ + return EC_Normal; +} + + +unsigned long DcmOtherDouble::getVM() +{ + /* value multiplicity for OF is defined as 1 */ + return 1; +} + + +// ******************************** + + +OFCondition DcmOtherDouble::writeXML(STD_NAMESPACE ostream &out, + const size_t flags) +{ + /* always write XML start tag */ + writeXMLStartTag(out, flags); + /* OF data requires special handling in the Native DICOM Model format */ + if (flags & DCMTypes::XF_useNativeModel) + { + /* for an empty value field, we do not need to do anything */ + if (getLengthField() > 0) + { + /* encode binary data as Base64 */ + if (flags & DCMTypes::XF_encodeBase64) + { + out << ""; + Uint8 *byteValues = OFstatic_cast(Uint8 *, getValue()); + /* Base64 encoder requires big endian input data */ + swapIfNecessary(EBO_BigEndian, gLocalByteOrder, byteValues, getLengthField(), sizeof(Float64)); + /* update the byte order indicator variable correspondingly */ + setByteOrder(EBO_BigEndian); + OFStandard::encodeBase64(out, byteValues, OFstatic_cast(size_t, getLengthField())); + out << "" << OFendl; + } else { + /* generate a new UID but the binary data is not (yet) written. */ + OFUUID uuid; + out << "" << OFendl; + } + } + } else { + /* write element value (if loaded) */ + if (valueLoaded()) + { + Float64 *floatValues = NULL; + /* get and check 64 bit float data */ + if (getFloat64Array(floatValues).good() && (floatValues != NULL)) + { + /* increase default precision - see DcmFloatingPointDouble::print() */ + const STD_NAMESPACE streamsize oldPrecision = out.precision(17); + /* we cannot use getVM() since it always returns 1 */ + const size_t count = getLengthField() / sizeof(Float64); + /* print float values with separators */ + out << (*(floatValues++)); + for (unsigned long i = 1; i < count; i++) + out << "\\" << (*(floatValues++)); + /* reset i/o manipulators */ + out.precision(oldPrecision); + } + } + } + /* always write XML end tag */ + writeXMLEndTag(out, flags); + /* always report success */ + return EC_Normal; +} diff --git a/dcmdata/libsrc/dcvrof.cc b/dcmdata/libsrc/dcvrof.cc new file mode 100644 index 00000000..cf0c87ef --- /dev/null +++ b/dcmdata/libsrc/dcvrof.cc @@ -0,0 +1,154 @@ +/* + * + * Copyright (C) 2002-2013, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Joerg Riesmeier + * + * Purpose: Implementation of class DcmOtherFloat + * + */ + + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/ofstd/ofuuid.h" + +#include "dcmtk/dcmdata/dcvrof.h" +#include "dcmtk/dcmdata/dcvrfl.h" +#include "dcmtk/dcmdata/dcswap.h" +#include "dcmtk/dcmdata/dcuid.h" /* for UID generation */ + + +// ******************************** + + +DcmOtherFloat::DcmOtherFloat(const DcmTag &tag, + const Uint32 len) + : DcmFloatingPointSingle(tag, len) +{ +} + + +DcmOtherFloat::DcmOtherFloat(const DcmOtherFloat &old) + : DcmFloatingPointSingle(old) +{ +} + + +DcmOtherFloat::~DcmOtherFloat() +{ +} + + +DcmOtherFloat &DcmOtherFloat::operator=(const DcmOtherFloat &obj) +{ + DcmFloatingPointSingle::operator=(obj); + return *this; +} + + +OFCondition DcmOtherFloat::copyFrom(const DcmObject& rhs) +{ + if (this != &rhs) + { + if (rhs.ident() != ident()) return EC_IllegalCall; + *this = OFstatic_cast(const DcmOtherFloat &, rhs); + } + return EC_Normal; +} + + +// ******************************** + + +DcmEVR DcmOtherFloat::ident() const +{ + return EVR_OF; +} + + +OFCondition DcmOtherFloat::checkValue(const OFString & /*vm*/, + const OFBool /*oldFormat*/) +{ + /* currently no checks are performed */ + return EC_Normal; +} + + +unsigned long DcmOtherFloat::getVM() +{ + /* value multiplicity for OF is defined as 1 */ + return 1; +} + + +// ******************************** + + +OFCondition DcmOtherFloat::writeXML(STD_NAMESPACE ostream &out, + const size_t flags) +{ + /* always write XML start tag */ + writeXMLStartTag(out, flags); + /* OF data requires special handling in the Native DICOM Model format */ + if (flags & DCMTypes::XF_useNativeModel) + { + /* for an empty value field, we do not need to do anything */ + if (getLengthField() > 0) + { + /* encode binary data as Base64 */ + if (flags & DCMTypes::XF_encodeBase64) + { + out << ""; + Uint8 *byteValues = OFstatic_cast(Uint8 *, getValue()); + /* Base64 encoder requires big endian input data */ + swapIfNecessary(EBO_BigEndian, gLocalByteOrder, byteValues, getLengthField(), sizeof(Float32)); + /* update the byte order indicator variable correspondingly */ + setByteOrder(EBO_BigEndian); + OFStandard::encodeBase64(out, byteValues, OFstatic_cast(size_t, getLengthField())); + out << "" << OFendl; + } else { + /* generate a new UID but the binary data is not (yet) written. */ + OFUUID uuid; + out << "" << OFendl; + } + } + } else { + /* write element value (if loaded) */ + if (valueLoaded()) + { + Float32 *floatValues = NULL; + /* get and check 32 bit float data */ + if (getFloat32Array(floatValues).good() && (floatValues != NULL)) + { + /* increase default precision - see DcmFloatingPointSingle::print() */ + const STD_NAMESPACE streamsize oldPrecision = out.precision(8); + /* we cannot use getVM() since it always returns 1 */ + const size_t count = getLengthField() / sizeof(Float32); + /* print float values with separators */ + out << (*(floatValues++)); + for (unsigned long i = 1; i < count; i++) + out << "\\" << (*(floatValues++)); + /* reset i/o manipulators */ + out.precision(oldPrecision); + } + } + } + /* always write XML end tag */ + writeXMLEndTag(out, flags); + /* always report success */ + return EC_Normal; +} diff --git a/dcmdata/libsrc/dcvrpn.cc b/dcmdata/libsrc/dcvrpn.cc new file mode 100644 index 00000000..c8326671 --- /dev/null +++ b/dcmdata/libsrc/dcvrpn.cc @@ -0,0 +1,476 @@ +/* + * + * Copyright (C) 1994-2013, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Gerd Ehlers, Andreas Barth, Joerg Riesmeier + * + * Purpose: Implementation of class DcmPersonName + * + */ + + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/dcmdata/dcvrpn.h" + + +// ******************************** + + +DcmPersonName::DcmPersonName(const DcmTag &tag, + const Uint32 len) + : DcmCharString(tag, len) +{ + setMaxLength(64); // not correct: max length of PN is 3*64+2 = 194 characters (not bytes!) + setNonSignificantChars(" \\^="); + setDelimiterChars("\\^="); +} + + +DcmPersonName::DcmPersonName(const DcmPersonName& old) + : DcmCharString(old) +{ +} + + +DcmPersonName::~DcmPersonName() +{ +} + + +DcmPersonName &DcmPersonName::operator=(const DcmPersonName &obj) +{ + DcmCharString::operator=(obj); + return *this; +} + + +OFCondition DcmPersonName::copyFrom(const DcmObject& rhs) +{ + if (this != &rhs) + { + if (rhs.ident() != ident()) return EC_IllegalCall; + *this = OFstatic_cast(const DcmPersonName &, rhs); + } + return EC_Normal; +} + + +// ******************************** + + +DcmEVR DcmPersonName::ident() const +{ + return EVR_PN; +} + + +OFCondition DcmPersonName::checkValue(const OFString &vm, + const OFBool /*oldFormat*/) +{ + OFString strVal; + /* get "raw value" without any modifications (if possible) */ + OFCondition l_error = getStringValue(strVal); + if (l_error.good()) + { + OFString charset; + /* try to determine the value of the SpecificCharacterSet element */ + getSpecificCharacterSet(charset); + l_error = DcmPersonName::checkStringValue(strVal, vm, charset); + } + return l_error; +} + + +// ******************************** + + +OFCondition DcmPersonName::getOFString(OFString &stringVal, + const unsigned long pos, + OFBool normalize) +{ + OFCondition l_error = DcmCharString::getOFString(stringVal, pos, normalize); + if (l_error.good() && normalize) + normalizeString(stringVal, !MULTIPART, !DELETE_LEADING, DELETE_TRAILING); + return l_error; +} + + +OFCondition DcmPersonName::writeXML(STD_NAMESPACE ostream &out, + const size_t flags) +{ + /* PN requires special handling in the Native DICOM Model format */ + if (flags & DCMTypes::XF_useNativeModel) + { + /* write normal XML start tag */ + DcmElement::writeXMLStartTag(out, flags); + /* if the value is empty, we do not need to insert any PersonName attribute at all */ + if (!isEmpty()) + { + /* condition variable, not meant to be used as a result of this method */ + OFCondition result; + /* iterate over multiple Person Names if necessary */ + const unsigned long vm = getVM(); + /* strings to hold family, first, and middle name as well as prefix and suffix component */ + OFString components[5]; + /* arrays in order to permit looping while creating the output */ + const char* compGroupNames[3] = { "Alphabetic", "Ideographic", "Phonetic" }; + const char* compNames[5] = { "FamilyName", "GivenName", "MiddleName", "NamePrefix", "NameSuffix" }; + for (unsigned int it = 0; it < vm; it++) + { + out << "" << OFendl; + OFString allGroups, oneCompGroup; + result = getOFString(allGroups, it); + if (result.good()) + { + /* process alphabetic, ideographic and phonetic encoding, as available */ + for (unsigned int cg = 0; cg < 3; cg++) + { + /* get one component group (more efficient to check for non-zero length on whole group later) */ + result = getComponentGroup(allGroups, cg, oneCompGroup); + if (result.good() && !oneCompGroup.empty()) + { + /* get all name components from current group, i.e. last, first, middle name, prefix, suffix. + * uses single group, so the component group parameter is always 0 + */ + result = getNameComponentsFromString(oneCompGroup, components[0], components[1], components[2], components[3], components[4], 0); + } + /* output one component group, e.g. Onken */ + if (result.good()) + { + out << "<" << compGroupNames[cg] << ">" << OFendl; // e.g. + /* go through components (last name, first name, ...) */ + for (unsigned short c = 0; c < 5; c++) + { + if (!components[c].empty()) + { + /* output name component, e.g. Onken */ + out << "<" << compNames[c] << ">" << components[c] << "" << OFendl; + } + } + out << "" << OFendl; // e.g. + } + } + } + out << "" << OFendl; + } + } + /* write normal XML end tag */ + DcmElement::writeXMLEndTag(out, flags); + /* always report success */ + return EC_Normal; + } else { + /* DCMTK-specific format does not require anything special */ + return DcmElement::writeXML(out, flags); + } +} + + + +// ******************************** + + +OFCondition DcmPersonName::getNameComponents(OFString &lastName, + OFString &firstName, + OFString &middleName, + OFString &namePrefix, + OFString &nameSuffix, + const unsigned long pos, + const unsigned int componentGroup) +{ + OFString dicomName; + OFCondition l_error = getOFString(dicomName, pos); + if (l_error.good()) + l_error = getNameComponentsFromString(dicomName, lastName, firstName, middleName, namePrefix, nameSuffix, componentGroup); + else + { + lastName.clear(); + firstName.clear(); + middleName.clear(); + namePrefix.clear(); + nameSuffix.clear(); + } + return l_error; +} + + +OFCondition DcmPersonName::getNameComponentsFromString(const OFString &dicomName, + OFString &lastName, + OFString &firstName, + OFString &middleName, + OFString &namePrefix, + OFString &nameSuffix, + const unsigned int componentGroup) +{ + OFCondition l_error = EC_Normal; + /* initialize all name components */ + lastName.clear(); + firstName.clear(); + middleName.clear(); + namePrefix.clear(); + nameSuffix.clear(); + if (!dicomName.empty()) + { + /* Excerpt from DICOM part 5: + "For the purpose of writing names in ideographic characters and in + phonetic characters, up to 3 groups of components may be used." + */ + OFString name; + l_error = getComponentGroup(dicomName, componentGroup, name); + /* check whether component group is valid (= non-empty) */ + if (l_error.good() && !name.empty()) + { + /* find caret separators */ + /* (tbd: add more sophisticated heuristics for comma and space separated names) */ + const size_t pos1 = name.find('^'); + if (pos1 != OFString_npos) + { + const size_t pos2 = name.find('^', pos1 + 1); + lastName = name.substr(0, pos1); + if (pos2 != OFString_npos) + { + const size_t pos3 = name.find('^', pos2 + 1); + firstName = name.substr(pos1 + 1, pos2 - pos1 - 1); + if (pos3 != OFString_npos) + { + const size_t pos4 = name.find('^', pos3 + 1); + middleName = name.substr(pos2 + 1, pos3 - pos2 - 1); + if (pos4 != OFString_npos) + { + namePrefix = name.substr(pos3 + 1, pos4 - pos3 - 1); + nameSuffix = name.substr(pos4 + 1); + } else + namePrefix = name.substr(pos3 + 1); + } else + middleName = name.substr(pos2 + 1); + } else + firstName = name.substr(pos1 + 1); + } else + lastName = name; + } + } + return l_error; +} + + +// ******************************** + + +OFCondition DcmPersonName::getFormattedName(OFString &formattedName, + const unsigned long pos, + const unsigned int componentGroup) +{ + OFString dicomName; + OFCondition l_error = getOFString(dicomName, pos); + if (l_error.good()) + l_error = getFormattedNameFromString(dicomName, formattedName, componentGroup); + else + formattedName.clear(); + return l_error; +} + + +OFCondition DcmPersonName::getComponentGroup(const OFString &allCmpGroups, + const unsigned int groupNo, + OFString &cmpGroup) +{ + OFCondition l_error = EC_IllegalParameter; + cmpGroup.clear(); + /* Excerpt from DICOM part 5: + "For the purpose of writing names in ideographic characters and in + phonetic characters, up to 3 groups of components may be used." + */ + if (groupNo < 3) + { + // find component group (0..2) + const size_t posA = allCmpGroups.find('='); + if (posA != OFString_npos) + { + if (groupNo > 0) + { + const size_t posB = allCmpGroups.find('=', posA + 1); + if (posB != OFString_npos) + { + if (groupNo == 1) + cmpGroup = allCmpGroups.substr(posA + 1, posB - posA - 1); + else /* groupNo == 2 */ + cmpGroup = allCmpGroups.substr(posB + 1); + l_error = EC_Normal; + } + else if (groupNo == 1) + { + cmpGroup = allCmpGroups.substr(posA + 1); + l_error = EC_Normal; + } + } else { + /* groupNo == 0 */ + cmpGroup = allCmpGroups.substr(0, posA); + l_error = EC_Normal; + } + } + else if (groupNo == 0) + { + cmpGroup = allCmpGroups; + l_error = EC_Normal; + } + } + return l_error; +} + + +OFCondition DcmPersonName::getFormattedNameFromString(const OFString &dicomName, + OFString &formattedName, + const unsigned int componentGroup) +{ + OFString lastName, firstName, middleName, namePrefix, nameSuffix; + OFCondition l_error = getNameComponentsFromString(dicomName, lastName, firstName, middleName, namePrefix, nameSuffix, componentGroup); + if (l_error.good()) + l_error = getFormattedNameFromComponents(lastName, firstName, middleName, namePrefix, nameSuffix, formattedName); + else + formattedName.clear(); + return l_error; +} + + +OFCondition DcmPersonName::getFormattedNameFromComponents(const OFString &lastName, + const OFString &firstName, + const OFString &middleName, + const OFString &namePrefix, + const OFString &nameSuffix, + OFString &formattedName) +{ + formattedName.clear(); + /* concatenate name components */ + if (!namePrefix.empty()) + formattedName += namePrefix; + if (!firstName.empty()) + { + if (!formattedName.empty()) + formattedName += ' '; + formattedName += firstName; + } + if (!middleName.empty()) + { + if (!formattedName.empty()) + formattedName += ' '; + formattedName += middleName; + } + if (!lastName.empty()) + { + if (!formattedName.empty()) + formattedName += ' '; + formattedName += lastName; + } + if (!nameSuffix.empty()) + { + if (!formattedName.empty()) + formattedName += ", "; + formattedName += nameSuffix; + } + return EC_Normal; +} + + +OFCondition DcmPersonName::getStringFromNameComponents(const OFString &lastName, + const OFString &firstName, + const OFString &middleName, + const OFString &namePrefix, + const OFString &nameSuffix, + OFString &dicomName) +{ + const size_t middleLen = middleName.length(); + const size_t prefixLen = namePrefix.length(); + const size_t suffixLen = nameSuffix.length(); + /* concatenate name components */ + dicomName = lastName; + if (firstName.length() + middleLen + prefixLen + suffixLen > 0) + dicomName += '^'; + dicomName += firstName; + if (middleLen + prefixLen + suffixLen > 0) + dicomName += '^'; + dicomName += middleName; + if (prefixLen + suffixLen > 0) + dicomName += '^'; + dicomName += namePrefix; + if (suffixLen > 0) + dicomName += '^'; + dicomName += nameSuffix; + return EC_Normal; +} + + +// ******************************** + + +OFCondition DcmPersonName::putNameComponents(const OFString &lastName, + const OFString &firstName, + const OFString &middleName, + const OFString &namePrefix, + const OFString &nameSuffix) +{ + OFString dicomName; + /* concatenate name components */ + OFCondition l_error = getStringFromNameComponents(lastName, firstName, middleName, namePrefix, nameSuffix, dicomName); + /* put element value */ + if (l_error.good()) + l_error = putOFStringArray(dicomName); + return l_error; +} + + +// ******************************** + + +OFCondition DcmPersonName::checkStringValue(const OFString &value, + const OFString &vm, + const OFString &charset) +{ + /* currently not checked: maximum length per component group (64 characters) */ + OFCondition result = EC_Normal; + const size_t valLen = value.length(); + if (valLen > 0) + { + size_t posStart = 0; + unsigned long vmNum = 0; + /* iterate over all value components */ + while (posStart != OFString_npos) + { + ++vmNum; + /* search for next component separator */ + const size_t posEnd = value.find('\\', posStart); + const size_t length = (posEnd == OFString_npos) ? valLen - posStart : posEnd - posStart; + if (dcmEnableVRCheckerForStringValues.get()) + { + /* currently, the VR checker only supports ASCII and Latin-1 */ + if (charset.empty() || (charset == "ISO_IR 6") || (charset == "ISO_IR 100")) + { + /* check value representation */ + const int vrID = DcmElement::scanValue(value, "pn", posStart, length); + if (vrID != 11) + { + result = EC_ValueRepresentationViolated; + break; + } + } + } + posStart = (posEnd == OFString_npos) ? posEnd : posEnd + 1; + } + if (result.good() && !vm.empty()) + { + /* check value multiplicity */ + result = DcmElement::checkVM(vmNum, vm); + } + } + return result; +} diff --git a/dcmdata/libsrc/dcvrpobw.cc b/dcmdata/libsrc/dcvrpobw.cc new file mode 100644 index 00000000..42c2ba63 --- /dev/null +++ b/dcmdata/libsrc/dcvrpobw.cc @@ -0,0 +1,311 @@ +/* + * + * Copyright (C) 1997-2010, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Andreas Barth + * + * Purpose: + * class DcmPolymorphOBOW for Tags that can change their VR + * between OB and OW (e.g. Tag PixelData, OverlayData). This class shall + * not be used directly in applications. No identification exists. + * + */ + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ +#include "dcmtk/dcmdata/dcvrpobw.h" + + +DcmPolymorphOBOW::DcmPolymorphOBOW( + const DcmTag & tag, + const Uint32 len) + : DcmOtherByteOtherWord(tag, len), + changeVR(OFFalse), + currentVR(EVR_OW) +{ + if (getTag().getEVR() == EVR_ox || getTag().getEVR() == EVR_lt) setTagVR(EVR_OW); +} + +DcmPolymorphOBOW::DcmPolymorphOBOW(const DcmPolymorphOBOW & oldObj) +: DcmOtherByteOtherWord(oldObj) +, changeVR(oldObj.changeVR) +, currentVR(oldObj.currentVR) +{ +} + +DcmPolymorphOBOW::~DcmPolymorphOBOW() +{ +} + +DcmPolymorphOBOW &DcmPolymorphOBOW::operator=(const DcmPolymorphOBOW & obj) +{ + if (this != &obj) + { + DcmOtherByteOtherWord::operator=(obj); + changeVR = obj.changeVR; + currentVR = obj.currentVR; + } + return *this; +} + +OFCondition DcmPolymorphOBOW::copyFrom(const DcmObject& rhs) +{ + if (this != &rhs) + { + if (rhs.ident() != ident()) return EC_IllegalCall; + *this = OFstatic_cast(const DcmPolymorphOBOW &, rhs); + } + return EC_Normal; +} + +OFCondition +DcmPolymorphOBOW::getUint8Array( + Uint8 * & bytes) +{ + errorFlag = EC_Normal; + OFBool bchangeVR = OFFalse; + if (currentVR == EVR_OW) + { + if (getByteOrder() == EBO_BigEndian) + { + swapValueField(sizeof(Uint16)); + setByteOrder(EBO_LittleEndian); + } + if (getTag().getEVR() == EVR_OW) + { + bchangeVR = OFTrue; + setTagVR(EVR_OB); + currentVR = EVR_OB; + } + } + bytes = OFstatic_cast(Uint8 *, this -> getValue()); + if (bchangeVR) + setTagVR(EVR_OW); + + return errorFlag; +} + + +OFCondition +DcmPolymorphOBOW::getUint16Array( + Uint16 * & words) +{ + errorFlag = EC_Normal; + OFBool bchangeVR = OFFalse; + if (currentVR == EVR_OB) + { + setByteOrder(EBO_LittleEndian); + currentVR = EVR_OW; + if (getTag().getEVR() == EVR_OB) + { + setTagVR(EVR_OW); + bchangeVR = OFTrue; + } + } + words = OFstatic_cast(Uint16 *, this -> getValue()); + if (bchangeVR) + setTagVR(EVR_OB); + + return errorFlag; +} + +OFCondition +DcmPolymorphOBOW::createUint8Array( + const Uint32 numBytes, + Uint8 * & bytes) +{ + currentVR = EVR_OB; + setTagVR(EVR_OB); + errorFlag = createEmptyValue(OFstatic_cast(Uint32, sizeof(Uint8) * OFstatic_cast(size_t, numBytes))); + setByteOrder(gLocalByteOrder); + if (EC_Normal == errorFlag) + bytes = OFstatic_cast(Uint8 *, this->getValue()); + else + bytes = NULL; + return errorFlag; +} + + +OFCondition +DcmPolymorphOBOW::createUint16Array( + const Uint32 numWords, + Uint16 * & words) +{ + currentVR = EVR_OW; + setTagVR(EVR_OW); + errorFlag = createEmptyValue(OFstatic_cast(Uint32, sizeof(Uint16) * OFstatic_cast(size_t, numWords))); + setByteOrder(gLocalByteOrder); + if (EC_Normal == errorFlag) + words = OFstatic_cast(Uint16 *, this->getValue()); + else + words = NULL; + return errorFlag; +} + + +OFCondition +DcmPolymorphOBOW::putUint8Array( + const Uint8 * byteValue, + const unsigned long numBytes) +{ + errorFlag = EC_Normal; + currentVR = getTag().getEVR(); + if (numBytes) + { + if (byteValue) + { + errorFlag = putValue(byteValue, OFstatic_cast(Uint32, sizeof(Uint8) * OFstatic_cast(size_t, numBytes))); + if (errorFlag == EC_Normal) + { + if (getTag().getEVR() == EVR_OW && getByteOrder() == EBO_BigEndian) + setByteOrder(EBO_LittleEndian); + this -> alignValue(); + } + } + else + errorFlag = EC_CorruptedData; + + } + else + this -> putValue(NULL, 0); + + return errorFlag; +} + + +OFCondition +DcmPolymorphOBOW::putUint16Array( + const Uint16 * wordValue, + const unsigned long numWords) +{ + errorFlag = EC_Normal; + currentVR = getTag().getEVR(); + if (numWords) + { + if (wordValue) + { + errorFlag = putValue(wordValue, OFstatic_cast(Uint32, sizeof(Uint16) * OFstatic_cast(size_t, numWords))); + if (errorFlag == EC_Normal && + getTag().getEVR() == EVR_OB && getByteOrder() == EBO_BigEndian) + { + swapValueField(sizeof(Uint16)); + setByteOrder(EBO_LittleEndian); + } + } + else + errorFlag = EC_CorruptedData; + } + else + errorFlag = this -> putValue(NULL, 0); + + return errorFlag; +} + + +OFCondition +DcmPolymorphOBOW::read( + DcmInputStream & inStream, + const E_TransferSyntax ixfer, + const E_GrpLenEncoding glenc, + const Uint32 maxReadLength) +{ + OFCondition l_error = + DcmOtherByteOtherWord::read(inStream, ixfer, glenc, maxReadLength); + + if (getTransferState() == ERW_ready) + currentVR = getTag().getEVR(); + + return l_error; +} + +void +DcmPolymorphOBOW::transferEnd() +{ + changeVR = OFFalse; + DcmOtherByteOtherWord::transferEnd(); +} + +void +DcmPolymorphOBOW::transferInit() +{ + changeVR = OFFalse; + DcmOtherByteOtherWord::transferInit(); +} + +OFCondition DcmPolymorphOBOW::write( + DcmOutputStream &outStream, + const E_TransferSyntax oxfer, + const E_EncodingType enctype, + DcmWriteCache *wcache) +{ + DcmXfer oXferSyn(oxfer); + if (getTransferState() == ERW_init) + { + if (getTag().getEVR() == EVR_OB && oXferSyn.isImplicitVR() && getByteOrder() == EBO_BigEndian) + { + // VR is OB and it will be written as OW in LittleEndianImplicit. + setTagVR(EVR_OW); + if (currentVR == EVR_OB) setByteOrder(EBO_LittleEndian); + currentVR = EVR_OB; + changeVR = OFTrue; + } + else if (getTag().getEVR() == EVR_OW && currentVR == EVR_OB) + { + setByteOrder(EBO_LittleEndian); + currentVR = EVR_OW; + } + } + errorFlag = DcmOtherByteOtherWord::write(outStream, oxfer, enctype, wcache); + if (getTransferState() == ERW_ready && changeVR) + { + // VR must be OB again. No Swapping is needed since the written + // transfer syntax was LittleEndianImplicit and so no swapping + // took place. + setTagVR(EVR_OB); + } + return errorFlag; +} + +OFCondition DcmPolymorphOBOW::writeSignatureFormat( + DcmOutputStream &outStream, + const E_TransferSyntax oxfer, + const E_EncodingType enctype, + DcmWriteCache *wcache) +{ + DcmXfer oXferSyn(oxfer); + if (getTransferState() == ERW_init) + { + if (getTag().getEVR() == EVR_OB && oXferSyn.isImplicitVR() && getByteOrder() == EBO_BigEndian) + { + // VR is OB and it will be written as OW in LittleEndianImplicit. + setTagVR(EVR_OW); + if (currentVR == EVR_OB) setByteOrder(EBO_LittleEndian); + currentVR = EVR_OB; + changeVR = OFTrue; + } + else if (getTag().getEVR() == EVR_OW && currentVR == EVR_OB) + { + setByteOrder(EBO_LittleEndian); + currentVR = EVR_OW; + } + } + errorFlag = DcmOtherByteOtherWord::writeSignatureFormat(outStream, oxfer, enctype, wcache); + if (getTransferState() == ERW_ready && changeVR) + { + // VR must be OB again. No Swapping is needed since the written + // transfer syntax was LittleEndianImplicit and so no swapping + // took place. + setTagVR(EVR_OB); + } + return errorFlag; +} diff --git a/dcmdata/libsrc/dcvrsh.cc b/dcmdata/libsrc/dcvrsh.cc new file mode 100644 index 00000000..b01ab037 --- /dev/null +++ b/dcmdata/libsrc/dcvrsh.cc @@ -0,0 +1,118 @@ +/* + * + * Copyright (C) 1994-2013, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Gerd Ehlers + * + * Purpose: Implementation of class DcmShortString + * + */ + + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/dcmdata/dcvrsh.h" + + +// ******************************** + + +DcmShortString::DcmShortString(const DcmTag &tag, + const Uint32 len) + : DcmCharString(tag, len) +{ + setMaxLength(16); + setNonSignificantChars(" \\"); + setDelimiterChars("\\"); +} + + +DcmShortString::DcmShortString(const DcmShortString &old) + : DcmCharString(old) +{ +} + + +DcmShortString::~DcmShortString() +{ +} + + +DcmShortString &DcmShortString::operator=(const DcmShortString &obj) +{ + DcmCharString::operator=(obj); + return *this; +} + + +OFCondition DcmShortString::copyFrom(const DcmObject& rhs) +{ + if (this != &rhs) + { + if (rhs.ident() != ident()) return EC_IllegalCall; + *this = OFstatic_cast(const DcmShortString &, rhs); + } + return EC_Normal; +} + + +// ******************************** + + +DcmEVR DcmShortString::ident() const +{ + return EVR_SH; +} + + +OFCondition DcmShortString::checkValue(const OFString &vm, + const OFBool /*oldFormat*/) +{ + OFString strVal; + /* get "raw value" without any modifications (if possible) */ + OFCondition l_error = getStringValue(strVal); + if (l_error.good()) + { + OFString charset; + /* try to determine the value of the SpecificCharacterSet element */ + getSpecificCharacterSet(charset); + l_error = DcmShortString::checkStringValue(strVal, vm, charset); + } + return l_error; +} + + +// ******************************** + + +OFCondition DcmShortString::getOFString(OFString &stringVal, + const unsigned long pos, + OFBool normalize) +{ + OFCondition l_error = DcmCharString::getOFString(stringVal, pos, normalize); + if (l_error.good() && normalize) + normalizeString(stringVal, !MULTIPART, DELETE_LEADING, DELETE_TRAILING); + return l_error; +} + + +// ******************************** + + +OFCondition DcmShortString::checkStringValue(const OFString &value, + const OFString &vm, + const OFString &charset) +{ + return DcmByteString::checkStringValue(value, vm, "lo", 12, 0 /* maxLen: no check */, charset); +} diff --git a/dcmdata/libsrc/dcvrsl.cc b/dcmdata/libsrc/dcvrsl.cc new file mode 100644 index 00000000..84001698 --- /dev/null +++ b/dcmdata/libsrc/dcvrsl.cc @@ -0,0 +1,366 @@ +/* + * + * Copyright (C) 1994-2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Gerd Ehlers, Andreas Barth + * + * Purpose: Implementation of class DcmSignedLong + * + */ + + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ +#include "dcmtk/ofstd/ofstream.h" +#include "dcmtk/dcmdata/dcvrsl.h" + +#define INCLUDE_CSTDIO +#define INCLUDE_CSTRING +#include "dcmtk/ofstd/ofstdinc.h" + + +// ******************************** + + +DcmSignedLong::DcmSignedLong(const DcmTag &tag, + const Uint32 len) + : DcmElement(tag, len) +{ +} + + +DcmSignedLong::DcmSignedLong(const DcmSignedLong &old) + : DcmElement(old) +{ +} + + +DcmSignedLong::~DcmSignedLong() +{ +} + + +DcmSignedLong &DcmSignedLong::operator=(const DcmSignedLong &obj) +{ + DcmElement::operator=(obj); + return *this; +} + + +int DcmSignedLong::compare(const DcmElement& rhs) const +{ + int result = DcmElement::compare(rhs); + if (result != 0) + { + return result; + } + + /* cast away constness (dcmdata is not const correct...) */ + DcmSignedLong* myThis = NULL; + DcmSignedLong* myRhs = NULL; + myThis = OFconst_cast(DcmSignedLong*, this); + myRhs = OFstatic_cast(DcmSignedLong*, OFconst_cast(DcmElement*, &rhs)); + + /* iterate over all components and test equality */ + unsigned long thisVM = myThis->getVM(); + for (unsigned long count = 0; count < thisVM; count++) + { + Sint32 val = 0; + if (myThis->getSint32(val, count).good()) + { + Sint32 rhsVal = 0; + if (myRhs->getSint32(rhsVal, count).good()) + { + if (val > rhsVal) + { + return 1; + } + else if (val < rhsVal) + { + return -1; + } + /* otherwise they are equal, continue comparison */ + } + else + { + break; // values equal until this point (rhs shorter) + } + } + } + + /* we get here if all values are equal. Now look at the number of components. */ + unsigned long rhsVM = myRhs->getVM(); + if (thisVM < rhsVM) + { + return -1; + } + else if (thisVM > rhsVM) + { + return 1; + } + + /* all values as well as VM equal: objects are equal */ + return 0; +} + + +OFCondition DcmSignedLong::copyFrom(const DcmObject& rhs) +{ + if (this != &rhs) + { + if (rhs.ident() != ident()) return EC_IllegalCall; + *this = OFstatic_cast(const DcmSignedLong &, rhs); + } + return EC_Normal; +} + + +// ******************************** + + +DcmEVR DcmSignedLong::ident() const +{ + return EVR_SL; +} + + +OFCondition DcmSignedLong::checkValue(const OFString &vm, + const OFBool /*oldFormat*/) +{ + /* check VM only */ + return DcmElement::checkVM(getVM(), vm); +} + + +unsigned long DcmSignedLong::getVM() +{ + return getLengthField() / OFstatic_cast(unsigned long, sizeof(Sint32)); +} + + +// ******************************** + + +void DcmSignedLong::print(STD_NAMESPACE ostream&out, + const size_t flags, + const int level, + const char * /*pixelFileName*/, + size_t * /*pixelCounter*/) +{ + if (valueLoaded()) + { + /* get signed integer data */ + Sint32 *sintVals; + errorFlag = getSint32Array(sintVals); + if (sintVals != NULL) + { + const unsigned long count = getVM(); + const unsigned long maxLength = (flags & DCMTypes::PF_shortenLongTagValues) ? + DCM_OptPrintLineLength : OFstatic_cast(unsigned long, -1) /*unlimited*/; + unsigned long printedLength = 0; + unsigned long newLength = 0; + char buffer[32]; + /* print line start with tag and VR */ + printInfoLineStart(out, flags, level); + /* print multiple values */ + for (unsigned int i = 0; i < count; i++, sintVals++) + { + /* check whether first value is printed (omit delimiter) */ +#if SIZEOF_LONG == 8 + if (i == 0) + sprintf(buffer, "%d", *sintVals); + else + sprintf(buffer, "\\%d", *sintVals); +#else + if (i == 0) + sprintf(buffer, "%ld", *sintVals); + else + sprintf(buffer, "\\%ld", *sintVals); +#endif + /* check whether current value sticks to the length limit */ + newLength = printedLength + OFstatic_cast(unsigned long, strlen(buffer)); + if ((newLength <= maxLength) && ((i + 1 == count) || (newLength + 3 <= maxLength))) + { + out << buffer; + printedLength = newLength; + } else { + /* check whether output has been truncated */ + if (i + 1 < count) + { + out << "..."; + printedLength += 3; + } + break; + } + } + /* print line end with length, VM and tag name */ + printInfoLineEnd(out, flags, printedLength); + } else + printInfoLine(out, flags, level, "(no value available)"); + } else + printInfoLine(out, flags, level, "(not loaded)"); +} + + +// ******************************** + + +OFCondition DcmSignedLong::getSint32(Sint32 &sintVal, + const unsigned long pos) +{ + /* get signed integer data */ + Sint32 *sintValues = NULL; + errorFlag = getSint32Array(sintValues); + /* check data before returning */ + if (errorFlag.good()) + { + if (sintValues == NULL) + errorFlag = EC_IllegalCall; + else if (pos >= getVM()) + errorFlag = EC_IllegalParameter; + else + sintVal = sintValues[pos]; + } + /* clear value in case of error */ + if (errorFlag.bad()) + sintVal = 0; + return errorFlag; +} + + +OFCondition DcmSignedLong::getSint32Array(Sint32 *&sintVals) +{ + sintVals = OFstatic_cast(Sint32 *, getValue()); + return errorFlag; +} + + +// ******************************** + + +OFCondition DcmSignedLong::getOFString(OFString &stringVal, + const unsigned long pos, + OFBool /*normalize*/) +{ + Sint32 sintVal; + /* get the specified numeric value */ + errorFlag = getSint32(sintVal, pos); + if (errorFlag.good()) + { + /* ... and convert it to a character string */ + char buffer[32]; + sprintf(buffer, "%li", OFstatic_cast(long, sintVal)); + /* assign result */ + stringVal = buffer; + } + return errorFlag; +} + + +// ******************************** + + +OFCondition DcmSignedLong::putSint32(const Sint32 sintVal, + const unsigned long pos) +{ + Sint32 val = sintVal; + errorFlag = changeValue(&val, OFstatic_cast(Uint32, sizeof(Sint32) * pos), OFstatic_cast(Uint32, sizeof(Sint32))); + return errorFlag; +} + + +OFCondition DcmSignedLong::putSint32Array(const Sint32 *sintVals, + const unsigned long numSints) +{ + errorFlag = EC_Normal; + if (numSints > 0) + { + /* check for valid data */ + if (sintVals != NULL) + errorFlag = putValue(sintVals, OFstatic_cast(Uint32, sizeof(Sint32) * OFstatic_cast(size_t, numSints))); + else + errorFlag = EC_CorruptedData; + } else + errorFlag = putValue(NULL, 0); + return errorFlag; +} + + +// ******************************** + + +OFCondition DcmSignedLong::putString(const char *stringVal) +{ + /* determine length of the string value */ + const size_t stringLen = (stringVal != NULL) ? strlen(stringVal) : 0; + /* call the real function */ + return putString(stringVal, OFstatic_cast(Uint32, stringLen)); +} + + +OFCondition DcmSignedLong::putString(const char *stringVal, + const Uint32 stringLen) +{ + errorFlag = EC_Normal; + /* determine VM of the string */ + const unsigned long vm = DcmElement::determineVM(stringVal, stringLen); + if (vm > 0) + { + Sint32 *field = new Sint32[vm]; + OFString value; + size_t pos = 0; + /* retrieve signed integer data from character string */ + for (unsigned long i = 0; (i < vm) && errorFlag.good(); i++) + { + /* get specified value from multi-valued string */ + pos = DcmElement::getValueFromString(stringVal, pos, stringLen, value); + if (value.empty() || +#if SIZEOF_LONG == 8 + (sscanf(value.c_str(), "%d", &field[i]) != 1) +#else + (sscanf(value.c_str(), "%ld", &field[i]) != 1) +#endif + ) + { + errorFlag = EC_CorruptedData; + } + } + /* set binary data as the element value */ + if (errorFlag.good()) + errorFlag = putSint32Array(field, vm); + /* delete temporary buffer */ + delete[] field; + } else + errorFlag = putValue(NULL, 0); + return errorFlag; +} + + +// ******************************** + + +OFCondition DcmSignedLong::verify(const OFBool autocorrect) +{ + /* check for valid value length */ + if (getLengthField() % (sizeof(Sint32)) != 0) + { + errorFlag = EC_CorruptedData; + if (autocorrect) + { + /* strip to valid length */ + setLengthField(getLengthField() - (getLengthField() % OFstatic_cast(Uint32, sizeof(Sint32)))); + } + } else + errorFlag = EC_Normal; + return errorFlag; +} diff --git a/dcmdata/libsrc/dcvrss.cc b/dcmdata/libsrc/dcvrss.cc new file mode 100644 index 00000000..a80969eb --- /dev/null +++ b/dcmdata/libsrc/dcvrss.cc @@ -0,0 +1,351 @@ +/* + * + * Copyright (C) 1994-2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Gerd Ehlers, Andreas Barth + * + * Purpose: Implementation of class DcmSignedShort + * + */ + + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ +#include "dcmtk/ofstd/ofstream.h" +#include "dcmtk/dcmdata/dcvrss.h" + +#define INCLUDE_CSTDIO +#define INCLUDE_CSTRING +#include "dcmtk/ofstd/ofstdinc.h" + + +// ******************************** + + +DcmSignedShort::DcmSignedShort(const DcmTag &tag, + const Uint32 len) + : DcmElement(tag, len) +{ +} + + +DcmSignedShort::DcmSignedShort(const DcmSignedShort &old) + : DcmElement(old) +{ +} + + +DcmSignedShort::~DcmSignedShort() +{ +} + + +DcmSignedShort &DcmSignedShort::operator=(const DcmSignedShort &obj) +{ + DcmElement::operator=(obj); + return *this; +} + + +int DcmSignedShort::compare(const DcmElement& rhs) const +{ + int result = DcmElement::compare(rhs); + if (result != 0) + { + return result; + } + + /* cast away constness (dcmdata is not const correct...) */ + DcmSignedShort* myThis = NULL; + DcmSignedShort* myRhs = NULL; + myThis = OFconst_cast(DcmSignedShort*, this); + myRhs = OFstatic_cast(DcmSignedShort*, OFconst_cast(DcmElement*, &rhs)); + + /* iterate over all components and test equality */ + unsigned long thisVM = myThis->getVM(); + for (unsigned long count = 0; count < thisVM; count++) + { + Sint16 val = 0; + if (myThis->getSint16(val, count).good()) + { + Sint16 rhsVal = 0; + if (myRhs->getSint16(rhsVal, count).good()) + { + if (val > rhsVal) + { + return 1; + } + else if (val < rhsVal) + { + return -1; + } + /* otherwise they are equal, continue comparison */ + } + else + { + break; // values equal until this point (rhs shorter) + } + } + } + + /* we get here if all values are equal. Now look at the number of components. */ + unsigned long rhsVM = myRhs->getVM(); + if (thisVM < rhsVM) + { + return -1; + } + else if (thisVM > rhsVM) + { + return 1; + } + + /* all values as well as VM equal: objects are equal */ + return 0; +} + + +OFCondition DcmSignedShort::copyFrom(const DcmObject& rhs) +{ + if (this != &rhs) + { + if (rhs.ident() != ident()) return EC_IllegalCall; + *this = OFstatic_cast(const DcmSignedShort &, rhs); + } + return EC_Normal; +} + + +// ******************************** + + +DcmEVR DcmSignedShort::ident() const +{ + return EVR_SS; +} + + +OFCondition DcmSignedShort::checkValue(const OFString &vm, + const OFBool /*oldFormat*/) +{ + /* check VM only */ + return DcmElement::checkVM(getVM(), vm); +} + + +unsigned long DcmSignedShort::getVM() +{ + return getLengthField() / OFstatic_cast(unsigned long, sizeof(Sint16)); +} + + +// ******************************** + + +void DcmSignedShort::print(STD_NAMESPACE ostream&out, + const size_t flags, + const int level, + const char * /*pixelFileName*/, + size_t * /*pixelCounter*/) +{ + if (valueLoaded()) + { + /* get signed integer data */ + Sint16 *sintVals; + errorFlag = getSint16Array(sintVals); + if (sintVals != NULL) + { + const unsigned long count = getVM(); + const unsigned long maxLength = (flags & DCMTypes::PF_shortenLongTagValues) ? + DCM_OptPrintLineLength : OFstatic_cast(unsigned long, -1) /*unlimited*/; + unsigned long printedLength = 0; + unsigned long newLength = 0; + char buffer[32]; + /* print line start with tag and VR */ + printInfoLineStart(out, flags, level); + /* print multiple values */ + for (unsigned int i = 0; i < count; i++, sintVals++) + { + /* check whether first value is printed (omit delimiter) */ + if (i == 0) + sprintf(buffer, "%hd", *sintVals); + else + sprintf(buffer, "\\%hd", *sintVals); + /* check whether current value sticks to the length limit */ + newLength = printedLength + OFstatic_cast(unsigned long, strlen(buffer)); + if ((newLength <= maxLength) && ((i + 1 == count) || (newLength + 3 <= maxLength))) + { + out << buffer; + printedLength = newLength; + } else { + /* check whether output has been truncated */ + if (i + 1 < count) + { + out << "..."; + printedLength += 3; + } + break; + } + } + /* print line end with length, VM and tag name */ + printInfoLineEnd(out, flags, printedLength); + } else + printInfoLine(out, flags, level, "(no value available)"); + } else + printInfoLine(out, flags, level, "(not loaded)"); +} + + +// ******************************** + + +OFCondition DcmSignedShort::getSint16(Sint16 &sintVal, + const unsigned long pos) +{ + /* get signed integer data */ + Sint16 *sintValues = NULL; + errorFlag = getSint16Array(sintValues); + /* check data before returning */ + if (errorFlag.good()) + { + if (sintValues == NULL) + errorFlag = EC_IllegalCall; + else if (pos >= getVM()) + errorFlag = EC_IllegalParameter; + else + sintVal = sintValues[pos]; + } + /* clear value in case of error */ + if (errorFlag.bad()) + sintVal = 0; + return errorFlag; +} + + +OFCondition DcmSignedShort::getSint16Array(Sint16 *&sintVals) +{ + sintVals = OFstatic_cast(Sint16 *, getValue()); + return errorFlag; +} + + +// ******************************** + + +OFCondition DcmSignedShort::getOFString(OFString &stringVal, + const unsigned long pos, + OFBool /*normalize*/) +{ + Sint16 sintVal; + /* get the specified numeric value */ + errorFlag = getSint16(sintVal, pos); + if (errorFlag.good()) + { + /* ... and convert it to a character string */ + char buffer[32]; + sprintf(buffer, "%i", sintVal); + /* assign result */ + stringVal = buffer; + } + return errorFlag; +} + + +// ******************************** + + +OFCondition DcmSignedShort::putSint16(const Sint16 sintVal, + const unsigned long pos) +{ + Sint16 val = sintVal; + errorFlag = changeValue(&val, OFstatic_cast(Uint32, sizeof(Sint16) * pos), OFstatic_cast(Uint32, sizeof(Sint16))); + return errorFlag; +} + + +OFCondition DcmSignedShort::putSint16Array(const Sint16 *sintVals, + const unsigned long numSints) +{ + errorFlag = EC_Normal; + if (numSints > 0) + { + /* check for valid data */ + if (sintVals != NULL) + errorFlag = putValue(sintVals, OFstatic_cast(Uint32, sizeof(Sint16) * OFstatic_cast(size_t, numSints))); + else + errorFlag = EC_CorruptedData; + } else + errorFlag = putValue(NULL, 0); + return errorFlag; +} + + +// ******************************** + + +OFCondition DcmSignedShort::putString(const char *stringVal) +{ + /* determine length of the string value */ + const size_t stringLen = (stringVal != NULL) ? strlen(stringVal) : 0; + /* call the real function */ + return putString(stringVal, OFstatic_cast(Uint32, stringLen)); +} + + +OFCondition DcmSignedShort::putString(const char *stringVal, + const Uint32 stringLen) +{ + errorFlag = EC_Normal; + /* determine VM of the string */ + const unsigned long vm = DcmElement::determineVM(stringVal, stringLen); + if (vm > 0) + { + Sint16 *field = new Sint16[vm]; + OFString value; + size_t pos = 0; + /* retrieve signed integer data from character string */ + for (unsigned long i = 0; (i < vm) && errorFlag.good(); i++) + { + /* get specified value from multi-valued string */ + pos = DcmElement::getValueFromString(stringVal, pos, stringLen, value); + if (value.empty() || (sscanf(value.c_str(), "%hd", &field[i]) != 1)) + errorFlag = EC_CorruptedData; + } + /* set binary data as the element value */ + if (errorFlag.good()) + errorFlag = putSint16Array(field, vm); + /* delete temporary buffer */ + delete[] field; + } else + errorFlag = putValue(NULL, 0); + return errorFlag; +} + + +// ******************************** + + +OFCondition DcmSignedShort::verify(const OFBool autocorrect) +{ + /* check for valid value length */ + if (getLengthField() % (sizeof(Sint16)) != 0) + { + errorFlag = EC_CorruptedData; + if (autocorrect) + { + /* strip to valid length */ + setLengthField(getLengthField() - (getLengthField() % OFstatic_cast(Uint32, sizeof(Sint16)))); + } + } else + errorFlag = EC_Normal; + return errorFlag; +} diff --git a/dcmdata/libsrc/dcvrst.cc b/dcmdata/libsrc/dcvrst.cc new file mode 100644 index 00000000..12d5c82f --- /dev/null +++ b/dcmdata/libsrc/dcvrst.cc @@ -0,0 +1,131 @@ +/* + * + * Copyright (C) 1994-2013, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Gerd Ehlers + * + * Purpose: Implementation of class DcmShortText + * + */ + + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/dcmdata/dcvrst.h" + + +// ******************************** + + +DcmShortText::DcmShortText(const DcmTag &tag, + const Uint32 len) + : DcmCharString(tag, len) +{ + setMaxLength(1024); +} + + +DcmShortText::DcmShortText(const DcmShortText &old) + : DcmCharString(old) +{ +} + + +DcmShortText::~DcmShortText() +{ +} + + +DcmShortText &DcmShortText::operator=(const DcmShortText &obj) +{ + DcmCharString::operator=(obj); + return *this; +} + + +OFCondition DcmShortText::copyFrom(const DcmObject& rhs) +{ + if (this != &rhs) + { + if (rhs.ident() != ident()) return EC_IllegalCall; + *this = OFstatic_cast(const DcmShortText &, rhs); + } + return EC_Normal; +} + + +// ******************************** + + +DcmEVR DcmShortText::ident() const +{ + return EVR_ST; +} + + +OFCondition DcmShortText::checkValue(const OFString & /*vm*/, + const OFBool /*oldFormat*/) +{ + OFString strVal; + /* get "raw value" without any modifications (if possible) */ + OFCondition l_error = getStringValue(strVal); + if (l_error.good()) + { + OFString charset; + /* try to determine the value of the SpecificCharacterSet element */ + getSpecificCharacterSet(charset); + l_error = DcmShortText::checkStringValue(strVal, charset); + } + return l_error; +} + + +unsigned long DcmShortText::getVM() +{ + /* value multiplicity is 1 for non-empty string, 0 otherwise */ + return (getRealLength() > 0) ? 1 : 0; +} + + +// ******************************** + + +OFCondition DcmShortText::getOFString(OFString &stringVal, + const unsigned long /*pos*/, + OFBool normalize) +{ + /* treat backslash as a normal character */ + return getOFStringArray(stringVal, normalize); +} + + +OFCondition DcmShortText::getOFStringArray(OFString &stringVal, + OFBool normalize) +{ + /* get string value without handling the "\" as a delimiter */ + OFCondition l_error = getStringValue(stringVal); + if (l_error.good() && normalize) + normalizeString(stringVal, !MULTIPART, !DELETE_LEADING, DELETE_TRAILING); + return l_error; +} + + +// ******************************** + + +OFCondition DcmShortText::checkStringValue(const OFString &value, + const OFString &charset) +{ + return DcmByteString::checkStringValue(value, "" /* vm */, "lt", 14, 0 /* maxLen: no check */, charset); +} diff --git a/dcmdata/libsrc/dcvrtm.cc b/dcmdata/libsrc/dcvrtm.cc new file mode 100644 index 00000000..3aa4117d --- /dev/null +++ b/dcmdata/libsrc/dcvrtm.cc @@ -0,0 +1,417 @@ +/* + * + * Copyright (C) 1994-2013, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Gerd Ehlers, Joerg Riesmeier + * + * Purpose: Implementation of class DcmTime + * + */ + + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/dcmdata/dcvrtm.h" +#include "dcmtk/ofstd/ofstd.h" + +#define INCLUDE_CSTDIO +#include "dcmtk/ofstd/ofstdinc.h" + + +#define MAX_TM_LENGTH 16 + + +// ******************************** + + +DcmTime::DcmTime(const DcmTag &tag, + const Uint32 len) + : DcmByteString(tag, len) +{ + setMaxLength(MAX_TM_LENGTH); + setNonSignificantChars("\\"); +} + + +DcmTime::DcmTime(const DcmTime &old) + : DcmByteString(old) +{ +} + + +DcmTime::~DcmTime() +{ +} + + +DcmTime &DcmTime::operator=(const DcmTime &obj) +{ + DcmByteString::operator=(obj); + return *this; +} + + +OFCondition DcmTime::copyFrom(const DcmObject& rhs) +{ + if (this != &rhs) + { + if (rhs.ident() != ident()) return EC_IllegalCall; + *this = OFstatic_cast(const DcmTime &, rhs); + } + return EC_Normal; +} + + +// ******************************** + + +DcmEVR DcmTime::ident() const +{ + return EVR_TM; +} + + +OFCondition DcmTime::checkValue(const OFString &vm, + const OFBool oldFormat) +{ + OFString strVal; + /* get "raw value" without any modifications (if possible) */ + OFCondition l_error = getStringValue(strVal); + if (l_error.good()) + l_error = DcmTime::checkStringValue(strVal, vm, oldFormat); + return l_error; +} + + +// ******************************** + + +OFCondition DcmTime::getOFString(OFString &stringVal, + const unsigned long pos, + OFBool normalize) +{ + OFCondition l_error = DcmByteString::getOFString(stringVal, pos, normalize); + if (l_error.good() && normalize) + normalizeString(stringVal, !MULTIPART, !DELETE_LEADING, DELETE_TRAILING); + return l_error; +} + + +// ******************************** + + +OFCondition DcmTime::getOFTime(OFTime &timeValue, + const unsigned long pos, + const OFBool supportOldFormat) +{ + OFString dicomTime; + /* convert the current element value to OFTime format */ + OFCondition l_error = getOFString(dicomTime, pos); + if (l_error.good()) + l_error = getOFTimeFromString(dicomTime, timeValue, supportOldFormat); + else + timeValue.clear(); + return l_error; +} + + +OFCondition DcmTime::getISOFormattedTime(OFString &formattedTime, + const unsigned long pos, + const OFBool seconds, + const OFBool fraction, + const OFBool createMissingPart, + const OFBool supportOldFormat) +{ + OFString dicomTime; + /* get current element value and convert to ISO formatted time */ + OFCondition l_error = getOFString(dicomTime, pos); + if (l_error.good()) + l_error = getISOFormattedTimeFromString(dicomTime, formattedTime, seconds, fraction, createMissingPart, supportOldFormat); + else + formattedTime.clear(); + return l_error; +} + + +OFCondition DcmTime::setCurrentTime(const OFBool seconds, + const OFBool fraction) +{ + OFString dicomTime; + /* set the element value to the current system time */ + OFCondition l_error = getCurrentTime(dicomTime, seconds, fraction); + if (l_error.good()) + l_error = putOFStringArray(dicomTime); + return l_error; +} + + +OFCondition DcmTime::setOFTime(const OFTime &timeValue) +{ + OFString dicomTime; + /* convert OFTime value to DICOM TM format and set the element value */ + OFCondition l_error = getDicomTimeFromOFTime(timeValue, dicomTime); + if (l_error.good()) + l_error = putOFStringArray(dicomTime); + return l_error; +} + + +// ******************************** + + +OFCondition DcmTime::getCurrentTime(OFString &dicomTime, + const OFBool seconds, + const OFBool fraction) +{ + OFCondition l_error = EC_IllegalCall; + OFTime timeValue; + /* get the current system time */ + if (timeValue.setCurrentTime()) + { + /* format: HHMM[SS[.FFFFFF]] */ + if (timeValue.getISOFormattedTime(dicomTime, seconds, fraction, OFFalse /*timeZone*/, OFFalse /*showDelimiter*/)) + l_error = EC_Normal; + } + /* set default time if an error occurred */ + if (l_error.bad()) + { + /* if the current system time cannot be retrieved create a valid default time */ + if (seconds) + { + if (fraction) + { + /* format: HHMMSS.FFFFFF */ + dicomTime = "000000.000000"; + } else { + /* format: HHMMS */ + dicomTime = "000000"; + } + } else { + /* format: HHMM */ + dicomTime = "0000"; + } + } + return l_error; +} + + +OFCondition DcmTime::getDicomTimeFromOFTime(const OFTime &timeValue, + OFString &dicomTime, + const OFBool seconds, + const OFBool fraction) +{ + OFCondition l_error = EC_IllegalParameter; + /* convert OFTime value to DICOM TM format */ + if (timeValue.getISOFormattedTime(dicomTime, seconds, fraction, OFFalse /*timeZone*/, OFFalse /*showDelimiter*/)) + l_error = EC_Normal; + return l_error; +} + + +OFCondition DcmTime::getOFTimeFromString(const OFString &dicomTime, + OFTime &timeValue, + const OFBool supportOldFormat) +{ + OFCondition l_error = EC_IllegalParameter; + /* clear result variable */ + timeValue.clear(); + /* minimal check for valid format */ + if (supportOldFormat || (dicomTime.find(":") == OFString_npos)) + { + unsigned int hour, minute = 0; + double second = 0.0; + /* normalize time format (remove ":" chars) */ + OFString string = dicomTime; + if ((string.length() > 5) && (string[5] == ':')) + string.erase(5, 1); + if ((string.length() > 2) && (string[2] == ':')) + string.erase(2, 1); + /* extract components from time string: HH[MM[SS[.FFFFFF]]] */ + /* scan seconds using OFStandard::atof to avoid locale issues */ + if (sscanf(string.c_str(), "%02u%02u", &hour, &minute) >= 1) + { + if (string.length() > 4) + { + /* get optional seconds part */ + string.erase(0, 4); + second = OFStandard::atof(string.c_str()); + } + /* always use the local time zone */ + if (timeValue.setTime(hour, minute, second, OFTime::getLocalTimeZone())) + l_error = EC_Normal; + } + } + return l_error; +} + + +OFCondition DcmTime::getISOFormattedTimeFromString(const OFString &dicomTime, + OFString &formattedTime, + const OFBool seconds, + const OFBool fraction, + const OFBool createMissingPart, + const OFBool supportOldFormat) +{ + OFCondition result = EC_Normal; + if (!dicomTime.empty()) + { + /* minimal check for valid format */ + if (supportOldFormat || (dicomTime.find(":") == OFString_npos)) + { + const size_t length = dicomTime.length(); + /* check for prior V3.0 version of VR=TM: HH:MM:SS.frac */ + const size_t minPos = (supportOldFormat && (length > 2) && (dicomTime[2] == ':')) ? 3 : 2; + const size_t secPos = (supportOldFormat && (length > minPos + 2) && (dicomTime[minPos + 2] == ':')) ? minPos + 3 : minPos + 2; + /* decimal point for fractional seconds */ + const size_t decPoint = dicomTime.find("."); + const size_t decLength = (decPoint != OFString_npos) ? decPoint : length; + OFString hourStr, minStr, secStr, fracStr; + /* hours */ + if (decLength >= 2) + hourStr = dicomTime.substr(0, 2); + else + hourStr = "00"; + /* minutes */ + if (decLength >= minPos + 2) + minStr = dicomTime.substr(minPos, 2); + else + minStr = "00"; + /* seconds */ + if (decLength >= secPos + 2) + secStr = dicomTime.substr(secPos, 2); + else if (createMissingPart) + secStr = "00"; + /* fractional seconds */ + if ((length >= secPos + 4) && (decPoint == secPos + 2)) + { + if (length < secPos + 9) + { + fracStr = dicomTime.substr(secPos + 3); + fracStr.append(secPos + 9 - length, '0'); + } else + fracStr = dicomTime.substr(secPos + 3, 6); + } else if (createMissingPart) + fracStr = "000000"; + /* concatenate time components */ + formattedTime = hourStr; + formattedTime += ":"; + formattedTime += minStr; + if (seconds && !secStr.empty()) + { + formattedTime += ":"; + formattedTime += secStr; + if (fraction && !fracStr.empty()) + { + formattedTime += "."; + formattedTime += fracStr; + } + } + result = EC_Normal; + } else { + /* invalid input format */ + result = EC_IllegalParameter; + } + /* clear the result variable in case of error */ + if (result.bad()) + formattedTime.clear(); + } else { + /* input string is empty, so is the result string */ + formattedTime.clear(); + } + return result; +} + + +OFCondition DcmTime::getTimeZoneFromString(const OFString &dicomTimeZone, + double &timeZone) +{ + OFCondition result = EC_IllegalParameter; + /* init return value */ + timeZone = 0; + /* minimal check for valid format */ + if (dicomTimeZone.length() == 5) + { + unsigned int hour; + unsigned int minute; + /* positive sign */ + if (dicomTimeZone[0] == '+') + { + /* extract components from time zone string */ + if (sscanf(dicomTimeZone.c_str() + 1, "%02u%02u", &hour, &minute) == 2) + { + timeZone = OFstatic_cast(double, hour) + OFstatic_cast(double, minute) / 60; + result = EC_Normal; + } + } + /* negative sign */ + else if (dicomTimeZone[0] == '-') + { + /* extract components from time zone string */ + if (sscanf(dicomTimeZone.c_str() + 1, "%02u%02u", &hour, &minute) == 2) + { + timeZone = -OFstatic_cast(double, hour) - OFstatic_cast(double, minute) / 60; + result = EC_Normal; + } + } + } + return result; +} + + +// ******************************** + + +OFCondition DcmTime::checkStringValue(const OFString &value, + const OFString &vm, + const OFBool oldFormat) +{ + OFCondition result = EC_Normal; + const size_t valLen = value.length(); + if (valLen > 0) + { + size_t posStart = 0; + unsigned long vmNum = 0; + /* iterate over all value components */ + while (posStart != OFString_npos) + { + ++vmNum; + /* search for next component separator */ + const size_t posEnd = value.find('\\', posStart); + const size_t length = (posEnd == OFString_npos) ? valLen - posStart : posEnd - posStart; + /* check length of current value component */ + if (length > MAX_TM_LENGTH) + { + result = EC_MaximumLengthViolated; + break; + } + else if (dcmEnableVRCheckerForStringValues.get()) + { + /* check value representation */ + const int vrID = DcmElement::scanValue(value, "tm", posStart, length); + if ((vrID != 4) && (!oldFormat || (vrID != 5))) + { + result = EC_ValueRepresentationViolated; + break; + } + } + posStart = (posEnd == OFString_npos) ? posEnd : posEnd + 1; + } + if (result.good() && !vm.empty()) + { + /* check value multiplicity */ + result = DcmElement::checkVM(vmNum, vm); + } + } + return result; +} diff --git a/dcmdata/libsrc/dcvruc.cc b/dcmdata/libsrc/dcvruc.cc new file mode 100644 index 00000000..aed7031b --- /dev/null +++ b/dcmdata/libsrc/dcvruc.cc @@ -0,0 +1,116 @@ +/* + * + * Copyright (C) 2015, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Joerg Riesmeier + * + * Purpose: Implementation of class DcmUnlimitedCharacters + * + */ + + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/dcmdata/dcvruc.h" + + +// ******************************** + + +DcmUnlimitedCharacters::DcmUnlimitedCharacters(const DcmTag &tag, + const Uint32 len) + : DcmCharString(tag, len) +{ + setMaxLength(DCM_UndefinedLength); +} + + +DcmUnlimitedCharacters::DcmUnlimitedCharacters(const DcmUnlimitedCharacters &old) + : DcmCharString(old) +{ +} + + +DcmUnlimitedCharacters::~DcmUnlimitedCharacters() +{ +} + + +DcmUnlimitedCharacters &DcmUnlimitedCharacters::operator=(const DcmUnlimitedCharacters &obj) +{ + DcmCharString::operator=(obj); + return *this; +} + + +OFCondition DcmUnlimitedCharacters::copyFrom(const DcmObject& rhs) +{ + if (this != &rhs) + { + if (rhs.ident() != ident()) return EC_IllegalCall; + *this = OFstatic_cast(const DcmUnlimitedCharacters &, rhs); + } + return EC_Normal; +} + + +// ******************************** + + +DcmEVR DcmUnlimitedCharacters::ident() const +{ + return EVR_UC; +} + + +OFCondition DcmUnlimitedCharacters::checkValue(const OFString &vm, + const OFBool /*oldFormat*/) +{ + OFString strVal; + /* get "raw value" without any modifications (if possible) */ + OFCondition l_error = getStringValue(strVal); + if (l_error.good()) + { + OFString charset; + /* try to determine the value of the SpecificCharacterSet element */ + getSpecificCharacterSet(charset); + l_error = DcmUnlimitedCharacters::checkStringValue(strVal, vm, charset); + } + return l_error; +} + + +// ******************************** + + +OFCondition DcmUnlimitedCharacters::getOFString(OFString &stringVal, + const unsigned long pos, + OFBool normalize) +{ + OFCondition l_error = DcmCharString::getOFString(stringVal, pos, normalize); + if (l_error.good() && normalize) + normalizeString(stringVal, !MULTIPART, !DELETE_LEADING, DELETE_TRAILING); + return l_error; +} + + +// ******************************** + + +OFCondition DcmUnlimitedCharacters::checkStringValue(const OFString &value, + const OFString &vm, + const OFString &charset) +{ + return DcmByteString::checkStringValue(value, vm, "uc", 20, 0 /* maxLen: no check */, charset); +} diff --git a/dcmdata/libsrc/dcvrui.cc b/dcmdata/libsrc/dcvrui.cc new file mode 100644 index 00000000..c2e5f5ce --- /dev/null +++ b/dcmdata/libsrc/dcvrui.cc @@ -0,0 +1,248 @@ +/* + * + * Copyright (C) 1994-2012, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Gerd Ehlers, Andreas Barth + * + * Purpose: Implementation of class DcmUniqueIdentifier + * + */ + + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/ofstd/ofstream.h" +#include "dcmtk/ofstd/ofstring.h" +#include "dcmtk/ofstd/ofstd.h" +#include "dcmtk/dcmdata/dcvrui.h" +#include "dcmtk/dcmdata/dcuid.h" + +#define INCLUDE_CSTRING +#define INCLUDE_CCTYPE +#include "dcmtk/ofstd/ofstdinc.h" + + +#define MAX_UI_LENGTH 64 + + +// ******************************** + + +DcmUniqueIdentifier::DcmUniqueIdentifier(const DcmTag &tag, + const Uint32 len) + : DcmByteString(tag, len) +{ + /* padding character is NULL not a space! */ + setPaddingChar('\0'); + setMaxLength(MAX_UI_LENGTH); + setNonSignificantChars("\\"); +} + + +DcmUniqueIdentifier::DcmUniqueIdentifier(const DcmUniqueIdentifier &old) + : DcmByteString(old) +{ +} + + +DcmUniqueIdentifier::~DcmUniqueIdentifier() +{ +} + + +DcmUniqueIdentifier &DcmUniqueIdentifier::operator=(const DcmUniqueIdentifier &obj) +{ + DcmByteString::operator=(obj); + return *this; +} + + +OFCondition DcmUniqueIdentifier::copyFrom(const DcmObject& rhs) +{ + if (this != &rhs) + { + if (rhs.ident() != ident()) return EC_IllegalCall; + *this = OFstatic_cast(const DcmUniqueIdentifier &, rhs); + } + return EC_Normal; +} + + +// ******************************** + + +DcmEVR DcmUniqueIdentifier::ident() const +{ + return EVR_UI; +} + + +OFCondition DcmUniqueIdentifier::checkValue(const OFString &vm, + const OFBool /*oldFormat*/) +{ + OFString strVal; + /* get "raw value" without any modifications (if possible) */ + OFCondition l_error = getStringValue(strVal); + if (l_error.good()) + l_error = DcmUniqueIdentifier::checkStringValue(strVal, vm); + return l_error; +} + + +// ******************************** + + +void DcmUniqueIdentifier::print(STD_NAMESPACE ostream &out, + const size_t flags, + const int level, + const char * /*pixelFileName*/, + size_t * /*pixelCounter*/) +{ + if (valueLoaded()) + { + /* get string data (possibly multi-valued) */ + char *stringVal = NULL; + Uint32 stringLen = 0; + getString(stringVal, stringLen); + if ((stringVal != NULL) && (stringLen > 0)) + { + const char *symbol = NULL; + if (!(flags & DCMTypes::PF_doNotMapUIDsToNames)) + { + /* check whether UID number can be mapped to a UID name */ + symbol = dcmFindNameOfUID(stringVal); + } + if ((symbol != NULL) && (strlen(symbol) > 0)) + { + const size_t bufSize = strlen(symbol) + 1 /* for "=" */ + 1; + char *buffer = new char[bufSize]; + if (buffer != NULL) + { + /* concatenate "=" and the UID name */ + OFStandard::strlcpy(buffer, "=", bufSize); + OFStandard::strlcat(buffer, symbol, bufSize); + printInfoLine(out, flags, level, buffer, NULL /*tag*/, OFFalse /*isInfo*/); + /* delete temporary character buffer */ + delete[] buffer; + } else /* could not allocate buffer */ + DcmByteString::print(out, flags, level); + } else /* no symbol (UID name) found or mapping switched off */ + DcmByteString::print(out, flags, level); + } else + printInfoLine(out, flags, level, "(no value available)"); + } else + printInfoLine(out, flags, level, "(not loaded)"); +} + + +// ******************************** + + +OFCondition DcmUniqueIdentifier::getOFString(OFString &stringVal, + const unsigned long pos, + OFBool normalize) +{ + OFCondition l_error = DcmByteString::getOFString(stringVal, pos, normalize); + if (l_error.good() && normalize) + normalizeString(stringVal, !MULTIPART, !DELETE_LEADING, DELETE_TRAILING, getPaddingChar() /* NULL-byte */); + return l_error; +} + + +// ******************************** + + +OFCondition DcmUniqueIdentifier::putString(const char *stringVal) +{ + /* determine length of the string value */ + const size_t stringLen = (stringVal != NULL) ? strlen(stringVal) : 0; + /* call the real function */ + return putString(stringVal, OFstatic_cast(Uint32, stringLen)); +} + + +OFCondition DcmUniqueIdentifier::putString(const char *stringVal, + const Uint32 stringLen) +{ + const char *uid = stringVal; + Uint32 uidLen = stringLen; + /* check whether parameter contains a UID name instead of a UID number */ + if ((stringVal != NULL) && (stringVal[0] == '=')) + { + uid = dcmFindUIDFromName(stringVal + 1); + uidLen = (uid != NULL) ? OFstatic_cast(Uint32, strlen(uid)) : 0; + } + /* call inherited method to set the UID string */ + return DcmByteString::putString(uid, uidLen); +} + + +// ******************************** + + +OFCondition DcmUniqueIdentifier::makeMachineByteString(const Uint32 length) +{ + /* get string data */ + char *value = OFstatic_cast(char *, getValue()); + /* determine initial string length */ + const size_t len = (length == 0) ? getLengthField() : length; + if ((value != NULL) && (len > 0)) + { + /* check whether string representation is not the internal one */ + if (getStringMode() != DCM_MachineString) + { + /* check whether automatic input data correction is enabled */ + if (dcmEnableAutomaticInputDataCorrection.get()) + { + /* + ** Remove any leading, embedded, or trailing white space. + ** This manipulation attempts to correct problems with + ** incorrectly encoded UIDs which have been observed in + ** some images. + */ + size_t curPos = 0; + for (size_t i = 0; i < len; i++) + { + if (!isspace(OFstatic_cast(unsigned char, value[i]))) + value[curPos++] = value[i]; + } + /* there was at least one space character in the string */ + if (curPos < len) + { + DCMDATA_WARN("DcmUniqueIdentifier: Element " << getTagName() << " " << getTag() + << " contains one or more space characters, which were removed"); + /* remember new length */ + const Uint32 newLen = OFstatic_cast(Uint32, curPos); + /* blank out all trailing characters */ + while (curPos < len) + value[curPos++] = '\0'; + /* call inherited method: re-computes the string length, etc. */ + return DcmByteString::makeMachineByteString(newLen); + } + } + } + } + /* call inherited method: re-computes the string length, etc. */ + return DcmByteString::makeMachineByteString(OFstatic_cast(Uint32, len)); +} + + +// ******************************** + + +OFCondition DcmUniqueIdentifier::checkStringValue(const OFString &value, + const OFString &vm) +{ + return DcmByteString::checkStringValue(value, vm, "ui", 9, MAX_UI_LENGTH); +} diff --git a/dcmdata/libsrc/dcvrul.cc b/dcmdata/libsrc/dcvrul.cc new file mode 100644 index 00000000..28a535ab --- /dev/null +++ b/dcmdata/libsrc/dcvrul.cc @@ -0,0 +1,364 @@ +/* + * + * Copyright (C) 1994-2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Gerd Ehlers, Andreas Barth + * + * Purpose: Implementation of class DcmUnsignedLong + * + */ + + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/ofstd/ofstream.h" +#include "dcmtk/dcmdata/dcvrul.h" + +#define INCLUDE_CSTDIO +#define INCLUDE_CSTRING +#include "dcmtk/ofstd/ofstdinc.h" + + +// ******************************** + + +DcmUnsignedLong::DcmUnsignedLong(const DcmTag &tag, + const Uint32 len) + : DcmElement(tag, len) +{ +} + + +DcmUnsignedLong::DcmUnsignedLong(const DcmUnsignedLong &old) + : DcmElement(old) +{ +} + + +DcmUnsignedLong::~DcmUnsignedLong() +{ +} + + +DcmUnsignedLong &DcmUnsignedLong::operator=(const DcmUnsignedLong &obj) +{ + DcmElement::operator=(obj); + return *this; +} + + +int DcmUnsignedLong::compare(const DcmElement& rhs) const +{ + int result = DcmElement::compare(rhs); + if (result != 0) + { + return result; + } + + /* cast away constness (dcmdata is not const correct...) */ + DcmUnsignedLong* myThis = NULL; + DcmUnsignedLong* myRhs = NULL; + myThis = OFconst_cast(DcmUnsignedLong*, this); + myRhs = OFstatic_cast(DcmUnsignedLong*, OFconst_cast(DcmElement*, &rhs)); + + /* iterate over all components and test equality */ + unsigned long thisVM = myThis->getVM(); + for (unsigned long count = 0; count < thisVM; count++) + { + Uint32 val = 0; + if (myThis->getUint32(val, count).good()) + { + Uint32 rhsVal = 0; + if (myRhs->getUint32(rhsVal, count).good()) + { + if (val > rhsVal) + { + return 1; + } + else if (val < rhsVal) + { + return -1; + } + } + else + { + break; // values equal until this point (rhs shorter) + } + } + } + + /* we get here if all values are equal. Now look at the number of components. */ + unsigned long rhsVM = myRhs->getVM(); + if (thisVM < rhsVM) + { + return -1; + } + else if (thisVM > rhsVM) + { + return 1; + } + + /* all values as well as VM equal: objects are equal */ + return 0; +} + + +OFCondition DcmUnsignedLong::copyFrom(const DcmObject& rhs) +{ + if (this != &rhs) + { + if (rhs.ident() != ident()) return EC_IllegalCall; + *this = OFstatic_cast(const DcmUnsignedLong &, rhs); + } + return EC_Normal; +} + + +// ******************************** + + +DcmEVR DcmUnsignedLong::ident() const +{ + return EVR_UL; +} + + +OFCondition DcmUnsignedLong::checkValue(const OFString &vm, + const OFBool /*oldFormat*/) +{ + /* check VM only */ + return DcmElement::checkVM(getVM(), vm); +} + + +unsigned long DcmUnsignedLong::getVM() +{ + return OFstatic_cast(unsigned long, getLengthField() / sizeof(Uint32)); +} + + +// ******************************** + + +void DcmUnsignedLong::print(STD_NAMESPACE ostream&out, + const size_t flags, + const int level, + const char * /*pixelFileName*/, + size_t * /*pixelCounter*/) +{ + if (valueLoaded()) + { + /* get unsigned integer data */ + Uint32 *uintVals; + errorFlag = getUint32Array(uintVals); + if (uintVals != NULL) + { + const unsigned long count = getVM(); + const unsigned long maxLength = (flags & DCMTypes::PF_shortenLongTagValues) ? + DCM_OptPrintLineLength : OFstatic_cast(unsigned long, -1) /*unlimited*/; + unsigned long printedLength = 0; + unsigned long newLength = 0; + char buffer[32]; + /* print line start with tag and VR */ + printInfoLineStart(out, flags, level); + /* print multiple values */ + for (unsigned int i = 0; i < count; i++, uintVals++) + { + /* check whether first value is printed (omit delimiter) */ + if (i == 0) +#if SIZEOF_LONG == 8 + sprintf(buffer, "%u", *uintVals); + else + sprintf(buffer, "\\%u", *uintVals); +#else + sprintf(buffer, "%lu", *uintVals); + else + sprintf(buffer, "\\%lu", *uintVals); +#endif + /* check whether current value sticks to the length limit */ + newLength = printedLength + OFstatic_cast(unsigned long, strlen(buffer)); + if ((newLength <= maxLength) && ((i + 1 == count) || (newLength + 3 <= maxLength))) + { + out << buffer; + printedLength = newLength; + } else { + /* check whether output has been truncated */ + if (i + 1 < count) + { + out << "..."; + printedLength += 3; + } + break; + } + } + /* print line end with length, VM and tag name */ + printInfoLineEnd(out, flags, printedLength); + } else + printInfoLine(out, flags, level, "(no value available)"); + } else + printInfoLine(out, flags, level, "(not loaded)"); +} + + +// ******************************** + + +OFCondition DcmUnsignedLong::getUint32(Uint32 &uintVal, + const unsigned long pos) +{ + /* get unsigned integer data */ + Uint32 *uintValues = NULL; + errorFlag = getUint32Array(uintValues); + /* check data before returning */ + if (errorFlag.good()) + { + if (uintValues == NULL) + errorFlag = EC_IllegalCall; + else if (pos >= getVM()) + errorFlag = EC_IllegalParameter; + else + uintVal = uintValues[pos]; + } + /* clear value in case of error */ + if (errorFlag.bad()) + uintVal = 0; + return errorFlag; +} + + +OFCondition DcmUnsignedLong::getUint32Array(Uint32 *&uintVals) +{ + uintVals = OFstatic_cast(Uint32 *, getValue()); + return errorFlag; +} + + +// ******************************** + + +OFCondition DcmUnsignedLong::getOFString(OFString &stringVal, + const unsigned long pos, + OFBool /*normalize*/) +{ + Uint32 uintVal; + /* get the specified numeric value */ + errorFlag = getUint32(uintVal, pos); + if (errorFlag.good()) + { + /* ... and convert it to a character string */ + char buffer[32]; + sprintf(buffer, "%lu", OFstatic_cast(unsigned long, uintVal)); + /* assign result */ + stringVal = buffer; + } + return errorFlag; +} + + +// ******************************** + + +OFCondition DcmUnsignedLong::putUint32(const Uint32 uintVal, + const unsigned long pos) +{ + Uint32 val = uintVal; + errorFlag = changeValue(&val, OFstatic_cast(Uint32, sizeof(Uint32) * pos), OFstatic_cast(Uint32, sizeof(Uint32))); + return errorFlag; +} + + +OFCondition DcmUnsignedLong::putUint32Array(const Uint32 *uintVals, + const unsigned long numUints) +{ + errorFlag = EC_Normal; + if (numUints > 0) + { + /* check for valid data */ + if (uintVals != NULL) + errorFlag = putValue(uintVals, OFstatic_cast(Uint32, sizeof(Uint32) * OFstatic_cast(size_t, numUints))); + else + errorFlag = EC_CorruptedData; + } else + errorFlag = putValue(NULL, 0); + return errorFlag; +} + + +// ******************************** + + +OFCondition DcmUnsignedLong::putString(const char *stringVal) +{ + /* determine length of the string value */ + const size_t stringLen = (stringVal != NULL) ? strlen(stringVal) : 0; + /* call the real function */ + return putString(stringVal, OFstatic_cast(Uint32, stringLen)); +} + + +OFCondition DcmUnsignedLong::putString(const char *stringVal, + const Uint32 stringLen) +{ + errorFlag = EC_Normal; + /* determine VM of the string */ + const unsigned long vm = DcmElement::determineVM(stringVal, stringLen); + if (vm > 0) + { + Uint32 *field = new Uint32[vm]; + OFString value; + size_t pos = 0; + /* retrieve unsigned integer data from character string */ + for (unsigned long i = 0; (i < vm) && errorFlag.good(); i++) + { + /* get specified value from multi-valued string */ + pos = DcmElement::getValueFromString(stringVal, pos, stringLen, value); + if (value.empty() || +#if SIZEOF_LONG == 8 + (sscanf(value.c_str(), "%u", &field[i]) != 1) +#else + (sscanf(value.c_str(), "%lu", &field[i]) != 1) +#endif + ) + { + errorFlag = EC_CorruptedData; + } + } + /* set binary data as the element value */ + if (errorFlag.good()) + errorFlag = putUint32Array(field, vm); + /* delete temporary buffer */ + delete[] field; + } else + errorFlag = putValue(NULL, 0); + return errorFlag; +} + + +// ******************************** + + +OFCondition DcmUnsignedLong::verify(const OFBool autocorrect) +{ + /* check for valid value length */ + if (getLengthField() % (sizeof(Uint32)) != 0) + { + errorFlag = EC_CorruptedData; + if (autocorrect) + { + /* strip to valid length */ + setLengthField(getLengthField() - (getLengthField() % OFstatic_cast(Uint32, sizeof(Uint32)))); + } + } else + errorFlag = EC_Normal; + return errorFlag; +} diff --git a/dcmdata/libsrc/dcvrulup.cc b/dcmdata/libsrc/dcvrulup.cc new file mode 100644 index 00000000..68cd01e5 --- /dev/null +++ b/dcmdata/libsrc/dcvrulup.cc @@ -0,0 +1,131 @@ +/* + * + * Copyright (C) 1994-2010, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Gerd Ehlers, Andreas Barth + * + * Purpose: Implementation of class DcmUnsignedLongOffset + * + */ + + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmdata/dcvrulup.h" + +#define INCLUDE_CSTDIO +#define INCLUDE_CSTRING +#include "dcmtk/ofstd/ofstdinc.h" + + +// ******************************** + + +DcmUnsignedLongOffset::DcmUnsignedLongOffset(const DcmTag &tag, + const Uint32 len) + : DcmUnsignedLong(tag, len), + nextRecord(NULL) +{ +} + + +DcmUnsignedLongOffset::DcmUnsignedLongOffset(const DcmUnsignedLongOffset &old) + : DcmUnsignedLong(old), + nextRecord(old.nextRecord) +{ +} + + +DcmUnsignedLongOffset& DcmUnsignedLongOffset::operator=(const DcmUnsignedLongOffset& obj) +{ + if (this != &obj) + { + // copy parent's member variables + DcmUnsignedLong::operator=(obj); + // copy member variables + nextRecord = obj.nextRecord; + } + return *this; +} + + +DcmUnsignedLongOffset::~DcmUnsignedLongOffset() +{ +} + + +OFCondition DcmUnsignedLongOffset::copyFrom(const DcmObject& rhs) +{ + if (this != &rhs) + { + if (rhs.ident() != ident()) return EC_IllegalCall; + *this = OFstatic_cast(const DcmUnsignedLongOffset &, rhs); + } + return EC_Normal; +} + + +// ******************************** + + +DcmEVR DcmUnsignedLongOffset::ident() const +{ + /* internal type identifier */ + return EVR_up; +} + + +OFCondition DcmUnsignedLongOffset::clear() +{ + /* call inherited method */ + errorFlag = DcmUnsignedLong::clear(); + /* remove reference to object */ + nextRecord = NULL; + return errorFlag; +} + + +// ******************************** + + +DcmObject* DcmUnsignedLongOffset::getNextRecord() +{ + errorFlag = EC_Normal; + /* return pointer to currently stored object reference */ + return nextRecord; +} + + +DcmObject *DcmUnsignedLongOffset::setNextRecord(DcmObject *record) +{ + errorFlag = EC_Normal; + /* store new object reference */ + nextRecord = record; + return record; +} + + +// ******************************** + + +OFCondition DcmUnsignedLongOffset::verify(const OFBool autocorrect) +{ + /* call inherited method */ + errorFlag = DcmUnsignedLong::verify(autocorrect); + /* perform additional checks on the stored value */ + Uint32 *uintVals; + errorFlag = getUint32Array(uintVals); + if (errorFlag.good() && (getLengthField() > 0) && (uintVals != NULL) && (*uintVals != 0) && (nextRecord == NULL)) + errorFlag = EC_CorruptedData; + return errorFlag; +} diff --git a/dcmdata/libsrc/dcvrur.cc b/dcmdata/libsrc/dcvrur.cc new file mode 100644 index 00000000..881ca4cf --- /dev/null +++ b/dcmdata/libsrc/dcvrur.cc @@ -0,0 +1,125 @@ +/* + * + * Copyright (C) 2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Joerg Riesmeier + * + * Purpose: Implementation of class DcmUniversalResourceIdentifierOrLocator + * + */ + + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/dcmdata/dcvrur.h" + + +// ******************************** + + +DcmUniversalResourceIdentifierOrLocator::DcmUniversalResourceIdentifierOrLocator(const DcmTag &tag, + const Uint32 len) + : DcmByteString(tag, len) +{ + setMaxLength(DCM_UndefinedLength); +} + + +DcmUniversalResourceIdentifierOrLocator::DcmUniversalResourceIdentifierOrLocator(const DcmUniversalResourceIdentifierOrLocator &old) + : DcmByteString(old) +{ +} + + +DcmUniversalResourceIdentifierOrLocator::~DcmUniversalResourceIdentifierOrLocator() +{ +} + + +DcmUniversalResourceIdentifierOrLocator &DcmUniversalResourceIdentifierOrLocator::operator=(const DcmUniversalResourceIdentifierOrLocator &obj) +{ + DcmByteString::operator=(obj); + return *this; +} + + +OFCondition DcmUniversalResourceIdentifierOrLocator::copyFrom(const DcmObject& rhs) +{ + if (this != &rhs) + { + if (rhs.ident() != ident()) return EC_IllegalCall; + *this = OFstatic_cast(const DcmUniversalResourceIdentifierOrLocator &, rhs); + } + return EC_Normal; +} + + +// ******************************** + + +DcmEVR DcmUniversalResourceIdentifierOrLocator::ident() const +{ + return EVR_UR; +} + + +OFCondition DcmUniversalResourceIdentifierOrLocator::checkValue(const OFString & /*vm*/, + const OFBool /*oldFormat*/) +{ + OFString strVal; + /* get "raw value" without any modifications (if possible) */ + OFCondition l_error = getStringValue(strVal); + if (l_error.good()) + l_error = DcmUniversalResourceIdentifierOrLocator::checkStringValue(strVal); + return l_error; +} + + +unsigned long DcmUniversalResourceIdentifierOrLocator::getVM() +{ + /* value multiplicity is 1 for non-empty string, 0 otherwise */ + return (getRealLength() > 0) ? 1 : 0; +} + + +// ******************************** + + +OFCondition DcmUniversalResourceIdentifierOrLocator::getOFString(OFString &strValue, + const unsigned long /*pos*/, + OFBool normalize) +{ + /* treat backslash as a normal character */ + return getOFStringArray(strValue, normalize); +} + + +OFCondition DcmUniversalResourceIdentifierOrLocator::getOFStringArray(OFString &strValue, + OFBool normalize) +{ + /* get string value without handling the "\" as a delimiter */ + OFCondition l_error = getStringValue(strValue); + if (l_error.good() && normalize) + normalizeString(strValue, !MULTIPART, !DELETE_LEADING, DELETE_TRAILING); + return l_error; +} + + +// ******************************** + + +OFCondition DcmUniversalResourceIdentifierOrLocator::checkStringValue(const OFString &value) +{ + return DcmByteString::checkStringValue(value, "" /* vm */, "ur", 19, 0 /* maxLen: no check */); +} diff --git a/dcmdata/libsrc/dcvrus.cc b/dcmdata/libsrc/dcvrus.cc new file mode 100644 index 00000000..0954595b --- /dev/null +++ b/dcmdata/libsrc/dcvrus.cc @@ -0,0 +1,349 @@ +/* + * + * Copyright (C) 1994-2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Gerd Ehlers, Andreas Barth + * + * Purpose: Implementation of class DcmUnsignedShort + * + */ + + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ +#include "dcmtk/ofstd/ofstream.h" +#include "dcmtk/dcmdata/dcvrus.h" + +#define INCLUDE_CSTDIO +#define INCLUDE_CSTRING +#include "dcmtk/ofstd/ofstdinc.h" + + +// ******************************** + + +DcmUnsignedShort::DcmUnsignedShort(const DcmTag &tag, const Uint32 len) + : DcmElement(tag, len) +{ +} + + +DcmUnsignedShort::DcmUnsignedShort(const DcmUnsignedShort &old) + : DcmElement(old) +{ +} + + +DcmUnsignedShort::~DcmUnsignedShort() +{ +} + + +DcmUnsignedShort &DcmUnsignedShort::operator=(const DcmUnsignedShort &obj) +{ + DcmElement::operator=(obj); + return *this; +} + + +int DcmUnsignedShort::compare(const DcmElement& rhs) const +{ + int result = DcmElement::compare(rhs); + if (result != 0) + { + return result; + } + + /* cast away constness (dcmdata is not const correct...) */ + DcmUnsignedShort* myThis = NULL; + DcmUnsignedShort* myRhs = NULL; + myThis = OFconst_cast(DcmUnsignedShort*, this); + myRhs = OFstatic_cast(DcmUnsignedShort*, OFconst_cast(DcmElement*, &rhs)); + + /* iterate over all components and test equality */ + unsigned long thisVM = myThis->getVM(); + for (unsigned long count = 0; count < thisVM; count++) + { + Uint16 val = 0; + if (myThis->getUint16(val, count).good()) + { + Uint16 rhsVal = 0; + if (myRhs->getUint16(rhsVal, count).good()) + { + if (val > rhsVal) + { + return 1; + } + else if (val < rhsVal) + { + return -1; + } + } + else + { + break; // values equal until this point (rhs shorter) + } + } + } + + /* we get here if all values are equal. Now look at the number of components. */ + unsigned long rhsVM = myRhs->getVM(); + if (thisVM < rhsVM) + { + return -1; + } + else if (thisVM > rhsVM) + { + return 1; + } + + /* all values as well as VM equal: objects are equal */ + return 0; +} + + +OFCondition DcmUnsignedShort::copyFrom(const DcmObject& rhs) +{ + if (this != &rhs) + { + if (rhs.ident() != ident()) return EC_IllegalCall; + *this = OFstatic_cast(const DcmUnsignedShort &, rhs); + } + return EC_Normal; +} + + +// ******************************** + + +DcmEVR DcmUnsignedShort::ident() const +{ + return EVR_US; +} + + +OFCondition DcmUnsignedShort::checkValue(const OFString &vm, + const OFBool /*oldFormat*/) +{ + /* check VM only */ + return DcmElement::checkVM(getVM(), vm); +} + + +unsigned long DcmUnsignedShort::getVM() +{ + return OFstatic_cast(unsigned long, getLengthField() / sizeof(Uint16)); +} + + +// ******************************** + + +void DcmUnsignedShort::print(STD_NAMESPACE ostream&out, + const size_t flags, + const int level, + const char * /*pixelFileName*/, + size_t * /*pixelCounter*/) +{ + if (valueLoaded()) + { + /* get unsigned integer data */ + Uint16 *uintVals; + errorFlag = getUint16Array(uintVals); + if (uintVals != NULL) + { + const unsigned long count = getVM(); + const unsigned long maxLength = (flags & DCMTypes::PF_shortenLongTagValues) ? + DCM_OptPrintLineLength : OFstatic_cast(unsigned long, -1) /*unlimited*/; + unsigned long printedLength = 0; + unsigned long newLength = 0; + char buffer[32]; + /* print line start with tag and VR */ + printInfoLineStart(out, flags, level); + /* print multiple values */ + for (unsigned int i = 0; i < count; i++, uintVals++) + { + /* check whether first value is printed (omit delimiter) */ + if (i == 0) + sprintf(buffer, "%hu", *uintVals); + else + sprintf(buffer, "\\%hu", *uintVals); + /* check whether current value sticks to the length limit */ + newLength = printedLength + OFstatic_cast(unsigned long, strlen(buffer)); + if ((newLength <= maxLength) && ((i + 1 == count) || (newLength + 3 <= maxLength))) + { + out << buffer; + printedLength = newLength; + } else { + /* check whether output has been truncated */ + if (i + 1 < count) + { + out << "..."; + printedLength += 3; + } + break; + } + } + /* print line end with length, VM and tag name */ + printInfoLineEnd(out, flags, printedLength); + } else + printInfoLine(out, flags, level, "(no value available)"); + } else + printInfoLine(out, flags, level, "(not loaded)"); +} + + +// ******************************** + + +OFCondition DcmUnsignedShort::getUint16(Uint16 &uintVal, + const unsigned long pos) +{ + /* get unsigned integer data */ + Uint16 *uintValues = NULL; + errorFlag = getUint16Array(uintValues); + /* check data before returning */ + if (errorFlag.good()) + { + if (uintValues == NULL) + errorFlag = EC_IllegalCall; + else if (pos >= getVM()) + errorFlag = EC_IllegalParameter; + else + uintVal = uintValues[pos]; + } + /* clear value in case of error */ + if (errorFlag.bad()) + uintVal = 0; + return errorFlag; +} + + +OFCondition DcmUnsignedShort::getUint16Array(Uint16 *&uintVals) +{ + uintVals = OFstatic_cast(Uint16 *, getValue()); + return errorFlag; +} + + +// ******************************** + + +OFCondition DcmUnsignedShort::getOFString(OFString &stringVal, + const unsigned long pos, + OFBool /*normalize*/) +{ + Uint16 uintVal; + /* get the specified numeric value */ + errorFlag = getUint16(uintVal, pos); + if (errorFlag.good()) + { + /* ... and convert it to a character string */ + char buffer[32]; + sprintf(buffer, "%hu", uintVal); + /* assign result */ + stringVal = buffer; + } + return errorFlag; +} + + +// ******************************** + + +OFCondition DcmUnsignedShort::putUint16(const Uint16 uintVal, + const unsigned long pos) +{ + Uint16 val = uintVal; + errorFlag = changeValue(&val, OFstatic_cast(Uint32, sizeof(Uint16) * pos), OFstatic_cast(Uint32, sizeof(Uint16))); + return errorFlag; +} + + +OFCondition DcmUnsignedShort::putUint16Array(const Uint16 *uintVals, + const unsigned long numUints) +{ + errorFlag = EC_Normal; + if (numUints > 0) + { + /* check for valid data */ + if (uintVals != NULL) + errorFlag = putValue(uintVals, OFstatic_cast(Uint32, sizeof(Uint16) * OFstatic_cast(size_t, numUints))); + else + errorFlag = EC_CorruptedData; + } else + errorFlag = putValue(NULL, 0); + return errorFlag; +} + + +// ******************************** + + +OFCondition DcmUnsignedShort::putString(const char *stringVal) +{ + /* determine length of the string value */ + const size_t stringLen = (stringVal != NULL) ? strlen(stringVal) : 0; + /* call the real function */ + return putString(stringVal, OFstatic_cast(Uint32, stringLen)); +} + + +OFCondition DcmUnsignedShort::putString(const char *stringVal, + const Uint32 stringLen) +{ + errorFlag = EC_Normal; + /* determine VM of the string */ + const unsigned long vm = DcmElement::determineVM(stringVal, stringLen); + if (vm > 0) + { + Uint16 *field = new Uint16[vm]; + OFString value; + size_t pos = 0; + /* retrieve unsigned integer data from character string */ + for (unsigned long i = 0; (i < vm) && errorFlag.good(); i++) + { + /* get specified value from multi-valued string */ + pos = DcmElement::getValueFromString(stringVal, pos, stringLen, value); + if (value.empty() || (sscanf(value.c_str(), "%hu", &field[i]) != 1)) + errorFlag = EC_CorruptedData; + } + /* set binary data as the element value */ + if (errorFlag.good()) + errorFlag = putUint16Array(field, vm); + /* delete temporary buffer */ + delete[] field; + } else + errorFlag = putValue(NULL, 0); + return errorFlag; +} + + +// ******************************** + + +OFCondition DcmUnsignedShort::verify(const OFBool autocorrect) +{ + /* check for valid value length */ + if (getLengthField() % (sizeof(Uint16)) != 0) + { + errorFlag = EC_CorruptedData; + if (autocorrect) + { + /* strip to valid length */ + setLengthField(getLengthField() - (getLengthField() % OFstatic_cast(Uint32, sizeof(Uint16)))); + } + } else + errorFlag = EC_Normal; + return errorFlag; +} diff --git a/dcmdata/libsrc/dcvrut.cc b/dcmdata/libsrc/dcvrut.cc new file mode 100644 index 00000000..9a21d515 --- /dev/null +++ b/dcmdata/libsrc/dcvrut.cc @@ -0,0 +1,131 @@ +/* + * + * Copyright (C) 1998-2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Andrew Hewett + * + * Purpose: Implementation of class DcmUnlimitedText + * + */ + + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/dcmdata/dcvrut.h" + + +// ******************************** + + +DcmUnlimitedText::DcmUnlimitedText(const DcmTag &tag, + const Uint32 len) + : DcmCharString(tag, len) +{ + setMaxLength(DCM_UndefinedLength); +} + + +DcmUnlimitedText::DcmUnlimitedText(const DcmUnlimitedText &old) + : DcmCharString(old) +{ +} + + +DcmUnlimitedText::~DcmUnlimitedText() +{ +} + + +DcmUnlimitedText &DcmUnlimitedText::operator=(const DcmUnlimitedText &obj) +{ + DcmCharString::operator=(obj); + return *this; +} + + +OFCondition DcmUnlimitedText::copyFrom(const DcmObject& rhs) +{ + if (this != &rhs) + { + if (rhs.ident() != ident()) return EC_IllegalCall; + *this = OFstatic_cast(const DcmUnlimitedText &, rhs); + } + return EC_Normal; +} + + +// ******************************** + + +DcmEVR DcmUnlimitedText::ident() const +{ + return EVR_UT; +} + + +OFCondition DcmUnlimitedText::checkValue(const OFString & /*vm*/, + const OFBool /*oldFormat*/) +{ + OFString strVal; + /* get "raw value" without any modifications (if possible) */ + OFCondition l_error = getStringValue(strVal); + if (l_error.good()) + { + OFString charset; + /* try to determine the value of the SpecificCharacterSet element */ + getSpecificCharacterSet(charset); + l_error = DcmUnlimitedText::checkStringValue(strVal, charset); + } + return l_error; +} + + +unsigned long DcmUnlimitedText::getVM() +{ + /* value multiplicity is 1 for non-empty string, 0 otherwise */ + return (getRealLength() > 0) ? 1 : 0; +} + + +// ******************************** + + +OFCondition DcmUnlimitedText::getOFString(OFString &strValue, + const unsigned long /*pos*/, + OFBool normalize) +{ + /* treat backslash as a normal character */ + return getOFStringArray(strValue, normalize); +} + + +OFCondition DcmUnlimitedText::getOFStringArray(OFString &strValue, + OFBool normalize) +{ + /* get string value without handling the "\" as a delimiter */ + OFCondition l_error = getStringValue(strValue); + if (l_error.good() && normalize) + normalizeString(strValue, !MULTIPART, !DELETE_LEADING, DELETE_TRAILING); + return l_error; +} + + +// ******************************** + + +OFCondition DcmUnlimitedText::checkStringValue(const OFString &value, + const OFString &charset) +{ + return DcmByteString::checkStringValue(value, "" /* vm */, "lt", 14, 0 /* maxLen: no check */, charset); +} diff --git a/dcmdata/libsrc/dcwcache.cc b/dcmdata/libsrc/dcwcache.cc new file mode 100644 index 00000000..5791c9c7 --- /dev/null +++ b/dcmdata/libsrc/dcwcache.cc @@ -0,0 +1,91 @@ +/* + * + * Copyright (C) 2007-2010, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Marco Eichelberg + * + * Purpose: Implementation of class DcmWriteCache + * + */ + + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/dcmdata/dcwcache.h" /* for class DcmWriteCache */ +#include "dcmtk/dcmdata/dcelem.h" /* for class DcmElement */ +#include "dcmtk/dcmdata/dcostrma.h" /* for class DcmOutputStream */ + + +void DcmWriteCache::init(void *owner, + Uint32 fieldLength, + Uint32 bytesTransferred, + E_ByteOrder byteOrder) +{ + if (! buf_) + { + capacity_ = DcmWriteCacheBufsize; + buf_ = new Uint8[capacity_]; + } + + if (owner != owner_) + { + owner_ = owner; + fieldLength_ = fieldLength; + fieldOffset_ = bytesTransferred; + byteOrder_ = byteOrder; + offset_ = 0; + numBytes_ = 0; + } +} + +OFCondition DcmWriteCache::fillBuffer(DcmElement& elem) +{ + OFCondition result = EC_Normal; + if (buf_) + { + // re-fill the buffer only if completely empty + if (! numBytes_) + { + offset_ = 0; + + // compute the number of bytes to read - either buffer size or + // the remaining number of bytes in the element, whatever is smaller + Uint32 bytesToRead = fieldLength_ - fieldOffset_; + if (bytesToRead > capacity_) bytesToRead = capacity_; + + result = elem.getPartialValue(buf_, fieldOffset_, bytesToRead, &fcache_, byteOrder_); + + if (result.good()) + { + numBytes_ = bytesToRead; + fieldOffset_ += numBytes_; + } + + } + } else result = EC_IllegalCall; + return result; +} + +Uint32 DcmWriteCache::writeBuffer(DcmOutputStream &outStream) +{ + Uint32 result = 0; + if (buf_ && numBytes_) + { + result = OFstatic_cast(Uint32, outStream.write(buf_ + offset_, numBytes_)); + + numBytes_ -= result; + offset_ += result; + } + return result; +} diff --git a/dcmdata/libsrc/dcxfer.cc b/dcmdata/libsrc/dcxfer.cc new file mode 100644 index 00000000..b7ec1b50 --- /dev/null +++ b/dcmdata/libsrc/dcxfer.cc @@ -0,0 +1,694 @@ +/* + * + * Copyright (C) 1994-2015, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Gerd Ehlers + * + * Purpose: handling of transfer syntaxes + * + */ + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ +#include "dcmtk/dcmdata/dcxfer.h" +#include "dcmtk/dcmdata/dcuid.h" + +#define INCLUDE_CSTRING +#include "dcmtk/ofstd/ofstdinc.h" + + +typedef struct +{ + const char *xferID; + const char *xferName; + E_TransferSyntax xfer; + E_ByteOrder byteOrder; + E_VRType vrType; + E_JPEGEncapsulated encapsulated; + Uint32 JPEGProcess8; + Uint32 JPEGProcess12; + OFBool lossy; + OFBool retired; + E_StreamCompression streamCompression; +} S_XferNames; + + +#define ERROR_XferName "Unknown Transfer Syntax" + + +const S_XferNames XferNames[] = +{ + { UID_LittleEndianImplicitTransferSyntax, + "Little Endian Implicit", + EXS_LittleEndianImplicit, + EBO_LittleEndian, + EVT_Implicit, + EJE_NotEncapsulated, + 0L, 0L, + OFFalse, + OFFalse, + ESC_none }, + { "", // illegal type + "Virtual Big Endian Implicit", + EXS_BigEndianImplicit, + EBO_BigEndian, + EVT_Implicit, + EJE_NotEncapsulated, + 0L, 0L, + OFFalse, + OFFalse, + ESC_none }, + { UID_LittleEndianExplicitTransferSyntax, + "Little Endian Explicit", + EXS_LittleEndianExplicit, + EBO_LittleEndian, + EVT_Explicit, + EJE_NotEncapsulated, + 0L, 0L, + OFFalse, + OFFalse, + ESC_none }, + { UID_BigEndianExplicitTransferSyntax, + "Big Endian Explicit", + EXS_BigEndianExplicit, + EBO_BigEndian, + EVT_Explicit, + EJE_NotEncapsulated, + 0L, 0L, + OFFalse, + OFTrue, // retired with Supplement 98 + ESC_none }, + { UID_JPEGProcess1TransferSyntax, + "JPEG Baseline", + EXS_JPEGProcess1, + EBO_LittleEndian, + EVT_Explicit, + EJE_Encapsulated, + 1L, 1L, + OFTrue, + OFFalse, + ESC_none }, + { UID_JPEGProcess2_4TransferSyntax, + "JPEG Extended, Process 2+4", + EXS_JPEGProcess2_4, + EBO_LittleEndian, + EVT_Explicit, + EJE_Encapsulated, + 2L ,4L, + OFTrue, + OFFalse, + ESC_none }, + { UID_JPEGProcess3_5TransferSyntax, + "JPEG Extended, Process 3+5", + EXS_JPEGProcess3_5, + EBO_LittleEndian, + EVT_Explicit, + EJE_Encapsulated, + 3L ,5L, + OFTrue, + OFTrue, + ESC_none }, + { UID_JPEGProcess6_8TransferSyntax, + "JPEG Spectral Selection, Non-hierarchical, Process 6+8", + EXS_JPEGProcess6_8, + EBO_LittleEndian, + EVT_Explicit, + EJE_Encapsulated, + 6L ,8L, + OFTrue, + OFTrue, + ESC_none }, + { UID_JPEGProcess7_9TransferSyntax, + "JPEG Spectral Selection, Non-hierarchical, Process 7+9", + EXS_JPEGProcess7_9, + EBO_LittleEndian, + EVT_Explicit, + EJE_Encapsulated, + 7L ,9L, + OFTrue, + OFTrue, + ESC_none }, + { UID_JPEGProcess10_12TransferSyntax, + "JPEG Full Progression, Non-hierarchical, Process 10+12", + EXS_JPEGProcess10_12, + EBO_LittleEndian, + EVT_Explicit, + EJE_Encapsulated, + 10L ,12L, + OFTrue, + OFTrue, + ESC_none }, + { UID_JPEGProcess11_13TransferSyntax, + "JPEG Full Progression, Non-hierarchical, Process 11+13", + EXS_JPEGProcess11_13, + EBO_LittleEndian, + EVT_Explicit, + EJE_Encapsulated, + 11L ,13L, + OFTrue, + OFTrue, + ESC_none }, + { UID_JPEGProcess14TransferSyntax, + "JPEG Lossless, Non-hierarchical, Process 14", + EXS_JPEGProcess14, + EBO_LittleEndian, + EVT_Explicit, + EJE_Encapsulated, + 14L ,14L, + OFFalse, + OFFalse, + ESC_none }, + { UID_JPEGProcess15TransferSyntax, + "JPEG Lossless, Non-hierarchical, Process 15", + EXS_JPEGProcess15, + EBO_LittleEndian, + EVT_Explicit, + EJE_Encapsulated, + 15L ,15L, + OFTrue, + OFTrue, + ESC_none }, + { UID_JPEGProcess16_18TransferSyntax, + "JPEG Extended, Hierarchical, Process 16+18", + EXS_JPEGProcess16_18, + EBO_LittleEndian, + EVT_Explicit, + EJE_Encapsulated, + 16L ,18L, + OFTrue, + OFTrue, + ESC_none }, + { UID_JPEGProcess17_19TransferSyntax, + "JPEG Extended, Hierarchical, Process 17+19", + EXS_JPEGProcess17_19, + EBO_LittleEndian, + EVT_Explicit, + EJE_Encapsulated, + 17L ,19L, + OFTrue, + OFTrue, + ESC_none }, + { UID_JPEGProcess20_22TransferSyntax, + "JPEG Spectral Selection, Hierarchical, Process 20+22", + EXS_JPEGProcess20_22, + EBO_LittleEndian, + EVT_Explicit, + EJE_Encapsulated, + 20L ,22L, + OFTrue, + OFTrue, + ESC_none }, + { UID_JPEGProcess21_23TransferSyntax, + "JPEG Spectral Selection, Hierarchical, Process 21+23", + EXS_JPEGProcess21_23, + EBO_LittleEndian, + EVT_Explicit, + EJE_Encapsulated, + 21L ,23L, + OFTrue, + OFTrue, + ESC_none }, + { UID_JPEGProcess24_26TransferSyntax, + "JPEG Full Progression, Hierarchical, Process 24+26", + EXS_JPEGProcess24_26, + EBO_LittleEndian, + EVT_Explicit, + EJE_Encapsulated, + 24L ,26L, + OFTrue, + OFTrue, + ESC_none }, + { UID_JPEGProcess25_27TransferSyntax, + "JPEG Full Progression, Hierarchical, Process 25+27", + EXS_JPEGProcess25_27, + EBO_LittleEndian, + EVT_Explicit, + EJE_Encapsulated, + 25L ,27L, + OFTrue, + OFTrue, + ESC_none }, + { UID_JPEGProcess28TransferSyntax, + "JPEG Lossless, Hierarchical, Process 28", + EXS_JPEGProcess28, + EBO_LittleEndian, + EVT_Explicit, + EJE_Encapsulated, + 28L ,28L, + OFTrue, + OFTrue, + ESC_none }, + { UID_JPEGProcess29TransferSyntax, + "JPEG Lossless, Hierarchical, Process 29", + EXS_JPEGProcess29, + EBO_LittleEndian, + EVT_Explicit, + EJE_Encapsulated, + 29L ,29L, + OFTrue, + OFTrue, + ESC_none }, + { UID_JPEGProcess14SV1TransferSyntax, + "JPEG Lossless, Non-hierarchical, 1st Order Prediction", + EXS_JPEGProcess14SV1, + EBO_LittleEndian, + EVT_Explicit, + EJE_Encapsulated, + 14L ,14L, + OFFalse, + OFFalse, + ESC_none }, + { UID_RLELosslessTransferSyntax, + "RLE Lossless", + EXS_RLELossless, + EBO_LittleEndian, + EVT_Explicit, + EJE_Encapsulated, + 0L, 0L, + OFFalse, + OFFalse, + ESC_none }, + { UID_JPEGLSLosslessTransferSyntax, + "JPEG-LS Lossless", + EXS_JPEGLSLossless, + EBO_LittleEndian, + EVT_Explicit, + EJE_Encapsulated, + 0L, 0L, + OFFalse, + OFFalse, + ESC_none }, + { UID_JPEGLSLossyTransferSyntax, + "JPEG-LS Lossy (Near-lossless)", + EXS_JPEGLSLossy, + EBO_LittleEndian, + EVT_Explicit, + EJE_Encapsulated, + 0L, 0L, + OFTrue, + OFFalse, + ESC_none }, + { UID_DeflatedExplicitVRLittleEndianTransferSyntax, + "Deflated Explicit VR Little Endian", + EXS_DeflatedLittleEndianExplicit, + EBO_LittleEndian, + EVT_Explicit, + EJE_NotEncapsulated, + 0L, 0L, + OFFalse, + OFFalse, +#ifdef WITH_ZLIB + ESC_zlib +#else + ESC_unsupported +#endif + }, + { UID_JPEG2000LosslessOnlyTransferSyntax, + "JPEG 2000 (Lossless only)", + EXS_JPEG2000LosslessOnly, + EBO_LittleEndian, + EVT_Explicit, + EJE_Encapsulated, + 0L, 0L, + OFFalse, + OFFalse, + ESC_none }, + { UID_JPEG2000TransferSyntax, + "JPEG 2000 (Lossless or Lossy)", + EXS_JPEG2000, + EBO_LittleEndian, + EVT_Explicit, + EJE_Encapsulated, + 0L, 0L, + OFTrue, + OFFalse, + ESC_none }, + { UID_MPEG2MainProfileAtMainLevelTransferSyntax, + "MPEG2 Main Profile @ Main Level", + EXS_MPEG2MainProfileAtMainLevel, + EBO_LittleEndian, + EVT_Explicit, + EJE_Encapsulated, + 0L, 0L, + OFTrue, + OFFalse, + ESC_none }, + { UID_MPEG2MainProfileAtHighLevelTransferSyntax, + "MPEG2 Main Profile @ High Level", + EXS_MPEG2MainProfileAtHighLevel, + EBO_LittleEndian, + EVT_Explicit, + EJE_Encapsulated, + 0L, 0L, + OFTrue, + OFFalse, + ESC_none }, + { UID_MPEG4HighProfileLevel4_1TransferSyntax, + "MPEG-4 AVC/H.264 High Profile / Level 4.1", + EXS_MPEG4HighProfileLevel4_1, + EBO_LittleEndian, + EVT_Explicit, + EJE_Encapsulated, + 0L, 0L, + OFTrue, + OFFalse, + ESC_none }, + { UID_MPEG4BDcompatibleHighProfileLevel4_1TransferSyntax, + "MPEG-4 AVC/H.264 BD-compatible High Profile / Level 4.1", + EXS_MPEG4BDcompatibleHighProfileLevel4_1, + EBO_LittleEndian, + EVT_Explicit, + EJE_Encapsulated, + 0L, 0L, + OFTrue, + OFFalse, + ESC_none }, + { UID_MPEG4HighProfileLevel4_2_For2DVideoTransferSyntax, + "MPEG-4 AVC/H.264 High Profile / Level 4.2 For 2D Video", + EXS_MPEG4HighProfileLevel4_2_For2DVideo, + EBO_LittleEndian, + EVT_Explicit, + EJE_Encapsulated, + 0L, 0L, + OFTrue, + OFFalse, + ESC_none }, + { UID_MPEG4HighProfileLevel4_2_For3DVideoTransferSyntax, + "MPEG-4 AVC/H.264 High Profile / Level 4.2 For 3D Video", + EXS_MPEG4HighProfileLevel4_2_For3DVideo, + EBO_LittleEndian, + EVT_Explicit, + EJE_Encapsulated, + 0L, 0L, + OFTrue, + OFFalse, + ESC_none }, + { UID_MPEG4StereoHighProfileLevel4_2TransferSyntax, + "MPEG-4 AVC/H.264 Stereo High Profile / Level 4.2", + EXS_MPEG4StereoHighProfileLevel4_2, + EBO_LittleEndian, + EVT_Explicit, + EJE_Encapsulated, + 0L, 0L, + OFTrue, + OFFalse, + ESC_none }, + { UID_JPEG2000Part2MulticomponentImageCompressionLosslessOnlyTransferSyntax, + "JPEG 2000 Part 2 Multicomponent Image Compression (Lossless only)", + EXS_JPEG2000MulticomponentLosslessOnly, + EBO_LittleEndian, + EVT_Explicit, + EJE_Encapsulated, + 0L, 0L, + OFFalse, + OFFalse, + ESC_none }, + { UID_JPEG2000Part2MulticomponentImageCompressionTransferSyntax, + "JPEG 2000 Part 2 Multicomponent Image Compression (Lossless or Lossy)", + EXS_JPEG2000Multicomponent, + EBO_LittleEndian, + EVT_Explicit, + EJE_Encapsulated, + 0L, 0L, + OFTrue, + OFFalse, + ESC_none }, + { UID_JPIPReferencedTransferSyntax, + "JPIP Referenced", + EXS_JPIPReferenced, + EBO_LittleEndian, + EVT_Explicit, + EJE_NotEncapsulated, // in fact, pixel data shall be referenced via (0028,7FE0) Pixel Data Provider URL + 0L, 0L, + OFTrue, // really lossy? + OFFalse, + ESC_none }, + { UID_JPIPReferencedDeflateTransferSyntax, + "JPIP Referenced Deflate", + EXS_JPIPReferencedDeflate, + EBO_LittleEndian, + EVT_Explicit, + EJE_NotEncapsulated, // in fact, pixel data shall be referenced via (0028,7FE0) Pixel Data Provider URL + 0L, 0L, + OFTrue, // really lossy? + OFFalse, +#ifdef WITH_ZLIB + ESC_zlib +#else + ESC_unsupported +#endif + } + + // enter further transfer syntaxes here ... +}; + +const int DIM_OF_XferNames = OFstatic_cast(int, sizeof(XferNames) / sizeof(S_XferNames)); + + +// ******************************** + + +DcmXfer::DcmXfer(E_TransferSyntax xfer) + : xferID(""), + xferName(ERROR_XferName), + xferSyn(EXS_Unknown), + byteOrder(EBO_unknown), + vrType(EVT_Implicit), + encapsulated(EJE_NotEncapsulated), + JPEGProcess8(0L), + JPEGProcess12(0L), + lossy(OFFalse), + retired(OFFalse), + streamCompression(ESC_none) +{ + int i = 0; + while ((i < DIM_OF_XferNames) && XferNames[i].xfer != xfer) + i++; + if ((i < DIM_OF_XferNames) && (XferNames[i].xfer == xfer)) + { + xferSyn = XferNames[i].xfer; + xferID = XferNames[i].xferID; + xferName = XferNames[i].xferName; + byteOrder = XferNames[i].byteOrder; + vrType = XferNames[i].vrType; + encapsulated = XferNames[i].encapsulated; + JPEGProcess8 = XferNames[i].JPEGProcess8; + JPEGProcess12 = XferNames[i].JPEGProcess12; + lossy = XferNames[i].lossy; + retired = XferNames[i].retired; + streamCompression = XferNames[i].streamCompression; + } +} + + +// ******************************** + + +DcmXfer::DcmXfer(const char* xferName_xferID) + : xferID(""), + xferName(ERROR_XferName), + xferSyn(EXS_Unknown), + byteOrder(EBO_unknown), + vrType(EVT_Implicit), + encapsulated(EJE_NotEncapsulated), + JPEGProcess8(0L), + JPEGProcess12(0L), + lossy(OFFalse), + retired(OFFalse), + streamCompression(ESC_none) +{ + const char* xname = xferName_xferID; + if (xname != NULL) + { + int i = 0; + while ((i < DIM_OF_XferNames) && (strcmp(XferNames[i].xferID, xname) != 0)) + i++; + if ((i < DIM_OF_XferNames) && (strcmp(XferNames[i].xferID, xname) == 0)) + { + xferSyn = XferNames[i].xfer; + xferID = XferNames[i].xferID; + xferName = XferNames[i].xferName; + byteOrder = XferNames[i].byteOrder; + vrType = XferNames[i].vrType; + encapsulated = XferNames[i].encapsulated; + JPEGProcess8 = XferNames[i].JPEGProcess8; + JPEGProcess12 = XferNames[i].JPEGProcess12; + lossy = XferNames[i].lossy; + retired = XferNames[i].retired; + streamCompression = XferNames[i].streamCompression; + } + else + { + i = 0; + while ((i < DIM_OF_XferNames) && (strcmp(XferNames[i].xferName, xname) != 0)) + i++; + if ((i < DIM_OF_XferNames) && (strcmp(XferNames[i].xferName, xname) == 0)) + { + xferSyn = XferNames[i].xfer; + xferID = XferNames[i].xferID; + xferName = XferNames[i].xferName; + byteOrder = XferNames[i].byteOrder; + vrType = XferNames[i].vrType; + encapsulated = XferNames[i].encapsulated; + JPEGProcess8 = XferNames[i].JPEGProcess8; + JPEGProcess12 = XferNames[i].JPEGProcess12; + lossy = XferNames[i].lossy; + retired = XferNames[i].retired; + streamCompression = XferNames[i].streamCompression; + } + } + } +} + + +// ******************************** + + +DcmXfer::DcmXfer(const DcmXfer &newXfer) + : xferID(newXfer.xferID), + xferName(newXfer.xferName), + xferSyn(newXfer.xferSyn), + byteOrder(newXfer.byteOrder), + vrType(newXfer.vrType), + encapsulated(newXfer.encapsulated), + JPEGProcess8(newXfer.JPEGProcess8), + JPEGProcess12(newXfer.JPEGProcess12), + lossy(newXfer.lossy), + retired(newXfer.retired), + streamCompression(newXfer.streamCompression) +{ +} + + +// ******************************** + + +DcmXfer::~DcmXfer() +{ +} + + +// ******************************** + + +DcmXfer &DcmXfer::operator=(const E_TransferSyntax xfer) +{ + int i = 0; + while ((i < DIM_OF_XferNames) && (XferNames[i].xfer != xfer)) + i++; + if ((i < DIM_OF_XferNames) && (XferNames[i].xfer == xfer)) + { + xferSyn = XferNames[i].xfer; + xferID = XferNames[i].xferID; + xferName = XferNames[i].xferName; + byteOrder = XferNames[i].byteOrder; + vrType = XferNames[i].vrType; + encapsulated = XferNames[i].encapsulated; + JPEGProcess8 = XferNames[i].JPEGProcess8; + JPEGProcess12 = XferNames[i].JPEGProcess12; + lossy = XferNames[i].lossy; + retired = XferNames[i].retired; + streamCompression = XferNames[i].streamCompression; + } else { + xferSyn = EXS_Unknown; + xferID = ""; + xferName = ERROR_XferName; + byteOrder = EBO_unknown; + vrType = EVT_Implicit; + encapsulated = EJE_NotEncapsulated; + JPEGProcess8 = 0L; + JPEGProcess12 = 0L; + lossy = OFFalse; + retired = OFFalse; + streamCompression = ESC_none; + } + return *this; +} + + +// ******************************** + + +DcmXfer &DcmXfer::operator=(const DcmXfer &newXfer) +{ + if (this != &newXfer) + { + xferSyn = newXfer.xferSyn; + xferID = newXfer.xferID; + xferName = newXfer.xferName; + byteOrder = newXfer.byteOrder; + vrType = newXfer.vrType; + encapsulated = newXfer.encapsulated; + JPEGProcess8 = newXfer.JPEGProcess8; + JPEGProcess12 = newXfer.JPEGProcess12; + lossy = newXfer.lossy; + retired = newXfer.retired; + streamCompression = newXfer.streamCompression; + } + return *this; +} + + +// ******************************** + +Uint32 DcmXfer::sizeofTagHeader(DcmEVR evr) const +{ + Uint32 len = 0; + if (isExplicitVR()) + { + // some VRs have an extended format + DcmVR vr(evr); + if (vr.usesExtendedLengthEncoding()) { + len = 12; // for Tag, Length, VR and reserved + } else { + len = 8; // for Tag, Length and VR + } + } else { + // all implicit VRs have the same format + len = 8; // for Tag and Length + } + return len; +} + +// ******************************** + +static E_ByteOrder FindMachineTransferSyntax() +{ + E_ByteOrder localByteOrderFlag; + union + { + Uint32 ul; + char uc[4]; + } tl; + + union + { + Uint16 us; + char uc[2]; + } ts; + + tl.ul = 1; + ts.us = 1; + + if (tl.uc[0] == 1 && !(tl.uc[1] | tl.uc[2] | tl.uc[3]) && ts.uc[0] == 1 && !(ts.uc[1])) + localByteOrderFlag = EBO_LittleEndian; + else if (tl.uc[3] == 1 && !(tl.uc[0] | tl.uc[1] | tl.uc[2]) && ts.uc[1] == 1 && !(ts.uc[0])) + localByteOrderFlag = EBO_BigEndian; + else + localByteOrderFlag = EBO_unknown; + + return localByteOrderFlag; +} + +// global constant: local byte order (little or big endian) +const E_ByteOrder gLocalByteOrder = FindMachineTransferSyntax(); diff --git a/dcmdata/libsrc/mkdeftag.cc b/dcmdata/libsrc/mkdeftag.cc new file mode 100644 index 00000000..fe90c98b --- /dev/null +++ b/dcmdata/libsrc/mkdeftag.cc @@ -0,0 +1,275 @@ +/* + * + * Copyright (C) 1994-2015, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Andrew Hewett + * + * Purpose: Generate a C++ header defining symbolic names for DICOM Tags. + * + */ + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#ifdef HAVE_WINDOWS_H +#include /* this includes either winsock.h or winsock2.h */ +#elif defined(HAVE_WINSOCK_H) +#include /* include winsock.h directly i.e. on MacOS */ +#endif + +#ifdef HAVE_GUSI_H +#include +#endif + +#include "dcmtk/dcmdata/dcdict.h" +#include "dcmtk/dcmdata/cmdlnarg.h" +#include "dcmtk/ofstd/ofstring.h" +#include "dcmtk/ofstd/ofdatime.h" +#include "dcmtk/ofstd/ofstd.h" +#include "dcmtk/dcmdata/dcdicent.h" + +static char* +convertToIdentifier(char* s) +{ + if (s == NULL) { + return s; + } + size_t len = strlen(s); + size_t i=0; + unsigned char c; + + for (i=0; igetTagName() == NULL) + return; + + strcpy(buf, e->getTagName()); + + convertToIdentifier(buf); + + tagPrefix = "#define DCM_"; + fputs(tagPrefix, fout); /* write out prefix */ + fputs(buf, fout); /* write out rest of name */ + + const OFintptr_t n = 48 - (strlen(tagPrefix) + strlen(buf)); + for (OFintptr_t i=0; igetGroup(), e->getElement()); + + if (e->isRepeating()) { + fprintf(fout, " /* (0x%04x", e->getGroup()); + if (e->isRepeatingGroup()) { + if (e->getGroupRangeRestriction() != DcmDictRange_Even) { + fprintf(fout, "-%c", + rangeRestriction2char(e->getGroupRangeRestriction())); + } + fprintf(fout, "-0x%04x", e->getUpperGroup()); + } + fprintf(fout, ",0x%04x", e->getElement()); + if (e->isRepeatingElement()) { + if (e->getElementRangeRestriction() != DcmDictRange_Even) { + fprintf(fout, "-%c", + rangeRestriction2char(e->getElementRangeRestriction())); + } + fprintf(fout, "-0x%04x", e->getUpperElement()); + } + fprintf(fout, ") */"); + } + fputs("\n", fout); +} + +int main(int argc, char* argv[]) +{ + const char* progname = "mkdeftag"; + const char* filename = NULL; + DcmDictEntry* e = NULL; + int i = 0; + FILE* fout = NULL; + +#ifdef HAVE_GUSI_H + GUSISetup(GUSIwithSIOUXSockets); + GUSISetup(GUSIwithInternetSockets); +#endif + +#ifdef HAVE_WINSOCK_H + WSAData winSockData; + /* we need at least version 1.1 */ + WORD winSockVersionNeeded = MAKEWORD( 1, 1 ); + WSAStartup(winSockVersionNeeded, &winSockData); +#endif + + prepareCmdLineArgs(argc, argv, "mkdeftag"); + + DcmDataDictionary& globalDataDict = dcmDataDict.wrlock(); + + /* clear out global data dictionary */ + globalDataDict.clear(); + + progname = argv[0]; + + if (argc >= 3 && 0 == strcmp(argv[1], "-o")) { + filename = argv[2]; + argv += 2; + argc -= 2; + } + + for (i=1; i 1) { + fprintf(fout, "** From: %s\n", argv[1]); + for (i=2; igetPrivateCreator() == NULL) // exclude private tags + { + e = new DcmDictEntry(*(*iter)); + list.insertAndReplace(e); + } + } + + /* generate the entries themselves */ + fputs("\n/*\n", fout); + fputs("** Fixed Tags in ascending (gggg,eeee) order.\n", fout); + fprintf(fout, "** Number of entries: %lu\n", OFstatic_cast(unsigned long, list.size())); + fputs("** Tags with a repeating component (repeating tags) are listed later.\n", fout); + fputs("*/\n", fout); + + /* output the list contents */ + DcmDictEntryListIterator listIter(list.begin()); + DcmDictEntryListIterator listLast(list.end()); + for (; listIter != listLast; ++listIter) + { + printDefined(fout, *listIter); + } + + // count non-private repeating tags in dictionary + int repCount = 0; + DcmDictEntryListIterator repIter(globalDataDict.repeatingBegin()); + DcmDictEntryListIterator repLast(globalDataDict.repeatingEnd()); + for (; repIter != repLast; ++repIter) + { + if ((*repIter)->getPrivateCreator() == NULL) ++repCount; + } + + fputs("\n/*\n", fout); + fputs("** Tags where the group/element can vary (repeating tags).\n", + fout); + fprintf(fout, "** Number of entries: %d\n", repCount); + fputs("*/\n", fout); + + repIter = globalDataDict.repeatingBegin(); + for (; repIter != repLast; ++repIter) + { + if ((*repIter)->getPrivateCreator() == NULL) // exclude private tags + { + printDefined(fout, *repIter); + } + } + fputs("\n#endif /* !DCDEFTAG_H */\n", fout); + + dcmDataDict.unlock(); + return 0; +} + +void +DcmDataDictionary::loadBuiltinDictionary() +{ + /* + * * Empty Stub. + ** + ** Used to keep compiler happy when building mkdictbi since it links itself + ** against dcdict.cc. + */ +} diff --git a/dcmdata/libsrc/mkdictbi.cc b/dcmdata/libsrc/mkdictbi.cc new file mode 100644 index 00000000..16af4a01 --- /dev/null +++ b/dcmdata/libsrc/mkdictbi.cc @@ -0,0 +1,297 @@ +/* + * + * Copyright (C) 1994-2015, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Andrew Hewett + * + * Purpose: + * Generate a builtin data dictionary which can be compiled into + * the dcmdata library. + * + */ + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + + +#ifdef HAVE_WINDOWS_H +#include /* this includes either winsock.h or winsock2.h */ +#elif defined(HAVE_WINSOCK_H) +#include /* include winsock.h directly i.e. on MacOS */ +#endif + +#ifdef HAVE_GUSI_H +#include +#endif + +#include "dcmtk/dcmdata/dcdict.h" +#include "dcmtk/dcmdata/cmdlnarg.h" +#include "dcmtk/ofstd/ofstring.h" +#include "dcmtk/ofstd/ofdatime.h" +#include "dcmtk/ofstd/ofstd.h" +#include "dcmtk/dcmdata/dcdicent.h" + +#define PRIVATE_TAGS_IFNAME "ENABLE_PRIVATE_TAGS" + +void +DcmDataDictionary::loadBuiltinDictionary() +{ + /* + * * Empty Stub. + ** + ** Used to keep compiler happy when building mkdictbi since it links itself + ** against dcdict.cc. + */ +} + +static const char* +rr2s(DcmDictRangeRestriction rr) +{ + const char* s; + switch (rr) { + case DcmDictRange_Unspecified: + s = "DcmDictRange_Unspecified"; + break; + case DcmDictRange_Odd: + s = "DcmDictRange_Odd"; + break; + case DcmDictRange_Even: + s = "DcmDictRange_Even"; + break; + default: + s = "DcmDictRange_GENERATOR_ERROR"; + break; + } + return s; +} + +static void +printSimpleEntry(FILE* fout, const DcmDictEntry* e, OFBool& isFirst, OFBool& isPrivate) +{ + + const char *c = e->getPrivateCreator(); + + if (c && !isPrivate) + { + fprintf(fout, "#ifdef %s\n", PRIVATE_TAGS_IFNAME); + isPrivate = OFTrue; + } + else if (isPrivate && !c) + { + fprintf(fout, "#endif\n"); + isPrivate = OFFalse; + } + + if (isFirst) + { + fprintf(fout, " "); + isFirst = OFFalse; + } else fprintf(fout, " , "); + + fprintf(fout, "{ 0x%04x, 0x%04x, 0x%04x, 0x%04x,\n", + e->getGroup(), e->getElement(), + e->getUpperGroup(), e->getUpperElement()); + fprintf(fout, " EVR_%s, \"%s\", %d, %d, \"%s\",\n", + e->getVR().getVRName(), + e->getTagName(), + e->getVMMin(), e->getVMMax(), + OFSTRING_GUARD(e->getStandardVersion())); + fprintf(fout, " %s, %s,\n", rr2s(e->getGroupRangeRestriction()), + rr2s(e->getElementRangeRestriction())); + + if (c) + fprintf(fout, " \"%s\" }\n", c); + else + fprintf(fout, " NULL }\n"); +} + +int +main(int argc, char* argv[]) +{ + char* progname; + const char* filename = NULL; + FILE* fout = NULL; + DcmDictEntry* e = NULL; + +#ifdef HAVE_GUSI_H + GUSISetup(GUSIwithSIOUXSockets); + GUSISetup(GUSIwithInternetSockets); +#endif + +#ifdef HAVE_WINSOCK_H + WSAData winSockData; + /* we need at least version 1.1 */ + WORD winSockVersionNeeded = MAKEWORD( 1, 1 ); + WSAStartup(winSockVersionNeeded, &winSockData); +#endif + + prepareCmdLineArgs(argc, argv, "mkdictbi"); + + DcmDataDictionary& globalDataDict = dcmDataDict.wrlock(); + + /* clear out any preloaded dictionary */ + globalDataDict.clear(); + + progname = argv[0]; + + if (argc >= 3 && 0 == strcmp(argv[1], "-o")) { + filename = argv[2]; + argv += 2; + argc -= 2; + } + + int i; + for (i=1; i 1) { + fprintf(fout, "** From: %s\n", argv[1]); + for (i=2; igroup, b->element,\n"); + fprintf(fout, " b->upperGroup, b->upperElement, b->evr,\n"); + fprintf(fout, " b->tagName, b->vmMin, b->vmMax,\n"); + fprintf(fout, " b->standardVersion, OFFalse, b->privateCreator);\n"); + fprintf(fout, " e->setGroupRangeRestriction(b->groupRestriction);\n"); + fprintf(fout, " e->setElementRangeRestriction(b->elementRestriction);\n"); + fprintf(fout, " addEntry(e);\n"); + fprintf(fout, " }\n"); + fprintf(fout, "}\n"); + fprintf(fout, "\n"); + fprintf(fout, "\n"); + fprintf(fout, "#else // WITH_BUILTIN_DICTIONARY\n"); + fprintf(fout, "void\n"); + fprintf(fout, "DcmDataDictionary::loadBuiltinDictionary()\n"); + fprintf(fout, "{\n"); + fprintf(fout, "/*\n"); + fprintf(fout, " ** Empty Stub.\n"); + fprintf(fout, " **\n"); + fprintf(fout, " ** We don't want a populated built-in data dictionary. In order to enable it,\n"); + fprintf(fout, " ** define WITH_BUILTIN_DICTIONARY. To re-create the builtin dictionary from\n"); + fprintf(fout, " ** a textfile like dicom.dic, use dcmdata/libsrc/mkdictbi.\n"); + fprintf(fout, "*/\n"); + fprintf(fout, "}\n"); + fprintf(fout, "\n"); + fprintf(fout, "#endif // WITH_BUILTIN_DICTIONARY\n"); + fprintf(fout, "\n"); + dcmDataDict.unlock(); + if (filename) + { + fclose(fout); + } + return 0; +} diff --git a/dcmdata/libsrc/vrscan.cc b/dcmdata/libsrc/vrscan.cc new file mode 100644 index 00000000..ebb4bc29 --- /dev/null +++ b/dcmdata/libsrc/vrscan.cc @@ -0,0 +1,91 @@ +/* + * + * Copyright (C) 2010, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Uli Schlachter + * + * Purpose: Interface to the VR scanner. + * + */ + + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/dcmdata/vrscan.h" +#include "dcmtk/ofstd/ofbmanip.h" +#include "dcmtk/ofstd/ofstd.h" /* For OFString::strerror() */ +#include "dcmtk/dcmdata/dctypes.h" /* For DCMDATA_WARN() */ + +BEGIN_EXTERN_C +#include "vrscani.h" +#include "vrscanl.h" +END_EXTERN_C + +char* vrscan::makeBuffer(const OFString& vr, const OFString& value, size_t& size) +{ + char *buffer, *pos; + + // Allocate the needed buffer + size = vr.length() + value.length() + 2; + pos = buffer = new char[size]; + + // Fill it with the input + OFBitmanipTemplate::copyMem(vr.data(), pos, vr.size()); + pos += vr.size(); + + OFBitmanipTemplate::copyMem(value.data(), pos, value.size()); + pos += value.size(); + + // yy_scan_buffer() requires this + pos[0] = pos[1] = '\0'; + + return buffer; +} + +int vrscan::scan(const OFString& vr, const OFString& value) +{ + struct vrscan_error error; + yyscan_t scanner; + int result; + + if (yylex_init(&scanner)) + { + char buf[256]; + DCMDATA_WARN("Error while setting up lexer: " + << OFStandard::strerror(errno, buf, sizeof(buf))); + return 16; + } + + size_t bufSize; + char *buf = makeBuffer(vr, value, bufSize); + error.error_msg = "(Unknown error)"; + yyset_extra(&error, scanner); + + if (setjmp(error.setjmp_buffer)) + { + DCMDATA_WARN("Fatal error in lexer: " << error.error_msg); + result = 16 /* UNKNOWN */; + } else { + yy_scan_buffer(buf, bufSize, scanner); + + result = yylex(scanner); + if (yylex(scanner)) + result = 16 /* UNKNOWN */; + } + + yylex_destroy(scanner); + delete[] buf; + + return result; +} diff --git a/dcmdata/libsrc/vrscani.h b/dcmdata/libsrc/vrscani.h new file mode 100644 index 00000000..ec4f2a0a --- /dev/null +++ b/dcmdata/libsrc/vrscani.h @@ -0,0 +1,44 @@ +/* + * + * Copyright (C) 2010, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Uli Schlachter + * + * Purpose: Internal header for vrscanl.c and vrscan.cc + * + */ + +#ifndef VRSCANI_H +#define VRSCANI_H + +/* This needs its own header because both vrscanl.c and vrscan.cc need it. */ + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ +#include + +struct vrscan_error { + jmp_buf setjmp_buffer; + const char *error_msg; +}; + +#define YY_EXTRA_TYPE struct vrscan_error * +#define YY_FATAL_ERROR(msg) do { \ + yyget_extra(yyscanner)->error_msg = msg; \ + longjmp(yyget_extra(yyscanner)->setjmp_buffer, 1); \ +} while (0); + +/* Don't try to include unistd.h which doesn't exist on windows */ +#define YY_NO_UNISTD_H + +#endif /* VRSCANI_H */ diff --git a/dcmdata/libsrc/vrscanl.c b/dcmdata/libsrc/vrscanl.c new file mode 100644 index 00000000..9642f578 --- /dev/null +++ b/dcmdata/libsrc/vrscanl.c @@ -0,0 +1,6442 @@ +#line 2 "vrscanl.c" + +#line 4 "vrscanl.c" + +#define YY_INT_ALIGNED short int + +/* A lexical scanner generated by flex */ + +#define FLEX_SCANNER +#define YY_FLEX_MAJOR_VERSION 2 +#define YY_FLEX_MINOR_VERSION 5 +#define YY_FLEX_SUBMINOR_VERSION 35 +#if YY_FLEX_SUBMINOR_VERSION > 0 +#define FLEX_BETA +#endif + +/* First, we deal with platform-specific or compiler-specific issues. */ + +/* begin standard C headers. */ +#include +#include +#include +#include + +/* end standard C headers. */ + +/* flex integer type definitions */ + +#ifndef FLEXINT_H +#define FLEXINT_H + +/* C99 systems have . Non-C99 systems may or may not. */ + +#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L + +/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h, + * if you want the limit (max/min) macros for int types. + */ +#ifndef __STDC_LIMIT_MACROS +#define __STDC_LIMIT_MACROS 1 +#endif + +#include +typedef int8_t flex_int8_t; +typedef uint8_t flex_uint8_t; +typedef int16_t flex_int16_t; +typedef uint16_t flex_uint16_t; +typedef int32_t flex_int32_t; +typedef uint32_t flex_uint32_t; +#else +typedef signed char flex_int8_t; +typedef short int flex_int16_t; +typedef int flex_int32_t; +typedef unsigned char flex_uint8_t; +typedef unsigned short int flex_uint16_t; +typedef unsigned int flex_uint32_t; + +/* Limits of integral types. */ +#ifndef INT8_MIN +#define INT8_MIN (-128) +#endif +#ifndef INT16_MIN +#define INT16_MIN (-32767-1) +#endif +#ifndef INT32_MIN +#define INT32_MIN (-2147483647-1) +#endif +#ifndef INT8_MAX +#define INT8_MAX (127) +#endif +#ifndef INT16_MAX +#define INT16_MAX (32767) +#endif +#ifndef INT32_MAX +#define INT32_MAX (2147483647) +#endif +#ifndef UINT8_MAX +#define UINT8_MAX (255U) +#endif +#ifndef UINT16_MAX +#define UINT16_MAX (65535U) +#endif +#ifndef UINT32_MAX +#define UINT32_MAX (4294967295U) +#endif + +#endif /* ! C99 */ + +#endif /* ! FLEXINT_H */ + +#ifdef __cplusplus + +/* The "const" storage-class-modifier is valid. */ +#define YY_USE_CONST + +#else /* ! __cplusplus */ + +/* C99 requires __STDC__ to be defined as 1. */ +#if defined (__STDC__) + +#define YY_USE_CONST + +#endif /* defined (__STDC__) */ +#endif /* ! __cplusplus */ + +#ifdef YY_USE_CONST +#define yyconst const +#else +#define yyconst +#endif + +/* Returned upon end-of-file. */ +#define YY_NULL 0 + +/* Promotes a possibly negative, possibly signed char to an unsigned + * integer for use as an array index. If the signed char is negative, + * we want to instead treat it as an 8-bit unsigned char, hence the + * double cast. + */ +#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) + +/* An opaque pointer. */ +#ifndef YY_TYPEDEF_YY_SCANNER_T +#define YY_TYPEDEF_YY_SCANNER_T +typedef void* yyscan_t; +#endif + +/* For convenience, these vars (plus the bison vars far below) + are macros in the reentrant scanner. */ +#define yyin yyg->yyin_r +#define yyout yyg->yyout_r +#define yyextra yyg->yyextra_r +#define yyleng yyg->yyleng_r +#define yytext yyg->yytext_r +#define yylineno (YY_CURRENT_BUFFER_LVALUE->yy_bs_lineno) +#define yycolumn (YY_CURRENT_BUFFER_LVALUE->yy_bs_column) +#define yy_flex_debug yyg->yy_flex_debug_r + +/* Enter a start condition. This macro really ought to take a parameter, + * but we do it the disgusting crufty way forced on us by the ()-less + * definition of BEGIN. + */ +#define BEGIN yyg->yy_start = 1 + 2 * + +/* Translate the current start state into a value that can be later handed + * to BEGIN to return to the state. The YYSTATE alias is for lex + * compatibility. + */ +#define YY_START ((yyg->yy_start - 1) / 2) +#define YYSTATE YY_START + +/* Action number for EOF rule of a given start state. */ +#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) + +/* Special action meaning "start processing a new file". */ +#define YY_NEW_FILE yyrestart(yyin ,yyscanner ) + +#define YY_END_OF_BUFFER_CHAR 0 + +/* Size of default input buffer. */ +#ifndef YY_BUF_SIZE +#ifdef __ia64__ +/* On IA-64, the buffer size is 16k, not 8k. + * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case. + * Ditto for the __ia64__ case accordingly. + */ +#define YY_BUF_SIZE 32768 +#else +#define YY_BUF_SIZE 16384 +#endif /* __ia64__ */ +#endif + +/* The state buf must be large enough to hold one state per character in the main buffer. + */ +#define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type)) + +#ifndef YY_TYPEDEF_YY_BUFFER_STATE +#define YY_TYPEDEF_YY_BUFFER_STATE +typedef struct yy_buffer_state *YY_BUFFER_STATE; +#endif + +#define EOB_ACT_CONTINUE_SCAN 0 +#define EOB_ACT_END_OF_FILE 1 +#define EOB_ACT_LAST_MATCH 2 + + #define YY_LESS_LINENO(n) + +/* Return all but the first "n" matched characters back to the input stream. */ +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + int yyless_macro_arg = (n); \ + YY_LESS_LINENO(yyless_macro_arg);\ + *yy_cp = yyg->yy_hold_char; \ + YY_RESTORE_YY_MORE_OFFSET \ + yyg->yy_c_buf_p = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \ + YY_DO_BEFORE_ACTION; /* set up yytext again */ \ + } \ + while ( 0 ) + +#define unput(c) yyunput( c, yyg->yytext_ptr , yyscanner ) + +#ifndef YY_TYPEDEF_YY_SIZE_T +#define YY_TYPEDEF_YY_SIZE_T +typedef size_t yy_size_t; +#endif + +#ifndef YY_STRUCT_YY_BUFFER_STATE +#define YY_STRUCT_YY_BUFFER_STATE +struct yy_buffer_state + { + FILE *yy_input_file; + + char *yy_ch_buf; /* input buffer */ + char *yy_buf_pos; /* current position in input buffer */ + + /* Size of input buffer in bytes, not including room for EOB + * characters. + */ + yy_size_t yy_buf_size; + + /* Number of characters read into yy_ch_buf, not including EOB + * characters. + */ + int yy_n_chars; + + /* Whether we "own" the buffer - i.e., we know we created it, + * and can realloc() it to grow it, and should free() it to + * delete it. + */ + int yy_is_our_buffer; + + /* Whether this is an "interactive" input source; if so, and + * if we're using stdio for input, then we want to use getc() + * instead of fread(), to make sure we stop fetching input after + * each newline. + */ + int yy_is_interactive; + + /* Whether we're considered to be at the beginning of a line. + * If so, '^' rules will be active on the next match, otherwise + * not. + */ + int yy_at_bol; + + int yy_bs_lineno; /**< The line count. */ + int yy_bs_column; /**< The column count. */ + + /* Whether to try to fill the input buffer when we reach the + * end of it. + */ + int yy_fill_buffer; + + int yy_buffer_status; + +#define YY_BUFFER_NEW 0 +#define YY_BUFFER_NORMAL 1 + /* When an EOF's been seen but there's still some text to process + * then we mark the buffer as YY_EOF_PENDING, to indicate that we + * shouldn't try reading from the input source any more. We might + * still have a bunch of tokens to match, though, because of + * possible backing-up. + * + * When we actually see the EOF, we change the status to "new" + * (via yyrestart()), so that the user can continue scanning by + * just pointing yyin at a new input file. + */ +#define YY_BUFFER_EOF_PENDING 2 + + }; +#endif /* !YY_STRUCT_YY_BUFFER_STATE */ + +/* We provide macros for accessing buffer states in case in the + * future we want to put the buffer states in a more general + * "scanner state". + * + * Returns the top of the stack, or NULL. + */ +#define YY_CURRENT_BUFFER ( yyg->yy_buffer_stack \ + ? yyg->yy_buffer_stack[yyg->yy_buffer_stack_top] \ + : NULL) + +/* Same as previous macro, but useful when we know that the buffer stack is not + * NULL or when we need an lvalue. For internal use only. + */ +#define YY_CURRENT_BUFFER_LVALUE yyg->yy_buffer_stack[yyg->yy_buffer_stack_top] + +void yyrestart (FILE *input_file ,yyscan_t yyscanner ); +void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner ); +YY_BUFFER_STATE yy_create_buffer (FILE *file,int size ,yyscan_t yyscanner ); +void yy_delete_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner ); +void yy_flush_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner ); +void yypush_buffer_state (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner ); +void yypop_buffer_state (yyscan_t yyscanner ); + +static void yyensure_buffer_stack (yyscan_t yyscanner ); +static void yy_load_buffer_state (yyscan_t yyscanner ); +static void yy_init_buffer (YY_BUFFER_STATE b,FILE *file ,yyscan_t yyscanner ); + +#define YY_FLUSH_BUFFER yy_flush_buffer(YY_CURRENT_BUFFER ,yyscanner) + +YY_BUFFER_STATE yy_scan_buffer (char *base,yy_size_t size ,yyscan_t yyscanner ); +YY_BUFFER_STATE yy_scan_string (yyconst char *yy_str ,yyscan_t yyscanner ); +YY_BUFFER_STATE yy_scan_bytes (yyconst char *bytes,int len ,yyscan_t yyscanner ); + +void *yyalloc (yy_size_t ,yyscan_t yyscanner ); +void *yyrealloc (void *,yy_size_t ,yyscan_t yyscanner ); +void yyfree (void * ,yyscan_t yyscanner ); + +#define yy_new_buffer yy_create_buffer + +#define yy_set_interactive(is_interactive) \ + { \ + if ( ! YY_CURRENT_BUFFER ){ \ + yyensure_buffer_stack (yyscanner); \ + YY_CURRENT_BUFFER_LVALUE = \ + yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \ + } \ + YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \ + } + +#define yy_set_bol(at_bol) \ + { \ + if ( ! YY_CURRENT_BUFFER ){\ + yyensure_buffer_stack (yyscanner); \ + YY_CURRENT_BUFFER_LVALUE = \ + yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \ + } \ + YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \ + } + +#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol) + +/* Begin user sect3 */ + +#define yywrap(n) 1 +#define YY_SKIP_YYWRAP + +typedef unsigned char YY_CHAR; + +typedef int yy_state_type; + +#define yytext_ptr yytext_r + +static yy_state_type yy_get_previous_state (yyscan_t yyscanner ); +static yy_state_type yy_try_NUL_trans (yy_state_type current_state ,yyscan_t yyscanner); +static int yy_get_next_buffer (yyscan_t yyscanner ); +static void yy_fatal_error (yyconst char msg[] ,yyscan_t yyscanner ); + +/* Done after the current pattern has been matched and before the + * corresponding action - sets up yytext. + */ +#define YY_DO_BEFORE_ACTION \ + yyg->yytext_ptr = yy_bp; \ + yyleng = (size_t) (yy_cp - yy_bp); \ + yyg->yy_hold_char = *yy_cp; \ + *yy_cp = '\0'; \ + yyg->yy_c_buf_p = yy_cp; + +#define YY_NUM_RULES 22 +#define YY_END_OF_BUFFER 23 +/* This struct is not used in this scanner, + but its presence is necessary. */ +struct yy_trans_info + { + flex_int32_t yy_verify; + flex_int32_t yy_nxt; + }; +static yyconst flex_int16_t yy_accept[1613] = + { 0, + 0, 0, 23, 21, 20, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 16, 1, 12, 2, 7, 8, + 10, 15, 0, 0, 13, 5, 0, 11, 0, 0, + 16, 16, 0, 1, 12, 12, 12, 0, 0, 0, + 2, 0, 0, 0, 7, 7, 0, 0, 0, 8, + 0, 0, 0, 10, 10, 10, 10, 10, 15, 15, + 15, 17, 0, 13, 13, 13, 13, 13, 0, 0, + 5, 19, 11, 11, 11, 18, 16, 16, 0, 16, + 0, 0, 12, 12, 12, 12, 0, 0, 0, 0, + 0, 0, 0, 7, 7, 7, 7, 0, 0, 0, + + 0, 7, 0, 0, 0, 0, 0, 0, 0, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 0, 0, 0, 10, 10, 10, 10, 15, + 15, 15, 15, 17, 0, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 5, 0, 0, 19, + 0, 11, 11, 11, 18, 16, 16, 0, 0, 12, + 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 7, 0, 0, 7, 7, 7, 7, 7, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 15, 15, 14, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 5, 0, 0, 5, 5, 0, 11, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 7, 0, 7, 0, + 7, 0, 0, 7, 9, 8, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 14, 14, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 5, 0, 0, 0, 5, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 7, + 0, 7, 9, 0, 0, 9, 8, 0, 0, 9, + 8, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 14, 14, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 0, 0, 5, + 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 9, 8, 9, 0, 0, 8, 0, 0, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 14, 13, 13, 13, 13, 13, + + 13, 13, 13, 13, 13, 13, 13, 13, 5, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, + 8, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 13, 13, + 13, 13, 13, 13, 13, 0, 0, 5, 0, 0, + 4, 2, 0, 0, 0, 0, 0, 0, 0, 9, + 8, 0, 0, 0, 0, 0, 0, 10, 10, 10, + + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 13, 13, 5, 0, 0, 0, 0, 0, 0, 4, + 2, 0, 4, 2, 0, 0, 0, 0, 9, 8, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + + 10, 10, 10, 5, 0, 5, 0, 3, 0, 0, + 0, 0, 0, 0, 9, 8, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + + 10, 5, 0, 5, 0, 3, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 0, 0, 9, 8, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 5, 0, 5, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, + + 0, 8, 0, 0, 0, 0, 0, 0, 5, 0, + 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, + 0, 0, 0, 0, 8, 5, 0, 5, 0, 0, + 0, 0, 0, 9, 0, 0, 0, 8, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, + 0, 0, 9, 0, 8, 0, 0, 0, 0, 9, + 0, 0, 0, 8, 6, 0, 9, 8, 9, 0, + 8, 0, 6, 6, 6, 9, 8, 9, 8, 0, + 0, 6, 9, 8, 9, 8, 0, 9, 8, 9, + + 8, 9, 8, 9, 8, 9, 8, 9, 8, 9, + 8, 0 + } ; + +static yyconst flex_int32_t yy_ec[256] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, + 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 4, 1, 1, 1, + 1, 5, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 7, 6, 8, 9, 6, 10, 11, 12, + 13, 14, 15, 16, 17, 18, 19, 20, 6, 6, + 21, 6, 6, 6, 22, 22, 22, 23, 24, 22, + 22, 22, 22, 22, 22, 22, 23, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 23, 22, 23, 22, + 6, 25, 6, 26, 22, 6, 27, 6, 28, 29, + + 30, 6, 6, 6, 31, 6, 6, 32, 33, 34, + 35, 36, 6, 37, 38, 39, 40, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4 + } ; + +static yyconst flex_int32_t yy_meta[41] = + { 0, + 1, 2, 2, 3, 4, 5, 6, 6, 7, 8, + 9, 9, 9, 9, 9, 10, 10, 10, 10, 11, + 12, 13, 13, 14, 15, 16, 5, 5, 5, 17, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 + } ; + +static yyconst flex_int16_t yy_base[2637] = + { 0, + 0, 38, 1164,16659,16659, 0, 1122, 6, 1088, 7, + 1092, 1060, 1059, 6, 0, 1065, 1, 36, 46, 38, + 74, 47, 0, 1047, 75, 92, 0, 50, 0, 51, + 89, 90, 0, 1030, 93, 100, 101, 0, 0, 990, + 96, 104, 2, 0, 111, 123, 0, 2, 988, 112, + 948, 135, 1, 156, 114, 139, 122, 177, 128, 129, + 133, 943, 898, 178, 192, 195, 201, 203, 0, 4, + 200, 905, 137, 154, 58, 903, 140, 151, 152, 173, + 0, 0, 209, 210, 214, 218, 0, 229, 0, 239, + 0, 4, 882, 231, 232, 235, 249, 50, 259, 225, + + 0, 266, 0, 270, 0, 287, 0, 133, 875, 297, + 237, 267, 258, 298, 319, 300, 316, 314, 315, 323, + 344, 354, 365, 338, 270, 380, 346, 396, 383, 384, + 395, 397, 398, 866, 819, 405, 407, 399, 413, 422, + 424, 430, 432, 439, 441, 447, 449, 0, 403, 835, + 815, 450, 452, 454, 771, 465, 466, 750, 0, 471, + 473, 0, 0, 0, 0, 0, 465, 0, 475, 262, + 487, 286, 0, 488, 490, 494, 497, 499, 310, 0, + 0, 0, 0, 0, 515, 0, 525, 535, 500, 551, + 501, 538, 539, 572, 555, 593, 550, 568, 567, 569, + + 575, 614, 603, 576, 597, 615, 636, 618, 657, 631, + 653, 632, 640, 678, 654, 675, 676, 679, 682, 703, + 713, 704, 705, 725, 706, 728, 730, 736, 738, 744, + 746, 753, 755, 761, 763, 770, 772, 778, 780, 787, + 785, 0, 0, 727, 789, 732, 485, 715, 713, 431, + 548, 0, 0, 0, 0, 0, 795, 0, 797, 345, + 802, 379, 0, 806, 813, 823, 0, 0, 0, 0, + 844, 810, 840, 811, 812, 814, 865, 734, 816, 839, + 841, 886, 842, 907, 847, 863, 881, 882, 884, 928, + 917, 888, 889, 890, 949, 911, 930, 932, 944, 945, + + 970, 980, 991, 946, 1007, 947, 951, 953, 1028, 1009, + 1049, 972, 1024, 974, 1006, 1023, 1070, 1059, 1025, 1031, + 1032, 1091, 1053, 1072, 709, 1074, 1086, 1088, 1110, 1112, + 1118, 1093, 1115, 1120, 1127, 1129, 1137, 1144, 1146, 1152, + 1154, 1161, 1163, 1122, 0, 0, 1014, 1151, 0, 0, + 687, 490, 0, 1003, 0, 1118, 1180, 1183, 0, 1156, + 0, 1178, 1180, 0, 1185, 677, 1193, 0, 1189, 1197, + 1199, 1220, 1201, 1218, 1215, 1216, 1222, 1243, 1201, 1239, + 1241, 1244, 1265, 1246, 1247, 1260, 1262, 1268, 1289, 1299, + 1310, 1291, 1326, 1292, 1293, 1314, 1347, 1330, 1325, 1328, + + 1329, 1368, 1342, 1343, 1344, 1350, 1351, 1389, 1378, 1372, + 1390, 1391, 1393, 1404, 1405, 1406, 1427, 1408, 1443, 1422, + 1430, 1431, 1464, 1447, 1445, 1446, 1459, 1485, 1460, 1506, + 1461, 1462, 1483, 1487, 1488, 1527, 1516, 1489, 1510, 1528, + 1549, 1531, 1544, 1545, 1546, 1550, 1571, 1581, 1552, 1553, + 1574, 1592, 1596, 1598, 1604, 1606, 1607, 1609, 1611, 1621, + 1623, 1633, 1635, 1645, 1647, 1648, 1657, 0, 657, 1638, + 1640, 0, 0, 1409, 1594, 1664, 531, 0, 1495, 0, + 1669, 1678, 1682, 1659, 0, 1686, 1680, 0, 1689, 1703, + 1681, 1699, 1706, 1707, 1718, 1739, 1723, 1720, 1721, 1722, + + 1760, 1734, 1735, 1736, 1737, 1743, 1781, 1770, 1762, 1764, + 1783, 1785, 1796, 1797, 1798, 1819, 1800, 1802, 1814, 1815, + 1821, 1842, 1852, 1823, 1844, 1845, 1866, 1863, 1867, 1868, + 1869, 1870, 1891, 1901, 1892, 1893, 1894, 1895, 1916, 1917, + 1918, 1919, 1920, 1921, 1922, 1923, 1924, 1945, 1920, 1966, + 1929, 1962, 1961, 1963, 1964, 1987, 1997, 1969, 1970, 1988, + 2009, 1991, 2010, 2012, 2013, 2024, 2045, 2029, 2066, 2026, + 2042, 2040, 2041, 2043, 2087, 2076, 2049, 2068, 2070, 2108, + 2089, 2091, 2103, 2104, 2105, 2129, 2139, 2106, 2110, 2112, + 2131, 2133, 2150, 2152, 2154, 2155, 2157, 2159, 2165, 2166, + + 2167, 2169, 2171, 2180, 2183, 2193, 2194, 2195, 2198, 0, + 0, 646, 651, 0, 634, 560, 0, 632, 585, 0, + 1831, 1927, 2200, 0, 628, 624, 0, 611, 688, 2216, + 2220, 2241, 2197, 2237, 2212, 2219, 2238, 2262, 2272, 2244, + 2245, 2263, 2284, 2266, 2285, 2287, 2288, 2299, 2320, 2304, + 2301, 2302, 2303, 2315, 2316, 2324, 2339, 2341, 2342, 2343, + 2345, 2346, 2347, 2368, 2343, 2389, 2352, 2364, 2371, 2385, + 2386, 2410, 2348, 2387, 2392, 2393, 2431, 2408, 2414, 2426, + 2427, 2429, 2452, 2462, 2433, 2435, 2454, 2456, 2473, 2475, + 2477, 2478, 2479, 2480, 2481, 2482, 2483, 2504, 2479, 2505, + + 2506, 2507, 2508, 2519, 2520, 2521, 2542, 2523, 2563, 2537, + 2559, 2538, 2546, 2560, 2584, 2524, 2561, 2567, 2582, 2605, + 2586, 2588, 2600, 2601, 2603, 2626, 2636, 2607, 2609, 2628, + 2630, 2647, 2649, 2651, 2672, 2653, 2654, 2655, 2656, 2668, + 2693, 2703, 2670, 2694, 2695, 2716, 2697, 2718, 2719, 2720, + 2731, 2752, 2736, 2733, 2734, 2735, 2747, 2748, 2756, 2771, + 2773, 2774, 2775, 2777, 2778, 2779, 2800, 2775, 2784, 2796, + 2801, 2803, 2815, 2817, 2818, 0, 0, 2825, 0, 2780, + 574, 503, 509, 0, 506, 695, 0, 499, 819, 2836, + 2844, 0, 497, 832, 0, 493, 1041, 2865, 2819, 2826, + + 2827, 2828, 2840, 2886, 2875, 2867, 2868, 2869, 2907, 2890, + 2902, 2903, 2904, 2905, 2928, 2938, 2909, 2911, 2930, 2932, + 2949, 2951, 2953, 2954, 2955, 2956, 2957, 2958, 2959, 2980, + 2847, 2961, 2962, 2963, 2984, 2995, 2996, 2997, 3018, 2999, + 3039, 3001, 3002, 3013, 3014, 3020, 3060, 3049, 3041, 3042, + 3043, 3081, 3064, 3076, 3077, 3078, 3079, 3102, 3112, 3083, + 3085, 3104, 3106, 3123, 3125, 3127, 3128, 3129, 3130, 3131, + 3132, 3133, 3154, 3004, 3135, 3136, 3137, 3158, 3169, 3170, + 3171, 3192, 3173, 3175, 3176, 3187, 3188, 3194, 3209, 3210, + 3211, 3232, 3174, 3253, 3213, 3215, 3216, 3227, 3228, 3274, + + 3217, 3234, 3249, 3250, 3295, 3251, 3255, 3256, 3257, 3272, + 3316, 3305, 3278, 3297, 3299, 3318, 3320, 3331, 3332, 3333, + 3334, 3335, 3337, 3339, 3341, 3362, 3341, 3383, 3343, 3360, + 3358, 3364, 3379, 3404, 3414, 3381, 3385, 3386, 3425, 3387, + 3408, 3426, 3427, 3429, 3450, 3435, 3448, 3451, 3452, 3453, + 3454, 3465, 3466, 3467, 3469, 3475, 3476, 3477, 3480, 3501, + 3476, 3498, 3499, 3502, 3503, 3504, 3505, 3516, 3537, 3520, + 3532, 3533, 3534, 488, 0, 0, 0, 426, 1111, 394, + 1940, 3485, 392, 386, 0, 3521, 0, 3553, 3562, 3565, + 3586, 3535, 3583, 3556, 3564, 3581, 3607, 3617, 3590, 3608, + + 3609, 3630, 3611, 3632, 3633, 3634, 3645, 3666, 3650, 3647, + 3648, 3649, 3661, 3662, 3670, 3685, 3687, 3688, 3689, 3691, + 3692, 3693, 3714, 3572, 3695, 3696, 3697, 3698, 3710, 3729, + 3731, 3752, 3733, 3735, 3736, 3747, 3748, 3750, 3754, 3769, + 3771, 3792, 3694, 3813, 3773, 3775, 3776, 3787, 3788, 3834, + 3732, 3790, 3794, 3809, 3855, 3811, 3815, 3816, 3817, 3830, + 3876, 3737, 3832, 3838, 3851, 3853, 3857, 3878, 3859, 3874, + 3880, 3893, 3895, 3897, 3899, 3920, 3777, 3901, 3902, 3903, + 3904, 3916, 3918, 3935, 3956, 3937, 3939, 3951, 3952, 3953, + 3954, 3958, 3960, 3975, 3996, 3900, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 1198, 3977, 4017, 3979, 4013, + 3991, 3992, 3994, 4038, 3936, 4000, 4015, 4021, 4059, 4034, + 4036, 4040, 4042, 4055, 4080, 3941, 4057, 4061, 4063, 4076, + 4078, 4095, 4082, 4084, 4097, 4099, 4101, 4103, 4105, 4126, + 3976, 4107, 4110, 4122, 4124, 4128, 4129, 4141, 4162, 4143, + 4183, 4145, 4179, 4157, 4158, 4160, 4204, 3980, 4166, 4181, + 4187, 4225, 4200, 4202, 4206, 4208, 4221, 4246, 4145, 4223, + 4227, 4229, 4242, 4244, 4261, 4248, 4250, 4263, 4265, 4267, + 4269, 4271, 4292, 4106, 4273, 4276, 4288, 4290, 4294, 4295, + 4307, 4328, 4309, 4311, 4323, 4324, 4325, 4326, 4330, 4332, + + 4347, 4368, 4311, 4349, 0, 4351, 365, 325, 0, 1270, + 337, 0, 332, 1281, 4363, 4384, 0, 4272, 0, 4348, + 4405, 4370, 4389, 4372, 4400, 4401, 4426, 4352, 4402, 4403, + 4407, 4447, 4408, 4424, 4429, 4430, 4442, 4468, 4478, 4443, + 4445, 4451, 4469, 4470, 4491, 4472, 4493, 4494, 4495, 4496, + 4497, 4498, 4519, 4391, 4500, 4501, 4502, 4503, 4534, 4535, + 4536, 4557, 4538, 4540, 4541, 4552, 4553, 4559, 4574, 4575, + 4576, 4597, 4501, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 287, 4578, 4618, 4580, 4581, 4592, 4593, 4599, + 4639, 4537, 4614, 4615, 4616, 4660, 4620, 4621, 4622, 4637, + + 4643, 4681, 4542, 4655, 4656, 4658, 4662, 4664, 4683, 4679, + 4685, 4698, 4700, 4702, 4704, 4706, 4727, 4577, 4708, 4709, + 4710, 4711, 4723, 4725, 4742, 4763, 4744, 4746, 4758, 4759, + 4760, 4761, 4765, 4767, 4782, 4803, 4707, 4824, 4784, 4786, + 4798, 4799, 4800, 4845, 4743, 4801, 4805, 4807, 4866, 4822, + 4826, 4828, 4840, 4841, 4887, 4748, 4843, 4847, 4849, 4862, + 4864, 4889, 4868, 4870, 4885, 4891, 4904, 4906, 4908, 4929, + 4583, 4910, 4912, 4913, 4925, 4927, 4931, 4944, 4965, 4946, + 4948, 4960, 4961, 4962, 4963, 4967, 4969, 4984, 5005, 4788, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1327, + + 4986, 4988, 0, 5000, 0, 279, 0, 4904, 0, 4914, + 270, 1360, 1415, 0, 1452, 1537, 0, 5021, 5026, 5047, + 5002, 5030, 5007, 5031, 5042, 5068, 4947, 5043, 5044, 5045, + 5089, 5049, 5066, 5070, 5071, 5072, 5110, 4985, 5084, 5085, + 5087, 5093, 5106, 5114, 5111, 5112, 5125, 5129, 5133, 5135, + 5136, 5157, 4990, 5138, 5139, 5140, 5141, 5152, 5154, 5173, + 5194, 5175, 5176, 5178, 5189, 5190, 5191, 5192, 5197, 5213, + 5234, 5174, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 257, 5215, 5216, 0, 5218, 0, 0, 0, 0, + 0, 0, 0, 5179, 0, 2155, 5229, 0, 5214, 0, + + 2224, 5250, 1562, 1719, 0, 1807, 1876, 0, 5237, 0, + 5251, 0, 0, 1879, 2022, 0, 231, 0, 228, 0, + 0, 221, 0, 199, 0, 0, 5219, 0, 2228, 5256, + 0, 5255, 0, 2485, 5265, 5255, 0, 5266, 0, 0, + 0, 197, 195, 5277, 0, 191, 176, 5287, 0, 170, + 0, 149, 0, 0, 145, 0, 112, 0, 0, 5272, + 0, 101, 5273, 0, 5274, 0, 0, 87, 54, 5296, + 0, 52, 49, 5301, 5282, 0, 5306, 5310, 5295, 0, + 5311, 0, 5314, 5312, 5320, 5322, 5333, 5341, 5345, 0, + 5032, 5329, 5352, 5356, 5360, 5364, 4, 5368, 5375, 5379, + + 5383, 5387, 5391, 5398, 5402, 5406, 5410, 5414, 5421, 5425, + 5429,16659, 5454, 5468, 5478, 5490, 5498, 5510, 5518, 5531, + 5547, 5562, 5577, 5587, 5598, 5612, 5626, 5636, 5639, 5651, + 5659, 5662, 5670, 5677, 5691, 5699, 5702, 5710, 5717, 5729, + 5742, 5757, 5772, 5787, 5797, 5801, 5809, 5821, 5831, 5834, + 5837, 5840, 5843, 5850, 5862, 5865, 5872, 5882, 5885, 5888, + 5895, 5907, 5919, 5931, 5943, 5955, 5963, 5970, 5982, 5995, + 6010, 6026, 6041, 6056, 6071, 6086, 6101, 6116, 6131, 6146, + 6160, 6168, 6176, 6186, 6190, 6199, 6211, 6221, 6228, 6236, + 6239, 6242, 6245, 6250, 6257, 6269, 6272, 6279, 6293, 6307, + + 6319, 6322, 6325, 6328, 6331, 6338, 6350, 6362, 6374, 6386, + 6398, 6410, 6422, 6434, 6446, 6458, 6470, 6482, 6494, 6506, + 6518, 6530, 6542, 6555, 6570, 6585, 6600, 6615, 6630, 6645, + 6660, 6675, 6690, 6705, 6720, 6735, 6745, 2256, 6752, 6760, + 6764, 6772, 6775, 6778, 6781, 6786, 6793, 6805, 6808, 6811, + 6814, 6821, 6833, 6845, 6857, 6869, 6881, 6893, 6905, 6917, + 6929, 6941, 6953, 6965, 6977, 6989, 7001, 7013, 7025, 7037, + 7049, 7061, 7073, 7085, 7097, 7109, 7121, 7133, 7145, 7157, + 7169, 7181, 7193, 7206, 7221, 7236, 7251, 7266, 7281, 7296, + 7311, 7326, 7341, 7356, 7371, 7386, 7401, 7415, 7423, 7426, + + 7429, 2314, 2530, 2540, 7432, 7435, 2653, 7438, 2660, 7450, + 7462, 7474, 7486, 7498, 7510, 7522, 7534, 7546, 7558, 7570, + 7582, 7594, 7606, 7618, 7630, 7642, 7654, 7666, 7678, 7690, + 7702, 7714, 7726, 7738, 7750, 7762, 7774, 7786, 7798, 7810, + 7822, 7834, 7846, 7858, 7870, 7882, 7894, 7906, 7918, 7930, + 7942, 7954, 7966, 7978, 7990, 8002, 8014, 8026, 8038, 8050, + 8063, 8078, 8093, 8108, 8123, 8138, 8153, 8168, 8183, 8198, + 8213, 8228, 8243, 8253, 8260, 8272, 8280, 2745, 2785, 2853, + 2857, 2962, 8287, 8299, 8311, 8323, 8335, 8347, 8359, 8371, + 8383, 8395, 8407, 8419, 8431, 8443, 8455, 8467, 8479, 8491, + + 8503, 8515, 8527, 8539, 8551, 8563, 8575, 8587, 8599, 8611, + 8623, 8635, 8647, 8659, 8671, 8683, 8695, 8707, 8719, 8731, + 8743, 8755, 8767, 8779, 8791, 8803, 8815, 8827, 8839, 8851, + 8863, 8875, 8887, 8899, 8911, 8923, 8935, 8947, 8959, 8971, + 8983, 8995, 9007, 9019, 9031, 9043, 9055, 9067, 9079, 9091, + 9103, 9115, 9127, 9139, 9151, 9163, 9175, 9188, 9203, 9218, + 9233, 9248, 9263, 9278, 9293, 9308, 3002, 9318, 3031, 3136, + 3180, 3213, 3285, 9325, 9337, 9349, 9361, 9373, 9385, 9397, + 9409, 9421, 9433, 9445, 9457, 9469, 9481, 9493, 9505, 9517, + 9529, 9541, 9553, 9565, 9577, 9589, 9601, 9613, 9625, 9637, + + 9649, 9661, 9673, 9685, 9697, 9709, 9721, 9733, 9745, 9757, + 9769, 9781, 9793, 9805, 9817, 9829, 9841, 9853, 9865, 9877, + 9889, 9901, 9913, 9925, 9937, 9949, 9961, 9973, 9985, 9997, + 10009,10021,10033,10045,10057,10069,10081,10093,10105,10117, + 10129,10141,10153,10165,10177,10189,10201,10213,10225,10237, + 10249,10261,10273,10285,10297,10309,10321,10333,10345,10357, + 10369,10381,10393,10405,10417,10429,10441,10453,10465,10477, + 10489,10501,10513,10525,10537,10550,10565,10580,10595,10605, + 10608, 3527, 3534, 3569, 3600, 3659,10615,10627,10639,10651, + 10663,10675,10687,10699,10711,10723,10735,10747,10759,10771, + + 10783,10795,10807,10819,10831,10843,10855,10867,10879,10891, + 10903,10915,10927,10939,10951,10963,10975,10987,10999,11011, + 11023,11035,11047,11059,11071,11083,11095,11107,11119,11131, + 11143,11155,11167,11179,11191,11203,11215,11227,11239,11251, + 11263,11275,11287,11299,11311,11323,11335,11347,11359,11371, + 11383,11395,11407,11419,11431,11443,11455,11467,11479,11491, + 11503,11515,11527,11539,11551,11563,11575,11587,11599,11611, + 11623,11635,11647,11659,11671,11683,11695,11707,11719,11731, + 11743,11755,11767,11779,11791,11803,11815,11827,11839,11851, + 11863,11875,11887,11899,11911,11923,11935,11947,11959,11971, + + 11983,11995,12007,12019,12031,12043,12055,12067,12079,12091, + 12103,12115,12127,12139,12151,12163,12175,12187,12200,12214, + 12222,12225, 3773,12228,12236,12239,12246,12258,12270,12282, + 12294,12306,12318,12330,12342,12354,12366,12378,12390,12402, + 12414,12426,12438,12450,12462,12474,12486,12498,12510,12522, + 12534,12546,12558,12570,12582,12594,12606,12618,12630,12642, + 12654,12666,12678,12690,12702,12714,12726,12738,12750,12762, + 12774,12786,12798,12810,12822,12834,12846,12858,12870,12882, + 12894,12906,12918,12930,12942,12954,12966,12978,12990,13002, + 13014,13026,13038,13050,13062,13074,13086,13098,13110,13122, + + 13134,13146,13158,13170,13182,13194,13206,13218,13230,13242, + 13254,13266,13278,13290,13302,13314,13326,13338,13350,13362, + 13374,13386,13398,13410,13422,13434,13446,13458,13470,13482, + 13494,13506,13518,13530,13542,13554,13566,13578,13590,13602, + 13614,13626,13638,13650,13662,13674,13686,13698,13710,13722, + 13734,13746,13758,13770,13782,13794,13806,13818,13830,13842, + 13854,13866,13878,13890,13902,13914,13926,13938,13950,13962, + 13974,13986,13998,14010,14022,14034,14046,14058,14070,14082, + 14094,14106,14118,14126,14133,14141, 3906,14148,14160,14168, + 14171,14178,14190,14202,14214,14226,14238,14250,14262,14274, + + 14286,14298,14310,14322,14334,14346,14358,14370,14382,14394, + 14406,14418,14430,14442,14454,14466,14478,14490,14502,14514, + 14526,14538,14550,14562,14574,14586,14598,14610,14622,14634, + 14646,14658,14670,14682,14694,14706,14718,14730,14742,14754, + 14766,14778,14790,14802,14814,14826,14838,14850,14862,14874, + 14886,14898,14910,14922,14934,14946,14958,14970,14982,14994, + 15006,15018,15030,15042,15054,15066,15078,15090,15102,15114, + 15126,15138,15150,15162,15174,15186,15198,15210,15222,15234, + 15246,15258,15270,15282,15294,15306,15318,15330,15342,15354, + 15366,15378,15390,15402,15414,15426,15438,15450,15462,15474, + + 15486,15498,15510,15522,15534,15546,15558,15570,15582,15594, + 15606,15618,15630,15642,15654,15662,15669,15677,15680,15688, + 15691,15694,15697,15704,15716,15728,15740,15752,15764,15776, + 15788,15800,15812,15824,15836,15848,15860,15872,15884,15896, + 15908,15920,15932,15944,15956,15968,15980,15992,16004,16016, + 16028,16040,16052,16064,16076,16088,16100,16112,16124,16136, + 16148,16160,16172,16184,16196,16208,16220,16228,16235,16243, + 16246,16249,16252, 4151, 4317,16259, 4784, 4953,16271,16279, + 16282,16289,16297,16304,16312,16315, 5029,16318, 5139,16321, + 5142, 5146,16328, 5279, 5323,16340,16348,16355,16363,16366, + + 16369,16372, 5334,16375, 5347,16378,16381,16384,16387,16390, + 16393,16396,16399,16406,16418,16426,16429,16436,16448,16460, + 16472,16480,16487,16499,16511,16523,16535,16547,16559,16571, + 16583,16595,16607,16619,16631,16643 + } ; + +static yyconst flex_int16_t yy_def[2637] = + { 0, + 1613, 1613, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, + 1612, 1612, 1612, 1612, 1614, 1615, 1616, 1617, 1618, 1619, + 1612, 1620, 1621, 1612, 1622, 1612, 1623, 1624, 1625, 1614, + 1626, 1627, 1628, 1629, 1616, 1616, 1630, 1631, 1631, 1631, + 1632, 1618, 42, 1633, 1634, 1635, 1636, 1636, 1636, 1637, + 21, 21, 1638, 1612, 1639, 1640, 1640, 1612, 1620, 1620, + 1641, 1621, 1612, 1622, 1622, 1642, 1643, 1644, 1645, 1612, + 1612, 1623, 1612, 1646, 1647, 1625, 1626, 1626, 1627, 1648, + 1649, 1650, 1616, 1616, 1630, 1630, 1651, 1651, 1652, 1651, + 1653, 1653, 1653, 1633, 1612, 1654, 1634, 1655, 1635, 99, + + 1656, 1657, 1658, 1658, 1659, 1658, 1660, 1660, 1660, 1612, + 1661, 1662, 1662, 1612, 1612, 1663, 1664, 1664, 1665, 1666, + 1612, 121, 1612, 123, 1667, 1612, 1668, 1669, 1669, 1670, + 1670, 1671, 1671, 1672, 1612, 1673, 1673, 1674, 1675, 1676, + 1676, 1677, 1678, 1679, 1679, 1680, 1681, 1682, 1612, 1683, + 1684, 1685, 1612, 1686, 1612, 1687, 1687, 1612, 1688, 1689, + 1689, 1690, 1691, 1691, 1691, 1692, 1692, 1693, 1692, 1694, + 1695, 1696, 1697, 1697, 1698, 1612, 1699, 1700, 1701, 1702, + 1703, 1703, 1703, 1704, 1704, 1705, 1704, 1612, 1706, 1707, + 1707, 1708, 1709, 1612, 194, 1612, 1710, 1711, 1711, 1712, + + 1713, 1612, 202, 1714, 1715, 1716, 1612, 1717, 1612, 1718, + 1719, 1719, 1612, 1612, 1720, 1721, 1721, 1722, 1723, 1612, + 220, 1724, 1724, 1725, 1726, 1726, 1727, 1728, 1728, 1729, + 1730, 1730, 1731, 1732, 1733, 1733, 1734, 1735, 1735, 1736, + 1612, 1737, 1738, 1612, 1739, 1740, 1741, 1612, 1612, 1612, + 1612, 1742, 1743, 1743, 1743, 1744, 1744, 1745, 1745, 1746, + 1747, 1748, 1749, 1749, 1612, 1612, 1750, 1751, 1751, 1751, + 1612, 1752, 1753, 1753, 1754, 1755, 1612, 277, 1756, 1757, + 1758, 1612, 1759, 1612, 1760, 1761, 1761, 1762, 1763, 1612, + 290, 1764, 1765, 1766, 1612, 1767, 1768, 1769, 1770, 1771, + + 1612, 301, 1612, 1772, 1773, 1773, 1774, 1775, 1612, 309, + 1612, 1776, 1777, 1777, 1778, 1779, 1612, 317, 1780, 1781, + 1782, 1612, 1783, 1784, 1785, 1786, 1786, 1787, 1788, 1788, + 1789, 1790, 1790, 1791, 1792, 1792, 1793, 1794, 1794, 1795, + 1796, 1796, 1797, 1798, 1799, 1800, 1612, 1612, 1801, 1802, + 1612, 1612, 1803, 1612, 1804, 1612, 1612, 1612, 1805, 1805, + 1806, 1806, 1612, 1807, 1612, 1808, 1612, 1809, 1612, 1612, + 1612, 1612, 1810, 1811, 1811, 1812, 1813, 1612, 378, 1814, + 1815, 1816, 1612, 1817, 1818, 1819, 1820, 1821, 1612, 389, + 1612, 1822, 1823, 1823, 1824, 1825, 1612, 397, 1826, 1827, + + 1828, 1612, 1829, 1830, 1831, 1832, 1833, 1612, 408, 1834, + 1835, 1836, 1837, 1838, 1839, 1840, 1612, 1841, 1842, 1842, + 1843, 1844, 1612, 423, 1845, 1846, 1847, 1612, 1848, 1612, + 1849, 1850, 1850, 1851, 1852, 1612, 436, 1853, 1854, 1855, + 1612, 1856, 1857, 1858, 1859, 1860, 1612, 447, 1861, 1862, + 1863, 1863, 1864, 1865, 1865, 1866, 1867, 1867, 1868, 1869, + 1869, 1870, 1871, 1871, 1872, 1873, 1873, 1874, 1612, 1875, + 1876, 1877, 1878, 1612, 1612, 1612, 1612, 1879, 1612, 1880, + 1612, 1612, 1612, 1612, 1881, 1612, 1612, 1882, 1612, 1612, + 1883, 1884, 1884, 1885, 1886, 1612, 496, 1887, 1888, 1889, + + 1612, 1890, 1891, 1892, 1893, 1894, 1612, 507, 1895, 1896, + 1897, 1898, 1899, 1900, 1901, 1612, 1902, 1903, 1903, 1904, + 1905, 1612, 522, 1906, 1907, 1908, 1612, 1909, 1910, 1911, + 1912, 1913, 1612, 533, 1914, 1915, 1916, 1917, 1918, 1919, + 1920, 1921, 1922, 1923, 1924, 1925, 1926, 1612, 548, 1612, + 1927, 1928, 1928, 1929, 1930, 1612, 556, 1931, 1932, 1933, + 1612, 1934, 1935, 1936, 1937, 1938, 1612, 567, 1612, 1939, + 1940, 1940, 1941, 1942, 1612, 575, 1943, 1944, 1945, 1612, + 1946, 1947, 1948, 1949, 1950, 1612, 586, 1951, 1952, 1953, + 1954, 1955, 1956, 1957, 1958, 1959, 1959, 1960, 1961, 1961, + + 1962, 1962, 1963, 1964, 1964, 1965, 1966, 1966, 1612, 1967, + 1968, 1612, 1612, 1969, 1969, 1612, 1970, 1970, 1612, 1971, + 1612, 1612, 1612, 1972, 1972, 1612, 1973, 1973, 1612, 1612, + 1612, 1612, 1974, 1975, 1975, 1976, 1977, 1612, 638, 1978, + 1979, 1980, 1612, 1981, 1982, 1983, 1984, 1985, 1612, 649, + 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, + 1996, 1997, 1998, 1612, 664, 1612, 1999, 2000, 2000, 2001, + 2002, 1612, 672, 2003, 2004, 2005, 1612, 2006, 2007, 2008, + 2009, 2010, 1612, 683, 2011, 2012, 2013, 2014, 2015, 2016, + 2017, 2018, 2019, 2020, 2021, 2022, 2023, 1612, 698, 2024, + + 2025, 2026, 2027, 2028, 2029, 2030, 1612, 2031, 1612, 2032, + 2033, 2033, 2034, 2035, 1612, 715, 2036, 2037, 2038, 1612, + 2039, 2040, 2041, 2042, 2043, 1612, 726, 2044, 2045, 2046, + 2047, 2048, 2049, 2050, 1612, 2051, 2052, 2052, 2053, 2054, + 1612, 741, 2055, 2056, 2057, 1612, 2058, 2059, 2060, 2061, + 2062, 1612, 752, 2063, 2064, 2065, 2066, 2067, 2068, 2069, + 2070, 2071, 2072, 2073, 2074, 2075, 1612, 767, 2076, 2076, + 2077, 2077, 2078, 2079, 2079, 2080, 2081, 1612, 2082, 1612, + 1612, 1612, 1612, 2083, 2083, 1612, 2084, 2084, 1612, 1612, + 1612, 2085, 2085, 1612, 2086, 2086, 1612, 1612, 2087, 2088, + + 2088, 2089, 2090, 1612, 804, 2091, 2092, 2093, 1612, 2094, + 2095, 2096, 2097, 2098, 1612, 815, 2099, 2100, 2101, 2102, + 2103, 2104, 2105, 2106, 2107, 2108, 2109, 2110, 2111, 1612, + 830, 2112, 2113, 2114, 2115, 2116, 2117, 2118, 1612, 2119, + 1612, 2120, 2121, 2121, 2122, 2123, 1612, 847, 2124, 2125, + 2126, 1612, 2127, 2128, 2129, 2130, 2131, 1612, 858, 2132, + 2133, 2134, 2135, 2136, 2137, 2138, 2139, 2140, 2141, 2142, + 2143, 2144, 1612, 873, 2145, 2146, 2147, 2148, 2149, 2150, + 2151, 1612, 2152, 2153, 2154, 2155, 2156, 2157, 2158, 2159, + 2160, 1612, 892, 1612, 2161, 2162, 2162, 2163, 2164, 1612, + + 900, 2165, 2166, 2167, 1612, 2168, 2169, 2170, 2171, 2172, + 1612, 911, 2173, 2174, 2175, 2176, 2177, 2178, 2179, 2180, + 2181, 2182, 2183, 2184, 2185, 1612, 926, 1612, 2186, 2187, + 2187, 2188, 2189, 1612, 934, 2190, 2191, 2192, 1612, 2193, + 2194, 2195, 2196, 2197, 1612, 945, 2198, 2199, 2200, 2201, + 2202, 2203, 2204, 2205, 2206, 2207, 2208, 2209, 2210, 1612, + 960, 2211, 2212, 2213, 2214, 2215, 2216, 2217, 1612, 2218, + 2219, 2219, 2220, 1612, 2221, 2222, 2223, 2223, 1612, 2224, + 2224, 1612, 1612, 1612, 2225, 1612, 2226, 1612, 1612, 1612, + 1612, 2227, 2228, 2228, 2229, 2230, 1612, 997, 2231, 2232, + + 2233, 1612, 2234, 2235, 2236, 2237, 2238, 1612, 1008, 2239, + 2240, 2241, 2242, 2243, 2244, 2245, 2246, 2247, 2248, 2249, + 2250, 2251, 1612, 1023, 2252, 2253, 2254, 2255, 2256, 2257, + 2258, 1612, 2259, 2260, 2261, 2262, 2263, 2264, 2265, 2266, + 2267, 1612, 1042, 1612, 2268, 2269, 2269, 2270, 2271, 1612, + 1050, 2272, 2273, 2274, 1612, 2275, 2276, 2277, 2278, 2279, + 1612, 1061, 2280, 2281, 2282, 2283, 2284, 2285, 2286, 2287, + 2288, 2289, 2290, 2291, 2292, 1612, 1076, 2293, 2294, 2295, + 2296, 2297, 2298, 2299, 1612, 2300, 2301, 2302, 2303, 2304, + 2305, 2306, 2307, 2308, 1612, 1095, 1096, 1096, 1096, 1096, + + 1096, 1096, 1096, 1096, 1096, 1096, 1612, 1612, 2309, 2310, + 2310, 2311, 2312, 1612, 1114, 2313, 2314, 2315, 1612, 2316, + 2317, 2318, 2319, 2320, 1612, 1125, 2321, 2322, 2323, 2324, + 2325, 2326, 2327, 2328, 2329, 2330, 2331, 2332, 2333, 1612, + 1140, 2334, 2335, 2336, 2337, 2338, 2339, 2340, 1612, 2341, + 1612, 2342, 2343, 2343, 2344, 2345, 1612, 1157, 2346, 2347, + 2348, 1612, 2349, 2350, 2351, 2352, 2353, 1612, 1168, 2354, + 2355, 2356, 2357, 2358, 2359, 2360, 2361, 2362, 2363, 2364, + 2365, 2366, 1612, 1183, 2367, 2368, 2369, 2370, 2371, 2372, + 2373, 1612, 2374, 2375, 2376, 2377, 2378, 2379, 2380, 2381, + + 2382, 1612, 1202, 2383, 2384, 2385, 1612, 1612, 2386, 2386, + 2386, 2387, 2387, 1612, 2388, 2389, 2390, 1612, 2391, 1612, + 1612, 2392, 2393, 2393, 2394, 2395, 1612, 1227, 2396, 2397, + 2398, 1612, 2399, 2400, 2401, 2402, 2403, 1612, 1238, 2404, + 2405, 2406, 2407, 2408, 2409, 2410, 2411, 2412, 2413, 2414, + 2415, 2416, 1612, 1253, 2417, 2418, 2419, 2420, 2421, 2422, + 2423, 1612, 2424, 2425, 2426, 2427, 2428, 2429, 2430, 2431, + 2432, 1612, 1272, 1273, 1273, 1273, 1273, 1273, 1273, 1273, + 1273, 1273, 1273, 1612, 1612, 2433, 2434, 2434, 2435, 2436, + 1612, 1291, 2437, 2438, 2439, 1612, 2440, 2441, 2442, 2443, + + 2444, 1612, 1302, 2445, 2446, 2447, 2448, 2449, 2450, 2451, + 2452, 2453, 2454, 2455, 2456, 2457, 1612, 1317, 2458, 2459, + 2460, 2461, 2462, 2463, 2464, 1612, 2465, 2466, 2467, 2468, + 2469, 2470, 2471, 2472, 2473, 1612, 1336, 1612, 2474, 2475, + 2475, 2476, 2477, 1612, 1344, 2478, 2479, 2480, 1612, 2481, + 2482, 2483, 2484, 2485, 1612, 1355, 2486, 2487, 2488, 2489, + 2490, 2491, 2492, 2493, 2494, 2495, 2496, 2497, 2498, 1612, + 1370, 2499, 2500, 2501, 2502, 2503, 2504, 2505, 1612, 2506, + 2507, 2508, 2509, 2510, 2511, 2512, 2513, 2514, 1612, 1389, + 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, 1390, + + 1612, 2515, 2516, 2517, 2518, 2519, 2520, 2520, 2521, 2520, + 1612, 1612, 1612, 2522, 1612, 1612, 2523, 2524, 2525, 1612, + 2526, 2527, 2527, 2528, 2529, 1612, 1426, 2530, 2531, 2532, + 1612, 2533, 2534, 2535, 2536, 2537, 1612, 1437, 2538, 2539, + 2540, 2541, 2542, 2543, 2544, 2545, 2546, 2547, 2548, 2549, + 2550, 1612, 1452, 2551, 2552, 2553, 2554, 2555, 2556, 2557, + 1612, 2558, 2559, 2560, 2561, 2562, 2563, 2564, 2565, 2566, + 1612, 1471, 1472, 1472, 1472, 1472, 1472, 1472, 1472, 1472, + 1472, 1472, 1612, 2567, 2568, 2569, 2570, 2571, 2572, 2573, + 2573, 2573, 2574, 1612, 2575, 1612, 2576, 2577, 1612, 2578, + + 1612, 2579, 1612, 1612, 2580, 1612, 1612, 2581, 2582, 2583, + 2584, 2585, 2586, 1612, 1612, 2587, 1612, 2587, 1612, 2588, + 2589, 1612, 2589, 1612, 2590, 2591, 1612, 2592, 1612, 2593, + 2594, 1612, 2595, 1612, 2596, 1612, 2597, 2598, 2599, 2600, + 2601, 1612, 1612, 1612, 2602, 1612, 1612, 1612, 2603, 1612, + 2603, 1612, 2604, 2605, 1612, 2605, 1612, 2606, 2607, 1612, + 2608, 1612, 1612, 2609, 1612, 2610, 2611, 1612, 1612, 1612, + 2612, 1612, 1612, 1612, 1612, 2613, 2614, 2615, 1612, 2616, + 1612, 2617, 1612, 1612, 1612, 2618, 2619, 2620, 2621, 2622, + 1612, 1612, 2623, 2624, 2625, 2626, 1612, 2627, 2628, 2629, + + 2630, 2631, 2632, 2633, 2634, 1612, 1612, 2635, 2636, 1612, + 1612, 0, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, + 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, + 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, + 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, + 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, + 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, + 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, + 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, + 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, + + 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, + 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, + 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, + 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, + 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, + 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, + 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, + 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, + 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, + 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, + + 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, + 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, + 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, + 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, + 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, + 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, + 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, + 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, + 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, + 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, + + 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, + 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, + 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, + 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, + 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, + 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, + 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, + 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, + 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, + 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, + + 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, + 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, + 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, + 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, + 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, + 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, + 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, + 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, + 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, + 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, + + 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, + 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, + 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, + 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, + 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, + 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, + 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, + 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, + 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, + 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, + + 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, + 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, + 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, + 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, + 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, + 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, + 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, + 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, + 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, + 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, + + 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, + 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, + 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, + 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, + 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, + 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, + 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, + 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, + 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, + 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, + + 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, + 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, + 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, + 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, + 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, + 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, + 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, + 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, + 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, + 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, + + 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, + 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, + 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, + 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, + 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, + 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, + 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, + 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, + 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, + 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, + + 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, + 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, + 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, + 1612, 1612, 1612, 1612, 1612, 1612 + } ; + +static yyconst flex_int16_t yy_nxt[16700] = + { 0, + 1612, 1612, 5, 1612, 30, 35, 1612, 1612, 1612, 1612, + 110, 111, 112, 147, 147, 147, 147, 88, 89, 104, + 105, 167, 168, 350, 32, 37, 6, 7, 8, 15, + 9, 10, 18, 27, 11, 12, 28, 16, 13, 14, + 5, 22, 29, 19, 20, 23, 39, 40, 48, 49, + 42, 60, 43, 43, 44, 30, 173, 173, 1581, 73, + 41, 1581, 50, 1579, 6, 7, 8, 153, 9, 10, + 46, 61, 11, 12, 75, 1612, 13, 14, 51, 65, + 52, 53, 75, 54, 55, 56, 57, 57, 57, 57, + 57, 57, 57, 77, 79, 66, 1579, 83, 58, 67, + + 68, 69, 69, 70, 84, 85, 92, 93, 42, 477, + 43, 43, 44, 32, 32, 95, 71, 37, 114, 96, + 41, 1573, 108, 109, 37, 37, 114, 99, 1612, 100, + 100, 101, 130, 131, 98, 46, 50, 133, 58, 1612, + 98, 1612, 1612, 114, 77, 151, 58, 46, 120, 121, + 185, 186, 61, 61, 1572, 77, 79, 61, 1569, 1612, + 114, 75, 151, 58, 32, 115, 116, 117, 118, 118, + 118, 118, 118, 118, 118, 32, 1612, 156, 75, 1568, + 58, 123, 65, 124, 125, 1565, 126, 127, 128, 129, + 129, 129, 129, 129, 129, 129, 65, 32, 66, 137, + + 1565, 58, 67, 68, 1563, 141, 1563, 145, 1547, 148, + 148, 149, 66, 83, 84, 138, 67, 68, 160, 67, + 139, 142, 161, 66, 71, 67, 143, 67, 146, 1612, + 1546, 1612, 1612, 37, 37, 95, 95, 1543, 37, 95, + 1542, 114, 37, 163, 163, 163, 163, 163, 165, 165, + 165, 165, 165, 95, 170, 46, 46, 96, 172, 46, + 170, 58, 114, 99, 172, 100, 100, 101, 256, 256, + 176, 114, 98, 46, 177, 1612, 193, 194, 98, 209, + 210, 211, 58, 1612, 181, 181, 181, 181, 181, 179, + 46, 58, 258, 258, 1406, 179, 183, 183, 183, 183, + + 183, 114, 114, 1406, 114, 1612, 188, 189, 190, 191, + 191, 191, 191, 191, 191, 191, 263, 263, 114, 114, + 114, 58, 58, 114, 58, 201, 202, 114, 196, 197, + 198, 199, 199, 199, 199, 199, 199, 199, 58, 58, + 58, 1411, 1612, 58, 1612, 1612, 1410, 58, 114, 1406, + 213, 359, 359, 206, 206, 206, 206, 207, 208, 208, + 208, 208, 208, 208, 208, 208, 208, 208, 58, 123, + 58, 124, 125, 1405, 126, 127, 128, 129, 129, 129, + 129, 129, 129, 129, 213, 361, 361, 213, 130, 214, + 215, 216, 217, 217, 217, 217, 217, 217, 217, 131, + + 213, 222, 223, 226, 58, 219, 220, 58, 61, 137, + 981, 137, 245, 245, 245, 245, 980, 229, 980, 61, + 58, 61, 61, 67, 227, 138, 141, 138, 141, 67, + 139, 67, 139, 138, 232, 1208, 236, 67, 230, 352, + 353, 354, 142, 145, 142, 145, 67, 143, 67, 143, + 233, 239, 142, 241, 67, 234, 67, 237, 151, 66, + 246, 66, 246, 67, 146, 67, 146, 66, 243, 156, + 156, 67, 240, 244, 75, 160, 75, 161, 75, 253, + 253, 253, 253, 253, 255, 255, 255, 255, 255, 32, + 32, 95, 95, 246, 176, 37, 1205, 37, 176, 473, + + 474, 176, 990, 176, 114, 114, 989, 177, 984, 75, + 98, 46, 46, 260, 46, 983, 98, 982, 46, 260, + 262, 46, 179, 46, 58, 58, 262, 981, 179, 268, + 268, 268, 268, 268, 270, 270, 270, 270, 270, 114, + 620, 621, 114, 114, 271, 272, 273, 274, 274, 274, + 274, 274, 274, 274, 114, 114, 352, 355, 356, 58, + 276, 277, 58, 58, 283, 283, 283, 283, 283, 781, + 781, 114, 114, 114, 58, 58, 114, 289, 290, 114, + 114, 281, 281, 281, 281, 282, 283, 283, 283, 283, + 283, 58, 58, 58, 782, 782, 58, 114, 980, 58, + + 58, 114, 284, 285, 286, 287, 287, 287, 287, 287, + 287, 287, 296, 296, 296, 296, 296, 58, 114, 114, + 791, 58, 114, 294, 294, 294, 294, 295, 296, 296, + 296, 296, 296, 790, 790, 213, 213, 790, 58, 58, + 114, 782, 58, 781, 213, 300, 300, 300, 300, 300, + 300, 300, 301, 302, 302, 58, 58, 213, 213, 780, + 58, 213, 308, 309, 58, 779, 303, 304, 305, 306, + 306, 306, 306, 306, 306, 306, 610, 58, 58, 213, + 213, 58, 213, 213, 316, 317, 213, 311, 312, 313, + 314, 314, 314, 314, 314, 314, 314, 791, 791, 58, + + 58, 366, 58, 58, 983, 983, 58, 213, 222, 223, + 226, 34, 321, 321, 321, 321, 322, 323, 323, 323, + 323, 323, 323, 323, 323, 323, 323, 58, 61, 61, + 67, 227, 226, 325, 327, 351, 346, 346, 347, 34, + 229, 153, 229, 384, 384, 384, 384, 384, 330, 325, + 232, 244, 67, 227, 67, 328, 138, 232, 138, 333, + 67, 230, 67, 230, 138, 336, 233, 236, 67, 331, + 67, 234, 248, 233, 236, 155, 339, 67, 234, 67, + 334, 233, 239, 142, 239, 67, 337, 67, 237, 241, + 142, 342, 142, 348, 67, 237, 67, 340, 66, 95, + + 66, 95, 67, 240, 67, 240, 176, 66, 350, 244, + 176, 67, 343, 244, 114, 114, 114, 363, 114, 46, + 114, 46, 364, 365, 73, 179, 46, 367, 984, 984, + 46, 179, 368, 369, 58, 58, 58, 366, 58, 150, + 58, 989, 989, 114, 114, 114, 114, 50, 114, 377, + 378, 114, 224, 372, 373, 374, 375, 375, 375, 375, + 375, 375, 375, 58, 58, 58, 58, 114, 58, 114, + 134, 58, 396, 397, 382, 382, 382, 382, 383, 384, + 384, 384, 384, 384, 187, 114, 114, 58, 114, 58, + 114, 169, 114, 114, 114, 388, 388, 388, 388, 388, + + 388, 388, 389, 390, 390, 58, 58, 155, 58, 150, + 58, 114, 58, 58, 58, 114, 391, 392, 393, 394, + 394, 394, 394, 394, 394, 394, 403, 403, 403, 403, + 403, 58, 114, 135, 114, 58, 114, 401, 401, 401, + 401, 402, 403, 403, 403, 403, 403, 134, 114, 114, + 213, 213, 58, 114, 58, 213, 58, 213, 407, 407, + 407, 407, 407, 407, 407, 408, 409, 409, 58, 58, + 58, 58, 1612, 58, 114, 58, 213, 58, 213, 414, + 414, 414, 414, 415, 416, 416, 416, 416, 416, 416, + 416, 416, 416, 416, 58, 213, 58, 106, 58, 90, + + 417, 418, 419, 420, 420, 420, 420, 420, 420, 420, + 213, 213, 475, 475, 475, 58, 422, 423, 429, 429, + 429, 429, 429, 470, 470, 470, 470, 213, 213, 213, + 58, 58, 213, 435, 436, 213, 213, 427, 427, 427, + 427, 428, 429, 429, 429, 429, 429, 58, 58, 58, + 990, 990, 58, 213, 34, 58, 58, 213, 430, 431, + 432, 433, 433, 433, 433, 433, 433, 433, 442, 442, + 442, 442, 442, 58, 213, 63, 449, 58, 327, 440, + 440, 440, 440, 441, 442, 442, 442, 442, 442, 34, + 327, 26, 452, 25, 58, 213, 325, 333, 67, 328, + + 446, 446, 446, 446, 446, 446, 446, 447, 448, 448, + 67, 328, 67, 453, 330, 58, 330, 67, 334, 333, + 1208, 1208, 455, 24, 458, 21, 241, 476, 476, 476, + 138, 336, 138, 336, 67, 331, 67, 331, 138, 67, + 334, 461, 67, 456, 67, 459, 244, 233, 339, 233, + 339, 67, 337, 67, 337, 348, 464, 233, 342, 17, + 176, 67, 462, 1612, 142, 342, 142, 467, 67, 340, + 67, 340, 142, 1612, 66, 244, 67, 465, 67, 343, + 46, 66, 176, 66, 363, 67, 343, 67, 477, 478, + 479, 477, 480, 481, 482, 482, 482, 367, 483, 483, + + 483, 484, 46, 487, 366, 114, 485, 486, 488, 489, + 502, 502, 502, 502, 502, 1612, 1612, 50, 1612, 114, + 114, 366, 114, 50, 114, 58, 114, 495, 496, 490, + 491, 492, 493, 493, 493, 493, 493, 493, 493, 58, + 58, 1612, 58, 114, 58, 114, 58, 114, 114, 1612, + 114, 114, 500, 500, 500, 500, 501, 502, 502, 502, + 502, 502, 1612, 58, 114, 58, 114, 58, 58, 114, + 58, 58, 114, 1612, 506, 506, 506, 506, 506, 506, + 506, 507, 508, 508, 58, 1612, 58, 1408, 1409, 58, + 1411, 1411, 58, 114, 1612, 114, 114, 114, 513, 513, + + 513, 513, 514, 515, 515, 515, 515, 515, 515, 515, + 515, 515, 515, 58, 114, 58, 58, 58, 114, 516, + 517, 518, 519, 519, 519, 519, 519, 519, 519, 114, + 114, 1612, 114, 114, 58, 521, 522, 1612, 58, 528, + 528, 528, 528, 528, 1612, 1612, 114, 114, 114, 58, + 58, 114, 58, 58, 114, 114, 526, 526, 526, 526, + 527, 528, 528, 528, 528, 528, 58, 58, 58, 1493, + 1494, 58, 114, 1612, 58, 58, 114, 532, 532, 532, + 532, 532, 532, 532, 533, 534, 534, 541, 541, 541, + 541, 541, 58, 114, 114, 114, 58, 114, 539, 539, + + 539, 539, 540, 541, 541, 541, 541, 541, 114, 114, + 114, 1612, 213, 58, 58, 58, 1612, 58, 613, 613, + 613, 1612, 548, 549, 1495, 1496, 213, 1612, 58, 58, + 58, 213, 58, 1612, 213, 213, 550, 551, 552, 553, + 553, 553, 553, 553, 553, 553, 58, 213, 1612, 213, + 213, 58, 555, 556, 58, 58, 562, 562, 562, 562, + 562, 1498, 1499, 213, 213, 213, 213, 58, 213, 58, + 58, 574, 575, 560, 560, 560, 560, 561, 562, 562, + 562, 562, 562, 58, 58, 58, 58, 213, 58, 213, + 1612, 213, 213, 213, 566, 566, 566, 566, 566, 566, + + 566, 567, 568, 568, 622, 622, 622, 58, 1612, 58, + 213, 58, 58, 58, 213, 569, 570, 571, 572, 572, + 572, 572, 572, 572, 572, 581, 581, 581, 581, 581, + 58, 213, 213, 1612, 58, 213, 579, 579, 579, 579, + 580, 581, 581, 581, 581, 581, 1500, 1501, 213, 213, + 213, 58, 58, 213, 213, 58, 449, 595, 585, 585, + 585, 585, 585, 585, 585, 586, 587, 587, 58, 58, + 58, 1526, 1527, 58, 58, 213, 325, 325, 452, 1612, + 592, 592, 592, 592, 593, 594, 594, 594, 594, 594, + 594, 594, 594, 594, 594, 58, 452, 1612, 67, 453, + + 597, 1612, 455, 614, 615, 615, 616, 1612, 455, 1612, + 600, 458, 1612, 458, 1612, 602, 67, 453, 138, 1612, + 67, 598, 67, 456, 138, 461, 138, 461, 67, 456, + 67, 67, 459, 67, 459, 67, 603, 605, 1612, 464, + 1612, 233, 348, 233, 348, 67, 462, 67, 462, 464, + 1612, 608, 467, 233, 1612, 142, 1612, 67, 606, 67, + 465, 467, 244, 484, 244, 142, 1612, 142, 66, 67, + 465, 67, 67, 617, 618, 618, 619, 66, 623, 623, + 623, 67, 363, 366, 487, 114, 367, 624, 625, 625, + 626, 627, 628, 628, 629, 630, 630, 630, 631, 631, + + 631, 1612, 366, 114, 50, 58, 50, 114, 637, 638, + 114, 114, 632, 633, 634, 635, 635, 635, 635, 635, + 635, 635, 114, 58, 114, 114, 114, 58, 1528, 1529, + 58, 58, 644, 644, 644, 644, 644, 1612, 114, 114, + 114, 114, 58, 114, 58, 58, 58, 114, 642, 642, + 642, 642, 643, 644, 644, 644, 644, 644, 58, 58, + 58, 58, 1612, 58, 114, 1612, 114, 58, 114, 648, + 648, 648, 648, 648, 648, 648, 649, 650, 650, 657, + 657, 657, 657, 657, 58, 114, 58, 114, 58, 114, + 655, 655, 655, 655, 656, 657, 657, 657, 657, 657, + + 114, 114, 114, 1612, 114, 58, 114, 58, 1612, 58, + 1612, 671, 672, 1612, 664, 665, 1531, 1532, 114, 114, + 58, 58, 58, 114, 58, 114, 58, 114, 666, 667, + 668, 669, 669, 669, 669, 669, 669, 669, 58, 58, + 783, 783, 783, 58, 1612, 58, 114, 58, 114, 114, + 1612, 676, 676, 676, 676, 677, 678, 678, 678, 678, + 678, 678, 678, 678, 678, 678, 58, 114, 58, 58, + 114, 114, 114, 114, 114, 682, 682, 682, 682, 682, + 682, 682, 683, 684, 684, 1533, 1534, 58, 478, 479, + 58, 58, 58, 58, 58, 114, 114, 114, 114, 114, + + 689, 689, 689, 689, 690, 691, 691, 691, 691, 691, + 691, 691, 691, 691, 691, 58, 58, 58, 58, 58, + 114, 114, 114, 114, 114, 114, 114, 114, 114, 708, + 708, 708, 708, 213, 698, 699, 784, 785, 785, 786, + 58, 58, 58, 58, 58, 58, 58, 58, 58, 114, + 1210, 1211, 1612, 58, 706, 706, 706, 707, 708, 708, + 708, 708, 708, 708, 981, 213, 213, 213, 213, 58, + 213, 714, 715, 213, 213, 709, 710, 711, 712, 712, + 712, 712, 712, 712, 712, 58, 58, 58, 58, 1612, + 58, 213, 213, 58, 58, 213, 719, 719, 719, 719, + + 720, 721, 721, 721, 721, 721, 721, 721, 721, 721, + 721, 58, 58, 213, 213, 58, 213, 213, 725, 725, + 725, 725, 725, 725, 725, 726, 727, 727, 213, 1612, + 213, 480, 481, 58, 58, 1612, 58, 58, 734, 734, + 734, 734, 734, 1612, 213, 213, 213, 213, 58, 213, + 58, 740, 741, 213, 732, 732, 732, 732, 733, 734, + 734, 734, 734, 734, 58, 58, 58, 58, 1612, 58, + 213, 1612, 213, 58, 213, 735, 736, 737, 738, 738, + 738, 738, 738, 738, 738, 747, 747, 747, 747, 747, + 58, 213, 58, 213, 58, 213, 745, 745, 745, 745, + + 746, 747, 747, 747, 747, 747, 1612, 213, 213, 213, + 213, 58, 213, 58, 213, 58, 213, 751, 751, 751, + 751, 751, 751, 751, 752, 753, 753, 58, 58, 58, + 58, 1612, 58, 213, 58, 213, 58, 213, 758, 758, + 758, 758, 759, 760, 760, 760, 760, 760, 760, 760, + 760, 760, 760, 58, 213, 58, 213, 58, 595, 597, + 1612, 597, 1612, 770, 1518, 1518, 1519, 767, 768, 600, + 600, 602, 1612, 602, 58, 772, 58, 1612, 325, 67, + 598, 67, 598, 67, 605, 138, 138, 605, 1612, 67, + 67, 67, 603, 67, 603, 67, 773, 775, 608, 608, + + 233, 114, 241, 233, 67, 606, 776, 67, 606, 787, + 788, 788, 789, 233, 142, 142, 114, 67, 67, 67, + 484, 58, 244, 114, 487, 792, 793, 793, 794, 795, + 796, 796, 797, 1523, 1523, 1524, 58, 1551, 1551, 1552, + 366, 114, 114, 58, 50, 114, 803, 804, 114, 114, + 798, 799, 800, 801, 801, 801, 801, 801, 801, 801, + 1612, 58, 58, 345, 345, 58, 114, 114, 58, 58, + 114, 808, 808, 808, 808, 809, 810, 810, 810, 810, + 810, 810, 810, 810, 810, 810, 58, 58, 114, 114, + 58, 114, 114, 814, 814, 814, 814, 814, 814, 814, + + 815, 816, 816, 114, 1612, 114, 114, 114, 58, 58, + 1612, 58, 58, 823, 823, 823, 823, 823, 1612, 114, + 114, 472, 472, 58, 114, 58, 58, 58, 114, 821, + 821, 821, 821, 822, 823, 823, 823, 823, 823, 58, + 58, 830, 831, 114, 58, 114, 114, 114, 58, 114, + 114, 114, 840, 840, 840, 840, 114, 853, 853, 853, + 853, 853, 1612, 58, 1612, 58, 58, 58, 114, 58, + 58, 58, 114, 846, 847, 114, 58, 838, 838, 838, + 839, 840, 840, 840, 840, 840, 840, 1612, 58, 114, + 114, 114, 58, 114, 1612, 58, 114, 114, 841, 842, + + 843, 844, 844, 844, 844, 844, 844, 844, 1612, 58, + 58, 58, 114, 58, 114, 1612, 58, 58, 114, 851, + 851, 851, 851, 852, 853, 853, 853, 853, 853, 1612, + 114, 114, 58, 114, 58, 114, 1612, 114, 58, 114, + 857, 857, 857, 857, 857, 857, 857, 858, 859, 859, + 58, 58, 1612, 58, 1612, 58, 114, 58, 114, 58, + 114, 864, 864, 864, 864, 865, 866, 866, 866, 866, + 866, 866, 866, 866, 866, 866, 58, 114, 58, 114, + 58, 114, 114, 114, 114, 114, 114, 114, 883, 883, + 883, 883, 873, 874, 1556, 1556, 1557, 58, 1612, 58, + + 1612, 58, 58, 58, 58, 58, 58, 58, 114, 114, + 114, 114, 114, 881, 881, 881, 882, 883, 883, 883, + 883, 883, 883, 114, 114, 114, 1612, 114, 58, 58, + 58, 58, 58, 906, 906, 906, 906, 906, 475, 475, + 1612, 213, 213, 58, 58, 58, 114, 58, 476, 476, + 213, 891, 891, 891, 891, 891, 891, 892, 893, 893, + 893, 58, 58, 213, 213, 213, 58, 213, 899, 900, + 58, 213, 894, 895, 896, 897, 897, 897, 897, 897, + 897, 897, 1612, 58, 58, 58, 213, 58, 213, 1612, + 213, 58, 213, 904, 904, 904, 904, 905, 906, 906, + + 906, 906, 906, 1612, 213, 213, 58, 213, 58, 213, + 58, 213, 58, 213, 910, 910, 910, 910, 910, 910, + 910, 911, 912, 912, 58, 58, 1612, 58, 1612, 58, + 213, 58, 213, 58, 213, 917, 917, 917, 917, 918, + 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, + 58, 213, 58, 213, 58, 213, 1612, 213, 213, 213, + 213, 482, 482, 933, 934, 1612, 926, 927, 483, 483, + 1612, 58, 213, 58, 213, 58, 213, 58, 58, 58, + 58, 928, 929, 930, 931, 931, 931, 931, 931, 931, + 931, 1612, 58, 1612, 58, 1612, 58, 213, 213, 213, + + 1612, 213, 938, 938, 938, 938, 939, 940, 940, 940, + 940, 940, 940, 940, 940, 940, 940, 58, 58, 58, + 213, 58, 213, 213, 213, 944, 944, 944, 944, 944, + 944, 944, 945, 946, 946, 213, 1612, 213, 213, 213, + 58, 1612, 58, 58, 58, 953, 953, 953, 953, 953, + 1612, 213, 213, 613, 613, 58, 213, 58, 58, 58, + 213, 951, 951, 951, 951, 952, 953, 953, 953, 953, + 953, 58, 58, 960, 961, 213, 58, 213, 213, 213, + 58, 213, 213, 213, 970, 970, 970, 970, 770, 977, + 978, 978, 979, 622, 622, 58, 1612, 58, 58, 58, + + 770, 58, 58, 58, 213, 772, 1612, 772, 67, 968, + 968, 968, 969, 970, 970, 970, 970, 970, 970, 972, + 67, 775, 775, 114, 58, 67, 773, 67, 773, 348, + 114, 114, 114, 975, 1612, 996, 997, 233, 233, 67, + 363, 67, 67, 58, 114, 985, 985, 986, 367, 244, + 58, 58, 58, 987, 987, 988, 1033, 1033, 1033, 1033, + 366, 623, 623, 1612, 58, 630, 630, 1612, 50, 114, + 1612, 114, 114, 114, 991, 992, 993, 994, 994, 994, + 994, 994, 994, 994, 1003, 1003, 1003, 1003, 1003, 58, + 114, 58, 58, 58, 114, 1001, 1001, 1001, 1001, 1002, + + 1003, 1003, 1003, 1003, 1003, 1612, 114, 114, 114, 114, + 58, 114, 1612, 114, 58, 114, 1007, 1007, 1007, 1007, + 1007, 1007, 1007, 1008, 1009, 1009, 58, 58, 58, 58, + 1612, 58, 114, 58, 114, 58, 114, 1014, 1014, 1014, + 1014, 1015, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, + 1016, 1016, 58, 114, 58, 114, 58, 114, 114, 114, + 114, 114, 114, 114, 1612, 114, 114, 114, 1023, 1024, + 631, 631, 1612, 58, 1612, 58, 1612, 58, 58, 58, + 58, 58, 58, 58, 114, 58, 58, 58, 114, 1031, + 1031, 1031, 1032, 1033, 1033, 1033, 1033, 1033, 1033, 114, + + 114, 114, 1612, 114, 58, 114, 114, 1612, 58, 777, + 777, 1049, 1050, 1086, 1086, 1086, 1086, 114, 114, 58, + 58, 58, 114, 58, 114, 58, 58, 1041, 1041, 1041, + 1041, 1041, 1041, 1042, 1043, 1043, 1043, 58, 58, 781, + 781, 1612, 58, 114, 58, 114, 114, 114, 1044, 1045, + 1046, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1056, 1056, + 1056, 1056, 1056, 58, 114, 58, 58, 58, 114, 1054, + 1054, 1054, 1054, 1055, 1056, 1056, 1056, 1056, 1056, 1612, + 114, 114, 114, 114, 58, 114, 1612, 114, 58, 114, + 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1061, 1062, 1062, + + 58, 58, 58, 58, 1612, 58, 114, 58, 114, 58, + 114, 1067, 1067, 1067, 1067, 1068, 1069, 1069, 1069, 1069, + 1069, 1069, 1069, 1069, 1069, 1069, 58, 114, 58, 114, + 58, 114, 114, 114, 114, 114, 114, 114, 1612, 114, + 114, 114, 1076, 1077, 782, 782, 1612, 58, 1612, 58, + 1612, 58, 58, 58, 58, 58, 58, 58, 114, 58, + 58, 58, 114, 1084, 1084, 1084, 1085, 1086, 1086, 1086, + 1086, 1086, 1086, 114, 114, 114, 1612, 114, 58, 114, + 114, 1612, 58, 1107, 1107, 1107, 1107, 1107, 783, 783, + 1612, 114, 114, 58, 58, 58, 114, 58, 114, 58, + + 58, 1094, 1094, 1094, 1094, 1094, 1094, 1095, 1096, 1096, + 1096, 58, 58, 114, 114, 114, 58, 213, 58, 213, + 213, 790, 790, 1612, 1113, 1114, 1120, 1120, 1120, 1120, + 1120, 213, 213, 58, 58, 58, 114, 58, 213, 58, + 58, 1105, 1105, 1105, 1105, 1106, 1107, 1107, 1107, 1107, + 1107, 58, 58, 213, 213, 213, 58, 213, 58, 213, + 213, 213, 1108, 1109, 1110, 1111, 1111, 1111, 1111, 1111, + 1111, 1111, 1612, 58, 58, 58, 213, 58, 213, 58, + 58, 58, 213, 1118, 1118, 1118, 1118, 1119, 1120, 1120, + 1120, 1120, 1120, 791, 791, 1612, 58, 1612, 58, 213, + + 1612, 213, 58, 213, 1124, 1124, 1124, 1124, 1124, 1124, + 1124, 1125, 1126, 1126, 1133, 1133, 1133, 1133, 1133, 58, + 213, 58, 213, 58, 213, 1131, 1131, 1131, 1131, 1132, + 1133, 1133, 1133, 1133, 1133, 213, 213, 213, 213, 213, + 58, 213, 58, 213, 58, 213, 1612, 213, 1140, 1141, + 1150, 1150, 1150, 1150, 1612, 58, 58, 58, 58, 58, + 1612, 58, 213, 58, 213, 58, 213, 58, 213, 1156, + 1157, 1148, 1148, 1148, 1149, 1150, 1150, 1150, 1150, 1150, + 1150, 1612, 58, 213, 58, 213, 58, 213, 58, 213, + 213, 213, 1151, 1152, 1153, 1154, 1154, 1154, 1154, 1154, + + 1154, 1154, 1612, 58, 1612, 58, 1612, 58, 213, 58, + 58, 58, 213, 1161, 1161, 1161, 1161, 1162, 1163, 1163, + 1163, 1163, 1163, 1163, 1163, 1163, 1163, 1163, 58, 213, + 213, 213, 58, 213, 1167, 1167, 1167, 1167, 1167, 1167, + 1167, 1168, 1169, 1169, 1176, 1176, 1176, 1176, 1176, 58, + 58, 58, 213, 58, 213, 213, 213, 213, 213, 1174, + 1174, 1174, 1174, 1175, 1176, 1176, 1176, 1176, 1176, 213, + 213, 213, 58, 213, 58, 58, 58, 58, 58, 213, + 213, 213, 1183, 1184, 213, 1193, 1193, 1193, 1193, 58, + 58, 58, 1612, 58, 1212, 1213, 1213, 1214, 1612, 58, + + 58, 58, 213, 213, 58, 213, 213, 213, 213, 213, + 1191, 1191, 1191, 1192, 1193, 1193, 1193, 1193, 1193, 1193, + 213, 1612, 58, 58, 213, 58, 58, 58, 58, 58, + 1215, 1215, 1215, 1215, 976, 976, 972, 972, 241, 114, + 58, 213, 983, 983, 58, 1612, 1201, 1201, 1201, 1201, + 1201, 1201, 1202, 1203, 1203, 1203, 67, 67, 244, 58, + 114, 58, 1216, 1216, 1216, 1216, 484, 1612, 114, 487, + 1612, 1217, 1217, 1218, 1219, 1219, 1220, 984, 984, 1612, + 58, 1263, 1263, 1263, 1263, 114, 366, 114, 58, 50, + 114, 1612, 1226, 1227, 114, 1221, 1222, 1223, 1224, 1224, + + 1224, 1224, 1224, 1224, 1224, 58, 1612, 58, 989, 989, + 58, 114, 114, 114, 58, 114, 1231, 1231, 1231, 1231, + 1232, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, + 1233, 58, 58, 58, 114, 58, 114, 114, 114, 1237, + 1237, 1237, 1237, 1237, 1237, 1237, 1238, 1239, 1239, 114, + 1612, 114, 114, 114, 58, 1612, 58, 58, 58, 1246, + 1246, 1246, 1246, 1246, 1612, 114, 114, 990, 990, 58, + 114, 58, 58, 58, 114, 1244, 1244, 1244, 1244, 1245, + 1246, 1246, 1246, 1246, 1246, 58, 58, 1253, 1254, 114, + 58, 114, 114, 114, 58, 114, 114, 114, 1612, 114, + + 114, 114, 114, 1284, 1284, 1284, 1284, 1284, 1612, 58, + 1612, 58, 58, 58, 114, 58, 58, 58, 114, 58, + 58, 58, 58, 1261, 1261, 1261, 1262, 1263, 1263, 1263, + 1263, 1263, 1263, 114, 58, 114, 1612, 114, 58, 114, + 114, 1056, 1056, 1056, 1056, 1056, 1069, 1069, 1069, 1069, + 1069, 114, 114, 58, 114, 58, 114, 58, 114, 58, + 58, 1271, 1271, 1271, 1271, 1271, 1271, 1272, 1273, 1273, + 1273, 58, 58, 114, 58, 114, 58, 114, 58, 114, + 114, 1208, 1208, 1612, 1049, 1050, 1086, 1086, 1086, 1086, + 1612, 114, 114, 58, 114, 58, 114, 58, 114, 58, + + 58, 1282, 1282, 1282, 1282, 1283, 1284, 1284, 1284, 1284, + 1284, 58, 58, 114, 58, 114, 58, 114, 58, 114, + 114, 114, 1044, 1045, 1046, 1047, 1047, 1047, 1047, 1047, + 1047, 1047, 1612, 58, 114, 58, 114, 58, 114, 58, + 58, 58, 114, 1054, 1054, 1054, 1054, 1055, 1056, 1056, + 1056, 1056, 1056, 1612, 58, 114, 58, 114, 58, 114, + 1612, 114, 58, 114, 1060, 1060, 1060, 1060, 1060, 1060, + 1060, 1061, 1062, 1062, 1612, 58, 1612, 58, 114, 58, + 114, 58, 114, 58, 114, 1067, 1067, 1067, 1067, 1068, + 1069, 1069, 1069, 1069, 1069, 1076, 1077, 114, 58, 114, + + 58, 114, 58, 114, 58, 114, 114, 114, 114, 1107, + 1107, 1107, 1107, 1107, 1411, 1411, 1612, 58, 1612, 58, + 114, 58, 114, 58, 114, 58, 58, 58, 58, 1084, + 1084, 1084, 1085, 1086, 1086, 1086, 1086, 1086, 1086, 114, + 58, 114, 58, 114, 58, 1297, 1297, 1297, 1297, 1297, + 1310, 1310, 1310, 1310, 1310, 114, 114, 114, 114, 58, + 114, 58, 114, 58, 114, 1094, 1094, 1094, 1094, 1094, + 1094, 1095, 1096, 1096, 1096, 58, 58, 58, 58, 114, + 58, 114, 58, 213, 58, 1327, 1327, 1327, 1327, 1350, + 1350, 1350, 1350, 1350, 1612, 213, 213, 1612, 213, 58, + + 114, 58, 1612, 58, 213, 1105, 1105, 1105, 1105, 1106, + 1107, 1107, 1107, 1107, 1107, 58, 58, 213, 58, 213, + 58, 213, 1290, 1291, 58, 213, 1285, 1286, 1287, 1288, + 1288, 1288, 1288, 1288, 1288, 1288, 1612, 58, 213, 58, + 213, 58, 213, 1612, 213, 58, 213, 1295, 1295, 1295, + 1295, 1296, 1297, 1297, 1297, 1297, 1297, 1612, 58, 213, + 58, 213, 58, 213, 58, 213, 58, 213, 1301, 1301, + 1301, 1301, 1301, 1301, 1301, 1302, 1303, 1303, 1612, 58, + 213, 58, 213, 58, 213, 58, 213, 58, 213, 1308, + 1308, 1308, 1308, 1309, 1310, 1310, 1310, 1310, 1310, 213, + + 58, 213, 58, 213, 58, 213, 58, 213, 58, 213, + 1612, 213, 1317, 1318, 213, 1380, 1380, 1380, 1380, 58, + 1612, 58, 1612, 58, 1612, 58, 213, 58, 213, 58, + 213, 58, 213, 213, 58, 1325, 1325, 1325, 1326, 1327, + 1327, 1327, 1327, 1327, 1327, 213, 58, 213, 58, 213, + 58, 1612, 58, 58, 1363, 1363, 1363, 1363, 1363, 1516, + 1516, 213, 213, 1612, 213, 58, 213, 58, 1612, 58, + 213, 1335, 1335, 1335, 1335, 1335, 1335, 1336, 1337, 1337, + 1337, 58, 58, 213, 58, 213, 58, 213, 1343, 1344, + 58, 213, 1338, 1339, 1340, 1341, 1341, 1341, 1341, 1341, + + 1341, 1341, 1612, 58, 213, 58, 213, 58, 213, 1612, + 213, 58, 213, 1348, 1348, 1348, 1348, 1349, 1350, 1350, + 1350, 1350, 1350, 1612, 58, 213, 58, 213, 58, 213, + 58, 213, 58, 213, 1354, 1354, 1354, 1354, 1354, 1354, + 1354, 1355, 1356, 1356, 1612, 58, 213, 58, 213, 58, + 213, 58, 213, 58, 213, 1361, 1361, 1361, 1361, 1362, + 1363, 1363, 1363, 1363, 1363, 213, 58, 213, 58, 213, + 58, 213, 58, 213, 58, 213, 1612, 213, 1370, 1371, + 213, 1418, 1418, 1418, 1418, 58, 1612, 58, 1612, 58, + 1612, 58, 213, 58, 213, 58, 213, 58, 213, 213, + + 58, 1378, 1378, 1378, 1379, 1380, 1380, 1380, 1380, 1380, + 1380, 213, 58, 213, 58, 213, 58, 1612, 58, 58, + 1401, 1401, 1401, 1401, 1401, 1518, 1518, 213, 213, 213, + 213, 58, 213, 58, 213, 58, 213, 1388, 1388, 1388, + 1388, 1388, 1388, 1389, 1390, 1390, 1390, 58, 58, 58, + 58, 213, 58, 241, 58, 348, 58, 1419, 1419, 1419, + 1419, 1233, 1233, 1233, 1233, 1233, 1612, 363, 1612, 1412, + 1413, 58, 213, 244, 114, 244, 114, 1399, 1399, 1399, + 1399, 1400, 1401, 1401, 1401, 1401, 1401, 366, 367, 1612, + 1415, 1416, 58, 114, 58, 1612, 58, 1612, 1226, 1227, + + 1263, 1263, 1263, 1263, 114, 114, 114, 114, 50, 114, + 1612, 114, 114, 58, 1221, 1222, 1223, 1224, 1224, 1224, + 1224, 1224, 1224, 1224, 58, 58, 58, 58, 114, 58, + 114, 58, 58, 114, 114, 1231, 1231, 1231, 1231, 1232, + 1233, 1233, 1233, 1233, 1233, 1612, 114, 114, 58, 114, + 58, 114, 1612, 58, 58, 114, 1237, 1237, 1237, 1237, + 1237, 1237, 1237, 1238, 1239, 1239, 58, 58, 1612, 58, + 1612, 58, 114, 114, 114, 58, 114, 1244, 1244, 1244, + 1244, 1245, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, + 1246, 1246, 58, 58, 58, 114, 58, 114, 114, 114, + + 114, 114, 114, 1612, 114, 114, 114, 114, 1253, 1254, + 1284, 1284, 1284, 1284, 1284, 58, 1612, 58, 58, 58, + 58, 58, 58, 114, 58, 58, 58, 58, 1261, 1261, + 1261, 1262, 1263, 1263, 1263, 1263, 1263, 1263, 114, 114, + 114, 1612, 114, 58, 114, 114, 1432, 1432, 1432, 1432, + 1432, 1445, 1445, 1445, 1445, 1445, 114, 114, 58, 58, + 58, 114, 58, 114, 58, 58, 1271, 1271, 1271, 1271, + 1271, 1271, 1272, 1273, 1273, 1273, 58, 58, 114, 114, + 114, 58, 114, 58, 213, 213, 1462, 1462, 1462, 1462, + 1425, 1426, 1380, 1380, 1380, 1380, 213, 213, 58, 58, + + 58, 114, 58, 213, 58, 58, 1282, 1282, 1282, 1282, + 1283, 1284, 1284, 1284, 1284, 1284, 58, 58, 213, 213, + 213, 58, 213, 58, 213, 213, 213, 1420, 1421, 1422, + 1423, 1423, 1423, 1423, 1423, 1423, 1423, 1612, 58, 58, + 58, 213, 58, 213, 58, 58, 58, 213, 1430, 1430, + 1430, 1430, 1431, 1432, 1432, 1432, 1432, 1432, 1612, 213, + 213, 58, 213, 58, 213, 1612, 213, 58, 213, 1436, + 1436, 1436, 1436, 1436, 1436, 1436, 1437, 1438, 1438, 58, + 58, 1612, 58, 213, 58, 213, 58, 213, 58, 213, + 1443, 1443, 1443, 1443, 1444, 1445, 1445, 1445, 1445, 1445, + + 1452, 1453, 213, 58, 213, 58, 213, 58, 213, 58, + 213, 1612, 213, 213, 213, 213, 1483, 1483, 1483, 1483, + 1483, 1612, 58, 1612, 58, 1612, 58, 213, 58, 213, + 58, 213, 58, 58, 58, 58, 1460, 1460, 1460, 1461, + 1462, 1462, 1462, 1462, 1462, 1462, 213, 58, 213, 58, + 213, 58, 1350, 1350, 1350, 1350, 1350, 1363, 1363, 1363, + 1363, 1363, 213, 213, 213, 213, 58, 213, 58, 213, + 58, 213, 1470, 1470, 1470, 1470, 1470, 1470, 1471, 1472, + 1472, 1472, 58, 58, 58, 58, 213, 58, 213, 58, + 213, 58, 1521, 1521, 1612, 1343, 1344, 1401, 1401, 1401, + + 1401, 1401, 213, 213, 213, 213, 58, 213, 58, 213, + 58, 213, 1481, 1481, 1481, 1481, 1482, 1483, 1483, 1483, + 1483, 1483, 58, 58, 58, 58, 213, 58, 213, 58, + 213, 58, 213, 1338, 1339, 1340, 1341, 1341, 1341, 1341, + 1341, 1341, 1341, 1612, 213, 213, 58, 213, 58, 213, + 58, 213, 58, 213, 1348, 1348, 1348, 1348, 1349, 1350, + 1350, 1350, 1350, 1350, 58, 58, 213, 58, 213, 58, + 213, 58, 213, 58, 213, 1354, 1354, 1354, 1354, 1354, + 1354, 1354, 1355, 1356, 1356, 1612, 58, 1612, 58, 213, + 58, 213, 58, 213, 58, 213, 1361, 1361, 1361, 1361, + + 1362, 1363, 1363, 1363, 1363, 1363, 1370, 1371, 213, 58, + 213, 58, 213, 58, 213, 58, 213, 213, 1490, 1490, + 1490, 1490, 1490, 1492, 1492, 1492, 1492, 1492, 58, 213, + 58, 213, 58, 213, 58, 213, 58, 58, 1378, 1378, + 1378, 1379, 1380, 1380, 1380, 1380, 1380, 1380, 213, 58, + 213, 58, 213, 58, 1612, 58, 1432, 1432, 1432, 1432, + 1432, 1523, 1523, 1612, 213, 213, 213, 213, 58, 213, + 58, 213, 58, 213, 1388, 1388, 1388, 1388, 1388, 1388, + 1389, 1390, 1390, 1390, 58, 58, 58, 58, 213, 58, + 213, 58, 241, 58, 1445, 1445, 1445, 1445, 1445, 1462, + + 1462, 1462, 1462, 1612, 348, 1612, 213, 1612, 58, 213, + 58, 213, 244, 1612, 1399, 1399, 1399, 1399, 1400, 1401, + 1401, 1401, 1401, 1401, 244, 484, 58, 1503, 1504, 58, + 487, 58, 1506, 1507, 213, 213, 1541, 1541, 1612, 1425, + 1426, 1597, 1597, 1597, 1597, 366, 213, 213, 213, 213, + 50, 213, 1612, 213, 58, 58, 1420, 1421, 1422, 1423, + 1423, 1423, 1423, 1423, 1423, 1423, 58, 58, 58, 58, + 213, 58, 213, 58, 213, 213, 213, 1430, 1430, 1430, + 1430, 1431, 1432, 1432, 1432, 1432, 1432, 1612, 213, 213, + 58, 213, 58, 213, 58, 58, 58, 213, 1436, 1436, + + 1436, 1436, 1436, 1436, 1436, 1437, 1438, 1438, 58, 58, + 213, 58, 1612, 58, 213, 213, 213, 58, 213, 1443, + 1443, 1443, 1443, 1444, 1445, 1445, 1445, 1445, 1445, 213, + 58, 1452, 1453, 213, 58, 58, 58, 213, 58, 213, + 213, 1612, 213, 213, 213, 213, 1545, 1545, 1612, 58, + 1549, 1549, 1612, 58, 1551, 1551, 213, 58, 213, 58, + 58, 213, 58, 58, 58, 58, 1460, 1460, 1460, 1461, + 1462, 1462, 1462, 1462, 1462, 1462, 58, 213, 58, 213, + 213, 58, 213, 1483, 1483, 1483, 1483, 1483, 1516, 1516, + 1516, 1516, 1517, 213, 213, 213, 213, 58, 213, 58, + + 58, 213, 58, 1470, 1470, 1470, 1470, 1470, 1470, 1471, + 1472, 1472, 1472, 58, 58, 58, 58, 213, 58, 213, + 241, 58, 348, 1521, 1521, 1521, 1521, 1522, 1549, 1549, + 1549, 1549, 1550, 363, 1612, 1412, 1413, 58, 213, 58, + 244, 241, 244, 1481, 1481, 1481, 1481, 1482, 1483, 1483, + 1483, 1483, 1483, 366, 367, 348, 1415, 1416, 58, 241, + 484, 244, 1503, 1504, 1554, 1554, 1554, 1554, 1555, 487, + 348, 1506, 1507, 1612, 50, 244, 348, 363, 367, 244, + 366, 363, 1612, 1412, 1413, 1564, 1583, 1554, 1554, 50, + 244, 367, 1612, 1415, 1416, 1566, 244, 366, 50, 484, + + 484, 366, 1503, 1504, 1580, 487, 1584, 1506, 1507, 1582, + 363, 50, 1412, 1413, 367, 487, 1415, 1416, 1583, 366, + 366, 1590, 1590, 1591, 1592, 50, 363, 1612, 1412, 1413, + 366, 1556, 1556, 1592, 50, 50, 1584, 367, 1584, 1415, + 1416, 1567, 1567, 1612, 1584, 484, 366, 1503, 1504, 487, + 1612, 1506, 1507, 1584, 1571, 1571, 363, 50, 1412, 1413, + 367, 1612, 1415, 1416, 484, 366, 1503, 1504, 487, 50, + 1506, 1507, 363, 1612, 1412, 1413, 366, 1612, 1612, 367, + 50, 1415, 1416, 484, 366, 1503, 1504, 487, 50, 1506, + 1507, 363, 366, 1412, 1413, 367, 1612, 1415, 1416, 50, + + 1612, 1612, 484, 366, 1503, 1504, 487, 50, 1506, 1507, + 363, 366, 1412, 1413, 367, 50, 1415, 1416, 484, 1612, + 1503, 1504, 366, 1612, 1612, 487, 50, 1506, 1507, 484, + 366, 1503, 1504, 487, 50, 1506, 1507, 1612, 366, 1612, + 1612, 1612, 1612, 1612, 1612, 50, 1612, 1612, 1612, 366, + 1612, 1612, 1612, 50, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 31, 31, 31, 31, 31, 31, 31, 31, 31, + 31, 31, 31, 31, 31, 33, 33, 33, 1612, 1612, + 1612, 1612, 33, 36, 1612, 1612, 1612, 36, 36, 36, + + 1612, 1612, 36, 36, 36, 38, 38, 38, 1612, 1612, + 1612, 1612, 38, 45, 1612, 45, 45, 45, 45, 45, + 1612, 1612, 1612, 1612, 45, 47, 47, 47, 1612, 1612, + 1612, 1612, 47, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 62, 62, + 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, + 62, 62, 62, 62, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 72, + 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, + 72, 1612, 72, 72, 74, 74, 74, 1612, 1612, 1612, + + 1612, 74, 76, 76, 76, 76, 76, 76, 76, 76, + 76, 76, 1612, 76, 76, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, 78, 80, + 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, + 80, 80, 80, 81, 81, 81, 82, 82, 82, 1612, + 1612, 1612, 1612, 82, 86, 1612, 1612, 1612, 86, 86, + 86, 1612, 1612, 86, 86, 86, 87, 87, 87, 91, + 91, 91, 1612, 1612, 1612, 1612, 91, 94, 94, 94, + 97, 1612, 1612, 97, 97, 97, 97, 1612, 1612, 1612, + 97, 97, 1612, 97, 102, 1612, 102, 102, 102, 102, + + 102, 1612, 1612, 1612, 1612, 102, 103, 103, 103, 107, + 107, 107, 1612, 1612, 1612, 1612, 107, 113, 113, 113, + 119, 1612, 1612, 1612, 119, 119, 119, 1612, 1612, 1612, + 1612, 119, 122, 1612, 1612, 1612, 122, 122, 122, 1612, + 1612, 1612, 1612, 122, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 136, + 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, + 136, 136, 136, 136, 140, 140, 140, 140, 140, 140, + 140, 140, 140, 140, 140, 140, 140, 140, 140, 144, + 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, + + 144, 144, 144, 144, 147, 147, 147, 152, 152, 152, + 152, 1612, 1612, 1612, 1612, 152, 154, 154, 154, 1612, + 1612, 1612, 1612, 154, 157, 157, 157, 157, 157, 157, + 157, 157, 157, 157, 157, 157, 157, 157, 158, 158, + 158, 159, 159, 159, 162, 162, 162, 164, 164, 164, + 166, 166, 166, 171, 1612, 1612, 1612, 171, 171, 171, + 1612, 1612, 1612, 171, 171, 1612, 171, 174, 1612, 174, + 174, 174, 175, 175, 175, 178, 1612, 1612, 178, 178, + 178, 178, 1612, 1612, 1612, 178, 178, 1612, 178, 180, + 180, 180, 182, 182, 182, 184, 184, 184, 192, 1612, + + 1612, 1612, 192, 192, 192, 1612, 1612, 1612, 1612, 192, + 195, 1612, 1612, 1612, 195, 195, 195, 1612, 1612, 1612, + 1612, 195, 200, 1612, 1612, 1612, 200, 200, 200, 1612, + 1612, 1612, 1612, 200, 203, 1612, 1612, 1612, 203, 203, + 203, 1612, 1612, 1612, 1612, 203, 204, 1612, 1612, 1612, + 204, 204, 204, 1612, 1612, 1612, 1612, 204, 205, 1612, + 1612, 1612, 205, 205, 205, 1612, 1612, 1612, 1612, 205, + 212, 212, 212, 218, 1612, 1612, 1612, 218, 218, 218, + 1612, 1612, 1612, 1612, 218, 221, 1612, 1612, 1612, 221, + 221, 221, 1612, 1612, 1612, 1612, 221, 59, 59, 59, + + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 62, 62, 62, + 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, + 62, 62, 62, 136, 136, 136, 136, 136, 136, 136, + 136, 136, 136, 136, 136, 136, 136, 136, 225, 225, + 225, 225, 225, 225, 225, 225, 225, 1612, 225, 225, + 225, 225, 225, 228, 228, 228, 228, 228, 228, 228, + 228, 228, 228, 228, 228, 228, 228, 228, 140, 140, + 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, + + 140, 140, 140, 231, 231, 231, 231, 231, 231, 231, + 231, 231, 231, 231, 231, 231, 231, 231, 235, 235, + 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, + 235, 235, 235, 144, 144, 144, 144, 144, 144, 144, + 144, 144, 144, 144, 144, 144, 144, 144, 238, 238, + 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, + 238, 238, 238, 242, 1612, 1612, 1612, 242, 242, 1612, + 242, 1612, 1612, 1612, 242, 245, 245, 245, 72, 72, + 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, + 1612, 72, 72, 74, 74, 74, 152, 152, 152, 152, + + 1612, 1612, 1612, 1612, 152, 247, 247, 247, 247, 1612, + 1612, 1612, 1612, 247, 157, 157, 157, 157, 157, 157, + 157, 157, 157, 157, 157, 157, 157, 157, 249, 249, + 249, 86, 1612, 1612, 1612, 86, 86, 86, 1612, 1612, + 86, 86, 86, 250, 250, 250, 251, 251, 251, 252, + 252, 252, 254, 254, 254, 257, 1612, 257, 257, 257, + 171, 1612, 1612, 1612, 171, 171, 171, 1612, 1612, 1612, + 171, 171, 1612, 171, 259, 1612, 259, 259, 259, 174, + 174, 174, 175, 1612, 1612, 1612, 175, 175, 175, 1612, + 1612, 1612, 175, 175, 1612, 175, 261, 1612, 1612, 1612, + + 261, 261, 261, 1612, 1612, 1612, 261, 261, 1612, 261, + 178, 1612, 1612, 178, 178, 178, 178, 1612, 1612, 1612, + 178, 178, 1612, 178, 264, 1612, 264, 264, 264, 265, + 265, 265, 266, 266, 266, 267, 267, 267, 269, 269, + 269, 275, 1612, 1612, 1612, 275, 275, 275, 1612, 1612, + 1612, 1612, 275, 278, 1612, 1612, 1612, 278, 278, 278, + 1612, 1612, 1612, 1612, 278, 279, 1612, 1612, 1612, 279, + 279, 279, 1612, 1612, 1612, 1612, 279, 280, 1612, 1612, + 1612, 280, 280, 280, 1612, 1612, 1612, 1612, 280, 288, + 1612, 1612, 1612, 288, 288, 288, 1612, 1612, 1612, 1612, + + 288, 291, 1612, 1612, 1612, 291, 291, 291, 1612, 1612, + 1612, 1612, 291, 292, 1612, 1612, 1612, 292, 292, 292, + 1612, 1612, 1612, 1612, 292, 293, 1612, 1612, 1612, 293, + 293, 293, 1612, 1612, 1612, 1612, 293, 297, 1612, 1612, + 1612, 297, 297, 297, 1612, 1612, 1612, 1612, 297, 298, + 1612, 1612, 1612, 298, 298, 298, 1612, 1612, 1612, 1612, + 298, 299, 1612, 1612, 1612, 299, 299, 299, 1612, 1612, + 1612, 1612, 299, 302, 1612, 1612, 1612, 302, 302, 302, + 1612, 1612, 1612, 1612, 302, 307, 1612, 1612, 1612, 307, + 307, 307, 1612, 1612, 1612, 1612, 307, 310, 1612, 1612, + + 1612, 310, 310, 310, 1612, 1612, 1612, 1612, 310, 315, + 1612, 1612, 1612, 315, 315, 315, 1612, 1612, 1612, 1612, + 315, 318, 1612, 1612, 1612, 318, 318, 318, 1612, 1612, + 1612, 1612, 318, 319, 1612, 1612, 1612, 319, 319, 319, + 1612, 1612, 1612, 1612, 319, 320, 1612, 1612, 1612, 320, + 320, 320, 1612, 1612, 1612, 1612, 320, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 324, 324, 324, 324, 324, 324, 324, 324, + 324, 1612, 324, 324, 324, 1612, 324, 225, 225, 225, + 225, 225, 225, 225, 225, 225, 1612, 225, 225, 225, + + 225, 225, 326, 326, 326, 326, 326, 326, 326, 326, + 326, 1612, 326, 326, 326, 326, 326, 228, 228, 228, + 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, + 228, 228, 329, 329, 329, 329, 329, 329, 329, 329, + 329, 329, 329, 329, 329, 329, 329, 231, 231, 231, + 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, + 231, 231, 332, 332, 332, 332, 332, 332, 332, 332, + 332, 1612, 332, 332, 332, 332, 332, 335, 335, 335, + 335, 335, 335, 335, 335, 335, 335, 335, 335, 335, + 335, 335, 235, 235, 235, 235, 235, 235, 235, 235, + + 235, 235, 235, 235, 235, 235, 235, 338, 338, 338, + 338, 338, 338, 338, 338, 338, 338, 338, 338, 338, + 338, 338, 238, 238, 238, 238, 238, 238, 238, 238, + 238, 238, 238, 238, 238, 238, 238, 341, 341, 341, + 341, 341, 341, 341, 341, 341, 341, 341, 341, 341, + 341, 341, 344, 344, 344, 349, 1612, 1612, 1612, 349, + 349, 1612, 349, 1612, 1612, 1612, 349, 154, 154, 154, + 247, 247, 247, 247, 1612, 1612, 1612, 1612, 247, 357, + 357, 357, 358, 358, 358, 257, 257, 257, 259, 259, + 259, 360, 1612, 360, 360, 360, 261, 1612, 1612, 1612, + + 261, 261, 261, 1612, 1612, 1612, 261, 261, 1612, 261, + 362, 1612, 362, 362, 362, 264, 264, 264, 370, 370, + 370, 371, 371, 371, 376, 1612, 1612, 1612, 376, 376, + 376, 1612, 1612, 1612, 1612, 376, 379, 1612, 1612, 1612, + 379, 379, 379, 1612, 1612, 1612, 1612, 379, 380, 1612, + 1612, 1612, 380, 380, 380, 1612, 1612, 1612, 1612, 380, + 381, 1612, 1612, 1612, 381, 381, 381, 1612, 1612, 1612, + 1612, 381, 385, 1612, 1612, 1612, 385, 385, 385, 1612, + 1612, 1612, 1612, 385, 386, 1612, 1612, 1612, 386, 386, + 386, 1612, 1612, 1612, 1612, 386, 387, 1612, 1612, 1612, + + 387, 387, 387, 1612, 1612, 1612, 1612, 387, 390, 1612, + 1612, 1612, 390, 390, 390, 1612, 1612, 1612, 1612, 390, + 395, 1612, 1612, 1612, 395, 395, 395, 1612, 1612, 1612, + 1612, 395, 398, 1612, 1612, 1612, 398, 398, 398, 1612, + 1612, 1612, 1612, 398, 399, 1612, 1612, 1612, 399, 399, + 399, 1612, 1612, 1612, 1612, 399, 400, 1612, 1612, 1612, + 400, 400, 400, 1612, 1612, 1612, 1612, 400, 404, 1612, + 1612, 1612, 404, 404, 404, 1612, 1612, 1612, 1612, 404, + 405, 1612, 1612, 1612, 405, 405, 405, 1612, 1612, 1612, + 1612, 405, 406, 1612, 1612, 1612, 406, 406, 406, 1612, + + 1612, 1612, 1612, 406, 409, 1612, 1612, 1612, 409, 409, + 409, 1612, 1612, 1612, 1612, 409, 410, 1612, 1612, 1612, + 410, 410, 410, 1612, 1612, 1612, 1612, 410, 411, 1612, + 1612, 1612, 411, 411, 411, 1612, 1612, 1612, 1612, 411, + 412, 1612, 1612, 1612, 412, 412, 412, 1612, 1612, 1612, + 1612, 412, 413, 1612, 1612, 1612, 413, 413, 413, 1612, + 1612, 1612, 1612, 413, 421, 1612, 1612, 1612, 421, 421, + 421, 1612, 1612, 1612, 1612, 421, 424, 1612, 1612, 1612, + 424, 424, 424, 1612, 1612, 1612, 1612, 424, 425, 1612, + 1612, 1612, 425, 425, 425, 1612, 1612, 1612, 1612, 425, + + 426, 1612, 1612, 1612, 426, 426, 426, 1612, 1612, 1612, + 1612, 426, 434, 1612, 1612, 1612, 434, 434, 434, 1612, + 1612, 1612, 1612, 434, 437, 1612, 1612, 1612, 437, 437, + 437, 1612, 1612, 1612, 1612, 437, 438, 1612, 1612, 1612, + 438, 438, 438, 1612, 1612, 1612, 1612, 438, 439, 1612, + 1612, 1612, 439, 439, 439, 1612, 1612, 1612, 1612, 439, + 443, 1612, 1612, 1612, 443, 443, 443, 1612, 1612, 1612, + 1612, 443, 444, 1612, 1612, 1612, 444, 444, 444, 1612, + 1612, 1612, 1612, 444, 445, 1612, 1612, 1612, 445, 445, + 445, 1612, 1612, 1612, 1612, 445, 448, 1612, 1612, 1612, + + 448, 448, 448, 1612, 1612, 1612, 1612, 448, 324, 324, + 324, 324, 324, 324, 324, 324, 324, 1612, 324, 324, + 324, 1612, 324, 450, 450, 450, 450, 450, 450, 450, + 450, 450, 1612, 450, 450, 450, 1612, 450, 326, 326, + 326, 326, 326, 326, 326, 326, 326, 1612, 326, 326, + 326, 326, 326, 451, 451, 451, 451, 451, 451, 451, + 451, 451, 1612, 451, 451, 451, 451, 451, 329, 329, + 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, + 329, 329, 329, 454, 454, 454, 454, 454, 454, 454, + 454, 454, 454, 454, 454, 454, 454, 454, 332, 332, + + 332, 332, 332, 332, 332, 332, 332, 1612, 332, 332, + 332, 332, 332, 457, 457, 457, 457, 457, 457, 457, + 457, 457, 1612, 457, 457, 457, 457, 457, 335, 335, + 335, 335, 335, 335, 335, 335, 335, 335, 335, 335, + 335, 335, 335, 460, 460, 460, 460, 460, 460, 460, + 460, 460, 460, 460, 460, 460, 460, 460, 338, 338, + 338, 338, 338, 338, 338, 338, 338, 338, 338, 338, + 338, 338, 338, 463, 463, 463, 463, 463, 463, 463, + 463, 463, 463, 463, 463, 463, 463, 463, 341, 341, + 341, 341, 341, 341, 341, 341, 341, 341, 341, 341, + + 341, 341, 341, 466, 466, 466, 466, 466, 466, 466, + 466, 466, 466, 466, 466, 466, 1612, 466, 468, 1612, + 1612, 1612, 468, 468, 1612, 1612, 1612, 1612, 1612, 468, + 469, 469, 469, 470, 470, 470, 471, 471, 471, 360, + 360, 360, 362, 362, 362, 107, 107, 107, 1612, 1612, + 1612, 1612, 107, 494, 1612, 1612, 1612, 494, 494, 494, + 1612, 1612, 1612, 1612, 494, 497, 1612, 1612, 1612, 497, + 497, 497, 1612, 1612, 1612, 1612, 497, 498, 1612, 1612, + 1612, 498, 498, 498, 1612, 1612, 1612, 1612, 498, 499, + 1612, 1612, 1612, 499, 499, 499, 1612, 1612, 1612, 1612, + + 499, 503, 1612, 1612, 1612, 503, 503, 503, 1612, 1612, + 1612, 1612, 503, 504, 1612, 1612, 1612, 504, 504, 504, + 1612, 1612, 1612, 1612, 504, 505, 1612, 1612, 1612, 505, + 505, 505, 1612, 1612, 1612, 1612, 505, 508, 1612, 1612, + 1612, 508, 508, 508, 1612, 1612, 1612, 1612, 508, 509, + 1612, 1612, 1612, 509, 509, 509, 1612, 1612, 1612, 1612, + 509, 510, 1612, 1612, 1612, 510, 510, 510, 1612, 1612, + 1612, 1612, 510, 511, 1612, 1612, 1612, 511, 511, 511, + 1612, 1612, 1612, 1612, 511, 512, 1612, 1612, 1612, 512, + 512, 512, 1612, 1612, 1612, 1612, 512, 520, 1612, 1612, + + 1612, 520, 520, 520, 1612, 1612, 1612, 1612, 520, 523, + 1612, 1612, 1612, 523, 523, 523, 1612, 1612, 1612, 1612, + 523, 524, 1612, 1612, 1612, 524, 524, 524, 1612, 1612, + 1612, 1612, 524, 525, 1612, 1612, 1612, 525, 525, 525, + 1612, 1612, 1612, 1612, 525, 529, 1612, 1612, 1612, 529, + 529, 529, 1612, 1612, 1612, 1612, 529, 530, 1612, 1612, + 1612, 530, 530, 530, 1612, 1612, 1612, 1612, 530, 531, + 1612, 1612, 1612, 531, 531, 531, 1612, 1612, 1612, 1612, + 531, 534, 1612, 1612, 1612, 534, 534, 534, 1612, 1612, + 1612, 1612, 534, 535, 1612, 1612, 1612, 535, 535, 535, + + 1612, 1612, 1612, 1612, 535, 536, 1612, 1612, 1612, 536, + 536, 536, 1612, 1612, 1612, 1612, 536, 537, 1612, 1612, + 1612, 537, 537, 537, 1612, 1612, 1612, 1612, 537, 538, + 1612, 1612, 1612, 538, 538, 538, 1612, 1612, 1612, 1612, + 538, 542, 1612, 1612, 1612, 542, 542, 542, 1612, 1612, + 1612, 1612, 542, 543, 1612, 1612, 1612, 543, 543, 543, + 1612, 1612, 1612, 1612, 543, 544, 1612, 1612, 1612, 544, + 544, 544, 1612, 1612, 1612, 1612, 544, 545, 1612, 1612, + 1612, 545, 545, 545, 1612, 1612, 1612, 1612, 545, 546, + 1612, 1612, 1612, 546, 546, 546, 1612, 1612, 1612, 1612, + + 546, 547, 1612, 1612, 1612, 547, 547, 547, 1612, 1612, + 1612, 1612, 547, 549, 1612, 1612, 1612, 549, 549, 549, + 1612, 1612, 1612, 1612, 549, 554, 1612, 1612, 1612, 554, + 554, 554, 1612, 1612, 1612, 1612, 554, 557, 1612, 1612, + 1612, 557, 557, 557, 1612, 1612, 1612, 1612, 557, 558, + 1612, 1612, 1612, 558, 558, 558, 1612, 1612, 1612, 1612, + 558, 559, 1612, 1612, 1612, 559, 559, 559, 1612, 1612, + 1612, 1612, 559, 563, 1612, 1612, 1612, 563, 563, 563, + 1612, 1612, 1612, 1612, 563, 564, 1612, 1612, 1612, 564, + 564, 564, 1612, 1612, 1612, 1612, 564, 565, 1612, 1612, + + 1612, 565, 565, 565, 1612, 1612, 1612, 1612, 565, 568, + 1612, 1612, 1612, 568, 568, 568, 1612, 1612, 1612, 1612, + 568, 573, 1612, 1612, 1612, 573, 573, 573, 1612, 1612, + 1612, 1612, 573, 576, 1612, 1612, 1612, 576, 576, 576, + 1612, 1612, 1612, 1612, 576, 577, 1612, 1612, 1612, 577, + 577, 577, 1612, 1612, 1612, 1612, 577, 578, 1612, 1612, + 1612, 578, 578, 578, 1612, 1612, 1612, 1612, 578, 582, + 1612, 1612, 1612, 582, 582, 582, 1612, 1612, 1612, 1612, + 582, 583, 1612, 1612, 1612, 583, 583, 583, 1612, 1612, + 1612, 1612, 583, 584, 1612, 1612, 1612, 584, 584, 584, + + 1612, 1612, 1612, 1612, 584, 587, 1612, 1612, 1612, 587, + 587, 587, 1612, 1612, 1612, 1612, 587, 588, 1612, 1612, + 1612, 588, 588, 588, 1612, 1612, 1612, 1612, 588, 589, + 1612, 1612, 1612, 589, 589, 589, 1612, 1612, 1612, 1612, + 589, 590, 1612, 1612, 1612, 590, 590, 590, 1612, 1612, + 1612, 1612, 590, 591, 1612, 1612, 1612, 591, 591, 591, + 1612, 1612, 1612, 1612, 591, 324, 324, 324, 324, 324, + 324, 324, 324, 324, 1612, 324, 324, 324, 1612, 324, + 450, 450, 450, 450, 450, 450, 450, 450, 450, 1612, + 450, 450, 450, 1612, 450, 451, 451, 451, 451, 451, + + 451, 451, 451, 451, 1612, 451, 451, 451, 451, 451, + 596, 596, 596, 596, 596, 596, 596, 596, 596, 1612, + 596, 596, 596, 596, 596, 454, 454, 454, 454, 454, + 454, 454, 454, 454, 454, 454, 454, 454, 454, 454, + 599, 599, 599, 599, 599, 599, 599, 599, 599, 599, + 599, 599, 599, 1612, 599, 457, 457, 457, 457, 457, + 457, 457, 457, 457, 1612, 457, 457, 457, 457, 457, + 601, 601, 601, 601, 601, 601, 601, 601, 601, 1612, + 601, 601, 601, 601, 601, 460, 460, 460, 460, 460, + 460, 460, 460, 460, 460, 460, 460, 460, 460, 460, + + 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, + 604, 604, 604, 604, 604, 463, 463, 463, 463, 463, + 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, + 607, 607, 607, 607, 607, 607, 607, 607, 607, 607, + 607, 607, 607, 1612, 607, 466, 466, 466, 466, 466, + 466, 466, 466, 466, 466, 466, 466, 466, 1612, 466, + 609, 609, 609, 349, 1612, 1612, 1612, 349, 349, 1612, + 1612, 1612, 1612, 1612, 349, 611, 1612, 1612, 1612, 611, + 611, 1612, 1612, 1612, 1612, 1612, 611, 612, 612, 612, + 636, 1612, 1612, 1612, 636, 636, 636, 1612, 1612, 1612, + + 1612, 636, 639, 1612, 1612, 1612, 639, 639, 639, 1612, + 1612, 1612, 1612, 639, 640, 1612, 1612, 1612, 640, 640, + 640, 1612, 1612, 1612, 1612, 640, 641, 1612, 1612, 1612, + 641, 641, 641, 1612, 1612, 1612, 1612, 641, 645, 1612, + 1612, 1612, 645, 645, 645, 1612, 1612, 1612, 1612, 645, + 646, 1612, 1612, 1612, 646, 646, 646, 1612, 1612, 1612, + 1612, 646, 647, 1612, 1612, 1612, 647, 647, 647, 1612, + 1612, 1612, 1612, 647, 650, 1612, 1612, 1612, 650, 650, + 650, 1612, 1612, 1612, 1612, 650, 651, 1612, 1612, 1612, + 651, 651, 651, 1612, 1612, 1612, 1612, 651, 652, 1612, + + 1612, 1612, 652, 652, 652, 1612, 1612, 1612, 1612, 652, + 653, 1612, 1612, 1612, 653, 653, 653, 1612, 1612, 1612, + 1612, 653, 654, 1612, 1612, 1612, 654, 654, 654, 1612, + 1612, 1612, 1612, 654, 658, 1612, 1612, 1612, 658, 658, + 658, 1612, 1612, 1612, 1612, 658, 659, 1612, 1612, 1612, + 659, 659, 659, 1612, 1612, 1612, 1612, 659, 660, 1612, + 1612, 1612, 660, 660, 660, 1612, 1612, 1612, 1612, 660, + 661, 1612, 1612, 1612, 661, 661, 661, 1612, 1612, 1612, + 1612, 661, 662, 1612, 1612, 1612, 662, 662, 662, 1612, + 1612, 1612, 1612, 662, 663, 1612, 1612, 1612, 663, 663, + + 663, 1612, 1612, 1612, 1612, 663, 665, 1612, 1612, 1612, + 665, 665, 665, 1612, 1612, 1612, 1612, 665, 670, 1612, + 1612, 1612, 670, 670, 670, 1612, 1612, 1612, 1612, 670, + 673, 1612, 1612, 1612, 673, 673, 673, 1612, 1612, 1612, + 1612, 673, 674, 1612, 1612, 1612, 674, 674, 674, 1612, + 1612, 1612, 1612, 674, 675, 1612, 1612, 1612, 675, 675, + 675, 1612, 1612, 1612, 1612, 675, 679, 1612, 1612, 1612, + 679, 679, 679, 1612, 1612, 1612, 1612, 679, 680, 1612, + 1612, 1612, 680, 680, 680, 1612, 1612, 1612, 1612, 680, + 681, 1612, 1612, 1612, 681, 681, 681, 1612, 1612, 1612, + + 1612, 681, 684, 1612, 1612, 1612, 684, 684, 684, 1612, + 1612, 1612, 1612, 684, 685, 1612, 1612, 1612, 685, 685, + 685, 1612, 1612, 1612, 1612, 685, 686, 1612, 1612, 1612, + 686, 686, 686, 1612, 1612, 1612, 1612, 686, 687, 1612, + 1612, 1612, 687, 687, 687, 1612, 1612, 1612, 1612, 687, + 688, 1612, 1612, 1612, 688, 688, 688, 1612, 1612, 1612, + 1612, 688, 692, 1612, 1612, 1612, 692, 692, 692, 1612, + 1612, 1612, 1612, 692, 693, 1612, 1612, 1612, 693, 693, + 693, 1612, 1612, 1612, 1612, 693, 694, 1612, 1612, 1612, + 694, 694, 694, 1612, 1612, 1612, 1612, 694, 695, 1612, + + 1612, 1612, 695, 695, 695, 1612, 1612, 1612, 1612, 695, + 696, 1612, 1612, 1612, 696, 696, 696, 1612, 1612, 1612, + 1612, 696, 697, 1612, 1612, 1612, 697, 697, 697, 1612, + 1612, 1612, 1612, 697, 699, 1612, 1612, 1612, 699, 699, + 699, 1612, 1612, 1612, 1612, 699, 700, 1612, 1612, 1612, + 700, 700, 700, 1612, 1612, 1612, 1612, 700, 701, 1612, + 1612, 1612, 701, 701, 701, 1612, 1612, 1612, 1612, 701, + 702, 1612, 1612, 1612, 702, 702, 702, 1612, 1612, 1612, + 1612, 702, 703, 1612, 1612, 1612, 703, 703, 703, 1612, + 1612, 1612, 1612, 703, 704, 1612, 1612, 1612, 704, 704, + + 704, 1612, 1612, 1612, 1612, 704, 705, 1612, 1612, 1612, + 705, 705, 705, 1612, 1612, 1612, 1612, 705, 713, 1612, + 1612, 1612, 713, 713, 713, 1612, 1612, 1612, 1612, 713, + 716, 1612, 1612, 1612, 716, 716, 716, 1612, 1612, 1612, + 1612, 716, 717, 1612, 1612, 1612, 717, 717, 717, 1612, + 1612, 1612, 1612, 717, 718, 1612, 1612, 1612, 718, 718, + 718, 1612, 1612, 1612, 1612, 718, 722, 1612, 1612, 1612, + 722, 722, 722, 1612, 1612, 1612, 1612, 722, 723, 1612, + 1612, 1612, 723, 723, 723, 1612, 1612, 1612, 1612, 723, + 724, 1612, 1612, 1612, 724, 724, 724, 1612, 1612, 1612, + + 1612, 724, 727, 1612, 1612, 1612, 727, 727, 727, 1612, + 1612, 1612, 1612, 727, 728, 1612, 1612, 1612, 728, 728, + 728, 1612, 1612, 1612, 1612, 728, 729, 1612, 1612, 1612, + 729, 729, 729, 1612, 1612, 1612, 1612, 729, 730, 1612, + 1612, 1612, 730, 730, 730, 1612, 1612, 1612, 1612, 730, + 731, 1612, 1612, 1612, 731, 731, 731, 1612, 1612, 1612, + 1612, 731, 739, 1612, 1612, 1612, 739, 739, 739, 1612, + 1612, 1612, 1612, 739, 742, 1612, 1612, 1612, 742, 742, + 742, 1612, 1612, 1612, 1612, 742, 743, 1612, 1612, 1612, + 743, 743, 743, 1612, 1612, 1612, 1612, 743, 744, 1612, + + 1612, 1612, 744, 744, 744, 1612, 1612, 1612, 1612, 744, + 748, 1612, 1612, 1612, 748, 748, 748, 1612, 1612, 1612, + 1612, 748, 749, 1612, 1612, 1612, 749, 749, 749, 1612, + 1612, 1612, 1612, 749, 750, 1612, 1612, 1612, 750, 750, + 750, 1612, 1612, 1612, 1612, 750, 753, 1612, 1612, 1612, + 753, 753, 753, 1612, 1612, 1612, 1612, 753, 754, 1612, + 1612, 1612, 754, 754, 754, 1612, 1612, 1612, 1612, 754, + 755, 1612, 1612, 1612, 755, 755, 755, 1612, 1612, 1612, + 1612, 755, 756, 1612, 1612, 1612, 756, 756, 756, 1612, + 1612, 1612, 1612, 756, 757, 1612, 1612, 1612, 757, 757, + + 757, 1612, 1612, 1612, 1612, 757, 761, 1612, 1612, 1612, + 761, 761, 761, 1612, 1612, 1612, 1612, 761, 762, 1612, + 1612, 1612, 762, 762, 762, 1612, 1612, 1612, 1612, 762, + 763, 1612, 1612, 1612, 763, 763, 763, 1612, 1612, 1612, + 1612, 763, 764, 1612, 1612, 1612, 764, 764, 764, 1612, + 1612, 1612, 1612, 764, 765, 1612, 1612, 1612, 765, 765, + 765, 1612, 1612, 1612, 1612, 765, 766, 1612, 1612, 1612, + 766, 766, 766, 1612, 1612, 1612, 1612, 766, 768, 1612, + 1612, 1612, 768, 768, 768, 1612, 1612, 1612, 1612, 768, + 450, 450, 450, 450, 450, 450, 450, 450, 450, 1612, + + 450, 450, 450, 1612, 450, 596, 596, 596, 596, 596, + 596, 596, 596, 596, 1612, 596, 596, 596, 596, 596, + 769, 769, 769, 769, 769, 769, 769, 769, 769, 1612, + 769, 769, 769, 1612, 769, 599, 599, 599, 599, 599, + 599, 599, 599, 599, 599, 599, 599, 599, 1612, 599, + 601, 601, 601, 601, 601, 601, 601, 601, 601, 1612, + 601, 601, 601, 601, 601, 771, 771, 771, 771, 771, + 771, 771, 771, 771, 1612, 771, 771, 771, 771, 771, + 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, + 604, 604, 604, 604, 604, 774, 774, 774, 774, 774, + + 774, 774, 774, 774, 774, 774, 774, 774, 1612, 774, + 607, 607, 607, 607, 607, 607, 607, 607, 607, 607, + 607, 607, 607, 1612, 607, 778, 778, 778, 802, 1612, + 1612, 1612, 802, 802, 802, 1612, 1612, 1612, 1612, 802, + 805, 1612, 1612, 1612, 805, 805, 805, 1612, 1612, 1612, + 1612, 805, 806, 1612, 1612, 1612, 806, 806, 806, 1612, + 1612, 1612, 1612, 806, 807, 1612, 1612, 1612, 807, 807, + 807, 1612, 1612, 1612, 1612, 807, 811, 1612, 1612, 1612, + 811, 811, 811, 1612, 1612, 1612, 1612, 811, 812, 1612, + 1612, 1612, 812, 812, 812, 1612, 1612, 1612, 1612, 812, + + 813, 1612, 1612, 1612, 813, 813, 813, 1612, 1612, 1612, + 1612, 813, 816, 1612, 1612, 1612, 816, 816, 816, 1612, + 1612, 1612, 1612, 816, 817, 1612, 1612, 1612, 817, 817, + 817, 1612, 1612, 1612, 1612, 817, 818, 1612, 1612, 1612, + 818, 818, 818, 1612, 1612, 1612, 1612, 818, 819, 1612, + 1612, 1612, 819, 819, 819, 1612, 1612, 1612, 1612, 819, + 820, 1612, 1612, 1612, 820, 820, 820, 1612, 1612, 1612, + 1612, 820, 824, 1612, 1612, 1612, 824, 824, 824, 1612, + 1612, 1612, 1612, 824, 825, 1612, 1612, 1612, 825, 825, + 825, 1612, 1612, 1612, 1612, 825, 826, 1612, 1612, 1612, + + 826, 826, 826, 1612, 1612, 1612, 1612, 826, 827, 1612, + 1612, 1612, 827, 827, 827, 1612, 1612, 1612, 1612, 827, + 828, 1612, 1612, 1612, 828, 828, 828, 1612, 1612, 1612, + 1612, 828, 829, 1612, 1612, 1612, 829, 829, 829, 1612, + 1612, 1612, 1612, 829, 831, 1612, 1612, 1612, 831, 831, + 831, 1612, 1612, 1612, 1612, 831, 832, 1612, 1612, 1612, + 832, 832, 832, 1612, 1612, 1612, 1612, 832, 833, 1612, + 1612, 1612, 833, 833, 833, 1612, 1612, 1612, 1612, 833, + 834, 1612, 1612, 1612, 834, 834, 834, 1612, 1612, 1612, + 1612, 834, 835, 1612, 1612, 1612, 835, 835, 835, 1612, + + 1612, 1612, 1612, 835, 836, 1612, 1612, 1612, 836, 836, + 836, 1612, 1612, 1612, 1612, 836, 837, 1612, 1612, 1612, + 837, 837, 837, 1612, 1612, 1612, 1612, 837, 845, 1612, + 1612, 1612, 845, 845, 845, 1612, 1612, 1612, 1612, 845, + 848, 1612, 1612, 1612, 848, 848, 848, 1612, 1612, 1612, + 1612, 848, 849, 1612, 1612, 1612, 849, 849, 849, 1612, + 1612, 1612, 1612, 849, 850, 1612, 1612, 1612, 850, 850, + 850, 1612, 1612, 1612, 1612, 850, 854, 1612, 1612, 1612, + 854, 854, 854, 1612, 1612, 1612, 1612, 854, 855, 1612, + 1612, 1612, 855, 855, 855, 1612, 1612, 1612, 1612, 855, + + 856, 1612, 1612, 1612, 856, 856, 856, 1612, 1612, 1612, + 1612, 856, 859, 1612, 1612, 1612, 859, 859, 859, 1612, + 1612, 1612, 1612, 859, 860, 1612, 1612, 1612, 860, 860, + 860, 1612, 1612, 1612, 1612, 860, 861, 1612, 1612, 1612, + 861, 861, 861, 1612, 1612, 1612, 1612, 861, 862, 1612, + 1612, 1612, 862, 862, 862, 1612, 1612, 1612, 1612, 862, + 863, 1612, 1612, 1612, 863, 863, 863, 1612, 1612, 1612, + 1612, 863, 867, 1612, 1612, 1612, 867, 867, 867, 1612, + 1612, 1612, 1612, 867, 868, 1612, 1612, 1612, 868, 868, + 868, 1612, 1612, 1612, 1612, 868, 869, 1612, 1612, 1612, + + 869, 869, 869, 1612, 1612, 1612, 1612, 869, 870, 1612, + 1612, 1612, 870, 870, 870, 1612, 1612, 1612, 1612, 870, + 871, 1612, 1612, 1612, 871, 871, 871, 1612, 1612, 1612, + 1612, 871, 872, 1612, 1612, 1612, 872, 872, 872, 1612, + 1612, 1612, 1612, 872, 874, 1612, 1612, 1612, 874, 874, + 874, 1612, 1612, 1612, 1612, 874, 875, 1612, 1612, 1612, + 875, 875, 875, 1612, 1612, 1612, 1612, 875, 876, 1612, + 1612, 1612, 876, 876, 876, 1612, 1612, 1612, 1612, 876, + 877, 1612, 1612, 1612, 877, 877, 877, 1612, 1612, 1612, + 1612, 877, 878, 1612, 1612, 1612, 878, 878, 878, 1612, + + 1612, 1612, 1612, 878, 879, 1612, 1612, 1612, 879, 879, + 879, 1612, 1612, 1612, 1612, 879, 880, 1612, 1612, 1612, + 880, 880, 880, 1612, 1612, 1612, 1612, 880, 884, 1612, + 1612, 1612, 884, 884, 884, 1612, 1612, 1612, 1612, 884, + 885, 1612, 1612, 1612, 885, 885, 885, 1612, 1612, 1612, + 1612, 885, 886, 1612, 1612, 1612, 886, 886, 886, 1612, + 1612, 1612, 1612, 886, 887, 1612, 1612, 1612, 887, 887, + 887, 1612, 1612, 1612, 1612, 887, 888, 1612, 1612, 1612, + 888, 888, 888, 1612, 1612, 1612, 1612, 888, 889, 1612, + 1612, 1612, 889, 889, 889, 1612, 1612, 1612, 1612, 889, + + 890, 1612, 1612, 1612, 890, 890, 890, 1612, 1612, 1612, + 1612, 890, 893, 1612, 1612, 1612, 893, 893, 893, 1612, + 1612, 1612, 1612, 893, 898, 1612, 1612, 1612, 898, 898, + 898, 1612, 1612, 1612, 1612, 898, 901, 1612, 1612, 1612, + 901, 901, 901, 1612, 1612, 1612, 1612, 901, 902, 1612, + 1612, 1612, 902, 902, 902, 1612, 1612, 1612, 1612, 902, + 903, 1612, 1612, 1612, 903, 903, 903, 1612, 1612, 1612, + 1612, 903, 907, 1612, 1612, 1612, 907, 907, 907, 1612, + 1612, 1612, 1612, 907, 908, 1612, 1612, 1612, 908, 908, + 908, 1612, 1612, 1612, 1612, 908, 909, 1612, 1612, 1612, + + 909, 909, 909, 1612, 1612, 1612, 1612, 909, 912, 1612, + 1612, 1612, 912, 912, 912, 1612, 1612, 1612, 1612, 912, + 913, 1612, 1612, 1612, 913, 913, 913, 1612, 1612, 1612, + 1612, 913, 914, 1612, 1612, 1612, 914, 914, 914, 1612, + 1612, 1612, 1612, 914, 915, 1612, 1612, 1612, 915, 915, + 915, 1612, 1612, 1612, 1612, 915, 916, 1612, 1612, 1612, + 916, 916, 916, 1612, 1612, 1612, 1612, 916, 920, 1612, + 1612, 1612, 920, 920, 920, 1612, 1612, 1612, 1612, 920, + 921, 1612, 1612, 1612, 921, 921, 921, 1612, 1612, 1612, + 1612, 921, 922, 1612, 1612, 1612, 922, 922, 922, 1612, + + 1612, 1612, 1612, 922, 923, 1612, 1612, 1612, 923, 923, + 923, 1612, 1612, 1612, 1612, 923, 924, 1612, 1612, 1612, + 924, 924, 924, 1612, 1612, 1612, 1612, 924, 925, 1612, + 1612, 1612, 925, 925, 925, 1612, 1612, 1612, 1612, 925, + 927, 1612, 1612, 1612, 927, 927, 927, 1612, 1612, 1612, + 1612, 927, 932, 1612, 1612, 1612, 932, 932, 932, 1612, + 1612, 1612, 1612, 932, 935, 1612, 1612, 1612, 935, 935, + 935, 1612, 1612, 1612, 1612, 935, 936, 1612, 1612, 1612, + 936, 936, 936, 1612, 1612, 1612, 1612, 936, 937, 1612, + 1612, 1612, 937, 937, 937, 1612, 1612, 1612, 1612, 937, + + 941, 1612, 1612, 1612, 941, 941, 941, 1612, 1612, 1612, + 1612, 941, 942, 1612, 1612, 1612, 942, 942, 942, 1612, + 1612, 1612, 1612, 942, 943, 1612, 1612, 1612, 943, 943, + 943, 1612, 1612, 1612, 1612, 943, 946, 1612, 1612, 1612, + 946, 946, 946, 1612, 1612, 1612, 1612, 946, 947, 1612, + 1612, 1612, 947, 947, 947, 1612, 1612, 1612, 1612, 947, + 948, 1612, 1612, 1612, 948, 948, 948, 1612, 1612, 1612, + 1612, 948, 949, 1612, 1612, 1612, 949, 949, 949, 1612, + 1612, 1612, 1612, 949, 950, 1612, 1612, 1612, 950, 950, + 950, 1612, 1612, 1612, 1612, 950, 954, 1612, 1612, 1612, + + 954, 954, 954, 1612, 1612, 1612, 1612, 954, 955, 1612, + 1612, 1612, 955, 955, 955, 1612, 1612, 1612, 1612, 955, + 956, 1612, 1612, 1612, 956, 956, 956, 1612, 1612, 1612, + 1612, 956, 957, 1612, 1612, 1612, 957, 957, 957, 1612, + 1612, 1612, 1612, 957, 958, 1612, 1612, 1612, 958, 958, + 958, 1612, 1612, 1612, 1612, 958, 959, 1612, 1612, 1612, + 959, 959, 959, 1612, 1612, 1612, 1612, 959, 961, 1612, + 1612, 1612, 961, 961, 961, 1612, 1612, 1612, 1612, 961, + 962, 1612, 1612, 1612, 962, 962, 962, 1612, 1612, 1612, + 1612, 962, 963, 1612, 1612, 1612, 963, 963, 963, 1612, + + 1612, 1612, 1612, 963, 964, 1612, 1612, 1612, 964, 964, + 964, 1612, 1612, 1612, 1612, 964, 965, 1612, 1612, 1612, + 965, 965, 965, 1612, 1612, 1612, 1612, 965, 966, 1612, + 1612, 1612, 966, 966, 966, 1612, 1612, 1612, 1612, 966, + 967, 1612, 1612, 1612, 967, 967, 967, 1612, 1612, 1612, + 1612, 967, 769, 769, 769, 769, 769, 769, 769, 769, + 769, 1612, 769, 769, 769, 1612, 769, 771, 771, 771, + 771, 771, 771, 771, 771, 771, 1612, 771, 771, 771, + 771, 771, 971, 971, 971, 971, 971, 971, 971, 971, + 971, 1612, 971, 971, 971, 1612, 971, 774, 774, 774, + + 774, 774, 774, 774, 774, 774, 774, 774, 774, 774, + 1612, 774, 973, 973, 973, 974, 974, 974, 995, 1612, + 1612, 1612, 995, 995, 995, 1612, 1612, 1612, 1612, 995, + 998, 1612, 1612, 1612, 998, 998, 998, 1612, 1612, 1612, + 1612, 998, 999, 1612, 1612, 1612, 999, 999, 999, 1612, + 1612, 1612, 1612, 999, 1000, 1612, 1612, 1612, 1000, 1000, + 1000, 1612, 1612, 1612, 1612, 1000, 1004, 1612, 1612, 1612, + 1004, 1004, 1004, 1612, 1612, 1612, 1612, 1004, 1005, 1612, + 1612, 1612, 1005, 1005, 1005, 1612, 1612, 1612, 1612, 1005, + 1006, 1612, 1612, 1612, 1006, 1006, 1006, 1612, 1612, 1612, + + 1612, 1006, 1009, 1612, 1612, 1612, 1009, 1009, 1009, 1612, + 1612, 1612, 1612, 1009, 1010, 1612, 1612, 1612, 1010, 1010, + 1010, 1612, 1612, 1612, 1612, 1010, 1011, 1612, 1612, 1612, + 1011, 1011, 1011, 1612, 1612, 1612, 1612, 1011, 1012, 1612, + 1612, 1612, 1012, 1012, 1012, 1612, 1612, 1612, 1612, 1012, + 1013, 1612, 1612, 1612, 1013, 1013, 1013, 1612, 1612, 1612, + 1612, 1013, 1017, 1612, 1612, 1612, 1017, 1017, 1017, 1612, + 1612, 1612, 1612, 1017, 1018, 1612, 1612, 1612, 1018, 1018, + 1018, 1612, 1612, 1612, 1612, 1018, 1019, 1612, 1612, 1612, + 1019, 1019, 1019, 1612, 1612, 1612, 1612, 1019, 1020, 1612, + + 1612, 1612, 1020, 1020, 1020, 1612, 1612, 1612, 1612, 1020, + 1021, 1612, 1612, 1612, 1021, 1021, 1021, 1612, 1612, 1612, + 1612, 1021, 1022, 1612, 1612, 1612, 1022, 1022, 1022, 1612, + 1612, 1612, 1612, 1022, 1024, 1612, 1612, 1612, 1024, 1024, + 1024, 1612, 1612, 1612, 1612, 1024, 1025, 1612, 1612, 1612, + 1025, 1025, 1025, 1612, 1612, 1612, 1612, 1025, 1026, 1612, + 1612, 1612, 1026, 1026, 1026, 1612, 1612, 1612, 1612, 1026, + 1027, 1612, 1612, 1612, 1027, 1027, 1027, 1612, 1612, 1612, + 1612, 1027, 1028, 1612, 1612, 1612, 1028, 1028, 1028, 1612, + 1612, 1612, 1612, 1028, 1029, 1612, 1612, 1612, 1029, 1029, + + 1029, 1612, 1612, 1612, 1612, 1029, 1030, 1612, 1612, 1612, + 1030, 1030, 1030, 1612, 1612, 1612, 1612, 1030, 1034, 1612, + 1612, 1612, 1034, 1034, 1034, 1612, 1612, 1612, 1612, 1034, + 1035, 1612, 1612, 1612, 1035, 1035, 1035, 1612, 1612, 1612, + 1612, 1035, 1036, 1612, 1612, 1612, 1036, 1036, 1036, 1612, + 1612, 1612, 1612, 1036, 1037, 1612, 1612, 1612, 1037, 1037, + 1037, 1612, 1612, 1612, 1612, 1037, 1038, 1612, 1612, 1612, + 1038, 1038, 1038, 1612, 1612, 1612, 1612, 1038, 1039, 1612, + 1612, 1612, 1039, 1039, 1039, 1612, 1612, 1612, 1612, 1039, + 1040, 1612, 1612, 1612, 1040, 1040, 1040, 1612, 1612, 1612, + + 1612, 1040, 1043, 1612, 1612, 1612, 1043, 1043, 1043, 1612, + 1612, 1612, 1612, 1043, 1048, 1612, 1612, 1612, 1048, 1048, + 1048, 1612, 1612, 1612, 1612, 1048, 1051, 1612, 1612, 1612, + 1051, 1051, 1051, 1612, 1612, 1612, 1612, 1051, 1052, 1612, + 1612, 1612, 1052, 1052, 1052, 1612, 1612, 1612, 1612, 1052, + 1053, 1612, 1612, 1612, 1053, 1053, 1053, 1612, 1612, 1612, + 1612, 1053, 1057, 1612, 1612, 1612, 1057, 1057, 1057, 1612, + 1612, 1612, 1612, 1057, 1058, 1612, 1612, 1612, 1058, 1058, + 1058, 1612, 1612, 1612, 1612, 1058, 1059, 1612, 1612, 1612, + 1059, 1059, 1059, 1612, 1612, 1612, 1612, 1059, 1062, 1612, + + 1612, 1612, 1062, 1062, 1062, 1612, 1612, 1612, 1612, 1062, + 1063, 1612, 1612, 1612, 1063, 1063, 1063, 1612, 1612, 1612, + 1612, 1063, 1064, 1612, 1612, 1612, 1064, 1064, 1064, 1612, + 1612, 1612, 1612, 1064, 1065, 1612, 1612, 1612, 1065, 1065, + 1065, 1612, 1612, 1612, 1612, 1065, 1066, 1612, 1612, 1612, + 1066, 1066, 1066, 1612, 1612, 1612, 1612, 1066, 1070, 1612, + 1612, 1612, 1070, 1070, 1070, 1612, 1612, 1612, 1612, 1070, + 1071, 1612, 1612, 1612, 1071, 1071, 1071, 1612, 1612, 1612, + 1612, 1071, 1072, 1612, 1612, 1612, 1072, 1072, 1072, 1612, + 1612, 1612, 1612, 1072, 1073, 1612, 1612, 1612, 1073, 1073, + + 1073, 1612, 1612, 1612, 1612, 1073, 1074, 1612, 1612, 1612, + 1074, 1074, 1074, 1612, 1612, 1612, 1612, 1074, 1075, 1612, + 1612, 1612, 1075, 1075, 1075, 1612, 1612, 1612, 1612, 1075, + 1077, 1612, 1612, 1612, 1077, 1077, 1077, 1612, 1612, 1612, + 1612, 1077, 1078, 1612, 1612, 1612, 1078, 1078, 1078, 1612, + 1612, 1612, 1612, 1078, 1079, 1612, 1612, 1612, 1079, 1079, + 1079, 1612, 1612, 1612, 1612, 1079, 1080, 1612, 1612, 1612, + 1080, 1080, 1080, 1612, 1612, 1612, 1612, 1080, 1081, 1612, + 1612, 1612, 1081, 1081, 1081, 1612, 1612, 1612, 1612, 1081, + 1082, 1612, 1612, 1612, 1082, 1082, 1082, 1612, 1612, 1612, + + 1612, 1082, 1083, 1612, 1612, 1612, 1083, 1083, 1083, 1612, + 1612, 1612, 1612, 1083, 1087, 1612, 1612, 1612, 1087, 1087, + 1087, 1612, 1612, 1612, 1612, 1087, 1088, 1612, 1612, 1612, + 1088, 1088, 1088, 1612, 1612, 1612, 1612, 1088, 1089, 1612, + 1612, 1612, 1089, 1089, 1089, 1612, 1612, 1612, 1612, 1089, + 1090, 1612, 1612, 1612, 1090, 1090, 1090, 1612, 1612, 1612, + 1612, 1090, 1091, 1612, 1612, 1612, 1091, 1091, 1091, 1612, + 1612, 1612, 1612, 1091, 1092, 1612, 1612, 1612, 1092, 1092, + 1092, 1612, 1612, 1612, 1612, 1092, 1093, 1612, 1612, 1612, + 1093, 1093, 1093, 1612, 1612, 1612, 1612, 1093, 1096, 1612, + + 1612, 1612, 1096, 1096, 1096, 1612, 1612, 1612, 1612, 1096, + 1097, 1612, 1612, 1612, 1097, 1097, 1097, 1612, 1612, 1612, + 1612, 1097, 1098, 1612, 1612, 1612, 1098, 1098, 1098, 1612, + 1612, 1612, 1612, 1098, 1099, 1612, 1612, 1612, 1099, 1099, + 1099, 1612, 1612, 1612, 1612, 1099, 1100, 1612, 1612, 1612, + 1100, 1100, 1100, 1612, 1612, 1612, 1612, 1100, 1101, 1612, + 1612, 1612, 1101, 1101, 1101, 1612, 1612, 1612, 1612, 1101, + 1102, 1612, 1612, 1612, 1102, 1102, 1102, 1612, 1612, 1612, + 1612, 1102, 1103, 1612, 1612, 1612, 1103, 1103, 1103, 1612, + 1612, 1612, 1612, 1103, 1104, 1612, 1612, 1612, 1104, 1104, + + 1104, 1612, 1612, 1612, 1612, 1104, 1112, 1612, 1612, 1612, + 1112, 1112, 1112, 1612, 1612, 1612, 1612, 1112, 1115, 1612, + 1612, 1612, 1115, 1115, 1115, 1612, 1612, 1612, 1612, 1115, + 1116, 1612, 1612, 1612, 1116, 1116, 1116, 1612, 1612, 1612, + 1612, 1116, 1117, 1612, 1612, 1612, 1117, 1117, 1117, 1612, + 1612, 1612, 1612, 1117, 1121, 1612, 1612, 1612, 1121, 1121, + 1121, 1612, 1612, 1612, 1612, 1121, 1122, 1612, 1612, 1612, + 1122, 1122, 1122, 1612, 1612, 1612, 1612, 1122, 1123, 1612, + 1612, 1612, 1123, 1123, 1123, 1612, 1612, 1612, 1612, 1123, + 1126, 1612, 1612, 1612, 1126, 1126, 1126, 1612, 1612, 1612, + + 1612, 1126, 1127, 1612, 1612, 1612, 1127, 1127, 1127, 1612, + 1612, 1612, 1612, 1127, 1128, 1612, 1612, 1612, 1128, 1128, + 1128, 1612, 1612, 1612, 1612, 1128, 1129, 1612, 1612, 1612, + 1129, 1129, 1129, 1612, 1612, 1612, 1612, 1129, 1130, 1612, + 1612, 1612, 1130, 1130, 1130, 1612, 1612, 1612, 1612, 1130, + 1134, 1612, 1612, 1612, 1134, 1134, 1134, 1612, 1612, 1612, + 1612, 1134, 1135, 1612, 1612, 1612, 1135, 1135, 1135, 1612, + 1612, 1612, 1612, 1135, 1136, 1612, 1612, 1612, 1136, 1136, + 1136, 1612, 1612, 1612, 1612, 1136, 1137, 1612, 1612, 1612, + 1137, 1137, 1137, 1612, 1612, 1612, 1612, 1137, 1138, 1612, + + 1612, 1612, 1138, 1138, 1138, 1612, 1612, 1612, 1612, 1138, + 1139, 1612, 1612, 1612, 1139, 1139, 1139, 1612, 1612, 1612, + 1612, 1139, 1141, 1612, 1612, 1612, 1141, 1141, 1141, 1612, + 1612, 1612, 1612, 1141, 1142, 1612, 1612, 1612, 1142, 1142, + 1142, 1612, 1612, 1612, 1612, 1142, 1143, 1612, 1612, 1612, + 1143, 1143, 1143, 1612, 1612, 1612, 1612, 1143, 1144, 1612, + 1612, 1612, 1144, 1144, 1144, 1612, 1612, 1612, 1612, 1144, + 1145, 1612, 1612, 1612, 1145, 1145, 1145, 1612, 1612, 1612, + 1612, 1145, 1146, 1612, 1612, 1612, 1146, 1146, 1146, 1612, + 1612, 1612, 1612, 1146, 1147, 1612, 1612, 1612, 1147, 1147, + + 1147, 1612, 1612, 1612, 1612, 1147, 1155, 1612, 1612, 1612, + 1155, 1155, 1155, 1612, 1612, 1612, 1612, 1155, 1158, 1612, + 1612, 1612, 1158, 1158, 1158, 1612, 1612, 1612, 1612, 1158, + 1159, 1612, 1612, 1612, 1159, 1159, 1159, 1612, 1612, 1612, + 1612, 1159, 1160, 1612, 1612, 1612, 1160, 1160, 1160, 1612, + 1612, 1612, 1612, 1160, 1164, 1612, 1612, 1612, 1164, 1164, + 1164, 1612, 1612, 1612, 1612, 1164, 1165, 1612, 1612, 1612, + 1165, 1165, 1165, 1612, 1612, 1612, 1612, 1165, 1166, 1612, + 1612, 1612, 1166, 1166, 1166, 1612, 1612, 1612, 1612, 1166, + 1169, 1612, 1612, 1612, 1169, 1169, 1169, 1612, 1612, 1612, + + 1612, 1169, 1170, 1612, 1612, 1612, 1170, 1170, 1170, 1612, + 1612, 1612, 1612, 1170, 1171, 1612, 1612, 1612, 1171, 1171, + 1171, 1612, 1612, 1612, 1612, 1171, 1172, 1612, 1612, 1612, + 1172, 1172, 1172, 1612, 1612, 1612, 1612, 1172, 1173, 1612, + 1612, 1612, 1173, 1173, 1173, 1612, 1612, 1612, 1612, 1173, + 1177, 1612, 1612, 1612, 1177, 1177, 1177, 1612, 1612, 1612, + 1612, 1177, 1178, 1612, 1612, 1612, 1178, 1178, 1178, 1612, + 1612, 1612, 1612, 1178, 1179, 1612, 1612, 1612, 1179, 1179, + 1179, 1612, 1612, 1612, 1612, 1179, 1180, 1612, 1612, 1612, + 1180, 1180, 1180, 1612, 1612, 1612, 1612, 1180, 1181, 1612, + + 1612, 1612, 1181, 1181, 1181, 1612, 1612, 1612, 1612, 1181, + 1182, 1612, 1612, 1612, 1182, 1182, 1182, 1612, 1612, 1612, + 1612, 1182, 1184, 1612, 1612, 1612, 1184, 1184, 1184, 1612, + 1612, 1612, 1612, 1184, 1185, 1612, 1612, 1612, 1185, 1185, + 1185, 1612, 1612, 1612, 1612, 1185, 1186, 1612, 1612, 1612, + 1186, 1186, 1186, 1612, 1612, 1612, 1612, 1186, 1187, 1612, + 1612, 1612, 1187, 1187, 1187, 1612, 1612, 1612, 1612, 1187, + 1188, 1612, 1612, 1612, 1188, 1188, 1188, 1612, 1612, 1612, + 1612, 1188, 1189, 1612, 1612, 1612, 1189, 1189, 1189, 1612, + 1612, 1612, 1612, 1189, 1190, 1612, 1612, 1612, 1190, 1190, + + 1190, 1612, 1612, 1612, 1612, 1190, 1194, 1612, 1612, 1612, + 1194, 1194, 1194, 1612, 1612, 1612, 1612, 1194, 1195, 1612, + 1612, 1612, 1195, 1195, 1195, 1612, 1612, 1612, 1612, 1195, + 1196, 1612, 1612, 1612, 1196, 1196, 1196, 1612, 1612, 1612, + 1612, 1196, 1197, 1612, 1612, 1612, 1197, 1197, 1197, 1612, + 1612, 1612, 1612, 1197, 1198, 1612, 1612, 1612, 1198, 1198, + 1198, 1612, 1612, 1612, 1612, 1198, 1199, 1612, 1612, 1612, + 1199, 1199, 1199, 1612, 1612, 1612, 1612, 1199, 1200, 1612, + 1612, 1612, 1200, 1200, 1200, 1612, 1612, 1612, 1612, 1200, + 1203, 1612, 1612, 1612, 1203, 1203, 1203, 1612, 1612, 1612, + + 1612, 1203, 971, 971, 971, 971, 971, 971, 971, 971, + 971, 1612, 971, 971, 971, 1612, 971, 1204, 1612, 1612, + 1612, 1204, 1204, 1204, 1612, 1612, 1612, 1612, 1204, 1206, + 1206, 1206, 1207, 1207, 1207, 1209, 1209, 1209, 1612, 1612, + 1612, 1612, 1209, 1215, 1215, 1215, 1216, 1216, 1216, 1225, + 1612, 1612, 1612, 1225, 1225, 1225, 1612, 1612, 1612, 1612, + 1225, 1228, 1612, 1612, 1612, 1228, 1228, 1228, 1612, 1612, + 1612, 1612, 1228, 1229, 1612, 1612, 1612, 1229, 1229, 1229, + 1612, 1612, 1612, 1612, 1229, 1230, 1612, 1612, 1612, 1230, + 1230, 1230, 1612, 1612, 1612, 1612, 1230, 1234, 1612, 1612, + + 1612, 1234, 1234, 1234, 1612, 1612, 1612, 1612, 1234, 1235, + 1612, 1612, 1612, 1235, 1235, 1235, 1612, 1612, 1612, 1612, + 1235, 1236, 1612, 1612, 1612, 1236, 1236, 1236, 1612, 1612, + 1612, 1612, 1236, 1239, 1612, 1612, 1612, 1239, 1239, 1239, + 1612, 1612, 1612, 1612, 1239, 1240, 1612, 1612, 1612, 1240, + 1240, 1240, 1612, 1612, 1612, 1612, 1240, 1241, 1612, 1612, + 1612, 1241, 1241, 1241, 1612, 1612, 1612, 1612, 1241, 1242, + 1612, 1612, 1612, 1242, 1242, 1242, 1612, 1612, 1612, 1612, + 1242, 1243, 1612, 1612, 1612, 1243, 1243, 1243, 1612, 1612, + 1612, 1612, 1243, 1247, 1612, 1612, 1612, 1247, 1247, 1247, + + 1612, 1612, 1612, 1612, 1247, 1248, 1612, 1612, 1612, 1248, + 1248, 1248, 1612, 1612, 1612, 1612, 1248, 1249, 1612, 1612, + 1612, 1249, 1249, 1249, 1612, 1612, 1612, 1612, 1249, 1250, + 1612, 1612, 1612, 1250, 1250, 1250, 1612, 1612, 1612, 1612, + 1250, 1251, 1612, 1612, 1612, 1251, 1251, 1251, 1612, 1612, + 1612, 1612, 1251, 1252, 1612, 1612, 1612, 1252, 1252, 1252, + 1612, 1612, 1612, 1612, 1252, 1254, 1612, 1612, 1612, 1254, + 1254, 1254, 1612, 1612, 1612, 1612, 1254, 1255, 1612, 1612, + 1612, 1255, 1255, 1255, 1612, 1612, 1612, 1612, 1255, 1256, + 1612, 1612, 1612, 1256, 1256, 1256, 1612, 1612, 1612, 1612, + + 1256, 1257, 1612, 1612, 1612, 1257, 1257, 1257, 1612, 1612, + 1612, 1612, 1257, 1258, 1612, 1612, 1612, 1258, 1258, 1258, + 1612, 1612, 1612, 1612, 1258, 1259, 1612, 1612, 1612, 1259, + 1259, 1259, 1612, 1612, 1612, 1612, 1259, 1260, 1612, 1612, + 1612, 1260, 1260, 1260, 1612, 1612, 1612, 1612, 1260, 1264, + 1612, 1612, 1612, 1264, 1264, 1264, 1612, 1612, 1612, 1612, + 1264, 1265, 1612, 1612, 1612, 1265, 1265, 1265, 1612, 1612, + 1612, 1612, 1265, 1266, 1612, 1612, 1612, 1266, 1266, 1266, + 1612, 1612, 1612, 1612, 1266, 1267, 1612, 1612, 1612, 1267, + 1267, 1267, 1612, 1612, 1612, 1612, 1267, 1268, 1612, 1612, + + 1612, 1268, 1268, 1268, 1612, 1612, 1612, 1612, 1268, 1269, + 1612, 1612, 1612, 1269, 1269, 1269, 1612, 1612, 1612, 1612, + 1269, 1270, 1612, 1612, 1612, 1270, 1270, 1270, 1612, 1612, + 1612, 1612, 1270, 1273, 1612, 1612, 1612, 1273, 1273, 1273, + 1612, 1612, 1612, 1612, 1273, 1274, 1612, 1612, 1612, 1274, + 1274, 1274, 1612, 1612, 1612, 1612, 1274, 1275, 1612, 1612, + 1612, 1275, 1275, 1275, 1612, 1612, 1612, 1612, 1275, 1276, + 1612, 1612, 1612, 1276, 1276, 1276, 1612, 1612, 1612, 1612, + 1276, 1277, 1612, 1612, 1612, 1277, 1277, 1277, 1612, 1612, + 1612, 1612, 1277, 1278, 1612, 1612, 1612, 1278, 1278, 1278, + + 1612, 1612, 1612, 1612, 1278, 1279, 1612, 1612, 1612, 1279, + 1279, 1279, 1612, 1612, 1612, 1612, 1279, 1280, 1612, 1612, + 1612, 1280, 1280, 1280, 1612, 1612, 1612, 1612, 1280, 1281, + 1612, 1612, 1612, 1281, 1281, 1281, 1612, 1612, 1612, 1612, + 1281, 1048, 1612, 1612, 1612, 1048, 1048, 1048, 1612, 1612, + 1612, 1612, 1048, 1051, 1612, 1612, 1612, 1051, 1051, 1051, + 1612, 1612, 1612, 1612, 1051, 1052, 1612, 1612, 1612, 1052, + 1052, 1052, 1612, 1612, 1612, 1612, 1052, 1053, 1612, 1612, + 1612, 1053, 1053, 1053, 1612, 1612, 1612, 1612, 1053, 1057, + 1612, 1612, 1612, 1057, 1057, 1057, 1612, 1612, 1612, 1612, + + 1057, 1058, 1612, 1612, 1612, 1058, 1058, 1058, 1612, 1612, + 1612, 1612, 1058, 1059, 1612, 1612, 1612, 1059, 1059, 1059, + 1612, 1612, 1612, 1612, 1059, 1062, 1612, 1612, 1612, 1062, + 1062, 1062, 1612, 1612, 1612, 1612, 1062, 1063, 1612, 1612, + 1612, 1063, 1063, 1063, 1612, 1612, 1612, 1612, 1063, 1064, + 1612, 1612, 1612, 1064, 1064, 1064, 1612, 1612, 1612, 1612, + 1064, 1065, 1612, 1612, 1612, 1065, 1065, 1065, 1612, 1612, + 1612, 1612, 1065, 1066, 1612, 1612, 1612, 1066, 1066, 1066, + 1612, 1612, 1612, 1612, 1066, 1070, 1612, 1612, 1612, 1070, + 1070, 1070, 1612, 1612, 1612, 1612, 1070, 1071, 1612, 1612, + + 1612, 1071, 1071, 1071, 1612, 1612, 1612, 1612, 1071, 1072, + 1612, 1612, 1612, 1072, 1072, 1072, 1612, 1612, 1612, 1612, + 1072, 1073, 1612, 1612, 1612, 1073, 1073, 1073, 1612, 1612, + 1612, 1612, 1073, 1074, 1612, 1612, 1612, 1074, 1074, 1074, + 1612, 1612, 1612, 1612, 1074, 1075, 1612, 1612, 1612, 1075, + 1075, 1075, 1612, 1612, 1612, 1612, 1075, 1077, 1612, 1612, + 1612, 1077, 1077, 1077, 1612, 1612, 1612, 1612, 1077, 1078, + 1612, 1612, 1612, 1078, 1078, 1078, 1612, 1612, 1612, 1612, + 1078, 1079, 1612, 1612, 1612, 1079, 1079, 1079, 1612, 1612, + 1612, 1612, 1079, 1080, 1612, 1612, 1612, 1080, 1080, 1080, + + 1612, 1612, 1612, 1612, 1080, 1081, 1612, 1612, 1612, 1081, + 1081, 1081, 1612, 1612, 1612, 1612, 1081, 1082, 1612, 1612, + 1612, 1082, 1082, 1082, 1612, 1612, 1612, 1612, 1082, 1083, + 1612, 1612, 1612, 1083, 1083, 1083, 1612, 1612, 1612, 1612, + 1083, 1087, 1612, 1612, 1612, 1087, 1087, 1087, 1612, 1612, + 1612, 1612, 1087, 1088, 1612, 1612, 1612, 1088, 1088, 1088, + 1612, 1612, 1612, 1612, 1088, 1089, 1612, 1612, 1612, 1089, + 1089, 1089, 1612, 1612, 1612, 1612, 1089, 1090, 1612, 1612, + 1612, 1090, 1090, 1090, 1612, 1612, 1612, 1612, 1090, 1091, + 1612, 1612, 1612, 1091, 1091, 1091, 1612, 1612, 1612, 1612, + + 1091, 1092, 1612, 1612, 1612, 1092, 1092, 1092, 1612, 1612, + 1612, 1612, 1092, 1093, 1612, 1612, 1612, 1093, 1093, 1093, + 1612, 1612, 1612, 1612, 1093, 1096, 1612, 1612, 1612, 1096, + 1096, 1096, 1612, 1612, 1612, 1612, 1096, 1097, 1612, 1612, + 1612, 1097, 1097, 1097, 1612, 1612, 1612, 1612, 1097, 1098, + 1612, 1612, 1612, 1098, 1098, 1098, 1612, 1612, 1612, 1612, + 1098, 1099, 1612, 1612, 1612, 1099, 1099, 1099, 1612, 1612, + 1612, 1612, 1099, 1100, 1612, 1612, 1612, 1100, 1100, 1100, + 1612, 1612, 1612, 1612, 1100, 1101, 1612, 1612, 1612, 1101, + 1101, 1101, 1612, 1612, 1612, 1612, 1101, 1102, 1612, 1612, + + 1612, 1102, 1102, 1102, 1612, 1612, 1612, 1612, 1102, 1103, + 1612, 1612, 1612, 1103, 1103, 1103, 1612, 1612, 1612, 1612, + 1103, 1104, 1612, 1612, 1612, 1104, 1104, 1104, 1612, 1612, + 1612, 1612, 1104, 1289, 1612, 1612, 1612, 1289, 1289, 1289, + 1612, 1612, 1612, 1612, 1289, 1292, 1612, 1612, 1612, 1292, + 1292, 1292, 1612, 1612, 1612, 1612, 1292, 1293, 1612, 1612, + 1612, 1293, 1293, 1293, 1612, 1612, 1612, 1612, 1293, 1294, + 1612, 1612, 1612, 1294, 1294, 1294, 1612, 1612, 1612, 1612, + 1294, 1298, 1612, 1612, 1612, 1298, 1298, 1298, 1612, 1612, + 1612, 1612, 1298, 1299, 1612, 1612, 1612, 1299, 1299, 1299, + + 1612, 1612, 1612, 1612, 1299, 1300, 1612, 1612, 1612, 1300, + 1300, 1300, 1612, 1612, 1612, 1612, 1300, 1303, 1612, 1612, + 1612, 1303, 1303, 1303, 1612, 1612, 1612, 1612, 1303, 1304, + 1612, 1612, 1612, 1304, 1304, 1304, 1612, 1612, 1612, 1612, + 1304, 1305, 1612, 1612, 1612, 1305, 1305, 1305, 1612, 1612, + 1612, 1612, 1305, 1306, 1612, 1612, 1612, 1306, 1306, 1306, + 1612, 1612, 1612, 1612, 1306, 1307, 1612, 1612, 1612, 1307, + 1307, 1307, 1612, 1612, 1612, 1612, 1307, 1311, 1612, 1612, + 1612, 1311, 1311, 1311, 1612, 1612, 1612, 1612, 1311, 1312, + 1612, 1612, 1612, 1312, 1312, 1312, 1612, 1612, 1612, 1612, + + 1312, 1313, 1612, 1612, 1612, 1313, 1313, 1313, 1612, 1612, + 1612, 1612, 1313, 1314, 1612, 1612, 1612, 1314, 1314, 1314, + 1612, 1612, 1612, 1612, 1314, 1315, 1612, 1612, 1612, 1315, + 1315, 1315, 1612, 1612, 1612, 1612, 1315, 1316, 1612, 1612, + 1612, 1316, 1316, 1316, 1612, 1612, 1612, 1612, 1316, 1318, + 1612, 1612, 1612, 1318, 1318, 1318, 1612, 1612, 1612, 1612, + 1318, 1319, 1612, 1612, 1612, 1319, 1319, 1319, 1612, 1612, + 1612, 1612, 1319, 1320, 1612, 1612, 1612, 1320, 1320, 1320, + 1612, 1612, 1612, 1612, 1320, 1321, 1612, 1612, 1612, 1321, + 1321, 1321, 1612, 1612, 1612, 1612, 1321, 1322, 1612, 1612, + + 1612, 1322, 1322, 1322, 1612, 1612, 1612, 1612, 1322, 1323, + 1612, 1612, 1612, 1323, 1323, 1323, 1612, 1612, 1612, 1612, + 1323, 1324, 1612, 1612, 1612, 1324, 1324, 1324, 1612, 1612, + 1612, 1612, 1324, 1328, 1612, 1612, 1612, 1328, 1328, 1328, + 1612, 1612, 1612, 1612, 1328, 1329, 1612, 1612, 1612, 1329, + 1329, 1329, 1612, 1612, 1612, 1612, 1329, 1330, 1612, 1612, + 1612, 1330, 1330, 1330, 1612, 1612, 1612, 1612, 1330, 1331, + 1612, 1612, 1612, 1331, 1331, 1331, 1612, 1612, 1612, 1612, + 1331, 1332, 1612, 1612, 1612, 1332, 1332, 1332, 1612, 1612, + 1612, 1612, 1332, 1333, 1612, 1612, 1612, 1333, 1333, 1333, + + 1612, 1612, 1612, 1612, 1333, 1334, 1612, 1612, 1612, 1334, + 1334, 1334, 1612, 1612, 1612, 1612, 1334, 1337, 1612, 1612, + 1612, 1337, 1337, 1337, 1612, 1612, 1612, 1612, 1337, 1342, + 1612, 1612, 1612, 1342, 1342, 1342, 1612, 1612, 1612, 1612, + 1342, 1345, 1612, 1612, 1612, 1345, 1345, 1345, 1612, 1612, + 1612, 1612, 1345, 1346, 1612, 1612, 1612, 1346, 1346, 1346, + 1612, 1612, 1612, 1612, 1346, 1347, 1612, 1612, 1612, 1347, + 1347, 1347, 1612, 1612, 1612, 1612, 1347, 1351, 1612, 1612, + 1612, 1351, 1351, 1351, 1612, 1612, 1612, 1612, 1351, 1352, + 1612, 1612, 1612, 1352, 1352, 1352, 1612, 1612, 1612, 1612, + + 1352, 1353, 1612, 1612, 1612, 1353, 1353, 1353, 1612, 1612, + 1612, 1612, 1353, 1356, 1612, 1612, 1612, 1356, 1356, 1356, + 1612, 1612, 1612, 1612, 1356, 1357, 1612, 1612, 1612, 1357, + 1357, 1357, 1612, 1612, 1612, 1612, 1357, 1358, 1612, 1612, + 1612, 1358, 1358, 1358, 1612, 1612, 1612, 1612, 1358, 1359, + 1612, 1612, 1612, 1359, 1359, 1359, 1612, 1612, 1612, 1612, + 1359, 1360, 1612, 1612, 1612, 1360, 1360, 1360, 1612, 1612, + 1612, 1612, 1360, 1364, 1612, 1612, 1612, 1364, 1364, 1364, + 1612, 1612, 1612, 1612, 1364, 1365, 1612, 1612, 1612, 1365, + 1365, 1365, 1612, 1612, 1612, 1612, 1365, 1366, 1612, 1612, + + 1612, 1366, 1366, 1366, 1612, 1612, 1612, 1612, 1366, 1367, + 1612, 1612, 1612, 1367, 1367, 1367, 1612, 1612, 1612, 1612, + 1367, 1368, 1612, 1612, 1612, 1368, 1368, 1368, 1612, 1612, + 1612, 1612, 1368, 1369, 1612, 1612, 1612, 1369, 1369, 1369, + 1612, 1612, 1612, 1612, 1369, 1371, 1612, 1612, 1612, 1371, + 1371, 1371, 1612, 1612, 1612, 1612, 1371, 1372, 1612, 1612, + 1612, 1372, 1372, 1372, 1612, 1612, 1612, 1612, 1372, 1373, + 1612, 1612, 1612, 1373, 1373, 1373, 1612, 1612, 1612, 1612, + 1373, 1374, 1612, 1612, 1612, 1374, 1374, 1374, 1612, 1612, + 1612, 1612, 1374, 1375, 1612, 1612, 1612, 1375, 1375, 1375, + + 1612, 1612, 1612, 1612, 1375, 1376, 1612, 1612, 1612, 1376, + 1376, 1376, 1612, 1612, 1612, 1612, 1376, 1377, 1612, 1612, + 1612, 1377, 1377, 1377, 1612, 1612, 1612, 1612, 1377, 1381, + 1612, 1612, 1612, 1381, 1381, 1381, 1612, 1612, 1612, 1612, + 1381, 1382, 1612, 1612, 1612, 1382, 1382, 1382, 1612, 1612, + 1612, 1612, 1382, 1383, 1612, 1612, 1612, 1383, 1383, 1383, + 1612, 1612, 1612, 1612, 1383, 1384, 1612, 1612, 1612, 1384, + 1384, 1384, 1612, 1612, 1612, 1612, 1384, 1385, 1612, 1612, + 1612, 1385, 1385, 1385, 1612, 1612, 1612, 1612, 1385, 1386, + 1612, 1612, 1612, 1386, 1386, 1386, 1612, 1612, 1612, 1612, + + 1386, 1387, 1612, 1612, 1612, 1387, 1387, 1387, 1612, 1612, + 1612, 1612, 1387, 1390, 1612, 1612, 1612, 1390, 1390, 1390, + 1612, 1612, 1612, 1612, 1390, 1391, 1612, 1612, 1612, 1391, + 1391, 1391, 1612, 1612, 1612, 1612, 1391, 1392, 1612, 1612, + 1612, 1392, 1392, 1392, 1612, 1612, 1612, 1612, 1392, 1393, + 1612, 1612, 1612, 1393, 1393, 1393, 1612, 1612, 1612, 1612, + 1393, 1394, 1612, 1612, 1612, 1394, 1394, 1394, 1612, 1612, + 1612, 1612, 1394, 1395, 1612, 1612, 1612, 1395, 1395, 1395, + 1612, 1612, 1612, 1612, 1395, 1396, 1612, 1612, 1612, 1396, + 1396, 1396, 1612, 1612, 1612, 1612, 1396, 1397, 1612, 1612, + + 1612, 1397, 1397, 1397, 1612, 1612, 1612, 1612, 1397, 1398, + 1612, 1612, 1612, 1398, 1398, 1398, 1612, 1612, 1612, 1612, + 1398, 1402, 1612, 1612, 1612, 1402, 1402, 1402, 1612, 1612, + 1612, 1612, 1402, 1403, 1403, 1403, 1404, 1612, 1612, 1612, + 1404, 1404, 1404, 1612, 1612, 1612, 1612, 1404, 1407, 1407, + 1407, 1414, 1612, 1414, 1612, 1414, 1414, 1612, 1612, 1612, + 1612, 1612, 1414, 1417, 1612, 1417, 1612, 1417, 1417, 1612, + 1612, 1612, 1612, 1612, 1417, 1418, 1418, 1418, 1419, 1419, + 1419, 1225, 1612, 1612, 1612, 1225, 1225, 1225, 1612, 1612, + 1612, 1612, 1225, 1228, 1612, 1612, 1612, 1228, 1228, 1228, + + 1612, 1612, 1612, 1612, 1228, 1229, 1612, 1612, 1612, 1229, + 1229, 1229, 1612, 1612, 1612, 1612, 1229, 1230, 1612, 1612, + 1612, 1230, 1230, 1230, 1612, 1612, 1612, 1612, 1230, 1234, + 1612, 1612, 1612, 1234, 1234, 1234, 1612, 1612, 1612, 1612, + 1234, 1235, 1612, 1612, 1612, 1235, 1235, 1235, 1612, 1612, + 1612, 1612, 1235, 1236, 1612, 1612, 1612, 1236, 1236, 1236, + 1612, 1612, 1612, 1612, 1236, 1239, 1612, 1612, 1612, 1239, + 1239, 1239, 1612, 1612, 1612, 1612, 1239, 1240, 1612, 1612, + 1612, 1240, 1240, 1240, 1612, 1612, 1612, 1612, 1240, 1241, + 1612, 1612, 1612, 1241, 1241, 1241, 1612, 1612, 1612, 1612, + + 1241, 1242, 1612, 1612, 1612, 1242, 1242, 1242, 1612, 1612, + 1612, 1612, 1242, 1243, 1612, 1612, 1612, 1243, 1243, 1243, + 1612, 1612, 1612, 1612, 1243, 1247, 1612, 1612, 1612, 1247, + 1247, 1247, 1612, 1612, 1612, 1612, 1247, 1248, 1612, 1612, + 1612, 1248, 1248, 1248, 1612, 1612, 1612, 1612, 1248, 1249, + 1612, 1612, 1612, 1249, 1249, 1249, 1612, 1612, 1612, 1612, + 1249, 1250, 1612, 1612, 1612, 1250, 1250, 1250, 1612, 1612, + 1612, 1612, 1250, 1251, 1612, 1612, 1612, 1251, 1251, 1251, + 1612, 1612, 1612, 1612, 1251, 1252, 1612, 1612, 1612, 1252, + 1252, 1252, 1612, 1612, 1612, 1612, 1252, 1254, 1612, 1612, + + 1612, 1254, 1254, 1254, 1612, 1612, 1612, 1612, 1254, 1255, + 1612, 1612, 1612, 1255, 1255, 1255, 1612, 1612, 1612, 1612, + 1255, 1256, 1612, 1612, 1612, 1256, 1256, 1256, 1612, 1612, + 1612, 1612, 1256, 1257, 1612, 1612, 1612, 1257, 1257, 1257, + 1612, 1612, 1612, 1612, 1257, 1258, 1612, 1612, 1612, 1258, + 1258, 1258, 1612, 1612, 1612, 1612, 1258, 1259, 1612, 1612, + 1612, 1259, 1259, 1259, 1612, 1612, 1612, 1612, 1259, 1260, + 1612, 1612, 1612, 1260, 1260, 1260, 1612, 1612, 1612, 1612, + 1260, 1264, 1612, 1612, 1612, 1264, 1264, 1264, 1612, 1612, + 1612, 1612, 1264, 1265, 1612, 1612, 1612, 1265, 1265, 1265, + + 1612, 1612, 1612, 1612, 1265, 1266, 1612, 1612, 1612, 1266, + 1266, 1266, 1612, 1612, 1612, 1612, 1266, 1267, 1612, 1612, + 1612, 1267, 1267, 1267, 1612, 1612, 1612, 1612, 1267, 1268, + 1612, 1612, 1612, 1268, 1268, 1268, 1612, 1612, 1612, 1612, + 1268, 1269, 1612, 1612, 1612, 1269, 1269, 1269, 1612, 1612, + 1612, 1612, 1269, 1270, 1612, 1612, 1612, 1270, 1270, 1270, + 1612, 1612, 1612, 1612, 1270, 1273, 1612, 1612, 1612, 1273, + 1273, 1273, 1612, 1612, 1612, 1612, 1273, 1274, 1612, 1612, + 1612, 1274, 1274, 1274, 1612, 1612, 1612, 1612, 1274, 1275, + 1612, 1612, 1612, 1275, 1275, 1275, 1612, 1612, 1612, 1612, + + 1275, 1276, 1612, 1612, 1612, 1276, 1276, 1276, 1612, 1612, + 1612, 1612, 1276, 1277, 1612, 1612, 1612, 1277, 1277, 1277, + 1612, 1612, 1612, 1612, 1277, 1278, 1612, 1612, 1612, 1278, + 1278, 1278, 1612, 1612, 1612, 1612, 1278, 1279, 1612, 1612, + 1612, 1279, 1279, 1279, 1612, 1612, 1612, 1612, 1279, 1280, + 1612, 1612, 1612, 1280, 1280, 1280, 1612, 1612, 1612, 1612, + 1280, 1281, 1612, 1612, 1612, 1281, 1281, 1281, 1612, 1612, + 1612, 1612, 1281, 1424, 1612, 1612, 1612, 1424, 1424, 1424, + 1612, 1612, 1612, 1612, 1424, 1427, 1612, 1612, 1612, 1427, + 1427, 1427, 1612, 1612, 1612, 1612, 1427, 1428, 1612, 1612, + + 1612, 1428, 1428, 1428, 1612, 1612, 1612, 1612, 1428, 1429, + 1612, 1612, 1612, 1429, 1429, 1429, 1612, 1612, 1612, 1612, + 1429, 1433, 1612, 1612, 1612, 1433, 1433, 1433, 1612, 1612, + 1612, 1612, 1433, 1434, 1612, 1612, 1612, 1434, 1434, 1434, + 1612, 1612, 1612, 1612, 1434, 1435, 1612, 1612, 1612, 1435, + 1435, 1435, 1612, 1612, 1612, 1612, 1435, 1438, 1612, 1612, + 1612, 1438, 1438, 1438, 1612, 1612, 1612, 1612, 1438, 1439, + 1612, 1612, 1612, 1439, 1439, 1439, 1612, 1612, 1612, 1612, + 1439, 1440, 1612, 1612, 1612, 1440, 1440, 1440, 1612, 1612, + 1612, 1612, 1440, 1441, 1612, 1612, 1612, 1441, 1441, 1441, + + 1612, 1612, 1612, 1612, 1441, 1442, 1612, 1612, 1612, 1442, + 1442, 1442, 1612, 1612, 1612, 1612, 1442, 1446, 1612, 1612, + 1612, 1446, 1446, 1446, 1612, 1612, 1612, 1612, 1446, 1447, + 1612, 1612, 1612, 1447, 1447, 1447, 1612, 1612, 1612, 1612, + 1447, 1448, 1612, 1612, 1612, 1448, 1448, 1448, 1612, 1612, + 1612, 1612, 1448, 1449, 1612, 1612, 1612, 1449, 1449, 1449, + 1612, 1612, 1612, 1612, 1449, 1450, 1612, 1612, 1612, 1450, + 1450, 1450, 1612, 1612, 1612, 1612, 1450, 1451, 1612, 1612, + 1612, 1451, 1451, 1451, 1612, 1612, 1612, 1612, 1451, 1453, + 1612, 1612, 1612, 1453, 1453, 1453, 1612, 1612, 1612, 1612, + + 1453, 1454, 1612, 1612, 1612, 1454, 1454, 1454, 1612, 1612, + 1612, 1612, 1454, 1455, 1612, 1612, 1612, 1455, 1455, 1455, + 1612, 1612, 1612, 1612, 1455, 1456, 1612, 1612, 1612, 1456, + 1456, 1456, 1612, 1612, 1612, 1612, 1456, 1457, 1612, 1612, + 1612, 1457, 1457, 1457, 1612, 1612, 1612, 1612, 1457, 1458, + 1612, 1612, 1612, 1458, 1458, 1458, 1612, 1612, 1612, 1612, + 1458, 1459, 1612, 1612, 1612, 1459, 1459, 1459, 1612, 1612, + 1612, 1612, 1459, 1463, 1612, 1612, 1612, 1463, 1463, 1463, + 1612, 1612, 1612, 1612, 1463, 1464, 1612, 1612, 1612, 1464, + 1464, 1464, 1612, 1612, 1612, 1612, 1464, 1465, 1612, 1612, + + 1612, 1465, 1465, 1465, 1612, 1612, 1612, 1612, 1465, 1466, + 1612, 1612, 1612, 1466, 1466, 1466, 1612, 1612, 1612, 1612, + 1466, 1467, 1612, 1612, 1612, 1467, 1467, 1467, 1612, 1612, + 1612, 1612, 1467, 1468, 1612, 1612, 1612, 1468, 1468, 1468, + 1612, 1612, 1612, 1612, 1468, 1469, 1612, 1612, 1612, 1469, + 1469, 1469, 1612, 1612, 1612, 1612, 1469, 1472, 1612, 1612, + 1612, 1472, 1472, 1472, 1612, 1612, 1612, 1612, 1472, 1473, + 1612, 1612, 1612, 1473, 1473, 1473, 1612, 1612, 1612, 1612, + 1473, 1474, 1612, 1612, 1612, 1474, 1474, 1474, 1612, 1612, + 1612, 1612, 1474, 1475, 1612, 1612, 1612, 1475, 1475, 1475, + + 1612, 1612, 1612, 1612, 1475, 1476, 1612, 1612, 1612, 1476, + 1476, 1476, 1612, 1612, 1612, 1612, 1476, 1477, 1612, 1612, + 1612, 1477, 1477, 1477, 1612, 1612, 1612, 1612, 1477, 1478, + 1612, 1612, 1612, 1478, 1478, 1478, 1612, 1612, 1612, 1612, + 1478, 1479, 1612, 1612, 1612, 1479, 1479, 1479, 1612, 1612, + 1612, 1612, 1479, 1480, 1612, 1612, 1612, 1480, 1480, 1480, + 1612, 1612, 1612, 1612, 1480, 1342, 1612, 1612, 1612, 1342, + 1342, 1342, 1612, 1612, 1612, 1612, 1342, 1345, 1612, 1612, + 1612, 1345, 1345, 1345, 1612, 1612, 1612, 1612, 1345, 1346, + 1612, 1612, 1612, 1346, 1346, 1346, 1612, 1612, 1612, 1612, + + 1346, 1347, 1612, 1612, 1612, 1347, 1347, 1347, 1612, 1612, + 1612, 1612, 1347, 1351, 1612, 1612, 1612, 1351, 1351, 1351, + 1612, 1612, 1612, 1612, 1351, 1352, 1612, 1612, 1612, 1352, + 1352, 1352, 1612, 1612, 1612, 1612, 1352, 1353, 1612, 1612, + 1612, 1353, 1353, 1353, 1612, 1612, 1612, 1612, 1353, 1356, + 1612, 1612, 1612, 1356, 1356, 1356, 1612, 1612, 1612, 1612, + 1356, 1357, 1612, 1612, 1612, 1357, 1357, 1357, 1612, 1612, + 1612, 1612, 1357, 1358, 1612, 1612, 1612, 1358, 1358, 1358, + 1612, 1612, 1612, 1612, 1358, 1359, 1612, 1612, 1612, 1359, + 1359, 1359, 1612, 1612, 1612, 1612, 1359, 1360, 1612, 1612, + + 1612, 1360, 1360, 1360, 1612, 1612, 1612, 1612, 1360, 1364, + 1612, 1612, 1612, 1364, 1364, 1364, 1612, 1612, 1612, 1612, + 1364, 1365, 1612, 1612, 1612, 1365, 1365, 1365, 1612, 1612, + 1612, 1612, 1365, 1366, 1612, 1612, 1612, 1366, 1366, 1366, + 1612, 1612, 1612, 1612, 1366, 1367, 1612, 1612, 1612, 1367, + 1367, 1367, 1612, 1612, 1612, 1612, 1367, 1368, 1612, 1612, + 1612, 1368, 1368, 1368, 1612, 1612, 1612, 1612, 1368, 1369, + 1612, 1612, 1612, 1369, 1369, 1369, 1612, 1612, 1612, 1612, + 1369, 1371, 1612, 1612, 1612, 1371, 1371, 1371, 1612, 1612, + 1612, 1612, 1371, 1372, 1612, 1612, 1612, 1372, 1372, 1372, + + 1612, 1612, 1612, 1612, 1372, 1373, 1612, 1612, 1612, 1373, + 1373, 1373, 1612, 1612, 1612, 1612, 1373, 1374, 1612, 1612, + 1612, 1374, 1374, 1374, 1612, 1612, 1612, 1612, 1374, 1375, + 1612, 1612, 1612, 1375, 1375, 1375, 1612, 1612, 1612, 1612, + 1375, 1376, 1612, 1612, 1612, 1376, 1376, 1376, 1612, 1612, + 1612, 1612, 1376, 1377, 1612, 1612, 1612, 1377, 1377, 1377, + 1612, 1612, 1612, 1612, 1377, 1381, 1612, 1612, 1612, 1381, + 1381, 1381, 1612, 1612, 1612, 1612, 1381, 1382, 1612, 1612, + 1612, 1382, 1382, 1382, 1612, 1612, 1612, 1612, 1382, 1383, + 1612, 1612, 1612, 1383, 1383, 1383, 1612, 1612, 1612, 1612, + + 1383, 1384, 1612, 1612, 1612, 1384, 1384, 1384, 1612, 1612, + 1612, 1612, 1384, 1385, 1612, 1612, 1612, 1385, 1385, 1385, + 1612, 1612, 1612, 1612, 1385, 1386, 1612, 1612, 1612, 1386, + 1386, 1386, 1612, 1612, 1612, 1612, 1386, 1387, 1612, 1612, + 1612, 1387, 1387, 1387, 1612, 1612, 1612, 1612, 1387, 1390, + 1612, 1612, 1612, 1390, 1390, 1390, 1612, 1612, 1612, 1612, + 1390, 1391, 1612, 1612, 1612, 1391, 1391, 1391, 1612, 1612, + 1612, 1612, 1391, 1392, 1612, 1612, 1612, 1392, 1392, 1392, + 1612, 1612, 1612, 1612, 1392, 1393, 1612, 1612, 1612, 1393, + 1393, 1393, 1612, 1612, 1612, 1612, 1393, 1394, 1612, 1612, + + 1612, 1394, 1394, 1394, 1612, 1612, 1612, 1612, 1394, 1395, + 1612, 1612, 1612, 1395, 1395, 1395, 1612, 1612, 1612, 1612, + 1395, 1396, 1612, 1612, 1612, 1396, 1396, 1396, 1612, 1612, + 1612, 1612, 1396, 1397, 1612, 1612, 1612, 1397, 1397, 1397, + 1612, 1612, 1612, 1612, 1397, 1398, 1612, 1612, 1612, 1398, + 1398, 1398, 1612, 1612, 1612, 1612, 1398, 1484, 1612, 1612, + 1612, 1484, 1484, 1484, 1612, 1612, 1612, 1612, 1484, 1485, + 1485, 1485, 1486, 1612, 1612, 1612, 1486, 1486, 1486, 1612, + 1612, 1612, 1612, 1486, 1487, 1487, 1487, 1488, 1488, 1488, + 1612, 1612, 1612, 1612, 1488, 1489, 1489, 1489, 1491, 1491, + + 1491, 1497, 1497, 1497, 1502, 1502, 1502, 1505, 1612, 1505, + 1612, 1505, 1505, 1612, 1612, 1612, 1612, 1612, 1505, 1508, + 1612, 1508, 1612, 1508, 1508, 1612, 1612, 1612, 1612, 1612, + 1508, 1424, 1612, 1612, 1612, 1424, 1424, 1424, 1612, 1612, + 1612, 1612, 1424, 1427, 1612, 1612, 1612, 1427, 1427, 1427, + 1612, 1612, 1612, 1612, 1427, 1428, 1612, 1612, 1612, 1428, + 1428, 1428, 1612, 1612, 1612, 1612, 1428, 1429, 1612, 1612, + 1612, 1429, 1429, 1429, 1612, 1612, 1612, 1612, 1429, 1433, + 1612, 1612, 1612, 1433, 1433, 1433, 1612, 1612, 1612, 1612, + 1433, 1434, 1612, 1612, 1612, 1434, 1434, 1434, 1612, 1612, + + 1612, 1612, 1434, 1435, 1612, 1612, 1612, 1435, 1435, 1435, + 1612, 1612, 1612, 1612, 1435, 1438, 1612, 1612, 1612, 1438, + 1438, 1438, 1612, 1612, 1612, 1612, 1438, 1439, 1612, 1612, + 1612, 1439, 1439, 1439, 1612, 1612, 1612, 1612, 1439, 1440, + 1612, 1612, 1612, 1440, 1440, 1440, 1612, 1612, 1612, 1612, + 1440, 1441, 1612, 1612, 1612, 1441, 1441, 1441, 1612, 1612, + 1612, 1612, 1441, 1442, 1612, 1612, 1612, 1442, 1442, 1442, + 1612, 1612, 1612, 1612, 1442, 1446, 1612, 1612, 1612, 1446, + 1446, 1446, 1612, 1612, 1612, 1612, 1446, 1447, 1612, 1612, + 1612, 1447, 1447, 1447, 1612, 1612, 1612, 1612, 1447, 1448, + + 1612, 1612, 1612, 1448, 1448, 1448, 1612, 1612, 1612, 1612, + 1448, 1449, 1612, 1612, 1612, 1449, 1449, 1449, 1612, 1612, + 1612, 1612, 1449, 1450, 1612, 1612, 1612, 1450, 1450, 1450, + 1612, 1612, 1612, 1612, 1450, 1451, 1612, 1612, 1612, 1451, + 1451, 1451, 1612, 1612, 1612, 1612, 1451, 1453, 1612, 1612, + 1612, 1453, 1453, 1453, 1612, 1612, 1612, 1612, 1453, 1454, + 1612, 1612, 1612, 1454, 1454, 1454, 1612, 1612, 1612, 1612, + 1454, 1455, 1612, 1612, 1612, 1455, 1455, 1455, 1612, 1612, + 1612, 1612, 1455, 1456, 1612, 1612, 1612, 1456, 1456, 1456, + 1612, 1612, 1612, 1612, 1456, 1457, 1612, 1612, 1612, 1457, + + 1457, 1457, 1612, 1612, 1612, 1612, 1457, 1458, 1612, 1612, + 1612, 1458, 1458, 1458, 1612, 1612, 1612, 1612, 1458, 1459, + 1612, 1612, 1612, 1459, 1459, 1459, 1612, 1612, 1612, 1612, + 1459, 1463, 1612, 1612, 1612, 1463, 1463, 1463, 1612, 1612, + 1612, 1612, 1463, 1464, 1612, 1612, 1612, 1464, 1464, 1464, + 1612, 1612, 1612, 1612, 1464, 1465, 1612, 1612, 1612, 1465, + 1465, 1465, 1612, 1612, 1612, 1612, 1465, 1466, 1612, 1612, + 1612, 1466, 1466, 1466, 1612, 1612, 1612, 1612, 1466, 1467, + 1612, 1612, 1612, 1467, 1467, 1467, 1612, 1612, 1612, 1612, + 1467, 1468, 1612, 1612, 1612, 1468, 1468, 1468, 1612, 1612, + + 1612, 1612, 1468, 1469, 1612, 1612, 1612, 1469, 1469, 1469, + 1612, 1612, 1612, 1612, 1469, 1472, 1612, 1612, 1612, 1472, + 1472, 1472, 1612, 1612, 1612, 1612, 1472, 1473, 1612, 1612, + 1612, 1473, 1473, 1473, 1612, 1612, 1612, 1612, 1473, 1474, + 1612, 1612, 1612, 1474, 1474, 1474, 1612, 1612, 1612, 1612, + 1474, 1475, 1612, 1612, 1612, 1475, 1475, 1475, 1612, 1612, + 1612, 1612, 1475, 1476, 1612, 1612, 1612, 1476, 1476, 1476, + 1612, 1612, 1612, 1612, 1476, 1477, 1612, 1612, 1612, 1477, + 1477, 1477, 1612, 1612, 1612, 1612, 1477, 1478, 1612, 1612, + 1612, 1478, 1478, 1478, 1612, 1612, 1612, 1612, 1478, 1479, + + 1612, 1612, 1612, 1479, 1479, 1479, 1612, 1612, 1612, 1612, + 1479, 1480, 1612, 1612, 1612, 1480, 1480, 1480, 1612, 1612, + 1612, 1612, 1480, 1509, 1612, 1612, 1612, 1509, 1509, 1509, + 1612, 1612, 1612, 1612, 1509, 1510, 1510, 1510, 1511, 1612, + 1612, 1612, 1511, 1511, 1511, 1612, 1612, 1612, 1612, 1511, + 1512, 1512, 1512, 1513, 1513, 1513, 1514, 1514, 1514, 1515, + 1515, 1515, 1520, 1612, 1520, 1612, 1520, 1520, 1612, 1612, + 1612, 1612, 1612, 1520, 1525, 1612, 1525, 1612, 1525, 1525, + 1612, 1612, 1612, 1612, 1612, 1525, 1530, 1530, 1530, 1535, + 1535, 1535, 1536, 1612, 1612, 1612, 1536, 1536, 1536, 1612, + + 1612, 1612, 1612, 1536, 1537, 1537, 1537, 1538, 1612, 1612, + 1612, 1538, 1538, 1538, 1612, 1612, 1612, 1612, 1538, 1539, + 1539, 1539, 1540, 1540, 1540, 1544, 1544, 1544, 1548, 1548, + 1548, 1553, 1612, 1553, 1612, 1553, 1553, 1612, 1612, 1612, + 1612, 1612, 1553, 1558, 1612, 1558, 1612, 1558, 1558, 1612, + 1612, 1612, 1612, 1612, 1558, 1559, 1559, 1559, 1560, 1612, + 1612, 1612, 1560, 1560, 1560, 1612, 1612, 1612, 1612, 1560, + 1561, 1561, 1561, 1562, 1562, 1562, 1563, 1563, 1563, 1565, + 1565, 1565, 1570, 1570, 1570, 1574, 1574, 1574, 1575, 1575, + 1575, 1576, 1576, 1576, 1577, 1577, 1577, 1578, 1578, 1578, + + 1579, 1579, 1579, 1581, 1581, 1581, 1585, 1585, 1585, 1586, + 1612, 1586, 1612, 1586, 1586, 1586, 1612, 1612, 1612, 1612, + 1586, 1587, 1612, 1587, 1612, 1587, 1587, 1587, 1612, 1612, + 1612, 1612, 1587, 1588, 1588, 1588, 1589, 1589, 1589, 1593, + 1612, 1593, 1612, 1593, 1593, 1593, 1612, 1612, 1612, 1612, + 1593, 1594, 1612, 1594, 1612, 1594, 1594, 1594, 1612, 1612, + 1612, 1612, 1594, 1595, 1612, 1595, 1612, 1595, 1595, 1595, + 1612, 1612, 1612, 1612, 1595, 1596, 1612, 1596, 1612, 1596, + 1596, 1596, 1612, 1612, 1612, 1612, 1596, 1597, 1597, 1597, + 1598, 1612, 1598, 1612, 1598, 1598, 1598, 1612, 1612, 1612, + + 1612, 1598, 1599, 1612, 1599, 1612, 1599, 1599, 1599, 1612, + 1612, 1612, 1612, 1599, 1600, 1612, 1600, 1612, 1600, 1600, + 1600, 1612, 1612, 1612, 1612, 1600, 1601, 1612, 1601, 1612, + 1601, 1601, 1601, 1612, 1612, 1612, 1612, 1601, 1602, 1612, + 1602, 1612, 1602, 1602, 1602, 1612, 1612, 1612, 1612, 1602, + 1603, 1612, 1603, 1612, 1603, 1603, 1603, 1612, 1612, 1612, + 1612, 1603, 1604, 1612, 1604, 1612, 1604, 1604, 1604, 1612, + 1612, 1612, 1612, 1604, 1605, 1612, 1605, 1612, 1605, 1605, + 1605, 1612, 1612, 1612, 1612, 1605, 1606, 1612, 1606, 1612, + 1606, 1606, 1606, 1612, 1612, 1612, 1612, 1606, 1607, 1612, + + 1607, 1612, 1607, 1607, 1607, 1612, 1612, 1612, 1612, 1607, + 1608, 1612, 1608, 1612, 1608, 1608, 1608, 1612, 1612, 1612, + 1612, 1608, 1609, 1612, 1609, 1612, 1609, 1609, 1609, 1612, + 1612, 1612, 1612, 1609, 1610, 1612, 1610, 1612, 1610, 1610, + 1610, 1612, 1612, 1612, 1612, 1610, 1611, 1612, 1611, 1612, + 1611, 1611, 1611, 1612, 1612, 1612, 1612, 1611, 3, 1612, + 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, + 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, + 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, + 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612 + + } ; + +static yyconst flex_int16_t yy_chk[16700] = + { 0, + 0, 0, 1, 0, 15, 17, 43, 0, 43, 43, + 53, 53, 53, 70, 70, 70, 70, 39, 39, 48, + 48, 92, 92, 1597, 15, 17, 1, 1, 1, 6, + 1, 1, 8, 14, 1, 1, 14, 6, 1, 1, + 2, 10, 14, 8, 8, 10, 18, 18, 20, 20, + 19, 22, 19, 19, 19, 30, 98, 98, 1573, 28, + 18, 1572, 20, 1569, 2, 2, 2, 75, 2, 2, + 19, 22, 2, 2, 28, 30, 2, 2, 21, 25, + 21, 21, 75, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 31, 32, 25, 1568, 35, 21, 25, + + 25, 26, 26, 26, 36, 37, 41, 41, 42, 1562, + 42, 42, 42, 31, 32, 45, 26, 35, 55, 45, + 41, 1557, 50, 50, 36, 37, 57, 46, 42, 46, + 46, 46, 59, 60, 45, 45, 50, 61, 55, 52, + 45, 52, 52, 56, 77, 73, 57, 46, 56, 56, + 108, 108, 59, 60, 1555, 78, 79, 61, 1552, 52, + 54, 73, 74, 56, 77, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 78, 79, 80, 74, 1550, + 54, 58, 64, 58, 58, 1547, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 65, 80, 64, 66, + + 1546, 58, 64, 64, 1543, 67, 1542, 68, 1524, 71, + 71, 71, 65, 83, 84, 66, 65, 65, 85, 66, + 66, 67, 86, 68, 71, 67, 67, 68, 68, 100, + 1522, 100, 100, 83, 84, 94, 95, 1519, 85, 96, + 1517, 111, 86, 88, 88, 88, 88, 88, 90, 90, + 90, 90, 90, 97, 94, 94, 95, 97, 96, 96, + 94, 111, 113, 99, 96, 99, 99, 99, 170, 170, + 102, 112, 97, 97, 102, 1482, 112, 112, 97, 125, + 125, 125, 113, 99, 104, 104, 104, 104, 104, 102, + 102, 112, 172, 172, 1411, 102, 106, 106, 106, 106, + + 106, 110, 114, 1406, 116, 1283, 110, 110, 110, 110, + 110, 110, 110, 110, 110, 110, 179, 179, 118, 119, + 117, 110, 114, 115, 116, 117, 117, 120, 115, 115, + 115, 115, 115, 115, 115, 115, 115, 115, 118, 119, + 117, 1213, 124, 115, 124, 124, 1211, 120, 121, 1208, + 127, 260, 260, 121, 121, 121, 121, 121, 121, 121, + 121, 121, 121, 122, 122, 122, 122, 122, 121, 123, + 127, 123, 123, 1207, 123, 123, 123, 123, 123, 123, + 123, 123, 123, 123, 126, 262, 262, 129, 130, 126, + 126, 126, 126, 126, 126, 126, 126, 126, 126, 131, + + 128, 132, 133, 138, 126, 128, 128, 129, 130, 136, + 984, 137, 149, 149, 149, 149, 983, 139, 980, 131, + 128, 132, 133, 138, 138, 136, 140, 137, 141, 136, + 136, 137, 137, 139, 142, 978, 143, 139, 139, 250, + 250, 250, 140, 144, 141, 145, 140, 140, 141, 141, + 142, 146, 143, 147, 142, 142, 143, 143, 152, 144, + 153, 145, 154, 144, 144, 145, 145, 146, 147, 156, + 157, 146, 146, 147, 152, 160, 153, 161, 154, 167, + 167, 167, 167, 167, 169, 169, 169, 169, 169, 156, + 157, 171, 174, 247, 175, 160, 974, 161, 176, 352, + + 352, 177, 796, 178, 189, 191, 793, 178, 788, 247, + 171, 171, 174, 175, 175, 785, 171, 783, 176, 175, + 177, 177, 178, 178, 189, 191, 177, 782, 178, 185, + 185, 185, 185, 185, 187, 187, 187, 187, 187, 188, + 477, 477, 192, 193, 188, 188, 188, 188, 188, 188, + 188, 188, 188, 188, 197, 190, 251, 251, 251, 188, + 190, 190, 192, 193, 195, 195, 195, 195, 195, 616, + 616, 199, 198, 200, 197, 190, 194, 198, 198, 201, + 204, 194, 194, 194, 194, 194, 194, 194, 194, 194, + 194, 199, 198, 200, 619, 619, 194, 196, 781, 201, + + 204, 205, 196, 196, 196, 196, 196, 196, 196, 196, + 196, 196, 203, 203, 203, 203, 203, 196, 202, 206, + 628, 205, 208, 202, 202, 202, 202, 202, 202, 202, + 202, 202, 202, 626, 626, 210, 212, 625, 202, 206, + 207, 618, 208, 615, 213, 207, 207, 207, 207, 207, + 207, 207, 207, 207, 207, 210, 212, 211, 215, 613, + 207, 209, 211, 211, 213, 612, 209, 209, 209, 209, + 209, 209, 209, 209, 209, 209, 469, 211, 215, 216, + 217, 209, 214, 218, 216, 216, 219, 214, 214, 214, + 214, 214, 214, 214, 214, 214, 214, 629, 629, 216, + + 217, 366, 214, 218, 786, 786, 219, 220, 222, 223, + 225, 351, 220, 220, 220, 220, 220, 220, 220, 220, + 220, 220, 221, 221, 221, 221, 221, 220, 222, 223, + 225, 225, 226, 325, 227, 249, 244, 244, 244, 248, + 228, 246, 229, 278, 278, 278, 278, 278, 230, 224, + 231, 244, 226, 226, 227, 227, 228, 232, 229, 233, + 228, 228, 229, 229, 230, 234, 231, 235, 230, 230, + 231, 231, 158, 232, 236, 155, 237, 232, 232, 233, + 233, 234, 238, 235, 239, 234, 234, 235, 235, 241, + 236, 240, 237, 245, 236, 236, 237, 237, 238, 257, + + 239, 259, 238, 238, 239, 239, 261, 240, 245, 241, + 264, 240, 240, 245, 272, 274, 275, 265, 276, 257, + 279, 259, 265, 265, 151, 261, 261, 266, 789, 789, + 264, 261, 266, 266, 272, 274, 275, 265, 276, 150, + 279, 794, 794, 280, 273, 281, 283, 266, 271, 273, + 273, 285, 135, 271, 271, 271, 271, 271, 271, 271, + 271, 271, 271, 280, 273, 281, 283, 286, 271, 277, + 134, 285, 286, 286, 277, 277, 277, 277, 277, 277, + 277, 277, 277, 277, 109, 287, 288, 286, 289, 277, + 282, 93, 292, 293, 294, 282, 282, 282, 282, 282, + + 282, 282, 282, 282, 282, 287, 288, 76, 289, 72, + 282, 284, 292, 293, 294, 296, 284, 284, 284, 284, + 284, 284, 284, 284, 284, 284, 291, 291, 291, 291, + 291, 284, 290, 63, 297, 296, 298, 290, 290, 290, + 290, 290, 290, 290, 290, 290, 290, 62, 299, 300, + 304, 306, 290, 295, 297, 307, 298, 308, 295, 295, + 295, 295, 295, 295, 295, 295, 295, 295, 299, 300, + 304, 306, 51, 295, 301, 307, 312, 308, 314, 301, + 301, 301, 301, 301, 301, 301, 301, 301, 301, 302, + 302, 302, 302, 302, 301, 303, 312, 49, 314, 40, + + 303, 303, 303, 303, 303, 303, 303, 303, 303, 303, + 315, 305, 354, 354, 354, 303, 305, 305, 310, 310, + 310, 310, 310, 347, 347, 347, 347, 316, 313, 319, + 315, 305, 309, 313, 313, 320, 321, 309, 309, 309, + 309, 309, 309, 309, 309, 309, 309, 316, 313, 319, + 797, 797, 309, 311, 34, 320, 321, 323, 311, 311, + 311, 311, 311, 311, 311, 311, 311, 311, 318, 318, + 318, 318, 318, 311, 317, 24, 324, 323, 326, 317, + 317, 317, 317, 317, 317, 317, 317, 317, 317, 16, + 327, 13, 328, 12, 317, 322, 324, 332, 326, 326, + + 322, 322, 322, 322, 322, 322, 322, 322, 322, 322, + 327, 327, 328, 328, 329, 322, 330, 332, 332, 333, + 979, 979, 331, 11, 334, 9, 344, 356, 356, 356, + 329, 335, 330, 336, 329, 329, 330, 330, 331, 333, + 333, 337, 331, 331, 334, 334, 344, 335, 338, 336, + 339, 335, 335, 336, 336, 348, 340, 337, 341, 7, + 360, 337, 337, 3, 338, 342, 339, 343, 338, 338, + 339, 339, 340, 0, 341, 348, 340, 340, 341, 341, + 360, 342, 362, 343, 363, 342, 342, 343, 357, 357, + 357, 358, 358, 358, 365, 365, 365, 367, 369, 369, + + 369, 370, 362, 371, 363, 373, 370, 370, 371, 371, + 379, 379, 379, 379, 379, 1106, 1106, 367, 0, 375, + 376, 370, 374, 371, 372, 373, 377, 374, 374, 372, + 372, 372, 372, 372, 372, 372, 372, 372, 372, 375, + 376, 0, 374, 380, 372, 381, 377, 378, 382, 0, + 384, 385, 378, 378, 378, 378, 378, 378, 378, 378, + 378, 378, 0, 380, 386, 381, 387, 378, 382, 383, + 384, 385, 388, 0, 383, 383, 383, 383, 383, 383, + 383, 383, 383, 383, 386, 0, 387, 1210, 1210, 383, + 1214, 1214, 388, 389, 0, 392, 394, 395, 389, 389, + + 389, 389, 389, 389, 389, 389, 389, 389, 390, 390, + 390, 390, 390, 389, 391, 392, 394, 395, 396, 391, + 391, 391, 391, 391, 391, 391, 391, 391, 391, 399, + 393, 0, 400, 401, 391, 393, 393, 0, 396, 398, + 398, 398, 398, 398, 1400, 1400, 403, 404, 405, 399, + 393, 397, 400, 401, 406, 407, 397, 397, 397, 397, + 397, 397, 397, 397, 397, 397, 403, 404, 405, 1412, + 1412, 397, 402, 0, 406, 407, 410, 402, 402, 402, + 402, 402, 402, 402, 402, 402, 402, 409, 409, 409, + 409, 409, 402, 408, 411, 412, 410, 413, 408, 408, + + 408, 408, 408, 408, 408, 408, 408, 408, 414, 415, + 416, 0, 418, 408, 411, 412, 0, 413, 474, 474, + 474, 0, 415, 415, 1413, 1413, 420, 0, 414, 415, + 416, 417, 418, 0, 421, 422, 417, 417, 417, 417, + 417, 417, 417, 417, 417, 417, 420, 419, 0, 425, + 426, 417, 419, 419, 421, 422, 424, 424, 424, 424, + 424, 1415, 1415, 427, 429, 431, 432, 419, 423, 425, + 426, 432, 432, 423, 423, 423, 423, 423, 423, 423, + 423, 423, 423, 427, 429, 431, 432, 433, 423, 428, + 0, 434, 435, 438, 428, 428, 428, 428, 428, 428, + + 428, 428, 428, 428, 479, 479, 479, 433, 0, 428, + 430, 434, 435, 438, 439, 430, 430, 430, 430, 430, + 430, 430, 430, 430, 430, 437, 437, 437, 437, 437, + 430, 436, 440, 0, 439, 442, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 1416, 1416, 443, 444, + 445, 436, 440, 441, 446, 442, 449, 450, 441, 441, + 441, 441, 441, 441, 441, 441, 441, 441, 443, 444, + 445, 1503, 1503, 441, 446, 447, 449, 450, 451, 0, + 447, 447, 447, 447, 447, 447, 447, 447, 447, 447, + 448, 448, 448, 448, 448, 447, 452, 0, 451, 451, + + 453, 0, 454, 475, 475, 475, 475, 0, 455, 0, + 456, 457, 0, 458, 0, 459, 452, 452, 454, 0, + 453, 453, 454, 454, 455, 460, 456, 461, 455, 455, + 456, 457, 457, 458, 458, 459, 459, 462, 0, 463, + 0, 460, 470, 461, 471, 460, 460, 461, 461, 464, + 0, 465, 466, 462, 0, 463, 0, 462, 462, 463, + 463, 467, 470, 484, 471, 464, 0, 465, 466, 464, + 464, 465, 466, 476, 476, 476, 476, 467, 481, 481, + 481, 467, 482, 484, 487, 491, 483, 482, 482, 482, + 482, 483, 483, 483, 483, 486, 486, 486, 489, 489, + + 489, 0, 482, 492, 487, 491, 483, 490, 492, 492, + 493, 494, 490, 490, 490, 490, 490, 490, 490, 490, + 490, 490, 495, 492, 498, 499, 500, 490, 1504, 1504, + 493, 494, 497, 497, 497, 497, 497, 0, 502, 503, + 504, 505, 495, 496, 498, 499, 500, 506, 496, 496, + 496, 496, 496, 496, 496, 496, 496, 496, 502, 503, + 504, 505, 0, 496, 501, 0, 509, 506, 510, 501, + 501, 501, 501, 501, 501, 501, 501, 501, 501, 508, + 508, 508, 508, 508, 501, 507, 509, 511, 510, 512, + 507, 507, 507, 507, 507, 507, 507, 507, 507, 507, + + 513, 514, 515, 0, 517, 507, 518, 511, 0, 512, + 0, 518, 518, 0, 514, 514, 1506, 1506, 519, 520, + 513, 514, 515, 516, 517, 521, 518, 524, 516, 516, + 516, 516, 516, 516, 516, 516, 516, 516, 519, 520, + 621, 621, 621, 516, 0, 521, 522, 524, 525, 526, + 0, 522, 522, 522, 522, 522, 522, 522, 522, 522, + 522, 523, 523, 523, 523, 523, 522, 528, 525, 526, + 527, 529, 530, 531, 532, 527, 527, 527, 527, 527, + 527, 527, 527, 527, 527, 1507, 1507, 528, 1514, 1514, + 527, 529, 530, 531, 532, 533, 535, 536, 537, 538, + + 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, + 534, 534, 534, 534, 534, 533, 535, 536, 537, 538, + 539, 540, 541, 542, 543, 544, 545, 546, 547, 549, + 549, 549, 549, 551, 540, 540, 622, 622, 622, 622, + 539, 540, 541, 542, 543, 544, 545, 546, 547, 548, + 981, 981, 0, 551, 548, 548, 548, 548, 548, 548, + 548, 548, 548, 548, 981, 553, 552, 554, 555, 548, + 550, 552, 552, 558, 559, 550, 550, 550, 550, 550, + 550, 550, 550, 550, 550, 553, 552, 554, 555, 0, + 550, 556, 560, 558, 559, 562, 556, 556, 556, 556, + + 556, 556, 556, 556, 556, 556, 557, 557, 557, 557, + 557, 556, 560, 561, 563, 562, 564, 565, 561, 561, + 561, 561, 561, 561, 561, 561, 561, 561, 566, 0, + 570, 1515, 1515, 561, 563, 0, 564, 565, 568, 568, + 568, 568, 568, 0, 572, 573, 571, 574, 566, 567, + 570, 571, 571, 577, 567, 567, 567, 567, 567, 567, + 567, 567, 567, 567, 572, 573, 571, 574, 0, 567, + 569, 0, 578, 577, 579, 569, 569, 569, 569, 569, + 569, 569, 569, 569, 569, 576, 576, 576, 576, 576, + 569, 575, 578, 581, 579, 582, 575, 575, 575, 575, + + 575, 575, 575, 575, 575, 575, 0, 583, 584, 585, + 588, 575, 580, 581, 589, 582, 590, 580, 580, 580, + 580, 580, 580, 580, 580, 580, 580, 583, 584, 585, + 588, 0, 580, 586, 589, 591, 590, 592, 586, 586, + 586, 586, 586, 586, 586, 586, 586, 586, 587, 587, + 587, 587, 587, 586, 593, 591, 594, 592, 595, 596, + 0, 597, 0, 598, 1496, 1496, 1496, 593, 593, 599, + 600, 601, 0, 602, 593, 603, 594, 0, 595, 596, + 596, 597, 597, 598, 604, 599, 600, 605, 0, 599, + 600, 601, 601, 602, 602, 603, 603, 606, 607, 608, + + 604, 633, 609, 605, 604, 604, 609, 605, 605, 623, + 623, 623, 623, 606, 607, 608, 635, 606, 607, 608, + 630, 633, 609, 636, 631, 630, 630, 630, 630, 631, + 631, 631, 631, 1501, 1501, 1501, 635, 1529, 1529, 1529, + 630, 634, 637, 636, 631, 632, 634, 634, 640, 641, + 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, + 0, 634, 637, 1738, 1738, 632, 638, 642, 640, 641, + 644, 638, 638, 638, 638, 638, 638, 638, 638, 638, + 638, 639, 639, 639, 639, 639, 638, 642, 643, 645, + 644, 646, 647, 643, 643, 643, 643, 643, 643, 643, + + 643, 643, 643, 648, 0, 651, 652, 653, 643, 645, + 0, 646, 647, 650, 650, 650, 650, 650, 0, 654, + 655, 1802, 1802, 648, 649, 651, 652, 653, 656, 649, + 649, 649, 649, 649, 649, 649, 649, 649, 649, 654, + 655, 656, 656, 657, 649, 658, 659, 660, 656, 661, + 662, 663, 665, 665, 665, 665, 667, 673, 673, 673, + 673, 673, 0, 657, 0, 658, 659, 660, 668, 661, + 662, 663, 664, 668, 668, 669, 667, 664, 664, 664, + 664, 664, 664, 664, 664, 664, 664, 0, 668, 670, + 671, 674, 664, 666, 0, 669, 675, 676, 666, 666, + + 666, 666, 666, 666, 666, 666, 666, 666, 0, 670, + 671, 674, 678, 666, 672, 0, 675, 676, 679, 672, + 672, 672, 672, 672, 672, 672, 672, 672, 672, 0, + 680, 681, 678, 682, 672, 677, 0, 685, 679, 686, + 677, 677, 677, 677, 677, 677, 677, 677, 677, 677, + 680, 681, 0, 682, 0, 677, 683, 685, 687, 686, + 688, 683, 683, 683, 683, 683, 683, 683, 683, 683, + 683, 684, 684, 684, 684, 684, 683, 689, 687, 690, + 688, 691, 692, 693, 694, 695, 696, 697, 699, 699, + 699, 699, 690, 690, 1534, 1534, 1534, 689, 0, 690, + + 0, 691, 692, 693, 694, 695, 696, 697, 698, 700, + 701, 702, 703, 698, 698, 698, 698, 698, 698, 698, + 698, 698, 698, 704, 705, 706, 0, 708, 698, 700, + 701, 702, 703, 716, 716, 716, 716, 716, 1803, 1803, + 0, 710, 712, 704, 705, 706, 707, 708, 1804, 1804, + 713, 707, 707, 707, 707, 707, 707, 707, 707, 707, + 707, 710, 712, 711, 714, 717, 707, 709, 711, 711, + 713, 718, 709, 709, 709, 709, 709, 709, 709, 709, + 709, 709, 0, 711, 714, 717, 719, 709, 715, 0, + 721, 718, 722, 715, 715, 715, 715, 715, 715, 715, + + 715, 715, 715, 0, 723, 724, 719, 725, 715, 720, + 721, 728, 722, 729, 720, 720, 720, 720, 720, 720, + 720, 720, 720, 720, 723, 724, 0, 725, 0, 720, + 726, 728, 730, 729, 731, 726, 726, 726, 726, 726, + 726, 726, 726, 726, 726, 727, 727, 727, 727, 727, + 726, 732, 730, 733, 731, 734, 0, 736, 737, 738, + 739, 1807, 1807, 737, 737, 0, 733, 733, 1809, 1809, + 0, 732, 740, 733, 743, 734, 735, 736, 737, 738, + 739, 735, 735, 735, 735, 735, 735, 735, 735, 735, + 735, 0, 740, 0, 743, 0, 735, 741, 744, 745, + + 0, 747, 741, 741, 741, 741, 741, 741, 741, 741, + 741, 741, 742, 742, 742, 742, 742, 741, 744, 745, + 746, 747, 748, 749, 750, 746, 746, 746, 746, 746, + 746, 746, 746, 746, 746, 751, 0, 754, 755, 756, + 746, 0, 748, 749, 750, 753, 753, 753, 753, 753, + 0, 757, 758, 1878, 1878, 751, 752, 754, 755, 756, + 759, 752, 752, 752, 752, 752, 752, 752, 752, 752, + 752, 757, 758, 759, 759, 760, 752, 761, 762, 763, + 759, 764, 765, 766, 768, 768, 768, 768, 769, 780, + 780, 780, 780, 1879, 1879, 760, 0, 761, 762, 763, + + 770, 764, 765, 766, 767, 771, 0, 772, 769, 767, + 767, 767, 767, 767, 767, 767, 767, 767, 767, 773, + 770, 774, 775, 799, 767, 771, 771, 772, 772, 778, + 800, 801, 802, 778, 0, 800, 800, 774, 775, 773, + 790, 774, 775, 799, 803, 790, 790, 790, 791, 778, + 800, 801, 802, 791, 791, 791, 831, 831, 831, 831, + 790, 1880, 1880, 0, 803, 1881, 1881, 0, 791, 798, + 0, 806, 807, 808, 798, 798, 798, 798, 798, 798, + 798, 798, 798, 798, 805, 805, 805, 805, 805, 798, + 804, 806, 807, 808, 810, 804, 804, 804, 804, 804, + + 804, 804, 804, 804, 804, 0, 811, 812, 813, 814, + 804, 809, 0, 817, 810, 818, 809, 809, 809, 809, + 809, 809, 809, 809, 809, 809, 811, 812, 813, 814, + 0, 809, 815, 817, 819, 818, 820, 815, 815, 815, + 815, 815, 815, 815, 815, 815, 815, 816, 816, 816, + 816, 816, 815, 821, 819, 822, 820, 823, 824, 825, + 826, 827, 828, 829, 0, 832, 833, 834, 822, 822, + 1882, 1882, 0, 821, 0, 822, 0, 823, 824, 825, + 826, 827, 828, 829, 830, 832, 833, 834, 835, 830, + 830, 830, 830, 830, 830, 830, 830, 830, 830, 836, + + 837, 838, 0, 840, 830, 842, 843, 0, 835, 1967, + 1967, 843, 843, 874, 874, 874, 874, 844, 845, 836, + 837, 838, 839, 840, 846, 842, 843, 839, 839, 839, + 839, 839, 839, 839, 839, 839, 839, 844, 845, 1969, + 1969, 0, 839, 841, 846, 849, 850, 851, 841, 841, + 841, 841, 841, 841, 841, 841, 841, 841, 848, 848, + 848, 848, 848, 841, 847, 849, 850, 851, 853, 847, + 847, 847, 847, 847, 847, 847, 847, 847, 847, 0, + 854, 855, 856, 857, 847, 852, 0, 860, 853, 861, + 852, 852, 852, 852, 852, 852, 852, 852, 852, 852, + + 854, 855, 856, 857, 0, 852, 858, 860, 862, 861, + 863, 858, 858, 858, 858, 858, 858, 858, 858, 858, + 858, 859, 859, 859, 859, 859, 858, 864, 862, 865, + 863, 866, 867, 868, 869, 870, 871, 872, 0, 875, + 876, 877, 865, 865, 1970, 1970, 0, 864, 0, 865, + 0, 866, 867, 868, 869, 870, 871, 872, 873, 875, + 876, 877, 878, 873, 873, 873, 873, 873, 873, 873, + 873, 873, 873, 879, 880, 881, 0, 883, 873, 884, + 885, 0, 878, 893, 893, 893, 893, 893, 1971, 1971, + 0, 886, 887, 879, 880, 881, 882, 883, 888, 884, + + 885, 882, 882, 882, 882, 882, 882, 882, 882, 882, + 882, 886, 887, 889, 890, 891, 882, 895, 888, 896, + 897, 1972, 1972, 0, 896, 896, 901, 901, 901, 901, + 901, 898, 899, 889, 890, 891, 892, 895, 902, 896, + 897, 892, 892, 892, 892, 892, 892, 892, 892, 892, + 892, 898, 899, 903, 904, 906, 892, 894, 902, 907, + 908, 909, 894, 894, 894, 894, 894, 894, 894, 894, + 894, 894, 0, 903, 904, 906, 910, 894, 900, 907, + 908, 909, 913, 900, 900, 900, 900, 900, 900, 900, + 900, 900, 900, 1973, 1973, 0, 910, 0, 900, 905, + + 0, 914, 913, 915, 905, 905, 905, 905, 905, 905, + 905, 905, 905, 905, 912, 912, 912, 912, 912, 905, + 911, 914, 916, 915, 917, 911, 911, 911, 911, 911, + 911, 911, 911, 911, 911, 918, 919, 920, 921, 922, + 911, 923, 916, 924, 917, 925, 0, 929, 918, 918, + 927, 927, 927, 927, 0, 918, 919, 920, 921, 922, + 0, 923, 931, 924, 930, 925, 926, 929, 932, 930, + 930, 926, 926, 926, 926, 926, 926, 926, 926, 926, + 926, 0, 931, 933, 930, 936, 926, 928, 932, 937, + 938, 940, 928, 928, 928, 928, 928, 928, 928, 928, + + 928, 928, 0, 933, 0, 936, 0, 928, 934, 937, + 938, 940, 941, 934, 934, 934, 934, 934, 934, 934, + 934, 934, 934, 935, 935, 935, 935, 935, 934, 939, + 942, 943, 941, 944, 939, 939, 939, 939, 939, 939, + 939, 939, 939, 939, 946, 946, 946, 946, 946, 939, + 942, 943, 947, 944, 945, 948, 949, 950, 951, 945, + 945, 945, 945, 945, 945, 945, 945, 945, 945, 952, + 953, 954, 947, 955, 945, 948, 949, 950, 951, 956, + 957, 958, 952, 952, 959, 961, 961, 961, 961, 952, + 953, 954, 0, 955, 982, 982, 982, 982, 0, 956, + + 957, 958, 962, 963, 959, 960, 964, 965, 966, 967, + 960, 960, 960, 960, 960, 960, 960, 960, 960, 960, + 968, 0, 962, 963, 970, 960, 964, 965, 966, 967, + 986, 986, 986, 986, 2082, 2082, 971, 972, 973, 992, + 968, 969, 2083, 2083, 970, 0, 969, 969, 969, 969, + 969, 969, 969, 969, 969, 969, 971, 972, 973, 992, + 994, 969, 988, 988, 988, 988, 989, 0, 995, 990, + 0, 989, 989, 989, 990, 990, 990, 2084, 2084, 0, + 994, 1024, 1024, 1024, 1024, 996, 989, 993, 995, 990, + 991, 0, 993, 993, 999, 991, 991, 991, 991, 991, + + 991, 991, 991, 991, 991, 996, 0, 993, 2085, 2085, + 991, 997, 1000, 1001, 999, 1003, 997, 997, 997, 997, + 997, 997, 997, 997, 997, 997, 998, 998, 998, 998, + 998, 997, 1000, 1001, 1002, 1003, 1004, 1005, 1006, 1002, + 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1007, + 0, 1010, 1011, 1012, 1002, 0, 1004, 1005, 1006, 1009, + 1009, 1009, 1009, 1009, 0, 1013, 1014, 2086, 2086, 1007, + 1008, 1010, 1011, 1012, 1015, 1008, 1008, 1008, 1008, 1008, + 1008, 1008, 1008, 1008, 1008, 1013, 1014, 1015, 1015, 1016, + 1008, 1017, 1018, 1019, 1015, 1020, 1021, 1022, 0, 1025, + + 1026, 1027, 1028, 1043, 1043, 1043, 1043, 1043, 0, 1016, + 0, 1017, 1018, 1019, 1029, 1020, 1021, 1022, 1023, 1025, + 1026, 1027, 1028, 1023, 1023, 1023, 1023, 1023, 1023, 1023, + 1023, 1023, 1023, 1030, 1029, 1031, 0, 1033, 1023, 1034, + 1035, 1051, 1051, 1051, 1051, 1051, 1062, 1062, 1062, 1062, + 1062, 1036, 1037, 1030, 1038, 1031, 1032, 1033, 1039, 1034, + 1035, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, + 1032, 1036, 1037, 1040, 1038, 1041, 1032, 1045, 1039, 1046, + 1047, 2223, 2223, 0, 1046, 1046, 1077, 1077, 1077, 1077, + 0, 1048, 1049, 1040, 1052, 1041, 1042, 1045, 1053, 1046, + + 1047, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, + 1042, 1048, 1049, 1054, 1052, 1056, 1042, 1044, 1053, 1057, + 1058, 1059, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, + 1044, 1044, 0, 1054, 1060, 1056, 1063, 1044, 1050, 1057, + 1058, 1059, 1064, 1050, 1050, 1050, 1050, 1050, 1050, 1050, + 1050, 1050, 1050, 0, 1060, 1065, 1063, 1066, 1050, 1055, + 0, 1067, 1064, 1069, 1055, 1055, 1055, 1055, 1055, 1055, + 1055, 1055, 1055, 1055, 0, 1065, 0, 1066, 1070, 1055, + 1061, 1067, 1068, 1069, 1071, 1061, 1061, 1061, 1061, 1061, + 1061, 1061, 1061, 1061, 1061, 1068, 1068, 1072, 1070, 1073, + + 1061, 1074, 1068, 1075, 1071, 1078, 1079, 1080, 1081, 1096, + 1096, 1096, 1096, 1096, 2387, 2387, 0, 1072, 0, 1073, + 1082, 1074, 1083, 1075, 1076, 1078, 1079, 1080, 1081, 1076, + 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1084, + 1082, 1086, 1083, 1087, 1076, 1115, 1115, 1115, 1115, 1115, + 1126, 1126, 1126, 1126, 1126, 1088, 1089, 1090, 1091, 1084, + 1085, 1086, 1092, 1087, 1093, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1088, 1089, 1090, 1091, 1094, + 1085, 1107, 1092, 1109, 1093, 1141, 1141, 1141, 1141, 1158, + 1158, 1158, 1158, 1158, 0, 1111, 1112, 0, 1113, 1094, + + 1095, 1107, 0, 1109, 1116, 1095, 1095, 1095, 1095, 1095, + 1095, 1095, 1095, 1095, 1095, 1111, 1112, 1110, 1113, 1117, + 1095, 1108, 1110, 1110, 1116, 1118, 1108, 1108, 1108, 1108, + 1108, 1108, 1108, 1108, 1108, 1108, 0, 1110, 1120, 1117, + 1121, 1108, 1114, 0, 1122, 1118, 1123, 1114, 1114, 1114, + 1114, 1114, 1114, 1114, 1114, 1114, 1114, 0, 1120, 1124, + 1121, 1127, 1114, 1119, 1122, 1128, 1123, 1129, 1119, 1119, + 1119, 1119, 1119, 1119, 1119, 1119, 1119, 1119, 0, 1124, + 1130, 1127, 1131, 1119, 1125, 1128, 1133, 1129, 1134, 1125, + 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1132, + + 1130, 1135, 1131, 1136, 1125, 1137, 1133, 1138, 1134, 1139, + 0, 1142, 1132, 1132, 1143, 1184, 1184, 1184, 1184, 1132, + 0, 1135, 0, 1136, 0, 1137, 1144, 1138, 1145, 1139, + 1140, 1142, 1146, 1147, 1143, 1140, 1140, 1140, 1140, 1140, + 1140, 1140, 1140, 1140, 1140, 1148, 1144, 1150, 1145, 1152, + 1140, 0, 1146, 1147, 1169, 1169, 1169, 1169, 1169, 2574, + 2574, 1154, 1155, 0, 1156, 1148, 1149, 1150, 0, 1152, + 1159, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, 1149, + 1149, 1154, 1155, 1153, 1156, 1160, 1149, 1151, 1153, 1153, + 1159, 1161, 1151, 1151, 1151, 1151, 1151, 1151, 1151, 1151, + + 1151, 1151, 0, 1153, 1163, 1160, 1164, 1151, 1157, 0, + 1165, 1161, 1166, 1157, 1157, 1157, 1157, 1157, 1157, 1157, + 1157, 1157, 1157, 0, 1163, 1167, 1164, 1170, 1157, 1162, + 1165, 1171, 1166, 1172, 1162, 1162, 1162, 1162, 1162, 1162, + 1162, 1162, 1162, 1162, 0, 1167, 1173, 1170, 1174, 1162, + 1168, 1171, 1176, 1172, 1177, 1168, 1168, 1168, 1168, 1168, + 1168, 1168, 1168, 1168, 1168, 1175, 1173, 1178, 1174, 1179, + 1168, 1180, 1176, 1181, 1177, 1182, 0, 1185, 1175, 1175, + 1186, 1218, 1218, 1218, 1218, 1175, 0, 1178, 0, 1179, + 0, 1180, 1187, 1181, 1188, 1182, 1183, 1185, 1189, 1190, + + 1186, 1183, 1183, 1183, 1183, 1183, 1183, 1183, 1183, 1183, + 1183, 1191, 1187, 1193, 1188, 1194, 1183, 0, 1189, 1190, + 1203, 1203, 1203, 1203, 1203, 2575, 2575, 1195, 1196, 1197, + 1198, 1191, 1192, 1193, 1199, 1194, 1200, 1192, 1192, 1192, + 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1195, 1196, 1197, + 1198, 1201, 1192, 1204, 1199, 1206, 1200, 1220, 1220, 1220, + 1220, 1228, 1228, 1228, 1228, 1228, 0, 1215, 0, 1215, + 1215, 1201, 1202, 1204, 1222, 1206, 1224, 1202, 1202, 1202, + 1202, 1202, 1202, 1202, 1202, 1202, 1202, 1215, 1216, 0, + 1216, 1216, 1202, 1223, 1222, 0, 1224, 0, 1223, 1223, + + 1254, 1254, 1254, 1254, 1225, 1226, 1229, 1230, 1216, 1221, + 0, 1231, 1233, 1223, 1221, 1221, 1221, 1221, 1221, 1221, + 1221, 1221, 1221, 1221, 1225, 1226, 1229, 1230, 1234, 1221, + 1227, 1231, 1233, 1235, 1236, 1227, 1227, 1227, 1227, 1227, + 1227, 1227, 1227, 1227, 1227, 0, 1237, 1240, 1234, 1241, + 1227, 1232, 0, 1235, 1236, 1242, 1232, 1232, 1232, 1232, + 1232, 1232, 1232, 1232, 1232, 1232, 1237, 1240, 0, 1241, + 0, 1232, 1238, 1243, 1244, 1242, 1246, 1238, 1238, 1238, + 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1239, 1239, 1239, + 1239, 1239, 1238, 1243, 1244, 1245, 1246, 1247, 1248, 1249, + + 1250, 1251, 1252, 0, 1255, 1256, 1257, 1258, 1245, 1245, + 1273, 1273, 1273, 1273, 1273, 1245, 0, 1247, 1248, 1249, + 1250, 1251, 1252, 1253, 1255, 1256, 1257, 1258, 1253, 1253, + 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1253, 1259, 1260, + 1261, 0, 1263, 1253, 1264, 1265, 1292, 1292, 1292, 1292, + 1292, 1303, 1303, 1303, 1303, 1303, 1266, 1267, 1259, 1260, + 1261, 1262, 1263, 1268, 1264, 1265, 1262, 1262, 1262, 1262, + 1262, 1262, 1262, 1262, 1262, 1262, 1266, 1267, 1269, 1270, + 1271, 1262, 1284, 1268, 1286, 1287, 1318, 1318, 1318, 1318, + 1287, 1287, 1371, 1371, 1371, 1371, 1288, 1289, 1269, 1270, + + 1271, 1272, 1284, 1290, 1286, 1287, 1272, 1272, 1272, 1272, + 1272, 1272, 1272, 1272, 1272, 1272, 1288, 1289, 1293, 1294, + 1295, 1272, 1285, 1290, 1297, 1298, 1299, 1285, 1285, 1285, + 1285, 1285, 1285, 1285, 1285, 1285, 1285, 0, 1293, 1294, + 1295, 1300, 1285, 1291, 1297, 1298, 1299, 1301, 1291, 1291, + 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 0, 1304, + 1305, 1300, 1306, 1291, 1296, 0, 1307, 1301, 1308, 1296, + 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1296, 1304, + 1305, 0, 1306, 1310, 1296, 1302, 1307, 1309, 1308, 1311, + 1302, 1302, 1302, 1302, 1302, 1302, 1302, 1302, 1302, 1302, + + 1309, 1309, 1312, 1310, 1313, 1302, 1314, 1309, 1315, 1311, + 1316, 0, 1319, 1320, 1321, 1322, 1337, 1337, 1337, 1337, + 1337, 0, 1312, 0, 1313, 0, 1314, 1323, 1315, 1324, + 1316, 1317, 1319, 1320, 1321, 1322, 1317, 1317, 1317, 1317, + 1317, 1317, 1317, 1317, 1317, 1317, 1325, 1323, 1327, 1324, + 1328, 1317, 1345, 1345, 1345, 1345, 1345, 1356, 1356, 1356, + 1356, 1356, 1329, 1330, 1331, 1332, 1325, 1326, 1327, 1333, + 1328, 1334, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, + 1326, 1326, 1329, 1330, 1331, 1332, 1335, 1326, 1339, 1333, + 1340, 1334, 2577, 2577, 0, 1340, 1340, 1390, 1390, 1390, + + 1390, 1390, 1341, 1342, 1343, 1346, 1335, 1336, 1339, 1347, + 1340, 1348, 1336, 1336, 1336, 1336, 1336, 1336, 1336, 1336, + 1336, 1336, 1341, 1342, 1343, 1346, 1350, 1336, 1338, 1347, + 1351, 1348, 1352, 1338, 1338, 1338, 1338, 1338, 1338, 1338, + 1338, 1338, 1338, 0, 1353, 1354, 1350, 1357, 1338, 1344, + 1351, 1358, 1352, 1359, 1344, 1344, 1344, 1344, 1344, 1344, + 1344, 1344, 1344, 1344, 1353, 1354, 1360, 1357, 1361, 1344, + 1349, 1358, 1363, 1359, 1364, 1349, 1349, 1349, 1349, 1349, + 1349, 1349, 1349, 1349, 1349, 0, 1360, 0, 1361, 1365, + 1349, 1355, 1363, 1362, 1364, 1366, 1355, 1355, 1355, 1355, + + 1355, 1355, 1355, 1355, 1355, 1355, 1362, 1362, 1367, 1365, + 1368, 1355, 1369, 1362, 1372, 1366, 1373, 1374, 1408, 1408, + 1408, 1408, 1408, 1410, 1410, 1410, 1410, 1410, 1367, 1375, + 1368, 1376, 1369, 1370, 1372, 1377, 1373, 1374, 1370, 1370, + 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1370, 1378, 1375, + 1380, 1376, 1381, 1370, 0, 1377, 1427, 1427, 1427, 1427, + 1427, 2578, 2578, 0, 1382, 1383, 1384, 1385, 1378, 1379, + 1380, 1386, 1381, 1387, 1379, 1379, 1379, 1379, 1379, 1379, + 1379, 1379, 1379, 1379, 1382, 1383, 1384, 1385, 1388, 1379, + 1401, 1386, 1402, 1387, 1438, 1438, 1438, 1438, 1438, 1453, + + 1453, 1453, 1453, 0, 1404, 0, 1421, 0, 1388, 1389, + 1401, 1423, 1402, 0, 1389, 1389, 1389, 1389, 1389, 1389, + 1389, 1389, 1389, 1389, 1404, 1418, 1421, 1418, 1418, 1389, + 1419, 1423, 1419, 1419, 1422, 1424, 2587, 2587, 0, 1422, + 1422, 1591, 1591, 1591, 1591, 1418, 1425, 1428, 1429, 1430, + 1419, 1420, 0, 1432, 1422, 1424, 1420, 1420, 1420, 1420, + 1420, 1420, 1420, 1420, 1420, 1420, 1425, 1428, 1429, 1430, + 1433, 1420, 1426, 1432, 1434, 1435, 1436, 1426, 1426, 1426, + 1426, 1426, 1426, 1426, 1426, 1426, 1426, 0, 1439, 1440, + 1433, 1441, 1426, 1431, 1434, 1435, 1436, 1442, 1431, 1431, + + 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1439, 1440, + 1443, 1441, 0, 1431, 1437, 1445, 1446, 1442, 1444, 1437, + 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1437, 1447, + 1443, 1444, 1444, 1448, 1437, 1445, 1446, 1449, 1444, 1450, + 1451, 0, 1454, 1455, 1456, 1457, 2589, 2589, 0, 1447, + 2591, 2591, 0, 1448, 2592, 2592, 1458, 1449, 1459, 1450, + 1451, 1452, 1454, 1455, 1456, 1457, 1452, 1452, 1452, 1452, + 1452, 1452, 1452, 1452, 1452, 1452, 1458, 1460, 1459, 1462, + 1463, 1452, 1464, 1472, 1472, 1472, 1472, 1472, 1494, 1494, + 1494, 1494, 1494, 1465, 1466, 1467, 1468, 1460, 1461, 1462, + + 1463, 1469, 1464, 1461, 1461, 1461, 1461, 1461, 1461, 1461, + 1461, 1461, 1461, 1465, 1466, 1467, 1468, 1470, 1461, 1483, + 1484, 1469, 1486, 1499, 1499, 1499, 1499, 1499, 1527, 1527, + 1527, 1527, 1527, 1497, 0, 1497, 1497, 1470, 1471, 1483, + 1484, 1509, 1486, 1471, 1471, 1471, 1471, 1471, 1471, 1471, + 1471, 1471, 1471, 1497, 1502, 1511, 1502, 1502, 1471, 1536, + 1530, 1509, 1530, 1530, 1532, 1532, 1532, 1532, 1532, 1535, + 1538, 1535, 1535, 0, 1502, 1511, 1560, 1563, 1565, 1536, + 1530, 1544, 0, 1544, 1544, 1544, 1575, 2594, 2594, 1535, + 1538, 1548, 0, 1548, 1548, 1548, 1560, 1563, 1565, 1579, + + 1570, 1544, 1570, 1570, 1570, 1574, 1575, 1574, 1574, 1574, + 1577, 1548, 1577, 1577, 1578, 1581, 1578, 1578, 1583, 1579, + 1570, 1584, 1584, 1584, 1585, 1574, 1586, 0, 1586, 1586, + 1577, 2595, 2595, 1592, 1578, 1581, 1584, 1587, 1583, 1587, + 1587, 2603, 2603, 0, 1585, 1588, 1586, 1588, 1588, 1589, + 0, 1589, 1589, 1592, 2605, 2605, 1593, 1587, 1593, 1593, + 1594, 0, 1594, 1594, 1595, 1588, 1595, 1595, 1596, 1589, + 1596, 1596, 1598, 0, 1598, 1598, 1593, 0, 0, 1599, + 1594, 1599, 1599, 1600, 1595, 1600, 1600, 1601, 1596, 1601, + 1601, 1602, 1598, 1602, 1602, 1603, 0, 1603, 1603, 1599, + + 0, 0, 1604, 1600, 1604, 1604, 1605, 1601, 1605, 1605, + 1606, 1602, 1606, 1606, 1607, 1603, 1607, 1607, 1608, 0, + 1608, 1608, 1604, 0, 0, 1609, 1605, 1609, 1609, 1610, + 1606, 1610, 1610, 1611, 1607, 1611, 1611, 0, 1608, 0, + 0, 0, 0, 0, 0, 1609, 0, 0, 0, 1610, + 0, 0, 0, 1611, 1613, 1613, 1613, 1613, 1613, 1613, + 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, 1613, + 1613, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, + 1614, 1614, 1614, 1614, 1614, 1615, 1615, 1615, 0, 0, + 0, 0, 1615, 1616, 0, 0, 0, 1616, 1616, 1616, + + 0, 0, 1616, 1616, 1616, 1617, 1617, 1617, 0, 0, + 0, 0, 1617, 1618, 0, 1618, 1618, 1618, 1618, 1618, + 0, 0, 0, 0, 1618, 1619, 1619, 1619, 0, 0, + 0, 0, 1619, 1620, 1620, 1620, 1620, 1620, 1620, 1620, + 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1620, 1621, 1621, + 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, 1621, + 1621, 1621, 1621, 1621, 1622, 1622, 1622, 1622, 1622, 1622, + 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1622, 1623, + 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, 1623, + 1623, 0, 1623, 1623, 1624, 1624, 1624, 0, 0, 0, + + 0, 1624, 1625, 1625, 1625, 1625, 1625, 1625, 1625, 1625, + 1625, 1625, 0, 1625, 1625, 1626, 1626, 1626, 1626, 1626, + 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1626, 1627, + 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, 1627, + 1627, 1627, 1627, 1628, 1628, 1628, 1629, 1629, 1629, 0, + 0, 0, 0, 1629, 1630, 0, 0, 0, 1630, 1630, + 1630, 0, 0, 1630, 1630, 1630, 1631, 1631, 1631, 1632, + 1632, 1632, 0, 0, 0, 0, 1632, 1633, 1633, 1633, + 1634, 0, 0, 1634, 1634, 1634, 1634, 0, 0, 0, + 1634, 1634, 0, 1634, 1635, 0, 1635, 1635, 1635, 1635, + + 1635, 0, 0, 0, 0, 1635, 1636, 1636, 1636, 1637, + 1637, 1637, 0, 0, 0, 0, 1637, 1638, 1638, 1638, + 1639, 0, 0, 0, 1639, 1639, 1639, 0, 0, 0, + 0, 1639, 1640, 0, 0, 0, 1640, 1640, 1640, 0, + 0, 0, 0, 1640, 1641, 1641, 1641, 1641, 1641, 1641, + 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1642, + 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, 1642, + 1642, 1642, 1642, 1642, 1643, 1643, 1643, 1643, 1643, 1643, + 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1644, + 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, 1644, + + 1644, 1644, 1644, 1644, 1645, 1645, 1645, 1646, 1646, 1646, + 1646, 0, 0, 0, 0, 1646, 1647, 1647, 1647, 0, + 0, 0, 0, 1647, 1648, 1648, 1648, 1648, 1648, 1648, + 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1648, 1649, 1649, + 1649, 1650, 1650, 1650, 1651, 1651, 1651, 1652, 1652, 1652, + 1653, 1653, 1653, 1654, 0, 0, 0, 1654, 1654, 1654, + 0, 0, 0, 1654, 1654, 0, 1654, 1655, 0, 1655, + 1655, 1655, 1656, 1656, 1656, 1657, 0, 0, 1657, 1657, + 1657, 1657, 0, 0, 0, 1657, 1657, 0, 1657, 1658, + 1658, 1658, 1659, 1659, 1659, 1660, 1660, 1660, 1661, 0, + + 0, 0, 1661, 1661, 1661, 0, 0, 0, 0, 1661, + 1662, 0, 0, 0, 1662, 1662, 1662, 0, 0, 0, + 0, 1662, 1663, 0, 0, 0, 1663, 1663, 1663, 0, + 0, 0, 0, 1663, 1664, 0, 0, 0, 1664, 1664, + 1664, 0, 0, 0, 0, 1664, 1665, 0, 0, 0, + 1665, 1665, 1665, 0, 0, 0, 0, 1665, 1666, 0, + 0, 0, 1666, 1666, 1666, 0, 0, 0, 0, 1666, + 1667, 1667, 1667, 1668, 0, 0, 0, 1668, 1668, 1668, + 0, 0, 0, 0, 1668, 1669, 0, 0, 0, 1669, + 1669, 1669, 0, 0, 0, 0, 1669, 1670, 1670, 1670, + + 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, 1670, + 1670, 1670, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, + 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1672, 1672, 1672, + 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, 1672, + 1672, 1672, 1672, 1673, 1673, 1673, 1673, 1673, 1673, 1673, + 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1673, 1674, 1674, + 1674, 1674, 1674, 1674, 1674, 1674, 1674, 0, 1674, 1674, + 1674, 1674, 1674, 1675, 1675, 1675, 1675, 1675, 1675, 1675, + 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1675, 1676, 1676, + 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, 1676, + + 1676, 1676, 1676, 1677, 1677, 1677, 1677, 1677, 1677, 1677, + 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1678, 1678, + 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, 1678, + 1678, 1678, 1678, 1679, 1679, 1679, 1679, 1679, 1679, 1679, + 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1679, 1680, 1680, + 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, + 1680, 1680, 1680, 1681, 0, 0, 0, 1681, 1681, 0, + 1681, 0, 0, 0, 1681, 1682, 1682, 1682, 1683, 1683, + 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1683, + 0, 1683, 1683, 1684, 1684, 1684, 1685, 1685, 1685, 1685, + + 0, 0, 0, 0, 1685, 1686, 1686, 1686, 1686, 0, + 0, 0, 0, 1686, 1687, 1687, 1687, 1687, 1687, 1687, + 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1687, 1688, 1688, + 1688, 1689, 0, 0, 0, 1689, 1689, 1689, 0, 0, + 1689, 1689, 1689, 1690, 1690, 1690, 1691, 1691, 1691, 1692, + 1692, 1692, 1693, 1693, 1693, 1694, 0, 1694, 1694, 1694, + 1695, 0, 0, 0, 1695, 1695, 1695, 0, 0, 0, + 1695, 1695, 0, 1695, 1696, 0, 1696, 1696, 1696, 1697, + 1697, 1697, 1698, 0, 0, 0, 1698, 1698, 1698, 0, + 0, 0, 1698, 1698, 0, 1698, 1699, 0, 0, 0, + + 1699, 1699, 1699, 0, 0, 0, 1699, 1699, 0, 1699, + 1700, 0, 0, 1700, 1700, 1700, 1700, 0, 0, 0, + 1700, 1700, 0, 1700, 1701, 0, 1701, 1701, 1701, 1702, + 1702, 1702, 1703, 1703, 1703, 1704, 1704, 1704, 1705, 1705, + 1705, 1706, 0, 0, 0, 1706, 1706, 1706, 0, 0, + 0, 0, 1706, 1707, 0, 0, 0, 1707, 1707, 1707, + 0, 0, 0, 0, 1707, 1708, 0, 0, 0, 1708, + 1708, 1708, 0, 0, 0, 0, 1708, 1709, 0, 0, + 0, 1709, 1709, 1709, 0, 0, 0, 0, 1709, 1710, + 0, 0, 0, 1710, 1710, 1710, 0, 0, 0, 0, + + 1710, 1711, 0, 0, 0, 1711, 1711, 1711, 0, 0, + 0, 0, 1711, 1712, 0, 0, 0, 1712, 1712, 1712, + 0, 0, 0, 0, 1712, 1713, 0, 0, 0, 1713, + 1713, 1713, 0, 0, 0, 0, 1713, 1714, 0, 0, + 0, 1714, 1714, 1714, 0, 0, 0, 0, 1714, 1715, + 0, 0, 0, 1715, 1715, 1715, 0, 0, 0, 0, + 1715, 1716, 0, 0, 0, 1716, 1716, 1716, 0, 0, + 0, 0, 1716, 1717, 0, 0, 0, 1717, 1717, 1717, + 0, 0, 0, 0, 1717, 1718, 0, 0, 0, 1718, + 1718, 1718, 0, 0, 0, 0, 1718, 1719, 0, 0, + + 0, 1719, 1719, 1719, 0, 0, 0, 0, 1719, 1720, + 0, 0, 0, 1720, 1720, 1720, 0, 0, 0, 0, + 1720, 1721, 0, 0, 0, 1721, 1721, 1721, 0, 0, + 0, 0, 1721, 1722, 0, 0, 0, 1722, 1722, 1722, + 0, 0, 0, 0, 1722, 1723, 0, 0, 0, 1723, + 1723, 1723, 0, 0, 0, 0, 1723, 1724, 1724, 1724, + 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, 1724, + 1724, 1724, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, + 1725, 0, 1725, 1725, 1725, 0, 1725, 1726, 1726, 1726, + 1726, 1726, 1726, 1726, 1726, 1726, 0, 1726, 1726, 1726, + + 1726, 1726, 1727, 1727, 1727, 1727, 1727, 1727, 1727, 1727, + 1727, 0, 1727, 1727, 1727, 1727, 1727, 1728, 1728, 1728, + 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, 1728, + 1728, 1728, 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1729, + 1729, 1729, 1729, 1729, 1729, 1729, 1729, 1730, 1730, 1730, + 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, 1730, + 1730, 1730, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, + 1731, 0, 1731, 1731, 1731, 1731, 1731, 1732, 1732, 1732, + 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, 1732, + 1732, 1732, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1733, + + 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1734, 1734, 1734, + 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, 1734, + 1734, 1734, 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1735, + 1735, 1735, 1735, 1735, 1735, 1735, 1735, 1736, 1736, 1736, + 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, 1736, + 1736, 1736, 1737, 1737, 1737, 1739, 0, 0, 0, 1739, + 1739, 0, 1739, 0, 0, 0, 1739, 1740, 1740, 1740, + 1741, 1741, 1741, 1741, 0, 0, 0, 0, 1741, 1742, + 1742, 1742, 1743, 1743, 1743, 1744, 1744, 1744, 1745, 1745, + 1745, 1746, 0, 1746, 1746, 1746, 1747, 0, 0, 0, + + 1747, 1747, 1747, 0, 0, 0, 1747, 1747, 0, 1747, + 1748, 0, 1748, 1748, 1748, 1749, 1749, 1749, 1750, 1750, + 1750, 1751, 1751, 1751, 1752, 0, 0, 0, 1752, 1752, + 1752, 0, 0, 0, 0, 1752, 1753, 0, 0, 0, + 1753, 1753, 1753, 0, 0, 0, 0, 1753, 1754, 0, + 0, 0, 1754, 1754, 1754, 0, 0, 0, 0, 1754, + 1755, 0, 0, 0, 1755, 1755, 1755, 0, 0, 0, + 0, 1755, 1756, 0, 0, 0, 1756, 1756, 1756, 0, + 0, 0, 0, 1756, 1757, 0, 0, 0, 1757, 1757, + 1757, 0, 0, 0, 0, 1757, 1758, 0, 0, 0, + + 1758, 1758, 1758, 0, 0, 0, 0, 1758, 1759, 0, + 0, 0, 1759, 1759, 1759, 0, 0, 0, 0, 1759, + 1760, 0, 0, 0, 1760, 1760, 1760, 0, 0, 0, + 0, 1760, 1761, 0, 0, 0, 1761, 1761, 1761, 0, + 0, 0, 0, 1761, 1762, 0, 0, 0, 1762, 1762, + 1762, 0, 0, 0, 0, 1762, 1763, 0, 0, 0, + 1763, 1763, 1763, 0, 0, 0, 0, 1763, 1764, 0, + 0, 0, 1764, 1764, 1764, 0, 0, 0, 0, 1764, + 1765, 0, 0, 0, 1765, 1765, 1765, 0, 0, 0, + 0, 1765, 1766, 0, 0, 0, 1766, 1766, 1766, 0, + + 0, 0, 0, 1766, 1767, 0, 0, 0, 1767, 1767, + 1767, 0, 0, 0, 0, 1767, 1768, 0, 0, 0, + 1768, 1768, 1768, 0, 0, 0, 0, 1768, 1769, 0, + 0, 0, 1769, 1769, 1769, 0, 0, 0, 0, 1769, + 1770, 0, 0, 0, 1770, 1770, 1770, 0, 0, 0, + 0, 1770, 1771, 0, 0, 0, 1771, 1771, 1771, 0, + 0, 0, 0, 1771, 1772, 0, 0, 0, 1772, 1772, + 1772, 0, 0, 0, 0, 1772, 1773, 0, 0, 0, + 1773, 1773, 1773, 0, 0, 0, 0, 1773, 1774, 0, + 0, 0, 1774, 1774, 1774, 0, 0, 0, 0, 1774, + + 1775, 0, 0, 0, 1775, 1775, 1775, 0, 0, 0, + 0, 1775, 1776, 0, 0, 0, 1776, 1776, 1776, 0, + 0, 0, 0, 1776, 1777, 0, 0, 0, 1777, 1777, + 1777, 0, 0, 0, 0, 1777, 1778, 0, 0, 0, + 1778, 1778, 1778, 0, 0, 0, 0, 1778, 1779, 0, + 0, 0, 1779, 1779, 1779, 0, 0, 0, 0, 1779, + 1780, 0, 0, 0, 1780, 1780, 1780, 0, 0, 0, + 0, 1780, 1781, 0, 0, 0, 1781, 1781, 1781, 0, + 0, 0, 0, 1781, 1782, 0, 0, 0, 1782, 1782, + 1782, 0, 0, 0, 0, 1782, 1783, 0, 0, 0, + + 1783, 1783, 1783, 0, 0, 0, 0, 1783, 1784, 1784, + 1784, 1784, 1784, 1784, 1784, 1784, 1784, 0, 1784, 1784, + 1784, 0, 1784, 1785, 1785, 1785, 1785, 1785, 1785, 1785, + 1785, 1785, 0, 1785, 1785, 1785, 0, 1785, 1786, 1786, + 1786, 1786, 1786, 1786, 1786, 1786, 1786, 0, 1786, 1786, + 1786, 1786, 1786, 1787, 1787, 1787, 1787, 1787, 1787, 1787, + 1787, 1787, 0, 1787, 1787, 1787, 1787, 1787, 1788, 1788, + 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, 1788, + 1788, 1788, 1788, 1789, 1789, 1789, 1789, 1789, 1789, 1789, + 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1789, 1790, 1790, + + 1790, 1790, 1790, 1790, 1790, 1790, 1790, 0, 1790, 1790, + 1790, 1790, 1790, 1791, 1791, 1791, 1791, 1791, 1791, 1791, + 1791, 1791, 0, 1791, 1791, 1791, 1791, 1791, 1792, 1792, + 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, 1792, + 1792, 1792, 1792, 1793, 1793, 1793, 1793, 1793, 1793, 1793, + 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1794, 1794, + 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, 1794, + 1794, 1794, 1794, 1795, 1795, 1795, 1795, 1795, 1795, 1795, + 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1796, 1796, + 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, 1796, + + 1796, 1796, 1796, 1797, 1797, 1797, 1797, 1797, 1797, 1797, + 1797, 1797, 1797, 1797, 1797, 1797, 0, 1797, 1798, 0, + 0, 0, 1798, 1798, 0, 0, 0, 0, 0, 1798, + 1799, 1799, 1799, 1800, 1800, 1800, 1801, 1801, 1801, 1805, + 1805, 1805, 1806, 1806, 1806, 1808, 1808, 1808, 0, 0, + 0, 0, 1808, 1810, 0, 0, 0, 1810, 1810, 1810, + 0, 0, 0, 0, 1810, 1811, 0, 0, 0, 1811, + 1811, 1811, 0, 0, 0, 0, 1811, 1812, 0, 0, + 0, 1812, 1812, 1812, 0, 0, 0, 0, 1812, 1813, + 0, 0, 0, 1813, 1813, 1813, 0, 0, 0, 0, + + 1813, 1814, 0, 0, 0, 1814, 1814, 1814, 0, 0, + 0, 0, 1814, 1815, 0, 0, 0, 1815, 1815, 1815, + 0, 0, 0, 0, 1815, 1816, 0, 0, 0, 1816, + 1816, 1816, 0, 0, 0, 0, 1816, 1817, 0, 0, + 0, 1817, 1817, 1817, 0, 0, 0, 0, 1817, 1818, + 0, 0, 0, 1818, 1818, 1818, 0, 0, 0, 0, + 1818, 1819, 0, 0, 0, 1819, 1819, 1819, 0, 0, + 0, 0, 1819, 1820, 0, 0, 0, 1820, 1820, 1820, + 0, 0, 0, 0, 1820, 1821, 0, 0, 0, 1821, + 1821, 1821, 0, 0, 0, 0, 1821, 1822, 0, 0, + + 0, 1822, 1822, 1822, 0, 0, 0, 0, 1822, 1823, + 0, 0, 0, 1823, 1823, 1823, 0, 0, 0, 0, + 1823, 1824, 0, 0, 0, 1824, 1824, 1824, 0, 0, + 0, 0, 1824, 1825, 0, 0, 0, 1825, 1825, 1825, + 0, 0, 0, 0, 1825, 1826, 0, 0, 0, 1826, + 1826, 1826, 0, 0, 0, 0, 1826, 1827, 0, 0, + 0, 1827, 1827, 1827, 0, 0, 0, 0, 1827, 1828, + 0, 0, 0, 1828, 1828, 1828, 0, 0, 0, 0, + 1828, 1829, 0, 0, 0, 1829, 1829, 1829, 0, 0, + 0, 0, 1829, 1830, 0, 0, 0, 1830, 1830, 1830, + + 0, 0, 0, 0, 1830, 1831, 0, 0, 0, 1831, + 1831, 1831, 0, 0, 0, 0, 1831, 1832, 0, 0, + 0, 1832, 1832, 1832, 0, 0, 0, 0, 1832, 1833, + 0, 0, 0, 1833, 1833, 1833, 0, 0, 0, 0, + 1833, 1834, 0, 0, 0, 1834, 1834, 1834, 0, 0, + 0, 0, 1834, 1835, 0, 0, 0, 1835, 1835, 1835, + 0, 0, 0, 0, 1835, 1836, 0, 0, 0, 1836, + 1836, 1836, 0, 0, 0, 0, 1836, 1837, 0, 0, + 0, 1837, 1837, 1837, 0, 0, 0, 0, 1837, 1838, + 0, 0, 0, 1838, 1838, 1838, 0, 0, 0, 0, + + 1838, 1839, 0, 0, 0, 1839, 1839, 1839, 0, 0, + 0, 0, 1839, 1840, 0, 0, 0, 1840, 1840, 1840, + 0, 0, 0, 0, 1840, 1841, 0, 0, 0, 1841, + 1841, 1841, 0, 0, 0, 0, 1841, 1842, 0, 0, + 0, 1842, 1842, 1842, 0, 0, 0, 0, 1842, 1843, + 0, 0, 0, 1843, 1843, 1843, 0, 0, 0, 0, + 1843, 1844, 0, 0, 0, 1844, 1844, 1844, 0, 0, + 0, 0, 1844, 1845, 0, 0, 0, 1845, 1845, 1845, + 0, 0, 0, 0, 1845, 1846, 0, 0, 0, 1846, + 1846, 1846, 0, 0, 0, 0, 1846, 1847, 0, 0, + + 0, 1847, 1847, 1847, 0, 0, 0, 0, 1847, 1848, + 0, 0, 0, 1848, 1848, 1848, 0, 0, 0, 0, + 1848, 1849, 0, 0, 0, 1849, 1849, 1849, 0, 0, + 0, 0, 1849, 1850, 0, 0, 0, 1850, 1850, 1850, + 0, 0, 0, 0, 1850, 1851, 0, 0, 0, 1851, + 1851, 1851, 0, 0, 0, 0, 1851, 1852, 0, 0, + 0, 1852, 1852, 1852, 0, 0, 0, 0, 1852, 1853, + 0, 0, 0, 1853, 1853, 1853, 0, 0, 0, 0, + 1853, 1854, 0, 0, 0, 1854, 1854, 1854, 0, 0, + 0, 0, 1854, 1855, 0, 0, 0, 1855, 1855, 1855, + + 0, 0, 0, 0, 1855, 1856, 0, 0, 0, 1856, + 1856, 1856, 0, 0, 0, 0, 1856, 1857, 0, 0, + 0, 1857, 1857, 1857, 0, 0, 0, 0, 1857, 1858, + 0, 0, 0, 1858, 1858, 1858, 0, 0, 0, 0, + 1858, 1859, 0, 0, 0, 1859, 1859, 1859, 0, 0, + 0, 0, 1859, 1860, 0, 0, 0, 1860, 1860, 1860, + 0, 0, 0, 0, 1860, 1861, 1861, 1861, 1861, 1861, + 1861, 1861, 1861, 1861, 0, 1861, 1861, 1861, 0, 1861, + 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 1862, 0, + 1862, 1862, 1862, 0, 1862, 1863, 1863, 1863, 1863, 1863, + + 1863, 1863, 1863, 1863, 0, 1863, 1863, 1863, 1863, 1863, + 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 1864, 0, + 1864, 1864, 1864, 1864, 1864, 1865, 1865, 1865, 1865, 1865, + 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, 1865, + 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, 1866, + 1866, 1866, 1866, 0, 1866, 1867, 1867, 1867, 1867, 1867, + 1867, 1867, 1867, 1867, 0, 1867, 1867, 1867, 1867, 1867, + 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 1868, 0, + 1868, 1868, 1868, 1868, 1868, 1869, 1869, 1869, 1869, 1869, + 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, 1869, + + 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, 1870, + 1870, 1870, 1870, 1870, 1870, 1871, 1871, 1871, 1871, 1871, + 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, + 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, 1872, + 1872, 1872, 1872, 0, 1872, 1873, 1873, 1873, 1873, 1873, + 1873, 1873, 1873, 1873, 1873, 1873, 1873, 1873, 0, 1873, + 1874, 1874, 1874, 1875, 0, 0, 0, 1875, 1875, 0, + 0, 0, 0, 0, 1875, 1876, 0, 0, 0, 1876, + 1876, 0, 0, 0, 0, 0, 1876, 1877, 1877, 1877, + 1883, 0, 0, 0, 1883, 1883, 1883, 0, 0, 0, + + 0, 1883, 1884, 0, 0, 0, 1884, 1884, 1884, 0, + 0, 0, 0, 1884, 1885, 0, 0, 0, 1885, 1885, + 1885, 0, 0, 0, 0, 1885, 1886, 0, 0, 0, + 1886, 1886, 1886, 0, 0, 0, 0, 1886, 1887, 0, + 0, 0, 1887, 1887, 1887, 0, 0, 0, 0, 1887, + 1888, 0, 0, 0, 1888, 1888, 1888, 0, 0, 0, + 0, 1888, 1889, 0, 0, 0, 1889, 1889, 1889, 0, + 0, 0, 0, 1889, 1890, 0, 0, 0, 1890, 1890, + 1890, 0, 0, 0, 0, 1890, 1891, 0, 0, 0, + 1891, 1891, 1891, 0, 0, 0, 0, 1891, 1892, 0, + + 0, 0, 1892, 1892, 1892, 0, 0, 0, 0, 1892, + 1893, 0, 0, 0, 1893, 1893, 1893, 0, 0, 0, + 0, 1893, 1894, 0, 0, 0, 1894, 1894, 1894, 0, + 0, 0, 0, 1894, 1895, 0, 0, 0, 1895, 1895, + 1895, 0, 0, 0, 0, 1895, 1896, 0, 0, 0, + 1896, 1896, 1896, 0, 0, 0, 0, 1896, 1897, 0, + 0, 0, 1897, 1897, 1897, 0, 0, 0, 0, 1897, + 1898, 0, 0, 0, 1898, 1898, 1898, 0, 0, 0, + 0, 1898, 1899, 0, 0, 0, 1899, 1899, 1899, 0, + 0, 0, 0, 1899, 1900, 0, 0, 0, 1900, 1900, + + 1900, 0, 0, 0, 0, 1900, 1901, 0, 0, 0, + 1901, 1901, 1901, 0, 0, 0, 0, 1901, 1902, 0, + 0, 0, 1902, 1902, 1902, 0, 0, 0, 0, 1902, + 1903, 0, 0, 0, 1903, 1903, 1903, 0, 0, 0, + 0, 1903, 1904, 0, 0, 0, 1904, 1904, 1904, 0, + 0, 0, 0, 1904, 1905, 0, 0, 0, 1905, 1905, + 1905, 0, 0, 0, 0, 1905, 1906, 0, 0, 0, + 1906, 1906, 1906, 0, 0, 0, 0, 1906, 1907, 0, + 0, 0, 1907, 1907, 1907, 0, 0, 0, 0, 1907, + 1908, 0, 0, 0, 1908, 1908, 1908, 0, 0, 0, + + 0, 1908, 1909, 0, 0, 0, 1909, 1909, 1909, 0, + 0, 0, 0, 1909, 1910, 0, 0, 0, 1910, 1910, + 1910, 0, 0, 0, 0, 1910, 1911, 0, 0, 0, + 1911, 1911, 1911, 0, 0, 0, 0, 1911, 1912, 0, + 0, 0, 1912, 1912, 1912, 0, 0, 0, 0, 1912, + 1913, 0, 0, 0, 1913, 1913, 1913, 0, 0, 0, + 0, 1913, 1914, 0, 0, 0, 1914, 1914, 1914, 0, + 0, 0, 0, 1914, 1915, 0, 0, 0, 1915, 1915, + 1915, 0, 0, 0, 0, 1915, 1916, 0, 0, 0, + 1916, 1916, 1916, 0, 0, 0, 0, 1916, 1917, 0, + + 0, 0, 1917, 1917, 1917, 0, 0, 0, 0, 1917, + 1918, 0, 0, 0, 1918, 1918, 1918, 0, 0, 0, + 0, 1918, 1919, 0, 0, 0, 1919, 1919, 1919, 0, + 0, 0, 0, 1919, 1920, 0, 0, 0, 1920, 1920, + 1920, 0, 0, 0, 0, 1920, 1921, 0, 0, 0, + 1921, 1921, 1921, 0, 0, 0, 0, 1921, 1922, 0, + 0, 0, 1922, 1922, 1922, 0, 0, 0, 0, 1922, + 1923, 0, 0, 0, 1923, 1923, 1923, 0, 0, 0, + 0, 1923, 1924, 0, 0, 0, 1924, 1924, 1924, 0, + 0, 0, 0, 1924, 1925, 0, 0, 0, 1925, 1925, + + 1925, 0, 0, 0, 0, 1925, 1926, 0, 0, 0, + 1926, 1926, 1926, 0, 0, 0, 0, 1926, 1927, 0, + 0, 0, 1927, 1927, 1927, 0, 0, 0, 0, 1927, + 1928, 0, 0, 0, 1928, 1928, 1928, 0, 0, 0, + 0, 1928, 1929, 0, 0, 0, 1929, 1929, 1929, 0, + 0, 0, 0, 1929, 1930, 0, 0, 0, 1930, 1930, + 1930, 0, 0, 0, 0, 1930, 1931, 0, 0, 0, + 1931, 1931, 1931, 0, 0, 0, 0, 1931, 1932, 0, + 0, 0, 1932, 1932, 1932, 0, 0, 0, 0, 1932, + 1933, 0, 0, 0, 1933, 1933, 1933, 0, 0, 0, + + 0, 1933, 1934, 0, 0, 0, 1934, 1934, 1934, 0, + 0, 0, 0, 1934, 1935, 0, 0, 0, 1935, 1935, + 1935, 0, 0, 0, 0, 1935, 1936, 0, 0, 0, + 1936, 1936, 1936, 0, 0, 0, 0, 1936, 1937, 0, + 0, 0, 1937, 1937, 1937, 0, 0, 0, 0, 1937, + 1938, 0, 0, 0, 1938, 1938, 1938, 0, 0, 0, + 0, 1938, 1939, 0, 0, 0, 1939, 1939, 1939, 0, + 0, 0, 0, 1939, 1940, 0, 0, 0, 1940, 1940, + 1940, 0, 0, 0, 0, 1940, 1941, 0, 0, 0, + 1941, 1941, 1941, 0, 0, 0, 0, 1941, 1942, 0, + + 0, 0, 1942, 1942, 1942, 0, 0, 0, 0, 1942, + 1943, 0, 0, 0, 1943, 1943, 1943, 0, 0, 0, + 0, 1943, 1944, 0, 0, 0, 1944, 1944, 1944, 0, + 0, 0, 0, 1944, 1945, 0, 0, 0, 1945, 1945, + 1945, 0, 0, 0, 0, 1945, 1946, 0, 0, 0, + 1946, 1946, 1946, 0, 0, 0, 0, 1946, 1947, 0, + 0, 0, 1947, 1947, 1947, 0, 0, 0, 0, 1947, + 1948, 0, 0, 0, 1948, 1948, 1948, 0, 0, 0, + 0, 1948, 1949, 0, 0, 0, 1949, 1949, 1949, 0, + 0, 0, 0, 1949, 1950, 0, 0, 0, 1950, 1950, + + 1950, 0, 0, 0, 0, 1950, 1951, 0, 0, 0, + 1951, 1951, 1951, 0, 0, 0, 0, 1951, 1952, 0, + 0, 0, 1952, 1952, 1952, 0, 0, 0, 0, 1952, + 1953, 0, 0, 0, 1953, 1953, 1953, 0, 0, 0, + 0, 1953, 1954, 0, 0, 0, 1954, 1954, 1954, 0, + 0, 0, 0, 1954, 1955, 0, 0, 0, 1955, 1955, + 1955, 0, 0, 0, 0, 1955, 1956, 0, 0, 0, + 1956, 1956, 1956, 0, 0, 0, 0, 1956, 1957, 0, + 0, 0, 1957, 1957, 1957, 0, 0, 0, 0, 1957, + 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 0, + + 1958, 1958, 1958, 0, 1958, 1959, 1959, 1959, 1959, 1959, + 1959, 1959, 1959, 1959, 0, 1959, 1959, 1959, 1959, 1959, + 1960, 1960, 1960, 1960, 1960, 1960, 1960, 1960, 1960, 0, + 1960, 1960, 1960, 0, 1960, 1961, 1961, 1961, 1961, 1961, + 1961, 1961, 1961, 1961, 1961, 1961, 1961, 1961, 0, 1961, + 1962, 1962, 1962, 1962, 1962, 1962, 1962, 1962, 1962, 0, + 1962, 1962, 1962, 1962, 1962, 1963, 1963, 1963, 1963, 1963, + 1963, 1963, 1963, 1963, 0, 1963, 1963, 1963, 1963, 1963, + 1964, 1964, 1964, 1964, 1964, 1964, 1964, 1964, 1964, 1964, + 1964, 1964, 1964, 1964, 1964, 1965, 1965, 1965, 1965, 1965, + + 1965, 1965, 1965, 1965, 1965, 1965, 1965, 1965, 0, 1965, + 1966, 1966, 1966, 1966, 1966, 1966, 1966, 1966, 1966, 1966, + 1966, 1966, 1966, 0, 1966, 1968, 1968, 1968, 1974, 0, + 0, 0, 1974, 1974, 1974, 0, 0, 0, 0, 1974, + 1975, 0, 0, 0, 1975, 1975, 1975, 0, 0, 0, + 0, 1975, 1976, 0, 0, 0, 1976, 1976, 1976, 0, + 0, 0, 0, 1976, 1977, 0, 0, 0, 1977, 1977, + 1977, 0, 0, 0, 0, 1977, 1978, 0, 0, 0, + 1978, 1978, 1978, 0, 0, 0, 0, 1978, 1979, 0, + 0, 0, 1979, 1979, 1979, 0, 0, 0, 0, 1979, + + 1980, 0, 0, 0, 1980, 1980, 1980, 0, 0, 0, + 0, 1980, 1981, 0, 0, 0, 1981, 1981, 1981, 0, + 0, 0, 0, 1981, 1982, 0, 0, 0, 1982, 1982, + 1982, 0, 0, 0, 0, 1982, 1983, 0, 0, 0, + 1983, 1983, 1983, 0, 0, 0, 0, 1983, 1984, 0, + 0, 0, 1984, 1984, 1984, 0, 0, 0, 0, 1984, + 1985, 0, 0, 0, 1985, 1985, 1985, 0, 0, 0, + 0, 1985, 1986, 0, 0, 0, 1986, 1986, 1986, 0, + 0, 0, 0, 1986, 1987, 0, 0, 0, 1987, 1987, + 1987, 0, 0, 0, 0, 1987, 1988, 0, 0, 0, + + 1988, 1988, 1988, 0, 0, 0, 0, 1988, 1989, 0, + 0, 0, 1989, 1989, 1989, 0, 0, 0, 0, 1989, + 1990, 0, 0, 0, 1990, 1990, 1990, 0, 0, 0, + 0, 1990, 1991, 0, 0, 0, 1991, 1991, 1991, 0, + 0, 0, 0, 1991, 1992, 0, 0, 0, 1992, 1992, + 1992, 0, 0, 0, 0, 1992, 1993, 0, 0, 0, + 1993, 1993, 1993, 0, 0, 0, 0, 1993, 1994, 0, + 0, 0, 1994, 1994, 1994, 0, 0, 0, 0, 1994, + 1995, 0, 0, 0, 1995, 1995, 1995, 0, 0, 0, + 0, 1995, 1996, 0, 0, 0, 1996, 1996, 1996, 0, + + 0, 0, 0, 1996, 1997, 0, 0, 0, 1997, 1997, + 1997, 0, 0, 0, 0, 1997, 1998, 0, 0, 0, + 1998, 1998, 1998, 0, 0, 0, 0, 1998, 1999, 0, + 0, 0, 1999, 1999, 1999, 0, 0, 0, 0, 1999, + 2000, 0, 0, 0, 2000, 2000, 2000, 0, 0, 0, + 0, 2000, 2001, 0, 0, 0, 2001, 2001, 2001, 0, + 0, 0, 0, 2001, 2002, 0, 0, 0, 2002, 2002, + 2002, 0, 0, 0, 0, 2002, 2003, 0, 0, 0, + 2003, 2003, 2003, 0, 0, 0, 0, 2003, 2004, 0, + 0, 0, 2004, 2004, 2004, 0, 0, 0, 0, 2004, + + 2005, 0, 0, 0, 2005, 2005, 2005, 0, 0, 0, + 0, 2005, 2006, 0, 0, 0, 2006, 2006, 2006, 0, + 0, 0, 0, 2006, 2007, 0, 0, 0, 2007, 2007, + 2007, 0, 0, 0, 0, 2007, 2008, 0, 0, 0, + 2008, 2008, 2008, 0, 0, 0, 0, 2008, 2009, 0, + 0, 0, 2009, 2009, 2009, 0, 0, 0, 0, 2009, + 2010, 0, 0, 0, 2010, 2010, 2010, 0, 0, 0, + 0, 2010, 2011, 0, 0, 0, 2011, 2011, 2011, 0, + 0, 0, 0, 2011, 2012, 0, 0, 0, 2012, 2012, + 2012, 0, 0, 0, 0, 2012, 2013, 0, 0, 0, + + 2013, 2013, 2013, 0, 0, 0, 0, 2013, 2014, 0, + 0, 0, 2014, 2014, 2014, 0, 0, 0, 0, 2014, + 2015, 0, 0, 0, 2015, 2015, 2015, 0, 0, 0, + 0, 2015, 2016, 0, 0, 0, 2016, 2016, 2016, 0, + 0, 0, 0, 2016, 2017, 0, 0, 0, 2017, 2017, + 2017, 0, 0, 0, 0, 2017, 2018, 0, 0, 0, + 2018, 2018, 2018, 0, 0, 0, 0, 2018, 2019, 0, + 0, 0, 2019, 2019, 2019, 0, 0, 0, 0, 2019, + 2020, 0, 0, 0, 2020, 2020, 2020, 0, 0, 0, + 0, 2020, 2021, 0, 0, 0, 2021, 2021, 2021, 0, + + 0, 0, 0, 2021, 2022, 0, 0, 0, 2022, 2022, + 2022, 0, 0, 0, 0, 2022, 2023, 0, 0, 0, + 2023, 2023, 2023, 0, 0, 0, 0, 2023, 2024, 0, + 0, 0, 2024, 2024, 2024, 0, 0, 0, 0, 2024, + 2025, 0, 0, 0, 2025, 2025, 2025, 0, 0, 0, + 0, 2025, 2026, 0, 0, 0, 2026, 2026, 2026, 0, + 0, 0, 0, 2026, 2027, 0, 0, 0, 2027, 2027, + 2027, 0, 0, 0, 0, 2027, 2028, 0, 0, 0, + 2028, 2028, 2028, 0, 0, 0, 0, 2028, 2029, 0, + 0, 0, 2029, 2029, 2029, 0, 0, 0, 0, 2029, + + 2030, 0, 0, 0, 2030, 2030, 2030, 0, 0, 0, + 0, 2030, 2031, 0, 0, 0, 2031, 2031, 2031, 0, + 0, 0, 0, 2031, 2032, 0, 0, 0, 2032, 2032, + 2032, 0, 0, 0, 0, 2032, 2033, 0, 0, 0, + 2033, 2033, 2033, 0, 0, 0, 0, 2033, 2034, 0, + 0, 0, 2034, 2034, 2034, 0, 0, 0, 0, 2034, + 2035, 0, 0, 0, 2035, 2035, 2035, 0, 0, 0, + 0, 2035, 2036, 0, 0, 0, 2036, 2036, 2036, 0, + 0, 0, 0, 2036, 2037, 0, 0, 0, 2037, 2037, + 2037, 0, 0, 0, 0, 2037, 2038, 0, 0, 0, + + 2038, 2038, 2038, 0, 0, 0, 0, 2038, 2039, 0, + 0, 0, 2039, 2039, 2039, 0, 0, 0, 0, 2039, + 2040, 0, 0, 0, 2040, 2040, 2040, 0, 0, 0, + 0, 2040, 2041, 0, 0, 0, 2041, 2041, 2041, 0, + 0, 0, 0, 2041, 2042, 0, 0, 0, 2042, 2042, + 2042, 0, 0, 0, 0, 2042, 2043, 0, 0, 0, + 2043, 2043, 2043, 0, 0, 0, 0, 2043, 2044, 0, + 0, 0, 2044, 2044, 2044, 0, 0, 0, 0, 2044, + 2045, 0, 0, 0, 2045, 2045, 2045, 0, 0, 0, + 0, 2045, 2046, 0, 0, 0, 2046, 2046, 2046, 0, + + 0, 0, 0, 2046, 2047, 0, 0, 0, 2047, 2047, + 2047, 0, 0, 0, 0, 2047, 2048, 0, 0, 0, + 2048, 2048, 2048, 0, 0, 0, 0, 2048, 2049, 0, + 0, 0, 2049, 2049, 2049, 0, 0, 0, 0, 2049, + 2050, 0, 0, 0, 2050, 2050, 2050, 0, 0, 0, + 0, 2050, 2051, 0, 0, 0, 2051, 2051, 2051, 0, + 0, 0, 0, 2051, 2052, 0, 0, 0, 2052, 2052, + 2052, 0, 0, 0, 0, 2052, 2053, 0, 0, 0, + 2053, 2053, 2053, 0, 0, 0, 0, 2053, 2054, 0, + 0, 0, 2054, 2054, 2054, 0, 0, 0, 0, 2054, + + 2055, 0, 0, 0, 2055, 2055, 2055, 0, 0, 0, + 0, 2055, 2056, 0, 0, 0, 2056, 2056, 2056, 0, + 0, 0, 0, 2056, 2057, 0, 0, 0, 2057, 2057, + 2057, 0, 0, 0, 0, 2057, 2058, 0, 0, 0, + 2058, 2058, 2058, 0, 0, 0, 0, 2058, 2059, 0, + 0, 0, 2059, 2059, 2059, 0, 0, 0, 0, 2059, + 2060, 0, 0, 0, 2060, 2060, 2060, 0, 0, 0, + 0, 2060, 2061, 0, 0, 0, 2061, 2061, 2061, 0, + 0, 0, 0, 2061, 2062, 0, 0, 0, 2062, 2062, + 2062, 0, 0, 0, 0, 2062, 2063, 0, 0, 0, + + 2063, 2063, 2063, 0, 0, 0, 0, 2063, 2064, 0, + 0, 0, 2064, 2064, 2064, 0, 0, 0, 0, 2064, + 2065, 0, 0, 0, 2065, 2065, 2065, 0, 0, 0, + 0, 2065, 2066, 0, 0, 0, 2066, 2066, 2066, 0, + 0, 0, 0, 2066, 2067, 0, 0, 0, 2067, 2067, + 2067, 0, 0, 0, 0, 2067, 2068, 0, 0, 0, + 2068, 2068, 2068, 0, 0, 0, 0, 2068, 2069, 0, + 0, 0, 2069, 2069, 2069, 0, 0, 0, 0, 2069, + 2070, 0, 0, 0, 2070, 2070, 2070, 0, 0, 0, + 0, 2070, 2071, 0, 0, 0, 2071, 2071, 2071, 0, + + 0, 0, 0, 2071, 2072, 0, 0, 0, 2072, 2072, + 2072, 0, 0, 0, 0, 2072, 2073, 0, 0, 0, + 2073, 2073, 2073, 0, 0, 0, 0, 2073, 2074, 0, + 0, 0, 2074, 2074, 2074, 0, 0, 0, 0, 2074, + 2075, 0, 0, 0, 2075, 2075, 2075, 0, 0, 0, + 0, 2075, 2076, 2076, 2076, 2076, 2076, 2076, 2076, 2076, + 2076, 0, 2076, 2076, 2076, 0, 2076, 2077, 2077, 2077, + 2077, 2077, 2077, 2077, 2077, 2077, 0, 2077, 2077, 2077, + 2077, 2077, 2078, 2078, 2078, 2078, 2078, 2078, 2078, 2078, + 2078, 0, 2078, 2078, 2078, 0, 2078, 2079, 2079, 2079, + + 2079, 2079, 2079, 2079, 2079, 2079, 2079, 2079, 2079, 2079, + 0, 2079, 2080, 2080, 2080, 2081, 2081, 2081, 2087, 0, + 0, 0, 2087, 2087, 2087, 0, 0, 0, 0, 2087, + 2088, 0, 0, 0, 2088, 2088, 2088, 0, 0, 0, + 0, 2088, 2089, 0, 0, 0, 2089, 2089, 2089, 0, + 0, 0, 0, 2089, 2090, 0, 0, 0, 2090, 2090, + 2090, 0, 0, 0, 0, 2090, 2091, 0, 0, 0, + 2091, 2091, 2091, 0, 0, 0, 0, 2091, 2092, 0, + 0, 0, 2092, 2092, 2092, 0, 0, 0, 0, 2092, + 2093, 0, 0, 0, 2093, 2093, 2093, 0, 0, 0, + + 0, 2093, 2094, 0, 0, 0, 2094, 2094, 2094, 0, + 0, 0, 0, 2094, 2095, 0, 0, 0, 2095, 2095, + 2095, 0, 0, 0, 0, 2095, 2096, 0, 0, 0, + 2096, 2096, 2096, 0, 0, 0, 0, 2096, 2097, 0, + 0, 0, 2097, 2097, 2097, 0, 0, 0, 0, 2097, + 2098, 0, 0, 0, 2098, 2098, 2098, 0, 0, 0, + 0, 2098, 2099, 0, 0, 0, 2099, 2099, 2099, 0, + 0, 0, 0, 2099, 2100, 0, 0, 0, 2100, 2100, + 2100, 0, 0, 0, 0, 2100, 2101, 0, 0, 0, + 2101, 2101, 2101, 0, 0, 0, 0, 2101, 2102, 0, + + 0, 0, 2102, 2102, 2102, 0, 0, 0, 0, 2102, + 2103, 0, 0, 0, 2103, 2103, 2103, 0, 0, 0, + 0, 2103, 2104, 0, 0, 0, 2104, 2104, 2104, 0, + 0, 0, 0, 2104, 2105, 0, 0, 0, 2105, 2105, + 2105, 0, 0, 0, 0, 2105, 2106, 0, 0, 0, + 2106, 2106, 2106, 0, 0, 0, 0, 2106, 2107, 0, + 0, 0, 2107, 2107, 2107, 0, 0, 0, 0, 2107, + 2108, 0, 0, 0, 2108, 2108, 2108, 0, 0, 0, + 0, 2108, 2109, 0, 0, 0, 2109, 2109, 2109, 0, + 0, 0, 0, 2109, 2110, 0, 0, 0, 2110, 2110, + + 2110, 0, 0, 0, 0, 2110, 2111, 0, 0, 0, + 2111, 2111, 2111, 0, 0, 0, 0, 2111, 2112, 0, + 0, 0, 2112, 2112, 2112, 0, 0, 0, 0, 2112, + 2113, 0, 0, 0, 2113, 2113, 2113, 0, 0, 0, + 0, 2113, 2114, 0, 0, 0, 2114, 2114, 2114, 0, + 0, 0, 0, 2114, 2115, 0, 0, 0, 2115, 2115, + 2115, 0, 0, 0, 0, 2115, 2116, 0, 0, 0, + 2116, 2116, 2116, 0, 0, 0, 0, 2116, 2117, 0, + 0, 0, 2117, 2117, 2117, 0, 0, 0, 0, 2117, + 2118, 0, 0, 0, 2118, 2118, 2118, 0, 0, 0, + + 0, 2118, 2119, 0, 0, 0, 2119, 2119, 2119, 0, + 0, 0, 0, 2119, 2120, 0, 0, 0, 2120, 2120, + 2120, 0, 0, 0, 0, 2120, 2121, 0, 0, 0, + 2121, 2121, 2121, 0, 0, 0, 0, 2121, 2122, 0, + 0, 0, 2122, 2122, 2122, 0, 0, 0, 0, 2122, + 2123, 0, 0, 0, 2123, 2123, 2123, 0, 0, 0, + 0, 2123, 2124, 0, 0, 0, 2124, 2124, 2124, 0, + 0, 0, 0, 2124, 2125, 0, 0, 0, 2125, 2125, + 2125, 0, 0, 0, 0, 2125, 2126, 0, 0, 0, + 2126, 2126, 2126, 0, 0, 0, 0, 2126, 2127, 0, + + 0, 0, 2127, 2127, 2127, 0, 0, 0, 0, 2127, + 2128, 0, 0, 0, 2128, 2128, 2128, 0, 0, 0, + 0, 2128, 2129, 0, 0, 0, 2129, 2129, 2129, 0, + 0, 0, 0, 2129, 2130, 0, 0, 0, 2130, 2130, + 2130, 0, 0, 0, 0, 2130, 2131, 0, 0, 0, + 2131, 2131, 2131, 0, 0, 0, 0, 2131, 2132, 0, + 0, 0, 2132, 2132, 2132, 0, 0, 0, 0, 2132, + 2133, 0, 0, 0, 2133, 2133, 2133, 0, 0, 0, + 0, 2133, 2134, 0, 0, 0, 2134, 2134, 2134, 0, + 0, 0, 0, 2134, 2135, 0, 0, 0, 2135, 2135, + + 2135, 0, 0, 0, 0, 2135, 2136, 0, 0, 0, + 2136, 2136, 2136, 0, 0, 0, 0, 2136, 2137, 0, + 0, 0, 2137, 2137, 2137, 0, 0, 0, 0, 2137, + 2138, 0, 0, 0, 2138, 2138, 2138, 0, 0, 0, + 0, 2138, 2139, 0, 0, 0, 2139, 2139, 2139, 0, + 0, 0, 0, 2139, 2140, 0, 0, 0, 2140, 2140, + 2140, 0, 0, 0, 0, 2140, 2141, 0, 0, 0, + 2141, 2141, 2141, 0, 0, 0, 0, 2141, 2142, 0, + 0, 0, 2142, 2142, 2142, 0, 0, 0, 0, 2142, + 2143, 0, 0, 0, 2143, 2143, 2143, 0, 0, 0, + + 0, 2143, 2144, 0, 0, 0, 2144, 2144, 2144, 0, + 0, 0, 0, 2144, 2145, 0, 0, 0, 2145, 2145, + 2145, 0, 0, 0, 0, 2145, 2146, 0, 0, 0, + 2146, 2146, 2146, 0, 0, 0, 0, 2146, 2147, 0, + 0, 0, 2147, 2147, 2147, 0, 0, 0, 0, 2147, + 2148, 0, 0, 0, 2148, 2148, 2148, 0, 0, 0, + 0, 2148, 2149, 0, 0, 0, 2149, 2149, 2149, 0, + 0, 0, 0, 2149, 2150, 0, 0, 0, 2150, 2150, + 2150, 0, 0, 0, 0, 2150, 2151, 0, 0, 0, + 2151, 2151, 2151, 0, 0, 0, 0, 2151, 2152, 0, + + 0, 0, 2152, 2152, 2152, 0, 0, 0, 0, 2152, + 2153, 0, 0, 0, 2153, 2153, 2153, 0, 0, 0, + 0, 2153, 2154, 0, 0, 0, 2154, 2154, 2154, 0, + 0, 0, 0, 2154, 2155, 0, 0, 0, 2155, 2155, + 2155, 0, 0, 0, 0, 2155, 2156, 0, 0, 0, + 2156, 2156, 2156, 0, 0, 0, 0, 2156, 2157, 0, + 0, 0, 2157, 2157, 2157, 0, 0, 0, 0, 2157, + 2158, 0, 0, 0, 2158, 2158, 2158, 0, 0, 0, + 0, 2158, 2159, 0, 0, 0, 2159, 2159, 2159, 0, + 0, 0, 0, 2159, 2160, 0, 0, 0, 2160, 2160, + + 2160, 0, 0, 0, 0, 2160, 2161, 0, 0, 0, + 2161, 2161, 2161, 0, 0, 0, 0, 2161, 2162, 0, + 0, 0, 2162, 2162, 2162, 0, 0, 0, 0, 2162, + 2163, 0, 0, 0, 2163, 2163, 2163, 0, 0, 0, + 0, 2163, 2164, 0, 0, 0, 2164, 2164, 2164, 0, + 0, 0, 0, 2164, 2165, 0, 0, 0, 2165, 2165, + 2165, 0, 0, 0, 0, 2165, 2166, 0, 0, 0, + 2166, 2166, 2166, 0, 0, 0, 0, 2166, 2167, 0, + 0, 0, 2167, 2167, 2167, 0, 0, 0, 0, 2167, + 2168, 0, 0, 0, 2168, 2168, 2168, 0, 0, 0, + + 0, 2168, 2169, 0, 0, 0, 2169, 2169, 2169, 0, + 0, 0, 0, 2169, 2170, 0, 0, 0, 2170, 2170, + 2170, 0, 0, 0, 0, 2170, 2171, 0, 0, 0, + 2171, 2171, 2171, 0, 0, 0, 0, 2171, 2172, 0, + 0, 0, 2172, 2172, 2172, 0, 0, 0, 0, 2172, + 2173, 0, 0, 0, 2173, 2173, 2173, 0, 0, 0, + 0, 2173, 2174, 0, 0, 0, 2174, 2174, 2174, 0, + 0, 0, 0, 2174, 2175, 0, 0, 0, 2175, 2175, + 2175, 0, 0, 0, 0, 2175, 2176, 0, 0, 0, + 2176, 2176, 2176, 0, 0, 0, 0, 2176, 2177, 0, + + 0, 0, 2177, 2177, 2177, 0, 0, 0, 0, 2177, + 2178, 0, 0, 0, 2178, 2178, 2178, 0, 0, 0, + 0, 2178, 2179, 0, 0, 0, 2179, 2179, 2179, 0, + 0, 0, 0, 2179, 2180, 0, 0, 0, 2180, 2180, + 2180, 0, 0, 0, 0, 2180, 2181, 0, 0, 0, + 2181, 2181, 2181, 0, 0, 0, 0, 2181, 2182, 0, + 0, 0, 2182, 2182, 2182, 0, 0, 0, 0, 2182, + 2183, 0, 0, 0, 2183, 2183, 2183, 0, 0, 0, + 0, 2183, 2184, 0, 0, 0, 2184, 2184, 2184, 0, + 0, 0, 0, 2184, 2185, 0, 0, 0, 2185, 2185, + + 2185, 0, 0, 0, 0, 2185, 2186, 0, 0, 0, + 2186, 2186, 2186, 0, 0, 0, 0, 2186, 2187, 0, + 0, 0, 2187, 2187, 2187, 0, 0, 0, 0, 2187, + 2188, 0, 0, 0, 2188, 2188, 2188, 0, 0, 0, + 0, 2188, 2189, 0, 0, 0, 2189, 2189, 2189, 0, + 0, 0, 0, 2189, 2190, 0, 0, 0, 2190, 2190, + 2190, 0, 0, 0, 0, 2190, 2191, 0, 0, 0, + 2191, 2191, 2191, 0, 0, 0, 0, 2191, 2192, 0, + 0, 0, 2192, 2192, 2192, 0, 0, 0, 0, 2192, + 2193, 0, 0, 0, 2193, 2193, 2193, 0, 0, 0, + + 0, 2193, 2194, 0, 0, 0, 2194, 2194, 2194, 0, + 0, 0, 0, 2194, 2195, 0, 0, 0, 2195, 2195, + 2195, 0, 0, 0, 0, 2195, 2196, 0, 0, 0, + 2196, 2196, 2196, 0, 0, 0, 0, 2196, 2197, 0, + 0, 0, 2197, 2197, 2197, 0, 0, 0, 0, 2197, + 2198, 0, 0, 0, 2198, 2198, 2198, 0, 0, 0, + 0, 2198, 2199, 0, 0, 0, 2199, 2199, 2199, 0, + 0, 0, 0, 2199, 2200, 0, 0, 0, 2200, 2200, + 2200, 0, 0, 0, 0, 2200, 2201, 0, 0, 0, + 2201, 2201, 2201, 0, 0, 0, 0, 2201, 2202, 0, + + 0, 0, 2202, 2202, 2202, 0, 0, 0, 0, 2202, + 2203, 0, 0, 0, 2203, 2203, 2203, 0, 0, 0, + 0, 2203, 2204, 0, 0, 0, 2204, 2204, 2204, 0, + 0, 0, 0, 2204, 2205, 0, 0, 0, 2205, 2205, + 2205, 0, 0, 0, 0, 2205, 2206, 0, 0, 0, + 2206, 2206, 2206, 0, 0, 0, 0, 2206, 2207, 0, + 0, 0, 2207, 2207, 2207, 0, 0, 0, 0, 2207, + 2208, 0, 0, 0, 2208, 2208, 2208, 0, 0, 0, + 0, 2208, 2209, 0, 0, 0, 2209, 2209, 2209, 0, + 0, 0, 0, 2209, 2210, 0, 0, 0, 2210, 2210, + + 2210, 0, 0, 0, 0, 2210, 2211, 0, 0, 0, + 2211, 2211, 2211, 0, 0, 0, 0, 2211, 2212, 0, + 0, 0, 2212, 2212, 2212, 0, 0, 0, 0, 2212, + 2213, 0, 0, 0, 2213, 2213, 2213, 0, 0, 0, + 0, 2213, 2214, 0, 0, 0, 2214, 2214, 2214, 0, + 0, 0, 0, 2214, 2215, 0, 0, 0, 2215, 2215, + 2215, 0, 0, 0, 0, 2215, 2216, 0, 0, 0, + 2216, 2216, 2216, 0, 0, 0, 0, 2216, 2217, 0, + 0, 0, 2217, 2217, 2217, 0, 0, 0, 0, 2217, + 2218, 0, 0, 0, 2218, 2218, 2218, 0, 0, 0, + + 0, 2218, 2219, 2219, 2219, 2219, 2219, 2219, 2219, 2219, + 2219, 0, 2219, 2219, 2219, 0, 2219, 2220, 0, 0, + 0, 2220, 2220, 2220, 0, 0, 0, 0, 2220, 2221, + 2221, 2221, 2222, 2222, 2222, 2224, 2224, 2224, 0, 0, + 0, 0, 2224, 2225, 2225, 2225, 2226, 2226, 2226, 2227, + 0, 0, 0, 2227, 2227, 2227, 0, 0, 0, 0, + 2227, 2228, 0, 0, 0, 2228, 2228, 2228, 0, 0, + 0, 0, 2228, 2229, 0, 0, 0, 2229, 2229, 2229, + 0, 0, 0, 0, 2229, 2230, 0, 0, 0, 2230, + 2230, 2230, 0, 0, 0, 0, 2230, 2231, 0, 0, + + 0, 2231, 2231, 2231, 0, 0, 0, 0, 2231, 2232, + 0, 0, 0, 2232, 2232, 2232, 0, 0, 0, 0, + 2232, 2233, 0, 0, 0, 2233, 2233, 2233, 0, 0, + 0, 0, 2233, 2234, 0, 0, 0, 2234, 2234, 2234, + 0, 0, 0, 0, 2234, 2235, 0, 0, 0, 2235, + 2235, 2235, 0, 0, 0, 0, 2235, 2236, 0, 0, + 0, 2236, 2236, 2236, 0, 0, 0, 0, 2236, 2237, + 0, 0, 0, 2237, 2237, 2237, 0, 0, 0, 0, + 2237, 2238, 0, 0, 0, 2238, 2238, 2238, 0, 0, + 0, 0, 2238, 2239, 0, 0, 0, 2239, 2239, 2239, + + 0, 0, 0, 0, 2239, 2240, 0, 0, 0, 2240, + 2240, 2240, 0, 0, 0, 0, 2240, 2241, 0, 0, + 0, 2241, 2241, 2241, 0, 0, 0, 0, 2241, 2242, + 0, 0, 0, 2242, 2242, 2242, 0, 0, 0, 0, + 2242, 2243, 0, 0, 0, 2243, 2243, 2243, 0, 0, + 0, 0, 2243, 2244, 0, 0, 0, 2244, 2244, 2244, + 0, 0, 0, 0, 2244, 2245, 0, 0, 0, 2245, + 2245, 2245, 0, 0, 0, 0, 2245, 2246, 0, 0, + 0, 2246, 2246, 2246, 0, 0, 0, 0, 2246, 2247, + 0, 0, 0, 2247, 2247, 2247, 0, 0, 0, 0, + + 2247, 2248, 0, 0, 0, 2248, 2248, 2248, 0, 0, + 0, 0, 2248, 2249, 0, 0, 0, 2249, 2249, 2249, + 0, 0, 0, 0, 2249, 2250, 0, 0, 0, 2250, + 2250, 2250, 0, 0, 0, 0, 2250, 2251, 0, 0, + 0, 2251, 2251, 2251, 0, 0, 0, 0, 2251, 2252, + 0, 0, 0, 2252, 2252, 2252, 0, 0, 0, 0, + 2252, 2253, 0, 0, 0, 2253, 2253, 2253, 0, 0, + 0, 0, 2253, 2254, 0, 0, 0, 2254, 2254, 2254, + 0, 0, 0, 0, 2254, 2255, 0, 0, 0, 2255, + 2255, 2255, 0, 0, 0, 0, 2255, 2256, 0, 0, + + 0, 2256, 2256, 2256, 0, 0, 0, 0, 2256, 2257, + 0, 0, 0, 2257, 2257, 2257, 0, 0, 0, 0, + 2257, 2258, 0, 0, 0, 2258, 2258, 2258, 0, 0, + 0, 0, 2258, 2259, 0, 0, 0, 2259, 2259, 2259, + 0, 0, 0, 0, 2259, 2260, 0, 0, 0, 2260, + 2260, 2260, 0, 0, 0, 0, 2260, 2261, 0, 0, + 0, 2261, 2261, 2261, 0, 0, 0, 0, 2261, 2262, + 0, 0, 0, 2262, 2262, 2262, 0, 0, 0, 0, + 2262, 2263, 0, 0, 0, 2263, 2263, 2263, 0, 0, + 0, 0, 2263, 2264, 0, 0, 0, 2264, 2264, 2264, + + 0, 0, 0, 0, 2264, 2265, 0, 0, 0, 2265, + 2265, 2265, 0, 0, 0, 0, 2265, 2266, 0, 0, + 0, 2266, 2266, 2266, 0, 0, 0, 0, 2266, 2267, + 0, 0, 0, 2267, 2267, 2267, 0, 0, 0, 0, + 2267, 2268, 0, 0, 0, 2268, 2268, 2268, 0, 0, + 0, 0, 2268, 2269, 0, 0, 0, 2269, 2269, 2269, + 0, 0, 0, 0, 2269, 2270, 0, 0, 0, 2270, + 2270, 2270, 0, 0, 0, 0, 2270, 2271, 0, 0, + 0, 2271, 2271, 2271, 0, 0, 0, 0, 2271, 2272, + 0, 0, 0, 2272, 2272, 2272, 0, 0, 0, 0, + + 2272, 2273, 0, 0, 0, 2273, 2273, 2273, 0, 0, + 0, 0, 2273, 2274, 0, 0, 0, 2274, 2274, 2274, + 0, 0, 0, 0, 2274, 2275, 0, 0, 0, 2275, + 2275, 2275, 0, 0, 0, 0, 2275, 2276, 0, 0, + 0, 2276, 2276, 2276, 0, 0, 0, 0, 2276, 2277, + 0, 0, 0, 2277, 2277, 2277, 0, 0, 0, 0, + 2277, 2278, 0, 0, 0, 2278, 2278, 2278, 0, 0, + 0, 0, 2278, 2279, 0, 0, 0, 2279, 2279, 2279, + 0, 0, 0, 0, 2279, 2280, 0, 0, 0, 2280, + 2280, 2280, 0, 0, 0, 0, 2280, 2281, 0, 0, + + 0, 2281, 2281, 2281, 0, 0, 0, 0, 2281, 2282, + 0, 0, 0, 2282, 2282, 2282, 0, 0, 0, 0, + 2282, 2283, 0, 0, 0, 2283, 2283, 2283, 0, 0, + 0, 0, 2283, 2284, 0, 0, 0, 2284, 2284, 2284, + 0, 0, 0, 0, 2284, 2285, 0, 0, 0, 2285, + 2285, 2285, 0, 0, 0, 0, 2285, 2286, 0, 0, + 0, 2286, 2286, 2286, 0, 0, 0, 0, 2286, 2287, + 0, 0, 0, 2287, 2287, 2287, 0, 0, 0, 0, + 2287, 2288, 0, 0, 0, 2288, 2288, 2288, 0, 0, + 0, 0, 2288, 2289, 0, 0, 0, 2289, 2289, 2289, + + 0, 0, 0, 0, 2289, 2290, 0, 0, 0, 2290, + 2290, 2290, 0, 0, 0, 0, 2290, 2291, 0, 0, + 0, 2291, 2291, 2291, 0, 0, 0, 0, 2291, 2292, + 0, 0, 0, 2292, 2292, 2292, 0, 0, 0, 0, + 2292, 2293, 0, 0, 0, 2293, 2293, 2293, 0, 0, + 0, 0, 2293, 2294, 0, 0, 0, 2294, 2294, 2294, + 0, 0, 0, 0, 2294, 2295, 0, 0, 0, 2295, + 2295, 2295, 0, 0, 0, 0, 2295, 2296, 0, 0, + 0, 2296, 2296, 2296, 0, 0, 0, 0, 2296, 2297, + 0, 0, 0, 2297, 2297, 2297, 0, 0, 0, 0, + + 2297, 2298, 0, 0, 0, 2298, 2298, 2298, 0, 0, + 0, 0, 2298, 2299, 0, 0, 0, 2299, 2299, 2299, + 0, 0, 0, 0, 2299, 2300, 0, 0, 0, 2300, + 2300, 2300, 0, 0, 0, 0, 2300, 2301, 0, 0, + 0, 2301, 2301, 2301, 0, 0, 0, 0, 2301, 2302, + 0, 0, 0, 2302, 2302, 2302, 0, 0, 0, 0, + 2302, 2303, 0, 0, 0, 2303, 2303, 2303, 0, 0, + 0, 0, 2303, 2304, 0, 0, 0, 2304, 2304, 2304, + 0, 0, 0, 0, 2304, 2305, 0, 0, 0, 2305, + 2305, 2305, 0, 0, 0, 0, 2305, 2306, 0, 0, + + 0, 2306, 2306, 2306, 0, 0, 0, 0, 2306, 2307, + 0, 0, 0, 2307, 2307, 2307, 0, 0, 0, 0, + 2307, 2308, 0, 0, 0, 2308, 2308, 2308, 0, 0, + 0, 0, 2308, 2309, 0, 0, 0, 2309, 2309, 2309, + 0, 0, 0, 0, 2309, 2310, 0, 0, 0, 2310, + 2310, 2310, 0, 0, 0, 0, 2310, 2311, 0, 0, + 0, 2311, 2311, 2311, 0, 0, 0, 0, 2311, 2312, + 0, 0, 0, 2312, 2312, 2312, 0, 0, 0, 0, + 2312, 2313, 0, 0, 0, 2313, 2313, 2313, 0, 0, + 0, 0, 2313, 2314, 0, 0, 0, 2314, 2314, 2314, + + 0, 0, 0, 0, 2314, 2315, 0, 0, 0, 2315, + 2315, 2315, 0, 0, 0, 0, 2315, 2316, 0, 0, + 0, 2316, 2316, 2316, 0, 0, 0, 0, 2316, 2317, + 0, 0, 0, 2317, 2317, 2317, 0, 0, 0, 0, + 2317, 2318, 0, 0, 0, 2318, 2318, 2318, 0, 0, + 0, 0, 2318, 2319, 0, 0, 0, 2319, 2319, 2319, + 0, 0, 0, 0, 2319, 2320, 0, 0, 0, 2320, + 2320, 2320, 0, 0, 0, 0, 2320, 2321, 0, 0, + 0, 2321, 2321, 2321, 0, 0, 0, 0, 2321, 2322, + 0, 0, 0, 2322, 2322, 2322, 0, 0, 0, 0, + + 2322, 2323, 0, 0, 0, 2323, 2323, 2323, 0, 0, + 0, 0, 2323, 2324, 0, 0, 0, 2324, 2324, 2324, + 0, 0, 0, 0, 2324, 2325, 0, 0, 0, 2325, + 2325, 2325, 0, 0, 0, 0, 2325, 2326, 0, 0, + 0, 2326, 2326, 2326, 0, 0, 0, 0, 2326, 2327, + 0, 0, 0, 2327, 2327, 2327, 0, 0, 0, 0, + 2327, 2328, 0, 0, 0, 2328, 2328, 2328, 0, 0, + 0, 0, 2328, 2329, 0, 0, 0, 2329, 2329, 2329, + 0, 0, 0, 0, 2329, 2330, 0, 0, 0, 2330, + 2330, 2330, 0, 0, 0, 0, 2330, 2331, 0, 0, + + 0, 2331, 2331, 2331, 0, 0, 0, 0, 2331, 2332, + 0, 0, 0, 2332, 2332, 2332, 0, 0, 0, 0, + 2332, 2333, 0, 0, 0, 2333, 2333, 2333, 0, 0, + 0, 0, 2333, 2334, 0, 0, 0, 2334, 2334, 2334, + 0, 0, 0, 0, 2334, 2335, 0, 0, 0, 2335, + 2335, 2335, 0, 0, 0, 0, 2335, 2336, 0, 0, + 0, 2336, 2336, 2336, 0, 0, 0, 0, 2336, 2337, + 0, 0, 0, 2337, 2337, 2337, 0, 0, 0, 0, + 2337, 2338, 0, 0, 0, 2338, 2338, 2338, 0, 0, + 0, 0, 2338, 2339, 0, 0, 0, 2339, 2339, 2339, + + 0, 0, 0, 0, 2339, 2340, 0, 0, 0, 2340, + 2340, 2340, 0, 0, 0, 0, 2340, 2341, 0, 0, + 0, 2341, 2341, 2341, 0, 0, 0, 0, 2341, 2342, + 0, 0, 0, 2342, 2342, 2342, 0, 0, 0, 0, + 2342, 2343, 0, 0, 0, 2343, 2343, 2343, 0, 0, + 0, 0, 2343, 2344, 0, 0, 0, 2344, 2344, 2344, + 0, 0, 0, 0, 2344, 2345, 0, 0, 0, 2345, + 2345, 2345, 0, 0, 0, 0, 2345, 2346, 0, 0, + 0, 2346, 2346, 2346, 0, 0, 0, 0, 2346, 2347, + 0, 0, 0, 2347, 2347, 2347, 0, 0, 0, 0, + + 2347, 2348, 0, 0, 0, 2348, 2348, 2348, 0, 0, + 0, 0, 2348, 2349, 0, 0, 0, 2349, 2349, 2349, + 0, 0, 0, 0, 2349, 2350, 0, 0, 0, 2350, + 2350, 2350, 0, 0, 0, 0, 2350, 2351, 0, 0, + 0, 2351, 2351, 2351, 0, 0, 0, 0, 2351, 2352, + 0, 0, 0, 2352, 2352, 2352, 0, 0, 0, 0, + 2352, 2353, 0, 0, 0, 2353, 2353, 2353, 0, 0, + 0, 0, 2353, 2354, 0, 0, 0, 2354, 2354, 2354, + 0, 0, 0, 0, 2354, 2355, 0, 0, 0, 2355, + 2355, 2355, 0, 0, 0, 0, 2355, 2356, 0, 0, + + 0, 2356, 2356, 2356, 0, 0, 0, 0, 2356, 2357, + 0, 0, 0, 2357, 2357, 2357, 0, 0, 0, 0, + 2357, 2358, 0, 0, 0, 2358, 2358, 2358, 0, 0, + 0, 0, 2358, 2359, 0, 0, 0, 2359, 2359, 2359, + 0, 0, 0, 0, 2359, 2360, 0, 0, 0, 2360, + 2360, 2360, 0, 0, 0, 0, 2360, 2361, 0, 0, + 0, 2361, 2361, 2361, 0, 0, 0, 0, 2361, 2362, + 0, 0, 0, 2362, 2362, 2362, 0, 0, 0, 0, + 2362, 2363, 0, 0, 0, 2363, 2363, 2363, 0, 0, + 0, 0, 2363, 2364, 0, 0, 0, 2364, 2364, 2364, + + 0, 0, 0, 0, 2364, 2365, 0, 0, 0, 2365, + 2365, 2365, 0, 0, 0, 0, 2365, 2366, 0, 0, + 0, 2366, 2366, 2366, 0, 0, 0, 0, 2366, 2367, + 0, 0, 0, 2367, 2367, 2367, 0, 0, 0, 0, + 2367, 2368, 0, 0, 0, 2368, 2368, 2368, 0, 0, + 0, 0, 2368, 2369, 0, 0, 0, 2369, 2369, 2369, + 0, 0, 0, 0, 2369, 2370, 0, 0, 0, 2370, + 2370, 2370, 0, 0, 0, 0, 2370, 2371, 0, 0, + 0, 2371, 2371, 2371, 0, 0, 0, 0, 2371, 2372, + 0, 0, 0, 2372, 2372, 2372, 0, 0, 0, 0, + + 2372, 2373, 0, 0, 0, 2373, 2373, 2373, 0, 0, + 0, 0, 2373, 2374, 0, 0, 0, 2374, 2374, 2374, + 0, 0, 0, 0, 2374, 2375, 0, 0, 0, 2375, + 2375, 2375, 0, 0, 0, 0, 2375, 2376, 0, 0, + 0, 2376, 2376, 2376, 0, 0, 0, 0, 2376, 2377, + 0, 0, 0, 2377, 2377, 2377, 0, 0, 0, 0, + 2377, 2378, 0, 0, 0, 2378, 2378, 2378, 0, 0, + 0, 0, 2378, 2379, 0, 0, 0, 2379, 2379, 2379, + 0, 0, 0, 0, 2379, 2380, 0, 0, 0, 2380, + 2380, 2380, 0, 0, 0, 0, 2380, 2381, 0, 0, + + 0, 2381, 2381, 2381, 0, 0, 0, 0, 2381, 2382, + 0, 0, 0, 2382, 2382, 2382, 0, 0, 0, 0, + 2382, 2383, 0, 0, 0, 2383, 2383, 2383, 0, 0, + 0, 0, 2383, 2384, 2384, 2384, 2385, 0, 0, 0, + 2385, 2385, 2385, 0, 0, 0, 0, 2385, 2386, 2386, + 2386, 2388, 0, 2388, 0, 2388, 2388, 0, 0, 0, + 0, 0, 2388, 2389, 0, 2389, 0, 2389, 2389, 0, + 0, 0, 0, 0, 2389, 2390, 2390, 2390, 2391, 2391, + 2391, 2392, 0, 0, 0, 2392, 2392, 2392, 0, 0, + 0, 0, 2392, 2393, 0, 0, 0, 2393, 2393, 2393, + + 0, 0, 0, 0, 2393, 2394, 0, 0, 0, 2394, + 2394, 2394, 0, 0, 0, 0, 2394, 2395, 0, 0, + 0, 2395, 2395, 2395, 0, 0, 0, 0, 2395, 2396, + 0, 0, 0, 2396, 2396, 2396, 0, 0, 0, 0, + 2396, 2397, 0, 0, 0, 2397, 2397, 2397, 0, 0, + 0, 0, 2397, 2398, 0, 0, 0, 2398, 2398, 2398, + 0, 0, 0, 0, 2398, 2399, 0, 0, 0, 2399, + 2399, 2399, 0, 0, 0, 0, 2399, 2400, 0, 0, + 0, 2400, 2400, 2400, 0, 0, 0, 0, 2400, 2401, + 0, 0, 0, 2401, 2401, 2401, 0, 0, 0, 0, + + 2401, 2402, 0, 0, 0, 2402, 2402, 2402, 0, 0, + 0, 0, 2402, 2403, 0, 0, 0, 2403, 2403, 2403, + 0, 0, 0, 0, 2403, 2404, 0, 0, 0, 2404, + 2404, 2404, 0, 0, 0, 0, 2404, 2405, 0, 0, + 0, 2405, 2405, 2405, 0, 0, 0, 0, 2405, 2406, + 0, 0, 0, 2406, 2406, 2406, 0, 0, 0, 0, + 2406, 2407, 0, 0, 0, 2407, 2407, 2407, 0, 0, + 0, 0, 2407, 2408, 0, 0, 0, 2408, 2408, 2408, + 0, 0, 0, 0, 2408, 2409, 0, 0, 0, 2409, + 2409, 2409, 0, 0, 0, 0, 2409, 2410, 0, 0, + + 0, 2410, 2410, 2410, 0, 0, 0, 0, 2410, 2411, + 0, 0, 0, 2411, 2411, 2411, 0, 0, 0, 0, + 2411, 2412, 0, 0, 0, 2412, 2412, 2412, 0, 0, + 0, 0, 2412, 2413, 0, 0, 0, 2413, 2413, 2413, + 0, 0, 0, 0, 2413, 2414, 0, 0, 0, 2414, + 2414, 2414, 0, 0, 0, 0, 2414, 2415, 0, 0, + 0, 2415, 2415, 2415, 0, 0, 0, 0, 2415, 2416, + 0, 0, 0, 2416, 2416, 2416, 0, 0, 0, 0, + 2416, 2417, 0, 0, 0, 2417, 2417, 2417, 0, 0, + 0, 0, 2417, 2418, 0, 0, 0, 2418, 2418, 2418, + + 0, 0, 0, 0, 2418, 2419, 0, 0, 0, 2419, + 2419, 2419, 0, 0, 0, 0, 2419, 2420, 0, 0, + 0, 2420, 2420, 2420, 0, 0, 0, 0, 2420, 2421, + 0, 0, 0, 2421, 2421, 2421, 0, 0, 0, 0, + 2421, 2422, 0, 0, 0, 2422, 2422, 2422, 0, 0, + 0, 0, 2422, 2423, 0, 0, 0, 2423, 2423, 2423, + 0, 0, 0, 0, 2423, 2424, 0, 0, 0, 2424, + 2424, 2424, 0, 0, 0, 0, 2424, 2425, 0, 0, + 0, 2425, 2425, 2425, 0, 0, 0, 0, 2425, 2426, + 0, 0, 0, 2426, 2426, 2426, 0, 0, 0, 0, + + 2426, 2427, 0, 0, 0, 2427, 2427, 2427, 0, 0, + 0, 0, 2427, 2428, 0, 0, 0, 2428, 2428, 2428, + 0, 0, 0, 0, 2428, 2429, 0, 0, 0, 2429, + 2429, 2429, 0, 0, 0, 0, 2429, 2430, 0, 0, + 0, 2430, 2430, 2430, 0, 0, 0, 0, 2430, 2431, + 0, 0, 0, 2431, 2431, 2431, 0, 0, 0, 0, + 2431, 2432, 0, 0, 0, 2432, 2432, 2432, 0, 0, + 0, 0, 2432, 2433, 0, 0, 0, 2433, 2433, 2433, + 0, 0, 0, 0, 2433, 2434, 0, 0, 0, 2434, + 2434, 2434, 0, 0, 0, 0, 2434, 2435, 0, 0, + + 0, 2435, 2435, 2435, 0, 0, 0, 0, 2435, 2436, + 0, 0, 0, 2436, 2436, 2436, 0, 0, 0, 0, + 2436, 2437, 0, 0, 0, 2437, 2437, 2437, 0, 0, + 0, 0, 2437, 2438, 0, 0, 0, 2438, 2438, 2438, + 0, 0, 0, 0, 2438, 2439, 0, 0, 0, 2439, + 2439, 2439, 0, 0, 0, 0, 2439, 2440, 0, 0, + 0, 2440, 2440, 2440, 0, 0, 0, 0, 2440, 2441, + 0, 0, 0, 2441, 2441, 2441, 0, 0, 0, 0, + 2441, 2442, 0, 0, 0, 2442, 2442, 2442, 0, 0, + 0, 0, 2442, 2443, 0, 0, 0, 2443, 2443, 2443, + + 0, 0, 0, 0, 2443, 2444, 0, 0, 0, 2444, + 2444, 2444, 0, 0, 0, 0, 2444, 2445, 0, 0, + 0, 2445, 2445, 2445, 0, 0, 0, 0, 2445, 2446, + 0, 0, 0, 2446, 2446, 2446, 0, 0, 0, 0, + 2446, 2447, 0, 0, 0, 2447, 2447, 2447, 0, 0, + 0, 0, 2447, 2448, 0, 0, 0, 2448, 2448, 2448, + 0, 0, 0, 0, 2448, 2449, 0, 0, 0, 2449, + 2449, 2449, 0, 0, 0, 0, 2449, 2450, 0, 0, + 0, 2450, 2450, 2450, 0, 0, 0, 0, 2450, 2451, + 0, 0, 0, 2451, 2451, 2451, 0, 0, 0, 0, + + 2451, 2452, 0, 0, 0, 2452, 2452, 2452, 0, 0, + 0, 0, 2452, 2453, 0, 0, 0, 2453, 2453, 2453, + 0, 0, 0, 0, 2453, 2454, 0, 0, 0, 2454, + 2454, 2454, 0, 0, 0, 0, 2454, 2455, 0, 0, + 0, 2455, 2455, 2455, 0, 0, 0, 0, 2455, 2456, + 0, 0, 0, 2456, 2456, 2456, 0, 0, 0, 0, + 2456, 2457, 0, 0, 0, 2457, 2457, 2457, 0, 0, + 0, 0, 2457, 2458, 0, 0, 0, 2458, 2458, 2458, + 0, 0, 0, 0, 2458, 2459, 0, 0, 0, 2459, + 2459, 2459, 0, 0, 0, 0, 2459, 2460, 0, 0, + + 0, 2460, 2460, 2460, 0, 0, 0, 0, 2460, 2461, + 0, 0, 0, 2461, 2461, 2461, 0, 0, 0, 0, + 2461, 2462, 0, 0, 0, 2462, 2462, 2462, 0, 0, + 0, 0, 2462, 2463, 0, 0, 0, 2463, 2463, 2463, + 0, 0, 0, 0, 2463, 2464, 0, 0, 0, 2464, + 2464, 2464, 0, 0, 0, 0, 2464, 2465, 0, 0, + 0, 2465, 2465, 2465, 0, 0, 0, 0, 2465, 2466, + 0, 0, 0, 2466, 2466, 2466, 0, 0, 0, 0, + 2466, 2467, 0, 0, 0, 2467, 2467, 2467, 0, 0, + 0, 0, 2467, 2468, 0, 0, 0, 2468, 2468, 2468, + + 0, 0, 0, 0, 2468, 2469, 0, 0, 0, 2469, + 2469, 2469, 0, 0, 0, 0, 2469, 2470, 0, 0, + 0, 2470, 2470, 2470, 0, 0, 0, 0, 2470, 2471, + 0, 0, 0, 2471, 2471, 2471, 0, 0, 0, 0, + 2471, 2472, 0, 0, 0, 2472, 2472, 2472, 0, 0, + 0, 0, 2472, 2473, 0, 0, 0, 2473, 2473, 2473, + 0, 0, 0, 0, 2473, 2474, 0, 0, 0, 2474, + 2474, 2474, 0, 0, 0, 0, 2474, 2475, 0, 0, + 0, 2475, 2475, 2475, 0, 0, 0, 0, 2475, 2476, + 0, 0, 0, 2476, 2476, 2476, 0, 0, 0, 0, + + 2476, 2477, 0, 0, 0, 2477, 2477, 2477, 0, 0, + 0, 0, 2477, 2478, 0, 0, 0, 2478, 2478, 2478, + 0, 0, 0, 0, 2478, 2479, 0, 0, 0, 2479, + 2479, 2479, 0, 0, 0, 0, 2479, 2480, 0, 0, + 0, 2480, 2480, 2480, 0, 0, 0, 0, 2480, 2481, + 0, 0, 0, 2481, 2481, 2481, 0, 0, 0, 0, + 2481, 2482, 0, 0, 0, 2482, 2482, 2482, 0, 0, + 0, 0, 2482, 2483, 0, 0, 0, 2483, 2483, 2483, + 0, 0, 0, 0, 2483, 2484, 0, 0, 0, 2484, + 2484, 2484, 0, 0, 0, 0, 2484, 2485, 0, 0, + + 0, 2485, 2485, 2485, 0, 0, 0, 0, 2485, 2486, + 0, 0, 0, 2486, 2486, 2486, 0, 0, 0, 0, + 2486, 2487, 0, 0, 0, 2487, 2487, 2487, 0, 0, + 0, 0, 2487, 2488, 0, 0, 0, 2488, 2488, 2488, + 0, 0, 0, 0, 2488, 2489, 0, 0, 0, 2489, + 2489, 2489, 0, 0, 0, 0, 2489, 2490, 0, 0, + 0, 2490, 2490, 2490, 0, 0, 0, 0, 2490, 2491, + 0, 0, 0, 2491, 2491, 2491, 0, 0, 0, 0, + 2491, 2492, 0, 0, 0, 2492, 2492, 2492, 0, 0, + 0, 0, 2492, 2493, 0, 0, 0, 2493, 2493, 2493, + + 0, 0, 0, 0, 2493, 2494, 0, 0, 0, 2494, + 2494, 2494, 0, 0, 0, 0, 2494, 2495, 0, 0, + 0, 2495, 2495, 2495, 0, 0, 0, 0, 2495, 2496, + 0, 0, 0, 2496, 2496, 2496, 0, 0, 0, 0, + 2496, 2497, 0, 0, 0, 2497, 2497, 2497, 0, 0, + 0, 0, 2497, 2498, 0, 0, 0, 2498, 2498, 2498, + 0, 0, 0, 0, 2498, 2499, 0, 0, 0, 2499, + 2499, 2499, 0, 0, 0, 0, 2499, 2500, 0, 0, + 0, 2500, 2500, 2500, 0, 0, 0, 0, 2500, 2501, + 0, 0, 0, 2501, 2501, 2501, 0, 0, 0, 0, + + 2501, 2502, 0, 0, 0, 2502, 2502, 2502, 0, 0, + 0, 0, 2502, 2503, 0, 0, 0, 2503, 2503, 2503, + 0, 0, 0, 0, 2503, 2504, 0, 0, 0, 2504, + 2504, 2504, 0, 0, 0, 0, 2504, 2505, 0, 0, + 0, 2505, 2505, 2505, 0, 0, 0, 0, 2505, 2506, + 0, 0, 0, 2506, 2506, 2506, 0, 0, 0, 0, + 2506, 2507, 0, 0, 0, 2507, 2507, 2507, 0, 0, + 0, 0, 2507, 2508, 0, 0, 0, 2508, 2508, 2508, + 0, 0, 0, 0, 2508, 2509, 0, 0, 0, 2509, + 2509, 2509, 0, 0, 0, 0, 2509, 2510, 0, 0, + + 0, 2510, 2510, 2510, 0, 0, 0, 0, 2510, 2511, + 0, 0, 0, 2511, 2511, 2511, 0, 0, 0, 0, + 2511, 2512, 0, 0, 0, 2512, 2512, 2512, 0, 0, + 0, 0, 2512, 2513, 0, 0, 0, 2513, 2513, 2513, + 0, 0, 0, 0, 2513, 2514, 0, 0, 0, 2514, + 2514, 2514, 0, 0, 0, 0, 2514, 2515, 0, 0, + 0, 2515, 2515, 2515, 0, 0, 0, 0, 2515, 2516, + 2516, 2516, 2517, 0, 0, 0, 2517, 2517, 2517, 0, + 0, 0, 0, 2517, 2518, 2518, 2518, 2519, 2519, 2519, + 0, 0, 0, 0, 2519, 2520, 2520, 2520, 2521, 2521, + + 2521, 2522, 2522, 2522, 2523, 2523, 2523, 2524, 0, 2524, + 0, 2524, 2524, 0, 0, 0, 0, 0, 2524, 2525, + 0, 2525, 0, 2525, 2525, 0, 0, 0, 0, 0, + 2525, 2526, 0, 0, 0, 2526, 2526, 2526, 0, 0, + 0, 0, 2526, 2527, 0, 0, 0, 2527, 2527, 2527, + 0, 0, 0, 0, 2527, 2528, 0, 0, 0, 2528, + 2528, 2528, 0, 0, 0, 0, 2528, 2529, 0, 0, + 0, 2529, 2529, 2529, 0, 0, 0, 0, 2529, 2530, + 0, 0, 0, 2530, 2530, 2530, 0, 0, 0, 0, + 2530, 2531, 0, 0, 0, 2531, 2531, 2531, 0, 0, + + 0, 0, 2531, 2532, 0, 0, 0, 2532, 2532, 2532, + 0, 0, 0, 0, 2532, 2533, 0, 0, 0, 2533, + 2533, 2533, 0, 0, 0, 0, 2533, 2534, 0, 0, + 0, 2534, 2534, 2534, 0, 0, 0, 0, 2534, 2535, + 0, 0, 0, 2535, 2535, 2535, 0, 0, 0, 0, + 2535, 2536, 0, 0, 0, 2536, 2536, 2536, 0, 0, + 0, 0, 2536, 2537, 0, 0, 0, 2537, 2537, 2537, + 0, 0, 0, 0, 2537, 2538, 0, 0, 0, 2538, + 2538, 2538, 0, 0, 0, 0, 2538, 2539, 0, 0, + 0, 2539, 2539, 2539, 0, 0, 0, 0, 2539, 2540, + + 0, 0, 0, 2540, 2540, 2540, 0, 0, 0, 0, + 2540, 2541, 0, 0, 0, 2541, 2541, 2541, 0, 0, + 0, 0, 2541, 2542, 0, 0, 0, 2542, 2542, 2542, + 0, 0, 0, 0, 2542, 2543, 0, 0, 0, 2543, + 2543, 2543, 0, 0, 0, 0, 2543, 2544, 0, 0, + 0, 2544, 2544, 2544, 0, 0, 0, 0, 2544, 2545, + 0, 0, 0, 2545, 2545, 2545, 0, 0, 0, 0, + 2545, 2546, 0, 0, 0, 2546, 2546, 2546, 0, 0, + 0, 0, 2546, 2547, 0, 0, 0, 2547, 2547, 2547, + 0, 0, 0, 0, 2547, 2548, 0, 0, 0, 2548, + + 2548, 2548, 0, 0, 0, 0, 2548, 2549, 0, 0, + 0, 2549, 2549, 2549, 0, 0, 0, 0, 2549, 2550, + 0, 0, 0, 2550, 2550, 2550, 0, 0, 0, 0, + 2550, 2551, 0, 0, 0, 2551, 2551, 2551, 0, 0, + 0, 0, 2551, 2552, 0, 0, 0, 2552, 2552, 2552, + 0, 0, 0, 0, 2552, 2553, 0, 0, 0, 2553, + 2553, 2553, 0, 0, 0, 0, 2553, 2554, 0, 0, + 0, 2554, 2554, 2554, 0, 0, 0, 0, 2554, 2555, + 0, 0, 0, 2555, 2555, 2555, 0, 0, 0, 0, + 2555, 2556, 0, 0, 0, 2556, 2556, 2556, 0, 0, + + 0, 0, 2556, 2557, 0, 0, 0, 2557, 2557, 2557, + 0, 0, 0, 0, 2557, 2558, 0, 0, 0, 2558, + 2558, 2558, 0, 0, 0, 0, 2558, 2559, 0, 0, + 0, 2559, 2559, 2559, 0, 0, 0, 0, 2559, 2560, + 0, 0, 0, 2560, 2560, 2560, 0, 0, 0, 0, + 2560, 2561, 0, 0, 0, 2561, 2561, 2561, 0, 0, + 0, 0, 2561, 2562, 0, 0, 0, 2562, 2562, 2562, + 0, 0, 0, 0, 2562, 2563, 0, 0, 0, 2563, + 2563, 2563, 0, 0, 0, 0, 2563, 2564, 0, 0, + 0, 2564, 2564, 2564, 0, 0, 0, 0, 2564, 2565, + + 0, 0, 0, 2565, 2565, 2565, 0, 0, 0, 0, + 2565, 2566, 0, 0, 0, 2566, 2566, 2566, 0, 0, + 0, 0, 2566, 2567, 0, 0, 0, 2567, 2567, 2567, + 0, 0, 0, 0, 2567, 2568, 2568, 2568, 2569, 0, + 0, 0, 2569, 2569, 2569, 0, 0, 0, 0, 2569, + 2570, 2570, 2570, 2571, 2571, 2571, 2572, 2572, 2572, 2573, + 2573, 2573, 2576, 0, 2576, 0, 2576, 2576, 0, 0, + 0, 0, 0, 2576, 2579, 0, 2579, 0, 2579, 2579, + 0, 0, 0, 0, 0, 2579, 2580, 2580, 2580, 2581, + 2581, 2581, 2582, 0, 0, 0, 2582, 2582, 2582, 0, + + 0, 0, 0, 2582, 2583, 2583, 2583, 2584, 0, 0, + 0, 2584, 2584, 2584, 0, 0, 0, 0, 2584, 2585, + 2585, 2585, 2586, 2586, 2586, 2588, 2588, 2588, 2590, 2590, + 2590, 2593, 0, 2593, 0, 2593, 2593, 0, 0, 0, + 0, 0, 2593, 2596, 0, 2596, 0, 2596, 2596, 0, + 0, 0, 0, 0, 2596, 2597, 2597, 2597, 2598, 0, + 0, 0, 2598, 2598, 2598, 0, 0, 0, 0, 2598, + 2599, 2599, 2599, 2600, 2600, 2600, 2601, 2601, 2601, 2602, + 2602, 2602, 2604, 2604, 2604, 2606, 2606, 2606, 2607, 2607, + 2607, 2608, 2608, 2608, 2609, 2609, 2609, 2610, 2610, 2610, + + 2611, 2611, 2611, 2612, 2612, 2612, 2613, 2613, 2613, 2614, + 0, 2614, 0, 2614, 2614, 2614, 0, 0, 0, 0, + 2614, 2615, 0, 2615, 0, 2615, 2615, 2615, 0, 0, + 0, 0, 2615, 2616, 2616, 2616, 2617, 2617, 2617, 2618, + 0, 2618, 0, 2618, 2618, 2618, 0, 0, 0, 0, + 2618, 2619, 0, 2619, 0, 2619, 2619, 2619, 0, 0, + 0, 0, 2619, 2620, 0, 2620, 0, 2620, 2620, 2620, + 0, 0, 0, 0, 2620, 2621, 0, 2621, 0, 2621, + 2621, 2621, 0, 0, 0, 0, 2621, 2622, 2622, 2622, + 2623, 0, 2623, 0, 2623, 2623, 2623, 0, 0, 0, + + 0, 2623, 2624, 0, 2624, 0, 2624, 2624, 2624, 0, + 0, 0, 0, 2624, 2625, 0, 2625, 0, 2625, 2625, + 2625, 0, 0, 0, 0, 2625, 2626, 0, 2626, 0, + 2626, 2626, 2626, 0, 0, 0, 0, 2626, 2627, 0, + 2627, 0, 2627, 2627, 2627, 0, 0, 0, 0, 2627, + 2628, 0, 2628, 0, 2628, 2628, 2628, 0, 0, 0, + 0, 2628, 2629, 0, 2629, 0, 2629, 2629, 2629, 0, + 0, 0, 0, 2629, 2630, 0, 2630, 0, 2630, 2630, + 2630, 0, 0, 0, 0, 2630, 2631, 0, 2631, 0, + 2631, 2631, 2631, 0, 0, 0, 0, 2631, 2632, 0, + + 2632, 0, 2632, 2632, 2632, 0, 0, 0, 0, 2632, + 2633, 0, 2633, 0, 2633, 2633, 2633, 0, 0, 0, + 0, 2633, 2634, 0, 2634, 0, 2634, 2634, 2634, 0, + 0, 0, 0, 2634, 2635, 0, 2635, 0, 2635, 2635, + 2635, 0, 0, 0, 0, 2635, 2636, 0, 2636, 0, + 2636, 2636, 2636, 0, 0, 0, 0, 2636, 1612, 1612, + 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, + 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, + 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, + 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612, 1612 + + } ; + +/* The intent behind this definition is that it'll catch + * any uses of REJECT which flex missed. + */ +#define REJECT reject_used_but_not_detected +#define yymore() yymore_used_but_not_detected +#define YY_MORE_ADJ 0 +#define YY_RESTORE_YY_MORE_OFFSET +#line 1 "vrscanl.l" +/* + * + * Copyright (C) 1997-2015, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Hermann Grevemeyer et al. + * + * Purpose: + * These are the regular expressions for the value representations + * + */ +/* Avoid compiler warnings about unused functions */ +#define YY_NO_INPUT 1 +#line 28 "vrscanl.l" +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "vrscani.h" +/* Make this work on windows (we don't need interactivity anyway) */ +/* This seems to be a bug: The .c file won't include it, but .h will + * nevertheless. + * %option nounistd + * Our workaround: Define YY_NO_UNISTD_H in vrscani.h and make + * sure that header is included before vrscanl.h. + */ +#line 4905 "vrscanl.c" + +#define INITIAL 0 + +#ifndef YY_NO_UNISTD_H +/* Special case for "unistd.h", since it is non-ANSI. We include it way + * down here because we want the user's section 1 to have been scanned first. + * The user has a chance to override it with an option. + */ +#include +#endif + +#ifndef YY_EXTRA_TYPE +#define YY_EXTRA_TYPE void * +#endif + +/* Holds the entire state of the reentrant scanner. */ +struct yyguts_t + { + + /* User-defined. Not touched by flex. */ + YY_EXTRA_TYPE yyextra_r; + + /* The rest are the same as the globals declared in the non-reentrant scanner. */ + FILE *yyin_r, *yyout_r; + size_t yy_buffer_stack_top; /**< index of top of stack. */ + size_t yy_buffer_stack_max; /**< capacity of stack. */ + YY_BUFFER_STATE * yy_buffer_stack; /**< Stack as an array. */ + char yy_hold_char; + int yy_n_chars; + int yyleng_r; + char *yy_c_buf_p; + int yy_init; + int yy_start; + int yy_did_buffer_switch_on_eof; + int yy_start_stack_ptr; + int yy_start_stack_depth; + int *yy_start_stack; + yy_state_type yy_last_accepting_state; + char* yy_last_accepting_cpos; + + int yylineno_r; + int yy_flex_debug_r; + + char *yytext_r; + int yy_more_flag; + int yy_more_len; + + }; /* end struct yyguts_t */ + +static int yy_init_globals (yyscan_t yyscanner ); + +int yylex_init (yyscan_t* scanner); + +int yylex_init_extra (YY_EXTRA_TYPE user_defined,yyscan_t* scanner); + +/* Accessor methods to globals. + These are made visible to non-reentrant scanners for convenience. */ + +int yylex_destroy (yyscan_t yyscanner ); + +int yyget_debug (yyscan_t yyscanner ); + +void yyset_debug (int debug_flag ,yyscan_t yyscanner ); + +YY_EXTRA_TYPE yyget_extra (yyscan_t yyscanner ); + +void yyset_extra (YY_EXTRA_TYPE user_defined ,yyscan_t yyscanner ); + +FILE *yyget_in (yyscan_t yyscanner ); + +void yyset_in (FILE * in_str ,yyscan_t yyscanner ); + +FILE *yyget_out (yyscan_t yyscanner ); + +void yyset_out (FILE * out_str ,yyscan_t yyscanner ); + +int yyget_leng (yyscan_t yyscanner ); + +char *yyget_text (yyscan_t yyscanner ); + +int yyget_lineno (yyscan_t yyscanner ); + +void yyset_lineno (int line_number ,yyscan_t yyscanner ); + +/* Macros after this point can all be overridden by user definitions in + * section 1. + */ + +#ifndef YY_SKIP_YYWRAP +#ifdef __cplusplus +extern "C" int yywrap (yyscan_t yyscanner ); +#else +extern int yywrap (yyscan_t yyscanner ); +#endif +#endif + +#ifndef yytext_ptr +static void yy_flex_strncpy (char *,yyconst char *,int ,yyscan_t yyscanner); +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen (yyconst char * ,yyscan_t yyscanner); +#endif + +#ifndef YY_NO_INPUT + +#ifdef __cplusplus +static int yyinput (yyscan_t yyscanner ); +#else +static int input (yyscan_t yyscanner ); +#endif + +#endif + +/* Amount of stuff to slurp up with each read. */ +#ifndef YY_READ_BUF_SIZE +#ifdef __ia64__ +/* On IA-64, the buffer size is 16k, not 8k */ +#define YY_READ_BUF_SIZE 16384 +#else +#define YY_READ_BUF_SIZE 8192 +#endif /* __ia64__ */ +#endif + +/* Copy whatever the last rule matched to the standard output. */ +#ifndef ECHO +/* This used to be an fputs(), but since the string might contain NUL's, + * we now use fwrite(). + */ +#define ECHO do { if (fwrite( yytext, yyleng, 1, yyout )) {} } while (0) +#endif + +/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, + * is returned in "result". + */ +#ifndef YY_INPUT +#define YY_INPUT(buf,result,max_size) \ + if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \ + { \ + int c = '*'; \ + size_t n; \ + for ( n = 0; n < max_size && \ + (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ + buf[n] = (char) c; \ + if ( c == '\n' ) \ + buf[n++] = (char) c; \ + if ( c == EOF && ferror( yyin ) ) \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + result = n; \ + } \ + else \ + { \ + errno=0; \ + while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \ + { \ + if( errno != EINTR) \ + { \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + break; \ + } \ + errno=0; \ + clearerr(yyin); \ + } \ + }\ +\ + +#endif + +/* No semi-colon after return; correct usage is to write "yyterminate();" - + * we don't want an extra ';' after the "return" because that will cause + * some compilers to complain about unreachable statements. + */ +#ifndef yyterminate +#define yyterminate() return YY_NULL +#endif + +/* Number of entries by which start-condition stack grows. */ +#ifndef YY_START_STACK_INCR +#define YY_START_STACK_INCR 25 +#endif + +/* Report a fatal error. */ +#ifndef YY_FATAL_ERROR +#define YY_FATAL_ERROR(msg) yy_fatal_error( msg , yyscanner) +#endif + +/* end tables serialization structures and prototypes */ + +/* Default declaration of generated scanner - a define so the user can + * easily add parameters. + */ +#ifndef YY_DECL +#define YY_DECL_IS_OURS 1 + +extern int yylex (yyscan_t yyscanner); + +#define YY_DECL int yylex (yyscan_t yyscanner) +#endif /* !YY_DECL */ + +/* Code executed at the beginning of each rule, after yytext and yyleng + * have been set up. + */ +#ifndef YY_USER_ACTION +#define YY_USER_ACTION +#endif + +/* Code executed at the end of each rule. */ +#ifndef YY_BREAK +#define YY_BREAK break; +#endif + +#define YY_RULE_SETUP \ + YY_USER_ACTION + +/** The main scanner function which does all the work. + */ +YY_DECL +{ + register yy_state_type yy_current_state; + register char *yy_cp, *yy_bp; + register int yy_act; + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + +#line 100 "vrscanl.l" + + +#line 5132 "vrscanl.c" + + if ( !yyg->yy_init ) + { + yyg->yy_init = 1; + +#ifdef YY_USER_INIT + YY_USER_INIT; +#endif + + if ( ! yyg->yy_start ) + yyg->yy_start = 1; /* first start state */ + + if ( ! yyin ) + yyin = stdin; + + if ( ! yyout ) + yyout = stdout; + + if ( ! YY_CURRENT_BUFFER ) { + yyensure_buffer_stack (yyscanner); + YY_CURRENT_BUFFER_LVALUE = + yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); + } + + yy_load_buffer_state(yyscanner ); + } + + while ( 1 ) /* loops until end-of-file is reached */ + { + yy_cp = yyg->yy_c_buf_p; + + /* Support of yytext. */ + *yy_cp = yyg->yy_hold_char; + + /* yy_bp points to the position in yy_ch_buf of the start of + * the current run. + */ + yy_bp = yy_cp; + + yy_current_state = yyg->yy_start; +yy_match: + do + { + register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)]; + if ( yy_accept[yy_current_state] ) + { + yyg->yy_last_accepting_state = yy_current_state; + yyg->yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 1613 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + ++yy_cp; + } + while ( yy_current_state != 1612 ); + yy_cp = yyg->yy_last_accepting_cpos; + yy_current_state = yyg->yy_last_accepting_state; + +yy_find_action: + yy_act = yy_accept[yy_current_state]; + + YY_DO_BEFORE_ACTION; + +do_action: /* This label is used only to access EOF actions. */ + + switch ( yy_act ) + { /* beginning of action switch */ + case 0: /* must back up */ + /* undo the effects of YY_DO_BEFORE_ACTION */ + *yy_cp = yyg->yy_hold_char; + yy_cp = yyg->yy_last_accepting_cpos; + yy_current_state = yyg->yy_last_accepting_state; + goto yy_find_action; + +case 1: +YY_RULE_SETUP +#line 102 "vrscanl.l" +{return 1; /* AS */} + YY_BREAK +case 2: +YY_RULE_SETUP +#line 103 "vrscanl.l" +{return 2; /* DA */} + YY_BREAK +case 3: +YY_RULE_SETUP +#line 104 "vrscanl.l" +{return 3; /* OLD_DA */} + YY_BREAK +case 4: +YY_RULE_SETUP +#line 105 "vrscanl.l" +{return 17; /* dubious DA */} + YY_BREAK +case 5: +YY_RULE_SETUP +#line 106 "vrscanl.l" +{return 4; /* TM */} + YY_BREAK +case 6: +YY_RULE_SETUP +#line 107 "vrscanl.l" +{return 5; /* OLD_TM */} + YY_BREAK +case 7: +YY_RULE_SETUP +#line 108 "vrscanl.l" +{return 6; /* DS */} + YY_BREAK +case 8: +YY_RULE_SETUP +#line 109 "vrscanl.l" +{return 7; /* DT */} + YY_BREAK +case 9: +YY_RULE_SETUP +#line 110 "vrscanl.l" +{return 18; /* dubious DT */} + YY_BREAK +case 10: +YY_RULE_SETUP +#line 111 "vrscanl.l" +{return 8; /* IS */} + YY_BREAK +case 11: +YY_RULE_SETUP +#line 112 "vrscanl.l" +{return 9; /* UI */} + YY_BREAK +case 12: +YY_RULE_SETUP +#line 113 "vrscanl.l" +{return 10; /* CS */} + YY_BREAK +case 13: +YY_RULE_SETUP +#line 114 "vrscanl.l" +{return 11; /* PN */} + YY_BREAK +case 14: +YY_RULE_SETUP +#line 115 "vrscanl.l" +{return 15; /* OLD_PN: not used any longer within DCMTK */} + YY_BREAK +case 15: +YY_RULE_SETUP +#line 116 "vrscanl.l" +{return 12; /* LO | SH */} + YY_BREAK +case 16: +YY_RULE_SETUP +#line 117 "vrscanl.l" +{return 13; /* AE */} + YY_BREAK +case 17: +/* rule 17 can match eol */ +YY_RULE_SETUP +#line 118 "vrscanl.l" +{return 14; /* LT | ST | UT */} + YY_BREAK +case 18: +YY_RULE_SETUP +#line 119 "vrscanl.l" +{return 19; /* UR */} + YY_BREAK +case 19: +YY_RULE_SETUP +#line 120 "vrscanl.l" +{return 20; /* UC */} + YY_BREAK +/* . doesn't match \n, this needs a special case! */ +case 20: +/* rule 20 can match eol */ +#line 123 "vrscanl.l" +case 21: +/* rule 21 can match eol */ +YY_RULE_SETUP +#line 123 "vrscanl.l" +{return 16; /* UNKNOWN */;} + YY_BREAK +case 22: +YY_RULE_SETUP +#line 125 "vrscanl.l" +ECHO; + YY_BREAK +#line 5322 "vrscanl.c" +case YY_STATE_EOF(INITIAL): + yyterminate(); + + case YY_END_OF_BUFFER: + { + /* Amount of text matched not including the EOB char. */ + int yy_amount_of_matched_text = (int) (yy_cp - yyg->yytext_ptr) - 1; + + /* Undo the effects of YY_DO_BEFORE_ACTION. */ + *yy_cp = yyg->yy_hold_char; + YY_RESTORE_YY_MORE_OFFSET + + if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW ) + { + /* We're scanning a new file or input source. It's + * possible that this happened because the user + * just pointed yyin at a new source and called + * yylex(). If so, then we have to assure + * consistency between YY_CURRENT_BUFFER and our + * globals. Here is the right place to do so, because + * this is the first action (other than possibly a + * back-up) that will match for the new input source. + */ + yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; + YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin; + YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL; + } + + /* Note that here we test for yy_c_buf_p "<=" to the position + * of the first EOB in the buffer, since yy_c_buf_p will + * already have been incremented past the NUL character + * (since all states make transitions on EOB to the + * end-of-buffer state). Contrast this with the test + * in input(). + */ + if ( yyg->yy_c_buf_p <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] ) + { /* This was really a NUL. */ + yy_state_type yy_next_state; + + yyg->yy_c_buf_p = yyg->yytext_ptr + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state( yyscanner ); + + /* Okay, we're now positioned to make the NUL + * transition. We couldn't have + * yy_get_previous_state() go ahead and do it + * for us because it doesn't know how to deal + * with the possibility of jamming (and we don't + * want to build jamming into it because then it + * will run more slowly). + */ + + yy_next_state = yy_try_NUL_trans( yy_current_state , yyscanner); + + yy_bp = yyg->yytext_ptr + YY_MORE_ADJ; + + if ( yy_next_state ) + { + /* Consume the NUL. */ + yy_cp = ++yyg->yy_c_buf_p; + yy_current_state = yy_next_state; + goto yy_match; + } + + else + { + yy_cp = yyg->yy_last_accepting_cpos; + yy_current_state = yyg->yy_last_accepting_state; + goto yy_find_action; + } + } + + else switch ( yy_get_next_buffer( yyscanner ) ) + { + case EOB_ACT_END_OF_FILE: + { + yyg->yy_did_buffer_switch_on_eof = 0; + + if ( yywrap(yyscanner ) ) + { + /* Note: because we've taken care in + * yy_get_next_buffer() to have set up + * yytext, we can now set up + * yy_c_buf_p so that if some total + * hoser (like flex itself) wants to + * call the scanner after we return the + * YY_NULL, it'll still work - another + * YY_NULL will get returned. + */ + yyg->yy_c_buf_p = yyg->yytext_ptr + YY_MORE_ADJ; + + yy_act = YY_STATE_EOF(YY_START); + goto do_action; + } + + else + { + if ( ! yyg->yy_did_buffer_switch_on_eof ) + YY_NEW_FILE; + } + break; + } + + case EOB_ACT_CONTINUE_SCAN: + yyg->yy_c_buf_p = + yyg->yytext_ptr + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state( yyscanner ); + + yy_cp = yyg->yy_c_buf_p; + yy_bp = yyg->yytext_ptr + YY_MORE_ADJ; + goto yy_match; + + case EOB_ACT_LAST_MATCH: + yyg->yy_c_buf_p = + &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars]; + + yy_current_state = yy_get_previous_state( yyscanner ); + + yy_cp = yyg->yy_c_buf_p; + yy_bp = yyg->yytext_ptr + YY_MORE_ADJ; + goto yy_find_action; + } + break; + } + + default: + YY_FATAL_ERROR( + "fatal flex scanner internal error--no action found" ); + } /* end of action switch */ + } /* end of scanning one token */ +} /* end of yylex */ + +/* yy_get_next_buffer - try to read in a new buffer + * + * Returns a code representing an action: + * EOB_ACT_LAST_MATCH - + * EOB_ACT_CONTINUE_SCAN - continue scanning from current position + * EOB_ACT_END_OF_FILE - end of file + */ +static int yy_get_next_buffer (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf; + register char *source = yyg->yytext_ptr; + register int number_to_move, i; + int ret_val; + + if ( yyg->yy_c_buf_p > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] ) + YY_FATAL_ERROR( + "fatal flex scanner internal error--end of buffer missed" ); + + if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 ) + { /* Don't try to fill the buffer, so this is an EOF. */ + if ( yyg->yy_c_buf_p - yyg->yytext_ptr - YY_MORE_ADJ == 1 ) + { + /* We matched a single character, the EOB, so + * treat this as a final EOF. + */ + return EOB_ACT_END_OF_FILE; + } + + else + { + /* We matched some text prior to the EOB, first + * process it. + */ + return EOB_ACT_LAST_MATCH; + } + } + + /* Try to read more data. */ + + /* First move last chars to start of buffer. */ + number_to_move = (int) (yyg->yy_c_buf_p - yyg->yytext_ptr) - 1; + + for ( i = 0; i < number_to_move; ++i ) + *(dest++) = *(source++); + + if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING ) + /* don't do the read, it's not guaranteed to return an EOF, + * just force an EOF + */ + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars = 0; + + else + { + int num_to_read = + YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; + + while ( num_to_read <= 0 ) + { /* Not enough room in the buffer - grow it. */ + + /* just a shorter name for the current buffer */ + YY_BUFFER_STATE b = YY_CURRENT_BUFFER; + + int yy_c_buf_p_offset = + (int) (yyg->yy_c_buf_p - b->yy_ch_buf); + + if ( b->yy_is_our_buffer ) + { + int new_size = b->yy_buf_size * 2; + + if ( new_size <= 0 ) + b->yy_buf_size += b->yy_buf_size / 8; + else + b->yy_buf_size *= 2; + + b->yy_ch_buf = (char *) + /* Include room in for 2 EOB chars. */ + yyrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ,yyscanner ); + } + else + /* Can't grow it, we don't own it. */ + b->yy_ch_buf = 0; + + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( + "fatal error - scanner input buffer overflow" ); + + yyg->yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset]; + + num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - + number_to_move - 1; + + } + + if ( num_to_read > YY_READ_BUF_SIZE ) + num_to_read = YY_READ_BUF_SIZE; + + /* Read in more data. */ + YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]), + yyg->yy_n_chars, (size_t) num_to_read ); + + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars; + } + + if ( yyg->yy_n_chars == 0 ) + { + if ( number_to_move == YY_MORE_ADJ ) + { + ret_val = EOB_ACT_END_OF_FILE; + yyrestart(yyin ,yyscanner); + } + + else + { + ret_val = EOB_ACT_LAST_MATCH; + YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = + YY_BUFFER_EOF_PENDING; + } + } + + else + ret_val = EOB_ACT_CONTINUE_SCAN; + + if ((yy_size_t) (yyg->yy_n_chars + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) { + /* Extend the array by 50%, plus the number we really need. */ + yy_size_t new_size = yyg->yy_n_chars + number_to_move + (yyg->yy_n_chars >> 1); + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ,yyscanner ); + if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" ); + } + + yyg->yy_n_chars += number_to_move; + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] = YY_END_OF_BUFFER_CHAR; + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR; + + yyg->yytext_ptr = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0]; + + return ret_val; +} + +/* yy_get_previous_state - get the state just before the EOB char was reached */ + + static yy_state_type yy_get_previous_state (yyscan_t yyscanner) +{ + register yy_state_type yy_current_state; + register char *yy_cp; + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + yy_current_state = yyg->yy_start; + + for ( yy_cp = yyg->yytext_ptr + YY_MORE_ADJ; yy_cp < yyg->yy_c_buf_p; ++yy_cp ) + { + register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); + if ( yy_accept[yy_current_state] ) + { + yyg->yy_last_accepting_state = yy_current_state; + yyg->yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 1613 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + } + + return yy_current_state; +} + +/* yy_try_NUL_trans - try to make a transition on the NUL character + * + * synopsis + * next_state = yy_try_NUL_trans( current_state ); + */ + static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state , yyscan_t yyscanner) +{ + register int yy_is_jam; + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; /* This var may be unused depending upon options. */ + register char *yy_cp = yyg->yy_c_buf_p; + + register YY_CHAR yy_c = 1; + if ( yy_accept[yy_current_state] ) + { + yyg->yy_last_accepting_state = yy_current_state; + yyg->yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 1613 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + yy_is_jam = (yy_current_state == 1612); + + return yy_is_jam ? 0 : yy_current_state; +} + +#ifndef YY_NO_INPUT +#ifdef __cplusplus + static int yyinput (yyscan_t yyscanner) +#else + static int input (yyscan_t yyscanner) +#endif + +{ + int c; + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + *yyg->yy_c_buf_p = yyg->yy_hold_char; + + if ( *yyg->yy_c_buf_p == YY_END_OF_BUFFER_CHAR ) + { + /* yy_c_buf_p now points to the character we want to return. + * If this occurs *before* the EOB characters, then it's a + * valid NUL; if not, then we've hit the end of the buffer. + */ + if ( yyg->yy_c_buf_p < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] ) + /* This was really a NUL. */ + *yyg->yy_c_buf_p = '\0'; + + else + { /* need more input */ + int offset = yyg->yy_c_buf_p - yyg->yytext_ptr; + ++yyg->yy_c_buf_p; + + switch ( yy_get_next_buffer( yyscanner ) ) + { + case EOB_ACT_LAST_MATCH: + /* This happens because yy_g_n_b() + * sees that we've accumulated a + * token and flags that we need to + * try matching the token before + * proceeding. But for input(), + * there's no matching to consider. + * So convert the EOB_ACT_LAST_MATCH + * to EOB_ACT_END_OF_FILE. + */ + + /* Reset buffer status. */ + yyrestart(yyin ,yyscanner); + + /*FALLTHROUGH*/ + + case EOB_ACT_END_OF_FILE: + { + if ( yywrap(yyscanner ) ) + return EOF; + + if ( ! yyg->yy_did_buffer_switch_on_eof ) + YY_NEW_FILE; +#ifdef __cplusplus + return yyinput(yyscanner); +#else + return input(yyscanner); +#endif + } + + case EOB_ACT_CONTINUE_SCAN: + yyg->yy_c_buf_p = yyg->yytext_ptr + offset; + break; + } + } + } + + c = *(unsigned char *) yyg->yy_c_buf_p; /* cast for 8-bit char's */ + *yyg->yy_c_buf_p = '\0'; /* preserve yytext */ + yyg->yy_hold_char = *++yyg->yy_c_buf_p; + + return c; +} +#endif /* ifndef YY_NO_INPUT */ + +/** Immediately switch to a different input stream. + * @param input_file A readable stream. + * @param yyscanner The scanner object. + * @note This function does not reset the start condition to @c INITIAL . + */ + void yyrestart (FILE * input_file , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + if ( ! YY_CURRENT_BUFFER ){ + yyensure_buffer_stack (yyscanner); + YY_CURRENT_BUFFER_LVALUE = + yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); + } + + yy_init_buffer(YY_CURRENT_BUFFER,input_file ,yyscanner); + yy_load_buffer_state(yyscanner ); +} + +/** Switch to a different input buffer. + * @param new_buffer The new input buffer. + * @param yyscanner The scanner object. + */ + void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + /* TODO. We should be able to replace this entire function body + * with + * yypop_buffer_state(); + * yypush_buffer_state(new_buffer); + */ + yyensure_buffer_stack (yyscanner); + if ( YY_CURRENT_BUFFER == new_buffer ) + return; + + if ( YY_CURRENT_BUFFER ) + { + /* Flush out information for old buffer. */ + *yyg->yy_c_buf_p = yyg->yy_hold_char; + YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = yyg->yy_c_buf_p; + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars; + } + + YY_CURRENT_BUFFER_LVALUE = new_buffer; + yy_load_buffer_state(yyscanner ); + + /* We don't actually know whether we did this switch during + * EOF (yywrap()) processing, but the only time this flag + * is looked at is after yywrap() is called, so it's safe + * to go ahead and always set it. + */ + yyg->yy_did_buffer_switch_on_eof = 1; +} + +static void yy_load_buffer_state (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; + yyg->yytext_ptr = yyg->yy_c_buf_p = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos; + yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file; + yyg->yy_hold_char = *yyg->yy_c_buf_p; +} + +/** Allocate and initialize an input buffer state. + * @param file A readable stream. + * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE. + * @param yyscanner The scanner object. + * @return the allocated buffer state. + */ + YY_BUFFER_STATE yy_create_buffer (FILE * file, int size , yyscan_t yyscanner) +{ + YY_BUFFER_STATE b; + + b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state ) ,yyscanner ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + + b->yy_buf_size = size; + + /* yy_ch_buf has to be 2 characters longer than the size given because + * we need to put in 2 end-of-buffer characters. + */ + b->yy_ch_buf = (char *) yyalloc(b->yy_buf_size + 2 ,yyscanner ); + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + + b->yy_is_our_buffer = 1; + + yy_init_buffer(b,file ,yyscanner); + + return b; +} + +/** Destroy the buffer. + * @param b a buffer created with yy_create_buffer() + * @param yyscanner The scanner object. + */ + void yy_delete_buffer (YY_BUFFER_STATE b , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + if ( ! b ) + return; + + if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */ + YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0; + + if ( b->yy_is_our_buffer ) + yyfree((void *) b->yy_ch_buf ,yyscanner ); + + yyfree((void *) b ,yyscanner ); +} + +#ifndef __cplusplus +extern int isatty (int ); +#endif /* __cplusplus */ + +/* Initializes or reinitializes a buffer. + * This function is sometimes called more than once on the same buffer, + * such as during a yyrestart() or at EOF. + */ + static void yy_init_buffer (YY_BUFFER_STATE b, FILE * file , yyscan_t yyscanner) + +{ + int oerrno = errno; + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + yy_flush_buffer(b ,yyscanner); + + b->yy_input_file = file; + b->yy_fill_buffer = 1; + + /* If b is the current buffer, then yy_init_buffer was _probably_ + * called from yyrestart() or through yy_get_next_buffer. + * In that case, we don't want to reset the lineno or column. + */ + if (b != YY_CURRENT_BUFFER){ + b->yy_bs_lineno = 1; + b->yy_bs_column = 0; + } + + b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0; + + errno = oerrno; +} + +/** Discard all buffered characters. On the next scan, YY_INPUT will be called. + * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER. + * @param yyscanner The scanner object. + */ + void yy_flush_buffer (YY_BUFFER_STATE b , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + if ( ! b ) + return; + + b->yy_n_chars = 0; + + /* We always need two end-of-buffer characters. The first causes + * a transition to the end-of-buffer state. The second causes + * a jam in that state. + */ + b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; + b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; + + b->yy_buf_pos = &b->yy_ch_buf[0]; + + b->yy_at_bol = 1; + b->yy_buffer_status = YY_BUFFER_NEW; + + if ( b == YY_CURRENT_BUFFER ) + yy_load_buffer_state(yyscanner ); +} + +/** Pushes the new state onto the stack. The new state becomes + * the current state. This function will allocate the stack + * if necessary. + * @param new_buffer The new state. + * @param yyscanner The scanner object. + */ +void yypush_buffer_state (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + if (new_buffer == NULL) + return; + + yyensure_buffer_stack(yyscanner); + + /* This block is copied from yy_switch_to_buffer. */ + if ( YY_CURRENT_BUFFER ) + { + /* Flush out information for old buffer. */ + *yyg->yy_c_buf_p = yyg->yy_hold_char; + YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = yyg->yy_c_buf_p; + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars; + } + + /* Only push if top exists. Otherwise, replace top. */ + if (YY_CURRENT_BUFFER) + yyg->yy_buffer_stack_top++; + YY_CURRENT_BUFFER_LVALUE = new_buffer; + + /* copied from yy_switch_to_buffer. */ + yy_load_buffer_state(yyscanner ); + yyg->yy_did_buffer_switch_on_eof = 1; +} + +/** Removes and deletes the top of the stack, if present. + * The next element becomes the new top. + * @param yyscanner The scanner object. + */ +void yypop_buffer_state (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + if (!YY_CURRENT_BUFFER) + return; + + yy_delete_buffer(YY_CURRENT_BUFFER ,yyscanner); + YY_CURRENT_BUFFER_LVALUE = NULL; + if (yyg->yy_buffer_stack_top > 0) + --yyg->yy_buffer_stack_top; + + if (YY_CURRENT_BUFFER) { + yy_load_buffer_state(yyscanner ); + yyg->yy_did_buffer_switch_on_eof = 1; + } +} + +/* Allocates the stack if it does not exist. + * Guarantees space for at least one push. + */ +static void yyensure_buffer_stack (yyscan_t yyscanner) +{ + int num_to_alloc; + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + if (!yyg->yy_buffer_stack) { + + /* First allocation is just for 2 elements, since we don't know if this + * scanner will even need a stack. We use 2 instead of 1 to avoid an + * immediate realloc on the next call. + */ + num_to_alloc = 1; + yyg->yy_buffer_stack = (struct yy_buffer_state**)yyalloc + (num_to_alloc * sizeof(struct yy_buffer_state*) + , yyscanner); + if ( ! yyg->yy_buffer_stack ) + YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" ); + + memset(yyg->yy_buffer_stack, 0, num_to_alloc * sizeof(struct yy_buffer_state*)); + + yyg->yy_buffer_stack_max = num_to_alloc; + yyg->yy_buffer_stack_top = 0; + return; + } + + if (yyg->yy_buffer_stack_top >= (yyg->yy_buffer_stack_max) - 1){ + + /* Increase the buffer to prepare for a possible push. */ + int grow_size = 8 /* arbitrary grow size */; + + num_to_alloc = yyg->yy_buffer_stack_max + grow_size; + yyg->yy_buffer_stack = (struct yy_buffer_state**)yyrealloc + (yyg->yy_buffer_stack, + num_to_alloc * sizeof(struct yy_buffer_state*) + , yyscanner); + if ( ! yyg->yy_buffer_stack ) + YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" ); + + /* zero only the new slots.*/ + memset(yyg->yy_buffer_stack + yyg->yy_buffer_stack_max, 0, grow_size * sizeof(struct yy_buffer_state*)); + yyg->yy_buffer_stack_max = num_to_alloc; + } +} + +/** Setup the input buffer state to scan directly from a user-specified character buffer. + * @param base the character buffer + * @param size the size in bytes of the character buffer + * @param yyscanner The scanner object. + * @return the newly allocated buffer state object. + */ +YY_BUFFER_STATE yy_scan_buffer (char * base, yy_size_t size , yyscan_t yyscanner) +{ + YY_BUFFER_STATE b; + + if ( size < 2 || + base[size-2] != YY_END_OF_BUFFER_CHAR || + base[size-1] != YY_END_OF_BUFFER_CHAR ) + /* They forgot to leave room for the EOB's. */ + return 0; + + b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state ) ,yyscanner ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" ); + + b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ + b->yy_buf_pos = b->yy_ch_buf = base; + b->yy_is_our_buffer = 0; + b->yy_input_file = 0; + b->yy_n_chars = b->yy_buf_size; + b->yy_is_interactive = 0; + b->yy_at_bol = 1; + b->yy_fill_buffer = 0; + b->yy_buffer_status = YY_BUFFER_NEW; + + yy_switch_to_buffer(b ,yyscanner ); + + return b; +} + +/** Setup the input buffer state to scan a string. The next call to yylex() will + * scan from a @e copy of @a str. + * @param yystr a NUL-terminated string to scan + * @param yyscanner The scanner object. + * @return the newly allocated buffer state object. + * @note If you want to scan bytes that may contain NUL values, then use + * yy_scan_bytes() instead. + */ +YY_BUFFER_STATE yy_scan_string (yyconst char * yystr , yyscan_t yyscanner) +{ + + return yy_scan_bytes(yystr,strlen(yystr) ,yyscanner); +} + +/** Setup the input buffer state to scan the given bytes. The next call to yylex() will + * scan from a @e copy of @a bytes. + * @param yybytes the byte buffer to scan + * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes. + * @param yyscanner The scanner object. + * @return the newly allocated buffer state object. + */ +YY_BUFFER_STATE yy_scan_bytes (yyconst char * yybytes, int _yybytes_len , yyscan_t yyscanner) +{ + YY_BUFFER_STATE b; + char *buf; + yy_size_t n; + int i; + + /* Get memory for full buffer, including space for trailing EOB's. */ + n = _yybytes_len + 2; + buf = (char *) yyalloc(n ,yyscanner ); + if ( ! buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" ); + + for ( i = 0; i < _yybytes_len; ++i ) + buf[i] = yybytes[i]; + + buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR; + + b = yy_scan_buffer(buf,n ,yyscanner); + if ( ! b ) + YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" ); + + /* It's okay to grow etc. this buffer, and we should throw it + * away when we're done. + */ + b->yy_is_our_buffer = 1; + + return b; +} + +#ifndef YY_EXIT_FAILURE +#define YY_EXIT_FAILURE 2 +#endif + +static void yy_fatal_error (yyconst char* msg , yyscan_t yyscanner) +{ + (void) fprintf( stderr, "%s\n", msg ); + exit( YY_EXIT_FAILURE ); +} + +/* Redefine yyless() so it works in section 3 code. */ + +#undef yyless +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + int yyless_macro_arg = (n); \ + YY_LESS_LINENO(yyless_macro_arg);\ + yytext[yyleng] = yyg->yy_hold_char; \ + yyg->yy_c_buf_p = yytext + yyless_macro_arg; \ + yyg->yy_hold_char = *yyg->yy_c_buf_p; \ + *yyg->yy_c_buf_p = '\0'; \ + yyleng = yyless_macro_arg; \ + } \ + while ( 0 ) + +/* Accessor methods (get/set functions) to struct members. */ + +/** Get the user-defined data for this scanner. + * @param yyscanner The scanner object. + */ +YY_EXTRA_TYPE yyget_extra (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + return yyextra; +} + +/** Get the current line number. + * @param yyscanner The scanner object. + */ +int yyget_lineno (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + if (! YY_CURRENT_BUFFER) + return 0; + + return yylineno; +} + +/** Get the current column number. + * @param yyscanner The scanner object. + */ +int yyget_column (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + if (! YY_CURRENT_BUFFER) + return 0; + + return yycolumn; +} + +/** Get the input stream. + * @param yyscanner The scanner object. + */ +FILE *yyget_in (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + return yyin; +} + +/** Get the output stream. + * @param yyscanner The scanner object. + */ +FILE *yyget_out (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + return yyout; +} + +/** Get the length of the current token. + * @param yyscanner The scanner object. + */ +int yyget_leng (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + return yyleng; +} + +/** Get the current token. + * @param yyscanner The scanner object. + */ + +char *yyget_text (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + return yytext; +} + +/** Set the user-defined data. This data is never touched by the scanner. + * @param user_defined The data to be associated with this scanner. + * @param yyscanner The scanner object. + */ +void yyset_extra (YY_EXTRA_TYPE user_defined , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + yyextra = user_defined ; +} + +/** Set the current line number. + * @param line_number + * @param yyscanner The scanner object. + */ +void yyset_lineno (int line_number , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + /* lineno is only valid if an input buffer exists. */ + if (! YY_CURRENT_BUFFER ) + yy_fatal_error( "yyset_lineno called with no buffer" , yyscanner); + + yylineno = line_number; +} + +/** Set the current column. + * @param line_number + * @param yyscanner The scanner object. + */ +void yyset_column (int column_no , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + /* column is only valid if an input buffer exists. */ + if (! YY_CURRENT_BUFFER ) + yy_fatal_error( "yyset_column called with no buffer" , yyscanner); + + yycolumn = column_no; +} + +/** Set the input stream. This does not discard the current + * input buffer. + * @param in_str A readable stream. + * @param yyscanner The scanner object. + * @see yy_switch_to_buffer + */ +void yyset_in (FILE * in_str , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + yyin = in_str ; +} + +void yyset_out (FILE * out_str , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + yyout = out_str ; +} + +int yyget_debug (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + return yy_flex_debug; +} + +void yyset_debug (int bdebug , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + yy_flex_debug = bdebug ; +} + +/* Accessor methods for yylval and yylloc */ + +/* User-visible API */ + +/* yylex_init is special because it creates the scanner itself, so it is + * the ONLY reentrant function that doesn't take the scanner as the last argument. + * That's why we explicitly handle the declaration, instead of using our macros. + */ + +int yylex_init(yyscan_t* ptr_yy_globals) + +{ + if (ptr_yy_globals == NULL){ + errno = EINVAL; + return 1; + } + + *ptr_yy_globals = (yyscan_t) yyalloc ( sizeof( struct yyguts_t ), NULL ); + + if (*ptr_yy_globals == NULL){ + errno = ENOMEM; + return 1; + } + + /* By setting to 0xAA, we expose bugs in yy_init_globals. Leave at 0x00 for releases. */ + memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t)); + + return yy_init_globals ( *ptr_yy_globals ); +} + +/* yylex_init_extra has the same functionality as yylex_init, but follows the + * convention of taking the scanner as the last argument. Note however, that + * this is a *pointer* to a scanner, as it will be allocated by this call (and + * is the reason, too, why this function also must handle its own declaration). + * The user defined value in the first argument will be available to yyalloc in + * the yyextra field. + */ + +int yylex_init_extra(YY_EXTRA_TYPE yy_user_defined,yyscan_t* ptr_yy_globals ) + +{ + struct yyguts_t dummy_yyguts; + + yyset_extra (yy_user_defined, &dummy_yyguts); + + if (ptr_yy_globals == NULL){ + errno = EINVAL; + return 1; + } + + *ptr_yy_globals = (yyscan_t) yyalloc ( sizeof( struct yyguts_t ), &dummy_yyguts ); + + if (*ptr_yy_globals == NULL){ + errno = ENOMEM; + return 1; + } + + /* By setting to 0xAA, we expose bugs in + yy_init_globals. Leave at 0x00 for releases. */ + memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t)); + + yyset_extra (yy_user_defined, *ptr_yy_globals); + + return yy_init_globals ( *ptr_yy_globals ); +} + +static int yy_init_globals (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + /* Initialization is the same as for the non-reentrant scanner. + * This function is called from yylex_destroy(), so don't allocate here. + */ + + yyg->yy_buffer_stack = 0; + yyg->yy_buffer_stack_top = 0; + yyg->yy_buffer_stack_max = 0; + yyg->yy_c_buf_p = (char *) 0; + yyg->yy_init = 0; + yyg->yy_start = 0; + + yyg->yy_start_stack_ptr = 0; + yyg->yy_start_stack_depth = 0; + yyg->yy_start_stack = NULL; + +/* Defined in main.c */ +#ifdef YY_STDINIT + yyin = stdin; + yyout = stdout; +#else + yyin = (FILE *) 0; + yyout = (FILE *) 0; +#endif + + /* For future reference: Set errno on error, since we are called by + * yylex_init() + */ + return 0; +} + +/* yylex_destroy is for both reentrant and non-reentrant scanners. */ +int yylex_destroy (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + /* Pop the buffer stack, destroying each element. */ + while(YY_CURRENT_BUFFER){ + yy_delete_buffer(YY_CURRENT_BUFFER ,yyscanner ); + YY_CURRENT_BUFFER_LVALUE = NULL; + yypop_buffer_state(yyscanner); + } + + /* Destroy the stack itself. */ + yyfree(yyg->yy_buffer_stack ,yyscanner); + yyg->yy_buffer_stack = NULL; + + /* Destroy the start condition stack. */ + yyfree(yyg->yy_start_stack ,yyscanner ); + yyg->yy_start_stack = NULL; + + /* Reset the globals. This is important in a non-reentrant scanner so the next time + * yylex() is called, initialization will occur. */ + yy_init_globals( yyscanner); + + /* Destroy the main struct (reentrant only). */ + yyfree ( yyscanner , yyscanner ); + yyscanner = NULL; + return 0; +} + +/* + * Internal utility routines. + */ + +#ifndef yytext_ptr +static void yy_flex_strncpy (char* s1, yyconst char * s2, int n , yyscan_t yyscanner) +{ + register int i; + for ( i = 0; i < n; ++i ) + s1[i] = s2[i]; +} +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen (yyconst char * s , yyscan_t yyscanner) +{ + register int n; + for ( n = 0; s[n]; ++n ) + ; + + return n; +} +#endif + +void *yyalloc (yy_size_t size , yyscan_t yyscanner) +{ + return (void *) malloc( size ); +} + +void *yyrealloc (void * ptr, yy_size_t size , yyscan_t yyscanner) +{ + /* The cast to (char *) in the following accommodates both + * implementations that use char* generic pointers, and those + * that use void* generic pointers. It works with the latter + * because both ANSI C and C++ allow castless assignment from + * any pointer type to void*, and deal with argument conversions + * as though doing an assignment. + */ + return (void *) realloc( (char *) ptr, size ); +} + +void yyfree (void * ptr , yyscan_t yyscanner) +{ + free( (char *) ptr ); /* see yyrealloc() for (char *) cast */ +} + +#define YYTABLES_NAME "yytables" + +#line 125 "vrscanl.l" + + + diff --git a/dcmdata/libsrc/vrscanl.h b/dcmdata/libsrc/vrscanl.h new file mode 100644 index 00000000..6b05068c --- /dev/null +++ b/dcmdata/libsrc/vrscanl.h @@ -0,0 +1,349 @@ +#ifndef yyHEADER_H +#define yyHEADER_H 1 +#define yyIN_HEADER 1 + +#line 6 "vrscanl.h" + +#line 8 "vrscanl.h" + +#define YY_INT_ALIGNED short int + +/* A lexical scanner generated by flex */ + +#define FLEX_SCANNER +#define YY_FLEX_MAJOR_VERSION 2 +#define YY_FLEX_MINOR_VERSION 5 +#define YY_FLEX_SUBMINOR_VERSION 35 +#if YY_FLEX_SUBMINOR_VERSION > 0 +#define FLEX_BETA +#endif + +/* First, we deal with platform-specific or compiler-specific issues. */ + +/* begin standard C headers. */ +#include +#include +#include +#include + +/* end standard C headers. */ + +/* flex integer type definitions */ + +#ifndef FLEXINT_H +#define FLEXINT_H + +/* C99 systems have . Non-C99 systems may or may not. */ + +#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L + +/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h, + * if you want the limit (max/min) macros for int types. + */ +#ifndef __STDC_LIMIT_MACROS +#define __STDC_LIMIT_MACROS 1 +#endif + +#include +typedef int8_t flex_int8_t; +typedef uint8_t flex_uint8_t; +typedef int16_t flex_int16_t; +typedef uint16_t flex_uint16_t; +typedef int32_t flex_int32_t; +typedef uint32_t flex_uint32_t; +#else +typedef signed char flex_int8_t; +typedef short int flex_int16_t; +typedef int flex_int32_t; +typedef unsigned char flex_uint8_t; +typedef unsigned short int flex_uint16_t; +typedef unsigned int flex_uint32_t; + +/* Limits of integral types. */ +#ifndef INT8_MIN +#define INT8_MIN (-128) +#endif +#ifndef INT16_MIN +#define INT16_MIN (-32767-1) +#endif +#ifndef INT32_MIN +#define INT32_MIN (-2147483647-1) +#endif +#ifndef INT8_MAX +#define INT8_MAX (127) +#endif +#ifndef INT16_MAX +#define INT16_MAX (32767) +#endif +#ifndef INT32_MAX +#define INT32_MAX (2147483647) +#endif +#ifndef UINT8_MAX +#define UINT8_MAX (255U) +#endif +#ifndef UINT16_MAX +#define UINT16_MAX (65535U) +#endif +#ifndef UINT32_MAX +#define UINT32_MAX (4294967295U) +#endif + +#endif /* ! C99 */ + +#endif /* ! FLEXINT_H */ + +#ifdef __cplusplus + +/* The "const" storage-class-modifier is valid. */ +#define YY_USE_CONST + +#else /* ! __cplusplus */ + +/* C99 requires __STDC__ to be defined as 1. */ +#if defined (__STDC__) + +#define YY_USE_CONST + +#endif /* defined (__STDC__) */ +#endif /* ! __cplusplus */ + +#ifdef YY_USE_CONST +#define yyconst const +#else +#define yyconst +#endif + +/* An opaque pointer. */ +#ifndef YY_TYPEDEF_YY_SCANNER_T +#define YY_TYPEDEF_YY_SCANNER_T +typedef void* yyscan_t; +#endif + +/* For convenience, these vars (plus the bison vars far below) + are macros in the reentrant scanner. */ +#define yyin yyg->yyin_r +#define yyout yyg->yyout_r +#define yyextra yyg->yyextra_r +#define yyleng yyg->yyleng_r +#define yytext yyg->yytext_r +#define yylineno (YY_CURRENT_BUFFER_LVALUE->yy_bs_lineno) +#define yycolumn (YY_CURRENT_BUFFER_LVALUE->yy_bs_column) +#define yy_flex_debug yyg->yy_flex_debug_r + +/* Size of default input buffer. */ +#ifndef YY_BUF_SIZE +#ifdef __ia64__ +/* On IA-64, the buffer size is 16k, not 8k. + * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case. + * Ditto for the __ia64__ case accordingly. + */ +#define YY_BUF_SIZE 32768 +#else +#define YY_BUF_SIZE 16384 +#endif /* __ia64__ */ +#endif + +#ifndef YY_TYPEDEF_YY_BUFFER_STATE +#define YY_TYPEDEF_YY_BUFFER_STATE +typedef struct yy_buffer_state *YY_BUFFER_STATE; +#endif + +#ifndef YY_TYPEDEF_YY_SIZE_T +#define YY_TYPEDEF_YY_SIZE_T +typedef size_t yy_size_t; +#endif + +#ifndef YY_STRUCT_YY_BUFFER_STATE +#define YY_STRUCT_YY_BUFFER_STATE +struct yy_buffer_state + { + FILE *yy_input_file; + + char *yy_ch_buf; /* input buffer */ + char *yy_buf_pos; /* current position in input buffer */ + + /* Size of input buffer in bytes, not including room for EOB + * characters. + */ + yy_size_t yy_buf_size; + + /* Number of characters read into yy_ch_buf, not including EOB + * characters. + */ + int yy_n_chars; + + /* Whether we "own" the buffer - i.e., we know we created it, + * and can realloc() it to grow it, and should free() it to + * delete it. + */ + int yy_is_our_buffer; + + /* Whether this is an "interactive" input source; if so, and + * if we're using stdio for input, then we want to use getc() + * instead of fread(), to make sure we stop fetching input after + * each newline. + */ + int yy_is_interactive; + + /* Whether we're considered to be at the beginning of a line. + * If so, '^' rules will be active on the next match, otherwise + * not. + */ + int yy_at_bol; + + int yy_bs_lineno; /**< The line count. */ + int yy_bs_column; /**< The column count. */ + + /* Whether to try to fill the input buffer when we reach the + * end of it. + */ + int yy_fill_buffer; + + int yy_buffer_status; + + }; +#endif /* !YY_STRUCT_YY_BUFFER_STATE */ + +void yyrestart (FILE *input_file ,yyscan_t yyscanner ); +void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner ); +YY_BUFFER_STATE yy_create_buffer (FILE *file,int size ,yyscan_t yyscanner ); +void yy_delete_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner ); +void yy_flush_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner ); +void yypush_buffer_state (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner ); +void yypop_buffer_state (yyscan_t yyscanner ); + +YY_BUFFER_STATE yy_scan_buffer (char *base,yy_size_t size ,yyscan_t yyscanner ); +YY_BUFFER_STATE yy_scan_string (yyconst char *yy_str ,yyscan_t yyscanner ); +YY_BUFFER_STATE yy_scan_bytes (yyconst char *bytes,int len ,yyscan_t yyscanner ); + +void *yyalloc (yy_size_t ,yyscan_t yyscanner ); +void *yyrealloc (void *,yy_size_t ,yyscan_t yyscanner ); +void yyfree (void * ,yyscan_t yyscanner ); + +/* Begin user sect3 */ + +#define yywrap(n) 1 +#define YY_SKIP_YYWRAP + +#define yytext_ptr yytext_r + +#ifdef YY_HEADER_EXPORT_START_CONDITIONS +#define INITIAL 0 + +#endif + +#ifndef YY_NO_UNISTD_H +/* Special case for "unistd.h", since it is non-ANSI. We include it way + * down here because we want the user's section 1 to have been scanned first. + * The user has a chance to override it with an option. + */ +#include +#endif + +#ifndef YY_EXTRA_TYPE +#define YY_EXTRA_TYPE void * +#endif + +int yylex_init (yyscan_t* scanner); + +int yylex_init_extra (YY_EXTRA_TYPE user_defined,yyscan_t* scanner); + +/* Accessor methods to globals. + These are made visible to non-reentrant scanners for convenience. */ + +int yylex_destroy (yyscan_t yyscanner ); + +int yyget_debug (yyscan_t yyscanner ); + +void yyset_debug (int debug_flag ,yyscan_t yyscanner ); + +YY_EXTRA_TYPE yyget_extra (yyscan_t yyscanner ); + +void yyset_extra (YY_EXTRA_TYPE user_defined ,yyscan_t yyscanner ); + +FILE *yyget_in (yyscan_t yyscanner ); + +void yyset_in (FILE * in_str ,yyscan_t yyscanner ); + +FILE *yyget_out (yyscan_t yyscanner ); + +void yyset_out (FILE * out_str ,yyscan_t yyscanner ); + +int yyget_leng (yyscan_t yyscanner ); + +char *yyget_text (yyscan_t yyscanner ); + +int yyget_lineno (yyscan_t yyscanner ); + +void yyset_lineno (int line_number ,yyscan_t yyscanner ); + +/* Macros after this point can all be overridden by user definitions in + * section 1. + */ + +#ifndef YY_SKIP_YYWRAP +#ifdef __cplusplus +extern "C" int yywrap (yyscan_t yyscanner ); +#else +extern int yywrap (yyscan_t yyscanner ); +#endif +#endif + +#ifndef yytext_ptr +static void yy_flex_strncpy (char *,yyconst char *,int ,yyscan_t yyscanner); +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen (yyconst char * ,yyscan_t yyscanner); +#endif + +#ifndef YY_NO_INPUT + +#endif + +/* Amount of stuff to slurp up with each read. */ +#ifndef YY_READ_BUF_SIZE +#ifdef __ia64__ +/* On IA-64, the buffer size is 16k, not 8k */ +#define YY_READ_BUF_SIZE 16384 +#else +#define YY_READ_BUF_SIZE 8192 +#endif /* __ia64__ */ +#endif + +/* Number of entries by which start-condition stack grows. */ +#ifndef YY_START_STACK_INCR +#define YY_START_STACK_INCR 25 +#endif + +/* Default declaration of generated scanner - a define so the user can + * easily add parameters. + */ +#ifndef YY_DECL +#define YY_DECL_IS_OURS 1 + +extern int yylex (yyscan_t yyscanner); + +#define YY_DECL int yylex (yyscan_t yyscanner) +#endif /* !YY_DECL */ + +/* yy_get_previous_state - get the state just before the EOB char was reached */ + +#undef YY_NEW_FILE +#undef YY_FLUSH_BUFFER +#undef yy_set_bol +#undef yy_new_buffer +#undef yy_set_interactive +#undef YY_DO_BEFORE_ACTION + +#ifdef YY_DECL_IS_OURS +#undef YY_DECL_IS_OURS +#undef YY_DECL +#endif + +#line 125 "vrscanl.l" + + +#line 348 "vrscanl.h" +#undef yyIN_HEADER +#endif /* yyHEADER_H */ diff --git a/dcmdata/libsrc/vrscanl.l b/dcmdata/libsrc/vrscanl.l new file mode 100644 index 00000000..40512095 --- /dev/null +++ b/dcmdata/libsrc/vrscanl.l @@ -0,0 +1,125 @@ +/* + * + * Copyright (C) 1997-2015, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Hermann Grevemeyer et al. + * + * Purpose: + * These are the regular expressions for the value representations + * + */ + +%option reentrant +/* Avoid compiler warnings about unused functions */ +%option noyywrap nounput noinput + +%{ +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "vrscani.h" +%} + +/* Make this work on windows (we don't need interactivity anyway) */ +%option nointeractive +/* This seems to be a bug: The .c file won't include it, but .h will + * nevertheless. + * %option nounistd + * Our workaround: Define YY_NO_UNISTD_H in vrscani.h and make + * sure that header is included before vrscanl.h. + */ + +default_charset_without_control_chars [\041-\133\135-\176][\040-\133\135-\176]* +charset_without_control_chars [\040-\133\135-\176\240-\377\033]+ +charset_with_control_chars [\040-\176\240-\377\011\012\014\015\033]+ +spaces [ ]* +dt_offset (\-1200)|(\+1400)|(((\-((0[1-9])|(1[0-1])))|(\+((0[1-9])|(1[0-3])))){tm_minute}) +da_year (18[5-9][0-9])|(19[0-9]{2})|(20[0-4][0-9]) +da_year_dub [0-9]{4} +da_month (0[1-9])|(1[0-2]) +da_day (0[1-9])|([1-2][0-9])|(3[0-1]) +tm_hour ([0-1][0-9])|(2[0-3]) +tm_minute [0-5][0-9] +tm_second [0-5][0-9] +is_positive \+?0*(([0-9]{1,9})|(1[0-9]{9})|(20[0-9]{8})|(21[0-3][0-9]{7})|(214[0-6][0-9]{6})|(2147[0-3][0-9]{5})|(21474[0-7][0-9]{4})|(214748[0-2][0-9]{3})|(2147483[0-5][0-9]{2})|(21474836[0-3][0-9])|(214748364[0-7])) +is_negative \-0*(([0-9]{1,9})|(1[0-9]{9})|(20[0-9]{8})|(21[0-3][0-9]{7})|(214[0-6][0-9]{6})|(2147[0-3][0-9]{5})|(21474[0-7][0-9]{4})|(214748[0-2][0-9]{3})|(2147483[0-5][0-9]{2})|(21474836[0-3][0-9])|(214748364[0-8])) +pn_chars [\040-\074\076-\133\135\137-\176\240-\377\033]+ +ur_chars [\041-\133\135-\176]+ +pn_component_group {pn_chars}?(\^{pn_chars}?(\^{pn_chars}?(\^{pn_chars}?(\^{pn_chars}?)?)?)?)? + +normalized-as [0-9]{3}[DWMY] +normalized-da {da_year}{da_month}{da_day} +normalized-da-old {da_year_dub}\.{da_month}\.{da_day} +normalized-da-dub {da_year_dub}{da_month}{da_day} +normalized-tm {tm_hour}({tm_minute}({tm_second}(\.[0-9]{1,6})?)?)? +normalized-tm-old {tm_hour}:{tm_minute}:{tm_second}\.[0-9]{6} +normalized-ds ([\-\+]?[0-9]*[\.]?[0-9]+)|([\-\+]?[0-9]+[\.]?[0-9]*)|([\-\+]?[0-9]*[\.]?[0-9]+[Ee][\+\-]?[0-9]+)|([\-\+]?[0-9]+[\.]?[0-9]*[Ee][\+\-]?[0-9]+) +normalized-dt {da_year}({da_month}({da_day}({normalized-tm}{dt_offset}?)?)?)? +normalized-dt-dub {da_year_dub}({da_month}({da_day}({normalized-tm}{dt_offset}?)?)?)? +normalized-is {is_positive}|{is_negative} +normalized-ui (([0-9]\.)|([1-9][0-9]+\.))*(([0-9])|([1-9][0-9]+)) +normalized-cs [0-9A-Z _]+ +normalized-pn {pn_component_group}(\={pn_component_group}(\={pn_component_group})?)? +normalized-pn-old {pn_chars} +normalized-lo-sh {charset_without_control_chars} +normalized-ae {default_charset_without_control_chars} +normalized-lt-st-ut {charset_with_control_chars} +normalized-ur {ur_chars} +normalized-uc {charset_without_control_chars} + +as {normalized-as} +da {normalized-da} +da-old {normalized-da-old} +da-dub {normalized-da-dub} +tm {normalized-tm}{spaces} +tm-old {normalized-tm-old}{spaces} +ds {spaces}{normalized-ds}{spaces} +dt {normalized-dt}{spaces} +dt-dub {normalized-dt-dub}{spaces} +is {spaces}{normalized-is}{spaces} +ui {normalized-ui} +cs {spaces}{normalized-cs}{spaces} +pn {normalized-pn}{spaces} +pn-old {normalized-pn-old}{spaces} +lo-sh {spaces}{normalized-lo-sh}{spaces} +ae {spaces}{normalized-ae}{spaces} +lt-st-ut {normalized-lt-st-ut}{spaces} +ur {normalized-ur}{spaces} +uc {normalized-uc}{spaces} + +%% + +as{as}?(\\{as}?)* {return 1; /* AS */} +da{da}?(\\{da}?)* {return 2; /* DA */} +da{da-old}?(\\{da-old}?)* {return 3; /* OLD_DA */} +da{da-dub}?(\\{da-dub}?)* {return 17; /* dubious DA */} +tm{tm}?(\\{tm}?)* {return 4; /* TM */} +tm{tm-old}?(\\{tm-old}?)* {return 5; /* OLD_TM */} +ds{ds}?(\\{ds}?)* {return 6; /* DS */} +dt{dt}?(\\{dt}?)* {return 7; /* DT */} +dt{dt-dub}?(\\{dt-dub}?)* {return 18; /* dubious DT */} +is{is}?(\\{is}?)* {return 8; /* IS */} +ui{ui}?(\\{ui}?)* {return 9; /* UI */} +cs{cs}?(\\{cs}?)* {return 10; /* CS */} +pn{pn}?(\\{pn}?)* {return 11; /* PN */} +oldpn{pn-old}?(\\{pn-old}?)* {return 15; /* OLD_PN: not used any longer within DCMTK */} +lo{lo-sh}?(\\{lo-sh}?)* {return 12; /* LO | SH */} +ae{ae}?(\\{ae}?)* {return 13; /* AE */} +lt{lt-st-ut} {return 14; /* LT | ST | UT */} +ur{ur} {return 19; /* UR */} +uc{uc} {return 20; /* UC */} + /* . doesn't match \n, this needs a special case! */ +\n | +. {return 16; /* UNKNOWN */;} + +%% diff --git a/dcmdata/tests/CMakeLists.txt b/dcmdata/tests/CMakeLists.txt new file mode 100644 index 00000000..928940bd --- /dev/null +++ b/dcmdata/tests/CMakeLists.txt @@ -0,0 +1,8 @@ +# declare executables +DCMTK_ADD_EXECUTABLE(dcmdata_tests tests tpread ti2dbmp tchval tpath tvrdatim telemlen tparser tdict tvrds tvrfd tvrui tstrval tspchrs tvrpn tparent tfilter tvrcomp) + +# make sure executables are linked to the corresponding libraries +DCMTK_TARGET_LINK_MODULES(dcmdata_tests i2d dcmdata oflog ofstd) + +# This macro parses tests.cc and registers all tests +DCMTK_ADD_TESTS(dcmdata) diff --git a/dcmdata/tests/Makefile.dep b/dcmdata/tests/Makefile.dep new file mode 100644 index 00000000..a3b461ac --- /dev/null +++ b/dcmdata/tests/Makefile.dep @@ -0,0 +1,1082 @@ +tchval.o: tchval.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../ofstd/include/dcmtk/ofstd/oftest.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../include/dcmtk/dcmdata/dcuid.h ../include/dcmtk/dcmdata/dcdefine.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../include/dcmtk/dcmdata/dctk.h ../include/dcmtk/dcmdata/dctypes.h \ + ../include/dcmtk/dcmdata/dcswap.h ../include/dcmtk/dcmdata/dcerror.h \ + ../include/dcmtk/dcmdata/dcxfer.h ../include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../include/dcmtk/dcmdata/dcistrma.h ../include/dcmtk/dcmdata/dcostrma.h \ + ../include/dcmtk/dcmdata/dctagkey.h ../include/dcmtk/dcmdata/dctag.h \ + ../include/dcmtk/dcmdata/dcdicent.h ../include/dcmtk/dcmdata/dchashdi.h \ + ../include/dcmtk/dcmdata/dcdict.h ../include/dcmtk/dcmdata/dcdeftag.h \ + ../include/dcmtk/dcmdata/dcobject.h ../include/dcmtk/dcmdata/dcstack.h \ + ../include/dcmtk/dcmdata/dcelem.h ../include/dcmtk/dcmdata/dcitem.h \ + ../include/dcmtk/dcmdata/dclist.h ../include/dcmtk/dcmdata/dcpcache.h \ + ../include/dcmtk/dcmdata/dcmetinf.h ../include/dcmtk/dcmdata/dcdatset.h \ + ../include/dcmtk/dcmdata/dcsequen.h ../include/dcmtk/dcmdata/dcfilefo.h \ + ../include/dcmtk/dcmdata/dcdicdir.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../include/dcmtk/dcmdata/dcdirrec.h ../include/dcmtk/dcmdata/dcvrulup.h \ + ../include/dcmtk/dcmdata/dcvrul.h ../include/dcmtk/dcmdata/dcpixseq.h \ + ../include/dcmtk/dcmdata/dcofsetl.h ../include/dcmtk/dcmdata/dcbytstr.h \ + ../include/dcmtk/dcmdata/dcvrae.h ../include/dcmtk/dcmdata/dcvras.h \ + ../include/dcmtk/dcmdata/dcvrcs.h ../include/dcmtk/dcmdata/dcvrda.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../include/dcmtk/dcmdata/dcvrds.h ../include/dcmtk/dcmdata/dcvrdt.h \ + ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../include/dcmtk/dcmdata/dcvris.h ../include/dcmtk/dcmdata/dcvrtm.h \ + ../include/dcmtk/dcmdata/dcvrui.h ../include/dcmtk/dcmdata/dcvrur.h \ + ../include/dcmtk/dcmdata/dcchrstr.h ../include/dcmtk/dcmdata/dcvrlo.h \ + ../include/dcmtk/dcmdata/dcvrlt.h ../include/dcmtk/dcmdata/dcvrpn.h \ + ../include/dcmtk/dcmdata/dcvrsh.h ../include/dcmtk/dcmdata/dcvrst.h \ + ../include/dcmtk/dcmdata/dcvruc.h ../include/dcmtk/dcmdata/dcvrut.h \ + ../include/dcmtk/dcmdata/dcvrobow.h ../include/dcmtk/dcmdata/dcpixel.h \ + ../include/dcmtk/dcmdata/dcvrpobw.h ../include/dcmtk/dcmdata/dcovlay.h \ + ../include/dcmtk/dcmdata/dcvrat.h ../include/dcmtk/dcmdata/dcvrss.h \ + ../include/dcmtk/dcmdata/dcvrus.h ../include/dcmtk/dcmdata/dcvrsl.h \ + ../include/dcmtk/dcmdata/dcvrfl.h ../include/dcmtk/dcmdata/dcvrfd.h \ + ../include/dcmtk/dcmdata/dcvrof.h ../include/dcmtk/dcmdata/dcvrod.h \ + ../include/dcmtk/dcmdata/cmdlnarg.h ../include/dcmtk/dcmdata/vrscan.h \ + ../../ofstd/include/dcmtk/ofstd/ofbmanip.h +tdict.o: tdict.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../ofstd/include/dcmtk/ofstd/oftest.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../include/dcmtk/dcmdata/dcuid.h ../include/dcmtk/dcmdata/dcdefine.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../include/dcmtk/dcmdata/dcdict.h ../include/dcmtk/dcmdata/dchashdi.h \ + ../include/dcmtk/dcmdata/dctagkey.h ../include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../include/dcmtk/dcmdata/dcdicent.h +telemlen.o: telemlen.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../ofstd/include/dcmtk/ofstd/oftest.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../include/dcmtk/dcmdata/dcuid.h ../include/dcmtk/dcmdata/dcdefine.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../include/dcmtk/dcmdata/dctk.h ../include/dcmtk/dcmdata/dctypes.h \ + ../include/dcmtk/dcmdata/dcswap.h ../include/dcmtk/dcmdata/dcerror.h \ + ../include/dcmtk/dcmdata/dcxfer.h ../include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../include/dcmtk/dcmdata/dcistrma.h ../include/dcmtk/dcmdata/dcostrma.h \ + ../include/dcmtk/dcmdata/dctagkey.h ../include/dcmtk/dcmdata/dctag.h \ + ../include/dcmtk/dcmdata/dcdicent.h ../include/dcmtk/dcmdata/dchashdi.h \ + ../include/dcmtk/dcmdata/dcdict.h ../include/dcmtk/dcmdata/dcdeftag.h \ + ../include/dcmtk/dcmdata/dcobject.h ../include/dcmtk/dcmdata/dcstack.h \ + ../include/dcmtk/dcmdata/dcelem.h ../include/dcmtk/dcmdata/dcitem.h \ + ../include/dcmtk/dcmdata/dclist.h ../include/dcmtk/dcmdata/dcpcache.h \ + ../include/dcmtk/dcmdata/dcmetinf.h ../include/dcmtk/dcmdata/dcdatset.h \ + ../include/dcmtk/dcmdata/dcsequen.h ../include/dcmtk/dcmdata/dcfilefo.h \ + ../include/dcmtk/dcmdata/dcdicdir.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../include/dcmtk/dcmdata/dcdirrec.h ../include/dcmtk/dcmdata/dcvrulup.h \ + ../include/dcmtk/dcmdata/dcvrul.h ../include/dcmtk/dcmdata/dcpixseq.h \ + ../include/dcmtk/dcmdata/dcofsetl.h ../include/dcmtk/dcmdata/dcbytstr.h \ + ../include/dcmtk/dcmdata/dcvrae.h ../include/dcmtk/dcmdata/dcvras.h \ + ../include/dcmtk/dcmdata/dcvrcs.h ../include/dcmtk/dcmdata/dcvrda.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../include/dcmtk/dcmdata/dcvrds.h ../include/dcmtk/dcmdata/dcvrdt.h \ + ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../include/dcmtk/dcmdata/dcvris.h ../include/dcmtk/dcmdata/dcvrtm.h \ + ../include/dcmtk/dcmdata/dcvrui.h ../include/dcmtk/dcmdata/dcvrur.h \ + ../include/dcmtk/dcmdata/dcchrstr.h ../include/dcmtk/dcmdata/dcvrlo.h \ + ../include/dcmtk/dcmdata/dcvrlt.h ../include/dcmtk/dcmdata/dcvrpn.h \ + ../include/dcmtk/dcmdata/dcvrsh.h ../include/dcmtk/dcmdata/dcvrst.h \ + ../include/dcmtk/dcmdata/dcvruc.h ../include/dcmtk/dcmdata/dcvrut.h \ + ../include/dcmtk/dcmdata/dcvrobow.h ../include/dcmtk/dcmdata/dcpixel.h \ + ../include/dcmtk/dcmdata/dcvrpobw.h ../include/dcmtk/dcmdata/dcovlay.h \ + ../include/dcmtk/dcmdata/dcvrat.h ../include/dcmtk/dcmdata/dcvrss.h \ + ../include/dcmtk/dcmdata/dcvrus.h ../include/dcmtk/dcmdata/dcvrsl.h \ + ../include/dcmtk/dcmdata/dcvrfl.h ../include/dcmtk/dcmdata/dcvrfd.h \ + ../include/dcmtk/dcmdata/dcvrof.h ../include/dcmtk/dcmdata/dcvrod.h \ + ../include/dcmtk/dcmdata/cmdlnarg.h ../include/dcmtk/dcmdata/dcpxitem.h \ + ../include/dcmtk/dcmdata/dcostrmb.h +tests.o: tests.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../ofstd/include/dcmtk/ofstd/oftest.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../include/dcmtk/dcmdata/dcuid.h ../include/dcmtk/dcmdata/dcdefine.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h +tfilter.o: tfilter.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../ofstd/include/dcmtk/ofstd/oftest.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../include/dcmtk/dcmdata/dcuid.h ../include/dcmtk/dcmdata/dcdefine.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../include/dcmtk/dcmdata/dcdeftag.h ../include/dcmtk/dcmdata/dctagkey.h \ + ../include/dcmtk/dcmdata/dcfilter.h \ + ../../ofstd/include/dcmtk/ofstd/ofalgo.h \ + ../include/dcmtk/dcmdata/dcfilefo.h ../include/dcmtk/dcmdata/dcsequen.h \ + ../include/dcmtk/dcmdata/dcelem.h ../include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../include/dcmtk/dcmdata/dcerror.h ../include/dcmtk/dcmdata/dcxfer.h \ + ../include/dcmtk/dcmdata/dctypes.h ../include/dcmtk/dcmdata/dcvr.h \ + ../include/dcmtk/dcmdata/dctag.h ../include/dcmtk/dcmdata/dcstack.h \ + ../include/dcmtk/dcmdata/dclist.h ../include/dcmtk/dcmdata/dcdatset.h \ + ../include/dcmtk/dcmdata/dcitem.h ../include/dcmtk/dcmdata/dcpcache.h +ti2dbmp.o: ti2dbmp.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../ofstd/include/dcmtk/ofstd/oftest.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../include/dcmtk/dcmdata/dcuid.h ../include/dcmtk/dcmdata/dcdefine.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../include/dcmtk/dcmdata/libi2d/i2dbmps.h \ + ../include/dcmtk/dcmdata/libi2d/i2dimgs.h \ + ../include/dcmtk/dcmdata/dcxfer.h ../include/dcmtk/dcmdata/dctypes.h \ + ../include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../include/dcmtk/dcmdata/libi2d/i2define.h +tparent.o: tparent.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../ofstd/include/dcmtk/ofstd/oftest.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../include/dcmtk/dcmdata/dcuid.h ../include/dcmtk/dcmdata/dcdefine.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../include/dcmtk/dcmdata/dctk.h ../include/dcmtk/dcmdata/dctypes.h \ + ../include/dcmtk/dcmdata/dcswap.h ../include/dcmtk/dcmdata/dcerror.h \ + ../include/dcmtk/dcmdata/dcxfer.h ../include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../include/dcmtk/dcmdata/dcistrma.h ../include/dcmtk/dcmdata/dcostrma.h \ + ../include/dcmtk/dcmdata/dctagkey.h ../include/dcmtk/dcmdata/dctag.h \ + ../include/dcmtk/dcmdata/dcdicent.h ../include/dcmtk/dcmdata/dchashdi.h \ + ../include/dcmtk/dcmdata/dcdict.h ../include/dcmtk/dcmdata/dcdeftag.h \ + ../include/dcmtk/dcmdata/dcobject.h ../include/dcmtk/dcmdata/dcstack.h \ + ../include/dcmtk/dcmdata/dcelem.h ../include/dcmtk/dcmdata/dcitem.h \ + ../include/dcmtk/dcmdata/dclist.h ../include/dcmtk/dcmdata/dcpcache.h \ + ../include/dcmtk/dcmdata/dcmetinf.h ../include/dcmtk/dcmdata/dcdatset.h \ + ../include/dcmtk/dcmdata/dcsequen.h ../include/dcmtk/dcmdata/dcfilefo.h \ + ../include/dcmtk/dcmdata/dcdicdir.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../include/dcmtk/dcmdata/dcdirrec.h ../include/dcmtk/dcmdata/dcvrulup.h \ + ../include/dcmtk/dcmdata/dcvrul.h ../include/dcmtk/dcmdata/dcpixseq.h \ + ../include/dcmtk/dcmdata/dcofsetl.h ../include/dcmtk/dcmdata/dcbytstr.h \ + ../include/dcmtk/dcmdata/dcvrae.h ../include/dcmtk/dcmdata/dcvras.h \ + ../include/dcmtk/dcmdata/dcvrcs.h ../include/dcmtk/dcmdata/dcvrda.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../include/dcmtk/dcmdata/dcvrds.h ../include/dcmtk/dcmdata/dcvrdt.h \ + ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../include/dcmtk/dcmdata/dcvris.h ../include/dcmtk/dcmdata/dcvrtm.h \ + ../include/dcmtk/dcmdata/dcvrui.h ../include/dcmtk/dcmdata/dcvrur.h \ + ../include/dcmtk/dcmdata/dcchrstr.h ../include/dcmtk/dcmdata/dcvrlo.h \ + ../include/dcmtk/dcmdata/dcvrlt.h ../include/dcmtk/dcmdata/dcvrpn.h \ + ../include/dcmtk/dcmdata/dcvrsh.h ../include/dcmtk/dcmdata/dcvrst.h \ + ../include/dcmtk/dcmdata/dcvruc.h ../include/dcmtk/dcmdata/dcvrut.h \ + ../include/dcmtk/dcmdata/dcvrobow.h ../include/dcmtk/dcmdata/dcpixel.h \ + ../include/dcmtk/dcmdata/dcvrpobw.h ../include/dcmtk/dcmdata/dcovlay.h \ + ../include/dcmtk/dcmdata/dcvrat.h ../include/dcmtk/dcmdata/dcvrss.h \ + ../include/dcmtk/dcmdata/dcvrus.h ../include/dcmtk/dcmdata/dcvrsl.h \ + ../include/dcmtk/dcmdata/dcvrfl.h ../include/dcmtk/dcmdata/dcvrfd.h \ + ../include/dcmtk/dcmdata/dcvrof.h ../include/dcmtk/dcmdata/dcvrod.h \ + ../include/dcmtk/dcmdata/cmdlnarg.h dctmacro.h \ + ../include/dcmtk/dcmdata/dcistrmb.h ../include/dcmtk/dcmdata/dcostrmb.h +tparser.o: tparser.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../ofstd/include/dcmtk/ofstd/oftest.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../include/dcmtk/dcmdata/dcuid.h ../include/dcmtk/dcmdata/dcdefine.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/oftempf.h \ + ../include/dcmtk/dcmdata/dctk.h ../include/dcmtk/dcmdata/dctypes.h \ + ../include/dcmtk/dcmdata/dcswap.h ../include/dcmtk/dcmdata/dcerror.h \ + ../include/dcmtk/dcmdata/dcxfer.h ../include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../include/dcmtk/dcmdata/dcistrma.h ../include/dcmtk/dcmdata/dcostrma.h \ + ../include/dcmtk/dcmdata/dctagkey.h ../include/dcmtk/dcmdata/dctag.h \ + ../include/dcmtk/dcmdata/dcdicent.h ../include/dcmtk/dcmdata/dchashdi.h \ + ../include/dcmtk/dcmdata/dcdict.h ../include/dcmtk/dcmdata/dcdeftag.h \ + ../include/dcmtk/dcmdata/dcobject.h ../include/dcmtk/dcmdata/dcstack.h \ + ../include/dcmtk/dcmdata/dcelem.h ../include/dcmtk/dcmdata/dcitem.h \ + ../include/dcmtk/dcmdata/dclist.h ../include/dcmtk/dcmdata/dcpcache.h \ + ../include/dcmtk/dcmdata/dcmetinf.h ../include/dcmtk/dcmdata/dcdatset.h \ + ../include/dcmtk/dcmdata/dcsequen.h ../include/dcmtk/dcmdata/dcfilefo.h \ + ../include/dcmtk/dcmdata/dcdicdir.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../include/dcmtk/dcmdata/dcdirrec.h ../include/dcmtk/dcmdata/dcvrulup.h \ + ../include/dcmtk/dcmdata/dcvrul.h ../include/dcmtk/dcmdata/dcpixseq.h \ + ../include/dcmtk/dcmdata/dcofsetl.h ../include/dcmtk/dcmdata/dcbytstr.h \ + ../include/dcmtk/dcmdata/dcvrae.h ../include/dcmtk/dcmdata/dcvras.h \ + ../include/dcmtk/dcmdata/dcvrcs.h ../include/dcmtk/dcmdata/dcvrda.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../include/dcmtk/dcmdata/dcvrds.h ../include/dcmtk/dcmdata/dcvrdt.h \ + ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../include/dcmtk/dcmdata/dcvris.h ../include/dcmtk/dcmdata/dcvrtm.h \ + ../include/dcmtk/dcmdata/dcvrui.h ../include/dcmtk/dcmdata/dcvrur.h \ + ../include/dcmtk/dcmdata/dcchrstr.h ../include/dcmtk/dcmdata/dcvrlo.h \ + ../include/dcmtk/dcmdata/dcvrlt.h ../include/dcmtk/dcmdata/dcvrpn.h \ + ../include/dcmtk/dcmdata/dcvrsh.h ../include/dcmtk/dcmdata/dcvrst.h \ + ../include/dcmtk/dcmdata/dcvruc.h ../include/dcmtk/dcmdata/dcvrut.h \ + ../include/dcmtk/dcmdata/dcvrobow.h ../include/dcmtk/dcmdata/dcpixel.h \ + ../include/dcmtk/dcmdata/dcvrpobw.h ../include/dcmtk/dcmdata/dcovlay.h \ + ../include/dcmtk/dcmdata/dcvrat.h ../include/dcmtk/dcmdata/dcvrss.h \ + ../include/dcmtk/dcmdata/dcvrus.h ../include/dcmtk/dcmdata/dcvrsl.h \ + ../include/dcmtk/dcmdata/dcvrfl.h ../include/dcmtk/dcmdata/dcvrfd.h \ + ../include/dcmtk/dcmdata/dcvrof.h ../include/dcmtk/dcmdata/dcvrod.h \ + ../include/dcmtk/dcmdata/cmdlnarg.h ../include/dcmtk/dcmdata/dcpxitem.h \ + ../include/dcmtk/dcmdata/dcistrmb.h ../include/dcmtk/dcmdata/dcostrmb.h \ + dctmacro.h +tpath.o: tpath.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../ofstd/include/dcmtk/ofstd/oftest.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../include/dcmtk/dcmdata/dcuid.h ../include/dcmtk/dcmdata/dcdefine.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../include/dcmtk/dcmdata/dctk.h ../include/dcmtk/dcmdata/dctypes.h \ + ../include/dcmtk/dcmdata/dcswap.h ../include/dcmtk/dcmdata/dcerror.h \ + ../include/dcmtk/dcmdata/dcxfer.h ../include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../include/dcmtk/dcmdata/dcistrma.h ../include/dcmtk/dcmdata/dcostrma.h \ + ../include/dcmtk/dcmdata/dctagkey.h ../include/dcmtk/dcmdata/dctag.h \ + ../include/dcmtk/dcmdata/dcdicent.h ../include/dcmtk/dcmdata/dchashdi.h \ + ../include/dcmtk/dcmdata/dcdict.h ../include/dcmtk/dcmdata/dcdeftag.h \ + ../include/dcmtk/dcmdata/dcobject.h ../include/dcmtk/dcmdata/dcstack.h \ + ../include/dcmtk/dcmdata/dcelem.h ../include/dcmtk/dcmdata/dcitem.h \ + ../include/dcmtk/dcmdata/dclist.h ../include/dcmtk/dcmdata/dcpcache.h \ + ../include/dcmtk/dcmdata/dcmetinf.h ../include/dcmtk/dcmdata/dcdatset.h \ + ../include/dcmtk/dcmdata/dcsequen.h ../include/dcmtk/dcmdata/dcfilefo.h \ + ../include/dcmtk/dcmdata/dcdicdir.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../include/dcmtk/dcmdata/dcdirrec.h ../include/dcmtk/dcmdata/dcvrulup.h \ + ../include/dcmtk/dcmdata/dcvrul.h ../include/dcmtk/dcmdata/dcpixseq.h \ + ../include/dcmtk/dcmdata/dcofsetl.h ../include/dcmtk/dcmdata/dcbytstr.h \ + ../include/dcmtk/dcmdata/dcvrae.h ../include/dcmtk/dcmdata/dcvras.h \ + ../include/dcmtk/dcmdata/dcvrcs.h ../include/dcmtk/dcmdata/dcvrda.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../include/dcmtk/dcmdata/dcvrds.h ../include/dcmtk/dcmdata/dcvrdt.h \ + ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../include/dcmtk/dcmdata/dcvris.h ../include/dcmtk/dcmdata/dcvrtm.h \ + ../include/dcmtk/dcmdata/dcvrui.h ../include/dcmtk/dcmdata/dcvrur.h \ + ../include/dcmtk/dcmdata/dcchrstr.h ../include/dcmtk/dcmdata/dcvrlo.h \ + ../include/dcmtk/dcmdata/dcvrlt.h ../include/dcmtk/dcmdata/dcvrpn.h \ + ../include/dcmtk/dcmdata/dcvrsh.h ../include/dcmtk/dcmdata/dcvrst.h \ + ../include/dcmtk/dcmdata/dcvruc.h ../include/dcmtk/dcmdata/dcvrut.h \ + ../include/dcmtk/dcmdata/dcvrobow.h ../include/dcmtk/dcmdata/dcpixel.h \ + ../include/dcmtk/dcmdata/dcvrpobw.h ../include/dcmtk/dcmdata/dcovlay.h \ + ../include/dcmtk/dcmdata/dcvrat.h ../include/dcmtk/dcmdata/dcvrss.h \ + ../include/dcmtk/dcmdata/dcvrus.h ../include/dcmtk/dcmdata/dcvrsl.h \ + ../include/dcmtk/dcmdata/dcvrfl.h ../include/dcmtk/dcmdata/dcvrfd.h \ + ../include/dcmtk/dcmdata/dcvrof.h ../include/dcmtk/dcmdata/dcvrod.h \ + ../include/dcmtk/dcmdata/cmdlnarg.h ../include/dcmtk/dcmdata/dcpath.h +tpread.o: tpread.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/oftest.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../include/dcmtk/dcmdata/dcuid.h ../include/dcmtk/dcmdata/dcdefine.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../include/dcmtk/dcmdata/dctk.h ../include/dcmtk/dcmdata/dctypes.h \ + ../include/dcmtk/dcmdata/dcswap.h ../include/dcmtk/dcmdata/dcerror.h \ + ../include/dcmtk/dcmdata/dcxfer.h ../include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../include/dcmtk/dcmdata/dcistrma.h ../include/dcmtk/dcmdata/dcostrma.h \ + ../include/dcmtk/dcmdata/dctagkey.h ../include/dcmtk/dcmdata/dctag.h \ + ../include/dcmtk/dcmdata/dcdicent.h ../include/dcmtk/dcmdata/dchashdi.h \ + ../include/dcmtk/dcmdata/dcdict.h ../include/dcmtk/dcmdata/dcdeftag.h \ + ../include/dcmtk/dcmdata/dcobject.h ../include/dcmtk/dcmdata/dcstack.h \ + ../include/dcmtk/dcmdata/dcelem.h ../include/dcmtk/dcmdata/dcitem.h \ + ../include/dcmtk/dcmdata/dclist.h ../include/dcmtk/dcmdata/dcpcache.h \ + ../include/dcmtk/dcmdata/dcmetinf.h ../include/dcmtk/dcmdata/dcdatset.h \ + ../include/dcmtk/dcmdata/dcsequen.h ../include/dcmtk/dcmdata/dcfilefo.h \ + ../include/dcmtk/dcmdata/dcdicdir.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../include/dcmtk/dcmdata/dcdirrec.h ../include/dcmtk/dcmdata/dcvrulup.h \ + ../include/dcmtk/dcmdata/dcvrul.h ../include/dcmtk/dcmdata/dcpixseq.h \ + ../include/dcmtk/dcmdata/dcofsetl.h ../include/dcmtk/dcmdata/dcbytstr.h \ + ../include/dcmtk/dcmdata/dcvrae.h ../include/dcmtk/dcmdata/dcvras.h \ + ../include/dcmtk/dcmdata/dcvrcs.h ../include/dcmtk/dcmdata/dcvrda.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../include/dcmtk/dcmdata/dcvrds.h ../include/dcmtk/dcmdata/dcvrdt.h \ + ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../include/dcmtk/dcmdata/dcvris.h ../include/dcmtk/dcmdata/dcvrtm.h \ + ../include/dcmtk/dcmdata/dcvrui.h ../include/dcmtk/dcmdata/dcvrur.h \ + ../include/dcmtk/dcmdata/dcchrstr.h ../include/dcmtk/dcmdata/dcvrlo.h \ + ../include/dcmtk/dcmdata/dcvrlt.h ../include/dcmtk/dcmdata/dcvrpn.h \ + ../include/dcmtk/dcmdata/dcvrsh.h ../include/dcmtk/dcmdata/dcvrst.h \ + ../include/dcmtk/dcmdata/dcvruc.h ../include/dcmtk/dcmdata/dcvrut.h \ + ../include/dcmtk/dcmdata/dcvrobow.h ../include/dcmtk/dcmdata/dcpixel.h \ + ../include/dcmtk/dcmdata/dcvrpobw.h ../include/dcmtk/dcmdata/dcovlay.h \ + ../include/dcmtk/dcmdata/dcvrat.h ../include/dcmtk/dcmdata/dcvrss.h \ + ../include/dcmtk/dcmdata/dcvrus.h ../include/dcmtk/dcmdata/dcvrsl.h \ + ../include/dcmtk/dcmdata/dcvrfl.h ../include/dcmtk/dcmdata/dcvrfd.h \ + ../include/dcmtk/dcmdata/dcvrof.h ../include/dcmtk/dcmdata/dcvrod.h \ + ../include/dcmtk/dcmdata/cmdlnarg.h ../include/dcmtk/dcmdata/dcostrmz.h \ + ../include/dcmtk/dcmdata/dcistrmz.h ../include/dcmtk/dcmdata/dcfcache.h +tspchrs.o: tspchrs.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../ofstd/include/dcmtk/ofstd/oftest.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../include/dcmtk/dcmdata/dcuid.h ../include/dcmtk/dcmdata/dcdefine.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../include/dcmtk/dcmdata/dcspchrs.h \ + ../../ofstd/include/dcmtk/ofstd/ofchrenc.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../include/dcmtk/dcmdata/dctypes.h +tstrval.o: tstrval.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../ofstd/include/dcmtk/ofstd/oftest.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../include/dcmtk/dcmdata/dcuid.h ../include/dcmtk/dcmdata/dcdefine.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../include/dcmtk/dcmdata/dcelem.h ../include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../include/dcmtk/dcmdata/dcerror.h ../include/dcmtk/dcmdata/dcxfer.h \ + ../include/dcmtk/dcmdata/dctypes.h ../include/dcmtk/dcmdata/dcvr.h \ + ../include/dcmtk/dcmdata/dctag.h ../include/dcmtk/dcmdata/dctagkey.h \ + ../include/dcmtk/dcmdata/dcstack.h +tvrcomp.o: tvrcomp.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../ofstd/include/dcmtk/ofstd/oftest.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../include/dcmtk/dcmdata/dcvras.h ../include/dcmtk/dcmdata/dcbytstr.h \ + ../include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../include/dcmtk/dcmdata/dcdefine.h ../include/dcmtk/dcmdata/dcelem.h \ + ../include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../include/dcmtk/dcmdata/dcerror.h ../include/dcmtk/dcmdata/dcxfer.h \ + ../include/dcmtk/dcmdata/dcvr.h ../include/dcmtk/dcmdata/dctag.h \ + ../include/dcmtk/dcmdata/dctagkey.h ../include/dcmtk/dcmdata/dcstack.h \ + ../include/dcmtk/dcmdata/dcvrae.h ../include/dcmtk/dcmdata/dcchrstr.h \ + ../include/dcmtk/dcmdata/dcvrlo.h ../include/dcmtk/dcmdata/dcvrlt.h \ + ../include/dcmtk/dcmdata/dcvrpn.h ../include/dcmtk/dcmdata/dcvrst.h \ + ../include/dcmtk/dcmdata/dcvrut.h ../include/dcmtk/dcmdata/dcvrcs.h \ + ../include/dcmtk/dcmdata/dcvrda.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../include/dcmtk/dcmdata/dcvrdt.h \ + ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../include/dcmtk/dcmdata/dcvrds.h ../include/dcmtk/dcmdata/dcvris.h \ + ../include/dcmtk/dcmdata/dcvrtm.h ../include/dcmtk/dcmdata/dcvrui.h \ + ../include/dcmtk/dcmdata/dcitem.h ../include/dcmtk/dcmdata/dclist.h \ + ../include/dcmtk/dcmdata/dcpcache.h ../include/dcmtk/dcmdata/dcsequen.h \ + ../include/dcmtk/dcmdata/dcvrat.h ../include/dcmtk/dcmdata/dcvrfd.h \ + ../include/dcmtk/dcmdata/dcvrfl.h ../include/dcmtk/dcmdata/dcvrobow.h \ + ../include/dcmtk/dcmdata/dcvrsl.h ../include/dcmtk/dcmdata/dcvrss.h \ + ../include/dcmtk/dcmdata/dcvrul.h ../include/dcmtk/dcmdata/dcvrus.h \ + ../include/dcmtk/dcmdata/dcdeftag.h ../include/dcmtk/dcmdata/dcpxitem.h \ + ../include/dcmtk/dcmdata/dcofsetl.h ../include/dcmtk/dcmdata/dcvrpobw.h \ + ../include/dcmtk/dcmdata/dcovlay.h ../include/dcmtk/dcmdata/dcpixel.h +tvrdatim.o: tvrdatim.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../ofstd/include/dcmtk/ofstd/oftest.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../include/dcmtk/dcmdata/dcuid.h ../include/dcmtk/dcmdata/dcdefine.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../include/dcmtk/dcmdata/dcvrda.h ../include/dcmtk/dcmdata/dcbytstr.h \ + ../include/dcmtk/dcmdata/dctypes.h ../include/dcmtk/dcmdata/dcelem.h \ + ../include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../include/dcmtk/dcmdata/dcerror.h ../include/dcmtk/dcmdata/dcxfer.h \ + ../include/dcmtk/dcmdata/dcvr.h ../include/dcmtk/dcmdata/dctag.h \ + ../include/dcmtk/dcmdata/dctagkey.h ../include/dcmtk/dcmdata/dcstack.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../include/dcmtk/dcmdata/dcvrtm.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../include/dcmtk/dcmdata/dcvrdt.h \ + ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../include/dcmtk/dcmdata/dcdeftag.h +tvrds.o: tvrds.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../ofstd/include/dcmtk/ofstd/oftest.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../include/dcmtk/dcmdata/dcuid.h ../include/dcmtk/dcmdata/dcdefine.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../include/dcmtk/dcmdata/dcvrds.h ../include/dcmtk/dcmdata/dcbytstr.h \ + ../include/dcmtk/dcmdata/dctypes.h ../include/dcmtk/dcmdata/dcelem.h \ + ../include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../include/dcmtk/dcmdata/dcerror.h ../include/dcmtk/dcmdata/dcxfer.h \ + ../include/dcmtk/dcmdata/dcvr.h ../include/dcmtk/dcmdata/dctag.h \ + ../include/dcmtk/dcmdata/dctagkey.h ../include/dcmtk/dcmdata/dcstack.h \ + ../include/dcmtk/dcmdata/dcdeftag.h +tvrfd.o: tvrfd.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../ofstd/include/dcmtk/ofstd/oftest.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../include/dcmtk/dcmdata/dcuid.h ../include/dcmtk/dcmdata/dcdefine.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../include/dcmtk/dcmdata/dcvrfd.h ../include/dcmtk/dcmdata/dcelem.h \ + ../include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../include/dcmtk/dcmdata/dcerror.h ../include/dcmtk/dcmdata/dcxfer.h \ + ../include/dcmtk/dcmdata/dctypes.h ../include/dcmtk/dcmdata/dcvr.h \ + ../include/dcmtk/dcmdata/dctag.h ../include/dcmtk/dcmdata/dctagkey.h \ + ../include/dcmtk/dcmdata/dcstack.h ../include/dcmtk/dcmdata/dcdeftag.h +tvrpn.o: tvrpn.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../ofstd/include/dcmtk/ofstd/oftest.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../include/dcmtk/dcmdata/dcuid.h ../include/dcmtk/dcmdata/dcdefine.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../include/dcmtk/dcmdata/dcvrpn.h ../include/dcmtk/dcmdata/dcchrstr.h \ + ../include/dcmtk/dcmdata/dcbytstr.h ../include/dcmtk/dcmdata/dctypes.h \ + ../include/dcmtk/dcmdata/dcelem.h ../include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../include/dcmtk/dcmdata/dcerror.h ../include/dcmtk/dcmdata/dcxfer.h \ + ../include/dcmtk/dcmdata/dcvr.h ../include/dcmtk/dcmdata/dctag.h \ + ../include/dcmtk/dcmdata/dctagkey.h ../include/dcmtk/dcmdata/dcstack.h +tvrui.o: tvrui.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../ofstd/include/dcmtk/ofstd/oftest.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../include/dcmtk/dcmdata/dcuid.h ../include/dcmtk/dcmdata/dcdefine.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../include/dcmtk/dcmdata/dcvrui.h ../include/dcmtk/dcmdata/dcbytstr.h \ + ../include/dcmtk/dcmdata/dctypes.h ../include/dcmtk/dcmdata/dcelem.h \ + ../include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../include/dcmtk/dcmdata/dcerror.h ../include/dcmtk/dcmdata/dcxfer.h \ + ../include/dcmtk/dcmdata/dcvr.h ../include/dcmtk/dcmdata/dctag.h \ + ../include/dcmtk/dcmdata/dctagkey.h ../include/dcmtk/dcmdata/dcstack.h \ + ../include/dcmtk/dcmdata/dcdeftag.h diff --git a/dcmdata/tests/Makefile.in b/dcmdata/tests/Makefile.in new file mode 100644 index 00000000..563cc66f --- /dev/null +++ b/dcmdata/tests/Makefile.in @@ -0,0 +1,56 @@ +# +# Makefile for dcmdata/tests +# + +@SET_MAKE@ + +SHELL = /bin/sh +VPATH = @srcdir@:@top_srcdir@/include:@top_srcdir@/@configdir@/include +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +configdir = @top_srcdir@/@configdir@ + +include $(configdir)/@common_makefile@ + +ofstddir = $(top_srcdir)/../ofstd +oflogdir = $(top_srcdir)/../oflog + +LOCALINCLUDES = -I$(top_srcdir)/include -I$(ofstddir)/include -I$(oflogdir)/include +LIBDIRS = -L$(top_srcdir)/libsrc -L$(top_srcdir)/libi2d -L$(ofstddir)/libsrc \ + -L$(oflogdir)/libsrc +LOCALLIBS = -ldcmdata -loflog -lofstd $(ZLIBLIBS) $(ICONVLIBS) +I2DLIBS = -li2d + +objs = tests.o tpread.o ti2dbmp.o tchval.o tpath.o tvrdatim.o telemlen.o tparser.o \ + tdict.o tvrds.o tvrfd.o tvrui.o tstrval.o tspchrs.o tvrpn.o tparent.o \ + tfilter.o tvrcomp.o + +progs = tests + + +all: $(progs) + +tests: $(objs) + $(CXX) $(CXXFLAGS) $(LIBDIRS) $(LDFLAGS) -o $@ $(objs) $(I2DLIBS) $(LOCALLIBS) $(LIBS) + + +check: tests + DCMDICTPATH=../data/dicom.dic ./tests + +check-exhaustive: tests + DCMDICTPATH=../data/dicom.dic ./tests -x + + +install: all + +clean: + rm -f $(objs) $(progs) $(TRASH) + +distclean: + rm -f $(objs) $(progs) $(DISTTRASH) + + +dependencies: + $(CXX) -MM $(defines) $(includes) $(CPPFLAGS) $(CXXFLAGS) *.cc > $(DEP) + +include $(DEP) diff --git a/dcmdata/tests/dcmpsdmp.tcl b/dcmdata/tests/dcmpsdmp.tcl new file mode 100644 index 00000000..aa2b0169 --- /dev/null +++ b/dcmdata/tests/dcmpsdmp.tcl @@ -0,0 +1,187 @@ +#!/bin/sh +# the next line restarts using wish \ +exec wish4.2 "$0" "$@" + +# inserts the tag value + +proc insertTagValue {w s} { + set sp [string index $s 0] + if {$sp == "("} { + if {[string match {*\,*} $s] == 0} { + $w insert end $s tag_val1 + } else { + $w insert end $s tag_val2 + } + } elseif {$sp == "\["} { + $w insert end $s tag_val2 + } elseif {$sp == "="} { + $w insert end $s tag_val3 + } else { + $w insert end $s tag_val4 + } +} + + +# load text from file into window + +proc loadText {w name} { +# $w configure -state normal + set f [open $name] + while {![eof $f]} { + gets $f s + set sp [string index $s 0] + if {$sp == "#" || $sp == "*"} { + $w insert end $s tag_emph + } elseif {[string match {(\ )*\(*\)*\#*} $s] == 0} { + set sp1 [string first ")" $s] + $w insert end [string range $s 0 $sp1] tag_tag + set sp1 [expr int ($sp1 + 1)] + set sp2 [expr int ($sp1 + 3)] + $w insert end [string range $s $sp1 $sp2] tag_vr + set sp3 [string last "#" $s] + set sp1 [expr int ($sp2 + 1)] + set sp2 [expr int ($sp3 - 1)] + insertTagValue $w [string range $s $sp1 $sp2] + set ss [string range $s $sp3 end] + set sp3 [string last " " $ss] + set sp2 [expr int ($sp3)] + $w insert end [string range $ss 0 $sp2] tag_len + set sp1 [expr int ($sp3 + 1)] + $w insert end [string range $ss $sp1 end] tag_name + } else { + $w insert end $s + } + $w insert end "\n" + } + close $f +# $w configure -state disabled +} + + +# search string in text window and mark all positions with tag + +proc findText {w name tag} { + $w tag remove $tag 1.0 end + set hits 0 + set pos -1 + if {$name != ""} { + set cur 1.0 + while 1 { + set cur [$w search -count length -- $name $cur end] + if {$cur == ""} { + break + } + if {$pos < 0} { + set pos $cur + } + $w tag add $tag $cur "$cur + $length char" + set cur [$w index "$cur + $length char"] + incr hits + } + } + if {$pos >= 0} { + $w see $pos + } + return $hits +} + +# search string in both text windows + +proc findTextCommand {name} { + global hitsText + + set dh [findText .dump.text $name tag_found] + set hitsText [concat "Hits: " $dh] + focus .find.entry + .find.entry delete 0 end +} + + +# set up text window + +proc setupTextWindow {} { + global findName + global hitsText + + set hitsText "Hits: 0" + + frame .find + button .find.button -text "Find" -command "findTextCommand \$findName" -width 4 -anchor w + entry .find.entry -textvariable findName + label .find.label -textvariable hitsText -width 13 + pack .find.button -side left + pack .find.label -side right + pack .find.entry -fill x -expand yes -padx 5 + + frame .dump + text .dump.text -height 1 -wrap none -background #fff7e9 -selectbackground lightgray -font -*-Courier-Medium-R-Normal--*-150-*-*-*-*-*-* -xscrollcommand ".dump.xscroll set" -yscrollcommand ".dump.yscroll set" + scrollbar .dump.xscroll -orient horizontal -command ".dump.text xview" + scrollbar .dump.yscroll -orient vertical -command ".dump.text yview" + pack .dump.xscroll -side bottom -fill x + pack .dump.yscroll -side right -fill y + pack .dump.text -expand yes -fill both + + + .dump.text tag configure tag_emph -foreground black -font -*-Courier-Bold-R-Normal--*-150-*-*-*-*-*-* + .dump.text tag configure tag_found -background lightgray -underline true + .dump.text tag configure tag_tag -foreground darkblue + .dump.text tag configure tag_vr -foreground darkred + .dump.text tag configure tag_val1 -foreground darkgray + .dump.text tag configure tag_val2 -foreground black + .dump.text tag configure tag_val3 -foreground darkblue + .dump.text tag configure tag_val4 -foreground black + .dump.text tag configure tag_len -foreground darkgray + .dump.text tag configure tag_name -foreground darkblue + + pack .find -side top -fill x + pack .dump -expand yes -fill both + + bind .find.entry "findTextCommand \$findName" + bind .dump.text {if {[.dump.text tag nextrange sel 1.0] != ""} {findTextCommand [selection get]}} + + focus .find.entry +} + + +# main window +catch {eval destroy [winfo child .]} errMsg +if {$errMsg > 0} { + exit 1 +} + +# initialization +set temp "/tmp" +if [info exists env(TEMP)] { + set temp $env(TEMP) +} elseif [info exists env(TMP)] { + set temp $env(TMP) +} +set dumpReport [file join $temp dcmdump.report] +set dumpApp "dcmdump" + +# set up window +wm iconname . "DICOM Dump" +if {$tcl_platform(os) == "SunOS"} { + wm geometry . 956x903 +} else { + wm geometry . [expr int([winfo screenwidth .] * 0.995)]x[expr int([winfo screenheight .] * 0.938)] +} +wm geometry . +0+0 +wm minsize . 400 165 + +setupTextWindow + +# set up bindings +bind all {destroy .} + +# start dump process +if {$argc > 0} { + set fileName [lindex $argv 0] + wm title . "Please wait ..." + catch {exec $dumpApp $fileName >& $dumpReport} + loadText .dump.text $dumpReport + update + wm title . [format "DICOM File Contents - %s" $fileName] +} else { + wm title . [format "DICOM File Contents - "] +} diff --git a/dcmdata/tests/dctmacro.h b/dcmdata/tests/dctmacro.h new file mode 100644 index 00000000..c487f88e --- /dev/null +++ b/dcmdata/tests/dctmacro.h @@ -0,0 +1,126 @@ +/* + * + * Copyright (C) 2011-2012, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Uli Schlachter + * + * Purpose: test program for reading DICOM datasets + * + */ + + +#ifndef DCTMACRO_H +#define DCTMACRO_H + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/dcmdata/dcdatset.h" +#include "dcmtk/dcmdata/dcistrmb.h" +#include "dcmtk/dcmdata/dcostrmb.h" +#include "dcmtk/dcmdata/dcxfer.h" + + +/* Macros for handling the endianness */ +#define LITTLE_ENDIAN_UINT16(w) OFstatic_cast(Uint8, (w) & 0xff), OFstatic_cast(Uint8, (w) >> 8) +#define LITTLE_ENDIAN_UINT32(w) LITTLE_ENDIAN_UINT16((w) & 0xffff), LITTLE_ENDIAN_UINT16((w) >> 16) + +#define BIG_ENDIAN_UINT16(w) OFstatic_cast(Uint8, (w) >> 8), OFstatic_cast(Uint8, (w) & 0xff) +#define BIG_ENDIAN_UINT32(w) BIG_ENDIAN_UINT16((w) >> 16), BIG_ENDIAN_UINT16((w) & 0xffff) + +/* Various definitions for "fake generating" DICOM datasets, explicit transfer syntaxes */ +#define RESERVED_BYTES 0, 0 +#define TAG(tag) ENDIAN_UINT16((tag).getGroup()), ENDIAN_UINT16((tag).getElement()) +#define TAG_AND_LENGTH(tag, v, r, length) \ + TAG(tag), v, r, RESERVED_BYTES, ENDIAN_UINT32(length) +#define TAG_AND_LENGTH_SHORT(tag, v, r, length) \ + TAG(tag), v, r, ENDIAN_UINT16(length) +#define ITEM(length) \ + TAG(DCM_Item), ENDIAN_UINT32(length) +#define ITEM_END \ + TAG(DCM_ItemDelimitationItem), ENDIAN_UINT32(0) +#define SEQUENCE_END \ + TAG(DCM_SequenceDelimitationItem), ENDIAN_UINT32(0) + +/* Various definitions for "fake generating" DICOM datasets, implicit transfer syntaxes */ +#define IMPLICIT_TAG_AND_LENGTH(tag, length) \ + TAG(tag), ENDIAN_UINT32(length) + +#define UNDEFINED_LENGTH 0xffffffff +#define UNDEFINED_LENGTH_SHORT 0xffff +#define VALUE 0x2a + + +/** + * Read the dataset from the buffer into a dataset object. + * @param dset the dataset to read into + * @param buffer the buffer to read from + * @param length the length of the buffer + * @param ts the transfer syntax that is used + * @return EC_Normal if reading worked, else an error + */ +static inline OFCondition readDataset(DcmDataset& dset, const Uint8* buffer, size_t length, E_TransferSyntax ts) +{ + DcmInputBufferStream stream; + stream.setBuffer(buffer, length); + stream.setEos(); + + dset.clear(); + dset.transferInit(); + const OFCondition cond = dset.read(stream, ts); + dset.transferEnd(); + + return cond; +} + +/** + * Read the dataset from the buffer into a dataset object. + * The difference to readDataset() is that this function then writes it out into + * a buffer again which is read again. So this also tests the write functions. + * @param dset the dataset to read itno + * @param buffer the buffer to read from + * @param length the length of the buffer + * @param ts1 the transfer syntax that is used in buffer + * @param ts2 the transfer syntax that should be used for the write/read cycle + * @return EC_Normal if reading worked, else an error + */ +static inline OFCondition readDatasetTwice(DcmDataset& dset, const Uint8* buffer, + size_t length, E_TransferSyntax ts1, E_TransferSyntax ts2, E_EncodingType encType = EET_ExplicitLength) +{ + OFCondition cond = readDataset(dset, buffer, length, ts1); + if (cond.bad()) + return cond; + + // Write the dataset into a temporary buffer + OFVector writeBuffer(length * 2); + DcmOutputBufferStream out(&writeBuffer[0], writeBuffer.size()); + dset.transferInit(); + cond = dset.write(out, ts1, encType, NULL); + dset.transferEnd(); + + // To avoid error messages, we must always flush the buffer + void *outBuffer; + offile_off_t outLength; + out.flushBuffer(outBuffer, outLength); + + if (cond.bad()) + // Writing failed + return cond; + + // Now read the dataset again + return readDataset(dset, OFstatic_cast(const Uint8 *, outBuffer), + OFstatic_cast(size_t, outLength), ts2); +} + + +#endif // DCTMACRO_H diff --git a/dcmdata/tests/tchval.cc b/dcmdata/tests/tchval.cc new file mode 100644 index 00000000..9b966967 --- /dev/null +++ b/dcmdata/tests/tchval.cc @@ -0,0 +1,275 @@ +/* + * + * Copyright (C) 2009-2015, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Joerg Riesmeier + * + * Purpose: test program for checkStringValue() methods + * + */ + + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/ofstd/oftest.h" +#include "dcmtk/dcmdata/dctk.h" +#include "dcmtk/dcmdata/vrscan.h" +#include "dcmtk/ofstd/ofbmanip.h" + + +#define CHECK_GOOD(number, check) do { \ + if (!(check).good()) \ + OFCHECK_FAIL(number ": " #check); \ +} while (0); + +#define CHECK_BAD(number, check) do { \ + if (!(check).bad()) \ + OFCHECK_FAIL(number ": " #check); \ +} while (0); + +OFTEST(dcmdata_checkStringValue) +{ + /* test "Application Entity" */ + CHECK_BAD ( "AE-01", DcmApplicationEntity::checkStringValue(" ", "1") ) + CHECK_GOOD( "AE-02", DcmApplicationEntity::checkStringValue("A\\") ) + CHECK_GOOD( "AE-03", DcmApplicationEntity::checkStringValue(" AETITLE", "1") ) + CHECK_GOOD( "AE-04", DcmApplicationEntity::checkStringValue("AE-Title ", "1") ) + CHECK_GOOD( "AE-05", DcmApplicationEntity::checkStringValue(" AE Title ", "1") ) + CHECK_GOOD( "AE-06", DcmApplicationEntity::checkStringValue("A \\ B", "2") ) + CHECK_BAD ( "AE-07", DcmApplicationEntity::checkStringValue("J\366rg", "1") ) + CHECK_BAD ( "AE-08", DcmApplicationEntity::checkStringValue("1234567890-ABCDE ") ) + CHECK_GOOD( "AE-09", DcmApplicationEntity::checkStringValue("\\ AE \\", "3-3n") ) + + /* test "Age String" */ + CHECK_GOOD( "AS-01", DcmAgeString::checkStringValue("001Y", "1") ) + CHECK_GOOD( "AS-02", DcmAgeString::checkStringValue("099Y", "1") ) + CHECK_BAD ( "AS-03", DcmAgeString::checkStringValue("099Z", "1") ) + CHECK_GOOD( "AS-04", DcmAgeString::checkStringValue("199D\\000W\\500M", "2-n") ) + CHECK_BAD ( "AS-05", DcmAgeString::checkStringValue("Y010", "1") ) + CHECK_BAD ( "AS-06", DcmAgeString::checkStringValue("10Y", "1") ) + CHECK_BAD ( "AS-07", DcmAgeString::checkStringValue("010 Y", "1") ) + CHECK_BAD ( "AS-08", DcmAgeString::checkStringValue(" 010Y", "1") ) + CHECK_BAD ( "AS-09", DcmAgeString::checkStringValue("010Y ", "1") ) + CHECK_BAD ( "AS-10", DcmAgeString::checkStringValue("0109Y", "1") ) + + /* test "Code String" */ + CHECK_GOOD( "CS-01", DcmCodeString::checkStringValue("TEST 1234567890\\TEST", "2-2n") ) + CHECK_BAD ( "CS-02", DcmCodeString::checkStringValue("TEST 1234567890\\TEST\\", "2-2n") ) + CHECK_GOOD( "CS-03", DcmCodeString::checkStringValue("", "2-2n") ) + CHECK_GOOD( "CS-04", DcmCodeString::checkStringValue("\\TEST 1234567890", "2") ) + CHECK_GOOD( "CS-05", DcmCodeString::checkStringValue("\\ ", "2") ) + CHECK_BAD ( "CS-06", DcmCodeString::checkStringValue("\\TEST 1234567890 A", "2") ) + CHECK_BAD ( "CS-07", DcmCodeString::checkStringValue("J\366rg", "1-2") ) + CHECK_BAD ( "CS-08", DcmCodeString::checkStringValue("Joerg", "1-2") ) + CHECK_GOOD( "CS-09", DcmCodeString::checkStringValue("MARCO \\ JOERG", "1-2") ) + CHECK_GOOD( "CS-10", DcmCodeString::checkStringValue("MARCO\\ MICHAEL \\JOERG\\") ) + CHECK_BAD ( "CS-11", DcmCodeString::checkStringValue(" 1234567890 ") ) + CHECK_BAD ( "CS-12", DcmCodeString::checkStringValue("1234567890-ABCDE") ) + CHECK_GOOD( "CS-13", DcmCodeString::checkStringValue(" ") ) + CHECK_BAD ( "CS-14", DcmCodeString::checkStringValue(" ") ) + + /* test "Date" */ + CHECK_GOOD( "DA-01", DcmDate::checkStringValue("20090731", "1") ) + CHECK_GOOD( "DA-02", DcmDate::checkStringValue("18200101", "1") ) + CHECK_GOOD( "DA-03", DcmDate::checkStringValue("21001231", "1") ) + CHECK_BAD ( "DA-04", DcmDate::checkStringValue("1820.01.01", "1", OFFalse) ) + CHECK_GOOD( "DA-05", DcmDate::checkStringValue("1820.01.01", "1", OFTrue) ) + CHECK_GOOD( "DA-06", DcmDate::checkStringValue("20090731\\18200101") ) + CHECK_GOOD( "DA-07", DcmDate::checkStringValue("20090731\\18200101", "2-2n") ) + CHECK_GOOD( "DA-08", DcmDate::checkStringValue("20090731\\18200101\\20000101\\21001231", "2-2n") ) + CHECK_BAD ( "DA-09", DcmDate::checkStringValue("20090731", "6") ) + CHECK_BAD ( "DA-10", DcmDate::checkStringValue("20000001", "1") ) + CHECK_BAD ( "DA-11", DcmDate::checkStringValue("00001232", "1") ) + CHECK_BAD ( "DA-12", DcmDate::checkStringValue("20000000", "1") ) + + /* test "Date Time" */ + CHECK_GOOD( "DT-01", DcmDateTime::checkStringValue("200907311230", "1") ) + CHECK_GOOD( "DT-02", DcmDateTime::checkStringValue("18200101000000", "1") ) + CHECK_GOOD( "DT-03", DcmDateTime::checkStringValue("21001231235959.000001", "1") ) + CHECK_GOOD( "DT-04", DcmDateTime::checkStringValue("20090731", "1") ) + CHECK_BAD ( "DT-05", DcmDateTime::checkStringValue("200907312400", "1") ) + CHECK_BAD ( "DT-06", DcmDateTime::checkStringValue("20090731 1200") ) + CHECK_GOOD( "DT-07", DcmDateTime::checkStringValue("2009073100\\1820010112", "2-2n") ) + CHECK_GOOD( "DT-08", DcmDateTime::checkStringValue("2009073100\\1820010112\\200001010030\\21001231171540.123", "2-2n") ) + CHECK_GOOD( "DT-09", DcmDateTime::checkStringValue("200907311230+0100", "1") ) + CHECK_GOOD( "DT-10", DcmDateTime::checkStringValue("20090731123000+1000", "1") ) + CHECK_BAD ( "DT-11", DcmDateTime::checkStringValue("200907311230+1900", "1") ) + CHECK_GOOD( "DT-12", DcmDateTime::checkStringValue("20090731123000.123456+0100", "1") ) + CHECK_BAD ( "DT-13", DcmDateTime::checkStringValue("20090731123000.123456+0100 ", "1") ) + CHECK_GOOD( "DT-14", DcmDateTime::checkStringValue("200907311230", "1") ) + CHECK_GOOD( "DT-15", DcmDateTime::checkStringValue("200907", "1") ) + CHECK_GOOD( "DT-16", DcmDateTime::checkStringValue("2009", "1") ) + CHECK_BAD ( "DT-17", DcmDateTime::checkStringValue("20091", "1") ) + + /* test "Decimal String" */ + CHECK_GOOD( "DS-01", DcmDecimalString::checkStringValue(" 0", "1") ) + CHECK_GOOD( "DS-02", DcmDecimalString::checkStringValue("0.0 ", "1") ) + CHECK_GOOD( "DS-03", DcmDecimalString::checkStringValue("-1", "1") ) + CHECK_GOOD( "DS-04", DcmDecimalString::checkStringValue("+12345.67890", "1") ) + CHECK_BAD ( "DS-05", DcmDecimalString::checkStringValue(" -12345.6789 ", "1") ) + CHECK_GOOD( "DS-06", DcmDecimalString::checkStringValue("01.01", "1") ) + CHECK_BAD ( "DS-06", DcmDecimalString::checkStringValue("0.1.01", "1") ) + CHECK_BAD ( "DS-07", DcmDecimalString::checkStringValue("0 1", "1") ) + CHECK_BAD ( "DS-08", DcmDecimalString::checkStringValue("0-1", "1") ) + CHECK_GOOD( "DS-09", DcmDecimalString::checkStringValue("1.0E99", "1") ) + CHECK_BAD ( "DS-10", DcmDecimalString::checkStringValue("1.099E", "1") ) + CHECK_GOOD( "DS-11", DcmDecimalString::checkStringValue("-10e+99", "1") ) + CHECK_GOOD( "DS-12", DcmDecimalString::checkStringValue("-10e+99\\+1E-1", "2") ) + + /* test "Integer String" */ + CHECK_GOOD( "IS-01", DcmIntegerString::checkStringValue("0", "1") ) + CHECK_GOOD( "IS-02", DcmIntegerString::checkStringValue("+0", "1") ) + CHECK_GOOD( "IS-03", DcmIntegerString::checkStringValue("-0", "1") ) + CHECK_GOOD( "IS-04", DcmIntegerString::checkStringValue("00", "1") ) + CHECK_GOOD( "IS-05", DcmIntegerString::checkStringValue("000000000001", "1") ) + CHECK_BAD ( "IS-06", DcmIntegerString::checkStringValue("1000000000001", "1") ) + CHECK_BAD ( "IS-07", DcmIntegerString::checkStringValue("-000000000001", "1") ) + CHECK_BAD ( "IS-08", DcmIntegerString::checkStringValue("3000000000", "1") ) + CHECK_GOOD( "IS-08", DcmIntegerString::checkStringValue("+2000000000", "1") ) + CHECK_GOOD( "IS-09", DcmIntegerString::checkStringValue("+2147483647", "1") ) + CHECK_BAD ( "IS-10", DcmIntegerString::checkStringValue("2147483648", "1") ) + CHECK_GOOD( "IS-11", DcmIntegerString::checkStringValue("-2147483648", "1") ) + CHECK_BAD ( "IS-12", DcmIntegerString::checkStringValue("-2147483649", "1") ) + CHECK_GOOD( "IS-13", DcmIntegerString::checkStringValue(" -2147483648\\+2147483647 ", "2") ) + CHECK_BAD ( "IS-14", DcmIntegerString::checkStringValue(" -2147483648 \\+2147483647", "2") ) + + /* test "Long String" */ + CHECK_GOOD( "LO-01", DcmLongString::checkStringValue(" ", "1") ) + CHECK_GOOD( "LO-02", DcmLongString::checkStringValue(" . ", "1") ) + CHECK_GOOD( "LO-03", DcmLongString::checkStringValue("ABC 123 abc _+-/", "1") ) + CHECK_GOOD( "LO-04", DcmLongString::checkStringValue(" ", "1") ) + CHECK_GOOD( "LO-05", DcmLongString::checkStringValue("ABC\\123", "2") ) + CHECK_GOOD( "LO-06", DcmLongString::checkStringValue(" J\366rg Riesmeier ", "1") ) +// CHECK_BAD ( "LO-07", DcmLongString::checkStringValueu("OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany, http://www.offis.de/", "1") ) + CHECK_GOOD( "LO-08", DcmLongString::checkStringValue("\\ _2_ \\ _3_ \\ _4_ \\ _5_ \\", "6") ) + CHECK_GOOD( "LO-09", DcmLongString::checkStringValue("ESC\033aping", "1") ) + CHECK_BAD ( "LO-10", DcmLongString::checkStringValue("not allowed: \r\014", "1") ) + + /* test "Long Text" */ + CHECK_GOOD( "LT-01", DcmLongText::checkStringValue(" Hello \\ 12345 \\ \344\366\374\337 ") ) + CHECK_GOOD( "LT-02", DcmLongText::checkStringValue(" permitted control characters: \011 \012 \014 \015 ") ) + CHECK_GOOD( "LT-03", DcmLongText::checkStringValue(" ") ) + + /* test "Person Name" */ + CHECK_GOOD( "PN-01", DcmPersonName::checkStringValue("A^Riesmeier^^=R^J\366rg", "1") ) + CHECK_GOOD( "PN-02", DcmPersonName::checkStringValue("A^Riesmeier^^=R^J\366rg\\", "1-n") ) + CHECK_BAD ( "PN-03", DcmPersonName::checkStringValue("A^Riesmeier^^=R^J\366rg\\", "1") ) + CHECK_GOOD( "PN-04", DcmPersonName::checkStringValue("Eichelberg^Marco^^Dr.=Onken^Michael^=Riesmeier^J\366rg^^Dr.^", "1") ) + CHECK_GOOD( "PN-05", DcmPersonName::checkStringValue("Eichelberg\\Onken\\Riesmeier", "3") ) + CHECK_GOOD( "PN-06", DcmPersonName::checkStringValue(" ") ) + CHECK_GOOD( "PN-07", DcmPersonName::checkStringValue(" A") ) + CHECK_GOOD( "PN-08", DcmPersonName::checkStringValue("^^^^") ) + CHECK_GOOD( "PN-09", DcmPersonName::checkStringValue("^ J\366rg ^") ) + CHECK_GOOD( "PN-10", DcmPersonName::checkStringValue("^^^^MD ") ) + CHECK_BAD ( "PN-11", DcmPersonName::checkStringValue("^^^^^") ) + CHECK_GOOD( "PN-12", DcmPersonName::checkStringValue("A^B^C^D^E=F^G^H^I^J=K^L^M^N^O") ) + /* The almighty DICOM standard says: + * Any component group may be absent, including the first component group. + * In this case, the person name may start with one or more “=” delimiters. + */ + CHECK_GOOD( "PN-13", DcmPersonName::checkStringValue("==Test") ) + CHECK_GOOD( "PN-14", DcmPersonName::checkStringValue("Test==") ) + CHECK_GOOD( "PN-15", DcmPersonName::checkStringValue("==") ) + CHECK_BAD ( "PN-16", DcmPersonName::checkStringValue("===") ) + CHECK_BAD ( "PN-17", DcmPersonName::checkStringValue("^=^=^=^") ) + CHECK_GOOD( "PN-18", DcmPersonName::checkStringValue("^^^^=^^^^=^^^^") ) + CHECK_GOOD( "PN-19", DcmPersonName::checkStringValue("") ) + /* further tests for component groups */ + CHECK_GOOD( "PN-20", DcmPersonName::checkStringValue("Unspecified^^^^=^^^^=^^^^") ) + CHECK_GOOD( "PN-21", DcmPersonName::checkStringValue("^^^^=^^Unspecified^^=^^^^") ) + CHECK_GOOD( "PN-22", DcmPersonName::checkStringValue("^^^^=^^^^=^^^^Unspecified") ) + + /* test "Short String" */ + CHECK_GOOD( "SH-01", DcmShortString::checkStringValue(" ", "1") ) + CHECK_GOOD( "SH-02", DcmShortString::checkStringValue(" . ", "1") ) + CHECK_GOOD( "SH-03", DcmShortString::checkStringValue("ABC 123 abc _+-/", "1") ) + CHECK_GOOD( "SH-04", DcmShortString::checkStringValue(" ", "1") ) + CHECK_GOOD( "SH-05", DcmShortString::checkStringValue("ABC\\123", "2") ) + CHECK_GOOD( "SH-06", DcmShortString::checkStringValue(" J\366rg Riesmeier ", "1") ) +// CHECK_BAD ( "SH-07", DcmShortString::checkStringValue("OFFIS e.V., Oldenburg", "1") ) + CHECK_GOOD( "SH-08", DcmShortString::checkStringValue("\\ _2_ \\ _3_ \\ _4_ \\ _5_ \\", "6") ) + CHECK_BAD ( "SH-09", DcmShortString::checkStringValue(" ", "2") ) + CHECK_GOOD( "SH-10", DcmShortString::checkStringValue("", "2") ) + CHECK_GOOD( "SH-11", DcmShortString::checkStringValue("ESC\033aping", "1") ) + CHECK_BAD ( "SH-12", DcmShortString::checkStringValue("not allowed: \n\010\r\014", "1") ) + + /* test "Short Text" */ + CHECK_GOOD( "ST-01", DcmShortText::checkStringValue(" umlaut characters are allowed: \304\326\334\344\366\374\naccented characters also: \341\340\351\350\355\354\342\352\364\rand control characters, of course, including \033=ESC ") ) + CHECK_BAD ( "ST-02", DcmShortText::checkStringValue(" other control characters are not allowed: \013 \010 \200 ") ) + CHECK_GOOD( "ST-03", DcmShortText::checkStringValue(" . ") ) + CHECK_GOOD( "ST-04", DcmShortText::checkStringValue(" ") ) + + /* test "Time" */ + CHECK_GOOD( "TM-01", DcmTime::checkStringValue("0000", "1") ) + CHECK_BAD ( "TM-02", DcmTime::checkStringValue("2400", "1") ) + CHECK_GOOD( "TM-03", DcmTime::checkStringValue("123045", "1") ) + CHECK_GOOD( "TM-04", DcmTime::checkStringValue("235959.123", "1") ) + CHECK_GOOD( "TM-05", DcmTime::checkStringValue("235959.987654", "1") ) + CHECK_BAD ( "TM-06", DcmTime::checkStringValue("000000.0000000", "1") ) + CHECK_GOOD( "TM-07", DcmTime::checkStringValue("1215 ", "1") ) + CHECK_BAD ( "TM-08", DcmTime::checkStringValue(" 1215", "1") ) + CHECK_BAD ( "TM-09", DcmTime::checkStringValue("12 15", "1") ) + CHECK_BAD ( "TM-10", DcmTime::checkStringValue("235959.987654 ", "1") ) + CHECK_GOOD( "TM-11", DcmTime::checkStringValue("0000 \\010101 \\020202.02 \\030303.0303", "4") ) + CHECK_BAD ( "TM-12", DcmTime::checkStringValue("12:30:00.123456", "1", OFFalse) ) + CHECK_GOOD( "TM-13", DcmTime::checkStringValue("12:30:00.123456", "1", OFTrue) ) + CHECK_BAD ( "TM-14", DcmTime::checkStringValue("12:30", "1", OFTrue) ) + CHECK_GOOD( "TM-15", DcmTime::checkStringValue("12 ", "1") ) + CHECK_BAD ( "TM-16", DcmTime::checkStringValue(" ", "1") ) + + /* test "Unlimited Characters" */ + CHECK_GOOD( "UC-01", DcmUnlimitedCharacters::checkStringValue("ABC", "1") ) + CHECK_GOOD( "UC-02", DcmUnlimitedCharacters::checkStringValue("ABC\\123", "2") ) + CHECK_GOOD( "UC-03", DcmUnlimitedCharacters::checkStringValue(" J\366rg Riesmeier ", "1") ) + CHECK_GOOD( "UC-04", DcmUnlimitedCharacters::checkStringValue("ESC\033aping", "1") ) + CHECK_BAD ( "UC-05", DcmUnlimitedCharacters::checkStringValue("not allowed: \n\010\r\014", "1") ) + CHECK_GOOD( "UC-06", DcmUnlimitedCharacters::checkStringValue(" ", "1") ) + CHECK_GOOD( "UC-07", DcmUnlimitedCharacters::checkStringValue("A\\B", "2") ) + + /* test "Unique Identifier" */ + CHECK_GOOD( "UI-01", DcmUniqueIdentifier::checkStringValue("0", "1") ) + CHECK_GOOD( "UI-02", DcmUniqueIdentifier::checkStringValue("0.1", "1") ) + CHECK_GOOD( "UI-03", DcmUniqueIdentifier::checkStringValue("1.2.3.4.5.6.7.8.9.0.123.4321", "1") ) + CHECK_BAD ( "UI-04", DcmUniqueIdentifier::checkStringValue("1.02", "1") ) + CHECK_BAD ( "UI-05", DcmUniqueIdentifier::checkStringValue(".2", "1") ) + CHECK_BAD ( "UI-06", DcmUniqueIdentifier::checkStringValue("1.", "1") ) + CHECK_BAD ( "UI-07", DcmUniqueIdentifier::checkStringValue("1.2.3.4.5.6.7.8.9.0 ", "1") ) + CHECK_BAD ( "UI-08", DcmUniqueIdentifier::checkStringValue(" 1.2.3.4.5.6.7.8.9.0", "1") ) + CHECK_BAD ( "UI-09", DcmUniqueIdentifier::checkStringValue("1.2.3.4.5. 6.7.8.9.0", "1") ) + CHECK_GOOD( "UI-10", DcmUniqueIdentifier::checkStringValue("1.2.3.4.5.6.7.8.9.0\\99", "2") ) + CHECK_GOOD( "UI-11", DcmUniqueIdentifier::checkStringValue("1.2.3.4.5.6.7.8.9.0.123.456.789.0.111222333444555666777888999000", "1") ) + CHECK_BAD ( "UI-12", DcmUniqueIdentifier::checkStringValue("1.2.3.4.5.6.7.8.9.0.123.456.789.10.111222333444555666777888999000", "1") ) + + /* test "Universal Resource Identifier or Universal Resource Locator (URI/URL)" */ + CHECK_GOOD( "UR-01", DcmUniversalResourceIdentifierOrLocator::checkStringValue("http://www.dcmtk.org/ ") ) + CHECK_BAD ( "UR-02", DcmUniversalResourceIdentifierOrLocator::checkStringValue(" http://www.dcmtk.org/") ) + CHECK_BAD ( "UR-03", DcmUniversalResourceIdentifierOrLocator::checkStringValue("http:\\\\www.dcmtk.org") ) + CHECK_BAD ( "UR-04", DcmUniversalResourceIdentifierOrLocator::checkStringValue("http://localhost/some space") ) + CHECK_GOOD( "UR-05", DcmUniversalResourceIdentifierOrLocator::checkStringValue("http://localhost/some%20space") ) + CHECK_GOOD( "UR-06", DcmUniversalResourceIdentifierOrLocator::checkStringValue("foo://example.com:8042/over/there?name=ferret#nose") ) + CHECK_GOOD( "UR-07", DcmUniversalResourceIdentifierOrLocator::checkStringValue("urn:example:animal:ferret:nose") ) + CHECK_GOOD( "UR-08", DcmUniversalResourceIdentifierOrLocator::checkStringValue("http://joe:passwd@www.example.net:8080/index.html?action=something&session=A54C6FE2#info") ) + + /* test "Unlimited Text" */ + OFString hugeString(1024 * 512, 'n'); + + CHECK_GOOD( "UT-01", DcmUnlimitedText::checkStringValue(" This text can be pretty long ... ") ) + CHECK_GOOD( "UT-02", DcmUnlimitedText::checkStringValue(hugeString) ) + + hugeString[hugeString.length() / 2] = '\t'; + CHECK_GOOD( "UT-03", DcmUnlimitedText::checkStringValue(hugeString) ) + + hugeString[hugeString.length() - 1] = '\v'; + CHECK_BAD ( "UT-04", DcmUnlimitedText::checkStringValue(hugeString) ) +} diff --git a/dcmdata/tests/tdict.cc b/dcmdata/tests/tdict.cc new file mode 100644 index 00000000..dd5d74a9 --- /dev/null +++ b/dcmdata/tests/tdict.cc @@ -0,0 +1,108 @@ +/* + * + * Copyright (C) 2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Uli Schlachter + * + * Purpose: test program for the data dictionary + * + */ + + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/ofstd/oftest.h" +#include "dcmtk/dcmdata/dcdict.h" +#include "dcmtk/dcmdata/dctagkey.h" +#include "dcmtk/dcmdata/dcvr.h" +#include "dcmtk/dcmdata/dcdicent.h" + +OFTEST(dcmdata_readingDataDictionary) +{ + // Does loading the global data dictionary work? + OFCHECK(dcmDataDict.isDictionaryLoaded()); +} + +OFTEST(dcmdata_usingDataDictionary) +{ + // This dictionary will only contain the skeleton entries + DcmDataDictionary localDict(OFFalse, OFFalse); + DcmDictEntry *entry1; + DcmDictEntry *entry2; + const char *name = "TestEntry"; + const char *creator = "Test"; + DcmTagKey key1(2, 2); + DcmTagKey key2(4, 5); + int entries; + +#define checkDictionary(num_entries, e_name, key1_c, key2_c, key1_nc, key2_nc) \ + entries = localDict.numberOfNormalTagEntries(); \ + entries += localDict.numberOfRepeatingTagEntries(); \ + OFCHECK_EQUAL(localDict.numberOfSkeletonEntries() + num_entries, entries); \ + OFCHECK_EQUAL(localDict.numberOfEntries(), num_entries); \ + OFCHECK(!localDict.isDictionaryLoaded()); \ + OFCHECK(localDict.findEntry("UnexistingEntry") == NULL); \ + OFCHECK(localDict.findEntry(name) == e_name); \ + OFCHECK(localDict.findEntry(key1, creator) == key1_c); \ + OFCHECK(localDict.findEntry(key2, creator) == key2_c); \ + OFCHECK(localDict.findEntry(key1, NULL) == key1_nc); \ + OFCHECK(localDict.findEntry(key2, NULL) == key2_nc); + + checkDictionary(0, NULL, NULL, NULL, NULL, NULL); + + entry1 = new DcmDictEntry(2, 2, DcmVR(EVR_PN), name, 0, 1, + "test", OFTrue, "Test"); + entry2 = new DcmDictEntry(4, 4, 4, 6, DcmVR(EVR_PN), name, 0, 1, + "test", OFTrue, "Test"); + localDict.addEntry(entry1); + localDict.addEntry(entry2); + + checkDictionary(2, entry1, entry1, entry2, NULL, NULL); + + // This also gets rid of the skeleton entries! + localDict.clear(); + + OFCHECK_EQUAL(localDict.numberOfNormalTagEntries(), 0); + OFCHECK_EQUAL(localDict.numberOfRepeatingTagEntries(), 0); + OFCHECK_EQUAL(localDict.numberOfSkeletonEntries(), 0); + OFCHECK_EQUAL(localDict.numberOfEntries(), 0); + + checkDictionary(0, NULL, NULL, NULL, NULL, NULL); + + // Load the skeleton dictionary again + OFCHECK(localDict.reloadDictionaries(OFFalse, OFFalse)); + + checkDictionary(0, NULL, NULL, NULL, NULL, NULL); + + entry1 = new DcmDictEntry(2, 2, DcmVR(EVR_PN), name, 0, 1, + "test", OFTrue, NULL); + entry2 = new DcmDictEntry(4, 4, 4, 6, DcmVR(EVR_PN), name, 0, 1, + "test", OFTrue, NULL); + localDict.addEntry(entry1); + localDict.addEntry(entry2); + + checkDictionary(2, entry1, NULL, NULL, entry1, entry2); + + // Now we will overwrite entries + entry1 = new DcmDictEntry(2, 2, DcmVR(EVR_PN), "overwritten", 0, 1, + "test", OFTrue, NULL); + entry2 = new DcmDictEntry(4, 4, 4, 6, DcmVR(EVR_PN), "overwritten", 0, 1, + "test", OFTrue, NULL); + localDict.addEntry(entry1); + localDict.addEntry(entry2); + + checkDictionary(2, NULL, NULL, NULL, entry1, entry2); + +#undef checkDictionary +} diff --git a/dcmdata/tests/telemlen.cc b/dcmdata/tests/telemlen.cc new file mode 100644 index 00000000..e731320b --- /dev/null +++ b/dcmdata/tests/telemlen.cc @@ -0,0 +1,155 @@ +/* + * + * Copyright (C) 2011-2015, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Uli Schlachter + * + * Purpose: test program for DcmElement::calcElementLength + * + */ + + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/ofstd/oftest.h" +#include "dcmtk/dcmdata/dctk.h" +#include "dcmtk/dcmdata/dcpxitem.h" +#include "dcmtk/dcmdata/dcostrmb.h" + + +static void testElementLengthForElem(DcmElement& elem, const char *type, + offile_off_t len) +{ + const int maxSize = 100; + Uint8 buf[maxSize]; + DcmOutputBufferStream stream(buf, maxSize); + void *unused; + offile_off_t length; + OFCondition cond; + + elem.transferInit(); + cond = elem.write(stream, EXS_LittleEndianExplicit, EET_ExplicitLength, NULL); + elem.transferEnd(); + + stream.flushBuffer(unused, length); + if (cond.bad()) + OFCHECK_FAIL("Failed to write element " << type << " to stream: " << cond.text()); + if (length != len) + { + OFCHECK_FAIL("Expected length (" << OFstatic_cast(size_t, len) + << "), but got (" << OFstatic_cast(size_t, length) + << ") while writing " << type); + } + + length = elem.calcElementLength(EXS_LittleEndianExplicit, EET_ExplicitLength); + if (length != len) + { + OFCHECK_FAIL("Expected length (" << OFstatic_cast(size_t, len) + << "), but got (" << OFstatic_cast(size_t, length) + << ") while handling " << type); + } +} + +static void testElementLengthForVR(DcmEVR vr, offile_off_t len) +{ + const DcmTag tag(DCM_PatientName, vr); + + // Test all the calcElementLength and write implementations + DcmUnlimitedText ut(tag); + DcmByteString bs(tag); + DcmPixelData pd(tag); + DcmPolymorphOBOW po(tag); + DcmSequenceOfItems sq(tag); + DcmOtherByteOtherWord oo(tag); + + // Make sure the PixelData assumes it is un-encapsulated, else + // calcElementLength() will fail (Yes, this is a hack) + pd.putUint8Array(NULL, 0); + pd.setVR(vr); + + testElementLengthForElem(ut, "UnlimitedText", len); + testElementLengthForElem(bs, "ByteString", len); + testElementLengthForElem(pd, "PixelData", len); + testElementLengthForElem(po, "PolymorphOBOW", len); + testElementLengthForElem(sq, "SequenceOfItems", len); + testElementLengthForElem(oo, "OtherByteOtherWord", len); +} + +// These don't make sense to be tested: EVR_item, EVR_metainfo, +// EVR_dataset, EVR_fileFormat, EVR_dicomDir, EVR_dirRecord, EVR_pixelSQ + +OFTEST(dcmdata_elementLength_pixelItem) +{ + // EVR_pixelItem only makes sense for class DcmPixelItem. + // In fact, it enforces that VR in the constructor. + const DcmTag tag(DCM_PatientName, EVR_pixelItem); + DcmPixelItem pi(tag); + testElementLengthForElem(pi, "PixelItem", 8); +} + +OFTEST(dcmdata_elementLength_pixelSequence) +{ + // DcmPixelSequence forces EVR_OB, no point in trying other VRs. + const DcmTag tag(DCM_PatientName, EVR_OB); + DcmPixelSequence ps(tag); + testElementLengthForElem(ps, "PixelSeq", 20); +} + +/* Test extended length VRs */ +#define TEST_VR(vr) OFTEST(dcmdata_elementLength_ ## vr) { testElementLengthForVR(vr, 12); } +TEST_VR(EVR_OB) +TEST_VR(EVR_OD) +TEST_VR(EVR_OF) +TEST_VR(EVR_OW) +TEST_VR(EVR_SQ) +TEST_VR(EVR_UC) +TEST_VR(EVR_UR) +TEST_VR(EVR_UT) +TEST_VR(EVR_ox) +TEST_VR(EVR_lt) +TEST_VR(EVR_UNKNOWN) +TEST_VR(EVR_UN) +/* Converted to UN during write */ +TEST_VR(EVR_na) +TEST_VR(EVR_UNKNOWN2B) +#undef TEST_VR + +/* Test "short" length VRs */ +#define TEST_VR(vr) OFTEST(dcmdata_elementLength_ ## vr) { testElementLengthForVR(vr, 8); } +TEST_VR(EVR_AE) +TEST_VR(EVR_AS) +TEST_VR(EVR_AT) +TEST_VR(EVR_CS) +TEST_VR(EVR_DA) +TEST_VR(EVR_DS) +TEST_VR(EVR_DT) +TEST_VR(EVR_FL) +TEST_VR(EVR_FD) +TEST_VR(EVR_IS) +TEST_VR(EVR_LO) +TEST_VR(EVR_PN) +TEST_VR(EVR_SH) +TEST_VR(EVR_SL) +TEST_VR(EVR_SS) +TEST_VR(EVR_ST) +TEST_VR(EVR_TM) +TEST_VR(EVR_UI) +TEST_VR(EVR_UL) +TEST_VR(EVR_US) +TEST_VR(EVR_xs) +TEST_VR(EVR_LT) +TEST_VR(EVR_up) +TEST_VR(EVR_PixelData) +TEST_VR(EVR_OverlayData) +#undef TEST_VR diff --git a/dcmdata/tests/tests.cc b/dcmdata/tests/tests.cc new file mode 100644 index 00000000..335333fa --- /dev/null +++ b/dcmdata/tests/tests.cc @@ -0,0 +1,104 @@ +/* + * + * Copyright (C) 2011-2015 OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Uli Schlachter + * + * Purpose: main test program + * + */ + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/ofstd/oftest.h" + +OFTEST_REGISTER(dcmdata_partialElementAccess); +OFTEST_REGISTER(dcmdata_i2d_bmp); +OFTEST_REGISTER(dcmdata_checkStringValue); +OFTEST_REGISTER(dcmdata_determineVM); +OFTEST_REGISTER(dcmdata_getValueFromString); +OFTEST_REGISTER(dcmdata_pathAccess); +OFTEST_REGISTER(dcmdata_dateTime); +OFTEST_REGISTER(dcmdata_decimalString_1); +OFTEST_REGISTER(dcmdata_decimalString_2); +OFTEST_REGISTER(dcmdata_decimalString_3); +OFTEST_REGISTER(dcmdata_decimalString_4); +OFTEST_REGISTER(dcmdata_floatingPointDouble); +OFTEST_REGISTER(dcmdata_personName); +OFTEST_REGISTER(dcmdata_uniqueIdentifier_1); +OFTEST_REGISTER(dcmdata_uniqueIdentifier_2); +OFTEST_REGISTER(dcmdata_VRCompare); +OFTEST_REGISTER(dcmdata_elementLength_EVR_AE); +OFTEST_REGISTER(dcmdata_elementLength_EVR_AS); +OFTEST_REGISTER(dcmdata_elementLength_EVR_AT); +OFTEST_REGISTER(dcmdata_elementLength_EVR_CS); +OFTEST_REGISTER(dcmdata_elementLength_EVR_DA); +OFTEST_REGISTER(dcmdata_elementLength_EVR_DS); +OFTEST_REGISTER(dcmdata_elementLength_EVR_DT); +OFTEST_REGISTER(dcmdata_elementLength_EVR_FD); +OFTEST_REGISTER(dcmdata_elementLength_EVR_FL); +OFTEST_REGISTER(dcmdata_elementLength_EVR_IS); +OFTEST_REGISTER(dcmdata_elementLength_EVR_LO); +OFTEST_REGISTER(dcmdata_elementLength_EVR_LT); +OFTEST_REGISTER(dcmdata_elementLength_EVR_OB); +OFTEST_REGISTER(dcmdata_elementLength_EVR_OD); +OFTEST_REGISTER(dcmdata_elementLength_EVR_OF); +OFTEST_REGISTER(dcmdata_elementLength_EVR_OW); +OFTEST_REGISTER(dcmdata_elementLength_EVR_OverlayData); +OFTEST_REGISTER(dcmdata_elementLength_EVR_PN); +OFTEST_REGISTER(dcmdata_elementLength_EVR_PixelData); +OFTEST_REGISTER(dcmdata_elementLength_EVR_SH); +OFTEST_REGISTER(dcmdata_elementLength_EVR_SL); +OFTEST_REGISTER(dcmdata_elementLength_EVR_SQ); +OFTEST_REGISTER(dcmdata_elementLength_EVR_SS); +OFTEST_REGISTER(dcmdata_elementLength_EVR_ST); +OFTEST_REGISTER(dcmdata_elementLength_EVR_TM); +OFTEST_REGISTER(dcmdata_elementLength_EVR_UC); +OFTEST_REGISTER(dcmdata_elementLength_EVR_UI); +OFTEST_REGISTER(dcmdata_elementLength_EVR_UL); +OFTEST_REGISTER(dcmdata_elementLength_EVR_UN); +OFTEST_REGISTER(dcmdata_elementLength_EVR_UNKNOWN); +OFTEST_REGISTER(dcmdata_elementLength_EVR_UNKNOWN2B); +OFTEST_REGISTER(dcmdata_elementLength_EVR_UR); +OFTEST_REGISTER(dcmdata_elementLength_EVR_US); +OFTEST_REGISTER(dcmdata_elementLength_EVR_UT); +OFTEST_REGISTER(dcmdata_elementLength_EVR_lt); +OFTEST_REGISTER(dcmdata_elementLength_EVR_na); +OFTEST_REGISTER(dcmdata_elementLength_EVR_ox); +OFTEST_REGISTER(dcmdata_elementLength_EVR_up); +OFTEST_REGISTER(dcmdata_elementLength_EVR_xs); +OFTEST_REGISTER(dcmdata_elementLength_pixelItem); +OFTEST_REGISTER(dcmdata_elementLength_pixelSequence); +OFTEST_REGISTER(dcmdata_elementParent); +OFTEST_REGISTER(dcmdata_parser_missingDelimitationItems); +OFTEST_REGISTER(dcmdata_parser_missingSequenceDelimitationItem_1); +OFTEST_REGISTER(dcmdata_parser_missingSequenceDelimitationItem_2); +OFTEST_REGISTER(dcmdata_parser_wrongDelimitationItemForSequence); +OFTEST_REGISTER(dcmdata_parser_wrongDelimitationItemForItem); +OFTEST_REGISTER(dcmdata_parser_explicitItemLengthTooLarge); +OFTEST_REGISTER(dcmdata_parser_oddLengthPartialValue_lastItem); +OFTEST_REGISTER(dcmdata_parser_oddLengthPartialValue_notLastItem); +OFTEST_REGISTER(dcmdata_parser_wrongExplicitVRinDataset_default); +OFTEST_REGISTER(dcmdata_parser_wrongExplicitVRinDataset_defaultVR_dictLen); +OFTEST_REGISTER(dcmdata_parser_wrongExplicitVRinDataset_dictVR_defaultLen); +OFTEST_REGISTER(dcmdata_parser_wrongExplicitVRinDataset_preferDataDict); +OFTEST_REGISTER(dcmdata_parser_undefinedLengthUNSequence); +OFTEST_REGISTER(dcmdata_readingDataDictionary); +OFTEST_REGISTER(dcmdata_usingDataDictionary); +OFTEST_REGISTER(dcmdata_specificCharacterSet_1); +OFTEST_REGISTER(dcmdata_specificCharacterSet_2); +OFTEST_REGISTER(dcmdata_specificCharacterSet_3); +OFTEST_REGISTER(dcmdata_specificCharacterSet_4); +OFTEST_REGISTER(dcmdata_attribute_filter); +OFTEST_MAIN("dcmdata") diff --git a/dcmdata/tests/tfilter.cc b/dcmdata/tests/tfilter.cc new file mode 100644 index 00000000..9370f302 --- /dev/null +++ b/dcmdata/tests/tfilter.cc @@ -0,0 +1,78 @@ +/* + * + * Copyright (C) 2012, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Jan Schlamelcher + * + * Purpose: test program for class DcmAttributeFilter + * + */ + + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/ofstd/oftest.h" +#include "dcmtk/ofstd/ofvector.h" +#include "dcmtk/dcmdata/dcdeftag.h" +#include "dcmtk/dcmdata/dcuid.h" +#include "dcmtk/dcmdata/dcfilter.h" + + +OFTEST( dcmdata_attribute_filter ) +{ + DcmAttributeFilter ct_filter( DCM_SOPClassUID, UID_CTImageStorage ); + DcmItem item; + + item.putAndInsertString( DCM_SOPClassUID, UID_CTImageStorage ); + OFCHECK( ct_filter( item ) ); // test filter matches + item.putAndInsertString( DCM_SOPClassUID, UID_ComputedRadiographyImageStorage ); + OFCHECK( !ct_filter( item ) ); // test filter fails + // test anonymous filter object + OFCHECK( DcmAttributeFilter( DCM_SOPClassUID, UID_ComputedRadiographyImageStorage )( item ) ); + +#if !defined(_MSC_VER) || _MSC_VER > 1200 // iterator based filters not supported for VS <= 6.0. + // test iterator (array) based range + const char* filter_range[3] = + { + UID_ComputedRadiographyImageStorage, + UID_CTImageStorage, + UID_MRImageStorage + }; + + // create filter from range (iterators) + DcmAttributeFilter cr_ct_mr_filter( DCM_SOPClassUID, filter_range + 0, filter_range + 3 ); + + // test container-based (OFVector) range + OFVector filter_vector; + filter_vector.push_back( UID_CTImageStorage ); + filter_vector.push_back( UID_MRImageStorage ); + + // create filter from range (container) + DcmAttributeFilter ct_mr_filter( DCM_SOPClassUID, filter_vector ); + + // test all range-based filters + OFCHECK( cr_ct_mr_filter( item ) ); + OFCHECK( !ct_mr_filter( item ) ); + item.putAndInsertString( DCM_SOPClassUID, UID_CTImageStorage ); + OFCHECK( cr_ct_mr_filter( item ) ); + OFCHECK( ct_mr_filter( item ) ); + item.putAndInsertString( DCM_SOPClassUID, UID_MRImageStorage ); + OFCHECK( cr_ct_mr_filter( item ) ); + OFCHECK( ct_mr_filter( item ) ); + item.putAndInsertString( DCM_SOPClassUID, UID_EnhancedCTImageStorage ); + OFCHECK( !cr_ct_mr_filter( item ) ); +#endif + + OFCHECK( DcmAttributeFilter()( item ) ); // test default constructed (allow any) filter. +} diff --git a/dcmdata/tests/ti2dbmp.cc b/dcmdata/tests/ti2dbmp.cc new file mode 100644 index 00000000..74d5ec4b --- /dev/null +++ b/dcmdata/tests/ti2dbmp.cc @@ -0,0 +1,320 @@ +/* + * + * Copyright (C) 2010-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Uli Schlachter + * + * Purpose: test program for class I2DBmpSource + * + */ + + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/ofstd/oftest.h" +#include "dcmtk/dcmdata/libi2d/i2dbmps.h" + +static OFLogger i2dbmpLogger = OFLog::getLogger("dcmtk.test.i2dbmp"); + +enum offset { + BMP_IMAGE_OFFSET = 10, + BMP_WIDTH = 18, + BMP_HEIGHT = 22, + // BPP is only 2 bytes wide! + BMP_BPP = 28, + BMP_COLORS = 46 +}; + +// temporary file which will be used +static const char *temporaryFile = "i2dbmp.tmp"; + +static Uint8 bmpHeader[] = { + // Offset 0, Magic identification number + 'B', 'M', + // 2, File size, most likely wrong anyway + 42, 0x42, 13, 37, + // 6, Reservered + 0x13, 0x37, 0xde, 0xad, + // 10, Offset of the image data from start of data, this is IMPORTANT + 0, 0, 0, 0, + // 14, value is 40, the size of the BITMAPINFOHEADER struct (the following data) + 40, 0, 0, 0, + // 18, Width of the image + 0, 0, 0, 0, + // 22, height of image, if this is negative it's a top-down image + 0, 0, 0, 0, + // 26, number of planes, always 1 in BMP + 1, 0, + // 28, Bit depth + 24, 0, + // 30, compression info + 0, 0, 0, 0, + // 34, zero or size of image data in bytes + 12, 11, 10, 9, + // 38, X pixels per meter + 8, 7, 6, 5, + // 42, X pixels per meter + 4, 3, 2, 1, + // 46, colors used, 0 means the default value + 5, 0, 0, 0, + // 50, number of important colors, this field is useless + 1, 2, 3, 4, + + // Now comes the color table, this one gives us just some colors (the fourth + // byte is unused, let's write some garbage into it) + // color 0, black + 0x00, 0x00, 0x00, 18, + // color 1, blue + 0xff, 0x00, 0x00, 97, + // color 2, green + 0x00, 0xff, 0x00, 123, + // color 3, red + 0x00, 0x00, 0xff, 93, + // color 4, white + 0xff, 0xff, 0xff, 30, + + // Now you'd get the actual pixel data +}; + +#define LOG_DEBUG(arg) OFLOG_DEBUG(i2dbmpLogger, arg) +#define TEST(arg) LOG_DEBUG(arg << "...") + +#define EXPECT_SUCCESS(b) OFCHECK(b) +#define EXPECT_FAIL(b) EXPECT_SUCCESS(!(b)) + +static void setDWord(int offset, int width, bool sign = false) +{ + Uint32 w = width; + if (sign) + w = ~w + 1; + + for (int i = 0; i < 4; i++) + { + bmpHeader[offset++] = OFstatic_cast(Uint8, w & 0xff); + w >>= 8; + } +} + +static bool writeImage(const void *pixelData, unsigned int pixelDataLength) +{ + OFFile file; + if (!file.fopen(temporaryFile, "wb")) + { + OFCHECK_FAIL("Failed to open temporary file " << temporaryFile); + return false; + } + + file.fwrite(bmpHeader, 1, sizeof(bmpHeader)); + if (pixelData != NULL) + file.fwrite(pixelData, 1, pixelDataLength); + file.fclose(); + + return true; +} + +static bool readFile(char *&pixData, Uint32 &outputLength, Uint16 &rows, Uint16 &cols) +{ + I2DBmpSource source; + Uint16 samplesPerPixel, bitsAlloc, bitsStored; + Uint16 highBit, pixelRepr, planConf, pixAspectH, pixAspectV; + OFString photoMetrInt; + E_TransferSyntax ts; + + source.setImageFile(temporaryFile); + OFCondition res = source.readPixelData(rows, cols, samplesPerPixel, photoMetrInt, + bitsAlloc, bitsStored, highBit, pixelRepr, + planConf, pixAspectH, pixAspectV, pixData, + outputLength, ts); + if (res.bad()) + { + LOG_DEBUG("Reading file failed: " << res.text()); + return false; + } + + return true; +} + +static bool canHandleImage(const void *pixelData, unsigned int pixelDataLength) +{ + if (!writeImage(pixelData, pixelDataLength)) + return false; + + char *pixData; + Uint32 length; + Uint16 rows, cols; + + if (!readFile(pixData, length, rows, cols)) + return false; + + return true; +} + +static bool compareImage(const void *pixelData, unsigned int pixelDataLength, + void *expectedOutput, unsigned int expectedOutputLength, + Uint16 width, Uint16 height) +{ + if (!writeImage(pixelData, pixelDataLength)) + return false; + + char *pixData; + Uint32 length; + Uint16 rows, cols; + + if (!readFile(pixData, length, rows, cols)) + return false; + + if (expectedOutputLength != length) + { + LOG_DEBUG("Output length does not match!"); + delete[] pixData; + return false; + } + if (memcmp(expectedOutput, pixData, expectedOutputLength) != 0) + { + LOG_DEBUG("Output data does not match!"); + delete[] pixData; + return false; + } + + delete[] pixData; + + if (width != cols) + { + LOG_DEBUG("Output width does not match!"); + return false; + } + if (height != rows) + { + LOG_DEBUG("Output height does not match!"); + return false; + } + + return true; +} + +OFTEST(dcmdata_i2d_bmp) +{ + // This pixel data is used for all tests with at least 16bpp + Uint8 pixelData1[] = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88 }; + Uint8 expected1a[] = { 0x77, 0x66, 0x55, 0x33, 0x22, 0x11 }; // 32/24bpp, 1x2, bottom-up + Uint8 expected1b[] = { 0x33, 0x22, 0x11, 0x77, 0x66, 0x55 }; // 32/24bpp, 1x2, top-down + Uint8 expected1c[] = { 0x33, 0x22, 0x11, 0x66, 0x55, 0x44 }; // 24bpp, 2x1, bottom-up + Uint8 expected1d[] = { 0xc8, 0x90, 0xa8, 0x10, 0x18, 0xb8, + 0x40, 0x80, 0x88, 0x88, 0x08, 0x98, + }; // 16bpp, 2x2, top-down + + // These are the values of the color table +#define BLACK 0x00, 0x00, 0x00 +#define BLUE 0x00, 0x00, 0xff +#define GREEN 0x00, 0xff, 0x00 +#define RED 0xff, 0x00, 0x00 +#define WHITE 0xff, 0xff, 0xff + + Uint8 pixelData2[] = { 0, 1, 2, 3, 4, 3, 2, 1 }; + Uint8 expected2[] = { BLACK, BLUE, GREEN, WHITE, RED, GREEN }; // 8bpp, 3x2, top-down + + // Only byte 0 and 4 are actually used + Uint8 pixelData3[] = { 0x40, 0xff, 0xff, 0xff, 0x32, 0xff, 0xff, 0xff }; + Uint8 expected3[] = { RED, GREEN, WHITE, BLACK }; // 4bpp, 2x2, bottom-up + + /* Only first three *bits* of byte 0 and 4 are important, + * thanks to the 4 byte alignment requirement for rows. + */ + Uint8 pixelData4[] = { 0xaf, 0xff, 0x00, 0xad, 0x80, 0xde, 0xad, 0xab }; + Uint8 expected4[] = { BLUE, BLACK, BLACK, BLUE, BLACK, BLUE }; // 1bpp, 3x2, bottom-up + +#undef BLACK +#undef BLUE +#undef GREEN +#undef RED +#undef WHITE + + setDWord(BMP_IMAGE_OFFSET, OFstatic_cast(int, sizeof(bmpHeader))); + + TEST("Trying to read a 0x0 image"); + setDWord(BMP_WIDTH, 0); + setDWord(BMP_HEIGHT, 0); + EXPECT_FAIL(canHandleImage(pixelData1, OFstatic_cast(Uint32, sizeof(pixelData1)))); + setDWord(BMP_WIDTH, 1); + setDWord(BMP_HEIGHT, 2); + + TEST("Checking large bpp values"); + bmpHeader[BMP_BPP ] = 0; + bmpHeader[BMP_BPP + 1] = 0xef; + EXPECT_FAIL(canHandleImage(pixelData1, OFstatic_cast(Uint32, sizeof(pixelData1)))); + bmpHeader[BMP_BPP ] = 32; + bmpHeader[BMP_BPP + 1] = 0; + + TEST("Checking large number of colors"); + setDWord(BMP_COLORS, 1 << 31); + EXPECT_FAIL(canHandleImage(pixelData1, OFstatic_cast(Uint32, sizeof(pixelData1)))); + setDWord(BMP_COLORS, 5); + + TEST("Checking premature end of file"); + EXPECT_FAIL(canHandleImage(pixelData1, OFstatic_cast(Uint32, sizeof(pixelData1)) - 1)); + + TEST("Decoding a 32bpp image"); + EXPECT_SUCCESS(compareImage(pixelData1, OFstatic_cast(Uint32, sizeof(pixelData1)), expected1a, OFstatic_cast(Uint32, sizeof(expected1a)), 1, 2)); + + TEST("Decoding a 24bpp image"); + // Because rows are aligned to 4-bytes boundaries, this can use the + // same pixel data as the 32bpp image + bmpHeader[BMP_BPP] = 24; + EXPECT_SUCCESS(compareImage(pixelData1, OFstatic_cast(Uint32, sizeof(pixelData1)), expected1a, OFstatic_cast(Uint32, sizeof(expected1a)), 1, 2)); + + TEST("Decoding a 24bpp top-down image"); + setDWord(BMP_HEIGHT, -2); + EXPECT_SUCCESS(compareImage(pixelData1, OFstatic_cast(Uint32, sizeof(pixelData1)), expected1b, OFstatic_cast(Uint32, sizeof(expected1b)), 1, 2)); + + TEST("Checking correct handling of row alignment"); + setDWord(BMP_WIDTH, 2); + setDWord(BMP_HEIGHT, 1); + EXPECT_SUCCESS(compareImage(pixelData1, OFstatic_cast(Uint32, sizeof(pixelData1)), expected1c, OFstatic_cast(Uint32, sizeof(expected1c)), 2, 1)); + + TEST("Decoding a 16bpp image"); + bmpHeader[BMP_BPP] = 16; + setDWord(BMP_WIDTH, 2); + setDWord(BMP_HEIGHT, 2); + EXPECT_SUCCESS(compareImage(pixelData1, OFstatic_cast(Uint32, sizeof(pixelData1)), expected1d, OFstatic_cast(Uint32, sizeof(expected1d)), 2, 2)); + + // Everything starting from 8bpp uses color tables! + TEST("Decoding a 8bpp top-down image"); + setDWord(BMP_WIDTH, 3); + setDWord(BMP_HEIGHT, -2); + bmpHeader[BMP_BPP] = 8; + EXPECT_SUCCESS(compareImage(pixelData2, OFstatic_cast(Uint32, sizeof(pixelData2)), expected2, OFstatic_cast(Uint32, sizeof(expected2)), 3, 2)); + + TEST("Decoding a 4bpp image"); + bmpHeader[BMP_BPP] = 4; + setDWord(BMP_WIDTH, 2); + setDWord(BMP_HEIGHT, 2); + EXPECT_SUCCESS(compareImage(pixelData3, OFstatic_cast(Uint32, sizeof(pixelData3)), expected3, OFstatic_cast(Uint32, sizeof(expected3)), 2, 2)); + + TEST("Decoding a 1bpp image"); + bmpHeader[BMP_BPP] = 1; + setDWord(BMP_WIDTH, 3); + setDWord(BMP_HEIGHT, 2); + EXPECT_SUCCESS(compareImage(pixelData4, OFstatic_cast(Uint32, sizeof(pixelData4)), expected4, OFstatic_cast(Uint32, sizeof(expected4)), 3, 2)); + + TEST("Decoding an image with too large color table"); + setDWord(BMP_COLORS, -1); + EXPECT_FAIL(canHandleImage(pixelData4, OFstatic_cast(Uint32, sizeof(pixelData4)))); + + TEST("Decoding an image with too small color table"); + setDWord(BMP_COLORS, 1); + EXPECT_FAIL(canHandleImage(pixelData4, OFstatic_cast(Uint32, sizeof(pixelData4)))); + + /* Remove our temporary file */ + unlink(temporaryFile); +} diff --git a/dcmdata/tests/tparent.cc b/dcmdata/tests/tparent.cc new file mode 100644 index 00000000..ddf3b3cb --- /dev/null +++ b/dcmdata/tests/tparent.cc @@ -0,0 +1,185 @@ +/* + * + * Copyright (C) 2012, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Uli Schlachter + * + * Purpose: test program for parent element handling + * + */ + + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/ofstd/oftest.h" +#include "dcmtk/dcmdata/dctk.h" +#include "dctmacro.h" + + +/* To switch between big and little endian, just change these macros */ +#define TRANSFER_SYNTAX EXS_LittleEndianExplicit +#define ENDIAN_UINT16(w) LITTLE_ENDIAN_UINT16(w) +#define ENDIAN_UINT32(w) LITTLE_ENDIAN_UINT32(w) + + +// This checks if each object's parent is set correctly. This should be called +// as testParent(fileFormat); because other parameters are just used internally. +static void testParents(DcmObject& item, DcmObject *root = NULL, DcmObject *parent = NULL) +{ + OFCHECK_EQUAL(item.getParent(), parent); + + // DcmFileFormat doesn't count as root, but DcmMetaInfo and DcmDataset do. + // Thus we need some magic to check against them as root. + if (root != NULL) + { + DcmItem *pItem = item.getParentItem(); + OFCHECK(pItem == parent || pItem == parent->getParent()); + if (pItem) + { + DcmEVR ident = pItem->ident(); + OFCHECK(ident == EVR_item || ident == EVR_dataset + || ident == EVR_metainfo || ident == EVR_dirRecord); + } + + OFCHECK_EQUAL(item.getRootItem(), root); + } + else + { + OFCHECK(item.getRootItem() == NULL); + OFCHECK(item.getParentItem() == NULL); + } + + // iterate over all children and check them, too + DcmObject *obj = NULL; + while ((obj = item.nextInContainer(obj)) != NULL) + testParents(*obj, root == NULL ? obj : root, &item); +} + +OFTEST(dcmdata_elementParent) +{ + DcmFileFormat ff; + DcmItem *item = NULL; + DcmElement *elem = NULL; + DcmSequenceOfItems *seq = NULL; + OFCondition cond = EC_Normal; + + testParents(ff); + + // Some test dataset that we use to verify that reading works + const Uint8 testData[] = { + TAG_AND_LENGTH(DCM_DirectoryRecordSequence, 'S', 'Q', UNDEFINED_LENGTH), + ITEM(UNDEFINED_LENGTH), + TAG_AND_LENGTH_SHORT(DCM_OffsetOfTheNextDirectoryRecord, 'U', 'L', 4), + 0x42, 0x00, 0x00, 0x00, + ITEM_END, + SEQUENCE_END, + TAG_AND_LENGTH_SHORT(DCM_PatientName, 'P', 'N', 4), + 'T', 'e', 's', 't', + TAG_AND_LENGTH(DCM_ConceptNameCodeSequence, 'S', 'Q', UNDEFINED_LENGTH), + ITEM(UNDEFINED_LENGTH), + TAG_AND_LENGTH_SHORT(DCM_CodeValue, 'S', 'H', 6), + 'D', 'T', '.', '0', '6', ' ', + ITEM_END, + SEQUENCE_END, + TAG_AND_LENGTH(DCM_VerifyingObserverSequence, 'S', 'Q', UNDEFINED_LENGTH), + ITEM(UNDEFINED_LENGTH), + TAG_AND_LENGTH_SHORT(DCM_VerificationDateTime, 'D', 'T', 8), + '2', '0', '1', '2', '0', '4', '2', '3', + TAG_AND_LENGTH(DCM_VerifyingObserverIdentificationCodeSequence, 'S', 'Q', UNDEFINED_LENGTH), + ITEM(UNDEFINED_LENGTH), + TAG_AND_LENGTH_SHORT(DCM_CodeValue, 'S', 'H', 10), + 'U', 'S', 'R', '.', '0', '0', '0', '0', '2', ' ', + ITEM_END, + SEQUENCE_END, + ITEM_END, + SEQUENCE_END, + TAG_AND_LENGTH(DCM_PixelData, 'O', 'B', UNDEFINED_LENGTH), + ITEM(8), 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + ITEM(8), 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + ITEM(2), 0x10, 0x2a, + SEQUENCE_END + }; + + cond = readDataset(*ff.getDataset(), testData, sizeof(testData), EXS_LittleEndianExplicit); + OFCHECK(cond.good()); + testParents(ff); + + // Now test the insert/remove methods directly + DcmDataset *dset = ff.getAndRemoveDataset(); + OFCHECK(dset->getParent() == NULL); + delete dset; + testParents(ff); + dset = ff.getDataset(); + + elem = new DcmPersonName(DCM_PatientName); + OFCHECK(elem->getParent() == NULL); + cond = dset->insert(elem); + OFCHECK(cond.good()); + OFCHECK(elem->getParent() == dset); + testParents(ff); + + seq = new DcmSequenceOfItems(DCM_OtherPatientIDsSequence); + OFCHECK(seq->getParent() == NULL); + cond = dset->insert(seq); + OFCHECK(cond.good()); + OFCHECK(seq->getParent() == dset); + testParents(ff); + + item = new DcmItem(DCM_Item); + OFCHECK(item->getParent() == NULL); + cond = seq->insert(item); + OFCHECK(cond.good()); + OFCHECK(item->getParent() == seq); + testParents(ff); + + elem = new DcmLongString(DCM_OtherPatientIDs); + OFCHECK(elem->getParent() == NULL); + cond = item->insert(elem); + OFCHECK(cond.good()); + OFCHECK(elem->getParent() == item); + testParents(ff); + + item = new DcmItem(DCM_Item); + OFCHECK(item->getParent() == NULL); + cond = seq->insert(item); + OFCHECK(cond.good()); + OFCHECK(item->getParent() == seq); + testParents(ff); + + elem = new DcmLongString(DCM_OtherPatientIDs); + OFCHECK(elem->getParent() == NULL); + cond = item->insert(elem); + OFCHECK(cond.good()); + OFCHECK(elem->getParent() == item); + testParents(ff); + + elem = new DcmPersonName(DCM_PatientName); + OFCHECK(elem->getParent() == NULL); + cond = item->insert(elem); + OFCHECK(cond.good()); + OFCHECK(elem->getParent() == item); + testParents(ff); + + elem = item->remove(1); + OFCHECK_EQUAL(elem->getTag(), DCM_OtherPatientIDs); + OFCHECK(elem->getParent() == NULL); + delete elem; + testParents(ff); + + elem = item->remove(DCM_PatientName); + OFCHECK_EQUAL(elem->getTag(), DCM_PatientName); + OFCHECK(elem->getParent() == NULL); + delete elem; + testParents(ff); +} diff --git a/dcmdata/tests/tparser.cc b/dcmdata/tests/tparser.cc new file mode 100644 index 00000000..67d8b0be --- /dev/null +++ b/dcmdata/tests/tparser.cc @@ -0,0 +1,490 @@ +/* + * + * Copyright (C) 2011-2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Uli Schlachter + * + * Purpose: test program for reading DICOM datasets + * + */ + + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/ofstd/oftest.h" +#include "dcmtk/ofstd/ofstd.h" +#include "dcmtk/ofstd/oftempf.h" +#include "dcmtk/dcmdata/dctk.h" +#include "dcmtk/dcmdata/dcpxitem.h" +#include "dcmtk/dcmdata/dcistrmb.h" +#include "dcmtk/dcmdata/dcostrmb.h" +#include "dctmacro.h" + + +/* To switch between big and little endian, just change these macros */ +#define TRANSFER_SYNTAX EXS_LittleEndianExplicit +#define ENDIAN_UINT16(w) LITTLE_ENDIAN_UINT16(w) +#define ENDIAN_UINT32(w) LITTLE_ENDIAN_UINT32(w) + + +static OFLogger tparserLogger = OFLog::getLogger("dcmtk.test.tparser"); + +OFTEST(dcmdata_parser_missingDelimitationItems) +{ + const Uint8 data[] = { + TAG_AND_LENGTH(DCM_IconImageSequence, 'S', 'Q', UNDEFINED_LENGTH), + ITEM(UNDEFINED_LENGTH), + TAG_AND_LENGTH(DCM_PixelData, 'O', 'B', 4), + VALUE, VALUE, VALUE, VALUE, + /* Delimitation Items missing at the end of the stream */ + }; + DcmDataset dset; + OFCondition cond; + + // This should assume the above sequence is complete + dcmIgnoreParsingErrors.set(OFTrue); + cond = readDataset(dset, data, sizeof(data), TRANSFER_SYNTAX); + if (cond.bad()) + { + OFCHECK_FAIL("Parsing should have worked, but got error: " << cond.text()); + } + + // This should complain about the missing item + dcmIgnoreParsingErrors.set(OFFalse); + cond = readDataset(dset, data, sizeof(data), TRANSFER_SYNTAX); + if (cond != EC_SequDelimitationItemMissing) + { + OFCHECK_FAIL("Parsing should have failed with 'Sequence Delimitation Item missing', but got: " << cond.text()); + } +} + +OFTEST(dcmdata_parser_missingSequenceDelimitationItem_1) +{ + const Uint8 data[] = { + TAG_AND_LENGTH(DCM_PixelData, 'O', 'B', UNDEFINED_LENGTH), + ITEM(4), + VALUE, VALUE, VALUE, VALUE + /* SequenceDelimitationItem missing at the end of the stream */ + }; + DcmDataset dset; + OFCondition cond; + + // This should assume the above sequence is complete + dcmIgnoreParsingErrors.set(OFTrue); + cond = readDataset(dset, data, sizeof(data), TRANSFER_SYNTAX); + if (cond.bad()) + { + OFCHECK_FAIL("Parsing should have worked, but got error: " << cond.text()); + } + + // This should complain about the missing item + dcmIgnoreParsingErrors.set(OFFalse); + cond = readDataset(dset, data, sizeof(data), TRANSFER_SYNTAX); + if (cond != EC_SequDelimitationItemMissing) + { + OFCHECK_FAIL("Parsing should have failed with 'Sequence Delimitation Item missing', but got: " << cond.text()); + } +} + +OFTEST(dcmdata_parser_missingSequenceDelimitationItem_2) +{ + const Uint8 data[] = { + TAG_AND_LENGTH(DCM_IconImageSequence, 'S', 'Q', UNDEFINED_LENGTH), + ITEM(UNDEFINED_LENGTH), + TAG_AND_LENGTH(DCM_PixelData, 'O', 'B', 4), + VALUE, VALUE, VALUE, VALUE, + ITEM_END, + /* SequenceDelimitationItem missing, but there's further data after the sequence */ + TAG_AND_LENGTH(DCM_DataSetTrailingPadding, 'O', 'B', 4), + VALUE, VALUE, VALUE, VALUE + }; + DcmDataset dset; + OFCondition cond; + + // This should fail with a specific error code + dcmIgnoreParsingErrors.set(OFFalse); + cond = readDataset(dset, data, sizeof(data), TRANSFER_SYNTAX); + if (cond != EC_SequDelimitationItemMissing) + { + OFCHECK_FAIL("Parsing should have failed with 'Sequence Delimitation Item missing', but got: " << cond.text()); + } +} + +OFTEST(dcmdata_parser_wrongDelimitationItemForSequence) +{ + const Uint8 data[] = { + TAG_AND_LENGTH(DCM_IconImageSequence, 'S', 'Q', UNDEFINED_LENGTH), + ITEM(UNDEFINED_LENGTH), + TAG_AND_LENGTH(DCM_PixelData, 'O', 'B', 4), + VALUE, VALUE, VALUE, VALUE, + ITEM_END, + /* wrong delimitation item */ + ITEM_END, + TAG_AND_LENGTH(DCM_DataSetTrailingPadding, 'O', 'B', 4), + VALUE, VALUE, VALUE, VALUE + }; + DcmDataset dset; + OFCondition cond; + + // This should complain about the wrong delimitation item + dcmIgnoreParsingErrors.set(OFFalse); + dcmReplaceWrongDelimitationItem.set(OFFalse); + cond = readDataset(dset, data, sizeof(data), TRANSFER_SYNTAX); + if (cond != EC_SequDelimitationItemMissing) + { + OFCHECK_FAIL("Parsing should have failed with 'Sequence Delimitation Item missing', but got: " << cond.text()); + } + + // This should assume the above sequence encoding is correct + dcmIgnoreParsingErrors.set(OFTrue); + cond = readDataset(dset, data, sizeof(data), TRANSFER_SYNTAX); + if (cond.good()) + { + OFLOG_DEBUG(tparserLogger, DcmObject::PrintHelper(dset)); + if (dset.card() != 1) + OFCHECK_FAIL("There should be exactly 1 element on the main dataset level, but " << dset.card() << " found"); + } else { + OFCHECK_FAIL("Parsing should have worked, but got error: " << cond.text()); + } + + // This should replace the wrong delimitation item + dcmIgnoreParsingErrors.set(OFFalse); + dcmReplaceWrongDelimitationItem.set(OFTrue); + cond = readDataset(dset, data, sizeof(data), TRANSFER_SYNTAX); + if (cond.good()) + { + OFLOG_DEBUG(tparserLogger, DcmObject::PrintHelper(dset)); + if (dset.card() != 2) + OFCHECK_FAIL("There should be exactly 2 elements on the main dataset level, but " << dset.card() << " found"); + } else { + OFCHECK_FAIL("Parsing should have worked, but got error: " << cond.text()); + } +} + +OFTEST(dcmdata_parser_wrongDelimitationItemForItem) +{ + const Uint8 data[] = { + TAG_AND_LENGTH(DCM_IconImageSequence, 'S', 'Q', UNDEFINED_LENGTH), + ITEM(UNDEFINED_LENGTH), + TAG_AND_LENGTH(DCM_PixelData, 'O', 'B', 4), + VALUE, VALUE, VALUE, VALUE, + /* wrong delimitation item */ + SEQUENCE_END, + SEQUENCE_END, + TAG_AND_LENGTH(DCM_DataSetTrailingPadding, 'O', 'B', 4), + VALUE, VALUE, VALUE, VALUE + }; + DcmDataset dset; + OFCondition cond; + + // This should complain about the wrong delimitation item + dcmIgnoreParsingErrors.set(OFFalse); + dcmReplaceWrongDelimitationItem.set(OFFalse); + cond = readDataset(dset, data, sizeof(data), TRANSFER_SYNTAX); + if (cond != EC_ItemDelimitationItemMissing) + { + OFCHECK_FAIL("Parsing should have failed with 'Item Delimitation Item missing', but got: " << cond.text()); + } + + // This should assume the above item encoding is correct + dcmIgnoreParsingErrors.set(OFTrue); + cond = readDataset(dset, data, sizeof(data), TRANSFER_SYNTAX); + if (cond.good()) + { + OFLOG_DEBUG(tparserLogger, DcmObject::PrintHelper(dset)); + if (dset.card() != 2) + OFCHECK_FAIL("There should be exactly 2 elements on the main dataset level, but " << dset.card() << " found"); + } else { + OFCHECK_FAIL("Parsing should have worked, but got error: " << cond.text()); + } + + // This should replace the wrong delimitation item + dcmIgnoreParsingErrors.set(OFFalse); + dcmReplaceWrongDelimitationItem.set(OFTrue); + cond = readDataset(dset, data, sizeof(data), TRANSFER_SYNTAX); + if (cond.good()) + { + OFLOG_DEBUG(tparserLogger, DcmObject::PrintHelper(dset)); + if (dset.card() != 2) + OFCHECK_FAIL("There should be exactly 2 elements on the main dataset level, but " << dset.card() << " found"); + } else { + OFCHECK_FAIL("Parsing should have worked, but got error: " << cond.text()); + } +} + +OFTEST(dcmdata_parser_explicitItemLengthTooLarge) +{ + /* Produce some test data: Sequence with single item, containing a single element. */ + const Uint8 data[] = { + IMPLICIT_TAG_AND_LENGTH(DCM_RequestAttributesSequence, UNDEFINED_LENGTH), + ITEM(12), // 4 for tag, 4 for length, and 4 bytes extra that should produce the error + IMPLICIT_TAG_AND_LENGTH(DCM_CodeValue, 0), + SEQUENCE_END + }; + DcmDataset dset; + OFCondition cond; + + // This should complain about the item being too large + dcmIgnoreParsingErrors.set(OFFalse); + cond = readDataset(dset, data, sizeof(data), EXS_LittleEndianImplicit); + if (cond != EC_PrematureSequDelimitationItem) + { + OFCHECK_FAIL("Parsing should have failed with 'Sequence Delimitation Item occured before Item was completely read', but got: " << cond.text()); + } + + // This should ignore the error during parsing + dcmIgnoreParsingErrors.set(OFTrue); + cond = readDataset(dset, data, sizeof(data), EXS_LittleEndianImplicit); + if (cond.bad()) + { + OFCHECK_FAIL("Parsing should have worked, but got error: " << cond.text()); + } +} + +static void testOddLengthPartialValue(const Uint8* data, size_t length) +{ + const unsigned int bytesToRead = 5; + DcmFileFormat dfile; + OFCondition cond; + DcmElement *elem; + Uint8 buf[bytesToRead]; + OFTempFile temp; + + if (temp.getStatus().bad()) + { + OFCHECK_FAIL("Could not create temporary file: " << temp.getStatus().text()); + return; + } + + // Deferred value loading only works with files + OFFile f; + f.fopen(temp.getFilename(), "wb"); + f.fwrite(data, 1, length); + f.fclose(); + + // Everything larger than 1 byte won't be loaded now but only later + cond = dfile.loadFile(temp.getFilename(), TRANSFER_SYNTAX, EGL_noChange, 1, ERM_dataset); + if (cond.bad()) + { + OFCHECK_FAIL(cond.text()); + return; + } + + cond = dfile.getDataset()->findAndGetElement(DCM_PixelData, elem); + if (cond.bad()) + { + OFCHECK_FAIL(cond.text()); + return; + } + + // This is what we are actually testing for. The bug was that + // getPartialValue() tried to load one more byte than what was available. + // This resulted in an "Invalid stream" error. + cond = elem->getPartialValue(buf, 0, bytesToRead); + if (cond.bad()) + { + OFCHECK_FAIL(cond.text()); + return; + } + + for (unsigned int i = 0; i < bytesToRead; i++) + { + OFCHECK_EQUAL(buf[i], VALUE); + } +} + +OFTEST(dcmdata_parser_oddLengthPartialValue_lastItem) +{ + const Uint8 data[] = { + /* This needs an odd length and OW for the bug that we are testing */ + TAG_AND_LENGTH(DCM_PixelData, 'O', 'W', 5), + VALUE, VALUE, VALUE, VALUE, VALUE + }; + + testOddLengthPartialValue(data, sizeof(data)); +} + +OFTEST(dcmdata_parser_oddLengthPartialValue_notLastItem) +{ + const Uint8 data[] = { + /* This needs an odd length and OW for the bug that we are testing */ + TAG_AND_LENGTH(DCM_PixelData, 'O', 'W', 5), + VALUE, VALUE, VALUE, VALUE, VALUE, + /* This time something else is behind the tested element */ + TAG_AND_LENGTH(DCM_DataSetTrailingPadding, 'O', 'B', 4), + VALUE, VALUE, VALUE, VALUE + }; + + testOddLengthPartialValue(data, sizeof(data)); +} + +static const DcmTagKey wrongExplicitVRinDataset_unknownTag1(0x0006, 0x0006); +static const DcmTagKey wrongExplicitVRinDataset_unknownTag2(0x0006, 0x0008); + +#define WRONG_EXPLICIT_VR_COMMON \ + /* This non-standard tag cannot be corrected (not in data dictionary, short length field) */ \ + TAG_AND_LENGTH_SHORT(wrongExplicitVRinDataset_unknownTag1, 'P', 'N', 4), \ + 'A', 'B', 'C', 'D', \ + /* This non-standard tag cannot be corrected (not in data dictionary, long length field) */ \ + TAG_AND_LENGTH(wrongExplicitVRinDataset_unknownTag2, 'U', 'T', 4), \ + 'E', 'F', 'G', 'H', \ + /* This standard tag has a wrong VR ("ST" instead of "PN") */ \ + TAG_AND_LENGTH_SHORT(DCM_PatientName, 'S', 'T', 4), \ + 'I', 'J', 'K', 'L', \ + /* This standard tag has a correct VR, no modification required */ \ + TAG_AND_LENGTH_SHORT(DCM_PatientSex, 'C', 'S', 2), \ + 'O', ' ' + +static const Uint8 wrongExplicitVRinDataset_default_testData[] = { + WRONG_EXPLICIT_VR_COMMON, + /* This standard tag has a wrong VR ("UN") and does not use the "PN" length field size */ + TAG_AND_LENGTH(DCM_PatientBirthName, 'U', 'N', 4), + '0', '8', '1', '5', + /* This standard tag has a wrong VR ("LO") and does not use the "UT" length field size */ + TAG_AND_LENGTH_SHORT(DCM_PixelDataProviderURL, 'L', 'O', 4), + '4', '2', '4', '2', +}; + +static const Uint8 wrongExplicitVRinDataset_dictLen_testData[] = { + WRONG_EXPLICIT_VR_COMMON, + /* This standard tag has a wrong VR ("UN") and uses the "PN" length field size */ + TAG_AND_LENGTH_SHORT(DCM_PatientBirthName, 'U', 'N', 4), + '0', '8', '1', '5', + /* This standard tag has a wrong VR ("LO") and uses the "UT" length field size */ + TAG_AND_LENGTH(DCM_PixelDataProviderURL, 'L', 'O', 4), + '4', '2', '4', '2', +}; +#undef WRONG_EXPLICIT_VR_COMMON + +static void testForExpectedVR(DcmDataset &dset, const DcmTagKey &tag, const DcmEVR vr) +{ + DcmElement *elem; + OFCondition cond = dset.findAndGetElement(tag, elem); + if (cond.good()) + { + /* check whether the VR generated by the parser is the expected one */ + OFCHECK_EQUAL(elem->getVR(), vr); + } else { + OFCHECK_FAIL(cond.text()); + } +} + +static void testExplicitVRinDataset(OFBool useDictionaryVR, OFBool useDictionaryVRLen) +{ + DcmDataset dset; + OFCondition cond; + const OFConditionConst *expectedError; + const Uint8 *broken, *working; + size_t brokenLength, workingLength; + + if (useDictionaryVRLen) { + broken = wrongExplicitVRinDataset_default_testData; + brokenLength = sizeof(wrongExplicitVRinDataset_default_testData); + working = wrongExplicitVRinDataset_dictLen_testData; + workingLength = sizeof(wrongExplicitVRinDataset_dictLen_testData); + // This gets the length field wrong and interprets an element's value as + // the beginning of the following element; then complains about the length + expectedError = NULL; + } else { + working = wrongExplicitVRinDataset_default_testData; + workingLength = sizeof(wrongExplicitVRinDataset_default_testData); + broken = wrongExplicitVRinDataset_dictLen_testData; + brokenLength = sizeof(wrongExplicitVRinDataset_dictLen_testData); + // This gets the length field wrong and tries to allocate a huge element + expectedError = &EC_MemoryExhausted; + } + + dcmPreferLengthFieldSizeFromDataDictionary.set(useDictionaryVRLen); + dcmPreferVRFromDataDictionary.set(useDictionaryVR); + + // The broken version shouldn't be parseable + cond = readDataset(dset, broken, brokenLength, TRANSFER_SYNTAX); + if (cond != EC_InvalidStream && (expectedError == NULL || cond != *expectedError)) + { + OFCHECK_FAIL("Dataset should fail, but got: " << cond.text()); + if (cond.good()) + OFLOG_DEBUG(tparserLogger, DcmObject::PrintHelper(dset)); + } + + // The good version should work + cond = readDataset(dset, working, workingLength, TRANSFER_SYNTAX); + + // Reset to the default values + dcmPreferLengthFieldSizeFromDataDictionary.set(OFFalse); + dcmPreferVRFromDataDictionary.set(OFFalse); + if (cond.bad()) { + OFCHECK_FAIL(cond.text()); + return; + } + OFLOG_DEBUG(tparserLogger, DcmObject::PrintHelper(dset)); + testForExpectedVR(dset, wrongExplicitVRinDataset_unknownTag1, EVR_PN); + testForExpectedVR(dset, wrongExplicitVRinDataset_unknownTag2, EVR_UT); + testForExpectedVR(dset, DCM_PatientName, useDictionaryVR ? EVR_PN : EVR_ST); + testForExpectedVR(dset, DCM_PatientBirthName, useDictionaryVR ? EVR_PN : EVR_UN); + testForExpectedVR(dset, DCM_PixelDataProviderURL, useDictionaryVR ? EVR_UR : EVR_LO); +} + +OFTEST(dcmdata_parser_wrongExplicitVRinDataset_default) +{ + testExplicitVRinDataset(OFFalse, OFFalse); +} + +OFTEST(dcmdata_parser_wrongExplicitVRinDataset_defaultVR_dictLen) +{ + testExplicitVRinDataset(OFFalse, OFTrue); +} + +OFTEST(dcmdata_parser_wrongExplicitVRinDataset_dictVR_defaultLen) +{ + testExplicitVRinDataset(OFTrue, OFFalse); +} + +OFTEST(dcmdata_parser_wrongExplicitVRinDataset_preferDataDict) +{ + testExplicitVRinDataset(OFTrue, OFTrue); +} + +OFTEST(dcmdata_parser_undefinedLengthUNSequence) +{ + const Uint8 data[] = { + // Sequence with undefined length and VR UN => gets read as implicit TS + TAG_AND_LENGTH(DCM_IconImageSequence, 'U', 'N', UNDEFINED_LENGTH), + ITEM(UNDEFINED_LENGTH), + IMPLICIT_TAG_AND_LENGTH(DCM_PatientName, 4), + 'A', 'B', 'C', 'D', + IMPLICIT_TAG_AND_LENGTH(DCM_PixelData, 2), + VALUE, VALUE, + ITEM_END, + SEQUENCE_END + }; + DcmDataset dset; + OFCondition cond; + + cond = readDatasetTwice(dset, data, sizeof(data), EXS_JPEGProcess14, EXS_JPEGProcess14); + if (cond.good()) + { + OFLOG_DEBUG(tparserLogger, DcmObject::PrintHelper(dset)); + OFCHECK_EQUAL(1, dset.card()); + + DcmElement *elem = NULL; + cond = dset.findAndGetElement(DCM_PatientName, elem, OFTrue); + if (cond.good()) + OFCHECK(elem != NULL); + else + OFCHECK_FAIL("There should have been a PatientName item, but: " << cond.text()); + } else { + OFCHECK_FAIL("Parsing should have worked, but got error: " << cond.text()); + return; + } +} diff --git a/dcmdata/tests/tpath.cc b/dcmdata/tests/tpath.cc new file mode 100644 index 00000000..ef598758 --- /dev/null +++ b/dcmdata/tests/tpath.cc @@ -0,0 +1,355 @@ +/* + * + * Copyright (C) 2008-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Michael Onken + * + * Purpose: Test program for testing path features of DcmItem + * and DcmSequenceOfItem + * + */ + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ +#include "dcmtk/ofstd/oftest.h" +#include "dcmtk/dcmdata/dctk.h" +#include "dcmtk/dcmdata/dcpath.h" + + +static OFLogger tpathLogger = OFLog::getLogger("dcmtk.test.tpath"); + +#define CHECK_GOOD(check) OFCHECK((check).good()) + +#define RETURN_ERROR(msg) do { \ + OFOStringStream oss; \ + OFCondition cond; \ + oss << msg << OFStringStream_ends; \ + OFSTRINGSTREAM_GETSTR(oss, str) \ + cond = makeOFCondition(OFM_dcmdata, 1, OF_error, str); \ + OFSTRINGSTREAM_FREESTR(str) \ + return cond; \ +} while (0) + + +static OFCondition testPathInsertionsWithoutWildcard(const OFString& path, + DcmDataset *dset, + const Uint16& expectedNumObjects, + const OFBool& expectFailed = OFFalse, + const OFBool& createIfNecessary = OFTrue) +{ + DcmPathProcessor proc; + OFCondition result = proc.findOrCreatePath(dset, path, createIfNecessary); + if (result.bad()) + { + if (!expectFailed) + { + OFLOG_DEBUG(tpathLogger, "Path: " << path << " ... FAILED!"); + RETURN_ERROR("Path " << (createIfNecessary ? "insertion" : "lookup") << " failed: " << result.text()); + } + return EC_Normal; + } + + // get results + OFList< DcmPath* > results; + Uint32 numResults = proc.getResults(results); + if (numResults != 1) + { + // non-wildcard insertion should ALWAYS only return one result + OFLOG_DEBUG(tpathLogger, "Path: " << path << " ... FAILED!"); + RETURN_ERROR("Returned path list does contain more than one result but no wildcard was specified"); + } + DcmPath* oneResult = * (results.begin()); + + if (oneResult->size() != expectedNumObjects) + { + if (!expectFailed) + { + OFLOG_DEBUG(tpathLogger, "Path: " << path << " ... FAILED!"); + RETURN_ERROR("Returned object list does not contain " << expectedNumObjects << " but only " << oneResult->size() << "elements"); + } + } + else + { + OFListIterator(DcmPathNode*) it = oneResult->begin(); + for (Uint16 i=0; i < expectedNumObjects; i++) + { + if (*it == NULL) + { + OFLOG_DEBUG(tpathLogger, "Path: " << path << " ... FAILED!"); + RETURN_ERROR("Path insertion failed: One of the created objects is NULL"); + } + it++; + } + } + + OFLOG_DEBUG(tpathLogger, "Path: " << path << " ... OK"); + return EC_Normal; +} + +static OFCondition testPathInsertionsWithWildcard(const OFString& path, + DcmDataset *dset, + const Uint16& expectedNumResults, + const OFBool& expectFailed = OFFalse, + const OFBool& createIfNecessary = OFTrue) +{ + DcmPathProcessor proc; + OFCondition result = proc.findOrCreatePath(dset, path, createIfNecessary); + if (result.bad()) + { + if (!expectFailed) + { + OFLOG_DEBUG(tpathLogger, "Path: " << path << " ... FAILED!"); + RETURN_ERROR("Path " << (createIfNecessary ? "insertion" : "lookup") << " failed: " << result.text()); + } + return EC_Normal; + } + + // get results + OFList< DcmPath* > results; + Uint32 numResults = proc.getResults(results); + if ( (numResults != expectedNumResults) && !expectFailed ) + { + OFLOG_DEBUG(tpathLogger, "Path: " << path << " ... FAILED!"); + RETURN_ERROR("Expected " << expectedNumResults << " but " << numResults << " results were returned"); + } + // check results + OFListIterator(DcmPath*) oneResult = results.begin(); + while (oneResult != results.end()) + { + if (*oneResult) + { + OFListIterator(DcmPathNode*) it = (*oneResult)->begin(); + while (it != (*oneResult)->end()) + { + if (*it == NULL) + { + OFLOG_DEBUG(tpathLogger, "Path: " << path << " ... FAILED!"); + RETURN_ERROR("Path insertion failed: One of the result paths contains NULL"); + } + it++; + } + } + else + { + OFLOG_DEBUG(tpathLogger, "Path: " << path << " ... FAILED!"); + RETURN_ERROR("Path insertion failed: One of the returned paths is NULL"); + } + oneResult++; + } + OFLOG_DEBUG(tpathLogger, "Path: " << path << " ... OK"); + return EC_Normal; +} + +OFTEST(dcmdata_pathAccess) +{ + // TODO TODO TODO TODO TODO TODO TODO TODO +#ifdef HAVE_GUSI_H + GUSISetup(GUSIwithSIOUXSockets); + GUSISetup(GUSIwithInternetSockets); +#endif + + /* make sure data dictionary is loaded */ + if (!dcmDataDict.isDictionaryLoaded()) + { + OFCHECK_FAIL("no data dictionary loaded, check environment variable: " DCM_DICT_ENVIRONMENT_VARIABLE); + return; + } + + DcmFileFormat dcmff; + DcmDataset *dset = dcmff.getDataset(); + OFString path; + const OFString precalculatedDump = /* break the dump into smaller parts because MSVC6 only accepts 2048 character string constants maximum */ + "# Dicom-Data-Set\n# Used TransferSyntax: Unknown Transfer Syntax\n(0040,a730) SQ (Sequence with explicit length #=6) # 0, 1 ContentSequence\n" + " (fffe,e000) na (Item with explicit length #=0) # 0, 1 Item\n (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n" + " (fffe,e000) na (Item with explicit length #=0) # 0, 1 Item\n (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n" + " (fffe,e000) na (Item with explicit length #=0) # 0, 1 Item\n (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n" + " (fffe,e000) na (Item with explicit length #=0) # 0, 1 Item\n (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n" + " (fffe,e000) na (Item with explicit length #=0) # 0, 1 Item\n (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n" + " (fffe,e000) na (Item with explicit length #=1) # 0, 1 Item\n (0040,a730) SQ (Sequence with explicit length #=4) # 0, 1 ContentSequence\n" + " (fffe,e000) na (Item with explicit length #=0) # 0, 1 Item\n (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n" + " (fffe,e000) na (Item with explicit length #=0) # 0, 1 Item\n (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n" + " (fffe,e000) na (Item with explicit length #=0) # 0, 1 Item\n (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n" + " (fffe,e000) na (Item with explicit length #=1) # 0, 1 Item\n (0040,a043) SQ (Sequence with explicit length #=1) # 0, 1 ConceptNameCodeSequence\n" + " (fffe,e000) na (Item with explicit length #=2) # 0, 1 Item\n (0008,0100) SH (no value available) # 0, 0 CodeValue\n" + " (0008,0104) LO (no value available) # 0, 0 CodeMeaning\n (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n" + " (fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n" + " (fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n" + "(fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n"; + + const OFString precalculatedDump2 = + "# Dicom-Data-Set\n# Used TransferSyntax: Unknown Transfer Syntax\n(0010,0020) LO (no value available) # 0, 0 PatientID\n" + "(0040,a730) SQ (Sequence with explicit length #=6) # 0, 1 ContentSequence\n (fffe,e000) na (Item with explicit length #=1) # 0, 1 Item\n" + " (0040,a730) SQ (Sequence with explicit length #=4) # 0, 1 ContentSequence\n (fffe,e000) na (Item with explicit length #=1) # 0, 1 Item\n" + " (0010,0020) LO (no value available) # 0, 0 PatientID\n (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n" + " (fffe,e000) na (Item with explicit length #=0) # 0, 1 Item\n (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n" + " (fffe,e000) na (Item with explicit length #=0) # 0, 1 Item\n (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n" + " (fffe,e000) na (Item with explicit length #=1) # 0, 1 Item\n (0010,0010) PN (no value available) # 0, 0 PatientName\n" + " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n (fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n" + " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n (fffe,e000) na (Item with explicit length #=1) # 0, 1 Item\n" + " (0040,a730) SQ (Sequence with explicit length #=4) # 0, 1 ContentSequence\n (fffe,e000) na (Item with explicit length #=1) # 0, 1 Item\n" + " (0010,0020) LO (no value available) # 0, 0 PatientID\n (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n" + " (fffe,e000) na (Item with explicit length #=0) # 0, 1 Item\n (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n" + " (fffe,e000) na (Item with explicit length #=0) # 0, 1 Item\n (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n" + " (fffe,e000) na (Item with explicit length #=1) # 0, 1 Item\n (0010,0010) PN (no value available) # 0, 0 PatientName\n" + " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n (fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n" + " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n (fffe,e000) na (Item with explicit length #=1) # 0, 1 Item\n" + " (0040,a730) SQ (Sequence with explicit length #=4) # 0, 1 ContentSequence\n (fffe,e000) na (Item with explicit length #=1) # 0, 1 Item\n" + " (0010,0020) LO (no value available) # 0, 0 PatientID\n (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n" + " (fffe,e000) na (Item with explicit length #=0) # 0, 1 Item\n (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n" + " (fffe,e000) na (Item with explicit length #=0) # 0, 1 Item\n (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n" + " (fffe,e000) na (Item with explicit length #=1) # 0, 1 Item\n (0010,0010) PN (no value available) # 0, 0 PatientName\n" + " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n (fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n" + " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n (fffe,e000) na (Item with explicit length #=1) # 0, 1 Item\n" + " (0040,a730) SQ (Sequence with explicit length #=4) # 0, 1 ContentSequence\n (fffe,e000) na (Item with explicit length #=1) # 0, 1 Item\n" + " (0010,0020) LO (no value available) # 0, 0 PatientID\n (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n" + " (fffe,e000) na (Item with explicit length #=0) # 0, 1 Item\n (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n" + " (fffe,e000) na (Item with explicit length #=0) # 0, 1 Item\n (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n" + " (fffe,e000) na (Item with explicit length #=1) # 0, 1 Item\n (0010,0010) PN (no value available) # 0, 0 PatientName\n" + " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n (fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n" + " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n (fffe,e000) na (Item with explicit length #=1) # 0, 1 Item\n" + " (0040,a730) SQ (Sequence with explicit length #=4) # 0, 1 ContentSequence\n (fffe,e000) na (Item with explicit length #=1) # 0, 1 Item\n" + " (0010,0020) LO (no value available) # 0, 0 PatientID\n (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n" + " (fffe,e000) na (Item with explicit length #=0) # 0, 1 Item\n (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n" + " (fffe,e000) na (Item with explicit length #=0) # 0, 1 Item\n (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n" + " (fffe,e000) na (Item with explicit length #=1) # 0, 1 Item\n (0010,0010) PN (no value available) # 0, 0 PatientName\n" + " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n (fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n" + " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n (fffe,e000) na (Item with explicit length #=1) # 0, 1 Item\n" + " (0040,a730) SQ (Sequence with explicit length #=4) # 0, 1 ContentSequence\n (fffe,e000) na (Item with explicit length #=1) # 0, 1 Item\n" + " (0010,0020) LO (no value available) # 0, 0 PatientID\n (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n" + " (fffe,e000) na (Item with explicit length #=0) # 0, 1 Item\n (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n" + " (fffe,e000) na (Item with explicit length #=0) # 0, 1 Item\n (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n" + " (fffe,e000) na (Item with explicit length #=2) # 0, 1 Item\n (0010,0010) PN (no value available) # 0, 0 PatientName\n" + " (0040,a043) SQ (Sequence with explicit length #=1) # 0, 1 ConceptNameCodeSequence\n (fffe,e000) na (Item with explicit length #=2) # 0, 1 Item\n" + " (0008,0100) SH (no value available) # 0, 0 CodeValue\n (0008,0104) LO (no value available) # 0, 0 CodeMeaning\n" + " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n (fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n" + " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n (fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n" + " (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem\n(fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n"; + + const Uint32 precalculatedLength = 148; + const Uint32 precalculatedLength2 = 464; + + /* ********************************************************************* */ + /* Test insertions using no wildcards */ + /* ********************************************************************* */ + + OFLOG_DEBUG(tpathLogger, "These insertions should work:\n" + << "============================="); + path = "PatientID"; + CHECK_GOOD(testPathInsertionsWithoutWildcard(path, dset, 1)); + path = "ContentSequence"; + CHECK_GOOD(testPathInsertionsWithoutWildcard(path, dset, 1)); + path = "(0040,A730)"; + CHECK_GOOD(testPathInsertionsWithoutWildcard(path, dset, 1)); + path = "(0040,A730)[5]"; + CHECK_GOOD(testPathInsertionsWithoutWildcard(path, dset, 2)); + path = "(0040,A730)[5].ContentSequence[3].ConceptNameCodeSequence[0].CodeValue"; + CHECK_GOOD(testPathInsertionsWithoutWildcard(path, dset, 7)); + path = "ContentSequence[5].ContentSequence[3].ConceptNameCodeSequence[0].(0008,0104)"; + CHECK_GOOD(testPathInsertionsWithoutWildcard(path, dset, 7)); + + OFLOG_DEBUG(tpathLogger, "\nThese insertions should NOT work (wrong syntax):\n" + << "================================================"); + + path = "ContentSequences"; + CHECK_GOOD(testPathInsertionsWithoutWildcard(path, dset, 1, OFTrue)); + path = "(1234,ContentSequences"; + CHECK_GOOD(testPathInsertionsWithoutWildcard(path, dset, 1, OFTrue)); + path = "(00X4,A730)"; + CHECK_GOOD(testPathInsertionsWithoutWildcard(path, dset, 1, OFTrue)); + path = "(0040,A730)[-5]"; + CHECK_GOOD(testPathInsertionsWithoutWildcard(path, dset, 2, OFTrue)); + path = "(0040,A730)[a].ContentSequence[3].ConceptNameCodeSequence[0].CodeValue"; + CHECK_GOOD(testPathInsertionsWithoutWildcard(path, dset, 7, OFTrue)); + + OFLOG_DEBUG(tpathLogger, "\nThese find routines should work:\n" + << "================================"); + + path = "PatientID"; + CHECK_GOOD(testPathInsertionsWithoutWildcard(path, dset, 1, OFFalse, OFFalse /* do not create */)); + path = "ContentSequence"; + CHECK_GOOD(testPathInsertionsWithoutWildcard(path, dset, 1, OFFalse, OFFalse /* do not create */)); + path = "(0040,A730)"; + CHECK_GOOD(testPathInsertionsWithoutWildcard(path, dset, 1, OFFalse, OFFalse /* do not create */)); + path = "(0040,A730)[5]"; + CHECK_GOOD(testPathInsertionsWithoutWildcard(path, dset, 2, OFFalse, OFFalse /* do not create */)); + path = "(0040,A730)[5].ContentSequence[3].ConceptNameCodeSequence[0].CodeValue"; + CHECK_GOOD(testPathInsertionsWithoutWildcard(path, dset, 7, OFFalse, OFFalse /* do not create */)); + path = "ContentSequence[5].ContentSequence[3].ConceptNameCodeSequence[0].(0008,0104)"; + CHECK_GOOD(testPathInsertionsWithoutWildcard(path, dset, 7, OFFalse, OFFalse /* do not create */)); + + OFLOG_DEBUG(tpathLogger, "\nThese find routines should NOT work:\n" + << "===================================="); + + path = "PatientName"; // was never inserted + CHECK_GOOD(testPathInsertionsWithoutWildcard(path, dset, 1, OFTrue, OFFalse /* do not create */)); + path = "(0040,A730)[6]"; // we only have 6 items in there (not 7) + CHECK_GOOD(testPathInsertionsWithoutWildcard(path, dset, 2, OFTrue, OFFalse /* do not create */)); + path = "ConceptNameCodeSequence"; // should not exist on main level + CHECK_GOOD(testPathInsertionsWithoutWildcard(path, dset, 1, OFTrue, OFFalse /* do not create */)); + + OFLOG_DEBUG(tpathLogger, "\nChecking dataset length:\n" + << "========================"); + Uint32 length = dset->calcElementLength(EXS_LittleEndianExplicit,EET_ExplicitLength); + if (length == precalculatedLength) + { + OFLOG_DEBUG(tpathLogger, "Checking whether length of encoded dataset matches pre-calculated length ... OK"); + } + else + { + OFLOG_DEBUG(tpathLogger, "Checking whether length of encoded dataset matches pre-calculated length ... FAILED!"); + OFLOG_DEBUG(tpathLogger, "Length is " << length << ", but should be " << precalculatedLength); + OFLOG_DEBUG(tpathLogger, "Please check dump and adapt test in case of false alarm:" << OFendl); + OFLOG_DEBUG(tpathLogger, "Dump of assembled test object:"); + OFLOG_DEBUG(tpathLogger, DcmObject::PrintHelper(*dset)); + OFLOG_DEBUG(tpathLogger, "Dump of pre-defined template:" << OFendl); + OFLOG_DEBUG(tpathLogger, precalculatedDump); + OFCHECK_FAIL("Wrong length"); + } + + /* ********************************************************************* */ + /* Test insertions using wildcards */ + /* ********************************************************************* */ + + OFLOG_DEBUG(tpathLogger, "\nThese wildcard insertions should work:\n" + << "======================================"); + path = "ContentSequence[*].ContentSequence[3].PatientName"; + CHECK_GOOD(testPathInsertionsWithWildcard(path, dset, 6, OFFalse /* should work*/, OFTrue /*do create*/)); + path = "ContentSequence[*].ContentSequence[0].PatientID"; + CHECK_GOOD(testPathInsertionsWithWildcard(path, dset, 6, OFFalse /* should work*/, OFTrue /*do create*/)); + + OFLOG_DEBUG(tpathLogger, "\nTesting wildcard insertions should NOT work:\n" + << "============================================"); + path = "SourceImageSequence[*]"; + CHECK_GOOD(testPathInsertionsWithWildcard(path, dset, 0, OFTrue /* should fail*/, OFTrue /*do create*/)); + path = "ContentSequence[*].SourceImageSequence[*]"; + CHECK_GOOD(testPathInsertionsWithWildcard(path, dset, 0, OFTrue /* should fail*/, OFTrue /*do create*/)); + + OFLOG_DEBUG(tpathLogger, "\nChecking dataset length:\n" + << "========================"); + length = dset->calcElementLength(EXS_LittleEndianExplicit,EET_ExplicitLength); + if (length == precalculatedLength2) + { + OFLOG_DEBUG(tpathLogger, "Checking whether length of encoded dataset matches pre-calculated length ... OK"); + } + else + { + OFLOG_DEBUG(tpathLogger, "Checking whether length of encoded dataset matches pre-calculated length ... FAILED!"); + OFLOG_DEBUG(tpathLogger, "Length is " << length << ", but should be " << precalculatedLength2); + OFLOG_DEBUG(tpathLogger, "Please check dump and adapt test in case of false alarm:" << OFendl); + OFLOG_DEBUG(tpathLogger, "Dump of assembled test object:"); + OFLOG_DEBUG(tpathLogger, DcmObject::PrintHelper(*dset)); + OFLOG_DEBUG(tpathLogger, "Dump of pre-defined template:" << OFendl); + OFLOG_DEBUG(tpathLogger, precalculatedDump2); + OFCHECK_FAIL("Wrong length"); + } +} diff --git a/dcmdata/tests/tpread.cc b/dcmdata/tests/tpread.cc new file mode 100644 index 00000000..9e4971fc --- /dev/null +++ b/dcmdata/tests/tpread.cc @@ -0,0 +1,422 @@ +/* + * + * Copyright (C) 1994-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Marco Eichelberg + * + * Purpose: Test application for partial element access API + * + */ + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#define INCLUDE_CSTDLIB +#define INCLUDE_CSTDIO +#define INCLUDE_CSTRING +#include "dcmtk/ofstd/ofstdinc.h" + +#ifdef HAVE_GUSI_H +#include +#endif + +#include "dcmtk/ofstd/oftest.h" +#include "dcmtk/dcmdata/dctk.h" +#include "dcmtk/dcmdata/dcuid.h" /* for dcmtk version name */ +#include "dcmtk/dcmdata/dcostrmz.h" /* for dcmZlibCompressionLevel */ +#include "dcmtk/dcmdata/dcistrmz.h" /* for dcmZlibExpectRFC1950Encoding */ +#include "dcmtk/dcmdata/dcfcache.h" + +#ifdef WITH_ZLIB +#include /* for zlibVersion() */ +#endif + +static OFLogger tstpreadLogger = OFLog::getLogger("dcmtk.test.tstpread"); + +// ******************************************** + +#define BUFSIZE 32768 + +static void createTestDataset(DcmDataset *dset, unsigned char *buffer) +{ + // byte array, VR=OB + dset->putAndInsertUint8Array(DCM_EncapsulatedDocument, buffer, BUFSIZE); + + // short array, VR=US + dset->putAndInsertUint16Array(DCM_RWavePointer, OFreinterpret_cast(Uint16 *, buffer), BUFSIZE/OFstatic_cast(Uint32, sizeof(Uint16))); + + // long array, VR=UL + DcmElement *elem = new DcmUnsignedLong(DCM_TableOfPixelValues); + elem->putUint32Array(OFreinterpret_cast(Uint32 *, buffer), BUFSIZE/OFstatic_cast(Uint32, sizeof(Uint32))); + dset->insert(elem); + + // double array, VR=FD + elem = new DcmFloatingPointDouble(DCM_TableOfYBreakPoints); + elem->putFloat64Array(OFreinterpret_cast(Float64 *, buffer), BUFSIZE/OFstatic_cast(Uint32, sizeof(Float64))); + dset->insert(elem); +} + +static OFCondition sequentialNonOverlappingRead(DcmElement *delem, DcmFileCache *dcache, unsigned char *buffer) +{ + unsigned char *target = new unsigned char[BUFSIZE]; + Uint32 offset = 0; + Uint32 bytes_to_read = 0; + OFCondition cond; + + while (offset < BUFSIZE) + { + bytes_to_read = (rand() % 20)+1; // read 1 to 20 bytes + + // make sure we don't attempt to read beyond the end of the attribute value + if (offset + bytes_to_read > BUFSIZE) bytes_to_read = BUFSIZE - offset; + + cond = delem->getPartialValue(target, offset, bytes_to_read, dcache); + if (cond.bad()) + { + + delete[] target; + return cond; + } + + if (0 != memcmp(target, buffer+offset, bytes_to_read)) + { + OFOStringStream str; + str << "Error: unexpected sequence of " << bytes_to_read << " bytes found at offset " << offset << OFendl; + str << "Expected: "; + for (Uint32 i=0; i BUFSIZE) bytes_to_read = BUFSIZE - offset; + + cond = delem->getPartialValue(target, offset, bytes_to_read, dcache); + if (cond.bad()) + { + delete[] target; + return cond; + } + + if (0 != memcmp(target, buffer+offset, bytes_to_read)) + { + OFOStringStream str; + str << "Error: unexpected sequence of " << bytes_to_read << " bytes found at offset " << offset << OFendl; + str << "Expected: "; + for (Uint32 i=0; i 4) offset -= (rand() % 4); // let the read operations overlap by 0-3 bytes + } + delete[] target; + return EC_Normal; +} + +static OFCondition randomRead(DcmElement *delem, DcmFileCache *dcache, unsigned char *buffer) +{ + unsigned char *target = new unsigned char[BUFSIZE]; + Uint32 offset = 0; + Uint32 bytes_to_read = 0; + OFCondition cond; + + for (int i=1000; i; --i) + { + bytes_to_read = (rand() % 20)+1; // read 1 to 20 bytes + offset = rand() % BUFSIZE; + + // make sure we don't attempt to read beyond the end of the attribute value + if (offset + bytes_to_read > BUFSIZE) bytes_to_read = BUFSIZE - offset; + + cond = delem->getPartialValue(target, offset, bytes_to_read, dcache); + if (cond.bad()) + { + delete[] target; + return cond; + } + + if (0 != memcmp(target, buffer+offset, bytes_to_read)) + { + OFOStringStream str; + str << "Error: unexpected sequence of " << bytes_to_read << " bytes found at offset " << offset << OFendl; + str << "Expected: "; + for (Uint32 k=0; kfindAndGetElement(DCM_EncapsulatedDocument, delem); + if (cond.bad()) return cond; + + cond = sequentialNonOverlappingRead(delem, &cache, buffer); + if (cond.bad()) return cond; + + cond = dset->findAndGetElement(DCM_RWavePointer, delem); + if (cond.bad()) return cond; + + cond = sequentialNonOverlappingRead(delem, &cache, buffer); + if (cond.bad()) return cond; + + cond = dset->findAndGetElement(DCM_TableOfPixelValues, delem); + if (cond.bad()) return cond; + + cond = sequentialNonOverlappingRead(delem, &cache, buffer); + if (cond.bad()) return cond; + + cond = dset->findAndGetElement(DCM_TableOfYBreakPoints, delem); + if (cond.bad()) return cond; + + cond = sequentialNonOverlappingRead(delem, &cache, buffer); + + return cond; +} + +static OFCondition sequentialOverlappingRead(DcmDataset *dset, unsigned char *buffer) +{ + DcmFileCache cache; + DcmElement *delem = NULL; + OFCondition cond; + + cond = dset->findAndGetElement(DCM_EncapsulatedDocument, delem); + if (cond.bad()) return cond; + + cond = sequentialOverlappingRead(delem, &cache, buffer); + if (cond.bad()) return cond; + + cond = dset->findAndGetElement(DCM_RWavePointer, delem); + if (cond.bad()) return cond; + + cond = sequentialOverlappingRead(delem, &cache, buffer); + if (cond.bad()) return cond; + + cond = dset->findAndGetElement(DCM_TableOfPixelValues, delem); + if (cond.bad()) return cond; + + cond = sequentialOverlappingRead(delem, &cache, buffer); + if (cond.bad()) return cond; + + cond = dset->findAndGetElement(DCM_TableOfYBreakPoints, delem); + if (cond.bad()) return cond; + + cond = sequentialOverlappingRead(delem, &cache, buffer); + + return cond; +} + +static OFCondition randomRead(DcmDataset *dset, unsigned char *buffer) +{ + DcmFileCache cache; + DcmElement *delem = NULL; + OFCondition cond; + + cond = dset->findAndGetElement(DCM_EncapsulatedDocument, delem); + if (cond.bad()) return cond; + + cond = randomRead(delem, &cache, buffer); + if (cond.bad()) return cond; + + cond = dset->findAndGetElement(DCM_RWavePointer, delem); + if (cond.bad()) return cond; + + cond = randomRead(delem, &cache, buffer); + if (cond.bad()) return cond; + + cond = dset->findAndGetElement(DCM_TableOfPixelValues, delem); + if (cond.bad()) return cond; + + cond = randomRead(delem, &cache, buffer); + if (cond.bad()) return cond; + + cond = dset->findAndGetElement(DCM_TableOfYBreakPoints, delem); + if (cond.bad()) return cond; + + cond = randomRead(delem, &cache, buffer); + + return cond; +} + +OFTEST(dcmdata_partialElementAccess) +{ + // TODO TODO TODO TODO??? +#ifdef HAVE_GUSI_H + GUSISetup(GUSIwithSIOUXSockets); + GUSISetup(GUSIwithInternetSockets); +#endif + + /* make sure data dictionary is loaded */ + if (!dcmDataDict.isDictionaryLoaded()) + { + OFCHECK_FAIL("no data dictionary loaded, check environment variable: " DCM_DICT_ENVIRONMENT_VARIABLE); + return; + } + + OFLOG_DEBUG(tstpreadLogger, "Creating test dataset"); + + DcmFileFormat dfile; + + unsigned char *buffer = new unsigned char[BUFSIZE]; + unsigned char *bufptr = buffer; + srand(OFstatic_cast(unsigned int, time(NULL))); + for (int i = BUFSIZE; i; --i) + { + *bufptr++ = OFstatic_cast(unsigned char, rand()); + } + + createTestDataset(dfile.getDataset(), buffer); + OFCondition cond = EC_Normal; + + OFLOG_DEBUG(tstpreadLogger, "Writing test files"); + + cond = dfile.saveFile("test_be.dcm", EXS_BigEndianExplicit); + if (cond.bad()) { OFCHECK_FAIL(cond.text()); } + cond = dfile.saveFile("test_le.dcm", EXS_LittleEndianExplicit); + if (cond.bad()) { OFCHECK_FAIL(cond.text()); } +#ifdef WITH_ZLIB + cond = dfile.saveFile("test_df.dcm", EXS_DeflatedLittleEndianExplicit); + if (cond.bad()) { OFCHECK_FAIL(cond.text()); } +#endif + + OFLOG_DEBUG(tstpreadLogger, "Opening test files"); + + DcmFileFormat dfile_be; + DcmFileFormat dfile_le; + DcmFileFormat dfile_df; + + cond = dfile_be.loadFile("test_be.dcm"); + if (cond.bad()) { OFCHECK_FAIL(cond.text()); } + + cond = dfile_le.loadFile("test_le.dcm"); + if (cond.bad()) { OFCHECK_FAIL(cond.text()); } + +#ifdef WITH_ZLIB + cond = dfile_df.loadFile("test_df.dcm"); + if (cond.bad()) { OFCHECK_FAIL(cond.text()); } +#endif + + // testing sequential, non overlapping reads of partial element values + OFLOG_DEBUG(tstpreadLogger, "Testing sequential, non overlapping reads of partial element values"); + + cond = sequentialNonOverlappingRead(dfile_be.getDataset(), buffer); + if (cond.bad()) { OFCHECK_FAIL(cond.text()); } + + cond = sequentialNonOverlappingRead(dfile_le.getDataset(), buffer); + if (cond.bad()) { OFCHECK_FAIL(cond.text()); } + +#ifdef WITH_ZLIB + cond = sequentialNonOverlappingRead(dfile_df.getDataset(), buffer); + if (cond.bad()) { OFCHECK_FAIL(cond.text()); } +#endif + + // testing random reads of partial element values + OFLOG_DEBUG(tstpreadLogger, "Testing random reads of partial element values"); + + cond = randomRead(dfile_be.getDataset(), buffer); + if (cond.bad()) { OFCHECK_FAIL(cond.text()); } + + cond = randomRead(dfile_le.getDataset(), buffer); + if (cond.bad()) { OFCHECK_FAIL(cond.text()); } + +#ifdef WITH_ZLIB + cond = randomRead(dfile_df.getDataset(), buffer); + if (cond.bad()) { OFCHECK_FAIL(cond.text()); } +#endif + + // testing overlapping reads of partial element values + OFLOG_DEBUG(tstpreadLogger, "Testing overlapping reads of partial element values"); + + cond = sequentialOverlappingRead(dfile_be.getDataset(), buffer); + if (cond.bad()) { OFCHECK_FAIL(cond.text()); } + + cond = sequentialOverlappingRead(dfile_le.getDataset(), buffer); + if (cond.bad()) { OFCHECK_FAIL(cond.text()); } + +#ifdef WITH_ZLIB + cond = sequentialOverlappingRead(dfile_df.getDataset(), buffer); + if (cond.bad()) { OFCHECK_FAIL(cond.text()); } +#endif + + unlink("test_be.dcm"); + unlink("test_le.dcm"); +#ifdef WITH_ZLIB + unlink("test_df.dcm"); +#endif + delete[] buffer; +} diff --git a/dcmdata/tests/tspchrs.cc b/dcmdata/tests/tspchrs.cc new file mode 100644 index 00000000..ae4dae7a --- /dev/null +++ b/dcmdata/tests/tspchrs.cc @@ -0,0 +1,191 @@ +/* + * + * Copyright (C) 2011-2013, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Joerg Riesmeier + * + * Purpose: test program for class DcmSpecificCharacterSet + * + */ + + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/ofstd/oftest.h" +#include "dcmtk/dcmdata/dcspchrs.h" +#include "dcmtk/dcmdata/dctypes.h" + + +OFTEST(dcmdata_specificCharacterSet_1) +{ + DcmSpecificCharacterSet converter; + if (converter.isConversionLibraryAvailable()) + { + // try to select all DICOM character sets without code extensions + OFCHECK(converter.selectCharacterSet("").good()); + OFCHECK(converter.selectCharacterSet("ISO_IR 6 ").good()); + OFCHECK(converter.selectCharacterSet("ISO_IR 100").good()); + OFCHECK(converter.selectCharacterSet("ISO_IR 101").good()); + OFCHECK(converter.selectCharacterSet("ISO_IR 109").good()); + OFCHECK(converter.selectCharacterSet("ISO_IR 110").good()); + OFCHECK(converter.selectCharacterSet("ISO_IR 144").good()); + OFCHECK(converter.selectCharacterSet("ISO_IR 127").good()); + OFCHECK(converter.selectCharacterSet("ISO_IR 126").good()); + OFCHECK(converter.selectCharacterSet("ISO_IR 138").good()); + OFCHECK(converter.selectCharacterSet("ISO_IR 148").good()); + OFCHECK(converter.selectCharacterSet("ISO_IR 13 ").good()); + OFCHECK(converter.selectCharacterSet("ISO_IR 166").good()); + OFCHECK(converter.selectCharacterSet("ISO_IR 192").good()); + OFCHECK(converter.selectCharacterSet(" GB18030 ").good()); + // try to select all DICOM character sets with code extensions + OFCHECK(converter.selectCharacterSet("\\ISO 2022 IR 6 ").good()); + OFCHECK(converter.selectCharacterSet("\\ISO 2022 IR 100").good()); + OFCHECK(converter.selectCharacterSet("\\ISO 2022 IR 101").good()); + OFCHECK(converter.selectCharacterSet("\\ISO 2022 IR 109").good()); + OFCHECK(converter.selectCharacterSet("\\ISO 2022 IR 110").good()); + OFCHECK(converter.selectCharacterSet("\\ISO 2022 IR 144").good()); + OFCHECK(converter.selectCharacterSet("\\ISO 2022 IR 127").good()); + OFCHECK(converter.selectCharacterSet("\\ISO 2022 IR 126").good()); + OFCHECK(converter.selectCharacterSet("\\ISO 2022 IR 138").good()); + OFCHECK(converter.selectCharacterSet("\\ISO 2022 IR 148").good()); + OFCHECK(converter.selectCharacterSet("\\ISO 2022 IR 13 ").good()); + OFCHECK(converter.selectCharacterSet("\\ISO 2022 IR 166").good()); + OFCHECK(converter.selectCharacterSet("\\ISO 2022 IR 87" ).good()); + OFCHECK(converter.selectCharacterSet("\\ISO 2022 IR 159").good()); + OFCHECK(converter.selectCharacterSet("\\ISO 2022 IR 149").good()); + // the following should fail + OFCHECK(converter.selectCharacterSet("DCMTK").bad()); + OFCHECK(converter.selectCharacterSet(" \\ ").bad()); + OFCHECK(converter.selectCharacterSet("\\ISO 2022 IR 999").bad()); + OFCHECK(converter.selectCharacterSet("\\ISO_IR 100").bad()); + OFCHECK(converter.selectCharacterSet("ISO 2022 IR 87\\ISO 2022 IR 100").bad()); + OFCHECK(converter.selectCharacterSet("ISO 2022 IR 159\\ISO 2022 IR 100").bad()); + OFCHECK(converter.selectCharacterSet("ISO 2022 IR 149\\ISO 2022 IR 100").bad()); + // the following should work + OFCHECK(converter.selectCharacterSet("ISO 2022 IR 6\\ISO 2022 IR 100").good()); + OFCHECK(converter.selectCharacterSet("ISO 2022 IR 100\\ISO 2022 IR 126").good()); + OFCHECK(converter.selectCharacterSet("ISO 2022 IR 144\\ISO 2022 IR 138").good()); + // use a different destination character set than the default (UTF-8) + OFCHECK(converter.selectCharacterSet("", "ISO_IR 100").good()); + OFCHECK(converter.selectCharacterSet("ISO_IR 6", "ISO_IR 100").good()); + OFCHECK(converter.selectCharacterSet("ISO_IR 192", " ISO_IR 100 ").good()); + OFCHECK(converter.selectCharacterSet("ISO_IR 192", "ISO 2022 IR 100\\ISO 2022 IR 126").bad()); + } else { + // in case there is no libiconv, report a warning but do not fail + DCMDATA_WARN("Cannot test DcmSpecificCharacterSet since the underlying character set conversion library is not available"); + } +} + +OFTEST(dcmdata_specificCharacterSet_2) +{ + DcmSpecificCharacterSet converter; + if (converter.isConversionLibraryAvailable()) + { + OFString resultStr; + // check whether string conversion from Latin-1 to UTF-8 works + OFCHECK(converter.selectCharacterSet("ISO_IR 100").good()); + OFCHECK(converter.convertString("J\366rg", resultStr).good()); + OFCHECK_EQUAL(resultStr, "J\303\266rg"); + OFCHECK(converter.convertString("J\351r\364me", resultStr).good()); + OFCHECK_EQUAL(resultStr, "J\303\251r\303\264me"); + // check whether string conversion from UTF-8 to UTF-8 works :-) + OFCHECK(converter.selectCharacterSet("ISO_IR 192").good()); + OFCHECK(converter.convertString("J\303\266rg", resultStr).good()); + OFCHECK_EQUAL(resultStr, "J\303\266rg"); + OFCHECK(converter.convertString("J\303\251r\303\264me", resultStr).good()); + OFCHECK_EQUAL(resultStr, "J\303\251r\303\264me"); + // the following should fail + converter.clear(); + OFCHECK(converter.convertString("Some Text", resultStr).bad()); + } else { + // in case there is no libiconv, report a warning but do not fail + DCMDATA_WARN("Cannot test DcmSpecificCharacterSet since the underlying character set conversion library is not available"); + } +} + + +OFTEST(dcmdata_specificCharacterSet_3) +{ + DcmSpecificCharacterSet converter; + if (converter.isConversionLibraryAvailable()) + { + OFString resultStr; + // we need the PN delimiters for a standard comformant conversion + const OFString delimiters("\\^="); + // check whether string conversion from Japanese language to UTF-8 works + // example taken from DICOM PS 3.5 Annex H.3.1 + OFCHECK(converter.selectCharacterSet("\\ISO 2022 IR 87").good()); + OFCHECK(converter.convertString("Yamada^Tarou=\033$B;3ED\033(B^\033$BB@O:\033(B=\033$B$d$^$@\033(B^\033$B$?$m$&\033(B", resultStr, delimiters).good()); + OFCHECK_EQUAL(resultStr, "Yamada^Tarou=\345\261\261\347\224\260^\345\244\252\351\203\216=\343\202\204\343\201\276\343\201\240^\343\201\237\343\202\215\343\201\206"); + // example taken from DICOM PS 3.5 Annex H.3.2 + OFCHECK(converter.selectCharacterSet("ISO 2022 IR 13\\ISO 2022 IR 87").good()); + OFCHECK(converter.convertString("\324\317\300\336^\300\333\263=\033$B;3ED\033(J^\033$BB@O:\033(J=\033$B$d$^$@\033(J^\033$B$?$m$&\033(J", resultStr, delimiters).good()); + OFCHECK_EQUAL(resultStr, "\357\276\224\357\276\217\357\276\200\357\276\236^\357\276\200\357\276\233\357\275\263=\345\261\261\347\224\260^\345\244\252\351\203\216=\343\202\204\343\201\276\343\201\240^\343\201\237\343\202\215\343\201\206"); + // check whether string conversion from Korean language to UTF-8 works + // example taken from DICOM PS 3.5 Annex I.2 + OFCHECK(converter.selectCharacterSet("\\ISO 2022 IR 149").good()); + OFCHECK(converter.convertString("Hong^Gildong=\033$)C\373\363^\033$)C\321\316\324\327=\033$)C\310\253^\033$)C\261\346\265\277", resultStr, delimiters).good()); + OFCHECK_EQUAL(resultStr, "Hong^Gildong=\346\264\252^\345\220\211\346\264\236=\355\231\215^\352\270\270\353\217\231"); + // check whether string conversion from Chinese language to UTF-8 works + // example taken from DICOM PS 3.5 Annex J.2 + OFCHECK(converter.selectCharacterSet("GB18030").good()); + OFCHECK(converter.convertString("Wang^XiaoDong=\315\365^\320\241\266\253=", resultStr, delimiters).good()); + OFCHECK_EQUAL(resultStr, "Wang^XiaoDong=\347\216\213^\345\260\217\344\270\234="); + // check whether CR and LF are detected correctly + OFCHECK(converter.selectCharacterSet("\\ISO 2022 IR 13").good()); + OFCHECK(converter.convertString("Japanese\r\033(J\324\317\300\336\nText", resultStr).good()); + OFCHECK_EQUAL(resultStr, "Japanese\015\357\276\224\357\276\217\357\276\200\357\276\236\012Text"); + // same with '\' (backslash), which is used for separating multiple values + OFCHECK(converter.selectCharacterSet("\\ISO 2022 IR 13").good()); + OFCHECK(converter.convertString("Japanese\\\033(J\324\317\300\336\\Text", resultStr, "\\").good()); + OFCHECK_EQUAL(resultStr, "Japanese\\\357\276\224\357\276\217\357\276\200\357\276\236\\Text"); + // the following should fail (wrong character set) + OFCHECK(converter.selectCharacterSet("\\ISO 2022 IR 166").good()); + OFCHECK(converter.convertString("Yamada^Tarou=\033$B;3ED\033(B^\033$BB@O:\033(B=\033$B$d$^$@\033(B^\033$B$?$m$&\033(B", resultStr, delimiters).bad()); + } else { + // in case there is no libiconv, report a warning but do not fail + DCMDATA_WARN("Cannot test DcmSpecificCharacterSet since the underlying character set conversion library is not available"); + } +} + + +OFTEST(dcmdata_specificCharacterSet_4) +{ + DcmSpecificCharacterSet converter; + if (converter.isConversionLibraryAvailable()) + { + OFString resultStr; + // check whether string conversion from UTF-8 to Latin-1 works + OFCHECK(converter.selectCharacterSet("ISO_IR 192", "ISO_IR 100").good()); + OFCHECK(converter.convertString("J\303\266rg", resultStr).good()); + OFCHECK_EQUAL(resultStr, "J\366rg"); + OFCHECK(converter.convertString("J\303\251r\303\264me", resultStr).good()); + OFCHECK_EQUAL(resultStr, "J\351r\364me"); + // the following should fail + OFCHECK(converter.selectCharacterSet("\\ISO 2022 IR 87", "ISO_IR 100").good()); + OFCHECK(converter.convertString("Yamada^Tarou=\033$B;3ED\033(B^\033$BB@O:\033(B=\033$B$d$^$@\033(B^\033$B$?$m$&\033(B", resultStr).bad()); + OFCHECK(converter.selectCharacterSet("ISO_IR 100", "").good()); + OFCHECK(converter.convertString("J\366rg", resultStr).bad()); + // the following should work + OFCHECK(converter.selectCharacterSet("ISO_IR 100", "", OFTrue /*transliterate*/).good()); + OFCHECK(converter.convertString("J\366rg", resultStr).good()); + OFCHECK_EQUAL(resultStr, "J\"org"); + OFCHECK(converter.selectCharacterSet("ISO_IR 100", "", OFFalse /*transliterate*/, OFTrue /*discardIllegal*/).good()); + OFCHECK(converter.convertString("J\366rg", resultStr).good()); + OFCHECK_EQUAL(resultStr, "Jrg"); // discard mode removes characters that cannot be "translated" + } else { + // in case there is no libiconv, report a warning but do not fail + DCMDATA_WARN("Cannot test DcmSpecificCharacterSet since the underlying character set conversion library is not available"); + } +} diff --git a/dcmdata/tests/tstrval.cc b/dcmdata/tests/tstrval.cc new file mode 100644 index 00000000..9c059b5a --- /dev/null +++ b/dcmdata/tests/tstrval.cc @@ -0,0 +1,67 @@ +/* + * + * Copyright (C) 2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Joerg Riesmeier + * + * Purpose: test program for various "string value" methods + * + */ + + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/ofstd/oftest.h" +#include "dcmtk/dcmdata/dcelem.h" + + +OFTEST(dcmdata_determineVM) +{ + OFCHECK_EQUAL(DcmElement::determineVM(NULL, 0), 0); + OFCHECK_EQUAL(DcmElement::determineVM("", 0), 0); + OFCHECK_EQUAL(DcmElement::determineVM(" ", 1), 1); + OFCHECK_EQUAL(DcmElement::determineVM("\\", 1), 2); + OFCHECK_EQUAL(DcmElement::determineVM("1\\2", 3), 2); + OFCHECK_EQUAL(DcmElement::determineVM("1\\2\\", 4), 3); + OFCHECK_EQUAL(DcmElement::determineVM("\\2\\3\\", 5), 4); + OFCHECK_EQUAL(DcmElement::determineVM("1\\\\\\4", 5), 4); + /* also test with embedded NULL byte */ + OFCHECK_EQUAL(DcmElement::determineVM("1\\\\\\\04", 6), 4); +} + +OFTEST(dcmdata_getValueFromString) +{ + OFString str; + /* simple test */ + OFCHECK_EQUAL(DcmElement::getValueFromString("1\\2\\3\\4", 0, 7, str), 2); + OFCHECK_EQUAL(str, "1"); + OFCHECK_EQUAL(DcmElement::getValueFromString("1\\2\\3\\4", 2, 7, str), 4); + OFCHECK_EQUAL(str, "2"); + OFCHECK_EQUAL(DcmElement::getValueFromString("1\\2\\3\\4", 4, 7, str), 6); + OFCHECK_EQUAL(str, "3"); + OFCHECK_EQUAL(DcmElement::getValueFromString("1\\2\\3\\4", 6, 7, str), 8); + OFCHECK_EQUAL(str, "4"); + /* boundary test */ + OFCHECK_EQUAL(DcmElement::getValueFromString("\\aa\\bbb\\", 0, 8, str), 1); + OFCHECK_EQUAL(str, ""); + OFCHECK_EQUAL(DcmElement::getValueFromString("\\aa\\bbb\\", 1, 8, str), 4); + OFCHECK_EQUAL(str, "aa"); + OFCHECK_EQUAL(DcmElement::getValueFromString("\\aa\\bbb\\", 4, 8, str), 8); + OFCHECK_EQUAL(str, "bbb"); + OFCHECK_EQUAL(DcmElement::getValueFromString("\\aa\\bbb\\", 8, 8, str), 8); + OFCHECK_EQUAL(str, ""); + /* test with embedded NULL byte */ + OFCHECK_EQUAL(DcmElement::getValueFromString("\\aa\\b\0bb\\", 4, 9, str), 9); + OFCHECK_EQUAL(str, OFString("b\0bb", 4)); +} diff --git a/dcmdata/tests/tvrcomp.cc b/dcmdata/tests/tvrcomp.cc new file mode 100644 index 00000000..b7e8dcdf --- /dev/null +++ b/dcmdata/tests/tvrcomp.cc @@ -0,0 +1,488 @@ +/* + * + * Copyright (C) 2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: ofstd + * + * Author: Michael Onken + * + * Purpose: test program for compare() method of VR classes + * + */ + + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#define OFTEST_OFSTD_ONLY +#include "dcmtk/ofstd/oftest.h" +#include "dcmtk/dcmdata/dcvras.h" +#include "dcmtk/dcmdata/dcvrae.h" +#include "dcmtk/dcmdata/dcchrstr.h" +#include "dcmtk/dcmdata/dcvrlo.h" +#include "dcmtk/dcmdata/dcvrlt.h" +#include "dcmtk/dcmdata/dcvrpn.h" +#include "dcmtk/dcmdata/dcvrst.h" +#include "dcmtk/dcmdata/dcvrut.h" +#include "dcmtk/dcmdata/dcvras.h" +#include "dcmtk/dcmdata/dcvrcs.h" +#include "dcmtk/dcmdata/dcvrda.h" +#include "dcmtk/dcmdata/dcvrdt.h" +#include "dcmtk/dcmdata/dcvrds.h" +#include "dcmtk/dcmdata/dcvris.h" +#include "dcmtk/dcmdata/dcvrtm.h" +#include "dcmtk/dcmdata/dcvrui.h" +#include "dcmtk/dcmdata/dcelem.h" +#include "dcmtk/dcmdata/dcitem.h" +#include "dcmtk/dcmdata/dcsequen.h" +#include "dcmtk/dcmdata/dcvrat.h" +#include "dcmtk/dcmdata/dcvrfd.h" +#include "dcmtk/dcmdata/dcvrfl.h" +#include "dcmtk/dcmdata/dcvrobow.h" +#include "dcmtk/dcmdata/dcvrsl.h" +#include "dcmtk/dcmdata/dcvrss.h" +#include "dcmtk/dcmdata/dcvrul.h" +#include "dcmtk/dcmdata/dcvrus.h" +#include "dcmtk/dcmdata/dcdeftag.h" +#include "dcmtk/dcmdata/dcpxitem.h" +#include "dcmtk/dcmdata/dcvrpobw.h" +#include "dcmtk/dcmdata/dcovlay.h" +#include "dcmtk/dcmdata/dcpixel.h" + + +template +static void checkByteString(const DcmTagKey& key) +{ + // Start with equal values + OFString val1 = "TEST"; + OFString val2 = "TEST"; + ByteStringType obj1(key); + ByteStringType obj2(key); + ByteStringType objOtherTag(DCM_UndefinedTagKey); + + // Check equality + obj1.putOFStringArray("TEST"); + obj2.putOFStringArray("TEST"); + OFCHECK_EQUAL(obj1.compare(obj2), 0); + // Reverse test should yield same result + OFCHECK_EQUAL(obj2.compare(obj1), 0); + + // Check differing tags (DCM_UndefinedTagKey always smaller than any other key) + objOtherTag.putOFStringArray("TEST" /* same value*/); + OFCHECK(obj1.compare(objOtherTag) < 0); + // Reverse test should yield opposite result + OFCHECK(objOtherTag.compare(obj1) > 0); + + // Check second string longer + obj2.putOFStringArray("TEST_LONG"); + OFCHECK(obj1.compare(obj2) < 0); + // Reverse test should yield opposite result + OFCHECK(obj2.compare(obj1) > 0); + + // Test different VM + obj1.putOFStringArray("TEST\\TEST"); + obj2.putOFStringArray("TEST\\TEST\\TEST"); + OFCHECK(obj1.compare(obj2) < 0); + // Reverse test should yield opposite result + OFCHECK(obj2.compare(obj1) > 0); +} + + +static void checkAttributeTags() +{ + // Start with equal values + DcmAttributeTag obj1(DCM_FrameIncrementPointer); + DcmAttributeTag obj2(DCM_FrameIncrementPointer); + DcmAttributeTag objOtherTag(DCM_UndefinedTagKey); + + // Check equality + obj1.putTagVal(DcmTagKey(0010,0010)); + obj2.putTagVal(DcmTagKey(0010,0010)); + OFCHECK_EQUAL(obj1.compare(obj2), 0); + // Reverse test should yield same result + OFCHECK_EQUAL(obj2.compare(obj1), 0); + + // Check differing tags (DCM_UndefinedTagKey always smaller than any other key) + objOtherTag.putTagVal(DcmTagKey(0010,0010)); + OFCHECK(obj1.compare(objOtherTag) < 0); + // Reverse test should yield opposite result + OFCHECK(objOtherTag.compare(obj1) > 0); + + // Check second attribute larger + obj2.putTagVal(DcmTagKey(0010,0020)); + OFCHECK(obj1.compare(obj2) < 0); + // Reverse test should yield opposite result + OFCHECK(obj2.compare(obj1) > 0); + + // Test different VM + obj1.putTagVal(DcmTagKey(0010,0010), 1); // VM = 2 + obj2.putTagVal(DcmTagKey(0010,0010), 0); + obj2.putTagVal(DcmTagKey(0010,0010), 1); + obj2.putTagVal(DcmTagKey(0010,0010), 2); // VM = 3 + + OFCHECK(obj1.compare(obj2) < 0); + // Reverse test should yield opposite result + OFCHECK(obj2.compare(obj1) > 0); +} + + +static void checkFloatingPointDouble() +{ + // Start with equal values + DcmFloatingPointDouble obj1(DCM_RealWorldValueLUTData); + DcmFloatingPointDouble obj2(DCM_RealWorldValueLUTData); + DcmFloatingPointDouble objOtherTag(DCM_UndefinedTagKey); + + // Check equality + obj1.putFloat64(10.0); + obj2.putFloat64(10.0); + OFCHECK_EQUAL(obj1.compare(obj2), 0); + // Reverse test should yield same result + OFCHECK_EQUAL(obj2.compare(obj1), 0); + + // Check differing tags (DCM_UndefinedTagKey always smaller than any other key) + objOtherTag.putFloat64(10.0); + OFCHECK(obj1.compare(objOtherTag) < 0); + // Reverse test should yield opposite result + OFCHECK(objOtherTag.compare(obj1) > 0); + + // Check second attribute larger + obj2.putFloat64(100.50); + OFCHECK(obj1.compare(obj2) < 0); + // Reverse test should yield opposite result + OFCHECK(obj2.compare(obj1) > 0); + + // Test different VM + obj1.putFloat64(10.0); // VM = 2 + obj2.putFloat64(10.0, 0); + obj2.putFloat64(10.0, 1); + obj2.putFloat64(10.0, 2); // VM = 3 + + OFCHECK(obj1.compare(obj2) < 0); + // Reverse test should yield opposite result + OFCHECK(obj2.compare(obj1) > 0); +} + + +static void checkFloatingPointSingle() +{ + // Start with equal values + DcmFloatingPointSingle obj1(DCM_CornealPointLocation); + DcmFloatingPointSingle obj2(DCM_CornealPointLocation); + DcmFloatingPointSingle objOtherTag(DCM_UndefinedTagKey); + + // Check equality + obj1.putFloat32(10.0); + obj2.putFloat32(10.0); + OFCHECK_EQUAL(obj1.compare(obj2), 0); + // Reverse test should yield same result + OFCHECK_EQUAL(obj2.compare(obj1), 0); + + // Check differing tags (DCM_UndefinedTagKey always smaller than any other key) + objOtherTag.putFloat32(10.0); + OFCHECK(obj1.compare(objOtherTag) < 0); + // Reverse test should yield opposite result + OFCHECK(objOtherTag.compare(obj1) > 0); + + // Check second attribute larger + obj2.putFloat32(100.50); + OFCHECK(obj1.compare(obj2) < 0); + // Reverse test should yield opposite result + OFCHECK(obj2.compare(obj1) > 0); + + // Test different VM + obj1.putFloat32(10.0); // VM = 2 + obj2.putFloat32(10.0, 0); + obj2.putFloat32(10.0, 1); + obj2.putFloat32(10.0, 2); // VM = 3 + + OFCHECK(obj1.compare(obj2) < 0); + // Reverse test should yield opposite result + OFCHECK(obj2.compare(obj1) > 0); +} + +template +static void checkOtherByteOtherWord(const DcmTagKey& tagKey) +{ + // Start with equal values + BinaryOBOWType obj1(tagKey); + BinaryOBOWType obj2(tagKey); + BinaryOBOWType objOtherTag(DCM_UndefinedTagKey); + + // Check equality + Uint8 testData[1] = {100}; + obj1.putUint8Array(testData, 1); + obj2.putUint8Array(testData, 1); + OFCHECK_EQUAL(obj1.compare(obj2), 0); + // Reverse test should yield same result + OFCHECK_EQUAL(obj2.compare(obj1), 0); + + // Check differing tags (DCM_UndefinedTagKey always smaller than any other key) + objOtherTag.putUint8Array(testData, 1); + OFCHECK(obj1.compare(objOtherTag) < 0); + // Reverse test should yield opposite result + OFCHECK(objOtherTag.compare(obj1) > 0); + + // Check second attribute larger + Uint8 biggerTestData[1] = {101}; + obj2.putUint8Array(biggerTestData, 1); + OFCHECK(obj1.compare(obj2) < 0); + // Reverse test should yield opposite result + OFCHECK(obj2.compare(obj1) > 0); + + // Test different VM + Uint8 largeVMTestData[2] = {100, 101}; + Uint8 evenLargerVMTestData[3] = {100, 101, 102}; + obj1.putUint8Array(largeVMTestData, 2); // VM = 2 + obj2.putUint8Array(evenLargerVMTestData, 3); // VM = 3 + + OFCHECK(obj1.compare(obj2) < 0); + // Reverse test should yield opposite result + OFCHECK(obj2.compare(obj1) > 0); +} + + +static void checkSignedLong() +{ + // Start with equal values + DcmSignedLong obj1(DCM_SelectorSLValue); + DcmSignedLong obj2(DCM_SelectorSLValue); + DcmSignedLong objOtherTag(DCM_UndefinedTagKey); + + // Check equality + obj1.putSint32(-10); + obj2.putSint32(-10); + OFCHECK_EQUAL(obj1.compare(obj2), 0); + // Reverse test should yield same result + OFCHECK_EQUAL(obj2.compare(obj1), 0); + + // Check differing tags (DCM_UndefinedTagKey always smaller than any other key) + objOtherTag.putSint32(-10); + OFCHECK(obj1.compare(objOtherTag) < 0); + // Reverse test should yield opposite result + OFCHECK(objOtherTag.compare(obj1) > 0); + + // Check second attribute larger + obj2.putSint32(-5); + OFCHECK(obj1.compare(obj2) < 0); + // Reverse test should yield opposite result + OFCHECK(obj2.compare(obj1) > 0); + + // Test different VM + obj1.putSint32(-10); // VM = 2 + obj2.putSint32(-10, 0); + obj2.putSint32(-10, 1); + obj2.putSint32(-10, 2); // VM = 3 + + OFCHECK(obj1.compare(obj2) < 0); + // Reverse test should yield opposite result + OFCHECK(obj2.compare(obj1) > 0); +} + + +static void checkSignedShort() +{ + // Start with equal values + DcmSignedShort obj1(DCM_SelectorSSValue); + DcmSignedShort obj2(DCM_SelectorSSValue); + DcmSignedShort objOtherTag(DCM_UndefinedTagKey); + + // Check equality + obj1.putSint16(-10); + obj2.putSint16(-10); + OFCHECK_EQUAL(obj1.compare(obj2), 0); + // Reverse test should yield same result + OFCHECK_EQUAL(obj2.compare(obj1), 0); + + // Check differing tags (DCM_UndefinedTagKey always smaller than any other key) + objOtherTag.putSint16(-10); + OFCHECK(obj1.compare(objOtherTag) < 0); + // Reverse test should yield opposite result + OFCHECK(objOtherTag.compare(obj1) > 0); + + // Check second attribute larger + obj2.putSint16(-5); + OFCHECK(obj1.compare(obj2) < 0); + // Reverse test should yield opposite result + OFCHECK(obj2.compare(obj1) > 0); + + // Test different VM + obj1.putSint16(-10); // VM = 2 + obj2.putSint16(-10, 0); + obj2.putSint16(-10, 1); + obj2.putSint16(-10, 2); // VM = 3 + + OFCHECK(obj1.compare(obj2) < 0); + // Reverse test should yield opposite result + OFCHECK(obj2.compare(obj1) > 0); +} + + +static void checkUnsignedLong() +{ + // Start with equal values + DcmUnsignedLong obj1(DCM_SelectorULValue); + DcmUnsignedLong obj2(DCM_SelectorULValue); + DcmUnsignedLong objOtherTag(DCM_UndefinedTagKey); + + // Check equality + obj1.putUint32(10); + obj2.putUint32(10); + OFCHECK_EQUAL(obj1.compare(obj2), 0); + // Reverse test should yield same result + OFCHECK_EQUAL(obj2.compare(obj1), 0); + + // Check differing tags (DCM_UndefinedTagKey always smaller than any other key) + objOtherTag.putUint32(10); + OFCHECK(obj1.compare(objOtherTag) < 0); + // Reverse test should yield opposite result + OFCHECK(objOtherTag.compare(obj1) > 0); + + // Check second attribute larger + obj2.putUint32(10000); + OFCHECK(obj1.compare(obj2) < 0); + // Reverse test should yield opposite result + OFCHECK(obj2.compare(obj1) > 0); + + // Test different VM + obj1.putUint32(10); // VM = 2 + obj2.putUint32(10, 0); + obj2.putUint32(10, 1); + obj2.putUint32(10, 2); // VM = 3 + + OFCHECK(obj1.compare(obj2) < 0); + // Reverse test should yield opposite result + OFCHECK(obj2.compare(obj1) > 0); +} + + +static void checkUnsignedShort() +{ + // Start with equal values + DcmUnsignedShort obj1(DCM_SelectorUSValue); + DcmUnsignedShort obj2(DCM_SelectorUSValue); + DcmUnsignedShort objOtherTag(DCM_UndefinedTagKey); + + // Check equality + obj1.putUint16(10); + obj2.putUint16(10); + OFCHECK_EQUAL(obj1.compare(obj2), 0); + // Reverse test should yield same result + OFCHECK_EQUAL(obj2.compare(obj1), 0); + + // Check differing tags (DCM_UndefinedTagKey always smaller than any other key) + objOtherTag.putUint16(10); + OFCHECK(obj1.compare(objOtherTag) < 0); + // Reverse test should yield opposite result + OFCHECK(objOtherTag.compare(obj1) > 0); + + // Check second attribute larger + obj2.putUint16(10000); + OFCHECK(obj1.compare(obj2) < 0); + // Reverse test should yield opposite result + OFCHECK(obj2.compare(obj1) > 0); + + // Test different VM + obj1.putUint16(10); // VM = 2 + obj2.putUint16(10, 0); + obj2.putUint16(10, 1); + obj2.putUint16(10, 2); // VM = 3 + + OFCHECK(obj1.compare(obj2) < 0); + // Reverse test should yield opposite result + OFCHECK(obj2.compare(obj1) > 0); +} + + +static void checkDcmItemAndSequences() +{ + // Start with equal values + DcmItem obj1; + DcmItem obj2; + + obj1.putAndInsertUint16(DcmTagKey(0x0028,0x0010) /* Rows */, 10); + obj1.putAndInsertUint16(DcmTagKey(0x0028,0x0020) /* Columns */, 10); + obj2.putAndInsertUint16(DcmTagKey(0x0028,0x0010) /* Rows */, 10); + obj2.putAndInsertUint16(DcmTagKey(0x0028,0x0020) /* Columns */, 10); + + // Check equality + OFCHECK_EQUAL(obj1.compare(obj2), 0); + // Reverse test should yield same result + OFCHECK_EQUAL(obj2.compare(obj1), 0); + + // Check values in second item larger + obj2.putAndInsertUint16(DcmTagKey(0x0028,0x0010) /* Rows */, 100); + obj2.putAndInsertUint16(DcmTagKey(0x0028,0x0020) /* Columns */, 100); + OFCHECK(obj1.compare(obj2) < 0); + // Reverse test should yield opposite result + OFCHECK(obj2.compare(obj1) > 0); + + // Test different VM (i.e. item cardinality): + // obj1 has VM = 2 + // Make obj2 VM = 3 by adding another tag + obj2.insertEmptyElement(DcmTagKey(0x7fe0,0x0010) /* Pixel Data */); + + OFCHECK(obj1.compare(obj2) < 0); + // Reverse test should yield opposite result + OFCHECK(obj2.compare(obj1) > 0); + + // Check sequences + + DcmSequenceOfItems seq1(DCM_AnatomicRegionModifierSequence); + obj2.findAndDeleteElement(DCM_PixelData); // reset obj2 + seq1.insert(new DcmItem(obj1)); + seq1.insert(new DcmItem(obj2)); + DcmSequenceOfItems seq2(DCM_AnatomicRegionModifierSequence); + seq2.insert(new DcmItem(obj1)); + seq2.insert(new DcmItem(obj2)); + + // Check equality + OFCHECK_EQUAL(seq1.compare(seq2), 0); + // Reverse test should yield same result + OFCHECK_EQUAL(seq2.compare(seq1), 0); + + // Test different VM (i.e. sequence cardinality): + // seq1 has VM = 2 + // Make seq2 VM = 3 by adding another item + seq2.insertAtCurrentPos(new DcmItem());; + + OFCHECK(seq1.compare(seq2) < 0); + // Reverse test should yield opposite result + OFCHECK(seq2.compare(seq1) > 0); +} + + +OFTEST(dcmdata_VRCompare) +{ + // Check the different VRs implemented by DcmByteString. + // We gracefully ignore the maximum VM here since there is not + // even an attribute (e.g.) at the moment which is of VR + // AS and has a VM >1. + checkByteString(DCM_PatientAge); + checkByteString(DCM_RetrieveAETitle); + checkByteString(DCM_SeriesDescription); + checkByteString(DCM_AdditionalPatientHistory); + checkByteString(DCM_OtherPatientNames); + checkByteString(DCM_RTPlanDescription); + checkByteString(DCM_RetrieveURL); + checkAttributeTags(); + checkFloatingPointDouble(); + checkFloatingPointSingle(); + checkOtherByteOtherWord(DCM_PixelData); + checkOtherByteOtherWord(DCM_PixelData); + checkOtherByteOtherWord(DCM_OverlayData); + checkOtherByteOtherWord(DCM_PixelData); + checkSignedLong(); + checkSignedShort(); + checkUnsignedLong(); + checkUnsignedShort(); + checkDcmItemAndSequences(); +} diff --git a/dcmdata/tests/tvrdatim.cc b/dcmdata/tests/tvrdatim.cc new file mode 100644 index 00000000..16d21cfa --- /dev/null +++ b/dcmdata/tests/tvrdatim.cc @@ -0,0 +1,144 @@ +/* + * + * Copyright (C) 2002-2013, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Joerg Riesmeier + * + * Purpose: test program for classes DcmDate, DcmTime and DcmDateTime + * + */ + + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/ofstd/oftest.h" +#include "dcmtk/dcmdata/dcvrda.h" +#include "dcmtk/dcmdata/dcvrtm.h" +#include "dcmtk/dcmdata/dcvrdt.h" +#include "dcmtk/dcmdata/dcdeftag.h" + +#define CHECK_EQUAL(string) do { \ + strstream << OFStringStream_ends; \ + OFSTRINGSTREAM_GETOFSTRING(strstream, res); \ + OFCHECK_EQUAL(res, string); \ + strstream.clear(); \ + strstream.str(""); \ +} while (0) +#define CHECK_STREAM_EQUAL(val, string) do { \ + strstream << val; \ + CHECK_EQUAL(string); \ + strstream.clear(); \ + strstream.str(""); \ +} while(0) + +OFTEST(dcmdata_dateTime) +{ + double timeZone; + OFDate dateVal; + OFTime timeVal; + OFDateTime dateTime; + OFString string; + DcmDate dcmDate(DCM_StudyDate); + DcmTime dcmTime(DCM_StudyTime); + DcmDateTime dcmDateTime(DCM_DateTime); + OFOStringStream strstream; + + // Determine the local time zone, needed because setOFTime loses the timezone + timeVal.setCurrentTime(); + const double localTimeZone = timeVal.getTimeZone(); + + OFDate curDateVal(2011, 5, 9); + OFTime curTimeVal(10, 35, 20, localTimeZone); + OFDateTime curDateTimeVal(curDateVal, curTimeVal); + + dcmDate.setOFDate(curDateVal); + dcmDate.print(strstream); + CHECK_EQUAL("(0008,0020) DA [20110509] # 8, 1 StudyDate\n"); + OFCHECK(dcmDate.getOFDate(dateVal).good()); + OFCHECK_EQUAL(dateVal, curDateVal); + + dcmTime.setOFTime(curTimeVal); + dcmTime.print(strstream); + CHECK_EQUAL("(0008,0030) TM [103520] # 6, 1 StudyTime\n"); + OFCHECK(dcmTime.getOFTime(timeVal).good()); + OFCHECK_EQUAL(timeVal, curTimeVal); + + dcmDateTime.setOFDateTime(curDateTimeVal); + dcmDateTime.print(strstream); + CHECK_EQUAL("(0040,a120) DT [20110509103520] # 14, 1 DateTime\n"); + OFCHECK(dcmDateTime.getOFDateTime(dateTime).good()); + OFCHECK_EQUAL(dateTime, curDateTimeVal); + OFCHECK(dateTime.getISOFormattedDateTime(string, OFTrue /*seconds*/, OFTrue /*fraction*/, OFFalse /*timeZone*/, OFFalse /*delimiter*/)); + OFCHECK_EQUAL(string, "20110509103520.000000"); + + dcmTime.putString("12"); + dcmTime.print(strstream); + CHECK_EQUAL("(0008,0030) TM [12] # 2, 1 StudyTime\n"); + OFCHECK(dcmTime.getOFTime(timeVal).good()); + CHECK_STREAM_EQUAL(timeVal, "12:00:00"); + + dcmTime.putString("1203"); + dcmTime.print(strstream); + CHECK_EQUAL("(0008,0030) TM [1203] # 4, 1 StudyTime\n"); + OFCHECK(dcmTime.getOFTime(timeVal).good()); + CHECK_STREAM_EQUAL(timeVal, "12:03:00"); + + dcmTime.putString("120315"); + dcmTime.print(strstream); + CHECK_EQUAL("(0008,0030) TM [120315] # 6, 1 StudyTime\n"); + OFCHECK(dcmTime.getOFTime(timeVal).good()); + CHECK_STREAM_EQUAL(timeVal, "12:03:15"); + dcmTime.putString("120301.99"); + dcmTime.print(strstream); + CHECK_EQUAL("(0008,0030) TM [120301.99] # 10, 1 StudyTime\n"); + OFCHECK(dcmTime.getOFTime(timeVal).good()); + timeVal.getISOFormattedTime(string, OFTrue /*seconds*/, OFTrue /*fraction*/, OFFalse /*timeZone*/); + OFCHECK_EQUAL(string, "12:03:01.990000"); + + dcmTime.putString("12:03"); + dcmTime.print(strstream); + CHECK_EQUAL("(0008,0030) TM [12:03] # 6, 1 StudyTime\n"); + OFCHECK(dcmTime.getOFTime(timeVal).good()); + CHECK_STREAM_EQUAL(timeVal, "12:03:00"); + dcmTime.putString("12:03:15"); + dcmTime.print(strstream); + CHECK_EQUAL("(0008,0030) TM [12:03:15] # 8, 1 StudyTime\n"); + OFCHECK(dcmTime.getOFTime(timeVal).good()); + CHECK_STREAM_EQUAL(timeVal, "12:03:15"); + + OFCHECK(DcmTime::getTimeZoneFromString("+0030", timeZone).good()); + OFCHECK_EQUAL(timeZone, 0.5); + OFCHECK(DcmTime::getTimeZoneFromString("+1130", timeZone).good()); + OFCHECK_EQUAL(timeZone, 11.5); + OFCHECK(DcmTime::getTimeZoneFromString("-0100", timeZone).good()); + OFCHECK_EQUAL(timeZone, -1); + OFCHECK(DcmTime::getTimeZoneFromString("-0530", timeZone).good()); + OFCHECK_EQUAL(timeZone, -5.5); + OFCHECK(DcmTime::getTimeZoneFromString("01130", timeZone).bad()); + OFCHECK(DcmTime::getTimeZoneFromString("+100", timeZone).bad()); + OFCHECK(DcmTime::getTimeZoneFromString("UTC+1", timeZone).bad()); + + dcmDateTime.putString("200204101203+0500"); + dcmDateTime.print(strstream); + CHECK_EQUAL("(0040,a120) DT [200204101203+0500] # 18, 1 DateTime\n"); + OFCHECK(dcmDateTime.getOFDateTime(dateTime).good()); + CHECK_STREAM_EQUAL(dateTime, "2002-04-10 12:03:00"); + + dcmDateTime.putString("20020410"); + dcmDateTime.print(strstream); + CHECK_EQUAL("(0040,a120) DT [20020410] # 8, 1 DateTime\n"); + OFCHECK(dcmDateTime.getOFDateTime(dateTime).good()); + dateTime.getISOFormattedDateTime(string, OFTrue /*seconds*/, OFFalse /*fraction*/, OFFalse /*timeZone*/); + OFCHECK_EQUAL(string, "2002-04-10 00:00:00"); +} diff --git a/dcmdata/tests/tvrds.cc b/dcmdata/tests/tvrds.cc new file mode 100644 index 00000000..8c3a15ff --- /dev/null +++ b/dcmdata/tests/tvrds.cc @@ -0,0 +1,91 @@ +/* + * + * Copyright (C) 2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Joerg Riesmeier + * + * Purpose: test program for class DcmDecimalString + * + */ + + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/ofstd/oftest.h" +#include "dcmtk/dcmdata/dcvrds.h" +#include "dcmtk/dcmdata/dcdeftag.h" + + +OFTEST(dcmdata_decimalString_1) +{ + DcmDecimalString decStr(DCM_ContourData); + OFVector doubleVals; + OFCHECK(decStr.putString("1\\2.0\\3.5\\-4.99\\+500.005\\6.66E-01").good()); + OFCHECK(decStr.getFloat64Vector(doubleVals).good()); + OFCHECK_EQUAL(doubleVals.size(), 6); + OFCHECK_EQUAL(doubleVals[0], 1); + OFCHECK_EQUAL(doubleVals[1], 2); + OFCHECK_EQUAL(doubleVals[2], 3.5); + OFCHECK_EQUAL(doubleVals[3], -4.99); + OFCHECK_EQUAL(doubleVals[4], 500.005); + OFCHECK_EQUAL(doubleVals[5], 0.666); +} + +OFTEST(dcmdata_decimalString_2) +{ + DcmDecimalString decStr(DCM_ContourData); + OFVector doubleVals; + /* insert a NULL byte into the string */ + OFCHECK(decStr.putString("1\\2.0\\3.5\\-4.99\0\\+500.005\\6.66E-01", 34).good()); + OFCHECK(decStr.getFloat64Vector(doubleVals).good()); + OFCHECK_EQUAL(doubleVals.size(), 6); + OFCHECK_EQUAL(doubleVals[0], 1); + OFCHECK_EQUAL(doubleVals[1], 2); + OFCHECK_EQUAL(doubleVals[2], 3.5); + OFCHECK_EQUAL(doubleVals[3], -4.99); + OFCHECK_EQUAL(doubleVals[4], 500.005); + OFCHECK_EQUAL(doubleVals[5], 0.666); +} + +OFTEST(dcmdata_decimalString_3) +{ + DcmDecimalString decStr(DCM_ContourData); + OFVector doubleVals; + /* insert a NULL byte into the string */ + OFCHECK(decStr.putOFStringArray(OFString("1\\2.0\\3.5\\-4.99\0\\+500.005\\6.66E-01", 34)).good()); + OFCHECK(decStr.getFloat64Vector(doubleVals).good()); + OFCHECK_EQUAL(doubleVals.size(), 6); + OFCHECK_EQUAL(doubleVals[0], 1); + OFCHECK_EQUAL(doubleVals[1], 2); + OFCHECK_EQUAL(doubleVals[2], 3.5); + OFCHECK_EQUAL(doubleVals[3], -4.99); + OFCHECK_EQUAL(doubleVals[4], 500.005); + OFCHECK_EQUAL(doubleVals[5], 0.666); +} + +OFTEST(dcmdata_decimalString_4) +{ + DcmDecimalString decStr(DCM_ContourData); + OFVector doubleVals; + OFCHECK(decStr.putString("1\\2.0\\3.5\\-4.99\\+500.005\\6.66E-01\\").good()); + OFCHECK_EQUAL(decStr.getVM(), 7); + OFCHECK(decStr.putString("\\1\\2.0\\3.5\\-4.99\\+500.005\\6.66E-01").good()); + OFCHECK_EQUAL(decStr.getVM(), 7); + OFCHECK(decStr.putString("1\\2.0\\3.5\\-4.99\\ \\+500.005\\6.66E-01").good()); + OFCHECK_EQUAL(decStr.getVM(), 7); + /* insert an invalid value into the string */ + OFCHECK(decStr.putString("1\\2.0\\3.5\\-4.99\\ - \\+500.005\\6.66E-01").good()); + OFCHECK(decStr.getFloat64Vector(doubleVals).bad()); + OFCHECK_EQUAL(doubleVals.size(), 4); +} diff --git a/dcmdata/tests/tvrfd.cc b/dcmdata/tests/tvrfd.cc new file mode 100644 index 00000000..45fd48df --- /dev/null +++ b/dcmdata/tests/tvrfd.cc @@ -0,0 +1,63 @@ +/* + * + * Copyright (C) 2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Joerg Riesmeier + * + * Purpose: test program for class DcmFloatingPointDouble + * + */ + + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/ofstd/oftest.h" +#include "dcmtk/dcmdata/dcvrfd.h" +#include "dcmtk/dcmdata/dcdeftag.h" + + +OFTEST(dcmdata_floatingPointDouble) +{ + Float64 value; + DcmFloatingPointDouble floatDouble(DCM_InversionTimes); + /* append new values */ + OFCHECK(floatDouble.putFloat64(1.1, 0).good()); + OFCHECK(floatDouble.putFloat64(2.2, 1).good()); + OFCHECK(floatDouble.putFloat64(3.3, 2).good()); + OFCHECK(floatDouble.putFloat64(4.4, 3).good()); + OFCHECK(floatDouble.putFloat64(5.5, 5).bad()); + /* check number of values */ + OFCHECK_EQUAL(floatDouble.getVM(), 4); + /* check all set values */ + OFCHECK(floatDouble.getFloat64(value, 0).good()); + OFCHECK_EQUAL(value, 1.1); + OFCHECK(floatDouble.getFloat64(value, 1).good()); + OFCHECK_EQUAL(value, 2.2); + OFCHECK(floatDouble.getFloat64(value, 2).good()); + OFCHECK_EQUAL(value, 3.3); + OFCHECK(floatDouble.getFloat64(value, 3).good()); + OFCHECK_EQUAL(value, 4.4); + /* change existing values */ + OFCHECK(floatDouble.putFloat64(22.22, 1).good()); + OFCHECK(floatDouble.putFloat64(33.33, 2).good()); + /* check again all set values */ + OFCHECK(floatDouble.getFloat64(value, 0).good()); + OFCHECK_EQUAL(value, 1.1); + OFCHECK(floatDouble.getFloat64(value, 1).good()); + OFCHECK_EQUAL(value, 22.22); + OFCHECK(floatDouble.getFloat64(value, 2).good()); + OFCHECK_EQUAL(value, 33.33); + OFCHECK(floatDouble.getFloat64(value, 3).good()); + OFCHECK_EQUAL(value, 4.4); +} diff --git a/dcmdata/tests/tvrpn.cc b/dcmdata/tests/tvrpn.cc new file mode 100644 index 00000000..b251fad0 --- /dev/null +++ b/dcmdata/tests/tvrpn.cc @@ -0,0 +1,86 @@ +/* + * + * Copyright (C) 2011-2012, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Michael Onken + * + * Purpose: test program for class DcmPersonName + * + */ + + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/ofstd/oftest.h" +#include "dcmtk/dcmdata/dcvrpn.h" + + +OFTEST(dcmdata_personName) +{ + /* test getComponentGroup()*/ + OFString resultStr; + OFCHECK( DcmPersonName::getComponentGroup("Eichelberg^Marco^^Dr.=Onken^Michael^=Riesmeier^J\366rg^^Dr.^", 0, resultStr).good() ); + OFCHECK_EQUAL(resultStr, "Eichelberg^Marco^^Dr."); + OFCHECK( DcmPersonName::getComponentGroup("Eichelberg^Marco^^Dr.=Onken^Michael^=Riesmeier^J\366rg^^Dr.^", 1, resultStr).good() ); + OFCHECK_EQUAL(resultStr, "Onken^Michael^"); + OFCHECK( DcmPersonName::getComponentGroup("Eichelberg^Marco^^Dr.=Onken^Michael^=Riesmeier^J\366rg^^Dr.^", 2, resultStr).good() ); + OFCHECK_EQUAL(resultStr, "Riesmeier^J\366rg^^Dr.^"); + + OFCHECK( DcmPersonName::getComponentGroup("=Onken^Michael^", 1, resultStr).good() ); + OFCHECK_EQUAL(resultStr, "Onken^Michael^"); + OFCHECK( DcmPersonName::getComponentGroup("==Riesmeier^J\366rg^^Dr.^", 2, resultStr).good() ); + OFCHECK_EQUAL(resultStr, "Riesmeier^J\366rg^^Dr.^"); + + OFCHECK( DcmPersonName::getComponentGroup("", 0, resultStr).good() ); + OFCHECK_EQUAL(resultStr, ""); + OFCHECK( DcmPersonName::getComponentGroup("Riesmeier^J\366rg^^Dr.^==", 0, resultStr).good() ); + OFCHECK_EQUAL(resultStr, "Riesmeier^J\366rg^^Dr.^"); + + OFCHECK( DcmPersonName::getComponentGroup("Eichelberg^Marco", 1, resultStr).bad() ); + OFCHECK( DcmPersonName::getComponentGroup("Onken^Michael^=Riesmeier^J\366rg^^Dr.^", 2, resultStr).bad() ); + OFCHECK( DcmPersonName::getComponentGroup("=Onken^Michael^=Riesmeier^J\366rg^^Dr.^", 0, resultStr).good() ); + OFCHECK_EQUAL(resultStr, ""); + + /* test getComponentsFromString(). So far only minimal tests to assure + * changes to getComponentGroup does not introduce problems + */ + OFString l, f, m, p, s; + OFCHECK( DcmPersonName::getNameComponentsFromString("Eichelberg^Marco^^Dr.=Onken^Michael^=Riesmeier^J\366rg^^Dr.^", l,f,m,p,s, 0).good()); + OFCHECK_EQUAL(l, "Eichelberg"); + OFCHECK_EQUAL(f, "Marco"); + OFCHECK_EQUAL(m, ""); + OFCHECK_EQUAL(p, "Dr."); + OFCHECK_EQUAL(s, ""); + + OFCHECK( DcmPersonName::getNameComponentsFromString("Eichelberg^Marco^^Dr.=Onken^Michael^=Riesmeier^J\366rg^^Dr.^", l,f,m,p,s, 1).good()); + OFCHECK_EQUAL(l, "Onken"); + OFCHECK_EQUAL(f, "Michael"); + OFCHECK_EQUAL(m, ""); + OFCHECK_EQUAL(p, ""); + OFCHECK_EQUAL(s, ""); + + OFCHECK( DcmPersonName::getNameComponentsFromString("Eichelberg^Marco^^Dr.=Onken^Michael^=Riesmeier^J\366rg^^Dr.^", l,f,m,p,s, 2).good()); + OFCHECK_EQUAL(l, "Riesmeier"); + OFCHECK_EQUAL(f, "J\366rg"); + OFCHECK_EQUAL(m, ""); + OFCHECK_EQUAL(p, "Dr."); + OFCHECK_EQUAL(s, ""); + + OFCHECK( DcmPersonName::getNameComponentsFromString("Eichelberg^Marco^^Dr.=Onken^Michael^=Riesmeier^J\366rg^^Dr.^", l,f,m,p,s, 2).good()); + OFCHECK_EQUAL(l, "Riesmeier"); + OFCHECK_EQUAL(f, "J\366rg"); + OFCHECK_EQUAL(m, ""); + OFCHECK_EQUAL(p, "Dr."); + OFCHECK_EQUAL(s, ""); +} diff --git a/dcmdata/tests/tvrui.cc b/dcmdata/tests/tvrui.cc new file mode 100644 index 00000000..4e83bcfd --- /dev/null +++ b/dcmdata/tests/tvrui.cc @@ -0,0 +1,85 @@ +/* + * + * Copyright (C) 2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Joerg Riesmeier + * + * Purpose: test program for class DcmUniqueIdentifier + * + */ + + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/ofstd/oftest.h" +#include "dcmtk/dcmdata/dcvrui.h" +#include "dcmtk/dcmdata/dcdeftag.h" + + +OFTEST(dcmdata_uniqueIdentifier_1) +{ + /* test UI value with 0-byte padding */ + OFString value; + DcmUniqueIdentifier sopInstanceUID(DCM_SOPInstanceUID); + dcmEnableAutomaticInputDataCorrection.set(OFTrue); + OFCHECK(sopInstanceUID.putString("1.2.3.4\0", 8).good()); + OFCHECK(sopInstanceUID.checkValue("1").good()); + OFCHECK(sopInstanceUID.getOFString(value, 0).good()); + OFCHECK_EQUAL(value, "1.2.3.4"); + // switch automatic data correct off + dcmEnableAutomaticInputDataCorrection.set(OFFalse); + OFCHECK(sopInstanceUID.putString("1.2.3.4\\5.6.7.8").good()); + OFCHECK(sopInstanceUID.checkValue("2").good()); + OFCHECK(sopInstanceUID.putString("1.2.3.4\\5.6.7.8\0", 16).good()); + // the trailing 0-byte is still there, which leads to an error + OFCHECK(sopInstanceUID.checkValue("2").bad()); + OFCHECK(sopInstanceUID.getOFString(value, 1 /*, normalize = OFTrue */).good()); + OFCHECK_EQUAL(value, "5.6.7.8"); + OFCHECK(sopInstanceUID.getOFString(value, 1, OFFalse /*normalize*/).good()); + OFCHECK_EQUAL(value, OFString("5.6.7.8\0", 8)); +} + + +OFTEST(dcmdata_uniqueIdentifier_2) +{ + /* test UI value with space character padding */ + OFString value; + DcmUniqueIdentifier sopInstanceUID(DCM_SOPInstanceUID); + dcmEnableAutomaticInputDataCorrection.set(OFTrue); + OFCHECK(sopInstanceUID.putString("1.2.3.4 ").good()); + OFCHECK(sopInstanceUID.checkValue("1").good()); + OFCHECK(sopInstanceUID.putString("1.2.3.4 ").good()); + OFCHECK(sopInstanceUID.checkValue("1").good()); + OFCHECK(sopInstanceUID.getOFString(value, 0).good()); + OFCHECK_EQUAL(value, "1.2.3.4"); + // we also accept leading and embedded space characters + OFCHECK(sopInstanceUID.putString(" 1.2.3.4 ").good()); + OFCHECK(sopInstanceUID.checkValue("1").good()); + OFCHECK(sopInstanceUID.putString("1.2. 3.4").good()); + OFCHECK(sopInstanceUID.checkValue("1").good()); + OFCHECK(sopInstanceUID.getOFString(value, 0).good()); + OFCHECK_EQUAL(value, "1.2.3.4"); + // switch automatic data correct off + dcmEnableAutomaticInputDataCorrection.set(OFFalse); + OFCHECK(sopInstanceUID.putString("1.2.3.4 ").good()); + OFCHECK(sopInstanceUID.checkValue("1").bad()); + OFCHECK(sopInstanceUID.getOFString(value, 0).good()); + OFCHECK_EQUAL(value, "1.2.3.4 "); + OFCHECK(sopInstanceUID.putString("1.2.3.4\\5.6.7.8 ").good()); + OFCHECK(sopInstanceUID.checkValue("2").bad()); + OFCHECK(sopInstanceUID.getOFString(value, 0).good()); + OFCHECK_EQUAL(value, "1.2.3.4"); + OFCHECK(sopInstanceUID.getOFString(value, 1).good()); + OFCHECK_EQUAL(value, "5.6.7.8 "); +} diff --git a/dcmfg/CMakeLists.txt b/dcmfg/CMakeLists.txt new file mode 100644 index 00000000..48559a49 --- /dev/null +++ b/dcmfg/CMakeLists.txt @@ -0,0 +1,10 @@ +# declare project +PROJECT(dcmfg) + +# declare include directories which hold for all subdirectories +INCLUDE_DIRECTORIES(${dcmfg_SOURCE_DIR}/include ${dcmiod_SOURCE_DIR}/include ${dcmdata_SOURCE_DIR}/include ${ofstd_SOURCE_DIR}/include ${oflog_SOURCE_DIR}/include ${ZLIB_INCDIR}) + +# recurse into subdirectories +FOREACH(SUBDIR libsrc include) + ADD_SUBDIRECTORY(${SUBDIR}) +ENDFOREACH(SUBDIR) diff --git a/dcmfg/Makefile.in b/dcmfg/Makefile.in new file mode 100644 index 00000000..9851281d --- /dev/null +++ b/dcmfg/Makefile.in @@ -0,0 +1,85 @@ +# +# Makefile for dcmiod +# + +@SET_MAKE@ + +SHELL = /bin/sh +VPATH = @srcdir@:@top_srcdir@/include:@top_srcdir@/@configdir@/include +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +configdir = @top_srcdir@/@configdir@ + +include $(configdir)/@common_makefile@ + + +all: include-all libsrc-all tests-all + +install: install-doc install-support + +install-doc: docs-install + +install-data: data-install + +install-etc: etc-install + +install-include: include-install + +install-lib: libsrc-install install-include + +install-support: install-data install-etc + + +include-all: + (cd include && $(MAKE) ARCH="$(ARCH)" all) + +libsrc-all: include-all + (cd libsrc && $(MAKE) ARCH="$(ARCH)" all) + +tests-all: libsrc-all + (cd tests && $(MAKE) ARCH="$(ARCH)" all) + +check: tests-all + (cd tests && $(MAKE) check) + +check-exhaustive: tests-all + (cd tests && $(MAKE) check-exhaustive) + + +include-install: + (cd include && $(MAKE) ARCH="$(ARCH)" install) + +libsrc-install: libsrc-all + (cd libsrc && $(MAKE) ARCH="$(ARCH)" install) + +docs-install: + (cd docs && $(MAKE) install) + +data-install: + (cd data && $(MAKE) install) + +etc-install: + (cd etc && $(MAKE) install) + + +clean: + (cd include && $(MAKE) clean) + (cd libsrc && $(MAKE) clean) + (cd tests && $(MAKE) clean) + (cd docs && $(MAKE) clean) + (cd data && $(MAKE) clean) + (cd etc && $(MAKE) clean) + rm -f $(TRASH) + +distclean: + (cd include && $(MAKE) distclean) + (cd libsrc && $(MAKE) distclean) + (cd tests && $(MAKE) distclean) + (cd docs && $(MAKE) distclean) + (cd data && $(MAKE) distclean) + (cd etc && $(MAKE) distclean) + rm -f $(DISTTRASH) + +dependencies: + (cd libsrc && touch $(DEP) && $(MAKE) dependencies) +# (cd tests && touch $(DEP) && $(MAKE) dependencies) diff --git a/dcmfg/configure b/dcmfg/configure new file mode 100755 index 00000000..425e8d6d --- /dev/null +++ b/dcmfg/configure @@ -0,0 +1,56 @@ +#! /bin/sh + +parentdir=`pwd` +thisdir=$parentdir + +# The following test constructs relative path from the module +# directory to the configuration directory. If you know this path +# you can substitute this with +# configdir= +# It is very important that the configdir path is relative. + +configdir="configdir" + +while test "$parentdir" != "/" -a "$configdir" = "configdir"; do + if test -d "$parentdir/config" ; then + configdir=$parentdir/config + else + parentdir=`echo $parentdir | sed 's/\/[^\/]*$//'` + fi +done + +if test "$configdir" = "configdir" ; then + echo "Cannot find configure directory" + exit 1 +fi + +if test $# != 0; then + case $1 in + -a) + shift + cd "$configdir" + echo "running configure in config-directory" + ./configure $* + cd $thisdir + echo "running configure for this module" + sh "$configdir/confmod" --srcdir=. $* + ;; + -c) + shift + cd "$configdir" + echo "running configure in config-directory" + ./configure $* + ;; + *) + echo "running configure for this module" + sh "$configdir/confmod" --srcdir=. $* + ;; + esac +else + echo "running configure for this module" + sh "$configdir/confmod" --srcdir=. $* +fi + + + + diff --git a/dcmfg/data/Makefile.in b/dcmfg/data/Makefile.in new file mode 100644 index 00000000..007da889 --- /dev/null +++ b/dcmfg/data/Makefile.in @@ -0,0 +1,23 @@ +# +# Makefile for dcmfg/data +# + +@SET_MAKE@ + +SHELL = /bin/sh +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +configdir = @top_srcdir@/@configdir@ + +include $(configdir)/@common_makefile@ + + +all: + +install: + +clean: + rm -f $(TRASH) + +distclean: + rm -f $(DISTTRASH) diff --git a/dcmfg/docs/Makefile.in b/dcmfg/docs/Makefile.in new file mode 100644 index 00000000..d44d05da --- /dev/null +++ b/dcmfg/docs/Makefile.in @@ -0,0 +1,23 @@ +# +# Makefile for dcmfg/docs +# + +@SET_MAKE@ + +SHELL = /bin/sh +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +configdir = @top_srcdir@/@configdir@ + +include $(configdir)/@common_makefile@ + + +all: + +install: + +clean: + rm -f $(TRASH) + +distclean: + rm -f $(DISTTRASH) diff --git a/dcmfg/docs/dcmfg.dox b/dcmfg/docs/dcmfg.dox new file mode 100644 index 00000000..989c540f --- /dev/null +++ b/dcmfg/docs/dcmfg.dox @@ -0,0 +1,14 @@ +/*! + +\page mod_dcmfg dcmfg: a library for working with functional groups + +This module contains classes to deal with DICOM Functional Groups as they are +used in objects of the "Enhanced" family in DICOM. Some but not all functional +groups have been implemented. However, unknown groups can be read and written, +and modified using a low(er) level access method. + +The main classes are (in alphabetical order): +\li \b FGBase +\li \b FGInterface + +*/ diff --git a/dcmfg/etc/Makefile.in b/dcmfg/etc/Makefile.in new file mode 100644 index 00000000..808115cc --- /dev/null +++ b/dcmfg/etc/Makefile.in @@ -0,0 +1,23 @@ +# +# Makefile for dcmfg/etc +# + +@SET_MAKE@ + +SHELL = /bin/sh +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +configdir = @top_srcdir@/@configdir@ + +include $(configdir)/@common_makefile@ + + +all: + +install: + +clean: + rm -f $(TRASH) + +distclean: + rm -f $(DISTTRASH) diff --git a/dcmfg/include/CMakeLists.txt b/dcmfg/include/CMakeLists.txt new file mode 100644 index 00000000..516fa22a --- /dev/null +++ b/dcmfg/include/CMakeLists.txt @@ -0,0 +1,2 @@ +# declare installation files +INSTALL(DIRECTORY dcmtk/dcmfg DESTINATION ${DCMTK_INSTALL_INCDIR}/dcmtk COMPONENT include FILES_MATCHING PATTERN "*.h") diff --git a/dcmfg/include/Makefile.in b/dcmfg/include/Makefile.in new file mode 100644 index 00000000..23a4a91c --- /dev/null +++ b/dcmfg/include/Makefile.in @@ -0,0 +1,27 @@ +# +# Makefile for dcmfg/include +# + +@SET_MAKE@ + +SHELL = /bin/sh +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +configdir = @top_srcdir@/@configdir@ + +include $(configdir)/@common_makefile@ + + +all: + +install: + $(configdir)/mkinstalldirs $(DESTDIR)$(includedir)/dcmtk/dcmfg + for file in dcmtk/dcmfg/*.h ; do \ + $(INSTALL_DATA) $$file $(DESTDIR)$(includedir)/dcmtk/dcmfg ;\ + done + +clean: + rm -f $(TRASH) + +distclean: + rm -f $(DISTTRASH) diff --git a/dcmfg/include/dcmtk/dcmfg/fg.h b/dcmfg/include/dcmtk/dcmfg/fg.h new file mode 100644 index 00000000..5a78d0a7 --- /dev/null +++ b/dcmfg/include/dcmtk/dcmfg/fg.h @@ -0,0 +1,114 @@ +/* + * + * Copyright (C) 2015, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmfg + * + * Author: Michael Onken + * + * Purpose: Class for managing Functional Groups from a DICOM object + * + */ + +#ifndef FG_H +#define FG_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/ofstd/ofmap.h" +#include "dcmtk/dcmfg/fgtypes.h" +#include "dcmtk/dcmfg/fgbase.h" +#include "dcmtk/dcmdata/dctagkey.h" +#include "dcmtk/dcmdata/dcsequen.h" + + +// forward declaration +class FGBase; + +/** Class representing a list of functional groups where each type of group + * can only be once in the list. + */ +class DCMTK_DCMFG_EXPORT FunctionalGroups +{ + +public: + + /// Iterator type for iterating functional groups + typedef OFMap::iterator iterator; + + /// Const iterator type for iterating functional groups + typedef OFMap::const_iterator const_iterator; + + /** Constructor, creates empty set of functional groups + */ + FunctionalGroups(); + + /** Virtual desctructor, cleans up set of functional groups and + * frees the related memory + */ + virtual ~FunctionalGroups(); + + /** Cleans up set of functional groups and frees the related memory + */ + virtual void clear(); + + /** Find a functional group by its type + * @param fgType The type of the functional group + * @return The functional group, if found, NULL otherwise + */ + virtual FGBase* find(const DcmFGTypes::E_FGType fgType); + + /** Iterator pointing to first functional group in the set + * @return First functional group in set + */ + virtual FunctionalGroups::iterator begin(); + + /** Iterator pointing behind last functional group in the set + * @return Iterator pointing behind last functional group in the set + */ + virtual FunctionalGroups::iterator end(); + + /** Const iterator pointing to first functional group in the set + * @return First functional group in set + */ + virtual FunctionalGroups::const_iterator begin() const; + + /** Const iterator pointing behind last functional group in the set + * @return Iterator pointing behind last functional group in the set + */ + virtual FunctionalGroups::const_iterator end() const; + + /** Insert new functional group; ownership is taken over from caller if + * function call is successful. + * @param group The group to insert + * @param replaceOld If OFTrue, then the existing functional group of the + * same type (if existing) is deleted and replaced by the given one. + * @return EC_Normal, if insertion was successful, error otherwise. In the + * latter case, the caller keeps the ownership of the given object. + */ + virtual OFCondition insert(FGBase* group, + const OFBool replaceOld); + + /** Remove functional group specified by its type. The memory is not + * freed by the call but must freed by the caller using the returned pointer. + * @param fgType The type of the group to remove + * @return The functional group removed, or NULL, if not found + */ + virtual FGBase* remove(const DcmFGTypes::E_FGType fgType); + +private: + + /// Map holding the functional groups, one of each type at most + OFMap m_groups; + +}; + +#endif // FG_H diff --git a/dcmfg/include/dcmtk/dcmfg/fgbase.h b/dcmfg/include/dcmtk/dcmfg/fgbase.h new file mode 100644 index 00000000..19457a90 --- /dev/null +++ b/dcmfg/include/dcmtk/dcmfg/fgbase.h @@ -0,0 +1,258 @@ +/* + * + * Copyright (C) 2015, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmfg + * + * Author: Michael Onken + * + * Purpose: Base class(es) for functional groups + * + */ + +#ifndef FGBASE_H +#define FGBASE_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/ofstd/ofstd.h" +#include "dcmtk/dcmdata/dcitem.h" +#include "dcmtk/dcmfg/fgtypes.h" + +/** Abstract base class for deriving specific functional groups + */ +class DCMTK_DCMFG_EXPORT FGBase +{ + +public: + + /** Constructor, creates new functional group of given type. + * @param fgType The type of functional group to create + */ + FGBase(const DcmFGTypes::E_FGType fgType); + + /** Check whether functional group has valid and complete data + * @return EC_Normal, if check is ok, error otherwise + */ + virtual OFCondition check() const = 0; + + /** Read functional group from given item. Old data is overwritten. + * @param item The item to read from. This must contain the sequence + * element that uniquely identifies the functional group. + * @return EC_Normal if reading was successful, error otherwise + */ + virtual OFCondition read(DcmItem& item) = 0; + + /** Write functional group to given item. If the functional group already + * exists it is overwritten. + * @param item The item to write to. The method will write the sequence + * specific for the functional group into the item + * @return EC_Normal if writing was successful, error otherwise + */ + virtual OFCondition write(DcmItem& item) = 0; + + /** Find out whether functional group is potentially only shared, only + * per-frame or can be both + * @return The functional group "shared type" + */ + virtual DcmFGTypes::E_FGSharedType getSharedType() const =0; + + /** Return the type of this functional group + * @return The functional group's type + */ + virtual DcmFGTypes::E_FGType getType() const; + + /** Clear any data in the group + */ + virtual void clearData() =0; + + /** Virtual desctructor + */ + virtual ~FGBase(); + + /** Comparison operator that compares the normalized value of this object + * with a given object of the same type, i.e.\ the elements within both + * functional groups (this and rhs parameter) are compared by value! + * Both objects (this and rhs) need to have the same type (e.g.\ both + * FGDerivationImage) to be comparable. This function is used in order + * to decide whether a functional group already exists, or is new. This + * is used in particular to find out whether a given functional group + * can be shared (i.e.\ the same information already exists as shared + * functional group) or is different from the same shared group. In that + * case the shared functional group must be distributed into per-frame + * functional groups, instead. The exact implementation for implementing + * the comparison is not relevant. However, it must be a comparison + * by value. + * @param rhs the right hand side of the comparison + * @return 0 if the object values are equal. + * -1 if either the value of the first component that does not match + * is lower in the rhs object, or all compared components match + * but the rhs component is shorter. Also returned if this type and + * rhs type (DcmFGTypes::E_FGType) do not match. + * 1 if either the value of the first component that does not match + * is greater in the rhs object, or all compared components match + * but the rhs component is longer. + */ + virtual int compare(const FGBase& rhs) const = 0; + + /** Returs a deep copy of this object + * @return Deep copy of this object + */ + virtual FGBase *clone() const = 0; + +protected: + + /** Get the item containing the payload of a functional group sequence, + * identified by the functional group's sequence key provided and the desired + * item number. + * @param source The item to read the sequence from, e.g.\ item of the + * Shared Functional Group Sequence + * @param seqKey The identifying key of the functional group's sequence + * @param itemNum The item number to get from that sequence (usually, + * a functional group has exactly a single item, i.e.\ the parameter + * would be set to 0 + * @param result The item if found, otherwise NULL + * @return EC_Normal, if specified item could be retrieved, error otherwise + */ + virtual OFCondition getItemFromFGSequence(DcmItem& source, + const DcmTagKey& seqKey, + const unsigned long itemNum, + DcmItem*& result); + + /** Create functional group sequence specified by given sequence tag key + * @param destination The item to put the sequence into + * @param seqKey The functional group's tag key + * @param numItems The number of items to create within sequence (minus 1). + * Usually, functional group only contain a single item, + * i.e.\ numItems would be set to 0 + * @param firstItem Reference to the first item the method created + * @return EC_Normal if creation was successful, error otherwise + */ + virtual OFCondition createNewFGSequence(DcmItem& destination, + const DcmTagKey& seqKey, + const unsigned long numItems, + DcmItem*& firstItem); + +private: + + /// Private default constructor, shall not be used + FGBase(); + + /// The type of the functional group + DcmFGTypes::E_FGType m_fgType; + +}; + + +/** Class representing an "unknown" functional group, e.g.\ a private one + * specified by a vendor or one that is not explicitly known yet to the + * dcmfg library. + * The main purpose is to have a container for such functional groups that + * allows to read them into memory, access them using a low level API, and + * to be able to write store them back. + */ +class DCMTK_DCMFG_EXPORT FGUnknown : public FGBase +{ + +public: + + /** Creates unknown (to the dcmfg class library) functional group + * @param seqStartTag The tag that uniquely identifies this functional group + * @param sharedType Defines whether this group is potentially per-frame, + * shared or can be both. Default is "unknown". + */ + FGUnknown(const DcmTagKey& seqStartTag, + const DcmFGTypes::E_FGSharedType sharedType = DcmFGTypes::EFGS_UNKNOWN); + + /** Returns type of this functional group (always "EFG_UNKNOWN") + * @return Always returns DcmFGTypes::EFG_UNKNOWN + */ + virtual DcmFGTypes::E_FGType getType() const {return DcmFGTypes::EFG_UNKNOWN;} + + /** Returns whether this group is potentially per-frame, shared or can be both + * @return The functional group's "shared type" + */ + virtual DcmFGTypes::E_FGSharedType getSharedType() const {return m_sharedType;} + + /** Returs a deep copy of this object + * @return Deep copy of this object + */ + virtual FGBase *clone() const; + + /** Check whether this functional group contains valid data + * @returns EC_Normal if functional group is valid. For now, always returns + * EC_Normal + */ + virtual OFCondition check() const; + + /** Clear data within this group + */ + virtual void clearData(); + + /** Read this group into memory + * @param item The item to read from + */ + virtual OFCondition read(DcmItem& item); + + /** Write this group to given item + * @param item The item to write to + */ + virtual OFCondition write(DcmItem& item); + + /** Comparison operator that compares the normalized value of this object + * with a given object of the same type, i.e.\ the elements within both + * functional groups (this and rhs parameter) are compared by value! + * Both objects (this and rhs) need to have the same type (i.e.\ both + * FGUnknown) to be comparable. This function is used in order + * to decide whether a functional group already exists, or is new. This + * is used in particular to find out whether a given functional group + * can be shared (i.e.\ the same information already exists as shared + * functional group) or is different from the same shared group. In that + * case the shared functional group must be distributed into per-frame + * functional groups, instead. The exact implementation for implementing + * the comparison is not relevant. However, it must be a comparison + * by value. + * @param rhs the right hand side of the comparison + * @return 0 if the object values are equal. + * -1 if either the value of the first component that does not match + * is lower in the this object, or all compared components match + * but this component is shorter. Also returned if this type and + * rhs type (DcmFGTypes::E_FGType) do not match. + * 1 if either the value of the first component that does not match + * is greater in this object, or all compared components match + * but this component is longer. + */ + virtual int compare(const FGBase& rhs) const; + + /** Virtual desctructor, frees memory + */ + virtual ~FGUnknown(); + +private: + + /** Private default constructor, shall not be used + */ + FGUnknown(); + + /// The tag that uniquely identifies this functional group + DcmTagKey m_seqStartTag; + + /// The data hold by this item, i.e.\ the sequence making up the functional + /// group + DcmSequenceOfItems* m_fgSequence; + + /// Denotes whether this group is potentially per-frame, shared or can be both + DcmFGTypes::E_FGSharedType m_sharedType; + +}; + +#endif // FGBASE_H + diff --git a/dcmfg/include/dcmtk/dcmfg/fgdefine.h b/dcmfg/include/dcmtk/dcmfg/fgdefine.h new file mode 100644 index 00000000..72e2371a --- /dev/null +++ b/dcmfg/include/dcmtk/dcmfg/fgdefine.h @@ -0,0 +1,36 @@ +/* + * + * Copyright (C) 2015, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmfg + * + * Author: Michael Onken + * + * Purpose: Contains preprocessor definitions + * + */ + + +#ifndef FGDEFINE_H +#define FGDEFINE_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/ofstd/ofdefine.h" + + +#ifdef dcmfg_EXPORTS +#define DCMTK_DCMFG_EXPORT DCMTK_DECL_EXPORT +#else +#define DCMTK_DCMFG_EXPORT DCMTK_DECL_IMPORT +#endif + +#endif // FGDEFINE_H diff --git a/dcmfg/include/dcmtk/dcmfg/fgderimg.h b/dcmfg/include/dcmtk/dcmfg/fgderimg.h new file mode 100644 index 00000000..b892dca8 --- /dev/null +++ b/dcmfg/include/dcmtk/dcmfg/fgderimg.h @@ -0,0 +1,379 @@ +/* + * + * Copyright (C) 2015, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmfg + * + * Author: Michael Onken + * + * Purpose: Class for managing Derivation Image Functional Group + * + */ + + +#ifndef FGDERIMG_H +#define FGDERIMG_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/ofstd/ofvector.h" +#include "dcmtk/ofstd/ofstring.h" +#include "dcmtk/dcmiod/iodmacro.h" +#include "dcmtk/dcmfg/fgbase.h" + +/** Class representing a single item of the Source Image Sequence + */ +class DCMTK_DCMFG_EXPORT SourceImageItem +{ + +public: + + /** Constructor, constructs empty Source Image Sequence item + */ + SourceImageItem(); + + /** Virtual desctructor, cleans up memory + */ + virtual ~SourceImageItem(); + + /** Clears all data handled by this component + */ + virtual void clearData(); + + /** Check whether this item contains valid data + * @return EC_Normal if data is valid, error otherwise + */ + virtual OFCondition check() const; + + /** Return handle to to purpose of reference code + * @return EC_Normal if data is valid, error otherwise + */ + virtual CodeSequenceMacro& getPurposeOfReferenceCode(); + + /** Returns handle to to image sop instance reference + * @return EC_Normal if data is valid, error otherwise + */ + virtual ImageSOPInstanceReferenceMacro& getImageSOPInstanceReference(); + + /** Reads source image item from given item + * @return EC_Normal if reading was successful, error otherwise + */ + virtual OFCondition read(DcmItem& itemOfSourceImageSequence, + const OFBool clearOldData = OFTrue); + + /** Writes source image item to given item + * @return EC_Normal if writing was successful, error otherwise + */ + virtual OFCondition write(DcmItem& itemOfSourceImageSequence); + + + /** Comparison operator that compares the normalized value of this object + * with a given object of the same type, i.e.\ the elements within both + * functional groups (this and rhs parameter) are compared by value! + * Both objects (this and rhs) need to have the same type (i.e.\ both + * FGUnknown) to be comparable. This function is used in order + * to decide whether a functional group already exists, or is new. This + * is used in particular to find out whether a given functional group + * can be shared (i.e.\ the same information already exists as shared + * functional group) or is different from the same shared group. In that + * case the shared functional group must be distributed into per-frame + * functional groups, instead. The exact implementation for implementing + * the comparison is not relevant. However, it must be a comparison + * by value. + * @param rhs the right hand side of the comparison + * @return 0 if the object values are equal. + * -1 if either the value of the first component that does not match + * is lower in the this object, or all compared components match + * but this component is shorter. Also returned if this type and + * rhs type (DcmFGTypes::E_FGType) do not match. + * 1 if either the value of the first component that does not match + * is greater in this object, or all compared components match + * but this component is longer. + */ + virtual int compare(const SourceImageItem& rhs) const; + + /** Assignment operator, deletes old data + * @param rhs The item that should be assigned to "this" class + * @return Reference to "this" class + */ + SourceImageItem& operator=(const SourceImageItem& rhs); + +private: + + /// Describes purpose of reference (single item of Purpose of Reference Code + /// Sequence) + CodeSequenceMacro m_PurposeOfReferenceCode; + + /// Contains the referenced images (as represented by one of the items of + /// "this" Source Image Sequence) + ImageSOPInstanceReferenceMacro m_ImageSOPInstanceReference; +}; + +/// Iterator for traversing over items of the Source Image Sequence +typedef OFVector::iterator SourceImageIterator; + + +/** Class representing a single item in Derivation Image Sequence + */ +class DCMTK_DCMFG_EXPORT DerivationImageItem +{ +public: + + /** Constructor, initializes empty derivation image item + */ + DerivationImageItem(); + + /** Virtual desctructor + */ + virtual ~DerivationImageItem(); + + /** Assignment operator, deletes old data + * @param rhs The item that should be assigned to "this" class + * @return Reference to "this" class + */ + DerivationImageItem& operator=(const DerivationImageItem& rhs); + + /** Copy constructor, deletes old data + * @param rhs The item that should be used for initialization + */ + DerivationImageItem(const DerivationImageItem& rhs); + + /** Comparison operator that compares the normalized value of this object + * with a given object of the same type + * @param rhs The right hand side of the comparison + * @return 0 If the object values are equal. + * -1 if either the value of the first component that does not match + * is lower in the rhs object, or all compared components match + * but the rhs component is shorter. Also returned if rhs cannot be + * casted to DcmAttributeTag. + * 1 if either the value of the first component that does not match + * is greater in the rhs object, or all compared components match + * but the rhs component is longer. + */ + virtual int compare(const DerivationImageItem& rhs) const; + + /** Clears all data handled by this component + */ + virtual void clearData(); + + /** Check whether item contains valid data + * @return EC_Normal if item is valid, error otherwise + */ + virtual OFCondition check() const; + + /** Convenience function to add item representing reference to a file. No + * restrictions are set which frames or segments from this image has been + * actually used. However, such information could be added to the source + * image item later by modifying the resulting item being handed back to the + * caller. + * @param file Files that should be referenced by their UID, must be readable. + * @param purposeOfReference Code representing the purpose of reference + * (Defined CID 7202) + * @param resultSourceImageItem The created derivation image item if + * successful, NULL otherwise + * @return EC_Normal if adding works, error code otherwise + */ + virtual OFCondition addSourceImageItem(const OFString& file, + const CodeSequenceMacro& purposeOfReference, + SourceImageItem*& resultSourceImageItem); + + /** Convenience function to add items representing references to some files + * which all have the same purpose of reference (code). No restrictions are + * set which frames or segments from those images have been actually used. + * However, such information could be added to the source image item later by + * modifying the resulting item handed back to the caller. + * @param files List of files that should be referenced by their UIDs. + * @param purposeOfReference Code representing the purpose of reference + * (Defined CID 7202) + * @param resultSourceImageItems The created derivation image items (one per + * file) if successful, NULL otherwise + * @param skipFileErrors If OFTrue, then files that could not be added will + * not lead to error. + * @return EC_Normal if adding works, error code otherwise + */ + virtual OFCondition addSourceImageItems(const OFVector& files, + const CodeSequenceMacro& purposeOfReference, + OFVector& resultSourceImageItems, + const OFBool skipFileErrors = OFFalse); + + /** Get Derivation Description + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return status, EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getDerivationDescription(OFString &value, + const signed long pos = 0) const; + + /** Get reference to derivation code items + * @return Reference to derivation code items + */ + virtual OFVector& getDerivationCodeItems(); + + /** Get reference to source image itmes + * @return Reference to source image items + */ + virtual OFVector& getSourceImageItems(); + + /** Set Derivation Description + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR (ST) and VM (1) if + * enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setDerivationDescription(const OFString &value, + const OFBool checkValue = OFTrue); + + /** Read Derivation Image Sequence Item describing derivation from a + * set of images + * @param itemOfDerivationImageSequence The item to read from + * @param clearOldData If OFTrue, old data is deleted first + * @return EC_Normal if reading was successful, error otherwise + */ + virtual OFCondition read(DcmItem& itemOfDerivationImageSequence, + const OFBool clearOldData = OFTrue); + + /** Write Derivation Image Sequence Item describing derivation from a + * set of images + * @param itemOfDerivationImageSequence The item to write to + * @return EC_Normal if writing was successful, error otherwise + */ + virtual OFCondition write(DcmItem& itemOfDerivationImageSequence); + +private: + + // DICOM attributes. + // The comments for each attribute describe "Name: (VR, VM, Type)". + // See DICOM standard for further reference. + + /// Derivation Description: (ST, 1, 3) + DcmShortText m_DerivationDescription; + + /// List of derivation codes for this set of images (1-n items permitted) + OFVector m_DerivationCodeItems; + + // List of source images, as described by Source Image Sequence (0-n items + // permitted) + OFVector m_SourceImageItems; + +}; + +/** Class representing the "Derivation Image Functional Group Macro" + */ +class DCMTK_DCMFG_EXPORT FGDerivationImage : public FGBase +{ +public: + + /** Constructor creating an empty functional group + */ + FGDerivationImage(); + + /** Virtual destructor, frees memory + */ + virtual ~FGDerivationImage(); + + /** Returs a deep copy of this object + * @return Deep copy of this object + */ + virtual FGBase *clone() const; + + /** Convenience function to create a minimalistic FGDerivationImage + * @param derivationImages The list of SOP instances to reference + * @param derivationDescription Description of the derivation performed + * @param derivationCode Coded representation of the derivation description + * @param purposeOfReference Purpose of referencing the SOP instances + * @return The created derivation image item, if successful, NULL otherwise + */ + static FGDerivationImage* createMinimal(const OFVector& derivationImages, + const OFString& derivationDescription, + const CodeSequenceMacro& derivationCode, + const CodeSequenceMacro& purposeOfReference); + + /** Comparison operator that compares the normalized value of this object + * with a given object of the same type, i.e.\ the elements within both + * functional groups (this and rhs parameter) are compared by value! + * Both objects (this and rhs) need to have the same type (i.e.\ both + * FGDerivationImage) to be comparable. This function is used in order + * to decide whether a functional group already exists, or is new. This + * is used in particular to find out whether a given functional group + * can be shared (i.e.\ the same information already exists as shared + * functional group) or is different from the same shared group. In that + * case the shared functional group must be distributed into per-frame + * functional groups, instead. The exact implementation for implementing + * the comparison is not relevant. However, it must be a comparison + * by value. + * @param rhs the right hand side of the comparison + * @return 0 if the object values are equal. + * -1 if either the value of the first component that does not match + * is lower in the rhs object, or all compared components match + * but the rhs component is shorter. Also returned if this type and + * rhs type (DcmFGTypes::E_FGType) do not match. + * 1 if either the value of the first component that does not match + * is greater in the rhs object, or all compared components match + * but the rhs component is longer. + */ + virtual int compare(const FGBase& rhs) const; + + /** Returns shared type of this functional group + * @return Always returns DcmFGTypes::EFGS_BOTH + */ + virtual DcmFGTypes::E_FGSharedType getSharedType() const {return DcmFGTypes::EFGS_BOTH;} + + /** Convenience function to add an item only having a single derivation code + * derivation description. No source images have to provided but can be added + * later on the resulting DerivationImageItem. + * @param derivationCode Code describing derivation + * @param derivationDescription Free text description of derivation (can be + * empty) + * @param item The created derivation image item if successful, NULL + * otherwise + * @return EC_Normal if adding works, error code otherwise + */ + virtual OFCondition addDerivationImageItem(const CodeSequenceMacro& derivationCode, + const OFString& derivationDescription, + DerivationImageItem*& item); + + /** Clears all data handled by this component + */ + virtual void clearData(); + + /** Checks whether this class contains valid data + * @return EC_Normal if data is valid, error otherwise + */ + virtual OFCondition check() const; + + /** Get reference to derivation image items + * @return Reference to derivation image items + */ + virtual OFVector& getDerivationImageItems(); + + /** Read Derivation Image Sequence from given item, which can contain zero or + * more items + * @param item The item to read from + * @return Returns EC_Normal if at least one derivation image item could be + * read or no item exists at all, otherwise an error is returned + */ + virtual OFCondition read(DcmItem& item); + + /** Write Derivation Image Sequence (containing contain zero or more items) + * to given item + * @param item The item to write to + * @return EC_Normal if writing was successful, error otherwise + */ + virtual OFCondition write(DcmItem& item); + +private: + + /// List of derivation image items making up the Derivation Image Sequence + OFVector m_DerivationImageItems; + +}; + +#endif // FGDERIMG_H diff --git a/dcmfg/include/dcmtk/dcmfg/fgfact.h b/dcmfg/include/dcmtk/dcmfg/fgfact.h new file mode 100644 index 00000000..c44de470 --- /dev/null +++ b/dcmfg/include/dcmtk/dcmfg/fgfact.h @@ -0,0 +1,80 @@ +/* + * + * Copyright (C) 2015, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmfg + * + * Author: Michael Onken + * + * Purpose: Factory class for creating functional groups + * + */ + +#ifndef FGFACT_H +#define FGFACT_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/ofstd/ofmap.h" +#include "dcmtk/dcmdata/dctagkey.h" +#include "dcmtk/dcmfg/fgtypes.h" + +class FGBase; + + +/** Singleton class that is used to create functional groups by knowing + * their type or other unique features, i.e.\ offering factory functionality. + */ +class DCMTK_DCMFG_EXPORT FGFactory +{ +public: + + /** Return the single instance of the factory + * @return The instance of FGFactory + */ + static FGFactory& instance(); + + /** Create new functional group based on given type + * @param fgtype The type of functional group to create + * @return The functional group or NULL if error occurs + */ + FGBase *create(const DcmFGTypes::E_FGType fgtype); + + /** Create new functional group based its unique sequence tag key + * @param fgSequenceKey Tag key of the functional groups sequence + * @return The functional group or NULL if error occurs + */ + FGBase *create(const DcmTagKey& fgSequenceKey); + +private: + + /** Private undefined constructor (singleton implementation) + */ + FGFactory(); + + /** Private undefined copy constructor (singleton implementation) + */ + FGFactory(const FGFactory&); + + /** Private undefined assignment operator (singleton implementation) + */ + FGFactory& operator=(const FGFactory&); + + /** Private undefined destructor (singleton implementation) + */ + ~FGFactory() {} + + /// The instance of FGFactory handled by this singleton class + static FGFactory* m_Instance; + +}; + +#endif // FGFACT_H diff --git a/dcmfg/include/dcmtk/dcmfg/fgfracon.h b/dcmfg/include/dcmtk/dcmfg/fgfracon.h new file mode 100644 index 00000000..1cde4af8 --- /dev/null +++ b/dcmfg/include/dcmtk/dcmfg/fgfracon.h @@ -0,0 +1,378 @@ +/* + * + * Copyright (C) 2015, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmfg + * + * Author: Michael Onken + * + * Purpose: Class for managing the Frame Content Functional Group + * + */ + +#ifndef FGFRACON_H +#define FGFRACON_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/ofstd/ofvector.h" +#include "dcmtk/ofstd/ofstring.h" +#include "dcmtk/dcmdata/dctk.h" +#include "dcmtk/dcmfg/fgbase.h" + +/** Class representing the "Frame Content" Functional Group Macro. Can only be + * used as per-frame functional group (never shared). + */ +class DCMTK_DCMFG_EXPORT FGFrameContent : public FGBase +{ +public: + + /** Constructor, creates empty functional group + */ + FGFrameContent(); + + /** Virtual destructor + */ + virtual ~FGFrameContent(); + + /** Returs a deep copy of this object + * @return Deep copy of this object + */ + virtual FGBase *clone() const; + + /** Returns shared functional group type (always "per-frame") + * @return The functional group type (DcmFGTypes::EFGS_ONLYPERFRAME) + */ + virtual DcmFGTypes::E_FGSharedType getSharedType() const {return DcmFGTypes::EFGS_ONLYPERFRAME;} + + /** Clear all data + */ + virtual void clearData(); + + /** Check whether the current content of this gruop consistent and complete + * @return EC_Normal, if no errors are found, error otherwise + */ + virtual OFCondition check() const; + + /** Read Frame Content Sequence from given item + * @param item The item to read from + * @return EC_Normal if reading was successful, error otherwise + */ + virtual OFCondition read(DcmItem& item); + + /** Writes the content of this class into Frame Content Sequence + * (newly cerated) into given item + * @param item The item to write to + * @return EC_Normal if writing was succesful, error otherwise + */ + virtual OFCondition write(DcmItem& item); + + /** Comparison operator that compares the normalized value of this object + * with a given object of the same type, i.e.\ the elements within both + * functional groups (this and rhs parameter) are compared by value! + * Both objects (this and rhs) need to have the same type (i.e.\ both + * FGUnknown) to be comparable. This function is used in order + * to decide whether a functional group already exists, or is new. This + * is used in particular to find out whether a given functional group + * can be shared (i.e.\ the same information already exists as shared + * functional group) or is different from the same shared group. In that + * case the shared functional group must be distributed into per-frame + * functional groups, instead. The exact implementation for implementing + * the comparison is not relevant. However, it must be a comparison + * by value. + * @param rhs the right hand side of the comparison + * @return 0 if the object values are equal. + * -1 if either the value of the first component that does not match + * is lower in the this object, or all compared components match + * but this component is shorter. Also returned if this type and + * rhs type (DcmFGTypes::E_FGType) do not match. + * 1 if either the value of the first component that does not match + * is greater in this object, or all compared components match + * but this component is longer. + */ + virtual int compare(const FGBase& rhs) const; + + // --- get() functionality --- + + /** Get Frame Acquisition Number + * @param value Reference to variable that should hold the result + * @param pos Position of the value inside the DICOM element. If 0, the first + * value is returned. If the no value at the given position exists, + * an error is returned. + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getFrameAcquisitionNumber(Uint16& value, + const signed long pos = 0); + + /** Get Frame Reference Date Time + * @param value Reference to variable that should hold the result + * @param pos Position of the value inside the DICOM element. If 0, the first + * value is returned. If the no value at the given position exists, + * an error is returned. + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getFrameReferenceDateTime(OFString& value, + const signed long pos = 0); + /** Get Frame Acquisition Date Time + * @param value Reference to variable that should hold the result + * @param pos Position of the value inside the DICOM element. If 0, the first + * value is returned. If the no value at the given position exists, + * an error is returned. + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getFrameAcquisitionDateTime(OFString& value, + const signed long pos = 0); + + /** Get Frame Acquisition Duration + * @param value Reference to variable that should hold the result + * @param pos Position of the value inside the DICOM element. If 0, the first + * value is returned. If the no value at the given position exists, + * an error is returned. + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getFrameAcquisitionDuration(Float64& value, + const unsigned long pos = 0); + + /** Get Cardiac Cycle Position + * @param value Reference to variable that should hold the result + * @param pos Position of the value inside the DICOM element. If 0, the first + * value is returned. If the no value at the given position exists, + * an error is returned. + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getCardiacCyclePosition(OFString& value, + const signed long pos = 0); + + /** Get Respiratory Cycle Position + * @param value Reference to variable that should hold the result + * @param pos Position of the value inside the DICOM element. If 0, the first + * value is returned. If the no value at the given position exists, + * an error is returned. + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getRespiratoryCyclePosition(OFString& value, + const signed long pos = 0); + + /** Get Dimension Index Value + * @param value Reference to variable that should hold the result + * @param pos Position of the value inside the DICOM element. If 0, the first + * value is returned. If the no value at the given position exists, + * an error is returned. + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getDimensionIndexValues(Uint32& value, + const signed long pos = 0); + + /** Get Temporal Position Index + * @param value Reference to variable that should hold the result + * @param pos Position of the value inside the DICOM element. If 0, the first + * value is returned. If the no value at the given position exists, + * an error is returned. + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getTemporalPositionIndex(Uint32& value, + const signed long pos = 0); + + /** Get Stack ID + * @param value Reference to variable that should hold the result + * @param pos Position of the value inside the DICOM element. If 0, the first + * value is returned. If the no value at the given position exists, + * an error is returned. + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getStackID(OFString& value, + const signed long pos = 0); + + /** Get In-Stack Position Number + * @param value Reference to variable that should hold the result + * @param pos Position of the value inside the DICOM element. If 0, the first + * value is returned. If the no value at the given position exists, + * an error is returned. + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getInStackPositionNumber(Uint32& value, + const signed long pos = 0); + + /** Get Frame Comments + * @param value Reference to variable that should hold the result + * @param pos Position of the value inside the DICOM element. If 0, the first + * value is returned. If the no value at the given position exists, + * an error is returned. + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getFrameComments(OFString& value, + const signed long pos = 0); + + /** Get Frame Label + * @param value Reference to variable that should hold the result + * @param pos Position of the value inside the DICOM element. If 0, the first + * value is returned. If the no value at the given position exists, + * an error is returned. + * @return EC_Normal, if value could be returned, error otherwise + */ + virtual OFCondition getFrameLabel(OFString& value, + const signed long pos = 0); + + // --- set() functionality --- + + /** Set Frame Acquisition Number + * @param value Value that should be set + * @param checkValue If OFTrue, basic checks are performed whether the value is + * valid for this attribute + * @return EC_Normal, if value was set, error otherwise + */ + virtual OFCondition setFrameAcquisitionNumber(const Uint16& value, + const OFBool checkValue = OFTrue); + + /** Set Frame Frame Reference Date Time + * @param value Value that should be set + * @param checkValue If OFTrue, basic checks are performed whether the value is + * valid for this attribute + * @return EC_Normal, if value was set, error otherwise + */ + virtual OFCondition setFrameReferenceDateTime(const OFString& value, + const OFBool checkValue = OFTrue); + + /** Set Frame Acquisition Date Time + * @param value Value that should be set + * @param checkValue If OFTrue, basic checks are performed whether the value is + * valid for this attribute + * @return EC_Normal, if value was set, error otherwise + */ + virtual OFCondition setFrameAcquisitionDateTime(const OFString& value, + const OFBool checkValue = OFTrue); + + /** Set Frame Acquisition Duration + * @param value Value that should be set + * @param checkValue If OFTrue, basic checks are performed whether the value is + * valid for this attribute + * @return EC_Normal, if value was set, error otherwise + */ + virtual OFCondition setFrameAcquisitionDuration(const Float64& value, + const OFBool checkValue = OFTrue); + + /** Set Cardiac Cycle Position + * @param value Value that should be set + * @param checkValue If OFTrue, basic checks are performed whether the value is + * valid for this attribute + * @return EC_Normal, if value was set, error otherwise + */ + virtual OFCondition setCardiacCyclePosition(const OFString& value, + const OFBool checkValue = OFTrue); + + /** Set Respiratory Cycle Position + * @param value Value that should be set + * @param checkValue If OFTrue, basic checks are performed whether the value is + * valid for this attribute + * @return EC_Normal, if value was set, error otherwise + */ + virtual OFCondition setRespiratoryCyclePosition(const OFString& value, + const OFBool checkValue = OFTrue); + + /** Set one of the Dimension Index Values + * @param value Value that should be set (lowest index starts with 1) + * @param pos The position of the value that should be set (lowest index + * starts with 0), i.e.\ select the 1st, 2nd, ..nth dimension + * @param checkValue If OFTrue, basic checks are performed whether the + * valid for this attribute + * @return EC_Normal, if value was set, error otherwise + */ + virtual OFCondition setDimensionIndexValues(const Uint32& value, + const unsigned int pos, + const OFBool checkValue = OFTrue); + + /** Set Temporal Position Index + * @param value Value that should be set + * @param checkValue If OFTrue, basic checks are performed whether the value is + * valid for this attribute + * @return EC_Normal, if value was set, error otherwise + */ + virtual OFCondition setTemporalPositionIndex(const Uint32& value, + const OFBool checkValue = OFTrue); + + /** Set Stack ID + * @param value Value that should be set + * @param checkValue If OFTrue, basic checks are performed whether the value is + * valid for this attribute + * @return EC_Normal, if value was set, error otherwise + */ + virtual OFCondition setStackID(const OFString& value, + const OFBool checkValue = OFTrue); + + /** Set In-Stack Position Number + * @param value Value that should be set + * @param checkValue If OFTrue, basic checks are performed whether the value is + * valid for this attribute + * @return EC_Normal, if value was set, error otherwise + */ + virtual OFCondition setInStackPositionNumber(const Uint32& value, + const OFBool checkValue = OFTrue); + + /** Set Frame Comments + * @param value Value that should be set + * @param checkValue If OFTrue, basic checks are performed whether the value is + * valid for this attribute + * @return EC_Normal, if value was set, error otherwise + */ + virtual OFCondition setFrameComments(const OFString& value, + const OFBool checkValue = OFTrue); + + /** Set Frame Label + * @param value Value that should be set + * @param checkValue If OFTrue, basic checks are performed whether the value is + * valid for this attribute + * @return EC_Normal, if value was set, error otherwise + */ + virtual OFCondition setFrameLabel(const OFString& value, + const OFBool checkValue = OFTrue); + +private: + + /* Content of Frame Content Macro */ + + /// Frame Acquisition Number (US, VM 1, Required type 3) + DcmUnsignedShort m_FrameAcquisitonNumber; + + /// Frame Reference DateTime (DT, 1, 1C) + DcmDateTime m_FrameReferenceDateTime; + + /// Frame Acquisition DateTime (DT, 1, 1C) + DcmDateTime m_FrameAcquisitionDateTime; + + /// Frame Acquisition Duration (FD, 1, 1C) + DcmFloatingPointDouble m_FrameAcquisitionDuration; + + /// Cardiac Cycle Positition (CS, 1, 3) + DcmCodeString m_CardiacCyclePosition; + + /// Respiratory Cycle Position (CS, 1, 3) + DcmCodeString m_RespiratoryCyclePosition; + + /// Dimension Index Values (UL, 1-n, 1C) + DcmUnsignedLong m_DimensionIndexValues; + + /// Temporal Position Index (UL, 1, 1C) + DcmUnsignedLong m_TemporalPositionIndex; + + /// Stack ID (SH, 1, 1C) + DcmShortString m_StackID; + + /// In-Stack Position Number (UL, 1, 1C) + DcmUnsignedLong m_InStackPositionNumber; + + /// Frame Comments (LT, 1, 3) + DcmLongText m_FrameComments; + + /// Frame Label (LO, 1, 3) + DcmLongString m_FrameLabel; +}; + +#endif // FGFRACON_H diff --git a/dcmfg/include/dcmtk/dcmfg/fgframevoilut.h b/dcmfg/include/dcmtk/dcmfg/fgframevoilut.h new file mode 100644 index 00000000..0c125803 --- /dev/null +++ b/dcmfg/include/dcmtk/dcmfg/fgframevoilut.h @@ -0,0 +1,209 @@ +/* + * + * Copyright (C) 2015, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmfg + * + * Author: Michael Onken + * + * Purpose: Class for managing Frame VOI LUT Functional Group + * + */ + +#ifndef FGFRAMEVOILUT_H +#define FGFRAMEVOILUT_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmdata/dcitem.h" +#include "dcmtk/dcmfg/fgbase.h" + +/** Class representing the "Frame VOI LUT" Functional Group Macro + */ +class DCMTK_DCMFG_EXPORT FGFrameVOILUT : public FGBase +{ +public: + + /** Constructor creating empty functional group + */ + FGFrameVOILUT(); + + /** Virutal destructor + */ + virtual ~FGFrameVOILUT(); + + /** Returs a deep copy of this object + * @return Deep copy of this object + */ + virtual FGBase *clone() const; + + /** Get shared type of this kind functional group (can be both, per-frame or + * shared) + * @return Always returns DcmFGTypes::EFGS_BOTH + */ + virtual DcmFGTypes::E_FGSharedType getSharedType() const {return DcmFGTypes::EFGS_BOTH;} + + /** Clear old values + */ + virtual void clearData(); + + /** Check whether functional group contains valid data + * @return EC_Normal if data is valid, error otherwise + */ + virtual OFCondition check() const; + + /** Read Frame VOI LUT Sequence from given item + * @param item The item to read from + * @return EC_Normal if reading was successful, error otherwise + */ + virtual OFCondition read(DcmItem& item); + + /** Write Frame VOI LUT Sequence to given item + * @param item The item to write to + * @return EC_Normal if writing was successful, error otherwise + */ + virtual OFCondition write(DcmItem& item); + + // --- get() functionality --- + + /** Get Window Center + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getWindowCenter(Float64& value, + const unsigned long pos = 0); + + /** Get Window Width + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getWindowWidth(Float64& value, + const unsigned long pos = 0); + + /** Get Window Center and Window Width Explanation + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getWindowCenterAndWindowWidthExplanation(OFString& value, + const unsigned long pos = 0); + + /** Get tripe of information: Window Center, Window With, Window Center and + * Window Width Explanation + * @param windowCenter Reference to variable in which Window Center should + * be stored + * @param windowWidth Reference to variable in which Window Width should + * be stored + * @param explanation Reference to variable in which Window Center and + * Window Width Explanation should be stored + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getCenterWidthExplanation(Float64& windowCenter, + Float64& windowWidth, + OFString& explanation); + + /** Get VOI LUT Function + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getVOILUTFunction(OFString& value, + const unsigned long pos = 0); + + + // --- set() functionality --- + + /** Set Window Center + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR (DS) and VM (1) + * if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setWindowCenter(const OFString& value, + const OFBool checkValue = OFTrue); + + /** Set Window Width + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR (DS) and VM (1) + * if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setWindowWidth(const OFString& value, + const OFBool checkValue = OFTrue); + + /** Set Window Center and Window Width Explanation + * @param windowCenter Value for Window Center + * @param windowWidth Value for Window Width + * @param explanation Value for Window Center and Window Width Explanation + * should be stored + * @param checkValue Check 'value' for conformance with VR (DS) and VM (1-n) + * if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setCenterWidthExplanation(const Float64& windowCenter, + const Float64& windowWidth, + const OFString& explanation = "", + const OFBool checkValue = OFTrue); + + /** Set VOI LUT Function + * @param value Value for VOI LUT Function + * @param checkValue Check 'value' for conformance with VR (CS) and VM (1) + * if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setVOILUTFunction(const OFString& value, + const OFBool checkValue = OFTrue); + + /** Comparison operator that compares the normalized value of this object + * with a given object of the same type, i.e.\ the elements within both + * functional groups (this and rhs parameter) are compared by value! + * Both objects (this and rhs) need to have the same type (i.e.\ both + * FGUnknown) to be comparable. This function is used in order + * to decide whether a functional group already exists, or is new. This + * is used in particular to find out whether a given functional group + * can be shared (i.e.\ the same information already exists as shared + * functional group) or is different from the same shared group. In that + * case the shared functional group must be distributed into per-frame + * functional groups, instead. The exact implementation for implementing + * the comparison is not relevant. However, it must be a comparison + * by value. + * @param rhs the right hand side of the comparison + * @return 0 if the object values are equal. + * -1 if either the value of the first component that does not match + * is lower in the this object, or all compared components match + * but this component is shorter. Also returned if this type and + * rhs type (DcmFGTypes::E_FGType) do not match. + * 1 if either the value of the first component that does not match + * is greater in this object, or all compared components match + * but this component is longer. + */ + virtual int compare(const FGBase& rhs) const; + +private: + + /* Content of Frame VOI LUT Macro */ + + /// Window Center (DS, VM 1-n, Required type 1) + DcmDecimalString m_WindowCenter; + + /// Window Width (DS, VM 1-n, Required type 1) + DcmDecimalString m_WindowWidth; + + /// Window Center & Window Width Explanation (LO, VM 1-n, Required type 3) + DcmLongString m_WindowCenterWindowWidthExplanation; + + /// VOI LUT Function (CS, VM 1, Requirement Type 3) + DcmCodeString m_VOILUTFunction; +}; + +#endif // FGFRAMEVOILUT_H diff --git a/dcmfg/include/dcmtk/dcmfg/fgimagedatatype.h b/dcmfg/include/dcmtk/dcmfg/fgimagedatatype.h new file mode 100644 index 00000000..9ebceffa --- /dev/null +++ b/dcmfg/include/dcmtk/dcmfg/fgimagedatatype.h @@ -0,0 +1,179 @@ +/* + * + * Copyright (C) 2015, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmfg + * + * Author: Michael Onken + * + * Purpose: Class for managing Image Data Type Functional Group + * + */ + +#ifndef FGIMAGEDATATYPE_H +#define FGIMAGEDATATYPE_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmdata/dcitem.h" +#include "dcmtk/dcmfg/fgbase.h" + +/** Class for managing Image Data Type Functional Group that identifies the + * data type characteristics of this frame + */ +class DCMTK_DCMFG_EXPORT FGImageDataType : public FGBase +{ +public: + + /** Constructor, creates empty Image Data Type functional group + */ + FGImageDataType(); + + /** Destructor, frees memory + */ + virtual ~FGImageDataType(); + + /** Returs a deep copy of this object + * @return Deep copy of this object + */ + virtual FGBase *clone() const; + + /** Get potential shared type of this group, always returns + * DcmFGTypes::EFGS_BOTH + * @return Always returns DcmFGTypes::EFGS_BOTH + */ + virtual DcmFGTypes::E_FGSharedType getSharedType() const {return DcmFGTypes::EFGS_BOTH;} + + /** Clear data + */ + virtual void clearData(); + + /** Check whether current data of this functional group is valid + * @return EC_Normal if data is valid, error otherwise + */ + virtual OFCondition check() const; + + /** Read Image Data Type Sequence (this functional group) from given item + * @param item Item to read from + * @return EC_Normal if reading works, error otherwise + */ + virtual OFCondition read(DcmItem &item); + + /** Write Image Data Type Sequence (this functional group) to given item + * @param item Item to write to + * @return EC_Normal if writing works, error otherwise + */ + virtual OFCondition write(DcmItem& item); + + // --- get() functionality --- + + /** Get Data Type + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getDataType(OFString& value, + const signed long pos = 0); + + /** Get Aliased Data Type + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getAliasedDataType(OFString& value, + const signed long pos = 0); + + /** Get Zero Velocity Pixel Value + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getZeroVelocityPixelValue(Sint32& value, + const signed long pos = 0); + + // --- set() functionality --- + + /** Set Data Type + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR (CS) and VM (1) + * if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setDataType(const OFString& value, + const OFBool checkValue = OFTrue); + + /** Set Aliased Data Type + * @param value Permitted values: "YES" or "NO". + * @param checkValue If enabled, the value is checked for conformance + * @return EC_Normal if value was set, error code otherwise + */ + virtual OFCondition setAliasedDataType(const OFString& value, + const OFBool checkValue = OFTrue); + + /** Set Zero Velocity Pixel Value. Only use if Zero Velocity Pixel Value is of + * VR US, i.e.\ Pixel Representation = 0 + * @param value Value to be set + + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setZeroVelocityPixelValueUS(const Uint16 value); + + /** Set Zero Velocity Pixel Value. Only use if Zero Velocity Pixel Value is of + * VR SS, i.e.\ Pixel Representation = 1 + * @param value Value to be set + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setZeroVelocityPixelValueSS(const Sint16 value); + + /** Comparison operator that compares the normalized value of this object + * with a given object of the same type, i.e.\ the elements within both + * functional groups (this and rhs parameter) are compared by value! + * Both objects (this and rhs) need to have the same type (i.e.\ both + * FGUnknown) to be comparable. This function is used in order + * to decide whether a functional group already exists, or is new. This + * is used in particular to find out whether a given functional group + * can be shared (i.e.\ the same information already exists as shared + * functional group) or is different from the same shared group. In that + * case the shared functional group must be distributed into per-frame + * functional groups, instead. The exact implementation for implementing + * the comparison is not relevant. However, it must be a comparison + * by value. + * @param rhs the right hand side of the comparison + * @return 0 if the object values are equal. + * -1 if either the value of the first component that does not match + * is lower in the this object, or all compared components match + * but this component is shorter. Also returned if this type and + * rhs type (DcmFGTypes::E_FGType) do not match. + * 1 if either the value of the first component that does not match + * is greater in this object, or all compared components match + * but this component is longer. + */ + virtual int compare(const FGBase& rhs) const; + +private: + + /* Content of Image Data Type Macro */ + + /// Data Type (CS, VM 1, Required type 1) + DcmCodeString m_DataType; + + /// Aliased Data Type (CS, VM 1, Required Type 1) + DcmCodeString m_AliasedDataType; + + /// Zero Velocity Pixel Value (US or SS, VM , Required Type 1C) + DcmUnsignedShort m_ZeroVelocityPixelValueUS; + + /// Zero Velocity Pixel Value (US or SS, VM , Required Type 1C) + DcmSignedShort m_ZeroVelocityPixelValueSS; + +}; + +#endif // FGIMAGEDATATYPE_H diff --git a/dcmfg/include/dcmtk/dcmfg/fginterface.h b/dcmfg/include/dcmtk/dcmfg/fginterface.h new file mode 100644 index 00000000..05f71316 --- /dev/null +++ b/dcmfg/include/dcmtk/dcmfg/fginterface.h @@ -0,0 +1,279 @@ +/* + * + * Copyright (C) 2015, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmfg + * + * Author: Michael Onken + * + * Purpose: Main interface class for managing Functional Groups + * + */ + +#ifndef FGINTERFACE_H +#define FGINTERFACE_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/ofstd/ofvector.h" +#include "dcmtk/ofstd/ofmap.h" +#include "dcmtk/dcmdata/dcsequen.h" +#include "dcmtk/dcmdata/dcdatset.h" +#include "dcmtk/dcmdata/dctk.h" +#include "dcmtk/dcmiod/iodrules.h" +#include "dcmtk/dcmfg/fgtypes.h" +#include "dcmtk/dcmfg/fgdefine.h" +#include "dcmtk/dcmfg/fg.h" + +// Forward declaration +class IODMultiframeDimensionModule; + +/** Main interface class to access functional groups from DICOM Enhanced + * objects. Allows reading, modifying and writing functional groups back + * and forth from DICOM datasets. + */ +class DCMTK_DCMFG_EXPORT FGInterface +{ + +public: + + /// Type representing per-frame functional groups, i.e.\ a number of + /// functional groups assigned to each frame + typedef OFMap PerFrameGroups; + + /// Iterator type for iterating over functional groups + typedef FunctionalGroups::iterator iterator; + + /// Const iterator type for iterating over functional groups + typedef FunctionalGroups::const_iterator const_iterator; + + /** Constructor, constructs empty sets of per-frame and shared + * functional groups + */ + FGInterface(); + + /** Virtual destructor, frees memory + */ + virtual ~FGInterface(); + + /** Delete all functional groups (shared and per-frame) + */ + virtual void clear(); + + /** Checks the functional groups for consistency + * @return OFTrue, if check consistency is ok, error otherwise + */ + virtual OFBool check(); + + /** Returns number of frames. Computed by number of per-frame + * functional group items (i.e.\ the Number of Frames attribues + * is not taken into account). + * @return Number of frames + */ + virtual size_t getNumberOfFrames(); + + /** Read enhanced multi-frame information from DICOM item, usually + * DcmDataset, i.e.\ must contain Shared and Per-frame Functional Group + * Sequences + * @param dataset The item to read from + * @return EC_Normal if reading was successful, error otherwise + */ + virtual OFCondition read(DcmItem& dataset); + + /** Write enhanced multi-frame information to DICOM item, + * usually DcmDataset, i.e.\ writes Shared and Per-frame Functional Group + * Sequences + * @param dataset The item to write to + * @return EC_Normal if successful, error otherwise + */ + virtual OFCondition write(DcmItem& dataset); + + /** Get specific functional group for a frame, no matter whether it is stored + * per frame or shared + * @param frameNo The frame number the functional group should apply to + * (starts with 0) + * @param fgType The type of functional group to look for + * @return The functional group if found, NULL otherwise + */ + virtual FGBase* get(const Uint32 frameNo, + const DcmFGTypes::E_FGType fgType); + + // TODO Add get(..) version that takes the sequence tag (e.g.\ for unknown + // functional groups + + /** Get specific functional group for a frame, no matter whether it is stored + * per frame or shared. + * @param frameNo The frame number of group of interest (starts from 0) + * @param fgType The type of functional group to look for + * @param isPerFrame If OFTrue, the group found was found as per-frame, + * otherwise it is a shared functional group + * @return The functional group if found, error otherwise + */ + virtual FGBase* get(const Uint32 frameNo, + const DcmFGTypes::E_FGType fgType, + OFBool& isPerFrame); + + /** Return all per-frame functional groups, e.g.\ to iterate over them + * @param frameNo The frame number of the groups of interest (starts from 0) + * @return The per-frame functional groups for the given frame + */ + const FunctionalGroups* getPerFrame(const Uint32 frameNo) const; + + /** Return all shared functional groups, e.g.\ to iterate over them + * @return The shared functional groups + */ + const FunctionalGroups* getShared() const; + + /** Add functional group that should be shared for all frames. This will + * delete all per-frame groups of the same type if existing. + * @param group The group to be added (copy is performed) + * @return EC_Normal, if adding was successful, error otherwise + */ + virtual OFCondition addShared(const FGBase& group); + + /** Add functional group for given frame. If there is already a shared + * functional group with identical values, the call returns without + * errors, too. If there is a shared group that differs, the shared group + * is converted to be "per-frame" for all frames and then the given group + * is inserted for the frame specified by the user. + * If a per-frame functional group of the same type already exists it is + * overwritten. + * @param frameNo The frame number this group should be added for (starts + * from 0) + * @param group The group to be added + * @return EC_Normal, if adding was successful, error otherwise + */ + virtual OFCondition addPerFrame(const Uint32 frameNo, + const FGBase& group); + + /** Deletes a shared functional group of the given type + * @param fgType The type of functional group to delete + * @return OFTrue if group existed and could be deleted, OFFalse (group did + * not exist) otherwise + */ + virtual OFBool deleteShared(const DcmFGTypes::E_FGType fgType); + + /** Deletes per-frame functional group of the given type for a specific frame + * @param frameNo The frame number for the functional group of interest + * @param fgType The type of functional group to delete + * @return OFTrue if group existed and could be deleted, OFFalse (group did + * not exist) otherwise + */ + virtual OFBool deletePerFrame(const Uint32 frameNo, + const DcmFGTypes::E_FGType fgType); + + /** Deletes per-frame functional group for all frames + * @param fgType The type of functional group to delete + * @return Number of per-frame groups deleted (usually equal to number of + * images) + */ + size_t deletePerFrame(const DcmFGTypes::E_FGType fgType); + +protected: + + /** Get shared functional group based on its type + * @param fgType The type of functional group + * @return The functional group or NULL if not existant + */ + virtual FGBase* getShared(const DcmFGTypes::E_FGType fgType); + + /** Insert shared functional group + * @param group The functional group to be inserted + * @param replaceExisting If OFTrue, an existing shared functional group + * will be deleted, otherwise the old group is not overwritten + * @return EC_Normal if insertion worked, FG_EC_DoubledFG if group exists and + * is not overwritten, other error code for other cases + */ + virtual OFCondition insertShared(FGBase* group, + const OFBool replaceExisting = OFTrue); + + /** Get per-frame functional group + * @param frameNo The frame number of the group + * @param fgType The type of the group + * @return The functional group or NULL if not existant + */ + virtual FGBase* getPerFrame(const Uint32 frameNo, + const DcmFGTypes::E_FGType fgType); + + /** Insert per-frame functional group + * @param frameNo The frame number the group should be added for + * @param group The functional group to be inserted + * @param replaceExisting If OFTrue, an existing per-frame functional group + * will be deleted, otherwise the old group is not overwritten + * @return EC_Normal if insertion worked, FG_EC_DoubledFG if group exists and + * is not overwritten, other error code for other cases + */ + virtual OFCondition insertPerFrame(const Uint32 frameNo, + FGBase* group, + const OFBool replaceExisting = OFTrue); + + /** Get existing per-frame group or create it for the given frame. Note that + * the per-frame groups do not have to be created "in order", i.e.\ one could + * add groups in order 3,5,1 ,... . + * @param frameNo The frame number to get/create per-frame groups for + * @return The functional groups if found/created, NULL in case of error + */ + virtual FunctionalGroups* getOrCreatePerFrameGroups(const Uint32 frameNo); + + /** Read Shared Functional Group Sequence from given item + * @param dataset The item to read from + * @return EC_Normal if reading was successful, error otherwise + */ + virtual OFCondition readSharedFG(DcmItem& dataset); + + /** Read Per-Frame Functional Group Sequence from given item + * @param dataset The item to read from + * @return EC_Normal if reading was successful, error otherwise + */ + virtual OFCondition readPerFrameFG(DcmItem& dataset); + + /** Read single functional group into the item provided + * @param fgItem The item to read from + * @param groups The resulting group after reading + * @return EC_Normal if reading was successful, error otherwise + */ + virtual OFCondition readSingleFG(DcmItem& fgItem, + FunctionalGroups& groups); + + /** Write Shared Functional Group Sequence to given item + * @param dataset The item to write to + * @return EC_Normal if writing was successful, error otherwise + */ + virtual OFCondition writeSharedFG(DcmItem& dataset); + + /** Write Per-Frame Functional Group Sequence to given item + * @param dataset The item to write to + * @return EC_Normal if writing was successful, error otherwise + */ + virtual OFCondition writePerFrameFG(DcmItem& dataset); + + /** Convert a shared functional group to a per-frame one by copying the + * shared one into a per-frame one for each frame and deleting the shared one + * aftewrards. + * @param fgType The type of functional group to convert + * @return EC_Normal if conversion worked out, FG_EC_NoSuchGroup if such a + * group does not exist and other error otherwise. In the last case + * the functional groups may be left in invalid state, but that + * should only happen for fatal errors like exhausted memory. + */ + virtual OFCondition convertSharedToPerFrame(const DcmFGTypes::E_FGType fgType); + +private: + + /// Shared functional groups + FunctionalGroups m_shared; + + /// Link from frame number (map key) to the list of functional groups (value) + /// relevant for the frame + PerFrameGroups m_perFrame; +}; + +#endif // MODMULTIFRAMEFGH_H diff --git a/dcmfg/include/dcmtk/dcmfg/fgpixmsr.h b/dcmfg/include/dcmtk/dcmfg/fgpixmsr.h new file mode 100644 index 00000000..895f6bff --- /dev/null +++ b/dcmfg/include/dcmtk/dcmfg/fgpixmsr.h @@ -0,0 +1,170 @@ +/* + * + * Copyright (C) 2015, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmfg + * + * Author: Michael Onken + * + * Purpose: Class for managing Pixel Measures Functional Group + * + */ + +#ifndef FGPIXMSR_H +#define FGPIXMSR_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmdata/dcitem.h" +#include "dcmtk/dcmdata/dcvrds.h" +#include "dcmtk/dcmfg/fgbase.h" + +/** Class representing the Pixel Measures Functional Group Macro + */ +class DCMTK_DCMFG_EXPORT FGPixelMeasures : public FGBase +{ +public: + + /** Constructor, creates empty Pixel Measures Functional Group + */ + FGPixelMeasures(); + + /** Virtual desctructor, frees memory + */ + virtual ~FGPixelMeasures(); + + /** Returs a deep copy of this object + * @return Deep copy of this object + */ + virtual FGBase *clone() const; + + + /** Returs shared type of this group (can be shared or per-frame) + * @return Always returns DcmFGTypes::EFGS_BOTH; + */ + virtual DcmFGTypes::E_FGSharedType getSharedType() const {return DcmFGTypes::EFGS_BOTH;} + + /** Clear all data + */ + virtual void clearData(); + + /** Check whether data in functional group is valid + * @return EC_Normal if data is valid, error otherwise + */ + virtual OFCondition check() const; + + /** Read functional group from given item + * @param item The item to read from, must contain Pixel Measures Sequence + * @return EC_Normal if reading was successful, error otherwise + */ + virtual OFCondition read(DcmItem& item); + + /** Write functional group to given item + * @param item The item to write Pixel Measures Sequence to + * @return EC_Normal if writing was successful, error otherwise + */ + virtual OFCondition write(DcmItem& item); + + // --- get() functionality --- + + /** Get Pixel Spacing + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getPixelSpacing(Float64& value, + const signed long pos = 0); + + /** Get Slice Thickness + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getSliceThickness(Float64& value, + const signed long pos = 0); + + /** Get Spacing Between Slices + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getSpacingBetweenSlices(Float64& value, + const signed long pos = 0); + + // --- set() functionality --- + + /** Set Pixel Spacing + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR (DS) and VM (1) if + * enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setPixelSpacing(const OFString& value, + const OFBool checkValue = OFTrue); + + /** Set Slice Thickness + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR (DS) and VM (1) if + * enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setSliceThickness(const OFString& value, + const OFBool checkValue = OFTrue); + + /** Set Spacing between Slices + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR (DS) and VM (1) if + * enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setSpacingBetweenSlices(const OFString& value, + const OFBool checkValue = OFTrue); + + /** Comparison operator that compares the normalized value of this object + * with a given object of the same type, i.e.\ the elements within both + * functional groups (this and rhs parameter) are compared by value! + * Both objects (this and rhs) need to have the same type (i.e.\ both + * FGUnknown) to be comparable. This function is used in order + * to decide whether a functional group already exists, or is new. This + * is used in particular to find out whether a given functional group + * can be shared (i.e.\ the same information already exists as shared + * functional group) or is different from the same shared group. In that + * case the shared functional group must be distributed into per-frame + * functional groups, instead. The exact implementation for implementing + * the comparison is not relevant. However, it must be a comparison + * by value. + * @param rhs the right hand side of the comparison + * @return 0 if the object values are equal. + * -1 if either the value of the first component that does not match + * is lower in the this object, or all compared components match + * but this component is shorter. Also returned if this type and + * rhs type (DcmFGTypes::E_FGType) do not match. + * 1 if either the value of the first component that does not match + * is greater in this object, or all compared components match + * but this component is longer. + */ + virtual int compare(const FGBase& rhs) const; + +private: + + /* Content of Pixel Measures Macro */ + + /// Pixel Spacing (DS, VM 2, Required type 1C) + DcmDecimalString m_PixelSpacing; + + /// Slice Thickness (DS, VM 1, Required type 1C) + DcmDecimalString m_SliceThickness; + + /// Spacing Between Slices (DS, VM 1, Required type 3) + DcmDecimalString m_SpacingBetweenSlices; +}; + +#endif // FGPIXMSRS_H diff --git a/dcmfg/include/dcmtk/dcmfg/fgplanor.h b/dcmfg/include/dcmtk/dcmfg/fgplanor.h new file mode 100644 index 00000000..9c86cf37 --- /dev/null +++ b/dcmfg/include/dcmtk/dcmfg/fgplanor.h @@ -0,0 +1,175 @@ +/* + * + * Copyright (C) 2015, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmfg + * + * Author: Michael Onken + * + * Purpose: Class for managing Plane Orientation (Patient) Functional Group + * + */ + +#ifndef FGPLANOR_H +#define FGPLANOR_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmfg/fgbase.h" +#include "dcmtk/dcmdata/dcsequen.h" +#include "dcmtk/dcmdata/dcvrds.h" + +/** Class representing the Plane Orientation (Patient) Functional Group Macro. + * It specifies the direction cosines of the first row and the first column + * with respect to the patient. + */ +class DCMTK_DCMFG_EXPORT FGPlaneOrientationPatient : public FGBase +{ +public: + + /** Constructor, creates empty functional group + */ + FGPlaneOrientationPatient(); + + /** Destructor, frees memory + */ + virtual ~FGPlaneOrientationPatient(); + + /** Returs a deep copy of this object + * @return Deep copy of this object + */ + virtual FGBase *clone() const; + + /** Convenience function to create a mininmal functional group. + * @param imageOrientationPatientRowX Row X Value + * @param imageOrientationPatientRowY Row Y Value + * @param imageOrientationPatientRowZ Row Z Value + * @param imageOrientationPatientColX Column X Value + * @param imageOrientationPatientColY Column Y Value + * @param imageOrientationPatientColZ Column Z Value + * @return The functional group created with above parameters + */ + static FGPlaneOrientationPatient* createMinimal(const OFString& imageOrientationPatientRowX, + const OFString& imageOrientationPatientRowY, + const OFString& imageOrientationPatientRowZ, + const OFString& imageOrientationPatientColX, + const OFString& imageOrientationPatientColY, + const OFString& imageOrientationPatientColZ); + + /** Get shared type of this functional group (can be both, shared and + * per-frame) + * @return Always returns DcmFGTypes::EFGS_BOTH + */ + virtual DcmFGTypes::E_FGSharedType getSharedType() const {return DcmFGTypes::EFGS_BOTH;} + + /** Clears all data + */ + virtual void clearData(); + + /** Check whether this group contains valid data + * @return EC_Normal if data is valid, error otherwise + */ + virtual OFCondition check() const; + + /** Read functional group from item, must contain the Plane Orientation + * Sequence + * @param item The item to read from + * @return EC_Normal if reading was succesful, error otherwise + */ + virtual OFCondition read(DcmItem& item); + + /** Writes functional group to given item (will write Plane Orientation + * Sequence to it) + * @param item The item to write to + * @return EC_Normal if writing was succesful, error otherwise + */ + virtual OFCondition write(DcmItem& item); + + /** Comparison operator that compares the normalized value of this object + * with a given object of the same type, i.e.\ the elements within both + * functional groups (this and rhs parameter) are compared by value! + * Both objects (this and rhs) need to have the same type (i.e.\ both + * FGUnknown) to be comparable. This function is used in order + * to decide whether a functional group already exists, or is new. This + * is used in particular to find out whether a given functional group + * can be shared (i.e.\ the same information already exists as shared + * functional group) or is different from the same shared group. In that + * case the shared functional group must be distributed into per-frame + * functional groups, instead. The exact implementation for implementing + * the comparison is not relevant. However, it must be a comparison + * by value. + * @param rhs the right hand side of the comparison + * @return 0 if the object values are equal. + * -1 if either the value of the first component that does not match + * is lower in the this object, or all compared components match + * but this component is shorter. Also returned if this type and + * rhs type (DcmFGTypes::E_FGType) do not match. + * 1 if either the value of the first component that does not match + * is greater in this object, or all compared components match + * but this component is longer. + */ + virtual int compare(const FGBase& rhs) const; + + // --- get() functionality --- + + /** Get Image Orientation Patient + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getImageOrientationPatient(OFString& value, + const signed long pos); + + /** Retrieve all values of Image Orientation Patient at the same time + * @param rowX Row X Value + * @param rowY Row Y Value + * @param rowZ Row Z Value + * @param colX Column X Value + * @param colY Column Y Value + * @param colZ Column Z Value + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getImageOrientationPatient(Float64& rowX, + Float64& rowY, + Float64& rowZ, + Float64& colX, + Float64& colY, + Float64& colZ); + + // --- set() functionality --- + + /** Set all values of Image Orientation Patient at once + * @param rowX Row X Value + * @param rowY Row Y Value + * @param rowZ Row Z Value + * @param colX Column X Value + * @param colY Column Y Value + * @param colZ Column Z Value + * @param checkValue If OFTrue, values are checked for validity + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setImageOrientationPatient(const OFString& rowX, + const OFString& rowY, + const OFString& rowZ, + const OFString& colX, + const OFString& colY, + const OFString& colZ, + const OFBool checkValue = OFTrue); + +private: + + /* Content of Plane Orientation (Patient) Macro */ + + /// Image Orientation (Patient) (DS, VM 6, Required type 1C) + DcmDecimalString m_ImageOrientationPatient; +}; + +#endif // FGPLANOR_H diff --git a/dcmfg/include/dcmtk/dcmfg/fgplanorvol.h b/dcmfg/include/dcmtk/dcmfg/fgplanorvol.h new file mode 100644 index 00000000..f1782ca0 --- /dev/null +++ b/dcmfg/include/dcmtk/dcmfg/fgplanorvol.h @@ -0,0 +1,159 @@ +/* + * + * Copyright (C) 2015, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmfg + * + * Author: Michael Onken + * + * Purpose: Class for managing Plane Orientation (Volume) Functional Group + * + */ + +#ifndef FGPLANORVOL_H +#define FGPLANORVOL_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmdata/dcitem.h" +#include "dcmtk/dcmfg/fgbase.h" + +/** Class representing the Plane Orientation (Volume) Functional Group Macro. + * It specifies the direction cosines of the first row and the first column of + * the frame with respect to the Volume Frame of Reference. + */ +class DCMTK_DCMFG_EXPORT FGPlaneOrientationVolume : public FGBase +{ +public: + + /** Constructor, creates empty Plane Orientation (Volume) Functional Group + */ + FGPlaneOrientationVolume(); + + /** Destructor, frees memory + */ + virtual ~FGPlaneOrientationVolume(); + + /** Returs a deep copy of this object + * @return Deep copy of this object + */ + virtual FGBase *clone() const; + + /** Get shared type of this functional group (can be both, per-frame and + * shared) + * @return Always returns DcmFGTypes::EFGS_BOTH + */ + virtual DcmFGTypes::E_FGSharedType getSharedType() const {return DcmFGTypes::EFGS_BOTH;} + + /** Clears all data + */ + virtual void clearData(); + + /** Check whether functional group contains valid data + * @return EC_Normal if data is valid, error otherwise + */ + virtual OFCondition check() const; + + /** Read functional group from given item, i.e.\ read Plane Orientation + * (Volume) Sequence + * @param item The item to read from + * @return EC_Normal if reading was successful, error otherwise + */ + virtual OFCondition read(DcmItem& item); + + /** Write functional group to given item, i.e.\ write Plane Orientation + * (Volume) Sequence + * @param item The item to write to + * @return EC_Normal if writing was successful, error otherwise + */ + virtual OFCondition write(DcmItem& item); + + // --- get() functionality --- + + /** Get Image Orientation Volume + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getImageOrientationVolume(Float64& value, + const unsigned long pos = 0); + + /** Retrieve all values of Image Orientation Volume at the same time + * @param rowX Row X Value + * @param rowY Row Y Value + * @param rowZ Row Z Value + * @param colX Column X Value + * @param colY Column Y Value + * @param colZ Column Z Value + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getImageOrientationVolume(Float64& rowX, + Float64& rowY, + Float64& rowZ, + Float64& colX, + Float64& colY, + Float64& colZ); + + // --- set() functionality --- + + /** Set all values of Image Orientation Volume at once + * @param rowX Row X Value + * @param rowY Row Y Value + * @param rowZ Row Z Value + * @param colX Column X Value + * @param colY Column Y Value + * @param colZ Column Z Value + * @param checkValue If OFTrue, values are checked for validity (not + * implemented yet) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setImageOrientationVolume(const Float64& rowX, + const Float64& rowY, + const Float64& rowZ, + const Float64& colX, + const Float64& colY, + const Float64& colZ, + const OFBool checkValue = OFTrue); + + /** Comparison operator that compares the normalized value of this object + * with a given object of the same type, i.e.\ the elements within both + * functional groups (this and rhs parameter) are compared by value! + * Both objects (this and rhs) need to have the same type (i.e.\ both + * FGUnknown) to be comparable. This function is used in order + * to decide whether a functional group already exists, or is new. This + * is used in particular to find out whether a given functional group + * can be shared (i.e.\ the same information already exists as shared + * functional group) or is different from the same shared group. In that + * case the shared functional group must be distributed into per-frame + * functional groups, instead. The exact implementation for implementing + * the comparison is not relevant. However, it must be a comparison + * by value. + * @param rhs the right hand side of the comparison + * @return 0 if the object values are equal. + * -1 if either the value of the first component that does not match + * is lower in the this object, or all compared components match + * but this component is shorter. Also returned if this type and + * rhs type (DcmFGTypes::E_FGType) do not match. + * 1 if either the value of the first component that does not match + * is greater in this object, or all compared components match + * but this component is longer. + */ + virtual int compare(const FGBase& rhs) const; + +private: + + /* Content of Plane Orientation (Volume) Macro */ + + /// Image Orientation (Volume) (FD, VM 6, Required type 1) + DcmFloatingPointDouble m_ImageOrientationVolume; +}; + +#endif // FGPLANORVOL_H diff --git a/dcmfg/include/dcmtk/dcmfg/fgplanpo.h b/dcmfg/include/dcmtk/dcmfg/fgplanpo.h new file mode 100644 index 00000000..bb9a8b34 --- /dev/null +++ b/dcmfg/include/dcmtk/dcmfg/fgplanpo.h @@ -0,0 +1,157 @@ +/* + * + * Copyright (C) 2015, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmfg + * + * Author: Michael Onken + * + * Purpose: Class for managing Plane Position (Patient) Functional Group + * + */ + +#ifndef FGPLANPO_H +#define FGPLANPO_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmfg/fgbase.h" +#include "dcmtk/dcmdata/dcsequen.h" +#include "dcmtk/dcmdata/dcvrds.h" + +/** Class representing the Plane Position (Patient) Functional Group containing + * the x, y, and z coordinates of the upper left hand corner (center of the + * first voxel transmitted) of the frame. + */ +class DCMTK_DCMFG_EXPORT FGPlanePosPatient : public FGBase +{ +public: + + /** Constructor, creates empty functional group + */ + FGPlanePosPatient(); + + /** Destructor, frees memory + */ + virtual ~FGPlanePosPatient(); + + /** Returs a deep copy of this object + * @return Deep copy of this object + */ + virtual FGBase *clone() const; + + /** Convenience function to create minimal functional group + * @param imagePositionPatientX The X coordinate of the upper left hand + * corner of the the frame in mm. + * @param imagePositionPatientY The Y coordinate of the upper left hand + * corner of the the frame in mm. + * @param imagePositionPatientZ The Z coordinate of the upper left hand + * corner of the the frame in mm. + */ + static FGPlanePosPatient* createMinimal(const OFString& imagePositionPatientX, + const OFString& imagePositionPatientY, + const OFString& imagePositionPatientZ); + + /** Returns that this functional group can be shared or per-frame (both) + * @return Always returns DcmFGTypes::EFGS_BOTH + */ + virtual DcmFGTypes::E_FGSharedType getSharedType() const {return DcmFGTypes::EFGS_BOTH;} + + /** Clears all data + */ + virtual void clearData(); + + /** Check whether data in functional group is valid + * @return EC_Normal if data is valid, error otherwise + */ + virtual OFCondition check() const; + + /** Read functional group from item, must contain the Plane Position Sequence + * @param item The item to read from + * @return EC_Normal if reading was succesful, error otherwise + */ + virtual OFCondition read(DcmItem& item); + + /** Write functional group to item, will write the Plane Position Sequence + * @param item The item to write to + * @return EC_Normal if writing was succesful, error otherwise + */ + virtual OFCondition write(DcmItem& item); + + /** Comparison operator that compares the normalized value of this object + * with a given object of the same type, i.e.\ the elements within both + * functional groups (this and rhs parameter) are compared by value! + * Both objects (this and rhs) need to have the same type (i.e.\ both + * FGUnknown) to be comparable. This function is used in order + * to decide whether a functional group already exists, or is new. This + * is used in particular to find out whether a given functional group + * can be shared (i.e.\ the same information already exists as shared + * functional group) or is different from the same shared group. In that + * case the shared functional group must be distributed into per-frame + * functional groups, instead. The exact implementation for implementing + * the comparison is not relevant. However, it must be a comparison + * by value. + * @param rhs the right hand side of the comparison + * @return 0 if the object values are equal. + * -1 if either the value of the first component that does not match + * is lower in the this object, or all compared components match + * but this component is shorter. Also returned if this type and + * rhs type (DcmFGTypes::E_FGType) do not match. + * 1 if either the value of the first component that does not match + * is greater in this object, or all compared components match + * but this component is longer. + */ + virtual int compare(const FGBase& rhs) const; + + // --- get() functionality --- + + /** Get Image Position Patient + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getImagePositionPatient(OFString& value, + const signed long pos); + + /** Retrieve all values of Image Orientation Patient at the same time + * @param coordinateX X coordinate of upper left hand corner voxel in mm + * @param coordinateY Y coordinate of upper left hand corner voxel in mm + * @param coordinateZ Z coordinate of upper left hand corner voxel in mm + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getImagePositionPatient(Float64& coordinateX, + Float64& coordinateY, + Float64& coordinateZ); + + // --- set() functionality --- + + /** Set Image Position Patient. The x, y, and z coordinates of the upper left + * hand corner (center of the first voxel transmitted) of the frame, in mm. + * @param coordinateX X coordinate of upper left hand corner voxel in mm + * @param coordinateY Y coordinate of upper left hand corner voxel in mm + * @param coordinateZ Z coordinate of upper left hand corner voxel in mm + * @param checkValue Check coordinates for validity, including VR (DS) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setImagePositionPatient(const OFString& coordinateX, + const OFString& coordinateY, + const OFString& coordinateZ, + const OFBool checkValue = OFTrue); + +private: + + /* Content of Plane Position Patient Macro */ + + /// Image Position (Patient) (DS, VM 3, Required type 1C) + DcmDecimalString m_ImagePositionPatient; +}; + +#endif // FGPLANPO_H diff --git a/dcmfg/include/dcmtk/dcmfg/fgplanposvol.h b/dcmfg/include/dcmtk/dcmfg/fgplanposvol.h new file mode 100644 index 00000000..224395cf --- /dev/null +++ b/dcmfg/include/dcmtk/dcmfg/fgplanposvol.h @@ -0,0 +1,157 @@ +/* + * + * Copyright (C) 2015, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmfg + * + * Author: Michael Onken + * + * Purpose: Class for managing Plane Position (Volume) Functional Group + * + */ + +#ifndef FGPLANEPOSVOL_H +#define FGPLANEPOSVOL_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmdata/dcitem.h" +#include "dcmtk/dcmfg/fgbase.h" + +/** Class representing the Plane Position (Volume) Functional Group that + * identifies the position of the plane of this frame. + */ +class DCMTK_DCMFG_EXPORT FGPlanePositionVolume : public FGBase +{ +public: + + /** Constructor, creates empty functional group + */ + FGPlanePositionVolume(); + + /** Virtual desctructor, frees memory + */ + virtual ~FGPlanePositionVolume(); + + /** Returs a deep copy of this object + * @return Deep copy of this object + */ + virtual FGBase *clone() const; + + /** Returns shared type of this functional group (can be shared or per-frame, + * i.e.\ both) + * @return Always returns DcmFGTypes::EFGS_BOTH + */ + virtual DcmFGTypes::E_FGSharedType getSharedType() const {return DcmFGTypes::EFGS_BOTH;} + + /** Clears all data + */ + virtual void clearData(); + + /** Check whether data of this functional group is valid + * @return EC_Normal if data is valid, error otherwise + */ + virtual OFCondition check() const; + + /** Read functional group from item, must contain the Plane Position (Volume) + * Sequence + * @param item The item to read from + * @return EC_Normal if reading was succesful, error otherwise + */ + virtual OFCondition read(DcmItem& item); + + /** Writes functional group to item, i.e.\ writes the Plane Position (Volume) + * Sequence + * @param item The item to write to + * @return EC_Normal if writing was succesful, error otherwise + */ + virtual OFCondition write(DcmItem& item); + + // --- get() functionality --- + + /** Get Image Position Volume + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getImagePositionVolume(Float64& value, + const unsigned long pos = 0); + + /** Retrieve all values of Image Position Volume at the same time + * @param valueX X coordinate of upper left hand corner voxel in mm + * @param valueY Y coordinate of upper left hand corner voxel in mm + * @param valueZ Z coordinate of upper left hand corner voxel in mm + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getImagePositionVolume(Float64& valueX, + Float64& valueY, + Float64& valueZ); + + // --- set() functionality --- + + /** Set Image Position Volume, i.e.\ the x/y/z coordinates of the upper left + * hand corner (center of the first voxel transmitted) of the frame, in mm. + * @param value X,Y or Z coordinate of upper left hand corner voxel in mm + * @param pos pos 0 is x, pos 1 is Y, pos 2 addresses Z coordinate + * @param checkValue Check coordinates for validity, including VR (FD) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setImagePositionVolume(const Float64& value, + const unsigned long pos = 0, + const OFBool checkValue = OFTrue); + + /** Set Image Position Volume, i.e.\ the x/y/z coordinates of the upper left + * hand corner (center of the first voxel transmitted) of the frame, in mm. + * @param valueX X coordinate of upper left hand corner voxel in mm + * @param valueY coordinate of upper left hand corner voxel in mm + * @param valueZ coordinate of upper left hand corner voxel in mm + * @param checkValue Check coordinates for validity, including VR (FD) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setImagePositionVolume(const Float64& valueX, + const Float64& valueY, + const Float64& valueZ, + const OFBool checkValue = OFTrue); + + /** Comparison operator that compares the normalized value of this object + * with a given object of the same type, i.e.\ the elements within both + * functional groups (this and rhs parameter) are compared by value! + * Both objects (this and rhs) need to have the same type (i.e.\ both + * FGUnknown) to be comparable. This function is used in order + * to decide whether a functional group already exists, or is new. This + * is used in particular to find out whether a given functional group + * can be shared (i.e.\ the same information already exists as shared + * functional group) or is different from the same shared group. In that + * case the shared functional group must be distributed into per-frame + * functional groups, instead. The exact implementation for implementing + * the comparison is not relevant. However, it must be a comparison + * by value. + * @param rhs the right hand side of the comparison + * @return 0 if the object values are equal. + * -1 if either the value of the first component that does not match + * is lower in the this object, or all compared components match + * but this component is shorter. Also returned if this type and + * rhs type (DcmFGTypes::E_FGType) do not match. + * 1 if either the value of the first component that does not match + * is greater in this object, or all compared components match + * but this component is longer. + */ + virtual int compare(const FGBase& rhs) const; + +private: + + /* Content of Plane Position (Volume) Macro */ + + /// Image Position (Volume) (FD, VM 3, Required type 1) + DcmFloatingPointDouble m_ImagePositionVolume; +}; + +#endif // FGPLANEPOSVOL_H diff --git a/dcmfg/include/dcmtk/dcmfg/fgrealworldvaluemapping.h b/dcmfg/include/dcmtk/dcmfg/fgrealworldvaluemapping.h new file mode 100644 index 00000000..4217749d --- /dev/null +++ b/dcmfg/include/dcmtk/dcmfg/fgrealworldvaluemapping.h @@ -0,0 +1,372 @@ +/* + * + * Copyright (C) 2015, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmfg + * + * Author: Michael Onken + * + * Purpose: Class for managing Real World Value Mapping Functional Group + * + */ + +#ifndef FGREALWORLDVALUEMAPPING_H +#define FGREALWORLDVALUEMAPPING_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmfg/fgbase.h" +#include "dcmtk/dcmdata/dcitem.h" +#include "dcmtk/dcmiod/modbase.h" +#include "dcmtk/dcmiod/iodmacro.h" + +/** Class representing the Real World Value Mapping Functional Group that + * specifies the mapping of stored values to associated Real World values + */ +class DCMTK_DCMFG_EXPORT FGRealWorldValueMapping: public FGBase +{ +public: + + // Forward declaration + class RWVMItem; + + /** Constructor, creates empty functional group + */ + FGRealWorldValueMapping(); + + /** Desctructor, frees memory + */ + virtual ~FGRealWorldValueMapping(); + + /** Returs a deep copy of this object + * @return Deep copy of this object + */ + virtual FGBase *clone() const; + + /** Returns that this functional group can be used as both, shared + * and per-frame + * @returns Always returns DcmFGTypes::EFGS_BOTH + */ + virtual DcmFGTypes::E_FGSharedType getSharedType() const {return DcmFGTypes::EFGS_BOTH;} + + /** Clear all data + */ + virtual void clearData(); + + /** Check whether data of functional group is valid + * @return EC_Normal if data is valid, error otherwise + */ + virtual OFCondition check() const; + + + /** Read functional group from item, must contain the Real World Value Mapping + * Sequence + * @param item The item to read from + * @return EC_Normal if reading was succesful, error otherwise + */ + virtual OFCondition read(DcmItem& item); + + /** Writes this functional group to item, i.e.\ will write the Real World Value + * Mapping Sequence + * @param item The item to read from + * @return EC_Normal if reading was succesful, error otherwise + */ + virtual OFCondition write(DcmItem& item); + + // --- get() functionality --- + + /** Return references to the various items inside the Real World Value Mapping + * Sequence + * @return Reference to Real World Value Mapping Sequence items + */ + virtual OFVector< RWVMItem* >& getRealWorldValueMapping(); + + /** Comparison operator that compares the normalized value of this object + * with a given object of the same type, i.e.\ the elements within both + * functional groups (this and rhs parameter) are compared by value! + * Both objects (this and rhs) need to have the same type (i.e.\ both + * FGUnknown) to be comparable. This function is used in order + * to decide whether a functional group already exists, or is new. This + * is used in particular to find out whether a given functional group + * can be shared (i.e.\ the same information already exists as shared + * functional group) or is different from the same shared group. In that + * case the shared functional group must be distributed into per-frame + * functional groups, instead. The exact implementation for implementing + * the comparison is not relevant. However, it must be a comparison + * by value. + * @param rhs the right hand side of the comparison + * @return 0 if the object values are equal. + * -1 if either the value of the first component that does not match + * is lower in the this object, or all compared components match + * but this component is shorter. Also returned if this type and + * rhs type (DcmFGTypes::E_FGType) do not match. + * 1 if either the value of the first component that does not match + * is greater in this object, or all compared components match + * but this component is longer. + */ + virtual int compare(const FGBase& rhs) const; + +private: + + /* Content of Real World Value Mapping Macro */ + + /// Items (1-n) of Real World Value Mapping Sequence + OFVector m_Items; +}; + +/** Class representing the Real World Value Mapping Item Macro: + * Attribute name: (VR, VM, Requirement Type) + * Real World Value First Value Mapped: (US or SS, 1, 1) + * Real World Value Last Value Mapped: (US or SS, 1, 1) + * Real World Value Intercept: (FD, 1, 1C) + * Real World Value Slope: (FD, 1, 1C) + * Real World Value LUT Data (FD, 1-n, 1C) + * LUT Explanation (LO, 1, 1) + * LUT Label (SH, 1, 1) + * Measurement Units Code Sequence (SQ, 1, 1) + * Not yet supported: Quantity Definition Sequence (SQ, 1, 3) + */ +class DCMTK_DCMFG_EXPORT FGRealWorldValueMapping::RWVMItem : public IODComponent +{ +public: + + /** Constructor + * @param item The item to be used for data storage. If NULL, the + * class creates an empty data container. + * @param rules The rule set for this class. If NULL, the class creates + * one from scratch and adds its values. + * @param parent The parent of the IOD component (NULL if none or unknown) + */ + RWVMItem(OFshared_ptr item, + OFshared_ptr rules, + IODComponent* parent = NULL); + + /** Constructor + * @param parent The parent of the IOD component (NULL if none or unknown) + */ + RWVMItem(IODComponent* parent = NULL); + + /** Clone this class (perform deep copy) + * @return Clone of this class or NULL (e.g.\ if memory exhausted) + */ + RWVMItem* clone(); + + /** Virtual destructor, frees memory + */ + virtual ~RWVMItem(); + + /** Resets rules to their original values + */ + virtual void resetRules(); + + /** Get name of component + * @return Name of the module + */ + virtual OFString getName() const; + + /** Comparison operator that compares the normalized value of this object + * with a given object of the same type, i.e.\ the elements within both + * functional groups (this and rhs parameter) are compared by value! + * Both objects (this and rhs) need to have the same type (i.e.\ both + * FGUnknown) to be comparable. This function is used in order + * to decide whether a functional group already exists, or is new. This + * is used in particular to find out whether a given functional group + * can be shared (i.e.\ the same information already exists as shared + * functional group) or is different from the same shared group. In that + * case the shared functional group must be distributed into per-frame + * functional groups, instead. The exact implementation for implementing + * the comparison is not relevant. However, it must be a comparison + * by value. + * @param rhs the right hand side of the comparison + * @return 0 if the object values are equal. + * -1 if either the value of the first component that does not match + * is lower in the this object, or all compared components match + * but this component is shorter. Also returned if this type and + * rhs type (DcmFGTypes::E_FGType) do not match. + * 1 if either the value of the first component that does not match + * is greater in this object, or all compared components match + * but this component is longer. + */ + virtual int compare(const IODComponent& rhs) const; + + /** Read attributes from given item into this class + * @param source The source to read from + * @param clearOldData If OFTrue, old data is cleared before reading. + * Otherwise old data is overwritten (or amended) + * @result EC_Normal if reading was successful, error otherwise + */ + virtual OFCondition read(DcmItem& source, + const OFBool clearOldData = OFTrue); + + /** Write attributes from this class into given item + * @param destination The item to write to + * @result EC_Normal if writing was successful, error otherwise + */ + virtual OFCondition write(DcmItem& destination); + + // --- get() functionality --- + + /** Get Real World Value First Value Mapped + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getRealWorldValueFirstValueMapped(Sint32& value, + const unsigned long pos = 0) const; + + /** Get Real World Value First Value Mapped + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getRealWorldValueLastValueMapped(Sint32 &value, + const unsigned long pos = 0) const; + + /** Get Real World Value LUT Data + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getRealWorldValueLUTData(Float64 &value, + const unsigned long pos = 0) const; + + /** Get Real World Value LUT Data + * @param values Reference to variable in which the values should be stored + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getRealWorldValueLUTData(OFVector& values) const; + + /** Get LUT Explanation + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getLUTExplanation(OFString &value, + const signed long pos = 0) const; + + /** Get LUT Label + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getLUTLabel(OFString &value, + const signed long pos = 0) const; + + /** Get Measurement Units Code Sequence (content) + * @return Reference to Measurement Units Code + */ + virtual CodeSequenceMacro& getMeasurementUnitsCode(); + + // --- set() functionality --- + + /** Set Real World Value First Value Mapped + * @param value Value to be set. If Pixel Representation is 0 (unsigned + * pixel data) value must be 0 < value < 2^16. Otherwise use + * setRealWorldValueFirstValueMappedSigned(). + * @param checkValue Check 'value' for conformance with VR (US and VM (1) + * if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setRealWorldValueFirstValueMappedUnsigned(const Uint16 &value, + const OFBool checkValue = OFTrue); + + /** Set Real World Value First Value Mapped + * @param value Value to be set. If Pixel Representation is -1 (signed + * pixel data) value must be -2^15 < value < 2^15-1. Otherwise use + * setRealWorldValueFirstValueMappedUnSigned(). + * @param checkValue Check 'value' for conformance with VR (SS) and VM (1) + * if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setRealWorldValueFirstValueMappeSigned(const Sint16 &value, + const OFBool checkValue = OFTrue); + + /** Set Real World Value Last Value Mapped + * @param value Value to be set. If Pixel Representation is 0 (unsigned + * pixel data) value must be 0 < value < 2^16. Otherwise use + * setRealWorldValueLastValueMappedSigned(). + * @param checkValue Check 'value' for conformance with VR (US and VM (1) + * if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setRealWorldValueLastValueMappedUnsigned(const Uint16 &value, + const OFBool checkValue = OFTrue); + + /** Set Real World Value Last Value Mapped + * @param value Value to be set. If Pixel Representation is -1 (signed + * pixel data) value must be -2^15 < value < 2^15-1. Otherwise use + * setRealWorldValueLastValueMappedUnSigned(). + * @param checkValue Check 'value' for conformance with VR (SS) and VM (1) + * if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setRealWorldValueLastValueMappedSigned(const Sint16 &value, + const OFBool checkValue = OFTrue); + + /** Set Real World Value Intercept + * @param value Value to be set + * @param checkValue Check 'value' for conformance with VR (FD) and VM (1) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setRealWorldValueIntercept(const Float64& value, + const OFBool checkValue = OFTrue); + + /** Set Real World Value Slope + * @param value Value to be set + * @param checkValue Check 'value' for conformance with VR (FD) and VM (1) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setRealWorldValueSlope(const Float64& value, + const OFBool checkValue = OFTrue); + + /** Set Real World Value LUT Data + * @param value Values to be set + * @param checkValue Check 'value' for conformance with VR (FD) and VM (1-n) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setRealWorldValueLUTData(const OFVector& value, + const OFBool checkValue = OFTrue); + + /** Set LUT Explanation + * @param value Value to be set + * @param checkValue Check 'value' for conformance with VR (LO) and VM (1) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setLUTExplanation(const OFString &value, + const OFBool checkValue = OFTrue); + + /** Set LUT Label + * @param value Value to be set + * @param checkValue Check 'value' for conformance with VR (SH) and VM (1) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setLUTLabel(const OFString &value, + const OFBool checkValue = OFTrue); + +protected: + + static OFCondition getUSorSS(DcmItem& item, + const DcmTagKey& key, + const unsigned long pos, + Sint32& value); + +private: + + /// The name of this module ("RealWorldValueMappingItemMacro") + static const OFString m_ModuleName; + + /// Measurement Units Code Sequence + CodeSequenceMacro m_MeasurementUnitsCode; + + /// TODO Content Item Macro for Quantity Definition Sequence +}; + +#endif // FGREALWORLDVALUEMAPPING_H diff --git a/dcmfg/include/dcmtk/dcmfg/fgseg.h b/dcmfg/include/dcmtk/dcmfg/fgseg.h new file mode 100644 index 00000000..c14752e1 --- /dev/null +++ b/dcmfg/include/dcmtk/dcmfg/fgseg.h @@ -0,0 +1,128 @@ +/* + * + * Copyright (C) 2015, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmfg + * + * Author: Michael Onken + * + * Purpose: Class for managing Segmentation Functional Group + * + */ + +#ifndef FGSEG_H +#define FGSEG_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmdata/dcitem.h" +#include "dcmtk/dcmdata/dcsequen.h" +#include "dcmtk/dcmdata/dcvrus.h" +#include "dcmtk/dcmfg/fgbase.h" + +/** Class representing the Segmentation Functional Group Macro + */ +class DCMTK_DCMFG_EXPORT FGSegmentation : public FGBase +{ + +public: + + /** Constructor, creates empty functional group + */ + FGSegmentation(); + + /** Desctructor, frees memory + */ + virtual ~FGSegmentation(); + + /** Returs a deep copy of this object + * @return Deep copy of this object + */ + virtual FGBase *clone() const; + + /** Returns that this functional group can be used shared or per-frame, + * i.e.\ both + * @return Always returns DcmFGTypes::EFGS_BOTH + */ + virtual DcmFGTypes::E_FGSharedType getSharedType() const {return DcmFGTypes::EFGS_BOTH;} + + /** Clear all data + */ + virtual void clearData(); + + /** Check whether data in this functional group is valid + * @return EC_Normal if data is valid, error otherwise + */ + OFCondition check() const; + + /** Comparison operator that compares the normalized value of this object + * with a given object of the same type, i.e.\ the elements within both + * functional groups (this and rhs parameter) are compared by value! + * Both objects (this and rhs) need to have the same type (i.e.\ both + * FGSegmentation) to be comparable. This function is used in order + * to decide whether a functional group already exists, or is new. This + * is used in particular to find out whether a given functional group + * can be shared (i.e.\ the same information already exists as shared + * functional group) or is different from the same shared group. In that + * case the shared functional group must be distributed into per-frame + * functional groups, instead. The exact implementation for implementing + * the comparison is not relevant. However, it must be a comparison + * by value. + * @param rhs the right hand side of the comparison + * @return 0 if the object values are equal. + * -1 if either the value of the first component that does not match + * is lower in the rhs object, or all compared components match + * but the rhs component is shorter. Also returned if this type and + * rhs type (DcmFGTypes::E_FGType) do not match. + * 1 if either the value of the first component that does not match + * is greater in the rhs object, or all compared components match + * but the rhs component is longer. + */ + virtual int compare(const FGBase& rhs) const; + + /** Get Referenced Segment Number + * @param value Reference to variable in which the value should be stored + * @param pos Index value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getReferencedSegmentNumber(Uint16 &value, + const unsigned long pos = 0); + + /** Set Referenced Segment Number + * @param segmentNumber Value to be set + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setReferencedSegmentNumber(const Uint16 &segmentNumber); + + /** Read functional group from item, must contain the Segment Identification + * Sequence + * @param item The item to read from + * @return EC_Normal if reading was succesful, error otherwise + */ + virtual OFCondition read(DcmItem& item); + + /** Write functional group to item, will write Segment Identification + * Sequence + * @param item The item to write to + * @return EC_Normal if writing was succesful, error otherwise + */ + virtual OFCondition write(DcmItem& item); + +private: + + /// Referenced Segment Number: (US, 1-n, 1) + /// Represents single value within the single permitted item of the + /// Segment Identification Sequence being the data structure the + /// Segmentation FG is made of. + DcmUnsignedShort m_ReferencedSegmentNumber; +}; + +#endif // FGSEG_H diff --git a/dcmfg/include/dcmtk/dcmfg/fgtypes.h b/dcmfg/include/dcmtk/dcmfg/fgtypes.h new file mode 100644 index 00000000..791f67a8 --- /dev/null +++ b/dcmfg/include/dcmtk/dcmfg/fgtypes.h @@ -0,0 +1,209 @@ +/* + * + * Copyright (C) 2015, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmfg + * + * Author: Michael Onken + * + * Purpose: Class for managing common functional group types + * + */ + +#ifndef FGTYPES_H +#define FGTYPES_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/oflog/oflog.h" +#include "dcmtk/dcmdata/dctk.h" +#include "dcmtk/dcmfg/fgdefine.h" + +class FGBase; +class FunctionalGroups; + +/*-----------------------* + * logging * + *-----------------------*/ + +extern DCMTK_DCMFG_EXPORT OFLogger DCM_dcmfgLogger; + +#define DCMFG_TRACE(msg) OFLOG_TRACE(DCM_dcmfgLogger, msg) +#define DCMFG_DEBUG(msg) OFLOG_DEBUG(DCM_dcmfgLogger, msg) +#define DCMFG_INFO(msg) OFLOG_INFO(DCM_dcmfgLogger, msg) +#define DCMFG_WARN(msg) OFLOG_WARN(DCM_dcmfgLogger, msg) +#define DCMFG_ERROR(msg) OFLOG_ERROR(DCM_dcmfgLogger, msg) +#define DCMFG_FATAL(msg) OFLOG_FATAL(DCM_dcmfgLogger, msg) + + +/*-----------------------* + * constant definitions * + *-----------------------*/ + +/* Specific error conditions for module dcmfg.(TODO) + * These error codes can be used in addition to the general purpose + * codes defined in module dcmdata. + */ + +/// Functional group already exists +extern DCMTK_DCMFG_EXPORT const OFConditionConst FG_EC_DoubledFG; +/// Specified functional group does not exist +extern DCMTK_DCMFG_EXPORT const OFConditionConst FG_EC_NoSuchGroup; +/// Not enough items +extern DCMTK_DCMFG_EXPORT const OFConditionConst FG_EC_NotEnoughItems; +/// Too many Items +extern DCMTK_DCMFG_EXPORT const OFConditionConst FG_EC_TooManyItems; +/// Invalid data +extern DCMTK_DCMFG_EXPORT const OFConditionConst FG_EC_InvalidData; +/// Could not write functional group +extern DCMTK_DCMFG_EXPORT const OFConditionConst FG_EC_CouldNotWriteFG; +/// Could not insert functional group +extern DCMTK_DCMFG_EXPORT const OFConditionConst FG_EC_CouldNotInsertFG; +/// No such shared functional group +extern DCMTK_DCMFG_EXPORT const OFConditionConst FG_EC_NoSharedFG; +/// No such per-frame functional group +extern DCMTK_DCMFG_EXPORT const OFConditionConst FG_EC_NoPerFrameFG; +/// Could not create functional group +extern DCMTK_DCMFG_EXPORT const OFConditionConst FG_EC_CouldNotCreateFG; +/// Could not create functional group +extern DCMTK_DCMFG_EXPORT const OFConditionConst FG_EC_CouldNotReadSourceImage; +/// Could not create functional group +extern DCMTK_DCMFG_EXPORT const OFConditionConst FG_EC_CouldNotAddFG; +/// Not enough frames found +extern DCMTK_DCMFG_EXPORT const OFConditionConst FG_EC_NotEnoughFrames; +/// No stacks speficied (but expected) +extern DCMTK_DCMFG_EXPORT const OFConditionConst FG_EC_NoStacksFound; + +/*---------------------* + * class declaration * + *---------------------*/ + +/** General purpose class hiding global functions, constants and types related + * to functional groups from the global namespace. + */ +class DCMTK_DCMFG_EXPORT DcmFGTypes +{ + +public: + + // --- Type definitions --- + + /** Functional group types + */ + enum E_FGType + { + /// Undefined functional group + EFG_UNDEFINED, + /// Unknown functional group + EFG_UNKNOWN, + /// Cardiac Synchronization + EFG_CARDIACSYNC, + /// Contrast/Bolus Usage + EFG_CONTRASTBOLUSUSAGE, + /// Derivation Image + EFG_DERIVATIONIMAGE, + /// Frame Anantomy + EFG_FRAMEANATOMY, + /// Frame Content + EFG_FRAMECONTENT, + /// Frame Display Shutter + EFG_FRAMEDISPLAYSHUTTER, + /// Frame Pixel Shift + EFG_FRAMEPIXELSHIFT, + /// "Frame VOI LUT" or "Frame VOI LUT with LUT" Macro (share same starting sequence) + EFG_FRAMEVOILUTMETA, + /// Image Data Type + EFG_IMAGEDATATYPE, + /// Irradiation Event Identification + EFG_IRRADIATIONEVENTIDENT, + /// Patient Orientation in Frame + EFG_PATIENTORIENTINFRAME, + /// Patient Physiological State + EFG_PATIENTPHYSIOSTATE, + /// Pixel Intensity Relationship LUT + EFG_PIXELINTENSITYRELLUT, + /// Pixel Measures + EFG_PIXELMEASURES, + /// "Pixel Value Transformation" or "Identity Pixel Value Transformation" Macro (share same sequence and attributes) + EFG_PIXELVALUETRANSMETA, + /// Plane Orientation (Volume) + EFG_PLANEORIENTVOLUME, + /// Plane Position (Volume) + EFG_PLANEPOSITIONVOLUME, + /// Plane Position (Patient) + EFG_PLANEPOSPATIENT, + /// Plane Orientation (Patient) + EFG_PLANEORIENTPATIENT, + /// Radiopharmaceutical Usage + EFG_RADIOPHARAMAUSAGE, + /// Real World Value Mapping + EFG_REALWORLDVALUEMAPPING, + /// Respiratory Synchronization + EFG_RESPIRATORYSYNC, + /// Segmentation Macro + EFG_SEGMENTATION, + /// Temporal Position Macro + EFG_TEMPORALPOSITION, + /// Unassigned Shared Converted Attributes Macro + EFG_UNASSIGNEDSHAREDCONVERTEDATTRIBUTES, + /// US Image Description Macro + EFG_USIMAGEDESCRIPTION + }; + + /** Functional group types + */ + enum E_FGSharedType + { + /// Unknown + EFGS_UNKNOWN, + /// Functional Group can be shared or per-frame + EFGS_BOTH, + /// Functional Group can only pe shared (not per-frame) + EFGS_ONLYSHARED, + /// Functional Group can only pe per-frame (not shared) + EFGS_ONLYPERFRAME + }; + + /** US Image Description Frame Type (first value) + */ + enum E_FGUSFrameType + { + /// Unknown + EFGFT_UNKNOWN, + /// ORIGINAL + EFGFT_ORIGINAL, + /// DERIVED + EFGFT_DERIVED + }; + + // -- static helpers -- + + /** Returns functional group type based on tag key + * @param key The key to get the group type for + * @return The functional group type + */ + static E_FGType tagKey2FGType(const DcmTagKey& key); + + /** Returns the name of the functional group based on the group type + * @param fgType The functional group type + * @return The name of the functional group + */ + static OFString FGType2OFString(const E_FGType fgType); + + /** Returns the name of a functional group based on a given tag key + * @param key The tag key to get the functional group type for + * @return The name of the functional group + */ + static OFString tagKey2FGString(const DcmTagKey& key); + +}; + +#endif // FGTYPES_H diff --git a/dcmfg/include/dcmtk/dcmfg/fgusimagedescription.h b/dcmfg/include/dcmtk/dcmfg/fgusimagedescription.h new file mode 100644 index 00000000..731c8729 --- /dev/null +++ b/dcmfg/include/dcmtk/dcmfg/fgusimagedescription.h @@ -0,0 +1,183 @@ +/* + * + * Copyright (C) 2015, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmfg + * + * Author: Michael Onken + * + * Purpose: Class for managing US Image Description Functional Group + * + */ + +#ifndef FGUSIMAGEDESCRIPTION_H +#define FGUSIMAGEDESCRIPTION_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmdata/dcitem.h" +#include "dcmtk/dcmfg/fgtypes.h" +#include "dcmtk/dcmfg/fgbase.h" + +/** Class representing the US Image Description Functional Group + */ +class DCMTK_DCMFG_EXPORT FGUSImageDescription: public FGBase +{ +public: + + /** Constructor, creates empty functional group + */ + FGUSImageDescription(); + + /** Desctructor, frees memory + */ + virtual ~FGUSImageDescription(); + + /** Returs a deep copy of this object + * @return Deep copy of this object + */ + virtual FGBase *clone() const; + + /** Clears all data + */ + virtual void clearData(); + + /** Check whether data in this functional group is valid + * @return EC_Normal if data is valid, error otherwise + */ + virtual OFCondition check() const; + + /** Read functional group from item, must contain the US Image Description + * Sequence + * @param item The item to read from + * @return EC_Normal if reading was succesful, error otherwise + */ + virtual OFCondition read(DcmItem &item); + + /** Write functional group to item, will write to US Image Description + * Sequence + * @param item The item to write to + * @return EC_Normal if writing was succesful, error otherwise + */ + virtual OFCondition write(DcmItem& item); + + /** Get shared type of this functional group (can be both, shared and + * per-frame) + * @return Always returns DcmFGTypes::EFGS_BOTH + */ + virtual DcmFGTypes::E_FGSharedType getSharedType() const {return DcmFGTypes::EFGS_BOTH;} + + // --- get() functionality --- + + /** Get Frame Type + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getFrameType(OFString& value, + const signed long pos = 0); + + /** Get Volumetric Properties + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getVolumetricProperties(OFString& value, + const signed long pos = 0); + + /** Get Volume Based Calculation Technique + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getVolumeBasedCalculationTechnique(OFString& value, + const signed long pos = 0); + + // --- set() functionality --- + + /** Set Frame Type. Frame Type contains up to four values. Value 3 and 4 are + * optional and can be left empty if desired. The values in their order + * of occurence are: + * 1) Pixel Data Characteristics: Either ORIGINAL or DERIVED + * 2) Patient Examination Characteristics: Fixed to "PRIMARY", thus cannot be + * influenced through this function. + * 3) Image Flavor: Defined Terms listed in the standard + * 4) Derived Pixel Contrast: Defined Terms listed in the standard + * @param pixelDataChar Value 1 of Frame Type + * @param imageFlavor Value 3 of Frame Type + * @param derivedPixelContrast Value 4 of Frame Type + * @param checkValue If OFTrue, the value is checked for conformance. + * @return EC_Normal if setting was successful, error otherwise. + */ + virtual OFCondition setFrameType(const DcmFGTypes::E_FGUSFrameType pixelDataChar, + const OFString& imageFlavor = "", + const OFString& derivedPixelContrast = "", + const OFBool checkValue = OFTrue); + + /** Set Volumetric Properties + * @param value The value to set. Permitted values: + * "VOLUME", "SAMPLED", "DISTORTED", "MIXED" + * @param checkValue If OFTrue, the value is checked for conformance + * @return EC_Normal if setting was successful, error otherwise. + */ + virtual OFCondition setVolumetricProperties(const OFString& value, + const OFBool checkValue = OFTrue); + + /** Set Volume Based Calculation Technique + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR (CS) and VM (1) + * if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setVolumeBasedCalculationTechnique(const OFString& value, + const OFBool checkValue = OFTrue); + + /** Comparison operator that compares the normalized value of this object + * with a given object of the same type, i.e.\ the elements within both + * functional groups (this and rhs parameter) are compared by value! + * Both objects (this and rhs) need to have the same type (i.e.\ both + * FGUnknown) to be comparable. This function is used in order + * to decide whether a functional group already exists, or is new. This + * is used in particular to find out whether a given functional group + * can be shared (i.e.\ the same information already exists as shared + * functional group) or is different from the same shared group. In that + * case the shared functional group must be distributed into per-frame + * functional groups, instead. The exact implementation for implementing + * the comparison is not relevant. However, it must be a comparison + * by value. + * @param rhs the right hand side of the comparison + * @return 0 if the object values are equal. + * -1 if either the value of the first component that does not match + * is lower in the this object, or all compared components match + * but this component is shorter. Also returned if this type and + * rhs type (DcmFGTypes::E_FGType) do not match. + * 1 if either the value of the first component that does not match + * is greater in this object, or all compared components match + * but this component is longer. + */ + virtual int compare(const FGBase& rhs) const; + +private: + + /* Content of US Image Description Macro */ + + /// Frame Type (CS, VM 4, Required type 1) + DcmCodeString m_FrameType; + + /// Volumetric Properties (CS 1, VM 1, Required Type 1) + DcmCodeString m_VolumetricProperties; + + /// Volume Based Calculation Technique (CS, VM 1, Required Type 1) + DcmCodeString m_VolumeBasedCalculationTechnique; +}; + +#endif // FGUSIMAGEDESCRIPTION_H + diff --git a/dcmfg/include/dcmtk/dcmfg/stack.h b/dcmfg/include/dcmtk/dcmfg/stack.h new file mode 100644 index 00000000..2af57442 --- /dev/null +++ b/dcmfg/include/dcmtk/dcmfg/stack.h @@ -0,0 +1,144 @@ +/* + * + * Copyright (C) 2015, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmfg + * + * Author: Michael Onken + * + * Purpose: Class representing a stack in the context of Enhanced DICOM objects + * + */ + +#ifndef FGSTACK_H +#define FGSTACK_H + +#include "dcmtk/config/osconfig.h" +#include +#include "dcmtk/ofstd/ofstring.h" +#include "dcmtk/ofstd/ofvector.h" +#include "dcmtk/dcmfg/fgdefine.h" + +/** Class representing a stack in the context of an Enhanced DICOM object. + * Therefore the class stores the ID of the stack (Stack ID) and all the frame + * numbers being part of that stack, as well as for each frame its position + * within the stack. + */ +class DCMTK_DCMFG_EXPORT FGStack +{ +public: + + // Make sure the main interface class has easy access to internal members + friend class FGStackInterface; + + /// Iterator type for iterating over the frames of a stack + typedef OFMap::iterator iterator; + + /// Const terator for iterating over the frames of a stack + typedef OFMap::const_iterator const_iterator; + + /** Constructor, creates stack from Stack ID and assigned frame numbers + * @param stackID The Stack ID of the stack + * @param frameNumbers A map with frame numbers as the keys, and the + * position of the frame within the stack as the value for each + * frame. First position is 1. There may be frames having the same + * positions in the same stack. However, in that case the standard + * lists some elements which at least must have the same values, then: + * - Dimension Organization UID (0020,9164) to qualify the Stack ID + * - Image Position (Patient) (0020,0032) + * - Image Orientation (Patient) (0020,0037) + * - Rows (0028,0010) * first value of Pixel Spacing (0028,0030) (= field of view in the row direction) + * - Columns (0028,0011) * second value of Pixel Spacing (0028,0030) (= field of view in the column direction) + * - Slice Thickness (0018,0050) + * The values may change over time (last check was DICOM 2014a), so + * the latest edition of the standard should be consulted if it is + * planned to apply the same in-stack position to different frames. + */ + FGStack(const OFString& stackID, + const OFMap frameNumbers); + + /** Constructor, create empty stack with given Stack ID (and fill in frames + * later) + * @param stackID The Stack ID of the frame + */ + FGStack(const OFString& stackID); + + /** Virtual destructor, frees memory + */ + virtual ~FGStack(); + + // TODO add sorted iterators using views, for example + + /** Return const iterator to first frame (not sorted after stack position) + * @return Const iterator to first frame + */ + const_iterator begin() const; + + /** Return iterator to first frame (not sorted after stack position) + * @return Iterator to first frame + */ + iterator begin(); + + /** Return const iterator pointing behind last frame (not sorted after stack position) + * @return Const iterator pointing behind last frame + */ + const_iterator end() const; + + /** Return iterator pointing behind last frame (not sorted after stack position) + * @return Iterator pointing behind last frame + */ + iterator end(); + + /** Add frame to stack and set its in-stack position. Any old position + * will be overwritten. + * @param frameNumber The frame number that should be added to the stack + * @param inStackPos The position in the stack (starting from 1). More than + * one frame can have the same position in the stack, however there + * are rules (see documentation of constructor and the DICOM + * standard) + */ + virtual OFBool addFrame(const Uint32 frameNumber, + const Uint32 inStackPos); + + /** Get Stack ID uniquely identifying this stack + * @return The Stack ID + */ + virtual OFString getStackID() const; + + /** Get the stack position for a given frame + * @param frameNumber The number of the frame + * @return The stack position for that frame + */ + Uint32 getInStackPos(const Uint32 frameNumber) const; + + /** Get list of frames that are set to a specific In-Stack Position + * @param inStackPos In-Stack Position Number to find frames for + * @param resultFrameNumbers The frame numbers assigned to that stack + * position + */ + void getFramesAtStackPos(const Uint32 inStackPos, + OFVector& resultFrameNumbers); + +private: + + /// The Stack ID of this frame + OFString m_StackID; + + /// Map with frames, key is the frame number, value is the in-stack position. + /// More than one frame can have the same in-stack position + OFMap m_FrameNumbers; + + // TODO Maybe add a redundant data structures mapping in-stack positions + // to frame numbers in order to enable fast access? +}; + +#endif // STACKREADER_H diff --git a/dcmfg/include/dcmtk/dcmfg/stackinterface.h b/dcmfg/include/dcmtk/dcmfg/stackinterface.h new file mode 100644 index 00000000..0b560b3c --- /dev/null +++ b/dcmfg/include/dcmtk/dcmfg/stackinterface.h @@ -0,0 +1,73 @@ +/* + * + * Copyright (C) 2015, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmfg + * + * Author: Michael Onken + * + * Purpose: Class for reading, accessing and writing stacks + * + */ + +#ifndef STACKINTERFACE_H +#define STACKINTERFACE_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/ofstd/ofmap.h" +#include "dcmtk/ofstd/ofstring.h" +#include "dcmtk/dcmdata/dctk.h" +#include "dcmtk/dcmfg/fginterface.h" +#include "dcmtk/dcmfg/stack.h" + +// Forward declaration +class FGFrameContent; + + +/** Class for convenient access of stacks within an Enhanced DICOM object + */ +class DCMTK_DCMFG_EXPORT FGStackInterface +{ +public: + + FGStackInterface(); + + OFBool checkConsistency(FGInterface* fgContext = NULL); + + virtual void clear(); + + virtual ~FGStackInterface(); + + virtual OFBool addStack(FGStack* stack); + + virtual OFCondition read(FGInterface& fgSource); + + virtual OFCondition write(FGInterface& fgDestination); + + size_t numStacks() const; + +protected: + + FGFrameContent* ensureFrameContentFG(const Uint32 frameNo, + FGInterface& fg); + + // Returns number of errors + virtual size_t checkContext(FGStack* stack, + FGInterface* context); + +private: + + /// The stacks found + OFMap m_Stacks; +}; + +#endif // STACKINTERFACE_H \ No newline at end of file diff --git a/dcmfg/libsrc/CMakeLists.txt b/dcmfg/libsrc/CMakeLists.txt new file mode 100644 index 00000000..c37d8683 --- /dev/null +++ b/dcmfg/libsrc/CMakeLists.txt @@ -0,0 +1,23 @@ +# create library from source files +DCMTK_ADD_LIBRARY(dcmfg + fg + fgbase + fgderimg + fgfact + fgfracon + fgframevoilut + fgimagedatatype + fginterface + fgpixmsr + fgplanor + fgplanorvol + fgplanpo + fgplanposvol + fgrealworldvaluemapping + fgseg + fgusimagedescription + fgtypes + stack + stackinterface) + +DCMTK_TARGET_LINK_MODULES(dcmfg dcmiod dcmdata ofstd oflog) diff --git a/dcmfg/libsrc/Makefile.dep b/dcmfg/libsrc/Makefile.dep new file mode 100644 index 00000000..f1e984a2 --- /dev/null +++ b/dcmfg/libsrc/Makefile.dep @@ -0,0 +1,2179 @@ +fg.o: fg.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmfg/fg.h ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../include/dcmtk/dcmfg/fgtypes.h ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcostrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicent.h \ + ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcmetinf.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicdir.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdirrec.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrulup.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrul.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixseq.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcofsetl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrae.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvras.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrda.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrds.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrdt.h \ + ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvris.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrtm.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrur.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcchrstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlt.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpn.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsh.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrst.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvruc.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrut.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixel.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpobw.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcovlay.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrat.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrss.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrus.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfd.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrof.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrod.h \ + ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ + ../include/dcmtk/dcmfg/fgdefine.h ../include/dcmtk/dcmfg/fgbase.h +fgbase.o: fgbase.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmfg/fgbase.h ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../include/dcmtk/dcmfg/fgtypes.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcostrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicent.h \ + ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcmetinf.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicdir.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdirrec.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrulup.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrul.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixseq.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcofsetl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrae.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvras.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrda.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrds.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrdt.h \ + ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvris.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrtm.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrur.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcchrstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlt.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpn.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsh.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrst.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvruc.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrut.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixel.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpobw.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcovlay.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrat.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrss.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrus.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfd.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrof.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrod.h \ + ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ + ../include/dcmtk/dcmfg/fgdefine.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodcommn.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodrules.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \ + ../../dcmiod/include/dcmtk/dcmiod/ioddef.h \ + ../../dcmiod/include/dcmtk/dcmiod/modpatient.h \ + ../../ofstd/include/dcmtk/ofstd/ofmem.h \ + ../../dcmiod/include/dcmtk/dcmiod/modbase.h \ + ../../dcmiod/include/dcmtk/dcmiod/modpatientstudy.h \ + ../../ofstd/include/dcmtk/ofstd/ofoption.h \ + ../../ofstd/include/dcmtk/ofstd/ofalign.h \ + ../../dcmiod/include/dcmtk/dcmiod/modgeneralstudy.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodmacro.h \ + ../../dcmiod/include/dcmtk/dcmiod/modequipment.h \ + ../../dcmiod/include/dcmtk/dcmiod/modgeneralseries.h \ + ../../dcmiod/include/dcmtk/dcmiod/modfor.h \ + ../../dcmiod/include/dcmtk/dcmiod/modsopcommon.h \ + ../../dcmiod/include/dcmtk/dcmiod/modcommoninstanceref.h +fgderimg.o: fgderimg.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../include/dcmtk/dcmfg/fgderimg.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodmacro.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcostrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicent.h \ + ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcmetinf.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicdir.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdirrec.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrulup.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrul.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixseq.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcofsetl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrae.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvras.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrda.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrds.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrdt.h \ + ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvris.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrtm.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrur.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcchrstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlt.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpn.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsh.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrst.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvruc.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrut.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixel.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpobw.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcovlay.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrat.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrss.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrus.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfd.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrof.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrod.h \ + ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodrules.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \ + ../../dcmiod/include/dcmtk/dcmiod/ioddef.h \ + ../../dcmiod/include/dcmtk/dcmiod/modbase.h \ + ../../ofstd/include/dcmtk/ofstd/ofmem.h ../include/dcmtk/dcmfg/fgbase.h \ + ../include/dcmtk/dcmfg/fgtypes.h ../include/dcmtk/dcmfg/fgdefine.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodutil.h +fgfact.o: fgfact.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodutil.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h \ + ../../dcmiod/include/dcmtk/dcmiod/ioddef.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodrules.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \ + ../include/dcmtk/dcmfg/fgfact.h ../include/dcmtk/dcmfg/fgtypes.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcostrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicent.h \ + ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcmetinf.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicdir.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdirrec.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrulup.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrul.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixseq.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcofsetl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrae.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvras.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrda.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrds.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrdt.h \ + ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvris.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrtm.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrur.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcchrstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlt.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpn.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsh.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrst.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvruc.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrut.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixel.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpobw.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcovlay.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrat.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrss.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrus.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfd.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrof.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrod.h \ + ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ + ../include/dcmtk/dcmfg/fgdefine.h ../include/dcmtk/dcmfg/fgderimg.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodmacro.h \ + ../../dcmiod/include/dcmtk/dcmiod/modbase.h \ + ../../ofstd/include/dcmtk/ofstd/ofmem.h ../include/dcmtk/dcmfg/fgbase.h \ + ../include/dcmtk/dcmfg/fgfracon.h ../include/dcmtk/dcmfg/fgframevoilut.h \ + ../include/dcmtk/dcmfg/fgimagedatatype.h \ + ../include/dcmtk/dcmfg/fgpixmsr.h ../include/dcmtk/dcmfg/fgplanor.h \ + ../include/dcmtk/dcmfg/fgplanorvol.h ../include/dcmtk/dcmfg/fgplanpo.h \ + ../include/dcmtk/dcmfg/fgplanposvol.h ../include/dcmtk/dcmfg/fgseg.h \ + ../include/dcmtk/dcmfg/fgusimagedescription.h \ + ../include/dcmtk/dcmfg/fgrealworldvaluemapping.h +fgfracon.o: fgfracon.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodutil.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h \ + ../../dcmiod/include/dcmtk/dcmiod/ioddef.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodrules.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \ + ../include/dcmtk/dcmfg/fgfracon.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcostrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicent.h \ + ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcmetinf.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicdir.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdirrec.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrulup.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrul.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixseq.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcofsetl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrae.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvras.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrda.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrds.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrdt.h \ + ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvris.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrtm.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrur.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcchrstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlt.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpn.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsh.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrst.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvruc.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrut.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixel.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpobw.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcovlay.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrat.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrss.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrus.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfd.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrof.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrod.h \ + ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ + ../include/dcmtk/dcmfg/fgbase.h ../include/dcmtk/dcmfg/fgtypes.h \ + ../include/dcmtk/dcmfg/fgdefine.h +fgframevoilut.o: fgframevoilut.cc \ + ../../config/include/dcmtk/config/osconfig.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodutil.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h \ + ../../dcmiod/include/dcmtk/dcmiod/ioddef.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodrules.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \ + ../include/dcmtk/dcmfg/fgframevoilut.h ../include/dcmtk/dcmfg/fgbase.h \ + ../include/dcmtk/dcmfg/fgtypes.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcostrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicent.h \ + ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcmetinf.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicdir.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdirrec.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrulup.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrul.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixseq.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcofsetl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrae.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvras.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrda.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrds.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrdt.h \ + ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvris.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrtm.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrur.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcchrstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlt.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpn.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsh.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrst.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvruc.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrut.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixel.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpobw.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcovlay.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrat.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrss.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrus.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfd.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrof.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrod.h \ + ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ + ../include/dcmtk/dcmfg/fgdefine.h +fgimagedatatype.o: fgimagedatatype.cc \ + ../../config/include/dcmtk/config/osconfig.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodutil.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h \ + ../../dcmiod/include/dcmtk/dcmiod/ioddef.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodrules.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \ + ../include/dcmtk/dcmfg/fgimagedatatype.h ../include/dcmtk/dcmfg/fgbase.h \ + ../include/dcmtk/dcmfg/fgtypes.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcostrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicent.h \ + ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcmetinf.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicdir.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdirrec.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrulup.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrul.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixseq.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcofsetl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrae.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvras.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrda.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrds.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrdt.h \ + ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvris.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrtm.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrur.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcchrstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlt.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpn.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsh.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrst.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvruc.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrut.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixel.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpobw.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcovlay.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrat.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrss.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrus.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfd.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrof.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrod.h \ + ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ + ../include/dcmtk/dcmfg/fgdefine.h +fginterface.o: fginterface.cc \ + ../../config/include/dcmtk/config/osconfig.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofmem.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodutil.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h \ + ../../dcmiod/include/dcmtk/dcmiod/ioddef.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodrules.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \ + ../include/dcmtk/dcmfg/fginterface.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcostrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicent.h \ + ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcmetinf.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicdir.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdirrec.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrulup.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrul.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixseq.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcofsetl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrae.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvras.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrda.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrds.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrdt.h \ + ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvris.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrtm.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrur.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcchrstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlt.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpn.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsh.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrst.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvruc.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrut.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixel.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpobw.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcovlay.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrat.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrss.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrus.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfd.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrof.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrod.h \ + ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ + ../include/dcmtk/dcmfg/fgtypes.h ../include/dcmtk/dcmfg/fgdefine.h \ + ../include/dcmtk/dcmfg/fg.h ../include/dcmtk/dcmfg/fgbase.h \ + ../include/dcmtk/dcmfg/fgfact.h +fgpixmsr.o: fgpixmsr.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmfg/fgpixmsr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrds.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../include/dcmtk/dcmfg/fgbase.h ../include/dcmtk/dcmfg/fgtypes.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcostrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicent.h \ + ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcmetinf.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicdir.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdirrec.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrulup.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrul.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixseq.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcofsetl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrae.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvras.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrda.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrdt.h \ + ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvris.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrtm.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrur.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcchrstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlt.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpn.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsh.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrst.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvruc.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrut.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixel.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpobw.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcovlay.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrat.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrss.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrus.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfd.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrof.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrod.h \ + ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ + ../include/dcmtk/dcmfg/fgdefine.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodutil.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h \ + ../../dcmiod/include/dcmtk/dcmiod/ioddef.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodrules.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h +fgplanor.o: fgplanor.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmfg/fgplanor.h ../include/dcmtk/dcmfg/fgbase.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../include/dcmtk/dcmfg/fgtypes.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcostrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicent.h \ + ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcmetinf.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicdir.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdirrec.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrulup.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrul.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixseq.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcofsetl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrae.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvras.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrda.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrds.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrdt.h \ + ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvris.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrtm.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrur.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcchrstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlt.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpn.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsh.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrst.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvruc.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrut.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixel.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpobw.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcovlay.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrat.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrss.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrus.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfd.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrof.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrod.h \ + ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ + ../include/dcmtk/dcmfg/fgdefine.h ../include/dcmtk/dcmfg/fgfact.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodutil.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h \ + ../../dcmiod/include/dcmtk/dcmiod/ioddef.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodrules.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h +fgplanorvol.o: fgplanorvol.cc \ + ../../config/include/dcmtk/config/osconfig.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfd.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodutil.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h \ + ../../dcmiod/include/dcmtk/dcmiod/ioddef.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodrules.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \ + ../include/dcmtk/dcmfg/fgplanorvol.h ../include/dcmtk/dcmfg/fgbase.h \ + ../include/dcmtk/dcmfg/fgtypes.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcostrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicent.h \ + ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcmetinf.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicdir.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdirrec.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrulup.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrul.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixseq.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcofsetl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrae.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvras.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrda.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrds.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrdt.h \ + ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvris.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrtm.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrur.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcchrstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlt.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpn.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsh.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrst.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvruc.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrut.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixel.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpobw.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcovlay.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrat.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrss.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrus.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrof.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrod.h \ + ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ + ../include/dcmtk/dcmfg/fgdefine.h +fgplanpo.o: fgplanpo.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmfg/fgplanpo.h ../include/dcmtk/dcmfg/fgbase.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../include/dcmtk/dcmfg/fgtypes.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcostrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicent.h \ + ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcmetinf.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicdir.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdirrec.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrulup.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrul.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixseq.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcofsetl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrae.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvras.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrda.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrds.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrdt.h \ + ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvris.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrtm.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrur.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcchrstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlt.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpn.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsh.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrst.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvruc.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrut.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixel.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpobw.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcovlay.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrat.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrss.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrus.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfd.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrof.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrod.h \ + ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ + ../include/dcmtk/dcmfg/fgdefine.h ../include/dcmtk/dcmfg/fgfact.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodutil.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h \ + ../../dcmiod/include/dcmtk/dcmiod/ioddef.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodrules.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h +fgplanposvol.o: fgplanposvol.cc \ + ../../config/include/dcmtk/config/osconfig.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodutil.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h \ + ../../dcmiod/include/dcmtk/dcmiod/ioddef.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodrules.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \ + ../include/dcmtk/dcmfg/fgplanposvol.h ../include/dcmtk/dcmfg/fgbase.h \ + ../include/dcmtk/dcmfg/fgtypes.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcostrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicent.h \ + ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcmetinf.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicdir.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdirrec.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrulup.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrul.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixseq.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcofsetl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrae.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvras.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrda.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrds.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrdt.h \ + ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvris.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrtm.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrur.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcchrstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlt.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpn.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsh.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrst.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvruc.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrut.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixel.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpobw.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcovlay.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrat.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrss.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrus.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfd.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrof.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrod.h \ + ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ + ../include/dcmtk/dcmfg/fgdefine.h +fgrealworldvaluemapping.o: fgrealworldvaluemapping.cc \ + ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmfg/fgrealworldvaluemapping.h \ + ../include/dcmtk/dcmfg/fgbase.h ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../include/dcmtk/dcmfg/fgtypes.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcostrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicent.h \ + ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcmetinf.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicdir.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdirrec.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrulup.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrul.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixseq.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcofsetl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrae.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvras.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrda.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrds.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrdt.h \ + ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvris.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrtm.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrur.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcchrstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlt.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpn.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsh.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrst.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvruc.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrut.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixel.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpobw.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcovlay.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrat.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrss.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrus.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfd.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrof.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrod.h \ + ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ + ../include/dcmtk/dcmfg/fgdefine.h \ + ../../dcmiod/include/dcmtk/dcmiod/modbase.h \ + ../../ofstd/include/dcmtk/ofstd/ofmem.h \ + ../../dcmiod/include/dcmtk/dcmiod/ioddef.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodrules.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodmacro.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodutil.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h +fgseg.o: fgseg.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmfg/fgseg.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrus.h \ + ../include/dcmtk/dcmfg/fgbase.h ../include/dcmtk/dcmfg/fgtypes.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcostrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicent.h \ + ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcmetinf.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicdir.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdirrec.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrulup.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrul.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixseq.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcofsetl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrae.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvras.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrda.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrds.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrdt.h \ + ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvris.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrtm.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrur.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcchrstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlt.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpn.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsh.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrst.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvruc.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrut.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixel.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpobw.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcovlay.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrat.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrss.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfd.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrof.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrod.h \ + ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ + ../include/dcmtk/dcmfg/fgdefine.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodutil.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h \ + ../../dcmiod/include/dcmtk/dcmiod/ioddef.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodrules.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h +fgtypes.o: fgtypes.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmfg/fgtypes.h ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcostrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicent.h \ + ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcmetinf.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicdir.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdirrec.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrulup.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrul.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixseq.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcofsetl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrae.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvras.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrda.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrds.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrdt.h \ + ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvris.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrtm.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrur.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcchrstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlt.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpn.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsh.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrst.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvruc.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrut.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixel.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpobw.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcovlay.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrat.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrss.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrus.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfd.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrof.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrod.h \ + ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ + ../include/dcmtk/dcmfg/fgdefine.h ../include/dcmtk/dcmfg/fgbase.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodcommn.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodrules.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \ + ../../dcmiod/include/dcmtk/dcmiod/ioddef.h \ + ../../dcmiod/include/dcmtk/dcmiod/modpatient.h \ + ../../ofstd/include/dcmtk/ofstd/ofmem.h \ + ../../dcmiod/include/dcmtk/dcmiod/modbase.h \ + ../../dcmiod/include/dcmtk/dcmiod/modpatientstudy.h \ + ../../ofstd/include/dcmtk/ofstd/ofoption.h \ + ../../ofstd/include/dcmtk/ofstd/ofalign.h \ + ../../dcmiod/include/dcmtk/dcmiod/modgeneralstudy.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodmacro.h \ + ../../dcmiod/include/dcmtk/dcmiod/modequipment.h \ + ../../dcmiod/include/dcmtk/dcmiod/modgeneralseries.h \ + ../../dcmiod/include/dcmtk/dcmiod/modfor.h \ + ../../dcmiod/include/dcmtk/dcmiod/modsopcommon.h \ + ../../dcmiod/include/dcmtk/dcmiod/modcommoninstanceref.h +fgusimagedescription.o: fgusimagedescription.cc \ + ../../config/include/dcmtk/config/osconfig.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodutil.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h \ + ../../dcmiod/include/dcmtk/dcmiod/ioddef.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodrules.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \ + ../include/dcmtk/dcmfg/fgusimagedescription.h \ + ../include/dcmtk/dcmfg/fgtypes.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcostrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicent.h \ + ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcmetinf.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicdir.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdirrec.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrulup.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrul.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixseq.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcofsetl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrae.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvras.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrda.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrds.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrdt.h \ + ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvris.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrtm.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrur.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcchrstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlt.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpn.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsh.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrst.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvruc.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrut.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixel.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpobw.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcovlay.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrat.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrss.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrus.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfd.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrof.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrod.h \ + ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ + ../include/dcmtk/dcmfg/fgdefine.h ../include/dcmtk/dcmfg/fgbase.h +stack.o: stack.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmfg/stack.h ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../include/dcmtk/dcmfg/fgdefine.h +stackinterface.o: stackinterface.cc \ + ../../config/include/dcmtk/config/osconfig.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodutil.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h \ + ../../dcmiod/include/dcmtk/dcmiod/ioddef.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodrules.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \ + ../include/dcmtk/dcmfg/stackinterface.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcostrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicent.h \ + ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcmetinf.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicdir.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdirrec.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrulup.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrul.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixseq.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcofsetl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrae.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvras.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrda.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrds.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrdt.h \ + ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvris.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrtm.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrur.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcchrstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlt.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpn.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsh.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrst.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvruc.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrut.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixel.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpobw.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcovlay.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrat.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrss.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrus.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfd.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrof.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrod.h \ + ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ + ../include/dcmtk/dcmfg/fginterface.h ../include/dcmtk/dcmfg/fgtypes.h \ + ../include/dcmtk/dcmfg/fgdefine.h ../include/dcmtk/dcmfg/fg.h \ + ../include/dcmtk/dcmfg/fgbase.h ../include/dcmtk/dcmfg/stack.h \ + ../include/dcmtk/dcmfg/fgfracon.h diff --git a/dcmfg/libsrc/Makefile.in b/dcmfg/libsrc/Makefile.in new file mode 100644 index 00000000..cce48f35 --- /dev/null +++ b/dcmfg/libsrc/Makefile.in @@ -0,0 +1,57 @@ +# +# Makefile for dcmfg/libsrc +# + +@SET_MAKE@ + +SHELL = /bin/sh +VPATH = @srcdir@:@top_srcdir@/include:@top_srcdir@/@configdir@/include +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +configdir = @top_srcdir@/@configdir@ + +include $(configdir)/@common_makefile@ + +ofstddir = $(top_srcdir)/../ofstd +oflogdir = $(top_srcdir)/../oflog +dcmdatadir = $(top_srcdir)/../dcmdata +dcmioddir = $(top_srcdir)/../dcmiod + +LOCALINCLUDES = -I$(ofstddir)/include -I$(oflogdir)/include \ + -I$(dcmdatadir)/include -I$(dcmioddir)/include + +LOCALDEFS = + +objs = fgderimg.o fgframevoilut.o fgpixmsr.o fgplanpo.o fgseg.o stackinterface.o \ + fgbase.o fgfact.o fgimagedatatype.o fgplanor.o fgplanposvol.o fgtypes.o \ + fg.o fgfracon.o fginterface.o fgplanorvol.o fgrealworldvaluemapping.o \ + fgusimagedescription.o stack.o + + +library = libdcmfg.$(LIBEXT) + + +all: $(library) + +install: $(library) + $(configdir)/mkinstalldirs $(DESTDIR)$(libdir) + $(INSTALL_DATA) $(library) $(DESTDIR)$(libdir)/$(library) + $(RANLIB) $(DESTDIR)$(libdir)/$(library) + + +$(library): $(objs) + $(AR) $(ARFLAGS) $@ $(objs) + $(RANLIB) $@ + + +clean: + rm -f $(objs) $(library) $(TRASH) + +distclean: + rm -f $(objs) $(library) $(DISTTRASH) + + +dependencies: + $(CXX) -MM $(defines) $(includes) $(CPPFLAGS) $(CXXFLAGS) *.cc > $(DEP) + +include $(DEP) diff --git a/dcmfg/libsrc/fg.cc b/dcmfg/libsrc/fg.cc new file mode 100644 index 00000000..e5a24939 --- /dev/null +++ b/dcmfg/libsrc/fg.cc @@ -0,0 +1,131 @@ +/* + * + * Copyright (C) 2015, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmfg + * + * Author: Michael Onken + * + * Purpose: Class for managing Functional Groups from a DICOM object + * + */ + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmfg/fg.h" + + +FunctionalGroups::FunctionalGroups() +: m_groups() +{ +} + + +FunctionalGroups::~FunctionalGroups() +{ + clear(); +} + + +void FunctionalGroups::clear() +{ + // free memory of underyling map + while ( m_groups.size() > 0) + { + FunctionalGroups::iterator it = m_groups.begin(); + FGBase* fg = (*it).second; + m_groups.erase(it); + delete fg; + } +} + + + +FGBase* FunctionalGroups::find(const DcmFGTypes::E_FGType fgType) +{ + FGBase* group = NULL; + FunctionalGroups::iterator it = m_groups.find(fgType); + if ( it != m_groups.end() ) + { + group = (*it).second; + } + return group; +} + + +FunctionalGroups::iterator FunctionalGroups::begin() +{ + return m_groups.begin(); +} + + +FunctionalGroups::iterator FunctionalGroups::end() +{ + return m_groups.end(); +} + + +FunctionalGroups::const_iterator FunctionalGroups::begin() const +{ + return m_groups.begin(); +} + + +FunctionalGroups::const_iterator FunctionalGroups::end() const +{ + return m_groups.end(); +} + + +OFCondition FunctionalGroups::insert(FGBase* group, + const OFBool replaceOld) +{ + if (group == NULL) + return EC_IllegalParameter; + + OFCondition result; + FGBase* existing = find(group->getType()); + if (existing) + { + if (replaceOld) + { + DCMFG_DEBUG("Replacing existing functional group"); + delete remove(group->getType()); + } + else + { + DCMFG_ERROR("Cannot insert functional group: Group does already exist"); + result = FG_EC_DoubledFG; + } + } + if (result.good()) + { + if ( (m_groups.insert(OFMake_pair(group->getType(), group)).second) ) + { + DCMFG_DEBUG("Functional group successfully inserted: " << DcmFGTypes::FGType2OFString(group->getType())); + } + else + { + DCMFG_ERROR("Cannot insert functional group: Internal error"); + result = FG_EC_CouldNotInsertFG; + } + } + return result; +} + + +FGBase* FunctionalGroups::remove(const DcmFGTypes::E_FGType fgType) +{ + FGBase* fg = find(fgType); + m_groups.erase(fgType); + return fg; +} + diff --git a/dcmfg/libsrc/fgbase.cc b/dcmfg/libsrc/fgbase.cc new file mode 100644 index 00000000..fd067e89 --- /dev/null +++ b/dcmfg/libsrc/fgbase.cc @@ -0,0 +1,221 @@ +/* + * + * Copyright (C) 2015, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmfg + * + * Author: Michael Onken + * + * Purpose: Base class(es) for functional groups + * + */ + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmfg/fgbase.h" +#include "dcmtk/dcmdata/dcdeftag.h" +#include "dcmtk/dcmiod/iodcommn.h" // for static element helpers + + +FGBase::FGBase(const DcmFGTypes::E_FGType fgType) +{ + m_fgType = fgType; +} + + +FGBase::~FGBase() +{ +} + + +void FGBase::clearData() +{ +} + + +DcmFGTypes::E_FGType FGBase::getType() const +{ + return m_fgType; +} + + +DcmFGTypes::E_FGSharedType FGBase::getSharedType() const +{ + return DcmFGTypes::EFGS_UNKNOWN; +} + + +int FGBase::compare(const FGBase& rhs) const +{ + // Check for equality from FGBase' point of view + + // Same objects? + if (this == &rhs) + return 0; + + // Type identical? + if ( this->getType() != rhs.getType() ) + return -1; + + // This is all we can do + return 0; +} + + +OFCondition FGBase::getItemFromFGSequence(DcmItem& source, + const DcmTagKey& seqKey, + const long unsigned int itemNum, + DcmItem*& result) +{ + result = NULL; + DcmSequenceOfItems *seq = NULL; + if (source.findAndGetSequence(seqKey, seq).bad()) + { + DCMFG_ERROR("Functional Group Sequence does not exist: " << seqKey << " (" << DcmFGTypes::tagKey2FGType(seqKey) << ")"); + return EC_TagNotFound; + } + result = seq->getItem(itemNum); + if (result == NULL) + { + DCMFG_DEBUG("Functional Group Sequence " << seqKey << " ( " << DcmFGTypes::tagKey2FGType(seqKey) << ") does not have " << itemNum-1 << "items"); + return FG_EC_NotEnoughItems; + } + return EC_Normal; +} + + +OFCondition FGBase::createNewFGSequence(DcmItem& destination, + const DcmTagKey& seqKey, + const long unsigned int numItems, + DcmItem*& firstItem) +{ + firstItem = NULL; + OFCondition result = destination.insertEmptyElement(seqKey, OFTrue /* replace old */); + if (result.bad()) + { + DCMFG_ERROR("Coudl not create Functional Group with sequence " << seqKey << " ( " << DcmFGTypes::tagKey2FGType(seqKey) << ")"); + return FG_EC_CouldNotInsertFG; + } + DcmItem* dummy =NULL; + result = destination.findOrCreateSequenceItem(seqKey, dummy, numItems ); + if (result.bad()) + { + // clean up + destination.findAndDeleteElement(seqKey); + DCMFG_ERROR("Could not create " << numItems << " items in Functional Group with sequence " << seqKey << " ( " << DcmFGTypes::tagKey2FGType(seqKey) << ")"); + return FG_EC_CouldNotInsertFG; + } + destination.findOrCreateSequenceItem(seqKey, firstItem, 0); + return EC_Normal; +} + + + +FGUnknown::FGUnknown(const DcmTagKey& seqStartTag, + const DcmFGTypes::E_FGSharedType sharedType) : + FGBase(DcmFGTypes::EFG_UNKNOWN), + m_seqStartTag(seqStartTag), + m_fgSequence(NULL), + m_sharedType(sharedType) +{ +} + + +void FGUnknown::clearData() +{ + if (m_fgSequence != NULL) + { + delete m_fgSequence; + m_fgSequence = NULL; + } +} + + +OFCondition FGUnknown::read(DcmItem& item) +{ + // clear old data + clearData(); + OFCondition result = item.findAndGetSequence(m_seqStartTag, m_fgSequence, OFFalse /* no depth search */, OFTrue /* create copy! */); + if ( result.bad() ) + { + if (m_fgSequence != NULL) + delete m_fgSequence; + m_fgSequence = NULL; + } + return result; +} + + +OFCondition FGUnknown::write(DcmItem& item) +{ + return item.insert(new DcmSequenceOfItems(*m_fgSequence), OFTrue /* replace old! */); +} + + +OFCondition FGUnknown::check() const +{ + // TODO + return EC_Normal; +} + + +int FGUnknown::compare(const FGBase& rhs) const +{ + int result = FGBase::compare(rhs); + if (result == 0) + { + const FGUnknown* myRhs = OFstatic_cast(const FGUnknown*, &rhs); + + // Compare all elements + if (m_seqStartTag == myRhs->m_seqStartTag) + { + if (m_fgSequence && myRhs->m_fgSequence) + { + result = m_fgSequence->compare( *(myRhs->m_fgSequence) ); + } + else if (!m_fgSequence && !myRhs->m_fgSequence) // if both are not set, objects are still equal + { + result = 0; + } + else if (m_fgSequence) + { + return 1; // this object is bigger (more information) + } + else if (myRhs->m_fgSequence) + { + return -1; // rhs object is bigger (more information) + } + } + else + { + result = (m_seqStartTag < myRhs->m_seqStartTag) ? -1 : 1; + } + } + + return result; +} + + +FGUnknown::~FGUnknown() +{ + clearData(); +} + + +FGBase* FGUnknown::clone() const +{ + FGUnknown* copy = new FGUnknown(this->m_seqStartTag); + if (copy) + { + *(copy->m_fgSequence) = *(this->m_fgSequence); + } + return copy; +} diff --git a/dcmfg/libsrc/fgderimg.cc b/dcmfg/libsrc/fgderimg.cc new file mode 100644 index 00000000..63502981 --- /dev/null +++ b/dcmfg/libsrc/fgderimg.cc @@ -0,0 +1,628 @@ +/* + * + * Copyright (C) 2015, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmfg + * + * Author: Michael Onken + * + * Purpose: Class for managing Derivation Image Functional Group + * + */ + + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmdata/dcitem.h" +#include "dcmtk/dcmdata/dcdatutl.h" +#include "dcmtk/dcmfg/fgderimg.h" +#include "dcmtk/dcmiod/iodutil.h" + + +FGDerivationImage::FGDerivationImage() : + FGBase(DcmFGTypes::EFG_DERIVATIONIMAGE), + m_DerivationImageItems() +{ +} + + +FGDerivationImage::~FGDerivationImage() +{ + DcmIODUtil::freeContainer(m_DerivationImageItems); +} + + +FGBase* FGDerivationImage::clone() const +{ + FGDerivationImage* copy = new FGDerivationImage(); + if (copy) + { + OFVector::const_iterator it = m_DerivationImageItems.begin(); + while ( it != m_DerivationImageItems.end() ) + { + DerivationImageItem* itemCopy = new DerivationImageItem(); + if (!itemCopy) + { + DCMFG_FATAL("Cannot clone FGDerivationImage: Memory exhausted"); + return NULL; + } + *itemCopy = **it; + copy->getDerivationImageItems().push_back(itemCopy); + it++; + } + } + return copy; +} + + +FGDerivationImage* FGDerivationImage::createMinimal(const OFVector& derivationImages, + const OFString& derivationDescription, + const CodeSequenceMacro& derivationCode, + const CodeSequenceMacro& purposeOfReference) +{ + OFCondition result; + FGDerivationImage* group = new FGDerivationImage(); + if (group) + { + DerivationImageItem* derivItem = NULL; + result = group->addDerivationImageItem(derivationCode, derivationDescription, derivItem); + if (result.good()) + { + OFVector srcImages = derivItem->getSourceImageItems(); + OFVector::const_iterator imageRef = derivationImages.begin(); + while (imageRef != derivationImages.end()) + { + SourceImageItem* item = new SourceImageItem(); + if (item) + { + item->getPurposeOfReferenceCode() = purposeOfReference; + item->getImageSOPInstanceReference() = *imageRef; + derivItem->getSourceImageItems().push_back(item); + } + else + { + DCMFG_ERROR("Cannot create derivation description: Out of memory"); + result = EC_MemoryExhausted; + } + imageRef++; + } + } + else + { + DCMFG_ERROR("Cannot create derivation description: " << result.text()); + } + } + else + { + result = EC_MemoryExhausted; + } + + if (result.bad()) + { + delete group; + group = NULL; + } + + return group; +} + + +int FGDerivationImage::compare(const FGBase& rhs) const +{ + int result = FGBase::compare(rhs); + if (result != 0) + return result; + + const FGDerivationImage* myRhs = OFstatic_cast(const FGDerivationImage*, &rhs); + + size_t thisSize = m_DerivationImageItems.size(); + size_t rhsSize = myRhs->m_DerivationImageItems.size(); + size_t maxSize = (thisSize > rhsSize) ? thisSize : rhsSize; + for (size_t count = 0; count < maxSize; count++) + { + int error = (*(m_DerivationImageItems[count])).compare( (*(myRhs->m_DerivationImageItems[count])) ); + if (error != 0) + { + return error; + } + } + + if (thisSize < rhsSize) + { + return 1; + } + else if (thisSize > rhsSize) + { + return -1; + } + + return 0; + +} + + +void FGDerivationImage::clearData() +{ + DcmIODUtil::freeContainer(m_DerivationImageItems); +} + + +OFCondition FGDerivationImage::check() const +{ + // TODO + return EC_Normal; +} + +DerivationImageItem& DerivationImageItem::operator=(const DerivationImageItem& rhs) +{ + m_DerivationDescription = rhs.m_DerivationDescription; + // Copy nested structures: Derivation Codes + OFVector::const_iterator code = rhs.m_DerivationCodeItems.begin(); + while ( code != rhs.m_DerivationCodeItems.end() ) + { + m_DerivationCodeItems.push_back(new CodeSequenceMacro(**code)); + code++; + } + // Copy nested structures: Derivation Codes + OFVector::const_iterator source = rhs.m_SourceImageItems.begin(); + while ( source != rhs.m_SourceImageItems.end() ) + { + m_SourceImageItems.push_back(new SourceImageItem(**source)); + source++; + } + return *this; +} + + +OFCondition FGDerivationImage::addDerivationImageItem(const CodeSequenceMacro& derivationCode, + const OFString& derivationDescription, + DerivationImageItem*& item) +{ + OFCondition result; + item = new DerivationImageItem(); + if (item == NULL) + { + return EC_MemoryExhausted; + } + + // Initialize with given data + if (result.good()) + { + result = item->setDerivationDescription(derivationDescription); + } + if (result.good()) + { + item->getDerivationCodeItems().push_back(new CodeSequenceMacro(derivationCode)); + m_DerivationImageItems.push_back(item); + } + else + { + delete item; + item = NULL; + result = FG_EC_InvalidData; + } + return result; +} + + +OFVector& FGDerivationImage::getDerivationImageItems() +{ + return m_DerivationImageItems; +} + + +OFCondition FGDerivationImage::read(DcmItem& item) +{ + /* re-initialize object */ + clearData(); + + DcmSequenceOfItems *derivationImageSequence = NULL; + if (item.findAndGetSequence(DCM_DerivationImageSequence, derivationImageSequence).bad()) + return FG_EC_NoSuchGroup; + + /* Read Derivation Image Sequence */ + DcmIODUtil::readSubSequence > + ( derivationImageSequence, + DCM_DerivationImageSequence, + m_DerivationImageItems, + "0-n", + "2", + "DerivationImageMacro"); + + return EC_Normal; +} + + +OFCondition FGDerivationImage::write(DcmItem& item) +{ + OFCondition result = EC_Normal; + DcmIODUtil::writeSubSequence > + ( result, + DCM_DerivationImageSequence, + m_DerivationImageItems, + item, + "0-n", + "2", + "DerivationImageMacro" ); + return result; +} + + +/* -- Class SourceImage Implementation -- */ + +SourceImageItem::SourceImageItem() + : m_PurposeOfReferenceCode(), + m_ImageSOPInstanceReference() +{ +} + + +SourceImageItem::~SourceImageItem() +{ + clearData(); +} + + +SourceImageItem& SourceImageItem::operator=(const SourceImageItem& rhs) +{ + m_PurposeOfReferenceCode = rhs.m_PurposeOfReferenceCode; + m_ImageSOPInstanceReference = rhs.m_ImageSOPInstanceReference; + return *this; +} + + +void SourceImageItem::clearData() +{ + m_PurposeOfReferenceCode.clearData(); + m_ImageSOPInstanceReference.clear(); +} + + +OFCondition SourceImageItem::check() const +{ + // TODO + return EC_Normal; +} + + +int SourceImageItem::compare(const SourceImageItem& rhs) const +{ + int result = this->m_PurposeOfReferenceCode.compare(rhs.m_PurposeOfReferenceCode); + if (result != 0) + { + result = this->m_ImageSOPInstanceReference.compare(rhs.m_ImageSOPInstanceReference); + } + + return result; +} + + +CodeSequenceMacro& SourceImageItem::getPurposeOfReferenceCode() +{ + return m_PurposeOfReferenceCode; +} + + +ImageSOPInstanceReferenceMacro& SourceImageItem::getImageSOPInstanceReference() +{ + return m_ImageSOPInstanceReference; +} + + +OFCondition SourceImageItem::read(DcmItem& itemOfSourceImageSequence, + const OFBool clearOldData) +{ + /* Re-initialize object */ + if (clearOldData) + clearData(); + + /* Read Purpose of Reference Code Sequence */ + DcmIODUtil::readSingleItem(itemOfSourceImageSequence, DCM_PurposeOfReferenceCodeSequence, m_PurposeOfReferenceCode, "1", "DerivationImageMacro"); + + /* Read Source Image Sequence */ + m_ImageSOPInstanceReference.read(itemOfSourceImageSequence); + + return EC_Normal; +} + + +OFCondition SourceImageItem::write(DcmItem& itemOfSourceImageSequence) +{ + OFCondition result = EC_Normal; + + /* Write Purpose of Reference Code Sequence */ + DcmIODUtil::writeSingleItem(result, DCM_PurposeOfReferenceCodeSequence, m_PurposeOfReferenceCode, itemOfSourceImageSequence, "1", "DerivationImageMacro"); + + /* Write Image SOP Instance Reference Macro */ + if ( result.good() ) + { + m_ImageSOPInstanceReference.write(itemOfSourceImageSequence); + } + + return result; +} + + +/* -- Class DerivationImages Implementation -- */ + +DerivationImageItem::DerivationImageItem() + : m_DerivationDescription(DCM_DerivationDescription), + m_DerivationCodeItems(), + m_SourceImageItems() +{ +} + + +DerivationImageItem::DerivationImageItem(const DerivationImageItem& rhs) + : m_DerivationDescription(rhs.m_DerivationDescription), + m_DerivationCodeItems(), + m_SourceImageItems() +{ + OFVector::const_iterator it = rhs.m_DerivationCodeItems.begin(); + while (it != rhs.m_DerivationCodeItems.end()) + { + CodeSequenceMacro* copy = new CodeSequenceMacro(**it); + if (!copy) + { + DCMFG_ERROR("Could not create copy of DerivationImageItem: Memory exhausted"); + this->clearData(); + return; + } + m_DerivationCodeItems.push_back(copy); + it++; + } + + OFVector::const_iterator src = rhs.m_SourceImageItems.begin(); + while (src != rhs.m_SourceImageItems.end()) + { + SourceImageItem* copy = new SourceImageItem(**src); + if (!copy) + { + DCMFG_ERROR("Could not create copy of DerivationImageItem: Memory exhausted"); + this->clearData(); + return; + } + m_SourceImageItems.push_back(copy); + it++; + } +} + + +void DerivationImageItem::clearData() +{ + m_DerivationDescription.clear(); + DcmIODUtil::freeContainer(m_DerivationCodeItems); + DcmIODUtil::freeContainer(m_SourceImageItems); +} + + +int DerivationImageItem::compare(const DerivationImageItem& rhs) const +{ + if (this == &rhs) + return OFTrue; + + int result = m_DerivationDescription.compare(rhs.m_DerivationDescription); + if (result != 0) return result; + + size_t numThis = m_DerivationCodeItems.size(); + size_t numRhs = rhs.m_DerivationCodeItems.size(); + size_t maxSize = (numThis > numRhs) ? numThis : numRhs; + for (size_t count = 0; count < maxSize; count++) + { + int error = (*m_DerivationCodeItems[count]).compare(*(rhs.m_DerivationCodeItems[count])); + if (error != 0) + { + return error; + } + } + if (numThis < numRhs) + { + return 1; + } + else if (numThis > numRhs) + { + return -1; + } + + numThis = m_SourceImageItems.size(); + numRhs = rhs.m_SourceImageItems.size(); + maxSize = (numThis > numRhs) ? numThis : numRhs; + for (size_t count = 0; count < maxSize; count++) + { + int error = (*m_SourceImageItems[count]).compare(*(rhs.m_SourceImageItems[count])); + if (error != 0) + { + return error; + } + } + if (numThis < numRhs) + { + return 1; + } + else if (numThis > numRhs) + { + return -1; + } + + // If we get here, the object values must be identical + return 0; +} + + +OFCondition DerivationImageItem::check() const +{ + // TODO + return EC_Normal; +} + + + +DerivationImageItem::~DerivationImageItem() +{ + clearData(); +} + + +OFCondition DerivationImageItem::addSourceImageItem(const OFString& file, + const CodeSequenceMacro& purposeOfReference, + SourceImageItem*& resultSourceImageItem) +{ + // Create new source image item + SourceImageItem *item = new SourceImageItem(); + if (item == NULL) + { + return EC_MemoryExhausted; + } + item->getPurposeOfReferenceCode() = purposeOfReference; + // TODO: Check code for completeness, and context group? + resultSourceImageItem = NULL; + OFString sopClass, sopInstance, ts; + OFCondition result = DcmDataUtil::getSOPInstanceFromFile(file, sopClass, sopInstance, ts /*ignored*/); + { + if ( result.good() ) result = item->getImageSOPInstanceReference().setReferencedSOPClassUID(sopClass); + if ( result.good() ) result = item->getImageSOPInstanceReference().setReferencedSOPInstanceUID(sopInstance); + } + if (result.good()) + { + m_SourceImageItems.push_back(item); + resultSourceImageItem = item; + } + return result; +} + + +OFCondition DerivationImageItem::addSourceImageItems(const OFVector< OFString >& files, + const CodeSequenceMacro& purposeOfReference, + OFVector& resultSourceImageItems, + const OFBool skipErrors) +{ + // Add files + OFCondition result; + OFVector::const_iterator it = files.begin(); + while (it != files.end()) + { + SourceImageItem* resultItem = NULL; + result = addSourceImageItem((*it), purposeOfReference, resultItem); + if (result.good()) + { + resultSourceImageItems.push_back(resultItem); + } + else if (result.bad() && !skipErrors) + { + DCMFG_ERROR("Could not add Source Image Sequence item for file " << *it << ": " << result.text()); + break; + } + else if (result.bad()) + { + DCMFG_WARN("Could not add Source Image Sequence item for file " << *it << ": " << result.text()); + } + it++; + } + + return result; +} + + +OFVector& DerivationImageItem::getDerivationCodeItems() +{ + return m_DerivationCodeItems; +} + + +OFCondition DerivationImageItem::getDerivationDescription(OFString& value, + const long signed int pos) const +{ + return DcmIODUtil::getStringValueFromElement(m_DerivationDescription, value, pos); +} + + +OFCondition DerivationImageItem::setDerivationDescription(const OFString& value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmShortText::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_DerivationDescription.putOFStringArray(value); + return result; + +} + + +OFVector& DerivationImageItem::getSourceImageItems() +{ + return m_SourceImageItems; +} + + +OFCondition DerivationImageItem::read(DcmItem& itemOfDerivationImageSequence, + const OFBool clearOldData) +{ + OFCondition result = EC_Normal; + + /* re-initialize object */ + if (clearOldData) + clearData(); + + /* Derivation Description */ + DcmIODUtil::getAndCheckElementFromDataset(itemOfDerivationImageSequence, m_DerivationDescription, "1" /* vm */, "3" /* type */, "DerivationImageMacro"); + + /* Derivation Code Sequence */ + DcmIODUtil::readSubSequence > + ( itemOfDerivationImageSequence, + DCM_DerivationCodeSequence, + m_DerivationCodeItems, + "1" /* vm */, + "3" /* type */, + "DerivationImageMacro" ); + + + /* Source Image Sequence */ + DcmIODUtil::readSubSequence > + ( itemOfDerivationImageSequence, + DCM_SourceImageSequence, + m_SourceImageItems, + "0-n" /* vm */, + "2" /* type */, + "DerivationImageMacro" ); + + return result; +} + + +OFCondition DerivationImageItem::write(DcmItem& itemOfDerivationImageSequence) +{ + OFCondition result = EC_Normal; + + /* Write Derivation Description */ + DcmIODUtil::copyElementToDataset(result, itemOfDerivationImageSequence, m_DerivationDescription, "1", "3", "DerivationImageMacro"); + + /* Write Derivation Code Sequence */ + DcmIODUtil::writeSubSequence > + ( result, + DCM_DerivationCodeSequence, + m_DerivationCodeItems, + itemOfDerivationImageSequence, + "1-n", + "1", + "DerivationImageMacro" ); + + /* Write Source Image Sequence */ + DcmIODUtil::writeSubSequence > + ( result, + DCM_SourceImageSequence, + m_SourceImageItems, + itemOfDerivationImageSequence, + "0-n", + "2", + "DerivationImageMacro" ); + + return result; +} + diff --git a/dcmfg/libsrc/fgfact.cc b/dcmfg/libsrc/fgfact.cc new file mode 100644 index 00000000..d7f7e99f --- /dev/null +++ b/dcmfg/libsrc/fgfact.cc @@ -0,0 +1,144 @@ +/* + * + * Copyright (C) 2015, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmfg + * + * Author: Michael Onken + * + * Purpose: Factory class for creating functional groups + * + */ + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmiod/iodutil.h" +#include "dcmtk/dcmfg/fgfact.h" +#include "dcmtk/dcmfg/fgderimg.h" +#include "dcmtk/dcmfg/fgfracon.h" +#include "dcmtk/dcmfg/fgframevoilut.h" +#include "dcmtk/dcmfg/fgimagedatatype.h" +#include "dcmtk/dcmfg/fgpixmsr.h" +#include "dcmtk/dcmfg/fgplanor.h" +#include "dcmtk/dcmfg/fgplanorvol.h" +#include "dcmtk/dcmfg/fgplanpo.h" +#include "dcmtk/dcmfg/fgplanposvol.h" +#include "dcmtk/dcmfg/fgseg.h" +#include "dcmtk/dcmfg/fgusimagedescription.h" +#include "dcmtk/dcmfg/fgrealworldvaluemapping.h" + + +FGFactory* FGFactory::m_Instance = NULL; + +FGFactory::FGFactory() +{ + // noting to do (private constructor) +} + + + +FGFactory& FGFactory::instance() +{ + if (m_Instance == NULL) + { + m_Instance = new FGFactory(); + } + return *m_Instance; +} + + +FGBase* FGFactory::create(const DcmFGTypes::E_FGType fgtype) +{ + switch(fgtype) + { + case DcmFGTypes::EFG_PIXELMEASURES: + return new FGPixelMeasures(); + break; + case DcmFGTypes::EFG_FRAMECONTENT: + return new FGFrameContent(); + break; + case DcmFGTypes::EFG_FRAMEVOILUTMETA: // Frame VOI LUT and Frame VOI LUT with LUT + return new FGFrameVOILUT(); + case DcmFGTypes::EFG_PLANEPOSPATIENT: + return new FGPlanePosPatient(); + break; + case DcmFGTypes::EFG_PLANEPOSITIONVOLUME: + return new FGPlanePositionVolume(); + case DcmFGTypes::EFG_PLANEORIENTPATIENT: + return new FGPlaneOrientationPatient(); + break; + case DcmFGTypes::EFG_PLANEORIENTVOLUME: + return new FGPlaneOrientationVolume(); + case DcmFGTypes::EFG_DERIVATIONIMAGE: + return new FGDerivationImage(); + break; + case DcmFGTypes::EFG_IMAGEDATATYPE: + return new FGImageDataType(); + break; + case DcmFGTypes::EFG_REALWORLDVALUEMAPPING: + return new FGRealWorldValueMapping(); + break; + case DcmFGTypes::EFG_SEGMENTATION: + return new FGSegmentation(); + break; + case DcmFGTypes::EFG_USIMAGEDESCRIPTION: + return new FGUSImageDescription(); + break; + case DcmFGTypes::EFG_CARDIACSYNC: + case DcmFGTypes::EFG_FRAMEANATOMY: + case DcmFGTypes::EFG_PIXELVALUETRANSMETA: // Pixel Value Transformation Macro or Identity Pixel Value Transformation Macro + case DcmFGTypes::EFG_CONTRASTBOLUSUSAGE: + case DcmFGTypes::EFG_PIXELINTENSITYRELLUT: + case DcmFGTypes::EFG_FRAMEPIXELSHIFT: + case DcmFGTypes::EFG_PATIENTORIENTINFRAME: + case DcmFGTypes::EFG_FRAMEDISPLAYSHUTTER: + case DcmFGTypes::EFG_RESPIRATORYSYNC: + case DcmFGTypes::EFG_IRRADIATIONEVENTIDENT: + case DcmFGTypes::EFG_RADIOPHARAMAUSAGE: + case DcmFGTypes::EFG_PATIENTPHYSIOSTATE: + case DcmFGTypes::EFG_TEMPORALPOSITION: + { + DCMFG_DEBUG("Encountered functional group that is not explicitly supported yet:" << DcmFGTypes::FGType2OFString(fgtype) ); + return NULL; + break; + } + default: + { + DCMFG_DEBUG("Encountered unknown functional group"); + return NULL; + break; + } + } + return NULL; +} + + +FGBase* FGFactory::create(const DcmTagKey& fgSequenceKey) +{ + if (!DcmIODUtil::isSequenceTag(fgSequenceKey)) + { + DCMFG_ERROR("Cannot create functional group from non-sequence tag"); + return NULL;; + } + FGBase* fg = NULL; + DcmFGTypes::E_FGType fgType = DcmFGTypes::tagKey2FGType(fgSequenceKey); + if (fgType != DcmFGTypes::EFG_UNKNOWN) + { + fg = create(fgType); + } + /* if the sequence is know but there is no specific implementation, create generic functional group */ + if (fg == NULL) + { + DCMFG_DEBUG("Encountered unknown functional group, started by tag key: " << fgSequenceKey); + fg = new FGUnknown(fgSequenceKey); + } + return fg; +} diff --git a/dcmfg/libsrc/fgfracon.cc b/dcmfg/libsrc/fgfracon.cc new file mode 100644 index 00000000..89d35569 --- /dev/null +++ b/dcmfg/libsrc/fgfracon.cc @@ -0,0 +1,370 @@ +/* + * + * Copyright (C) 2015, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmfg + * + * Author: Michael Onken + * + * Purpose: Class for managing the Frame Content Functional Group + * + */ + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmdata/dcdeftag.h" +#include "dcmtk/dcmiod/iodutil.h" +#include "dcmtk/dcmfg/fgfracon.h" +#include "dcmtk/dcmfg/fgtypes.h" + +// Constructor +FGFrameContent::FGFrameContent() : + FGBase(DcmFGTypes::EFG_FRAMECONTENT), + m_FrameAcquisitonNumber(DCM_FrameAcquisitionNumber), + m_FrameReferenceDateTime(DCM_FrameReferenceDateTime), + m_FrameAcquisitionDateTime(DCM_FrameAcquisitionDateTime), + m_FrameAcquisitionDuration(DCM_FrameAcquisitionDuration), + m_CardiacCyclePosition(DCM_CardiacCyclePosition), + m_RespiratoryCyclePosition(DCM_RespiratoryCyclePosition), + m_DimensionIndexValues(DCM_DimensionIndexValues), + m_TemporalPositionIndex(DCM_TemporalPositionIndex), + m_StackID(DCM_StackID), + m_InStackPositionNumber(DCM_InStackPositionNumber), + m_FrameComments(DCM_FrameComments), + m_FrameLabel(DCM_FrameLabel) +{ +} + + +FGFrameContent::~FGFrameContent() +{ + // nothing to do +} + + +FGBase* FGFrameContent::clone() const +{ + FGFrameContent* copy = new FGFrameContent(); + if (copy) + { + copy->m_FrameAcquisitonNumber = this->m_FrameAcquisitonNumber; + copy->m_FrameReferenceDateTime = this->m_FrameReferenceDateTime; + copy->m_FrameAcquisitionDateTime = this->m_FrameAcquisitionDateTime; + copy->m_FrameAcquisitionDuration = this->m_FrameAcquisitionDuration; + copy->m_CardiacCyclePosition = this->m_CardiacCyclePosition; + copy->m_RespiratoryCyclePosition = this->m_RespiratoryCyclePosition; + copy->m_DimensionIndexValues = this->m_DimensionIndexValues; + copy->m_TemporalPositionIndex = this->m_TemporalPositionIndex; + copy->m_StackID = this->m_StackID; + copy->m_InStackPositionNumber = this->m_InStackPositionNumber; + copy->m_FrameComments = this->m_FrameComments; + copy->m_FrameLabel = this->m_FrameLabel; + } + return copy; +} + + +void FGFrameContent::clearData() +{ + m_FrameAcquisitonNumber.clear(); + m_FrameReferenceDateTime.clear(); + m_FrameAcquisitionDateTime.clear(); + m_FrameAcquisitionDuration.clear(); + m_CardiacCyclePosition.clear(); + m_RespiratoryCyclePosition.clear(); + m_DimensionIndexValues.clear(); + m_TemporalPositionIndex.clear(); + m_StackID.clear(); + m_InStackPositionNumber.clear(); + m_FrameComments.clear(); + m_FrameLabel.clear(); +} + + +OFCondition FGFrameContent::check() const +{ + // TODO + return EC_Normal; +} + + +/// Read Frame Content Sequence from given item +OFCondition FGFrameContent::read(DcmItem& item) +{ + clearData(); + + DcmItem* seqItem = NULL; + OFCondition result = getItemFromFGSequence(item, DCM_FrameContentSequence, 0, seqItem); + if (result.bad()) + return result; + + DcmIODUtil::getAndCheckElementFromDataset(*seqItem, m_FrameAcquisitonNumber, "1", "3", "FrameContentMacro"); + DcmIODUtil::getAndCheckElementFromDataset(*seqItem, m_FrameReferenceDateTime, "1", "1C", "FrameContentMacro"); + DcmIODUtil::getAndCheckElementFromDataset(*seqItem, m_FrameAcquisitionDateTime, "1", "1C", "FrameContentMacro"); + DcmIODUtil::getAndCheckElementFromDataset(*seqItem, m_FrameAcquisitionDuration, "1", "1C", "FrameContentMacro"); + DcmIODUtil::getAndCheckElementFromDataset(*seqItem, m_CardiacCyclePosition, "1", "3", "FrameContentMacro"); + DcmIODUtil::getAndCheckElementFromDataset(*seqItem, m_RespiratoryCyclePosition, "1", "3", "FrameContentMacro"); + DcmIODUtil::getAndCheckElementFromDataset(*seqItem, m_DimensionIndexValues, "1-n", "1C", "FrameContentMacro"); + DcmIODUtil::getAndCheckElementFromDataset(*seqItem, m_TemporalPositionIndex, "1", "1C", "FrameContentMacro"); + DcmIODUtil::getAndCheckElementFromDataset(*seqItem, m_StackID, "1", "1C", "FrameContentMacro"); + DcmIODUtil::getAndCheckElementFromDataset(*seqItem, m_InStackPositionNumber, "1", "1C", "FrameContentMacro"); + DcmIODUtil::getAndCheckElementFromDataset(*seqItem, m_FrameComments, "1", "3", "FrameContentMacro"); + DcmIODUtil::getAndCheckElementFromDataset(*seqItem, m_FrameLabel, "1", "3", "FrameContentMacro"); + + return EC_Normal; + +} + +/// Writes single Frame Content Sequence into given item +OFCondition FGFrameContent::write(DcmItem& item) +{ + DcmItem *seqItem = NULL; + OFCondition result = createNewFGSequence(item, DCM_FrameContentSequence, 0, seqItem); + if (result.bad()) + return result; + + // --- write frame content macro attributes --- + DcmIODUtil::copyElementToDataset(result, *seqItem, m_FrameAcquisitonNumber, "1", "3", "FrameContentMacro"); + DcmIODUtil::copyElementToDataset(result, *seqItem, m_FrameReferenceDateTime, "1", "1C", "FrameContentMacro"); + DcmIODUtil::copyElementToDataset(result, *seqItem, m_FrameAcquisitionDateTime, "1", "1C", "FrameContentMacro"); + DcmIODUtil::copyElementToDataset(result, *seqItem, m_FrameAcquisitionDuration, "1", "1C", "FrameContentMacro"); + DcmIODUtil::copyElementToDataset(result, *seqItem, m_CardiacCyclePosition, "1", "3", "FrameContentMacro"); + DcmIODUtil::copyElementToDataset(result, *seqItem, m_RespiratoryCyclePosition, "1", "3", "FrameContentMacro"); + DcmIODUtil::copyElementToDataset(result, *seqItem, m_DimensionIndexValues, "1-n", "1C", "FrameContentMacro"); + DcmIODUtil::copyElementToDataset(result, *seqItem, m_TemporalPositionIndex, "1", "1C", "FrameContentMacro"); + DcmIODUtil::copyElementToDataset(result, *seqItem, m_StackID, "1", "1C", "FrameContentMacro"); + DcmIODUtil::copyElementToDataset(result, *seqItem, m_InStackPositionNumber, "1", "1C", "FrameContentMacro"); + DcmIODUtil::copyElementToDataset(result, *seqItem, m_FrameComments, "1", "3", "FrameContentMacro"); + DcmIODUtil::copyElementToDataset(result, *seqItem, m_FrameLabel, "1", "3", "FrameContentMacro"); + return result; +} + + +int FGFrameContent::compare(const FGBase& rhs) const +{ + int result = FGBase::compare(rhs); + if (result != 0) + return result; + + const FGFrameContent* myRhs = OFstatic_cast(const FGFrameContent*, &rhs); + + // Compare all elements + result = m_FrameAcquisitonNumber.compare(myRhs->m_FrameAcquisitonNumber); + if (result == 0) + result = m_FrameReferenceDateTime.compare(myRhs->m_FrameReferenceDateTime); + if (result == 0) + result = m_FrameAcquisitionDateTime.compare(myRhs->m_FrameAcquisitionDateTime); + if (result == 0) + result = m_FrameAcquisitionDuration.compare(myRhs->m_FrameAcquisitionDuration); + if (result == 0) + result = m_CardiacCyclePosition.compare(myRhs->m_CardiacCyclePosition); + if (result == 0) + result = m_RespiratoryCyclePosition.compare(myRhs->m_RespiratoryCyclePosition); + if (result == 0) + result = m_DimensionIndexValues.compare(myRhs->m_DimensionIndexValues); + if (result == 0) + result = m_TemporalPositionIndex.compare(myRhs->m_TemporalPositionIndex); + if (result == 0) + result = m_StackID.compare(myRhs->m_StackID); + if (result == 0) + result = m_InStackPositionNumber.compare(myRhs->m_InStackPositionNumber); + if (result == 0) + result = m_FrameComments.compare(myRhs->m_FrameComments); + if (result == 0) + result = m_FrameLabel.compare(myRhs->m_FrameLabel); + + return result; +} + + +// --- get() functionality --- + +OFCondition FGFrameContent::getFrameAcquisitionNumber(Uint16& value, + const signed long pos) +{ + return m_FrameAcquisitonNumber.getUint16(value, pos); +} + +OFCondition FGFrameContent::getFrameReferenceDateTime(OFString& value, + const signed long pos) +{ + return DcmIODUtil::getStringValueFromElement(m_FrameReferenceDateTime, value, pos); +} + +OFCondition FGFrameContent::getFrameAcquisitionDateTime(OFString& value, + const signed long pos) +{ + return DcmIODUtil::getStringValueFromElement(m_FrameAcquisitionDateTime, value, pos); +} + +OFCondition FGFrameContent::getFrameAcquisitionDuration(Float64& value, + const unsigned long pos) +{ + return m_FrameAcquisitionDuration.getFloat64(value, pos); +} + +OFCondition FGFrameContent::getCardiacCyclePosition(OFString& value, + const signed long pos) +{ + return DcmIODUtil::getStringValueFromElement(m_CardiacCyclePosition, value, pos); +} + +OFCondition FGFrameContent::getRespiratoryCyclePosition(OFString& value, + const signed long pos) +{ + return DcmIODUtil::getStringValueFromElement(m_RespiratoryCyclePosition, value, pos); +} + +OFCondition FGFrameContent::getDimensionIndexValues(Uint32& value, + const signed long pos) +{ + return m_DimensionIndexValues.getUint32(value, pos); +} + +OFCondition FGFrameContent::getTemporalPositionIndex(Uint32& value, + const signed long pos) +{ + return m_TemporalPositionIndex.getUint32(value, pos); +} + +OFCondition FGFrameContent::getStackID(OFString& value, + const signed long pos) +{ + return DcmIODUtil::getStringValueFromElement(m_StackID, value, pos); +} + +OFCondition FGFrameContent::getInStackPositionNumber(Uint32& value, + const long signed int pos) +{ + return m_InStackPositionNumber.getUint32(value, pos); +} + + +OFCondition FGFrameContent::getFrameComments(OFString& value, + const signed long pos) +{ + return DcmIODUtil::getStringValueFromElement(m_FrameComments, value, pos); +} + +OFCondition FGFrameContent::getFrameLabel(OFString& value, + const signed long pos) +{ + return DcmIODUtil::getStringValueFromElement(m_FrameLabel, value, pos); +} + +// --- set() functionality --- + +OFCondition FGFrameContent::setFrameAcquisitionNumber(const Uint16& value, + const OFBool checkValue) +{ + m_FrameAcquisitonNumber.putUint16(value); + return EC_Normal; +} + +OFCondition FGFrameContent::setFrameReferenceDateTime(const OFString& value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmDateTime::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_FrameReferenceDateTime.putOFStringArray(value); + return result; +} + +OFCondition FGFrameContent::setFrameAcquisitionDateTime(const OFString& value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmDateTime::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_FrameAcquisitionDateTime.putOFStringArray(value); + return result; +} + +OFCondition FGFrameContent::setFrameAcquisitionDuration(const Float64& value, + const OFBool checkValue) +{ + // basic checking always included + return m_FrameAcquisitionDuration.putFloat64(value); +} + +OFCondition FGFrameContent::setCardiacCyclePosition(const OFString& value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmCodeString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_CardiacCyclePosition.putOFStringArray(value); + return result; +} + +OFCondition FGFrameContent::setRespiratoryCyclePosition(const OFString& value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmCodeString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_RespiratoryCyclePosition.putOFStringArray(value); + return result; +} + +OFCondition FGFrameContent::setDimensionIndexValues(const Uint32& value, + const unsigned int pos, + const OFBool checkValue) +{ + // no meaningful check possible in this context + if (value == 0) + { + DCMFG_ERROR("Cannot set dimension index value 0, must be >= 1)"); + return EC_InvalidValue; + } + return m_DimensionIndexValues.putUint32(value, pos); +} + +OFCondition FGFrameContent::setTemporalPositionIndex(const Uint32& value, + const OFBool checkValue) +{ + // no meaningful check possible in this context + return m_TemporalPositionIndex.putUint32(value); +} + +OFCondition FGFrameContent::setStackID(const OFString& value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmShortString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_StackID.putOFStringArray(value); + return result; +} + + +OFCondition FGFrameContent::setInStackPositionNumber(const Uint32& value, + const OFBool checkValue) +{ + // no meaningful check possible in this context + return m_InStackPositionNumber.putUint32(value); +} + + +OFCondition FGFrameContent::setFrameComments(const OFString& value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmLongText::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_FrameComments.putOFStringArray(value); + return result; +} + +OFCondition FGFrameContent::setFrameLabel(const OFString& value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmLongString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_FrameLabel.putOFStringArray(value); + return result; +} + diff --git a/dcmfg/libsrc/fgframevoilut.cc b/dcmfg/libsrc/fgframevoilut.cc new file mode 100644 index 00000000..d88afe2b --- /dev/null +++ b/dcmfg/libsrc/fgframevoilut.cc @@ -0,0 +1,221 @@ +/* + * + * Copyright (C) 2015, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmfg + * + * Author: Michael Onken + * + * Purpose: Class for managing Frame VOI LUT Functional Group + * + */ + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmdata/dcdeftag.h" +#include "dcmtk/dcmiod/iodutil.h" +#include "dcmtk/dcmfg/fgframevoilut.h" +#include "dcmtk/dcmfg/fgtypes.h" + +// Constructor +FGFrameVOILUT::FGFrameVOILUT() : + FGBase(DcmFGTypes::EFG_FRAMEVOILUTMETA), + m_WindowCenter(DCM_WindowCenter), + m_WindowWidth(DCM_WindowWidth), + m_WindowCenterWindowWidthExplanation(DCM_WindowCenterWidthExplanation), + m_VOILUTFunction(DCM_VOILUTFunction) +{ +} + + +FGFrameVOILUT::~FGFrameVOILUT() +{ + // nothing to do +} + + +FGBase* FGFrameVOILUT::clone() const +{ + FGFrameVOILUT* copy = new FGFrameVOILUT(); + if (copy) + { + copy->m_WindowCenter = this->m_WindowCenter; + copy->m_WindowWidth= this->m_WindowWidth; + copy->m_WindowCenterWindowWidthExplanation = this->m_WindowCenterWindowWidthExplanation; + copy->m_VOILUTFunction= this->m_VOILUTFunction; + } + return copy; +} + + +void FGFrameVOILUT::clearData() +{ + m_WindowCenter.clear(); + m_WindowWidth.clear(); + m_WindowCenterWindowWidthExplanation.clear(); + m_VOILUTFunction.clear(); +} + + +OFCondition FGFrameVOILUT::check() const +{ + // TODO + return EC_Normal; +} + + +// --- get() functionality --- + + +OFCondition FGFrameVOILUT::getWindowCenter(Float64& value, + const unsigned long pos) +{ + return m_WindowCenter.getFloat64(value, pos); +} + + +OFCondition FGFrameVOILUT::getWindowWidth(Float64& value, + const unsigned long pos) +{ + return m_WindowWidth.getFloat64(value, pos); +} + + +OFCondition FGFrameVOILUT::getWindowCenterAndWindowWidthExplanation(OFString& value, + const unsigned long pos) +{ + return m_WindowCenterWindowWidthExplanation.getOFString(value, pos); +} + + +OFCondition FGFrameVOILUT::getCenterWidthExplanation(Float64& windowCenter, + Float64& windowWidth, + OFString& explanation) +{ + OFCondition result = m_WindowCenter.getFloat64(windowCenter); + if (result.good()) result = m_WindowWidth.getFloat64(windowWidth); + if (result.good()) result = m_WindowCenterWindowWidthExplanation.getOFString(explanation, 0); + return result; +} + + +OFCondition FGFrameVOILUT::getVOILUTFunction(OFString& value, + const unsigned long pos) +{ + return m_VOILUTFunction.getOFString(value, pos); +} + + +// --- set() functionality --- + + +OFCondition FGFrameVOILUT::setWindowCenter(const OFString& value, + const OFBool checkValue) +{ + // no checks at the moment + return m_WindowCenter.putOFStringArray(value); +} + +OFCondition FGFrameVOILUT::setWindowWidth(const OFString& value, + const OFBool checkValue) +{ + // no checks at the moment + return m_WindowWidth.putOFStringArray(value); +} + + +OFCondition FGFrameVOILUT::setCenterWidthExplanation(const Float64& windowCenter, + const Float64& windowWidth, + const OFString& explanation, + const OFBool checkValue) +{ + OFCondition result = m_WindowCenter.putFloat64(windowCenter); + if (result.good()) result = m_WindowWidth.putFloat64(windowWidth); + if (result.good() && !explanation.empty()) + { + if (checkValue) + { + result = (checkValue) ? DcmLongString::checkStringValue(explanation, "1") : EC_Normal; + } + if (result.good()) + { + result = m_WindowCenterWindowWidthExplanation.putString(explanation.c_str()); + } + } + return result; +} + + +OFCondition FGFrameVOILUT::setVOILUTFunction(const OFString& value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmCodeString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_VOILUTFunction.putString(value.c_str()); + return result; +} + + +/// Read Frame Content Sequence from given item +OFCondition FGFrameVOILUT::read(DcmItem& item) +{ + clearData(); + + DcmItem* seqItem = NULL; + OFCondition result = getItemFromFGSequence(item, DCM_FrameVOILUTSequence, 0, seqItem); + if (result.bad()) + return result; + + DcmIODUtil::getAndCheckElementFromDataset(*seqItem, m_WindowCenter, "1-n", "1", "FrameVOILUTMacro"); + DcmIODUtil::getAndCheckElementFromDataset(*seqItem, m_WindowWidth, "1-n", "1", "FrameVOILUTMacro"); + DcmIODUtil::getAndCheckElementFromDataset(*seqItem, m_WindowCenterWindowWidthExplanation, "1-n", "3", "FrameVOILUTMacro"); + DcmIODUtil::getAndCheckElementFromDataset(*seqItem, m_VOILUTFunction, "1", "3", "FrameVOILUTMacro"); + + return EC_Normal; + +} + +/// Writes single Frame Content Sequence into given item +OFCondition FGFrameVOILUT::write(DcmItem& item) +{ + DcmItem *seqItem = NULL; + OFCondition result = createNewFGSequence(item, DCM_FrameVOILUTSequence, 0, seqItem); + if (result.bad()) + return result; + + // --- write frame content macro attributes --- + DcmIODUtil::copyElementToDataset(result, *seqItem, m_WindowCenter, "1-n", "1", "FrameVOILUTMacro"); + DcmIODUtil::copyElementToDataset(result, *seqItem, m_WindowWidth, "1-n", "1", "FrameVOILUTMacro"); + DcmIODUtil::copyElementToDataset(result, *seqItem, m_WindowCenterWindowWidthExplanation, "1-n", "3", "FrameVOILUTMacro"); + DcmIODUtil::copyElementToDataset(result, *seqItem, m_VOILUTFunction, "1", "3", "FrameVOILUTMacro"); + return result; +} + + +int FGFrameVOILUT::compare(const FGBase& rhs) const +{ + int result = FGBase::compare(rhs); + if (result != 0) + return result; + + const FGFrameVOILUT* myRhs = OFstatic_cast(const FGFrameVOILUT*, &rhs); + + // Compare all elements + result = m_WindowCenter.compare(myRhs->m_WindowCenter); + if (result == 0) + result = m_WindowWidth.compare(myRhs->m_WindowWidth); + if (result == 0) + result = m_WindowCenterWindowWidthExplanation.compare(myRhs->m_WindowCenterWindowWidthExplanation); + if (result == 0) + result = m_VOILUTFunction.compare(myRhs->m_VOILUTFunction); + + return result; +} diff --git a/dcmfg/libsrc/fgimagedatatype.cc b/dcmfg/libsrc/fgimagedatatype.cc new file mode 100644 index 00000000..ea83c8e4 --- /dev/null +++ b/dcmfg/libsrc/fgimagedatatype.cc @@ -0,0 +1,249 @@ +/* + * + * Copyright (C) 2015, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmfg + * + * Author: Michael Onken + * + * Purpose: Class for managing Image Data Type Functional Group + * + */ + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmdata/dcdeftag.h" +#include "dcmtk/dcmiod/iodutil.h" +#include "dcmtk/dcmfg/fgimagedatatype.h" +#include "dcmtk/dcmfg/fgtypes.h" + +// Constructor +FGImageDataType::FGImageDataType() : + FGBase(DcmFGTypes::EFG_IMAGEDATATYPE), + m_DataType(DCM_DataType), + m_AliasedDataType(DCM_AliasedDataType), + m_ZeroVelocityPixelValueUS(DCM_ZeroVelocityPixelValue), + m_ZeroVelocityPixelValueSS(DCM_ZeroVelocityPixelValue) +{ +} + + +FGImageDataType::~FGImageDataType() +{ + // nothing to do +} + + +FGBase* FGImageDataType::clone() const +{ + FGImageDataType* copy = new FGImageDataType(); + if (copy) + { + copy->m_DataType = this->m_DataType; + copy->m_AliasedDataType= this->m_AliasedDataType; + if (! OFconst_cast(DcmSignedShort*, &this->m_ZeroVelocityPixelValueSS)->isEmpty()) + { + copy->m_ZeroVelocityPixelValueSS = this->m_ZeroVelocityPixelValueSS; + } + else if (! OFconst_cast(DcmUnsignedShort*, &this->m_ZeroVelocityPixelValueUS)->isEmpty()) + { + copy->m_ZeroVelocityPixelValueUS = this->m_ZeroVelocityPixelValueUS; + } + // both emtpy? nothing to do then + } + return copy; +} + + +void FGImageDataType::clearData() +{ + m_DataType.clear(); + m_AliasedDataType.clear(); + m_ZeroVelocityPixelValueSS.clear(); + m_ZeroVelocityPixelValueUS.clear(); +} + + +OFCondition FGImageDataType::check() const +{ + // TODO + return EC_Normal; +} + + +// --- get() functionality --- + +OFCondition FGImageDataType::getDataType(OFString& value, + const long signed int pos) +{ + return DcmIODUtil::getStringValueFromElement(m_DataType, value, pos); +} + + +OFCondition FGImageDataType::getAliasedDataType(OFString& value, const long signed int pos) +{ + return DcmIODUtil::getStringValueFromElement(m_AliasedDataType, value, pos); +} + + +OFCondition FGImageDataType::getZeroVelocityPixelValue(Sint32& value, + const long signed int pos) +{ + OFCondition result; + if (!m_ZeroVelocityPixelValueSS.isEmpty()) + { + Sint16 val = 0; + if ( (result = m_ZeroVelocityPixelValueSS.getSint16(val)).good()) + { + value = val; + } + } + else if (!m_ZeroVelocityPixelValueUS.isEmpty()) + { + Uint16 val = 0; + if ( (result = m_ZeroVelocityPixelValueUS.getUint16(val)).good()) + { + value = val; + } + } + else + return EC_TagNotFound; + + return EC_Normal; +} + + +// --- set() functionality --- + + +OFCondition FGImageDataType::setDataType(const OFString& value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmCodeString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_DataType.putOFStringArray(value); + return result; +} + + +OFCondition FGImageDataType::setAliasedDataType(const OFString& value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmCodeString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_AliasedDataType.putOFStringArray(value); + return result; +} + + +OFCondition FGImageDataType::setZeroVelocityPixelValueSS(const Sint16 value) +{ + return m_ZeroVelocityPixelValueSS.putSint16(value); +} + + +OFCondition FGImageDataType::setZeroVelocityPixelValueUS(const Uint16 value) +{ + return m_ZeroVelocityPixelValueUS.putUint16(value); +} + + +/// Read Frame Content Sequence from given item +OFCondition FGImageDataType::read(DcmItem& item) +{ + clearData(); + + DcmItem* seqItem = NULL; + OFCondition result = getItemFromFGSequence(item, DCM_ImageDataTypeSequence, 0, seqItem); + if (result.bad()) + return result; + + DcmElement* elem = NULL; + DcmIODUtil::getAndCheckElementFromDataset(*seqItem, m_DataType, "1", "1", "ImageDataTypeMacro"); + DcmIODUtil::getAndCheckElementFromDataset(*seqItem, m_AliasedDataType, "1", "1", "ImageDataTypeMacro"); + + DcmIODUtil::getAndCheckElementFromDataset(*seqItem, *elem, "1", "1C", "ImageDataTypeMacro"); + if (elem) + { + if (elem->getVR() == EVR_SS) + { + m_ZeroVelocityPixelValueSS.copyFrom(*elem); + } + else if (elem->getVR() == EVR_US) + { + m_ZeroVelocityPixelValueUS.copyFrom(*elem); + } + else + { + Uint16 pixrep = 0; + if (item.findAndGetUint16(DCM_PixelRepresentation, pixrep).good()) + { + if (pixrep == 0) + { + m_ZeroVelocityPixelValueUS.putUint16(pixrep, 0); + } + else + { + m_ZeroVelocityPixelValueSS.putSint16(pixrep, 1); + } + } + else + { + DCMFG_ERROR("Cannot read Zero Velocity Pixel Value"); + } + } + } + return EC_Normal; +} + + +/// Writes single Frame Content Sequence into given item +OFCondition FGImageDataType::write(DcmItem& item) +{ + DcmItem *seqItem = NULL; + OFCondition result = createNewFGSequence(item, DCM_ImageDataTypeSequence, 0, seqItem); + if (result.bad()) + return result; + + // --- write frame content macro attributes --- + DcmIODUtil::copyElementToDataset(result, *seqItem, m_DataType, "1", "1", "ImageDataTypeMacro"); + DcmIODUtil::copyElementToDataset(result, *seqItem, m_AliasedDataType, "1", "1", "ImageDataTypeMacro"); + if (!m_ZeroVelocityPixelValueSS.isEmpty()) + { + DcmIODUtil::copyElementToDataset(result, *seqItem, m_ZeroVelocityPixelValueSS, "1", "1C", "ImageDataTypeMacro"); + } else if (!m_ZeroVelocityPixelValueUS.isEmpty()) + { + DcmIODUtil::copyElementToDataset(result, *seqItem, m_ZeroVelocityPixelValueUS, "1", "1C", "ImageDataTypeMacro"); + } + + return result; +} + + +int FGImageDataType::compare(const FGBase& rhs) const +{ + int result = FGBase::compare(rhs); + if (result != 0) + return result; + + const FGImageDataType* myRhs = OFstatic_cast(const FGImageDataType*, &rhs); + + // Compare all elements + result = m_DataType.compare(myRhs->m_DataType); + if (result == 0) + result = m_AliasedDataType.compare(myRhs->m_AliasedDataType); + if (result == 0) + result = m_ZeroVelocityPixelValueSS.compare(myRhs->m_ZeroVelocityPixelValueSS); + if (result == 0) + result = m_ZeroVelocityPixelValueUS.compare(myRhs->m_ZeroVelocityPixelValueUS); + + return result; +} diff --git a/dcmfg/libsrc/fginterface.cc b/dcmfg/libsrc/fginterface.cc new file mode 100644 index 00000000..651fb9c3 --- /dev/null +++ b/dcmfg/libsrc/fginterface.cc @@ -0,0 +1,677 @@ +/* + * + * Copyright (C) 2015, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmfg + * + * Author: Michael Onken + * + * Purpose: Main interface class for managing Functional Groups + * + */ + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/ofstd/ofmap.h" +#include "dcmtk/ofstd/ofmem.h" +#include "dcmtk/dcmiod/iodutil.h" // for static helpers +#include "dcmtk/dcmfg/fginterface.h" +#include "dcmtk/dcmfg/fg.h" +#include "dcmtk/dcmfg/fgfact.h" // for creating new functional groups + + +FGInterface::FGInterface() : +m_shared(), +m_perFrame() +{ +} + + +FGInterface::~FGInterface() +{ + clear(); +} + + +void FGInterface::clear() +{ + // Clear per frame functional groups + while (m_perFrame.size() > 0) + { + OFMap::iterator it = m_perFrame.begin(); + FunctionalGroups* fg = (*it).second; + m_perFrame.erase(it); + delete fg; + } + + // Clear shared functional groups + m_shared.clear(); +} + + +size_t FGInterface::getNumberOfFrames() +{ + return m_perFrame.size(); +} + + +OFCondition FGInterface::addShared(const FGBase& group) +{ + DcmFGTypes::E_FGSharedType sharedType = group.getSharedType(); + if ( sharedType == DcmFGTypes::EFGS_ONLYPERFRAME ) + { + DCMFG_ERROR("Cannot add group as shared, per DICOM, group type " << DcmFGTypes::FGType2OFString(group.getType()) << " is always per-frame"); + return FG_EC_CouldNotAddFG; + } + + // Delete all per frame groups of this type + for (size_t count = 0; count < m_perFrame.size(); count++) + { + deletePerFrame(count, group.getType()); + } + + // Create copy for insertion + FGBase* copy = group.clone(); + if (!copy) + { + return EC_MemoryExhausted; + } + + // Insert shared one, replace old one if existing + OFCondition result = insertShared(copy, OFTrue /* replace */); + if (result.bad()) + { + DCMFG_ERROR("Could not add shared group of type: " << DcmFGTypes::FGType2OFString(group.getType()));; + delete copy; + } + + return result; +} + + +OFCondition FGInterface::addPerFrame(const Uint32 frameNo, + const FGBase& group) +{ + OFCondition result = EC_Normal; + DcmFGTypes::E_FGSharedType sharedType = group.getSharedType(); + if ( sharedType == DcmFGTypes::EFGS_ONLYSHARED) + { + DCMFG_ERROR("Cannot add group as per-frame, group type " << DcmFGTypes::FGType2OFString(group.getType()) << " is always shared"); + return FG_EC_CouldNotAddFG; + } + + // Check whether there is already a shared group of this type. + // If the content is equal to the given group, we re-use the shared one + FGBase* shared = getShared(group.getType()); + // If there is a shared group + if ( shared ) + { + // If shared has identical values as given group, nothing has to be done. + // Else if shared group with such type exists, but content differs, + // we must the make the existing shared FG "per-frame", i.e. distribute + // it to all frames, and add the given group for the given frame. + if ( (*shared).compare(group) != 0 ) + { + // We need to unshare this group, i.e. distribute it to frames + DCMFG_DEBUG("Converting shared group of type " << DcmFGTypes::FGType2OFString(group.getType()) << " to per-frame, triggered by deviating per-frame insertion"); + result = convertSharedToPerFrame(group.getType()); + } + else + { + DCMFG_DEBUG("Re-using shared group instead of adding per-frame for frame " << frameNo << ", type " << DcmFGTypes::FGType2OFString(group.getType())); + return EC_Normal; + } + } + + if (result.good()) + { + FGBase* copy = group.clone(); + if (!copy) + return EC_MemoryExhausted; + result = insertPerFrame(frameNo, copy); + if (result.bad()) + delete copy; + } + + return result; +} + + +// Get specific functional group for a frame, +// no matter whether it is stored per frame or shared +FGBase* FGInterface::get(const Uint32 frameNo, + const DcmFGTypes::E_FGType fgType) +{ + OFBool helpShared; // throw-away variable + return get(frameNo, fgType, helpShared); +} + + +const FunctionalGroups* FGInterface::getPerFrame(const Uint32 frameNo) const +{ + if (frameNo > m_perFrame.size()) + { + return NULL; + } + else + { + return (*(m_perFrame.find(frameNo))).second; + } +} + + +const FunctionalGroups* FGInterface::getShared() const +{ + return &m_shared; +} + + +// Read enhanced multi-frame information from DICOM item, usually DcmDataset +OFCondition FGInterface::read(DcmItem& dataset) +{ + OFCondition result = EC_Normal; + + // clear any old values + clear(); + + /* read shared functional groups */ + if (result.good()) + { + result = readSharedFG(dataset); + } + + /* read per frame functional groups */ + if (result.good()) + { + result = readPerFrameFG(dataset); + } + + return result; + +} + + +OFCondition FGInterface::readSharedFG(DcmItem& dataset) +{ + /* read shared functional groups */ + DcmSequenceOfItems *shared = NULL; + OFCondition result = dataset.findAndGetSequence(DCM_SharedFunctionalGroupsSequence, shared); + if (result.bad()) + { + DCMFG_ERROR("Could not find Shared Functional Group Sequence"); + return FG_EC_NoSharedFG; + } + + if (shared->card() > 1) + { + DCMFG_WARN("More than one item in Shared Functional Group Sequence, only considering the first one"); + } + else if (shared->card() == 0) + { + DCMFG_WARN("No Item in Shared Functional Group Sequence but exactly one expected"); + return FG_EC_NoSharedFG; + } + + // get the only item of shared functional group sequence + DcmItem* sharedFGs = shared->getItem(0); + // read all functional groups from shared fg sequence item + result = readSingleFG(*sharedFGs, m_shared); + + return result; +} + + + +OFCondition FGInterface::readPerFrameFG(DcmItem& dataset) +{ + /* read per-frame functional groups */ + DcmSequenceOfItems *perFrame = NULL; + OFCondition result = dataset.findAndGetSequence(DCM_PerFrameFunctionalGroupsSequence, perFrame); + if (result.bad()) + { + DCMFG_ERROR("Could not find Per-Frame Functional Group Sequence"); + return FG_EC_NoPerFrameFG; + } + + /* 1-n items required */ + size_t numFrames = perFrame->card(); + if (numFrames == 0) + { + DCMFG_WARN("No Item in Shared Functional Group Sequence but exactly one or more expected"); + return FG_EC_NoPerFrameFG; + } + + /* Read functional groups for each item (one per frame) */ + for (size_t count = 0; count < numFrames; count++) + { + DcmItem* oneFrameItem = perFrame->getItem(count); + OFauto_ptr perFrameGroups(new FunctionalGroups()); + // FunctionalGroups* perFrameGroups = new FunctionalGroups(); + if (!oneFrameItem) + { + DCMFG_ERROR("Could not get functional group item for frame #" << count << "(internal error)"); + } + else if (!perFrameGroups.get()) + { + DCMFG_ERROR("Could not create functional groups for frame #" << count << ": Memory exhausted?"); + } + else + { + result = readSingleFG(*oneFrameItem, *perFrameGroups); + if (result.good()) + { + if ( !m_perFrame.insert( OFMake_pair(count, perFrameGroups.release()) ).second ) + { + DCMFG_ERROR("Could not store functional groups for frame #" << count << " (internal error)"); + } + } + else + { + DCMFG_ERROR("Could not read functional groups for frame #" << count << ": " << result.text() ); + } + } + } + return EC_Normal; // for now we always return EC_Normal... +} + + + +OFCondition FGInterface::readSingleFG(DcmItem& fgItem, + FunctionalGroups& groups) +{ + OFCondition result; + size_t card = fgItem.card(); + OFString fgname; + for (size_t count = 0; count < card; count++) + { + DcmElement *elem = fgItem.getElement(count); + // TODO: non-sequence elements are not explicily forbidden here(?), we could store them and re-store them later + if (elem->getVR() != EVR_SQ) + { + DCMFG_WARN("Found non-sequence element in functional group sequence item (ignored): " << elem->getTag()); + } + else + { + FGBase *fg = FGFactory::instance().create(elem->getTag()); + if (fg != NULL) + { + OFStringStream stream; + stream << DcmFGTypes::tagKey2FGString(elem->getTag()) << " " << elem->getTag(); + OFSTRINGSTREAM_GETSTR(stream,tmpstr) + fgname = tmpstr; + OFSTRINGSTREAM_FREESTR(tmpstr) + result = fg->read(fgItem); + if (result.bad()) + { + DCMFG_WARN("Cannot read functional group: " << fgname << " (ignored)"); + } + // we also accept groups while reading which could instantiated but not could not be read + result = groups.insert(fg, OFTrue); + if (result.good()) + { + DCMFG_DEBUG("Inserted functional group: " << fgname ); + } + else + { + DCMFG_ERROR("Could not insert functional group: " << fgname << " (internal error)"); + delete fg; + } + } + else + { + DCMFG_WARN("Cannot understand functional group for sequence tag: " << elem->getTag()); + } + } + } + return EC_Normal; // for now we always return EC_Normal... +} + + + +// Write enhanced multi-frame information to DICOM item, usually DcmDataset +OFCondition FGInterface::write(DcmItem& dataset) +{ + //Check data integrity of functional group macros */ + if ( !check() ) + return FG_EC_CouldNotWriteFG; + + // Write shared functional Groups + OFCondition result = writeSharedFG(dataset); + + // Write per frame functional groups + if ( result.good() ) result = writePerFrameFG(dataset); + + return result; +} + + +// TODO: overload (templates?) to return correct derived class type? +FGBase* FGInterface::getShared(const DcmFGTypes::E_FGType fgType) +{ + return m_shared.find(fgType); +} + + +OFCondition FGInterface::insertShared(FGBase* group, + const OFBool replaceExisting) +{ + return m_shared.insert(group, replaceExisting); +} + + +FGBase* FGInterface::getPerFrame(const Uint32 frameNo, + const DcmFGTypes::E_FGType fgType) +{ + FGBase* group = NULL; + OFMap::iterator it = m_perFrame.find(frameNo); + if ( it != m_perFrame.end() ) + { + FunctionalGroups* perFrameGroups = (*it).second; + group = perFrameGroups->find(fgType); + } + + return group; +} + + +OFBool FGInterface::deleteShared(const DcmFGTypes::E_FGType fgType) +{ + FGBase* group = m_shared.find(fgType); + if (group) + { + delete m_shared.remove(fgType); + return OFTrue; + } + return OFFalse; +} + + + +OFBool FGInterface::deletePerFrame(const Uint32 frameNo, + const DcmFGTypes::E_FGType fgType) +{ + OFMap::iterator it = m_perFrame.find(frameNo); + if (it != m_perFrame.end()) + { + if ( (*it).second ) + { + FGBase *remove = (*it).second->remove(fgType); + if (remove) + { + DCMFG_DEBUG("Deleting FG for frame " << frameNo << ", type: " << DcmFGTypes::FGType2OFString(fgType)); + delete remove; + remove = NULL; + return OFTrue; + } + } + } + return OFFalse; +} + + +size_t FGInterface::deletePerFrame(const DcmFGTypes::E_FGType fgType) +{ + size_t numDeleted = 0; + const size_t numFrames = m_perFrame.size(); + for (size_t frameNo = 0; frameNo < numFrames; frameNo++) + { + if (deletePerFrame(frameNo, fgType)) + { + numDeleted++; + } + } + return numDeleted; +} + + + +FunctionalGroups* FGInterface::getOrCreatePerFrameGroups(const Uint32 frameNo) +{ + OFMap::iterator it = m_perFrame.find(frameNo); + if (it != m_perFrame.end()) + return (*it).second; + + FunctionalGroups *fg = new FunctionalGroups(); + if (fg != NULL) + { + if ( !(m_perFrame.insert(OFMake_pair(frameNo, fg))).second ) + { + DCMFG_ERROR("Could not insert Per-frame Functional Groups for frame " << frameNo << ": " << "Internal error"); + delete fg; + fg = NULL; + } + } + else + { + DCMFG_ERROR("Could not create Per-frame Functional Groups for frame " << frameNo << ": " << "Memory exhausted"); + } + + return fg; +} + + +OFCondition FGInterface::writePerFrameFG(DcmItem& dataset) +{ + DCMFG_DEBUG("Writing per-frame functional groups"); + OFCondition result = dataset.insertEmptyElement(DCM_PerFrameFunctionalGroupsSequence, OFTrue); // start with empty sequence + if (result.bad()) + { + DCMFG_ERROR("Could not create Per-frame Functional Groups Sequence"); + return result; + } + + /* Iterate over frames */ + OFMap::iterator it = m_perFrame.begin(); + size_t numFrames = m_perFrame.size(); + for ( size_t count = 0; (count < numFrames) && result.good(); count++) + { + DcmItem* perFrameItem = NULL; + result = dataset.findOrCreateSequenceItem(DCM_PerFrameFunctionalGroupsSequence, perFrameItem, count); + if (result.good()) + { + /* Iterate over groups for each frame */ + FunctionalGroups::iterator groupIt = (*it).second->begin(); + while ( result.good() && (groupIt != (*it).second->end()) ) + { + DCMFG_DEBUG("Writing per-frame group: " << DcmFGTypes::FGType2OFString((*groupIt).second->getType()) << " for frame #" << count); + result = (*groupIt).second->write(*perFrameItem); + groupIt++; + } + } + else + { + DCMFG_ERROR("Cannot create item in Per-frame Functional Groups Sequence"); + } + it++; + } + return result; +} + + +OFCondition FGInterface::writeSharedFG(DcmItem& dataset) +{ + DCMFG_DEBUG("Writing shared functional groups"); + OFCondition result = dataset.insertEmptyElement(DCM_SharedFunctionalGroupsSequence, OFTrue); // start with empty sequence + DcmItem *sharedFGItem = NULL; + if (result.good()) + { + result = dataset.findOrCreateSequenceItem(DCM_SharedFunctionalGroupsSequence, sharedFGItem, 0); + } + if (result.bad()) + { + DCMFG_ERROR("Could not create Shared Functional Groups Sequence with single item"); + return result; + } + + FunctionalGroups::iterator it = m_shared.begin(); + while ( (it != m_shared.end()) && result.good() ) + { + DCMFG_DEBUG("Writing shared group: " << DcmFGTypes::FGType2OFString((*it).second->getType())); + result = (*it).second->write(*sharedFGItem); + it++; + } + return result; +} + + +OFCondition FGInterface::insertPerFrame(const Uint32 frameNo, + FGBase* group, + const OFBool replaceExisting) +{ + if (group == NULL) + return EC_IllegalParameter; + + OFCondition result = EC_Normal; + FGBase* existing = getPerFrame(frameNo, group->getType()); + if (existing) + { + if (replaceExisting) + { + DCMFG_DEBUG("Replacing per-frame FG for frame: " << frameNo << ", type: " << DcmFGTypes::FGType2OFString(group->getType())); + deletePerFrame(frameNo, group->getType()); + } + else + { + result = FG_EC_DoubledFG; + } + } + + // Insert per-frame functional group + if (result.good()) + { + FunctionalGroups* perFrameGroups = getOrCreatePerFrameGroups(frameNo); + if (perFrameGroups != NULL) + { + result = perFrameGroups->insert(group, replaceExisting); + } + else + { + result = FG_EC_CouldNotInsertFG; + } + } + return result; +} + + +OFCondition FGInterface::convertSharedToPerFrame(const DcmFGTypes::E_FGType fgType) +{ + FGBase* shared = m_shared.remove(fgType); + if (!shared) + { + return FG_EC_NoSuchGroup; + } + + OFCondition result; + size_t numFrames = m_perFrame.size(); + // Walk over all existing frames and copy "old" shared group to them + size_t count = 0; + for (count = 0; result.good() && (count < numFrames); count++) + { + FGBase* clone = shared->clone(); + if (!clone) + { + result = EC_MemoryExhausted; + } + else + { + result = insertPerFrame(count, clone, OFTrue /* replace existing */); + if (result.bad()) + { + delete clone; + } + } + } + return result ; +} + + +FGBase* FGInterface::get(const Uint32 frameNo, + const DcmFGTypes::E_FGType fgType, + OFBool& isPerFrame) +{ + FGBase *group = m_shared.find(fgType); + if ( !group ) + { + group = getPerFrame(frameNo, fgType); + isPerFrame = OFTrue; + } + else + { + isPerFrame = OFFalse; + } + + return group; +} + + +OFBool FGInterface::check() +{ + size_t numFrames = m_perFrame.size(); + DCMFG_DEBUG("Checking functional group structure for " << numFrames << " frames"); + size_t numErrors = 0; + for (size_t frameCount = 0; frameCount < numFrames; frameCount++) + { + DCMFG_TRACE("Checking frame " << frameCount << "..."); + // Every frame requires the FrameContent functional group, check "en passent" + OFBool foundFrameContent = OFFalse; + OFMap::iterator frameFG = m_perFrame.begin(); + while (frameFG != m_perFrame.end()) + { + FunctionalGroups::iterator group = (*frameFG).second->begin(); + while (group != (*frameFG).second->end()) + { + // Check that per-frame group is not shared group at the same time + DcmFGTypes::E_FGType groupType = group->second->getType(); + if ( (groupType != DcmFGTypes::EFG_UNDEFINED) && + (groupType != DcmFGTypes::EFG_UNKNOWN) ) + { + if (m_shared.find(groupType) != NULL) + { + DCMFG_ERROR("Functional group of type " << DcmFGTypes::FGType2OFString(groupType) << " is shared AND per-frame for frame " << frameCount); + numErrors++; + } + if (groupType == DcmFGTypes::EFG_FRAMECONTENT) + foundFrameContent = OFTrue; + } + // Check if "per-frame" is allowed for this group; + if (group->second->getSharedType() == DcmFGTypes::EFGS_ONLYSHARED) + { + DCMFG_ERROR("Functional group of type " << DcmFGTypes::FGType2OFString(groupType) << " can never be per-frame, but found for frame " << frameCount); + numErrors++; + } + group++; + } + frameFG++; + } + if (!foundFrameContent) + { + DCMFG_ERROR("Frame Content FGfunctioanl group missing for frame # " << frameCount ); + numErrors++; + } + } + + // Check whether shared groups contain FGs that are only permitted per-frame + FunctionalGroups::iterator it = m_shared.begin(); + while (it != m_shared.begin()) + { + if ( (*it).second->getSharedType() == DcmFGTypes::EFGS_ONLYPERFRAME ) + { + DCMFG_ERROR("Functional group of type " << DcmFGTypes::FGType2OFString((*it).second->getType()) << " used as shared functional group but must be per-frame "); + numErrors++; + } + it++; + } + + if (numErrors > 0) + return OFFalse; + + return OFTrue; +} diff --git a/dcmfg/libsrc/fgpixmsr.cc b/dcmfg/libsrc/fgpixmsr.cc new file mode 100644 index 00000000..09a20410 --- /dev/null +++ b/dcmfg/libsrc/fgpixmsr.cc @@ -0,0 +1,162 @@ +/* + * + * Copyright (C) 2015, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmfg + * + * Author: Michael Onken + * + * Purpose: Class for managing Pixel Measures Functional Group + * + */ + + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmfg/fgpixmsr.h" +#include "dcmtk/dcmdata/dcdeftag.h" +#include "dcmtk/dcmiod/iodutil.h" + + +FGPixelMeasures::FGPixelMeasures() +: FGBase(DcmFGTypes::EFG_PIXELMEASURES), + m_PixelSpacing(DCM_PixelSpacing), + m_SliceThickness(DCM_SliceThickness), + m_SpacingBetweenSlices(DCM_SpacingBetweenSlices) +{ +} + + +FGPixelMeasures::~FGPixelMeasures() +{ + // nothing to do +} + + +FGBase* FGPixelMeasures::clone() const +{ + FGPixelMeasures* copy = new FGPixelMeasures(); + if (copy) + { + copy->m_PixelSpacing = this->m_PixelSpacing; + copy->m_SliceThickness = this->m_SliceThickness; + copy->m_SpacingBetweenSlices = this->m_SpacingBetweenSlices; + } + return copy; +} + + +void FGPixelMeasures::clearData() +{ + m_PixelSpacing.clear(); + m_SliceThickness.clear(); + m_SpacingBetweenSlices.clear(); +} + + +OFCondition FGPixelMeasures::check() const +{ + // TODO + return EC_Normal; +} + + +int FGPixelMeasures::compare(const FGBase& rhs) const +{ + int result = FGBase::compare(rhs); + if (result != 0) + return result; + + const FGPixelMeasures* myRhs = OFstatic_cast(const FGPixelMeasures*, &rhs); + + // Compare all elements + result = m_PixelSpacing.compare(myRhs->m_PixelSpacing); + if (result == 0) + result = m_SliceThickness.compare(myRhs->m_SliceThickness); + if (result == 0) + result = m_SpacingBetweenSlices.compare(myRhs->m_SpacingBetweenSlices); + + return result; +} + + +/// Read from Frame Content Sequence +OFCondition FGPixelMeasures::read(DcmItem& item) +{ + clearData(); + + OFCondition result; + DcmItem* seqItem = NULL; + result = getItemFromFGSequence(item, DCM_PixelMeasuresSequence, 0, seqItem); + if (result.bad()) + return result; + + DcmIODUtil::getAndCheckElementFromDataset(*seqItem, m_PixelSpacing, "2", "1C", "PixelMeasuresMacro"); + DcmIODUtil::getAndCheckElementFromDataset(*seqItem, m_SliceThickness, "1", "1C", "PixelMeasuresMacro"); + DcmIODUtil::getAndCheckElementFromDataset(*seqItem, m_SpacingBetweenSlices, "1", "3", "PixelMeasuresMacro"); + + return EC_Normal; +} + +OFCondition FGPixelMeasures::write(DcmItem& item) +{ + DcmItem* seqItem = NULL; + OFCondition result = createNewFGSequence(item, DCM_PixelMeasuresSequence, 0, seqItem); + if (result.bad()) + return result; + + // --- write frame content macro attributes --- + DcmIODUtil::copyElementToDataset(result, *seqItem, m_PixelSpacing, "2", "1C", "PixelMeasuresMacro"); + DcmIODUtil::copyElementToDataset(result, *seqItem, m_SliceThickness, "1", "1C", "PixelMeasuresMacro"); + DcmIODUtil::copyElementToDataset(result, *seqItem, m_SpacingBetweenSlices, "1", "3", "PixelMeasuresMacro"); + + return result; +} + + +OFCondition FGPixelMeasures::getPixelSpacing(Float64& value, + const signed long pos) +{ + return m_PixelSpacing.getFloat64(value, pos); +} + + +OFCondition FGPixelMeasures:: getSliceThickness(Float64& value, + const signed long pos) +{ + return m_SliceThickness.getFloat64(value, pos); +} + + +OFCondition FGPixelMeasures:: getSpacingBetweenSlices(Float64& value, + const signed long pos) +{ + return m_SpacingBetweenSlices.getFloat64(value, pos); +} + + +OFCondition FGPixelMeasures::setPixelSpacing(const OFString& value, + const OFBool checkValue) +{ + return m_PixelSpacing.putOFStringArray(value); +} + + +OFCondition FGPixelMeasures::setSliceThickness(const OFString& value, + const OFBool checkValue) +{ + return m_SliceThickness.putOFStringArray(value); +} + +OFCondition FGPixelMeasures::setSpacingBetweenSlices(const OFString& value, + const OFBool checkValue) +{ + return m_SpacingBetweenSlices.putOFStringArray(value);} diff --git a/dcmfg/libsrc/fgplanor.cc b/dcmfg/libsrc/fgplanor.cc new file mode 100644 index 00000000..b46599d5 --- /dev/null +++ b/dcmfg/libsrc/fgplanor.cc @@ -0,0 +1,185 @@ +/* + * + * Copyright (C) 2015, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmfg + * + * Author: Michael Onken + * + * Purpose: Class for managing Plane Orientation (Patient) Functional Group + * + */ + + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmfg/fgplanor.h" +#include "dcmtk/dcmfg/fgfact.h" +#include "dcmtk/dcmdata/dcdeftag.h" +#include "dcmtk/dcmiod/iodutil.h" + + +FGPlaneOrientationPatient::FGPlaneOrientationPatient() : + FGBase(DcmFGTypes::EFG_PLANEORIENTPATIENT), + m_ImageOrientationPatient(DCM_ImageOrientationPatient) +{ +} + +/// clear old values +void FGPlaneOrientationPatient::clearData() +{ + m_ImageOrientationPatient.clear(); +} + + +OFCondition FGPlaneOrientationPatient::check() const +{ + // TODO + return EC_Normal; +} + + +FGBase* FGPlaneOrientationPatient::clone() const +{ + FGPlaneOrientationPatient* copy = new FGPlaneOrientationPatient(); + if (copy) + { + copy->m_ImageOrientationPatient = this->m_ImageOrientationPatient; + } + return copy; +} + + +FGPlaneOrientationPatient* FGPlaneOrientationPatient::createMinimal(const OFString& imageOrientationPatientRowX, + const OFString& imageOrientationPatientRowY, + const OFString& imageOrientationPatientRowZ, + const OFString& imageOrientationPatientColX, + const OFString& imageOrientationPatientColY, + const OFString& imageOrientationPatientColZ) +{ + FGPlaneOrientationPatient *fg = OFstatic_cast(FGPlaneOrientationPatient*, FGFactory::instance().create(DcmFGTypes::EFG_PLANEORIENTPATIENT)); + if (fg) + { + OFCondition result = fg->setImageOrientationPatient(imageOrientationPatientRowX, + imageOrientationPatientRowY, + imageOrientationPatientRowZ, + imageOrientationPatientColX, + imageOrientationPatientColY, + imageOrientationPatientColZ); + if (result.bad()) + { + DCMFG_ERROR("Could not create new FGPlaneOrientationPatient: Invalid data for Image Orientation Patient: " << result.text()); + delete fg; + return NULL; + } + } + return fg; +} + + + +/// Read from Plane Position Sequence +OFCondition FGPlaneOrientationPatient::read(DcmItem& item) +{ + clearData(); + + DcmItem *seqItem = NULL; + OFCondition result = getItemFromFGSequence(item, DCM_PlaneOrientationSequence, 0, seqItem); + if (result.bad()) + return result; + + DcmIODUtil::getAndCheckElementFromDataset(*seqItem, m_ImageOrientationPatient, "6", "1C", "PlaneOrientationPatient"); + + return EC_Normal; +} + + +OFCondition FGPlaneOrientationPatient::write(DcmItem& item) +{ + DcmItem *seqItem = NULL; + OFCondition result = createNewFGSequence(item, DCM_PlaneOrientationSequence, 0, seqItem); + if (result.bad()) + return result; + + // --- write plane position (patient) attributes --- + DcmIODUtil::copyElementToDataset(result, *seqItem, m_ImageOrientationPatient, "6", "1C", "PlaneOrientationPatient"); + + return result; +} + + + +int FGPlaneOrientationPatient::compare(const FGBase& rhs) const +{ + int result = FGBase::compare(rhs); + if (result == 0) + { + const FGPlaneOrientationPatient* myRhs = OFstatic_cast(const FGPlaneOrientationPatient*, &rhs); + + // Compare all elements + result = m_ImageOrientationPatient.compare(myRhs->m_ImageOrientationPatient); + } + + return result; +} + + +OFCondition FGPlaneOrientationPatient::getImageOrientationPatient(OFString& value, + const signed long pos = 0) + +{ + return DcmIODUtil::getStringValueFromElement(m_ImageOrientationPatient, value, pos); +} + + +OFCondition FGPlaneOrientationPatient::getImageOrientationPatient(Float64& rowX, + Float64& rowY, + Float64& rowZ, + Float64& colX, + Float64& colY, + Float64& colZ) +{ + OFCondition result = m_ImageOrientationPatient.getFloat64(rowX, 0); + if (result.good()) m_ImageOrientationPatient.getFloat64(rowY, 1); + if (result.good()) m_ImageOrientationPatient.getFloat64(rowZ, 2); + if (result.good()) m_ImageOrientationPatient.getFloat64(colX, 3); + if (result.good()) m_ImageOrientationPatient.getFloat64(colY, 4); + if (result.good()) m_ImageOrientationPatient.getFloat64(colZ, 5); + return result; +} + + +OFCondition FGPlaneOrientationPatient::setImageOrientationPatient(const OFString& rowX, + const OFString& rowY, + const OFString& rowZ, + const OFString& colX, + const OFString& colY, + const OFString& colZ, + const OFBool checkValue) +{ + OFString str(rowX); str += "\\"; + str += rowY; str += "\\"; + str += rowZ; str += "\\"; + str += colX; str += "\\"; + str += colY; str += "\\"; + str += colZ; + + OFCondition result = (checkValue) ? DcmDecimalString::checkStringValue(str, "6") : EC_Normal; + if (result.good()) + result = m_ImageOrientationPatient.putOFStringArray(str); + return result; +} + + +FGPlaneOrientationPatient::~FGPlaneOrientationPatient() +{ + // nothing to do +} diff --git a/dcmfg/libsrc/fgplanorvol.cc b/dcmfg/libsrc/fgplanorvol.cc new file mode 100644 index 00000000..d5c038f0 --- /dev/null +++ b/dcmfg/libsrc/fgplanorvol.cc @@ -0,0 +1,160 @@ +/* + * + * Copyright (C) 2015, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmfg + * + * Author: Michael Onken + * + * Purpose: Class for managing Plane Orientation (Volume) Functional Group + * + */ + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmdata/dcvrfd.h" +#include "dcmtk/dcmdata/dcdeftag.h" +#include "dcmtk/dcmiod/iodutil.h" +#include "dcmtk/dcmfg/fgplanorvol.h" +#include "dcmtk/dcmfg/fgtypes.h" + + +// Constructor +FGPlaneOrientationVolume::FGPlaneOrientationVolume() : + FGBase(DcmFGTypes::EFG_PLANEORIENTVOLUME), + m_ImageOrientationVolume(DCM_ImageOrientationVolume) +{ +} + + +FGPlaneOrientationVolume::~FGPlaneOrientationVolume() +{ + // nothing to do +} + + +FGBase* FGPlaneOrientationVolume::clone() const +{ + FGPlaneOrientationVolume* copy = new FGPlaneOrientationVolume(); + if (copy) + { + copy->m_ImageOrientationVolume = this->m_ImageOrientationVolume; + } + return copy; +} + + +void FGPlaneOrientationVolume::clearData() +{ + m_ImageOrientationVolume.clear(); +} + + +OFCondition FGPlaneOrientationVolume::check() const +{ + // TODO + return EC_Normal; +} + + +// --- get() functionality --- + +OFCondition FGPlaneOrientationVolume::getImageOrientationVolume(Float64& value, + const long unsigned int pos) +{ + return m_ImageOrientationVolume.getFloat64(value, pos); +} + + + +OFCondition FGPlaneOrientationVolume::getImageOrientationVolume(Float64& rowX, + Float64& rowY, + Float64& rowZ, + Float64& colX, + Float64& colY, + Float64& colZ) +{ + OFCondition result = m_ImageOrientationVolume.getFloat64(rowX, 0); + if (result.good()) result = m_ImageOrientationVolume.getFloat64(rowY, 1); + if (result.good()) result = m_ImageOrientationVolume.getFloat64(rowZ, 2); + if (result.good()) result = m_ImageOrientationVolume.getFloat64(colX, 3); + if (result.good()) result = m_ImageOrientationVolume.getFloat64(colY, 4); + if (result.good()) result = m_ImageOrientationVolume.getFloat64(colZ, 5); + return result; +} + + +// --- set() functionality --- + + +OFCondition FGPlaneOrientationVolume::setImageOrientationVolume(const Float64& rowX, + const Float64& rowY, + const Float64& rowZ, + const Float64& colX, + const Float64& colY, + const Float64& colZ, + const OFBool) +{ + OFCondition result = m_ImageOrientationVolume.putFloat64(rowX, 0); + if (result.good()) m_ImageOrientationVolume.putFloat64(rowY, 1); + if (result.good()) m_ImageOrientationVolume.putFloat64(rowZ, 2); + if (result.good()) m_ImageOrientationVolume.putFloat64(colX, 3); + if (result.good()) m_ImageOrientationVolume.putFloat64(colY, 4); + if (result.good()) m_ImageOrientationVolume.putFloat64(colZ, 5); + return result; +} + + +/// Read Plane Orientation (Volume) Sequence from given item +OFCondition FGPlaneOrientationVolume::read(DcmItem& item) +{ + clearData(); + + DcmItem* seqItem = NULL; + OFCondition result = getItemFromFGSequence(item, DCM_PlaneOrientationVolumeSequence, 0, seqItem); + if (result.bad()) + return result; + + DcmIODUtil::getAndCheckElementFromDataset(*seqItem, m_ImageOrientationVolume, "6", "1", "PlaneOrientationVolume"); + + return EC_Normal; + +} + +/// Writes single Plane Orientation (Volume) Sequence into given item +OFCondition FGPlaneOrientationVolume::write(DcmItem& item) +{ + DcmItem *seqItem = NULL; + OFCondition result = createNewFGSequence(item, DCM_PlaneOrientationVolumeSequence, 0, seqItem); + if (result.bad()) + return result; + + // --- write frame content macro attributes --- + DcmIODUtil::copyElementToDataset(result, *seqItem, m_ImageOrientationVolume, "6", "1", "PlaneOrientationVolume"); + return result; +} + + +int FGPlaneOrientationVolume::compare(const FGBase& rhs) const +{ + int result = FGBase::compare(rhs); + if (result != 0) + return result; + + const FGPlaneOrientationVolume* myRhs = OFstatic_cast(const FGPlaneOrientationVolume*, &rhs); + + // Compare all elements + result = m_ImageOrientationVolume.compare(myRhs->m_ImageOrientationVolume); + return result; +} + + + diff --git a/dcmfg/libsrc/fgplanpo.cc b/dcmfg/libsrc/fgplanpo.cc new file mode 100644 index 00000000..be4c46da --- /dev/null +++ b/dcmfg/libsrc/fgplanpo.cc @@ -0,0 +1,166 @@ +/* + * + * Copyright (C) 2015, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmfg + * + * Author: Michael Onken + * + * Purpose: Class for managing Plane Position (Patient) Functional Group + * + */ + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmfg/fgplanpo.h" +#include "dcmtk/dcmfg/fgfact.h" +#include "dcmtk/dcmdata/dcdeftag.h" +#include "dcmtk/dcmiod/iodutil.h" + +FGPlanePosPatient::FGPlanePosPatient() : + FGBase(DcmFGTypes::EFG_PLANEPOSPATIENT), + m_ImagePositionPatient(DCM_ImagePositionPatient) +{ +} + +FGBase* FGPlanePosPatient::clone() const +{ + FGPlanePosPatient* copy = new FGPlanePosPatient(); + if (copy) + { + copy->m_ImagePositionPatient = this->m_ImagePositionPatient; + } + return copy; +} + + +FGPlanePosPatient* FGPlanePosPatient::createMinimal(const OFString& imagePositionPatientX, + const OFString& imagePositionPatientY, + const OFString& imagePositionPatientZ) +{ + FGPlanePosPatient *fg = OFstatic_cast(FGPlanePosPatient*, FGFactory::instance().create(DcmFGTypes::EFG_PLANEPOSPATIENT)); + if (fg) + { + OFCondition result = fg->setImagePositionPatient(imagePositionPatientX, imagePositionPatientY, imagePositionPatientZ); + if (result.bad()) + { + DCMFG_ERROR("Coudl not create new FGPlanePosPatient: Invalid data for Image Position Patient: " << result.text()); + delete fg; + return NULL; + } + } + return fg; +} + + + +/// clear old values +void FGPlanePosPatient::clearData() +{ + m_ImagePositionPatient.clear(); +} + + +OFCondition FGPlanePosPatient::check() const +{ + // TODO + return EC_Normal; +} + + +/// Read from Plane Position Sequence +OFCondition FGPlanePosPatient::read(DcmItem& item) +{ + clearData(); + + DcmItem* seqItem = NULL; + OFCondition result = getItemFromFGSequence(item, DCM_PlanePositionSequence, 0, seqItem); + if (result.bad()) + return result; + + DcmIODUtil::getAndCheckElementFromDataset(*seqItem, m_ImagePositionPatient, "3", "1C", "PlanePositionSequence"); + + return EC_Normal; +} + + +OFCondition FGPlanePosPatient::write(DcmItem& item) +{ + DcmItem* seqItem = NULL; + OFCondition result = createNewFGSequence(item, DCM_PlanePositionSequence, 0, seqItem); + if (result.bad()) + return result; + + // --- write plane position (patient) attributes --- + DcmIODUtil::copyElementToDataset(result, *seqItem, m_ImagePositionPatient, "3", "1C", "PlanePositionSequence"); + + return result; +} + + +int FGPlanePosPatient::compare(const FGBase& rhs) const +{ + int result = FGBase::compare(rhs); + if (result == 0) + { + const FGPlanePosPatient* myRhs = OFstatic_cast(const FGPlanePosPatient*, &rhs); + + // Compare all elements + result = m_ImagePositionPatient.compare(myRhs->m_ImagePositionPatient); + } + + return result; +} + + + +OFCondition FGPlanePosPatient::getImagePositionPatient(OFString& value, + const signed long pos = 0) + +{ + return DcmIODUtil::getStringValueFromElement(m_ImagePositionPatient, value, pos); +} + + +OFCondition FGPlanePosPatient::getImagePositionPatient(Float64& coordinateX, + Float64& coordinateY, + Float64& coordinateZ) +{ + OFCondition result = m_ImagePositionPatient.getFloat64(coordinateX, 0); + if (result.good()) result = m_ImagePositionPatient.getFloat64(coordinateY, 1); + if (result.good()) result = m_ImagePositionPatient.getFloat64(coordinateZ, 2); + return result; +} + + +OFCondition FGPlanePosPatient::setImagePositionPatient(const OFString& coordinateX, + const OFString& coordinateY, + const OFString& coordinateZ, + const OFBool checkValue) + +{ + + OFString str(coordinateX); + str += "\\"; + str += coordinateY; + str += "\\"; + str += coordinateZ; + OFCondition result = (checkValue) ? DcmDecimalString::checkStringValue(str, "3") : EC_Normal; + if (result.good()) + result = m_ImagePositionPatient.putOFStringArray(str); + return result; +} + + +FGPlanePosPatient::~FGPlanePosPatient() +{ + // nothing to do +} diff --git a/dcmfg/libsrc/fgplanposvol.cc b/dcmfg/libsrc/fgplanposvol.cc new file mode 100644 index 00000000..6ad95180 --- /dev/null +++ b/dcmfg/libsrc/fgplanposvol.cc @@ -0,0 +1,150 @@ +/* + * + * Copyright (C) 2015, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmfg + * + * Author: Michael Onken + * + * Purpose: Class for managing Plane Position (Volume) Functional Group + * + */ + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmdata/dcdeftag.h" +#include "dcmtk/dcmiod/iodutil.h" +#include "dcmtk/dcmfg/fgplanposvol.h" +#include "dcmtk/dcmfg/fgtypes.h" + +// Constructor +FGPlanePositionVolume::FGPlanePositionVolume() : + FGBase(DcmFGTypes::EFG_PLANEPOSITIONVOLUME), + m_ImagePositionVolume(DCM_ImagePositionVolume) +{ +} + + +FGPlanePositionVolume::~FGPlanePositionVolume() +{ + // nothing to do +} + + +FGBase* FGPlanePositionVolume::clone() const +{ + FGPlanePositionVolume* copy = new FGPlanePositionVolume(); + if (copy) + { + copy->m_ImagePositionVolume = this->m_ImagePositionVolume; + } + return copy; +} + + +void FGPlanePositionVolume::clearData() +{ + m_ImagePositionVolume.clear(); +} + + +OFCondition FGPlanePositionVolume::check() const +{ + // TODO + return EC_Normal; +} + + +// --- get() functionality --- + +OFCondition FGPlanePositionVolume::getImagePositionVolume(Float64& value, + const long unsigned int pos) +{ + return m_ImagePositionVolume.getFloat64(value, pos); +} + + +OFCondition FGPlanePositionVolume::getImagePositionVolume(Float64& valueX, + Float64& valueY, + Float64& valueZ) +{ + OFCondition result = m_ImagePositionVolume.getFloat64(valueX, 0); + if (result.good()) result = m_ImagePositionVolume.getFloat64(valueY, 1); + if (result.good()) result = m_ImagePositionVolume.getFloat64(valueZ, 2); + return result; +} + + +OFCondition FGPlanePositionVolume::setImagePositionVolume(const Float64& valueX, + const Float64& valueY, + const Float64& valueZ, + const OFBool checkValue) +{ + OFCondition result = m_ImagePositionVolume.putFloat64(valueX, 0); + if (result.good()) result = m_ImagePositionVolume.putFloat64(valueY, 1); + if (result.good()) result = m_ImagePositionVolume.putFloat64(valueZ, 2); + return result; +} + + +OFCondition FGPlanePositionVolume::setImagePositionVolume(const Float64& value, + const long unsigned int pos, + const OFBool checkValue) +{ + if (pos > 2) + return EC_ValueMultiplicityViolated; + + return m_ImagePositionVolume.putFloat64(value, pos); +} + + +/// Read Plane Position (Volume) Sequence from given item +OFCondition FGPlanePositionVolume::read(DcmItem& item) +{ + clearData(); + + DcmItem* seqItem = NULL; + OFCondition result = getItemFromFGSequence(item, DCM_PlanePositionVolumeSequence, 0, seqItem); + if (result.bad()) + return result; + + DcmIODUtil::getAndCheckElementFromDataset(*seqItem, m_ImagePositionVolume, "3", "1", "PlanePositionVolume"); + + return EC_Normal; + +} + +/// Writes single Plane Position (Volume) Sequence into given item +OFCondition FGPlanePositionVolume::write(DcmItem& item) +{ + DcmItem *seqItem = NULL; + OFCondition result = createNewFGSequence(item, DCM_PlanePositionVolumeSequence, 0, seqItem); + if (result.bad()) + return result; + + // --- write frame content macro attributes --- + DcmIODUtil::copyElementToDataset(result, *seqItem, m_ImagePositionVolume, "3", "1", "PlanePositionVolume"); + return result; +} + + +int FGPlanePositionVolume::compare(const FGBase& rhs) const +{ + int result = FGBase::compare(rhs); + if (result != 0) + return result; + + const FGPlanePositionVolume* myRhs = OFstatic_cast(const FGPlanePositionVolume*, &rhs); + + // Compare all elements + result = m_ImagePositionVolume.compare(myRhs->m_ImagePositionVolume); + return result; +} diff --git a/dcmfg/libsrc/fgrealworldvaluemapping.cc b/dcmfg/libsrc/fgrealworldvaluemapping.cc new file mode 100644 index 00000000..0a41a3ee --- /dev/null +++ b/dcmfg/libsrc/fgrealworldvaluemapping.cc @@ -0,0 +1,390 @@ +/* + * + * Copyright (C) 2015, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmfg + * + * Author: Michael Onken + * + * Purpose: Class for managing Real World Value Mapping Functional Group + * + */ + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmfg/fgrealworldvaluemapping.h" +#include "dcmtk/dcmdata/dcdeftag.h" +#include "dcmtk/dcmiod/iodutil.h" + +const OFString FGRealWorldValueMapping::RWVMItem::m_ModuleName = "RealWorldValueMappingItemMacro"; + +FGRealWorldValueMapping::FGRealWorldValueMapping() +: FGBase(DcmFGTypes::EFG_REALWORLDVALUEMAPPING), + m_Items() +{ +} + + +FGRealWorldValueMapping::~FGRealWorldValueMapping() +{ + clearData(); +} + + +FGBase* FGRealWorldValueMapping::clone() const +{ + FGRealWorldValueMapping* copy = new FGRealWorldValueMapping(); + if (copy) + { + for (OFVector::const_iterator it = m_Items.begin(); it < m_Items.end(); it++) + { + if (*it == NULL) return NULL; + FGRealWorldValueMapping::RWVMItem* item = (*it)->clone(); + if (item == NULL) return NULL; + copy->m_Items.push_back(item); + } + } + return copy; +} + + +void FGRealWorldValueMapping::clearData() +{ + DcmIODUtil::freeContainer(m_Items); +} + + +OFCondition FGRealWorldValueMapping::check() const +{ + // TODO + return EC_Normal; +} + + +int FGRealWorldValueMapping::compare(const FGBase& rhs) const +{ + int result = FGBase::compare(rhs); + if (result != 0) + return result; + + const FGRealWorldValueMapping* myRhs = OFstatic_cast(const FGRealWorldValueMapping*, &rhs); + + // Compare all items, start with VM + if (m_Items.size() < myRhs->m_Items.size()) + return 1; + else if (m_Items.size() > myRhs->m_Items.size()) + return -1; + + for (size_t n = 0; m_Items.size(); n++) + { + result = m_Items[n]->compare( *(myRhs->m_Items[n]) ); + if (result != 0) return result; + } + return result; +} + + +/// Read from Frame Content Sequence +OFCondition FGRealWorldValueMapping::read(DcmItem& item) +{ + clearData(); + + DcmIODUtil::readSubSequence(item, DCM_RealWorldValueMappingSequence, m_Items, "1-n", "1", "RealWorldValueMappingMacro"); + + return EC_Normal; +} + +OFCondition FGRealWorldValueMapping::write(DcmItem& item) +{ + // OFCondition result = createNewFGSequence(item, DCM_RealWorldValueMappingSequence, 0, seqItem); + OFCondition result; + DcmIODUtil::writeSubSequence(result, DCM_RealWorldValueMappingSequence, m_Items, item, "1-n", "1", "RealWorldValueMappingMacro"); + return result; +} + + +OFVector< FGRealWorldValueMapping::RWVMItem* >& FGRealWorldValueMapping::getRealWorldValueMapping() +{ + return m_Items; +} + + +// ----------------------------------------------------------- + + +FGRealWorldValueMapping::RWVMItem::RWVMItem(IODComponent* parent) +: IODComponent(parent), + m_MeasurementUnitsCode() +{ + resetRules(); +} + + +FGRealWorldValueMapping::RWVMItem::RWVMItem(OFshared_ptr< DcmItem > item, + OFshared_ptr< IODRules > rules, + IODComponent* parent) +: IODComponent(item, rules, parent), + m_MeasurementUnitsCode() +{ + resetRules(); +} + + +FGRealWorldValueMapping::RWVMItem* FGRealWorldValueMapping::RWVMItem::clone() +{ + FGRealWorldValueMapping::RWVMItem* mapping = new FGRealWorldValueMapping::RWVMItem(*this); + if (mapping) + { + // We do not have a copy constructor or clone function on IODComponent + OFString code, meaning, scheme, version; + m_MeasurementUnitsCode.getCodeValue(code); + m_MeasurementUnitsCode.getCodeMeaning(meaning); + m_MeasurementUnitsCode.getCodingSchemeDesignator(scheme); + m_MeasurementUnitsCode.getCodingSchemeVersion(version); + mapping->m_MeasurementUnitsCode.set(code, scheme, meaning, version, OFFalse /* do not check */); + } + return mapping; +} + + + +FGRealWorldValueMapping::RWVMItem::~RWVMItem() +{ + // nothing to do +} + + +OFString FGRealWorldValueMapping::RWVMItem::getName() const +{ + return m_ModuleName; +} + + +int FGRealWorldValueMapping::RWVMItem::compare(const IODComponent& rhs) const +{ + return IODComponent::compare(rhs); +} + +void FGRealWorldValueMapping::RWVMItem::resetRules() +{ + // parameters are tag, VM, type. Overwrite old rules if any. + m_Rules->addRule(new IODRule(DCM_RealWorldValueFirstValueMapped, "1","1",m_ModuleName, DcmIODTypes::IE_INSTANCE), OFTrue); + m_Rules->addRule(new IODRule(DCM_RealWorldValueLastValueMapped, "1","1", m_ModuleName, DcmIODTypes::IE_INSTANCE), OFTrue); + m_Rules->addRule(new IODRule(DCM_RealWorldValueIntercept, "1","1C", m_ModuleName, DcmIODTypes::IE_INSTANCE), OFTrue); + m_Rules->addRule(new IODRule(DCM_RealWorldValueSlope, "1","1C", m_ModuleName, DcmIODTypes::IE_INSTANCE), OFTrue); + m_Rules->addRule(new IODRule(DCM_RealWorldValueLUTData, "1-n","1C", m_ModuleName, DcmIODTypes::IE_INSTANCE), OFTrue); + m_Rules->addRule(new IODRule(DCM_LUTExplanation, "1","1", m_ModuleName, DcmIODTypes::IE_INSTANCE), OFTrue); + m_Rules->addRule(new IODRule(DCM_LUTLabel, "1","1", m_ModuleName, DcmIODTypes::IE_INSTANCE), OFTrue); + m_Rules->addRule(new IODRule(DCM_MeasurementUnitsCodeSequence, "1","1", m_ModuleName, DcmIODTypes::IE_INSTANCE), OFTrue); + //m_Rules->addRule(new IODRule(DCM_QuantityDefinitionSequence, "1","3", m_ModuleName, DcmIODTypes::IE_INSTANCE), OFTrue); +} + +OFCondition FGRealWorldValueMapping::RWVMItem::read(DcmItem& source, + const OFBool clearOldData) +{ + DcmIODUtil::readSingleItem(source, DCM_MeasurementUnitsCodeSequence, m_MeasurementUnitsCode, "1", m_ModuleName); + return IODComponent::read(source, clearOldData); +} + + +OFCondition FGRealWorldValueMapping::RWVMItem::write(DcmItem& destination) +{ + OFCondition result; + DcmIODUtil::writeSingleItem(result, DCM_MeasurementUnitsCodeSequence, m_MeasurementUnitsCode, *m_Item, "1", m_ModuleName); + if (result.good()) result = IODComponent::write(destination); + return result; +} + + +OFCondition FGRealWorldValueMapping::RWVMItem::getRealWorldValueFirstValueMapped(Sint32& value, + const unsigned long pos) const +{ + return getUSorSS(*m_Item, DCM_RealWorldValueFirstValueMapped, pos, value); +} + + +OFCondition FGRealWorldValueMapping::RWVMItem::getRealWorldValueLastValueMapped(Sint32& value, + const unsigned long pos) const +{ + return getUSorSS(*m_Item, DCM_RealWorldValueLastValueMapped, pos, value); +} + + +OFCondition FGRealWorldValueMapping::RWVMItem::getRealWorldValueLUTData(OFVector< Float64 >& values) const +{ + DcmElement* elem = NULL; + OFCondition result = m_Item->findAndGetElement(DCM_RealWorldValueLUTData, elem); + if (result.good()) + { + size_t numValues = elem->getVM(); + for (size_t n = 0; n < numValues; n++) + { + Float64 value; + result = elem->getFloat64(value, n); + if (result.good()) values.push_back(value); + } + } + return result; +} + + +OFCondition FGRealWorldValueMapping::RWVMItem::getRealWorldValueLUTData(Float64& value, + const unsigned long pos) const +{ + return m_Item->findAndGetFloat64(DCM_RealWorldValueLUTData, value, pos); +} + + +OFCondition FGRealWorldValueMapping::RWVMItem::getLUTExplanation(OFString& value, + const signed long pos) const +{ + return DcmIODUtil::getStringValueFromItem(DCM_LUTExplanation, *m_Item, value, pos); +} + + +OFCondition FGRealWorldValueMapping::RWVMItem::getLUTLabel(OFString& value, + const signed long pos) const +{ + return DcmIODUtil::getStringValueFromItem(DCM_LUTLabel, *m_Item, value, pos); +} + + +CodeSequenceMacro& FGRealWorldValueMapping::RWVMItem::getMeasurementUnitsCode() +{ + return m_MeasurementUnitsCode; +} + + +OFCondition FGRealWorldValueMapping::RWVMItem::setRealWorldValueFirstValueMappedUnsigned(const Uint16& value, + const OFBool checkValue) +{ + DcmUnsignedShort* us = new DcmUnsignedShort(DCM_RealWorldValueFirstValueMapped); + OFCondition result = us->putUint16(value); + if (result.good()) result = m_Item->insert(us, OFTrue /* replace old */); + if (result.bad()) delete us; + return result; +} + + +OFCondition FGRealWorldValueMapping::RWVMItem::setRealWorldValueFirstValueMappeSigned(const Sint16& value, + const OFBool checkValue) +{ + DcmSignedShort* ss = new DcmSignedShort(DCM_RealWorldValueFirstValueMapped); + OFCondition result = ss->putSint16(value); + if (result.good()) result = m_Item->insert(ss, OFTrue /* replace old */); + if (result.bad()) delete ss; + return result; +} + +OFCondition FGRealWorldValueMapping::RWVMItem::setRealWorldValueLastValueMappedSigned(const Sint16& value, + const OFBool checkValue) +{ + DcmSignedShort* ss = new DcmSignedShort(DCM_RealWorldValueLastValueMapped); + OFCondition result = ss->putSint16(value); + if (result.good()) result = m_Item->insert(ss, OFTrue /* replace old */); + if (result.bad()) delete ss; + return result; + +} + + +OFCondition FGRealWorldValueMapping::RWVMItem::setRealWorldValueLastValueMappedUnsigned(const Uint16& value, + const OFBool checkValue) +{ + DcmUnsignedShort* us = new DcmUnsignedShort(DCM_RealWorldValueLastValueMapped); + OFCondition result = us->putUint16(value); + if (result.good()) result = m_Item->insert(us, OFTrue /* replace old */); + if (result.bad()) delete us; + return result; +} + + +OFCondition FGRealWorldValueMapping::RWVMItem::setRealWorldValueIntercept(const Float64& value, + const OFBool checkValue) +{ + return m_Item->putAndInsertFloat64(DCM_RealWorldValueIntercept, value); +} + + +OFCondition FGRealWorldValueMapping::RWVMItem::setRealWorldValueSlope(const Float64& value, + const OFBool checkValue) +{ + return m_Item->putAndInsertFloat64(DCM_RealWorldValueSlope, value); +} + + +OFCondition FGRealWorldValueMapping::RWVMItem::setRealWorldValueLUTData(const OFVector< Float64 >& value, + const OFBool checkValue) +{ + DcmElement *elem = NULL; + OFCondition result = m_Item->findAndGetElement(DCM_RealWorldValueLUTData, elem); + if (result.good()) + { + size_t count = value.size(); + for (size_t n = 0; n < count; n++) + { + if (result.good()) result = elem->putFloat64(value[n], n); + } + } + return result; +} + + +OFCondition FGRealWorldValueMapping::RWVMItem::setLUTExplanation(const OFString& value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmLongString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_LUTExplanation, value); + return result; +} + + +OFCondition FGRealWorldValueMapping::RWVMItem::setLUTLabel(const OFString& value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmShortString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_LUTLabel, value); + return result; +} + + +OFCondition FGRealWorldValueMapping::RWVMItem::getUSorSS(DcmItem& item, + const DcmTagKey& key, + const unsigned long pos, + Sint32& value) +{ + DcmElement *elem = NULL; + OFCondition result = item.findAndGetElement(key, elem); + if (result.good() && elem) + { + DcmEVR evr = elem->getVR(); + if (evr == EVR_US) + { + Uint16 num; + result = elem->getUint16(num, pos); + if (result.good()) value = num; + } + else if (evr == EVR_SS) + { + Sint16 num; + result = elem->getSint16(num, pos); + if (result.good()) value = num; + } + else + { + DCMFG_ERROR("Illegal VR " << DcmVR(evr).getVRName() << " for tag " << DcmTag(key).getTagName()); + result = EC_InvalidVR; + } + } + return result; +} diff --git a/dcmfg/libsrc/fgseg.cc b/dcmfg/libsrc/fgseg.cc new file mode 100644 index 00000000..4e28d64b --- /dev/null +++ b/dcmfg/libsrc/fgseg.cc @@ -0,0 +1,138 @@ +/* + * + * Copyright (C) 2015, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmfg + * + * Author: Michael Onken + * + * Purpose: Class for managing Segmentation Functional Group + * + */ + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmfg/fgseg.h" +#include "dcmtk/dcmdata/dcdeftag.h" +#include "dcmtk/dcmiod/iodutil.h" // for static element helpers + + +FGSegmentation::FGSegmentation() : + FGBase(DcmFGTypes::EFG_SEGMENTATION), + m_ReferencedSegmentNumber(DCM_ReferencedSegmentNumber) +{ +} + + +FGSegmentation::~FGSegmentation() +{ + clearData(); +} + +FGBase* FGSegmentation::clone() const +{ + FGSegmentation* copy = new FGSegmentation(); + if (copy) + { + copy->m_ReferencedSegmentNumber = this->m_ReferencedSegmentNumber; + } + return copy; +} + + + +void FGSegmentation::clearData() +{ + m_ReferencedSegmentNumber.clear(); +} + + +OFCondition FGSegmentation::check() const +{ + // TODO + return EC_Normal; +} + + +OFCondition FGSegmentation::getReferencedSegmentNumber(Uint16& value, + const unsigned long pos) +{ + return m_ReferencedSegmentNumber.getUint16(value, pos); +} + + +OFCondition FGSegmentation::setReferencedSegmentNumber(const Uint16& segmentNumber) +{ + return m_ReferencedSegmentNumber.putUint16(segmentNumber); +} + + +OFCondition FGSegmentation::write(DcmItem& item) +{ + OFCondition result = EC_Normal; + + /* Clear old data */ + item.findAndDeleteElement(DCM_SegmentIdentificationSequence); + + /* write and get Segment Identification Sequence with one item */ + DcmItem *newItem = NULL; + result = item.findOrCreateSequenceItem(DCM_SegmentIdentificationSequence, newItem, 0); + if ( result.bad() ) + { + DCMFG_ERROR("Could not create Segment Identification Sequence with one item (internal error): " << result.text()); + return FG_EC_CouldNotWriteFG; + } + DcmIODUtil::copyElementToDataset(result, *newItem, m_ReferencedSegmentNumber, "1-n", "1", "SegmentationMacro"); + + /* Return result */ + return result; +} + + +OFCondition FGSegmentation::read(DcmItem& item) +{ + OFCondition result = EC_Normal; + + /* re-initialize object */ + clearData(); + + DcmSequenceOfItems *segmentIdentificationSequence = NULL; + result = item.findAndGetSequence(DCM_SegmentIdentificationSequence, segmentIdentificationSequence); + + if ( result.good() ) + { + /* Referenced Segment Number */ + // check whether structure is ok (single item in sequence) and report problems + DcmItem *idItem= NULL; + DcmIODUtil::getAndCheckSingleItem(*segmentIdentificationSequence, idItem, DCM_SegmentIdentificationSequence); + if (idItem) + { + // so far we ignore the result when reading (but report problems to the logger) + DcmIODUtil::getAndCheckElementFromDataset(*idItem, m_ReferencedSegmentNumber, "1-n" /* vm */, "1" /* type */, "SegmentationMacro"); + } + } + return result; +} + + +int FGSegmentation::compare(const FGBase& rhs) const +{ + int result = FGBase::compare(rhs); + if (result == 0) + { + const FGSegmentation* myRhs = OFstatic_cast(const FGSegmentation*, &rhs); + + // Compare all elements + result = m_ReferencedSegmentNumber.compare(myRhs->m_ReferencedSegmentNumber); + } + + return result; +} diff --git a/dcmfg/libsrc/fgtypes.cc b/dcmfg/libsrc/fgtypes.cc new file mode 100644 index 00000000..1a6dce85 --- /dev/null +++ b/dcmfg/libsrc/fgtypes.cc @@ -0,0 +1,183 @@ +/* + * + * Copyright (C) 2015, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmfg + * + * Author: Michael Onken + * + * Purpose: Class for managing common functional group types + * + */ + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmfg/fgtypes.h" +#include "dcmtk/dcmdata/dcerror.h" +#include "dcmtk/dcmfg/fgdefine.h" +#include "dcmtk/dcmfg/fgbase.h" +#include "dcmtk/dcmiod/iodcommn.h" + +OFLogger DCM_dcmfgLogger = OFLog::getLogger("dcmtk.dcmfg"); + +/*---------------------------------* + * constant definitions + *---------------------------------*/ + +// conditions +makeOFConditionConst(FG_EC_DoubledFG, OFM_dcmfg, 1, OF_error, "Doubled Functional Group"); +makeOFConditionConst(FG_EC_NoSuchGroup, OFM_dcmfg, 2, OF_error, "No such Functional Group"); +makeOFConditionConst(FG_EC_NotEnoughItems, OFM_dcmfg, 3, OF_error, "Not enough Items in Functional Group"); +makeOFConditionConst(FG_EC_TooManyItems, OFM_dcmfg, 4, OF_error, "Too many Items in Functional Group"); +makeOFConditionConst(FG_EC_InvalidData, OFM_dcmfg, 5, OF_error, "Invalid data in Functional Group"); +makeOFConditionConst(FG_EC_CouldNotWriteFG, OFM_dcmfg, 6, OF_error, "Could not write Functional Group"); +makeOFConditionConst(FG_EC_CouldNotInsertFG, OFM_dcmfg, 7, OF_error, "Could not insert Functional Group"); +makeOFConditionConst(FG_EC_NoSharedFG, OFM_dcmfg, 8, OF_error, "No shared Functional Groups found"); +makeOFConditionConst(FG_EC_NoPerFrameFG, OFM_dcmfg, 9, OF_error, "No Per-Frame Functional Groups found"); +makeOFConditionConst(FG_EC_CouldNotCreateFG, OFM_dcmfg, 10, OF_error, "Could not create Functional Group"); +makeOFConditionConst(FG_EC_CouldNotReadSourceImage, OFM_dcmfg, 11, OF_error, "Could not read source image"); +makeOFConditionConst(FG_EC_CouldNotAddFG, OFM_dcmfg, 12, OF_error, "Could add Functional Group"); +makeOFConditionConst(FG_EC_NotEnoughFrames, OFM_dcmfg, 13, OF_error, "Not enough frames"); +makeOFConditionConst(FG_EC_NoStacksFound, OFM_dcmfg, 14, OF_error, "No stacks found"); + + +OFString DcmFGTypes::FGType2OFString(const DcmFGTypes::E_FGType fgType) +{ + switch (fgType) + { + /// Undefined functional group + case EFG_UNDEFINED: return "Undefined Functional Group Macro"; break; + /// Unknown functional group + case EFG_UNKNOWN: return "Unknown Functional Group Macro"; break; + /// Pixel Measures + case EFG_PIXELMEASURES: return "Pixel Measures Functional Group Macro"; break; + /// Frame Content + case EFG_FRAMECONTENT: return "Frame Content Functional Group Macro"; break; + /// Plane Position (Patient) + case EFG_PLANEPOSPATIENT: return "Plane Position (Patient) Functional Group Macro"; break; + /// Plane Orientation (Patient) + case EFG_PLANEORIENTPATIENT: return "Plane Orientation (Patient) Functional Group Macro"; break; + /// Derivation Image + case EFG_DERIVATIONIMAGE: return "Deriviation Image Functional Group Macro"; break; + /// Cardiac Synchronization + case EFG_CARDIACSYNC: return "Cardiac Synchronization Functional Group Macro"; break; + /// Frame Anantomy + case EFG_FRAMEANATOMY: return "Frame Anatomy Functional Group Macro"; break; + /// Pixel Value Transformation or Identity Pixel Value Transformation + case EFG_PIXELVALUETRANSMETA: return "Pixel Value Transformation / Identity Pixel Value Transformation Functional Group Macro"; break; + /// Frame VOI LUT or Frame VOI LUT with LUT + case EFG_FRAMEVOILUTMETA: return "Frame VOI LUT / Frame VOI LUT with LUT Macro"; break;; + /// Real World Value Mapping + case EFG_REALWORLDVALUEMAPPING: return "Real World Value Mapping Functional Group Macro"; break; + /// Contrast/Bolus Usage + case EFG_CONTRASTBOLUSUSAGE: return "Contrast/Bolus Usage Group Macro"; break; + /// Pixel Intensity Relationship LUT + case EFG_PIXELINTENSITYRELLUT: return "Pixel Intensity Relation LUT Functional Group Macro"; break; + /// Frame Pixel Shift + case EFG_FRAMEPIXELSHIFT: return "Frame Pixel Shift Functional Group Macro"; break; + /// Patient Orientation in Frame + case EFG_PATIENTORIENTINFRAME: return "Patient Orientation in Frame Functional Group Macro"; break; + /// Frame Display Shutter + case EFG_FRAMEDISPLAYSHUTTER: return "Frame Display Shutter Functional Group Macro"; break; + /// Respiratory Synchronization + case EFG_RESPIRATORYSYNC: return "Respiratory Synchronization Functional Group Macro"; break; + /// Irradiation Event Identification + case EFG_IRRADIATIONEVENTIDENT: return "Irradiation Event Identification Functional Group Macro"; break; + /// Radiopharmaceutical Usage + case EFG_RADIOPHARAMAUSAGE: return "Radiopharmaceutical Usage Functional Group Macro"; break; + /// Patient Physiological State + case EFG_PATIENTPHYSIOSTATE: return "Patient Physiological State Functional Group Macro"; break; + /// Plane Position (Volume) + case EFG_PLANEPOSITIONVOLUME: return "Plane Position (Volume) Functional Group Macro"; break; + /// Plane Orientation (Volume) + case EFG_PLANEORIENTVOLUME: return "Plane Orientation (Volume) Functional Group Macro"; break; + /// Temporal Position Macro + case EFG_TEMPORALPOSITION: return "Temporal Position Functional Group Macro"; break; + /// Image Data Type + case EFG_IMAGEDATATYPE: return "Image Data Type Functional Group Macro"; break; + /// Unassigned Shared Converted Attributes Macro + case EFG_UNASSIGNEDSHAREDCONVERTEDATTRIBUTES: return "Unassigned Shared Converted Attributes Macro"; break; + /// Segmentation Macro + case EFG_SEGMENTATION: return "Segmentation Functional Group Macro"; break; + /// US Image Description Functional Group Macro + case EFG_USIMAGEDESCRIPTION: return "US Image Description Functional Group Macro"; break; + } + return "Unknown Functional Group Macro (internal error)"; +} + + +DcmFGTypes::E_FGType DcmFGTypes::tagKey2FGType(const DcmTagKey& key) +{ + // TODO: Use neat value to enum trick from Alexandrescu in order to have switch statement instead? + if (key == DCM_PixelMeasuresSequence) + return EFG_PIXELMEASURES; + else if (key == DCM_FrameContentSequence) + return EFG_FRAMECONTENT; + else if (key == DCM_PlanePositionSequence) + return EFG_PLANEPOSPATIENT; + else if (key == DCM_PlaneOrientationSequence) + return EFG_PLANEORIENTPATIENT; + else if (key == DCM_DerivationImageSequence) + return EFG_DERIVATIONIMAGE; + else if (key == DCM_CardiacSynchronizationSequence) + return EFG_CARDIACSYNC; + else if (key == DCM_FrameAnatomySequence) + return EFG_FRAMEANATOMY; + else if (key == DCM_PixelValueTransformationSequence) + return EFG_PIXELVALUETRANSMETA; + else if (key == DCM_FrameVOILUTSequence) + return EFG_FRAMEVOILUTMETA; + else if (key == DCM_RealWorldValueMappingSequence) + return EFG_REALWORLDVALUEMAPPING; + else if (key == DCM_ContrastBolusUsageSequence) + return EFG_CONTRASTBOLUSUSAGE; + else if (key == DCM_PixelIntensityRelationshipLUTSequence) + return EFG_PIXELINTENSITYRELLUT; + else if (key == DCM_FramePixelShiftSequence) + return EFG_FRAMEPIXELSHIFT; + else if (key == DCM_PatientOrientationInFrameSequence) + return EFG_PATIENTORIENTINFRAME; + else if (key == DCM_FrameDisplayShutterSequence) + return EFG_FRAMEDISPLAYSHUTTER; + else if (key == DCM_RespiratorySynchronizationSequence) + return EFG_RESPIRATORYSYNC; + else if (key == DCM_IrradiationEventIdentificationSequence) + return EFG_IRRADIATIONEVENTIDENT; + else if (key == DCM_RadiopharmaceuticalUsageSequence) + return EFG_RADIOPHARAMAUSAGE; + else if (key == DCM_PatientPhysiologicalStateSequence) + return EFG_PATIENTPHYSIOSTATE; + else if (key == DCM_PlanePositionVolumeSequence) + return EFG_PLANEPOSITIONVOLUME; + else if (key == DCM_PlaneOrientationVolumeSequence) + return EFG_PLANEORIENTVOLUME; + else if (key == DCM_TemporalPositionSequence) + return EFG_TEMPORALPOSITION; + else if (key == DCM_ImageDataTypeSequence) + return EFG_IMAGEDATATYPE; + else if (key == DCM_UnassignedSharedConvertedAttributesSequence) + return EFG_UNASSIGNEDSHAREDCONVERTEDATTRIBUTES; + else if (key == DCM_SegmentIdentificationSequence) + return EFG_SEGMENTATION; + else if (key == DCM_USImageDescriptionSequence) + return EFG_USIMAGEDESCRIPTION; + else + return EFG_UNKNOWN; +} + + +OFString DcmFGTypes::tagKey2FGString(const DcmTagKey& key) +{ + E_FGType fgtype = tagKey2FGType(key); + return FGType2OFString(fgtype); +} + + diff --git a/dcmfg/libsrc/fgusimagedescription.cc b/dcmfg/libsrc/fgusimagedescription.cc new file mode 100644 index 00000000..5685e7f2 --- /dev/null +++ b/dcmfg/libsrc/fgusimagedescription.cc @@ -0,0 +1,200 @@ +/* + * + * Copyright (C) 2015, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmfg + * + * Author: Michael Onken + * + * Purpose: Class for managing US Image Description Functional Group + * + */ + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmdata/dcdeftag.h" +#include "dcmtk/dcmiod/iodutil.h" +#include "dcmtk/dcmiod/iodtypes.h" +#include "dcmtk/dcmfg/fgusimagedescription.h" + +// Constructor +FGUSImageDescription::FGUSImageDescription() : + FGBase(DcmFGTypes::EFG_USIMAGEDESCRIPTION), + m_FrameType(DCM_FrameType), + m_VolumetricProperties(DCM_VolumetricProperties), + m_VolumeBasedCalculationTechnique(DCM_VolumeBasedCalculationTechnique) +{ +} + + +FGUSImageDescription::~FGUSImageDescription() +{ + // nothing to do +} + + +FGBase* FGUSImageDescription::clone() const +{ + FGUSImageDescription* copy = new FGUSImageDescription(); + if (copy) + { + copy->m_FrameType = this->m_FrameType; + copy->m_VolumetricProperties = this->m_VolumetricProperties; + copy->m_VolumeBasedCalculationTechnique = this->m_VolumeBasedCalculationTechnique; + } + return copy; +} + + +void FGUSImageDescription::clearData() +{ + m_FrameType.clear(); + m_VolumetricProperties.clear(); + m_VolumeBasedCalculationTechnique.clear(); +} + + +OFCondition FGUSImageDescription::check() const +{ + // TODO + return EC_Normal; +} + + +// --- get() functionality --- + +OFCondition FGUSImageDescription::getFrameType(OFString& value, + const long signed int pos) +{ + return DcmIODUtil::getStringValueFromElement(m_FrameType, value, pos); +} + + +OFCondition FGUSImageDescription::getVolumetricProperties(OFString& value, + const long signed int pos) +{ + return DcmIODUtil::getStringValueFromElement(m_VolumetricProperties, value, pos); +} + + +OFCondition FGUSImageDescription::getVolumeBasedCalculationTechnique(OFString& value, + const long signed int pos) +{ + return DcmIODUtil::getStringValueFromElement(m_VolumeBasedCalculationTechnique, value, pos); +} + + +// --- set() functionality --- + + +OFCondition FGUSImageDescription::setFrameType(const DcmFGTypes::E_FGUSFrameType pixelDataChar, + const OFString& imageFlavor, + const OFString& derivedPixelContrast, + const OFBool checkValue) +{ + // Build a string of VM 4 with first two values at least set + OFString value; + switch (pixelDataChar) + { + case(DcmFGTypes::EFGFT_ORIGINAL): value = "ORIGINAL\\PRIMARY\\"; break; + case(DcmFGTypes::EFGFT_DERIVED) : value = "DERIVED\\PRIMARY\\"; break; + default: return IOD_EC_InvalidElementValue; + } + value += imageFlavor; + value += "\\"; + value += derivedPixelContrast; + + return m_FrameType.putOFStringArray(value); +} + + +OFCondition FGUSImageDescription::setVolumetricProperties(const OFString& value, + const OFBool checkValue) +{ + OFCondition result; + if (checkValue) + { + if ( (value != "VOLUME") && (value != "SAMPLED") && (value != "DISTORTED") && (value != "MIXED") ) + { + result = IOD_EC_InvalidElementValue; + } + else + result = DcmCodeString::checkStringValue(value, "1"); + } + if (result.good()) + { + result = m_VolumetricProperties.putOFStringArray(value); + } + return result; +} + + +OFCondition FGUSImageDescription::setVolumeBasedCalculationTechnique(const OFString& value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmCodeString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_VolumeBasedCalculationTechnique.putOFStringArray(value); + return result; +} + + +/// Read Frame Content Sequence from given item +OFCondition FGUSImageDescription::read(DcmItem& item) +{ + clearData(); + + DcmItem* seqItem = NULL; + OFCondition result = getItemFromFGSequence(item, DCM_USImageDescriptionSequence, 0, seqItem); + if (result.bad()) + return result; + + DcmIODUtil::getAndCheckElementFromDataset(*seqItem, m_FrameType, "4", "1", "USImageDescriptionMacro"); + DcmIODUtil::getAndCheckElementFromDataset(*seqItem, m_VolumetricProperties, "1", "1", "USImageDescriptionMacro"); + DcmIODUtil::getAndCheckElementFromDataset(*seqItem, m_VolumeBasedCalculationTechnique, "1", "1", "USImageDescriptionMacro"); + return result;; +} + + +/// Writes single Frame Content Sequence into given item +OFCondition FGUSImageDescription::write(DcmItem& item) +{ + DcmItem *seqItem = NULL; + OFCondition result = createNewFGSequence(item, DCM_USImageDescriptionSequence, 0, seqItem); + if (result.bad()) + return result; + + // --- write frame content macro attributes --- + DcmIODUtil::copyElementToDataset(result, *seqItem, m_FrameType, "4", "1", "USImageDescriptionMacro"); + DcmIODUtil::copyElementToDataset(result, *seqItem, m_VolumetricProperties, "1", "1", "USImageDescriptionMacro"); + DcmIODUtil::copyElementToDataset(result, *seqItem, m_VolumeBasedCalculationTechnique, "1", "1", "USImageDescriptionMacro"); + + return result; +} + + +int FGUSImageDescription::compare(const FGBase& rhs) const +{ + int result = FGBase::compare(rhs); + if (result != 0) + return result; + + const FGUSImageDescription* myRhs = OFstatic_cast(const FGUSImageDescription*, &rhs); + + // Compare all elements + result = m_FrameType.compare(myRhs->m_FrameType); + if (result == 0) + result = m_VolumetricProperties.compare(myRhs->m_VolumetricProperties); + if (result == 0) + result = m_VolumeBasedCalculationTechnique.compare(myRhs->m_VolumeBasedCalculationTechnique); + + return result; +} diff --git a/dcmfg/libsrc/stack.cc b/dcmfg/libsrc/stack.cc new file mode 100644 index 00000000..d59f1f4d --- /dev/null +++ b/dcmfg/libsrc/stack.cc @@ -0,0 +1,107 @@ +/* + * + * Copyright (C) 2015, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmfg + * + * Author: Michael Onken + * + * Purpose: Class representing a stack in the context of Enhanced multiframe + * + */ + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmfg/stack.h" + + +FGStack::FGStack(const OFString& stackID, + const OFMap< Uint32, Uint32 > frameNumbers) +: m_StackID(stackID), + m_FrameNumbers(frameNumbers) +{ + +} + +FGStack::FGStack(const OFString& stackID) +: m_StackID(stackID), + m_FrameNumbers() +{ + +} + +OFBool FGStack::addFrame(const Uint32 frameNumber, + const Uint32 inStackPos) +{ + m_FrameNumbers.insert(OFMake_pair(frameNumber, inStackPos)); + return OFTrue; +} + + +FGStack::~FGStack() +{ + +} + + +FGStack::const_iterator FGStack::begin() const +{ + return m_FrameNumbers.begin(); +} + + +FGStack::iterator FGStack::begin() +{ + return m_FrameNumbers.begin(); +} + + +FGStack::const_iterator FGStack::end() const +{ + return m_FrameNumbers.end(); +} + + +FGStack::iterator FGStack::end() +{ + return m_FrameNumbers.end(); +} + + +OFString FGStack::getStackID() const +{ + return m_StackID; +} + + +Uint32 FGStack::getInStackPos(const Uint32 frameNumber) const +{ + FGStack::const_iterator it = m_FrameNumbers.find(frameNumber); + if (it == m_FrameNumbers.end()) + return 0; + else + return (*it).second; +} + + +void FGStack::getFramesAtStackPos(const Uint32 inStackPos, + OFVector& resultFrameNumbers) +{ + FGStack::iterator it = m_FrameNumbers.begin(); + while (it != m_FrameNumbers.end()) + { + if ((*it).second == inStackPos) + { + resultFrameNumbers.push_back( (*it).second); + } + it++; + } +} diff --git a/dcmfg/libsrc/stackinterface.cc b/dcmfg/libsrc/stackinterface.cc new file mode 100644 index 00000000..b6d086e7 --- /dev/null +++ b/dcmfg/libsrc/stackinterface.cc @@ -0,0 +1,274 @@ +/* + * + * Copyright (C) 2015, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmfg + * + * Author: Michael Onken + * + * Purpose: Class for reading, accessing and writing stacks + * + */ + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmiod/iodutil.h" +#include "dcmtk/dcmfg/stackinterface.h" +#include "dcmtk/dcmfg/fgfracon.h" + + +FGStackInterface::FGStackInterface() +: m_Stacks() +{ +} + + +FGStackInterface::~FGStackInterface() +{ + while (m_Stacks.size() != 0) + { + OFMap::iterator it = m_Stacks.begin(); + FGStack *toDelete = (*it).second; + m_Stacks.erase(it); + delete toDelete; + } +} + + +void FGStackInterface::clear() +{ + size_t stackSize = m_Stacks.size(); + OFMap::iterator it; + for (size_t count = 0; count < stackSize; count++) + { + it = m_Stacks.begin(); + m_Stacks.erase(it); + } +} + + +OFCondition FGStackInterface::read(FGInterface& fgSource) +{ + clear(); + size_t numFrames = fgSource.getNumberOfFrames(); + for (size_t count = 0; count < numFrames; count++) + { + // Get frame content FG if existing + FGFrameContent* fracon = OFstatic_cast(FGFrameContent*, fgSource.get(count, DcmFGTypes::EFG_FRAMECONTENT)); + if (fracon != NULL) + { + OFString stackID; + Uint32 inStackPos; + // Check whether stack ID is actually present and get value + if ( (fracon->getStackID(stackID).good()) && (fracon->getInStackPositionNumber(inStackPos).good()) ) + { + // Check whether this is a stack ID we do not know yet + OFMap::iterator it = m_Stacks.begin(); + while (it != m_Stacks.end()) + { + // If this is an old stack, add frame to it + if ( (*it).second->getStackID() == stackID) + { + // Add frame to stack if it is not in yet + if ( (*it).second->getInStackPos(count) == 0) + { + (*it).second->addFrame(count, inStackPos); + } + } + it++; + } + // If this is a new stack, add it to the list + if (it == m_Stacks.end()) + { + FGStack *stack = new FGStack(stackID); + if (stack == NULL) + { + return EC_MemoryExhausted; + } + stack->addFrame(count, inStackPos); + if ( !m_Stacks.insert(OFMake_pair(stack->getStackID(), stack)).second ) + { + delete stack; + DCMFG_ERROR("Could not add stack to internal list (internal error, ignored)"); + } + } + } + else + { + DCMFG_WARN("Rading stacks but Frame " << count << " does not provide Stack ID or In-Stack Position"); + } + } + else + { + DCMFG_WARN("Rading stacks but Frame " << count << " does not provide a Frame Content functional group"); + } + } + + if (m_Stacks.size() == 0) + { + return FG_EC_NoStacksFound; + } + + return EC_Normal; +} + + +OFCondition FGStackInterface::write(FGInterface& fgDestination) +{ + size_t numFrames = fgDestination.getNumberOfFrames(); + if (numFrames == 0) + { + return FG_EC_NotEnoughFrames; + } + + // Check whether maximum in-stack position does not exceed number of frames in image + if (!checkConsistency(&fgDestination)) + { + return FG_EC_InvalidData; + } + + // Walk through stacks, and for each, add/overwrite stack information to + // the respective Frame Content functional groups + OFCondition result; + OFMap::iterator stack = m_Stacks.begin(); + while (result.good() && (stack != m_Stacks.end()) ) + { + OFString stackID = (*stack).second->getStackID(); + // Walk over all referenced frames and add Stack information + OFMap::const_iterator stackEntry = (*stack).second->begin(); + while (stackEntry != (*stack).second->end()) + { + Uint32 frameNo = (*stackEntry).first; + Uint32 inStackPos = (*stackEntry).second; + FGFrameContent* fg = ensureFrameContentFG(frameNo, fgDestination); + // Create functional group if not already existing + if (fg == NULL) + { + result = FG_EC_CouldNotAddFG; + } + if (result.good()) result = fg->setStackID(stackID); + if (result.good()) result = fg->setInStackPositionNumber(inStackPos+1 /* vector counts from 0, position in DICOM starts with 1 */); + if (result.bad()) + { + DCMFG_ERROR("Could not create or add stack with ID " << stackID << " to frame " << frameNo << ": " << result.text()); + } + stackEntry++; + } + stack++; + } + return result; +} + + +FGFrameContent* FGStackInterface::ensureFrameContentFG(const Uint32 frameNo, + FGInterface& fg) +{ + FGFrameContent* content = OFstatic_cast(FGFrameContent*, fg.get(frameNo, DcmFGTypes::EFG_FRAMECONTENT)); + if (!content) + { + FGFrameContent newContent; + OFCondition result = fg.addPerFrame(frameNo, newContent); + if (result.bad()) + { + DCMFG_ERROR("Could not add Frame Content FG for frame " << frameNo); + } + else + { + content = OFstatic_cast(FGFrameContent*, fg.get(frameNo, DcmFGTypes::EFG_FRAMECONTENT)); + } + } + return content; +} + + +OFBool FGStackInterface::addStack(FGStack* stack) +{ + if (stack == NULL) + return OFFalse; + + if (stack->getStackID().empty()) + { + DCMFG_ERROR("Stack ID cannot be empty"); + return OFFalse; + } + + return m_Stacks.insert(OFMake_pair(stack->getStackID(), stack)).second; +} + + +size_t FGStackInterface::numStacks() const +{ + return m_Stacks.size(); +} + + +OFBool FGStackInterface::checkConsistency(FGInterface* fgContext) +{ + size_t errors = 0; + size_t count = 0; + // Run over stacks and check whether each has a Stack ID. + // Also check whether stacks can be valid in the context + // of the given functional groups (e.g. frame range ok) + OFMap::iterator it = m_Stacks.begin(); + while (it != m_Stacks.end()) + { + if ( (*it).second->getStackID().empty()) + { + errors++; + DCMFG_ERROR("Stack ID for stack #" << count << " is empty"); + } + if (fgContext) + { + errors += checkContext((*it).second, fgContext); + } + it++; + count++; + } + return (errors == 0); +} + + +size_t FGStackInterface::checkContext(FGStack* stack, + FGInterface* context) +{ + // Must be non-empty + if ( !stack || !context) + return 1; + + // Check whether we have any frames + size_t numFrames = context->getNumberOfFrames(); + if (numFrames == 0) + { + DCMFG_ERROR("Cannot have stacks without frames"); + return 1; + } + + // Walk over frames in stack and check that frame number and + // in-stack position is in range with the number of available frames + size_t errors = 0; + const OFMap& frames = stack->m_FrameNumbers; + FGStack::const_iterator it = frames.begin(); + for (size_t count = 0; count < numFrames; count++) + { + // Frame number must be in range + if ( (*it).first > numFrames ) + { + DCMFG_ERROR("Stack references frame #" << (*it).first << " but only #" << numFrames << " frames exist"); + errors++; + } + if ( (*it).second> numFrames ) + { + DCMFG_ERROR("Stack references in-stack position #" << (*it).first << " but only #" << numFrames << " frames exist"); + errors++; + } + } + return errors; +} diff --git a/dcmfg/tests/Makefile.in b/dcmfg/tests/Makefile.in new file mode 100644 index 00000000..733bd293 --- /dev/null +++ b/dcmfg/tests/Makefile.in @@ -0,0 +1,30 @@ +# +# Makefile for dcmfg/tests +# + +@SET_MAKE@ + +SHELL = /bin/sh +VPATH = @srcdir@:@top_srcdir@/include:@top_srcdir@/@configdir@/include +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +configdir = @top_srcdir@/@configdir@ + +include $(configdir)/@common_makefile@ + + +all: + +check: + +check-exhaustive: + +install: + +clean: + rm -f $(TRASH) + +distclean: + rm -f $(DISTTRASH) + +dependencies: diff --git a/dcmimage/CMakeLists.txt b/dcmimage/CMakeLists.txt new file mode 100644 index 00000000..e1313f05 --- /dev/null +++ b/dcmimage/CMakeLists.txt @@ -0,0 +1,10 @@ +# declare project +PROJECT(dcmimage) + +# declare include directories which hold for all subdirectories +INCLUDE_DIRECTORIES(${dcmimage_SOURCE_DIR}/include ${ofstd_SOURCE_DIR}/include ${oflog_SOURCE_DIR}/include ${dcmdata_SOURCE_DIR}/include ${dcmimgle_SOURCE_DIR}/include ${ZLIB_INCDIR} ${LIBTIFF_INCDIR} ${LIBPNG_INCDIR}) + +# recurse into subdirectories +FOREACH(SUBDIR libsrc apps include) + ADD_SUBDIRECTORY(${SUBDIR}) +ENDFOREACH(SUBDIR) diff --git a/dcmimage/Makefile.in b/dcmimage/Makefile.in new file mode 100644 index 00000000..27206e96 --- /dev/null +++ b/dcmimage/Makefile.in @@ -0,0 +1,97 @@ +# +# Makefile for dcmimage +# + +@SET_MAKE@ + +SHELL = /bin/sh +VPATH = @srcdir@:@top_srcdir@/include:@top_srcdir@/@configdir@/include +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +configdir = @top_srcdir@/@configdir@ + +include $(configdir)/@common_makefile@ + + +all: include-all libsrc-all apps-all tests-all + +install: install-bin install-doc install-support + +install-bin: apps-install + +install-doc: docs-install + +install-data: data-install + +install-etc: etc-install + +install-include: include-install + +install-lib: libsrc-install install-include + +install-support: install-data install-etc + + +include-all: + (cd include && $(MAKE) ARCH="$(ARCH)" all) + +libsrc-all: include-all + (cd libsrc && $(MAKE) ARCH="$(ARCH)" all) + +apps-all: libsrc-all + (cd apps && $(MAKE) ARCH="$(ARCH)" all) + +tests-all: libsrc-all + (cd tests && $(MAKE) ARCH="$(ARCH)" all) + + +check: tests-all + (cd tests && $(MAKE) check) + +check-exhaustive: tests-all + (cd tests && $(MAKE) check-exhaustive) + + +include-install: + (cd include && $(MAKE) ARCH="$(ARCH)" install) + +libsrc-install: libsrc-all + (cd libsrc && $(MAKE) ARCH="$(ARCH)" install) + +apps-install: apps-all + (cd apps && $(MAKE) ARCH="$(ARCH)" install) + +docs-install: + (cd docs && $(MAKE) install) + +data-install: + (cd data && $(MAKE) install) + +etc-install: + (cd etc && $(MAKE) install) + + +clean: + (cd include && $(MAKE) clean) + (cd libsrc && $(MAKE) clean) + (cd apps && $(MAKE) clean) + (cd tests && $(MAKE) clean) + (cd docs && $(MAKE) clean) + (cd data && $(MAKE) clean) + (cd etc && $(MAKE) clean) + rm -f $(TRASH) + +distclean: + (cd include && $(MAKE) distclean) + (cd libsrc && $(MAKE) distclean) + (cd apps && $(MAKE) distclean) + (cd tests && $(MAKE) distclean) + (cd docs && $(MAKE) distclean) + (cd data && $(MAKE) distclean) + (cd etc && $(MAKE) distclean) + rm -f $(DISTTRASH) + +dependencies: + (cd libsrc && touch $(DEP) && $(MAKE) dependencies) + (cd apps && touch $(DEP) && $(MAKE) dependencies) +# (cd tests && touch $(DEP) && $(MAKE) dependencies) diff --git a/dcmimage/apps/CMakeLists.txt b/dcmimage/apps/CMakeLists.txt new file mode 100644 index 00000000..ff27c849 --- /dev/null +++ b/dcmimage/apps/CMakeLists.txt @@ -0,0 +1,9 @@ +# declare executables +FOREACH(PROGRAM dcm2pnm dcmquant dcmscale) + DCMTK_ADD_EXECUTABLE(${PROGRAM} ${PROGRAM}) +ENDFOREACH(PROGRAM) + +# make sure executables are linked to the corresponding libraries +FOREACH(PROGRAM dcm2pnm dcmquant dcmscale) + DCMTK_TARGET_LINK_MODULES(${PROGRAM} dcmimage dcmimgle dcmdata oflog ofstd) +ENDFOREACH(PROGRAM) diff --git a/dcmimage/apps/Makefile.dep b/dcmimage/apps/Makefile.dep new file mode 100644 index 00000000..1a5e6e0b --- /dev/null +++ b/dcmimage/apps/Makefile.dep @@ -0,0 +1,401 @@ +dcm2pnm.o: dcm2pnm.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcostrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicent.h \ + ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcmetinf.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicdir.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdirrec.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrulup.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrul.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixseq.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcofsetl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrae.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvras.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrda.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrds.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrdt.h \ + ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvris.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrtm.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrur.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcchrstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlt.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpn.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsh.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrst.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvruc.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrut.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixel.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpobw.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcovlay.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrat.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrss.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrus.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfd.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrof.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrod.h \ + ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcrledrg.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/dcmimage.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/dimoimg.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diimage.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfcache.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diovlay.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diobjcou.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/didefine.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diovdat.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diovpln.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diutils.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/dimopx.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/dipixel.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/dimomod.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diluptab.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/dibaslut.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/dimoopx.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/didispfn.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/digsdfn.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diciefn.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/dicielut.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/didislut.h \ + ../include/dcmtk/dcmimage/diregist.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diregbas.h \ + ../include/dcmtk/dcmimage/dicdefin.h \ + ../include/dcmtk/dcmimage/dipitiff.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diplugin.h \ + ../include/dcmtk/dcmimage/dipipng.h +dcmquant.o: dcmquant.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcostrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicent.h \ + ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcmetinf.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicdir.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdirrec.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrulup.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrul.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixseq.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcofsetl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrae.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvras.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrda.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrds.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrdt.h \ + ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvris.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrtm.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrur.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcchrstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlt.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpn.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsh.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrst.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvruc.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrut.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixel.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpobw.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcovlay.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrat.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrss.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrus.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfd.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrof.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrod.h \ + ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/dcmimage.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/dimoimg.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diimage.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfcache.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diovlay.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diobjcou.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/didefine.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diovdat.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diovpln.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diutils.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/dimopx.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/dipixel.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/dimomod.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diluptab.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/dibaslut.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/dimoopx.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/didispfn.h \ + ../include/dcmtk/dcmimage/diregist.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diregbas.h \ + ../include/dcmtk/dcmimage/dicdefin.h ../include/dcmtk/dcmimage/diquant.h \ + ../include/dcmtk/dcmimage/diqttype.h \ + ../../dcmdata/include/dcmtk/dcmdata/dccodec.h +dcmscale.o: dcmscale.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcostrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicent.h \ + ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcmetinf.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicdir.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdirrec.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrulup.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrul.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixseq.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcofsetl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrae.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvras.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrda.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrds.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrdt.h \ + ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvris.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrtm.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrur.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcchrstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlt.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpn.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsh.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrst.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvruc.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrut.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixel.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpobw.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcovlay.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrat.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrss.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrus.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfd.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrof.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrod.h \ + ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/dcmimage.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/dimoimg.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diimage.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfcache.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diovlay.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diobjcou.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/didefine.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diovdat.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diovpln.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diutils.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/dimopx.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/dipixel.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/dimomod.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diluptab.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/dibaslut.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/dimoopx.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/didispfn.h \ + ../include/dcmtk/dcmimage/diregist.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diregbas.h \ + ../include/dcmtk/dcmimage/dicdefin.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcrledrg.h diff --git a/dcmimage/apps/Makefile.in b/dcmimage/apps/Makefile.in new file mode 100644 index 00000000..36e35b11 --- /dev/null +++ b/dcmimage/apps/Makefile.in @@ -0,0 +1,60 @@ +# +# Makefile for dcmimage/apps +# + +@SET_MAKE@ + +SHELL = /bin/sh +VPATH = @srcdir@:@top_srcdir@/include:@top_srcdir@/@configdir@/include +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +configdir = @top_srcdir@/@configdir@ + +include $(configdir)/@common_makefile@ + +ofstddir = $(top_srcdir)/../ofstd +oflogdir = $(top_srcdir)/../oflog +dcmdatadir = $(top_srcdir)/../dcmdata +dcmimgledir = $(top_srcdir)/../dcmimgle + +LOCALINCLUDES = -I$(ofstddir)/include -I$(oflogdir)/include \ + -I$(dcmdatadir)/include -I$(dcmimgledir)/include +LIBDIRS = -L$(top_srcdir)/libsrc -L$(ofstddir)/libsrc -L$(oflogdir)/libsrc \ + -L$(dcmdatadir)/libsrc -L$(dcmimgledir)/libsrc +LOCALLIBS = -ldcmimage -ldcmimgle -ldcmdata -loflog -lofstd $(TIFFLIBS) $(PNGLIBS) \ + $(ZLIBLIBS) $(ICONVLIBS) + +objs = dcm2pnm.o dcmquant.o dcmscale.o +progs = dcm2pnm dcmquant dcmscale + + +all: $(progs) + +dcm2pnm: dcm2pnm.o + $(CXX) $(CXXFLAGS) $(LIBDIRS) $(LDFLAGS) -o $@ $@.o $(LOCALLIBS) $(MATHLIBS) $(LIBS) + +dcmquant: dcmquant.o + $(CXX) $(CXXFLAGS) $(LIBDIRS) $(LDFLAGS) -o $@ $@.o $(LOCALLIBS) $(MATHLIBS) $(LIBS) + +dcmscale: dcmscale.o + $(CXX) $(CXXFLAGS) $(LIBDIRS) $(LDFLAGS) -o $@ $@.o $(LOCALLIBS) $(MATHLIBS) $(LIBS) + + +install: all + $(configdir)/mkinstalldirs $(DESTDIR)$(bindir) + for prog in $(progs); do \ + $(INSTALL_PROGRAM) $$prog$(BINEXT) $(DESTDIR)$(bindir) && $(STRIP) $(DESTDIR)$(bindir)/$$prog$(BINEXT) ;\ + done + + +clean: + rm -f $(objs) $(progs) $(TRASH) + +distclean: + rm -f $(objs) $(progs) $(DISTTRASH) + + +dependencies: + $(CXX) -MM $(defines) $(includes) $(CPPFLAGS) $(CXXFLAGS) *.cc > $(DEP) + +include $(DEP) diff --git a/dcmimage/apps/dcm2pnm.cc b/dcmimage/apps/dcm2pnm.cc new file mode 100644 index 00000000..96d0a750 --- /dev/null +++ b/dcmimage/apps/dcm2pnm.cc @@ -0,0 +1,1551 @@ +/* + * + * Copyright (C) 1996-2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimage + * + * Authors: Marco Eichelberg, Joerg Riesmeier + * + * Purpose: Convert DICOM Images to PPM or PGM using the dcmimage library. + * + */ + + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#define INCLUDE_CSTDIO +#define INCLUDE_CSTRING +#include "dcmtk/ofstd/ofstdinc.h" + +#ifdef HAVE_GUSI_H +#include +#endif + +#include "dcmtk/dcmdata/dctk.h" /* for various dcmdata headers */ +#include "dcmtk/dcmdata/cmdlnarg.h" /* for prepareCmdLineArgs */ +#include "dcmtk/dcmdata/dcuid.h" /* for dcmtk version name */ +#include "dcmtk/dcmdata/dcrledrg.h" /* for DcmRLEDecoderRegistration */ + +#include "dcmtk/dcmimgle/dcmimage.h" /* for DicomImage */ +#include "dcmtk/dcmimgle/digsdfn.h" /* for DiGSDFunction */ +#include "dcmtk/dcmimgle/diciefn.h" /* for DiCIELABFunction */ + +#include "dcmtk/ofstd/ofconapp.h" /* for OFConsoleApplication */ +#include "dcmtk/ofstd/ofcmdln.h" /* for OFCommandLine */ + +#include "dcmtk/dcmimage/diregist.h" /* include to support color images */ +#include "dcmtk/ofstd/ofstd.h" /* for OFStandard */ + +#ifdef BUILD_DCM2PNM_AS_DCMJ2PNM +#include "dcmtk/dcmjpeg/djdecode.h" /* for dcmjpeg decoders */ +#include "dcmtk/dcmjpeg/dipijpeg.h" /* for dcmimage JPEG plugin */ +#endif + +#ifdef BUILD_DCM2PNM_AS_DCML2PNM +#include "dcmtk/dcmjpls/djdecode.h" /* for dcmjpls decoders */ +#endif + +#ifdef WITH_LIBTIFF +#include "dcmtk/dcmimage/dipitiff.h" /* for dcmimage TIFF plugin */ +#endif + +#ifdef WITH_LIBPNG +#include "dcmtk/dcmimage/dipipng.h" /* for dcmimage PNG plugin */ +#endif + +#ifdef WITH_ZLIB +#include /* for zlibVersion() */ +#endif + +#include "dcmtk/ofstd/ofstream.h" +#include "dcmtk/oflog/oflog.h" + +#define OFFIS_OUTFILE_DESCRIPTION "output filename to be written (default: stdout)" + +#ifdef BUILD_DCM2PNM_AS_DCML2PNM +# define OFFIS_CONSOLE_APPLICATION "dcml2pnm" +#elif defined(BUILD_DCM2PNM_AS_DCMJ2PNM) +# define OFFIS_CONSOLE_APPLICATION "dcmj2pnm" +#else +# define OFFIS_CONSOLE_APPLICATION "dcm2pnm" +#endif + +static OFLogger dcm2pnmLogger = OFLog::getLogger("dcmtk.apps." OFFIS_CONSOLE_APPLICATION); + +static const char *consoleDescription = "Convert DICOM images to PGM/PPM" +#ifdef WITH_LIBPNG + ", PNG" +#endif +#ifdef WITH_LIBTIFF + ", TIFF" +#endif +#ifdef BUILD_DCM2PNM_AS_DCMJ2PNM + ", JPEG" +#endif + " or BMP"; + +static char rcsid[] = "$dcmtk: " OFFIS_CONSOLE_APPLICATION " v" + OFFIS_DCMTK_VERSION " " OFFIS_DCMTK_RELEASEDATE " $"; + +#define SHORTCOL 4 +#define LONGCOL 20 + +/* output file types */ +enum E_FileType +{ + EFT_RawPNM, + EFT_8bitPNM, + EFT_16bitPNM, + EFT_NbitPNM, + EFT_BMP, + EFT_8bitBMP, + EFT_24bitBMP, + EFT_32bitBMP, + EFT_JPEG, + EFT_TIFF, + EFT_PNG, + EFT_16bitPNG +#ifdef PASTEL_COLOR_OUTPUT + ,EFT_PastelPNM +#endif +}; + + +// ******************************************** + +int main(int argc, char *argv[]) +{ + OFConsoleApplication app(OFFIS_CONSOLE_APPLICATION, consoleDescription, rcsid); + OFCommandLine cmd; + + E_FileReadMode opt_readMode = ERM_autoDetect; /* default: fileformat or dataset */ + E_TransferSyntax opt_transferSyntax = EXS_Unknown; /* default: xfer syntax recognition */ + + unsigned long opt_compatibilityMode = CIF_MayDetachPixelData | CIF_TakeOverExternalDataset; + OFBool opt_ignoreVoiLutDepth = OFFalse; /* default: do not ignore VOI LUT bit depth */ + OFCmdUnsignedInt opt_frame = 1; /* default: first frame */ + OFCmdUnsignedInt opt_frameCount = 1; /* default: one frame */ + OFBool opt_useFrameNumber = OFFalse; /* default: use frame counter */ + OFBool opt_multiFrame = OFFalse; /* default: no multiframes */ + int opt_convertToGrayscale = 0; /* default: color or grayscale */ + int opt_changePolarity = 0; /* default: normal polarity */ + int opt_useAspectRatio = 1; /* default: use aspect ratio for scaling */ + OFCmdUnsignedInt opt_useInterpolation = 1; /* default: use interpolation method '1' for scaling */ + int opt_useClip = 0; /* default: don't clip */ + OFCmdSignedInt opt_left = 0, opt_top = 0; /* clip region (origin) */ + OFCmdUnsignedInt opt_width = 0, opt_height = 0; /* clip region (extension) */ + int opt_rotateDegree = 0; /* default: no rotation */ + int opt_flipType = 0; /* default: no flipping */ + int opt_scaleType = 0; /* default: no scaling */ + /* 1 = X-factor, 2 = Y-factor, 3=X-size, 4=Y-size */ + OFCmdFloat opt_scale_factor = 1.0; + OFCmdUnsignedInt opt_scale_size = 1; + int opt_windowType = 0; /* default: no windowing */ + /* 1=Wi, 2=Wl, 3=Wm, 4=Wh, 5=Ww, 6=Wn, 7=Wr */ + OFCmdUnsignedInt opt_windowParameter = 0; + OFCmdUnsignedInt opt_roiLeft = 0, opt_roiTop = 0, opt_roiWidth = 0, opt_roiHeight = 0; + OFCmdFloat opt_windowCenter = 0.0, opt_windowWidth = 0.0; + + EF_VoiLutFunction opt_voiFunction = EFV_Default; + ES_PresentationLut opt_presShape = ESP_Default; + OFString opt_displayFile; + int opt_displayFunction = 0; /* default: GSDF */ + /* 0=GSDF, 1=CIELAB */ + OFCmdFloat opt_ambientLight = -1; /* default: not set */ + OFCmdFloat opt_illumination = -1; /* default: not set */ + OFCmdFloat opt_minDensity = -1; /* default: not set */ + OFCmdFloat opt_maxDensity = -1; /* default: not set */ + DiDisplayFunction::E_DeviceType deviceType = DiDisplayFunction::EDT_Monitor; + +#ifdef WITH_LIBTIFF + // TIFF parameters +#ifdef HAVE_LIBTIFF_LZW_COMPRESSION + DiTIFFCompression opt_tiffCompression = E_tiffLZWCompression; +#else + DiTIFFCompression opt_tiffCompression = E_tiffPackBitsCompression; +#endif + DiTIFFLZWPredictor opt_lzwPredictor = E_tiffLZWPredictorDefault; + OFCmdUnsignedInt opt_rowsPerStrip = 0; +#endif + +#ifdef WITH_LIBPNG + // PNG parameters + DiPNGInterlace opt_interlace = E_pngInterlaceAdam7; + DiPNGMetainfo opt_metainfo = E_pngFileMetainfo; +#endif + +#ifdef BUILD_DCM2PNM_AS_DCMJ2PNM + // JPEG parameters + OFCmdUnsignedInt opt_quality = 90; /* default: 90% JPEG quality */ + E_SubSampling opt_sampling = ESS_422; /* default: 4:2:2 sub-sampling */ + E_DecompressionColorSpaceConversion opt_decompCSconversion = EDC_photometricInterpretation; +#endif + + int opt_Overlay[16]; + int opt_O_used = 0; /* flag for +O parameter */ + EM_Overlay opt_OverlayMode = EMO_Default; /* default: Replace or ROI */ + + OFCmdFloat opt_foregroundDensity = 1.0; + OFCmdFloat opt_thresholdDensity = 0.5; + + int opt_imageInfo = 0; /* default: no info */ + int opt_suppressOutput = 0; /* default: create output */ + E_FileType opt_fileType = EFT_RawPNM; /* default: 8-bit PGM/PPM */ + /* (binary for file output and ASCII for stdout) */ + OFCmdUnsignedInt opt_fileBits = 0; /* default: 0 */ + const char * opt_ifname = NULL; + const char * opt_ofname = NULL; + + unsigned long i; + for (i = 0; i < 16; i++) + opt_Overlay[i] = 2; /* default: display all overlays if present */ + + prepareCmdLineArgs(argc, argv, OFFIS_CONSOLE_APPLICATION); + cmd.setOptionColumns(LONGCOL, SHORTCOL); + + cmd.addParam("dcmfile-in", "DICOM input filename to be converted"); + cmd.addParam("bitmap-out", OFFIS_OUTFILE_DESCRIPTION, OFCmdParam::PM_Optional); + + cmd.addGroup("general options:", LONGCOL, SHORTCOL + 2); + cmd.addOption("--help", "-h", "print this help text and exit", OFCommandLine::AF_Exclusive); + cmd.addOption("--version", "print version information and exit", OFCommandLine::AF_Exclusive); + OFLog::addOptions(cmd); + + cmd.addGroup("input options:"); + + cmd.addSubGroup("input file format:"); + cmd.addOption("--read-file", "+f", "read file format or data set (default)"); + cmd.addOption("--read-file-only", "+fo", "read file format only"); + cmd.addOption("--read-dataset", "-f", "read data set without file meta information"); + + cmd.addSubGroup("input transfer syntax:"); + cmd.addOption("--read-xfer-auto", "-t=", "use TS recognition (default)"); + cmd.addOption("--read-xfer-detect", "-td", "ignore TS specified in the file meta header"); + cmd.addOption("--read-xfer-little", "-te", "read with explicit VR little endian TS"); + cmd.addOption("--read-xfer-big", "-tb", "read with explicit VR big endian TS"); + cmd.addOption("--read-xfer-implicit", "-ti", "read with implicit VR little endian TS"); + + cmd.addGroup("image processing options:"); + + cmd.addSubGroup("frame selection:"); + cmd.addOption("--frame", "+F", 1, "[n]umber: integer", + "select specified frame (default: 1)"); + cmd.addOption("--frame-range", "+Fr", 2, "[n]umber [c]ount: integer", + "select c frames beginning with frame n"); + cmd.addOption("--all-frames", "+Fa", "select all frames"); + + cmd.addSubGroup("rotation:"); + cmd.addOption("--rotate-left", "+Rl", "rotate image left (-90 degrees)"); + cmd.addOption("--rotate-right", "+Rr", "rotate image right (+90 degrees)"); + cmd.addOption("--rotate-top-down", "+Rtd", "rotate image top-down (180 degrees)"); + + cmd.addSubGroup("flipping:"); + cmd.addOption("--flip-horizontally", "+Lh", "flip image horizontally"); + cmd.addOption("--flip-vertically", "+Lv", "flip image vertically"); + cmd.addOption("--flip-both-axes", "+Lhv", "flip image horizontally and vertically"); + + cmd.addSubGroup("scaling:"); + cmd.addOption("--recognize-aspect", "+a", "recognize pixel aspect ratio (default)"); + cmd.addOption("--ignore-aspect", "-a", "ignore pixel aspect ratio when scaling"); + cmd.addOption("--interpolate", "+i", 1, "[n]umber of algorithm: integer", + "use interpolation when scaling (1..4, def: 1)"); + cmd.addOption("--no-interpolation", "-i", "no interpolation when scaling"); + cmd.addOption("--no-scaling", "-S", "no scaling, ignore pixel aspect ratio (default)"); + cmd.addOption("--scale-x-factor", "+Sxf", 1, "[f]actor: float", + "scale x axis by factor, auto-compute y axis"); + cmd.addOption("--scale-y-factor", "+Syf", 1, "[f]actor: float", + "scale y axis by factor, auto-compute x axis"); + cmd.addOption("--scale-x-size", "+Sxv", 1, "[n]umber: integer", + "scale x axis to n pixels, auto-compute y axis"); + cmd.addOption("--scale-y-size", "+Syv", 1, "[n]umber: integer", + "scale y axis to n pixels, auto-compute x axis"); +#ifdef BUILD_DCM2PNM_AS_DCMJ2PNM + cmd.addSubGroup("color space conversion (compressed images only):"); + cmd.addOption("--conv-photometric", "+cp", "convert if YCbCr photometric interpr. (default)"); + cmd.addOption("--conv-lossy", "+cl", "convert YCbCr to RGB if lossy JPEG"); + cmd.addOption("--conv-guess", "+cg", "convert to RGB if YCbCr is guessed by library"); + cmd.addOption("--conv-guess-lossy", "+cgl", "convert to RGB if lossy JPEG and YCbCr is\nguessed by the underlying JPEG library"); + cmd.addOption("--conv-always", "+ca", "always convert YCbCr to RGB"); + cmd.addOption("--conv-never", "+cn", "never convert color space"); +#endif + + cmd.addSubGroup("modality LUT transformation:"); + cmd.addOption("--no-modality", "-M", "ignore stored modality LUT transformation"); + cmd.addOption("--use-modality", "+M", "use modality LUT transformation (default)"); + + cmd.addSubGroup("VOI LUT transformation:"); + cmd.addOption("--no-windowing", "-W", "no VOI windowing (default)"); + cmd.addOption("--use-window", "+Wi", 1, "[n]umber: integer", + "use the n-th VOI window from image file"); + cmd.addOption("--use-voi-lut", "+Wl", 1, "[n]umber: integer", + "use the n-th VOI look up table from image file"); + cmd.addOption("--min-max-window", "+Wm", "compute VOI window using min-max algorithm"); + cmd.addOption("--min-max-window-n", "+Wn", "compute VOI window using min-max algorithm,\nignoring extreme values"); + cmd.addOption("--roi-min-max-window", "+Wr", 4, "[l]eft [t]op [w]idth [h]eight: integer", + "compute ROI window using min-max algorithm,\nregion of interest is specified by l,t,w,h"); + cmd.addOption("--histogram-window", "+Wh", 1, "[n]umber: integer", + "compute VOI window using Histogram algorithm,\nignoring n percent"); + cmd.addOption("--set-window", "+Ww", 2, "[c]enter [w]idth: float", + "compute VOI window using center c and width w"); + cmd.addOption("--linear-function", "+Wfl", "set VOI LUT function to LINEAR"); + cmd.addOption("--sigmoid-function", "+Wfs", "set VOI LUT function to SIGMOID"); + + cmd.addSubGroup("presentation LUT transformation:"); + cmd.addOption("--identity-shape", "+Pid", "set presentation LUT shape to IDENTITY"); + cmd.addOption("--inverse-shape", "+Piv", "set presentation LUT shape to INVERSE"); + cmd.addOption("--lin-od-shape", "+Pod", "set presentation LUT shape to LIN OD"); + + cmd.addSubGroup("overlay:"); + cmd.addOption("--no-overlays", "-O", "do not display overlays"); + cmd.addOption("--display-overlay", "+O" , 1, "[n]umber: integer", + "display overlay n (0..16, 0=all, default: +O 0)"); + cmd.addOption("--ovl-replace", "+Omr", "use overlay mode \"Replace\"\n(default for Graphic overlays)"); + cmd.addOption("--ovl-threshold", "+Omt", "use overlay mode \"Threshold Replace\""); + cmd.addOption("--ovl-complement", "+Omc", "use overlay mode \"Complement\""); + cmd.addOption("--ovl-invert", "+Omv", "use overlay mode \"Invert Bitmap\""); + cmd.addOption("--ovl-roi", "+Omi", "use overlay mode \"Region of Interest\"\n(default for ROI overlays)"); + cmd.addOption("--set-foreground", "+Osf", 1, "[d]ensity: float", + "set overlay foreground density (0..1, def: 1)"); + cmd.addOption("--set-threshold", "+Ost", 1, "[d]ensity: float", + "set overlay threshold density (0..1, def: 0.5)"); + + cmd.addSubGroup("display LUT transformation:"); + cmd.addOption("--monitor-file", "+Dm", 1, "[f]ilename: string", + "calibrate output according to monitor\ncharacteristics defined in f"); + cmd.addOption("--printer-file", "+Dp", 1, "[f]ilename: string", + "calibrate output according to printer\ncharacteristics defined in f"); + cmd.addOption("--ambient-light", "+Da", 1, "[a]mbient light: float", + "ambient light value (cd/m^2, default: file f)"); + cmd.addOption("--illumination", "+Di", 1, "[i]llumination: float", + "illumination value (cd/m^2, default: file f)"); + cmd.addOption("--min-density", "+Dn", 1, "[m]inimum optical density: float", + "Dmin value (default: off, only with +Dp)"); + cmd.addOption("--max-density", "+Dx", 1, "[m]aximum optical density: float", + "Dmax value (default: off, only with +Dp)"); + cmd.addOption("--gsd-function", "+Dg", "use GSDF for calibration (default for +Dm/+Dp)"); + cmd.addOption("--cielab-function", "+Dc", "use CIELAB function for calibration "); + + cmd.addSubGroup("compatibility:"); + cmd.addOption("--accept-acr-nema", "+Ma", "accept ACR-NEMA images without photometric\ninterpretation"); + cmd.addOption("--accept-palettes", "+Mp", "accept incorrect palette attribute tags\n(0028,111x) and (0028,121x)"); + cmd.addOption("--check-lut-depth", "+Mc", "check 3rd value of the LUT descriptor, compare\nwith expected bit depth based on LUT data"); + cmd.addOption("--ignore-mlut-depth", "+Mm", "ignore 3rd value of the modality LUT descriptor,\ndetermine bits per table entry automatically"); + cmd.addOption("--ignore-vlut-depth", "+Mv", "ignore 3rd value of the VOI LUT descriptor,\ndetermine bits per table entry automatically"); + +#ifdef WITH_LIBTIFF + cmd.addSubGroup("TIFF format:"); +#ifdef HAVE_LIBTIFF_LZW_COMPRESSION + cmd.addOption("--compr-lzw", "+Tl", "LZW compression (default)"); + cmd.addOption("--compr-rle", "+Tr", "RLE compression"); + cmd.addOption("--compr-none", "+Tn", "uncompressed"); + cmd.addOption("--predictor-default", "+Pd", "no LZW predictor (default)"); + cmd.addOption("--predictor-none", "+Pn", "LZW predictor 1 (no prediction)"); + cmd.addOption("--predictor-horz", "+Ph", "LZW predictor 2 (horizontal differencing)"); +#else + cmd.addOption("--compr-rle", "+Tr", "RLE compression (default)"); + cmd.addOption("--compr-none", "+Tn", "uncompressed"); +#endif + cmd.addOption("--rows-per-strip", "+Rs", 1, "[r]ows: integer (default: 0)", + "rows per strip, default 8K per strip"); +#endif + +#ifdef WITH_LIBPNG + cmd.addSubGroup("PNG format:"); + cmd.addOption("--interlace", "+il", "create interlaced file (default)"); + cmd.addOption("--nointerlace", "-il", "create non-interlaced file"); + cmd.addOption("--meta-file", "+mf", "create PNG file meta information (default)"); + cmd.addOption("--meta-none", "-mf", "no PNG file meta information"); +#endif + +#ifdef BUILD_DCM2PNM_AS_DCMJ2PNM + cmd.addSubGroup("JPEG format"); + cmd.addOption("--compr-quality", "+Jq", 1, "[q]uality: integer (0..100, default: 90)", + "quality value for compression (in percent)"); + cmd.addOption("--sample-444", "+Js4", "4:4:4 sampling (no subsampling)"); + cmd.addOption("--sample-422", "+Js2", "4:2:2 subsampling (horizontal subsampling of\nchroma components, default)"); + cmd.addOption("--sample-411", "+Js1", "4:1:1 subsampling (horizontal and vertical\nsubsampling of chroma components)"); +#endif + + cmd.addSubGroup("other transformations:"); + cmd.addOption("--grayscale", "+G", "convert to grayscale if necessary"); + cmd.addOption("--change-polarity", "+P", "change polarity (invert pixel output)"); + cmd.addOption("--clip-region", "+C", 4, "[l]eft [t]op [w]idth [h]eight: integer", + "clip image region (l, t, w, h)"); + + cmd.addGroup("output options:"); + cmd.addSubGroup("general:"); + cmd.addOption("--image-info", "-im", "print image details (requires verbose mode)"); + cmd.addOption("--no-output", "-o", "do not create any output (useful with -im)"); + cmd.addSubGroup("filename generation (only with --frame-range or --all-frames):"); + cmd.addOption("--use-frame-counter", "+Fc", "use 0-based counter for filenames (default)"); + cmd.addOption("--use-frame-number", "+Fn", "use absolute frame number for filenames"); + cmd.addSubGroup("image format:"); + cmd.addOption("--write-raw-pnm", "+op", "write 8-bit binary PGM/PPM (default for files)"); + cmd.addOption("--write-8-bit-pnm", "+opb", "write 8-bit ASCII PGM/PPM (default for stdout)"); + cmd.addOption("--write-16-bit-pnm", "+opw", "write 16-bit ASCII PGM/PPM"); + cmd.addOption("--write-n-bit-pnm", "+opn", 1, "[n]umber: integer", + "write n-bit ASCII PGM/PPM (1..32)"); + cmd.addOption("--write-bmp", "+ob", "write 8-bit (monochrome) or 24-bit (color) BMP"); + cmd.addOption("--write-8-bit-bmp", "+obp", "write 8-bit palette BMP (monochrome only)"); + cmd.addOption("--write-24-bit-bmp", "+obt", "write 24-bit truecolor BMP"); + cmd.addOption("--write-32-bit-bmp", "+obr", "write 32-bit truecolor BMP"); +#ifdef WITH_LIBTIFF + cmd.addOption("--write-tiff", "+ot", "write 8-bit (monochrome) or 24-bit (color) TIFF"); +#endif +#ifdef WITH_LIBPNG + cmd.addOption("--write-png", "+on", "write 8-bit (monochrome) or 24-bit (color) PNG"); + cmd.addOption("--write-16-bit-png", "+on2", "write 16-bit (monochrome) or 48-bit (color) PNG"); +#endif +#ifdef BUILD_DCM2PNM_AS_DCMJ2PNM + cmd.addOption("--write-jpeg", "+oj", "write 8-bit lossy JPEG (baseline)"); +#endif +#ifdef PASTEL_COLOR_OUTPUT + cmd.addOption("--write-pastel-pnm", "+op", "write 8-bit binary PPM with pastel colors\n(early experimental version)"); +#endif + + if (app.parseCommandLine(cmd, argc, argv)) + { + /* check exclusive options first */ + if (cmd.hasExclusiveOption()) + { + if (cmd.findOption("--version")) + { + app.printHeader(OFTrue /*print host identifier*/); + COUT << OFendl << "External libraries used:"; +#if !defined(WITH_ZLIB) && !defined(BUILD_DCM2PNM_AS_DCMJ2PNM) && !defined(BUILD_DCM2PNM_AS_DCML2PNM) && !defined(WITH_LIBTIFF) && !defined(WITH_LIBPNG) + COUT << " none" << OFendl; +#else + COUT << OFendl; +#endif +#ifdef WITH_ZLIB + COUT << "- ZLIB, Version " << zlibVersion() << OFendl; +#endif +#ifdef BUILD_DCM2PNM_AS_DCMJ2PNM + COUT << "- " << DiJPEGPlugin::getLibraryVersionString() << OFendl; +#endif +#ifdef BUILD_DCM2PNM_AS_DCML2PNM + COUT << "- " << DJLSDecoderRegistration::getLibraryVersionString() << OFendl; +#endif +#ifdef WITH_LIBTIFF + COUT << "- " << DiTIFFPlugin::getLibraryVersionString() << OFendl; +#ifdef HAVE_LIBTIFF_LZW_COMPRESSION + COUT << " with LZW compression support" << OFendl; +#else + COUT << " without LZW compression support" << OFendl; +#endif +#endif +#ifdef WITH_LIBPNG + COUT << "- " << DiPNGPlugin::getLibraryVersionString() << OFendl; +#endif + return 0; + } + } + + /* command line parameters */ + + cmd.getParam(1, opt_ifname); + cmd.getParam(2, opt_ofname); + + /* general options */ + + OFLog::configureFromCommandLine(cmd, app); + + /* input options: input file format */ + + cmd.beginOptionBlock(); + if (cmd.findOption("--read-file")) opt_readMode = ERM_autoDetect; + if (cmd.findOption("--read-file-only")) opt_readMode = ERM_fileOnly; + if (cmd.findOption("--read-dataset")) opt_readMode = ERM_dataset; + cmd.endOptionBlock(); + + /* input options: input transfer syntax */ + + cmd.beginOptionBlock(); + if (cmd.findOption("--read-xfer-auto")) + opt_transferSyntax = EXS_Unknown; + if (cmd.findOption("--read-xfer-detect")) + dcmAutoDetectDatasetXfer.set(OFTrue); + if (cmd.findOption("--read-xfer-little")) + { + app.checkDependence("--read-xfer-little", "--read-dataset", opt_readMode == ERM_dataset); + opt_transferSyntax = EXS_LittleEndianExplicit; + } + if (cmd.findOption("--read-xfer-big")) + { + app.checkDependence("--read-xfer-big", "--read-dataset", opt_readMode == ERM_dataset); + opt_transferSyntax = EXS_BigEndianExplicit; + } + if (cmd.findOption("--read-xfer-implicit")) + { + app.checkDependence("--read-xfer-implicit", "--read-dataset", opt_readMode == ERM_dataset); + opt_transferSyntax = EXS_LittleEndianImplicit; + } + cmd.endOptionBlock(); + + /* image processing options: compatibility options */ + + if (cmd.findOption("--accept-acr-nema")) + opt_compatibilityMode |= CIF_AcrNemaCompatibility; + if (cmd.findOption("--accept-palettes")) + opt_compatibilityMode |= CIF_WrongPaletteAttributeTags; + if (cmd.findOption("--check-lut-depth")) + opt_compatibilityMode |= CIF_CheckLutBitDepth; + if (cmd.findOption("--ignore-mlut-depth")) + opt_compatibilityMode |= CIF_IgnoreModalityLutBitDepth; + if (cmd.findOption("--ignore-vlut-depth")) + opt_ignoreVoiLutDepth = OFTrue; + + /* image processing options: frame selection */ + + cmd.beginOptionBlock(); + if (cmd.findOption("--frame")) + app.checkValue(cmd.getValueAndCheckMin(opt_frame, 1)); + if (cmd.findOption("--frame-range")) + { + app.checkValue(cmd.getValueAndCheckMin(opt_frame, 1)); + app.checkValue(cmd.getValueAndCheckMin(opt_frameCount, 1)); + opt_multiFrame = OFTrue; + } + if (cmd.findOption("--all-frames")) + { + opt_frameCount = 0; + opt_multiFrame = OFTrue; + } + cmd.endOptionBlock(); + + /* image processing options: other transformations */ + + if (cmd.findOption("--grayscale")) + opt_convertToGrayscale = 1; + if (cmd.findOption("--change-polarity")) + opt_changePolarity = 1; + + if (cmd.findOption("--clip-region")) + { + app.checkValue(cmd.getValue(opt_left)); + app.checkValue(cmd.getValue(opt_top)); + app.checkValue(cmd.getValue(opt_width)); + app.checkValue(cmd.getValue(opt_height)); + opt_useClip = 1; + } + + /* image processing options: rotation */ + + cmd.beginOptionBlock(); + if (cmd.findOption("--rotate-left")) + opt_rotateDegree = 270; + if (cmd.findOption("--rotate-right")) + opt_rotateDegree = 90; + if (cmd.findOption("--rotate-top-down")) + opt_rotateDegree = 180; + cmd.endOptionBlock(); + + /* image processing options: flipping */ + + cmd.beginOptionBlock(); + if (cmd.findOption("--flip-horizontally")) + opt_flipType = 1; + if (cmd.findOption("--flip-vertically")) + opt_flipType = 2; + if (cmd.findOption("--flip-both-axes")) + opt_flipType = 3; + cmd.endOptionBlock(); + + /* image processing options: scaling */ + + cmd.beginOptionBlock(); + if (cmd.findOption("--recognize-aspect")) + opt_useAspectRatio = 1; + if (cmd.findOption("--ignore-aspect")) + opt_useAspectRatio = 0; + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--interpolate")) + app.checkValue(cmd.getValueAndCheckMinMax(opt_useInterpolation, 1, 4)); + if (cmd.findOption("--no-interpolation")) + opt_useInterpolation = 0; + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--no-scaling")) + opt_scaleType = 0; + if (cmd.findOption("--scale-x-factor")) + { + opt_scaleType = 1; + app.checkValue(cmd.getValueAndCheckMin(opt_scale_factor, 0.0, OFFalse)); + } + if (cmd.findOption("--scale-y-factor")) + { + opt_scaleType = 2; + app.checkValue(cmd.getValueAndCheckMin(opt_scale_factor, 0.0, OFFalse)); + } + if (cmd.findOption("--scale-x-size")) + { + opt_scaleType = 3; + app.checkValue(cmd.getValueAndCheckMin(opt_scale_size, 1)); + } + if (cmd.findOption("--scale-y-size")) + { + opt_scaleType = 4; + app.checkValue(cmd.getValueAndCheckMin(opt_scale_size, 1)); + } + cmd.endOptionBlock(); + + /* image processing options: color space conversion */ + +#ifdef BUILD_DCM2PNM_AS_DCMJ2PNM + cmd.beginOptionBlock(); + if (cmd.findOption("--conv-photometric")) + opt_decompCSconversion = EDC_photometricInterpretation; + if (cmd.findOption("--conv-lossy")) + opt_decompCSconversion = EDC_lossyOnly; + if (cmd.findOption("--conv-guess")) + opt_decompCSconversion = EDC_guess; + if (cmd.findOption("--conv-guess-lossy")) + opt_decompCSconversion = EDC_guessLossyOnly; + if (cmd.findOption("--conv-always")) + opt_decompCSconversion = EDC_always; + if (cmd.findOption("--conv-never")) + opt_decompCSconversion = EDC_never; + cmd.endOptionBlock(); +#endif + + /* image processing options: modality LUT transformation */ + + cmd.beginOptionBlock(); + if (cmd.findOption("--no-modality")) + opt_compatibilityMode |= CIF_IgnoreModalityTransformation; + if (cmd.findOption("--use-modality")) + opt_compatibilityMode &= ~CIF_IgnoreModalityTransformation; + cmd.endOptionBlock(); + + /* image processing options: VOI LUT transformation */ + + cmd.beginOptionBlock(); + if (cmd.findOption("--no-windowing")) + opt_windowType = 0; + if (cmd.findOption("--use-window")) + { + opt_windowType = 1; + app.checkValue(cmd.getValueAndCheckMin(opt_windowParameter, 1)); + } + if (cmd.findOption("--use-voi-lut")) + { + opt_windowType = 2; + app.checkValue(cmd.getValueAndCheckMin(opt_windowParameter, 1)); + } + if (cmd.findOption("--min-max-window")) + opt_windowType = 3; + if (cmd.findOption("--min-max-window-n")) + opt_windowType = 6; + if (cmd.findOption("--roi-min-max-window")) + { + opt_windowType = 7; + app.checkValue(cmd.getValue(opt_roiLeft)); + app.checkValue(cmd.getValue(opt_roiTop)); + app.checkValue(cmd.getValueAndCheckMin(opt_roiWidth, 1)); + app.checkValue(cmd.getValueAndCheckMin(opt_roiHeight, 1)); + } + if (cmd.findOption("--histogram-window")) + { + opt_windowType = 4; + app.checkValue(cmd.getValueAndCheckMinMax(opt_windowParameter, 0, 100)); + } + if (cmd.findOption("--set-window")) + { + opt_windowType = 5; + app.checkValue(cmd.getValue(opt_windowCenter)); + app.checkValue(cmd.getValueAndCheckMin(opt_windowWidth, 1.0)); + } + cmd.endOptionBlock(); + cmd.beginOptionBlock(); + if (cmd.findOption("--linear-function")) + opt_voiFunction = EFV_Linear; + if (cmd.findOption("--sigmoid-function")) + opt_voiFunction = EFV_Sigmoid; + cmd.endOptionBlock(); + + /* image processing options: presentation LUT transformation */ + + cmd.beginOptionBlock(); + if (cmd.findOption("--identity-shape")) + opt_presShape = ESP_Identity; + if (cmd.findOption("--inverse-shape")) + opt_presShape = ESP_Inverse; + if (cmd.findOption("--lin-od-shape")) + opt_presShape = ESP_LinOD; + cmd.endOptionBlock(); + + /* image processing options: display LUT transformation */ + + cmd.beginOptionBlock(); + if (cmd.findOption("--monitor-file")) + { + app.checkValue(cmd.getValue(opt_displayFile)); + deviceType = DiDisplayFunction::EDT_Monitor; + } + if (cmd.findOption("--printer-file")) + { + app.checkValue(cmd.getValue(opt_displayFile)); + deviceType = DiDisplayFunction::EDT_Printer; + } + cmd.endOptionBlock(); + + if (cmd.findOption("--ambient-light")) + app.checkValue(cmd.getValueAndCheckMin(opt_ambientLight, 0)); + if (cmd.findOption("--illumination")) + app.checkValue(cmd.getValueAndCheckMin(opt_illumination, 0)); + if (cmd.findOption("--min-density")) + { + app.checkDependence("--min-density", "--printer-file", deviceType == DiDisplayFunction::EDT_Printer); + app.checkValue(cmd.getValueAndCheckMin(opt_minDensity, 0)); + } + if (cmd.findOption("--max-density")) + { + app.checkDependence("--max-density", "--printer-file", deviceType == DiDisplayFunction::EDT_Printer); + app.checkValue(cmd.getValueAndCheckMin(opt_maxDensity, (opt_minDensity < 0) ? 0.0 : opt_minDensity, OFFalse /*incl*/)); + } + + cmd.beginOptionBlock(); + if (cmd.findOption("--gsd-function")) + opt_displayFunction = 0; + if (cmd.findOption("--cielab-function")) + opt_displayFunction = 1; + cmd.endOptionBlock(); + + /* image processing options: overlay */ + + cmd.beginOptionBlock(); + if (cmd.findOption("--no-overlays")) + { + opt_O_used = 1; + for (i = 0; i < 16; i++) + opt_Overlay[i] = 0; + } + if (cmd.findOption("--display-overlay", 0, OFCommandLine::FOM_First)) + { + do { + unsigned long l; + app.checkValue(cmd.getValueAndCheckMinMax(l, 1, 16)); + if (!opt_O_used) + { + for (i = 0; i < 16; i++) opt_Overlay[i] = 0; + opt_O_used = 1; + } + if (l > 0) + opt_Overlay[l - 1]=1; + else + { + for (i = 0; i < 16; i++) + opt_Overlay[i] = 2; + } + } while (cmd.findOption("--display-overlay", 0, OFCommandLine::FOM_Next)); + } + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--ovl-replace")) + opt_OverlayMode = EMO_Replace; + if (cmd.findOption("--ovl-threshold")) + opt_OverlayMode = EMO_ThresholdReplace; + if (cmd.findOption("--ovl-complement")) + opt_OverlayMode = EMO_Complement; + if (cmd.findOption("--ovl-invert")) + opt_OverlayMode = EMO_InvertBitmap; + if (cmd.findOption("--ovl-roi")) + opt_OverlayMode = EMO_RegionOfInterest; + cmd.endOptionBlock(); + + if (cmd.findOption("--set-foreground")) + app.checkValue(cmd.getValueAndCheckMinMax(opt_foregroundDensity, 0.0, 1.0)); + if (cmd.findOption("--set-threshold")) + app.checkValue(cmd.getValueAndCheckMinMax(opt_thresholdDensity, 0.0, 1.0)); + + /* image processing options: TIFF options */ + +#ifdef WITH_LIBTIFF + cmd.beginOptionBlock(); +#ifdef HAVE_LIBTIFF_LZW_COMPRESSION + if (cmd.findOption("--compr-lzw")) opt_tiffCompression = E_tiffLZWCompression; +#endif + if (cmd.findOption("--compr-rle")) opt_tiffCompression = E_tiffPackBitsCompression; + if (cmd.findOption("--compr-none")) opt_tiffCompression = E_tiffNoCompression; + cmd.endOptionBlock(); + +#ifdef HAVE_LIBTIFF_LZW_COMPRESSION + cmd.beginOptionBlock(); + if (cmd.findOption("--predictor-default")) opt_lzwPredictor = E_tiffLZWPredictorDefault; + if (cmd.findOption("--predictor-none")) opt_lzwPredictor = E_tiffLZWPredictorNoPrediction; + if (cmd.findOption("--predictor-horz")) opt_lzwPredictor = E_tiffLZWPredictorHDifferencing; + cmd.endOptionBlock(); +#endif + + if (cmd.findOption("--rows-per-strip")) + app.checkValue(cmd.getValueAndCheckMinMax(opt_rowsPerStrip, 0, 65535)); +#endif + + /* image processing options: PNG options */ + +#ifdef WITH_LIBPNG + cmd.beginOptionBlock(); + if (cmd.findOption("--interlace")) opt_interlace = E_pngInterlaceAdam7; + if (cmd.findOption("--nointerlace")) opt_interlace = E_pngInterlaceNone; + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--meta-none")) opt_metainfo = E_pngNoMetainfo; + if (cmd.findOption("--meta-file")) opt_metainfo = E_pngFileMetainfo; + cmd.endOptionBlock(); +#endif + + /* image processing options: JPEG options */ + +#ifdef BUILD_DCM2PNM_AS_DCMJ2PNM + if (cmd.findOption("--compr-quality")) + app.checkValue(cmd.getValueAndCheckMinMax(opt_quality, 0, 100)); + cmd.beginOptionBlock(); + if (cmd.findOption("--sample-444")) + opt_sampling = ESS_444; + if (cmd.findOption("--sample-422")) + opt_sampling = ESS_422; + if (cmd.findOption("--sample-411")) + opt_sampling = ESS_411; + cmd.endOptionBlock(); +#endif + + /* output options */ + + if (cmd.findOption("--image-info")) + { + app.checkDependence("--image-info", "verbose mode", dcm2pnmLogger.isEnabledFor(OFLogger::INFO_LOG_LEVEL)); + opt_imageInfo = 1; + } + + cmd.beginOptionBlock(); + if (cmd.findOption("--use-frame-counter")) + { + app.checkDependence("--use-frame-counter", "--frame-range or --all-frames", opt_multiFrame); + opt_useFrameNumber = OFFalse; + } + if (cmd.findOption("--use-frame-number")) + { + app.checkDependence("--use-frame-number", "--frame-range or --all-frames", opt_multiFrame); + opt_useFrameNumber = OFTrue; + } + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--no-output")) + opt_suppressOutput = 1; + if (cmd.findOption("--write-raw-pnm")) + opt_fileType = EFT_RawPNM; + if (cmd.findOption("--write-8-bit-pnm")) + opt_fileType = EFT_8bitPNM; + if (cmd.findOption("--write-16-bit-pnm")) + opt_fileType = EFT_16bitPNM; + if (cmd.findOption("--write-n-bit-pnm")) + { + opt_fileType = EFT_NbitPNM; + app.checkValue(cmd.getValueAndCheckMinMax(opt_fileBits, 1, 32)); + } + if (cmd.findOption("--write-bmp")) + opt_fileType = EFT_BMP; + if (cmd.findOption("--write-8-bit-bmp")) + opt_fileType = EFT_8bitBMP; + if (cmd.findOption("--write-24-bit-bmp")) + opt_fileType = EFT_24bitBMP; + if (cmd.findOption("--write-32-bit-bmp")) + opt_fileType = EFT_32bitBMP; +#ifdef BUILD_DCM2PNM_AS_DCMJ2PNM + if (cmd.findOption("--write-jpeg")) + opt_fileType = EFT_JPEG; +#endif +#ifdef WITH_LIBTIFF + if (cmd.findOption("--write-tiff")) + opt_fileType = EFT_TIFF; +#endif +#ifdef WITH_LIBPNG + if (cmd.findOption("--write-png")) + opt_fileType = EFT_PNG; + if (cmd.findOption("--write-16-bit-png")) + opt_fileType = EFT_16bitPNG; +#endif +#ifdef PASTEL_COLOR_OUTPUT + if (cmd.findOption("--write-pastel-pnm")) + opt_fileType = EFT_PastelPNM; +#endif + cmd.endOptionBlock(); + } + + /* print resource identifier */ + OFLOG_DEBUG(dcm2pnmLogger, rcsid << OFendl); + + /* make sure data dictionary is loaded */ + if (!dcmDataDict.isDictionaryLoaded()) + { + OFLOG_WARN(dcm2pnmLogger, "no data dictionary loaded, check environment variable: " + << DCM_DICT_ENVIRONMENT_VARIABLE); + } + + OFLOG_INFO(dcm2pnmLogger, "reading DICOM file: " << opt_ifname); + + // register RLE decompression codec + DcmRLEDecoderRegistration::registerCodecs(); +#ifdef BUILD_DCM2PNM_AS_DCMJ2PNM + // register JPEG decompression codecs + DJDecoderRegistration::registerCodecs(opt_decompCSconversion); +#endif +#ifdef BUILD_DCM2PNM_AS_DCML2PNM + // register JPEG-LS decompression codecs + DJLSDecoderRegistration::registerCodecs(); +#endif + + DcmFileFormat *dfile = new DcmFileFormat(); + OFCondition cond = dfile->loadFile(opt_ifname, opt_transferSyntax, EGL_withoutGL, DCM_MaxReadLength, opt_readMode); + + if (cond.bad()) + { + OFLOG_FATAL(dcm2pnmLogger, cond.text() << ": reading file: " << opt_ifname); + return 1; + } + + OFLOG_INFO(dcm2pnmLogger, "preparing pixel data"); + + DcmDataset *dataset = dfile->getDataset(); + E_TransferSyntax xfer = dataset->getOriginalXfer(); + + Sint32 frameCount; + if (dataset->findAndGetSint32(DCM_NumberOfFrames, frameCount).bad()) + frameCount = 1; + if ((opt_frameCount == 0) || ((opt_frame == 1) && (opt_frameCount == OFstatic_cast(Uint32, frameCount)))) + { + // since we process all frames anyway, decompress the complete pixel data (if required) + opt_compatibilityMode |= CIF_DecompressCompletePixelData; + } + if ((frameCount > 1) && !(opt_compatibilityMode & CIF_DecompressCompletePixelData)) + { + // use partial read access to pixel data (only in case of multiple frames, but not for all frames) + opt_compatibilityMode |= CIF_UsePartialAccessToPixelData; + } + + DicomImage *di = new DicomImage(dfile, xfer, opt_compatibilityMode, opt_frame - 1, opt_frameCount); + if (di == NULL) + { + OFLOG_FATAL(dcm2pnmLogger, "Out of memory"); + return 1; + } + + if (di->getStatus() != EIS_Normal) + { + OFLOG_FATAL(dcm2pnmLogger, DicomImage::getString(di->getStatus())); + return 1; + } + + /* create & set display function */ + DiDisplayFunction *disp = NULL; + if (!opt_displayFile.empty()) + { + if (opt_displayFunction == 1) + disp = new DiCIELABFunction(opt_displayFile.c_str(), deviceType); + else + disp = new DiGSDFunction(opt_displayFile.c_str(), deviceType); + if (disp != NULL) + { + if (opt_ambientLight >= 0) + disp->setAmbientLightValue(opt_ambientLight); + if (opt_illumination >= 0) + disp->setIlluminationValue(opt_illumination); + if (opt_minDensity >= 0) + disp->setMinDensityValue(opt_minDensity); + if (opt_maxDensity >= 0) + disp->setMaxDensityValue(opt_maxDensity); + if ((di != NULL) && (disp->isValid())) + { + OFLOG_INFO(dcm2pnmLogger, "activating " + << ((opt_displayFunction == 1) ? "CIELAB" : "GSDF") + << " display function for " + << ((deviceType == DiDisplayFunction::EDT_Monitor) ? "softcopy" : "hardcopy") + << " devices"); + if (!di->setDisplayFunction(disp)) + OFLOG_WARN(dcm2pnmLogger, "cannot select display function"); + } + } + } + + if (opt_imageInfo) + { + /* dump image parameters */ + OFLOG_INFO(dcm2pnmLogger, "dumping image parameters"); + + double minVal = 0.0; + double maxVal = 0.0; + const char *colorModel; + const char *SOPClassUID = NULL; + const char *SOPInstanceUID = NULL; + const char *SOPClassText = NULL; + const char *XferText = DcmXfer(xfer).getXferName(); + + int minmaxValid = di->getMinMaxValues(minVal, maxVal); + colorModel = di->getString(di->getPhotometricInterpretation()); + if (colorModel == NULL) + colorModel = "unknown"; + + dataset->findAndGetString(DCM_SOPClassUID, SOPClassUID); + dataset->findAndGetString(DCM_SOPInstanceUID, SOPInstanceUID); + + if (SOPInstanceUID == NULL) + SOPInstanceUID = "not present"; + if (SOPClassUID == NULL) + SOPClassText = "not present"; + else + SOPClassText = dcmFindNameOfUID(SOPClassUID); + if (SOPClassText == NULL) + SOPClassText = SOPClassUID; + + char aspectRatio[30]; + OFStandard::ftoa(aspectRatio, sizeof(aspectRatio), di->getHeightWidthRatio(), OFStandard::ftoa_format_f, 0, 2); + + /* dump some general information */ + OFLOG_INFO(dcm2pnmLogger, " filename : " << opt_ifname << OFendl + << " transfer syntax : " << XferText << OFendl + << " SOP class : " << SOPClassText << OFendl + << " SOP instance UID : " << SOPInstanceUID << OFendl + << " columns x rows : " << di->getWidth() << " x " << di->getHeight() << OFendl + << " bits per sample : " << di->getDepth() << OFendl + << " color model : " << colorModel << OFendl + << " pixel aspect ratio : " << aspectRatio << OFendl + << " number of frames : " << di->getNumberOfFrames() << " (" << di->getFrameCount() << " processed)"); + if (di->getFrameTime() > 0) + OFLOG_INFO(dcm2pnmLogger, " frame time (in ms) : " << di->getFrameTime()); + + /* dump VOI windows */ + unsigned long count; + OFString explStr, funcStr; + count = di->getWindowCount(); + switch (di->getVoiLutFunction()) + { + case EFV_Default: + funcStr = ""; + break; + case EFV_Linear: + funcStr = "LINEAR"; + break; + case EFV_Sigmoid: + funcStr = "SIGMOID"; + break; + } + OFLOG_INFO(dcm2pnmLogger, " VOI LUT function : " << funcStr); + OFLOG_INFO(dcm2pnmLogger, " VOI windows in file : " << di->getWindowCount()); + for (i = 0; i < count; i++) + { + if (di->getVoiWindowExplanation(i, explStr) == NULL) + OFLOG_INFO(dcm2pnmLogger, " - "); + else + OFLOG_INFO(dcm2pnmLogger, " - " << explStr); + } + + /* dump VOI LUTs */ + count = di->getVoiLutCount(); + OFLOG_INFO(dcm2pnmLogger, " VOI LUTs in file : " << count); + for (i = 0; i < count; i++) + { + if (di->getVoiLutExplanation(i, explStr) == NULL) + OFLOG_INFO(dcm2pnmLogger, " - "); + else + OFLOG_INFO(dcm2pnmLogger, " - " << explStr); + } + + /* dump presentation LUT shape */ + OFString shapeStr; + switch (di->getPresentationLutShape()) + { + case ESP_Default: + shapeStr = ""; + break; + case ESP_Identity: + shapeStr = "IDENTITY"; + break; + case ESP_Inverse: + shapeStr = "INVERSE"; + break; + case ESP_LinOD: + shapeStr = "LIN OD"; + break; + } + OFLOG_INFO(dcm2pnmLogger, " presentation shape : " << shapeStr); + + /* dump overlays */ + OFLOG_INFO(dcm2pnmLogger, " overlays in file : " << di->getOverlayCount()); + + if (minmaxValid) + { + char minmaxText[30]; + OFStandard::ftoa(minmaxText, sizeof(minmaxText), maxVal, OFStandard::ftoa_format_f, 0, 0); + OFLOG_INFO(dcm2pnmLogger, " maximum pixel value : " << minmaxText); + OFStandard::ftoa(minmaxText, sizeof(minmaxText), minVal, OFStandard::ftoa_format_f, 0, 0); + OFLOG_INFO(dcm2pnmLogger, " minimum pixel value : " << minmaxText); + } + } + + if (!opt_suppressOutput) + { + /* try to select frame */ + if (opt_frame != di->getFirstFrame() + 1) + { + OFLOG_FATAL(dcm2pnmLogger, "cannot select frame " << opt_frame << ", invalid frame number"); + return 1; + } + + /* convert to grayscale if necessary */ + if ((opt_convertToGrayscale) && (!di->isMonochrome())) + { + OFLOG_INFO(dcm2pnmLogger, "converting image to grayscale"); + + DicomImage *newimage = di->createMonochromeImage(); + if (newimage == NULL) + { + OFLOG_FATAL(dcm2pnmLogger, "Out of memory or cannot convert to monochrome image"); + return 1; + } + else if (newimage->getStatus() != EIS_Normal) + { + OFLOG_FATAL(dcm2pnmLogger, DicomImage::getString(newimage->getStatus())); + return 1; + } + else + { + delete di; + di = newimage; + } + } + + /* process overlay parameters */ + di->hideAllOverlays(); + for (unsigned int k = 0; k < 16; k++) + { + if (opt_Overlay[k]) + { + if ((opt_Overlay[k] == 1) || (k < di->getOverlayCount())) + { + OFLOG_INFO(dcm2pnmLogger, "activating overlay plane " << k + 1); + if (opt_OverlayMode != EMO_Default) + { + if (!di->showOverlay(k, opt_OverlayMode, opt_foregroundDensity, opt_thresholdDensity)) + OFLOG_WARN(dcm2pnmLogger, "cannot display overlay plane " << k + 1); + } else { + if (!di->showOverlay(k)) /* use default values */ + OFLOG_WARN(dcm2pnmLogger, "cannot display overlay plane " << k + 1); + } + } + } + } + + /* process VOI parameters */ + switch (opt_windowType) + { + case 1: /* use the n-th VOI window from the image file */ + if ((opt_windowParameter < 1) || (opt_windowParameter > di->getWindowCount())) + { + OFLOG_FATAL(dcm2pnmLogger, "cannot select VOI window " << opt_windowParameter << ", only " + << di->getWindowCount() << " window(s) in file"); + return 1; + } + OFLOG_INFO(dcm2pnmLogger, "activating VOI window " << opt_windowParameter); + if (!di->setWindow(opt_windowParameter - 1)) + OFLOG_WARN(dcm2pnmLogger, "cannot select VOI window " << opt_windowParameter); + break; + case 2: /* use the n-th VOI look up table from the image file */ + if ((opt_windowParameter < 1) || (opt_windowParameter > di->getVoiLutCount())) + { + OFLOG_FATAL(dcm2pnmLogger, "cannot select VOI LUT " << opt_windowParameter << ", only " + << di->getVoiLutCount() << " LUT(s) in file"); + return 1; + } + OFLOG_INFO(dcm2pnmLogger, "activating VOI LUT " << opt_windowParameter); + if (!di->setVoiLut(opt_windowParameter - 1, opt_ignoreVoiLutDepth ? ELM_IgnoreValue : ELM_UseValue)) + OFLOG_WARN(dcm2pnmLogger, "cannot select VOI LUT " << opt_windowParameter); + break; + case 3: /* Compute VOI window using min-max algorithm */ + OFLOG_INFO(dcm2pnmLogger, "activating VOI window min-max algorithm"); + if (!di->setMinMaxWindow(0)) + OFLOG_WARN(dcm2pnmLogger, "cannot compute min/max VOI window"); + break; + case 4: /* Compute VOI window using Histogram algorithm, ignoring n percent */ + OFLOG_INFO(dcm2pnmLogger, "activating VOI window histogram algorithm, ignoring " << opt_windowParameter << "%"); + if (!di->setHistogramWindow(OFstatic_cast(double, opt_windowParameter)/100.0)) + OFLOG_WARN(dcm2pnmLogger, "cannot compute histogram VOI window"); + break; + case 5: /* Compute VOI window using center and width */ + OFLOG_INFO(dcm2pnmLogger, "activating VOI window center=" << opt_windowCenter << ", width=" << opt_windowWidth); + if (!di->setWindow(opt_windowCenter, opt_windowWidth)) + OFLOG_WARN(dcm2pnmLogger, "cannot set VOI window to specified values"); + break; + case 6: /* Compute VOI window using min-max algorithm ignoring extremes */ + OFLOG_INFO(dcm2pnmLogger, "activating VOI window min-max algorithm, ignoring extreme values"); + if (!di->setMinMaxWindow(1)) + OFLOG_WARN(dcm2pnmLogger, "cannot compute min/max VOI window"); + break; + case 7: /* Compute region of interest VOI window */ + OFLOG_INFO(dcm2pnmLogger, "activating region of interest VOI window"); + if (!di->setRoiWindow(opt_roiLeft, opt_roiTop, opt_roiWidth, opt_roiHeight)) + OFLOG_WARN(dcm2pnmLogger, "cannot compute region of interest VOI window"); + break; + default: /* no VOI windowing */ + if (di->isMonochrome()) + { + OFLOG_INFO(dcm2pnmLogger, "disabling VOI window computation"); + if (!di->setNoVoiTransformation()) + OFLOG_WARN(dcm2pnmLogger, "cannot ignore VOI window"); + } + break; + } + /* VOI LUT function */ + if (opt_voiFunction != EFV_Default) + { + if (opt_voiFunction == EFV_Linear) + OFLOG_INFO(dcm2pnmLogger, "setting VOI LUT function to LINEAR"); + else if (opt_voiFunction == EFV_Sigmoid) + OFLOG_INFO(dcm2pnmLogger, "setting VOI LUT function to SIGMOID"); + if (!di->setVoiLutFunction(opt_voiFunction)) + OFLOG_WARN(dcm2pnmLogger, "cannot set VOI LUT function"); + } + + /* process presentation LUT parameters */ + if (opt_presShape != ESP_Default) + { + if (opt_presShape == ESP_Identity) + OFLOG_INFO(dcm2pnmLogger, "setting presentation LUT shape to IDENTITY"); + else if (opt_presShape == ESP_Inverse) + OFLOG_INFO(dcm2pnmLogger, "setting presentation LUT shape to INVERSE"); + else if (opt_presShape == ESP_LinOD) + OFLOG_INFO(dcm2pnmLogger, "setting presentation LUT shape to LIN OD"); + if (!di->setPresentationLutShape(opt_presShape)) + OFLOG_WARN(dcm2pnmLogger, "cannot set presentation LUT shape"); + } + + /* change polarity */ + if (opt_changePolarity) + { + OFLOG_INFO(dcm2pnmLogger, "setting polarity to REVERSE"); + if (!di->setPolarity(EPP_Reverse)) + OFLOG_WARN(dcm2pnmLogger, "cannot set polarity"); + } + + /* perform clipping */ + if (opt_useClip && (opt_scaleType == 0)) + { + OFLOG_INFO(dcm2pnmLogger, "clipping image to (" << opt_left << "," << opt_top << "," << opt_width + << "," << opt_height << ")"); + DicomImage *newimage = di->createClippedImage(opt_left, opt_top, opt_width, opt_height); + if (newimage == NULL) + { + OFLOG_FATAL(dcm2pnmLogger, "clipping to (" << opt_left << "," << opt_top << "," << opt_width + << "," << opt_height << ") failed"); + return 1; + } else if (newimage->getStatus() != EIS_Normal) + { + OFLOG_FATAL(dcm2pnmLogger, DicomImage::getString(newimage->getStatus())); + return 1; + } + else + { + delete di; + di = newimage; + } + } + + /* perform rotation */ + if (opt_rotateDegree > 0) + { + OFLOG_INFO(dcm2pnmLogger, "rotating image by " << opt_rotateDegree << " degrees"); + if (!di->rotateImage(opt_rotateDegree)) + OFLOG_WARN(dcm2pnmLogger, "cannot rotate image"); + } + + /* perform flipping */ + if (opt_flipType > 0) + { + switch (opt_flipType) + { + case 1: + OFLOG_INFO(dcm2pnmLogger, "flipping image horizontally"); + if (!di->flipImage(1, 0)) + OFLOG_WARN(dcm2pnmLogger, "cannot flip image"); + break; + case 2: + OFLOG_INFO(dcm2pnmLogger, "flipping image vertically"); + if (!di->flipImage(0, 1)) + OFLOG_WARN(dcm2pnmLogger, "cannot flip image"); + break; + case 3: + OFLOG_INFO(dcm2pnmLogger, "flipping image horizontally and vertically"); + if (!di->flipImage(1, 1)) + OFLOG_WARN(dcm2pnmLogger, "cannot flip image"); + break; + default: + break; + } + } + + /* perform scaling */ + if (opt_scaleType > 0) + { + DicomImage *newimage; + if (opt_useClip) + OFLOG_INFO(dcm2pnmLogger, "clipping image to (" << opt_left << "," << opt_top << "," << opt_width << "," << opt_height << ")"); + switch (opt_scaleType) + { + case 1: + OFLOG_INFO(dcm2pnmLogger, "scaling image, X factor=" << opt_scale_factor + << ", Interpolation=" << OFstatic_cast(int, opt_useInterpolation) + << ", Aspect Ratio=" << (opt_useAspectRatio ? "yes" : "no")); + if (opt_useClip) + newimage = di->createScaledImage(opt_left, opt_top, opt_width, opt_height, opt_scale_factor, 0.0, + OFstatic_cast(int, opt_useInterpolation), opt_useAspectRatio); + else + newimage = di->createScaledImage(opt_scale_factor, 0.0, OFstatic_cast(int, opt_useInterpolation), + opt_useAspectRatio); + break; + case 2: + OFLOG_INFO(dcm2pnmLogger, "scaling image, Y factor=" << opt_scale_factor + << ", Interpolation=" << OFstatic_cast(int, opt_useInterpolation) + << ", Aspect Ratio=" << (opt_useAspectRatio ? "yes" : "no")); + if (opt_useClip) + newimage = di->createScaledImage(opt_left, opt_top, opt_width, opt_height, 0.0, opt_scale_factor, + OFstatic_cast(int, opt_useInterpolation), opt_useAspectRatio); + else + newimage = di->createScaledImage(0.0, opt_scale_factor, OFstatic_cast(int, opt_useInterpolation), + opt_useAspectRatio); + break; + case 3: + OFLOG_INFO(dcm2pnmLogger, "scaling image, X size=" << opt_scale_size + << ", Interpolation=" << OFstatic_cast(int, opt_useInterpolation) + << ", Aspect Ratio=" << (opt_useAspectRatio ? "yes" : "no")); + if (opt_useClip) + newimage = di->createScaledImage(opt_left, opt_top, opt_width, opt_height, opt_scale_size, 0, + OFstatic_cast(int, opt_useInterpolation), opt_useAspectRatio); + else + newimage = di->createScaledImage(opt_scale_size, 0, OFstatic_cast(int, opt_useInterpolation), + opt_useAspectRatio); + break; + case 4: + OFLOG_INFO(dcm2pnmLogger, "scaling image, Y size=" << opt_scale_size + << ", Interpolation=" << OFstatic_cast(int, opt_useInterpolation) + << ", Aspect Ratio=" << (opt_useAspectRatio ? "yes" : "no")); + if (opt_useClip) + newimage = di->createScaledImage(opt_left, opt_top, opt_width, opt_height, 0, opt_scale_size, + OFstatic_cast(int, opt_useInterpolation), opt_useAspectRatio); + else + newimage = di->createScaledImage(0, opt_scale_size, OFstatic_cast(int, opt_useInterpolation), + opt_useAspectRatio); + break; + default: + OFLOG_INFO(dcm2pnmLogger, "internal error: unknown scaling type"); + newimage = NULL; + break; + } + if (newimage == NULL) + { + OFLOG_FATAL(dcm2pnmLogger, "Out of memory or cannot scale image"); + return 1; + } + else if (newimage->getStatus() != EIS_Normal) + { + OFLOG_FATAL(dcm2pnmLogger, DicomImage::getString(newimage->getStatus())); + return 1; + } + else + { + delete di; + di = newimage; + } + } + + /* write selected frame(s) to file */ + + int result = 0; + FILE *ofile = NULL; + OFString ofname; + unsigned int fcount = OFstatic_cast(unsigned int, ((opt_frameCount > 0) && (opt_frameCount <= di->getFrameCount())) ? opt_frameCount : di->getFrameCount()); + const char *ofext = NULL; + /* determine default file extension */ + switch (opt_fileType) + { + case EFT_BMP: + case EFT_8bitBMP: + case EFT_24bitBMP: + case EFT_32bitBMP: + ofext = "bmp"; + break; + case EFT_JPEG: + ofext = "jpg"; + break; + case EFT_TIFF: + ofext = "tif"; + break; + case EFT_PNG: + case EFT_16bitPNG: + ofext = "png"; + break; + default: + if (di->isMonochrome()) ofext = "pgm"; else ofext = "ppm"; + break; + } + + if (fcount < opt_frameCount) + { + OFLOG_WARN(dcm2pnmLogger, "cannot select " << opt_frameCount << " frames, limiting to " + << fcount << " frames"); + } + + for (unsigned int frame = 0; frame < fcount; frame++) + { + if (opt_ofname) + { + /* output to file */ + if (opt_multiFrame) + { + OFOStringStream stream; + /* generate output filename */ + stream << opt_ofname << "."; + if (opt_useFrameNumber) + stream << "f" << (opt_frame + frame); + else + stream << frame; + stream << "." << ofext << OFStringStream_ends; + /* convert string stream into a character string */ + OFSTRINGSTREAM_GETSTR(stream, buffer_str) + ofname.assign(buffer_str); + OFSTRINGSTREAM_FREESTR(buffer_str) + } else + ofname.assign(opt_ofname); + OFLOG_INFO(dcm2pnmLogger, "writing frame " << (opt_frame + frame) << " to " << ofname); + ofile = fopen(ofname.c_str(), "wb"); + if (ofile == NULL) + { + OFLOG_FATAL(dcm2pnmLogger, "cannot create file " << ofname); + return 1; + } + } else { + /* output to stdout */ + ofile = stdout; + OFLOG_INFO(dcm2pnmLogger, "writing frame " << (opt_frame + frame) << " to stdout"); + } + + /* finally create output image file */ + + switch (opt_fileType) + { + case EFT_RawPNM: + result = di->writeRawPPM(ofile, 8, frame); + break; + case EFT_8bitPNM: + result = di->writePPM(ofile, 8, frame); + break; + case EFT_16bitPNM: + result = di->writePPM(ofile, 16, frame); + break; + case EFT_NbitPNM: + result = di->writePPM(ofile, OFstatic_cast(int, opt_fileBits), frame); + break; + case EFT_BMP: + result = di->writeBMP(ofile, 0, frame); + break; + case EFT_8bitBMP: + result = di->writeBMP(ofile, 8, frame); + break; + case EFT_24bitBMP: + result = di->writeBMP(ofile, 24, frame); + break; + case EFT_32bitBMP: + result = di->writeBMP(ofile, 32, frame); + break; +#ifdef BUILD_DCM2PNM_AS_DCMJ2PNM + case EFT_JPEG: + { + /* initialize JPEG plugin */ + DiJPEGPlugin plugin; + plugin.setQuality(OFstatic_cast(unsigned int, opt_quality)); + plugin.setSampling(opt_sampling); + result = di->writePluginFormat(&plugin, ofile, frame); + } + break; +#endif +#ifdef WITH_LIBTIFF + case EFT_TIFF: + { + /* initialize TIFF plugin */ + DiTIFFPlugin tiffPlugin; + tiffPlugin.setCompressionType(opt_tiffCompression); + tiffPlugin.setLZWPredictor(opt_lzwPredictor); + tiffPlugin.setRowsPerStrip(OFstatic_cast(unsigned long, opt_rowsPerStrip)); + result = di->writePluginFormat(&tiffPlugin, ofile, frame); + } + break; +#endif +#ifdef WITH_LIBPNG + case EFT_PNG: + case EFT_16bitPNG: + { + /* initialize PNG plugin */ + DiPNGPlugin pngPlugin; + pngPlugin.setInterlaceType(opt_interlace); + pngPlugin.setMetainfoType(opt_metainfo); + if (opt_fileType == EFT_16bitPNG) + pngPlugin.setBitsPerSample(16); + result = di->writePluginFormat(&pngPlugin, ofile, frame); + } + break; +#endif +#ifdef PASTEL_COLOR_OUTPUT + case EFT_PastelPNM: + result = di->writePPM(ofile, MI_PastelColor, frame); + break; +#endif + default: + if (opt_ofname) + result = di->writeRawPPM(ofile, 8, frame); + else /* stdout */ + result = di->writePPM(ofile, 8, frame); + break; + } + + if (opt_ofname) + fclose(ofile); + + if (!result) + { + OFLOG_FATAL(dcm2pnmLogger, "cannot write frame"); + return 1; + } + } + } + + /* done, now cleanup. */ + OFLOG_INFO(dcm2pnmLogger, "cleaning up memory"); + delete di; + delete disp; + + // deregister RLE decompression codec + DcmRLEDecoderRegistration::cleanup(); +#ifdef BUILD_DCM2PNM_AS_DCMJ2PNM + // deregister JPEG decompression codecs + DJDecoderRegistration::cleanup(); +#endif +#ifdef BUILD_DCM2PNM_AS_DCML2PNM + // deregister JPEG-LS decompression codecs + DJLSDecoderRegistration::cleanup(); +#endif + + return 0; +} diff --git a/dcmimage/apps/dcmquant.cc b/dcmimage/apps/dcmquant.cc new file mode 100644 index 00000000..e36d1256 --- /dev/null +++ b/dcmimage/apps/dcmquant.cc @@ -0,0 +1,508 @@ +/* + * + * Copyright (C) 2001-2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimage + * + * Authors: Marco Eichelberg + * + * Purpose: Convert DICOM color images palette color + * + */ + + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#define INCLUDE_CSTDIO +#define INCLUDE_CSTRING +#include "dcmtk/ofstd/ofstdinc.h" + +#ifdef HAVE_GUSI_H +#include +#endif + +#include "dcmtk/dcmdata/dctk.h" /* for various dcmdata headers */ +#include "dcmtk/dcmdata/cmdlnarg.h" /* for prepareCmdLineArgs */ +#include "dcmtk/dcmdata/dcuid.h" /* for dcmtk version name */ +#include "dcmtk/dcmimgle/dcmimage.h" /* for DicomImage */ + +#include "dcmtk/ofstd/ofconapp.h" /* for OFConsoleApplication */ +#include "dcmtk/ofstd/ofcmdln.h" /* for OFCommandLine */ + +#include "dcmtk/dcmimage/diregist.h" /* include to support color images */ +#include "dcmtk/dcmimage/diquant.h" /* for DcmQuant */ +#include "dcmtk/dcmdata/dccodec.h" /* for DcmCodec */ + +#ifdef BUILD_WITH_DCMJPEG_SUPPORT +#include "dcmtk/dcmjpeg/djdecode.h" /* for dcmjpeg decoders */ +#include "dcmtk/dcmjpeg/dipijpeg.h" /* for dcmimage JPEG plugin */ +#endif + +#ifdef WITH_ZLIB +#include /* for zlibVersion() */ +#endif + +#define OFFIS_CONSOLE_DESCRIPTION "Convert DICOM color images to palette color" + +#ifdef BUILD_WITH_DCMJPEG_SUPPORT +#define OFFIS_CONSOLE_APPLICATION "dcmjquan" +#else +#define OFFIS_CONSOLE_APPLICATION "dcmquant" +#endif + +static OFLogger dcmquantLogger = OFLog::getLogger("dcmtk.apps." OFFIS_CONSOLE_APPLICATION); + +static char rcsid[] = "$dcmtk: " OFFIS_CONSOLE_APPLICATION " v" + OFFIS_DCMTK_VERSION " " OFFIS_DCMTK_RELEASEDATE " $"; + +#define SHORTCOL 3 +#define LONGCOL 21 + + +// ******************************************** + +int main(int argc, char *argv[]) +{ + OFConsoleApplication app(OFFIS_CONSOLE_APPLICATION, OFFIS_CONSOLE_DESCRIPTION, rcsid); + OFCommandLine cmd; + + E_FileReadMode opt_readMode = ERM_autoDetect; + E_FileWriteMode opt_writeMode = EWM_fileformat; + E_TransferSyntax opt_ixfer = EXS_Unknown; + E_TransferSyntax opt_oxfer = EXS_Unknown; + E_GrpLenEncoding opt_oglenc = EGL_recalcGL; + E_EncodingType opt_oenctype = EET_ExplicitLength; + E_PaddingEncoding opt_opadenc = EPD_noChange; + OFCmdUnsignedInt opt_filepad = 0; + OFCmdUnsignedInt opt_itempad = 0; + + unsigned long opt_compatibilityMode = CIF_MayDetachPixelData; + /* default: pixel data may detached if no longer needed */ + OFCmdUnsignedInt opt_frame = 1; /* default: first frame */ + OFCmdUnsignedInt opt_frameCount = 0; /* default: all frames */ + + OFBool opt_palette_ow = OFFalse; + OFBool opt_entries_word = OFFalse; + OFBool opt_palette_fs = OFFalse; + OFCmdUnsignedInt opt_palette_col = 256; + + DcmLargestDimensionType opt_largeType = DcmLargestDimensionType_default; + DcmRepresentativeColorType opt_repType = DcmRepresentativeColorType_default; + + OFBool opt_secondarycapture = OFFalse; + OFBool opt_uidcreation = OFTrue; + +#ifdef BUILD_WITH_DCMJPEG_SUPPORT + // JPEG parameters, currently not used +# if 0 + OFCmdUnsignedInt opt_quality = 90; /* default: 90% JPEG quality */ + E_SubSampling opt_sampling = ESS_422; /* default: 4:2:2 sub-sampling */ +# endif + E_DecompressionColorSpaceConversion opt_decompCSconversion = EDC_photometricInterpretation; +#endif + + const char * opt_ifname = NULL; + const char * opt_ofname = NULL; + + prepareCmdLineArgs(argc, argv, OFFIS_CONSOLE_APPLICATION); + cmd.setOptionColumns(LONGCOL, SHORTCOL); + + cmd.addParam("dcmfile-in", "DICOM input filename to be converted"); + cmd.addParam("dcmfile-out", "DICOM output filename to be written"); + + cmd.addGroup("general options:", LONGCOL, SHORTCOL + 2); + cmd.addOption("--help", "-h", "print this help text and exit", OFCommandLine::AF_Exclusive); + cmd.addOption("--version", "print version information and exit", OFCommandLine::AF_Exclusive); + OFLog::addOptions(cmd); + + cmd.addGroup("input options:"); + + cmd.addSubGroup("input file format:"); + cmd.addOption("--read-file", "+f", "read file format or data set (default)"); + cmd.addOption("--read-file-only", "+fo", "read file format only"); + cmd.addOption("--read-dataset", "-f", "read data set without file meta information"); + + cmd.addSubGroup("input transfer syntax:"); + cmd.addOption("--read-xfer-auto", "-t=", "use TS recognition (default)"); + cmd.addOption("--read-xfer-detect", "-td", "ignore TS specified in the file meta header"); + cmd.addOption("--read-xfer-little", "-te", "read with explicit VR little endian TS"); + cmd.addOption("--read-xfer-big", "-tb", "read with explicit VR big endian TS"); + cmd.addOption("--read-xfer-implicit", "-ti", "read with implicit VR little endian TS"); + + cmd.addGroup("image processing and encoding options:"); + cmd.addSubGroup("frame selection:"); + cmd.addOption("--frame", "+fr", 1, "[n]umber: integer", + "select specified frame"); + cmd.addOption("--all-frames", "+fa", "select all frames (default)"); + +#ifdef BUILD_WITH_DCMJPEG_SUPPORT + cmd.addSubGroup("color space conversion options (compressed images only):"); + cmd.addOption("--conv-photometric", "+cp", "convert if YCbCr photometric interpr. (default)"); + cmd.addOption("--conv-lossy", "+cl", "convert YCbCr to RGB if lossy JPEG"); + cmd.addOption("--conv-guess", "+cg", "convert to RGB if YCbCr is guessed by library"); + cmd.addOption("--conv-guess-lossy", "+cgl", "convert to RGB if lossy JPEG and YCbCr is\nguessed by the underlying JPEG library"); + cmd.addOption("--conv-always", "+ca", "always convert YCbCr to RGB"); + cmd.addOption("--conv-never", "+cn", "never convert color space"); +#endif + + cmd.addSubGroup("compatibility:"); + cmd.addOption("--accept-palettes", "+Mp", "accept incorrect palette attribute tags\n(0028,111x) and (0028,121x)"); + + cmd.addSubGroup("median cut dimension selection:"); + cmd.addOption("--mc-dimension-rgb", "+Dr", "max dimension from RGB range (default)"); + cmd.addOption("--mc-dimension-lum", "+Dl", "max dimension from luminance"); + + cmd.addSubGroup("median cut representative color selection:"); + cmd.addOption("--mc-color-avgbox", "+Cb", "average colors in box (default)"); + cmd.addOption("--mc-color-avgpixel", "+Cp", "average pixels in box"); + cmd.addOption("--mc-color-center", "+Cc", "select center of box"); + + cmd.addSubGroup("color palette creation:"); + cmd.addOption("--write-ow", "+pw", "write Palette LUT as OW instead of US"); + cmd.addOption("--lut-entries-word", "+pe", "write Palette LUT with 16-bit entries"); + cmd.addOption("--floyd-steinberg", "+pf", "use Floyd-Steinberg error diffusion"); + cmd.addOption("--colors", "+pc", 1, "number of colors: 2..65536 (default 256)", + "number of colors to quantize to"); + + cmd.addSubGroup("SOP Class UID:"); + cmd.addOption("--class-default", "+cd", "keep SOP Class UID (default)"); + cmd.addOption("--class-sc", "+cs", "convert to Secondary Capture Image\n(implies --uid-always)"); + + cmd.addSubGroup("SOP Instance UID:"); + cmd.addOption("--uid-always", "+ua", "always assign new UID (default)"); + cmd.addOption("--uid-never", "+un", "never assign new UID"); + + cmd.addGroup("output options:"); + cmd.addSubGroup("output file format:"); + cmd.addOption("--write-file", "+F", "write file format (default)"); + cmd.addOption("--write-dataset", "-F", "write data set without file meta information"); + cmd.addSubGroup("output transfer syntax:"); + cmd.addOption("--write-xfer-same", "+t=", "write with same TS as input (default)"); + cmd.addOption("--write-xfer-little", "+te", "write with explicit VR little endian TS"); + cmd.addOption("--write-xfer-big", "+tb", "write with explicit VR big endian TS"); + cmd.addOption("--write-xfer-implicit", "+ti", "write with implicit VR little endian TS"); + cmd.addSubGroup("post-1993 value representations:"); + cmd.addOption("--enable-new-vr", "+u", "enable support for new VRs (UN/UT) (default)"); + cmd.addOption("--disable-new-vr", "-u", "disable support for new VRs, convert to OB"); + cmd.addSubGroup("group length encoding:"); + cmd.addOption("--group-length-recalc", "+g=", "recalculate group lengths if present (default)"); + cmd.addOption("--group-length-create", "+g", "always write with group length elements"); + cmd.addOption("--group-length-remove", "-g", "always write without group length elements"); + cmd.addSubGroup("length encoding in sequences and items:"); + cmd.addOption("--length-explicit", "+e", "write with explicit lengths (default)"); + cmd.addOption("--length-undefined", "-e", "write with undefined lengths"); + cmd.addSubGroup("data set trailing padding (not with --write-dataset):"); + cmd.addOption("--padding-retain", "-p=", "do not change padding\n(default if not --write-dataset)"); + cmd.addOption("--padding-off", "-p", "no padding (implicit if --write-dataset)"); + cmd.addOption("--padding-create", "+p", 2, "[f]ile-pad [i]tem-pad: integer", + "align file on multiple of f bytes\nand items on multiple of i bytes"); + + if (app.parseCommandLine(cmd, argc, argv)) + { + /* check exclusive options first */ + if (cmd.hasExclusiveOption()) + { + if (cmd.findOption("--version")) + { + app.printHeader(OFTrue /*print host identifier*/); + COUT << OFendl << "External libraries used:"; +#if !defined(WITH_ZLIB) && !defined(BUILD_WITH_DCMJPEG_SUPPORT) + COUT << " none" << OFendl; +#else + COUT << OFendl; +#endif +#ifdef WITH_ZLIB + COUT << "- ZLIB, Version " << zlibVersion() << OFendl; +#endif +#ifdef BUILD_WITH_DCMJPEG_SUPPORT + COUT << "- " << DiJPEGPlugin::getLibraryVersionString() << OFendl; +#endif + return 0; + } + } + + /* command line parameters */ + + cmd.getParam(1, opt_ifname); + cmd.getParam(2, opt_ofname); + + OFLog::configureFromCommandLine(cmd, app); + + cmd.beginOptionBlock(); + if (cmd.findOption("--read-file")) opt_readMode = ERM_autoDetect; + if (cmd.findOption("--read-file-only")) opt_readMode = ERM_fileOnly; + if (cmd.findOption("--read-dataset")) opt_readMode = ERM_dataset; + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--read-xfer-auto")) + opt_ixfer = EXS_Unknown; + if (cmd.findOption("--read-xfer-detect")) + dcmAutoDetectDatasetXfer.set(OFTrue); + if (cmd.findOption("--read-xfer-little")) + { + app.checkDependence("--read-xfer-little", "--read-dataset", opt_readMode == ERM_dataset); + opt_ixfer = EXS_LittleEndianExplicit; + } + if (cmd.findOption("--read-xfer-big")) + { + app.checkDependence("--read-xfer-big", "--read-dataset", opt_readMode == ERM_dataset); + opt_ixfer = EXS_BigEndianExplicit; + } + if (cmd.findOption("--read-xfer-implicit")) + { + app.checkDependence("--read-xfer-implicit", "--read-dataset", opt_readMode == ERM_dataset); + opt_ixfer = EXS_LittleEndianImplicit; + } + cmd.endOptionBlock(); + + if (cmd.findOption("--accept-palettes")) + opt_compatibilityMode |= CIF_WrongPaletteAttributeTags; + + cmd.beginOptionBlock(); + if (cmd.findOption("--frame")) + { + app.checkValue(cmd.getValueAndCheckMin(opt_frame, 1)); + opt_frameCount = 1; + } + if (cmd.findOption("--all-frames")) + { + opt_frame = 1; + opt_frameCount = 0; + } + cmd.endOptionBlock(); + +#ifdef BUILD_WITH_DCMJPEG_SUPPORT + cmd.beginOptionBlock(); + if (cmd.findOption("--conv-photometric")) + opt_decompCSconversion = EDC_photometricInterpretation; + if (cmd.findOption("--conv-lossy")) + opt_decompCSconversion = EDC_lossyOnly; + if (cmd.findOption("--conv-guess")) + opt_decompCSconversion = EDC_guess; + if (cmd.findOption("--conv-guess-lossy")) + opt_decompCSconversion = EDC_guessLossyOnly; + if (cmd.findOption("--conv-always")) + opt_decompCSconversion = EDC_always; + if (cmd.findOption("--conv-never")) + opt_decompCSconversion = EDC_never; + cmd.endOptionBlock(); +#endif + + if (cmd.findOption("--write-ow")) opt_palette_ow = OFTrue; + if (cmd.findOption("--lut-entries-word")) opt_entries_word = OFTrue; + if (cmd.findOption("--floyd-steinberg")) opt_palette_fs = OFTrue; + if (cmd.findOption("--colors")) cmd.getValueAndCheckMinMax(opt_palette_col, 2, 65536); + + cmd.beginOptionBlock(); + if (cmd.findOption("--mc-dimension-rgb")) opt_largeType = DcmLargestDimensionType_default; + if (cmd.findOption("--mc-dimension-lum")) opt_largeType = DcmLargestDimensionType_luminance; + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--mc-color-avgbox")) opt_repType = DcmRepresentativeColorType_default; + if (cmd.findOption("--mc-color-avgpixel")) opt_repType = DcmRepresentativeColorType_averagePixels; + if (cmd.findOption("--mc-color-center")) opt_repType = DcmRepresentativeColorType_centerOfBox; + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--class-default")) opt_secondarycapture = OFFalse; + if (cmd.findOption("--class-sc")) opt_secondarycapture = OFTrue; + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--uid-always")) opt_uidcreation = OFTrue; + if (cmd.findOption("--uid-never")) opt_uidcreation = OFFalse; + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--write-file")) opt_writeMode = EWM_fileformat; + if (cmd.findOption("--write-dataset")) opt_writeMode = EWM_dataset; + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--write-xfer-same")) opt_oxfer = EXS_Unknown; + if (cmd.findOption("--write-xfer-little")) opt_oxfer = EXS_LittleEndianExplicit; + if (cmd.findOption("--write-xfer-big")) opt_oxfer = EXS_BigEndianExplicit; + if (cmd.findOption("--write-xfer-implicit")) opt_oxfer = EXS_LittleEndianImplicit; + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--enable-new-vr")) dcmEnableGenerationOfNewVRs(); + if (cmd.findOption("--disable-new-vr")) dcmDisableGenerationOfNewVRs(); + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--group-length-recalc")) opt_oglenc = EGL_recalcGL; + if (cmd.findOption("--group-length-create")) opt_oglenc = EGL_withGL; + if (cmd.findOption("--group-length-remove")) opt_oglenc = EGL_withoutGL; + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--length-explicit")) opt_oenctype = EET_ExplicitLength; + if (cmd.findOption("--length-undefined")) opt_oenctype = EET_UndefinedLength; + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--padding-retain")) + { + app.checkConflict("--padding-retain", "--write-dataset", opt_writeMode == EWM_dataset); + opt_opadenc = EPD_noChange; + } + if (cmd.findOption("--padding-off")) opt_opadenc = EPD_withoutPadding; + if (cmd.findOption("--padding-create")) + { + app.checkConflict("--padding-create", "--write-dataset", opt_writeMode == EWM_dataset); + app.checkValue(cmd.getValueAndCheckMin(opt_filepad, 0)); + app.checkValue(cmd.getValueAndCheckMin(opt_itempad, 0)); + opt_opadenc = EPD_withPadding; + } + cmd.endOptionBlock(); + } + + /* print resource identifier */ + OFLOG_DEBUG(dcmquantLogger, rcsid << OFendl); + + /* make sure data dictionary is loaded */ + if (!dcmDataDict.isDictionaryLoaded()) + { + OFLOG_WARN(dcmquantLogger, "no data dictionary loaded, check environment variable: " + << DCM_DICT_ENVIRONMENT_VARIABLE); + } + +#ifdef BUILD_WITH_DCMJPEG_SUPPORT + // register global decompression codecs + DJDecoderRegistration::registerCodecs(opt_decompCSconversion); +#endif + + // ====================================================================== + // read input file + + if ((opt_ifname == NULL) || (strlen(opt_ifname) == 0)) + { + OFLOG_FATAL(dcmquantLogger, "invalid filename: "); + return 1; + } + + DcmFileFormat fileformat; + DcmDataset *dataset = fileformat.getDataset(); + + OFCondition error = fileformat.loadFile(opt_ifname, opt_ixfer, EGL_noChange, DCM_MaxReadLength, opt_readMode); + if (error.bad()) + { + OFLOG_FATAL(dcmquantLogger, error.text() << ": reading file: " << opt_ifname); + return 1; + } + + OFLOG_INFO(dcmquantLogger, "load all data into memory"); + + /* make sure that pixel data is loaded before output file is created */ + dataset->loadAllDataIntoMemory(); + + // select uncompressed output transfer syntax. + // this will implicitly decompress the image if necessary. + + if (opt_oxfer == EXS_Unknown) + { + OFLOG_INFO(dcmquantLogger, "set output transfer syntax to input transfer syntax"); + opt_oxfer = dataset->getOriginalXfer(); + } + + OFLOG_INFO(dcmquantLogger, "check if new output transfer syntax is possible"); + + DcmXfer opt_oxferSyn(opt_oxfer); + dataset->chooseRepresentation(opt_oxfer, NULL); + + if (dataset->canWriteXfer(opt_oxfer)) + { + OFLOG_INFO(dcmquantLogger, "output transfer syntax " << opt_oxferSyn.getXferName() + << " can be written"); + } else { + OFLOG_FATAL(dcmquantLogger, "no conversion to transfer syntax " << opt_oxferSyn.getXferName() + << " possible"); + return 1; + } + + // ====================================================================== + // image processing starts here + + OFLOG_INFO(dcmquantLogger, "preparing pixel data."); + + // create DicomImage object + DicomImage di(dataset, opt_oxfer, opt_compatibilityMode, opt_frame - 1, opt_frameCount); + if (di.getStatus() != EIS_Normal) + { + OFLOG_FATAL(dcmquantLogger, DicomImage::getString(di.getStatus())); + return 1; + } + + if (di.isMonochrome()) + { + OFLOG_FATAL(dcmquantLogger, "cannot convert monochrome image to palette color"); + return 1; + } + + OFString derivationDescription; + + // create palette color image + error = DcmQuant::createPaletteColorImage( + di, *dataset, opt_palette_ow, opt_entries_word, opt_palette_fs, opt_palette_col, + derivationDescription, opt_largeType, opt_repType); + + // update image type + if (error.good()) error = DcmCodec::updateImageType(dataset); + + // update derivation description + if (error.good()) error = DcmQuant::updateDerivationDescription(dataset, derivationDescription.c_str()); + + // create new SOP instance UID + if (error.good() && (opt_secondarycapture || opt_uidcreation)) + error = DcmCodec::newInstance(dataset, "DCM", "121320", "Uncompressed predecessor"); + + // convert to Secondary Capture if requested by user. + // This method creates a new SOP class UID, so it should be executed + // after the call to newInstance() which creates a Source Image Sequence. + if (error.good() && opt_secondarycapture) error = DcmCodec::convertToSecondaryCapture(dataset); + + if (error.bad()) + { + OFLOG_FATAL(dcmquantLogger, error.text() << ": converting image: " << opt_ifname); + return 1; + } + + // ====================================================================== + // write back output file + + OFLOG_INFO(dcmquantLogger, "write converted DICOM file"); + + // update file meta information with new SOP Instance UID + if ((opt_uidcreation || opt_secondarycapture) && (opt_writeMode == EWM_fileformat)) + opt_writeMode = EWM_updateMeta; + + error = fileformat.saveFile(opt_ofname, opt_oxfer, opt_oenctype, opt_oglenc, opt_opadenc, + OFstatic_cast(Uint32, opt_filepad), OFstatic_cast(Uint32, opt_itempad), opt_writeMode); + + if (error.bad()) + { + OFLOG_FATAL(dcmquantLogger, error.text() << ": writing file: " << opt_ofname); + return 1; + } + + OFLOG_INFO(dcmquantLogger, "conversion successful"); + +#ifdef BUILD_WITH_DCMJPEG_SUPPORT + // deregister global decompression codecs + DJDecoderRegistration::cleanup(); +#endif + + return 0; +} diff --git a/dcmimage/apps/dcmscale.cc b/dcmimage/apps/dcmscale.cc new file mode 100644 index 00000000..12145c85 --- /dev/null +++ b/dcmimage/apps/dcmscale.cc @@ -0,0 +1,656 @@ +/* + * + * Copyright (C) 2002-2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimage + * + * Authors: Joerg Riesmeier + * + * Purpose: Scale DICOM images + * + */ + + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#define INCLUDE_CSTDIO +#define INCLUDE_CSTRING +#include "dcmtk/ofstd/ofstdinc.h" + +#ifdef HAVE_GUSI_H +#include +#endif + +#include "dcmtk/dcmdata/dctk.h" /* for various dcmdata headers */ +#include "dcmtk/dcmdata/cmdlnarg.h" /* for prepareCmdLineArgs */ +#include "dcmtk/dcmdata/dcuid.h" /* for dcmtk version name */ + +#include "dcmtk/ofstd/ofconapp.h" /* for OFConsoleApplication */ +#include "dcmtk/ofstd/ofcmdln.h" /* for OFCommandLine */ + +#include "dcmtk/oflog/oflog.h" /* for OFLogger */ + +#include "dcmtk/dcmimgle/dcmimage.h" /* for DicomImage */ +#include "dcmtk/dcmimage/diregist.h" /* include to support color images */ +#include "dcmtk/dcmdata/dcrledrg.h" /* for DcmRLEDecoderRegistration */ + +#ifdef BUILD_DCMSCALE_AS_DCMJSCAL +#include "dcmtk/dcmjpeg/djdecode.h" /* for dcmjpeg decoders */ +#include "dcmtk/dcmjpeg/dipijpeg.h" /* for dcmimage JPEG plugin */ +#endif + +#ifdef WITH_ZLIB +#include /* for zlibVersion() */ +#endif + +#define OFFIS_CONSOLE_DESCRIPTION "Scale DICOM images" + +#ifdef BUILD_DCMSCALE_AS_DCMJSCAL +#define OFFIS_CONSOLE_APPLICATION "dcmjscal" +#else +#define OFFIS_CONSOLE_APPLICATION "dcmscale" +#endif + +static OFLogger dcmscaleLogger = OFLog::getLogger("dcmtk.apps." OFFIS_CONSOLE_APPLICATION); + +static char rcsid[] = "$dcmtk: " OFFIS_CONSOLE_APPLICATION " v" + OFFIS_DCMTK_VERSION " " OFFIS_DCMTK_RELEASEDATE " $"; + +#define SHORTCOL 4 +#define LONGCOL 21 + + +// ******************************************** + +int main(int argc, char *argv[]) +{ + OFConsoleApplication app(OFFIS_CONSOLE_APPLICATION, OFFIS_CONSOLE_DESCRIPTION, rcsid); + OFCommandLine cmd; + + OFBool opt_uidCreation = OFTrue; + E_FileReadMode opt_readMode = ERM_autoDetect; + E_FileWriteMode opt_writeMode = EWM_fileformat; + E_TransferSyntax opt_ixfer = EXS_Unknown; + E_TransferSyntax opt_oxfer = EXS_Unknown; + E_GrpLenEncoding opt_oglenc = EGL_recalcGL; + E_EncodingType opt_oenctype = EET_ExplicitLength; + E_PaddingEncoding opt_opadenc = EPD_noChange; + OFCmdUnsignedInt opt_filepad = 0; + OFCmdUnsignedInt opt_itempad = 0; + +#ifdef BUILD_DCMSCALE_AS_DCMJSCAL + // JPEG parameters, currently not used +# if 0 + OFCmdUnsignedInt opt_quality = 90; /* default: 90% JPEG quality */ + E_SubSampling opt_sampling = ESS_422; /* default: 4:2:2 sub-sampling */ +# endif + E_DecompressionColorSpaceConversion opt_decompCSconversion = EDC_photometricInterpretation; +#endif + + int opt_useAspectRatio = 1; /* default: use aspect ratio for scaling */ + OFCmdUnsignedInt opt_useInterpolation = 1; /* default: use interpolation method '1' for scaling */ + int opt_scaleType = 0; /* default: no scaling */ + /* 1 = X-factor, 2 = Y-factor, 3=X-size, 4=Y-size */ + OFCmdFloat opt_scale_factor = 1.0; + OFCmdUnsignedInt opt_scale_size = 1; + + OFBool opt_useClip = OFFalse; /* default: don't clip */ + OFCmdSignedInt opt_left = 0, opt_top = 0; /* clip region (origin) */ + OFCmdUnsignedInt opt_width = 0, opt_height = 0; /* clip region (extension) */ + + const char *opt_ifname = NULL; + const char *opt_ofname = NULL; + + prepareCmdLineArgs(argc, argv, OFFIS_CONSOLE_APPLICATION); + cmd.setOptionColumns(LONGCOL, SHORTCOL); + + cmd.addParam("dcmfile-in", "DICOM input filename to be scaled"); + cmd.addParam("dcmfile-out", "DICOM output filename to be written"); + + cmd.addGroup("general options:", LONGCOL, SHORTCOL + 2); + cmd.addOption("--help", "-h", "print this help text and exit", OFCommandLine::AF_Exclusive); + cmd.addOption("--version", "print version information and exit", OFCommandLine::AF_Exclusive); + OFLog::addOptions(cmd); + + cmd.addGroup("input options:"); + cmd.addSubGroup("input file format:"); + cmd.addOption("--read-file", "+f", "read file format or data set (default)"); + cmd.addOption("--read-file-only", "+fo", "read file format only"); + cmd.addOption("--read-dataset", "-f", "read data set without file meta information"); + cmd.addSubGroup("input transfer syntax:"); + cmd.addOption("--read-xfer-auto", "-t=", "use TS recognition (default)"); + cmd.addOption("--read-xfer-detect", "-td", "ignore TS specified in the file meta header"); + cmd.addOption("--read-xfer-little", "-te", "read with explicit VR little endian TS"); + cmd.addOption("--read-xfer-big", "-tb", "read with explicit VR big endian TS"); + cmd.addOption("--read-xfer-implicit", "-ti", "read with implicit VR little endian TS"); + + cmd.addGroup("image processing and encoding options:"); +#ifdef BUILD_DCMSCALE_AS_DCMJSCAL + cmd.addSubGroup("color space conversion options (compressed images only):"); + cmd.addOption("--conv-photometric", "+cp", "convert if YCbCr photometric interpr. (default)"); + cmd.addOption("--conv-lossy", "+cl", "convert YCbCr to RGB if lossy JPEG"); + cmd.addOption("--conv-guess", "+cg", "convert to RGB if YCbCr is guessed by library"); + cmd.addOption("--conv-guess-lossy", "+cgl", "convert to RGB if lossy JPEG and YCbCr is\nguessed by the underlying JPEG library"); + cmd.addOption("--conv-always", "+ca", "always convert YCbCr to RGB"); + cmd.addOption("--conv-never", "+cn", "never convert color space"); +#endif + cmd.addSubGroup("scaling:"); + cmd.addOption("--recognize-aspect", "+a", "recognize pixel aspect ratio (default)"); + cmd.addOption("--ignore-aspect", "-a", "ignore pixel aspect ratio when scaling"); + cmd.addOption("--interpolate", "+i", 1, "[n]umber of algorithm: integer", + "use interpolation when scaling (1..4, def: 1)"); + cmd.addOption("--no-interpolation", "-i", "no interpolation when scaling"); + cmd.addOption("--no-scaling", "-S", "no scaling, ignore pixel aspect ratio (default)"); + cmd.addOption("--scale-x-factor", "+Sxf", 1, "[f]actor: float", + "scale x axis by factor, auto-compute y axis"); + cmd.addOption("--scale-y-factor", "+Syf", 1, "[f]actor: float", + "scale y axis by factor, auto-compute x axis"); + cmd.addOption("--scale-x-size", "+Sxv", 1, "[n]umber: integer", + "scale x axis to n pixels, auto-compute y axis"); + cmd.addOption("--scale-y-size", "+Syv", 1, "[n]umber: integer", + "scale y axis to n pixels, auto-compute x axis"); + cmd.addSubGroup("other transformations:"); + cmd.addOption("--clip-region", "+C", 4, "[l]eft [t]op [w]idth [h]eight: integer", + "clip rectangular image region (l, t, w, h)"); + cmd.addSubGroup("SOP Instance UID:"); + cmd.addOption("--uid-always", "+ua", "always assign new SOP Instance UID (default)"); + cmd.addOption("--uid-never", "+un", "never assign new SOP Instance UID"); + + cmd.addGroup("output options:"); + cmd.addSubGroup("output file format:"); + cmd.addOption("--write-file", "+F", "write file format (default)"); + cmd.addOption("--write-dataset", "-F", "write data set without file meta information"); + cmd.addSubGroup("output transfer syntax:"); + cmd.addOption("--write-xfer-same", "+t=", "write with same TS as input (default)"); + cmd.addOption("--write-xfer-little", "+te", "write with explicit VR little endian TS"); + cmd.addOption("--write-xfer-big", "+tb", "write with explicit VR big endian TS"); + cmd.addOption("--write-xfer-implicit", "+ti", "write with implicit VR little endian TS"); + cmd.addSubGroup("post-1993 value representations:"); + cmd.addOption("--enable-new-vr", "+u", "enable support for new VRs (UN/UT) (default)"); + cmd.addOption("--disable-new-vr", "-u", "disable support for new VRs, convert to OB"); + cmd.addSubGroup("group length encoding:"); + cmd.addOption("--group-length-recalc", "+g=", "recalculate group lengths if present (default)"); + cmd.addOption("--group-length-create", "+g", "always write with group length elements"); + cmd.addOption("--group-length-remove", "-g", "always write without group length elements"); + cmd.addSubGroup("length encoding in sequences and items:"); + cmd.addOption("--length-explicit", "+e", "write with explicit lengths (default)"); + cmd.addOption("--length-undefined", "-e", "write with undefined lengths"); + cmd.addSubGroup("data set trailing padding (not with --write-dataset):"); + cmd.addOption("--padding-retain", "-p=", "do not change padding\n(default if not --write-dataset)"); + cmd.addOption("--padding-off", "-p", "no padding (implicit if --write-dataset)"); + cmd.addOption("--padding-create", "+p", 2, "[f]ile-pad [i]tem-pad: integer", + "align file on multiple of f bytes\nand items on multiple of i bytes"); + + if (app.parseCommandLine(cmd, argc, argv)) + { + /* check exclusive options first */ + if (cmd.hasExclusiveOption()) + { + if (cmd.findOption("--version")) + { + app.printHeader(OFTrue /*print host identifier*/); + COUT << OFendl << "External libraries used:"; +#if !defined(WITH_ZLIB) && !defined(BUILD_DCMSCALE_AS_DCMJSCAL) + COUT << " none" << OFendl; +#else + COUT << OFendl; +#endif +#ifdef WITH_ZLIB + COUT << "- ZLIB, Version " << zlibVersion() << OFendl; +#endif +#ifdef BUILD_DCMSCALE_AS_DCMJSCAL + COUT << "- " << DiJPEGPlugin::getLibraryVersionString() << OFendl; +#endif + return 0; + } + } + + /* command line parameters */ + + cmd.getParam(1, opt_ifname); + cmd.getParam(2, opt_ofname); + + /* general options */ + + OFLog::configureFromCommandLine(cmd, app); + + /* input options */ + + cmd.beginOptionBlock(); + if (cmd.findOption("--read-file")) opt_readMode = ERM_autoDetect; + if (cmd.findOption("--read-file-only")) opt_readMode = ERM_fileOnly; + if (cmd.findOption("--read-dataset")) opt_readMode = ERM_dataset; + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--read-xfer-auto")) + opt_ixfer = EXS_Unknown; + if (cmd.findOption("--read-xfer-detect")) + dcmAutoDetectDatasetXfer.set(OFTrue); + if (cmd.findOption("--read-xfer-little")) + { + app.checkDependence("--read-xfer-little", "--read-dataset", opt_readMode == ERM_dataset); + opt_ixfer = EXS_LittleEndianExplicit; + } + if (cmd.findOption("--read-xfer-big")) + { + app.checkDependence("--read-xfer-big", "--read-dataset", opt_readMode == ERM_dataset); + opt_ixfer = EXS_BigEndianExplicit; + } + if (cmd.findOption("--read-xfer-implicit")) + { + app.checkDependence("--read-xfer-implicit", "--read-dataset", opt_readMode == ERM_dataset); + opt_ixfer = EXS_LittleEndianImplicit; + } + cmd.endOptionBlock(); + + /* image processing options: color space conversion */ + +#ifdef BUILD_DCMSCALE_AS_DCMJSCAL + cmd.beginOptionBlock(); + if (cmd.findOption("--conv-photometric")) + opt_decompCSconversion = EDC_photometricInterpretation; + if (cmd.findOption("--conv-lossy")) + opt_decompCSconversion = EDC_lossyOnly; + if (cmd.findOption("--conv-guess")) + opt_decompCSconversion = EDC_guess; + if (cmd.findOption("--conv-guess-lossy")) + opt_decompCSconversion = EDC_guessLossyOnly; + if (cmd.findOption("--conv-always")) + opt_decompCSconversion = EDC_always; + if (cmd.findOption("--conv-never")) + opt_decompCSconversion = EDC_never; + cmd.endOptionBlock(); +#endif + + /* image processing options: scaling */ + + cmd.beginOptionBlock(); + if (cmd.findOption("--recognize-aspect")) + opt_useAspectRatio = 1; + if (cmd.findOption("--ignore-aspect")) + opt_useAspectRatio = 0; + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--interpolate")) + app.checkValue(cmd.getValueAndCheckMinMax(opt_useInterpolation, 1, 4)); + if (cmd.findOption("--no-interpolation")) + opt_useInterpolation = 0; + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--no-scaling")) + opt_scaleType = 0; + if (cmd.findOption("--scale-x-factor")) + { + opt_scaleType = 1; + app.checkValue(cmd.getValueAndCheckMin(opt_scale_factor, 0.0, OFFalse)); + } + if (cmd.findOption("--scale-y-factor")) + { + opt_scaleType = 2; + app.checkValue(cmd.getValueAndCheckMin(opt_scale_factor, 0.0, OFFalse)); + } + if (cmd.findOption("--scale-x-size")) + { + opt_scaleType = 3; + app.checkValue(cmd.getValueAndCheckMin(opt_scale_size, 1)); + } + if (cmd.findOption("--scale-y-size")) + { + opt_scaleType = 4; + app.checkValue(cmd.getValueAndCheckMin(opt_scale_size, 1)); + } + cmd.endOptionBlock(); + + /* image processing options: other transformations */ + + if (cmd.findOption("--clip-region")) + { + app.checkValue(cmd.getValue(opt_left)); + app.checkValue(cmd.getValue(opt_top)); + app.checkValue(cmd.getValue(opt_width)); + app.checkValue(cmd.getValue(opt_height)); + opt_useClip = OFTrue; + } + + /* image processing options: SOP Instance UID options */ + + cmd.beginOptionBlock(); + if (cmd.findOption("--uid-always")) opt_uidCreation = OFTrue; + if (cmd.findOption("--uid-never")) opt_uidCreation = OFFalse; + cmd.endOptionBlock(); + + /* output options */ + + cmd.beginOptionBlock(); + if (cmd.findOption("--write-file")) opt_writeMode = EWM_fileformat; + if (cmd.findOption("--write-dataset")) opt_writeMode = EWM_dataset; + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--write-xfer-same")) opt_oxfer = EXS_Unknown; + if (cmd.findOption("--write-xfer-little")) opt_oxfer = EXS_LittleEndianExplicit; + if (cmd.findOption("--write-xfer-big")) opt_oxfer = EXS_BigEndianExplicit; + if (cmd.findOption("--write-xfer-implicit")) opt_oxfer = EXS_LittleEndianImplicit; + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--enable-new-vr")) dcmEnableGenerationOfNewVRs(); + if (cmd.findOption("--disable-new-vr")) dcmDisableGenerationOfNewVRs(); + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--group-length-recalc")) opt_oglenc = EGL_recalcGL; + if (cmd.findOption("--group-length-create")) opt_oglenc = EGL_withGL; + if (cmd.findOption("--group-length-remove")) opt_oglenc = EGL_withoutGL; + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--length-explicit")) opt_oenctype = EET_ExplicitLength; + if (cmd.findOption("--length-undefined")) opt_oenctype = EET_UndefinedLength; + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--padding-retain")) + { + app.checkConflict("--padding-retain", "--write-dataset", opt_writeMode == EWM_dataset); + opt_opadenc = EPD_noChange; + } + if (cmd.findOption("--padding-off")) opt_opadenc = EPD_withoutPadding; + if (cmd.findOption("--padding-create")) + { + app.checkConflict("--padding-create", "--write-dataset", opt_writeMode == EWM_dataset); + app.checkValue(cmd.getValueAndCheckMin(opt_filepad, 0)); + app.checkValue(cmd.getValueAndCheckMin(opt_itempad, 0)); + opt_opadenc = EPD_withPadding; + } + cmd.endOptionBlock(); + } + + /* print resource identifier */ + OFLOG_DEBUG(dcmscaleLogger, rcsid << OFendl); + + /* make sure data dictionary is loaded */ + if (!dcmDataDict.isDictionaryLoaded()) + { + OFLOG_WARN(dcmscaleLogger, "no data dictionary loaded, check environment variable: " + << DCM_DICT_ENVIRONMENT_VARIABLE); + } + + // register RLE decompression codec + DcmRLEDecoderRegistration::registerCodecs(); +#ifdef BUILD_DCMSCALE_AS_DCMJSCAL + // register global decompression codecs + DJDecoderRegistration::registerCodecs(opt_decompCSconversion); +#endif + + // ====================================================================== + // read input file + + if ((opt_ifname == NULL) || (strlen(opt_ifname) == 0)) + { + OFLOG_FATAL(dcmscaleLogger, "invalid input filename: "); + return 1; + } + + /* no clipping/scaling */ + if (!opt_scaleType && !opt_useClip) + { + OFLOG_FATAL(dcmscaleLogger, "nothing to do"); + return 1; + } + + OFLOG_INFO(dcmscaleLogger, "open input file " << opt_ifname); + + DcmFileFormat fileformat; + DcmDataset *dataset = fileformat.getDataset(); + + OFCondition error = fileformat.loadFile(opt_ifname, opt_ixfer, EGL_noChange, DCM_MaxReadLength, opt_readMode); + if (error.bad()) + { + OFLOG_FATAL(dcmscaleLogger, error.text() << ": reading file: " << opt_ifname); + return 1; + } + + OFLOG_INFO(dcmscaleLogger, "load all data into memory"); + + /* make sure that pixel data is loaded before output file is created */ + dataset->loadAllDataIntoMemory(); + + // select uncompressed output transfer syntax. + // this will implicitly decompress the image if necessary. + + if (opt_oxfer == EXS_Unknown) + { + OFLOG_INFO(dcmscaleLogger, "set output transfer syntax to input transfer syntax"); + opt_oxfer = dataset->getOriginalXfer(); + } + + OFLOG_INFO(dcmscaleLogger, "check if new output transfer syntax is possible"); + + DcmXfer opt_oxferSyn(opt_oxfer); + dataset->chooseRepresentation(opt_oxfer, NULL); + + if (dataset->canWriteXfer(opt_oxfer)) + { + OFLOG_INFO(dcmscaleLogger, "output transfer syntax " << opt_oxferSyn.getXferName() + << " can be written"); + } else { + OFLOG_FATAL(dcmscaleLogger, "no conversion to transfer syntax " << opt_oxferSyn.getXferName() + << " possible"); + return 1; + } + + // ====================================================================== + // image processing starts here + + OFLOG_INFO(dcmscaleLogger, "preparing pixel data"); + + const unsigned long flags = (opt_scaleType > 0) ? CIF_MayDetachPixelData : 0; + // create DicomImage object + DicomImage *di = new DicomImage(dataset, opt_oxfer, flags); + if (di == NULL) + { + OFLOG_FATAL(dcmscaleLogger, "memory exhausted"); + return 1; + } + if (di->getStatus() != EIS_Normal) + { + OFLOG_FATAL(dcmscaleLogger, DicomImage::getString(di->getStatus())); + return 1; + } + + DicomImage *newimage = NULL; + OFString derivationDescription; + + if (opt_useClip) + OFLOG_INFO(dcmscaleLogger, "clipping image to (" << opt_left << "," << opt_top + << "," << opt_width << "," << opt_height << ")"); + // perform clipping (without scaling) + if (opt_scaleType <= 0) + { + if (opt_useClip) + { + newimage = di->createClippedImage(opt_left, opt_top, opt_width, opt_height); + derivationDescription = "Clipped rectangular image region"; + } + } + // perform scaling (and possibly clipping) + else if (opt_scaleType <= 4) + { + switch (opt_scaleType) + { + case 1: + OFLOG_INFO(dcmscaleLogger, "scaling image, X factor=" << opt_scale_factor + << ", Interpolation=" << OFstatic_cast(int, opt_useInterpolation) + << ", Aspect Ratio=" << (opt_useAspectRatio ? "yes" : "no")); + if (opt_useClip) + newimage = di->createScaledImage(opt_left, opt_top, opt_width, opt_height, opt_scale_factor, 0.0, + OFstatic_cast(int, opt_useInterpolation), opt_useAspectRatio); + else + newimage = di->createScaledImage(opt_scale_factor, 0.0, OFstatic_cast(int, opt_useInterpolation), + opt_useAspectRatio); + break; + case 2: + OFLOG_INFO(dcmscaleLogger, "scaling image, Y factor=" << opt_scale_factor + << ", Interpolation=" << OFstatic_cast(int, opt_useInterpolation) + << ", Aspect Ratio=" << (opt_useAspectRatio ? "yes" : "no")); + if (opt_useClip) + newimage = di->createScaledImage(opt_left, opt_top, opt_width, opt_height, 0.0, opt_scale_factor, + OFstatic_cast(int, opt_useInterpolation), opt_useAspectRatio); + else + newimage = di->createScaledImage(0.0, opt_scale_factor, OFstatic_cast(int, opt_useInterpolation), + opt_useAspectRatio); + break; + case 3: + OFLOG_INFO(dcmscaleLogger, "scaling image, X size=" << opt_scale_size + << ", Interpolation=" << OFstatic_cast(int, opt_useInterpolation) + << ", Aspect Ratio=" << (opt_useAspectRatio ? "yes" : "no")); + if (opt_useClip) + newimage = di->createScaledImage(opt_left, opt_top, opt_width, opt_height, opt_scale_size, 0, + OFstatic_cast(int, opt_useInterpolation), opt_useAspectRatio); + else + newimage = di->createScaledImage(opt_scale_size, 0, OFstatic_cast(int, opt_useInterpolation), + opt_useAspectRatio); + break; + case 4: + OFLOG_INFO(dcmscaleLogger, "scaling image, Y size=" << opt_scale_size + << ", Interpolation=" << OFstatic_cast(int, opt_useInterpolation) + << ", Aspect Ratio=" << (opt_useAspectRatio ? "yes" : "no")); + if (opt_useClip) + newimage = di->createScaledImage(opt_left, opt_top, opt_width, opt_height, 0, opt_scale_size, + OFstatic_cast(int, opt_useInterpolation), opt_useAspectRatio); + else + newimage = di->createScaledImage(0, opt_scale_size, OFstatic_cast(int, opt_useInterpolation), + opt_useAspectRatio); + break; + default: + break; + } + if (opt_useClip) + derivationDescription = "Scaled rectangular image region"; + else + derivationDescription = "Scaled image"; + } + if (opt_scaleType > 4) + OFLOG_ERROR(dcmscaleLogger, "internal error: unknown scaling type"); + else if (newimage == NULL) + { + OFLOG_FATAL(dcmscaleLogger, "cannot create new image"); + return 1; + } + else if (newimage->getStatus() != EIS_Normal) + { + OFLOG_FATAL(dcmscaleLogger, DicomImage::getString(newimage->getStatus())); + return 1; + } + /* write scaled image to dataset (update attributes of Image Pixel Module) */ + else if (!newimage->writeImageToDataset(*dataset)) + { + OFLOG_FATAL(dcmscaleLogger, "cannot write new image to dataset"); + return 1; + } + delete newimage; + + /* cleanup original image */ + delete di; + + // ====================================================================== + // update some header attributes + + // update Derivation Description + if (!derivationDescription.empty()) + { + const char *oldDerivation = NULL; + if (dataset->findAndGetString(DCM_DerivationDescription, oldDerivation).good()) + { + // append old Derivation Description, if any + derivationDescription += " ["; + derivationDescription += oldDerivation; + derivationDescription += "]"; + if (derivationDescription.length() > 1024) + { + // ST is limited to 1024 characters, cut off tail + derivationDescription.erase(1020); + derivationDescription += "...]"; + } + } + dataset->putAndInsertString(DCM_DerivationDescription, derivationDescription.c_str()); + } + + // update Image Type + OFString imageType = "DERIVED"; + const char *oldImageType = NULL; + if (dataset->findAndGetString(DCM_ImageType, oldImageType).good()) + { + if (oldImageType != NULL) + { + // append old image type information beginning with second entry + const char *pos = strchr(oldImageType, '\\'); + if (pos != NULL) + imageType += pos; + } + } + dataset->putAndInsertString(DCM_ImageType, imageType.c_str()); + + // update SOP Instance UID + if (opt_uidCreation) + { + // add reference to source image + DcmItem *ditem = NULL; + const char *sopClassUID = NULL; + const char *sopInstanceUID = NULL; + if (dataset->findAndGetString(DCM_SOPClassUID, sopClassUID).good() && + dataset->findAndGetString(DCM_SOPInstanceUID, sopInstanceUID).good()) + { + dataset->findAndDeleteElement(DCM_SourceImageSequence); + if (dataset->findOrCreateSequenceItem(DCM_SourceImageSequence, ditem).good()) + { + ditem->putAndInsertString(DCM_SOPClassUID, sopClassUID); + ditem->putAndInsertString(DCM_SOPInstanceUID, sopInstanceUID); + } + } + // create new SOP instance UID + char new_uid[100]; + dataset->putAndInsertString(DCM_SOPInstanceUID, dcmGenerateUniqueIdentifier(new_uid)); + // force meta-header to refresh SOP Instance UID + if (opt_writeMode == EWM_fileformat) + opt_writeMode = EWM_updateMeta; + } + + // ====================================================================== + // write back output file + + OFLOG_INFO(dcmscaleLogger, "create output file " << opt_ofname); + + error = fileformat.saveFile(opt_ofname, opt_oxfer, opt_oenctype, opt_oglenc, opt_opadenc, + OFstatic_cast(Uint32, opt_filepad), OFstatic_cast(Uint32, opt_itempad), opt_writeMode); + + if (error.bad()) + { + OFLOG_FATAL(dcmscaleLogger, error.text() << ": writing file: " << opt_ofname); + return 1; + } + + OFLOG_INFO(dcmscaleLogger, "conversion successful"); + + // deregister RLE decompression codec + DcmRLEDecoderRegistration::cleanup(); +#ifdef BUILD_DCMSCALE_AS_DCMJSCAL + // deregister global decompression codecs + DJDecoderRegistration::cleanup(); +#endif + + return 0; +} diff --git a/dcmimage/configure b/dcmimage/configure new file mode 100755 index 00000000..396668ee --- /dev/null +++ b/dcmimage/configure @@ -0,0 +1,56 @@ +#! /bin/sh + +parentdir=`pwd` +thisdir=$parentdir + +# The following test constructs relative path from the module +# directory to the configuration directory. If you know this path +# you can substitute this with +# configdir= +# It is very important that the configdir path is relative. + +configdir="configdir" + +while test "$parentdir" != "/" -a "$configdir" = "configdir"; do + if test -d "$parentdir/config" ; then + configdir=$parentdir/config + else + parentdir=`echo $parentdir | sed 's/\/[^\/]*$//'` + fi +done + +if test "$configdir" = "configdir" ; then + echo "Cannot find configure directory" + exit 1 +fi + +if test $# != 0; then + case $1 in + -a) + shift + cd "$configdir" + echo "running configure in config-directory" + ./configure $* + cd $thisdir + echo "running configure for this module" + sh "$configdir/confmod" --srcdir=. $* + ;; + -c) + shift + cd "$configdir" + echo "running configure in config-directory" + ./configure $* + ;; + *) + echo "running configure for this module" + sh "$configdir/confmod" --srcdir=. $* + ;; + esac +else + echo "running configure for this module" + sh "$configdir/confmod" --srcdir=. $* +fi + + + + diff --git a/dcmimage/data/Makefile.in b/dcmimage/data/Makefile.in new file mode 100644 index 00000000..d2fd21f1 --- /dev/null +++ b/dcmimage/data/Makefile.in @@ -0,0 +1,23 @@ +# +# Makefile for dcmimage/data +# + +@SET_MAKE@ + +SHELL = /bin/sh +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +configdir = @top_srcdir@/@configdir@ + +include $(configdir)/@common_makefile@ + + +all: + +install: + +clean: + rm -f $(TRASH) + +distclean: + rm -f $(DISTTRASH) diff --git a/dcmimage/docs/Makefile.in b/dcmimage/docs/Makefile.in new file mode 100644 index 00000000..91c2c5e8 --- /dev/null +++ b/dcmimage/docs/Makefile.in @@ -0,0 +1,23 @@ +# +# Makefile for dcmimage/docs +# + +@SET_MAKE@ + +SHELL = /bin/sh +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +configdir = @top_srcdir@/@configdir@ + +include $(configdir)/@common_makefile@ + + +all: + +install: + +clean: + rm -f $(TRASH) + +distclean: + rm -f $(DISTTRASH) diff --git a/dcmimage/docs/dcm2pnm.man b/dcmimage/docs/dcm2pnm.man new file mode 100644 index 00000000..52ab5379 --- /dev/null +++ b/dcmimage/docs/dcm2pnm.man @@ -0,0 +1,502 @@ +/*! + +\if MANPAGES +\page dcm2pnm Convert DICOM images to PGM/PPM, PNG, TIFF or BMP +\else +\page dcm2pnm dcm2pnm: Convert DICOM images to PGM/PPM, PNG, TIFF or BMP +\endif + +\section synopsis SYNOPSIS + +\verbatim +dcm2pnm [options] dcmfile-in [bitmap-out] +\endverbatim + +\section description DESCRIPTION + +The \b dcm2pnm utility reads a DICOM image, converts the pixel data according +to the selected image processing options and writes back an image in the +well-known PGM/PPM (portable gray map / portable pix map), PNG, TIFF or +Windows BMP format. This utility only supports uncompressed and RLE +compressed DICOM images. The command line tool \b dcmj2pnm also supports a +number of JPEG compression schemes. + +\section parameters PARAMETERS + +\verbatim +dcmfile-in DICOM input filename to be converted + +bitmap-out output filename to be written (default: stdout) +\endverbatim + +\section options OPTIONS + +\subsection general_options general options +\verbatim + -h --help + print this help text and exit + + --version + print version information and exit + + --arguments + print expanded command line arguments + + -q --quiet + quiet mode, print no warnings and errors + + -v --verbose + verbose mode, print processing details + + -d --debug + debug mode, print debug information + + -ll --log-level [l]evel: string constant + (fatal, error, warn, info, debug, trace) + use level l for the logger + + -lc --log-config [f]ilename: string + use config file f for the logger +\endverbatim + +\subsection input_options input options +\verbatim +input file format: + + +f --read-file + read file format or data set (default) + + +fo --read-file-only + read file format only + + -f --read-dataset + read data set without file meta information + +input transfer syntax: + + -t= --read-xfer-auto + use TS recognition (default) + + -td --read-xfer-detect + ignore TS specified in the file meta header + + -te --read-xfer-little + read with explicit VR little endian TS + + -tb --read-xfer-big + read with explicit VR big endian TS + + -ti --read-xfer-implicit + read with implicit VR little endian TS +\endverbatim + +\subsection image_processing_options image processing options +\verbatim +frame selection: + + +F --frame [n]umber: integer + select specified frame (default: 1) + + +Fr --frame-range [n]umber [c]ount: integer + select c frames beginning with frame n + + +Fa --all-frames + select all frames + +rotation: + + +Rl --rotate-left + rotate image left (-90 degrees) + + +Rr --rotate-right + rotate image right (+90 degrees) + + +Rtd --rotate-top-down + rotate image top-down (180 degrees) + +flipping: + + +Lh --flip-horizontally + flip image horizontally + + +Lv --flip-vertically + flip image vertically + + +Lhv --flip-both-axes + flip image horizontally and vertically + +scaling: + + +a --recognize-aspect + recognize pixel aspect ratio (default) + + -a --ignore-aspect + ignore pixel aspect ratio when scaling + + +i --interpolate [n]umber of algorithm: integer + use interpolation when scaling (1..4, default: 1) + + -i --no-interpolation + no interpolation when scaling + + -S --no-scaling + no scaling, ignore pixel aspect ratio (default) + + +Sxf --scale-x-factor [f]actor: float + scale x axis by factor, auto-compute y axis + + +Syf --scale-y-factor [f]actor: float + scale y axis by factor, auto-compute x axis + + +Sxv --scale-x-size [n]umber: integer + scale x axis to n pixels, auto-compute y axis + + +Syv --scale-y-size [n]umber: integer + scale y axis to n pixels, auto-compute x axis + +modality LUT transformation: + + -M --no-modality + ignore stored modality LUT transformation + + +M --use-modality + use modality LUT transformation (default) + +VOI LUT transformation: + + -W --no-windowing + no VOI windowing (default) + + +Wi --use-window [n]umber: integer + use the n-th VOI window from image file + + +Wl --use-voi-lut [n]umber: integer + use the n-th VOI look up table from image file + + +Wm --min-max-window + compute VOI window using min-max algorithm + + +Wn --min-max-window-n + compute VOI window using min-max algorithm, + ignoring extreme values + + +Wr --roi-min-max-window [l]eft [t]op [w]idth [h]eight: integer + compute ROI window using min-max algorithm, + region of interest is specified by l,t,w,h + + +Wh --histogram-window [n]umber: integer + compute VOI window using Histogram algorithm, + ignoring n percent + + +Ww --set-window [c]enter [w]idth: float + compute VOI window using center c and width w + + +Wfl --linear-function + set VOI LUT function to LINEAR + + +Wfs --sigmoid-function + set VOI LUT function to SIGMOID + +presentation LUT transformation: + + +Pid --identity-shape + set presentation LUT shape to IDENTITY + + +Piv --inverse-shape + set presentation LUT shape to INVERSE + + +Pod --lin-od-shape + set presentation LUT shape to LIN OD + +overlay: + + -O --no-overlays + do not display overlays + + +O --display-overlay [n]umber: integer + display overlay n (0..16, 0=all, default: +O 0) + + +Omr --ovl-replace + use overlay mode "Replace" + (default for Graphic overlays) + + +Omt --ovl-threshold + use overlay mode "Threshold Replace" + + +Omc --ovl-complement + use overlay mode "Complement" + + +Omv --ovl-invert + use overlay mode "Invert Bitmap" + + +Omi --ovl-roi + use overlay mode "Region of Interest" + (default for ROI overlays) + + +Osf --set-foreground [d]ensity: float + set overlay foreground density (0..1, default: 1) + + +Ost --set-threshold [d]ensity: float + set overlay threshold density (0..1, default: 0.5) + +display LUT transformation: + + +Dm --monitor-file [f]ilename: string + calibrate output according to monitor characteristics + defined in f + + +Dp --printer-file [f]ilename: string + calibrate output according to printer characteristics + defined in f + + +Da --ambient-light [a]mbient light: float + ambient light value (cd/m^2, default: file f) + + +Di --illumination [i]llumination: float + illumination value (cd/m^2, default: file f) + + +Dn --min-density [m]inimum optical density: float + Dmin value (default: off, only with +Dp) + + +Dx --max-density [m]aximum optical density: float + Dmax value (default: off, only with +Dp) + + +Dg --gsd-function + use GSDF for calibration (default for +Dm/+Dp) + + +Dc --cielab-function + use CIELAB function for calibration + +compatibility: + + +Ma --accept-acr-nema + accept ACR-NEMA images without photometric + interpretation + + +Mp --accept-palettes + accept incorrect palette attribute tags + (0028,111x) and (0028,121x) + + +Mc --check-lut-depth + check 3rd value of the LUT descriptor, compare + with expected bit depth based on LUT data + + +Mm --ignore-mlut-depth + ignore 3rd value of the modality LUT descriptor, + determine bits per table entry automatically + + +Mv --ignore-vlut-depth + ignore 3rd value of the VOI LUT descriptor, + determine bits per table entry automatically + +TIFF format: + + +Tl --compr-lzw + LZW compression (default) + + +Tr --compr-rle + RLE compression + + +Tn --compr-none + uncompressed + + +Pd --predictor-default + no LZW predictor (default) + + +Pn --predictor-none + LZW predictor 1 (no prediction) + + +Ph --predictor-horz + LZW predictor 2 (horizontal differencing) + + +Rs --rows-per-strip [r]ows: integer (default: 0) + rows per strip, default 8K per strip + +PNG format: + + +il --interlace + create interlaced file (default) + + -il --nointerlace + create non-interlaced file + + +mf --meta-file + create PNG file meta information (default) + + -mf --meta-none + no PNG file meta information + +other transformations: + + +G --grayscale + convert to grayscale if necessary + + +P --change-polarity + change polarity (invert pixel output) + + +C --clip-region [l]eft [t]op [w]idth [h]eight: integer + clip image region (l, t, w, h) +\endverbatim + +\subsection output_options output options +\verbatim +general: + + -im --image-info + print image details (requires verbose mode) + + -o --no-output + do not create any output (useful with -im) + +filename generation (only with --frame-range or --all-frames): + + +Fc --use-frame-counter + use 0-based counter for filenames (default) + + +Fn --use-frame-number + use absolute frame number for filenames + +image format: + + +op --write-raw-pnm + write 8-bit binary PGM/PPM (default for files) + + +opb --write-8-bit-pnm + write 8-bit ASCII PGM/PPM (default for stdout) + + +opw --write-16-bit-pnm + write 16-bit ASCII PGM/PPM + + +opn --write-n-bit-pnm [n]umber: integer + write n-bit ASCII PGM/PPM (1..32) + + +ob --write-bmp + write 8-bit (monochrome) or 24-bit (color) BMP + + +obp --write-8-bit-bmp + write 8-bit palette BMP (monochrome only) + + +obt --write-24-bit-bmp + write 24-bit truecolor BMP + + +obr --write-32-bit-bmp + write 32-bit truecolor BMP + + +ot --write-tiff + write 8-bit (monochrome) or 24-bit (color) TIFF + + +on --write-png + write 8-bit (monochrome) or 24-bit (color) PNG + + +on2 --write-16-bit-png + write 16-bit (monochrome) or 48-bit (color) PNG +\endverbatim + +\section notes NOTES + +The following preferred interpolation algorithms can be selected using the +\e --interpolate option: + +\li 1 = free scaling algorithm with interpolation from pbmplus toolkit +\li 2 = free scaling algorithm with interpolation from c't magazine +\li 3 = magnification algorithm with bilinear interpolation from Eduard Stanescu +\li 4 = magnification algorithm with bicubic interpolation from Eduard Stanescu + +The \e --write-tiff option is only available when DCMTK has been configured +and compiled with support for the external \b libtiff TIFF library. The +availability of the TIFF compression options depends on the \b libtiff +configuration. In particular, the patented LZW algorithm may not be +available. + +The \e --write-png option is only available when DCMTK has been configured +and compiled with support for the external \b libpng PNG library. Option +\e --interlace enables progressive image view while loading the PNG file. +Only a few applications take care of the meta info (TEXT) in a PNG file. + +\section transfer_syntaxes TRANSFER SYNTAXES + +\b dcm2pnm supports the following transfer syntaxes for input (\e dcmfile-in): + +\verbatim +LittleEndianImplicitTransferSyntax 1.2.840.10008.1.2 +LittleEndianExplicitTransferSyntax 1.2.840.10008.1.2.1 +DeflatedExplicitVRLittleEndianTransferSyntax 1.2.840.10008.1.2.1.99 (*) +BigEndianExplicitTransferSyntax 1.2.840.10008.1.2.2 +RLELosslessTransferSyntax 1.2.840.10008.1.2.5 +\endverbatim + +(*) if compiled with zlib support enabled + +\section logging LOGGING + +The level of logging output of the various command line tools and underlying +libraries can be specified by the user. By default, only errors and warnings +are written to the standard error stream. Using option \e --verbose also +informational messages like processing details are reported. Option +\e --debug can be used to get more details on the internal activity, e.g. for +debugging purposes. Other logging levels can be selected using option +\e --log-level. In \e --quiet mode only fatal errors are reported. In such +very severe error events, the application will usually terminate. For more +details on the different logging levels, see documentation of module "oflog". + +In case the logging output should be written to file (optionally with logfile +rotation), to syslog (Unix) or the event log (Windows) option \e --log-config +can be used. This configuration file also allows for directing only certain +messages to a particular output stream and for filtering certain messages +based on the module or application where they are generated. An example +configuration file is provided in \/logger.cfg. + +\section command_line COMMAND LINE + +All command line tools use the following notation for parameters: square +brackets enclose optional values (0-1), three trailing dots indicate that +multiple values are allowed (1-n), a combination of both means 0 to n values. + +Command line options are distinguished from parameters by a leading '+' or '-' +sign, respectively. Usually, order and position of command line options are +arbitrary (i.e. they can appear anywhere). However, if options are mutually +exclusive the rightmost appearance is used. This behavior conforms to the +standard evaluation rules of common Unix shells. + +In addition, one or more command files can be specified using an '@' sign as a +prefix to the filename (e.g. \@command.txt). Such a command argument +is replaced by the content of the corresponding text file (multiple +whitespaces are treated as a single separator unless they appear between two +quotation marks) prior to any further evaluation. Please note that a command +file cannot contain another command file. This simple but effective approach +allows one to summarize common combinations of options/parameters and avoids +longish and confusing command lines (an example is provided in file +\/dumppat.txt). + +\section environment ENVIRONMENT + +The \b dcm2pnm utility will attempt to load DICOM data dictionaries specified +in the \e DCMDICTPATH environment variable. By default, i.e. if the +\e DCMDICTPATH environment variable is not set, the file +\/dicom.dic will be loaded unless the dictionary is built +into the application (default for Windows). + +The default behavior should be preferred and the \e DCMDICTPATH environment +variable only used when alternative data dictionaries are required. The +\e DCMDICTPATH environment variable has the same format as the Unix shell +\e PATH variable in that a colon (":") separates entries. On Windows systems, +a semicolon (";") is used as a separator. The data dictionary code will +attempt to load each file specified in the \e DCMDICTPATH environment variable. +It is an error if no data dictionary can be loaded. + +\section files FILES + +\/camera.lut - sample characteristics file of a camera +\n\/monitor.lut - sample characteristics file of a monitor +\n\/printer.lut - sample characteristics file of a printer +\n\/scanner.lut - sample characteristics file of a scanner + +\section see_also SEE ALSO + +dcmj2pnm(1), img2dcm(1) + +\section copyright COPYRIGHT + +Copyright (C) 1998-2014 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany. + +*/ diff --git a/dcmimage/docs/dcmimage.dox b/dcmimage/docs/dcmimage.dox new file mode 100644 index 00000000..ccd922df --- /dev/null +++ b/dcmimage/docs/dcmimage.dox @@ -0,0 +1,44 @@ +/*! + +\page mod_dcmimage dcmimage: adds support for color images to dcmimgle + +This module contains classes to access and render DICOM color images. Support +for monochrome images is provided by the module \ref mod_dcmimgle "dcmimgle". +Support for JPEG compressed images is provide by the module +\ref mod_dcmjpeg "dcmjpeg". + +The main interface class is: +\li \b DicomImage (from module \ref mod_dcmimgle "dcmimgle") + +\section Tools + +This module contains the following command line tools: +\li \ref dcm2pnm +\li \ref dcmquant +\li \ref dcmscale + +\section Examples + +The following example shows how to load a DICOM single-frame image (monochrome +or color) and render its pixel data: + +\code +#include "dcmtk/dcmimage/diregist.h" /* required to support color images */ +/* ... */ +DicomImage *image = new DicomImage("test.dcm"); +if (image != NULL) +{ + if (image->getStatus() == EIS_Normal) + { + Uint8 *pixelData = (Uint8 *)(image->getOutputData(8 /* bits per sample */)); + if (pixelData != NULL) + { + /* do something useful with the pixel data */ + } + } else + cerr << "Error: cannot load DICOM image (" << DicomImage::getString(image->getStatus()) << ")" << endl; +} +delete image; +\endcode + +*/ diff --git a/dcmimage/docs/dcmquant.man b/dcmimage/docs/dcmquant.man new file mode 100644 index 00000000..0f446e30 --- /dev/null +++ b/dcmimage/docs/dcmquant.man @@ -0,0 +1,285 @@ +/*! + +\if MANPAGES +\page dcmquant Convert DICOM color images to palette color +\else +\page dcmquant dcmquant: Convert DICOM color images to palette color +\endif + +\section synopsis SYNOPSIS + +\verbatim +dcmquant [options] dcmfile-in dcmfile-out +\endverbatim + +\section description DESCRIPTION + +The \b dcmquant utility reads a DICOM color image, computes a palette color +look-up table of the desired size for this image (based on the median cut +algorithm published by Paul Heckbert) and converts the color image into a +DICOM palette color image. + +\section parameters PARAMETERS + +\verbatim +dcmfile-in DICOM input filename to be converted + +dcmfile-out DICOM output filename to be written +\endverbatim + +\section options OPTIONS + +\subsection general_options general options +\verbatim + -h --help + print this help text and exit + + --version + print version information and exit + + --arguments + print expanded command line arguments + + -q --quiet + quiet mode, print no warnings and errors + + -v --verbose + verbose mode, print processing details + + -d --debug + debug mode, print debug information + + -ll --log-level [l]evel: string constant + (fatal, error, warn, info, debug, trace) + use level l for the logger + + -lc --log-config [f]ilename: string + use config file f for the logger +\endverbatim + +\subsection input_options input options +\verbatim +input file format: + + +f --read-file + read file format or data set (default) + + +fo --read-file-only + read file format only + + -f --read-dataset + read data set without file meta information + +input transfer syntax: + + -t= --read-xfer-auto + use TS recognition (default) + + -td --read-xfer-detect + ignore TS specified in the file meta header + + -te --read-xfer-little + read with explicit VR little endian TS + + -tb --read-xfer-big + read with explicit VR big endian TS + + -ti --read-xfer-implicit + read with implicit VR little endian TS +\endverbatim + +\subsection processing_options image processing and encoding options +\verbatim +frame selection: + + +F --frame [n]umber: integer + select specified frame + + +Fa --all-frames + select all frames (default) + +compatibility: + + +Mp --accept-palettes + accept incorrect palette attribute tags + (0028,111x) and (0028,121x) + +median cut dimension selection: + + +Dr --mc-dimension-rgb + max dimension from RGB range (default) + + +Dl --mc-dimension-lum + max dimension from luminance + +median cut representative color selection: + + +Cb --mc-color-avgbox + average colors in box (default) + + +Cp --mc-color-avgpixel + average pixels in box + + +Cc --mc-color-center + select center of box + +color palette creation: + + +pw --write-ow + write Palette LUT as OW instead of US + + +pe --lut-entries-word + write Palette LUT with 16-bit entries + + +pf --floyd-steinberg + use Floyd-Steinberg error diffusion + + +pc --colors number of colors: 2..65536 (default 256) + number of colors to quantize to + +SOP Class UID: + + +cd --class-default + keep SOP Class UID (default) + + +cs --class-sc + convert to Secondary Capture Image + (implies --uid-always) + +SOP Instance UID: + + +ua --uid-always + always assign new UID (default) + + +un --uid-never + never assign new UID +\endverbatim + +\subsection output_options output options +\verbatim + +output file format: + + +F --write-file + write file format (default) + + -F --write-dataset + write data set without file meta information + +output transfer syntax: + + +t= --write-xfer-same + write with same TS as input (default) + + +te --write-xfer-little + write with explicit VR little endian TS + + +tb --write-xfer-big + write with explicit VR big endian TS + + +ti --write-xfer-implicit + write with implicit VR little endian TS + +post-1993 value representations: + + +u --enable-new-vr + enable support for new VRs (UN/UT) (default) + + -u --disable-new-vr + disable support for new VRs, convert to OB + +group length encoding: + + +g= --group-length-recalc + recalculate group lengths if present (default) + + +g --group-length-create + always write with group length elements + + -g --group-length-remove + always write without group length elements + +length encoding in sequences and items: + + +e --length-explicit + write with explicit lengths (default) + + -e --length-undefined + write with undefined lengths + +data set trailing padding (not with --write-dataset): + + -p= --padding-retain + do not change padding + (default if not --write-dataset) + + -p --padding-off + no padding (implicit if --write-dataset) + + +p --padding-create [f]ile-pad [i]tem-pad: integer + align file on multiple of f bytes and items on + multiple of i bytes +\endverbatim + +\section logging LOGGING + +The level of logging output of the various command line tools and underlying +libraries can be specified by the user. By default, only errors and warnings +are written to the standard error stream. Using option \e --verbose also +informational messages like processing details are reported. Option +\e --debug can be used to get more details on the internal activity, e.g. for +debugging purposes. Other logging levels can be selected using option +\e --log-level. In \e --quiet mode only fatal errors are reported. In such +very severe error events, the application will usually terminate. For more +details on the different logging levels, see documentation of module "oflog". + +In case the logging output should be written to file (optionally with logfile +rotation), to syslog (Unix) or the event log (Windows) option \e --log-config +can be used. This configuration file also allows for directing only certain +messages to a particular output stream and for filtering certain messages +based on the module or application where they are generated. An example +configuration file is provided in \/logger.cfg. + +\section command_line COMMAND LINE + +All command line tools use the following notation for parameters: square +brackets enclose optional values (0-1), three trailing dots indicate that +multiple values are allowed (1-n), a combination of both means 0 to n values. + +Command line options are distinguished from parameters by a leading '+' or '-' +sign, respectively. Usually, order and position of command line options are +arbitrary (i.e. they can appear anywhere). However, if options are mutually +exclusive the rightmost appearance is used. This behavior conforms to the +standard evaluation rules of common Unix shells. + +In addition, one or more command files can be specified using an '@' sign as a +prefix to the filename (e.g. \@command.txt). Such a command argument +is replaced by the content of the corresponding text file (multiple +whitespaces are treated as a single separator unless they appear between two +quotation marks) prior to any further evaluation. Please note that a command +file cannot contain another command file. This simple but effective approach +allows one to summarize common combinations of options/parameters and avoids +longish and confusing command lines (an example is provided in file +\/dumppat.txt). + +\section environment ENVIRONMENT + +The \b dcmquant utility will attempt to load DICOM data dictionaries specified +in the \e DCMDICTPATH environment variable. By default, i.e. if the +\e DCMDICTPATH environment variable is not set, the file +\/dicom.dic will be loaded unless the dictionary is built +into the application (default for Windows). + +The default behavior should be preferred and the \e DCMDICTPATH environment +variable only used when alternative data dictionaries are required. The +\e DCMDICTPATH environment variable has the same format as the Unix shell +\e PATH variable in that a colon (":") separates entries. On Windows systems, +a semicolon (";") is used as a separator. The data dictionary code will +attempt to load each file specified in the \e DCMDICTPATH environment variable. +It is an error if no data dictionary can be loaded. + +\section copyright COPYRIGHT + +Copyright (C) 2001-2014 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany. + +*/ diff --git a/dcmimage/docs/dcmscale.man b/dcmimage/docs/dcmscale.man new file mode 100644 index 00000000..75a218cc --- /dev/null +++ b/dcmimage/docs/dcmscale.man @@ -0,0 +1,271 @@ +/*! + +\if MANPAGES +\page dcmscale Scale DICOM images +\else +\page dcmscale dcmscale: Scale DICOM images +\endif + +\section synopsis SYNOPSIS + +\verbatim +dcmscale [options] dcmfile-in dcmfile-out +\endverbatim + +\section description DESCRIPTION + +The \b dcmscale utility reads a DICOM image, scales it according to the +command line settings and writes back the DICOM image. This utility only +supports uncompressed and RLE compressed DICOM images. + +\section parameters PARAMETERS + +\verbatim +dcmfile-in DICOM input filename to be scaled + +dcmfile-out DICOM output filename to be written +\endverbatim + +\section options OPTIONS + +\subsection general_options general options +\verbatim + -h --help + print this help text and exit + + --version + print version information and exit + + --arguments + print expanded command line arguments + + -q --quiet + quiet mode, print no warnings and errors + + -v --verbose + verbose mode, print processing details + + -d --debug + debug mode, print debug information + + -ll --log-level [l]evel: string constant + (fatal, error, warn, info, debug, trace) + use level l for the logger + + -lc --log-config [f]ilename: string + use config file f for the logger +\endverbatim + +\subsection input_options input options +\verbatim +input file format: + + +f --read-file + read file format or data set (default) + + +fo --read-file-only + read file format only + + -f --read-dataset + read data set without file meta information + +input transfer syntax: + + -t= --read-xfer-auto + use TS recognition (default) + + -td --read-xfer-detect + ignore TS specified in the file meta header + + -te --read-xfer-little + read with explicit VR little endian TS + + -tb --read-xfer-big + read with explicit VR big endian TS + + -ti --read-xfer-implicit + read with implicit VR little endian TS +\endverbatim + +\subsection processing_options image processing and encoding options +\verbatim +scaling: + + +a --recognize-aspect + recognize pixel aspect ratio (default) + + -a --ignore-aspect + ignore pixel aspect ratio when scaling + + +i --interpolate [n]umber of algorithm: integer + use interpolation when scaling (1..4, default: 1) + + -i --no-interpolation + no interpolation when scaling + + -S --no-scaling + no scaling, ignore pixel aspect ratio (default) + + +Sxf --scale-x-factor [f]actor: float + scale x axis by factor, auto-compute y axis + + +Syf --scale-y-factor [f]actor: float + scale y axis by factor, auto-compute x axis + + +Sxv --scale-x-size [n]umber: integer + scale x axis to n pixels, auto-compute y axis + + +Syv --scale-y-size [n]umber: integer + scale y axis to n pixels, auto-compute x axis + +other transformations: + + +C --clip-region [l]eft [t]op [w]idth [h]eight: integer + clip rectangular image region (l, t, w, h) + +SOP Instance UID: + + +ua --uid-always + always assign new SOP Instance UID (default) + + +un --uid-never + never assign new SOP Instance UID +\endverbatim + +\subsection output_options output options +\verbatim +output file format: + + +F --write-file + write file format (default) + + -F --write-dataset + write data set without file meta information + +output transfer syntax: + + +t= --write-xfer-same + write with same TS as input (default) + + +te --write-xfer-little + write with explicit VR little endian TS + + +tb --write-xfer-big + write with explicit VR big endian TS + + +ti --write-xfer-implicit + write with implicit VR little endian TS + +post-1993 value representations: + + +u --enable-new-vr + enable support for new VRs (UN/UT) (default) + + -u --disable-new-vr + disable support for new VRs, convert to OB + +group length encoding: + + +g= --group-length-recalc + recalculate group lengths if present (default) + + +g --group-length-create + always write with group length elements + + -g --group-length-remove + always write without group length elements + +length encoding in sequences and items: + + +e --length-explicit + write with explicit lengths (default) + + -e --length-undefined + write with undefined lengths + +data set trailing padding (not with --write-dataset): + + -p= --padding-retain + do not change padding + (default if not --write-dataset) + + -p --padding-off + no padding (implicit if --write-dataset) + + +p --padding-create [f]ile-pad [i]tem-pad: integer + align file on multiple of f bytes and items on + multiple of i bytes +\endverbatim + +\section notes NOTES + +The following preferred interpolation algorithms can be selected using the +\e --interpolate option: + +\li 1 = free scaling algorithm with interpolation from pbmplus toolkit +\li 2 = free scaling algorithm with interpolation from c't magazine +\li 3 = magnification algorithm with bilinear interpolation from Eduard Stanescu +\li 4 = magnification algorithm with bicubic interpolation from Eduard Stanescu + +\section logging LOGGING + +The level of logging output of the various command line tools and underlying +libraries can be specified by the user. By default, only errors and warnings +are written to the standard error stream. Using option \e --verbose also +informational messages like processing details are reported. Option +\e --debug can be used to get more details on the internal activity, e.g. for +debugging purposes. Other logging levels can be selected using option +\e --log-level. In \e --quiet mode only fatal errors are reported. In such +very severe error events, the application will usually terminate. For more +details on the different logging levels, see documentation of module "oflog". + +In case the logging output should be written to file (optionally with logfile +rotation), to syslog (Unix) or the event log (Windows) option \e --log-config +can be used. This configuration file also allows for directing only certain +messages to a particular output stream and for filtering certain messages +based on the module or application where they are generated. An example +configuration file is provided in \/logger.cfg. + +\section command_line COMMAND LINE + +All command line tools use the following notation for parameters: square +brackets enclose optional values (0-1), three trailing dots indicate that +multiple values are allowed (1-n), a combination of both means 0 to n values. + +Command line options are distinguished from parameters by a leading '+' or '-' +sign, respectively. Usually, order and position of command line options are +arbitrary (i.e. they can appear anywhere). However, if options are mutually +exclusive the rightmost appearance is used. This behavior conforms to the +standard evaluation rules of common Unix shells. + +In addition, one or more command files can be specified using an '@' sign as a +prefix to the filename (e.g. \@command.txt). Such a command argument +is replaced by the content of the corresponding text file (multiple +whitespaces are treated as a single separator unless they appear between two +quotation marks) prior to any further evaluation. Please note that a command +file cannot contain another command file. This simple but effective approach +allows one to summarize common combinations of options/parameters and avoids +longish and confusing command lines (an example is provided in file +\/dumppat.txt). + +\section environment ENVIRONMENT + +The \b dcmscale utility will attempt to load DICOM data dictionaries specified +in the \e DCMDICTPATH environment variable. By default, i.e. if the +\e DCMDICTPATH environment variable is not set, the file +\/dicom.dic will be loaded unless the dictionary is built +into the application (default for Windows). + +The default behavior should be preferred and the \e DCMDICTPATH environment +variable only used when alternative data dictionaries are required. The +\e DCMDICTPATH environment variable has the same format as the Unix shell +\e PATH variable in that a colon (":") separates entries. On Windows systems, +a semicolon (";") is used as a separator. The data dictionary code will +attempt to load each file specified in the \e DCMDICTPATH environment variable. +It is an error if no data dictionary can be loaded. + +\section copyright COPYRIGHT + +Copyright (C) 2002-2014 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany. + +*/ diff --git a/dcmimage/etc/Makefile.in b/dcmimage/etc/Makefile.in new file mode 100644 index 00000000..d497229a --- /dev/null +++ b/dcmimage/etc/Makefile.in @@ -0,0 +1,23 @@ +# +# Makefile for dcmimage/etc +# + +@SET_MAKE@ + +SHELL = /bin/sh +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +configdir = @top_srcdir@/@configdir@ + +include $(configdir)/@common_makefile@ + + +all: + +install: + +clean: + rm -f $(TRASH) + +distclean: + rm -f $(DISTTRASH) diff --git a/dcmimage/include/CMakeLists.txt b/dcmimage/include/CMakeLists.txt new file mode 100644 index 00000000..aaf8525a --- /dev/null +++ b/dcmimage/include/CMakeLists.txt @@ -0,0 +1,2 @@ +# declare installation files +INSTALL(DIRECTORY dcmtk/dcmimage DESTINATION ${DCMTK_INSTALL_INCDIR}/dcmtk COMPONENT include FILES_MATCHING PATTERN "*.h") diff --git a/dcmimage/include/Makefile.in b/dcmimage/include/Makefile.in new file mode 100644 index 00000000..134bd1a1 --- /dev/null +++ b/dcmimage/include/Makefile.in @@ -0,0 +1,27 @@ +# +# Makefile for dcmimage/include +# + +@SET_MAKE@ + +SHELL = /bin/sh +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +configdir = @top_srcdir@/@configdir@ + +include $(configdir)/@common_makefile@ + + +all: + +install: + $(configdir)/mkinstalldirs $(DESTDIR)$(includedir)/dcmtk/dcmimage + for file in dcmtk/dcmimage/*.h ; do \ + $(INSTALL_DATA) $$file $(DESTDIR)$(includedir)/dcmtk/dcmimage ;\ + done + +clean: + rm -f $(TRASH) + +distclean: + rm -f $(DISTTRASH) diff --git a/dcmimage/include/dcmtk/dcmimage/diargimg.h b/dcmimage/include/dcmtk/dcmimage/diargimg.h new file mode 100644 index 00000000..a16e3943 --- /dev/null +++ b/dcmimage/include/dcmtk/dcmimage/diargimg.h @@ -0,0 +1,90 @@ +/* + * + * Copyright (C) 1996-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimage + * + * Author: Joerg Riesmeier + * + * Purpose: DiARGBImage (Header) + * + */ + + +#ifndef DIARGIMG_H +#define DIARGIMG_H + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/dcmimage/dicoimg.h" + + +/*------------------------* + * forward declarations * + *------------------------*/ + +class DiLookupTable; + + +/*---------------------* + * class declaration * + *---------------------*/ + +/** Class for ARGB images + */ +class DCMTK_DCMIMAGE_EXPORT DiARGBImage + : public DiColorImage +{ + + public: + + /** constructor + * + ** @param docu pointer to dataset (encapsulated) + * @param status current image status + */ + DiARGBImage(const DiDocument *docu, + const EI_Status status); + + /** destructor + */ + virtual ~DiARGBImage(); + + /** process next couple of frames + * + ** @param fcount number of frames to be processed (0 = same number as before) + * + ** @return status, true if successful, false otherwise + */ + virtual int processNextFrames(const unsigned long fcount); + + + protected: + + /** initialize internal data structures and member variables + */ + void Init(); + + + private: + + /// three color palettes for R, G and B + DiLookupTable *Palette[3]; + + // --- declarations to avoid compiler warnings + + DiARGBImage(const DiARGBImage &); + DiARGBImage &operator=(const DiARGBImage &); +}; + + +#endif diff --git a/dcmimage/include/dcmtk/dcmimage/diargpxt.h b/dcmimage/include/dcmtk/dcmimage/diargpxt.h new file mode 100644 index 00000000..692ef7c8 --- /dev/null +++ b/dcmimage/include/dcmtk/dcmimage/diargpxt.h @@ -0,0 +1,193 @@ +/* + * + * Copyright (C) 1996-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimage + * + * Author: Joerg Riesmeier + * + * Purpose: DicomARGBPixelTemplate (Header) - UNTESTED !!! + * + */ + + +#ifndef DIARGPXT_H +#define DIARGPXT_H + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/dcmimage/dicopxt.h" +#include "dcmtk/dcmimgle/diluptab.h" +#include "dcmtk/dcmimgle/diinpx.h" /* gcc 3.4 needs this */ + +/*---------------------* + * class declaration * + *---------------------*/ + +/** Template class to handle ARGB pixel data + */ +template +class DiARGBPixelTemplate + : public DiColorPixelTemplate +{ + + public: + + /** constructor + * + ** @param docu pointer to DICOM document + * @param pixel pointer to input pixel representation + * @param palette pointer to RGB color palette + * @param status reference to status variable + * @param planeSize number of pixels in a plane + * @param bits number of bits per sample + */ + DiARGBPixelTemplate(const DiDocument *docu, + const DiInputPixel *pixel, + DiLookupTable *palette[3], + EI_Status &status, + const unsigned long planeSize, + const int bits) + : DiColorPixelTemplate(docu, pixel, 4, status) + { + if ((pixel != NULL) && (this->Count > 0) && (status == EIS_Normal)) + convert(OFstatic_cast(const T1 *, pixel->getData()) + pixel->getPixelStart(), palette, planeSize, bits); + } + + /** destructor + */ + virtual ~DiARGBPixelTemplate() + { + } + + + private: + + /** convert input pixel data to intermediate representation + * + ** @param pixel pointer to input pixel data + * @param palette pointer to RGB color palette + * @param planeSize number of pixels in a plane + * @param bits number of bits per sample + */ + void convert(const T1 *pixel, + DiLookupTable *palette[3], + const unsigned long planeSize, + const int bits) + { // not very much optimized, but no one really uses ARGB !! + if (this->Init(pixel)) + { + register T2 value; + const T1 offset = OFstatic_cast(T1, DicomImageClass::maxval(bits - 1)); + // use the number of input pixels derived from the length of the 'PixelData' + // attribute), but not more than the size of the intermediate buffer + const unsigned long count = (this->InputCount < this->Count) ? this->InputCount : this->Count; + if (this->PlanarConfiguration) + { +/* + register const T1 *a = pixel; // points to alpha plane + const T1 *rgb[3]; + rgb[0] = a + this->InputCount; // points to red plane + rgb[1] = rgb[0] + this->InputCount; // points to green plane + rgb[2] = rgb[1] + this->InputCount; // points to blue plane + for (i = 0; i < count; ++i) + { + value = OFstatic_cast(T2, *(a++)); // get alpha value + if (value > 0) + { + for (int j = 0; j < 3; ++j) // set palette color + { + if (value <= palette[j]->getFirstEntry(value)) + this->Data[j][i] = OFstatic_cast(T3, palette[j]->getFirstValue()); + else if (value >= palette[j]->getLastEntry(value)) + this->Data[j][i] = OFstatic_cast(T3, palette[j]->getLastValue()); + else + this->Data[j][i] = OFstatic_cast(T3, palette[j]->getValue(value)); + ++rgb[j]; // skip RGB values + } + } + else + { + for (j = 0; j < 3; ++j) // copy RGB values + this->Data[j][i] = OFstatic_cast(T3, removeSign(*(rgb[j]++), offset)); + } + } +*/ + register unsigned long l; + register unsigned long i = 0; + register const T1 *a = pixel; // points to alpha plane + const T1 *rgb[3]; + rgb[0] = a + planeSize; // points to red plane + rgb[1] = rgb[0] + planeSize; // points to green plane + rgb[2] = rgb[1] + planeSize; // points to blue plane + while (i < count) + { + /* convert a single frame */ + for (l = planeSize; (l != 0) && (i < count); --l, ++i) + { + value = OFstatic_cast(T2, *(a++)); // get alpha value + if (value > 0) + { + for (int j = 0; j < 3; ++j) // set palette color + { + if (value <= palette[j]->getFirstEntry(value)) + this->Data[j][i] = OFstatic_cast(T3, palette[j]->getFirstValue()); + else if (value >= palette[j]->getLastEntry(value)) + this->Data[j][i] = OFstatic_cast(T3, palette[j]->getLastValue()); + else + this->Data[j][i] = OFstatic_cast(T3, palette[j]->getValue(value)); + ++rgb[j]; // skip RGB values + } + } + else + { + for (int j = 0; j < 3; ++j) // copy RGB values + this->Data[j][i] = OFstatic_cast(T3, removeSign(*(rgb[j]++), offset)); + } + } + /* jump to next frame start (skip 2 planes) */ + a += 2 * planeSize; + for (int j = 0; j < 3; ++j) + rgb[j] += 2 * planeSize; + } + } else { + register unsigned long i; + register const T1 *p = pixel; + for (i = 0; i < count; ++i) + { + value = OFstatic_cast(T2, *(p++)); // get alpha value + if (value > 0) + { + for (int j = 0; j < 3; ++j) // set palette color + { + if (value <= palette[j]->getFirstEntry(value)) + this->Data[j][i] = OFstatic_cast(T3, palette[j]->getFirstValue()); + else if (value >= palette[j]->getLastEntry(value)) + this->Data[j][i] = OFstatic_cast(T3, palette[j]->getLastValue()); + else + this->Data[j][i] = OFstatic_cast(T3, palette[j]->getValue(value)); + } + p += 3; // skip RGB values + } + else + { + for (int j = 0; j < 3; ++j) // copy RGB values + this->Data[j][i] = OFstatic_cast(T3, removeSign(*(p++), offset)); + } + } + } + } + } +}; + + +#endif diff --git a/dcmimage/include/dcmtk/dcmimage/dicdefin.h b/dcmimage/include/dcmtk/dcmimage/dicdefin.h new file mode 100644 index 00000000..7b830176 --- /dev/null +++ b/dcmimage/include/dcmtk/dcmimage/dicdefin.h @@ -0,0 +1,38 @@ +/* + * + * Copyright (C) 2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimage + * + * Author: Uli Schlachter + * + * Purpose: Contains preprocessor definitions + * + */ + + +#ifndef DICDEFIN_H +#define DICDEFIN_H + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/ofstd/ofdefine.h" + + +#ifdef dcmimage_EXPORTS +#define DCMTK_DCMIMAGE_EXPORT DCMTK_DECL_EXPORT +#else +#define DCMTK_DCMIMAGE_EXPORT DCMTK_DECL_IMPORT +#endif + + +#endif diff --git a/dcmimage/include/dcmtk/dcmimage/dicmyimg.h b/dcmimage/include/dcmtk/dcmimage/dicmyimg.h new file mode 100644 index 00000000..290aea10 --- /dev/null +++ b/dcmimage/include/dcmtk/dcmimage/dicmyimg.h @@ -0,0 +1,72 @@ +/* + * + * Copyright (C) 1996-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimage + * + * Author: Joerg Riesmeier + * + * Purpose: DicomCMYKImage (Header) + * + */ + + +#ifndef DICMYIMG_H +#define DICMYIMG_H + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/dcmimage/dicoimg.h" + + +/*---------------------* + * class declaration * + *---------------------*/ + +/** Class for CMYK images + */ +class DCMTK_DCMIMAGE_EXPORT DiCMYKImage + : public DiColorImage +{ + + public: + + /** constructor + * + ** @param docu pointer to dataset (encapsulated) + * @param status current image status + */ + DiCMYKImage(const DiDocument *docu, + const EI_Status status); + + /** destructor + */ + virtual ~DiCMYKImage(); + + /** process next couple of frames + * + ** @param fcount number of frames to be processed (0 = same number as before) + * + ** @return status, true if successful, false otherwise + */ + virtual int processNextFrames(const unsigned long fcount); + + + protected: + + /** initialize internal data structures and member variables + */ + void Init(); +}; + + +#endif diff --git a/dcmimage/include/dcmtk/dcmimage/dicmypxt.h b/dcmimage/include/dcmtk/dcmimage/dicmypxt.h new file mode 100644 index 00000000..0b1bc8c2 --- /dev/null +++ b/dcmimage/include/dcmtk/dcmimage/dicmypxt.h @@ -0,0 +1,146 @@ +/* + * + * Copyright (C) 1996-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimage + * + * Author: Joerg Riesmeier + * + * Purpose: DicomCMYKPixelTemplate (Header) + * + */ + + +#ifndef DICMYPXT_H +#define DICMYPXT_H + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/dcmimage/dicopxt.h" +#include "dcmtk/dcmimgle/diinpx.h" /* gcc 3.4 needs this */ + + +/*---------------------* + * class declaration * + *---------------------*/ + +/** Template class to handle CMYK pixel data + */ +template +class DiCMYKPixelTemplate + : public DiColorPixelTemplate +{ + + public: + + /** constructor + * + ** @param docu pointer to DICOM document + * @param pixel pointer to input pixel representation + * @param status reference to status variable + * @param planeSize number of pixels in a plane + * @param bits number of bits per sample + */ + DiCMYKPixelTemplate(const DiDocument *docu, + const DiInputPixel *pixel, + EI_Status &status, + const unsigned long planeSize, + const int bits) + : DiColorPixelTemplate(docu, pixel, 4, status) + { + if ((pixel != NULL) && (this->Count > 0) && (status == EIS_Normal)) + convert(OFstatic_cast(const T1 *, pixel->getData()) + pixel->getPixelStart(), planeSize, bits); + } + + /** destructor + */ + virtual ~DiCMYKPixelTemplate() + { + } + + + private: + + /** convert input pixel data to intermediate representation + * + ** @param pixel pointer to input pixel data + * @param planeSize number of pixels in a plane + * @param bits number of bits per sample + */ + void convert(const T1 *pixel, + const unsigned long planeSize, + const int bits) + { + if (this->Init(pixel)) + { + // use the number of input pixels derived from the length of the 'PixelData' + // attribute), but not more than the size of the intermediate buffer + const unsigned long count = (this->InputCount < this->Count) ? this->InputCount : this->Count; + const T2 maxvalue = OFstatic_cast(T2, DicomImageClass::maxval(bits)); + const T1 offset = OFstatic_cast(T1, DicomImageClass::maxval(bits - 1)); + register const T1 *p = pixel; + if (this->PlanarConfiguration) + { +/* + register const T1 *k; + register T2 *q; + for (int j = 0; j < 3; ++j) + { + q = this->Data[j]; + k = pixel + 3 * this->InputCount; // beginning of 'black' plane + for (i = count; i != 0; --i) + *(q++) = maxvalue - removeSign(*(p++), offset) - removeSign(*(k++), offset); + } +*/ + register const T1 *k; + register T2 *q; + register unsigned long l; + register unsigned long i = 0; + while (i < count) + { + /* store current pixel index */ + const unsigned long iStart = i; + /* beginning of 'black' plane */ + const T1 *kStart = p + 3 * planeSize; + /* for all planes ... */ + for (int j = 0; j < 3; ++j) + { + q = this->Data[j] + iStart; + /* reset to beginning of 'black' plane */ + k = kStart; + /* convert a single plane */ + for (l = planeSize, i = iStart; (l != 0) && (i < count); --l, ++i) + *(q++) = maxvalue - removeSign(*(p++), offset) - removeSign(*(k++), offset); + } + /* skip black plane */ + p += planeSize; + } + } + else + { + register T1 k; + register int j; + register unsigned long i; + for (i = 0; i < count; ++i) + { + k = *(p + 3); + for (j = 0; j < 3; ++j) + this->Data[j][i] = maxvalue - removeSign(*(p++), offset) - removeSign(k, offset); + ++p; // skip 'black' + } + } + } + } +}; + + +#endif diff --git a/dcmimage/include/dcmtk/dcmimage/dicocpt.h b/dcmimage/include/dcmtk/dcmimage/dicocpt.h new file mode 100644 index 00000000..7869bdee --- /dev/null +++ b/dcmimage/include/dcmtk/dcmimage/dicocpt.h @@ -0,0 +1,91 @@ +/* + * + * Copyright (C) 1998-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimage + * + * Author: Joerg Riesmeier + * + * Purpose: DicomColorCopyTemplate (Header) + * + */ + + +#ifndef DICOCPT_H +#define DICOCPT_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/ofstd/ofbmanip.h" + +#include "dcmtk/dcmimage/dicopxt.h" + + +/*---------------------* + * class declaration * + *---------------------*/ + +/** Template class to copy color pixel data + */ +template +class DiColorCopyTemplate + : public DiColorPixelTemplate +{ + + public: + + /** constructor + * + ** @param pixel pointer to color intermediate representation of pixel data + * @param fstart first frame to be copied + * @param fcount number of frames to be copied + * @param fsize size of one frame (in bytes) + */ + DiColorCopyTemplate(const DiColorPixel *pixel, + const unsigned long fstart, + const unsigned long fcount, + const unsigned long fsize) + : DiColorPixelTemplate(pixel, fcount * fsize) + { + if ((pixel != NULL) && (pixel->getCount() > 0)) + { + if ((pixel->getCount() > fstart * fsize) && (pixel->getCount() >= (fstart + fcount) * fsize)) + copy(OFstatic_cast(const T **, OFconst_cast(void *, pixel->getData())), fstart * fsize); + } + } + + /** destructor + */ + ~DiColorCopyTemplate() + { + } + + + private: + + /** copy specified amount of pixel data + * + ** @param pixel array of pixel data (3 color components) to be copied + * @param offset offset to the first pixel to be copied + */ + inline void copy(const T *pixel[3], + const unsigned long offset) + { + if (this->Init(pixel)) + { + for (int j = 0; j < 3; j++) + OFBitmanipTemplate::copyMem(pixel[j] + offset, this->Data[j], this->getCount()); + } + } +}; + + +#endif diff --git a/dcmimage/include/dcmtk/dcmimage/dicoflt.h b/dcmimage/include/dcmtk/dcmimage/dicoflt.h new file mode 100644 index 00000000..f2e0c819 --- /dev/null +++ b/dcmimage/include/dcmtk/dcmimage/dicoflt.h @@ -0,0 +1,107 @@ +/* + * + * Copyright (C) 1998-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimage + * + * Author: Joerg Riesmeier + * + * Purpose: DicomColorFlipTemplate (Header) + * + */ + + +#ifndef DICOFLT_H +#define DICOFLT_H + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/dcmimage/dicopxt.h" +#include "dcmtk/dcmimgle/diflipt.h" + + +/*---------------------* + * class declaration * + *---------------------*/ + +/** Template class to flip color images (on pixel data level) + * horizontally and vertically + */ +template +class DiColorFlipTemplate + : public DiColorPixelTemplate, + protected DiFlipTemplate +{ + + public: + + /** constructor + * + ** @param pixel pointer to intermediate pixel representation + * @param columns number of columns + * @param rows number of rows + * @param frames number of frames + * @param horz flip horizontally if true + * @param vert flip vertically if true + */ + DiColorFlipTemplate(const DiColorPixel *pixel, + const Uint16 columns, + const Uint16 rows, + const Uint32 frames, + const int horz, + const int vert) + : DiColorPixelTemplate(pixel, OFstatic_cast(unsigned long, columns) * OFstatic_cast(unsigned long, rows) * frames), + DiFlipTemplate(3, columns, rows, frames) + { + if ((pixel != NULL) && (pixel->getCount() > 0)) + { + if (pixel->getCount() == OFstatic_cast(unsigned long, columns) * OFstatic_cast(unsigned long, rows) * frames) + flip(OFstatic_cast(const T **, OFconst_cast(void *, pixel->getData())), horz, vert); + else { + DCMIMAGE_WARN("could not flip image ... corrupted data"); + } + } + } + + /** destructor + */ + ~DiColorFlipTemplate() + { + } + + + private: + + /** choose flipping algorithm depending on given parameters + * + ** @param pixel pointer to pixel data (3 components) which should be flipped + * @param horz flip horizontally if true + * @param vert flip vertically if true + */ + inline void flip(const T *pixel[3], + const int horz, + const int vert) + { + if (this->Init(pixel)) + { + if (horz && vert) + this->flipHorzVert(pixel, this->Data); + else if (horz) + this->flipHorz(pixel, this->Data); + else if (vert) + this->flipVert(pixel, this->Data); + } + } +}; + + +#endif diff --git a/dcmimage/include/dcmtk/dcmimage/dicoimg.h b/dcmimage/include/dcmtk/dcmimage/dicoimg.h new file mode 100644 index 00000000..4a8b4828 --- /dev/null +++ b/dcmimage/include/dcmtk/dcmimage/dicoimg.h @@ -0,0 +1,446 @@ +/* + * + * Copyright (C) 1996-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimage + * + * Author: Joerg Riesmeier + * + * Purpose: DicomColorImage (Header) + * + */ + + +#ifndef DICOIMG_H +#define DICOIMG_H + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/dcmimgle/diimage.h" +#include "dcmtk/dcmimage/dicopx.h" + + +/*------------------------* + * forward declarations * + *------------------------*/ + +class DiColorOutputPixel; + + +/*---------------------* + * class declaration * + *---------------------*/ + +/** Base class for color images + */ +class DCMTK_DCMIMAGE_EXPORT DiColorImage + : public DiImage +{ + + public: + + /** constructor + * + ** @param docu pointer to the DICOM document + * @param status status of the image object + * @param spp sample per pixel (1, 3 or 4 depending on the color model) + * @param rgb specifies whether internal image representation is in RGB format + */ + DiColorImage(const DiDocument *docu, + const EI_Status status, + const int spp, + const OFBool rgb = OFTrue); + + /** destructor + */ + virtual ~DiColorImage(); + + /** get color model of internal pixel representation. + * + ** @return returns EPI_RGB or EPI_YBR_Full depending on the 'rgb' flag in the constructor + */ + virtual EP_Interpretation getInternalColorModel() const + { + return (RGBColorModel) ? EPI_RGB : EPI_YBR_Full; + } + + /** get number of bytes required for the rendered output of a single frame + * + * @param bits number of bits for the output pixel data (depth) + * + ** @return number of bytes if successful, 0 otherwise + */ + virtual unsigned long getOutputDataSize(const int bits = 0) const; + + /** get pixel data with specified format. + * (memory is handled internally) + * The standard color model of the pixel data is RGB, but if the flag "rgb" is OFFalse + * and the original color model was YCbCr_Full or YCbCr_Full_422 YCbCr_Full is used instead. + * + ** @param frame number of frame to be rendered + * @param bits number of bits per sample for the output pixel data (depth) + * @param planar 0 = color-by-pixel (R1G1B1...R2G2B2...R3G3B3...), + * 1 = color-by-plane (R1R2R3...G1G2G3...B1B2B3...) + * + ** @return untyped pointer to the pixel data if successful, NULL otherwise + */ + const void *getOutputData(const unsigned long frame, + const int bits, + const int planar = 0); + + /** get pixel data with specified format. + * (memory is handled externally) + * The standard color model of the pixel data is RGB, but if the flag "rgb" is OFFalse + * and the original color model was YCbCr_Full or YCbCr_Full_422 YCbCr_Full is used instead. + * + ** @param buffer untyped pointer to the externally allocated memory buffer + * @param size size of the memory buffer in bytes (will be checked) + * @param frame number of frame to be rendered + * @param bits number of bits per sample for the output pixel data (depth) + * @param planar 0 = color-by-pixel (R1G1B1...R2G2B2...R3G3B3...) + * 1 = color-by-plane (R1R2R3...G1G2G3...B1B2B3...) + * + ** @return status, true if successful, false otherwise + */ + int getOutputData(void *buffer, + const unsigned long size, + const unsigned long frame, + const int bits, + const int planar = 0); + + /** get pixel data of specified plane. + * (memory is handled internally) + * + ** @param plane index of color plane + * + ** @return untyped pointer to the pixel data if successful, NULL otherwise + */ + const void *getOutputPlane(const int plane) const; + + /** delete internally handled output memory buffer + * Save memory if data is no longer needed. + */ + void deleteOutputData(); + + /** create copy of current image object + * + ** @param fstart first frame to be processed + * @param fcount number of frames + * + ** @return pointer to new DicomImage object (NULL if an error occurred) + */ + DiImage *createImage(const unsigned long fstart, + const unsigned long fcount) const; + + /** create scaled copy of specified (clipping) area of the current image object. + * + ** @param left_pos x coordinate of top left corner of area to be scaled + * (referring to image origin, negative values create a border around the image) + * @param top_pos y coordinate of top left corner of area to be scaled + * @param src_cols width of area to be scaled + * @param src_rows height of area to be scaled + * @param dest_cols width of scaled image (in pixels) + * @param dest_rows height of scaled image (in pixels) + * @param interpolate specifies whether scaling algorithm should use interpolation (if necessary). + * default: no interpolation (0), preferred interpolation algorithm (if applicable): + * 1 = pbmplus algorithm, 2 = c't algorithm, 3 = bilinear magnification, + * 4 = bicubic magnification + * @param aspect specifies whether pixel aspect ratio should be taken into consideration + * (if true, width OR height should be 0, i.e. this component will be calculated + * automatically) + * @param pvalue dummy parameter (only used for monochrome images) + * + ** @return pointer to new DiImage object (NULL if an error occurred) + */ + DiImage *createScale(const signed long left_pos, + const signed long top_pos, + const unsigned long src_cols, + const unsigned long src_rows, + const unsigned long dest_cols, + const unsigned long dest_rows, + const int interpolate, + const int aspect, + const Uint16 pvalue) const; + + /** flip current image (horizontally and/or vertically) + * + ** @param horz flip horizontally if true + * @param vert flip vertically if true + * + ** @return true if successful (1 = flipped at least direction, + * 2 = not flipped, because of image resolution - width and/or height equal to 1), + * false otherwise + */ + int flip(const int horz, + const int vert); + + /** create a flipped copy of the current image + * + ** @param horz flip horizontally if true + * @param vert flip vertically if true + * + ** @return pointer to new DiImage object (NULL if an error occurred) + */ + DiImage *createFlip(const int horz, + const int vert) const; + + /** rotate current image (by steps of 90 degrees) + * + ** @param degree angle by which the image shall be rotated (-360, -270, -180, -90, 0, 90, 180, 270, 360) + * + ** @return true if successful (1 = rotated by at least 90 degrees, + * 2 = not rotated, because of image resolution or angle), + * false otherwise + */ + int rotate(const int degree); + + /** create a rotated copy of the current image. + * + ** @param degree angle by which the image shall be rotated + * + ** @return pointer to new DiImage object (NULL if an error occurred) + */ + DiImage *createRotate(const int degree) const; + + /** create monochrome copy of the current image + * + ** @param red coefficient by which the red component is weighted + * @param green coefficient by which the green component is weighted + * @param blue coefficient by which the blue component is weighted + * + ** @return pointer to new DiImage object (NULL if an error occurred) + */ + DiImage *createMono(const double red, + const double green, + const double blue) const; + + /** get pointer to intermediate pixel data representation + * + ** @return pointer to intermediate pixel data + */ + const DiPixel *getInterData() const + { + return InterData; + } + + /** get pointer to intermediate pixel data representation + * + ** @return pointer to intermediate pixel data + */ + const DiColorPixel *getColorInterData() const + { + return InterData; + } + + /** create true color (24/32 bit) bitmap for MS Windows. + * memory is not handled internally - must be deleted from calling program. + * + ** @param data untyped pointer memory buffer (set to NULL if not allocated externally) + * @param size size of the memory buffer in bytes (if 0 'data' is set to NULL) + * @param frame index of frame to be converted (starting from 0) + * @param bits number of bits per pixel used for the output bitmap (24 or 32) + * @param upsideDown specifies the order of lines in the images (0 = top-down, bottom-up otherwise) + * @param padding align each line to a 32-bit address if true (default) + * + ** @return number of bytes allocated by the bitmap, or 0 if an error occured + */ + unsigned long createDIB(void *&data, + const unsigned long size, + const unsigned long frame, + const int bits, + const int upsideDown, + const int padding = 1); + + /** create true color (32 bit) bitmap for Java (AWT default format). + * Memory is not handled internally - must be deleted from calling program. + * + ** @param data resulting pointer to bitmap data (set to NULL if an error occurred) + * @param frame index of frame to be converted (default: first frame) + * @param bits number of bits per pixel used for the output bitmap (32) + * + ** @return number of bytes allocated by the bitmap, or 0 if an error occured + */ + unsigned long createAWTBitmap(void *&data, + const unsigned long frame, + const int bits); + + /** write current image and related attributes to DICOM dataset. + * + ** @param dataset reference to DICOM dataset where the image attributes are stored + * @param mode dummy parameter (only used for monochrome images) + * @param planar flag, whether the output data (for multi-planar images) should be planar or not + * + ** @return true if successful, false otherwise + */ + int writeImageToDataset(DcmItem &dataset, + const int mode, + const int planar); + + /** write pixel data to PPM file. + * pixel data is written in ASCII format. + * + ** @param stream open C++ output stream + * @param frame index of frame used for output + * @param bits number of bits used for output of pixel data + * + ** @return true if successful, false otherwise + */ + int writePPM(STD_NAMESPACE ostream& stream, + const unsigned long frame, + const int bits); + + /** write pixel data to PPM file. + * pixel data is written in ASCII format. + * + ** @param stream open C output stream + * @param frame index of frame used for output + * @param bits number of bits used for output of pixel data + * + ** @return true if successful, false otherwise + */ + int writePPM(FILE *stream, + const unsigned long frame, + const int bits); + + /** write pixel data to raw PPM file + * + ** @param stream open C output stream + * @param frame index of frame used for output + * @param bits number of bits used for output of pixel data + * + ** @return true if successful, false otherwise + */ + int writeRawPPM(FILE *stream, + const unsigned long frame, + const int bits); + + /** write pixel data to BMP file + * + ** @param stream open C output stream + * @param frame index of frame used for output (default: first frame = 0) + * @param bits number of bits used for output of pixel data (24 or 32, default (0) = 24) + * + ** @return true if successful, false otherwise + */ + int writeBMP(FILE *stream, + const unsigned long frame, + const int bits); + + + protected: + + /** constructor, copy + * + ** @param image pointer to reference image + * @param fstart first frame to be processed + * @param fcount number of frames + */ + DiColorImage(const DiColorImage *image, + const unsigned long fstart, + const unsigned long fcount); + + /** constructor, scale/clip + * + ** @param image pointer to reference image + * @param left_pos x coordinate of top left corner of area to be scaled + * (referring to image origin, negative values create a border around the image) + * @param top_pos y coordinate of top left corner of area to be scaled + * @param src_cols width of area to be scaled + * @param src_rows height of area to be scaled + * @param dest_cols width of scaled image (in pixels) + * @param dest_rows height of scaled image (in pixels) + * @param interpolate specifies whether scaling algorithm should use interpolation (if necessary). + * default: no interpolation (0), preferred interpolation algorithm (if applicable): + * 1 = pbmplus algorithm, 2 = c't algorithm, 3 = bilinear magnification, + * 4 = bicubic magnification + * @param aspect specifies whether pixel aspect ratio should be taken into consideration + * (if true, width OR height should be 0, i.e. this component will be calculated + * automatically) + */ + DiColorImage(const DiColorImage *image, + const signed long left_pos, + const signed long top_pos, + const Uint16 src_cols, + const Uint16 src_rows, + const Uint16 dest_cols, + const Uint16 dest_rows, + const int interpolate = 0, + const int aspect = 0); + + /** constructor, flip + * + ** @param image pointer to reference image + ** @param horz flip horizontally if true + * @param vert flip vertically if true + */ + DiColorImage(const DiColorImage *image, + const int horz, + const int vert); + + /** constructor, rotate + * + ** @param image pointer to reference image + * @param degree angle by which the image shall be rotated + */ + DiColorImage(const DiColorImage *image, + const int degree); + + /** check intermediate pixel representation for consistency + * + ** @param mode check number of pixels stored in the dataset if true + */ + int checkInterData(const int mode = 1); + + /** get pixel data with specified format. + * (memory is handled externally) + * + ** @param buffer untyped pointer to the externally allocated memory buffer + * @param size size of the memory buffer in bytes (will be checked) + * @param frame number of frame to be rendered + * @param bits number of bits for the output pixel data (depth) + * @param planar flag, 0 = color-by-pixel and 1 = color-by-plane + * + ** @return untyped pointer to the pixel data if successful, NULL otherwise + */ + const void *getData(void *buffer, + const unsigned long size, + const unsigned long frame, + const int bits, + const int planar); + + /** update Image Pixel Module attributes in the given dataset. + * Removes color palette lookup tables. Used in writeXXXToDataset() routines. + * + ** @param dataset reference to DICOM image dataset + */ + virtual void updateImagePixelModuleAttributes(DcmItem &dataset); + + /// flag, indicating whether the intermediate representation uses the RGB color model + const OFBool RGBColorModel; + + /// points to intermediate pixel data representation (object) + DiColorPixel *InterData; + + + private: + + /// points to current output data (object) + DiColorOutputPixel *OutputData; + + // --- declarations to avoid compiler warnings + + DiColorImage(const DiColorImage &); + DiColorImage &operator=(const DiColorImage &); +}; + + +#endif diff --git a/dcmimage/include/dcmtk/dcmimage/dicomot.h b/dcmimage/include/dcmtk/dcmimage/dicomot.h new file mode 100644 index 00000000..99ef8d52 --- /dev/null +++ b/dcmimage/include/dcmtk/dcmimage/dicomot.h @@ -0,0 +1,111 @@ +/* + * + * Copyright (C) 1996-2010, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimage + * + * Author: Joerg Riesmeier + * + * Purpose: DicomColorMonochromeTemplate (Header) + * + */ + + +#ifndef DICOMOT_H +#define DICOMOT_H + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/dcmimgle/dimopxt.h" +#include "dcmtk/dcmimage/dicopx.h" + + +/*---------------------* + * class declaration * + *---------------------*/ + +/** Template class to convert color image to monochrome images. + * (on pixel data level) + */ +template +class DiColorMonoTemplate + : public DiMonoPixelTemplate +{ + + public: + + /** constructor + * + ** @param pixel intermediate representation of color pixel data + * @param modality pointer to object managing modality transform + * @param red coefficient of red pixel component + * @param green coefficient of green pixel component + * @param blue coefficient of blue pixel component + */ + DiColorMonoTemplate(const DiColorPixel *pixel, + DiMonoModality *modality, + const double red, + const double green, + const double blue) + : DiMonoPixelTemplate(pixel, modality) + { + if ((pixel != NULL) && (pixel->getCount() > 0)) + { + convert(OFstatic_cast(const T **, OFconst_cast(void *, pixel->getData())), red, green, blue); + this->determineMinMax(); + } + } + + /** destructor + */ + virtual ~DiColorMonoTemplate() + { + } + + + private: + + /** convert color pixel data to monochrome format + * + ** @param pixel intermediate representation of color pixel data + * @param red coefficient of red pixel component + * @param green coefficient of green pixel component + * @param blue coefficient of blue pixel component + */ + void convert(const T *pixel[3], + const double red, + const double green, + const double blue) + { + if (pixel != NULL) + { + this->Data = new T[this->Count]; + if (this->Data != NULL) + { + register const T *r = pixel[0]; + register const T *g = pixel[1]; + register const T *b = pixel[2]; + register T *q = this->Data; + register unsigned long i; + for (i = this->Count; i != 0; i--) + { + *(q++) = OFstatic_cast(T, OFstatic_cast(double, *(r++)) * red + + OFstatic_cast(double, *(g++)) * green + + OFstatic_cast(double, *(b++)) * blue); + } + } + } + } +}; + + +#endif diff --git a/dcmimage/include/dcmtk/dcmimage/dicoopx.h b/dcmimage/include/dcmtk/dcmimage/dicoopx.h new file mode 100644 index 00000000..eba3038a --- /dev/null +++ b/dcmimage/include/dcmtk/dcmimage/dicoopx.h @@ -0,0 +1,136 @@ +/* + * + * Copyright (C) 1996-2012, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimgle + * + * Author: Joerg Riesmeier + * + * Purpose: DicomColorOutputPixel (Header) + * + */ + + +#ifndef DICOOPX_H +#define DICOOPX_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmimgle/diutils.h" +#include "dcmtk/ofstd/ofstream.h" + +#define INCLUDE_CSTDLIB +#define INCLUDE_CSTDIO +#include "dcmtk/ofstd/ofstdinc.h" + +#include "dcmtk/dcmimage/dicdefin.h" + + +/*------------------------* + * forward declarations * + *------------------------*/ + +class DiPixel; + + +/*---------------------* + * class declaration * + *---------------------*/ + +/** Abstract base class to create color output data + */ +class DCMTK_DCMIMAGE_EXPORT DiColorOutputPixel +{ + + public: + + /** constructor + * + ** @param pixel pointer to intermediate pixel representation + * @param size number of pixel per frame + * @param frame frame to be rendered + */ + DiColorOutputPixel(const DiPixel *pixel, + const unsigned long size, + const unsigned long frame); + + /** destructor + */ + virtual ~DiColorOutputPixel(); + + /** get integer representation (abstract) + * + ** @return integer representation + */ + virtual EP_Representation getRepresentation() const = 0; + + /** get pointer to output pixel data (abstract) + * + ** @return pointer to pixel data + */ + virtual const void *getData() const = 0; + + /** get pointer to outpout pixel data (abstract) + * + ** @return pointer to pixel data + */ + virtual void *getDataPtr() = 0; + + /** get pointer to given plane of output pixel data (abstract) + * + ** @param plane number of the plane to be retrieved (0..2) + * + ** @return pointer to beginning of plane if successful, NULL otherwise + */ + virtual const void *getPlane(const int plane) const = 0; + + /** get size of one pixel / item in the pixel array (abstract) + * + ** @return item size + */ + virtual size_t getItemSize() const = 0; + + /** write pixel data of selected frame to PPM/ASCII file (abstract) + * + ** @param stream open C++ output stream + * + ** @return status, true if successful, false otherwise + */ + virtual int writePPM(STD_NAMESPACE ostream& stream) const = 0; + + /** write pixel data of selected frame to PPM/ASCII file (abstract) + * + ** @param stream open C file stream + * + ** @return status, true if successful, false otherwise + */ + virtual int writePPM(FILE *stream) const = 0; + + /** get number of pixel per frame + * + ** @return number of pixel per frame + */ + inline unsigned long getCount() const + { + return FrameSize; + } + + + protected: + + /// number of pixels per frame (intermediate representation) + /*const*/ unsigned long Count; + /// number of pixels per frame (memory buffer size) + const unsigned long FrameSize; +}; + + +#endif diff --git a/dcmimage/include/dcmtk/dcmimage/dicoopxt.h b/dcmimage/include/dcmtk/dcmimage/dicoopxt.h new file mode 100644 index 00000000..447e0324 --- /dev/null +++ b/dcmimage/include/dcmtk/dcmimage/dicoopxt.h @@ -0,0 +1,417 @@ +/* + * + * Copyright (C) 1996-2012, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimgle + * + * Author: Joerg Riesmeier + * + * Purpose: DicomColorOutputPixelTemplate (Header) + * + */ + + +#ifndef DICOOPXT_H +#define DICOOPXT_H + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/dcmimage/dicoopx.h" +#include "dcmtk/dcmimage/dicopx.h" +#include "dcmtk/dcmimgle/dipxrept.h" + +#include "dcmtk/ofstd/ofbmanip.h" + + +/*---------------------* + * class declaration * + *---------------------*/ + +/** Template class to create color output data + */ +template +class DiColorOutputPixelTemplate + : public DiColorOutputPixel, + public DiPixelRepresentationTemplate +{ + + public: + + /** constructor + * + ** @param buffer storage area for the output pixel data (optional, maybe NULL) + * @param pixel pointer to intermediate pixel representation (color) + * @param count number of pixels per frame + * @param frame frame to be rendered + * @param bits1 bit depth of input data (intermediate) + * @param bits2 bit depth of output data + * @param planar flag indicating whether data shall be stored color-by-pixel or color-by-plane + * @param inverse invert pixel data if true (0/0/0 = white) + */ + DiColorOutputPixelTemplate(void *buffer, + const DiColorPixel *pixel, + const unsigned long count, + const unsigned long frame, + const int bits1, /* input depth */ + const int bits2, /* output depth */ + const int planar, + const int inverse) + : DiColorOutputPixel(pixel, count, frame), + Data(NULL), + DeleteData(buffer == NULL), + isPlanar(planar) + { + if ((pixel != NULL) && (Count > 0) && (FrameSize >= Count)) + { + Data = OFstatic_cast(T2 *, buffer); + convert(OFstatic_cast(const T1 **, OFconst_cast(void *, pixel->getData())), frame * FrameSize, bits1, bits2, planar, inverse); + } + } + + /** constructor + * + ** @param buffer storage area for the output pixel data (optional, maybe NULL) + * @param pixel pointer to intermediate pixel representation + * @param count number of pixels per frame + * @param frame frame to be rendered + * (#)param frames (total number of frames present in intermediate representation) + * @param planar flag indicating whether data shall be stored color-by-pixel or color-by-plane + */ + DiColorOutputPixelTemplate(void *buffer, + const DiPixel *pixel, + const unsigned long count, + const unsigned long frame, + const unsigned long /*frames*/, + const int planar) + : DiColorOutputPixel(pixel, count, frame), + Data(NULL), + DeleteData(buffer == NULL), + isPlanar(planar) + { + if ((pixel != NULL) && (Count > 0) && (FrameSize >= Count)) + Data = OFstatic_cast(T2 *, buffer); + } + + /** destructor + */ + virtual ~DiColorOutputPixelTemplate() + { + if (DeleteData) + delete[] Data; + } + + /** get integer representation + * + ** @return integer representation + */ + inline EP_Representation getRepresentation() const + { + return DiPixelRepresentationTemplate::getRepresentation(); + } + + /** get size of one pixel / item in the pixel array + * + ** @return item size + */ + inline size_t getItemSize() const + { + return sizeof(T2) * 3; + } + + /** get pointer to output pixel data + * + ** @return pointer to pixel data + */ + inline const void *getData() const + { + return OFstatic_cast(const void *, Data); + } + + /** get pointer to output pixel data + * + ** @return pointer to pixel data + */ + virtual void *getDataPtr() + { + return OFstatic_cast(void *, Data); + } + + /** get pointer to given plane of output pixel data + * + ** @param plane number of the plane to be retrieved (0..2) + * + ** @return pointer to beginning of plane if successful, NULL otherwise + */ + inline const void *getPlane(const int plane) const + { + void *result = NULL; + if (Data != NULL) + { + if (plane <= 0) + result = OFstatic_cast(void *, Data); + else + { + if (isPlanar) + result = OFstatic_cast(void *, Data + ((plane == 1) ? 1 : 2) * FrameSize); + else + result = OFstatic_cast(void *, Data + ((plane == 1) ? 1 : 2)); + } + } + return result; + } + + /** write pixel data of selected frame to PPM/ASCII file + * + ** @param stream open C++ output stream + * + ** @return status, true if successful, false otherwise + */ + int writePPM(STD_NAMESPACE ostream& stream) const + { + if (Data != NULL) + { + register T2 *p = Data; + register unsigned long i; + register int j; + for (i = FrameSize; i != 0; --i) + for (j = 3; j != 0; --j) + stream << OFstatic_cast(unsigned long, *(p++)) << " "; // typecast to resolve problems with 'char' + return 1; + } + return 0; + } + + /** write pixel data of selected frame to PPM/ASCII file + * + ** @param stream open C file stream + * + ** @return status, true if successful, false otherwise + */ + int writePPM(FILE *stream) const + { + if (Data != NULL) + { + register T2 *p = Data; + register unsigned long i; + register int j; + for (i = FrameSize; i != 0; --i) + for (j = 3; j != 0; --j) + fprintf(stream, "%lu ", OFstatic_cast(unsigned long, *(p++))); + return 1; + } + return 0; + } + + + protected: + + /// pointer to the storage area where the output data should be stored + T2 *Data; + + + private: + + /** convert intermediate pixel data to output format (render pixel data) + * + ** @param pixel pointer to intermediate pixel representation (color) + * @param start offset to first pixel to be converted + * @param bits1 bit depth of input data (intermediate) + * @param bits2 bit depth of output data + * @param planar flag indicating whether data shall be stored color-by-pixel or color-by-plane + * @param inverse invert pixel data if true (0/0/0 = white) + */ + void convert(const T1 *pixel[3], + const unsigned long start, + const int bits1, + const int bits2, + const int planar, + const int inverse) + { + if ((pixel[0] != NULL) && (pixel[1] != NULL) && (pixel[2] != NULL)) + { + if (Data == NULL) + Data = new T2[FrameSize * 3]; + if (Data != NULL) + { + DCMIMAGE_DEBUG("converting color pixel data to output format"); + register T2 *q = Data; + register unsigned long i; + const T2 max2 = OFstatic_cast(T2, DicomImageClass::maxval(bits2)); + if (planar) + { + register const T1 *p; + if (bits1 == bits2) + { + for (int j = 0; j < 3; ++j) + { + p = pixel[j] + start; + /* invert output data */ + if (inverse) + { + for (i = Count; i != 0; --i) // copy inverted data + *(q++) = max2 - OFstatic_cast(T2, *(p++)); + } else { + for (i = Count; i != 0; --i) // copy + *(q++) = OFstatic_cast(T2, *(p++)); + } + if (Count < FrameSize) + { + OFBitmanipTemplate::zeroMem(q, FrameSize - Count); // set remaining pixels of frame to zero + q += (FrameSize - Count); + } + } + } + else if (bits1 < bits2) // optimization possible using LUT + { + const double gradient1 = OFstatic_cast(double, DicomImageClass::maxval(bits2)) / + OFstatic_cast(double, DicomImageClass::maxval(bits1)); + const T2 gradient2 = OFstatic_cast(T2, gradient1); + for (int j = 0; j < 3; ++j) + { + p = pixel[j] + start; + if (gradient1 == OFstatic_cast(double, gradient2)) // integer multiplication? + { + /* invert output data */ + if (inverse) + { + for (i = Count; i != 0; --i) // expand depth & invert + *(q++) = max2 - OFstatic_cast(T2, *(p++)) * gradient2; + } else { + for (i = Count; i != 0; --i) // expand depth + *(q++) = OFstatic_cast(T2, *(p++)) * gradient2; + } + } else { + /* invert output data */ + if (inverse) + { + for (i = Count; i != 0; --i) // expand depth & invert + *(q++) = max2 - OFstatic_cast(T2, OFstatic_cast(double, *(p++)) * gradient1); + } else { + for (i = Count; i != 0; --i) // expand depth + *(q++) = OFstatic_cast(T2, OFstatic_cast(double, *(p++)) * gradient1); + } + } + if (Count < FrameSize) + { + OFBitmanipTemplate::zeroMem(q, FrameSize - Count); // set remaining pixels of frame to zero + q += (FrameSize - Count); + } + } // ... to be enhanced ! + } + else /* bits1 > bits2 */ + { + const int shift = bits1 - bits2; + for (int j = 0; j < 3; ++j) + { + p = pixel[j] + start; + /* invert output data */ + if (inverse) + { + for (i = Count; i != 0; --i) // reduce depth & invert + *(q++) = max2 - OFstatic_cast(T2, *(p++) >> shift); + } else { + for (i = Count; i != 0; --i) // reduce depth + *(q++) = OFstatic_cast(T2, *(p++) >> shift); + } + if (Count < FrameSize) + { + OFBitmanipTemplate::zeroMem(q, FrameSize - Count); // set remaining pixels of frame to zero + q += (FrameSize - Count); + } + } + } + } + else /* not planar */ + { + register int j; + if (bits1 == bits2) + { + /* invert output data */ + if (inverse) + { + for (i = start; i < start + Count; ++i) + for (j = 0; j < 3; ++j) // copy inverted data + *(q++) = max2 - OFstatic_cast(T2, pixel[j][i]); + } else { + for (i = start; i < start + Count; ++i) + for (j = 0; j < 3; ++j) // copy + *(q++) = OFstatic_cast(T2, pixel[j][i]); + } + } + else if (bits1 < bits2) // optimization possible using LUT + { + const double gradient1 = OFstatic_cast(double, DicomImageClass::maxval(bits2)) / + OFstatic_cast(double, DicomImageClass::maxval(bits1)); + const T2 gradient2 = OFstatic_cast(T2, gradient1); + if (gradient1 == OFstatic_cast(double, gradient2)) // integer multiplication? + { + /* invert output data */ + if (inverse) + { + for (i = start; i < start + Count; ++i) // expand depth & invert + for (j = 0; j < 3; ++j) + *(q++) = max2 - OFstatic_cast(T2, pixel[j][i]) * gradient2; + } else { + for (i = start; i < start + Count; ++i) + for (j = 0; j < 3; ++j) // expand depth + *(q++) = OFstatic_cast(T2, pixel[j][i]) * gradient2; + } + } else { + /* invert output data */ + if (inverse) + { + for (i = start; i < start + Count; ++i) + for (j = 0; j < 3; ++j) // expand depth & invert + *(q++) = max2 - OFstatic_cast(T2, OFstatic_cast(double, pixel[j][i]) * gradient1); + } else { + for (i = start; i < start + Count; ++i) + for (j = 0; j < 3; ++j) // expand depth + *(q++) = OFstatic_cast(T2, OFstatic_cast(double, pixel[j][i]) * gradient1); + } + } + } + else /* bits1 > bits2 */ + { + const int shift = bits1 - bits2; + /* invert output data */ + if (inverse) + { + for (i = start; i < start + Count; ++i) + for (j = 0; j < 3; ++j) // reduce depth & invert + *(q++) = max2 - OFstatic_cast(T2, pixel[j][i] >> shift); + } else { + for (i = start; i < start + Count; ++i) + for (j = 0; j < 3; ++j) // reduce depth + *(q++) = OFstatic_cast(T2, pixel[j][i] >> shift); + } + } + if (Count < FrameSize) + OFBitmanipTemplate::zeroMem(q, 3 * (FrameSize - Count)); // set remaining pixels of frame to zero + } + } + } else + Data = NULL; + } + + /// flag indicating whether the output data buffer should be deleted in the destructor + int DeleteData; + /// flag indicating whether pixel data is stored color-by-pixel or color-by-plane + int isPlanar; + + // --- declarations to avoid compiler warnings + + DiColorOutputPixelTemplate(const DiColorOutputPixelTemplate &); + DiColorOutputPixelTemplate &operator=(const DiColorOutputPixelTemplate &); +}; + + +#endif diff --git a/dcmimage/include/dcmtk/dcmimage/dicopx.h b/dcmimage/include/dcmtk/dcmimage/dicopx.h new file mode 100644 index 00000000..3a937f15 --- /dev/null +++ b/dcmimage/include/dcmtk/dcmimage/dicopx.h @@ -0,0 +1,167 @@ +/* + * + * Copyright (C) 1996-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimage + * + * Author: Joerg Riesmeier + * + * Purpose: DicomColorPixel (Header) + * + */ + + +#ifndef DICOPX_H +#define DICOPX_H + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/dcmimage/dilogger.h" +#include "dcmtk/dcmimgle/dipixel.h" + + +/*------------------------* + * forward declarations * + *------------------------*/ + +class DiDocument; +class DiInputPixel; +class DiMonoPixel; +class DiColorPixel; + + +/*---------------------* + * class declaration * + *---------------------*/ + + +/** Abstract base class to handle color pixel data + */ +class DCMTK_DCMIMAGE_EXPORT DiColorPixel + : public DiPixel +{ + + public: + + /** constructor + * + ** @param docu pointer to the DICOM document + * @param pixel pointer to input pixel data + * @param samples number of expected samples per pixel (for checking purposes) + * @param status status of the image object (reference variable) + * @param sample_rate dummy parameter (used for derived classes only) + */ + DiColorPixel(const DiDocument *docu, + const DiInputPixel *pixel, + const Uint16 samples, + EI_Status &status, + const Uint16 sample_rate = 0); + + /** destructor + */ + virtual ~DiColorPixel(); + + /** get number of planes + * + ** @return number of planes (here 3, color) + */ + inline int getPlanes() const + { + return 3; + } + + /** get planar configuration of the original pixel data + * + ** @return planar configuration (0 = color-by-pixel, 1 = color-by-plane) + */ + inline int getPlanarConfiguration() const + { + return PlanarConfiguration; + } + + /** fill given memory block with pixel data (all three image planes, RGB) + * + ** @param data pointer to memory block (array of 8 or 16 bit values, OB/OW) + * @param count number of T-size entries allocated in the 'data' array + * @param fcount number of pixels per frame + * @param frames total number of frames present in intermediate representation + * @param planar flag indicating whether data shall be stored color-by-pixel or color-by-plane + * + ** @return OFTrue if successful, OFFalse otherwise + */ + virtual OFBool getPixelData(void *data, + const unsigned long count, + const unsigned long fcount, + const unsigned long frames, + const int planar) const = 0; + + /** create true color (24/32 bit) bitmap for MS Windows. + * + ** @param data untyped pointer memory buffer (set to NULL if not allocated externally) + * @param size size of the memory buffer in bytes (if 0 'data' is set to NULL) + * @param width number of columns of the image + * @param height number of rows of the image + * @param frame index of frame to be converted (starting from 0) + * @param fromBits number of bits per sample used for internal representation of the image + * @param toBits number of bits per sample used for the output bitmap (<= 8) + * @param mode color output mode (24 or 32 bits, see dcmimgle/dcmimage.h for details) + * @param upsideDown specifies the order of lines in the images (0 = top-down, bottom-up otherwise) + * @param padding align each line to a 32-bit address if true + * + ** @return number of bytes allocated by the bitmap, or 0 if an error occured + */ + virtual unsigned long createDIB(void *&data, + const unsigned long size, + const Uint16 width, + const Uint16 height, + const unsigned long frame, + const int fromBits, + const int toBits, + const int mode, + const int upsideDown, + const int padding) const = 0; + + /** create true color (32 bit) bitmap for Java (AWT default format). + * + ** @param data resulting pointer to bitmap data (set to NULL if an error occurred) + * @param width number of columns of the image + * @param height number of rows of the image + * @param frame index of frame to be converted (starting from 0) + * @param fromBits number of bits per sample used for internal representation of the image + * @param toBits number of bits per sample used for the output bitmap (<= 8) + * + ** @return number of bytes allocated by the bitmap, or 0 if an error occured + */ + virtual unsigned long createAWTBitmap(void *&data, + const Uint16 width, + const Uint16 height, + const unsigned long frame, + const int fromBits, + const int toBits) const = 0; + + + protected: + + /** constructor + * + ** @param pixel pointer to intermediate color pixel data + * @param count number of pixels + */ + DiColorPixel(const DiColorPixel *pixel, + const unsigned long count); + + /// planar configuration of the original pixel data (0 = color-by-pixel, 1 = color-by-plane) + int PlanarConfiguration; +}; + + +#endif diff --git a/dcmimage/include/dcmtk/dcmimage/dicopxt.h b/dcmimage/include/dcmtk/dcmimage/dicopxt.h new file mode 100644 index 00000000..875590cc --- /dev/null +++ b/dcmimage/include/dcmtk/dcmimage/dicopxt.h @@ -0,0 +1,601 @@ +/* + * + * Copyright (C) 1996-2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimage + * + * Author: Joerg Riesmeier + * + * Purpose: DicomColorPixelTemplate (Header) + * + */ + + +#ifndef DICOPXT_H +#define DICOPXT_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/ofstd/ofbmanip.h" + +#include "dcmtk/dcmimage/dicopx.h" +#include "dcmtk/dcmimgle/dipxrept.h" + + +/********************************************************************/ + + +inline Uint8 removeSign(const Uint8 value, const Uint8) +{ + return value; +} + + +inline Uint16 removeSign(const Uint16 value, const Uint16) +{ + return value; +} + + +inline Uint32 removeSign(const Uint32 value, const Uint32) +{ + return value; +} + + +inline Uint8 removeSign(const Sint8 value, const Sint8 offset) +{ + return OFstatic_cast(Uint8, OFstatic_cast(Sint16, value) + OFstatic_cast(Sint16, offset) + 1); +} + + +inline Uint16 removeSign(const Sint16 value, const Sint16 offset) +{ + return OFstatic_cast(Uint16, OFstatic_cast(Sint32, value) + OFstatic_cast(Sint32, offset) + 1); +} + +/* +inline Uint32 removeSign(const Sint32 value, const Sint32 offset) +{ + return (value < 0) ? OFstatic_cast(Uint32, value + offset + 1) : OFstatic_cast(Uint32, value) + OFstatic_cast(Uint32, offset) + 1; +} + + +inline Uint8 removeSign(const Sint8 value, const Uint8 mask) +{ + return OFstatic_cast(Uint8, value) ^ mask; +} + + +inline Uint16 removeSign(const Sint16 value, const Uint16 mask) +{ + return OFstatic_cast(Uint16, value) ^ mask; +} +*/ + +inline Uint32 removeSign(const Sint32 value, const Uint32 mask) +{ + return OFstatic_cast(Uint32, value) ^ mask; +} + + +/*---------------------* + * class declaration * + *---------------------*/ + +/** Template class to handle color pixel data + */ +template +class DiColorPixelTemplate + : public DiColorPixel, + public DiPixelRepresentationTemplate +{ + + public: + + /** constructor + * + ** @param docu pointer to the DICOM document + * @param pixel pointer to input pixel data + * @param samples number of expected samples per pixel (for checking purposes) + * @param status status of the image object (reference variable) + * @param sample_rate dummy parameter (used for derived classes only) + */ + DiColorPixelTemplate(const DiDocument *docu, + const DiInputPixel *pixel, + const Uint16 samples, + EI_Status &status, + const Uint16 sample_rate = 0) + : DiColorPixel(docu, pixel, samples, status, sample_rate) + { + Data[0] = NULL; + Data[1] = NULL; + Data[2] = NULL; + } + + /** destructor + */ + virtual ~DiColorPixelTemplate() + { +#if defined(HAVE_STD__NOTHROW) && defined(HAVE_NOTHROW_DELETE) + /* use a non-throwing delete (if available) */ + operator delete[] (Data[0], std::nothrow); + operator delete[] (Data[1], std::nothrow); + operator delete[] (Data[2], std::nothrow); +#else + delete[] Data[0]; + delete[] Data[1]; + delete[] Data[2]; +#endif + } + + /** get integer representation + * + ** @return integer representation of the internally stored pixel data + */ + inline EP_Representation getRepresentation() const + { + return DiPixelRepresentationTemplate::getRepresentation(); + } + + /** get pointer to internal array of pixel data. + * The returned array [0..2] points to the three image planes. + * + ** @return pointer to array of pixel data + */ + inline const void *getData() const + { + return OFstatic_cast(const void *, Data); + } + + /** get pointer to internal array of pixel data. + * The returned array [0..2] points to the three image planes. + * + ** @return pointer to array of pixel data + */ + inline void *getDataPtr() + { + return OFstatic_cast(void *, Data); + } + + /** get pointer to internal array of pixel data. + * The returned array [0..2] points to the three image planes. + * + ** @return reference to pointer to pixel data + */ + inline void *getDataArrayPtr() + { + return OFstatic_cast(void *, Data); + } + + /** fill given memory block with pixel data (all three image planes, RGB) + * + ** @param data pointer to memory block (array of 8 or 16 bit values, OB/OW) + * @param count number of T-size entries allocated in the 'data' array + * @param fcount number of pixels per frame + * @param frames total number of frames present in intermediate representation + * @param planar flag indicating whether data shall be stored color-by-pixel or color-by-plane + * + ** @return OFTrue if successful, OFFalse otherwise + */ + OFBool getPixelData(void *data, + const unsigned long count, + const unsigned long fcount, + const unsigned long frames, + const int planar) const + { + OFBool result = OFFalse; + /* check parameters and internal data */ + if ((data != NULL) && (count >= Count * 3) && (frames > 0) && (frames * fcount <= Count) && + (Data[0] != NULL) && (Data[1] != NULL) && (Data[2] != NULL)) + { + register T *q = OFstatic_cast(T *, data); + register int j; + register unsigned long k; + register unsigned long offset = 0; + if (planar) + { + /* for all frames ... */ + for (k = 0; k < frames; ++k) + { + /* copy all three planes to the given memory block */ + for (j = 0; j < 3; ++j) + { + OFBitmanipTemplate::copyMem(Data[j] + offset, q, fcount); + q += fcount; + } + offset += fcount; + } + } else { + register unsigned long i; + /* for all frames ... */ + for (k = 0; k < frames; ++k) + { + /* copy pixel data values from internal representation */ + for (i = 0; i < fcount; ++i) + { + for (j = 0; j < 3; ++j) + *(q++) = Data[j][i + offset]; + } + offset += fcount; + } + } + result = OFTrue; + } + return result; + } + + /** create true color (24/32 bit) bitmap for MS Windows. + * + ** @param data untyped pointer memory buffer (set to NULL if not allocated externally) + * @param size size of the memory buffer in bytes (if 0 'data' is set to NULL) + * @param width number of columns of the image + * @param height number of rows of the image + * @param frame index of frame to be converted (starting from 0) + * @param fromBits number of bits per sample used for internal representation of the image + * @param toBits number of bits per sample used for the output bitmap (<= 8) + * @param mode color output mode (24 or 32 bits, see dcmimgle/dcmimage.h for details) + * @param upsideDown specifies the order of lines in the images (0 = top-down, bottom-up otherwise) + * @param padding align each line to a 32-bit address if true + * + ** @return number of bytes allocated by the bitmap, or 0 if an error occurred + */ + unsigned long createDIB(void *&data, + const unsigned long size, + const Uint16 width, + const Uint16 height, + const unsigned long frame, + const int fromBits, + const int toBits, + const int mode, + const int upsideDown, + const int padding) const + { + unsigned long bytes = 0; + if ((Data[0] != NULL) && (Data[1] != NULL) && (Data[2] != NULL) && (toBits <= 8)) + { + const unsigned long count = OFstatic_cast(unsigned long, width) * OFstatic_cast(unsigned long, height); + const unsigned long start = count * frame + ((upsideDown) ? + OFstatic_cast(unsigned long, height - 1) * OFstatic_cast(unsigned long, width) : 0); + const signed long nextRow = (upsideDown) ? -2 * OFstatic_cast(signed long, width) : 0; + register const T *r = Data[0] + start; + register const T *g = Data[1] + start; + register const T *b = Data[2] + start; + register Uint16 x; + register Uint16 y; + if (mode == 24) // 24 bits per pixel + { + const unsigned long wid3 = OFstatic_cast(unsigned long, width) * 3; + // each line has to start at 32-bit-address, if 'padding' is true + const int gap = (padding) ? OFstatic_cast(int, (4 - (wid3 & 0x3)) & 0x3) : 0; + unsigned long fsize = (wid3 + gap) * OFstatic_cast(unsigned long, height); + if ((data == NULL) || (size >= fsize)) + { + if (data == NULL) + data = new Uint8[fsize]; + if (data != NULL) + { + register Uint8 *q = OFstatic_cast(Uint8 *, data); + if (fromBits == toBits) + { + /* copy pixel data as is */ + for (y = height; y != 0; y--) + { + for (x = width; x != 0; x--) + { + /* reverse sample order: B-G-R */ + *(q++) = OFstatic_cast(Uint8, *(b++)); + *(q++) = OFstatic_cast(Uint8, *(g++)); + *(q++) = OFstatic_cast(Uint8, *(r++)); + } + r += nextRow; g += nextRow; b += nextRow; // go backwards if 'upsideDown' + q += gap; // new line: jump to next 32-bit address + } + } + else if (fromBits < toBits) + { + /* increase color depth: multiply with factor */ + const double gradient1 = OFstatic_cast(double, DicomImageClass::maxval(toBits)) / + OFstatic_cast(double, DicomImageClass::maxval(fromBits)); + const Uint8 gradient2 = OFstatic_cast(Uint8, gradient1); + if (gradient1 == OFstatic_cast(double, gradient2)) // integer multiplication? + { + for (y = height; y != 0; y--) + { + for (x = width; x != 0; x--) + { + /* reverse sample order: B-G-R */ + *(q++) = OFstatic_cast(Uint8, *(b++) * gradient2); + *(q++) = OFstatic_cast(Uint8, *(g++) * gradient2); + *(q++) = OFstatic_cast(Uint8, *(r++) * gradient2); + } + r += nextRow; g += nextRow; b += nextRow; // go backwards if 'upsideDown' + q += gap; // new line: jump to next 32-bit address + } + } else { + for (y = height; y != 0; y--) + { + for (x = width; x != 0; x--) + { + /* reverse sample order: B-G-R */ + *(q++) = OFstatic_cast(Uint8, OFstatic_cast(double, *(b++)) * gradient1); + *(q++) = OFstatic_cast(Uint8, OFstatic_cast(double, *(g++)) * gradient1); + *(q++) = OFstatic_cast(Uint8, OFstatic_cast(double, *(r++)) * gradient1); + } + r += nextRow; g += nextRow; b += nextRow; // go backwards if 'upsideDown' + q += gap; // new line: jump to next 32-bit address + } + } + } + else /* fromBits > toBits */ + { + /* reduce color depth: right shift */ + const int shift = fromBits - toBits; + for (y = height; y != 0; y--) + { + for (x = width; x != 0; x--) + { + /* reverse sample order: B-G-R */ + *(q++) = OFstatic_cast(Uint8, *(b++) >> shift); + *(q++) = OFstatic_cast(Uint8, *(g++) >> shift); + *(q++) = OFstatic_cast(Uint8, *(r++) >> shift); + } + r += nextRow; g += nextRow; b += nextRow; // go backwards if 'upsideDown' + q += gap; // new line: jump to next 32-bit address + } + } + bytes = fsize; + } + } + } + else if (mode == 32) // 32 bits per pixel + { + const unsigned long fsize = count * 4; + if ((data == NULL) || (size >= fsize)) + { + if (data == NULL) + data = new Uint32[count]; + if (data != NULL) + { + register Uint32 *q = OFstatic_cast(Uint32 *, data); + if (fromBits == toBits) + { + /* copy pixel data as is */ + for (y = height; y != 0; y--) + { + for (x = width; x != 0; x--) + { + /* normal sample order: 0-R-G-B */ + *(q++) = (OFstatic_cast(Uint32, *(r++)) << 16) | + (OFstatic_cast(Uint32, *(g++)) << 8) | + OFstatic_cast(Uint32, *(b++)); + } + r += nextRow; g += nextRow; b += nextRow; // go backwards if 'upsideDown' + } + } + else if (fromBits < toBits) + { + /* increase color depth: multiply with factor */ + const double gradient1 = OFstatic_cast(double, DicomImageClass::maxval(toBits)) / + OFstatic_cast(double, DicomImageClass::maxval(fromBits)); + const Uint32 gradient2 = OFstatic_cast(Uint32, gradient1); + if (gradient1 == OFstatic_cast(double, gradient2)) // integer multiplication? + { + for (y = height; y != 0; y--) + { + for (x = width; x != 0; x--) + { + /* normal sample order: 0-R-G-B */ + *(q++) = (OFstatic_cast(Uint32, *(r++) * gradient2) << 16) | + (OFstatic_cast(Uint32, *(g++) * gradient2) << 8) | + OFstatic_cast(Uint32, *(b++) * gradient2); + } + r += nextRow; g += nextRow; b += nextRow; // go backwards if 'upsideDown' + } + } else { + for (y = height; y != 0; y--) + { + for (x = width; x != 0; x--) + { + /* normal sample order: 0-R-G-B */ + *(q++) = (OFstatic_cast(Uint32, OFstatic_cast(double, *(r++)) * gradient1) << 16) | + (OFstatic_cast(Uint32, OFstatic_cast(double, *(g++)) * gradient1) << 8) | + OFstatic_cast(Uint32, OFstatic_cast(double, *(b++)) * gradient1); + } + r += nextRow; g += nextRow; b += nextRow; // go backwards if 'upsideDown' + } + } + } + else /* fromBits > toBits */ + { + /* reduce color depth: right shift */ + const int shift = fromBits - toBits; + for (y = height; y != 0; y--) + { + for (x = width; x != 0; x--) + { + /* normal sample order: 0-R-G-B */ + *(q++) = (OFstatic_cast(Uint32, *(r++) >> shift) << 16) | + (OFstatic_cast(Uint32, *(g++) >> shift) << 8) | + OFstatic_cast(Uint32, *(b++) >> shift); + } + r += nextRow; g += nextRow; b += nextRow; // go backwards if 'upsideDown' + } + } + bytes = fsize; + } + } + } + } + return bytes; + } + + /** create true color (32 bit) bitmap for Java (AWT default format). + * + ** @param data resulting pointer to bitmap data (set to NULL if an error occurred) + * @param width number of columns of the image + * @param height number of rows of the image + * @param frame index of frame to be converted (starting from 0) + * @param fromBits number of bits per sample used for internal representation of the image + * @param toBits number of bits per sample used for the output bitmap (<= 8) + * + ** @return number of bytes allocated by the bitmap, or 0 if an error occurred + */ + unsigned long createAWTBitmap(void *&data, + const Uint16 width, + const Uint16 height, + const unsigned long frame, + const int fromBits, + const int toBits) const + { + data = NULL; + unsigned long bytes = 0; + if ((Data[0] != NULL) && (Data[1] != NULL) && (Data[2] != NULL) && (toBits <= 8)) + { + const unsigned long count = OFstatic_cast(unsigned long, width) * OFstatic_cast(unsigned long, height); + data = new Uint32[count]; + if (data != NULL) + { + const unsigned long start = count * frame; + register const T *r = Data[0] + start; + register const T *g = Data[1] + start; + register const T *b = Data[2] + start; + register Uint32 *q = OFstatic_cast(Uint32 *, data); + register unsigned long i; + if (fromBits == toBits) + { + /* copy pixel data as is */ + for (i = count; i != 0; --i) + { + /* sample order: R-G-B */ + *(q++) = (OFstatic_cast(Uint32, *(r++)) << 24) | + (OFstatic_cast(Uint32, *(g++)) << 16) | + (OFstatic_cast(Uint32, *(b++)) << 8); + } + } + else if (fromBits < toBits) + { + /* increase color depth: multiply with factor */ + const double gradient1 = OFstatic_cast(double, DicomImageClass::maxval(toBits)) / + OFstatic_cast(double, DicomImageClass::maxval(fromBits)); + const Uint32 gradient2 = OFstatic_cast(Uint32, gradient1); + if (gradient1 == OFstatic_cast(double, gradient2)) // integer multiplication? + { + for (i = count; i != 0; --i) + { + /* sample order: R-G-B */ + *(q++) = (OFstatic_cast(Uint32, *(r++) * gradient2) << 24) | + (OFstatic_cast(Uint32, *(g++) * gradient2) << 16) | + (OFstatic_cast(Uint32, *(b++) * gradient2) << 8); + } + } else { + for (i = count; i != 0; --i) + { + /* sample order: R-G-B */ + *(q++) = (OFstatic_cast(Uint32, OFstatic_cast(double, *(r++)) * gradient1) << 24) | + (OFstatic_cast(Uint32, OFstatic_cast(double, *(g++)) * gradient1) << 16) | + (OFstatic_cast(Uint32, OFstatic_cast(double, *(b++)) * gradient1) << 8); + } + } + } + else /* fromBits > toBits */ + { + /* reduce color depth: right shift */ + const int shift = fromBits - toBits; + for (i = count; i != 0; --i) + { + /* sample order: R-G-B */ + *(q++) = (OFstatic_cast(Uint32, *(r++) >> shift) << 24) | + (OFstatic_cast(Uint32, *(g++) >> shift) << 16) | + (OFstatic_cast(Uint32, *(b++) >> shift) << 8); + } + } + bytes = count * 4; + } + } + return bytes; + } + + + protected: + + /** constructor + * + ** @param pixel pointer to intermediate color pixel data + * @param count number of pixels + */ + DiColorPixelTemplate(const DiColorPixel *pixel, + const unsigned long count) + : DiColorPixel(pixel, count) + { + Data[0] = NULL; + Data[1] = NULL; + Data[2] = NULL; + } + + /** initialize internal memory + * + ** @param pixel pointer to input pixel data + * + ** @return true (1) if successful, false (0) otherwise + */ + inline int Init(const void *pixel) + { + int result = 0; + if (pixel != NULL) + { + result = 1; + /* allocate data buffer for the 3 planes */ + for (int j = 0; j < 3; j++) + { +#ifdef HAVE_STD__NOTHROW + /* use a non-throwing new here (if available) because the allocated buffer can be huge */ + Data[j] = new (std::nothrow) T[Count]; +#else + /* make sure that the pointer is set to NULL in case of error */ + try + { + Data[j] = new T[Count]; + } + catch (STD_NAMESPACE bad_alloc const &) + { + Data[j] = NULL; + } +#endif + if (Data[j] != NULL) + { + /* erase empty part of the buffer (=blacken the background) */ + if (InputCount < Count) + OFBitmanipTemplate::zeroMem(Data[j] + InputCount, Count - InputCount); + } else { + DCMIMAGE_DEBUG("cannot allocate memory buffer for 'Data[" << j << "]' in DiColorPixelTemplate::Init()"); + result = 0; // at least one buffer could not be allocated! + } + } + } + return result; + } + + + /// pointer to pixel data (3 components) + T *Data[3]; + + + private: + + // --- declarations to avoid compiler warnings + + DiColorPixelTemplate(const DiColorPixelTemplate &); + DiColorPixelTemplate &operator=(const DiColorPixelTemplate &); +}; + + +#endif diff --git a/dcmimage/include/dcmtk/dcmimage/dicorot.h b/dcmimage/include/dcmtk/dcmimage/dicorot.h new file mode 100644 index 00000000..a1533fe8 --- /dev/null +++ b/dcmimage/include/dcmtk/dcmimage/dicorot.h @@ -0,0 +1,107 @@ +/* + * + * Copyright (C) 1998-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimgle + * + * Author: Joerg Riesmeier + * + * Purpose: DicomColorRotateTemplate (Header) + * + */ + + +#ifndef DICOROT_H +#define DICOROT_H + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/dcmimage/dicopxt.h" +#include "dcmtk/dcmimgle/dirotat.h" + + +/*---------------------* + * class declaration * + *---------------------*/ + +/** Template class to rotate color images (on pixel data level). + * by steps of 90 degrees + */ +template +class DiColorRotateTemplate + : public DiColorPixelTemplate, + protected DiRotateTemplate +{ + + public: + + /** constructor + * + ** @param pixel pointer to intermediate pixel representation + * @param src_cols width of clipping area + * @param src_rows height of clipping area + * @param dest_cols width of destination image (scaled image) + * @param dest_rows height of destination image + * @param frames number of frames + * @param degree angle by which the pixel data should be rotated + */ + DiColorRotateTemplate(const DiColorPixel *pixel, + const Uint16 src_cols, + const Uint16 src_rows, + const Uint16 dest_cols, + const Uint16 dest_rows, + const Uint32 frames, + const int degree) + : DiColorPixelTemplate(pixel, OFstatic_cast(unsigned long, dest_cols) * OFstatic_cast(unsigned long, dest_rows) * frames), + DiRotateTemplate(3, src_cols, src_rows, dest_cols, dest_rows, frames) + { + if ((pixel != NULL) && (pixel->getCount() > 0)) + { + if (pixel->getCount() == OFstatic_cast(unsigned long, src_cols) * OFstatic_cast(unsigned long, src_rows) * frames) + rotate(OFstatic_cast(const T **, OFconst_cast(void *, pixel->getData())), degree); + else { + DCMIMAGE_WARN("could not rotate image ... corrupted data"); + } + } + } + + /** destructor + */ + ~DiColorRotateTemplate() + { + } + + + private: + + /** rotate pixel data + * + ** @param pixel pointer to pixel data (3 components) to be rotated + * @param degree angle by which the pixel data should be rotated + */ + inline void rotate(const T *pixel[3], + const int degree) + { + if (this->Init(pixel)) + { + if (degree == 90) + this->rotateRight(pixel, this->Data); + else if (degree == 180) + this->rotateTopDown(pixel, this->Data); + else if (degree == 270) + this->rotateLeft(pixel, this->Data); + } + } +}; + + +#endif diff --git a/dcmimage/include/dcmtk/dcmimage/dicosct.h b/dcmimage/include/dcmtk/dcmimage/dicosct.h new file mode 100644 index 00000000..8eb31715 --- /dev/null +++ b/dcmimage/include/dcmtk/dcmimage/dicosct.h @@ -0,0 +1,109 @@ +/* + * + * Copyright (C) 1996-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimage + * + * Author: Joerg Riesmeier + * + * Purpose: DicomColorScaleTemplate (Header) + * + */ + + +#ifndef DICOSCT_H +#define DICOSCT_H + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/dcmimage/dicopxt.h" +#include "dcmtk/dcmimgle/discalet.h" + + +/*---------------------* + * class declaration * + *---------------------*/ + +/** Template class to scale color images (on pixel data level). + */ +template +class DiColorScaleTemplate + : public DiColorPixelTemplate, + protected DiScaleTemplate +{ + + public: + + /** constructor + * + ** @param pixel pointer to intermediate pixel representation + * @param columns width of source image + * @param rows height of source image + * @param left_pos left coordinate of clipping area + * @param top_pos top coordinate of clipping area + * @param src_cols width of clipping area + * @param src_rows height of clipping area + * @param dest_cols width of destination image (scaled image) + * @param dest_rows height of destination image + * @param frames number of frames + * @param bits number of bits per plane/pixel + * @param interpolate use of interpolation when scaling + */ + DiColorScaleTemplate(const DiColorPixel *pixel, + const Uint16 columns, + const Uint16 rows, + const signed long left_pos, + const signed long top_pos, + const Uint16 src_cols, + const Uint16 src_rows, + const Uint16 dest_cols, + const Uint16 dest_rows, + const Uint32 frames, + const int bits, + const int interpolate) + : DiColorPixelTemplate(pixel, OFstatic_cast(unsigned long, dest_cols) * OFstatic_cast(unsigned long, dest_rows) * frames), + DiScaleTemplate(3, columns, rows, left_pos, top_pos, src_cols, src_rows, dest_cols, dest_rows, frames, bits) + { + if ((pixel != NULL) && (pixel->getCount() > 0)) + { + if (pixel->getCount() == OFstatic_cast(unsigned long, columns) * OFstatic_cast(unsigned long, rows) * frames) + scale(OFstatic_cast(const T **, OFconst_cast(void *, pixel->getData())), interpolate); + else { + DCMIMAGE_WARN("could not scale image ... corrupted data"); + } + } + } + + /** destructor + */ + virtual ~DiColorScaleTemplate() + { + } + + + private: + + /** scale pixel data + * + ** @param pixel pointer to pixel data (3 components9 to be scaled + * @param interpolate use of interpolation when scaling + */ + inline void scale(const T *pixel[3], + const int interpolate) + { + if (this->Init(pixel)) + this->scaleData(pixel, this->Data, interpolate); + } +}; + + +#endif diff --git a/dcmimage/include/dcmtk/dcmimage/dihsvimg.h b/dcmimage/include/dcmtk/dcmimage/dihsvimg.h new file mode 100644 index 00000000..e9ba8a9a --- /dev/null +++ b/dcmimage/include/dcmtk/dcmimage/dihsvimg.h @@ -0,0 +1,72 @@ +/* + * + * Copyright (C) 1996-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimage + * + * Author: Joerg Riesmeier + * + * Purpose: DicomHSVImage (Header) + * + */ + + +#ifndef DIHSVIMG_H +#define DIHSVIMG_H + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/dcmimage/dicoimg.h" + + +/*---------------------* + * class declaration * + *---------------------*/ + +/** Class for HSV images + */ +class DCMTK_DCMIMAGE_EXPORT DiHSVImage + : public DiColorImage +{ + + public: + + /** constructor + * + ** @param docu pointer to dataset (encapsulated) + * @param status current image status + */ + DiHSVImage(const DiDocument *docu, + const EI_Status status); + + /** destructor + */ + virtual ~DiHSVImage(); + + /** process next couple of frames + * + ** @param fcount number of frames to be processed (0 = same number as before) + * + ** @return status, true if successful, false otherwise + */ + virtual int processNextFrames(const unsigned long fcount); + + + protected: + + /** initialize internal data structures and member variables + */ + void Init(); +}; + + +#endif diff --git a/dcmimage/include/dcmtk/dcmimage/dihsvpxt.h b/dcmimage/include/dcmtk/dcmimage/dihsvpxt.h new file mode 100644 index 00000000..dcabd6ab --- /dev/null +++ b/dcmimage/include/dcmtk/dcmimage/dihsvpxt.h @@ -0,0 +1,210 @@ +/* + * + * Copyright (C) 1996-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimage + * + * Author: Joerg Riesmeier + * + * Purpose: DicomHSVPixelTemplate (Header) + * + */ + + +#ifndef DIHSVPXT_H +#define DIHSVPXT_H + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/dcmimage/dicopxt.h" +#include "dcmtk/dcmimgle/diinpx.h" /* gcc 3.4 needs this */ + + +/*---------------------* + * class declaration * + *---------------------*/ + +/** Template class to handle HSV pixel data + */ +template +class DiHSVPixelTemplate + : public DiColorPixelTemplate +{ + + public: + + /** constructor + * + ** @param docu pointer to DICOM document + * @param pixel pointer to input pixel representation + * @param status reference to status variable + * @param planeSize number of pixels in a plane + * @param bits number of bits per sample + */ + DiHSVPixelTemplate(const DiDocument *docu, + const DiInputPixel *pixel, + EI_Status &status, + const unsigned long planeSize, + const int bits) + : DiColorPixelTemplate(docu, pixel, 3, status) + { + if ((pixel != NULL) && (this->Count > 0) && (status == EIS_Normal)) + convert(OFstatic_cast(const T1 *, pixel->getData()) + pixel->getPixelStart(), planeSize, bits); + } + + /** destructor + */ + virtual ~DiHSVPixelTemplate() + { + } + + + private: + + /** convert input pixel data to intermediate representation + * + ** @param pixel pointer to input pixel data + * @param planeSize number of pixels in a plane + * @param bits number of bits per sample + */ + void convert(const T1 *pixel, + const unsigned long planeSize, + const int bits) + { + if (this->Init(pixel)) + { + register T2 *r = this->Data[0]; + register T2 *g = this->Data[1]; + register T2 *b = this->Data[2]; + const T2 maxvalue = OFstatic_cast(T2, DicomImageClass::maxval(bits)); + const T1 offset = OFstatic_cast(T1, DicomImageClass::maxval(bits - 1)); + // use the number of input pixels derived from the length of the 'PixelData' + // attribute), but not more than the size of the intermediate buffer + const unsigned long count = (this->InputCount < this->Count) ? this->InputCount : this->Count; + if (this->PlanarConfiguration) + { +/* + register const T1 *h = pixel; + register const T1 *s = h + this->InputCount; + register const T1 *v = s + this->InputCount; + for (i = count; i != 0; --i) + convertValue(*(r++), *(g++), *(b++), removeSign(*(h++), offset), removeSign(*(s++), offset), + removeSign(*(v++), offset), maxvalue); +*/ + register unsigned long l; + register unsigned long i = count; + register const T1 *h = pixel; + register const T1 *s = h + planeSize; + register const T1 *v = s + planeSize; + while (i != 0) + { + /* convert a single frame */ + for (l = planeSize; (l != 0) && (i != 0); --l, --i) + { + convertValue(*(r++), *(g++), *(b++), removeSign(*(h++), offset), removeSign(*(s++), offset), + removeSign(*(v++), offset), maxvalue); + } + /* jump to next frame start (skip 2 planes) */ + h += 2 * planeSize; + s += 2 * planeSize; + v += 2 * planeSize; + } + } + else + { + register const T1 *p = pixel; + register T2 h; + register T2 s; + register T2 v; + register unsigned long i; + for (i = count; i != 0; --i) + { + h = removeSign(*(p++), offset); + s = removeSign(*(p++), offset); + v = removeSign(*(p++), offset); + convertValue(*(r++), *(g++), *(b++), h, s, v, maxvalue); + } + } + } + } + + /** convert a single HSV value to RGB + */ + void convertValue(T2 &red, + T2 &green, + T2 &blue, + const T2 hue, + const T2 saturation, + const T2 value, + const T2 maxvalue) + { + /* + * conversion algorithm taken from Foley et al.: 'Computer Graphics: Principles and Practice' (1990) + */ + + if (saturation == 0) + { + red = value; + green = value; + blue = value; + } + else + { + const double h = (OFstatic_cast(double, hue) * 6) / (OFstatic_cast(double, maxvalue) + 1); // '... + 1' to assert h < 6 + const double s = OFstatic_cast(double, saturation) / OFstatic_cast(double, maxvalue); + const double v = OFstatic_cast(double, value) / OFstatic_cast(double, maxvalue); + const T2 hi = OFstatic_cast(T2, h); + const double hf = h - hi; + const T2 p = OFstatic_cast(T2, maxvalue * v * (1 - s)); + const T2 q = OFstatic_cast(T2, maxvalue * v * (1 - s * hf)); + const T2 t = OFstatic_cast(T2, maxvalue * v * (1 - s * (1 - hf))); + switch (hi) + { + case 0: + red = value; + green = t; + blue = p; + break; + case 1: + red = q; + green = value; + blue = p; + break; + case 2: + red = p; + green = value; + blue = t; + break; + case 3: + red = p; + green = q; + blue = value; + break; + case 4: + red = t; + green = p; + blue = value; + break; + case 5: + red = value; + green = p; + blue = q; + break; + default: + DCMIMAGE_WARN("invalid value for 'hi' while converting HSV to RGB"); + } + } + } +}; + + +#endif diff --git a/dcmimage/include/dcmtk/dcmimage/dilogger.h b/dcmimage/include/dcmtk/dcmimage/dilogger.h new file mode 100644 index 00000000..df868824 --- /dev/null +++ b/dcmimage/include/dcmtk/dcmimage/dilogger.h @@ -0,0 +1,41 @@ +/* + * + * Copyright (C) 2009-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimage + * + * Author: Joerg Riesmeier + * + * Purpose: Logger (Header) + * + */ + + +#ifndef DILOGGER_H +#define DILOGGER_H + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/oflog/oflog.h" + +#include "dcmtk/dcmimage/dicdefin.h" + +extern DCMTK_DCMIMAGE_EXPORT OFLogger DCM_dcmimageLogger; + +#define DCMIMAGE_TRACE(msg) OFLOG_TRACE(DCM_dcmimageLogger, msg) +#define DCMIMAGE_DEBUG(msg) OFLOG_DEBUG(DCM_dcmimageLogger, msg) +#define DCMIMAGE_INFO(msg) OFLOG_INFO(DCM_dcmimageLogger, msg) +#define DCMIMAGE_WARN(msg) OFLOG_WARN(DCM_dcmimageLogger, msg) +#define DCMIMAGE_ERROR(msg) OFLOG_ERROR(DCM_dcmimageLogger, msg) +#define DCMIMAGE_FATAL(msg) OFLOG_FATAL(DCM_dcmimageLogger, msg) + +#endif diff --git a/dcmimage/include/dcmtk/dcmimage/dipalimg.h b/dcmimage/include/dcmtk/dcmimage/dipalimg.h new file mode 100644 index 00000000..c0342de8 --- /dev/null +++ b/dcmimage/include/dcmtk/dcmimage/dipalimg.h @@ -0,0 +1,90 @@ +/* + * + * Copyright (C) 1996-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimage + * + * Author: Joerg Riesmeier + * + * Purpose: DicomPaletteImage (Header) + * + */ + + +#ifndef DIPALIMG_H +#define DIPALIMG_H + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/dcmimage/dicoimg.h" + + +/*------------------------* + * forward declarations * + *------------------------*/ + +class DiLookupTable; + + +/*---------------------* + * class declaration * + *---------------------*/ + +/** Class for PALETTE COLOR images + */ +class DCMTK_DCMIMAGE_EXPORT DiPaletteImage + : public DiColorImage +{ + + public: + + /** constructor + * + ** @param docu pointer to dataset (encapsulated) + * @param status current image status + */ + DiPaletteImage(const DiDocument *docu, + const EI_Status status); + + /** destructor + */ + virtual ~DiPaletteImage(); + + /** process next couple of frames + * + ** @param fcount number of frames to be processed (0 = same number as before) + * + ** @return status, true if successful, false otherwise + */ + virtual int processNextFrames(const unsigned long fcount); + + + protected: + + /** initialize internal data structures and member variables + */ + void Init(); + + + private: + + /// three color palettes for R, G and B + DiLookupTable *Palette[3]; + + // --- declarations to avoid compiler warnings + + DiPaletteImage(const DiPaletteImage &); + DiPaletteImage &operator=(const DiPaletteImage &); +}; + + +#endif diff --git a/dcmimage/include/dcmtk/dcmimage/dipalpxt.h b/dcmimage/include/dcmtk/dcmimage/dipalpxt.h new file mode 100644 index 00000000..c29e0b24 --- /dev/null +++ b/dcmimage/include/dcmtk/dcmimage/dipalpxt.h @@ -0,0 +1,115 @@ +/* + * + * Copyright (C) 1996-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimage + * + * Author: Joerg Riesmeier + * + * Purpose: DicomPalettePixelTemplate (Header) + * + */ + + +#ifndef DIPALPXT_H +#define DIPALPXT_H + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/dcmimage/dicopxt.h" +#include "dcmtk/dcmimgle/diluptab.h" +#include "dcmtk/dcmimgle/diinpx.h" /* gcc 3.4 needs this */ + + +/*---------------------* + * class declaration * + *---------------------*/ + +/** Template class to handle Palette color pixel data + */ +template +class DiPalettePixelTemplate + : public DiColorPixelTemplate +{ + + public: + + /** constructor + * + ** @param docu pointer to DICOM document + * @param pixel pointer to input pixel representation + * @param palette pointer to RGB color palette + * @param status reference to status variable + */ + DiPalettePixelTemplate(const DiDocument *docu, + const DiInputPixel *pixel, + DiLookupTable *palette[3], + EI_Status &status) + : DiColorPixelTemplate(docu, pixel, 1, status) + { + if ((pixel != NULL) && (this->Count > 0) && (status == EIS_Normal)) + { + if (this->PlanarConfiguration) + { + status = EIS_InvalidValue; + DCMIMAGE_ERROR("invalid value for 'PlanarConfiguration' (" << this->PlanarConfiguration << ")"); + } + else + convert(OFstatic_cast(const T1 *, pixel->getData()) + pixel->getPixelStart(), palette); + } + } + + /** destructor + */ + virtual ~DiPalettePixelTemplate() + { + } + + + private: + + /** convert input pixel data to intermediate representation + * + ** @param pixel pointer to input pixel data + * @param palette pointer to RGB color palette + */ + void convert(const T1 *pixel, + DiLookupTable *palette[3]) + { // can be optimized if necessary ! + if (this->Init(pixel)) + { + register const T1 *p = pixel; + register T2 value = 0; + register unsigned long i; + register int j; + // use the number of input pixels derived from the length of the 'PixelData' + // attribute), but not more than the size of the intermediate buffer + const unsigned long count = (this->InputCount < this->Count) ? this->InputCount : this->Count; + for (i = 0; i < count; ++i) + { + value = OFstatic_cast(T2, *(p++)); + for (j = 0; j < 3; ++j) + { + if (value <= palette[j]->getFirstEntry(value)) + this->Data[j][i] = OFstatic_cast(T3, palette[j]->getFirstValue()); + else if (value >= palette[j]->getLastEntry(value)) + this->Data[j][i] = OFstatic_cast(T3, palette[j]->getLastValue()); + else + this->Data[j][i] = OFstatic_cast(T3, palette[j]->getValue(value)); + } + } + } + } +}; + + +#endif diff --git a/dcmimage/include/dcmtk/dcmimage/dipipng.h b/dcmimage/include/dcmtk/dcmimage/dipipng.h new file mode 100644 index 00000000..027aacc0 --- /dev/null +++ b/dcmimage/include/dcmtk/dcmimage/dipipng.h @@ -0,0 +1,137 @@ +/* + * + * Copyright (C) 2003-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimage + * + * Author: Alexander Haderer + * + * Purpose: Implements PNG interface for plugable image formats + * + */ + + +#ifndef DIPIPNG_H +#define DIPIPNG_H + +#include "dcmtk/config/osconfig.h" + +#ifdef WITH_LIBPNG + +#include "dcmtk/ofstd/ofstring.h" +#include "dcmtk/dcmimgle/diplugin.h" +#include "dcmtk/dcmimage/dicdefin.h" + + +/*------------------------* + * forward declarations * + *------------------------*/ + +class DiImage; + + +/*--------------------* + * type definitions * + *--------------------*/ + +/** describes the different types of interlace supported by + * the PNG plugin. Enumeration depends on capabilities + * of underlying PNG library (libpng). + */ +enum DiPNGInterlace +{ + /// Adam7 + E_pngInterlaceAdam7, + + /// no interlace + E_pngInterlaceNone +}; + +/** describes the different types of metainfo written to + * the png file + */ +enum DiPNGMetainfo +{ + /// no meta information + E_pngNoMetainfo, + + /// file time, creator + E_pngFileMetainfo +}; + + +/*---------------------* + * class declaration * + *---------------------*/ + +/** Implementation of a PNG plugin for the dcmimgle/dcmimage library + */ +class DCMTK_DCMIMAGE_EXPORT DiPNGPlugin + : public DiPluginFormat +{ + + public: + + /** constructor + */ + DiPNGPlugin(); + + /** destructor + */ + virtual ~DiPNGPlugin(); + + /** write given image to a file stream (PNG format) + * @param image pointer to DICOM image object to be written + * @param stream stream to which the image is written (open in binary mode!) + * @param frame index of frame used for output (default: first frame = 0) + * @return true if successful, false otherwise + */ + virtual int write(DiImage *image, + FILE *stream, + const unsigned long frame = 0) const; + + /** set interlace type for PNG creation + * @param inter interlace type + */ + void setInterlaceType(DiPNGInterlace inter); + + /** set metainfo type for PNG creation + * @param minfo metainfo type + */ + void setMetainfoType(DiPNGMetainfo minfo); + + /* set bits per sample for PNG creation + * @param bpp bits per sample (8 or 16) + */ + void setBitsPerSample(const int bpp); + + /** get version information of the PNG library. + * Typical output format: "LIBPNG, Version 3.5.7" + * @return name and version number of the PNG library + */ + static OFString getLibraryVersionString(); + + + private: + + /// PNG interlace type + DiPNGInterlace interlaceType; + + /// PNG metainfo type + DiPNGMetainfo metainfoType; + + /// bits per sample (8 or 16, default: 8) + int bitsPerSample; +}; + +#endif +#endif diff --git a/dcmimage/include/dcmtk/dcmimage/dipitiff.h b/dcmimage/include/dcmtk/dcmimage/dipitiff.h new file mode 100644 index 00000000..17d564ea --- /dev/null +++ b/dcmimage/include/dcmtk/dcmimage/dipitiff.h @@ -0,0 +1,146 @@ +/* + * + * Copyright (C) 2001-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmjpeg + * + * Author: Marco Eichelberg + * + * Purpose: Implements TIFF interface for plugable image formats + * + */ + + +#ifndef DIPITIFF_H +#define DIPITIFF_H + +#include "dcmtk/config/osconfig.h" + +#ifdef WITH_LIBTIFF + +#include "dcmtk/ofstd/ofstring.h" + +#include "dcmtk/dcmimgle/diplugin.h" + +#include "dcmtk/dcmimage/dicdefin.h" + + +/*------------------------* + * forward declarations * + *------------------------*/ + +class DiImage; + + +/*--------------------* + * type definitions * + *--------------------*/ + +/** describes the different types of compression supported by + * the TIFF plugin. Enumeration depends on capabilities + * of underlying TIFF library (libtiff). + */ +enum DiTIFFCompression +{ + /// PackBits compression (RLE) + E_tiffPackBitsCompression, + + /// LZW compression + E_tiffLZWCompression, + + /// uncompressed + E_tiffNoCompression +}; + +/** describes the optional predictor used with TIFF LZW compression + */ +enum DiTIFFLZWPredictor +{ + /// omit preditor tag (defaults to no prediction) + E_tiffLZWPredictorDefault, + + /// predictor 1: no prediction scheme + E_tiffLZWPredictorNoPrediction, + + /// predictor 2: use horizontal differencing + E_tiffLZWPredictorHDifferencing +}; + + +/*---------------------* + * class declaration * + *---------------------*/ + +/** Implementation of a TIFF plugin for the dcmimgle/dcmimage library + */ +class DCMTK_DCMIMAGE_EXPORT DiTIFFPlugin + : public DiPluginFormat +{ + + public: + + /** constructor + */ + DiTIFFPlugin(); + + /** destructor + */ + virtual ~DiTIFFPlugin(); + + /** write given image to a file stream (TIFF format) + * @param image pointer to DICOM image object to be written + * @param stream stream to which the image is written (open in binary mode!) + * @param frame index of frame used for output (default: first frame = 0) + * @return true if successful, false otherwise + */ + virtual int write(DiImage *image, + FILE *stream, + const unsigned long frame = 0) const; + + /** set compression type for TIFF creation + * @param ctype compression type + */ + void setCompressionType(DiTIFFCompression ctype); + + /** set predictor type for LZW compression + * @param pred predictor type + */ + void setLZWPredictor(DiTIFFLZWPredictor pred); + + /** set rows per strip for TIFF creation. + * @param rows rows per strip. By default (value 0), + * rows per strip is calculated automatically such that + * each strip contains about 8 kByte of data. + */ + void setRowsPerStrip(unsigned long rows = 0); + + /** get version information of the TIFF library. + * Typical output format: "LIBTIFF, Version 3.5.7" + * @return name and version number of the TIFF library + */ + static OFString getLibraryVersionString(); + + + private: + + /// TIFF compression type + DiTIFFCompression compressionType; + + /// TIFF predictor type + DiTIFFLZWPredictor predictor; + + /// TIFF rows per strip + unsigned long rowsPerStrip; +}; + +#endif +#endif diff --git a/dcmimage/include/dcmtk/dcmimage/diqtcmap.h b/dcmimage/include/dcmtk/dcmimage/diqtcmap.h new file mode 100644 index 00000000..d989ffcf --- /dev/null +++ b/dcmimage/include/dcmtk/dcmimage/diqtcmap.h @@ -0,0 +1,131 @@ +/* + * + * Copyright (C) 2002-2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimage + * + * Author: Marco Eichelberg + * + * Purpose: class DcmQuantColorMapping + * + */ + + +#ifndef DIQTCMAP_H +#define DIQTCMAP_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmimage/diqttype.h" /* for DcmQuantComponent */ +#include "dcmtk/dcmimgle/dcmimage.h" /* gcc 3.4 needs this */ +#include "dcmtk/dcmimage/diqtstab.h" /* gcc 3.4 needs this */ +#include "dcmtk/dcmimage/diqtpix.h" /* gcc 3.4 needs this */ +#include "dcmtk/dcmimage/diqthash.h" /* gcc 3.4 needs this */ +#include "dcmtk/dcmimage/diqtctab.h" /* gcc 3.4 needs this */ + +class DicomImage; +class DcmQuantColorHashTable; +class DcmQuantColorTable; +class DcmQuantPixel; +class DcmQuantScaleTable; + + +/** template class that maps a color image into a palette color image + * with given color palette. The two template parameters define the + * error diffusion class used to implement e.g. Floyd-Steinberg error + * diffusion and the output type of the color index values, which may be + * 8 bit or 16 bit unsigned integers. + */ +template +class DcmQuantColorMapping +{ +public: + + /** converts a single frame of a color image into a palette color image. + * @param sourceImage color image + * @param frameNumber number of frame (in sourceImage) that is converted + * @param maxval maximum pixel value to which all color samples + * were down-sampled during computation of the histogram on which + * the color LUT is based. This value is required to make sure that the + * hash table doesn't get too large. + * @param cht color hash table. This table is passed by the caller since + * the same hash table can be used if multiple frames are converted. + * Initially (i.e. when called for the first frame) the hash table is empty. + * @param colormap color LUT to which the color image is mapped. + * @param fs error diffusion object, e.g. an instance of class DcmQuantIdent + * or class DcmQuantFloydSteinberg, depending on the template instantiation. + * @param tp pointer to an array to which the palette color image data + * is written. The array must be large enough to store sourceImage.getWidth() + * times sourceImage.getHeight() values of type T2. + */ + static void create( + DicomImage& sourceImage, + unsigned long frameNumber, + unsigned long maxval, + DcmQuantColorHashTable& cht, + DcmQuantColorTable& colormap, + T1& fs, + T2 *tp) + { + unsigned long cols = sourceImage.getWidth(); + unsigned long rows = sourceImage.getHeight(); + const int bits = sizeof(DcmQuantComponent)*8; + DcmQuantPixel px; + long limitcol; + long col; // must be signed! + long maxval_l = OFstatic_cast(long, maxval); + register int ind; + const DcmQuantComponent *currentpixel; + register DcmQuantComponent cr, cg, cb; + + // create scale table + DcmQuantScaleTable scaletable; + scaletable.createTable(OFstatic_cast(DcmQuantComponent, -1), maxval); + + const void *data = sourceImage.getOutputData(bits, frameNumber, 0); + if (data) + { + const DcmQuantComponent *cp = OFstatic_cast(const DcmQuantComponent *, data); + for (unsigned long row = 0; row < rows; ++row) + { + fs.startRow(col, limitcol); + do + { + currentpixel = cp + col + col + col; + cr = *currentpixel++; + cg = *currentpixel++; + cb = *currentpixel; + px.scale(cr, cg, cb, scaletable); + + fs.adjust(px, col, maxval_l); + + // Check hash table to see if we have already matched this color. + ind = cht.lookup(px); + if (ind < 0) + { + ind = colormap.computeIndex(px); + cht.add(px, ind); + } + + fs.propagate(px, colormap.getPixel(ind), col); + tp[col] = OFstatic_cast(T2, ind); + fs.nextCol(col); + } while ( col != limitcol ); + fs.finishRow(); + cp += (cols * 3); // advance source pointer by one row + tp += cols; // advance target pointer by one row + } // for all rows + } // if (data) + } +}; + + +#endif diff --git a/dcmimage/include/dcmtk/dcmimage/diqtctab.h b/dcmimage/include/dcmtk/dcmimage/diqtctab.h new file mode 100644 index 00000000..ffd1cf65 --- /dev/null +++ b/dcmimage/include/dcmtk/dcmimage/diqtctab.h @@ -0,0 +1,232 @@ +/* + * + * Copyright (C) 2002-2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimage + * + * Author: Marco Eichelberg + * + * Purpose: class DcmQuantColorTable + * + */ + + +#ifndef DIQTCTAB_H +#define DIQTCTAB_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/ofstd/oftypes.h" /* for OFBool */ +#include "dcmtk/ofstd/ofcond.h" /* for OFCondition */ +#include "dcmtk/dcmimage/diqtpix.h" /* for DcmQuantPixel */ +#include "dcmtk/dcmimage/diqthash.h" /* for DcmQuantHistogramItem */ +#include "dcmtk/ofstd/ofstring.h" /* for class OFString */ + + +class DicomImage; +class DcmItem; + + +/** this class implements a color table that can either be + * a look-up table or an image color histogram. + */ +class DCMTK_DCMIMAGE_EXPORT DcmQuantColorTable +{ +public: + + /// constructor + DcmQuantColorTable(); + + /// destructor + ~DcmQuantColorTable(); + + /// resets the object to default-constructed state + void clear(); + + /** returns the number of colors in the color table + * @return number of colors in color table + */ + inline unsigned long getColors() const + { + return numColors; + } + + /** creates a description string suitable for use as + * Derivation Description. + * @param str description string returned in this parameter + */ + void setDescriptionString(OFString& str) const; + + /** creates a color table containing a histogram of the given + * image. Pixel sample values are downsampled if necessary + * to make sure the histogram fits into the given size limit. + * @param image color image for which a histogram is computed + * @param maxcolors maximum number of colors allowed in histogram. + * If necessary, pixel sample values are down-sampled to enforce + * this maximum. + * @return EC_Normal if successful, an error code otherwise. + */ + OFCondition computeHistogram(DicomImage& image, unsigned long maxcolors); + + /** after a call to computeHistogram(), this method + * returns the maximum pixel value to which all color samples + * were down-sampled during computation of the histogram. + */ + inline unsigned long getMaxVal() const + { + return maxval; + } + + /** returns the color at index idx. + * @param idx index, must be < getColors() + * @return const reference to color + */ + inline const DcmQuantPixel& getPixel(unsigned long idx) const + { +#ifdef DEBUG + assert(array && idx < numColors); +#endif + return *(array[idx]); + } + + /** returns the red color component at index idx + * @param idx index, must be < getColors() + * @return red color component + */ + inline DcmQuantComponent getRed(unsigned long idx) const + { +#ifdef DEBUG + assert(array && idx < numColors); +#endif + return array[idx]->getRed(); + } + + /** returns the green color component at index idx + * @param idx index, must be < getColors() + * @return green color component + */ + inline DcmQuantComponent getGreen(unsigned long idx) const + { +#ifdef DEBUG + assert(array && idx < numColors); +#endif + return array[idx]->getGreen(); + } + + /** returns the blue color component at index idx + * @param idx index, must be < getColors() + * @return blue color component + */ + inline DcmQuantComponent getBlue(unsigned long idx) const + { +#ifdef DEBUG + assert(array && idx < numColors); +#endif + return array[idx]->getBlue(); + } + + /** computes a color LUT for the given image histogram. + * This median-cut colormap generator is based + * on Paul Heckbert's paper "Color Image Quantization for Frame Buffer + * Display", SIGGRAPH '82 Proceedings, page 297. + * @param histogram image color histogram + * @param sum number of pixels in image (colums * rows * frames) + * @param theMaxval maximum value to which pixels were + * downsampled for histogram computation + * @param numberOfColors desired number of colors in color LUT + * @param largeType algorithm used for determining the largest dimension + * in the Median Cut algorithm + * @param repType algorithm for choosing a representative color for each + * box in the Median Cut algorithm + * @return EC_Normal if successful, an error code otherwise. + */ + OFCondition medianCut( + DcmQuantColorTable& histogram, + unsigned long sum, + unsigned long theMaxval, + unsigned long numberOfColors, + DcmLargestDimensionType largeType, + DcmRepresentativeColorType repType); + + /** determines for a given color the closest match in the color LUT. + * @param px color to look up in LUT + * @return index of closest match in LUT, -1 if look-up table empty + */ + inline int computeIndex(const DcmQuantPixel& px) const + { + int result = -1; + register int r2, g2, b2; + register long newdist; + register int r1 = OFstatic_cast(int, px.getRed()); + register int g1 = OFstatic_cast(int, px.getGreen()); + register int b1 = OFstatic_cast(int, px.getBlue()); + register long dist = 2000000000; + for (unsigned long i = 0; i < numColors; ++i) + { + r2 = r1 - OFstatic_cast(int, array[i]->getRed()); + g2 = g1 - OFstatic_cast(int, array[i]->getGreen()); + b2 = b1 - OFstatic_cast(int, array[i]->getBlue()); + newdist = r2*r2 + g2*g2 + b2*b2; + if (newdist < dist) + { + result = OFstatic_cast(int, i); + dist = newdist; + if (dist < array[i]->getValue()) i=numColors; // break out of for loop + } + } + return result; + } + + /** writes the current color table into a DICOM object, encoded as + * Red/Green/Blue Palette Color Lookup Table and Data. + * @param target DICOM dataset to write to + * @param writeAsOW if true, LUT data is encoded as OW, otherwise LUT data + * is encoded as US. A LUT with 64k entries is always encoded as OW since + * a US data element with 64k entries cannot be written in explicit VR. + * @param write16BitEntries if true, LUT data is encoded with 16 bits per entry + * @return EC_Normal if successful, an error code otherwise. + */ + OFCondition write( + DcmItem& target, + OFBool writeAsOW, + OFBool write16BitEntries); + + +private: + + /** after a call to medianCut(), this method computes for each entry in + * the color map the minimum of the euclidean distances to any other + * of the entries. Any color which has an euclidean distance of less + * than half of this distance is necessarily mapped to this entry. + * This data is used by computeIndex() + */ + void computeClusters(); + + /// private undefined copy constructor + DcmQuantColorTable(const DcmQuantColorTable& src); + + /// private undefined copy assignment operator + DcmQuantColorTable& operator=(const DcmQuantColorTable& src); + + /// color table data + DcmQuantHistogramItemPointer *array; + + /// number of entries in color table + unsigned long numColors; + + /** maximum pixel value to which all color samples + * were down-sampled during computation of the histogram. + */ + unsigned long maxval; + +}; + +#endif diff --git a/dcmimage/include/dcmtk/dcmimage/diqtfs.h b/dcmimage/include/dcmtk/dcmimage/diqtfs.h new file mode 100644 index 00000000..41b5cfcc --- /dev/null +++ b/dcmimage/include/dcmtk/dcmimage/diqtfs.h @@ -0,0 +1,220 @@ +/* + * + * Copyright (C) 2002-2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimage + * + * Author: Marco Eichelberg + * + * Purpose: class DcmQuantFloydSteinberg + * + */ + + +#ifndef DIQTFS_H +#define DIQTFS_H + + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmimage/diqtpix.h" /* for DcmQuantPixel */ +#include "dcmtk/ofstd/ofcond.h" /* for OFCondition */ + + +/** Floyd-Steinberg error vectors are stored internally as integer numbers + * containing the error multiplied by this constant. + */ +#define DcmQuantFloydSteinbergScale 1024 + + +/** this class implements Floyd-Steinberg error diffusion. + * It is used during the color quantization of an image. + */ +class DCMTK_DCMIMAGE_EXPORT DcmQuantFloydSteinberg +{ +public: + + /// constructor + DcmQuantFloydSteinberg(); + + /// destructor + ~DcmQuantFloydSteinberg(); + + /** initializes the Floyd-Steinberg error vectors for an image with the + * given number of columns. + * @param cols number of columns in image + * @return EC_Normal if successful, an error code otherwise. + */ + OFCondition initialize(unsigned long cols); + + /** uses the Floyd-Steinberg error vectors to adjust the color of the current image pixel. + * @param px the original image pixel is passed in this parameter. Upon return, the pixel + * value contains the new value after error diffusion. + * @param col column in which the current pixel is located, must be [0..columns-1] + * @param maxval maximum value for each color component. + */ + inline void adjust(DcmQuantPixel& px, long col, long maxval) + { + register long sr = px.getRed() + thisrerr[col + 1] / DcmQuantFloydSteinbergScale; + register long sg = px.getGreen() + thisgerr[col + 1] / DcmQuantFloydSteinbergScale; + register long sb = px.getBlue() + thisberr[col + 1] / DcmQuantFloydSteinbergScale; + if ( sr < 0 ) sr = 0; + else if ( sr > OFstatic_cast(long, maxval) ) sr = maxval; + if ( sg < 0 ) sg = 0; + else if ( sg > OFstatic_cast(long, maxval) ) sg = maxval; + if ( sb < 0 ) sb = 0; + else if ( sb > OFstatic_cast(long, maxval) ) sb = maxval; + px.assign(OFstatic_cast(DcmQuantComponent, sr), OFstatic_cast(DcmQuantComponent, sg), OFstatic_cast(DcmQuantComponent, sb)); + } + + /** propagates the Floyd-Steinberg error terms for one pixel. + * @param px color value the current image pixel should have (after adjustment) + * @param mapped color value (selected from the color LUT) the current image pixel really uses + * @param col column in which the current pixel is located, must be [0..columns-1] + */ + inline void propagate(const DcmQuantPixel& px, const DcmQuantPixel& mapped, long col) + { + register long err; + + /* Propagate Floyd-Steinberg error terms. */ + if ( fs_direction ) + { + err = ( OFstatic_cast(long, px.getRed()) - OFstatic_cast(long, mapped.getRed()) ) * DcmQuantFloydSteinbergScale; + thisrerr[col + 2] += ( err * 7 ) / 16; + nextrerr[col ] += ( err * 3 ) / 16; + nextrerr[col + 1] += ( err * 5 ) / 16; + nextrerr[col + 2] += ( err ) / 16; + err = ( OFstatic_cast(long, px.getGreen()) - OFstatic_cast(long, mapped.getGreen()) ) * DcmQuantFloydSteinbergScale; + thisgerr[col + 2] += ( err * 7 ) / 16; + nextgerr[col ] += ( err * 3 ) / 16; + nextgerr[col + 1] += ( err * 5 ) / 16; + nextgerr[col + 2] += ( err ) / 16; + err = ( OFstatic_cast(long, px.getBlue()) - OFstatic_cast(long, mapped.getBlue()) ) * DcmQuantFloydSteinbergScale; + thisberr[col + 2] += ( err * 7 ) / 16; + nextberr[col ] += ( err * 3 ) / 16; + nextberr[col + 1] += ( err * 5 ) / 16; + nextberr[col + 2] += ( err ) / 16; + } + else + { + err = ( OFstatic_cast(long, px.getRed()) - OFstatic_cast(long, mapped.getRed()) ) * DcmQuantFloydSteinbergScale; + thisrerr[col ] += ( err * 7 ) / 16; + nextrerr[col + 2] += ( err * 3 ) / 16; + nextrerr[col + 1] += ( err * 5 ) / 16; + nextrerr[col ] += ( err ) / 16; + err = ( OFstatic_cast(long, px.getGreen()) - OFstatic_cast(long, mapped.getGreen()) ) * DcmQuantFloydSteinbergScale; + thisgerr[col ] += ( err * 7 ) / 16; + nextgerr[col + 2] += ( err * 3 ) / 16; + nextgerr[col + 1] += ( err * 5 ) / 16; + nextgerr[col ] += ( err ) / 16; + err = ( OFstatic_cast(long, px.getBlue()) - OFstatic_cast(long, mapped.getBlue()) ) * DcmQuantFloydSteinbergScale; + thisberr[col ] += ( err * 7 ) / 16; + nextberr[col + 2] += ( err * 3 ) / 16; + nextberr[col + 1] += ( err * 5 ) / 16; + nextberr[col ] += ( err ) / 16; + } + } + + /** starts error diffusion for a new row. + * The error vectors for the next image row are initialized to zero. + * The initial and last column of the current row are determined + * @param col initial column for the current row returned in this parameter + * @param limitcol limit column (one past the last valid column) for the + * current row returned in this parameter. May become negative. + */ + inline void startRow(long& col, long& limitcol) + { + for (unsigned long c = 0; c < columns + 2; ++c) + nextrerr[c] = nextgerr[c] = nextberr[c] = 0; + + if (fs_direction) + { + col = 0; + limitcol = columns; + } + else + { + col = columns - 1; + limitcol = -1; + } + } + + /** finishes error diffusion for one image row. The direction flag is + * inverted and the error vectors for the "current" and "next" image row + * are swapped. + */ + inline void finishRow() + { + temperr = thisrerr; + thisrerr = nextrerr; + nextrerr = temperr; + temperr = thisgerr; + thisgerr = nextgerr; + nextgerr = temperr; + temperr = thisberr; + thisberr = nextberr; + nextberr = temperr; + fs_direction = ! fs_direction; + } + + /** increases or decreases the column number + * depending on the direction flag. + * @param col column number, may become negative + */ + inline void nextCol(long& col) const + { + if (fs_direction) ++col; else --col; + } + +private: + + /// frees all memory allocated by the error vectors + void cleanup(); + + /// private undefined copy constructor + DcmQuantFloydSteinberg(const DcmQuantFloydSteinberg& src); + + /// private undefined copy assignment operator + DcmQuantFloydSteinberg& operator=(const DcmQuantFloydSteinberg& src); + + /// current red error vector. Points to an array of (columns + 2) entries. + long *thisrerr; + + /// red error vector for next row. Points to an array of (columns + 2) entries. + long *nextrerr; + + /// current green error vector. Points to an array of (columns + 2) entries. + long *thisgerr; + + /// green error vector for next row. Points to an array of (columns + 2) entries. + long *nextgerr; + + /// current blue error vector. Points to an array of (columns + 2) entries. + long *thisberr; + + /// blue error vector for next row. Points to an array of (columns + 2) entries. + long *nextberr; + + /// temporary pointer used for swapping error vectors + long *temperr; + + /** boolean flag indicating in which direction (left to right/right to left) + * the FS distribution should be done. Flag is inverted after each row. + */ + int fs_direction; + + /// number of columns in image + unsigned long columns; + +}; + + +#endif diff --git a/dcmimage/include/dcmtk/dcmimage/diqthash.h b/dcmimage/include/dcmtk/dcmimage/diqthash.h new file mode 100644 index 00000000..715ee833 --- /dev/null +++ b/dcmimage/include/dcmtk/dcmimage/diqthash.h @@ -0,0 +1,129 @@ +/* + * + * Copyright (C) 2002-2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimage + * + * Author: Marco Eichelberg + * + * Purpose: class DcmQuantColorHashTable + * + */ + + +#ifndef DIQTHASH_H +#define DIQTHASH_H + + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/ofstd/ofvector.h" +#include "dcmtk/dcmimage/diqtpix.h" /* for DcmQuantPixel */ +#include "dcmtk/dcmimage/diqthitl.h" /* for DcmQuantHistogramItemList */ + + +class DicomImage; + +/** this class implements a hash table for colors. + * Each entry of the hash table consists of an RGB + * color (DcmQuantPixel object) and an integer value (e. g. counter). + * This class is used during the quantization of a color image. + */ +class DCMTK_DCMIMAGE_EXPORT DcmQuantColorHashTable +{ +public: + /// constructor + DcmQuantColorHashTable(); + + /// destructor + ~DcmQuantColorHashTable(); + + /** adds a new color to the hash table. The color must not yet + * be present (the caller is responsible for checking this). + * @param colorP color to be added to table + * @param value integer value (counter) associated to color + */ + inline void add(const DcmQuantPixel& colorP, int value) + { + item(colorP).push_front(colorP, value); + } + + /** looks up the given color in the hash table. + * If found, the value associated to the color is returned, -1 otherwise. + * @param colorP color to look up in hash table + * @return value associated to given color if found, -1 otherwise. + */ + inline int lookup(const DcmQuantPixel& colorP) const + { + DcmQuantHistogramItemListPointer const p(m_Table[colorP.hash()]); + return p ? p->lookup(colorP) : -1; + } + + /** adds all pixels of all frames of the given image (which must be a + * color image) to the hash table. The counter (integer value associated + * to each color) counts the occurence of the color in the image. + * If more than maxcolors colors are found, the function returns zero. + * @param image image in which colors are to be counted + * @param newmaxval maximum pixel value to which the contents of the + * image are scaled down (see documentation of class DcmQuantScaleTable) + * before counting colors. This is used by the caller to reduce the number + * of colors in the image if necessary. + * @param maxcolors maximum number of colors allowed. If more colors are found, + * the method immediately returns with a return value of zero. + * @return number of colors found, 0 if too many colors. + */ + unsigned long addToHashTable( + DicomImage& image, + unsigned long newmaxval, + unsigned long maxcolors); + + /** counts the number of entries in the hash table + * @return number of entries in hash table + */ + unsigned long countEntries() const; + + /** converts the contents of this hash table into a histogram array. + * After a successful call to addToHashTable(), this object contains + * an image histogram stored in a hash table. This method creates + * a new array of DcmQuantHistogramItem pointers on the heap + * and moves the contents of the hash table into this array. + * @param array the hash table array is returned in this parameter + * @return number of elements in array + */ + unsigned long createHistogram(DcmQuantHistogramItemPointer *& array); + +private: + + typedef OFVector table_type; + typedef table_type::iterator table_iterator; + typedef table_type::const_iterator const_table_iterator; + + /// private undefined copy constructor + DcmQuantColorHashTable(const DcmQuantColorHashTable& src); + + /// private undefined copy assignment operator + DcmQuantColorHashTable& operator=(const DcmQuantColorHashTable& src); + + /** Retrieves the specified item from the hash table. + * If the item has not been created a new item is created and is returned. + */ + DcmQuantHistogramItemList& item(const DcmQuantPixel& colorP) + { + DcmQuantHistogramItemListPointer& p(m_Table[colorP.hash()]); + return p ? *p : *(p = new DcmQuantHistogramItemList()); + } + + /// hash array of lists for color/value pairs + table_type m_Table; +}; + + +#endif diff --git a/dcmimage/include/dcmtk/dcmimage/diqthitl.h b/dcmimage/include/dcmtk/dcmimage/diqthitl.h new file mode 100644 index 00000000..bb161e14 --- /dev/null +++ b/dcmimage/include/dcmtk/dcmimage/diqthitl.h @@ -0,0 +1,129 @@ +/* + * + * Copyright (C) 2002-2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimage + * + * Author: Marco Eichelberg + * + * Purpose: class DcmQuantHistogramItemList + * + */ + + +#ifndef DIQTHITL_H +#define DIQTHITL_H + + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/ofstd/oflist.h" /* for OFList */ +#include "dcmtk/dcmimage/diqthitm.h" /* for DcmQuantHistogramItem */ + + +/** this is a helper class used by class DcmQuantColorHashTable. + * It maintains a list of DcmQuantHistogramItem objects. + */ +class DCMTK_DCMIMAGE_EXPORT DcmQuantHistogramItemList +{ +public: + + /// constructor + DcmQuantHistogramItemList(); + + /// destructor. Destroys all objects pointed to by list. + ~DcmQuantHistogramItemList(); + + /** this method moves the contents of this list into the given array. + * The list becomes empty if the array is large enough to contain all list members. + * @param array array of pointers to DcmQuantHistogramItem + * @param counter When called, contains the index of the array element + * into which the first member of the list will be moved. Must be < numcolors. + * Upon return, contains the array index of the last element moved + 1. + * @param numcolors number of elements in array + */ + void moveto(DcmQuantHistogramItemPointer *array, unsigned long& counter, unsigned long numcolors); + + /** searches the list for an entry that equals the given pixel value. + * If found, the integer value assigned to that pixel is returned, otherwise returns -1. + * @param colorP pixel to lookup in list + * @return integer value for given color if found, -1 otherwise. + */ + inline int lookup(const DcmQuantPixel& colorP) + { + first = list_.begin(); + while (first != last) + { + if ((*first)->equals(colorP)) return (*first)->getValue(); + ++first; + } + return -1; + } + + /** adds the given pixel to the list. If the pixel is already + * contained in the list, it's integer value (counter) is increased + * and 0 is returned. Otherwise, a new entry with a counter of 1 + * is created and 1 is returned. + * @param colorP pixel to add to the list + * @return 0 if pixel was already in list, 1 otherwise. + */ + inline unsigned long add(const DcmQuantPixel& colorP) + { + first = list_.begin(); + while (first != last) + { + if ((*first)->equals(colorP)) + { + (*first)->incValue(); + return 0; + } + ++first; + } + + // not found in list, create new entry + list_.push_front(new DcmQuantHistogramItem(colorP, 1)); + return 1; + } + + /** inserts a new DcmQuantHistogramItem at the beginning of the list. + * @param colorP pixel value assigned to the new object in the list + * @param value integer value assigned to the new object in the list + */ + inline void push_front(const DcmQuantPixel& colorP, int value) + { + list_.push_front(new DcmQuantHistogramItem(colorP, value)); + } + + /// returns current number of objects in the list + inline size_t size() const + { + return list_.size(); + } + +private: + + /// list of (pointers to) DcmQuantHistogramItem objects + OFList list_; + + /// temporary iterator used in various methods; declared here for efficiency reasons only. + OFListIterator(DcmQuantHistogramItem *) first; + + /// constant iterator which always contains list_.end(); declared here for efficiency reasons only. + OFListIterator(DcmQuantHistogramItem *) last; + +}; + + +/// typedef for a pointer to a DcmQuantHistogramItemList object +typedef DcmQuantHistogramItemList *DcmQuantHistogramItemListPointer; + + +#endif diff --git a/dcmimage/include/dcmtk/dcmimage/diqthitm.h b/dcmimage/include/dcmtk/dcmimage/diqthitm.h new file mode 100644 index 00000000..be2b3cb0 --- /dev/null +++ b/dcmimage/include/dcmtk/dcmimage/diqthitm.h @@ -0,0 +1,109 @@ +/* + * + * Copyright (C) 2002-2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimage + * + * Author: Marco Eichelberg + * + * Purpose: class DcmQuantHistogramItem + * + */ + + +#ifndef DIQTHITM_H +#define DIQTHITM_H + + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/ofstd/oftypes.h" /* for OFBool */ +#include "dcmtk/dcmimage/diqtpix.h" /* for DcmQuantPixel */ + + +/** this class extends DcmQuantPixel by an integer value + * which is used for various purposes. + * The class is used as a helper class during computation of an image + * histogram, as a member of a color LUT and as a member of a color hash + * table. + */ +class DCMTK_DCMIMAGE_EXPORT DcmQuantHistogramItem: public DcmQuantPixel +{ +public: + /** constructor + * @param colorP pixel value + * @param val initial value + */ + DcmQuantHistogramItem(const DcmQuantPixel& colorP, int val) + : DcmQuantPixel(colorP) + , value(val) + { + } + + /// default constructor + DcmQuantHistogramItem() + : DcmQuantPixel() + , value(0) + { + } + + // we don't declare a destructor here, but the standard destructor will do. + + /** compares the stored pixel value with the given pixel. + * @param colorP pixel to compare with + * @return true if pixel values are equal, false otherwise + */ + inline OFBool equals(const DcmQuantPixel& colorP) const + { + return *this == colorP; + } + + /// returns the integer value maintained by this object + inline int getValue() const + { + return value; + } + + /** assigns a new integer value to this object + * @param v new value + */ + inline void setValue(int v) + { + value = v; + } + + /// increases the integer value maintained by this object by one + inline void incValue() + { + ++value; + } + +private: + + /** integer value assigned to this pixel. This value is used for different + * purposes. + * During computation of a histogram it is used as a counter that counts + * the instances of the current color. + * In a color hash table, it contains the index value from the color LUT + * assigned to this color. + * In a color LUT, it is the cluster value, i.e. the radius in which all + * color are guaranteed to be mapped to this palette color. + */ + int value; + +}; + + +/// typedef for a pointer to a DcmQuantHistogramItem object +typedef DcmQuantHistogramItem *DcmQuantHistogramItemPointer; + + +#endif diff --git a/dcmimage/include/dcmtk/dcmimage/diqtid.h b/dcmimage/include/dcmtk/dcmimage/diqtid.h new file mode 100644 index 00000000..9ae02e15 --- /dev/null +++ b/dcmimage/include/dcmtk/dcmimage/diqtid.h @@ -0,0 +1,100 @@ +/* + * + * Copyright (C) 2002-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimage + * + * Author: Marco Eichelberg + * + * Purpose: class DcmQuantIdent + * + */ + + +#ifndef DIQTID_H +#define DIQTID_H + + +#include "dcmtk/config/osconfig.h" + + +class DcmQuantPixel; + + +/** pseudo error diffusion class implementing an identity transformation. + * This class implements a public API mostly identical to that + * of class DcmQuantFloydSteinberg. + * Since several methods of the error diffusion class are called for each + * single image pixel during conversion of a color image to palette color, + * we do not use virtual methods and a common abstract base class here. + * Instead we implement all methods inline, and use a template to select + * the appropriate class at compile time. With a decent optimizer this + * reduces the overhead for using this class to zero. + */ +class DCMTK_DCMIMAGE_EXPORT DcmQuantIdent +{ +public: + + /// constructor + DcmQuantIdent(unsigned long cols) + : columns(cols) + { + } + + /// destructor + ~DcmQuantIdent() + { + } + + /// dummy method needed for API compatibility with DcmQuantFloydSteinberg + inline void adjust(DcmQuantPixel&, long, long) + { + } + + /// dummy method needed for API compatibility with DcmQuantFloydSteinberg + inline void propagate(const DcmQuantPixel&, const DcmQuantPixel&, long) + { + } + + /** starts a new row. The initial and last column of the current row are determined. + * @param col initial column for the current row returned in this parameter + * @param limitcol limit column (one past the last valid column) for the + * current row returned in this parameter. + */ + inline void startRow(long& col, long& limitcol) + { + col = 0; + limitcol = columns; + } + + /// dummy method needed for API compatibility with DcmQuantFloydSteinberg + inline void finishRow() + { + } + + /** increases the column number + * @param col column number + */ + inline void nextCol(long& col) const + { + ++col; + } + +private: + + /// number of columns in image + unsigned long columns; + +}; + + +#endif diff --git a/dcmimage/include/dcmtk/dcmimage/diqtpbox.h b/dcmimage/include/dcmtk/dcmimage/diqtpbox.h new file mode 100644 index 00000000..97498766 --- /dev/null +++ b/dcmimage/include/dcmtk/dcmimage/diqtpbox.h @@ -0,0 +1,116 @@ +/* + * + * Copyright (C) 2002-2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimage + * + * Author: Marco Eichelberg + * + * Purpose: class DcmQuantPixelBoxArray + * + */ + + +#ifndef DIQTPBOX_H +#define DIQTPBOX_H + + +#include "dcmtk/config/osconfig.h" + +#define INCLUDE_CSTDLIB +#define INCLUDE_CASSERT +#include "dcmtk/ofstd/ofstdinc.h" + +#include "dcmtk/dcmimage/dicdefin.h" + +BEGIN_EXTERN_C +#ifdef HAVE_SYS_TYPES_H +/* needed e.g. on Solaris for definition of size_t */ +#include +#endif +END_EXTERN_C + +/** helper structure for class DcmQuantPixelBoxArray. + * Each object of this class represents a pixel box used in the + * Median Cut algorithm. + */ +struct DCMTK_DCMIMAGE_EXPORT DcmQuantPixelBox +{ + /// index of the color histogram array where the colors represented by this box start + int ind; + + /// the number of colors represented by this box + int colors; + + /// the number of pixels represented by this box + unsigned long sum; +}; + + +/// typedef for a pointer to a DcmQuantPixelBox object +typedef DcmQuantPixelBox *DcmQuantPixelBoxPointer; + + +/** helper class for the Median Cut algorithm. An object of + * this class maintains an array of pixel boxes which is used + * to determine a color look-up table of given size for a + * true color image. + */ +class DCMTK_DCMIMAGE_EXPORT DcmQuantPixelBoxArray +{ +public: + + /** constructor. Creates an array with the given number of pixel boxes. + * @param entries number of entries in array, must be > 0. + */ + DcmQuantPixelBoxArray(unsigned long entries); + + /// destructor + ~DcmQuantPixelBoxArray(); + + /** looks up an array element + * @param idx index, must be smaller than the number of entries + * with which this object was initialized + * @return non-const reference to DcmQuantPixelBox struct + */ + inline DcmQuantPixelBox& operator[](size_t idx) + { +#ifdef DEBUG + assert(idx < length); +#endif + return *(array[idx]); + } + + /** sorts the given number of pixel boxes in the array, + * starting with the first array element. + * The boxes are sorted in decreasing order of the "sum" member. + * @param boxes number of boxes to sort, must be <= entries. + */ + void sort(unsigned long boxes); + +private: + + /// private undefined copy constructor + DcmQuantPixelBoxArray(const DcmQuantPixelBoxArray& src); + + /// private undefined copy assignment operator + DcmQuantPixelBoxArray& operator=(const DcmQuantPixelBoxArray& src); + + /// array of pixel boxes + DcmQuantPixelBoxPointer *array; + + /// number of elements in array + unsigned long length; +}; + + +#endif diff --git a/dcmimage/include/dcmtk/dcmimage/diqtpix.h b/dcmimage/include/dcmtk/dcmimage/diqtpix.h new file mode 100644 index 00000000..87ff6d52 --- /dev/null +++ b/dcmimage/include/dcmtk/dcmimage/diqtpix.h @@ -0,0 +1,165 @@ +/* + * + * Copyright (C) 2002-2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimage + * + * Author: Marco Eichelberg + * + * Purpose: class DcmQuantPixel + * + */ + + +#ifndef DIQTPIX_H +#define DIQTPIX_H + + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/ofstd/oftypes.h" /* for OFBool */ +#include "dcmtk/dcmimage/diqttype.h" /* for DcmQuantHashSize, DcmQuantComponent */ +#include "dcmtk/dcmimage/diqtstab.h" /* for DcmScaleTable */ + + +/** objects of this class represent individual RGB pixels. This class is + * used by the color quantization classes. For efficiency considerations, + * all methods are declared inline. + */ +class DCMTK_DCMIMAGE_EXPORT DcmQuantPixel +{ +public: + + /** default constructor, creates black pixel + */ + DcmQuantPixel() + : red(0) + , green(0) + , blue(0) + { + } + + /** copy assignment constructor + */ + DcmQuantPixel(const DcmQuantPixel& arg) + : red(arg.red) + , green(arg.green) + , blue(arg.blue) + { + } + + /** destructor + */ + virtual ~DcmQuantPixel() + { + } + + // we don't declare a destructor here, but the standard destructor will do. + + /// comparison operator for equality + inline OFBool operator==(const DcmQuantPixel& src) const + { + return (red == src.red) && (green == src.green) && (blue == src.blue); + } + + /** this method computes the luminance of the current pixel + * according to the NTSC formula. The range of the luminance equals the + * range of the underlying DcmQuantComponent type. However, the + * luminance is returned as a double. + * @return luminance of this pixel + */ + inline double luminance() const + { + return 0.299 * red + 0.587 * green + 0.114 * blue; + } + + /** this method computes an unsigned long hash value for the current pixel. + * The hash algorithm is taken from Jef Poskanzer's ppm utility library. + * The return value is guaranteed to be < DcmQuantHashSize. + * @return hash value for current pixel + */ + inline unsigned long hash() const + { + return ((OFstatic_cast(unsigned long, red) * 33023UL + OFstatic_cast(unsigned long, green) * 30013UL + + OFstatic_cast(unsigned long, blue) * 27011UL) & 0x7fffffffUL) % DcmQuantHashSize; + } + + /** returns the red component + * @return red component of this pixel + */ + inline DcmQuantComponent getRed() const + { + return red; + } + + /** returns the green component + * @return green component of this pixel + */ + inline DcmQuantComponent getGreen() const + { + return green; + } + + /** returns the blue component + * @return blue component of this pixel + */ + inline DcmQuantComponent getBlue() const + { + return blue; + } + + /** assigns new R, G and B values to this pixel + * @param r new R + * @param g new G + * @param b new B + */ + inline void assign( + DcmQuantComponent r, + DcmQuantComponent g, + DcmQuantComponent b) + { + red = r; + green = g; + blue = b; + } + + /** assigns new R, G and B values to this pixel + * using the given scale table in which all + * three values are looked up. + * @param r new R + * @param g new G + * @param b new B + * @param table scale table (LUT) in which R, G and B are looked up. + */ + inline void scale( + DcmQuantComponent r, + DcmQuantComponent g, + DcmQuantComponent b, + const DcmQuantScaleTable& table) + { + red = table[r]; + green = table[g]; + blue = table[b]; + } + +private: + /// red color component of this pixel + DcmQuantComponent red; + + /// green color component of this pixel + DcmQuantComponent green; + + /// blue color component of this pixel + DcmQuantComponent blue; +}; + + +#endif diff --git a/dcmimage/include/dcmtk/dcmimage/diqtstab.h b/dcmimage/include/dcmtk/dcmimage/diqtstab.h new file mode 100644 index 00000000..aab01920 --- /dev/null +++ b/dcmimage/include/dcmtk/dcmimage/diqtstab.h @@ -0,0 +1,115 @@ +/* + * + * Copyright (C) 2002-2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimage + * + * Author: Marco Eichelberg + * + * Purpose: class DcmQuantScaleTable + * + */ + + +#ifndef DIQTSTAB_H +#define DIQTSTAB_H + + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/ofstd/ofcast.h" +#include "dcmtk/dcmimage/diqttype.h" /* for DcmQuantComponent */ + +#define INCLUDE_CSTDLIB +#define INCLUDE_CASSERT +#include "dcmtk/ofstd/ofstdinc.h" + + +/** this is a helper class used for temporarily reducing the image bit depth + * during calculation of an image histogram. An object of this class + * contains a look-up table that maps image pixel values to scaled-down + * image pixel values. + */ +class DCMTK_DCMIMAGE_EXPORT DcmQuantScaleTable +{ +public: + + /// constructor + DcmQuantScaleTable() + : table(NULL) + , numEntries(0) + { + } + + /// destructor + ~DcmQuantScaleTable() + { + cleanup(); + } + + /** array look-up operation. + * @param idx pixel value to look up. Object must be initialized + * (i.e. createTable() must have been called before) and idx must + * be less or equal to the parameter oldmaxval passed to createTable(). + * @return scaled-down value from look-up table. + */ + inline DcmQuantComponent operator[](unsigned int idx) const + { +#ifdef DEBUG + assert(idx < numEntries); +#endif + return table[idx]; + } + + /** initializes the look-up table. + * @param oldmaxval maximum possible pixel value in source image + * @param newmaxval new desired maximum value, should be < oldmaxval + */ + void createTable( + unsigned long oldmaxval, + unsigned long newmaxval) + { + cleanup(); + + table = new DcmQuantComponent[oldmaxval+1]; + if (table) + { + numEntries = OFstatic_cast(unsigned int, oldmaxval) + 1; + for (unsigned int i=0; i < numEntries; i++) + table[i] = OFstatic_cast(DcmQuantComponent, (OFstatic_cast(unsigned long, i) * newmaxval + oldmaxval/2) / oldmaxval); + } + } + +private: + + /// resets the object to the default-constructed state + inline void cleanup() + { + delete[] table; + table = NULL; + numEntries = 0; + } + + /// private undefined copy constructor + DcmQuantScaleTable(const DcmQuantScaleTable& src); + + /// private undefined copy assignment operator + DcmQuantScaleTable& operator=(const DcmQuantScaleTable& src); + + /// array of pixel values + DcmQuantComponent *table; + + /// number of entries in array + unsigned int numEntries; +}; + + +#endif diff --git a/dcmimage/include/dcmtk/dcmimage/diqttype.h b/dcmimage/include/dcmtk/dcmimage/diqttype.h new file mode 100644 index 00000000..2a86b07f --- /dev/null +++ b/dcmimage/include/dcmtk/dcmimage/diqttype.h @@ -0,0 +1,74 @@ +/* + * + * Copyright (C) 2002-2010, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimage + * + * Author: Marco Eichelberg + * + * Purpose: typdefs and constants for the color quantization classes + * + */ + + +#ifndef DIQTTYPE_H +#define DIQTTYPE_H + + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/dcmimage/dicdefin.h" + +/// the basic type for pixel color components +typedef unsigned char DcmQuantComponent; + +/// size of color hash table. Don't touch this. +#define DcmQuantHashSize 20023UL + +/** maximum number of colors we count in a color histogram. + * If the number of colors turns out to be larger than this, + * then the image bit depth is reduced until the number + * of colors becomes smaller than this maximum. + */ +#define DcmQuantMaxColors 65536 + + +/** defines the algorithm used for determining the + * largest dimension in the Median Cut algorithm + */ +enum DcmLargestDimensionType +{ + /// determine dimension by comparing the range in RGB space (default) + DcmLargestDimensionType_default, + + /// determine dimension by transforming into luminance before comparison + DcmLargestDimensionType_luminance +}; + + +/** defines the algorithm for choosing a representative color for each + * box in the Median Cut algorithm + */ +enum DcmRepresentativeColorType +{ + /// average all the colors in the box (as specified in Heckbert's paper; this is the default) + DcmRepresentativeColorType_default, + + /// average all pixels in the box + DcmRepresentativeColorType_averagePixels, + + /// choose center of the box, ignoring any structure within the boxes + DcmRepresentativeColorType_centerOfBox + +}; + +#endif diff --git a/dcmimage/include/dcmtk/dcmimage/diquant.h b/dcmimage/include/dcmtk/dcmimage/diquant.h new file mode 100644 index 00000000..23993f02 --- /dev/null +++ b/dcmimage/include/dcmtk/dcmimage/diquant.h @@ -0,0 +1,85 @@ +/* + * + * Copyright (C) 2002-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimage + * + * Author: Marco Eichelberg + * + * Purpose: class DcmQuantFloydSteinberg + * + */ + + +#ifndef DIQUANT_H +#define DIQUANT_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/ofstd/ofcond.h" /* for OFCondition */ +#include "dcmtk/dcmdata/dctypes.h" /* for Uint32 etc. */ +#include "dcmtk/dcmimage/diqttype.h" /* for enums */ +#include "dcmtk/ofstd/ofstring.h" /* for class OFString */ + + +class DicomImage; +class DcmItem; +class DcmTagKey; + + +class DCMTK_DCMIMAGE_EXPORT DcmQuant +{ +public: + + /** converts the given color image into a palette color image. + * All frames of the image are converted. The converted result + * is written as a complete Image Pixel module to the given + * target item. + * @param sourceImage DICOM color image + * @param target target item to which the palette color image is written + * @param writeAsOW if true, the LUT Data attributes are encoded as OW instead + * US. LUT Data is always written as OW if numberOfColors is 65536. + * @param write16BitEntries if true, LUT data is encoded with 16 bits per entry + * @param floydSteinberg determines whether or not to use Floyd-Steinberg + * error diffusion during creation of the palette color image + * @param numberOfColors desired number of colors in the color palette. + * Valid range is [2..65536]. + * @param description description string suitable for use as + * Derivation Description returned in this parameter + * @param largeType algorithm used for determining the largest dimension + * in the Median Cut algorithm + * @param repType algorithm for choosing a representative color for each + * box in the Median Cut algorithm + * @return EC_Normal if successful, an error code otherwise. + */ + static OFCondition createPaletteColorImage( + DicomImage& sourceImage, + DcmItem& target, + OFBool writeAsOW, + OFBool write16BitEntries, + OFBool floydSteinberg, + Uint32 numberOfColors, + OFString& description, + DcmLargestDimensionType largeType = DcmLargestDimensionType_default, + DcmRepresentativeColorType repType = DcmRepresentativeColorType_default); + + /** create Derivation Description. If a derivation description + * already exists, the old text is appended to the new text. + * @param dataset dataset to be modified + * @param description description string. + * @return EC_Normal if successful, an error code otherwise + */ + static OFCondition updateDerivationDescription(DcmItem *dataset, const char *description); + +}; + + +#endif diff --git a/dcmimage/include/dcmtk/dcmimage/diregist.h b/dcmimage/include/dcmtk/dcmimage/diregist.h new file mode 100644 index 00000000..098025ae --- /dev/null +++ b/dcmimage/include/dcmtk/dcmimage/diregist.h @@ -0,0 +1,88 @@ +/* + * + * Copyright (C) 1998-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimage + * + * Author: Joerg Riesmeier + * + * Purpose: DicomRegister (Header) + * + */ + + +#ifndef DIREGIST_H +#define DIREGIST_H + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/dcmimgle/diregbas.h" + +#include "dcmtk/dcmimage/dicdefin.h" + + +/*---------------------* + * class declaration * + *---------------------*/ + +/** Class to register color support to dcmimgle library + */ +class DCMTK_DCMIMAGE_EXPORT DiRegister + : public DiRegisterBase +{ + + public: + + /** constructor + */ + DiRegister(); + + /** destructor + */ + virtual ~DiRegister(); + + /** create color image representation + * + ** @param docu pointer to dataset (encapsulated) + * @param status image status + * @param photo photometric interpretation + * + ** @return pointer to new DiImage object (NULL if an error occurred) + */ + virtual DiImage *createImage(const DiDocument *docu, + const EI_Status status, + const EP_Interpretation photo); + + /** create monochrome pixel data from color image + * + ** @param image pointer to color image + * @param red coefficient by which the red component is weighted + * @param green coefficient by which the green component is weighted + * @param blue coefficient by which the blue component is weighted + * + ** @return pointer to new DiImage object (NULL if an error occurred) + */ + virtual DiMonoPixel *createMonoImageData(const DiColorImage *image, + const double red, + const double green, + const double blue); +}; + + +/*------------------* + * initialization * + *------------------*/ + +static DiRegister Init_dcmimage_Module; // registration pointer is initialized in class constructor + + +#endif diff --git a/dcmimage/include/dcmtk/dcmimage/dirgbimg.h b/dcmimage/include/dcmtk/dcmimage/dirgbimg.h new file mode 100644 index 00000000..02322d4f --- /dev/null +++ b/dcmimage/include/dcmtk/dcmimage/dirgbimg.h @@ -0,0 +1,72 @@ +/* + * + * Copyright (C) 1996-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimage + * + * Author: Joerg Riesmeier + * + * Purpose: DicomRGBImage (Header) + * + */ + + +#ifndef DIRGBIMG_H +#define DIRGBIMG_H + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/dcmimage/dicoimg.h" + + +/*---------------------* + * class declaration * + *---------------------*/ + +/** Class for RGB images + */ +class DCMTK_DCMIMAGE_EXPORT DiRGBImage + : public DiColorImage +{ + + public: + + /** constructor + * + ** @param docu pointer to dataset (encapsulated) + * @param status current image status + */ + DiRGBImage(const DiDocument *docu, + const EI_Status status); + + /** destructor + */ + virtual ~DiRGBImage(); + + /** process next couple of frames + * + ** @param fcount number of frames to be processed (0 = same number as before) + * + ** @return status, true if successful, false otherwise + */ + virtual int processNextFrames(const unsigned long fcount); + + + protected: + + /** initialize internal data structures and member variables + */ + void Init(); +}; + + +#endif diff --git a/dcmimage/include/dcmtk/dcmimage/dirgbpxt.h b/dcmimage/include/dcmtk/dcmimage/dirgbpxt.h new file mode 100644 index 00000000..ed6c0ee0 --- /dev/null +++ b/dcmimage/include/dcmtk/dcmimage/dirgbpxt.h @@ -0,0 +1,134 @@ +/* + * + * Copyright (C) 1996-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimage + * + * Author: Joerg Riesmeier + * + * Purpose: DicomRGBPixelTemplate (Header) + * + */ + + +#ifndef DIRGBPXT_H +#define DIRGBPXT_H + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/dcmimage/dicopxt.h" +#include "dcmtk/dcmimgle/diinpx.h" /* gcc 3.4 needs this */ + + +/*---------------------* + * class declaration * + *---------------------*/ + +/** Template class to handle RGB pixel data + */ +template +class DiRGBPixelTemplate + : public DiColorPixelTemplate +{ + + public: + + /** constructor + * + ** @param docu pointer to DICOM document + * @param pixel pointer to input pixel representation + * @param status reference to status variable + * @param planeSize number of pixel in a single plane + * @param bits number of bits per sample + */ + DiRGBPixelTemplate(const DiDocument *docu, + const DiInputPixel *pixel, + EI_Status &status, + const unsigned long planeSize, + const int bits) + : DiColorPixelTemplate(docu, pixel, 3, status) + { + if ((pixel != NULL) && (this->Count > 0) && (status == EIS_Normal)) + convert(OFstatic_cast(const T1 *, pixel->getData()) + pixel->getPixelStart(), planeSize, bits); + } + + /** destructor + */ + virtual ~DiRGBPixelTemplate() + { + } + + + private: + + /** convert input pixel data to intermediate representation + * + ** @param pixel pointer to input pixel data + * @param planeSize number of pixels in a plane + * @param bits number of bits per sample + */ + void convert(const T1 *pixel, + const unsigned long planeSize, + const int bits) + { + if (this->Init(pixel)) + { + // use the number of input pixels derived from the length of the 'PixelData' + // attribute), but not more than the size of the intermediate buffer + const unsigned long count = (this->InputCount < this->Count) ? this->InputCount : this->Count; + const T1 offset = OFstatic_cast(T1, DicomImageClass::maxval(bits - 1)); + register const T1 *p = pixel; + if (this->PlanarConfiguration) + { +/* + register T2 *q; + // number of pixels to be skipped (only applicable if 'PixelData' contains more + // pixels than expected) + const unsigned long skip = (this->InputCount > this->Count) ? (this->InputCount - this->Count) : 0; + for (int j = 0; j < 3; ++j) + { + q = this->Data[j]; + for (i = count; i != 0; --i) + *(q++) = removeSign(*(p++), offset); + // skip to beginning of next plane + p += skip; + } +*/ + register unsigned long l; + register unsigned long i = 0; + while (i < count) + { + /* store current pixel index */ + const unsigned long iStart = i; + /* for all planes ... */ + for (int j = 0; j < 3; ++j) + { + /* convert a single plane */ + for (l = planeSize, i = iStart; (l != 0) && (i < count); --l, ++i) + this->Data[j][i] = removeSign(*(p++), offset); + } + } + } + else + { + register int j; + register unsigned long i; + for (i = 0; i < count; ++i) /* for all pixel ... */ + for (j = 0; j < 3; ++j) + this->Data[j][i] = removeSign(*(p++), offset); /* ... copy planes */ + } + } + } +}; + + +#endif diff --git a/dcmimage/include/dcmtk/dcmimage/diybrimg.h b/dcmimage/include/dcmtk/dcmimage/diybrimg.h new file mode 100644 index 00000000..3c348c80 --- /dev/null +++ b/dcmimage/include/dcmtk/dcmimage/diybrimg.h @@ -0,0 +1,72 @@ +/* + * + * Copyright (C) 1998-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimage + * + * Author: Joerg Riesmeier + * + * Purpose: DicomYBRImage (Header) + * + */ + + +#ifndef DIYBRIMG_H +#define DIYBRIMG_H + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/dcmimage/dicoimg.h" + + +/*---------------------* + * class declaration * + *---------------------*/ + +/** Class for YCbCr images + */ +class DCMTK_DCMIMAGE_EXPORT DiYBRImage + : public DiColorImage +{ + + public: + + /** constructor + * + ** @param docu pointer to dataset (encapsulated) + * @param status current image status + */ + DiYBRImage(const DiDocument *docu, + const EI_Status status); + + /** destructor + */ + virtual ~DiYBRImage(); + + /** process next couple of frames + * + ** @param fcount number of frames to be processed (0 = same number as before) + * + ** @return status, true if successful, false otherwise + */ + virtual int processNextFrames(const unsigned long fcount); + + + protected: + + /** initialize internal data structures and member variables + */ + void Init(); +}; + + +#endif diff --git a/dcmimage/include/dcmtk/dcmimage/diybrpxt.h b/dcmimage/include/dcmtk/dcmimage/diybrpxt.h new file mode 100644 index 00000000..f926aca8 --- /dev/null +++ b/dcmimage/include/dcmtk/dcmimage/diybrpxt.h @@ -0,0 +1,284 @@ +/* + * + * Copyright (C) 1998-2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimage + * + * Author: Joerg Riesmeier + * + * Purpose: DicomYBRPixelTemplate (Header) + * + */ + + +#ifndef DIYBRPXT_H +#define DIYBRPXT_H + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/dcmimage/dicopxt.h" +#include "dcmtk/dcmimgle/diinpx.h" /* gcc 3.4 needs this */ + + +/*---------------------* + * class declaration * + *---------------------*/ + +/** Template class to handle YCbCr pixel data + */ +template +class DiYBRPixelTemplate + : public DiColorPixelTemplate +{ + + public: + + /** constructor + * + ** @param docu pointer to DICOM document + * @param pixel pointer to input pixel representation + * @param status reference to status variable + * @param planeSize number of pixels in a plane + * @param bits number of bits per sample + * @param rgb flag, convert color model to RGB only if true + */ + DiYBRPixelTemplate(const DiDocument *docu, + const DiInputPixel *pixel, + EI_Status &status, + const unsigned long planeSize, + const int bits, + const OFBool rgb) + : DiColorPixelTemplate(docu, pixel, 3, status) + { + if ((pixel != NULL) && (this->Count > 0) && (status == EIS_Normal)) + convert(OFstatic_cast(const T1 *, pixel->getData()) + pixel->getPixelStart(), planeSize, bits, rgb); + } + + /** destructor + */ + virtual ~DiYBRPixelTemplate() + { + } + + + private: + + /** convert input pixel data to intermediate representation + * + ** @param pixel pointer to input pixel data + * @param planeSize number of pixels in a plane + * @param bits number of bits per sample + * @param rgb flag, convert color model to RGB only if true + */ + void convert(const T1 *pixel, + const unsigned long planeSize, + const int bits, + const OFBool rgb) + { + if (this->Init(pixel)) + { + const T1 offset = OFstatic_cast(T1, DicomImageClass::maxval(bits - 1)); + // use the number of input pixels derived from the length of the 'PixelData' + // attribute), but not more than the size of the intermediate buffer + const unsigned long count = (this->InputCount < this->Count) ? this->InputCount : this->Count; + if (rgb) /* convert to RGB model */ + { + register T2 *r = this->Data[0]; + register T2 *g = this->Data[1]; + register T2 *b = this->Data[2]; + const T2 maxvalue = OFstatic_cast(T2, DicomImageClass::maxval(bits)); + DiPixelRepresentationTemplate rep; + if (bits == 8 && !rep.isSigned()) // only for unsigned 8 bit + { + Sint16 rcr_tab[256]; + Sint16 gcb_tab[256]; + Sint16 gcr_tab[256]; + Sint16 bcb_tab[256]; + const double r_const = 0.7010 * OFstatic_cast(double, maxvalue); + const double g_const = 0.5291 * OFstatic_cast(double, maxvalue); + const double b_const = 0.8859 * OFstatic_cast(double, maxvalue); + register unsigned long l; + for (l = 0; l < 256; ++l) + { + rcr_tab[l] = OFstatic_cast(Sint16, 1.4020 * OFstatic_cast(double, l) - r_const); + gcb_tab[l] = OFstatic_cast(Sint16, 0.3441 * OFstatic_cast(double, l)); + gcr_tab[l] = OFstatic_cast(Sint16, 0.7141 * OFstatic_cast(double, l) - g_const); + bcb_tab[l] = OFstatic_cast(Sint16, 1.7720 * OFstatic_cast(double, l) - b_const); + } + register Sint32 sr; + register Sint32 sg; + register Sint32 sb; + if (this->PlanarConfiguration) + { +/* + register const T1 *y = pixel; + register const T1 *cb = y + this->InputCount; + register const T1 *cr = cb + this->InputCount; + for (i = count; i != 0; --i, ++y, ++cb, ++cr) + { + sr = OFstatic_cast(Sint32, *y) + OFstatic_cast(Sint32, rcr_tab[*cr]); + sg = OFstatic_cast(Sint32, *y) - OFstatic_cast(Sint32, gcb_tab[*cb]) - OFstatic_cast(Sint32, gcr_tab[*cr]); + sb = OFstatic_cast(Sint32, *y) + OFstatic_cast(Sint32, bcb_tab[*cb]); + *(r++) = (sr < 0) ? 0 : (sr > OFstatic_cast(Sint32, maxvalue)) ? maxvalue : OFstatic_cast(T2, sr); + *(g++) = (sg < 0) ? 0 : (sg > OFstatic_cast(Sint32, maxvalue)) ? maxvalue : OFstatic_cast(T2, sg); + *(b++) = (sb < 0) ? 0 : (sb > OFstatic_cast(Sint32, maxvalue)) ? maxvalue : OFstatic_cast(T2, sb); + } +*/ + register const T1 *y = pixel; + register const T1 *cb = y + planeSize; + register const T1 *cr = cb + planeSize; + register unsigned long i = count; + while (i != 0) + { + /* convert a single frame */ + for (l = planeSize; (l != 0) && (i != 0); --l, --i, ++y, ++cb, ++cr) + { + sr = OFstatic_cast(Sint32, *y) + OFstatic_cast(Sint32, rcr_tab[OFstatic_cast(Uint32, *cr)]); + sg = OFstatic_cast(Sint32, *y) - OFstatic_cast(Sint32, gcb_tab[OFstatic_cast(Uint32, *cb)]) - OFstatic_cast(Sint32, gcr_tab[OFstatic_cast(Uint32, *cr)]); + sb = OFstatic_cast(Sint32, *y) + OFstatic_cast(Sint32, bcb_tab[OFstatic_cast(Uint32, *cb)]); + *(r++) = (sr < 0) ? 0 : (sr > OFstatic_cast(Sint32, maxvalue)) ? maxvalue : OFstatic_cast(T2, sr); + *(g++) = (sg < 0) ? 0 : (sg > OFstatic_cast(Sint32, maxvalue)) ? maxvalue : OFstatic_cast(T2, sg); + *(b++) = (sb < 0) ? 0 : (sb > OFstatic_cast(Sint32, maxvalue)) ? maxvalue : OFstatic_cast(T2, sb); + } + /* jump to next frame start (skip 2 planes) */ + y += 2 * planeSize; + cb += 2 * planeSize; + cr += 2 * planeSize; + } + } + else + { + register const T1 *p = pixel; + register T1 y; + register T1 cb; + register T1 cr; + register unsigned long i; + for (i = count; i != 0; --i) + { + y = *(p++); + cb = *(p++); + cr = *(p++); + sr = OFstatic_cast(Sint32, y) + OFstatic_cast(Sint32, rcr_tab[OFstatic_cast(Uint32, cr)]); + sg = OFstatic_cast(Sint32, y) - OFstatic_cast(Sint32, gcb_tab[OFstatic_cast(Uint32, cb)]) - OFstatic_cast(Sint32, gcr_tab[OFstatic_cast(Uint32, cr)]); + sb = OFstatic_cast(Sint32, y) + OFstatic_cast(Sint32, bcb_tab[OFstatic_cast(Uint32, cb)]); + *(r++) = (sr < 0) ? 0 : (sr > OFstatic_cast(Sint32, maxvalue)) ? maxvalue : OFstatic_cast(T2, sr); + *(g++) = (sg < 0) ? 0 : (sg > OFstatic_cast(Sint32, maxvalue)) ? maxvalue : OFstatic_cast(T2, sg); + *(b++) = (sb < 0) ? 0 : (sb > OFstatic_cast(Sint32, maxvalue)) ? maxvalue : OFstatic_cast(T2, sb); + } + } + } + else + { + if (this->PlanarConfiguration) + { +/* + register const T1 *y = pixel; + register const T1 *cb = y + this->InputCount; + register const T1 *cr = cb + this->InputCount; + for (i = count; i != 0; --i) + convertValue(*(r++), *(g++), *(b++), removeSign(*(y++), offset), removeSign(*(cb++), offset), + removeSign(*(cr++), offset), maxvalue); +*/ + register unsigned long l; + register unsigned long i = count; + register const T1 *y = pixel; + register const T1 *cb = y + planeSize; + register const T1 *cr = cb + planeSize; + while (i != 0) + { + /* convert a single frame */ + for (l = planeSize; (l != 0) && (i != 0); --l, --i) + { + convertValue(*(r++), *(g++), *(b++), removeSign(*(y++), offset), removeSign(*(cb++), offset), + removeSign(*(cr++), offset), maxvalue); + } + /* jump to next frame start (skip 2 planes) */ + y += 2 * planeSize; + cb += 2 * planeSize; + cr += 2 * planeSize; + } + } + else + { + register const T1 *p = pixel; + register T2 y; + register T2 cb; + register T2 cr; + register unsigned long i; + for (i = count; i != 0; --i) + { + y = removeSign(*(p++), offset); + cb = removeSign(*(p++), offset); + cr = removeSign(*(p++), offset); + convertValue(*(r++), *(g++), *(b++), y, cb, cr, maxvalue); + } + } + } + } else { /* retain YCbCr model */ + register const T1 *p = pixel; + if (this->PlanarConfiguration) + { +/* + register T2 *q; + // number of pixels to be skipped (only applicable if 'PixelData' contains more + // pixels than expected) + const unsigned long skip = (this->InputCount > this->Count) ? (this->InputCount - this->Count) : 0; + for (int j = 0; j < 3; ++j) + { + q = this->Data[j]; + for (i = count; i != 0; --i) + *(q++) = removeSign(*(p++), offset); + // skip to beginning of next plane + p += skip; + } +*/ + register unsigned long l; + register unsigned long i = 0; + while (i < count) + { + /* store current pixel index */ + const unsigned long iStart = i; + for (int j = 0; j < 3; ++j) + { + /* convert a single plane */ + for (l = planeSize, i = iStart; (l != 0) && (i < count); --l, ++i) + this->Data[j][i] = removeSign(*(p++), offset); + } + } + } + else + { + register int j; + register unsigned long i; + for (i = 0; i < count; ++i) /* for all pixel ... */ + for (j = 0; j < 3; ++j) + this->Data[j][i] = removeSign(*(p++), offset); /* ... copy planes */ + } + } + } + } + + /** convert a single YCbCr value to RGB + */ + inline void convertValue(T2 &red, T2 &green, T2 &blue, const T2 y, const T2 cb, const T2 cr, const T2 maxvalue) + { + double dr = OFstatic_cast(double, y) + 1.4020 * OFstatic_cast(double, cr) - 0.7010 * OFstatic_cast(double, maxvalue); + double dg = OFstatic_cast(double, y) - 0.3441 * OFstatic_cast(double, cb) - 0.7141 * OFstatic_cast(double, cr) + 0.5291 * OFstatic_cast(double, maxvalue); + double db = OFstatic_cast(double, y) + 1.7720 * OFstatic_cast(double, cb) - 0.8859 * OFstatic_cast(double, maxvalue); + red = (dr < 0.0) ? 0 : (dr > OFstatic_cast(double, maxvalue)) ? maxvalue : OFstatic_cast(T2, dr); + green = (dg < 0.0) ? 0 : (dg > OFstatic_cast(double, maxvalue)) ? maxvalue : OFstatic_cast(T2, dg); + blue = (db < 0.0) ? 0 : (db > OFstatic_cast(double, maxvalue)) ? maxvalue : OFstatic_cast(T2, db); + } +}; + + +#endif diff --git a/dcmimage/include/dcmtk/dcmimage/diyf2img.h b/dcmimage/include/dcmtk/dcmimage/diyf2img.h new file mode 100644 index 00000000..7068bbf6 --- /dev/null +++ b/dcmimage/include/dcmtk/dcmimage/diyf2img.h @@ -0,0 +1,72 @@ +/* + * + * Copyright (C) 1996-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimage + * + * Author: Joerg Riesmeier + * + * Purpose: DicomYBR422Image (Header) + * + */ + + +#ifndef DIYF2IMG_H +#define DIYF2IMG_H + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/dcmimage/dicoimg.h" + + +/*---------------------* + * class declaration * + *---------------------*/ + +/** Class for YCbCr Full 4:2:2 images + */ +class DCMTK_DCMIMAGE_EXPORT DiYBR422Image + : public DiColorImage +{ + + public: + + /** constructor + * + ** @param docu pointer to dataset (encapsulated) + * @param status current image status + */ + DiYBR422Image(const DiDocument *docu, + const EI_Status status); + + /** destructor + */ + virtual ~DiYBR422Image(); + + /** process next couple of frames + * + ** @param fcount number of frames to be processed (0 = same number as before) + * + ** @return status, true if successful, false otherwise + */ + virtual int processNextFrames(const unsigned long fcount); + + + protected: + + /** initialize internal data structures and member variables + */ + void Init(); +}; + + +#endif diff --git a/dcmimage/include/dcmtk/dcmimage/diyf2pxt.h b/dcmimage/include/dcmtk/dcmimage/diyf2pxt.h new file mode 100644 index 00000000..5e1859d0 --- /dev/null +++ b/dcmimage/include/dcmtk/dcmimage/diyf2pxt.h @@ -0,0 +1,156 @@ +/* + * + * Copyright (C) 1998-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimage + * + * Author: Joerg Riesmeier + * + * Purpose: DicomYBR422PixelTemplate (Header) + * + */ + + +#ifndef DIYF2PXT_H +#define DIYF2PXT_H + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/dcmimage/dicopxt.h" +#include "dcmtk/dcmimgle/diinpx.h" /* gcc 3.4 needs this */ + + +/*---------------------* + * class declaration * + *---------------------*/ + +/** Template class to handle YCbCr Full 4:2:2 pixel data + */ +template +class DiYBR422PixelTemplate + : public DiColorPixelTemplate +{ + + public: + + /** constructor + * + ** @param docu pointer to DICOM document + * @param pixel pointer to input pixel representation + * @param status reference to status variable + * @param bits number of bits per sample + * @param rgb flag, convert color model to RGB only if true + */ + DiYBR422PixelTemplate(const DiDocument *docu, + const DiInputPixel *pixel, + EI_Status &status, + const int bits, + const OFBool rgb) + : DiColorPixelTemplate(docu, pixel, 3, status, 2) + { + if ((pixel != NULL) && (this->Count > 0) && (status == EIS_Normal)) + { + if (this->PlanarConfiguration) + { + status = EIS_InvalidValue; + DCMIMAGE_ERROR("invalid value for 'PlanarConfiguration' (" << this->PlanarConfiguration << ")"); + } + else + convert(OFstatic_cast(const T1 *, pixel->getData()) + pixel->getPixelStart(), bits, rgb); + } + } + + /** destructor + */ + virtual ~DiYBR422PixelTemplate() + { + } + + + private: + + /** convert input pixel data to intermediate representation + * + ** @param pixel pointer to input pixel data + * @param bits number of bits per sample + * @param rgb flag, convert color model to RGB only if true + */ + void convert(const T1 *pixel, + const int bits, + const OFBool rgb) + { + if (this->Init(pixel)) + { + const T1 offset = OFstatic_cast(T1, DicomImageClass::maxval(bits - 1)); + register unsigned long i; + register const T1 *p = pixel; + register T2 *r = this->Data[0]; + register T2 *g = this->Data[1]; + register T2 *b = this->Data[2]; + register T2 y1; + register T2 y2; + register T2 cb; + register T2 cr; + // use the number of input pixels derived from the length of the 'PixelData' + // attribute), but not more than the size of the intermediate buffer + const unsigned long count = (this->InputCount < this->Count) ? this->InputCount : this->Count; + if (rgb) /* convert to RGB model */ + { + const T2 maxvalue = OFstatic_cast(T2, DicomImageClass::maxval(bits)); + for (i = count / 2; i != 0; --i) + { + y1 = removeSign(*(p++), offset); + y2 = removeSign(*(p++), offset); + cb = removeSign(*(p++), offset); + cr = removeSign(*(p++), offset); + convertValue(*(r++), *(g++), *(b++), y1, cb, cr, maxvalue); + convertValue(*(r++), *(g++), *(b++), y2, cb, cr, maxvalue); + } + } else { /* retain YCbCr model: YCbCr_422_full -> YCbCr_full */ + for (i = count / 2; i != 0; --i) + { + y1 = removeSign(*(p++), offset); + y2 = removeSign(*(p++), offset); + cb = removeSign(*(p++), offset); + cr = removeSign(*(p++), offset); + *(r++) = y1; + *(g++) = cb; + *(b++) = cr; + *(r++) = y2; + *(g++) = cb; + *(b++) = cr; + } + } + } + } + + /** convert a single YCbCr value to RGB + */ + inline void convertValue(T2 &red, + T2 &green, + T2 &blue, + const T2 y, + const T2 cb, + const T2 cr, + const T2 maxvalue) + { + double dr = OFstatic_cast(double, y) + 1.4020 * OFstatic_cast(double, cr) - 0.7010 * OFstatic_cast(double, maxvalue); + double dg = OFstatic_cast(double, y) - 0.3441 * OFstatic_cast(double, cb) - 0.7141 * OFstatic_cast(double, cr) + 0.5291 * OFstatic_cast(double, maxvalue); + double db = OFstatic_cast(double, y) + 1.7720 * OFstatic_cast(double, cb) - 0.8859 * OFstatic_cast(double, maxvalue); + red = (dr < 0.0) ? 0 : (dr > OFstatic_cast(double, maxvalue)) ? maxvalue : OFstatic_cast(T2, dr); + green = (dg < 0.0) ? 0 : (dg > OFstatic_cast(double, maxvalue)) ? maxvalue : OFstatic_cast(T2, dg); + blue = (db < 0.0) ? 0 : (db > OFstatic_cast(double, maxvalue)) ? maxvalue : OFstatic_cast(T2, db); + } +}; + + +#endif diff --git a/dcmimage/include/dcmtk/dcmimage/diyp2img.h b/dcmimage/include/dcmtk/dcmimage/diyp2img.h new file mode 100644 index 00000000..a3819739 --- /dev/null +++ b/dcmimage/include/dcmtk/dcmimage/diyp2img.h @@ -0,0 +1,72 @@ +/* + * + * Copyright (C) 1998-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimage + * + * Author: Joerg Riesmeier + * + * Purpose: DicomYBRPart422Image (Header) + * + */ + + +#ifndef DIYP2IMG_H +#define DIYP2IMG_H + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/dcmimage/dicoimg.h" + + +/*---------------------* + * class declaration * + *---------------------*/ + +/** Class for YCbCr Partial 4:2:2 images + */ +class DCMTK_DCMIMAGE_EXPORT DiYBRPart422Image + : public DiColorImage +{ + + public: + + /** constructor + * + ** @param docu pointer to dataset (encapsulated) + * @param status current image status + */ + DiYBRPart422Image(const DiDocument *docu, + const EI_Status status); + + /** destructor + */ + virtual ~DiYBRPart422Image(); + + /** process next couple of frames + * + ** @param fcount number of frames to be processed (0 = same number as before) + * + ** @return status, true if successful, false otherwise + */ + virtual int processNextFrames(const unsigned long fcount); + + + protected: + + /** initialize internal data structures and member variables + */ + void Init(); +}; + + +#endif diff --git a/dcmimage/include/dcmtk/dcmimage/diyp2pxt.h b/dcmimage/include/dcmtk/dcmimage/diyp2pxt.h new file mode 100644 index 00000000..238631f0 --- /dev/null +++ b/dcmimage/include/dcmtk/dcmimage/diyp2pxt.h @@ -0,0 +1,136 @@ +/* + * + * Copyright (C) 1998-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimage + * + * Author: Joerg Riesmeier + * + * Purpose: DicomYBRPart422PixelTemplate (Header) + * + */ + + +#ifndef DIYP2PXT_H +#define DIYP2PXT_H + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/dcmimage/dicopxt.h" +#include "dcmtk/dcmimgle/diinpx.h" /* gcc 3.4 needs this */ + + +/*---------------------* + * class declaration * + *---------------------*/ + +/** Template class to handle YCbCr Partial 4:2:2 pixel data + */ +template +class DiYBRPart422PixelTemplate + : public DiColorPixelTemplate +{ + + public: + + /** constructor + * + ** @param docu pointer to DICOM document + * @param pixel pointer to input pixel representation + * @param status reference to status variable + * @param bits number of bits per sample + */ + DiYBRPart422PixelTemplate(const DiDocument *docu, + const DiInputPixel *pixel, + EI_Status &status, + const int bits) + : DiColorPixelTemplate(docu, pixel, 3, status, 2) + { + if ((pixel != NULL) && (this->Count > 0) && (status == EIS_Normal)) + { + if (this->PlanarConfiguration) + { + status = EIS_InvalidValue; + DCMIMAGE_ERROR("invalid value for 'PlanarConfiguration' (" << this->PlanarConfiguration << ")"); + } + else + convert(OFstatic_cast(const T1 *, pixel->getData()) + pixel->getPixelStart(), bits); + } + } + + /** destructor + */ + virtual ~DiYBRPart422PixelTemplate() + { + } + + + private: + + /** convert input pixel data to intermediate representation + * + ** @param pixel pointer to input pixel data + * @param bits number of bits per sample + */ + void convert(const T1 *pixel, + const int bits) + { + if (this->Init(pixel)) + { + register T2 *r = this->Data[0]; + register T2 *g = this->Data[1]; + register T2 *b = this->Data[2]; + register unsigned long i; + const T2 maxvalue = OFstatic_cast(T2, DicomImageClass::maxval(bits)); + const T1 offset = OFstatic_cast(T1, DicomImageClass::maxval(bits - 1)); + // use the number of input pixels derived from the length of the 'PixelData' + // attribute), but not more than the size of the intermediate buffer + const unsigned long count = (this->InputCount < this->Count) ? this->InputCount : this->Count; + + register const T1 *p = pixel; + register T2 y1; + register T2 y2; + register T2 cb; + register T2 cr; + for (i = count / 2; i != 0; --i) + { + y1 = removeSign(*(p++), offset); + y2 = removeSign(*(p++), offset); + cb = removeSign(*(p++), offset); + cr = removeSign(*(p++), offset); + convertValue(*(r++), *(g++), *(b++), y1, cb, cr, maxvalue); + convertValue(*(r++), *(g++), *(b++), y2, cb, cr, maxvalue); + } + } + } + + /** convert a single YCbCr value to RGB + */ + inline void convertValue(T2 &red, + T2 &green, + T2 &blue, + const T2 y, + const T2 cb, + const T2 cr, + const T2 maxvalue) + { + double dr = 1.1631 * OFstatic_cast(double, y) + 1.5969 * OFstatic_cast(double, cr) - 0.8713 * OFstatic_cast(double, maxvalue); + double dg = 1.1631 * OFstatic_cast(double, y) - 0.3913 * OFstatic_cast(double, cb) - 0.8121 * OFstatic_cast(double, cr) + 0.5290 * OFstatic_cast(double, maxvalue); + double db = 1.1631 * OFstatic_cast(double, y) + 2.0177 * OFstatic_cast(double, cb) - 1.0820 * OFstatic_cast(double, maxvalue); + red = (dr < 0.0) ? 0 : (dr > OFstatic_cast(double, maxvalue)) ? maxvalue : OFstatic_cast(T2, dr); + green = (dg < 0.0) ? 0 : (dg > OFstatic_cast(double, maxvalue)) ? maxvalue : OFstatic_cast(T2, dg); + blue = (db < 0.0) ? 0 : (db > OFstatic_cast(double, maxvalue)) ? maxvalue : OFstatic_cast(T2, db); + } +}; + + +#endif diff --git a/dcmimage/libsrc/CMakeLists.txt b/dcmimage/libsrc/CMakeLists.txt new file mode 100644 index 00000000..f1d4a111 --- /dev/null +++ b/dcmimage/libsrc/CMakeLists.txt @@ -0,0 +1,5 @@ +# create library from source files +DCMTK_ADD_LIBRARY(dcmimage diargimg dicmyimg dicoimg dicoopx dicopx dihsvimg dilogger dipalimg dipipng dipitiff diqtctab diqtfs diqthash diqthitl diqtpbox diquant diregist dirgbimg diybrimg diyf2img diyp2img) + +DCMTK_TARGET_LINK_MODULES(dcmimage oflog dcmdata dcmimgle) +DCMTK_TARGET_LINK_LIBRARIES(dcmimage ${LIBTIFF_LIBS} ${LIBPNG_LIBS}) diff --git a/dcmimage/libsrc/Makefile.dep b/dcmimage/libsrc/Makefile.dep new file mode 100644 index 00000000..5f351e4a --- /dev/null +++ b/dcmimage/libsrc/Makefile.dep @@ -0,0 +1,1306 @@ +diargimg.o: diargimg.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../include/dcmtk/dcmimage/diargimg.h ../include/dcmtk/dcmimage/dicoimg.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diimage.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diovlay.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diobjcou.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/didefine.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diovdat.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diovpln.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diutils.h \ + ../include/dcmtk/dcmimage/dicopx.h ../include/dcmtk/dcmimage/dilogger.h \ + ../include/dcmtk/dcmimage/dicdefin.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/dipixel.h \ + ../include/dcmtk/dcmimage/diargpxt.h ../include/dcmtk/dcmimage/dicopxt.h \ + ../../ofstd/include/dcmtk/ofstd/ofbmanip.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/dipxrept.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diluptab.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/dibaslut.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diinpx.h \ + ../include/dcmtk/dcmimage/diqttype.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/didocu.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h +dicmyimg.o: dicmyimg.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../include/dcmtk/dcmimage/dicmyimg.h ../include/dcmtk/dcmimage/dicoimg.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diimage.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diovlay.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diobjcou.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/didefine.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diovdat.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diovpln.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diutils.h \ + ../include/dcmtk/dcmimage/dicopx.h ../include/dcmtk/dcmimage/dilogger.h \ + ../include/dcmtk/dcmimage/dicdefin.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/dipixel.h \ + ../include/dcmtk/dcmimage/dicmypxt.h ../include/dcmtk/dcmimage/dicopxt.h \ + ../../ofstd/include/dcmtk/ofstd/ofbmanip.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/dipxrept.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diinpx.h +dicoimg.o: dicoimg.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixel.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpobw.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../include/dcmtk/dcmimage/dicoimg.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diimage.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diovlay.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diobjcou.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/didefine.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diovdat.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diovpln.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diutils.h \ + ../include/dcmtk/dcmimage/dicopx.h ../include/dcmtk/dcmimage/dilogger.h \ + ../include/dcmtk/dcmimage/dicdefin.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/dipixel.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/dimo2img.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/dimoimg.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/dimopx.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/dimomod.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diluptab.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/dibaslut.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/dimoopx.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/didispfn.h \ + ../include/dcmtk/dcmimage/dicopxt.h \ + ../../ofstd/include/dcmtk/ofstd/ofbmanip.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/dipxrept.h \ + ../include/dcmtk/dcmimage/dicocpt.h ../include/dcmtk/dcmimage/dicosct.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/discalet.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/ditranst.h \ + ../include/dcmtk/dcmimage/dicoflt.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diflipt.h \ + ../include/dcmtk/dcmimage/dicorot.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/dirotat.h \ + ../include/dcmtk/dcmimage/dicoopxt.h ../include/dcmtk/dcmimage/dicoopx.h +dicoopx.o: dicoopx.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmimage/dicoopx.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diutils.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/didefine.h \ + ../include/dcmtk/dcmimage/dicdefin.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/dipixel.h +dicopx.o: dicopx.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../include/dcmtk/dcmimage/dicopx.h ../include/dcmtk/dcmimage/dilogger.h \ + ../include/dcmtk/dcmimage/dicdefin.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/dipixel.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diutils.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/didefine.h \ + ../include/dcmtk/dcmimage/diqttype.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/dimopx.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/dimomod.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diluptab.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/dibaslut.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diobjcou.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diinpx.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/didocu.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h +dihsvimg.o: dihsvimg.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../include/dcmtk/dcmimage/dihsvimg.h ../include/dcmtk/dcmimage/dicoimg.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diimage.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diovlay.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diobjcou.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/didefine.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diovdat.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diovpln.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diutils.h \ + ../include/dcmtk/dcmimage/dicopx.h ../include/dcmtk/dcmimage/dilogger.h \ + ../include/dcmtk/dcmimage/dicdefin.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/dipixel.h \ + ../include/dcmtk/dcmimage/dihsvpxt.h ../include/dcmtk/dcmimage/dicopxt.h \ + ../../ofstd/include/dcmtk/ofstd/ofbmanip.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/dipxrept.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diinpx.h +dilogger.o: dilogger.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmimage/dilogger.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../include/dcmtk/dcmimage/dicdefin.h +dipalimg.o: dipalimg.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/didocu.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diobjcou.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/didefine.h \ + ../include/dcmtk/dcmimage/dipalimg.h ../include/dcmtk/dcmimage/dicoimg.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diimage.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diovlay.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diovdat.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diovpln.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diutils.h \ + ../include/dcmtk/dcmimage/dicopx.h ../include/dcmtk/dcmimage/dilogger.h \ + ../include/dcmtk/dcmimage/dicdefin.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/dipixel.h \ + ../include/dcmtk/dcmimage/dipalpxt.h ../include/dcmtk/dcmimage/dicopxt.h \ + ../../ofstd/include/dcmtk/ofstd/ofbmanip.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/dipxrept.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diluptab.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/dibaslut.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diinpx.h \ + ../include/dcmtk/dcmimage/diqttype.h +dipipng.o: dipipng.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diimage.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diovlay.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diobjcou.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/didefine.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diovdat.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diovpln.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diutils.h \ + ../include/dcmtk/dcmimage/dipipng.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diplugin.h \ + ../include/dcmtk/dcmimage/dicdefin.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcuid.h +dipitiff.o: dipitiff.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diimage.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diovlay.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diobjcou.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/didefine.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diovdat.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diovpln.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diutils.h \ + ../include/dcmtk/dcmimage/dipitiff.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diplugin.h \ + ../include/dcmtk/dcmimage/dicdefin.h +diqtctab.o: diqtctab.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmimage/diqtctab.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../include/dcmtk/dcmimage/diqtpix.h ../include/dcmtk/dcmimage/diqttype.h \ + ../include/dcmtk/dcmimage/dicdefin.h \ + ../include/dcmtk/dcmimage/diqtstab.h \ + ../include/dcmtk/dcmimage/diqthash.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../include/dcmtk/dcmimage/diqthitl.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../include/dcmtk/dcmimage/diqthitm.h \ + ../include/dcmtk/dcmimage/diqtpbox.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrus.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcuid.h +diqtfs.o: diqtfs.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmimage/diqtfs.h ../include/dcmtk/dcmimage/diqtpix.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../include/dcmtk/dcmimage/diqttype.h \ + ../include/dcmtk/dcmimage/dicdefin.h \ + ../include/dcmtk/dcmimage/diqtstab.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h +diqthash.o: diqthash.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmimage/diqthash.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../include/dcmtk/dcmimage/diqtpix.h ../include/dcmtk/dcmimage/diqttype.h \ + ../include/dcmtk/dcmimage/dicdefin.h \ + ../include/dcmtk/dcmimage/diqtstab.h \ + ../include/dcmtk/dcmimage/diqthitl.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../include/dcmtk/dcmimage/diqthitm.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/dcmimage.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/dimoimg.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diimage.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diovlay.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diobjcou.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/didefine.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diovdat.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diovpln.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diutils.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/dimopx.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/dipixel.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/dimomod.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diluptab.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/dibaslut.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/dimoopx.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/didispfn.h +diqthitl.o: diqthitl.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmimage/diqthitl.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../include/dcmtk/dcmimage/diqthitm.h ../include/dcmtk/dcmimage/diqtpix.h \ + ../include/dcmtk/dcmimage/diqttype.h \ + ../include/dcmtk/dcmimage/dicdefin.h \ + ../include/dcmtk/dcmimage/diqtstab.h +diqtpbox.o: diqtpbox.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../include/dcmtk/dcmimage/diqtpbox.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../include/dcmtk/dcmimage/dicdefin.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h +diquant.o: diquant.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmimage/diquant.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../include/dcmtk/dcmimage/diqttype.h \ + ../include/dcmtk/dcmimage/dicdefin.h ../include/dcmtk/dcmimage/diqtid.h \ + ../include/dcmtk/dcmimage/diqtcmap.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/dcmimage.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/dimoimg.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diimage.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diovlay.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diobjcou.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/didefine.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diovdat.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diovpln.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diutils.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/dimopx.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/dipixel.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/dimomod.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diluptab.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/dibaslut.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/dimoopx.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/didispfn.h \ + ../include/dcmtk/dcmimage/diqtstab.h ../include/dcmtk/dcmimage/diqtpix.h \ + ../include/dcmtk/dcmimage/diqthash.h \ + ../include/dcmtk/dcmimage/diqthitl.h \ + ../include/dcmtk/dcmimage/diqthitm.h \ + ../include/dcmtk/dcmimage/diqtctab.h ../include/dcmtk/dcmimage/diqtfs.h \ + ../include/dcmtk/dcmimage/dilogger.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixel.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpobw.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcuid.h +diregist.o: diregist.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmimage/diregist.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diregbas.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diutils.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/didefine.h \ + ../include/dcmtk/dcmimage/dicdefin.h \ + ../include/dcmtk/dcmimage/dipalimg.h ../include/dcmtk/dcmimage/dicoimg.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diimage.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diovlay.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diobjcou.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diovdat.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diovpln.h \ + ../include/dcmtk/dcmimage/dicopx.h ../include/dcmtk/dcmimage/dilogger.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/dipixel.h \ + ../include/dcmtk/dcmimage/dirgbimg.h \ + ../include/dcmtk/dcmimage/dihsvimg.h \ + ../include/dcmtk/dcmimage/diargimg.h \ + ../include/dcmtk/dcmimage/dicmyimg.h \ + ../include/dcmtk/dcmimage/diybrimg.h \ + ../include/dcmtk/dcmimage/diyf2img.h \ + ../include/dcmtk/dcmimage/diyp2img.h ../include/dcmtk/dcmimage/dicomot.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/dimopxt.h \ + ../../ofstd/include/dcmtk/ofstd/ofbmanip.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/dipxrept.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/dimopx.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/dimomod.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diluptab.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/dibaslut.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/dimoopx.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/didocu.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h +dirgbimg.o: dirgbimg.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../include/dcmtk/dcmimage/dirgbimg.h ../include/dcmtk/dcmimage/dicoimg.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diimage.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diovlay.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diobjcou.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/didefine.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diovdat.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diovpln.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diutils.h \ + ../include/dcmtk/dcmimage/dicopx.h ../include/dcmtk/dcmimage/dilogger.h \ + ../include/dcmtk/dcmimage/dicdefin.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/dipixel.h \ + ../include/dcmtk/dcmimage/dirgbpxt.h ../include/dcmtk/dcmimage/dicopxt.h \ + ../../ofstd/include/dcmtk/ofstd/ofbmanip.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/dipxrept.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diinpx.h +diybrimg.o: diybrimg.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../include/dcmtk/dcmimage/diybrimg.h ../include/dcmtk/dcmimage/dicoimg.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diimage.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diovlay.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diobjcou.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/didefine.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diovdat.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diovpln.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diutils.h \ + ../include/dcmtk/dcmimage/dicopx.h ../include/dcmtk/dcmimage/dilogger.h \ + ../include/dcmtk/dcmimage/dicdefin.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/dipixel.h \ + ../include/dcmtk/dcmimage/diybrpxt.h ../include/dcmtk/dcmimage/dicopxt.h \ + ../../ofstd/include/dcmtk/ofstd/ofbmanip.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/dipxrept.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diinpx.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/didocu.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h +diyf2img.o: diyf2img.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../include/dcmtk/dcmimage/diyf2img.h ../include/dcmtk/dcmimage/dicoimg.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diimage.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diovlay.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diobjcou.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/didefine.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diovdat.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diovpln.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diutils.h \ + ../include/dcmtk/dcmimage/dicopx.h ../include/dcmtk/dcmimage/dilogger.h \ + ../include/dcmtk/dcmimage/dicdefin.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/dipixel.h \ + ../include/dcmtk/dcmimage/diyf2pxt.h ../include/dcmtk/dcmimage/dicopxt.h \ + ../../ofstd/include/dcmtk/ofstd/ofbmanip.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/dipxrept.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diinpx.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/didocu.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h +diyp2img.o: diyp2img.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../include/dcmtk/dcmimage/diyp2img.h ../include/dcmtk/dcmimage/dicoimg.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diimage.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diovlay.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diobjcou.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/didefine.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diovdat.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diovpln.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diutils.h \ + ../include/dcmtk/dcmimage/dicopx.h ../include/dcmtk/dcmimage/dilogger.h \ + ../include/dcmtk/dcmimage/dicdefin.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/dipixel.h \ + ../include/dcmtk/dcmimage/diyp2pxt.h ../include/dcmtk/dcmimage/dicopxt.h \ + ../../ofstd/include/dcmtk/ofstd/ofbmanip.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/dipxrept.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diinpx.h diff --git a/dcmimage/libsrc/Makefile.in b/dcmimage/libsrc/Makefile.in new file mode 100644 index 00000000..5c0491e9 --- /dev/null +++ b/dcmimage/libsrc/Makefile.in @@ -0,0 +1,57 @@ +# +# Makefile for dcmimage/libsrc +# + +@SET_MAKE@ + +SHELL = /bin/sh +VPATH = @srcdir@:@top_srcdir@/include:@top_srcdir@/@configdir@/include +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +configdir = @top_srcdir@/@configdir@ + +include $(configdir)/@common_makefile@ + +ofstddir = $(top_srcdir)/../ofstd +oflogdir = $(top_srcdir)/../oflog +dcmdatadir = $(top_srcdir)/../dcmdata +dcmimgledir = $(top_srcdir)/../dcmimgle + +# Special defines for the Library, define them in LOCALDEFS +# REVERSE_OVERLAY_ORIGIN_ORDER +# swap order of overlay origin coordinates +# LOCALDEFS = -DREVERSE_OVERLAY_ORIGIN_ORDER + +LOCALINCLUDES = -I$(ofstddir)/include -I$(oflogdir)/include -I$(dcmdatadir)/include -I$(dcmimgledir)/include + +objs = dicoimg.o dicopx.o dicoopx.o diregist.o dilogger.o \ + diargimg.o dicmyimg.o dihsvimg.o dipalimg.o dirgbimg.o \ + diybrimg.o diyf2img.o diyp2img.o dipitiff.o dipipng.o \ + diqtctab.o diqtfs.o diqthash.o diqthitl.o diqtpbox.o diquant.o +library = libdcmimage.$(LIBEXT) + + +all: $(library) + +install: $(library) + $(configdir)/mkinstalldirs $(DESTDIR)$(libdir) + $(INSTALL_DATA) $(library) $(DESTDIR)$(libdir)/$(library) + $(RANLIB) $(DESTDIR)$(libdir)/$(library) + + +$(library): $(objs) + $(AR) $(ARFLAGS) $@ $(objs) + $(RANLIB) $@ + + +clean: + rm -f $(objs) $(library) $(TRASH) + +distclean: + rm -f $(objs) $(library) $(DISTTRASH) + + +dependencies: + $(CXX) -MM $(defines) $(includes) $(CPPFLAGS) $(CXXFLAGS) *.cc > $(DEP) + +include $(DEP) diff --git a/dcmimage/libsrc/diargimg.cc b/dcmimage/libsrc/diargimg.cc new file mode 100644 index 00000000..34c5bd04 --- /dev/null +++ b/dcmimage/libsrc/diargimg.cc @@ -0,0 +1,152 @@ +/* + * + * Copyright (C) 1996-2010, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimage + * + * Author: Joerg Riesmeier + * + * Purpose: DiARGBImage (Source) - UNTESTED !!! + * + */ + + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/dcmdata/dctypes.h" +#include "dcmtk/dcmdata/dcdeftag.h" + +#include "dcmtk/dcmimage/diargimg.h" +#include "dcmtk/dcmimage/diargpxt.h" +#include "dcmtk/dcmimage/diqttype.h" +#include "dcmtk/dcmimage/dilogger.h" +#include "dcmtk/dcmimgle/diluptab.h" +#include "dcmtk/dcmimgle/diinpx.h" +#include "dcmtk/dcmimgle/didocu.h" + + +/*----------------* + * constructors * + *----------------*/ + +DiARGBImage::DiARGBImage(const DiDocument *docu, + const EI_Status status) + : DiColorImage(docu, status, 4), + Palette() // initializes the three color palettes to NULL +{ + if ((Document != NULL) && (InputData != NULL) && (ImageStatus == EIS_Normal)) + { + if (BitsStored <= MAX_TABLE_ENTRY_SIZE) // color depth <= 16 + { + const EL_BitsPerTableEntry descMode = (Document->getFlags() & CIF_CheckLutBitDepth) ? ELM_CheckValue : ELM_UseValue; + Palette[0] = new DiLookupTable(Document, DCM_RedPaletteColorLookupTableDescriptor, + DCM_RedPaletteColorLookupTableData, DCM_UndefinedTagKey, descMode, &ImageStatus); + Palette[1] = new DiLookupTable(Document, DCM_GreenPaletteColorLookupTableDescriptor, + DCM_GreenPaletteColorLookupTableData, DCM_UndefinedTagKey, descMode, &ImageStatus); + Palette[2] = new DiLookupTable(Document, DCM_BluePaletteColorLookupTableDescriptor, + DCM_BluePaletteColorLookupTableData, DCM_UndefinedTagKey, descMode, &ImageStatus); + if ((ImageStatus == EIS_Normal) && (Palette[0] != NULL) && (Palette[1] != NULL) && (Palette[2] != NULL)) + { + BitsPerSample = BitsStored; + for (int jj = 0; jj < 3; jj++) // determine maximum bit count + { + if (Palette[jj]->getBits() > OFstatic_cast(Uint16, BitsPerSample)) + BitsPerSample = Palette[jj]->getBits(); + } + Init(); // create intermediate representation + } + } + else // color depth > 16 + { + ImageStatus = EIS_InvalidValue; + DCMIMAGE_ERROR("invalid value for 'BitsStored' (" << BitsStored << ") " + << "... exceeds maximum palette entry size of " << MAX_TABLE_ENTRY_SIZE << " bits"); + } + } +} + + +/*--------------* + * destructor * + *--------------*/ + +DiARGBImage::~DiARGBImage() +{ + delete Palette[0]; + delete Palette[1]; + delete Palette[2]; +} + + +/*********************************************************************/ + + +void DiARGBImage::Init() +{ + /* number of pixels per plane */ + const unsigned long planeSize = OFstatic_cast(unsigned long, Columns) * OFstatic_cast(unsigned long, Rows); + switch (InputData->getRepresentation()) + { + case EPR_Uint8: + if (BitsPerSample <= 8) + InterData = new DiARGBPixelTemplate(Document, InputData, Palette, ImageStatus, + planeSize, BitsStored); + else + InterData = new DiARGBPixelTemplate(Document, InputData, Palette, ImageStatus, + planeSize, BitsStored); + break; + case EPR_Sint8: + if (BitsPerSample <= 8) + InterData = new DiARGBPixelTemplate(Document, InputData, Palette, ImageStatus, + planeSize, BitsStored); + else + InterData = new DiARGBPixelTemplate(Document, InputData, Palette, ImageStatus, + planeSize, BitsStored); + break; + case EPR_Uint16: + if (BitsPerSample <= 8) + InterData = new DiARGBPixelTemplate(Document, InputData, Palette, ImageStatus, + planeSize, BitsStored); + else + InterData = new DiARGBPixelTemplate(Document, InputData, Palette, ImageStatus, + planeSize, BitsStored); + break; + case EPR_Sint16: + if (BitsPerSample <= 8) + InterData = new DiARGBPixelTemplate(Document, InputData, Palette, ImageStatus, + planeSize, BitsStored); + else + InterData = new DiARGBPixelTemplate(Document, InputData, Palette, ImageStatus, + planeSize, BitsStored); + break; + default: + DCMIMAGE_WARN("invalid value for inter-representation"); + } + deleteInputData(); // input data is no longer needed + checkInterData(); +} + + +/*********************************************************************/ + + +int DiARGBImage::processNextFrames(const unsigned long fcount) +{ + if (DiImage::processNextFrames(fcount)) + { + delete InterData; + InterData = NULL; + Init(); + return (ImageStatus == EIS_Normal); + } + return 0; +} diff --git a/dcmimage/libsrc/dicmyimg.cc b/dcmimage/libsrc/dicmyimg.cc new file mode 100644 index 00000000..e3985fad --- /dev/null +++ b/dcmimage/libsrc/dicmyimg.cc @@ -0,0 +1,103 @@ +/* + * + * Copyright (C) 1996-2010, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimage + * + * Author: Joerg Riesmeier + * + * Purpose: DicomCMYKImage (Source) + * + */ + + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/dcmdata/dctypes.h" + +#include "dcmtk/dcmimage/dicmyimg.h" +#include "dcmtk/dcmimage/dicmypxt.h" +#include "dcmtk/dcmimage/dilogger.h" +#include "dcmtk/dcmimgle/diinpx.h" + + +/*----------------* + * constructors * + *----------------*/ + +DiCMYKImage::DiCMYKImage(const DiDocument *docu, + const EI_Status status) + : DiColorImage(docu, status, 4) +{ + if ((Document != NULL) && (InputData != NULL) && (ImageStatus == EIS_Normal)) + { + Init(); // create intermediate representation + } +} + + +/*--------------* + * destructor * + *--------------*/ + +DiCMYKImage::~DiCMYKImage() +{ +} + + +/*********************************************************************/ + + +void DiCMYKImage::Init() +{ + /* number of pixels per plane */ + const unsigned long planeSize = OFstatic_cast(unsigned long, Columns) * OFstatic_cast(unsigned long, Rows); + switch (InputData->getRepresentation()) + { + case EPR_Uint8: + InterData = new DiCMYKPixelTemplate(Document, InputData, ImageStatus, planeSize, BitsPerSample); + break; + case EPR_Sint8: + InterData = new DiCMYKPixelTemplate(Document, InputData, ImageStatus, planeSize, BitsPerSample); + break; + case EPR_Uint16: + InterData = new DiCMYKPixelTemplate(Document, InputData, ImageStatus, planeSize, BitsPerSample); + break; + case EPR_Sint16: + InterData = new DiCMYKPixelTemplate(Document, InputData, ImageStatus, planeSize, BitsPerSample); + break; + case EPR_Uint32: + InterData = new DiCMYKPixelTemplate(Document, InputData, ImageStatus, planeSize, BitsPerSample); + break; + case EPR_Sint32: + InterData = new DiCMYKPixelTemplate(Document, InputData, ImageStatus, planeSize, BitsPerSample); + break; + } + deleteInputData(); + checkInterData(); +} + + +/*********************************************************************/ + + +int DiCMYKImage::processNextFrames(const unsigned long fcount) +{ + if (DiImage::processNextFrames(fcount)) + { + delete InterData; + InterData = NULL; + Init(); + return (ImageStatus == EIS_Normal); + } + return 0; +} diff --git a/dcmimage/libsrc/dicoimg.cc b/dcmimage/libsrc/dicoimg.cc new file mode 100644 index 00000000..661fd64a --- /dev/null +++ b/dcmimage/libsrc/dicoimg.cc @@ -0,0 +1,699 @@ +/* + * + * Copyright (C) 1996-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimage + * + * Author: Joerg Riesmeier + * + * Purpose: DicomColorImage (Source) + * + */ + + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/dcmdata/dctypes.h" +#include "dcmtk/dcmdata/dcdeftag.h" +#include "dcmtk/dcmdata/dcpixel.h" + +#include "dcmtk/dcmimage/dicoimg.h" +#include "dcmtk/dcmimgle/dimo2img.h" +#include "dcmtk/dcmimage/dicopxt.h" +#include "dcmtk/dcmimage/dicocpt.h" +#include "dcmtk/dcmimage/dicosct.h" +#include "dcmtk/dcmimage/dicoflt.h" +#include "dcmtk/dcmimage/dicorot.h" +#include "dcmtk/dcmimage/dicoopxt.h" +#include "dcmtk/dcmimage/dilogger.h" +#include "dcmtk/dcmimgle/diutils.h" + + +/*----------------* + * constructors * + *----------------*/ + +DiColorImage::DiColorImage(const DiDocument *docu, + const EI_Status status, + const int spp, + const OFBool rgb) + : DiImage(docu, status, spp), + RGBColorModel(rgb), + InterData(NULL), + OutputData(NULL) +{ + detachPixelData(); +} + + +DiColorImage::DiColorImage(const DiColorImage *image, + const unsigned long fstart, + const unsigned long fcount) + : DiImage(image, fstart, fcount), + RGBColorModel(image->RGBColorModel), + InterData(NULL), + OutputData(NULL) +{ + if (image->InterData != NULL) + { + const unsigned long fsize = OFstatic_cast(unsigned long, Columns) * OFstatic_cast(unsigned long, Rows); + switch (image->InterData->getRepresentation()) + { + case EPR_Uint8: + InterData = new DiColorCopyTemplate(image->InterData, fstart, fcount, fsize); + break; + case EPR_Sint8: + InterData = new DiColorCopyTemplate(image->InterData, fstart, fcount, fsize); + break; + case EPR_Uint16: + InterData = new DiColorCopyTemplate(image->InterData, fstart, fcount, fsize); + break; + case EPR_Sint16: + InterData = new DiColorCopyTemplate(image->InterData, fstart, fcount, fsize); + break; + case EPR_Uint32: + InterData = new DiColorCopyTemplate(image->InterData, fstart, fcount, fsize); + break; + case EPR_Sint32: + InterData = new DiColorCopyTemplate(image->InterData, fstart, fcount, fsize); + break; + } + checkInterData(0); + } +} + + +DiColorImage::DiColorImage(const DiColorImage *image, + const signed long left_pos, + const signed long top_pos, + const Uint16 src_cols, + const Uint16 src_rows, + const Uint16 dest_cols, + const Uint16 dest_rows, + const int interpolate, + const int aspect) + : DiImage(image, dest_cols, dest_rows, aspect), + RGBColorModel(image->RGBColorModel), + InterData(NULL), + OutputData(NULL) +{ + if (image->InterData != NULL) + { + switch (image->InterData->getRepresentation()) + { + case EPR_Uint8: + InterData = new DiColorScaleTemplate(image->InterData, image->Columns, image->Rows, left_pos, top_pos, + src_cols, src_rows, dest_cols, dest_rows, NumberOfFrames, image->BitsPerSample, interpolate); + break; + case EPR_Uint16: + InterData = new DiColorScaleTemplate(image->InterData, image->Columns, image->Rows, left_pos, top_pos, + src_cols, src_rows, dest_cols, dest_rows, NumberOfFrames, image->BitsPerSample, interpolate); + break; + case EPR_Uint32: + InterData = new DiColorScaleTemplate(image->InterData, image->Columns, image->Rows, left_pos, top_pos, + src_cols, src_rows, dest_cols, dest_rows, NumberOfFrames, image->BitsPerSample, interpolate); + break; + default: + DCMIMAGE_WARN("invalid value for inter-representation"); + } + checkInterData(0); + } +} + + +DiColorImage::DiColorImage(const DiColorImage *image, + const int horz, + const int vert) + : DiImage(image), + RGBColorModel(image->RGBColorModel), + InterData(NULL), + OutputData(NULL) +{ + if (image->InterData != NULL) + { + switch (image->InterData->getRepresentation()) + { + case EPR_Uint8: + InterData = new DiColorFlipTemplate(image->InterData, Columns, Rows, NumberOfFrames, horz, vert); + break; + case EPR_Uint16: + InterData = new DiColorFlipTemplate(image->InterData, Columns, Rows, NumberOfFrames, horz, vert); + break; + case EPR_Uint32: + InterData = new DiColorFlipTemplate(image->InterData, Columns, Rows, NumberOfFrames, horz, vert); + break; + default: + DCMIMAGE_WARN("invalid value for inter-representation"); + } + checkInterData(0); + } +} + + +DiColorImage::DiColorImage(const DiColorImage *image, + const int degree) + : DiImage(image, degree), + RGBColorModel(image->RGBColorModel), + InterData(NULL), + OutputData(NULL) +{ + if (image->InterData != NULL) + { + switch (image->InterData->getRepresentation()) + { + case EPR_Uint8: + InterData = new DiColorRotateTemplate(image->InterData, image->Columns, image->Rows, Columns, Rows, + NumberOfFrames, degree); + break; + case EPR_Uint16: + InterData = new DiColorRotateTemplate(image->InterData, image->Columns, image->Rows, Columns, Rows, + NumberOfFrames, degree); + break; + case EPR_Uint32: + InterData = new DiColorRotateTemplate(image->InterData, image->Columns, image->Rows, Columns, Rows, + NumberOfFrames, degree); + break; + default: + DCMIMAGE_WARN("invalid value for inter-representation"); + } + checkInterData(0); + } +} + + +/*--------------* + * destructor * + *--------------*/ + +DiColorImage::~DiColorImage() +{ + delete InterData; + delete OutputData; +} + + +/*********************************************************************/ + + +int DiColorImage::checkInterData(const int mode) +{ + if (InterData == NULL) + { + if (ImageStatus == EIS_Normal) + { + ImageStatus = EIS_MemoryFailure; + DCMIMAGE_ERROR("can't allocate memory for inter-representation"); + } else + ImageStatus = EIS_InvalidImage; + } + else if (InterData->getData() == NULL) + ImageStatus = EIS_InvalidImage; + else if (mode && (ImageStatus == EIS_Normal) && isOriginal /* do not check derived images */) + { + const unsigned long count = OFstatic_cast(unsigned long, Columns) * OFstatic_cast(unsigned long, Rows) * NumberOfFrames; + if ((InterData->getInputCount() != count) && ((InterData->getInputCount() >> 1) != ((count + 1) >> 1))) + { + DCMIMAGE_WARN("computed (" << count << ") and stored (" << InterData->getInputCount() + << ") " << "pixel count differ"); + } + } + return (ImageStatus == EIS_Normal); +} + + +void DiColorImage::deleteOutputData() +{ + delete OutputData; + OutputData = NULL; +} + + +unsigned long DiColorImage::getOutputDataSize(const int bits) const +{ + unsigned long result = 0; + if ((ImageStatus == EIS_Normal) && (bits > 0) && (bits <= MAX_BITS)) + { + int bytesPerPixel = 1; + if (bits > 16) + bytesPerPixel = 4; + else if (bits > 8) + bytesPerPixel = 2; + /* compute number of bytes required to store a rendered frame */ + result = OFstatic_cast(unsigned long, Columns) * OFstatic_cast(unsigned long, Rows) * 3 /*samples*/ * bytesPerPixel; + } + return result; +} + + +const void *DiColorImage::getOutputData(const unsigned long frame, + const int bits, + const int planar) +{ + return getData(NULL, 0, frame, bits, planar); +} + + +int DiColorImage::getOutputData(void *buffer, + const unsigned long size, + const unsigned long frame, + const int bits, + const int planar) +{ + return (getData(buffer, size, frame, bits, planar) != NULL); +} + + +const void *DiColorImage::getData(void *buffer, + const unsigned long size, + const unsigned long frame, + const int bits, + const int planar) +{ + if ((InterData != NULL) && (ImageStatus == EIS_Normal) && (frame < NumberOfFrames) && (bits > 0) && (bits <= MAX_BITS)) + { + if ((buffer == NULL) || (size >= getOutputDataSize(bits))) + { + deleteOutputData(); // delete old image data + const unsigned long count = OFstatic_cast(unsigned long, Columns) * OFstatic_cast(unsigned long, Rows); + const int inverse = (Polarity == EPP_Reverse); + switch (InterData->getRepresentation()) + { + case EPR_Uint8: + if (bits <= 8) + OutputData = new DiColorOutputPixelTemplate(buffer, InterData, count, frame, + getBits(), bits, planar, inverse); + else if (bits <= 16) + OutputData = new DiColorOutputPixelTemplate(buffer, InterData, count, frame, + getBits(), bits, planar, inverse); + else + OutputData = new DiColorOutputPixelTemplate(buffer, InterData, count, frame, + getBits(), bits, planar, inverse); + break; + case EPR_Uint16: + if (bits <= 8) + OutputData = new DiColorOutputPixelTemplate(buffer, InterData, count, frame, + getBits(), bits, planar, inverse); + else if (bits <= 16) + OutputData = new DiColorOutputPixelTemplate(buffer, InterData, count, frame, + getBits(), bits, planar, inverse); + else + OutputData = new DiColorOutputPixelTemplate(buffer, InterData, count, frame, + getBits(), bits, planar, inverse); + break; + case EPR_Uint32: + if (bits <= 8) + OutputData = new DiColorOutputPixelTemplate(buffer, InterData, count, frame, + getBits(), bits, planar, inverse); + else if (bits <= 16) + OutputData = new DiColorOutputPixelTemplate(buffer, InterData, count, frame, + getBits(), bits, planar, inverse); + else + OutputData = new DiColorOutputPixelTemplate(buffer, InterData, count, frame, + getBits(), bits, planar, inverse); + break; + default: + DCMIMAGE_WARN("invalid value for inter-representation"); + } + if (OutputData == NULL) + { + ImageStatus = EIS_MemoryFailure; + DCMIMAGE_ERROR("can't allocate memory for inter-representation"); + } + else + return OutputData->getData(); + } else { + DCMIMAGE_ERROR("given output buffer is too small (only " << size << " bytes)"); + } + } + return NULL; +} + + +const void *DiColorImage::getOutputPlane(const int plane) const +{ + if (OutputData != NULL) + return OutputData->getPlane(plane); + return NULL; +} + + +DiImage *DiColorImage::createImage(const unsigned long fstart, + const unsigned long fcount) const +{ + DiImage *image = new DiColorImage(this, fstart, fcount); + return image; +} + + +DiImage *DiColorImage::createScale(const signed long left_pos, + const signed long top_pos, + const unsigned long src_cols, + const unsigned long src_rows, + const unsigned long dest_cols, + const unsigned long dest_rows, + const int interpolate, + const int aspect, + const Uint16 /*pvalue*/) const +{ + DiImage *image = new DiColorImage(this, left_pos, top_pos, OFstatic_cast(Uint16, src_cols), OFstatic_cast(Uint16, src_rows), + OFstatic_cast(Uint16, dest_cols), OFstatic_cast(Uint16, dest_rows), interpolate, aspect); + return image; +} + + +int DiColorImage::flip(const int horz, + const int vert) +{ + switch (InterData->getRepresentation()) + { + case EPR_Uint8: + { + DiFlipTemplate dummy(InterData, Columns, Rows, NumberOfFrames, horz, vert); + } + break; + case EPR_Uint16: + { + DiFlipTemplate dummy(InterData, Columns, Rows, NumberOfFrames, horz, vert); + } + break; + case EPR_Uint32: + { + DiFlipTemplate dummy(InterData, Columns, Rows, NumberOfFrames, horz, vert); + } + break; + default: + DCMIMAGE_WARN("invalid value for inter-representation"); + } + return 1; +} + + +DiImage *DiColorImage::createFlip(const int horz, + const int vert) const +{ + DiImage *image = new DiColorImage(this, horz, vert); + return image; +} + + +int DiColorImage::rotate(const int degree) +{ + const Uint16 old_cols = Columns; // save old values + const Uint16 old_rows = Rows; + DiImage::rotate(degree); // swap width and height if necessary + if ((Columns > 1) && (Rows > 1)) + { + switch (InterData->getRepresentation()) + { + case EPR_Uint8: + { + DiRotateTemplate dummy(InterData, old_cols, old_rows, Columns, Rows, + NumberOfFrames, degree); + } + break; + case EPR_Uint16: + { + DiRotateTemplate dummy(InterData, old_cols, old_rows, Columns, Rows, + NumberOfFrames, degree); + } + break; + case EPR_Uint32: + { + DiRotateTemplate dummy(InterData, old_cols, old_rows, Columns, Rows, + NumberOfFrames, degree); + } + break; + default: + DCMIMAGE_WARN("invalid value for inter-representation"); + } + } + return 1; +} + + +DiImage *DiColorImage::createRotate(const int degree) const +{ + DiImage *image = new DiColorImage(this, degree); + return image; +} + + +DiImage *DiColorImage::createMono(const double red, + const double green, + const double blue) const +{ + DiImage *image = NULL; + if (RGBColorModel) + image = new DiMono2Image(this, red, green, blue); + return image; +} + + +unsigned long DiColorImage::createDIB(void *&data, + const unsigned long size, + const unsigned long frame, + const int bits, + const int upsideDown, + const int padding) +{ + if (RGBColorModel && (InterData != NULL)) + { + if (size == 0) + data = NULL; + if ((bits == 24) || (bits == 32)) + return InterData->createDIB(data, size, Columns, Rows, frame, getBits() /*fromBits*/, 8 /*toBits*/, bits /*mode*/, upsideDown, padding); + } + return 0; +} + + +unsigned long DiColorImage::createAWTBitmap(void *&data, + const unsigned long frame, + const int bits) +{ + if (RGBColorModel && (InterData != NULL) && (bits == 32)) + return InterData->createAWTBitmap(data, Columns, Rows, frame, getBits() /*fromBits*/, 8 /*toBits*/); + return 0; +} + + +void DiColorImage::updateImagePixelModuleAttributes(DcmItem &dataset) +{ + DiImage::updateImagePixelModuleAttributes(dataset); + /* remove color palette LUTs (if any) */ + delete dataset.remove(DCM_PaletteColorLookupTableUID); + delete dataset.remove(DCM_RedPaletteColorLookupTableDescriptor); + delete dataset.remove(DCM_GreenPaletteColorLookupTableDescriptor); + delete dataset.remove(DCM_BluePaletteColorLookupTableDescriptor); + delete dataset.remove(DCM_RedPaletteColorLookupTableData); + delete dataset.remove(DCM_GreenPaletteColorLookupTableData); + delete dataset.remove(DCM_BluePaletteColorLookupTableData); + delete dataset.remove(DCM_SegmentedRedPaletteColorLookupTableData); + delete dataset.remove(DCM_SegmentedGreenPaletteColorLookupTableData); + delete dataset.remove(DCM_SegmentedBluePaletteColorLookupTableData); +} + + +// --- write current image to DICOM dataset + +int DiColorImage::writeImageToDataset(DcmItem &dataset, + const int /*mode*/, + const int planar) +{ + int result = 0; + if ((InterData != NULL) && (InterData->getCount() > 0) && (BitsPerSample > 0)) + { + /* create new pixel data element */ + DcmPixelData *pixel = new DcmPixelData(DCM_PixelData); + if (pixel != NULL) + { + OFBool ok = OFFalse; + /* number of samples */ + const unsigned long count = InterData->getCount() * 3 /*planes*/; + /* number of pixels per frame */ + const unsigned long fcount = OFstatic_cast(unsigned long, Columns) * OFstatic_cast(unsigned long, Rows); + /* determine planar configuration */ + const int planarConfig = (planar == 2) ? InterData->getPlanarConfiguration() : ((planar == 0) ? 0 : 1); + switch (InterData->getRepresentation()) + { + case EPR_Uint8: + case EPR_Sint8: + { + /* write 8 bit pixel data (OB) */ + Uint8 *data = NULL; + if (pixel->createUint8Array(count, data).good() && + InterData->getPixelData(OFstatic_cast(void *, data), OFstatic_cast(size_t, count), fcount, NumberOfFrames, planarConfig)) + { + ok = OFTrue; + } + break; + } + case EPR_Uint16: + case EPR_Sint16: + { + /* write 16 bit pixel data (OW) */ + Uint16 *data = NULL; + if (pixel->createUint16Array(count, data).good() && + InterData->getPixelData(OFstatic_cast(void *, data), OFstatic_cast(size_t, count), fcount, NumberOfFrames, planarConfig)) + { + ok = OFTrue; + } + break; + } + case EPR_Uint32: + case EPR_Sint32: + { + /* write 32 bit pixel data (OW) */ + Uint16 *data = NULL; + if (pixel->createUint16Array(count * 2 /*double-words*/, data).good() && + InterData->getPixelData(OFstatic_cast(void *, data), OFstatic_cast(size_t, count), fcount, NumberOfFrames, planarConfig)) + { + ok = OFTrue; + } + break; + } + } + /* check whether pixel data has been written and insert element into the dataset */ + if (ok && dataset.insert(pixel, OFTrue /*replaceOld*/).good()) + { + char numBuf[20]; + /* set color model */ + if (getInternalColorModel() == EPI_YBR_Full) + dataset.putAndInsertString(DCM_PhotometricInterpretation, "YBR_FULL"); + else + dataset.putAndInsertString(DCM_PhotometricInterpretation, "RGB"); + /* set image resolution */ + dataset.putAndInsertUint16(DCM_Columns, Columns); + dataset.putAndInsertUint16(DCM_Rows, Rows); +#if SIZEOF_LONG == 8 + sprintf(numBuf, "%d", NumberOfFrames); +#else + sprintf(numBuf, "%ld", NumberOfFrames); +#endif + dataset.putAndInsertString(DCM_NumberOfFrames, numBuf); + dataset.putAndInsertUint16(DCM_SamplesPerPixel, 3); + dataset.putAndInsertUint16(DCM_PlanarConfiguration, planarConfig); + /* set pixel encoding and data */ + switch (InterData->getRepresentation()) + { + case EPR_Uint8: + dataset.putAndInsertUint16(DCM_BitsAllocated, 8); + dataset.putAndInsertUint16(DCM_PixelRepresentation, 0); + break; + case EPR_Sint8: + dataset.putAndInsertUint16(DCM_BitsAllocated, 8); + dataset.putAndInsertUint16(DCM_PixelRepresentation, 1); + break; + case EPR_Uint16: + dataset.putAndInsertUint16(DCM_BitsAllocated, 16); + dataset.putAndInsertUint16(DCM_PixelRepresentation, 0); + break; + case EPR_Sint16: + dataset.putAndInsertUint16(DCM_BitsAllocated, 16); + dataset.putAndInsertUint16(DCM_PixelRepresentation, 1); + break; + case EPR_Uint32: + dataset.putAndInsertUint16(DCM_BitsAllocated, 32); + dataset.putAndInsertUint16(DCM_PixelRepresentation, 0); + break; + case EPR_Sint32: + dataset.putAndInsertUint16(DCM_BitsAllocated, 32); + dataset.putAndInsertUint16(DCM_PixelRepresentation, 1); + break; + } + dataset.putAndInsertUint16(DCM_BitsStored, BitsPerSample); + dataset.putAndInsertUint16(DCM_HighBit, BitsPerSample - 1); + /* update other DICOM attributes */ + updateImagePixelModuleAttributes(dataset); + result = 1; + } else { + /* pixel data element has not been inserted, thus delete it */ + delete pixel; + } + } + } + return result; +} + + +int DiColorImage::writePPM(STD_NAMESPACE ostream& stream, + const unsigned long frame, + const int bits) +{ + if (RGBColorModel) + { + getOutputData(frame, bits); + if (OutputData != NULL) + { + stream << "P3" << OFendl; + stream << Columns << " " << Rows << OFendl; + stream << DicomImageClass::maxval(bits) << OFendl; + int ok = OutputData->writePPM(stream); + deleteOutputData(); + return ok; + } + } + return 0; +} + + +int DiColorImage::writePPM(FILE *stream, + const unsigned long frame, + const int bits) +{ + if (RGBColorModel) + { + if (stream != NULL) + { + getOutputData(frame, bits); + if (OutputData != NULL) + { + fprintf(stream, "P3\n%u %u\n%lu\n", Columns, Rows, DicomImageClass::maxval(bits)); + int ok = OutputData->writePPM(stream); + deleteOutputData(); + return ok; + } + } + } + return 0; +} + + +int DiColorImage::writeRawPPM(FILE *stream, + const unsigned long frame, + const int bits) +{ + if (RGBColorModel) + { + if ((stream != NULL) && (bits <= MAX_RAWPPM_BITS)) + { + getOutputData(frame, bits); + if ((OutputData != NULL) && (OutputData->getData() != NULL)) + { + fprintf(stream, "P6\n%u %u\n%lu\n", Columns, Rows, DicomImageClass::maxval(bits)); + fwrite(OutputData->getData(), OFstatic_cast(size_t, OutputData->getCount()), OutputData->getItemSize(), stream); + return 1; + } + } + } + return 0; +} + + +int DiColorImage::writeBMP(FILE *stream, + const unsigned long frame, + const int bits) +{ + if (RGBColorModel && ((bits == 0) || (bits == 24) || (bits == 32))) + return DiImage::writeBMP(stream, frame, (bits == 0) ? 24 : bits); + return 0; +} diff --git a/dcmimage/libsrc/dicoopx.cc b/dcmimage/libsrc/dicoopx.cc new file mode 100644 index 00000000..451c6f87 --- /dev/null +++ b/dcmimage/libsrc/dicoopx.cc @@ -0,0 +1,55 @@ +/* + * + * Copyright (C) 1996-2010, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimgle + * + * Author: Joerg Riesmeier + * + * Purpose: DicomColorOutputPixel (Source) + * + */ + + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/dcmimage/dicoopx.h" +#include "dcmtk/dcmimgle/dipixel.h" + + +/*----------------* + * constructors * + *----------------*/ + +DiColorOutputPixel::DiColorOutputPixel(const DiPixel *pixel, + const unsigned long size, + const unsigned long frame) + : Count(0), + FrameSize(size) +{ + if (pixel != NULL) + { + if (pixel->getCount() > frame * size) + Count = pixel->getCount() - frame * size; // number of pixels remaining for this 'frame' + } + if (Count > FrameSize) + Count = FrameSize; // cut off at frame 'size' +} + + +/*--------------* + * destructor * + *--------------*/ + +DiColorOutputPixel::~DiColorOutputPixel() +{ +} diff --git a/dcmimage/libsrc/dicopx.cc b/dcmimage/libsrc/dicopx.cc new file mode 100644 index 00000000..e1c279dc --- /dev/null +++ b/dcmimage/libsrc/dicopx.cc @@ -0,0 +1,106 @@ +/* + * + * Copyright (C) 1996-2010, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimage + * + * Author: Joerg Riesmeier + * + * Purpose: DicomColorPixel (Source) + * + */ + + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmdata/dctypes.h" +#include "dcmtk/dcmdata/dcdeftag.h" + +#include "dcmtk/dcmimage/dicopx.h" +#include "dcmtk/dcmimage/diqttype.h" +#include "dcmtk/dcmimgle/dimopx.h" +#include "dcmtk/dcmimgle/diinpx.h" +#include "dcmtk/dcmimgle/didocu.h" + + +/*----------------* + * constructors * + *----------------*/ + +DiColorPixel::DiColorPixel(const DiDocument *docu, + const DiInputPixel *pixel, + const Uint16 samples, + EI_Status &status, + const Uint16 sample_rate) + : DiPixel(0), + PlanarConfiguration(0) +{ + if (docu != NULL) + { + Uint16 us = 0; + if (docu->getValue(DCM_SamplesPerPixel, us)) + { + if (us != samples) + { + DCMIMAGE_WARN("invalid value for 'SamplesPerPixel' (" << us + << ") ... assuming " << samples); + } + if (docu->getValue(DCM_PlanarConfiguration, us)) + { + /* only use Planar Configuration attribute if there are multiple planes */ + if (samples > 1) + { + PlanarConfiguration = (us == 1); + if ((us != 0) && (us != 1)) + { + DCMIMAGE_WARN("invalid value for 'PlanarConfiguration' (" << us + << ") ... assuming 'color-by-pixel' (0)"); + } + } else { + DCMIMAGE_WARN("unexpected attribute 'PlanarConfiguration' (" << us + << ") ... ignoring"); + } + } + else if (samples > 1) + { + status = EIS_MissingAttribute; + DCMIMAGE_ERROR("mandatory attribute 'PlanarConfiguration' is missing"); + return; + } + if (pixel != NULL) + { + // number of pixels (per plane) computed from the length of the PixelData attribute + InputCount = pixel->getPixelCount() / ((sample_rate == 0) ? samples : sample_rate); + // number of pixels allocated for the intermediate buffer + Count = pixel->getComputedCount() / ((sample_rate == 0) ? samples : sample_rate); + } + } else { + status = EIS_MissingAttribute; + DCMIMAGE_ERROR("mandatory attribute 'SamplesPerPixel' is missing"); + } + } +} + +DiColorPixel::DiColorPixel(const DiColorPixel *pixel, + const unsigned long count) + : DiPixel(count, pixel->InputCount), + PlanarConfiguration(pixel->PlanarConfiguration) +{ +} + + +/*--------------* + * destructor * + *--------------*/ + +DiColorPixel::~DiColorPixel() +{ +} diff --git a/dcmimage/libsrc/dihsvimg.cc b/dcmimage/libsrc/dihsvimg.cc new file mode 100644 index 00000000..49e4c1ae --- /dev/null +++ b/dcmimage/libsrc/dihsvimg.cc @@ -0,0 +1,103 @@ +/* + * + * Copyright (C) 1996-2010, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimage + * + * Author: Joerg Riesmeier + * + * Purpose: DicomHSVImage (Source) + * + */ + + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/dcmdata/dctypes.h" + +#include "dcmtk/dcmimage/dihsvimg.h" +#include "dcmtk/dcmimage/dihsvpxt.h" +#include "dcmtk/dcmimage/dilogger.h" +#include "dcmtk/dcmimgle/diinpx.h" + + +/*----------------* + * constructors * + *----------------*/ + +DiHSVImage::DiHSVImage(const DiDocument *docu, + const EI_Status status) + : DiColorImage(docu, status, 3) +{ + if ((Document != NULL) && (InputData != NULL) && (ImageStatus == EIS_Normal)) + { + Init(); // create intermediate representation + } +} + + +/*--------------* + * destructor * + *--------------*/ + +DiHSVImage::~DiHSVImage() +{ +} + + +/*********************************************************************/ + + +void DiHSVImage::Init() +{ + /* number of pixels per plane */ + const unsigned long planeSize = OFstatic_cast(unsigned long, Columns) * OFstatic_cast(unsigned long, Rows); + switch (InputData->getRepresentation()) + { + case EPR_Uint8: + InterData = new DiHSVPixelTemplate(Document, InputData, ImageStatus, planeSize, BitsPerSample); + break; + case EPR_Sint8: + InterData = new DiHSVPixelTemplate(Document, InputData, ImageStatus, planeSize, BitsPerSample); + break; + case EPR_Uint16: + InterData = new DiHSVPixelTemplate(Document, InputData, ImageStatus, planeSize, BitsPerSample); + break; + case EPR_Sint16: + InterData = new DiHSVPixelTemplate(Document, InputData, ImageStatus, planeSize, BitsPerSample); + break; + case EPR_Uint32: + InterData = new DiHSVPixelTemplate(Document, InputData, ImageStatus, planeSize, BitsPerSample); + break; + case EPR_Sint32: + InterData = new DiHSVPixelTemplate(Document, InputData, ImageStatus, planeSize, BitsPerSample); + break; + } + deleteInputData(); + checkInterData(); +} + + +/*********************************************************************/ + + +int DiHSVImage::processNextFrames(const unsigned long fcount) +{ + if (DiImage::processNextFrames(fcount)) + { + delete InterData; + InterData = NULL; + Init(); + return (ImageStatus == EIS_Normal); + } + return 0; +} diff --git a/dcmimage/libsrc/dilogger.cc b/dcmimage/libsrc/dilogger.cc new file mode 100644 index 00000000..e497115b --- /dev/null +++ b/dcmimage/libsrc/dilogger.cc @@ -0,0 +1,32 @@ +/* + * + * Copyright (C) 2009-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimage + * + * Author: Joerg Riesmeier + * + * Purpose: Logger (Source) + * + */ + + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/dcmimage/dilogger.h" + + +/*--------------------* + * global variables * + *--------------------*/ + +OFLogger DCM_dcmimageLogger = OFLog::getLogger("dcmtk.dcmimage"); diff --git a/dcmimage/libsrc/dipalimg.cc b/dcmimage/libsrc/dipalimg.cc new file mode 100644 index 00000000..ab0a34e6 --- /dev/null +++ b/dcmimage/libsrc/dipalimg.cc @@ -0,0 +1,169 @@ +/* + * + * Copyright (C) 1996-2010, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimage + * + * Author: Joerg Riesmeier + * + * Purpose: DicomPaletteImage (Source) + * + */ + + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/dcmdata/dctypes.h" +#include "dcmtk/dcmdata/dcdeftag.h" +#include "dcmtk/dcmdata/dctag.h" + +#include "dcmtk/dcmimgle/didocu.h" +#include "dcmtk/dcmimage/dipalimg.h" +#include "dcmtk/dcmimage/dipalpxt.h" +#include "dcmtk/dcmimage/diqttype.h" +#include "dcmtk/dcmimage/dilogger.h" +#include "dcmtk/dcmimgle/diluptab.h" +#include "dcmtk/dcmimgle/diinpx.h" + + +/*----------------* + * constructors * + *----------------*/ + +DiPaletteImage::DiPaletteImage(const DiDocument *docu, + const EI_Status status) + : DiColorImage(docu, status, 1), + Palette() // initializes the three color palettes to NULL +{ + if ((Document != NULL) && (InputData != NULL) && (ImageStatus == EIS_Normal)) + { + if (BitsStored <= MAX_TABLE_ENTRY_SIZE) + { + const EL_BitsPerTableEntry descMode = (docu->getFlags() & CIF_CheckLutBitDepth) ? ELM_CheckValue : ELM_UseValue; + /* wrong palette attribute tags used */ + if (Document->getFlags() & CIF_WrongPaletteAttributeTags) + { + Palette[0] = new DiLookupTable(Document, DCM_RETIRED_LargeRedPaletteColorLookupTableDescriptor, + DCM_RETIRED_LargeRedPaletteColorLookupTableData, DCM_UndefinedTagKey /*explanation*/, descMode, &ImageStatus); + Palette[1] = new DiLookupTable(Document, DCM_RETIRED_LargeGreenPaletteColorLookupTableDescriptor, + DCM_RETIRED_LargeGreenPaletteColorLookupTableData, DCM_UndefinedTagKey /*explanation*/, descMode, &ImageStatus); + Palette[2] = new DiLookupTable(Document, DCM_RETIRED_LargeBluePaletteColorLookupTableDescriptor, + DCM_RETIRED_LargeBluePaletteColorLookupTableData, DCM_UndefinedTagKey /*explanation*/, descMode, &ImageStatus); + } else { + const Uint16 *dummy = NULL; + /* check for (non-empty) segmented palette */ + if ((Document->getValue(DCM_SegmentedRedPaletteColorLookupTableData, dummy) > 0) || + (Document->getValue(DCM_SegmentedGreenPaletteColorLookupTableData, dummy) > 0) || + (Document->getValue(DCM_SegmentedBluePaletteColorLookupTableData, dummy) > 0)) + { + DCMIMAGE_WARN("segmented palettes not yet supported ... ignoring"); + } + /* read data from non-segmented palettes (if present) */ + Palette[0] = new DiLookupTable(Document, DCM_RedPaletteColorLookupTableDescriptor, + DCM_RedPaletteColorLookupTableData, DCM_UndefinedTagKey /*explanation*/, descMode, &ImageStatus); + Palette[1] = new DiLookupTable(Document, DCM_GreenPaletteColorLookupTableDescriptor, + DCM_GreenPaletteColorLookupTableData, DCM_UndefinedTagKey /*explanation*/, descMode, &ImageStatus); + Palette[2] = new DiLookupTable(Document, DCM_BluePaletteColorLookupTableDescriptor, + DCM_BluePaletteColorLookupTableData, DCM_UndefinedTagKey /*explanation*/, descMode, &ImageStatus); + } + if ((ImageStatus == EIS_Normal) && (Palette[0] != NULL) && (Palette[1] != NULL) && (Palette[2] != NULL)) + { + BitsPerSample = 0; + /* determine the maximum value for bits stored of the three lookup tables */ + for (int jj = 0; jj < 3; jj++) + { + if (Palette[jj]->getBits() > OFstatic_cast(Uint16, BitsPerSample)) + BitsPerSample = Palette[jj]->getBits(); + } + if ((BitsPerSample < 1) || (BitsPerSample > MAX_TABLE_ENTRY_SIZE)) + { + DCMIMAGE_WARN("invalid value for 'BitsPerSample' (" << BitsPerSample + << ") computed from color palettes"); + } + Init(); // create intermediate representation + } + } + else + { + ImageStatus = EIS_InvalidValue; + DCMIMAGE_ERROR("invalid value for 'BitsStored' (" << BitsStored << ") " + << "... exceeds maximum palette entry size of " << MAX_TABLE_ENTRY_SIZE << " bits"); + } + } +} + + +/*--------------* + * destructor * + *--------------*/ + +DiPaletteImage::~DiPaletteImage() +{ + delete Palette[0]; + delete Palette[1]; + delete Palette[2]; +} + + +/*********************************************************************/ + + +void DiPaletteImage::Init() +{ + switch (InputData->getRepresentation()) + { + case EPR_Uint8: + if (BitsPerSample <= 8) + InterData = new DiPalettePixelTemplate(Document, InputData, Palette, ImageStatus); + else + InterData = new DiPalettePixelTemplate(Document, InputData, Palette, ImageStatus); + break; + case EPR_Sint8: + if (BitsPerSample <= 8) + InterData = new DiPalettePixelTemplate(Document, InputData, Palette, ImageStatus); + else + InterData = new DiPalettePixelTemplate(Document, InputData, Palette, ImageStatus); + break; + case EPR_Uint16: + if (BitsPerSample <= 8) + InterData = new DiPalettePixelTemplate(Document, InputData, Palette, ImageStatus); + else + InterData = new DiPalettePixelTemplate(Document, InputData, Palette, ImageStatus); + break; + case EPR_Sint16: + if (BitsPerSample <= 8) + InterData = new DiPalettePixelTemplate(Document, InputData, Palette, ImageStatus); + else + InterData = new DiPalettePixelTemplate(Document, InputData, Palette, ImageStatus); + break; + default: + DCMIMAGE_WARN("invalid value for inter-representation"); + } + deleteInputData(); + checkInterData(); +} + + +/*********************************************************************/ + + +int DiPaletteImage::processNextFrames(const unsigned long fcount) +{ + if (DiImage::processNextFrames(fcount)) + { + delete InterData; + InterData = NULL; + Init(); + return (ImageStatus == EIS_Normal); + } + return 0; +} diff --git a/dcmimage/libsrc/dipipng.cc b/dcmimage/libsrc/dipipng.cc new file mode 100644 index 00000000..9488d9f1 --- /dev/null +++ b/dcmimage/libsrc/dipipng.cc @@ -0,0 +1,235 @@ +/* + * + * Copyright (C) 2003-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimage + * + * Author: Alexander Haderer + * + * Purpose: Implements PNG interface for plugable image formats + * + */ + + +#include "dcmtk/config/osconfig.h" + +#ifdef WITH_LIBPNG + +#include "dcmtk/dcmdata/dctypes.h" +#include "dcmtk/dcmimgle/diimage.h" +#include "dcmtk/dcmimage/dipipng.h" +#include "dcmtk/dcmdata/dcuid.h" /* for dcmtk version */ + +BEGIN_EXTERN_C +#ifdef HAVE_LIBPNG_PNG_H +#include +#else +#include +#endif +END_EXTERN_C + + +DiPNGPlugin::DiPNGPlugin() +: DiPluginFormat() +, interlaceType(E_pngInterlaceAdam7) +, metainfoType(E_pngFileMetainfo) +, bitsPerSample(8) +{ +} + + +DiPNGPlugin::~DiPNGPlugin() +{ +} + + +int DiPNGPlugin::write( + DiImage *image, + FILE *stream, + const unsigned long frame) const +{ + volatile int result = 0; // gcc -W requires volatile here because of longjmp + if ((image != NULL) && (stream != NULL)) + { + /* create bitmap with 8 or 16 bits per sample */ + const int bit_depth = bitsPerSample; + const void *data = image->getOutputData(frame, bit_depth /*bits*/, 0 /*planar*/); + if (data != NULL) + { + png_struct *png_ptr = NULL; + png_info *info_ptr = NULL; + png_byte *pix_ptr = NULL; + + png_byte ** volatile row_ptr = NULL; + volatile png_textp text_ptr = NULL; + png_time ptime; + + const int width = image->getColumns(); + const int height = image->getRows(); + int color_type; + int bpp; // bytesperpixel + + int row; + + // create png write struct + png_ptr = png_create_write_struct( PNG_LIBPNG_VER_STRING, NULL, NULL, NULL ); + if( png_ptr == NULL ) { + return 0; + } + + // create png info struct + info_ptr = png_create_info_struct( png_ptr ); + if( info_ptr == NULL ) { + png_destroy_write_struct( &png_ptr, NULL ); + return 0; + } + + // setjmp stuff for png lib + if( setjmp(png_jmpbuf(png_ptr) ) ) { + png_destroy_write_struct( &png_ptr, NULL ); + if( row_ptr ) delete[] row_ptr; + if( text_ptr ) delete[] text_ptr; + return 0; + } + + if( (image->getInternalColorModel() == EPI_Monochrome1) || + (image->getInternalColorModel() == EPI_Monochrome2) ) + { + color_type = PNG_COLOR_TYPE_GRAY; + bpp = bit_depth / 8; + } else { + color_type = PNG_COLOR_TYPE_RGB; + bpp = 3 * bit_depth / 8; + } + + int opt_interlace = 0; + switch (interlaceType) { + case E_pngInterlaceAdam7: + opt_interlace = PNG_INTERLACE_ADAM7; + break; + case E_pngInterlaceNone: + opt_interlace = PNG_INTERLACE_NONE; + break; + } + + // init png io structure + png_init_io( png_ptr, stream ); + + // set write mode + png_set_IHDR( png_ptr, info_ptr, width, height, bit_depth, color_type, + opt_interlace, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); + + // set text & time + if( metainfoType == E_pngFileMetainfo ) { + text_ptr = new png_text[3]; + if( text_ptr == NULL ) { + png_destroy_write_struct( &png_ptr, NULL ); + return result; + } + text_ptr[0].key = OFconst_cast(char *, "Title"); + text_ptr[0].text = OFconst_cast(char *, "Converted DICOM Image"); + text_ptr[0].compression = PNG_TEXT_COMPRESSION_NONE; + text_ptr[1].key = OFconst_cast(char *, "Software"); + text_ptr[1].text = OFconst_cast(char *, "OFFIS DCMTK"); + text_ptr[1].compression = PNG_TEXT_COMPRESSION_NONE; + text_ptr[2].key = OFconst_cast(char *, "Version"); + text_ptr[2].text = OFconst_cast(char *, OFFIS_DCMTK_VERSION); + text_ptr[2].compression = PNG_TEXT_COMPRESSION_NONE; +#ifdef PNG_iTXt_SUPPORTED + text_ptr[0].lang = NULL; + text_ptr[1].lang = NULL; + text_ptr[2].lang = NULL; +#endif + png_set_text( png_ptr, info_ptr, text_ptr, 3 ); + + png_convert_from_time_t( &ptime, time(NULL) ); + png_set_tIME( png_ptr, info_ptr, &ptime ); + } + + // write header + png_write_info( png_ptr, info_ptr ); + row_ptr = new png_bytep[height]; + if( row_ptr == NULL ) { + png_destroy_write_struct( &png_ptr, NULL ); + if( text_ptr ) delete[] text_ptr; + return result; + } + for( row=0, pix_ptr=OFstatic_cast(png_byte*, OFconst_cast(void*, data)); + row + +#ifdef HAVE_WINDOWS_H +#include /* for _get_osfhandle() */ +#endif +END_EXTERN_C + + +DiTIFFPlugin::DiTIFFPlugin() +: DiPluginFormat() +, compressionType(E_tiffLZWCompression) +, predictor(E_tiffLZWPredictorDefault) +, rowsPerStrip(0) +{ +} + + +DiTIFFPlugin::~DiTIFFPlugin() +{ +} + + +int DiTIFFPlugin::write( + DiImage *image, + FILE *stream, + const unsigned long frame) const +{ + int result = 0; + if ((image != NULL) && (stream != NULL)) + { + int stream_fd = fileno(stream); + + +#ifdef HAVE_WINDOWS_H + +#if TIFFLIB_VERSION < 20050912 +#error TIFF library versions prior to 3.7.4 are not supported by DCMTK on Win32 - critical API change! +#endif + +/* Older versions of libtiff expected a Win32 HANDLE when compiled on Windows + * instead of a file descriptor. The code below was needed to make that work. + * Libtiff version 3.7.4 and newer are known to use a file descriptor instead, + * but it is not completely clear at which libtiff release the API change happened. + * + * #ifdef __CYGWIN__ + * stream_fd = OFstatic_cast(int, get_osfhandle(stream_fd)); + * #else + * stream_fd =OFstatic_cast(int, _get_osfhandle(stream_fd)); + * #endif + */ + +#elif TIFFLIB_VERSION < 20041016 +#error TIFF library versions prior to 3.7.0 are not supported by DCMTK - TIFFCleanup is missing! +#endif + + /* create bitmap with 8 bits per sample */ + void *data = OFconst_cast(void *, image->getOutputData(frame, 8 /*bits*/, 0 /*planar*/)); + if (data != NULL) + { + OFBool isMono = (image->getInternalColorModel() == EPI_Monochrome1) || (image->getInternalColorModel() == EPI_Monochrome2); + Uint16 rows = image->getRows(); + Uint16 cols = image->getColumns(); + + short photometric = isMono ? PHOTOMETRIC_MINISBLACK : PHOTOMETRIC_RGB; + short samplesperpixel = isMono ? 1 : 3; + unsigned long bytesperrow = cols * samplesperpixel; + if (bytesperrow > 0) + { + short opt_predictor = 0; + switch (predictor) + { + case E_tiffLZWPredictorDefault: + opt_predictor = 0; + break; + case E_tiffLZWPredictorNoPrediction: + opt_predictor = 1; + break; + case E_tiffLZWPredictorHDifferencing: + opt_predictor = 2; + break; + } + + unsigned short opt_compression = COMPRESSION_NONE; + switch (compressionType) + { + case E_tiffLZWCompression: + opt_compression = COMPRESSION_LZW; + break; + case E_tiffPackBitsCompression: + opt_compression = COMPRESSION_PACKBITS; + break; + case E_tiffNoCompression: + opt_compression = COMPRESSION_NONE; + break; + } + + long opt_rowsperstrip = OFstatic_cast(long, rowsPerStrip); + if (opt_rowsperstrip <= 0) opt_rowsperstrip = 8192 / bytesperrow; + if (opt_rowsperstrip == 0) opt_rowsperstrip++; + + OFBool OK = OFTrue; + unsigned char *bytedata = OFstatic_cast(unsigned char *, data); + TIFF *tif = TIFFFdOpen(stream_fd, "TIFF", "w"); + if (tif) + { + /* Set TIFF parameters. */ + TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, cols); + TIFFSetField(tif, TIFFTAG_IMAGELENGTH, rows); + TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 8); + TIFFSetField(tif, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT); + TIFFSetField(tif, TIFFTAG_COMPRESSION, opt_compression); + if (opt_compression == COMPRESSION_LZW && opt_predictor != 0) + TIFFSetField(tif, TIFFTAG_PREDICTOR, opt_predictor); + TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, photometric); + TIFFSetField(tif, TIFFTAG_FILLORDER, FILLORDER_MSB2LSB); + TIFFSetField(tif, TIFFTAG_DOCUMENTNAME, "unnamed"); + TIFFSetField(tif, TIFFTAG_IMAGEDESCRIPTION, "converted DICOM image"); + TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, samplesperpixel); + TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, opt_rowsperstrip); + /* TIFFSetField(tif, TIFFTAG_STRIPBYTECOUNTS, rows / opt_rowsperstrip); */ + TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); + + /* Now write the TIFF data. */ + unsigned long offset = 0; + for (Uint16 i=0; (i < rows) && OK; i++) + { + if (TIFFWriteScanline(tif, bytedata + offset, i, 0) < 0) OK = OFFalse; + offset += bytesperrow; + } + TIFFFlushData(tif); + /* Clean up internal structures and free memory. + * However, the file will be closed by the caller, therefore + * TIFFClose(tif) is not called. + */ + TIFFCleanup(tif); + } + if (OK) result = 1; + } + } + + /* delete pixel data */ + image->deleteOutputData(); + } + return result; +} + + +void DiTIFFPlugin::setCompressionType(DiTIFFCompression ctype) +{ + compressionType = ctype; +} + +void DiTIFFPlugin::setLZWPredictor(DiTIFFLZWPredictor pred) +{ + predictor = pred; +} + +void DiTIFFPlugin::setRowsPerStrip(unsigned long rows) +{ + rowsPerStrip = rows; +} + +OFString DiTIFFPlugin::getLibraryVersionString() +{ + /* use first line only, omit copyright information */ + OFString versionStr = TIFFGetVersion(); + const size_t pos = versionStr.find('\n'); + if (pos != OFString_npos) + versionStr.erase(pos); + return versionStr; +} + +#else /* WITH_LIBTIFF */ + +int dipitiff_cc_dummy_to_keep_linker_from_moaning = 0; + +#endif diff --git a/dcmimage/libsrc/diqtctab.cc b/dcmimage/libsrc/diqtctab.cc new file mode 100644 index 00000000..559e2d9c --- /dev/null +++ b/dcmimage/libsrc/diqtctab.cc @@ -0,0 +1,546 @@ +/* + * + * Copyright (C) 2002-2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimage + * + * Author: Marco Eichelberg + * + * Purpose: class DcmQuantColorTable + * + */ + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/dcmimage/diqtctab.h" +#include "dcmtk/dcmimage/diqtpbox.h" +#include "dcmtk/dcmdata/dcerror.h" /* for EC_IllegalCall */ +#include "dcmtk/dcmdata/dcelem.h" /* for DcmElement */ +#include "dcmtk/dcmdata/dcitem.h" /* for DcmItem */ +#include "dcmtk/dcmdata/dcvrus.h" /* for DcmUnsignedShort */ +#include "dcmtk/dcmdata/dcvrobow.h" /* for DcmOtherByteOtherWord */ +#include "dcmtk/dcmdata/dcswap.h" /* for swapIfNecessary() */ +#include "dcmtk/dcmdata/dcdeftag.h" /* for tag constants */ +#include "dcmtk/dcmdata/dcuid.h" /* for OFFIS_DCMTK_VERSION */ + +#define INCLUDE_CSTDIO +#include "dcmtk/ofstd/ofstdinc.h" + +/* ------------------------------------------------------------ */ + +// static comparison functions for qsort + +BEGIN_EXTERN_C +static int redcompare(const void *x1, const void *x2) +{ + return OFstatic_cast(int, (*OFstatic_cast(const DcmQuantHistogramItemPointer *, x1))->getRed()) + - OFstatic_cast(int, (*OFstatic_cast(const DcmQuantHistogramItemPointer *, x2))->getRed()); +} + +static int greencompare(const void *x1, const void *x2) +{ + return OFstatic_cast(int, (*OFstatic_cast(const DcmQuantHistogramItemPointer *, x1))->getGreen()) + - OFstatic_cast(int, (*OFstatic_cast(const DcmQuantHistogramItemPointer *, x2))->getGreen()); +} + +static int bluecompare(const void *x1, const void *x2) +{ + return OFstatic_cast(int, (*OFstatic_cast(const DcmQuantHistogramItemPointer *, x1))->getBlue()) + - OFstatic_cast(int, (*OFstatic_cast(const DcmQuantHistogramItemPointer *, x2))->getBlue()); +} +END_EXTERN_C + +/* ------------------------------------------------------------ */ + +DcmQuantColorTable::DcmQuantColorTable() +: array(NULL) +, numColors(0) +, maxval(0) +{ +} + + +DcmQuantColorTable::~DcmQuantColorTable() +{ + clear(); +} + + +void DcmQuantColorTable::clear() +{ + if (array) + { + for (unsigned long i=0; i < numColors; i++) delete array[i]; + delete[] array; + array = NULL; + } + numColors = 0; + maxval = 0; +} + + +OFCondition DcmQuantColorTable::computeHistogram( + DicomImage& image, + unsigned long maxcolors) +{ + // reset object to initial state + clear(); + + // compute initial maxval + maxval = OFstatic_cast(DcmQuantComponent, -1); + DcmQuantColorHashTable *htable = NULL; + + // attempt to make a histogram of the colors, unclustered. + // If at first we don't succeed, lower maxval to increase color + // coherence and try again. This will eventually terminate. + OFBool done = OFFalse; + while (! done) + { + htable = new DcmQuantColorHashTable(); + numColors = htable->addToHashTable(image, maxval, maxcolors); + if (numColors > 0) done = OFTrue; + else + { + delete htable; + maxval = maxval/2; + } + } + + numColors = htable->createHistogram(array); + delete htable; + return EC_Normal; +} + + +OFCondition DcmQuantColorTable::medianCut( + DcmQuantColorTable& histogram, + unsigned long sum, + unsigned long theMaxval, + unsigned long numberOfColors, + DcmLargestDimensionType largeType, + DcmRepresentativeColorType repType) +{ + // reset object to initial state + clear(); + + // update maxval + maxval = theMaxval; + + // initialize color table + array = new DcmQuantHistogramItemPointer[numberOfColors]; + for (unsigned int xx=0; xx < numberOfColors; xx++) array[xx] = new DcmQuantHistogramItem(); + numColors = numberOfColors; + + register int i; + register unsigned int bi; + DcmQuantPixelBoxArray bv(numberOfColors); + + // Set up the initial box. + bv[0].ind = 0; + bv[0].colors = OFstatic_cast(int, histogram.getColors()); + bv[0].sum = sum; + unsigned int boxes = 1; + + // Main loop: split boxes until we have enough. + while ( boxes < numberOfColors ) + { + register int indx, clrs; + unsigned long sm; + register int minr, maxr, ming, maxg, minb, maxb, v; + unsigned long halfsum, lowersum; + + // Find the first splittable box. + for ( bi = 0; bi < boxes; ++bi ) + if ( bv[bi].colors >= 2 ) + break; + if ( bi == boxes ) + break; /* ran out of colors! */ + indx = bv[bi].ind; + clrs = bv[bi].colors; + sm = bv[bi].sum; + + // Go through the box finding the minimum and maximum of each + // component - the boundaries of the box. + minr = maxr = histogram.array[indx]->getRed(); + ming = maxg = histogram.array[indx]->getGreen(); + minb = maxb = histogram.array[indx]->getBlue(); + for ( i = 1; i < clrs; ++i ) + { + v = histogram.array[indx+i]->getRed(); + if ( v < minr ) minr = v; + if ( v > maxr ) maxr = v; + v = histogram.array[indx+i]->getGreen(); + if ( v < ming ) ming = v; + if ( v > maxg ) maxg = v; + v = histogram.array[indx+i]->getBlue(); + if ( v < minb ) minb = v; + if ( v > maxb ) maxb = v; + } + + /* + ** Find the largest dimension, and sort by that component. I have + ** included two methods for determining the "largest" dimension; + ** first by simply comparing the range in RGB space, and second + ** by transforming into luminosities before the comparison. + */ + if (largeType == DcmLargestDimensionType_default) + { + if ( maxr - minr >= maxg - ming && maxr - minr >= maxb - minb ) + qsort(OFreinterpret_cast(char*, &(histogram.array[indx])), clrs, sizeof(DcmQuantHistogramItemPointer), redcompare); + else if ( maxg - ming >= maxb - minb ) + qsort(OFreinterpret_cast(char*, &(histogram.array[indx])), clrs, sizeof(DcmQuantHistogramItemPointer), greencompare); + else + qsort(OFreinterpret_cast(char*, &(histogram.array[indx])), clrs, sizeof(DcmQuantHistogramItemPointer), bluecompare); + } + else // DcmLargestDimensionType_luminance + { + double rl, gl, bl; + DcmQuantPixel p; + + p.assign(maxr - minr, 0, 0); + rl = p.luminance(); + + p.assign(0, maxg - ming, 0); + gl = p.luminance(); + + p.assign(0, 0, maxb - minb); + bl = p.luminance(); + + if ( rl >= gl && rl >= bl ) + qsort(OFreinterpret_cast(char*, &(histogram.array[indx])), clrs, sizeof(DcmQuantHistogramItemPointer), redcompare); + else if ( gl >= bl ) + qsort(OFreinterpret_cast(char*, &(histogram.array[indx])), clrs, sizeof(DcmQuantHistogramItemPointer), greencompare); + else + qsort(OFreinterpret_cast(char*, &(histogram.array[indx])), clrs, sizeof(DcmQuantHistogramItemPointer), bluecompare); + } + + /* + ** Now find the median based on the counts, so that about half the + ** pixels (not colors, pixels) are in each subdivision. + */ + lowersum = histogram.array[indx]->getValue(); + halfsum = sm / 2; + for ( i = 1; i < clrs - 1; ++i ) + { + if ( lowersum >= halfsum ) + break; + lowersum += histogram.array[indx+i]->getValue(); + } + + // Split the box, and sort to bring the biggest boxes to the top. + bv[bi].colors = i; + bv[bi].sum = lowersum; + bv[boxes].ind = indx + i; + bv[boxes].colors = clrs - i; + bv[boxes].sum = sm - lowersum; + ++boxes; + bv.sort(boxes); + } + + /* + ** Ok, we've got enough boxes. Now choose a representative color for + ** each box. There are a number of possible ways to make this choice. + ** One would be to choose the center of the box; this ignores any structure + ** within the boxes. Another method would be to average all the colors in + ** the box - this is the method specified in Heckbert's paper. A third + ** method is to average all the pixels in the box. + */ + if (repType == DcmRepresentativeColorType_centerOfBox) + { + for ( bi = 0; bi < boxes; ++bi ) + { + register int indx = bv[bi].ind; + register int clrs = bv[bi].colors; + register int minr, maxr, ming, maxg, minb, maxb, v; + + minr = maxr = histogram.array[indx]->getRed(); + ming = maxg = histogram.array[indx]->getGreen(); + minb = maxb = histogram.array[indx]->getBlue(); + for ( i = 1; i < clrs; ++i ) + { + v = histogram.array[indx+i]->getRed(); + minr = (minr < v ? minr : v); + maxr = (minr > v ? minr : v); + v = histogram.array[indx+i]->getGreen(); + ming = (ming < v ? ming : v); + maxg = (ming > v ? ming : v); + v = histogram.array[indx+i]->getBlue(); + minb = (minb < v ? minb : v); + maxb = (minb > v ? minb : v); + } + array[bi]->assign(( minr + maxr ) / 2, ( ming + maxg ) / 2, ( minb + maxb ) / 2); + } + } + else if (repType == DcmRepresentativeColorType_default) + { + for ( bi = 0; bi < boxes; ++bi ) + { + register int indx = bv[bi].ind; + register int clrs = bv[bi].colors; + register long r = 0, g = 0, b = 0; + + for ( i = 0; i < clrs; ++i ) + { + r += histogram.array[indx+i]->getRed(); + g += histogram.array[indx+i]->getGreen(); + b += histogram.array[indx+i]->getBlue(); + } + r = r / clrs; + g = g / clrs; + b = b / clrs; + array[bi]->assign(OFstatic_cast(DcmQuantComponent, r), OFstatic_cast(DcmQuantComponent, g), OFstatic_cast(DcmQuantComponent, b)); + } + } + else // DcmRepresentativeColorType_averagePixels + { + for ( bi = 0; bi < boxes; ++bi ) + { + register int indx = bv[bi].ind; + register int clrs = bv[bi].colors; + register unsigned long r = 0, g = 0, b = 0, sumVal = 0; + + for ( i = 0; i < clrs; ++i ) + { + r += histogram.array[indx+i]->getRed() * histogram.array[indx+i]->getValue(); + g += histogram.array[indx+i]->getGreen() * histogram.array[indx+i]->getValue(); + b += histogram.array[indx+i]->getBlue() * histogram.array[indx+i]->getValue(); + sumVal += histogram.array[indx+i]->getValue(); + } + r = r / sumVal; + if ( r > maxval ) r = maxval; /* avoid math errors */ + g = g / sumVal; + if ( g > maxval ) g = maxval; + b = b / sumVal; + if ( b > maxval ) b = maxval; + array[bi]->assign(OFstatic_cast(DcmQuantComponent, r), OFstatic_cast(DcmQuantComponent, g), OFstatic_cast(DcmQuantComponent, b)); + } + } + + // All done, now compute clusters + computeClusters(); + return EC_Normal; +} + + +void DcmQuantColorTable::computeClusters() +{ + unsigned long i; + unsigned long j; + unsigned long k=0; + int cluster; + int newdist; + int r1, g1, b1; + int r2, g2, b2; + + // initialize clusters + for (i = 0; i < numColors; ++i) array[i]->setValue(2000000000); + + for (i = 0; i < numColors-1; ++i) + { + cluster = array[i]->getValue(); + r1 = OFstatic_cast(int, array[i]->getRed()); + g1 = OFstatic_cast(int, array[i]->getGreen()); + b1 = OFstatic_cast(int, array[i]->getBlue()); + + for (j = i+1; j < numColors; ++j) + { + // compute euclidean distance between i and j + r2 = r1 - OFstatic_cast(int, array[j]->getRed()); + g2 = g1 - OFstatic_cast(int, array[j]->getGreen()); + b2 = b1 - OFstatic_cast(int, array[j]->getBlue()); + newdist = (r2*r2 + g2*g2 + b2*b2)/2; + if (newdist < cluster) + { + cluster = newdist; + k = j; + } + } + array[i]->setValue(cluster); + array[k]->setValue(cluster); + } +} + + +OFCondition DcmQuantColorTable::write( + DcmItem& target, + OFBool writeAsOW, + OFBool write16BitEntries) +{ + if (numColors == 0) return EC_IllegalCall; + + // if we're using 16 bit per sample anyway, force 16 bit palette entries + if (sizeof(DcmQuantComponent) > 1) write16BitEntries = OFTrue; + + OFCondition result = EC_Normal; + if (array) + { + // create palette color LUT descriptor + Uint16 descriptor[3]; + descriptor[0] = (numColors > 65535) ? 0 : OFstatic_cast(Uint16, numColors); // number of entries + descriptor[1] = 0; // first pixel value mapped + descriptor[2] = write16BitEntries ? 16 : 8; // bits per entry, must be 8 or 16. + + // if we're writing a 16-bit LUT with 64K entries, we must write as OW because + // otherwise the US length field will overflow when writing in explicit VR! + if ((descriptor[0] == 0) && write16BitEntries) writeAsOW = OFTrue; + + DcmElement *elem; + if (result.good()) + { + elem = new DcmUnsignedShort(DCM_RedPaletteColorLookupTableDescriptor); + if (elem) + { + result = elem->putUint16Array(descriptor, 3); + if (result.good()) result = target.insert(elem, OFTrue); + if (result.bad()) delete elem; + } else result = EC_MemoryExhausted; + } + + if (result.good()) + { + elem = new DcmUnsignedShort(DCM_GreenPaletteColorLookupTableDescriptor); + if (elem) + { + result = elem->putUint16Array(descriptor, 3); + if (result.good()) result = target.insert(elem, OFTrue); + if (result.bad()) delete elem; + } else result = EC_MemoryExhausted; + } + + if (result.good()) + { + elem = new DcmUnsignedShort(DCM_BluePaletteColorLookupTableDescriptor); + if (elem) + { + result = elem->putUint16Array(descriptor, 3); + if (result.good()) result = target.insert(elem, OFTrue); + if (result.bad()) delete elem; + } else result = EC_MemoryExhausted; + } + + // now create the LUT content + if (result.good()) + { + Uint16* rLUT = NULL; + Uint16* gLUT = NULL; + Uint16* bLUT = NULL; + unsigned long numWords = 0; + double factor = 1.0; + if (write16BitEntries) + { + numWords = numColors; + rLUT = new Uint16[numWords]; + gLUT = new Uint16[numWords]; + bLUT = new Uint16[numWords]; + factor = 65535.0 / maxval; + if (rLUT && gLUT && bLUT) + { + for (unsigned long i=0; igetRed()) * factor); + gLUT[i] = OFstatic_cast(Uint16, OFstatic_cast(double, array[i]->getGreen()) * factor); + bLUT[i] = OFstatic_cast(Uint16, OFstatic_cast(double, array[i]->getBlue()) * factor); + + // if the source data is only 8 bits per entry, replicate high and low bytes + if (sizeof(DcmQuantComponent) == 1) + { + rLUT[i] |= rLUT[i] << 8; + gLUT[i] |= gLUT[i] << 8; + bLUT[i] |= bLUT[i] << 8; + } + } + } else result = EC_MemoryExhausted; + } + else + { + // number of Uint16 words needed to store numColors Uint8 values plus padding + numWords = (numColors+1)/2; + rLUT = new Uint16[numWords]; + gLUT = new Uint16[numWords]; + bLUT = new Uint16[numWords]; + rLUT[numWords-1] = 0; + gLUT[numWords-1] = 0; + bLUT[numWords-1] = 0; + factor = 255.0 / maxval; + if (rLUT && gLUT && bLUT) + { + Uint8 *rLUT8 = OFreinterpret_cast(Uint8 *, rLUT); + Uint8 *gLUT8 = OFreinterpret_cast(Uint8 *, gLUT); + Uint8 *bLUT8 = OFreinterpret_cast(Uint8 *, bLUT); + for (unsigned long i=0; igetRed()) * factor); + gLUT8[i] = OFstatic_cast(Uint8, OFstatic_cast(double, array[i]->getGreen()) * factor); + bLUT8[i] = OFstatic_cast(Uint8, OFstatic_cast(double, array[i]->getBlue()) * factor); + } + // we have written the byte array in little endian order, now swap to US/OW if neccessary + swapIfNecessary(gLocalByteOrder, EBO_LittleEndian, rLUT, numWords*sizeof(Uint16), sizeof(Uint16)); + swapIfNecessary(gLocalByteOrder, EBO_LittleEndian, gLUT, numWords*sizeof(Uint16), sizeof(Uint16)); + swapIfNecessary(gLocalByteOrder, EBO_LittleEndian, bLUT, numWords*sizeof(Uint16), sizeof(Uint16)); + } else result = EC_MemoryExhausted; + } + + // the LUT data is prepared, now create the corresponding DICOM elements + if (result.good()) + { + if (writeAsOW) elem = new DcmOtherByteOtherWord(DcmTag(DCM_RedPaletteColorLookupTableData, EVR_OW)); + else elem = new DcmUnsignedShort(DcmTag(DCM_RedPaletteColorLookupTableData, EVR_US)); + if (elem) + { + result = elem->putUint16Array(rLUT, numWords); + if (result.good()) result = target.insert(elem, OFTrue); + if (result.bad()) delete elem; + } else result = EC_MemoryExhausted; + } + + if (result.good()) + { + if (writeAsOW) elem = new DcmOtherByteOtherWord(DcmTag(DCM_GreenPaletteColorLookupTableData, EVR_OW)); + else elem = new DcmUnsignedShort(DcmTag(DCM_GreenPaletteColorLookupTableData, EVR_US)); + if (elem) + { + result = elem->putUint16Array(gLUT, numWords); + if (result.good()) result = target.insert(elem, OFTrue); + if (result.bad()) delete elem; + } else result = EC_MemoryExhausted; + } + + if (result.good()) + { + if (writeAsOW) elem = new DcmOtherByteOtherWord(DcmTag(DCM_BluePaletteColorLookupTableData, EVR_OW)); + else elem = new DcmUnsignedShort(DcmTag(DCM_BluePaletteColorLookupTableData, EVR_US)); + if (elem) + { + result = elem->putUint16Array(bLUT, numWords); + if (result.good()) result = target.insert(elem, OFTrue); + if (result.bad()) delete elem; + } else result = EC_MemoryExhausted; + } + delete[] rLUT; + delete[] gLUT; + delete[] bLUT; + } + } else result = EC_IllegalCall; + + return result; +} + +void DcmQuantColorTable::setDescriptionString(OFString& str) const +{ + char buf[100]; + + sprintf(buf, "Converted to PALETTE COLOR %lu/0/%u with DCMTK %s", + (numColors > 65535) ? 0 : numColors, (sizeof(DcmQuantComponent) == 1) ? 8 : 16, + OFFIS_DCMTK_VERSION); + + str = buf; +} diff --git a/dcmimage/libsrc/diqtfs.cc b/dcmimage/libsrc/diqtfs.cc new file mode 100644 index 00000000..57947e64 --- /dev/null +++ b/dcmimage/libsrc/diqtfs.cc @@ -0,0 +1,101 @@ +/* + * + * Copyright (C) 2002-2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimage + * + * Author: Marco Eichelberg + * + * Purpose: class DcmQuantFloydSteinberg + * + */ + + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmimage/diqtfs.h" +#include "dcmtk/ofstd/ofstd.h" /* for OFStandard::myrand_r */ + +#define INCLUDE_CTIME +#include "dcmtk/ofstd/ofstdinc.h" + +BEGIN_EXTERN_C +#include // needed for time() +END_EXTERN_C + + +DcmQuantFloydSteinberg::DcmQuantFloydSteinberg() +: thisrerr(NULL) +, nextrerr(NULL) +, thisgerr(NULL) +, nextgerr(NULL) +, thisberr(NULL) +, nextberr(NULL) +, temperr (NULL) +, fs_direction(0) +, columns(0) +{ +} + + +DcmQuantFloydSteinberg::~DcmQuantFloydSteinberg() +{ + cleanup(); +} + + +void DcmQuantFloydSteinberg::cleanup() +{ + delete[] thisrerr; + delete[] nextrerr; + delete[] thisgerr; + delete[] nextgerr; + delete[] thisberr; + delete[] nextberr; +} + + +OFCondition DcmQuantFloydSteinberg::initialize(unsigned long cols) +{ + columns = cols; + cleanup(); + unsigned int now = OFstatic_cast(unsigned int, time(NULL)); + + /* Initialize Floyd-Steinberg error vectors. */ + thisrerr = new long[columns+2]; + if (! thisrerr) return EC_MemoryExhausted; + + nextrerr = new long[columns+2]; + if (! nextrerr) return EC_MemoryExhausted; + + thisgerr = new long[columns+2]; + if (! thisgerr) return EC_MemoryExhausted; + + nextgerr = new long[columns+2]; + if (! nextgerr) return EC_MemoryExhausted; + + thisberr = new long[columns+2]; + if (! thisberr) return EC_MemoryExhausted; + + nextberr = new long[columns+2]; + if (! nextberr) return EC_MemoryExhausted; + + for (unsigned long col = 0; col < columns + 2; ++col) + { + thisrerr[col] = OFrand_r(now) % ( DcmQuantFloydSteinbergScale * 2 ) - DcmQuantFloydSteinbergScale; + thisgerr[col] = OFrand_r(now) % ( DcmQuantFloydSteinbergScale * 2 ) - DcmQuantFloydSteinbergScale; + thisberr[col] = OFrand_r(now) % ( DcmQuantFloydSteinbergScale * 2 ) - DcmQuantFloydSteinbergScale; + /* (random errors in [-1 .. 1]) */ + } + fs_direction = 1; + + return EC_Normal; +} diff --git a/dcmimage/libsrc/diqthash.cc b/dcmimage/libsrc/diqthash.cc new file mode 100644 index 00000000..d93e9347 --- /dev/null +++ b/dcmimage/libsrc/diqthash.cc @@ -0,0 +1,114 @@ +/* + * + * Copyright (C) 2002-2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimage + * + * Author: Marco Eichelberg + * + * Purpose: class DcmQuantColorHashTable + * + */ + + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmimage/diqthash.h" +#include "dcmtk/dcmdata/dcxfer.h" /* for E_TransferSyntax */ +#include "dcmtk/dcmimgle/dcmimage.h" /* for DicomImage */ + + +DcmQuantColorHashTable::DcmQuantColorHashTable() +: m_Table(DcmQuantHashSize, OFnullptr) +{ + +} + + +DcmQuantColorHashTable::~DcmQuantColorHashTable() +{ + for (table_iterator it = m_Table.begin(); it != m_Table.end(); delete *it++); +} + + +unsigned long DcmQuantColorHashTable::countEntries() const +{ + unsigned long result = 0; + for (const_table_iterator it = m_Table.begin(); it != m_Table.end(); ++it) + if (*it) result += (*it)->size(); + return result; +} + + +unsigned long DcmQuantColorHashTable::createHistogram(DcmQuantHistogramItemPointer *& array) +{ + unsigned long numcolors = countEntries(); + array = new DcmQuantHistogramItemPointer[numcolors]; + if (array) + { + unsigned long counter = 0; + for (table_iterator it = m_Table.begin(); it != m_Table.end(); ++it) + if (*it) (*it)->moveto(array, counter, numcolors); + } + return numcolors; +} + + +unsigned long DcmQuantColorHashTable::addToHashTable( + DicomImage& image, + unsigned long newmaxval, + unsigned long maxcolors) +{ + const unsigned long cols = image.getWidth(); + const unsigned long rows = image.getHeight(); + const unsigned long frames = image.getFrameCount(); + const int bits = sizeof(DcmQuantComponent)*8; + + unsigned long numcolors = 0; + unsigned long j, k; + const DcmQuantComponent *cp; + DcmQuantPixel px; + const void *data = NULL; + + // compute maxval + unsigned long maxval = 0; + for (int bb=0; bb < bits; bb++) maxval = (maxval << 1) | 1; + + DcmQuantScaleTable scaletable; + scaletable.createTable(maxval, newmaxval); + + register DcmQuantComponent r, g, b; + + for (unsigned long ff=0; ff maxcolors) return 0; + } + } + } + } + return numcolors; +} diff --git a/dcmimage/libsrc/diqthitl.cc b/dcmimage/libsrc/diqthitl.cc new file mode 100644 index 00000000..dbb67c31 --- /dev/null +++ b/dcmimage/libsrc/diqthitl.cc @@ -0,0 +1,53 @@ +/* + * + * Copyright (C) 2002-2010, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimage + * + * Author: Marco Eichelberg + * + * Purpose: class DcmQuantHistogramItemList + * + */ + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmimage/diqthitl.h" + + +DcmQuantHistogramItemList::DcmQuantHistogramItemList() +: list_() +, first(list_.end()) +, last(list_.end()) +{ +} + + +DcmQuantHistogramItemList::~DcmQuantHistogramItemList() +{ + first = list_.begin(); + while (first != last) + { + delete *first; + first = list_.erase(first); + } +} + + +void DcmQuantHistogramItemList::moveto(DcmQuantHistogramItemPointer *array, unsigned long& counter, unsigned long numcolors) +{ + first = list_.begin(); + while ((first != last) && (counter < numcolors)) + { + array[counter++] = *first; + first = list_.erase(first); + } +} diff --git a/dcmimage/libsrc/diqtpbox.cc b/dcmimage/libsrc/diqtpbox.cc new file mode 100644 index 00000000..ac3648d5 --- /dev/null +++ b/dcmimage/libsrc/diqtpbox.cc @@ -0,0 +1,65 @@ +/* + * + * Copyright (C) 2002-2010, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimage + * + * Author: Marco Eichelberg + * + * Purpose: class DcmQuantPixelBoxArray + * + */ + + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/ofstd/ofcast.h" +#include "dcmtk/dcmimage/diqtpbox.h" /* for DcmQuantPixelBoxArray */ + +#ifdef USE_STD_CXX_INCLUDES +// Solaris defines qsort() in namespace std, other compilers don't... +namespace std { } +using namespace std; +#endif + + +BEGIN_EXTERN_C +static int sumcompare(const void *x1, const void *x2) +{ + return (*(DcmQuantPixelBoxPointer *) x2)->sum + - (*(DcmQuantPixelBoxPointer *) x1)->sum; +} +END_EXTERN_C + + +void DcmQuantPixelBoxArray::sort(unsigned long boxes) +{ +#ifdef DEBUG + assert(boxes <= length); +#endif + qsort(OFreinterpret_cast(char *, array), OFstatic_cast(unsigned int, boxes), sizeof(DcmQuantPixelBoxPointer), sumcompare); +} + + +DcmQuantPixelBoxArray::DcmQuantPixelBoxArray(unsigned long entries) +: array(NULL) +, length(entries) +{ + array = new DcmQuantPixelBoxPointer[entries]; + for (unsigned long i=0; i 65536)||(numberOfColors < 2)) return EC_IllegalCall; + + OFCondition result = EC_Normal; + + // Create histogram of the colors, clustered if necessary + DCMIMAGE_DEBUG("computing image histogram"); + + DcmQuantColorTable chv; + result = chv.computeHistogram(sourceImage, DcmQuantMaxColors); + if (result.bad()) return result; + + unsigned long maxval = chv.getMaxVal(); + DCMIMAGE_DEBUG("image histogram: found " << chv.getColors() << " colors (at maxval=" << maxval << ")"); + + // apply median-cut to histogram, making the new colormap. + unsigned long cols = sourceImage.getWidth(); + unsigned long rows = sourceImage.getHeight(); + unsigned long frames = sourceImage.getFrameCount(); + + DCMIMAGE_DEBUG("computing color map using Heckbert's median cut algorithm"); + + DcmQuantColorTable colormap; + result = colormap.medianCut(chv, cols * rows * frames, maxval, numberOfColors, largeType, repType); + if (result.bad()) return result; + chv.clear(); // frees most memory used by chv. + + // map the colors in the image to their closest match in the + // new colormap, and write 'em out. + DcmQuantColorHashTable cht; + DCMIMAGE_DEBUG("mapping image data to color table"); + + DcmQuantFloydSteinberg fs; + if (floydSteinberg) + { + result = fs.initialize(cols); + if (result.bad()) return result; + } + DcmQuantIdent id(cols); + + register OFBool isByteData = (numberOfColors <= 256); + + // compute size requirement for palette color pixel data in bytes + unsigned long totalSize = cols * rows * frames; + if (! isByteData) totalSize *= 2; + if (totalSize & 1) totalSize++; + + Uint16 *imageData16 = NULL; + Uint8 *imageData8 = NULL; + DcmPixelData *pixelData = new DcmPixelData(DCM_PixelData); + if (pixelData) + { + result = pixelData->createUint16Array(totalSize/sizeof(Uint16), imageData16); + if (result.good()) + { + imageData16[(totalSize/sizeof(Uint16)) -1] = 0; // make sure pad byte is zero + imageData8 = OFreinterpret_cast(Uint8 *, imageData16); + result = target.insert(pixelData, OFTrue); + if (result.good()) + { + for (unsigned long ff=0; ff::create(sourceImage, ff, maxval, cht, colormap, fs, imageData8 + cols*rows*ff); + else DcmQuantColorMapping::create(sourceImage, ff, maxval, cht, colormap, id, imageData8 + cols*rows*ff); + } + else + { + if (floydSteinberg) + DcmQuantColorMapping::create(sourceImage, ff, maxval, cht, colormap, fs, imageData16 + cols*rows*ff); + else DcmQuantColorMapping::create(sourceImage, ff, maxval, cht, colormap, id, imageData16 + cols*rows*ff); + } + } // for all frames + + // image creation is complete, finally adjust byte order if necessary + if (isByteData) + { + result = swapIfNecessary(gLocalByteOrder, EBO_LittleEndian, imageData16, totalSize, sizeof(Uint16)); + } + + } + } + } + + DCMIMAGE_DEBUG("creating DICOM image pixel module"); + + // create target image pixel module + if (result.good()) result = target.putAndInsertUint16(DCM_SamplesPerPixel, 1); + if (result.good()) result = target.putAndInsertUint16(DCM_PixelRepresentation, 0); + if (result.good()) result = target.putAndInsertString(DCM_PhotometricInterpretation, "PALETTE COLOR"); + if (result.good()) result = target.putAndInsertUint16(DCM_Rows, OFstatic_cast(Uint16, rows)); + if (result.good()) result = target.putAndInsertUint16(DCM_Columns, OFstatic_cast(Uint16, cols)); + + // determine bits allocated, stored, high bit + Uint16 bitsAllocated = 8; + Uint16 bitsStored = 8; + Uint16 highBit = 7; + if (! isByteData) + { + bitsAllocated = 16; + bitsStored = 8; + while ((1UL << bitsStored) < OFstatic_cast(unsigned long, numberOfColors)) bitsStored++; + highBit = bitsStored - 1; + } + if (result.good()) result = target.putAndInsertUint16(DCM_BitsAllocated, bitsAllocated); + if (result.good()) result = target.putAndInsertUint16(DCM_BitsStored, bitsStored); + if (result.good()) result = target.putAndInsertUint16(DCM_HighBit, highBit); + + // make sure these attributes are not present in the target image + delete target.remove(DCM_SmallestImagePixelValue); + delete target.remove(DCM_LargestImagePixelValue); + delete target.remove(DCM_PixelPaddingValue); + delete target.remove(DCM_PixelPaddingRangeLimit); + delete target.remove(DCM_SmallestPixelValueInSeries); + delete target.remove(DCM_LargestPixelValueInSeries); + delete target.remove(DCM_PaletteColorLookupTableUID); + delete target.remove(DCM_SegmentedRedPaletteColorLookupTableData); + delete target.remove(DCM_SegmentedGreenPaletteColorLookupTableData); + delete target.remove(DCM_SegmentedBluePaletteColorLookupTableData); + delete target.remove(DCM_PlanarConfiguration); + + // UNIMPLEMENTED: frame increment pointer + // UNIMPLEMENTED: pixel aspect ratio/pixel spacing/imager pixel spacing + + if (frames > 1) + { + char buf[20]; + sprintf(buf, "%lu", frames); + if (result.good()) result = target.putAndInsertString(DCM_NumberOfFrames, buf); + } + + // create palette color LUT descriptor and data + if (result.good()) result = colormap.write(target, writeAsOW, write16BitEntries); + + // create derivation description string + if (result.good()) colormap.setDescriptionString(description); + + return result; +} + + +OFCondition DcmQuant::updateDerivationDescription(DcmItem *dataset, const char *description) +{ + if (description == NULL) return EC_IllegalCall; + + OFString derivationDescription(description); + + // append old Derivation Description, if any + const char *oldDerivation = NULL; + if ((dataset->findAndGetString(DCM_DerivationDescription, oldDerivation)).good() && oldDerivation) + { + derivationDescription += " ["; + derivationDescription += oldDerivation; + derivationDescription += "]"; + if (derivationDescription.length() > 1024) + { + // ST is limited to 1024 characters, cut off tail + derivationDescription.erase(1020); + derivationDescription += "...]"; + } + } + + return dataset->putAndInsertString(DCM_DerivationDescription, derivationDescription.c_str()); +} diff --git a/dcmimage/libsrc/diregist.cc b/dcmimage/libsrc/diregist.cc new file mode 100644 index 00000000..1133a655 --- /dev/null +++ b/dcmimage/libsrc/diregist.cc @@ -0,0 +1,136 @@ +/* + * + * Copyright (C) 1996-2010, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimage + * + * Author: Joerg Riesmeier + * + * Purpose: DicomRegister (Source) + * + */ + + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/dcmimage/diregist.h" +#include "dcmtk/dcmimage/dipalimg.h" +#include "dcmtk/dcmimage/dirgbimg.h" +#include "dcmtk/dcmimage/dihsvimg.h" +#include "dcmtk/dcmimage/diargimg.h" +#include "dcmtk/dcmimage/dicmyimg.h" +#include "dcmtk/dcmimage/diybrimg.h" +#include "dcmtk/dcmimage/diyf2img.h" +#include "dcmtk/dcmimage/diyp2img.h" +#include "dcmtk/dcmimage/dicomot.h" +#include "dcmtk/dcmimgle/didocu.h" + + +/*----------------* + * constructors * + *----------------*/ + +DiRegister::DiRegister() +{ + DiRegisterBase::Pointer = this; +} + + +/*--------------* + * destructor * + *--------------*/ + +DiRegister::~DiRegister() +{ +} + + +/*--------------*/ + +DiImage *DiRegister::createImage(const DiDocument *docu, + const EI_Status status, + const EP_Interpretation photo) +{ + DiImage *image = NULL; + switch (photo) + { + case EPI_PaletteColor: + image = new DiPaletteImage(docu, status); + break; + case EPI_RGB: + image = new DiRGBImage(docu, status); + break; + case EPI_HSV: + image = new DiHSVImage(docu, status); + break; + case EPI_ARGB: + image = new DiARGBImage(docu, status); + break; + case EPI_CMYK: + image = new DiCMYKImage(docu, status); + break; + case EPI_YBR_Full: + image = new DiYBRImage(docu, status); + break; + case EPI_YBR_Full_422: + image = new DiYBR422Image(docu, status); + break; + case EPI_YBR_Partial_422: + image = new DiYBRPart422Image(docu, status); + break; + default: + ; + } + return image; +} + + +DiMonoPixel *DiRegister::createMonoImageData(const DiColorImage *image, + const double red, + const double green, + const double blue) +{ + DiMonoPixel *inter = NULL; + if (image != NULL) + { + const DiColorPixel *color = image->getColorInterData(); + if (color != NULL) + { + DiMonoModality *modality = new DiMonoModality(image->getBits()); + if (modality != NULL) + { + switch (color->getRepresentation()) + { + case EPR_Uint8: + inter = new DiColorMonoTemplate(color, modality, red, green, blue); + break; + case EPR_Sint8: + inter = new DiColorMonoTemplate(color, modality, red, green, blue); + break; + case EPR_Uint16: + inter = new DiColorMonoTemplate(color, modality, red, green, blue); + break; + case EPR_Sint16: + inter = new DiColorMonoTemplate(color, modality, red, green, blue); + break; + case EPR_Uint32: + inter = new DiColorMonoTemplate(color, modality, red, green, blue); + break; + case EPR_Sint32: + inter = new DiColorMonoTemplate(color, modality, red, green, blue); + break; + } + } + } + } + return inter; +} diff --git a/dcmimage/libsrc/dirgbimg.cc b/dcmimage/libsrc/dirgbimg.cc new file mode 100644 index 00000000..432245ed --- /dev/null +++ b/dcmimage/libsrc/dirgbimg.cc @@ -0,0 +1,103 @@ +/* + * + * Copyright (C) 1996-2010, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimage + * + * Author: Joerg Riesmeier + * + * Purpose: DicomRGBImage (Source) + * + */ + + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/dcmdata/dctypes.h" + +#include "dcmtk/dcmimage/dirgbimg.h" +#include "dcmtk/dcmimage/dirgbpxt.h" +#include "dcmtk/dcmimage/dilogger.h" +#include "dcmtk/dcmimgle/diinpx.h" + + +/*----------------* + * constructors * + *----------------*/ + +DiRGBImage::DiRGBImage(const DiDocument *docu, + const EI_Status status) + : DiColorImage(docu, status, 3) +{ + if ((Document != NULL) && (InputData != NULL) && (ImageStatus == EIS_Normal)) + { + Init(); // create intermediate representation + } +} + + +/*--------------* + * destructor * + *--------------*/ + +DiRGBImage::~DiRGBImage() +{ +} + + +/*********************************************************************/ + + +void DiRGBImage::Init() +{ + /* number of pixels per plane */ + const unsigned long planeSize = OFstatic_cast(unsigned long, Columns) * OFstatic_cast(unsigned long, Rows); + switch (InputData->getRepresentation()) + { + case EPR_Uint8: + InterData = new DiRGBPixelTemplate(Document, InputData, ImageStatus, planeSize, BitsPerSample); + break; + case EPR_Sint8: + InterData = new DiRGBPixelTemplate(Document, InputData, ImageStatus, planeSize, BitsPerSample); + break; + case EPR_Uint16: + InterData = new DiRGBPixelTemplate(Document, InputData, ImageStatus, planeSize, BitsPerSample); + break; + case EPR_Sint16: + InterData = new DiRGBPixelTemplate(Document, InputData, ImageStatus, planeSize, BitsPerSample); + break; + case EPR_Uint32: + InterData = new DiRGBPixelTemplate(Document, InputData, ImageStatus, planeSize, BitsPerSample); + break; + case EPR_Sint32: + InterData = new DiRGBPixelTemplate(Document, InputData, ImageStatus, planeSize, BitsPerSample); + break; + } + deleteInputData(); + checkInterData(); +} + + +/*********************************************************************/ + + +int DiRGBImage::processNextFrames(const unsigned long fcount) +{ + if (DiImage::processNextFrames(fcount)) + { + delete InterData; + InterData = NULL; + Init(); + return (ImageStatus == EIS_Normal); + } + return 0; +} diff --git a/dcmimage/libsrc/diybrimg.cc b/dcmimage/libsrc/diybrimg.cc new file mode 100644 index 00000000..81105594 --- /dev/null +++ b/dcmimage/libsrc/diybrimg.cc @@ -0,0 +1,104 @@ +/* + * + * Copyright (C) 1996-2010, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimage + * + * Author: Joerg Riesmeier + * + * Purpose: DicomYBRImage (Source) + * + */ + + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/dcmdata/dctypes.h" + +#include "dcmtk/dcmimage/diybrimg.h" +#include "dcmtk/dcmimage/diybrpxt.h" +#include "dcmtk/dcmimage/dilogger.h" +#include "dcmtk/dcmimgle/diinpx.h" +#include "dcmtk/dcmimgle/didocu.h" + + +/*----------------* + * constructors * + *----------------*/ + +DiYBRImage::DiYBRImage(const DiDocument *docu, + const EI_Status status) + : DiColorImage(docu, status, 3, !(docu->getFlags() & CIF_KeepYCbCrColorModel) /* RGBColorModel */) +{ + if ((Document != NULL) && (InputData != NULL) && (ImageStatus == EIS_Normal)) + { + Init(); // create intermediate representation + } +} + + +/*--------------* + * destructor * + *--------------*/ + +DiYBRImage::~DiYBRImage() +{ +} + + +/*********************************************************************/ + + +void DiYBRImage::Init() +{ + /* number of pixels per plane */ + const unsigned long planeSize = OFstatic_cast(unsigned long, Columns) * OFstatic_cast(unsigned long, Rows); + switch (InputData->getRepresentation()) + { + case EPR_Uint8: + InterData = new DiYBRPixelTemplate(Document, InputData, ImageStatus, planeSize, BitsPerSample, RGBColorModel); + break; + case EPR_Sint8: + InterData = new DiYBRPixelTemplate(Document, InputData, ImageStatus, planeSize, BitsPerSample, RGBColorModel); + break; + case EPR_Uint16: + InterData = new DiYBRPixelTemplate(Document, InputData, ImageStatus, planeSize, BitsPerSample, RGBColorModel); + break; + case EPR_Sint16: + InterData = new DiYBRPixelTemplate(Document, InputData, ImageStatus, planeSize, BitsPerSample, RGBColorModel); + break; + case EPR_Uint32: + InterData = new DiYBRPixelTemplate(Document, InputData, ImageStatus, planeSize, BitsPerSample, RGBColorModel); + break; + case EPR_Sint32: + InterData = new DiYBRPixelTemplate(Document, InputData, ImageStatus, planeSize, BitsPerSample, RGBColorModel); + break; + } + deleteInputData(); + checkInterData(); +} + + +/*********************************************************************/ + + +int DiYBRImage::processNextFrames(const unsigned long fcount) +{ + if (DiImage::processNextFrames(fcount)) + { + delete InterData; + InterData = NULL; + Init(); + return (ImageStatus == EIS_Normal); + } + return 0; +} diff --git a/dcmimage/libsrc/diyf2img.cc b/dcmimage/libsrc/diyf2img.cc new file mode 100644 index 00000000..4aeaa7a8 --- /dev/null +++ b/dcmimage/libsrc/diyf2img.cc @@ -0,0 +1,102 @@ +/* + * + * Copyright (C) 1996-2010, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimage + * + * Author: Joerg Riesmeier + * + * Purpose: DicomYBR422Image (Source) + * + */ + + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/dcmdata/dctypes.h" + +#include "dcmtk/dcmimage/diyf2img.h" +#include "dcmtk/dcmimage/diyf2pxt.h" +#include "dcmtk/dcmimage/dilogger.h" +#include "dcmtk/dcmimgle/diinpx.h" +#include "dcmtk/dcmimgle/didocu.h" + + +/*----------------* + * constructors * + *----------------*/ + +DiYBR422Image::DiYBR422Image(const DiDocument *docu, + const EI_Status status) + : DiColorImage(docu, status, 2, !(docu->getFlags() & CIF_KeepYCbCrColorModel) /* RGBColorModel */) +{ + if ((Document != NULL) && (InputData != NULL) && (ImageStatus == EIS_Normal)) + { + Init(); // create intermediate representation + } +} + + +/*--------------* + * destructor * + *--------------*/ + +DiYBR422Image::~DiYBR422Image() +{ +} + + +/*********************************************************************/ + + +void DiYBR422Image::Init() +{ + switch (InputData->getRepresentation()) + { + case EPR_Uint8: + InterData = new DiYBR422PixelTemplate(Document, InputData, ImageStatus, BitsPerSample, RGBColorModel); + break; + case EPR_Sint8: + InterData = new DiYBR422PixelTemplate(Document, InputData, ImageStatus, BitsPerSample, RGBColorModel); + break; + case EPR_Uint16: + InterData = new DiYBR422PixelTemplate(Document, InputData, ImageStatus, BitsPerSample, RGBColorModel); + break; + case EPR_Sint16: + InterData = new DiYBR422PixelTemplate(Document, InputData, ImageStatus, BitsPerSample, RGBColorModel); + break; + case EPR_Uint32: + InterData = new DiYBR422PixelTemplate(Document, InputData, ImageStatus, BitsPerSample, RGBColorModel); + break; + case EPR_Sint32: + InterData = new DiYBR422PixelTemplate(Document, InputData, ImageStatus, BitsPerSample, RGBColorModel); + break; + } + deleteInputData(); + checkInterData(); +} + + +/*********************************************************************/ + + +int DiYBR422Image::processNextFrames(const unsigned long fcount) +{ + if (DiImage::processNextFrames(fcount)) + { + delete InterData; + InterData = NULL; + Init(); + return (ImageStatus == EIS_Normal); + } + return 0; +} diff --git a/dcmimage/libsrc/diyp2img.cc b/dcmimage/libsrc/diyp2img.cc new file mode 100644 index 00000000..14437852 --- /dev/null +++ b/dcmimage/libsrc/diyp2img.cc @@ -0,0 +1,101 @@ +/* + * + * Copyright (C) 1996-2010, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimage + * + * Author: Joerg Riesmeier + * + * Purpose: DicomYBRPart422Image (Source) + * + */ + + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/dcmdata/dctypes.h" + +#include "dcmtk/dcmimage/diyp2img.h" +#include "dcmtk/dcmimage/diyp2pxt.h" +#include "dcmtk/dcmimage/dilogger.h" +#include "dcmtk/dcmimgle/diinpx.h" + + +/*----------------* + * constructors * + *----------------*/ + +DiYBRPart422Image::DiYBRPart422Image(const DiDocument *docu, + const EI_Status status) + : DiColorImage(docu, status, 2) +{ + if ((Document != NULL) && (InputData != NULL) && (ImageStatus == EIS_Normal)) + { + Init(); // create intermediate representation + } +} + + +/*--------------* + * destructor * + *--------------*/ + +DiYBRPart422Image::~DiYBRPart422Image() +{ +} + + +/*********************************************************************/ + + +void DiYBRPart422Image::Init() +{ + switch (InputData->getRepresentation()) + { + case EPR_Uint8: + InterData = new DiYBRPart422PixelTemplate(Document, InputData, ImageStatus, BitsPerSample); + break; + case EPR_Sint8: + InterData = new DiYBRPart422PixelTemplate(Document, InputData, ImageStatus, BitsPerSample); + break; + case EPR_Uint16: + InterData = new DiYBRPart422PixelTemplate(Document, InputData, ImageStatus, BitsPerSample); + break; + case EPR_Sint16: + InterData = new DiYBRPart422PixelTemplate(Document, InputData, ImageStatus, BitsPerSample); + break; + case EPR_Uint32: + InterData = new DiYBRPart422PixelTemplate(Document, InputData, ImageStatus, BitsPerSample); + break; + case EPR_Sint32: + InterData = new DiYBRPart422PixelTemplate(Document, InputData, ImageStatus, BitsPerSample); + break; + } + deleteInputData(); + checkInterData(); +} + + +/*********************************************************************/ + + +int DiYBRPart422Image::processNextFrames(const unsigned long fcount) +{ + if (DiImage::processNextFrames(fcount)) + { + delete InterData; + InterData = NULL; + Init(); + return (ImageStatus == EIS_Normal); + } + return 0; +} diff --git a/dcmimage/tests/Makefile.in b/dcmimage/tests/Makefile.in new file mode 100644 index 00000000..44f4a480 --- /dev/null +++ b/dcmimage/tests/Makefile.in @@ -0,0 +1,29 @@ +# +# Makefile for dcmimage/tests +# + +@SET_MAKE@ + +SHELL = /bin/sh +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +configdir = @top_srcdir@/@configdir@ + +include $(configdir)/@common_makefile@ + + +all: + +check: + +check-exhaustive: + +install: + +clean: + rm -f $(TRASH) + +distclean: + rm -f $(DISTTRASH) + +dependencies: diff --git a/dcmimgle/CMakeLists.txt b/dcmimgle/CMakeLists.txt new file mode 100644 index 00000000..a60c171a --- /dev/null +++ b/dcmimgle/CMakeLists.txt @@ -0,0 +1,10 @@ +# declare project +PROJECT(dcmimgle) + +# declare include directories which hold for all subdirectories +INCLUDE_DIRECTORIES(${dcmimgle_SOURCE_DIR}/include ${ofstd_SOURCE_DIR}/include ${oflog_SOURCE_DIR}/include ${dcmdata_SOURCE_DIR}/include ${ZLIB_INCDIR}) + +# recurse into subdirectories +FOREACH(SUBDIR libsrc apps include data) + ADD_SUBDIRECTORY(${SUBDIR}) +ENDFOREACH(SUBDIR) diff --git a/dcmimgle/Makefile.in b/dcmimgle/Makefile.in new file mode 100644 index 00000000..a791ad08 --- /dev/null +++ b/dcmimgle/Makefile.in @@ -0,0 +1,97 @@ +# +# Makefile for dcmimgle +# + +@SET_MAKE@ + +SHELL = /bin/sh +VPATH = @srcdir@:@top_srcdir@/include:@top_srcdir@/@configdir@/include +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +configdir = @top_srcdir@/@configdir@ + +include $(configdir)/@common_makefile@ + + +all: include-all libsrc-all apps-all tests-all + +install: install-bin install-doc install-support + +install-bin: apps-install + +install-doc: docs-install + +install-data: data-install + +install-etc: etc-install + +install-include: include-install + +install-lib: libsrc-install install-include + +install-support: install-data install-etc + + +include-all: + (cd include && $(MAKE) ARCH="$(ARCH)" all) + +libsrc-all: include-all + (cd libsrc && $(MAKE) ARCH="$(ARCH)" all) + +apps-all: libsrc-all + (cd apps && $(MAKE) ARCH="$(ARCH)" all) + +tests-all: libsrc-all + (cd tests && $(MAKE) ARCH="$(ARCH)" all) + + +check: tests-all + (cd tests && $(MAKE) check) + +check-exhaustive: tests-all + (cd tests && $(MAKE) check-exhaustive) + + +include-install: + (cd include && $(MAKE) ARCH="$(ARCH)" install) + +libsrc-install: libsrc-all + (cd libsrc && $(MAKE) ARCH="$(ARCH)" install) + +apps-install: apps-all + (cd apps && $(MAKE) ARCH="$(ARCH)" install) + +docs-install: + (cd docs && $(MAKE) install) + +data-install: + (cd data && $(MAKE) install) + +etc-install: + (cd etc && $(MAKE) install) + + +clean: + (cd include && $(MAKE) clean) + (cd libsrc && $(MAKE) clean) + (cd apps && $(MAKE) clean) + (cd tests && $(MAKE) clean) + (cd docs && $(MAKE) clean) + (cd data && $(MAKE) clean) + (cd etc && $(MAKE) clean) + rm -f $(TRASH) + +distclean: + (cd include && $(MAKE) distclean) + (cd libsrc && $(MAKE) distclean) + (cd apps && $(MAKE) distclean) + (cd tests && $(MAKE) distclean) + (cd docs && $(MAKE) distclean) + (cd data && $(MAKE) distclean) + (cd etc && $(MAKE) distclean) + rm -f $(DISTTRASH) + +dependencies: + (cd libsrc && touch $(DEP) && $(MAKE) dependencies) + (cd apps && touch $(DEP) && $(MAKE) dependencies) +# (cd tests && touch $(DEP) && $(MAKE) dependencies) diff --git a/dcmimgle/apps/CMakeLists.txt b/dcmimgle/apps/CMakeLists.txt new file mode 100644 index 00000000..8dd407c8 --- /dev/null +++ b/dcmimgle/apps/CMakeLists.txt @@ -0,0 +1,9 @@ +# declare executables +FOREACH(PROGRAM dcmdspfn dcod2lum dconvlum) + DCMTK_ADD_EXECUTABLE(${PROGRAM} ${PROGRAM}) +ENDFOREACH(PROGRAM) + +# make sure executables are linked to the corresponding libraries +FOREACH(PROGRAM dcmdspfn dcod2lum dconvlum) + DCMTK_TARGET_LINK_MODULES(${PROGRAM} dcmimgle dcmdata oflog ofstd) +ENDFOREACH(PROGRAM) diff --git a/dcmimgle/apps/Makefile.dep b/dcmimgle/apps/Makefile.dep new file mode 100644 index 00000000..4f3993f1 --- /dev/null +++ b/dcmimgle/apps/Makefile.dep @@ -0,0 +1,145 @@ +dcmdspfn.o: dcmdspfn.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcostrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicent.h \ + ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcmetinf.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicdir.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdirrec.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrulup.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrul.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixseq.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcofsetl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrae.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvras.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrda.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrds.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrdt.h \ + ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvris.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrtm.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrur.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcchrstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlt.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpn.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsh.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrst.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvruc.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrut.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixel.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpobw.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcovlay.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrat.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrss.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrus.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfd.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrof.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrod.h \ + ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ + ../include/dcmtk/dcmimgle/digsdfn.h ../include/dcmtk/dcmimgle/didispfn.h \ + ../include/dcmtk/dcmimgle/didefine.h ../include/dcmtk/dcmimgle/diciefn.h \ + ../include/dcmtk/dcmimgle/dicielut.h \ + ../include/dcmtk/dcmimgle/didislut.h \ + ../include/dcmtk/dcmimgle/dibaslut.h ../include/dcmtk/dcmimgle/diutils.h +dcod2lum.o: dcod2lum.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../include/dcmtk/dcmimgle/didispfn.h \ + ../include/dcmtk/dcmimgle/didefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h +dconvlum.o: dconvlum.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h diff --git a/dcmimgle/apps/Makefile.in b/dcmimgle/apps/Makefile.in new file mode 100644 index 00000000..315fb2f3 --- /dev/null +++ b/dcmimgle/apps/Makefile.in @@ -0,0 +1,56 @@ +# +# Makefile for dcmimgle/apps +# + +@SET_MAKE@ + +SHELL = /bin/sh +VPATH = @srcdir@:@top_srcdir@/include:@top_srcdir@/@configdir@/include +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +configdir = @top_srcdir@/@configdir@ + +include $(configdir)/@common_makefile@ + +ofstddir = $(top_srcdir)/../ofstd +oflogdir = $(top_srcdir)/../oflog +dcmdatadir = $(top_srcdir)/../dcmdata + +LOCALINCLUDES = -I$(ofstddir)/include -I$(oflogdir)/include -I$(dcmdatadir)/include +LIBDIRS = -L$(top_srcdir)/libsrc -L$(ofstddir)/libsrc -L$(oflogdir)/libsrc -L$(dcmdatadir)/libsrc +LOCALLIBS = -ldcmimgle -ldcmdata -loflog -lofstd $(ZLIBLIBS) $(ICONVLIBS) + +objs = dconvlum.o dcmdspfn.o dcod2lum.o +progs = dconvlum dcmdspfn dcod2lum + + +all: $(progs) + +dconvlum: dconvlum.o + $(CXX) $(CXXFLAGS) $(LIBDIRS) $(LDFLAGS) -o $@ $@.o $(LOCALLIBS) $(MATHLIBS) $(LIBS) + +dcmdspfn: dcmdspfn.o + $(CXX) $(CXXFLAGS) $(LIBDIRS) $(LDFLAGS) -o $@ $@.o $(LOCALLIBS) $(MATHLIBS) $(LIBS) + +dcod2lum: dcod2lum.o + $(CXX) $(CXXFLAGS) $(LIBDIRS) $(LDFLAGS) -o $@ $@.o $(LOCALLIBS) $(MATHLIBS) $(LIBS) + + +install: all + $(configdir)/mkinstalldirs $(DESTDIR)$(bindir) + for prog in $(progs); do \ + $(INSTALL_PROGRAM) $$prog$(BINEXT) $(DESTDIR)$(bindir) && $(STRIP) $(DESTDIR)$(bindir)/$$prog$(BINEXT) ;\ + done + + +clean: + rm -f $(objs) $(progs) $(TRASH) + +distclean: + rm -f $(objs) $(progs) $(DISTTRASH) + + +dependencies: + $(CXX) -MM $(defines) $(includes) $(CPPFLAGS) $(CXXFLAGS) *.cc > $(DEP) + +include $(DEP) diff --git a/dcmimgle/apps/dcmdspfn.cc b/dcmimgle/apps/dcmdspfn.cc new file mode 100644 index 00000000..7f3f978a --- /dev/null +++ b/dcmimgle/apps/dcmdspfn.cc @@ -0,0 +1,309 @@ +/* + * + * Copyright (C) 1999-2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimgle + * + * Authors: Joerg Riesmeier + * + * Purpose: export display curves to a text file + * + */ + + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#ifdef HAVE_GUSI_H +#include +#endif + +#include "dcmtk/dcmdata/dctk.h" +#include "dcmtk/dcmdata/cmdlnarg.h" + +#include "dcmtk/ofstd/ofconapp.h" +#include "dcmtk/ofstd/ofcmdln.h" + +#include "dcmtk/dcmimgle/digsdfn.h" +#include "dcmtk/dcmimgle/diciefn.h" + +#define OFFIS_CONSOLE_APPLICATION "dcmdspfn" + +static OFLogger dcmdspfnLogger = OFLog::getLogger("dcmtk.apps." OFFIS_CONSOLE_APPLICATION); + +static char rcsid[] = "$dcmtk: " OFFIS_CONSOLE_APPLICATION " v" + OFFIS_DCMTK_VERSION " " OFFIS_DCMTK_RELEASEDATE " $"; + +#define SHORTCOL 3 +#define LONGCOL 15 + +// ******************************************** + + +int main(int argc, char *argv[]) +{ + OFConsoleApplication app(OFFIS_CONSOLE_APPLICATION, "Export standard display curves to a text file", rcsid); + OFCommandLine cmd; + + const char *opt_ifname = NULL; + const char *opt_ofname = NULL; + int opt_outputMode = 0; + OFCmdUnsignedInt opt_ddlCount = 256; + OFCmdSignedInt opt_polyOrder = -1; + OFCmdFloat opt_ambLight = -1; + OFCmdFloat opt_illum = -1; + OFCmdFloat opt_Dmin = -1; + OFCmdFloat opt_Dmax = -1; + OFCmdFloat opt_minVal = 0; + OFCmdFloat opt_maxVal = 0; + DiDisplayFunction::E_DeviceType deviceType = DiDisplayFunction::EDT_Monitor; + + prepareCmdLineArgs(argc, argv, OFFIS_CONSOLE_APPLICATION); + cmd.setOptionColumns(LONGCOL, SHORTCOL); + + cmd.addGroup("general options:"); + cmd.addOption("--help", "-h", "print this help text and exit", OFCommandLine::AF_Exclusive); + cmd.addOption("--version", "print version information and exit", OFCommandLine::AF_Exclusive); + OFLog::addOptions(cmd); + + cmd.addGroup("input options: (mutually exclusive)"); + cmd.addOption("--monitor-file", "+Im", 1, "[f]ilename: string", + "text file describing the monitor characteristics"); + cmd.addOption("--camera-file", "+Ic", 1, "[f]ilename: string", + "text file describing the camera characteristics"); + cmd.addOption("--printer-file", "+Ip", 1, "[f]ilename: string", + "text file describing the printer characteristics"); + cmd.addOption("--scanner-file", "+Is", 1, "[f]ilename: string", + "text file describing the scanner characteristics"); + cmd.addOption("--lum-range", "+Il", 2, "[m]in max: float", + "minimum and maximum luminance (cd/m^2)"); + cmd.addOption("--od-range", "+Io", 2, "[m]in max: float", + "minimum and maximum optical density (OD),\nautomatically converted to luminance"); + + cmd.addGroup("creation options:"); + cmd.addOption("--ambient-light", "+Ca", 1, "[a]mbient light: float", + "ambient light value (cd/m^2, default: file f)"); + cmd.addOption("--illumination", "+Ci", 1, "[i]llumination: float", + "illumination value (cd/m^2, default: file f)"); + cmd.addOption("--min-density", "+Dn", 1, "[m]inimum optical density: float", + "Dmin value (default: off, only with +Ip and +Io)"); + cmd.addOption("--max-density", "+Dx", 1, "[m]aximum optical density: float", + "Dmax value (default: off, only with +Ip and +Io)"); + cmd.addOption("--ddl-count", "+Cd", 1, "[n]umber of DDLs: integer", + "number of Digital Driving Levels\n(default: 256, only with --lum/od-range)"); + cmd.addOption("--curve-fitting", "+Cf", 1, "[n]umber : integer", + "use polynomial curve fitting algorithm with order n\n(0..99, default: file setting or cubic spline)"); + + cmd.addGroup("output options:"); + cmd.addOption("--gsdf", "+Og", 1, "[f]ilename: string", + "write GSDF curve data to file f"); + cmd.addOption("--cielab", "+Oc", 1, "[f]ilename: string", + "write CIELAB curve data to file f"); + + if (app.parseCommandLine(cmd, argc, argv)) + { + /* print help text and exit */ + if (cmd.getArgCount() == 0) + app.printUsage(); + + /* check exclusive options */ + if (cmd.hasExclusiveOption()) + { + if (cmd.findOption("--version")) + { + app.printHeader(OFTrue /*print host identifier*/); + COUT << OFendl << "External libraries used: none" << OFendl; + return 0; + } + } + + OFLog::configureFromCommandLine(cmd, app); + + if (cmd.findOption("--ambient-light")) + app.checkValue(cmd.getValueAndCheckMin(opt_ambLight, 0)); + if (cmd.findOption("--illumination")) + app.checkValue(cmd.getValueAndCheckMin(opt_illum, 0)); + if (cmd.findOption("--ddl-count")) + { + if (opt_ifname != NULL) + { + app.checkConflict("--ddl-count", "--monitor-file", OFTrue); + app.checkConflict("--ddl-count", "--printer-file", OFTrue); + } else + app.checkValue(cmd.getValueAndCheckMinMax(opt_ddlCount, 2, 65536)); + } + if (cmd.findOption("--curve-fitting")) + app.checkValue(cmd.getValueAndCheckMinMax(opt_polyOrder, 0, 99)); + + cmd.beginOptionBlock(); + if (cmd.findOption("--monitor-file")) + { + app.checkValue(cmd.getValue(opt_ifname)); + deviceType = DiDisplayFunction::EDT_Monitor; + } + if (cmd.findOption("--camera-file")) + { + app.checkValue(cmd.getValue(opt_ifname)); + deviceType = DiDisplayFunction::EDT_Camera; + } + if (cmd.findOption("--printer-file")) + { + app.checkValue(cmd.getValue(opt_ifname)); + deviceType = DiDisplayFunction::EDT_Printer; + } + if (cmd.findOption("--scanner-file")) + { + app.checkValue(cmd.getValue(opt_ifname)); + deviceType = DiDisplayFunction::EDT_Scanner; + } + if (cmd.findOption("--lum-range")) + { + app.checkValue(cmd.getValueAndCheckMin(opt_minVal, 0)); + app.checkValue(cmd.getValueAndCheckMin(opt_maxVal, opt_minVal, OFFalse)); + deviceType = DiDisplayFunction::EDT_Monitor; + } + if (cmd.findOption("--od-range")) + { + app.checkDependence("--od-range", "--illumination", opt_illum >= 0); + OFCmdFloat minVal = 0; + OFCmdFloat maxVal = 0; + app.checkValue(cmd.getValueAndCheckMin(minVal, 0)); + app.checkValue(cmd.getValueAndCheckMin(maxVal, minVal, OFFalse)); + deviceType = DiDisplayFunction::EDT_Printer; + /* convert given optical density to luminance */ + opt_minVal = DiDisplayFunction::convertODtoLum(maxVal, 0 /*ambLight*/, opt_illum); + opt_maxVal = DiDisplayFunction::convertODtoLum(minVal, 0 /*ambLight*/, opt_illum); + } + cmd.endOptionBlock(); + + if (cmd.findOption("--min-density")) + { + app.checkDependence("--min-density", "--printer-file or --od-range", deviceType == DiDisplayFunction::EDT_Printer); + app.checkValue(cmd.getValueAndCheckMin(opt_Dmin, 0)); + } + if (cmd.findOption("--max-density")) + { + app.checkDependence("--max-density", "--printer-file or --od-range", deviceType == DiDisplayFunction::EDT_Printer); + app.checkValue(cmd.getValueAndCheckMin(opt_Dmax, (opt_Dmin < 0) ? 0.0 : opt_Dmin, OFFalse /*incl*/)); + } + + if (cmd.findOption("--gsdf")) + ++opt_outputMode; + if (cmd.findOption("--cielab")) + ++opt_outputMode; + } + + /* print resource identifier */ + OFLOG_DEBUG(dcmdspfnLogger, rcsid << OFendl); + + if (opt_outputMode > 0) + { + if (opt_ifname != NULL) + OFLOG_INFO(dcmdspfnLogger, "reading LUT file: " << opt_ifname); + + /* Grayscale Standard Display Function */ + if (cmd.findOption("--gsdf")) + { + OFLOG_INFO(dcmdspfnLogger, "creating GSDF display curve ..."); + app.checkValue(cmd.getValue(opt_ofname)); + DiGSDFunction *disp = NULL; + if (opt_ifname != NULL) + disp = new DiGSDFunction(opt_ifname, deviceType, OFstatic_cast(signed int, opt_polyOrder)); + else + disp = new DiGSDFunction(opt_minVal, opt_maxVal, opt_ddlCount, DiDisplayFunction::EDT_Monitor, + OFstatic_cast(signed int, opt_polyOrder)); + if ((disp != NULL) && disp->isValid()) + { + if (opt_ambLight >= 0) + { + OFLOG_INFO(dcmdspfnLogger, "setting ambient light value ..."); + disp->setAmbientLightValue(opt_ambLight); + } + if (opt_illum >= 0) + { + OFLOG_INFO(dcmdspfnLogger, "setting illumination value ..."); + disp->setIlluminationValue(opt_illum); + } + /* Dmin/max only supported for printers */ + if (disp->getDeviceType() == DiDisplayFunction::EDT_Printer) + { + if (opt_Dmin >= 0) + { + OFLOG_INFO(dcmdspfnLogger, "setting minimum optical density value ..."); + disp->setMinDensityValue(opt_Dmin); + } + if (opt_Dmax >= 0) + { + OFLOG_INFO(dcmdspfnLogger, "setting maximum optical density value ..."); + disp->setMaxDensityValue(opt_Dmax); + } + } + OFLOG_INFO(dcmdspfnLogger, "writing output file: " << opt_ofname); + if (!disp->writeCurveData(opt_ofname, opt_ifname != NULL)) + { + OFLOG_FATAL(dcmdspfnLogger, "can't write output file"); + return 1; + } + } else { + OFLOG_FATAL(dcmdspfnLogger, "can't create display curve"); + return 1; + } + delete disp; + } + + /* CIELAB display function */ + if (cmd.findOption("--cielab")) + { + OFLOG_INFO(dcmdspfnLogger, "creating CIELAB display curve ..."); + app.checkValue(cmd.getValue(opt_ofname)); + DiCIELABFunction *disp = NULL; + if (opt_ifname != NULL) + disp = new DiCIELABFunction(opt_ifname, deviceType, OFstatic_cast(signed int, opt_polyOrder)); + else + disp = new DiCIELABFunction(opt_minVal, opt_maxVal, opt_ddlCount, DiDisplayFunction::EDT_Monitor, + OFstatic_cast(signed int, opt_polyOrder)); + if ((disp != NULL) && disp->isValid()) + { + if (opt_ambLight >= 0) + { + OFLOG_INFO(dcmdspfnLogger, "setting ambient light value ..."); + disp->setAmbientLightValue(opt_ambLight); + } + /* Dmin/max only supported for printers */ + if (disp->getDeviceType() == DiDisplayFunction::EDT_Printer) + { + if (opt_Dmin >= 0) + { + OFLOG_INFO(dcmdspfnLogger, "setting minimum optical density value ..."); + disp->setMinDensityValue(opt_Dmin); + } + if (opt_Dmax >= 0) + { + OFLOG_INFO(dcmdspfnLogger, "setting maximum optical density value ..."); + disp->setMaxDensityValue(opt_Dmax); + } + } + OFLOG_INFO(dcmdspfnLogger, "writing output file: " << opt_ofname); + if (!disp->writeCurveData(opt_ofname, opt_ifname != NULL)) + { + OFLOG_FATAL(dcmdspfnLogger, "can't write output file"); + return 1; + } + } else { + OFLOG_FATAL(dcmdspfnLogger, "can't create display curve"); + return 1; + } + } + } else { + OFLOG_WARN(dcmdspfnLogger, "nothing to do, no output file specified"); + } + return 0; +} diff --git a/dcmimgle/apps/dcod2lum.cc b/dcmimgle/apps/dcod2lum.cc new file mode 100644 index 00000000..2b438e37 --- /dev/null +++ b/dcmimgle/apps/dcod2lum.cc @@ -0,0 +1,175 @@ +/* + * + * Copyright (C) 2002-2010, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimgle + * + * Authors: Joerg Riesmeier + * + * Purpose: convert hardcopy characteristic curve file to softcopy format + * + */ + + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#define INCLUDE_CSTDLIB +#define INCLUDE_CCTYPE +#define INCLUDE_CSTRING +#include "dcmtk/ofstd/ofstdinc.h" + +#include "dcmtk/ofstd/ofstream.h" +#include "dcmtk/ofstd/ofconsol.h" +#include "dcmtk/dcmimgle/didispfn.h" +#include "dcmtk/dcmdata/dcuid.h" /* for dcmtk version name */ + + +#define OFFIS_CONSOLE_APPLICATION "dcod2lum" + +static char rcsid[] = "$dcmtk: " OFFIS_CONSOLE_APPLICATION " v" + OFFIS_DCMTK_VERSION " " OFFIS_DCMTK_RELEASEDATE " $"; + + +int main(int argc, char *argv[]) +{ + int error = 0; + /* check number of arguments */ + if (argc == 3) + { +#ifdef HAVE_IOS_NOCREATE + STD_NAMESPACE ifstream input(argv[1], STD_NAMESPACE ios::in | STD_NAMESPACE ios::nocreate); +#else + STD_NAMESPACE ifstream input(argv[1], STD_NAMESPACE ios::in); +#endif + if (input) + { + STD_NAMESPACE ofstream output(argv[2]); + if (output) + { + char c; + int i = 0; + int maxddl = 0; + int order = -1; + double amb = 0; + double lum = 0; + output << "# Softcopy characteristic curve file (converted from hardcopy format)" << OFendl; + while (input.get(c) && !error) + { + if (c == '#') // comment character + { + while (input.get(c) && (c != '\n') && (c != '\r')); // skip comments + } + else if (!isspace(OFstatic_cast(unsigned char, c))) // skip whitespaces + { + input.putback(c); + if (maxddl == 0) // read maxvalue + { + char str[4]; + input.get(str, sizeof(str)); + if (strcmp(str, "max") == 0) // check for key word: max + { + input >> maxddl; + if (maxddl > 0) + { + output << OFendl << "# maximum DDL value" << OFendl; + output << "max " << maxddl << OFendl; + } else + error = 1; + } else + error = 1; + } + else if ((amb <= 0) && (c == 'a')) // read ambient light value (optional) + { + char str[4]; + input.get(str, sizeof(str)); + if (strcmp(str, "amb") == 0) // check for key word: amb + { + input >> amb; + if (amb >= 0) + { + output << OFendl << "# reflected ambient light (already included)" << OFendl; + output << "# amb " << amb << OFendl; + } else + error = 1; + } else + error = 1; + } + else if ((lum <= 0) && (c == 'l')) // read illumination value (optional) + { + char str[4]; + input.get(str, sizeof(str)); + if (strcmp(str, "lum") == 0) // check for key word: lum + { + input >> lum; + if (lum >= 0) + { + output << OFendl << "# illumination (already included)" << OFendl; + output << "# lum " << lum << OFendl; + } else + error = 1; + } else + error = 1; + } + else if ((order < 0) && (c == 'o')) // read polynomial order (optional) + { + char str[4]; + input.get(str, sizeof(str)); + if (strcmp(str, "ord") == 0) // check for key word: ord + { + input >> order; + if (order >= 0) + { + output << OFendl << "# order of the polynomial curve fitting algorithm (optional)" << OFendl; + output << "ord " << order << OFendl; + } else + error = 1; + } else + error = 1; + } else { + int ddlval; + double odval; + input >> ddlval; // read DDL value + input >> odval; // read OD value + if (input.good() && (ddlval <= maxddl)) + { + if (i == 0) + output << OFendl << "# DDL LumVal" << OFendl; + output << ddlval << "\t"; + output.setf(STD_NAMESPACE ios::fixed, STD_NAMESPACE ios::floatfield); + output << DiDisplayFunction::convertODtoLum(odval, amb, lum) << OFendl; + ++i; + } else + error = 1; + } + } + } + if (error) + { + output << OFendl << "# error: corrupted input file" << OFendl; + CERR << "ERROR: corrupted input file !" << OFendl; + } else + output << OFendl << "# end of file" << OFendl; + } else + CERR << "ERROR: can't create output file !" << OFendl; + } else + CERR << "ERROR: can't open input file !" << OFendl; + } else { + /* print usage */ + CERR << rcsid << OFendl << OFendl; + CERR << OFFIS_CONSOLE_APPLICATION << ": Convert hardcopy characteristic curve file to softcopy format" << OFendl; + CERR << "usage: " << OFFIS_CONSOLE_APPLICATION << " in-file out-file" << OFendl << OFendl; + CERR << "parameters:" << OFendl; + CERR << " in-file hardcopy characteristic curve file to be converted" << OFendl; + CERR << " out-file softcopy characteristic curve file to be written" << OFendl; + } + return error; +} diff --git a/dcmimgle/apps/dconvlum.cc b/dcmimgle/apps/dconvlum.cc new file mode 100644 index 00000000..d0954c73 --- /dev/null +++ b/dcmimgle/apps/dconvlum.cc @@ -0,0 +1,110 @@ +/* + * + * Copyright (C) 1999-2010, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimgle + * + * Authors: Joerg Riesmeier + * + * Purpose: convert VeriLUM CCx_xx.dat files to DCMTK display files + * + */ + + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#define INCLUDE_CSTDLIB +#define INCLUDE_CCTYPE +#include "dcmtk/ofstd/ofstdinc.h" + +#include "dcmtk/ofstd/ofstream.h" +#include "dcmtk/ofstd/ofstd.h" +#include "dcmtk/ofstd/ofconsol.h" +#include "dcmtk/dcmdata/dcuid.h" /* for dcmtk version name */ + + +#define OFFIS_CONSOLE_APPLICATION "dconvlum" + +static char rcsid[] = "$dcmtk: " OFFIS_CONSOLE_APPLICATION " v" + OFFIS_DCMTK_VERSION " " OFFIS_DCMTK_RELEASEDATE " $"; + + +int main(int argc, char *argv[]) +{ + /* check number of arguments */ + if ((argc >= 3) && (argc <= 4)) + { +#ifdef HAVE_IOS_NOCREATE + STD_NAMESPACE ifstream input(argv[1], STD_NAMESPACE ios::in | STD_NAMESPACE ios::nocreate); +#else + STD_NAMESPACE ifstream input(argv[1], STD_NAMESPACE ios::in); +#endif + if (input) + { + STD_NAMESPACE ofstream output(argv[2]); + if (output) + { + const unsigned int maxddl = 255; // maximum DDL value (8 bits) + output << "# Monitor characteristic file (converted from VeriLUM to DCMTK)" << OFendl << "# "; + char c; + while (input.get(c) && (c != '\n') && (c != '\r')) // read description + output << c; // ... and write it to output file + output << OFendl << OFendl; + output << "# maximum DDL value" << OFendl << OFendl; + output << " max " << maxddl << OFendl << OFendl; + if (argc == 4) + { + double ambient = OFStandard::atof(argv[3]); + output << "# ambient light value" << OFendl << OFendl; + output << " amb " << ambient << OFendl << OFendl; + } + output << "# DDL LumVal" << OFendl << OFendl; + double lum; + unsigned int ddl; + unsigned int i = 0; + while ((i <= maxddl) && input.good() && output.good()) + { + while (input.get(c) && !isdigit(OFstatic_cast(unsigned char, c))); // skip non-numeric chars + input.putback(c); + input >> ddl; // read DDL value + while (input.get(c) && !isdigit(OFstatic_cast(unsigned char, c))); // skip non-numeric chars + input.putback(c); + input >> lum; // read luminance value + output.width(5); + output << ddl; // write DDL value + output.width(12); + output.setf(STD_NAMESPACE ios::fixed, STD_NAMESPACE ios::floatfield); + output << lum << OFendl; // write luminance value + ++i; + } + if (i <= maxddl) + CERR << "ERROR: can't convert input file ... error in line #" << i << OFendl; + else { + output << OFendl << "# eof of file"; + return 0; // everything is OK + } + } else + CERR << "ERROR: can't create output file" << OFendl; + } else + CERR << "ERROR: can't open input file" << OFendl; + } else { + /* print usage */ + CERR << rcsid << OFendl << OFendl; + CERR << OFFIS_CONSOLE_APPLICATION << ": Convert VeriLUM \"CCx_xx.dat\" files to DCMTK display files" << OFendl; + CERR << "usage: " << OFFIS_CONSOLE_APPLICATION << " in-file out-file [ambient]" << OFendl << OFendl; + CERR << "parameters:" << OFendl; + CERR << " in-file VeriLUM characteristic curve file to be converted" << OFendl; + CERR << " out-file DCMTK display file to be written" << OFendl; + CERR << " ambient ambient light (cd/m^2, floating point value)" << OFendl; + } + return 1; // an error has happened +} diff --git a/dcmimgle/configure b/dcmimgle/configure new file mode 100755 index 00000000..396668ee --- /dev/null +++ b/dcmimgle/configure @@ -0,0 +1,56 @@ +#! /bin/sh + +parentdir=`pwd` +thisdir=$parentdir + +# The following test constructs relative path from the module +# directory to the configuration directory. If you know this path +# you can substitute this with +# configdir= +# It is very important that the configdir path is relative. + +configdir="configdir" + +while test "$parentdir" != "/" -a "$configdir" = "configdir"; do + if test -d "$parentdir/config" ; then + configdir=$parentdir/config + else + parentdir=`echo $parentdir | sed 's/\/[^\/]*$//'` + fi +done + +if test "$configdir" = "configdir" ; then + echo "Cannot find configure directory" + exit 1 +fi + +if test $# != 0; then + case $1 in + -a) + shift + cd "$configdir" + echo "running configure in config-directory" + ./configure $* + cd $thisdir + echo "running configure for this module" + sh "$configdir/confmod" --srcdir=. $* + ;; + -c) + shift + cd "$configdir" + echo "running configure in config-directory" + ./configure $* + ;; + *) + echo "running configure for this module" + sh "$configdir/confmod" --srcdir=. $* + ;; + esac +else + echo "running configure for this module" + sh "$configdir/confmod" --srcdir=. $* +fi + + + + diff --git a/dcmimgle/data/CMakeLists.txt b/dcmimgle/data/CMakeLists.txt new file mode 100644 index 00000000..c08733ee --- /dev/null +++ b/dcmimgle/data/CMakeLists.txt @@ -0,0 +1,2 @@ +# declare installation files +INSTALL(FILES camera.lut monitor.lut printer.lut scanner.lut DESTINATION ${DCMTK_INSTALL_DATDIR} COMPONENT data) diff --git a/dcmimgle/data/Makefile.in b/dcmimgle/data/Makefile.in new file mode 100644 index 00000000..88f91a2f --- /dev/null +++ b/dcmimgle/data/Makefile.in @@ -0,0 +1,29 @@ +# +# Makefile for dcmimgle/data +# + +@SET_MAKE@ + +SHELL = /bin/sh +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +configdir = @top_srcdir@/@configdir@ + +include $(configdir)/@common_makefile@ + +files = camera.lut monitor.lut printer.lut scanner.lut + + +all: + +install: + $(configdir)/mkinstalldirs $(DESTDIR)$(datadir) + for file in $(files); do \ + $(INSTALL_DATA) $$file $(DESTDIR)$(datadir) ;\ + done + +clean: + rm -f $(TRASH) + +distclean: + rm -f $(DISTTRASH) diff --git a/dcmimgle/data/camera.lut b/dcmimgle/data/camera.lut new file mode 100644 index 00000000..2cfb8bfe --- /dev/null +++ b/dcmimgle/data/camera.lut @@ -0,0 +1,26 @@ +# Camera characteristic file + +# maximum DDL value + + max 4095 + +# DDL LumVal + + 0 11.588656 + 16 16.934737 + 32 23.521660 + 48 32.963072 + 96 46.394017 + 145 61.407916 + 241 82.615611 + 353 110.237447 + 514 151.589157 + 723 200.998517 + 996 261.785082 + 1461 357.560166 + 2023 489.766584 + 2794 657.187314 + 3758 863.159038 + 4095 1160.879875 + +# end of file diff --git a/dcmimgle/data/monitor.lut b/dcmimgle/data/monitor.lut new file mode 100644 index 00000000..1c229894 --- /dev/null +++ b/dcmimgle/data/monitor.lut @@ -0,0 +1,270 @@ +# Monitor characteristic file + +# maximum DDL value + + max 255 + +# ambient light (optional) + + amb 1.0 + +# DDL LumVal + + 0 0.186260 + 1 0.199540 + 2 0.213000 + 3 0.226850 + 4 0.241260 + 5 0.256440 + 6 0.272560 + 7 0.289820 + 8 0.308410 + 9 0.328520 + 10 0.350340 + 11 0.374050 + 12 0.399850 + 13 0.427930 + 14 0.458480 + 15 0.491690 + 16 0.527740 + 17 0.566800 + 18 0.608900 + 19 0.654050 + 20 0.702250 + 21 0.753510 + 22 0.807840 + 23 0.865250 + 24 0.925730 + 25 0.989300 + 26 1.055950 + 27 1.125710 + 28 1.198560 + 29 1.274530 + 30 1.353610 + 31 1.435800 + 32 1.521130 + 33 1.609590 + 34 1.701190 + 35 1.795960 + 36 1.893890 + 37 1.995020 + 38 2.099340 + 39 2.206880 + 40 2.317650 + 41 2.431660 + 42 2.548930 + 43 2.669460 + 44 2.793280 + 45 2.920390 + 46 3.050810 + 47 3.184560 + 48 3.321650 + 49 3.462090 + 50 3.605910 + 51 3.753140 + 52 3.903820 + 53 4.057970 + 54 4.215620 + 55 4.376800 + 56 4.541540 + 57 4.709880 + 58 4.881840 + 59 5.057460 + 60 5.236750 + 61 5.419770 + 62 5.606520 + 63 5.797050 + 64 5.991380 + 65 6.189550 + 66 6.391550 + 67 6.597390 + 68 6.807060 + 69 7.020590 + 70 7.237950 + 71 7.459160 + 72 7.684220 + 73 7.913130 + 74 8.145890 + 75 8.382510 + 76 8.622980 + 77 8.867310 + 78 9.115500 + 79 9.367550 + 80 9.623470 + 81 9.883250 + 82 10.146910 + 83 10.414440 + 84 10.685870 + 85 10.961190 + 86 11.240410 + 87 11.523550 + 88 11.810600 + 89 12.101570 + 90 12.396480 + 91 12.695330 + 92 12.998130 + 93 13.304880 + 94 13.615600 + 95 13.930280 + 96 14.248940 + 97 14.571590 + 98 14.898230 + 99 15.228890 + 100 15.563570 + 101 15.902290 + 102 16.245070 + 103 16.591910 + 104 16.942840 + 105 17.297860 + 106 17.656990 + 107 18.020250 + 108 18.387640 + 109 18.759180 + 110 19.134890 + 111 19.514770 + 112 19.898850 + 113 20.287130 + 114 20.679590 + 115 21.076230 + 116 21.477030 + 117 21.881960 + 118 22.291010 + 119 22.704160 + 120 23.121390 + 121 23.542700 + 122 23.968050 + 123 24.397430 + 124 24.830830 + 125 25.268230 + 126 25.709610 + 127 26.154950 + 128 26.604230 + 129 27.057450 + 130 27.514600 + 131 27.975710 + 132 28.440770 + 133 28.909800 + 134 29.382810 + 135 29.859810 + 136 30.340810 + 137 30.825820 + 138 31.314850 + 139 31.807910 + 140 32.305020 + 141 32.806170 + 142 33.311390 + 143 33.820680 + 144 34.334050 + 145 34.851510 + 146 35.373040 + 147 35.898610 + 148 36.428200 + 149 36.961790 + 150 37.499360 + 151 38.040870 + 152 38.586320 + 153 39.135660 + 154 39.688880 + 155 40.245950 + 156 40.806860 + 157 41.371570 + 158 41.940060 + 159 42.512310 + 160 43.088300 + 161 43.668010 + 162 44.251470 + 163 44.838720 + 164 45.429800 + 165 46.024740 + 166 46.623600 + 167 47.226410 + 168 47.833210 + 169 48.444030 + 170 49.058920 + 171 49.677930 + 172 50.301070 + 173 50.928410 + 174 51.559970 + 175 52.195800 + 176 52.835940 + 177 53.480410 + 178 54.129180 + 179 54.782210 + 180 55.439460 + 181 56.100870 + 182 56.766410 + 183 57.436030 + 184 58.109700 + 185 58.787350 + 186 59.468950 + 187 60.154460 + 188 60.843840 + 189 61.537030 + 190 62.233990 + 191 62.934680 + 192 63.639060 + 193 64.347100 + 194 65.058820 + 195 65.774270 + 196 66.493510 + 197 67.216560 + 198 67.943490 + 199 68.674330 + 200 69.409130 + 201 70.147940 + 202 70.890790 + 203 71.637750 + 204 72.388850 + 205 73.144130 + 206 73.903650 + 207 74.667450 + 208 75.435570 + 209 76.208050 + 210 76.984850 + 211 77.765920 + 212 78.551230 + 213 79.340710 + 214 80.134330 + 215 80.932040 + 216 81.733790 + 217 82.539530 + 218 83.349220 + 219 84.162800 + 220 84.980240 + 221 85.801480 + 222 86.626480 + 223 87.455180 + 224 88.287560 + 225 89.123560 + 226 89.963230 + 227 90.806620 + 228 91.653780 + 229 92.504770 + 230 93.359640 + 231 94.218430 + 232 95.081200 + 233 95.948010 + 234 96.818900 + 235 97.693920 + 236 98.573140 + 237 99.456590 + 238 100.344340 + 239 101.236440 + 240 102.132930 + 241 103.033820 + 242 103.938850 + 243 104.847740 + 244 105.760200 + 245 106.675910 + 246 107.594590 + 247 108.515940 + 248 109.439670 + 249 110.365470 + 250 111.293050 + 251 112.222110 + 252 113.152360 + 253 114.083500 + 254 115.015230 + 255 115.947260 + +# eof of file \ No newline at end of file diff --git a/dcmimgle/data/printer.lut b/dcmimgle/data/printer.lut new file mode 100644 index 00000000..d6b226f5 --- /dev/null +++ b/dcmimgle/data/printer.lut @@ -0,0 +1,38 @@ +# Printer characteristic file + +# maximum DDL value + + max 255 + +# illumination (optional) + + lum 2000 + +# reflected ambient light (optional) + + amb 10 + +# order of the polynomial curve fitting algorithm (optional) + + ord 5 + +# DDL OD Val + + 0 3.00 + 16 2.40 + 33 2.09 + 51 1.86 + 67 1.68 + 84 1.52 + 102 1.37 + 119 1.24 + 135 1.10 + 153 0.97 + 170 0.85 + 187 0.72 + 204 0.59 + 221 0.46 + 238 0.33 + 255 0.19 + +# eof of file \ No newline at end of file diff --git a/dcmimgle/data/scanner.lut b/dcmimgle/data/scanner.lut new file mode 100644 index 00000000..25b68a4e --- /dev/null +++ b/dcmimgle/data/scanner.lut @@ -0,0 +1,34 @@ +# Scanner characteristic file + +# maximum DDL value + + max 4095 + +# illumination (optional) + + lum 2000 + +# reflected ambient light (optional) + + amb 10 + +# DDL OD Val + + 0 3.10 + 16 2.46 + 32 2.17 + 48 1.94 + 96 1.74 + 145 1.59 + 241 1.44 + 353 1.30 + 514 1.15 + 723 1.02 + 996 0.90 + 1461 0.76 + 2023 0.62 + 2794 0.49 + 3758 0.37 + 4095 0.24 + +# eof of file \ No newline at end of file diff --git a/dcmimgle/docs/Makefile.in b/dcmimgle/docs/Makefile.in new file mode 100644 index 00000000..c1decf2f --- /dev/null +++ b/dcmimgle/docs/Makefile.in @@ -0,0 +1,23 @@ +# +# Makefile for dcmimgle/docs +# + +@SET_MAKE@ + +SHELL = /bin/sh +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +configdir = @top_srcdir@/@configdir@ + +include $(configdir)/@common_makefile@ + + +all: + +install: + +clean: + rm -f $(TRASH) + +distclean: + rm -f $(DISTTRASH) diff --git a/dcmimgle/docs/dcmdspfn.man b/dcmimgle/docs/dcmdspfn.man new file mode 100644 index 00000000..a1d91af8 --- /dev/null +++ b/dcmimgle/docs/dcmdspfn.man @@ -0,0 +1,201 @@ +/*! + +\if MANPAGES +\page dcmdspfn Export standard display curves to a text file +\else +\page dcmdspfn dcmdspfn: Export standard display curves to a text file +\endif + +\section synopsis SYNOPSIS + +\verbatim +dcmdspfn [options] +\endverbatim + +\section description DESCRIPTION + +Command line program converts a DCMTK monitor / camera / printer / scanner +characteristics file to tabbed text file describing the characteristic curve +(CC), the display function and the post-standardized curve (PSC) for an 8 bit +display. The 256 values of each curve can be visualized by a common spread +sheet program. Above that the display curve (without CC and PSC) can also be +computed for a specified luminance/OD range (min/max) and a certain number of +Digital Driving Levels (DDL). + +\section parameters PARAMETERS + +\verbatim +dcmfile-in DICOM input filename to be dumped +\endverbatim + +\section options OPTIONS + +\subsection general_options general options +\verbatim + -h --help + print this help text and exit + + --version + print version information and exit + + --arguments + print expanded command line arguments + + -q --quiet + quiet mode, print no warnings and errors + + -v --verbose + verbose mode, print processing details + + -d --debug + debug mode, print debug information + + -ll --log-level [l]evel: string constant + (fatal, error, warn, info, debug, trace) + use level l for the logger + + -lc --log-config [f]ilename: string + use config file f for the logger +\endverbatim + +\subsection input_options input options (mutually exclusive) +\verbatim + +Im --monitor-file [f]ilename: string + text file describing the monitor characteristics + + +Ic --camera-file [f]ilename: string + text file describing the camera characteristics + + +Ip --printer-file [f]ilename: string + text file describing the printer characteristics + + +Is --scanner-file [f]ilename: string + text file describing the scanner characteristics + + +Il --lum-range [m]in max: float + minimum and maximum luminance (cd/m^2) + + +Io --od-range [m]in max: float + minimum and maximum optical density (OD), + automatically converted to luminance +\endverbatim + +\subsection creation_options creation options +\verbatim + +Ca --ambient-light [a]mbient light: float + ambient light value (cd/m^2, default: file f) + + +Ci --illumination [i]llumination: float + illumination value (cd/m^2, default: file f) + + +Dn --min-density [m]inimum optical density: float + Dmin value (default: off, only with +Ip and +Io) + + +Dx --max-density [m]aximum optical density: float + Dmax value (default: off, only with +Ip and +Io) + + +Cd --ddl-count [n]umber of DDLs: integer + number of Digital Driving Levels + (default: 256, only with --lum/od-range) + + +Cf --curve-fitting [n]umber: integer + use polynomial curve fitting algorithm with order n + (0..99, default: file setting or cubic spline) +\endverbatim + +\subsection output_options output options +\verbatim + +Og --gsdf [f]ilename: string + write GSDF curve data to file f + + +Oc --cielab [f]ilename: string + write CIELAB curve data to file f +\endverbatim + +\section notes NOTES + +The output file describing the CC, GSDF or CIELAB and PSC for an 8 bit display +system (monitor, camera, printer or scanner) is a simple text file. Lines +starting with a '#' are treated as comments and, therefore, skipped as well as +blank lines. An input file can for instance be created by the command line +tool \b dconvlum. + +The ambient light value possibly defined in the characteristics file is also +used for the calculation. In this case the value is part of the file comment +header as well as the number of DDL (digital driving level) values, the +absolute luminance range (measured in candela per square meter) and the range +of the JND index (just noticeable difference) in case of GSDF. Alternatively, +the ambient light value can be specified as a command line option. When +setting the two luminance values instead of reading a monitor characteristic +file as input the luminance range is linearly divided by the number of DDLs. + +For printers and scanners the illumination can be specified in addition to the +reflected ambient light (both in the characteristics file and on the command +line). The header of the output file includes the minimum and maximum Optical +Density (OD) instead of the luminance range. Please note that the OD values +in the input file have to be ordered in descending order (in contrast to the +luminance values used for monitors and cameras). The DDL value 0 always means +black (darkest value) and the maximum DDL value means white (brightest value, +clear film). + +The \e data folder contains sample characteristics file for monitors, +cameras, printers and scanners. See DICOM standard part 14 for more details +on display calibration and Barten's model (including GSDF). + +\section logging LOGGING + +The level of logging output of the various command line tools and underlying +libraries can be specified by the user. By default, only errors and warnings +are written to the standard error stream. Using option \e --verbose also +informational messages like processing details are reported. Option +\e --debug can be used to get more details on the internal activity, e.g. for +debugging purposes. Other logging levels can be selected using option +\e --log-level. In \e --quiet mode only fatal errors are reported. In such +very severe error events, the application will usually terminate. For more +details on the different logging levels, see documentation of module "oflog". + +In case the logging output should be written to file (optionally with logfile +rotation), to syslog (Unix) or the event log (Windows) option \e --log-config +can be used. This configuration file also allows for directing only certain +messages to a particular output stream and for filtering certain messages +based on the module or application where they are generated. An example +configuration file is provided in \/logger.cfg. + +\section command_line COMMAND LINE + +All command line tools use the following notation for parameters: square +brackets enclose optional values (0-1), three trailing dots indicate that +multiple values are allowed (1-n), a combination of both means 0 to n values. + +Command line options are distinguished from parameters by a leading '+' or '-' +sign, respectively. Usually, order and position of command line options are +arbitrary (i.e. they can appear anywhere). However, if options are mutually +exclusive the rightmost appearance is used. This behavior conforms to the +standard evaluation rules of common Unix shells. + +In addition, one or more command files can be specified using an '@' sign as a +prefix to the filename (e.g. \@command.txt). Such a command argument +is replaced by the content of the corresponding text file (multiple +whitespaces are treated as a single separator unless they appear between two +quotation marks) prior to any further evaluation. Please note that a command +file cannot contain another command file. This simple but effective approach +allows one to summarize common combinations of options/parameters and avoids +longish and confusing command lines (an example is provided in file +\/dumppat.txt). + +\section files FILES + +\/camera.lut - sample characteristics file of a camera +\n\/monitor.lut - sample characteristics file of a monitor +\n\/printer.lut - sample characteristics file of a printer +\n\/scanner.lut - sample characteristics file of a scanner + +\section see_also SEE ALSO + +dconvlum(1), dcod2lum(1) + +\section copyright COPYRIGHT + +Copyright (C) 1999-2014 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany. + +*/ diff --git a/dcmimgle/docs/dcmimgle.dox b/dcmimgle/docs/dcmimgle.dox new file mode 100644 index 00000000..3ad39e14 --- /dev/null +++ b/dcmimgle/docs/dcmimgle.dox @@ -0,0 +1,48 @@ +/*! + +\page mod_dcmimgle dcmimgle: an image processing library and utility apps + +This module contains classes to access and render DICOM monochrome images. +Support for color images is provided by the module +\ref mod_dcmimage "dcmimage". Support for JPEG compressed images is provided +by the module \ref mod_dcmjpeg "dcmjpeg". + +The main interface classes are: +\li \b DicomImage +\li \b DiDisplayFunction + +\section Tools + +This module contains the following command line tools: +\li \ref dcmdspfn +\li \ref dcod2lum +\li \ref dconvlum + +\section Examples + +The following example shows how to load a DICOM single-frame monochrome image +and render its pixel data: + +\code +DicomImage *image = new DicomImage("test.dcm"); +if (image != NULL) +{ + if (image->getStatus() == EIS_Normal) + { + if (image->isMonochrome()) + { + image->setMinMaxWindow(); + Uint8 *pixelData = (Uint8 *)(image->getOutputData(8 /* bits */)); + if (pixelData != NULL) + { + /* do something useful with the pixel data */ + } + } + } else + cerr << "Error: cannot load DICOM image (" << DicomImage::getString(image->getStatus()) << ")" << endl; +} +delete image; +\endcode + + +*/ diff --git a/dcmimgle/docs/dcod2lum.man b/dcmimgle/docs/dcod2lum.man new file mode 100644 index 00000000..e86f21af --- /dev/null +++ b/dcmimgle/docs/dcod2lum.man @@ -0,0 +1,61 @@ +/*! + +\if MANPAGES +\page dcod2lum Convert hardcopy characteristic curve file to softcopy format +\else +\page dcod2lum dcod2lum: Convert hardcopy characteristic curve file to softcopy format +\endif + +\section synopsis SYNOPSIS + +\verbatim +dcod2lum in-file out-file +\endverbatim + +\section description DESCRIPTION + +Command line program that converts a hardcopy characteristic curve file to +softcopy format. In other words, the measured optical density (OD) values +from the input file are transformed to the luminance space according to the +formula: + +\verbatim + L = La + L0 * 10^(-D) +\endverbatim + +where \e L is the resulting luminance, \e La is the reflected ambient light +and \e L0 the illumination (both measured in cd/m^2), 'D' the optical density +(OD). Please note that if no illumination value is specified in the input +file (keyword \e lum) all optical density values are mapped to a constant +luminance. + +\section parameters PARAMETERS + +\verbatim +in-file hardcopy characteristic curve file to be converted + +out-file softcopy characteristic curve file to be written +\endverbatim + +\section notes NOTES + +The format of both input and output file is described the documentation of the +\b dcmdspfn command line tool. In addition, the \e data folder contains +sample characteristics file monitors, cameras, printers and scanners. + +\section files FILES + +\/camera.lut - sample characteristics file of a camera +\n\/monitor.lut - sample characteristics file of a monitor +\n\/printer.lut - sample characteristics file of a printer +\n\/scanner.lut - sample characteristics file of a scanner + +\section see_also SEE ALSO + +dcmdspfn(1) + +\section copyright COPYRIGHT + +Copyright (C) 2002-2014 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany. + +*/ diff --git a/dcmimgle/docs/dconvlum.man b/dcmimgle/docs/dconvlum.man new file mode 100644 index 00000000..60b752aa --- /dev/null +++ b/dcmimgle/docs/dconvlum.man @@ -0,0 +1,59 @@ +/*! + +\if MANPAGES +\page dconvlum Convert VeriLUM files to DCMTK display files +\else +\page dconvlum dconvlum: Convert VeriLUM files to DCMTK display files +\endif + +\section synopsis SYNOPSIS + +\verbatim +dconvlum in-file out-file [ambient] +\endverbatim + +\section description DESCRIPTION + +Command line program that converts VeriLUM file with characteristic curve data +(\e CCx_xx.dat) to a format used for the Barten transformation in this toolkit. +VeriLUM is a calibration package from ImageSmiths consisting of a photometer +(with serial RS232 connector) and a Windows NT software. + +\section parameters PARAMETERS + +\verbatim +in-file VeriLUM characteristic curve file to be converted + +out-file DCMTK display file to be written + +ambient ambient light (cd/m^2, floating point value) +\endverbatim + +\section notes NOTES + +The output file describing the characteristic curve of a display system +(monitor) is a simple text file. Lines starting with a '#' are treated as +comments and therefore skipped as well as blank lines. This conversion +program creates such a file automatically (including some comment lines) by +transforming the information stored in the VeriLUM file. The number following +the magic word 'max' defines the maximum DDL value (e.g. 255 for 8 bit +displays). This definition is required before the luminance data can be +defined. Optionally the ambient light value can be specified in this file +too. The floating point value (in candela per square meter) must follow the +word 'amb'. Finally the luminance values are defined for each corresponding +DDL (digital driving level) value. The entries do not necessarily have to be +ordered or complete, i.e. there can be less than 'max' + 1 entries. Missing +values are calculated by cubic spline interpolation. + +See DICOM standard part 14 for more details on display calibration and +Barten's model (including GSDF). + +\section see_also SEE ALSO + +dcmdspfn(1), dcm2pnm(1) + +\section copyright COPYRIGHT + +Copyright (C) 1999-2014 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany. + +*/ \ No newline at end of file diff --git a/dcmimgle/etc/Makefile.in b/dcmimgle/etc/Makefile.in new file mode 100644 index 00000000..f951e882 --- /dev/null +++ b/dcmimgle/etc/Makefile.in @@ -0,0 +1,23 @@ +# +# Makefile for dcmimgle/etc +# + +@SET_MAKE@ + +SHELL = /bin/sh +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +configdir = @top_srcdir@/@configdir@ + +include $(configdir)/@common_makefile@ + + +all: + +install: + +clean: + rm -f $(TRASH) + +distclean: + rm -f $(DISTTRASH) diff --git a/dcmimgle/include/CMakeLists.txt b/dcmimgle/include/CMakeLists.txt new file mode 100644 index 00000000..5c2663e3 --- /dev/null +++ b/dcmimgle/include/CMakeLists.txt @@ -0,0 +1,2 @@ +# declare installation files +INSTALL(DIRECTORY dcmtk/dcmimgle DESTINATION ${DCMTK_INSTALL_INCDIR}/dcmtk COMPONENT include FILES_MATCHING PATTERN "*.h") diff --git a/dcmimgle/include/Makefile.in b/dcmimgle/include/Makefile.in new file mode 100644 index 00000000..3c83b384 --- /dev/null +++ b/dcmimgle/include/Makefile.in @@ -0,0 +1,27 @@ +# +# Makefile for dcmimgle/include +# + +@SET_MAKE@ + +SHELL = /bin/sh +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +configdir = @top_srcdir@/@configdir@ + +include $(configdir)/@common_makefile@ + + +all: + +install: + $(configdir)/mkinstalldirs $(DESTDIR)$(includedir)/dcmtk/dcmimgle + for file in dcmtk/dcmimgle/*.h ; do \ + $(INSTALL_DATA) $$file $(DESTDIR)$(includedir)/dcmtk/dcmimgle ;\ + done + +clean: + rm -f $(TRASH) + +distclean: + rm -f $(DISTTRASH) diff --git a/dcmimgle/include/dcmtk/dcmimgle/dcmimage.h b/dcmimgle/include/dcmtk/dcmimgle/dcmimage.h new file mode 100644 index 00000000..5b27a6ce --- /dev/null +++ b/dcmimgle/include/dcmtk/dcmimgle/dcmimage.h @@ -0,0 +1,1905 @@ +/* + * + * Copyright (C) 1996-2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimgle + * + * Author: Joerg Riesmeier + * + * Purpose: Provides main interface to the "DICOM image toolkit" + * + */ + + +#ifndef DCMIMAGE_H +#define DCMIMAGE_H + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/ofstd/ofcast.h" + +#include "dcmtk/dcmimgle/dimoimg.h" +#include "dcmtk/dcmimgle/didispfn.h" +#include "dcmtk/dcmimgle/diutils.h" + + +/*------------------------* + * forward declarations * + *------------------------*/ + +class DcmXfer; +class DcmObject; +class DcmOverlayData; +class DcmLongString; +class DcmUnsignedShort; + +class DiPixel; +class DiDocument; +class DiPluginFormat; + + +/*---------------------* + * class declaration * + *---------------------*/ + +/** Interface class for dcmimgle/dcmimage module. + * The main purpose of these modules is image display. + */ +class DCMTK_DCMIMGLE_EXPORT DicomImage +{ + + public: + + // --- constructors and destructor + + /** constructor, open a DICOM file. + * Opens specified file and reads image related data, creates internal representation + * of image data. Use getStatus() to obtain detailed information about any errors. + * + ** @param filename the DICOM file + * @param flags configuration flags (see diutils.h, CIF_MayDetachPixelData is set automatically) + * @param fstart first frame to be processed (optional, 0 = 1st frame), all subsequent use + * of parameters labeled 'frame' in this class refers to this start frame. + * @param fcount number of frames (optional, 0 = all frames) + */ + DicomImage(const char *filename, + const unsigned long flags = 0, + const unsigned long fstart = 0, + const unsigned long fcount = 0); + +#ifndef STARVIEW + /** constructor, use a given DcmObject + * + ** @param object pointer to DICOM data structures (fileformat, dataset or item). + * (do not delete while referenced, i.e. while this image object or any + * descendant exists; not deleted within dcmimage unless configuration flag + * CIF_TakeOverExternalDataset is set - in this case do not delete it at all) + * @param xfer transfer syntax of the 'object'. + * (could also be EXS_Unknown in case of fileformat or dataset) + * @param flags configuration flags (CIF_xxx, see diutils.h) + * @param fstart first frame to be processed (optional, 0 = 1st frame), all subsequent use + * of parameters labeled 'frame' in this class refers to this start frame. + * @param fcount number of frames (optional, 0 = all frames) + */ + DicomImage(DcmObject *object, + const E_TransferSyntax xfer, + const unsigned long flags = 0, + const unsigned long fstart = 0, + const unsigned long fcount = 0); + + /** constructor, use a given DcmObject with specified rescale/slope. + * NB: This constructor ignores the Photometric Interpretation stored in the DICOM dataset + * and always creates a MONOCHROME2 image - useful in combination with Presentation States. + * + ** @param object pointer to DICOM data structures (fileformat, dataset or item). + * (do not delete while referenced, i.e. while this image object or any + * descendant exists; not deleted within dcmimage unless configuration flag + * CIF_TakeOverExternalDataset is set - in this case do not delete it at all) + * @param xfer transfer syntax of the 'object'. + * (could also be EXS_Unknown in case of fileformat or dataset) + * @param slope rescale slope (modality transformation) + * @param intercept rescale intercept (modality transformation) + * @param flags configuration flags (CIF_xxx, see diutils.h) + * @param fstart first frame to be processed (optional, 0 = 1st frame), all subsequent use + * of parameters labeled 'frame' in this class refers to this start frame. + * @param fcount number of frames (optional, 0 = all frames) + */ + DicomImage(DcmObject *object, + const E_TransferSyntax xfer, + const double slope, + const double intercept, + const unsigned long flags = 0, + const unsigned long fstart = 0, + const unsigned long fcount = 0); + + /** constructor, use a given DcmObject with specified modality LUT. + * NB: This constructor ignores the Photometric Interpretation stored in the DICOM dataset + * and always creates a MONOCHROME2 image - useful in combination with Presentation States. + * + ** @param object pointer to DICOM data structures (fileformat, dataset or item). + * (do not delete while referenced, i.e. while this image object or any + * descendant exists; not deleted within dcmimage unless configuration flag + * CIF_TakeOverExternalDataset is set - in this case do not delete it at all) + * @param xfer transfer syntax of the 'object'. + * (could also be EXS_Unknown in case of fileformat or dataset) + * @param data dataset element containing modality LUT data + * @param descriptor dataset element containing modality LUT descriptor + * @param explanation dataset element containing modality LUT explanation + * @param flags configuration flags (CIF_xxx, see diutils.h) + * @param fstart first frame to be processed (optional, 0 = 1st frame), all subsequent use + * of parameters labeled 'frame' in this class refers to this start frame. + * @param fcount number of frames (optional, 0 = all frames) + */ + DicomImage(DcmObject *object, + E_TransferSyntax xfer, + const DcmUnsignedShort &data, + const DcmUnsignedShort &descriptor, + const DcmLongString *explanation = NULL, + const unsigned long flags = 0, + const unsigned long fstart = 0, + const unsigned long fcount = 0); +#endif + + /** destructor + */ + virtual ~DicomImage(); + + + // --- multi-frame handling + + /** process next couple of frames. If the image object has been created with less than the number + * of frames stored in the DICOM image, this function allows for accessing the subsequent frames. + * Multiple calls to this function allow for successively processing all frames stored in the + * file or dataset. See parameters 'fstart' and 'fcount' of the constructor for how to initially + * create an instance of this class. + * NB: Only "original" images can be processed in this way, i.e. images that were created by one + * of the above constructors. Images that were created by one of the createXXX() methods can + * not be processed since they are derived from original image data in a certain way, e.g. + * scaled. + * + ** @param fcount number of frames to be processed (0 = same number as before) + * + ** @return status, true if successful, false otherwise + */ + inline int processNextFrames(const unsigned long fcount = 0) + { + return (Image != NULL) ? + Image->processNextFrames(fcount) : 0; + } + + + // --- information: return requested value if successful + + /** convert status code to status string + * + ** @param status code of current internal status + * + ** @return pointer to status string + */ + static const char *getString(const EI_Status status); + + /** convert photometric interpretation code to interpretation string (defined term) + * + ** @param interpret code of image's photometric interpretation + * + ** @return pointer to photometric interpretation string + */ + static const char *getString(const EP_Interpretation interpret); + + /** get current status information + * + ** @return status code + */ + inline EI_Status getStatus() const + { + return (Image != NULL) ? + Image->getStatus() : ImageStatus; + } + + /** get number of frames. + * Please note that this function does not return the number of frames stored in the + * DICOM file/dataset (use getNumberOfFrames() instead). It rather refers to the + * number of frames processed by this class (see constructors for details). + * + ** @return number of frames processed by this class + */ + inline unsigned long getFrameCount() const + { + return (Image != NULL) ? + Image->getNumberOfFrames() : 0; + } + + /** get index of first frame. + * This functions returns the index of the first frame processed by this class (see + * constructors for details). + * + ** @return index of first frame (0..n-1) + */ + inline unsigned long getFirstFrame() const + { + return (Image != NULL) ? + Image->getFirstFrame() : 0; + } + + /** get number of frames stored in the DICOM file/dataset. + * This attribute is mandatory for DICOM images with multiple frames. + * For single frame images, the value defaults to 1. + * + ** @return number of frames stored in the DICOM file/dataset + */ + inline unsigned long getNumberOfFrames() const + { + return (Image != NULL) ? + Image->getTotalNumberOfFrames() : 0; + } + + /** get index of representative frame. + * This attribute is optionally stored in the DICOM dataset (type 3). + * + ** @return index of representative frame (0..n-1) + */ + inline unsigned long getRepresentativeFrame() const + { + return (Image != NULL) ? + Image->getRepresentativeFrame() : 0; + } + + /** get nominal time (in milliseconds) between individual frames. + * This attribute might not always be stored in the DICOM dataset. + * + ** @return nominal time between individual frames, 0 if absent + */ + inline double getFrameTime() const + { + return (Image != NULL) ? + Image->getFrameTime() : 0; + } + + /** get image width in pixels + * + ** @return number of pixels in one row + */ + inline unsigned long getWidth() const + { + return (Image != NULL) ? + Image->getColumns() : 0; + } + + /** get image height in pixels + * + ** @return number of pixels in one column + */ + inline unsigned long getHeight() const + { + return (Image != NULL) ? + Image->getRows() : 0; + } + + /** get image depth + * + ** @return number of bits per sample of the internal representation + */ + inline int getDepth() const + { + return (Image != NULL) ? + Image->getBits() : 0; + } + + /** get minimum and maximum pixel values. + * the resulting pixel values are stored in 'double' variables to avoid problems + * with different number ranges, limited to monochrome images. + * Please note that the min/max values refer to the full pixel data (i.e. including + * all possible present frames as specified in the constructor of this class). + * + ** @param min minimum pixel value (reference parameter) + * @param max maximum pixel value (reference parameter) + * @param mode 0 = min/max 'used' pixel values, + * 1 = min/max 'possible' pixel values (absolute min/max) + * + ** @return status code (true if successful) + */ + inline int getMinMaxValues(double &min, + double &max, + const int mode = 0) const + { + return ((Image != NULL) && (Image->getMonoImagePtr() != NULL)) ? + Image->getMonoImagePtr()->getMinMaxValues(min, max, mode) : 0; + } + + /** get width height ratio (pixel aspect ratio: x/y). + * If present in the dataset and not overwritten using setWidthHeightRatio(), the following + * attributes are supported in order to determine this value: + * - Pixel Spacing, Imager Pixel Spacing, Nominal Scanned Pixel Spacing, Pixel Aspect Ratio + ** @return pixel aspect ratio (floating point value) + */ + inline double getWidthHeightRatio() const + { + return (Image != NULL) ? + Image->getColumnRowRatio() : 0; + } + + /** get height width ratio (pixel aspect ratio: y/x). + * If present in the dataset and not overwritten using setWidthHeightRatio(), the following + * attributes are supported in order to determine this value: + * - Pixel Spacing, Imager Pixel Spacing, Nominal Scanned Pixel Spacing, Pixel Aspect Ratio + * + ** @return pixel aspect ratio (floating point value) + */ + inline double getHeightWidthRatio() const + { + return (Image != NULL) ? + Image->getRowColumnRatio() : 0; + } + + /** set width height ratio (pixel aspect ratio: x/y) + * + ** @param ratio pixel aspect ratio (x/y) + * + ** @return status code (true if successful) + */ + inline int setWidthHeightRatio(const double ratio) const + { + return (Image != NULL) ? + Image->setColumnRowRatio(ratio) : 0; + } + + /** set height width ratio (pixel aspect ratio: y/x) + * + ** @param ratio pixel aspect ratio (y/x) + * + ** @return status code (true if successful) + */ + inline int setHeightWidthRatio(const double ratio) const + { + return (Image != NULL) ? + Image->setRowColumnRatio(ratio) : 0; + } + + /** check whether given output value is unused + * + ** @param value output value to be checked + * + ** @return status, true if unused (1 = within output range, 2 = out of range), false otherwise + */ + inline int isOutputValueUnused(const unsigned long value) + { + return ((Image != NULL) && (Image->getMonoImagePtr() != NULL)) ? + Image->getMonoImagePtr()->isValueUnused(value) : 0; + } + + // --- output: return pointer to output data if successful + + /** get number of bytes required for the rendered output of a single frame. + * This function determines the size of a rendered frame as created by getOutputData(). + * Therefore, it can be used to allocate a sufficiently large memory buffer and pass + * its size to the second variant of getOutputData(). + * + ** @param bits number of bits per sample used to render the pixel data + * (image depth, 1..MAX_BITS, 0 means 'bits stored' in the image) + * (MI_PastelColor = -1 for true color pastel mode, EXPERIMENTAL) + * + ** @return number of bytes if successful, 0 otherwise + */ + inline unsigned long getOutputDataSize(const int bits = 0) const + { + return (Image != NULL) ? + Image->getOutputDataSize(Image->getBits(bits)) : 0; + } + + /** render pixel data and return pointer to internal memory buffer. + * apply VOI/PLUT transformation and (visible) overlay planes. + * internal memory buffer will be delete for the next getBitmap/Output operation. + * output data is always padded to 8, 16, 32, ... bits (bits allocated). + * Supported output color models: Monochrome 2 for monochrome images and RGB + * (or YCbCr_Full if flag CIF_KeepYCbCrColorModel is set) for color images. + * The rendered pixel data is always unsigned. + * + ** @param bits number of bits per sample used to render the pixel data + * (image depth, 1..MAX_BITS, 0 means 'bits stored' in the image) + * (MI_PastelColor = -1 for true color pastel mode, EXPERIMENTAL) + * @param frame number of frame to be rendered (0..n-1) + * @param planar 0 = color-by-pixel (R1G1B1...R2G2B2...R3G3B3...), + * 1 = color-by-plane (R1R2R3...G1G2G3...B1B2B3...) + * (only applicable to multi-planar/color images, otherwise ignored) + * + ** @return pointer to internal memory buffer containing rendered pixel data + * (if successful, NULL otherwise) + */ + inline const void *getOutputData(const int bits = 0, + const unsigned long frame = 0, + const int planar = 0) + { + return (Image != NULL) ? + Image->getOutputData(frame, Image->getBits(bits), planar) : NULL; + } + + /** render pixel data and output to given memory buffer. + * apply VOI/PLUT transformation and (visible) overlay planes. + * output data is always padded to 8, 16, 32, ... bits (bits allocated). + * Supported output color models: Monochrome 2 for monochrome images and RGB + * (or YCbCr_Full if flag CIF_KeepYCbCrColorModel is set) for color images. + * The rendered pixel data is always unsigned. + * + ** @param buffer pointer to memory buffer (must already be allocated) + * @param size size of memory buffer (will be checked whether it is sufficient) + * @param bits number of bits per sample used to render the pixel data + * (image depth, 1..MAX_BITS, 0 means 'bits stored' in the image) + * (MI_PastelColor = -1 for true color pastel mode, EXPERIMENTAL) + * @param frame number of frame to be rendered (0..n-1) + * @param planar 0 = color-by-pixel (R1G1B1...R2G2B2...R3G3B3...), + * 1 = color-by-plane (R1R2R3...G1G2G3...B1B2B3...) + * (only applicable to multi-planar/color images, otherwise ignored) + * + ** @return status code (true if successful) + */ + inline int getOutputData(void *buffer, + const unsigned long size, + const int bits = 0, + const unsigned long frame = 0, + const int planar = 0) + { + return (Image != NULL) ? + Image->getOutputData(buffer, size, frame, Image->getBits(bits), planar) : 0; + } + + /** render pixel data and return pointer to given plane (internal memory buffer). + * apply VOI/PLUT transformation and (visible) overlay planes + * internal memory buffer will be delete for the next getBitmap/Output operation. + * Supported output color models: Monochrome 2 for monochrome images and RGB + * (or YCbCr_Full if flag CIF_KeepYCbCrColorModel is set) for color images. + * The rendered pixel data is always unsigned. + * + ** @param plane number of plane to be rendered + * + ** @return pointer to internal memory buffer containing rendered pixel data + * (if successful, NULL otherwise) + */ + inline const void *getOutputPlane(const int plane) const + { + return (Image != NULL) ? + Image->getOutputPlane(plane) : NULL; + } + + /** delete internal memory buffer used for rendered images. + * Save memory if data is no longer needed. + */ + inline void deleteOutputData() const + { + if (Image != NULL) + Image->deleteOutputData(); + } + + // --- misc + + /** check whether image is monochrome or not. + * + ** @return true if image is monochrome, false otherwise (i.e. color image) + */ + inline int isMonochrome() const + { + return (PhotometricInterpretation == EPI_Monochrome1) || (PhotometricInterpretation == EPI_Monochrome2); + } + + /** get code for photometric interpretation (color model). + * + ** @return code for photometric interpretation of the image + */ + inline EP_Interpretation getPhotometricInterpretation() const + { + return PhotometricInterpretation; + } + + /** check whether image has given SOP class UID. + * + ** @return true if image has given SOP class UID, false otherwise + */ + int hasSOPclassUID(const char *uid) const; + + /** get intermediate pixel data representation (read-only). + * This function allows to access the pixel data after they have been extracted + * from the DICOM data element and the modality transformation has been applied + * (if present and not disabled). Please note that for monochrome images the + * internal representation might be signed whereas color images are automatically + * converted to unsigned RGB format. Pixels are aligned to 8, 16 or 32 bits. + * Always use DiPixel::getRepresentation() in order to determine the integer + * representation of the internally stored pixel data. + * + ** @return pointer to intermediate pixel data representation + */ + inline const DiPixel *getInterData() const + { + return (Image != NULL) ? + Image->getInterData() : NULL; + } + + // --- display function for output device characteristic (calibration): + // only applicable to grayscale images + + /** get display function + * + ** @return pointer to current display function, NULL if absent + */ + inline DiDisplayFunction *getDisplayFunction() const + { + return ((Image != NULL) && (Image->getMonoImagePtr() != NULL)) ? + Image->getMonoImagePtr()->getDisplayFunction() : OFstatic_cast(DiDisplayFunction *, NULL); + } + + /** set display function + * + ** @param display object describing the output device characteristic (only referenced!) + * + ** @return true if successful, false otherwise + */ + inline int setDisplayFunction(DiDisplayFunction *display) + { + return ((Image != NULL) && (Image->getMonoImagePtr() != NULL)) ? + Image->getMonoImagePtr()->setDisplayFunction(display) : 0; + } + + /** set no display function. + * disables display function transformation, object is not deleted! + * + ** @return true if successful (1 = disabled current function, + * 2 = there was no function to disable), + * false otherwise + */ + inline int setNoDisplayFunction() + { + return ((Image != NULL) && (Image->getMonoImagePtr() != NULL)) ? + Image->getMonoImagePtr()->setNoDisplayFunction() : 0; + } + + /** delete specified display LUT(s) + * + ** @param bits parameter of LUT to be deleted (0 = all) + * + ** @return true if successful, false otherwise + */ + inline int deleteDisplayLUT(const int bits = 0) + { + return ((Image != NULL) && (Image->getMonoImagePtr() != NULL)) ? + Image->getMonoImagePtr()->deleteDisplayLUT(bits) : 0; + } + + /** convert P-value to DDL. + * conversion uses display LUT if present, linear scaling otherwise. + * + ** @param pvalue P-value to be converted (0..65535) + * @param ddl reference to resulting DDL + * @param bits number of bits for output + * + ** @return true if successful (1 = display function transformation, + * 2 = linear scaling), + * false otherwise + */ + inline int convertPValueToDDL(const Uint16 pvalue, + Uint16 &ddl, + const int bits = 8) + { + return ((Image != NULL) && (Image->getMonoImagePtr() != NULL)) ? + Image->getMonoImagePtr()->convertPValueToDDL(pvalue, ddl, bits) : 0; + } + + // --- windowing (voi): only applicable to grayscale images + // return true if successful (see also 'dimoimg.cc') + + /** unset all VOI transformations (windows and LUTs). + * only applicable to monochrome images + * + ** @return true if successful (1 = previous window/LUT has been valid, + * 2 = otherwise), + * false otherwise (image is invalid or not monochrome) + */ + inline int setNoVoiTransformation() + { + return ((Image != NULL) && (Image->getMonoImagePtr() != NULL)) ? + Image->getMonoImagePtr()->setNoVoiTransformation() : 0; + } + + /** set automatically calculated minimum/maximum window. + * possibly active VOI LUT is implicitly disabled. + * Please note that the min/max values refer to the full pixel data (i.e. including + * all possible present frames as specified in the constructor of this class). + * + ** @param idx ignore global min/max values if true (1) + * + ** @return true if successful (1 = window has changed, + * 2 = new window is the same as previous one), + * false otherwise + */ + inline int setMinMaxWindow(const int idx = 0) + { + return ((Image != NULL) && (Image->getMonoImagePtr() != NULL)) ? + Image->getMonoImagePtr()->setMinMaxWindow(idx) : 0; + } + + /** set automatically calculated histogram window. + * possibly active VOI LUT is implicitly disabled. + * + ** @param thresh threshhold value specifying percentage of histogram border which + * shall be ignored (defaut: 5%). + * + ** @return true if successful, false otherwise + */ + inline int setHistogramWindow(const double thresh = 0.05) + { + return ((Image != NULL) && (Image->getMonoImagePtr() != NULL)) ? + Image->getMonoImagePtr()->setHistogramWindow(thresh) : 0; + } + + /** set automatically calculated VOI window for the specified Region of Interest (ROI). + * The ROI is specified by means of a rectangle (left, top, width, height). Only the part + * of the ROI that overlaps with the image is regarded - if the overlapping area is empty + * this method returns false (0). + * Possibly active VOI LUT is implicitly disabled. + * + ** @param left_pos x-coordinate of the top left-hand corner of the ROI (starting from 0) + * @param top_pos y-coordinate of the top left-hand corner of the ROI (starting from 0) + * @param width width in pixels of the rectangular ROI (minimum: 1) + * @param height height in pixels of the rectangular ROI (minimum: 1) + * @param frame index of the frame to be used for calculation (default: 0 = first) + * + ** @return true if successful (1 = window has changed, + * 2 = new window is the same as previous one), + * false otherwise + */ + inline int setRoiWindow(const unsigned long left_pos, + const unsigned long top_pos, + const unsigned long width, + const unsigned long height, + const unsigned long frame = 0) + { + return ((Image != NULL) && (Image->getMonoImagePtr() != NULL)) ? + Image->getMonoImagePtr()->setRoiWindow(left_pos, top_pos, width, height, frame) : 0; + } + + /** set specified VOI window (given by index to window width/center sequence stored in image + * file). + * possibly active VOI LUT is implicitly disabled. + * NB: This function does nothing if the flag CIF_UsePresentationState is set. + * + ** @param window index to window width/center sequence (0..n-1) + * + ** @return true if successful, false otherwise (none monochrome or invalid index) + */ + inline int setWindow(const unsigned long window) + { + return ((Image != NULL) && (Image->getMonoImagePtr() != NULL)) ? + Image->getMonoImagePtr()->setWindow(window) : 0; + } + + /** set specified VOI window (given by window width and center). + * possibly active VOI LUT is implicitly disabled. + * + ** @param center center of specified window + * @param width width of specified window (>= 1.0) + * + ** @return true if successful (1 = window has changed, + * 2 = new window is the same as previous one), + * false otherwise + */ + inline int setWindow(const double center, + const double width) + { + return ((Image != NULL) && (Image->getMonoImagePtr() != NULL)) ? + Image->getMonoImagePtr()->setWindow(center, width) : 0; + } + + /** get current VOI window as window center and width values + * + ** @param center return current window center value + * @param width return current window width value + * + ** @return true if successful, false otherwise + */ + inline int getWindow(double ¢er, + double &width) + { + return ((Image != NULL) && (Image->getMonoImagePtr() != NULL)) ? + Image->getMonoImagePtr()->getWindow(center, width) : 0; + } + + /** get number of VOI windows (stored in image file). + * NB: This function does nothing if the flag CIF_UsePresentationState is set. + * + ** @return number of VOI windows + */ + inline unsigned long getWindowCount() const + { + return ((Image != NULL) && (Image->getMonoImagePtr() != NULL)) ? + Image->getMonoImagePtr()->getWindowCount() : 0; + } + + /** set VOI LUT function + * + ** @param function type of VOI LUT function (default, linear or sigmoid). + * 'default' basically means the same as 'linear'. + * + ** @return true if successful (1 = function has changed, + * 2 = function has not changed), + * false otherwise + */ + inline int setVoiLutFunction(const EF_VoiLutFunction function) + { + return ((Image != NULL) && (Image->getMonoImagePtr() != NULL)) ? + Image->getMonoImagePtr()->setVoiLutFunction(function) : 0; + } + + /** get VOI LUT function. + * possible values are: EFV_Default, EFV_Linear, EFV_Sigmoid. + * + ** @return currently active VOI LUT function or EFV_Default if not set + */ + inline EF_VoiLutFunction getVoiLutFunction() const + { + return ((Image != NULL) && (Image->getMonoImagePtr() != NULL)) ? + Image->getMonoImagePtr()->getVoiLutFunction() : EFV_Default; + } + + /** set VOI LUT (given by dcmdata elements). + * possibly active window/center is implicitly disabled. + * Given data is only referenced and not copied! Make sure that the corresponding DcmXXX + * objects exist as long as the VOI LUT is set. + * + ** @param data contains LUT data + * @param descriptor describes LUT structure + * @param explanation free form description of VOI LUT (optional) + * @param descripMode mode specifying the use of the bits per table entry value + * + ** @return true if successful, false otherwise + */ + inline int setVoiLut(const DcmUnsignedShort &data, + const DcmUnsignedShort &descriptor, + const DcmLongString *explanation = NULL, + const EL_BitsPerTableEntry descripMode = ELM_UseValue) + { + return ((Image != NULL) && (Image->getMonoImagePtr() != NULL)) ? + Image->getMonoImagePtr()->setVoiLut(data, descriptor, explanation, descripMode) : 0; + } + + /** set VOI LUT (given by index to VOI LUT sequence stored in image file). + * possibly active window/center is implicitly disabled. + * NB: This function does nothing if the flag CIF_UsePresentationState is set. + * + ** @param table index to VOI LUT sequence (0..n-1) + * @param descripMode mode specifying the use of the bits per table entry value + * + ** @return true if successful, false otherwise (none monochrome or invalid index) + */ + inline int setVoiLut(const unsigned long table, + const EL_BitsPerTableEntry descripMode = ELM_UseValue) + { + return ((Image != NULL) && (Image->getMonoImagePtr() != NULL)) ? + Image->getMonoImagePtr()->setVoiLut(table, descripMode) : 0; + } + + /** get number of VOI LUTs (stored in image file) + * + ** @return number of VOI LUTs + */ + inline unsigned long getVoiLutCount() const + { + return ((Image != NULL) && (Image->getMonoImagePtr() != NULL)) ? + Image->getMonoImagePtr()->getVoiLutCount() : 0; + } + + /** get description of active VOI transformation + * + ** @return pointer to description text (NULL if absent) + */ + inline const char *getVoiTransformationExplanation() const + { + return ((Image != NULL) && (Image->getMonoImagePtr() != NULL)) ? + Image->getMonoImagePtr()->getVoiTransformationExplanation() : OFstatic_cast(const char *, NULL); + } + + /** get description of specified VOI window (stored in the image file) + * + ** @param window index of the stored VOI window (0..n-1) + * @param explanation variable in which the explanation string is stored + * + ** @return pointer to description text (NULL if absent or index invalid) + */ + inline const char *getVoiWindowExplanation(const unsigned long window, + OFString &explanation) const + { + return ((Image != NULL) && (Image->getMonoImagePtr() != NULL)) ? + Image->getMonoImagePtr()->getVoiWindowExplanation(window, explanation) : OFstatic_cast(const char *, NULL); + } + + /** get description of specified VOI LUT (stored in the image file) + * + ** @param table index of the stored VOI LUT (0..n-1) + * @param explanation variable in which the explanation string is stored + * + ** @return pointer to description text (NULL if absent or index invalid) + */ + inline const char *getVoiLutExplanation(const unsigned long table, + OFString &explanation) const + { + return ((Image != NULL) && (Image->getMonoImagePtr() != NULL)) ? + Image->getMonoImagePtr()->getVoiLutExplanation(table, explanation) : OFstatic_cast(const char *, NULL); + } + + /** get description of performed modality LUT transformation + * + ** @return pointer to description text (NULL if absent) + */ + inline const char *getModalityLutExplanation() const + { + return ((Image != NULL) && (Image->getMonoImagePtr() != NULL)) ? + Image->getMonoImagePtr()->getModalityLutExplanation() : OFstatic_cast(const char *, NULL); + } + + // --- hardcopy parameters + + /** get polarity. applicable to monochrome and color images. + * possible values are EPP_Normal and EPP_Reverse + * + ** @return currently active polarity mode or EPP_Normal if not applicable + */ + inline EP_Polarity getPolarity() const + { + return (Image != NULL) ? + Image->getPolarity() : EPP_Normal; + } + + /** set polarity. applicable to monochrome and color images. + * + ** @param polarity polarity (normal or reverse) + * + ** @return true if successful (1 = polarity has changed, + * 2 = polarity has not changed), + * false otherwise + */ + inline int setPolarity(const EP_Polarity polarity) + { + return (Image != NULL) ? + Image->setPolarity(polarity) : 0; + } + + /** set hardcopy parameters. only applicable to monochrome images. + * used to display LinOD images + * + ** @param min minimum density of the print-out (in hundreds of Optical Density, + * e.g. 150 means 1.5 OD) + * @param max maximum density of the print-out (ditto) + * @param reflect reflected ambient light (in candela per square meter - cd/m^2) + * @param illumin illumination (ditto) + * + ** @return true if successful (1 = at least one of the parameters has changed, + * 2 = no parameter has changed), + * false otherwise + */ + inline int setHardcopyParameters(const unsigned int min, + const unsigned int max, + const unsigned int reflect, + const unsigned int illumin) + { + return ((Image != NULL) && (Image->getMonoImagePtr() != NULL)) ? + Image->getMonoImagePtr()->setHardcopyParameters(min, max, reflect, illumin) : 0; + } + + // --- presentation LUT: only applicable to grayscale images + + /** get shape for presentation transformation. + * possible values are: ESP_Default, ESP_Identity, ESP_Inverse, ESP_LinOD. + * If a presentation LUT is currently active ESP_Default is always returned. + * + ** @return currently active presentation LUT shape or ESP_Default if not set + */ + inline ES_PresentationLut getPresentationLutShape() const + { + return ((Image != NULL) && (Image->getMonoImagePtr() != NULL)) ? + Image->getMonoImagePtr()->getPresentationLutShape() : ESP_Default; + } + + /** set shape for presentation transformation. + * possibly active presentation LUT is implicitly disabled. + * + ** @param shape presentation LUT shape (default, identity, inverse or lin OD). + * 'default' means that the output data is always created with 0 for black + * and maxvalue for white (i.e. monochrome2 data is created for output). + * + ** @return true if successful (1 = shape has changed, + * 2 = shape has not changed), + * false otherwise + */ + inline int setPresentationLutShape(const ES_PresentationLut shape) + { + return ((Image != NULL) && (Image->getMonoImagePtr() != NULL)) ? + Image->getMonoImagePtr()->setPresentationLutShape(shape) : 0; + } + + /** set LUT for presentation transformation. + * possibly active presentation LUT is implicitly disabled. + * Given data is only referenced and not copied! Make sure that the corresponding DcmXXX + * objects exist as long as the presentation LUT is set. + * + ** @param data contains LUT data + * @param descriptor describes LUT structure + * @param explanation free form description of presentation LUT (optional) + * @param descripMode mode specifying the use of the bits per table entry value + * + ** @return true if successful, false otherwise + */ + inline int setPresentationLut(const DcmUnsignedShort &data, + const DcmUnsignedShort &descriptor, + const DcmLongString *explanation = NULL, + const EL_BitsPerTableEntry descripMode = ELM_UseValue) + { + return ((Image != NULL) && (Image->getMonoImagePtr() != NULL)) ? + Image->getMonoImagePtr()->setPresentationLut(data, descriptor, explanation, descripMode) : 0; + } + + /** get description of active presentation LUT + * + ** @return pointer to description text (NULL if absent) + */ + inline const char *getPresentationLutExplanation() const + { + return ((Image != NULL) && (Image->getMonoImagePtr() != NULL)) ? + Image->getMonoImagePtr()->getPresentationLutExplanation() : OFstatic_cast(const char *, NULL); + } + + /** set inverse LUT for presentation transformation. + * this LUT transform is e.g. used for DICOM print (12->8, 8->12 bit) + * possibly active presentation LUT will not be considered! + * + ** @param data contains LUT data + * @param descriptor describes LUT structure + * @param descripMode mode specifying the use of the bits per table entry value + * + ** @return true if successful, false otherwise + */ + inline int setInversePresentationLut(const DcmUnsignedShort &data, + const DcmUnsignedShort &descriptor, + const EL_BitsPerTableEntry descripMode = ELM_UseValue) + { + return ((Image != NULL) && (Image->getMonoImagePtr() != NULL)) ? + Image->getMonoImagePtr()->setInversePresentationLut(data, descriptor, descripMode) : 0; + } + + // --- overlays: return true (!0) if successful (see also 'diovlay.cc') + // only applicable to grayscale images + + /** add specified plane to group of additional overlay planes. + * replaces old overlay plane if group number already exists. + * + ** @param group group number (0x60nn) of overlay plane + * @param width width of overlay plane (in pixels) + * @param height height of overlay plane (in pixels) + * @param left_pos x coordinate of plane origin (referring to image origin) + * @param top_pos y coordinate of plane origin + * @param data overlay plane data (dcmdata element) + * @param label overlay plane label + * @param description overlay plane description + * @param mode display mode (see 'diutils.h') + * + ** @return false (0) if an error occurred, true otherwise (1 = added new plane, + * 2 = replaced existing plane) + */ + inline int addOverlay(const unsigned int group, + const signed int left_pos, + const signed int top_pos, + const unsigned int width, + const unsigned int height, + const DcmOverlayData &data, + const DcmLongString &label, + const DcmLongString &description, + const EM_Overlay mode = EMO_Default) + { + return ((Image != NULL) && (Image->getMonoImagePtr() != NULL)) ? + Image->getMonoImagePtr()->addOverlay(group, left_pos, top_pos, width, height, data, label, description, mode) : 0; + } + + /** remove specified (additional) overlay plane + * + ** @param group group number (0x60nn) of overlay plane + * + ** @return false (0) if an error occurred (e.g. plane doesn't exist), true otherwise + */ + inline int removeOverlay(const unsigned int group) + { + return ((Image != NULL) && (Image->getOverlayPtr(1) != NULL)) ? + Image->getOverlayPtr(1)->removePlane(group) : 0; + } + + /** remove all additional overlay planes + * + ** @return false (0) if an error occurred, true otherwise (1 = all planes deleted, + * 2 = no planes to be deleted) + */ + inline int removeAllOverlays() + { + return ((Image != NULL) && (Image->getMonoImagePtr() != NULL)) ? + Image->getMonoImagePtr()->removeAllOverlays() : 0; + } + + /** check whether specified overlay plane is visible/activated. + * see show/hideOverlay() to modify the visibility status. + * + ** @param plane number (0..15) or group number (0x60nn) of overlay plane + * @param idx index of overlay group (0 = dataset, 1 = additional), default: 0 + * + ** @return true (1) if overlay plane is visible, false (0) otherwise + */ + inline int isOverlayVisible(const unsigned int plane, + const unsigned int idx = 0) + { + return ((Image != NULL) && (Image->getOverlayPtr(idx) != NULL)) ? + Image->getOverlayPtr(idx)->isPlaneVisible(plane) : 0; + } + + /** activate specified overlay plane + * + ** @param plane number (0..15) or group number (0x60nn) of overlay plane + * @param idx index of overlay group (0 = dataset, 1 = additional), default: 0 + * + ** @return false (0) if an error occurred, true otherwise (1 = plane successfully activated, + * 2 = plane has already been visible) + */ + inline int showOverlay(const unsigned int plane, + const unsigned int idx = 0) + { + return ((Image != NULL) && (Image->getOverlayPtr(idx) != NULL)) ? + Image->getOverlayPtr(idx)->showPlane(plane) : 0; + } + + /** activate specified overlay plane and change some parameters + * + ** @param plane number (0..15) or group number (0x60nn) of overlay plane + * @param mode display mode (see 'diutils.h') + * @param fore plane's foreground color (in percent, default: 1.0) + * @param thresh threshold value (in percent, default: 0.5), only for EMO_ThresholdReplace + * @param idx index of overlay group (0 = dataset, 1 = additional), default: 0 + * + ** @return false (0) if an error occurred, true otherwise + */ + inline int showOverlay(const unsigned int plane, + const EM_Overlay mode, + const double fore = 1.0, + const double thresh = 0.5, + const unsigned int idx = 0) + { + return ((Image != NULL) && (Image->getOverlayPtr(idx) != NULL)) ? + Image->getOverlayPtr(idx)->showPlane(plane, fore, thresh, mode) : 0; + } + + /** activate specified overlay plane and change 'pvalue' (only for bitmap shutters) + * + ** @param plane number (0..15) or group number (0x60nn) of overlay plane + * @param pvalue P-value used to display overlay plane + * + ** @return false (0) if an error occurred, true otherwise + */ + inline int showOverlay(const unsigned int plane, + const Uint16 pvalue) + { + return ((Image != NULL) && (Image->getOverlayPtr(1) != NULL)) ? + Image->getOverlayPtr(1)->showPlane(plane, pvalue) : 0; + } + + /** activate all overlay planes (make them visible) + * + ** @param idx index of overlay group (0 = dataset, 1 = additional), default: 0 + * + ** @return false (0) if an error occurred, true otherwise (1 = planes have been successfully activated, + * 2 = no planes to be activated) + */ + inline int showAllOverlays(const unsigned int idx = 0) + { + return ((Image != NULL) && (Image->getOverlayPtr(idx) != NULL)) ? + Image->getOverlayPtr(idx)->showAllPlanes() : 0; + } + + /** activate all overlay planes and set specified parameters + * + ** @param mode display mode (see 'diutils.h') + * @param fore plane's foreground color (in percent, default: 1.0) + * @param thresh threshold value (in percent, default: 0.5), only for EMO_ThresholdReplace + * @param idx index of overlay group (0 = dataset, 1 = additional), default: 0 + * + ** @return false (0) if an error occurred, true otherwise (1 = planes have been successfully activated, + * 2 = no planes to be activated) + */ + inline int showAllOverlays(const EM_Overlay mode, + const double fore = 1, + const double thresh = 0.5, + const unsigned int idx = 0) + { + return ((Image != NULL) && (Image->getOverlayPtr(idx) != NULL)) ? + Image->getOverlayPtr(idx)->showAllPlanes(fore, thresh, mode) : 0; + } + + /** deactivate specified overlay plane + * + ** @param plane number (0..15) or group number (0x60nn) of overlay plane + * @param idx index of overlay group (0 = dataset, 1 = additional), default: 0 + * + ** @return false (0) if an error occurred, true otherwise (1 = plane successfully deactivated, + * 2 = plane has already been invisible) + */ + inline int hideOverlay(const unsigned int plane, + const unsigned int idx = 0) + { + return ((Image != NULL) && (Image->getOverlayPtr(idx) != NULL)) ? + Image->getOverlayPtr(idx)->hidePlane(plane) : 0; + } + + /** deactivate all overlay planes (make them invisible) + * + ** @param idx index of overlay group (0 = dataset, 1 = additional), default: 0 + * + ** @return false (0) if an error occurred, true otherwise (1 = planes have been successfully deactivated, + * 2 = no planes to be deactivated) + */ + inline int hideAllOverlays(const unsigned int idx = 0) + { + return ((Image != NULL) && (Image->getOverlayPtr(idx) != NULL)) ? + Image->getOverlayPtr(idx)->hideAllPlanes() : 0; + } + + /** move origin of specified overlay plane to given position + * + ** @param plane number (0..15) or group number (0x60nn) of overlay plane + * @param left_pos x coordinate of new plane origin (origin = 0) + * @param top_pos y coordinate of new plane origin (origin = 0) + * @param idx index of overlay group (0 = dataset, 1 = additional), default: 0 + * + ** @return false (0) if an error occurred, true otherwise (1 = plane has been successfully moved, + * 2 = old and new position are equal, nothing to do) + */ + inline int placeOverlay(const unsigned int plane, + const signed int left_pos, + const signed int top_pos, + const unsigned int idx = 0) + { + return ((Image != NULL) && (Image->getOverlayPtr(idx) != NULL)) ? + Image->getOverlayPtr(idx)->placePlane(plane, left_pos, top_pos) : 0; + } + + /** get number of overlay planes + * + ** @param idx index of overlay group (0 = dataset, 1 = additional), default: 0 + * + ** @return number of overlay planes stored in the image + */ + inline unsigned int getOverlayCount(const unsigned int idx = 0) const + { + return ((Image != NULL) && (Image->getOverlayPtr(idx) != NULL)) ? + Image->getOverlayPtr(idx)->getCount() : 0; + } + + /** get group number of specified overlay plane + * + ** @param plane number (0..15) or group number (0x60nn) of overlay plane + * @param idx index of overlay group (0 = dataset, 1 = additional), default: 0 + * + ** @return group number of given overlay plane if successful, false (0) otherwise + */ + inline unsigned int getOverlayGroupNumber(const unsigned int plane, + const unsigned int idx = 0) const + { + return ((Image != NULL) && (Image->getOverlayPtr(idx) != NULL)) ? + Image->getOverlayPtr(idx)->getPlaneGroupNumber(plane) : 0; + } + + /** get label of specified overlay plane + * + ** @param plane number (0..15) or group number (0x60nn) of overlay plane + * @param idx index of overlay group (0 = dataset, 1 = additional), default: 0 + * + ** @return pointer to overlay plane label if successful, false (NULL) otherwise + */ + inline const char *getOverlayLabel(const unsigned int plane, + const unsigned int idx = 0) const + { + return ((Image != NULL) && (Image->getOverlayPtr(idx) != NULL)) ? + Image->getOverlayPtr(idx)->getPlaneLabel(plane) : OFstatic_cast(const char *, NULL); + } + + /** get description of specified overlay plane + * + ** @param plane number (0..15) or group number (0x60nn) of overlay plane + * @param idx index of overlay group (0 = dataset, 1 = additional), default: 0 + * + ** @return pointer to overlay plane description if successful, false (NULL) otherwise + */ + inline const char *getOverlayDescription(const unsigned int plane, + const unsigned int idx = 0) const + { + return ((Image != NULL) && (Image->getOverlayPtr(idx) != NULL)) ? + Image->getOverlayPtr(idx)->getPlaneDescription(plane) : OFstatic_cast(const char *, NULL); + } + + /** get mode of specified overlay plane + * + ** @param plane number (0..15) or group number (0x60nn) of overlay plane + * @param idx index of overlay group (0 = dataset, 1 = additional), default: 0 + * + ** @return mode of overlay plane if successful, EMO_Default otherwise + */ + inline EM_Overlay getOverlayMode(const unsigned int plane, + const unsigned int idx = 0) const + { + return ((Image != NULL) && (Image->getOverlayPtr(idx) != NULL)) ? + Image->getOverlayPtr(idx)->getPlaneMode(plane) : EMO_Default; + } + + /** create bitmap for specified overlay plane. + * (up to 16 bits per pixel with two values: 'fore' and 'back') + * Please note that the current origin of the overlay plane is used. Furthermore, the size + * of the overlay plane is restricted to the size of the surrounding image. Use the method + * getFullOverlayData() if the complete bitmap data is required regardless of its position. + * + ** @param plane number (0..15) or group number (0x60nn) of overlay plane + * @param width returns width of overlay plane (in pixels) + * @param height returns height of overlay plane (in pixels) + * @param left_pos returns x coordinate of plane's origin + * @param top_pos returns y coordinate of plane's origin + * @param mode returns display mode (see 'diutils.h') + * @param frame index of frame used for output (default: 0 = first) + * @param bits number of bits (stored) in the resulting array, default: 8, range: 1..16 + * Used to mask the values for foreground and background color. The resulting + * array is always padded to 8 or 16 bits with 1, 8 or 16 bits allocated + * depending on the value of 'bits'. + * @param fore foreground color to be set in bitmap, default: 255, range: 0..2^bits-1 + * @param back background color to be set in bitmap (transparent), default: 0, range: 0..2^bits-1 + * @param idx index of overlay group (0 = dataset, planes stored in the image dataset; + * 1 = additional, planes added by addOverlay(); + * 2 = 'additional' overlay planes hide 'dataset' planes + * when the overlay group number exists in both), + * default: 2 + * + ** @return pointer to overlay plane data (internal memory buffer) + */ + const void *getOverlayData(const unsigned int plane, + unsigned int &left_pos, + unsigned int &top_pos, + unsigned int &width, + unsigned int &height, + EM_Overlay &mode, + const unsigned long frame = 0, + const int bits = 8, + const Uint16 fore = 0xff, + const Uint16 back = 0x0, + const unsigned int idx = 2) const + { + return ((Image != NULL) && (Image->getMonoImagePtr() != NULL)) ? + Image->getMonoImagePtr()->getOverlayData(frame, plane, left_pos, top_pos, width, height, mode, idx, bits, fore, back) : NULL; + } + + /** create bitmap for specified overlay plane. + * (up to 16 bits per pixel with two values: 'fore' and 'back') + * In contrast to the previous method the full bitmap data is always returned. + * + ** @param plane number (0..15) or group number (0x60nn) of overlay plane + * @param width returns width of overlay plane (in pixels) + * @param height returns height of overlay plane (in pixels) + * @param frame index of frame used for output (default: 0 = first) + * @param bits number of bits (stored) in the resulting array, default: 8, range: 1..16 + * Used to mask the values for foreground and background color. The resulting + * array is always padded to 8 or 16 bits with 1, 8 or 16 bits allocated + * depending on the value of 'bits'. + * @param fore foreground color to be set in bitmap, default: 255, range: 0..2^bits-1 + * @param back background color to be set in bitmap (transparent), default: 0, range: 0..2^bits-1 + * @param idx index of overlay group (0 = dataset, planes stored in the image dataset; + * 1 = additional, planes added by addOverlay()), + * default: 0 + * + ** @return pointer to overlay plane data (internal memory buffer) + */ + const void *getFullOverlayData(const unsigned int plane, + unsigned int &width, + unsigned int &height, + const unsigned long frame = 0, + const int bits = 8, + const Uint16 fore = 0xff, + const Uint16 back = 0x0, + const unsigned int idx = 0) const + { + return ((Image != NULL) && (Image->getMonoImagePtr() != NULL)) ? + Image->getMonoImagePtr()->getFullOverlayData(frame, plane, width, height, idx, bits, fore, back) : NULL; + } + + /** delete buffer for overlay plane data. + * Save memory if data is no longer needed. + */ + inline void deleteOverlayData() const + { + if ((Image != NULL) && (Image->getMonoImagePtr() != NULL)) + Image->getMonoImagePtr()->deleteOverlayData(); + } + + /** create bitmap for specified overlay plane and store it in (6xxx,3000) format. + * (1 bit allocated and stored, foreground color is 1, background color is 0, + * data is 16 bit padded - even length) + * memory is allocated but not handled internally - must be deleted from calling program. + * + ** @param buffer stores pointer to overlay data (memory is allocated internally) + * @param plane number (0..15) or group number (0x60nn) of overlay plane + * @param width returns width of overlay plane (in pixels) + * @param height returns height of overlay plane (in pixels) + * @param frames returns number of frames + * @param idx index of overlay group (0 = dataset, planes stored in the image dataset; + * 1 = additional, planes added by addOverlay()), + * default: 0 + * + ** @return number of bytes allocated for the 'buffer' if successful, 0 otherwise + */ + unsigned long create6xxx3000OverlayData(Uint8 *&buffer, + const unsigned int plane, + unsigned int &width, + unsigned int &height, + unsigned long &frames, + const unsigned int idx = 0) const + { + return ((Image != NULL) && (Image->getMonoImagePtr() != NULL)) ? + Image->getMonoImagePtr()->create6xxx3000OverlayData(buffer, plane, width, height, frames, idx) : 0; + } + + + // --- create...Image: return pointer to new 'DicomImage' object, memory isn't handled internally ! + + /** create copy of current image object. + * memory is not handled internally - must be deleted from calling program. + * + ** @param fstart first frame to be processed (0 = 1st frame) + * @param fcount number of frames (0 = all frames) + * + ** @return pointer to new DicomImage object (NULL if an error occurred) + */ + DicomImage *createDicomImage(unsigned long fstart = 0, + unsigned long fcount = 0) const; + + /** create scaled copy of current image object (given by exact size). + * memory is not handled internally - must be deleted from calling program. + * + ** @param width width of new image (in pixels) + * @param height height of new image (in pixels) + * @param interpolate specifies whether scaling algorithm should use interpolation (if necessary). + * default: no interpolation (0), preferred interpolation algorithm (if applicable): + * 1 = pbmplus algorithm, 2 = c't algorithm, 3 = bilinear magnification, + * 4 = bicubic magnification + * @param aspect specifies whether pixel aspect ratio should be taken into consideration + * (if true, width OR height should be 0, i.e. this component will be calculated + * automatically) + * + ** @return pointer to new DicomImage object (NULL if an error occurred) + */ + DicomImage *createScaledImage(const unsigned long width, + const unsigned long height = 0, + const int interpolate = 0, + int aspect = 0) const; + + /** create scaled copy of current image object (given by scaling factors). + * memory is not handled internally - must be deleted from calling program. + * + ** @param xfactor width of new image is multiplied with this factor (> 0) + * @param yfactor height of new image is multiplied with this factor (> 0) + * @param interpolate specifies whether scaling algorithm should use interpolation (if necessary). + * default: no interpolation (0), preferred interpolation algorithm (if applicable): + * 1 = pbmplus algorithm, 2 = c't algorithm, 3 = bilinear magnification, + * 4 = bicubic magnification + * @param aspect specifies whether pixel aspect ratio should be taken into consideration + * (if true, width OR height should be 0, i.e. this component will be calculated + * automatically) + * + ** @return pointer to new DicomImage object (NULL if an error occurred) + */ + DicomImage *createScaledImage(const double xfactor, + const double yfactor = 0, + const int interpolate = 0, + const int aspect = 0) const; + + /** create scaled copy of specified (clipping) area of the current image object. + * memory is not handled internally - must be deleted from calling program. + * NB: Clipping and interpolated scaling at the same moment is not yet fully implemented! + * + ** @param left_pos x coordinate of top left corner of area to be scaled + * (referring to image origin, negative values create a border around the image) + * @param top_pos y coordinate of top left corner of area to be scaled + * @param clip_width width of area to be scaled + * @param clip_height height of area to be scaled + * @param scale_width width of scaled image (in pixels) + * @param scale_height height of scaled image (in pixels) + * @param interpolate specifies whether scaling algorithm should use interpolation (if necessary). + * default: no interpolation (0), preferred interpolation algorithm (if applicable): + * 1 = pbmplus algorithm, 2 = c't algorithm, 3 = bilinear magnification, + * 4 = bicubic magnification + * @param aspect specifies whether pixel aspect ratio should be taken into consideration + * (if true, width OR height should be 0, i.e. this component will be calculated + * automatically) + * @param pvalue P-value used for the border outside the image (0..65535) + * + ** @return pointer to new DicomImage object (NULL if an error occurred) + */ + DicomImage *createScaledImage(const signed long left_pos, + const signed long top_pos, + unsigned long clip_width, + unsigned long clip_height, + unsigned long scale_width = 0, + unsigned long scale_height = 0, + const int interpolate = 0, + int aspect = 0, + const Uint16 pvalue = 0) const; + + /** create scaled copy of specified (clipping) area of the current image object. + * memory is not handled internally - must be deleted from calling program. + * NB: Clipping and interpolated scaling at the same moment is not yet fully implemented! + * + ** @param left_pos x coordinate of top left corner of area to be scaled + * (referring to image origin, negative values create a border around the image) + * @param top_pos y coordinate of top left corner of area to be scaled + * @param width width of area to be scaled + * @param height height of area to be scaled + * @param xfactor width of new image is multiplied with this factor (> 0) + * @param yfactor height of new image is multiplied with this factor (> 0) + * @param interpolate specifies whether scaling algorithm should use interpolation (if necessary). + * default: no interpolation (0), preferred interpolation algorithm (if applicable): + * 1 = pbmplus algorithm, 2 = c't algorithm, 3 = bilinear magnification, + * 4 = bicubic magnification + * @param aspect specifies whether pixel aspect ratio should be taken into consideration + * (if true, width OR height should be 0, i.e. this component will be calculated + * automatically) + * @param pvalue P-value used for the border outside the image (0..65535) + * + ** @return pointer to new DicomImage object (NULL if an error occurred) + */ + DicomImage *createScaledImage(const signed long left_pos, + const signed long top_pos, + unsigned long width, + unsigned long height, + const double xfactor, + const double yfactor = 0, + const int interpolate = 0, + const int aspect = 0, + const Uint16 pvalue = 0) const; + + /** create copy of specified area of the current image object (clipping). + * memory is not handled internally - must be deleted from calling program. + * + ** @param left_pos x coordinate of top left corner of area to be copied + * (referring to image origin, negative values create a border around the image) + * @param top_pos y coordinate of top left corner of area to be copied + * @param width width of area to be copied/clipped + * @param height height of area to be copied/clipped + * @param pvalue P-value used for the border outside the image (0..65535) + * + ** @return pointer to new DicomImage object (NULL if an error occurred) + */ + DicomImage *createClippedImage(const signed long left_pos, + const signed long top_pos, + unsigned long width = 0, + unsigned long height = 0, + const Uint16 pvalue = 0) const; + + /** flip current image (horizontally and/or vertically) + * + ** @param horz flip horizontally if true + * @param vert flip vertically if true + * + ** @return true if successful (1 = flipped at least direction, + * 2 = not flipped, because of image resolution - width and/or height equal to 1), + * false otherwise + */ + int flipImage(int horz = 1, + int vert = 0) const; + + /** create a flipped copy of the current image. + * memory is not handled internally - must be deleted from calling program. + * + ** @param horz flip horizontally if true + * @param vert flip vertically if true + * + ** @return pointer to new DicomImage object (NULL if an error occurred) + */ + DicomImage *createFlippedImage(int horz = 1, + int vert = 0) const; + + /** rotate current image (by steps of 90 degrees) + * + ** @param degree angle by which the image shall be rotated (-360, -270, -180, -90, 0, 90, 180, 270, 360) + * + ** @return true if successful (1 = rotated by at least 90 degrees, + * 2 = not rotated, because of image resolution or angle), + * false otherwise + */ + int rotateImage(signed int degree) const; + + /** create a rotated copy of the current image. + * memory is not handled internally - must be deleted from calling program. + * + ** @param degree angle by which the image shall be rotated (-360, -270, -180, -90, 0, 90, 180, 270, 360) + * + ** @return pointer to new DicomImage object (NULL if an error occurred) + */ + DicomImage *createRotatedImage(signed int degree) const; + + /** create monochrome copy of the current image. + * equal to createDicomImage() for monochrome images. + * memory is not handled internally - must be deleted from calling program. + * This method does not work if original YCbCr color model is retained (see CIF_KeepYCbCrColorModel). + * + ** @param red coefficient by which the red component is weighted (default: NTSC value) + * @param green coefficient by which the green component is weighted (default: NTSC value) + * @param blue coefficient by which the blue component is weighted (default: NTSC value) + * + ** @return pointer to new DicomImage object (NULL if an error occurred) + */ + DicomImage *createMonochromeImage(const double red = 0.299, + const double green = 0.587, + const double blue = 0.114) const; + + /** create true color (24/32 bit) or palette (8 bit) bitmap for MS Windows. + * 8 bit images require an appropriate color palette (256 entries, values: 0 to 255) and are only + * applicable to monochrome images, the beginning of a each line starts on a 32-bit address (if + * 'padding' is true); 24 bit images store 24 bits per pixel (BGR) and do align each line to a + * 32-bit address (if 'padding' is true); 32 bit images store 32 bits per pixel (ARGB), but only + * use the lower 24 bits (-RGB). + * The memory buffer can be allocated both externally (from the calling program) and internally + * (inside this class/module). If the 'data' parameter is not NULL and the 'size' parameter, which + * describes the size (in bytes) of the allocated buffer, is sufficiently large, the bitmap is stored + * in this buffer. Otherwise (i.e. 'data' is NULL) the memory is allocated internally. Please note + * that in both cases the memory is not handled internally after this method has finished and, + * therefore, must be deleted from the calling program. + * This method does not work if original YCbCr color model is retained (see CIF_KeepYCbCrColorModel). + * + ** @param data untyped pointer memory buffer (set to NULL if not allocated externally) + * @param size size of the memory buffer in bytes (if 0 'data' is set to NULL) + * @param frame index of frame to be converted (default: 0 = first frame) + * @param bits number of bits per pixel used for the output bitmap (8, 24 or 32, default: 24) + * @param upsideDown flag indicating whether the first line stored is the top-most (default: 0) or + * the bottom-most of the source image (as required by the BMP file format) + * @param padding align each line to a 32-bit address if true (default) + * + ** @return number of bytes allocated by the bitmap, or 0 if an error occurred + */ + unsigned long createWindowsDIB(void *&data, + const unsigned long size, + const unsigned long frame = 0, + const int bits = 24, + const int upsideDown = 0, + const int padding = 1) + { + return (Image != NULL) ? + Image->createDIB(data, size, frame, bits, upsideDown, padding) : 0; + } + + /** create true color (32 bit) or palette (8 bit) bitmap for Java (AWT default format). + * 32 bit images allocate 32 bits per pixel (RGB), but only use the upper 24 bits. The sample + * order for color images is: Red, Green, Blue. + * Memory is not handled internally - must be deleted from calling program. + * This method does not work if original YCbCr color model is retained (see CIF_KeepYCbCrColorModel). + * + ** @param data resulting pointer to bitmap data (set to NULL if an error occurred) + * @param frame index of frame to be converted (default: 0 = first frame) + * @param bits number of bits per pixel used for the output bitmap (8 or 32, default: 32) + * + ** @return number of bytes allocated by the bitmap, or 0 if an error occurred + */ + unsigned long createJavaAWTBitmap(void *&data, + const unsigned long frame = 0, + const int bits = 32) + { + return (Image != NULL) ? + Image->createAWTBitmap(data, frame, bits) : 0; + } + + /** create 12 bit packed (monochrome) bitmap for DICOM printers. + * Memory is not handled internally - must be deleted from calling program. + * + ** @param buffer pointer to input memory buffer (16 bits allocated, 12 bits stored) + * @param size size of memory buffer (will be checked whether it is sufficient) + * @param count number of entries (pixels) in input buffer + * + ** @return pointer to memory buffer containing the packed output bitmap data (NULL if an error occurred) + */ + static void *create12BitPackedBitmap(const void *buffer, + const unsigned long size, + const unsigned long count) + { + return DiMonoImage::createPackedBitmap(buffer, size, count, 16, 12); + } + + /** create new single frame DicomImage with applied grayscale transformations. + * The method getOutputData() is used internally for the new bitmap. + * Limited to monochrome images. + * + ** @param frame index of frame to be converted + * @param bits number of bits per pixel used for the output bitmap + * + ** @return pointer to new DicomImage object (NULL if an error occurred) + */ + DicomImage *createMonoOutputImage(const unsigned long frame, + const int bits); + + // --- output image file: return true ('1') if successful + + /** render pixel data of the given frame and write image related attributes to DICOM dataset. + * Applies VOI/PLUT transformation and (visible) overlay planes, output data is + * always padded to 8, 16, 32, ... bits (bits allocated). Replaces any modality + * transformation in the dataset by a linear rescale/slope since the modality + * transformation is rendered into the pixel data. Replaces the VOI transformations + * in the dataset by a "max range" VOI window. Removes all Overlay Plane Module + * attributes for embedded overlay planes from the dataset. + * Writes the following DICOM attributes (from Image Pixel Module): + * - Photometric Interpretation, Samples per Pixel + * - Columns, Rows, Number of Frames + * - Bits Allocated, Bits Stored, High Bit + * - Planar Configuration (only if "Samples per Pixel" is greater than 1) + * - Pixel Representation, Pixel Data + * Updates the following DICOM attributes (if present in the original image dataset): + * - Pixel Spacing and/or Pixel Aspect Ratio + * Supported output color models: Monochrome 2 for monochrome images and RGB + * (or YCbCr_Full if flag CIF_KeepYCbCrColorModel is set) for color images. + * + ** @param dataset reference to DICOM dataset where the image attributes are stored + * @param bits number of bits per sample (image depth, 1..MAX_BITS) + * @param frame number of frame to be rendered (0..n-1) + * @param planar 0 = color-by-pixel (R1G1B1...R2G2B2...R3G3B3...), + * 1 = color-by-plane (R1R2R3...G1G2G3...B1B2B3...) + * (only applicable to multi-planar/color images, otherwise ignored) + * + ** @return true if successful, false otherwise + */ + inline int writeFrameToDataset(DcmItem &dataset, + const int bits = 0, + const unsigned long frame = 0, + const int planar = 0) + { + return (Image != NULL) ? + Image->writeFrameToDataset(dataset, frame, bits, planar) : 0; + } + + /** write current image and related attributes to DICOM dataset. + * Uses the internal representation of the pixel data, therefore the output data is + * always padded to 8, 16, 32, ... bits (bits allocated). Replaces any modality + * transformation in the dataset by a linear rescale/slope since the modality + * transformation is rendered into the pixel data. Removes all Overlay Plane Module + * attributes for embedded overlay planes from the dataset. + * Writes the following DICOM attributes (from Image Pixel Module): + * - Photometric Interpretation, Samples per Pixel + * - Columns, Rows, Number of Frames + * - Bits Allocated, Bits Stored, High Bit + * - Planar Configuration (only if "Samples per Pixel" is greater than 1) + * - Pixel Representation, Pixel Data + * Updates the following DICOM attributes (if present in the original image dataset): + * - Pixel Spacing and/or Pixel Aspect Ratio + * Supported output color models: Monochrome 1 or 2 for monochrome images and RGB + * (or YCbCr_Full if flag CIF_KeepYCbCrColorModel is set) for color images. + * + ** @param dataset reference to DICOM dataset where the image attributes are stored + * @param mode 0 = determine value of BitsStored from 'used' pixel values, + * 1 = determine value of BitsStored from 'possible' pixel values + * (used for monochrome images only) + * @param planar 0 = color-by-pixel (R1G1B1...R2G2B2...R3G3B3...), + * 1 = color-by-plane (R1R2R3...G1G2G3...B1B2B3...), + * 2 = same as original DICOM image (i.e. color-by-pixel or color-by-plane) + * (only applicable to multi-planar/color images, otherwise ignored) + * + ** @return true if successful, false otherwise + */ + inline int writeImageToDataset(DcmItem &dataset, + const int mode = 0, + const int planar = 2) + { + return (Image != NULL) ? + Image->writeImageToDataset(dataset, mode, planar) : 0; + } + + /** write pixel data to PPM file (specified by filename). + * pixel data is written in ASCII format. + * This method does not work if original YCbCr color model is retained + * (see CIF_KeepYCbCrColorModel). + * + ** @param filename name of output file (%d is replaced by frame number if present) + * @param bits number of bits used for output of pixel data + * (default: full resolution, max: 32; + * MI_PastelColor = -1 for true color pastel mode, EXPERIMENTAL) + * @param frame index of frame used for output (default: first frame = 0) + * + ** @return true if successful, false otherwise + */ + int writePPM(const char *filename, + const int bits = 0, + const unsigned long frame = 0); + + /** write pixel data to PPM file (specified by open C++ stream). + * pixel data is written in ASCII format. + * This method does not work if original YCbCr color model is retained + * (see CIF_KeepYCbCrColorModel). + * + ** @param stream open C++ output stream + * @param bits number of bits used for output of pixel data + * (default: full resolution, max: 32; + * MI_PastelColor = -1 for true color pastel mode, EXPERIMENTAL) + * @param frame index of frame used for output (default: first frame = 0) + * + ** @return true if successful, false otherwise + */ + int writePPM(STD_NAMESPACE ostream& stream, + const int bits = 0, + const unsigned long frame = 0); + + /** write pixel data to PPM file (specified by open C stream). + * pixel data is written in ASCII format. + * This method does not work if original YCbCr color model is retained + * (see CIF_KeepYCbCrColorModel). + * + ** @param stream open C output stream + * @param bits number of bits used for output of pixel data + * (default: full resolution, max: 32; + * MI_PastelColor = -1 for true color pastel mode, EXPERIMENTAL) + * @param frame index of frame used for output (default: first frame = 0) + * + ** @return true if successful, false otherwise + */ + int writePPM(FILE *stream, + const int bits = 0, + const unsigned long frame = 0); + + /** write pixel data to raw PPM file (specified by filename). + * pixel data is written in binary format. + * This method does not work if original YCbCr color model is retained + * (see CIF_KeepYCbCrColorModel). + * + ** @param filename name of output file (%d is replaced by frame number if present) + * @param bits number of bits used for output of pixel data + * (default: full resolution, max: 8; + * MI_PastelColor = -1 for true color pastel mode, EXPERIMENTAL) + * @param frame index of frame used for output (default: first frame = 0) + * + ** @return true if successful, false otherwise + */ + int writeRawPPM(const char *filename, + const int bits = 0, + const unsigned long frame= 0); + + /** write pixel data to raw PPM file (specified by open C stream). + * pixel data is written in binary format. + * This method does not work if original YCbCr color model is retained + * (see CIF_KeepYCbCrColorModel). + * + ** @param stream open C output stream (binary mode required!) + * @param bits number of bits used for output of pixel data + * (default: full resolution, max: 8; + * MI_PastelColor = -1 for true color pastel mode, EXPERIMENTAL) + * @param frame index of frame used for output (default: first frame = 0) + * + ** @return true if successful, false otherwise + */ + int writeRawPPM(FILE *stream, + const int bits = 0, + const unsigned long frame = 0); + + /** write pixel data to BMP file (specified by open C stream). + * pixel data is written in palette or truecolor mode. + * This method does not work if original YCbCr color model is retained + * (see CIF_KeepYCbCrColorModel). + * + ** @param stream open C output stream (binary mode required!) + * @param bits number of bits used for output of pixel data + * (8, 24 or 32, default (0): 8 for monochrome and 24 for color images) + * @param frame index of frame used for output (default: first frame = 0) + * + ** @return true if successful, false otherwise + */ + int writeBMP(FILE *stream, + const int bits = 0, + const unsigned long frame = 0); + + /** write pixel data to BMP file (specified by filename). + * pixel data is written in palette or truecolor mode. + * This method does not work if original YCbCr color model is retained + * (see CIF_KeepYCbCrColorModel). + * + ** @param filename name of output file (%d is replaced by frame number if present) + * @param bits number of bits used for output of pixel data + * (8, 24 or 32, default (0): 8 for monochrome and 24 for color images) + * @param frame index of frame used for output (default: first frame = 0) + * + ** @return true if successful, false otherwise + */ + int writeBMP(const char *filename, + const int bits = 0, + const unsigned long frame = 0); + + /** write pixel data to pluggable image format file (specified by open C stream). + * Format specific parameters may be set directly in the instantiated 'plugin' class. + * + ** @param plugin pointer to image format plugin (derived from abstract class DiPluginFormat) + * @param stream open C output stream (binary mode required!) + * @param frame index of frame used for output (default: first frame = 0) + * + ** @return true if successful, false otherwise + */ + int writePluginFormat(const DiPluginFormat *plugin, + FILE *stream, + const unsigned long frame = 0); + + /** write pixel data to pluggable image format file (specified by filename). + * Format specific parameters may be set directly in the instantiated 'plugin' class. + * + ** @param plugin pointer to image format plugin (derived from abstract class DiPluginFormat) + * @param filename name of output file (%d is replaced by frame number if present) + * @param frame index of frame used for output (default: first frame = 0) + * + ** @return true if successful, false otherwise + */ + int writePluginFormat(const DiPluginFormat *plugin, + const char *filename, + const unsigned long frame = 0); + + + protected: + + /** constructor, create copy of given image object with different image data and photometric interpretation + * + ** @param dicom source object to be copied + * @param image new image data + * @param interpret new photometric interpretation + */ + DicomImage(const DicomImage *dicom, + DiImage *image, + const EP_Interpretation interpret = EPI_Unknown); + + /** initialize object. + * create internal image object depending on color model. is used for all 'real' constructors. + */ + void Init(); + + /** check whether data dictionary is present + * + ** @return true if dictionary is present, false otherwise + */ + int checkDataDictionary(); + + /** get SOP class UID of current image object + * + ** @return SOP class UID (or NULL if an error occurred) + */ + const char *getSOPclassUID() const; + + /** normalize given degree value (for internal use). + * negative value are mapped to positive range (-360 -> 0, -270 -> 90, -180 -> 180, -90 -> 270), + * 360 is set to 0, all other values are rejected + * + ** @param degree value to be normalized, valid values are: 0, 90, 180, 270 + * + ** @return true if successful, false otherwise (invalid value) + */ + int normalizeDegreeValue(signed int °ree) const; + + + private: + + /// current state of converting progress (error level) + EI_Status ImageStatus; + /// DICOM color model (enumeration) + EP_Interpretation PhotometricInterpretation; + + /// points to document object + DiDocument *Document; + /// points to image object + DiImage *Image; + + // --- declarations to avoid compiler warnings + + DicomImage(const DicomImage &); + DicomImage &operator=(const DicomImage &); +}; + + +#endif diff --git a/dcmimgle/include/dcmtk/dcmimgle/dibaslut.h b/dcmimgle/include/dcmtk/dcmimgle/dibaslut.h new file mode 100644 index 00000000..55368d18 --- /dev/null +++ b/dcmimgle/include/dcmtk/dcmimgle/dibaslut.h @@ -0,0 +1,310 @@ +/* + * + * Copyright (C) 1996-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimgle + * + * Author: Joerg Riesmeier + * + * Purpose: DicomBaseLUT (Header) + * + */ + + +#ifndef DIBASLUT_H +#define DIBASLUT_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/ofstd/ofstring.h" +#include "dcmtk/ofstd/ofcast.h" + +#include "dcmtk/dcmimgle/diutils.h" + + +/*---------------------* + * macro definitions * + *---------------------*/ + +#define MIN_TABLE_ENTRY_SIZE 8 +#define MAX_TABLE_ENTRY_SIZE 16 +#define MAX_TABLE_ENTRY_COUNT 65536 + + +/*---------------------* + * class declaration * + *---------------------*/ + +/** Base class to handle look-up tables + */ +class DCMTK_DCMIMGLE_EXPORT DiBaseLUT +{ + + public: + + /** constructor + * + ** @param count number of LUT entries + * @param bits number of bits per entry + */ + DiBaseLUT(const Uint32 count = 0, + const Uint16 bits = 0); + + /** destructor + */ + virtual ~DiBaseLUT(); + + /** get number of LUT entries + * + ** @return number of LUT entries + */ + inline Uint32 getCount() const + { + return Count; + } + + /** get number of bits per entry + * + ** @return number of bits per entry + */ + inline Uint16 getBits() const + { + return Bits; + } + + /** get index of first LUT entry. + * First input value mapped (FIV) in LUT descriptor is US -> 16 bit unsigned. + * ... or the previous pixel transformation requires an unsigned LUT input value. + * + ** (#)param dummy (used to distinguish between signed and unsigned methods) + * + ** @return index of first LUT entry + */ + inline Uint32 getFirstEntry(const Uint32 = 0) const + { + return FirstEntry; + } + + /** get index of first LUT entry. + * First input value mapped (FIV) in LUT descriptor is SS -> 16 bit signed. + * ... or the previous pixel transformation requires a signed LUT input value. + * + ** (#)param dummy (used to distinguish between signed and unsigned methods) + * + ** @return index of first LUT entry + */ + inline Sint32 getFirstEntry(const Sint32) const + { + return OFstatic_cast(Sint16, FirstEntry); + } + + /** get index of last LUT entry. + * FIV in LUT descriptor is US -> 16 bit unsigned. + * ... or the previous pixel transformation requires an unsigned LUT input value. + * + ** (#)param dummy (used to distinguish between signed and unsigned methods) + * + ** @return index of last LUT entry + */ + inline Uint32 getLastEntry(const Uint32 = 0) const + { + return FirstEntry + Count - 1; + } + + /** get index of last LUT entry. + * FIV in LUT descriptor is SS -> 16 bit signed. + * ... or the previous pixel transformation requires a signed LUT input value. + * + ** (#)param dummy (used to distinguish between signed and unsigned methods) + * + ** @return index of first LUT entry + */ + inline Sint32 getLastEntry(const Sint32) const + { + return OFstatic_cast(Sint32, OFstatic_cast(Sint16, FirstEntry)) + Count - 1; + } + + /** get value of specified LUT entry + * + ** @param pos position in the LUT to be returned + * + ** @return value of specified LUT entry + */ + inline Uint16 getValue(const Uint16 pos) const + { + return Data[pos]; + } + + /** get value of specified LUT entry. + * FIV in LUT descriptor is US -> 16 bit unsigned. + * ... or the previous pixel transformation requires an unsigned LUT input value. + * + ** @param pos position in the LUT to be returned + * + ** @return value of specified LUT entry + */ + inline Uint16 getValue(const Uint32 pos) const + { + return Data[pos - FirstEntry]; + } + + /** get value of specified LUT entry. + * FIV in LUT descriptor is SS -> 16 bit signed. + * ... or the previous pixel transformation requires a signed LUT input value. + * + ** @param pos position in the LUT to be returned + * + ** @return value of specified LUT entry + */ + inline Uint16 getValue(const Sint32 pos) const + { + return Data[pos - OFstatic_cast(Sint32, OFstatic_cast(Sint16, FirstEntry))]; + } + + /** get value of first LUT entry. + * + ** @return value of first LUT entry + */ + inline Uint16 getFirstValue() const + { + return Data[0]; + } + + /** get value of last LUT entry. + * + ** @return value of last LUT entry + */ + inline Uint16 getLastValue() const + { + return Data[Count - 1]; + } + + /** get pointer to LUT data + * + ** @return pointer to LUT data + */ + inline const Uint16 *getData() const + { + return Data; + } + + /** get minimum value of the LUT. + * + ** @return minimum value of the LUT + */ + inline Uint16 getMinValue() const + { + return MinValue; + } + + /** get maximum value of the LUT. + * + ** @return maximum value of the LUT + */ + inline Uint16 getMaxValue() const + { + return MaxValue; + } + + /** get absolute value range of the LUT entries. + * The maximum value which could be stored with the specified bit depth is calculated. + * + ** @return absolute range of LUT entries + */ + inline Uint32 getAbsMaxRange() const + { + return DicomImageClass::maxval(Bits, 0); + } + + /** check whether LUT is valid + * + ** @return status, true if valid, false otherwise + */ + inline int isValid() const + { + return Valid; + } + + /** get LUT explanation string + * + ** @return LUT explanation string if successful, NULL otherwise + */ + inline const char *getExplanation() const + { + return (Explanation.empty()) ? OFstatic_cast(const char *, NULL) : Explanation.c_str(); + } + + /** compares current LUT with specified LUT + * + ** @param lut LUT to be compared with the current one + * + ** @return OFTrue if LUTs are equal, OFFalse otherwise + */ + virtual OFBool operator==(const DiBaseLUT &lut); + + + protected: + + /** constructor + * + ** @param buffer pointer to array with LUT entries + * @param count number of LUT entries + * @param bits number of bits per entry + */ + DiBaseLUT(Uint16 *buffer, + const Uint32 count = 0, + const Uint16 bits = 0); + + /** compares current LUT with specified LUT + * + ** @param lut LUT to be compared with the current one + * + ** @return true if LUTs are not equal (1 = invalid LUT, + * 2 = descriptor differs, + * 3 = data differs) + * false (0) otherwise + */ + int compare(const DiBaseLUT *lut); + + /// number of LUT entries + Uint32 Count; + /// first input value mapped (FIV) + Uint16 FirstEntry; + /// number of bits per entry + Uint16 Bits; + + /// minimum LUT value + Uint16 MinValue; + /// maximum LUT value + Uint16 MaxValue; + + /// status code, indicating whether LUT is valid + int Valid; + + /// LUT explanation string + OFString Explanation; + + /// pointer to lookup table data + const Uint16 *Data; + /// pointer to data buffer (will be deleted in the destructor) + Uint16 *DataBuffer; + + + private: + + // --- declarations to avoid compiler warnings + + DiBaseLUT(const DiBaseLUT &); + DiBaseLUT &operator=(const DiBaseLUT &); +}; + + +#endif diff --git a/dcmimgle/include/dcmtk/dcmimgle/diciefn.h b/dcmimgle/include/dcmtk/dcmimgle/diciefn.h new file mode 100644 index 00000000..632c0d39 --- /dev/null +++ b/dcmimgle/include/dcmtk/dcmimgle/diciefn.h @@ -0,0 +1,145 @@ +/* + * + * Copyright (C) 1998-2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimgle + * + * Author: Joerg Riesmeier + * + * Purpose: DicomCIELABFunction (Header) + * + */ + + +#ifndef DICIEFN_H +#define DICIEFN_H + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/dcmimgle/didispfn.h" +#include "dcmtk/dcmimgle/dicielut.h" + + +/*---------------------* + * class declaration * + *---------------------*/ + +/** Class to manage CIELAB LUTs (for calibration) + */ +class DCMTK_DCMIMGLE_EXPORT DiCIELABFunction + : public DiDisplayFunction +{ + + public: + + /** constructor, read device characteristics file. + * Keywords: "max" for maximum DDL (Digital Driving Level, required at first position) + * "amb" for ambient light and "lum" for illumination (both optional) + * "ord" for the order of the polynomial curve fitting algorithm used to interpolate + * the given base points (0 or absent = use cubic spline interpolation) + * + ** @param filename name of the characteristics file (luminance/OD for each DDL) + * @param deviceType type of the output device (default: monitor) + * @param ord order of the polynomial curve fitting algorithm used to interpolate + * the given base points (-1 = use file setting, 0 = cubic spline) + */ + DiCIELABFunction(const char *filename, + const E_DeviceType deviceType = EDT_Monitor, + const signed int ord = -1); + + /** constructor, use given array of luminance/OD values. UNTESTED + * Values must be sorted and complete (i.e. there must be an entry for each DDL) + * The given arrays are copied internally. + * + ** @param val_tab pointer to array with luminance/OD values + * @param count number of array elements (should be equal to 'max + 1') + * @param max maximum DDL (digital driving level) + * @param deviceType type of the output device (default: monitor) + * @param ord order of the polynomial curve fitting algorithm used to interpolate + * the given base points (0 or negative = use cubic spline interpolation) + */ + DiCIELABFunction(const double *val_tab, + const unsigned long count, + const Uint16 max = 255, + const E_DeviceType deviceType = EDT_Monitor, + const signed int ord = 0); + + /** constructor, use given array of DDL and luminance values. UNTESTED + * Values will be automatically sorted and missing values will be interpolated. + * The given arrays are copied internally. + * + ** @param ddl_tab pointer to array with DDL values (must be with the interval 0..max) + * @param val_tab pointer to array with luminance/OD values + * @param count number of array elements (2..65536) + * @param max maximum DDL (digital driving level) + * @param deviceType type of the output device (default: monitor) + * @param ord order of the polynomial curve fitting algorithm used to interpolate + * the given base points (0 or negative = use cubic spline interpolation) + */ + DiCIELABFunction(const Uint16 *ddl_tab, + const double *val_tab, + const unsigned long count, + const Uint16 max = 255, + const E_DeviceType deviceType = EDT_Monitor, + const signed int ord = 0); + + /** constructor, compute luminance/OD values automatically within the specified range. + * + ** @param val_min minimum luminance/OD value + * @param val_max maximum luminance/OD value + * @param count number of DDLs (digital driving level, 1..65536)) + * @param deviceType type of the output device (default: monitor) + * @param ord order of the polynomial curve fitting algorithm used to interpolate + * the given base points (0 or negative = use cubic spline interpolation) + */ + DiCIELABFunction(const double val_min, + const double val_max, + const unsigned long count = 256, + const E_DeviceType deviceType = EDT_Monitor, + const signed int ord = 0); + + /** destructor + */ + virtual ~DiCIELABFunction(); + + /** write curve data to a text file + * + ** @param filename name of the text file to which the data should be written + * @param mode write CC and PSC to file if OFTrue + * + ** @return status, true if successful, false otherwise + */ + int writeCurveData(const char *filename, + const OFBool mode = OFTrue); + + + protected: + + /** create CIELAB LUT with specified number of entries + * + ** @param count number of LUT entries + * + ** @return pointer to created LUT if successful, NULL otherwise + */ + DiDisplayLUT *getDisplayLUT(unsigned long count); + + + private: + + // --- declarations to avoid compiler warnings + + DiCIELABFunction(const DiDisplayFunction &); + DiCIELABFunction &operator=(const DiDisplayFunction &); +}; + + +#endif diff --git a/dcmimgle/include/dcmtk/dcmimgle/dicielut.h b/dcmimgle/include/dcmtk/dcmimgle/dicielut.h new file mode 100644 index 00000000..26eb2f66 --- /dev/null +++ b/dcmimgle/include/dcmtk/dcmimgle/dicielut.h @@ -0,0 +1,108 @@ +/* + * + * Copyright (C) 1996-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimgle + * + * Author: Joerg Riesmeier + * + * Purpose: DicomCIELABLUT (Header) + * + */ + + +#ifndef DICIELUT_H +#define DICIELUT_H + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/dcmimgle/didislut.h" + + +/*---------------------* + * class declaration * + *---------------------*/ + +/** Class to compute and store the CIELAB lookup table + */ +class DCMTK_DCMIMGLE_EXPORT DiCIELABLUT + : public DiDisplayLUT +{ + + public: + + /** constructor + * + ** @param count number of values to be stored in the LUT + * @param max maximum value to be stored in the LUT + * @param ddl_tab array of DDL values + * @param val_tab array of values + * @param ddl_cnt number of DDL values + * @param val_min minimum value in the array + * @param val_max maximum value in the array + * @param lum_min minimum luminance value to be used (lower border) + * @param lum_max maximum luminance value to be used (upper border) + * @param amb ambient light value + * @param inverse apply inverse transformation if OFTrue + * @param stream output stream (used to write curve data to a file) + * @param printMode write CC and PSC to stream if OFTrue + */ + DiCIELABLUT(const unsigned long count, + const Uint16 max, + const Uint16 *ddl_tab, + const double *val_tab, + const unsigned long ddl_cnt, + const double val_min, + const double val_max, + const double lum_min, + const double lum_max, + const double amb, + const OFBool inverse = OFFalse, + STD_NAMESPACE ostream *stream = NULL, + const OFBool printMode = OFTrue); + + /** destructor + */ + virtual ~DiCIELABLUT(); + + + protected: + + /** create lookup table + * + ** @param ddl_tab array of DDL values + * @param val_tab array of values + * @param ddl_cnt number of DDL values + * @param val_min minimum value in the array + * @param val_max maximum value in the array + * @param lum_min minimum luminance value to be used (lower border) + * @param lum_max maximum luminance value to be used (upper border) + * @param inverse apply inverse transformation if OFTrue + * @param stream output stream (used to write curve data to a file) + * @param printMode write CC and PSC to stream if OFTrue + * + ** @return status, true if successful, false otherwise + */ + int createLUT(const Uint16 *ddl_tab, + const double *val_tab, + const unsigned long ddl_cnt, + const double val_min, + const double val_max, + const double lum_min, + const double lum_max, + const OFBool inverse = OFFalse, + STD_NAMESPACE ostream *stream = NULL, + const OFBool printMode = OFTrue); +}; + + +#endif diff --git a/dcmimgle/include/dcmtk/dcmimgle/dicrvfit.h b/dcmimgle/include/dcmtk/dcmimgle/dicrvfit.h new file mode 100644 index 00000000..b4e5575b --- /dev/null +++ b/dcmimgle/include/dcmtk/dcmimgle/dicrvfit.h @@ -0,0 +1,325 @@ +/* + * + * Copyright (C) 1996-2010, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimgle + * + * Author: Joerg Riesmeier + * + * Purpose: DiCurveFitting (header/implementation) + * + */ + + +#ifndef DICRVFIT_H +#define DICRVFIT_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/ofstd/oftypes.h" +#include "dcmtk/ofstd/ofcast.h" + +#define INCLUDE_CMATH +#define INCLUDE_CSTDDEF /* For NULL */ +#include "dcmtk/ofstd/ofstdinc.h" + + +/*---------------------* + * macro definitions * + *---------------------*/ + +// SunCC 4.x does not support default values for template types :-/ +#define T3_ double + + +/*------------------* + * template class * + *------------------*/ + +/** Template class for polynomial curve fitting algorithm + */ +template +class DiCurveFitting +{ + + public: + + /** calculate coefficients for resulting polynomial function. + * T1 = type of x coordinates + * T2 = type of y coordinates + * T3_ = type of coefficients (and for internal calculations) + * + ** @param x array with x coordinates of given points + * @param y array with y coordinates of given points + * @param n number of entries in array (= points) + * @param o order of polynomial function + * @param c array to store the resulting coefficients (o+1 entries !) + * + ** @return true if successful, false otherwise + */ + static int calculateCoefficients(const T1 *x, + const T2 *y, + const unsigned int n, + const unsigned int o, + T3_ *c) + { + int result = 0; + if ((x != NULL) && (y != NULL) && (c !=NULL) && (n > 0)) + { + const unsigned int order = o + 1; + const unsigned int order2 = order * order; + T3_ *basis = new T3_[order * n]; + T3_ *alpha = new T3_[order2]; + T3_ *beta = new T3_[order]; + if ((basis != NULL) && (alpha != NULL) && (beta != NULL)) + { + register unsigned int i; + register unsigned int j; + register unsigned int k; + for (i = 0; i < order; ++i) + { + for (j = 0; j < n; ++j) + { + k = i + j * order; + if (i == 0) + basis[k] = 1; + else + basis[k] = OFstatic_cast(T3_, x[j]) * basis[k - 1]; + } + } + T3_ sum; + for (i = 0; i < order; ++i) + { + const unsigned int i_order = i * order; + for (j = 0; j <= i; ++j) + { + sum = 0; + for (k = 0; k < n; ++k) + sum += basis[i + k * order] * basis[j + k * order]; + alpha[i + j * order] = sum; + if (i != j) + alpha[j + i_order] = sum; + } + } + for (i = 0; i < order; ++i) + { + sum = 0; + for (j = 0; j < n; ++j) + sum += OFstatic_cast(T3_, y[j]) * basis[i + j * order]; + beta[i] = sum; + } + if (solve(alpha, beta, order)) + { + for (i = 0; i < order; ++i) + c[i] = beta[i]; + result = 1; + } + } + delete[] basis; + delete[] alpha; + delete[] beta; + } + return result; + } + + + /** calculate y coordinates for the given range of x coordinates. + * The polynomial function is defined by the specified coefficients. + * T1 = type of x coordinates + * T2 = type of y coordinates + * T3_ = type of coefficients (and for internal calculations) + * + ** @param xs first x coordinate for computation + * @param xe last x coordinate for computation + * @param y array to store the resulting y coordinates (n entries !) + * @param n number of entries in array (= points) + * @param o order of polynomial function + * @param c array of coefficients computed by the above method (o+1 entries !) + * + ** @return true if successful, false otherwise + */ + static int calculateValues(const T1 xs, + const T1 xe, + T2 *y, + const unsigned int n, + const unsigned int o, + const T3_ *c) + { + int result = 0; + if ((y != NULL) && (c != NULL) && (n > 0) && (xe > xs)) + { + register unsigned int i; + register unsigned int j; + T3_ x; + T3_ x2; + T3_ w; + const T3_ xo = OFstatic_cast(T3_, xs); + const T3_ xi = OFstatic_cast(T3_, (OFstatic_cast(T3_, xe) - OFstatic_cast(T3_, xs)) / (n - 1)); + for (i = 0; i < n; ++i) + { + x = xo + OFstatic_cast(T3_, i) * xi; + x2 = 1; + w = 0; + for (j = 0; j <= o; ++j) + { + w += c[j] * x2; + x2 *= x; + } + convertValue(w, y[i]); // cut value if necessary + } + result = 1; + } + return result; + } + + + private: + + /** helper routine: convert to unsigned 8 bit value + * + ** @param input input value to be converted + * @param output output value (range: 0..255) + * + ** @return output value + */ + static void convertValue(const T3_ input, Uint8 &output) + { + output = (input <= 0) ? 0 : ((input >= 255) ? 255 : OFstatic_cast(Uint8, input)); + } + + /** helper routine: convert to signed 8 bit value + * + ** @param input input value to be converted + * @param output output value (range: -128..127) + * + ** @return output value + */ + static void convertValue(const T3_ input, Sint8 &output) + { + output = (input <= -128) ? -128 : ((input >= 127) ? 127 : OFstatic_cast(Sint8, input)); + } + + /** helper routine: convert to unsigned 16 bit value + * + ** @param input input value to be converted + * @param output output value (range: 0..65535) + * + ** @return output value + */ + static void convertValue(const T3_ input, Uint16 &output) + { + output = (input <= 0) ? 0 : ((input >= 65535) ? 65535 : OFstatic_cast(Uint16, input)); + } + + /** helper routine: convert to signed 16 bit value + * + ** @param input input value to be converted + * @param output output value (range: -32768..32767) + * + ** @return output value + */ + static void convertValue(const T3_ input, Sint16 &output) + { + output = (input <= -32768) ? -32768 : ((input >= 32767) ? 32767 : OFstatic_cast(Sint16, input)); + } + + /** helper routine: convert to floating point value (double precision) + * + ** @param input input value to be converted + * @param output output value (double) + * + ** @return output value + */ + static inline void convertValue(const T3_ input, double &output) + { + output = OFstatic_cast(double, input); + } + + /** solve the equation given by the two matrixes. + * T3_ = type of coefficients (and for internal calculations) + * + ** @param a first matrix (array of values) + * @param b second matrix (array of values) + * @param n number of entries in array + * + ** @return true if successful, false otherwise + */ + static int solve(T3_ *a, + T3_ *b, + const unsigned int n) + { + int result = 0; + if ((a != NULL) && (b != NULL) && (n > 0)) + { + register unsigned int i; + register unsigned int j; + register unsigned int k; + signed int pivot; + T3_ mag; + T3_ mag2; + T3_ temp; + for (i = 0; i < n; ++i) + { + mag = 0; + pivot = -1; + for (j = i; j < n; ++j) + { + mag2 = fabs(a[i + j * n]); + if (mag2 > mag) + { + mag = mag2; + pivot = j; + } + } + if ((pivot == -1) || (mag == 0)) + break; + else + { + const unsigned int piv = OFstatic_cast(unsigned int, pivot); + const unsigned int i_n = i * n; + if (piv != i) + { + const unsigned int piv_n = piv * n; + for (j = i; j < n; ++j) + { + temp = a[j + i_n]; + a[j + i_n] = a[j + piv_n]; + a[j + piv_n] = temp; + } + temp = b[i]; + b[i] = b[piv]; + b[piv] = temp; + } + mag = a[i + i_n]; + for (j = i; j < n; ++j) + a[j + i_n] /= mag; + b[i] /= mag; + for (j = 0; j < n; ++j) + { + if (i == j) + continue; + const unsigned int j_n = j * n; + mag2 = a[i + j_n]; + for (k = i; k < n; ++k) + a[k + j_n] -= mag2 * a[k + i_n]; + b[j] -= mag2 * b[i]; + } + result = 1; + } + + } + } + return result; + } +}; + + +#endif diff --git a/dcmimgle/include/dcmtk/dcmimgle/didefine.h b/dcmimgle/include/dcmtk/dcmimgle/didefine.h new file mode 100644 index 00000000..6dce8579 --- /dev/null +++ b/dcmimgle/include/dcmtk/dcmimgle/didefine.h @@ -0,0 +1,38 @@ +/* + * + * Copyright (C) 2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimgle + * + * Author: Uli Schlachter + * + * Purpose: Contains preprocessor definitions + * + */ + + +#ifndef DIDEFINE_H +#define DIDEFINE_H + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/ofstd/ofdefine.h" + + +#ifdef dcmimgle_EXPORTS +#define DCMTK_DCMIMGLE_EXPORT DCMTK_DECL_EXPORT +#else +#define DCMTK_DCMIMGLE_EXPORT DCMTK_DECL_IMPORT +#endif + + +#endif diff --git a/dcmimgle/include/dcmtk/dcmimgle/didislut.h b/dcmimgle/include/dcmtk/dcmimgle/didislut.h new file mode 100644 index 00000000..c3cc406b --- /dev/null +++ b/dcmimgle/include/dcmtk/dcmimgle/didislut.h @@ -0,0 +1,87 @@ +/* + * + * Copyright (C) 1996-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimgle + * + * Author: Joerg Riesmeier + * + * Purpose: DicomDisplayLUT (Header) + * + */ + + +#ifndef DIDISLUT_H +#define DIDISLUT_H + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/dcmimgle/dibaslut.h" + + +/*---------------------* + * class declaration * + *---------------------*/ + +/** Class to compute and store the Display lookup table + */ +class DCMTK_DCMIMGLE_EXPORT DiDisplayLUT + : public DiBaseLUT +{ + + public: + + /** constructor + * + ** @param count number of values to be stored + * @param max maximum value to be stored + * @param amb ambient light value + * @param illum illumination value (optional) + */ + DiDisplayLUT(const unsigned long count, + const Uint16 max, + const double amb, + const double illum = 0); + + /** destructor + */ + virtual ~DiDisplayLUT(); + + /** get ambient light value + * + ** @return ambient light value + */ + inline double getAmbientLightValue() const + { + return AmbientLight; + } + + /** get illumination value + * + ** @return illumination value + */ + inline double getIlluminationValue() const + { + return Illumination; + } + + + private: + + /// ambient light value (measured in cd/m^2) + const double AmbientLight; + /// illumination value (measured in cd/m^2) + const double Illumination; +}; + + +#endif diff --git a/dcmimgle/include/dcmtk/dcmimgle/didispfn.h b/dcmimgle/include/dcmtk/dcmimgle/didispfn.h new file mode 100644 index 00000000..a170c5f1 --- /dev/null +++ b/dcmimgle/include/dcmtk/dcmimgle/didispfn.h @@ -0,0 +1,487 @@ +/* + * + * Copyright (C) 1998-2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimgle + * + * Author: Joerg Riesmeier + * + * Purpose: DicomDisplayFunction (Header) + * + */ + + +#ifndef DIDISPFN_H +#define DIDISPFN_H + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/ofstd/oftypes.h" + +#include "dcmtk/dcmimgle/didefine.h" + +/*------------------------* + * forward declarations * + *------------------------*/ + +class DiDisplayLUT; + + +/*---------------------* + * macro definitions * + *---------------------*/ + +#define MAX_DISPLAY_FUNCTIONS 2 +#define MAX_NUMBER_OF_TABLES 15 +#define WIDTH_OF_PVALUES 16 + + +/*---------------------* + * class declaration * + *---------------------*/ + +/** Class to handle hardcopy and softcopy device characteristics file + * and manage display LUTs (for calibration) + */ +class DCMTK_DCMIMGLE_EXPORT DiDisplayFunction +{ + + public: + + /** output device type + */ + enum E_DeviceType + { + /// monitor (softcopy output device), values expected to be in luminance (cd/m^2) + EDT_Monitor, + /// camera (softcopy input device), values expected to be in luminance (cd/m^2) + EDT_Camera, + /// printer (hardcopy output device), values expected to be in optical density (OD) + EDT_Printer, + /// scanner (hardcopy input device), values expected to be in optical density (OD) + EDT_Scanner + }; + + /** constructor, read device characteristics file. + * Keywords: "max" for maximum DDL (digital driving level, required at first position) + * "amb" for ambient light and "lum" for illumination (both optional) + * "ord" for the order of the polynomial curve fitting algorithm used to interpolate + * the given base points (0 or absent = use cubic spline interpolation) + * + ** @param filename name of the characteristics file (luminance/OD for each DDL) + * @param deviceType type of the output device (default: monitor) + * @param ord order of the polynomial curve fitting algorithm used to interpolate + * the given base points (-1 = use file setting, 0 = cubic spline) + */ + DiDisplayFunction(const char *filename, + const E_DeviceType deviceType = EDT_Monitor, + const signed int ord = -1); + + /** constructor, use given array of luminance/OD values. UNTESTED + * Values must be sorted and complete (i.e. there must be an entry for each DDL). + * The given arrays are copied internally. + * + ** @param val_tab pointer to array with luminance/OD values + * @param count number of array elements (should be equal to 'max + 1') + * @param max maximum DDL (digital driving level) + * @param deviceType type of the output device (default: monitor) + * @param ord order of the polynomial curve fitting algorithm used to interpolate + * the given base points (0 or negative = use cubic spline interpolation) + */ + DiDisplayFunction(const double *val_tab, + const unsigned long count, + const Uint16 max = 255, + const E_DeviceType deviceType = EDT_Monitor, + const signed int ord = 0); + + /** constructor, use given array of DDL and luminance/OD values. UNTESTED + * Values will be automatically sorted and missing values will be interpolated. + * The given arrays are copied internally. + * + ** @param ddl_tab pointer to array with DDL values (must be with the interval 0..max) + * @param val_tab pointer to array with luminance/OD values + * @param count number of array elements (2..65536) + * @param max maximum DDL (digital driving level) + * @param deviceType type of the output device (default: monitor) + * @param ord order of the polynomial curve fitting algorithm used to interpolate + * the given base points (0 or negative = use cubic spline interpolation) + */ + DiDisplayFunction(const Uint16 *ddl_tab, + const double *val_tab, + const unsigned long count, + const Uint16 max = 255, + const E_DeviceType deviceType = EDT_Monitor, + const signed int ord = 0); + + /** constructor, compute luminance/OD values automatically within the specified range. + * Initial values for hardcopy: "lum" = 2000, "amb" = 10, for softcopy: "amb" = 0. + * + ** @param val_min minimum luminance/OD value + * @param val_max maximum luminance/OD value + * @param count number of DDLs (digital driving level, 1..65536) + * @param deviceType type of the output device (default: monitor) + * @param ord order of the polynomial curve fitting algorithm used to interpolate + * the given base points (0 or negative = use cubic spline interpolation) + */ + DiDisplayFunction(const double val_min, + const double val_max, + const unsigned long count = 256, + const E_DeviceType deviceType = EDT_Monitor, + const signed int ord = 0); + + /** destructor + */ + virtual ~DiDisplayFunction(); + + /** check whether DisplayFunction is valid + * + ** @return status, true if valid, false otherwise + */ + inline int isValid() const + { + return Valid; + } + + /** get output device type (monitor, camera, printer or scanner) + * + ** @return output device type + */ + inline E_DeviceType getDeviceType() const + { + return DeviceType; + } + + /** get maximum DDL value. + * The minimum DDL value is always 0. + * + ** @return maximum DDL value + */ + inline Uint16 getMaxDDLValue() const + { + return MaxDDLValue; + } + + /** get minimum luminance/OD value from the characteristic curve. + * In case of a usually monotonous characteristic curve the value is + * equivalent to the first/last entry of the array. + * + ** @return minimum luminance/OD value, 0 in case of error + */ + inline double getMinValue() const + { + return MinValue; + } + + /** get maximum luminance/OD value from the characteristic curve. + * In case of a usually monotonous characteristic curve the value is + * equivalent to the last/first entry of the array. + * + ** @return maximum luminance/OD value, 0 in case of error + */ + inline double getMaxValue() const + { + return MaxValue; + } + + /** get the luminance/OD value for a given DDL. + * Looks up a luminance/OD value in the device's characteristic curve. + * Please note that neither ambient light/illumination nor min/max + * density are used. + * + ** @param ddl DDL (digital driving level) to be looked up + * + ** @return luminance/OD value if successful, -1 otherwise + */ + double getValueforDDL(const Uint16 ddl) const; + + /** get the DDL for a given luminance/OD value. + * Determines the DDL from the device's characteristic curve which is + * mapped to the closest possible luminance/OD value. + * Please note that neither ambient light/illumination nor min/max + * density are used. + * + ** @param value luminance/OD value to be looked up + * + ** @return DDL (digital driving level) if successful, 0 otherwise + */ + Uint16 getDDLforValue(const double value) const; + + /** create look-up table with specified number of entries + * + ** @param bits depth of input values + * @param count number of LUT entries (default: 0 = computed automatically) + * + ** @return pointer to created LUT if successful, NULL otherwise + */ + const DiDisplayLUT *getLookupTable(const int bits, + unsigned long count = 0); + + /** delete specified LUT + * + ** @param bits depth of input values of the LUT to be deleted + * + ** @return status, true if valid, false otherwise + */ + int deleteLookupTable(const int bits); + + /** write curve data to a text file (abstract method) + * + ** @param filename name of the text file to which the data should be written + * @param mode write CC and PSC to file if OFTrue + * + ** @return status, true if successful, false otherwise + */ + virtual int writeCurveData(const char *filename, + const OFBool mode = OFTrue) = 0; + + /** get (reflected) ambient light value. + * measured in cd/m^2. + * + ** @return current ambient light value + */ + inline double getAmbientLightValue() const + { + return AmbientLight; + } + + /** set (reflected) ambient light value. + * measured in cd/m^2. applicable to softcopy and hardcopy devices. + * typical values: 0.5-5 for softcopy devices, 10 for transmissive hardcopy + * printer and 0 for reflective hardcopy printers. + * + ** @param value ambient light value to be set (>= 0) + * + ** @return status, true if successful, false otherwise + */ + virtual int setAmbientLightValue(const double value); + + /** get illumination value. + * measured in cd/m^2. + * + ** @return current illumination value + */ + inline double getIlluminationValue() const + { + return Illumination; + } + + /** set illumination value. + * measured in cd/m^2. applicable to hardcopy devices only. + * typical values: 2000 for transmissive hardcopy printer and 150 for + * reflective hardcopy printers. + * + ** @param value illumination value to be set (>= 0) + * + ** @return status, true if successful, false otherwise + */ + virtual int setIlluminationValue(const double value); + + /** get minimum optical density value "Dmin". + * measured in optical density (OD). + * + ** @return current Dmin value or -1 if not set + */ + inline double getMinDensityValue() const + { + return MinDensity; + } + + /** set minimum optical density value "Dmin". + * measured in optical density (OD). applicable to printers only. + * typical value: 0.2 + * + ** @param value Dmin value to be set (or < 0 to unset) + * + ** @return status, true if successful (1 = Dmin set, 2 = Dmin unset), false otherwise + */ + virtual int setMinDensityValue(const double value); + + /** get maximum optical density value "Dmax". + * measured in optical density (OD). + * + ** @return current Dmax value or -1 if not set + */ + inline double getMaxDensityValue() const + { + return MaxDensity; + } + + /** set maximum optical density value "Dmax". + * measured in optical density (OD). applicable to printers only. + * typical value: 3.0 + * + ** @param value Dmax value to be set (or < 0 to unset) + * + ** @return status, true if successful (1 = Dmax set, 2 = Dmax unset), false otherwise + */ + virtual int setMaxDensityValue(const double value); + + /** get minimum luminance value "Lmin". + * measured in cd/m^2. value is computed from "Dmax". + * + ** @return current Lmin value or -1 if Dmax not set + */ + double getMinLuminanceValue() const; + + /** get maximum luminance value "Lmax". + * measured in cd/m^2. value is computed from "Dmin". + * + ** @return current Lmax value or -1 if Dmin not set + */ + double getMaxLuminanceValue() const; + + /** get order of the polynomial curve fitting algorithm. + * used to interpolate the given base points. + * + ** @return polynomial order (0 = use cubic spline interpolation, -1 = not specified) + */ + inline signed int getPolynomialOrder() const + { + return Order; + } + + /** convert the given OD value to luminance. + * This function uses the currently set ambient light and illumination values. + * + ** @param value optical density value to be converted (>= 0) + * @param useAmb use ambient light value if OFTrue + * + ** @return luminance value if successful, -1 otherwise + */ + double convertODtoLum(const double value, + const OFBool useAmb = OFTrue) const; + + /** convert the given OD value to luminance. + * This function uses the specified ambient light and illumination values. + * + ** @param value optical density value to be converted (>= 0) + * @param ambient ambient light value used for the conversion (>= 0) + * @param illum illumination value used for the conversion (>= 0) + * + ** @return luminance value if successful, -1 otherwise + */ + static double convertODtoLum(const double value, + const double ambient, + const double illum); + + + protected: + + /** create display LUT with specified number of entries (abstract method) + * + ** @param count number of LUT entries + * + ** @return pointer to created LUT if successful, NULL otherwise + */ + virtual DiDisplayLUT *getDisplayLUT(unsigned long count) = 0; + + /** read the given device characteristics file + * + ** @param filename name of the characteristics file + * + ** @return status, true if successful, false otherwise + */ + int readConfigFile(const char *filename); + + /** create a sorted (by DDL) table from the given DDL and luminance/OD tables + * + ** @param ddl_tab pointer to array with DDL values + * @param val_tab pointer to array with luminance/OD values + * + ** @return status, true if successful, false otherwise + */ + int createSortedTable(const Uint16 *ddl_tab, + const double *val_tab); + + /** create a table with luminance values from the given OD table. + * Uses the currently set ambient light and illumination value. The resulting luminance + * table has to be deleted by the caller. + * + ** @param od_tab pointer to array with optical density values + * @param count number of entries in the array + * @param useAmb use ambient light value if OFTrue + * + ** @return pointer to luminance table if successful, NULL otherwise + */ + double *convertODtoLumTable(const double *od_tab, + const unsigned long count, + const OFBool useAmb); + + /** interpolate device characteristic curve by means of a cubic spline interpolation + */ + int interpolateValues(); + + /** calculate minimum and maximum luminance/OD values + * + ** @return status, true if successful, false otherwise + */ + int calculateMinMax(); + + /** check whether Dmin and Dmax are properly specified. + * report a warning message if "Dmin >= Dmax". + * + ** @return status, true if successful, false otherwise + */ + int checkMinMaxDensity() const; + + /// status flag, indicating whether display function is valid + int Valid; + + /// output device type (monitor, camera, printer or scanner) + const E_DeviceType DeviceType; + + /// number of DDL and luminance/OD values + unsigned long ValueCount; + /// maximum DDL value (usually 255) + Uint16 MaxDDLValue; + /// order of the polynomial curve fitting algorithm + signed int Order; + + /// (reflected) ambient light value + double AmbientLight; + /// illumination value + double Illumination; + + /// minimum optical density (-1 if unset) + double MinDensity; + /// maximum optical density (-1 if unset) + double MaxDensity; + + /// pointer to array of DDL values + Uint16 *DDLValue; + /// pointer to array of corresponding luminance/OD values + double *LODValue; + + /// minimum luminance/OD value + double MinValue; + /// maximum luminance/OD value + double MaxValue; + + /// constant defining minimum value for number of bits for LUT input (here: 8) + static const int MinBits; + /// constant defining maximum value for number of bits for LUT input (here: 16) + static const int MaxBits; + + /// array with pointer to the different lookup tables (here: 8-16 bits) + DiDisplayLUT *LookupTable[MAX_NUMBER_OF_TABLES]; + + + private: + + // --- declarations to avoid compiler warnings + + DiDisplayFunction(const DiDisplayFunction &); + DiDisplayFunction &operator=(const DiDisplayFunction &); +}; + + +#endif diff --git a/dcmimgle/include/dcmtk/dcmimgle/didocu.h b/dcmimgle/include/dcmtk/dcmimgle/didocu.h new file mode 100644 index 00000000..2fe2829d --- /dev/null +++ b/dcmimgle/include/dcmtk/dcmimgle/didocu.h @@ -0,0 +1,424 @@ +/* + * + * Copyright (C) 1996-2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimgle + * + * Author: Joerg Riesmeier + * + * Purpose: DicomDocument (Header) + * + */ + + +#ifndef DIDOCU_H +#define DIDOCU_H + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/dcmdata/dctypes.h" +#include "dcmtk/dcmdata/dcfilefo.h" +#include "dcmtk/dcmdata/dcxfer.h" +#include "dcmtk/dcmimgle/diobjcou.h" +#include "dcmtk/ofstd/ofstring.h" + +#define INCLUDE_CSTDDEF +#include "dcmtk/ofstd/ofstdinc.h" + + +/*------------------------* + * forward declarations * + *------------------------*/ + +class DcmStack; +class DcmObject; +class DcmTagKey; +class DcmElement; +class DcmPixelData; +class DcmSequenceOfItems; + + +/*---------------------* + * class declaration * + *---------------------*/ + +/** Interface class to DICOM data management (dcmdata). + * NB: This is an internal class of module dcmimgle/dcmimage. Please do not + * use it for accessing DICOM data structures. Instead use the classes + * and functions provided by dcmdata (e.g. class DcmFileFormat, DcmItem). + */ +class DCMTK_DCMIMGLE_EXPORT DiDocument + : public DiObjectCounter +{ + + public: + + /** constructor, open a DICOM file + * + ** @param filename the DICOM file + * @param flags configuration flags (only stored for later use) + * @param fstart first frame to be processed (only stored for later use) + * @param fcount number of frames (only stored for later use) + */ + DiDocument(const char *filename, + const unsigned long flags = 0, + const unsigned long fstart = 0, + const unsigned long fcount = 0); + + /** constructor, use a given DcmObject + * + ** @param object pointer to DICOM data structures (fileformat, dataset or item) + * @param xfer transfer syntax of the 'object'. + * (could also be EXS_Unknown in case of fileformat or dataset) + * @param flags configuration flags (only stored for later use) + * @param fstart first frame to be processed (only stored for later use) + * @param fcount number of frames (only stored for later use) + */ + DiDocument(DcmObject *object, + const E_TransferSyntax xfer, + const unsigned long flags = 0, + const unsigned long fstart = 0, + const unsigned long fcount = 0); + + /** destructor + */ + virtual ~DiDocument(); + + /** check whether current document is valid + * + ** @return status, true if successful, false otherwise + */ + inline int good() const + { + return Object != NULL; + } + + /** get current DICOM object (dataset) + * + ** @return pointer to DICOM object + */ + inline DcmObject *getDicomObject() const + { + return Object; + } + + /** get current DICOM dataset + * + ** @return pointer to DICOM dataset + */ + inline DcmDataset *getDataset() const + { + return OFstatic_cast(DcmDataset *, Object); + } + + /** get first frame to be processed + * + ** @return first frame to be processed + */ + inline unsigned long getFrameStart() const + { + return FrameStart; + } + + /** get number of frames to be processed + * + ** @return number of frames to be processed + */ + inline unsigned long getFrameCount() const + { + return FrameCount; + } + + /** get configuration flags + * + ** @return configuration flags + */ + inline unsigned long getFlags() const + { + return Flags; + } + + /** get transfer syntax of the DICOM dataset + * + ** @return transfer syntax + */ + inline E_TransferSyntax getTransferSyntax() const + { + return Xfer; + } + + /** get photometric interpretation (color model). + * Please note that this is the color model of the decompressed image which might + * deviate from the color model of the original compressed image. + * + ** @return photometric interpretation of the DICOM object + */ + inline const char *getPhotometricInterpretation() const + { + return PhotometricInterpretation.c_str(); + } + + /** get pixel data object + * + ** @return reference to pixel data object (might be NULL) + */ + inline DcmPixelData *getPixelData() const + { + return PixelData; + } + + /** check whether pixel data only exist in compressed format + * + ** @return true if pixel data is compressed, false if an uncompressed version exists + */ + inline OFBool isCompressed() const + { + return DcmXfer(Xfer).isEncapsulated(); + } + + /** search for given tag + * + ** @param tag tag to search for + * @param obj element in the dataset where the search should start (default: root) + * + ** @return pointer to element if successful, NULL otherwise + */ + DcmElement *search(const DcmTagKey &tag, + DcmObject *obj = NULL) const; + + /** search for given tag and put result(s) on a stack + * + ** @param tag tag to search for + * @param stack stack where the result(s) should be stored + * + ** @return status, true if successful, false otherwise + */ + int search(const DcmTagKey &tag, + DcmStack &stack) const; + + + /** get value multiplicity (VM) of given tag + * + ** @param tag tag to be searched + * + ** @return VM if successful, 0 otherwise + */ + unsigned long getVM(const DcmTagKey &tag) const; + + /** get value of given tag (Uint16) + * + ** @param tag tag to search for + * @param returnVal reference to the storage area for the resulting value + * @param pos position in multi-valued elements (starting with 0) + * @param item pointer to item in dataset where to start (default: main dataset) + * @param allowSigned also allow signed value (Sint16) if true + * + ** @return VM if successful, 0 otherwise + */ + unsigned long getValue(const DcmTagKey &tag, + Uint16 &returnVal, + const unsigned long pos = 0, + DcmItem *item = NULL, + const OFBool allowSigned = OFFalse) const; + + /** get value of given tag (Sint16) + * + ** @param tag tag to search for + * @param returnVal reference to the storage area for the resulting value + * @param pos position in multi-valued elements (starting with 0) + * @param item pointer to item in dataset where to start (default: main dataset) + * + ** @return VM if successful, 0 otherwise + */ + unsigned long getValue(const DcmTagKey &tag, + Sint16 &returnVal, + const unsigned long pos = 0, + DcmItem *item = NULL) const; + + /** get value of given tag (Uint32) + * + ** @param tag tag to search for + * @param returnVal reference to the storage area for the resulting value + * @param pos position in multi-valued elements (starting with 0) + * @param item pointer to item in dataset where to start (default: main dataset) + * + ** @return VM if successful, 0 otherwise + */ + unsigned long getValue(const DcmTagKey &tag, + Uint32 &returnVal, + const unsigned long pos = 0, + DcmItem *item = NULL) const; + + /** get value of given tag (Sint32) + * + ** @param tag tag to search for + * @param returnVal reference to the storage area for the resulting value + * @param pos position in multi-valued elements (starting with 0) + * @param item pointer to item in dataset where to start (default: main dataset) + * + ** @return VM if successful, 0 otherwise + */ + unsigned long getValue(const DcmTagKey &tag, + Sint32 &returnVal, + const unsigned long pos = 0, + DcmItem *item = NULL) const; + + /** get value of given tag (double) + * + ** @param tag tag to search for + * @param returnVal reference to the storage area for the resulting value + * @param pos position in multi-valued elements (starting with 0) + * @param item pointer to item in dataset where to start (default: main dataset) + * + ** @return VM if successful, 0 otherwise + */ + unsigned long getValue(const DcmTagKey &tag, + double &returnVal, + const unsigned long pos = 0, + DcmItem *item = NULL) const; + + /** get value of given tag (Uint16 array) + * + ** @param tag tag to search for + * @param returnVal reference to the storage area for the resulting value + * @param item pointer to item in dataset where to start (default: main dataset) + * + ** @return VM / number of values if successful, 0 otherwise + */ + unsigned long getValue(const DcmTagKey &tag, + const Uint16 *&returnVal, + DcmItem *item = NULL) const; + + /** get value of given tag (const char *) + * + ** @param tag tag to search for + * @param returnVal reference to the storage area for the resulting value + * @param item pointer to item in dataset where to start (default: main dataset) + * + ** @return VM if successful, 0 otherwise + */ + unsigned long getValue(const DcmTagKey &tag, + const char *&returnVal, + DcmItem *item = NULL) const; + + /** get value of given tag (OFString) + * + ** @param tag tag to search for + * @param returnVal reference to the storage area for the resulting value + * @param pos position in multi-valued elements (starting with 0) + * @param item pointer to item in dataset where to start (default: main dataset) + * + ** @return VM if successful, 0 otherwise + */ + unsigned long getValue(const DcmTagKey &tag, + OFString &returnVal, + const unsigned long pos = 0, + DcmItem *item = NULL) const; + + /** get sequence of given tag + * + ** @param tag tag to search for + * @param seq reference to the storage area for the resulting value + * @param item pointer to item in dataset where to start (default: main dataset) + * + ** @return cardinality if successful, 0 otherwise + */ + unsigned long getSequence(const DcmTagKey &tag, + DcmSequenceOfItems *&seq, + DcmItem *item = NULL) const; + + // --- static helper functions --- + + /** get value of given element (Uint16) + * + ** @param elem element where the value is stored + * @param returnVal reference to the storage area for the resulting value + * @param pos position in multi-valued elements (starting with 0) + * @param allowSigned also allow signed value (Sint16) if true + * + ** @return VM if successful, 0 otherwise + */ + static unsigned long getElemValue(const DcmElement *elem, + Uint16 &returnVal, + const unsigned long pos = 0, + const OFBool allowSigned = OFFalse); + + /** get value of given element (Uint16 array) + * + ** @param elem element where the value is stored + * @param returnVal reference to the storage area for the resulting value + * + ** @return VM / number of values if successful, 0 otherwise + */ + static unsigned long getElemValue(const DcmElement *elem, + const Uint16 *&returnVal); + + /** get value of given element (const char *) + * + ** @param elem element where the value is stored + * @param returnVal reference to the storage area for the resulting value + * + ** @return VM if successful, 0 otherwise + */ + static unsigned long getElemValue(const DcmElement *elem, + const char *&returnVal); + + /** get value of given element (OFString) + * + ** @param elem element where the value is stored + * @param returnVal reference to the storage area for the resulting value + * @param pos position in multi-valued elements (starting with 0) + * + ** @return VM if successful, 0 otherwise + */ + static unsigned long getElemValue(const DcmElement *elem, + OFString &returnVal, + const unsigned long pos = 0); + + + protected: + + /** convert pixel data to uncompressed representation (if required) + */ + void convertPixelData(); + + + private: + + /// reference to DICOM dataset (in memory) + DcmObject *Object; + /// reference to DICOM fileformat (read from file, maybe NULL) + DcmFileFormat *FileFormat; + /// reference to pixel data object + DcmPixelData *PixelData; + /// transfer syntax used for reading the dataset + E_TransferSyntax Xfer; + + /// first frame to be processed + unsigned long FrameStart; + /// number of frames to be processed + unsigned long FrameCount; + + /// configuration flags + unsigned long Flags; + + /// photometric interpretation (color model) + OFString PhotometricInterpretation; + + // --- declarations to avoid compiler warnings + + DiDocument(const DiDocument &); + DiDocument &operator=(const DiDocument &); +}; + + +#endif diff --git a/dcmimgle/include/dcmtk/dcmimgle/diflipt.h b/dcmimgle/include/dcmtk/dcmimgle/diflipt.h new file mode 100644 index 00000000..a75b62be --- /dev/null +++ b/dcmimgle/include/dcmtk/dcmimgle/diflipt.h @@ -0,0 +1,334 @@ +/* + * + * Copyright (C) 1996-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimgle + * + * Author: Joerg Riesmeier + * + * Purpose: DicomFlipTemplate (Header) + * + */ + + +#ifndef DIFLIPT_H +#define DIFLIPT_H + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/dcmimgle/dipixel.h" +#include "dcmtk/dcmimgle/ditranst.h" + + +/*---------------------* + * class declaration * + *---------------------*/ + +/** Template class to flip images (on pixel data level). + * horizontally and vertically + */ +template +class DiFlipTemplate + : public DiTransTemplate +{ + + public: + + /** constructor. + * This method is used to flip an image and store the result in the same storage area. + * + ** @param pixel pointer to object where the pixel data are stored + * @param columns width of the image + * @param rows height of the image + * @param frames number of frames + * @param horz flags indicating whether to flip horizontally or not + * @param vert flags indicating whether to flip vertically or not + */ + DiFlipTemplate(DiPixel *pixel, + const Uint16 columns, + const Uint16 rows, + const Uint32 frames, + const int horz, + const int vert) + : DiTransTemplate(0, columns, rows, columns, rows, frames) + { + if (pixel != NULL) + { + this->Planes = pixel->getPlanes(); + if ((pixel->getCount() > 0) && (this->Planes > 0) && + (pixel->getCount() == OFstatic_cast(unsigned long, columns) * OFstatic_cast(unsigned long, rows) * frames)) + { + if (horz && vert) + flipHorzVert(OFstatic_cast(T **, pixel->getDataArrayPtr())); + else if (horz) + flipHorz(OFstatic_cast(T **, pixel->getDataArrayPtr())); + else if (vert) + flipVert(OFstatic_cast(T **, pixel->getDataArrayPtr())); + } else { + DCMIMGLE_WARN("could not flip image ... corrupted data"); + } + } + } + + /** constructor. + * This method is used to perform only the preparation and to start flipping later with method 'flipData()' + * + ** @param planes number of planes (1 or 3) + * @param columns width of the image + * @param rows height of the image + * @param frames number of frames + */ + DiFlipTemplate(const int planes, + const Uint16 columns, + const Uint16 rows, + const Uint32 frames) + : DiTransTemplate(planes, columns, rows, columns, rows, frames) + { + } + + /** destructor + */ + virtual ~DiFlipTemplate() + { + } + + /** choose algorithm depending on flipping mode + * + ** @param src array of pointers to source image pixels + * @param dest array of pointers to destination image pixels + * @param horz flags indicating whether to flip horizontally or not + * @param vert flags indicating whether to flip vertically or not + */ + inline void flipData(const T *src[], + T *dest[], + const int horz, + const int vert) + { + if ((src != NULL) && (dest != NULL)) + { + if (horz && vert) + flipHorzVert(src, dest); + else if (horz) + flipHorz(src, dest); + else if (vert) + flipVert(src, dest); + else + this->copyPixel(src, dest); + } + } + + + protected: + + /** flip source image horizontally and store result in destination image + * + ** @param src array of pointers to source image pixels + * @param dest array of pointers to destination image pixels + */ + inline void flipHorz(const T *src[], + T *dest[]) + { + if ((src != NULL) && (dest != NULL)) + { + register Uint16 x; + register Uint16 y; + register const T *p; + register T *q; + register T *r; + for (int j = 0; j < this->Planes; ++j) + { + p = src[j]; + r = dest[j]; + for (Uint32 f = this->Frames; f != 0; --f) + { + for (y = this->Src_Y; y != 0; --y) + { + q = r + this->Dest_X; + for (x = this->Src_X; x != 0; --x) + *--q = *p++; + r += this->Dest_X; + } + } + } + } + } + + /** flip source image vertically and store result in destination image + * + ** @param src array of pointers to source image pixels + * @param dest array of pointers to destination image pixels + */ + inline void flipVert(const T *src[], + T *dest[]) + { + if ((src != NULL) && (dest != NULL)) + { + register Uint16 x; + register Uint16 y; + register const T *p; + register T *q; + register T *r; + const unsigned long count = OFstatic_cast(unsigned long, this->Dest_X) * OFstatic_cast(unsigned long, this->Dest_Y); + for (int j = 0; j < this->Planes; ++j) + { + p = src[j]; + r = dest[j]; + for (Uint32 f = this->Frames; f != 0; --f) + { + r += count; + for (y = this->Src_Y; y != 0; --y) + { + q = r - this->Dest_X; + for (x = this->Src_X; x != 0; --x) + *q++ = *p++; + r -= this->Dest_X; + } + r += count; + } + } + } + } + + /** flip source image horizontally and vertically and store result in destination image + * + ** @param src array of pointers to source image pixels + * @param dest array of pointers to destination image pixels + */ + inline void flipHorzVert(const T *src[], + T *dest[]) + { + if ((src != NULL) && (dest != NULL)) + { + register unsigned long i; + register const T *p; + register T *q; + const unsigned long count = OFstatic_cast(unsigned long, this->Dest_X) * OFstatic_cast(unsigned long, this->Dest_Y); + for (int j = 0; j < this->Planes; ++j) + { + p = src[j]; + q = dest[j]; + for (Uint32 f = this->Frames; f != 0; --f) + { + q += count; + for (i = count; i != 0; --i) + *--q = *p++; + q += count; + } + } + } + } + + private: + + /** flip image horizontally and store result in the same storage area + * + ** @param data array of pointers to source/destination image pixels + */ + inline void flipHorz(T *data[]) + { + register Uint16 x; + register Uint16 y; + register T *p; + register T *q; + register T t; + T *r; + for (int j = 0; j < this->Planes; ++j) + { + r = data[j]; + for (Uint32 f = this->Frames; f != 0; --f) + { + for (y = this->Src_Y; y != 0; --y) + { + p = r; + r += this->Dest_X; + q = r; + for (x = this->Src_X / 2; x != 0; --x) + { + t = *p; + *p++ = *--q; + *q = t; + } + } + } + } + } + + /** flip image vertically and store result in the same storage area + * + ** @param data array of pointers to source/destination image pixels + */ + inline void flipVert(T *data[]) + { + register Uint16 x; + register Uint16 y; + register T *p; + register T *q; + register T *r; + register T t; + T *s; + const unsigned long count = OFstatic_cast(unsigned long, this->Dest_X) * OFstatic_cast(unsigned long, this->Dest_Y); + for (int j = 0; j < this->Planes; ++j) + { + s = data[j]; + for (Uint32 f = this->Frames; f != 0; --f) + { + p = s; + s += count; + r = s; + for (y = this->Src_Y / 2; y != 0; --y) + { + r -= this->Dest_X; + q = r; + for (x = this->Src_X; x != 0; --x) + { + t = *p; + *p++ = *q; + *q++ = t; + } + } + } + } + } + + /** flip image horizontally and vertically and store result in the same storage area + * + ** @param data array of pointers to source/destination image pixels + */ + inline void flipHorzVert(T *data[]) + { + register unsigned long i; + register T *p; + register T *q; + register T t; + T *s; + const unsigned long count = OFstatic_cast(unsigned long, this->Dest_X) * OFstatic_cast(unsigned long, this->Dest_Y); + for (int j = 0; j < this->Planes; ++j) + { + s = data[j]; + for (Uint32 f = this->Frames; f != 0; --f) + { + p = s; + q = s + count; + for (i = count / 2; i != 0; --i) + { + t = *p; + *p++ = *--q; + *q = t; + } + s += count; + } + } + } +}; + + +#endif diff --git a/dcmimgle/include/dcmtk/dcmimgle/digsdfn.h b/dcmimgle/include/dcmtk/dcmimgle/digsdfn.h new file mode 100644 index 00000000..6a9f47a8 --- /dev/null +++ b/dcmimgle/include/dcmtk/dcmimgle/digsdfn.h @@ -0,0 +1,227 @@ +/* + * + * Copyright (C) 1998-2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimgle + * + * Author: Joerg Riesmeier + * + * Purpose: DicomGSDFunction (Header) + * + */ + + +#ifndef DIGSDFN_H +#define DIGSDFN_H + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/dcmimgle/didispfn.h" + +#define INCLUDE_CSTDDEF /* For NULL */ +#include "dcmtk/ofstd/ofstdinc.h" + + +/*---------------------* + * class declaration * + *---------------------*/ + +/** Class to manage GSDF LUTs (for calibration) + */ +class DCMTK_DCMIMGLE_EXPORT DiGSDFunction + : public DiDisplayFunction +{ + + public: + + /** constructor, read device characteristics file. + * Keywords: "max" for maximum DDL (Digital Driving Level, required at first position) + * "amb" for ambient light and "lum" for illumination (both optional) + * "ord" for the order of the polynomial curve fitting algorithm used to interpolate + * the given base points (0 or absent = use cubic spline interpolation) + * + ** @param filename name of the characteristics file (luminance/OD for each DDL) + * @param deviceType type of the output device (default: monitor) + * @param ord order of the polynomial curve fitting algorithm used to interpolate + * the given base points (-1 = use file setting, 0 = cubic spline) + */ + DiGSDFunction(const char *filename, + const E_DeviceType deviceType = EDT_Monitor, + const signed int ord = -1); + + /** constructor, use given array of luminance/OD values. UNTESTED + * Values must be sorted and complete (i.e. there must be an entry for each DDL). + * The given arrays are copied internally. + * + ** @param val_tab pointer to array with luminance/OD values + * @param count number of array elements (should be equal to 'max + 1') + * @param max maximum DDL (digital driving level) + * @param deviceType type of the output device (default: monitor) + * @param ord order of the polynomial curve fitting algorithm used to interpolate + * the given base points (0 or negative = use cubic spline interpolation) + */ + DiGSDFunction(const double *val_tab, + const unsigned long count, + const Uint16 max = 255, + const E_DeviceType deviceType = EDT_Monitor, + const signed int ord = 0); + + /** constructor, use given array of DDL and luminance/OD values. UNTESTED + * Values will be automatically sorted and missing values will be interpolated. + * The given arrays are copied internally. + * + ** @param ddl_tab pointer to array with DDL values (must be with the interval 0..max) + * @param val_tab pointer to array with luminance/OD values + * @param count number of array elements (2..65536) + * @param max maximum DDL (digital driving level) + * @param deviceType type of the output device (default: monitor) + * @param ord order of the polynomial curve fitting algorithm used to interpolate + * the given base points (0 or negative = use cubic spline interpolation) + */ + DiGSDFunction(const Uint16 *ddl_tab, + const double *val_tab, + const unsigned long count, + const Uint16 max = 255, + const E_DeviceType deviceType = EDT_Monitor, + const signed int ord = 0); + + /** constructor, compute luminance/OD values automatically within the specified range. + * + ** @param val_min minimum luminance/OD value + * @param val_max maximum luminance/OD value + * @param count number of DDLs (digital driving level, 1..65536)) + * @param deviceType type of the output device (default: monitor) + * @param ord order of the polynomial curve fitting algorithm used to interpolate + * the given base points (0 or negative = use cubic spline interpolation) + */ + DiGSDFunction(const double val_min, + const double val_max, + const unsigned long count = 256, + const E_DeviceType deviceType = EDT_Monitor, + const signed int ord = 0); + + /** destructor + */ + virtual ~DiGSDFunction(); + + /** write curve data to a text file + * + ** @param filename name of the text file to which the data should be written + * @param mode write CC and PSC to file if OFTrue + * + ** @return status, true if successful, false otherwise + */ + int writeCurveData(const char *filename, + const OFBool mode = OFTrue); + + /** set (reflected) ambient light value. + * measured in cd/m^2. applicable to softcopy and hardcopy devices. + * typical values: 0.5-5 for softcopy devices, 10 for transmissive hardcopy + * printer and 0 for reflective hardcopy printers. + * + ** @param value ambient light value to be set (>= 0) + * + ** @return status, true if successful, false otherwise + */ + int setAmbientLightValue(const double value); + + /** set illumination value. + * measured in cd/m^2. applicable to hardcopy devices only. + * typical values: 2000 for transmissive hardcopy printer and 150 for + * reflective hardcopy printers. + * + ** @param value illumination value to be set (>= 0) + * + ** @return status, true if successful, false otherwise + */ + int setIlluminationValue(const double value); + + /** set minimum optical density value "Dmin". + * measured in optical density (OD). applicable to printers only. + * typical value: 0.2 + * + ** @param value Dmin value to be set (or < 0 to unset) + * + ** @return status, true if successful (1 = Dmax set, 2 = Dmax unset), false otherwise + */ + int setMinDensityValue(const double value); + + /** set maximum optical density value "Dmax". + * measured in optical density (OD). applicable to printers only. + * typical value: 3.0 + * + ** @param value Dmax value to be set (or < 0 to unset) + * + ** @return status, true if successful (1 = Dmax set, 2 = Dmax unset), false otherwise + */ + int setMaxDensityValue(const double value); + + /** calculate the JND index for a given luminance value + * + ** @param lum luminance value + * + ** @return JND index if successful, -1 otherwise + */ + static double getJNDIndex(const double lum); + + + protected: + + /** create GSDF LUT with specified number of entries + * + ** @param count number of LUT entries + * + ** @return pointer to created LUT if successful, NULL otherwise + */ + DiDisplayLUT *getDisplayLUT(unsigned long count); + + /** calculate GSDF (array of 1023 luminance/OD values) + * + ** @return status, true if successful, false otherwise + */ + int calculateGSDF(); + + /** calculate helper function for GSDF interpolation + * + ** @return status, true if successful, false otherwise + */ + int calculateGSDFSpline(); + + /** calculate 'JNDMin' and 'JNDMax' for the given luminance/OD range + * + ** @return status, true if successful, false otherwise + */ + int calculateJNDBoundaries(); + + + private: + + /// minimum JND index value for the given display system + double JNDMin; + /// maximum JND index value for the given display system + double JNDMax; + + /// constant defining the number JND indexes for the maximum luminance/OD range (1023) + static const unsigned int GSDFCount; + /// array of luminance/OD values defining the GSDF + double *GSDFValue; + /// array of values used for the interpolation of the GSDF + double *GSDFSpline; + + // --- declarations to avoid compiler warnings + + DiGSDFunction(const DiGSDFunction &); + DiGSDFunction &operator=(const DiGSDFunction &); +}; + + +#endif diff --git a/dcmimgle/include/dcmtk/dcmimgle/digsdlut.h b/dcmimgle/include/dcmtk/dcmimgle/digsdlut.h new file mode 100644 index 00000000..b5f9356f --- /dev/null +++ b/dcmimgle/include/dcmtk/dcmimgle/digsdlut.h @@ -0,0 +1,122 @@ +/* + * + * Copyright (C) 1996-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimgle + * + * Author: Joerg Riesmeier + * + * Purpose: DicomGSDFLUT (Header) + * + */ + + +#ifndef DIGSDLUT_H +#define DIGSDLUT_H + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/dcmimgle/didislut.h" + + +/*---------------------* + * class declaration * + *---------------------*/ + +/** Class to compute and store the GSDF lookup table + */ +class DCMTK_DCMIMGLE_EXPORT DiGSDFLUT + : public DiDisplayLUT +{ + + public: + + /** constructor + * + ** @param count number of values to be stored in the LUT + * @param max maximum value to be stored in the LUT + * @param ddl_tab array of DDL values + * @param val_tab array of values + * @param ddl_cnt number of DDL values + * @param gsdf_tab array with Grayscale Standard Display Function + * @param gsdf_spl array with helper function used for interpolation + * @param gsdf_cnt number of values in GSDF array + * @param jnd_min minimum JND index value + * @param jnd_max maximum JND index value + * @param lum_min minimum luminance value to be used (lower border) + * @param lum_max maximum luminance value to be used (upper border) + * @param amb (reflected) ambient light value + * @param illum illumination value + * @param inverse apply inverse transformation if OFTrue + * @param stream output stream (used to write curve data to a file) + * @param printMode write CC and PSC to stream if OFTrue + */ + DiGSDFLUT(const unsigned long count, + const Uint16 max, + const Uint16 *ddl_tab, + const double *val_tab, + const unsigned long ddl_cnt, + const double *gsdf_tab, + const double *gsdf_spl, + const unsigned int gsdf_cnt, + const double jnd_min, + const double jnd_max, + const double lum_min, + const double lum_max, + const double amb, + const double illum, + const OFBool inverse = OFFalse, + STD_NAMESPACE ostream *stream = NULL, + const OFBool printMode = OFTrue); + + /** destructor + */ + virtual ~DiGSDFLUT(); + + + protected: + + /** create lookup table + * + ** @param ddl_tab array of DDL values + * @param val_tab array of luminance values + * @param ddl_cnt number of DDL values + * @param gsdf_tab array with Grayscale Standard Display Function + * @param gsdf_spl array with helper function used for interpolation + * @param gsdf_cnt number of values in GSDF array + * @param jnd_min minimum JND index value + * @param jnd_max maximum JND index value + * @param lum_min minimum luminance value to be used (lower border) + * @param lum_max maximum luminance value to be used (upper border) + * @param inverse apply inverse transformation if OFTrue + * @param stream output stream (used to write curve data to a file) + * @param printMode write CC and PSC to stream if OFTrue + * + ** @return status, true if successful, false otherwise + */ + int createLUT(const Uint16 *ddl_tab, + const double *val_tab, + const unsigned long ddl_cnt, + const double *gsdf_tab, + const double *gsdf_spl, + const unsigned int gsdf_cnt, + const double jnd_min, + const double jnd_max, + const double lum_min, + const double lum_max, + const OFBool inverse = OFFalse, + STD_NAMESPACE ostream *stream = NULL, + const OFBool printMode = OFTrue); +}; + + +#endif diff --git a/dcmimgle/include/dcmtk/dcmimgle/diimage.h b/dcmimgle/include/dcmtk/dcmimgle/diimage.h new file mode 100644 index 00000000..50fb32bc --- /dev/null +++ b/dcmimgle/include/dcmtk/dcmimgle/diimage.h @@ -0,0 +1,676 @@ +/* + * + * Copyright (C) 1996-2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimgle + * + * Author: Joerg Riesmeier + * + * Purpose: DicomImage (Header) + * + */ + + +#ifndef DIIMAGE_H +#define DIIMAGE_H + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/dcmdata/dcitem.h" +#include "dcmtk/dcmdata/dcfcache.h" + +#ifdef SUNCC +#include "dcmtk/dcmimgle/didocu.h" +#endif + +#include "dcmtk/dcmimgle/diovlay.h" +#include "dcmtk/dcmimgle/diutils.h" + +#define INCLUDE_CSTDIO +#include "dcmtk/ofstd/ofstdinc.h" + +#include "dcmtk/ofstd/ofstream.h" + + +/*------------------------* + * forward declarations * + *------------------------*/ + +class DcmPixelData; +class DcmUnsignedShort; + +#ifndef SUNCC + class DiDocument; +#endif + +class DiPixel; +class DiMonoImage; +class DiInputPixel; + + +/*---------------------* + * class declaration * + *---------------------*/ + +/** Base class for images. + * NB: This is an internal class of module dcmimgle/dcmimage. Please do not + * use it directly. Instead use the main interface class DicomImage. + */ +class DCMTK_DCMIMGLE_EXPORT DiImage +{ + + public: + + /** constructor + * + ** @param docu pointer to the DICOM document + * @param status status of the image object + * @param spp samples per pixel + */ + DiImage(const DiDocument *docu, + const EI_Status status, + const int spp); + + /** destructor + */ + virtual ~DiImage(); + + /** process next couple of frames + * + ** @param fcount number of frames to be processed (0 = same number as before) + * + ** @return status, true if successful, false otherwise + */ + virtual int processNextFrames(const unsigned long fcount); + + /** get status of the image object + * + ** @return status of the image object + */ + inline EI_Status getStatus() const + { + return ImageStatus; + } + + /** get number of frames + * + ** @return number of frames + */ + inline Uint32 getNumberOfFrames() const + { + return NumberOfFrames; + } + + /** get index of first frame + * + ** @return index of first frame + */ + inline Uint32 getFirstFrame() const + { + return FirstFrame; + } + + /** get total number of frames + * + ** @return total number of frames + */ + inline Uint32 getTotalNumberOfFrames() const + { + return TotalNumberOfFrames; + } + + /** get representative frame + * + ** @return representative frame + */ + inline Uint32 getRepresentativeFrame() const + { + return RepresentativeFrame; + } + + /** get frame time + * + ** @return frame time + */ + inline double getFrameTime() const + { + return FrameTime; + } + + /** get number of rows + * + ** @return number of rows + */ + inline Uint16 getRows() const + { + return Rows; + } + + /** get number of columns + * + ** @return number of columns + */ + inline Uint16 getColumns() const + { + return Columns; + } + + /** get pixel's width + * + ** @return pixel's width + */ + inline double getPixelWidth() const + { + return (PixelWidth > 0) ? PixelWidth : 1; + } + + /** get pixel's height + * + ** @return pixel's height + */ + inline double getPixelHeight() const + { + return (PixelHeight > 0) ? PixelHeight : 1; + } + + /** get pixel's rows/column ratio + * + ** @return pixel's rows/column ratio + */ + inline double getRowColumnRatio() const + { + return getPixelHeight() / getPixelWidth(); + } + + /** get pixel's column/rows ratio + * + ** @return pixel's column/rows ratio + */ + inline double getColumnRowRatio() const + { + return getPixelWidth() / getPixelHeight(); + } + + /** set pixel's rows/column ratio + * + ** @param ratio pixel's rows/column ratio + * + ** @return status, true if successful, false otherwise + */ + int setRowColumnRatio(const double ratio); + + /** set pixel's column/rows ratio + * + ** @param ratio pixel's column/rows ratio + * + ** @return status, true if successful, false otherwise + */ + int setColumnRowRatio(const double ratio); + + /** get polarity. + * possible values are EPP_Normal and EPP_Reverse + * + ** @return currently active polarity mode + */ + inline EP_Polarity getPolarity() const + { + return Polarity; + } + + /** set polarity. + * + ** @param polarity polarity (normal or reverse) + * + ** @return true if successful (1 = polarity has changed, + * 2 = polarity has not changed) + * false otherwise + */ + int setPolarity(const EP_Polarity polarity); + + /** get number of bits per sample. + * If the optional parameter is specified the value will be checked and in any case + * a valid value will be returned. + * + ** @param bits value to be returned (if less than 1 or greater than the maximum (32) + * the default value will be used which is equal to the bits per sample + * value stored in the DICOM dataset) + * + ** @return status, true if successful, false otherwise + */ + virtual int getBits(const int bits = 0) const + { + return ((bits < 1) || (bits > MAX_BITS)) ? BitsPerSample : bits; + } + + /** get color model of internal pixel representation. + * Possible values are: EPI_Monochrome1, EPI_Monochrome2, EPI_RGB and EPI_YBR_Full + * + ** @return color model of internal pixel representation + */ + virtual EP_Interpretation getInternalColorModel() const = 0; + + /** get access to intermediate pixel data representation (abstract) + * + ** @return pointer to intermediate pixel data + */ + virtual const DiPixel *getInterData() const = 0; + + /** get number of bytes required for the rendered output of a single frame + * + * @param bits number of bits for the output pixel data (depth) + * + ** @return number of bytes if successful, 0 otherwise + */ + virtual unsigned long getOutputDataSize(const int bits = 0) const = 0; + + /** get pixel data with specified format (abstract). + * (memory is handled internally) + * + ** @param frame number of frame to be rendered + * @param bits number of bits for the output pixel data (depth) + * @param planar flag, whether the output data (for multi-planar images) should be planar or not + * + ** @return untyped pointer to the pixel data if successful, NULL otherwise + */ + virtual const void *getOutputData(const unsigned long frame, + const int bits, + const int planar) = 0; + + /** get pixel data with specified format (abstract). + * (memory is handled externally) + * + ** @param buffer untyped pointer to the externally allocated memory buffer + * @param size size of the memory buffer in bytes (will be checked) + * @param frame number of frame to be rendered + * @param bits number of bits for the output pixel data (depth) + * @param planar flag, whether the output data (for multi-planar images) should be planar or not + * + ** @return status, true if successful, false otherwise + */ + virtual int getOutputData(void *buffer, + const unsigned long size, + const unsigned long frame, + const int bits, + const int planar) = 0; + + /** get pixel data of specified plane (abstract). + * (memory is handled internally) + * + ** @param plane number of plane which should be rendered (starting from 0) + * + ** @return untyped pointer to the pixel data if successful, NULL otherwise + */ + virtual const void *getOutputPlane(const int plane) const = 0; + + /** delete internally handled output memory buffer (abstract) + */ + virtual void deleteOutputData() = 0; + + /** get pointer to the object managing the overlay planes + * + ** (#)param idx index of overlay group (here: not used, since only applicable for monochrome images) + * + ** @return pointer to the overlay managing object, here: NULL + */ + virtual DiOverlay *getOverlayPtr(const unsigned int /*idx*/) + { + return NULL; + } + + /** get pointer to monochrome image object + * + ** @return pointer to monochrome image object (here: always NULL) + */ + virtual DiMonoImage *getMonoImagePtr() + { + return NULL; + } + + /** create copy of current image object (abstract) + * + ** @param fstart first frame to be processed (not fully implemented!) + * @param fcount number of frames (not fully implemented!) + * + ** @return pointer to new DiImage object (NULL if an error occurred) + */ + virtual DiImage *createImage(const unsigned long fstart, + const unsigned long fcount) const = 0; + + /** create scaled copy of specified (clipping) area of the current image object (abstract). + * + ** @param left_pos x coordinate of top left corner of area to be scaled + * (referring to image origin, negative values create a border around the image) + * @param top_pos y coordinate of top left corner of area to be scaled + * @param clip_width width of area to be scaled + * @param clip_height height of area to be scaled + * @param scale_width width of scaled image (in pixels) + * @param scale_height height of scaled image (in pixels) + * @param interpolate specifies whether scaling algorithm should use interpolation (if necessary). + * default: no interpolation (0), preferred interpolation algorithm (if applicable): + * 1 = pbmplus algorithm, 2 = c't algorithm, 3 = bilinear magnification, + * 4 = bicubic magnification + * @param aspect specifies whether pixel aspect ratio should be taken into consideration + * (if true, width OR height should be 0, i.e. this component will be calculated + * automatically) + * @param pvalue P-value used for the border outside the image (0..65535) + * + ** @return pointer to new DiImage object (NULL if an error occurred) + */ + virtual DiImage *createScale(const signed long left_pos, + const signed long top_pos, + const unsigned long clip_width, + const unsigned long clip_height, + const unsigned long scale_width, + const unsigned long scale_height, + const int interpolate, + const int aspect, + const Uint16 pvalue) const = 0; + + /** flip current image horizontally and/or vertically (abstract) + * + ** @param horz flip horizontally if true + * @param vert flip vertically if true + * + ** @return true if successful, false otherwise + */ + virtual int flip(const int horz, + const int vert) = 0; + + /** create a flipped copy of the current image (abstract). + * + ** @param horz flip horizontally if true + * @param vert flip vertically if true + * + ** @return pointer to new DiImage object (NULL if an error occurred) + */ + virtual DiImage *createFlip(const int horz, + const int vert) const = 0; + + /** rotate current image (by steps of 90 degrees) + * + ** @param degree angle by which the image shall be rotated + * + ** @return true if successful, false otherwise + */ + virtual int rotate(const int degree); + + /** create a rotated copy of the current image (abstract). + * + ** @param degree angle by which the image shall be rotated + * + ** @return pointer to new DiImage object (NULL if an error occurred) + */ + virtual DiImage *createRotate(const int degree) const = 0; + + /** create monochrome copy of the current image (abstract). + * + ** @param red coefficient by which the red component is weighted + * @param green coefficient by which the green component is weighted + * @param blue coefficient by which the blue component is weighted + * + ** @return pointer to new DiImage object (NULL if an error occurred) + */ + virtual DiImage *createMono(const double red, + const double green, + const double blue) const = 0; + + /** create true color (24/32 bit) or palette (8 bit) bitmap for MS Windows (abstract). + * + ** @param data untyped pointer memory buffer (set to NULL if not allocated externally) + * @param size size of the memory buffer in bytes (if 0 'data' is set to NULL) + * @param frame index of frame to be converted (starting from 0) + * @param bits number of bits per pixel used for the output bitmap (8, 24 or 32) + * @param upsideDown specifies the order of lines in the images (0 = top-down, bottom-up otherwise) + * @param padding align each line to a 32-bit address if true (default) + * + ** @return number of bytes allocated by the bitmap, or 0 if an error occurred + */ + virtual unsigned long createDIB(void *&data, + const unsigned long size, + const unsigned long frame, + const int bits, + const int upsideDown, + const int padding = 1) = 0; + + /** create true color (32 bit) bitmap for Java AWT (abstract). + * + ** @param data resulting pointer to bitmap data (set to NULL if an error occurred) + * @param frame index of frame to be converted + * @param bits number of bits per pixel used for the output bitmap (8 or 32) + * + ** @return number of bytes allocated by the bitmap, or 0 if an error occurred + */ + virtual unsigned long createAWTBitmap(void *&data, + const unsigned long frame, + const int bits) = 0; + + /** render pixel data of given frame and write image related attributes to DICOM dataset. + * + ** @param dataset reference to DICOM dataset where the image attributes are stored + * @param frame index of frame used for output + * @param bits number of bits used for output of pixel data + * @param planar flag, whether the output data (for multi-planar images) should be planar or not + * + ** @return true if successful, false otherwise + */ + int writeFrameToDataset(DcmItem &dataset, + const unsigned long frame = 0, + const int bits = 0, + const int planar = 0); + + /** write current image and related attributes to DICOM dataset. + * + ** @param dataset reference to DICOM dataset where the image attributes are stored + * @param mode determine value of BitsStored from 'used' or 'possible' pixel values + * @param planar flag, whether the output data (for multi-planar images) should be planar or not + * + ** @return true if successful, false otherwise + */ + virtual int writeImageToDataset(DcmItem &dataset, + const int mode = 0, + const int planar = 2) = 0; + + /** write pixel data to PPM file (abstract). + * pixel data is written in ASCII format. + * + ** @param stream open C++ output stream + * @param frame index of frame used for output + * @param bits number of bits used for output of pixel data + * + ** @return true if successful, false otherwise + */ + virtual int writePPM(STD_NAMESPACE ostream& stream, + const unsigned long frame, + const int bits) = 0; + + /** write pixel data to PPM file (abstract). + * pixel data is written in ASCII format. + * + ** @param stream open C output stream + * @param frame index of frame used for output + * @param bits number of bits used for output of pixel data + * + ** @return true if successful, false otherwise + */ + virtual int writePPM(FILE *stream, + const unsigned long frame, + const int bits) = 0; + + /** write pixel data to raw PPM file (abstract) + * + ** @param stream open C output stream + * @param frame index of frame used for output + * @param bits number of bits used for output of pixel data + * + ** @return true if successful, false otherwise + */ + virtual int writeRawPPM(FILE *stream, + const unsigned long frame, + const int bits) = 0; + + /** write pixel data to BMP file + * + ** @param stream open C output stream + * @param frame index of frame used for output (default: first frame = 0) + * @param bits number of bits used for output of pixel data (8, 24 or 32) + * + ** @return true if successful, false otherwise + */ + virtual int writeBMP(FILE *stream, + const unsigned long frame, + const int bits); + + + protected: + + /** constructor + * + ** @param docu pointer to the DICOM document + * @param status status of the image object + */ + DiImage(const DiDocument *docu, + const EI_Status status); + + /** constructor, copy + * + ** @param image pointer to reference image + * @param fstart first frame to be processed + * @param fcount number of frames + */ + DiImage(const DiImage *image, + const unsigned long fstart, + const unsigned long fcount); + + /** constructor, scale/clip + * + ** @param image pointer to reference image + * @param width number of columns of the new image + * @param height number of rows of the new image + * @param aspect flag indicating whether pixel aspect ratio should be used or not + */ + DiImage(const DiImage *image, + const Uint16 width, + const Uint16 height, + const int aspect = 0); + + /** constructor, rotate + * + ** @param image pointer to reference image + * @param degree angle by which the image shall be rotated + */ + DiImage(const DiImage *image, + const int degree = 0); + + /** constructor, createMonoOutput + * + ** @param image pointer to reference image + * @param frame number of frame stored in the new image object + * @param stored number of bits stored + * @param alloc number of bits allocated + */ + DiImage(const DiImage *image, + const unsigned long frame, + const int stored, + const int alloc); + + /** delete internally handled object for the input pixel data conversion + */ + void deleteInputData(); + + /** check and possibly correct values for pixel spacing, aspect ratio etc. + */ + void checkPixelExtension(); + + /** create input pixel data representation from DICOM dataset structures + */ + void convertPixelData(); + + /** update Image Pixel Module attributes in the given dataset. + * Removes smallest/largest pixel value and updates pixel aspect ratio as well + * as pixel spacing (if required). + * Used in writeXXXToDataset() routines. + * + ** @param dataset reference to DICOM image dataset + */ + virtual void updateImagePixelModuleAttributes(DcmItem &dataset); + + /** detach pixel data. + * removes storage area used for the pixel data from memory + */ + int detachPixelData(); + + /// copy of status variable declared in class 'DicomImage' + EI_Status ImageStatus; + /// points to special object, which encapsulates the dcmdata module + const DiDocument *Document; + + /// first frame to be processed + Uint32 FirstFrame; + /// number of frames in case of multi-frame images (otherwise '1') + Uint32 NumberOfFrames; + /// total number of frames stored in the dataset + Uint32 TotalNumberOfFrames; + /// number of representative frame, type 3 attribute (default '0') + Uint32 RepresentativeFrame; + /// nominal time between individual frames (0 if absent) + double FrameTime; + /// number of rows (in pixel) + Uint16 Rows; + /// number of columns (in pixel) + Uint16 Columns; + /// width of each pixel according to 'PixelSpacing/AspectRatio' + double PixelWidth; + /// height of each pixel according to 'PixelSpacing/AspectRatio' + double PixelHeight; + /// number of bits allocated for each pixel + Uint16 BitsAllocated; + /// number of bits stored for each pixel (see 'BitsPerSample') + Uint16 BitsStored; + /// position of highest stored bit + Uint16 HighBit; + + /// actual number of bits per sample (depth) + int BitsPerSample; + /// number of samples per pixel (1, 3 or 4) + int SamplesPerPixel; + + /// polarity (normal or reverse) + EP_Polarity Polarity; + + /// is 'true' if pixel data is signed + int hasSignedRepresentation; + /// is 'true' if attribute 'PixelSpacing' is present + int hasPixelSpacing; + /// is 'true' if attribute 'ImagerPixelSpacing' is present + int hasImagerPixelSpacing; + /// is 'true' if attribute 'hasNominalScannedPixelSpacing' is present + int hasNominalScannedPixelSpacing; + /// is 'true' if attribute 'PixelAspectRatio' is present + int hasPixelAspectRatio; + /// is 'false' if derived from original image data (e.g. scaled) + int isOriginal; + + /// points to intermediate pixel representation (template object) + DiInputPixel *InputData; + /// file cache object used for partial read + DcmFileCache FileCache; + /// current pixel item fragment (for encapsulated pixel data) + Uint32 CurrentFragment; + + // --- declarations to avoid compiler warnings + + DiImage(const DiImage &); + DiImage &operator=(const DiImage &); +}; + + +#endif diff --git a/dcmimgle/include/dcmtk/dcmimgle/diinpx.h b/dcmimgle/include/dcmtk/dcmimgle/diinpx.h new file mode 100644 index 00000000..ade09a34 --- /dev/null +++ b/dcmimgle/include/dcmtk/dcmimgle/diinpx.h @@ -0,0 +1,208 @@ +/* + * + * Copyright (C) 1996-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimgle + * + * Author: Joerg Riesmeier + * + * Purpose: DicomInputPixel (Header) + * + */ + + +#ifndef DIINPX_H +#define DIINPX_H + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/dcmimgle/diutils.h" + + +/*---------------------* + * class declaration * + *---------------------*/ + +/** Abstract base class to convert DICOM pixel stream to intermediate representation + */ +class DCMTK_DCMIMGLE_EXPORT DiInputPixel +{ + + public: + + /** constructor + * + ** @param bits number of bits stored for each pixel (depth) + * @param first first frame to be processed + * @param number number of frames to be processed + * @param fsize number of pixels per frame (frame size) + */ + DiInputPixel(const unsigned int bits, + const unsigned long first, + const unsigned long number, + const unsigned long fsize); + + /** destructor + */ + virtual ~DiInputPixel(); + + /** determine minimum and maximum pixel value (abstract) + * + ** @return status, true if successful, false otherwise + */ + virtual int determineMinMax() = 0; + + /** get pixel representation (abstract). + * Determine which integer type (size and signed/unsigned) is necessary to store + * the pixel data. + * + ** @return pixel representation + */ + virtual EP_Representation getRepresentation() const = 0; + + /** get pointer to input pixel data (abstract) + * + ** @return pointer to input pixel data + */ + virtual const void *getData() const = 0; + + /** get pointer to input pixel data (abstract) + * + ** @return pointer to input pixel data + */ + virtual void *getDataPtr() = 0; + + /** remove reference to (internally handled) pixel data (abstract) + */ + virtual void removeDataReference() = 0; + + /** get minimum pixel value (abstract) + * + ** @param idx specifies whether to return the global minimum (0) or + * the minimum of the selected pixel range (1, see PixelStart/Range) + * + ** @return minimum pixel value + */ + virtual double getMinValue(const int idx) const = 0; + + /** get maximum pixel value (abstract) + * + ** @param idx specifies whether to return the global maximum (0) or + * the maximum of the selected pixel range (1, see PixelStart/Range) + * + ** @return maximum pixel value + */ + virtual double getMaxValue(const int idx) const = 0; + + /** get number of bits per pixel + * + ** @return number of bits per pixel + */ + inline unsigned int getBits() const + { + return Bits; + } + + /** get absolute minimum pixel value + * + ** @return absolute minimum pixel value + */ + inline double getAbsMinimum() const + { + return AbsMinimum; + } + + /** get absolute maximum pixel value + * + ** @return absolute maximum pixel value + */ + inline double getAbsMaximum() const + { + return AbsMaximum; + } + + /** get absolute pixel value range + * + ** @return absolute pixel value range + */ + inline double getAbsMaxRange() const + { + return AbsMaximum - AbsMinimum + 1; + } + + /** get number of pixels stored + * + ** @return number of pixels stored + */ + inline unsigned long getCount() const + { + return Count; + } + + /** get first pixel to be processed + * + ** @return first pixel to be processed + */ + inline unsigned long getPixelStart() const + { + return PixelStart; + } + + /** get number of pixels to be processed + * + ** @return number of pixels to be processed + */ + inline unsigned long getPixelCount() const + { + return PixelCount; + } + + /** get number of pixels computed from the image resolution + * + ** @return number of pixels computed + */ + inline unsigned long getComputedCount() const + { + return ComputedCount; + } + + + protected: + + /// number of pixels stored + unsigned long Count; + /// bits per pixel/sample + unsigned int Bits; + + /// first frame to be processed + unsigned long FirstFrame; + /// number of frames to be processed + unsigned long NumberOfFrames; + /// number of pixels per frame + unsigned long FrameSize; + + /// first pixel to be processed + unsigned long PixelStart; + /// number of pixels to be processed + unsigned long PixelCount; + + /// number of pixels computed from the image resolution + unsigned long ComputedCount; + + /// absolute minimum (possible) pixel value + double AbsMinimum; + /// absolute maximum (possible) pixel value + double AbsMaximum; +}; + + +#endif diff --git a/dcmimgle/include/dcmtk/dcmimgle/diinpxt.h b/dcmimgle/include/dcmtk/dcmimgle/diinpxt.h new file mode 100644 index 00000000..6a05cbe7 --- /dev/null +++ b/dcmimgle/include/dcmtk/dcmimgle/diinpxt.h @@ -0,0 +1,673 @@ +/* + * + * Copyright (C) 1996-2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimgle + * + * Author: Joerg Riesmeier + * + * Purpose: DicomInputPixelTemplate (Header) + * + */ + + +#ifndef DIINPXT_H +#define DIINPXT_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmdata/dcpixel.h" + +#include "dcmtk/ofstd/ofbmanip.h" +#include "dcmtk/ofstd/ofcast.h" + +#include "dcmtk/dcmimgle/diinpx.h" +#include "dcmtk/dcmimgle/didocu.h" +#include "dcmtk/dcmimgle/dipxrept.h" + + +/*--------------------* + * helper functions * + *--------------------*/ + +static inline Uint8 expandSign(const Uint8 Value, + const Uint8, + const Uint8) +{ + return Value; +} + + +static inline Uint16 expandSign(const Uint16 Value, + const Uint16, + const Uint16) +{ + return Value; +} + + +static inline Uint32 expandSign(const Uint32 Value, + const Uint32, + const Uint32) +{ + return Value; +} + + +static inline Sint8 expandSign(const Sint8 Value, + const Sint8 SignBit, + const Sint8 SignMask) +{ + return (Value & SignBit) ? (Value | SignMask) : Value; +} + + +static inline Sint16 expandSign(const Sint16 Value, + const Sint16 SignBit, + const Sint16 SignMask) +{ + return (Value & SignBit) ? (Value | SignMask) : Value; +} + + +static inline Sint32 expandSign(const Sint32 Value, + const Sint32 SignBit, + const Sint32 SignMask) +{ + return (Value & SignBit) ? (Value | SignMask) : Value; +} + + +static Uint32 getPixelData(DcmPixelData *PixelData, + Uint8 *&pixel) +{ + PixelData->getUint8Array(pixel); + return PixelData->getLength(); +} + + +static Uint32 getPixelData(DcmPixelData *PixelData, + Uint16 *&pixel) +{ + PixelData->getUint16Array(pixel); + return PixelData->getLength(); +} + + +/*---------------------* + * class declaration * + *---------------------*/ + +/** Template class to convert DICOM pixel stream to intermediate representation + */ +template +class DiInputPixelTemplate + : public DiInputPixel, + public DiPixelRepresentationTemplate +{ + + public: + + /** constructor + * + ** @param document pointer to DICOM image object + * @param alloc number of bits allocated for each pixel + * @param stored number of bits stored for each pixel + * @param high position of high bit within bits allocated + * @param first first frame to be processed + * @param number number of frames to be processed + * @param fsize number of pixels per frame (frame size) + * @param fileCache pointer to file cache object used for partial read + * @param fragment current pixel item fragment (for encapsulated pixel data) + */ + DiInputPixelTemplate(const DiDocument *document, + const Uint16 alloc, + const Uint16 stored, + const Uint16 high, + const unsigned long first, + const unsigned long number, + const unsigned long fsize, + DcmFileCache *fileCache, + Uint32 &fragment) + : DiInputPixel(stored, first, number, fsize), + Data(NULL) + { + MinValue[0] = 0; + MinValue[1] = 0; + MaxValue[0] = 0; + MaxValue[1] = 0; + if (this->isSigned()) + { + AbsMinimum = -OFstatic_cast(double, DicomImageClass::maxval(Bits - 1, 0)); + AbsMaximum = OFstatic_cast(double, DicomImageClass::maxval(Bits - 1)); + } else { + AbsMinimum = 0; + AbsMaximum = OFstatic_cast(double, DicomImageClass::maxval(Bits)); + } + if ((document != NULL) && (document->getPixelData() != NULL)) + convert(document, alloc, stored, high, fileCache, fragment); + if ((PixelCount == 0) || (PixelStart + PixelCount > Count)) // check for corrupt pixel length + { + PixelCount = Count - PixelStart; + DCMIMGLE_DEBUG("setting number of pixels to be processed (PixelCount) to: " << PixelCount); + } + } + + /** destructor + */ + virtual ~DiInputPixelTemplate() + { +#if defined(HAVE_STD__NOTHROW) && defined(HAVE_NOTHROW_DELETE) + /* use a non-throwing delete (if available) */ + operator delete[] (Data, std::nothrow); +#else + delete[] Data; +#endif + } + + /** determine minimum and maximum pixel value + * + ** @return status, true if successful, false otherwise + */ + int determineMinMax() + { + if (Data != NULL) + { + DCMIMGLE_DEBUG("determining minimum and maximum pixel values for input data"); + register T2 *p = Data; + register unsigned long i; + const unsigned long ocnt = OFstatic_cast(unsigned long, getAbsMaxRange()); + Uint8 *lut = NULL; + if ((sizeof(T2) <= 2) && (Count > 3 * ocnt)) // optimization criteria + { + lut = new Uint8[ocnt]; + if (lut != NULL) + { + DCMIMGLE_DEBUG("using optimized routine with additional LUT"); + OFBitmanipTemplate::zeroMem(lut, ocnt); + register Uint8 *q = lut - OFstatic_cast(T2, getAbsMinimum()); + for (i = Count; i != 0; --i) // fill lookup table + *(q + *(p++)) = 1; + q = lut; + for (i = 0; i < ocnt; ++i) // search for minimum + { + if (*(q++) != 0) + { + MinValue[0] = OFstatic_cast(T2, OFstatic_cast(double, i) + getAbsMinimum()); + break; + } + } + q = lut + ocnt; + for (i = ocnt; i != 0; --i) // search for maximum + { + if (*(--q) != 0) + { + MaxValue[0] = OFstatic_cast(T2, OFstatic_cast(double, i - 1) + getAbsMinimum()); + break; + } + } + if (Count >= PixelCount) // use global min/max value + { + MinValue[1] = MinValue[0]; + MaxValue[1] = MaxValue[0]; + } else { // calculate min/max for selected range + OFBitmanipTemplate::zeroMem(lut, ocnt); + p = Data + PixelStart; + q = lut - OFstatic_cast(T2, getAbsMinimum()); + for (i = PixelCount; i != 0; --i) // fill lookup table + *(q + *(p++)) = 1; + q = lut; + for (i = 0; i < ocnt; ++i) // search for minimum + { + if (*(q++) != 0) + { + MinValue[1] = OFstatic_cast(T2, OFstatic_cast(double, i) + getAbsMinimum()); + break; + } + } + q = lut + ocnt; + for (i = ocnt; i != 0; --i) // search for maximum + { + if (*(--q) != 0) + { + MaxValue[1] = OFstatic_cast(T2, OFstatic_cast(double, i - 1) + getAbsMinimum()); + break; + } + } + } + } + } + if (lut == NULL) // use conventional method + { + register T2 value = *p; + MinValue[0] = value; + MaxValue[0] = value; + for (i = Count; i > 1; --i) + { + value = *(++p); + if (value < MinValue[0]) + MinValue[0] = value; + else if (value > MaxValue[0]) + MaxValue[0] = value; + } + if (Count <= PixelCount) // use global min/max value + { + MinValue[1] = MinValue[0]; + MaxValue[1] = MaxValue[0]; + } else { // calculate min/max for selected range + p = Data + PixelStart; + value = *p; + MinValue[1] = value; + MaxValue[1] = value; + for (i = PixelCount; i > 1; --i) + { + value = *(++p); + if (value < MinValue[1]) + MinValue[1] = value; + else if (value > MaxValue[1]) + MaxValue[1] = value; + } + } + } + delete[] lut; + return 1; + } + return 0; + } + + /** get pixel representation + * + ** @return pixel representation + */ + inline EP_Representation getRepresentation() const + { + return DiPixelRepresentationTemplate::getRepresentation(); + } + + /** get pointer to input pixel data + * + ** @return pointer to input pixel data + */ + inline const void *getData() const + { + return OFstatic_cast(const void *, Data); + } + + /** get reference to pointer to input pixel data + * + ** @return reference to pointer to input pixel data + */ + virtual void *getDataPtr() + { + return OFstatic_cast(void *, Data); + } + + /** remove reference to (internally handled) pixel data + */ + inline void removeDataReference() + { + Data = NULL; + } + + /** get minimum pixel value + * + ** @param idx specifies whether to return the global minimum (0) or + * the minimum of the selected pixel range (1, see PixelStart/Range) + * + ** @return minimum pixel value + */ + inline double getMinValue(const int idx) const + { + return (idx == 0) ? OFstatic_cast(double, MinValue[0]) : OFstatic_cast(double, MinValue[1]); + } + + /** get maximum pixel value + * + ** @param idx specifies whether to return the global maximum (0) or + * the maximum of the selected pixel range (1, see PixelStart/Range) + * + ** @return maximum pixel value + */ + inline double getMaxValue(const int idx) const + { + return (idx == 0) ? OFstatic_cast(double, MaxValue[0]) : OFstatic_cast(double, MaxValue[1]); + } + + + private: + + /** convert pixel data from DICOM dataset to input representation + * + ** @param document pointer to DICOM image object + * @param bitsAllocated number of bits allocated for each pixel + * @param bitsStored number of bits stored for each pixel + * @param highBit position of high bit within bits allocated + * @param fileCache pointer to file cache object used for partial read + * @param fragment current pixel item fragment (for encapsulated pixel data) + */ + void convert(const DiDocument *document, + const Uint16 bitsAllocated, + const Uint16 bitsStored, + const Uint16 highBit, + DcmFileCache *fileCache, + Uint32 &fragment) + { + T1 *pixel = NULL; + OFBool deletePixel = OFFalse; + Uint32 lengthBytes = 0; + DcmPixelData *pixelData = document->getPixelData(); + const Uint16 bitsof_T1 = bitsof(T1); + const Uint16 bitsof_T2 = bitsof(T2); + const OFBool uncompressed = pixelData->canWriteXfer(EXS_LittleEndianExplicit, EXS_Unknown); + /* check whether to use partial read */ + if ((document->getFlags() & CIF_UsePartialAccessToPixelData) && (PixelCount > 0) && (bitsAllocated % 8 == 0)) + { + /* Bits Allocated is always a multiple of 8 (see above), same for bits of T1 */ + const Uint32 byteFactor = bitsAllocated / 8; + const Uint32 bytes_T1 = bitsof_T1 / 8; + const Uint32 count_T1 = (byteFactor == bytes_T1) ? PixelCount : (PixelCount * byteFactor + bytes_T1 - 1) / bytes_T1; +#ifdef DEBUG + DCMIMGLE_TRACE("PixelCount: " << PixelCount << ", byteFactor: " << byteFactor << ", bytes_T1: " << bytes_T1 << ", count_T1: " << count_T1); +#endif + /* allocate temporary buffer, even number of bytes required for getUncompressedFrame() */ + const Uint32 extraByte = ((sizeof(T1) == 1) && (count_T1 & 1)) ? 1 : 0; +#ifdef HAVE_STD__NOTHROW + /* use a non-throwing new here (if available) because the allocated buffer can be huge */ + pixel = new (std::nothrow) T1[count_T1 + extraByte]; +#else + /* make sure that the pointer is set to NULL in case of error */ + try + { + pixel = new T1[count_T1 + extraByte]; + } + catch (STD_NAMESPACE bad_alloc const &) + { + pixel = NULL; + } +#endif + if (pixel != NULL) + { + if (uncompressed) + { + DCMIMGLE_DEBUG("using partial read access to uncompressed pixel data"); + const Uint32 offset = PixelStart * byteFactor; + const Uint32 bufSize = PixelCount * byteFactor; + const OFCondition status = pixelData->getPartialValue(pixel, offset, bufSize, fileCache); + if (status.good()) + { + PixelStart = 0; + lengthBytes = bufSize; + } else { + DCMIMGLE_ERROR("can't access partial value from byte offset " << offset << " to " + << (offset + bufSize - 1) << ": " << status.text()); + } + } else { + DCMIMGLE_DEBUG("using partial read access to compressed pixel data"); + OFCondition status = EC_IllegalCall; + OFString decompressedColorModel; + const Uint32 fsize = FrameSize * byteFactor; + for (Uint32 frame = 0; frame < NumberOfFrames; ++frame) + { + /* make sure that the buffer always has an even number of bytes as required for getUncompressedFrame() */ + const Uint32 bufSize = (fsize & 1) ? fsize + 1 : fsize; + status = pixelData->getUncompressedFrame(document->getDataset(), FirstFrame + frame, fragment, + OFreinterpret_cast(Uint8 *, pixel) + lengthBytes, bufSize, decompressedColorModel, fileCache); + if (status.good()) + { + DCMIMGLE_TRACE("successfully decompressed frame " << FirstFrame + frame); + lengthBytes += fsize; + } else { + DCMIMGLE_ERROR("can't decompress frame " << FirstFrame + frame << ": " << status.text()); + break; + } + } + if (status.good()) + PixelStart = 0; + /* check whether color model changed during decompression */ + if (!decompressedColorModel.empty() && (decompressedColorModel != document->getPhotometricInterpretation())) + { + DCMIMGLE_WARN("Photometric Interpretation of decompressed pixel data deviates from original image: " + << decompressedColorModel); + } + } + deletePixel = OFTrue; + } else + DCMIMGLE_DEBUG("cannot allocate memory buffer for 'pixel' in DiInputPixelTemplate::convert()"); + } else { + DCMIMGLE_DEBUG("reading uncompressed pixel data completely into memory"); + /* always access complete pixel data */ + lengthBytes = getPixelData(pixelData, pixel); + } + if ((pixel != NULL) && (lengthBytes > 0)) + { + const Uint32 length_T1 = lengthBytes / sizeof(T1); + /* need to split 'length' in order to avoid integer overflow for large pixel data */ + const Uint32 length_B1 = lengthBytes / bitsAllocated; + const Uint32 length_B2 = lengthBytes % bitsAllocated; +// # old code: Count = ((lengthBytes * 8) + bitsAllocated - 1) / bitsAllocated; + Count = 8 * length_B1 + (8 * length_B2 + bitsAllocated - 1) / bitsAllocated; + register unsigned long i; +#ifdef HAVE_STD__NOTHROW + /* use a non-throwing new here (if available) because the allocated buffer can be huge */ + Data = new (std::nothrow) T2[Count]; +#else + /* make sure that the pointer is set to NULL in case of error */ + try + { + Data = new T2[Count]; + } + catch (STD_NAMESPACE bad_alloc const &) + { + Data = NULL; + } +#endif + if (Data != NULL) + { + DCMIMGLE_TRACE("Input length: " << lengthBytes << " bytes, Pixel count: " << Count + << " (" << PixelCount << "), In: " << bitsof_T1 << " bits, Out: " << bitsof_T2 + << " bits (" << (this->isSigned() ? "signed" : "unsigned") << ")"); + register const T1 *p = pixel; + register T2 *q = Data; + if (bitsof_T1 == bitsAllocated) // case 1: equal 8/16 bit + { + if (bitsStored == bitsAllocated) + { + DCMIMGLE_DEBUG("convert input pixel data: case 1a (single copy)"); + for (i = Count; i != 0; --i) + *(q++) = OFstatic_cast(T2, *(p++)); + } + else /* bitsStored < bitsAllocated */ + { + register T1 mask = 0; + for (i = 0; i < bitsStored; ++i) + mask |= OFstatic_cast(T1, 1 << i); + const T2 sign = 1 << (bitsStored - 1); + T2 smask = 0; + for (i = bitsStored; i < bitsof_T2; ++i) + smask |= OFstatic_cast(T2, 1 << i); + const Uint16 shift = highBit + 1 - bitsStored; + if (shift == 0) + { + DCMIMGLE_DEBUG("convert input pixel data: case 1b (mask & sign)"); + for (i = length_T1; i != 0; --i) + *(q++) = expandSign(OFstatic_cast(T2, *(p++) & mask), sign, smask); + } + else /* shift > 0 */ + { + DCMIMGLE_DEBUG("convert input pixel data: case 1c (shift & mask & sign)"); + for (i = length_T1; i != 0; --i) + *(q++) = expandSign(OFstatic_cast(T2, (*(p++) >> shift) & mask), sign, smask); + } + } + } + else if ((bitsof_T1 > bitsAllocated) && (bitsof_T1 % bitsAllocated == 0)) // case 2: divisor of 8/16 bit + { + const Uint16 times = bitsof_T1 / bitsAllocated; + register T1 mask = 0; + for (i = 0; i < bitsStored; ++i) + mask |= OFstatic_cast(T1, 1 << i); + register Uint16 j; + register T1 value; + if ((bitsStored == bitsAllocated) && (bitsStored == bitsof_T2)) + { + if (times == 2) + { + DCMIMGLE_DEBUG("convert input pixel data: case 2a (simple mask)"); + for (i = length_T1; i != 0; --i, ++p) + { + *(q++) = OFstatic_cast(T2, *p & mask); + *(q++) = OFstatic_cast(T2, *p >> bitsAllocated); + } + /* check for additional input pixel (in case of odd length when using partial access) */ + if (length_T1 * 2 /* times */ < lengthBytes) + { + DCMIMGLE_TRACE("found trailing pixel at the end of odd-length input data ... copying value"); + *(q++) = OFstatic_cast(T2, *p & mask); + } + } + else + { + DCMIMGLE_DEBUG("convert input pixel data: case 2b (mask)"); + for (i = length_T1; i != 0; --i) + { + value = *(p++); + for (j = times; j != 0; --j) + { + *(q++) = OFstatic_cast(T2, value & mask); + value >>= bitsAllocated; + } + } + } + } + else + { + DCMIMGLE_DEBUG("convert input pixel data: case 2c (shift & mask & sign)"); + const T2 sign = 1 << (bitsStored - 1); + T2 smask = 0; + for (i = bitsStored; i < bitsof_T2; ++i) + smask |= OFstatic_cast(T2, 1 << i); + const Uint16 shift = highBit + 1 - bitsStored; + for (i = length_T1; i != 0; --i) + { + value = *(p++) >> shift; + for (j = times; j != 0; --j) + { + *(q++) = expandSign(OFstatic_cast(T2, value & mask), sign, smask); + value >>= bitsAllocated; + } + } + } + } + else if ((bitsof_T1 < bitsAllocated) && (bitsAllocated % bitsof_T1 == 0) // case 3: multiplicand of 8/16 + && (bitsStored == bitsAllocated)) + { + DCMIMGLE_DEBUG("convert input pixel data: case 3 (multi copy)"); + const Uint16 times = bitsAllocated / bitsof_T1; + register Uint16 j; + register Uint16 shift; + register T2 value; + for (i = length_T1; i != 0; --i) + { + shift = 0; + value = OFstatic_cast(T2, *(p++)); + for (j = times; j > 1; --j, --i) + { + shift += bitsof_T1; + value |= OFstatic_cast(T2, *(p++)) << shift; + } + *(q++) = value; + } + } + else // case 4: anything else + { + DCMIMGLE_DEBUG("convert input pixel data: case 4 (general)"); + register T2 value = 0; + register Uint16 bits = 0; + register Uint32 skip = highBit + 1 - bitsStored; + register Uint32 times; + T1 mask[bitsof_T1]; + mask[0] = 1; + for (i = 1; i < bitsof_T1; ++i) + mask[i] = (mask[i - 1] << 1) | 1; + T2 smask = 0; + for (i = bitsStored; i < bitsof_T2; ++i) + smask |= OFstatic_cast(T2, 1 << i); + const T2 sign = 1 << (bitsStored - 1); + const Uint32 gap = bitsAllocated - bitsStored; + i = 0; + while (i < length_T1) + { + if (skip < bitsof_T1) + { + if (skip + bitsStored - bits < bitsof_T1) // -++- --++ + { + value |= (OFstatic_cast(T2, (*p >> skip) & mask[bitsStored - bits - 1]) << bits); + skip += bitsStored - bits + gap; + bits = bitsStored; + } + else // ++-- ++++ + { + value |= (OFstatic_cast(T2, (*p >> skip) & mask[bitsof_T1 - skip - 1]) << bits); + bits += bitsof_T1 - OFstatic_cast(Uint16, skip); + skip = (bits == bitsStored) ? gap : 0; + ++i; + ++p; + } + if (bits == bitsStored) + { + *(q++) = expandSign(value, sign, smask); + value = 0; + bits = 0; + } + } + else + { + times = skip / bitsof_T1; + i += times; + p += times; + skip -= times * bitsof_T1; + } + } + } + } else + DCMIMGLE_DEBUG("cannot allocate memory buffer for 'Data' in DiInputPixelTemplate::convert()"); + } else { + /* in case of error, reset pixel count variable */ + Count = 0; + } + if (deletePixel) + { + /* delete temporary buffer */ +#if defined(HAVE_STD__NOTHROW) && defined(HAVE_NOTHROW_DELETE) + /* use a non-throwing delete (if available) */ + operator delete[] (pixel, std::nothrow); +#else + delete[] pixel; +#endif + } + } + + /// pointer to pixel data + T2 *Data; + + /// minimum pixel value ([0] = global, [1] = selected pixel range) + T2 MinValue[2]; + /// maximum pixel value ([0] = global, [1] = selected pixel range) + T2 MaxValue[2]; + + // --- declarations to avoid compiler warnings + + DiInputPixelTemplate(const DiInputPixelTemplate &); + DiInputPixelTemplate &operator=(const DiInputPixelTemplate &); +}; + + +#endif diff --git a/dcmimgle/include/dcmtk/dcmimgle/diluptab.h b/dcmimgle/include/dcmtk/dcmimgle/diluptab.h new file mode 100644 index 00000000..4383f350 --- /dev/null +++ b/dcmimgle/include/dcmtk/dcmimgle/diluptab.h @@ -0,0 +1,251 @@ +/* + * + * Copyright (C) 1996-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimgle + * + * Author: Joerg Riesmeier + * + * Purpose: DicomLookupTable (Header) + * + */ + + +#ifndef DILUPTAB_H +#define DILUPTAB_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmdata/dctagkey.h" + +#include "dcmtk/dcmimgle/dibaslut.h" +#include "dcmtk/dcmimgle/diobjcou.h" + + +/*------------------------* + * forward declarations * + *------------------------*/ + +class DcmObject; +class DcmUnsignedShort; +class DcmLongString; +class DiDocument; +class DcmItem; + + +/*---------------------* + * class declaration * + *---------------------*/ + +/** Class to handle color palette look-up tables + */ +class DCMTK_DCMIMGLE_EXPORT DiLookupTable + : public DiBaseLUT, + public DiObjectCounter +{ + + public: + + /** constructor + * + ** @param docu pointer to dataset (encapsulated) + * @param descriptor tag key containing the LUT descriptor + * @param data tag key containing the LUT data + * @param explanation tag key containing the LUT explanation + * @param descripMode mode specifying the use of the bits per table entry value + * @param status pointer to image status variable (optional) + */ + DiLookupTable(const DiDocument *docu, + const DcmTagKey &descriptor, + const DcmTagKey &data, + const DcmTagKey &explanation, + const EL_BitsPerTableEntry descripMode = ELM_UseValue, + EI_Status *status = NULL); + + /** constructor + * + ** @param docu pointer to dataset (encapsulated) + * @param sequence tag key containing the LUT sequence + * @param descriptor tag key containing the LUT descriptor + * @param data tag key containing the LUT data + * @param explanation tag key containing the LUT explanation + * @param descripMode mode specifying the use of the bits per table entry value + * @param pos position in the LUT sequence which should be used (optional) + * @param card pointer to storage area where the number of sequence entries + * should be stored (optional) + */ + DiLookupTable(const DiDocument *docu, + const DcmTagKey &sequence, + const DcmTagKey &descriptor, + const DcmTagKey &data, + const DcmTagKey &explanation, + const EL_BitsPerTableEntry descripMode = ELM_UseValue, + const unsigned long pos = 0, + unsigned long *card = NULL); + + /** constructor + * + ** @param data element containing the LUT data + * @param descriptor element containing the LUT descriptor + * @param explanation element containing the LUT explanation (optional) + * @param descripMode mode specifying the use of the bits per table entry value + * @param first expected value for "first input value mapped" (optional) + * @param status pointer to image status variable (optional) + */ + DiLookupTable(const DcmUnsignedShort &data, + const DcmUnsignedShort &descriptor, + const DcmLongString *explanation = NULL, + const EL_BitsPerTableEntry descripMode = ELM_UseValue, + const signed long first = -1, + EI_Status *status = NULL); + + /** constructor + * + ** @param buffer pointer to array with LUT entries + * @param count number of LUT entries + * @param bits number of bits per entry + */ + DiLookupTable(Uint16 *buffer, + const Uint32 count, + const Uint16 bits); + + /** destructor + */ + virtual ~DiLookupTable(); + + /** invert all LUT values. + * (new_value = max_value - old_value, e.g. used for presentation LUTs) + * + ** @param flag if bit 0 is set (0x1, default) the internal copy of the LUT data is modified + * or a copy of the original data is created (if not already existing), + * if bit 1 is set (0x2) the original LUT data is modified, + * a combination of both modes is also supported. + * + ** @return status true if successful (0x1 if internal data modified, 0x2 if original data, 0x3 if both), + * false otherwise + */ + int invertTable(const int flag = 0x1); + + /** mirror the order of all LUT entries. + * i.e. the last one becomes the first etc. + * (value[i] = value[last - i], e.g. used for presentation LUTs) + * + ** @param flag if bit 0 is set (0x1, default) the internal copy of the LUT data is modified + * or a copy of the original data is created (if not already existing), + * if bit 1 is set (0x2) the original LUT data is modified, + * a combination of both modes is also supported. + * + ** @return status true if successful (0x1 if internal data modified, 0x2 if original data, 0x3 if both), + * false otherwise + */ + int mirrorTable(const int flag = 0x1); + + /** create an inverse copy of the current LUT. + * (input values become output values and vice versa) + * This function is used for DICOM print (mainly 8<->12 bit). + * + ** @return pointer to inverse LUT + */ + DiLookupTable *createInverseLUT() const; + + /** compares current LUT with specified LUT + * + ** @param data element containing the LUT data + * @param descriptor element containing the LUT descriptor + * + ** @return true if LUTs are not equal (1 = invalid LUT / memory error, + * 2 = descriptor differs, + * 3 = data differs) + * false (0) otherwise + */ + int compareLUT(const DcmUnsignedShort &data, + const DcmUnsignedShort &descriptor); + + + /** compares current LUT with specified LUT + * + ** @param lut LUT to be compared with the current one + * + ** @return OFTrue if LUTs are equal, OFFalse otherwise + */ + virtual OFBool operator==(const DiBaseLUT &lut); + + /** compares current LUT with specified LUT + * + ** @param lut LUT to be compared with the current one + * + ** @return OFTrue if LUTs are equal, OFFalse otherwise + */ + virtual OFBool operator==(const DiLookupTable &lut); + + + protected: + + /** initialize lookup table + * + ** @param docu pointer to dataset (encapsulated) + * @param item pointer to item in dataset where to start (maybe NULL) + * @param descriptor tag key containing the LUT descriptor + * @param data tag key containing the LUT data + * @param explanation tag key containing the LUT explanation + * @param descripMode mode specifying the use of the bits per table entry value + * @param status pointer to image status variable (optional) + */ + void Init(const DiDocument *docu, + DcmItem *item, + const DcmTagKey &descriptor, + const DcmTagKey &data, + const DcmTagKey &explanation, + const EL_BitsPerTableEntry descripMode = ELM_UseValue, + EI_Status *status = NULL); + + /** check (and possibly correct) lookup table for consistency + * + ** @param count number of LUT entries + * @param bits bits per LUT entry + * @param descripMode mode specifying the use of the bits per table entry value + * @param status pointer to image status variable (optional) + */ + void checkTable(unsigned long count, + Uint16 bits, + const EL_BitsPerTableEntry descripMode = ELM_UseValue, + EI_Status *status = NULL); + + /** check (and possibly correct) value for bits per LUT entry. + * Be very lenient with the value stored in the LUT descriptor and + * therefore perform some addition (heuristical tests) to assume the + * most probable value. + * + ** @param bits actual value for bits per entry + * @param rightBits right value (8 or 16) + * @param wrongBits wrong value (8 or 16) + * @param descripMode mode specifying the use of the bits per table entry value + */ + void checkBits(const Uint16 bits, + const Uint16 rightBits, + const Uint16 wrongBits = 0, + const EL_BitsPerTableEntry descripMode = ELM_UseValue); + + private: + + /// number of bits originally allocated for a LUT entry + int OriginalBitsAllocated; + /// pointer to original data buffer (where the LUT data is created from) + void *OriginalData; + + // --- declarations to avoid compiler warnings + + DiLookupTable(const DiLookupTable &); + DiLookupTable &operator=(const DiLookupTable &); +}; + + +#endif diff --git a/dcmimgle/include/dcmtk/dcmimgle/dimo1img.h b/dcmimgle/include/dcmtk/dcmimgle/dimo1img.h new file mode 100644 index 00000000..ec50d783 --- /dev/null +++ b/dcmimgle/include/dcmtk/dcmimgle/dimo1img.h @@ -0,0 +1,227 @@ +/* + * + * Copyright (C) 1996-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimgle + * + * Author: Joerg Riesmeier + * + * Purpose: DicomMonochrome1Image (Header) + * + */ + + +#ifndef DIMO1IMG_H +#define DIMO1IMG_H + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/dcmimgle/dimoimg.h" + + +/*---------------------* + * class declaration * + *---------------------*/ + +/** Class for MONOCHROME1 images + */ +class DCMTK_DCMIMGLE_EXPORT DiMono1Image + : public DiMonoImage +{ + + public: + + /** constructor + * + ** @param docu pointer to dataset (encapsulated) + * @param status current image status + */ + DiMono1Image(const DiDocument *docu, + const EI_Status status); + + /** destructor + */ + virtual ~DiMono1Image(); + + /** get color model of internal pixel representation. + * @return always returns EPI_Monochrome1 + */ + virtual EP_Interpretation getInternalColorModel() const + { + return EPI_Monochrome1; + } + + /** get pixel data with specified format. + * (memory is handled internally) + * + ** @param frame number of frame to be rendered + * @param bits number of bits for the output pixel data (depth) + * @param planar flags, whether the output data (for multi-planar images) should be planar or not + * + ** @return untyped pointer to the pixel data if successful, NULL otherwise + */ + virtual const void *getOutputData(const unsigned long frame, + const int bits, + const int planar = 0); + + /** get pixel data with specified format. + * (memory is handled externally) + * + ** @param buffer untyped pointer to the externally allocated memory buffer + * @param size size of the memory buffer in bytes (will be checked) + * @param frame number of frame to be rendered + * @param bits number of bits for the output pixel data (depth) + * @param planar flags, whether the output data (for multi-planar images) should be planar or not + * + ** @return status, true if successful, false otherwise + */ + virtual int getOutputData(void *buffer, + const unsigned long size, + const unsigned long frame, + const int bits, + const int planar = 0); + + /** create copy of current image object + * + ** @param fstart first frame to be processed + * @param fcount number of frames + * + ** @return pointer to new DicomImage object (NULL if an error occurred) + */ + DiImage *createImage(const unsigned long fstart, + const unsigned long fcount) const; + + /** create scaled copy of specified (clipping) area of the current image object. + * + ** @param left_pos x coordinate of top left corner of area to be scaled + * (referring to image origin, negative values create a border around the image) + * @param top_pos y coordinate of top left corner of area to be scaled + * @param clip_width width of area to be scaled + * @param clip_height height of area to be scaled + * @param scale_width width of scaled image (in pixels) + * @param scale_height height of scaled image (in pixels) + * @param interpolate specifies whether scaling algorithm should use interpolation (if necessary). + * default: no interpolation (0), preferred interpolation algorithm (if applicable): + * 1 = pbmplus algorithm, 2 = c't algorithm, 3 = bilinear magnification, + * 4 = bicubic magnification + * @param aspect specifies whether pixel aspect ratio should be taken into consideration + * (if true, width OR height should be 0, i.e. this component will be calculated + * automatically) + * @param pvalue P-value used for the border outside the image (0..65535) + * + ** @return pointer to new DiImage object (NULL if an error occurred) + */ + DiImage *createScale(const signed long left_pos, + const signed long top_pos, + const unsigned long clip_width, + const unsigned long clip_height, + const unsigned long scale_width, + const unsigned long scale_height, + const int interpolate, + const int aspect, + const Uint16 pvalue) const; + + /** create a flipped copy of the current image + * + ** @param horz flip horizontally if true + * @param vert flip vertically if true + * + ** @return pointer to new DiImage object (NULL if an error occurred) + */ + DiImage *createFlip(const int horz, + const int vert) const; + + /** create a rotated copy of the current image. + * + ** @param degree angle by which the image shall be rotated + * + ** @return pointer to new DiImage object (NULL if an error occurred) + */ + DiImage *createRotate(const int degree) const; + + /** create monochrome copy of the current image. + * Since the image is already monochrome the effect is the same as with createImage(). + * + ** @param dummy1 not used + * @param dummy2 not used + * @param dummy3 not used + * + ** @return pointer to new DiImage object (NULL if an error occurred) + */ + DiImage *createMono(const double dummy1, + const double dummy2, + const double dummy3) const; + + + protected: + + /** constructor, copy + * + ** @param image pointer to reference image + * @param fstart first frame to be processed + * @param fcount number of frames + */ + DiMono1Image(const DiMonoImage *image, + const unsigned long fstart, + const unsigned long fcount); + + /** constructor, scale/clip + * + ** @param image pointer to reference image + * @param left_pos x coordinate of top left corner of area to be scaled + * (referring to image origin, negative values create a border around the image) + * @param top_pos y coordinate of top left corner of area to be scaled + * @param src_cols width of area to be scaled + * @param src_rows height of area to be scaled + * @param dest_cols width of scaled image (in pixels) + * @param dest_rows height of scaled image (in pixels) + * @param interpolate specifies whether scaling algorithm should use interpolation (if necessary). + * default: no interpolation (0), preferred interpolation algorithm (if applicable): + * 1 = pbmplus algorithm, 2 = c't algorithm, 3 = bilinear magnification, + * 4 = bicubic magnification + * @param aspect specifies whether pixel aspect ratio should be taken into consideration + * (if true, width OR height should be 0, i.e. this component will be calculated + * automatically) + * @param pvalue P-value used for the border outside the image (0..65535) + */ + DiMono1Image(const DiMonoImage *image, + const signed long left_pos, + const signed long top_pos, + const Uint16 src_cols, + const Uint16 src_rows, + const Uint16 dest_cols, + const Uint16 dest_rows, + const int interpolate = 0, + const int aspect = 0, + const Uint16 pvalue = 0); + + /** constructor, flip + * + ** @param image pointer to reference image + ** @param horz flip horizontally if true + * @param vert flip vertically if true + */ + DiMono1Image(const DiMonoImage *image, + const int horz, + const int vert); + + /** constructor, rotate + * + ** @param image pointer to reference image + * @param degree angle by which the image shall be rotated + */ + DiMono1Image(const DiMonoImage *image, + const int degree); +}; + + +#endif diff --git a/dcmimgle/include/dcmtk/dcmimgle/dimo2img.h b/dcmimgle/include/dcmtk/dcmimgle/dimo2img.h new file mode 100644 index 00000000..101f43e4 --- /dev/null +++ b/dcmimgle/include/dcmtk/dcmimgle/dimo2img.h @@ -0,0 +1,289 @@ +/* + * + * Copyright (C) 1996-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimgle + * + * Author: Joerg Riesmeier + * + * Purpose: DicomMonochrome2Image (Header) + * + */ + + +#ifndef DIMO2IMG_H +#define DIMO2IMG_H + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/dcmimgle/dimoimg.h" + + +/*---------------------* + * class declaration * + *---------------------*/ + +/** Class for MONOCHROME2 images + */ +class DCMTK_DCMIMGLE_EXPORT DiMono2Image + : public DiMonoImage +{ + + public: + + /** constructor + * + ** @param docu pointer to dataset (encapsulated) + * @param status current image status + */ + DiMono2Image(const DiDocument *docu, + const EI_Status status); + + /** constructor, modality (linear) + * + ** @param docu pointer to dataset (encapsulated) + * @param status current image status + * @param slope rescale slope + * @param intercept rescale intercept + */ + DiMono2Image(const DiDocument *docu, + const EI_Status status, + const double slope, + const double intercept); + + /** constructor, modality (LUT) + * + ** @param docu pointer to dataset (encapsulated) + * @param status current image status + * @param data element containing the modality LUT data + * @param descriptor element containing the modality LUT descriptor + * @param explanation element containing the modality LUT explanation (optional) + */ + DiMono2Image(const DiDocument *docu, + const EI_Status status, + const DcmUnsignedShort &data, + const DcmUnsignedShort &descriptor, + const DcmLongString *explanation); + + /** constructor, convert color images to monochrome + * + ** @param image pointer to reference image + * @param red coefficient by which the red component is weighted + * @param green coefficient by which the green component is weighted + * @param blue coefficient by which the blue component is weighted + */ + DiMono2Image(const DiColorImage *image, + const double red, + const double green, + const double blue); + + /** constructor, createMonoOutput + * + ** @param image pointer to reference image + * @param pixel pointer to output pixel data used for the new image + * @param frame number of frame stored in the new image object + * @param stored number of bits stored + * @param alloc number of bits allocated + */ + DiMono2Image(const DiMonoImage *image, + DiMonoOutputPixel *pixel, + const unsigned long frame, + const int stored, + const int alloc); + + /** destructor + */ + virtual ~DiMono2Image(); + + /** get color model of internal pixel representation. + * @return always returns EPI_Monochrome2 + */ + virtual EP_Interpretation getInternalColorModel() const + { + return EPI_Monochrome2; + } + + /** get pixel data with specified format. + * (memory is handled internally) + * + ** @param frame number of frame to be rendered + * @param bits number of bits for the output pixel data (depth) + * @param planar flags, whether the output data (for multi-planar images) should be planar or not + * + ** @return untyped pointer to the pixel data if successful, NULL otherwise + */ + virtual const void *getOutputData(const unsigned long frame, + const int bits, + const int planar = 0); + + /** get pixel data with specified format. + * (memory is handled externally) + * + ** @param buffer untyped pointer to the externally allocated memory buffer + * @param size size of the memory buffer in bytes (will be checked) + * @param frame number of frame to be rendered + * @param bits number of bits for the output pixel data (depth) + * @param planar flags, whether the output data (for multi-planar images) should be planar or not + * + ** @return status, true if successful, false otherwise + */ + virtual int getOutputData(void *buffer, + const unsigned long size, + const unsigned long frame, + const int bits, + const int planar = 0); + + /** create copy of current image object + * + ** @param fstart first frame to be processed + * @param fcount number of frames + * + ** @return pointer to new DicomImage object (NULL if an error occurred) + */ + DiImage *createImage(const unsigned long fstart, + const unsigned long fcount) const; + + /** create scaled copy of specified (clipping) area of the current image object. + * + ** @param left_pos x coordinate of top left corner of area to be scaled + * (referring to image origin, negative values create a border around the image) + * @param top_pos y coordinate of top left corner of area to be scaled + * @param clip_width width of area to be scaled + * @param clip_height height of area to be scaled + * @param scale_width width of scaled image (in pixels) + * @param scale_height height of scaled image (in pixels) + * @param interpolate specifies whether scaling algorithm should use interpolation (if necessary). + * default: no interpolation (0), preferred interpolation algorithm (if applicable): + * 1 = pbmplus algorithm, 2 = c't algorithm, 3 = bilinear magnification, + * 4 = bicubic magnification + * @param aspect specifies whether pixel aspect ratio should be taken into consideration + * (if true, width OR height should be 0, i.e. this component will be calculated + * automatically) + * @param pvalue P-value used for the border outside the image (0..65535) + * + ** @return pointer to new DiImage object (NULL if an error occurred) + */ + DiImage *createScale(const signed long left_pos, + const signed long top_pos, + const unsigned long clip_width, + const unsigned long clip_height, + const unsigned long scale_width, + const unsigned long scale_height, + const int interpolate, + const int aspect, + const Uint16 pvalue) const; + + /** create a flipped copy of the current image + * + ** @param horz flip horizontally if true + * @param vert flip vertically if true + * + ** @return pointer to new DiImage object (NULL if an error occurred) + */ + DiImage *createFlip(const int horz, + const int vert) const; + + /** create a rotated copy of the current image. + * + ** @param degree angle by which the image shall be rotated + * + ** @return pointer to new DiImage object (NULL if an error occurred) + */ + DiImage *createRotate(const int degree) const; + + /** create monochrome copy of the current image. + * Since the image is already monochrome the effect is the same as with createImage(). + * + ** @param dummy1 not used + * @param dummy2 not used + * @param dummy3 not used + * + ** @return pointer to new DiImage object (NULL if an error occurred) + */ + DiImage *createMono(const double dummy1, + const double dummy2, + const double dummy3) const; + + + protected: + + /** constructor + * + ** @param docu pointer to dataset (encapsulated) + * @param status current image status + * @param dummy (necessary to be different from another constructor) + */ + DiMono2Image(const DiDocument *docu, + const EI_Status status, + const char dummy); + + /** constructor, copy + * + ** @param image pointer to reference image + * @param fstart first frame to be processed + * @param fcount number of frames + */ + DiMono2Image(const DiMonoImage *image, + const unsigned long fstart, + const unsigned long fcount); + + /** constructor, scale/clip + * + ** @param image pointer to reference image + * @param left_pos x coordinate of top left corner of area to be scaled + * (referring to image origin, negative values create a border around the image) + * @param top_pos y coordinate of top left corner of area to be scaled + * @param src_cols width of area to be scaled + * @param src_rows height of area to be scaled + * @param dest_cols width of scaled image (in pixels) + * @param dest_rows height of scaled image (in pixels) + * @param interpolate specifies whether scaling algorithm should use interpolation (if necessary). + * default: no interpolation (0), preferred interpolation algorithm (if applicable): + * 1 = pbmplus algorithm, 2 = c't algorithm, 3 = bilinear magnification, + * 4 = bicubic magnification + * @param aspect specifies whether pixel aspect ratio should be taken into consideration + * (if true, width OR height should be 0, i.e. this component will be calculated + * automatically) + * @param pvalue P-value used for the border outside the image (0..65535) + */ + DiMono2Image(const DiMonoImage *image, + const signed long left_pos, + const signed long top_pos, + const Uint16 src_cols, + const Uint16 src_rows, + const Uint16 dest_cols, + const Uint16 dest_rows, + const int interpolate = 0, + const int aspect = 0, + const Uint16 pvalue = 0); + + /** constructor, flip + * + ** @param image pointer to reference image + ** @param horz flip horizontally if true + * @param vert flip vertically if true + */ + DiMono2Image(const DiMonoImage *image, + const int horz, + const int vert); + + /** constructor, rotate + * + ** @param image pointer to reference image + * @param degree angle by which the image shall be rotated + */ + DiMono2Image(const DiMonoImage *image, + const int degree); +}; + + +#endif diff --git a/dcmimgle/include/dcmtk/dcmimgle/dimocpt.h b/dcmimgle/include/dcmtk/dcmimgle/dimocpt.h new file mode 100644 index 00000000..7172ea3a --- /dev/null +++ b/dcmimgle/include/dcmtk/dcmimgle/dimocpt.h @@ -0,0 +1,93 @@ +/* + * + * Copyright (C) 1996-2010, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimgle + * + * Author: Joerg Riesmeier + * + * Purpose: DicomMonochromeCopyTemplate (Header) + * + */ + + +#ifndef DIMOCPT_H +#define DIMOCPT_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/ofstd/ofbmanip.h" +#include "dcmtk/ofstd/ofcast.h" + +#include "dcmtk/dcmimgle/dimopxt.h" + + +/*---------------------* + * class declaration * + *---------------------*/ + +/** Template class to copy monochrome pixel data + */ +template +class DiMonoCopyTemplate + : public DiMonoPixelTemplate +{ + + public: + + /** constructor + * + ** @param pixel pointer to monochrome intermediate representation of pixel data + * @param fstart first frame to be copied + * @param fcount number of frames to be copied + * @param fsize size of one frame (in bytes) + */ + DiMonoCopyTemplate(const DiMonoPixel *pixel, + const unsigned long fstart, + const unsigned long fcount, + const unsigned long fsize) + : DiMonoPixelTemplate(pixel, fcount * fsize) + { + if ((pixel != NULL) && (pixel->getCount() > 0)) + { + if ((pixel->getCount() > fstart * fsize) && (pixel->getCount() >= (fstart + fcount) * fsize)) + copy(OFstatic_cast(const T *, pixel->getData()) + fstart * fsize); + /* need to determine the global min/max value */ + this->determineMinMax(); + } + } + + /** destructor + */ + ~DiMonoCopyTemplate() + { + } + + + private: + + /** copy specified amount of pixel data + * + ** @param pixel array of pixel data to be copied + */ + inline void copy(const T *pixel) + { + if (pixel != NULL) + { + this->Data = new T[this->getCount()]; + if (this->Data != NULL) + OFBitmanipTemplate::copyMem(pixel, this->Data, this->getCount()); + } + } +}; + + +#endif diff --git a/dcmimgle/include/dcmtk/dcmimgle/dimoflt.h b/dcmimgle/include/dcmtk/dcmimgle/dimoflt.h new file mode 100644 index 00000000..bf626c3b --- /dev/null +++ b/dcmimgle/include/dcmtk/dcmimgle/dimoflt.h @@ -0,0 +1,113 @@ +/* + * + * Copyright (C) 1996-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimgle + * + * Author: Joerg Riesmeier + * + * Purpose: DicomMonochromeFlipTemplate (Header) + * + */ + + +#ifndef DIMOFLT_H +#define DIMOFLT_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/ofstd/oftypes.h" +#include "dcmtk/ofstd/ofcast.h" + +#include "dcmtk/dcmimgle/dimopxt.h" +#include "dcmtk/dcmimgle/diflipt.h" + + +/*---------------------* + * class declaration * + *---------------------*/ + +/** Template class to flip monochrome images (on pixel data level) + * horizontally and vertically + */ +template +class DiMonoFlipTemplate + : public DiMonoPixelTemplate, + protected DiFlipTemplate +{ + + public: + + /** constructor + * + ** @param pixel pointer to intermediate pixel representation + * @param columns number of columns + * @param rows number of rows + * @param frames number of frames + * @param horz flip horizontally if true + * @param vert flip vertically if true + */ + DiMonoFlipTemplate(const DiMonoPixel *pixel, + const Uint16 columns, + const Uint16 rows, + const Uint32 frames, + const int horz, + const int vert) + : DiMonoPixelTemplate(pixel, OFstatic_cast(unsigned long, columns) * OFstatic_cast(unsigned long, rows) * frames), + DiFlipTemplate(1, columns, rows, frames) + { + if ((pixel != NULL) && (pixel->getCount() > 0)) + { + if (pixel->getCount() == OFstatic_cast(unsigned long, columns) * OFstatic_cast(unsigned long, rows) * frames) + flip(OFstatic_cast(const T *, pixel->getData()), horz, vert); + else { + DCMIMGLE_WARN("could not flip image ... corrupted data"); + } + } + } + + /** destructor + */ + ~DiMonoFlipTemplate() + { + } + + + private: + + /** choose flipping algorithm depending on given parameters + * + ** @param pixel pointer to pixel data which should be flipped + * @param horz flip horizontally if true + * @param vert flip vertically if true + */ + inline void flip(const T *pixel, + const int horz, + const int vert) + { + if (pixel != NULL) + { + this->Data = new T[this->getCount()]; + if (this->Data != NULL) + { + if (horz && vert) + this->flipHorzVert(&pixel, &this->Data); + else if (horz) + this->flipHorz(&pixel, &this->Data); + else if (vert) + this->flipVert(&pixel, &this->Data); + } + } + } +}; + + +#endif diff --git a/dcmimgle/include/dcmtk/dcmimgle/dimoimg.h b/dcmimgle/include/dcmtk/dcmimgle/dimoimg.h new file mode 100644 index 00000000..13b27f31 --- /dev/null +++ b/dcmimgle/include/dcmtk/dcmimgle/dimoimg.h @@ -0,0 +1,1155 @@ +/* + * + * Copyright (C) 1996-2012, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimgle + * + * Author: Joerg Riesmeier + * + * Purpose: DicomMonochromeImage (Header) + * + */ + + +#ifndef DIMOIMG_H +#define DIMOIMG_H + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/ofstd/ofcast.h" + +#include "dcmtk/dcmimgle/diimage.h" +#include "dcmtk/dcmimgle/dimopx.h" +#include "dcmtk/dcmimgle/dimoopx.h" +#include "dcmtk/dcmimgle/didispfn.h" + + +/*------------------------* + * forward declarations * + *------------------------*/ + +class DiColorImage; + + +/*---------------------* + * class declaration * + *---------------------*/ + +/** Base class for monochrome images + */ +class DCMTK_DCMIMGLE_EXPORT DiMonoImage + : public DiImage +{ + + public: + + /** constructor + * + ** @param docu pointer to the DICOM document + * @param status status of the image object + */ + DiMonoImage(const DiDocument *docu, + const EI_Status status); + + /** constructor, rescale + * + ** @param docu pointer to the DICOM document + * @param status status of the image object + * @param slope rescale slope + * @param intercept rescale intercept + */ + DiMonoImage(const DiDocument *docu, + const EI_Status status, + const double slope, + const double intercept); + + /** constructor, modality LUT + * + ** @param docu pointer to the DICOM document + * @param status status of the image object + * @param data element containing the modality LUT data + * @param descriptor element containing the modality LUT descriptor + * @param explanation element containing the modality LUT explanation (optional) + */ + DiMonoImage(const DiDocument *docu, + const EI_Status status, + const DcmUnsignedShort &data, + const DcmUnsignedShort &descriptor, + const DcmLongString *explanation); + + /** destructor + */ + virtual ~DiMonoImage(); + + /** process next couple of frames + * + ** @param fcount number of frames to be processed (0 = same number as before) + * + ** @return status, true if successful, false otherwise + */ + virtual int processNextFrames(const unsigned long fcount); + + /** get minimum and maximum pixel values. + * the resulting pixel values are stored in 'double' variables to avoid problems + * with different number ranges, limited to monochrome images + * + ** @param min minimum pixel value (reference parameter) + * @param max maximum pixel value (reference parameter) + * @param mode 0 = min/max 'used' pixel values, + * 1 = min/max 'possible' pixel values (absolute min/max) + * + ** @return status code (true if successful) + */ + int getMinMaxValues(double &min, + double &max, + const int mode) const; + + /** get display function + * + ** @return pointer to current display function, NULL if absent + */ + DiDisplayFunction *getDisplayFunction() const + { + return DisplayFunction; + } + + /** set display function + * + ** @param display object describing the output device characteristic (only referenced!) + * + ** @return true if successful, false otherwise + */ + int setDisplayFunction(DiDisplayFunction *display); + + /** set no display function. + * disables display function transformation, object is not deleted! + * + ** @return true if successful (1 = disabled current function, + * 2 = there was no function to disable) + * false otherwise + */ + int setNoDisplayFunction(); + + /** unset all VOI transformations (windows and LUTs). + * only applicable for monochrome images + * + ** @return true if successful (1 = previous window/LUT has been valid, + * 2 = otherwise), + * false otherwise (image is invalid or not monochrome) + */ + int setNoVoiTransformation(); + + /** delete specified display LUT(s) + * + ** @param bits parameter of LUT to be deleted (0 = all) + * + ** @return true if successful, false otherwise + */ + inline int deleteDisplayLUT(const int bits) + { + return (DisplayFunction != NULL) ? DisplayFunction->deleteLookupTable(bits) : 0; + } + + /** check whether given output value is unused + * + ** @param value output value to be checked + * + ** @return status, true if unused (1 = within output range, 2 = out of range), false otherwise + */ + inline int isValueUnused(const unsigned long value) + { + return (OutputData != NULL) ? OutputData->isUnused(value) : 0; + } + + /** convert P-value to DDL. + * conversion uses display LUT if present, linear scaling otherwise. + * + ** @param pvalue P-value to be converted (0..65535) + * @param ddl reference to resulting DDL + * @param bits number of bits for output + * + ** @return true if successful (1 = display function transformation, + * 2 = linear scaling), + * false otherwise + */ + int convertPValueToDDL(const Uint16 pvalue, + Uint16 &ddl, + const int bits); + + /** set automatically calculated minimum/maximum window. + * possibly active VOI LUT is implicitly disabled. + * + ** @param idx ignore global min/max values if false (0) + * + ** @return true if successful (1 = window has changed, + * 2 = new window is the same as previous one), + * false otherwise + */ + int setMinMaxWindow(const int idx = 1); + + /** set automatically calculated VOI window for the specified Region of Interest (ROI). + * The ROI is specified by means of a rectangle (left_pos, top_pos, width, height). + * Possibly active VOI LUT is implicitly disabled. + * + ** @param left_pos x-coordinate of the top left-hand corner of the ROI (starting from 0) + * @param top_pos y-coordinate of the top left-hand corner of the ROI (starting from 0) + * @param width width in pixels of the rectangular ROI (minimum: 1) + * @param height height in pixels of the rectangular ROI (minimum: 1) + * @param frame index of the frame to be used for the calculation + * + ** @return true if successful (1 = window has changed, + * 2 = new window is the same as previous one), + * false otherwise + */ + int setRoiWindow(const unsigned long left_pos, + const unsigned long top_pos, + const unsigned long width, + const unsigned long height, + const unsigned long frame); + + /** set automatically calculated histogram window. + * possibly active VOI LUT is implicitly disabled. + * + ** @param thresh threshhold value specifying percentage of histogram border which shall be ignored + * + ** @return true if successful, false otherwise + */ + int setHistogramWindow(const double thresh); + + /** set specified window (given by index to window width/center sequence stored in image file). + * possibly active VOI LUT is implicitly disabled. + * + ** @param pos index to window width/center sequence + * + ** @return true if successful, false otherwise + */ + int setWindow(const unsigned long pos = 0); + + /** set specified window (given by window width and center). + * possibly active VOI LUT is implicitly disabled. + * + ** @param center center of specified window + * @param width width of specified window + * @param explanation window explanation (optional) + * + ** @return true if successful (1 = window has changed, + * 2 = new window is the same as previous one), + * false otherwise + */ + int setWindow(const double center, + const double width, + const char *explanation = NULL); + + /** get current window center and width values + * + ** @param center return current window center value + * @param width return current window width value + * + ** @return true if successful, false otherwise + */ + int getWindow(double ¢er, + double &width); + + /** get number of VOI windows (stored in image file) + * + ** @return number of VOI windows + */ + inline unsigned long getWindowCount() const + { + return WindowCount; + } + + /** get VOI LUT function. + * possible values are: EFV_Default, EFV_Linear, EFV_Sigmoid. + * + ** @return currently active VOI LUT function + */ + EF_VoiLutFunction getVoiLutFunction() const; + + /** set VOI LUT function + * + ** @param function type of VOI LUT function (default, linear or sigmoid). + * 'default' basically means the same as 'linear'. + * + ** @return true if successful (1 = function has changed, + * 2 = function has not changed) + * false otherwise + */ + int setVoiLutFunction(const EF_VoiLutFunction function); + + /** set VOI LUT (given by dcmdata elements). + * possibly active window/center is implicitly disabled. + * + ** @param data contains LUT data + * @param descriptor describes LUT structure + * @param explanation free form description of VOI LUT (optional) + * @param descripMode mode specifying the use of the bits per table entry value + * + ** @return true if successful, false otherwise + */ + int setVoiLut(const DcmUnsignedShort &data, + const DcmUnsignedShort &descriptor, + const DcmLongString *explanation, + const EL_BitsPerTableEntry descripMode = ELM_UseValue); + + /** set VOI LUT (given by index to VOI LUT sequence stored in image file). + * possibly active window/center is implicitly disabled. + * + ** @param pos index to VOI LUT sequence + * @param descripMode mode specifying the use of the bits per table entry value + * + ** @return true if successful, false otherwise + */ + int setVoiLut(const unsigned long pos, + const EL_BitsPerTableEntry descripMode = ELM_UseValue); + + /** get number of VOI LUTs (stored in image file) + * + ** @return number of VOI LUTs + */ + inline unsigned long getVoiLutCount() const + { + return VoiLutCount; + } + + /** get description of active VOI transformation + * + ** @return pointer to description text (NULL if absent) + */ + inline const char *getVoiTransformationExplanation() const + { + return VoiExplanation.c_str(); + } + + /** get description of specified VOI window (stored in the image file) + * + ** @param pos index of the stored VOI window (0..n-1) + * @param explanation variable in which the result text is stored + * + ** @return pointer to description text (NULL if absent or index invalid) + */ + const char *getVoiWindowExplanation(const unsigned long pos, + OFString &explanation) const; + + /** get description of specified VOI LUT (stored in the image file) + * + ** @param pos index of the stored VOI LUT (0..n-1) + * @param explanation variable in which the result text is stored + * + ** @return pointer to description text (NULL if absent or index invalid) + */ + const char *getVoiLutExplanation(const unsigned long pos, + OFString &explanation) const; + + /** get description of performed modality LUT transformation + * + ** @return pointer to description text (NULL if absent) + */ + inline const char *getModalityLutExplanation() const + { + return (InterData != NULL) ? InterData->getModalityLutExplanation() : OFstatic_cast(const char *, NULL); + } + + /** set hardcopy parameters. (used to display LinOD images) + * + ** @param min minimum density of the print-out (in hundreds of Optical Density, e.g. 150 means 1.5 OD) + * @param max maximum density of the print-out (ditto) + * @param reflect reflected ambient light (in candela per square meter - cd/m^2) + * @param illumin illumination (ditto) + * + ** @return true if successful (1 = at least one of the parameters has changed, + * 2 = no parameter has changed) + * false otherwise + */ + int setHardcopyParameters(const unsigned int min, + const unsigned int max, + const unsigned int reflect, + const unsigned int illumin); + + /** get shape for presentation transformation. + * possible values are: ESP_Default, ESP_Identity, ESP_Inverse, ESP_LinOD + * If a presentation LUT is currently active ESP_Default is always returned. + * + ** @return currently active presentation LUT shape + */ + ES_PresentationLut getPresentationLutShape() const; + + /** set shape for presentation transformation. + * possibly active presentation LUT is implicitly disabled. + * + ** @param shape presentation LUT shape (default, identity or inverse). + * 'default' means that the output data is always created with 0 for black + * and maxvalue for white (i.e. monochrome2 data is created for output). + * + ** @return true if successful (1 = shape has changed, + * 2 = shape has not changed) + * false otherwise + */ + int setPresentationLutShape(const ES_PresentationLut shape); + + /** set LUT for presentation transformation. + * possibly active presentation LUT is implicitly disabled. + * + ** @param data contains LUT data + * @param descriptor describes LUT structure + * @param explanation free form description of presentation LUT (optional) + * @param descripMode mode specifying the use of the bits per table entry value + * + ** @return true if successful, false otherwise + */ + int setPresentationLut(const DcmUnsignedShort &data, + const DcmUnsignedShort &descriptor, + const DcmLongString *explanation = NULL, + const EL_BitsPerTableEntry descripMode = ELM_UseValue); + + /** set inverse LUT for presentation transformation. + * this LUT transform is e.g. used for DICOM print (12->8, 8->12 bit) + * possibly active presentation LUT will not be considered ! + * + ** @param data contains LUT data + * @param descriptor describes LUT structure + * @param descripMode mode specifying the use of the bits per table entry value + * + ** @return true if successful, false otherwise + */ + int setInversePresentationLut(const DcmUnsignedShort &data, + const DcmUnsignedShort &descriptor, + const EL_BitsPerTableEntry descripMode = ELM_UseValue); + + /** get description of active presentation LUT + * + ** @return pointer to description text (NULL if absent) + */ + inline const char *getPresentationLutExplanation() const + { + return (PresLutData != NULL) ? PresLutData->getExplanation() : OFstatic_cast(const char *, NULL); + } + + /** add specified plane to group of additional overlay planes. + * replaces old overlay plane if group number already exists. + * + ** @param group group number (0x60nn) of overlay plane + * @param left_pos x coordinate of plane orgin (referring to image origin) + * @param top_pos y coordinate of plane origin + * @param columns width of overlay plane (in pixels) + * @param rows height of overlay plane (in pixels) + * @param data overlay plane data (dcmdata element) + * @param label overlay plane label + * @param description overlay plane description + * @param mode display mode (see 'diutils.h') + * + ** @return false (0) if an error occurred, true otherwise (1 = added new plane, + * 2 = replaced existing plane) + */ + int addOverlay(const unsigned int group, + const signed int left_pos, + const signed int top_pos, + const unsigned int columns, + const unsigned int rows, + const DcmOverlayData &data, + const DcmLongString &label, + const DcmLongString &description, + const EM_Overlay mode); + + /** remove all additional overlay planes + * + ** @return false (0) if an error occurred, true otherwise + */ + int removeAllOverlays(); + + /** get pointer to specified overlay managing object + * + ** @param idx index of overlay group (0 = dataset, 1 = additional) + * + ** @return pointer to overlay managing object (NULL if absent or invalid) + */ + inline DiOverlay *getOverlayPtr(const unsigned int idx) + { + return (idx < 2) ? Overlays[idx] : OFstatic_cast(DiOverlay *, NULL); + } + + /** get pointer to current monochrome image (this) + * + ** @return pointer to this object + */ + inline DiMonoImage *getMonoImagePtr() + { + return this; + } + + /** flip current image (horizontally and/or vertically) + * + ** @param horz flip horizontally if true + * @param vert flip vertically if true + * + ** @return true if successful (1 = flipped at least direction, + * 2 = not flipped, because of image resolution - width and/or height equal to 1), + * false otherwise + */ + int flip(const int horz, + const int vert); + + /** rotate current image (by steps of 90 degrees) + * + ** @param degree angle by which the image shall be rotated (-360, -270, -180, -90, 0, 90, 180, 270, 360) + * + ** @return true if successful (1 = rotated by at least 90 degrees, + * 2 = not rotated, because of image resolution or angle), + * false otherwise + */ + int rotate(const int degree); + + /** get number of bits per sample. + * If the optional parameter is specified the value will be checked and in any case + * a valid value will be returned. + * + ** @param bits value to be returned (if less than 1 or greater than the maximum (32) + * the default value will be used which is equal to the bits per sample + * value stored in the DICOM dataset) + * + ** @return status, true if successful, false otherwise + */ + virtual int getBits(const int bits = 0) const + { + return (((bits < 1) || (bits > MAX_BITS)) && (bits != MI_PastelColor)) ? BitsPerSample : bits; + } + + /** get number of bytes required for the rendered output of a single frame + * + * @param bits number of bits for the output pixel data (depth) + * + ** @return number of bytes if successful, 0 otherwise + */ + virtual unsigned long getOutputDataSize(const int bits = 0) const; + + /** get pixel data with specified format. + * (memory is handled internally) + * + ** @param frame number of frame to be rendered + * @param bits number of bits for the output pixel data (depth) + * @param planar flag, only useful for multi-planar images (color) + * + ** @return untyped pointer to the pixel data if successful, NULL otherwise + */ + virtual const void *getOutputData(const unsigned long frame, + const int bits, + const int planar = 0) = 0; + + /** get pixel data with specified format. + * (memory is handled externally) + * + ** @param buffer untyped pointer to the externally allocated memory buffer + * @param size size of the memory buffer in bytes (will be checked) + * @param frame number of frame to be rendered + * @param bits number of bits for the output pixel data (depth) + * @param planar flag, only useful for multi-planar images (color) + * + ** @return status, true if successful, false otherwise + */ + virtual int getOutputData(void *buffer, + const unsigned long size, + const unsigned long frame, + const int bits, + const int planar = 0) = 0; + + /** get pixel data of specified plane. + * (memory is handled internally) + * + ** @param dummy (not used) + * + ** @return untyped pointer to the pixel data if successful, NULL otherwise + */ + const void *getOutputPlane(const int dummy) const; + + /** delete internally handled output memory buffer + * Save memory if data is no longer needed. + */ + void deleteOutputData(); + + /** create bitmap for specified overlay plane. + * (up to 16 bits per pixel with two values: fore and back) + * + ** @param frame index of frame used for output + * @param plane number (0..15) or group number (0x60nn) of overlay plane + * @param left_pos returns x coordinate of plane's origin + * @param top_pos returns y coordinate of plane's origin + * @param width returns width of overlay plane (in pixels) + * @param height returns height of overlay plane (in pixels) + * @param mode return display mode (see 'diutils.h') + * @param idx index of overlay group (0 = dataset, 1 = additional, 2 = '1' plane hides '0' plane) + * @param bits number of bits (stored) in the resulting array, default: 8 + * @param fore foreground color to be set in bitmap, default: 255 + * @param back background color to be set in bitmap (transparent), default: 0 + * + ** @return pointer to overlay plane data (internal memory buffer) + */ + const void *getOverlayData(const unsigned long frame, + const unsigned int plane, + unsigned int &left_pos, + unsigned int &top_pos, + unsigned int &width, + unsigned int &height, + EM_Overlay &mode, + const unsigned int idx, + const int bits = 8, + const Uint16 fore = 0xff, + const Uint16 back = 0x0); + + /** create bitmap for specified overlay plane. + * (up to 16 bits per pixel with two values: fore and back) + * + ** @param frame index of frame used for output + * @param plane number (0..15) or group number (0x60nn) of overlay plane + * @param width returns width of overlay plane (in pixels) + * @param height returns height of overlay plane (in pixels) + * @param idx index of overlay group (0 = dataset, 1 = additional, 2 = '1' plane hides '0' plane) + * @param bits number of bits (stored) in the resulting array, default: 8 + * @param fore foreground color to be set in bitmap, default: 255 + * @param back background color to be set in bitmap (transparent), default: 0 + * + ** @return pointer to overlay plane data (internal memory buffer) + */ + const void *getFullOverlayData(const unsigned long frame, + const unsigned int plane, + unsigned int &width, + unsigned int &height, + const unsigned int idx, + const int bits = 8, + const Uint16 fore = 0xff, + const Uint16 back = 0x0); + + /** delete buffer for overlay plane data. + * Save memory if data is no longer needed. + */ + void deleteOverlayData(); + + /** create bitmap for specified overlay plane and store it in (6xxx,3000) format. + * (1 bit allocated and stored, foreground color is 1, background color is 0, + * data is 16 bit padded - even length) + * memory is not handled internally - must be deleted from calling program. + * + ** @param buffer stores pointer to overlay data (memory is allocated internally) + * @param plane number (0..15) or group number (0x60nn) of overlay plane + * @param width returns width of overlay plane (in pixels) + * @param height returns height of overlay plane (in pixels) + * @param frames returns number of frames (multiple overlay frames possible!) + * @param idx index of overlay group (0 = dataset, planes stored in the image dataset; + * 1 = additional, planes added by addOverlay()), + * default: 0 + * + ** @return number of bytes allocated for the 'buffer' if successful, 0 otherwise + */ + unsigned long create6xxx3000OverlayData(Uint8 *&buffer, + const unsigned int plane, + unsigned int &width, + unsigned int &height, + unsigned long &frames, + const unsigned int idx = 0); + + /** get pointer to intermediate pixel data representation + * + ** @return pointer to intermediate pixel data + */ + const DiPixel *getInterData() const + { + return InterData; + } + + /** get pointer to intermediate pixel data representation + * + ** @return pointer to intermediate pixel data + */ + const DiMonoPixel *getMonoInterData() const + { + return InterData; + } + + /** create true color (24/32 bit) or palette (8 bit) bitmap for MS Windows. + * memory is not handled internally - must be deleted from calling program. + * + ** @param data untyped pointer memory buffer (set to NULL if not allocated externally) + * @param size size of the memory buffer in bytes (if 0 'data' is set to NULL) + * @param frame index of frame to be converted (starting from 0) + * @param bits number of bits per pixel used for the output bitmap (8, 24 or 32) + * @param upsideDown specifies the order of lines in the images (0 = top-down, bottom-up otherwise) + * @param padding align each line to a 32-bit address if true (default) + * + ** @return number of bytes allocated by the bitmap, or 0 if an error occured + */ + unsigned long createDIB(void *&data, + const unsigned long size, + const unsigned long frame, + const int bits, + const int upsideDown, + const int padding = 1); + + /** create true color (32 bit) or palette (8 bit) bitmap for Java (AWT default format). + * Memory is not handled internally - must be deleted from calling program. + * + ** @param data resulting pointer to bitmap data (set to NULL if an error occurred) + * @param frame index of frame to be converted (starting from 0) + * @param bits number of bits per pixel used for the output bitmap (8 or 32) + * + ** @return number of bytes allocated by the bitmap, or 0 if an error occured + */ + unsigned long createAWTBitmap(void *&data, + const unsigned long frame, + const int bits); + + /** create packed bitmap (e.g. 12/16 bit -> 12/12 bit for DICOM printers). + * Memory is not handled internally - must be deleted from calling program. + * + ** @param buffer pointer to input memory buffer + * @param size size of memory buffer (will be checked whether it is sufficient) + * @param count number of entries (pixels) in input buffer + * @param alloc number of bits allocated for the pixels stored in the buffer (e.g. 16) + * @param stored number of bits stored for the pixels stored in the buffer (e.g. 12) + * + ** @return pointer to memory buffer containing the packed output bitmap data (NULL if an error occurred) + */ + static void *createPackedBitmap(const void *buffer, + const unsigned long size, + const unsigned long count, + const int alloc, + const int stored); + + /** create new single frame DiImage with applied grayscale transformations. + * The method getOutputData() is used internally for the new bitmap. + * + ** @param frame index of frame to be converted + * @param bits number of bits per pixel used for the output bitmap + * + ** @return pointer to new DiImage object (NULL if an error occurred) + */ + DiImage *createOutputImage(const unsigned long frame, + const int bits); + + /** write current image and related attributes to DICOM dataset. + * + ** @param dataset reference to DICOM dataset where the image attributes are stored + * @param mode 0 = determine value of BitsStored from 'used' pixel values, + * 1 = determine value of BitsStored from 'possible' pixel values + * @param planar dummy parameter (only used for color images) + * + ** @return true if successful, false otherwise + */ + int writeImageToDataset(DcmItem &dataset, + const int mode, + const int planar); + + /** write pixel data to PPM file. + * pixel data is written in ASCII format. + * + ** @param stream open C++ output stream + * @param frame index of frame used for output + * @param bits number of bits used for output of pixel data + * + ** @return true if successful, false otherwise + */ + int writePPM(STD_NAMESPACE ostream& stream, + const unsigned long frame, + const int bits); + + /** write pixel data to PPM file. + * pixel data is written in ASCII format. + * + ** @param stream open C output stream + * @param frame index of frame used for output + * @param bits number of bits used for output of pixel data + * + ** @return true if successful, false otherwise + */ + int writePPM(FILE *stream, + const unsigned long frame, + const int bits); + + /** write pixel data to raw PPM file + * + ** @param stream open C output stream + * @param frame index of frame used for output + * @param bits number of bits used for output of pixel data + * + ** @return true if successful, false otherwise + */ + int writeRawPPM(FILE *stream, + const unsigned long frame, + const int bits); + + /** write pixel data to BMP file + * + ** @param stream open C output stream + * @param frame index of frame used for output (default: first frame = 0) + * @param bits number of bits used for output of pixel data (8, 24 or 32, default (0) = 8) + * + ** @return true if successful, false otherwise + */ + int writeBMP(FILE *stream, + const unsigned long frame, + const int bits); + + + protected: + + /** constructor + * + ** @param image pointer to dataset (encapsulated) + * @param status current image status + * @param dummy (necessary to be different from another constructor) + */ + DiMonoImage(const DiDocument *image, + const EI_Status status, + const char dummy); + + /** constructor, copy + * + ** @param image pointer to reference image + * @param fstart first frame to be processed + * @param fcount number of frames + */ + DiMonoImage(const DiMonoImage *image, + const unsigned long fstart, + const unsigned long fcount); + + /** constructor, convert color images to monochrome + * + ** @param image pointer to reference image + * @param red coefficient by which the red component is weighted + * @param green coefficient by which the green component is weighted + * @param blue coefficient by which the blue component is weighted + * + ** @return pointer to new DiImage object (NULL if an error occurred) + */ + DiMonoImage(const DiColorImage *image, + const double red, + const double green, + const double blue); + + /** constructor, scale/clip + * + ** @param image pointer to reference image + * @param left_pos x coordinate of top left corner of area to be scaled + * (referring to image origin, negative values create a border around the image) + * @param top_pos y coordinate of top left corner of area to be scaled + * @param src_cols width of area to be scaled + * @param src_rows height of area to be scaled + * @param dest_cols width of scaled image (in pixels) + * @param dest_rows height of scaled image (in pixels) + * @param interpolate specifies whether scaling algorithm should use interpolation (if necessary). + * default: no interpolation (0), preferred interpolation algorithm (if applicable): + * 1 = pbmplus algorithm, 2 = c't algorithm, 3 = bilinear magnification, + * 4 = bicubic magnification + * @param aspect specifies whether pixel aspect ratio should be taken into consideration + * (if true, width OR height should be 0, i.e. this component will be calculated + * automatically) + * @param pvalue P-value used for the border outside the image (0..65535) + */ + DiMonoImage(const DiMonoImage *image, + const signed long left_pos, + const signed long top_pos, + const Uint16 src_cols, + const Uint16 src_rows, + const Uint16 dest_cols, + const Uint16 dest_rows, + const int interpolate, + const int aspect, + const Uint16 pvalue); + + /** constructor, flip + * + ** @param image pointer to reference image + ** @param horz flip horizontally if true + * @param vert flip vertically if true + */ + DiMonoImage(const DiMonoImage *image, + const int horz, + const int vert); + + /** constructor, rotate + * + ** @param image pointer to reference image + * @param degree angle by which the image shall be rotated + */ + DiMonoImage(const DiMonoImage *image, + const int degree); + + /** constructor, createMonoOutput + * + ** @param image pointer to reference image + * @param pixel pointer to output pixel data used for the new image + * @param frame number of frame stored in the new image object + * @param stored number of bits stored + * @param alloc number of bits allocated + */ + DiMonoImage(const DiMonoImage *image, + DiMonoOutputPixel *pixel, + const unsigned long frame, + const int stored, + const int alloc); + + /** initialize internal data structures and member variables + * + ** @param modality pointer to object handling the modality transform + * @param reuse reuse particular information determined in a previous call + */ + void Init(DiMonoModality *modality, + const OFBool reuse = OFFalse); + + /** initialize internal data structures (for Uint8) + * + ** @param modality pointer to object handling the modality transform + */ + void InitUint8(DiMonoModality *modality); + + /** initialize internal data structures (for Sint8) + * + ** @param modality pointer to object handling the modality transform + */ + void InitSint8(DiMonoModality *modality); + + /** initialize internal data structures (for Uint16) + * + ** @param modality pointer to object handling the modality transform + */ + void InitUint16(DiMonoModality *modality); + + /** initialize internal data structures (for Sint16) + * + ** @param modality pointer to object handling the modality transform + */ + void InitSint16(DiMonoModality *modality); + + /** initialize internal data structures (for Uint32) + * + ** @param modality pointer to object handling the modality transform + */ + void InitUint32(DiMonoModality *modality); + + /** initialize internal data structures (for Sint32) + * + ** @param modality pointer to object handling the modality transform + */ + void InitSint32(DiMonoModality *modality); + + /** check intermediate pixel representation for consistency + * + ** @param mode check number of pixels stored in the dataset if true + */ + int checkInterData(const int mode = 1); + + /** update Image Pixel Module attributes in the given dataset. + * Removes possibly existing embedded overlay planes and replaces any + * present modality transformation by a linear rescale/slope. + * Used in writeXXXToDataset() routines. + * + ** @param dataset reference to DICOM image dataset + */ + virtual void updateImagePixelModuleAttributes(DcmItem &dataset); + + /** get pixel data with specified format. + * (memory is handled externally) + * + ** @param buffer untyped pointer to the externally allocated memory buffer + * @param size size of the memory buffer in bytes (will be checked) + * @param frame number of frame to be rendered + * @param bits number of bits for the output pixel data (depth) + * @param planar flag, only useful for multi-planar images (color) + * @param negative invert pixel data if true + * + ** @return untyped pointer to the pixel data if successful, NULL otherwise + */ + const void *getData(void *buffer, + const unsigned long size, + const unsigned long frame, + int bits, + const int planar, + const int negative); + + /** get pixel data with specified format for Uint8 input (helper function). + * (memory is handled externally) + * + ** @param buffer untyped pointer to the externally allocated memory buffer + * @param disp pointer to current display function object + * @param samples number of samples per pixel + * @param frame number of frame to be rendered + * @param bits number of bits for the output pixel data (depth) + * @param low output pixel value to which 0 is mapped (min) + * @param high output pixel value to which 2^bits-1 is mapped (max) + */ + void getDataUint8(void *buffer, + DiDisplayFunction *disp, + const int samples, + const unsigned long frame, + const int bits, + const Uint32 low, + const Uint32 high); + + /** get pixel data with specified format for Sint8 input (helper function). + * (memory is handled externally) + * + ** @param buffer untyped pointer to the externally allocated memory buffer + * @param disp pointer to current display function object + * @param samples number of samples per pixel + * @param frame number of frame to be rendered + * @param bits number of bits for the output pixel data (depth) + * @param low output pixel value to which 0 is mapped (min) + * @param high output pixel value to which 2^bits-1 is mapped (max) + */ + void getDataSint8(void *buffer, + DiDisplayFunction *disp, + const int samples, + const unsigned long frame, + const int bits, + const Uint32 low, + const Uint32 high); + + /** get pixel data with specified format for Uint16 input (helper function). + * (memory is handled externally) + * + ** @param buffer untyped pointer to the externally allocated memory buffer + * @param disp pointer to current display function object + * @param samples number of samples per pixel + * @param frame number of frame to be rendered + * @param bits number of bits for the output pixel data (depth) + * @param low output pixel value to which 0 is mapped (min) + * @param high output pixel value to which 2^bits-1 is mapped (max) + */ + void getDataUint16(void *buffer, + DiDisplayFunction *disp, + const int samples, + const unsigned long frame, + const int bits, + const Uint32 low, + const Uint32 high); + + /** get pixel data with specified format for Sint16 input (helper function). + * (memory is handled externally) + * + ** @param buffer untyped pointer to the externally allocated memory buffer + * @param disp pointer to current display function object + * @param samples number of samples per pixel + * @param frame number of frame to be rendered + * @param bits number of bits for the output pixel data (depth) + * @param low output pixel value to which 0 is mapped (min) + * @param high output pixel value to which 2^bits-1 is mapped (max) + */ + void getDataSint16(void *buffer, + DiDisplayFunction *disp, + const int samples, + const unsigned long frame, + const int bits, + const Uint32 low, + const Uint32 high); + + /** get pixel data with specified format for Uint32 input (helper function). + * (memory is handled externally) + * + ** @param buffer untyped pointer to the externally allocated memory buffer + * @param disp pointer to current display function object + * @param samples number of samples per pixel + * @param frame number of frame to be rendered + * @param bits number of bits for the output pixel data (depth) + * @param low output pixel value to which 0 is mapped (min) + * @param high output pixel value to which 2^bits-1 is mapped (max) + */ + void getDataUint32(void *buffer, + DiDisplayFunction *disp, + const int samples, + const unsigned long frame, + const int bits, + const Uint32 low, + const Uint32 high); + + /** get pixel data with specified format for Sint32 input (helper function). + * (memory is handled externally) + * + ** @param buffer untyped pointer to the externally allocated memory buffer + * @param disp pointer to current display function object + * @param samples number of samples per pixel + * @param frame number of frame to be rendered + * @param bits number of bits for the output pixel data (depth) + * @param low output pixel value to which 0 is mapped (min) + * @param high output pixel value to which 2^bits-1 is mapped (max) + */ + void getDataSint32(void *buffer, + DiDisplayFunction *disp, + const int samples, + const unsigned long frame, + const int bits, + const Uint32 low, + const Uint32 high); + + /** create a presentation look-up table converting the pixel data which is linear to + * Optical Density to DDLs of the softcopy device (used to display print images on screen). + * + ** @param count number of LUT entries + * @param bits number of bits per entry + * + ** @return true if successful, false otherwise + */ + int createLinODPresentationLut(const unsigned long count, const int bits); + + /// center of current VOI-window + double WindowCenter; + /// width of current VOI-window + double WindowWidth; + /// number of stored VOI-windows + unsigned long WindowCount; + /// number of stored VOU-LUTs + unsigned long VoiLutCount; + + /// true, if current VOI-window is valid + int ValidWindow; + + /// free text explanation of current VOI transformation + OFString VoiExplanation; + /// VOI LUT function (linear or sigmoid) + EF_VoiLutFunction VoiLutFunction; + /// presentation LUT shape (identity, inverse or lin od) + ES_PresentationLut PresLutShape; + + /// minimum density of a print-out (in hundreds of Optical Density) + unsigned int MinDensity; + /// maximum density of a print-out (ditto) + unsigned int MaxDensity; + /// reflected ambient light (in candela per squaremeter) + unsigned int Reflection; + /// illumination (ditto) + unsigned int Illumination; + + /// points to associated overlay-objects ([0] = built-in, [1] = additional) + DiOverlay *Overlays[2]; + /// points to associated VOI-LUT-object + DiLookupTable *VoiLutData; + /// points to associated presentation-LUT-object + DiLookupTable *PresLutData; + /// points to intermediate pixel data representation (object) + DiMonoPixel *InterData; + + /// points to grayscale standard display function (only referenced!) + DiDisplayFunction *DisplayFunction; + + + private: + + /// points to current output data (object) + DiMonoOutputPixel *OutputData; + /// points to current overlay plane data (pixel array) + void *OverlayData; + + // --- declarations to avoid compiler warnings + + DiMonoImage(const DiMonoImage &); + DiMonoImage &operator=(const DiMonoImage &); +}; + + +#endif diff --git a/dcmimgle/include/dcmtk/dcmimgle/dimoipxt.h b/dcmimgle/include/dcmtk/dcmimgle/dimoipxt.h new file mode 100644 index 00000000..2e7dc91c --- /dev/null +++ b/dcmimgle/include/dcmtk/dcmimgle/dimoipxt.h @@ -0,0 +1,269 @@ +/* + * + * Copyright (C) 1996-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimgle + * + * Author: Joerg Riesmeier + * + * Purpose: DicomMonochromeInputPixelTemplate (Header) + * + */ + + +#ifndef DIMOIPXT_H +#define DIMOIPXT_H + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/ofstd/ofbmanip.h" +#include "dcmtk/ofstd/ofcast.h" + +#include "dcmtk/dcmimgle/dimopxt.h" +#include "dcmtk/dcmimgle/diinpx.h" + + +/*---------------------* + * class declaration * + *---------------------*/ + +/** Template class to convert monochrome pixel data to intermediate representation + */ +template +class DiMonoInputPixelTemplate + : public DiMonoPixelTemplate +{ + + public: + + /** constructor + * + ** @param pixel pointer to input pixel representation + * @param modality pointer to modality transform object + */ + DiMonoInputPixelTemplate(DiInputPixel *pixel, + DiMonoModality *modality) + : DiMonoPixelTemplate(pixel, modality) + { + /* erase empty part of the buffer (= blacken the background) */ + if ((this->Data != NULL) && (this->InputCount < this->Count)) + OFBitmanipTemplate::zeroMem(this->Data + this->InputCount, this->Count - this->InputCount); + if ((pixel != NULL) && (this->Count > 0)) + { + // check whether to apply any modality transform + if ((this->Modality != NULL) && this->Modality->hasLookupTable() && (bitsof(T1) <= MAX_TABLE_ENTRY_SIZE)) + { + modlut(pixel); + // ignore modality LUT min/max values since the image does not necessarily have to use all LUT entries + this->determineMinMax(); + } + else if ((this->Modality != NULL) && this->Modality->hasRescaling()) + { + rescale(pixel, this->Modality->getRescaleSlope(), this->Modality->getRescaleIntercept()); + this->determineMinMax(OFstatic_cast(T3, this->Modality->getMinValue()), OFstatic_cast(T3, this->Modality->getMaxValue())); + } else { + rescale(pixel); // "copy" or reference pixel data + this->determineMinMax(OFstatic_cast(T3, this->Modality->getMinValue()), OFstatic_cast(T3, this->Modality->getMaxValue())); + } + } + } + + /** destructor + */ + virtual ~DiMonoInputPixelTemplate() + { + } + + + private: + + /** initialize optimization LUT + * + ** @param lut reference to storage area for lookup table + * @param ocnt number of LUT entries (will be check as optimization criteria) + * + ** @return status, true if successful (LUT has been created), false otherwise + */ + inline int initOptimizationLUT(T3 *&lut, + const unsigned long ocnt) + { + int result = 0; + if ((sizeof(T1) <= 2) && (this->InputCount > 3 * ocnt)) // optimization criteria + { // use LUT for optimization + lut = new T3[ocnt]; + if (lut != NULL) + { + DCMIMGLE_DEBUG("using optimized routine with additional LUT"); + result = 1; + } + } + return result; + } + + /** perform modality LUT transform + * + ** @param input pointer to input pixel representation + */ + void modlut(DiInputPixel *input) + { + const T1 *pixel = OFstatic_cast(const T1 *, input->getData()); + if ((pixel != NULL) && (this->Modality != NULL)) + { + const DiLookupTable *mlut = this->Modality->getTableData(); + if (mlut != NULL) + { + const int useInputBuffer = (sizeof(T1) == sizeof(T3)) && (this->Count <= input->getCount()); + if (useInputBuffer) // do not copy pixel data, reference them! + { + DCMIMGLE_DEBUG("re-using input buffer, do not copy pixel data"); + this->Data = OFstatic_cast(T3 *, input->getDataPtr()); + input->removeDataReference(); // avoid double deletion + } else + this->Data = new T3[this->Count]; + if (this->Data != NULL) + { + DCMIMGLE_DEBUG("applying modality tranformation with LUT (" << mlut->getCount() << " entries)"); + register T2 value = 0; + const T2 firstentry = mlut->getFirstEntry(value); // choose signed/unsigned method + const T2 lastentry = mlut->getLastEntry(value); + const T3 firstvalue = OFstatic_cast(T3, mlut->getFirstValue()); + const T3 lastvalue = OFstatic_cast(T3, mlut->getLastValue()); + register const T1 *p = pixel + input->getPixelStart(); + register T3 *q = this->Data; + register unsigned long i; + T3 *lut = NULL; + const unsigned long ocnt = OFstatic_cast(unsigned long, input->getAbsMaxRange()); // number of LUT entries + if (initOptimizationLUT(lut, ocnt)) + { // use LUT for optimization + const T2 absmin = OFstatic_cast(T2, input->getAbsMinimum()); + q = lut; + for (i = 0; i < ocnt; ++i) // calculating LUT entries + { + value = OFstatic_cast(T2, i) + absmin; + if (value <= firstentry) + *(q++) = firstvalue; + else if (value >= lastentry) + *(q++) = lastvalue; + else + *(q++) = OFstatic_cast(T3, mlut->getValue(value)); + } + const T3 *lut0 = lut - OFstatic_cast(T2, absmin); // points to 'zero' entry + q = this->Data; + for (i = this->InputCount; i != 0; --i) // apply LUT + *(q++) = *(lut0 + (*(p++))); + } + if (lut == NULL) // use "normal" transformation + { + for (i = this->InputCount; i != 0; --i) + { + value = OFstatic_cast(T2, *(p++)); + if (value <= firstentry) + *(q++) = firstvalue; + else if (value >= lastentry) + *(q++) = lastvalue; + else + *(q++) = OFstatic_cast(T3, mlut->getValue(value)); + } + } + delete[] lut; + } + } + } + } + + /** perform rescale slope/intercept transform + * + ** @param input pointer to input pixel representation + * @param slope rescale slope value (optional) + * @param intercept rescale intercept value (optional) + */ + void rescale(DiInputPixel *input, + const double slope = 1.0, + const double intercept = 0.0) + { + const T1 *pixel = OFstatic_cast(const T1 *, input->getData()); + if (pixel != NULL) + { + const int useInputBuffer = (sizeof(T1) == sizeof(T3)) && (this->Count <= input->getCount()) && (input->getPixelStart() == 0); + if (useInputBuffer) + { // do not copy pixel data, reference them! + DCMIMGLE_DEBUG("re-using input buffer, do not copy pixel data"); + this->Data = OFstatic_cast(T3 *, input->getDataPtr()); + input->removeDataReference(); // avoid double deletion + } else + this->Data = new T3[this->Count]; + if (this->Data != NULL) + { + register T3 *q = this->Data; + register unsigned long i; + if ((slope == 1.0) && (intercept == 0.0)) + { + if (!useInputBuffer) + { + register const T1 *p = pixel + input->getPixelStart(); + for (i = this->InputCount; i != 0; --i) // copy pixel data: can't use copyMem because T1 isn't always equal to T3 + *(q++) = OFstatic_cast(T3, *(p++)); + } + } else { + DCMIMGLE_DEBUG("applying modality transformation with rescale slope = " << slope << ", intercept = " << intercept); + T3 *lut = NULL; + register const T1 *p = pixel + input->getPixelStart(); + const unsigned long ocnt = OFstatic_cast(unsigned long, input->getAbsMaxRange()); // number of LUT entries + if (initOptimizationLUT(lut, ocnt)) + { // use LUT for optimization + const double absmin = input->getAbsMinimum(); + q = lut; + if (slope == 1.0) + { + for (i = 0; i < ocnt; ++i) // calculating LUT entries + *(q++) = OFstatic_cast(T3, OFstatic_cast(double, i) + absmin + intercept); + } else { + if (intercept == 0.0) + { + for (i = 0; i < ocnt; ++i) + *(q++) = OFstatic_cast(T3, (OFstatic_cast(double, i) + absmin) * slope); + } else { + for (i = 0; i < ocnt; ++i) + *(q++) = OFstatic_cast(T3, (OFstatic_cast(double, i) + absmin) * slope + intercept); + } + } + const T3 *lut0 = lut - OFstatic_cast(T2, absmin); // points to 'zero' entry + q = this->Data; + for (i = this->InputCount; i != 0; --i) // apply LUT + *(q++) = *(lut0 + (*(p++))); + } + if (lut == NULL) // use "normal" transformation + { + if (slope == 1.0) + { + for (i = this->InputCount; i != 0; --i) + *(q++) = OFstatic_cast(T3, OFstatic_cast(double, *(p++)) + intercept); + } else { + if (intercept == 0.0) + { + for (i = this->InputCount; i != 0; --i) + *(q++) = OFstatic_cast(T3, OFstatic_cast(double, *(p++)) * slope); + } else { + for (i = this->InputCount; i != 0; --i) + *(q++) = OFstatic_cast(T3, OFstatic_cast(double, *(p++)) * slope + intercept); + } + } + } + delete[] lut; + } + } + } + } +}; + + +#endif diff --git a/dcmimgle/include/dcmtk/dcmimgle/dimomod.h b/dcmimgle/include/dcmtk/dcmimgle/dimomod.h new file mode 100644 index 00000000..a4dbcb2c --- /dev/null +++ b/dcmimgle/include/dcmtk/dcmimgle/dimomod.h @@ -0,0 +1,283 @@ +/* + * + * Copyright (C) 1996-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimgle + * + * Author: Joerg Riesmeier + * + * Purpose: DicomMonochromeModality (Header) + * + */ + + +#ifndef DIMOMOD_H +#define DIMOMOD_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/ofstd/ofcast.h" + +#include "dcmtk/dcmimgle/diluptab.h" +#include "dcmtk/dcmimgle/diobjcou.h" + + +/*------------------------* + * forward declarations * + *------------------------*/ + +class DiDocument; +class DiInputPixel; + + +/*---------------------* + * class declaration * + *---------------------*/ + +/** Class to handle modality specific transformations (incl. modality LUT) + */ +class DCMTK_DCMIMGLE_EXPORT DiMonoModality + : public DiObjectCounter +{ + + public: + + /** constructor + * + ** @param docu pointer to dataset (encapsulated) + * @param pixel pointer to input pixel data + */ + DiMonoModality(const DiDocument *docu, + DiInputPixel *pixel); + + /** constructor, rescale + * + ** @param docu pointer to dataset (encapsulated) + * @param pixel pointer to input pixel data + * @param slope rescale slope (<> 0) + * @param intercept rescale intercept + */ + DiMonoModality(const DiDocument *docu, + DiInputPixel *pixel, + const double slope, + const double intercept); + + /** constructor, LUT + * + ** @param docu pointer to dataset (encapsulated) + * @param pixel pointer to input pixel data + * @param data element containing the modality LUT data + * @param descriptor element containing the modality LUT descriptor + * @param explanation element containing the modality LUT explanation (optional) + */ + DiMonoModality(const DiDocument *docu, + DiInputPixel *pixel, + const DcmUnsignedShort &data, + const DcmUnsignedShort &descriptor, + const DcmLongString *explanation); + + /** constructor, no modality transform + * + ** @param bits number of bits per pixel + */ + DiMonoModality(const int bits); + + /** destructor + */ + virtual ~DiMonoModality(); + + /** get integer representation + * + ** @return integer representation + */ + inline EP_Representation getRepresentation() const + { + return Representation; + } + + /** get minimum pixel value after modality transform + * + ** @return minimum pixel value + */ + inline double getMinValue() const + { + return MinValue; + } + + /** get maximum pixel value after modality transform + * + ** @return maximum pixel value + */ + inline double getMaxValue() const + { + return MaxValue; + } + + /** get number of bits describing the width of output data + * + ** @return number of bits (might be 0) + */ + inline unsigned int getBits() const + { + return Bits; + } + + /** get number of bits actually used to store the output data. + * (based on the range given by 'MinValue' and 'MaxValue') + * + ** @return number of used bits (might be 0) + */ + inline unsigned int getUsedBits() const + { + return UsedBits; + } + + /** get absolute (possible) minimum pixel value after modality transform + * + ** @return absolute minimum pixel value + */ + inline double getAbsMinimum() const + { + return AbsMinimum; + } + + /** get absolute (possible) maximum pixel value after modality transform + * + ** @return absolute maximum pixel value + */ + inline double getAbsMaximum() const + { + return AbsMaximum; + } + + /** get rescale intercept value + * + ** @return rescale intercept value + */ + inline double getRescaleIntercept() const + { + return RescaleIntercept; + } + + /** get rescale slope value + * + ** @return rescale slope value + */ + inline double getRescaleSlope() const + { + return RescaleSlope; + } + + /** get pointer to lookup table data + * + ** @return pointer to lookup table data or NULL if absent + */ + inline const DiLookupTable *getTableData() const + { + return TableData; + } + + /** get modality LUT explanation + * + ** @return modality LUT explanation or NULL if absent + */ + inline const char *getExplanation() const + { + return (TableData != NULL) ? TableData->getExplanation() : OFstatic_cast(const char *, NULL); + } + + /** check whether lookup table is present + * + ** @return true if lookup table is present, false otherwise + */ + inline int hasLookupTable() const + { + return LookupTable; + } + + /** check whether rescaling is present + * + ** @return true if rescaling is present, false otherwise + */ + inline int hasRescaling() const + { + return Rescaling; + } + + + protected: + + /** initialize internal data structures and values + * + ** @param docu pointer to dataset (encapsulated) + * @param pixel pointer to input pixel data + */ + int Init(const DiDocument *docu, + DiInputPixel *pixel); + + /** check lookup table for validity (and possibly correct it) + */ + void checkTable(); + + /** check rescaling for validity (and possibly correct it) + * + ** @param pixel pointer to input pixel data + */ + void checkRescaling(const DiInputPixel *pixel); + + /** determine integer representation used for the output data + * + ** @param docu pointer to dataset (encapsulated) + */ + void determineRepresentation(const DiDocument *docu); + + + private: + + /// integer representation + EP_Representation Representation; + + /// minimum pixel value + double MinValue; + /// maximum pixel value + double MaxValue; + + /// number of bits + unsigned int Bits; + /// number of used bits + unsigned int UsedBits; + + /// absolute minimum pixel value + double AbsMinimum; + /// absolute maximum pixel value + double AbsMaximum; + + /// rescale intercept + double RescaleIntercept; + /// rescale slope + double RescaleSlope; + + /// status flag: lookup table present + int LookupTable; + /// status flag: rescaling present + int Rescaling; + + /// pointer to modality lookup table + DiLookupTable *TableData; + + // --- declarations to avoid compiler warnings + + DiMonoModality(const DiMonoModality &); + DiMonoModality &operator=(const DiMonoModality &); +}; + + +#endif diff --git a/dcmimgle/include/dcmtk/dcmimgle/dimoopx.h b/dcmimgle/include/dcmtk/dcmimgle/dimoopx.h new file mode 100644 index 00000000..99328299 --- /dev/null +++ b/dcmimgle/include/dcmtk/dcmimgle/dimoopx.h @@ -0,0 +1,157 @@ +/* + * + * Copyright (C) 1996-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimgle + * + * Author: Joerg Riesmeier + * + * Purpose: DicomMonoOutputPixel (Header) + * + */ + + +#ifndef DIMOOPX_H +#define DIMOOPX_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmimgle/diutils.h" + +#include "dcmtk/ofstd/ofstream.h" + + +/*------------------------* + * forward declarations * + *------------------------*/ + +class DiMonoPixel; + + +/*---------------------* + * class declaration * + *---------------------*/ + +/** Abstract base class to create monochrome output data + */ +class DCMTK_DCMIMGLE_EXPORT DiMonoOutputPixel +{ + + public: + + /** constructor + * + ** @param pixel pointer to intermediate pixel representation + * @param size number of pixel per frame + * @param frame frame to be rendered + * @param max maximum output value + */ + DiMonoOutputPixel(const DiMonoPixel *pixel, + const unsigned long size, + const unsigned long frame, + const unsigned long max); + + /** destructor + */ + virtual ~DiMonoOutputPixel(); + + /** get integer representation (abstract) + * + ** @return integer representation + */ + virtual EP_Representation getRepresentation() const = 0; + + /** get pointer to output pixel data (abstract) + * + ** @return pointer to pixel data + */ + virtual const void *getData() const = 0; + + /** get pointer to output pixel data (abstract) + * + ** @return pointer to pixel data + */ + virtual void *getDataPtr() = 0; + + /** remove reference to (internally handled) pixel data (abstract) + */ + virtual void removeDataReference() = 0; + + /** get size of one pixel / item in the pixel array (abstract) + * + ** @return item size + */ + virtual size_t getItemSize() const = 0; + + /** write pixel data of selected frame to PPM/ASCII file (abstract) + * + ** @param stream open C++ output stream + * + ** @return status, true if successful, false otherwise + */ + virtual int writePPM(STD_NAMESPACE ostream& stream) const = 0; + + /** write pixel data of selected frame to PPM/ASCII file (abstract) + * + ** @param stream open C file stream + * + ** @return status, true if successful, false otherwise + */ + virtual int writePPM(FILE *stream) const = 0; + + /** get number of pixel per frame + * + ** @return number of pixel per frame + */ + inline unsigned long getCount() const + { + return FrameSize; + } + + /** check whether specified pixel value is used in the image. + * Pixel array is examined when this method is called for the first time + * (just-in-time creation / create on demand of the supporting table). + * + ** @param value pixel value to be checked + * + ** @return true if value is used, false otherwise + */ + int isUnused(const unsigned long value); + + + protected: + + /** examine which pixel values are actually used (abstract) + */ + virtual void determineUsedValues() = 0; + + + /// number of pixels per frame (intermediate representation) + /*const*/ unsigned long Count; + /// number of pixels per frame (memory buffer size) + const unsigned long FrameSize; + + /// array of used pixel values + Uint8 *UsedValues; + /// maximum output value + const unsigned long MaxValue; + + + private: + + // --- declarations to avoid compiler warnings + + DiMonoOutputPixel(const DiMonoOutputPixel &); + DiMonoOutputPixel &operator=(const DiMonoOutputPixel &); +}; + + +#endif diff --git a/dcmimgle/include/dcmtk/dcmimgle/dimoopxt.h b/dcmimgle/include/dcmtk/dcmimgle/dimoopxt.h new file mode 100644 index 00000000..c2a482af --- /dev/null +++ b/dcmimgle/include/dcmtk/dcmimgle/dimoopxt.h @@ -0,0 +1,1294 @@ +/* + * + * Copyright (C) 1996-2013, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimgle + * + * Author: Joerg Riesmeier + * + * Purpose: DicomMonoOutputPixelTemplate (Header) + * + */ + + +#ifndef DIMOOPXT_H +#define DIMOOPXT_H + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/ofstd/ofcast.h" +#include "dcmtk/ofstd/ofbmanip.h" + +#include "dcmtk/dcmimgle/dimoopx.h" +#include "dcmtk/dcmimgle/dimopx.h" +#include "dcmtk/dcmimgle/diluptab.h" +#include "dcmtk/dcmimgle/diovlay.h" +#include "dcmtk/dcmimgle/dipxrept.h" +#include "dcmtk/dcmimgle/didispfn.h" +#include "dcmtk/dcmimgle/didislut.h" + +#ifdef PASTEL_COLOR_OUTPUT +#include "dimcopxt.h" +#endif + +#define INCLUDE_CMATH +#include "dcmtk/ofstd/ofstdinc.h" + + +/*---------------------* + * class declaration * + *---------------------*/ + +/** Template class to create monochrome output data + */ +template +class DiMonoOutputPixelTemplate + : public DiMonoOutputPixel, + public DiPixelRepresentationTemplate +{ + + public: + + /** constructor + * + ** @param buffer storage area for the output pixel data (optional, maybe NULL) + * @param pixel pointer to intermediate pixel representation + * @param overlays array of overlay management objects + * @param vlut VOI LUT (optional, maybe NULL) + * @param plut presentation LUT (optional, maybe NULL) + * @param disp display function (optional, maybe NULL) + * @param vfunc VOI LUT function (optional) + * @param center window center (optional, invalid if 'width' < 1) + * @param width window width (optional, invalid if < 1) + * @param low lowest pixel value for the output data (e.g. 0) + * @param high highest pixel value for the output data (e.g. 255) + * @param columns image's width (in pixels) + * @param rows image's height + * @param frame frame to be rendered + * (#)param frames total number of frames present in intermediate representation + * @param pastel flag indicating whether to use not only 'real' grayscale values (optional, experimental) + */ + DiMonoOutputPixelTemplate(void *buffer, + const DiMonoPixel *pixel, + DiOverlay *overlays[2], + const DiLookupTable *vlut, + const DiLookupTable *plut, + DiDisplayFunction *disp, + const EF_VoiLutFunction vfunc, + const double center, + const double width, + const Uint32 low, + const Uint32 high, + const Uint16 columns, + const Uint16 rows, + const unsigned long frame, +#ifdef PASTEL_COLOR_OUTPUT + const unsigned long frames, +#else + const unsigned long /*frames*/, +#endif + const int pastel = 0) + : DiMonoOutputPixel(pixel, OFstatic_cast(unsigned long, columns) * OFstatic_cast(unsigned long, rows), frame, + OFstatic_cast(unsigned long, fabs(OFstatic_cast(double, high - low)))), + Data(NULL), + DeleteData(buffer == NULL), + ColorData(NULL) + { + if ((pixel != NULL) && (Count > 0) && (FrameSize >= Count)) + { + if (pastel) +#ifdef PASTEL_COLOR_OUTPUT + color(buffer, pixel, frame, frames); +#else + DCMIMGLE_ERROR("pastel color output not supported"); +#endif + else + { + DCMIMGLE_TRACE("monochrome output image - columns: " << columns << ", rows: " << rows << ", frame: " << frame); + DCMIMGLE_TRACE("monochrome output values - low: " << OFstatic_cast(unsigned long, low) << ", high: " + << OFstatic_cast(unsigned long, high) << ((low > high) ? " (inverted)" : "")); + Data = OFstatic_cast(T3 *, buffer); + if ((vlut != NULL) && (vlut->isValid())) // valid VOI LUT ? + voilut(pixel, frame * FrameSize, vlut, plut, disp, OFstatic_cast(T3, low), OFstatic_cast(T3, high)); + else + { + if (width < 1) // no valid window according to supplement 33 + nowindow(pixel, frame * FrameSize, plut, disp, OFstatic_cast(T3, low), OFstatic_cast(T3, high)); + else if (vfunc == EFV_Sigmoid) + sigmoid(pixel, frame * FrameSize, plut, disp, center, width, OFstatic_cast(T3, low), OFstatic_cast(T3, high)); + else // linear + window(pixel, frame * FrameSize, plut, disp, center, width, OFstatic_cast(T3, low), OFstatic_cast(T3, high)); + } + overlay(overlays, disp, columns, rows, frame); // add (visible) overlay planes to output bitmap + } + } + } + + /** destructor + */ + virtual ~DiMonoOutputPixelTemplate() + { + if (DeleteData) + delete[] Data; + delete ColorData; + } + + /** get integer representation of output data + * + ** @return integer representation + */ + inline EP_Representation getRepresentation() const + { + return DiPixelRepresentationTemplate::getRepresentation(); + } + + /** get size of one pixel / item in the pixel array + * + ** @return item size + */ + inline size_t getItemSize() const + { + return (ColorData != NULL) ? ColorData->getItemSize() : sizeof(T3); + } + + /** get pointer to output pixel data + * + ** @return pointer to pixel data + */ + inline const void *getData() const + { + return (ColorData != NULL) ? ColorData->getData() : OFstatic_cast(const void *, Data); + } + + /** get pointer to output pixel data + * + ** @return pointer to pixel data + */ + virtual void *getDataPtr() + { + return (ColorData != NULL) ? ColorData->getDataPtr() : OFstatic_cast(void *, Data); + } + + /** remove reference to (internally handled) pixel data (abstract) + */ + inline void removeDataReference() + { + Data = NULL; + DeleteData = 0; + } + + /** write pixel data of selected frame to PPM/ASCII file + * + ** @param stream open C++ output stream + * + ** @return status, true if successful, false otherwise + */ + inline int writePPM(STD_NAMESPACE ostream& stream) const + { + if (Data != NULL) + { + register unsigned long i; + for (i = 0; i < FrameSize; ++i) + stream << OFstatic_cast(unsigned long, Data[i]) << " "; // typecast to resolve problems with 'char' + return 1; + } + if (ColorData != NULL) + return ColorData->writePPM(stream); + return 0; + } + + /** write pixel data of selected frame to PPM/ASCII file + * + ** @param stream open C file stream + * + ** @return status, true if successful, false otherwise + */ + inline int writePPM(FILE *stream) const + { + if (Data != NULL) + { + register unsigned long i; + for (i = 0; i < FrameSize; ++i) + fprintf(stream, "%lu ", OFstatic_cast(unsigned long, Data[i])); + return 1; + } + if (ColorData != NULL) + return ColorData->writePPM(stream); + return 0; + } + + + protected: + + /** examine which pixel values are actually used + */ + inline void determineUsedValues() + { + if ((UsedValues == NULL) && (MaxValue > 0) && (MaxValue < MAX_TABLE_ENTRY_COUNT)) + { + UsedValues = new Uint8[MaxValue + 1]; + if (UsedValues != NULL) + { + OFBitmanipTemplate::zeroMem(UsedValues, MaxValue + 1); // initialize array + register const T3 *p = Data; + register Uint8 *q = UsedValues; + register unsigned long i; + for (i = Count; i != 0; --i) + *(q + *(p++)) = 1; // mark used entries + } + } + } + + + private: + + /** create a display LUT with the specified number of input bits + * + ** @param dlut reference to storage area where the display LUT should be stored + * @param disp pointer to object describing the current display function + * @param bits number of bits defining the input width of the display LUT + */ + inline void createDisplayLUT(const DiDisplayLUT *&dlut, + DiDisplayFunction *disp, + const int bits) + { + if ((disp != NULL) && (disp->isValid())) + { // create Display LUT + dlut = disp->getLookupTable(bits); + if ((dlut != NULL) && (dlut->isValid())) // LUT is valid + { + DCMIMGLE_DEBUG("using display transformation"); + } else { + DCMIMGLE_WARN("can't create display LUT ... ignoring display transformation"); + dlut = NULL; + } + } + } + + /** initialize an optimization LUT if the optimization criteria is fulfilled + * + ** @param lut reference to storage area where the optimization LUT should be stored + * @param ocnt number of entries for the optimization LUT + */ + inline int initOptimizationLUT(T3 *&lut, + const unsigned long ocnt) + { + int result = 0; + if ((sizeof(T1) <= 2) && (Count > 3 * ocnt)) // optimization criteria + { // use LUT for optimization + lut = new T3[ocnt]; + if (lut != NULL) + { + DCMIMGLE_DEBUG("using optimized routine with additional LUT (" << ocnt << " entries)"); + result = 1; + } + } + return result; + } + +#ifdef PASTEL_COLOR_OUTPUT + void color(void *buffer, // create true color pastel image + const DiMonoPixel *inter, + const unsigned long frame, + const unsigned long frames) + { + ColorData = new DiMonoColorOutputPixelTemplate(buffer, inter, frame, frames); + if (ColorData != NULL) + DCMIMGLE_DEBUG(">>> COLOR <<<"); + } +#endif + + /** apply the currently active VOI LUT to the output data + * + ** @param inter pointer to intermediate pixel representation + * @param start offset of the first pixel to be processed + * @param vlut VOI LUT + * @param plut presentation LUT (optional, maybe NULL) + * @param disp display function (optional, maybe NULL) + * @param low lowest pixel value for the output data (e.g. 0) + * @param high highest pixel value for the output data (e.g. 255) + */ + void voilut(const DiMonoPixel *inter, + const Uint32 start, + const DiLookupTable *vlut, + const DiLookupTable *plut, + DiDisplayFunction *disp, + const T3 low, + const T3 high) + { + const T1 *pixel = OFstatic_cast(const T1 *, inter->getData()); + if ((pixel != NULL) && (vlut != NULL)) + { + if (Data == NULL) + Data = new T3[FrameSize]; + if (Data != NULL) + { + DCMIMGLE_DEBUG("applying VOI transformation with LUT (" << vlut->getCount() << " entries)"); + const DiDisplayLUT *dlut = NULL; + const double minvalue = vlut->getMinValue(); + const double outrange = OFstatic_cast(double, high) - OFstatic_cast(double, low) + 1; + register unsigned long i; + if (minvalue == vlut->getMaxValue()) // LUT has only one entry or all entries are equal + { + T3 value; + if ((plut != NULL) && (plut->isValid())) // has presentation LUT + { + DCMIMGLE_DEBUG("applying presentation LUT transformation"); + createDisplayLUT(dlut, disp, plut->getBits()); + const Uint32 value2 = OFstatic_cast(Uint32, (minvalue / OFstatic_cast(double, vlut->getAbsMaxRange())) * plut->getCount()); + if (dlut != NULL) // perform display transformation + { + DCMIMGLE_TRACE("monochrome rendering: VOI LUT #1 - UNTESTED"); + if (low > high) // invers + value = OFstatic_cast(T3, dlut->getValue(OFstatic_cast(Uint16, plut->getAbsMaxRange() - plut->getValue(value2) - 1))); + else // normal + value = OFstatic_cast(T3, dlut->getValue(OFstatic_cast(Uint16, plut->getValue(value2)))); + } else { // don't use display: invalid or absent + DCMIMGLE_TRACE("monochrome rendering: VOI LUT #2"); + value = OFstatic_cast(T3, OFstatic_cast(double, low) + OFstatic_cast(double, plut->getValue(value2)) * outrange / OFstatic_cast(double, plut->getAbsMaxRange())); + } + } else { // has no presentation LUT + createDisplayLUT(dlut, disp, vlut->getBits()); + if (dlut != NULL) // perform display transformation + { + DCMIMGLE_TRACE("monochrome rendering: VOI LUT #3 - UNTESTED"); + if (low > high) // invers + value = OFstatic_cast(T3, dlut->getValue(OFstatic_cast(Uint16, vlut->getAbsMaxRange() - minvalue - 1))); + else // normal + value = OFstatic_cast(T3, dlut->getValue(OFstatic_cast(Uint16, minvalue))); + } else { // don't use display: invalid or absent + DCMIMGLE_TRACE("monochrome rendering: VOI LUT #4"); + value = OFstatic_cast(T3, OFstatic_cast(double, low) + (minvalue / OFstatic_cast(double, vlut->getAbsMaxRange())) * outrange); + } + } + OFBitmanipTemplate::setMem(Data, value, Count); // set output pixels to LUT value + } else { + register T2 value = 0; + const T2 absmin = OFstatic_cast(T2, inter->getAbsMinimum()); + const T2 firstentry = vlut->getFirstEntry(value); // choose signed/unsigned method + const T2 lastentry = vlut->getLastEntry(value); + const unsigned long ocnt = OFstatic_cast(unsigned long, inter->getAbsMaxRange()); // number of LUT entries + register const T1 *p = pixel + start; + register T3 *q = Data; + T3 *lut = NULL; + if ((plut != NULL) && (plut->isValid())) // has presentation LUT + { + DCMIMGLE_DEBUG("applying presentation LUT transformation"); + createDisplayLUT(dlut, disp, plut->getBits()); + register Uint32 value2; // presentation LUT is always unsigned + const Uint32 pcnt = plut->getCount(); + const double gradient1 = OFstatic_cast(double, pcnt) / OFstatic_cast(double, vlut->getAbsMaxRange()); + const Uint32 firstvalue = OFstatic_cast(Uint32, OFstatic_cast(double, vlut->getFirstValue()) * gradient1); + const Uint32 lastvalue = OFstatic_cast(Uint32, OFstatic_cast(double, vlut->getLastValue()) * gradient1); + if (initOptimizationLUT(lut, ocnt)) + { // use LUT for optimization + q = lut; + if (dlut != NULL) // perform display transformation + { + DCMIMGLE_TRACE("monochrome rendering: VOI LUT #5"); + if (low > high) // inverse + { + const Uint16 maxvalue = OFstatic_cast(Uint16, plut->getAbsMaxRange() - 1); + for (i = 0; i < ocnt; ++i) + { + value = OFstatic_cast(T2, i) + absmin; + if (value <= firstentry) + value2 = firstvalue; + else if (value >= lastentry) + value2 = lastvalue; + else + value2 = OFstatic_cast(Uint32, OFstatic_cast(double, vlut->getValue(value)) * gradient1); + *(q++) = OFstatic_cast(T3, dlut->getValue(OFstatic_cast(Uint16, maxvalue - plut->getValue(value2)))); + } + } else { // normal + for (i = 0; i < ocnt; ++i) + { + value = OFstatic_cast(T2, i) + absmin; + if (value <= firstentry) + value2 = firstvalue; + else if (value >= lastentry) + value2 = lastvalue; + else + value2 = OFstatic_cast(Uint32, OFstatic_cast(double, vlut->getValue(value)) * gradient1); + *(q++) = OFstatic_cast(T3, dlut->getValue(plut->getValue(value2))); + } + } + } else { // don't use display: invalid or absent + DCMIMGLE_TRACE("monochrome rendering: VOI LUT #6"); + const double gradient2 = outrange / OFstatic_cast(double, plut->getAbsMaxRange()); + for (i = 0; i < ocnt; ++i) + { + value = OFstatic_cast(T2, i) + absmin; + if (value <= firstentry) + value2 = firstvalue; + else if (value >= lastentry) + value2 = lastvalue; + else + value2 = OFstatic_cast(Uint32, OFstatic_cast(double, vlut->getValue(value)) * gradient1); + *(q++) = OFstatic_cast(T3, OFstatic_cast(double, low) + OFstatic_cast(double, plut->getValue(value2)) * gradient2); + } + } + const T3 *lut0 = lut - OFstatic_cast(T2, inter->getAbsMinimum()); // points to 'zero' entry + q = Data; + for (i = Count; i != 0; --i) // apply LUT + *(q++) = *(lut0 + (*(p++))); + } + if (lut == NULL) // use "normal" transformation + { + if (dlut != NULL) // perform display transformation + { + DCMIMGLE_TRACE("monochrome rendering: VOI LUT #7"); + if (low > high) // inverse + { + const Uint16 maxvalue = OFstatic_cast(Uint16, vlut->getAbsMaxRange() - 1); + for (i = Count; i != 0; --i) + { + value = OFstatic_cast(T2, *(p++)); // pixel value + if (value <= firstentry) + value2 = firstvalue; + else if (value >= lastentry) + value2 = lastvalue; + else + value2 = OFstatic_cast(Uint32, OFstatic_cast(double, vlut->getValue(value)) * gradient1); + *(q++) = OFstatic_cast(T3, dlut->getValue(OFstatic_cast(Uint16, maxvalue - plut->getValue(value2)))); + } + } else { // normal + for (i = Count; i != 0; --i) + { + value = OFstatic_cast(T2, *(p++)); // pixel value + if (value <= firstentry) + value2 = firstvalue; + else if (value >= lastentry) + value2 = lastvalue; + else + value2 = OFstatic_cast(Uint32, OFstatic_cast(double, vlut->getValue(value)) * gradient1); + *(q++) = OFstatic_cast(T3, dlut->getValue(plut->getValue(value2))); + } + } + } else { // don't use display: invalid or absent + DCMIMGLE_TRACE("monochrome rendering: VOI LUT #8"); + const double gradient2 = outrange / OFstatic_cast(double, plut->getAbsMaxRange()); + for (i = Count; i != 0; --i) + { + value = OFstatic_cast(T2, *(p++)); // pixel value + if (value <= firstentry) + value2 = firstvalue; + else if (value >= lastentry) + value2 = lastvalue; + else + value2 = OFstatic_cast(Uint32, OFstatic_cast(double, vlut->getValue(value)) * gradient1); + *(q++) = OFstatic_cast(T3, OFstatic_cast(double, low) + OFstatic_cast(double, plut->getValue(value2)) * gradient2); + } + } + } + } else { // has no presentation LUT + createDisplayLUT(dlut, disp, vlut->getBits()); + const double gradient = outrange / OFstatic_cast(double, vlut->getAbsMaxRange()); + const T3 firstvalue = OFstatic_cast(T3, OFstatic_cast(double, low) + OFstatic_cast(double, vlut->getFirstValue()) * gradient); + const T3 lastvalue = OFstatic_cast(T3, OFstatic_cast(double, low) + OFstatic_cast(double, vlut->getLastValue()) * gradient); + if (initOptimizationLUT(lut, ocnt)) + { // use LUT for optimization + q = lut; + if (dlut != NULL) // perform display transformation + { + DCMIMGLE_TRACE("monochrome rendering: VOI LUT #9"); + if (low > high) // inverse + { + const Uint16 maxvalue = OFstatic_cast(Uint16, vlut->getAbsMaxRange() - 1); + for (i = 0; i < ocnt; ++i) + { + value = OFstatic_cast(T2, i) + absmin; + if (value < firstentry) + value = firstentry; + else if (value > lastentry) + value = lastentry; + *(q++) = OFstatic_cast(T3, dlut->getValue(OFstatic_cast(Uint16, maxvalue - vlut->getValue(value)))); + } + } else { // normal + for (i = 0; i < ocnt; ++i) + { + value = OFstatic_cast(T2, i) + absmin; + if (value < firstentry) + value = firstentry; + else if (value > lastentry) + value = lastentry; + *(q++) = OFstatic_cast(T3, dlut->getValue(vlut->getValue(value))); + } + } + } else { // don't use display: invalid or absent + DCMIMGLE_TRACE("monochrome rendering: VOI LUT #10"); + for (i = 0; i < ocnt; ++i) // calculating LUT entries + { + value = OFstatic_cast(T2, i) + absmin; + if (value <= firstentry) + *(q++) = firstvalue; + else if (value >= lastentry) + *(q++) = lastvalue; + else + *(q++) = OFstatic_cast(T3, OFstatic_cast(double, low) + OFstatic_cast(double, vlut->getValue(value)) * gradient); + } + } + const T3 *lut0 = lut - OFstatic_cast(T2, inter->getAbsMinimum()); // points to 'zero' entry + q = Data; + for (i = Count; i != 0; --i) // apply LUT + *(q++) = *(lut0 + (*(p++))); + } + if (lut == NULL) // use "normal" transformation + { + if (dlut != NULL) // perform display transformation + { + DCMIMGLE_TRACE("monochrome rendering: VOI LUT #11"); + if (low > high) // inverse + { + const Uint16 maxvalue = OFstatic_cast(Uint16, vlut->getAbsMaxRange() - 1); + for (i = Count; i != 0; --i) + { + value = OFstatic_cast(T2, *(p++)); + if (value < firstentry) + value = firstentry; + else if (value > lastentry) + value = lastentry; + *(q++) = OFstatic_cast(T3, dlut->getValue(OFstatic_cast(Uint16, maxvalue - vlut->getValue(value)))); + } + } else { // normal + for (i = Count; i != 0; --i) + { + value = OFstatic_cast(T2, *(p++)); + if (value < firstentry) + value = firstentry; + else if (value > lastentry) + value = lastentry; + *(q++) = OFstatic_cast(T3, dlut->getValue(vlut->getValue(value))); + } + } + } else { // don't use display: invalid or absent + DCMIMGLE_TRACE("monochrome rendering: VOI LUT #12"); + for (i = 0; i < Count; ++i) + { + value = OFstatic_cast(T2, *(p++)); + if (value <= firstentry) + *(q++) = firstvalue; + else if (value >= lastentry) + *(q++) = lastvalue; + else + *(q++) = OFstatic_cast(T3, OFstatic_cast(double, low) + OFstatic_cast(double, vlut->getValue(value)) * gradient); + } + } + } + } + delete[] lut; + } + if (Count < FrameSize) + OFBitmanipTemplate::zeroMem(Data + Count, FrameSize - Count); // set remaining pixels of frame to zero + } + } else + Data = NULL; + } + + /** perform linear scaling to the output data (no windowing) + * + ** @param inter pointer to intermediate pixel representation + * @param start offset of the first pixel to be processed + * @param plut presentation LUT (optional, maybe NULL) + * @param disp display function (optional, maybe NULL) + * @param low lowest pixel value for the output data (e.g. 0) + * @param high highest pixel value for the output data (e.g. 255) + */ + void nowindow(const DiMonoPixel *inter, + const Uint32 start, + const DiLookupTable *plut, + DiDisplayFunction *disp, + const T3 low, + const T3 high) + { + const DiDisplayLUT *dlut = NULL; + const T1 *pixel = OFstatic_cast(const T1 *, inter->getData()); + if (pixel != NULL) + { + if (Data == NULL) // create new output buffer + Data = new T3[FrameSize]; + if (Data != NULL) + { + DCMIMGLE_DEBUG("applying no VOI transformation (linear scaling)"); + const double absmin = inter->getAbsMinimum(); + const double absmax = inter->getAbsMaximum(); + const double outrange = OFstatic_cast(double, high) - OFstatic_cast(double, low) + 1; + const unsigned long ocnt = OFstatic_cast(unsigned long, inter->getAbsMaxRange()); // number of LUT entries + DCMIMGLE_TRACE("intermediate pixel data - absmin: " << absmin << ", absmax: " << absmax); + register const T1 *p = pixel + start; + register T3 *q = Data; + register unsigned long i; + T3 *lut = NULL; + if ((plut != NULL) && (plut->isValid())) // has presentation LUT + { + DCMIMGLE_DEBUG("applying presentation LUT transformation"); + createDisplayLUT(dlut, disp, plut->getBits()); + register Uint32 value; // presentation LUT is always unsigned + const double gradient1 = OFstatic_cast(double, plut->getCount()) / inter->getAbsMaxRange(); + const double gradient2 = outrange / OFstatic_cast(double, plut->getAbsMaxRange()); + if (initOptimizationLUT(lut, ocnt)) + { // use LUT for optimization + q = lut; + if (dlut != NULL) // perform display transformation + { + DCMIMGLE_TRACE("monochrome rendering: VOI NONE #1"); + if (low > high) // inverse + { + const Uint16 maxvalue = OFstatic_cast(Uint16, plut->getAbsMaxRange() - 1); + for (i = 0; i < ocnt; ++i) + { + value = OFstatic_cast(Uint32, OFstatic_cast(double, i) * gradient1); + *(q++) = OFstatic_cast(T3, dlut->getValue(OFstatic_cast(Uint16, maxvalue - plut->getValue(value)))); + } + } else { // normal + for (i = 0; i < ocnt; ++i) + { + value = OFstatic_cast(Uint32, OFstatic_cast(double, i) * gradient1); + *(q++) = OFstatic_cast(T3, dlut->getValue(plut->getValue(value))); + } + } + } else { // don't use display: invalid or absent + DCMIMGLE_TRACE("monochrome rendering: VOI NONE #2"); + for (i = 0; i < ocnt; ++i) + { + value = OFstatic_cast(Uint32, OFstatic_cast(double, i) * gradient1); + *(q++) = OFstatic_cast(T3, OFstatic_cast(double, low) + OFstatic_cast(double, plut->getValue(value)) * gradient2); + } + } + const T3 *lut0 = lut - OFstatic_cast(T2, inter->getAbsMinimum()); // points to 'zero' entry + q = Data; + for (i = Count; i != 0; --i) // apply LUT + *(q++) = *(lut0 + (*(p++))); + } + if (lut == NULL) // use "normal" transformation + { + if (dlut != NULL) // perform display transformation + { + DCMIMGLE_TRACE("monochrome rendering: VOI NONE #3"); + if (low > high) // inverse + { + const Uint16 maxvalue = OFstatic_cast(Uint16, plut->getAbsMaxRange() - 1); + for (i = Count; i != 0; --i) + { + value = OFstatic_cast(Uint32, (OFstatic_cast(double, *(p++)) - absmin) * gradient1); + *(q++) = OFstatic_cast(T3, dlut->getValue(OFstatic_cast(Uint16, maxvalue - plut->getValue(value)))); + } + } else { // normal + for (i = Count; i != 0; --i) + { + value = OFstatic_cast(Uint32, (OFstatic_cast(double, *(p++)) - absmin) * gradient1); + *(q++) = OFstatic_cast(T3, dlut->getValue(plut->getValue(value))); + } + } + } else { // don't use display: invalid or absent + DCMIMGLE_TRACE("monochrome rendering: VOI NONE #4"); + for (i = Count; i != 0; --i) + { + value = OFstatic_cast(Uint32, (OFstatic_cast(double, *(p++)) - absmin) * gradient1); + *(q++) = OFstatic_cast(T3, OFstatic_cast(double, low) + OFstatic_cast(double, plut->getValue(value)) * gradient2); + } + } + } + } else { // has no presentation LUT + createDisplayLUT(dlut, disp, inter->getBits()); + register const double gradient = outrange / (inter->getAbsMaxRange()); + if (initOptimizationLUT(lut, ocnt)) + { // use LUT for optimization + q = lut; + if (dlut != NULL) // perform display transformation + { + DCMIMGLE_TRACE("monochrome rendering: VOI NONE #5"); + if (low > high) // inverse + { + for (i = ocnt; i != 0; --i) // calculating LUT entries + *(q++) = OFstatic_cast(T3, dlut->getValue(OFstatic_cast(Uint16, i - 1))); + } else { // normal + for (i = 0; i < ocnt; ++i) // calculating LUT entries + *(q++) = OFstatic_cast(T3, dlut->getValue(OFstatic_cast(Uint16, i))); + } + } else { // don't use display: invalid or absent + DCMIMGLE_TRACE("monochrome rendering: VOI NONE #6"); + for (i = 0; i < ocnt; ++i) // calculating LUT entries + *(q++) = OFstatic_cast(T3, OFstatic_cast(double, low) + OFstatic_cast(double, i) * gradient); + } + const T3 *lut0 = lut - OFstatic_cast(T2, inter->getAbsMinimum()); // points to 'zero' entry + q = Data; + for (i = Count; i != 0; --i) // apply LUT + *(q++) = *(lut0 + (*(p++))); + } + if (lut == NULL) // use "normal" transformation + { + if (dlut != NULL) // perform display transformation + { + DCMIMGLE_TRACE("monochrome rendering: VOI NONE #7"); + if (low > high) // inverse + { + for (i = Count; i != 0; --i) + *(q++) = OFstatic_cast(T3, dlut->getValue(OFstatic_cast(Uint16, absmax - (OFstatic_cast(double, *(p++)) - absmin)))); + } else { // normal + for (i = Count; i != 0; --i) + *(q++) = OFstatic_cast(T3, dlut->getValue(OFstatic_cast(Uint16, OFstatic_cast(double, *(p++)) - absmin))); + } + } else { // don't use display: invalid or absent + DCMIMGLE_TRACE("monochrome rendering: VOI NONE #8"); + for (i = Count; i != 0; --i) + *(q++) = OFstatic_cast(T3, OFstatic_cast(double, low) + (OFstatic_cast(double, *(p++)) - absmin) * gradient); + } + } + } + delete[] lut; + if (Count < FrameSize) + OFBitmanipTemplate::zeroMem(Data + Count, FrameSize - Count); // set remaining pixels of frame to zero + } + } else + Data = NULL; + } + + /** apply the currently active sigmoid VOI window to the output data + * + ** @param inter pointer to intermediate pixel representation + * @param start offset of the first pixel to be processed + * @param plut presentation LUT (optional, maybe NULL) + * @param disp display function (optional, maybe NULL) + * @param center window center + * @param width window width (>= 1) + * @param low lowest pixel value for the output data (e.g. 0) + * @param high highest pixel value for the output data (e.g. 255) + */ + void sigmoid(const DiMonoPixel *inter, + const Uint32 start, + const DiLookupTable *plut, + DiDisplayFunction *disp, + const double center, + const double width, + const T3 low, + const T3 high) + { + const T1 *pixel = OFstatic_cast(const T1 *, inter->getData()); + if (pixel != NULL) + { + if (Data == NULL) + Data = new T3[FrameSize]; // create new output buffer + if (Data != NULL) + { + DCMIMGLE_DEBUG("applying sigmoid VOI transformation with window center = " << center << ", width = " << width); + const DiDisplayLUT *dlut = NULL; + const double absmin = inter->getAbsMinimum(); + const double outrange = OFstatic_cast(double, high) - OFstatic_cast(double, low); // output range + const unsigned long ocnt = OFstatic_cast(unsigned long, inter->getAbsMaxRange()); // number of LUT entries + register const T1 *p = pixel + start; + register T3 *q = Data; + register unsigned long i; + register double value; + T3 *lut = NULL; + if ((plut != NULL) && (plut->isValid())) // has presentation LUT + { + DCMIMGLE_DEBUG("applying presentation LUT transformation"); + createDisplayLUT(dlut, disp, plut->getBits()); + register Uint32 value2; // presentation LUT is always unsigned + const double plutcnt_1 = OFstatic_cast(double, plut->getCount() - 1); + const double plutmax_1 = OFstatic_cast(double, plut->getAbsMaxRange() - 1); + if (initOptimizationLUT(lut, ocnt)) + { // use LUT for optimization + q = lut; + if (dlut != NULL) // perform display transformation + { + DCMIMGLE_TRACE("monochrome rendering: VOI SIGMOID #1"); + const double maxvalue = OFstatic_cast(double, dlut->getCount() - 1); + const double offset = (low > high) ? maxvalue : 0; + const double gradient = (low > high) ? (-maxvalue / plutmax_1) : (maxvalue / plutmax_1); + for (i = 0; i < ocnt; ++i) + { + value = OFstatic_cast(double, i) + absmin; + value2 = OFstatic_cast(Uint32, plutcnt_1 / (1 + exp(-4 * (value - center) / width))); + *(q++) = OFstatic_cast(T3, dlut->getValue(OFstatic_cast(Uint16, offset + OFstatic_cast(double, plut->getValue(value2)) * gradient))); + } + } else { // don't use display: invalid or absent + DCMIMGLE_TRACE("monochrome rendering: VOI SIGMOID #2"); + const double gradient = outrange / plutmax_1; + for (i = 0; i < ocnt; ++i) + { + value = OFstatic_cast(double, i) + absmin; + value2 = OFstatic_cast(Uint32, plutcnt_1 / (1 + exp(-4 * (value - center) / width))); + *(q++) = OFstatic_cast(T3, OFstatic_cast(double, low) + OFstatic_cast(double, plut->getValue(value2)) * gradient); + } + } + const T3 *lut0 = lut - OFstatic_cast(T2, absmin); // points to 'zero' entry + q = Data; + for (i = Count; i != 0; --i) // apply LUT + *(q++) = *(lut0 + (*(p++))); + } + if (lut == NULL) // use "normal" transformation + { + if (dlut != NULL) // perform display transformation + { + DCMIMGLE_TRACE("monochrome rendering: VOI SIGMOID #3"); + const double maxvalue = OFstatic_cast(double, dlut->getCount() - 1); + const double offset = (low > high) ? maxvalue : 0; + const double gradient = (low > high) ? (-maxvalue / plutmax_1) : (maxvalue / plutmax_1); + for (i = Count; i != 0; --i) + { + value = OFstatic_cast(double, *(p++)); + value2 = OFstatic_cast(Uint32, plutcnt_1 / (1 + exp(-4 * (value - center) / width))); + *(q++) = OFstatic_cast(T3, dlut->getValue(OFstatic_cast(Uint16, offset + OFstatic_cast(double, plut->getValue(value2)) * gradient))); + } + } else { // don't use display: invalid or absent + DCMIMGLE_TRACE("monochrome rendering: VOI SIGMOID #4"); + const double gradient = outrange / plutmax_1; + for (i = Count; i != 0; --i) + { + value = OFstatic_cast(double, *(p++)); + value2 = OFstatic_cast(Uint32, plutcnt_1 / (1 + exp(-4 * (value - center) / width))); + *(q++) = OFstatic_cast(T3, OFstatic_cast(double, low) + OFstatic_cast(double, plut->getValue(value2)) * gradient); + } + } + } + } else { // has no presentation LUT + createDisplayLUT(dlut, disp, bitsof(T1)); + if (initOptimizationLUT(lut, ocnt)) + { // use LUT for optimization + q = lut; + if (dlut != NULL) // perform display transformation + { + DCMIMGLE_TRACE("monochrome rendering: VOI SIGMOID #5"); + const double maxvalue = OFstatic_cast(double, dlut->getCount() - 1); + const double outrange2 = (low > high) ? -maxvalue : maxvalue; + const double offset = (low > high) ? maxvalue : 0; + for (i = 0; i < ocnt; ++i) // calculating LUT entries + { + value = OFstatic_cast(double, i) + absmin; + *(q++) = OFstatic_cast(T3, dlut->getValue(OFstatic_cast(Uint16, offset + outrange2 / (1 + exp(-4 * (value - center) / width))))); + } + } else { // don't use display: invalid or absent + DCMIMGLE_TRACE("monochrome rendering: VOI SIGMOID #6"); + for (i = 0; i < ocnt; ++i) // calculating LUT entries + { + value = OFstatic_cast(double, i) + absmin; + *(q++) = OFstatic_cast(T3, outrange / (1 + exp(-4 * (value - center) / width))); + } + } + const T3 *lut0 = lut - OFstatic_cast(T2, absmin); // points to 'zero' entry + q = Data; + for (i = Count; i != 0; --i) // apply LUT + *(q++) = *(lut0 + (*(p++))); + } + if (lut == NULL) // use "normal" transformation + { + if (dlut != NULL) // perform display transformation + { + DCMIMGLE_TRACE("monochrome rendering: VOI SIGMOID #7"); + const double maxvalue = OFstatic_cast(double, dlut->getCount() - 1); + const double outrange2 = (low > high) ? -maxvalue : maxvalue; + const double offset = (low > high) ? maxvalue : 0; + for (i = Count; i != 0; --i) + { + value = OFstatic_cast(double, *(p++)); + *(q++) = OFstatic_cast(T3, dlut->getValue(OFstatic_cast(Uint16, offset + outrange2 / (1 + exp(-4 * (value - center) / width))))); + } + } else { // don't use display: invalid or absent + DCMIMGLE_TRACE("monochrome rendering: VOI SIGMOID #8"); + for (i = Count; i != 0; --i) + { + value = OFstatic_cast(double, *(p++)); + *(q++) = OFstatic_cast(T3, outrange / (1 + exp(-4 * (value - center) / width))); + } + } + } + } + delete[] lut; + if (Count < FrameSize) + OFBitmanipTemplate::zeroMem(Data + Count, FrameSize - Count); // set remaining pixels of frame to zero + } + } else + Data = NULL; + } + + /** apply the currently active linear VOI window to the output data + * + ** @param inter pointer to intermediate pixel representation + * @param start offset of the first pixel to be processed + * @param plut presentation LUT (optional, maybe NULL) + * @param disp display function (optional, maybe NULL) + * @param center window center + * @param width window width (>= 1) + * @param low lowest pixel value for the output data (e.g. 0) + * @param high highest pixel value for the output data (e.g. 255) + */ + void window(const DiMonoPixel *inter, + const Uint32 start, + const DiLookupTable *plut, + DiDisplayFunction *disp, + const double center, + const double width, + const T3 low, + const T3 high) + { + const T1 *pixel = OFstatic_cast(const T1 *, inter->getData()); + if (pixel != NULL) + { + if (Data == NULL) + Data = new T3[FrameSize]; // create new output buffer + if (Data != NULL) + { + DCMIMGLE_DEBUG("applying linear VOI transformation with window center = " << center << ", width = " << width); + const DiDisplayLUT *dlut = NULL; + const double absmin = inter->getAbsMinimum(); + const double width_1 = width - 1; + const double leftBorder = center - 0.5 - width_1 / 2; // window borders, according to supplement 33 + const double rightBorder = center - 0.5 + width_1 / 2; + const double outrange = OFstatic_cast(double, high) - OFstatic_cast(double, low); // output range + const unsigned long ocnt = OFstatic_cast(unsigned long, inter->getAbsMaxRange()); // number of LUT entries + register const T1 *p = pixel + start; + register T3 *q = Data; + register unsigned long i; + register double value; + T3 *lut = NULL; + if ((plut != NULL) && (plut->isValid())) // has presentation LUT + { + DCMIMGLE_DEBUG("applying presentation LUT transformation"); + createDisplayLUT(dlut, disp, plut->getBits()); + register Uint32 value2; // presentation LUT is always unsigned + const Uint32 pcnt = plut->getCount(); + const double plutmax_1 = OFstatic_cast(double, plut->getAbsMaxRange()) - 1; + const double gradient1 = (width_1 == 0) ? 0 : OFstatic_cast(double, pcnt - 1) / width_1; + if (initOptimizationLUT(lut, ocnt)) + { // use LUT for optimization + q = lut; + if (dlut != NULL) // perform display transformation + { + DCMIMGLE_TRACE("monochrome rendering: VOI LINEAR #1"); + const double maxvalue = OFstatic_cast(double, dlut->getCount() - 1); + const double offset = (low > high) ? maxvalue : 0; + const double gradient2 = (low > high) ? (-maxvalue / plutmax_1) : (maxvalue / plutmax_1); + for (i = 0; i < ocnt; ++i) + { + value = OFstatic_cast(double, i) + absmin; // pixel value + if (value <= leftBorder) + value2 = 0; // first LUT index + else if (value > rightBorder) + value2 = pcnt - 1; // last LUT index + else + value2 = OFstatic_cast(Uint32, (value - leftBorder) * gradient1); + *(q++) = OFstatic_cast(T3, dlut->getValue(OFstatic_cast(Uint16, offset + OFstatic_cast(double, plut->getValue(value2)) * gradient2))); + } + } else { // don't use display: invalid or absent + DCMIMGLE_TRACE("monochrome rendering: VOI LINEAR #2"); + const double gradient2 = outrange / plutmax_1; + for (i = 0; i < ocnt; ++i) + { + value = OFstatic_cast(double, i) + absmin; // pixel value + if (value <= leftBorder) + value2 = 0; // first LUT index + else if (value > rightBorder) + value2 = pcnt - 1; // last LUT index + else + value2 = OFstatic_cast(Uint32, (value - leftBorder) * gradient1); + *(q++) = OFstatic_cast(T3, OFstatic_cast(double, low) + OFstatic_cast(double, plut->getValue(value2)) * gradient2); + } + } + const T3 *lut0 = lut - OFstatic_cast(T2, absmin); // points to 'zero' entry + q = Data; + for (i = Count; i != 0; --i) // apply LUT + *(q++) = *(lut0 + (*(p++))); + } + if (lut == NULL) // use "normal" transformation + { + if (dlut != NULL) // perform display transformation + { + DCMIMGLE_TRACE("monochrome rendering: VOI LINEAR #3"); + const double maxvalue = OFstatic_cast(double, dlut->getCount() - 1); + const double offset = (low > high) ? maxvalue : 0; + const double gradient2 = (low > high) ? (-maxvalue / plutmax_1) : (maxvalue / plutmax_1); + for (i = Count; i != 0; --i) + { + value = OFstatic_cast(double, *(p++)); // pixel value + if (value <= leftBorder) + value2 = 0; // first LUT index + else if (value > rightBorder) + value2 = pcnt - 1; // last LUT index + else + value2 = OFstatic_cast(Uint32, (value - leftBorder) * gradient1); + *(q++) = OFstatic_cast(T3, dlut->getValue(OFstatic_cast(Uint16, offset + OFstatic_cast(double, plut->getValue(value2)) * gradient2))); + } + } else { // don't use display: invalid or absent + DCMIMGLE_TRACE("monochrome rendering: VOI LINEAR #4"); + const double gradient2 = outrange / plutmax_1; + for (i = Count; i != 0; --i) + { + value = OFstatic_cast(double, *(p++)); // pixel value + if (value <= leftBorder) + value2 = 0; // first LUT index + else if (value > rightBorder) + value2 = pcnt - 1; // last LUT index + else + value2 = OFstatic_cast(Uint32, (value - leftBorder) * gradient1); + *(q++) = OFstatic_cast(T3, OFstatic_cast(double, low) + OFstatic_cast(double, plut->getValue(value2)) * gradient2); + } + } + } + } else { // has no presentation LUT + createDisplayLUT(dlut, disp, bitsof(T1)); + if (initOptimizationLUT(lut, ocnt)) + { // use LUT for optimization + q = lut; + if (dlut != NULL) // perform display transformation + { + DCMIMGLE_TRACE("monochrome rendering: VOI LINEAR #5"); + const double maxvalue = OFstatic_cast(double, dlut->getCount() - 1); + const double offset = (low > high) ? maxvalue : 0; + const double gradient = (width_1 == 0) ? 0 : ((low > high) ? (-maxvalue / width_1) : (maxvalue / width_1)); + for (i = 0; i < ocnt; ++i) // calculating LUT entries + { + value = OFstatic_cast(double, i) + absmin - leftBorder; + if (value < 0) // left border + value = 0; + else if (value > width_1) // right border + value = width_1; + *(q++) = OFstatic_cast(T3, dlut->getValue(OFstatic_cast(Uint16, offset + value * gradient))); // calculate value + } + } else { // don't use display: invalid or absent + DCMIMGLE_TRACE("monochrome rendering: VOI LINEAR #6"); + const double offset = (width_1 == 0) ? 0 : (high - ((center - 0.5) / width_1 + 0.5) * outrange); + const double gradient = (width_1 == 0) ? 0 : outrange / width_1; + for (i = 0; i < ocnt; ++i) // calculating LUT entries + { + value = OFstatic_cast(double, i) + absmin; + if (value <= leftBorder) + *(q++) = low; // black/white + else if (value > rightBorder) + *(q++) = high; // white/black + else + *(q++) = OFstatic_cast(T3, offset + value * gradient); // gray value + } + } + const T3 *lut0 = lut - OFstatic_cast(T2, absmin); // points to 'zero' entry + q = Data; + for (i = Count; i != 0; --i) // apply LUT + *(q++) = *(lut0 + (*(p++))); + } + if (lut == NULL) // use "normal" transformation + { + if (dlut != NULL) // perform display transformation + { + DCMIMGLE_TRACE("monochrome rendering: VOI LINEAR #7"); + const double maxvalue = OFstatic_cast(double, dlut->getCount() - 1); + const double offset = (low > high) ? maxvalue : 0; + const double gradient = (width_1 == 0) ? 0 : ((low > high) ? (-maxvalue / width_1) : (maxvalue / width_1)); + for (i = Count; i != 0; --i) // calculating LUT entries + { + value = OFstatic_cast(double, *(p++)) - leftBorder; + if (value < 0) // left border + value = 0; + else if (value > width_1) // right border + value = width_1; + *(q++) = OFstatic_cast(T3, dlut->getValue(OFstatic_cast(Uint16, offset + value * gradient))); // calculate value + } + } else { // don't use display: invalid or absent + DCMIMGLE_TRACE("monochrome rendering: VOI LINEAR #8"); + const double offset = (width_1 == 0) ? 0 : (high - ((center - 0.5) / width_1 + 0.5) * outrange); + const double gradient = (width_1 == 0) ? 0 : outrange / width_1; + for (i = Count; i != 0; --i) + { + value = OFstatic_cast(double, *(p++)); + if (value <= leftBorder) + *(q++) = low; // black/white + else if (value > rightBorder) + *(q++) = high; // white/black + else + *(q++) = OFstatic_cast(T3, offset + value * gradient); // gray value + } + } + } + } + delete[] lut; + if (Count < FrameSize) + OFBitmanipTemplate::zeroMem(Data + Count, FrameSize - Count); // set remaining pixels of frame to zero + } + } else + Data = NULL; + } + + + /** apply the currently active overlay planes to the output data + * + ** @param overlays array of overlay management objects + * @param disp display function (optional, maybe NULL) + * @param columns image's width (in pixels) + * @param rows image's height (in pixels) + * @param frame number of frame to be rendered + */ + void overlay(DiOverlay *overlays[2], + DiDisplayFunction *disp, + const Uint16 columns, + const Uint16 rows, + const unsigned long frame) + { + if ((Data != NULL) && (overlays != NULL)) + { + for (unsigned int j = 0; j < 2; ++j) + { + if (overlays[j] != NULL) + { + if (overlays[j]->getCount() > 0) + DCMIMGLE_DEBUG("applying " << ((j == 0) ? "built-in" : "additional") << " overlay planes"); + const signed long left_pos = overlays[j]->getLeft(); + const signed long top_pos = overlays[j]->getTop(); + register DiOverlayPlane *plane; + for (unsigned int i = 0; i < overlays[j]->getCount(); ++i) + { + plane = overlays[j]->getPlane(i); + if ((plane != NULL) && plane->isVisible() && plane->reset(frame)) + { + register T3 *q; + register Uint16 x; + register Uint16 y; + const Uint16 xmin = (plane->getLeft(left_pos) > 0) ? plane->getLeft(left_pos) : 0; + const Uint16 ymin = (plane->getTop(top_pos) > 0) ? plane->getTop(top_pos) : 0; + const Uint16 xmax = (plane->getRight(left_pos) < columns) ? plane->getRight(left_pos) : columns; + const Uint16 ymax = (plane->getBottom(top_pos) < rows) ? plane->getBottom(top_pos) : rows; + const T3 maxvalue = OFstatic_cast(T3, DicomImageClass::maxval(bitsof(T3))); + switch (plane->getMode()) + { + case EMO_Replace: + { + DCMIMGLE_DEBUG("applying overlay plane " << (i + 1) << " with 'replace' mode"); + const T3 fore = OFstatic_cast(T3, plane->getForeground() * maxvalue); + for (y = ymin; y < ymax; ++y) + { + plane->setStart(OFstatic_cast(Uint16, left_pos + xmin), OFstatic_cast(Uint16, top_pos + y)); + q = Data + OFstatic_cast(unsigned long, y) * OFstatic_cast(unsigned long, columns) + OFstatic_cast(unsigned long, xmin); + for (x = xmin; x < xmax; ++x, ++q) + { + if (plane->getNextBit()) + *q = fore; + } + } + break; + } + case EMO_ThresholdReplace: + { + DCMIMGLE_DEBUG("applying overlay plane " << (i + 1) << " with 'threshold replace' mode"); + const T3 fore = OFstatic_cast(T3, plane->getForeground() * maxvalue); + const T3 thresh = OFstatic_cast(T3, plane->getThreshold() * maxvalue); + for (y = ymin; y < ymax; ++y) + { + plane->setStart(OFstatic_cast(Uint16, left_pos + xmin), OFstatic_cast(Uint16, top_pos + y)); + q = Data + OFstatic_cast(unsigned long, y) * OFstatic_cast(unsigned long, columns) + OFstatic_cast(unsigned long, xmin); + for (x = xmin; x < xmax; ++x, ++q) + { + if (plane->getNextBit()) + *q = (*q <= thresh) ? fore : 1; + } + } + break; + } + case EMO_Complement: + { + DCMIMGLE_DEBUG("applying overlay plane " << (i + 1) << " with 'complement' mode"); + const T3 thresh = OFstatic_cast(T3, DicomImageClass::maxval(bitsof(T3) / 2)); + for (y = ymin; y < ymax; ++y) + { + plane->setStart(OFstatic_cast(Uint16, left_pos + xmin), OFstatic_cast(Uint16, top_pos + y)); + q = Data + OFstatic_cast(unsigned long, y) * OFstatic_cast(unsigned long, columns) + OFstatic_cast(unsigned long, xmin); + for (x = xmin; x < xmax; ++x, ++q) + { + if (plane->getNextBit()) + *q = (*q <= thresh) ? maxvalue : 0; + } + } + break; + } + case EMO_InvertBitmap: + { + DCMIMGLE_DEBUG("applying overlay plane " << (i + 1) << " with 'invert bitmap' mode"); + const T3 fore = OFstatic_cast(T3, plane->getForeground() * maxvalue); + for (y = ymin; y < ymax; ++y) + { + plane->setStart(OFstatic_cast(Uint16, left_pos + xmin), OFstatic_cast(Uint16, top_pos + y)); + q = Data + OFstatic_cast(unsigned long, y) * OFstatic_cast(unsigned long, columns) + OFstatic_cast(unsigned long, xmin); + for (x = xmin; x < xmax; ++x, ++q) + { + if (!plane->getNextBit()) + *q = fore; + } + } + break; + } + case EMO_RegionOfInterest: + { + DCMIMGLE_DEBUG("applying overlay plane " << (i + 1) << " with 'region of interest' mode"); + const int dim = bitsof(T3) / 2; + for (y = ymin; y < ymax; ++y) + { + plane->setStart(OFstatic_cast(Uint16, left_pos + xmin), OFstatic_cast(Uint16, top_pos + y)); + q = Data + OFstatic_cast(unsigned long, y) * OFstatic_cast(unsigned long, columns) + OFstatic_cast(unsigned long, xmin); + for (x = xmin; x < xmax; ++x, ++q) + { + if (!plane->getNextBit()) + *q = *q >> dim; + } + } + break; + } + case EMO_BitmapShutter: + { + DCMIMGLE_DEBUG("applying overlay plane " << (i + 1) << " with 'bitmap shutter' mode"); + register T3 fore = OFstatic_cast(T3, OFstatic_cast(double, maxvalue) * OFstatic_cast(double, plane->getPValue()) / OFstatic_cast(double, DicomImageClass::maxval(WIDTH_OF_PVALUES))); + if ((disp != NULL) && (disp->isValid())) + { + const DiDisplayLUT *dlut = disp->getLookupTable(WIDTH_OF_PVALUES); + if ((dlut != NULL) && (dlut->isValid())) + fore = OFstatic_cast(T3, dlut->getValue(plane->getPValue())); + } + for (y = ymin; y < ymax; ++y) + { + plane->setStart(OFstatic_cast(Uint16, left_pos + xmin), OFstatic_cast(Uint16, top_pos + y)); + q = Data + OFstatic_cast(unsigned long, y) * OFstatic_cast(unsigned long, columns) + OFstatic_cast(unsigned long, xmin); + for (x = xmin; x < xmax; ++x, ++q) + { + if (plane->getNextBit()) + *q = fore; + } + } + break; + } + default: /* e.g. EMO_Default */ + DCMIMGLE_WARN("unhandled overlay mode (" << OFstatic_cast(int, plane->getMode()) << ")"); + } + } + } + } + } + } + } + + + /// pointer to the storage area where the output data should be stored + T3 *Data; + /// flag indicating whether the output data buffer should be deleted in the destructor + int DeleteData; + +#ifdef PASTEL_COLOR_OUTPUT + DiMonoColorOutputPixelTemplate *ColorData; +#else + // dummy variable + DiMonoOutputPixel *ColorData; +#endif + + // --- declarations to avoid compiler warnings + + DiMonoOutputPixelTemplate(const DiMonoOutputPixelTemplate &); + DiMonoOutputPixelTemplate &operator=(const DiMonoOutputPixelTemplate &); +}; + + +#endif diff --git a/dcmimgle/include/dcmtk/dcmimgle/dimopx.h b/dcmimgle/include/dcmtk/dcmimgle/dimopx.h new file mode 100644 index 00000000..a2ca5fc7 --- /dev/null +++ b/dcmimgle/include/dcmtk/dcmimgle/dimopx.h @@ -0,0 +1,242 @@ +/* + * + * Copyright (C) 1996-2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimgle + * + * Author: Joerg Riesmeier + * + * Purpose: DicomMonochromePixel (Header) + * + */ + + +#ifndef DIMOPX_H +#define DIMOPX_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/ofstd/ofcast.h" + +#include "dcmtk/dcmimgle/dipixel.h" +#include "dcmtk/dcmimgle/dimomod.h" + + +/*------------------------* + * forward declarations * + *------------------------*/ + +class DiInputPixel; +class DiMonoOutputPixel; + + +/*---------------------* + * class declaration * + *---------------------*/ + +/** Abstract base class to handle monochrome pixel data + */ +class DCMTK_DCMIMGLE_EXPORT DiMonoPixel + : public DiPixel +{ + + public: + + /** constructor + * + ** @param count number of pixels + */ + DiMonoPixel(const unsigned long count); + + /** constructor + * + ** @param pixel pointer to input pixel data + * @param modality pointer to object managing modality transform + */ + DiMonoPixel(const DiInputPixel *pixel, + DiMonoModality *modality); + + /** constructor + * + ** @param pixel pointer to output pixel data used for intermediate representation + * @param modality pointer to object managing modality transform + */ + DiMonoPixel(DiMonoOutputPixel *pixel, + DiMonoModality *modality); + + /** destructor + */ + virtual ~DiMonoPixel(); + + /** get number of planes + * + ** @return number of planes (here 1, monochrome) + */ + inline int getPlanes() const + { + return 1; + } + + /** get minimum and maximum pixel values (abstract) + * + ** @param min reference to storage area for minimum pixel value + * @param max reference to storage area for maximum pixel value + * + ** @return status, true if successful, false otherwise + */ + virtual int getMinMaxValues(double &min, + double &max) const = 0; + + /** get automatically computed min-max window (abstract) + * + ** @param idx ignore global min/max pixel values if > 0 + * @param center reference to storage area for window center value + * @param width reference to storage area for window width value + * + ** @return status, true if successful, false otherwise + */ + virtual int getMinMaxWindow(const int idx, + double ¢er, + double &width) = 0; + + /** get automatically computed Region of Interest (ROI) window (abstract) + * + ** @param left_pos x-coordinate of the top left-hand corner of the ROI (starting from 0) + * @param top_pos y-coordinate of the top left-hand corner of the ROI (starting from 0) + * @param width width in pixels of the rectangular ROI (minimum: 1) + * @param height height in pixels of the rectangular ROI (minimum: 1) + * @param columns number of columns (width) of the associated image + * @param rows number of rows (height) of the associated image + * @param frame index of the frame to be used for the calculation + * @param voiCenter reference to storage area for window center value + * @param voiWidth reference to storage area for window width value + * + ** @return status, true if successful, false otherwise + */ + virtual int getRoiWindow(const unsigned long left_pos, + const unsigned long top_pos, + const unsigned long width, + const unsigned long height, + const unsigned long columns, + const unsigned long rows, + const unsigned long frame, + double &voiCenter, + double &voiWidth) = 0; + + /** get automatically computed histogram window (abstract) + * + ** @param thresh ignore certain percentage of pixels at lower and upper boundaries + * @param center reference to storage area for window center value + * @param width reference to storage area for window width value + * + ** @return status, true if successful, false otherwise + */ + virtual int getHistogramWindow(const double thresh, + double ¢er, + double &width) = 0; + + /** get number of bits per pixel + * + ** @return number of bits + */ + inline unsigned int getBits() const + { + return (Modality != NULL) ? Modality->getBits() : 0; + } + + /** get absolute minimum pixel value. + * The result depends on former transforms. + * + ** @return absolute minimum value + */ + inline double getAbsMinimum() const + { + return (Modality != NULL) ? Modality->getAbsMinimum() : 0; + } + + /** get absolute maximum pixel value. + * The result depends on former transforms. + * + ** @return absolute maximum value + */ + inline double getAbsMaximum() const + { + return (Modality != NULL) ? Modality->getAbsMaximum() : 0; + } + + /** get absolute pixel range + * + ** @return absolute pixel range + */ + inline double getAbsMaxRange() const + { + return getAbsMaximum() - getAbsMinimum() + 1; + } + + /** get modality LUT explanation string + * + ** @return modality LUT explanation + */ + inline const char *getModalityLutExplanation() const + { + return (Modality != NULL) ? Modality->getExplanation() : OFstatic_cast(const char *, NULL); + } + + /** add a reference to the internally managed modality transform object + * + ** @return pointer to modality transform object (might be NULL) + */ + DiMonoModality *addReferenceToModality(); + + /** check whether pixel data is 'potentially' signed. + * This check is necessary to interpret possibly following LUT descriptors correctly + * (see supplement 33) + * + ** @return true if pixel data is potentially signed, false otherwise + */ + inline int isPotentiallySigned() const + { + return (getAbsMinimum() < 0); + } + + + protected: + + /** constructor + * + ** @param pixel pointer to intermediate pixel data (not necessarily monochrome) + * @param modality pointer to object managing modality transform + */ + DiMonoPixel(const DiPixel *pixel, + DiMonoModality *modality); + + /** constructor + * + ** @param pixel pointer to intermediate monochrome pixel data + * @param count number of pixels + */ + DiMonoPixel(const DiMonoPixel *pixel, + const unsigned long count); + + /// pointer to modality transform object + DiMonoModality *Modality; + + + private: + + // --- declarations to avoid compiler warnings + + DiMonoPixel(const DiMonoPixel &); + DiMonoPixel &operator=(const DiMonoPixel &); +}; + + +#endif diff --git a/dcmimgle/include/dcmtk/dcmimgle/dimopxt.h b/dcmimgle/include/dcmtk/dcmimgle/dimopxt.h new file mode 100644 index 00000000..d4da5351 --- /dev/null +++ b/dcmimgle/include/dcmtk/dcmimgle/dimopxt.h @@ -0,0 +1,437 @@ +/* + * + * Copyright (C) 1996-2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimgle + * + * Author: Joerg Riesmeier + * + * Purpose: DicomMonochromePixelTemplate (Header) + * + */ + + +#ifndef DIMOPXT_H +#define DIMOPXT_H + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/ofstd/ofbmanip.h" +#include "dcmtk/ofstd/ofcast.h" + +#include "dcmtk/dcmimgle/dipxrept.h" +#include "dcmtk/dcmimgle/dimopx.h" +#include "dcmtk/dcmimgle/dimoopx.h" + + +/*---------------------* + * class declaration * + *---------------------*/ + +/** Template class to handle monochrome pixel data + */ +template +class DiMonoPixelTemplate + : public DiMonoPixel, + public DiPixelRepresentationTemplate +{ + + public: + + /** constructor + * + ** @param count number of pixels + */ + DiMonoPixelTemplate(const unsigned long count) + : DiMonoPixel(count), + Data(NULL) + { + MinValue[0] = 0; + MinValue[1] = 0; + MaxValue[0] = 0; + MaxValue[1] = 0; + // allocate buffer of given size +#ifdef HAVE_STD__NOTHROW + /* use a non-throwing new here (if available) because the allocated buffer can be huge */ + Data = new (std::nothrow) T[Count]; +#else + /* make sure that the pointer is set to NULL in case of error */ + try + { + Data = new T[Count]; + } + catch (STD_NAMESPACE bad_alloc const &) + { + Data = NULL; + } +#endif + if (Data == NULL) + DCMIMGLE_DEBUG("cannot allocate memory buffer for 'Data' in DiMonoPixelTemplate constructor"); + } + + /** constructor + * + ** @param pixel pointer to input pixel data + * @param modality pointer to object managing modality transform + */ + DiMonoPixelTemplate(const DiInputPixel *pixel, + DiMonoModality *modality) + : DiMonoPixel(pixel, modality), + Data(NULL) + { + MinValue[0] = 0; + MinValue[1] = 0; + MaxValue[0] = 0; + MaxValue[1] = 0; + } + + /** constructor + * + ** @param pixel pointer to output pixel data used for intermediate representation + * @param modality pointer to object managing modality transform + */ + DiMonoPixelTemplate(DiMonoOutputPixel *pixel, + DiMonoModality *modality) + : DiMonoPixel(pixel, modality), + Data(OFstatic_cast(T *, pixel->getDataPtr())) + { + MinValue[0] = 0; + MinValue[1] = 0; + MaxValue[0] = 0; + MaxValue[1] = 0; + } + + /** destructor + */ + virtual ~DiMonoPixelTemplate() + { +#if defined(HAVE_STD__NOTHROW) && defined(HAVE_NOTHROW_DELETE) + /* use a non-throwing delete (if available) */ + operator delete[] (Data, std::nothrow); +#else + delete[] Data; +#endif + } + + /** get integer representation + * + ** @return integer representation of the internally stored pixel data + */ + inline EP_Representation getRepresentation() const + { + return DiPixelRepresentationTemplate::getRepresentation(); + } + + /** get pointer to internal pixel data + * + ** @return pointer to pixel data + */ + inline const void *getData() const + { + return OFstatic_cast(const void *, Data); + } + + /** get pointer to internal pixel data + * + ** @return pointer to pixel data + */ + inline void *getDataPtr() + { + return OFstatic_cast(void *, Data); + } + + /** get reference to pointer to internal pixel data. + * The returned array points to the (single) image plane. The behaviour of + * this method is, therefore, identical for both monochrome and color images. + * + ** @return reference to pointer to pixel data + */ + inline void *getDataArrayPtr() + { + return OFstatic_cast(void *, &Data); + } + + /** get minimum and maximum pixel values + * + ** @param min reference to storage area for minimum pixel value + * @param max reference to storage area for maximum pixel value + * + ** @return status, true if successful, false otherwise + */ + inline int getMinMaxValues(double &min, + double &max) const + { + min = MinValue[0]; + max = MaxValue[0]; + return 1; + } + + /** get automatically computed min-max window + * + ** @param idx ignore global min/max pixel values if > 0 + * @param center reference to storage area for window center value + * @param width reference to storage area for window width value + * + ** @return status, true if successful, false otherwise + */ + inline int getMinMaxWindow(const int idx, + double ¢er, + double &width) + { + int result = 0; + if ((idx >= 0) && (idx <= 1)) + { + if ((idx == 1) && (MinValue[1] == 0) && (MaxValue[1] == 0)) + determineMinMax(0, 0, 0x2); // determine on demand + /* suppl. 33: "A Window Center of 2^n-1 and a Window Width of 2^n + selects the range of input values from 0 to 2^n-1." + */ + center = (OFstatic_cast(double, MinValue[idx]) + OFstatic_cast(double, MaxValue[idx]) + 1) / 2; // type cast to avoid overflows ! + width = OFstatic_cast(double, MaxValue[idx]) - OFstatic_cast(double, MinValue[idx]) + 1; + result = (width > 0); // check for valid value + } + return result; + } + + /** get automatically computed Region of Interest (ROI) window + * + ** @param left_pos x-coordinate of the top left-hand corner of the ROI (starting from 0) + * @param top_pos y-coordinate of the top left-hand corner of the ROI (starting from 0) + * @param width width in pixels of the rectangular ROI (minimum: 1) + * @param height height in pixels of the rectangular ROI (minimum: 1) + * @param columns number of columns (width) of the associated image + * @param rows number of rows (height) of the associated image + * @param frame index of the frame to be used for the calculation + * @param voiCenter reference to storage area for window center value + * @param voiWidth reference to storage area for window width value + * + ** @return status, true if successful, false otherwise + */ + virtual int getRoiWindow(const unsigned long left_pos, + const unsigned long top_pos, + const unsigned long width, + const unsigned long height, + const unsigned long columns, + const unsigned long rows, + const unsigned long frame, + double &voiCenter, + double &voiWidth) + { + int result = 0; + if ((Data != NULL) && (left_pos < columns) && (top_pos < rows)) + { + register T *p = Data + (columns * rows * frame) + (top_pos * columns) + left_pos; + const unsigned long right_pos = (left_pos + width < columns) ? left_pos + width : columns; + const unsigned long bottom = (top_pos + height < rows) ? top_pos + height : rows; + const unsigned long skip_x = left_pos + (columns - right_pos); + register unsigned long x; + register unsigned long y; + register T value = 0; + register T min = *p; // get first pixel as initial value for min ... + register T max = min; // ... and max + for (y = top_pos; y < bottom; ++y) + { + for (x = left_pos; x < right_pos; ++x) + { + value = *(p++); + if (value < min) + min = value; + else if (value > max) + max = value; + } + p += skip_x; // skip rest of current line and beginning of next + } + /* suppl. 33: "A Window Center of 2^n-1 and a Window Width of 2^n + selects the range of input values from 0 to 2^n-1." + */ + voiCenter = (OFstatic_cast(double, min) + OFstatic_cast(double, max) + 1) / 2; // type cast to avoid overflows ! + voiWidth = OFstatic_cast(double, max) - OFstatic_cast(double, min) + 1; + result = (width > 0); // check for valid value + } + return result; + } + + /** get automatically computed histogram window + * + ** @param thresh ignore certain percentage of pixels at lower and upper boundaries + * @param center reference to storage area for window center value + * @param width reference to storage area for window width value + * + ** @return status, true if successful, false otherwise + */ + int getHistogramWindow(const double thresh, // could be optimized if necessary (see diinpxt.h)! + double ¢er, + double &width) + { + if ((Data != NULL) && (MinValue[0] < MaxValue[0])) + { + const Uint32 count = OFstatic_cast(Uint32, MaxValue[0] - MinValue[0] + 1); + Uint32 *quant = new Uint32[count]; + if (quant != NULL) + { + register unsigned long i; + OFBitmanipTemplate::zeroMem(quant, count); // initialize array + for (i = 0; i < Count; ++i) + { + if ((Data[i] >= MinValue[0]) && (Data[i] <= MaxValue[0])) // only for stability ! + ++quant[OFstatic_cast(Uint32, Data[i] - MinValue[0])]; // count values +#ifdef DEBUG + else + DCMIMGLE_WARN("invalid value (" << Data[i] << ") in DiMonoPixelTemplate::getHistogramWindow()"); +#endif + } + const Uint32 threshvalue = OFstatic_cast(Uint32, thresh * OFstatic_cast(double, Count)); + register Uint32 t = 0; + i = 0; + while ((i < count) && (t < threshvalue)) + t += quant[i++]; + const T minvalue = (i < count) ? OFstatic_cast(T, MinValue[0] + i) : 0; + t = 0; + i = count; + while ((i > 0) && (t < threshvalue)) + t += quant[--i]; + const T maxvalue = (i > 0) ? OFstatic_cast(T, MinValue[0] + i) : 0; + delete[] quant; + if (minvalue < maxvalue) + { + /* suppl. 33: "A Window Center of 2^n-1 and a Window Width of 2^n + selects the range of input values from 0 to 2^n-1." + */ + center = (OFstatic_cast(double, minvalue) + OFstatic_cast(double, maxvalue) + 1) / 2; + width = OFstatic_cast(double, maxvalue) - OFstatic_cast(double, minvalue) + 1; + return (width > 0); + } + } + } + return 0; + } + + + protected: + + /** constructor + * + ** @param pixel pointer to intermediate pixel data (not necessarily monochrome) + * @param modality pointer to object managing modality transform + */ + DiMonoPixelTemplate(const DiPixel *pixel, + DiMonoModality *modality) + : DiMonoPixel(pixel, modality), + Data(NULL) + { + MinValue[0] = 0; + MinValue[1] = 0; + MaxValue[0] = 0; + MaxValue[1] = 0; + } + + /** constructor + * + ** @param pixel pointer to intermediate monochrome pixel data + * @param count number of pixels + */ + DiMonoPixelTemplate(const DiMonoPixel *pixel, + const unsigned long count) + : DiMonoPixel(pixel, count), + Data(NULL) + { + MinValue[0] = 0; + MinValue[1] = 0; + MaxValue[0] = 0; + MaxValue[1] = 0; + } + + /** determine minimum and maximum pixel values + * + ** @param minvalue starting global minimum value (0 = invalid) + * @param maxvalue starting global maximum value (0 = invalid) + * @param mode calculate global min/max if 0x1 bit is set (default), + * calculate next min/max if 0x2 bit is set + */ + void determineMinMax(T minvalue = 0, + T maxvalue = 0, + const int mode = 0x1) + { + if (Data != NULL) + { + if (mode & 0x1) + { + if ((minvalue == 0) && (maxvalue == 0)) + { + DCMIMGLE_DEBUG("determining global minimum and maximum pixel values for monochrome image"); + register T *p = Data; + register T value = *p; + register unsigned long i; + minvalue = value; + maxvalue = value; + for (i = Count; i > 1; --i) // could be optimized if necessary (see diinpxt.h) ! + { + value = *(++p); + if (value < minvalue) + minvalue = value; + else if (value > maxvalue) + maxvalue = value; + } + } + MinValue[0] = minvalue; // global minimum + MaxValue[0] = maxvalue; // global maximum + MinValue[1] = 0; // invalidate value + MaxValue[1] = 0; + } else { + minvalue = MinValue[0]; + maxvalue = MaxValue[0]; + } + if (mode & 0x2) + { + DCMIMGLE_DEBUG("determining next minimum and maximum pixel values for monochrome image"); + register T *p = Data; + register T value; + register int firstmin = 1; + register int firstmax = 1; + register unsigned long i; + for (i = Count; i != 0; --i) // could be optimized if necessary (see diinpxt.h) ! + { + value = *(p++); + if ((value > minvalue) && ((value < MinValue[1]) || firstmin)) + { + MinValue[1] = value; + firstmin = 0; + } + if ((value < maxvalue) && ((value > MaxValue[1]) || firstmax)) + { + MaxValue[1] = value; + firstmax = 0; + } + } + } + } + } + + /// pointer to pixel data + T *Data; + + + private: + + /// minimum pixel values (0 = global, 1 = ignoring global) + T MinValue[2]; + /// maximum pixel values + T MaxValue[2]; + + // --- declarations to avoid compiler warnings + + DiMonoPixelTemplate(const DiMonoPixelTemplate &); + DiMonoPixelTemplate &operator=(const DiMonoPixelTemplate &); +}; + + +#endif diff --git a/dcmimgle/include/dcmtk/dcmimgle/dimorot.h b/dcmimgle/include/dcmtk/dcmimgle/dimorot.h new file mode 100644 index 00000000..c4969569 --- /dev/null +++ b/dcmimgle/include/dcmtk/dcmimgle/dimorot.h @@ -0,0 +1,112 @@ +/* + * + * Copyright (C) 1996-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimgle + * + * Author: Joerg Riesmeier + * + * Purpose: DicomMonochromeRotateTemplate (Header) + * + */ + + +#ifndef DIMOROT_H +#define DIMOROT_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/ofstd/ofcast.h" + +#include "dcmtk/dcmimgle/dimopxt.h" +#include "dcmtk/dcmimgle/dirotat.h" + + +/*---------------------* + * class declaration * + *---------------------*/ + +/** Template class to rotate monochrome images (on pixel data level). + * by steps of 90 degrees + */ +template +class DiMonoRotateTemplate + : public DiMonoPixelTemplate, + protected DiRotateTemplate +{ + + public: + + /** constructor + * + ** @param pixel pointer to intermediate pixel representation + * @param src_cols width of clipping area + * @param src_rows height of clipping area + * @param dest_cols width of destination image (scaled image) + * @param dest_rows height of destination image + * @param frames number of frames + * @param degree angle by which the pixel data should be rotated + */ + DiMonoRotateTemplate(const DiMonoPixel *pixel, + const Uint16 src_cols, + const Uint16 src_rows, + const Uint16 dest_cols, + const Uint16 dest_rows, + const Uint32 frames, + const int degree) + : DiMonoPixelTemplate(pixel, OFstatic_cast(unsigned long, dest_cols) * OFstatic_cast(unsigned long, dest_rows) * frames), + DiRotateTemplate(1, src_cols, src_rows, dest_cols, dest_rows, frames) + { + if ((pixel != NULL) && (pixel->getCount() > 0)) + { + if (pixel->getCount() == OFstatic_cast(unsigned long, src_cols) * OFstatic_cast(unsigned long, src_rows) * frames) + rotate(OFstatic_cast(const T *, pixel->getData()), degree); + else { + DCMIMGLE_WARN("could not rotate image ... corrupted data"); + } + } + } + + /** destructor + */ + ~DiMonoRotateTemplate() + { + } + + + private: + + /** rotate pixel data + * + ** @param pixel pointer to pixel data to be rotated + * @param degree angle by which the pixel data should be rotated + */ + inline void rotate(const T *pixel, + const int degree) + { + if (pixel != NULL) + { + this->Data = new T[DiMonoPixelTemplate::getCount()]; + if (this->Data != NULL) + { + if (degree == 90) + this->rotateRight(&pixel, &(this->Data)); + else if (degree == 180) + this->rotateTopDown(&pixel, &(this->Data)); + else if (degree == 270) + this->rotateLeft(&pixel, &(this->Data)); + } + } + } +}; + + +#endif diff --git a/dcmimgle/include/dcmtk/dcmimgle/dimosct.h b/dcmimgle/include/dcmtk/dcmimgle/dimosct.h new file mode 100644 index 00000000..a437b818 --- /dev/null +++ b/dcmimgle/include/dcmtk/dcmimgle/dimosct.h @@ -0,0 +1,127 @@ +/* + * + * Copyright (C) 1996-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimgle + * + * Author: Joerg Riesmeier + * + * Purpose: DicomMonochromeScaleTemplate (Header) + * + */ + + +#ifndef DIMOSCT_H +#define DIMOSCT_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/ofstd/ofcast.h" + +#include "dcmtk/dcmimgle/dimopxt.h" +#include "dcmtk/dcmimgle/discalet.h" +#include "dcmtk/dcmimgle/didispfn.h" + + +/*---------------------* + * class declaration * + *---------------------*/ + +/** Template class to scale monochrome images (on pixel data level). + */ +template +class DiMonoScaleTemplate + : public DiMonoPixelTemplate, + protected DiScaleTemplate +{ + + public: + + /** constructor + * + ** @param pixel pointer to intermediate pixel representation + * @param columns width of source image + * @param rows height of source image + * @param left_pos left coordinate of clipping area + * @param top_pos top coordinate of clipping area + * @param src_cols width of clipping area + * @param src_rows height of clipping area + * @param dest_cols width of destination image (scaled image) + * @param dest_rows height of destination image + * @param frames number of frames + * @param bits number of bits per plane/pixel + * @param interpolate use of interpolation when scaling + * @param pvalue value possibly used for regions outside the image boundaries + */ + DiMonoScaleTemplate(const DiMonoPixel *pixel, + const Uint16 columns, + const Uint16 rows, + const signed long left_pos, + const signed long top_pos, + const Uint16 src_cols, + const Uint16 src_rows, + const Uint16 dest_cols, + const Uint16 dest_rows, + const Uint32 frames, + const int bits, + const int interpolate, + const Uint16 pvalue) + : DiMonoPixelTemplate(pixel, OFstatic_cast(unsigned long, dest_cols) * OFstatic_cast(unsigned long, dest_rows) * frames), + DiScaleTemplate(1, columns, rows, left_pos, top_pos, src_cols, src_rows, dest_cols, dest_rows, frames, bits) + { + if ((pixel != NULL) && (pixel->getCount() > 0)) + { + if (pixel->getCount() == OFstatic_cast(unsigned long, columns) * OFstatic_cast(unsigned long, rows) * frames) + { + scale(OFstatic_cast(const T *, pixel->getData()), pixel->getBits(), interpolate, pvalue); + this->determineMinMax(); + } else { + DCMIMGLE_WARN("could not scale image ... corrupted data"); + } + } + } + + /** destructor + */ + virtual ~DiMonoScaleTemplate() + { + } + + + private: + + /** scale pixel data + * + ** @param pixel pointer to pixel data to be scaled + * @param bits bit depth of pixel data + * @param interpolate use of interpolation when scaling + * @param pvalue value possibly used for regions outside the image boundaries + */ + inline void scale(const T *pixel, + const unsigned int bits, + const int interpolate, + const Uint16 pvalue) + { + if (pixel != NULL) + { + this->Data = new T[this->getCount()]; + if (this->Data != NULL) + { + const T value = OFstatic_cast(T, OFstatic_cast(double, DicomImageClass::maxval(bits)) * + OFstatic_cast(double, pvalue) / OFstatic_cast(double, DicomImageClass::maxval(WIDTH_OF_PVALUES))); + this->scaleData(&pixel, &this->Data, interpolate, value); + } + } + } +}; + + +#endif diff --git a/dcmimgle/include/dcmtk/dcmimgle/diobjcou.h b/dcmimgle/include/dcmtk/dcmimgle/diobjcou.h new file mode 100644 index 00000000..f9e15425 --- /dev/null +++ b/dcmimgle/include/dcmtk/dcmimgle/diobjcou.h @@ -0,0 +1,117 @@ +/* + * + * Copyright (C) 1996-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimgle + * + * Author: Joerg Riesmeier + * + * Purpose: DicomObjectCounter (Header) + * + */ + + +#ifndef DIOBJCOU_H +#define DIOBJCOU_H + +#include "dcmtk/config/osconfig.h" + +#ifdef WITH_THREADS +#include "dcmtk/ofstd/ofthread.h" +#endif + +#include "dcmtk/dcmimgle/didefine.h" + + +/*---------------------* + * class declaration * + *---------------------*/ + +/** Class to count number of instances (objects created from a certain class). + * used to manage more than one reference to an object in a secure way. + */ +class DCMTK_DCMIMGLE_EXPORT DiObjectCounter +{ + + public: + + /** add a reference. + * Increase the internal counter by 1. + */ + inline void addReference() + { +#ifdef WITH_THREADS + theMutex.lock(); +#endif + ++Counter; +#ifdef WITH_THREADS + theMutex.unlock(); +#endif + } + + /** remove a reference. + * Decrease the internal counter by 1 and delete the object only if the counter is zero. + */ + inline void removeReference() + { +#ifdef WITH_THREADS + theMutex.lock(); +#endif + if (--Counter == 0) + { +#ifdef WITH_THREADS + theMutex.unlock(); +#endif + delete this; +#ifdef WITH_THREADS + } else { + theMutex.unlock(); +#endif + } + } + + + protected: + + /** constructor. + * Internal counter is initialized with 1. + */ + DiObjectCounter() + : Counter(1) +#ifdef WITH_THREADS + ,theMutex() +#endif + { + } + + /** destructor + */ + virtual ~DiObjectCounter() + { + } + + + private: + + /// internal counter + unsigned long Counter; + +#ifdef WITH_THREADS + /** if compiled for multi-thread operation, the Mutex protecting + * access to the value of this object. + */ + OFMutex theMutex; +#endif +}; + + +#endif diff --git a/dcmimgle/include/dcmtk/dcmimgle/diovdat.h b/dcmimgle/include/dcmtk/dcmimgle/diovdat.h new file mode 100644 index 00000000..3b884c93 --- /dev/null +++ b/dcmimgle/include/dcmtk/dcmimgle/diovdat.h @@ -0,0 +1,85 @@ +/* + * + * Copyright (C) 1996-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimgle + * + * Author: Joerg Riesmeier + * + * Purpose: DicomOverlayData (Header) + * + */ + + +#ifndef DIOVDAT_H +#define DIOVDAT_H + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/dcmimgle/diobjcou.h" + + +/*------------------------* + * forward declarations * + *------------------------*/ + +class DiOverlay; +class DiOverlayPlane; + + +/*-------------------------------* + * declaration of helper class * + *-------------------------------*/ + +/** Class to handle overlay pixel data + */ +class DCMTK_DCMIMGLE_EXPORT DiOverlayData + : public DiObjectCounter +{ + + friend class DiOverlay; + + public: + + /** constructor + * + ** @param entries number of array entries + * @param count number of valid overlay planes + */ + DiOverlayData(unsigned int entries, + unsigned int count = 0); + + /** destructor + */ + virtual ~DiOverlayData(); + + + private: + + /// number of (valid) overlay planes + unsigned int Count; + /// number of array entries (allocated memory) + unsigned int ArrayEntries; + + /// pointer to an array of planes + DiOverlayPlane **Planes; + /// pointer to overlay data (if scaled, flipped or rotated) + Uint16 *DataBuffer; + + // --- declarations to avoid compiler warnings + + DiOverlayData(const DiOverlayData &); + DiOverlayData &operator=(const DiOverlayData &); +}; + + +#endif diff --git a/dcmimgle/include/dcmtk/dcmimgle/diovlay.h b/dcmimgle/include/dcmtk/dcmimgle/diovlay.h new file mode 100644 index 00000000..e0f9c2bb --- /dev/null +++ b/dcmimgle/include/dcmtk/dcmimgle/diovlay.h @@ -0,0 +1,477 @@ +/* + * + * Copyright (C) 1996-2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimgle + * + * Author: Joerg Riesmeier + * + * Purpose: DicomOverlay (Header) + * + */ + + +#ifndef DIOVLAY_H +#define DIOVLAY_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/ofstd/ofcast.h" + +#include "dcmtk/dcmimgle/diobjcou.h" +#include "dcmtk/dcmimgle/diovdat.h" +#include "dcmtk/dcmimgle/diovpln.h" +#include "dcmtk/dcmimgle/diutils.h" + + +/*------------------------* + * forward declarations * + *------------------------*/ + +class DiDocument; + +class DcmOverlayData; +class DcmLongString; + + +/*---------------------* + * class declaration * + *---------------------*/ + +/** Class to handle a set of overlay planes + */ +class DCMTK_DCMIMGLE_EXPORT DiOverlay + : public DiObjectCounter +{ + + public: + + /** constructor + * + ** @param docu pointer to dataset (encapsulated) + * @param alloc bits allocated for image pixel data + * @param stored bits stored for image pixel data + * @param high high bit for image pixel data + */ + DiOverlay(const DiDocument *docu = NULL, + const Uint16 alloc = 0, + const Uint16 stored = 0, + const Uint16 high = 0); + + /** constructor, clip/scale + * + ** @param overlay pointer to reference overlay object + * @param left_pos x-coordinate of new overlay origin (offset for all planes) + * @param top_pos y-coordinate of new overlay origin (offset for all planes) + * @param xfactor scaling factor in x-direction + * @param yfactor scaling factor in y-direction + */ + DiOverlay(const DiOverlay *overlay, + const signed long left_pos, + const signed long top_pos, + const double xfactor, + const double yfactor); + + /** constructor, flip + * + ** @param overlay pointer to reference overlay object + * @param horz flip horizontally if true + * @param vert flip vertically if true + * @param columns width of the surrounding image + * @param rows height of the surrounding image + */ + DiOverlay(const DiOverlay *overlay, + const int horz, + const int vert, + const Uint16 columns, + const Uint16 rows); + + /** constructor, rotate + * + ** @param overlay pointer to reference overlay object + * @param degree angle by which the overlay planes should be rotated + * @param columns width of the surrounding image + * @param rows height of the surrounding image + */ + DiOverlay(const DiOverlay *overlay, + const int degree, + const Uint16 columns, + const Uint16 rows); + + /** destructor + */ + virtual ~DiOverlay(); + + /** check whether specified plane is currently visible (not hidden) + * + ** @param plane index of plane (starting from 0) or group number (0x6000-0x60ff) + * + ** @return true if plane is visible, false otherwise + */ + int isPlaneVisible(unsigned int plane); + + /** make specified plane visible + * + ** @param plane index of plane (starting from 0) or group number (0x6000-0x60ff) + * + ** @return status, true if successful, false otherwise + */ + int showPlane(unsigned int plane); + + /** make specified plane visible and set parameters + * + ** @param plane index of plane (starting from 0) or group number (0x6000-0x60ff) + * @param fore foreground color for overlay plane (in percent: 0.0-1.0) + * @param thresh threshold value for overlay plane (0.0-1.0) + * @param mode new overlay mode (EMO_Default for stored mode) + * + ** @return status, true if successful, false otherwise + */ + int showPlane(unsigned int plane, + const double fore, + const double thresh, + const EM_Overlay mode); + + /** make specified plane visible and set p-value. + * Only applicable for bitmap shutters. + * + ** @param plane index of plane (starting from 0) or group number (0x6000-0x60ff) + * @param pvalue p-value to be used for the overlay plane (0..65535) + * + ** @return status, true if successful, false otherwise + */ + int showPlane(unsigned int plane, + const Uint16 pvalue); + + /** make all planes visible + * + ** @return status, true if successful, false otherwise + */ + int showAllPlanes(); + + /** make all planes visible + * + ** @param fore foreground color for overlay planes (in percent: 0.0-1.0) + * @param thresh threshold value for overlay planes (in percent: 0.0-1.0) + * @param mode new overlay mode (EMO_Default for stored mode) + * + ** @return status, true if successful, false otherwise + */ + int showAllPlanes(const double fore, + const double thresh, + const EM_Overlay mode); + + /** make specified plane invisible + * + ** @param plane index of plane (starting from 0) or group number (0x6000-0x60ff) + * + ** @return status, true if successful, false otherwise + */ + int hidePlane(unsigned int plane); + + /** make all planes invisible + * + ** @return status, true if successful, false otherwise + */ + int hideAllPlanes(); + + /** move plane to a new place + * + ** @param plane index of plane (starting from 0) or group number (0x6000-0x60ff) + * @param left_pos new x-coordinate of the overlay plane origin + * @param top_pos new y-coordinate of the overlay plane origin + * + ** @return status, true if successful, false otherwise + */ + int placePlane(unsigned int plane, + const signed int left_pos, + const signed int top_pos); + + /** get group number of specified plane + * + ** @param plane index of plane (starting from 0) or group number (0x6000-0x60ff) + * + ** @return group number (0x6000-0x60ff) if successful, 0 otherwise + */ + unsigned int getPlaneGroupNumber(unsigned int plane) const; + + /** get label of specified plane + * + ** @param plane index of plane (starting from 0) or group number (0x6000-0x60ff) + * + ** @return plane label if successful, NULL otherwise + */ + const char *getPlaneLabel(unsigned int plane) const; + + /** get description of specified plane + * + ** @param plane index of plane (starting from 0) or group number (0x6000-0x60ff) + * + ** @return plane description if successful, NULL otherwise + */ + const char *getPlaneDescription(unsigned int plane) const; + + /** get overlay mode of specified plane + * + ** @param plane index of plane (starting from 0) or group number (0x6000-0x60ff) + * + ** @return overlay mode if successful, EMO_Default otherwise + */ + EM_Overlay getPlaneMode(unsigned int plane) const; + + /** get number of overlay planes + * + ** @return number of overlay planes + */ + inline unsigned int getCount() const + { + return (Data != NULL) ? Data->Count : 0; + } + + /** get current x-coordinate of overlay origin. + * This value is added to the origin of all overlay planes. + * + ** @return x-coordinate of overlay origin + */ + inline signed long getLeft() const + { + return Left; + } + + /** get current y-coordinate of overlay origin. + * This value is added to the origin of all overlay planes. + * + ** @return y-coordinate of overlay origin + */ + inline signed long getTop() const + { + return Top; + } + + /** check whether there are any overlay planes embedded in the pixel data + * + ** @return true if there are embedded planes, false otherwise + */ + int hasEmbeddedData() const; + + /** add plane to list of additional overlay planes + * + ** @param group group number of plane to be added (0x6000-0x60ff). + * If group number already exists in the list of additional planes + * the old one is replaced. If the number exists in the list of + * planes stored in the image dataset the new plane hides it. + * @param left_pos x-coordinate of the plane origin + * @param top_pos y-coordinate of the plane origin + * @param columns width of the overlay plane (in pixels) + * @param rows height of the overlay plane + * @param data element where the plane data is stored + * @param label element where the plane label is stored + * @param description element where the plane description is stored + * @param mode overlay plane mode + * + ** @return status, true if successful, false otherwise + */ + int addPlane(const unsigned int group, + const signed int left_pos, + const signed int top_pos, + const unsigned int columns, + const unsigned int rows, + const DcmOverlayData &data, + const DcmLongString &label, + const DcmLongString &description, + const EM_Overlay mode); + + + /** remove specified plane from list of additional overlay planes + * + ** @param group group number of plane to be removed (0x6000-0x60ff) + * + ** @return status, true if successful, false otherwise + */ + int removePlane(const unsigned int group); + + inline DiOverlayPlane *getPlane(const unsigned int plane) const + { + return ((Data != NULL) && (Data->Planes != NULL) && (plane < Data->Count)) ? Data->Planes[plane] : OFstatic_cast(DiOverlayPlane *, NULL); + } + + /** check whether specified plane exists + * + ** @param plane index of plane (starting from 0) or group number (0x6000-0x60ff) + * @param visible flag indicating whether plane should be visible or not (default: 0 = ignore) + * + ** @return status, true if such a plane exists, false otherwise + */ + inline int hasPlane(unsigned int plane, + const int visible = 0) const + { + return (convertToPlaneNumber(plane, AdditionalPlanes) > 1) && (!visible || Data->Planes[plane]->isVisible()); + } + + /** get overlay plane data as an array of 1/8/16 bit values. + * Memory isn't handled internally and must therefore be deleted from calling program. + * + ** @param frame number of frame + * @param plane index of plane (starting from 0) or group number (0x6000-0x60ff) + * @param left_pos get x-coordinate of the plane origin + * @param top_pos get y-coordinate of the plane origin + * @param width get width of the overlay plane (in pixels) + * @param height get height of the overlay plane + * @param mode get overlay plane mode + * @param columns width of the surrounding image + * @param rows height of the surrounding image + * @param bits number of bits (stored) in the resulting array, default: 8 + * @param fore foreground color used for the plane (default: 0xff = white, for 8 bits) + * @param back transparent background color (default: 0x00 = black) + * + ** @return pointer to pixel data if successful, NULL otherwise + */ + void *getPlaneData(const unsigned long frame, + unsigned int plane, + unsigned int &left_pos, + unsigned int &top_pos, + unsigned int &width, + unsigned int &height, + EM_Overlay &mode, + const Uint16 columns, + const Uint16 rows, + const int bits = 8, + const Uint16 fore = 0xff, + const Uint16 back = 0x0); + + /** get overlay plane data as an array of 1/8/16 bit values. + * Memory isn't handled internally and must therefore be deleted from calling program. + * + ** @param frame number of frame + * @param plane index of plane (starting from 0) or group number (0x6000-0x60ff) + * @param width get width of the overlay plane (in pixels) + * @param height get height of the overlay plane + * @param bits number of bits (stored) in the resulting array, default: 8 + * @param fore foreground color used for the plane (default: 0xff = white, for 8 bits) + * @param back transparent background color (default: 0x00 = black) + * + ** @return pointer to pixel data if successful, NULL otherwise + */ + void *getFullPlaneData(const unsigned long frame, + unsigned int plane, + unsigned int &width, + unsigned int &height, + const int bits = 8, + const Uint16 fore = 0xff, + const Uint16 back = 0x0); + + /** create overlay plane data in (6xxx,3000) format. + * (1 bit allocated and stored, foreground color is 1, background color is 0, + * data is 16 bit padded - even length) + * Memory isn't handled internally and must therefore be deleted from calling program. + * + ** @param buffer stores pointer to overlay data (memory is allocated internally) + * @param plane number (0..15) or group number (0x60nn) of overlay plane + * @param width returns width of overlay plane (in pixels) + * @param height returns height of overlay plane (in pixels) + * @param frames returns number of frames (multiple overlay frames possible!) + * + ** @return number of bytes allocated for the 'buffer' if successful, 0 otherwise + */ + unsigned long create6xxx3000PlaneData(Uint8 *&buffer, + unsigned int plane, + unsigned int &width, + unsigned int &height, + unsigned long &frames); + + /// constant defining the maximum number of overlay planes (16) + static const unsigned int MaxOverlayCount; + /// constant defining the group number of the first overlay plane (0x6000) + static const unsigned int FirstOverlayGroup; + + + protected: + + /** initialize new overlay managing object + * + ** @param overlay reference object used as a template + * + ** @return pointer to a new array of pixel data + */ + Uint16 *Init(const DiOverlay *overlay); + + /** convert given plane or group number to a valid plane number + * + ** @param plane plane or group number to be converted + * @param mode true or false, see return value + * + ** @return status, true if successful, false otherwise. + * (1 = additional plane with the specified group number would be new, + * 2 = additional plane with the specified group number already exists, + * 3 = 'plane' is the number of a valid plane - only if 'mode' us false) + */ + int convertToPlaneNumber(unsigned int &plane, + const int mode) const; + + /** convert five plane number to corresponding group number + * + ** @param plane index of plane (0..15) + * + ** @return group number + */ + unsigned int convertToGroupNumber(const unsigned int plane) const + { + return FirstOverlayGroup + 2 * plane; + } + + /** check whether given group number is valid. + * Valid means that the number is even and between 0x6000 and 0x60ff. + * + ** @param group group number to be checked + * + ** @return status, true if valid, false otherwise + */ + int isValidGroupNumber(const unsigned int group) const; + + /** check whether the specified plane is valid. and determine maximum resolution + * and number of frames which are common for all overlay planes so far. + * + ** @param plane index of plane (0..15) + * @param mode if true the maximum number of frames is determined, otherwise not + * + ** @return status, true if successful, false otherwise + */ + int checkPlane(const unsigned int plane, + const int mode = 1); + + + private: + + /// left offset to all planes + signed long Left; + /// top offset to all planes + signed long Top; + /// maximum width of all planes + Uint16 Width; + /// maximum height of all planes + Uint16 Height; + /// maximum number of frames + unsigned long Frames; + + /// status, if true planes are added later with addPlane() + int AdditionalPlanes; + + /// points to overlay data (provides shared data) + DiOverlayData *Data; + + // --- declarations to avoid compiler warnings + + DiOverlay(const DiOverlay &); + DiOverlay &operator=(const DiOverlay &); +}; + + +#endif diff --git a/dcmimgle/include/dcmtk/dcmimgle/diovlimg.h b/dcmimgle/include/dcmtk/dcmimgle/diovlimg.h new file mode 100644 index 00000000..1f4a8135 --- /dev/null +++ b/dcmimgle/include/dcmtk/dcmimgle/diovlimg.h @@ -0,0 +1,57 @@ +/* + * + * Copyright (C) 1996-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimgle + * + * Author: Joerg Riesmeier + * + * Purpose: DicomOverlayImage (Header) + * + */ + + +#ifndef DIOVLIMG_H +#define DIOVLIMG_H + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/dcmimgle/dimo2img.h" + + +/*---------------------* + * class declaration * + *---------------------*/ + +/** Class for standalone overlay images + */ +class DCMTK_DCMIMGLE_EXPORT DiOverlayImage + : public DiMono2Image +{ + + public: + + /** constructor + * + ** @param docu pointer to dataset (encapsulated) + * @param status current image status + */ + DiOverlayImage(const DiDocument *docu, + const EI_Status status); + + /** destructor + */ + virtual ~DiOverlayImage(); +}; + + +#endif diff --git a/dcmimgle/include/dcmtk/dcmimgle/diovpln.h b/dcmimgle/include/dcmtk/dcmimgle/diovpln.h new file mode 100644 index 00000000..8cd7ff6f --- /dev/null +++ b/dcmimgle/include/dcmtk/dcmimgle/diovpln.h @@ -0,0 +1,560 @@ +/* + * + * Copyright (C) 1996-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimgle + * + * Author: Joerg Riesmeier + * + * Purpose: DicomOverlayPlane (Header) + * + */ + + +#ifndef DIOVPLN_H +#define DIOVPLN_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/ofstd/ofstring.h" +#include "dcmtk/ofstd/ofcast.h" + +#include "dcmtk/dcmimgle/diutils.h" + +#define INCLUDE_CSTDDEF +#include "dcmtk/ofstd/ofstdinc.h" + + +/*------------------------* + * forward declarations * + *------------------------*/ + +class DcmOverlayData; +class DcmLongString; + +class DiDocument; + + +/*---------------------* + * class declaration * + *---------------------*/ + +/** Class to handle a single overlay plane + */ +class DCMTK_DCMIMGLE_EXPORT DiOverlayPlane +{ + + public: + + /** constructor + * + ** @param docu pointer to dataset (encapsulated) + * @param group group number of the overlay plane + * @param alloc value for bits allocated of the surrounding image + * @param stored value for bits stored of the surrounding image + * @param high value for high bit of the surrounding image + */ + DiOverlayPlane(const DiDocument *docu, + const unsigned int group, + Uint16 alloc, + const Uint16 stored, + const Uint16 high); + + /** constructor, additional + * + ** @param group group number of the overlay plane + * @param left_pos x-coordinate of the plane origin + * @param top_pos y-coordinate of the plane origin + * @param columns width of the overlay plane + * @param rows height of the overlay plane + * @param data element containing the plane data + * @param label element containing the plane label + * @param description element containing the plane description + * @param mode overlay plane mode + */ + DiOverlayPlane(const unsigned int group, + const Sint16 left_pos, + const Sint16 top_pos, + const Uint16 columns, + const Uint16 rows, + const DcmOverlayData &data, + const DcmLongString &label, + const DcmLongString &description, + const EM_Overlay mode); + + /** constructor, copy + * + ** @param plane reference overlay plane to be copied + * @param bit position of the plane bit + * @param data pointer to buffer for plane data + * @param temp temporary buffer used to extract plane information + * @param width width of the array where the plane is stored + * @param height height of the array where the plane is stored + * @param columns width of the overlay plane + * @param rows height of the overlay plane + */ + DiOverlayPlane(DiOverlayPlane *plane, + const unsigned int bit, + Uint16 *data, + Uint16 *temp, + const Uint16 width, + const Uint16 height, + const Uint16 columns, + const Uint16 rows); + + /** destructor + */ + ~DiOverlayPlane(); + + /** get x-coordinate of overlay plane origin + * + ** @param left_pos offset to be subtracted from the actual value (optional) + * + ** @return x-coordinate of overlay plane origin + */ + inline Sint16 getLeft(const Sint32 left_pos = 0) const + { + return OFstatic_cast(Sint16, OFstatic_cast(Sint32, Left) - left_pos); + } + + /** get y-coordinate of overlay plane origin + * + ** @param top_pos offset to be subtracted from the actual value (optional) + * + ** @return y-coordinate of overlay plane origin + */ + inline Sint16 getTop(const Sint32 top_pos = 0) const + { + return OFstatic_cast(Sint16, OFstatic_cast(Sint32, Top) - top_pos); + } + + /** get width of overlay plane + * + ** @return width of overlay plane + */ + inline Uint16 getWidth() const + { + return Width; + } + + /** get height of overlay plane + * + ** @return height of overlay plane + */ + inline Uint16 getHeight() const + { + return Height; + } + + /** get right border of overlay plane origin + * + ** @param left_pos offset to be subtracted from the actual value (optional). + * + ** @return right border of overlay plane origin. Negative values are set to 0. + */ + inline Uint16 getRight(const Sint32 left_pos = 0) const + { + return (OFstatic_cast(Sint32, Left) + OFstatic_cast(Sint32, Width) - left_pos > 0) ? + OFstatic_cast(Uint16, OFstatic_cast(Sint32, Left) + OFstatic_cast(Sint32, Width) - left_pos) : 0; + } + + /** get bottom border of overlay plane origin + * + ** @param top_pos offset to be subtracted from the actual value (optional). + * + ** @return bottom border of overlay plane origin. Negative values are set to 0. + */ + inline Uint16 getBottom(const Sint32 top_pos = 0) const + { + return (OFstatic_cast(Sint32, Top) + OFstatic_cast(Sint32, Height) - top_pos > 0) ? + OFstatic_cast(Uint16, OFstatic_cast(Sint32, Top) + OFstatic_cast(Sint32, Height) - top_pos) : 0; + } + + /** check whether overlay plane is valid + * + ** @return true if plane is valid, false otherwise + */ + inline int isValid() const + { + return Valid; + } + + /** check whether overlay plane is visible + * + ** @return true if plane is visible, false otherwise + */ + inline int isVisible() const + { + return Visible; + } + + /** make overlay plane visible + */ + inline void show() + { + Visible = 1; + } + + /** make overlay plane invisible + */ + inline void hide() + { + Visible = 0; + } + + /** move overlay plane to a new place + * + ** @param left_pos x-coordinate of the new plane origin (maybe negative) + * @param top_pos y-coordinate of the new plane origin (maybe negative) + */ + void place(const signed int left_pos, + const signed int top_pos); + + /** set scaling factor in x- and y-direction + * + ** @param xfactor scaling factor in x-direction + * @param yfactor scaling factor in y-direction + */ + void setScaling(const double xfactor, + const double yfactor); + + /** set flipping + * + ** @param horz flip horizontally if true + * @param vert flip vertically if true + * @param columns width of surrounding image (incl. origin offset) + * @param rows height of surrounding image (incl. origin offset) + */ + void setFlipping(const int horz, + const int vert, + const signed long columns, + const signed long rows); + + /** set rotation + * + ** @param degree angle by which the plane should be rotated + * @param left_pos x-coordinate of the origin for all overlay planes + * @param top_pos y-coordinate of the origin for all overlay planes + * @param columns width of surrounding image (already rotated) + * @param rows height of surrounding image (already rotated) + */ + void setRotation(const int degree, + const signed long left_pos, + const signed long top_pos, + const Uint16 columns, + const Uint16 rows); + + /** make overlay plane visible and set parameters + * + ** @param fore foreground color of the plane (in percent: 0.0-1.0) + * @param thresh threshold value for 'threshold replace' (0.0-1.0) + * @param mode new overlay plane mode (EMO_Default for stored mode) + */ + void show(const double fore, + const double thresh, + const EM_Overlay mode); + + /** make overlay plane visible and set p-value. + * Only applicable for bitmap shutters. + * + ** @param pvalue p-value to be used for the overlay plane (0..65535) + * + ** @return status, true if successful, false otherwise + */ + int show(const Uint16 pvalue); + + /** get number of frames + * + ** @return number of frames + */ + inline unsigned long getNumberOfFrames() const + { + return NumberOfFrames; + } + + /** get foreground color of the plane + * + ** @return foreground color (in percent: 0.0-1.0) + */ + inline double getForeground() const + { + return Foreground; + } + + /** get threshold value of the plane + * + ** @return threshold value (in percent: 0.0-1.0) + */ + inline double getThreshold() const + { + return Threshold; + } + + /** get p-value of the plane. + * Only valid for bitmap shutters. + * + ** @return p-value (0..65535) + */ + inline Uint16 getPValue() const + { + return PValue; + } + + /** get overlay plane mode + * + ** @return overlay plane mode + */ + inline EM_Overlay getMode() const + { + return Mode; + } + + /** check whether overlay plane is embedded in the pixel data + * + ** @return true if plane is embedded, false otherwise + */ + inline int isEmbedded() const + { + return EmbeddedData; + } + + /** get label of overlay plane + * + ** @return label if successful, NULL otherwise + */ + const char *getLabel() const + { + return (Label.empty()) ? OFstatic_cast(const char *, NULL) : Label.c_str(); + } + + /** get description of overlay plane + * + ** @return description if successful, NULL otherwise + */ + const char *getDescription() const + { + return (Description.empty()) ? OFstatic_cast(const char *, NULL) : Description.c_str(); + } + + /** get group number of overlay plane + * + ** @return group number (0x6000-0x60ff) + */ + Uint16 getGroupNumber() const + { + return GroupNumber; + } + + /** get overlay plane data as an array of 1/8/16 bit values. + * Overlay plane is clipped to the area specified by the four min/max coordinates. + * Memory isn't handled internally and must therefore be deleted from calling program. + * + ** @param frame number of frame + * @param xmin x-coordinate of the top left hand corner + * @param ymin y-coordinate of the top left hand corner + * @param xmax x-coordinate of the bottom right hand corner + * @param ymax y-coordinate of the bottom right hand corner + * @param bits number of bits (stored) in the resulting array + * @param fore foreground color used for the plane (0x00-0xff) + * @param back transparent background color (0x00-0xff) + * + ** @return pointer to pixel data if successful, NULL otherwise + */ + void *getData(const unsigned long frame, + const Uint16 xmin, + const Uint16 ymin, + const Uint16 xmax, + const Uint16 ymax, + const int bits, + const Uint16 fore, + const Uint16 back); + + /** create overlay plane data in (6xxx,3000) format. + * (1 bit allocated and stored, foreground color is 1, background color is 0, + * data is 16 bit padded - even length) + * Memory isn't handled internally and must therefore be deleted from calling program. + * + ** @param buffer stores pointer to overlay data (memory is allocated internally) + * @param width returns width of overlay plane (in pixels) + * @param height returns height of overlay plane (in pixels) + * @param frames returns number of frames (multiple overlay frames possible!) + * + ** @return number of bytes allocated for the 'buffer' if successful, 0 otherwise + */ + unsigned long create6xxx3000Data(Uint8 *&buffer, + unsigned int &width, + unsigned int &height, + unsigned long &frames); + + /** reset internal 'cursor' to the beginning of the specified frame + * + ** @param frame number of current frame + * + ** @return status, true if successful, false otherwise + */ + inline int reset(const unsigned long frame); + + /** get value of the current overlay plane bit and move 'cursor' to the next position + * + ** @return true if plane bit is set, false otherwise + */ + inline int getNextBit(); + + /** set internal 'cursor' to a specific position + * + ** @param x new x-coordinate to start from + * @param y new y-coordinate to start from + */ + inline void setStart(const Uint16 x, + const Uint16 y); + + + protected: + + /// number of frames + Uint32 NumberOfFrames; + /// number of starting frame + Uint16 ImageFrameOrigin; + /// first frame to be processed (from DicomImage constructor) + Uint32 FirstFrame; + + /// y-coordinate of overlay plane's origin + Sint16 Top; + /// x-coordinate of overlay plane's origin + Sint16 Left; + /// visible height + Uint16 Height; + /// visible width + Uint16 Width; + /// number of (stored) rows + Uint16 Rows; + /// number of (stored) columns + Uint16 Columns; + /// number of allocated bits per pixel + Uint16 BitsAllocated; + /// position of overlay plane bit + Uint16 BitPosition; + + /// "color" of overlay plane (in percent: '0.0' = dark, '1.0' = bright) + double Foreground; + /// threshold value used for "threshold replace" + double Threshold; + /// P-value used for bitmap shutters + Uint16 PValue; + + /// current overlay mode + EM_Overlay Mode; + /// default (stored) overlay mode + EM_Overlay DefaultMode; + + /// label of overlay plane + OFString Label; + /// textual description of overlay plane + OFString Description; + + /// group number of overlay plane + Uint16 GroupNumber; + + /// validity status + int Valid; + /// visibility status + int Visible; + + + private: + + /// current bit position + unsigned long BitPos; + /// starting bit position of current frame + unsigned long StartBitPos; + + /// x-coordinate of first pixel in surrounding memory buffer + unsigned int StartLeft; + /// y-coordinate of first pixel in surrounding memory buffer + unsigned int StartTop; + + /// true, if overlay data in embedded in pixel data + int EmbeddedData; + + /// pointer to current element of 'Data' + const Uint16 *Ptr; + /// pointer to starting element of current frame + const Uint16 *StartPtr; + /// pointer to overlay data (standalone) or pixel data (embedded) + const Uint16 *Data; + + // --- declarations to avoid compiler warnings + + DiOverlayPlane(const DiOverlayPlane &); + DiOverlayPlane &operator=(const DiOverlayPlane &); +}; + + +/********************************************************************/ + + +inline int DiOverlayPlane::reset(const unsigned long frame) +{ + int result = 0; + if (Valid && (Data != NULL)) + { + const Uint32 frameNumber = FirstFrame + frame; + DCMIMGLE_TRACE("reset overlay plane in group 0x" << STD_NAMESPACE hex << GroupNumber << " to start position"); + DCMIMGLE_TRACE(" frameNumber: " << frameNumber << " (" << FirstFrame << "+" << frame + << "), ImageFrameOrigin: " << ImageFrameOrigin << ", NumberOfFrames: " << NumberOfFrames); + if ((frameNumber >= ImageFrameOrigin) && (frameNumber < ImageFrameOrigin + NumberOfFrames)) + { + const unsigned long bits = (OFstatic_cast(unsigned long, StartLeft) + OFstatic_cast(unsigned long, StartTop) * + OFstatic_cast(unsigned long, Columns) + (frameNumber - ImageFrameOrigin) * OFstatic_cast(unsigned long, Rows) * + OFstatic_cast(unsigned long, Columns)) * OFstatic_cast(unsigned long, BitsAllocated); + StartBitPos = BitPos = OFstatic_cast(unsigned long, BitPosition) + bits; + DCMIMGLE_TRACE(" StartBitPos: " << StartBitPos << ", BitPosition: " << BitPosition << ", bits: " << bits); + /* distinguish between embedded and separate overlay data */ + if (BitsAllocated == 16) + StartPtr = Ptr = Data + (bits >> 4); + else + StartPtr = Data; + result = (getRight() > 0) && (getBottom() > 0); + } else + DCMIMGLE_TRACE(" -> overlay plane does not apply to this frame"); + } + return result; +} + + +inline int DiOverlayPlane::getNextBit() +{ + int result; + if (BitsAllocated == 16) // optimization + result = OFstatic_cast(int, *(Ptr++) & (1 << BitPosition)); + else + { + Ptr = StartPtr + (BitPos >> 4); // div 16 + result = OFstatic_cast(int, *Ptr & (1 << (BitPos & 0xf))); // mod 16 + BitPos += BitsAllocated; // next bit + } + return result; +} + + +inline void DiOverlayPlane::setStart(const Uint16 x, + const Uint16 y) +{ + if (BitsAllocated == 16) + Ptr = StartPtr + OFstatic_cast(unsigned long, y - Top) * OFstatic_cast(unsigned long, Columns) + + OFstatic_cast(unsigned long, x - Left); + else + BitPos = StartBitPos + (OFstatic_cast(unsigned long, y - Top) * OFstatic_cast(unsigned long, Columns) + + OFstatic_cast(unsigned long, x - Left)) * OFstatic_cast(unsigned long, BitsAllocated); +} + + +#endif diff --git a/dcmimgle/include/dcmtk/dcmimgle/dipixel.h b/dcmimgle/include/dcmtk/dcmimgle/dipixel.h new file mode 100644 index 00000000..7439e9ba --- /dev/null +++ b/dcmimgle/include/dcmtk/dcmimgle/dipixel.h @@ -0,0 +1,122 @@ +/* + * + * Copyright (C) 1996-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimgle + * + * Author: Joerg Riesmeier + * + * Purpose: DicomPixel (Header) + * + */ + + +#ifndef DIPIXEL_H +#define DIPIXEL_H + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/dcmimgle/diutils.h" + + +/*---------------------* + * class declaration * + *---------------------*/ + +/** Abstract base class to handle pixel data + */ +class DCMTK_DCMIMGLE_EXPORT DiPixel +{ + + public: + + /** constructor + * + ** @param count number of pixels stored in the buffer + * @param inputCount number of pixels read from 'PixelData' attribute + */ + DiPixel(const unsigned long count, + const unsigned long inputCount = 0) + : Count(count), + InputCount(inputCount) + { + } + + /** destructor + */ + virtual ~DiPixel() + { + } + + /** get integer representation (abstract) + * + ** @return integer representation of the internally stored pixel data + */ + virtual EP_Representation getRepresentation() const = 0; + + /** get number of planes (abstract). + * + ** @return number of planes (e.g. 1 for monochrome and 3 for color images) + */ + virtual int getPlanes() const = 0; + + /** get pointer to pixel data (abstract). + * NB: See implemented method in derived class for details. + * + ** @return pointer to pixel data + */ + virtual const void *getData() const = 0; + + /** get pointer to pixel data (abstract). + * NB: See implemented method in derived class for details. + * + ** @return pointer to pixel data + */ + virtual void *getDataPtr() = 0; + + /** get pointer to array of pixel data (abstract). + * The number of planes in the returned array can be determined using 'getPlanes()'. + * + ** @return pointer to array of pixel data + */ + virtual void *getDataArrayPtr() = 0; + + /** get number of pixels + * + ** @return number of pixels + */ + inline unsigned long getCount() const + { + return Count; + } + + /** get number of pixels stored in the 'PixelData' element + * + ** @return number pixels read from the input buffer + */ + inline unsigned long getInputCount() const + { + return InputCount; + } + + + protected: + + /// number of pixels + /*const*/ unsigned long Count; + + /// number of pixels in the input buffer + unsigned long InputCount; +}; + + +#endif diff --git a/dcmimgle/include/dcmtk/dcmimgle/diplugin.h b/dcmimgle/include/dcmtk/dcmimgle/diplugin.h new file mode 100644 index 00000000..a68dfd53 --- /dev/null +++ b/dcmimgle/include/dcmtk/dcmimgle/diplugin.h @@ -0,0 +1,77 @@ +/* + * + * Copyright (C) 2001-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimgle + * + * Author: Joerg Riesmeier + * + * Purpose: Provides abstract interface to plugable image output formats + * + */ + + +#ifndef DIPLUGIN_H +#define DIPLUGIN_H + +#include "dcmtk/config/osconfig.h" + +#define INCLUDE_CSTDIO +#include "dcmtk/ofstd/ofstdinc.h" + + +/*------------------------* + * forward declarations * + *------------------------*/ + +class DiImage; + + +/*---------------------* + * class declaration * + *---------------------*/ + +/** abstract interface to plugable image output formats. + * This is an abstract base class used as an interface to support multiple + * plugable image output formats for the dcmimle/dcmimage library. An example + * implementation can be found in dcmjpeg/libsrc/dipijpeg.cc (JPEG plugin). + */ +class DCMTK_DCMIMGLE_EXPORT DiPluginFormat +{ + + public: + + /** destructor (virtual) + */ + virtual ~DiPluginFormat() {} + + /** write given image to a file stream (abstract) + * + ** @param image pointer to DICOM image object to be written + * @param stream stream to which the image is written (open in binary mode!) + * @param frame index of frame used for output (default: first frame = 0) + * + ** @return true if successful, false otherwise + */ + virtual int write(DiImage *image, + FILE *stream, + const unsigned long frame = 0) const = 0; + + protected: + + /** constructor (protected) + */ + DiPluginFormat() {} +}; + + +#endif diff --git a/dcmimgle/include/dcmtk/dcmimgle/dipxrept.h b/dcmimgle/include/dcmtk/dcmimgle/dipxrept.h new file mode 100644 index 00000000..123f799e --- /dev/null +++ b/dcmimgle/include/dcmtk/dcmimgle/dipxrept.h @@ -0,0 +1,159 @@ +/* + * + * Copyright (C) 1996-2010, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimgle + * + * Author: Joerg Riesmeier + * + * Purpose: DicomPixelRepresentationTemplate (Header) + * + */ + + +#ifndef DIPXREPT_H +#define DIPXREPT_H + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/dcmimgle/diutils.h" + +#ifdef HAVE_EXPLICIT_TEMPLATE_SPECIALIZATION +#define EXPLICIT_SPECIALIZATION template<> +#else +#define EXPLICIT_SPECIALIZATION +#endif + + +/*---------------------* + * class declaration * + *---------------------*/ + +/** Template class to determine pixel representation. + * Size of basic structure, sign-extension + */ +template +class DiPixelRepresentationTemplate +{ + + public: + + /// default constructor + DiPixelRepresentationTemplate() {} + + /// destructor + virtual ~DiPixelRepresentationTemplate() {} + + /** check whether template type T is signed or not + * + ** @return true if signed, false otherwise + */ + inline int isSigned() const; + + protected: + + /** determine integer representation for template type T + * + ** @return integer representation + */ + virtual inline EP_Representation getRepresentation() const; +}; + + +/********************************************************************/ + + +EXPLICIT_SPECIALIZATION +inline EP_Representation DiPixelRepresentationTemplate::getRepresentation() const +{ + return EPR_Uint8; +} + + +EXPLICIT_SPECIALIZATION +inline EP_Representation DiPixelRepresentationTemplate::getRepresentation() const +{ + return EPR_Sint8; +} + + +EXPLICIT_SPECIALIZATION +inline EP_Representation DiPixelRepresentationTemplate::getRepresentation() const +{ + return EPR_Uint16; +} + + +EXPLICIT_SPECIALIZATION +inline EP_Representation DiPixelRepresentationTemplate::getRepresentation() const +{ + return EPR_Sint16; +} + + +EXPLICIT_SPECIALIZATION +inline EP_Representation DiPixelRepresentationTemplate::getRepresentation() const +{ + return EPR_Uint32; +} + + +EXPLICIT_SPECIALIZATION +inline EP_Representation DiPixelRepresentationTemplate::getRepresentation() const +{ + return EPR_Sint32; +} + + +EXPLICIT_SPECIALIZATION +inline int DiPixelRepresentationTemplate::isSigned() const +{ + return 0; +} + + +EXPLICIT_SPECIALIZATION +inline int DiPixelRepresentationTemplate::isSigned() const +{ + return 0; +} + + +EXPLICIT_SPECIALIZATION +inline int DiPixelRepresentationTemplate::isSigned() const +{ + return 0; +} + + +EXPLICIT_SPECIALIZATION +inline int DiPixelRepresentationTemplate::isSigned() const +{ + return 1; +} + + +EXPLICIT_SPECIALIZATION +inline int DiPixelRepresentationTemplate::isSigned() const +{ + return 1; +} + + +EXPLICIT_SPECIALIZATION +inline int DiPixelRepresentationTemplate::isSigned() const +{ + return 1; +} + + +#endif diff --git a/dcmimgle/include/dcmtk/dcmimgle/diregbas.h b/dcmimgle/include/dcmtk/dcmimgle/diregbas.h new file mode 100644 index 00000000..a957331e --- /dev/null +++ b/dcmimgle/include/dcmtk/dcmimgle/diregbas.h @@ -0,0 +1,96 @@ +/* + * + * Copyright (C) 1996-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimgle + * + * Author: Joerg Riesmeier + * + * Purpose: DicomRegisterBase (Header) + * + */ + + +#ifndef DIREGBAS_H +#define DIREGBAS_H + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/dcmimgle/diutils.h" + + +/*------------------------* + * forward declarations * + *------------------------*/ + +class DiImage; +class DiColorImage; +class DiMonoPixel; +class DiDocument; +class DiRegisterBase; + + +/*---------------------* + * class declaration * + *---------------------*/ + +/** Abstract base class to register additional libraries + */ +class DCMTK_DCMIMGLE_EXPORT DiRegisterBase +{ + + public: + + /** constructor, default + */ + DiRegisterBase() + { + } + + /** destructor + */ + virtual ~DiRegisterBase() + { + } + + /** create color image representation (abstract) + * + ** @param docu pointer to dataset (encapsulated) + * @param status image status + * @param photo photometric interpretation + * + ** @return pointer to new DiImage object (NULL if an error occurred) + */ + virtual DiImage *createImage(const DiDocument *docu, + const EI_Status status, + const EP_Interpretation photo) = 0; + + /** create monochrome pixel data of color image (abstract) + * + ** @param image pointer to color image + * @param red coefficient by which the red component is weighted + * @param green coefficient by which the green component is weighted + * @param blue coefficient by which the blue component is weighted + * + ** @return pointer to new DiImage object (NULL if an error occurred) + */ + virtual DiMonoPixel *createMonoImageData(const DiColorImage *image, + const double red, + const double green, + const double blue) = 0; + + /// global pointer to registered 'dcmimage' library + static DiRegisterBase *Pointer; +}; + + +#endif diff --git a/dcmimgle/include/dcmtk/dcmimgle/dirotat.h b/dcmimgle/include/dcmtk/dcmimgle/dirotat.h new file mode 100644 index 00000000..2a92cac7 --- /dev/null +++ b/dcmimgle/include/dcmtk/dcmimgle/dirotat.h @@ -0,0 +1,347 @@ +/* + * + * Copyright (C) 1996-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimgle + * + * Author: Joerg Riesmeier + * + * Purpose: DicomRotateTemplate (Header) + * + */ + + +#ifndef DIROTAT_H +#define DIROTAT_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/ofstd/ofcast.h" + +#include "dcmtk/dcmimgle/dipixel.h" +#include "dcmtk/dcmimgle/ditranst.h" + + +/*---------------------* + * class declaration * + *---------------------*/ + +/** Template class to rotate images (on pixel data level). + * by steps of 90 degrees + */ +template +class DiRotateTemplate + : public DiTransTemplate +{ + + public: + + /** constructor. + * This method is used to rotate an image and store the result in the same storage area. + * + ** @param pixel pointer to object where the pixel data are stored + * @param src_cols original width of the image + * @param src_rows original height of the image + * @param dest_cols new width of the image + * @param dest_rows new height of the image + * @param frames number of frames + * @param degree angle by which the image should be rotated + */ + DiRotateTemplate(DiPixel *pixel, + const Uint16 src_cols, + const Uint16 src_rows, + const Uint16 dest_cols, + const Uint16 dest_rows, + const Uint32 frames, + const int degree) + : DiTransTemplate(0, src_cols, src_rows, dest_cols, dest_rows, frames) + { + if (pixel != NULL) + { + this->Planes = pixel->getPlanes(); + if ((pixel->getCount() > 0) && (this->Planes > 0) && + (pixel->getCount() == OFstatic_cast(unsigned long, src_cols) * OFstatic_cast(unsigned long, src_rows) * frames)) + { + if (degree == 90) + rotateRight(OFstatic_cast(T **, pixel->getDataArrayPtr())); + else if (degree == 180) + rotateTopDown(OFstatic_cast(T **, pixel->getDataArrayPtr())); + else if (degree == 270) + rotateLeft(OFstatic_cast(T **, pixel->getDataArrayPtr())); + } else { + DCMIMGLE_WARN("could not rotate image ... corrupted data"); + } + } + } + + /** constructor. + * This method is used to perform only the preparation and to start rotation later with method 'rotateData()' + * + ** @param planes number of planes (1 or 3) + * @param src_cols original width of the image + * @param src_rows original height of the image + * @param dest_cols new width of the image + * @param dest_rows new height of the image + * @param frames number of frames + */ + DiRotateTemplate(const int planes, + const Uint16 src_cols, + const Uint16 src_rows, + const Uint16 dest_cols, + const Uint16 dest_rows, + const Uint32 frames) + : DiTransTemplate(planes, src_cols, src_rows, dest_cols, dest_rows, frames) + { + } + + /** destructor + */ + virtual ~DiRotateTemplate() + { + } + + /** choose algorithm depending on rotation angle + * + ** @param src array of pointers to source image pixels + * @param dest array of pointers to destination image pixels + * @param degree angle by which the image should be rotated + */ + inline void rotateData(const T *src[], + T *dest[], + const int degree) + { + if (degree == 90) + rotateRight(src, dest); + else if (degree == 180) + rotateTopDown(src, dest); + else if (degree == 270) + rotateLeft(src, dest); + else + this->copyPixel(src, dest); + } + + + protected: + + /** rotate source image left and store result in destination image + * + ** @param src array of pointers to source image pixels + * @param dest array of pointers to destination image pixels + */ + inline void rotateLeft(const T *src[], + T *dest[]) + { + if ((src != NULL) && (dest != NULL)) + { + register Uint16 x; + register Uint16 y; + register const T *p; + register T *q; + register T *r; + const unsigned long count = OFstatic_cast(unsigned long, this->Dest_X) * OFstatic_cast(unsigned long, this->Dest_Y); + for (int j = 0; j < this->Planes; ++j) + { + p = src[j]; + r = dest[j]; + for (unsigned long f = this->Frames; f != 0; --f) + { + r += count; + for (x = this->Dest_X; x != 0; --x) + { + q = r - x; + for (y = this->Dest_Y; y != 0; --y) + { + *q = *p++; + q -= this->Dest_X; + } + } + } + } + } + } + + /** rotate source image right and store result in destination image + * + ** @param src array of pointers to source image pixels + * @param dest array of pointers to destination image pixels + */ + inline void rotateRight(const T *src[], + T *dest[]) + { + if ((src != NULL) && (dest != NULL)) + { + register Uint16 x; + register Uint16 y; + register const T *p; + register T *q; + register T *r; + const unsigned long count = OFstatic_cast(unsigned long, this->Dest_X) * OFstatic_cast(unsigned long, this->Dest_Y); + for (int j = 0; j < this->Planes; ++j) + { + p = src[j]; + r = dest[j]; + for (unsigned long f = this->Frames; f != 0; --f) + { + for (x = this->Dest_X; x != 0; --x) + { + q = r + x - 1; + for (y = this->Dest_Y; y != 0; --y) + { + *q = *p++; + q += this->Dest_X; + } + } + r += count; + } + } + } + } + + /** rotate source image top-down and store result in destination image + * + ** @param src array of pointers to source image pixels + * @param dest array of pointers to destination image pixels + */ + inline void rotateTopDown(const T *src[], + T *dest[]) + { + if ((src != NULL) && (dest != NULL)) + { + register unsigned long i; + register const T *p; + register T *q; + const unsigned long count = OFstatic_cast(unsigned long, this->Dest_X) * OFstatic_cast(unsigned long, this->Dest_Y); + for (int j = 0; j < this->Planes; ++j) + { + p = src[j]; + q = dest[j]; + for (unsigned long f = this->Frames; f != 0; --f) + { + q += count; + for (i = count; i != 0; --i) + *--q = *p++; + q += count; + } + } + } + } + + private: + + /** rotate image left and store result in the same storage area + * + ** @param data array of pointers to source/destination image pixels + */ + inline void rotateLeft(T *data[]) + { + const unsigned long count = OFstatic_cast(unsigned long, this->Dest_X) * OFstatic_cast(unsigned long, this->Dest_Y); + T *temp = new T[count]; + if (temp != NULL) + { + register Uint16 x; + register Uint16 y; + register const T *p; + register T *q; + register T *r; + for (int j = 0; j < this->Planes; ++j) + { + r = data[j]; + for (unsigned long f = this->Frames; f != 0; --f) + { + OFBitmanipTemplate::copyMem(OFstatic_cast(const T *, r), temp, count); // create temporary copy of current frame + p = temp; + r += count; + for (x = this->Dest_X; x != 0; --x) + { + q = r - x; + for (y = this->Dest_Y; y != 0; --y) + { + *q = *p++; + q -= this->Dest_X; + } + } + } + } + delete[] temp; + } + } + + /** rotate image right and store result in the same storage area + * + ** @param data array of pointers to source/destination image pixels + */ + inline void rotateRight(T *data[]) + { + const unsigned long count = OFstatic_cast(unsigned long, this->Dest_X) * OFstatic_cast(unsigned long, this->Dest_Y); + T *temp = new T[count]; + if (temp != NULL) + { + register Uint16 x; + register Uint16 y; + register const T *p; + register T *q; + register T *r; + for (int j = 0; j < this->Planes; ++j) + { + r = data[j]; + for (unsigned long f = this->Frames; f != 0; --f) + { + OFBitmanipTemplate::copyMem(OFstatic_cast(const T *, r), temp, count); // create temporary copy of current frame + p = temp; + for (x = this->Dest_X; x != 0; --x) + { + q = r + x - 1; + for (y = this->Dest_Y; y != 0; --y) + { + *q = *p++; + q += this->Dest_X; + } + } + r += count; + } + } + delete[] temp; + } + } + + /** rotate image top-down and store result in the same storage area + * + ** @param data array of pointers to source/destination image pixels + */ + inline void rotateTopDown(T *data[]) + { + register unsigned long i; + register T *p; + register T *q; + register T t; + T *s; + const unsigned long count = OFstatic_cast(unsigned long, this->Dest_X) * OFstatic_cast(unsigned long, this->Dest_Y); + for (int j = 0; j < this->Planes; ++j) + { + s = data[j]; + for (unsigned long f = this->Frames; f != 0; --f) + { + p = s; + q = s + count; + for (i = count / 2; i != 0; --i) + { + t = *p; + *p++ = *--q; + *q = t; + } + s += count; + } + } + } +}; + + +#endif diff --git a/dcmimgle/include/dcmtk/dcmimgle/discalet.h b/dcmimgle/include/dcmtk/dcmimgle/discalet.h new file mode 100644 index 00000000..762c13bf --- /dev/null +++ b/dcmimgle/include/dcmtk/dcmimgle/discalet.h @@ -0,0 +1,1239 @@ +/* + * + * Copyright (C) 1996-2015, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimgle + * + * Author: Joerg Riesmeier + * + * Purpose: DicomScaleTemplates (Header) + * + */ + + +#ifndef DISCALET_H +#define DISCALET_H + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/ofstd/ofcast.h" + +#include "dcmtk/dcmimgle/ditranst.h" +#include "dcmtk/dcmimgle/dipxrept.h" + + +/*---------------------* + * macro definitions * + *---------------------*/ + +#define SCALE_FACTOR 4096 +#define HALFSCALE_FACTOR 2048 + + +/*--------------------* + * helper functions * + *--------------------*/ + +// help function to set scaling values +static inline void setScaleValues(Uint16 data[], + const Uint16 min, + const Uint16 max) +{ + register Uint16 remainder = max % min; + Uint16 step0 = max / min; + Uint16 step1 = max / min; + if (remainder > OFstatic_cast(Uint16, min / 2)) + { + remainder = min - remainder; + ++step0; + } else + ++step1; + const double count = OFstatic_cast(double, min) / (OFstatic_cast(double, remainder) + 1); + register Uint16 i; + register double c = count; + for (i = 0; i < min; ++i) + { + if ((i >= OFstatic_cast(Uint16, c)) && (remainder > 0)) + { + --remainder; + c += count; + data[i] = step1; + } + else + data[i] = step0; + } +} + +// cubic value interpolation using Catmull-Rom formula. +// the interpolated pixel lies between the second and the third original pixels +static inline double cubicValue(const double v1, + const double v2, + const double v3, + const double v4, + const double dD, + const double minVal, + const double maxVal) +{ + double dVal = 0.5 * ((((-v1 + 3 * v2 - 3 * v3 + v4) * dD + (2 * v1 - 5 * v2 + 4 * v3 - v4)) * dD + (-v1 + v3)) * dD + (v2 + v2)); + return (dVal < minVal) ? minVal : ((dVal > maxVal) ? maxVal : dVal); +} + + +/*---------------------* + * class declaration * + *---------------------*/ + +/** Template class to scale images (on pixel data level). + * with and without interpolation + */ +template +class DiScaleTemplate + : public DiTransTemplate +{ + + public: + + /** constructor, scale clipping area. + * + ** @param planes number of planes (1 or 3) + * @param columns width of source image + * @param rows height of source image + * @param left_pos left coordinate of clipping area + * @param top_pos top coordinate of clipping area + * @param src_cols width of clipping area + * @param src_rows height of clipping area + * @param dest_cols width of destination image (scaled image) + * @param dest_rows height of destination image + * @param frames number of frames + * @param bits number of bits per plane/pixel + */ + DiScaleTemplate(const int planes, + const Uint16 columns, /* resolution of source image */ + const Uint16 rows, + const signed long left_pos, /* origin of clipping area */ + const signed long top_pos, + const Uint16 src_cols, /* extension of clipping area */ + const Uint16 src_rows, + const Uint16 dest_cols, /* extension of destination image */ + const Uint16 dest_rows, + const Uint32 frames, /* number of frames */ + const int bits = 0) + : DiTransTemplate(planes, src_cols, src_rows, dest_cols, dest_rows, frames, bits), + Left(left_pos), + Top(top_pos), + Columns(columns), + Rows(rows) + { + } + + /** constructor, scale whole image. + * + ** @param planes number of planes (1 or 3) + * @param src_cols width of source image + * @param src_rows height of source image + * @param dest_cols width of destination image (scaled image) + * @param dest_rows height of destination image + * @param frames number of frames + * @param bits number of bits per plane/pixel + */ + DiScaleTemplate(const int planes, + const Uint16 src_cols, /* resolution of source image */ + const Uint16 src_rows, + const Uint16 dest_cols, /* resolution of destination image */ + const Uint16 dest_rows, + const Uint32 frames, /* number of frames */ + const int bits = 0) + : DiTransTemplate(planes, src_cols, src_rows, dest_cols, dest_rows, frames, bits), + Left(0), + Top(0), + Columns(src_cols), + Rows(src_rows) + { + } + + /** destructor + */ + virtual ~DiScaleTemplate() + { + } + + /** check whether template type T is signed or not + * + ** @return true if signed, false otherwise + */ + inline int isSigned() const + { + const DiPixelRepresentationTemplate rep; + return rep.isSigned(); + } + + /** choose scaling/clipping algorithm depending on specified parameters. + * + ** @param src array of pointers to source image pixels + * @param dest array of pointers to destination image pixels + * @param interpolate preferred interpolation algorithm (0 = no interpolation, 1 = pbmplus algorithm, + * 2 = c't algorithm, 3 = bilinear magnification, 4 = bicubic magnification) + * @param value value to be set outside the image boundaries (used for clipping, default: 0) + */ + void scaleData(const T *src[], + T *dest[], + const int interpolate, + const T value = 0) + { + if ((src != NULL) && (dest != NULL)) + { + DCMIMGLE_TRACE("Col/Rows: " << Columns << " " << Rows << OFendl + << "Left/Top: " << Left << " " << Top << OFendl + << "Src X/Y: " << this->Src_X << " " << this->Src_Y << OFendl + << "Dest X/Y: " << this->Dest_X << " " << this->Dest_Y); + if ((Left + OFstatic_cast(signed long, this->Src_X) <= 0) || (Top + OFstatic_cast(signed long, this->Src_Y) <= 0) || + (Left >= OFstatic_cast(signed long, Columns)) || (Top >= OFstatic_cast(signed long, Rows))) + { // no image to be displayed + DCMIMGLE_DEBUG("clipping area is fully outside the image boundaries"); + this->fillPixel(dest, value); // ... fill bitmap + } + else if ((this->Src_X == this->Dest_X) && (this->Src_Y == this->Dest_Y)) // no scaling + { + if ((Left == 0) && (Top == 0) && (Columns == this->Src_X) && (Rows == this->Src_Y)) + this->copyPixel(src, dest); // copying + else if ((Left >= 0) && (OFstatic_cast(Uint16, Left + this->Src_X) <= Columns) && + (Top >= 0) && (OFstatic_cast(Uint16, Top + this->Src_Y) <= Rows)) + clipPixel(src, dest); // clipping + else + clipBorderPixel(src, dest, value); // clipping (with border) + } + else if ((interpolate == 1) && (this->Bits <= MAX_INTERPOLATION_BITS)) + interpolatePixel(src, dest); // interpolation (pbmplus) + else if ((interpolate == 4) && (this->Dest_X >= this->Src_X) && (this->Dest_Y >= this->Src_Y) && + (this->Src_X >= 3) && (this->Src_Y >= 3)) + bicubicPixel(src, dest); // bicubic magnification + else if ((interpolate >= 3) && (this->Dest_X >= this->Src_X) && (this->Dest_Y >= this->Src_Y) && + (this->Src_X >= 2) && (this->Src_Y >= 2)) + bilinearPixel(src, dest); // bilinear magnification + else if ((interpolate >= 1) && (this->Dest_X >= this->Src_X) && (this->Dest_Y >= this->Src_Y)) + expandPixel(src, dest); // interpolated expansion (c't) + else if ((interpolate >= 1) && (this->Src_X >= this->Dest_X) && (this->Src_Y >= this->Dest_Y)) + reducePixel(src, dest); // interpolated reduction (c't) + else if ((interpolate >= 1) && (this->Bits <= MAX_INTERPOLATION_BITS)) + interpolatePixel(src, dest); // interpolation (pbmplus), fallback + else if ((this->Dest_X % this->Src_X == 0) && (this->Dest_Y % this->Src_Y == 0)) + replicatePixel(src, dest); // replication + else if ((this->Src_X % this->Dest_X == 0) && (this->Src_Y % this->Dest_Y == 0)) + suppressPixel(src, dest); // suppression + else + scalePixel(src, dest); // general scaling + } + } + + protected: + + /// left coordinate of clipping area + const signed long Left; + /// top coordinate of clipping area + const signed long Top; + /// width of source image + const Uint16 Columns; + /// height of source image + const Uint16 Rows; + + + private: + + /** clip image to specified area (only inside image boundaries). + * This is an optimization of the more general method clipBorderPixel(). + * + ** @param src array of pointers to source image pixels + * @param dest array of pointers to destination image pixels + */ + void clipPixel(const T *src[], + T *dest[]) + { + DCMIMGLE_DEBUG("using clip image to specified area algorithm"); + const unsigned long x_feed = Columns - this->Src_X; + const unsigned long y_feed = OFstatic_cast(unsigned long, Rows - this->Src_Y) * OFstatic_cast(unsigned long, Columns); + register Uint16 x; + register Uint16 y; + register const T *p; + register T *q; + for (int j = 0; j < this->Planes; ++j) + { + p = src[j] + OFstatic_cast(unsigned long, Top) * OFstatic_cast(unsigned long, Columns) + Left; + q = dest[j]; + for (unsigned long f = this->Frames; f != 0; --f) + { + for (y = this->Dest_Y; y != 0; --y) + { + for (x = this->Dest_X; x != 0; --x) + *(q++) = *(p++); + p += x_feed; + } + p += y_feed; + } + } + } + + /** clip image to specified area and add a border if necessary + * + ** @param src array of pointers to source image pixels + * @param dest array of pointers to destination image pixels + * @param value value to be set outside the image boundaries + */ + void clipBorderPixel(const T *src[], + T *dest[], + const T value) + { + DCMIMGLE_DEBUG("using clip image to specified area and add border algorithm"); + const Uint16 s_left = (Left > 0) ? OFstatic_cast(Uint16, Left) : 0; + const Uint16 s_top = (Top > 0) ? OFstatic_cast(Uint16, Top) : 0; + const Uint16 d_left = (Left < 0 ? OFstatic_cast(Uint16, -Left) : 0); + const Uint16 d_top = (Top < 0) ? OFstatic_cast(Uint16, -Top) : 0; + const Uint16 d_right = (OFstatic_cast(unsigned long, this->Src_X) + OFstatic_cast(unsigned long, s_left) < + OFstatic_cast(unsigned long, Columns) + OFstatic_cast(unsigned long, d_left)) ? + (this->Src_X - 1) : (Columns + d_left - s_left - 1); + const Uint16 d_bottom = (OFstatic_cast(unsigned long, this->Src_Y) + OFstatic_cast(unsigned long, s_top) < + OFstatic_cast(unsigned long, Rows) + OFstatic_cast(unsigned long, d_top)) ? + (this->Src_Y - 1) : (Rows + d_top - s_top - 1); + const Uint16 x_count = d_right - d_left + 1; + const Uint16 y_count = d_bottom - d_top + 1; + const unsigned long s_start = OFstatic_cast(unsigned long, s_top) * OFstatic_cast(unsigned long, Columns) + s_left; + const unsigned long x_feed = Columns - x_count; + const unsigned long y_feed = OFstatic_cast(unsigned long, Rows - y_count) * Columns; + const unsigned long t_feed = OFstatic_cast(unsigned long, d_top) * OFstatic_cast(unsigned long, this->Src_X); + const unsigned long b_feed = OFstatic_cast(unsigned long, this->Src_Y - d_bottom - 1) * OFstatic_cast(unsigned long, this->Src_X); + + /* + * The approach is to divide the destination image in up to four areas outside the source image + * plus one area for the source image. The for and while loops are scanning linearly over the + * destination image and setting the appropriate value depending on the current area. This is + * different from most of the other algorithms in this toolkit where the source image is scanned + * linearly. + */ + register Uint16 x; + register Uint16 y; + register unsigned long i; + register const T *p; + register T *q; + for (int j = 0; j < this->Planes; ++j) + { + p = src[j] + s_start; + q = dest[j]; + for (unsigned long f = this->Frames; f != 0; --f) + { + for (i = t_feed; i != 0; --i) // top + *(q++) = value; + for (y = y_count; y != 0; --y) // middle part: + { + x = 0; + while (x < d_left) // - left + { + *(q++) = value; + ++x; + } + while (x <= d_right) // - middle + { + *(q++) = *(p++); + ++x; + } + while (x < this->Src_X) // - right + { + *(q++) = value; + ++x; + } + p += x_feed; + } + for (i = b_feed; i != 0; --i) // bottom + *(q++) = value; + p += y_feed; + } + } + } + + /** enlarge image by an integer factor. + * Pixels are replicated independently in both directions. + * + ** @param src array of pointers to source image pixels + * @param dest array of pointers to destination image pixels + */ + void replicatePixel(const T *src[], + T *dest[]) + { + DCMIMGLE_DEBUG("using replicate pixel scaling algorithm without interpolation"); + const Uint16 x_factor = this->Dest_X / this->Src_X; + const Uint16 y_factor = this->Dest_Y / this->Src_Y; + const unsigned long x_feed = Columns; + const unsigned long y_feed = OFstatic_cast(unsigned long, Rows - this->Src_Y) * OFstatic_cast(unsigned long, Columns); + const T *sp; + register Uint16 x; + register Uint16 y; + register Uint16 dx; + register Uint16 dy; + register const T *p; + register T *q; + register T value; + for (int j = 0; j < this->Planes; ++j) + { + sp = src[j] + OFstatic_cast(unsigned long, Top) * OFstatic_cast(unsigned long, Columns) + Left; + q = dest[j]; + for (unsigned long f = this->Frames; f != 0; --f) + { + for (y = this->Src_Y; y != 0; --y) + { + for (dy = y_factor; dy != 0; --dy) + { + for (x = this->Src_X, p = sp; x != 0; --x) + { + value = *(p++); + for (dx = x_factor; dx != 0; --dx) + *(q++) = value; + } + } + sp += x_feed; + } + sp += y_feed; + } + } + } + + /** shrink image by an integer divisor. + * Pixels are suppressed independently in both directions. + * + ** @param src array of pointers to source image pixels + * @param dest array of pointers to destination image pixels + */ + void suppressPixel(const T *src[], + T *dest[]) + { + DCMIMGLE_DEBUG("using suppress pixel scaling algorithm without interpolation"); + const unsigned int x_divisor = this->Src_X / this->Dest_X; + const unsigned long x_feed = OFstatic_cast(unsigned long, this->Src_Y / this->Dest_Y) * OFstatic_cast(unsigned long, Columns) - this->Src_X; + const unsigned long y_feed = OFstatic_cast(unsigned long, Rows - this->Src_Y) * OFstatic_cast(unsigned long, Columns); + register Uint16 x; + register Uint16 y; + register const T *p; + register T *q; + for (int j = 0; j < this->Planes; ++j) + { + p = src[j] + OFstatic_cast(unsigned long, Top) * OFstatic_cast(unsigned long, Columns) + Left; + q = dest[j]; + for (unsigned long f = this->Frames; f != 0; --f) + { + for (y = this->Dest_Y; y != 0; --y) + { + for (x = this->Dest_X; x != 0; --x) + { + *(q++) = *p; + p += x_divisor; + } + p += x_feed; + } + p += y_feed; + } + } + } + + /** free scaling method without interpolation. + * This algorithm is necessary for overlays (1 bpp). + * + ** @param src array of pointers to source image pixels + * @param dest array of pointers to destination image pixels + */ + void scalePixel(const T *src[], + T *dest[]) + { + DCMIMGLE_DEBUG("using free scaling algorithm without interpolation"); + const Uint16 xmin = (this->Dest_X < this->Src_X) ? this->Dest_X : this->Src_X; // minimum width + const Uint16 ymin = (this->Dest_Y < this->Src_Y) ? this->Dest_Y : this->Src_Y; // minimum height + Uint16 *x_step = new Uint16[xmin]; + Uint16 *y_step = new Uint16[ymin]; + Uint16 *x_fact = new Uint16[xmin]; + Uint16 *y_fact = new Uint16[ymin]; + + /* + * Approach: If one pixel line has to be added or removed it is taken from the middle of the image (1/2). + * For two lines it is at 1/3 and 2/3 of the image and so on. It sounds easy but it was a hard job ;-) + */ + + if ((x_step != NULL) && (y_step != NULL) && (x_fact != NULL) && (y_fact != NULL)) + { + register Uint16 x; + register Uint16 y; + if (this->Dest_X < this->Src_X) + setScaleValues(x_step, this->Dest_X, this->Src_X); + else if (this->Dest_X > this->Src_X) + setScaleValues(x_fact, this->Src_X, this->Dest_X); + if (this->Dest_X <= this->Src_X) + OFBitmanipTemplate::setMem(x_fact, 1, xmin); // initialize with default values + if (this->Dest_X >= this->Src_X) + OFBitmanipTemplate::setMem(x_step, 1, xmin); // initialize with default values + x_step[xmin - 1] += Columns - this->Src_X; // skip to next line + if (this->Dest_Y < this->Src_Y) + setScaleValues(y_step, this->Dest_Y, this->Src_Y); + else if (this->Dest_Y > this->Src_Y) + setScaleValues(y_fact, this->Src_Y, this->Dest_Y); + if (this->Dest_Y <= this->Src_Y) + OFBitmanipTemplate::setMem(y_fact, 1, ymin); // initialize with default values + if (this->Dest_Y >= this->Src_Y) + OFBitmanipTemplate::setMem(y_step, 1, ymin); // initialize with default values + y_step[ymin - 1] += Rows - this->Src_Y; // skip to next frame + const T *sp; + register Uint16 dx; + register Uint16 dy; + register const T *p; + register T *q; + register T value; + for (int j = 0; j < this->Planes; ++j) + { + sp = src[j] + OFstatic_cast(unsigned long, Top) * OFstatic_cast(unsigned long, Columns) + Left; + q = dest[j]; + for (unsigned long f = 0; f < this->Frames; ++f) + { + for (y = 0; y < ymin; ++y) + { + for (dy = 0; dy < y_fact[y]; ++dy) + { + for (x = 0, p = sp; x < xmin; ++x) + { + value = *p; + for (dx = 0; dx < x_fact[x]; ++dx) + *(q++) = value; + p += x_step[x]; + } + } + sp += OFstatic_cast(unsigned long, y_step[y]) * OFstatic_cast(unsigned long, Columns); + } + } + } + } + delete[] x_step; + delete[] y_step; + delete[] x_fact; + delete[] y_fact; + } + + + /** free scaling method with interpolation + * + ** @param src array of pointers to source image pixels + * @param dest array of pointers to destination image pixels + */ + void interpolatePixel(const T *src[], + T *dest[]) + { + DCMIMGLE_DEBUG("using scaling algorithm with interpolation from pbmplus toolkit"); + if ((this->Src_X != Columns) || (this->Src_Y != Rows)) + { + DCMIMGLE_ERROR("interpolated scaling and clipping at the same time not implemented ... ignoring clipping region"); + this->Src_X = Columns; // temporarily removed 'const' for 'Src_X' in class 'DiTransTemplate' + this->Src_Y = Rows; // ... 'Src_Y' ... + } + + /* + * based on scaling algorithm from "Extended Portable Bitmap Toolkit" (pbmplus10dec91) + * (adapted to be used with signed pixel representation, inverse images - mono1, + * various bit depths, multi-frame and multi-plane/color images) + */ + + register Uint16 x; + register Uint16 y; + register const T *p; + register T *q; + const T *sp = NULL; // initialization avoids compiler warning + const T *fp; + T *sq; + + const unsigned long sxscale = OFstatic_cast(unsigned long, (OFstatic_cast(double, this->Dest_X) / OFstatic_cast(double, this->Src_X)) * SCALE_FACTOR); + const unsigned long syscale = OFstatic_cast(unsigned long, (OFstatic_cast(double, this->Dest_Y) / OFstatic_cast(double, this->Src_Y)) * SCALE_FACTOR); + const signed long maxvalue = DicomImageClass::maxval(this->Bits - isSigned()); + + T *xtemp = new T[this->Src_X]; + signed long *xvalue = new signed long[this->Src_X]; + + if ((xtemp == NULL) || (xvalue == NULL)) + { + DCMIMGLE_ERROR("can't allocate temporary buffers for interpolation scaling"); + this->clearPixel(dest); + } else { + for (int j = 0; j < this->Planes; ++j) + { + fp = src[j]; + sq = dest[j]; + for (unsigned long f = this->Frames; f != 0; --f) + { + for (x = 0; x < this->Src_X; ++x) + xvalue[x] = HALFSCALE_FACTOR; + register unsigned long yfill = SCALE_FACTOR; + register unsigned long yleft = syscale; + register int yneed = 1; + int ysrc = 0; + for (y = 0; y < this->Dest_Y; ++y) + { + if (this->Src_Y == this->Dest_Y) + { + sp = fp; + for (x = this->Src_X, p = sp, q = xtemp; x != 0; --x) + *(q++) = *(p++); + fp += this->Src_X; + } + else + { + while (yleft < yfill) + { + if (yneed && (ysrc < OFstatic_cast(int, this->Src_Y))) + { + sp = fp; + fp += this->Src_X; + ++ysrc; + } + for (x = 0, p = sp; x < this->Src_X; ++x) + xvalue[x] += yleft * OFstatic_cast(signed long, *(p++)); + yfill -= yleft; + yleft = syscale; + yneed = 1; + } + if (yneed && (ysrc < OFstatic_cast(int, this->Src_Y))) + { + sp = fp; + fp += this->Src_X; + ++ysrc; + yneed = 0; + } + register signed long v; + for (x = 0, p = sp, q = xtemp; x < this->Src_X; ++x) + { + v = xvalue[x] + yfill * OFstatic_cast(signed long, *(p++)); + v /= SCALE_FACTOR; + *(q++) = OFstatic_cast(T, (v > maxvalue) ? maxvalue : v); + xvalue[x] = HALFSCALE_FACTOR; + } + yleft -= yfill; + if (yleft == 0) + { + yleft = syscale; + yneed = 1; + } + yfill = SCALE_FACTOR; + } + if (this->Src_X == this->Dest_X) + { + for (x = this->Dest_X, p = xtemp, q = sq; x != 0; --x) + *(q++) = *(p++); + sq += this->Dest_X; + } + else + { + register signed long v = HALFSCALE_FACTOR; + register unsigned long xfill = SCALE_FACTOR; + register unsigned long xleft; + register int xneed = 0; + q = sq; + for (x = 0, p = xtemp; x < this->Src_X; ++x, ++p) + { + xleft = sxscale; + while (xleft >= xfill) + { + if (xneed) + { + ++q; + v = HALFSCALE_FACTOR; + } + v += xfill * OFstatic_cast(signed long, *p); + v /= SCALE_FACTOR; + *q = OFstatic_cast(T, (v > maxvalue) ? maxvalue : v); + xleft -= xfill; + xfill = SCALE_FACTOR; + xneed = 1; + } + if (xleft > 0) + { + if (xneed) + { + ++q; + v = HALFSCALE_FACTOR; + xneed = 0; + } + v += xleft * OFstatic_cast(signed long, *p); + xfill -= xleft; + } + } + if (xfill > 0) + v += xfill * OFstatic_cast(signed long, *(--p)); + if (!xneed) + { + v /= SCALE_FACTOR; + *q = OFstatic_cast(T, (v > maxvalue) ? maxvalue : v); + } + sq += this->Dest_X; + } + } + } + } + } + delete[] xtemp; + delete[] xvalue; + } + + + /** free scaling method with interpolation (only for magnification) + * + ** @param src array of pointers to source image pixels + * @param dest array of pointers to destination image pixels + */ + void expandPixel(const T *src[], + T *dest[]) + { + DCMIMGLE_DEBUG("using expand pixel scaling algorithm with interpolation from c't magazine"); + const double x_factor = OFstatic_cast(double, this->Src_X) / OFstatic_cast(double, this->Dest_X); + const double y_factor = OFstatic_cast(double, this->Src_Y) / OFstatic_cast(double, this->Dest_Y); + const unsigned long f_size = OFstatic_cast(unsigned long, Rows) * OFstatic_cast(unsigned long, Columns); + const T *sp; + double bx, ex; + double by, ey; + int bxi, exi; + int byi, eyi; + unsigned long offset; + double value, sum; + double x_part, y_part; + double l_factor, r_factor; + double t_factor, b_factor; + register int xi; + register int yi; + register Uint16 x; + register Uint16 y; + register const T *p; + register T *q; + + /* + * based on scaling algorithm from "c't - Magazin fuer Computertechnik" (c't 11/94) + * (adapted to be used with signed pixel representation, inverse images - mono1, + * various bit depths, multi-frame and multi-plane/color images, combined clipping/scaling) + */ + + for (int j = 0; j < this->Planes; ++j) + { + sp = src[j] + OFstatic_cast(unsigned long, Top) * OFstatic_cast(unsigned long, Columns) + Left; + q = dest[j]; + for (unsigned long f = 0; f < this->Frames; ++f) + { + for (y = 0; y < this->Dest_Y; ++y) + { + by = y_factor * OFstatic_cast(double, y); + ey = y_factor * (OFstatic_cast(double, y) + 1.0); + if (ey > this->Src_Y) + { +#ifdef DEBUG // this output is only useful for debugging purposes + DCMIMGLE_TRACE(" limiting value of 'ey' to 'Src_Y': " << ey << " -> " << this->Src_Y); +#endif + // see reducePixel() + ey = this->Src_Y; + } + byi = OFstatic_cast(int, by); + eyi = OFstatic_cast(int, ey); + if (OFstatic_cast(double, eyi) == ey) + { +#ifdef DEBUG // this output is only useful for debugging purposes + DCMIMGLE_TRACE(" decreasing value of 'eyi' by 1: " << eyi << " -> " << (eyi - 1)); +#endif + --eyi; + } + y_part = OFstatic_cast(double, eyi) / y_factor; + b_factor = y_part - OFstatic_cast(double, y); + t_factor = (OFstatic_cast(double, y) + 1.0) - y_part; + for (x = 0; x < this->Dest_X; ++x) + { + value = 0; + bx = x_factor * OFstatic_cast(double, x); + ex = x_factor * (OFstatic_cast(double, x) + 1.0); + if (ex > this->Src_X) + { +#ifdef DEBUG // this output is only useful for debugging purposes + DCMIMGLE_TRACE(" limiting value of 'ex' to 'Src_X': " << ex << " -> " << this->Src_X); +#endif + // see reducePixel() + ex = this->Src_X; + } + bxi = OFstatic_cast(int, bx); + exi = OFstatic_cast(int, ex); + if (OFstatic_cast(double, exi) == ex) + { +#ifdef DEBUG // this output is only useful for debugging purposes + DCMIMGLE_TRACE(" decreasing value of 'exi' by 1: " << exi << " -> " << (exi - 1)); +#endif + --exi; + } + x_part = OFstatic_cast(double, exi) / x_factor; + l_factor = x_part - OFstatic_cast(double, x); + r_factor = (OFstatic_cast(double, x) + 1.0) - x_part; + offset = OFstatic_cast(unsigned long, byi) * OFstatic_cast(unsigned long, Columns); + for (yi = byi; yi <= eyi; ++yi) + { + p = sp + offset + bxi; + for (xi = bxi; xi <= exi; ++xi) + { + sum = OFstatic_cast(double, *(p++)); + if (bxi != exi) + { + if (xi == bxi) + sum *= l_factor; + else + sum *= r_factor; + } + if (byi != eyi) + { + if (yi == byi) + sum *= b_factor; + else + sum *= t_factor; + } + value += sum; + } + offset += Columns; + } + *(q++) = OFstatic_cast(T, value + 0.5); + } + } + sp += f_size; + } + } + } + + + /** free scaling method with interpolation (only for reduction) + * + ** @param src array of pointers to source image pixels + * @param dest array of pointers to destination image pixels + */ + void reducePixel(const T *src[], + T *dest[]) + { + DCMIMGLE_DEBUG("using reduce pixel scaling algorithm with interpolation from c't magazine"); + const double x_factor = OFstatic_cast(double, this->Src_X) / OFstatic_cast(double, this->Dest_X); + const double y_factor = OFstatic_cast(double, this->Src_Y) / OFstatic_cast(double, this->Dest_Y); + const double xy_factor = x_factor * y_factor; + const unsigned long f_size = OFstatic_cast(unsigned long, Rows) * OFstatic_cast(unsigned long, Columns); + const T *sp; + double bx, ex; + double by, ey; + int bxi, exi; + int byi, eyi; + unsigned long offset; + double value, sum; + double l_factor, r_factor; + double t_factor, b_factor; + register int xi; + register int yi; + register Uint16 x; + register Uint16 y; + register const T *p; + register T *q; + + /* + * based on scaling algorithm from "c't - Magazin fuer Computertechnik" (c't 11/94) + * (adapted to be used with signed pixel representation, inverse images - mono1, + * various bit depths, multi-frame and multi-plane/color images, combined clipping/scaling) + */ + + for (int j = 0; j < this->Planes; ++j) + { + sp = src[j] + OFstatic_cast(unsigned long, Top) * OFstatic_cast(unsigned long, Columns) + Left; + q = dest[j]; + for (unsigned long f = 0; f < this->Frames; ++f) + { + for (y = 0; y < this->Dest_Y; ++y) + { + by = y_factor * OFstatic_cast(double, y); + ey = y_factor * (OFstatic_cast(double, y) + 1.0); + if (ey > this->Src_Y) + { +#ifdef DEBUG // this output is only useful for debugging purposes + DCMIMGLE_TRACE(" limiting value of 'ey' to 'Src_Y': " << ey << " -> " << this->Src_Y); +#endif + // yes, this can happen due to rounding, e.g. double(943) / double(471) * double(471) + // is something like 943.00000000000011368683772161602974 and then, the eyi == ey check + // fails to bring eyi back into range! + ey = this->Src_Y; + } + byi = OFstatic_cast(int, by); + eyi = OFstatic_cast(int, ey); + if (OFstatic_cast(double, eyi) == ey) + { +#ifdef DEBUG // this output is only useful for debugging purposes + DCMIMGLE_TRACE(" decreasing value of 'eyi' by 1: " << eyi << " -> " << (eyi - 1)); +#endif + --eyi; + } + b_factor = 1 + OFstatic_cast(double, byi) - by; + t_factor = ey - OFstatic_cast(double, eyi); + for (x = 0; x < this->Dest_X; ++x) + { + value = 0; + bx = x_factor * OFstatic_cast(double, x); + ex = x_factor * (OFstatic_cast(double, x) + 1.0); + if (ex > this->Src_X) + { +#ifdef DEBUG // this output is only useful for debugging purposes + DCMIMGLE_TRACE(" limiting value of 'ex' to 'Src_X': " << ex << " -> " << this->Src_X); +#endif + // see above comment + ex = this->Src_X; + } + bxi = OFstatic_cast(int, bx); + exi = OFstatic_cast(int, ex); + if (OFstatic_cast(double, exi) == ex) + { +#ifdef DEBUG // this output is only useful for debugging purposes + DCMIMGLE_TRACE(" decreasing value of 'exi' by 1: " << exi << " -> " << (exi - 1)); +#endif + --exi; + } + l_factor = 1 + OFstatic_cast(double, bxi) - bx; + r_factor = ex - OFstatic_cast(double, exi); + offset = OFstatic_cast(unsigned long, byi) * OFstatic_cast(unsigned long, Columns); + for (yi = byi; yi <= eyi; ++yi) + { + p = sp + offset + bxi; + for (xi = bxi; xi <= exi; ++xi) + { + sum = OFstatic_cast(double, *(p++)) / xy_factor; + if (xi == bxi) + sum *= l_factor; + else if (xi == exi) + sum *= r_factor; + if (yi == byi) + sum *= b_factor; + else if (yi == eyi) + sum *= t_factor; + value += sum; + } + offset += Columns; + } + *(q++) = OFstatic_cast(T, value + 0.5); + } + } + sp += f_size; + } + } + } + + /** bilinear interpolation method (only for magnification) + * + ** @param src array of pointers to source image pixels + * @param dest array of pointers to destination image pixels + */ + void bilinearPixel(const T *src[], + T *dest[]) + { + DCMIMGLE_DEBUG("using magnification algorithm with bilinear interpolation contributed by Eduard Stanescu"); + const double x_factor = OFstatic_cast(double, this->Src_X) / OFstatic_cast(double, this->Dest_X); + const double y_factor = OFstatic_cast(double, this->Src_Y) / OFstatic_cast(double, this->Dest_Y); + const unsigned long f_size = OFstatic_cast(unsigned long, Rows) * OFstatic_cast(unsigned long, Columns); + const unsigned long l_offset = OFstatic_cast(unsigned long, this->Src_Y - 1) * OFstatic_cast(unsigned long, this->Dest_X); + register Uint16 x; + register Uint16 y; + register T *pD; + register T *pCurrTemp; + register const T *pCurrSrc; + Uint16 nSrcIndex; + double dOff; + T *pT; + const T *pS; + const T *pF; + + // buffer used for storing temporarily the interpolated lines + T *pTemp = new T[OFstatic_cast(unsigned long, this->Src_Y) * OFstatic_cast(unsigned long, this->Dest_X)]; + if (pTemp == NULL) + { + DCMIMGLE_ERROR("can't allocate temporary buffer for interpolation scaling"); + this->clearPixel(dest); + } else { + + /* + * based on scaling algorithm contributed by Eduard Stanescu + * (adapted to be used with signed pixel representation, inverse images - mono1, + * various bit depths, multi-frame multi-plane/color images, combined clipping/scaling) + */ + + for (int j = 0; j < this->Planes; ++j) + { + pF = src[j] + OFstatic_cast(unsigned long, Top) * OFstatic_cast(unsigned long, Columns) + Left; + pD = dest[j]; + for (unsigned long f = this->Frames; f != 0; --f) + { + pT = pCurrTemp = pTemp; + pS = pCurrSrc = pF; + // first, interpolate the columns: + // column 0, just copy the source data column 0 + for (y = this->Src_Y; y != 0; --y) + { + *(pCurrTemp) = *(pCurrSrc); + pCurrSrc += Columns; + pCurrTemp += this->Dest_X; + } + pCurrSrc = pS; + nSrcIndex = 0; + // column 1 to column Dest_X - 1 + for (x = 1; x < this->Dest_X - 1; ++x) + { + pCurrTemp = ++pT; + dOff = x * x_factor - nSrcIndex; + dOff = (1.0 < dOff) ? 1.0 : dOff; + for (y = 0; y < this->Src_Y; ++y) + { + // use floating points in order to avoid possible integer overflow + const double v1 = OFstatic_cast(double, *(pCurrSrc)); + const double v2 = OFstatic_cast(double, *(pCurrSrc + 1)); + *(pCurrTemp) = OFstatic_cast(T, v1 + (v2 - v1) * dOff); + pCurrSrc += Columns; + pCurrTemp += this->Dest_X; + } + // don't go beyond the source data + if ((nSrcIndex < this->Src_X - 2) && (x * x_factor >= nSrcIndex + 1)) + { + pS++; + nSrcIndex++; + } + pCurrSrc = pS; + } + pCurrTemp = ++pT; + // last column, just copy the source data column Src_X + for (y = this->Src_Y; y != 0; --y) + { + *(pCurrTemp) = *(pCurrSrc); + pCurrSrc += Columns; + pCurrTemp += this->Dest_X; + } + // now the columns are interpolated in temp buffer, so interpolate the lines + pT = pCurrTemp = pTemp; + // line 0, just copy the temp buffer line 0 + for (x = this->Dest_X; x != 0; --x) + *(pD++) = *(pCurrTemp++); + nSrcIndex = 0; + pCurrTemp = pTemp; + for (y = 1; y < this->Dest_Y - 1; ++y) + { + dOff = y * y_factor - nSrcIndex; + dOff = (1.0 < dOff) ? 1.0 : dOff; + for (x = this->Dest_X; x != 0; --x) + { + // use floating points in order to avoid possible integer overflow + const double v1 = OFstatic_cast(double, *(pCurrTemp)); + const double v2 = OFstatic_cast(double, *(pCurrTemp + this->Dest_X)); + *(pD++) = OFstatic_cast(T, v1 + (v2 - v1) * dOff); + pCurrTemp++; + } + // don't go beyond the source data + if ((nSrcIndex < this->Src_Y - 2) && (y * y_factor >= nSrcIndex + 1)) + { + pT += this->Dest_X; + nSrcIndex++; + } + pCurrTemp = pT; + } + // the last line, just copy the temp buffer line Src_X + pCurrTemp = pTemp + l_offset; + for (x = this->Dest_X; x != 0; --x) + *(pD++) = *(pCurrTemp++); + // skip to next frame + pF += f_size; + } + } + } + delete[] pTemp; + } + + /** bicubic interpolation method (only for magnification) + * + ** @param src array of pointers to source image pixels + * @param dest array of pointers to destination image pixels + */ + void bicubicPixel(const T *src[], + T *dest[]) + { + DCMIMGLE_DEBUG("using magnification algorithm with bicubic interpolation contributed by Eduard Stanescu"); + const double minVal = (isSigned()) ? -OFstatic_cast(double, DicomImageClass::maxval(this->Bits - 1, 0)) : 0.0; + const double maxVal = OFstatic_cast(double, DicomImageClass::maxval(this->Bits - isSigned())); + const double x_factor = OFstatic_cast(double, this->Src_X) / OFstatic_cast(double, this->Dest_X); + const double y_factor = OFstatic_cast(double, this->Src_Y) / OFstatic_cast(double, this->Dest_Y); + const Uint16 xDelta = OFstatic_cast(Uint16, 1 / x_factor); + const Uint16 yDelta = OFstatic_cast(Uint16, 1 / y_factor); + const unsigned long f_size = OFstatic_cast(unsigned long, Rows) * OFstatic_cast(unsigned long, Columns); + const unsigned long l_offset = OFstatic_cast(unsigned long, this->Src_Y - 1) * OFstatic_cast(unsigned long, this->Dest_X); + register Uint16 x; + register Uint16 y; + register T *pD; + register T *pCurrTemp; + register const T *pCurrSrc; + Uint16 nSrcIndex; + double dOff; + T *pT; + const T *pS; + const T *pF; + + // buffer used for storing temporarily the interpolated lines + T *pTemp = pT = pCurrTemp = new T[OFstatic_cast(unsigned long, this->Src_Y) * OFstatic_cast(unsigned long, this->Dest_X)]; + if (pTemp == NULL) + { + DCMIMGLE_ERROR("can't allocate temporary buffer for interpolation scaling"); + this->clearPixel(dest); + } else { + + /* + * based on scaling algorithm contributed by Eduard Stanescu + * (adapted to be used with signed pixel representation, inverse images - mono1, + * various bit depths, multi-frame multi-plane/color images, combined clipping/scaling) + */ + + for (int j = 0; j < this->Planes; ++j) + { + pF = src[j] + OFstatic_cast(unsigned long, Top) * OFstatic_cast(unsigned long, Columns) + Left; + pD = dest[j]; + for (unsigned long f = this->Frames; f != 0; --f) + { + pT = pCurrTemp = pTemp; + pS = pCurrSrc = pF; + // first, interpolate the columns: + // column 0, just copy the source data column 0 + for (y = this->Src_Y; y != 0; --y) + { + *(pCurrTemp) = *(pCurrSrc); + pCurrSrc += Columns; + pCurrTemp += this->Dest_X; + } + pCurrSrc = pS; + // for the next few columns, linear interpolation + for (x = 1; x < xDelta + 1; ++x) + { + pCurrSrc = pS; + pCurrTemp = ++pT; + dOff = x * x_factor; + dOff = (1.0 < dOff) ? 1.0 : dOff; + for (y = this->Src_Y; y != 0; --y) + { + *(pCurrTemp) = OFstatic_cast(T, *(pCurrSrc) + (*(pCurrSrc + 1) - *(pCurrSrc)) * dOff); + pCurrSrc += Columns; + pCurrTemp += this->Dest_X; + } + } + nSrcIndex = 1; + pCurrSrc = ++pS; + // the majority of the columns + for (x = xDelta + 1; x < this->Dest_X - 2 * xDelta; ++x) + { + pCurrTemp = ++pT; + dOff = x * x_factor - nSrcIndex; + dOff = (1.0 < dOff) ? 1.0 : dOff; + for (y = this->Src_Y; y != 0; --y) + { + *(pCurrTemp) = OFstatic_cast(T, cubicValue(*(pCurrSrc - 1), *(pCurrSrc), *(pCurrSrc + 1), *(pCurrSrc + 2), dOff, minVal, maxVal)); + pCurrSrc += Columns; + pCurrTemp += this->Dest_X; + } + // don't go beyond the source data + if ((nSrcIndex < this->Src_X - 3) && (x * x_factor >= nSrcIndex + 1)) + { + pS++; + nSrcIndex++; + } + pCurrSrc = pS; + } + // last few columns except the very last one, linear interpolation + for (x = this->Dest_X - 2 * xDelta; x < this->Dest_X - 1; ++x) + { + pCurrTemp = ++pT; + dOff = x * x_factor - nSrcIndex; + dOff = (1.0 < dOff) ? 1.0 : dOff; + for (y = this->Src_Y; y != 0; --y) + { + *(pCurrTemp) = OFstatic_cast(T, *(pCurrSrc) + (*(pCurrSrc + 1) - *(pCurrSrc)) * dOff); + pCurrSrc += Columns; + pCurrTemp += this->Dest_X; + } + // don't go beyond the source data + if ((nSrcIndex < this->Src_X - 2) && (x * x_factor >= nSrcIndex + 1)) + { + pS++; + nSrcIndex++; + } + pCurrSrc = pS; + } + // last column, just copy the source data column Src_X + pCurrTemp = pTemp + this->Dest_X - 1; + pCurrSrc = pF + this->Src_X - 1; + for (y = this->Src_Y; y != 0; --y) + { + *(pCurrTemp) = *(pCurrSrc); + pCurrSrc += Columns; + pCurrTemp += this->Dest_X; + } + // now the columns are interpolated in temp buffer, so interpolate the lines + pT = pCurrTemp = pTemp; + // line 0, just copy the temp buffer line 0 + for (x = this->Dest_X; x != 0; --x) + *(pD++) = *(pCurrTemp++); + // for the next few lines, linear interpolation between line 0 and 1 of the temp buffer + for (y = 1; y < yDelta + 1; ++y) + { + pCurrTemp = pTemp; + dOff = y * y_factor; + dOff = (1.0 < dOff) ? 1.0 : dOff; + for (x = this->Dest_X; x != 0; --x) + { + *(pD++) = OFstatic_cast(T, *(pCurrTemp) + (*(pCurrTemp + this->Dest_X) - *(pCurrTemp)) * dOff); + pCurrTemp++; + } + } + nSrcIndex = 1; + pCurrTemp = pT = pTemp + this->Dest_X; + for (y = yDelta + 1; y < this->Dest_Y - yDelta - 1; ++y) + { + dOff = y * y_factor - nSrcIndex; + dOff = (1.0 < dOff) ? 1.0 : dOff; + for (x = this->Dest_X; x != 0; --x) + { + *(pD++) = OFstatic_cast(T, cubicValue(*(pCurrTemp - this->Dest_X),*(pCurrTemp), *(pCurrTemp + this->Dest_X), + *(pCurrTemp + this->Dest_X + this->Dest_X), dOff, minVal, maxVal)); + pCurrTemp++; + } + // don't go beyond the source data + if ((nSrcIndex < this->Src_Y - 3) && (y * y_factor >= nSrcIndex + 1)) + { + pT += this->Dest_X; + nSrcIndex++; + } + pCurrTemp = pT; + } + // the last few lines except the very last one, linear interpolation in between the second last and the last lines + pCurrTemp = pT = pTemp + OFstatic_cast(unsigned long, this->Src_Y - 2) * OFstatic_cast(unsigned long, this->Dest_X); + for (y = this->Dest_Y - yDelta - 1; y < this->Dest_Y - 1; ++y) + { + dOff = y * y_factor - nSrcIndex; + dOff = (1.0 < dOff) ? 1.0 : dOff; + for (x = this->Dest_X; x != 0; --x) + { + *(pD++) = OFstatic_cast(T, *(pCurrTemp) + (*(pCurrTemp + this->Dest_X) - *(pCurrTemp)) * dOff); + pCurrTemp++; + } + pCurrTemp = pT; + } + // the the last line, just copy the temp buffer line Src_X + pCurrTemp = pTemp + l_offset; + for (x = this->Dest_X; x != 0; --x) + *(pD++) = *(pCurrTemp++); + // skip to next frame + pF += f_size; + } + } + } + delete[] pTemp; + } +}; + +#endif diff --git a/dcmimgle/include/dcmtk/dcmimgle/displint.h b/dcmimgle/include/dcmtk/dcmimgle/displint.h new file mode 100644 index 00000000..2b2aba1e --- /dev/null +++ b/dcmimgle/include/dcmtk/dcmimgle/displint.h @@ -0,0 +1,187 @@ +/* + * + * Copyright (C) 1996-2010, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimgle + * + * Author: Joerg Riesmeier + * + * Purpose: DiCubicSpline Function/Interpolation (Header/Implementation) + * + */ + + +#ifndef DISPLINT_H +#define DISPLINT_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/ofstd/ofcast.h" + +#define INCLUDE_CSTDDEF /* For NULL */ +#include "dcmtk/ofstd/ofstdinc.h" + + +/*--------------------* + * macro definition * + *--------------------*/ + +// SunCC 4.x does not support default values for template types :-/ +#define T3_ double + + +/*------------------* + * template class * + *------------------*/ + +/** Template class for cubic spline interpolation + */ +template +class DiCubicSpline +{ + + public: + + /** calculate spline function for given points. + * T1 = type of x coordinates + * T2 = type of y coordinates + * T3_ = type of y coordinates of the spline function + * + ** @param x array with x coordinates of given points + * @param y array with y coordinates of given points + * @param n number of entries in array (= points) + * @param y2 array used to store the resulting spline function (used for CubicSplineInterpolation) + * @param yp1 first derivative of the interpolating function at point 1 + * @param ypn first derivative of the interpolating function at point n + * + ** @return true if successful, false otherwise + */ + static int Function(const T1 *x, + const T2 *y, + const unsigned int n, + T3_ *y2, + const T3_ yp1 = 1.0e30, + const T3_ ypn = 1.0e30) + { + if ((x != NULL) && (y != NULL) && (n > 0) && (y2 != NULL)) + { + T3_ *u = new T3_[n]; // temporary vector + if (u != NULL) + { + register unsigned int i; + T3_ p, qn, sig, un; + if (yp1 > 0.99e30) // ignore value for first derivative at point 1 + y2[0] = u[0] = 0.0; + else + { + y2[0] = -0.5; + u[0] = (3.0 / (OFstatic_cast(T3_, x[1]) - OFstatic_cast(T3_, x[0]))) * + ((OFstatic_cast(T3_, y[1]) - OFstatic_cast(T3_, y[0])) / + (OFstatic_cast(T3_, x[1]) - OFstatic_cast(T3_, x[0])) - yp1); + } + for (i = 1; i < n - 1; ++i) + { + sig = (OFstatic_cast(T3_, x[i]) - OFstatic_cast(T3_, x[i - 1])) / + (OFstatic_cast(T3_, x[i + 1]) - OFstatic_cast(T3_, x[i - 1])); + p = sig * y2[i - 1] + 2.0; + y2[i] = (sig - 1.0) / p; + u[i] = (OFstatic_cast(T3_, y[i + 1]) - OFstatic_cast(T3_, y[i])) / + (OFstatic_cast(T3_, x[i + 1]) - OFstatic_cast(T3_, x[i])) - + (OFstatic_cast(T3_, y[i]) - OFstatic_cast(T3_, y[i - 1])) / + (OFstatic_cast(T3_, x[i]) - OFstatic_cast(T3_, x[i - 1])); + u[i] = (6.0 * u[i] / (OFstatic_cast(T3_, x[i + 1]) - + OFstatic_cast(T3_, x[i - 1])) - sig * u[i - 1]) / p; + } + if (ypn > 0.99e30) // ignore value for first derivative at point 1 + qn = un = 0.0; + else + { + qn = 0.5; + un = (3.0 / (OFstatic_cast(T3_, x[n - 1]) - OFstatic_cast(T3_, x[n - 2]))) * + (ypn - (OFstatic_cast(T3_, y[n - 1]) - OFstatic_cast(T3_, y[n - 2])) / + (OFstatic_cast(T3_, x[n - 1]) - OFstatic_cast(T3_, x[n - 2]))); + } + y2[n - 1] = (un - qn * u[n - 2]) / (qn * y2[n - 2] + 1.0); + for (i = n - 1; i > 0; --i) + y2[i - 1] = y2[i - 1] * y2[i] + u[i - 1]; + delete[] u; + return 1; + } + } + return 0; + } + + + /** perform cubic spline interpolation for given points. + * T1 = type of x coordinates + * T2 = type of y coordinates + * T3_ = type of y coordinates of the spline function + * + ** @param xa array with x coordinates of given points + * @param ya array with y coordinates of given points + * @param y2a array used to store the resulting spline function (calculated by CubicSplineFunction) + * @param na number of entries in above arrays (xa, ya and y2a) + * @param x array with x coordinates of points to be interpolated + * @param y array used to store interpolated values + * @param n number of entries in above array (x and y) + * + ** @return true if successful, false otherwise + */ + static int Interpolation(const T1 *xa, + const T2 *ya, + const T3_ *y2a, + const unsigned int na, + const T1 *x, + T2 *y, + const unsigned int n) + { + if ((xa != NULL) && (ya != NULL) && (y2a != NULL) && (na > 0) && (x != NULL) && (y != NULL) && (n > 0)) + { + register unsigned int k, i; + register unsigned int klo = 0; + register unsigned int khi = na - 1; + T3_ h, b, a; + for (i = 0; i < n; ++i) + { + if ((xa[klo] > x[i]) || (xa[khi] < x[i])) // optimization + { + klo = 0; + khi = na - 1; + } + while (khi - klo > 1) // search right place in the table, if necessary + { + k = (khi + klo) >> 1; + if (xa[k] > x[i]) + khi = k; + else + klo = k; + } + if (xa[khi] == x[i]) // optimization: use known values + y[i] = ya[khi]; + else + { + h = OFstatic_cast(T3_, xa[khi]) - OFstatic_cast(T3_, xa[klo]); + if (h == 0.0) // bad xa input, values must be distinct ! + return 0; + a = (OFstatic_cast(T3_, xa[khi]) - OFstatic_cast(T3_, x[i])) / h; + b = (OFstatic_cast(T3_, x[i]) - OFstatic_cast(T3_, xa[klo])) / h; + y[i] = OFstatic_cast(T2, a * OFstatic_cast(T3_, ya[klo]) + b * OFstatic_cast(T3_, ya[khi]) + + ((a * a * a - a) * y2a[klo] + (b * b * b - b) * y2a[khi]) * (h * h) / 6.0); + } + } + return 1; + } + return 0; + } +}; + + +#endif diff --git a/dcmimgle/include/dcmtk/dcmimgle/ditranst.h b/dcmimgle/include/dcmtk/dcmimgle/ditranst.h new file mode 100644 index 00000000..fd29ea6f --- /dev/null +++ b/dcmimgle/include/dcmtk/dcmimgle/ditranst.h @@ -0,0 +1,138 @@ +/* + * + * Copyright (C) 1996-2010, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimgle + * + * Author: Joerg Riesmeier + * + * Purpose: DicomTransTemplate (Header) + * + */ + + +#ifndef DITRANST_H +#define DITRANST_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/ofstd/oftypes.h" +#include "dcmtk/ofstd/ofcast.h" + +#include "dcmtk/ofstd/ofbmanip.h" + +#include "dcmtk/dcmimgle/diutils.h" + + +/*---------------------* + * class declaration * + *---------------------*/ + +/** Template class building the base for other transformations. + * (e.g. scaling, flipping) + */ +template +class DiTransTemplate +{ + + protected: + + /** constructor + * + ** @param planes number of planes + * @param src_x width of source image + * @param src_y height of source image + * @param dest_x width of destination image (after transformation) + * @param dest_y height of destination image + * @param frames number of frames + * @param bits number of bits per plane/pixel (optional) + */ + DiTransTemplate(const int planes, + const Uint16 src_x, + const Uint16 src_y, + const Uint16 dest_x, + const Uint16 dest_y, + const Uint32 frames, + const int bits = 0) + : Planes(planes), + Src_X(src_x), + Src_Y(src_y), + Dest_X(dest_x), + Dest_Y(dest_y), + Frames(frames), + Bits(((bits < 1) || (bits > OFstatic_cast(int, bitsof(T)))) ? OFstatic_cast(int, bitsof(T)) : bits) + { + } + + /** destructor + */ + virtual ~DiTransTemplate() + { + } + + /** copy pixel data + * + ** @param src array of pointers to source image pixels + * @param dest array of pointers to destination image pixels + */ + inline void copyPixel(const T *src[], + T *dest[]) + { + const unsigned long count = OFstatic_cast(unsigned long, Dest_X) * OFstatic_cast(unsigned long, Dest_Y) * Frames; + for (int j = 0; j < Planes; ++j) + OFBitmanipTemplate::copyMem(src[j], dest[j], count); + } + + /** fill pixel data with specified value + * + ** @param dest array of pointers to destination image pixels + * @param value value to be filled in destination array + */ + inline void fillPixel(T *dest[], + const T value) + { + const unsigned long count = OFstatic_cast(unsigned long, Dest_X) * OFstatic_cast(unsigned long, Dest_Y) * Frames; + for (int j = 0; j < Planes; ++j) + OFBitmanipTemplate::setMem(dest[j], value, count); + } + + /** clear pixel data (set values to 0) + * + ** @param dest array of pointers to destination image pixels + */ + inline void clearPixel(T *dest[]) + { + const unsigned long count = OFstatic_cast(unsigned long, Dest_X) * OFstatic_cast(unsigned long, Dest_Y) * Frames; + for (int j = 0; j < Planes; ++j) + OFBitmanipTemplate::zeroMem(dest[j], count); + } + + + /// number of planes + /*const*/ int Planes; // allow later changing to avoid warnings on Irix + + /// width of source image + /*const*/ Uint16 Src_X; // add 'const' when interpolated scaling with clipping is fully implemented + /// height of source image + /*const*/ Uint16 Src_Y; // ... dito ... + /// width of destination image + const Uint16 Dest_X; + /// height of destination image + const Uint16 Dest_Y; + + /// number of frames + const Uint32 Frames; + /// number of bits per plane/pixel + const int Bits; +}; + + +#endif diff --git a/dcmimgle/include/dcmtk/dcmimgle/diutils.h b/dcmimgle/include/dcmtk/dcmimgle/diutils.h new file mode 100644 index 00000000..598fdb1a --- /dev/null +++ b/dcmimgle/include/dcmtk/dcmimgle/diutils.h @@ -0,0 +1,444 @@ +/* + * + * Copyright (C) 1996-2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimgle + * + * Author: Joerg Riesmeier + * + * Purpose: Utilities (Header) + * + */ + + +#ifndef DIUTILS_H +#define DIUTILS_H + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/ofstd/oftypes.h" +#include "dcmtk/ofstd/ofcast.h" + +#include "dcmtk/oflog/oflog.h" + +#include "dcmtk/dcmimgle/didefine.h" + +extern DCMTK_DCMIMGLE_EXPORT OFLogger DCM_dcmimgleLogger; + +#define DCMIMGLE_TRACE(msg) OFLOG_TRACE(DCM_dcmimgleLogger, msg) +#define DCMIMGLE_DEBUG(msg) OFLOG_DEBUG(DCM_dcmimgleLogger, msg) +#define DCMIMGLE_INFO(msg) OFLOG_INFO(DCM_dcmimgleLogger, msg) +#define DCMIMGLE_WARN(msg) OFLOG_WARN(DCM_dcmimgleLogger, msg) +#define DCMIMGLE_ERROR(msg) OFLOG_ERROR(DCM_dcmimgleLogger, msg) +#define DCMIMGLE_FATAL(msg) OFLOG_FATAL(DCM_dcmimgleLogger, msg) + + +// include this file in doxygen documentation + +/** @file diutils.h + * @brief utilities for the dcmimgle/dcmimage module + */ + + +/*---------------------* + * const definitions * + *---------------------*/ + +/** @name configuration flags + */ + +//@{ + +/// compatibility with old ACR-NEMA images +const unsigned long CIF_AcrNemaCompatibility = 0x0000001; + +/// accept wrong palette attribute tags +const unsigned long CIF_WrongPaletteAttributeTags = 0x0000002; + +/// element pixel data may be detached if it is no longer needed by DicomImage +const unsigned long CIF_MayDetachPixelData = 0x0000004; + +/// use presentation state instead of 'built-in' LUTs & overlays +const unsigned long CIF_UsePresentationState = 0x0000008; + +/// don't convert YCbCr (Full and Full 4:2:2) color images to RGB +const unsigned long CIF_KeepYCbCrColorModel = 0x0000010; + +/// take responsibility for the given external DICOM dataset, i.e. delete it on destruction +const unsigned long CIF_TakeOverExternalDataset = 0x0000020; + +/// ignore modality transformation (rescale slope/intercept or LUT) stored in the dataset +const unsigned long CIF_IgnoreModalityTransformation = 0x0000040; + +/// ignore third value of the modality LUT descriptor, determine bit depth automatically +const unsigned long CIF_IgnoreModalityLutBitDepth = 0x0000080; + +/// check third value of the LUT descriptor, compare with with expected bit depth based on LUT data +const unsigned long CIF_CheckLutBitDepth = 0x0000100; + +/// use absolute (possible) pixel range for determining the internal representation (monochrome only) +const unsigned long CIF_UseAbsolutePixelRange = 0x0000200; + +/// use partial access to pixel data, i.e. without decompressing or loading a complete multi-frame image. +/// Please note that the use of this flag can cause another copy of the pixel data to be created in memory, +/// e.g. in case the pixel data element value has already been loaded or decompressed completely in memory. +const unsigned long CIF_UsePartialAccessToPixelData = 0x0000400; + +/// always decompress complete pixel data when processing an image, i.e. even if partial access is used +const unsigned long CIF_DecompressCompletePixelData = 0x0000800; + +/// never access embedded overlays since this requires to load and uncompress the complete pixel data +const unsigned long CIF_NeverAccessEmbeddedOverlays = 0x0001000; +//@} + + +// / true color color mode (for monochrome images only) +const int MI_PastelColor = -1; + + +/*--------------------* + * type definitions * + *--------------------*/ + +/** constants for photometric interpretation + */ +enum EP_Interpretation +{ + /// unknown, undefined, invalid + EPI_Unknown, + /// no element value available + EPI_Missing, + /// monochrome 1 + EPI_Monochrome1, + /// monochrome 2 + EPI_Monochrome2, + /// palette color + EPI_PaletteColor, + /// RGB color + EPI_RGB, + /// HSV color (retired) + EPI_HSV, + /// ARGB color (retired) + EPI_ARGB, + /// CMYK color (retired) + EPI_CMYK, + /// YCbCr full + EPI_YBR_Full, + /// YCbCr full 4:2:2 + EPI_YBR_Full_422, + /// YCbCr partial 4:2:2 + EPI_YBR_Partial_422 +}; + + +/** structure for photometric string and related constant + */ +struct DCMTK_DCMIMGLE_EXPORT SP_Interpretation +{ + /// string (name of the color model without spaces and underscores) + const char *Name; + /// defined term according to the DICOM standard + const char *DefinedTerm; + /// integer constant + EP_Interpretation Type; +}; + + +/** structure for BMP bitmap file header + */ +struct DCMTK_DCMIMGLE_EXPORT SB_BitmapFileHeader +{ + /// signature, must always be 'BM' + char bfType[2]; + /// file size in bytes + Uint32 bfSize; + /// reserved, should be '0' + Uint16 bfReserved1; + /// reserved, should be '0' + Uint16 bfReserved2; + /// offset from the beginning of the file to the bitmap data (in bytes) + Uint32 bfOffBits; +}; + + +/** structure for BMP bitmap info header + */ +struct DCMTK_DCMIMGLE_EXPORT SB_BitmapInfoHeader +{ + /// size of the BitmapInfoHeader, usually '40' + Uint32 biSize; + /// width of the image (in pixels) + Sint32 biWidth; + /// height of the image (in pixels) + Sint32 biHeight; + /// number of planes, usually '1' + Uint16 biPlanes; + /// bits per pixel, supported values: 8 = color palette with 256 entries, 24 = true color + Uint16 biBitCount; + /// type of compression, support value: 0 = BI_RGB, no compression + Uint32 biCompression; + /// size of the image data (in bytes), might be set to '0' if image is uncompressed + Uint32 biSizeImage; + /// horizontal resolution: pixels/meter, usually set to '0' + Sint32 biXPelsPerMeter; + /// vertical resolution: pixels/meter, usually set to '0' + Sint32 biYPelsPerMeter; + /// number of actually used colors, if '0' the number of colors is calculated using 'biBitCount' + Uint32 biClrUsed; + /// number of important colors, '0' means all + Uint32 biClrImportant; +}; + + +/** internal representation of pixel data + */ +enum EP_Representation +{ + /// unsigned 8 bit integer + EPR_Uint8, EPR_MinUnsigned = EPR_Uint8, + /// signed 8 bit integer + EPR_Sint8, EPR_MinSigned = EPR_Sint8, + /// unsigned 16 bit integer + EPR_Uint16, + /// signed 16 bit integer + EPR_Sint16, + /// unsigned 32 bit integer + EPR_Uint32, EPR_MaxUnsigned = EPR_Uint32, + /// signed 32 bit integer + EPR_Sint32, EPR_MaxSigned = EPR_Sint32 +}; + + +/** image status code + */ +enum EI_Status +{ + /// normal, no error + EIS_Normal, + /// data dictionary not found + EIS_NoDataDictionary, + /// invalid dataset/file + EIS_InvalidDocument, + /// mandatory attribute missing + EIS_MissingAttribute, + /// invalid value for an important attribute + EIS_InvalidValue, + /// specified value for an attribute not supported + EIS_NotSupportedValue, + /// memory exhausted etc. + EIS_MemoryFailure, + /// invalid image, internal error + EIS_InvalidImage, + /// other error + EIS_OtherError +}; + + +/** overlay modes. + * This mode is used to define how to display an overlay plane. + */ +enum EM_Overlay +{ + /// default mode, as stored in the dataset + EMO_Default, + /// replace mode + EMO_Replace, + /// graphics overlay + EMO_Graphic = EMO_Replace, + /// threshold replace + EMO_ThresholdReplace, + /// complement + EMO_Complement, + /// invert the overlay bitmap + EMO_InvertBitmap, + /// region of interest (ROI) + EMO_RegionOfInterest, + /// bitmap shutter, used for GSPS objects + EMO_BitmapShutter +}; + + +/** VOI LUT functions + */ +enum EF_VoiLutFunction +{ + /// default function (not explicitly set) + EFV_Default, + /// function LINEAR + EFV_Linear, + /// function SIGMOID + EFV_Sigmoid +}; + + +/** presentation LUT shapes + */ +enum ES_PresentationLut +{ + /// default shape (not explicitly set) + ESP_Default, + /// shape IDENTITY + ESP_Identity, + /// shape INVERSE + ESP_Inverse, + /// shape LIN OD + ESP_LinOD +}; + + +/** polarity + */ +enum EP_Polarity +{ + /// NORMAL + EPP_Normal, + /// REVERSE (opposite polarity) + EPP_Reverse +}; + + +/** bits per table entry modes. + * Specifies whether the given value in the LUT descriptor is used. + */ +enum EL_BitsPerTableEntry +{ + /// use given value + ELM_UseValue, + /// ignore given value, use auto detection + ELM_IgnoreValue, + /// check whether given value is consistent with LUT data + ELM_CheckValue +}; + + +/*----------------------------* + * constant initializations * + *----------------------------*/ + +const SP_Interpretation PhotometricInterpretationNames[] = +{ + {"MONOCHROME1", "MONOCHROME1", EPI_Monochrome1}, + {"MONOCHROME2", "MONOCHROME2", EPI_Monochrome2}, + {"PALETTECOLOR", "PALETTE COLOR", EPI_PaletteColor}, // space deleted to simplify detection + {"RGB", "RGB", EPI_RGB}, + {"HSV", "HSV", EPI_HSV}, + {"ARGB", "ARGB", EPI_ARGB}, + {"CMYK", "CMYK", EPI_CMYK}, + {"YBRFULL", "YBR_FULL", EPI_YBR_Full}, // underscore deleted to simplify detection + {"YBRFULL422", "YBR_FULL_422", EPI_YBR_Full_422}, // underscores deleted to simplify detection + {"YBRPARTIAL422", "YBR_PARTIAL_422", EPI_YBR_Partial_422}, // underscores deleted to simplify detection + {NULL, NULL, EPI_Unknown} +}; + + +/*---------------------* + * macro definitions * + *---------------------*/ + +#define MAX_UINT Uint32 +#define MAX_SINT Sint32 + +#define MAX_BITS 32 +#define MAX_BITS_TYPE Uint32 +#define MAX_RAWPPM_BITS 8 +#define MAX_INTERPOLATION_BITS 16 + +#define bitsof(expr) (sizeof(expr) << 3) + + +/*----------------------* + * class declarations * + *----------------------*/ + +/** Class comprising several global functions and constants. + * introduced to avoid problems with naming convention + */ +class DCMTK_DCMIMGLE_EXPORT DicomImageClass +{ + + public: + + /** calculate maximum value which could be stored in the specified number of bits + * + ** @param mv_bits number of bits + * @param mv_pos value subtracted from the maximum value (0 or 1) + * + ** @return maximum value + */ + static inline unsigned long maxval(const int mv_bits, + const unsigned long mv_pos = 1) + { + return (mv_bits < MAX_BITS) ? + (OFstatic_cast(unsigned long, 1) << mv_bits) - mv_pos : OFstatic_cast(MAX_BITS_TYPE, -1); + } + + /** calculate number of bits which are necessary to store the specified value + * + ** @param tb_value value to be stored + * @param tb_pos value subtracted from the value (0 or 1) before converting + * + ** @return number of bits + */ + static inline unsigned int tobits(unsigned long tb_value, + const unsigned long tb_pos = 1) + { + if (tb_value > 0) + tb_value -= tb_pos; + register unsigned int tb_bits = 0; + while (tb_value > 0) + { + ++tb_bits; + tb_value >>= 1; + } + return tb_bits; + } + + /** calculate number of bits which are necessary to store the specified value range + * + ** @param minvalue minimum value to be stored + * @param maxvalue maximum value to be stored + * + ** @return number of bits + */ + static unsigned int rangeToBits(double minvalue, + double maxvalue); + + /** determine whether integer representation is signed or unsigned + * + ** @param repres integer representation (enum) to be checked + * + ** @return true if representation is signed, false if unsigned + */ + static int isRepresentationSigned(EP_Representation repres); + + /** determine number of bits used for a particular integer representation + * + ** @param repres integer representation (enum) to be checked + * + ** @return number of bits + */ + static unsigned int getRepresentationBits(EP_Representation repres); + + /** determine integer representation which is necessary to store values in the specified range + * + ** @param minvalue minimum value to be stored + * @param maxvalue maximum value to be stored + * + ** @return integer representation (enum) + */ + static EP_Representation determineRepresentation(double minvalue, + double maxvalue); + +}; + + +#endif diff --git a/dcmimgle/libsrc/CMakeLists.txt b/dcmimgle/libsrc/CMakeLists.txt new file mode 100644 index 00000000..2d264806 --- /dev/null +++ b/dcmimgle/libsrc/CMakeLists.txt @@ -0,0 +1,4 @@ +# create library from source files +DCMTK_ADD_LIBRARY(dcmimgle dcmimage dibaslut diciefn dicielut didislut didispfn didocu digsdfn digsdlut diimage diinpx diluptab dimo1img dimo2img dimoimg dimoimg3 dimoimg4 dimoimg5 dimomod dimoopx dimopx diovdat diovlay diovlimg diovpln diutils) + +DCMTK_TARGET_LINK_MODULES(dcmimgle ofstd oflog dcmdata) diff --git a/dcmimgle/libsrc/Makefile.dep b/dcmimgle/libsrc/Makefile.dep new file mode 100644 index 00000000..2e925c4a --- /dev/null +++ b/dcmimgle/libsrc/Makefile.dep @@ -0,0 +1,1530 @@ +dcmimage.o: dcmimage.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \ + ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ + ../include/dcmtk/dcmimgle/dcmimage.h ../include/dcmtk/dcmimgle/dimoimg.h \ + ../include/dcmtk/dcmimgle/diimage.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ + ../include/dcmtk/dcmimgle/diovlay.h ../include/dcmtk/dcmimgle/diobjcou.h \ + ../include/dcmtk/dcmimgle/didefine.h ../include/dcmtk/dcmimgle/diovdat.h \ + ../include/dcmtk/dcmimgle/diovpln.h ../include/dcmtk/dcmimgle/diutils.h \ + ../include/dcmtk/dcmimgle/dimopx.h ../include/dcmtk/dcmimgle/dipixel.h \ + ../include/dcmtk/dcmimgle/dimomod.h ../include/dcmtk/dcmimgle/diluptab.h \ + ../include/dcmtk/dcmimgle/dibaslut.h ../include/dcmtk/dcmimgle/dimoopx.h \ + ../include/dcmtk/dcmimgle/didispfn.h \ + ../include/dcmtk/dcmimgle/diovlimg.h \ + ../include/dcmtk/dcmimgle/dimo2img.h \ + ../include/dcmtk/dcmimgle/dimo1img.h ../include/dcmtk/dcmimgle/didocu.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../include/dcmtk/dcmimgle/diregbas.h \ + ../include/dcmtk/dcmimgle/diplugin.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicent.h +dibaslut.o: dibaslut.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmimgle/dibaslut.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../include/dcmtk/dcmimgle/diutils.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../include/dcmtk/dcmimgle/didefine.h +diciefn.o: diciefn.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmimgle/diciefn.h ../include/dcmtk/dcmimgle/didispfn.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../include/dcmtk/dcmimgle/didefine.h \ + ../include/dcmtk/dcmimgle/dicielut.h \ + ../include/dcmtk/dcmimgle/didislut.h \ + ../include/dcmtk/dcmimgle/dibaslut.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../include/dcmtk/dcmimgle/diutils.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h +dicielut.o: dicielut.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmimgle/dicielut.h \ + ../include/dcmtk/dcmimgle/didislut.h \ + ../include/dcmtk/dcmimgle/dibaslut.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../include/dcmtk/dcmimgle/diutils.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../include/dcmtk/dcmimgle/didefine.h +didislut.o: didislut.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmimgle/didislut.h \ + ../include/dcmtk/dcmimgle/dibaslut.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../include/dcmtk/dcmimgle/diutils.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../include/dcmtk/dcmimgle/didefine.h +didispfn.o: didispfn.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../ofstd/include/dcmtk/ofstd/ofbmanip.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../include/dcmtk/dcmimgle/didispfn.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../include/dcmtk/dcmimgle/didefine.h \ + ../include/dcmtk/dcmimgle/displint.h \ + ../include/dcmtk/dcmimgle/dicrvfit.h \ + ../include/dcmtk/dcmimgle/didislut.h \ + ../include/dcmtk/dcmimgle/dibaslut.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../include/dcmtk/dcmimgle/diutils.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h +didocu.o: didocu.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcostrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicent.h \ + ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcmetinf.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicdir.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdirrec.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrulup.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrul.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixseq.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcofsetl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrae.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvras.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrda.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrds.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrdt.h \ + ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvris.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrtm.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrur.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcchrstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlt.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpn.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsh.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrst.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvruc.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrut.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixel.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpobw.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcovlay.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrat.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrss.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrus.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfd.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrof.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrod.h \ + ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ + ../include/dcmtk/dcmimgle/didocu.h ../include/dcmtk/dcmimgle/diobjcou.h \ + ../include/dcmtk/dcmimgle/didefine.h ../include/dcmtk/dcmimgle/diutils.h +digsdfn.o: digsdfn.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmimgle/digsdfn.h ../include/dcmtk/dcmimgle/didispfn.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../include/dcmtk/dcmimgle/didefine.h \ + ../include/dcmtk/dcmimgle/displint.h \ + ../include/dcmtk/dcmimgle/digsdlut.h \ + ../include/dcmtk/dcmimgle/didislut.h \ + ../include/dcmtk/dcmimgle/dibaslut.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../include/dcmtk/dcmimgle/diutils.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h +digsdlut.o: digsdlut.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmimgle/digsdlut.h \ + ../include/dcmtk/dcmimgle/didislut.h \ + ../include/dcmtk/dcmimgle/dibaslut.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../include/dcmtk/dcmimgle/diutils.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../include/dcmtk/dcmimgle/didefine.h \ + ../include/dcmtk/dcmimgle/displint.h +diimage.o: diimage.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ + ../include/dcmtk/dcmimgle/diimage.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ + ../include/dcmtk/dcmimgle/diovlay.h ../include/dcmtk/dcmimgle/diobjcou.h \ + ../include/dcmtk/dcmimgle/didefine.h ../include/dcmtk/dcmimgle/diovdat.h \ + ../include/dcmtk/dcmimgle/diovpln.h ../include/dcmtk/dcmimgle/diutils.h \ + ../include/dcmtk/dcmimgle/diinpxt.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixel.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpobw.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../ofstd/include/dcmtk/ofstd/ofbmanip.h \ + ../include/dcmtk/dcmimgle/diinpx.h ../include/dcmtk/dcmimgle/didocu.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../include/dcmtk/dcmimgle/dipxrept.h +diinpx.o: diinpx.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmimgle/diinpx.h ../include/dcmtk/dcmimgle/diutils.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../include/dcmtk/dcmimgle/didefine.h +diluptab.o: diluptab.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrus.h \ + ../../ofstd/include/dcmtk/ofstd/ofbmanip.h \ + ../include/dcmtk/dcmimgle/diluptab.h \ + ../include/dcmtk/dcmimgle/dibaslut.h ../include/dcmtk/dcmimgle/diutils.h \ + ../include/dcmtk/dcmimgle/didefine.h \ + ../include/dcmtk/dcmimgle/diobjcou.h ../include/dcmtk/dcmimgle/didocu.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h +dimo1img.o: dimo1img.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../include/dcmtk/dcmimgle/dimo1img.h ../include/dcmtk/dcmimgle/dimoimg.h \ + ../include/dcmtk/dcmimgle/diimage.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ + ../include/dcmtk/dcmimgle/diovlay.h ../include/dcmtk/dcmimgle/diobjcou.h \ + ../include/dcmtk/dcmimgle/didefine.h ../include/dcmtk/dcmimgle/diovdat.h \ + ../include/dcmtk/dcmimgle/diovpln.h ../include/dcmtk/dcmimgle/diutils.h \ + ../include/dcmtk/dcmimgle/dimopx.h ../include/dcmtk/dcmimgle/dipixel.h \ + ../include/dcmtk/dcmimgle/dimomod.h ../include/dcmtk/dcmimgle/diluptab.h \ + ../include/dcmtk/dcmimgle/dibaslut.h ../include/dcmtk/dcmimgle/dimoopx.h \ + ../include/dcmtk/dcmimgle/didispfn.h +dimo2img.o: dimo2img.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../include/dcmtk/dcmimgle/dimo2img.h ../include/dcmtk/dcmimgle/dimoimg.h \ + ../include/dcmtk/dcmimgle/diimage.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ + ../include/dcmtk/dcmimgle/diovlay.h ../include/dcmtk/dcmimgle/diobjcou.h \ + ../include/dcmtk/dcmimgle/didefine.h ../include/dcmtk/dcmimgle/diovdat.h \ + ../include/dcmtk/dcmimgle/diovpln.h ../include/dcmtk/dcmimgle/diutils.h \ + ../include/dcmtk/dcmimgle/dimopx.h ../include/dcmtk/dcmimgle/dipixel.h \ + ../include/dcmtk/dcmimgle/dimomod.h ../include/dcmtk/dcmimgle/diluptab.h \ + ../include/dcmtk/dcmimgle/dibaslut.h ../include/dcmtk/dcmimgle/dimoopx.h \ + ../include/dcmtk/dcmimgle/didispfn.h +dimoimg.o: dimoimg.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../include/dcmtk/dcmimgle/dimoimg.h ../include/dcmtk/dcmimgle/diimage.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ + ../include/dcmtk/dcmimgle/diovlay.h ../include/dcmtk/dcmimgle/diobjcou.h \ + ../include/dcmtk/dcmimgle/didefine.h ../include/dcmtk/dcmimgle/diovdat.h \ + ../include/dcmtk/dcmimgle/diovpln.h ../include/dcmtk/dcmimgle/diutils.h \ + ../include/dcmtk/dcmimgle/dimopx.h ../include/dcmtk/dcmimgle/dipixel.h \ + ../include/dcmtk/dcmimgle/dimomod.h ../include/dcmtk/dcmimgle/diluptab.h \ + ../include/dcmtk/dcmimgle/dibaslut.h ../include/dcmtk/dcmimgle/dimoopx.h \ + ../include/dcmtk/dcmimgle/didispfn.h \ + ../include/dcmtk/dcmimgle/dimo2img.h \ + ../include/dcmtk/dcmimgle/dimoipxt.h \ + ../../ofstd/include/dcmtk/ofstd/ofbmanip.h \ + ../include/dcmtk/dcmimgle/dimopxt.h ../include/dcmtk/dcmimgle/dipxrept.h \ + ../include/dcmtk/dcmimgle/diinpx.h ../include/dcmtk/dcmimgle/dimocpt.h \ + ../include/dcmtk/dcmimgle/dimosct.h ../include/dcmtk/dcmimgle/discalet.h \ + ../include/dcmtk/dcmimgle/ditranst.h ../include/dcmtk/dcmimgle/dimoflt.h \ + ../include/dcmtk/dcmimgle/diflipt.h ../include/dcmtk/dcmimgle/dimorot.h \ + ../include/dcmtk/dcmimgle/dirotat.h ../include/dcmtk/dcmimgle/dimoopxt.h \ + ../include/dcmtk/dcmimgle/didislut.h ../include/dcmtk/dcmimgle/digsdfn.h \ + ../include/dcmtk/dcmimgle/didocu.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../include/dcmtk/dcmimgle/diregbas.h +dimoimg3.o: dimoimg3.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmimgle/dimoimg.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../include/dcmtk/dcmimgle/diimage.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ + ../include/dcmtk/dcmimgle/diovlay.h ../include/dcmtk/dcmimgle/diobjcou.h \ + ../include/dcmtk/dcmimgle/didefine.h ../include/dcmtk/dcmimgle/diovdat.h \ + ../include/dcmtk/dcmimgle/diovpln.h ../include/dcmtk/dcmimgle/diutils.h \ + ../include/dcmtk/dcmimgle/dimopx.h ../include/dcmtk/dcmimgle/dipixel.h \ + ../include/dcmtk/dcmimgle/dimomod.h ../include/dcmtk/dcmimgle/diluptab.h \ + ../include/dcmtk/dcmimgle/dibaslut.h ../include/dcmtk/dcmimgle/dimoopx.h \ + ../include/dcmtk/dcmimgle/didispfn.h \ + ../include/dcmtk/dcmimgle/dimoipxt.h \ + ../../ofstd/include/dcmtk/ofstd/ofbmanip.h \ + ../include/dcmtk/dcmimgle/dimopxt.h ../include/dcmtk/dcmimgle/dipxrept.h \ + ../include/dcmtk/dcmimgle/diinpx.h ../include/dcmtk/dcmimgle/dimoopxt.h \ + ../include/dcmtk/dcmimgle/didislut.h +dimoimg4.o: dimoimg4.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmimgle/dimoimg.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../include/dcmtk/dcmimgle/diimage.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ + ../include/dcmtk/dcmimgle/diovlay.h ../include/dcmtk/dcmimgle/diobjcou.h \ + ../include/dcmtk/dcmimgle/didefine.h ../include/dcmtk/dcmimgle/diovdat.h \ + ../include/dcmtk/dcmimgle/diovpln.h ../include/dcmtk/dcmimgle/diutils.h \ + ../include/dcmtk/dcmimgle/dimopx.h ../include/dcmtk/dcmimgle/dipixel.h \ + ../include/dcmtk/dcmimgle/dimomod.h ../include/dcmtk/dcmimgle/diluptab.h \ + ../include/dcmtk/dcmimgle/dibaslut.h ../include/dcmtk/dcmimgle/dimoopx.h \ + ../include/dcmtk/dcmimgle/didispfn.h \ + ../include/dcmtk/dcmimgle/dimoipxt.h \ + ../../ofstd/include/dcmtk/ofstd/ofbmanip.h \ + ../include/dcmtk/dcmimgle/dimopxt.h ../include/dcmtk/dcmimgle/dipxrept.h \ + ../include/dcmtk/dcmimgle/diinpx.h ../include/dcmtk/dcmimgle/dimoopxt.h \ + ../include/dcmtk/dcmimgle/didislut.h +dimoimg5.o: dimoimg5.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmimgle/dimoimg.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../include/dcmtk/dcmimgle/diimage.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ + ../include/dcmtk/dcmimgle/diovlay.h ../include/dcmtk/dcmimgle/diobjcou.h \ + ../include/dcmtk/dcmimgle/didefine.h ../include/dcmtk/dcmimgle/diovdat.h \ + ../include/dcmtk/dcmimgle/diovpln.h ../include/dcmtk/dcmimgle/diutils.h \ + ../include/dcmtk/dcmimgle/dimopx.h ../include/dcmtk/dcmimgle/dipixel.h \ + ../include/dcmtk/dcmimgle/dimomod.h ../include/dcmtk/dcmimgle/diluptab.h \ + ../include/dcmtk/dcmimgle/dibaslut.h ../include/dcmtk/dcmimgle/dimoopx.h \ + ../include/dcmtk/dcmimgle/didispfn.h \ + ../include/dcmtk/dcmimgle/dimoipxt.h \ + ../../ofstd/include/dcmtk/ofstd/ofbmanip.h \ + ../include/dcmtk/dcmimgle/dimopxt.h ../include/dcmtk/dcmimgle/dipxrept.h \ + ../include/dcmtk/dcmimgle/diinpx.h ../include/dcmtk/dcmimgle/dimoopxt.h \ + ../include/dcmtk/dcmimgle/didislut.h +dimomod.o: dimomod.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ + ../include/dcmtk/dcmimgle/dimomod.h ../include/dcmtk/dcmimgle/diluptab.h \ + ../include/dcmtk/dcmimgle/dibaslut.h ../include/dcmtk/dcmimgle/diutils.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../include/dcmtk/dcmimgle/didefine.h \ + ../include/dcmtk/dcmimgle/diobjcou.h ../include/dcmtk/dcmimgle/didocu.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../include/dcmtk/dcmimgle/diinpx.h +dimoopx.o: dimoopx.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmimgle/dimoopx.h ../include/dcmtk/dcmimgle/diutils.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../include/dcmtk/dcmimgle/didefine.h ../include/dcmtk/dcmimgle/dimopx.h \ + ../include/dcmtk/dcmimgle/dipixel.h ../include/dcmtk/dcmimgle/dimomod.h \ + ../include/dcmtk/dcmimgle/diluptab.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../include/dcmtk/dcmimgle/dibaslut.h \ + ../include/dcmtk/dcmimgle/diobjcou.h +dimopx.o: dimopx.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmimgle/dimopx.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../include/dcmtk/dcmimgle/dipixel.h ../include/dcmtk/dcmimgle/diutils.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../include/dcmtk/dcmimgle/didefine.h ../include/dcmtk/dcmimgle/dimomod.h \ + ../include/dcmtk/dcmimgle/diluptab.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../include/dcmtk/dcmimgle/dibaslut.h \ + ../include/dcmtk/dcmimgle/diobjcou.h ../include/dcmtk/dcmimgle/diinpx.h \ + ../include/dcmtk/dcmimgle/dimoopx.h +diovdat.o: diovdat.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../include/dcmtk/dcmimgle/diovlay.h ../include/dcmtk/dcmimgle/diobjcou.h \ + ../include/dcmtk/dcmimgle/didefine.h ../include/dcmtk/dcmimgle/diovdat.h \ + ../include/dcmtk/dcmimgle/diovpln.h ../include/dcmtk/dcmimgle/diutils.h \ + ../../ofstd/include/dcmtk/ofstd/ofbmanip.h +diovlay.o: diovlay.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../include/dcmtk/dcmimgle/diovlay.h ../include/dcmtk/dcmimgle/diobjcou.h \ + ../include/dcmtk/dcmimgle/didefine.h ../include/dcmtk/dcmimgle/diovdat.h \ + ../include/dcmtk/dcmimgle/diovpln.h ../include/dcmtk/dcmimgle/diutils.h \ + ../include/dcmtk/dcmimgle/discalet.h \ + ../include/dcmtk/dcmimgle/ditranst.h \ + ../../ofstd/include/dcmtk/ofstd/ofbmanip.h \ + ../include/dcmtk/dcmimgle/dipxrept.h ../include/dcmtk/dcmimgle/diflipt.h \ + ../include/dcmtk/dcmimgle/dipixel.h ../include/dcmtk/dcmimgle/dirotat.h \ + ../include/dcmtk/dcmimgle/didocu.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h +diovlimg.o: diovlimg.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../include/dcmtk/dcmimgle/diovlimg.h \ + ../include/dcmtk/dcmimgle/dimo2img.h ../include/dcmtk/dcmimgle/dimoimg.h \ + ../include/dcmtk/dcmimgle/diimage.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ + ../include/dcmtk/dcmimgle/diovlay.h ../include/dcmtk/dcmimgle/diobjcou.h \ + ../include/dcmtk/dcmimgle/didefine.h ../include/dcmtk/dcmimgle/diovdat.h \ + ../include/dcmtk/dcmimgle/diovpln.h ../include/dcmtk/dcmimgle/diutils.h \ + ../include/dcmtk/dcmimgle/dimopx.h ../include/dcmtk/dcmimgle/dipixel.h \ + ../include/dcmtk/dcmimgle/dimomod.h ../include/dcmtk/dcmimgle/diluptab.h \ + ../include/dcmtk/dcmimgle/dibaslut.h ../include/dcmtk/dcmimgle/dimoopx.h \ + ../include/dcmtk/dcmimgle/didispfn.h ../include/dcmtk/dcmimgle/dimopxt.h \ + ../../ofstd/include/dcmtk/ofstd/ofbmanip.h \ + ../include/dcmtk/dcmimgle/dipxrept.h ../include/dcmtk/dcmimgle/didocu.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h +diovpln.o: diovpln.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixel.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpobw.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../ofstd/include/dcmtk/ofstd/ofbmanip.h \ + ../include/dcmtk/dcmimgle/diovpln.h ../include/dcmtk/dcmimgle/diutils.h \ + ../include/dcmtk/dcmimgle/didefine.h ../include/dcmtk/dcmimgle/didocu.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../include/dcmtk/dcmimgle/diobjcou.h +diutils.o: diutils.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../include/dcmtk/dcmimgle/diutils.h ../include/dcmtk/dcmimgle/didefine.h diff --git a/dcmimgle/libsrc/Makefile.in b/dcmimgle/libsrc/Makefile.in new file mode 100644 index 00000000..b48c9e3f --- /dev/null +++ b/dcmimgle/libsrc/Makefile.in @@ -0,0 +1,57 @@ +# +# Makefile for dcmimgle/libsrc +# + +@SET_MAKE@ + +SHELL = /bin/sh +VPATH = @srcdir@:@top_srcdir@/include:@top_srcdir@/@configdir@/include +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +configdir = @top_srcdir@/@configdir@ + +include $(configdir)/@common_makefile@ + +ofstddir = $(top_srcdir)/../ofstd +oflogdir = $(top_srcdir)/../oflog +dcmdatadir = $(top_srcdir)/../dcmdata + +LOCALINCLUDES = -I$(ofstddir)/include -I$(oflogdir)/include -I$(dcmdatadir)/include +LOCALDEFS = + +# Special defines for the Library, define them in LOCALDEFS +# REVERSE_OVERLAY_ORIGIN_ORDER +# swap order of overlay origin coordinates + +objs = dcmimage.o didocu.o diimage.o diinpx.o diutils.o \ + dimoimg.o dimoimg3.o dimoimg4.o dimoimg5.o \ + dimo1img.o dimo2img.o dimomod.o dimopx.o dimoopx.o \ + diovlay.o diovdat.o diovpln.o diovlimg.o dibaslut.o diluptab.o \ + didispfn.o didislut.o digsdfn.o digsdlut.o diciefn.o dicielut.o +library = libdcmimgle.$(LIBEXT) + + +all: $(library) + +install: $(library) + $(configdir)/mkinstalldirs $(DESTDIR)$(libdir) + $(INSTALL_DATA) $(library) $(DESTDIR)$(libdir)/$(library) + $(RANLIB) $(DESTDIR)$(libdir)/$(library) + + +$(library): $(objs) + $(AR) $(ARFLAGS) $@ $(objs) + $(RANLIB) $@ + + +clean: + rm -f $(objs) $(library) $(TRASH) + +distclean: + rm -f $(objs) $(library) $(DISTTRASH) + + +dependencies: + $(CXX) -MM $(defines) $(includes) $(CPPFLAGS) $(CXXFLAGS) *.cc > $(DEP) + +include $(DEP) diff --git a/dcmimgle/libsrc/dcmimage.cc b/dcmimgle/libsrc/dcmimage.cc new file mode 100644 index 00000000..182ef40b --- /dev/null +++ b/dcmimgle/libsrc/dcmimage.cc @@ -0,0 +1,795 @@ +/* + * + * Copyright (C) 1996-2010, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimgle + * + * Author: Joerg Riesmeier + * + * Purpose: DicomImage-Interface (Source) + * + */ + + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/dcmdata/dctypes.h" +#include "dcmtk/dcmdata/dcdeftag.h" +#include "dcmtk/dcmdata/dcobject.h" +#include "dcmtk/dcmdata/dcuid.h" +#include "dcmtk/dcmdata/dcdict.h" + +#include "dcmtk/dcmimgle/dcmimage.h" +#include "dcmtk/dcmimgle/diovlimg.h" +#include "dcmtk/dcmimgle/dimo1img.h" +#include "dcmtk/dcmimgle/dimo2img.h" +#include "dcmtk/dcmimgle/didocu.h" +#include "dcmtk/dcmimgle/diregbas.h" +#include "dcmtk/dcmimgle/diplugin.h" +#include "dcmtk/dcmdata/dcdicent.h" /* needed by MSVC5 */ + +#define INCLUDE_CCTYPE +#include "dcmtk/ofstd/ofstdinc.h" + +#ifndef FILENAME_MAX +#define FILENAME_MAX 255 +#endif + + +/*------------------* + * initialization * + *------------------*/ + +DiRegisterBase *DiRegisterBase::Pointer = NULL; + + +/*----------------* + * constructors * + *----------------*/ + +// --- create 'DicomImage' from 'filename', for valid 'flags' see 'diutils.h' + +DicomImage::DicomImage(const char *filename, + const unsigned long flags, + const unsigned long fstart, + const unsigned long fcount) + : ImageStatus(EIS_Normal), + PhotometricInterpretation(EPI_Unknown), + Document(NULL), + Image(NULL) +{ + if (checkDataDictionary()) // valid 'dicom.dic' found ? + { + Document = new DiDocument(filename, flags | CIF_MayDetachPixelData, fstart, fcount); + Init(); + } +} + + +// --- create 'DicomImage' from valid 'DicomObject' with transfer syntax 'xfer' + +DicomImage::DicomImage(DcmObject *object, + const E_TransferSyntax xfer, + const unsigned long flags, + const unsigned long fstart, + const unsigned long fcount) + : ImageStatus(EIS_Normal), + PhotometricInterpretation(EPI_Unknown), + Document(NULL), + Image(NULL) +{ + if (checkDataDictionary()) // valid 'dicom.dic' found ? + { + Document = new DiDocument(object, xfer, flags, fstart, fcount); + Init(); + } +} + + +// --- create 'DicomImage' from valid 'DicomObject' with given rescale 'slope' and 'intercept' + +DicomImage::DicomImage(DcmObject *object, + const E_TransferSyntax xfer, + const double slope, + const double intercept, + const unsigned long flags, + const unsigned long fstart, + const unsigned long fcount) + : ImageStatus(EIS_Normal), + PhotometricInterpretation(EPI_Unknown), + Document(NULL), + Image(NULL) +{ + if (checkDataDictionary()) // valid 'dicom.dic' found ? + { + Document = new DiDocument(object, xfer, flags, fstart, fcount); + if ((Document != NULL) && (Document->good())) + { + PhotometricInterpretation = EPI_Monochrome2; // default for presentation states + Image = new DiMono2Image(Document, ImageStatus, slope, intercept); + } + } +} + + +// --- create 'DicomImage' from valid 'DicomObject' with given modality LUT (specified by 'data' and 'descriptor') + +DicomImage::DicomImage(DcmObject *object, + E_TransferSyntax xfer, + const DcmUnsignedShort &data, + const DcmUnsignedShort &descriptor, + const DcmLongString *explanation, + const unsigned long flags, + const unsigned long fstart, + const unsigned long fcount) + : ImageStatus(EIS_Normal), + PhotometricInterpretation(EPI_Unknown), + Document(NULL), + Image(NULL) +{ + if (checkDataDictionary()) // valid 'dicom.dic' found ? + { + Document = new DiDocument(object, xfer, flags, fstart, fcount); + if ((Document != NULL) && (Document->good())) + { + PhotometricInterpretation = EPI_Monochrome2; // default for presentation states + Image = new DiMono2Image(Document, ImageStatus, data, descriptor, explanation); + } + } +} + + +// --- protected: create 'DicomImage' from source with different image data and photometric interpretation + +DicomImage::DicomImage(const DicomImage *dicom, + DiImage *image, + const EP_Interpretation interpret) + : ImageStatus(dicom->ImageStatus), + PhotometricInterpretation(dicom->PhotometricInterpretation), + Document(dicom->Document), // necessary, ever used ?? + Image(image) +{ + if (interpret != EPI_Unknown) + PhotometricInterpretation = interpret; + if (Document != NULL) + Document->addReference(); // 'Document' is only referenced not copied ! +} + + +/*--------------* + * destructor * + *--------------*/ + +DicomImage::~DicomImage() +{ + delete Image; + if (Document != NULL) + Document->removeReference(); // only delete if object is no longer referenced +} + + +/*********************************************************************/ + +// --- initialize 'DicomImage' object (same procedure for every 'real' constructor) + +void DicomImage::Init() +{ + if ((Document != NULL) && (Document->good())) + { + const char *str; + if (hasSOPclassUID(UID_RETIRED_StandaloneOverlayStorage)) + { + PhotometricInterpretation = EPI_Monochrome2; // standalone overlays are handled like monochrome + Image = new DiOverlayImage(Document, ImageStatus); // images without pixel data + } + else if (Document->getFlags() & CIF_UsePresentationState) + { + PhotometricInterpretation = EPI_Monochrome2; // default for presentation states + Image = new DiMono2Image(Document, ImageStatus); + } + else if (strlen(str = Document->getPhotometricInterpretation()) > 0) + { + const SP_Interpretation *pin = PhotometricInterpretationNames; + char *cstr = new char[strlen(str) + 1]; + if (cstr != NULL) + { + char *q = cstr; + unsigned char c; + for (const char *p = str; *p != 0; p++) // remove invalid chars + { + c = OFstatic_cast(unsigned char, *p); + if (isalpha(c)) + *(q++) = toupper(c); + else if (isdigit(c)) + *(q++) = c; + } + *q = '\0'; // end of C string + while ((pin->Name != NULL) && (strcmp(pin->Name, cstr) != 0)) + ++pin; + delete[] cstr; + } else { + DCMIMGLE_WARN("can't create filtered version of 'PhotometricInterpretation' (" << str << ")"); + cstr = OFconst_cast(char *, str); // just reference the original string + while ((pin->DefinedTerm != NULL) && (strcmp(pin->DefinedTerm, cstr) != 0)) + ++pin; + } + PhotometricInterpretation = pin->Type; // unknown if last entry + switch (PhotometricInterpretation) + { + case EPI_Monochrome1: // create 'Image' depending on color model + Image = new DiMono1Image(Document, ImageStatus); + break; + case EPI_Monochrome2: + Image = new DiMono2Image(Document, ImageStatus); + break; + default: // unknown or unsupported color model + if (DiRegisterBase::Pointer != NULL) + Image = DiRegisterBase::Pointer->createImage(Document, ImageStatus, PhotometricInterpretation); + if (Image == NULL) + { + if (PhotometricInterpretation == EPI_Unknown) + { + ImageStatus = EIS_InvalidValue; + DCMIMGLE_ERROR("invalid value for 'PhotometricInterpretation' (" << str << ")"); + } else { + ImageStatus = EIS_NotSupportedValue; + DCMIMGLE_ERROR("unsupported value for 'PhotometricInterpretation' (" << str << ")"); + } + } + } + } + else if (Document->getFlags() & CIF_AcrNemaCompatibility) // ACR-NEMA has no 'photometric interpretation' + { + PhotometricInterpretation = EPI_Monochrome2; + Image = new DiMono2Image(Document, ImageStatus); + } else { + ImageStatus = EIS_MissingAttribute; + PhotometricInterpretation = EPI_Missing; + if (Document->getPixelData() != NULL) + DCMIMGLE_ERROR("mandatory attribute 'PhotometricInterpretation' is missing or can't be determined"); + } + } + else + ImageStatus = EIS_InvalidDocument; +} + + +// --- check whether the loadable 'DataDictionary' is present/loaded + +int DicomImage::checkDataDictionary() +{ + if (!dcmDataDict.isDictionaryLoaded()) + { + ImageStatus = EIS_NoDataDictionary; + DCMIMGLE_ERROR("can't load data dictionary"); + } + return ImageStatus == EIS_Normal; +} + + +/*********************************************************************/ + + +const char *DicomImage::getString(const EI_Status status) +{ + switch (status) + { + case EIS_Normal: + return "Status OK"; + case EIS_NoDataDictionary: + return "No data dictionary"; + case EIS_InvalidDocument: + return "Invalid DICOM document"; + case EIS_MissingAttribute: + return "Missing attribute"; + case EIS_InvalidValue: + return "Invalid element value"; + case EIS_NotSupportedValue: + return "Unsupported element value"; + case EIS_MemoryFailure: + return "Out of memory"; + case EIS_InvalidImage: + return "Invalid DICOM image"; + case EIS_OtherError: + default: + return "Unspecified"; + } +} + + +const char *DicomImage::getString(const EP_Interpretation interpret) +{ + const SP_Interpretation *pin = PhotometricInterpretationNames; + while ((pin->DefinedTerm != NULL) && (pin->Type != interpret)) + ++pin; + return pin->DefinedTerm; +} + + +// --- return unique 'SOPclassUID' string + +const char *DicomImage::getSOPclassUID() const +{ + if (Document != NULL) + { + const char *str; + if (Document->getValue(DCM_SOPClassUID, str)) + return str; + } + return NULL; +} + + +// --- return 'true' (1) if 'Document' has the same 'SOPclassUID' as given in parameter 'uid' + +int DicomImage::hasSOPclassUID(const char *uid) const +{ + const char *str = getSOPclassUID(); + return (str != NULL) && (strcmp(str, uid) == 0); +} + + +// --- create new 'DicomImage' with 'fcount' frames starting with frame 'fstart' + +DicomImage *DicomImage::createDicomImage(unsigned long fstart, + unsigned long fcount) const +{ + if ((Image != NULL) && (fstart < getFrameCount())) + { + if ((fcount == 0) || (fstart + fcount > getFrameCount())) + fcount = getFrameCount() - fstart; + DiImage *image = Image->createImage(fstart, fcount); + if (image != NULL) + { + DicomImage *dicom = new DicomImage(this, image); + return dicom; + } + } + return NULL; +} + + +// --- create scaled to given size ('width' and 'height') image, memory isn't handled internally ! +// --- if one dimension ist '0' the other is automatically adjusted (with respect to pixel aspect ratio) + +DicomImage *DicomImage::createScaledImage(const unsigned long width, + const unsigned long height, + const int interpolate, + int aspect) const +{ + return createScaledImage(0, 0, getWidth(), getHeight(), width, height, interpolate, aspect); +} + + +// --- create scaled with given factors ('xfactor' and 'yfactor') image, memory isn't handled internally ! + +DicomImage *DicomImage::createScaledImage(const double xfactor, + const double yfactor, + const int interpolate, + const int aspect) const +{ + return createScaledImage(0, 0, getWidth(), getHeight(), OFstatic_cast(unsigned long, xfactor * getWidth()), + OFstatic_cast(unsigned long, yfactor * getHeight()), interpolate, aspect); +} + + +// --- clip & scale + +DicomImage *DicomImage::createScaledImage(const signed long left_pos, + const signed long top_pos, + unsigned long clip_width, + unsigned long clip_height, + unsigned long scale_width, + unsigned long scale_height, + const int interpolate, + int aspect, + const Uint16 pvalue) const +{ + const unsigned long gw = getWidth(); + const unsigned long gh = getHeight(); + if ((Image != NULL) && (gw > 0) && (gh > 0)) + { + if ((clip_width == 0) && (left_pos < OFstatic_cast(signed long, gw))) // set 'width' if parameter is missing + clip_width = gw - left_pos; + if ((clip_height == 0) && (top_pos < OFstatic_cast(signed long, gh))) // same for 'height' + clip_height = gh - top_pos; + if ((scale_width == 0) && (scale_height == 0)) + { + scale_width = clip_width; // auto-set width/height + scale_height = clip_height; + } + else if ((clip_width > 0) && (clip_height > 0)) + { + if (aspect) // maintain pixel aspect ratio + { + if (scale_width == 0) + scale_width = OFstatic_cast(unsigned long, getWidthHeightRatio() * OFstatic_cast(double, scale_height * clip_width) / clip_height); + else if (scale_height == 0) + scale_height = OFstatic_cast(unsigned long, getHeightWidthRatio() * OFstatic_cast(double, scale_width * clip_height) / clip_width); + else + aspect = 0; // ignore pixel aspect ratio + } + else // ignore pixel aspect ratio + { + if (scale_width == 0) + scale_width = OFstatic_cast(unsigned long, OFstatic_cast(double, scale_height * clip_width) / clip_height); + else if (scale_height == 0) + scale_height = OFstatic_cast(unsigned long, OFstatic_cast(double, scale_width * clip_height) / clip_width); + } + } + const unsigned long maxvalue = DicomImageClass::maxval(bitsof(Uint16)); + if (scale_width > maxvalue) + scale_width = maxvalue; // limit 'width' to maximum value (65535) + if (scale_height > maxvalue) + scale_height = maxvalue; // same for 'height' + + /* need to limit clipping region ... !? */ + + if (((left_pos < 0) || (OFstatic_cast(unsigned long, left_pos + clip_width) > gw) || + (top_pos < 0) || (OFstatic_cast(unsigned long, top_pos + clip_height) > gh)) && + ((clip_width != scale_width) || (clip_height != scale_height))) + { + DCMIMGLE_ERROR("combined clipping & scaling outside image boundaries not yet supported"); + } + else if ((scale_width > 0) && (scale_height > 0)) + { + DiImage *image = Image->createScale(left_pos, top_pos, clip_width, clip_height, scale_width, scale_height, + interpolate, aspect, pvalue); + if (image != NULL) + { + DicomImage *dicom = new DicomImage(this, image); + return dicom; + } + } + } + return NULL; +} + + +// --- clip & scale + +DicomImage *DicomImage::createScaledImage(const signed long left_pos, + const signed long top_pos, + unsigned long width, + unsigned long height, + const double xfactor, + const double yfactor, + const int interpolate, + const int aspect, + const Uint16 pvalue) const +{ + if ((xfactor >= 0) && (yfactor >= 0)) + { + const unsigned long gw = getWidth(); + const unsigned long gh = getHeight(); + if ((width == 0) && (left_pos < OFstatic_cast(signed long, gw))) // set 'width' if parameter is missing (0) + width = gw - left_pos; + if ((height == 0) && (top_pos < OFstatic_cast(signed long, gh))) // same for 'height' + height = gh - top_pos; + return createScaledImage(left_pos, top_pos, width, height, OFstatic_cast(unsigned long, xfactor * width), + OFstatic_cast(unsigned long, yfactor * height), interpolate, aspect, pvalue); + } + return NULL; +} + + +// --- create clipped to given box ('left_pos', 'top_pos' and 'width', 'height') image, +// ---- memory isn't handled internally! 'width' and 'height' are optional + +DicomImage *DicomImage::createClippedImage(const signed long left_pos, + const signed long top_pos, + unsigned long width, + unsigned long height, + const Uint16 pvalue) const +{ + return createScaledImage(left_pos, top_pos, width, height, OFstatic_cast(unsigned long, 0), + OFstatic_cast(unsigned long, 0), 0, 0, pvalue); +} + + +// --- flip image (horizontal: x > 1 and/or vertical y > 1) + +int DicomImage::flipImage(int horz, + int vert) const +{ + if ((Image != NULL) && (horz || vert)) + { + if (getWidth() <= 1) + horz = 0; + if (getHeight() <= 1) + vert = 0; + if (horz || vert) + return Image->flip(horz, vert); + else + return 2; + } + return 0; +} + + +// --- create flipped image (horizontal: x > 1 and/or vertical y > 1), memory isn't handled internally ! + +DicomImage *DicomImage::createFlippedImage(int horz, + int vert) const +{ + if ((Image != NULL) && (horz || vert)) + { + if (getWidth() <= 1) // can't flip horizontally + horz = 0; + if (getHeight() <= 1) // can't flip vertically + vert = 0; + DiImage *image; + if (horz || vert) // flip at least one axis + image = Image->createFlip(horz, vert); + else // copy image + image = Image->createImage(0, getFrameCount()); + if (image != NULL) + { + DicomImage *dicom = new DicomImage(this, image); + return dicom; + } + } + return NULL; +} + + +// -- normalize given 'degree' value to 0, 90, 180, 270 + +int DicomImage::normalizeDegreeValue(signed int °ree) const +{ + switch (degree) + { + case 0: + case 360: + case -360: + degree = 0; + return 1; + case 90: + case -270: + degree = 90; + return 1; + case 180: + case -180: + degree = 180; + return 1; + case 270: + case -90: + degree = 270; + return 1; + default: + return 0; + } +} + + +// --- rotate image by given 'degree' + +int DicomImage::rotateImage(signed int degree) const +{ + if ((Image != NULL) && normalizeDegreeValue(degree)) + { + if ((degree == 0) || (getWidth() * getHeight() <= 1)) // nothing to do + return 2; + else + return Image->rotate(OFstatic_cast(int, degree)); + } + return 0; +} + + +// --- create by given 'degree' rotated image, memory isn't handled internally ! + +DicomImage *DicomImage::createRotatedImage(signed int degree) const +{ + if ((Image != NULL) && normalizeDegreeValue(degree)) + { + DiImage *image = Image->createRotate(OFstatic_cast(int, degree)); + if (image != NULL) + { + DicomImage *dicom = new DicomImage(this, image); + return dicom; + } + } + return NULL; +} + + +// --- create color-image to mono-image with given 'red', 'green' and 'blue' coefficients converted image, memory ... ! + +DicomImage *DicomImage::createMonochromeImage(const double red, + const double green, + const double blue) const +{ + if (Image != NULL) + { + DiImage *image = Image->createMono(red, green, blue); // create monochrome image data + if (image != NULL) + { + DicomImage *dicom = new DicomImage(this, image, EPI_Monochrome2); + return dicom; + } + } + return NULL; +} + + +// --- create monochrome output image of specified frame (incl. windowing) + +DicomImage *DicomImage::createMonoOutputImage(const unsigned long frame, + const int bits) +{ + if ((Image != NULL) && (Image->getMonoImagePtr() != NULL)) + { + DiImage *image = Image->getMonoImagePtr()->createOutputImage(frame, bits); + if (image != NULL) + { + DicomImage *dicom = new DicomImage(this, image, EPI_Monochrome2); + return dicom; + } + } + return NULL; +} + + +/*********************************************************************/ + + +// --- write 'frame' of image data to 'filename' with 'bits' depth + +int DicomImage::writePPM(const char *filename, + const int bits, + const unsigned long frame) +{ + if ((filename != NULL) && (Image != NULL)) + { + char fname[FILENAME_MAX + 1]; + if (sprintf(fname, filename, frame) >= 0) // replace '%d' etc. with frame number + filename = fname; + FILE *stream = fopen(filename, "w"); // open text file for writing + int ok = writePPM(stream, bits, frame); + fclose(stream); + return ok; + } + return 0; +} + + +// --- same for C++ 'ostream' + +int DicomImage::writePPM(STD_NAMESPACE ostream& stream, + const int bits, + const unsigned long frame) +{ + if ((stream.good()) && (Image != NULL)) + return Image->writePPM(stream, frame, Image->getBits(bits)); + return 0; +} + + +// --- same for C 'FILE' + +int DicomImage::writePPM(FILE *stream, + const int bits, + const unsigned long frame) +{ + if ((stream != NULL) && (Image != NULL)) + return Image->writePPM(stream, frame, Image->getBits(bits)); + return 0; +} + + +// --- same for RAW PPM (binary form of PPM with a maximum of 8 bits depth) + +int DicomImage::writeRawPPM(const char *filename, + const int bits, + const unsigned long frame) +{ + if ((filename != NULL) && (Image != NULL) && (Image->getBits(bits) <= MAX_RAWPPM_BITS)) + { + char fname[FILENAME_MAX + 1]; + if (sprintf(fname, filename, frame) >= 0) // replace '%d' etc. with frame number + filename = fname; + FILE *stream = fopen(filename, "wb"); // open binary file for writing + if (stream != NULL) + { + int ok = Image->writeRawPPM(stream, frame, Image->getBits(bits)); + fclose(stream); + return ok; + } + } + return 0; +} + +// --- same for C 'FILE' + +int DicomImage::writeRawPPM(FILE *stream, + const int bits, + const unsigned long frame) +{ + if ((stream != NULL) && (Image != NULL)) + return Image->writeRawPPM(stream, frame, Image->getBits(bits)); + return 0; +} + + +// --- write 'frame' of image data to 'filename' with 'bits' depth in BMP format + +int DicomImage::writeBMP(const char *filename, + const int bits, + const unsigned long frame) +{ + if ((filename != NULL) && (Image != NULL) && + ((bits == 0) || ((bits == 8) && isMonochrome()) || (bits == 24) || (bits == 32))) + { + char fname[FILENAME_MAX + 1]; + if (sprintf(fname, filename, frame) >= 0) // replace '%d' etc. with frame number + filename = fname; + FILE *stream = fopen(filename, "wb"); // open binary file for writing + if (stream != NULL) + { + int ok = Image->writeBMP(stream, frame, bits); + fclose(stream); + return ok; + } + } + return 0; +} + + +// --- same for open C 'FILE' in BMP format + +int DicomImage::writeBMP(FILE *stream, + const int bits, + const unsigned long frame) +{ + if ((stream != NULL) && (Image != NULL) && + ((bits == 0) || ((bits == 8) && isMonochrome()) || (bits == 24) || (bits == 32))) + { + return Image->writeBMP(stream, frame, bits); + } + return 0; +} + + +// --- write 'frame' of image data to 'filename' plugable image format + +int DicomImage::writePluginFormat(const DiPluginFormat *plugin, + const char *filename, + const unsigned long frame) +{ + if ((plugin != NULL) && (filename != NULL) && (Image != NULL)) + { + char fname[FILENAME_MAX + 1]; + if (sprintf(fname, filename, frame) >= 0) // replace '%d' etc. with frame number + filename = fname; + FILE *stream = fopen(filename, "wb"); // open binary file for writing + if (stream != NULL) + { + int ok = plugin->write(Image, stream, frame); + fclose(stream); + return ok; + } + } + return 0; +} + + +// --- same for open C 'FILE' in plugable image format + +int DicomImage::writePluginFormat(const DiPluginFormat *plugin, + FILE *stream, + const unsigned long frame) +{ + if ((plugin != NULL) && (stream != NULL) && (Image != NULL)) + return plugin->write(Image, stream, frame); + return 0; +} diff --git a/dcmimgle/libsrc/dibaslut.cc b/dcmimgle/libsrc/dibaslut.cc new file mode 100644 index 00000000..f77ad283 --- /dev/null +++ b/dcmimgle/libsrc/dibaslut.cc @@ -0,0 +1,102 @@ +/* + * + * Copyright (C) 1996-2010, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimgle + * + * Author: Joerg Riesmeier + * + * Purpose: DicomBaseLUT (Source) + * + */ + + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/dcmimgle/dibaslut.h" + + +/*----------------* + * constructors * + *----------------*/ + +DiBaseLUT::DiBaseLUT(const Uint32 count, + const Uint16 bits) + : Count(count), + FirstEntry(0), + Bits(bits), + MinValue(0), + MaxValue(0), + Valid(0), + Explanation(), + Data(NULL), + DataBuffer(NULL) +{ +} + + +DiBaseLUT::DiBaseLUT(Uint16 *buffer, + const Uint32 count, + const Uint16 bits) + : Count(count), + FirstEntry(0), + Bits(bits), + MinValue(0), + MaxValue(0), + Valid(0), + Explanation(), + Data(buffer), + DataBuffer(buffer) +{ +} + + +/*--------------* + * destructor * + *--------------*/ + +DiBaseLUT::~DiBaseLUT() +{ + delete[] DataBuffer; +} + + +/********************************************************************/ + + +OFBool DiBaseLUT::operator==(const DiBaseLUT &lut) +{ + return (compare(&lut) == 0); +} + + +int DiBaseLUT::compare(const DiBaseLUT *lut) +{ + int result = 1; // invalid LUT (1) + if (Valid && (lut != NULL) && lut->isValid()) + { + result = 2; // descriptor differs (2) + if ((Count == lut->getCount()) && (FirstEntry == lut->getFirstEntry()) && (Bits == lut->getBits())) + { // special case: if Count == 0 LUT data is equal + register Uint32 i = Count; // ... but normally not Valid ! + if ((MinValue == lut->getMinValue()) && (MaxValue == lut->getMaxValue())) + { // additional check for better performance + register const Uint16 *p = Data; + register const Uint16 *q = lut->getData(); + while ((i != 0) && (*(p++) == *(q++))) + --i; + } + result = (i != 0) ? 3 : 0; // check whether data is equal (0) + } + } + return result; +} diff --git a/dcmimgle/libsrc/diciefn.cc b/dcmimgle/libsrc/diciefn.cc new file mode 100644 index 00000000..688df221 --- /dev/null +++ b/dcmimgle/libsrc/diciefn.cc @@ -0,0 +1,241 @@ +/* + * + * Copyright (C) 1998-2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimgle + * + * Author: Joerg Riesmeier + * + * Purpose: DicomCIELABFunction (Source) + * + */ + + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/dcmimgle/diciefn.h" +#include "dcmtk/ofstd/ofstream.h" + +#define INCLUDE_CMATH +#define INCLUDE_CSTRING +#include "dcmtk/ofstd/ofstdinc.h" + + +/*----------------* + * constructors * + *----------------*/ + +DiCIELABFunction::DiCIELABFunction(const char *filename, + const E_DeviceType deviceType, + const signed int ord) + : DiDisplayFunction(filename, deviceType, ord) +{ + if (!Valid) + { + DCMIMGLE_ERROR("invalid DISPLAY file ... ignoring"); + } +} + + +DiCIELABFunction::DiCIELABFunction(const double *val_tab, // UNTESTED !! + const unsigned long count, + const Uint16 max, + const E_DeviceType deviceType, + const signed int ord) + : DiDisplayFunction(val_tab, count, max, deviceType, ord) +{ + if (!Valid) + { + DCMIMGLE_ERROR("invalid DISPLAY values ... ignoring"); + } +} + + +DiCIELABFunction::DiCIELABFunction(const Uint16 *ddl_tab, // UNTESTED !! + const double *val_tab, + const unsigned long count, + const Uint16 max, + const E_DeviceType deviceType, + const signed int ord) + : DiDisplayFunction(ddl_tab, val_tab, count, max, deviceType, ord) +{ + if (!Valid) + { + DCMIMGLE_ERROR("invalid DISPLAY values ... ignoring"); + } +} + + +DiCIELABFunction::DiCIELABFunction(const double val_min, + const double val_max, + const unsigned long count, + const E_DeviceType deviceType, + const signed int ord) + : DiDisplayFunction(val_min, val_max, count, deviceType, ord) +{ + if (!Valid) + { + DCMIMGLE_ERROR("invalid DISPLAY values ... ignoring"); + } +} + + +/*--------------* + * destructor * + *--------------*/ + +DiCIELABFunction::~DiCIELABFunction() +{ +} + + +/********************************************************************/ + + +DiDisplayLUT *DiCIELABFunction::getDisplayLUT(unsigned long count) +{ + DiDisplayLUT *lut = NULL; + if (count <= MAX_TABLE_ENTRY_COUNT) + { + if ((DeviceType == EDT_Printer) || (DeviceType == EDT_Scanner)) + { + /* hardcopy: values are in optical density, first convert them to luminance */ + double *tmp_tab = convertODtoLumTable(LODValue, ValueCount, OFFalse /*useAmb*/); + if (tmp_tab != NULL) + { + checkMinMaxDensity(); + /* create new CIELAB LUT */ + lut = new DiCIELABLUT(count, MaxDDLValue, DDLValue, tmp_tab, ValueCount, + convertODtoLum(MaxValue, OFFalse /*useAmb*/), convertODtoLum(MinValue, OFFalse /*useAmb*/), + getMinLuminanceValue(), getMaxLuminanceValue(), AmbientLight, (DeviceType == EDT_Scanner)); + /* delete temporary table */ + delete[] tmp_tab; + } + } else { + /* softcopy: values are already in luminance */ + lut = new DiCIELABLUT(count, MaxDDLValue, DDLValue, LODValue, ValueCount, + MinValue, MaxValue, -1 /*Lmin*/, -1 /*Lmax*/, AmbientLight, (DeviceType == EDT_Camera)); + } + } + return lut; +} + + +int DiCIELABFunction::writeCurveData(const char *filename, + const OFBool mode) +{ + if ((filename != NULL) && (strlen(filename) > 0)) + { + STD_NAMESPACE ofstream file(filename); + if (file) + { + const OFBool inverseLUT = (DeviceType == EDT_Scanner) || (DeviceType == EDT_Camera); + /* comment header */ + file << "# Display function : CIELAB" << OFendl; + if (DeviceType == EDT_Printer) + file << "# Type of output device : Printer (hardcopy)" << OFendl; + else if (DeviceType == EDT_Scanner) + file << "# Type of output device : Scanner (hardcopy)" << OFendl; + else if (DeviceType == EDT_Camera) + file << "# Type of output device : Camera (softcopy)" << OFendl; + else + file << "# Type of output device : Monitor (softcopy)" << OFendl; + file << "# Digital driving levels : " << ValueCount << OFendl; + if ((DeviceType == EDT_Printer) || (DeviceType == EDT_Scanner)) + file << "# Illumination [cd/m^2] : " << Illumination << OFendl; + file << "# Ambient light [cd/m^2] : " << AmbientLight << OFendl; + if ((DeviceType == EDT_Printer) || (DeviceType == EDT_Scanner)) + { + const double min_lum = getMinLuminanceValue(); + const double max_lum = getMaxLuminanceValue(); + file << "# Luminance w/o [cd/m^2] : " << convertODtoLum(MaxValue, OFFalse /*useAmb*/) << " - " + << convertODtoLum(MinValue, OFFalse /*useAmb*/); + if ((min_lum >= 0) || (max_lum >= 0)) + { + file << " (Lmin = "; + if (min_lum >= 0) + file << min_lum; + else + file << "n/s"; + file << ", Lmax = "; + if (max_lum >= 0) + file << max_lum; + else + file << "n/s"; + file << ")"; + } + file << OFendl; + file << "# Optical density [OD] : " << MinValue << " - " << MaxValue; + if ((MinDensity >= 0) || (MaxDensity >= 0)) + { + file << " (Dmin = "; + if (MinDensity >= 0) + file << MinDensity; + else + file << "n/s"; + file << ", Dmax = "; + if (MaxDensity >= 0) + file << MaxDensity; + else + file << "n/s"; + file << ")"; + } + file << OFendl; + } else + file << "# Luminance w/o [cd/m^2] : " << MinValue << " - " << MaxValue << OFendl; + file << "# Interpolation method : "; + if (getPolynomialOrder() > 0) + file << "Curve fitting algorithm with order " << getPolynomialOrder() << OFendl << OFendl; + else + file << "Cubic spline interpolation" << OFendl << OFendl; + /* print headings of the table */ + if (mode) + { + file << "# NB: values for CC, CIELAB and PSC"; + if (inverseLUT) + file << "'"; // add ' to PSC + file << " are specified in cd/m^2" << OFendl << OFendl; + file << "DDL\tCC\tCIELAB\tPSC"; + if (inverseLUT) + file << "'"; // add ' to PSC + file << OFendl; + } else { + file << "# NB: values for CC and CIELAB are specified in cd/m^2" << OFendl << OFendl; + file << "DDL\tCIELAB" << OFendl; + } + /* create CIELAB LUT and write curve data to file */ + DiCIELABLUT *lut = NULL; + if ((DeviceType == EDT_Printer) || (DeviceType == EDT_Scanner)) + { + /* hardcopy: values are in optical density, first convert them to luminance */ + double *tmp_tab = convertODtoLumTable(LODValue, ValueCount, OFFalse /*useAmb*/); + if (tmp_tab != NULL) + { + checkMinMaxDensity(); + lut = new DiCIELABLUT(ValueCount, MaxDDLValue, DDLValue, tmp_tab, ValueCount, + convertODtoLum(MaxValue, OFFalse /*useAmb*/), convertODtoLum(MinValue, OFFalse /*useAmb*/), + getMinLuminanceValue(), getMaxLuminanceValue(), AmbientLight, inverseLUT, &file, mode); + /* delete temporary table */ + delete[] tmp_tab; + } + } else { + /* softcopy: values are already in luminance */ + lut = new DiCIELABLUT(ValueCount, MaxDDLValue, DDLValue, LODValue, ValueCount, + MinValue, MaxValue, -1 /*Lmin*/, -1 /*Lmax*/, AmbientLight, inverseLUT, &file, mode); + } + int status = (lut != NULL) && (lut->isValid()); + delete lut; + return status; + } + } + return 0; +} diff --git a/dcmimgle/libsrc/dicielut.cc b/dcmimgle/libsrc/dicielut.cc new file mode 100644 index 00000000..b6abc941 --- /dev/null +++ b/dcmimgle/libsrc/dicielut.cc @@ -0,0 +1,198 @@ +/* + * + * Copyright (C) 1999-2010, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimgle + * + * Author: Joerg Riesmeier + * + * Purpose: DicomCIELABLUT (Source) + * + */ + + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/dcmimgle/dicielut.h" + +#define INCLUDE_CMATH +#include "dcmtk/ofstd/ofstdinc.h" + + +/*----------------* + * constructors * + *----------------*/ + +DiCIELABLUT::DiCIELABLUT(const unsigned long count, + const Uint16 max, + const Uint16 *ddl_tab, + const double *val_tab, + const unsigned long ddl_cnt, + const double val_min, + const double val_max, + const double lum_min, + const double lum_max, + const double amb, + const OFBool inverse, + STD_NAMESPACE ostream *stream, + const OFBool printMode) + : DiDisplayLUT(count, max, amb /*, 'illum' not used*/) +{ + if ((Count > 0) && (Bits > 0)) + { + DCMIMGLE_DEBUG("new CIELAB LUT with " << Bits << " bits output and " << Count << " entries created"); + if (val_min >= val_max) + { + DCMIMGLE_ERROR("invalid value range for CIELAB LUT creation (" << val_min << " - " << val_max << ")"); + } + /* create the lookup table */ + Valid = createLUT(ddl_tab, val_tab, ddl_cnt, val_min, val_max, lum_min, lum_max, + inverse, stream, printMode); + } +} + + +/*--------------* + * destructor * + *--------------*/ + +DiCIELABLUT::~DiCIELABLUT() +{ +} + + +/********************************************************************/ + + +int DiCIELABLUT::createLUT(const Uint16 *ddl_tab, + const double *val_tab, + const unsigned long ddl_cnt, + const double val_min, + const double val_max, + const double lum_min, + const double lum_max, + const OFBool inverse, + STD_NAMESPACE ostream *stream, + const OFBool printMode) +{ + int status = 0; + if ((ddl_tab != NULL) && (val_tab != NULL) && (ddl_cnt > 0) && (val_max > 0) && (val_min < val_max)) + { + const unsigned long cin_ctn = (inverse) ? ddl_cnt : Count; // number of points to be interpolated + double *cielab = new double[cin_ctn]; + if (cielab != NULL) + { + register unsigned long i; + register double llin = 0; + register double cub = 0; + const double amb = getAmbientLightValue(); + /* check whether Lmin or Lmax is set */ + const double min = (lum_min < 0) ? val_min + amb : lum_min /*includes 'amb'*/; + const double max = (lum_max < 0) ? val_max + amb : lum_max /*includes 'amb'*/; + const double lmin = min / max; + const double hmin = (lmin > 0.008856) ? 116.0 * pow(lmin, 1.0 / 3.0) - 16 : 903.3 * lmin; + const double lfac = (100.0 - hmin) / (OFstatic_cast(double, cin_ctn - 1) * 903.3); + const double loff = hmin / 903.3; + const double cfac = (100.0 - hmin) / (OFstatic_cast(double, cin_ctn - 1) * 116.0); + const double coff = (16.0 + hmin) / 116.0; + for (i = 0; i < cin_ctn; ++i) // compute CIELAB function + { + llin = OFstatic_cast(double, i) * lfac + loff; + cub = OFstatic_cast(double, i) * cfac + coff; + cielab[i] = ((llin > 0.008856) ? cub * cub * cub : llin) * max; + } + DataBuffer = new Uint16[Count]; + if (DataBuffer != NULL) // create look-up table + { + register Uint16 *q = DataBuffer; + register unsigned long j = 0; + /* check whether to apply the inverse transformation */ + if (inverse) + { + register double v; + const double factor = OFstatic_cast(double, ddl_cnt - 1) / OFstatic_cast(double, Count - 1); + /* convert from DDL */ + for (i = 0; i < Count; ++i) + { + v = val_tab[OFstatic_cast(int, i * factor)] + amb; // need to scale index to range of value table + while ((j + 1 < ddl_cnt) && (cielab[j] < v)) // search for closest index, assuming monotony + ++j; + if ((j > 0) && (fabs(cielab[j - 1] - v) < fabs(cielab[j] - v))) + --j; + *(q++) = ddl_tab[j]; + } + } else { + /* initial DDL boundaries */ + unsigned long ddl_min = 0; + unsigned long ddl_max= ddl_cnt - 1; + /* check whether minimum luminance is specified */ + if (lum_min >= 0) + { + j = ddl_min; + /* determine corresponding minimum DDL value */ + while ((j < ddl_max) && (val_tab[j] + amb < lum_min)) + ++j; + ddl_min = j; + } + /* check whether maximum luminance is specified */ + if (lum_max >= 0) + { + j = ddl_max; + /* determine corresponding maximum DDL value */ + while ((j > ddl_min) && (val_tab[j] + amb > lum_max)) + --j; + ddl_max = j; + } + j = ddl_min; + register const double *r = cielab; + /* convert to DDL */ + for (i = Count; i != 0; --i, ++r) + { + while ((j < ddl_max) && (val_tab[j] + amb < *r)) // search for closest index, assuming monotony + ++j; + if ((j > 0) && (fabs(val_tab[j - 1] + amb - *r) < fabs(val_tab[j] + amb - *r))) + --j; + *(q++) = ddl_tab[j]; + } + } + Data = DataBuffer; + if (stream != NULL) // write curve data to file + { + if (Count == ddl_cnt) // check whether CIELAB LUT fits exactly to DISPLAY file + { + for (i = 0; i < ddl_cnt; ++i) + { + (*stream) << ddl_tab[i]; // DDL + stream->setf(STD_NAMESPACE ios::fixed, STD_NAMESPACE ios::floatfield); + if (printMode) + (*stream) << "\t" << val_tab[i] + amb; // CC + (*stream) << "\t" << cielab[i]; // CIELAB + if (printMode) + { + if (inverse) + (*stream) << "\t" << cielab[Data[i]]; // PSC' + else + (*stream) << "\t" << val_tab[Data[i]] + amb; // PSC + } + (*stream) << OFendl; + } + } else { + DCMIMGLE_WARN("can't write curve data, wrong DISPLAY file or CIELAB LUT"); + } + } + status = 1; + } + } + delete[] cielab; + } + return status; +} diff --git a/dcmimgle/libsrc/didislut.cc b/dcmimgle/libsrc/didislut.cc new file mode 100644 index 00000000..26b334ee --- /dev/null +++ b/dcmimgle/libsrc/didislut.cc @@ -0,0 +1,49 @@ +/* + * + * Copyright (C) 1996-2010, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimgle + * + * Author: Joerg Riesmeier + * + * Purpose: DicomDisplayLUT (Source) + * + */ + + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/dcmimgle/didislut.h" + + +/*----------------* + * constructors * + *----------------*/ + +DiDisplayLUT::DiDisplayLUT(const unsigned long count, + const Uint16 max, + const double amb, + const double illum) + : DiBaseLUT(count, DicomImageClass::tobits(max, 0)), + AmbientLight((amb > 0) ? amb : 0), + Illumination((illum > 0) ? illum : 0) +{ +} + + +/*--------------* + * destructor * + *--------------*/ + +DiDisplayLUT::~DiDisplayLUT() +{ +} diff --git a/dcmimgle/libsrc/didispfn.cc b/dcmimgle/libsrc/didispfn.cc new file mode 100644 index 00000000..5d0d311b --- /dev/null +++ b/dcmimgle/libsrc/didispfn.cc @@ -0,0 +1,679 @@ +/* + * + * Copyright (C) 1999-2010, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimgle + * + * Author: Joerg Riesmeier + * + * Purpose: DicomDisplayFunction (Source) + * + */ + + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/ofstd/ofbmanip.h" +#include "dcmtk/dcmimgle/didispfn.h" +#include "dcmtk/dcmimgle/displint.h" +#include "dcmtk/dcmimgle/dicrvfit.h" +#include "dcmtk/dcmimgle/didislut.h" +#include "dcmtk/ofstd/ofstream.h" + +#define INCLUDE_CCTYPE +#define INCLUDE_CMATH +#include "dcmtk/ofstd/ofstdinc.h" + + +/*----------------------------* + * constant initializations * + *----------------------------*/ + +const int DiDisplayFunction::MinBits = 2; +const int DiDisplayFunction::MaxBits = 16; + + +/*----------------* + * constructors * + *----------------*/ + +DiDisplayFunction::DiDisplayFunction(const char *filename, + const E_DeviceType deviceType, + const signed int ord) + : Valid(0), + DeviceType(deviceType), + ValueCount(0), + MaxDDLValue(0), + Order(0), + AmbientLight(0), + Illumination(0), + MinDensity(-1), + MaxDensity(-1), + DDLValue(NULL), + LODValue(NULL), + MinValue(0), + MaxValue(0) +{ + OFBitmanipTemplate::zeroMem(LookupTable, MAX_NUMBER_OF_TABLES); + if (readConfigFile(filename)) + { + /* overwrite file setting for polynomial order */ + if (ord >= 0) + Order = ord; + Valid = createSortedTable(DDLValue, LODValue) && calculateMinMax() && interpolateValues(); + } +} + + +DiDisplayFunction::DiDisplayFunction(const double *val_tab, // UNTESTED !! + const unsigned long count, + const Uint16 max, + const E_DeviceType deviceType, + const signed int ord) + : Valid(0), + DeviceType(deviceType), + ValueCount(count), + MaxDDLValue(max), + Order(ord), + AmbientLight(0), + Illumination(0), + MinDensity(-1), + MaxDensity(-1), + DDLValue(NULL), + LODValue(NULL), + MinValue(0), + MaxValue(0) +{ + OFBitmanipTemplate::zeroMem(LookupTable, MAX_NUMBER_OF_TABLES); + /* check number of entries */ + if ((ValueCount > 0) && (ValueCount == OFstatic_cast(unsigned long, MaxDDLValue) + 1)) + { + /* copy value table */ + DDLValue = new Uint16[ValueCount]; + LODValue = new double[ValueCount]; + if ((DDLValue != NULL) && (LODValue != NULL)) + { + register unsigned int i; + for (i = 0; i <= MaxDDLValue; ++i) + { + DDLValue[i] = OFstatic_cast(Uint16, i); // set DDL values + LODValue[i] = val_tab[i]; // copy table + } + Valid = calculateMinMax(); + } + } +} + + +DiDisplayFunction::DiDisplayFunction(const Uint16 *ddl_tab, // UNTESTED !! + const double *val_tab, + const unsigned long count, + const Uint16 max, + const E_DeviceType deviceType, + const signed int ord) + : Valid(0), + DeviceType(deviceType), + ValueCount(count), + MaxDDLValue(max), + Order(ord), + AmbientLight(0), + Illumination(0), + MinDensity(-1), + MaxDensity(-1), + DDLValue(NULL), + LODValue(NULL), + MinValue(0), + MaxValue(0) +{ + OFBitmanipTemplate::zeroMem(LookupTable, MAX_NUMBER_OF_TABLES); + /* check for maximum number of entries */ + if (ValueCount <= MAX_TABLE_ENTRY_COUNT) + Valid = createSortedTable(ddl_tab, val_tab) && calculateMinMax() && interpolateValues(); +} + + +DiDisplayFunction::DiDisplayFunction(const double val_min, + const double val_max, + const unsigned long count, + const E_DeviceType deviceType, + const signed int ord) + : Valid(0), + DeviceType(deviceType), + ValueCount(count), + MaxDDLValue(0), + Order(ord), + AmbientLight(0), + Illumination(0), + MinDensity(-1), + MaxDensity(-1), + DDLValue(NULL), + LODValue(NULL), + MinValue(val_min), + MaxValue(val_max) +{ + OFBitmanipTemplate::zeroMem(LookupTable, MAX_NUMBER_OF_TABLES); + /* check parameters */ + if ((ValueCount > 1) && (ValueCount <= MAX_TABLE_ENTRY_COUNT) && (MinValue < MaxValue)) + { + /* create value tables */ + MaxDDLValue = OFstatic_cast(Uint16, count - 1); + DDLValue = new Uint16[ValueCount]; + LODValue = new double[ValueCount]; + if ((DDLValue != NULL) && (LODValue != NULL)) + { + register Uint16 i; + const double min = ((DeviceType == EDT_Printer) || (DeviceType == EDT_Scanner)) ? val_max : val_min; + const double max = ((DeviceType == EDT_Printer) || (DeviceType == EDT_Scanner)) ? val_min : val_max; + const double val = (max - min) / OFstatic_cast(double, MaxDDLValue); + DDLValue[0] = 0; + LODValue[0] = min; + for (i = 1; i < MaxDDLValue; ++i) + { + DDLValue[i] = i; // set DDL values + LODValue[i] = LODValue[i - 1] + val; // compute luminance/OD value + } + DDLValue[MaxDDLValue] = MaxDDLValue; + LODValue[MaxDDLValue] = max; + Valid = 1; + } + } +} + + +/*--------------* + * destructor * + *--------------*/ + +DiDisplayFunction::~DiDisplayFunction() +{ + delete[] DDLValue; + delete[] LODValue; + register int i; + for (i = 0; i < MAX_NUMBER_OF_TABLES; ++i) + delete LookupTable[i]; +} + + +/********************************************************************/ + + +double DiDisplayFunction::getValueforDDL(const Uint16 ddl) const +{ + if ((LODValue != NULL) && (ddl < ValueCount)) + return LODValue[ddl]; + return -1; +} + + +Uint16 DiDisplayFunction::getDDLforValue(const double value) const +{ + if ((LODValue != NULL) && (ValueCount > 0)) + { + register unsigned long j = 0; + /* search for closest index, assuming monotony */ + if ((DeviceType == EDT_Printer) || (DeviceType == EDT_Scanner)) + { + /* hardcopy device: descending values */ + while ((j + 1 < ValueCount) && (LODValue[j] > value)) + ++j; + } else { + /* softcopy device: ascending values */ + while ((j + 1 < ValueCount) && (LODValue[j] < value)) + ++j; + } + /* check which value is closer, the upper or the lower */ + if ((j > 0) && (fabs(LODValue[j - 1] - value) < fabs(LODValue[j] - value))) + --j; + return OFstatic_cast(Uint16, j); + } + return 0; +} + + +const DiDisplayLUT *DiDisplayFunction::getLookupTable(const int bits, + unsigned long count) +{ + if (Valid && (bits >= MinBits) && (bits <= MaxBits)) + { + const int idx = bits - MinBits; + /* automatically compute number of entries */ + if (count == 0) + count = DicomImageClass::maxval(bits, 0); + /* check whether existing LUT is still valid */ + if ((LookupTable[idx] != NULL) && ((count != LookupTable[idx]->getCount()) || + (AmbientLight != LookupTable[idx]->getAmbientLightValue()) || + (Illumination != LookupTable[idx]->getIlluminationValue()))) + { + delete LookupTable[idx]; + LookupTable[idx] = NULL; + } + if (LookupTable[idx] == NULL) // first calculation of this LUT + LookupTable[idx] = getDisplayLUT(count); + return LookupTable[idx]; + } + return NULL; +} + + +int DiDisplayFunction::deleteLookupTable(const int bits) +{ + if (bits == 0) + { + /* delete all LUTs */ + register int i; + for (i = 0; i < MAX_NUMBER_OF_TABLES; ++i) + { + delete LookupTable[i]; + LookupTable[i] = NULL; + } + return 1; + } + else if ((bits >= MinBits) && (bits <= MaxBits)) + { + /* delete the specified LUT */ + const int idx = bits - MinBits; + if (LookupTable[idx] != NULL) + { + delete LookupTable[idx]; + LookupTable[idx] = NULL; + return 1; + } + return 2; + } + return 0; +} + + +int DiDisplayFunction::setAmbientLightValue(const double value) +{ + if (value >= 0) + { + AmbientLight = value; + return 1; + } + return 0; +} + + +int DiDisplayFunction::setIlluminationValue(const double value) +{ + if (value >= 0) + { + Illumination = value; + return 1; + } + return 0; +} + + +int DiDisplayFunction::setMinDensityValue(const double value) +{ + MinDensity = value; + return (value < 0) ? 2 : 1; +} + + +int DiDisplayFunction::setMaxDensityValue(const double value) +{ + MaxDensity = value; + return (value < 0) ? 2 : 1; +} + + +/********************************************************************/ + + +int DiDisplayFunction::readConfigFile(const char *filename) +{ + if ((filename != NULL) && (strlen(filename) > 0)) + { +#ifdef HAVE_IOS_NOCREATE + STD_NAMESPACE ifstream file(filename, STD_NAMESPACE ios::in | STD_NAMESPACE ios::nocreate); +#else + STD_NAMESPACE ifstream file(filename, STD_NAMESPACE ios::in); +#endif + if (file) + { + char c; + while (file.get(c)) + { + if (c == '#') // comment character + { + while (file.get(c) && (c != '\n') && (c != '\r')); // skip comments + } + else if (!isspace(OFstatic_cast(unsigned char, c))) // skip whitespaces + { + file.putback(c); + if (MaxDDLValue == 0) // read maxvalue + { + char str[4]; + file.get(str, sizeof(str)); + if (strcmp(str, "max") == 0) // check for key word: max + { + file >> MaxDDLValue; + if (MaxDDLValue > 0) + { + DDLValue = new Uint16[OFstatic_cast(unsigned long, MaxDDLValue) + 1]; + LODValue = new double[OFstatic_cast(unsigned long, MaxDDLValue) + 1]; + if ((DDLValue == NULL) || (LODValue == NULL)) + return 0; + } else { + DCMIMGLE_ERROR("invalid or missing value for maximum DDL value in DISPLAY file"); + return 0; // abort + } + } else { + DCMIMGLE_ERROR("missing keyword 'max' for maximum DDL value in DISPLAY file"); + return 0; // abort + } + } + else if ((AmbientLight == 0.0) && (c == 'a')) // read ambient light value (optional) + { + char str[4]; + file.get(str, sizeof(str)); + if (strcmp(str, "amb") == 0) // check for key word: amb + { + file >> AmbientLight; + if (AmbientLight < 0) + { + DCMIMGLE_WARN("invalid value for ambient light in DISPLAY file ... ignoring"); + AmbientLight = 0; + } + } else { + DCMIMGLE_ERROR("invalid DISPLAY file ... ignoring"); + return 0; // abort + } + } + else if ((Illumination == 0.0) && (c == 'l')) // read ambient light value (optional) + { + char str[4]; + file.get(str, sizeof(str)); + if (strcmp(str, "lum") == 0) // check for key word: lum + { + file >> Illumination; + if (Illumination < 0) + { + DCMIMGLE_WARN("invalid value for illumination in DISPLAY file ... ignoring"); + Illumination = 0; + } + } else { + DCMIMGLE_ERROR("invalid DISPLAY file ... ignoring"); + return 0; // abort + } + } + else if ((Order == 0) && (c == 'o')) // read polynomial order (optional) + { + char str[4]; + file.get(str, sizeof(str)); + if (strcmp(str, "ord") == 0) // check for key word: ord + { + file >> Order; + if (Order < 0) + { + DCMIMGLE_WARN("invalid value for polynomial order in DISPLAY file ... ignoring"); + Order = 0; + } + } else { + DCMIMGLE_ERROR("invalid DISPLAY file ... ignoring"); + return 0; // abort + } + } else { + if (ValueCount <= OFstatic_cast(unsigned long, MaxDDLValue)) + { + file >> DDLValue[ValueCount]; // read DDL value + file >> LODValue[ValueCount]; // read luminance/OD value + if (file.fail()) + { + DCMIMGLE_WARN("missing luminance/OD value in DISPLAY file ... ignoring last entry"); + } + else if (DDLValue[ValueCount] > MaxDDLValue) + { + DCMIMGLE_WARN("DDL value (" << DDLValue[ValueCount] << ") exceeds maximum value (" + << MaxDDLValue << ") in DISPLAY file ... ignoring value"); + } else + ++ValueCount; + } else { + DCMIMGLE_WARN("too many values in DISPLAY file ... ignoring last line(s)"); + return 2; + } + } + } + } + if ((MaxDDLValue > 0) && (ValueCount > 0)) + return ((DDLValue != NULL) && (LODValue != NULL)); + else { + DCMIMGLE_WARN("invalid DISPLAY file ... ignoring"); + } + } else { + DCMIMGLE_WARN("can't open DISPLAY file ... ignoring"); + } + } + return 0; +} + + +int DiDisplayFunction::createSortedTable(const Uint16 *ddl_tab, + const double *val_tab) +{ + int status = 0; + Uint16 *old_ddl = DDLValue; + double *old_val = LODValue; + if ((ValueCount > 0) && (ddl_tab != NULL) && (val_tab != NULL)) + { + const unsigned long count = OFstatic_cast(unsigned long, MaxDDLValue) + 1; + DDLValue = new Uint16[ValueCount]; + LODValue = new double[ValueCount]; + Sint32 *sort_tab = new Sint32[count]; // auxilliary array (temporary) + if ((DDLValue != NULL) && (LODValue != NULL) && (sort_tab != NULL)) + { + OFBitmanipTemplate::setMem(sort_tab, -1, count); // initialize array + register unsigned long i; + for (i = 0; i < ValueCount; ++i) + { + if (ddl_tab[i] <= MaxDDLValue) // calculate sort table + sort_tab[ddl_tab[i]] = i; + } + ValueCount = 0; + for (i = 0; i <= MaxDDLValue; ++i) // sort ascending + { + if (sort_tab[i] >= 0) + { + DDLValue[ValueCount] = ddl_tab[sort_tab[i]]; + LODValue[ValueCount] = (val_tab[sort_tab[i]] > 0) ? val_tab[sort_tab[i]] : 0; + ++ValueCount; // re-count to ignore values exceeding max + } + } + i = 1; + if ((DeviceType == EDT_Printer) || (DeviceType == EDT_Scanner)) + { + /* hardcopy device: check for monotonous descending OD values */ + while ((i < ValueCount) && (LODValue[i - 1] >= LODValue[i])) + ++i; + if (i < ValueCount) + { + DCMIMGLE_WARN("OD values (ordered by DDLs) don't descend monotonously"); + } + } else { + /* softcopy device: check for monotonous ascending luminance values */ + while ((i < ValueCount) && (LODValue[i - 1] <= LODValue[i])) + ++i; + if (i < ValueCount) + { + DCMIMGLE_WARN("luminance values (ordered by DDLs) don't ascend monotonously"); + } + } + status = (ValueCount > 0); + } + delete[] sort_tab; + } + delete[] old_ddl; + delete[] old_val; + return status; +} + + +int DiDisplayFunction::interpolateValues() +{ + if (ValueCount <= OFstatic_cast(unsigned long, MaxDDLValue)) // interpolation necessary ? + { + int status = 0; + if (Order > 0) + { + /* use polynomial curve fitting */ + double *coeff = new double[Order + 1]; + /* compute coefficients */ + if ((coeff != NULL) && DiCurveFitting::calculateCoefficients(DDLValue, LODValue, + OFstatic_cast(unsigned int, ValueCount), Order, coeff)) + { + /* delete old data arrays */ + delete[] DDLValue; + delete[] LODValue; + /* create new data arrays */ + ValueCount = OFstatic_cast(unsigned long, MaxDDLValue) + 1; + DDLValue = new Uint16[ValueCount]; + LODValue = new double[ValueCount]; + if ((DDLValue != NULL) && (LODValue != NULL)) + { + /* set x values linearly */ + register unsigned int i; + for (i = 0; i <= MaxDDLValue; ++i) + DDLValue[i] = OFstatic_cast(Uint16, i); + /* compute new y values */ + status = DiCurveFitting::calculateValues(0, MaxDDLValue, LODValue, + OFstatic_cast(unsigned int, ValueCount), Order, coeff); + } + } + delete[] coeff; + } else { + /* use cubic spline interpolation */ + double *spline = new double[ValueCount]; + if ((spline != NULL) && + DiCubicSpline::Function(DDLValue, LODValue, OFstatic_cast(unsigned int, ValueCount), spline)) + { + /* save old values */ + const unsigned long count = ValueCount; + Uint16 *old_ddl = DDLValue; + double *old_val = LODValue; + /* create new data arrays */ + ValueCount = OFstatic_cast(unsigned long, MaxDDLValue) + 1; + DDLValue = new Uint16[ValueCount]; + LODValue = new double[ValueCount]; + if ((DDLValue != NULL) && (LODValue != NULL)) + { + /* set x values linearly */ + register unsigned int i; + for (i = 0; i <= MaxDDLValue; ++i) + DDLValue[i] = OFstatic_cast(Uint16, i); + /* compute new y values */ + status = DiCubicSpline::Interpolation(old_ddl, old_val, spline, + OFstatic_cast(unsigned int, count), DDLValue, LODValue, OFstatic_cast(unsigned int, ValueCount)); + } + /* delete old data arrays */ + delete[] old_ddl; + delete[] old_val; + } + delete[] spline; + } + return status; + } + return 2; +} + + +int DiDisplayFunction::calculateMinMax() +{ + if ((LODValue != NULL) && (ValueCount > 0)) + { + MinValue = LODValue[0]; + MaxValue = LODValue[0]; + register unsigned long i; + for (i = 1; i < ValueCount; ++i) + { + if (LODValue[i] < MinValue) + MinValue = LODValue[i]; + if (LODValue[i] > MaxValue) + MaxValue = LODValue[i]; + } + return 1; + } + return 0; +} + + +int DiDisplayFunction::checkMinMaxDensity() const +{ + if ((MinDensity >= 0) && (MaxDensity >= 0) && (MinDensity >= MaxDensity)) + { + DCMIMGLE_WARN("invalid optical density range (Dmin = " << MinDensity << ", Dmax = " << MaxDensity << ")"); + return 0; + } + return 1; +} + + +double DiDisplayFunction::getMinLuminanceValue() const +{ + /* Dmax = -1 means unspecified */ + return (MaxDensity < 0) ? -1 : convertODtoLum(MaxDensity); +} + + +double DiDisplayFunction::getMaxLuminanceValue() const +{ + /* Dmin = -1 means unspecified */ + return (MinDensity < 0) ? -1 : convertODtoLum(MinDensity); +} + + +double *DiDisplayFunction::convertODtoLumTable(const double *od_tab, + const unsigned long count, + const OFBool useAmb) +{ + double *lum_tab = NULL; + if ((od_tab != NULL) && (count > 0)) + { + /* create a new table for the luminance values */ + lum_tab = new double[count]; + if (lum_tab != NULL) + { + /* compute luminance values from optical density */ + register unsigned int i; + if (useAmb) + { + for (i = 0; i < count; ++i) + lum_tab[i] = AmbientLight + Illumination * pow(OFstatic_cast(double, 10), -od_tab[i]); + } else { + /* ambient light is added later */ + for (i = 0; i < count; ++i) + lum_tab[i] = Illumination * pow(OFstatic_cast(double, 10), -od_tab[i]); + } + } + } + return lum_tab; +} + + +double DiDisplayFunction::convertODtoLum(const double value, + const OFBool useAmb) const +{ + return (useAmb) ? convertODtoLum(value, AmbientLight, Illumination) : + convertODtoLum(value, 0, Illumination); +} + + +double DiDisplayFunction::convertODtoLum(const double value, + const double ambient, + const double illum) +{ + /* formula from DICOM PS3.14: L = La + L0 * 10^-D */ + return (value >= 0) && (ambient >= 0) && (illum >= 0) ? + ambient + illum * pow(OFstatic_cast(double, 10), -value) : -1 /*invalid*/; +} diff --git a/dcmimgle/libsrc/didocu.cc b/dcmimgle/libsrc/didocu.cc new file mode 100644 index 00000000..13911355 --- /dev/null +++ b/dcmimgle/libsrc/didocu.cc @@ -0,0 +1,440 @@ +/* + * + * Copyright (C) 1996-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimgle + * + * Author: Joerg Riesmeier + * + * Purpose: DicomDocument (Source) + * + */ + + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/dcmdata/dctk.h" +#include "dcmtk/ofstd/ofstring.h" + +#include "dcmtk/dcmimgle/didocu.h" +#include "dcmtk/dcmimgle/diutils.h" + + +/*----------------* + * constructors * + *----------------*/ + +DiDocument::DiDocument(const char *filename, + const unsigned long flags, + const unsigned long fstart, + const unsigned long fcount) + : Object(NULL), + FileFormat(new DcmFileFormat()), + PixelData(NULL), + Xfer(EXS_Unknown), + FrameStart(fstart), + FrameCount(fcount), + Flags(flags), + PhotometricInterpretation() +{ + if (FileFormat) + { + if (FileFormat->loadFile(filename).bad()) + { + DCMIMGLE_ERROR("can't read file '" << filename << "'"); + delete FileFormat; + FileFormat = NULL; + } else { + Object = FileFormat->getDataset(); + if (Object != NULL) + { + Xfer = OFstatic_cast(DcmDataset *, Object)->getOriginalXfer(); + convertPixelData(); + } + } + } +} + + +DiDocument::DiDocument(DcmObject *object, + const E_TransferSyntax xfer, + const unsigned long flags, + const unsigned long fstart, + const unsigned long fcount) + : Object(NULL), + FileFormat(NULL), + PixelData(NULL), + Xfer(xfer), + FrameStart(fstart), + FrameCount(fcount), + Flags(flags), + PhotometricInterpretation() +{ + if (object != NULL) + { + const DcmEVR classType = object->ident(); + // check whether given DICOM object has a valid type + if (classType == EVR_fileFormat) + { + // store reference to DICOM file format to be deleted on object destruction + if (Flags & CIF_TakeOverExternalDataset) + FileFormat = OFstatic_cast(DcmFileFormat *, object); + Object = OFstatic_cast(DcmFileFormat *, object)->getDataset(); + } + else if ((classType == EVR_dataset) || (classType == EVR_item)) + Object = object; + else + DCMIMGLE_ERROR("invalid DICOM object passed to constructor (wrong class)"); + if (Object != NULL) + { + // try to determine the transfer syntax from the given object + if (Xfer == EXS_Unknown) + { + // check type before casting the object + if (Object->ident() == EVR_dataset) + Xfer = OFstatic_cast(DcmDataset *, Object)->getOriginalXfer(); + else // could only be an item + DCMIMGLE_WARN("can't determine original transfer syntax from given DICOM object"); + } + convertPixelData(); + } + } +} + + +void DiDocument::convertPixelData() +{ + DcmStack pstack; + DcmXfer xfer(Xfer); + DCMIMGLE_DEBUG("transfer syntax of DICOM dataset: " << xfer.getXferName() << " (" << xfer.getXferID() << ")"); + // only search on main dataset level + if (search(DCM_PixelData, pstack)) + { + DcmObject *pobject = pstack.top(); + if (pobject != NULL) + { + // check for correct class before type casting + if (pobject->ident() == EVR_PixelData) + { + PixelData = OFstatic_cast(DcmPixelData *, pobject); + // check for a special (faulty) case where the original pixel data is uncompressed and + // the transfer syntax of the dataset refers to encapsulated format (i.e. compression) + if (Object->ident() == EVR_dataset) + { + E_TransferSyntax repType = EXS_Unknown; + const DcmRepresentationParameter *repParam = NULL; + PixelData->getOriginalRepresentationKey(repType, repParam); + if (xfer.isEncapsulated() && !DcmXfer(repType).isEncapsulated()) + { + DCMIMGLE_WARN("pixel data is stored in uncompressed format, although " + << "the transfer syntax of the dataset refers to encapsulated format"); + } + } + // convert pixel data to uncompressed format (if required) + if ((Flags & CIF_DecompressCompletePixelData) || !(Flags & CIF_UsePartialAccessToPixelData)) + { + pstack.clear(); + // push reference to DICOM dataset on the stack (required for decompression process) + pstack.push(Object); + // dummy stack entry + pstack.push(PixelData); + if (PixelData->chooseRepresentation(EXS_LittleEndianExplicit, NULL, pstack).good()) + { + // set transfer syntax to unencapsulated/uncompressed + if (xfer.isEncapsulated()) + { + Xfer = EXS_LittleEndianExplicit; + DCMIMGLE_DEBUG("decompressed complete pixel data in memory: " << PixelData->getLength(Xfer) << " bytes"); + } + } else + DCMIMGLE_ERROR("can't change to unencapsulated representation for pixel data"); + } + // determine color model of the decompressed image + OFCondition status = PixelData->getDecompressedColorModel(OFstatic_cast(DcmItem *, Object), PhotometricInterpretation); + if (status.bad()) + { + DCMIMGLE_ERROR("can't determine 'PhotometricInterpretation' of decompressed image"); + DCMIMGLE_DEBUG("DcmPixelData::getDecompressedColorModel() returned: " << status.text()); + } + } else { + DCMIMGLE_ERROR("invalid pixel data in DICOM dataset (wrong class)"); + DCMIMGLE_DEBUG("found PixelData " << DCM_PixelData << " as an instance of the class for VR '" + << OFSTRING_GUARD(DcmVR(pobject->ident()).getVRName()) << "' instead of '" + << OFSTRING_GUARD(DcmVR(EVR_PixelData).getVRName()) << "'"); + } + } else + DCMIMGLE_ERROR("invalid pixel data in DICOM dataset"); + } else + DCMIMGLE_ERROR("no pixel data found in DICOM dataset"); +} + + +/*--------------* + * destructor * + *--------------*/ + +DiDocument::~DiDocument() +{ + // DICOM image loaded from file: delete file format (and data set) + if (FileFormat != NULL) + delete FileFormat; + // DICOM image loaded from external data set: only delete if flag is set + else if (Flags & CIF_TakeOverExternalDataset) + delete Object; +} + + +/********************************************************************/ + + +DcmElement *DiDocument::search(const DcmTagKey &tag, + DcmObject *obj) const +{ + DcmStack stack; + if (obj == NULL) + obj = Object; + // only search on main dataset level + if ((obj != NULL) && (obj->search(tag, stack, ESM_fromHere, OFFalse /* searchIntoSub */) == EC_Normal) && + (stack.top()->getLength(Xfer) > 0)) + { + return OFstatic_cast(DcmElement *, stack.top()); + } + return NULL; +} + + +/********************************************************************/ + + +int DiDocument::search(const DcmTagKey &tag, + DcmStack &pstack) const +{ + if (pstack.empty()) + pstack.push(Object); + DcmObject *obj = pstack.top(); + if ((obj != NULL) && (obj->search(tag, pstack, ESM_fromHere, OFFalse /* searchIntoSub */) == EC_Normal) && + (pstack.top()->getLength(Xfer) > 0)) + return 1; + return 0; +} + + +/********************************************************************/ + + +unsigned long DiDocument::getVM(const DcmTagKey &tag) const +{ + DcmElement *elem = search(tag); + if (elem != NULL) + return elem->getVM(); + return 0; +} + + +unsigned long DiDocument::getValue(const DcmTagKey &tag, + Uint16 &returnVal, + const unsigned long pos, + DcmItem *item, + const OFBool allowSigned) const +{ + return getElemValue(search(tag, item), returnVal, pos, allowSigned); +} + + +unsigned long DiDocument::getValue(const DcmTagKey &tag, + Sint16 &returnVal, + const unsigned long pos, + DcmItem *item) const +{ + DcmElement *elem = search(tag, item); + if (elem != NULL) + { + if (elem->getSint16(returnVal, pos).good()) + return elem->getVM(); + } + return 0; +} + + +unsigned long DiDocument::getValue(const DcmTagKey &tag, + Uint32 &returnVal, + const unsigned long pos, + DcmItem *item) const +{ + DcmElement *elem = search(tag, item); + if (elem != NULL) + { + if (elem->getUint32(returnVal, pos).good()) + return elem->getVM(); + } + return 0; +} + + +unsigned long DiDocument::getValue(const DcmTagKey &tag, + Sint32 &returnVal, + const unsigned long pos, + DcmItem *item) const +{ + DcmElement *elem = search(tag, item); + if (elem != NULL) + { + if (elem->getSint32(returnVal, pos).good()) + return elem->getVM(); + } + return 0; +} + + +unsigned long DiDocument::getValue(const DcmTagKey &tag, + double &returnVal, + const unsigned long pos, + DcmItem *item) const +{ + DcmElement *elem = search(tag, item); + if (elem != NULL) + { + if (elem->getFloat64(returnVal, pos).good()) + return elem->getVM(); + } + return 0; +} + + +unsigned long DiDocument::getValue(const DcmTagKey &tag, + const Uint16 *&returnVal, + DcmItem *item) const +{ + DcmElement *elem = search(tag, item); + if (elem != NULL) + { + Uint16 *val; + if (elem->getUint16Array(val).good()) + { + returnVal = val; + const DcmEVR vr = elem->getVR(); + if ((vr == EVR_OB) || (vr == EVR_OW) || (vr == EVR_lt)) + return elem->getLength(Xfer) / sizeof(Uint16); + return elem->getVM(); + } + } + return 0; +} + + +unsigned long DiDocument::getValue(const DcmTagKey &tag, + const char *&returnVal, + DcmItem *item) const +{ + return getElemValue(search(tag, item), returnVal); +} + + +unsigned long DiDocument::getValue(const DcmTagKey &tag, + OFString &returnVal, + const unsigned long pos, + DcmItem *item) const +{ + return getElemValue(search(tag, item), returnVal, pos); +} + + +unsigned long DiDocument::getSequence(const DcmTagKey &tag, + DcmSequenceOfItems *&seq, + DcmItem *item) const +{ + DcmElement *elem = search(tag, item); + if ((elem != NULL) && (elem->ident() == EVR_SQ)) + return (seq = OFstatic_cast(DcmSequenceOfItems *, elem))->card(); + return 0; +} + + +unsigned long DiDocument::getElemValue(const DcmElement *elem, + Uint16 &returnVal, + const unsigned long pos, + const OFBool allowSigned) +{ + if (elem != NULL) + { + // remove 'const' to use non-const methods + if (OFconst_cast(DcmElement *, elem)->getUint16(returnVal, pos).good()) + return OFconst_cast(DcmElement *, elem)->getVM(); + else if (allowSigned) + { + // try to retrieve signed value ... + Sint16 value = 0; + if (OFconst_cast(DcmElement *, elem)->getSint16(value, pos).good()) + { + // ... and cast to unsigned type + returnVal = OFstatic_cast(Uint16, value); + DCMIMGLE_TRACE("retrieved signed value (" << value << ") at position " << pos + << " from element " << OFconst_cast(DcmElement *, elem)->getTag() + << ", VR=" << DcmVR(OFconst_cast(DcmElement *, elem)->getVR()).getVRName() + << ", VM=" << OFconst_cast(DcmElement *, elem)->getVM()); + return OFconst_cast(DcmElement *, elem)->getVM(); + } + } + } + return 0; +} + + +unsigned long DiDocument::getElemValue(const DcmElement *elem, + const Uint16 *&returnVal) +{ + if (elem != NULL) + { + Uint16 *val; + // remove 'const' to use non-const methods + if (OFconst_cast(DcmElement *, elem)->getUint16Array(val).good()) + { + returnVal = val; + const DcmEVR vr = OFconst_cast(DcmElement *, elem)->getVR(); + if ((vr == EVR_OW) || (vr == EVR_lt)) + return OFconst_cast(DcmElement *, elem)->getLength(/*Xfer*/) / sizeof(Uint16); + return OFconst_cast(DcmElement *, elem)->getVM(); + } + } + return 0; +} + + +unsigned long DiDocument::getElemValue(const DcmElement *elem, + const char *&returnVal) +{ + if (elem != NULL) + { + char *val; + // remove 'const' to use non-const methods + if (OFconst_cast(DcmElement *, elem)->getString(val).good()) + { + returnVal = val; + return OFconst_cast(DcmElement *, elem)->getVM(); + } + } + return 0; +} + + +unsigned long DiDocument::getElemValue(const DcmElement *elem, + OFString &returnVal, + const unsigned long pos) +{ + if (elem != NULL) + { + // remove 'const' to use non-const methods + if (OFconst_cast(DcmElement *, elem)->getOFString(returnVal, pos).good()) + return OFconst_cast(DcmElement *, elem)->getVM(); + } + return 0; +} diff --git a/dcmimgle/libsrc/digsdfn.cc b/dcmimgle/libsrc/digsdfn.cc new file mode 100644 index 00000000..d6de9cc1 --- /dev/null +++ b/dcmimgle/libsrc/digsdfn.cc @@ -0,0 +1,430 @@ +/* + * + * Copyright (C) 1999-2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimgle + * + * Author: Joerg Riesmeier + * + * Purpose: DicomGSDFunction (Source) + * + */ + + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/dcmimgle/digsdfn.h" +#include "dcmtk/dcmimgle/displint.h" +#include "dcmtk/dcmimgle/digsdlut.h" + +#include "dcmtk/ofstd/ofstream.h" + +#define INCLUDE_CMATH +#define INCLUDE_CSTRING +#include "dcmtk/ofstd/ofstdinc.h" + + +/*----------------------------* + * constant initializations * + *----------------------------*/ + +const unsigned int DiGSDFunction::GSDFCount = 1023; + + +/*----------------* + * constructors * + *----------------*/ + +DiGSDFunction::DiGSDFunction(const char *filename, + const E_DeviceType deviceType, + const signed int ord) + : DiDisplayFunction(filename, deviceType, ord), + JNDMin(0), + JNDMax(0), + GSDFValue(NULL), + GSDFSpline(NULL) +{ + if (Valid) + Valid = calculateGSDF() && calculateGSDFSpline() && calculateJNDBoundaries(); + if (!Valid) + { + DCMIMGLE_ERROR("invalid DISPLAY file ... ignoring"); + } +} + + +DiGSDFunction::DiGSDFunction(const double *val_tab, // UNTESTED !! + const unsigned long count, + const Uint16 max, + const E_DeviceType deviceType, + const signed int ord) + : DiDisplayFunction(val_tab, count, max, deviceType, ord), + JNDMin(0), + JNDMax(0), + GSDFValue(NULL), + GSDFSpline(NULL) +{ + if (Valid) + Valid = calculateGSDF() && calculateGSDFSpline() && calculateJNDBoundaries(); + if (!Valid) + { + DCMIMGLE_ERROR("invalid DISPLAY values ... ignoring"); + } +} + + +DiGSDFunction::DiGSDFunction(const Uint16 *ddl_tab, // UNTESTED !! + const double *val_tab, + const unsigned long count, + const Uint16 max, + const E_DeviceType deviceType, + const signed int ord) + : DiDisplayFunction(ddl_tab, val_tab, count, max, deviceType, ord), + JNDMin(0), + JNDMax(0), + GSDFValue(NULL), + GSDFSpline(NULL) +{ + if (Valid) + Valid = calculateGSDF() && calculateGSDFSpline() && calculateJNDBoundaries(); + if (!Valid) + { + DCMIMGLE_ERROR("invalid DISPLAY values ... ignoring"); + } +} + + +DiGSDFunction::DiGSDFunction(const double val_min, + const double val_max, + const unsigned long count, + const E_DeviceType deviceType, + const signed int ord) + : DiDisplayFunction(val_min, val_max, count, deviceType, ord), + JNDMin(0), + JNDMax(0), + GSDFValue(NULL), + GSDFSpline(NULL) +{ + if (Valid) + Valid = calculateGSDF() && calculateGSDFSpline() && calculateJNDBoundaries(); + if (!Valid) + { + DCMIMGLE_ERROR("invalid DISPLAY values ... ignoring"); + } +} + + +/*--------------* + * destructor * + *--------------*/ + +DiGSDFunction::~DiGSDFunction() +{ + delete[] GSDFValue; + delete[] GSDFSpline; +} + + +/********************************************************************/ + + +DiDisplayLUT *DiGSDFunction::getDisplayLUT(unsigned long count) +{ + DiDisplayLUT *lut = NULL; + if (count <= MAX_TABLE_ENTRY_COUNT) + { + if ((DeviceType == EDT_Printer) || (DeviceType == EDT_Scanner)) + { + /* hardcopy: values are in optical density, first convert them to luminance */ + double *tmp_tab = convertODtoLumTable(LODValue, ValueCount, OFFalse /*useAmb*/); + if (tmp_tab != NULL) + { + checkMinMaxDensity(); + /* create new GSDF LUT */ + lut = new DiGSDFLUT(count, MaxDDLValue, DDLValue, tmp_tab, ValueCount, + GSDFValue, GSDFSpline, GSDFCount, JNDMin, JNDMax, getMinLuminanceValue(), + getMaxLuminanceValue(), AmbientLight, Illumination, (DeviceType == EDT_Scanner)); + /* delete temporary table */ + delete[] tmp_tab; + } + } else { + /* softcopy: values are already in luminance */ + lut = new DiGSDFLUT(count, MaxDDLValue, DDLValue, LODValue, ValueCount, + GSDFValue, GSDFSpline, GSDFCount, JNDMin, JNDMax, -1 /*Lmin*/, -1 /*Lmax*/, + AmbientLight, Illumination, (DeviceType == EDT_Camera)); + } + } + return lut; +} + + +int DiGSDFunction::writeCurveData(const char *filename, + const OFBool mode) +{ + if ((filename != NULL) && (strlen(filename) > 0)) + { + STD_NAMESPACE ofstream file(filename); + if (file) + { + const OFBool inverseLUT = (DeviceType == EDT_Scanner) || (DeviceType == EDT_Camera); + /* comment header */ + file << "# Display function : GSDF (DICOM Part 14)" << OFendl; + if (DeviceType == EDT_Printer) + file << "# Type of output device : Printer (hardcopy)" << OFendl; + else if (DeviceType == EDT_Scanner) + file << "# Type of output device : Scanner (hardcopy)" << OFendl; + else if (DeviceType == EDT_Camera) + file << "# Type of output device : Camera (softcopy)" << OFendl; + else + file << "# Type of output device : Monitor (softcopy)" << OFendl; + file << "# Digital driving levels : " << ValueCount << OFendl; + if ((DeviceType == EDT_Printer) || (DeviceType == EDT_Scanner)) + file << "# Illumination [cd/m^2] : " << Illumination << OFendl; + file << "# Ambient light [cd/m^2] : " << AmbientLight << OFendl; + if ((DeviceType == EDT_Printer) || (DeviceType == EDT_Scanner)) + { + const double min_lum = getMinLuminanceValue(); + const double max_lum = getMaxLuminanceValue(); + file << "# Luminance w/o [cd/m^2] : " << convertODtoLum(MaxValue, OFFalse /*useAmb*/) << " - " + << convertODtoLum(MinValue, OFFalse /*useAmb*/); + if ((min_lum >= 0) || (max_lum >= 0)) + { + file << " (Lmin = "; + if (min_lum >= 0) + file << min_lum; + else + file << "n/s"; + file << ", Lmax = "; + if (max_lum >= 0) + file << max_lum; + else + file << "n/s"; + file << ")"; + } + file << OFendl; + file << "# Optical density [OD] : " << MinValue << " - " << MaxValue; + if ((MinDensity >= 0) || (MaxDensity >= 0)) + { + file << " (Dmin = "; + if (MinDensity >= 0) + file << MinDensity; + else + file << "n/s"; + file << ", Dmax = "; + if (MaxDensity >= 0) + file << MaxDensity; + else + file << "n/s"; + file << ")"; + } + file << OFendl; + } else + file << "# Luminance w/o [cd/m^2] : " << MinValue << " - " << MaxValue << OFendl; + file << "# Barten JND index range : " << JNDMin << " - " << JNDMax << " (" << (JNDMax - JNDMin) << ")" << OFendl; + file << "# Interpolation method : "; + if (getPolynomialOrder() > 0) + file << "Curve fitting algorithm with order " << getPolynomialOrder() << OFendl << OFendl; + else + file << "Cubic spline interpolation" << OFendl << OFendl; + /* print headings of the table */ + if (mode) + { + file << "# NB: values for CC, GSDF and PSC"; + if (inverseLUT) + file << "'"; // add ' to PSC + file << " are specified in cd/m^2" << OFendl << OFendl; + file << "DDL\tCC\tGSDF\tPSC"; + if (inverseLUT) + file << "'"; // add ' to PSC + file << OFendl; + } else { + file << "# NB: values for CC and GSDF are specified in cd/m^2" << OFendl << OFendl; + file << "DDL\tGSDF" << OFendl; + } + /* create GSDF LUT and write curve data to file */ + DiGSDFLUT *lut = NULL; + if ((DeviceType == EDT_Printer) || (DeviceType == EDT_Scanner)) + { + /* hardcopy: values are in optical density, first convert them to luminance */ + double *tmp_tab = convertODtoLumTable(LODValue, ValueCount, OFFalse /*useAmb*/); + if (tmp_tab != NULL) + { + checkMinMaxDensity(); + lut = new DiGSDFLUT(ValueCount, MaxDDLValue, DDLValue, tmp_tab, ValueCount, + GSDFValue, GSDFSpline, GSDFCount, JNDMin, JNDMax, getMinLuminanceValue(), + getMaxLuminanceValue(), AmbientLight, Illumination, inverseLUT, &file, mode); + /* delete temporary table */ + delete[] tmp_tab; + } + } else { + /* softcopy: values are already in luminance */ + lut = new DiGSDFLUT(ValueCount, MaxDDLValue, DDLValue, LODValue, ValueCount, + GSDFValue, GSDFSpline, GSDFCount, JNDMin, JNDMax, -1 /*Lmin*/, -1 /*Lmax*/, + AmbientLight, Illumination, inverseLUT, &file, mode); + } + int status = (lut != NULL) && (lut->isValid()); + delete lut; + return status; + } + } + return 0; +} + + +int DiGSDFunction::setAmbientLightValue(const double value) +{ + int status = DiDisplayFunction::setAmbientLightValue(value); + if (status) + Valid = calculateJNDBoundaries(); // check validity + return status; +} + + +int DiGSDFunction::setIlluminationValue(const double value) +{ + int status = DiDisplayFunction::setIlluminationValue(value); + if (status && ((DeviceType == EDT_Printer) || (DeviceType == EDT_Scanner))) + Valid = calculateJNDBoundaries(); // check validity + return status; +} + + +int DiGSDFunction::setMinDensityValue(const double value) +{ + int status = DiDisplayFunction::setMinDensityValue(value); + if (status && (DeviceType == EDT_Printer)) + Valid = calculateJNDBoundaries(); // check validity + return status; +} + + +int DiGSDFunction::setMaxDensityValue(const double value) +{ + int status = DiDisplayFunction::setMaxDensityValue(value); + if (status && (DeviceType == EDT_Printer)) + Valid = calculateJNDBoundaries(); // check validity + return status; +} + + +/********************************************************************/ + + +int DiGSDFunction::calculateGSDF() +{ + GSDFValue = new double[GSDFCount]; + if (GSDFValue != NULL) + { + /* + * algorithm taken from DICOM part 14: Grayscale Standard Display Function (GSDF) + */ + const double a = -1.3011877; + const double b = -2.5840191e-2; + const double c = 8.0242636e-2; + const double d = -1.0320229e-1; + const double e = 1.3646699e-1; + const double f = 2.8745620e-2; + const double g = -2.5468404e-2; + const double h = -3.1978977e-3; + const double k = 1.2992634e-4; + const double m = 1.3635334e-3; + register unsigned int i; + register double ln; + register double ln2; + register double ln3; + register double ln4; + for (i = 0; i < GSDFCount; ++i) + { + ln = log(OFstatic_cast(double, i + 1)); + ln2 = ln * ln; + ln3 = ln2 * ln; + ln4 = ln3 * ln; + GSDFValue[i] = pow(OFstatic_cast(double, 10), (a + c*ln + e*ln2 + g*ln3 + m*ln4) / (1 + b*ln + d*ln2 + f*ln3 + h*ln4 + k*(ln4*ln))); + } + return 1; + } + return 0; +} + + +int DiGSDFunction::calculateGSDFSpline() +{ + int status = 0; + if ((GSDFValue != NULL) && (GSDFCount > 0)) + { + GSDFSpline = new double[GSDFCount]; + unsigned int *jidx = new unsigned int[GSDFCount]; + if ((GSDFSpline != NULL) && (jidx != NULL)) + { + register unsigned int i; + register unsigned int *p = jidx; + for (i = 1; i <= GSDFCount; ++i) + *(p++) = i; + status = DiCubicSpline::Function(jidx, GSDFValue, GSDFCount, GSDFSpline); + } + delete[] jidx; + } + return status; +} + + +int DiGSDFunction::calculateJNDBoundaries() +{ + if ((LODValue != NULL) && (ValueCount > 0)) + { + if ((DeviceType == EDT_Printer) || (DeviceType == EDT_Scanner)) + { + /* hardcopy device (printer/scanner), values are in OD */ + if (MaxDensity < 0) + JNDMin = getJNDIndex(convertODtoLum(MaxValue)); + else // max density specified + JNDMin = getJNDIndex(convertODtoLum(MaxDensity)); + if (MinDensity < 0) + JNDMax = getJNDIndex(convertODtoLum(MinValue)); + else // min density specified + JNDMax = getJNDIndex(convertODtoLum(MinDensity)); + } else { + /* softcopy device (monitor/camera), values are in cd/m^2 */ + JNDMin = getJNDIndex(MinValue + AmbientLight); + JNDMax = getJNDIndex(MaxValue + AmbientLight); + } + return (JNDMin >= 0) && (JNDMax >= 0); + } + return 0; +} + + +double DiGSDFunction::getJNDIndex(const double lum) +{ + if (lum > 0.0) + { + /* + * algorithm taken from DICOM part 14: Grayscale Standard Display Function (GSDF) + */ + const double a = 71.498068; + const double b = 94.593053; + const double c = 41.912053; + const double d = 9.8247004; + const double e = 0.28175407; + const double f = -1.1878455; + const double g = -0.18014349; + const double h = 0.14710899; + const double i = -0.017046845; + double lg10[8]; + lg10[0] = log10(lum); + register unsigned int j; + for (j = 0; j < 7; ++j) // reduce number of multiplications + lg10[j + 1] = lg10[j] * lg10[0]; + return a + b*lg10[0] + c*lg10[1] + d*lg10[2] + e*lg10[3] + f*lg10[4] + g*lg10[5] + h*lg10[6] + i*lg10[7]; + } + return -1; +} diff --git a/dcmimgle/libsrc/digsdlut.cc b/dcmimgle/libsrc/digsdlut.cc new file mode 100644 index 00000000..b823dc4b --- /dev/null +++ b/dcmimgle/libsrc/digsdlut.cc @@ -0,0 +1,218 @@ +/* + * + * Copyright (C) 1999-2010, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimgle + * + * Author: Joerg Riesmeier + * + * Purpose: DicomGSDFLUT (Source) + * + */ + + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/dcmimgle/digsdlut.h" +#include "dcmtk/dcmimgle/displint.h" + +#define INCLUDE_CMATH +#include "dcmtk/ofstd/ofstdinc.h" + + +/*----------------* + * constructors * + *----------------*/ + +DiGSDFLUT::DiGSDFLUT(const unsigned long count, + const Uint16 max, + const Uint16 *ddl_tab, + const double *val_tab, + const unsigned long ddl_cnt, + const double *gsdf_tab, + const double *gsdf_spl, + const unsigned int gsdf_cnt, + const double jnd_min, + const double jnd_max, + const double lum_min, + const double lum_max, + const double amb, + const double illum, + const OFBool inverse, + STD_NAMESPACE ostream *stream, + const OFBool printMode) + : DiDisplayLUT(count, max, amb, illum) +{ + if ((Count > 0) && (Bits > 0)) + { + DCMIMGLE_DEBUG("new GSDF LUT with " << Bits << " bits output and " << Count << " entries created"); + if (jnd_min >= jnd_max) + { + DCMIMGLE_ERROR("invalid JND range for GSDF LUT creation (" << jnd_min << " - " << jnd_max << ")"); + } + /* create the lookup table */ + Valid = createLUT(ddl_tab, val_tab, ddl_cnt, gsdf_tab, gsdf_spl, gsdf_cnt, + jnd_min, jnd_max, lum_min, lum_max, inverse, stream, printMode); + } +} + + +/*--------------* + * destructor * + *--------------*/ + +DiGSDFLUT::~DiGSDFLUT() +{ +} + + +/********************************************************************/ + + +int DiGSDFLUT::createLUT(const Uint16 *ddl_tab, + const double *val_tab, + const unsigned long ddl_cnt, + const double *gsdf_tab, + const double *gsdf_spl, + const unsigned int gsdf_cnt, + const double jnd_min, + const double jnd_max, + const double lum_min, + const double lum_max, + const OFBool inverse, + STD_NAMESPACE ostream *stream, + const OFBool printMode) +{ + /* check for valid parameters */ + if ((ddl_tab != NULL) && (val_tab != NULL) && (ddl_cnt > 0) && (gsdf_tab != NULL) && (gsdf_spl != NULL) && + (gsdf_cnt > 0) && (jnd_min < jnd_max)) + { + int status = 0; + const unsigned long gin_ctn = (inverse) ? ddl_cnt : Count; // number of points to be interpolated + double *jidx = new double[gin_ctn]; + if (jidx != NULL) + { + const double dist = (jnd_max - jnd_min) / (gin_ctn - 1); // distance between two entries + register unsigned long i; + register double *s = jidx; + register double value = jnd_min; // first value is fixed ! + for (i = gin_ctn; i > 1; --i) // initialize scaled JND index array + { + *(s++) = value; + value += dist; // add step by step ... + } + *s = jnd_max; // last value is fixed ! + double *jnd_idx = new double[gsdf_cnt]; + if (jnd_idx != NULL) + { + s = jnd_idx; + for (i = 0; i < gsdf_cnt; ++i) // initialize JND index array + *(s++) = i + 1; + double *gsdf = new double[gin_ctn]; // interpolated GSDF + if (gsdf != NULL) + { + if (DiCubicSpline::Interpolation(jnd_idx, gsdf_tab, gsdf_spl, gsdf_cnt, jidx, gsdf, + OFstatic_cast(unsigned int, gin_ctn))) + { + DataBuffer = new Uint16[Count]; + if (DataBuffer != NULL) + { + const double amb = getAmbientLightValue(); + register Uint16 *q = DataBuffer; + register unsigned long j = 0; + /* check whether to apply the inverse transformation */ + if (inverse) + { + register double v; + const double factor = OFstatic_cast(double, ddl_cnt - 1) / OFstatic_cast(double, Count - 1); + /* convert DDL to P-Value */ + for (i = 0; i < Count; ++i) + { + v = val_tab[OFstatic_cast(int, i * factor)] + amb; // need to scale index to range of value table + while ((j + 1 < ddl_cnt) && (gsdf[j] < v)) // search for closest index, assuming monotony + ++j; + if ((j > 0) && (fabs(gsdf[j - 1] - v) < fabs(gsdf[j] - v))) + --j; + *(q++) = ddl_tab[j]; + } + } else { + /* initial DDL boundaries */ + unsigned long ddl_min = 0; + unsigned long ddl_max= ddl_cnt - 1; + /* check whether minimum luminance is specified */ + if (lum_min >= 0) + { + j = ddl_min; + /* determine corresponding minimum DDL value */ + while ((j < ddl_max) && (val_tab[j] + amb < lum_min)) + ++j; + ddl_min = j; + } + /* check whether maximum luminance is specified */ + if (lum_max >= 0) + { + j = ddl_max; + /* determine corresponding maximum DDL value */ + while ((j > ddl_min) && (val_tab[j] + amb > lum_max)) + --j; + ddl_max = j; + } + j = ddl_min; + register const double *r = gsdf; + /* convert P-Value to DDL */ + for (i = Count; i != 0; --i, ++r) + { + while ((j < ddl_max) && (val_tab[j] + amb < *r)) // search for closest index, assuming monotony + ++j; + if ((j > 0) && (fabs(val_tab[j - 1] + amb - *r) < fabs(val_tab[j] + amb - *r))) + --j; + *(q++) = ddl_tab[j]; + } + } + Data = DataBuffer; + if (stream != NULL) // write curve data to file + { + if (Count == ddl_cnt) // check whether GSDF LUT fits exactly to DISPLAY file + { + for (i = 0; i < ddl_cnt; ++i) + { + (*stream) << ddl_tab[i]; // DDL + stream->setf(STD_NAMESPACE ios::fixed, STD_NAMESPACE ios::floatfield); + if (printMode) + (*stream) << "\t" << val_tab[i] + amb; // CC + (*stream) << "\t" << gsdf[i]; // GSDF + if (printMode) + { + if (inverse) + (*stream) << "\t" << gsdf[Data[i]]; // PSC' + else + (*stream) << "\t" << val_tab[Data[i]] + amb; // PSC + } + (*stream) << OFendl; + } + } else { + DCMIMGLE_WARN("can't write curve data, wrong DISPLAY file or GSDF LUT"); + } + } + status = 1; + } + } + } + delete[] gsdf; + } + delete[] jnd_idx; + } + delete[] jidx; + return status; + } + return 0; +} diff --git a/dcmimgle/libsrc/diimage.cc b/dcmimgle/libsrc/diimage.cc new file mode 100644 index 00000000..f80be773 --- /dev/null +++ b/dcmimgle/libsrc/diimage.cc @@ -0,0 +1,856 @@ +/* + * + * Copyright (C) 1996-2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimgle + * + * Author: Joerg Riesmeier + * + * Purpose: DicomImage (Source) + * + */ + + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmdata/dctypes.h" +#include "dcmtk/dcmdata/dcdeftag.h" +#include "dcmtk/dcmdata/dcswap.h" +#include "dcmtk/dcmdata/dcuid.h" + +#include "dcmtk/dcmimgle/diimage.h" +#include "dcmtk/dcmimgle/diinpxt.h" +#include "dcmtk/dcmimgle/didocu.h" +#include "dcmtk/dcmimgle/diutils.h" +#include "dcmtk/ofstd/ofstd.h" + +#define INCLUDE_CSTRING +#include "dcmtk/ofstd/ofstdinc.h" + + +/*----------------* + * constructors * + *----------------*/ + +DiImage::DiImage(const DiDocument *docu, + const EI_Status status, + const int spp) + : ImageStatus(status), + Document(docu), + FirstFrame(0), + NumberOfFrames(0), + TotalNumberOfFrames(0), + RepresentativeFrame(0), + FrameTime(0), + Rows(0), + Columns(0), + PixelWidth(1), + PixelHeight(1), + BitsAllocated(0), + BitsStored(0), + HighBit(0), + BitsPerSample(0), + SamplesPerPixel(spp), + Polarity(EPP_Normal), + hasSignedRepresentation(0), + hasPixelSpacing(0), + hasImagerPixelSpacing(0), + hasNominalScannedPixelSpacing(0), + hasPixelAspectRatio(0), + isOriginal(1), + InputData(NULL), + FileCache(), + CurrentFragment(0) +{ + if ((Document != NULL) && (ImageStatus == EIS_Normal)) + { + Sint32 sl = 0; + if (Document->getValue(DCM_NumberOfFrames, sl)) + { + if (sl < 1) + { + DCMIMGLE_WARN("invalid value for 'NumberOfFrames' (" << sl << ") ... assuming 1"); + NumberOfFrames = 1; + } else + NumberOfFrames = OFstatic_cast(Uint32, sl); + } else + NumberOfFrames = 1; + Uint16 us = 0; + if (Document->getValue(DCM_RepresentativeFrameNumber, us)) + { + if (us <= FirstFrame) + { + DCMIMGLE_WARN("invalid value for 'RepresentativeFrameNumber' (" << us << ") ... assuming first frame"); + RepresentativeFrame = FirstFrame; + } + else if (us > NumberOfFrames) + { + DCMIMGLE_WARN("invalid value for 'RepresentativeFrameNumber' (" << us << ") ... assuming last frame"); + RepresentativeFrame = NumberOfFrames - 1; + } + else + RepresentativeFrame = us - 1; + } + double ds = 0.0; + if (Document->getValue(DCM_FrameTime, ds)) + { + if (ds <= 0) + DCMIMGLE_WARN("invalid value for 'FrameTime' (" << ds << ") ... ignoring"); + else + FrameTime = ds; + } + FirstFrame = (docu->getFrameStart() < NumberOfFrames) ? docu->getFrameStart() : NumberOfFrames - 1; + /* store total number of frames in the dataset */ + TotalNumberOfFrames = NumberOfFrames; + /* restrict to actually processed/loaded number of frames */ + NumberOfFrames -= FirstFrame; + if ((docu->getFrameCount() > 0) && (NumberOfFrames > docu->getFrameCount())) + NumberOfFrames = docu->getFrameCount(); + /* start from first processed frame (might still exceed number of loaded frames) */ + RepresentativeFrame -= FirstFrame; + int ok = (Document->getValue(DCM_Rows, Rows) > 0); + ok &= (Document->getValue(DCM_Columns, Columns) > 0); + if (!ok || ((Rows > 0) && (Columns > 0))) + { + ok &= (Document->getValue(DCM_BitsAllocated, BitsAllocated) > 0); + ok &= (Document->getValue(DCM_BitsStored, BitsStored) > 0); + if (((Document->getValue(DCM_HighBit, HighBit) == 0) || ((HighBit == 0) && (BitsStored > 1))) && ok) + { + HighBit = BitsStored - 1; + DCMIMGLE_WARN("missing value for 'HighBit' ... assuming " << HighBit); + } + BitsPerSample = BitsStored; + if (Document->getValue(DCM_PixelRepresentation, us) > 0) + { + hasSignedRepresentation = (us == 1); + if ((us != 0) && (us != 1)) + DCMIMGLE_WARN("invalid value for 'PixelRepresentation' (" << us << ") ... assuming 'unsigned' (0)"); + } else { + ok = 0; + /* pixel representation is mandatory, the error status is set below */ + DCMIMGLE_ERROR("mandatory attribute 'PixelRepresentation' is missing"); + } + if (!(Document->getFlags() & CIF_UsePresentationState)) + { + hasPixelSpacing = (Document->getValue(DCM_PixelSpacing, PixelHeight, 0) > 0); + if (hasPixelSpacing) + { + if (Document->getValue(DCM_PixelSpacing, PixelWidth, 1) < 2) + DCMIMGLE_WARN("missing second value for 'PixelSpacing' ... assuming 'Width' = " << PixelWidth); + } else { + hasImagerPixelSpacing = (Document->getValue(DCM_ImagerPixelSpacing, PixelHeight, 0) > 0); + if (hasImagerPixelSpacing) + { + if (Document->getValue(DCM_ImagerPixelSpacing, PixelWidth, 1) < 2) + DCMIMGLE_WARN("missing second value for 'ImagerPixelSpacing' ... assuming 'Width' = " << PixelWidth); + } else { + hasNominalScannedPixelSpacing = (Document->getValue(DCM_NominalScannedPixelSpacing, PixelHeight, 0) > 0); + if (hasNominalScannedPixelSpacing) + { + if (Document->getValue(DCM_NominalScannedPixelSpacing, PixelWidth, 1) < 2) + DCMIMGLE_WARN("missing second value for 'NominalScannedPixelSpacing' ... assuming 'Width' = " << PixelWidth); + } else { + Sint32 sl2; + hasPixelAspectRatio = (Document->getValue(DCM_PixelAspectRatio, sl2, 0) > 0); + if (hasPixelAspectRatio) + { + PixelHeight = sl2; + if (Document->getValue(DCM_PixelAspectRatio, sl2, 1) < 2) + DCMIMGLE_WARN("missing second value for 'PixelAspectRatio' ... assuming 'Width' = " << PixelWidth); + else + PixelWidth = sl2; + } else { + PixelWidth = 1; + PixelHeight = 1; + } + } + } + } + checkPixelExtension(); + } + if (ok && (Document->getPixelData() != NULL)) + { + // convert pixel data (if present) + convertPixelData(); + } else { + ImageStatus = EIS_MissingAttribute; + DCMIMGLE_ERROR("one or more mandatory attributes are missing in image pixel module"); + } + } else { + ImageStatus = EIS_InvalidValue; + DCMIMGLE_ERROR("invalid value for 'Rows' (" << Rows << ") and/or 'Columns' (" << Columns << ")"); + } + } else { + ImageStatus = EIS_InvalidDocument; + DCMIMGLE_ERROR("this DICOM document is invalid"); + } +} + + +DiImage::DiImage(const DiDocument *docu, + const EI_Status status) + : ImageStatus(status), + Document(docu), + FirstFrame(0), + NumberOfFrames(0), + TotalNumberOfFrames(0), + RepresentativeFrame(0), + FrameTime(0), + Rows(0), + Columns(0), + PixelWidth(1), + PixelHeight(1), + BitsAllocated(0), + BitsStored(0), + HighBit(0), + BitsPerSample(0), + SamplesPerPixel(0), + Polarity(EPP_Normal), + hasSignedRepresentation(0), + hasPixelSpacing(0), + hasImagerPixelSpacing(0), + hasNominalScannedPixelSpacing(0), + hasPixelAspectRatio(0), + isOriginal(1), + InputData(NULL), + FileCache(), + CurrentFragment(0) +{ +} + + +DiImage::DiImage(const DiImage *image, + const unsigned long fstart, + const unsigned long fcount) + : ImageStatus(image->ImageStatus), + Document(image->Document), + FirstFrame(image->FirstFrame + fstart), + NumberOfFrames(fcount), + TotalNumberOfFrames(image->TotalNumberOfFrames), + RepresentativeFrame(image->RepresentativeFrame), + FrameTime(image->FrameTime), + Rows(image->Rows), + Columns(image->Columns), + PixelWidth(image->PixelWidth), + PixelHeight(image->PixelHeight), + BitsAllocated(image->BitsAllocated), + BitsStored(image->BitsStored), + HighBit(image->HighBit), + BitsPerSample(image->BitsPerSample), + SamplesPerPixel(image->SamplesPerPixel), + Polarity(image->Polarity), + hasSignedRepresentation(image->hasSignedRepresentation), + hasPixelSpacing(image->hasPixelSpacing), + hasImagerPixelSpacing(image->hasImagerPixelSpacing), + hasNominalScannedPixelSpacing(image->hasNominalScannedPixelSpacing), + hasPixelAspectRatio(image->hasPixelAspectRatio), + isOriginal(0), + InputData(NULL), + FileCache(), + CurrentFragment(0) +{ +} + + +/* constructor: image scaled */ + +DiImage::DiImage(const DiImage *image, + const Uint16 columns, + const Uint16 rows, + const int aspect) + : ImageStatus(image->ImageStatus), + Document(image->Document), + FirstFrame(image->FirstFrame), + NumberOfFrames(image->NumberOfFrames), + TotalNumberOfFrames(image->TotalNumberOfFrames), + RepresentativeFrame(image->RepresentativeFrame), + FrameTime(image->FrameTime), + Rows(rows), + Columns(columns), + PixelWidth(1), + PixelHeight(1), + BitsAllocated(image->BitsAllocated), + BitsStored(image->BitsStored), + HighBit(image->HighBit), + BitsPerSample(image->BitsPerSample), + SamplesPerPixel(image->SamplesPerPixel), + Polarity(image->Polarity), + hasSignedRepresentation(image->hasSignedRepresentation), + hasPixelSpacing(0), + hasImagerPixelSpacing(0), + hasNominalScannedPixelSpacing(0), + hasPixelAspectRatio(0), + isOriginal(0), + InputData(NULL), + FileCache(), + CurrentFragment(0) +{ + /* we do not check for "division by zero", this is already done somewhere else */ + const double xfactor = OFstatic_cast(double, Columns) / OFstatic_cast(double, image->Columns); + const double yfactor = OFstatic_cast(double, Rows) / OFstatic_cast(double, image->Rows); + /* re-compute pixel width and height */ + if (image->hasPixelSpacing) + { + hasPixelSpacing = image->hasPixelSpacing; + PixelWidth = image->PixelWidth / xfactor; + PixelHeight = image->PixelHeight / yfactor; + } + else if (image->hasImagerPixelSpacing) + { + /* never change ImagerPixelSpacing, use PixelSpacing instead */ + hasImagerPixelSpacing = 0; + hasPixelSpacing = 1; + PixelWidth = image->PixelWidth / xfactor; + PixelHeight = image->PixelHeight / yfactor; + } + else if (image->hasNominalScannedPixelSpacing) + { + /* never change NominalScannedPixelSpacing, use PixelSpacing instead */ + hasNominalScannedPixelSpacing = 0; + hasPixelSpacing = 1; + PixelWidth = image->PixelWidth / xfactor; + PixelHeight = image->PixelHeight / yfactor; + } + else if (image->hasPixelAspectRatio && !aspect /*recognize pixel aspect ratio*/) + { + hasPixelAspectRatio = image->hasPixelAspectRatio; + PixelWidth = image->PixelWidth * xfactor; + PixelHeight = image->PixelHeight * yfactor; + /* do not store pixel aspect ratio for square pixels */ + if (PixelWidth == PixelHeight) + hasPixelAspectRatio = 0; + } +} + + +DiImage::DiImage(const DiImage *image, + const int degree) + : ImageStatus(image->ImageStatus), + Document(image->Document), + FirstFrame(image->FirstFrame), + NumberOfFrames(image->NumberOfFrames), + TotalNumberOfFrames(image->TotalNumberOfFrames), + RepresentativeFrame(image->RepresentativeFrame), + FrameTime(image->FrameTime), + Rows(((degree == 90) ||(degree == 270)) ? image->Columns : image->Rows), + Columns(((degree == 90) ||(degree == 270)) ? image->Rows : image->Columns), + PixelWidth(((degree == 90) ||(degree == 270)) ? image->PixelHeight : image->PixelWidth), + PixelHeight(((degree == 90) ||(degree == 270)) ? image-> PixelWidth : image->PixelHeight), + BitsAllocated(image->BitsAllocated), + BitsStored(image->BitsStored), + HighBit(image->HighBit), + BitsPerSample(image->BitsPerSample), + SamplesPerPixel(image->SamplesPerPixel), + Polarity(image->Polarity), + hasSignedRepresentation(image->hasSignedRepresentation), + hasPixelSpacing(image->hasPixelSpacing), + hasImagerPixelSpacing(image->hasImagerPixelSpacing), + hasNominalScannedPixelSpacing(image->hasNominalScannedPixelSpacing), + hasPixelAspectRatio(image->hasPixelAspectRatio), + isOriginal(0), + InputData(NULL), + FileCache(), + CurrentFragment(0) +{ +} + + +DiImage::DiImage(const DiImage *image, + const unsigned long frame, + const int stored, + const int alloc) + : ImageStatus(image->ImageStatus), + Document(image->Document), + FirstFrame(frame), + NumberOfFrames(1), + TotalNumberOfFrames(image->TotalNumberOfFrames), + RepresentativeFrame(0), + FrameTime(0), + Rows(image->Rows), + Columns(image->Columns), + PixelWidth(image->PixelWidth), + PixelHeight(image->PixelHeight), + BitsAllocated(alloc), + BitsStored(stored), + HighBit(stored - 1), + BitsPerSample(image->BitsPerSample), + SamplesPerPixel(image->SamplesPerPixel), + Polarity(image->Polarity), + hasSignedRepresentation(0), + hasPixelSpacing(image->hasPixelSpacing), + hasImagerPixelSpacing(image->hasImagerPixelSpacing), + hasNominalScannedPixelSpacing(image->hasNominalScannedPixelSpacing), + hasPixelAspectRatio(image->hasPixelAspectRatio), + isOriginal(0), + InputData(NULL), + FileCache(), + CurrentFragment(0) +{ +} + + +/*--------------* + * destructor * + *--------------*/ + +DiImage::~DiImage() +{ + delete InputData; +} + + +/*********************************************************************/ + + +int DiImage::processNextFrames(const unsigned long fcount) +{ + if ((ImageStatus == EIS_Normal) && (Document != NULL) && isOriginal) + { + if ((Document->getFlags() & CIF_UsePartialAccessToPixelData) && (Document->getPixelData() != NULL)) + { + // check whether there are still any frames to be processed + if (FirstFrame + NumberOfFrames < TotalNumberOfFrames) + { + FirstFrame += NumberOfFrames; + if (fcount > 0) + NumberOfFrames = fcount; + if (FirstFrame + NumberOfFrames > TotalNumberOfFrames) + NumberOfFrames = TotalNumberOfFrames - FirstFrame; + // free memory of previously processed frames + deleteInputData(); + // create new input data representation + convertPixelData(); + return (ImageStatus == EIS_Normal); + } + } + } + return 0; +} + + +/********************************************************************/ + + +int DiImage::rotate(const int degree) +{ + if ((degree == 90) || (degree == 270)) + { + Uint16 us = Rows; // swap image width and height + Rows = Columns; + Columns = us; + double db = PixelWidth; // swap pixel width and height + PixelWidth = PixelHeight; + PixelHeight = db; + return 1; + } + return 0; +} + + +/********************************************************************/ + + +void DiImage::deleteInputData() +{ + delete InputData; + InputData = NULL; +} + + +void DiImage::checkPixelExtension() +{ + if (hasPixelSpacing || hasImagerPixelSpacing || hasNominalScannedPixelSpacing || hasPixelAspectRatio) + { + if (PixelHeight == 0) + { + DCMIMGLE_WARN("invalid value for 'PixelHeight' (" << PixelHeight << ") ... assuming 1"); + /* according to the standard, a value of 0 would be valid in case number of rows is 1 */ + PixelHeight = 1; + } + else if (PixelHeight < 0) + { + DCMIMGLE_WARN("negative value for 'PixelHeight' (" << PixelHeight << ") ... assuming " << -PixelHeight); + PixelHeight = -PixelHeight; + } + if (PixelWidth == 0) + { + DCMIMGLE_WARN("invalid value for 'PixelWidth' (" << PixelWidth << ") ... assuming 1"); + /* according to the standard, a value of 0 would be valid in case number of columns is 1 */ + PixelWidth = 1; + } + else if (PixelWidth < 0) + { + DCMIMGLE_WARN("negative value for 'PixelWidth' (" << PixelWidth << ") ... assuming " << -PixelWidth); + PixelWidth = -PixelWidth; + } + } +} + + +void DiImage::convertPixelData() +{ + // pointer is already checked for not being NULL + DcmPixelData *pixel = Document->getPixelData(); + const DcmEVR evr = pixel->getVR(); + const OFBool compressed = Document->isCompressed(); + const char *xferUID = DcmXfer(Document->getTransferSyntax()).getXferID(); + const char *xferName = dcmFindNameOfUID(xferUID); + // output some useful information, e.g. for tracing purposes + DCMIMGLE_TRACE("Pixel Data VR: " << DcmVR(evr).getVRName() << ", " << (compressed ? "Compressed" : "Uncompressed") + << " (" << ((xferName != NULL) ? xferName : xferUID) << ")"); + DCMIMGLE_TRACE("First frame: " << FirstFrame << ", Number of frames: " << NumberOfFrames + << ", Total number of frames: " << TotalNumberOfFrames); + DCMIMGLE_TRACE("Columns: " << Columns << ", Rows: " << Rows << ", Samples per Pixel: " << SamplesPerPixel + << ", Photometric Interpretation: " << Document->getPhotometricInterpretation()); + DCMIMGLE_TRACE("Bits Allocated: " << BitsAllocated << ", Bits Stored: " << BitsStored << ", High Bit: " << HighBit + << ", " << (hasSignedRepresentation ? "Signed" : "Unsigned") << " integer"); + /* check for valid/supported pixel data encoding */ + if ((evr == EVR_OW) || ((evr == EVR_OB) && (compressed || (BitsAllocated <= 16)))) + { + const unsigned long fsize = OFstatic_cast(unsigned long, Rows) * OFstatic_cast(unsigned long, Columns) * + OFstatic_cast(unsigned long, SamplesPerPixel); + if ((BitsAllocated < 1) || (BitsStored < 1) || (BitsAllocated < BitsStored) || + (BitsStored > OFstatic_cast(Uint16, HighBit + 1))) + { + ImageStatus = EIS_InvalidValue; + DCMIMGLE_ERROR("invalid values for 'BitsAllocated' (" << BitsAllocated << "), " + << "'BitsStored' (" << BitsStored << ") and/or 'HighBit' (" << HighBit << ")"); + return; + } + else if ((evr == EVR_OB) && (BitsStored <= 8)) + { + // report a warning message on this standard violation + if (!compressed && (BitsAllocated > 8)) + DCMIMGLE_WARN("invalid value for 'BitsAllocated' (" << BitsAllocated << "), > 8 for OB encoded uncompressed 'PixelData'"); + if (hasSignedRepresentation) + InputData = new DiInputPixelTemplate(Document, BitsAllocated, BitsStored, HighBit, FirstFrame, NumberOfFrames, fsize, &FileCache, CurrentFragment); + else + InputData = new DiInputPixelTemplate(Document, BitsAllocated, BitsStored, HighBit, FirstFrame, NumberOfFrames, fsize, &FileCache, CurrentFragment); + } + else if ((evr == EVR_OB) && (BitsStored <= 16)) + { + // report a warning message on this standard violation + if (!compressed && (BitsAllocated > 8)) + DCMIMGLE_WARN("invalid value for 'BitsAllocated' (" << BitsAllocated << "), > 8 for OB encoded uncompressed 'PixelData'"); + if (hasSignedRepresentation) + InputData = new DiInputPixelTemplate(Document, BitsAllocated, BitsStored, HighBit, FirstFrame, NumberOfFrames, fsize, &FileCache, CurrentFragment); + else + InputData = new DiInputPixelTemplate(Document, BitsAllocated, BitsStored, HighBit, FirstFrame, NumberOfFrames, fsize, &FileCache, CurrentFragment); + } + else if ((evr == EVR_OB) && compressed && (BitsStored <= 32)) + { + if (hasSignedRepresentation) + InputData = new DiInputPixelTemplate(Document, BitsAllocated, BitsStored, HighBit, FirstFrame, NumberOfFrames, fsize, &FileCache, CurrentFragment); + else + InputData = new DiInputPixelTemplate(Document, BitsAllocated, BitsStored, HighBit, FirstFrame, NumberOfFrames, fsize, &FileCache, CurrentFragment); + } + else if (BitsStored <= 8) + { + if (hasSignedRepresentation) + InputData = new DiInputPixelTemplate(Document, BitsAllocated, BitsStored, HighBit, FirstFrame, NumberOfFrames, fsize, &FileCache, CurrentFragment); + else + InputData = new DiInputPixelTemplate(Document, BitsAllocated, BitsStored, HighBit, FirstFrame, NumberOfFrames, fsize, &FileCache, CurrentFragment); + } + else if (BitsStored <= 16) + { + if (hasSignedRepresentation) + InputData = new DiInputPixelTemplate(Document, BitsAllocated, BitsStored, HighBit, FirstFrame, NumberOfFrames, fsize, &FileCache, CurrentFragment); + else + InputData = new DiInputPixelTemplate(Document, BitsAllocated, BitsStored, HighBit, FirstFrame, NumberOfFrames, fsize, &FileCache, CurrentFragment); + } + else if (BitsStored <= 32) + { + if (hasSignedRepresentation) + InputData = new DiInputPixelTemplate(Document, BitsAllocated, BitsStored, HighBit, FirstFrame, NumberOfFrames, fsize, &FileCache, CurrentFragment); + else + InputData = new DiInputPixelTemplate(Document, BitsAllocated, BitsStored, HighBit, FirstFrame, NumberOfFrames, fsize, &FileCache, CurrentFragment); + } + else /* BitsStored > 32 !! */ + { + ImageStatus = EIS_NotSupportedValue; + DCMIMGLE_ERROR("invalid value for 'BitsStored' (" << BitsStored << ") ... exceeds " << MAX_BITS << " bit"); + return; + } + if (InputData == NULL) + { + ImageStatus = EIS_MemoryFailure; + DCMIMGLE_ERROR("can't allocate memory for input-representation"); + } + else if (InputData->getData() == NULL) + { + ImageStatus = EIS_InvalidImage; + DCMIMGLE_ERROR("can't convert input pixel data, probably unsupported compression"); + } + else if (InputData->getPixelStart() >= InputData->getCount()) + { + ImageStatus = EIS_InvalidValue; + DCMIMGLE_ERROR("start offset (" << InputData->getPixelStart() << ") exceeds number of pixels stored (" + << InputData->getCount() << ")"); + } + } + else + { + ImageStatus = EIS_NotSupportedValue; + DCMIMGLE_ERROR("'PixelData' has a value representation other than OB (with 'BitsAllocated' <= 16) or OW"); + } +} + + +int DiImage::detachPixelData() +{ + if ((Document != NULL) && isOriginal) + { + if (Document->getFlags() & CIF_MayDetachPixelData) + { + /* do not detach if partial access is enabled */ + if (!(Document->getFlags() & CIF_UsePartialAccessToPixelData) || (FirstFrame + NumberOfFrames >= TotalNumberOfFrames)) + { + DcmPixelData *pixel = Document->getPixelData(); + if (pixel != NULL) + { + DCMIMGLE_DEBUG("detach pixel data"); + /* clear pixel data value */ + pixel->putUint16Array(NULL, 0); + return 1; + } + } else + DCMIMGLE_DEBUG("do not detach pixel data because of partial access"); + } + } + return 0; +} + + +int DiImage::setColumnRowRatio(const double ratio) +{ + hasPixelAspectRatio = 1; + hasPixelSpacing = hasImagerPixelSpacing = hasNominalScannedPixelSpacing = 0; + PixelWidth = ratio; + PixelHeight = 1; + checkPixelExtension(); + return 1; +} + + +int DiImage::setRowColumnRatio(const double ratio) +{ + hasPixelAspectRatio = 1; + hasPixelSpacing = hasImagerPixelSpacing = hasNominalScannedPixelSpacing = 0; + PixelWidth = 1; + PixelHeight = ratio; + checkPixelExtension(); + return 1; +} + + +int DiImage::setPolarity(const EP_Polarity polarity) +{ + if (polarity != Polarity) + { + Polarity = polarity; + return 1; + } + return 2; +} + + +void DiImage::updateImagePixelModuleAttributes(DcmItem &dataset) +{ + /* remove outdated attributes from the dataset */ + delete dataset.remove(DCM_SmallestImagePixelValue); + delete dataset.remove(DCM_LargestImagePixelValue); +/* + delete dataset.remove(DCM_PixelPaddingValue); + delete dataset.remove(DCM_PixelPaddingRangeLimit); + delete dataset.remove(DCM_SmallestPixelValueInSeries); + delete dataset.remove(DCM_LargestPixelValueInSeries); +*/ + /* update PixelAspectRatio & Co. */ + char buffer[32]; + OFStandard::ftoa(buffer, 15, PixelHeight, OFStandard::ftoa_format_f); + strcat(buffer, "\\"); + OFStandard::ftoa(strchr(buffer, 0), 15, PixelWidth, OFStandard::ftoa_format_f); + + if (hasPixelSpacing) + dataset.putAndInsertString(DCM_PixelSpacing, buffer); + else + delete dataset.remove(DCM_PixelSpacing); + /* check for square pixels */ + if (hasPixelAspectRatio && (PixelWidth != PixelHeight)) + dataset.putAndInsertString(DCM_PixelAspectRatio, buffer); + else + delete dataset.remove(DCM_PixelAspectRatio); +} + + +// --- write given frame of the current image to DICOM dataset + +int DiImage::writeFrameToDataset(DcmItem &dataset, + const unsigned long frame, + const int bits, + const int planar) +{ + int result = 0; + const int bitsStored = getBits(bits); + /* get output pixel data */ + const void *pixel = getOutputData(frame, bitsStored, planar); + if (pixel != NULL) + { + char buffer[32]; + unsigned long count; + /* write color model dependent attributes */ + if ((getInternalColorModel() == EPI_Monochrome1) || (getInternalColorModel() == EPI_Monochrome2)) + { + /* monochrome image */ + count = OFstatic_cast(unsigned long, Columns) * OFstatic_cast(unsigned long, Rows); + dataset.putAndInsertString(DCM_PhotometricInterpretation, "MONOCHROME2"); + dataset.putAndInsertUint16(DCM_SamplesPerPixel, 1); + } else { + /* color image */ + count = OFstatic_cast(unsigned long, Columns) * OFstatic_cast(unsigned long, Rows) * 3 /*samples per pixel*/; + if (getInternalColorModel() == EPI_YBR_Full) + dataset.putAndInsertString(DCM_PhotometricInterpretation, "YBR_FULL"); + else + dataset.putAndInsertString(DCM_PhotometricInterpretation, "RGB"); + dataset.putAndInsertUint16(DCM_PlanarConfiguration, planar != 0); + dataset.putAndInsertUint16(DCM_SamplesPerPixel, 3); + } + /* write remaining attributes */ + dataset.putAndInsertUint16(DCM_Columns, Columns); + dataset.putAndInsertUint16(DCM_Rows, Rows); + dataset.putAndInsertString(DCM_NumberOfFrames, "1"); + if (bitsStored <= 8) + dataset.putAndInsertUint16(DCM_BitsAllocated, 8); + else if (bitsStored <= 16) + dataset.putAndInsertUint16(DCM_BitsAllocated, 16); + else + dataset.putAndInsertUint16(DCM_BitsAllocated, 32); + dataset.putAndInsertUint16(DCM_BitsStored, bitsStored); + dataset.putAndInsertUint16(DCM_HighBit, bitsStored - 1); + dataset.putAndInsertUint16(DCM_PixelRepresentation, 0); + /* handle VOI transformations */ + if (dataset.tagExists(DCM_WindowCenter) || + dataset.tagExists(DCM_WindowWidth) || + dataset.tagExists(DCM_VOILUTSequence)) + { + delete dataset.remove(DCM_VOILUTSequence); + sprintf(buffer, "%lu", DicomImageClass::maxval(bitsStored, 0) / 2); + dataset.putAndInsertString(DCM_WindowCenter, buffer); + sprintf(buffer, "%lu", DicomImageClass::maxval(bitsStored, 0)); + dataset.putAndInsertString(DCM_WindowWidth, buffer); + } + delete dataset.remove(DCM_WindowCenterWidthExplanation); + /* write pixel data (OB or OW) */ + if (bitsStored <= 8) + dataset.putAndInsertUint8Array(DCM_PixelData, OFstatic_cast(Uint8 *, OFconst_cast(void *, pixel)), count); + else if (bitsStored <= 16) + dataset.putAndInsertUint16Array(DCM_PixelData, OFstatic_cast(Uint16 *, OFconst_cast(void *, pixel)), count); + else + dataset.putAndInsertUint16Array(DCM_PixelData, OFstatic_cast(Uint16 *, OFconst_cast(void *, pixel)), count * 2 /*double-words*/); + /* update other DICOM attributes */ + updateImagePixelModuleAttributes(dataset); + result = 1; + } + return result; +} + + +int DiImage::writeBMP(FILE *stream, + const unsigned long frame, + const int bits) +{ + int result = 0; + if ((stream != NULL) && ((bits == 8) || (bits == 24) || (bits == 32))) + { + /* create device independent bitmap: palette (8) or truecolor (24/32) */ + void *data = NULL; + const unsigned long bytes = createDIB(data, 0, frame, bits, 1 /*upsideDown*/); + if ((data != NULL) && (bytes > 0)) + { + /* number of bytes */ + SB_BitmapFileHeader fileHeader; + SB_BitmapInfoHeader infoHeader; + Uint32 *palette = (bits == 8) ? new Uint32[256] : OFstatic_cast(Uint32 *, NULL); + /* fill bitmap file header with data */ + fileHeader.bfType[0] = 'B'; + fileHeader.bfType[1] = 'M'; + fileHeader.bfSize = 14 /*sizeof(SB_BitmapFileHeader)*/ + 40 /*sizeof(SB_BitmapInfoHeader)*/ + bytes; + fileHeader.bfReserved1 = 0; + fileHeader.bfReserved2 = 0; + fileHeader.bfOffBits = 14 /*sizeof(SB_BitmapFileHeader)*/ + 40 /*sizeof(SB_BitmapInfoHeader)*/; + /* fill bitmap info header with data */ + infoHeader.biSize = 40 /*sizeof(SB_BitmapInfoHeader)*/; + infoHeader.biWidth = Columns; + infoHeader.biHeight = Rows; + infoHeader.biPlanes = 1; + infoHeader.biBitCount = bits; + infoHeader.biCompression = 0; + infoHeader.biSizeImage = 0; + infoHeader.biXPelsPerMeter = 0; + infoHeader.biYPelsPerMeter = 0; + infoHeader.biClrUsed = 0; + infoHeader.biClrImportant = 0; + /* create and fill color palette */ + if (palette != NULL) + { + /* add palette size */ + fileHeader.bfSize += 256 * 4; + fileHeader.bfOffBits += 256 * 4; + /* fill palette entries with gray values */ + for (Uint32 i = 0; i < 256; ++i) + palette[i] = (i << 16) | (i << 8) | i; + } + /* swap bytes if necessary */ + if (gLocalByteOrder != EBO_LittleEndian) + { + /* other data elements are always '0' and, therefore, can remain as they are */ + swap4Bytes(OFreinterpret_cast(Uint8 *, &fileHeader.bfSize)); + swap4Bytes(OFreinterpret_cast(Uint8 *, &fileHeader.bfOffBits)); + swap4Bytes(OFreinterpret_cast(Uint8 *, &infoHeader.biSize)); + swap4Bytes(OFreinterpret_cast(Uint8 *, &infoHeader.biWidth)); + swap4Bytes(OFreinterpret_cast(Uint8 *, &infoHeader.biHeight)); + swap2Bytes(OFreinterpret_cast(Uint8 *, &infoHeader.biPlanes)); + swap2Bytes(OFreinterpret_cast(Uint8 *, &infoHeader.biBitCount)); + if (palette != NULL) + swapBytes(OFreinterpret_cast(Uint8 *, palette), 256 * 4 /*byteLength*/, 4 /*valWidth*/); + } + /* write bitmap file header: do not write the struct because of 32-bit alignment */ + fwrite(&fileHeader.bfType, sizeof(fileHeader.bfType), 1, stream); + fwrite(&fileHeader.bfSize, sizeof(fileHeader.bfSize), 1, stream); + fwrite(&fileHeader.bfReserved1, sizeof(fileHeader.bfReserved1), 1, stream); + fwrite(&fileHeader.bfReserved2, sizeof(fileHeader.bfReserved2), 1, stream); + fwrite(&fileHeader.bfOffBits, sizeof(fileHeader.bfOffBits), 1, stream); + /* write bitmap info header: do not write the struct because of 32-bit alignment */ + fwrite(&infoHeader.biSize, sizeof(infoHeader.biSize), 1, stream); + fwrite(&infoHeader.biWidth, sizeof(infoHeader.biWidth), 1, stream); + fwrite(&infoHeader.biHeight, sizeof(infoHeader.biHeight), 1, stream); + fwrite(&infoHeader.biPlanes, sizeof(infoHeader.biPlanes), 1, stream); + fwrite(&infoHeader.biBitCount, sizeof(infoHeader.biBitCount), 1, stream); + fwrite(&infoHeader.biCompression, sizeof(infoHeader.biCompression), 1, stream); + fwrite(&infoHeader.biSizeImage, sizeof(infoHeader.biSizeImage), 1, stream); + fwrite(&infoHeader.biXPelsPerMeter, sizeof(infoHeader.biXPelsPerMeter), 1, stream); + fwrite(&infoHeader.biYPelsPerMeter, sizeof(infoHeader.biYPelsPerMeter), 1, stream); + fwrite(&infoHeader.biClrUsed, sizeof(infoHeader.biClrUsed), 1, stream); + fwrite(&infoHeader.biClrImportant, sizeof(infoHeader.biClrImportant), 1, stream); + /* write color palette (if applicable) */ + if (palette != NULL) + fwrite(palette, 4, 256, stream); + /* write pixel data */ + fwrite(data, 1, OFstatic_cast(size_t, bytes), stream); + /* delete color palette */ + delete[] palette; + result = 1; + } + /* delete pixel data */ + delete OFstatic_cast(char *, data); // type cast necessary to avoid compiler warnings using gcc >2.95 + } + return result; +} diff --git a/dcmimgle/libsrc/diinpx.cc b/dcmimgle/libsrc/diinpx.cc new file mode 100644 index 00000000..f0bf2bf8 --- /dev/null +++ b/dcmimgle/libsrc/diinpx.cc @@ -0,0 +1,56 @@ +/* + * + * Copyright (C) 1996-2010, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimgle + * + * Author: Joerg Riesmeier + * + * Purpose: DicomInputPixel (Source) + * + */ + + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/dcmimgle/diinpx.h" + + +/*----------------* + * constructors * + *----------------*/ + +DiInputPixel::DiInputPixel(const unsigned int bits, + const unsigned long first, + const unsigned long number, + const unsigned long fsize) + : Count(0), + Bits(bits), + FirstFrame(first), + NumberOfFrames(number), + FrameSize(fsize), + PixelStart(first * fsize), + PixelCount(number * fsize), + ComputedCount(number * fsize), + AbsMinimum(0), + AbsMaximum(0) +{ +} + + +/*--------------* + * destructor * + *--------------*/ + +DiInputPixel::~DiInputPixel() +{ +} diff --git a/dcmimgle/libsrc/diluptab.cc b/dcmimgle/libsrc/diluptab.cc new file mode 100644 index 00000000..b957eb7b --- /dev/null +++ b/dcmimgle/libsrc/diluptab.cc @@ -0,0 +1,545 @@ +/* + * + * Copyright (C) 1996-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimgle + * + * Author: Joerg Riesmeier + * + * Purpose: DicomLookupTable (Source) + * + */ + + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmdata/dcdeftag.h" +#include "dcmtk/dcmdata/dcsequen.h" +#include "dcmtk/dcmdata/dcitem.h" +#include "dcmtk/dcmdata/dcvrus.h" + +#include "dcmtk/ofstd/ofbmanip.h" +#include "dcmtk/ofstd/ofcast.h" + +#include "dcmtk/dcmimgle/diluptab.h" +#include "dcmtk/dcmimgle/didocu.h" + + +/*----------------* + * constructors * + *----------------*/ + +DiLookupTable::DiLookupTable(const DiDocument *docu, + const DcmTagKey &descriptor, + const DcmTagKey &data, + const DcmTagKey &explanation, + const EL_BitsPerTableEntry descripMode, + EI_Status *status) + : DiBaseLUT(), + OriginalBitsAllocated(16), + OriginalData(NULL) +{ + if (docu != NULL) + Init(docu, NULL, descriptor, data, explanation, descripMode, status); +} + + +DiLookupTable::DiLookupTable(const DiDocument *docu, + const DcmTagKey &sequence, + const DcmTagKey &descriptor, + const DcmTagKey &data, + const DcmTagKey &explanation, + const EL_BitsPerTableEntry descripMode, + const unsigned long pos, + unsigned long *card) + : DiBaseLUT(), + OriginalBitsAllocated(16), + OriginalData(NULL) +{ + if (docu != NULL) + { + DcmSequenceOfItems *seq = NULL; + const unsigned long count = docu->getSequence(sequence, seq); + /* store number of items in the optional return variable */ + if (card != NULL) + *card = count; + if ((seq != NULL) && (pos < count)) + { + DcmItem *item = seq->getItem(pos); + Init(docu, item, descriptor, data, explanation, descripMode); + } + } +} + + +DiLookupTable::DiLookupTable(const DcmUnsignedShort &data, + const DcmUnsignedShort &descriptor, + const DcmLongString *explanation, + const EL_BitsPerTableEntry descripMode, + const signed long first, + EI_Status *status) + : DiBaseLUT(), + OriginalBitsAllocated(16), + OriginalData(NULL) +{ + Uint16 us = 0; + const DcmElement *descElem = OFreinterpret_cast(const DcmElement *, &descriptor); + if (DiDocument::getElemValue(descElem, us, 0, OFTrue /*allowSigned*/) >= 3) // number of LUT entries + { + Count = (us == 0) ? MAX_TABLE_ENTRY_COUNT : us; // see DICOM supplement 5: "0" => 65536 + DiDocument::getElemValue(descElem, FirstEntry, 1, OFTrue /*allowSigned*/); // can be SS or US (will be typecasted later) + if ((first >= 0) && (FirstEntry != OFstatic_cast(Uint16, first))) + { + DCMIMGLE_WARN("invalid value for 'FirstInputValueMapped' in lookup table (" + << FirstEntry << ") ... assuming " << first); + FirstEntry = OFstatic_cast(Uint16, first); + } + DiDocument::getElemValue(descElem, us, 2, OFTrue /*allowSigned*/); // bits per entry (only informational) + unsigned long count = DiDocument::getElemValue(OFreinterpret_cast(const DcmElement *, &data), Data); + OriginalData = OFstatic_cast(void *, OFconst_cast(Uint16 *, Data)); // store pointer to original data + if (explanation != NULL) + DiDocument::getElemValue(OFreinterpret_cast(const DcmElement *, explanation), Explanation); // explanation (free form text) + checkTable(count, us, descripMode, status); + } else { + if (status != NULL) + { + *status = EIS_MissingAttribute; + DCMIMGLE_ERROR("incomplete or missing 'LookupTableDescriptor' " << descriptor.getTag()); + } else { + DCMIMGLE_WARN("incomplete or missing 'LookupTableDescriptor' " << descriptor.getTag() + << " ... ignoring LUT"); + } + } +} + + +DiLookupTable::DiLookupTable(Uint16 *buffer, + const Uint32 count, + const Uint16 bits) + : DiBaseLUT(buffer, count, bits), + OriginalBitsAllocated(16), + OriginalData(buffer) +{ + checkTable(count, bits); +} + + +/*--------------* + * destructor * + *--------------*/ + +DiLookupTable::~DiLookupTable() +{ +} + + +/********************************************************************/ + + +void DiLookupTable::Init(const DiDocument *docu, + DcmItem *item, + const DcmTagKey &descriptor, + const DcmTagKey &data, + const DcmTagKey &explanation, + const EL_BitsPerTableEntry descripMode, + EI_Status *status) +{ + Uint16 us = 0; + if (docu->getValue(descriptor, us, 0, item, OFTrue /*allowSigned*/) >= 3) // number of LUT entries + { + Count = (us == 0) ? MAX_TABLE_ENTRY_COUNT : us; // see DICOM supplement 5: "0" => 65536 + docu->getValue(descriptor, FirstEntry, 1, item, OFTrue /*allowSigned*/); // can be SS or US (will be typecasted later) + docu->getValue(descriptor, us, 2, item, OFTrue /*allowSigned*/); // bits per entry (only informational) + unsigned long count = docu->getValue(data, Data, item); + OriginalData = OFstatic_cast(void *, OFconst_cast(Uint16 *, Data)); // store pointer to original data + if (explanation != DCM_UndefinedTagKey) + docu->getValue(explanation, Explanation, 0 /*vm pos*/, item); // explanation (free form text) + checkTable(count, us, descripMode, status); + } else { + if (status != NULL) + { + *status = EIS_MissingAttribute; + DCMIMGLE_ERROR("incomplete or missing 'LookupTableDescriptor' " << descriptor); + } else { + DCMIMGLE_WARN("incomplete or missing 'LookupTableDescriptor' " << descriptor + << " ... ignoring LUT"); + } + } +} + + +void DiLookupTable::checkTable(unsigned long count, + Uint16 bits, + const EL_BitsPerTableEntry descripMode, + EI_Status *status) +{ + if (count > 0) // valid LUT + { + register unsigned long i; + if (count > MAX_TABLE_ENTRY_COUNT) // cut LUT length to maximum + count = MAX_TABLE_ENTRY_COUNT; + if (count != Count) // length of LUT differs from number of LUT entries + { + if (count == ((Count + 1) >> 1)) // bits allocated 8, ignore padding + { + OriginalBitsAllocated = 8; + DCMIMGLE_DEBUG("lookup table uses 8 bits allocated ... converting to 16 bits"); + DataBuffer = new Uint16[Count]; // create new LUT + if ((DataBuffer != NULL) && (Data != NULL)) + { + register const Uint8 *p = OFreinterpret_cast(const Uint8 *, Data); + register Uint16 *q = DataBuffer; + if (gLocalByteOrder == EBO_BigEndian) // local machine has big endian byte ordering + { + DCMIMGLE_DEBUG("local machine has big endian byte ordering ... swapping 8 bit LUT entries"); + for (i = count; i != 0; --i) // copy 8 bit entries to new 16 bit LUT (swap hi/lo byte) + { + *(q++) = *(p + 1); // copy low byte ... + *(q++) = *p; // ... and then high byte + p += 2; // jump to next hi/lo byte pair + } + } else { // local machine has little endian byte ordering (or unknown) + for (i = Count; i != 0; --i) + *(q++) = *(p++); // copy 8 bit entries to new 16 bit LUT + } + } + Data = DataBuffer; + } else { + DCMIMGLE_WARN("invalid value for 'NumberOfTableEntries' (" << Count << ") ... assuming " << count); + Count = count; + } + } + MinValue = OFstatic_cast(Uint16, DicomImageClass::maxval(MAX_TABLE_ENTRY_SIZE)); // set minimum to maximum value + register const Uint16 *p = Data; + register Uint16 value; + if (DataBuffer != NULL) // LUT entries have been copied 8 -> 16 bits + { + for (i = Count; i != 0; --i) + { + value = *(p++); + if (value < MinValue) // get global minimum + MinValue = value; + if (value > MaxValue) // get global maximum + MaxValue = value; + } + checkBits(bits, 8, 0, descripMode); // set 'Bits' + } else { + int cmp = 0; + for (i = Count; i != 0; --i) + { + value = *(p++); + if (((value >> 8) != 0) && (value & 0xff) != (value >> 8)) // lo-byte not equal to hi-byte and ... + cmp = 1; + if (value < MinValue) // get global minimum + MinValue = value; + if (value > MaxValue) // get global maximum + MaxValue = value; + } + if (cmp == 0) // lo-byte is always equal to hi-byte + checkBits(bits, MIN_TABLE_ENTRY_SIZE, MAX_TABLE_ENTRY_SIZE, descripMode); // set 'Bits' + else + checkBits(bits, MAX_TABLE_ENTRY_SIZE, MIN_TABLE_ENTRY_SIZE, descripMode); + } + Uint16 mask = OFstatic_cast(Uint16, DicomImageClass::maxval(Bits)); // mask lo-byte (8) or full word (16) + if (((MinValue & mask) != MinValue) || ((MaxValue & mask) != MaxValue)) + { // mask table entries and copy them to new LUT + MinValue &= mask; + MaxValue &= mask; + if (DataBuffer == NULL) + DataBuffer = new Uint16[Count]; // create new LUT + if (DataBuffer != NULL) + { + p = Data; + register Uint16 *q = DataBuffer; + for (i = Count; i != 0; --i) + *(q++) = *(p++) & mask; + } + Data = DataBuffer; + } + Valid = (Data != NULL); // lookup table is valid + } else { + if (status != NULL) + { + *status = EIS_InvalidValue; + DCMIMGLE_ERROR("empty 'LookupTableData' attribute"); + } else { + DCMIMGLE_WARN("empty 'LookupTableData' attribute ... ignoring LUT"); + } + } +} + + +/********************************************************************/ + + +void DiLookupTable::checkBits(const Uint16 bits, + const Uint16 rightBits, + const Uint16 wrongBits, + const EL_BitsPerTableEntry descripMode) +{ + /* is stored bit depth out of range? */ + if ((descripMode == ELM_IgnoreValue) || (bits < MIN_TABLE_ENTRY_SIZE) || (bits > MAX_TABLE_ENTRY_SIZE)) + { + /* check whether correct bit depth can be determined automatically */ + Bits = (MaxValue > 0) ? DicomImageClass::tobits(MaxValue, 0) : bits; + /* check bit depth (again) for valid range */ + if (Bits < MIN_TABLE_ENTRY_SIZE) + Bits = MIN_TABLE_ENTRY_SIZE; + else if (Bits > MAX_TABLE_ENTRY_SIZE) + Bits = MAX_TABLE_ENTRY_SIZE; + /* check whether value has changed? */ + if (bits != Bits) + { + if (descripMode == ELM_IgnoreValue) + { + DCMIMGLE_INFO("ignoring value for 'BitsPerTableEntry' (" << bits << ") ... using " << Bits << " instead"); + } else { + DCMIMGLE_WARN("unsuitable value for 'BitsPerTableEntry' (" << bits << ") ... valid range " + << MIN_TABLE_ENTRY_SIZE << "-" << MAX_TABLE_ENTRY_SIZE << ", using " << Bits); + } + } + } + else if ((descripMode == ELM_CheckValue) && (bits == wrongBits)) + { + DCMIMGLE_WARN("unsuitable value for 'BitsPerTableEntry' (" << bits << ") ... assuming " << rightBits); + Bits = rightBits; + } else { + /* assuming that the descriptor value is correct! */ + Bits = bits; + } +} + + +int DiLookupTable::invertTable(const int flag) +{ + int result = 0; + if ((Data != NULL) && (Count > 0) && (flag & 0x3)) + { + register Uint32 i; + if (flag & 0x2) + { + if (OriginalData != NULL) + { + if (OriginalBitsAllocated == 8) + { + if (Bits <= 8) + { + register const Uint8 *p = OFconst_cast(const Uint8 *, OFstatic_cast(Uint8 *, OriginalData)); + register Uint8 *q = OFstatic_cast(Uint8 *, OriginalData); + const Uint8 max = OFstatic_cast(Uint8, DicomImageClass::maxval(Bits)); + for (i = Count; i != 0; --i) + *(q++) = max - *(p++); + result |= 0x2; + } + } else { + register const Uint16 *p = OFconst_cast(const Uint16 *, OFstatic_cast(Uint16 *, OriginalData)); + register Uint16 *q = OFstatic_cast(Uint16 *, OriginalData); + const Uint16 max = OFstatic_cast(Uint16, DicomImageClass::maxval(Bits)); + for (i = Count; i != 0; --i) + *(q++) = max - *(p++); + result |= 0x2; + } + } + } + if (flag & 0x1) + { + if (DataBuffer != NULL) + { + register const Uint16 *p = OFconst_cast(const Uint16 *, DataBuffer); + register Uint16 *q = DataBuffer; + const Uint16 max = OFstatic_cast(Uint16, DicomImageClass::maxval(Bits)); + for (i = Count; i != 0; --i) + *(q++) = max - *(p++); + result |= 0x1; + } + else if (!(flag & 0x2)) + { + DataBuffer = new Uint16[Count]; + if (DataBuffer != NULL) + { + register const Uint16 *p = Data; + register Uint16 *q = DataBuffer; + const Uint16 max = OFstatic_cast(Uint16, DicomImageClass::maxval(Bits)); + for (i = Count; i != 0; --i) + *(q++) = max - *(p++); + Data = DataBuffer; + result |= 0x1; + } + } + } + } + return result; +} + + +int DiLookupTable::mirrorTable(const int flag) +{ + int result = 0; + if ((Data != NULL) && (Count > 0) && (flag & 0x3)) + { + register Uint32 i; + if (flag & 0x2) + { + if (OriginalData != NULL) + { + if (OriginalBitsAllocated == 8) + { + if (Bits <= 8) + { + register Uint8 *p = OFstatic_cast(Uint8 *, OriginalData) + (Count - 1); + register Uint8 *q = OFstatic_cast(Uint8 *, OriginalData); + register Uint8 val; + const unsigned long mid = Count / 2; + for (i = mid; i != 0; --i) + { + val = *q; + *(q++) = *p; + *(p--) = val; + } + result |= 0x2; + } + } else { + register Uint16 *p = OFstatic_cast(Uint16 *, OriginalData) + (Count - 1); + register Uint16 *q = OFstatic_cast(Uint16 *, OriginalData); + register Uint16 val; + const unsigned long mid = Count / 2; + for (i = mid; i != 0; --i) + { + val = *q; + *(q++) = *p; + *(p--) = val; + } + result |= 0x2; + } + } + } + if (flag & 0x1) + { + if (DataBuffer != NULL) + { + register Uint16 *p = DataBuffer + (Count - 1); + register Uint16 *q = DataBuffer; + register Uint16 val; + const unsigned long mid = Count / 2; + for (i = mid; i != 0; --i) + { + val = *q; + *(q++) = *p; + *(p--) = val; + } + result |= 0x1; + } + else if (!(flag & 0x2)) + { + DataBuffer = new Uint16[Count]; + if (DataBuffer != NULL) + { + register Uint16 *p = OFconst_cast(Uint16 *, Data) + (Count - 1); + register Uint16 *q = DataBuffer; + register Uint16 val; + const unsigned long mid = Count / 2; + for (i = mid; i != 0; --i) + { + val = *q; + *(q++) = *p; + *(p--) = val; + } + Data = DataBuffer; + result |= 0x1; + } + } + } + } + return result; +} + + +DiLookupTable *DiLookupTable::createInverseLUT() const +{ + DiLookupTable *lut = NULL; + if (Valid) + { + const Uint32 count = DicomImageClass::maxval(Bits, 0); + const Uint16 bits = DicomImageClass::tobits(Count + FirstEntry); + Uint16 *data = new Uint16[count]; + Uint8 *valid = new Uint8[count]; + if ((data != NULL) && (valid != NULL)) + { + OFBitmanipTemplate::zeroMem(valid, count); // initialize array + register Uint32 i; + for (i = 0; i < Count; ++i) // 'copy' values to new array + { + if (!valid[Data[i]]) + data[Data[i]] = OFstatic_cast(Uint16, i + FirstEntry); + valid[Data[i]] = 1; + } + Uint32 last = 0; + i = 0; + while (i < count) // fill gaps with valid values + { + if (valid[i]) // skip valid values + last = i; + else + { + register Uint32 j = i + 1; + while ((j < count) && !valid[j]) // find next valid value + ++j; + if (valid[last]) // check for starting conditions + { + const Uint32 mid = (j < count) ? (i + j) / 2 : count; + while (i < mid) + { // fill first half with 'left' value + data[i] = data[last]; + ++i; + } + } + if ((j < count) && valid[j]) + { + while (i < j) // fill second half with 'right' value + { + data[i] = data[j]; + ++i; + } + last = j; + } + } + ++i; + } + lut = new DiLookupTable(data, count, bits); // create new LUT + } + delete[] valid; + } + return lut; +} + + +int DiLookupTable::compareLUT(const DcmUnsignedShort &data, + const DcmUnsignedShort &descriptor) +{ + int result = 1; + DiBaseLUT *lut = new DiLookupTable(data, descriptor); + if (lut != NULL) + result = compare(lut); + delete lut; + return result; +} + + +OFBool DiLookupTable::operator==(const DiBaseLUT &lut) +{ + return (compare(&lut) == 0); +} + + +OFBool DiLookupTable::operator==(const DiLookupTable &lut) +{ + return (compare(OFstatic_cast(const DiBaseLUT *, &lut)) == 0); +} diff --git a/dcmimgle/libsrc/dimo1img.cc b/dcmimgle/libsrc/dimo1img.cc new file mode 100644 index 00000000..613b067c --- /dev/null +++ b/dcmimgle/libsrc/dimo1img.cc @@ -0,0 +1,154 @@ +/* + * + * Copyright (C) 1996-2010, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimgle + * + * Author: Joerg Riesmeier + * + * Purpose: DicomMonochrome1Image (Source) + * + */ + + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmdata/dctypes.h" + +#include "dcmtk/dcmimgle/dimo1img.h" +#include "dcmtk/dcmimgle/diutils.h" + + +/*----------------* + * constructors * + *----------------*/ + +DiMono1Image::DiMono1Image(const DiDocument *docu, + const EI_Status status) + : DiMonoImage(docu, status) +{ +} + + +DiMono1Image::DiMono1Image(const DiMonoImage *image, + const unsigned long fstart, + const unsigned long fcount) + : DiMonoImage(image, fstart, fcount) +{ +} + + +DiMono1Image::DiMono1Image(const DiMonoImage *image, + const signed long left_pos, + const signed long top_pos, + const Uint16 src_cols, + const Uint16 src_rows, + const Uint16 dest_cols, + const Uint16 dest_rows, + const int interpolate, + const int aspect, + const Uint16 pvalue) + : DiMonoImage(image, left_pos, top_pos, src_cols, src_rows, dest_cols, dest_rows, interpolate, aspect, pvalue) +{ +} + + +DiMono1Image::DiMono1Image(const DiMonoImage *image, + const int horz, + const int vert) + : DiMonoImage(image, horz, vert) +{ +} + + +DiMono1Image::DiMono1Image(const DiMonoImage *image, + const int degree) + : DiMonoImage(image, degree) +{ +} + + +/*--------------* + * destructor * + *--------------*/ + +DiMono1Image::~DiMono1Image() +{ +} + + +/*********************************************************************/ + + +const void *DiMono1Image::getOutputData(const unsigned long frame, + const int bits, + const int planar) +{ + return DiMonoImage::getData(NULL, 0, frame, bits, planar, 1); +} + + +int DiMono1Image::getOutputData(void *buffer, + const unsigned long size, + const unsigned long frame, + const int bits, + const int planar) +{ + return (DiMonoImage::getData(buffer, size, frame, bits, planar, 1) != NULL); +} + + +DiImage *DiMono1Image::createImage(const unsigned long fstart, + const unsigned long fcount) const +{ + DiImage *image = new DiMono1Image(this, fstart, fcount); + return image; +} + + +DiImage *DiMono1Image::createScale(const signed long left_pos, + const signed long top_pos, + const unsigned long src_cols, + const unsigned long src_rows, + const unsigned long dest_cols, + const unsigned long dest_rows, + const int interpolate, + const int aspect, + const Uint16 pvalue) const +{ + DiImage *image = new DiMono1Image(this, left_pos, top_pos, OFstatic_cast(Uint16, src_cols), + OFstatic_cast(Uint16, src_rows), OFstatic_cast(Uint16, dest_cols), OFstatic_cast(Uint16, dest_rows), + interpolate, aspect, pvalue); + return image; +} + + +DiImage *DiMono1Image::createFlip(const int horz, + const int vert) const +{ + DiImage *image = new DiMono1Image(this, horz, vert); + return image; +} + + +DiImage *DiMono1Image::createRotate(const int degree) const +{ + DiImage *image = new DiMono1Image(this, degree); + return image; +} + + +DiImage *DiMono1Image::createMono(const double, + const double, + const double) const +{ + return createImage(0, 0); +} diff --git a/dcmimgle/libsrc/dimo2img.cc b/dcmimgle/libsrc/dimo2img.cc new file mode 100644 index 00000000..ed88fbf8 --- /dev/null +++ b/dcmimgle/libsrc/dimo2img.cc @@ -0,0 +1,200 @@ +/* + * + * Copyright (C) 1996-2010, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimgle + * + * Author: Joerg Riesmeier + * + * Purpose: DicomMonochrome2Image (Source) + * + */ + + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmdata/dctypes.h" + +#include "dcmtk/dcmimgle/dimo2img.h" +#include "dcmtk/dcmimgle/diutils.h" + + +/*----------------* + * constructors * + *----------------*/ + +DiMono2Image::DiMono2Image(const DiDocument *docu, + const EI_Status status) + : DiMonoImage(docu, status) +{ +} + + +DiMono2Image::DiMono2Image(const DiDocument *docu, + const EI_Status status, + const double slope, + const double intercept) + : DiMonoImage(docu, status, slope, intercept) +{ +} + + +DiMono2Image::DiMono2Image(const DiDocument *docu, + const EI_Status status, + const DcmUnsignedShort &data, + const DcmUnsignedShort &descriptor, + const DcmLongString *explanation) + : DiMonoImage(docu, status, data, descriptor, explanation) +{ +} + + +DiMono2Image::DiMono2Image(const DiDocument *docu, + const EI_Status status, + const char dummy) + : DiMonoImage(docu, status, dummy) +{ +} + + +DiMono2Image::DiMono2Image(const DiMonoImage *image, + const unsigned long fstart, + const unsigned long fcount) + : DiMonoImage(image, fstart, fcount) +{ +} + + +DiMono2Image::DiMono2Image(const DiColorImage *image, + const double red, + const double green, + const double blue) + : DiMonoImage(image, red, green, blue) +{ +} + + +DiMono2Image::DiMono2Image(const DiMonoImage *image, + const signed long left_pos, + const signed long top_pos, + const Uint16 src_cols, + const Uint16 src_rows, + const Uint16 dest_cols, + const Uint16 dest_rows, + const int interpolate, + const int aspect, + const Uint16 pvalue) + : DiMonoImage(image, left_pos, top_pos, src_cols, src_rows, dest_cols, dest_rows, interpolate, aspect, pvalue) +{ +} + + +DiMono2Image::DiMono2Image(const DiMonoImage *image, + const int horz, + const int vert) + : DiMonoImage(image, horz, vert) +{ +} + + +DiMono2Image::DiMono2Image(const DiMonoImage *image, + const int degree) + : DiMonoImage(image, degree) +{ +} + + +DiMono2Image::DiMono2Image(const DiMonoImage *image, + DiMonoOutputPixel *pixel, + const unsigned long frame, + const int stored, + const int alloc) + : DiMonoImage(image, pixel, frame, stored, alloc) +{ +} + + +/*--------------* + * destructor * + *--------------*/ + +DiMono2Image::~DiMono2Image() +{ +} + + +/*********************************************************************/ + + +const void *DiMono2Image::getOutputData(const unsigned long frame, + const int bits, + const int planar) +{ + return DiMonoImage::getData(NULL, 0, frame, bits, planar, 0); +} + + +int DiMono2Image::getOutputData(void *buffer, + const unsigned long size, + const unsigned long frame, + const int bits, + const int planar) +{ + return (DiMonoImage::getData(buffer, size, frame, bits, planar, 0) != NULL); +} + + +DiImage *DiMono2Image::createImage(const unsigned long fstart, + const unsigned long fcount) const +{ + DiImage *image = new DiMono2Image(this, fstart, fcount); + return image; +} + + +DiImage *DiMono2Image::createScale(const signed long left_pos, + const signed long top_pos, + const unsigned long src_cols, + const unsigned long src_rows, + const unsigned long dest_cols, + const unsigned long dest_rows, + const int interpolate, + const int aspect, + const Uint16 pvalue) const +{ + DiImage *image = new DiMono2Image(this, left_pos, top_pos, OFstatic_cast(Uint16, src_cols), + OFstatic_cast(Uint16, src_rows), OFstatic_cast(Uint16, dest_cols), OFstatic_cast(Uint16, dest_rows), + interpolate, aspect, pvalue); + return image; +} + + +DiImage *DiMono2Image::createFlip(const int horz, + const int vert) const +{ + DiImage *image = new DiMono2Image(this, horz, vert); + return image; +} + + +DiImage *DiMono2Image::createRotate(const int degree) const +{ + DiImage *image = new DiMono2Image(this, degree); + return image; +} + + +DiImage *DiMono2Image::createMono(const double, + const double, + const double) const +{ + return createImage(0, 0); +} diff --git a/dcmimgle/libsrc/dimoimg.cc b/dcmimgle/libsrc/dimoimg.cc new file mode 100644 index 00000000..342de79c --- /dev/null +++ b/dcmimgle/libsrc/dimoimg.cc @@ -0,0 +1,2166 @@ +/* + * + * Copyright (C) 1996-2013, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimgle + * + * Author: Joerg Riesmeier + * + * Purpose: DicomMonochromeImage (Source) + * + */ + + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmdata/dctypes.h" +#include "dcmtk/dcmdata/dcdeftag.h" + +#include "dcmtk/dcmimgle/dimoimg.h" +#include "dcmtk/dcmimgle/dimo2img.h" +#include "dcmtk/dcmimgle/dimoipxt.h" +#include "dcmtk/dcmimgle/dimocpt.h" +#include "dcmtk/dcmimgle/dimosct.h" +#include "dcmtk/dcmimgle/dimoflt.h" +#include "dcmtk/dcmimgle/dimorot.h" +#include "dcmtk/dcmimgle/dimoopxt.h" +#include "dcmtk/dcmimgle/digsdfn.h" +#include "dcmtk/dcmimgle/didocu.h" +#include "dcmtk/dcmimgle/diutils.h" +#include "dcmtk/dcmimgle/diregbas.h" + +#define INCLUDE_CMATH +#include "dcmtk/ofstd/ofstdinc.h" + + +/*---------------------* + * const definitions * + *---------------------*/ + +const unsigned int Default_MinDensity = 20; +const unsigned int Default_MaxDensity = 300; +const unsigned int Default_Reflection = 10; +const unsigned int Default_Illumination = 2000; + + +/*----------------* + * constructors * + *----------------*/ + +/* + * standard constructor to create mono-image + */ + +DiMonoImage::DiMonoImage(const DiDocument *docu, + const EI_Status status) + : DiImage(docu, status, 1), + WindowCenter(0), + WindowWidth(0), + WindowCount(0), + VoiLutCount(0), + ValidWindow(0), + VoiExplanation(), + VoiLutFunction(EFV_Default), + PresLutShape(ESP_Default), + MinDensity(Default_MinDensity), + MaxDensity(Default_MaxDensity), + Reflection(Default_Reflection), + Illumination(Default_Illumination), + VoiLutData(NULL), + PresLutData(NULL), + InterData(NULL), + DisplayFunction(NULL), + OutputData(NULL), + OverlayData(NULL) +{ + Overlays[0] = NULL; + Overlays[1] = NULL; + if ((Document != NULL) && (InputData != NULL) && (ImageStatus == EIS_Normal)) + { + if (Document->getFlags() & CIF_UsePresentationState) + PresLutShape = ESP_Identity; + DiMonoModality *modality = new DiMonoModality(Document, InputData); + Init(modality); + } +} + + +DiMonoImage::DiMonoImage(const DiDocument *docu, + const EI_Status status, + const double slope, + const double intercept) + : DiImage(docu, status, 1), + WindowCenter(0), + WindowWidth(0), + WindowCount(0), + VoiLutCount(0), + ValidWindow(0), + VoiExplanation(), + VoiLutFunction(EFV_Default), + PresLutShape(ESP_Default), + MinDensity(Default_MinDensity), + MaxDensity(Default_MaxDensity), + Reflection(Default_Reflection), + Illumination(Default_Illumination), + VoiLutData(NULL), + PresLutData(NULL), + InterData(NULL), + DisplayFunction(NULL), + OutputData(NULL), + OverlayData(NULL) +{ + Overlays[0] = NULL; + Overlays[1] = NULL; + if ((Document != NULL) && (InputData != NULL) && (ImageStatus == EIS_Normal)) + { + if (Document->getFlags() & CIF_UsePresentationState) + PresLutShape = ESP_Identity; + DiMonoModality *modality = new DiMonoModality(Document, InputData, slope, intercept); + Init(modality); + } +} + + +DiMonoImage::DiMonoImage(const DiDocument *docu, + const EI_Status status, + const DcmUnsignedShort &data, + const DcmUnsignedShort &descriptor, + const DcmLongString *explanation) + : DiImage(docu, status, 1), + WindowCenter(0), + WindowWidth(0), + WindowCount(0), + VoiLutCount(0), + ValidWindow(0), + VoiExplanation(), + VoiLutFunction(EFV_Default), + PresLutShape(ESP_Default), + MinDensity(Default_MinDensity), + MaxDensity(Default_MaxDensity), + Reflection(Default_Reflection), + Illumination(Default_Illumination), + VoiLutData(NULL), + PresLutData(NULL), + InterData(NULL), + DisplayFunction(NULL), + OutputData(NULL), + OverlayData(NULL) +{ + Overlays[0] = NULL; + Overlays[1] = NULL; + if ((Document != NULL) && (InputData != NULL) && (ImageStatus == EIS_Normal)) + { + if (Document->getFlags() & CIF_UsePresentationState) + PresLutShape = ESP_Identity; + DiMonoModality *modality = new DiMonoModality(Document, InputData, data, descriptor, explanation); + Init(modality); + } +} + + +/* + * kind of copy-constructor, 'dummy' is necessary to differ from the above "standard"-constructor + */ + +DiMonoImage::DiMonoImage(const DiDocument *docu, + const EI_Status status, + const char /*dummy*/) + : DiImage(docu, status/*, dummy*/), + WindowCenter(0), + WindowWidth(0), + WindowCount(0), + VoiLutCount(0), + ValidWindow(0), + VoiExplanation(), + VoiLutFunction(EFV_Default), + PresLutShape(ESP_Default), + MinDensity(Default_MinDensity), + MaxDensity(Default_MaxDensity), + Reflection(Default_Reflection), + Illumination(Default_Illumination), + VoiLutData(NULL), + PresLutData(NULL), + InterData(NULL), + DisplayFunction(NULL), + OutputData(NULL), + OverlayData(NULL) +{ + Overlays[0] = NULL; + Overlays[1] = NULL; +} + + +/* + * create image copy of specified frame range + */ + +DiMonoImage::DiMonoImage(const DiMonoImage *image, + const unsigned long fstart, + const unsigned long fcount) + : DiImage(image, fstart, fcount), + WindowCenter(image->WindowCenter), + WindowWidth(image->WindowWidth), + WindowCount(image->WindowCount), + VoiLutCount(image->VoiLutCount), + ValidWindow(image->ValidWindow), + VoiExplanation(image->VoiExplanation), + VoiLutFunction(image->VoiLutFunction), + PresLutShape(image->PresLutShape), + MinDensity(image->MinDensity), + MaxDensity(image->MaxDensity), + Reflection(image->Reflection), + Illumination(image->Illumination), + VoiLutData(image->VoiLutData), + PresLutData(image->PresLutData), + InterData(NULL), + DisplayFunction(image->DisplayFunction), + OutputData(NULL), + OverlayData(NULL) +{ + Overlays[0] = image->Overlays[0]; + Overlays[1] = image->Overlays[1]; + if (image->InterData != NULL) + { + const unsigned long fsize = OFstatic_cast(unsigned long, Columns) * OFstatic_cast(unsigned long, Rows); + switch (image->InterData->getRepresentation()) + { + case EPR_Uint8: + InterData = new DiMonoCopyTemplate(image->InterData, fstart, fcount, fsize); + break; + case EPR_Sint8: + InterData = new DiMonoCopyTemplate(image->InterData, fstart, fcount, fsize); + break; + case EPR_Uint16: + InterData = new DiMonoCopyTemplate(image->InterData, fstart, fcount, fsize); + break; + case EPR_Sint16: + InterData = new DiMonoCopyTemplate(image->InterData, fstart, fcount, fsize); + break; + case EPR_Uint32: + InterData = new DiMonoCopyTemplate(image->InterData, fstart, fcount, fsize); + break; + case EPR_Sint32: + InterData = new DiMonoCopyTemplate(image->InterData, fstart, fcount, fsize); + break; + } + } + checkInterData(); + for (int i = 0; i < 2; ++i) + { + if (Overlays[i] != NULL) + Overlays[i]->addReference(); + } + if (VoiLutData != NULL) + VoiLutData->addReference(); + if (PresLutData != NULL) + PresLutData->addReference(); +} + + +/* + * convert color-image to mono-image with given 'red', 'green' and 'blue' coefficients + */ + +DiMonoImage::DiMonoImage(const DiColorImage *image, + const double red, + const double green, + const double blue) + : DiImage(OFreinterpret_cast(const DiImage *, image)), + WindowCenter(0), + WindowWidth(0), + WindowCount(0), + VoiLutCount(0), + ValidWindow(0), + VoiExplanation(), + VoiLutFunction(EFV_Default), + PresLutShape(ESP_Default), + MinDensity(Default_MinDensity), + MaxDensity(Default_MaxDensity), + Reflection(Default_Reflection), + Illumination(Default_Illumination), + VoiLutData(NULL), + PresLutData(NULL), + InterData(NULL), + DisplayFunction(NULL), + OutputData(NULL), + OverlayData(NULL) +{ + Overlays[0] = NULL; + Overlays[1] = NULL; + if ((Document != NULL) && (Document->getFlags() & CIF_UsePresentationState)) + PresLutShape = ESP_Identity; + if (DiRegisterBase::Pointer != NULL) + InterData = DiRegisterBase::Pointer->createMonoImageData(image, red, green, blue); + if ((InterData == NULL) || (InterData->getData() == NULL)) + ImageStatus = EIS_InvalidImage; +} + + +/* + * scale 'image' to size given by 'columns' and 'rows', 'interpolate' always if parameter is true + */ + +DiMonoImage::DiMonoImage(const DiMonoImage *image, + const signed long left_pos, + const signed long top_pos, + const Uint16 src_cols, + const Uint16 src_rows, + const Uint16 dest_cols, + const Uint16 dest_rows, + const int interpolate, + const int aspect, + const Uint16 pvalue) + : DiImage(image, dest_cols, dest_rows, aspect), + WindowCenter(image->WindowCenter), + WindowWidth(image->WindowWidth), + WindowCount(image->WindowCount), + VoiLutCount(image->VoiLutCount), + ValidWindow(image->ValidWindow), + VoiExplanation(image->VoiExplanation), + VoiLutFunction(image->VoiLutFunction), + PresLutShape(image->PresLutShape), + MinDensity(image->MinDensity), + MaxDensity(image->MaxDensity), + Reflection(image->Reflection), + Illumination(image->Illumination), + VoiLutData(image->VoiLutData), + PresLutData(image->PresLutData), + InterData(NULL), + DisplayFunction(image->DisplayFunction), + OutputData(NULL), + OverlayData(NULL) +{ + Overlays[0] = NULL; + Overlays[1] = NULL; + if (image->InterData != NULL) + { + const unsigned int bits = image->InterData->getBits(); + switch (image->InterData->getRepresentation()) + { + case EPR_Uint8: + InterData = new DiMonoScaleTemplate(image->InterData, image->Columns, image->Rows, + left_pos, top_pos, src_cols, src_rows, dest_cols, dest_rows, NumberOfFrames, + bits, interpolate, pvalue); + break; + case EPR_Sint8: + InterData = new DiMonoScaleTemplate(image->InterData, image->Columns, image->Rows, + left_pos, top_pos, src_cols, src_rows, dest_cols, dest_rows, NumberOfFrames, + bits, interpolate, pvalue); + break; + case EPR_Uint16: + InterData = new DiMonoScaleTemplate(image->InterData, image->Columns, image->Rows, + left_pos, top_pos, src_cols, src_rows, dest_cols, dest_rows, NumberOfFrames, + bits, interpolate, pvalue); + break; + case EPR_Sint16: + InterData = new DiMonoScaleTemplate(image->InterData, image->Columns, image->Rows, + left_pos, top_pos, src_cols, src_rows, dest_cols, dest_rows, NumberOfFrames, + bits, interpolate, pvalue); + break; + case EPR_Uint32: + InterData = new DiMonoScaleTemplate(image->InterData, image->Columns, image->Rows, + left_pos, top_pos, src_cols, src_rows, dest_cols, dest_rows, NumberOfFrames, + bits, interpolate, pvalue); + break; + case EPR_Sint32: + InterData = new DiMonoScaleTemplate(image->InterData, image->Columns, image->Rows, + left_pos, top_pos, src_cols, src_rows, dest_cols, dest_rows, NumberOfFrames, + bits, interpolate, pvalue); + break; + } + } + if (checkInterData(0)) + { + for (int i = 0; i < 2; ++i) + { + if ((image->Overlays[i] != NULL) && (image->Overlays[i]->getCount() > 0)) + { + Overlays[i] = new DiOverlay(image->Overlays[i], left_pos, top_pos, + OFstatic_cast(double, dest_cols) / OFstatic_cast(double, src_cols), + OFstatic_cast(double, dest_rows) / OFstatic_cast(double, src_rows)); + } + } + } + if (VoiLutData != NULL) + VoiLutData->addReference(); + if (PresLutData != NULL) + PresLutData->addReference(); +} + + +/* + * flip + */ + +DiMonoImage::DiMonoImage(const DiMonoImage *image, + const int horz, + const int vert) + : DiImage(image), + WindowCenter(image->WindowCenter), + WindowWidth(image->WindowWidth), + WindowCount(image->WindowCount), + VoiLutCount(image->VoiLutCount), + ValidWindow(image->ValidWindow), + VoiExplanation(image->VoiExplanation), + VoiLutFunction(image->VoiLutFunction), + PresLutShape(image->PresLutShape), + MinDensity(image->MinDensity), + MaxDensity(image->MaxDensity), + Reflection(image->Reflection), + Illumination(image->Illumination), + VoiLutData(image->VoiLutData), + PresLutData(image->PresLutData), + InterData(NULL), + DisplayFunction(image->DisplayFunction), + OutputData(NULL), + OverlayData(NULL) +{ + Overlays[0] = NULL; + Overlays[1] = NULL; + if (image->InterData != NULL) + { + switch (image->InterData->getRepresentation()) + { + case EPR_Uint8: + InterData = new DiMonoFlipTemplate(image->InterData, Columns, Rows, NumberOfFrames, horz, vert); + break; + case EPR_Sint8: + InterData = new DiMonoFlipTemplate(image->InterData, Columns, Rows, NumberOfFrames, horz, vert); + break; + case EPR_Uint16: + InterData = new DiMonoFlipTemplate(image->InterData, Columns, Rows, NumberOfFrames, horz, vert); + break; + case EPR_Sint16: + InterData = new DiMonoFlipTemplate(image->InterData, Columns, Rows, NumberOfFrames, horz, vert); + break; + case EPR_Uint32: + InterData = new DiMonoFlipTemplate(image->InterData, Columns, Rows, NumberOfFrames, horz, vert); + break; + case EPR_Sint32: + InterData = new DiMonoFlipTemplate(image->InterData, Columns, Rows, NumberOfFrames, horz, vert); + break; + } + } + if (checkInterData(0)) + { + for (int i = 0; i < 2; ++i) + { + if ((image->Overlays[i] != NULL) && (image->Overlays[i]->getCount() > 0)) + Overlays[i] = new DiOverlay(image->Overlays[i], horz, vert, Columns, Rows); + } + } + if (VoiLutData != NULL) + VoiLutData->addReference(); + if (PresLutData != NULL) + PresLutData->addReference(); +} + + +/* + * rotate + */ + +DiMonoImage::DiMonoImage(const DiMonoImage *image, + const int degree) + : DiImage(image, degree), + WindowCenter(image->WindowCenter), + WindowWidth(image->WindowWidth), + WindowCount(image->WindowCount), + VoiLutCount(image->VoiLutCount), + ValidWindow(image->ValidWindow), + VoiExplanation(image->VoiExplanation), + VoiLutFunction(image->VoiLutFunction), + PresLutShape(image->PresLutShape), + MinDensity(image->MinDensity), + MaxDensity(image->MaxDensity), + Reflection(image->Reflection), + Illumination(image->Illumination), + VoiLutData(image->VoiLutData), + PresLutData(image->PresLutData), + InterData(NULL), + DisplayFunction(image->DisplayFunction), + OutputData(NULL), + OverlayData(NULL) +{ + Overlays[0] = NULL; + Overlays[1] = NULL; + if (image->InterData != NULL) + { + switch (image->InterData->getRepresentation()) + { + case EPR_Uint8: + InterData = new DiMonoRotateTemplate(image->InterData, image->Columns, image->Rows, Columns, Rows, + NumberOfFrames, degree); + break; + case EPR_Sint8: + InterData = new DiMonoRotateTemplate(image->InterData, image->Columns, image->Rows, Columns, Rows, + NumberOfFrames, degree); + break; + case EPR_Uint16: + InterData = new DiMonoRotateTemplate(image->InterData, image->Columns, image->Rows, Columns, Rows, + NumberOfFrames, degree); + break; + case EPR_Sint16: + InterData = new DiMonoRotateTemplate(image->InterData, image->Columns, image->Rows, Columns, Rows, + NumberOfFrames, degree); + break; + case EPR_Uint32: + InterData = new DiMonoRotateTemplate(image->InterData, image->Columns, image->Rows, Columns, Rows, + NumberOfFrames, degree); + break; + case EPR_Sint32: + InterData = new DiMonoRotateTemplate(image->InterData, image->Columns, image->Rows, Columns, Rows, + NumberOfFrames, degree); + break; + } + } + if (checkInterData(0)) + { + for (int i = 0; i < 2; ++i) + { + if ((image->Overlays[i] != NULL) && (image->Overlays[i]->getCount() > 0)) + Overlays[i] = new DiOverlay(image->Overlays[i], degree, Columns, Rows); + } + } + if (VoiLutData != NULL) + VoiLutData->addReference(); + if (PresLutData != NULL) + PresLutData->addReference(); +} + + +/* + * this implementation is necessary to avoid linker errors on NeXTSTEP (gcc 2.5.8) + */ + +DiMonoImage::DiMonoImage(const DiMonoImage &) + : DiImage(NULL), + WindowCenter(0), + WindowWidth(0), + WindowCount(0), + VoiLutCount(0), + ValidWindow(0), + VoiExplanation(), + VoiLutFunction(EFV_Default), + PresLutShape(ESP_Default), + MinDensity(Default_MinDensity), + MaxDensity(Default_MaxDensity), + Reflection(Default_Reflection), + Illumination(Default_Illumination), + VoiLutData(NULL), + PresLutData(NULL), + InterData(NULL), + DisplayFunction(NULL), + OutputData(NULL), + OverlayData(NULL) +{ + DCMIMGLE_FATAL("using unimplemented copy constructor in class DiMonoImage ... aborting"); + abort(); +} + + +/* + * createMonoOutputImage + */ + +DiMonoImage::DiMonoImage(const DiMonoImage *image, + DiMonoOutputPixel *pixel, + const unsigned long frame, + const int stored, + const int alloc) + : DiImage(image, frame, stored, alloc), + WindowCenter(0), + WindowWidth(0), + WindowCount(0), + VoiLutCount(0), + ValidWindow(0), + VoiExplanation(), + VoiLutFunction(EFV_Default), + PresLutShape(ESP_Default), + MinDensity(Default_MinDensity), + MaxDensity(Default_MaxDensity), + Reflection(Default_Reflection), + Illumination(Default_Illumination), + VoiLutData(NULL), + PresLutData(NULL), + InterData(NULL), + DisplayFunction(NULL), + OutputData(NULL), + OverlayData(NULL) +{ + Overlays[0] = NULL; + Overlays[1] = NULL; + if ((Document != NULL) && (Document->getFlags() & CIF_UsePresentationState)) + PresLutShape = ESP_Identity; + if (pixel->getData() != NULL) + { + DiMonoModality *modality = new DiMonoModality(stored); + switch (pixel->getRepresentation()) + { + case EPR_Uint8: + InterData = new DiMonoPixelTemplate(pixel, modality); + break; + case EPR_Uint16: + InterData = new DiMonoPixelTemplate(pixel, modality); + break; + case EPR_Uint32: + InterData = new DiMonoPixelTemplate(pixel, modality); + break; + default: + break; + } + } + checkInterData(0); +} + + +/*--------------* + * destructor * + *--------------*/ + +DiMonoImage::~DiMonoImage() +{ + delete InterData; + delete OutputData; + delete OFstatic_cast(char *, OverlayData); // type cast necessary to avoid compiler warnings using gcc 2.95 + if (VoiLutData != NULL) + VoiLutData->removeReference(); // only delete if object is no longer referenced + if (PresLutData != NULL) + PresLutData->removeReference(); + for (int i = 0; i < 2; ++i) + { + if (Overlays[i] != NULL) + Overlays[i]->removeReference(); + } +} + + +/*********************************************************************/ + + +int DiMonoImage::processNextFrames(const unsigned long fcount) +{ + if (DiImage::processNextFrames(fcount)) + { + if (InterData != NULL) + { + /* do not create a new object but reference the existing one */ + DiMonoModality *modality = InterData->addReferenceToModality(); + delete InterData; + InterData = NULL; + Init(modality, OFTrue /* reuse */); + return (ImageStatus == EIS_Normal); + } + } + return 0; +} + +/*********************************************************************/ + + +void DiMonoImage::Init(DiMonoModality *modality, + const OFBool reuse) +{ + if (modality != NULL) + { + /* only create new overlay object if none exists */ + if (Overlays[0] == NULL) + { + Overlays[0] = new DiOverlay(Document, BitsAllocated, BitsStored, HighBit); + if ((Overlays[0] != NULL) && !(Document->getFlags() & CIF_UsePresentationState)) + Overlays[0]->showAllPlanes(); // default: show all overlays with stored modes + if ((Overlays[0] == NULL) || (Overlays[0]->getCount() == 0) || (!Overlays[0]->hasEmbeddedData())) + detachPixelData(); // no longer needed, save memory + } + switch (InputData->getRepresentation()) + { + case EPR_Uint8: + InitUint8(modality); + break; + case EPR_Sint8: + InitSint8(modality); + break; + case EPR_Uint16: + InitUint16(modality); + break; + case EPR_Sint16: + InitSint16(modality); + break; + case EPR_Uint32: + InitUint32(modality); + break; + case EPR_Sint32: + InitSint32(modality); + break; + } + deleteInputData(); // no longer needed, save memory + if (modality->getBits() > 0) + BitsPerSample = modality->getBits(); // get bit depth of internal representation + if (checkInterData()) + { + /* get grayscale related attributes (if desired) */ + if (!reuse && !(Document->getFlags() & CIF_UsePresentationState)) + { + /* VOI windows */ + WindowCount = Document->getVM(DCM_WindowCenter); + const unsigned long count = Document->getVM(DCM_WindowWidth); + if (count < WindowCount) // determine number of VOI windows + WindowCount = count; + /* VOI LUT */ + DcmSequenceOfItems *seq = NULL; + VoiLutCount = Document->getSequence(DCM_VOILUTSequence, seq); + /* VOI LUT Function */ + OFString str; + if (Document->getValue(DCM_VOILUTFunction, str)) + { + if (str == "LINEAR") + VoiLutFunction = EFV_Linear; + else if (str == "SIGMOID") + VoiLutFunction = EFV_Sigmoid; + else + DCMIMGLE_WARN("unknown value for 'VOILUTFunction' (" << str << ") ... ignoring"); + } + /* Presentation LUT Shape */ + if (Document->getValue(DCM_PresentationLUTShape, str)) + { + if (str == "IDENTITY") + PresLutShape = ESP_Identity; + else if (str == "INVERSE") + PresLutShape = ESP_Inverse; + else + DCMIMGLE_WARN("unknown value for 'PresentationLUTShape' (" << str << ") ... ignoring"); + } + } + } + } else + detachPixelData(); +} + + +void DiMonoImage::InitUint8(DiMonoModality *modality) +{ + if (modality != NULL) + { + switch (modality->getRepresentation()) + { + case EPR_Uint8: + InterData = new DiMonoInputPixelTemplate(InputData, modality); + break; + case EPR_Sint8: + InterData = new DiMonoInputPixelTemplate(InputData, modality); + break; + case EPR_Uint16: + InterData = new DiMonoInputPixelTemplate(InputData, modality); + break; + case EPR_Sint16: + InterData = new DiMonoInputPixelTemplate(InputData, modality); + break; + case EPR_Uint32: + InterData = new DiMonoInputPixelTemplate(InputData, modality); + break; + case EPR_Sint32: + InterData = new DiMonoInputPixelTemplate(InputData, modality); + break; + } + } +} + + +void DiMonoImage::InitSint8(DiMonoModality *modality) +{ + if (modality != NULL) + { + switch (modality->getRepresentation()) + { + case EPR_Uint8: + InterData = new DiMonoInputPixelTemplate(InputData, modality); + break; + case EPR_Sint8: + InterData = new DiMonoInputPixelTemplate(InputData, modality); + break; + case EPR_Uint16: + InterData = new DiMonoInputPixelTemplate(InputData, modality); + break; + case EPR_Sint16: + InterData = new DiMonoInputPixelTemplate(InputData, modality); + break; + case EPR_Uint32: + InterData = new DiMonoInputPixelTemplate(InputData, modality); + break; + case EPR_Sint32: + InterData = new DiMonoInputPixelTemplate(InputData, modality); + break; + } + } +} + +void DiMonoImage::InitUint16(DiMonoModality *modality) +{ + if (modality != NULL) + { + switch (modality->getRepresentation()) + { + case EPR_Uint8: + InterData = new DiMonoInputPixelTemplate(InputData, modality); + break; + case EPR_Sint8: + InterData = new DiMonoInputPixelTemplate(InputData, modality); + break; + case EPR_Uint16: + InterData = new DiMonoInputPixelTemplate(InputData, modality); + break; + case EPR_Sint16: + InterData = new DiMonoInputPixelTemplate(InputData, modality); + break; + case EPR_Uint32: + InterData = new DiMonoInputPixelTemplate(InputData, modality); + break; + case EPR_Sint32: + InterData = new DiMonoInputPixelTemplate(InputData, modality); + break; + } + } +} + + +void DiMonoImage::InitSint16(DiMonoModality *modality) +{ + if (modality != NULL) + { + switch (modality->getRepresentation()) + { + case EPR_Uint8: + InterData = new DiMonoInputPixelTemplate(InputData, modality); + break; + case EPR_Sint8: + InterData = new DiMonoInputPixelTemplate(InputData, modality); + break; + case EPR_Uint16: + InterData = new DiMonoInputPixelTemplate(InputData, modality); + break; + case EPR_Sint16: + InterData = new DiMonoInputPixelTemplate(InputData, modality); + break; + case EPR_Uint32: + InterData = new DiMonoInputPixelTemplate(InputData, modality); + break; + case EPR_Sint32: + InterData = new DiMonoInputPixelTemplate(InputData, modality); + break; + } + } +} + + +void DiMonoImage::InitUint32(DiMonoModality *modality) +{ + if (modality != NULL) + { + switch (modality->getRepresentation()) + { + case EPR_Uint8: + InterData = new DiMonoInputPixelTemplate(InputData, modality); + break; + case EPR_Sint8: + InterData = new DiMonoInputPixelTemplate(InputData, modality); + break; + case EPR_Uint16: + InterData = new DiMonoInputPixelTemplate(InputData, modality); + break; + case EPR_Sint16: + InterData = new DiMonoInputPixelTemplate(InputData, modality); + break; + case EPR_Uint32: + InterData = new DiMonoInputPixelTemplate(InputData, modality); + break; + case EPR_Sint32: + InterData = new DiMonoInputPixelTemplate(InputData, modality); + break; + } + } +} + + +void DiMonoImage::InitSint32(DiMonoModality *modality) +{ + if (modality != NULL) + { + switch (modality->getRepresentation()) + { + case EPR_Uint8: + InterData = new DiMonoInputPixelTemplate(InputData, modality); + break; + case EPR_Sint8: + InterData = new DiMonoInputPixelTemplate(InputData, modality); + break; + case EPR_Uint16: + InterData = new DiMonoInputPixelTemplate(InputData, modality); + break; + case EPR_Sint16: + InterData = new DiMonoInputPixelTemplate(InputData, modality); + break; + case EPR_Uint32: + InterData = new DiMonoInputPixelTemplate(InputData, modality); + break; + case EPR_Sint32: + InterData = new DiMonoInputPixelTemplate(InputData, modality); + break; + } + } +} + +/*********************************************************************/ + + +int DiMonoImage::checkInterData(const int mode) +{ + if (InterData == NULL) + { + if (ImageStatus == EIS_Normal) + { + ImageStatus = EIS_MemoryFailure; + DCMIMGLE_ERROR("can't allocate memory for inter-representation"); + } else + ImageStatus = EIS_InvalidImage; + } + else if (InterData->getData() == NULL) + ImageStatus = EIS_InvalidImage; + else if (mode && (ImageStatus == EIS_Normal) && isOriginal /* do not check derived images */) + { + const unsigned long count = OFstatic_cast(unsigned long, Columns) * OFstatic_cast(unsigned long, Rows) * NumberOfFrames; + if ((InterData->getInputCount() != count) && ((InterData->getInputCount() >> 1) != ((count + 1) >> 1))) + { + DCMIMGLE_WARN("computed (" << count << ") and stored (" << InterData->getInputCount() << ") pixel count differ"); + } + } + return (ImageStatus == EIS_Normal); +} + + +void DiMonoImage::deleteOutputData() +{ + delete OutputData; + OutputData = NULL; +} + + +unsigned long DiMonoImage::getOutputDataSize(const int bits) const +{ + unsigned long result = 0; + if ((ImageStatus == EIS_Normal) && (((bits > 0) && (bits <= MAX_BITS)) || (bits == MI_PastelColor))) + { + int samples = 1; + int bytesPerPixel = 1; + if (bits == MI_PastelColor) // use true color pastel mode + samples = 3; + else if (bits > 16) + bytesPerPixel = 4; + else if (bits > 8) + bytesPerPixel = 2; + /* compute number of bytes required to store a rendered frame */ + result = OFstatic_cast(unsigned long, Columns) * OFstatic_cast(unsigned long, Rows) * samples * bytesPerPixel; + } + return result; +} + + +const void *DiMonoImage::getOutputPlane(const int) const +{ + if (OutputData != NULL) + return OutputData->getData(); // monochrome images don't have multiple planes + return NULL; +} + + +void DiMonoImage::deleteOverlayData() +{ + delete OFstatic_cast(char *, OverlayData); // type cast necessary to avoid compiler warnings using gcc 2.95 + OverlayData = NULL; +} + + +/*********************************************************************/ + + +int DiMonoImage::getMinMaxValues(double &min, + double &max, + const int mode) const +{ + if (InterData != NULL) + { + if (mode) + { + min = InterData->getAbsMinimum(); + max = InterData->getAbsMaximum(); + return 1; + } + return InterData->getMinMaxValues(min, max); + } + return 0; +} + + +int DiMonoImage::setDisplayFunction(DiDisplayFunction *display) +{ + DisplayFunction = display; + return (DisplayFunction != NULL) && (DisplayFunction->isValid()); +} + + +int DiMonoImage::setNoDisplayFunction() +{ + if (DisplayFunction != NULL) + { + DisplayFunction = NULL; + return 1; + } + return 2; +} + + +int DiMonoImage::convertPValueToDDL(const Uint16 pvalue, + Uint16 &ddl, + const int bits) +{ + const unsigned long maxvalue = DicomImageClass::maxval(bits); + if ((DisplayFunction != NULL) && (DisplayFunction->isValid()) && (DisplayFunction->getMaxDDLValue() == maxvalue)) + { + const DiDisplayLUT *dlut = DisplayFunction->getLookupTable(WIDTH_OF_PVALUES); + if ((dlut != NULL) && (dlut->isValid())) + { + ddl = dlut->getValue(pvalue); // perform display transformation + return 1; + } + } + if ((bits >= 1) && (bits <= WIDTH_OF_PVALUES)) // no display function: perform linear scaling + { + ddl = OFstatic_cast(Uint16, OFstatic_cast(double, maxvalue) * OFstatic_cast(double, pvalue) / + OFstatic_cast(double, DicomImageClass::maxval(WIDTH_OF_PVALUES))); + return 2; + } + return 0; +} + + +int DiMonoImage::setNoVoiTransformation() +{ + int old = 2; + if (VoiLutData != NULL) + { + if (VoiLutData->isValid()) + old = 1; + VoiLutData->removeReference(); + } + VoiLutData = NULL; + VoiExplanation = ""; + if (ValidWindow) + old = 1; + ValidWindow = 0; + return old; +} + + +int DiMonoImage::setMinMaxWindow(const int idx) +{ + if (InterData != NULL) + { + double center; + double width; + if (InterData->getMinMaxWindow(idx != 0, center, width)) + return setWindow(center, width, "Min-Max Window"); + } + return 0; +} + + +int DiMonoImage::setRoiWindow(const unsigned long left_pos, + const unsigned long top_pos, + const unsigned long width, + const unsigned long height, + const unsigned long frame) +{ + if ((InterData != NULL) && (frame < NumberOfFrames)) + { + double voiCenter; + double voiWidth; + if (InterData->getRoiWindow(left_pos, top_pos, width, height, Columns, Rows, frame, voiCenter, voiWidth)) + return setWindow(voiCenter, voiWidth, "ROI Window"); + } + return 0; +} + + +int DiMonoImage::setHistogramWindow(const double thresh) +{ + if (InterData != NULL) + { + double center; + double width; + if (InterData->getHistogramWindow(thresh, center, width)) + return setWindow(center, width, "Histogram Window"); + } + return 0; +} + + +int DiMonoImage::setWindow(const unsigned long pos) +{ + if (!(Document->getFlags() & CIF_UsePresentationState)) + { + double center; + double width; + WindowCount = Document->getValue(DCM_WindowCenter, center, pos); + unsigned long count = Document->getValue(DCM_WindowWidth, width, pos); + if (count < WindowCount) + WindowCount = count; + if (pos < WindowCount) + { + /* save return value to be used later (setWindow clears the explanation string!) */ + const int result = setWindow(center, width); + /* get the stored explanation string */ + Document->getValue(DCM_WindowCenterWidthExplanation, VoiExplanation, pos); + return result; + } + } + return 0; +} + + +int DiMonoImage::setWindow(const double center, + const double width, + const char *explanation) +{ + if (VoiLutData != NULL) + VoiLutData->removeReference(); + VoiLutData = NULL; + if (explanation != NULL) + VoiExplanation = explanation; + else + VoiExplanation = ""; + if (width < 1) // not valid, according to supplement 33 + return ValidWindow = 0; + else if (!ValidWindow || (center != WindowCenter) || (width != WindowWidth)) + { + WindowCenter = center; + WindowWidth = width; + return ValidWindow = 1; + } + return 2; // window is unchanged (and valid) +} + + +int DiMonoImage::getWindow(double ¢er, double &width) +{ + if (ValidWindow) + { + center = WindowCenter; + width = WindowWidth; + return 1; + } + return 0; +} + + +EF_VoiLutFunction DiMonoImage::getVoiLutFunction() const +{ + return VoiLutFunction; +} + + +int DiMonoImage::setVoiLutFunction(const EF_VoiLutFunction function) +{ + if (function != VoiLutFunction) + { + VoiLutFunction = function; + return 1; + } + return 2; +} + + +int DiMonoImage::setVoiLut(const DcmUnsignedShort &data, + const DcmUnsignedShort &descriptor, + const DcmLongString *explanation, + const EL_BitsPerTableEntry descripMode) +{ + if (VoiLutData != NULL) + VoiLutData->removeReference(); + VoiLutData = new DiLookupTable(data, descriptor, explanation, descripMode); + if (VoiLutData != NULL) + { + VoiExplanation = OFSTRING_GUARD(VoiLutData->getExplanation()); + return VoiLutData->isValid(); + } + VoiExplanation = ""; + return 0; +} + + +int DiMonoImage::setVoiLut(const unsigned long pos, + const EL_BitsPerTableEntry descripMode) +{ + if (!(Document->getFlags() & CIF_UsePresentationState)) + { + if (VoiLutData != NULL) + VoiLutData->removeReference(); + VoiLutData = new DiLookupTable(Document, DCM_VOILUTSequence, DCM_LUTDescriptor, DCM_LUTData, + DCM_LUTExplanation, descripMode, pos, &VoiLutCount); + if (VoiLutData != NULL) + { + VoiExplanation = OFSTRING_GUARD(VoiLutData->getExplanation()); + return VoiLutData->isValid(); + } + VoiExplanation = ""; + } + return 0; +} + + +const char *DiMonoImage::getVoiWindowExplanation(const unsigned long pos, + OFString &explanation) const +{ + const char *result = NULL; + /* get the stored explanation string */ + if (Document->getValue(DCM_WindowCenterWidthExplanation, explanation, pos) > 0) + result = explanation.c_str(); + return result; +} + + +const char *DiMonoImage::getVoiLutExplanation(const unsigned long pos, + OFString &explanation) const +{ + const char *result = NULL; + /* get the given sequence item ... */ + DcmSequenceOfItems *seq = NULL; + if ((pos < Document->getSequence(DCM_VOILUTSequence, seq)) && (seq != NULL)) + { + /* ... and then the stored explanation string */ + if (Document->getValue(DCM_LUTExplanation, explanation, 0 /*vm pos*/, seq->getItem(pos)) > 0) + result = explanation.c_str(); + } + return result; +} + + +int DiMonoImage::setHardcopyParameters(const unsigned int min, + const unsigned int max, + const unsigned int reflect, + const unsigned int illumin) +{ + int result = 0; + if (min < max) + { + result = 2; + if (min != MinDensity) + { + MinDensity = min; + result = 1; + } + if (max != MaxDensity) + { + MaxDensity = max; + result = 1; + } + if (reflect != Reflection) + { + Reflection = reflect; + result = 1; + } + if (illumin != Illumination) + { + Illumination = illumin; + result = 1; + } + if ((result == 1) && (PresLutShape == ESP_LinOD) && (PresLutData != NULL)) + { + PresLutData->removeReference(); // look-up table no longer valid + PresLutData = NULL; + } + } + return result; +} + + +ES_PresentationLut DiMonoImage::getPresentationLutShape() const +{ + return (PresLutData != NULL) ? ESP_Default : PresLutShape; +} + + +int DiMonoImage::setPresentationLutShape(const ES_PresentationLut shape) +{ + if (PresLutData != NULL) + PresLutData->removeReference(); + PresLutData = NULL; + if (shape != PresLutShape) + { + PresLutShape = shape; + return 1; + } + return 2; +} + + +int DiMonoImage::setPresentationLut(const DcmUnsignedShort &data, + const DcmUnsignedShort &descriptor, + const DcmLongString *explanation, + const EL_BitsPerTableEntry descripMode) +{ + if (PresLutData != NULL) + PresLutData->removeReference(); + PresLutData = new DiLookupTable(data, descriptor, explanation, descripMode, 0); + if (PresLutData != NULL) + { + PresLutShape = ESP_Default; + return PresLutData->isValid(); + } + return 0; +} + + +int DiMonoImage::setInversePresentationLut(const DcmUnsignedShort &data, + const DcmUnsignedShort &descriptor, + const EL_BitsPerTableEntry descripMode) +{ + int status = 0; + if (PresLutData != NULL) + PresLutData->removeReference(); + PresLutData = NULL; + DiLookupTable *lut = new DiLookupTable(data, descriptor, NULL, descripMode, 0); + if ((lut != NULL) && (lut->isValid())) + { + PresLutData = lut->createInverseLUT(); + if (PresLutData != NULL) + status = PresLutData->isValid(); + } + delete lut; + return status; +} + + +int DiMonoImage::addOverlay(const unsigned int group, + const signed int left_pos, + const signed int top_pos, + const unsigned int columns, + const unsigned int rows, + const DcmOverlayData &data, + const DcmLongString &label, + const DcmLongString &description, + const EM_Overlay mode) +{ + if (Overlays[1] == NULL) + Overlays[1] = new DiOverlay(); + if (Overlays[1] != NULL) + return Overlays[1]->addPlane(group, left_pos, top_pos, columns, rows, data, label, description, mode); + return 0; +} + + +int DiMonoImage::removeAllOverlays() +{ + if (Overlays[1] != NULL) + { + delete Overlays[1]; + Overlays[1] = NULL; + return 1; + } + return 2; +} + + +int DiMonoImage::flip(const int horz, + const int vert) +{ + switch (InterData->getRepresentation()) + { + case EPR_Uint8: + { + DiFlipTemplate dummy(InterData, Columns, Rows, NumberOfFrames, horz, vert); + } + break; + case EPR_Sint8: + { + DiFlipTemplate dummy(InterData, Columns, Rows, NumberOfFrames, horz, vert); + } + break; + case EPR_Uint16: + { + DiFlipTemplate dummy(InterData, Columns, Rows, NumberOfFrames, horz, vert); + } + break; + case EPR_Sint16: + { + DiFlipTemplate dummy(InterData, Columns, Rows, NumberOfFrames, horz, vert); + } + break; + case EPR_Uint32: + { + DiFlipTemplate dummy(InterData, Columns, Rows, NumberOfFrames, horz, vert); + } + break; + case EPR_Sint32: + { + DiFlipTemplate dummy(InterData, Columns, Rows, NumberOfFrames, horz, vert); + } + break; + } + for (int i = 0; i < 2; ++i) + { + if ((Overlays[i] != NULL) && (Overlays[i]->getCount() > 0)) + { + DiOverlay *old = Overlays[i]; + Overlays[i] = new DiOverlay(old, horz, vert, Columns, Rows); + old->removeReference(); + } + } + return 1; +} + + +int DiMonoImage::rotate(const int degree) +{ + const Uint16 old_cols = Columns; // save old values + const Uint16 old_rows = Rows; + DiImage::rotate(degree); // swap width and height if necessary + if ((Columns > 1) && (Rows > 1)) // re-interpret pixel data for cols = 1 or rows = 1 + { + switch (InterData->getRepresentation()) + { + case EPR_Uint8: + { + DiRotateTemplate dummy(InterData, old_cols, old_rows, Columns, Rows, NumberOfFrames, degree); + } + break; + case EPR_Sint8: + { + DiRotateTemplate dummy(InterData, old_cols, old_rows, Columns, Rows, NumberOfFrames, degree); + } + break; + case EPR_Uint16: + { + DiRotateTemplate dummy(InterData, old_cols, old_rows, Columns, Rows, NumberOfFrames, degree); + } + break; + case EPR_Sint16: + { + DiRotateTemplate dummy(InterData, old_cols, old_rows, Columns, Rows, NumberOfFrames, degree); + } + break; + case EPR_Uint32: + { + DiRotateTemplate dummy(InterData, old_cols, old_rows, Columns, Rows, NumberOfFrames, degree); + } + break; + case EPR_Sint32: + { + DiRotateTemplate dummy(InterData, old_cols, old_rows, Columns, Rows, NumberOfFrames, degree); + } + break; + } + } + for (int i = 0; i < 2; ++i) + { + if ((Overlays[i] != NULL) && (Overlays[i]->getCount() > 0)) + { + DiOverlay *old = Overlays[i]; + Overlays[i] = new DiOverlay(old, degree, Columns, Rows); + old->removeReference(); + } + } + return 1; +} + + +/*********************************************************************/ + + +/* + * create output data of 'frame' with depth of 'bits' and min/max values depending on 'negative' (support mono1/2) + */ + +const void *DiMonoImage::getData(void *buffer, + const unsigned long size, + const unsigned long frame, + int bits, + const int /*planar*/, /* not yet supported, needed for pastel color images !! */ + const int negative) +{ + if ((InterData != NULL) && (ImageStatus == EIS_Normal) && (frame < NumberOfFrames) && + (((bits > 0) && (bits <= MAX_BITS)) || (bits == MI_PastelColor))) + { + if ((buffer == NULL) || (size >= getOutputDataSize(bits))) + { + deleteOutputData(); // delete old image data + if (!ValidWindow) + WindowWidth = -1; // negative width means no window, saves additional parameter ;) + Uint32 low; + Uint32 high; + if ((PresLutData == NULL) && + ((PresLutShape == ESP_Inverse) || (negative && (PresLutShape == ESP_Default)))) + { + low = DicomImageClass::maxval(bits); // inverse/negative: white to black + high = 0; + } else { + low = 0; // normal/positive: black to white + high = DicomImageClass::maxval(bits); + } + if ((PresLutData == NULL) && (PresLutShape == ESP_LinOD)) + { + if (!createLinODPresentationLut(4096, 16)) // create presentation LUT converting linOD data (on demand) + { + DCMIMGLE_WARN("could not create presentation LUT for LinOD conversion ... ignoring presentation LUT shape LinOD"); + } + } + if (Polarity == EPP_Reverse) // swap high and low value + { + Uint32 temp = low; + low = high; + high = temp; + } + DiDisplayFunction *disp = DisplayFunction; + if ((disp != NULL) && (disp->isValid()) && (disp->getMaxDDLValue() != DicomImageClass::maxval(bits))) + { + DCMIMGLE_WARN("selected display function doesn't fit to requested output depth (" << bits + << ") ... ignoring display transformation"); + disp = NULL; + } + const int samples = (bits == MI_PastelColor) ? 3 : 1; + switch (InterData->getRepresentation()) + { + case EPR_Uint8: + getDataUint8(buffer, disp, samples, frame, bits, low, high); + break; + case EPR_Sint8: + getDataSint8(buffer, disp, samples, frame, bits, low, high); + break; + case EPR_Uint16: + getDataUint16(buffer, disp, samples, frame, bits, low, high); + break; + case EPR_Sint16: + getDataSint16(buffer, disp, samples, frame, bits, low, high); + break; + case EPR_Uint32: + getDataUint32(buffer, disp, samples, frame, bits, low, high); + break; + case EPR_Sint32: + getDataSint32(buffer, disp, samples, frame, bits, low, high); + break; + } + if (OutputData == NULL) + { + ImageStatus = EIS_MemoryFailure; + DCMIMGLE_ERROR("can't allocate memory for output-representation"); + } + else + return OutputData->getData(); // points to beginning of output data + } else { + DCMIMGLE_ERROR("given output buffer is too small (only " << size << " bytes)"); + } + } + return NULL; +} + + +/* + * create 1/8/16-bit (bi-level) bitmap with overlay 'plane' data + */ + +const void *DiMonoImage::getOverlayData(const unsigned long frame, + const unsigned int plane, + unsigned int &left_pos, + unsigned int &top_pos, + unsigned int &width, + unsigned int &height, + EM_Overlay &mode, + const unsigned int idx, + const int bits, + const Uint16 fore, + const Uint16 back) +{ + if ((ImageStatus == EIS_Normal) && (bits > 0) && (bits <= 16) && (fore != back)) + { + int start = 1; // default: additional overlay planes hide dataset planes + int end = 0; + if (idx < 2) // specified index of overlay group + start = end = idx; + for (int i = start; i >= end; --i) // start searching with additional overlay planes + { + if ((Overlays[i] != NULL) && (Overlays[i]->hasPlane(plane))) + { + deleteOverlayData(); + OverlayData = Overlays[i]->getPlaneData(frame, plane, left_pos, top_pos, width, height, + mode, Columns, Rows, bits, fore, back); + return OFstatic_cast(const void *, OverlayData); + } + } + } + return NULL; +} + + +/* + * create 1/8/16-bit (bi-level) bitmap with overlay 'plane' data + */ + +const void *DiMonoImage::getFullOverlayData(const unsigned long frame, + const unsigned int plane, + unsigned int &width, + unsigned int &height, + const unsigned int idx, + const int bits, + const Uint16 fore, + const Uint16 back) +{ + if ((ImageStatus == EIS_Normal) && (bits > 0) && (bits <= 16) && (fore != back)) + { + if ((idx < 2) && (Overlays[idx] != NULL) && (Overlays[idx]->hasPlane(plane))) + { + deleteOverlayData(); + OverlayData = Overlays[idx]->getFullPlaneData(frame, plane, width, height, bits, fore, back); + return OFstatic_cast(const void *, OverlayData); + } + } + return NULL; +} + + +/* + * create 1-bit (bi-level) bitmap with overlay 'plane' data + * as required for the (6xxx,3000) OverlayData format + */ + +unsigned long DiMonoImage::create6xxx3000OverlayData(Uint8 *&buffer, + const unsigned int plane, + unsigned int &width, + unsigned int &height, + unsigned long &frames, + const unsigned int idx) +{ + if (ImageStatus == EIS_Normal) + { + if ((idx < 2) && (Overlays[idx] != NULL) && (Overlays[idx]->hasPlane(plane))) + return Overlays[idx]->create6xxx3000PlaneData(buffer, plane, width, height, frames); + } + return 0; +} + + +/* + * create 8-bit palette/monochrome or 24/32-bit true color device independent bitmap (DIB) as needed by MS-Windows + */ + +unsigned long DiMonoImage::createDIB(void *&data, + const unsigned long size, + const unsigned long frame, + const int bits, + const int upsideDown, + const int padding) +{ + unsigned long bytes = 0; + if (size == 0) + data = NULL; + if ((bits == 8) || (bits == 24) || (bits == 32)) + { + getOutputData(frame, 8); // create output data with 8 bit depth + if ((OutputData != NULL) && (OutputData->getData() != NULL)) + { + const signed long nextRow = (upsideDown) ? -2 * OFstatic_cast(signed long, Columns) : 0; + register const Uint8 *p = OFstatic_cast(const Uint8 *, OutputData->getData()) + ((upsideDown) ? + OFstatic_cast(unsigned long, Rows - 1) * OFstatic_cast(unsigned long, Columns) : 0); + if (bits == 8) // -- for idx color model (byte) + { + // each line has to start at 32-bit-address, if 'padding' is true + const int gap = (padding) ? (4 - (Columns & 0x3)) & 0x3 : 0; + const unsigned long count = OFstatic_cast(unsigned long, Columns + gap) * OFstatic_cast(unsigned long, Rows); + if ((gap > 0) || (nextRow != 0) || (data != NULL)) + { + if ((data == NULL) || (size >= count)) + { + if (data == NULL) + data = new Uint8[count]; // allocated memory buffer + if (data != NULL) + { + register Uint8 *q = OFstatic_cast(Uint8 *, data); + register Uint16 x; + register Uint16 y; + for (y = Rows; y != 0; --y) + { + for (x = Columns; x != 0; --x) + *(q++) = *(p++); // store gray value + p += nextRow; // jump (backwards) to next row + q += gap; // skip gap at the end of each line (32-bit boundary) + } + bytes = count; + } + } + } else { // data already aligned and correctly oriented + data = OutputData->getDataPtr(); + OutputData->removeDataReference(); // remove reference to internal memory + bytes = count; + } + } + else if (bits == 24) // -- for direct color model (24 bits/pixel) + { + const unsigned long col3 = OFstatic_cast(unsigned long, Columns) * 3; + // each line has to start at 32-bit-address, if 'padding' is true + const int gap = (padding) ? OFstatic_cast(int, (4 - (col3 & 0x3)) & 0x3) : 0; + const unsigned long count = (col3 + gap) * OFstatic_cast(unsigned long, Rows); + if ((data == NULL) || (size >= count)) + { + if (data == NULL) + data = new Uint8[count]; // allocated memory buffer + if (data != NULL) + { + register Uint8 *q = OFstatic_cast(Uint8 *, data); + register Uint8 value; + register Uint16 x; + register Uint16 y; + register int j; + for (y = Rows; y != 0; --y) + { + for (x = Columns; x != 0; --x) + { + value = *(p++); // store gray value + for (j = 3; j != 0; --j) + *(q++) = value; // copy to the three RGB-planes + } + p += nextRow; // jump (backwards) to next row + q += gap; // skip gap at the end of each line (32-bit boundary) + } + bytes = count; + } + } + } + else if (bits == 32) // -- for direct color model (32 bits/pixel) + { + const unsigned long count = OFstatic_cast(unsigned long, Columns) * OFstatic_cast(unsigned long, Rows); + if ((data == NULL) || (size >= count * 4)) + { + if (data == NULL) + data = new Uint32[count]; // allocated memory buffer + if (data != NULL) + { + register Uint32 *q = OFstatic_cast(Uint32 *, data); + register Uint32 value; + register Uint16 x; + register Uint16 y; + for (y = Rows; y != 0; --y) + { + for (x = Columns; x != 0; --x) + { + value = *(p++); // store gray value + *(q++) = (value << 16) | + (value << 8) | + value; // copy to the three RGB-planes + } + p += nextRow; // jump (backwards) to next row + } + bytes = count * 4; + } + } + } + } + deleteOutputData(); // output data is no longer needed + } + return bytes; +} + + +/* + * create 8-bit palette/monochrome or 32-bit true color bitmap as needed for Java/AWT + */ + +unsigned long DiMonoImage::createAWTBitmap(void *&data, + const unsigned long frame, + const int bits) +{ + data = NULL; + unsigned long bytes = 0; + if (bits == 8) // for idx color model (byte) + { + getOutputData(frame, 8); // create output data with 8 bit depth + if ((OutputData != NULL) && (OutputData->getData() != NULL)) + { + bytes = OFstatic_cast(unsigned long, Columns) * OFstatic_cast(unsigned long, Rows); + data = OutputData->getDataPtr(); + OutputData = NULL; // remove reference to internal memory + } + } + else if (bits == 32) // for direct color model (long int) + { + getOutputData(frame, 8); // create output data with 8 bit depth + if ((OutputData != NULL) && (OutputData->getData() != NULL)) + { + const unsigned long count = OFstatic_cast(unsigned long, Columns) * OFstatic_cast(unsigned long, Rows); + data = new Uint32[count]; + if (data != NULL) + { + register const Uint8 *p = OFstatic_cast(const Uint8 *, OutputData->getData()); + register Uint32 *q = OFstatic_cast(Uint32 *, data); + register Uint32 value; + register unsigned long i; + for (i = count; i != 0; --i) + { + value = *(p++); // store gray value + *(q++) = (value << 24) | + (value << 16) | + (value << 8); // copy to the three RGB-planes + } + bytes = count * 4; + } + } + deleteOutputData(); // output data is no longer needed + } + return bytes; +} + + +/* + * create packed bitmap (e.g. 12 bit for DICOM printers), currently restricted to 12/16 bit + */ + +void *DiMonoImage::createPackedBitmap(const void *buffer, + const unsigned long size, + const unsigned long count, + const int alloc, // number of bits allocated in buffer + const int stored) // number of bits stored in buffer +{ + if ((buffer != NULL) && (size > 0) && (alloc > 0) && (stored > 0) && (stored < alloc)) + { + if ((alloc == 16) && (stored == 12)) + { + /* need to split 'size' in order to avoid integer overflow for large pixel data */ + const unsigned long size_1 = size / alloc; + const unsigned long size_2 = size % alloc; +// # old code: if ((size * 8 + alloc - 1) / alloc == count) + if (8 * size_1 + (8 * size_2 + alloc - 1) / alloc == count) + { + Uint16 *data = NULL; + data = new Uint16[((count + 1) * stored - 1) / 16]; // create new memory buffer + if (data != NULL) + { + register const Uint16 *p = OFstatic_cast(const Uint16 *, buffer); + register Uint16 *q = data; + register unsigned long i; + register Uint16 value1; + register Uint16 value2; + for (i = 0; i < count - 3; i += 4) // make 3 items out of 4 + { + value1 = *(p++); + value2 = *(p++); + *(q++) = OFstatic_cast(Uint16, (value1 & 0x0fff) | (value2 << 12)); + value1 = *(p++); + *(q++) = OFstatic_cast(Uint16, ((value2 >> 4) & 0x00ff) | (value1 << 8)); + value2 = *(p++); + *(q++) = OFstatic_cast(Uint16, ((value1 >> 8) & 0x000f) | (value2 << 4)); + } + switch (count - i) // add remaining pixels + { + case 1: // add 1 pixel + *(q++) = OFstatic_cast(Uint16, *(p++) & 0x0fff); + break; + case 2: // add 2 pixels + value1 = *(p++); + value2 = *(p++); + *(q++) = OFstatic_cast(Uint16, (value1 & 0x0fff) | (value2 << 12)); + *(q++) = OFstatic_cast(Uint16, (value2 >> 4) & 0x00ff); + break; + case 3: // add 3 pixels + value1 = *(p++); + value2 = *(p++); + *(q++) = OFstatic_cast(Uint16, (value1 & 0x0fff) | (value2 << 12)); + value1 = *(p++); + *(q++) = OFstatic_cast(Uint16, ((value2 >> 4) & 0x00ff) | (value1 << 8)); + *(q++) = OFstatic_cast(Uint16, (value1 >> 8) & 0x000f); + break; + default: // add no pixel + ; + } + return OFstatic_cast(void *, data); + } + } + } + } + return NULL; +} + + +DiImage *DiMonoImage::createOutputImage(const unsigned long frame, + const int bits) +{ + getOutputData(frame, bits); + if ((OutputData != NULL) && (OutputData->getData() != NULL)) + { + + DiImage *image = new DiMono2Image(this, OutputData, frame, bits, OutputData->getItemSize() * 8); + if (image != NULL) + OutputData->removeDataReference(); // output data is now handled by new mono image + return image; + } + return NULL; +} + + +int DiMonoImage::createLinODPresentationLut(const unsigned long count, const int bits) +{ + if ((PresLutData == NULL) && (MinDensity < MaxDensity) && + (count > 1) && (count <= MAX_TABLE_ENTRY_COUNT) && + (bits > 0) && (bits <= MAX_TABLE_ENTRY_SIZE)) + { + Uint16 *data = new Uint16[count]; + if (data != NULL) + { + const double l0 = OFstatic_cast(double, Illumination); + const double la = OFstatic_cast(double, Reflection); + const double dmin = OFstatic_cast(double, MinDensity) / 100; + const double dmax = OFstatic_cast(double, MaxDensity) / 100; + const double lmin = la + l0 * pow(OFstatic_cast(double, 10), -dmax); + const double lmax = la + l0 * pow(OFstatic_cast(double, 10), -dmin); + const double jmin = DiGSDFunction::getJNDIndex(lmin); + const double jmax = DiGSDFunction::getJNDIndex(lmax); + const double factor = OFstatic_cast(double, DicomImageClass::maxval(bits)) / (jmax - jmin); + const double density = (dmax - dmin) / OFstatic_cast(double, count - 1); + Uint16 *p = data; + for (unsigned long i = 0; i < count; ++i) + { + *(p++) = OFstatic_cast(Uint16, (DiGSDFunction::getJNDIndex(la + l0 * + pow(OFstatic_cast(double, 10), -(dmin + OFstatic_cast(double, i) * density))) - jmin) * factor); + } + PresLutData = new DiLookupTable(data, count, bits); + return (PresLutData != NULL) && (PresLutData->isValid()); + } + } + return 0; +} + + +/*********************************************************************/ + +void DiMonoImage::updateImagePixelModuleAttributes(DcmItem &dataset) +{ + DiImage::updateImagePixelModuleAttributes(dataset); + /* replace any modality transformation in the dataset */ + if (dataset.tagExists(DCM_RescaleIntercept) || + dataset.tagExists(DCM_RescaleSlope) || + dataset.tagExists(DCM_ModalityLUTSequence)) + { + dataset.putAndInsertString(DCM_RescaleIntercept, "0"); + dataset.putAndInsertString(DCM_RescaleSlope, "1"); + delete dataset.remove(DCM_ModalityLUTSequence); + } + /* remove embedded overlay planes */ + for (Uint16 grp = 0x6000; grp < 0x601f; grp += 2) + { + if (!dataset.tagExists(DcmTagKey(grp, DCM_OverlayData.getElement()))) + { + delete dataset.remove(DcmTagKey(grp, 0x0000)); // group length + delete dataset.remove(DcmTagKey(grp, DCM_OverlayRows.getElement())); + delete dataset.remove(DcmTagKey(grp, DCM_OverlayColumns.getElement())); + delete dataset.remove(DcmTagKey(grp, DCM_RETIRED_OverlayPlanes.getElement())); + delete dataset.remove(DcmTagKey(grp, DCM_NumberOfFramesInOverlay.getElement())); + delete dataset.remove(DcmTagKey(grp, DCM_OverlayDescription.getElement())); + delete dataset.remove(DcmTagKey(grp, DCM_OverlayType.getElement())); + delete dataset.remove(DcmTagKey(grp, DCM_OverlaySubtype.getElement())); + delete dataset.remove(DcmTagKey(grp, DCM_OverlayOrigin.getElement())); + delete dataset.remove(DcmTagKey(grp, DCM_ImageFrameOrigin.getElement())); + delete dataset.remove(DcmTagKey(grp, DCM_RETIRED_OverlayPlaneOrigin.getElement())); + delete dataset.remove(DcmTagKey(grp, DCM_OverlayBitsAllocated.getElement())); + delete dataset.remove(DcmTagKey(grp, DCM_OverlayBitPosition.getElement())); + delete dataset.remove(DcmTagKey(grp, DCM_OverlayLabel.getElement())); + } + } +} + + +// --- write current image to DICOM dataset + +int DiMonoImage::writeImageToDataset(DcmItem &dataset, + const int mode, + const int /*planar*/) +{ + int result = 0; + if (InterData != NULL) + { + const void *pixel = InterData->getData(); + const unsigned long count = InterData->getCount(); + const EP_Representation repres = InterData->getRepresentation(); + if ((BitsPerSample > 0) && (pixel != NULL) && (count > 0)) + { + char numBuf[20]; + unsigned int bits = BitsPerSample; + /* only 'used' pixel data */ + if (!mode) + { + double minValue, maxValue; + InterData->getMinMaxValues(minValue, maxValue); + if (minValue < maxValue) + bits = DicomImageClass::rangeToBits(minValue, maxValue); + else + bits = 1; + } + /* check determined bits stored value */ + const unsigned int repBits = DicomImageClass::getRepresentationBits(repres); + if (bits > repBits) + bits = repBits; + /* set color model */ + if (getInternalColorModel() == EPI_Monochrome1) + dataset.putAndInsertString(DCM_PhotometricInterpretation, "MONOCHROME1"); + else + dataset.putAndInsertString(DCM_PhotometricInterpretation, "MONOCHROME2"); + /* set image resolution */ + dataset.putAndInsertUint16(DCM_Columns, Columns); + dataset.putAndInsertUint16(DCM_Rows, Rows); +#if SIZEOF_LONG == 8 + sprintf(numBuf, "%d", NumberOfFrames); +#else + sprintf(numBuf, "%ld", NumberOfFrames); +#endif + dataset.putAndInsertString(DCM_NumberOfFrames, numBuf); + dataset.putAndInsertUint16(DCM_SamplesPerPixel, 1); + /* set pixel encoding and data */ + switch (repres) + { + case EPR_Uint8: + dataset.putAndInsertUint16(DCM_BitsAllocated, 8); + dataset.putAndInsertUint16(DCM_PixelRepresentation, 0); + dataset.putAndInsertUint8Array(DCM_PixelData, OFstatic_cast(const Uint8 *, pixel), count); + break; + case EPR_Sint8: + dataset.putAndInsertUint16(DCM_BitsAllocated, 8); + dataset.putAndInsertUint16(DCM_PixelRepresentation, 1); + dataset.putAndInsertUint8Array(DCM_PixelData, OFstatic_cast(const Uint8 *, pixel), count); + break; + case EPR_Uint16: + dataset.putAndInsertUint16(DCM_BitsAllocated, 16); + dataset.putAndInsertUint16(DCM_PixelRepresentation, 0); + dataset.putAndInsertUint16Array(DCM_PixelData, OFstatic_cast(const Uint16 *, pixel), count); + break; + case EPR_Sint16: + dataset.putAndInsertUint16(DCM_BitsAllocated, 16); + dataset.putAndInsertUint16(DCM_PixelRepresentation, 1); + dataset.putAndInsertUint16Array(DCM_PixelData, OFstatic_cast(const Uint16 *, pixel), count); + break; + case EPR_Uint32: + dataset.putAndInsertUint16(DCM_BitsAllocated, 32); + dataset.putAndInsertUint16(DCM_PixelRepresentation, 0); + dataset.putAndInsertUint16Array(DCM_PixelData, OFstatic_cast(const Uint16 *, pixel), count * 2 /*double-words*/); + break; + case EPR_Sint32: + dataset.putAndInsertUint16(DCM_BitsAllocated, 32); + dataset.putAndInsertUint16(DCM_PixelRepresentation, 1); + dataset.putAndInsertUint16Array(DCM_PixelData, OFstatic_cast(const Uint16 *, pixel), count * 2 /*double-words*/); + break; + } + dataset.putAndInsertUint16(DCM_BitsStored, bits); + dataset.putAndInsertUint16(DCM_HighBit, bits - 1); + /* update other DICOM attributes */ + updateImagePixelModuleAttributes(dataset); + result = 1; + } + } + return result; +} + + +/* + * write output data of 'frame' with depth of 'bits' to C++-output 'stream' (format is PGM - portable gray map) + */ + +int DiMonoImage::writePPM(STD_NAMESPACE ostream& stream, + const unsigned long frame, + const int bits) +{ + getOutputData(frame, bits); + if (OutputData != NULL) + { + if (bits == MI_PastelColor) + { + stream << "P3" << OFendl; + stream << Columns << " " << Rows << OFendl; + stream << "255" << OFendl; + } else { + stream << "P2" << OFendl; + stream << Columns << " " << Rows << OFendl; + stream << DicomImageClass::maxval(bits) << OFendl; + } + int ok = OutputData->writePPM(stream); + deleteOutputData(); + return ok; + } + return 0; +} + + +/* + * write output data of 'frame' with depth of 'bits' to C-file 'stream' (format is PGM - portable gray map) + */ + +int DiMonoImage::writePPM(FILE *stream, + const unsigned long frame, + const int bits) +{ + if (stream != NULL) + { + getOutputData(frame, bits); + if (OutputData != NULL) + { + if (bits == MI_PastelColor) + fprintf(stream, "P3\n%u %u\n255\n", Columns, Rows); + else + fprintf(stream, "P2\n%u %u\n%lu\n", Columns, Rows, DicomImageClass::maxval(bits)); + int ok = OutputData->writePPM(stream); + deleteOutputData(); + return ok; + } + } + return 0; +} + + +/* + * write output data of 'frame' with depth of 'bits' (max. 8) to C-file 'stream' (format is RAW-PGM - binary PGM) + */ + +int DiMonoImage::writeRawPPM(FILE *stream, + const unsigned long frame, + const int bits) +{ + if ((stream != NULL) && (bits <= MAX_RAWPPM_BITS)) + { + getOutputData(frame, bits); + if ((OutputData != NULL) && (OutputData->getData() != NULL)) + { + if (bits == MI_PastelColor) + fprintf(stream, "P6\n%u %u\n255\n", Columns, Rows); + else + fprintf(stream, "P5\n%u %u\n%lu\n", Columns, Rows, DicomImageClass::maxval(bits)); + fwrite(OutputData->getData(), OFstatic_cast(size_t, OutputData->getCount()), OutputData->getItemSize(), stream); + deleteOutputData(); + return 1; + } + } + return 0; +} + + +/* + * write output data of 'frame' with depth of 'bits' (8, 24 or 32) to C-file 'stream' (format is BMP) + */ + +int DiMonoImage::writeBMP(FILE *stream, + const unsigned long frame, + const int bits) +{ + if ((bits == 0) || (bits == 8) || (bits == 24) || (bits == 32)) + return DiImage::writeBMP(stream, frame, (bits == 0) ? 8 : bits); + return 0; +} diff --git a/dcmimgle/libsrc/dimoimg3.cc b/dcmimgle/libsrc/dimoimg3.cc new file mode 100644 index 00000000..1a8da650 --- /dev/null +++ b/dcmimgle/libsrc/dimoimg3.cc @@ -0,0 +1,84 @@ +/* + * + * Copyright (C) 1996-2010, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimgle + * + * Author: Joerg Riesmeier + * + * Purpose: DicomMonochromeImage (Source, getData 8 bit) + * + */ + + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/dcmimgle/dimoimg.h" +#include "dcmtk/dcmimgle/dimoipxt.h" +#include "dcmtk/dcmimgle/dimoopxt.h" +#include "dcmtk/dcmimgle/diutils.h" + + +void DiMonoImage::getDataUint8(void *buffer, + DiDisplayFunction *disp, + const int samples, + const unsigned long frame, + const int bits, + const Uint32 low, + const Uint32 high) +{ + if (InterData != NULL) + { + if (InterData->isPotentiallySigned()) + { + if (bits <= 8) + OutputData = new DiMonoOutputPixelTemplate(buffer, InterData, Overlays, VoiLutData, PresLutData, + disp, VoiLutFunction, WindowCenter, WindowWidth, low, high, Columns, Rows, frame, NumberOfFrames, samples > 1); + else if (bits <= 16) + OutputData = new DiMonoOutputPixelTemplate(buffer, InterData, Overlays, VoiLutData, PresLutData, + disp, VoiLutFunction, WindowCenter, WindowWidth, low, high, Columns, Rows, frame, NumberOfFrames); + else + OutputData = new DiMonoOutputPixelTemplate(buffer, InterData, Overlays, VoiLutData, PresLutData, + disp, VoiLutFunction, WindowCenter, WindowWidth, low, high, Columns, Rows, frame, NumberOfFrames); + } else { + if (bits <= 8) + OutputData = new DiMonoOutputPixelTemplate(buffer, InterData, Overlays, VoiLutData, PresLutData, + disp, VoiLutFunction, WindowCenter, WindowWidth, low, high, Columns, Rows, frame, NumberOfFrames, samples > 1); + else if (bits <= 16) + OutputData = new DiMonoOutputPixelTemplate(buffer, InterData, Overlays, VoiLutData, PresLutData, + disp, VoiLutFunction, WindowCenter, WindowWidth, low, high, Columns, Rows, frame, NumberOfFrames); + else + OutputData = new DiMonoOutputPixelTemplate(buffer, InterData, Overlays, VoiLutData, PresLutData, + disp, VoiLutFunction, WindowCenter, WindowWidth, low, high, Columns, Rows, frame, NumberOfFrames); + } + } +} + + +void DiMonoImage::getDataSint8(void *buffer, + DiDisplayFunction *disp, + const int samples, + const unsigned long frame, + const int bits, + const Uint32 low, + const Uint32 high) +{ + if (bits <= 8) + OutputData = new DiMonoOutputPixelTemplate(buffer, InterData, Overlays, VoiLutData, PresLutData, + disp, VoiLutFunction, WindowCenter, WindowWidth, low, high, Columns, Rows, frame, NumberOfFrames, samples > 1); + else if (bits <= 16) + OutputData = new DiMonoOutputPixelTemplate(buffer, InterData, Overlays, VoiLutData, PresLutData, + disp, VoiLutFunction, WindowCenter, WindowWidth, low, high, Columns, Rows, frame, NumberOfFrames); + else + OutputData = new DiMonoOutputPixelTemplate(buffer, InterData, Overlays, VoiLutData, PresLutData, + disp, VoiLutFunction, WindowCenter, WindowWidth, low, high, Columns, Rows, frame, NumberOfFrames); +} diff --git a/dcmimgle/libsrc/dimoimg4.cc b/dcmimgle/libsrc/dimoimg4.cc new file mode 100644 index 00000000..ed3b8063 --- /dev/null +++ b/dcmimgle/libsrc/dimoimg4.cc @@ -0,0 +1,84 @@ +/* + * + * Copyright (C) 1996-2010, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimgle + * + * Author: Joerg Riesmeier + * + * Purpose: DicomMonochromeImage (Source, getData 16 bit) + * + */ + + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/dcmimgle/dimoimg.h" +#include "dcmtk/dcmimgle/dimoipxt.h" +#include "dcmtk/dcmimgle/dimoopxt.h" +#include "dcmtk/dcmimgle/diutils.h" + + +void DiMonoImage::getDataUint16(void *buffer, + DiDisplayFunction *disp, + const int samples, + const unsigned long frame, + const int bits, + const Uint32 low, + const Uint32 high) +{ + if (InterData != NULL) + { + if (InterData->isPotentiallySigned()) + { + if (bits <= 8) + OutputData = new DiMonoOutputPixelTemplate(buffer, InterData, Overlays, VoiLutData, PresLutData, + disp, VoiLutFunction, WindowCenter, WindowWidth, low, high, Columns, Rows, frame, NumberOfFrames, samples > 1); + else if (bits <= 16) + OutputData = new DiMonoOutputPixelTemplate(buffer, InterData, Overlays, VoiLutData, PresLutData, + disp, VoiLutFunction, WindowCenter, WindowWidth, low, high, Columns, Rows, frame, NumberOfFrames); + else + OutputData = new DiMonoOutputPixelTemplate(buffer, InterData, Overlays, VoiLutData, PresLutData, + disp, VoiLutFunction, WindowCenter, WindowWidth, low, high, Columns, Rows, frame, NumberOfFrames); + } else { + if (bits <= 8) + OutputData = new DiMonoOutputPixelTemplate(buffer, InterData, Overlays, VoiLutData, PresLutData, + disp, VoiLutFunction, WindowCenter, WindowWidth, low, high, Columns, Rows, frame, NumberOfFrames, samples > 1); + else if (bits <= 16) + OutputData = new DiMonoOutputPixelTemplate(buffer, InterData, Overlays, VoiLutData, PresLutData, + disp, VoiLutFunction, WindowCenter, WindowWidth, low, high, Columns, Rows, frame, NumberOfFrames); + else + OutputData = new DiMonoOutputPixelTemplate(buffer, InterData, Overlays, VoiLutData, PresLutData, + disp, VoiLutFunction, WindowCenter, WindowWidth, low, high, Columns, Rows, frame, NumberOfFrames); + } + } +} + + +void DiMonoImage::getDataSint16(void *buffer, + DiDisplayFunction *disp, + const int samples, + const unsigned long frame, + const int bits, + const Uint32 low, + const Uint32 high) +{ + if (bits <= 8) + OutputData = new DiMonoOutputPixelTemplate(buffer, InterData, Overlays, VoiLutData, PresLutData, + disp, VoiLutFunction, WindowCenter, WindowWidth, low, high, Columns, Rows, frame, NumberOfFrames, samples > 1); + else if (bits <= 16) + OutputData = new DiMonoOutputPixelTemplate(buffer, InterData, Overlays, VoiLutData, PresLutData, + disp, VoiLutFunction, WindowCenter, WindowWidth, low, high, Columns, Rows, frame, NumberOfFrames); + else + OutputData = new DiMonoOutputPixelTemplate(buffer, InterData, Overlays, VoiLutData, PresLutData, + disp, VoiLutFunction, WindowCenter, WindowWidth, low, high, Columns, Rows, frame, NumberOfFrames); +} diff --git a/dcmimgle/libsrc/dimoimg5.cc b/dcmimgle/libsrc/dimoimg5.cc new file mode 100644 index 00000000..7e416ae9 --- /dev/null +++ b/dcmimgle/libsrc/dimoimg5.cc @@ -0,0 +1,84 @@ +/* + * + * Copyright (C) 1996-2010, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimgle + * + * Author: Joerg Riesmeier + * + * Purpose: DicomMonochromeImage (Source, getData 32 bit) + * + */ + + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/dcmimgle/dimoimg.h" +#include "dcmtk/dcmimgle/dimoipxt.h" +#include "dcmtk/dcmimgle/dimoopxt.h" +#include "dcmtk/dcmimgle/diutils.h" + + +void DiMonoImage::getDataUint32(void *buffer, + DiDisplayFunction *disp, + const int samples, + const unsigned long frame, + const int bits, + const Uint32 low, + const Uint32 high) +{ + if (InterData != NULL) + { + if (InterData->isPotentiallySigned()) + { + if (bits <= 8) + OutputData = new DiMonoOutputPixelTemplate(buffer, InterData, Overlays, VoiLutData, PresLutData, + disp, VoiLutFunction, WindowCenter, WindowWidth, low, high, Columns, Rows, frame, NumberOfFrames, samples > 1); + else if (bits <= 16) + OutputData = new DiMonoOutputPixelTemplate(buffer, InterData, Overlays, VoiLutData, PresLutData, + disp, VoiLutFunction, WindowCenter, WindowWidth, low, high, Columns, Rows, frame, NumberOfFrames); + else + OutputData = new DiMonoOutputPixelTemplate(buffer, InterData, Overlays, VoiLutData, PresLutData, + disp, VoiLutFunction, WindowCenter, WindowWidth, low, high, Columns, Rows, frame, NumberOfFrames); + } else { + if (bits <= 8) + OutputData = new DiMonoOutputPixelTemplate(buffer, InterData, Overlays, VoiLutData, PresLutData, + disp, VoiLutFunction, WindowCenter, WindowWidth, low, high, Columns, Rows, frame, NumberOfFrames, samples > 1); + else if (bits <= 16) + OutputData = new DiMonoOutputPixelTemplate(buffer, InterData, Overlays, VoiLutData, PresLutData, + disp, VoiLutFunction, WindowCenter, WindowWidth, low, high, Columns, Rows, frame, NumberOfFrames); + else + OutputData = new DiMonoOutputPixelTemplate(buffer, InterData, Overlays, VoiLutData, PresLutData, + disp, VoiLutFunction, WindowCenter, WindowWidth, low, high, Columns, Rows, frame, NumberOfFrames); + } + } +} + + +void DiMonoImage::getDataSint32(void *buffer, + DiDisplayFunction *disp, + const int samples, + const unsigned long frame, + const int bits, + const Uint32 low, + const Uint32 high) +{ + if (bits <= 8) + OutputData = new DiMonoOutputPixelTemplate(buffer, InterData, Overlays, VoiLutData, PresLutData, + disp, VoiLutFunction, WindowCenter, WindowWidth, low, high, Columns, Rows, frame, NumberOfFrames, samples > 1); + else if (bits <= 16) + OutputData = new DiMonoOutputPixelTemplate(buffer, InterData, Overlays, VoiLutData, PresLutData, + disp, VoiLutFunction, WindowCenter, WindowWidth, low, high, Columns, Rows, frame, NumberOfFrames); + else + OutputData = new DiMonoOutputPixelTemplate(buffer, InterData, Overlays, VoiLutData, PresLutData, + disp, VoiLutFunction, WindowCenter, WindowWidth, low, high, Columns, Rows, frame, NumberOfFrames); +} diff --git a/dcmimgle/libsrc/dimomod.cc b/dcmimgle/libsrc/dimomod.cc new file mode 100644 index 00000000..ef8f27d0 --- /dev/null +++ b/dcmimgle/libsrc/dimomod.cc @@ -0,0 +1,293 @@ +/* + * + * Copyright (C) 1996-2012, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimgle + * + * Author: Joerg Riesmeier + * + * Purpose: DicomMonochromeModality (Source) + * + */ + + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmdata/dcdeftag.h" +#include "dcmtk/dcmdata/dcuid.h" + +#include "dcmtk/dcmimgle/dimomod.h" +#include "dcmtk/dcmimgle/didocu.h" +#include "dcmtk/dcmimgle/diinpx.h" + + +/*----------------* + * constructors * + *----------------*/ + +DiMonoModality::DiMonoModality(const DiDocument *docu, + DiInputPixel *pixel) + : Representation(EPR_MaxSigned), + MinValue(0), + MaxValue(0), + Bits(0), + UsedBits(0), + AbsMinimum(0), + AbsMaximum(0), + RescaleIntercept(0), + RescaleSlope(0), + LookupTable(0), + Rescaling(0), + TableData(NULL) +{ + if (Init(docu, pixel)) + { + if (docu->getFlags() & CIF_IgnoreModalityTransformation) // ignore modality LUT and rescaling + { + DCMIMGLE_INFO("configuration flag set ... ignoring possible modality transform"); + } + else if (!(docu->getFlags() & CIF_UsePresentationState)) // ignore modality LUT and rescaling + { + const char *sopClassUID = NULL; // check for XA and XRF image (ignore MLUT) + if ((docu->getValue(DCM_SOPClassUID, sopClassUID) == 0) || (sopClassUID == NULL) || + ((strcmp(sopClassUID, UID_XRayAngiographicImageStorage) != 0) && + (strcmp(sopClassUID, UID_XRayRadiofluoroscopicImageStorage) != 0) && + (strcmp(sopClassUID, UID_RETIRED_XRayAngiographicBiPlaneImageStorage) != 0))) + { + EL_BitsPerTableEntry descMode = ELM_UseValue; // first search on main level + if (docu->getFlags() & CIF_IgnoreModalityLutBitDepth) + descMode = ELM_IgnoreValue; + else if (docu->getFlags() & CIF_CheckLutBitDepth) + descMode = ELM_CheckValue; + TableData = new DiLookupTable(docu, DCM_ModalityLUTSequence, DCM_LUTDescriptor, DCM_LUTData, + DCM_LUTExplanation, descMode); + checkTable(); + if (LookupTable) + DCMIMGLE_DEBUG("found modality LUT on main dataset level"); + Rescaling = (docu->getValue(DCM_RescaleIntercept, RescaleIntercept) > 0); + Rescaling &= (docu->getValue(DCM_RescaleSlope, RescaleSlope) > 0); + if (Rescaling) + DCMIMGLE_DEBUG("found 'RescaleSlope/Intercept' on main dataset level"); + else if (!LookupTable) // then check for functional groups sequence + { + DcmSequenceOfItems *seq = NULL; + if (docu->getSequence(DCM_SharedFunctionalGroupsSequence, seq)) + { + DcmItem *item = seq->getItem(0); + if ((item != NULL) && docu->getSequence(DCM_PixelValueTransformationSequence, seq, item)) + { + item = seq->getItem(0); + if (item != NULL) + { + Rescaling = (docu->getValue(DCM_RescaleIntercept, RescaleIntercept, 0, item) > 0); + Rescaling &= (docu->getValue(DCM_RescaleSlope, RescaleSlope, 0, item) > 0); + if (Rescaling) + DCMIMGLE_DEBUG("found 'RescaleSlope/Intercept' in 'SharedFunctionalGroupsSequence'"); + } + } + } + } + checkRescaling(pixel); + } else { + /* David Clunie on comp.protocols.dicom (13.12.2000): + Modality LUTs in XA and XRF objects are totally screwy and + do not follow the normal rules. [...] A Modality LUT may be + included with the image to allow it to be scaled back to its + proportional value to X-Ray beamintensity. In otherwords, + for the objects that use this module (XA and XRF), the + Modality LUT is used BACKWARDS. It is used to convert + stored pixels to X-Ray beamintensityspace, but it is NOT + APPLIED to stored pixels for the purpose of display (or + more specifically prior to application of the VOI LUT Module + attributes to the storedpixeldata). + */ + DCMIMGLE_INFO("processing XA or XRF image ... ignoring possible modality transform"); + } + } + determineRepresentation(docu); + } +} + + +DiMonoModality::DiMonoModality(const DiDocument *docu, + DiInputPixel *pixel, + const double slope, + const double intercept) + : Representation(EPR_MaxSigned), + MinValue(0), + MaxValue(0), + Bits(0), + UsedBits(0), + AbsMinimum(0), + AbsMaximum(0), + RescaleIntercept(intercept), + RescaleSlope(slope), + LookupTable(0), + Rescaling(0), + TableData(NULL) +{ + if (Init(docu, pixel)) + { + Rescaling = 1; + checkRescaling(pixel); + determineRepresentation(docu); + } +} + + +DiMonoModality::DiMonoModality(const DiDocument *docu, + DiInputPixel *pixel, + const DcmUnsignedShort &data, + const DcmUnsignedShort &descriptor, + const DcmLongString *explanation) + : Representation(EPR_MaxSigned), + MinValue(0), + MaxValue(0), + Bits(0), + UsedBits(0), + AbsMinimum(0), + AbsMaximum(0), + RescaleIntercept(0), + RescaleSlope(0), + LookupTable(0), + Rescaling(0), + TableData(NULL) +{ + if (Init(docu, pixel)) + { + EL_BitsPerTableEntry descMode = ELM_UseValue; + if (docu->getFlags() & CIF_IgnoreModalityLutBitDepth) + descMode = ELM_IgnoreValue; + else if (docu->getFlags() & CIF_CheckLutBitDepth) + descMode = ELM_CheckValue; + TableData = new DiLookupTable(data, descriptor, explanation, descMode); + checkTable(); + determineRepresentation(docu); + } +} + + +DiMonoModality::DiMonoModality(const int bits) + : Representation(EPR_MaxSigned), + MinValue(0), + MaxValue(0), + Bits(bits), + UsedBits(0), + AbsMinimum(0), + AbsMaximum(DicomImageClass::maxval(bits)), + RescaleIntercept(0), + RescaleSlope(0), + LookupTable(0), + Rescaling(0), + TableData(NULL) +{ +} + + +/*--------------* + * destructor * + *--------------*/ + +DiMonoModality::~DiMonoModality() +{ + delete TableData; +} + + +/*********************************************************************/ + + +int DiMonoModality::Init(const DiDocument *docu, + DiInputPixel *pixel) +{ + if ((docu != NULL) && (pixel != NULL)) + { + pixel->determineMinMax(); + MinValue = pixel->getMinValue(1 /* selected range of pixels only */); + MaxValue = pixel->getMaxValue(1 /* selected range of pixels only */); + Bits = pixel->getBits(); + AbsMinimum = pixel->getAbsMinimum(); + AbsMaximum = pixel->getAbsMaximum(); + Uint16 us; + if (docu->getValue(DCM_SamplesPerPixel, us) > 0) + { + if (us != 1) + DCMIMGLE_WARN("invalid value for 'SamplesPerPixel' (" << us << ") ... assuming 1"); + } else + DCMIMGLE_WARN("missing value for 'SamplesPerPixel' ... assuming 1"); + return 1; + } + return 0; +} + + +void DiMonoModality::checkTable() +{ + if (TableData != NULL) + { + LookupTable = TableData->isValid(); + if (LookupTable) + { + MinValue = TableData->getMinValue(); + MaxValue = TableData->getMaxValue(); + Bits = TableData->getBits(); + AbsMinimum = 0; + AbsMaximum = DicomImageClass::maxval(Bits); + } + } +} + + +void DiMonoModality::checkRescaling(const DiInputPixel *pixel) +{ + if (Rescaling) + { + if (LookupTable) + { + DCMIMGLE_WARN("redundant values for 'RescaleSlope/Intercept' ... using modality LUT transformation"); + Rescaling = 0; + } else { + if (RescaleSlope == 0) + { + DCMIMGLE_WARN("invalid value for 'RescaleSlope' (" << RescaleSlope << ") ... ignoring modality transformation"); + Rescaling = 0; + } else { + if (RescaleSlope < 0) // negative slope value + { + const double temp = MinValue; + MinValue = MaxValue * RescaleSlope + RescaleIntercept; + MaxValue = temp * RescaleSlope + RescaleIntercept; + AbsMinimum = pixel->getAbsMaximum() * RescaleSlope + RescaleIntercept; + AbsMaximum = pixel->getAbsMinimum() * RescaleSlope + RescaleIntercept; + } else { // positive slope value + MinValue = MinValue * RescaleSlope + RescaleIntercept; + MaxValue = MaxValue * RescaleSlope + RescaleIntercept; + AbsMinimum = pixel->getAbsMinimum() * RescaleSlope + RescaleIntercept; + AbsMaximum = pixel->getAbsMaximum() * RescaleSlope + RescaleIntercept; + } + Bits = DicomImageClass::rangeToBits(AbsMinimum, AbsMaximum); + } + } + } +} + + +void DiMonoModality::determineRepresentation(const DiDocument *docu) +{ + UsedBits = DicomImageClass::rangeToBits(MinValue, MaxValue); + if ((docu != NULL) && (docu->getFlags() & CIF_UseAbsolutePixelRange)) + Representation = DicomImageClass::determineRepresentation(AbsMinimum, AbsMaximum); + else + Representation = DicomImageClass::determineRepresentation(MinValue, MaxValue); + DCMIMGLE_TRACE("internal representation for monochrome images: " + << DicomImageClass::getRepresentationBits(Representation) << " bits (" + << (DicomImageClass::isRepresentationSigned(Representation) ? "signed" : "unsigned") << ")"); +} diff --git a/dcmimgle/libsrc/dimoopx.cc b/dcmimgle/libsrc/dimoopx.cc new file mode 100644 index 00000000..8fe27693 --- /dev/null +++ b/dcmimgle/libsrc/dimoopx.cc @@ -0,0 +1,76 @@ +/* + * + * Copyright (C) 1996-2010, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimgle + * + * Author: Joerg Riesmeier + * + * Purpose: DicomMonoOutputPixel (Source) + * + */ + + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/dcmimgle/dimoopx.h" +#include "dcmtk/dcmimgle/dimopx.h" + + +/*----------------* + * constructors * + *----------------*/ + +DiMonoOutputPixel::DiMonoOutputPixel(const DiMonoPixel *pixel, + const unsigned long size, + const unsigned long frame, + const unsigned long max) + : Count(0), + FrameSize(size), + UsedValues(NULL), + MaxValue(max) +{ + if (pixel != NULL) + { + if (pixel->getCount() > frame * size) + Count = pixel->getCount() - frame * size; // number of pixels remaining for this 'frame' + } + if (Count > FrameSize) + Count = FrameSize; // cut off at frame 'size' +} + + +/*--------------* + * destructor * + *--------------*/ + +DiMonoOutputPixel::~DiMonoOutputPixel() +{ + delete[] UsedValues; +} + + +/**********************************/ + + +int DiMonoOutputPixel::isUnused(const unsigned long value) +{ + if (UsedValues == NULL) + determineUsedValues(); // create on demand + if (UsedValues != NULL) + { + if (value <= MaxValue) + return OFstatic_cast(int, UsedValues[value] == 0); + return 2; // out of range + } + return 0; +} diff --git a/dcmimgle/libsrc/dimopx.cc b/dcmimgle/libsrc/dimopx.cc new file mode 100644 index 00000000..2ac2eddb --- /dev/null +++ b/dcmimgle/libsrc/dimopx.cc @@ -0,0 +1,96 @@ +/* + * + * Copyright (C) 1996-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimgle + * + * Author: Joerg Riesmeier + * + * Purpose: DicomMonochromePixel (Source) + * + */ + + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/dcmimgle/dimopx.h" +#include "dcmtk/dcmimgle/dimomod.h" +#include "dcmtk/dcmimgle/diinpx.h" +#include "dcmtk/dcmimgle/dimoopx.h" + + +/*----------------* + * constructors * + *----------------*/ + +DiMonoPixel::DiMonoPixel(const unsigned long count) + : DiPixel(count), + Modality(NULL) +{ +} + + +DiMonoPixel::DiMonoPixel(const DiInputPixel *pixel, + DiMonoModality *modality) + : DiPixel((pixel != NULL) ? pixel->getComputedCount() : 0, + (pixel != NULL) ? pixel->getPixelCount() : 0), + Modality(modality) +{ +} + + +DiMonoPixel::DiMonoPixel(const DiPixel *pixel, + DiMonoModality *modality) + : DiPixel(pixel->getCount(), pixel->getInputCount()), + Modality(modality) +{ +} + + +DiMonoPixel::DiMonoPixel(const DiMonoPixel *pixel, + const unsigned long count) + : DiPixel(count, pixel->getInputCount()), + Modality(pixel->Modality) +{ + if (Modality != NULL) + Modality->addReference(); +} + + +DiMonoPixel::DiMonoPixel(DiMonoOutputPixel *pixel, + DiMonoModality *modality) + : DiPixel(pixel->getCount()), + Modality(modality) +{ +} + + +/*--------------* + * destructor * + *--------------*/ + +DiMonoPixel::~DiMonoPixel() +{ + if (Modality != NULL) + Modality->removeReference(); +} + + +/*********************************************************************/ + + +DiMonoModality *DiMonoPixel::addReferenceToModality() +{ + if (Modality != NULL) + Modality->addReference(); + return Modality; +} diff --git a/dcmimgle/libsrc/diovdat.cc b/dcmimgle/libsrc/diovdat.cc new file mode 100644 index 00000000..89aacfab --- /dev/null +++ b/dcmimgle/libsrc/diovdat.cc @@ -0,0 +1,66 @@ +/* + * + * Copyright (C) 1996-2010, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimgle + * + * Author: Joerg Riesmeier + * + * Purpose: DicomOverlayData (Source) + * + */ + + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmdata/dctypes.h" + +#include "dcmtk/dcmimgle/diovlay.h" +#include "dcmtk/dcmimgle/diovpln.h" + +#include "dcmtk/ofstd/ofbmanip.h" + + +/*---------------* + * constructor * + *---------------*/ + +DiOverlayData::DiOverlayData(unsigned int entries, + unsigned int count) + : Count(count), + ArrayEntries(entries), + Planes(NULL), + DataBuffer(NULL) +{ + if ((entries > 0) && (entries <= DiOverlay::MaxOverlayCount)) + { + Planes = new DiOverlayPlane *[entries]; + if (Planes != NULL) + OFBitmanipTemplate::zeroMem(Planes, entries); + } +} + + +/*---------------* + * destructors * + *---------------*/ + +DiOverlayData::~DiOverlayData() +{ + if (Planes != NULL) + { + register unsigned int i; + for (i = 0; i < ArrayEntries; ++i) + delete Planes[i]; + } + delete[] Planes; + delete[] DataBuffer; +} diff --git a/dcmimgle/libsrc/diovlay.cc b/dcmimgle/libsrc/diovlay.cc new file mode 100644 index 00000000..e48f19f3 --- /dev/null +++ b/dcmimgle/libsrc/diovlay.cc @@ -0,0 +1,592 @@ +/* + * + * Copyright (C) 1996-2010, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimgle + * + * Author: Joerg Riesmeier + * + * Purpose: DicomOverlay (Source) + * + */ + + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmdata/dctypes.h" + +#include "dcmtk/dcmimgle/diovlay.h" +#include "dcmtk/dcmimgle/diovdat.h" +#include "dcmtk/dcmimgle/diovpln.h" +#include "dcmtk/dcmimgle/discalet.h" +#include "dcmtk/dcmimgle/diflipt.h" +#include "dcmtk/dcmimgle/dirotat.h" +#include "dcmtk/dcmimgle/didocu.h" + + +/*----------------------------* + * constant initializations * + *----------------------------*/ + +const unsigned int DiOverlay::MaxOverlayCount = 16; +const unsigned int DiOverlay::FirstOverlayGroup = 0x6000; + + +/*----------------* + * constructors * + *----------------*/ + +DiOverlay::DiOverlay(const DiDocument *docu, + const Uint16 alloc, + const Uint16 stored, + const Uint16 high) + : Left(0), + Top(0), + Width(0), + Height(0), + Frames(0), + AdditionalPlanes(docu == NULL), // planes are added later + Data(NULL) +{ + Data = new DiOverlayData(MaxOverlayCount); // can't determine number of overlays :-( + if ((docu != NULL) && (Data != NULL) && (Data->Planes != NULL)) + { + register unsigned int i; + for (i = 0; i < MaxOverlayCount; ++i) + { + Data->Planes[Data->Count] = new DiOverlayPlane(docu, convertToGroupNumber(i), alloc, stored, high); + if (Data->Planes[Data->Count] != NULL) + { + if (checkPlane(Data->Count)) + ++(Data->Count); + else { + delete Data->Planes[Data->Count]; + Data->Planes[Data->Count] = NULL; + } + } + } + } +} + + +// --- scale/clip overlay + +DiOverlay::DiOverlay(const DiOverlay *overlay, + const signed long left_pos, + const signed long top_pos, + const double xfactor, + const double yfactor) + : Left(left_pos), + Top(top_pos), + Width(OFstatic_cast(Uint16, xfactor * overlay->Width)), + Height(OFstatic_cast(Uint16, yfactor * overlay->Height)), + Frames(overlay->Frames), + AdditionalPlanes(overlay->AdditionalPlanes), + Data(NULL) +{ + Uint16 *temp = Init(overlay); + if (temp != NULL) + { + register unsigned int i; + for (i = 0; i < Data->ArrayEntries; ++i) + { + if (Data->Planes[i] != NULL) + Data->Planes[i]->setScaling(xfactor, yfactor); + } + DiScaleTemplate scale(1, overlay->Width, overlay->Height, Width, Height, Frames); + scale.scaleData(OFconst_cast(const Uint16 **, &temp), &(Data->DataBuffer), 0); + if (temp != overlay->Data->DataBuffer) + delete[] temp; + } +} + + +// --- flip overlay + +DiOverlay::DiOverlay(const DiOverlay *overlay, + const int horz, + const int vert, + const Uint16 columns, // width of surrounding image + const Uint16 rows) + : Left((horz) ? 0 : overlay->Left), + Top((vert) ? 0 : overlay->Top), + Width(overlay->Width), + Height(overlay->Height), + Frames(overlay->Frames), + AdditionalPlanes(overlay->AdditionalPlanes), + Data(NULL) +{ + Uint16 *temp = Init(overlay); + if (temp != NULL) + { + DiFlipTemplate flip(1, Width, Height, Frames); + flip.flipData(OFconst_cast(const Uint16 **, &temp), &(Data->DataBuffer), horz, vert); + if (temp != overlay->Data->DataBuffer) + delete[] temp; + register unsigned int i; + for (i = 0; i < Data->ArrayEntries; ++i) + { + if (Data->Planes[i] != NULL) + { + Data->Planes[i]->setFlipping(horz, vert, OFstatic_cast(signed long, columns) + overlay->Left, + OFstatic_cast(signed long, rows) + overlay->Top); + } + } + } +} + + +// --- rotate overlay + +DiOverlay::DiOverlay(const DiOverlay *overlay, + const int degree, + const Uint16 columns, // width of surrounding image (already rotated) + const Uint16 rows) + : Left(0), + Top(0), + Width(((degree == 90) || (degree == 270)) ? overlay->Height : overlay->Width), + Height(((degree == 90) || (degree == 270)) ? overlay->Width : overlay->Height), + Frames(overlay->Frames), + AdditionalPlanes(overlay->AdditionalPlanes), + Data(NULL) +{ + Uint16 *temp = Init(overlay); + if (temp != NULL) + { + DiRotateTemplate rotate(1, overlay->Width, overlay->Height, Width, Height, Frames); + rotate.rotateData(OFconst_cast(const Uint16 **, &temp), &(Data->DataBuffer), degree); + if (temp != overlay->Data->DataBuffer) + delete[] temp; + register unsigned int i; + for (i = 0; i < Data->ArrayEntries; ++i) + { + if (Data->Planes[i] != NULL) + Data->Planes[i]->setRotation(degree, overlay->Left, overlay->Top, columns, rows); + } + } +} + + +/*--------------* + * destructor * + *--------------*/ + +DiOverlay::~DiOverlay() +{ + if (Data != NULL) + Data->removeReference(); +} + + +/********************************************************************/ + + +Uint16 *DiOverlay::Init(const DiOverlay *overlay) +{ + if ((overlay != NULL) && (overlay->Data != NULL) && (overlay->Data->Count > 0)) + { + if (AdditionalPlanes) + Data = new DiOverlayData(overlay->Data->ArrayEntries); // use same array size + else + Data = new DiOverlayData(overlay->Data->Count); // shrink array size to minimal size + const unsigned long count = OFstatic_cast(unsigned long, overlay->Width) * + OFstatic_cast(unsigned long, overlay->Height) * overlay->Frames; + if ((Data != NULL) && (Data->Planes != NULL) && (count > 0)) + { + register unsigned int i; + Data->DataBuffer = new Uint16[OFstatic_cast(unsigned long, Width) * OFstatic_cast(unsigned long, Height) * Frames]; + if (Data->DataBuffer != NULL) + { + Uint16 *temp = NULL; + if (overlay->Data->DataBuffer == NULL) // no data buffer + { + temp = new Uint16[count]; // create temporary buffer + if (temp != NULL) + OFBitmanipTemplate::zeroMem(temp, count); + } + for (i = 0; i < Data->ArrayEntries; ++i) + { + if ((overlay->Data->Planes[i] != NULL) /*&& (overlay->Data->Planes[i]->isValid())*/) + { + Data->Planes[i] = new DiOverlayPlane(overlay->Data->Planes[i], i, Data->DataBuffer, temp, + overlay->Width, overlay->Height, Width, Height); + ++(Data->Count); + } + } + if (Data->Count != overlay->Data->Count) // assertion! + { + DCMIMGLE_WARN("different number of overlay planes for scaled and unscaled image"); + } + if (overlay->Data->DataBuffer != NULL) // existing data buffer + temp = overlay->Data->DataBuffer; // point to input buffer + return temp; + } + } + } + return NULL; +} + + +int DiOverlay::convertToPlaneNumber(unsigned int &plane, + const int mode) const +{ + if ((Data != NULL) && (Data->Planes != NULL)) + { + if (isValidGroupNumber(plane)) + { + if (AdditionalPlanes) + { + plane = (plane - FirstOverlayGroup) >> 1; // plane = (group - 0x6000) / 2 + if (Data->Planes[plane] != NULL) + return 2; // plane alreay exists + return 1; // ... is new + } else { + register unsigned int i; + for (i = 0; i < Data->Count; ++i) + { + if ((Data->Planes[i] != NULL) && (Data->Planes[i]->getGroupNumber() == plane)) + { + plane = i; // plane number + return 2; + } + } + } + } else if (!mode && (plane < Data->Count) && (Data->Planes[plane] != NULL)) // valid plane number? + return 3; + } + return 0; +} + + +int DiOverlay::isValidGroupNumber(const unsigned int group) const +{ + return (group >= convertToGroupNumber(0)) && (group <= convertToGroupNumber(MaxOverlayCount - 1)) && !(group & 1); +} + + +int DiOverlay::checkPlane(const unsigned int plane, + const int mode) +{ + if ((Data != NULL) && (Data->Planes != NULL) && (plane < MaxOverlayCount) && (Data->Planes[plane] != NULL)) + { + if (Data->Planes[plane]->isValid()) + { + if (Data->Planes[plane]->getWidth() > Width) // determine maximum width + Width = Data->Planes[plane]->getWidth(); + if (Data->Planes[plane]->getHeight() > Height) // determine maximum height + Height = Data->Planes[plane]->getHeight(); + if (mode && (Data->Planes[plane]->getNumberOfFrames() > Frames)) // determine maximum frames + Frames = Data->Planes[plane]->getNumberOfFrames(); + return 1; + } + } + return 0; +} + + +int DiOverlay::isPlaneVisible(unsigned int plane) +{ + if (convertToPlaneNumber(plane, AdditionalPlanes) > 1) + return Data->Planes[plane]->isVisible(); + return 0; +} + + +int DiOverlay::showPlane(unsigned int plane) +{ + if (convertToPlaneNumber(plane, AdditionalPlanes) > 1) + { + if (Data->Planes[plane]->isVisible()) + return 2; + Data->Planes[plane]->show(); + return 1; + } + return 0; +} + + +int DiOverlay::showPlane(unsigned int plane, + const double fore, + const double tresh, + const EM_Overlay mode) +{ + if (convertToPlaneNumber(plane, AdditionalPlanes) > 1) + { + Data->Planes[plane]->show(fore, tresh, mode); + return 1; + } + return 0; +} + + +int DiOverlay::showPlane(unsigned int plane, + const Uint16 pvalue) +{ + if (convertToPlaneNumber(plane, AdditionalPlanes) > 1) + return Data->Planes[plane]->show(pvalue); + return 0; +} + + +int DiOverlay::showAllPlanes() +{ + if ((Data != NULL) && (Data->Planes != NULL)) + { + register unsigned int i; + for (i = 0; i < Data->ArrayEntries; ++i) + { + if (Data->Planes[i] != NULL) + Data->Planes[i]->show(); + } + if (Data->Count > 0) + return 1; + return 2; + } + return 0; +} + + +int DiOverlay::showAllPlanes(const double fore, + const double tresh, + const EM_Overlay mode) +{ + if ((Data != NULL) && (Data->Planes != NULL)) + { + register unsigned int i; + for (i = 0; i < Data->ArrayEntries; ++i) + { + if ((Data->Planes[i] != NULL)) + Data->Planes[i]->show(fore, tresh, mode); + } + if (Data->Count > 0) + return 1; + return 2; + } + return 0; +} + + +int DiOverlay::hidePlane(unsigned int plane) +{ + if (convertToPlaneNumber(plane, AdditionalPlanes) > 1) + { + if (!Data->Planes[plane]->isVisible()) + return 2; + Data->Planes[plane]->hide(); + return 1; + } + return 0; +} + + +int DiOverlay::hideAllPlanes() +{ + if ((Data != NULL) && (Data->Planes != NULL)) + { + register unsigned int i; + for (i = 0; i < Data->ArrayEntries; ++i) + { + if (Data->Planes[i] != NULL) + Data->Planes[i]->hide(); + } + if (Data->Count > 0) + return 1; + return 2; + } + return 0; +} + + +int DiOverlay::placePlane(unsigned int plane, + const signed int left_pos, + const signed int top_pos) +{ + if (convertToPlaneNumber(plane, AdditionalPlanes) > 1) + { + if ((Data->Planes[plane]->getLeft() == left_pos) && (Data->Planes[plane]->getTop() == top_pos)) + return 2; + Data->Planes[plane]->place(left_pos, top_pos); + return 1; + } + return 0; +} + + +unsigned int DiOverlay::getPlaneGroupNumber(unsigned int plane) const +{ + if (convertToPlaneNumber(plane, AdditionalPlanes) > 1) + return Data->Planes[plane]->getGroupNumber(); + return 0; +} + + +const char *DiOverlay::getPlaneLabel(unsigned int plane) const +{ + if (convertToPlaneNumber(plane, AdditionalPlanes) > 1) + return Data->Planes[plane]->getLabel(); + return NULL; +} + + +const char *DiOverlay::getPlaneDescription(unsigned int plane) const +{ + if (convertToPlaneNumber(plane, AdditionalPlanes) > 1) + return Data->Planes[plane]->getDescription(); + return NULL; +} + + +EM_Overlay DiOverlay::getPlaneMode(unsigned int plane) const +{ + if (convertToPlaneNumber(plane, AdditionalPlanes) > 1) + return Data->Planes[plane]->getMode(); + return EMO_Default; +} + + +int DiOverlay::hasEmbeddedData() const +{ + if ((Data != NULL) && (Data->Planes != NULL)) + { + register unsigned int i; + for (i = 0; i < Data->ArrayEntries; ++i) + { + if ((Data->Planes[i] != NULL) && (Data->Planes[i]->isEmbedded())) + return 1; + } + } + return 0; +} + + +int DiOverlay::addPlane(const unsigned int group, + const signed int left_pos, + const signed int top_pos, + const unsigned int columns, + const unsigned int rows, + const DcmOverlayData &data, + const DcmLongString &label, + const DcmLongString &description, + const EM_Overlay mode) +{ + int status = 0; + if (AdditionalPlanes && isValidGroupNumber(group)) + { + unsigned int plane = group; + status = convertToPlaneNumber(plane, AdditionalPlanes); + if ((status != 0) && (plane < Data->ArrayEntries)) + { + if (status == 1) // add new plane + ++(Data->Count); + else if (status == 2) // group number already exists + delete Data->Planes[plane]; + Data->Planes[plane] = new DiOverlayPlane(group, left_pos, top_pos, columns, rows, data, label, description, mode); + if (checkPlane(plane, 0)) + { + if (Data->Planes[plane]->getNumberOfFrames() > Frames) // set maximum number of frames + Frames = Data->Planes[plane]->getNumberOfFrames(); + } else { + delete Data->Planes[plane]; // remove invalid plane + Data->Planes[plane] = NULL; + if (status == 1) + --(Data->Count); // decrease number of planes + status = 0; + } + } + } + return status; +} + + +int DiOverlay::removePlane(const unsigned int group) +{ + unsigned int plane = group; + if (AdditionalPlanes && (convertToPlaneNumber(plane, AdditionalPlanes) > 1)) + { + delete Data->Planes[plane]; // remove invalid plane + Data->Planes[plane] = NULL; + --(Data->Count); // decrease number of planes + return 1; + } + return 0; +} + + +void *DiOverlay::getPlaneData(const unsigned long frame, + unsigned int plane, + unsigned int &left_pos, + unsigned int &top_pos, + unsigned int &width, + unsigned int &height, + EM_Overlay &mode, + const Uint16 columns, + const Uint16 rows, + const int bits, + const Uint16 fore, + const Uint16 back) +{ + if (convertToPlaneNumber(plane, AdditionalPlanes) > 1) // plane does exist + { + DiOverlayPlane *op = Data->Planes[plane]; + if ((op != NULL) && op->isValid()) + { + const Uint16 xmin = (op->getLeft(Left) > 0) ? op->getLeft(Left) : 0; + const Uint16 ymin = (op->getTop(Top) > 0) ? op->getTop(Top) : 0; + const Uint16 xmax = (op->getRight(Left) < columns) ? op->getRight(Left) : columns; + const Uint16 ymax = (op->getBottom(Top) < rows) ? op->getBottom(Top) : rows; + left_pos = xmin; + top_pos = ymin; + width = xmax - xmin; + height = ymax - ymin; + mode = op->getMode(); + return op->getData(frame, xmin, ymin, xmax, ymax, bits, fore, back); + } + } + return NULL; +} + + +void *DiOverlay::getFullPlaneData(const unsigned long frame, + unsigned int plane, + unsigned int &width, + unsigned int &height, + const int bits, + const Uint16 fore, + const Uint16 back) +{ + if (convertToPlaneNumber(plane, AdditionalPlanes) > 1) // plane does exist + { + DiOverlayPlane *op = Data->Planes[plane]; + if ((op != NULL) && op->isValid()) + { + width = op->getWidth(); + height = op->getHeight(); + return op->getData(frame, 0, 0, width, height, bits, fore, back); + } + } + return NULL; +} + + +unsigned long DiOverlay::create6xxx3000PlaneData(Uint8 *&buffer, + unsigned int plane, + unsigned int &width, + unsigned int &height, + unsigned long &frames) +{ + if (convertToPlaneNumber(plane, AdditionalPlanes) > 1) // plane does exist + { + DiOverlayPlane *op = Data->Planes[plane]; + if ((op != NULL) && op->isValid()) + return op->create6xxx3000Data(buffer, width, height, frames); + } + return 0; +} diff --git a/dcmimgle/libsrc/diovlimg.cc b/dcmimgle/libsrc/diovlimg.cc new file mode 100644 index 00000000..8c5d7a62 --- /dev/null +++ b/dcmimgle/libsrc/diovlimg.cc @@ -0,0 +1,94 @@ +/* + * + * Copyright (C) 1996-2010, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimgle + * + * Author: Joerg Riesmeier + * + * Purpose: DicomOverlayImage (Source) + * + */ + + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmdata/dctypes.h" + +#include "dcmtk/dcmimgle/diovlimg.h" +#include "dcmtk/dcmimgle/dimopxt.h" +#include "dcmtk/dcmimgle/didocu.h" + + +/*----------------* + * constructors * + *----------------*/ + +DiOverlayImage::DiOverlayImage(const DiDocument *docu, + const EI_Status status) + : DiMono2Image(docu, status, 0) +{ + if (Document != NULL) + { + Overlays[0] = new DiOverlay(Document); + if (Overlays[0] != NULL) + { + BitsPerSample = 1; + register unsigned int i; + register DiOverlayPlane *plane; + for (i = 0; i < Overlays[0]->getCount(); ++i) + { + plane = Overlays[0]->getPlane(i); + if (plane != NULL) + { + plane->show(); + if (plane->getNumberOfFrames() > NumberOfFrames) + NumberOfFrames = plane->getNumberOfFrames(); + if (plane->getRight() > Columns) // determine image's width and height + Columns = plane->getRight(); + if (plane->getBottom() > Rows) + Rows = plane->getBottom(); + } + } + if ((Rows > 0) && (Columns > 0)) + { + InterData = new DiMonoPixelTemplate(OFstatic_cast(unsigned long, Rows) * + OFstatic_cast(unsigned long, Columns) * NumberOfFrames); + if (InterData == NULL) + { + ImageStatus = EIS_MemoryFailure; + DCMIMGLE_ERROR("can't allocate memory for inter-representation"); + } + else if (InterData->getData() == NULL) + ImageStatus = EIS_InvalidImage; + } + else + { + ImageStatus = EIS_InvalidValue; + DCMIMGLE_ERROR("invalid value for 'Rows' (" << Rows << ") and/or 'Columns' (" << Columns << ")"); + } + } + } + else + { + ImageStatus = EIS_InvalidDocument; + DCMIMGLE_ERROR("this DICOM document is invalid"); + } +} + + +/*--------------* + * destructor * + *--------------*/ + +DiOverlayImage::~DiOverlayImage() +{ +} diff --git a/dcmimgle/libsrc/diovpln.cc b/dcmimgle/libsrc/diovpln.cc new file mode 100644 index 00000000..418aaca7 --- /dev/null +++ b/dcmimgle/libsrc/diovpln.cc @@ -0,0 +1,613 @@ +/* + * + * Copyright (C) 1996-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimgle + * + * Author: Joerg Riesmeier + * + * Purpose: DicomOverlayPlane (Source) + * + */ + + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/dcmdata/dctypes.h" +#include "dcmtk/dcmdata/dcdeftag.h" +#include "dcmtk/dcmdata/dctagkey.h" +#include "dcmtk/dcmdata/dcpixel.h" +#include "dcmtk/ofstd/ofbmanip.h" + +#include "dcmtk/dcmimgle/diovpln.h" +#include "dcmtk/dcmimgle/didocu.h" + + +/*----------------* + * constructors * + *----------------*/ + +DiOverlayPlane::DiOverlayPlane(const DiDocument *docu, + const unsigned int group, + Uint16 alloc, + const Uint16 stored, + const Uint16 high) + : NumberOfFrames(0), + ImageFrameOrigin(0), + FirstFrame(0), + Top(0), + Left(0), + Height(0), + Width(0), + Rows(0), + Columns(0), + BitsAllocated(0), + BitPosition(0), + Foreground(1), + Threshold(1), + PValue(0), + Mode(EMO_Graphic), + DefaultMode(EMO_Graphic), + Label(), + Description(), + GroupNumber(group), + Valid(0), + Visible(0), + BitPos(0), + StartBitPos(0), + StartLeft(0), + StartTop(0), + EmbeddedData(0), + Ptr(NULL), + StartPtr(NULL), + Data(NULL) +{ + if (docu != NULL) + { + /* determine first frame to be processed */ + FirstFrame = docu->getFrameStart(); + /* specifiy overlay group number */ + DcmTagKey tag(group, DCM_OverlayRows.getElement() /* dummy */); + /* get descriptive data */ + tag.setElement(DCM_OverlayLabel.getElement()); + docu->getValue(tag, Label); + tag.setElement(DCM_OverlayDescription.getElement()); + docu->getValue(tag, Description); + /* get overlay type */ + tag.setElement(DCM_OverlayType.getElement()); + const char *str; + if ((docu->getValue(tag, str) > 0) && (str != NULL) && (strcmp(str, "R") == 0)) + DefaultMode = Mode = EMO_RegionOfInterest; + Sint32 sl = 0; + /* multi-frame overlays */ + tag.setElement(DCM_NumberOfFramesInOverlay.getElement()); + docu->getValue(tag, sl); + NumberOfFrames = (sl < 1) ? 1 : OFstatic_cast(Uint32, sl); + tag.setElement(DCM_ImageFrameOrigin.getElement()); + docu->getValue(tag, ImageFrameOrigin); + if (ImageFrameOrigin > 0) // image frame origin is numbered from 1 + --ImageFrameOrigin; + tag.setElement(DCM_OverlayOrigin.getElement()); +#ifdef REVERSE_OVERLAY_ORIGIN_ORDER + Valid = (docu->getValue(tag, Left, 0) > 0); + if (Valid) + { + DCMIMGLE_DEBUG("processing overlay plane in group 0x" << STD_NAMESPACE hex << group); + if (docu->getValue(tag, Top, 1) < 2) + DCMIMGLE_WARN("missing second value for 'OverlayOrigin' ... assuming 'Top' = " << Top); + } +#else + Valid = (docu->getValue(tag, Top, 0) > 0); + if (Valid) + { + DCMIMGLE_DEBUG("processing overlay plane in group 0x" << STD_NAMESPACE hex << group); + if (docu->getValue(tag, Left, 1) < 2) + DCMIMGLE_WARN("missing second value for 'OverlayOrigin' ... assuming 'Left' = " << Left); + } +#endif + /* overlay origin is numbered from 1 */ + --Top; + --Left; + /* check overlay resolution */ + tag.setElement(DCM_OverlayRows.getElement()); + Valid &= (docu->getValue(tag, Rows) > 0); + Height = Rows; + tag.setElement(DCM_OverlayColumns.getElement()); + Valid &= (docu->getValue(tag, Columns) > 0); + Width = Columns; + /* check overlay encoding */ + tag.setElement(DCM_OverlayBitsAllocated.getElement()); + Valid &= (docu->getValue(tag, BitsAllocated) > 0); + tag.setElement(DCM_OverlayBitPosition.getElement()); + Valid &= (docu->getValue(tag, BitPosition) > 0); + tag.setElement(DCM_OverlayData.getElement()); + /* final validity checks */ + if (Valid) + { + /* separate overlay data? */ + unsigned long length = docu->getValue(tag, Data) * 2 /* bytes */; + if (length == 0) + { + if (!(docu->getFlags() & CIF_NeverAccessEmbeddedOverlays)) + { + if (!docu->isCompressed()) + { + /* if not, check for embedded overlay data */ + DcmPixelData *pixelData = docu->getPixelData(); + if (pixelData != NULL) + { + ImageFrameOrigin = 0; // see supplement 4 + const OFBool loaded = pixelData->valueLoaded(); + if (pixelData->getUint16Array(OFconst_cast(Uint16 *&, Data)).good()) + { + length = pixelData->getLength(docu->getTransferSyntax()); + EmbeddedData = (Data != NULL); + if (!loaded) + DCMIMGLE_DEBUG("loaded complete pixel data into memory for embedded overlay data: " << length << " bytes"); + } + } + } else + DCMIMGLE_ERROR("embedded overlay data cannot be accessed since pixel data is still compressed"); + } else + DCMIMGLE_WARN("ignoring possibly embedded overlay data by configuration"); + } else + alloc = 1; // separately stored overlay data + /* check for correct value of BitsAllocated */ + if (BitsAllocated != alloc) // see correction proposal 87 + { + DCMIMGLE_WARN("invalid value for 'OverlayBitsAllocated' (" << BitsAllocated << ") ... assuming " << alloc); + BitsAllocated = alloc; + } + /* check for correct value of BitPosition */ + if (BitPosition >= BitsAllocated) + { + DCMIMGLE_WARN("invalid value for 'OverlayBitPosition' (" << BitPosition << ") ... assuming " << (BitsAllocated - 1)); + BitPosition = BitsAllocated - 1; + } + if (EmbeddedData && (BitPosition <= high) && (BitPosition + stored > high)) + { + DCMIMGLE_WARN("invalid value for 'OverlayBitPosition' (" << BitPosition << "), refers to bit position within stored pixel value"); + Data = NULL; // invalid plane + } + /* expected length of overlay data */ + const unsigned long expLen = (OFstatic_cast(unsigned long, NumberOfFrames) * OFstatic_cast(unsigned long, Rows) * + OFstatic_cast(unsigned long, Columns) * OFstatic_cast(unsigned long, BitsAllocated) + 7) / 8; + if ((Data != NULL) && ((length == 0) || (length < expLen))) + { + DCMIMGLE_ERROR("overlay data length is too short, " << expLen << " bytes expected but " << length << " bytes found"); + Valid = 0; + Data = NULL; + } else + Valid = (Data != NULL); + } + if (Valid) + { + /* report that this group contains a valid overlay plane */ + DCMIMGLE_TRACE("overlay plane in group 0x" << STD_NAMESPACE hex << group << " is present and can be processed"); + } else { + /* report that this group does not contain a valid overlay plane */ + DCMIMGLE_TRACE("overlay plane in group 0x" << STD_NAMESPACE hex << group << " is missing or incomplete"); + } + } +} + + +DiOverlayPlane::DiOverlayPlane(const unsigned int group, + const Sint16 left_pos, + const Sint16 top_pos, + const Uint16 columns, + const Uint16 rows, + const DcmOverlayData &data, + const DcmLongString &label, + const DcmLongString &description, + const EM_Overlay mode) + : NumberOfFrames(1), + ImageFrameOrigin(0), + FirstFrame(0), + Top(top_pos), + Left(left_pos), + Height(rows), + Width(columns), + Rows(rows), + Columns(columns), + BitsAllocated(1), + BitPosition(0), + Foreground(1), + Threshold(1), + PValue(0), + Mode(mode), + DefaultMode(mode), + Label(), + Description(), + GroupNumber(group), + Valid(0), + Visible((mode == EMO_BitmapShutter) ? 1 : 0), + BitPos(0), + StartBitPos(0), + StartLeft(0), + StartTop(0), + EmbeddedData(0), + Ptr(NULL), + StartPtr(NULL), + Data(NULL) +{ + DiDocument::getElemValue(OFreinterpret_cast(const DcmElement *, &label), Label); + DiDocument::getElemValue(OFreinterpret_cast(const DcmElement *, &description), Description); + if ((Columns > 0) && (Rows > 0)) + { + const unsigned long length = DiDocument::getElemValue(OFreinterpret_cast(const DcmElement *, &data), Data) * 2 /* Bytes */; + /* expected length of overlay data */ + const unsigned long expLen = (OFstatic_cast(unsigned long, Rows) * OFstatic_cast(unsigned long, Columns) + 7) / 8; + if ((length == 0) || (length < expLen)) + { + DCMIMGLE_ERROR("overlay data length is too short, " << expLen << " bytes expected but " << length << " bytes found"); + /* Valid = 0; => This is the default. */ + Data = NULL; + } else + Valid = (Data != NULL); + } + --Top; // overlay origin is numbered from 1 + --Left; +} + + +DiOverlayPlane::DiOverlayPlane(DiOverlayPlane *plane, + const unsigned int bit, + Uint16 *data, + Uint16 *temp, + const Uint16 width, + const Uint16 height, + const Uint16 columns, + const Uint16 rows) + : NumberOfFrames(plane->NumberOfFrames), + ImageFrameOrigin(plane->ImageFrameOrigin), + FirstFrame(plane->FirstFrame), + Top(plane->Top), + Left(plane->Left), + Height(plane->Height), + Width(plane->Width), + Rows(rows), + Columns(columns), + BitsAllocated(16), + BitPosition(bit), + Foreground(plane->Foreground), + Threshold(plane->Threshold), + PValue(0), + Mode(plane->Mode), + DefaultMode(plane->DefaultMode), + Label(plane->Label), + Description(plane->Description), + GroupNumber(plane->GroupNumber), + Valid(0), + Visible(plane->Visible), + BitPos(0), + StartBitPos(0), + StartLeft(plane->StartLeft), + StartTop(plane->StartTop), + EmbeddedData(0), + Ptr(NULL), + StartPtr(NULL), + Data(data) +{ + if (temp != NULL) + { + register Uint16 x; + register Uint16 y; + register Uint16 *q = temp; + register const Uint16 mask = 1 << bit; + const Uint16 skip_x = width - plane->Columns; + const unsigned long skip_f = OFstatic_cast(unsigned long, height - plane->Rows) * OFstatic_cast(unsigned long, width); + for (unsigned long f = 0; f < NumberOfFrames; ++f) + { + if (plane->reset(f + ImageFrameOrigin)) + { + for (y = 0; y < plane->Rows; ++y) + { + for (x = 0; x < plane->Columns; ++x, ++q) + { + if (plane->getNextBit()) + *q |= mask; // set corresponding bit + else + *q &= ~mask; // unset ... bit + } + q += skip_x; // skip to next line start + } + q += skip_f; // skip to next frame start + } + } + } + Valid = (Data != NULL); +} + + +/*--------------* + * destructor * + *--------------*/ + +DiOverlayPlane::~DiOverlayPlane() +{ +} + + +/********************************************************************/ + + +void *DiOverlayPlane::getData(const unsigned long frame, + const Uint16 xmin, + const Uint16 ymin, + const Uint16 xmax, + const Uint16 ymax, + const int bits, + const Uint16 fore, + const Uint16 back) +{ + const unsigned long count = OFstatic_cast(unsigned long, xmax - xmin) * OFstatic_cast(unsigned long, ymax - ymin); + if (Valid && (count > 0)) + { + const Uint16 mask = OFstatic_cast(Uint16, DicomImageClass::maxval(bits)); + if (bits == 1) + { + const unsigned long count8 = (count + 7) / 8; // round value: 8 bit padding + Uint8 *data = new Uint8[count8]; + if (data != NULL) + { + if ((fore & mask) != (back & mask)) + { + OFBitmanipTemplate::setMem(data, 0x0, count8); + register Uint16 x; + register Uint16 y; + register Uint8 value = 0; + register Uint8 *q = data; + register int bit = 0; + if (reset(frame + ImageFrameOrigin)) + { + for (y = ymin; y < ymax; ++y) + { + setStart(xmin, y); + for (x = xmin; x < xmax; ++x) + { + if (getNextBit()) + { + if (fore) + value |= (1 << bit); + } else if (back) + value |= (1 << bit); + if (bit == 7) + { + *(q++) = value; + value = 0; + bit = 0; + } else { + ++bit; + } + } + } + if (bit != 0) + *(q++) = value; + } + } else { + OFBitmanipTemplate::setMem(data, (fore) ? 0xff : 0x0, count8); + } + } + return OFstatic_cast(void *, data); + } + else if ((bits > 1) && (bits <= 8)) + { + Uint8 *data = new Uint8[count]; + if (data != NULL) + { + const Uint8 fore8 = OFstatic_cast(Uint8, fore & mask); + const Uint8 back8 = OFstatic_cast(Uint8, back & mask); + OFBitmanipTemplate::setMem(data, back8, count); + if (fore8 != back8) // optimization + { + register Uint16 x; + register Uint16 y; + register Uint8 *q = data; + if (reset(frame + ImageFrameOrigin)) + { + for (y = ymin; y < ymax; ++y) + { + setStart(xmin, y); + for (x = xmin; x < xmax; ++x, ++q) + { + if (getNextBit()) + *q = fore8; // set pixel value (default: 0xff) + } + } + } + } + } + return OFstatic_cast(void *, data); + } + else if ((bits > 8) && (bits <= 16)) + { + Uint16 *data = new Uint16[count]; + if (data != NULL) + { + const Uint16 fore16 = fore & mask; + const Uint16 back16 = back & mask; + OFBitmanipTemplate::setMem(data, back16, count); + if (fore16 != back16) // optimization + { + register Uint16 x; + register Uint16 y; + register Uint16 *q = data; + if (reset(frame + ImageFrameOrigin)) + { + for (y = ymin; y < ymax; ++y) + { + setStart(xmin, y); + for (x = xmin; x < xmax; ++x, ++q) + { + if (getNextBit()) + *q = fore16; // set pixel value (default: 0xff) + } + } + } + } + } + return OFstatic_cast(void *, data); + } + } + return NULL; +} + + +unsigned long DiOverlayPlane::create6xxx3000Data(Uint8 *&buffer, + unsigned int &width, + unsigned int &height, + unsigned long &frames) +{ + buffer = NULL; + width = Width; + height = Height; + frames = NumberOfFrames; + const unsigned long count = OFstatic_cast(unsigned long, Width) * OFstatic_cast(unsigned long, Height) * NumberOfFrames; + if (Valid && (count > 0)) + { + const unsigned long count8 = ((count + 15) / 16) * 2; // round value: 16 bit padding + buffer = new Uint8[count8]; + if (buffer != NULL) + { + OFBitmanipTemplate::setMem(buffer, 0x0, count8); + register Uint16 x; + register Uint16 y; + register Uint8 value = 0; + register Uint8 *q = buffer; + register int bit = 0; + for (unsigned long f = 0; f < NumberOfFrames; ++f) + { + if (reset(f + ImageFrameOrigin)) + { + for (y = 0; y < Height; ++y) + { + for (x = 0; x < Width; ++x) + { + if (getNextBit()) + value |= (1 << bit); + if (bit == 7) + { + *(q++) = value; + value = 0; + bit = 0; + } else { + ++bit; + } + } + } + } + if (bit != 0) + *(q++) = value; + } + return count8; // number of bytes + } + } + return 0; +} + + +void DiOverlayPlane::show(const double fore, + const double thresh, + const EM_Overlay mode) +{ + Foreground = (fore < 0) ? 0 : (fore > 1) ? 1 : fore; + Threshold = (thresh < 0) ? 0 : (thresh > 1) ? 1 : thresh; + Mode = (mode == EMO_Default) ? DefaultMode : mode; + Visible = 1; +} + + +int DiOverlayPlane::show(const Uint16 pvalue) +{ + if (Mode == EMO_BitmapShutter) + { + PValue = pvalue; + Visible = 1; + return 1; + } + return 0; +} + + +void DiOverlayPlane::place(const signed int left_pos, + const signed int top_pos) +{ + Left = OFstatic_cast(Sint16, left_pos); + Top = OFstatic_cast(Sint16, top_pos); +} + + +void DiOverlayPlane::setScaling(const double xfactor, + const double yfactor) +{ + Left = OFstatic_cast(Sint16, xfactor * Left); + Top = OFstatic_cast(Sint16, yfactor * Top); + Width = OFstatic_cast(Uint16, xfactor * Width); + Height = OFstatic_cast(Uint16, yfactor * Height); +} + + +void DiOverlayPlane::setFlipping(const int horz, + const int vert, + const signed long columns, + const signed long rows) +{ + if (horz) + { + Left = OFstatic_cast(Sint16, columns - Width - Left); + StartLeft = OFstatic_cast(Uint16, OFstatic_cast(signed long, Columns) - Width - StartLeft); + } + if (vert) + { + Top = OFstatic_cast(Sint16, rows - Height - Top); + StartTop = OFstatic_cast(Uint16, OFstatic_cast(signed long, Rows) - Height - StartTop); + } +} + + +void DiOverlayPlane::setRotation(const int degree, + const signed long left_pos, + const signed long top_pos, + const Uint16 columns, + const Uint16 rows) +{ + if (degree == 180) // equal to v/h flip + setFlipping(1, 1, left_pos + columns, top_pos + rows); + else if ((degree == 90) || (degree == 270)) + { + Uint16 us = Height; // swap visible width/height + Height = Width; + Width = us; +/* + us = Rows; // swap stored width/height -> already done in the constructor ! + Rows = Columns; + Columns = us; +*/ + if (degree == 90) // rotate right + { + Sint16 ss = Left; + us = StartLeft; + Left = OFstatic_cast(Sint16, OFstatic_cast(signed long, columns) - Width - Top + top_pos); + StartLeft = OFstatic_cast(Uint16, OFstatic_cast(signed long, Columns) - Width - StartTop); + Top = OFstatic_cast(Sint16, ss - left_pos); + StartTop = us; + } else { // rotate left + Sint16 ss = Left; + us = StartLeft; + Left = OFstatic_cast(Sint16, Top - top_pos); + StartLeft = StartTop; + Top = OFstatic_cast(Sint16, OFstatic_cast(signed long, rows) - Height - ss + left_pos); + StartTop = OFstatic_cast(Uint16, OFstatic_cast(signed long, Rows) - Height - us); + } + } +} diff --git a/dcmimgle/libsrc/diutils.cc b/dcmimgle/libsrc/diutils.cc new file mode 100644 index 00000000..584cb7a4 --- /dev/null +++ b/dcmimgle/libsrc/diutils.cc @@ -0,0 +1,138 @@ +/* + * + * Copyright (C) 1996-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmimgle + * + * Author: Joerg Riesmeier + * + * Purpose: Utilities (Source) + * + */ + + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/dcmdata/dctypes.h" +#include "dcmtk/ofstd/ofstream.h" + +#include "dcmtk/dcmimgle/diutils.h" + +#define INCLUDE_CMATH +#include "dcmtk/ofstd/ofstdinc.h" + + +/*--------------------* + * global variables * + *--------------------*/ + +OFLogger DCM_dcmimgleLogger = OFLog::getLogger("dcmtk.dcmimgle"); + + +/*------------------------* + * function definitions * + *------------------------*/ + +unsigned int DicomImageClass::rangeToBits(double minvalue, + double maxvalue) +{ + /* assertion: min < max ! */ + if (minvalue > maxvalue) + { + const double temp = minvalue; + minvalue = maxvalue; + maxvalue = temp; + } + /* signed data? */ + if (minvalue < 0) + { + if (fabs(minvalue) > fabs(maxvalue)) + return tobits(OFstatic_cast(unsigned long, fabs(minvalue)), 1) + 1; + else /* 'minvalue' is negative, 'maxvalue' is positive */ + return tobits(OFstatic_cast(unsigned long, fabs(maxvalue)), 0) + 1; + } + return tobits(OFstatic_cast(unsigned long, maxvalue), 0); +} + + +int DicomImageClass::isRepresentationSigned(EP_Representation repres) +{ + /* determine whether integer representation is signed or unsigned */ + return (repres == EPR_Sint8) || (repres == EPR_Sint16) || (repres == EPR_Sint32); +} + + +unsigned int DicomImageClass::getRepresentationBits(EP_Representation repres) +{ + unsigned int bits = 0; + /* determine number of bits for specified representation */ + switch (repres) + { + case EPR_Uint8: + case EPR_Sint8: + bits = 8; + break; + case EPR_Uint16: + case EPR_Sint16: + bits = 16; + break; + case EPR_Uint32: + case EPR_Sint32: + bits = 32; + break; + } + return bits; +} + + +EP_Representation DicomImageClass::determineRepresentation(double minvalue, + double maxvalue) +{ + if (minvalue > maxvalue) /* assertion: min < max ! */ + { + const double temp = minvalue; + minvalue = maxvalue; + maxvalue = temp; + } + if (minvalue < 0) /* signed */ + { + if ((-minvalue <= maxval(7, 0)) && (maxvalue <= maxval(7))) + return EPR_Sint8; + if ((-minvalue <= maxval(15, 0)) && (maxvalue <= maxval(15))) + return EPR_Sint16; +#ifdef DEBUG + if (-minvalue > maxval(MAX_BITS - 1, 0)) + { + DCMIMGLE_WARN("minimum pixel value (" << minvalue << ") exceeds signed " << MAX_BITS + << " bit " << "representation after modality transformation"); + } + if (maxvalue > maxval(MAX_BITS - 1)) + { + DCMIMGLE_WARN("maximum pixel value (" << maxvalue << ") exceeds signed " << MAX_BITS + << " bit " << "representation after modality transformation"); + } +#endif + return EPR_Sint32; + } + if (maxvalue <= maxval(8)) + return EPR_Uint8; + if (maxvalue <= maxval(16)) + return EPR_Uint16; +#ifdef DEBUG + if (maxvalue > maxval(MAX_BITS)) + { + DCMIMGLE_WARN("maximum pixel value (" << maxvalue << ") exceeds unsigned " << MAX_BITS + << " bit " << "representation after modality transformation"); + } +#endif + return EPR_Uint32; +} diff --git a/dcmimgle/tests/Makefile.in b/dcmimgle/tests/Makefile.in new file mode 100644 index 00000000..f6382936 --- /dev/null +++ b/dcmimgle/tests/Makefile.in @@ -0,0 +1,29 @@ +# +# Makefile for dcmimgle/tests +# + +@SET_MAKE@ + +SHELL = /bin/sh +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +configdir = @top_srcdir@/@configdir@ + +include $(configdir)/@common_makefile@ + + +all: + +check: + +check-exhaustive: + +install: + +clean: + rm -f $(TRASH) + +distclean: + rm -f $(DISTTRASH) + +dependencies: diff --git a/dcmiod/CMakeLists.txt b/dcmiod/CMakeLists.txt new file mode 100644 index 00000000..807e794b --- /dev/null +++ b/dcmiod/CMakeLists.txt @@ -0,0 +1,10 @@ +# declare project +PROJECT(dcmiod) + +# declare include directories which hold for all subdirectories +INCLUDE_DIRECTORIES(${dcmiod_SOURCE_DIR}/include ${dcmdata_SOURCE_DIR}/include ${ofstd_SOURCE_DIR}/include ${oflog_SOURCE_DIR}/include ${ZLIB_INCDIR}) + +# recurse into subdirectories +FOREACH(SUBDIR libsrc include) + ADD_SUBDIRECTORY(${SUBDIR}) +ENDFOREACH(SUBDIR) diff --git a/dcmiod/Makefile.in b/dcmiod/Makefile.in new file mode 100644 index 00000000..af66effe --- /dev/null +++ b/dcmiod/Makefile.in @@ -0,0 +1,85 @@ +# +# Makefile for dcmiod +# + +@SET_MAKE@ + +SHELL = /bin/sh +VPATH = @srcdir@:@top_srcdir@/include:@top_srcdir@/@configdir@/include +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +configdir = @top_srcdir@/@configdir@ + +include $(configdir)/@common_makefile@ + + +all: include-all libsrc-all tests-all + +install: install-doc install-support + +install-doc: docs-install + +install-data: data-install + +install-etc: etc-install + +install-include: include-install + +install-lib: libsrc-install install-include + +install-support: install-data install-etc + + +include-all: + (cd include && $(MAKE) ARCH="$(ARCH)" all) + +libsrc-all: include-all + (cd libsrc && $(MAKE) ARCH="$(ARCH)" all) + +tests-all: libsrc-all + (cd tests && $(MAKE) ARCH="$(ARCH)" all) + + +check: tests-all + (cd tests && $(MAKE) check) + +check-exhaustive: tests-all + (cd tests && $(MAKE) check-exhaustive) + +include-install: + (cd include && $(MAKE) ARCH="$(ARCH)" install) + +libsrc-install: libsrc-all + (cd libsrc && $(MAKE) ARCH="$(ARCH)" install) + +docs-install: + (cd docs && $(MAKE) install) + +data-install: + (cd data && $(MAKE) install) + +etc-install: + (cd etc && $(MAKE) install) + + +clean: + (cd include && $(MAKE) clean) + (cd libsrc && $(MAKE) clean) + (cd tests && $(MAKE) clean) + (cd docs && $(MAKE) clean) + (cd data && $(MAKE) clean) + (cd etc && $(MAKE) clean) + rm -f $(TRASH) + +distclean: + (cd include && $(MAKE) distclean) + (cd libsrc && $(MAKE) distclean) + (cd tests && $(MAKE) distclean) + (cd docs && $(MAKE) distclean) + (cd data && $(MAKE) distclean) + (cd etc && $(MAKE) distclean) + rm -f $(DISTTRASH) + +dependencies: + (cd libsrc && touch $(DEP) && $(MAKE) dependencies) +# (cd tests && touch $(DEP) && $(MAKE) dependencies) diff --git a/dcmiod/configure b/dcmiod/configure new file mode 100755 index 00000000..396668ee --- /dev/null +++ b/dcmiod/configure @@ -0,0 +1,56 @@ +#! /bin/sh + +parentdir=`pwd` +thisdir=$parentdir + +# The following test constructs relative path from the module +# directory to the configuration directory. If you know this path +# you can substitute this with +# configdir= +# It is very important that the configdir path is relative. + +configdir="configdir" + +while test "$parentdir" != "/" -a "$configdir" = "configdir"; do + if test -d "$parentdir/config" ; then + configdir=$parentdir/config + else + parentdir=`echo $parentdir | sed 's/\/[^\/]*$//'` + fi +done + +if test "$configdir" = "configdir" ; then + echo "Cannot find configure directory" + exit 1 +fi + +if test $# != 0; then + case $1 in + -a) + shift + cd "$configdir" + echo "running configure in config-directory" + ./configure $* + cd $thisdir + echo "running configure for this module" + sh "$configdir/confmod" --srcdir=. $* + ;; + -c) + shift + cd "$configdir" + echo "running configure in config-directory" + ./configure $* + ;; + *) + echo "running configure for this module" + sh "$configdir/confmod" --srcdir=. $* + ;; + esac +else + echo "running configure for this module" + sh "$configdir/confmod" --srcdir=. $* +fi + + + + diff --git a/dcmiod/data/Makefile.in b/dcmiod/data/Makefile.in new file mode 100644 index 00000000..24749772 --- /dev/null +++ b/dcmiod/data/Makefile.in @@ -0,0 +1,23 @@ +# +# Makefile for dcmiod/data +# + +@SET_MAKE@ + +SHELL = /bin/sh +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +configdir = @top_srcdir@/@configdir@ + +include $(configdir)/@common_makefile@ + + +all: + +install: + +clean: + rm -f $(TRASH) + +distclean: + rm -f $(DISTTRASH) diff --git a/dcmiod/docs/Makefile.in b/dcmiod/docs/Makefile.in new file mode 100644 index 00000000..f4ba0bbc --- /dev/null +++ b/dcmiod/docs/Makefile.in @@ -0,0 +1,23 @@ +# +# Makefile for dcmiod/docs +# + +@SET_MAKE@ + +SHELL = /bin/sh +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +configdir = @top_srcdir@/@configdir@ + +include $(configdir)/@common_makefile@ + + +all: + +install: + +clean: + rm -f $(TRASH) + +distclean: + rm -f $(DISTTRASH) diff --git a/dcmiod/docs/dcmiod.dox b/dcmiod/docs/dcmiod.dox new file mode 100644 index 00000000..515f452b --- /dev/null +++ b/dcmiod/docs/dcmiod.dox @@ -0,0 +1,23 @@ +/*! + +\page mod_dcmiod dcmiod: a library for working with information objects and modules + +This module contains classes that represent DICOM IOD (Information Object +Definitions) from part 3 of the DICOM Standard, including their modules and the +elements contained therein. They should ease reading, modifying and writing +IODs by offering an explicit API for this purpose. The requirements regarding +existence of elements and their values are pre-configured and can be adapted +during runtime. + +The main classes are (in alphabetical order): +\li \b DcmIODCommon +\li \b DcmIODImage +\li \b IODFoRModule +\li \b IODGeneralImageModule +\li \b IODGeneralSeriesModule +\li \b IODGeneralStudyModule +\li \b IODImagePixelModule +\li \b IODPatientModule +\li \b IODSOPCommonModule + +*/ diff --git a/dcmiod/etc/Makefile.in b/dcmiod/etc/Makefile.in new file mode 100644 index 00000000..86ad5f60 --- /dev/null +++ b/dcmiod/etc/Makefile.in @@ -0,0 +1,23 @@ +# +# Makefile for dcmiod/etc +# + +@SET_MAKE@ + +SHELL = /bin/sh +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +configdir = @top_srcdir@/@configdir@ + +include $(configdir)/@common_makefile@ + + +all: + +install: + +clean: + rm -f $(TRASH) + +distclean: + rm -f $(DISTTRASH) diff --git a/dcmiod/include/CMakeLists.txt b/dcmiod/include/CMakeLists.txt new file mode 100644 index 00000000..35db5574 --- /dev/null +++ b/dcmiod/include/CMakeLists.txt @@ -0,0 +1,2 @@ +# declare installation files +INSTALL(DIRECTORY dcmtk/dcmiod DESTINATION ${DCMTK_INSTALL_INCDIR}/dcmtk COMPONENT include FILES_MATCHING PATTERN "*.h" PATTERN "CVS" EXCLUDE) diff --git a/dcmiod/include/Makefile.in b/dcmiod/include/Makefile.in new file mode 100644 index 00000000..40cbb39a --- /dev/null +++ b/dcmiod/include/Makefile.in @@ -0,0 +1,27 @@ +# +# Makefile for dcmiod/include +# + +@SET_MAKE@ + +SHELL = /bin/sh +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +configdir = @top_srcdir@/@configdir@ + +include $(configdir)/@common_makefile@ + + +all: + +install: + $(configdir)/mkinstalldirs $(DESTDIR)$(includedir)/dcmtk/dcmiod + for file in dcmtk/dcmiod/*.h ; do \ + $(INSTALL_DATA) $$file $(DESTDIR)$(includedir)/dcmtk/dcmiod ;\ + done + +clean: + rm -f $(TRASH) + +distclean: + rm -f $(DISTTRASH) diff --git a/dcmiod/include/dcmtk/dcmiod/iodcommn.h b/dcmiod/include/dcmtk/dcmiod/iodcommn.h new file mode 100644 index 00000000..d4cd8721 --- /dev/null +++ b/dcmiod/include/dcmtk/dcmiod/iodcommn.h @@ -0,0 +1,225 @@ +/* + * + * Copyright (C) 2015, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmiod + * + * Author: Michael Onken + * + * Purpose: Class representing IODs by exposing common DICOM module attributes + * + */ + +#ifndef IODCOMMN_H +#define IODCOMMN_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmiod/iodrules.h" +#include "dcmtk/dcmiod/modpatient.h" +#include "dcmtk/dcmiod/modpatientstudy.h" +#include "dcmtk/dcmiod/modgeneralstudy.h" +#include "dcmtk/dcmiod/modequipment.h" +#include "dcmtk/dcmiod/modgeneralseries.h" +#include "dcmtk/dcmiod/modfor.h" +#include "dcmtk/dcmiod/modsopcommon.h" +#include "dcmtk/dcmiod/modcommoninstanceref.h" + +/** Interface class to those modules and data attributes are common for many + * DICOM IODs. The class offers a dedicated API for getting and settings those + * attributes. Modules included: Patient Module, General Study Module, General + * Equipment Module, General Series Module, Frame of Reference Module, SOP + * Common Module. + */ +class DCMTK_DCMIOD_EXPORT DcmIODCommon +{ + +public: + + /** Constructor + */ + DcmIODCommon(); + + /** Get rules handled by this IOD + * @return The rules + */ + OFshared_ptr getRules(); + + /** Get item managed by this IOD + * @return The item + */ + OFshared_ptr getData(); + + /** Get Patient Module + * @return Reference to Patient Module + */ + IODPatientModule& getPatient(); + + /** Get Patient Study Module + * @return Reference to Patient Study Module + */ + IODPatientStudyModule& getPatientStudy(); + + /** Get General Study Module + * @return Reference to General Study Module + */ + IODGeneralStudyModule& getStudy(); + + /** Get General Equipment Module + * @return Reference to General Equipment Module + */ + IODGeneralEquipmentModule& getEquipment(); + + /** Get Series Module + * @return Reference to General Series Module + */ + IODGeneralSeriesModule& getSeries(); + + /** Get Frame of Reference Module + * @return Reference to Frame of Reference Module + */ + IODFoRModule& getFrameOfReference(); + + /** Get SOP Common Module + * @return Reference to SOP Common Module + */ + IODSOPCommonModule& getSOPCommon(); + + /** Get Common Instance Reference Module + * @return Common Instance Reference Module + */ + IODCommonInstanceReferenceModule& getCommonInstanceReference(); + + /** Destructor + */ + virtual ~DcmIODCommon(); + + /** Clear (removes) all attributes handled by the modules of this IOD. + * IOD Rules are not reset. + */ + virtual void clearData(); + + /** Create new study. + * After generating a new Study Instance UID the method createNewSeries() is + * called, i.e.\ also a new Series Instance UID and SOP instance UID are + * generated. This is a requirement of the DICOM standard. All other + * study-related attributes from the study-level modules managed by this class + * are cleared (as well as Series and Instance level attributes). + * @param clearEquipment If OFTrue (default), also the equipment information is + * cleared (General Equipment Module)) + */ + virtual void createNewStudy(const OFBool clearEquipment = OFTrue); + + /** Create a new series. + * After generating a new Series Instance UID the method + * createNewSOPInstance() is called, i.e.\ Series-related attributes managed + * by the series-level modules of this class are cleared, as well as + * instance-level data. + * @param clearFoR If OFTrue (default), also the frame of reference is + * cleared (FoR Module) + */ + virtual void createNewSeries(const OFBool clearFoR = OFTrue); + + /** Create a new SOP instance. + * Generate a new SOP Instance UID and set the Instance Creation Date/Time + * to the current date and time. + * It could be used explicitly from the calling application if a new UID + * should be created (this is the case if the Study Instance UID or Series + * Instance UID has changed as well as any other attribute on the instance + * level, e.g.\ image pixel data). Also clears other instance related data. + */ + virtual void createNewSOPInstance(); + + /** Make sure that the IOD contains a SOP Instance, Series Instance and Study + * Instance UID. They are created if empty. Invalid UIDs are corrected if + * desired. + */ + virtual void ensureInstanceUIDs(const OFBool correctInvalid = OFFalse); + + /** Read data into this class. + * Please note that the current content is also deleted if the reading + * process fails. If the log stream is set and valid the reason for any + * error might be obtained from the error/warning output. The reading + * process will ignore missing attributes or values as possible in order + * to read as as much as possible. + * @param dataset DICOM dataset from which the document should be read + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition read(DcmItem &dataset); + + /** Import common module attributes from dataset but only read Patient, Study, + * Series and/or Frame of Reference level portions. The current content + * is not deleted before reading. If the log stream is set and valid the + * reason for any error might be obtained from the error/warning output. + * @param dataset Reference to DICOM dataset from which the document + * should be read + * @param readPatient Read Patient-level information if OFTrue + * @param readStudy Read Study-level information if OFTrue, including + * equipment module + * @param readFoR Read Frame of Reference information if OFTrue. See + * also readSeries parameter. + * @param readSeries Read Series-level information if OFTrue, always + * includes Frame of Reference, i.e.\ readFoR is + * considered to be OFTrue + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition import(DcmItem& dataset, + OFBool readPatient, + OFBool readStudy, + OFBool readFoR = OFFalse, + OFBool readSeries = OFFalse); + + /** Write the attributes managed by this class to DICOM dataset. + * @param dataset Reference to DICOM dataset to which the current document + * should be written. The dataset is not cleared + * before writing to it. + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition write(DcmItem &dataset); + + +private: + + /// The data hold by this class (shared with modules below) + OFshared_ptr m_Item; + + /// The rules hold by this class (shared with modules below) + OFshared_ptr m_Rules; + + /// Patient Module + IODPatientModule m_Patient; + + /// Patient Study Module + IODPatientStudyModule m_PatientStudy; + + /// General Study Module + IODGeneralStudyModule m_Study; + + /// General Equipment Module + IODGeneralEquipmentModule m_Equipment; + + /// General Series Module + IODGeneralSeriesModule m_Series; + + /// Frame of Reference Module + IODFoRModule m_FrameOfReference; + + /// SOP Common Module + IODSOPCommonModule m_SOPCommon; + + /// Common Instance Reference Module + IODCommonInstanceReferenceModule m_CommonInstanceReferenceModule; + + /// Collects all modules of this class for convenience (iteration) + OFVector m_Modules; +}; + +#endif // IODCOMMN_H diff --git a/dcmiod/include/dcmtk/dcmiod/ioddef.h b/dcmiod/include/dcmtk/dcmiod/ioddef.h new file mode 100644 index 00000000..1989579d --- /dev/null +++ b/dcmiod/include/dcmtk/dcmiod/ioddef.h @@ -0,0 +1,39 @@ +/* + * + * Copyright (C) 2015, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmiod + * + * Author: Michael Onken + * + * Purpose: Contains preprocessor definitions for dcmiod module + * + */ + + +#ifndef IODDEF_H +#define IODDEF_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/ofstd/ofdefine.h" + + +// Make sure DLL exports work for this module + +#ifdef dcmiod_EXPORTS +#define DCMTK_DCMIOD_EXPORT DCMTK_DECL_EXPORT +#else +#define DCMTK_DCMIOD_EXPORT DCMTK_DECL_IMPORT +#endif + + +#endif // IODDEF_H diff --git a/dcmiod/include/dcmtk/dcmiod/iodimage.h b/dcmiod/include/dcmtk/dcmiod/iodimage.h new file mode 100644 index 00000000..6b0ac4e7 --- /dev/null +++ b/dcmiod/include/dcmtk/dcmiod/iodimage.h @@ -0,0 +1,95 @@ +/* + * + * Copyright (C) 2015, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmiod + * + * Author: Michael Onken + * + * Purpose: Class repres. image IOD by exposing common image IOD attributes + * + */ + +#ifndef IODIMAGE_H +#define IODIMAGE_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmiod/iodcommn.h" +#include "dcmtk/dcmiod/modgeneralimage.h" +#include "dcmtk/dcmiod/modimagepixel.h" + +/** Class for managing common image IOD attributes. At the moment support for + * the palette-related attributes and the smallest/largest image pixel value + * attributes is still missing. Also, pixel data must be handled separately. + * Modules supported on top of DcmIODCommon: General Image Module and + * Image Pixel Module. + */ +class DCMTK_DCMIOD_EXPORT DcmIODImage : + public DcmIODCommon +{ + +public: + + /** Constructor + */ + DcmIODImage(); + + /** Get General Image Module + * @return Reference to General Image Module + */ + IODGeneralImageModule& getGeneralImage(); + + /** Get Image Pixel Module + * @return Reference to Image Pixel Module + */ + IODImagePixelModule& getImagePixel(); + + /** Virtual Destructor + */ + virtual ~DcmIODImage(); + + /** Clear (removes) all attributes handled by the modules of this IOD. + * IOD Rules are not reset. + */ + virtual void clearData(); + + /** Read common image module attributes (all those handled by this class) + * from given item. Reads attributes from base class DcmIODCommon before. + * The current content is deleted even if the reading process fails. + * If the log stream is set and valid the reason for any error might be + * obtained from the error/warning output. + * @param dataset Reference to DICOM dataset from which the document + * should be read + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition read(DcmItem &dataset); + + /** Write current common image module's attributes to DICOM dataset. Also + * writes attributes of base class DcmIODCommon afterwards. + * @param dataset Reference to DICOM dataset to which the current document + * should be written. The dataset is not cleared before writing + * to it! + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition write(DcmItem &dataset); + +private: + + /// General Image Module + IODGeneralImageModule m_GeneralImage; + + /// Image Pixel Module + IODImagePixelModule m_ImagePixel; + +}; + +#endif // IODIMAGE_H diff --git a/dcmiod/include/dcmtk/dcmiod/iodmacro.h b/dcmiod/include/dcmtk/dcmiod/iodmacro.h new file mode 100644 index 00000000..472e4af4 --- /dev/null +++ b/dcmiod/include/dcmtk/dcmiod/iodmacro.h @@ -0,0 +1,1274 @@ +/* + * + * Copyright (C) 2015, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmiod + * + * Author: Michael Onken + * + * Purpose: Collection of classes representing DICOM IOD macros + * + */ + +#ifndef IODMACRO_H +#define IODMACRO_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/ofstd/ofvector.h" +#include "dcmtk/ofstd/ofstring.h" +#include "dcmtk/dcmdata/dctk.h" // For VR classes, i.e. DcmCodeString etc. +#include "dcmtk/dcmiod/iodrules.h" +#include "dcmtk/dcmiod/modbase.h" + +/** Class representing a Code Sequence Macro + */ +class DCMTK_DCMIOD_EXPORT CodeSequenceMacro : public IODComponent +{ + +public: + + /** Constructor + * @param item The item to be used for data storage. If NULL, the + * class creates an empty data container. + * @param rules The rule set for this class. If NULL, the class creates + * one from scratch and adds its values. + * @param parent The parent of the IOD component (NULL if none or unknown) + */ + CodeSequenceMacro(OFshared_ptr item, + OFshared_ptr rules, + IODComponent* parent = NULL); + + /** Constructor + * @param parent The parent of the IOD component (NULL if none or unknown) + */ + CodeSequenceMacro(IODComponent* parent = NULL); + + /** Convenience constructor to set initial values + * @param item The item to be used for data storage. If NULL, the + * class creates an empty data container. + * @param rules The rule set for this class. If NULL, the class creates + * one from scratch and adds its values. + * @param parent The parent of the IOD component (NULL if none or unknown) + * @param codeValue The code value + * @param codingSchemeDesignator The coding scheme designator + * @param codeMeaning The code meaning + * @param codingSchemeVersion The coding scheme version (might be empty if + * coding scheme is unique) + */ + CodeSequenceMacro(OFshared_ptr item, + OFshared_ptr rules, + IODComponent* parent, + const OFString& codeValue, + const OFString& codingSchemeDesignator, + const OFString& codeMeaning, + const OFString& codingSchemeVersion = ""); + + /** Convenience constructor to set initial values + * @param codeValue The code value + * @param codingSchemeDesignator The coding scheme designator + * @param codeMeaning The code meaning + * @param codingSchemeVersion The coding scheme version (might be empty if + * coding scheme is unique) + * @param parent The parent of the IOD component (NULL if none or unknown) + */ + CodeSequenceMacro(const OFString& codeValue, + const OFString& codingSchemeDesignator, + const OFString& codeMeaning, + const OFString& codingSchemeVersion = "", + IODComponent* parent = NULL); + + /** Resets rules to their original values + */ + virtual void resetRules(); + + /** Get name of macro + * @return Name of the component ("CodeSequenceMacro") + */ + virtual OFString getName() const; + + /** Virtual Destructor + */ + virtual ~CodeSequenceMacro(); + + /** Get Code Value + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getCodeValue(OFString &value, + const signed long pos = 0); + + /** Get Coding Scheme Designator + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getCodingSchemeDesignator(OFString &value, + const signed long pos = 0); + + /** Get Coding Scheme Version + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getCodingSchemeVersion(OFString &value, + const signed long pos = 0); + + /** Get Code Meaning + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getCodeMeaning(OFString &value, + const signed long pos = 0); + /** Set Code Value + * @param value The value to set + * @param checkValue If OFTrue, VM and VR of value are checked + * @return EC_Normal if setting was successful, error otherwise + */ + virtual OFCondition setCodeValue(const OFString &value, + const OFBool checkValue = OFTrue); + + /** Set Coding Scheme Designator + * @param value The value to set + * @param checkValue If OFTrue, VM and VR of value are checked + * @return EC_Normal if setting was successful, error otherwise + */ + virtual OFCondition setCodingSchemeDesignator(const OFString &value, + const OFBool checkValue = OFTrue); + + /** Set Coding Scheme Version + * @param value The value to set + * @param checkValue If OFTrue, VM and VR of value are checked + * @return EC_Normal if setting was successful, error otherwise + */ + virtual OFCondition setCodingSchemeVersion(const OFString &value, + const OFBool checkValue = OFTrue); + + /** Set Code Meaning + * @param value The value to set + * @param checkValue If OFTrue, VM and VR of value are checked + * @return EC_Normal if setting was successful, error otherwise + */ + virtual OFCondition setCodeMeaning(const OFString &value, + const OFBool checkValue = OFTrue); + + /** Set all values in this class conveniently + * @param value Code Value to set + * @param scheme Coding Scheme Designator to set + * @param meaning Code Meaning to set + * @param schemeVersion The Coding Scheme Designator version to set + * (optional) + * @param checkValue If OFTrue, VM and VR of values is checked + * @return EC_Normal if setting was successful, error otherwise + */ + virtual OFCondition set(const OFString &value, + const OFString &scheme, + const OFString &meaning, + const OFString &schemeVersion = "", + const OFBool checkValue = OFTrue); + +}; + + +/** Class implementing the SOP Instance Reference Macro + */ +class DCMTK_DCMIOD_EXPORT SOPInstanceReferenceMacro : public IODComponent +{ + +public: + + /** Constructor + * @param item The item to be used for data storage. If NULL, the + * class creates an empty data container. + * @param rules The rule set for this class. If NULL, the class creates + * one from scratch and adds its values. + * @param parent The parent of the IOD component (NULL if none or unknown) + */ + SOPInstanceReferenceMacro(OFshared_ptr item, + OFshared_ptr rules, + IODComponent* parent = NULL); + + /** Constructor + * @param parent The parent of the IOD component (NULL if none or unknown) + */ + SOPInstanceReferenceMacro(IODComponent* parent = NULL); + + /** Virtual Destructor + */ + virtual ~SOPInstanceReferenceMacro(); + + /** Resets rules to their original values + */ + virtual void resetRules(); + + /** Get name of macro + * @return Name of the module ("SOPInstanceReferenceMacro") + */ + virtual OFString getName() const; + + /** Get Referenced SOP Class UID + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getReferencedSOPClassUID(OFString &value, + const signed long pos = 0); + /** Get Referenced SOP Instance UID + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getReferencedSOPInstanceUID(OFString &value, + const signed long pos = 0); + /** Set Referenced SOP Class UID + * @param value The value to set + * @param checkValue If OFTrue, the value is checked regarding VM and VR + * @return EC_Normal, if successful, error otherwise + */ + virtual OFCondition setReferencedSOPClassUID(const OFString& value, + const OFBool checkValue = OFTrue); + /** Set Referenced SOP Instance UID + * @param value The value to set + * @param checkValue If OFTrue, the value is checked regarding VM and VR + * @return EC_Normal, if successful, error otherwise + */ + virtual OFCondition setReferencedSOPInstanceUID(const OFString& value, + const OFBool checkValue = OFTrue); +}; + + +/** Class representing the Series and Instance Reference Macro + */ +class DCMTK_DCMIOD_EXPORT IODSeriesAndInstanceReferenceMacro : public IODComponent +{ + +public: + + // Forward declaration + class ReferencedSeriesItem; + + /** Constructor + * @param data The item to be used for data storage. If NULL, the + * class creates an empty data container. + * @param rules The rule set for this class. If NULL, the class creates + * one from scratch and adds its values. + * @param parent The parent of the IOD component (NULL if none or unknown) + */ + IODSeriesAndInstanceReferenceMacro(OFshared_ptr data, + OFshared_ptr rules, + IODComponent* parent = NULL); + + /** Constructor + * @param parent The parent component of this class (if applicable, might + * be NULL) + */ + IODSeriesAndInstanceReferenceMacro(IODComponent* parent = NULL); + + /** Virtual Destructor + */ + virtual ~IODSeriesAndInstanceReferenceMacro(); + + /** Read Series and Instance Reference Macro from given item + * @param source The item to read from + * @param clearOldData If OFTrue, old data is deleted before + * reading (default) + * @return EC_Normal if successful, error otherwise + */ + virtual OFCondition read(DcmItem& source, + const OFBool clearOldData = OFTrue); + + /** Write Series and Instance Reference Macro to given item + * @param destination The item to write to + * @return EC_Normal if successful, error otherwise + */ + virtual OFCondition write(DcmItem& destination); + + /** Get name of module ("SeriesAndInstanceReferenceMacro") + * @return Name of the module ("SeriesAndInstanceReferenceMacro") + */ + virtual OFString getName() const; + + /** Resets rules to their original values + */ + virtual void resetRules(); + + /** Clear (removes) all attributes handled by the modules of this component. + * Rules are not reset. + */ + virtual void clearData(); + + /** Return reference to list of Referenced Series items + * @return Reference to list of Reference Series Items + */ + OFVector& getReferencedSeriesItems(); + +private: + + /// Vector with all items of the Referenced Series Sequence + OFVector m_ReferencedSeriesItems; + + /// Name of this component ("SeriesAndInstanceReferenceMacro") + static const OFString m_ComponentName; + +}; + + +/** Class representing Items from the Referenced Series Sequence: + * + * [Referenced Series Sequence: (SQ, VM 1-n, Type 1C)] + * > Series Instance UID: (UI, 1, 1) + * > Referenced Instance Sequence: (SQ, 1-n, 1) + * >> SOP Instance Reference Macro + * + */ +class DCMTK_DCMIOD_EXPORT IODSeriesAndInstanceReferenceMacro::ReferencedSeriesItem : public IODComponent +{ + +public: + + /** Constructor + * @param item The item to be used for data storage. If NULL, the + * class creates an empty data container. + * @param rules The rule set for this class. If NULL, the class creates + * one from scratch and adds its values. + * @param parent The parent of the IOD component (NULL if none or unknown) + */ + ReferencedSeriesItem(OFshared_ptr item, + OFshared_ptr rules, + IODComponent* parent = NULL); + + /** Constructor + * @param parent The parent component of this class (if applicable, might + * be NULL) + */ + ReferencedSeriesItem(IODComponent* parent = NULL); + + /** Destructor + */ + virtual ~ReferencedSeriesItem(); + + /** Clear (removes) all attributes handled by the modules of this component. + * Rules are not reset. + */ + virtual void clearData(); + + /** Read Referenced Series Sequence item data from given item + * @param source The item to read from + * @param clearOldData If OFTrue, old data is cleared before reading + */ + virtual OFCondition read(DcmItem& source, + const OFBool clearOldData = OFTrue); + + /** Write this Referenced Series Sequence item data to given item + * @param destination The item to write to + * @return EC_Normal if successful, error otherwise + */ + virtual OFCondition write(DcmItem& destination); + + /** Resets rules to their original values. + */ + virtual void resetRules(); + + /** Get name of module ("SeriesAndInstanceReferenceMacro") + * @return Name of the module ("SeriesAndInstanceReferenceMacro") + */ + virtual OFString getName() const; + + /** Get Series Instance UID + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getSeriesInstanceUID(OFString &value, + const signed long pos = 0) const; + + /** Set Series Instance UID + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR and VM if enabled + * @return status EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setSeriesInstanceUID(const OFString& value, + const OFBool checkValue = OFTrue); + + /** Get content of the Referenced Instance Sequence + * @return Reference to the Referenced Instance Sequence content + */ + virtual OFVector& getReferencedInstanceItems(); + +private: + + /// The name of this component ("SeriesAndInstanceReferenceMacro") + static const OFString m_ComponentName; + + /// Vector containing the data of all items of the Referenced Instance Sequence + OFVector m_ReferencedInstanceSequence; +}; + + +/** Class representing the Image SOP Instance Reference Macro + * TODO: Change implementation to use IODComponent class inherited anyway + * from SOPInstanceReferenceMacro + */ +class DCMTK_DCMIOD_EXPORT ImageSOPInstanceReferenceMacro : public SOPInstanceReferenceMacro +{ + +public: + + /** Constructor + */ + ImageSOPInstanceReferenceMacro(); + + /** Virtual Destructor + */ + virtual ~ImageSOPInstanceReferenceMacro(); + + /** Comparison operator that compares the normalized value of this object + * with a given object of the same type + * @param rhs The right hand side of the comparison + * @return 0 If the object values are equal. + * -1 if either the value of the first component that does not match + * is lower in the rhs object, or all compared components match + * but the rhs component is shorter. Also returned if rhs cannot be + * casted to DcmAttributeTag. + * 1 if either the value of the first component that does not match + * is greater in the rhs object, or all compared components match + * but the rhs component is longer. + */ + virtual int compare(const IODComponent& rhs) const; + + /** Clear data + */ + virtual void clear(); + + /** Read Image SOP Instance Reference Macro from given item + * @param source The item to read from + * @param clearOldData If OFTrue (default), old data is cleared before reading + * @return EC_Normal if successful, error otherwise + */ + virtual OFCondition read(DcmItem& source, + const OFBool clearOldData = OFTrue); + + /** Write Image SOP Instance Reference Macrom to given item + * @param item The item to write to + * @return EC_Normal if successful, error otherwise + */ + virtual OFCondition write(DcmItem& item); + + /** Get Referenced Frame Number + * @param values Reference to variable in which the value should be stored + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getReferencedFrameNumber(OFVector &values); + + /** Get Referenced Segment Number + * @param values Reference to variable in which the value should be stored + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getReferencedSegmentNumber(OFVector &values); + + /** Set Referenced Frame Number + * @param values The frame numbers that shoule be referenced + * @param checkValue If OFTrue (default) the given values will be checked + * @return EC_Normal if successful, error otherwise + */ + virtual OFCondition setReferencedFrameNumber(const OFVector& values, + const OFBool checkValue = OFTrue); + /** Add a Referenced Frame Number + * @param value The frame number to add + * @param checkValue If OFTrue, consistency checks are performed (as possible) + * @return EC_Normal if succesful, error otherwise + */ + virtual OFCondition addReferencedFrameNumber(const Uint16& value, + const OFBool checkValue = OFTrue); + /** Set the Referenced Segment Numbers + * @param values The segment numbers to add + * @param checkValue If OFTrue, consistency checks are performed (as possible) + * @return EC_Normal if succesful, error otherwise + */ + virtual OFCondition setReferencedSegmentNumber(const OFVector& values, + const OFBool checkValue = OFTrue); + + /** Add a Referenced Segment Number + * @param value The segment number to add + * @param checkValue If OFTrue, consistency checks are performed (as possible) + * @return EC_Normal if succesful, error otherwise + */ + virtual OFCondition addReferencedSegmentNumber(const Uint16& value, + const OFBool checkValue = OFTrue); + +private: + + // DICOM attributes. + // The comments for each attribute describe "Name: (VR, VM, Type)". + // See DICOM standard for further reference. + + /// Referenced Frame Number: (IS, 1-n, 1C) + DcmIntegerString ReferencedFrameNumber; + + /// Referenced Segment Number: (US, 1-n, 1C) + DcmUnsignedShort ReferencedSegmentNumber; + +}; + + +/** Class representing an item within the the Primary Anatomic Structure Macro + */ +class DCMTK_DCMIOD_EXPORT PrimaryAnatomicStructureMacroItem +{ + +public: + + /** Constructor + */ + PrimaryAnatomicStructureMacroItem(); + + /** Copy constructor + * @param rhs The item to copy from + */ + PrimaryAnatomicStructureMacroItem(const PrimaryAnatomicStructureMacroItem& rhs); + + /** Virtual destructor + */ + virtual ~PrimaryAnatomicStructureMacroItem(); + + /** Clear (removes) all attributes handled by the modules of this component. + */ + virtual void clearData(); + + /** Check whether this component's data satisfies the underlying + * rules + * @param quiet If OFTrue, not error / warning messages will be produced. + * Only the returned error code will indicate error or OK. Per + * default, logging output is produced. + * @result EC_Normal if rules are satisfied, error otherwise + */ + virtual OFCondition check(const OFBool quiet = OFFalse); + + /** Return the Anatomic Structure Code + * @return Reference to the anatomic structure code + */ + virtual CodeSequenceMacro& getAnatomicStructure(); + + /** Return the Anatomic Structure Modifier Codes + * @return The Anatomic Structure Modifier Codes + */ + virtual OFVector& getAnatomicStructureModifier(); + + /** Reads Primary Anatomic Region Sequence Item from given item + * @param source The item to read from + * @param clearOldData If OFTrue, old data is cleared first, otherwise it is + * kept where not overwritten + * @return EC_Normal if successful, error otherwise + */ + virtual OFCondition read(DcmItem& source, + const OFBool clearOldData = OFTrue); + + /** Write Anatomic Region Sequence Item to given item + * @param item The item to write to + * @return EC_Normal if successful, error otherwise + */ + virtual OFCondition write(DcmItem& item); + + /** Assignment operator (performs deep copy) + * @param rhs The item to copy from + * @return result + */ + PrimaryAnatomicStructureMacroItem& operator=(const PrimaryAnatomicStructureMacroItem &rhs); + +private: + + /// Primary Anatomic Structure Sequence Item + CodeSequenceMacro m_AnatomicStructure; + + /// Primary Anatomic Structure Structure Modifier Sequence (SQ, 1-n, 3) + OFVector m_AnatomicStructureModifier; + +}; + + +/** Class representing the Primary Anatomic Structure Macro + */ +class DCMTK_DCMIOD_EXPORT PrimaryAnatomicStructureMacro +{ + +public: + + /** Constructor + */ + PrimaryAnatomicStructureMacro(); + + /** Copy constructor + * @param rhs The macro to copy from + */ + PrimaryAnatomicStructureMacro(const PrimaryAnatomicStructureMacro& rhs); + + /** Virtual destructor + */ + virtual ~PrimaryAnatomicStructureMacro(); + + /** Clear (removes) all attributes handled by the modules of this component. + */ + virtual void clearData(); + + /** Check whether this component's data satisfies the underlying + * rules + * @param quiet If OFTrue, not error / warning messages will be produced. + * Only the returned error code will indicate error or OK. Per + * default, logging output is produced. + * @result EC_Normal if rules are satisfied, error otherwise + */ + virtual OFCondition check(const OFBool quiet = OFFalse); + + /** Return Primary Anatomic Structure items + * @return Reference to items of this macro + */ + virtual OFVector& getPrimaryAnatomicStructure(); + + /** Reads Primary Anatomic Region Sequence (i.e.\ this macro) from given item + * @param source The item to read from + * @param clearOldData If OFTrue, old data is cleared first, otherwise it is + * kept where not overwritten + * @return EC_Normal if reading was fine, error otherwise + */ + virtual OFCondition read(DcmItem& source, + const OFBool clearOldData = OFTrue); + + /** Write Anatomic Region Sequence (i.e.\ this macro) to given item + * @param item The item to write to + * @return EC_Normal if writing was fine, error otherwise + */ + virtual OFCondition write(DcmItem& item); + + /** Assignment operator + * @param rhs The macro to copy from + * @result Reference to "this" object + */ + PrimaryAnatomicStructureMacro& operator=(const PrimaryAnatomicStructureMacro &rhs); + +private: + + /// Primary Anatomic Structure Sequence (SQ, 0-1, 3) + OFVector m_PrimaryAnatomicStructure; +}; + + +/** Class representing the General Anatomy Mandatory or Optional Macro + */ +class DCMTK_DCMIOD_EXPORT GeneralAnatomyMacro +{ + +public: + + /** Constructor + * @param type Type of Anatomic Region Sequence. Permitted values: If 1, + * the class represents the "General Anatomy Mandatory Macro", if + * type 2 then it behaves like the "General Anatomy Required Macro", + * and type 3 like the "General Anatomy Optional Macro". Other values + * are interpreted as type 3 (optional). + */ + GeneralAnatomyMacro(const OFString& type); + + /** Copy constructor + * @param rhs The macro to copy from + */ + GeneralAnatomyMacro(const GeneralAnatomyMacro& rhs); + + /** Virtual desctructor + */ + virtual ~GeneralAnatomyMacro(); + + /** Clear (removes) all attributes handled by the modules of this component. + */ + virtual void clearData(); + + /** Check whether this component's data satisfies the underlying + * rules + * @param quiet If OFTrue, not error / warning messages will be produced. + * Only the returned error code will indicate error or OK. Per + * default, logging output is produced (OFFalse). + * @result EC_Normal if rules are satisfied, error otherwise + */ + virtual OFCondition check(const OFBool quiet = OFFalse); + + /** Return Anatomic Region + * @return Reference to Anatomic Region Code + */ + virtual CodeSequenceMacro& getAnatomicRegion(); + + /** Return Anatomic Region Modifier Codes + * @return Reference to Anatomic Region Modifier codes + */ + virtual OFVector& getAnatomicRegionModifier(); + + /** Return anatomic structure + * @return Reference to anatomic structure macro + */ + virtual PrimaryAnatomicStructureMacro& getPrimaryAnatomicStructure(); + + /** Reads Anatomic Region Sequence and Primary Anatomic Structure Macro from + * given item + * @param source The item to read from + * @param clearOldData If OFTrue, old data is cleared before reading, + * otherwise it is kept/overwritten. + * @return EC_Normal if no error, error otherwise + */ + virtual OFCondition read(DcmItem& source, + const OFBool clearOldData = OFTrue); + + /** Write Anatomic Region Sequence and Primary Anatomic Structure Macro to + * given item + * @param item The item to write to + * @return EC_Normal if writing was successful, error otherwise + */ + virtual OFCondition write(DcmItem& item); + + /** Assignment operator (performs deep copy) + * @param rhs The macro to copy from + * @return Reference to "this" object + */ + GeneralAnatomyMacro& operator=(const GeneralAnatomyMacro &rhs); + +private: + + /// Type (1,2,3) of Anatomic Region Sequence. + OFString m_Type; // TODO: Make enum? + + /// Anatomic Region Sequence (SQ, 1, 1) (Code Sequence Macro within item of + /// Anatomic Region Sequence)) + CodeSequenceMacro m_AnatomicRegion; + + /// Anatomic Region Modifier Macro (within item of Anatomic Region Sequence) + OFVector m_AnatomicRegionModifier; + + /// Primary Anatomic Structure Macro (on the same level as Anatomic + /// Region Sequence) + PrimaryAnatomicStructureMacro m_PrimaryAnatomicStructure; +}; + + +/** Class representing the Algorithm Identification Macro + */ +class DCMTK_DCMIOD_EXPORT AlgorithmIdentificationMacro +{ + +public: + + /** Constructor + */ + AlgorithmIdentificationMacro(); + + /** Virtual destructor + */ + virtual ~AlgorithmIdentificationMacro(); + + /** Clear (removes) all attributes handled by the modules of this component. + */ + virtual void clearData(); + + /** Perform consistency checks + * @param quiet If OFTrue, not error / warning messages will be produced. + * Only the returned error code will indicate error or OK. Per + * default, logging output is produced (OFFalse). + * @result EC_Normal if rules are satisfied, error otherwise + */ + virtual OFCondition check(const OFBool quiet = OFFalse); + + /** Return Algorithm Family Code + * @return Reference to algorithm family code + */ + virtual CodeSequenceMacro& getAlgorithmFamilyCode(); + + /** Get Algorithm Name Code + * @return Algorithm Name Code + */ + virtual CodeSequenceMacro& getAlgorithmNameCode(); + + /** Get Algorithm Name + * @param value Reference variable to store the value to + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if value could be get, error otherwise + */ + virtual OFCondition getAlgorithmName(OFString& value, + const signed long pos = 0); + + /** Get Algorithm Version + * @param value Reference variable to store the value to + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if value could be get, error otherwise + */ + virtual OFCondition getAlgorithmVersion(OFString& value, + const signed long pos = 0); + + /** Get Algorithm Parameters + * @param value Reference variable to store the value to + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if value could be get, error otherwise + */ + virtual OFCondition getAlgorithmParameters(OFString& value, + const signed long pos = 0); + /** Get Algorithm Source + * @param value Reference variable to store the value to + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if value could be get, error otherwise + */ + virtual OFCondition getAlgorithmSource(OFString& value, + const signed long pos = 0); + + /** Set Algorithm Name + * @param value The value to be set + * @param checkValue If OFTrue, the given value is checked + * @return EC_Normal, if value could be set, error otherwise + */ + virtual OFCondition setAlgorithmName(const OFString& value, + const OFBool checkValue = OFTrue); + + /** Set Algorithm Version + * @param value The value to be set + * @param checkValue If OFTrue, the given value is checked + * @return EC_Normal, if value could be set, error otherwise + */ + virtual OFCondition setAlgorithmVersion(const OFString& value, + const OFBool checkValue = OFTrue); + + /** Set Algorithm Parameters + * @param value The value to be set + * @param checkValue If OFTrue, the given value is checked + * @return EC_Normal, if value could be set, error otherwise + */ + virtual OFCondition setAlgorithmParameters(const OFString& value, + const OFBool checkValue = OFTrue); + + /** Set Algorithm Source + * @param value The value to be set + * @param checkValue If OFTrue, the given value is checked + * @return EC_Normal, if value could be set, error otherwise + */ + virtual OFCondition setAlgorithmSource(const OFString& value, + const OFBool checkValue = OFTrue); + + /** Reads this macro from given item + * @param source The item to read from + * @param clearOldData If OFTrue, old data is cleared before reading, + * otherwise it is kept/overwritten + * @return EC_Normal if reading was successful, error otherwise + */ + virtual OFCondition read(DcmItem& source, + const OFBool clearOldData = OFTrue); + + /** Write this macro to given item + * @param item The item to write to + * @return EC_Normal if writing was succesful, error otherwise + */ + virtual OFCondition write(DcmItem& item); + +private: + + /// Code Sequence Macro from Algorithm Family Code Sequence (single item), + /// (SQ, VM 1, Type 1) + CodeSequenceMacro m_AlgorithmFamilyCode; + + /// Code Sequence Macro from Algorithm Name Code Sequence (single item) + /// (SQ, VM 1, Type 3) + CodeSequenceMacro m_AlgorithmNameCode; + + /// Algorithm Name: (LO, VM 1, Typ 1) + DcmLongString m_AlgorithmName; + + /// Algorithm Version: (LO, VM 1, Typ 1) + DcmLongString m_AlgorithmVersion; + + /// Algorithm Parameters: (LT, VM 1, Typ 3) + DcmLongText m_AlgorithmParameters; + + /// Algorithm Source: (LO, VM 1, Typ 3) + DcmLongString m_AlgorithmSource; +}; + + +/** Content Identification Macro + */ +class DCMTK_DCMIOD_EXPORT ContentIdentificationMacro +{ + +public: + + /** Class repsenting an Alternate Content Description item + */ + class DCMTK_DCMIOD_EXPORT AlternateContentDescriptionItem + { + public: + + /** Constructor + */ + AlternateContentDescriptionItem(); + + /** Virtual destructor + */ + virtual ~AlternateContentDescriptionItem(); + + /** Clear (removes) all attributes handled by the modules of this component. + */ + virtual void clearData(); + + /** Get Content Description + * @param value Reference variable to store the value to + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, error otherwise + */ + virtual OFCondition getContentDescription(OFString& value, + const signed long pos = 0); + /** Get Language Code + * @return Reference to the language code + */ + virtual CodeSequenceMacro& getLanguageCode(); + + /** Set Content Description + * @param value The value to set + * @param checkValue If OFTrue, consistency check is performed + * @result EC_Normal if setting was successful, error otherwise + */ + virtual OFCondition setContentDescription(const OFString& value, + const OFBool checkValue = OFTrue); + + /** Read Alternate Content Description Sequence item from given item + * @param source The item to read from + * @param clearOldData If OFTrue, old data is cleared before reading, + * otherwise it is kept/overwritten + * @result EC_Normal, if reading was successful, error otherwise + */ + virtual OFCondition read(DcmItem& source, + const OFBool clearOldData = OFTrue); + + /** Write alternate content description item to given item + * @param item The item to write to + * @result EC_Normal, if writing was successful, error otherwise + */ + virtual OFCondition write(DcmItem& item); + + private: + + /// Content Desctription: (LO, VM 1, Type 1) + DcmLongString m_ContentDescription; + + /// Item of Language Code Sequence: (SQ, VM 1, Type 1) + CodeSequenceMacro m_LanguageCode; + }; + + /** Constructor + */ + ContentIdentificationMacro(); + + /** Copy constructor + * @param rhs The macro to copy from (deep copy) + */ + ContentIdentificationMacro(const ContentIdentificationMacro& rhs); + + /** Assignment operator (deep copy) + * @param rhs The macro to copy from + * @return Reference to "this" object + */ + ContentIdentificationMacro& operator=(const ContentIdentificationMacro& rhs); + + /** Virtual destructor + */ + virtual ~ContentIdentificationMacro(); + + /** Get rules for this data structure + * @return Reference to the rules + */ + virtual IODRules& getIODRules(); + + /** Clear (removes) all attributes handled by the modules of this component. + */ + virtual void clearData(); + + /** Resets rules to their original values + */ + virtual void resetRules(); + + /** Check whether this component's data satisfies the underlying + * rules + * @param quiet If OFTrue, not error / warning messages will be produced. + * Only the returned error code will indicate error or OK. Per + * default, logging output is produced (OFFalse). + * @result EC_Normal if rules are satisfied, error otherwise + */ + virtual OFCondition check(const OFBool quiet = OFFalse); + + /** Get Instance Number + * @param value Variable to store the result to + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if value could be get, error otherwise + */ + virtual OFCondition getInstanceNumber(OFString& value, + const signed long pos = 0) const; + + /** Get Content Label + * @param value Variable to store the result to + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if value could be get, error otherwise + */ + virtual OFCondition getContentLabel(OFString& value, + const signed long pos = 0) const; + + /** Get Content Description + * @param value Variable to store the result to + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if value could be get, error otherwise + */ + virtual OFCondition getContentDescription(OFString& value, + const signed long pos = 0) const; + + /** Get Alternate Content Description items + * @return Reference to the items + */ + virtual OFVector& getAlternateContentDescription(); + + /** Get Content Creator Name + * @param value Variable to store the result to + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if value could be get, error otherwise + */ + virtual OFCondition getContentCreatorName(OFString& value, + const signed long pos = 0) const; + + /** Get Content Creator Identification Code + * @return Reference to code + */ + virtual CodeSequenceMacro& getContentCreatorIdentificationCode(); + + /** Set Instance Number + * @param value Value to be set + * @param checkValue If OFTrue, value is checked for validity + * @return EC_Normal if setting was successful, error otherwise + */ + virtual OFCondition setInstanceNumber(const OFString& value, + const OFBool checkValue = OFTrue); + + /** Set Content Label + * @param value Value to be set + * @param checkValue If OFTrue, value is checked for validity + * @return EC_Normal if setting was successful, error otherwise + */ + virtual OFCondition setContentLabel(const OFString& value, + const OFBool checkValue = OFTrue); + + /** Set Content Description + * @param value Value to be set + * @param checkValue If OFTrue, value is checked for validity + * @return EC_Normal if setting was successful, error otherwise + */ + virtual OFCondition setContentDescription(const OFString& value, + const OFBool checkValue = OFTrue); + + /** Set Content Creator Name + * @param value Value to be set + * @param checkValue If OFTrue, value is checked for validity + * @return EC_Normal if setting was successful, error otherwise + */ + virtual OFCondition setContentCreatorName(const OFString& value, + const OFBool checkValue = OFTrue); + + /** Reads Content Identification Macro from given item + * @param source The item to read from + * @param clearOldData If OFTrue, old data is cleared before reading, otherwise + * it is kept/overwritten + */ + virtual OFCondition read(DcmItem& source, + const OFBool clearOldData = OFTrue); + + /** Write Content Identification Macro to given item + * @param item The item to write to + * @return EC_Normal if successul, error otherwise + */ + virtual OFCondition write(DcmItem& item); + +private: + + // Instance Number: (IS, VM 1, Type 1) + DcmIntegerString m_InstanceNumber; + + /// Content Label: (CS, VM 1, Type 1) + DcmCodeString m_ContentLabel; + + /// Content Description: (LO, VM1, Type 1) + DcmLongString m_ContentDescription; + + // Alternate Content Description Sequence (VM 1-n, Type 3) + OFVector m_AlternateContentDescription; + + /// Content Creator's Name: (LO, VM 1, Type 2) + DcmPersonName m_ContentCreatorName; + + /// Content Creator's Identification Code Sequence + CodeSequenceMacro m_ContentCreatorIdentificationCode; + + /// IOD rules for this data structure + IODRules m_IODRules; +}; + + +/** Class representing the HL7 V2 Hierarchic Designator Macro + */ +class HL7HierarchicDesignatorMacro : public IODComponent +{ + +public: + + /** Constructor + * @param item The item to be used for data storage. If NULL, the + * class creates an empty data container. + * @param rules The rule set for this class. If NULL, the class creates + * one from scratch and adds its values. + * @param parent The parent of the IOD component (NULL if none or unknown) + */ + HL7HierarchicDesignatorMacro(OFshared_ptr item, + OFshared_ptr rules, + IODComponent* parent = NULL); + + /** Constructor + * @param parent The parent of the IOD component (NULL if none or unknown) + */ + HL7HierarchicDesignatorMacro(IODComponent* parent = NULL); + + /** Resets rules to their original values + */ + virtual void resetRules(); + + /** Get name of macro + * @return Name of the module ("HL7HierarchicDesignatorMacro") + */ + virtual OFString getName() const; + + /** Get Local Namespace Entity ID + * @param value Variable to store the result to + * @param pos The index (0..VM) of the value to get + * @return EC_Normal if value could be get, error otherwise + */ + virtual OFCondition getLocalNamespaceEntityID(OFString& value, + const signed long pos = 0) const; + + /** Get Universal Entity ID + * @param value Variable to store the result to + * @param pos The index (0..VM) of the value to get + * @return EC_Normal if value could be get, error otherwise + */ + virtual OFCondition getUniversalEntityID(OFString& value, + const signed long pos = 0) const; + + /** Get Universal Entity ID Type + * @param value Variable to store the result to + * @param pos The index (0..VM) of the value to get + * @return EC_Normal if value could be get, error otherwise + */ + virtual OFCondition getUniversalEntityIDType(OFString& value, + const signed long pos = 0) const; + + /** Set Local Namespace Entity ID + * @param value Value to be set + * @param checkValue If OFTrue, value is checkd for validity + * @return EC_Normal if setting was successful, error otherwise + */ + virtual OFCondition setLocalNamespaceEntityID(const OFString& value, + const OFBool checkValue = OFTrue); + + /** Set Universal Entity ID + * @param value Value to be set + * @param checkValue If OFTrue, value is checkd for validity + * @return EC_Normal if setting was successful, error otherwise + */ + virtual OFCondition setUniversalEntityID(const OFString& value, + const OFBool checkValue = OFTrue); + + /** Set Universal Entity ID Type + * @param value Value to be set + * @param checkValue If OFTrue, value is checkd for validity + * @return EC_Normal if setting was successful, error otherwise + */ + virtual OFCondition setUniversalEntityIDType(const OFString& value, + const OFBool checkValue = OFTrue); +}; + +/** Class representing the Mandatory View and Slice Progression Direction Macro + */ + +class MandatoryViewAndSliceProgressionDirectionMacro : public IODComponent +{ + +public: + + /** Constructor + * @param item The item to be used for data storage. If NULL, the + * class creates an empty data container. + * @param rules The rule set where this classes rules are added to. If NULL, + * the class creates an empty rule set. + * @param parent The parent of the IOD component (NULL if none or unknown) + */ + MandatoryViewAndSliceProgressionDirectionMacro(OFshared_ptr item, + OFshared_ptr rules, + IODComponent* parent = NULL); + + /** Constructor + * @param parent The parent of the IOD component (NULL if none or unknown) + */ + MandatoryViewAndSliceProgressionDirectionMacro(IODComponent* parent = NULL); + + /** Clear (removes) all attributes handled by the modules of this component. + */ + virtual void clearData(); + + /** Resets rules to their original values + */ + virtual void resetRules(); + + /** Get name of macro + * @return Name of the module ("MandatoryViewAndSliceProgressionDirectionMacro") + */ + virtual OFString getName() const; + + /** Read Mandatory View and Slice Progression Direction Macro from given item + * @param source The item to read from + * @param clearOldData If OFTrue (default), old data is cleared + * before reading + * @return EC_Normal if successful, error otherwise + */ + virtual OFCondition read(DcmItem& source, + const OFBool clearOldData = OFTrue); + + /** Write Mandatory View and Slice Progression Direction Macro to given item + * @param item The item to write to + * @return EC_Normal if successful, error otherwise + */ + virtual OFCondition write(DcmItem& item); + + /** Get View Code + * @return Reference to code + */ + virtual CodeSequenceMacro& getViewCode(); + + /** Get View Modifier Code + * @return Reference to code + */ + virtual OFVector& getViewModifierCode(); + + +protected: + + /// View Code Sequence (SQ, VM 1, type 1) + CodeSequenceMacro m_ViewCodeSequence; + + /// View Modifier Code Sequence (SQ, VM 1-n, type 2C) + OFVector m_ViewModifierCode; +}; + +#endif // IODMACRO_H diff --git a/dcmiod/include/dcmtk/dcmiod/iodrules.h b/dcmiod/include/dcmtk/dcmiod/iodrules.h new file mode 100644 index 00000000..455ac8fc --- /dev/null +++ b/dcmiod/include/dcmtk/dcmiod/iodrules.h @@ -0,0 +1,246 @@ +/* + * + * Copyright (C) 2015, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmiod + * + * Author: Michael Onken + * + * Purpose: Class for managing attribute rules as found in DICOM modules + * + */ + +#ifndef IODRULES_H +#define IODRULES_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/ofstd/ofstring.h" +#include "dcmtk/ofstd/ofmap.h" +#include "dcmtk/ofstd/ofcond.h" +#include "dcmtk/dcmdata/dctagkey.h" +#include "dcmtk/dcmiod/iodtypes.h" + +#define INCLUDE_OSTREAM // for debugging +#include "dcmtk/ofstd/ofstdinc.h" + + +class DcmItem; +class DcmTagKey; +class DcmElement; +class IODRule; + + +/** Class representing rules for a set of DICOM attributes, e.g.\ for + * all attributes of a module, macro or the like. At the moment + * attributes within sequences are not yet supported. + */ +class DCMTK_DCMIOD_EXPORT IODRules +{ + +public: + + /// iterator type to iterate over rule set + typedef OFMap::iterator iterator; + + /// const iterator type to iterate over rule set + typedef OFMap::const_iterator const_iterator; + + /** Constructor + */ + IODRules(); + + /** Returns deep copy of this object + * @return Deep copy of "this" object + */ + IODRules* clone(); + + /** Return iterator to first rule + * @return Iterator to the first rule + */ + iterator begin(); + + /** Return iterator to last rule + * @return Iterator to the last rule + */ + iterator end(); + + /** Adds rule to this rule set + * @param rule The rule to add (ownership is transferred to this class) + * @param overwriteExisting If OFTrue (default), an existing rule for the + * same attribute (tag) is overwritten, otherwise the rule is not + * taken over (and ownership stays with caller) + * @return OFTrue if rule could be added, error otherwise + */ + virtual OFBool addRule(IODRule* rule, + const OFBool overwriteExisting = OFFalse); + + /** Delete rule by given tag key + * @param key Tag of the attribute rule to be deleted + * @return OFTrue if a rule could be found and deleted, OFFalse otherwise + */ + virtual OFBool deleteRule(const DcmTagKey key); + + /** Get all rules that are marked belonging to a specific module + * @param moduleName The module name (e.g.\ "PatientModule") + * @return Vector with pointers to all the rules belonging to given module + */ + const OFVector getByModule(const OFString& moduleName); + + /** Get a rule by its tag + * @param key The tag to find the rule for + * @return The rule, if found, NULL otherwise + */ + IODRule* getByTag(const DcmTagKey& key) const; + + /** Clear all rules + */ + virtual void clear(); + + /** Dump rules to stream, useful for debugging + * @param out The stream to dump to + */ + virtual void dump(STD_NAMESPACE ostream &out); + + /** Destructor + */ + virtual ~IODRules(); + +private: + + /// Map that holds all rules, accessable by their tag key + OFMap m_Rules; +}; + + +/** Class representing a single rule, that refers to a single attribute. + * Each rule is uniquely identified by the attribute's tag key and includes + * information on the Value Multiplicity (VM) of the attribute, its type + * (1, 1C, 2,...), the module (e.g.\ "PatientModule") or structure (e.g. + * "CodeSequenceMacro") it belongs to, a default value and its private + * creator if it is a private attribute. On top, the Information Entity + * according to the DICOM Model of the Real World can be stored, e.g. + * "Patient" for the "PatientModule". + */ +class DCMTK_DCMIOD_EXPORT IODRule +{ +public: + + /** Constructor to create a new attribute rule + * @param key The tag key of the attribute + * @param VM The VM of the attribute (notation like in DICOM part 6, + * e.g.\ "1-n") + * @param type The "IOD type" of the attribute. + * Allowed values "1", "1C", "2", "2C" and "3" + * @param module The module or "component" this attribute belongs to + * @param ie The Information Entity the module belongs to + * @param defaultValue The default value (default: empty) + * @param privateCreator The private creator of the attribute if attribute + * (default: No private creator) + */ + IODRule(const DcmTagKey& key, + const OFString& VM, + const OFString& type, + const OFString& module, + const DcmIODTypes::IOD_IE ie, + const OFString& defaultValue = "", + const OFString& privateCreator = ""); + + /** Return deep copy of this object + * @return Deep copy of "this" object + */ + IODRule* clone(); + + /** Get tag key of the attribute rule + * @return The tag key of the rule + */ + virtual DcmTagKey getTagKey() const; + + /** Get private creator of the related attribute + * @return The private creator of the attribute + */ + virtual OFString getPrivateCreator() const; + + /** The requirement type of the attribute (1, 1C, 2, 2C or 3) + * @return The requirement type of the attribute + */ + virtual OFString getType() const; + + /** The VM of the attribute as noted in the DICOM standard part 6, + * e.g.\ "1-n" or "2" + * @return The VM + */ + virtual OFString getVM() const; + + /** Get module (or component name) the related attribute belongs to + * @return The module or component name (e.g.\ "PatientName" or + * "CodeSequenceMacro") + */ + virtual OFString getModule() const; + + /** Get default value of this attribute + * @return The default value (might be empty) + */ + virtual OFString getDefaultValue() const; + + /** Get Information Entity the related attribute belongs to + * @return The Information Entity (might be empty) + */ + virtual DcmIODTypes::IOD_IE getIE() const; + + /** Check whether the given item fulfills the requirements of + * this rule, i.e.\ the related attribute is checked within the + * given item + * @param item The item to check the attribute in + * @param quiet If OFTrue, no error or warning messages will be produced + * but only the return code will indicate OK or error. + * @return EC_Normal if this rule is fulfilled, error otherwise + */ + virtual OFCondition check(DcmItem& item, + const OFBool quiet = OFFalse); + + /** Virtual Destructor + */ + virtual ~IODRule(); + +private: + + /// Private undefined default constructor + IODRule(); + + /// Private undefined copy constructor + IODRule(const IODRule& rhs); + + /// Tag key + DcmTagKey m_Key; + + /// VM, see DcmElement::checkVM() for permitted values (e.g.\ "1-n") + OFString m_VM; + + /// Requirement type: 1, 1C, 2, 2C or 3 + OFString m_Type; + + /// Module (e.g.\ "PatientModule" or "component name", e.g.\ "CodeSequenceMacro" + OFString m_Module; + + /// The Inforamtion Entitity the related attribute belongs to according to the + /// DICOM Model of the Real World, e.g.\ "Patient" for the attribute + /// "Patient Name" + DcmIODTypes::IOD_IE m_IE; + + /// Default value for attribute + OFString m_DefaultValue; + + /// Private Creator (if private attribute) + OFString m_PrivateCreator; +}; + +#endif // IODRULES_H diff --git a/dcmiod/include/dcmtk/dcmiod/iodtypes.h b/dcmiod/include/dcmtk/dcmiod/iodtypes.h new file mode 100644 index 00000000..48e991e9 --- /dev/null +++ b/dcmiod/include/dcmtk/dcmiod/iodtypes.h @@ -0,0 +1,138 @@ +/* + * + * Copyright (C) 2015, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmiod + * + * Author: Michael Onken + * + * Purpose: Class for managing common types needed by dcmiod module + * + */ + +#ifndef IODTYPES_H +#define IODTYPES_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/oflog/oflog.h" +#include "dcmtk/dcmiod/ioddef.h" + +// ---------------------------------------------------------------------------- +// Define the loggers for this module +// ---------------------------------------------------------------------------- + +extern DCMTK_DCMIOD_EXPORT OFLogger DCM_dcmiodLogger; + +#define DCMIOD_TRACE(msg) OFLOG_TRACE(DCM_dcmiodLogger, msg) +#define DCMIOD_DEBUG(msg) OFLOG_DEBUG(DCM_dcmiodLogger, msg) +#define DCMIOD_INFO(msg) OFLOG_INFO(DCM_dcmiodLogger, msg) +#define DCMIOD_WARN(msg) OFLOG_WARN(DCM_dcmiodLogger, msg) +#define DCMIOD_ERROR(msg) OFLOG_ERROR(DCM_dcmiodLogger, msg) +#define DCMIOD_FATAL(msg) OFLOG_FATAL(DCM_dcmiodLogger, msg) + + +// ---------------------------------------------------------------------------- +// Error constants +// ---------------------------------------------------------------------------- + +extern DCMTK_DCMIOD_EXPORT const OFConditionConst IOD_EC_WrongSOPClass; +extern DCMTK_DCMIOD_EXPORT const OFConditionConst IOD_EC_MissingAttribute; +extern DCMTK_DCMIOD_EXPORT const OFConditionConst IOD_EC_MissingSequenceData; +extern DCMTK_DCMIOD_EXPORT const OFConditionConst IOD_EC_InvalidDimensions; +extern DCMTK_DCMIOD_EXPORT const OFConditionConst IOD_EC_CannotInsertFrame; +extern DCMTK_DCMIOD_EXPORT const OFConditionConst IOD_EC_InvalidPixelData; +extern DCMTK_DCMIOD_EXPORT const OFConditionConst IOD_EC_InvalidObject; +extern DCMTK_DCMIOD_EXPORT const OFConditionConst IOD_EC_CannotDecompress; +extern DCMTK_DCMIOD_EXPORT const OFConditionConst IOD_EC_NoSuchRule; +extern DCMTK_DCMIOD_EXPORT const OFConditionConst IOD_EC_InvalidLaterality; +extern DCMTK_DCMIOD_EXPORT const OFConditionConst IOD_EC_InvalidElementValue; + + +/** Class that wraps some constant definitions in the context of IODs + */ +class DCMTK_DCMIOD_EXPORT DcmIODTypes +{ + +public: + + /** Struct representing a single frame + */ + struct Frame + { + /// Array for the pixel data bytes + Uint8* pixData; + /// Number of pixel data bytes (i.e.\ Bits Allocated) + size_t length; + /// Destructor, frees memory + ~Frame() {delete[] pixData;pixData = NULL;} + }; + + /** IOD Information Entities (incomplete list, extended as needed) + */ + enum IOD_IE + { + /// Undefined Information Entity (i.e.\ no value set) + IE_UNDEFINED, + /// Patient Entity + IE_PATIENT, + /// Study Entity + IE_STUDY, + /// Series Entity + IE_SERIES, + /// Frame of Reference Entity + IE_FOR, + /// Equipment Entity + IE_EQUIPMENT, + /// Image Entity + IE_IMAGE, + //// Meta Entity: Instance covering image, waveform, etc. + IE_INSTANCE + }; + + /** Enumerated values for attribute "Laterality" + */ + enum IOD_LATERALITY + { + /// Undefined (e.g.\ value not set) + LATERALITY_UNDEFINED, + /// Left body part + LATERALITY_L, + /// Right body part + LATERALITY_R + }; + + /** Enhanced US Image Module: Image Type (first value) + */ + enum IOD_ENHUSIMAGETYPE + { + /// Unknown + IMAGETYPE_UNKNOWN, + /// ORIGINAL + IMAGETYPE_ORIGINAL, + /// DERIVED + IMAGETYPE_DERIVED + }; + +private: + + /** Private undefined default constructor + */ + DcmIODTypes() {}; + + /** Private undefined destructor + */ + ~DcmIODTypes() {}; + +}; + + +#endif // IODTYPES_H diff --git a/dcmiod/include/dcmtk/dcmiod/iodutil.h b/dcmiod/include/dcmtk/dcmiod/iodutil.h new file mode 100644 index 00000000..44323de0 --- /dev/null +++ b/dcmiod/include/dcmtk/dcmiod/iodutil.h @@ -0,0 +1,900 @@ +/* + * + * Copyright (C) 2015, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmiod + * + * Author: Michael Onken + * + * Purpose: Static helper functionality for dcmiod module + * + */ + +#ifndef IODUTIL_H +#define IODUTIL_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/ofstd/oftraits.h" // for OFremove_pointer +#include "dcmtk/ofstd/ofstring.h" +#include "dcmtk/dcmdata/dcelem.h" +#include "dcmtk/dcmdata/dcsequen.h" +#include "dcmtk/dcmdata/dcdatset.h" +#include "dcmtk/dcmdata/dcdatutl.h" +#include "dcmtk/dcmiod/ioddef.h" +#include "dcmtk/dcmiod/iodrules.h" +#include "dcmtk/dcmiod/iodtypes.h" + +/** Class with helper functions used within the dcmiod module (and beyond) + */ +class DCMTK_DCMIOD_EXPORT DcmIODUtil +{ + +public: + + /** Get element from dataset and check it for correct value multiplicity + * and type. + * @param dataset DICOM dataset from which the element should be retrieved. + * (Would be 'const' if the methods from 'dcmdata' would also + * (be 'const'.) + * @param delem DICOM element used to store the value (always creates + * a copy of the dataset element's value) + * @param vm Value multiplicity (according to the data dictionary) to be + * checked for. (See DcmElement::checkVM() for a list of valid + * values.) Interpreted as cardinality (number of items) for + * sequence attributes. + * @param type Value type (valid value: "1", "1C", "2", something else + * which is not checked) + * @param moduleName Optional module name to be printed (NULL: no module + * printed at all) + * @return EC_Normal if element could be retrieved and value is correct, + * an error code otherwise + */ + static OFCondition getAndCheckElementFromDataset(DcmItem &dataset, + DcmElement &delem, + const OFString &vm, + const OFString &type, + const char *moduleName = NULL); + + /** Get element from dataset and check it for correct value multiplicity and + * type. + * @param dataset DICOM dataset from which the element should be retrieved. + * (Would be 'const' if the methods from 'dcmdata' would also + * be 'const') + * @param tagKey Tag key of the element to get + * @param delem DICOM element that is set to a copy of the dataset's + * orinal element + * @param vm Value multiplicity (according to the data dictionary) to be + * checked for. (See DcmElement::checkVM() for a list of valid + * values.) Interpreted as cardinality (number of items) for + * sequence attributes. + * @param type Value type (valid value: "1", "1C", "2", something else + * which is not checked) + * @param moduleName Optional module name to be printed (NULL: no module + * printed at all) + * @return EC_Normal if element could be retrieved and value is correct, an + * error code otherwise + */ + static OFCondition getAndCheckElementFromDataset(DcmItem &dataset, + const DcmTagKey& tagKey, + DcmElement*& delem, + const OFString &vm, + const OFString &type, + const char *moduleName = NULL); + + /** Get element from dataset and check it for correct value multiplicity + * and type. + * @param dataset DICOM dataset from which the element should be retrieved. + * (Would be 'const' if the methods from 'dcmdata' would also + * be 'const'.) + * @param delem DICOM element used to store the value (always creates + * a copy of the value from the original element) + * @param rule Rule describing parameters to be checked on element + * @return EC_Normal if element could be retrieved and value is correct, an + * error code otherwise + */ + static OFCondition getAndCheckElementFromDataset(DcmItem &dataset, + DcmElement &delem, + const IODRule* rule); + + /** Get element from dataset and check it for correct value multiplicity + * and type. + * @param dataset DICOM dataset from which the element should be retrieved. + * (Would be 'const' if the methods from 'dcmdata' would also + * be 'const') + * @param delem DICOM element that is set to a copy of the dataset's + * orinal element + * @param rule Rule describing parameters to be checked on element. + * @return EC_Normal if element could be retrieved and value is correct, an + * error code otherwise + */ + static OFCondition getAndCheckElementFromDataset(DcmItem &dataset, + DcmElement*& delem, + const IODRule* rule); + + /** Get current date in DICOM 'DA' format (YYYYMMDD) + * @param dateString String used to store the current date. + * (empty string if current date could not be retrieved) + * @return Resulting character string + */ + static const OFString& currentDate(OFString &dateString); + + /** Get current time in DICOM 'TM' format (HHMMSS) + * The optional UTC notation (e.g.\ +0100) is currently not supported. + * @param timeString String used to store the current time + * (empty string if current time could not be retrieved) + * @return Resulting character string, empty if time could not be retrieved + */ + static const OFString& currentTime(OFString &timeString); + + /** Copy given element to the dataset + * The element is only added if 'result' is EC_Normal. A copy of the given + * element is created, i.e.\ the caller is responsible for deleting the + * original element handed to this function (if desired). + * @param result Reference to status variable (checked before adding and + * updated afterwards!) + * @param dataset Reference to DICOM dataset to which the element should + * be added + * @param delem Reference to DICOM element which should be added; a + * copy is created so caller is responsible for deleting delem (if + * desired). + * @param vm Value multiplicity (according to the data dictionary) to be + * checked for. (See DcmElement::checkVM() for a list of valid + * values.). Interpreted as cardinality (number of items) for + * sequence attributes. + * @param type Value type (valid value: "1", "2" or something else which + * is not checked) + * @param moduleName Optional module name to be printed (NULL: no module + * printed at all) + * @return Current value of 'result', EC_Normal if successful, + * an error code otherwise + */ + static OFCondition copyElementToDataset(OFCondition &result, + DcmItem &dataset, + const DcmElement &delem, + const OFString &vm, + const OFString &type, + const char *moduleName = NULL); + + /** Copy given element to the dataset. The element is only added if 'result' + * is EC_Normal. + * @param result reference to status variable (checked before adding and + * updated afterwards!) + * @param dataset reference to DICOM dataset to which the element + * should be added + * @param delem reference to DICOM element which should be added; the value + * is copied from the original dataset's element + * @param rule Rule describing parameters to be checked on element. + * @return Current value of 'result', EC_Normal if successful, an error code + * otherwise + */ + static OFCondition copyElementToDataset(OFCondition &result, + DcmItem &dataset, + const DcmElement &delem, + const IODRule* rule); + + /** Add given element to the dataset + * The element is only added if 'result' is EC_Normal and the 'delem' + * pointer is not NULL. + * @param result Reference to status variable (checked before adding and + * updated afterwards!) + * @param dataset Reference to DICOM dataset to which the element should + * be added + * @param delem Pointer to DICOM element which should be added. The element + * is always consumed by this function, i.e.\ insertion was succesful + * and therefore ownership is transferred to the dataset, or the + * element is deleted from memory if it could not be inserted. + * @param rule Rule describing parameters to be checked on element. + * @return Current value of 'result', EC_Normal if successful, an error code otherwise + */ + static OFCondition addElementToDataset(OFCondition &result, + DcmItem &dataset, + DcmElement *delem, + const IODRule* rule); + + /** Check element value for correct value multiplicity and type. + * @param delem Pointer to DICOM element to be checked (might be NULL) + * @param tagKey DICOM tag of the DICOM element the parameter 'delem' points to + * @param vm Value multiplicity (according to the data dictionary) to be checked for. + * (See DcmElement::checkVM() for a list of valid values.) + * Interpreted as cardinality (number of items) for sequence attributes. + * @param type Value type (valid value: "1", "1C", "2", something else) + * @param searchCond Optional flag indicating the status of a previous 'search' function call + * @param moduleName Optional module name to be printed (default: "IOD" if NULL) + * @return EC_Normal if element value is correct, error otherwise + */ + static OFCondition checkElementValue(const DcmElement *delem, + const DcmTagKey &tagKey, + const OFString &vm, + const OFString &type, + const OFCondition &searchCond = EC_Normal, + const char *moduleName = NULL); + + /** Check element value for correct value multiplicity and type. + * @param delem DICOM element to be checked + * @param vm Value multiplicity (according to the data dictionary) to be checked for. + * (See DcmElement::checkVM() for a list of valid values.) + * Interpreted as cardinality (number of items) for sequence attributes. + * @param type Value type (valid value: "1", "1C", "2", something else) + * @param searchCond Optional flag indicating the status of a previous 'search' function call + * @param moduleName Optional module name to be printed (default: "IOD" if NULL) + * @return EC_Normal if element value is correct, error otherwise + */ + static OFCondition checkElementValue(const DcmElement &delem, + const OFString &vm, + const OFString &type, + const OFCondition &searchCond = EC_Normal, + const char *moduleName = NULL); + + /** Get string value from element + * @param delem DICOM element from which the string value should be retrieved + * @param stringValue Reference to variable in which the result should be stored. + * (This parameter is automatically cleared if an error occurs.) + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + static OFCondition getStringValueFromElement(const DcmElement &delem, + OFString &stringValue, + const signed long pos); + + /** Get string value from item + * @param key The tag key of the attribute whose value should be retrieved + * @param item The item to search the attribute in + * @param result Reference to variable in which the result should be stored. + * (This parameter is automatically cleared if an error occurs.) + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + static OFCondition getStringValueFromItem(const DcmTagKey& key, + DcmItem& item, + OFString& result, + const signed long& pos); + + /** Get Float64 value from item + * @param key The tag key of the attribute whose value should be retrieved + * @param item The item to search the attribute in + * @param result Reference to variable in which the result should be stored. + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + static OFCondition getFloat64ValueFromItem(const DcmTagKey& key, + DcmItem& item, + Float64& result, + const unsigned long& pos); + + /** Get Float64 values from item + * @param key The tag key of the attribute whose value should be retrieved + * @param item The item to search the attribute in + * @param result Reference to variable in which the result should be stored. + * @return EC_Normal if successful, an error code otherwise + */ + static OFCondition getFloat64ValuesFromItem(const DcmTagKey& key, + DcmItem& item, + OFVector& result); + + /** Get Float64 value from element + * @param delem The element whose value should be retrieved + * @param result Reference to variable in which the result should be stored. + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + static OFCondition getFloat64ValueFromElement(const DcmElement &delem, + Float64& result, + const unsigned long pos); + + /** Get Float64 values from element + * @param delem The element to get the value from + * @param result Reference to variable in which the result should be stored. + * @return EC_Normal if successful, an error code otherwise + */ + static OFCondition getFloat64ValuesFromElement(const DcmElement &delem, + OFVector& result); + + /** Set a DcmElement's content from Uint16 vector + * @param delem DICOM element to be filled + * @param values Vector use as a source for the values + * @param vm Value multiplicity (according to the data dictionary) to be + * checked for. (See DcmElement::checkVM() for a list of + * valid values.) + * @param check If OFTrue, then it is checked whether number of values + * conforms to the value provided by the vm parameter. + * @return Dtatus, EC_Normal if successful, an error code otherwise + */ + static OFCondition setUint16ValuesOnElement(DcmElement &delem, + const OFVector& values, + const OFString& vm, + const OFBool check); + + /** Get Uint16 values from DcmElement + * @param delem DICOM element to read from + * @param values Vector used as destination for the values + * @return Status EC_Normal if successful, an error code otherwise + */ + static OFCondition getUint16ValuesFromElement(DcmElement &delem, + OFVector& values); + + /** Returns single item from given sequence. Returns error number of items + * is 0 or more than 1. + * @param seq Sequence to read from. + * @param item The resulting item, NULL in case of error + * @param checkKey If given it is checked whether the given seq parameter + * matches the tag key provided in the checkKey parameter. If + * not, an error is returned. + * @return Status EC_Normal if successful, an error code otherwise + */ + static OFCondition getAndCheckSingleItem(DcmSequenceOfItems& seq, + DcmItem*& item, + const DcmTagKey& checkKey = DCM_UndefinedTagKey); + + /** Copies Uint8 values from given element to destination container + * (must support push_back() method). + * @param elem the element to read from. If NULL, an error is returned. + * @param destination the container to store the Uint8 values to + * @return EC_Normal if successful, an error code otherwise + */ + template + static OFCondition copyFromUint8Array(DcmElement* elem, + Container& destination) + { + if (elem == NULL) + return EC_IllegalParameter; + + size_t vm = elem->getVM(); + OFCondition result; + for (size_t count = 0; (count < vm) && result.good(); count ++) + { + Uint8 value; + result = elem->getUint8(value, count); + if ( result.good() ) + { + destination.push_back(value); + } + } + if ( result.bad() ) + { + destination.clear(); + } + return result; + } + + /** Check whether SOP Sclass UID matches the expected value + * @param item Item to read from. NULL value causes error return value. + * @param desiredSOPClass The value that is expected + * @param valueFound The value actually found (empty if no value could + * be retrieved) + * @return EC_Normal if value could be found and equals exptected value, + * EC_TagNotFound if SOP Class UID is not found in dataset, + * EC_InvalidValue if SOP class differs from expected value. + */ + static OFCondition checkSOPClass(DcmItem* item, + const OFString& desiredSOPClass, + OFString& valueFound); + + /** Check whether given tag is a sequence tag + * @param key the tag key to be checked + * @param privateCreator The private creator to check for if tag is private + * @return OFTrue if given tag is a sequence tag, OFFalse otherwise + */ + static OFBool isSequenceTag(const DcmTagKey& key, + const OFString& privateCreator = ""); + + /** Reads items from DICOM sequence into container by creating a dedicated + * container item for each DICOM item. The container must support + * push_back(T) function and the container's element type T must support + * the read(DcmItem*) function. + * @param source The source sequence to read items from + * @param seqKey The sequence's tag key that is expected + * @param destination The destination container to read into + * @param cardinality Expected number of items. + * See DcmElement::checkVM() for a list of valid values. + * @param type The sequence type as noted in part 3 of the DICOM standard, + * i.e.\ "1,1C,2,2C or 3". + * @param module Name of the module/macro this sequence is contained in. Used + * for error messages and can also be left empty. + * @return EC_Normal if successful, an error code otherwise + */ + template + static OFCondition readSubSequence(DcmSequenceOfItems* source, + const DcmTagKey& seqKey, + Container& destination, + const OFString& cardinality, + const OFString& type, + const OFString& module) + { + OFCondition result; + OFCondition exists = EC_Normal; + if (!source) + exists = EC_TagNotFound; + + /* Check sequence and report errors as warnings, read anyway */ + checkElementValue(source, seqKey, cardinality, type, exists, module.c_str()); + if (source) + { + const size_t card = source->card(); + for (size_t count = 0; count < card; count++) + { + DcmItem *item = source->getItem(count); + if (item != NULL) + { + // define the element type + typedef typename OFremove_pointer::type Element; + Element *newElem = new Element(); + // read into container item (clears old data first) + if ( newElem != NULL) + { + result = (newElem)->read(*item, OFFalse /* no need to delete anything */); + if ( result.good() ) + { + destination.push_back(newElem); + } + else + { + delete newElem; + DCMIOD_WARN("Could not read item #" << count << " from " << DcmTag(source->getTag()).getTagName() << " (skipping item): " << result.text() ); + } + } + else + { + DCMIOD_ERROR("Could not store data from item #" << count << " from " << DcmTag(source->getTag()).getTagName() << " (skipping item): Memory exhausted?"); + } + } + else + { + DCMIOD_WARN("Could not get item #" << count << " from " << DcmTag(source->getTag()).getTagName() << " (malformed data or internal error), skipping item"); + } + } + } + else + { + result = EC_IllegalParameter; + } + return result; + } + + + /** Reads DICOM sequence into container by creating a dedicated container element + * for each DICOM item. The container must support push_back(T) function + * and the container's element type T must support the read(DcmItem*) function. + * @param source The source DICOM item read the sequence from + * @param seqKey The tag key of the sequence to be read + * @param destination The destination container to read into + * @param cardinality Eexpected number of items. + * See DcmElement::checkVM() for a list of valid values. + * @param type The sequence type as noted in part 3 of the DICOM standard, + * i.e.\ "1,1C,2,2C or 3". + * @param module Nname of the module/macro this sequence is contained in. Used + * for error messages and can also be left empty. + * @return status EC_Normal if successful, an error code otherwise + */ + template + static OFCondition readSubSequence(DcmItem& source, + const DcmTagKey& seqKey, + Container& destination, + const OFString& cardinality, + const OFString& type, + const OFString& module) + { + OFCondition result; + DcmSequenceOfItems *seq = NULL; + + /* Get sequence and read it */ + source.findAndGetSequence(seqKey, seq); + result = readSubSequence(seq, seqKey, destination, cardinality, type, module ); + return result; + } + + + /** Reads DICOM sequence into container by creating a dedicated container + * element for each DICOM item. The container must support the + * push_back(T) function and the container's element type T must support + * the read(DcmItem*) function. + * @param source The source DICOM item read the sequence from + * @param seqKey The tag key of the sequence to be read + * @param destination The destination container to read into + * @param rule The rule for reading this sequence. If NULL, an error is returned. + * @return EC_Normal if successful, an error code otherwise + */ + template + static OFCondition readSubSequence(DcmItem& source, + const DcmTagKey& seqKey, + Container& destination, + IODRule *rule) + { + if (rule == NULL) + { + DCMIOD_ERROR("Cannot read sequence " << seqKey << " (no rule supplied)"); + return IOD_EC_NoSuchRule; + } + return readSubSequence(source, seqKey, destination, rule->getVM(), rule->getType(), rule->getModule()); + } + + + /** Reads single DICOM item from a specific sequence into a destination class. + * The container must support the read(DcmItem) function. If a single item + * (i.e.\ the first item of the specified sequence) cannot be read, an error + * is returned. + * @param source The source DICOM item read the sequence from + * @param seqKey The tag key of the sequence to be read + * @param destination The destination container to read into + * See DcmElement::checkVM() for a list of valid values. + * @param type The sequence type as noted in part 3 of the DICOM standard, + * i.e.\ "1,1C,2,2C or 3". + * @param module Name of the module/macro this sequence is contained in. + * Used for error messages and can also be left empty. + * @return EC_Normal if successful, an error code otherwise + */ + template + static OFCondition readSingleItem(DcmItem& source, + const DcmTagKey& seqKey, + Container& destination, + const OFString& type, + const OFString& module) + { + OFCondition result; + /* Check sequence, reports cardinality and type errors as warnings */ + checkSubSequence(result, source, seqKey, "1", type, module); + + /* Try to read sequence into internal data (ignore errors as nuch as possible) */ + DcmItem* item = NULL; + result = source.findAndGetSequenceItem(seqKey, item, 0); + if (item != NULL) + { + // read into Code Sequence Macro (clears old data first) + result = destination.read(*item, OFTrue /* clear old data */); + } + return result; + } + + /** Reads single DICOM item from a specific sequence into a destination class. + * The container must support the read(DcmItem) function. If a single item + * (i.e.\ the first item of the specified sequence) cannot be read, an error + * is returned. + * @param source The source DICOM item read the sequence from + * @param seqKey The tag key of the sequence to be read + * @param destination The destination container to read into + * See DcmElement::checkVM() for a list of valid values. + * @param rule The rule (for the sequence) used for reading. + * @return EC_Normal if successful, an error code otherwise. If the rule + * equlas NULL, then nothing is read at all and an error is returned + * (IOD_EC_NoSuchRule), but no error is reported to the logger. + */ + template + static OFCondition readSingleItem(DcmItem& source, + const DcmTagKey& seqKey, + Container& destination, + IODRule *rule = NULL) + { + if (rule == NULL) + { + DCMIOD_DEBUG("Will not read sequence " << seqKey << ": No rule supplied"); + return IOD_EC_NoSuchRule; + } + + return readSingleItem(source, seqKey, destination, rule->getType(), rule->getModule()); + } + + /** Write given container into a DICOM sequence that is created within the + * given item. The sequence is created from scratch, i.e.\ any old sequence + * (and its items) will be overwritten. + * @param result If writing is successful, result will contain EC_Normal. + * Otherwise an error code is set. + * @param seqKey The tag key of the sequence to be write + * @param source The source container to read from. Must support the + * write(DcmItem*) function. + * @param destination The DICOM destination item to write the sequence to + * See DcmElement::checkVM() for a list of valid values. + * @param cardinality Expected number of items (i.e.\ expected number of + * elements in source container). See DcmElement::checkVM() for a + * list of valid values. + * @param type The sequence type as noted in part 3 of the DICOM standard, + * i.e.\ "1,1C,2,2C or 3". + * @param module Name of the module/macro this sequence is contained in. Used + * for error messages and can also be left empty. + * @return EC_Normal if successful, an error code otherwise + */ + template + static void writeSubSequence(OFCondition& result, + const DcmTagKey& seqKey, + Container& source, + DcmItem& destination, + const OFString& cardinality, + const OFString& type, + const OFString& module) + { + if ( result.good() ) + { + // Delete old data + destination.findAndDeleteElement(seqKey); + + // If we have meaningful data, write it + OFBool haveData = source.size() > 0; + if (haveData) + { + destination.insertEmptyElement(seqKey); + Uint32 count = 0; + typename Container::iterator it = source.begin(); + while ( it != source.end() && result.good() ) + { + if ( (*it) != NULL) + { + DcmItem *localItem = NULL; + // If item is NULL result.bad() is always true. + result = destination.findOrCreateSequenceItem(seqKey, localItem, -2 /* append new */); + if ( result.good() ) + { + result = (*it)->write(*localItem); + if ( result.bad() ) + { + destination.findAndDeleteSequenceItem(seqKey, -1 /* last */); + } + } + else + { + DCMIOD_ERROR("Could not insert item data #" << count << " of " << DcmTag(seqKey).getTagName() << " (internal error), ignoring"); + } + } + else + { + DCMIOD_ERROR("Found uninitialized container item (NULL value) for sequence " << DcmTag(seqKey).getTagName() << " (internal error, skipping)"); + } + count++; + it++; + } + } + // If we do not have data, create empty sequence if type 2 + else if (type == "2") + { + destination.insertEmptyElement(seqKey); + } + + // Check result + checkSubSequence(result, destination, seqKey, cardinality, type, module); + + // Clean up if we did not have success */ + if (result.bad()) + { + destination.findAndDeleteElement(seqKey); + } + } + } + + /** Write given container into a DICOM sequence that is created within the given item. + * The container. The sequence is created from scratch, i.e.\ any old sequence + * (and its items) will be overwritten. + * @param result If writing is successful, result will contain EC_Normal. Otherwise + * an error code is set. + * @param seqKey The tag key of the sequence to be write + * @param source The source container to read from. Must support the write(DcmItem*) + * function. + * @param destination The DICOM destination item to write the sequence to + * @param rule Rule describing the requirements for this sequence. If NULL + * an error is returned (IOD_EC_NoSuchRule), but no error error is reported + * to the logger. + * @return EC_Normal if successful, an error code otherwise + */ + template + static void writeSubSequence(OFCondition& result, + const DcmTagKey& seqKey, + Container& source, + DcmItem& destination, + IODRule* rule) + { + if ( result.good() ) + { + if (rule == NULL) + { + DCMIOD_DEBUG("Will not write sequence " << seqKey << ": No rule supplied"); + result = IOD_EC_NoSuchRule; + } + else + { + writeSubSequence(result, rule->getTagKey(), source, destination, rule->getVM(), rule->getType(), rule->getModule()); + } + } + } + + + /** Writes given container into a DICOM item of a specific sequence. The + * sequence is created from scratch so that any old information will be lost. + * @param result If writing is successful, result will contain EC_Normal. + * Otherwise an error code is set. + * @param seqKey The tag key of the sequence to be written + * @param source The source container to read from. Must support the write(DcmItem*) + * function. + * @param destination The DICOM item that should hold the sequence + * (with a single item) in the end. + * @param type The sequence type as noted in part 3 of the DICOM standard, + * i.e.\ "1,1C,2,2C or 3". + * @param module Name of the module/macro this sequence is contained in. + * Used for error messages and can also be left empty. + * @return EC_Normal if successful, an error code otherwise + */ + template + static void writeSingleItem(OFCondition& result, + const DcmTagKey& seqKey, + Container& source, + DcmItem& destination, + const OFString& type, + const OFString& module) + { + if ( result.good() ) + { + // Delete old data + destination.findAndDeleteElement(seqKey); + + /* If we have data, write it */ + OFCondition haveData = source.check(OFTrue /* Be quiet */); + if (haveData.good()) + { + DcmItem *localItem = NULL; + // If item is NULL result.bad() is always true. + result = destination.findOrCreateSequenceItem(seqKey, localItem, 0); + if ( result.good() ) + { + result = source.write(*localItem); + // It can happen that check() returns OK but no elements have to be + // written at all (e.g.\ if it contains only type 3 attributes). In that + // case a sequence with a single empty item is written which must be removed + // afterwards. + if (result.good() && (localItem->card() == 0) ) + { + destination.findAndDeleteElement(seqKey); + } + } + } + /* If we do not have data, insert empty for type 2 */ + else if (type == "2") + { + destination.insertEmptyElement(seqKey); + } + else if (type == "1C") + { + DCMIOD_TRACE("Skipping type 1C sequence " << seqKey << ": No data or imcomplete data available"); + } + } + + /* Check outcome */ + checkSubSequence(result, destination, seqKey, "1", type, module); + } + + /** Writes given container into a DICOM item of a specific sequence. + * The sequence is created from scratch so that any old information + * will be lost. + * @param result If writing is successful, result will contain EC_Normal. + * Otherwise an error code is set. + * @param seqKey The tag key of the sequence to be written + * @param source The source container to read from. Must support the + * write(DcmItem*) function. + * @param destination The DICOM item that should hold the sequence + * (with a single item) in the end. + * @param rule The rule for writing the given sequence + * @return EC_Normal if successful, an error code otherwise + */ + template + static void writeSingleItem(OFCondition& result, + const DcmTagKey& seqKey, + Container& source, + DcmItem& destination, + IODRule *rule) + { + if (rule == NULL) + { + DCMIOD_ERROR("Cannot write sequence " << seqKey << " (no rule supplied)"); + result = EC_CannotCheck; + } + writeSingleItem(result, seqKey, source, destination, rule->getType(), rule->getModule()); + } + + + /** Check whether a given sequence exists in a given item and whether it conforms to + * to its requirement type + * @param result If sequence is valid, result is set to EC_Normal, otherwise + * to an error. + * @param surroundingItem The item that should contain the given sequence. + * @param seqKey The sequence to look for + * @param cardinality Expected number of items (i.e.\ expected number of + * elements in source container). See DcmElement::checkVM() for a + * list of valid values. + * @param type The sequence type as noted in part 3 of the DICOM standard, + * i.e.\ "1,1C,2,2C or 3". + * @param module Name of the module/macro this sequence is contained in. + * Used for error messages and can also be left empty. + * @return EC_Normal if successful, an error code otherwise + */ + static void checkSubSequence(OFCondition& result, + DcmItem& surroundingItem, + const DcmTagKey& seqKey, + const OFString& cardinality, + const OFString& type, + const OFString& module); + + /** Deletes all elements from given container and calls "delete" on each + * of them to clear memory. + * @param container The container that should be cleared. Must contain + * pointers to objects that are allocated on the heap. + */ + template + static void freeContainer(Container& container) + { + typename Container::iterator it = container.begin(); + while (it != container.end()) + { + delete *it; + it++; + } + container.clear(); + } + + /** Clones and copies all elements from source to destination container by + * copy constructing all elements. + * @param src The container that should be copied. Must contain pointers + * to objects that are allocated on the heap, and that are + * copy-constructable + * @param dst The container to copy the cloned elements to. + */ + template + static void copyContainer(const Container& src, Container& dst) + { + typedef typename OFremove_pointer::type Element; + typename Container::const_iterator it = src.begin(); + while (it != src.end()) + { + if (*it != NULL) + { + Element *elem = new Element(**it); + dst.push_back ( elem ); + } + else + { + DCMIOD_ERROR("Could not copy element while copying container: Element is NULL, skipping"); + } + it++; + } + } + + /** Function that takes a string representation of a tag key and + * converts it to a tag key instance if possible + * @param keyString String of the format "(gggg,eeee)" + * @return The tag key if it could be parsed, DCM_UndefinedTagKey is returned + * instead (0xffff,0xffff) + */ + static const DcmTagKey parseTagKey(const OFString& keyString); + + /** Decompress given dataset if possible. Decompression codecs have to be + * registered beforehand. + * @param dset The dataset to decompress + * @return EC_Normal if decompression works, error otherwise + */ + static OFCondition decompress(DcmDataset& dset); + + /** Create new Unique Identifier (UID) + * @param level 0: instance level, 1: Series level, >=2: Study level. + * Calling always with level=0 is not an error but will result + * in unique values, too. + * @return The UID created. + */ + static OFString createUID(const Uint8 level = 0); + +private: + + // We only have static functions so we do not need an instance of + // this class so far. + + /** Undefined default constructor (only static functions) + */ + DcmIODUtil(); + + /** Undefined desctructor + */ + ~DcmIODUtil(); +}; + +#endif // IODUTIL_H diff --git a/dcmiod/include/dcmtk/dcmiod/modacquisitioncontext.h b/dcmiod/include/dcmtk/dcmiod/modacquisitioncontext.h new file mode 100644 index 00000000..77a34e1d --- /dev/null +++ b/dcmiod/include/dcmtk/dcmiod/modacquisitioncontext.h @@ -0,0 +1,74 @@ +/* + * + * Copyright (C) 2015, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmiod + * + * Author: Michael Onken + * + * Purpose: Class for managing the Acquisition Context Module + * + */ + +#ifndef MODACQUISITIONCONTEXT_H +#define MODACQUISITIONCONTEXT_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmdata/dctk.h" +#include "dcmtk/dcmiod/iodrules.h" +#include "dcmtk/dcmiod/modbase.h" + +/** Class representing the Acquisition Context Module. At the moment + * only an empty Acquisition Context Sequence is supported, so this + * class servers more as a placeholder at the moment. + * + * Acquisition Context Sequence: (SQ, 1-n, 2) + * + */ +class DCMTK_DCMIOD_EXPORT IODAcquisitionContextModule : public IODModule +{ + +public: + + /** Constructor + * @param item The item to be used for data storage. If NULL, the + * class creates an empty data container. + * @param rules The rule set where this classes rules are added to. If NULL, the + * class creates an empty rule set. + */ + IODAcquisitionContextModule(OFshared_ptr item, + OFshared_ptr rules); + + /** Constructor + */ + IODAcquisitionContextModule(); + + /** Destructor + */ + virtual ~IODAcquisitionContextModule(); + + /** Resets rules to their original values + */ + virtual void resetRules(); + + /** Get name of module ("AcquisitionContextModule") + * @return Name of the module ("AcquisitionContextModule") + */ + virtual OFString getName() const; + +private: + + /// The name of this module ("AcquisitionContextModule") + static const OFString m_ModuleName; +}; + +#endif // MODACQUISITIONCONTEXT_H diff --git a/dcmiod/include/dcmtk/dcmiod/modbase.h b/dcmiod/include/dcmtk/dcmiod/modbase.h new file mode 100644 index 00000000..25271330 --- /dev/null +++ b/dcmiod/include/dcmtk/dcmiod/modbase.h @@ -0,0 +1,229 @@ +/* + * + * Copyright (C) 2015, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmiod + * + * Author: Michael Onken + * + * Purpose: Abstract base class for IOD Modules or other attribute collections + * + */ + +#ifndef MODBASE_H +#define MODBASE_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/ofstd/ofmem.h" +#include "dcmtk/ofstd/ofvector.h" +#include "dcmtk/dcmdata/dcitem.h" +#include "dcmtk/dcmiod/ioddef.h" +#include "dcmtk/dcmiod/iodrules.h" + +/** Class for managing sets of dicom attributes (e.g.\ macros and modules). + * The data is hold in a container (DcmItem) that can be shared with other + * components, i.e.\ different modules that hold their data in a common + * container. In order to know which attributes in the container should be + * actually handled by a component, the component also has a set of rules, which + * can also be shared between different components (e.g.\ all modules of an IOD + * can share the same set of rules). For each attribute there is one rule in + * the rule set, denoting the requirement type (1,2,3,1C,2C), the VM, and + * besides others also the name of the component that the attribute belongs + * to (e.g.\ "PatientModule"). Since the component knows its own name, it can + * decide which attributes in the data container it is responsible for. + * This class is meant to support nested substructures but so far only writes + * attributes on a single level (including sequences). Also, in this context + * the class carries a parent relationship which is not used at the moment. + */ +class DCMTK_DCMIOD_EXPORT IODComponent +{ + +public: + + /** Constructor + * @param item The item to be used for data storage. If NULL, the + * class creates an empty data container. + * @param rules The rule set for this class. If NULL, the class creates + * an empty rule set. + * @param parent The parent of the IOD component (NULL if none or unknown) + */ + IODComponent(OFshared_ptr item, + OFshared_ptr rules, + IODComponent* parent = NULL); + + /** Constructor, creates rules and item from scratch. + * @param parent The parent of the IOD component (NULL if none or unknown) + */ + IODComponent(IODComponent* parent = NULL); + + /** Assignment operator, copies contained item and rule set from rhs to + * "this" attribute set. Produces clone copy, i.e.\ the contained item + * and the rule set is copied. The parent component is set to NULL. + * @param rhs The IODComponent to be assigned + * @return Reference to this module + */ + IODComponent& operator=(const IODComponent& rhs); + + + /** Copy constructor, copies reference to contained item and + * rule set to "this" attribute set. + * @param rhs The component to be assigned + */ + IODComponent(const IODComponent& rhs); + + /** Virtual Destructor + */ + virtual ~IODComponent(); + + /** Clear all attributes from the data that are handled by this module. + * An attribute is considered belonging to the module if there are rules + * marked as belonging to this module via the rule's module name. + */ + void clearData(); + + /** Set missing values by inventing "default values". Automatically + * called during write() in IODComponent; does nothing in this base + * class implementation but can be overwritten by derived classes if + * default values are desired. + */ + virtual void inventMissing(); + + /** Resets rules to their original values + */ + virtual void resetRules() =0; + + /** Get rules handled by this module + * @return The rules + */ + OFshared_ptr getRules() + { + return m_Rules; + } + + /** Get name of component + * @return Name of the module + */ + virtual OFString getName() const =0; + + /** Get the data handled by this module + * @return The item containing the data of this module + */ + DcmItem& getData() + { + return *m_Item; + } + + /** Read attributes from given item into this class + * @param source The source to read from + * @param clearOldData If OFTrue, old data is cleared before reading. Otherwise + * old data is overwritten (or amended) + * @result EC_Normal if reading was successful, error otherwise + */ + virtual OFCondition read(DcmItem& source, + const OFBool clearOldData = OFTrue); + + /** Write attributes from this class into given item + * @param destination The item to write to + * @result EC_Normal if writing was successful, error otherwise + */ + virtual OFCondition write(DcmItem& destination); + + /** Check whether this component's data satisfies the underlying + * rules + * @param quiet If OFTrue, not error / warning messages will be produced. Only + * the returned error code will indicate error or OK. Per default, + * logging output is produced (OFFalse). + * @result EC_Normal if rules are satisfied, error otherwise + */ + virtual OFCondition check(const OFBool quiet = OFFalse); + + /** Comparison operator for IOD Components + * @param rhs The right hand side of the comparison + * @return 0, if the given object is equal to this object, other value otherwise + */ + virtual int compare(const IODComponent& rhs) const; + + /** Static helper function that reads attributes from given + * item into destination item, as determined by the provided + * rules and component name. The rules are only applied when reading + * from the source (which may result in warning messages on the logger), + * but if they could be found they are taken over into the destination + * item no matter whether the element validates against the rule. + * @param source The item to read from + * @param rules The rules that provide the attributes and requirements + * for these attributes + * @param destination The destination to write to + * @param componentName The name of the module/component to write + * @result EC_Normal if reading was successful, error otherwise + */ + static OFCondition read(DcmItem& source, + IODRules& rules, + DcmItem& destination, + const OFString& componentName); + + /** Static helper function that writes attributes from given + * item into destination item, as determined by the provided + * rules and component name. The rules are only applied when writing + * to the destination (which may result in warning messages on the logger, + * and the whole call returning with an error). During reading from the + * source item the elements read are not validated against the rules. + * @param source The item to read from + * @param rules The rules that provide the attributes and requirements + * for these attributes + * @param destination The destination to write to + * @param componentName The name of the module/component to write + * @result EC_Normal if reading was successful, error otherwise + */ + static OFCondition write(DcmItem& source, + IODRules& rules, + DcmItem& destination, + const OFString& componentName); +protected: + + /// Shared pointer to the data handled by this class. The item may contain + /// more attributes than this class is actually responsible for + OFshared_ptr m_Item; + + /// Rules describing the attributes governed by this class + OFshared_ptr m_Rules; + + /// The parent component (may be NULL) of this class + IODComponent* m_Parent; +}; + + +/** The class IODModule is an IODComponent without parent component since + * a module does always belong to the top level dataset. + */ +class DCMTK_DCMIOD_EXPORT IODModule : public IODComponent +{ +public: + + /** Constructor. Similar to the one of IODComponent but no parent + * can be defined since a module is always at top level. + * @param item The item to be used for data storage. If NULL, the + * class creates an empty data container. + * @param rules The rule set for this class. If NULL, the class creates + * an empty rule set. + */ + IODModule(OFshared_ptr item, + OFshared_ptr rules); + + /** Constructor. Creates new empty data container and new empty + * ruleset. No parent component is defined (since a module is always + * on top level. + */ + IODModule(); +}; + +#endif //MODBASE_H + diff --git a/dcmiod/include/dcmtk/dcmiod/modcommoninstanceref.h b/dcmiod/include/dcmtk/dcmiod/modcommoninstanceref.h new file mode 100644 index 00000000..f922fae9 --- /dev/null +++ b/dcmiod/include/dcmtk/dcmiod/modcommoninstanceref.h @@ -0,0 +1,210 @@ +/* + * + * Copyright (C) 2015, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmiod + * + * Author: Michael Onken + * + * Purpose: Class for managing the Common Instance Reference Module + * + */ + +#ifndef MODCOMMONINSTANCEREF_H +#define MODCOMMONINSTANCEREF_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/ofstd/ofmem.h" +#include "dcmtk/ofstd/ofvector.h" +#include "dcmtk/dcmdata/dctk.h" +#include "dcmtk/dcmiod/iodrules.h" +#include "dcmtk/dcmiod/modbase.h" +#include "dcmtk/dcmiod/iodmacro.h" + + +/** Class representing the Common Instance Reference Module: + * + * Referenced Series Sequence: (SQ, VM 1-n, Type 1C) + * > Series Instance UID: (UI, 1, 1) + * > Referenced Instance Sequence: (SQ, 1-n, 1) + * >> SOP Instance Reference Macro + * Studies Containing Other Referenced Instances Sequence: (SQ, 1-n, 1C) + * > Study Instance UID (UI, 1, 1) + * > Series and Instance Reference Macro + * + */ +class DCMTK_DCMIOD_EXPORT IODCommonInstanceReferenceModule : public IODModule +{ + +public: + + // Forward declaration (class defined later in this file) + class StudiesOtherInstancesItem; + + /** Constructor + * @param item The item to be used for data storage. If NULL, the + * class creates an empty data container. + * @param rules The rule set for this class. If NULL, the class creates + * one from scratch and adds its values. + */ + IODCommonInstanceReferenceModule(OFshared_ptr item, + OFshared_ptr rules); + + /** Constructor + */ + IODCommonInstanceReferenceModule(); + + /** Clears all data belonging to this module (rules are kept) + */ + virtual void clearData(); + + /** Destructor + */ + virtual ~IODCommonInstanceReferenceModule(); + + /** Read data of this module from given source item + * @param source The item to read from + * @param clearOldData If OFTrue, old data is cleared before reading, otherwise + * it is overwriten/amended. + * @result EC_Normal if successful, error otherwise + */ + virtual OFCondition read(DcmItem& source, + const OFBool clearOldData = OFTrue); + + /** Write data of this moduel into given destination item + * @param destination The item to write to + * @result EC_Normal if successful, error otherwise + */ + virtual OFCondition write(DcmItem& destination); + + /** Resets rules to their original values + */ + virtual void resetRules(); + + /** Get name of module ("CommonInstanceReferenceModule") + * @return Name of the module ("CommonInstanceReferenceModule") + */ + virtual OFString getName() const; + + /** Return reference to list of Referenced Series items + * @return Reference to list of Reference Series Items + */ + OFVector& getReferencedSeriesItems(); + +private: + + /// Vector with all items of the Referenced Series Sequence + OFVector m_ReferenceSeriesItems; + + /// Name of this component ("CommonInstanceReferenceModule") + static const OFString m_ComponentName; + + /// Items of Studies Containing Other Referenced Instances Sequence + OFVector m_StudiesContainingOtherReferencedInstancesSequence; +}; + + +/** Class representing items from the Studies Containing Other Referenced Instances Sequence, + * as used within the Common Instance Reference Module + * + * Studies Containing Other Referenced Instances Sequence: (SQ, 1-n, 1C) + * > Study Instance UID (UI, 1, 1) + * > Series and Instance Reference Macro + * + */ +class DCMTK_DCMIOD_EXPORT IODCommonInstanceReferenceModule::StudiesOtherInstancesItem : public IODComponent +{ + +public: + + /** Constructor + * @param item The item to be used for data storage. If NULL, the + * class creates an empty data container. + * @param rules The rule set for this class. If NULL, the class creates + * one from scratch and adds its values. + * @param parent The parent of the IOD component (NULL if none or unknown) + */ + StudiesOtherInstancesItem(OFshared_ptr item, + OFshared_ptr rules, + IODComponent* parent = NULL); + + /** Constructor + * @param parent The parent component of this module, might be NULL + */ + StudiesOtherInstancesItem(IODComponent* parent = NULL); + + /** Destructor + */ + virtual ~StudiesOtherInstancesItem(); + + /** Clear (removes) all attributes handled by the modules of this component. + * Rules are not reset. + */ + virtual void clearData(); + + /** Read data from source item into this module + * @param source The item to read from + * @param clearOldData If OFTrue, old data is cleared first, otherwise it is + * overwritten/amended + * @result EC_Normal if successful, error otherwise + */ + virtual OFCondition read(DcmItem& source, + const OFBool clearOldData = OFTrue); + + /** Write this module's data into given destination item + * @param destination Item to write to + * @result EC_Normal if successful, error otherwise + */ + virtual OFCondition write(DcmItem& destination); + + /** Resets rules to their original values + */ + virtual void resetRules(); + + /** Get name of module ("StudiesContainingOtherReferencedInstancesSequence") + * @return Name of the module ("StudiesContainingOtherReferencedInstancesSequence") + */ + virtual OFString getName() const; + + /** Get Study Instance UID + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getStudyInstanceUID(OFString &value, + const signed long pos = 0) const; + + /** Set Study Instance UID + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR (PN) and VM (1) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setStudyInstanceUID(const OFString& value, + const OFBool checkValue = OFTrue); + + + /** Get Series And Instance Reference Macro + * @return Reference to the Series And Instance Reference Macro structure + */ + virtual IODSeriesAndInstanceReferenceMacro& getReferencedSeriesAndInstanceReferences(); + +private: + + /// The name of this component ("StudiesContainingOtherReferencedInstancesSequence") + static const OFString m_ComponentName; + + /// The Series and Instance Reference Macro used in this item + IODSeriesAndInstanceReferenceMacro m_ReferencedSeriesAndInstance; +}; + + +#endif // MODCOMMONINSTANCEREF_H diff --git a/dcmiod/include/dcmtk/dcmiod/modenhequipment.h b/dcmiod/include/dcmtk/dcmiod/modenhequipment.h new file mode 100644 index 00000000..7e92fadc --- /dev/null +++ b/dcmiod/include/dcmtk/dcmiod/modenhequipment.h @@ -0,0 +1,157 @@ +/* + * + * Copyright (C) 2015, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmiod + * + * Author: Michael Onken + * + * Purpose: Class for managing the Enhanced General Equipment Module + * + */ + +#ifndef MODENHEQUIPMENT_H +#define MODENHEQUIPMENT_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmiod/ioddef.h" +#include "dcmtk/dcmiod/iodrules.h" +#include "dcmtk/dcmiod/modbase.h" + +/** Class representing the Enhanced Equipment Module: + * + * Manufacturer: (LO, 1, 1) + * Manufacturer's Model Name: (LO, 1, 1) + * Device Serial Number: (LO, 1, 1) + * Software Version(s): (LO, 1-n, 1) + */ +class DCMTK_DCMIOD_EXPORT IODEnhGeneralEquipmentModule : public IODModule +{ + +public: + + /** Convenient struct containing all information required for setting + * equipment information for use by external code) + */ + struct EquipmentInfo + { + // Manufacturer (VM 1) + OFString m_Manufacturer; + + // Manufacturer's Model Name (VM 1) + OFString m_ManufacturerModelName; + + // Device Serial Number (VM 1) + OFString m_DeviceSerialNumber; + + // Software Version(s) (VM 1-n) + OFString m_SoftwareVersions; + }; + + /** Constructor + * @param item The item to be used for data storage. If NULL, the + * class creates an empty data container. + * @param rules The rule set for this class. If NULL, the class creates + * one from scratch and adds its values. + */ + IODEnhGeneralEquipmentModule(OFshared_ptr item, + OFshared_ptr rules); + + /** Constructor + */ + IODEnhGeneralEquipmentModule(); + + /** Destructor + */ + virtual ~IODEnhGeneralEquipmentModule(); + + /** Resets rules to their original values. + */ + virtual void resetRules(); + + /** Get name of module + * @return Name of the module ("EnhancedEquipmentModule") + */ + virtual OFString getName() const; + + /** Get Manufacturer + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getManufacturer(OFString &value, + const signed long pos = 0) const; + + /** Get Manufacturer's Model Name + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getManufacturerModelName(OFString &value, + const signed long pos = 0) const; + + /** Get Device Serial Number + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getDeviceSerialNumber(OFString &value, + const signed long pos = 0) const; + + /** Get Software Version(s) + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getSoftwareVersions(OFString &value, + const signed long pos = 0) const; + + /** Set Manufacturer + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR (LO) and VM (1) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setManufacturer(const OFString &value, + const OFBool checkValue = OFTrue); + + /** Set Manufacturer's Model Name + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR (LO) and VM (1) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setManufacturerModelName(const OFString &value, + const OFBool checkValue = OFTrue); + + /** Set Device Serial Number + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR (LO) and VM (1) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setDeviceSerialNumber(const OFString &value, + const OFBool checkValue = OFTrue); + + /** Set Software Version(s) + * @param value Value to be set (possibly multi-valued) or "" for no value + * @param checkValue Check 'value' for conformance with VR (LO) and VM (1-n) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setSoftwareVersions(const OFString &value, + const OFBool checkValue = OFTrue); + +private: + + /// Name of the module ("EnhancedEquipmentModule") + OFString m_ModuleName; +}; + + +#endif // MODENHEQUIPMENT_H diff --git a/dcmiod/include/dcmtk/dcmiod/modenhusimage.h b/dcmiod/include/dcmtk/dcmiod/modenhusimage.h new file mode 100644 index 00000000..9057aa0b --- /dev/null +++ b/dcmiod/include/dcmtk/dcmiod/modenhusimage.h @@ -0,0 +1,593 @@ +/* + * + * Copyright (C) 2015, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmiod + * + * Author: Michael Onken + * + * Purpose: Class for managing the Enhanced US Image Module + * + */ + +#ifndef MODENHUSIMAGE_H +#define MODENHUSIMAGE_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmiod/modbase.h" +#include "dcmtk/dcmiod/iodmacro.h" + +/** Class representing the Enhanced US Image Module: + * + * Image Type: (CS, 2 as defined in part 3, 1) + * Samples Per Pixel: (US, 1, 1) + * Photometric Interpretation (CS, 1, 1) + * Rows: (US, 1, 1) + * Columns: (US, 1, 1) + * Bits Allocated: (US, 1, 1) + * Bits Stored: (US, 1, 1) + * High Bit: (US, 1, 1) + * Pixel Representation: (US, 1, 1) + * Dimension Organization Type (CS, 1, 1) + * Acquisition DateTime (DT, 1, 1) + * Acquisition Duration (FD, 1, 1) + * Pixel Spacing (DS, 2, 1) + * Position Measuring Device Used (CS, 1, 1C) + * Lossy Image Compression: (CS, 1, 1) + * Lossy Image Compression Ratio: (DS, 1-n, 1C) + * Lossy Image Compression Method: (CS, 1-n, 1C) + * Presentation LUT Shape: (CS, 1, 1) + * Rescale Slope: (DS, 1, 1) + * Rescale Intercept: (DS, 1, 1) + * Mandatory View And Slice Progression Macro (type 1) + * Burned In Annotation: (CS, 1, 1) + * Recognizable Visual Features: (CS, 1, 3) + * Transducer Scan Pattern Code Sequence: (SQ, 1, 1) + * Transducer Geometry Code Sequence: (SQ, 1, 1) + * Transducer Beam Steering Code Sequence: (SQ, 1, 1) + * Transducer Application Code Sequence: (SQ, 1, 1) + * Processing Function: (LO, 1, 3) + * Mechanical Index: (DS, 1, 1) + * Bone Thermal Index: (DS, 1, 1) + * Cranial Thermal Index: (DS, 1, 1) + * Soft Tissue Thermal Index: (DS, 1, 1) + * Depth(s) of Focus: (FD, 1-n, 1) + * Depth(s) of Scan Field: (IS, 1, 1) + */ +class DCMTK_DCMIOD_EXPORT IODEnhUSImageModule : public IODModule +{ + +public: + + /** Constructor + * @param item The item to be used for data storage. If NULL, the + * class creates an empty data container. + * @param rules The rule set where this classes rules are added to. If NULL, the + * class creates an empty rule set. + */ + IODEnhUSImageModule(OFshared_ptr item, + OFshared_ptr rules); + + /** Constructor + */ + IODEnhUSImageModule(); + + /** Destructor + */ + virtual ~IODEnhUSImageModule(); + + /** Resets rules to their original values. + */ + virtual void resetRules(); + + /** Get name of module + * @return Name of the module ("EnhancedUSImageModule") + */ + virtual OFString getName() const; + + /** Read attributes from given item into this class. Overwrites + * fucntion of base class IODComponent. + * @param source The source to read from + * @param clearOldData If OFTrue, old data is cleared before reading. Otherwise + * old data is overwritten (or amended) + * @result EC_Normal if reading was successful, error otherwise + */ + virtual OFCondition read(DcmItem& source, + const OFBool clearOldData = OFTrue); + + /** Write attributes from this class into given item. Overwrites + * function of base class IODComponent. + * @param destination The item to write to + * @result EC_Normal if writing was successful, error otherwise + */ + virtual OFCondition write(DcmItem& destination); + + /** Get Image Type + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all values + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getImageType(OFString &value, + const signed long pos = 0); + + /** Get Samples Per Pixel + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getSamplesPerPixel(Uint16& value, + const unsigned long pos = 0); + + /** Get Photometric Interpretation + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all values + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getPhotometricInterpretation(OFString& value, + const signed long pos = 0); + + /** Get Rows + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getRows(Uint16& value, + const unsigned long pos = 0); + + /** Get Columns + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getColumns(Uint16& value, + const unsigned long pos = 0); + /** Get Bits Allocated + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getBitsAllocated(Uint16& value, + const unsigned long pos = 0); + + /** Get Bits Stored + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getBitsStored(Uint16& value, + const unsigned long pos = 0); + + /** Get High Bit + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getHighBit(Uint16& value, + const unsigned long pos = 0); + + /** Get Pixel Representation + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getPixelRepresentation(Uint16& value, + const unsigned long pos = 0); + + /** Get Dimension Organization Type + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all values + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getDimensionOrganizationType(OFString& value, + const signed long pos = 0); + + /** Get Acquisition DateTime + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all values + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getAcquisitionDateTime(OFString& value, + const signed long pos = 0); + + /** Get Acquisition Duration + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getAcquisitionDuration(Float64& value, + const unsigned long pos = 0); + + /** Get Pixel Spacing + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getPixelSpacing(Float64& value, + const unsigned long pos = 0); + + /** Get Position Measuring Device + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getPositionMeasuringDevice(OFString& value, + const signed long pos = 0); + + /** Get Lossy Image Compression + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all values + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getLossyImageCompression(OFString& value, + const signed long pos = 0); + + /** Get Lossy Image Compression Ratio + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getLossyImageCompressionRatio(Float64& value, + const unsigned long pos = 0); + + /** Get Lossy Image Compression Method + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all values + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getLossyImageCompressionMethod(OFString& value, + const signed long pos = 0); + + /** Get Presentation LUT Shape + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all values + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getPresentationLUTShape(OFString& value, + const signed long pos = 0); + /** Get Rescale Slope + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getRescaleSlope(Float64& value, + const unsigned long pos = 0); + /** Get Rescale Intercept + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all values + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getRescaleIntercept(OFString& value, + const signed long pos = 0); + + /** Get Burned-In Annotation + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all values + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getBurnedInAnnotation(OFString& value, + const signed long pos = 0); + /** Get Recognizable Visual Features + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all values + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getRecognizableVisibleFeatures(OFString& value, + const signed long pos = 0); + /** Get Mandatory View And Slice Progression Direction + * @return Reference to Mandatory View And Slice Progression Direction + */ + virtual MandatoryViewAndSliceProgressionDirectionMacro& getMandatoryViewAndSliceProgressionDirection(); + + /** Get Anatomy + * @return Reference to Anatomy + */ + virtual GeneralAnatomyMacro& getAnatomy(); + + /** Get Transducer Scan Pattern + * @return Reference to Transducer Scan Pattern + */ + virtual CodeSequenceMacro& getTransducerScanPattern(); + + /** Get Transducer Geometry Code + * @return Reference to Transducer Geometry + */ + virtual CodeSequenceMacro& getTransducerGeometry(); + + /** Get Transducer Beam Steering + * @return Reference to Transducer Beam Steering + */ + virtual OFVector& getTransducerBeamSteering(); + + /** Get Transducer Application + * @return Reference to Transducer Application + */ + virtual CodeSequenceMacro& getTransducerApplication(); + + /** Get Processing Funcion + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all values + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getProcessingFunction(OFString& value, + const signed long pos = 0); + /** Get Mechanical Index + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getMechanicalIndex(Float64& value, + const unsigned long pos = 0); + + /** Get Bone Thermal Index + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getBoneThermalIndex(Float64& value, + const unsigned long pos = 0); + + /** Get Cranial Thermal Index + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all values + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getCranialThermalIndex(Float64& value, + const unsigned long pos = 0); + + /** Get Soft Tissue Thermal Index + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all values + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getSoftTissueThermalIndex(Float64& value, + const unsigned long pos = 0); + + /** Get Depth(s) of Focus + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getDepthsOfFocus(Float64& value, + const unsigned long pos = 0); + + /** Get Depth(s) of Scan Field + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getDepthsOfScanField(Float64& value, + const unsigned long pos = 0); + + /** Set Image Type. Image Type contains up to four values. Value 3 and 4 are + * optional and can be left empty if desired. The values in their order + * of occurence are: + * 1) Pixel Data Characteristics: Either ORIGINAL or DERIVED + * 2) Patient Examination Characteristics: Fixed to "PRIMARY", thus cannot be + * influenced through this function. + * 3) Image Flavor: Defined Terms listed in the standard + * 4) Derived Pixel Contrast: Defined Terms listed in the standard + * @param pixelDataChar Value 1 of Image Type + * @param imageFlavor Value 3 of Image Type + * @param derivedPixelContrast Value 4 of Image Type + * @param checkValue If OFTrue, the value is checked for conformance. + * @return EC_Normal if setting was successful, error otherwise. + */ + virtual OFCondition setImageType(const DcmIODTypes::IOD_ENHUSIMAGETYPE pixelDataChar, + const OFString& imageFlavor = "", + const OFString& derivedPixelContrast = "", + const OFBool checkValue = OFTrue); + + /** Set Rows + * @param value Value to be set + * @param checkValue Check 'value' for conformance if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setRows(const Uint16 value, + const OFBool checkValue = OFTrue); + + /** Set Columns + * @param value Value to be set + * @param checkValue Check 'value' for conformance if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setColumns(const Uint16 value, + const OFBool checkValue = OFTrue); + /** Set Bits Allocated + * @param value Value to be set, permitted values: 8 or 16 + * @param checkValue Check 'value' for conformance if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setBitsAllocated(const Uint16 value, + const OFBool checkValue = OFTrue); + + /** Set Bits Stored + * @param value Value to be set, permitted values: 8 or 16 + * @param checkValue Check 'value' for conformance if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setBitsStored(const Uint16 value, + const OFBool checkValue = OFTrue); + + /** Set High Bit + * @param value Value to be set, permitted values: 7 or 15 + * @param checkValue Check 'value' for conformance if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setHighBit(const Uint16 value, + const OFBool checkValue = OFTrue); + + /** Set Dimension Organization Type + * @param value Value to be set, permitted values: "3D" or "3D_TEMPORAL" + * @param checkValue Check 'value' for conformance if enabled, including VR (CS) and VM (1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setDimensionOrganizationType(const OFString& value, + const OFBool checkValue = OFTrue); + + /** Set Acquisition DateTime + * @param value Value to be set + * @param checkValue Check 'value' for conformance if enabled, including VR (DT) and VM (1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setAcquisitionDateTime(const OFString& value, + const OFBool checkValue = OFTrue); + + /** Set Acquisition Duration + * @param value Value to be set + * @param checkValue Check 'value' for conformance if enabled, + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setAcquisitionDuration(const Float64 value, + const OFBool checkValue = OFTrue); + + /** Set Pixel Spacing + * @param value Value to be set + * @param checkValue Check 'value' for conformance if enabled, including VR (DS) and VM (2) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setPixelSpacing(const OFString& value, + const OFBool checkValue = OFTrue); + + /** Set Position Measuring Device + * @param value Value to be set, permitted values: "RIGID" or "FREEHAND" + * @param checkValue Check 'value' for conformance if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setPositionMeasuringDevice(const OFString& value, + const OFBool checkValue = OFTrue); + + /** Set Lossy Image Compression + * @param value Value to be set, permitted values: "00" (not lossy compressed) or "01" (lossy compressed) + * @param checkValue Check 'value' for conformance if enabled, including VR (CS) and VM (1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setLossyImageCompression(const OFString& value, + const OFBool checkValue = OFTrue); + + /** Set Lossy Image Compression Ratio + * @param value Value to be set, including VR (DS) and VM (1-n) + * @param checkValue Check 'value' for conformance if enabled, including VR (DS) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setLossyImageCompressionRatio(const OFString& value, + const OFBool checkValue = OFTrue); + + /** Set Lossy Image Compression Method + * @param value Value to be set + * @param pos Index of the value to set (0..vm-1) + * @param checkValue Check 'value' for conformance if enabled, including VR (CS) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setLossyImageCompressionMethod(const OFString& value, + const unsigned long pos, + const OFBool checkValue = OFTrue); + + /** Set Recognizable Visual Features + * @param value Value to be set, permitted values: "YES" or "NO" + * @param checkValue Check 'value' for conformance if enabled, including VR (CS) and VM (1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setRecognizableVisibleFeatures(const OFString& value, + const OFBool checkValue = OFTrue); + + /** Set Processing Funcion + * @param value Value to be set + * @param checkValue Check 'value' for conformance if enabled, including VR (LO) and VM (1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setProcessingFunction(const OFString& value, + const OFBool checkValue = OFTrue); + + /** Set Mechanical Index + * @param value Value to be set + * @param checkValue Check 'value' for conformance if enabled, including VR (DS) and VM (1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setMechanicalIndex(const OFString& value, + const OFBool checkValue = OFTrue); + + /** Set Bone Thermal Index + * @param value Value to be set + * @param checkValue Check 'value' for conformance if enabled, including VR (DS) and VM (1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setBoneThermalIndex(const OFString& value, + const OFBool checkValue = OFTrue); + + /** Set Cranial Thermal Index + * @param value Value to be set + * @param checkValue Check 'value' for conformance if enabled, including VR (DS) and VM (1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setCranialThermalIndex(const OFString& value, + const OFBool checkValue = OFTrue); + + /** Set Soft Tissue Thermal Index + * @param value Value to be set + * @param checkValue Check 'value' for conformance if enabled, including VR (DS) and VM (1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setSoftTissueThermalIndex(const OFString& value, + const OFBool checkValue = OFTrue); + + /** Set Depth(s) of Focus + * @param value Value to be set + * @param pos Index of the value to set (0..vm-1) + * @param checkValue Check 'value' for conformance if enabled, including VR (FD) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setDepthsOfFocus(const Float64 value, + const unsigned long pos, + const OFBool checkValue = OFTrue); + + /** Set Depth(s) of Focus (convenience function) + * @param values Value(s) to be set + * @param checkValue Check 'value' for conformance if enabled, including VR (FD) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setDepthsOfFocus(const OFVector& values, + const OFBool checkValue = OFTrue); + + /** Set Depth(s) of Scan Field + * @param value Value to be set + * @param checkValue Check 'value' for conformance if enabled, including VR (IS) and VM (1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setDepthsOfScanField(const OFString& value, + const OFBool checkValue = OFTrue); + + +private: + + /// This module's name ("EnhancedUSImageModule") + static const OFString m_ModuleName; + + /// Mandatory View and Slice Progression Direction + MandatoryViewAndSliceProgressionDirectionMacro m_MandatoryViewAndSliceProgressionDirection; + + /// General Anatomy Mandatory Macro + GeneralAnatomyMacro m_Anatomy; + + /// Item of Transducer Scan Pattern Code Sequence + CodeSequenceMacro m_TransducerScanPattern; + + /// Item of Transducer Geometry Code Sequence + CodeSequenceMacro m_TransducerGeometry; + + /// Item of Transducer Beam Steering Code Sequence + OFVector m_TransducerBeamSteering; + + /// Item of Transducer Application Code Sequence + CodeSequenceMacro m_TransducerApplication; +}; + +#endif // MODENHUSIMAGE_H diff --git a/dcmiod/include/dcmtk/dcmiod/modenhusseries.h b/dcmiod/include/dcmtk/dcmiod/modenhusseries.h new file mode 100644 index 00000000..b34b143e --- /dev/null +++ b/dcmiod/include/dcmtk/dcmiod/modenhusseries.h @@ -0,0 +1,134 @@ +/* + * + * Copyright (C) 2015, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmiod + * + * Author: Michael Onken + * + * Purpose: Class for managing the Enhanced US Series Module + * + */ + +#ifndef MODENHUSSERIES_H +#define MODENHUSSERIES_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/ofstd/ofmem.h" +#include "dcmtk/ofstd/ofvector.h" +#include "dcmtk/ofstd/ofoption.h" +#include "dcmtk/dcmiod/iodrules.h" +#include "dcmtk/dcmiod/iodmacro.h" +#include "dcmtk/dcmiod/modbase.h" + +/** Class representing the Enhanced Ultrasound Series Module: + * + * Notation: "Attribute name: (VR, VM, Requirement Type)" + * Modality: (CS, 1, 1) + * Referenced Performed Procedure Step Sequence: (SQ, 1, 1C) + * > SOP Instance Reference Macro + * Performed Protocol Code Sequence: (SQ, 1, 1C) + * > Code Sequence Macro + * Not yet explicitly supported: + * ---------------------------------------------- + * > Protocol Context Sequence: (SQ, 1-n, 3) + * >> Content Item Macro + * >> Content Item Modifier Sequence: (SQ, 1-n, 3) + * >>> Content Item Macro + * ---------------------------------------------- + * Performed Protocol Type: (CS, 1, 1C) + */ +class DCMTK_DCMIOD_EXPORT IODEnhancedUSSeriesModule : public IODModule +{ + +public: + + /** Constructor + * @param item The item to be used for data storage. If NULL, the + * class creates an empty data container. + * @param rules The rule set for this class. If NULL, the class creates + * one from scratch and adds its values. + */ + IODEnhancedUSSeriesModule(OFshared_ptr item, + OFshared_ptr rules); + + /** Constructor + */ + IODEnhancedUSSeriesModule(); + + /** Destructor + */ + virtual ~IODEnhancedUSSeriesModule(); + + /** Resets rules to their original values + */ + virtual void resetRules(); + + /** Get name of module ("EnhancedUSSeriesModul") + * @return Name of the module ("EnhancedUSSeriesModul") + */ + virtual OFString getName() const; + + /** Read data into this module from given item + * @param source The item to read from + * @param clearOldData If OFTrue, old data in this module is cleared first (default: OFTrue) + * @return EC_Normal if reading was successful, error otherwise + */ + virtual OFCondition read(DcmItem& source, + const OFBool clearOldData = OFTrue); + + /** Write this module to given item + * @param destination The item to write to + * @return EC_Normal if writing was successful, error otherwise + */ + virtual OFCondition write(DcmItem& destination); + + /** Get Modality, always returns "US" + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getModality(OFString &value, + const signed long pos = 0) const; + + + /** Get Referenced Performed Procedure Step + * @return Reference to the Referenced Performed Procedure Step information + */ + virtual SOPInstanceReferenceMacro& getReferencedPPS(); + + /** Get Performed Protocol Code + * @return Reference to the Performed Protocol information + */ + virtual CodeSequenceMacro& getPerformedProtocolCode(); + + /** Get Performed Protocol Type + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getPerformedProtocolType(OFString &value, + const signed long pos = 0) const; + +private: + + /// The name of this module ("EnhancedUSSeriesModul") + static const OFString m_ModuleName; + + /// Referenced Performed Procedure Step Sequence + SOPInstanceReferenceMacro m_ReferencedPerformedProcedureStep; + + /// Performed Protocol Code Sequence (so far, without optional data) + CodeSequenceMacro m_PerformedProtocolCode; +}; + +#endif // MODENHUSSERIES_H diff --git a/dcmiod/include/dcmtk/dcmiod/modequipment.h b/dcmiod/include/dcmtk/dcmiod/modequipment.h new file mode 100644 index 00000000..e6ce52ea --- /dev/null +++ b/dcmiod/include/dcmtk/dcmiod/modequipment.h @@ -0,0 +1,233 @@ +/* + * + * Copyright (C) 2015, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmiod + * + * Author: Michael Onken + * + * Purpose: Class for managing the General Equipment Module + * + */ + +#ifndef MODEQUIPMENT_H +#define MODEQUIPMENT_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmiod/ioddef.h" +#include "dcmtk/dcmiod/iodrules.h" +#include "dcmtk/dcmiod/modbase.h" + +/** Class representing the General Equipment Module: + * + * Manufacturer: (LO, 1, 2) + * Institution Name: (LO, 1, 3) + * Institution Address: (ST, 1, 3) + * Station Name: (SH, 1, 3) + * Institutional Department Name: (LO, 1, 3) + * Manufacturer's Model Name: (LO, 1, 3) + * Device Serial Number: (LO, 1, 3) + * Software Version(s): (LO, 1-n, 3) + */ +class DCMTK_DCMIOD_EXPORT IODGeneralEquipmentModule : public IODModule +{ + +public: + + /** Convenient struct containing all information required for setting + * equipment information for use by external code) + */ + struct EquipmentInfo + { + // Manufacturer (VM 1) + OFString m_Manufacturer; + + // Manufacturer's Model Name (VM 1) + OFString m_ManufacturerModelName; + + // Device Serial Number (VM 1) + OFString m_DeviceSerialNumber; + + // Software Version(s) (VM 1-n) + OFString m_SoftwareVersions; + }; + + /** Constructor + * @param item The item to be used for data storage. If NULL, the + * class creates an empty data container. + * @param rules The rule set for this class. If NULL, the class creates + * one from scratch and adds its values. + */ + IODGeneralEquipmentModule(OFshared_ptr item, + OFshared_ptr rules); + + /** Constructor + */ + IODGeneralEquipmentModule(); + + /** Destructor + */ + virtual ~IODGeneralEquipmentModule(); + + /** Resets rules to their original values + */ + virtual void resetRules(); + + /** Get name of module + * @return Name of the module ("GeneralEquipmentModule") + * depending on configuration) + */ + virtual OFString getName() const; + + /** Get Manufacturer + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getManufacturer(OFString &value, + const signed long pos = 0) const; + + /** Get Institution Name + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getInstitutionName(OFString &value, + const signed long pos = 0) const; + + /** Get Institution Address + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getInstitutionAddress(OFString &value, + const signed long pos = 0) const; + + /** Get Station Name + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getStationName(OFString &value, + const signed long pos = 0) const; + + /** Get Institutional Department Name + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getInstitutionalDepartmentName(OFString &value, + const signed long pos = 0) const; + /** Get Manufacturer's Model Name + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getManufacturerModelName(OFString &value, + const signed long pos = 0) const; + + /** Get Device Serial Number + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getDeviceSerialNumber(OFString &value, + const signed long pos = 0) const; + + /** Get Software Version(s) + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getSoftwareVersions(OFString &value, + const signed long pos = 0) const; + + /** Set Manufacturer + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR (LO) and VM (1) + * if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setManufacturer(const OFString &value, + const OFBool checkValue = OFTrue); + + /** Set Institution Name + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR (LO) and VM (1) + * if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setInstitutionName(const OFString &value, + const OFBool checkValue = OFTrue); + + /** Set Institution Address + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR (ST) and VM (1) + * if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setInstitutionAddress(const OFString &value, + const OFBool checkValue = OFTrue); + + /** Set Station Name + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR (SH) and VM (1) + * if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setStationName(const OFString &value, + const OFBool checkValue = OFTrue); + + /** Set Institutional Department Name + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR (LO) and VM (1) + * if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setInstutionalDepartmentName(const OFString &value, + const OFBool checkValue = OFTrue); + + /** Set Manufacturer's Model Name + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR (LO) and VM (1) + * if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setManufacturerModelName(const OFString &value, + const OFBool checkValue = OFTrue); + + /** Set Device Serial Number + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR (LO) and VM (1) + * if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setDeviceSerialNumber(const OFString &value, + const OFBool checkValue = OFTrue); + + /** Set Software Version(s) + * @param value Value to be set (possibly multi-valued) or "" for no value + * @param checkValue Check 'value' for conformance with VR (LO) and VM (1-n) + * if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setSoftwareVersions(const OFString &value, + const OFBool checkValue = OFTrue); + +private: + + /// Name of the modue ("GeneralEquipmentModule") + OFString m_ModuleName; +}; + + +#endif // MODEQUIPMENT_H diff --git a/dcmiod/include/dcmtk/dcmiod/modfor.h b/dcmiod/include/dcmtk/dcmiod/modfor.h new file mode 100644 index 00000000..7da8fc42 --- /dev/null +++ b/dcmiod/include/dcmtk/dcmiod/modfor.h @@ -0,0 +1,108 @@ +/* + * + * Copyright (C) 2015, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmiod + * + * Author: Michael Onken + * + * Purpose: Class for managing the Frame of Reference Module + * + */ + +#ifndef MODFOR_H +#define MODFOR_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmiod/modbase.h" + +/** Class representing the Frame of Reference Module: + * + * Frame of Reference: (UI, 1, 1) + * Position Reference Indicator: (LO, 2, 1) + * + */ +class DCMTK_DCMIOD_EXPORT IODFoRModule : public IODModule +{ + +public: + + /** Constructor + * @param item The item to be used for data storage. If NULL, the + * class creates an empty data container. + * @param rules The rule set for this class. If NULL, the class creates + * one from scratch and adds its values. + */ + IODFoRModule(OFshared_ptr item, + OFshared_ptr rules); + /** Constructor + */ + IODFoRModule(); + + /** Destructor + */ + virtual ~IODFoRModule(); + + /** Resets rules to their original values + */ + virtual void resetRules(); + + /** Get name of module + * @return Name of the module ("FrameOfReferenceModule") + */ + virtual OFString getName() const; + + /** Get Frame of Reference UID + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getFrameOfReferenceUID(OFString &value, + const signed long pos = 0) const; + + /** Get Position Reference Indicator + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getPositionReferenceIndicator(OFString &value, + const signed long pos = 0) const; + + /** Set Frame of Reference UID + * @param value Value to be set (single value only). If an empty string is passed, + * the value "1" is set when displaying or writing the document since + * the corresponding DICOM attribute is mandatory. + * @param checkValue Check 'value' for conformance with VR (UI) and VM (1) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setFrameOfReferenceUID(const OFString &value, + const OFBool checkValue = OFTrue); + + /** Set Position Reference Indicator + * @param value Value to be set (single value only). If an empty string is passed, + * the value "1" is set when displaying or writing the document since + * the corresponding DICOM attribute is mandatory. + * @param checkValue Check 'value' for conformance with VR (LO) and VM (1) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setPositionReferenceIndicator(const OFString &value, + const OFBool checkValue = OFTrue); + + +private: + + /// Module name "FrameOfReferenceModule" + static const OFString m_ModuleName; + +}; + +#endif // MODFOR_H diff --git a/dcmiod/include/dcmtk/dcmiod/modgeneralimage.h b/dcmiod/include/dcmtk/dcmiod/modgeneralimage.h new file mode 100644 index 00000000..a8b4d9d5 --- /dev/null +++ b/dcmiod/include/dcmtk/dcmiod/modgeneralimage.h @@ -0,0 +1,361 @@ +/* + * + * Copyright (C) 2015, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmiod + * + * Author: Michael Onken + * + * Purpose: Class for managing the General Image Module + * + */ + +#ifndef MODGENERALIMAGE_H +#define MODGENERALIMAGE_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmiod/iodrules.h" +#include "dcmtk/dcmiod/modbase.h" + + +/** Class representing the General Image Module: + * + * Instance Number: (IS, 1, 2) + * Patient Orientation: (CS, 2, 2) + * Content Date: (DA, 1, 2C) + * Content Time: (TM, 1, 2C) + * Image Type: (CS, 1, 2-n) + * Acquisition Number (IS, 1, 3) + * Acquisition Date (DA, 1, 3) + * Acquisition Time (TM, 1, 3) + * Acquisition Date Time (DT, 1, 3) + * Image Comments (LT, 1, 3) + * Burned In Annotation (CS, 1, 3) + * Recognizable Visual Features (CS, 1, 3) + * Lossy Image Compression (CS, 1, 3) + * Lossy Image Compression Ratio (DS, 1, 3) + * Lossy Image Compression Method (CS, 1-n, 3) + * Presentation LUT Shape (CS, 1, 3) + * Irradiation Event UID (CS, 1-n, 3) + * + */ +class DCMTK_DCMIOD_EXPORT IODGeneralImageModule : public IODModule +{ + +public: + + /** Constructor + * @param item The item to be used for data storage. If NULL, the + * class creates an empty data container. + * @param rules The rule set for this class. If NULL, the class creates + * one from scratch and adds its values. + */ + IODGeneralImageModule(OFshared_ptr item, + OFshared_ptr rules); + + /** Constructor + */ + IODGeneralImageModule(); + + /** Destructor + */ + virtual ~IODGeneralImageModule(); + + /** Resets rules to their original values + */ + virtual void resetRules(); + + /** Get name of module + * @return Name of the module ("GeneralImageModule") + */ + virtual OFString getName() const; + + /** Get Instance Number + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getInstanceNumber(OFString &value, + const signed long pos = 0); + + /** Get Patient Orientation + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getPatientOrientation(OFString &value, + const signed long pos = 0); + + /** Get Content Date + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getContentDate(OFString &value, + const signed long pos = 0); + + /** Get Content Time + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getContentTime(OFString &value, + const signed long pos = 0); + + /** Get Image Type + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getImageType(OFString &value, + const signed long pos = 0); + + /** Get Acquisition Number + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getAcquisitionNumber(OFString &value, + const signed long pos = 0); + + /** Get Acquisition Date + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getAcquisitionDate(OFString &value, + const signed long pos = 0); + + /** Get Acquisition Time + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getAcquisitionTime(OFString &value, + const signed long pos = 0); + + /** Get Acquisition Date Time + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getAcquisitionDateTime(OFString &value, + const signed long pos = 0); + + /** Get Image Comments + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getImageComments(OFString &value, + const signed long pos = 0); + + /** Get Burned In Annotation + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getBurnedInAnnotation(OFString &value, + const signed long pos = 0); + + /** Get Recognizable Visual Features + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getRecognizableVisualFeatures(OFString &value, + const signed long pos = 0); + + /** Get Lossy Image Compression + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getLossyImageCompression(OFString &value, + const signed long pos = 0); + + /** Get Lossy Image Compression + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getLossyImageCompressionRatio(OFString &value, + const signed long pos = 0); + + /** Get Lossy Image Compression Method + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getLossyImageCompressionMethod(OFString &value, + const signed long pos = 0); + + /** Get Presentation LUT Shape + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getPresentationLUTShape(OFString &value, + const signed long pos = 0); + + /** Get Irridation Event UID + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getIrradiationEventUID(OFString &value, + const signed long pos = 0); + + /** Set Instance Number + * @param value Value to be set (single value only). + * @param checkValue Check 'value' for conformance with VR (IS) and VM (1) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setInstanceNumber(const OFString &value, + const OFBool checkValue = OFTrue); + + /** Set Patient Orientation + * @param value Value to be set (single value only). + * @param checkValue Check 'value' for conformance with VR (CS) and VM (2) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setPatientOrientation(const OFString &value, + const OFBool checkValue = OFTrue); + + /** Set Content Date + * @param value Value to be set (single value only). + * @param checkValue Check 'value' for conformance with VR (DA) and VM (1) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setContentDate(const OFString &value, + const OFBool checkValue = OFTrue); + + /** Set Content Time + * @param value Value to be set (single value only). + * @param checkValue Check 'value' for conformance with VR (TM) and VM (1) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setContentTime(const OFString &value, + const OFBool checkValue = OFTrue); + + + /** Set Image Type + * @param value Value to be set (single value only). + * @param checkValue Check 'value' for conformance with VR (CS) and VM (2-n) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setImageType(const OFString &value, + const OFBool checkValue = OFTrue); + + /** Set Acquisition Number + * @param value Value to be set (single value only). + * @param checkValue Check 'value' for conformance with VR (IS) and VM (1) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setAcquisitionNumber(const OFString &value, + const OFBool checkValue = OFTrue); + + /** Set Acquisition Date + * @param value Value to be set (single value only). + * @param checkValue Check 'value' for conformance with VR (DA) and VM (1) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setAcquisitionDate(const OFString &value, + const OFBool checkValue = OFTrue); + + /** Set Acquisition Time + * @param value Value to be set (single value only). + * @param checkValue Check 'value' for conformance with VR (TM) and VM (1) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setAcquisitionTime(const OFString &value, + const OFBool checkValue = OFTrue); + + /** Set Acquisition Date Time + * @param value Value to be set (single value only). + * @param checkValue Check 'value' for conformance with VR (DT) and VM (1) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setAcquisitionDateTime(const OFString &value, + const OFBool checkValue = OFTrue); + + /** Set Image Comments + * @param value Value to be set (single value only). + * @param checkValue Check 'value' for conformance with VR (LT) and VM (1) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setImageComments(const OFString &value, + const OFBool checkValue = OFTrue); + + /** Set Burned In Annotation + * @param value Value to be set (single value only). + * @param checkValue Check 'value' for conformance with VR (CS) and VM (1) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setBurnedInAnnotation(const OFString &value, + const OFBool checkValue = OFTrue); + + /** Set Recognizable Visual Features + * @param value Value to be set (single value only). + * @param checkValue Check 'value' for conformance with VR (CS) and VM (1) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setRecognizableVisualFeatures(const OFString &value, + const OFBool checkValue = OFTrue); + + /** Set Lossy Image Compression + * @param value Value to be set (single value only). + * @param checkValue Check 'value' for conformance with VR (CS) and VM (1) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setLossyImageCompression(const OFString &value, + const OFBool checkValue = OFTrue); + + /** Set Lossy Image Compression Ratio + * @param value Value to be set (single value only). + * @param checkValue Check 'value' for conformance with VR (DS) and VM (1) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setLossyImageCompressionRatio(const OFString &value, + const OFBool checkValue = OFTrue); + + /** Set Lossy Image Compression method + * @param value Value to be set (single value only). + * @param checkValue Check 'value' for conformance with VR (CS) and VM (1-n) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setLossyImageCompressionMethod(const OFString &value, + const OFBool checkValue = OFTrue); + + /** Set Presentation LUT Shape + * @param value Value to be set (single value only). + * @param checkValue Check 'value' for conformance with VR (CS) and VM (1) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setPresentationLUTShape(const OFString &value, + const OFBool checkValue = OFTrue); + + /** Set Irradiation Event UID + * @param value Value to be set (single value only). + * @param checkValue Check 'value' for conformance with VR (CS) and VM (1-n) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setIrradiationEventUID(const OFString &value, + const OFBool checkValue = OFTrue); + +private: + + /// The module's name ("GeneralIamgeModule") + static const OFString m_ModuleName; +}; + +#endif // MODGENERALIMAGE_H diff --git a/dcmiod/include/dcmtk/dcmiod/modgeneralseries.h b/dcmiod/include/dcmtk/dcmiod/modgeneralseries.h new file mode 100644 index 00000000..20dcdb07 --- /dev/null +++ b/dcmiod/include/dcmtk/dcmiod/modgeneralseries.h @@ -0,0 +1,299 @@ +/* + * + * Copyright (C) 2015, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmiod + * + * Author: Michael Onken + * + * Purpose: Class for managing the General Series Module + * + */ + +#ifndef MODGENERALSERIES_H +#define MODGENERALSERIES_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmiod/modbase.h" +#include "dcmtk/dcmiod/ioddef.h" + +/** Class representing the General Series Module: + * + * Modality: (CS, 1, 1) + * Series Instance Number: (UI, 1, 1) + * Series Number: (IS, 1, 2) + * Laterality: (CS, 1, 2C) + * Series Date: (DA, 1, 3) + * Series Time: (TM, 1, 3) + * Performing Physician's Name: (PN, 1, 3) + * Protocol Name: (LO, 1, 3) + * Series Description: (LO, 1, 3) + * Operators' Name: (PN, 1-n, 3) + * Body Part Examined: (CS, 1, 3) + * Patient Position: (CS, 1, 2C) + */ +class DCMTK_DCMIOD_EXPORT IODGeneralSeriesModule : public IODModule +{ + +public: + + /** Constructor + * @param item The item to be used for data storage. If NULL, the + * class creates an empty data container. + * @param rules The rule set for this class. If NULL, the class creates + * one from scratch and adds its values. + */ + IODGeneralSeriesModule(OFshared_ptr item, + OFshared_ptr rules); + + /** Constructor + */ + IODGeneralSeriesModule(); + + /** Destructor + */ + virtual ~IODGeneralSeriesModule(); + + /** Resets rules to their original values + */ + virtual void resetRules(); + + /** Set missing values by inventing "default values". Automatically + * called during write() by IODComponent. + */ + virtual void inventMissing(); + + /** Get name of module + * @return Name of the module ("GeneralSeriesModule") + */ + virtual OFString getName() const; + + /** Make sure that the module contains a Series Instance UID, i.e.\ a new one + * is created if empty. An invalid UID is corrected if desired. + * @param correctInvalid Correct invalid UID if OFTrue, otherwise do nothing + */ + virtual void ensureInstanceUID(const OFBool correctInvalid = OFFalse); + + /** Get Modality + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getModality(OFString &value, + const signed long pos = 0) const; + + /** Get series instance UID + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getSeriesInstanceUID(OFString &value, + const signed long pos = 0) const; + + /** Get Series Number + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getSeriesNumber(OFString &value, + const signed long pos = 0) const; + + /** Get Laterality + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getLaterality(OFString &value, + const signed long pos = 0) const; + + /** Get Series Date + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getSeriesDate(OFString &value, + const signed long pos = 0) const; + + /** Get Series Time + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getSeriesTime(OFString &value, + const signed long pos = 0) const; + + /** Get Performing Physician's Name + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getPerformingPhysicianName(OFString &value, + const signed long pos = 0) const; + + /** Get Protocol Name + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getProtocolName(OFString &value, + const signed long pos = 0) const; + + /** Get Series Description + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getSeriesDescription(OFString &value, + const signed long pos = 0) const; + + /** Get Operators' Name + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getOperatorsName(OFString &value, + const signed long pos = 0) const; + + /** Get Body Part Examined + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getBodyPartExamined(OFString &value, + const signed long pos = 0) const; + + /** Get Patient Position + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getPatientPosition(OFString &value, + const signed long pos = 0) const; + /** Set Modality + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR (CS) and VM (1) + * if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setModality(const OFString &value, + const OFBool checkValue = OFTrue); + + /** Set Series Instance UID + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR (UI) and VM (1) + * if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setSeriesInstanceUID(const OFString &value, + const OFBool checkValue = OFTrue); + + /** Set Series Number + * @param value Value to be set (single value only). If an empty string is, + * passed, the value "1" is set when displaying or writing the document + * since the corresponding DICOM attribute is mandatory. + * @param checkValue Check 'value' for conformance with VR (IS) and VM (1) + * if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setSeriesNumber(const OFString &value, + const OFBool checkValue = OFTrue); + + /** Set Laterality + * @param value Value to be set + * @param checkValue Check value (no effect in this call but included for + * consistency with other methods); provided value is + * always checked. + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setLaterality(const DcmIODTypes::IOD_LATERALITY value, + const OFBool checkValue = OFTrue); + + /** Set Series Date + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR (DA) and VM (1) + * if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setSeriesDate(const OFString &value, + const OFBool checkValue = OFTrue); + + /** Set Series Time + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR (TM) and VM (1) + * if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setSeriesTime(const OFString &value, + const OFBool checkValue = OFTrue); + + /** Set Performing Physician Name + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR (PN) and VM (1) + * if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setPerformingPhysicianName(const OFString &value, + const OFBool checkValue = OFTrue); + + /** Set Protocol Name + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR (LO) and VM (1) + * if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setProtocolName(const OFString &value, + const OFBool checkValue = OFTrue); + + /** Set Series Description + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR (LO) and VM (1) + * if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setSeriesDescription(const OFString &value, + const OFBool checkValue = OFTrue); + + /** Set Operators' Name + * @param value Value to be set + * @param checkValue Check 'value' for conformance with VR (PN) and VM (1-n) + * if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setOperatorsName(const OFString &value, + const OFBool checkValue = OFTrue); + + /** Set Body Part Examined + * @param value Value to be set + * @param checkValue Check 'value' for conformance with VR (CS) and VM (1) + * if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setBodyPartExamined(const OFString &value, + const OFBool checkValue = OFTrue); + + /** Set Patient Position + * @param value Value to be set + * @param checkValue Check 'value' for conformance with VR (CS) and VM (1) + * if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setPatientPosition(const OFString &value, + const OFBool checkValue = OFTrue); + +private: + + /// The name of this module ("GeneralSeriesModule") + static const OFString m_ModuleName; + +}; + +#endif // MODGENERALSERIES_H diff --git a/dcmiod/include/dcmtk/dcmiod/modgeneralstudy.h b/dcmiod/include/dcmtk/dcmiod/modgeneralstudy.h new file mode 100644 index 00000000..5fa81148 --- /dev/null +++ b/dcmiod/include/dcmtk/dcmiod/modgeneralstudy.h @@ -0,0 +1,245 @@ +/* + * + * Copyright (C) 2015, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmiod + * + * Author: Michael Onken + * + * Purpose: Class for managing the General Study Module + * + */ + +#ifndef MODGENERALSTUDY_H +#define MODGENERALSTUDY_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmiod/modbase.h" +#include "dcmtk/dcmiod/iodmacro.h" + +/** Class representing the General Study Module: + * Notation is "Attribute Name: (VR, VM, Type)" + * + * Study Instance UID: (UI, 1, 1) + * Study Date: (DA, 1, 2) + * Study Time: (TM, 1, 2) + * Referring Physician's Name: (PN, 1, 2) + * Study ID: (SH, 1, 2) + * Accession Number: (SH, 1, 2) + * Study Description: (LO, 1, 3) + * Issuer of Accession Number Sequence: (SQ, 3, 1) + * Procedure Code Sequence: (SQ, 1-n, 3) + * Reason for Performed Procedure Code Sequence: (SQ, 1-n, 3) + */ +class DCMTK_DCMIOD_EXPORT IODGeneralStudyModule : public IODModule +{ + +public: + + /** Constructor + * @param item The item to be used for data storage. If NULL, the + * class creates an empty data container. + * @param rules The rule set for this class. If NULL, the class creates + * one from scratch and adds its values. + */ + IODGeneralStudyModule(OFshared_ptr item, + OFshared_ptr rules); + /** Constructor + */ + IODGeneralStudyModule(); + + /** Destructor + */ + virtual ~IODGeneralStudyModule(); + + /** Set missing values by inventing "default values". Automatically + * called during write() by IODComponent. + */ + virtual void inventMissing(); + + /** Resets rules to their original values + */ + virtual void resetRules(); + + /** Get name of module + * @return Name of the module ("GeneralStudyModule") + */ + virtual OFString getName() const; + + /** Clear (removes) all attributes handled by the modules of this component. + * Rules are not reset. + */ + virtual void clearData(); + + /** Read data into this module from given item + * @param source The item to read from + * @param clearOldData If OFTrue, old data in this module is cleared first (default: OFTrue) + * @return EC_Normal if reading was successful, error otherwise + */ + virtual OFCondition read(DcmItem& source, + const OFBool clearOldData = OFTrue); + + /** Write this module to given item + * @param destination The item to write to + * @return EC_Normal if writing was successful, error otherwise + */ + virtual OFCondition write(DcmItem& destination); + + /** Make sure that the module contains a Study Instance UID, i.e.\ a new one + * is created if empty. An invalid UID is corrected if desired. + * @param correctInvalid Correct invalid UID if OFTrue, otherwise do nothing + */ + virtual void ensureInstanceUID(const OFBool correctInvalid = OFFalse); + + /** Get Study Instance UID + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getStudyInstanceUID(OFString &value, + const signed long pos = 0) const; + + /** Get Study Date + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getStudyDate(OFString &value, + const signed long pos = 0) const; + + /** Get Study Time + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getStudyTime(OFString &value, + const signed long pos = 0) const; + + /** Get Referring Physician's Name + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getReferringPhysicianName(OFString &value, + const signed long pos = 0) const; + + /** Get Study ID + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getStudyID(OFString &value, + const signed long pos = 0) const; + + /** Get Accession Number + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getAccessionNumber(OFString &value, + const signed long pos = 0) const; + + /** Get Study Description + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getStudyDescription(OFString &value, + const signed long pos = 0) const; + + /** Get reference to content of Issuer of Accession Number Sequence + * @return Reference to single item of Issuer of Accession Number Sequence + */ + virtual HL7HierarchicDesignatorMacro& getIssuerOfAccesionNumber(); + + /** Get reference to content of Procedure Code Sequence + * @return Reference to items of Procedure Code Sequence + */ + virtual OFVector& getProcedureCodeSequence(); + + /** Get reference to content of Reason for Performed Procedure Code Sequence + * @return Reference to items of Procedure Code Sequence + */ + virtual OFVector& getReasonForPerformedProcedureCodeSequence(); + + /** Set Study Instance UID + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR (UI) and VM (1) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setStudyInstanceUID(const OFString &value, + const OFBool checkValue = OFTrue); + + /** Set Study Date + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR (DA) and VM (1) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setStudyDate(const OFString &value, + const OFBool checkValue = OFTrue); + + /** set study time + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR (TM) and VM (1) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setStudyTime(const OFString &value, + const OFBool checkValue = OFTrue); + /** Set Referring Physician's Name + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR (PN) and VM (1) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setReferringPhysicianName(const OFString &value, + const OFBool checkValue = OFTrue); + + /** Set Study ID + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR (SH) and VM (1) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setStudyID(const OFString &value, + const OFBool checkValue = OFTrue); + + /** Set Accession Number + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR (SH) and VM (1) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setAccessionNumber(const OFString &value, + const OFBool checkValue = OFTrue); + + /** Set Study Description + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR (LO) and VM (1) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setStudyDescription(const OFString &value, + const OFBool checkValue = OFTrue); + +private: + + /// Name of this module ("GeneralStudyModule") + static const OFString m_ModuleName; + + /// Issuer of Accession Number Sequence + HL7HierarchicDesignatorMacro m_IssuerOfAccessionNumberSequence; + + /// Procedure Code Sequence + OFVector m_ProcedureCodeSequence; + + /// Reason for Performed Procedure Code Sequence + OFVector m_ReasonForPerformedProcedureCodeSequence; + +}; + +#endif // MODGENERALSTUDY_H diff --git a/dcmiod/include/dcmtk/dcmiod/modhelp.h b/dcmiod/include/dcmtk/dcmiod/modhelp.h new file mode 100644 index 00000000..5853f506 --- /dev/null +++ b/dcmiod/include/dcmtk/dcmiod/modhelp.h @@ -0,0 +1,210 @@ +/* + * + * Copyright (C) 2015, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmiod + * + * Author: Michael Onken, Andriy Fedorov + * + * Purpose: Helper functions for copying common modules between datasets + * + */ + +#ifndef MODHELP_H +#define MODHELP_H + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ +#include "dcmtk/ofstd/oftypes.h" + +#include "dcmtk/dcmiod/ioddef.h" +// forward declarations +class DcmTagKey; +class DcmItem; + + +/** This class contains helper functions that permit copying common modules + * from DICOM standard part 3 between DICOM datasets. + * @note The attribute lists per module are taken from the final text version + * of DICOM 2013. + */ +class DCMTK_DCMIOD_EXPORT DcmModuleHelpers { + + protected: + + /// Generic copy module helper method. + template + static inline void copyModule(const DcmTagKey (&tags)[N], + DcmItem& src, DcmItem& dest); + + /// List of tags within the Patient Module + static const DcmTagKey patientModuleTags[]; + + /// List of tags within the Clinical Trial Subject Module + static const DcmTagKey clinicalTrialSubjectModuleTags[]; + + /// List of tags within the General Study Module + static const DcmTagKey generalStudyModuleTags[]; + + /// List of tags within the Patient Study Module + static const DcmTagKey patientStudyModuleTags[]; + + /// List of tags within the Clinical Trial Study Module + static const DcmTagKey clinicalTrialStudyModuleTags[]; + + /// List of tags within the General Series Module + static const DcmTagKey generalSeriesModuleTags[]; + + /// List of tags within the Clinical Trial Series Module + static const DcmTagKey clinicalTrialSeriesModuleTags[]; + + /// List of tags within the General Equipment Module + static const DcmTagKey generalEquipmentModuleTags[]; + + /// List of tags within the Frame of Reference Module + static const DcmTagKey frameOfReferenceModuleTags[]; + + /// List of tags within the SOP Common Module, excluding Digital Signatures + /// Macro, i.e.\ MAC Parameters Sequence and Digital Signatures Sequence + static const DcmTagKey sopCommonModuleTags[]; + + /// List of tags within the General Image Module + static const DcmTagKey generalImageModuleTags[]; + + public: + + /** Copy element defined by tag from source item to destination item. + * No in-depth search is performed but only the main level is searched + * for the given tag. If the tag is not found, the destination item + * is not touched at all. + * @param tag Tag key of the element to be copied + * @param src Item that serves as a source for copying the element. + * In typical image objects, this will be the main dataset. + * @param dest Item that serves as a destination for inserting the + * copied element, if found. + */ + static void copyElement(const DcmTagKey& tag, DcmItem& src, DcmItem& dest); + + /** Copy Patient Module attributes. + * @param src Item to copy module from. Only the main level is searched, + * i.e.\ no in-depth search is performed on the various tags. + * @param dest Item to copy module to. An element not found within + * the source item will neither be created in the destination + * item, nor will any existing value be touched in the + * destination item. + */ + static void copyPatientModule(DcmItem& src, DcmItem& dest); + + /** Copy Clinical Trial Subject Module attributes. + * @param src Item to copy module from. Only the main level is searched, + * i.e.\ no in-depth search is performed on the various tags. + * @param dest Item to copy module to. An element not found within + * the source item will neither be created in the destination + * item, nor will any existing value be touched in the + * destination item. + */ + static void copyClinicalTrialSubjectModule(DcmItem& src, DcmItem& dest); + + /** Copy General Study Module attributes. + * @param src Item to copy module from. Only the main level is searched, + * i.e.\ no in-depth search is performed on the various tags. + * @param dest Item to copy module to. An element not found within + * the source item will neither be created in the destination + * item, nor will any existing value be touched in the + * destination item. + */ + static void copyGeneralStudyModule(DcmItem& src, DcmItem& dest); + + /** Copy Patient Study Module attributes. + * @param src Item to copy module from. Only the main level is searched, + * i.e.\ no in-depth search is performed on the various tags. + * @param dest Item to copy module to. An element not found within + * the source item will neither be created in the destination + * item, nor will any existing value be touched in the + * destination item. + */ + static void copyPatientStudyModule(DcmItem& src, DcmItem& dest); + + /** Copy Clinical Trial Study Module attributes. + * @param src Item to copy module from. Only the main level is searched, + * i.e.\ no in-depth search is performed on the various tags. + * @param dest Item to copy module to. An element not found within + * the source item will neither be created in the destination + * item, nor will any existing value be touched in the + * destination item. + */ + static void copyClinicalTrialStudyModule(DcmItem& src, DcmItem& dest); + + /** Copy General Series Module attributes. + * @param src Item to copy module from. Only the main level is searched, + * i.e.\ no in-depth search is performed on the various tags. + * @param dest Item to copy module to. An element not found within + * the source item will neither be created in the destination + * item, nor will any existing value be touched in the + * destination item. + */ + static void copyGeneralSeriesModule(DcmItem& src, DcmItem& dest); + + /** Copy Clinical Trial Series Module attributes. + * @param src Item to copy module from. Only the main level is searched, + * i.e.\ no in-depth search is performed on the various tags. + * @param dest Item to copy module to. An element not found within + * the source item will neither be created in the destination + * item, nor will any existing value be touched in the + * destination item. + */ + static void copyClinicalTrialSeriesModule(DcmItem& src, DcmItem& dest); + + /** Copy General Equipment Module attributes. + * @param src Item to copy module from. Only the main level is searched, + * i.e.\ no in-depth search is performed on the various tags. + * @param dest Item to copy module to. An element not found within + * the source item will neither be created in the destination + * item, nor will any existing value be touched in the + * destination item. + */ + static void copyGeneralEquipmentModule(DcmItem& src, DcmItem& dest); + + /** Copy Frame of Reference Module attributes. + * @param src Item to copy module from. Only the main level is searched, + * i.e.\ no in-depth search is performed on the various tags. + * @param dest Item to copy module to. An element not found within + * the source item will neither be created in the destination + * item, nor will any existing value be touched in the + * destination item. + */ + static void copyFrameOfReferenceModule(DcmItem& src, DcmItem& dest); + + /** Copy SOP Common Module attributes. + * Excludes: Digital Signatures Macro, i.e.\ MAC Parameters Sequence and + * Digital Signatures Sequence. + * @param src Item to copy module from. Only the main level is searched, + * i.e.\ no in-depth search is performed on the various tags. + * @param dest Item to copy module to. An element not found within + * the source item will neither be created in the destination + * item, nor will any existing value be touched in the + * destination item. + */ + static void copySOPCommonModule(DcmItem& src, DcmItem& dest); + + /** Copy General Image Module attributes. + * @param src Item to copy module from. Only the main level is searched, + * i.e.\ no in-depth search is performed on the various tags. + * @param dest Item to copy module to. An element not found within + * the source item will neither be created in the destination + * item, nor will any existing value be touched in the + + * destination item. + */ + static void copyGeneralImageModule(DcmItem& src, DcmItem& dest); +}; + +#endif // MODHELP_H diff --git a/dcmiod/include/dcmtk/dcmiod/modimagepixel.h b/dcmiod/include/dcmtk/dcmiod/modimagepixel.h new file mode 100644 index 00000000..4ca0dcd3 --- /dev/null +++ b/dcmiod/include/dcmtk/dcmiod/modimagepixel.h @@ -0,0 +1,261 @@ +/* + * + * Copyright (C) 2015, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmiod + * + * Author: Michael Onken + * + * Purpose: Class for managing the Image Pixel Module + * + */ + +#ifndef MODIMAGEPIXEL_H +#define MODIMAGEPIXEL_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmiod/modbase.h" + +/** Class representing the General Image Module: + * + * Samples Per Pixel: (US, 1, 1) + * Photometric Interpretation (CS, 1, 1) + * Rows: (US, 1, 1) + * Columns: (US, 1, 1) + * Bits Allocated: (US, 1, 1) + * Bits Stored: (US, 1, 1) + * High Bit: (US, 1, 1) + * Pixel Representation: (US, 1, 1) + * Pixel Data is left out for now + * Planar Configuration: (US, 1, 1C) + * Pixel Aspect Ratio: (IS, 2, 1C) + * ICC Profile: (OB, 1, 3) + */ +class DCMTK_DCMIOD_EXPORT IODImagePixelModule : public IODModule +{ + +public: + + /** Constructor + * @param item The item to be used for data storage. If NULL, the + * class creates an empty data container. + * @param rules The rule set for this class. If NULL, the class creates + * one from scratch and adds its values. + */ + IODImagePixelModule(OFshared_ptr item, + OFshared_ptr rules); + + /** Constructor + */ + IODImagePixelModule(); + + /** Destructor + */ + virtual ~IODImagePixelModule(); + + /** Resets rules to their original values + */ + virtual void resetRules(); + + /** Get name of module + * @return Name of the module ("ImagePixelModule") + */ + virtual OFString getName() const; + + /** Get Samples per Pixel + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getSamplesPerPixel(Uint16 &value, + const signed long pos = 0); + + /** Get Photometric Interpretation + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getPhotometricInterpretation(OFString&value, + const signed long pos = 0); + + /** Get Rows + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getRows(Uint16& value, + const signed long pos = 0); + + /** Get Columns + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getColumns(Uint16& value, + const signed long pos = 0); + /** Get Bits Allocated + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getBitsAllocated(Uint16& value, + const signed long pos = 0); + + /** Get Bits Stored + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getBitsStored(Uint16& value, + const signed long pos = 0); + + /** Get High Bit + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getHighBit(Uint16& value, + const signed long pos = 0); + + /** Get Pixel Representation + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getPixelRepresentation(Uint16& value, + const signed long pos = 0); + + /** Get Planar Configuration + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getPlanarConfiguration(Uint16& value, + const signed long pos = 0); + + /** Get Pixel Aspect Ratio + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getPixelAspectRatio(Uint16& value, + const signed long pos = 0); + + /** Get ICC Profile + * @param values Reference to variable in which the values should be stored + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getICCProfile(OFVector& values); + + /** set Samples per Pixel + * @param value Reference to variable in which the value should be stored + * @param checkValue Check 'value' for conformance with VR (US) and VM (1) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setSamplesPerPixel(const Uint16 value, + const OFBool checkValue = OFTrue); + + /** Set Photometric Interpretation + * @param value Reference to variable in which the value should be stored + * @param checkValue Check 'value' for conformance with VR (CS) and VM (1) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setPhotometricInterpretation(const OFString& value, + const OFBool checkValue = OFTrue); + + /** Set Rows + * @param value Reference to variable in which the value should be stored + * @param checkValue Check 'value' for conformance with VR (US) and consistency + * with other attributes if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setRows(const Uint16 value, + const OFBool checkValue = OFTrue); + + /** Set Columns + * @param value Reference to variable in which the value should be stored + * @param checkValue Check 'value' for conformance with VR (US) and consistency + * with other attributes if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setColumns(const Uint16 value, + const OFBool checkValue = OFTrue); + /** Set Bits Allocated + * @param value Reference to variable in which the value should be stored + * @param checkValue Check 'value' for conformance with VR (US) and consistency + * with other attributes if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setBitsAllocated(const Uint16 value, + const OFBool checkValue = OFTrue); + + /** Set Bits Stored + * @param value Reference to variable in which the value should be stored + * @param checkValue Check 'value' for conformance with VR (US) and consistency + * with other attributes if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setBitsStored(const Uint16 value, + const OFBool checkValue = OFTrue); + + /** Set High Bit + * @param value Reference to variable in which the value should be stored + * @param checkValue Check 'value' for conformance with VR (US) and consistency + * with other attributes if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setHighBit(const Uint16 value, + const OFBool checkValue = OFTrue); + + /** Set Pixel Representation + * @param value Reference to variable in which the value should be stored + * @param checkValue Check 'value' for conformance with VR (US) and consistency + * if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setPixelRepresentation(const Uint16 value, + const OFBool checkValue = OFTrue); + + /** Set Planar Configuration + * @param value Reference to variable in which the value should be stored + * @param checkValue Check 'value' for conformance with VR (US) and consistency + * with other attributes if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setPlanarConfiguration(const Uint16 value, + const OFBool checkValue = OFTrue); + + /** Set Pixel Aspect Ratio + * @param verticalPixelSize The vertical pixel size (no unit) + * @param horizontalPixelSize The horizontal pixel size (no unit) + * @param checkValue Check 'value' for conformance with VR (IS) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setPixelAspectRatio(const OFString& verticalPixelSize, + const OFString& horizontalPixelSize, + const OFBool checkValue = OFTrue); + + /** Set ICC Profile + * @param values Reference to variable in which the values should be stored + * @param length Length of array provied in values parameter + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setICCProfile(const Uint8* values, + const size_t length); +private: + + /// This module's name ("ImagePixelModule") + static const OFString m_ModuleName; + +}; + +#endif // MODIMAGEPIXEL_H diff --git a/dcmiod/include/dcmtk/dcmiod/modmultiframedimension.h b/dcmiod/include/dcmtk/dcmiod/modmultiframedimension.h new file mode 100644 index 00000000..da0e8d35 --- /dev/null +++ b/dcmiod/include/dcmtk/dcmiod/modmultiframedimension.h @@ -0,0 +1,381 @@ +/* + * + * Copyright (C) 2015, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmiod + * + * Author: Michael Onken + * + * Purpose: Class for managing the Multi-Frame Dimension Module + * + */ + +#ifndef MODMULTIFRAMEDIMENSION_H +#define MODMULTIFRAMEDIMENSION_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmiod/iodrules.h" +#include "dcmtk/dcmiod/modbase.h" + +/** Class representing the Multi-Frame Dimension Module: + * + * Dimension Organization Sequence: (SQ, VM 1-n, Type 1) + * > Dimension Organization UID: (UI, 1, 1) + * Dimension Organization Type: (CS, 1, 1) + * Dimension Index Sequence: (SQ, 1-n, 1) + * > Dimension Index Pointer (AT, 1, 1) + * > Dimension Index Private Creator (LO, 1, 1C) + * > Functional Group Pointer (AT, 1, 1C) + * > Functional Group Private Creator (LO, 1, 1C) + * > Dimension Organization UID (UI, 1, 1C) + * > Dimension Description Label (LO, 1, 3) + * + * The Dimension Organization UIDs within the Dimension Organization Sequence + * cannot be set explicitly. Instead the sequence is poplulated from the data + * found within the Dimension Index Sequence. + */ +class DCMTK_DCMIOD_EXPORT IODMultiframeDimensionModule : public IODModule +{ + +public: + + /** Helper class representing an item within the Dimension Index Sequence, + * i.e.\ a single dimension description + */ + class DimensionOrganizationItem : public IODComponent + { + + public: + + /** Constructor + * @param data The item to be used for data storage. If NULL, the + * class creates an empty data container. + * @param rules The rule set for this class. If NULL, the class creates + * one from scratch and adds its values. + * @param parent The parent of the IOD component (NULL if none or unknown) + */ + DimensionOrganizationItem(OFshared_ptr data, + OFshared_ptr rules, + IODComponent* parent); + + /** Constructor + * @param parent The parent of the IOD component (NULL if none or unknown) + */ + DimensionOrganizationItem(IODComponent* parent = NULL); + + /** Destructor + */ + virtual ~DimensionOrganizationItem(); + + /** Get name of module ("DimensionIndexPointerSequence") + * @return Name of the module ("DimensionIndexPointerSequence") + */ + virtual OFString getName() const; + + /** Resets rules of this module to their original values + */ + virtual void resetRules(); + + /** Get Dimension Organization UID + * @param value Reference to variable in which the value should be + * stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getDimensionOrganizationUID(OFString &value, + const signed long pos = 0) const; + + /** Set Dimension Organization UID + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR (PN) and VM (1) if enabled + * @return status EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setDimensionOrganizationUID(const OFString& value, + const OFBool checkValue = OFTrue); + }; + + /** Class representing a Dimension Index Pointer Sequence Item + * managed by the Multi-frame Dimension Module + */ + class DimensionIndexItem : public IODComponent + { + + public: + + /** Constructor + * @param data The item to be used for data storage. If NULL, the + * class creates an empty data container. + * @param rules The rule set for this class. If NULL, the class creates + * one from scratch and adds its values. + * @param parent The parent of the IOD component (NULL if none or unknown) + */ + DimensionIndexItem(OFshared_ptr data, + OFshared_ptr rules, + IODComponent* parent); + + /** Constructor + * @param parent The parent of the IOD component (NULL if none or unknown) + */ + DimensionIndexItem(IODComponent* parent = NULL); + + /** Destructor + */ + virtual ~DimensionIndexItem(); + + /** Get name of module ("DimensionIndexSequence") + * @return Name of the module ("[parent.]DimensionIndexSequence") + */ + virtual OFString getName() const; + + /** Resets rules to their original values + */ + virtual void resetRules(); + + /** Get Dimension Index Pointer + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getDimensionIndexPointer(DcmTagKey &value, + const signed long pos = 0) const; + + /** Get Dimension Index Private Creator + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getDimensionIndexPrivateCreator(OFString& value, + const signed long pos = 0) const; + + /** Get Functional Group Pointer + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getFunctionalGroupPointer(DcmTagKey &value, + const signed long pos = 0) const; + + /** Get Functional Group Private Creator + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getFunctionalGroupPrivateCreator(OFString &value, + const signed long pos = 0) const; + + /** Get Dimension Organization UID + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getDimensionOrganizationUID(OFString &value, + const signed long pos = 0) const; + + /** Get Dimension Description Label + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getDimensionDescriptionLabel(OFString &value, + const signed long pos = 0) const; + + /** Set Dimension Index Pointer + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR (PN) and VM (1) if enabled + * @return status EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setDimensionIndexPointer(const DcmTagKey&value, + const OFBool checkValue = OFTrue); + + /** Set Dimension Index Private Creator + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR (PN) and VM (1) if enabled + * @return status EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setDimensionIndexPrivateCreator(const OFString& value, + const OFBool checkValue = OFTrue); + + /** Set Dimension Index Functional Group Pointer + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR and VM if enabled + * @return status EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setFunctionalGroupPointer(const DcmTagKey& value, + const OFBool checkValue = OFTrue); + + /** Set Dimension Index Functional Group PrivateCreator + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR and VM if enabled + * @return status EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setFunctionalGroupPrivateCreator(const OFString& value, + const OFBool checkValue = OFTrue); + + /** Set Dimension Organization UID + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR and VM if enabled + * @return status EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setDimensionOrganizationUID(const OFString& value, + const OFBool checkValue = OFTrue); + + /** Set Dimension Description Label + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR and VM if enabled + * @return status EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setDimensionDescriptionLabel(const OFString& value, + const OFBool checkValue = OFTrue); + }; + + /** Constructor + * @param item The item to be used for data storage. If NULL, the + * class creates an empty data container. + * @param rules The rule set for this class. If NULL, the class creates + * one from scratch and adds its values. + */ + IODMultiframeDimensionModule(OFshared_ptr item, + OFshared_ptr rules); + + /** Constructor + */ + IODMultiframeDimensionModule(); + + /** Destructor + */ + virtual ~IODMultiframeDimensionModule(); + + /** Convenience method to add Dimension Index. + * @param dimensionIndexPointer The Dimension Index Pointer attribute + * @param dimensionOrganizationUID The Dimension Organization UID of the dimension organization + * the pointer refers to + * @param functionalGroupPointer The functional group where the pointer attribute can be found + * @param dimensionDescriptionLabel The description label of this dimension (optional) + * @param dimensionIndexPrivateCreator The private creator of the Dimension Index Pointer + * attribute. Reuquired if dimensionIndexPointer points to a private attribute tag. + * @param functionalGroupPrivateCreator The private creator of the functional group. Reuired + * if functionalGroupPointer points to a private attribute tag. + * @return EC_Normal if index could be added, error otherwise (basic parameter checking) + * + */ + virtual OFCondition addDimensionIndex(const DcmTagKey& dimensionIndexPointer, + const OFString& dimensionOrganizationUID, + const DcmTagKey& functionalGroupPointer, + const OFString& dimensionDescriptionLabel = "", + const OFString& dimensionIndexPrivateCreator = "", + const OFString& functionalGroupPrivateCreator = ""); + + /** Clear (removes) all attributes handled by the modules of this component. + * Rules are not reset. + */ + virtual void clearData(); + + /** Read data into this module from given item + * @param source The item to read from + * @param clearOldData If OFTrue, old data in this module is cleared first (default: OFTrue) + * @return EC_Normal if reading was successful, error otherwise + */ + virtual OFCondition read(DcmItem& source, + const OFBool clearOldData = OFTrue); + + /** Write this module to given item + * @param destination The item to write to + * @return EC_Normal if writing was successful, error otherwise + */ + virtual OFCondition write(DcmItem& destination); + + /** Resets rules to their original values. + */ + virtual void resetRules(); + + /** Get name of module ("MultiframeDimensionModule") + * @return Name of the module ("MultiframeDimensionModule") + */ + virtual OFString getName() const; + + /** Get Dimension Organization Type + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getDimensionOrganizationType(OFString &value, + const signed long pos = 0) const; + + /** Set Dimension Organization Type (Defined Terms as of DICOM 2014a "3D" and "3D_TEMPORAL") + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR and VM if enabled + * @return status EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setDimensionOrganizationType(const OFString &value, + const OFBool checkValue = OFTrue); + + /** Get content of the Dimension Index Sequence + * @return Reference to the Dimension Index Pointer Sequence + */ + virtual OFVector& getDimensionIndexSequence(); + + /** Get content of the Dimension Organization Sequence + * @return Reference to the Dimension Organization Sequence + */ + virtual OFVector& getDimensionOrganizationSequence(); + + + /** Check dimensions for consistency with functional groups. Note that one can provide + * an item that provides the dataset containing the functional groups to check against. + * This item must contain on main level the Shared and Per-frame Functional Group + * Sequence. If no item is given (NULL pointer) it is tried to find these sequences + * within "this" object which works in the case that this class was initialized with + * an existing item (or the fg data was inserted in another way afterwards). + * @param fgItem The item containing functional group information + * @return EC_Normal, if consistency is fine, error otherwise + */ + virtual OFCondition checkDimensions(DcmItem* fgItem = NULL); + + /** Get specific index pointer element from per-frame functional group + * sequence. Prints out error messages if index does not exist or + * index location information provided by parameters is incomplete or invalid + * @param perFrameFG An instance of the Per-Frame Functional Group Sequence that + * should be searched + * @param fgPointer The tag key of the functional group the value resides in + * @param indexPointer The tag of the dimension value inside the functional group + * @param fgPrivateCreator The private creator of the fgPointer tag key. Only required + * if fgPointer is a private tag key (odd element number) + * @param privateCreator The private creator of the indexPointer tag key. Only required + * if indexPointer is a private tag key (odd element number) + * @return The element pointed to. If element could not be located, NULL is returned. + */ + virtual DcmElement* getIndexElement(DcmSequenceOfItems* perFrameFG, + const DcmTagKey& fgPointer, + const DcmTagKey& indexPointer, + const OFString& fgPrivateCreator, + const OFString& privateCreator); + +protected: + + /** Go over Dimension Index Pointers and extract Dimension Organization UIDs for + * Dimension Organization Sequence. + */ + void createDimensionOrganizationData(); + +private: + + /// This module's name (MultiframeDimensionModule) + static const OFString m_ModuleName; + + /// Vector with all items of the Dimension Index Pointer Sequence + OFVector m_DimensionIndexSequence; + + /// Vector with all items of the Dimension Organization Sequence + OFVector m_DimensionOrganizationSequence; +}; + +#endif // MODMULTIFRAMEDIMENSION_H diff --git a/dcmiod/include/dcmtk/dcmiod/modmultiframefg.h b/dcmiod/include/dcmtk/dcmiod/modmultiframefg.h new file mode 100644 index 00000000..33afb033 --- /dev/null +++ b/dcmiod/include/dcmtk/dcmiod/modmultiframefg.h @@ -0,0 +1,292 @@ +/* + * + * Copyright (C) 2015, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmiod + * + * Author: Michael Onken + * + * Purpose: Class for managing the Multi-frame Functional Groups Module + * + */ + +#ifndef MODMULTIFRAMEFG_H +#define MODMULTIFRAMEFG_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmdata/dcsequen.h" +#include "dcmtk/dcmdata/dcdeftag.h" +#include "dcmtk/dcmdata/dcdatset.h" +#include "dcmtk/dcmiod/iodrules.h" +#include "dcmtk/dcmiod/ioddef.h" +#include "dcmtk/dcmiod/modbase.h" + +/** Class managing the data from the Multi-Frame Functional Group Module. The + * actual functional groups are not included and can be interfaced by the + * FGInterface class in module "dcmfg". + */ +class DCMTK_DCMIOD_EXPORT IODMultiFrameFGModule : public IODModule +{ + +public: + + // Forward declaration + class ConcatenationInfo; + + /** Constructor + * @param data The item to be used for data storage. If NULL, the + * class creates an empty data container. + * @param rules The rule set for this class. If NULL, the class creates + * one from scratch and adds its values. + */ + IODMultiFrameFGModule(OFshared_ptr data, + OFshared_ptr rules); + + /** Constructor + */ + IODMultiFrameFGModule(); + + /** Virtual destructor + */ + virtual ~IODMultiFrameFGModule(); + + /** Get name of the module ("MultiframeFunctionalGroupsModule") + * @return Name of the module ("MultiframeFunctionalGroupsModule") + */ + virtual OFString getName() const; + + /** Reset attribute rules to their default values + */ + virtual void resetRules(); + + // -- getters -- + + /** Get Instance Number + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getInstanceNumber(Sint32 &value, + const unsigned int pos = 0); + + /** Get Content Date + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getContentDate(OFString &value, + const signed long pos = 0); + + /** Get Content Time + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getContentTime(OFString &value, + const signed long pos = 0); + + /** Get Number of Frames + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getNumberOfFrames(Sint32 &value, + const unsigned int pos = 0); + + /** Get Representative Frame Number + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getRepresentativeFrameNumber(Uint16 &value, + const unsigned int pos = 0); + + /** Get Concatenation Information + * @return Reference to the concatentation information + */ + virtual ConcatenationInfo& getConcatenationInfo(); + + // -- setters -- + + /** Set Instance Number + * @param value Value to be stored + * @param checkValue Check 'value' for conformance with VR (IS) and VM (1) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setInstanceNumber(const OFString& value, + const OFBool checkValue = OFTrue); + + /** Set Content Date + * @param value Value to be stored + * @param checkValue Check 'value' for conformance with VR (DA) and VM (1) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setContentDate(const OFString &value, + const OFBool checkValue = OFTrue); + + /** Set Content Time + * @param value Value to be stored + * @param checkValue Check 'value' for conformance with VR (TM) and VM (1) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setContentTime(const OFString &value, + const OFBool checkValue = OFTrue); + + /** Set Number of Frames + * @param value Value to be stored + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setNumberOfFrames(const Uint16 value); + + /** Set Representative Frame Number + * @param value Value to be stored + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setRepresentativeFrameNumber(const Uint16 value); + + /** Set concatenation information + * @param concatenationInfo The concatenation info to set + * @return EC_Normal if successful, error otherwise + */ + virtual OFCondition setConcatenationInfo(const ConcatenationInfo& concatenationInfo); + + /** Helper class encapsulating concatenation information, including + * Concatenation Frame Offset Number, + * Concatenation UID, + * SOP Instance UID of Concatenation Source, + * In-concatenation Number, + * In-concatenation Total Number + */ + class DCMTK_DCMIOD_EXPORT ConcatenationInfo : public IODComponent + { + + public: + + /** Constructor + * @param data The item to be used for data storage. If NULL, the + * class creates an empty data container. + * @param rules The rule set where this classes rules are added to. If NULL, the + * class creates an empty rule set. + */ + ConcatenationInfo(OFshared_ptr data, + OFshared_ptr rules); + + /** Constructor + * @param parent The parent component of this class (if applicable, might be NULL) + */ + ConcatenationInfo(IODComponent* parent = NULL); + + /** Virtual destructor + */ + virtual ~ConcatenationInfo(); + + /** Resets attribute rules to their default values + */ + virtual void resetRules(); + + /** Get name of this component ("ConcatenationInfo") + */ + virtual OFString getName() const; + + // -- getters -- + + /** Get Concatenation Frame Offset Number + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + OFCondition getConcatenationFrameOffsetNumber(Uint32& value, + const unsigned int pos); + + /** Get Concatenation UID + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + OFCondition getConcatenationUID(OFString& value, + const signed long pos); + + /** Get SOP Instance UID of Concatenation Source + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + OFCondition getSOPInstanceUIDOfConcatenationSource(OFString& value, + const signed long pos); + + /** Get Concatenation Number + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + OFCondition getInConcatenationNumber(Uint16& value, + const unsigned int pos); + + /** Get Concatenation Total Number + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + OFCondition getInConcatenationTotalNumber(Uint16& value, + const unsigned int pos); + + // -- setters -- + + /** Set Concatenation Frame Offset Number + * @param value Value to be stored + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setConcatenationFrameOffsetNumber(const Uint32 value); + + /** Set Concatenation UID + * @param value Value to be stored + * @param checkValue If OFTrue, the value is checked for conformance + * (VR = UID and VM = 1). + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setConcatenationUID(const OFString &value, + const OFBool checkValue = OFTrue); + + /** Set SOP Instance UID of Concatenation Source + * @param value Value to be stored + * @param checkValue If OFTrue, the value is checked for conformance + * (VR = UID and VM = 1). + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setSOPInstanceUIDOfConcatenationSource(const OFString &value, + const OFBool checkValue = OFTrue); + + /** Set In-concatenation Number + * @param value Value to be stored + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setInConcatenationNumber(const Uint16 value); + + /** Set In-concatenation Total Number + * @param value Value to be stored + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setInConcatenationTotalNumber(const Uint16 value); + + }; // ConcatenationInfoClass + + +private: + + /// Concatenation Information + ConcatenationInfo m_ConcatenationInfo; + + /// Module name ("MultiframeFunctionalGroupsModule" + static const OFString m_ModuleName; +}; + +#endif // MODMULTIFRAMEFG_H diff --git a/dcmiod/include/dcmtk/dcmiod/modpatient.h b/dcmiod/include/dcmtk/dcmiod/modpatient.h new file mode 100644 index 00000000..3e9422cc --- /dev/null +++ b/dcmiod/include/dcmtk/dcmiod/modpatient.h @@ -0,0 +1,141 @@ +/* + * + * Copyright (C) 2015, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmiod + * + * Author: Michael Onken + * + * Purpose: Class for managing the Patient Module + * + */ + +#ifndef MODPATIENT_H +#define MODPATIENT_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/ofstd/ofmem.h" +#include "dcmtk/ofstd/ofvector.h" +#include "dcmtk/dcmdata/dctk.h" +#include "dcmtk/dcmiod/iodrules.h" +#include "dcmtk/dcmiod/modbase.h" + +/** Class representing the Patient Module: + * + * Patient's Name: (PN, 1, 2) + * Patient ID: (LO, 1, 2) + * Patient's Birth Date: (DA, 1, 2) + * Patient's Sex: (CS, 1, 2) + */ +class DCMTK_DCMIOD_EXPORT IODPatientModule : public IODModule +{ + +public: + + /** Constructor + * @param item The item to be used for data storage. If NULL, the + * class creates an empty data container. + * @param rules The rule set for this class. If NULL, the class creates + * one from scratch and adds its values. + */ + IODPatientModule(OFshared_ptr item, + OFshared_ptr rules); + + /** Constructor + */ + IODPatientModule(); + + /** Destructor + */ + virtual ~IODPatientModule(); + + /** Resets rules to their original values + */ + virtual void resetRules(); + + /** Get name of module ("PatientModule") + * @return Name of the module ("PatientModule") + */ + virtual OFString getName() const; + + /** Get Patient's Name + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getPatientName(OFString &value, + const signed long pos = 0) const; + + /** Get Patient ID + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getPatientID(OFString &value, + const signed long pos = 0) const; + + /** Get Patient's Birth Date + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getPatientBirthDate(OFString &value, + const signed long pos = 0) const; + + /** Get Patient's Sex + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getPatientSex(OFString &value, + const signed long pos = 0) const; + + + /** Set Patient's Name + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR (PN) and VM (1) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setPatientName(const OFString &value, + const OFBool checkValue = OFTrue); + + /** Set Patient ID + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR (LO) and VM (1) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setPatientID(const OFString &value, + const OFBool checkValue = OFTrue); + + /** Set Patient's Birth Date + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR (DA) and VM (1) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setPatientBirthDate(const OFString &value, + const OFBool checkValue = OFTrue); + + /** Set Patient's Sex + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR (CS) and VM (1) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setPatientSex(const OFString &value, + const OFBool checkValue = OFTrue); + +private: + + /// The name of this module ("PatientModule") + static const OFString m_ModuleName; +}; + +#endif // MODPATIENT_H diff --git a/dcmiod/include/dcmtk/dcmiod/modpatientstudy.h b/dcmiod/include/dcmtk/dcmiod/modpatientstudy.h new file mode 100644 index 00000000..6ac3a44c --- /dev/null +++ b/dcmiod/include/dcmtk/dcmiod/modpatientstudy.h @@ -0,0 +1,145 @@ +/* + * + * Copyright (C) 2015, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmiod + * + * Author: Michael Onken + * + * Purpose: Class for managing the Patient Study Module + * + */ + +#ifndef MODPATIENTSTUDY_H +#define MODPATIENTSTUDY_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/ofstd/ofmem.h" +#include "dcmtk/ofstd/ofoption.h" +#include "dcmtk/ofstd/ofvector.h" +#include "dcmtk/dcmdata/dctk.h" +#include "dcmtk/dcmiod/iodrules.h" +#include "dcmtk/dcmiod/modbase.h" + +/** Class representing the Patient Study Module: + * + * Admitting Diagnoses Description: (LO, 1-n, 3) + * Patient's Age: (AS, 1, 3) + * Patient's Size: (DS, 1, 3) + * Patient's Weight: (DS,1, 3) + */ +class DCMTK_DCMIOD_EXPORT IODPatientStudyModule : public IODModule +{ + +public: + + /** Constructor + * @param item The item to be used for data storage. If NULL, the + * class creates an empty data container. + * @param rules The rule set for this class. If NULL, the class creates + * one from scratch and adds its values. + */ + IODPatientStudyModule(OFshared_ptr item, + OFshared_ptr rules); + + /** Constructor + */ + IODPatientStudyModule(); + + /** Destructor + */ + virtual ~IODPatientStudyModule(); + + /** Resets rules to their original values + */ + virtual void resetRules(); + + /** Get name of module ("PatientStudyModule") + * @return Name of the module ("PatientStudyModule") + */ + virtual OFString getName() const; + + /** Get Admitting Diagnoses Description + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getAdmittingDiagnosesDescription(OFString& value, + const signed long pos = 0) const; + + /** Get Patient's Age (string as defined by VR "AS", see DICOM part 5) + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getPatientAge(OFString &value, + const signed long pos = 0) const; + + /** Get Patient's Weight (in kilograms) + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getPatientWeight(Float64 &value, + const unsigned long pos = 00) const; + + /** Get Patient's Size (in meters) + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getPatientSize(Float64 &value, + const unsigned long pos = 0) const; + + /** Set Admitting Diagnoses Description + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR (LO) and VM (1-n) + * if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setAdmittingDiagnosesDescription(const OFString &value, + const OFBool checkValue = OFTrue); + + /** Set Patient's Age (formatted as defined by VR "AS", see part 5 of the standard) + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR (AS) and VM (1) + * if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setPatientAge(const OFString &value, + const OFBool checkValue = OFTrue); + + /** Set Patient's Size (in meters) + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR (DS) and VM (1) + * if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setPatientSize(const OFString &value, + const OFBool checkValue = OFTrue); + + /** Set Patient's Weight (in kilograms) + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR (DS) and VM (1) + * if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setPatientWeight(const OFString &value, + const OFBool checkValue = OFTrue); + +private: + + /// The name of this module ("PatientStudyModule") + static const OFString m_ModuleName; +}; + +#endif // MODPATIENT_H diff --git a/dcmiod/include/dcmtk/dcmiod/modsegmentationseries.h b/dcmiod/include/dcmtk/dcmiod/modsegmentationseries.h new file mode 100644 index 00000000..901825d2 --- /dev/null +++ b/dcmiod/include/dcmtk/dcmiod/modsegmentationseries.h @@ -0,0 +1,141 @@ +/* + * + * Copyright (C) 2015, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmiod + * + * Author: Michael Onken + * + * Purpose: Class for managing the Segmentation Series Module + * + */ + +#ifndef MODSEGMENTATIONSERIES_H +#define MODSEGMENTATIONSERIES_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/ofstd/ofmem.h" +#include "dcmtk/ofstd/ofvector.h" +#include "dcmtk/dcmdata/dctk.h" +#include "dcmtk/dcmiod/modbase.h" + +/** Class representing the Segmentation Series Module: + * + * Modality: (CS, 1, 1) + * Series Number: (IS, 1, 2) + * ReferencedPerformedProcedureStepSequence: (SQ, 1, 1C) + * -> Referenced SOP Class UID: (UI, 1, 1) + * -> Referenced SOP Instance UID: (UI, 1, 1) + */ +class DCMTK_DCMIOD_EXPORT IODSegmentationSeriesModule : public IODModule +{ + +public: + + /** Constructor + * @param item The item to be used for data storage. If NULL, the + * class creates an empty data container. + * @param rules The rule set for this class. If NULL, the class creates + * one from scratch and adds its values. + */ + IODSegmentationSeriesModule(OFshared_ptr item, + OFshared_ptr rules); + /** Constructor + */ + IODSegmentationSeriesModule(); + + /** Destructor + */ + virtual ~IODSegmentationSeriesModule(); + + /** Resets rules to their original values + */ + virtual void resetRules(); + + /** Get name of this module + * @return Name of the module ("SegmentationSeriesModule") + */ + virtual OFString getName() const; + + /** Get Modality (always returns "SEG") + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getModality(OFString &value, + const signed long pos = 0) const; + + /** Get Series Number + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getSeriesNumber(OFString &value, + const signed long pos = 0) const; + + /** Get Referenced PPS SOP Class UID + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getPPSSOPClassUID(OFString &value, + const signed long pos = 0) const; + + /** Get Referenced PPS SOP Instance UID + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getPPSSOPInstanceUID(OFString &value, + const signed long pos = 0) const; + + /** Set Series Number + * @param value Value to be set (single value only). If an empty string is passed, + * the value "1" is set when displaying or writing the document since + * the corresponding DICOM attribute is mandatory. + * @param checkValue Check 'value' for conformance with VR (IS) and VM (1) + * if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setSeriesNumber(const OFString &value, + const OFBool checkValue = OFTrue); + + /** Set Referenced PPS SOP Class UID + * @param value Value to be set (single value only). If an empty string is passed, + * the value "1" is set when displaying or writing the document since + * the corresponding DICOM attribute is mandatory. + * @param checkValue Check 'value' for conformance with VR (IS) and VM (1) + * if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setPPSSOPClassUID(const OFString &value, + const OFBool checkValue = OFTrue); + + /** Set Referenced PPS SOP Instance UID + * @param value Value to be set (single value only). If an empty string is passed, + * the value "1" is set when displaying or writing the document since + * the corresponding DICOM attribute is mandatory. + * @param checkValue Check 'value' for conformance with VR (IS) and VM (1) + * if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setPPSSOPInstanceUID(const OFString &value, + const OFBool checkValue = OFTrue); + +private: + + /// Name of this module ("SegmentationSeriesModule") + static const OFString m_ModuleName; + +}; + +#endif // MODSEGMENTATIONSERIES_H diff --git a/dcmiod/include/dcmtk/dcmiod/modsopcommon.h b/dcmiod/include/dcmtk/dcmiod/modsopcommon.h new file mode 100644 index 00000000..0a584e10 --- /dev/null +++ b/dcmiod/include/dcmtk/dcmiod/modsopcommon.h @@ -0,0 +1,211 @@ +/* + * + * Copyright (C) 2015, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmiod + * + * Author: Michael Onken + * + * Purpose: Class for managing the SOP Common Module + * + */ + +#ifndef MODSOPCOMMON_H +#define MODSOPCOMMON_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/ofstd/ofcond.h" +#include "dcmtk/ofstd/ofstring.h" +#include "dcmtk/dcmiod/modbase.h" + + +/** Class representing the SOP Common Module. Supported Attributes: + * + * SOP Class UID: (UI, 1, 1) + * SOP Instance UID: (UI, 1, 1) + * Specific Character Set: (CS, 1-n, 1C) + * Instance Creation Date: (DA, 1, 3) + * Instance Creation Time: (TM, 1, 3) + * Instance Creator UID: (UI, 1, 3) + * Timezone Offset from UTC: (SH, 1, 3) + * + */ +class DCMTK_DCMIOD_EXPORT IODSOPCommonModule : public IODModule +{ + +public: + + /** Constructor + * @param item The item to be used for data storage. If NULL, the + * class creates an empty data container. + * @param rules The rule set for this class. If NULL, the class creates + * one from scratch and adds its values. + */ + IODSOPCommonModule(OFshared_ptr item, + OFshared_ptr rules); + + /** Constructor + */ + IODSOPCommonModule(); + + /** Destructor + */ + virtual ~IODSOPCommonModule(); + + /** Resets rules to their original values + */ + virtual void resetRules(); + + /** Set missing values by inventing "default values". Automatically + * called during write() by IODComponent. + */ + virtual void inventMissing(); + + /** Get name of module + * @return Name of the module ("SOPCommonModule") + */ + virtual OFString getName() const; + + /** Make sure that the module contains a SOP Instance UID, i.e.\ a new one + * is created if empty. An invalid UID is corrected if desired. + * @param correctInvalid Correct invalid UID if OFTrue, otherwise do nothing + */ + virtual void ensureInstanceUID(const OFBool correctInvalid = OFFalse); + + /** Get SOP Class UID + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getSOPClassUID(OFString &value, + const signed long pos = 0) const; + + /** Get SOP Instance UID + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getSOPInstanceUID(OFString &value, + const signed long pos = 0) const; + + /** Get Instance Creator UID + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getInstanceCreatorUID(OFString &value, + const signed long pos = 0) const; + + /** Get Timeho e Offset from UTC + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getTimezoneOffsetFromUTC(OFString &value, + const signed long pos = 0) const; + + /** Get Specific Character Set + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getSpecificCharacterSet(OFString &value, + const signed long pos = 0) const; + + /** Get Instance Creation Date + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getInstanceCreationDate(OFString &value, + const signed long pos = 0) const; + + /** Get Instance Creation Time + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getInstanceCreationTime(OFString &value, + const signed long pos = 0) const; + + /** Set SOP Instance UID + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR (UI) and VM (1) + * if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setSOPInstanceUID(const OFString &value, + const OFBool checkValue = OFTrue); + + /** Set SOP Class UID + * @param value Value to be set (single value only) or "" for no value + * @param checkValue ValueCheck 'value' for conformance with VR (UI) and + * VM (1) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setSOPClassUID(const OFString &value, + const OFBool checkValue = OFTrue); + + /** Set Specific Character Set. The internal enumerated value is set accordingly. + * Please note that code extensions techniques are not supported. Therefore, only + * a single value can be passed. + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR (CS) and VM (1) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setSpecificCharacterSet(const OFString &value, + const OFBool checkValue = OFTrue); + + /** Set Instance Creation Date + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR (TM) and VM (1) + * if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setInstanceCreationDate(const OFString &value, + const OFBool checkValue = OFTrue); + /** Set Instance Creation Date + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR (TM) and VM (1) + * if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setInstanceCreationTime(const OFString &value, + const OFBool checkValue = OFTrue); + + /** Set Instance Creator UID + * @param value Value to be set (single value only) or "" for no value + * @param checkValue Check 'value' for conformance with VR (UID) and VM (1) + * if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setInstanceCreatorUID(const OFString &value, + const OFBool checkValue = OFTrue); + + /** Set Timezone Offset From UTC + * @param value Value to be set (single value only) or "" for no value. + * Encoded as an ASCII string in the format “&ZZXX”. The components of this + * string, from left to right, are & = “+” or “-”, and ZZ = Hours and + * XX = Minutes of offset. + * @param checkValue Check 'value' for conformance with VR (SH) and VM (1) if enabled + * @return EC_Normal if successful, an error code otherwise + */ virtual OFCondition setTimeZoneOffsetFromUTC(const OFString &value, + const OFBool checkValue = OFTrue) const; + +private: + + /// Name of this module ("SOPCommonModule") + static const OFString m_ModuleName; + +}; + +#endif // MODSOPCOMMON_H diff --git a/dcmiod/include/dcmtk/dcmiod/modsynchronisation.h b/dcmiod/include/dcmtk/dcmiod/modsynchronisation.h new file mode 100644 index 00000000..d7e08324 --- /dev/null +++ b/dcmiod/include/dcmtk/dcmiod/modsynchronisation.h @@ -0,0 +1,208 @@ +/* + * + * Copyright (C) 2015, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmiod + * + * Author: Michael Onken + * + * Purpose: Class for managing the Synchronization Module + * + */ + +#ifndef MODSYNCHRONIZATION_H +#define MODSYNCHRONIZATION_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/ofstd/ofoption.h" +#include "dcmtk/dcmiod/modbase.h" + +/** Class representing the Synchronization Module: + * + * Synchronization Frame of Reference UID: (UI, 1, 1) + * Synchronization Trigger: (CS, 1, 1) + * Trigger Source or Type: (LO, 1, 3) + * Synchronization Channel: (US, 2, 1C) + * Acquisition Time Synchronized: (CS, 1, 1) + * Time Source: (SH, 1, 3) + * Time Distribution Protocol: (CS, 1, 3) + * NTP Source Address (LO, 1, 3) + */ +class DCMTK_DCMIOD_EXPORT IODSynchronizationModule : public IODModule +{ + +public: + + /** Constructor + * @param item The item to be used for data storage. If NULL, the + * class creates an empty data container. + * @param rules The rule set for this class. If NULL, the class creates + * one from scratch and adds its values. + */ + IODSynchronizationModule(OFshared_ptr item, + OFshared_ptr rules); + + /** Constructor + */ + IODSynchronizationModule(); + + /** Destructor + */ + virtual ~IODSynchronizationModule(); + + /** Resets rules to their original values + */ + virtual void resetRules(); + + /** Get name of module + * @return Name of the module ("SynchronizationModule") + */ + virtual OFString getName() const; + + /** Get Synchronization Frame of Reference UID + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getSynchronizationFrameOfReferenceUID(OFString& value, + const signed long pos = 0) const; + + /** Get Synchronization Trigger + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getSynchronizationTrigger(OFString& value, + const signed long pos = 0) const; + + /** Get Trigger Source or Type + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getTriggerSourceOrType(OFString& value, + const signed long pos = 0) const; + + /** Get Synchronization Channel + * @param value Reference to variable in which the value should be stored + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getSynchronizationChannel(OFVector& value) const; + + /** Get Acquisition Time Sychronized + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + */ + virtual OFCondition getAcquisitionTimeSynchronized(OFString& value, + const signed long pos = 0) const; + + /** Get Time Source + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + */ + virtual OFCondition getTimeSource(OFString& value, + const signed long pos = 0) const; + + /** Get Time Distribution Protocol + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + */ + virtual OFCondition getTimeDistributionProtocol(OFString& value, + const signed long pos = 0) const; + + /** Get NTP Source Address + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + */ + virtual OFCondition getNTPSourceAddress(OFString& value, + const signed long pos = 0) const; + + /** Set Synchronization Frame of Reference UID + * @param value Value to be set + * @param checkValue Check 'value' for conformance with VR (UI) and VM (1) + * if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setSynchronizationFrameofReferenceUID(const OFString &value, + const OFBool checkValue = OFTrue); + + /** Set Synchronization Trigger + * @param value Value to be set + * @param checkValue Check 'value' for conformance with VR (CS) and VM (1) + * if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setSynchronizationTrigger(const OFString &value, + const OFBool checkValue = OFTrue); + + /** Set Trigger Source or Type + * @param value Value to be set + * @param checkValue Check 'value' for conformance with VR (LO) and VM (1) + * if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setTriggerSourceOrType(const OFString &value, + const OFBool checkValue = OFTrue); + + /** Set Synchronization Channel + * @param value Value to be set + * @param checkValue The check parameter is provided for consistency with + * other methods but does not have any effect here. + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setSynchronizationChannel(const OFPair &value, + const OFBool checkValue = OFTrue); + + /** Set Acquisition Time Synchronized + * @param value Value to be set + * @param checkValue Check 'value' for conformance with VR (CS) and VM (1) + * if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setAcquisitionTimeSynchronized(const OFString &value, + const OFBool checkValue = OFTrue); + + /** Set Time Source + * @param value Value to be set + * @param checkValue Check 'value' for conformance with VR (SH) and VM (1) + * if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setTimeSource(const OFString &value, + const OFBool checkValue = OFTrue); + + /** Set Time Distribution Protocol + * @param value Value to be set + * @param checkValue Check 'value' for conformance with VR (CS) and VM (1) + * if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setTimeDistributionProtocol(const OFString &value, + const OFBool checkValue = OFTrue); + + /** Set NTP Source Address + * @param value Value to be set + * @param checkValue Check 'value' for conformance with VR (LO) and VM (1) + * if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setNTPSourceAddress(const OFString &value, + const OFBool checkValue = OFTrue); + +private: + + /// Module name "SynchronizationModule" + static const OFString m_ModuleName; + +}; + +#endif // MODSYNCHRONIZATION_H diff --git a/dcmiod/include/dcmtk/dcmiod/modusfor.h b/dcmiod/include/dcmtk/dcmiod/modusfor.h new file mode 100644 index 00000000..5cde7646 --- /dev/null +++ b/dcmiod/include/dcmtk/dcmiod/modusfor.h @@ -0,0 +1,229 @@ +/* + * + * Copyright (C) 2015, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmiod + * + * Author: Michael Onken + * + * Purpose: Class managing the Ultrasound Frame of Reference Module + * + */ + +#ifndef MODUSFOR_H +#define MODUSFOR_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/ofstd/ofoption.h" +#include "dcmtk/dcmiod/modbase.h" + +/** Class representing the Frame of Reference Module: + * + * Volume Frame of Reference UID: (UI, 1, 1) + * Ultrasound Acquisition Geometry: (CS, 1, 1) + * Apex Position: (FD, 3, 1C) + * Volume to Transducer Relationship: (CS, 1, 1C) + * Volume to Transducer Mapping Matrix: (FD, 16, 1) + * Patient Frame of Reference Source: (CS, 1, 1C) + * Table Frame of Reference UID: (UI, 1, 1C) + * Volume to Table Mapping Matrix: (FD, 16, 1C) + * + */ +class DCMTK_DCMIOD_EXPORT IODUSFoRModule : public IODModule +{ + +public: + + /** Constructor + * @param item The item to be used for data storage. If NULL, the + * class creates an empty data container. + * @param rules The rule set for this class. If NULL, the class creates + * one from scratch and adds its values. + */ + IODUSFoRModule(OFshared_ptr item, + OFshared_ptr rules); + + /** Constructor + */ + IODUSFoRModule(); + + /** Destructor + */ + virtual ~IODUSFoRModule(); + + /** Resets rules to their original values + */ + virtual void resetRules(); + + /** Get name of module + * @return Name of the module ("UltrasoundFrameOfReferenceModule") + */ + virtual OFString getName() const; + + /** Get Volume Frame of Reference UID + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getVolumeFrameOfReferenceUID(OFString& value, + const signed long pos = 0) const; + + /** Get Position Reference Indicator + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getUltrasoundAcquisitionGeometry(OFString& value, + const signed long pos = 0) const; + + /** Get Apex Position + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getApexPosition(Float64& value, + const unsigned long pos = 0) const; + + /** Get Apex Position + * @param value Reference to variable in which the value should be stored + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getApexPosition(OFVector& value); + + /** Get Volume to Transducer Relationship + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getVolumetoTransducerRelationship(OFString& value, + const signed long pos = 0); + + /** Get Volume to Table Mapping Matrix + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getVolumetoTransducerMappingMatrix(Float64& value, + const signed long pos = 0) const; + + /** Get Volume to Table Mapping Matrix + * @param value Reference to variable in which the value should be stored + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getVolumetoTransducerMappingMatrix(OFVector& value); + + /** Get Patient Frame of Reference Source + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getPatientFrameofReferenceSource(OFString& value, + const signed long pos = 0); + + /** Get Table Frame of Reference UID + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1), -1 for all components + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getTableFrameofReferenceUID(OFString& value, + const signed long pos = 0); + + /** Get Volume to Table Mapping Matrix + * @param value Reference to variable in which the value should be stored + * @param pos Index of the value to get (0..vm-1) + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getVolumetoTableMappingMatrix(Float64& value, + const signed long pos = 0) const; + + /** Get Volume to Table Mapping Matrix + * @param value Reference to variable in which the value should be stored + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition getVolumetoTableMappingMatrix(OFVector& value); + + /** Set Volume Frame Of Reference UID + * @param value Value to be set + * @param checkValue Check 'value' for conformance with VR (UI) and VM (1) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setVolumeFrameOfReferenceUID(const OFString &value, + const OFBool checkValue = OFTrue); + + /** Set Ultrasound Acquisition Geometry + * @param value Value to be set + * @param checkValue Check 'value' for conformance with VR (CS) and VM (1) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setUltrasoundAcquisitionGeometry(const OFString &value, + const OFBool checkValue = OFTrue); + + /** Set Apex Position + * @param xValue xValue to be set + * @param yValue yValue to be set + * @param zValue zValue to be set + * @param checkValue Does nothing at the moment + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setApexPosition(const Float64& xValue, + const Float64& yValue, + const Float64& zValue, + const OFBool checkValue = OFTrue); + + /** Set Volume to Transducer Relationship + * @param value Value to be set + * @param checkValue Check 'value' for conformance with VR (CS) and VM (1) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setVolumetoTransducerRelationship(const OFString &value, + const OFBool checkValue = OFTrue); + + /** Set Volume to Transducer Mapping Matrix + * @param value Value to be set + * @param checkValue Check 'value' for conformance with VR (FD) and VM (16) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setVolumetoTransducerMappingMatrix(const OFVector& value, + const OFBool checkValue = OFTrue); + + /** Set Patient Frame of Reference Source + * @param value Value to be set + * @param checkValue Check 'value' for conformance with VR (CS) and VM (1) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setPatientFrameOfReferenceSource(const OFString &value, + const OFBool checkValue = OFTrue); + + /** Set Table Frame of Reference UID + * @param value Value to be set + * @param checkValue Check 'value' for conformance with VR (UI) and VM (1) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setTableFrameofReferenceUID(const OFString &value, + const OFBool checkValue = OFTrue); + + /** Set Volume to Table Mapping Matrix + * @param value Value to be set + * @param checkValue Check 'value' for conformance with VR (FD) and VM (16) if enabled + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition setVolumeToTableMappingMatrix(const OFVector& value, + const OFBool checkValue = OFTrue); + +private: + + /// Module name "UltrasoundFrameOfReferenceModule" + static const OFString m_ModuleName; + +}; + +#endif // MODUSFOR_H diff --git a/dcmiod/libsrc/CMakeLists.txt b/dcmiod/libsrc/CMakeLists.txt new file mode 100644 index 00000000..174a1d8b --- /dev/null +++ b/dcmiod/libsrc/CMakeLists.txt @@ -0,0 +1,33 @@ +# create library from source files +DCMTK_ADD_LIBRARY(dcmiod + iodcommn + iodmacro + iodimage + iodrules + iodutil + iodtypes + modacquisitioncontext + modbase + modcommoninstanceref + modenhequipment + modenhusimage + modenhusseries + modequipment + modfor + modgeneralimage + modgeneralseries + modgeneralstudy + modhelp + modimagepixel + modmultiframefg + modmultiframedimension + modpatient + modpatientstudy + modsegmentationseries + modsopcommon + modsynchronization + modusfor) + +DCMTK_TARGET_LINK_MODULES(dcmiod dcmdata ofstd oflog) +DCMTK_TARGET_LINK_LIBRARIES(dcmiod ${ZLIB_LIBS}) + diff --git a/dcmiod/libsrc/Makefile.dep b/dcmiod/libsrc/Makefile.dep new file mode 100644 index 00000000..c18bdb91 --- /dev/null +++ b/dcmiod/libsrc/Makefile.dep @@ -0,0 +1,2422 @@ +iodcommn.o: iodcommn.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmiod/iodcommn.h ../include/dcmtk/dcmiod/iodrules.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../include/dcmtk/dcmiod/iodtypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h ../include/dcmtk/dcmiod/ioddef.h \ + ../include/dcmtk/dcmiod/modpatient.h \ + ../../ofstd/include/dcmtk/ofstd/ofmem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcostrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicent.h \ + ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcmetinf.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicdir.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdirrec.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrulup.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrul.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixseq.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcofsetl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrae.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvras.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrda.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrds.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrdt.h \ + ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvris.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrtm.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrur.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcchrstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlt.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpn.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsh.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrst.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvruc.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrut.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixel.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpobw.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcovlay.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrat.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrss.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrus.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfd.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrof.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrod.h \ + ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ + ../include/dcmtk/dcmiod/modbase.h \ + ../include/dcmtk/dcmiod/modpatientstudy.h \ + ../../ofstd/include/dcmtk/ofstd/ofoption.h \ + ../../ofstd/include/dcmtk/ofstd/ofalign.h \ + ../include/dcmtk/dcmiod/modgeneralstudy.h \ + ../include/dcmtk/dcmiod/iodmacro.h \ + ../include/dcmtk/dcmiod/modequipment.h \ + ../include/dcmtk/dcmiod/modgeneralseries.h \ + ../include/dcmtk/dcmiod/modfor.h ../include/dcmtk/dcmiod/modsopcommon.h \ + ../include/dcmtk/dcmiod/modcommoninstanceref.h \ + ../include/dcmtk/dcmiod/iodutil.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h +iodimage.o: iodimage.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmiod/iodimage.h ../include/dcmtk/dcmiod/iodcommn.h \ + ../include/dcmtk/dcmiod/iodrules.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../include/dcmtk/dcmiod/iodtypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h ../include/dcmtk/dcmiod/ioddef.h \ + ../include/dcmtk/dcmiod/modpatient.h \ + ../../ofstd/include/dcmtk/ofstd/ofmem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcostrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicent.h \ + ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcmetinf.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicdir.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdirrec.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrulup.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrul.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixseq.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcofsetl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrae.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvras.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrda.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrds.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrdt.h \ + ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvris.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrtm.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrur.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcchrstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlt.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpn.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsh.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrst.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvruc.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrut.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixel.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpobw.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcovlay.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrat.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrss.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrus.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfd.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrof.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrod.h \ + ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ + ../include/dcmtk/dcmiod/modbase.h \ + ../include/dcmtk/dcmiod/modpatientstudy.h \ + ../../ofstd/include/dcmtk/ofstd/ofoption.h \ + ../../ofstd/include/dcmtk/ofstd/ofalign.h \ + ../include/dcmtk/dcmiod/modgeneralstudy.h \ + ../include/dcmtk/dcmiod/iodmacro.h \ + ../include/dcmtk/dcmiod/modequipment.h \ + ../include/dcmtk/dcmiod/modgeneralseries.h \ + ../include/dcmtk/dcmiod/modfor.h ../include/dcmtk/dcmiod/modsopcommon.h \ + ../include/dcmtk/dcmiod/modcommoninstanceref.h \ + ../include/dcmtk/dcmiod/modgeneralimage.h \ + ../include/dcmtk/dcmiod/modimagepixel.h \ + ../include/dcmtk/dcmiod/iodutil.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h +iodmacro.o: iodmacro.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmiod/iodmacro.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcostrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicent.h \ + ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcmetinf.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicdir.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdirrec.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrulup.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrul.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixseq.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcofsetl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrae.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvras.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrda.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrds.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrdt.h \ + ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvris.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrtm.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrur.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcchrstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlt.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpn.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsh.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrst.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvruc.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrut.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixel.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpobw.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcovlay.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrat.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrss.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrus.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfd.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrof.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrod.h \ + ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ + ../include/dcmtk/dcmiod/iodrules.h ../include/dcmtk/dcmiod/iodtypes.h \ + ../include/dcmtk/dcmiod/ioddef.h ../include/dcmtk/dcmiod/modbase.h \ + ../../ofstd/include/dcmtk/ofstd/ofmem.h \ + ../include/dcmtk/dcmiod/iodutil.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h +iodrules.o: iodrules.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmiod/iodrules.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../include/dcmtk/dcmiod/iodtypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h ../include/dcmtk/dcmiod/ioddef.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h +iodtypes.o: iodtypes.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmiod/iodtypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../include/dcmtk/dcmiod/ioddef.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h +iodutil.o: iodutil.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../include/dcmtk/dcmiod/iodutil.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h \ + ../include/dcmtk/dcmiod/ioddef.h ../include/dcmtk/dcmiod/iodrules.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../include/dcmtk/dcmiod/iodtypes.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcmetinf.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \ + ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicent.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrda.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrtm.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcuid.h +modacquisitioncontext.o: modacquisitioncontext.cc \ + ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmiod/modacquisitioncontext.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcostrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicent.h \ + ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcmetinf.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicdir.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdirrec.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrulup.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrul.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixseq.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcofsetl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrae.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvras.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrda.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrds.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrdt.h \ + ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvris.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrtm.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrur.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcchrstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlt.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpn.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsh.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrst.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvruc.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrut.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixel.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpobw.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcovlay.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrat.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrss.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrus.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfd.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrof.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrod.h \ + ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ + ../include/dcmtk/dcmiod/iodrules.h ../include/dcmtk/dcmiod/iodtypes.h \ + ../include/dcmtk/dcmiod/ioddef.h ../include/dcmtk/dcmiod/modbase.h \ + ../../ofstd/include/dcmtk/ofstd/ofmem.h \ + ../include/dcmtk/dcmiod/iodutil.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h +modbase.o: modbase.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmiod/modbase.h \ + ../../ofstd/include/dcmtk/ofstd/ofmem.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../include/dcmtk/dcmiod/ioddef.h ../include/dcmtk/dcmiod/iodrules.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../include/dcmtk/dcmiod/iodtypes.h ../include/dcmtk/dcmiod/iodutil.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h +modcommoninstanceref.o: modcommoninstanceref.cc \ + ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmiod/modcommoninstanceref.h \ + ../../ofstd/include/dcmtk/ofstd/ofmem.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcostrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicent.h \ + ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcmetinf.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicdir.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdirrec.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrulup.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrul.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixseq.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcofsetl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrae.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvras.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrda.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrds.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrdt.h \ + ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvris.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrtm.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrur.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcchrstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlt.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpn.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsh.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrst.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvruc.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrut.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixel.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpobw.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcovlay.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrat.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrss.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrus.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfd.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrof.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrod.h \ + ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ + ../include/dcmtk/dcmiod/iodrules.h ../include/dcmtk/dcmiod/iodtypes.h \ + ../include/dcmtk/dcmiod/ioddef.h ../include/dcmtk/dcmiod/modbase.h \ + ../include/dcmtk/dcmiod/iodmacro.h ../include/dcmtk/dcmiod/iodutil.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h +modenhequipment.o: modenhequipment.cc \ + ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmiod/modenhequipment.h \ + ../include/dcmtk/dcmiod/ioddef.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../include/dcmtk/dcmiod/iodrules.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../include/dcmtk/dcmiod/iodtypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../include/dcmtk/dcmiod/modbase.h \ + ../../ofstd/include/dcmtk/ofstd/ofmem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcchrstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrst.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsh.h \ + ../include/dcmtk/dcmiod/iodutil.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h +modenhusimage.o: modenhusimage.cc \ + ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmiod/modenhusimage.h \ + ../include/dcmtk/dcmiod/modbase.h \ + ../../ofstd/include/dcmtk/ofstd/ofmem.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../include/dcmtk/dcmiod/ioddef.h ../include/dcmtk/dcmiod/iodrules.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../include/dcmtk/dcmiod/iodtypes.h ../include/dcmtk/dcmiod/iodmacro.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcostrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicent.h \ + ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcmetinf.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicdir.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdirrec.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrulup.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrul.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixseq.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcofsetl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrae.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvras.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrda.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrds.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrdt.h \ + ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvris.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrtm.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrur.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcchrstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlt.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpn.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsh.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrst.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvruc.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrut.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixel.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpobw.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcovlay.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrat.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrss.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrus.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfd.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrof.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrod.h \ + ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ + ../include/dcmtk/dcmiod/iodutil.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h +modenhusseries.o: modenhusseries.cc \ + ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmiod/modenhusseries.h \ + ../../ofstd/include/dcmtk/ofstd/ofmem.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../ofstd/include/dcmtk/ofstd/ofoption.h \ + ../../ofstd/include/dcmtk/ofstd/ofalign.h \ + ../include/dcmtk/dcmiod/iodrules.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../include/dcmtk/dcmiod/iodtypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h ../include/dcmtk/dcmiod/ioddef.h \ + ../include/dcmtk/dcmiod/iodmacro.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcostrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicent.h \ + ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcmetinf.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicdir.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdirrec.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrulup.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrul.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixseq.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcofsetl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrae.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvras.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrda.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrds.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrdt.h \ + ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvris.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrtm.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrur.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcchrstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlt.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpn.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsh.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrst.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvruc.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrut.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixel.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpobw.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcovlay.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrat.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrss.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrus.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfd.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrof.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrod.h \ + ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ + ../include/dcmtk/dcmiod/modbase.h ../include/dcmtk/dcmiod/iodutil.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h +modequipment.o: modequipment.cc \ + ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmiod/modequipment.h ../include/dcmtk/dcmiod/ioddef.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../include/dcmtk/dcmiod/iodrules.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../include/dcmtk/dcmiod/iodtypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../include/dcmtk/dcmiod/modbase.h \ + ../../ofstd/include/dcmtk/ofstd/ofmem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcchrstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrst.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsh.h \ + ../include/dcmtk/dcmiod/iodutil.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h +modfor.o: modfor.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmiod/modfor.h ../include/dcmtk/dcmiod/modbase.h \ + ../../ofstd/include/dcmtk/ofstd/ofmem.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../include/dcmtk/dcmiod/ioddef.h ../include/dcmtk/dcmiod/iodrules.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../include/dcmtk/dcmiod/iodtypes.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcchrstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../include/dcmtk/dcmiod/iodutil.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h +modgeneralimage.o: modgeneralimage.cc \ + ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmiod/modgeneralimage.h \ + ../include/dcmtk/dcmiod/iodrules.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../include/dcmtk/dcmiod/iodtypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h ../include/dcmtk/dcmiod/ioddef.h \ + ../include/dcmtk/dcmiod/modbase.h \ + ../../ofstd/include/dcmtk/ofstd/ofmem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrtm.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrdt.h \ + ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrds.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvris.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrda.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlt.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcchrstr.h \ + ../include/dcmtk/dcmiod/iodutil.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h +modgeneralseries.o: modgeneralseries.cc \ + ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmiod/modgeneralseries.h \ + ../include/dcmtk/dcmiod/modbase.h \ + ../../ofstd/include/dcmtk/ofstd/ofmem.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../include/dcmtk/dcmiod/ioddef.h ../include/dcmtk/dcmiod/iodrules.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../include/dcmtk/dcmiod/iodtypes.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcchrstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrda.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvris.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrtm.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpn.h \ + ../include/dcmtk/dcmiod/iodutil.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h +modgeneralstudy.o: modgeneralstudy.cc \ + ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmiod/modgeneralstudy.h \ + ../include/dcmtk/dcmiod/modbase.h \ + ../../ofstd/include/dcmtk/ofstd/ofmem.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../include/dcmtk/dcmiod/ioddef.h ../include/dcmtk/dcmiod/iodrules.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../include/dcmtk/dcmiod/iodtypes.h ../include/dcmtk/dcmiod/iodmacro.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcostrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicent.h \ + ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcmetinf.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicdir.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdirrec.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrulup.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrul.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixseq.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcofsetl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrae.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvras.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrda.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrds.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrdt.h \ + ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvris.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrtm.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrur.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcchrstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlt.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpn.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsh.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrst.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvruc.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrut.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixel.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpobw.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcovlay.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrat.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrss.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrus.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfd.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrof.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrod.h \ + ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ + ../include/dcmtk/dcmiod/iodutil.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h +modhelp.o: modhelp.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmiod/modhelp.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../include/dcmtk/dcmiod/ioddef.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h +modimagepixel.o: modimagepixel.cc \ + ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmiod/modimagepixel.h \ + ../include/dcmtk/dcmiod/modbase.h \ + ../../ofstd/include/dcmtk/ofstd/ofmem.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../include/dcmtk/dcmiod/ioddef.h ../include/dcmtk/dcmiod/iodrules.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../include/dcmtk/dcmiod/iodtypes.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvris.h \ + ../include/dcmtk/dcmiod/iodutil.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h +modmultiframedimension.o: modmultiframedimension.cc \ + ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmiod/modmultiframedimension.h \ + ../include/dcmtk/dcmiod/iodrules.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../include/dcmtk/dcmiod/iodtypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h ../include/dcmtk/dcmiod/ioddef.h \ + ../include/dcmtk/dcmiod/modbase.h \ + ../../ofstd/include/dcmtk/ofstd/ofmem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrat.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcchrstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpath.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../include/dcmtk/dcmiod/iodutil.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h +modmultiframefg.o: modmultiframefg.cc \ + ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmiod/modmultiframefg.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../include/dcmtk/dcmiod/iodrules.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../include/dcmtk/dcmiod/iodtypes.h ../include/dcmtk/dcmiod/ioddef.h \ + ../include/dcmtk/dcmiod/modbase.h \ + ../../ofstd/include/dcmtk/ofstd/ofmem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrtm.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrda.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvris.h \ + ../include/dcmtk/dcmiod/iodutil.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h +modpatient.o: modpatient.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmiod/modpatient.h \ + ../../ofstd/include/dcmtk/ofstd/ofmem.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcostrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicent.h \ + ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcmetinf.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicdir.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdirrec.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrulup.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrul.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixseq.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcofsetl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrae.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvras.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrda.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrds.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrdt.h \ + ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvris.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrtm.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrur.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcchrstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlt.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpn.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsh.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrst.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvruc.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrut.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixel.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpobw.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcovlay.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrat.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrss.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrus.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfd.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrof.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrod.h \ + ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ + ../include/dcmtk/dcmiod/iodrules.h ../include/dcmtk/dcmiod/iodtypes.h \ + ../include/dcmtk/dcmiod/ioddef.h ../include/dcmtk/dcmiod/modbase.h \ + ../include/dcmtk/dcmiod/iodutil.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h +modpatientstudy.o: modpatientstudy.cc \ + ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmiod/modpatientstudy.h \ + ../../ofstd/include/dcmtk/ofstd/ofmem.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../../ofstd/include/dcmtk/ofstd/ofoption.h \ + ../../ofstd/include/dcmtk/ofstd/ofalign.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcostrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicent.h \ + ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcmetinf.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicdir.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdirrec.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrulup.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrul.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixseq.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcofsetl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrae.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvras.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrda.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrds.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrdt.h \ + ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvris.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrtm.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrur.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcchrstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlt.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpn.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsh.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrst.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvruc.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrut.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixel.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpobw.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcovlay.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrat.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrss.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrus.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfd.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrof.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrod.h \ + ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ + ../include/dcmtk/dcmiod/iodrules.h ../include/dcmtk/dcmiod/iodtypes.h \ + ../include/dcmtk/dcmiod/ioddef.h ../include/dcmtk/dcmiod/modbase.h \ + ../include/dcmtk/dcmiod/iodutil.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h +modsegmentationseries.o: modsegmentationseries.cc \ + ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmiod/modsegmentationseries.h \ + ../../ofstd/include/dcmtk/ofstd/ofmem.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcostrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicent.h \ + ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcmetinf.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicdir.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdirrec.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrulup.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrul.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixseq.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcofsetl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrae.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvras.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrda.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrds.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrdt.h \ + ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvris.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrtm.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrur.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcchrstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlt.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpn.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsh.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrst.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvruc.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrut.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixel.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpobw.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcovlay.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrat.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrss.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrus.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfd.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrof.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrod.h \ + ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ + ../include/dcmtk/dcmiod/modbase.h ../include/dcmtk/dcmiod/ioddef.h \ + ../include/dcmtk/dcmiod/iodrules.h ../include/dcmtk/dcmiod/iodtypes.h \ + ../include/dcmtk/dcmiod/iodutil.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h +modsopcommon.o: modsopcommon.cc \ + ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmiod/modsopcommon.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../include/dcmtk/dcmiod/modbase.h \ + ../../ofstd/include/dcmtk/ofstd/ofmem.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../include/dcmtk/dcmiod/ioddef.h ../include/dcmtk/dcmiod/iodrules.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../include/dcmtk/dcmiod/iodtypes.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrda.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrtm.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsh.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcchrstr.h \ + ../include/dcmtk/dcmiod/iodutil.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h +modsynchronization.o: modsynchronization.cc \ + ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmiod/modsynchronisation.h \ + ../../ofstd/include/dcmtk/ofstd/ofoption.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../../ofstd/include/dcmtk/ofstd/ofalign.h \ + ../include/dcmtk/dcmiod/modbase.h \ + ../../ofstd/include/dcmtk/ofstd/ofmem.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../include/dcmtk/dcmiod/ioddef.h ../include/dcmtk/dcmiod/iodrules.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../include/dcmtk/dcmiod/iodtypes.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcchrstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsh.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../include/dcmtk/dcmiod/iodutil.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h +modusfor.o: modusfor.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmiod/modusfor.h \ + ../../ofstd/include/dcmtk/ofstd/ofoption.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../../ofstd/include/dcmtk/ofstd/ofalign.h \ + ../include/dcmtk/dcmiod/modbase.h \ + ../../ofstd/include/dcmtk/ofstd/ofmem.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../include/dcmtk/dcmiod/ioddef.h ../include/dcmtk/dcmiod/iodrules.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../include/dcmtk/dcmiod/iodtypes.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfd.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../include/dcmtk/dcmiod/iodutil.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatutl.h diff --git a/dcmiod/libsrc/Makefile.in b/dcmiod/libsrc/Makefile.in new file mode 100644 index 00000000..1b6bbc21 --- /dev/null +++ b/dcmiod/libsrc/Makefile.in @@ -0,0 +1,59 @@ +# +# Makefile for dcmiod/libsrc +# + +@SET_MAKE@ + +SHELL = /bin/sh +VPATH = @srcdir@:@top_srcdir@/include:@top_srcdir@/@configdir@/include +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +configdir = @top_srcdir@/@configdir@ + +include $(configdir)/@common_makefile@ + +ofstddir = $(top_srcdir)/../ofstd +oflogdir = $(top_srcdir)/../oflog +dcmdatadir = $(top_srcdir)/../dcmdata + +LOCALINCLUDES = -I$(ofstddir)/include -I$(oflogdir)/include -I$(dcmdatadir)/include + +LOCALDEFS = + +objs = iodcommn.o iodmacro.o iodimage.o iodrules.o iodutil.o iodtypes.o \ + modacquisitioncontext.o modbase.o modcommoninstanceref.o \ + modenhequipment.o modenhusimage.o modenhusseries.o modequipment.o \ + modfor.o modgeneralimage.o modgeneralseries.o modgeneralstudy.o \ + modhelp.o modimagepixel.o modmultiframefg.o \ + modmultiframedimension.o modpatient.o modpatientstudy.o \ + modsegmentationseries.o modsopcommon.o modsynchronization.o \ + modusfor.o + + +library = libdcmiod.$(LIBEXT) + + +all: $(library) + +install: $(library) + $(configdir)/mkinstalldirs $(DESTDIR)$(libdir) + $(INSTALL_DATA) $(library) $(DESTDIR)$(libdir)/$(library) + $(RANLIB) $(DESTDIR)$(libdir)/$(library) + + +$(library): $(objs) + $(AR) $(ARFLAGS) $@ $(objs) + $(RANLIB) $@ + + +clean: + rm -f $(objs) $(library) $(TRASH) + +distclean: + rm -f $(objs) $(library) $(DISTTRASH) + + +dependencies: + $(CXX) -MM $(defines) $(includes) $(CPPFLAGS) $(CXXFLAGS) *.cc > $(DEP) + +include $(DEP) diff --git a/dcmiod/libsrc/iodcommn.cc b/dcmiod/libsrc/iodcommn.cc new file mode 100644 index 00000000..467d91c3 --- /dev/null +++ b/dcmiod/libsrc/iodcommn.cc @@ -0,0 +1,240 @@ +/* + * + * Copyright (C) 2015, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmiod + * + * Author: Michael Onken + * + * Purpose: Class representing IODs by exposing common DICOM module attributes + * + */ + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ +#include "dcmtk/dcmiod/iodcommn.h" +#include "dcmtk/dcmdata/dctypes.h" // logger +#include "dcmtk/dcmiod/iodutil.h" + + +DcmIODCommon::DcmIODCommon() +: m_Item(new DcmItem()), + m_Rules(new IODRules), + m_Patient(m_Item, m_Rules), + m_PatientStudy(m_Item, m_Rules), + m_Study(m_Item, m_Rules), + m_Equipment(m_Item, m_Rules), + m_Series(m_Item, m_Rules), + m_FrameOfReference(m_Item, m_Rules), + m_SOPCommon(m_Item, m_Rules), + m_CommonInstanceReferenceModule(m_Item, m_Rules), + m_Modules() +{ + // Set initial values for a new SOP instance + ensureInstanceUIDs(OFFalse); + m_Modules.push_back(&m_Patient); + m_Modules.push_back(&m_PatientStudy); + m_Modules.push_back(&m_Study); + m_Modules.push_back(&m_Equipment); + m_Modules.push_back(&m_Series); + m_Modules.push_back(&m_FrameOfReference); + m_Modules.push_back(&m_SOPCommon); + m_Modules.push_back(&m_CommonInstanceReferenceModule); +} + + +DcmIODCommon::~DcmIODCommon() +{ +} + + +void DcmIODCommon::clearData() +{ + OFVector::iterator it = m_Modules.begin(); + while (it != m_Modules.end()) + { + (*it)->clearData(); + it++; + } +} + + +IODPatientModule& DcmIODCommon::getPatient() +{ + return m_Patient; +} + + +IODPatientStudyModule& DcmIODCommon::getPatientStudy() +{ + return m_PatientStudy; +} + + +IODGeneralStudyModule& DcmIODCommon::getStudy() +{ + return m_Study; +} + + +IODGeneralEquipmentModule& DcmIODCommon::getEquipment() +{ + return m_Equipment; +} + + +IODGeneralSeriesModule& DcmIODCommon::getSeries() +{ + return m_Series; +} + + +IODFoRModule& DcmIODCommon::getFrameOfReference() +{ + return m_FrameOfReference; +} + + +IODSOPCommonModule& DcmIODCommon::getSOPCommon() +{ + return m_SOPCommon; +} + + +IODCommonInstanceReferenceModule& DcmIODCommon::getCommonInstanceReference() +{ + return m_CommonInstanceReferenceModule; +} + + + +OFshared_ptr DcmIODCommon::getRules() +{ + return m_Rules; +} + + +OFshared_ptr DcmIODCommon::getData() +{ + return m_Item; +} + + +OFCondition DcmIODCommon::read(DcmItem &dataset) +{ + /* re-initialize object */ + DcmIODCommon::clearData(); + + OFVector::iterator it = m_Modules.begin(); + while ( it != m_Modules.end() ) + { + (*it)->read(dataset, OFTrue /* clear old data */); + it++; + } + + // we do not report errors here (only logger output) + return EC_Normal; +} + + +OFCondition DcmIODCommon::import(DcmItem& dataset, + OFBool readPatient, + OFBool readStudy, + OFBool readSeries, + OFBool readFoR) +{ + if (readPatient) + { + m_Patient.read(dataset, OFFalse /* do not clear old data */); + } + + if (readStudy) + { + m_Study.read(dataset, OFFalse /* do not clear old data */); + m_Equipment.read(dataset, OFFalse /* do not clear old data */); + m_PatientStudy.read(dataset, OFFalse /* do not clear old data */); + } + + if (readSeries) + { + m_Series.read(dataset, OFFalse /* do not clear old data */); + m_FrameOfReference.read(dataset, OFFalse /* do not clear old data */); + } + + if (readFoR) + { + m_FrameOfReference.read(dataset, OFFalse /* do not clear old data */); + } + + return EC_Normal; +} + + +void DcmIODCommon::ensureInstanceUIDs(const OFBool correctInvalid) +{ + m_Study.ensureInstanceUID(correctInvalid); + m_Series.ensureInstanceUID(correctInvalid); + m_SOPCommon.ensureInstanceUID(correctInvalid); +} + + +OFCondition DcmIODCommon::write(DcmItem &dataset) +{ + OFCondition result; + + OFVector::iterator it = m_Modules.begin(); + while ( (it != m_Modules.end() && result.good()) ) + { + result = (*it)->write(dataset); + it++; + } + return result; +} + + +void DcmIODCommon::createNewStudy(const OFBool clearEquipment) +{ + // clear all study-related attributes + m_Study.clearData(); + m_PatientStudy.clearData(); + if (clearEquipment) + m_Equipment.clearData(); + // make sure we have a valid Study Instance UID + m_Study.ensureInstanceUID(); + + // reset series- and instance related attributes + createNewSeries(); +} + + +void DcmIODCommon::createNewSeries(const OFBool clearFoR) +{ + // clear all series-related attributes + m_Series.clearData(); + // create new Series Instance UID + m_Series.ensureInstanceUID(); + + // clear frame of reference-related attributes if desired + if (clearFoR) + m_FrameOfReference.clearData(); + + /* also creates new series (since UID is empty) */ + createNewSOPInstance(); +} + + +void DcmIODCommon::createNewSOPInstance() +{ + m_SOPCommon.clearData(); + m_SOPCommon.ensureInstanceUID(); +} + + diff --git a/dcmiod/libsrc/iodimage.cc b/dcmiod/libsrc/iodimage.cc new file mode 100644 index 00000000..482f7cc0 --- /dev/null +++ b/dcmiod/libsrc/iodimage.cc @@ -0,0 +1,89 @@ +/* + * + * Copyright (C) 2015, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmiod + * + * Author: Michael Onken + * + * Purpose: Class repres. image IOD by exposing common image IOD attributes + * + */ + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ +#include "dcmtk/dcmiod/iodimage.h" +#include "dcmtk/dcmiod/iodutil.h" + +DcmIODImage::DcmIODImage() +: m_GeneralImage(getData(), getRules()), + m_ImagePixel(getData(), getRules()) +{ + // Nothing to do +} + + +IODGeneralImageModule& DcmIODImage::getGeneralImage() +{ + return m_GeneralImage; +} + + +IODImagePixelModule& DcmIODImage::getImagePixel() +{ + return m_ImagePixel; +} + + +DcmIODImage::~DcmIODImage() +{ + // IOD rules created in DcmIODImage are cleared in DcmIODCommon::~DcmIODCommon() +} + + +void DcmIODImage::clearData() +{ + // clear all attributes from base classes + DcmIODCommon::clearData(); + m_GeneralImage.clearData(); + m_ImagePixel.clearData(); +} + + +OFCondition DcmIODImage::read(DcmItem &dataset) +{ + // re-initialize object + DcmIODImage::clearData(); + + // read from base classes + DcmIODCommon::read(dataset); + m_GeneralImage.read(dataset, OFTrue /* clear old data */); + m_ImagePixel.read(dataset, OFTrue /* clear old data */); + + return EC_Normal; +} + + +OFCondition DcmIODImage::write(DcmItem &dataset) +{ + OFCondition result = EC_Normal; + + // Write base class attributes to dataset + result = DcmIODCommon::write(dataset); + + // Write extra modules to dataset + if (result.good()) + result = m_GeneralImage.write(dataset); + if (result.good()) + result = m_ImagePixel.write(dataset); + + return result; +} diff --git a/dcmiod/libsrc/iodmacro.cc b/dcmiod/libsrc/iodmacro.cc new file mode 100644 index 00000000..909a0c54 --- /dev/null +++ b/dcmiod/libsrc/iodmacro.cc @@ -0,0 +1,1712 @@ +/* + * + * Copyright (C) 2015, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmiod + * + * Author: Michael Onken + * + * Purpose: Collection of classes representing DICOM IOD macros + * + */ + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ +#include "dcmtk/dcmiod/iodmacro.h" +#include "dcmtk/dcmiod/iodutil.h" // for static IOD helpers + + +// --------------------------- Code Sequence Macro --------------------------- + + +// -- Code Sequence Macro + +CodeSequenceMacro::CodeSequenceMacro(OFshared_ptr item, + OFshared_ptr rules, + IODComponent* parent) + : IODComponent(item, rules, parent) +{ + // reset element rules + resetRules(); +} + + +CodeSequenceMacro::CodeSequenceMacro(IODComponent* parent) : IODComponent(parent) +{ + // reset element rules + resetRules(); +} + + +CodeSequenceMacro::~CodeSequenceMacro() +{ + // nothing to do +} + + +CodeSequenceMacro::CodeSequenceMacro(const OFString& codeValue, + const OFString& codingSchemeDesignator, + const OFString& codeMeaning, + const OFString& codingSchemeVersion, + IODComponent* parent) +: IODComponent(parent) +{ + // reset element rules + resetRules(); + setCodeValue(codeValue); + setCodeMeaning(codeMeaning); + setCodingSchemeDesignator(codingSchemeDesignator); + if (!codingSchemeVersion.empty()) + { + setCodingSchemeVersion(codingSchemeVersion); + } +} + +CodeSequenceMacro::CodeSequenceMacro(OFshared_ptr< DcmItem > item, + OFshared_ptr< IODRules > rules, + IODComponent* parent, + const OFString& codeValue, + const OFString& codingSchemeDesignator, + const OFString& codeMeaning, + const OFString& codingSchemeVersion) +: IODComponent(item, rules, parent) +{ + // reset element rules + resetRules(); + setCodeValue(codeValue); + setCodeMeaning(codeMeaning); + setCodingSchemeDesignator(codingSchemeDesignator); + if (!codingSchemeVersion.empty()) + { + setCodingSchemeVersion(codingSchemeVersion); + } +} + + +OFString CodeSequenceMacro::getName() const +{ + return "CodeSequenceMacro"; +} + + +void CodeSequenceMacro::resetRules() +{ + m_Rules->addRule(new IODRule(DCM_CodeValue, "1", "1", "CodeSequenceMacro", DcmIODTypes::IE_UNDEFINED), OFTrue /*overwrite old rule*/); + m_Rules->addRule(new IODRule(DCM_CodingSchemeDesignator, "1", "1", "CodeSequenceMacro", DcmIODTypes::IE_UNDEFINED), OFTrue /*overwrite old rule*/); + m_Rules->addRule(new IODRule(DCM_CodingSchemeVersion, "1", "1C", "CodeSequenceMacro", DcmIODTypes::IE_UNDEFINED), OFTrue /*overwrite old rule*/); + m_Rules->addRule(new IODRule(DCM_CodeMeaning, "1", "1", "CodeSequenceMacro", DcmIODTypes::IE_UNDEFINED), OFTrue /*overwrite old rule*/); +} + + +// -- get dicom attributes -- + +OFCondition CodeSequenceMacro::getCodeValue(OFString &value, + const signed long pos) +{ + return DcmIODUtil::getStringValueFromItem(DCM_CodeValue, *m_Item, value, pos); +} + + +OFCondition CodeSequenceMacro::getCodingSchemeDesignator(OFString &value, + const signed long pos) +{ + return DcmIODUtil::getStringValueFromItem(DCM_CodingSchemeDesignator, *m_Item, value, pos); +} + + +OFCondition CodeSequenceMacro::getCodingSchemeVersion(OFString &value, + const signed long pos) +{ + return DcmIODUtil::getStringValueFromItem(DCM_CodingSchemeVersion, *m_Item, value, pos); + +} + + +OFCondition CodeSequenceMacro::getCodeMeaning(OFString &value, + const signed long pos) +{ + return DcmIODUtil::getStringValueFromItem(DCM_CodeMeaning, *m_Item, value, pos); +} + + +// -- set dicom attributes -- + +OFCondition CodeSequenceMacro::setCodeValue(const OFString &value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmShortString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_CodeValue, value); + return result; +} + +OFCondition CodeSequenceMacro::setCodingSchemeDesignator(const OFString &value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmShortString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_CodingSchemeDesignator, value); + return result; +} + +OFCondition CodeSequenceMacro::setCodingSchemeVersion(const OFString &value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmShortString::checkStringValue(value, "1C") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_CodingSchemeVersion, value); + return result; +} + +OFCondition CodeSequenceMacro::setCodeMeaning(const OFString &value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmLongString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_CodeMeaning, value); + return result; +} + + +OFCondition CodeSequenceMacro::set(const OFString& value, + const OFString& scheme, + const OFString& meaning, + const OFString& schemeVersion, + const OFBool checkValue) +{ + if (checkValue) + { + if (value.empty() || scheme.empty() || meaning.empty() ) + { + DCMIOD_ERROR("Could not set code since Code Value, Coding Scheme Designator and Code Meaning must have non-empty values"); + return IOD_EC_InvalidElementValue; + } + } + OFCondition result = setCodeValue(value, checkValue); + if (result.good()) result = setCodingSchemeDesignator(scheme, checkValue); + if (result.good()) result = setCodeMeaning(meaning, checkValue); + if (result.good() && !schemeVersion.empty()) result = setCodingSchemeVersion(schemeVersion, checkValue); + return result; +} + + +// ---------------------- SeriesAndInstanceReferenceMacro---------------------- + +const OFString IODSeriesAndInstanceReferenceMacro::m_ComponentName = "SeriesAndInstanceReferenceMacro"; +const OFString IODSeriesAndInstanceReferenceMacro::ReferencedSeriesItem::m_ComponentName = "SeriesAndInstanceReferenceMacro"; + +IODSeriesAndInstanceReferenceMacro::IODSeriesAndInstanceReferenceMacro(OFshared_ptr< DcmItem > data, + OFshared_ptr< IODRules > rules, + IODComponent* parent) +: IODComponent(data, rules, parent) +{ + // reset element rules + resetRules(); +} + + +IODSeriesAndInstanceReferenceMacro::IODSeriesAndInstanceReferenceMacro(IODComponent* parent) +: IODComponent(parent) +{ + // reset element rules + resetRules(); +} + + +OFString IODSeriesAndInstanceReferenceMacro::getName() const +{ + return m_ComponentName; +} + + +OFCondition IODSeriesAndInstanceReferenceMacro::read(DcmItem& source, + const OFBool clearOldData) +{ + if (clearOldData) + clearData(); + + DcmIODUtil::readSubSequence >(source, DCM_ReferencedSeriesSequence, m_ReferencedSeriesItems, m_Rules->getByTag(DCM_ReferencedSeriesSequence)); + return EC_Normal; +} + + +OFCondition IODSeriesAndInstanceReferenceMacro::write(DcmItem& destination) +{ + OFCondition result = EC_Normal; + + DcmIODUtil::writeSubSequence >(result, DCM_ReferencedSeriesSequence, m_ReferencedSeriesItems, destination, m_Rules->getByTag(DCM_ReferencedSeriesSequence)); + + return result; +} + + +void IODSeriesAndInstanceReferenceMacro::clearData() +{ + DcmIODUtil::freeContainer(m_ReferencedSeriesItems); +} + + +void IODSeriesAndInstanceReferenceMacro::resetRules() +{ + m_Rules->addRule(new IODRule(DCM_ReferencedSeriesSequence, "1-n", "1", m_ComponentName, DcmIODTypes::IE_INSTANCE), OFTrue); +} + + +OFVector< IODSeriesAndInstanceReferenceMacro::ReferencedSeriesItem* >& IODSeriesAndInstanceReferenceMacro::getReferencedSeriesItems() +{ + return m_ReferencedSeriesItems; +} + + +IODSeriesAndInstanceReferenceMacro::~IODSeriesAndInstanceReferenceMacro() +{ + DcmIODUtil::freeContainer(m_ReferencedSeriesItems); +} + + +IODSeriesAndInstanceReferenceMacro::ReferencedSeriesItem::ReferencedSeriesItem(OFshared_ptr< DcmItem > item, + OFshared_ptr< IODRules > rules, + IODComponent* parent) +: IODComponent(item, rules, parent), + m_ReferencedInstanceSequence() +{ + // reset element rules + resetRules(); +} + + +IODSeriesAndInstanceReferenceMacro::ReferencedSeriesItem::ReferencedSeriesItem(IODComponent* parent) +: IODComponent(parent), + m_ReferencedInstanceSequence() +{ + // reset element rules + resetRules(); +} + + +IODSeriesAndInstanceReferenceMacro::ReferencedSeriesItem::~ReferencedSeriesItem() +{ + clearData(); +} + + +OFString IODSeriesAndInstanceReferenceMacro::ReferencedSeriesItem::getName() const +{ + return m_ComponentName; +} + + +void IODSeriesAndInstanceReferenceMacro::ReferencedSeriesItem::clearData() +{ + DcmIODUtil::freeContainer(m_ReferencedInstanceSequence); + IODComponent::clearData(); +} + + + +OFCondition IODSeriesAndInstanceReferenceMacro::ReferencedSeriesItem::read(DcmItem& source, + const OFBool clearOldData) +{ + if (clearOldData) + clearData(); + + IODComponent::read(source, clearOldData); + DcmIODUtil::readSubSequence(source, DCM_ReferencedInstanceSequence, m_ReferencedInstanceSequence, m_Rules->getByTag(DCM_ReferencedInstanceSequence)); + return EC_Normal; +} + + +OFCondition IODSeriesAndInstanceReferenceMacro::ReferencedSeriesItem::write(DcmItem& destination) +{ + OFCondition result = EC_Normal; + + DcmIODUtil::writeSubSequence >(result, DCM_ReferencedInstanceSequence, m_ReferencedInstanceSequence, *m_Item, m_Rules->getByTag(DCM_ReferencedInstanceSequence)); + result = IODComponent::write(destination); + + return result; +} + + +void IODSeriesAndInstanceReferenceMacro::ReferencedSeriesItem::resetRules() +{ + // Parameters for Rule are tag, VM, type (1,1C,2,2C,3), module name and logical IOD level + m_Rules->addRule(new IODRule(DCM_SeriesInstanceUID, "1", "1", m_ComponentName, DcmIODTypes::IE_INSTANCE), OFTrue); + m_Rules->addRule(new IODRule(DCM_ReferencedInstanceSequence, "1-n", "1", m_ComponentName, DcmIODTypes::IE_INSTANCE), OFTrue); +} + + +OFVector< SOPInstanceReferenceMacro* >& IODSeriesAndInstanceReferenceMacro::ReferencedSeriesItem::getReferencedInstanceItems() +{ + return m_ReferencedInstanceSequence; +} + + +OFCondition IODSeriesAndInstanceReferenceMacro::ReferencedSeriesItem::getSeriesInstanceUID(OFString& value, + const long signed int pos) const +{ + return DcmIODUtil::getStringValueFromItem(DCM_SeriesInstanceUID, *m_Item, value, pos); +} + + +OFCondition IODSeriesAndInstanceReferenceMacro::ReferencedSeriesItem::setSeriesInstanceUID(const OFString& value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmUniqueIdentifier::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_SeriesInstanceUID, value); + return result; +} + + + +// ---------------------- SOPInstanceReferenceMacro ---------------------- + + +SOPInstanceReferenceMacro::SOPInstanceReferenceMacro(OFshared_ptr< DcmItem > item, + OFshared_ptr< IODRules > rules, + IODComponent* parent) +: IODComponent(item, rules, parent) +{ + // reset element rules + resetRules(); +} + + +SOPInstanceReferenceMacro::SOPInstanceReferenceMacro(IODComponent* parent) +: IODComponent(parent) +{ + // reset element rules + resetRules(); +} + + +SOPInstanceReferenceMacro::~SOPInstanceReferenceMacro() +{ + // nothing to do +} + + +OFString SOPInstanceReferenceMacro::getName() const +{ + return "SOPInstanceReferenceMacro"; +} + + +void SOPInstanceReferenceMacro::resetRules() +{ + // Parameters for Rule are tag, VM, type (1,1C,2,2C,3), module name and logical IOD level + m_Rules->addRule(new IODRule(DCM_ReferencedSOPClassUID, "1", "1", "SOPInstanceReferenceMacro", DcmIODTypes::IE_UNDEFINED), OFTrue); + m_Rules->addRule(new IODRule(DCM_ReferencedSOPInstanceUID, "1", "1", "SOPInstanceReferenceMacro", DcmIODTypes::IE_UNDEFINED), OFTrue); +} + + +// -- get dicom attributes -- + +OFCondition SOPInstanceReferenceMacro::getReferencedSOPClassUID(OFString &value, + const signed long pos) +{ + return DcmIODUtil::getStringValueFromItem(DCM_ReferencedSOPClassUID, *m_Item, value, pos); +} + +OFCondition SOPInstanceReferenceMacro::getReferencedSOPInstanceUID(OFString &value, + const signed long pos) +{ + return DcmIODUtil::getStringValueFromItem(DCM_ReferencedSOPInstanceUID, *m_Item, value, pos); +} + +// -- set dicom attributes -- + +OFCondition SOPInstanceReferenceMacro::setReferencedSOPClassUID(const OFString& value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmUniqueIdentifier::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_ReferencedSOPClassUID, value); + return result; +} + + +OFCondition SOPInstanceReferenceMacro::setReferencedSOPInstanceUID(const OFString& value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmUniqueIdentifier::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_ReferencedSOPInstanceUID, value); + return result; +} + + +// ---------------------- ImageSOPInstanceReferenceMacro ---------------------- + + +ImageSOPInstanceReferenceMacro::ImageSOPInstanceReferenceMacro() + : ReferencedFrameNumber(DCM_ReferencedFrameNumber), + ReferencedSegmentNumber(DCM_ReferencedSegmentNumber) +{ + +} + + +ImageSOPInstanceReferenceMacro::~ImageSOPInstanceReferenceMacro() +{ +} + +int ImageSOPInstanceReferenceMacro::compare(const IODComponent& rhs) const +{ + ImageSOPInstanceReferenceMacro *macro = OFstatic_cast(ImageSOPInstanceReferenceMacro*, OFconst_cast(IODComponent*, &rhs) ); + if (macro == NULL) return -1; + int result = ReferencedFrameNumber.compare(macro->ReferencedFrameNumber); + if (result == 0) ReferencedSegmentNumber.compare(macro->ReferencedSegmentNumber); + if (result == 0) return SOPInstanceReferenceMacro::compare(rhs); + return result; +} + +void ImageSOPInstanceReferenceMacro::clear() +{ + SOPInstanceReferenceMacro::clearData(); + ReferencedFrameNumber.clear(); + ReferencedSegmentNumber.clear(); +} + + +OFCondition ImageSOPInstanceReferenceMacro::read(DcmItem& source, + const OFBool clearOldData) +{ + /* re-initialize object */ + if (clearOldData) + clear(); + + OFCondition result = SOPInstanceReferenceMacro::read(source, clearOldData); + + DcmIODUtil::getAndCheckElementFromDataset(source, ReferencedFrameNumber, "1-n", "1C", "ImageSOPInstanceReferenceMacro"); + DcmIODUtil::getAndCheckElementFromDataset(source, ReferencedSegmentNumber, "1-n", "1C", "ImageSOPInstanceReferenceMacro"); + + return result; +} + + +OFCondition ImageSOPInstanceReferenceMacro::write(DcmItem& item) +{ + OFCondition result = EC_Normal; + /* copy all elements to dataset */ + DcmIODUtil::copyElementToDataset(result, item, ReferencedFrameNumber, "1-n" /* VM */, "1C" /* Type */, "ImageSOPInstanceReferenceMacro"); + DcmIODUtil::copyElementToDataset(result, item, ReferencedSegmentNumber, "1-n", "1C", "ImageSOPInstanceReferenceMacro"); + + if ( result.good() ) + result = SOPInstanceReferenceMacro::write(item); + + return result; +} + +// -- get dicom attributes -- + +OFCondition ImageSOPInstanceReferenceMacro::getReferencedFrameNumber(OFVector &values) +{ + // cast away const since underlying dcmdata routine is not const... + DcmIntegerString *is = OFconst_cast(DcmIntegerString*, &ReferencedFrameNumber); + return DcmIODUtil::getUint16ValuesFromElement(*is, values); +} + + +OFCondition ImageSOPInstanceReferenceMacro::getReferencedSegmentNumber(OFVector &values) +{ + // cast away const since underlying dcmdata routine is not const... + DcmUnsignedShort *us = OFconst_cast(DcmUnsignedShort*, &ReferencedSegmentNumber); + return DcmIODUtil::getUint16ValuesFromElement(*us, values); +} + +// -- set dicom attributes -- + + +OFCondition ImageSOPInstanceReferenceMacro::setReferencedFrameNumber(const OFVector& values, + const OFBool checkValue) +{ + return DcmIODUtil::setUint16ValuesOnElement(ReferencedFrameNumber, values, "1-n", checkValue); +} + + +OFCondition ImageSOPInstanceReferenceMacro::addReferencedFrameNumber(const Uint16& value, + const OFBool checkValue) +{ + const unsigned long count = ReferencedFrameNumber.getVM(); + return ReferencedFrameNumber.putUint16(value, count /* starts with 0, so add new value at the end */); +} + + + +OFCondition ImageSOPInstanceReferenceMacro::setReferencedSegmentNumber(const OFVector& values, + const OFBool checkValue) +{ + return DcmIODUtil::setUint16ValuesOnElement(ReferencedSegmentNumber, values, "1-n", checkValue); +} + + +OFCondition ImageSOPInstanceReferenceMacro::addReferencedSegmentNumber(const Uint16& value, + const OFBool checkValue) +{ + const unsigned long count = ReferencedSegmentNumber.getVM(); + return ReferencedSegmentNumber.putUint16(value, count /* starts with 0, so add new value at the end */); + +} + + + +// ---------------------- GeneralAnatomyMacro ---------------------- + + + +GeneralAnatomyMacro::GeneralAnatomyMacro(const OFString& type) : + m_Type(type), + m_AnatomicRegion(), + m_AnatomicRegionModifier(), + m_PrimaryAnatomicStructure() +{ + m_Type = type; +} + + +GeneralAnatomyMacro::GeneralAnatomyMacro(const GeneralAnatomyMacro& rhs) +: m_Type(rhs.m_Type), + m_AnatomicRegion(), + m_AnatomicRegionModifier(), + m_PrimaryAnatomicStructure() +{ + if (this != &rhs) + { + m_Type = rhs.m_Type; + m_AnatomicRegion = m_AnatomicRegion; + m_PrimaryAnatomicStructure = rhs.m_PrimaryAnatomicStructure; + + OFVector::const_iterator it = rhs.m_AnatomicRegionModifier.begin(); + while ( it != rhs.m_AnatomicRegionModifier.end() ) + { + m_AnatomicRegionModifier.push_back( new CodeSequenceMacro(**it) ); + it++; + } + } +} + + + +GeneralAnatomyMacro::~GeneralAnatomyMacro() +{ + clearData(); +} + + +void GeneralAnatomyMacro::clearData() +{ + // m_Type stays the same + m_AnatomicRegion.clearData(); + DcmIODUtil::freeContainer(m_AnatomicRegionModifier); + m_PrimaryAnatomicStructure.clearData(); +} + + +OFCondition GeneralAnatomyMacro::check(const OFBool quiet) +{ + OFCondition result = m_AnatomicRegion.check(quiet); + if (result.bad()) + return result; + + OFVector::iterator it = m_AnatomicRegionModifier.begin(); + while (it != m_AnatomicRegionModifier.begin()) + { + result = (*it)->check(quiet); + if (result.bad()) return result; + it++; + } + result = m_PrimaryAnatomicStructure.check(quiet); + return result; +} + + +CodeSequenceMacro& GeneralAnatomyMacro::getAnatomicRegion() +{ + return m_AnatomicRegion; +} + + +OFVector& GeneralAnatomyMacro::getAnatomicRegionModifier() +{ + return m_AnatomicRegionModifier; +} + + +PrimaryAnatomicStructureMacro& GeneralAnatomyMacro::getPrimaryAnatomicStructure() +{ + return m_PrimaryAnatomicStructure; +} + + +// Reads Anatomic Region Sequence and Primary Anatomic Structure Macro from given item +OFCondition GeneralAnatomyMacro::read(DcmItem& source, + const OFBool clearOldData) +{ + OFCondition result = EC_Normal; + + /* re-initialize object */ + if (clearOldData) + clearData(); + + /* read Anatomic Region Sequence item into Code Sequence Macro */ + DcmIODUtil::readSingleItem(source, DCM_AnatomicRegionSequence, m_AnatomicRegion, m_Type, "GeneralAnatomyMacro"); + + /* Get the single item from Anatomic Region Sequence */ + DcmItem* localItem = NULL; + if ( source.findAndGetSequenceItem(DCM_AnatomicRegionSequence, localItem).bad() ) + { + return result; + } + + /* read Anatomic Region Modifier Sequence from */ + DcmIODUtil::readSubSequence > + ( *localItem, /* item of Anatomic Region Sequence */ + DCM_AnatomicRegionModifierSequence, + m_AnatomicRegionModifier, + "1-n", + "3", + "GeneralAnatomyMacro" ); + + /* read Primary Anatomic Structure Macro (main level, i.e.\ original item) */ + m_PrimaryAnatomicStructure.read(source); + + return result; +} + + +/// Write Anatomic Region Sequence from given item +OFCondition GeneralAnatomyMacro::write(DcmItem& item) +{ + OFCondition result = EC_Normal; + + /* delete old data */ + item.findAndDeleteElement(DCM_AnatomicRegionSequence); + + /* Write sub structures */ + DcmIODUtil::writeSingleItem(result, DCM_AnatomicRegionSequence, m_AnatomicRegion, item, m_Type, "GeneralAnatomyMacro"); + DcmIODUtil::writeSubSequence > + ( result, + DCM_AnatomicRegionModifierSequence, + m_AnatomicRegionModifier, + item, + "1-n", + "3", + "GeneralAnatomyMacro"); + return result; +} + + +GeneralAnatomyMacro& GeneralAnatomyMacro::operator=(const GeneralAnatomyMacro& rhs) +{ + if (this != &rhs) + { + clearData(); + m_Type = rhs.m_Type; + m_AnatomicRegion = rhs.m_AnatomicRegion; + m_PrimaryAnatomicStructure = rhs.m_PrimaryAnatomicStructure; + + OFVector::const_iterator it = rhs.m_AnatomicRegionModifier.begin(); + while ( it != rhs.m_AnatomicRegionModifier.end() ) + { + m_AnatomicRegionModifier.push_back( new CodeSequenceMacro(**it) ); + it++; + } + } + return *this; +} + + +// ---------------------- PrimaryAnatomicStructureMacroItem ------------------ + +PrimaryAnatomicStructureMacroItem::PrimaryAnatomicStructureMacroItem() : + m_AnatomicStructure(), + m_AnatomicStructureModifier() +{ +} + + +PrimaryAnatomicStructureMacroItem::PrimaryAnatomicStructureMacroItem(const PrimaryAnatomicStructureMacroItem& rhs) : + m_AnatomicStructure(), + m_AnatomicStructureModifier() +{ + if (this != &rhs) + { + m_AnatomicStructure = rhs.m_AnatomicStructure; + OFVector::const_iterator it = rhs.m_AnatomicStructureModifier.begin(); + while ( it != rhs.m_AnatomicStructureModifier.begin() ) + { + m_AnatomicStructureModifier.push_back(new CodeSequenceMacro(**it)); + it++; + } + } +} + + +PrimaryAnatomicStructureMacroItem& PrimaryAnatomicStructureMacroItem::operator=(const PrimaryAnatomicStructureMacroItem& rhs) +{ + if (this != &rhs) + { + clearData(); + m_AnatomicStructure = rhs.m_AnatomicStructure; + OFVector::const_iterator it = rhs.m_AnatomicStructureModifier.begin(); + while ( it != rhs.m_AnatomicStructureModifier.begin() ) + { + m_AnatomicStructureModifier.push_back(new CodeSequenceMacro(**it)); + it++; + } + } + return *this; +} + + +PrimaryAnatomicStructureMacroItem::~PrimaryAnatomicStructureMacroItem() +{ + clearData(); +} + + +void PrimaryAnatomicStructureMacroItem::clearData() +{ + m_AnatomicStructure.clearData(); + m_AnatomicStructureModifier.clear(); + DcmIODUtil::freeContainer(m_AnatomicStructureModifier); +} + + +OFCondition PrimaryAnatomicStructureMacroItem::check(const OFBool quiet) +{ + OFCondition result = m_AnatomicStructure.check(); + if (result.bad()) return result; + + OFVector::iterator it = m_AnatomicStructureModifier.begin(); + while (it != m_AnatomicStructureModifier.end()) + { + result = (*it)->check(quiet); + if (result.bad()) + return result; + it++; + } + return result; +} + + + +CodeSequenceMacro& PrimaryAnatomicStructureMacroItem::getAnatomicStructure() +{ + return m_AnatomicStructure; +} + + +OFVector& PrimaryAnatomicStructureMacroItem::getAnatomicStructureModifier() +{ + return m_AnatomicStructureModifier; +} + + +OFCondition PrimaryAnatomicStructureMacroItem::read(DcmItem& source, + const OFBool clearOldData) +{ + OFCondition result = EC_Normal; + + /* re-initialize object */ + if (clearOldData) + clearData(); + + m_AnatomicStructure.read(source); + + /* check whether cardinality of Primary Anatomic Structure Modifier Sequence and type is ok (produces warnings if not) */ + DcmIODUtil::checkSubSequence(result, source, DCM_PrimaryAnatomicStructureModifierSequence, "1-n", "3", "PrimaryAnatomicStructureMacro"); + + /* read Primary Anatomic Structure Modifier Sequence */ + DcmIODUtil::readSubSequence > + ( source, /* item of Primary Anatomic Structure Sequence */ + DCM_PrimaryAnatomicStructureModifierSequence, + m_AnatomicStructureModifier, + "1-n", + "3", + "GeneralAnatomyMacro" ); + + return result; +} + + +/// Write Primary Anatomic Structure Sequence Item to given item +OFCondition PrimaryAnatomicStructureMacroItem::write(DcmItem& source) +{ + OFCondition result; + m_AnatomicStructure.write(source); + DcmIODUtil::writeSubSequence > + ( + result, + DCM_PrimaryAnatomicStructureModifierSequence, + m_AnatomicStructureModifier, + source, + "1-n", + "3", + "PrimaryAnatomicStructureMacro" + ); + return result; +} + + +// ---------------------- PrimaryAnatomicStructureMacro ---------------------- + + +PrimaryAnatomicStructureMacro::PrimaryAnatomicStructureMacro() : + m_PrimaryAnatomicStructure() +{ + +} + + +PrimaryAnatomicStructureMacro::PrimaryAnatomicStructureMacro(const PrimaryAnatomicStructureMacro& rhs) +{ + if (this != &rhs) + { + OFVector::const_iterator it = rhs.m_PrimaryAnatomicStructure.begin(); + while ( it != rhs.m_PrimaryAnatomicStructure.begin() ) + { + m_PrimaryAnatomicStructure.push_back(new PrimaryAnatomicStructureMacroItem(**it)); + it++; + } + } +} + + +PrimaryAnatomicStructureMacro::~PrimaryAnatomicStructureMacro() +{ + clearData(); +} + + +void PrimaryAnatomicStructureMacro::clearData() +{ + m_PrimaryAnatomicStructure.clear(); +} + + +OFCondition PrimaryAnatomicStructureMacro::check(const OFBool quiet) +{ + OFCondition result; + OFVector::iterator it = m_PrimaryAnatomicStructure.begin(); + while (it != m_PrimaryAnatomicStructure.end()) + { + result = (*it)->check(quiet); + if (result.bad()) return result; + it++; + } + return result; +} + + +OFVector& PrimaryAnatomicStructureMacro::getPrimaryAnatomicStructure() +{ + return m_PrimaryAnatomicStructure; +} + + +/// Reads Primary Anatomic Region Sequence from given item +OFCondition PrimaryAnatomicStructureMacro::read(DcmItem& source, + const OFBool clearOldData) +{ + OFCondition result; + + if (clearOldData) + clearData(); + + // check for sequence and report warnings if not ok */ + DcmIODUtil::checkSubSequence(result, source, DCM_PrimaryAnatomicStructureSequence, "1-n", "3", "PrimaryAnantomicStructureMacro"); + + // read sequence into member + DcmIODUtil::readSubSequence > + ( source, + DCM_PrimaryAnatomicStructureSequence, + m_PrimaryAnatomicStructure, + "1-n", + "3", + "PrimaryAnatomicStructureMacro" + ); + return result; +} + + +/// Write Anatomic Region Sequence from given item +OFCondition PrimaryAnatomicStructureMacro::write(DcmItem& item) +{ + OFCondition result = EC_Normal; + + /* delete old data */ + item.findAndDeleteElement(DCM_PrimaryAnatomicStructureSequence); + item.insertEmptyElement(DCM_PrimaryAnatomicStructureSequence); + + DcmIODUtil::writeSubSequence > + ( + result, + DCM_PrimaryAnatomicStructureSequence, + m_PrimaryAnatomicStructure, + item, + "1-n", + "3", + "PrimaryAnatomicStructureMacro" + ); + + return result; +} + + +PrimaryAnatomicStructureMacro& PrimaryAnatomicStructureMacro::operator=(const PrimaryAnatomicStructureMacro& rhs) +{ + if (this != &rhs) + { + clearData(); + OFVector::const_iterator it = rhs.m_PrimaryAnatomicStructure.begin(); + while ( it != rhs.m_PrimaryAnatomicStructure.begin() ) + { + m_PrimaryAnatomicStructure.push_back(new PrimaryAnatomicStructureMacroItem(**it)); + it++; + } + } + return *this; +} + + +// ---------------------- AlgorithmIdentificationMacro ---------------------- + + +AlgorithmIdentificationMacro::AlgorithmIdentificationMacro() : + m_AlgorithmFamilyCode(), + m_AlgorithmNameCode(), + m_AlgorithmName(DCM_AlgorithmName), + m_AlgorithmVersion(DCM_AlgorithmVersion), + m_AlgorithmParameters(DCM_AlgorithmParameters), + m_AlgorithmSource(DCM_AlgorithmSource) +{ + +} +// +AlgorithmIdentificationMacro::~AlgorithmIdentificationMacro() +{ + clearData(); +} + + +void AlgorithmIdentificationMacro::clearData() +{ + m_AlgorithmFamilyCode.clearData(); + m_AlgorithmNameCode.clearData(); + m_AlgorithmName.clear(); + m_AlgorithmVersion.clear(); + m_AlgorithmParameters.clear(); + m_AlgorithmSource.clear(); +} + + +OFCondition AlgorithmIdentificationMacro::check(const OFBool quiet) +{ + OFCondition result; + result = m_AlgorithmFamilyCode.check(quiet); + if ( result.good() ) + { + if ( m_AlgorithmName.isEmpty() || m_AlgorithmVersion.isEmpty() ) + { + result = EC_MissingValue; + } + } + return result; +} + + + +CodeSequenceMacro& AlgorithmIdentificationMacro::getAlgorithmFamilyCode() +{ + return m_AlgorithmFamilyCode; +} + + +CodeSequenceMacro& AlgorithmIdentificationMacro::getAlgorithmNameCode() +{ + return m_AlgorithmNameCode; +} + + +OFCondition AlgorithmIdentificationMacro::getAlgorithmName(OFString& value, + const signed long pos) +{ + return DcmIODUtil::getStringValueFromElement(m_AlgorithmName, value, pos); +} + + +OFCondition AlgorithmIdentificationMacro::getAlgorithmVersion(OFString& value, + const signed long pos) +{ + return DcmIODUtil::getStringValueFromElement(m_AlgorithmVersion, value, pos); +} + + +OFCondition AlgorithmIdentificationMacro::getAlgorithmParameters(OFString& value, + const signed long pos) +{ + return DcmIODUtil::getStringValueFromElement(m_AlgorithmParameters, value, pos); +} + + +OFCondition AlgorithmIdentificationMacro::getAlgorithmSource(OFString& value, + const signed long pos) +{ + return DcmIODUtil::getStringValueFromElement(m_AlgorithmSource, value, pos); +} + + +OFCondition AlgorithmIdentificationMacro::setAlgorithmName(const OFString& value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmLongString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_AlgorithmName.putOFStringArray(value); + return result; +} + + +OFCondition AlgorithmIdentificationMacro::setAlgorithmVersion(const OFString& value, + const OFBool checkValue) + +{ + OFCondition result = (checkValue) ? DcmLongString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_AlgorithmVersion.putOFStringArray(value); + return result; +} + + +OFCondition AlgorithmIdentificationMacro::setAlgorithmParameters(const OFString& value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmLongText::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_AlgorithmParameters.putOFStringArray(value); + return result; +} + + +OFCondition AlgorithmIdentificationMacro::setAlgorithmSource(const OFString& value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmLongString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_AlgorithmSource.putOFStringArray(value); + return result; +} + + +/// Reads Anatomic Region Sequence and Primary Anatomic Structure Macro from given item +OFCondition AlgorithmIdentificationMacro::read(DcmItem& source, + const OFBool clearOldData) +{ + OFCondition result; + + if (clearOldData) + clearData(); + + DcmIODUtil::readSingleItem + ( + source, + DCM_AlgorithmFamilyCodeSequence, + m_AlgorithmFamilyCode, + "1", + "AlgorithmIdentificationMacro" + ); + + DcmIODUtil::readSingleItem + ( + source, + DCM_AlgorithmNameCodeSequence, + m_AlgorithmNameCode, + "3", + "AlgorithmIdentificationMacro"); + + DcmIODUtil::getAndCheckElementFromDataset(source, m_AlgorithmName, "1", "1", "AlgorithmIdentificationMacro"); + DcmIODUtil::getAndCheckElementFromDataset(source, m_AlgorithmVersion, "1", "1", "AlgorithmIdentificationMacro"); + DcmIODUtil::getAndCheckElementFromDataset(source, m_AlgorithmParameters, "1", "3", "AlgorithmIdentificationMacro"); + DcmIODUtil::getAndCheckElementFromDataset(source, m_AlgorithmSource, "1", "3", "AlgorithmIdentificationMacro"); + + return result; +} + + +OFCondition AlgorithmIdentificationMacro::write(DcmItem& item) +{ + OFCondition result = EC_Normal; + + // write to item + DcmIODUtil::copyElementToDataset(result, item, m_AlgorithmName, "1", "1", "AlgorithmIdentificationMacro"); + DcmIODUtil::copyElementToDataset(result, item, m_AlgorithmVersion, "1", "1", "AlgorithmIdentificationMacro"); + DcmIODUtil::copyElementToDataset(result, item, m_AlgorithmParameters, "1", "3", "AlgorithmIdentificationMacro"); + DcmIODUtil::copyElementToDataset(result, item, m_AlgorithmSource, "1", "3", "AlgorithmIdentificationMacro"); + + DcmIODUtil::writeSingleItem + ( result, + DCM_AlgorithmFamilyCodeSequence, + m_AlgorithmFamilyCode, + item, + "1", + "AlgorithmIdentificationMacro" + ); + + DcmIODUtil::writeSingleItem + ( result, + DCM_AlgorithmNameCodeSequence, + m_AlgorithmNameCode, + item, + "3", + "AlgorithmIdentificationMacro" + ); + + return result; +} + + +// ---------------------- ContentIdentificationMacro ---------------------- + +ContentIdentificationMacro::ContentIdentificationMacro() : + m_InstanceNumber(DCM_InstanceNumber), + m_ContentLabel(DCM_ContentLabel), + m_ContentDescription(DCM_ContentDescription), + m_AlternateContentDescription(), + m_ContentCreatorName(DCM_ContentCreatorName), + m_ContentCreatorIdentificationCode(), + m_IODRules() +{ + resetRules(); +} + + +void ContentIdentificationMacro::resetRules() +{ + m_IODRules.addRule(new IODRule(DCM_InstanceNumber, "1", "1", "ContentIdentificationMacro", DcmIODTypes::IE_INSTANCE), OFTrue); + m_IODRules.addRule(new IODRule(DCM_ContentLabel, "1", "1", "ContentIdentificationMacro", DcmIODTypes::IE_INSTANCE), OFTrue); + m_IODRules.addRule(new IODRule(DCM_ContentDescription, "1", "2", "ContentIdentificationMacro", DcmIODTypes::IE_INSTANCE), OFTrue); + m_IODRules.addRule(new IODRule(DCM_ContentCreatorName, "1", "2", "ContentIdentificationMacro", DcmIODTypes::IE_INSTANCE), OFTrue); + m_IODRules.addRule(new IODRule(DCM_AlternateContentDescriptionSequence, "1-n", "3", "ContentIdentificationMacro", DcmIODTypes::IE_INSTANCE), OFTrue); + m_IODRules.addRule(new IODRule(DCM_ContentCreatorIdentificationCodeSequence, "1", "3", "ContentIdentificationMacro", DcmIODTypes::IE_INSTANCE), OFTrue); +} + + +IODRules& ContentIdentificationMacro::getIODRules() +{ + return m_IODRules; +} + + +ContentIdentificationMacro::ContentIdentificationMacro(const ContentIdentificationMacro& rhs) : + m_InstanceNumber(DCM_InstanceNumber), + m_ContentLabel(DCM_ContentLabel), + m_ContentDescription(DCM_ContentDescription), + m_AlternateContentDescription(), + m_ContentCreatorName(DCM_ContentCreatorName), + m_ContentCreatorIdentificationCode(), + m_IODRules() +{ + if (&rhs != this) + { + resetRules(); + m_InstanceNumber = rhs.m_InstanceNumber; + m_ContentLabel = rhs.m_ContentLabel; + m_ContentDescription = rhs.m_ContentDescription; + m_ContentCreatorName = rhs.m_ContentCreatorName; + m_ContentCreatorIdentificationCode = rhs.m_ContentCreatorIdentificationCode; + /* perform deep vector copy */ + OFVector::const_iterator it = rhs.m_AlternateContentDescription.begin(); + while (it != rhs.m_AlternateContentDescription.end()) + { + m_AlternateContentDescription.push_back(new AlternateContentDescriptionItem(**it)); + it++; + } + } +} + + +ContentIdentificationMacro& ContentIdentificationMacro::operator=(const ContentIdentificationMacro& rhs) +{ + if (&rhs != this) + { + this->clearData(); + m_InstanceNumber = rhs.m_InstanceNumber; + m_ContentLabel = rhs.m_ContentLabel; + m_ContentDescription = rhs.m_ContentDescription; + m_ContentCreatorName = rhs.m_ContentCreatorName; + m_ContentCreatorIdentificationCode = rhs.m_ContentCreatorIdentificationCode; + /* perform deep vector copy */ + OFVector::const_iterator it = rhs.m_AlternateContentDescription.begin(); + while (it != rhs.m_AlternateContentDescription.end()) + { + AlternateContentDescriptionItem* newItem = new AlternateContentDescriptionItem(); + *newItem = **it; + m_AlternateContentDescription.push_back(newItem); + it++; + } + } + return *this; +} + + +ContentIdentificationMacro::~ContentIdentificationMacro() +{ + clearData(); +} + + +void ContentIdentificationMacro::clearData() +{ + m_InstanceNumber.clear(); + m_ContentLabel.clear(); + m_ContentDescription.clear(); + DcmIODUtil::freeContainer(m_AlternateContentDescription); + m_ContentCreatorName.clear(); + m_ContentCreatorIdentificationCode.clearData(); +} + + +OFCondition ContentIdentificationMacro::check(const OFBool quiet) +{ + OFCondition result; + OFBool failure = m_ContentLabel.isEmpty() || m_InstanceNumber.isEmpty(); + if (!failure) + { + if (!m_AlternateContentDescription.empty()) // type 3 + { + OFVector::iterator it = m_AlternateContentDescription.begin(); + while ( it != m_AlternateContentDescription.end() && !failure) + { + OFString str; + (*it)->getContentDescription(str).good(); // type 1 + failure = str.empty(); + if (!failure) + { + OFString meaning, value, designator; + (*it)->getLanguageCode().getCodeMeaning(meaning); + (*it)->getLanguageCode().getCodeValue(value); + (*it)->getLanguageCode().getCodeValue(designator); + failure = meaning.empty() || value.empty() || designator.empty(); + } + it++; + } + } + } + if ( failure ) + result = EC_IllegalParameter; + return result; +} + + + +OFCondition ContentIdentificationMacro::getInstanceNumber(OFString& value, + const signed long pos) const +{ + return DcmIODUtil::getStringValueFromElement(m_InstanceNumber, value, pos); +} + + + +OFCondition ContentIdentificationMacro::getContentLabel(OFString& value, + const signed long pos) const +{ + return DcmIODUtil::getStringValueFromElement(m_ContentLabel, value, pos); +} + + +OFCondition ContentIdentificationMacro::getContentDescription(OFString& value, + const signed long pos) const +{ + return DcmIODUtil::getStringValueFromElement(m_ContentDescription, value, pos); +} + + +OFCondition ContentIdentificationMacro::getContentCreatorName(OFString& value, + const signed long pos) const +{ + return DcmIODUtil::getStringValueFromElement(m_ContentCreatorName, value, pos); +} + + +CodeSequenceMacro& ContentIdentificationMacro::getContentCreatorIdentificationCode() +{ + return m_ContentCreatorIdentificationCode; +} + + +OFVector& ContentIdentificationMacro::getAlternateContentDescription() +{ + return m_AlternateContentDescription; +} + + +OFCondition ContentIdentificationMacro::setInstanceNumber(const OFString& value, + const OFBool checkValue) +{ + return m_InstanceNumber.putOFStringArray(value); +} + + +OFCondition ContentIdentificationMacro::setContentLabel(const OFString& value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmCodeString::checkStringValue(value, m_IODRules.getByTag(DCM_ContentLabel)->getVM()) : EC_Normal; + if (result.good()) + result = m_ContentLabel.putOFStringArray(value); + return result; +} + + +OFCondition ContentIdentificationMacro::setContentDescription(const OFString& value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmLongString::checkStringValue(value, m_IODRules.getByTag(DCM_ContentDescription)->getVM()) : EC_Normal; + if (result.good()) + result = m_ContentDescription.putOFStringArray(value); + return result; +} + + +OFCondition ContentIdentificationMacro::setContentCreatorName(const OFString& value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmPersonName::checkStringValue(value, m_IODRules.getByTag(DCM_ContentCreatorName)->getVM()) : EC_Normal; + if (result.good()) + result = m_ContentCreatorName.putOFStringArray(value); + return result; +} + + +OFCondition ContentIdentificationMacro::read(DcmItem& source, + const OFBool clearOldData) +{ + OFCondition result; + + if (clearOldData) + clearData(); + + /* flat elements */ + + DcmIODUtil::getAndCheckElementFromDataset(source, m_InstanceNumber, m_IODRules.getByTag(DCM_InstanceNumber)); + DcmIODUtil::getAndCheckElementFromDataset(source, m_ContentLabel, m_IODRules.getByTag(DCM_ContentLabel)); + DcmIODUtil::getAndCheckElementFromDataset(source, m_ContentDescription, m_IODRules.getByTag(DCM_ContentDescription)); + DcmIODUtil::getAndCheckElementFromDataset(source, m_ContentCreatorName, m_IODRules.getByTag(DCM_ContentCreatorName)); + + /* sub sequences */ + IODRule *rule = m_IODRules.getByTag(DCM_AlternateContentDescriptionSequence); + DcmIODUtil::readSubSequence > + ( source, + DCM_AlternateContentDescriptionSequence, + m_AlternateContentDescription, + rule->getVM(), + rule->getType(), + "ContentIdentificationMacro" ); + + rule = m_IODRules.getByTag(DCM_ContentCreatorIdentificationCodeSequence); + DcmIODUtil::readSingleItem + ( + source, + DCM_ContentCreatorIdentificationCodeSequence, + m_ContentCreatorIdentificationCode, + rule->getType(), + "ContentIdentificationMacro"); + + return result; +} + + +OFCondition ContentIdentificationMacro::write(DcmItem& item) +{ + OFCondition result = EC_Normal; + + /* flat elements */ + DcmIODUtil::copyElementToDataset(result, item, m_InstanceNumber, m_IODRules.getByTag(DCM_InstanceNumber)); + DcmIODUtil::copyElementToDataset(result, item, m_ContentLabel, m_IODRules.getByTag(DCM_ContentLabel)); + DcmIODUtil::copyElementToDataset(result, item, m_ContentDescription, m_IODRules.getByTag(DCM_ContentDescription)); + DcmIODUtil::copyElementToDataset(result, item, m_ContentCreatorName, m_IODRules.getByTag(DCM_ContentCreatorName)); + + IODRule *rule = m_IODRules.getByTag(DCM_ContentCreatorIdentificationCodeSequence); + DcmIODUtil::writeSingleItem + ( + result, + DCM_ContentCreatorIdentificationCodeSequence, + m_ContentCreatorIdentificationCode, + item, + rule->getType(), + "ContentIdentificationMacro" + ); + + rule = m_IODRules.getByTag(DCM_AlternateContentDescriptionSequence); + DcmIODUtil::writeSubSequence< OFVector > + ( + result, + DCM_AlternateContentDescriptionSequence, + m_AlternateContentDescription, + item, + rule->getVM(), + rule->getType(), + "ContentIdentificationMacro" + ); + + return result; + +} + + +// ---------------- ContentIdentificationMacro::AlternateContentDescriptionItem ----------------- + +ContentIdentificationMacro::AlternateContentDescriptionItem::AlternateContentDescriptionItem() + : m_ContentDescription(DCM_ContentDescription), + m_LanguageCode() +{ + // nothing to do +} + + +ContentIdentificationMacro::AlternateContentDescriptionItem::~AlternateContentDescriptionItem() +{ + m_LanguageCode.clearData(); +} + + +void ContentIdentificationMacro::AlternateContentDescriptionItem::clearData() +{ + m_ContentDescription.clear(); + m_LanguageCode.clearData(); +} + + +OFCondition ContentIdentificationMacro::AlternateContentDescriptionItem::read(DcmItem& source, + const OFBool clearOldData) +{ + OFCondition result; + if (clearOldData) + clearData(); + + DcmIODUtil::getAndCheckElementFromDataset(source, m_ContentDescription, "1", "1", "ContentIdentificationMacro"); + DcmIODUtil::readSingleItem + ( + source, + DCM_LanguageCodeSequence, + m_LanguageCode, + "1", + "ContentIdentificationMacro" + ); + + return result; +} + + +OFCondition ContentIdentificationMacro::AlternateContentDescriptionItem::getContentDescription(OFString& value, + const long signed int pos) +{ + return DcmIODUtil::getStringValueFromElement(m_ContentDescription, value, pos); +} + + + +CodeSequenceMacro& ContentIdentificationMacro::AlternateContentDescriptionItem::getLanguageCode() +{ + return m_LanguageCode; +} + + + +OFCondition ContentIdentificationMacro::AlternateContentDescriptionItem::write(DcmItem& item) +{ + OFCondition result = EC_Normal; + // write to item + DcmIODUtil::copyElementToDataset(result, item, m_ContentDescription, "1", "1", "ContentIdentificationMacro"); + DcmIODUtil::writeSingleItem + ( result, + DCM_LanguageCodeSequence, + m_LanguageCode, + item, + "1", + "ContentIdentificationMacro" + ); + return result; +} + + +OFCondition ContentIdentificationMacro::AlternateContentDescriptionItem::setContentDescription(const OFString& value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmLongString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_ContentDescription.putOFStringArray(value); + return result; +} + + +// -------------------- HL7HierarchicDesignatorMacro -------------------- + + +HL7HierarchicDesignatorMacro::HL7HierarchicDesignatorMacro(IODComponent* parent) +: IODComponent(parent) +{ + // reset element rules + resetRules(); +} + +HL7HierarchicDesignatorMacro::HL7HierarchicDesignatorMacro(OFshared_ptr< DcmItem > item, + OFshared_ptr< IODRules > rules, + IODComponent* parent) +: IODComponent(item, rules, parent) +{ + // reset element rules + resetRules(); +} + + +OFCondition HL7HierarchicDesignatorMacro::getUniversalEntityID(OFString& value, const long signed int pos) const +{ + return DcmIODUtil::getStringValueFromItem(DCM_UniversalEntityID, *m_Item, value, pos); +} + + +OFCondition HL7HierarchicDesignatorMacro::getLocalNamespaceEntityID(OFString& value, const long signed int pos) const +{ + return DcmIODUtil::getStringValueFromItem(DCM_LocalNamespaceEntityID, *m_Item, value, pos); +} + + +OFCondition HL7HierarchicDesignatorMacro::getUniversalEntityIDType(OFString& value, const long signed int pos) const +{ + return DcmIODUtil::getStringValueFromItem(DCM_UniversalEntityIDType, *m_Item, value, pos); +} + + +OFString HL7HierarchicDesignatorMacro::getName() const +{ + return "HL7HierarchicDesignatorMacro"; +} + + +void HL7HierarchicDesignatorMacro::resetRules() +{ + // parameters are tag, VM, type. Overwrite old rules if any. + m_Rules->addRule(new IODRule(DCM_UniversalEntityID, "1","1C", "HL7HierarchicDesignatorMacro", DcmIODTypes::IE_UNDEFINED), OFTrue); + m_Rules->addRule(new IODRule(DCM_LocalNamespaceEntityID, "1","1C", "HL7HierarchicDesignatorMacro", DcmIODTypes::IE_UNDEFINED), OFTrue); + m_Rules->addRule(new IODRule(DCM_UniversalEntityIDType, "1","1C", "HL7HierarchicDesignatorMacro", DcmIODTypes::IE_UNDEFINED), OFTrue); +} + + +OFCondition HL7HierarchicDesignatorMacro::setLocalNamespaceEntityID(const OFString& value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmUnlimitedText::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_LocalNamespaceEntityID,value); + return result; +} + + +OFCondition HL7HierarchicDesignatorMacro::setUniversalEntityID(const OFString& value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmUnlimitedText::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_UniversalEntityID,value); + return result; +} + + +OFCondition HL7HierarchicDesignatorMacro::setUniversalEntityIDType(const OFString& value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmCodeString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_UniversalEntityID,value); + return result; +} + + + +// -------------------- Mandatory View and Slice Progression Direction Macro -------------------- + +MandatoryViewAndSliceProgressionDirectionMacro::MandatoryViewAndSliceProgressionDirectionMacro(OFshared_ptr< DcmItem > item, + OFshared_ptr< IODRules > rules, + IODComponent* parent) +: IODComponent(item, rules, parent) +{ + resetRules(); +} + + + +MandatoryViewAndSliceProgressionDirectionMacro::MandatoryViewAndSliceProgressionDirectionMacro(IODComponent* parent) +: IODComponent(parent) +{ + resetRules(); +} + + +OFString MandatoryViewAndSliceProgressionDirectionMacro::getName() const +{ + return "MandatoryViewAndSliceProgressionDirectionMacro"; +} + + +void MandatoryViewAndSliceProgressionDirectionMacro::resetRules() +{ + m_Rules->addRule(new IODRule(DCM_ViewCodeSequence, "1","1", "MandatoryViewAndSliceProgressionDirectionMacro", DcmIODTypes::IE_UNDEFINED), OFTrue); + m_Rules->addRule(new IODRule(DCM_ViewModifierCodeSequence, "1-n","2C", "MandatoryViewAndSliceProgressionDirectionMacro", DcmIODTypes::IE_UNDEFINED), OFTrue); + m_Rules->addRule(new IODRule(DCM_SliceProgressionDirection, "1","1C", "MandatoryViewAndSliceProgressionDirectionMacro", DcmIODTypes::IE_UNDEFINED), OFTrue); +} + + +void MandatoryViewAndSliceProgressionDirectionMacro::clearData() +{ + DcmIODUtil::freeContainer(m_ViewModifierCode); + m_ViewCodeSequence.clearData(); + IODComponent::clearData(); +} + + + +OFCondition MandatoryViewAndSliceProgressionDirectionMacro::read(DcmItem& source, + const OFBool clearOldData) +{ + if (clearOldData) + { + m_ViewCodeSequence.clearData(); + DcmIODUtil::freeContainer(m_ViewModifierCode); + } + OFCondition result = EC_Normal; + DcmIODUtil::readSingleItem(source, DCM_ViewCodeSequence, m_ViewCodeSequence, m_Rules->getByTag(DCM_ViewCodeSequence)); + DcmIODUtil::readSubSequence(source, DCM_ViewCodeSequence, m_ViewModifierCode, m_Rules->getByTag(DCM_ViewCodeSequence)); + IODComponent::read(source, clearOldData); + return EC_Normal; +} + + +OFCondition MandatoryViewAndSliceProgressionDirectionMacro::write(DcmItem& item) +{ + OFCondition result = EC_Normal; + DcmIODUtil::writeSingleItem(result, DCM_ViewCodeSequence, m_ViewCodeSequence, *m_Item, m_Rules->getByTag(DCM_ViewCodeSequence)); + DcmIODUtil::writeSubSequence(result, DCM_ViewCodeSequence, m_ViewModifierCode, *m_Item, m_Rules->getByTag(DCM_ViewModifierCodeSequence)); + if (result.good()) result = IODComponent::write(item); + return result; +} + + +CodeSequenceMacro& MandatoryViewAndSliceProgressionDirectionMacro::getViewCode() +{ + return m_ViewCodeSequence; +} + + +OFVector< CodeSequenceMacro* >& MandatoryViewAndSliceProgressionDirectionMacro::getViewModifierCode() +{ + return m_ViewModifierCode; +} diff --git a/dcmiod/libsrc/iodrules.cc b/dcmiod/libsrc/iodrules.cc new file mode 100644 index 00000000..0d0bc074 --- /dev/null +++ b/dcmiod/libsrc/iodrules.cc @@ -0,0 +1,307 @@ +/* + * + * Copyright (C) 2015, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmiod + * + * Author: Michael Onken + * + * Purpose: Class for managing attribute rules as found in DICOM modules + * + */ + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmiod/iodrules.h" +#include "dcmtk/dcmiod/iodtypes.h" +#include "dcmtk/dcmdata/dcitem.h" +#include "dcmtk/dcmdata/dcelem.h" +#include "dcmtk/dcmdata/dctagkey.h" + + +IODRules::IODRules() : +m_Rules() +{ + // nothing to do +} + + +IODRules* IODRules::clone() +{ + IODRules *newRules = new IODRules(); + if (newRules) + { + OFMap::iterator it = m_Rules.begin(); + while (it != m_Rules.end()) + { + if (it->second) + { + IODRule* newRule = it->second->clone(); + if (newRule) + { + newRules->addRule(newRule); + } + else + { + DCMIOD_WARN("Cannot create new IODRule, memory exhausted?"); + } + } + else + { + DCMIOD_WARN("Found NULL IODRule, cannot clone"); + } + it++; + } + } + else + { + DCMIOD_WARN("Cannot create new IODRules, memory exhausted?"); + } + return newRules; +} + + +IODRule* IODRules::getByTag(const DcmTagKey& key) const +{ + IODRules::const_iterator it = m_Rules.find(key); + if ( it != m_Rules.end() ) + return (*it).second; + else + return NULL; +} + + +IODRules::iterator IODRules::begin() +{ + return m_Rules.begin(); +} + +IODRules::iterator IODRules::end() +{ + return m_Rules.end(); +} + + +void IODRules::clear() +{ + + while (m_Rules.size() > 0) + { + IODRules::iterator it = m_Rules.begin(); + IODRule* rule = (*it).second; + m_Rules.erase(it); + delete rule; + rule = NULL; + } +} + +OFBool IODRules::addRule(IODRule* rule, + const OFBool overwriteExisting) +{ + if (rule == NULL) + { + DCMIOD_ERROR("Cannot add IOD rule: NULL pointer"); + return OFFalse; + } + DcmTagKey key = rule->getTagKey(); + iterator it = m_Rules.find(key); + if ( it != m_Rules.end() ) + { + if (overwriteExisting) + { + delete (*it).second; + (*it).second = rule; + } + else + { + DCMIOD_DEBUG("IOD rule for tag " << key << " not inserted (already existing and overwriting disabled)"); + return OFFalse; + } + } + else + { + m_Rules.insert( OFMake_pair ( key, rule) ); + } + return OFTrue; +} + + +const OFVector< IODRule* > IODRules::getByModule(const OFString& moduleName) +{ + OFVector result; + IODRules::iterator it = m_Rules.begin(); + while (it != m_Rules.end()) + { + if ( (*it).second->getModule() == moduleName ) + { + result.push_back((*it).second); + } + it++; + } + return result; +} + + +OFBool IODRules::deleteRule(const DcmTagKey key) +{ + IODRules::iterator it = m_Rules.find(key); + if ( it != m_Rules.end() ) + { + IODRule* rule = (*it).second; + m_Rules.erase(it); + delete rule; + return OFTrue; + } + return OFFalse; +} + + +void IODRules::dump(STD_NAMESPACE ostream &out) +{ + IODRules::iterator it = m_Rules.begin(); + while ( it != m_Rules.end() ) + { + out << (*it).first << ": Type \"" << (*it).second->getType() << "\", VM \"" << (*it).second->getType() << "\"" << OFendl; + it++; + } +} + + +IODRules::~IODRules() +{ + clear(); +} + + + +IODRule::IODRule(const DcmTagKey& key, + const OFString& VM, + const OFString& type, + const OFString& module, + const DcmIODTypes::IOD_IE ie, + const OFString& defaultValue, + const OFString& privateCreator) +: m_Key(key), +m_VM(VM), +m_Type(type), +m_Module(module), +m_IE(ie), +m_DefaultValue(defaultValue), +m_PrivateCreator(privateCreator) +{ + // nothing else to do +} + + +IODRule::~IODRule() +{ + // nothing to do +} + + +IODRule* IODRule::clone() +{ + return new IODRule(m_Key, m_VM, m_Type, m_Module, m_IE, m_DefaultValue, m_PrivateCreator); +} + + + +OFString IODRule::getPrivateCreator() const +{ + return m_PrivateCreator; +} + + +DcmTagKey IODRule::getTagKey() const +{ + return m_Key; +} + + + +OFString IODRule::getModule() const +{ + return m_Module; +} + + +OFString IODRule::getType() const +{ + return m_Type; +} + + +OFString IODRule::getVM() const +{ + return m_VM; +} + + +OFString IODRule::getDefaultValue() const +{ + return m_DefaultValue; +} + + +DcmIODTypes::IOD_IE IODRule::getIE() const +{ + return m_IE; +} + + + +OFCondition IODRule::check(DcmItem& item, + const OFBool quiet) +{ + OFCondition result; + const OFString tagName = DcmTag(m_Key).getTagName(); + DcmElement *elem = NULL; + OFCondition searchCond = item.findAndGetElement(m_Key, elem, OFFalse /* only this level */); + /* NB: type 1C and 2C cannot be checked, assuming to be optional */ + if (((m_Type == "1") || (m_Type== "2")) && searchCond.bad()) + { + if (!quiet) DCMIOD_WARN(tagName << " " << m_Key << " absent in " << m_Module << " (type " << m_Type << ")"); + result = EC_MissingAttribute; + } + else if ((elem == NULL) || elem->isEmpty(OFTrue /*normalize*/)) + { + /* however, type 1C should never be present with empty value */ + if (((m_Type == "1") || (m_Type == "1C")) && searchCond.good()) + { + if (!quiet) DCMIOD_WARN(tagName << " " << m_Key << " empty in " << m_Module << " (type " << m_Type << ")"); + result = EC_MissingValue; + } + } else { + const OFCondition checkResult = elem->checkValue(m_VM, OFTrue /*oldFormat*/); + if (checkResult == EC_ValueRepresentationViolated) + { + if (!quiet) DCMIOD_WARN(tagName << " " << m_Key << " violates VR definition in " << m_Module); + result = checkResult; + } + else if (checkResult == EC_ValueMultiplicityViolated) + { + const OFString vmText = (elem->getVR() == EVR_SQ) ? " #items" : " VM"; + if (!quiet) DCMIOD_WARN(tagName << " " << m_Key << vmText << " != " << m_VM << " in " << m_Module); + result = checkResult; + } + else if (checkResult == EC_MaximumLengthViolated) + { + if (!quiet) DCMIOD_WARN(tagName << " " << m_Key << " violates maximum VR length in " << m_Module); + result = checkResult; + } + else if (checkResult.bad()) + { + if (!quiet) DCMIOD_DEBUG("INTERNAL ERROR while checking value of " << tagName << " " << m_Key << " in " << m_Module); + result = EC_InternalError; + } + } + return result; +} diff --git a/dcmiod/libsrc/iodtypes.cc b/dcmiod/libsrc/iodtypes.cc new file mode 100644 index 00000000..0fe15cab --- /dev/null +++ b/dcmiod/libsrc/iodtypes.cc @@ -0,0 +1,44 @@ +/* + * + * Copyright (C) 2015, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmiod + * + * Author: Michael Onken + * + * Purpose: Class for managing attribute rules as found in DICOM modules + * + */ + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmiod/iodtypes.h" +#include "dcmtk/dcmdata/dcerror.h" + +OFLogger DCM_dcmiodLogger = OFLog::getLogger("dcmtk.dcmiod"); + + +/*---------------------------------* + * constant definitions + *---------------------------------*/ + +// conditions +makeOFConditionConst(IOD_EC_WrongSOPClass, OFM_dcmiod, 1, OF_error, "Wrong SOP Class"); +makeOFConditionConst(IOD_EC_MissingAttribute, OFM_dcmiod, 2, OF_error, "Missing Attribute(s)"); +makeOFConditionConst(IOD_EC_MissingSequenceData, OFM_dcmiod, 3, OF_error, "Missing Sequence Data"); +makeOFConditionConst(IOD_EC_InvalidDimensions, OFM_dcmiod, 4, OF_error, "Invalid dimension information"); +makeOFConditionConst(IOD_EC_CannotInsertFrame, OFM_dcmiod, 5, OF_error, "Cannot insert frame"); +makeOFConditionConst(IOD_EC_InvalidPixelData, OFM_dcmiod, 6, OF_error, "Invalid Pixel Data"); +makeOFConditionConst(IOD_EC_InvalidObject, OFM_dcmiod, 7, OF_error, "Invalid Object"); +makeOFConditionConst(IOD_EC_CannotDecompress, OFM_dcmiod, 8, OF_error, "Cannot decompress"); +makeOFConditionConst(IOD_EC_NoSuchRule, OFM_dcmiod, 9, OF_error, "No such IOD rule"); +makeOFConditionConst(IOD_EC_InvalidLaterality, OFM_dcmiod, 10, OF_error, "Invalid value for 'Laterality' (only 'L' or 'R' permitted)"); +makeOFConditionConst(IOD_EC_InvalidElementValue, OFM_dcmiod, 11, OF_error, "Value not allowed for element"); diff --git a/dcmiod/libsrc/iodutil.cc b/dcmiod/libsrc/iodutil.cc new file mode 100644 index 00000000..b4224958 --- /dev/null +++ b/dcmiod/libsrc/iodutil.cc @@ -0,0 +1,569 @@ +/* + * + * Copyright (C) 2015, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmiod + * + * Author: Michael Onken + * + * Purpose: Static helper functionality for dcmiod module + * + */ + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ +#include "dcmtk/dcmdata/dctypes.h" // logger +#include "dcmtk/dcmiod/iodutil.h" +#include "dcmtk/dcmiod/iodrules.h" + +#include "dcmtk/dcmdata/dcmetinf.h" +#include "dcmtk/dcmdata/dcdeftag.h" +#include "dcmtk/dcmdata/dcdict.h" +#include "dcmtk/dcmdata/dcdicent.h" +#include "dcmtk/dcmdata/dcsequen.h" +#include "dcmtk/dcmdata/dcfilefo.h" +#include "dcmtk/dcmdata/dcvrda.h" +#include "dcmtk/dcmdata/dcvrtm.h" +#include "dcmtk/dcmdata/dcuid.h" +#include "dcmtk/dcmdata/dcitem.h" + + + +// --- static helpers --- + +OFCondition DcmIODUtil::getAndCheckElementFromDataset(DcmItem &dataset, + DcmElement &delem, + const OFString &vm, + const OFString &type, + const char *moduleName) +{ + DcmStack stack; + const DcmTagKey tagKey = delem.getTag(); + OFCondition result = dataset.search(tagKey, stack, ESM_fromHere, OFFalse /*searchIntoSub*/); + if (result.good()) + { + /* copy object from search stack */ + result = delem.copyFrom(*stack.top()); + /* we need a reference to the original element in order to determine the SpecificCharacterSet */ + checkElementValue(OFstatic_cast(DcmElement *, stack.top()), tagKey, vm, type, result, moduleName); + } + /* the element could not be found in the dataset */ + else + { + checkElementValue(delem, vm, type, result, moduleName); + } + return result; +} + + +OFCondition DcmIODUtil::getAndCheckElementFromDataset(DcmItem &dataset, + const DcmTagKey& tagKey, + DcmElement*& delem, + const OFString &vm, + const OFString &type, + const char *moduleName) +{ + if (delem) + return EC_IllegalParameter; + + DcmStack stack; + OFCondition result = dataset.search(tagKey, stack, ESM_fromHere, OFFalse /*searchIntoSub*/); + if (result.good()) + { + /* copy object from search stack */ + delem = OFstatic_cast ( DcmElement*, stack.top()->clone() ); + /* we need a reference to the original element in order to determine the SpecificCharacterSet */ + checkElementValue(OFstatic_cast(DcmElement *, stack.top()), tagKey, vm, type, result, moduleName); + } + /* the element could not be found in the dataset */ + else + checkElementValue(delem, tagKey, vm, type, result, moduleName); + + return result; +} + + + +OFCondition DcmIODUtil::getAndCheckElementFromDataset(DcmItem &dataset, + DcmElement &delem, + const IODRule* rule) +{ + if (rule == NULL) + return EC_CannotCheck; + + return getAndCheckElementFromDataset(dataset, delem, rule->getVM(), rule->getType(), rule->getModule().c_str()); +} + + +OFCondition DcmIODUtil::getAndCheckElementFromDataset(DcmItem &dataset, + DcmElement*& delem, + const IODRule* rule) +{ + if (rule == NULL) + return EC_CannotCheck; + + return getAndCheckElementFromDataset(dataset, rule->getTagKey(), delem, rule->getVM(), rule->getType(), rule->getModule().c_str()); +} + + + +OFCondition DcmIODUtil::copyElementToDataset(OFCondition &result, + DcmItem &dataset, + const DcmElement &delem, + const IODRule* rule) +{ + if (rule == NULL) + return EC_CannotCheck; + + if (result.bad()) + return result; + + // addElementToDataset() consumes element, so create a copy + DcmElement * copy = OFstatic_cast(DcmElement*, delem.clone()); + if (!copy) + return EC_MemoryExhausted; + + return addElementToDataset(result, dataset, copy, rule); +} + + +OFCondition DcmIODUtil::copyElementToDataset(OFCondition &result, + DcmItem &dataset, + const DcmElement &delem, + const OFString &vm, + const OFString &type, + const char *moduleName) +{ + // Create temporary rule (in order to avoid code-copying) + IODRule rule(delem.getTag(), vm, type, moduleName, DcmIODTypes::IE_UNDEFINED); + return copyElementToDataset(result, dataset, delem, &rule); +} + + +OFCondition DcmIODUtil::addElementToDataset(OFCondition &result, + DcmItem &dataset, + DcmElement *delem, + const IODRule* rule) +{ + OFBool insertionOK = OFFalse; + if (result.good()) + { + if (rule != NULL) + { + // Create empty type 2 element if required + OFString type = rule->getType(); + if (delem == NULL) + { + if (type == "2") + { + delem = newDicomElement(rule->getTagKey()); + if (delem == NULL) + return EC_MemoryExhausted; + } else if (type != "1") + { + // Not type 1 or type 2 means the is type 1C,2C or 3. For those it is + // fine to not insert anything + return EC_Normal; + } + else + { + // type 1 is missing + DCMIOD_WARN(DcmTag(rule->getTagKey()).getTagName() << " " << rule->getTagKey() << " absent in " << rule->getModule() << " (type " << rule->getType() << ")"); + return IOD_EC_MissingAttribute; + } + } + + // We have an element at this position, check its value + if ((type == "2") || !delem->isEmpty()) + { + /* insert non-empty element or empty "type 2" element */ + result = dataset.insert(delem, OFTrue /*replaceOld*/); + checkElementValue(*delem, rule->getVM(), type, result, rule->getModule().c_str()); + if (result.good()) + insertionOK = OFTrue; + } + else if (type == "1") + { + /* empty element value not allowed for "type 1" */ + result = EC_InvalidValue; + checkElementValue(*delem, rule->getVM(), type, result, rule->getModule().c_str()); + } + } + else + { + // No rule, no checks + result = EC_CannotCheck; + } + } + if (!insertionOK) + { + // Delete element since dataset did not take over ownership + delete delem; + } + + return result; +} + + +const OFString& DcmIODUtil::currentDate(OFString &dateString) +{ + if (DcmDate::getCurrentDate(dateString).bad()) + { + dateString = ""; + } + return dateString; +} + + +const OFString& DcmIODUtil::currentTime(OFString &timeString) +{ + if (DcmTime::getCurrentTime(timeString, OFTrue /*seconds*/, OFFalse /*fraction*/).bad()) + { + timeString = ""; + } + return timeString; +} + + +OFCondition DcmIODUtil::checkElementValue(const DcmElement *delem, + const DcmTagKey &tagKey, + const OFString &vm, + const OFString &type, + const OFCondition &searchCond, + const char *moduleName) +{ + OFCondition result = EC_Normal; + const OFString tagName = DcmTag(tagKey).getTagName(); + const OFString module = (moduleName == NULL) ? "IOD" : moduleName; + /* NB: type 1C and 2C cannot be checked, assuming to be optional */ + if (((type == "1") || (type == "2")) && searchCond.bad()) + { + DCMIOD_WARN(tagName << " " << tagKey << " absent in " << module << " (type " << type << ")"); + result = IOD_EC_MissingAttribute; + } + else if ((delem == NULL) || OFconst_cast(DcmElement*, delem)->isEmpty(OFTrue /*normalize*/)) // cast away constness of delem; value modification can happpen (eg. to remove padding) + { + /* however, type 1C should never be present with empty value */ + if (((type == "1") || (type == "1C")) && searchCond.good()) + { + DCMIOD_WARN(tagName << " " << tagKey << " empty in " << module << " (type " << type << ")"); + result = EC_MissingValue; + } + } else { + result = OFconst_cast(DcmElement*, delem)->checkValue(vm, OFTrue /*oldFormat*/); // cast away constness of delem; value modification can happpen (eg. to remove padding) + if (result == EC_ValueRepresentationViolated) + { + DCMIOD_WARN(tagName << " " << tagKey << " violates VR definition in " << module); + } + else if (result == EC_ValueMultiplicityViolated) + { + const OFString vmText = (delem->getVR() == EVR_SQ) ? " #items" : " VM"; + DCMIOD_WARN(tagName << " " << tagKey << vmText << " != " << vm << " in " << module); + } + else if (result == EC_MaximumLengthViolated) + { + DCMIOD_WARN(tagName << " " << tagKey << " violates maximum VR length in " << module); + } + else if (result.bad()) + { + DCMIOD_WARN("INTERNAL ERROR while checking value of " << tagName << " " << tagKey << " in " << module); + result = EC_Normal; + } + } + return result; +} + + +OFCondition DcmIODUtil::checkElementValue(const DcmElement &delem, + const OFString &vm, + const OFString &type, + const OFCondition &searchCond, + const char *moduleName) +{ + /* call the real function */ + return checkElementValue(&delem, delem.getTag(), vm, type, searchCond, moduleName); +} + + +OFCondition DcmIODUtil::getStringValueFromElement(const DcmElement &delem, + OFString &stringValue, + const signed long pos) +{ + OFCondition result = EC_Normal; + // cast away constness of delem; value modification can happpen (eg. to remove padding) + if (pos < 0) + result = OFconst_cast(DcmElement &, delem).getOFStringArray(stringValue); + else + result = OFconst_cast(DcmElement &, delem).getOFString(stringValue, OFstatic_cast(unsigned long, pos)); + if (result.bad()) + stringValue.clear(); + return result; +} + + +OFCondition DcmIODUtil::getFloat64ValueFromElement(const DcmElement& delem, + Float64& result, + const unsigned long pos) +{ + return OFconst_cast(DcmElement &, delem).getFloat64(result, OFstatic_cast(unsigned long, pos)); +} + + +OFCondition DcmIODUtil::getFloat64ValuesFromElement(const DcmElement& delem, + OFVector& result) +{ + Float64* floats = NULL; + OFCondition cond = OFconst_cast(DcmElement &, delem).getFloat64Array(floats); + if (cond.good()) + { + size_t vm = OFconst_cast(DcmElement &, delem).getVM(); + for (size_t n = 0; n < vm; n++) + { + result.push_back(floats[n]); + } + } + return cond; +} + + +OFCondition DcmIODUtil::getStringValueFromItem(const DcmTagKey& key, + DcmItem& item, + OFString& result, + const signed long& pos) +{ + DcmElement *elem = NULL; + item.findAndGetElement(key, elem); + if (elem != NULL) + return DcmIODUtil::getStringValueFromElement(*elem, result, pos); + else + return EC_TagNotFound; +} + + +OFCondition DcmIODUtil::getFloat64ValueFromItem(const DcmTagKey& key, + DcmItem& item, + Float64& result, + const unsigned long& pos) +{ + DcmElement *elem = NULL; + OFCondition cond = item.findAndGetElement(key, elem); + if (elem != NULL) + { + cond = DcmIODUtil::getFloat64ValueFromElement(*elem, result, pos); + } + return cond; +} + + +OFCondition DcmIODUtil::getFloat64ValuesFromItem(const DcmTagKey& key, + DcmItem& item, + OFVector& result) +{ + DcmElement *elem = NULL; + OFCondition cond = item.findAndGetElement(key, elem); + if (elem != NULL) + { + cond = DcmIODUtil::getFloat64ValuesFromElement(*elem, result); + } + return cond; +} + + +OFCondition DcmIODUtil::setUint16ValuesOnElement(DcmElement &delem, + const OFVector& values, + const OFString& vm, + const OFBool check) +{ + OFCondition result; + OFVector::const_iterator it = values.begin(); + for (size_t count=0; count < values.size(); count++ ) + { + result = delem.putUint16( (*it) ); + if ( result.bad() ) + { + DCMIOD_WARN(delem.getTag().getXTag() << ": Setting value " << " #" << count << " to \" " << *it << "\" not possible"); + } + else if (check) + { + result = DcmElement::checkVM(values.size(), vm); + } + it++; + } + return result; +} + + +OFCondition DcmIODUtil::getUint16ValuesFromElement(DcmElement &delem, + OFVector& values) +{ + OFCondition result; + const size_t count = delem.getVM(); + values.reserve(count); + for (size_t i = 0; i < count; i++) + { + Uint16 val; + result = delem.getUint16(val, i); + if (result.bad()) + { + DCMIOD_WARN(delem.getTag().getXTag() << ": Getting value " << " #" << i << " not possible"); + break; + } + values.push_back(val); + } + return result; +} + + +void DcmIODUtil::checkSubSequence(OFCondition& result, + DcmItem& surroundingItem, + const DcmTagKey& seqKey, + const OFString& cardinality, + const OFString& type, + const OFString& module) +{ + OFCondition exists = EC_Normal; + /* check result */ + if ( result.good() ) + { + DcmSequenceOfItems *seq = NULL; + exists = surroundingItem.findAndGetSequence(seqKey, seq); + result = DcmIODUtil::checkElementValue(seq, seqKey, cardinality, type, exists, module.c_str()); + } +} + + +OFCondition DcmIODUtil::getAndCheckSingleItem(DcmSequenceOfItems& seq, + DcmItem*& item, + const DcmTagKey& checkKey) +{ + item = NULL; + const OFString tagName = OFconst_cast(DcmTag*, &seq.getTag())->getTagName(); // getTagName is not const... + if (checkKey != DCM_UndefinedTagKey) + { + if (seq.getTag().getXTag() != checkKey) + { + DCMIOD_ERROR("Expected sequence " << checkKey << " but got " << &seq.getTag() << "(" << tagName << ")"); + return EC_ItemNotFound; + } + } + + // get actual tag name and cardinality + const Uint32 card = seq.card(); + if (card != 1) + { + if (card > 1) + { + DCMIOD_WARN("Only single item allowed in " << tagName << ", ignoring " << card -1 << " other items"); + } + else // card = 0 + { + DCMIOD_WARN("Cannot read from sequence " << tagName << ": No item found"); + return EC_ItemNotFound; + } + } + // get item and return it + item = seq.getItem(0); + if (item == NULL) + { + DCMIOD_ERROR("Cannot read item from " << tagName << ": No item found (internal errror)"); + return EC_CorruptedData; + } + return EC_Normal; +} + + +OFCondition DcmIODUtil::checkSOPClass(DcmItem* item, + const OFString& desiredSOPClass, + OFString& valueFound) +{ + valueFound.clear(); + if ( (item == NULL) && (item->card() == 0) ) + { + DCMIOD_TRACE("Cannot check SOP Class UID: Dataset not present or empty"); + return EC_IllegalParameter; + } + OFCondition result = item->findAndGetOFString(DCM_SOPClassUID, valueFound); + if ( result.bad() ) + { + DCMIOD_TRACE("No SOP Class UID in file, giving up"); + return EC_TagNotFound; + } + if (valueFound != desiredSOPClass) + { + DCMIOD_TRACE("File is not of SOP Class " << desiredSOPClass << ", but instead SOP Class is " << dcmFindNameOfUID(valueFound.c_str(), valueFound.c_str()) ); + return EC_InvalidValue; + } + return EC_Normal; + +} + + +OFBool DcmIODUtil::isSequenceTag(const DcmTagKey& key, + const OFString& privateCreator) +{ + const DcmDataDictionary& globalDataDict = dcmDataDict.rdlock(); + const DcmDictEntry *dictRef = NULL; + if (privateCreator.empty()) + dictRef = globalDataDict.findEntry(key, NULL); + else + dictRef = globalDataDict.findEntry(key, privateCreator.c_str()); + DcmVR vr; + if (dictRef) + { + vr = dictRef->getVR(); + } + dcmDataDict.unlock(); + if (vr.getEVR() == EVR_SQ) + return OFTrue; + return OFFalse; +} + + +const DcmTagKey DcmIODUtil::parseTagKey(const OFString& keyString) +{ + unsigned int g, e; + DcmTagKey resultKey = DCM_UndefinedTagKey; + if (sscanf(keyString.c_str(), "(%x,%x)", &g, &e) == 2) + { + resultKey.set(OFstatic_cast(Uint16, g), OFstatic_cast(Uint16, e)); + } + return resultKey; +} + + +OFCondition DcmIODUtil::decompress(DcmDataset& dset) +{ + DcmXfer xfer = dset.getOriginalXfer(); + if (xfer.isEncapsulated()) + { + if (EC_Normal != dset.chooseRepresentation(EXS_LittleEndianExplicit, NULL)) + { + DCMIOD_ERROR("No conversion uncompressed transfer syntax possible!"); + return IOD_EC_CannotDecompress; + } + } + + return EC_Normal; +} + + +OFString DcmIODUtil::createUID(const Uint8 level) +{ + char uid[100]; + switch (level) + { + case 0: dcmGenerateUniqueIdentifier(uid, SITE_INSTANCE_UID_ROOT); break; + case 1: dcmGenerateUniqueIdentifier(uid, SITE_SERIES_UID_ROOT); break; + case 2: dcmGenerateUniqueIdentifier(uid, SITE_STUDY_UID_ROOT); break; + default: dcmGenerateUniqueIdentifier(uid, SITE_STUDY_UID_ROOT); + } + return uid; +} \ No newline at end of file diff --git a/dcmiod/libsrc/modacquisitioncontext.cc b/dcmiod/libsrc/modacquisitioncontext.cc new file mode 100644 index 00000000..b5601cc3 --- /dev/null +++ b/dcmiod/libsrc/modacquisitioncontext.cc @@ -0,0 +1,67 @@ +/* + * + * Copyright (C) 2015, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmiod + * + * Author: Michael Onken + * + * Purpose: Class for managing the Acquisition Context Module + * + */ + + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ +#include "dcmtk/dcmiod/modacquisitioncontext.h" +#include "dcmtk/dcmiod/iodutil.h" + +const OFString IODAcquisitionContextModule::m_ModuleName = "AcquisitionContextModule"; + + +IODAcquisitionContextModule::IODAcquisitionContextModule(OFshared_ptr item, + OFshared_ptr rules) +: IODModule(item, rules) +{ + // reset element rules + resetRules(); +} + + +IODAcquisitionContextModule::IODAcquisitionContextModule() +: IODModule() +{ + // reset element rules + resetRules(); +} + + +OFString IODAcquisitionContextModule::getName() const +{ + return m_ModuleName; +} + + +void IODAcquisitionContextModule::resetRules() +{ + // parameters are tag, VM, type. Overwrite old rules if any. + m_Rules->addRule(new IODRule(DCM_AcquisitionContextSequence, "1-n","2", m_ModuleName, DcmIODTypes::IE_INSTANCE), OFTrue); +} + + +IODAcquisitionContextModule::~IODAcquisitionContextModule() +{ +} + + +// --- get attributes (C++ string) --- + +// --- set attributes --- diff --git a/dcmiod/libsrc/modbase.cc b/dcmiod/libsrc/modbase.cc new file mode 100644 index 00000000..d0a208f6 --- /dev/null +++ b/dcmiod/libsrc/modbase.cc @@ -0,0 +1,260 @@ +/* + * + * Copyright (C) 2015, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmiod + * + * Author: Michael Onken + * + * Purpose: Abstract base class for IOD Modules or other attribute collections + * + */ + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ +#include "dcmtk/dcmiod/modbase.h" +#include "dcmtk/dcmdata/dcitem.h" +#include "dcmtk/dcmiod/iodutil.h" +#include "dcmtk/dcmiod/iodrules.h" + + +IODComponent::IODComponent(OFshared_ptr item, + OFshared_ptr rules, + IODComponent* parent) +: m_Item(item), + m_Rules(rules), + m_Parent(parent) +{ + if (!m_Item) + m_Item.reset(new DcmItem()); + + if (!m_Rules) + m_Rules.reset(new IODRules()); +} + + +IODComponent::IODComponent(IODComponent* parent) +: m_Item(), + m_Rules(), + m_Parent(parent) +{ + m_Item.reset(new DcmItem()); + m_Rules.reset(new IODRules()); +} + + +IODComponent::~IODComponent() +{ + // Nothing to do for shared pointers +} + + +IODComponent& IODComponent::operator=(const IODComponent& rhs) +{ + if (&rhs != this) + { + m_Rules.reset( rhs.m_Rules->clone() ); + m_Item.reset( OFstatic_cast(DcmItem*, rhs.m_Item->clone()) ); + m_Parent = NULL; + } + return *this; +} + + +IODComponent::IODComponent(const IODComponent& rhs) +{ + + if (this == &rhs) + return; + + *this = rhs; +} + + +void IODComponent::inventMissing() +{ + // Try to fill in missing type 1 information + OFVector writeRules = m_Rules->getByModule(getName()); + OFVector::iterator rule = writeRules.begin(); + while (rule != writeRules.end()) + { + OFString val = (*rule)->getDefaultValue() ; + // We have a default value + if ( val.length() != 0 ) + { + // Check if element is not set + DcmElement *elem = NULL; + if ( getData().findAndGetElement( (*rule)->getTagKey(), elem ).bad() ) + { + elem = newDicomElement((*rule)->getTagKey()); + if (elem == NULL) + { + DCMIOD_ERROR("Could not allocate element " << (*rule)->getTagKey()); + } + else + { + elem->putString(val.c_str()); + m_Item->insert(elem); + } + } + else if (elem->getLength() == 0) + { + elem->putString(val.c_str()); + } + } + rule++; + } +} + + +void IODComponent::clearData() +{ + OFVector modRules = m_Rules->getByModule(getName()); + OFVector::iterator rule = modRules.begin(); + while (rule != modRules.end()) + { + m_Item->findAndDeleteElement( (*rule)->getTagKey() ); + rule++; + } +} + + +OFCondition IODComponent::read(DcmItem& source, + OFBool clearOldData) +{ + // Debug + DCMIOD_DEBUG("Reading component: " << getName()); + + // Clear old data if desried + if (clearOldData) + { + clearData(); + } + + // Do actual reading + read(source, *m_Rules, *m_Item, getName()); + // We do not report errors here (only logger output) + return EC_Normal; +} + + +OFCondition IODComponent::write(DcmItem& destination) +{ + // Debug + DCMIOD_DEBUG("Writing component: " << getName()); + + // Invent missing values + inventMissing(); + + // Start writing + OFCondition result = EC_Normal; + result = write(*m_Item, *m_Rules, destination, getName()); + return result; +} + + +int IODComponent::compare(const IODComponent& rhs) const +{ + return this->m_Item.get()->compare( *(rhs.m_Item.get()) ) ; +} + + +OFCondition IODComponent::check(const OFBool quiet) +{ + OFCondition result; + IODRules::iterator it = m_Rules->begin(); + while (it != m_Rules->end()) + { + result = (*it).second->check(*m_Item, quiet); + if (result.bad()) + break; + else + it++; + } + return result; +} + + +// static helper +OFCondition IODComponent::read(DcmItem& source, + IODRules& rules, + DcmItem& destination, + const OFString& componentName) +{ + OFVector modRules = rules.getByModule(componentName); + OFVector::iterator rule = modRules.begin(); + while (rule != modRules.end()) + { + // We do not read/copy sequences but only check them since they are not + // handled within this component + OFBool isSequence = ( DcmTag( (*rule)->getTagKey()).getEVR() == EVR_SQ); + if (isSequence) + { + DcmElement *elem = NULL; + source.findAndGetElement( (*rule)->getTagKey(), elem); + DcmIODUtil::checkElementValue(elem, (*rule)->getTagKey(), (*rule)->getVM(), (*rule)->getType(), EC_Normal, (*rule)->getModule().c_str()); + } + else // Normal attributes are checked and copied over into this IOD component + { + DcmElement* elem = NULL; + DcmIODUtil::getAndCheckElementFromDataset(source, elem, *rule); + if (elem != NULL) + { + OFCondition result = destination.insert(elem, OFTrue); + if (result.bad()) + { + DCMIOD_ERROR("Cannot insert element with tag: " << (*rule)->getTagKey()); + delete elem; + } + } + } + rule++; + } + return EC_Normal; +} + + +// static helper +OFCondition IODComponent::write(DcmItem& source, + IODRules& rules, + DcmItem& destination, + const OFString& componentName) +{ + OFCondition result = EC_Normal; + + OFVector writeRules = rules.getByModule(componentName); + OFVector::iterator rule = writeRules.begin(); + while (rule != writeRules.end()) + { + DcmElement* elem = NULL; + source.findAndGetElement( (*rule)->getTagKey(), elem, OFFalse /* only this level */, OFTrue /* create copy*/); + DcmIODUtil::addElementToDataset(result, destination, elem, *rule); + rule++; + } + + return result; +} + + +// -------- IODModule -------------- + +IODModule::IODModule(): IODComponent() +{ + // nothing to do, IODComponent does the work +} + + +IODModule::IODModule(OFshared_ptr< DcmItem > item, + OFshared_ptr< IODRules > rules) +: IODComponent(item, rules, NULL /* No parent for modules */) +{ + // nothing to do, IODComponent does the work +} diff --git a/dcmiod/libsrc/modcommoninstanceref.cc b/dcmiod/libsrc/modcommoninstanceref.cc new file mode 100644 index 00000000..78e6a101 --- /dev/null +++ b/dcmiod/libsrc/modcommoninstanceref.cc @@ -0,0 +1,203 @@ +/* + * + * Copyright (C) 2015, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmiod + * + * Author: Michael Onken + * + * Purpose: Class for managing the Common Instance Reference Module + * + */ + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmiod/modcommoninstanceref.h" +#include "dcmtk/dcmiod/iodutil.h" // for static helpers + +const OFString IODCommonInstanceReferenceModule::m_ComponentName = "CommonInstanceReferenceModule"; +const OFString IODCommonInstanceReferenceModule::StudiesOtherInstancesItem::m_ComponentName = "StudiesContainingOtherReferencedInstancesSequence"; + + +IODCommonInstanceReferenceModule::IODCommonInstanceReferenceModule(OFshared_ptr< DcmItem > item, + OFshared_ptr< IODRules > rules) +: IODModule(item, rules), + m_StudiesContainingOtherReferencedInstancesSequence() +{ + resetRules(); +} + + +IODCommonInstanceReferenceModule::IODCommonInstanceReferenceModule() +: IODModule() +{ + resetRules(); +} + + +IODCommonInstanceReferenceModule::~IODCommonInstanceReferenceModule() +{ + clearData(); +} + + +OFString IODCommonInstanceReferenceModule::getName() const +{ + return m_ComponentName; +} + + +OFVector< IODSeriesAndInstanceReferenceMacro::ReferencedSeriesItem* >& IODCommonInstanceReferenceModule::getReferencedSeriesItems() +{ + return m_ReferenceSeriesItems; +} + + +void IODCommonInstanceReferenceModule::clearData() +{ + DcmIODUtil::freeContainer(m_StudiesContainingOtherReferencedInstancesSequence); + DcmIODUtil::freeContainer(m_ReferenceSeriesItems); +} + + +OFCondition IODCommonInstanceReferenceModule::read(DcmItem& source, + const OFBool clearOldData) +{ + if (clearOldData) + clearData(); + + DcmIODUtil::readSubSequence >(source, DCM_ReferencedSeriesSequence, m_ReferenceSeriesItems, m_Rules->getByTag(DCM_ReferencedSeriesSequence)); + DcmIODUtil::readSubSequence >(source, + DCM_StudiesContainingOtherReferencedInstancesSequence, + m_StudiesContainingOtherReferencedInstancesSequence, + m_Rules->getByTag(DCM_StudiesContainingOtherReferencedInstancesSequence)); + + return EC_Normal; +} + + +OFCondition IODCommonInstanceReferenceModule::write(DcmItem& destination) +{ + OFCondition result = EC_Normal; + + DcmIODUtil::writeSubSequence >(result, DCM_ReferencedSeriesSequence, m_ReferenceSeriesItems, destination, m_Rules->getByTag(DCM_ReferencedSeriesSequence)); + DcmIODUtil::writeSubSequence >(result, + DCM_StudiesContainingOtherReferencedInstancesSequence, + m_StudiesContainingOtherReferencedInstancesSequence, + *m_Item, + m_Rules->getByTag(DCM_StudiesContainingOtherReferencedInstancesSequence)); + return result; +} + + +void IODCommonInstanceReferenceModule::resetRules() +{ + // Parameters for Rule are tag, VM, type (1,1C,2,2C,3), module name and logical IOD level + m_Rules->addRule(new IODRule(DCM_ReferencedSeriesSequence, "1-n", "1C", m_ComponentName, DcmIODTypes::IE_INSTANCE), OFTrue); + m_Rules->addRule(new IODRule(DCM_StudiesContainingOtherReferencedInstancesSequence, "1-n", "1C", m_ComponentName, DcmIODTypes::IE_INSTANCE), OFTrue); +} + + +// -- IODCommonInstanceReferenceModule::StudiesOtherInstancesItem -- + + +IODCommonInstanceReferenceModule::StudiesOtherInstancesItem::StudiesOtherInstancesItem(OFshared_ptr< DcmItem > item, + OFshared_ptr< IODRules > rules, + IODComponent* parent) +: IODComponent(item, rules, parent), + m_ReferencedSeriesAndInstance() +{ + // reset element rules + resetRules(); +} + + +IODCommonInstanceReferenceModule::StudiesOtherInstancesItem::StudiesOtherInstancesItem(IODComponent* parent) +: IODComponent(parent), + m_ReferencedSeriesAndInstance() +{ + // reset element rules + resetRules(); +} + + +IODCommonInstanceReferenceModule::StudiesOtherInstancesItem::~StudiesOtherInstancesItem() +{ + clearData(); +} + + + +OFString IODCommonInstanceReferenceModule::StudiesOtherInstancesItem::getName() const +{ + return m_ComponentName; +} + + +void IODCommonInstanceReferenceModule::StudiesOtherInstancesItem::clearData() +{ + m_ReferencedSeriesAndInstance.clearData(); + IODComponent::clearData(); +} + + +OFCondition IODCommonInstanceReferenceModule::StudiesOtherInstancesItem::read(DcmItem& source, + const OFBool clearOldData) +{ + if (clearOldData) + clearData(); + + IODComponent::read(source, clearOldData); + m_ReferencedSeriesAndInstance.read(source, clearOldData); + return EC_Normal; +} + + +OFCondition IODCommonInstanceReferenceModule::StudiesOtherInstancesItem::write(DcmItem& destination) +{ + OFCondition result = EC_Normal; + + result = IODComponent::write(destination); + + if (result.good()) result = m_ReferencedSeriesAndInstance.write(destination); + + return result; +} + + +void IODCommonInstanceReferenceModule::StudiesOtherInstancesItem::resetRules() +{ + // Parameters for Rule are tag, VM, type (1,1C,2,2C,3), module name and logical IOD level + m_Rules->addRule(new IODRule(DCM_StudyInstanceUID, "1", "1", m_ComponentName, DcmIODTypes::IE_INSTANCE), OFTrue); +} + + +IODSeriesAndInstanceReferenceMacro& IODCommonInstanceReferenceModule::StudiesOtherInstancesItem::getReferencedSeriesAndInstanceReferences() +{ + return m_ReferencedSeriesAndInstance; +} + + +OFCondition IODCommonInstanceReferenceModule::StudiesOtherInstancesItem::getStudyInstanceUID(OFString& value, + const long signed int pos) const +{ + return DcmIODUtil::getStringValueFromItem(DCM_StudyInstanceUID, *m_Item, value, pos); +} + + +OFCondition IODCommonInstanceReferenceModule::StudiesOtherInstancesItem::setStudyInstanceUID(const OFString& value, + const bool checkValue) +{ + OFCondition result = (checkValue) ? DcmUniqueIdentifier::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_StudyInstanceUID, value); + return result; +} diff --git a/dcmiod/libsrc/modenhequipment.cc b/dcmiod/libsrc/modenhequipment.cc new file mode 100644 index 00000000..4f1ee33a --- /dev/null +++ b/dcmiod/libsrc/modenhequipment.cc @@ -0,0 +1,134 @@ +/* + * + * Copyright (C) 2015, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmiod + * + * Author: Michael Onken + * + * Purpose: Class for managing the Enhanced General Equipment Module + * + */ + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ +#include "dcmtk/dcmiod/modenhequipment.h" +#include "dcmtk/dcmdata/dcdeftag.h" +#include "dcmtk/dcmdata/dcvrlo.h" +#include "dcmtk/dcmdata/dcvrst.h" +#include "dcmtk/dcmdata/dcvrsh.h" +#include "dcmtk/dcmiod/iodutil.h" + +IODEnhGeneralEquipmentModule::IODEnhGeneralEquipmentModule(OFshared_ptr item, + OFshared_ptr rules) +: IODModule(item, rules), + m_ModuleName("EnhancedGeneralEquipmentModule") +{ + // reset element rules + resetRules(); +} + + +IODEnhGeneralEquipmentModule::IODEnhGeneralEquipmentModule() +: IODModule() +{ + resetRules(); +} + + +void IODEnhGeneralEquipmentModule::resetRules() +{ + m_Rules->addRule(new IODRule(DCM_Manufacturer, "1","1", m_ModuleName, DcmIODTypes::IE_EQUIPMENT), OFTrue); + m_Rules->addRule(new IODRule(DCM_ManufacturerModelName, "1","1", m_ModuleName, DcmIODTypes::IE_EQUIPMENT), OFTrue); + m_Rules->addRule(new IODRule(DCM_DeviceSerialNumber, "1","1", m_ModuleName, DcmIODTypes::IE_EQUIPMENT), OFTrue); + m_Rules->addRule(new IODRule(DCM_SoftwareVersions, "1-n","1", m_ModuleName, DcmIODTypes::IE_EQUIPMENT), OFTrue); +} + + +IODEnhGeneralEquipmentModule::~IODEnhGeneralEquipmentModule() +{ + clearData(); +} + + +OFString IODEnhGeneralEquipmentModule::getName() const +{ + return m_ModuleName; +} + + +OFCondition IODEnhGeneralEquipmentModule::getDeviceSerialNumber(OFString& value, + const long signed int pos) const +{ + return DcmIODUtil::getStringValueFromItem(DCM_DeviceSerialNumber, *m_Item, value, pos); +} + + +OFCondition IODEnhGeneralEquipmentModule::getManufacturer(OFString& value, + const long signed int pos) const +{ + return DcmIODUtil::getStringValueFromItem(DCM_Manufacturer, *m_Item, value, pos); +} + + +OFCondition IODEnhGeneralEquipmentModule::getManufacturerModelName(OFString& value, + const long signed int pos) const +{ + return DcmIODUtil::getStringValueFromItem(DCM_ManufacturerModelName, *m_Item, value, pos); +} + + +OFCondition IODEnhGeneralEquipmentModule::getSoftwareVersions(OFString& value, + const long signed int pos) const +{ + return DcmIODUtil::getStringValueFromItem(DCM_SoftwareVersions, *m_Item, value, pos); +} + + +OFCondition IODEnhGeneralEquipmentModule::setDeviceSerialNumber(const OFString& value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmLongString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_DeviceSerialNumber, value); + return result; +} + + +OFCondition IODEnhGeneralEquipmentModule::setManufacturer(const OFString& value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmLongString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_Manufacturer, value); + return result; +} + + +OFCondition IODEnhGeneralEquipmentModule::setManufacturerModelName(const OFString& value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmLongString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_ManufacturerModelName, value); + return result; + +} + + +OFCondition IODEnhGeneralEquipmentModule::setSoftwareVersions(const OFString& value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmLongString::checkStringValue(value, "1-n") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_SoftwareVersions, value); + return result; +} diff --git a/dcmiod/libsrc/modenhusimage.cc b/dcmiod/libsrc/modenhusimage.cc new file mode 100644 index 00000000..980ac0ee --- /dev/null +++ b/dcmiod/libsrc/modenhusimage.cc @@ -0,0 +1,654 @@ +/* + * + * Copyright (C) 2015, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmiod + * + * Author: Michael Onken + * + * Purpose: Class for managing the Enhanced US Image Module + * + */ + + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ +#include "dcmtk/dcmiod/modenhusimage.h" +#include "dcmtk/dcmiod/iodutil.h" + +const OFString IODEnhUSImageModule::m_ModuleName = "EnhancedUSImageModule"; + + +IODEnhUSImageModule::IODEnhUSImageModule(OFshared_ptr item, + OFshared_ptr rules) +: IODModule(item, rules), + m_MandatoryViewAndSliceProgressionDirection(), + m_Anatomy("1" /* mandatory version */), + m_TransducerScanPattern(), + m_TransducerGeometry(), + m_TransducerBeamSteering(), + m_TransducerApplication() +{ + // reset element rules + resetRules(); +} + + +IODEnhUSImageModule::IODEnhUSImageModule() +: IODModule(), + m_MandatoryViewAndSliceProgressionDirection(), + m_Anatomy("1" /* mandatory version */), + m_TransducerScanPattern(), + m_TransducerGeometry(), + m_TransducerBeamSteering(), + m_TransducerApplication() +{ + // reset element rules + resetRules(); +} + + +OFString IODEnhUSImageModule::getName() const +{ + return m_ModuleName; +} + + +void IODEnhUSImageModule::resetRules() +{ + // parameters are tag, VM, type. Overwrite old rules if any. + m_Rules->addRule(new IODRule(DCM_ImageType, "4","1" ,m_ModuleName, DcmIODTypes::IE_IMAGE), OFTrue); + m_Rules->addRule(new IODRule(DCM_SamplesPerPixel, "1","1" ,m_ModuleName, DcmIODTypes::IE_IMAGE, "1"), OFTrue); + m_Rules->addRule(new IODRule(DCM_PhotometricInterpretation, "1","1" ,m_ModuleName, DcmIODTypes::IE_IMAGE, "MONOCHROME2"), OFTrue); + m_Rules->addRule(new IODRule(DCM_Rows, "1","1" ,m_ModuleName, DcmIODTypes::IE_IMAGE), OFTrue); + m_Rules->addRule(new IODRule(DCM_Columns, "1","1" ,m_ModuleName, DcmIODTypes::IE_IMAGE), OFTrue); + m_Rules->addRule(new IODRule(DCM_BitsAllocated, "1","1" ,m_ModuleName, DcmIODTypes::IE_IMAGE), OFTrue); + m_Rules->addRule(new IODRule(DCM_BitsStored, "1","1" ,m_ModuleName, DcmIODTypes::IE_IMAGE), OFTrue); + m_Rules->addRule(new IODRule(DCM_HighBit, "1","1" ,m_ModuleName, DcmIODTypes::IE_IMAGE), OFTrue); + m_Rules->addRule(new IODRule(DCM_PixelRepresentation, "1","1" ,m_ModuleName, DcmIODTypes::IE_IMAGE, "0"), OFTrue); + m_Rules->addRule(new IODRule(DCM_DimensionOrganizationType, "1","1" ,m_ModuleName, DcmIODTypes::IE_IMAGE), OFTrue); + m_Rules->addRule(new IODRule(DCM_AcquisitionDateTime, "1","1" ,m_ModuleName, DcmIODTypes::IE_IMAGE), OFTrue); + m_Rules->addRule(new IODRule(DCM_AcquisitionDuration, "1","1" ,m_ModuleName, DcmIODTypes::IE_IMAGE), OFTrue); + m_Rules->addRule(new IODRule(DCM_PixelSpacing, "2","1" ,m_ModuleName, DcmIODTypes::IE_IMAGE), OFTrue); + m_Rules->addRule(new IODRule(DCM_PositionMeasuringDeviceUsed, "1","1C" ,m_ModuleName, DcmIODTypes::IE_IMAGE), OFTrue); + m_Rules->addRule(new IODRule(DCM_LossyImageCompression, "1","1" ,m_ModuleName, DcmIODTypes::IE_IMAGE), OFTrue); + m_Rules->addRule(new IODRule(DCM_LossyImageCompressionRatio, "1-n","1C" ,m_ModuleName, DcmIODTypes::IE_IMAGE), OFTrue); + m_Rules->addRule(new IODRule(DCM_LossyImageCompressionMethod, "1-n","1C" ,m_ModuleName, DcmIODTypes::IE_IMAGE), OFTrue); + m_Rules->addRule(new IODRule(DCM_PresentationLUTShape, "1","1" ,m_ModuleName, DcmIODTypes::IE_IMAGE, "IDENTITY"), OFTrue); + m_Rules->addRule(new IODRule(DCM_RescaleSlope, "1","1" ,m_ModuleName, DcmIODTypes::IE_IMAGE, "1"), OFTrue); + m_Rules->addRule(new IODRule(DCM_RescaleIntercept, "1","1" ,m_ModuleName, DcmIODTypes::IE_IMAGE, "0"), OFTrue); + m_Rules->addRule(new IODRule(DCM_BurnedInAnnotation, "1","1" ,m_ModuleName, DcmIODTypes::IE_IMAGE, "NO"), OFTrue); + m_Rules->addRule(new IODRule(DCM_RecognizableVisualFeatures, "1","3" ,m_ModuleName, DcmIODTypes::IE_IMAGE, "NO"), OFTrue); + m_Rules->addRule(new IODRule(DCM_TransducerScanPatternCodeSequence, "1","1" ,m_ModuleName, DcmIODTypes::IE_IMAGE), OFTrue); + m_Rules->addRule(new IODRule(DCM_TransducerGeometryCodeSequence, "1","1" ,m_ModuleName, DcmIODTypes::IE_IMAGE), OFTrue); + m_Rules->addRule(new IODRule(DCM_TransducerBeamSteeringCodeSequence, "1","1" ,m_ModuleName, DcmIODTypes::IE_IMAGE), OFTrue); + m_Rules->addRule(new IODRule(DCM_TransducerApplicationCodeSequence, "1","1" ,m_ModuleName, DcmIODTypes::IE_IMAGE), OFTrue); + m_Rules->addRule(new IODRule(DCM_ProcessingFunction, "1","3" ,m_ModuleName, DcmIODTypes::IE_IMAGE), OFTrue); + m_Rules->addRule(new IODRule(DCM_MechanicalIndex, "1","1" ,m_ModuleName, DcmIODTypes::IE_IMAGE), OFTrue); + m_Rules->addRule(new IODRule(DCM_BoneThermalIndex, "1","1" ,m_ModuleName, DcmIODTypes::IE_IMAGE), OFTrue); + m_Rules->addRule(new IODRule(DCM_CranialThermalIndex, "1","1" ,m_ModuleName, DcmIODTypes::IE_IMAGE), OFTrue); + m_Rules->addRule(new IODRule(DCM_SoftTissueThermalIndex, "1","1" ,m_ModuleName, DcmIODTypes::IE_IMAGE), OFTrue); + m_Rules->addRule(new IODRule(DCM_DepthsOfFocus, "1-n","1" ,m_ModuleName, DcmIODTypes::IE_IMAGE), OFTrue); + m_Rules->addRule(new IODRule(DCM_DepthOfScanField, "1","1" ,m_ModuleName, DcmIODTypes::IE_IMAGE), OFTrue); +} + + +IODEnhUSImageModule::~IODEnhUSImageModule() +{ + DcmIODUtil::freeContainer(m_TransducerBeamSteering); +} + + +OFCondition IODEnhUSImageModule::read(DcmItem& source, + const OFBool clearOldData) +{ + if (clearOldData) + { + DcmIODUtil::freeContainer(m_TransducerBeamSteering); + } + m_MandatoryViewAndSliceProgressionDirection.read(source, clearOldData); + m_Anatomy.read(source, clearOldData); + DcmIODUtil::readSingleItem(source, DCM_TransducerApplicationCodeSequence, m_TransducerApplication, m_Rules->getByTag(DCM_TransducerApplicationCodeSequence)); + DcmIODUtil::readSingleItem(source, DCM_TransducerGeometryCodeSequence, m_TransducerGeometry, m_Rules->getByTag(DCM_TransducerGeometryCodeSequence)); + DcmIODUtil::readSingleItem(source, DCM_TransducerScanPatternCodeSequence, m_TransducerGeometry, m_Rules->getByTag(DCM_TransducerScanPatternCodeSequence)); + DcmIODUtil::readSubSequence(source, DCM_TransducerBeamSteeringCodeSequence, m_TransducerBeamSteering, m_Rules->getByTag(DCM_TransducerBeamSteeringCodeSequence)); + IODComponent::read(source, clearOldData); + return EC_Normal; +} + + + +OFCondition IODEnhUSImageModule::write(DcmItem& destination) +{ + OFCondition result; + + // Copy sequences to source (which then will be later copied to destination by IODComponent::write() + result = m_MandatoryViewAndSliceProgressionDirection.write(destination); + if (result.good()) result = m_Anatomy.write(destination); + DcmIODUtil::writeSingleItem(result, DCM_TransducerScanPatternCodeSequence, m_TransducerScanPattern, *m_Item, m_Rules->getByTag(DCM_TransducerScanPatternCodeSequence)); + DcmIODUtil::writeSingleItem(result, DCM_TransducerGeometryCodeSequence, m_TransducerGeometry, *m_Item, m_Rules->getByTag(DCM_TransducerGeometryCodeSequence)); + DcmIODUtil::writeSingleItem(result, DCM_TransducerApplicationCodeSequence, m_TransducerApplication, *m_Item, m_Rules->getByTag(DCM_TransducerApplicationCodeSequence)); + DcmIODUtil::writeSubSequence(result, DCM_TransducerBeamSteeringCodeSequence, m_TransducerBeamSteering, *m_Item, m_Rules->getByTag(DCM_TransducerBeamSteeringCodeSequence)); + if (result.good()) result = IODComponent::write(destination); + return result; +} + + +// --- get attributes (C++ string) --- + + +OFCondition IODEnhUSImageModule::getImageType(OFString& value, + const signed long pos) +{ + return DcmIODUtil::getStringValueFromItem(DCM_ImageType, *m_Item, value, pos); +} + + + +OFCondition IODEnhUSImageModule::getSamplesPerPixel(Uint16& value, + const unsigned long pos) +{ + return m_Item->findAndGetUint16(DCM_SamplesPerPixel, value, pos); +} + + + +OFCondition IODEnhUSImageModule::getPhotometricInterpretation(OFString& value, + const signed long pos) +{ + return DcmIODUtil::getStringValueFromItem(DCM_PhotometricInterpretation, *m_Item, value, pos); +} + + +OFCondition IODEnhUSImageModule::getRows(Uint16& value, + const unsigned long pos) +{ + return m_Item->findAndGetUint16(DCM_Rows, value, pos); +} + + + +OFCondition IODEnhUSImageModule::getColumns(Uint16& value, + const unsigned long pos) +{ + return m_Item->findAndGetUint16(DCM_Columns, value, pos); +} + + +OFCondition IODEnhUSImageModule::getBitsAllocated(Uint16& value, + const unsigned long pos) +{ + return m_Item->findAndGetUint16(DCM_BitsAllocated, value, pos); +} + + +OFCondition IODEnhUSImageModule::getBitsStored(Uint16& value, + const unsigned long pos) +{ + return m_Item->findAndGetUint16(DCM_BitsStored, value, pos); +} + + +OFCondition IODEnhUSImageModule::getHighBit(Uint16& value, + const unsigned long pos) +{ + return m_Item->findAndGetUint16(DCM_HighBit, value, pos); +} + + +OFCondition IODEnhUSImageModule::getPixelRepresentation(Uint16& value, + const unsigned long pos) +{ + return m_Item->findAndGetUint16(DCM_PixelRepresentation, value, pos); +} + + +OFCondition IODEnhUSImageModule::getDimensionOrganizationType(OFString& value, + const signed long pos) +{ + return DcmIODUtil::getStringValueFromItem(DCM_DimensionOrganizationType, *m_Item, value, pos); +} + + +OFCondition IODEnhUSImageModule::getAcquisitionDateTime(OFString& value, + const signed long pos) +{ + return DcmIODUtil::getStringValueFromItem(DCM_AcquisitionDateTime, *m_Item, value, pos); +} + + +OFCondition IODEnhUSImageModule::getAcquisitionDuration(Float64& value, + const unsigned long pos) +{ + return m_Item->findAndGetFloat64(DCM_AcquisitionDuration, value, pos); +} + + +OFCondition IODEnhUSImageModule::getPixelSpacing(Float64& value, + const unsigned long pos) +{ + return m_Item->findAndGetFloat64(DCM_PixelSpacing, value, pos); +} + + +OFCondition IODEnhUSImageModule::getPositionMeasuringDevice(OFString& value, + const signed long pos) +{ + return DcmIODUtil::getStringValueFromItem(DCM_PositionMeasuringDeviceUsed, *m_Item, value, pos); +} + + +OFCondition IODEnhUSImageModule::getLossyImageCompression(OFString& value, + const signed long pos) +{ + return DcmIODUtil::getStringValueFromItem(DCM_LossyImageCompression, *m_Item, value, pos); +} + + +OFCondition IODEnhUSImageModule::getLossyImageCompressionRatio(Float64& value, + const unsigned long pos) +{ + return m_Item->findAndGetFloat64(DCM_LossyImageCompressionRatio, value, pos); +} + + +OFCondition IODEnhUSImageModule::getLossyImageCompressionMethod(OFString& value, const signed long pos) +{ + return DcmIODUtil::getStringValueFromItem(DCM_LossyImageCompressionMethod, *m_Item, value, pos); +} + + +OFCondition IODEnhUSImageModule::getPresentationLUTShape(OFString& value, + const signed long pos) +{ + return DcmIODUtil::getStringValueFromItem(DCM_PresentationLUTShape, *m_Item, value, pos); +} + + +OFCondition IODEnhUSImageModule::getRescaleSlope(Float64& value, + const unsigned long pos) +{ + return m_Item->findAndGetFloat64(DCM_RescaleSlope, value, pos); +} + + +OFCondition IODEnhUSImageModule::getRescaleIntercept(OFString& value, + const signed long pos) +{ + return DcmIODUtil::getStringValueFromItem(DCM_RescaleSlope, *m_Item, value, pos); +} + + +GeneralAnatomyMacro& IODEnhUSImageModule::getAnatomy() +{ + return m_Anatomy; +} + + +MandatoryViewAndSliceProgressionDirectionMacro& IODEnhUSImageModule::getMandatoryViewAndSliceProgressionDirection() +{ + return m_MandatoryViewAndSliceProgressionDirection; +} + + +OFCondition IODEnhUSImageModule::getBurnedInAnnotation(OFString& value, + const signed long pos) +{ + return DcmIODUtil::getStringValueFromItem(DCM_BurnedInAnnotation, *m_Item, value, pos); +} + + +OFCondition IODEnhUSImageModule::getRecognizableVisibleFeatures(OFString& value, + const signed long pos) +{ + return DcmIODUtil::getStringValueFromItem(DCM_RecognizableVisualFeatures, *m_Item, value, pos); +} + + +CodeSequenceMacro& IODEnhUSImageModule::getTransducerScanPattern() +{ + return m_TransducerScanPattern; +} + + +CodeSequenceMacro& IODEnhUSImageModule::getTransducerGeometry() +{ + return m_TransducerGeometry; +} + + +OFVector& IODEnhUSImageModule::getTransducerBeamSteering() +{ + return m_TransducerBeamSteering; +} + + +CodeSequenceMacro& IODEnhUSImageModule::getTransducerApplication() +{ + return m_TransducerApplication; +} + + +OFCondition IODEnhUSImageModule::getProcessingFunction(OFString& value, + const signed long pos) +{ + return DcmIODUtil::getStringValueFromItem(DCM_ProcessingFunction, *m_Item, value, pos); +} + + +OFCondition IODEnhUSImageModule::getMechanicalIndex(Float64& value, + const unsigned long pos) +{ + return m_Item->findAndGetFloat64(DCM_MechanicalIndex, value, pos); +} + + +OFCondition IODEnhUSImageModule::getBoneThermalIndex(Float64& value, + const unsigned long pos) +{ + return m_Item->findAndGetFloat64(DCM_BoneThermalIndex, value, pos); +} + + +OFCondition IODEnhUSImageModule::getCranialThermalIndex(Float64& value, + const unsigned long pos) +{ + return m_Item->findAndGetFloat64(DCM_CranialThermalIndex, value, pos); +} + + +OFCondition IODEnhUSImageModule::getSoftTissueThermalIndex(Float64& value, + const unsigned long pos) +{ + return m_Item->findAndGetFloat64(DCM_SoftTissueThermalIndex, value, pos); +} + + +OFCondition IODEnhUSImageModule::getDepthsOfFocus(Float64& value, + const unsigned long pos) +{ + return m_Item->findAndGetFloat64(DCM_DepthsOfFocus, value, pos); +} + + +OFCondition IODEnhUSImageModule::getDepthsOfScanField(Float64& value, + const unsigned long pos) +{ + return m_Item->findAndGetFloat64(DCM_DepthsOfFocus, value, pos); +} + + +// --- set attributes --- + + +OFCondition IODEnhUSImageModule::setImageType(const DcmIODTypes::IOD_ENHUSIMAGETYPE pixelDataChar, + const OFString& imageFlavor, + const OFString& derivedPixelContrast, + const OFBool checkValue) +{ + OFString value; + switch (pixelDataChar) + { + case(DcmIODTypes::IMAGETYPE_ORIGINAL): value = "ORIGINAL\\PRIMARY\\"; break; + case(DcmIODTypes::IMAGETYPE_DERIVED) : value = "DERIVED\\PRIMARY\\"; break; + default: return IOD_EC_InvalidElementValue; + } + value += imageFlavor; + value += "\\"; + value += derivedPixelContrast; + + return m_Item->putAndInsertOFStringArray(DCM_ImageType, value); +} + + +OFCondition IODEnhUSImageModule::setRows(const Uint16 value, + const bool checkValue) +{ + if (checkValue && (value == 0)) + return IOD_EC_InvalidElementValue; + + return m_Item->putAndInsertUint16(DCM_Rows, value); +} + + +OFCondition IODEnhUSImageModule::setColumns(const Uint16 value, + const bool checkValue) +{ + if (checkValue && (value == 0)) + return IOD_EC_InvalidElementValue; + + return m_Item->putAndInsertUint16(DCM_Columns, value); +} + + +OFCondition IODEnhUSImageModule::setBitsAllocated(const Uint16 value, + const bool checkValue) +{ + if (checkValue && (value != 8) && (value != 16)) + return IOD_EC_InvalidElementValue; + + return m_Item->putAndInsertUint16(DCM_BitsAllocated, value); +} + + +OFCondition IODEnhUSImageModule::setBitsStored(const Uint16 value, + const bool checkValue) +{ + if (checkValue && (value != 8) && (value != 16)) + return IOD_EC_InvalidElementValue; + + return m_Item->putAndInsertUint16(DCM_BitsStored, value); +} + + +OFCondition IODEnhUSImageModule::setHighBit(const Uint16 value, + const bool checkValue) +{ + if (checkValue && (value != 7) && (value != 15)) + return IOD_EC_InvalidElementValue; + + return m_Item->putAndInsertUint16(DCM_HighBit, value); +} + + +OFCondition IODEnhUSImageModule::setDimensionOrganizationType(const OFString& value, + const bool checkValue) +{ + OFCondition result; + if (checkValue) + { + if ( (value != "3D") && (value != "3D_TEMPORAL") ) + return IOD_EC_InvalidElementValue; + } + return m_Item->putAndInsertOFStringArray(DCM_DimensionOrganizationType, value); +} + + +OFCondition IODEnhUSImageModule::setAcquisitionDateTime(const OFString& value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmDateTime::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_AcquisitionDateTime, value); + return result; +} + + +OFCondition IODEnhUSImageModule::setAcquisitionDuration(const Float64 value, + const OFBool) +{ + return m_Item->putAndInsertFloat64(DCM_AcquisitionDuration, value); +} + + +OFCondition IODEnhUSImageModule::setPixelSpacing(const OFString& value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmDecimalString::checkStringValue(value, "2") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_PixelSpacing, value); + return result; +} + + +OFCondition IODEnhUSImageModule::setPositionMeasuringDevice(const OFString& value, + const OFBool checkValue) +{ + OFCondition result; + if (checkValue) + { + result = DcmCodeString::checkStringValue(value, "1"); + if (result.good()) + { + if ( (value != "RIGID") && (value != "FREEHAND") ) + result = IOD_EC_InvalidElementValue; + } + } + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_PositionMeasuringDeviceUsed, value); + + return result; +} + + +OFCondition IODEnhUSImageModule::setLossyImageCompression(const OFString& value, + const OFBool checkValue) +{ + if (checkValue) + { + if ( (value != "00") && (value != "01") ) + return IOD_EC_InvalidElementValue; + } + + return m_Item->putAndInsertOFStringArray(DCM_LossyImageCompression, value); +} + + + +OFCondition IODEnhUSImageModule::setLossyImageCompressionMethod(const OFString& value, + const unsigned long pos, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmCodeString::checkStringValue(value, "1-n") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_LossyImageCompressionMethod, value); + return result; +} + + +OFCondition IODEnhUSImageModule::setLossyImageCompressionRatio(const OFString& value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmDecimalString::checkStringValue(value, "1-n") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_LossyImageCompressionRatio, value); + return result; +} + + +OFCondition IODEnhUSImageModule::setRecognizableVisibleFeatures(const OFString& value, + const OFBool checkValue) +{ + if (checkValue) + { + if ( (value != "NO" ) && (value != "YES") ) + return IOD_EC_InvalidElementValue; + } + return m_Item->putAndInsertOFStringArray(DCM_RecognizableVisualFeatures, value); +} + + +OFCondition IODEnhUSImageModule::setProcessingFunction(const OFString& value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmLongString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_ProcessingFunction, value); + return result; +} + + +OFCondition IODEnhUSImageModule::setMechanicalIndex(const OFString& value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmDecimalString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_MechanicalIndex, value); + return result; +} + + +OFCondition IODEnhUSImageModule::setBoneThermalIndex(const OFString& value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmDecimalString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_BoneThermalIndex, value); + return result; +} + + +OFCondition IODEnhUSImageModule::setCranialThermalIndex(const OFString& value, const bool checkValue) +{ + OFCondition result = (checkValue) ? DcmDecimalString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_CranialThermalIndex, value); + return result; +} + + +OFCondition IODEnhUSImageModule::setSoftTissueThermalIndex(const OFString& value, const bool checkValue) +{ + OFCondition result = (checkValue) ? DcmDecimalString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_SoftTissueThermalIndex, value); + return result; +} + + +OFCondition IODEnhUSImageModule::setDepthsOfFocus(const Float64 value, const long unsigned int pos, const bool checkValue) +{ + return m_Item->putAndInsertFloat64(DCM_DepthsOfFocus, value, pos); +} + + +OFCondition IODEnhUSImageModule::setDepthsOfFocus(const OFVector< Float64 >& values, const bool checkValue) +{ + DcmElement* elem = newDicomElement(DCM_DepthsOfFocus); + if (!elem) + return EC_MemoryExhausted; + + OFCondition result; + OFVector::const_iterator it = values.begin(); + while ((it != values.end()) && result.good()) + { + result = elem->putFloat64(*it); + it++; + } + if (result.bad()) + { + delete elem; + } + else + { + result = m_Item->insert(elem); + } + return result; +} + + +OFCondition IODEnhUSImageModule::setDepthsOfScanField(const OFString& value, const bool checkValue) +{ + OFCondition result = (checkValue) ? DcmIntegerString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_DepthOfScanField, value); + return result; +} diff --git a/dcmiod/libsrc/modenhusseries.cc b/dcmiod/libsrc/modenhusseries.cc new file mode 100644 index 00000000..fbce1ed2 --- /dev/null +++ b/dcmiod/libsrc/modenhusseries.cc @@ -0,0 +1,117 @@ +/* + * + * Copyright (C) 2015, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmiod + * + * Author: Michael Onken + * + * Purpose: Class for managing the Enhanced US Series Module + * + */ + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ +#include "dcmtk/dcmiod/modenhusseries.h" +#include "dcmtk/dcmiod/iodutil.h" + +const OFString IODEnhancedUSSeriesModule::m_ModuleName = "EnhancedUSSeries"; + + +IODEnhancedUSSeriesModule::IODEnhancedUSSeriesModule(OFshared_ptr item, + OFshared_ptr rules) +: IODModule(item, rules) +{ + // reset element rules + resetRules(); +} + + +IODEnhancedUSSeriesModule::IODEnhancedUSSeriesModule() +: IODModule() +{ + // reset element rules + resetRules(); +} + + +OFString IODEnhancedUSSeriesModule::getName() const +{ + return m_ModuleName; +} + + +void IODEnhancedUSSeriesModule::resetRules() +{ + // parameters are tag, VM, type. Overwrite old rules if any. + m_Rules->addRule(new IODRule(DCM_Modality, "1","1", m_ModuleName, DcmIODTypes::IE_SERIES, "US"), OFTrue); + m_Rules->addRule(new IODRule(DCM_ReferencedPerformedProcedureStepSequence, "1","1C", m_ModuleName, DcmIODTypes::IE_SERIES), OFTrue); + m_Rules->addRule(new IODRule(DCM_PerformedProtocolCodeSequence, "1","1C", m_ModuleName, DcmIODTypes::IE_SERIES), OFTrue); +} + + +OFCondition IODEnhancedUSSeriesModule::read(DcmItem& source, + const OFBool clearOldData) +{ + if (clearOldData) + clearData(); + + IODComponent::read(source, OFFalse /* data already cleared */); + + DcmIODUtil::readSingleItem(source, DCM_ReferencedPerformedProcedureStepSequence, m_ReferencedPerformedProcedureStep, m_Rules->getByTag(DCM_ReferencedPerformedProcedureStepSequence)); + DcmIODUtil::readSingleItem(source, DCM_PerformedProtocolCodeSequence, m_PerformedProtocolCode, m_Rules->getByTag(DCM_PerformedProtocolCodeSequence)); + + return EC_Normal; +} + + +OFCondition IODEnhancedUSSeriesModule::write(DcmItem& destination) +{ + OFCondition result = EC_Normal; + + result = IODComponent::write(destination); + DcmIODUtil::writeSingleItem(result, DCM_ReferencedPerformedProcedureStepSequence, m_ReferencedPerformedProcedureStep, destination, m_Rules->getByTag(DCM_ReferencedPerformedProcedureStepSequence)); + DcmIODUtil::writeSingleItem(result, DCM_PerformedProtocolCodeSequence, m_PerformedProtocolCode, destination, m_Rules->getByTag(DCM_PerformedProtocolCodeSequence)); + + return result; +} + + +IODEnhancedUSSeriesModule::~IODEnhancedUSSeriesModule() +{ +} + + +OFCondition IODEnhancedUSSeriesModule::getModality(OFString &value, + const signed long pos) const +{ + value = "US"; + return EC_Normal; +} + + +CodeSequenceMacro& IODEnhancedUSSeriesModule::getPerformedProtocolCode() +{ + return m_PerformedProtocolCode; +} + + +SOPInstanceReferenceMacro& IODEnhancedUSSeriesModule::getReferencedPPS() +{ + return m_ReferencedPerformedProcedureStep; +} + + +OFCondition IODEnhancedUSSeriesModule::getPerformedProtocolType(OFString &value, + const signed long pos) const +{ + return DcmIODUtil::getStringValueFromItem(DCM_PerformedProtocolType, *m_Item, value, pos); +} diff --git a/dcmiod/libsrc/modequipment.cc b/dcmiod/libsrc/modequipment.cc new file mode 100644 index 00000000..675ccbf4 --- /dev/null +++ b/dcmiod/libsrc/modequipment.cc @@ -0,0 +1,208 @@ +/* + * + * Copyright (C) 2015, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmiod + * + * Author: Michael Onken + * + * Purpose: Class for managing the General Equipment Module + * + */ + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ +#include "dcmtk/dcmiod/modequipment.h" +#include "dcmtk/dcmdata/dcdeftag.h" +#include "dcmtk/dcmdata/dcvrlo.h" +#include "dcmtk/dcmdata/dcvrst.h" +#include "dcmtk/dcmdata/dcvrsh.h" +#include "dcmtk/dcmiod/iodutil.h" + +IODGeneralEquipmentModule::IODGeneralEquipmentModule(OFshared_ptr item, + OFshared_ptr rules) +: IODModule(item, rules), + m_ModuleName("GeneralEquipmentModule") +{ + // reset element rules + resetRules(); +} + + +IODGeneralEquipmentModule::IODGeneralEquipmentModule() +: IODModule() +{ + resetRules(); +} + + +void IODGeneralEquipmentModule::resetRules() +{ + + // parameters are tag, VM, type. Overwrite old rules if any. + m_Rules->addRule(new IODRule(DCM_Manufacturer, "1","3", m_ModuleName, DcmIODTypes::IE_EQUIPMENT), OFTrue); + m_Rules->addRule(new IODRule(DCM_InstitutionName, "1","3", m_ModuleName, DcmIODTypes::IE_EQUIPMENT), OFTrue); + m_Rules->addRule(new IODRule(DCM_InstitutionAddress, "1","3", m_ModuleName, DcmIODTypes::IE_EQUIPMENT), OFTrue); + m_Rules->addRule(new IODRule(DCM_StationName, "1","3", m_ModuleName, DcmIODTypes::IE_EQUIPMENT), OFTrue); + m_Rules->addRule(new IODRule(DCM_InstitutionalDepartmentName, "1","3", m_ModuleName, DcmIODTypes::IE_EQUIPMENT), OFTrue); + m_Rules->addRule(new IODRule(DCM_ManufacturerModelName, "1","3", m_ModuleName, DcmIODTypes::IE_EQUIPMENT), OFTrue); + m_Rules->addRule(new IODRule(DCM_DeviceSerialNumber, "1","3", m_ModuleName, DcmIODTypes::IE_EQUIPMENT), OFTrue); + m_Rules->addRule(new IODRule(DCM_SoftwareVersions, "1-n","3", m_ModuleName, DcmIODTypes::IE_EQUIPMENT), OFTrue); +} + + +IODGeneralEquipmentModule::~IODGeneralEquipmentModule() +{ + clearData(); +} + + +OFString IODGeneralEquipmentModule::getName() const +{ + return m_ModuleName; +} + + +OFCondition IODGeneralEquipmentModule::getDeviceSerialNumber(OFString& value, + const long signed int pos) const +{ + return DcmIODUtil::getStringValueFromItem(DCM_DeviceSerialNumber, *m_Item, value, pos); +} + + +OFCondition IODGeneralEquipmentModule::getManufacturer(OFString& value, + const long signed int pos) const +{ + return DcmIODUtil::getStringValueFromItem(DCM_Manufacturer, *m_Item, value, pos); +} + + +OFCondition IODGeneralEquipmentModule::getInstitutionName(OFString& value, + const long signed int pos) const +{ + return DcmIODUtil::getStringValueFromItem(DCM_InstitutionName, *m_Item, value, pos); +} + + +OFCondition IODGeneralEquipmentModule::getInstitutionAddress(OFString& value, + const long signed int pos) const +{ + return DcmIODUtil::getStringValueFromItem(DCM_InstitutionAddress, *m_Item, value, pos); +} + + +OFCondition IODGeneralEquipmentModule::getStationName(OFString& value, + const long signed int pos) const +{ + return DcmIODUtil::getStringValueFromItem(DCM_StationName, *m_Item, value, pos); +} + + +OFCondition IODGeneralEquipmentModule::getInstitutionalDepartmentName(OFString& value, + const long signed int pos) const +{ + return DcmIODUtil::getStringValueFromItem(DCM_StationName, *m_Item, value, pos); +} + + +OFCondition IODGeneralEquipmentModule::getManufacturerModelName(OFString& value, + const long signed int pos) const +{ + return DcmIODUtil::getStringValueFromItem(DCM_ManufacturerModelName, *m_Item, value, pos); +} + + +OFCondition IODGeneralEquipmentModule::getSoftwareVersions(OFString& value, + const long signed int pos) const +{ + return DcmIODUtil::getStringValueFromItem(DCM_SoftwareVersions, *m_Item, value, pos); +} + + +OFCondition IODGeneralEquipmentModule::setDeviceSerialNumber(const OFString& value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmLongString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_DeviceSerialNumber, value); + return result; +} + + +OFCondition IODGeneralEquipmentModule::setManufacturer(const OFString& value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmLongString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_Manufacturer, value); + return result; +} + + +OFCondition IODGeneralEquipmentModule::setInstitutionName(const OFString& value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmLongString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_InstitutionName, value); + return result; +} + + +OFCondition IODGeneralEquipmentModule::setInstitutionAddress(const OFString& value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmShortText::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_InstitutionAddress, value); + return result; +} + + +OFCondition IODGeneralEquipmentModule::setStationName(const OFString& value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmShortString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_StationName, value); + return result; +} + + +OFCondition IODGeneralEquipmentModule::setInstutionalDepartmentName(const OFString& value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmLongString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_InstitutionalDepartmentName, value); + return result; +} + + +OFCondition IODGeneralEquipmentModule::setManufacturerModelName(const OFString& value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmLongString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_ManufacturerModelName, value); + return result; + +} + + +OFCondition IODGeneralEquipmentModule::setSoftwareVersions(const OFString& value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmLongString::checkStringValue(value, "1-n") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_SoftwareVersions, value); + return result; +} diff --git a/dcmiod/libsrc/modfor.cc b/dcmiod/libsrc/modfor.cc new file mode 100644 index 00000000..272ad5b8 --- /dev/null +++ b/dcmiod/libsrc/modfor.cc @@ -0,0 +1,102 @@ +/* + * + * Copyright (C) 2015, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmiod + * + * Author: Michael Onken + * + * Purpose: Class for managing the Frame of Reference Module + * + */ + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ +#include "dcmtk/dcmiod/modfor.h" +#include "dcmtk/dcmdata/dcvrui.h" +#include "dcmtk/dcmdata/dcvrlo.h" +#include "dcmtk/dcmdata/dcdeftag.h" +#include "dcmtk/dcmiod/iodutil.h" + +const OFString IODFoRModule::m_ModuleName = "FrameOfReferenceModule"; + + +IODFoRModule::IODFoRModule(OFshared_ptr item, + OFshared_ptr rules) +: IODModule(item, rules) +{ + // reset element rules + resetRules(); +} + + +IODFoRModule::IODFoRModule() +: IODModule() +{ + resetRules(); +} + + +void IODFoRModule::resetRules() +{ + // parameters are tag, VM, type. Overwrite old rules if any. + m_Rules->addRule(new IODRule(DCM_FrameOfReferenceUID, "1","1", m_ModuleName, DcmIODTypes::IE_FOR), OFTrue); + m_Rules->addRule(new IODRule(DCM_PositionReferenceIndicator, "1","2", m_ModuleName, DcmIODTypes::IE_FOR), OFTrue); +} + + +OFString IODFoRModule::getName() const +{ + return m_ModuleName; +} + + +IODFoRModule::~IODFoRModule() +{ + // clear rules from rule set + clearData(); +} + + +OFCondition IODFoRModule::getFrameOfReferenceUID(OFString& value, + const signed long pos) const +{ + return DcmIODUtil::getStringValueFromItem(DCM_FrameOfReferenceUID, *m_Item, value, pos); +} + + +OFCondition IODFoRModule::getPositionReferenceIndicator(OFString& value, + const signed long pos) const +{ + return DcmIODUtil::getStringValueFromItem(DCM_PositionReferenceIndicator, *m_Item, value, pos); +} + + + +OFCondition IODFoRModule::setFrameOfReferenceUID(const OFString &value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmUniqueIdentifier::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_FrameOfReferenceUID, value); + return result; +} + + +OFCondition IODFoRModule::setPositionReferenceIndicator(const OFString &value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmLongString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_PositionReferenceIndicator, value); + return result; +} + diff --git a/dcmiod/libsrc/modgeneralimage.cc b/dcmiod/libsrc/modgeneralimage.cc new file mode 100644 index 00000000..e724b01e --- /dev/null +++ b/dcmiod/libsrc/modgeneralimage.cc @@ -0,0 +1,379 @@ +/* + * + * Copyright (C) 2015, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmiod + * + * Author: Michael Onken + * + * Purpose: Class for managing the General Image Module + * + */ + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ +#include "dcmtk/dcmiod/modgeneralimage.h" +#include "dcmtk/dcmdata/dcdeftag.h" +#include "dcmtk/dcmdata/dcvrui.h" +#include "dcmtk/dcmdata/dcvrtm.h" +#include "dcmtk/dcmdata/dcvrdt.h" +#include "dcmtk/dcmdata/dcvrcs.h" +#include "dcmtk/dcmdata/dcvrds.h" +#include "dcmtk/dcmdata/dcvris.h" +#include "dcmtk/dcmdata/dcvrda.h" +#include "dcmtk/dcmdata/dcvrlt.h" + + +#include "dcmtk/dcmiod/iodutil.h" + +const OFString IODGeneralImageModule::m_ModuleName = "GeneralImageModule"; + + +IODGeneralImageModule::IODGeneralImageModule( OFshared_ptr item, + OFshared_ptr rules) +: IODModule(item, rules) +{ + // reset element rules + resetRules(); +} + + +IODGeneralImageModule::IODGeneralImageModule() +: IODModule() +{ + resetRules(); +} + + +IODGeneralImageModule::~IODGeneralImageModule() +{ +} + + +void IODGeneralImageModule::resetRules() +{ + // parameters are tag, VM, type. Overwrite old rules if any. + m_Rules->addRule(new IODRule(DCM_InstanceNumber, "1", "2", m_ModuleName, DcmIODTypes::IE_IMAGE), OFTrue); + m_Rules->addRule(new IODRule(DCM_PatientOrientation, "2", "2C", m_ModuleName, DcmIODTypes::IE_IMAGE), OFTrue); + m_Rules->addRule(new IODRule(DCM_ContentDate, "1", "2C", m_ModuleName, DcmIODTypes::IE_IMAGE), OFTrue); + m_Rules->addRule(new IODRule(DCM_ContentTime, "1", "2C", m_ModuleName, DcmIODTypes::IE_IMAGE), OFTrue); + m_Rules->addRule(new IODRule(DCM_ImageType, "2-n", "1", m_ModuleName, DcmIODTypes::IE_IMAGE), OFTrue); + m_Rules->addRule(new IODRule(DCM_AcquisitionNumber, "1", "3", m_ModuleName, DcmIODTypes::IE_IMAGE), OFTrue); + m_Rules->addRule(new IODRule(DCM_AcquisitionDate, "1", "3", m_ModuleName, DcmIODTypes::IE_IMAGE), OFTrue); + m_Rules->addRule(new IODRule(DCM_AcquisitionTime, "1", "3", m_ModuleName, DcmIODTypes::IE_IMAGE), OFTrue); + m_Rules->addRule(new IODRule(DCM_AcquisitionDateTime, "1", "3", m_ModuleName, DcmIODTypes::IE_IMAGE), OFTrue); + m_Rules->addRule(new IODRule(DCM_ImageComments, "1", "3", m_ModuleName, DcmIODTypes::IE_IMAGE), OFTrue); + m_Rules->addRule(new IODRule(DCM_BurnedInAnnotation, "1", "3", m_ModuleName, DcmIODTypes::IE_IMAGE), OFTrue); + m_Rules->addRule(new IODRule(DCM_RecognizableVisualFeatures, "1", "3", m_ModuleName, DcmIODTypes::IE_IMAGE), OFTrue); + m_Rules->addRule(new IODRule(DCM_LossyImageCompression, "1", "3", m_ModuleName, DcmIODTypes::IE_IMAGE), OFTrue); + m_Rules->addRule(new IODRule(DCM_LossyImageCompressionRatio, "1", "3", m_ModuleName, DcmIODTypes::IE_IMAGE), OFTrue); + m_Rules->addRule(new IODRule(DCM_LossyImageCompressionMethod, "1-n", "3", m_ModuleName, DcmIODTypes::IE_IMAGE), OFTrue); + m_Rules->addRule(new IODRule(DCM_PresentationLUTShape, "1", "3", m_ModuleName, DcmIODTypes::IE_IMAGE), OFTrue); + m_Rules->addRule(new IODRule(DCM_IrradiationEventUID, "1-n", "3", m_ModuleName, DcmIODTypes::IE_IMAGE), OFTrue); +} + + +OFString IODGeneralImageModule::getName() const +{ + return "GeneralImageModule"; +} + + + +OFCondition IODGeneralImageModule::getInstanceNumber(OFString &value, + const signed long pos) +{ + return DcmIODUtil::getStringValueFromItem(DCM_InstanceNumber, *m_Item, value, pos); +} + + +OFCondition IODGeneralImageModule::getPatientOrientation(OFString &value, + const signed long pos) +{ + return DcmIODUtil::getStringValueFromItem(DCM_PatientOrientation, *m_Item, value, pos); +} + + +OFCondition IODGeneralImageModule::getContentDate(OFString &value, + const signed long pos) +{ + return DcmIODUtil::getStringValueFromItem(DCM_ContentDate, *m_Item, value, pos); +} + + +OFCondition IODGeneralImageModule::getContentTime(OFString &value, + const signed long pos) +{ + return DcmIODUtil::getStringValueFromItem(DCM_ContentTime, *m_Item, value, pos); +} + + +OFCondition IODGeneralImageModule::getImageType(OFString &value, + const signed long pos) +{ + return DcmIODUtil::getStringValueFromItem(DCM_ImageType, *m_Item, value, pos); +} + + +OFCondition IODGeneralImageModule::getAcquisitionNumber(OFString &value, + const signed long pos) +{ + return DcmIODUtil::getStringValueFromItem(DCM_AcquisitionNumber, *m_Item, value, pos); +} + + +OFCondition IODGeneralImageModule::getAcquisitionDate(OFString &value, + const signed long pos) +{ + return DcmIODUtil::getStringValueFromItem(DCM_AcquisitionDate, *m_Item, value, pos); +} + + +OFCondition IODGeneralImageModule::getAcquisitionTime(OFString &value, + const signed long pos) +{ + return DcmIODUtil::getStringValueFromItem(DCM_AcquisitionTime, *m_Item, value, pos); +} + + +OFCondition IODGeneralImageModule::getAcquisitionDateTime(OFString &value, + const signed long pos) +{ + return DcmIODUtil::getStringValueFromItem(DCM_AcquisitionDateTime, *m_Item, value, pos); +} + + +OFCondition IODGeneralImageModule::getImageComments(OFString &value, + const signed long pos) +{ + return DcmIODUtil::getStringValueFromItem(DCM_ImageComments, *m_Item, value, pos); +} + +OFCondition IODGeneralImageModule::getBurnedInAnnotation(OFString &value, + const signed long pos) +{ + return DcmIODUtil::getStringValueFromItem(DCM_BurnedInAnnotation, *m_Item, value, pos); +} + + +OFCondition IODGeneralImageModule::getRecognizableVisualFeatures(OFString &value, + const signed long pos) +{ + return DcmIODUtil::getStringValueFromItem(DCM_RecognizableVisualFeatures, *m_Item, value, pos); +} + + +OFCondition IODGeneralImageModule::getLossyImageCompression(OFString &value, + const signed long pos) +{ + return DcmIODUtil::getStringValueFromItem(DCM_LossyImageCompression, *m_Item, value, pos); +} + + +OFCondition IODGeneralImageModule::getLossyImageCompressionRatio(OFString &value, + const signed long pos) +{ + return DcmIODUtil::getStringValueFromItem(DCM_LossyImageCompressionRatio, *m_Item, value, pos); +} + + +OFCondition IODGeneralImageModule::getLossyImageCompressionMethod(OFString &value, + const signed long pos) +{ + return DcmIODUtil::getStringValueFromItem(DCM_LossyImageCompressionMethod, *m_Item, value, pos); +} + + +OFCondition IODGeneralImageModule::getPresentationLUTShape(OFString &value, + const signed long pos) +{ + return DcmIODUtil::getStringValueFromItem(DCM_PresentationLUTShape, *m_Item, value, pos); +} + + +OFCondition IODGeneralImageModule::getIrradiationEventUID(OFString &value, + const signed long pos) +{ + return DcmIODUtil::getStringValueFromItem(DCM_IrradiationEventUID, *m_Item, value, pos); +} + + +OFCondition IODGeneralImageModule::setInstanceNumber(const OFString &value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmIntegerString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_InstanceNumber, value); + return result; +} + + +OFCondition IODGeneralImageModule::setPatientOrientation(const OFString &value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmCodeString::checkStringValue(value, "2") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_PatientOrientation, value); + return result; +} + + +OFCondition IODGeneralImageModule::setContentDate(const OFString &value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmDate::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_ContentDate, value); + return result; +} + + +OFCondition IODGeneralImageModule::setContentTime(const OFString &value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmTime::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_ContentTime, value); + return result; +} + + +OFCondition IODGeneralImageModule::setImageType(const OFString &value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmCodeString::checkStringValue(value, "2-n") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_ImageType, value); + return result; +} + + +OFCondition IODGeneralImageModule::setAcquisitionNumber(const OFString &value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmIntegerString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_AcquisitionNumber, value); + return result; +} + + +OFCondition IODGeneralImageModule::setAcquisitionDate(const OFString &value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmDate::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_AcquisitionDate, value); + return result; +} + + +OFCondition IODGeneralImageModule::setAcquisitionTime(const OFString &value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmTime::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_AcquisitionTime, value); + return result; +} + + +OFCondition IODGeneralImageModule::setAcquisitionDateTime(const OFString &value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmDateTime::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_AcquisitionDateTime, value); + return result; +} + + +OFCondition IODGeneralImageModule::setImageComments(const OFString &value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmLongText::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_ImageComments, value); + return result; +} + + +OFCondition IODGeneralImageModule::setBurnedInAnnotation(const OFString &value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmCodeString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_BurnedInAnnotation, value); + return result; +} + + + +OFCondition IODGeneralImageModule::setRecognizableVisualFeatures(const OFString &value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmCodeString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_RecognizableVisualFeatures, value); + return result; +} + + + +OFCondition IODGeneralImageModule::setLossyImageCompression(const OFString &value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmCodeString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_LossyImageCompression, value); + return result; +} + + + +OFCondition IODGeneralImageModule::setLossyImageCompressionRatio(const OFString &value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmDecimalString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_LossyImageCompressionRatio, value); + return result; +} + + +OFCondition IODGeneralImageModule::setLossyImageCompressionMethod(const OFString &value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmCodeString::checkStringValue(value, "1-n") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_LossyImageCompressionMethod, value); + return result; +} + + +OFCondition IODGeneralImageModule::setPresentationLUTShape(const OFString &value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmCodeString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_PresentationLUTShape, value); + return result; +} + + +OFCondition IODGeneralImageModule::setIrradiationEventUID(const OFString &value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmUniqueIdentifier::checkStringValue(value, "1-n") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_IrradiationEventUID, value); + return result; +} diff --git a/dcmiod/libsrc/modgeneralseries.cc b/dcmiod/libsrc/modgeneralseries.cc new file mode 100644 index 00000000..5602b04b --- /dev/null +++ b/dcmiod/libsrc/modgeneralseries.cc @@ -0,0 +1,316 @@ +/* + * + * Copyright (C) 2015, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmiod + * + * Author: Michael Onken + * + * Purpose: Class for managing the General Series Module + * + */ + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ +#include "dcmtk/dcmiod/modgeneralseries.h" +#include "dcmtk/dcmdata/dcdeftag.h" +#include "dcmtk/dcmdata/dcvrui.h" +#include "dcmtk/dcmdata/dcuid.h" +#include "dcmtk/dcmdata/dcvrcs.h" +#include "dcmtk/dcmdata/dcvrlo.h" +#include "dcmtk/dcmdata/dcvrda.h" +#include "dcmtk/dcmdata/dcvris.h" +#include "dcmtk/dcmdata/dcvrtm.h" +#include "dcmtk/dcmdata/dcvrpn.h" +#include "dcmtk/dcmiod/iodutil.h" + +const OFString IODGeneralSeriesModule::m_ModuleName = "GeneralSeriesModule"; + + +IODGeneralSeriesModule::IODGeneralSeriesModule(OFshared_ptr item, + OFshared_ptr rules) +: IODModule(item, rules) +{ + // reset element rules + resetRules(); +} + + +OFString IODGeneralSeriesModule::getName() const +{ + return m_ModuleName; +} + + +IODGeneralSeriesModule::IODGeneralSeriesModule() +: IODModule() +{ + resetRules(); +} + + +void IODGeneralSeriesModule::inventMissing() +{ + // Series Instance UID + ensureInstanceUID(); + + // Default handler + IODComponent::inventMissing(); +} + + +void IODGeneralSeriesModule::resetRules() +{ + // parameters are tag, VM, type. Overwrite old rules if any. + m_Rules->addRule(new IODRule(DCM_Modality, "1","1", m_ModuleName, DcmIODTypes::IE_SERIES), OFTrue); + m_Rules->addRule(new IODRule(DCM_SeriesInstanceUID, "1","1", m_ModuleName, DcmIODTypes::IE_SERIES), OFTrue); + m_Rules->addRule(new IODRule(DCM_SeriesNumber, "1","2", m_ModuleName, DcmIODTypes::IE_SERIES), OFTrue); + m_Rules->addRule(new IODRule(DCM_Laterality, "1","2C", m_ModuleName, DcmIODTypes::IE_SERIES), OFTrue); + m_Rules->addRule(new IODRule(DCM_SeriesDate, "1","3", m_ModuleName, DcmIODTypes::IE_SERIES), OFTrue); + m_Rules->addRule(new IODRule(DCM_SeriesTime, "1","3", m_ModuleName, DcmIODTypes::IE_SERIES), OFTrue); + m_Rules->addRule(new IODRule(DCM_PerformingPhysicianName, "1","3", m_ModuleName, DcmIODTypes::IE_SERIES), OFTrue); + m_Rules->addRule(new IODRule(DCM_ProtocolName, "1","3", m_ModuleName, DcmIODTypes::IE_SERIES), OFTrue); + m_Rules->addRule(new IODRule(DCM_SeriesDescription, "1","3", m_ModuleName, DcmIODTypes::IE_SERIES), OFTrue); + m_Rules->addRule(new IODRule(DCM_OperatorsName, "1-n","3", m_ModuleName, DcmIODTypes::IE_SERIES), OFTrue); + m_Rules->addRule(new IODRule(DCM_BodyPartExamined, "1","3", m_ModuleName, DcmIODTypes::IE_SERIES), OFTrue); + m_Rules->addRule(new IODRule(DCM_PatientPosition, "1","2C", m_ModuleName, DcmIODTypes::IE_SERIES), OFTrue); +} + + +void IODGeneralSeriesModule::ensureInstanceUID(const OFBool correctInvalid) +{ + OFString uidstr; + + /* create new sop instance UID if required */ + if (getSeriesInstanceUID(uidstr).bad() || uidstr.empty() ) + { + setSeriesInstanceUID(DcmIODUtil::createUID(1 /* Series Level */)); + } + else if (!uidstr.empty() && correctInvalid) + { + if (DcmUniqueIdentifier::checkStringValue(uidstr, "1").bad()) + { + setSeriesInstanceUID(DcmIODUtil::createUID(1 /* Series Level */)); } + } +} + + +IODGeneralSeriesModule::~IODGeneralSeriesModule() +{ +} + + +OFCondition IODGeneralSeriesModule::getModality(OFString &value, + const signed long pos) const +{ + return DcmIODUtil::getStringValueFromItem(DCM_Modality, *m_Item, value, pos); +} + + +OFCondition IODGeneralSeriesModule::getSeriesInstanceUID(OFString &value, + const signed long pos) const +{ + return DcmIODUtil::getStringValueFromItem(DCM_SeriesInstanceUID, *m_Item, value, pos); +} + + +OFCondition IODGeneralSeriesModule::getSeriesNumber(OFString &value, + const signed long pos) const +{ + return DcmIODUtil::getStringValueFromItem(DCM_SeriesNumber, *m_Item, value, pos); +} + + +OFCondition IODGeneralSeriesModule::getLaterality(OFString& value, + const signed long pos) const +{ + return DcmIODUtil::getStringValueFromItem(DCM_Laterality, *m_Item, value, pos); +} + + + +OFCondition IODGeneralSeriesModule::getSeriesDate(OFString &value, + const signed long pos) const +{ + return DcmIODUtil::getStringValueFromItem(DCM_SeriesDate, *m_Item, value, pos); +} + + +OFCondition IODGeneralSeriesModule::getSeriesTime(OFString &value, + const signed long pos) const +{ + return DcmIODUtil::getStringValueFromItem(DCM_SeriesTime, *m_Item, value, pos); +} + + +OFCondition IODGeneralSeriesModule::getPerformingPhysicianName(OFString &value, + const signed long pos) const +{ + return DcmIODUtil::getStringValueFromItem(DCM_PerformingPhysicianName, *m_Item, value, pos); +} + + +OFCondition IODGeneralSeriesModule::getProtocolName(OFString &value, + const signed long pos) const +{ + return DcmIODUtil::getStringValueFromItem(DCM_ProtocolName, *m_Item, value, pos); +} + + +OFCondition IODGeneralSeriesModule::getSeriesDescription(OFString &value, + const signed long pos) const +{ + return DcmIODUtil::getStringValueFromItem(DCM_SeriesDescription, *m_Item, value, pos); +} + + +OFCondition IODGeneralSeriesModule::getOperatorsName(OFString &value, + const signed long pos) const +{ + return DcmIODUtil::getStringValueFromItem(DCM_OperatorsName, *m_Item, value, pos); +} + + +OFCondition IODGeneralSeriesModule::getBodyPartExamined(OFString &value, + const signed long pos) const +{ + return DcmIODUtil::getStringValueFromItem(DCM_BodyPartExamined, *m_Item, value, pos); +} + + +OFCondition IODGeneralSeriesModule::getPatientPosition(OFString &value, + const signed long pos) const +{ + return DcmIODUtil::getStringValueFromItem(DCM_PatientPosition, *m_Item, value, pos); +} + + +OFCondition IODGeneralSeriesModule::setModality(const OFString &value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmCodeString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_Modality, value); + return result; +} + + +OFCondition IODGeneralSeriesModule::setSeriesInstanceUID(const OFString &value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmUniqueIdentifier::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_SeriesInstanceUID, value); + return result; +} + + +OFCondition IODGeneralSeriesModule::setSeriesNumber(const OFString &value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmIntegerString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_SeriesNumber, value); + return result; +} + + +OFCondition IODGeneralSeriesModule::setLaterality(const DcmIODTypes::IOD_LATERALITY laterality, + const OFBool checkValue) +{ + OFCondition result; + switch(laterality) + { + case DcmIODTypes::LATERALITY_L: result = m_Item->putAndInsertOFStringArray(DCM_Laterality, "L"); break; + case DcmIODTypes::LATERALITY_R: result = m_Item->putAndInsertOFStringArray(DCM_Laterality, "R"); break; + case DcmIODTypes::LATERALITY_UNDEFINED: result = IOD_EC_InvalidLaterality; break; + } + return result; +} + + +OFCondition IODGeneralSeriesModule::setSeriesDate(const OFString &value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmDate::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_SeriesDate, value); + return result; +} + + +OFCondition IODGeneralSeriesModule::setSeriesTime(const OFString &value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmTime::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_SeriesTime, value); + return result; +} + + +OFCondition IODGeneralSeriesModule::setPerformingPhysicianName(const OFString& value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmPersonName::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_PerformingPhysicianName, value); + return result; +} + + +OFCondition IODGeneralSeriesModule::setProtocolName(const OFString& value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmLongString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_ProtocolName, value); + return result; +} + + +OFCondition IODGeneralSeriesModule::setSeriesDescription(const OFString &value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmLongString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_SeriesDescription, value); + return result; +} + + +OFCondition IODGeneralSeriesModule::setOperatorsName(const OFString& value, const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmPersonName::checkStringValue(value, "1-n") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_OperatorsName, value); + return result; +} + + +OFCondition IODGeneralSeriesModule::setBodyPartExamined(const OFString& value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmCodeString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_BodyPartExamined, value); + return result; +} + + +OFCondition IODGeneralSeriesModule::setPatientPosition(const OFString& value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmCodeString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_PatientPosition, value); + return result; +} diff --git a/dcmiod/libsrc/modgeneralstudy.cc b/dcmiod/libsrc/modgeneralstudy.cc new file mode 100644 index 00000000..5cc9b3e3 --- /dev/null +++ b/dcmiod/libsrc/modgeneralstudy.cc @@ -0,0 +1,294 @@ +/* + * + * Copyright (C) 2015, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmiod + * + * Author: Michael Onken + * + * Purpose: Class for managing the General Study Module + * + */ + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ +#include "dcmtk/dcmiod/modgeneralstudy.h" +#include "dcmtk/dcmdata/dcdeftag.h" +#include "dcmtk/dcmdata/dcvrui.h" +#include "dcmtk/dcmdata/dcuid.h" +#include "dcmtk/dcmdata/dcvrpn.h" +#include "dcmtk/dcmdata/dcvrlo.h" +#include "dcmtk/dcmdata/dcvrda.h" +#include "dcmtk/dcmdata/dcvrtm.h" +#include "dcmtk/dcmdata/dcvrsh.h" +#include "dcmtk/dcmiod/iodutil.h" + +const OFString IODGeneralStudyModule::m_ModuleName = "GeneralStudyModule"; + + +IODGeneralStudyModule::IODGeneralStudyModule(OFshared_ptr item, + OFshared_ptr rules) +: IODModule(item, rules), + m_IssuerOfAccessionNumberSequence(), + m_ProcedureCodeSequence(), + m_ReasonForPerformedProcedureCodeSequence() +{ + // reset element rules + resetRules(); +} + + +IODGeneralStudyModule::IODGeneralStudyModule() +: IODModule() +{ + resetRules(); +} + + +void IODGeneralStudyModule::inventMissing() +{ + // Study Instance UID + ensureInstanceUID(); + + IODComponent::inventMissing(); +} + + +void IODGeneralStudyModule::resetRules() +{ + // parameters are tag, VM, type. Overwrite old rules if any. + m_Rules->addRule(new IODRule(DCM_StudyInstanceUID, "1","1", m_ModuleName, DcmIODTypes::IE_STUDY), OFTrue); + m_Rules->addRule(new IODRule(DCM_StudyDate, "1","2", m_ModuleName, DcmIODTypes::IE_STUDY), OFTrue); + m_Rules->addRule(new IODRule(DCM_StudyTime, "1","2", m_ModuleName, DcmIODTypes::IE_STUDY), OFTrue); + m_Rules->addRule(new IODRule(DCM_ReferringPhysicianName, "1","2", m_ModuleName, DcmIODTypes::IE_STUDY), OFTrue); + m_Rules->addRule(new IODRule(DCM_StudyID, "1","2", m_ModuleName, DcmIODTypes::IE_STUDY), OFTrue); + m_Rules->addRule(new IODRule(DCM_AccessionNumber, "1","2", m_ModuleName, DcmIODTypes::IE_STUDY), OFTrue); + m_Rules->addRule(new IODRule(DCM_StudyDescription, "1","3", m_ModuleName, DcmIODTypes::IE_STUDY), OFTrue); + m_Rules->addRule(new IODRule(DCM_IssuerOfAccessionNumberSequence, "1","3", m_ModuleName, DcmIODTypes::IE_STUDY), OFTrue); + m_Rules->addRule(new IODRule(DCM_ProcedureCodeSequence, "1-n","3", m_ModuleName, DcmIODTypes::IE_STUDY), OFTrue); + m_Rules->addRule(new IODRule(DCM_ReasonForPerformedProcedureCodeSequence, "1-n","3", m_ModuleName, DcmIODTypes::IE_STUDY), OFTrue); +} + + +OFString IODGeneralStudyModule::getName() const +{ + return m_ModuleName; +} + + +void IODGeneralStudyModule::clearData() +{ + m_IssuerOfAccessionNumberSequence.clearData(); + DcmIODUtil::freeContainer(m_ProcedureCodeSequence); + DcmIODUtil::freeContainer(m_ReasonForPerformedProcedureCodeSequence); +} + + +OFCondition IODGeneralStudyModule::read(DcmItem& source, + const OFBool clearOldData) +{ + if (clearOldData) + { + clearData(); + } + + IODComponent::read(source, OFFalse /* data already cleared above */); + + DcmIODUtil::readSingleItem(source, DCM_IssuerOfAccessionNumberSequence, m_IssuerOfAccessionNumberSequence, m_Rules->getByTag(DCM_IssuerOfAccessionNumberSequence)); + DcmIODUtil::readSubSequence(source, DCM_ProcedureCodeSequence, m_ProcedureCodeSequence, m_Rules->getByTag(DCM_ProcedureCodeSequence)); + DcmIODUtil::readSubSequence(source, DCM_ReasonForPerformedProcedureCodeSequence, m_ReasonForPerformedProcedureCodeSequence, m_Rules->getByTag(DCM_ReasonForPerformedProcedureCodeSequence)); + + return EC_Normal; +} + + +OFCondition IODGeneralStudyModule::write(DcmItem& destination) +{ + OFCondition result; + DcmIODUtil::writeSingleItem(result, DCM_IssuerOfAccessionNumberSequence, m_IssuerOfAccessionNumberSequence, *m_Item, m_Rules->getByTag(DCM_IssuerOfAccessionNumberSequence)); + DcmIODUtil::writeSubSequence(result, DCM_ProcedureCodeSequence, m_ProcedureCodeSequence, *m_Item, m_Rules->getByTag(DCM_ProcedureCodeSequence)); + DcmIODUtil::writeSubSequence(result, DCM_ReasonForPerformedProcedureCodeSequence, m_ReasonForPerformedProcedureCodeSequence, *m_Item, m_Rules->getByTag(DCM_ReasonForPerformedProcedureCodeSequence)); + + if (result.good()) result = IODComponent::write(destination); + + return result; +} + + + + +IODGeneralStudyModule::~IODGeneralStudyModule() +{ + DcmIODUtil::freeContainer(m_ProcedureCodeSequence); + DcmIODUtil::freeContainer(m_ReasonForPerformedProcedureCodeSequence); +} + + +void IODGeneralStudyModule::ensureInstanceUID(const OFBool correctInvalid) +{ + OFString uidstr; + + /* create new sop instance UID if required */ + if (getStudyInstanceUID(uidstr).bad() || uidstr.empty() ) + { + setStudyInstanceUID(DcmIODUtil::createUID(2 /* Study Level */)); + } + else if (!uidstr.empty() && correctInvalid) + { + if (DcmUniqueIdentifier::checkStringValue(uidstr, "1").bad()) + { + setStudyInstanceUID(DcmIODUtil::createUID(2 /* Study Level */)); + } + } +} + + +// --- get attributes (C++ string) --- + +OFCondition IODGeneralStudyModule::getStudyInstanceUID(OFString &value, + const signed long pos) const +{ + return DcmIODUtil::getStringValueFromItem(DCM_StudyInstanceUID, *m_Item, value, pos); +} + + +OFCondition IODGeneralStudyModule::getReferringPhysicianName(OFString &value, + const signed long pos) const +{ + return DcmIODUtil::getStringValueFromItem(DCM_ReferringPhysicianName, *m_Item, value, pos); +} + + +OFCondition IODGeneralStudyModule::getStudyDescription(OFString &value, + const signed long pos) const +{ + return DcmIODUtil::getStringValueFromItem(DCM_StudyDescription, *m_Item, value, pos); +} + + +OFCondition IODGeneralStudyModule::getStudyDate(OFString &value, + const signed long pos) const +{ + return DcmIODUtil::getStringValueFromItem(DCM_StudyDate, *m_Item, value, pos); + +} + + +OFCondition IODGeneralStudyModule::getStudyTime(OFString &value, + const signed long pos) const +{ + return DcmIODUtil::getStringValueFromItem(DCM_StudyTime, *m_Item, value, pos); +} + + +OFCondition IODGeneralStudyModule::getStudyID(OFString &value, + const signed long pos) const +{ + return DcmIODUtil::getStringValueFromItem(DCM_StudyID, *m_Item, value, pos); +} + + +OFCondition IODGeneralStudyModule::getAccessionNumber(OFString &value, + const signed long pos) const +{ + return DcmIODUtil::getStringValueFromItem(DCM_AccessionNumber, *m_Item, value, pos); +} + + +HL7HierarchicDesignatorMacro& IODGeneralStudyModule::getIssuerOfAccesionNumber() +{ + return m_IssuerOfAccessionNumberSequence; +} + + +OFVector< CodeSequenceMacro* >& IODGeneralStudyModule::getProcedureCodeSequence() +{ + return m_ProcedureCodeSequence; +} + + +OFVector< CodeSequenceMacro* >& IODGeneralStudyModule::getReasonForPerformedProcedureCodeSequence() +{ + return m_ReasonForPerformedProcedureCodeSequence; +} + + +// --- set attributes --- + +OFCondition IODGeneralStudyModule::setReferringPhysicianName(const OFString &value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmPersonName::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_ReferringPhysicianName,value); + return result; +} + + +OFCondition IODGeneralStudyModule::setStudyDescription(const OFString &value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmLongString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_StudyDescription,value); + return result; +} + + +OFCondition IODGeneralStudyModule::setStudyInstanceUID(const OFString &value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmUniqueIdentifier::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_StudyInstanceUID,value); + return result; +} + + +OFCondition IODGeneralStudyModule::setStudyDate(const OFString &value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmDate::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_StudyDate, value); + return result; +} + + +OFCondition IODGeneralStudyModule::setStudyTime(const OFString &value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmTime::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_StudyTime,value); + return result; +} + + +OFCondition IODGeneralStudyModule::setStudyID(const OFString &value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmShortString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_StudyID, value); + return result; +} + + +OFCondition IODGeneralStudyModule::setAccessionNumber(const OFString &value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmShortString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_AccessionNumber, value); + return result; +} + diff --git a/dcmiod/libsrc/modhelp.cc b/dcmiod/libsrc/modhelp.cc new file mode 100644 index 00000000..a68325e7 --- /dev/null +++ b/dcmiod/libsrc/modhelp.cc @@ -0,0 +1,345 @@ +/* + * + * Copyright (C) 2015, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmiod + * + * Author: Michael Onken + * + * Purpose: Helper functions for copying common modules between datasets + * + */ + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ +#include "dcmtk/dcmiod/modhelp.h" +#include "dcmtk/dcmdata/dcitem.h" +#include "dcmtk/dcmdata/dcdeftag.h" + + +// List of tags within the Patient Module +const DcmTagKey DcmModuleHelpers::patientModuleTags[] = +{ + DCM_PatientName, + DCM_PatientID, + // Macro IssuerOfPatientIDMacro + DCM_IssuerOfPatientID, + DCM_IssuerOfPatientIDQualifiersSequence, + // EndMacro IssuerOfPatientIDMacro + DCM_PatientBirthDate, + DCM_PatientSex, + DCM_QualityControlSubject, + DCM_ReferencedPatientSequence, + DCM_PatientBirthTime, + DCM_OtherPatientIDs, + DCM_OtherPatientIDsSequence, + DCM_OtherPatientNames, + DCM_EthnicGroup, + DCM_PatientComments, + DCM_PatientSpeciesDescription, + DCM_PatientSpeciesCodeSequence, + DCM_PatientBreedDescription, + DCM_PatientBreedCodeSequence, + DCM_BreedRegistrationSequence, + DCM_ResponsiblePerson, + DCM_ResponsiblePersonRole, + DCM_ResponsibleOrganization, + DCM_PatientIdentityRemoved, + DCM_DeidentificationMethod, + DCM_DeidentificationMethodCodeSequence +}; + +// List of tags within the Clinical Trial Subject Module +const DcmTagKey DcmModuleHelpers::clinicalTrialSubjectModuleTags[] = +{ + DCM_ClinicalTrialSponsorName, + DCM_ClinicalTrialProtocolID, + DCM_ClinicalTrialProtocolName, + DCM_ClinicalTrialSiteID, + DCM_ClinicalTrialSiteName, + DCM_ClinicalTrialSubjectID, + DCM_ClinicalTrialSubjectReadingID, + DCM_ClinicalTrialProtocolEthicsCommitteeName, + DCM_ClinicalTrialProtocolEthicsCommitteeApprovalNumber +}; + +// List of tags within the General Study Module +const DcmTagKey DcmModuleHelpers::generalStudyModuleTags[] = +{ + DCM_StudyInstanceUID, + DCM_StudyDate, + DCM_StudyTime, + DCM_ReferringPhysicianName, + DCM_ReferringPhysicianIdentificationSequence, + DCM_StudyID, + DCM_AccessionNumber, + DCM_IssuerOfAccessionNumberSequence, + DCM_StudyDescription, + DCM_PhysiciansOfRecord, + DCM_PhysiciansOfRecordIdentificationSequence, + DCM_NameOfPhysiciansReadingStudy, + DCM_PhysiciansReadingStudyIdentificationSequence, + DCM_RequestingServiceCodeSequence, + DCM_ReferencedStudySequence, + DCM_ProcedureCodeSequence, + DCM_ReasonForPerformedProcedureCodeSequence +}; + +// List of tags within the Patient Study Module +const DcmTagKey DcmModuleHelpers::patientStudyModuleTags[] = +{ + DCM_AdmittingDiagnosesDescription, + DCM_AdmittingDiagnosesCodeSequence, + DCM_PatientAge, + DCM_PatientSize, + DCM_PatientWeight, + DCM_PatientSizeCodeSequence, + DCM_Occupation, + DCM_AdditionalPatientHistory, + DCM_AdmissionID, + DCM_IssuerOfAdmissionIDSequence, + DCM_ServiceEpisodeID, + DCM_IssuerOfServiceEpisodeIDSequence, + DCM_ServiceEpisodeDescription, + DCM_PatientSexNeutered +}; + +// List of tags within the Clinical Trial Study Module +const DcmTagKey DcmModuleHelpers::clinicalTrialStudyModuleTags[] = +{ + DCM_ClinicalTrialTimePointID, + DCM_ClinicalTrialTimePointDescription, + DCM_ConsentForClinicalTrialUseSequence +}; + +// List of tags within the General Series Module +const DcmTagKey DcmModuleHelpers::generalSeriesModuleTags[] = +{ + DCM_Modality, + DCM_SeriesInstanceUID, + DCM_SeriesNumber, + DCM_Laterality, + DCM_SeriesDate, + DCM_SeriesTime, + DCM_PerformingPhysicianName, + DCM_PerformingPhysicianIdentificationSequence, + DCM_ProtocolName, + DCM_SeriesDescription, + DCM_SeriesDescriptionCodeSequence, + DCM_OperatorsName, + DCM_OperatorIdentificationSequence, + DCM_ReferencedPerformedProcedureStepSequence, + DCM_RelatedSeriesSequence, + DCM_BodyPartExamined, + DCM_PatientPosition, + DCM_SmallestPixelValueInSeries, + DCM_LargestPixelValueInSeries, + DCM_RequestAttributesSequence, + // Macro PerformedProcedureStepSummaryMacro + DCM_PerformedProcedureStepID, + DCM_PerformedProcedureStepStartDate, + DCM_PerformedProcedureStepStartTime, + DCM_PerformedProcedureStepEndDate, + DCM_PerformedProcedureStepEndTime, + DCM_PerformedProcedureStepDescription, + DCM_PerformedProtocolCodeSequence, + DCM_CommentsOnThePerformedProcedureStep, + // EndMacro PerformedProcedureStepSummaryMacro + DCM_AnatomicalOrientationType +}; + +// List of tags within the Clinical Trial Series Module +const DcmTagKey DcmModuleHelpers::clinicalTrialSeriesModuleTags[] = +{ + DCM_ClinicalTrialCoordinatingCenterName, + DCM_ClinicalTrialSeriesID, + DCM_ClinicalTrialSeriesDescription +}; + +// List of tags within the General Equipment Module +const DcmTagKey DcmModuleHelpers::generalEquipmentModuleTags[] = +{ + DCM_Manufacturer, + DCM_InstitutionName, + DCM_InstitutionAddress, + DCM_StationName, + DCM_InstitutionalDepartmentName, + DCM_ManufacturerModelName, + DCM_DeviceSerialNumber, + DCM_SoftwareVersions, + DCM_GantryID, + DCM_SpatialResolution, + DCM_DateOfLastCalibration, + DCM_TimeOfLastCalibration, + DCM_PixelPaddingValue +}; + +// List of tags within the Frame of Reference Module +const DcmTagKey DcmModuleHelpers::frameOfReferenceModuleTags[] = +{ + DCM_FrameOfReferenceUID, + DCM_PositionReferenceIndicator +}; + +// List of tags within the SOP Common Module, excluding Digital Signatures Macro +const DcmTagKey DcmModuleHelpers::sopCommonModuleTags[] = +{ + DCM_SOPClassUID, + DCM_SOPInstanceUID, + DCM_SpecificCharacterSet, + DCM_InstanceCreationDate, + DCM_InstanceCreationTime, + DCM_InstanceCoercionDateTime, + DCM_InstanceCreatorUID, + DCM_RelatedGeneralSOPClassUID, + DCM_OriginalSpecializedSOPClassUID, + DCM_CodingSchemeIdentificationSequence, + DCM_TimezoneOffsetFromUTC, + DCM_ContributingEquipmentSequence, + DCM_InstanceNumber, + DCM_SOPInstanceStatus, + DCM_SOPAuthorizationDateTime, + DCM_SOPAuthorizationComment, + DCM_AuthorizationEquipmentCertificationNumber, + // Macro DigitalSignaturesMacro + //DCM_MACParametersSequence, + //DCM_DigitalSignaturesSequence, + // EndMacro DigitalSignaturesMacro + DCM_EncryptedAttributesSequence, + DCM_OriginalAttributesSequence, + DCM_HL7StructuredDocumentReferenceSequence, + DCM_LongitudinalTemporalInformationModified, + DCM_QueryRetrieveView, + DCM_ConversionSourceAttributesSequence +}; + +// List of tags within the General Image Module +const DcmTagKey DcmModuleHelpers::generalImageModuleTags[] = +{ + DCM_InstanceNumber, + DCM_PatientOrientation, + DCM_ContentDate, + DCM_ContentTime, + DCM_ImageType, + DCM_AcquisitionNumber, + DCM_AcquisitionDate, + DCM_AcquisitionTime, + DCM_AcquisitionDateTime, + DCM_ReferencedImageSequence, + DCM_DerivationDescription, + DCM_DerivationCodeSequence, + DCM_SourceImageSequence, + DCM_ReferencedInstanceSequence, + DCM_ImagesInAcquisition, + DCM_ImageComments, + DCM_QualityControlImage, + DCM_BurnedInAnnotation, + DCM_RecognizableVisualFeatures, + DCM_LossyImageCompression, + DCM_LossyImageCompressionRatio, + DCM_LossyImageCompressionMethod, + DCM_IconImageSequence, + DCM_PresentationLUTShape, + DCM_IrradiationEventUID, + DCM_RealWorldValueMappingSequence +}; + + +void DcmModuleHelpers::copyElement(const DcmTagKey& tag, DcmItem& src, DcmItem& dest) +{ + DcmElement *delem; + OFCondition cond; + // get (deep) copy of element + cond = src.findAndGetElement(tag, delem, OFFalse /*searchIntoSub*/, OFTrue /*createCopy*/); + if (cond.good()) + { + // and insert into destination item + cond = dest.insert(delem, OFTrue); + if (cond.bad()) + { + // we do not expect any errors here, so report it + DCMDATA_ERROR("Could not insert element with tag " << tag << " into item: " << cond.text()); + } + } +} + +template +inline void DcmModuleHelpers::copyModule( const DcmTagKey (&tags)[N], DcmItem& src, DcmItem& dest ) +{ + for (const DcmTagKey* it = tags, * const end = tags + N; it != end; ++it) + DcmModuleHelpers::copyElement(*it, src, dest); +} + + +void DcmModuleHelpers::copyPatientModule(DcmItem& src, DcmItem& dest) +{ + copyModule(patientModuleTags, src, dest); +} + + +void DcmModuleHelpers::copyClinicalTrialSubjectModule(DcmItem& src, DcmItem& dest) +{ + copyModule(clinicalTrialSubjectModuleTags, src, dest); +} + + +void DcmModuleHelpers::copyGeneralStudyModule(DcmItem& src, DcmItem& dest) +{ + copyModule(generalStudyModuleTags, src, dest); +} + + +void DcmModuleHelpers::copyPatientStudyModule(DcmItem& src, DcmItem& dest) +{ + copyModule(patientStudyModuleTags, src, dest); +} + + +void DcmModuleHelpers::copyClinicalTrialStudyModule(DcmItem& src, DcmItem& dest) +{ + copyModule(clinicalTrialStudyModuleTags, src, dest); +} + + +void DcmModuleHelpers::copyGeneralSeriesModule(DcmItem& src, DcmItem& dest) +{ + copyModule(generalSeriesModuleTags, src, dest); +} + + +void DcmModuleHelpers::copyClinicalTrialSeriesModule(DcmItem& src, DcmItem& dest) +{ + copyModule(clinicalTrialSeriesModuleTags, src, dest); +} + + +void DcmModuleHelpers::copyGeneralEquipmentModule(DcmItem& src, DcmItem& dest) +{ + copyModule(generalEquipmentModuleTags, src, dest); +} + + +void DcmModuleHelpers::copyFrameOfReferenceModule(DcmItem& src, DcmItem& dest) +{ + copyModule(frameOfReferenceModuleTags, src, dest); +} + + +void DcmModuleHelpers::copySOPCommonModule(DcmItem& src, DcmItem& dest) +{ + copyModule(sopCommonModuleTags, src, dest); +} + + +void DcmModuleHelpers::copyGeneralImageModule(DcmItem& src, DcmItem& dest) +{ + copyModule(generalImageModuleTags, src, dest); +} diff --git a/dcmiod/libsrc/modimagepixel.cc b/dcmiod/libsrc/modimagepixel.cc new file mode 100644 index 00000000..e7fb2ca7 --- /dev/null +++ b/dcmiod/libsrc/modimagepixel.cc @@ -0,0 +1,299 @@ +/* + * + * Copyright (C) 2015, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmiod + * + * Author: Michael Onken + * + * Purpose: Class for managing the Image Pixel Module + * + */ + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ +#include "dcmtk/dcmiod/modimagepixel.h" +#include "dcmtk/dcmdata/dcdeftag.h" +#include "dcmtk/dcmdata/dcvrobow.h" +#include "dcmtk/dcmdata/dcvrcs.h" +#include "dcmtk/dcmdata/dcvris.h" +#include "dcmtk/dcmiod/iodutil.h" + +const OFString IODImagePixelModule::m_ModuleName = "ImagePixelModule"; + + +IODImagePixelModule::IODImagePixelModule(OFshared_ptr item, + OFshared_ptr rules) +: IODModule(item, rules) +{ + // reset element rules + resetRules(); +} + + +OFString IODImagePixelModule::getName() const +{ + return m_ModuleName; +} + + +IODImagePixelModule::IODImagePixelModule() +: IODModule() +{ + resetRules(); +} + + +void IODImagePixelModule::resetRules() +{ + // parameters are tag, VM, type. Overwrite old rules if any. + m_Rules->addRule(new IODRule(DCM_SamplesPerPixel, "1", "1", m_ModuleName, DcmIODTypes::IE_IMAGE), OFTrue); + m_Rules->addRule(new IODRule(DCM_PhotometricInterpretation, "1", "1", m_ModuleName, DcmIODTypes::IE_IMAGE), OFTrue); + m_Rules->addRule(new IODRule(DCM_Rows, "1", "1", m_ModuleName, DcmIODTypes::IE_IMAGE), OFTrue); + m_Rules->addRule(new IODRule(DCM_Columns, "1", "1n", m_ModuleName, DcmIODTypes::IE_IMAGE), OFTrue); + m_Rules->addRule(new IODRule(DCM_BitsAllocated, "1", "1", m_ModuleName, DcmIODTypes::IE_IMAGE), OFTrue); + m_Rules->addRule(new IODRule(DCM_BitsStored, "1", "1", m_ModuleName, DcmIODTypes::IE_IMAGE), OFTrue); + m_Rules->addRule(new IODRule(DCM_HighBit, "1", "1", m_ModuleName, DcmIODTypes::IE_IMAGE), OFTrue); + m_Rules->addRule(new IODRule(DCM_PixelRepresentation, "1", "1", m_ModuleName, DcmIODTypes::IE_IMAGE), OFTrue); + m_Rules->addRule(new IODRule(DCM_PlanarConfiguration, "1", "1C", m_ModuleName, DcmIODTypes::IE_IMAGE), OFTrue); + m_Rules->addRule(new IODRule(DCM_PixelAspectRatio, "2", "1C", m_ModuleName, DcmIODTypes::IE_IMAGE), OFTrue); + m_Rules->addRule(new IODRule(DCM_ICCProfile, "1", "3", m_ModuleName, DcmIODTypes::IE_IMAGE), OFTrue); +} + + +IODImagePixelModule::~IODImagePixelModule() +{ +} + + +OFCondition IODImagePixelModule::getSamplesPerPixel(Uint16 &value, + const signed long pos) +{ + return m_Item->findAndGetUint16(DCM_SamplesPerPixel, value, pos); +} + + +OFCondition IODImagePixelModule::getPhotometricInterpretation(OFString&value, + const signed long pos) +{ + return DcmIODUtil::getStringValueFromItem(DCM_PhotometricInterpretation, *m_Item, value, pos); +} + + +OFCondition IODImagePixelModule::getRows(Uint16& value, + const signed long pos) +{ + return m_Item->findAndGetUint16(DCM_Rows, value, pos); +} + + +OFCondition IODImagePixelModule::getColumns(Uint16& value, + const signed long pos) +{ + return m_Item->findAndGetUint16(DCM_Columns, value, pos); +} + + +OFCondition IODImagePixelModule::getBitsAllocated(Uint16& value, + const signed long pos) +{ + return m_Item->findAndGetUint16(DCM_BitsAllocated, value, pos); +} + + +OFCondition IODImagePixelModule::getBitsStored(Uint16& value, + const signed long pos) +{ + return m_Item->findAndGetUint16(DCM_BitsStored, value, pos); +} + + +OFCondition IODImagePixelModule::getHighBit(Uint16& value, + const signed long pos) +{ + return m_Item->findAndGetUint16(DCM_HighBit, value, pos); +} + + +OFCondition IODImagePixelModule::getPixelRepresentation(Uint16& value, + const signed long pos) +{ + return m_Item->findAndGetUint16(DCM_PixelRepresentation, value, pos); +} + + +OFCondition IODImagePixelModule::getPlanarConfiguration(Uint16& value, + const signed long pos) +{ + return m_Item->findAndGetUint16(DCM_PlanarConfiguration, value, pos); +} + + +OFCondition IODImagePixelModule::getPixelAspectRatio(Uint16& value, + const signed long pos) +{ + return m_Item->findAndGetUint16(DCM_PixelAspectRatio, value, pos); +} + + +OFCondition IODImagePixelModule::getICCProfile(OFVector& values) +{ + DcmElement* elem = NULL; + OFCondition result = m_Item->findAndGetElement(DCM_ICCProfile, elem); + if (result.good()) + { + DcmOtherByteOtherWord* ob = OFstatic_cast(DcmOtherByteOtherWord*, elem); + if (ob) + return DcmIODUtil::copyFromUint8Array > (ob, values); + else + return EC_InternalError; + } + else + return EC_TagNotFound; +} + + +OFCondition IODImagePixelModule::setSamplesPerPixel(const Uint16 value, + const OFBool checkValue) +{ + OFCondition result = EC_Normal; + + // only values 1, 3 and 4 (retired) are permitted + if (checkValue) + { + if ( (value == 0) || (value == 2) || (value > 4) ) + { + DCMIOD_ERROR("Value " << value << " not permitted for attribute Samples Per Pixel"); + result = EC_InvalidValue; + } + else if (value == 4) + { + DCMIOD_WARN("Value " << value << " is retired for attribute Samples Per Pixel"); + } + } + + if (result.good() ) + result = m_Item->putAndInsertUint16(DCM_SamplesPerPixel, value); + + // TODO: Check consistency with photometric interpretation + return result; +} + + +OFCondition IODImagePixelModule::setPhotometricInterpretation(const OFString& value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmCodeString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_PhotometricInterpretation, value); + return result; +} + + +OFCondition IODImagePixelModule::setRows(const Uint16 value, + const OFBool checkValue) +{ + return m_Item->putAndInsertUint16(DCM_Rows, value); +} + + +OFCondition IODImagePixelModule::setColumns(const Uint16 value, + const OFBool checkValue) +{ + return m_Item->putAndInsertUint16(DCM_Columns, value); +} + + +OFCondition IODImagePixelModule::setBitsAllocated(const Uint16 value, + const OFBool checkValue) +{ + return m_Item->putAndInsertUint16(DCM_BitsAllocated, value); +} + + +OFCondition IODImagePixelModule::setBitsStored(const Uint16 value, + const OFBool checkValue) +{ + // TODO: check consistency between bits allocated, bits stored and high bit if possible + return m_Item->putAndInsertUint16(DCM_BitsStored, value); +} + + +OFCondition IODImagePixelModule::setHighBit(const Uint16 value, + const OFBool checkValue) +{ + // TODO: check consistency between bits allocated, bits stored and high bit if possible + return m_Item->putAndInsertUint16(DCM_HighBit, value); +} + + +OFCondition IODImagePixelModule::setPixelRepresentation(const Uint16 value, + const OFBool checkValue) +{ + OFCondition result = EC_Normal; + if (checkValue) + { + if ( (value != 0) && (value != 1) ) + { + DCMIOD_ERROR("Value " << value << " not permitted for attribute Pixel Representation"); + result = EC_InvalidValue; + } + } + if ( result.good() ) + { + result = m_Item->putAndInsertUint16(DCM_PixelRepresentation, value); + } + return result; +} + + +OFCondition IODImagePixelModule::setPlanarConfiguration(const Uint16 value, + const OFBool checkValue) +{ + OFCondition result = EC_Normal; + if (checkValue) + { + if ( (value != 0) && (value != 1) ) + { + DCMIOD_ERROR("Value " << value << " not permitted for attribute Planar Configuration"); + result = EC_InvalidValue; + } + } + if ( result.good() ) + { + result = m_Item->putAndInsertUint16(DCM_PlanarConfiguration, value); + } + return result; +} + + +OFCondition IODImagePixelModule::setPixelAspectRatio(const OFString& verticalPixelSize, + const OFString& horizontalPixelSize, + const OFBool checkValue) +{ + OFString concat = verticalPixelSize; + concat += "\\"; concat += horizontalPixelSize; + OFCondition cond; + if (checkValue) + { + cond = DcmIntegerString::checkStringValue(concat, "2"); + // check for unsignedness, too? + } + if (cond.good()) m_Item->putAndInsertOFStringArray(DCM_PixelAspectRatio, concat); + return cond; +} + + +OFCondition IODImagePixelModule::setICCProfile(const Uint8* values, + const size_t length) +{ + return m_Item->putAndInsertUint8Array(DCM_ICCProfile, values, length); +} diff --git a/dcmiod/libsrc/modmultiframedimension.cc b/dcmiod/libsrc/modmultiframedimension.cc new file mode 100644 index 00000000..6dd6e755 --- /dev/null +++ b/dcmiod/libsrc/modmultiframedimension.cc @@ -0,0 +1,620 @@ +/* + * + * Copyright (C) 2015, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmiod + * + * Author: Michael Onken + * + * Purpose: Class for managing the Multi-frame Functional Groups Module + * + */ + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmiod/modmultiframedimension.h" +#include "dcmtk/dcmdata/dcdeftag.h" +#include "dcmtk/dcmdata/dcvrat.h" +#include "dcmtk/dcmdata/dcvrlo.h" +#include "dcmtk/dcmdata/dcvrui.h" +#include "dcmtk/dcmdata/dcvrcs.h" +#include "dcmtk/dcmdata/dcpath.h" // for private tag reservation checking // TODO move to DcmItem? +#include "dcmtk/dcmiod/iodutil.h" // for static helpers + +const OFString IODMultiframeDimensionModule::m_ModuleName = "MultiframeDimensionModule"; + + +IODMultiframeDimensionModule::IODMultiframeDimensionModule(OFshared_ptr data, + OFshared_ptr rules) : + IODModule(data, rules), + m_DimensionIndexSequence(), + m_DimensionOrganizationSequence() +{ + // reset element rules + resetRules(); +} + + +IODMultiframeDimensionModule::IODMultiframeDimensionModule() +: IODModule() +{ + resetRules(); +} + + +OFCondition IODMultiframeDimensionModule::addDimensionIndex(const DcmTagKey& dimensionIndexPointer, + const OFString& dimensionOrganizationUID, + const DcmTagKey& functionalGroupPointer, + const OFString& dimensionDescriptionLabel, + const OFString& dimensionIndexPrivateCreator, + const OFString& functionalGroupPrivateCreator) +{ + if ( (dimensionIndexPointer.isPrivate() && dimensionIndexPrivateCreator.empty()) || + (functionalGroupPointer.isPrivate() && functionalGroupPrivateCreator.empty()) ) + { + DCMIOD_ERROR("Cannot add private Dimension Index without private creator"); + return IOD_EC_MissingAttribute; + } + + if (dimensionOrganizationUID.empty()) + { + DCMIOD_ERROR("Cannot add Dimension Index without Dimension Organization UID"); + return IOD_EC_MissingAttribute; + } + + DimensionIndexItem* dim = new DimensionIndexItem(); + if (!dim) + return EC_MemoryExhausted; + + OFCondition result = dim->setDimensionOrganizationUID(dimensionOrganizationUID); + if (result.good()) result = dim->setFunctionalGroupPointer(functionalGroupPointer); + if (result.good()) result = dim->setDimensionIndexPointer(dimensionIndexPointer); + if (result.good() && !dimensionIndexPrivateCreator.empty()) dim->setDimensionIndexPrivateCreator(dimensionIndexPrivateCreator); + if (result.good() && !functionalGroupPrivateCreator.empty()) dim->setFunctionalGroupPrivateCreator(functionalGroupPrivateCreator); + if (result.good() && !dimensionDescriptionLabel.empty()) dim->setDimensionDescriptionLabel(dimensionDescriptionLabel); + + if (result.bad()) + { + DCMIOD_ERROR("Could not add Dimension Index: Invalid data values"); + delete dim; + } + + m_DimensionIndexSequence.push_back(dim); + + return result; +} + + +OFString IODMultiframeDimensionModule::getName() const +{ + return m_ModuleName; +} + + +void IODMultiframeDimensionModule::clearData() +{ + DcmIODUtil::freeContainer(m_DimensionIndexSequence); + IODComponent::clearData(); +} + + + +OFCondition IODMultiframeDimensionModule::read(DcmItem& source, + const OFBool clearOldData) +{ + if (clearOldData) + clearData(); + + IODComponent::read(source, OFFalse /* data already cleared above */); + + DcmIODUtil::readSubSequence(source, DCM_DimensionIndexSequence, m_DimensionIndexSequence, m_Rules->getByTag(DCM_DimensionIndexSequence)); + DcmIODUtil::readSubSequence(source, DCM_DimensionOrganizationSequence, m_DimensionOrganizationSequence, m_Rules->getByTag(DCM_DimensionOrganizationSequence)); + + return EC_Normal; +} + + +OFCondition IODMultiframeDimensionModule::write(DcmItem& destination) +{ + OFCondition result = EC_Normal; + + // Re-create dimension organization data + createDimensionOrganizationData(); + DcmIODUtil::writeSubSequence >(result, DCM_DimensionOrganizationSequence, m_DimensionOrganizationSequence, *m_Item, m_Rules->getByTag(DCM_DimensionOrganizationSequence)); + + DcmIODUtil::writeSubSequence >(result, DCM_DimensionIndexSequence, m_DimensionIndexSequence, *m_Item, m_Rules->getByTag(DCM_DimensionIndexSequence)); + + result = IODComponent::write(destination); + return result; +} + + +void IODMultiframeDimensionModule::resetRules() +{ + // Parameters for Rule are tag, VM, type (1,1C,2,2C,3), module name and logical IOD level + m_Rules->addRule(new IODRule(DCM_DimensionOrganizationSequence, "1-n", "1", m_ModuleName, DcmIODTypes::IE_INSTANCE), OFTrue); + m_Rules->addRule(new IODRule(DCM_DimensionOrganizationType, "1", "3", m_ModuleName, DcmIODTypes::IE_INSTANCE), OFTrue); + m_Rules->addRule(new IODRule(DCM_DimensionIndexSequence, "1-n", "1", m_ModuleName, DcmIODTypes::IE_INSTANCE), OFTrue); +} + + +OFCondition IODMultiframeDimensionModule::checkDimensions(DcmItem* fgItem) +{ + if (fgItem == NULL) + { + fgItem = &getData(); + } + + DcmSequenceOfItems *perFrame = NULL; + if (fgItem->findAndGetSequence(DCM_PerFrameFunctionalGroupsSequence, perFrame).bad()) + { + DCMIOD_WARN("Will not check dimension consistency with functional groups (no per-frame functional groups found)"); + } + + OFCondition result; + OFVector::iterator dim = m_DimensionIndexSequence.begin(); + size_t errors = 0; + size_t dimNo = 1; + while (dim != m_DimensionIndexSequence.end()) + { + DcmTagKey indexPointer; + result = (*dim)->getDimensionIndexPointer(indexPointer); + if (result.bad()) + { + DCMIOD_ERROR("Dimension " << dimNo << " does not provide a dimension index pointer"); + errors++; + } + OFString uid; + result = (*dim)->getDimensionOrganizationUID(uid); + if (result.bad()) + { + DCMIOD_ERROR("Dimension " << dimNo << " does not provide a dimension organization UID"); + errors++; + } + DcmTagKey fgPointer; + result = (*dim)->getFunctionalGroupPointer(fgPointer); + if (result.bad()) + { + DCMIOD_ERROR("Dimension " << dimNo << " does not provide a functional group pointer"); + errors++; + } + OFString privateCreator; + if (indexPointer.isPrivate() && (indexPointer != DCM_UndefinedTagKey) ) + { + result = (*dim)->getDimensionIndexPrivateCreator(privateCreator); + if (result.bad()) + { + DCMIOD_ERROR("Dimension " << dimNo << " has private index pointer " << indexPointer << " but private creator is not set"); + errors++; + } + } + OFString privateFGCreator; + if (fgPointer.isPrivate() && (fgPointer != DCM_UndefinedTagKey)) + { + result = (*dim)->getFunctionalGroupPrivateCreator(privateFGCreator); + if (result.bad()) + { + DCMIOD_ERROR("Dimension " << dimNo << " has private fg group pointer " << fgPointer << " but private creator is not set"); + errors++; + } + } + + if (perFrame && (fgPointer != DCM_UndefinedTagKey) && (indexPointer != DCM_UndefinedTagKey) ) + { + if (!getIndexElement(perFrame, fgPointer, indexPointer, privateFGCreator, privateCreator)) + { + errors++; + } + } + + dim++; + } + + if (errors > 0) + return IOD_EC_InvalidDimensions; + else + return EC_Normal; +} + + +DcmElement* IODMultiframeDimensionModule::getIndexElement(DcmSequenceOfItems *perFrameFG, + const DcmTagKey& fgPointer, + const DcmTagKey& indexPointer, + const OFString& fgPrivateCreator, + const OFString& privateCreator) +{ + if (perFrameFG == NULL) + { + DCMIOD_ERROR("Cannot get Dimension Index: No per-frame functional groups are provided"); + return NULL; // nothing to do + } + + size_t numFrames = perFrameFG->card(); + OFCondition result; + DcmElement *returnValue = NULL; + for (size_t count = 0; count < numFrames; count++) + { + DcmItem* item = perFrameFG->getItem(count); + if (item != NULL) + { + // Check for the functional group mentioned in dimension + DcmSequenceOfItems *fgSequence = NULL; + if (item->findAndGetSequence(fgPointer, fgSequence).good()) + { + // Check private reservation for fg if necessary + if (fgPointer.isPrivate()) + { + result = DcmPathProcessor::checkPrivateTagReservation(item, fgPointer, fgPrivateCreator); + if (result.bad()) + { + DCMIOD_ERROR("Cannot get Dimension Index for frame " << count << ": " << result.text()); + } + } + // Check whether actual fg information exists (single item in related fg sequence) + DcmItem *fgItem = fgSequence->getItem(0); + if (fgItem != NULL) + { + if (fgItem->findAndGetElement(indexPointer, returnValue).good()) + { + if (returnValue->getTag().isPrivate()) + { + if (!privateCreator.empty()) + { + result = DcmPathProcessor::checkPrivateTagReservation(fgItem, indexPointer, privateCreator); + if (result.bad()) + { + DCMIOD_ERROR("Cannot get Dimension Index for frame " << count << ": " << result.text()); + } + } + else + { + DCMIOD_ERROR("Cannot get Dimension Index since fg " << fgPointer << " misses reservation for frame " << count << ": " << result.text()); + } + } + } + else + { + DCMIOD_ERROR("Cannot get Dimension Index since fg " << fgPointer << " does not contain index pointer attribute " << indexPointer << " for frame " << count); + } + } + else + { + DCMIOD_ERROR("Cannot get Dimension Index since fg " << fgPointer << " does have any data for frame " << count); + } + } + else + { + DCMIOD_ERROR("Cannot get Dimension Index since fg " << fgPointer << " does not exist for frame " << count); + } + } + else + { + DCMIOD_ERROR("Cannot get Dimension Index: since no per-frame functional group for frame " << count << " exists"); + } + } + + return returnValue; +} + + + +void IODMultiframeDimensionModule::createDimensionOrganizationData() +{ + // Clear old data + DcmIODUtil::freeContainer(m_DimensionOrganizationSequence); + // Collect dimensions from all Dimension Index Pointers + OFVector::iterator item = m_DimensionIndexSequence.begin(); + while (item != m_DimensionIndexSequence.end()) + { + OFCondition result; + // Make sure every UID is only added once + OFBool isNew = OFTrue; + OFString existinguid, newuid; + (*item)->getDimensionOrganizationUID(newuid); + OFVector::iterator existing = m_DimensionOrganizationSequence.begin(); + while (existing != m_DimensionOrganizationSequence.end()) + { + (*existing)->getDimensionOrganizationUID(existinguid); + if (existinguid == newuid) + { + isNew = OFFalse; + break; + } + existing++; + } + if (isNew) + { + DimensionOrganizationItem* uidItem = new DimensionOrganizationItem(); + if (!uidItem) + { + DCMIOD_ERROR("Memory Exhausted while collecting Dimension Organziation UIDs"); + return; + } + result = uidItem->setDimensionOrganizationUID(newuid); + if (result.good()) + { + m_DimensionOrganizationSequence.push_back(uidItem); + } + else + { + DCMIOD_ERROR("Could not set Dimension Organization UID " << newuid << ": " << result.text()); + delete uidItem; + return; + } + } + item++; + } +} + + +OFCondition IODMultiframeDimensionModule::getDimensionOrganizationType(OFString& value, + const long signed int pos) const +{ + return DcmIODUtil::getStringValueFromItem(DCM_DimensionOrganizationType, *m_Item, value, pos); +} + + +OFCondition IODMultiframeDimensionModule::setDimensionOrganizationType(const OFString& value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmCodeString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_DimensionOrganizationType, value); + return result; +} + + +OFVector< IODMultiframeDimensionModule::DimensionIndexItem* >& IODMultiframeDimensionModule::getDimensionIndexSequence() +{ + return m_DimensionIndexSequence; +} + +OFVector< IODMultiframeDimensionModule::DimensionOrganizationItem* >& IODMultiframeDimensionModule::getDimensionOrganizationSequence() +{ + return m_DimensionOrganizationSequence; +} + +IODMultiframeDimensionModule::~IODMultiframeDimensionModule() +{ + DcmIODUtil::freeContainer(m_DimensionIndexSequence); + DcmIODUtil::freeContainer(m_DimensionOrganizationSequence); +} + + +IODMultiframeDimensionModule::DimensionIndexItem::DimensionIndexItem(OFshared_ptr data, + OFshared_ptr rules, + IODComponent* parent) +: IODComponent(data, rules, parent) +{ + // reset element rules + resetRules(); +} + +IODMultiframeDimensionModule::DimensionIndexItem::DimensionIndexItem(IODComponent* parent): +IODComponent(parent) +{ + // reset element rules + resetRules(); +} + + +IODMultiframeDimensionModule::DimensionIndexItem::~DimensionIndexItem() +{ + // Nothing to do +} + + +void IODMultiframeDimensionModule::DimensionIndexItem::resetRules() +{ + // Concatenation attributes + m_Rules->addRule(new IODRule(DCM_DimensionIndexPointer, "1", "1", getName(), DcmIODTypes::IE_INSTANCE), OFTrue); + m_Rules->addRule(new IODRule(DCM_DimensionIndexPrivateCreator, "1", "1C", getName(), DcmIODTypes::IE_INSTANCE), OFTrue); + m_Rules->addRule(new IODRule(DCM_FunctionalGroupPointer, "1", "1C", getName(), DcmIODTypes::IE_INSTANCE), OFTrue); + m_Rules->addRule(new IODRule(DCM_FunctionalGroupPrivateCreator, "1", "1C", getName(), DcmIODTypes::IE_INSTANCE), OFTrue); + m_Rules->addRule(new IODRule(DCM_DimensionOrganizationUID, "1", "1C", getName(), DcmIODTypes::IE_INSTANCE), OFTrue); + m_Rules->addRule(new IODRule(DCM_DimensionDescriptionLabel, "1", "1C", getName(), DcmIODTypes::IE_INSTANCE), OFTrue); +} + + +OFString IODMultiframeDimensionModule::DimensionIndexItem::getName() const +{ + return "DimensionIndexSequence"; +} + + +OFCondition IODMultiframeDimensionModule::DimensionIndexItem::getDimensionDescriptionLabel(OFString& value, + const long signed int pos) const +{ + return DcmIODUtil::getStringValueFromItem(DCM_DimensionDescriptionLabel, *m_Item, value, pos); +} + + +OFCondition IODMultiframeDimensionModule::DimensionIndexItem::getDimensionIndexPointer(DcmTagKey& value, + const long signed int pos) const +{ + OFString tagstr; + DcmIODUtil::getStringValueFromItem(DCM_DimensionIndexPointer, *m_Item, tagstr, pos); + value = DcmIODUtil::parseTagKey(tagstr); + if (value == DCM_UndefinedTagKey) + return EC_TagNotFound; + else + return EC_Normal; +} + + +OFCondition IODMultiframeDimensionModule::DimensionIndexItem::getDimensionIndexPrivateCreator(OFString& value, + const long signed int pos) const +{ + return DcmIODUtil::getStringValueFromItem(DCM_DimensionIndexPrivateCreator, *m_Item, value, pos); +} + + +OFCondition IODMultiframeDimensionModule::DimensionIndexItem::getDimensionOrganizationUID(OFString& value, + const long signed int pos) const +{ + return DcmIODUtil::getStringValueFromItem(DCM_DimensionOrganizationUID, *m_Item, value, pos); +} + + +OFCondition IODMultiframeDimensionModule::DimensionIndexItem::getFunctionalGroupPointer(DcmTagKey& value, + const long signed int pos) const +{ + OFString tagstr; + DcmIODUtil::getStringValueFromItem(DCM_FunctionalGroupPointer, *m_Item, tagstr, pos); + value = DcmIODUtil::parseTagKey(tagstr); + if (value == DCM_UndefinedTagKey) + return EC_TagNotFound; + else + return EC_Normal; +} + + +OFCondition IODMultiframeDimensionModule::DimensionIndexItem::getFunctionalGroupPrivateCreator(OFString& value, + const long signed int pos) const +{ + return DcmIODUtil::getStringValueFromItem(DCM_FunctionalGroupPrivateCreator, *m_Item, value, pos); +} + + +OFCondition IODMultiframeDimensionModule::DimensionIndexItem::setDimensionDescriptionLabel(const OFString& value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmLongString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_DimensionDescriptionLabel, value); + return result; +} + + +OFCondition IODMultiframeDimensionModule::DimensionIndexItem::setFunctionalGroupPointer(const DcmTagKey& value, + const OFBool checkValue) +{ + if (value == DCM_UndefinedTagKey) + return EC_IllegalParameter; + + DcmAttributeTag *elem = OFstatic_cast(DcmAttributeTag*, newDicomElement(DCM_FunctionalGroupPointer)); + if (elem == NULL) + return EC_InternalError; + + OFCondition result; + Uint16 *attrTagArray; + result = elem->putTagVal(value); + if (result.good()) result = elem->getUint16Array(attrTagArray); + if (result.good()) result = m_Item->putAndInsertUint16Array(DCM_FunctionalGroupPointer, attrTagArray, 1); + delete elem; + + return result; +} + + +OFCondition IODMultiframeDimensionModule::DimensionIndexItem::setFunctionalGroupPrivateCreator(const OFString& value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmLongString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_FunctionalGroupPrivateCreator, value); + return result; +} + + +OFCondition IODMultiframeDimensionModule::DimensionIndexItem::setDimensionIndexPointer(const DcmTagKey& value, + const OFBool checkValue) +{ + if (value == DCM_UndefinedTagKey) + return EC_IllegalParameter; + + DcmAttributeTag *elem = OFstatic_cast(DcmAttributeTag*, newDicomElement(DCM_DimensionIndexPointer)); + if (elem == NULL) + return EC_InternalError; + + OFCondition result; + Uint16 *attrTagArray; + result = elem->putTagVal(value); + if (result.good()) result = elem->getUint16Array(attrTagArray); + if (result.good()) result = m_Item->putAndInsertUint16Array(DCM_DimensionIndexPointer, attrTagArray, 1); + delete elem; + + return result; +} + + +OFCondition IODMultiframeDimensionModule::DimensionIndexItem::setDimensionIndexPrivateCreator(const OFString& value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmLongString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_DimensionIndexPrivateCreator, value); + return result; +} + + +OFCondition IODMultiframeDimensionModule::DimensionIndexItem::setDimensionOrganizationUID(const OFString& value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmUniqueIdentifier::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_DimensionOrganizationUID, value); + return result; +} + + + +// -- Dimension Organization Sequence Item -- + +IODMultiframeDimensionModule::DimensionOrganizationItem::DimensionOrganizationItem(OFshared_ptr data, + OFshared_ptr rules, + IODComponent* parent) +: IODComponent(data, rules, parent) +{ + // reset element rules + resetRules(); +} + +IODMultiframeDimensionModule::DimensionOrganizationItem::DimensionOrganizationItem(IODComponent* parent) +: IODComponent(parent) +{ + // reset element rules + resetRules(); +} + + +IODMultiframeDimensionModule::DimensionOrganizationItem::~DimensionOrganizationItem() +{ + // Nothing to do +} + + +void IODMultiframeDimensionModule::DimensionOrganizationItem::resetRules() +{ + // Concatenation attributes + m_Rules->addRule(new IODRule(DCM_DimensionOrganizationUID, "1", "1C", getName(), DcmIODTypes::IE_INSTANCE), OFTrue); +} + + +OFString IODMultiframeDimensionModule::DimensionOrganizationItem::getName() const +{ + return "DimensionOrganizationSequence"; +} + +OFCondition IODMultiframeDimensionModule::DimensionOrganizationItem::getDimensionOrganizationUID(OFString& value, + const long signed int pos) const +{ + return DcmIODUtil::getStringValueFromItem(DCM_DimensionOrganizationUID, *m_Item, value, pos); +} + + +OFCondition IODMultiframeDimensionModule::DimensionOrganizationItem::setDimensionOrganizationUID(const OFString& value, const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmUniqueIdentifier::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_DimensionOrganizationUID, value); + return result; +} diff --git a/dcmiod/libsrc/modmultiframefg.cc b/dcmiod/libsrc/modmultiframefg.cc new file mode 100644 index 00000000..2260f391 --- /dev/null +++ b/dcmiod/libsrc/modmultiframefg.cc @@ -0,0 +1,286 @@ +/* + * + * Copyright (C) 2015, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmiod + * + * Author: Michael Onken + * + * Purpose: Class for managing the Multi-frame Functional Groups Module + * + */ + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmiod/modmultiframefg.h" +#include "dcmtk/dcmdata/dcvrtm.h" +#include "dcmtk/dcmdata/dcvrda.h" +#include "dcmtk/dcmdata/dcvrui.h" +#include "dcmtk/dcmdata/dcvris.h" +#include "dcmtk/dcmiod/iodutil.h" // for static helpers + +const OFString IODMultiFrameFGModule::m_ModuleName = "MultiframeFunctionalGroupsModule"; + + +IODMultiFrameFGModule::IODMultiFrameFGModule(OFshared_ptr data, + OFshared_ptr rules) +: IODModule(data, rules), + m_ConcatenationInfo(data, rules) +{ + // reset element rules + resetRules(); +} + + +OFString IODMultiFrameFGModule::getName() const +{ + return m_ModuleName; +} + + +IODMultiFrameFGModule::IODMultiFrameFGModule() +: IODModule() +{ + resetRules(); +} + + +void IODMultiFrameFGModule::resetRules() +{ + m_Rules->addRule(new IODRule(DCM_InstanceNumber, "1", "1", m_ModuleName, DcmIODTypes::IE_INSTANCE), OFTrue); + m_Rules->addRule(new IODRule(DCM_ContentDate, "1", "1", m_ModuleName, DcmIODTypes::IE_INSTANCE), OFTrue); + m_Rules->addRule(new IODRule(DCM_ContentTime, "1", "1", m_ModuleName, DcmIODTypes::IE_INSTANCE), OFTrue); + m_Rules->addRule(new IODRule(DCM_NumberOfFrames, "1", "1", m_ModuleName, DcmIODTypes::IE_INSTANCE), OFTrue); + m_Rules->addRule(new IODRule(DCM_RepresentativeFrameNumber, "1", "3", m_ModuleName, DcmIODTypes::IE_INSTANCE), OFTrue); + m_ConcatenationInfo.resetRules(); +} + + +IODMultiFrameFGModule::~IODMultiFrameFGModule() +{ +} + + +IODMultiFrameFGModule::ConcatenationInfo& IODMultiFrameFGModule::getConcatenationInfo() +{ + return m_ConcatenationInfo; +} + + +OFCondition IODMultiFrameFGModule::getInstanceNumber(Sint32& value, + const unsigned int pos) +{ + return m_Item->findAndGetSint32(DCM_InstanceNumber, value, pos); +} + + +OFCondition IODMultiFrameFGModule::getContentDate(OFString& value, + const long signed int pos) +{ + return DcmIODUtil::getStringValueFromItem(DCM_ContentDate, *m_Item, value, pos); +} + + +OFCondition IODMultiFrameFGModule::getContentTime(OFString& value, + const long signed int pos) +{ + return DcmIODUtil::getStringValueFromItem(DCM_ContentTime, *m_Item, value, pos); +} + + +OFCondition IODMultiFrameFGModule::getNumberOfFrames(Sint32& value, + const unsigned int pos) +{ + return m_Item->findAndGetSint32(DCM_NumberOfFrames, value, pos); +} + + +OFCondition IODMultiFrameFGModule::getRepresentativeFrameNumber(Uint16& value, + const unsigned int pos) +{ + return m_Item->findAndGetUint16(DCM_RepresentativeFrameNumber, value, pos); +} + + +// -- setters -- + + +OFCondition IODMultiFrameFGModule::setConcatenationInfo(const IODMultiFrameFGModule::ConcatenationInfo& concatenationInfo) +{ + // TODO: Checks? + m_ConcatenationInfo = concatenationInfo; + return EC_Normal; +} + + +OFCondition IODMultiFrameFGModule::setInstanceNumber(const OFString& value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmIntegerString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_InstanceNumber, value); + return result; +} + + + +OFCondition IODMultiFrameFGModule::setContentDate(const OFString& value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmDate::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_ContentDate, value); + return result; +} + + +OFCondition IODMultiFrameFGModule::setContentTime(const OFString& value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmTime::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = result = m_Item->putAndInsertOFStringArray(DCM_ContentTime, value); + return result; +} + + +OFCondition IODMultiFrameFGModule::setNumberOfFrames(const Uint16 value) +{ + OFCondition result; + OFStringStream oss; + oss << value; + OFSTRINGSTREAM_GETSTR(oss,tempstr); + result = m_Item->putAndInsertOFStringArray(DCM_NumberOfFrames, tempstr); + OFSTRINGSTREAM_FREESTR(tmpstr); + return result; +} + + +OFCondition IODMultiFrameFGModule::setRepresentativeFrameNumber(const Uint16 value) +{ + return m_Item->putAndInsertUint16(DCM_RepresentativeFrameNumber, value); +} + + +IODMultiFrameFGModule::ConcatenationInfo::ConcatenationInfo(OFshared_ptr data, + OFshared_ptr rules) +: IODComponent(data, rules) +{ + + // reset element rules + resetRules(); +} + + +IODMultiFrameFGModule::ConcatenationInfo::ConcatenationInfo(IODComponent* parent) +: IODComponent(parent) +{ + // reset element rules + resetRules(); +} + + +IODMultiFrameFGModule::ConcatenationInfo::~ConcatenationInfo() +{ + // Nothing to do +} + + +OFString IODMultiFrameFGModule::ConcatenationInfo::getName() const +{ + return m_ModuleName; +} + + +void IODMultiFrameFGModule::ConcatenationInfo::resetRules() +{ + // Concatenation attributes + m_Rules->addRule(new IODRule(DCM_ConcatenationFrameOffsetNumber, "1", "1C", m_ModuleName, DcmIODTypes::IE_INSTANCE), OFTrue); + m_Rules->addRule(new IODRule(DCM_ConcatenationUID, "1", "1C", m_ModuleName, DcmIODTypes::IE_INSTANCE), OFTrue); + m_Rules->addRule(new IODRule(DCM_SOPInstanceUIDOfConcatenationSource, "1", "1C", m_ModuleName, DcmIODTypes::IE_INSTANCE), OFTrue); + m_Rules->addRule(new IODRule(DCM_InConcatenationNumber, "1", "1C", m_ModuleName, DcmIODTypes::IE_INSTANCE), OFTrue); + m_Rules->addRule(new IODRule(DCM_InConcatenationTotalNumber, "1", "3", m_ModuleName, DcmIODTypes::IE_INSTANCE), OFTrue); +} + + +OFCondition IODMultiFrameFGModule::ConcatenationInfo::getConcatenationFrameOffsetNumber(Uint32& value, + const unsigned int pos) +{ + return m_Item->findAndGetUint32(DCM_ConcatenationFrameOffsetNumber, value, pos); +} + + +OFCondition IODMultiFrameFGModule::ConcatenationInfo::getConcatenationUID(OFString& value, + const signed long pos) +{ + return DcmIODUtil::getStringValueFromItem(DCM_ConcatenationUID, *m_Item, value, pos); +} + + +OFCondition IODMultiFrameFGModule::ConcatenationInfo::getSOPInstanceUIDOfConcatenationSource(OFString& value, + const signed long pos) +{ + return DcmIODUtil::getStringValueFromItem(DCM_SOPInstanceUIDOfConcatenationSource, *m_Item, value, pos); +} + + +OFCondition IODMultiFrameFGModule::ConcatenationInfo::getInConcatenationNumber(Uint16& value, + const unsigned int pos) +{ + return m_Item->findAndGetUint16(DCM_InConcatenationNumber, value, pos); +} + + +OFCondition IODMultiFrameFGModule::ConcatenationInfo::getInConcatenationTotalNumber(Uint16& value, + const unsigned int pos) +{ + return m_Item->findAndGetUint16(DCM_InConcatenationTotalNumber, value, pos); +} + + +OFCondition IODMultiFrameFGModule::ConcatenationInfo::setConcatenationFrameOffsetNumber(const Uint32 value) +{ + return m_Item->putAndInsertUint32(DCM_ConcatenationFrameOffsetNumber, value); +} + + +OFCondition IODMultiFrameFGModule::ConcatenationInfo::setConcatenationUID(const OFString& value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmUniqueIdentifier::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_ConcatenationUID, value); + return result; + +} + + +OFCondition IODMultiFrameFGModule::ConcatenationInfo::setSOPInstanceUIDOfConcatenationSource(const OFString& value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmUniqueIdentifier::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_SOPInstanceUIDOfConcatenationSource, value); + return result; + +} + + +OFCondition IODMultiFrameFGModule::ConcatenationInfo::setInConcatenationNumber(const Uint16 value) +{ + return m_Item->putAndInsertUint16(DCM_InConcatenationNumber, value); +} + + +OFCondition IODMultiFrameFGModule::ConcatenationInfo::setInConcatenationTotalNumber(const Uint16 value) +{ + return m_Item->putAndInsertUint16(DCM_InConcatenationTotalNumber, value); +} diff --git a/dcmiod/libsrc/modpatient.cc b/dcmiod/libsrc/modpatient.cc new file mode 100644 index 00000000..5b040e6e --- /dev/null +++ b/dcmiod/libsrc/modpatient.cc @@ -0,0 +1,136 @@ +/* + * + * Copyright (C) 2015, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmiod + * + * Author: Michael Onken + * + * Purpose: Class for managing the Patient Module + * + */ + + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ +#include "dcmtk/dcmiod/modpatient.h" +#include "dcmtk/dcmiod/iodutil.h" + +const OFString IODPatientModule::m_ModuleName = "PatientModule"; + + +IODPatientModule::IODPatientModule(OFshared_ptr item, + OFshared_ptr rules) +: IODModule(item, rules) +{ + // reset element rules + resetRules(); +} + + +OFString IODPatientModule::getName() const +{ + return m_ModuleName; +} + + +IODPatientModule::IODPatientModule() +: IODModule() +{ + resetRules(); +} + + +void IODPatientModule::resetRules() +{ + // parameters are tag, VM, type. Overwrite old rules if any. + m_Rules->addRule(new IODRule(DCM_PatientName, "1","2",m_ModuleName, DcmIODTypes::IE_PATIENT), OFTrue); + m_Rules->addRule(new IODRule(DCM_PatientID, "1","2", m_ModuleName, DcmIODTypes::IE_PATIENT), OFTrue); + m_Rules->addRule(new IODRule(DCM_PatientBirthDate, "1","2", m_ModuleName, DcmIODTypes::IE_PATIENT), OFTrue); + m_Rules->addRule(new IODRule(DCM_PatientSex, "1","2", m_ModuleName, DcmIODTypes::IE_PATIENT), OFTrue); +} + + +IODPatientModule::~IODPatientModule() +{ +} + + +// --- get attributes (C++ string) --- + + +OFCondition IODPatientModule::getPatientName(OFString &value, + const signed long pos) const +{ + return DcmIODUtil::getStringValueFromItem(DCM_PatientName, *m_Item, value, pos); +} + + +OFCondition IODPatientModule::getPatientBirthDate(OFString &value, + const signed long pos) const +{ + return DcmIODUtil::getStringValueFromItem(DCM_PatientBirthDate, *m_Item, value, pos); +} + + +OFCondition IODPatientModule::getPatientSex(OFString &value, + const signed long pos) const +{ + return DcmIODUtil::getStringValueFromItem(DCM_PatientSex, *m_Item, value, pos); +} + +OFCondition IODPatientModule::getPatientID(OFString &value, + const signed long pos) const +{ + return DcmIODUtil::getStringValueFromItem(DCM_PatientID, *m_Item, value, pos); +} + +// --- set attributes --- + +OFCondition IODPatientModule::setPatientName(const OFString &value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmPersonName::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_PatientName, value); + return result; +} + + +OFCondition IODPatientModule::setPatientID(const OFString &value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmLongString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_PatientID, value); + return result; +} + + +OFCondition IODPatientModule::setPatientBirthDate(const OFString &value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmDate::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_PatientBirthDate, value); + return result; +} + + +OFCondition IODPatientModule::setPatientSex(const OFString &value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmCodeString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_PatientSex, value); + return result; +} + diff --git a/dcmiod/libsrc/modpatientstudy.cc b/dcmiod/libsrc/modpatientstudy.cc new file mode 100644 index 00000000..210e1ce7 --- /dev/null +++ b/dcmiod/libsrc/modpatientstudy.cc @@ -0,0 +1,134 @@ +/* + * + * Copyright (C) 2015, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmiod + * + * Author: Michael Onken + * + * Purpose: Class for managing the Patient Study Module + * + */ + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ +#include "dcmtk/dcmiod/modpatientstudy.h" +#include "dcmtk/dcmiod/iodutil.h" + +const OFString IODPatientStudyModule::m_ModuleName = "PatientStudyModule"; + + +IODPatientStudyModule::IODPatientStudyModule(OFshared_ptr item, + OFshared_ptr rules) +: IODModule(item, rules) +{ + resetRules(); +} + + +OFString IODPatientStudyModule::getName() const +{ + return m_ModuleName; +} + + +IODPatientStudyModule::IODPatientStudyModule() +: IODModule() +{ + resetRules(); +} + + +void IODPatientStudyModule::resetRules() +{ + // parameters are tag, VM, type. Overwrite old rules if any. + m_Rules->addRule(new IODRule(DCM_AdmittingDiagnosesDescription, "1-n","3",m_ModuleName, DcmIODTypes::IE_STUDY), OFTrue); + m_Rules->addRule(new IODRule(DCM_PatientAge, "1","3", m_ModuleName, DcmIODTypes::IE_STUDY), OFTrue); + m_Rules->addRule(new IODRule(DCM_PatientSize, "1","3", m_ModuleName, DcmIODTypes::IE_STUDY), OFTrue); + m_Rules->addRule(new IODRule(DCM_PatientWeight, "1","3", m_ModuleName, DcmIODTypes::IE_STUDY), OFTrue); +} + + +IODPatientStudyModule::~IODPatientStudyModule() +{ +} + + +// --- get attributes (C++ string) --- + +OFCondition IODPatientStudyModule::getAdmittingDiagnosesDescription(OFString& value, + const signed long pos) const +{ + return DcmIODUtil::getStringValueFromItem(DCM_AdmittingDiagnosesDescription, *m_Item, value, pos); +} + + +OFCondition IODPatientStudyModule::getPatientAge(OFString& value, + const signed long pos) const +{ + return DcmIODUtil::getStringValueFromItem(DCM_PatientAge, *m_Item, value, pos); +} + + +OFCondition IODPatientStudyModule::getPatientWeight(Float64& value, + const unsigned long pos) const +{ + return DcmIODUtil::getFloat64ValueFromItem(DCM_PatientWeight, *m_Item, value, pos); +} + + +OFCondition IODPatientStudyModule::getPatientSize(Float64& value, + const unsigned long pos) const +{ + return DcmIODUtil::getFloat64ValueFromItem(DCM_PatientSize, *m_Item, value, pos); +} + + +// --- set attributes --- + + +OFCondition IODPatientStudyModule::setAdmittingDiagnosesDescription(const OFString& value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmLongString::checkStringValue(value, "1-n") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_AdmittingDiagnosesDescription, value); + return result; +} + +OFCondition IODPatientStudyModule::setPatientAge(const OFString& value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmAgeString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_PatientAge, value); + return result; +} + + +OFCondition IODPatientStudyModule::setPatientSize(const OFString& value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmDecimalString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_PatientSize, value); + return result; +} + + +OFCondition IODPatientStudyModule::setPatientWeight(const OFString& value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmDecimalString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_PatientWeight, value); + return result; +} diff --git a/dcmiod/libsrc/modsegmentationseries.cc b/dcmiod/libsrc/modsegmentationseries.cc new file mode 100644 index 00000000..ff31d0e3 --- /dev/null +++ b/dcmiod/libsrc/modsegmentationseries.cc @@ -0,0 +1,147 @@ +/* + * + * Copyright (C) 2015, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmiod + * + * Author: Michael Onken + * + * Purpose: Class for managing the Segmentation Series Module + * + */ + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ +#include "dcmtk/dcmiod/modsegmentationseries.h" +#include "dcmtk/dcmiod/iodutil.h" + +const OFString IODSegmentationSeriesModule::m_ModuleName = "SegmentationSeriesModule"; + + +IODSegmentationSeriesModule::IODSegmentationSeriesModule(OFshared_ptr item, + OFshared_ptr rules) +: IODModule(item, rules) +{ + // reset element rules + resetRules(); +} + + +IODSegmentationSeriesModule::IODSegmentationSeriesModule() +: IODModule() +{ + resetRules(); +} + + +IODSegmentationSeriesModule::~IODSegmentationSeriesModule() +{ +} + + +OFString IODSegmentationSeriesModule::getName() const +{ + return m_ModuleName; +} + + +void IODSegmentationSeriesModule::resetRules() +{ + // parameters are tag, VM, type. Overwrite old rules if any. + m_Rules->addRule(new IODRule(DCM_Modality, "1","1", m_ModuleName, DcmIODTypes::IE_SERIES, "SEG"), OFTrue); + m_Rules->addRule(new IODRule(DCM_SeriesNumber, "1","1", m_ModuleName, DcmIODTypes::IE_SERIES, "1"), OFTrue); + m_Rules->addRule(new IODRule(DCM_ReferencedSOPClassUID, "1","1C", m_ModuleName, DcmIODTypes::IE_SERIES), OFTrue); + m_Rules->addRule(new IODRule(DCM_ReferencedSOPInstanceUID, "1","1C", m_ModuleName, DcmIODTypes::IE_SERIES), OFTrue); +} + + +OFCondition IODSegmentationSeriesModule::getModality(OFString &value, + const signed long pos) const +{ + return DcmIODUtil::getStringValueFromItem(DCM_Modality, *m_Item, value, pos); +} + + +OFCondition IODSegmentationSeriesModule::getSeriesNumber(OFString &value, + const signed long pos) const +{ + return DcmIODUtil::getStringValueFromItem(DCM_SeriesNumber, *m_Item, value, pos); +} + + +OFCondition IODSegmentationSeriesModule::getPPSSOPClassUID(OFString &value, + const signed long pos) const +{ + DcmItem *localItem = NULL; + OFCondition result = m_Item->findAndGetSequenceItem(DCM_ReferencedPerformedProcedureStepSequence, localItem, 0); + if (result.good()) + { + result = DcmIODUtil::getStringValueFromItem(DCM_ReferencedSOPClassUID, *localItem, value, pos); + } + return result; +} + + +OFCondition IODSegmentationSeriesModule::getPPSSOPInstanceUID(OFString &value, + const signed long pos) const +{ + DcmItem *localItem = NULL; + OFCondition result = m_Item->findAndGetSequenceItem(DCM_ReferencedPerformedProcedureStepSequence, localItem, 0); + if (result.good()) + { + result = DcmIODUtil::getStringValueFromItem(DCM_ReferencedSOPInstanceUID, *localItem, value, pos); + } + return result; +} + + +OFCondition IODSegmentationSeriesModule::setSeriesNumber(const OFString &value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmIntegerString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_SeriesNumber, value); + return result; +} + + +OFCondition IODSegmentationSeriesModule::setPPSSOPClassUID(const OFString& value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmUniqueIdentifier::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + { + DcmItem *localItem = NULL; + result = m_Item->findOrCreateSequenceItem(DCM_ReferencedPerformedProcedureStepSequence, localItem, 0); + if (result.good()) + { + result = m_Item->putAndInsertOFStringArray(DCM_ReferencedSOPClassUID, value); + } + } + return result; +} + + +OFCondition IODSegmentationSeriesModule::setPPSSOPInstanceUID(const OFString& value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmUniqueIdentifier::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + { + DcmItem *localItem = NULL; + result = m_Item->findOrCreateSequenceItem(DCM_ReferencedPerformedProcedureStepSequence, localItem, 0); + if (result.good()) + { + result = m_Item->putAndInsertOFStringArray(DCM_ReferencedSOPInstanceUID, value); + } + } + return result; +} diff --git a/dcmiod/libsrc/modsopcommon.cc b/dcmiod/libsrc/modsopcommon.cc new file mode 100644 index 00000000..fcfb705b --- /dev/null +++ b/dcmiod/libsrc/modsopcommon.cc @@ -0,0 +1,246 @@ +/* + * + * Copyright (C) 2015, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmiod + * + * Author: Michael Onken + * + * Purpose: Class for managing the SOP Common Module + * + */ + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ +#include "dcmtk/dcmiod/modsopcommon.h" +#include "dcmtk/dcmdata/dcuid.h" +#include "dcmtk/dcmdata/dcdeftag.h" +#include "dcmtk/dcmdata/dcvrcs.h" +#include "dcmtk/dcmdata/dcvrui.h" +#include "dcmtk/dcmdata/dcvrda.h" +#include "dcmtk/dcmdata/dcvrtm.h" +#include "dcmtk/dcmdata/dcvrsh.h" +#include "dcmtk/dcmiod/iodutil.h" + +const OFString IODSOPCommonModule::m_ModuleName = "SOPCommonModule"; + + +IODSOPCommonModule::IODSOPCommonModule(OFshared_ptr item, + OFshared_ptr rules) +: IODModule(item, rules) +{ + // reset element rules + resetRules(); +} + + +IODSOPCommonModule::IODSOPCommonModule() +: IODModule() +{ + resetRules(); +} + + +void IODSOPCommonModule::resetRules() +{ + // parameters are tag, VM, type. Overwrite old rules if any. + m_Rules->addRule(new IODRule(DCM_SOPClassUID, "1","1", m_ModuleName, DcmIODTypes::IE_INSTANCE), OFTrue); + m_Rules->addRule(new IODRule(DCM_SOPInstanceUID, "1","1", m_ModuleName, DcmIODTypes::IE_INSTANCE), OFTrue); + m_Rules->addRule(new IODRule(DCM_SpecificCharacterSet, "1-n","1C", m_ModuleName, DcmIODTypes::IE_INSTANCE), OFTrue); + m_Rules->addRule(new IODRule(DCM_InstanceCreationDate, "1","3", m_ModuleName, DcmIODTypes::IE_INSTANCE), OFTrue); + m_Rules->addRule(new IODRule(DCM_InstanceCreationTime, "1","3", m_ModuleName, DcmIODTypes::IE_INSTANCE), OFTrue); + m_Rules->addRule(new IODRule(DCM_InstanceCreatorUID, "1","3", m_ModuleName, DcmIODTypes::IE_INSTANCE), OFTrue); + m_Rules->addRule(new IODRule(DCM_TimezoneOffsetFromUTC, "1","3", m_ModuleName, DcmIODTypes::IE_INSTANCE), OFTrue); + +} + + +OFString IODSOPCommonModule::getName() const +{ + return m_ModuleName; +} + + + +void IODSOPCommonModule::inventMissing() +{ + // SOP Instance UID + ensureInstanceUID(); + + // All other attributes + IODComponent::inventMissing(); +} + + +IODSOPCommonModule::~IODSOPCommonModule() +{ +} + + +void IODSOPCommonModule::ensureInstanceUID(const OFBool correctInvalid) +{ + OFString uidstr; + + /* create new sop instance UID if required */ + if (getSOPInstanceUID(uidstr).bad() || uidstr.empty() ) + { + setSOPInstanceUID(DcmIODUtil::createUID(0 /* Instance Level */)); + } + else if (!uidstr.empty() && correctInvalid) + { + if (DcmUniqueIdentifier::checkStringValue(uidstr, "1").bad()) + { + setSOPInstanceUID(DcmIODUtil::createUID(0 /* Instance Level */)); } + } +} + + + +OFCondition IODSOPCommonModule::getSpecificCharacterSet(OFString &value, + const signed long pos) const +{ + return DcmIODUtil::getStringValueFromItem(DCM_SpecificCharacterSet, *m_Item, value, pos); +} + + +OFCondition IODSOPCommonModule::getSOPInstanceUID(OFString &value, + const signed long pos) const +{ + return DcmIODUtil::getStringValueFromItem(DCM_SOPInstanceUID, *m_Item, value, pos); +} + + +OFCondition IODSOPCommonModule::getSOPClassUID(OFString &value, + const signed long pos) const +{ + return DcmIODUtil::getStringValueFromItem(DCM_SOPClassUID, *m_Item, value, pos); +} + + +OFCondition IODSOPCommonModule::getInstanceCreationDate(OFString &value, + const signed long pos) const +{ + return DcmIODUtil::getStringValueFromItem(DCM_InstanceCreationDate, *m_Item, value, pos); +} + + +OFCondition IODSOPCommonModule::getInstanceCreationTime(OFString &value, + const signed long pos) const +{ + return DcmIODUtil::getStringValueFromItem(DCM_InstanceCreationTime, *m_Item, value, pos); +} + + +OFCondition IODSOPCommonModule::getInstanceCreatorUID(OFString &value, + const signed long pos) const +{ + return DcmIODUtil::getStringValueFromItem(DCM_InstanceCreatorUID, *m_Item, value, pos); +} + + +OFCondition IODSOPCommonModule::getTimezoneOffsetFromUTC(OFString& value, + const signed long pos) const +{ + return DcmIODUtil::getStringValueFromItem(DCM_TimezoneOffsetFromUTC, *m_Item, value, pos); +} + + + +OFCondition IODSOPCommonModule::setSpecificCharacterSet(const OFString &value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmCodeString::checkStringValue(value, "1-n") : EC_Normal; + if (result.good()) + { + result = m_Item->putAndInsertOFStringArray(DCM_SpecificCharacterSet, value); + } + return result; +} + + +OFCondition IODSOPCommonModule::setSOPClassUID(const OFString &value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmUniqueIdentifier::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + { + result = m_Item->putAndInsertOFStringArray(DCM_SOPClassUID, value); + } + return result; +} + + +OFCondition IODSOPCommonModule::setSOPInstanceUID(const OFString &value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmUniqueIdentifier::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + { + result = m_Item->putAndInsertOFStringArray(DCM_SOPInstanceUID, value); + } + return result; +} + + +OFCondition IODSOPCommonModule::setInstanceCreationDate(const OFString &value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmDate::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + { + result = m_Item->putAndInsertOFStringArray(DCM_InstanceCreationDate, value); + } + return result; +} + + +OFCondition IODSOPCommonModule::setInstanceCreationTime(const OFString &value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmTime::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + { + result = m_Item->putAndInsertOFStringArray(DCM_InstanceCreationTime, value); + } + return result; +} + + +OFCondition IODSOPCommonModule::setInstanceCreatorUID(const OFString &value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmUniqueIdentifier::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + { + result = m_Item->putAndInsertOFStringArray(DCM_InstanceCreatorUID, value); + } + return result; +} + + +OFCondition IODSOPCommonModule::setTimeZoneOffsetFromUTC(const OFString& value, + const OFBool checkValue) const +{ + OFCondition result; + if (checkValue) + { + result = DcmShortString::checkStringValue(value, "1"); + if (result.good()) + { + if (value.length() != 5) result = IOD_EC_InvalidElementValue; + } + } + if (result.good()) + { + result = m_Item->putAndInsertOFStringArray(DCM_TimezoneOffsetFromUTC, value); + } + return result; +} diff --git a/dcmiod/libsrc/modsynchronization.cc b/dcmiod/libsrc/modsynchronization.cc new file mode 100644 index 00000000..60a5ab94 --- /dev/null +++ b/dcmiod/libsrc/modsynchronization.cc @@ -0,0 +1,224 @@ +/* + * + * Copyright (C) 2015, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmiod + * + * Author: Michael Onken + * + * Purpose: Class for managing the Synchronization Module + * + */ + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ +#include "dcmtk/dcmiod/modsynchronisation.h" +#include "dcmtk/ofstd/ofstream.h" +#include "dcmtk/dcmdata/dcvrui.h" +#include "dcmtk/dcmdata/dcvrcs.h" +#include "dcmtk/dcmdata/dcvrlo.h" +#include "dcmtk/dcmdata/dcvrsh.h" +#include "dcmtk/dcmdata/dcdeftag.h" +#include "dcmtk/dcmiod/iodutil.h" + + +const OFString IODSynchronizationModule::m_ModuleName = "SynchronizationModul"; + + +IODSynchronizationModule::IODSynchronizationModule(OFshared_ptr item, + OFshared_ptr rules) +: IODModule(item, rules) +{ + // reset element rules + resetRules(); +} + + +IODSynchronizationModule::IODSynchronizationModule() +: IODModule() +{ + resetRules(); +} + + +void IODSynchronizationModule::resetRules() +{ + // parameters are tag, VM, type. Overwrite old rules if any. + m_Rules->addRule(new IODRule(DCM_SynchronizationFrameOfReferenceUID, "1","1", m_ModuleName, DcmIODTypes::IE_FOR), OFTrue); + m_Rules->addRule(new IODRule(DCM_SynchronizationTrigger, "1","1", m_ModuleName, DcmIODTypes::IE_FOR), OFTrue); + m_Rules->addRule(new IODRule(DCM_TriggerSourceOrType, "1","3", m_ModuleName, DcmIODTypes::IE_FOR), OFTrue); + m_Rules->addRule(new IODRule(DCM_SynchronizationChannel, "2","1C", m_ModuleName, DcmIODTypes::IE_FOR), OFTrue); + m_Rules->addRule(new IODRule(DCM_AcquisitionTimeSynchronized, "1","1", m_ModuleName, DcmIODTypes::IE_FOR), OFTrue); + m_Rules->addRule(new IODRule(DCM_TimeSource, "1","3", m_ModuleName, DcmIODTypes::IE_FOR), OFTrue); + m_Rules->addRule(new IODRule(DCM_TimeDistributionProtocol, "1","3", m_ModuleName, DcmIODTypes::IE_FOR), OFTrue); + m_Rules->addRule(new IODRule(DCM_NTPSourceAddress, "1","3", m_ModuleName, DcmIODTypes::IE_FOR), OFTrue); +} + + + +OFString IODSynchronizationModule::getName() const +{ + return m_ModuleName; +} + + +IODSynchronizationModule::~IODSynchronizationModule() +{ + // clear rules from rule set + clearData(); +} + + +OFCondition IODSynchronizationModule::getSynchronizationFrameOfReferenceUID(OFString& value, + const signed long pos) const +{ + return DcmIODUtil::getStringValueFromItem(DCM_SynchronizationFrameOfReferenceUID, *m_Item, value, pos); +} + + + +OFCondition IODSynchronizationModule::getSynchronizationTrigger(OFString& value, + const signed long pos) const +{ + return DcmIODUtil::getStringValueFromItem(DCM_SynchronizationTrigger, *m_Item, value, pos); +} + + +OFCondition IODSynchronizationModule::getTriggerSourceOrType(OFString& value, + const signed long pos) const +{ + return DcmIODUtil::getStringValueFromItem(DCM_TriggerSourceOrType, *m_Item, value, pos); +} + + +OFCondition IODSynchronizationModule::getSynchronizationChannel(OFVector& value) const +{ + DcmElement *elem = NULL; + OFCondition result = m_Item->findAndGetElement(DCM_SynchronizationChannel, elem); + if (elem) + { + result = DcmIODUtil::getUint16ValuesFromElement(*elem, value); + } + return result; +} + + +OFCondition IODSynchronizationModule::getAcquisitionTimeSynchronized(OFString& value, + const signed long pos) const +{ + return DcmIODUtil::getStringValueFromItem(DCM_AcquisitionTimeSynchronized, *m_Item, value, pos); +} + + +OFCondition IODSynchronizationModule::getTimeSource(OFString& value, + const signed long pos) const +{ + return DcmIODUtil::getStringValueFromItem(DCM_TimeSource, *m_Item, value, pos); +} + + +OFCondition IODSynchronizationModule::getTimeDistributionProtocol(OFString& value, + const signed long pos) const +{ + return DcmIODUtil::getStringValueFromItem(DCM_TimeDistributionProtocol, *m_Item, value, pos); +} + + +OFCondition IODSynchronizationModule::getNTPSourceAddress(OFString& value, + const signed long pos) const +{ + return DcmIODUtil::getStringValueFromItem(DCM_NTPSourceAddress, *m_Item, value, pos); +} + + +OFCondition IODSynchronizationModule::setSynchronizationFrameofReferenceUID(const OFString &value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmUniqueIdentifier::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_SynchronizationFrameOfReferenceUID, value); + return result; +} + + +OFCondition IODSynchronizationModule::setSynchronizationTrigger(const OFString &value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmCodeString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_SynchronizationTrigger, value); + // TODO: Further checks since this field has enumerated values + return result; +} + + +OFCondition IODSynchronizationModule::setTriggerSourceOrType(const OFString &value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmLongString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_TriggerSourceOrType, value); + return result; +} + + +OFCondition IODSynchronizationModule::setSynchronizationChannel(const OFPair &value, + const OFBool checkValue) +{ + OFCondition result = m_Item->putAndInsertUint16(DCM_SynchronizationChannel, value.first, 0); + if (result.good()) + { + result = m_Item->putAndInsertUint16(DCM_SynchronizationChannel, value.second, 0); + } + return result; +} + + +OFCondition IODSynchronizationModule::setAcquisitionTimeSynchronized(const OFString &value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmCodeString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_AcquisitionTimeSynchronized, value); + // TODO: Further checks since this field has enumerated values + return result; +} + + +OFCondition IODSynchronizationModule::setTimeSource(const OFString &value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmShortString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_TimeSource, value); + return result; +} + + +OFCondition IODSynchronizationModule::setTimeDistributionProtocol(const OFString &value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmCodeString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_TimeDistributionProtocol, value); + // TODO: Further checks since this field has enumerated values + return result; +} + + +OFCondition IODSynchronizationModule::setNTPSourceAddress(const OFString &value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmLongString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_NTPSourceAddress, value); + return result; +} diff --git a/dcmiod/libsrc/modusfor.cc b/dcmiod/libsrc/modusfor.cc new file mode 100644 index 00000000..41d9d278 --- /dev/null +++ b/dcmiod/libsrc/modusfor.cc @@ -0,0 +1,275 @@ +/* + * + * Copyright (C) 2015, Open Connections GmbH + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation are maintained by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmiod + * + * Author: Michael Onken + * + * Purpose: Class for managing the Ultrasound Frame of Reference Module + * + */ + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ +#include "dcmtk/dcmiod/modusfor.h" +#include "dcmtk/ofstd/ofstream.h" +#include "dcmtk/dcmdata/dcvrui.h" +#include "dcmtk/dcmdata/dcvrcs.h" +#include "dcmtk/dcmdata/dcvrfd.h" +#include "dcmtk/dcmdata/dcdeftag.h" +#include "dcmtk/dcmiod/iodutil.h" + + +const OFString IODUSFoRModule::m_ModuleName = "UltrasoundFrameOfReferenceModule"; + + +IODUSFoRModule::IODUSFoRModule(OFshared_ptr item, + OFshared_ptr rules) +: IODModule(item, rules) +{ + // reset element rules + resetRules(); +} + + +IODUSFoRModule::IODUSFoRModule() +: IODModule() +{ + resetRules(); +} + + +void IODUSFoRModule::resetRules() +{ + // parameters are tag, VM, type. Overwrite old rules if any. + m_Rules->addRule(new IODRule(DCM_VolumeFrameOfReferenceUID, "1","1", m_ModuleName, DcmIODTypes::IE_FOR), OFTrue); + m_Rules->addRule(new IODRule(DCM_UltrasoundAcquisitionGeometry, "1","1", m_ModuleName, DcmIODTypes::IE_FOR), OFTrue); + m_Rules->addRule(new IODRule(DCM_ApexPosition, "3","1C", m_ModuleName, DcmIODTypes::IE_FOR), OFTrue); + m_Rules->addRule(new IODRule(DCM_VolumeToTransducerRelationship, "1","1C", m_ModuleName, DcmIODTypes::IE_FOR), OFTrue); + m_Rules->addRule(new IODRule(DCM_VolumeToTransducerMappingMatrix, "16","1", m_ModuleName, DcmIODTypes::IE_FOR), OFTrue); + m_Rules->addRule(new IODRule(DCM_PatientFrameOfReferenceSource, "1","1C", m_ModuleName, DcmIODTypes::IE_FOR), OFTrue); + m_Rules->addRule(new IODRule(DCM_TableFrameOfReferenceUID, "1","1C", m_ModuleName, DcmIODTypes::IE_FOR), OFTrue); + m_Rules->addRule(new IODRule(DCM_VolumeToTableMappingMatrix, "16","1C", m_ModuleName, DcmIODTypes::IE_FOR), OFTrue); +} + + +OFString IODUSFoRModule::getName() const +{ + return m_ModuleName; +} + + +IODUSFoRModule::~IODUSFoRModule() +{ + // clear rules from rule set + clearData(); +} + + +OFCondition IODUSFoRModule::getVolumeFrameOfReferenceUID(OFString& value, + const long signed int pos) const +{ + return DcmIODUtil::getStringValueFromItem(DCM_VolumeFrameOfReferenceUID, *m_Item, value, pos); +} + + +OFCondition IODUSFoRModule::getUltrasoundAcquisitionGeometry(OFString& value, + const long signed int pos) const +{ + return DcmIODUtil::getStringValueFromItem(DCM_UltrasoundAcquisitionGeometry, *m_Item, value, pos); +} + + +OFCondition IODUSFoRModule::getApexPosition(OFVector& value) +{ + return DcmIODUtil::getFloat64ValuesFromItem(DCM_ApexPosition, *m_Item, value); +} + + +OFCondition IODUSFoRModule::getApexPosition(Float64& value, + const long unsigned int pos) const +{ + return DcmIODUtil::getFloat64ValueFromItem(DCM_ApexPosition, *m_Item, value, pos); +} + + +OFCondition IODUSFoRModule::getVolumetoTransducerRelationship(OFString& value, + const long signed int pos) +{ + return DcmIODUtil::getStringValueFromItem(DCM_UltrasoundAcquisitionGeometry, *m_Item, value, pos); +} + + +OFCondition IODUSFoRModule::getVolumetoTransducerMappingMatrix(Float64& value, + const signed long pos) const +{ + return DcmIODUtil::getFloat64ValueFromItem(DCM_VolumeToTransducerMappingMatrix, *m_Item, value, pos); +} + + +OFCondition IODUSFoRModule::getVolumetoTransducerMappingMatrix(OFVector< Float64 >& value) +{ + return DcmIODUtil::getFloat64ValuesFromItem(DCM_VolumeToTransducerMappingMatrix, *m_Item, value); +} + + +OFCondition IODUSFoRModule::getPatientFrameofReferenceSource(OFString& value, + const long signed int pos) +{ + return DcmIODUtil::getStringValueFromItem(DCM_PatientFrameOfReferenceSource, *m_Item, value, pos); +} + + +OFCondition IODUSFoRModule::getTableFrameofReferenceUID(OFString& value, + const long signed int pos) +{ + return DcmIODUtil::getStringValueFromItem(DCM_TableFrameOfReferenceUID, *m_Item, value, pos); +} + + +OFCondition IODUSFoRModule::getVolumetoTableMappingMatrix(Float64& value, + const long signed int pos) const +{ + return DcmIODUtil::getFloat64ValueFromItem(DCM_VolumeToTableMappingMatrix, *m_Item, value, pos); +} + + +OFCondition IODUSFoRModule::getVolumetoTableMappingMatrix(OFVector< Float64 >& value) +{ + return DcmIODUtil::getFloat64ValuesFromItem(DCM_VolumeToTableMappingMatrix, *m_Item, value); +} + + +OFCondition IODUSFoRModule::setVolumeFrameOfReferenceUID(const OFString& value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmUniqueIdentifier::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_VolumeFrameOfReferenceUID, value); + return result; +} + + +OFCondition IODUSFoRModule::setUltrasoundAcquisitionGeometry(const OFString& value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmCodeString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_UltrasoundAcquisitionGeometry, value); + return result; +} + + +OFCondition IODUSFoRModule::setApexPosition(const Float64& xValue, + const Float64& yValue, + const Float64& zValue, + const OFBool) +{ + + DcmElement *elem = newDicomElement(DCM_ApexPosition); + + + OFCondition result = elem->putFloat64(xValue, 0); + if (result.good()) result = elem->putFloat64(yValue, 1); + if (result.good()) result = elem->putFloat64(zValue, 2); + m_Item->insert(elem); + + return result; +} + + +OFCondition IODUSFoRModule::setVolumetoTransducerRelationship(const OFString& value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmCodeString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_VolumeToTransducerRelationship, value); + return result; +} + + +OFCondition IODUSFoRModule::setVolumetoTransducerMappingMatrix(const OFVector< Float64 >& value, + const OFBool checkValue) +{ + size_t vm = value.size(); + if ( checkValue && (vm != 16) ) + { + return EC_ValueMultiplicityViolated; + } + + OFCondition result; + + DcmElement* elem = NULL; + result = newDicomElement(elem, DCM_VolumeToTransducerMappingMatrix); + if (result.good()) + { + for (size_t n = 0; result.good() && n < vm; n++) + { + result = elem->putFloat64(value[n], n); + } + } + if (result.good()) + { + result = m_Item->insert(elem); + if (result.bad()) delete elem; + } + return result; +} + + +OFCondition IODUSFoRModule::setPatientFrameOfReferenceSource(const OFString& value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmCodeString::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_PatientFrameOfReferenceSource, value); + return result; +} + + +OFCondition IODUSFoRModule::setTableFrameofReferenceUID(const OFString& value, + const OFBool checkValue) +{ + OFCondition result = (checkValue) ? DcmUniqueIdentifier::checkStringValue(value, "1") : EC_Normal; + if (result.good()) + result = m_Item->putAndInsertOFStringArray(DCM_TableFrameOfReferenceUID, value); + return result; +} + + +OFCondition IODUSFoRModule::setVolumeToTableMappingMatrix(const OFVector< Float64 >& value, + const OFBool checkValue) +{ + size_t vm = value.size(); + if ( checkValue && (vm != 16) ) + { + return EC_ValueMultiplicityViolated; + } + + OFCondition result; + + DcmElement* elem = NULL; + result = newDicomElement(elem, DCM_VolumeToTableMappingMatrix); + if (result.good()) + { + for (size_t n = 0; result.good() && (n < vm); n++) + { + result = elem->putFloat64(value[n], n); + } + } + if (result.good()) + { + result = m_Item->insert(elem); + if (result.bad()) delete elem; + } + return result; +} diff --git a/dcmiod/tests/Makefile.in b/dcmiod/tests/Makefile.in new file mode 100644 index 00000000..fd8adcef --- /dev/null +++ b/dcmiod/tests/Makefile.in @@ -0,0 +1,29 @@ +# +# Makefile for dcmiod/tests +# + +@SET_MAKE@ + +SHELL = /bin/sh +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +configdir = @top_srcdir@/@configdir@ + +include $(configdir)/@common_makefile@ + + +all: + +check: + +check-exhaustive: + +install: + +clean: + rm -f $(TRASH) + +distclean: + rm -f $(DISTTRASH) + +dependencies: diff --git a/dcmjpeg/CMakeLists.txt b/dcmjpeg/CMakeLists.txt new file mode 100644 index 00000000..89b36ace --- /dev/null +++ b/dcmjpeg/CMakeLists.txt @@ -0,0 +1,7 @@ +# declare project +PROJECT(dcmjpeg) + +# recurse into subdirectories +FOREACH(SUBDIR libsrc libijg8 libijg12 libijg16 apps include) + ADD_SUBDIRECTORY(${SUBDIR}) +ENDFOREACH(SUBDIR) diff --git a/dcmjpeg/Makefile.in b/dcmjpeg/Makefile.in new file mode 100644 index 00000000..3d09954b --- /dev/null +++ b/dcmjpeg/Makefile.in @@ -0,0 +1,112 @@ +# +# Makefile for dcmjpeg +# + +@SET_MAKE@ + +SHELL = /bin/sh +VPATH = @srcdir@:@top_srcdir@/include:@top_srcdir@/@configdir@/include +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +configdir = @top_srcdir@/@configdir@ + +include $(configdir)/@common_makefile@ + + +all: include-all libsrc-all apps-all tests-all + +install: install-bin install-doc install-support + +install-bin: apps-install + +install-doc: docs-install + +install-data: data-install + +install-etc: etc-install + +install-include: include-install + +install-lib: libsrc-install install-include + +install-support: install-data install-etc + + +include-all: + (cd include && $(MAKE) ARCH="$(ARCH)" all) + +libsrc-all: include-all + (cd libijg8 && $(MAKE) ARCH="$(ARCH)" all) + (cd libijg12 && $(MAKE) ARCH="$(ARCH)" all) + (cd libijg16 && $(MAKE) ARCH="$(ARCH)" all) + (cd libsrc && $(MAKE) ARCH="$(ARCH)" all) + +apps-all: libsrc-all + (cd apps && $(MAKE) ARCH="$(ARCH)" all) + +tests-all: libsrc-all + (cd tests && $(MAKE) ARCH="$(ARCH)" all) + + +check: tests-all + (cd tests && $(MAKE) check) + +check-exhaustive: tests-all + (cd tests && $(MAKE) check-exhaustive) + + +include-install: + (cd include && $(MAKE) ARCH="$(ARCH)" install) + +libsrc-install: libsrc-all + (cd libijg8 && $(MAKE) ARCH="$(ARCH)" install) + (cd libijg12 && $(MAKE) ARCH="$(ARCH)" install) + (cd libijg16 && $(MAKE) ARCH="$(ARCH)" install) + (cd libsrc && $(MAKE) ARCH="$(ARCH)" install) + +apps-install: apps-all + (cd apps && $(MAKE) ARCH="$(ARCH)" install) + +docs-install: + (cd docs && $(MAKE) install) + +data-install: + (cd data && $(MAKE) install) + +etc-install: + (cd etc && $(MAKE) install) + + +clean: + (cd include && $(MAKE) clean) + (cd libijg8 && $(MAKE) clean) + (cd libijg12 && $(MAKE) clean) + (cd libijg16 && $(MAKE) clean) + (cd libsrc && $(MAKE) clean) + (cd apps && $(MAKE) clean) + (cd tests && $(MAKE) clean) + (cd docs && $(MAKE) clean) + (cd data && $(MAKE) clean) + (cd etc && $(MAKE) clean) + rm -f $(TRASH) + +distclean: + (cd include && $(MAKE) distclean) + (cd libijg8 && $(MAKE) distclean) + (cd libijg12 && $(MAKE) distclean) + (cd libijg16 && $(MAKE) distclean) + (cd libsrc && $(MAKE) distclean) + (cd apps && $(MAKE) distclean) + (cd tests && $(MAKE) distclean) + (cd docs && $(MAKE) distclean) + (cd data && $(MAKE) distclean) + (cd etc && $(MAKE) distclean) + rm -f $(DISTTRASH) + +dependencies: + (cd libijg8 && touch $(DEP) && $(MAKE) dependencies) + (cd libijg12 && touch $(DEP) && $(MAKE) dependencies) + (cd libijg16 && touch $(DEP) && $(MAKE) dependencies) + (cd libsrc && touch $(DEP) && $(MAKE) dependencies) + (cd apps && touch $(DEP) && $(MAKE) dependencies) +# (cd tests && touch $(DEP) && $(MAKE) dependencies) diff --git a/dcmjpeg/apps/CMakeLists.txt b/dcmjpeg/apps/CMakeLists.txt new file mode 100644 index 00000000..8e244251 --- /dev/null +++ b/dcmjpeg/apps/CMakeLists.txt @@ -0,0 +1,12 @@ +# declare additional include directories +INCLUDE_DIRECTORIES(${dcmjpeg_SOURCE_DIR}/include ${ofstd_SOURCE_DIR}/include ${oflog_SOURCE_DIR}/include ${dcmdata_SOURCE_DIR}/include ${dcmimgle_SOURCE_DIR}/include ${dcmimage_SOURCE_DIR}/include ${ZLIB_INCDIR} ${LIBTIFF_INCDIR} ${LIBPNG_INCDIR}) + +# declare executables +FOREACH(PROGRAM dcmcjpeg dcmdjpeg dcmj2pnm dcmmkdir) + DCMTK_ADD_EXECUTABLE(${PROGRAM} ${PROGRAM}) +ENDFOREACH(PROGRAM) + +# make sure executables are linked to the corresponding libraries +FOREACH(PROGRAM dcmcjpeg dcmdjpeg dcmj2pnm dcmmkdir) + DCMTK_TARGET_LINK_MODULES(${PROGRAM} dcmjpeg ijg8 ijg12 ijg16 dcmimage dcmimgle dcmdata oflog ofstd) +ENDFOREACH(PROGRAM) diff --git a/dcmjpeg/apps/Makefile.dep b/dcmjpeg/apps/Makefile.dep new file mode 100644 index 00000000..fde9a848 --- /dev/null +++ b/dcmjpeg/apps/Makefile.dep @@ -0,0 +1,498 @@ +dcmcjpeg.o: dcmcjpeg.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcostrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicent.h \ + ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcmetinf.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicdir.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdirrec.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrulup.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrul.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixseq.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcofsetl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrae.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvras.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrda.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrds.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrdt.h \ + ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvris.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrtm.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrur.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcchrstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlt.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpn.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsh.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrst.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvruc.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrut.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixel.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpobw.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcovlay.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrat.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrss.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrus.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfd.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrof.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrod.h \ + ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ + ../include/dcmtk/dcmjpeg/djdecode.h ../include/dcmtk/dcmjpeg/djutils.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diutils.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/didefine.h \ + ../include/dcmtk/dcmjpeg/djdefine.h ../include/dcmtk/dcmjpeg/djencode.h \ + ../include/dcmtk/dcmjpeg/djrplol.h ../include/dcmtk/dcmjpeg/djrploss.h \ + ../include/dcmtk/dcmjpeg/dipijpeg.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diplugin.h \ + ../../dcmimage/include/dcmtk/dcmimage/diregist.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diregbas.h \ + ../../dcmimage/include/dcmtk/dcmimage/dicdefin.h +dcmdjpeg.o: dcmdjpeg.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcostrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicent.h \ + ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcmetinf.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicdir.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdirrec.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrulup.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrul.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixseq.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcofsetl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrae.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvras.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrda.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrds.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrdt.h \ + ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvris.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrtm.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrur.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcchrstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlt.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpn.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsh.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrst.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvruc.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrut.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixel.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpobw.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcovlay.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrat.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrss.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrus.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfd.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrof.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrod.h \ + ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ + ../include/dcmtk/dcmjpeg/djdecode.h ../include/dcmtk/dcmjpeg/djutils.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diutils.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/didefine.h \ + ../include/dcmtk/dcmjpeg/djdefine.h ../include/dcmtk/dcmjpeg/dipijpeg.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diplugin.h +dcmj2pnm.o: dcmj2pnm.cc ../../dcmimage/apps/dcm2pnm.cc \ + ../../config/include/dcmtk/config/osconfig.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcostrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicent.h \ + ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcmetinf.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicdir.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdirrec.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrulup.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrul.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixseq.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcofsetl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrae.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvras.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrda.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrds.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrdt.h \ + ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvris.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrtm.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrur.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcchrstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlt.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpn.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsh.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrst.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvruc.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrut.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixel.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpobw.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcovlay.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrat.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrss.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrus.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfd.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrof.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrod.h \ + ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcrledrg.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/dcmimage.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/dimoimg.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diimage.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfcache.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diovlay.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diobjcou.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/didefine.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diovdat.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diovpln.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diutils.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/dimopx.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/dipixel.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/dimomod.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diluptab.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/dibaslut.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/dimoopx.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/didispfn.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/digsdfn.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diciefn.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/dicielut.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/didislut.h \ + ../../dcmimage/include/dcmtk/dcmimage/diregist.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diregbas.h \ + ../../dcmimage/include/dcmtk/dcmimage/dicdefin.h \ + ../include/dcmtk/dcmjpeg/djdecode.h ../include/dcmtk/dcmjpeg/djutils.h \ + ../include/dcmtk/dcmjpeg/djdefine.h ../include/dcmtk/dcmjpeg/dipijpeg.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diplugin.h \ + ../../dcmimage/include/dcmtk/dcmimage/dipitiff.h \ + ../../dcmimage/include/dcmtk/dcmimage/dipipng.h +dcmmkdir.o: dcmmkdir.cc ../../dcmdata/apps/dcmgpdir.cc \ + ../../config/include/dcmtk/config/osconfig.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcostrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicent.h \ + ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcmetinf.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicdir.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdirrec.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrulup.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrul.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixseq.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcofsetl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrae.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvras.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrda.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrds.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrdt.h \ + ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvris.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrtm.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrur.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcchrstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlt.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpn.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsh.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrst.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvruc.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrut.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixel.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpobw.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcovlay.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrat.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrss.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrus.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfd.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrof.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrod.h \ + ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcddirif.h \ + ../../dcmimage/include/dcmtk/dcmimage/diregist.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diregbas.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diutils.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/didefine.h \ + ../../dcmimage/include/dcmtk/dcmimage/dicdefin.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcrledrg.h \ + ../include/dcmtk/dcmjpeg/djdecode.h ../include/dcmtk/dcmjpeg/djutils.h \ + ../include/dcmtk/dcmjpeg/djdefine.h ../include/dcmtk/dcmjpeg/dipijpeg.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diplugin.h \ + ../include/dcmtk/dcmjpeg/ddpiimpl.h diff --git a/dcmjpeg/apps/Makefile.in b/dcmjpeg/apps/Makefile.in new file mode 100644 index 00000000..9b509d59 --- /dev/null +++ b/dcmjpeg/apps/Makefile.in @@ -0,0 +1,90 @@ +# +# Makefile for dcmjpeg/apps +# + +@SET_MAKE@ + +SHELL = /bin/sh +VPATH = @srcdir@:@top_srcdir@/include:@top_srcdir@/@configdir@/include +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +configdir = @top_srcdir@/@configdir@ + +include $(configdir)/@common_makefile@ + + +ofstddir =$(top_srcdir)/../ofstd +ofstdinc = -I$(ofstddir)/include +ofstdlibdir = -L$(ofstddir)/libsrc +ofstdlib = -lofstd + +oflogdir = $(top_srcdir)/../oflog +ofloginc = -I$(oflogdir)/include +ofloglibdir = -L$(oflogdir)/libsrc +ofloglib = -loflog + +dcmdatadir = $(top_srcdir)/../dcmdata +dcmdatainc = -I$(dcmdatadir)/include +dcmdatalibdir = -L$(dcmdatadir)/libsrc +dcmdatalib = -ldcmdata + +dcmimgledir = $(top_srcdir)/../dcmimgle +dcmimgleinc = -I$(dcmimgledir)/include +dcmimglelibdir = -L$(dcmimgledir)/libsrc +dcmimglelib = -ldcmimgle + +dcmimagedir = $(top_srcdir)/../dcmimage +dcmimageinc = -I$(dcmimagedir)/include +dcmimagelibdir = -L$(dcmimagedir)/libsrc +dcmimagelib = -ldcmimage + +dcmjpegdir = $(top_srcdir)/../dcmjpeg +dcmjpeginc = -I$(dcmjpegdir)/include +dcmjpeglibdir = -L$(dcmjpegdir)/libsrc -L$(dcmjpegdir)/libijg8 -L$(dcmjpegdir)/libijg12 \ + -L$(dcmjpegdir)/libijg16 +dcmjpeglib = -ldcmjpeg -lijg8 -lijg12 -lijg16 + +LOCALINCLUDES = $(dcmjpeginc) $(ofstdinc) $(ofloginc) $(dcmdatainc) $(dcmimageinc) \ + $(dcmimgleinc) +LIBDIRS = -L$(top_srcdir)/libsrc $(dcmjpeglibdir) $(dcmimagelibdir) $(dcmimglelibdir) \ + $(dcmdatalibdir) $(ofloglibdir) $(ofstdlibdir) +LOCALLIBS = $(dcmjpeglib) $(dcmimagelib) $(dcmimglelib) $(dcmdatalib) $(ofloglib) \ + $(ofstdlib) $(TIFFLIBS) $(PNGLIBS) $(ZLIBLIBS) $(ICONVLIBS) + +objs = dcmdjpeg.o dcmcjpeg.o dcmj2pnm.o dcmmkdir.o +progs = dcmdjpeg dcmcjpeg dcmj2pnm dcmmkdir + + +all: $(progs) + +dcmdjpeg: dcmdjpeg.o + $(CXX) $(CXXFLAGS) $(LIBDIRS) $(LDFLAGS) -o $@ $@.o $(LOCALLIBS) $(MATHLIBS) $(LIBS) + +dcmcjpeg: dcmcjpeg.o + $(CXX) $(CXXFLAGS) $(LIBDIRS) $(LDFLAGS) -o $@ $@.o $(LOCALLIBS) $(MATHLIBS) $(LIBS) + +dcmj2pnm: dcmj2pnm.o + $(CXX) $(CXXFLAGS) $(LIBDIRS) $(LDFLAGS) -o $@ $@.o $(LOCALLIBS) $(MATHLIBS) $(LIBS) + +dcmmkdir: dcmmkdir.o + $(CXX) $(CXXFLAGS) $(LIBDIRS) $(LDFLAGS) -o $@ $@.o $(LOCALLIBS) $(MATHLIBS) $(LIBS) + + +install: all + $(configdir)/mkinstalldirs $(DESTDIR)$(bindir) + for prog in $(progs); do \ + $(INSTALL_PROGRAM) $$prog$(BINEXT) $(DESTDIR)$(bindir) && $(STRIP) $(DESTDIR)$(bindir)/$$prog$(BINEXT) ;\ + done + + +clean: + rm -f $(objs) $(progs) $(TRASH) + +distclean: + rm -f $(objs) $(progs) $(DISTTRASH) + + +dependencies: + $(CXX) -MM $(defines) $(includes) $(CPPFLAGS) $(CXXFLAGS) *.cc > $(DEP) + +include $(DEP) diff --git a/dcmjpeg/apps/dcmcjpeg.cc b/dcmjpeg/apps/dcmcjpeg.cc new file mode 100644 index 00000000..b714870d --- /dev/null +++ b/dcmjpeg/apps/dcmcjpeg.cc @@ -0,0 +1,710 @@ +/* + * + * Copyright (C) 2001-2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmjpeg + * + * Author: Marco Eichelberg + * + * Purpose: Compress DICOM file + * + */ + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#define INCLUDE_CSTDLIB +#define INCLUDE_CSTDIO +#define INCLUDE_CSTRING +#include "dcmtk/ofstd/ofstdinc.h" + +#ifdef HAVE_GUSI_H +#include +#endif + +#include "dcmtk/dcmdata/dctk.h" +#include "dcmtk/dcmdata/cmdlnarg.h" +#include "dcmtk/ofstd/ofconapp.h" +#include "dcmtk/dcmdata/dcuid.h" /* for dcmtk version name */ +#include "dcmtk/dcmjpeg/djdecode.h" /* for dcmjpeg decoders */ +#include "dcmtk/dcmjpeg/djencode.h" /* for dcmjpeg encoders */ +#include "dcmtk/dcmjpeg/djrplol.h" /* for DJ_RPLossless */ +#include "dcmtk/dcmjpeg/djrploss.h" /* for DJ_RPLossy */ +#include "dcmtk/dcmjpeg/dipijpeg.h" /* for dcmimage JPEG plugin */ +#include "dcmtk/dcmimage/diregist.h" /* include to support color images */ + +#ifdef WITH_ZLIB +#include /* for zlibVersion() */ +#endif + +#define OFFIS_CONSOLE_APPLICATION "dcmcjpeg" + +static OFLogger dcmcjpegLogger = OFLog::getLogger("dcmtk.apps." OFFIS_CONSOLE_APPLICATION); + +static char rcsid[] = "$dcmtk: " OFFIS_CONSOLE_APPLICATION " v" + OFFIS_DCMTK_VERSION " " OFFIS_DCMTK_RELEASEDATE " $"; + +// ******************************************** + + +#define SHORTCOL 4 +#define LONGCOL 21 + +int main(int argc, char *argv[]) +{ + +#ifdef HAVE_GUSI_H + GUSISetup(GUSIwithSIOUXSockets); + GUSISetup(GUSIwithInternetSockets); +#endif + + const char *opt_ifname = NULL; + const char *opt_ofname = NULL; + + E_FileReadMode opt_readMode = ERM_autoDetect; + E_TransferSyntax opt_ixfer = EXS_Unknown; + E_GrpLenEncoding opt_oglenc = EGL_recalcGL; + E_EncodingType opt_oenctype = EET_ExplicitLength; + E_PaddingEncoding opt_opadenc = EPD_noChange; + OFCmdUnsignedInt opt_filepad = 0; + OFCmdUnsignedInt opt_itempad = 0; + OFBool opt_acceptWrongPaletteTags = OFFalse; + OFBool opt_acrNemaCompatibility = OFFalse; + + + // JPEG options + E_TransferSyntax opt_oxfer = EXS_JPEGProcess14SV1; + OFCmdUnsignedInt opt_selection_value = 6; + OFCmdUnsignedInt opt_point_transform = 0; + OFCmdUnsignedInt opt_quality = 90; + OFBool opt_huffmanOptimize = OFTrue; + OFCmdUnsignedInt opt_smoothing = 0; + int opt_compressedBits = 0; // 0=auto, 8/12/16=force + E_CompressionColorSpaceConversion opt_compCSconversion = ECC_lossyYCbCr; + E_DecompressionColorSpaceConversion opt_decompCSconversion = EDC_photometricInterpretation; + E_SubSampling opt_sampleFactors = ESS_444; + OFBool opt_useYBR422 = OFFalse; + OFCmdUnsignedInt opt_fragmentSize = 0; // 0=unlimited + OFBool opt_createOffsetTable = OFTrue; + int opt_windowType = 0; /* default: no windowing; 1=Wi, 2=Wl, 3=Wm, 4=Wh, 5=Ww, 6=Wn, 7=Wr */ + OFCmdUnsignedInt opt_windowParameter = 0; + OFCmdFloat opt_windowCenter=0.0, opt_windowWidth=0.0; + E_UIDCreation opt_uidcreation = EUC_default; + OFBool opt_secondarycapture = OFFalse; + OFCmdUnsignedInt opt_roiLeft = 0, opt_roiTop = 0, opt_roiWidth = 0, opt_roiHeight = 0; + OFBool opt_usePixelValues = OFTrue; + OFBool opt_useModalityRescale = OFFalse; + OFBool opt_trueLossless = OFTrue; + OFBool lossless = OFTrue; /* see opt_oxfer */ + + OFConsoleApplication app(OFFIS_CONSOLE_APPLICATION, "Encode DICOM file to JPEG transfer syntax", rcsid); + OFCommandLine cmd; + cmd.setOptionColumns(LONGCOL, SHORTCOL); + cmd.setParamColumn(LONGCOL + SHORTCOL + 4); + + cmd.addParam("dcmfile-in", "DICOM input filename to be converted"); + cmd.addParam("dcmfile-out", "DICOM output filename"); + + cmd.addGroup("general options:", LONGCOL, SHORTCOL + 2); + cmd.addOption("--help", "-h", "print this help text and exit", OFCommandLine::AF_Exclusive); + cmd.addOption("--version", "print version information and exit", OFCommandLine::AF_Exclusive); + OFLog::addOptions(cmd); + + cmd.addGroup("input options:"); + cmd.addSubGroup("input file format:"); + cmd.addOption("--read-file", "+f", "read file format or data set (default)"); + cmd.addOption("--read-file-only", "+fo", "read file format only"); + cmd.addOption("--read-dataset", "-f", "read data set without file meta information"); + cmd.addSubGroup("input transfer syntax:"); + cmd.addOption("--read-xfer-auto", "-t=", "use TS recognition (default)"); + cmd.addOption("--read-xfer-detect", "-td", "ignore TS specified in the file meta header"); + cmd.addOption("--read-xfer-little", "-te", "read with explicit VR little endian TS"); + cmd.addOption("--read-xfer-big", "-tb", "read with explicit VR big endian TS"); + cmd.addOption("--read-xfer-implicit", "-ti", "read with implicit VR little endian TS"); + cmd.addSubGroup("compatibility (ignored by +tl):"); + cmd.addOption("--accept-acr-nema", "+Ma", "accept ACR-NEMA images without photometric\ninterpretation"); + cmd.addOption("--accept-palettes", "+Mp", "accept incorrect palette attribute tags\n(0028,111x) and (0028,121x)"); + + cmd.addGroup("JPEG encoding options:"); + cmd.addSubGroup("JPEG process:"); + cmd.addOption("--encode-lossless-sv1", "+e1", "encode lossless sv1 (default)"); + cmd.addOption("--encode-lossless", "+el", "encode lossless"); + cmd.addOption("--encode-baseline", "+eb", "encode baseline"); + cmd.addOption("--encode-extended", "+ee", "encode extended sequential"); + cmd.addOption("--encode-spectral", "+es", "encode spectral selection"); + cmd.addOption("--encode-progressive", "+ep", "encode progressive"); + + cmd.addSubGroup("lossless JPEG codec selection:"); + cmd.addOption("--true-lossless", "+tl", "true lossless codec (default)"); + cmd.addOption("--pseudo-lossless", "+pl", "old pseudo-lossless codec"); + + cmd.addSubGroup("lossless JPEG representation:"); + cmd.addOption("--selection-value", "+sv", 1, "[sv]: integer (1..7, default: 6)", + "use selection value sv\nonly with --encode-lossless"); + cmd.addOption("--point-transform", "+pt", 1, "[pt]: integer (0..15, default: 0)", + "use point transform pt"); + + cmd.addSubGroup("lossy JPEG representation:"); + cmd.addOption("--quality", "+q", 1, "[q]: integer (0..100, default: 90)", + "use quality factor q"); + cmd.addOption("--smooth", "+sm", 1, "[s]: integer (0..100, default: 0)", + "use smoothing factor s"); + cmd.addSubGroup("other JPEG options:"); + cmd.addOption("--huffman-optimize", "+ho", "optimize huffman tables (default)"); + cmd.addOption("--huffman-standard", "-ho", "use standard huffman tables if 8 bits/sample"); + + cmd.addSubGroup("compressed bits per sample (always +ba with +tl):"); + cmd.addOption("--bits-auto", "+ba", "choose bits/sample automatically (default)"); + cmd.addOption("--bits-force-8", "+be", "force 8 bits/sample"); + cmd.addOption("--bits-force-12", "+bt", "force 12 bits/sample (not with baseline)"); + cmd.addOption("--bits-force-16", "+bs", "force 16 bits/sample (lossless only)"); + + cmd.addSubGroup("compression color space conversion (overridden by +tl):"); + cmd.addOption("--color-ybr", "+cy", "use YCbCr for color images if lossy (default)"); + cmd.addOption("--color-rgb", "+cr", "use RGB for color images if lossy"); + cmd.addOption("--monochrome", "+cm", "convert color images to monochrome"); + + cmd.addSubGroup("decompr. color space conversion (if input is compressed; always +cn with +tl):"); + cmd.addOption("--conv-photometric", "+cp", "convert if YCbCr photometric interpr. (default)"); + cmd.addOption("--conv-lossy", "+cl", "convert YCbCr to RGB if lossy JPEG"); + cmd.addOption("--conv-guess", "+cg", "convert to RGB if YCbCr is guessed by library"); + cmd.addOption("--conv-guess-lossy", "+cgl", "convert to RGB if lossy JPEG and YCbCr is\nguessed by the underlying JPEG library"); + cmd.addOption("--conv-always", "+ca", "always convert YCbCr to RGB"); + cmd.addOption("--conv-never", "+cn", "never convert color space"); + + cmd.addSubGroup("standard YCbCr component subsampling (not with +tl):"); + cmd.addOption("--sample-444", "+s4", "4:4:4 sampling with YBR_FULL (default)"); + cmd.addOption("--sample-422", "+s2", "4:2:2 subsampling with YBR_FULL_422"); + + cmd.addSubGroup("non-standard YCbCr component subsampling (not with +tl):"); + cmd.addOption("--nonstd-422-full", "+n2", "4:2:2 subsampling with YBR_FULL"); + cmd.addOption("--nonstd-411-full", "+n1", "4:1:1 subsampling with YBR_FULL"); + cmd.addOption("--nonstd-411", "+np", "4:1:1 subsampling with YBR_FULL_422"); + + cmd.addGroup("encapsulated pixel data encoding options:"); + cmd.addSubGroup("pixel data fragmentation:"); + cmd.addOption("--fragment-per-frame", "+ff", "encode each frame as one fragment (default)"); + cmd.addOption("--fragment-size", "+fs", 1, "[s]ize: integer", + "limit fragment size to s kbytes"); + cmd.addSubGroup("basic offset table encoding:"); + cmd.addOption("--offset-table-create", "+ot", "create offset table (default)"); + cmd.addOption("--offset-table-empty", "-ot", "leave offset table empty"); + + cmd.addSubGroup("VOI windowing for monochrome images (not with +tl):"); + cmd.addOption("--no-windowing", "-W", "no VOI windowing (default)"); + cmd.addOption("--use-window", "+Wi", 1, "[n]umber: integer", + "use the n-th VOI window from image file"); + cmd.addOption("--use-voi-lut", "+Wl", 1, "[n]umber: integer", + "use the n-th VOI look up table from image file"); + cmd.addOption("--min-max-window", "+Wm", "compute VOI window using min-max algorithm"); + cmd.addOption("--min-max-window-n", "+Wn", "compute VOI window using min-max algorithm,\nignoring extreme values"); + cmd.addOption("--roi-min-max-window", "+Wr", 4, "[l]eft [t]op [w]idth [h]eight: integer", + "compute ROI window using min-max algorithm,\nregion of interest is specified by l,t,w,h"); + cmd.addOption("--histogram-window", "+Wh", 1, "[n]umber: integer", + "compute VOI window using Histogram algorithm,\nignoring n percent"); + cmd.addOption("--set-window", "+Ww", 2, "[c]enter [w]idth: float", + "compute VOI window using center c and width w"); + + cmd.addSubGroup("pixel scaling for monochrome images (-W; ignored by +tl):"); + cmd.addOption("--scaling-pixel", "+sp", "scale using min/max pixel value (default)"); + cmd.addOption("--scaling-range", "+sr", "scale using min/max range"); + + cmd.addSubGroup("rescale slope/intercept encoding for monochrome (-W; ignored by +tl):"); + cmd.addOption("--rescale-identity", "+ri", "encode identity modality rescale (default)\nNever used for CT images"); + cmd.addOption("--rescale-map", "+rm", "use modality rescale to scale pixel range\nNever used for XA/RF/XA Biplane images"); + + cmd.addSubGroup("SOP Class UID:"); + cmd.addOption("--class-default", "+cd", "keep SOP Class UID (default)"); + cmd.addOption("--class-sc", "+cs", "convert to Secondary Capture Image\n(implies --uid-always)"); + + cmd.addSubGroup("SOP Instance UID:"); + cmd.addOption("--uid-default", "+ud", "assign new UID if lossy compression (default)"); + cmd.addOption("--uid-always", "+ua", "always assign new UID"); + cmd.addOption("--uid-never", "+un", "never assign new UID"); + + cmd.addGroup("output options:"); + cmd.addSubGroup("post-1993 value representations:"); + cmd.addOption("--enable-new-vr", "+u", "enable support for new VRs (UN/UT) (default)"); + cmd.addOption("--disable-new-vr", "-u", "disable support for new VRs, convert to OB"); + cmd.addSubGroup("group length encoding:"); + cmd.addOption("--group-length-recalc", "+g=", "recalculate group lengths if present (default)"); + cmd.addOption("--group-length-create", "+g", "always write with group length elements"); + cmd.addOption("--group-length-remove", "-g", "always write without group length elements"); + cmd.addSubGroup("length encoding in sequences and items:"); + cmd.addOption("--length-explicit", "+e", "write with explicit lengths (default)"); + cmd.addOption("--length-undefined", "-e", "write with undefined lengths"); + cmd.addSubGroup("data set trailing padding:"); + cmd.addOption("--padding-retain", "-p=", "do not change padding (default)"); + cmd.addOption("--padding-off", "-p", "no padding"); + cmd.addOption("--padding-create", "+p", 2, "[f]ile-pad [i]tem-pad: integer", + "align file on multiple of f bytes\nand items on multiple of i bytes"); + + /* evaluate command line */ + prepareCmdLineArgs(argc, argv, OFFIS_CONSOLE_APPLICATION); + if (app.parseCommandLine(cmd, argc, argv)) + { + /* check exclusive options first */ + if (cmd.hasExclusiveOption()) + { + if (cmd.findOption("--version")) + { + app.printHeader(OFTrue /*print host identifier*/); + COUT << OFendl << "External libraries used:" << OFendl; +#ifdef WITH_ZLIB + COUT << "- ZLIB, Version " << zlibVersion() << OFendl; +#endif + COUT << "- " << DiJPEGPlugin::getLibraryVersionString() << OFendl; + return 0; + } + } + + /* command line parameters */ + + cmd.getParam(1, opt_ifname); + cmd.getParam(2, opt_ofname); + + /* options */ + + OFLog::configureFromCommandLine(cmd, app); + + cmd.beginOptionBlock(); + if (cmd.findOption("--read-file")) opt_readMode = ERM_autoDetect; + if (cmd.findOption("--read-file-only")) opt_readMode = ERM_fileOnly; + if (cmd.findOption("--read-dataset")) opt_readMode = ERM_dataset; + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--read-xfer-auto")) + opt_ixfer = EXS_Unknown; + if (cmd.findOption("--read-xfer-detect")) + dcmAutoDetectDatasetXfer.set(OFTrue); + if (cmd.findOption("--read-xfer-little")) + { + app.checkDependence("--read-xfer-little", "--read-dataset", opt_readMode == ERM_dataset); + opt_ixfer = EXS_LittleEndianExplicit; + } + if (cmd.findOption("--read-xfer-big")) + { + app.checkDependence("--read-xfer-big", "--read-dataset", opt_readMode == ERM_dataset); + opt_ixfer = EXS_BigEndianExplicit; + } + if (cmd.findOption("--read-xfer-implicit")) + { + app.checkDependence("--read-xfer-implicit", "--read-dataset", opt_readMode == ERM_dataset); + opt_ixfer = EXS_LittleEndianImplicit; + } + cmd.endOptionBlock(); + + if (cmd.findOption("--accept-acr-nema")) + opt_acrNemaCompatibility = OFTrue; + if (cmd.findOption("--accept-palettes")) + opt_acceptWrongPaletteTags = OFTrue; + + // JPEG options + + cmd.beginOptionBlock(); + if (cmd.findOption("--encode-lossless-sv1")) opt_oxfer = EXS_JPEGProcess14SV1; + if (cmd.findOption("--encode-lossless")) opt_oxfer = EXS_JPEGProcess14; + if (cmd.findOption("--encode-baseline")) opt_oxfer = EXS_JPEGProcess1; + if (cmd.findOption("--encode-extended")) opt_oxfer = EXS_JPEGProcess2_4; + if (cmd.findOption("--encode-spectral")) opt_oxfer = EXS_JPEGProcess6_8; + if (cmd.findOption("--encode-progressive")) opt_oxfer = EXS_JPEGProcess10_12; + cmd.endOptionBlock(); + + // check for JPEG lossless output transfer syntaxes + lossless = (opt_oxfer == EXS_JPEGProcess14SV1) || (opt_oxfer == EXS_JPEGProcess14); + + cmd.beginOptionBlock(); + if (cmd.findOption("--true-lossless")) + { + // true lossless explicitely requested but selected TS denotes lossy process + app.checkDependence("--true-lossless", "--encode-lossless-sv1 or --encode-lossless", lossless); + opt_trueLossless = OFTrue; + } + if (cmd.findOption("--pseudo-lossless")) + { + // pseudo lossless explicitely requested but selected TS denotes lossy process + app.checkDependence("--pseudo-lossless", "--encode-lossless-sv1 or --encode-lossless", lossless); + opt_trueLossless = OFFalse; + } + cmd.endOptionBlock(); + + // disable true lossless mode since we are not encoding with JPEG lossless + if (!lossless) opt_trueLossless = OFFalse; + + if (cmd.findOption("--selection-value")) + { + app.checkDependence("--selection-value", "--encode-lossless", opt_oxfer == EXS_JPEGProcess14); + app.checkValue(cmd.getValueAndCheckMinMax(opt_selection_value, OFstatic_cast(OFCmdUnsignedInt, 1), OFstatic_cast(OFCmdUnsignedInt, 7))); + } + + if (cmd.findOption("--point-transform")) + { + app.checkDependence("--point-transform", "lossless JPEG", lossless); + app.checkValue(cmd.getValueAndCheckMinMax(opt_point_transform, OFstatic_cast(OFCmdUnsignedInt, 0), OFstatic_cast(OFCmdUnsignedInt, 15))); + } + + if (cmd.findOption("--quality")) + { + app.checkDependence("--quality", "lossy JPEG", !lossless); + app.checkValue(cmd.getValueAndCheckMinMax(opt_quality, OFstatic_cast(OFCmdUnsignedInt, 0), OFstatic_cast(OFCmdUnsignedInt, 100))); + } + + cmd.beginOptionBlock(); + if (cmd.findOption("--huffman-optimize")) opt_huffmanOptimize = OFTrue; + if (cmd.findOption("--huffman-standard")) opt_huffmanOptimize = OFFalse; + cmd.endOptionBlock(); + + if (cmd.findOption("--smooth")) + { + app.checkConflict("--smooth", "--true-lossless", opt_trueLossless); + app.checkValue(cmd.getValueAndCheckMinMax(opt_smoothing, OFstatic_cast(OFCmdUnsignedInt, 0), OFstatic_cast(OFCmdUnsignedInt, 100))); + } + + cmd.beginOptionBlock(); + if (cmd.findOption("--bits-auto")) + { + opt_compressedBits = 0; + } + if (cmd.findOption("--bits-force-8")) + { + app.checkConflict("--bits-force-8", "--true-lossless", opt_trueLossless); + opt_compressedBits = 8; + } + if (cmd.findOption("--bits-force-12")) + { + app.checkConflict("--bits-force-12", "--true-lossless", opt_trueLossless); + app.checkConflict("--bits-force-12", "--encode-baseline", opt_oxfer == EXS_JPEGProcess1); + opt_compressedBits = 12; + } + if (cmd.findOption("--bits-force-16")) + { + app.checkConflict("--bits-force-16", "--true-lossless", opt_trueLossless); + app.checkConflict("--bits-force-16", "--encode-baseline", opt_oxfer == EXS_JPEGProcess1); + app.checkConflict("--bits-force-16", "--encode-extended", opt_oxfer == EXS_JPEGProcess2_4); + app.checkConflict("--bits-force-16", "--encode-spectral", opt_oxfer == EXS_JPEGProcess6_8); + app.checkConflict("--bits-force-16", "--encode-progressive", opt_oxfer == EXS_JPEGProcess10_12); + opt_compressedBits = 16; + } + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--color-ybr")) + { + opt_compCSconversion = ECC_lossyYCbCr; + } + if (cmd.findOption("--color-rgb")) + { + app.checkConflict("--color-rgb", "--true-lossless", opt_trueLossless); + opt_compCSconversion = ECC_lossyRGB; + } + if (cmd.findOption("--monochrome")) + { + app.checkConflict("--monochrome", "--true-lossless", opt_trueLossless); + opt_compCSconversion = ECC_monochrome; + } + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--conv-photometric")) + { + opt_decompCSconversion = EDC_photometricInterpretation; + } + if (cmd.findOption("--conv-lossy")) + { + app.checkConflict("--conv-lossy", "--true-lossless", opt_trueLossless); + opt_decompCSconversion = EDC_lossyOnly; + } + if (cmd.findOption("--conv-guess")) + { + app.checkConflict("--conv-guess", "--true-lossless", opt_trueLossless); + opt_decompCSconversion = EDC_guess; + } + if (cmd.findOption("--conv-guess-lossy")) + { + app.checkConflict("--conv-guess-lossy", "--true-lossless", opt_trueLossless); + opt_decompCSconversion = EDC_guessLossyOnly; + } + if (cmd.findOption("--conv-always")) + { + app.checkConflict("--conv-always", "--true-lossless", opt_trueLossless); + opt_decompCSconversion = EDC_always; + } + if (cmd.findOption("--conv-never")) opt_decompCSconversion = EDC_never; + cmd.endOptionBlock(); + if (opt_trueLossless) opt_decompCSconversion = EDC_never; + + cmd.beginOptionBlock(); + if (cmd.findOption("--sample-444")) + { + app.checkConflict("--sample-444", "--true-lossless", opt_trueLossless); + opt_sampleFactors = ESS_444; + opt_useYBR422 = OFFalse; + } + if (cmd.findOption("--sample-422")) + { + app.checkConflict("--sample-422", "--true-lossless", opt_trueLossless); + opt_sampleFactors = ESS_422; + opt_useYBR422 = OFTrue; + } + if (cmd.findOption("--nonstd-422-full")) + { + app.checkConflict("--nonstd-422-full", "--true-lossless", opt_trueLossless); + opt_sampleFactors = ESS_422; + opt_useYBR422 = OFFalse; + } + if (cmd.findOption("--nonstd-411-full")) + { + app.checkConflict("--nonstd-411-full", "--true-lossless", opt_trueLossless); + opt_sampleFactors = ESS_411; + opt_useYBR422 = OFFalse; + } + if (cmd.findOption("--nonstd-411")) + { + app.checkConflict("--nonstd-411", "--true-lossless", opt_trueLossless); + opt_sampleFactors = ESS_411; + opt_useYBR422 = OFTrue; + } + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--fragment-per-frame")) opt_fragmentSize = 0; + if (cmd.findOption("--fragment-size")) + { + app.checkValue(cmd.getValueAndCheckMin(opt_fragmentSize, OFstatic_cast(OFCmdUnsignedInt, 1))); + } + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--offset-table-create")) opt_createOffsetTable = OFTrue; + if (cmd.findOption("--offset-table-empty")) opt_createOffsetTable = OFFalse; + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--no-windowing")) opt_windowType = 0; + if (cmd.findOption("--use-window")) + { + app.checkConflict("--use-window", "--true-lossless", opt_trueLossless); + opt_windowType = 1; + app.checkValue(cmd.getValueAndCheckMin(opt_windowParameter, 1)); + } + if (cmd.findOption("--use-voi-lut")) + { + app.checkConflict("--use-voi-lut", "--true-lossless", opt_trueLossless); + opt_windowType = 2; + app.checkValue(cmd.getValueAndCheckMin(opt_windowParameter, 1)); + } + if (cmd.findOption("--min-max-window")) + { + app.checkConflict("--min-max-window", "--true-lossless", opt_trueLossless); + opt_windowType = 3; + } + if (cmd.findOption("--min-max-window-n")) + { + app.checkConflict("--min-max-window-n", "--true-lossless", opt_trueLossless); + opt_windowType = 6; + } + if (cmd.findOption("--roi-min-max-window")) + { + app.checkConflict("--roi-min-max-window", "--true-lossless", opt_trueLossless); + opt_windowType = 7; + app.checkValue(cmd.getValue(opt_roiLeft)); + app.checkValue(cmd.getValue(opt_roiTop)); + app.checkValue(cmd.getValueAndCheckMin(opt_roiWidth, 1)); + app.checkValue(cmd.getValueAndCheckMin(opt_roiHeight, 1)); + } + if (cmd.findOption("--histogram-window")) + { + app.checkConflict("--histogram-window", "--true-lossless", opt_trueLossless); + opt_windowType = 4; + app.checkValue(cmd.getValueAndCheckMinMax(opt_windowParameter, 0, 100)); + } + if (cmd.findOption("--set-window")) + { + app.checkConflict("--set-window", "--true-lossless", opt_trueLossless); + opt_windowType = 5; + app.checkValue(cmd.getValue(opt_windowCenter)); + app.checkValue(cmd.getValueAndCheckMin(opt_windowWidth, 1.0)); + } + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--scaling-pixel")) opt_usePixelValues = OFTrue; + if (cmd.findOption("--scaling-range")) opt_usePixelValues = OFFalse; + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--rescale-identity")) opt_useModalityRescale = OFFalse; + if (cmd.findOption("--rescale-map")) opt_useModalityRescale = OFTrue; + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--class-default")) opt_secondarycapture = OFFalse; + if (cmd.findOption("--class-sc")) opt_secondarycapture = OFTrue; + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--uid-default")) opt_uidcreation = EUC_default; + if (cmd.findOption("--uid-always")) opt_uidcreation = EUC_always; + if (cmd.findOption("--uid-never")) opt_uidcreation = EUC_never; + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--enable-new-vr")) dcmEnableGenerationOfNewVRs(); + if (cmd.findOption("--disable-new-vr")) dcmDisableGenerationOfNewVRs(); + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--group-length-recalc")) opt_oglenc = EGL_recalcGL; + if (cmd.findOption("--group-length-create")) opt_oglenc = EGL_withGL; + if (cmd.findOption("--group-length-remove")) opt_oglenc = EGL_withoutGL; + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--length-explicit")) opt_oenctype = EET_ExplicitLength; + if (cmd.findOption("--length-undefined")) opt_oenctype = EET_UndefinedLength; + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--padding-retain")) opt_opadenc = EPD_noChange; + if (cmd.findOption("--padding-off")) opt_opadenc = EPD_withoutPadding; + if (cmd.findOption("--padding-create")) + { + app.checkValue(cmd.getValueAndCheckMin(opt_filepad, 0)); + app.checkValue(cmd.getValueAndCheckMin(opt_itempad, 0)); + opt_opadenc = EPD_withPadding; + } + cmd.endOptionBlock(); + + } + + /* print resource identifier */ + OFLOG_DEBUG(dcmcjpegLogger, rcsid << OFendl); + + // register global decompression codecs + DJDecoderRegistration::registerCodecs( + opt_decompCSconversion, + opt_uidcreation); + + // register global compression codecs + DJEncoderRegistration::registerCodecs( + opt_compCSconversion, + opt_uidcreation, + opt_huffmanOptimize, + OFstatic_cast(int, opt_smoothing), + opt_compressedBits, + OFstatic_cast(Uint32, opt_fragmentSize), + opt_createOffsetTable, + opt_sampleFactors, + opt_useYBR422, + opt_secondarycapture, + OFstatic_cast(Uint32, opt_windowType), + OFstatic_cast(Uint32, opt_windowParameter), + opt_windowCenter, + opt_windowWidth, + OFstatic_cast(Uint32, opt_roiLeft), + OFstatic_cast(Uint32, opt_roiTop), + OFstatic_cast(Uint32, opt_roiWidth), + OFstatic_cast(Uint32, opt_roiHeight), + opt_usePixelValues, + opt_useModalityRescale, + opt_acceptWrongPaletteTags, + opt_acrNemaCompatibility, + opt_trueLossless); + + /* make sure data dictionary is loaded */ + if (!dcmDataDict.isDictionaryLoaded()) + { + OFLOG_WARN(dcmcjpegLogger, "no data dictionary loaded, check environment variable: " + << DCM_DICT_ENVIRONMENT_VARIABLE); + } + + // open inputfile + if ((opt_ifname == NULL) || (strlen(opt_ifname) == 0)) + { + OFLOG_FATAL(dcmcjpegLogger, "invalid filename: "); + return 1; + } + + OFLOG_INFO(dcmcjpegLogger, "reading input file " << opt_ifname); + + DcmFileFormat fileformat; + OFCondition error = fileformat.loadFile(opt_ifname, opt_ixfer, EGL_noChange, DCM_MaxReadLength, opt_readMode); + if (error.bad()) + { + OFLOG_FATAL(dcmcjpegLogger, error.text() << ": reading file: " << opt_ifname); + return 1; + } + DcmDataset *dataset = fileformat.getDataset(); + + DcmXfer original_xfer(dataset->getOriginalXfer()); + if (original_xfer.isEncapsulated()) + { + OFLOG_INFO(dcmcjpegLogger, "DICOM file is already compressed, converting to uncompressed transfer syntax first"); + if (EC_Normal != dataset->chooseRepresentation(EXS_LittleEndianExplicit, NULL)) + { + OFLOG_FATAL(dcmcjpegLogger, "no conversion from compressed original to uncompressed transfer syntax possible!"); + return 1; + } + } + + OFString sopClass; + if (fileformat.getMetaInfo()->findAndGetOFString(DCM_MediaStorageSOPClassUID, sopClass).good()) + { + /* check for DICOMDIR files */ + if (sopClass == UID_MediaStorageDirectoryStorage) + { + OFLOG_FATAL(dcmcjpegLogger, "DICOMDIR files (Media Storage Directory Storage SOP Class) cannot be compressed!"); + return 1; + } + } + + OFLOG_INFO(dcmcjpegLogger, "Convert DICOM file to compressed transfer syntax"); + + DcmXfer opt_oxferSyn(opt_oxfer); + + // create representation parameters for lossy and lossless + DJ_RPLossless rp_lossless(OFstatic_cast(int, opt_selection_value), OFstatic_cast(int, opt_point_transform)); + DJ_RPLossy rp_lossy(OFstatic_cast(int, opt_quality)); + + const DcmRepresentationParameter *rp = &rp_lossy; + if (lossless) + rp = &rp_lossless; + + dataset->chooseRepresentation(opt_oxfer, rp); + if (dataset->canWriteXfer(opt_oxfer)) + { + OFLOG_INFO(dcmcjpegLogger, "Output transfer syntax " << opt_oxferSyn.getXferName() << " can be written"); + } else { + OFLOG_FATAL(dcmcjpegLogger, "no conversion to transfer syntax " << opt_oxferSyn.getXferName() << " possible!"); + return 1; + } + + OFLOG_INFO(dcmcjpegLogger, "creating output file " << opt_ofname); + + fileformat.loadAllDataIntoMemory(); + error = fileformat.saveFile(opt_ofname, opt_oxfer, opt_oenctype, opt_oglenc, + opt_opadenc, OFstatic_cast(Uint32, opt_filepad), OFstatic_cast(Uint32, opt_itempad), EWM_updateMeta); + + if (error.bad()) + { + OFLOG_FATAL(dcmcjpegLogger, error.text() << ": writing file: " << opt_ofname); + return 1; + } + + OFLOG_INFO(dcmcjpegLogger, "conversion successful"); + + // deregister global codecs + DJDecoderRegistration::cleanup(); + DJEncoderRegistration::cleanup(); + + return 0; +} diff --git a/dcmjpeg/apps/dcmdjpeg.cc b/dcmjpeg/apps/dcmdjpeg.cc new file mode 100644 index 00000000..e7489cb7 --- /dev/null +++ b/dcmjpeg/apps/dcmdjpeg.cc @@ -0,0 +1,349 @@ +/* + * + * Copyright (C) 2001-2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmjpeg + * + * Author: Marco Eichelberg + * + * Purpose: Decompress DICOM file + * + */ + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#define INCLUDE_CSTDLIB +#define INCLUDE_CSTDIO +#define INCLUDE_CSTRING +#include "dcmtk/ofstd/ofstdinc.h" + +#ifdef HAVE_GUSI_H +#include +#endif + +#include "dcmtk/dcmdata/dctk.h" +#include "dcmtk/dcmdata/cmdlnarg.h" +#include "dcmtk/ofstd/ofconapp.h" +#include "dcmtk/dcmdata/dcuid.h" /* for dcmtk version name */ +#include "dcmtk/dcmjpeg/djdecode.h" /* for dcmjpeg decoders */ +#include "dcmtk/dcmjpeg/dipijpeg.h" /* for dcmimage JPEG plugin */ + +#ifdef WITH_ZLIB +#include /* for zlibVersion() */ +#endif + +#define OFFIS_CONSOLE_APPLICATION "dcmdjpeg" + +static OFLogger dcmdjpegLogger = OFLog::getLogger("dcmtk.apps." OFFIS_CONSOLE_APPLICATION); + +static char rcsid[] = "$dcmtk: " OFFIS_CONSOLE_APPLICATION " v" + OFFIS_DCMTK_VERSION " " OFFIS_DCMTK_RELEASEDATE " $"; + +// ******************************************** + + +#define SHORTCOL 4 +#define LONGCOL 21 + +int main(int argc, char *argv[]) +{ + +#ifdef HAVE_GUSI_H + GUSISetup(GUSIwithSIOUXSockets); + GUSISetup(GUSIwithInternetSockets); +#endif + + const char *opt_ifname = NULL; + const char *opt_ofname = NULL; + + E_FileReadMode opt_readMode = ERM_autoDetect; + E_FileWriteMode opt_writeMode = EWM_fileformat; + E_TransferSyntax opt_oxfer = EXS_LittleEndianExplicit; + E_GrpLenEncoding opt_oglenc = EGL_recalcGL; + E_EncodingType opt_oenctype = EET_ExplicitLength; + E_PaddingEncoding opt_opadenc = EPD_noChange; + OFCmdUnsignedInt opt_filepad = 0; + OFCmdUnsignedInt opt_itempad = 0; + E_TransferSyntax opt_ixfer = EXS_Unknown; + + // JPEG parameters + E_DecompressionColorSpaceConversion opt_decompCSconversion = EDC_photometricInterpretation; + E_UIDCreation opt_uidcreation = EUC_default; + E_PlanarConfiguration opt_planarconfig = EPC_default; + OFBool opt_predictor6WorkaroundEnable = OFFalse; + + OFConsoleApplication app(OFFIS_CONSOLE_APPLICATION, "Decode JPEG-compressed DICOM file", rcsid); + OFCommandLine cmd; + cmd.setOptionColumns(LONGCOL, SHORTCOL); + cmd.setParamColumn(LONGCOL + SHORTCOL + 4); + + cmd.addParam("dcmfile-in", "DICOM input filename to be converted"); + cmd.addParam("dcmfile-out", "DICOM output filename"); + + cmd.addGroup("general options:", LONGCOL, SHORTCOL + 2); + cmd.addOption("--help", "-h", "print this help text and exit", OFCommandLine::AF_Exclusive); + cmd.addOption("--version", "print version information and exit", OFCommandLine::AF_Exclusive); + OFLog::addOptions(cmd); + + cmd.addGroup("input options:"); + cmd.addSubGroup("input file format:"); + cmd.addOption("--read-file", "+f", "read file format or data set (default)"); + cmd.addOption("--read-file-only", "+fo", "read file format only"); + cmd.addOption("--read-dataset", "-f", "read data set without file meta information"); + + cmd.addGroup("processing options:"); + cmd.addSubGroup("color space conversion:"); + cmd.addOption("--conv-photometric", "+cp", "convert if YCbCr photometric interpr. (default)"); + cmd.addOption("--conv-lossy", "+cl", "convert YCbCr to RGB if lossy JPEG"); + cmd.addOption("--conv-guess", "+cg", "convert to RGB if YCbCr is guessed by library"); + cmd.addOption("--conv-guess-lossy", "+cgl", "convert to RGB if lossy JPEG and YCbCr is\nguessed by the underlying JPEG library"); + cmd.addOption("--conv-always", "+ca", "always convert YCbCr to RGB"); + cmd.addOption("--conv-never", "+cn", "never convert color space"); + + cmd.addSubGroup("planar configuration:"); + cmd.addOption("--planar-auto", "+pa", "automatically determine planar configuration\nfrom SOP class and color space (default)"); + cmd.addOption("--color-by-pixel", "+px", "always store color-by-pixel"); + cmd.addOption("--color-by-plane", "+pl", "always store color-by-plane"); + + cmd.addSubGroup("SOP Instance UID:"); + cmd.addOption("--uid-default", "+ud", "keep same SOP Instance UID (default)"); + cmd.addOption("--uid-always", "+ua", "always assign new UID"); + + cmd.addSubGroup("workaround options for incorrect JPEG encodings:"); + cmd.addOption("--workaround-pred6", "+w6", "enable workaround for JPEG lossless images\nwith overflow in predictor 6"); + + cmd.addGroup("output options:"); + cmd.addSubGroup("output file format:"); + cmd.addOption("--write-file", "+F", "write file format (default)"); + cmd.addOption("--write-dataset", "-F", "write data set without file meta information"); + cmd.addSubGroup("output transfer syntax:"); + cmd.addOption("--write-xfer-little", "+te", "write with explicit VR little endian (default)"); + cmd.addOption("--write-xfer-big", "+tb", "write with explicit VR big endian TS"); + cmd.addOption("--write-xfer-implicit", "+ti", "write with implicit VR little endian TS"); + cmd.addSubGroup("post-1993 value representations:"); + cmd.addOption("--enable-new-vr", "+u", "enable support for new VRs (UN/UT) (default)"); + cmd.addOption("--disable-new-vr", "-u", "disable support for new VRs, convert to OB"); + cmd.addSubGroup("group length encoding:"); + cmd.addOption("--group-length-recalc", "+g=", "recalculate group lengths if present (default)"); + cmd.addOption("--group-length-create", "+g", "always write with group length elements"); + cmd.addOption("--group-length-remove", "-g", "always write without group length elements"); + cmd.addSubGroup("length encoding in sequences and items:"); + cmd.addOption("--length-explicit", "+e", "write with explicit lengths (default)"); + cmd.addOption("--length-undefined", "-e", "write with undefined lengths"); + cmd.addSubGroup("data set trailing padding (not with --write-dataset):"); + cmd.addOption("--padding-retain", "-p=", "do not change padding\n(default if not --write-dataset)"); + cmd.addOption("--padding-off", "-p", "no padding (implicit if --write-dataset)"); + cmd.addOption("--padding-create", "+p", 2, "[f]ile-pad [i]tem-pad: integer", + "align file on multiple of f bytes\nand items on multiple of i bytes"); + + /* evaluate command line */ + prepareCmdLineArgs(argc, argv, OFFIS_CONSOLE_APPLICATION); + if (app.parseCommandLine(cmd, argc, argv)) + { + /* check exclusive options first */ + if (cmd.hasExclusiveOption()) + { + if (cmd.findOption("--version")) + { + app.printHeader(OFTrue /*print host identifier*/); + COUT << OFendl << "External libraries used:" << OFendl; +#ifdef WITH_ZLIB + COUT << "- ZLIB, Version " << zlibVersion() << OFendl; +#endif + COUT << "- " << DiJPEGPlugin::getLibraryVersionString() << OFendl; + return 0; + } + } + + /* command line parameters */ + + cmd.getParam(1, opt_ifname); + cmd.getParam(2, opt_ofname); + + /* options */ + + OFLog::configureFromCommandLine(cmd, app); + + cmd.beginOptionBlock(); + if (cmd.findOption("--planar-auto")) opt_planarconfig = EPC_default; + if (cmd.findOption("--color-by-pixel")) opt_planarconfig = EPC_colorByPixel; + if (cmd.findOption("--color-by-plane")) opt_planarconfig = EPC_colorByPlane; + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--conv-photometric")) opt_decompCSconversion = EDC_photometricInterpretation; + if (cmd.findOption("--conv-lossy")) opt_decompCSconversion = EDC_lossyOnly; + if (cmd.findOption("--conv-guess")) opt_decompCSconversion = EDC_guess; + if (cmd.findOption("--conv-guess-lossy")) opt_decompCSconversion = EDC_guessLossyOnly; + if (cmd.findOption("--conv-always")) opt_decompCSconversion = EDC_always; + if (cmd.findOption("--conv-never")) opt_decompCSconversion = EDC_never; + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--uid-default")) opt_uidcreation = EUC_default; + if (cmd.findOption("--uid-always")) opt_uidcreation = EUC_always; + cmd.endOptionBlock(); + + if (cmd.findOption("--workaround-pred6")) opt_predictor6WorkaroundEnable = OFTrue; + + cmd.beginOptionBlock(); + if (cmd.findOption("--read-file")) + { + opt_readMode = ERM_autoDetect; + opt_ixfer = EXS_Unknown; + } + if (cmd.findOption("--read-file-only")) + { + opt_readMode = ERM_fileOnly; + opt_ixfer = EXS_Unknown; + } + if (cmd.findOption("--read-dataset")) + { + opt_readMode = ERM_dataset; + + // we don't know the real transfer syntax of the dataset, but this does + // not matter. As long as the content of encapsulated pixel sequences is + // some kind of JPEG bitstream supported by the underlying library, the + // decompression will work. So we simply choose one of the lossless + // transfer syntaxes, because these support all bit depths up to 16. + opt_ixfer = EXS_JPEGProcess14; + } + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--write-file")) opt_writeMode = EWM_fileformat; + if (cmd.findOption("--write-dataset")) opt_writeMode = EWM_dataset; + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--write-xfer-little")) opt_oxfer = EXS_LittleEndianExplicit; + if (cmd.findOption("--write-xfer-big")) opt_oxfer = EXS_BigEndianExplicit; + if (cmd.findOption("--write-xfer-implicit")) opt_oxfer = EXS_LittleEndianImplicit; + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--enable-new-vr")) dcmEnableGenerationOfNewVRs(); + if (cmd.findOption("--disable-new-vr")) dcmDisableGenerationOfNewVRs(); + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--group-length-recalc")) opt_oglenc = EGL_recalcGL; + if (cmd.findOption("--group-length-create")) opt_oglenc = EGL_withGL; + if (cmd.findOption("--group-length-remove")) opt_oglenc = EGL_withoutGL; + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--length-explicit")) opt_oenctype = EET_ExplicitLength; + if (cmd.findOption("--length-undefined")) opt_oenctype = EET_UndefinedLength; + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--padding-retain")) + { + app.checkConflict("--padding-retain", "--write-dataset", opt_writeMode == EWM_dataset); + opt_opadenc = EPD_noChange; + } + if (cmd.findOption("--padding-off")) opt_opadenc = EPD_withoutPadding; + if (cmd.findOption("--padding-create")) + { + app.checkConflict("--padding-create", "--write-dataset", opt_writeMode == EWM_dataset); + app.checkValue(cmd.getValueAndCheckMin(opt_filepad, 0)); + app.checkValue(cmd.getValueAndCheckMin(opt_itempad, 0)); + opt_opadenc = EPD_withPadding; + } + cmd.endOptionBlock(); + + } + + /* print resource identifier */ + OFLOG_DEBUG(dcmdjpegLogger, rcsid << OFendl); + + // register global decompression codecs + DJDecoderRegistration::registerCodecs( + opt_decompCSconversion, + opt_uidcreation, + opt_planarconfig, + opt_predictor6WorkaroundEnable); + + /* make sure data dictionary is loaded */ + if (!dcmDataDict.isDictionaryLoaded()) + { + OFLOG_WARN(dcmdjpegLogger, "no data dictionary loaded, check environment variable: " + << DCM_DICT_ENVIRONMENT_VARIABLE); + } + + // open inputfile + if ((opt_ifname == NULL) || (strlen(opt_ifname) == 0)) + { + OFLOG_FATAL(dcmdjpegLogger, "invalid filename: "); + return 1; + } + + OFCondition error = EC_Normal; + + DcmFileFormat fileformat; + + OFLOG_INFO(dcmdjpegLogger, "reading input file " << opt_ifname); + + error = fileformat.loadFile(opt_ifname, opt_ixfer, EGL_noChange, DCM_MaxReadLength, opt_readMode); + if (error.bad()) + { + OFLOG_FATAL(dcmdjpegLogger, error.text() << ": reading file: " << opt_ifname); + return 1; + } + + DcmDataset *dataset = fileformat.getDataset(); + + OFLOG_INFO(dcmdjpegLogger, "decompressing file"); + + DcmXfer opt_oxferSyn(opt_oxfer); + DcmXfer original_xfer(dataset->getOriginalXfer()); + + error = dataset->chooseRepresentation(opt_oxfer, NULL); + if (error.bad()) + { + OFLOG_FATAL(dcmdjpegLogger, error.text() << ": decompressing file: " << opt_ifname); + if (error == EJ_UnsupportedColorConversion) + OFLOG_FATAL(dcmdjpegLogger, "Try --conv-never to disable color space conversion"); + else if (error == EC_CannotChangeRepresentation) + OFLOG_FATAL(dcmdjpegLogger, "Input transfer syntax " << original_xfer.getXferName() << " not supported"); + return 1; + } + + if (! dataset->canWriteXfer(opt_oxfer)) + { + OFLOG_FATAL(dcmdjpegLogger, "no conversion to transfer syntax " << opt_oxferSyn.getXferName() << " possible"); + return 1; + } + + OFLOG_INFO(dcmdjpegLogger, "creating output file " << opt_ofname); + + // update file meta information with new SOP Instance UID + if ((opt_uidcreation == EUC_always) && (opt_writeMode == EWM_fileformat)) + opt_writeMode = EWM_updateMeta; + + fileformat.loadAllDataIntoMemory(); + error = fileformat.saveFile(opt_ofname, opt_oxfer, opt_oenctype, opt_oglenc, + opt_opadenc, OFstatic_cast(Uint32, opt_filepad), OFstatic_cast(Uint32, opt_itempad), opt_writeMode); + if (error != EC_Normal) + { + OFLOG_FATAL(dcmdjpegLogger, error.text() << ": writing file: " << opt_ofname); + return 1; + } + + OFLOG_INFO(dcmdjpegLogger, "conversion successful"); + + // deregister global decompression codecs + DJDecoderRegistration::cleanup(); + + return 0; +} diff --git a/dcmjpeg/apps/dcmj2pnm.cc b/dcmjpeg/apps/dcmj2pnm.cc new file mode 100644 index 00000000..69ee1b0a --- /dev/null +++ b/dcmjpeg/apps/dcmj2pnm.cc @@ -0,0 +1,27 @@ +/* + * + * Copyright (C) 2001-2010, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmjpeg + * + * Authors: Joerg Riesmeier + * + * Purpose: Convert DICOM Images to PPM or PGM using the dcmimage/dcmjpeg library. + * + */ + + +// compile "dcm2pnm" with dcmjpeg support +#define BUILD_DCM2PNM_AS_DCMJ2PNM + +// include full implementation of "dcm2pnm" +#include "../../dcmimage/apps/dcm2pnm.cc" diff --git a/dcmjpeg/apps/dcmmkdir.cc b/dcmjpeg/apps/dcmmkdir.cc new file mode 100644 index 00000000..d8a3514f --- /dev/null +++ b/dcmjpeg/apps/dcmmkdir.cc @@ -0,0 +1,47 @@ +/* + * + * Copyright (C) 2001-2010, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmjpeg + * + * Authors: Joerg Riesmeier + * + * Make a DICOMDIR according to the DICOM Part 11 Media Storage Application + * Profiles. Currently supports the following profiles: + * - General Purpose CD-R Interchange (STD-GEN-CD) + * - General Purpose Interchange on DVD-RAM Media (STD-GEN-DVD-RAM) + * - General Purpose DVD with Compression Interchange (STD-GEN-DVD-JPEG/J2K) + * - General Purpose USB and Flash Memory with Compression Interchange (STD-GEN-USB/MMC/CF/SD-JPEG/J2K) + * - General Purpose MIME Interchange (STD-GEN-MIME) + * - DVD Interchange with MPEG2 MP@ML (STD-DVD-MPEG2-MPML) + * - Basic Cardiac X-Ray Angiographic Studies on CD-R Media (STD-XABC-CD) + * - 1024 X-Ray Angiographic Studies on CD-R Media (STD-XA1K-CD) + * - 1024 X-Ray Angiographic Studies on DVD Media (STD-XA1K-DVD) + * - Dental Radiograph Interchange (STD-DEN-CD) + * - CT/MR Studies on various Media (STD-CTMR-xxxx) + * - Ultrasound Single Frame for Image Display (STD-US-ID-SF-xxxx) + * - Ultrasound Single Frame with Spatial Calibration (STD-US-SC-SF-xxxx) + * - Ultrasound Single Frame with Combined Calibration (STD-US-CC-SF-xxxx) + * - Ultrasound Single & Multi-Frame for Image Display (STD-US-ID-MF-xxxx) + * - Ultrasound Single & Multi-Frame with Spatial Calibration (STD-US-SC-MF-xxxx) + * - Ultrasound Single & Multi-Frame with Combined Calibration (STD-US-CC-MF-xxxx) + * - 12-lead ECG Interchange on Diskette (STD-WVFM-ECG-FD) + * - Hemodynamic Waveform Interchange on Diskette (STD-WVFM-HD-FD) + * + */ + + +// compile "dcmgpdir" with dcmjpeg support +#define BUILD_DCMGPDIR_AS_DCMMKDIR + +// include full implementation of "dcmgpdir" +#include "../../dcmdata/apps/dcmgpdir.cc" diff --git a/dcmjpeg/configure b/dcmjpeg/configure new file mode 100755 index 00000000..396668ee --- /dev/null +++ b/dcmjpeg/configure @@ -0,0 +1,56 @@ +#! /bin/sh + +parentdir=`pwd` +thisdir=$parentdir + +# The following test constructs relative path from the module +# directory to the configuration directory. If you know this path +# you can substitute this with +# configdir= +# It is very important that the configdir path is relative. + +configdir="configdir" + +while test "$parentdir" != "/" -a "$configdir" = "configdir"; do + if test -d "$parentdir/config" ; then + configdir=$parentdir/config + else + parentdir=`echo $parentdir | sed 's/\/[^\/]*$//'` + fi +done + +if test "$configdir" = "configdir" ; then + echo "Cannot find configure directory" + exit 1 +fi + +if test $# != 0; then + case $1 in + -a) + shift + cd "$configdir" + echo "running configure in config-directory" + ./configure $* + cd $thisdir + echo "running configure for this module" + sh "$configdir/confmod" --srcdir=. $* + ;; + -c) + shift + cd "$configdir" + echo "running configure in config-directory" + ./configure $* + ;; + *) + echo "running configure for this module" + sh "$configdir/confmod" --srcdir=. $* + ;; + esac +else + echo "running configure for this module" + sh "$configdir/confmod" --srcdir=. $* +fi + + + + diff --git a/dcmjpeg/data/Makefile.in b/dcmjpeg/data/Makefile.in new file mode 100644 index 00000000..78e447e8 --- /dev/null +++ b/dcmjpeg/data/Makefile.in @@ -0,0 +1,23 @@ +# +# Makefile for dcmjpeg/data +# + +@SET_MAKE@ + +SHELL = /bin/sh +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +configdir = @top_srcdir@/@configdir@ + +include $(configdir)/@common_makefile@ + + +all: + +install: + +clean: + rm -f $(TRASH) + +distclean: + rm -f $(DISTTRASH) diff --git a/dcmjpeg/docs/Makefile.in b/dcmjpeg/docs/Makefile.in new file mode 100644 index 00000000..7bd104a8 --- /dev/null +++ b/dcmjpeg/docs/Makefile.in @@ -0,0 +1,23 @@ +# +# Makefile for dcmjpeg/docs +# + +@SET_MAKE@ + +SHELL = /bin/sh +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +configdir = @top_srcdir@/@configdir@ + +include $(configdir)/@common_makefile@ + + +all: + +install: + +clean: + rm -f $(TRASH) + +distclean: + rm -f $(DISTTRASH) diff --git a/dcmjpeg/docs/dcmcjpeg.man b/dcmjpeg/docs/dcmcjpeg.man new file mode 100644 index 00000000..52ce96a3 --- /dev/null +++ b/dcmjpeg/docs/dcmcjpeg.man @@ -0,0 +1,673 @@ +/*! + +\if MANPAGES +\page dcmcjpeg Encode DICOM file to JPEG transfer syntax +\else +\page dcmcjpeg dcmcjpeg: Encode DICOM file to JPEG transfer syntax +\endif + +\section synopsis SYNOPSIS + +\verbatim +dcmcjpeg [options] dcmfile-in dcmfile-out +\endverbatim + +\section description DESCRIPTION + +The \b dcmcjpeg utility reads an uncompressed DICOM image (\e dcmfile-in), +performs a JPEG compression (i. e. conversion to an encapsulated DICOM transfer +syntax) and writes the converted image to an output file (\e dcmfile-out). + +\section parameters PARAMETERS + +\verbatim +dcmfile-in DICOM input filename to be converted + +dcmfile-out DICOM output filename +\endverbatim + +\section options OPTIONS + +\subsection general_options general options +\verbatim + -h --help + print this help text and exit + + --version + print version information and exit + + --arguments + print expanded command line arguments + + -q --quiet + quiet mode, print no warnings and errors + + -v --verbose + verbose mode, print processing details + + -d --debug + debug mode, print debug information + + -ll --log-level [l]evel: string constant + (fatal, error, warn, info, debug, trace) + use level l for the logger + + -lc --log-config [f]ilename: string + use config file f for the logger +\endverbatim + +\subsection input_options input options +\verbatim +input file format: + + +f --read-file + read file format or data set (default) + + +fo --read-file-only + read file format only + + -f --read-dataset + read data set without file meta information + +input transfer syntax: + + -t= --read-xfer-auto + use TS recognition (default) + + -td --read-xfer-detect + ignore TS specified in the file meta header + + -te --read-xfer-little + read with explicit VR little endian TS + + -tb --read-xfer-big + read with explicit VR big endian TS + + -ti --read-xfer-implicit + read with implicit VR little endian TS + +compatibility (ignored by +tl): + + +Ma --accept-acr-nema + accept ACR-NEMA images without photometric interpretation + + # Enables compatibility for old ACR-NEMA images without photometric + # information (only pseudo lossless encoder) + + +Mp --accept-palettes + accept incorrect palette attribute tags (0028,111x) and + (0028,121x) + + # If enabled, incorrect palette attribute tags are accepted + # (only pseudo lossless encoder) +\endverbatim + +\subsection JPEG_encoding_options JPEG encoding options +\verbatim +JPEG process: + + +e1 --encode-lossless-sv1 + encode lossless sv1 (default) + + # This option selects the JPEG Lossless, Non-Hierarchical, First-Order + # Prediction (Process 14 Selection Value 1) Transfer Syntax for + # Lossless JPEG Image Compression. + + +el --encode-lossless + encode lossless + + # This option selects the JPEG Lossless, Non-Hierarchical (Process 14) + # Transfer Syntax for Lossless JPEG Image Compression. + + +eb --encode-baseline + encode baseline + + # This option selects the JPEG Baseline (Process 1) Transfer Syntax + # for Lossy JPEG 8 Bit Image Compression. + + +ee --encode-extended + encode extended sequential + + # This option selects the JPEG Extended (Process 2 & 4) Transfer + # Syntax for Lossy JPEG Image Compression. + + +es --encode-spectral + encode spectral selection + + # This option selects the JPEG Spectral Selection, Non-Hierarchical + # (Process 6 & 8) Transfer Syntax for Lossy JPEG Image Compression. + + +ep --encode-progressive + encode progressive + + # This option selects the JPEG Full Progression, Non-Hierarchical + # (Process 10 & 12) Transfer Syntax for Lossy JPEG Image Compression. + +lossless JPEG codec selection: + + +tl --true-lossless + true lossless codec (default) + + # This option selects an encoder, that guarantees truely lossless + # image compression. See NOTES for further information. + + +pl --pseudo-lossless + old pseudo-lossless codec + + # Old encoder, that uses lossless compression algorithms, but can + # cause lossy images because of internal color space transformations + # etc. Higher compression ratio than --true-lossless in most cases. + +lossless JPEG representation: + + +sv --selection-value [sv]: integer (1..7, default: 6) + use selection value sv only with --encode-lossless + + # This option selects the selection value for lossless JPEG. + + +pt --point-transform [pt]: integer (0..15, default: 0) + use point transform pt + + # This option selects the point transform for lossless JPEG. + # WARNING: Using this option with a value other than zero causes + # a loss of precision, i. e. makes the compression "lossy". + +lossy JPEG representation: + + +q --quality [q]: integer (0..100, default: 90) + use quality factor q + + # This option selects the quality factor used to determine the + # quantization table inside the JPEG compressor, which affects + # compression ratio and image quality in lossy JPEG. + # See documentation of the Independent JPEG Group for details. + + +sm --smooth [s]: integer (0..100, default: 0) + use smoothing factor s + + # This option enables a smoothing (low-pass filter) of the image data + # prior to compression. Increases the compression ratio at the expense + # of image quality. + +other JPEG options: + + +ho --huffman-optimize + optimize huffman tables (default) + + # This option enables an optimization of the huffman tables during + # image compression. It results in a slightly smaller image at a small + # increase of CPU time. Always on if bits/sample is larger than 8. + + -ho --huffman-standard + use standard huffman tables if 8 bits/sample + + # This option disables an optimization of the huffman tables during + # image compression. + +compressed bits per sample (always +ba with +tl): + + +ba --bits-auto + choose bits/sample automatically (default) + + +be --bits-force-8 + force 8 bits/sample + + +bt --bits-force-12 + force 12 bits/sample (not with baseline) + + +bs --bits-force-16 + force 16 bits/sample (lossless only) + +compression color space conversion (overridden by +tl): + + +cy --color-ybr + use YCbCr for color images if lossy (default) + + # This option enables a transformation of the color space to YCbCr + # prior to image compression for color images in lossy JPEG. + + +cr --color-rgb + use RGB for color images if lossy + + # This option prevents the transformation of the color space to YCbCr + # prior to image compression for color images in lossy JPEG. It causes + # lossy image compression in the RGB color space which is not + # recommendable. + + +cm --monochrome + convert color images to monochrome + + # This option forces a conversion of color images to monochrome + # prior to compression. + +decompression color space conversion +(if input is compressed; always +cn with +tl): + + +cp --conv-photometric + convert if YCbCr photometric interpretation (default) + + # This option describes the behavior of dcmcjpeg when a compressed + # image is read and decompressed prior to re-compression. If the + # compressed image uses YBR_FULL or YBR_FULL_422 photometric + # interpretation, it is converted to RGB during decompression. + + +cl --conv-lossy + convert YCbCr to RGB if lossy JPEG + + # If the compressed image is encoded in lossy JPEG, assume YCbCr + # color model and convert to RGB. + + +cg --conv-guess + convert to RGB if YCbCr is guessed by library + + # If the underlying JPEG library "guesses" the color space of the + # compressed image to be YCbCr, convert to RGB. + + +cgl --conv-guess-lossy + convert to RGB if lossy JPEG and YCbCr is + guessed by the underlying JPEG library + + # If the compressed image is encoded in lossy JPEG and the underlying + # JPEG library "guesses" the color space to be YCbCr, convert to RGB. + + +ca --conv-always + always convert YCbCr to RGB + + # If the compressed image is a color image, assume YCbCr color model + # and convert to RGB. + + +cn --conv-never + never convert color space + + # Never convert color space during decompression. + +standard YCbCr component subsampling (not with +tl): + + +s4 --sample-444 + 4:4:4 sampling with YBR_FULL (default) + + # This option disables color component subsampling for compression in + # the YCbCr color space. The DICOM photometric interpretation is + # encoded as YBR_FULL. + + +s2 --sample-422 + 4:2:2 subsampling with YBR_FULL_422 + + # This option enables a 4:2:2 color component subsampling for + # compression in the YCbCr color space. The DICOM photometric + # interpretation is encoded as YBR_FULL. + +non-standard YCbCr component subsampling (not with +tl): + + +n2 --nonstd-422-full + 4:2:2 subsampling with YBR_FULL + + # This option enables a 4:2:2 color component subsampling for + # compression in the YCbCr color space. The DICOM photometric + # interpretation is encoded as YBR_FULL which violates DICOM rules. + + +n1 --nonstd-411-full + 4:1:1 subsampling with YBR_FULL + + # This option enables a 4:1:1 color component subsampling for + # compression in the YCbCr color space. The DICOM photometric + # interpretation is encoded as YBR_FULL which violates DICOM rules. + + +np --nonstd-411 + 4:1:1 subsampling with YBR_FULL_422 + + # This option enables a 4:1:1 color component subsampling for + # compression in the YCbCr color space. The DICOM photometric + # interpretation is encoded as YBR_FULL_422 which violates DICOM rules. +\endverbatim + +\subsection enc_pix_data_encoding_opt encapsulated pixel data encoding options: +\verbatim +encapsulated pixel data fragmentation: + + +ff --fragment-per-frame + encode each frame as one fragment (default) + + # This option causes the creation of one compressed fragment for each + # frame (recommended). + + +fs --fragment-size [s]ize: integer + limit fragment size to s kbytes + + # This option limits the fragment size which may cause the creation of + # multiple fragments per frame. + +basic offset table encoding: + + +ot --offset-table-create + create offset table (default) + + # This option causes the creation of a valid offset table for the + # compressed JPEG fragments. + + -ot --offset-table-empty + leave offset table empty + + # This option causes the creation of an empty offset table + # for the compressed JPEG fragments. + +VOI windowing for monochrome images (not with +tl): + + -W --no-windowing + no VOI windowing (default) + + # No window level/width is "burned" into monochrome images prior to + # compression. See notes below on pixel scaling and rescale slope + # and intercept encoding. + + +Wi --use-window [n]umber: integer + use the n-th VOI window from image file + + # Apply the n-th window center/width encoded in the image data prior + # to compression. + + +Wl --use-voi-lut [n]umber: integer + use the n-th VOI look up table from image file + + # Apply the n-th VOI LUT encoded in the image data prior + # to compression. + + +Wm --min-max-window + compute VOI window using min-max algorithm + + # Compute and apply a window center and width that covers the + # range from the smallest to the largest occuring pixel value. + + +Wn --min-max-window-n + compute VOI window using min-max algorithm, + ignoring extreme values + + # Compute and apply a window center and width that covers the + # range from the second smallest to the second largest occuring + # pixel value. This is useful if the background is set to an + # artificial black (padding value) or if white overlays are burned + # into the image data which should not be considered for the window + # computation. + + +Wr --roi-min-max-window [l]eft [t]op [w]idth [h]eight: integer + compute ROI window using min-max algorithm, + region of interest is specified by l,t,w,h + + # This option works like --min-max-window but only considers the given + # region of interest inside the image. + + +Wh --histogram-window [n]umber: integer + compute VOI window using Histogram algorithm, + ignoring n percent + + # Compute a histogram of the image data and apply window center + # and width such than n% of the image data are ignored for the window + # computation + + +Ww --set-window [c]enter [w]idth: float + compute VOI window using center c and width w + + # Apply the given window center/width prior to compression. + +pixel scaling for monochrome images (--no-windowing; ignored by +tl): + + +sp --scaling-pixel + scale using min/max pixel value (default) + + # Monochrome image pixel values are always scaled to make use of the + # pixel range available with the selected JPEG process as good as + # possible. This option selects a scaling based on the minimum and + # maximum pixel value occuring in the image. This often leads to + # significantly better image quality, but may cause different + # compressed images within one series to have different values for + # rescale slope and intercept, which is a problem if a presentation + # state for one series is to be created. + + +sr --scaling-range + scale using min/max range + + # This options selects a scaling based on the pixel range as defined + # by the stored bits, pixel representation and modality transform, + # without consideration of the minimum and maximum value really + # used within the image. + +rescale slope/intercept encoding for monochrome (-W; ignored by +tl): + + +ri --rescale-identity + encode identity modality rescale (default) + Never used for CT images + + # This options prevents the creation of a modality transformation + # other than an identity transformation (which is required for + # many DICOM IODs). Window center/width settings encoded + # in the image are adapted, VOI LUTs are removed. + + +rm --rescale-map + use modality rescale to scale pixel range + Never used for XA/RF/XA Biplane images + + # This option causes the creation of a modality rescale slope and + # intercept that maps the decompressed image data back to their + # original range. This keeps all VOI transformations valid but + # requires that the DICOM IOD supports a modality rescale slope + # and intercept transformation other than identity. + +SOP Class UID: + + +cd --class-default + keep SOP Class UID (default) + + # Keep the SOP Class UID of the source image. + + +cs --class-sc + convert to Secondary Capture Image (implies --uid-always) + + # Convert the image to Secondary Capture. In addition to the SOP + # Class UID, all attributes required for a valid secondary capture + # image are added. A new SOP instance UID is always assigned. + +SOP Instance UID: + + +ud --uid-default + assign new UID if lossy compression (default) + + # Assigns a new SOP instance UID if the compression is lossy. + + +ua --uid-always + always assign new UID + + # Unconditionally assigns a new SOP instance UID. + + +un --uid-never + never assign new UID + + # Never assigns a new SOP instance UID. +\endverbatim + +\subsection output_options output options +\verbatim +post-1993 value representations: + + +u --enable-new-vr + enable support for new VRs (UN/UT) (default) + + -u --disable-new-vr + disable support for new VRs, convert to OB + +group length encoding: + + +g= --group-length-recalc + recalculate group lengths if present (default) + + +g --group-length-create + always write with group length elements + + -g --group-length-remove + always write without group length elements + +length encoding in sequences and items: + + +e --length-explicit + write with explicit lengths (default) + + -e --length-undefined + write with undefined lengths + +data set trailing padding: + + -p= --padding-retain + do not change padding (default) + + -p --padding-off + no padding + + +p --padding-create [f]ile-pad [i]tem-pad: integer + align file on multiple of f bytes + and items on multiple of i bytes +\endverbatim + +\section notes NOTES + +The \b dcmcjpeg utility compresses DICOM images of all SOP classes. Special +handling has been implemented for CT images (where the modality transformation +is required to create Hounsfield units) and the XA/RF/Biplane SOP classes +(where the modality transformation has "inversed" semantics). However, +\b dcmcjpeg does not attempt to ensure that the compressed image still complies +with all restrictions of the object's IOD. + +A few examples: + +\li MR images are required to have BitsAllocated=16. +\li NM Images can only be encoded with MONOCHROME2 or PALETTE COLOR photometric + interpretation but not with RGB or YBR_FULL (which effectively prevents + compression). +\li Hardcopy Color images must have RGB color model which is a problem if lossy + compression is to be performed. + +The user is responsible for making sure that the compressed images he creates +are compliant with the DICOM standard. If in question, the \b dcmcjpeg utility +allows one to convert an image to secondary capture - this SOP class does not pose +restrictions as the ones mentioned above. + +With version DCMTK 3.5.4 a new encoder for truely lossless JPEG compression was +added (\e --true-lossless). Compared to the old (\e --pseudo-lossless) encoder, +that creates slightly lossy images caused from internal color space conversions, +windowing etc., there are a some issues to consider: + +\li Only source images with Bits Allocated 8 or 16 are supported +\li Options for color space conversions, windowing or pixel scaling are + ignored or overridden +\li Photometric Interpretations YBR_FULL_422, YBR_PARTIAL_422, YBR_PARTIAL_420, + YBR_ICT, YBR_RCT are not supported +\li The encoder changes automatically Planar Configuration from 1 to 0 if + necessary +\li The compression ratio can be lower than in \e --pseudo-lossless mode + +However, when using the new encoder (default), you can be sure, that +compression does not affect image quality. + +In order to be on the safe side, the Lossy Compression Flag is always set to +"01" and a new SOP instance UID is assigned (by default) for the old +pseudo-lossless encoder. The output of the old and new lossless encoder can +also be distinguished by the Derivation Description in the resulting DICOM +image, which contains the term "Lossless JPEG compression" for the new and +"Pseudo-Lossless JPEG compression" for the old encoder. + +\section transfer_syntaxes TRANSFER SYNTAXES + +\b dcmcjpeg supports the following transfer syntaxes for input +(\e dcmfile-in): + +\verbatim +LittleEndianImplicitTransferSyntax 1.2.840.10008.1.2 +LittleEndianExplicitTransferSyntax 1.2.840.10008.1.2.1 +DeflatedExplicitVRLittleEndianTransferSyntax 1.2.840.10008.1.2.1.99 (*) +BigEndianExplicitTransferSyntax 1.2.840.10008.1.2.2 +JPEGProcess1TransferSyntax 1.2.840.10008.1.2.4.50 +JPEGProcess2_4TransferSyntax 1.2.840.10008.1.2.4.51 +JPEGProcess6_8TransferSyntax 1.2.840.10008.1.2.4.53 +JPEGProcess10_12TransferSyntax 1.2.840.10008.1.2.4.55 +JPEGProcess14TransferSyntax 1.2.840.10008.1.2.4.57 +JPEGProcess14SV1TransferSyntax 1.2.840.10008.1.2.4.70 +\endverbatim + +(*) if compiled with zlib support enabled + +\b dcmcjpeg supports the following transfer syntaxes for output +(\e dcmfile-out): + +\verbatim +JPEGProcess1TransferSyntax 1.2.840.10008.1.2.4.50 +JPEGProcess2_4TransferSyntax 1.2.840.10008.1.2.4.51 +JPEGProcess6_8TransferSyntax 1.2.840.10008.1.2.4.53 +JPEGProcess10_12TransferSyntax 1.2.840.10008.1.2.4.55 +JPEGProcess14TransferSyntax 1.2.840.10008.1.2.4.57 +JPEGProcess14SV1TransferSyntax 1.2.840.10008.1.2.4.70 +\endverbatim + +\section logging LOGGING + +The level of logging output of the various command line tools and underlying +libraries can be specified by the user. By default, only errors and warnings +are written to the standard error stream. Using option \e --verbose also +informational messages like processing details are reported. Option +\e --debug can be used to get more details on the internal activity, e.g. for +debugging purposes. Other logging levels can be selected using option +\e --log-level. In \e --quiet mode only fatal errors are reported. In such +very severe error events, the application will usually terminate. For more +details on the different logging levels, see documentation of module "oflog". + +In case the logging output should be written to file (optionally with logfile +rotation), to syslog (Unix) or the event log (Windows) option \e --log-config +can be used. This configuration file also allows for directing only certain +messages to a particular output stream and for filtering certain messages +based on the module or application where they are generated. An example +configuration file is provided in \/logger.cfg. + +\section command_line COMMAND LINE + +All command line tools use the following notation for parameters: square +brackets enclose optional values (0-1), three trailing dots indicate that +multiple values are allowed (1-n), a combination of both means 0 to n values. + +Command line options are distinguished from parameters by a leading '+' or '-' +sign, respectively. Usually, order and position of command line options are +arbitrary (i.e. they can appear anywhere). However, if options are mutually +exclusive the rightmost appearance is used. This behavior conforms to the +standard evaluation rules of common Unix shells. + +In addition, one or more command files can be specified using an '@' sign as a +prefix to the filename (e.g. \@command.txt). Such a command argument +is replaced by the content of the corresponding text file (multiple +whitespaces are treated as a single separator unless they appear between two +quotation marks) prior to any further evaluation. Please note that a command +file cannot contain another command file. This simple but effective approach +allows one to summarize common combinations of options/parameters and avoids +longish and confusing command lines (an example is provided in file +\/dumppat.txt). + +\section environment ENVIRONMENT + +The \b dcmcjpeg utility will attempt to load DICOM data dictionaries specified +in the \e DCMDICTPATH environment variable. By default, i.e. if the +\e DCMDICTPATH environment variable is not set, the file +\/dicom.dic will be loaded unless the dictionary is built +into the application (default for Windows). + +The default behavior should be preferred and the \e DCMDICTPATH environment +variable only used when alternative data dictionaries are required. The +\e DCMDICTPATH environment variable has the same format as the Unix shell +\e PATH variable in that a colon (":") separates entries. On Windows systems, +a semicolon (";") is used as a separator. The data dictionary code will +attempt to load each file specified in the \e DCMDICTPATH environment variable. +It is an error if no data dictionary can be loaded. + +\section see_also SEE ALSO + +dcmdjpeg(1) + +\section copyright COPYRIGHT + +Copyright (C) 2001-2014 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany. + +*/ diff --git a/dcmjpeg/docs/dcmdjpeg.man b/dcmjpeg/docs/dcmdjpeg.man new file mode 100644 index 00000000..d87dfa3e --- /dev/null +++ b/dcmjpeg/docs/dcmdjpeg.man @@ -0,0 +1,328 @@ +/*! + +\if MANPAGES +\page dcmdjpeg Decode JPEG-compressed DICOM file +\else +\page dcmdjpeg dcmdjpeg: Decode JPEG-compressed DICOM file +\endif + +\section synopsis SYNOPSIS + +\verbatim +dcmdjpeg [options] dcmfile-in dcmfile-out +\endverbatim + +\section description DESCRIPTION + +The \b dcmdjpeg utility reads a JPEG-compressed DICOM image (\e dcmfile-in), +decompresses the JPEG data (i. e. conversion to a native DICOM transfer syntax) +and writes the converted image to an output file (\e dcmfile-out). + +\section parameters PARAMETERS + +\verbatim +dcmfile-in DICOM input filename to be converted + +dcmfile-out DICOM output filename +\endverbatim + +\section options OPTIONS + +\subsection general_options general options +\verbatim + -h --help + print this help text and exit + + --version + print version information and exit + + --arguments + print expanded command line arguments + + -q --quiet + quiet mode, print no warnings and errors + + -v --verbose + verbose mode, print processing details + + -d --debug + debug mode, print debug information + + -ll --log-level [l]evel: string constant + (fatal, error, warn, info, debug, trace) + use level l for the logger + + -lc --log-config [f]ilename: string + use config file f for the logger +\endverbatim + +\subsection input_options input options + +\verbatim +input file format: + + +f --read-file + read file format or data set (default) + + +fo --read-file-only + read file format only + + -f --read-dataset + read data set without file meta information + + # This option allows one to decompress JPEG compressed DICOM objects that + # have been stored as dataset without meta-header. Such a thing should + # not exist since the transfer syntax cannot be reliably determined, + # without meta-header but unfortunately it does. +\endverbatim + +\subsection processing_options processing options + +\verbatim +color space conversion: + + +cp --conv-photometric + convert if YCbCr photometric interpretation (default) + + # If the compressed image uses YBR_FULL or YBR_FULL_422 photometric + # interpretation, convert to RGB during decompression. + + +cl --conv-lossy + convert YCbCr to RGB if lossy JPEG + + # If the compressed image is encoded in lossy JPEG, assume YCbCr + # color model and convert to RGB. + + +cg --conv-guess + convert to RGB if YCbCr is guessed by library + + # If the underlying JPEG library "guesses" the color space of the + # compressed image to be YCbCr, convert to RGB. + + +cgl --conv-guess-lossy + convert to RGB if lossy JPEG and YCbCr is + guessed by the underlying JPEG library + + # If the compressed image is encoded in lossy JPEG and the underlying + # JPEG library "guesses" the color space to be YCbCr, convert to RGB. + + +ca --conv-always + always convert YCbCr to RGB + + # If the compressed image is a color image, assume YCbCr color model + # and convert to RGB. + + +cn --conv-never + never convert color space + + # Never convert color space during decompression. + +planar configuration: + + +pa --planar-auto + automatically determine planar configuration + from SOP class and color space (default) + + # If the compressed image is a color image, store in color-by-plane + # planar configuration if required by the SOP class and photometric + # interpretation. Hardcopy Color images are always stored color-by- + # plane, and the revised Ultrasound image objects are stored color-by- + # plane if the color model is YBR_FULL. Everything else is stored + # color-by-pixel. + + +px --color-by-pixel + always store color-by-pixel + + # If the compressed image is a color image, store in color-by-pixel + # planar configuration. + + +pl --color-by-plane + always store color-by-plane + + # If the compressed image is a color image, store in color-by-plane + # planar configuration. + +SOP Instance UID: + + +ud --uid-default + keep same SOP Instance UID (default) + + # Never assigns a new SOP instance UID. + + +ua --uid-always + always assign new UID + + # Always assigns a new SOP instance UID. + +workaround options for incorrect JPEG encodings: + + +w6 --workaround-pred6 + enable workaround for JPEG lossless images + with overflow in predictor 6 + + # DICOM images with 16 bits/pixel have been observed "in the wild" + # that are compressed with lossless JPEG and need special handling + # because the encoder produced an 16-bit integer overflow in predictor + # 6, which needs to be compensated (reproduced) during decompression. + # This flag enables a correct decompression of such faulty images, but + # at the same time will cause an incorrect decompression of correctly + # compressed images. Use with care. +\endverbatim + +\subsection output_options output options + +\verbatim +output file format: + + +F --write-file + write file format (default) + + -F --write-dataset + write data set without file meta information + +output transfer syntax: + + +te --write-xfer-little + write with explicit VR little endian (default) + + +tb --write-xfer-big + write with explicit VR big endian TS + + +ti --write-xfer-implicit + write with implicit VR little endian TS + +post-1993 value representations: + + +u --enable-new-vr + enable support for new VRs (UN/UT) (default) + + -u --disable-new-vr + disable support for new VRs, convert to OB + +group length encoding: + + +g= --group-length-recalc + recalculate group lengths if present (default) + + +g --group-length-create + always write with group length elements + + -g --group-length-remove + always write without group length elements + +length encoding in sequences and items: + + +e --length-explicit + write with explicit lengths (default) + + -e --length-undefined + write with undefined lengths + +data set trailing padding (not with --write-dataset): + + -p= --padding-retain + do not change padding (default if not --write-dataset) + + -p --padding-off + no padding (implicit if --write-dataset) + + +p --padding-create [f]ile-pad [i]tem-pad: integer + align file on multiple of f bytes + and items on multiple of i bytes +\endverbatim + +\section transfer_syntaxes TRANSFER SYNTAXES + +\b dcmdjpeg supports the following transfer syntaxes for input +(\e dcmfile-in): + +\verbatim +LittleEndianImplicitTransferSyntax 1.2.840.10008.1.2 +LittleEndianExplicitTransferSyntax 1.2.840.10008.1.2.1 +DeflatedExplicitVRLittleEndianTransferSyntax 1.2.840.10008.1.2.1.99 (*) +BigEndianExplicitTransferSyntax 1.2.840.10008.1.2.2 +JPEGProcess1TransferSyntax 1.2.840.10008.1.2.4.50 +JPEGProcess2_4TransferSyntax 1.2.840.10008.1.2.4.51 +JPEGProcess6_8TransferSyntax 1.2.840.10008.1.2.4.53 +JPEGProcess10_12TransferSyntax 1.2.840.10008.1.2.4.55 +JPEGProcess14TransferSyntax 1.2.840.10008.1.2.4.57 +JPEGProcess14SV1TransferSyntax 1.2.840.10008.1.2.4.70 +\endverbatim + +(*) if compiled with zlib support enabled + +\b dcmdjpeg supports the following transfer syntaxes for output +(\e dcmfile-out): + +\verbatim +LittleEndianImplicitTransferSyntax 1.2.840.10008.1.2 +LittleEndianExplicitTransferSyntax 1.2.840.10008.1.2.1 +BigEndianExplicitTransferSyntax 1.2.840.10008.1.2.2 +\endverbatim + +\section logging LOGGING + +The level of logging output of the various command line tools and underlying +libraries can be specified by the user. By default, only errors and warnings +are written to the standard error stream. Using option \e --verbose also +informational messages like processing details are reported. Option +\e --debug can be used to get more details on the internal activity, e.g. for +debugging purposes. Other logging levels can be selected using option +\e --log-level. In \e --quiet mode only fatal errors are reported. In such +very severe error events, the application will usually terminate. For more +details on the different logging levels, see documentation of module "oflog". + +In case the logging output should be written to file (optionally with logfile +rotation), to syslog (Unix) or the event log (Windows) option \e --log-config +can be used. This configuration file also allows for directing only certain +messages to a particular output stream and for filtering certain messages +based on the module or application where they are generated. An example +configuration file is provided in \/logger.cfg. + +\section command_line COMMAND LINE + +All command line tools use the following notation for parameters: square +brackets enclose optional values (0-1), three trailing dots indicate that +multiple values are allowed (1-n), a combination of both means 0 to n values. + +Command line options are distinguished from parameters by a leading '+' or '-' +sign, respectively. Usually, order and position of command line options are +arbitrary (i.e. they can appear anywhere). However, if options are mutually +exclusive the rightmost appearance is used. This behavior conforms to the +standard evaluation rules of common Unix shells. + +In addition, one or more command files can be specified using an '@' sign as a +prefix to the filename (e.g. \@command.txt). Such a command argument +is replaced by the content of the corresponding text file (multiple +whitespaces are treated as a single separator unless they appear between two +quotation marks) prior to any further evaluation. Please note that a command +file cannot contain another command file. This simple but effective approach +allows one to summarize common combinations of options/parameters and avoids +longish and confusing command lines (an example is provided in file +\/dumppat.txt). + +\section environment ENVIRONMENT + +The \b dcmdjpeg utility will attempt to load DICOM data dictionaries specified +in the \e DCMDICTPATH environment variable. By default, i.e. if the +\e DCMDICTPATH environment variable is not set, the file +\/dicom.dic will be loaded unless the dictionary is built +into the application (default for Windows). + +The default behavior should be preferred and the \e DCMDICTPATH environment +variable only used when alternative data dictionaries are required. The +\e DCMDICTPATH environment variable has the same format as the Unix shell +\e PATH variable in that a colon (":") separates entries. On Windows systems, +a semicolon (";") is used as a separator. The data dictionary code will +attempt to load each file specified in the \e DCMDICTPATH environment variable. +It is an error if no data dictionary can be loaded. + +\section see_also SEE ALSO + +dcmcjpeg(1) + +\section copyright COPYRIGHT + +Copyright (C) 2001-2014 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany. + +*/ diff --git a/dcmjpeg/docs/dcmj2pnm.man b/dcmjpeg/docs/dcmj2pnm.man new file mode 100644 index 00000000..b117525a --- /dev/null +++ b/dcmjpeg/docs/dcmj2pnm.man @@ -0,0 +1,547 @@ +/*! + +\if MANPAGES +\page dcmj2pnm Convert DICOM images to PGM/PPM, PNG, TIFF, JPEG or BMP +\else +\page dcmj2pnm dcmj2pnm: Convert DICOM images to PGM/PPM, PNG, TIFF, JPEG or BMP +\endif + +\section synopsis SYNOPSIS + +\verbatim +dcmj2pnm [options] dcmfile-in [bitmap-out] +\endverbatim + +\section description DESCRIPTION + +The \b dcmj2pnm utility reads a DICOM image, converts the pixel data according +to the selected image processing options and writes back an image in the +well-known PGM/PPM (portable gray map / portable pix map), PNG, TIFF, JPEG +(Joint Photographic Experts Group) or Windows BMP format. This utility +supports uncompressed as well as JPEG and RLE compressed DICOM images. + +\section parameters PARAMETERS + +\verbatim +dcmfile-in DICOM input filename to be converted + +bitmap-out output filename to be written (default: stdout) +\endverbatim + +\section options OPTIONS + +\subsection general_options general options +\verbatim + -h --help + print this help text and exit + + --version + print version information and exit + + --arguments + print expanded command line arguments + + -q --quiet + quiet mode, print no warnings and errors + + -v --verbose + verbose mode, print processing details + + -d --debug + debug mode, print debug information + + -ll --log-level [l]evel: string constant + (fatal, error, warn, info, debug, trace) + use level l for the logger + + -lc --log-config [f]ilename: string + use config file f for the logger +\endverbatim + +\subsection input_options input options +\verbatim +input file format: + + +f --read-file + read file format or data set (default) + + +fo --read-file-only + read file format only + + -f --read-dataset + read data set without file meta information + +input transfer syntax: + + -t= --read-xfer-auto + use TS recognition (default) + + -td --read-xfer-detect + ignore TS specified in the file meta header + + -te --read-xfer-little + read with explicit VR little endian TS + + -tb --read-xfer-big + read with explicit VR big endian TS + + -ti --read-xfer-implicit + read with implicit VR little endian TS +\endverbatim + +\subsection image_processing_options image processing options +\verbatim +frame selection: + + +F --frame [n]umber: integer + select specified frame (default: 1) + + +Fr --frame-range [n]umber [c]ount: integer + select c frames beginning with frame n + + +Fa --all-frames + select all frames + +rotation: + + +Rl --rotate-left + rotate image left (-90 degrees) + + +Rr --rotate-right + rotate image right (+90 degrees) + + +Rtd --rotate-top-down + rotate image top-down (180 degrees) + +flipping: + + +Lh --flip-horizontally + flip image horizontally + + +Lv --flip-vertically + flip image vertically + + +Lhv --flip-both-axes + flip image horizontally and vertically + +scaling: + + +a --recognize-aspect + recognize pixel aspect ratio (default) + + -a --ignore-aspect + ignore pixel aspect ratio when scaling + + +i --interpolate [n]umber of algorithm: integer + use interpolation when scaling (1..4, default: 1) + + -i --no-interpolation + no interpolation when scaling + + -S --no-scaling + no scaling, ignore pixel aspect ratio (default) + + +Sxf --scale-x-factor [f]actor: float + scale x axis by factor, auto-compute y axis + + +Syf --scale-y-factor [f]actor: float + scale y axis by factor, auto-compute x axis + + +Sxv --scale-x-size [n]umber: integer + scale x axis to n pixels, auto-compute y axis + + +Syv --scale-y-size [n]umber: integer + scale y axis to n pixels, auto-compute x axis + +color space conversion (compressed images only): + + +cp --conv-photometric + convert if YCbCr photometric interpretation (default) + + +cl --conv-lossy + convert YCbCr to RGB if lossy JPEG + + +cg --conv-guess + convert to RGB if YCbCr is guessed by library + + +cgl --conv-guess-lossy + convert to RGB if lossy JPEG and YCbCr is + guessed by the underlying JPEG library + + +ca --conv-always + always convert YCbCr to RGB + + +cn --conv-never + never convert color space + +modality LUT transformation: + + -M --no-modality + ignore stored modality LUT transformation + + +M --use-modality + use modality LUT transformation (default) + +VOI LUT transformation: + + -W --no-windowing + no VOI windowing (default) + + +Wi --use-window [n]umber: integer + use the n-th VOI window from image file + + +Wl --use-voi-lut [n]umber: integer + use the n-th VOI look up table from image file + + +Wm --min-max-window + compute VOI window using min-max algorithm + + +Wn --min-max-window-n + compute VOI window using min-max algorithm, + ignoring extreme values + + +Wr --roi-min-max-window [l]eft [t]op [w]idth [h]eight: integer + compute ROI window using min-max algorithm, + region of interest is specified by l,t,w,h + + +Wh --histogram-window [n]umber: integer + compute VOI window using Histogram algorithm, + ignoring n percent + + +Ww --set-window [c]enter [w]idth: float + compute VOI window using center c and width w + + +Wfl --linear-function + set VOI LUT function to LINEAR + + +Wfs --sigmoid-function + set VOI LUT function to SIGMOID + +presentation LUT transformation: + + +Pid --identity-shape + set presentation LUT shape to IDENTITY + + +Piv --inverse-shape + set presentation LUT shape to INVERSE + + +Pod --lin-od-shape + set presentation LUT shape to LIN OD + +overlay: + + -O --no-overlays + do not display overlays + + +O --display-overlay [n]umber: integer + display overlay n (0..16, 0=all, default: +O 0) + + +Omr --ovl-replace + use overlay mode "Replace" + (default for Graphic overlays) + + +Omt --ovl-threshold + use overlay mode "Threshold Replace" + + +Omc --ovl-complement + use overlay mode "Complement" + + +Omv --ovl-invert + use overlay mode "Invert Bitmap" + + +Omi --ovl-roi + use overlay mode "Region of Interest" + (default for ROI overlays) + + +Osf --set-foreground [d]ensity: float + set overlay foreground density (0..1, default: 1) + + +Ost --set-threshold [d]ensity: float + set overlay threshold density (0..1, default: 0.5) + +display LUT transformation: + + +Dm --monitor-file [f]ilename: string + calibrate output according to monitor characteristics + defined in f + + +Dp --printer-file [f]ilename: string + calibrate output according to printer characteristics + defined in f + + +Da --ambient-light [a]mbient light: float + ambient light value (cd/m^2, default: file f) + + +Di --illumination [i]llumination: float + illumination value (cd/m^2, default: file f) + + +Dn --min-density [m]inimum optical density: float + Dmin value (default: off, only with +Dp) + + +Dx --max-density [m]aximum optical density: float + Dmax value (default: off, only with +Dp) + + +Dg --gsd-function + use GSDF for calibration (default for +Dm/+Dp) + + +Dc --cielab-function + use CIELAB function for calibration + +compatibility: + + +Ma --accept-acr-nema + accept ACR-NEMA images without photometric + interpretation + + +Mp --accept-palettes + accept incorrect palette attribute tags + (0028,111x) and (0028,121x) + + +Mc --check-lut-depth + check 3rd value of the LUT descriptor, compare + with expected bit depth based on LUT data + + +Mm --ignore-mlut-depth + ignore 3rd value of the modality LUT descriptor, + determine bits per table entry automatically + + +Mv --ignore-vlut-depth + ignore 3rd value of the VOI LUT descriptor, + determine bits per table entry automatically + +TIFF format: + + +Tl --compr-lzw + LZW compression (default) + + +Tr --compr-rle + RLE compression + + +Tn --compr-none + uncompressed + + +Pd --predictor-default + no LZW predictor (default) + + +Pn --predictor-none + LZW predictor 1 (no prediction) + + +Ph --predictor-horz + LZW predictor 2 (horizontal differencing) + + +Rs --rows-per-strip [r]ows: integer (default: 0) + rows per strip, default 8K per strip + +PNG format: + + +il --interlace + create interlaced file (default) + + -il --nointerlace + create non-interlaced file + + +mf --meta-file + create PNG file meta information (default) + + -mf --meta-none + no PNG file meta information + +JPEG format: + + +Jq --compr-quality [q]uality: integer (0..100, default: 90) + quality value for compression (in percent) + + +Js4 --sample-444 + 4:4:4 sampling (no subsampling) + + +Js2 --sample-422 + 4:2:2 subsampling (horizontal subsampling of + chroma components, default) + + +Js1 --sample-411 + 4:1:1 subsampling (horizontal and vertical + subsampling of chroma components) + +other transformations: + + +G --grayscale + convert to grayscale if necessary + + +P --change-polarity + change polarity (invert pixel output) + + +C --clip-region [l]eft [t]op [w]idth [h]eight: integer + clip image region (l, t, w, h) +\endverbatim + +\subsection output_options output options +\verbatim +general: + + -im --image-info + print image details (requires verbose mode) + + -o --no-output + do not create any output (useful with -im) + +filename generation (only with --frame-range or --all-frames): + + +Fc --use-frame-counter + use 0-based counter for filenames (default) + + +Fn --use-frame-number + use absolute frame number for filenames + +image format: + + +op --write-raw-pnm + write 8-bit binary PGM/PPM (default for files) + + +opb --write-8-bit-pnm + write 8-bit ASCII PGM/PPM (default for stdout) + + +opw --write-16-bit-pnm + write 16-bit ASCII PGM/PPM + + +opn --write-n-bit-pnm [n]umber: integer + write n-bit ASCII PGM/PPM (1..32) + + +ob --write-bmp + write 8-bit (monochrome) or 24-bit (color) BMP + + +obp --write-8-bit-bmp + write 8-bit palette BMP (monochrome only) + + +obt --write-24-bit-bmp + write 24-bit truecolor BMP + + +obr --write-32-bit-bmp + write 32-bit truecolor BMP + + +ot --write-tiff + write 8-bit (monochrome) or 24-bit (color) TIFF + + +on --write-png + write 8-bit (monochrome) or 24-bit (color) PNG + + +on2 --write-16-bit-png + write 16-bit (monochrome) or 48-bit (color) PNG + + +oj --write-jpeg + write 8-bit lossy JPEG (baseline) +\endverbatim + +\section notes NOTES + +The following preferred interpolation algorithms can be selected using the +\e --interpolate option: + +\li 1 = free scaling algorithm with interpolation from pbmplus toolkit +\li 2 = free scaling algorithm with interpolation from c't magazine +\li 3 = magnification algorithm with bilinear interpolation from Eduard Stanescu +\li 4 = magnification algorithm with bicubic interpolation from Eduard Stanescu + +The \e --write-tiff option is only available when DCMTK has been configured +and compiled with support for the external \b libtiff TIFF library. The +availability of the TIFF compression options depends on the \b libtiff +configuration. In particular, the patented LZW algorithm may not be +available. + +The \e --write-png option is only available when DCMTK has been configured +and compiled with support for the external \b libpng PNG library. Option +\e --interlace enables progressive image view while loading the PNG file. +Only a few applications take care of the meta info (TEXT) in a PNG file. + +\section transfer_syntaxes TRANSFER SYNTAXES + +\b dcmj2pnm supports the following transfer syntaxes for input (\e dcmfile-in): + +\verbatim +LittleEndianImplicitTransferSyntax 1.2.840.10008.1.2 +LittleEndianExplicitTransferSyntax 1.2.840.10008.1.2.1 +DeflatedExplicitVRLittleEndianTransferSyntax 1.2.840.10008.1.2.1.99 (*) +BigEndianExplicitTransferSyntax 1.2.840.10008.1.2.2 +JPEGProcess1TransferSyntax 1.2.840.10008.1.2.4.50 +JPEGProcess2_4TransferSyntax 1.2.840.10008.1.2.4.51 +JPEGProcess6_8TransferSyntax 1.2.840.10008.1.2.4.53 +JPEGProcess10_12TransferSyntax 1.2.840.10008.1.2.4.55 +JPEGProcess14TransferSyntax 1.2.840.10008.1.2.4.57 +JPEGProcess14SV1TransferSyntax 1.2.840.10008.1.2.4.70 +RLELosslessTransferSyntax 1.2.840.10008.1.2.5 +\endverbatim + +(*) if compiled with zlib support enabled + +\section logging LOGGING + +The level of logging output of the various command line tools and underlying +libraries can be specified by the user. By default, only errors and warnings +are written to the standard error stream. Using option \e --verbose also +informational messages like processing details are reported. Option +\e --debug can be used to get more details on the internal activity, e.g. for +debugging purposes. Other logging levels can be selected using option +\e --log-level. In \e --quiet mode only fatal errors are reported. In such +very severe error events, the application will usually terminate. For more +details on the different logging levels, see documentation of module "oflog". + +In case the logging output should be written to file (optionally with logfile +rotation), to syslog (Unix) or the event log (Windows) option \e --log-config +can be used. This configuration file also allows for directing only certain +messages to a particular output stream and for filtering certain messages +based on the module or application where they are generated. An example +configuration file is provided in \/logger.cfg. + +\section command_line COMMAND LINE + +All command line tools use the following notation for parameters: square +brackets enclose optional values (0-1), three trailing dots indicate that +multiple values are allowed (1-n), a combination of both means 0 to n values. + +Command line options are distinguished from parameters by a leading '+' or '-' +sign, respectively. Usually, order and position of command line options are +arbitrary (i.e. they can appear anywhere). However, if options are mutually +exclusive the rightmost appearance is used. This behavior conforms to the +standard evaluation rules of common Unix shells. + +In addition, one or more command files can be specified using an '@' sign as a +prefix to the filename (e.g. \@command.txt). Such a command argument +is replaced by the content of the corresponding text file (multiple +whitespaces are treated as a single separator unless they appear between two +quotation marks) prior to any further evaluation. Please note that a command +file cannot contain another command file. This simple but effective approach +allows one to summarize common combinations of options/parameters and avoids +longish and confusing command lines (an example is provided in file +\/dumppat.txt). + +\section environment ENVIRONMENT + +The \b dcmj2pnm utility will attempt to load DICOM data dictionaries specified +in the \e DCMDICTPATH environment variable. By default, i.e. if the +\e DCMDICTPATH environment variable is not set, the file +\/dicom.dic will be loaded unless the dictionary is built +into the application (default for Windows). + +The default behavior should be preferred and the \e DCMDICTPATH environment +variable only used when alternative data dictionaries are required. The +\e DCMDICTPATH environment variable has the same format as the Unix shell +\e PATH variable in that a colon (":") separates entries. On Windows systems, +a semicolon (";") is used as a separator. The data dictionary code will +attempt to load each file specified in the \e DCMDICTPATH environment variable. +It is an error if no data dictionary can be loaded. + +\section files FILES + +\/camera.lut - sample characteristics file of a camera +\n\/monitor.lut - sample characteristics file of a monitor +\n\/printer.lut - sample characteristics file of a printer +\n\/scanner.lut - sample characteristics file of a scanner + +\section see_also SEE ALSO + +dcm2pnm(1), img2dcm(1) + +\section copyright COPYRIGHT + +Copyright (C) 2001-2014 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany. + +*/ diff --git a/dcmjpeg/docs/dcmjpeg.dox b/dcmjpeg/docs/dcmjpeg.dox new file mode 100644 index 00000000..b060942f --- /dev/null +++ b/dcmjpeg/docs/dcmjpeg.dox @@ -0,0 +1,77 @@ +/*! + +\page mod_dcmjpeg dcmjpeg: a compression/decompression library and utility apps + +This module contains classes that convert between uncompressed and JPEG +compressed representations (transfer syntaxes) of a DICOM image object. +Both lossless and lossy JPEG processes are supported. This module implements +a family of codecs that are derived from class DcmCodec and can be registered +in the codec list maintained in module dcmdata. + +The main interface classes are: +\li \b DJEncoderRegistration +\li \b DJDecoderRegistration +\li \b DJCodecEncoder +\li \b DJCodecDecoder + +\section Tools + +This module contains the following command line tools: +\li \ref dcmcjpeg +\li \ref dcmdjpeg +\li \ref dcmj2pnm +\li \ref dcmmkdir + +\section Examples + +The following example shows how to compress a DICOM image file with lossless JPEG: + +\code +DJEncoderRegistration::registerCodecs(); // register JPEG codecs +DcmFileFormat fileformat; +if (fileformat.loadFile("test.dcm").good()) +{ + DcmDataset *dataset = fileformat.getDataset(); + DcmItem *metaInfo = fileformat.getMetaInfo(); + DJ_RPLossless params; // codec parameters, we use the defaults + + // this causes the lossless JPEG version of the dataset to be created + dataset->chooseRepresentation(EXS_JPEGProcess14SV1, ¶ms); + + // check if everything went well + if (dataset->canWriteXfer(EXS_JPEGProcess14SV1)) + { + // force the meta-header UIDs to be re-generated when storing the file + // since the UIDs in the data set may have changed + delete metaInfo->remove(DCM_MediaStorageSOPClassUID); + delete metaInfo->remove(DCM_MediaStorageSOPInstanceUID); + + // store in lossless JPEG format + fileformat.saveFile("test_jpeg.dcm", EXS_JPEGProcess14SV1); + } +} +DJEncoderRegistration::cleanup(); // deregister JPEG codecs +\endcode + +The following example shows how to decompress a JPEG-compressed DICOM image file: + +\code +DJDecoderRegistration::registerCodecs(); // register JPEG codecs +DcmFileFormat fileformat; +if (fileformat.loadFile("test_jpeg.dcm").good()) +{ + DcmDataset *dataset = fileformat.getDataset(); + + // decompress data set if compressed + dataset->chooseRepresentation(EXS_LittleEndianExplicit, NULL); + + // check if everything went well + if (dataset->canWriteXfer(EXS_LittleEndianExplicit)) + { + fileformat.saveFile("test_decompressed.dcm", EXS_LittleEndianExplicit); + } +} +DJDecoderRegistration::cleanup(); // deregister JPEG codecs +\endcode + +*/ diff --git a/dcmjpeg/docs/dcmmkdir.man b/dcmjpeg/docs/dcmmkdir.man new file mode 100644 index 00000000..60bd2998 --- /dev/null +++ b/dcmjpeg/docs/dcmmkdir.man @@ -0,0 +1,464 @@ +/*! + +\if MANPAGES +\page dcmmkdir Create a DICOMDIR file +\else +\page dcmmkdir dcmmkdir: Create a DICOMDIR file +\endif + +\section synopsis SYNOPSIS + +\verbatim +dcmmkdir [options] [dcmfile-in...] +\endverbatim + +\section description DESCRIPTION + +The \b dcmmkdir utility creates a \e DICOMDIR file from the specified +referenced DICOM files according to the DICOM Part 11 Media Storage Application +Profiles. + +Currently the following profiles are supported (others might be added later): + +\li General Purpose CD-R Interchange (STD-GEN-CD) +\li General Purpose Interchange on DVD-RAM Media (STD-GEN-DVD-RAM) +\li General Purpose DVD Interchange with JPEG (STD-GEN-DVD-JPEG) +\li General Purpose DVD Interchange with JPEG 2000 (STD-GEN-DVD-J2K) +\li General Purpose BD Interchange with JPEG (STD-GEN-BD-JPEG) +\li General Purpose BD Interchange with JPEG 2000 (STD-GEN-BD-J2K) +\li General Purpose BD Interchange with MPEG2 MP\@ML (STD-GEN-BD-MPEG2-MPML) +\li General Purpose BD Interchange with MPEG2 MP\@HL (STD-GEN-BD-MPEG2-MPHL) +\li General Purpose BD Interchange with MPEG-4 AVC/H.264 HiP\@Level4.1 + (STD-GEN-BD-MPEG4-HPLV41) +\li General Purpose BD Interchange with MPEG-4 AVC/H.264 BD-Compatible + HiP\@Level4.1 (STD-GEN-BD-MPEG4-HPLV41BD) +\li General Purpose USB and Flash Memory Interchange with JPEG + (STD-GEN-USB/MMC/CF/SD-JPEG) +\li General Purpose USB and Flash Memory Interchange with JPEG 2000 + (STD-GEN-USB/MMC/CF/SD-J2K) +\li General Purpose MIME Interchange (STD-GEN-MIME) +\li DVD Interchange with MPEG2 MP\@ML (STD-DVD-MPEG2-MPML) +\li Basic Cardiac X-Ray Angiographic Studies on CD-R Media (STD-XABC-CD) +\li 1024 X-Ray Angiographic Studies on CD-R Media (STD-XA1K-CD) +\li 1024 X-Ray Angiographic Studies on DVD Media (STD-XA1K-DVD) +\li Dental Radiograph Interchange (STD-DEN-CD) +\li CT/MR Studies on various Media (STD-CTMR-xxxx) +\li Ultrasound Single Frame for Image Display (STD-US-ID-SF-xxxx) +\li Ultrasound Single Frame with Spatial Calibration (STD-US-SC-SF-xxxx) +\li Ultrasound Single Frame with Combined Calibration (STD-US-CC-SF-xxxx) +\li Ultrasound Single & Multi-Frame for Image Display (STD-US-ID-MF-xxxx) +\li Ultrasound Single & Multi-Frame with Spatial Calibration + (STD-US-SC-MF-xxxx) +\li Ultrasound Single & Multi-Frame with Combined Calibration + (STD-US-CC-MF-xxxx) +\li 12-lead ECG Interchange on Diskette (STD-WVFM-ECG-FD) +\li Hemodynamic Waveform Interchange on Diskette (STD-WVFM-HD-FD) + +This tool extends \b dcmgpdir which can only create General Purpose \e DICOMDIR +files. The default behavior of \b dcmmkdir (with \e --general-purpose) is +equivalent to that of \b dcmgpdir. + +\section parameters PARAMETERS + +\verbatim +dcmfile-in referenced DICOM file (or directory to be scanned) +\endverbatim + +\section options OPTIONS +\subsection general_options general options +\verbatim + -h --help + print this help text and exit + + --version + print version information and exit + + --arguments + print expanded command line arguments + + -q --quiet + quiet mode, print no warnings and errors + + -v --verbose + verbose mode, print processing details + + -d --debug + debug mode, print debug information + + -ll --log-level [l]evel: string constant + (fatal, error, warn, info, debug, trace) + use level l for the logger + + -lc --log-config [f]ilename: string + use config file f for the logger +\endverbatim + +\subsection input_options input options +\verbatim +DICOMDIR identifiers: + + +F --fileset-id [i]d: string + use specific file-set ID + (default: DCMTK_MEDIA_DEMO, "" for none) + + +R --descriptor [f]ilename: string + add a file-set descriptor file ID + (e.g. README, default: no descriptor) + + +C --char-set [c]harset: string + add a specific character set for descriptor + (default: "ISO_IR 100" if descriptor present) + +reading: + + +id --input-directory [d]irectory: string + read referenced DICOM files from directory d + (default for --recurse: current directory) + + -m --keep-filenames + expect filenames to be in DICOM format (default) + + +m --map-filenames + map to DICOM filenames (lowercase->uppercase, + and remove trailing period) + + -r --no-recurse + do not recurse within directories (default) + + +r --recurse + recurse within filesystem directories + + +p --pattern [p]attern: string (only with --recurse) + pattern for filename matching (wildcards) + + # possibly not available on all systems +\endverbatim + +\subsection processing_options processing options +\verbatim +consistency check: + + -W --no-consistency-check + do not check files for consistency + + +W --warn-inconsist-files + warn about inconsistent files (default) + + -a --abort-inconsist-file + abort on first inconsistent file + +type 1 attributes: + + -I --strict + exit with error if DICOMDIR type 1 attributes + are missing in DICOM file (default) + + +I --invent + invent DICOMDIR type 1 attributes if missing in DICOM file + + +Ipi --invent-patient-id + invent new PatientID in case of inconsistent + PatientName attributes + +other checks: + + +Nrs --allow-retired-sop + allow retired SOP classes defined in previous editions + of the DICOM standard + + -Nxc --no-xfer-check + do not reject images with non-standard transfer syntax + (just warn) + + -Nec --no-encoding-check + do not reject images with non-standard pixel encoding + (just warn) + + -Nrc --no-resolution-check + do not reject images with non-standard spatial resolution + (just warn) + +icon images: + + +X --add-icon-image + add monochrome icon image on IMAGE level + (default for cardiac profiles) + + -Xs --icon-image-size [s]ize: integer (1..128) + width and height of the icon image (in pixel) + (fixed: 128 for XA, 64 for CT/MR profile) + + -Xi --icon-file-prefix [p]refix: string + use PGM image 'prefix'+'dcmfile-in' as icon + (default: create icon from DICOM image) + + -Xd --default-icon [f]ilename: string + use specified PGM image if icon cannot be + created automatically (default: black image) +\endverbatim + +\subsection output_options output options +\verbatim +DICOMDIR file: + + +D --output-file [f]ilename: string + generate specific DICOMDIR file + (default: DICOMDIR in current directory) + +profiles: + + -Pgp --general-purpose + General Purpose Interchange on CD-R or DVD-RAM Media + (STD-GEN-CD/DVD-RAM, default) + + -Pdv --general-dvd-jpeg + General Purpose DVD Interchange with JPEG + (STD-GEN-DVD-JPEG) + + -Pd2 --general-dvd-j2k + General Purpose DVD Interchange with JPEG 2000 + (STD-GEN-DVD-J2K) + + -Pbd --general-bd-jpeg + General Purpose BD Interchange with JPEG + (STD-GEN-BD-JPEG) + + -Pb2 --general-bd-j2k + General Purpose BD Interchange with JPEG 2000 + (STD-GEN-BD-J2K) + + -Pbm --general-bd-mpeg2-mpml + General Purpose BD Interchange with MPEG2 MP@ML + (STD-GEN-BD-MPEG2-MPML) + + -Pbh --general-bd-mpeg2-mphl + General Purpose BD Interchange with MPEG2 MP@HL + (STD-GEN-BD-MPEG2-MPHL) + + -Pba --general-bd-mpeg4-hp + General Purpose BD Interchange with MPEG-4 AVC/H.264 + HiP@Level4.1 (STD-GEN-BD-MPEG4-HPLV41) + + -Pbb --general-bd-mpeg4-hpbd + General Purpose BD Interchange with MPEG-4 AVC/H.264 + BD-Compatible HiP@Level4.1 (STD-GEN-BD-MPEG4-HPLV41BD) + + -Pfl --usb-and-flash-jpeg + General Purpose USB/Flash Memory Interchange with JPEG + (STD-GEN-USB/MMC/CF/SD-JPEG) + + -Pf2 --usb-and-flash-j2k + General Purpose USB/Flash Memory Interchange with JPEG 2000 + (STD-GEN-USB/MMC/CF/SD-J2K) + + -Pmi --general-mime + General Purpose MIME Interchange (STD-GEN-MIME) + + -Pmp --mpeg2-mpml-dvd + DVD Interchange with MPEG2 Main Profile @ Main Level + (STD-DVD-MPEG2-MPML) + + -Pbc --basic-cardiac + Basic Cardiac X-Ray Angiographic Studies on CD-R Media + (STD-XABC-CD) + + -Pxa --xray-angiographic + 1024 X-Ray Angiographic Studies on CD-R Media + (STD-XA1K-CD) + + -Pxd --xray-angiographic-dvd + 1024 X-Ray Angiographic Studies on DVD Media + (STD-XA1K-DVD) + + -Pde --dental-radiograph + Dental Radiograph Interchange (STD-DEN-CD) + + -Pcm --ct-and-mr + CT/MR Studies (STD-CTMR-xxxx) + + -Pus --ultrasound-id-sf + Ultrasound Single Frame for Image Display + (STD-US-ID-SF-xxxx) + + --ultrasound-sc-sf + Ultrasound Single Frame with Spatial Calibration + (STD-US-SC-SF-xxxx) + + --ultrasound-cc-sf + Ultrasound Single Frame with Combined Calibration + (STD-US-CC-SF-xxxx) + + -Pum --ultrasound-id-mf + Ultrasound Single & Multi-Frame for Image Display + (STD-US-ID-MF-xxxx) + + --ultrasound-sc-mf + Ultrasound Single & Multi-Frame with Spatial Calibration + (STD-UD-SC-MF-xxxx) + + --ultrasound-cc-mf + Ultrasound Single & Multi-Frame with Combined Calibration + (STD-UD-CC-MF-xxxx) + + -Pec --12-lead-ecg + 12-lead ECG Interchange on Diskette + (STD-WVFM-ECG-FD) + + -Phd --hemodynamic-waveform + Hemodynamic Waveform Interchange on Diskette + (STD-WVFM-HD-FD) + +writing: + + -A --replace + replace existing DICOMDIR (default) + + +A --append + append to existing DICOMDIR + + +U --update + update existing DICOMDIR + + -w --discard + do not write out DICOMDIR + +backup: + + --create-backup + create a backup of existing DICOMDIR (default) + + -nb --no-backup + do not create a backup of existing DICOMDIR + +post-1993 value representations: + + +u --enable-new-vr + enable support for new VRs (UN/UT) (default) + + -u --disable-new-vr + disable support for new VRs, convert to OB + +group length encoding: + + -g --group-length-remove + write without group length elements (default) + + +g --group-length-create + write with group length elements + +length encoding in sequences and items: + + +e --length-explicit + write with explicit lengths (default) + + -e --length-undefined + write with undefined lengths +\endverbatim + +\section notes NOTES + +All files specified on the command line (or discovered by recursively examining +the contents of directories with the \e +r option) are first evaluated for +their compatibility with the specified Media Storage Application Profile (Part +11). Only appropriate files encoded using one of the allowed Transfer Syntaxes +will be accepted. Files having invalid filenames will be rejected (the rules +can be relaxed via the \e +m option). Files missing required attributes will +be rejected (the \e +I option can relax this behavior). + +A \e DICOMDIR file will only be constructed if all files have passed initial +tests. + +The \b dcmmkdir utility also allows one to append new entries to and to update +existing entries in a \e DICOMDIR file. Using option \e +A new entries are +only appended to the DICOMDIR, i.e. existing records like the ones for PATIENT +information are not updated. Using option \e +U also existing records are +updated according to the information found in the referenced DICOM files. +Please note that this update process might be slower than just appending new +entries. However, it makes sure that additional information that is required +for the selected application profile is also added to existing records. + +The support for icon images is currently restricted to monochrome images. +This might change in the future. Till then, color images are automatically +converted to grayscale mode. The icon size is 128*128 pixels for the cardiac +profiles (as required by the DICOM standard) and 64*64 for all others. + +\subsection scanning_directories Scanning Directories + +Adding files from directories is possible by using option \e --recurse. If no +further command line parameters are given, the directory specified by option +\e --input-directory (default: current directory) is scanned for files. If +parameters are given, they can either specify a file or directory name; the +input directory is always prepended. If the files in the provided directories +should be selected according to a specific name pattern (e.g. using wildcard +matching), option \e --pattern has to be used. Please note that this file +pattern only applies to the files within the scanned directories, and, if any +other patterns are specified on the command line outside the +\e --input-directory option (e.g. in order to select further files), these do +not apply to the specified directories. + +\section logging LOGGING + +The level of logging output of the various command line tools and underlying +libraries can be specified by the user. By default, only errors and warnings +are written to the standard error stream. Using option \e --verbose also +informational messages like processing details are reported. Option +\e --debug can be used to get more details on the internal activity, e.g. for +debugging purposes. Other logging levels can be selected using option +\e --log-level. In \e --quiet mode only fatal errors are reported. In such +very severe error events, the application will usually terminate. For more +details on the different logging levels, see documentation of module "oflog". + +In case the logging output should be written to file (optionally with logfile +rotation), to syslog (Unix) or the event log (Windows) option \e --log-config +can be used. This configuration file also allows for directing only certain +messages to a particular output stream and for filtering certain messages +based on the module or application where they are generated. An example +configuration file is provided in \/logger.cfg. + +\section command_line COMMAND LINE + +All command line tools use the following notation for parameters: square +brackets enclose optional values (0-1), three trailing dots indicate that +multiple values are allowed (1-n), a combination of both means 0 to n values. + +Command line options are distinguished from parameters by a leading '+' or '-' +sign, respectively. Usually, order and position of command line options are +arbitrary (i.e. they can appear anywhere). However, if options are mutually +exclusive the rightmost appearance is used. This behavior conforms to the +standard evaluation rules of common Unix shells. + +In addition, one or more command files can be specified using an '@' sign as a +prefix to the filename (e.g. \@command.txt). Such a command argument +is replaced by the content of the corresponding text file (multiple +whitespaces are treated as a single separator unless they appear between two +quotation marks) prior to any further evaluation. Please note that a command +file cannot contain another command file. This simple but effective approach +allows one to summarize common combinations of options/parameters and avoids +longish and confusing command lines (an example is provided in file +\/dumppat.txt). + +\section environment ENVIRONMENT + +The \b dcmmkdir utility will attempt to load DICOM data dictionaries specified +in the \e DCMDICTPATH environment variable. By default, i.e. if the +\e DCMDICTPATH environment variable is not set, the file +\/dicom.dic will be loaded unless the dictionary is built +into the application (default for Windows). + +The default behavior should be preferred and the \e DCMDICTPATH environment +variable only used when alternative data dictionaries are required. The +\e DCMDICTPATH environment variable has the same format as the Unix shell +\e PATH variable in that a colon (":") separates entries. On Windows systems, +a semicolon (";") is used as a separator. The data dictionary code will +attempt to load each file specified in the \e DCMDICTPATH environment variable. +It is an error if no data dictionary can be loaded. + +\section see_also SEE ALSO + +dcmgpdir(1) + +\section copyright COPYRIGHT + +Copyright (C) 2001-2014 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany. + +*/ diff --git a/dcmjpeg/docs/ijg_filelist.txt b/dcmjpeg/docs/ijg_filelist.txt new file mode 100644 index 00000000..9ba88e00 --- /dev/null +++ b/dcmjpeg/docs/ijg_filelist.txt @@ -0,0 +1,239 @@ +IJG JPEG LIBRARY: FILE LIST + +Copyright (C) 1994-1997, Thomas G. Lane. +This file is part of the Independent JPEG Group's software. +For conditions of distribution and use, see the accompanying README file. + + +Here is a road map to the files in the IJG JPEG distribution. The +distribution includes the JPEG library proper, plus two application +programs ("cjpeg" and "djpeg") which use the library to convert JPEG +files to and from some other popular image formats. A third application +"jpegtran" uses the library to do lossless conversion between different +variants of JPEG. There are also two stand-alone applications, +"rdjpgcom" and "wrjpgcom". + + +THE JPEG LIBRARY +================ + +Include files: + +jpeglib.h JPEG library's exported data and function declarations. +jconfig.h Configuration declarations. Note: this file is not present + in the distribution; it is generated during installation. +jmorecfg.h Additional configuration declarations; need not be changed + for a standard installation. +jerror.h Declares JPEG library's error and trace message codes. +jinclude.h Central include file used by all IJG .c files to reference + system include files. +jpegint.h JPEG library's internal data structures. +jlossls.h JPEG library's lossless codec data structures. +jlossy.h JPEG library's lossy codec structures. +jchuff.h Private declarations for Huffman encoder modules. +jdhuff.h Private declarations for Huffman decoder modules. +jdct.h Private declarations for forward & reverse DCT subsystems. +jmemsys.h Private declarations for memory management subsystem. +jversion.h Version information. + +Applications using the library should include jpeglib.h (which in turn +includes jconfig.h and jmorecfg.h). Optionally, jerror.h may be included +if the application needs to reference individual JPEG error codes. The +other include files are intended for internal use and would not normally +be included by an application program. (cjpeg/djpeg/etc do use jinclude.h, +since its function is to improve portability of the whole IJG distribution. +Most other applications will directly include the system include files they +want, and hence won't need jinclude.h.) + + +C source code files: + +These files contain most of the functions intended to be called directly by +an application program: + +jcapimin.c Application program interface: core routines for compression. +jcapistd.c Application program interface: standard compression. +jdapimin.c Application program interface: core routines for decompression. +jdapistd.c Application program interface: standard decompression. +jcomapi.c Application program interface routines common to compression + and decompression. +jcparam.c Compression parameter setting helper routines. +jctrans.c API and library routines for transcoding compression. +jdtrans.c API and library routines for transcoding decompression. + +Compression side of the library: + +jcinit.c Initialization: determines which other modules to use. +jcmaster.c Master control: setup and inter-pass sequencing logic. +jcmainct.c Main buffer controller (preprocessor => JPEG compressor). +jchuff.c Codec-independent Huffman entropy encoding routines. +jcprepct.c Preprocessor buffer controller. +jccolor.c Color space conversion. +jcsample.c Downsampling. +jcmarker.c JPEG marker writing. +jdatadst.c Data destination manager for stdio output. + +Lossy (DCT) codec: + +jlossy.c Lossy compressor proper. +jccoefct.c Buffer controller for DCT coefficient buffer. +jcdctmgr.c DCT manager (DCT implementation selection & control). +jfdctint.c Forward DCT using slow-but-accurate integer method. +jfdctfst.c Forward DCT using faster, less accurate integer method. +jfdctflt.c Forward DCT using floating-point arithmetic. +jcshuff.c Huffman entropy coding for sequential JPEG. +jcphuff.c Huffman entropy coding for progressive JPEG. + +Lossless (spatial) codec: + +jclossls.c Lossless compressor proper. +jcdiffct.c Buffer controller for difference buffer. +jcscale.c Point transformation. +jcpred.c Sample predictor and differencer. +jclhuff.c Huffman entropy encoding for lossless JPEG. + +Decompression side of the library: + +jdmaster.c Master control: determines which other modules to use. +jdinput.c Input controller: controls input processing modules. +jdmainct.c Main buffer controller (JPEG decompressor => postprocessor). +jdhuff.c Codec-independent Huffman entropy decoding routines. +jdpostct.c Postprocessor buffer controller. +jdmarker.c JPEG marker reading. +jdsample.c Upsampling. +jdcolor.c Color space conversion. +jdmerge.c Merged upsampling/color conversion (faster, lower quality). +jquant1.c One-pass color quantization using a fixed-spacing colormap. +jquant2.c Two-pass color quantization using a custom-generated colormap. + Also handles one-pass quantization to an externally given map. +jdatasrc.c Data source manager for stdio input. + +Lossy (DCT) codec: + +jdlossy.c Lossy decompressor proper. +jdcoefct.c Buffer controller for DCT coefficient buffer. +jdshuff.c Huffman entropy decoding for sequential JPEG. +jdphuff.c Huffman entropy decoding for progressive JPEG. +jddctmgr.c IDCT manager (IDCT implementation selection & control). +jidctint.c Inverse DCT using slow-but-accurate integer method. +jidctfst.c Inverse DCT using faster, less accurate integer method. +jidctflt.c Inverse DCT using floating-point arithmetic. +jidctred.c Inverse DCTs with reduced-size outputs. + +Lossless (spatial) codec: + +jdlossls.c Lossless decompressor proper. +jddiffct.c Buffer controller for difference buffers. +jdlhuff.c Huffman entropy decoding for lossless JPEG. +jdpred.c Sample predictor and undifferencer. +jdscale.c Point transformation, sample size scaling. + +Support files for both compression and decompression: + +jerror.c Standard error handling routines (application replaceable). +jmemmgr.c System-independent (more or less) memory management code. +jcodec.c Codec-independent utility routines. +jutils.c Miscellaneous utility routines. + +jmemmgr.c relies on a system-dependent memory management module. The IJG +distribution includes the following implementations of the system-dependent +module: + +jmemnobs.c "No backing store": assumes adequate virtual memory exists. +jmemansi.c Makes temporary files with ANSI-standard routine tmpfile(). +jmemname.c Makes temporary files with program-generated file names. +jmemdos.c Custom implementation for MS-DOS (16-bit environment only): + can use extended and expanded memory as well as temp files. +jmemmac.c Custom implementation for Apple Macintosh. + +Exactly one of the system-dependent modules should be configured into an +installed JPEG library (see install.doc for hints about which one to use). +On unusual systems you may find it worthwhile to make a special +system-dependent memory manager. + + +Non-C source code files: + +jmemdosa.asm 80x86 assembly code support for jmemdos.c; used only in + MS-DOS-specific configurations of the JPEG library. + + +CJPEG/DJPEG/JPEGTRAN +==================== + +Include files: + +cdjpeg.h Declarations shared by cjpeg/djpeg/jpegtran modules. +cderror.h Additional error and trace message codes for cjpeg et al. +transupp.h Declarations for jpegtran support routines in transupp.c. + +C source code files: + +cjpeg.c Main program for cjpeg. +djpeg.c Main program for djpeg. +jpegtran.c Main program for jpegtran. +cdjpeg.c Utility routines used by all three programs. +rdcolmap.c Code to read a colormap file for djpeg's "-map" switch. +rdswitch.c Code to process some of cjpeg's more complex switches. + Also used by jpegtran. +transupp.c Support code for jpegtran: lossless image manipulations. + +Image file reader modules for cjpeg: + +rdbmp.c BMP file input. +rdgif.c GIF file input (now just a stub). +rdppm.c PPM/PGM file input. +rdrle.c Utah RLE file input. +rdtarga.c Targa file input. + +Image file writer modules for djpeg: + +wrbmp.c BMP file output. +wrgif.c GIF file output (a mere shadow of its former self). +wrppm.c PPM/PGM file output. +wrrle.c Utah RLE file output. +wrtarga.c Targa file output. + + +RDJPGCOM/WRJPGCOM +================= + +C source code files: + +rdjpgcom.c Stand-alone rdjpgcom application. +wrjpgcom.c Stand-alone wrjpgcom application. + +These programs do not depend on the IJG library. They do use +jconfig.h and jinclude.h, only to improve portability. + + +ADDITIONAL FILES +================ + +Documentation (see README for a guide to the documentation files): + +README Master documentation file. +*.doc Other documentation files. +*.1 Documentation in Unix man page format. +change.log Version-to-version change highlights. +example.c Sample code for calling JPEG library. + +Configuration/installation files and programs (see install.doc for more info): + +configure Unix shell script to perform automatic configuration. +ltconfig Support scripts for configure (from GNU libtool). +ltmain.sh +config.guess +config.sub +install-sh Install shell script for those Unix systems lacking one. +ckconfig.c Program to generate jconfig.h on non-Unix systems. +jconfig.doc Template for making jconfig.h by hand. +makefile.* Sample makefiles for particular systems. +jconfig.* Sample jconfig.h for particular systems. +ansi2knr.c De-ANSIfier for pre-ANSI C compilers (courtesy of + L. Peter Deutsch and Aladdin Enterprises). + +Test files (see install.doc for test procedure): + +test*.* Source and comparison files for confidence test. + These are binary image files, NOT text files. diff --git a/dcmjpeg/docs/ijg_libjpeg.txt b/dcmjpeg/docs/ijg_libjpeg.txt new file mode 100644 index 00000000..20ce7b48 --- /dev/null +++ b/dcmjpeg/docs/ijg_libjpeg.txt @@ -0,0 +1,3011 @@ +USING THE IJG JPEG LIBRARY + +Copyright (C) 1994-1998, Thomas G. Lane. +This file is part of the Independent JPEG Group's software. +For conditions of distribution and use, see the accompanying README file. + + +This file describes how to use the IJG JPEG library within an application +program. Read it if you want to write a program that uses the library. + +The file example.c provides heavily commented skeleton code for calling the +JPEG library. Also see jpeglib.h (the include file to be used by application +programs) for full details about data structures and function parameter lists. +The library source code, of course, is the ultimate reference. + +Note that there have been *major* changes from the application interface +presented by IJG version 4 and earlier versions. The old design had several +inherent limitations, and it had accumulated a lot of cruft as we added +features while trying to minimize application-interface changes. We have +sacrificed backward compatibility in the version 5 rewrite, but we think the +improvements justify this. + + +TABLE OF CONTENTS +----------------- + +Overview: + Functions provided by the library + Outline of typical usage +Basic library usage: + Data formats + Compression details + Decompression details + Mechanics of usage: include files, linking, etc +Advanced features: + Compression parameter selection + Decompression parameter selection + Special color spaces + Error handling + Compressed data handling (source and destination managers) + I/O suspension + Progressive JPEG support + Buffered-image mode + Abbreviated datastreams and multiple images + Special markers + Raw (downsampled) image data + Really raw data: DCT coefficients + Progress monitoring + Memory management + Memory usage + Library compile-time options + Portability considerations + Notes for MS-DOS implementors + +You should read at least the overview and basic usage sections before trying +to program with the library. The sections on advanced features can be read +if and when you need them. + + +OVERVIEW +======== + +Functions provided by the library +--------------------------------- + +The IJG JPEG library provides C code to read and write JPEG-compressed image +files. The surrounding application program receives or supplies image data a +scanline at a time, using a straightforward uncompressed image format. All +details of color conversion and other preprocessing/postprocessing can be +handled by the library. + +The library includes a substantial amount of code that is not covered by the +JPEG standard but is necessary for typical applications of JPEG. These +functions preprocess the image before JPEG compression or postprocess it after +decompression. They include colorspace conversion, downsampling/upsampling, +and color quantization. The application indirectly selects use of this code +by specifying the format in which it wishes to supply or receive image data. +For example, if colormapped output is requested, then the decompression +library automatically invokes color quantization. + +A wide range of quality vs. speed tradeoffs are possible in JPEG processing, +and even more so in decompression postprocessing. The decompression library +provides multiple implementations that cover most of the useful tradeoffs, +ranging from very-high-quality down to fast-preview operation. On the +compression side we have generally not provided low-quality choices, since +compression is normally less time-critical. It should be understood that the +low-quality modes may not meet the JPEG standard's accuracy requirements; +nonetheless, they are useful for viewers. + +A word about functions *not* provided by the library. We handle a subset of +the ISO JPEG standard; most baseline, extended-sequential, and progressive +JPEG processes are supported. (Our subset includes all features now in common +use.) Unsupported ISO options include: + * Hierarchical storage + * Arithmetic entropy coding (unsupported for legal reasons) + * DNL marker + * Nonintegral subsampling ratios +We support both 8- and 12-bit data precision, but this is a compile-time +choice rather than a run-time choice; hence it is difficult to use both +precisions in a single application. + +By itself, the library handles only interchange JPEG datastreams --- in +particular the widely used JFIF file format. The library can be used by +surrounding code to process interchange or abbreviated JPEG datastreams that +are embedded in more complex file formats. (For example, this library is +used by the free LIBTIFF library to support JPEG compression in TIFF.) + + +Outline of typical usage +------------------------ + +The rough outline of a JPEG compression operation is: + + Allocate and initialize a JPEG compression object + Specify the destination for the compressed data (eg, a file) + Set parameters for compression, including image size & colorspace + jpeg_start_compress(...); + while (scan lines remain to be written) + jpeg_write_scanlines(...); + jpeg_finish_compress(...); + Release the JPEG compression object + +A JPEG compression object holds parameters and working state for the JPEG +library. We make creation/destruction of the object separate from starting +or finishing compression of an image; the same object can be re-used for a +series of image compression operations. This makes it easy to re-use the +same parameter settings for a sequence of images. Re-use of a JPEG object +also has important implications for processing abbreviated JPEG datastreams, +as discussed later. + +The image data to be compressed is supplied to jpeg_write_scanlines() from +in-memory buffers. If the application is doing file-to-file compression, +reading image data from the source file is the application's responsibility. +The library emits compressed data by calling a "data destination manager", +which typically will write the data into a file; but the application can +provide its own destination manager to do something else. + +Similarly, the rough outline of a JPEG decompression operation is: + + Allocate and initialize a JPEG decompression object + Specify the source of the compressed data (eg, a file) + Call jpeg_read_header() to obtain image info + Set parameters for decompression + jpeg_start_decompress(...); + while (scan lines remain to be read) + jpeg_read_scanlines(...); + jpeg_finish_decompress(...); + Release the JPEG decompression object + +This is comparable to the compression outline except that reading the +datastream header is a separate step. This is helpful because information +about the image's size, colorspace, etc is available when the application +selects decompression parameters. For example, the application can choose an +output scaling ratio that will fit the image into the available screen size. + +The decompression library obtains compressed data by calling a data source +manager, which typically will read the data from a file; but other behaviors +can be obtained with a custom source manager. Decompressed data is delivered +into in-memory buffers passed to jpeg_read_scanlines(). + +It is possible to abort an incomplete compression or decompression operation +by calling jpeg_abort(); or, if you do not need to retain the JPEG object, +simply release it by calling jpeg_destroy(). + +JPEG compression and decompression objects are two separate struct types. +However, they share some common fields, and certain routines such as +jpeg_destroy() can work on either type of object. + +The JPEG library has no static variables: all state is in the compression +or decompression object. Therefore it is possible to process multiple +compression and decompression operations concurrently, using multiple JPEG +objects. + +Both compression and decompression can be done in an incremental memory-to- +memory fashion, if suitable source/destination managers are used. See the +section on "I/O suspension" for more details. + + +BASIC LIBRARY USAGE +=================== + +Data formats +------------ + +Before diving into procedural details, it is helpful to understand the +image data format that the JPEG library expects or returns. + +The standard input image format is a rectangular array of pixels, with each +pixel having the same number of "component" or "sample" values (color +channels). You must specify how many components there are and the colorspace +interpretation of the components. Most applications will use RGB data +(three components per pixel) or grayscale data (one component per pixel). +PLEASE NOTE THAT RGB DATA IS THREE SAMPLES PER PIXEL, GRAYSCALE ONLY ONE. +A remarkable number of people manage to miss this, only to find that their +programs don't work with grayscale JPEG files. + +There is no provision for colormapped input. JPEG files are always full-color +or full grayscale (or sometimes another colorspace such as CMYK). You can +feed in a colormapped image by expanding it to full-color format. However +JPEG often doesn't work very well with source data that has been colormapped, +because of dithering noise. This is discussed in more detail in the JPEG FAQ +and the other references mentioned in the README file. + +Pixels are stored by scanlines, with each scanline running from left to +right. The component values for each pixel are adjacent in the row; for +example, R,G,B,R,G,B,R,G,B,... for 24-bit RGB color. Each scanline is an +array of data type JSAMPLE --- which is typically "unsigned char", unless +you've changed jmorecfg.h. (You can also change the RGB pixel layout, say +to B,G,R order, by modifying jmorecfg.h. But see the restrictions listed in +that file before doing so.) + +A 2-D array of pixels is formed by making a list of pointers to the starts of +scanlines; so the scanlines need not be physically adjacent in memory. Even +if you process just one scanline at a time, you must make a one-element +pointer array to conform to this structure. Pointers to JSAMPLE rows are of +type JSAMPROW, and the pointer to the pointer array is of type JSAMPARRAY. + +The library accepts or supplies one or more complete scanlines per call. +It is not possible to process part of a row at a time. Scanlines are always +processed top-to-bottom. You can process an entire image in one call if you +have it all in memory, but usually it's simplest to process one scanline at +a time. + +For best results, source data values should have the precision specified by +BITS_IN_JSAMPLE (normally 8 bits). For instance, if you choose to compress +data that's only 6 bits/channel, you should left-justify each value in a +byte before passing it to the compressor. If you need to compress data +that has more than 8 bits/channel, compile with BITS_IN_JSAMPLE = 12. +(See "Library compile-time options", later.) + + +The data format returned by the decompressor is the same in all details, +except that colormapped output is supported. (Again, a JPEG file is never +colormapped. But you can ask the decompressor to perform on-the-fly color +quantization to deliver colormapped output.) If you request colormapped +output then the returned data array contains a single JSAMPLE per pixel; +its value is an index into a color map. The color map is represented as +a 2-D JSAMPARRAY in which each row holds the values of one color component, +that is, colormap[i][j] is the value of the i'th color component for pixel +value (map index) j. Note that since the colormap indexes are stored in +JSAMPLEs, the maximum number of colors is limited by the size of JSAMPLE +(ie, at most 256 colors for an 8-bit JPEG library). + + +Compression details +------------------- + +Here we revisit the JPEG compression outline given in the overview. + +1. Allocate and initialize a JPEG compression object. + +A JPEG compression object is a "struct jpeg_compress_struct". (It also has +a bunch of subsidiary structures which are allocated via malloc(), but the +application doesn't control those directly.) This struct can be just a local +variable in the calling routine, if a single routine is going to execute the +whole JPEG compression sequence. Otherwise it can be static or allocated +from malloc(). + +You will also need a structure representing a JPEG error handler. The part +of this that the library cares about is a "struct jpeg_error_mgr". If you +are providing your own error handler, you'll typically want to embed the +jpeg_error_mgr struct in a larger structure; this is discussed later under +"Error handling". For now we'll assume you are just using the default error +handler. The default error handler will print JPEG error/warning messages +on stderr, and it will call exit() if a fatal error occurs. + +You must initialize the error handler structure, store a pointer to it into +the JPEG object's "err" field, and then call jpeg_create_compress() to +initialize the rest of the JPEG object. + +Typical code for this step, if you are using the default error handler, is + + struct jpeg_compress_struct cinfo; + struct jpeg_error_mgr jerr; + ... + cinfo.err = jpeg_std_error(&jerr); + jpeg_create_compress(&cinfo); + +jpeg_create_compress allocates a small amount of memory, so it could fail +if you are out of memory. In that case it will exit via the error handler; +that's why the error handler must be initialized first. + + +2. Specify the destination for the compressed data (eg, a file). + +As previously mentioned, the JPEG library delivers compressed data to a +"data destination" module. The library includes one data destination +module which knows how to write to a stdio stream. You can use your own +destination module if you want to do something else, as discussed later. + +If you use the standard destination module, you must open the target stdio +stream beforehand. Typical code for this step looks like: + + FILE * outfile; + ... + if ((outfile = fopen(filename, "wb")) == NULL) { + fprintf(stderr, "can't open %s\n", filename); + exit(1); + } + jpeg_stdio_dest(&cinfo, outfile); + +where the last line invokes the standard destination module. + +WARNING: it is critical that the binary compressed data be delivered to the +output file unchanged. On non-Unix systems the stdio library may perform +newline translation or otherwise corrupt binary data. To suppress this +behavior, you may need to use a "b" option to fopen (as shown above), or use +setmode() or another routine to put the stdio stream in binary mode. See +cjpeg.c and djpeg.c for code that has been found to work on many systems. + +You can select the data destination after setting other parameters (step 3), +if that's more convenient. You may not change the destination between +calling jpeg_start_compress() and jpeg_finish_compress(). + + +3. Set parameters for compression, including image size & colorspace. + +You must supply information about the source image by setting the following +fields in the JPEG object (cinfo structure): + + image_width Width of image, in pixels + image_height Height of image, in pixels + input_components Number of color channels (samples per pixel) + in_color_space Color space of source image + +The image dimensions are, hopefully, obvious. JPEG supports image dimensions +of 1 to 64K pixels in either direction. The input color space is typically +RGB or grayscale, and input_components is 3 or 1 accordingly. (See "Special +color spaces", later, for more info.) The in_color_space field must be +assigned one of the J_COLOR_SPACE enum constants, typically JCS_RGB or +JCS_GRAYSCALE. + +JPEG has a large number of compression parameters that determine how the +image is encoded. Most applications don't need or want to know about all +these parameters. You can set all the parameters to reasonable defaults by +calling jpeg_set_defaults(); then, if there are particular values you want +to change, you can do so after that. The "Compression parameter selection" +section tells about all the parameters. + +You must set in_color_space correctly before calling jpeg_set_defaults(), +because the defaults depend on the source image colorspace. However the +other three source image parameters need not be valid until you call +jpeg_start_compress(). There's no harm in calling jpeg_set_defaults() more +than once, if that happens to be convenient. + +Typical code for a 24-bit RGB source image is + + cinfo.image_width = Width; /* image width and height, in pixels */ + cinfo.image_height = Height; + cinfo.input_components = 3; /* # of color components per pixel */ + cinfo.in_color_space = JCS_RGB; /* colorspace of input image */ + + jpeg_set_defaults(&cinfo); + /* Make optional parameter settings here */ + + +4. jpeg_start_compress(...); + +After you have established the data destination and set all the necessary +source image info and other parameters, call jpeg_start_compress() to begin +a compression cycle. This will initialize internal state, allocate working +storage, and emit the first few bytes of the JPEG datastream header. + +Typical code: + + jpeg_start_compress(&cinfo, TRUE); + +The "TRUE" parameter ensures that a complete JPEG interchange datastream +will be written. This is appropriate in most cases. If you think you might +want to use an abbreviated datastream, read the section on abbreviated +datastreams, below. + +Once you have called jpeg_start_compress(), you may not alter any JPEG +parameters or other fields of the JPEG object until you have completed +the compression cycle. + + +5. while (scan lines remain to be written) + jpeg_write_scanlines(...); + +Now write all the required image data by calling jpeg_write_scanlines() +one or more times. You can pass one or more scanlines in each call, up +to the total image height. In most applications it is convenient to pass +just one or a few scanlines at a time. The expected format for the passed +data is discussed under "Data formats", above. + +Image data should be written in top-to-bottom scanline order. The JPEG spec +contains some weasel wording about how top and bottom are application-defined +terms (a curious interpretation of the English language...) but if you want +your files to be compatible with everyone else's, you WILL use top-to-bottom +order. If the source data must be read in bottom-to-top order, you can use +the JPEG library's virtual array mechanism to invert the data efficiently. +Examples of this can be found in the sample application cjpeg. + +The library maintains a count of the number of scanlines written so far +in the next_scanline field of the JPEG object. Usually you can just use +this variable as the loop counter, so that the loop test looks like +"while (cinfo.next_scanline < cinfo.image_height)". + +Code for this step depends heavily on the way that you store the source data. +example.c shows the following code for the case of a full-size 2-D source +array containing 3-byte RGB pixels: + + JSAMPROW row_pointer[1]; /* pointer to a single row */ + int row_stride; /* physical row width in buffer */ + + row_stride = image_width * 3; /* JSAMPLEs per row in image_buffer */ + + while (cinfo.next_scanline < cinfo.image_height) { + row_pointer[0] = & image_buffer[cinfo.next_scanline * row_stride]; + jpeg_write_scanlines(&cinfo, row_pointer, 1); + } + +jpeg_write_scanlines() returns the number of scanlines actually written. +This will normally be equal to the number passed in, so you can usually +ignore the return value. It is different in just two cases: + * If you try to write more scanlines than the declared image height, + the additional scanlines are ignored. + * If you use a suspending data destination manager, output buffer overrun + will cause the compressor to return before accepting all the passed lines. + This feature is discussed under "I/O suspension", below. The normal + stdio destination manager will NOT cause this to happen. +In any case, the return value is the same as the change in the value of +next_scanline. + + +6. jpeg_finish_compress(...); + +After all the image data has been written, call jpeg_finish_compress() to +complete the compression cycle. This step is ESSENTIAL to ensure that the +last bufferload of data is written to the data destination. +jpeg_finish_compress() also releases working memory associated with the JPEG +object. + +Typical code: + + jpeg_finish_compress(&cinfo); + +If using the stdio destination manager, don't forget to close the output +stdio stream (if necessary) afterwards. + +If you have requested a multi-pass operating mode, such as Huffman code +optimization, jpeg_finish_compress() will perform the additional passes using +data buffered by the first pass. In this case jpeg_finish_compress() may take +quite a while to complete. With the default compression parameters, this will +not happen. + +It is an error to call jpeg_finish_compress() before writing the necessary +total number of scanlines. If you wish to abort compression, call +jpeg_abort() as discussed below. + +After completing a compression cycle, you may dispose of the JPEG object +as discussed next, or you may use it to compress another image. In that case +return to step 2, 3, or 4 as appropriate. If you do not change the +destination manager, the new datastream will be written to the same target. +If you do not change any JPEG parameters, the new datastream will be written +with the same parameters as before. Note that you can change the input image +dimensions freely between cycles, but if you change the input colorspace, you +should call jpeg_set_defaults() to adjust for the new colorspace; and then +you'll need to repeat all of step 3. + + +7. Release the JPEG compression object. + +When you are done with a JPEG compression object, destroy it by calling +jpeg_destroy_compress(). This will free all subsidiary memory (regardless of +the previous state of the object). Or you can call jpeg_destroy(), which +works for either compression or decompression objects --- this may be more +convenient if you are sharing code between compression and decompression +cases. (Actually, these routines are equivalent except for the declared type +of the passed pointer. To avoid gripes from ANSI C compilers, jpeg_destroy() +should be passed a j_common_ptr.) + +If you allocated the jpeg_compress_struct structure from malloc(), freeing +it is your responsibility --- jpeg_destroy() won't. Ditto for the error +handler structure. + +Typical code: + + jpeg_destroy_compress(&cinfo); + + +8. Aborting. + +If you decide to abort a compression cycle before finishing, you can clean up +in either of two ways: + +* If you don't need the JPEG object any more, just call + jpeg_destroy_compress() or jpeg_destroy() to release memory. This is + legitimate at any point after calling jpeg_create_compress() --- in fact, + it's safe even if jpeg_create_compress() fails. + +* If you want to re-use the JPEG object, call jpeg_abort_compress(), or call + jpeg_abort() which works on both compression and decompression objects. + This will return the object to an idle state, releasing any working memory. + jpeg_abort() is allowed at any time after successful object creation. + +Note that cleaning up the data destination, if required, is your +responsibility; neither of these routines will call term_destination(). +(See "Compressed data handling", below, for more about that.) + +jpeg_destroy() and jpeg_abort() are the only safe calls to make on a JPEG +object that has reported an error by calling error_exit (see "Error handling" +for more info). The internal state of such an object is likely to be out of +whack. Either of these two routines will return the object to a known state. + + +Decompression details +--------------------- + +Here we revisit the JPEG decompression outline given in the overview. + +1. Allocate and initialize a JPEG decompression object. + +This is just like initialization for compression, as discussed above, +except that the object is a "struct jpeg_decompress_struct" and you +call jpeg_create_decompress(). Error handling is exactly the same. + +Typical code: + + struct jpeg_decompress_struct cinfo; + struct jpeg_error_mgr jerr; + ... + cinfo.err = jpeg_std_error(&jerr); + jpeg_create_decompress(&cinfo); + +(Both here and in the IJG code, we usually use variable name "cinfo" for +both compression and decompression objects.) + + +2. Specify the source of the compressed data (eg, a file). + +As previously mentioned, the JPEG library reads compressed data from a "data +source" module. The library includes one data source module which knows how +to read from a stdio stream. You can use your own source module if you want +to do something else, as discussed later. + +If you use the standard source module, you must open the source stdio stream +beforehand. Typical code for this step looks like: + + FILE * infile; + ... + if ((infile = fopen(filename, "rb")) == NULL) { + fprintf(stderr, "can't open %s\n", filename); + exit(1); + } + jpeg_stdio_src(&cinfo, infile); + +where the last line invokes the standard source module. + +WARNING: it is critical that the binary compressed data be read unchanged. +On non-Unix systems the stdio library may perform newline translation or +otherwise corrupt binary data. To suppress this behavior, you may need to use +a "b" option to fopen (as shown above), or use setmode() or another routine to +put the stdio stream in binary mode. See cjpeg.c and djpeg.c for code that +has been found to work on many systems. + +You may not change the data source between calling jpeg_read_header() and +jpeg_finish_decompress(). If you wish to read a series of JPEG images from +a single source file, you should repeat the jpeg_read_header() to +jpeg_finish_decompress() sequence without reinitializing either the JPEG +object or the data source module; this prevents buffered input data from +being discarded. + + +3. Call jpeg_read_header() to obtain image info. + +Typical code for this step is just + + jpeg_read_header(&cinfo, TRUE); + +This will read the source datastream header markers, up to the beginning +of the compressed data proper. On return, the image dimensions and other +info have been stored in the JPEG object. The application may wish to +consult this information before selecting decompression parameters. + +More complex code is necessary if + * A suspending data source is used --- in that case jpeg_read_header() + may return before it has read all the header data. See "I/O suspension", + below. The normal stdio source manager will NOT cause this to happen. + * Abbreviated JPEG files are to be processed --- see the section on + abbreviated datastreams. Standard applications that deal only in + interchange JPEG files need not be concerned with this case either. + +It is permissible to stop at this point if you just wanted to find out the +image dimensions and other header info for a JPEG file. In that case, +call jpeg_destroy() when you are done with the JPEG object, or call +jpeg_abort() to return it to an idle state before selecting a new data +source and reading another header. + + +4. Set parameters for decompression. + +jpeg_read_header() sets appropriate default decompression parameters based on +the properties of the image (in particular, its colorspace). However, you +may well want to alter these defaults before beginning the decompression. +For example, the default is to produce full color output from a color file. +If you want colormapped output you must ask for it. Other options allow the +returned image to be scaled and allow various speed/quality tradeoffs to be +selected. "Decompression parameter selection", below, gives details. + +If the defaults are appropriate, nothing need be done at this step. + +Note that all default values are set by each call to jpeg_read_header(). +If you reuse a decompression object, you cannot expect your parameter +settings to be preserved across cycles, as you can for compression. +You must set desired parameter values each time. + + +5. jpeg_start_decompress(...); + +Once the parameter values are satisfactory, call jpeg_start_decompress() to +begin decompression. This will initialize internal state, allocate working +memory, and prepare for returning data. + +Typical code is just + + jpeg_start_decompress(&cinfo); + +If you have requested a multi-pass operating mode, such as 2-pass color +quantization, jpeg_start_decompress() will do everything needed before data +output can begin. In this case jpeg_start_decompress() may take quite a while +to complete. With a single-scan (non progressive) JPEG file and default +decompression parameters, this will not happen; jpeg_start_decompress() will +return quickly. + +After this call, the final output image dimensions, including any requested +scaling, are available in the JPEG object; so is the selected colormap, if +colormapped output has been requested. Useful fields include + + output_width image width and height, as scaled + output_height + out_color_components # of color components in out_color_space + output_components # of color components returned per pixel + colormap the selected colormap, if any + actual_number_of_colors number of entries in colormap + +output_components is 1 (a colormap index) when quantizing colors; otherwise it +equals out_color_components. It is the number of JSAMPLE values that will be +emitted per pixel in the output arrays. + +Typically you will need to allocate data buffers to hold the incoming image. +You will need output_width * output_components JSAMPLEs per scanline in your +output buffer, and a total of output_height scanlines will be returned. + +Note: if you are using the JPEG library's internal memory manager to allocate +data buffers (as djpeg does), then the manager's protocol requires that you +request large buffers *before* calling jpeg_start_decompress(). This is a +little tricky since the output_XXX fields are not normally valid then. You +can make them valid by calling jpeg_calc_output_dimensions() after setting the +relevant parameters (scaling, output color space, and quantization flag). + + +6. while (scan lines remain to be read) + jpeg_read_scanlines(...); + +Now you can read the decompressed image data by calling jpeg_read_scanlines() +one or more times. At each call, you pass in the maximum number of scanlines +to be read (ie, the height of your working buffer); jpeg_read_scanlines() +will return up to that many lines. The return value is the number of lines +actually read. The format of the returned data is discussed under "Data +formats", above. Don't forget that grayscale and color JPEGs will return +different data formats! + +Image data is returned in top-to-bottom scanline order. If you must write +out the image in bottom-to-top order, you can use the JPEG library's virtual +array mechanism to invert the data efficiently. Examples of this can be +found in the sample application djpeg. + +The library maintains a count of the number of scanlines returned so far +in the output_scanline field of the JPEG object. Usually you can just use +this variable as the loop counter, so that the loop test looks like +"while (cinfo.output_scanline < cinfo.output_height)". (Note that the test +should NOT be against image_height, unless you never use scaling. The +image_height field is the height of the original unscaled image.) +The return value always equals the change in the value of output_scanline. + +If you don't use a suspending data source, it is safe to assume that +jpeg_read_scanlines() reads at least one scanline per call, until the +bottom of the image has been reached. + +If you use a buffer larger than one scanline, it is NOT safe to assume that +jpeg_read_scanlines() fills it. (The current implementation returns only a +few scanlines per call, no matter how large a buffer you pass.) So you must +always provide a loop that calls jpeg_read_scanlines() repeatedly until the +whole image has been read. + + +7. jpeg_finish_decompress(...); + +After all the image data has been read, call jpeg_finish_decompress() to +complete the decompression cycle. This causes working memory associated +with the JPEG object to be released. + +Typical code: + + jpeg_finish_decompress(&cinfo); + +If using the stdio source manager, don't forget to close the source stdio +stream if necessary. + +It is an error to call jpeg_finish_decompress() before reading the correct +total number of scanlines. If you wish to abort decompression, call +jpeg_abort() as discussed below. + +After completing a decompression cycle, you may dispose of the JPEG object as +discussed next, or you may use it to decompress another image. In that case +return to step 2 or 3 as appropriate. If you do not change the source +manager, the next image will be read from the same source. + + +8. Release the JPEG decompression object. + +When you are done with a JPEG decompression object, destroy it by calling +jpeg_destroy_decompress() or jpeg_destroy(). The previous discussion of +destroying compression objects applies here too. + +Typical code: + + jpeg_destroy_decompress(&cinfo); + + +9. Aborting. + +You can abort a decompression cycle by calling jpeg_destroy_decompress() or +jpeg_destroy() if you don't need the JPEG object any more, or +jpeg_abort_decompress() or jpeg_abort() if you want to reuse the object. +The previous discussion of aborting compression cycles applies here too. + + +Mechanics of usage: include files, linking, etc +----------------------------------------------- + +Applications using the JPEG library should include the header file jpeglib.h +to obtain declarations of data types and routines. Before including +jpeglib.h, include system headers that define at least the typedefs FILE and +size_t. On ANSI-conforming systems, including is sufficient; on +older Unix systems, you may need to define size_t. + +If the application needs to refer to individual JPEG library error codes, also +include jerror.h to define those symbols. + +jpeglib.h indirectly includes the files jconfig.h and jmorecfg.h. If you are +installing the JPEG header files in a system directory, you will want to +install all four files: jpeglib.h, jerror.h, jconfig.h, jmorecfg.h. + +The most convenient way to include the JPEG code into your executable program +is to prepare a library file ("libjpeg.a", or a corresponding name on non-Unix +machines) and reference it at your link step. If you use only half of the +library (only compression or only decompression), only that much code will be +included from the library, unless your linker is hopelessly brain-damaged. +The supplied makefiles build libjpeg.a automatically (see install.doc). + +While you can build the JPEG library as a shared library if the whim strikes +you, we don't really recommend it. The trouble with shared libraries is that +at some point you'll probably try to substitute a new version of the library +without recompiling the calling applications. That generally doesn't work +because the parameter struct declarations usually change with each new +version. In other words, the library's API is *not* guaranteed binary +compatible across versions; we only try to ensure source-code compatibility. +(In hindsight, it might have been smarter to hide the parameter structs from +applications and introduce a ton of access functions instead. Too late now, +however.) + +On some systems your application may need to set up a signal handler to ensure +that temporary files are deleted if the program is interrupted. This is most +critical if you are on MS-DOS and use the jmemdos.c memory manager back end; +it will try to grab extended memory for temp files, and that space will NOT be +freed automatically. See cjpeg.c or djpeg.c for an example signal handler. + +It may be worth pointing out that the core JPEG library does not actually +require the stdio library: only the default source/destination managers and +error handler need it. You can use the library in a stdio-less environment +if you replace those modules and use jmemnobs.c (or another memory manager of +your own devising). More info about the minimum system library requirements +may be found in jinclude.h. + + +ADVANCED FEATURES +================= + +Compression parameter selection +------------------------------- + +This section describes all the optional parameters you can set for JPEG +compression, as well as the "helper" routines provided to assist in this +task. Proper setting of some parameters requires detailed understanding +of the JPEG standard; if you don't know what a parameter is for, it's best +not to mess with it! See REFERENCES in the README file for pointers to +more info about JPEG. + +It's a good idea to call jpeg_set_defaults() first, even if you plan to set +all the parameters; that way your code is more likely to work with future JPEG +libraries that have additional parameters. For the same reason, we recommend +you use a helper routine where one is provided, in preference to twiddling +cinfo fields directly. + +The helper routines are: + +jpeg_set_defaults (j_compress_ptr cinfo) + This routine sets all JPEG parameters to reasonable defaults, using + only the input image's color space (field in_color_space, which must + already be set in cinfo). Many applications will only need to use + this routine and perhaps jpeg_set_quality(). + +jpeg_set_colorspace (j_compress_ptr cinfo, J_COLOR_SPACE colorspace) + Sets the JPEG file's colorspace (field jpeg_color_space) as specified, + and sets other color-space-dependent parameters appropriately. See + "Special color spaces", below, before using this. A large number of + parameters, including all per-component parameters, are set by this + routine; if you want to twiddle individual parameters you should call + jpeg_set_colorspace() before rather than after. + +jpeg_default_colorspace (j_compress_ptr cinfo) + Selects an appropriate JPEG colorspace based on cinfo->in_color_space, + and calls jpeg_set_colorspace(). This is actually a subroutine of + jpeg_set_defaults(). It's broken out in case you want to change + just the colorspace-dependent JPEG parameters. + +jpeg_set_quality (j_compress_ptr cinfo, int quality, boolean force_baseline) + Constructs JPEG quantization tables appropriate for the indicated + quality setting. The quality value is expressed on the 0..100 scale + recommended by IJG (cjpeg's "-quality" switch uses this routine). + Note that the exact mapping from quality values to tables may change + in future IJG releases as more is learned about DCT quantization. + If the force_baseline parameter is TRUE, then the quantization table + entries are constrained to the range 1..255 for full JPEG baseline + compatibility. In the current implementation, this only makes a + difference for quality settings below 25, and it effectively prevents + very small/low quality files from being generated. The IJG decoder + is capable of reading the non-baseline files generated at low quality + settings when force_baseline is FALSE, but other decoders may not be. + +jpeg_set_linear_quality (j_compress_ptr cinfo, int scale_factor, + boolean force_baseline) + Same as jpeg_set_quality() except that the generated tables are the + sample tables given in the JPEC spec section K.1, multiplied by the + specified scale factor (which is expressed as a percentage; thus + scale_factor = 100 reproduces the spec's tables). Note that larger + scale factors give lower quality. This entry point is useful for + conforming to the Adobe PostScript DCT conventions, but we do not + recommend linear scaling as a user-visible quality scale otherwise. + force_baseline again constrains the computed table entries to 1..255. + +int jpeg_quality_scaling (int quality) + Converts a value on the IJG-recommended quality scale to a linear + scaling percentage. Note that this routine may change or go away + in future releases --- IJG may choose to adopt a scaling method that + can't be expressed as a simple scalar multiplier, in which case the + premise of this routine collapses. Caveat user. + +jpeg_add_quant_table (j_compress_ptr cinfo, int which_tbl, + const unsigned int *basic_table, + int scale_factor, boolean force_baseline) + Allows an arbitrary quantization table to be created. which_tbl + indicates which table slot to fill. basic_table points to an array + of 64 unsigned ints given in normal array order. These values are + multiplied by scale_factor/100 and then clamped to the range 1..65535 + (or to 1..255 if force_baseline is TRUE). + CAUTION: prior to library version 6a, jpeg_add_quant_table expected + the basic table to be given in JPEG zigzag order. If you need to + write code that works with either older or newer versions of this + routine, you must check the library version number. Something like + "#if JPEG_LIB_VERSION >= 61" is the right test. + +jpeg_simple_progression (j_compress_ptr cinfo) + Generates a default scan script for writing a progressive-JPEG file. + This is the recommended method of creating a progressive file, + unless you want to make a custom scan sequence. You must ensure that + the JPEG color space is set correctly before calling this routine. + +jpeg_simple_lossless (j_compress_ptr cinfo, int predictor, int point_transform) + Generates a default scan script for writing a lossless-JPEG file. + This is the recommended method of creating a lossless file, + unless you want to make a custom scan sequence. You must ensure that + the JPEG color space is set correctly before calling this routine. + + +Compression parameters (cinfo fields) include: + +J_DCT_METHOD dct_method + Selects the algorithm used for the DCT step. Choices are: + JDCT_ISLOW: slow but accurate integer algorithm + JDCT_IFAST: faster, less accurate integer method + JDCT_FLOAT: floating-point method + JDCT_DEFAULT: default method (normally JDCT_ISLOW) + JDCT_FASTEST: fastest method (normally JDCT_IFAST) + The FLOAT method is very slightly more accurate than the ISLOW method, + but may give different results on different machines due to varying + roundoff behavior. The integer methods should give the same results + on all machines. On machines with sufficiently fast FP hardware, the + floating-point method may also be the fastest. The IFAST method is + considerably less accurate than the other two; its use is not + recommended if high quality is a concern. JDCT_DEFAULT and + JDCT_FASTEST are macros configurable by each installation. + +J_COLOR_SPACE jpeg_color_space +int num_components + The JPEG color space and corresponding number of components; see + "Special color spaces", below, for more info. We recommend using + jpeg_set_color_space() if you want to change these. + +boolean optimize_coding + TRUE causes the compressor to compute optimal Huffman coding tables + for the image. This requires an extra pass over the data and + therefore costs a good deal of space and time. The default is + FALSE, which tells the compressor to use the supplied or default + Huffman tables. In most cases optimal tables save only a few percent + of file size compared to the default tables. Note that when this is + TRUE, you need not supply Huffman tables at all, and any you do + supply will be overwritten. + +unsigned int restart_interval +int restart_in_rows + To emit restart markers in the JPEG file, set one of these nonzero. + Set restart_interval to specify the exact interval in MCU blocks. + Set restart_in_rows to specify the interval in MCU rows. (If + restart_in_rows is not 0, then restart_interval is set after the + image width in MCUs is computed.) Defaults are zero (no restarts). + One restart marker per MCU row is often a good choice. + NOTE: the overhead of restart markers is higher in grayscale JPEG + files than in color files, and MUCH higher in progressive JPEGs. + If you use restarts, you may want to use larger intervals in those + cases. + +const jpeg_scan_info * scan_info +int num_scans + By default, scan_info is NULL; this causes the compressor to write a + single-scan sequential JPEG file. If not NULL, scan_info points to + an array of scan definition records of length num_scans. The + compressor will then write a JPEG file having one scan for each scan + definition record. This is used to generate noninterleaved or + progressive JPEG files. The library checks that the scan array + defines a valid JPEG scan sequence. (jpeg_simple_progression creates + a suitable scan definition array for progressive JPEG.) This is + discussed further under "Progressive JPEG support". + +int smoothing_factor + If non-zero, the input image is smoothed; the value should be 1 for + minimal smoothing to 100 for maximum smoothing. Consult jcsample.c + for details of the smoothing algorithm. The default is zero. + +boolean write_JFIF_header + If TRUE, a JFIF APP0 marker is emitted. jpeg_set_defaults() and + jpeg_set_colorspace() set this TRUE if a JFIF-legal JPEG color space + (ie, YCbCr or grayscale) is selected, otherwise FALSE. + +UINT8 JFIF_major_version +UINT8 JFIF_minor_version + The version number to be written into the JFIF marker. + jpeg_set_defaults() initializes the version to 1.01 (major=minor=1). + You should set it to 1.02 (major=1, minor=2) if you plan to write + any JFIF 1.02 extension markers. + +UINT8 density_unit +UINT16 X_density +UINT16 Y_density + The resolution information to be written into the JFIF marker; + not used otherwise. density_unit may be 0 for unknown, + 1 for dots/inch, or 2 for dots/cm. The default values are 0,1,1 + indicating square pixels of unknown size. + +boolean write_Adobe_marker + If TRUE, an Adobe APP14 marker is emitted. jpeg_set_defaults() and + jpeg_set_colorspace() set this TRUE if JPEG color space RGB, CMYK, + or YCCK is selected, otherwise FALSE. It is generally a bad idea + to set both write_JFIF_header and write_Adobe_marker. In fact, + you probably shouldn't change the default settings at all --- the + default behavior ensures that the JPEG file's color space can be + recognized by the decoder. + +JQUANT_TBL * quant_tbl_ptrs[NUM_QUANT_TBLS] + Pointers to coefficient quantization tables, one per table slot, + or NULL if no table is defined for a slot. Usually these should + be set via one of the above helper routines; jpeg_add_quant_table() + is general enough to define any quantization table. The other + routines will set up table slot 0 for luminance quality and table + slot 1 for chrominance. + +JHUFF_TBL * dc_huff_tbl_ptrs[NUM_HUFF_TBLS] +JHUFF_TBL * ac_huff_tbl_ptrs[NUM_HUFF_TBLS] + Pointers to Huffman coding tables, one per table slot, or NULL if + no table is defined for a slot. Slots 0 and 1 are filled with the + JPEG sample tables by jpeg_set_defaults(). If you need to allocate + more table structures, jpeg_alloc_huff_table() may be used. + Note that optimal Huffman tables can be computed for an image + by setting optimize_coding, as discussed above; there's seldom + any need to mess with providing your own Huffman tables. + +There are some additional cinfo fields which are not documented here +because you currently can't change them; for example, you can't set +arith_code TRUE because arithmetic coding is unsupported. + + +Per-component parameters are stored in the struct cinfo.comp_info[i] for +component number i. Note that components here refer to components of the +JPEG color space, *not* the source image color space. A suitably large +comp_info[] array is allocated by jpeg_set_defaults(); if you choose not +to use that routine, it's up to you to allocate the array. + +int component_id + The one-byte identifier code to be recorded in the JPEG file for + this component. For the standard color spaces, we recommend you + leave the default values alone. + +int h_samp_factor +int v_samp_factor + Horizontal and vertical sampling factors for the component; must + be 1..4 according to the JPEG standard. Note that larger sampling + factors indicate a higher-resolution component; many people find + this behavior quite unintuitive. The default values are 2,2 for + luminance components and 1,1 for chrominance components, except + for grayscale where 1,1 is used. + +int quant_tbl_no + Quantization table number for component. The default value is + 0 for luminance components and 1 for chrominance components. + +int dc_tbl_no +int ac_tbl_no + DC and AC entropy coding table numbers. The default values are + 0 for luminance components and 1 for chrominance components. + +int component_index + Must equal the component's index in comp_info[]. (Beginning in + release v6, the compressor library will fill this in automatically; + you don't have to.) + + +Decompression parameter selection +--------------------------------- + +Decompression parameter selection is somewhat simpler than compression +parameter selection, since all of the JPEG internal parameters are +recorded in the source file and need not be supplied by the application. +(Unless you are working with abbreviated files, in which case see +"Abbreviated datastreams", below.) Decompression parameters control +the postprocessing done on the image to deliver it in a format suitable +for the application's use. Many of the parameters control speed/quality +tradeoffs, in which faster decompression may be obtained at the price of +a poorer-quality image. The defaults select the highest quality (slowest) +processing. + +The following fields in the JPEG object are set by jpeg_read_header() and +may be useful to the application in choosing decompression parameters: + +JDIMENSION image_width Width and height of image +JDIMENSION image_height +int num_components Number of color components +J_COLOR_SPACE jpeg_color_space Colorspace of image +boolean saw_JFIF_marker TRUE if a JFIF APP0 marker was seen + UINT8 JFIF_major_version Version information from JFIF marker + UINT8 JFIF_minor_version + UINT8 density_unit Resolution data from JFIF marker + UINT16 X_density + UINT16 Y_density +boolean saw_Adobe_marker TRUE if an Adobe APP14 marker was seen + UINT8 Adobe_transform Color transform code from Adobe marker + +The JPEG color space, unfortunately, is something of a guess since the JPEG +standard proper does not provide a way to record it. In practice most files +adhere to the JFIF or Adobe conventions, and the decoder will recognize these +correctly. See "Special color spaces", below, for more info. + + +The decompression parameters that determine the basic properties of the +returned image are: + +J_COLOR_SPACE out_color_space + Output color space. jpeg_read_header() sets an appropriate default + based on jpeg_color_space; typically it will be RGB or grayscale. + The application can change this field to request output in a different + colorspace. For example, set it to JCS_GRAYSCALE to get grayscale + output from a color file. (This is useful for previewing: grayscale + output is faster than full color since the color components need not + be processed.) Note that not all possible color space transforms are + currently implemented; you may need to extend jdcolor.c if you want an + unusual conversion. + +unsigned int scale_num, scale_denom + Scale the image by the fraction scale_num/scale_denom. Default is + 1/1, or no scaling. Currently, the only supported scaling ratios + are 1/1, 1/2, 1/4, and 1/8. (The library design allows for arbitrary + scaling ratios but this is not likely to be implemented any time soon.) + Smaller scaling ratios permit significantly faster decoding since + fewer pixels need be processed and a simpler IDCT method can be used. + +boolean quantize_colors + If set TRUE, colormapped output will be delivered. Default is FALSE, + meaning that full-color output will be delivered. + +The next three parameters are relevant only if quantize_colors is TRUE. + +int desired_number_of_colors + Maximum number of colors to use in generating a library-supplied color + map (the actual number of colors is returned in a different field). + Default 256. Ignored when the application supplies its own color map. + +boolean two_pass_quantize + If TRUE, an extra pass over the image is made to select a custom color + map for the image. This usually looks a lot better than the one-size- + fits-all colormap that is used otherwise. Default is TRUE. Ignored + when the application supplies its own color map. + +J_DITHER_MODE dither_mode + Selects color dithering method. Supported values are: + JDITHER_NONE no dithering: fast, very low quality + JDITHER_ORDERED ordered dither: moderate speed and quality + JDITHER_FS Floyd-Steinberg dither: slow, high quality + Default is JDITHER_FS. (At present, ordered dither is implemented + only in the single-pass, standard-colormap case. If you ask for + ordered dither when two_pass_quantize is TRUE or when you supply + an external color map, you'll get F-S dithering.) + +When quantize_colors is TRUE, the target color map is described by the next +two fields. colormap is set to NULL by jpeg_read_header(). The application +can supply a color map by setting colormap non-NULL and setting +actual_number_of_colors to the map size. Otherwise, jpeg_start_decompress() +selects a suitable color map and sets these two fields itself. +[Implementation restriction: at present, an externally supplied colormap is +only accepted for 3-component output color spaces.] + +JSAMPARRAY colormap + The color map, represented as a 2-D pixel array of out_color_components + rows and actual_number_of_colors columns. Ignored if not quantizing. + CAUTION: if the JPEG library creates its own colormap, the storage + pointed to by this field is released by jpeg_finish_decompress(). + Copy the colormap somewhere else first, if you want to save it. + +int actual_number_of_colors + The number of colors in the color map. + +Additional decompression parameters that the application may set include: + +J_DCT_METHOD dct_method + Selects the algorithm used for the DCT step. Choices are the same + as described above for compression. + +boolean do_fancy_upsampling + If TRUE, do careful upsampling of chroma components. If FALSE, + a faster but sloppier method is used. Default is TRUE. The visual + impact of the sloppier method is often very small. + +boolean do_block_smoothing + If TRUE, interblock smoothing is applied in early stages of decoding + progressive JPEG files; if FALSE, not. Default is TRUE. Early + progression stages look "fuzzy" with smoothing, "blocky" without. + In any case, block smoothing ceases to be applied after the first few + AC coefficients are known to full accuracy, so it is relevant only + when using buffered-image mode for progressive images. + +boolean enable_1pass_quant +boolean enable_external_quant +boolean enable_2pass_quant + These are significant only in buffered-image mode, which is + described in its own section below. + + +The output image dimensions are given by the following fields. These are +computed from the source image dimensions and the decompression parameters +by jpeg_start_decompress(). You can also call jpeg_calc_output_dimensions() +to obtain the values that will result from the current parameter settings. +This can be useful if you are trying to pick a scaling ratio that will get +close to a desired target size. It's also important if you are using the +JPEG library's memory manager to allocate output buffer space, because you +are supposed to request such buffers *before* jpeg_start_decompress(). + +JDIMENSION output_width Actual dimensions of output image. +JDIMENSION output_height +int out_color_components Number of color components in out_color_space. +int output_components Number of color components returned. +int rec_outbuf_height Recommended height of scanline buffer. + +When quantizing colors, output_components is 1, indicating a single color map +index per pixel. Otherwise it equals out_color_components. The output arrays +are required to be output_width * output_components JSAMPLEs wide. + +rec_outbuf_height is the recommended minimum height (in scanlines) of the +buffer passed to jpeg_read_scanlines(). If the buffer is smaller, the +library will still work, but time will be wasted due to unnecessary data +copying. In high-quality modes, rec_outbuf_height is always 1, but some +faster, lower-quality modes set it to larger values (typically 2 to 4). +If you are going to ask for a high-speed processing mode, you may as well +go to the trouble of honoring rec_outbuf_height so as to avoid data copying. +(An output buffer larger than rec_outbuf_height lines is OK, but won't +provide any material speed improvement over that height.) + + +Special color spaces +-------------------- + +The JPEG standard itself is "color blind" and doesn't specify any particular +color space. It is customary to convert color data to a luminance/chrominance +color space before compressing, since this permits greater compression. The +existing de-facto JPEG file format standards specify YCbCr or grayscale data +(JFIF), or grayscale, RGB, YCbCr, CMYK, or YCCK (Adobe). For special +applications such as multispectral images, other color spaces can be used, +but it must be understood that such files will be unportable. + +The JPEG library can handle the most common colorspace conversions (namely +RGB <=> YCbCr and CMYK <=> YCCK). It can also deal with data of an unknown +color space, passing it through without conversion. If you deal extensively +with an unusual color space, you can easily extend the library to understand +additional color spaces and perform appropriate conversions. + +For compression, the source data's color space is specified by field +in_color_space. This is transformed to the JPEG file's color space given +by jpeg_color_space. jpeg_set_defaults() chooses a reasonable JPEG color +space depending on in_color_space, but you can override this by calling +jpeg_set_colorspace(). Of course you must select a supported transformation. +jccolor.c currently supports the following transformations: + RGB => YCbCr + RGB => GRAYSCALE + YCbCr => GRAYSCALE + CMYK => YCCK +plus the null transforms: GRAYSCALE => GRAYSCALE, RGB => RGB, +YCbCr => YCbCr, CMYK => CMYK, YCCK => YCCK, and UNKNOWN => UNKNOWN. + +The de-facto file format standards (JFIF and Adobe) specify APPn markers that +indicate the color space of the JPEG file. It is important to ensure that +these are written correctly, or omitted if the JPEG file's color space is not +one of the ones supported by the de-facto standards. jpeg_set_colorspace() +will set the compression parameters to include or omit the APPn markers +properly, so long as it is told the truth about the JPEG color space. +For example, if you are writing some random 3-component color space without +conversion, don't try to fake out the library by setting in_color_space and +jpeg_color_space to JCS_YCbCr; use JCS_UNKNOWN. You may want to write an +APPn marker of your own devising to identify the colorspace --- see "Special +markers", below. + +When told that the color space is UNKNOWN, the library will default to using +luminance-quality compression parameters for all color components. You may +well want to change these parameters. See the source code for +jpeg_set_colorspace(), in jcparam.c, for details. + +For decompression, the JPEG file's color space is given in jpeg_color_space, +and this is transformed to the output color space out_color_space. +jpeg_read_header's setting of jpeg_color_space can be relied on if the file +conforms to JFIF or Adobe conventions, but otherwise it is no better than a +guess. If you know the JPEG file's color space for certain, you can override +jpeg_read_header's guess by setting jpeg_color_space. jpeg_read_header also +selects a default output color space based on (its guess of) jpeg_color_space; +set out_color_space to override this. Again, you must select a supported +transformation. jdcolor.c currently supports + YCbCr => GRAYSCALE + YCbCr => RGB + GRAYSCALE => RGB + YCCK => CMYK +as well as the null transforms. (Since GRAYSCALE=>RGB is provided, an +application can force grayscale JPEGs to look like color JPEGs if it only +wants to handle one case.) + +The two-pass color quantizer, jquant2.c, is specialized to handle RGB data +(it weights distances appropriately for RGB colors). You'll need to modify +the code if you want to use it for non-RGB output color spaces. Note that +jquant2.c is used to map to an application-supplied colormap as well as for +the normal two-pass colormap selection process. + +CAUTION: it appears that Adobe Photoshop writes inverted data in CMYK JPEG +files: 0 represents 100% ink coverage, rather than 0% ink as you'd expect. +This is arguably a bug in Photoshop, but if you need to work with Photoshop +CMYK files, you will have to deal with it in your application. We cannot +"fix" this in the library by inverting the data during the CMYK<=>YCCK +transform, because that would break other applications, notably Ghostscript. +Photoshop versions prior to 3.0 write EPS files containing JPEG-encoded CMYK +data in the same inverted-YCCK representation used in bare JPEG files, but +the surrounding PostScript code performs an inversion using the PS image +operator. I am told that Photoshop 3.0 will write uninverted YCCK in +EPS/JPEG files, and will omit the PS-level inversion. (But the data +polarity used in bare JPEG files will not change in 3.0.) In either case, +the JPEG library must not invert the data itself, or else Ghostscript would +read these EPS files incorrectly. + + +Error handling +-------------- + +When the default error handler is used, any error detected inside the JPEG +routines will cause a message to be printed on stderr, followed by exit(). +You can supply your own error handling routines to override this behavior +and to control the treatment of nonfatal warnings and trace/debug messages. +The file example.c illustrates the most common case, which is to have the +application regain control after an error rather than exiting. + +The JPEG library never writes any message directly; it always goes through +the error handling routines. Three classes of messages are recognized: + * Fatal errors: the library cannot continue. + * Warnings: the library can continue, but the data is corrupt, and a + damaged output image is likely to result. + * Trace/informational messages. These come with a trace level indicating + the importance of the message; you can control the verbosity of the + program by adjusting the maximum trace level that will be displayed. + +You may, if you wish, simply replace the entire JPEG error handling module +(jerror.c) with your own code. However, you can avoid code duplication by +only replacing some of the routines depending on the behavior you need. +This is accomplished by calling jpeg_std_error() as usual, but then overriding +some of the method pointers in the jpeg_error_mgr struct, as illustrated by +example.c. + +All of the error handling routines will receive a pointer to the JPEG object +(a j_common_ptr which points to either a jpeg_compress_struct or a +jpeg_decompress_struct; if you need to tell which, test the is_decompressor +field). This struct includes a pointer to the error manager struct in its +"err" field. Frequently, custom error handler routines will need to access +additional data which is not known to the JPEG library or the standard error +handler. The most convenient way to do this is to embed either the JPEG +object or the jpeg_error_mgr struct in a larger structure that contains +additional fields; then casting the passed pointer provides access to the +additional fields. Again, see example.c for one way to do it. (Beginning +with IJG version 6b, there is also a void pointer "client_data" in each +JPEG object, which the application can also use to find related data. +The library does not touch client_data at all.) + +The individual methods that you might wish to override are: + +error_exit (j_common_ptr cinfo) + Receives control for a fatal error. Information sufficient to + generate the error message has been stored in cinfo->err; call + output_message to display it. Control must NOT return to the caller; + generally this routine will exit() or longjmp() somewhere. + Typically you would override this routine to get rid of the exit() + default behavior. Note that if you continue processing, you should + clean up the JPEG object with jpeg_abort() or jpeg_destroy(). + +output_message (j_common_ptr cinfo) + Actual output of any JPEG message. Override this to send messages + somewhere other than stderr. Note that this method does not know + how to generate a message, only where to send it. + +format_message (j_common_ptr cinfo, char * buffer) + Constructs a readable error message string based on the error info + stored in cinfo->err. This method is called by output_message. Few + applications should need to override this method. One possible + reason for doing so is to implement dynamic switching of error message + language. + +emit_message (j_common_ptr cinfo, int msg_level) + Decide whether or not to emit a warning or trace message; if so, + calls output_message. The main reason for overriding this method + would be to abort on warnings. msg_level is -1 for warnings, + 0 and up for trace messages. + +Only error_exit() and emit_message() are called from the rest of the JPEG +library; the other two are internal to the error handler. + +The actual message texts are stored in an array of strings which is pointed to +by the field err->jpeg_message_table. The messages are numbered from 0 to +err->last_jpeg_message, and it is these code numbers that are used in the +JPEG library code. You could replace the message texts (for instance, with +messages in French or German) by changing the message table pointer. See +jerror.h for the default texts. CAUTION: this table will almost certainly +change or grow from one library version to the next. + +It may be useful for an application to add its own message texts that are +handled by the same mechanism. The error handler supports a second "add-on" +message table for this purpose. To define an addon table, set the pointer +err->addon_message_table and the message numbers err->first_addon_message and +err->last_addon_message. If you number the addon messages beginning at 1000 +or so, you won't have to worry about conflicts with the library's built-in +messages. See the sample applications cjpeg/djpeg for an example of using +addon messages (the addon messages are defined in cderror.h). + +Actual invocation of the error handler is done via macros defined in jerror.h: + ERREXITn(...) for fatal errors + WARNMSn(...) for corrupt-data warnings + TRACEMSn(...) for trace and informational messages. +These macros store the message code and any additional parameters into the +error handler struct, then invoke the error_exit() or emit_message() method. +The variants of each macro are for varying numbers of additional parameters. +The additional parameters are inserted into the generated message using +standard printf() format codes. + +See jerror.h and jerror.c for further details. + + +Compressed data handling (source and destination managers) +---------------------------------------------------------- + +The JPEG compression library sends its compressed data to a "destination +manager" module. The default destination manager just writes the data to a +stdio stream, but you can provide your own manager to do something else. +Similarly, the decompression library calls a "source manager" to obtain the +compressed data; you can provide your own source manager if you want the data +to come from somewhere other than a stdio stream. + +In both cases, compressed data is processed a bufferload at a time: the +destination or source manager provides a work buffer, and the library invokes +the manager only when the buffer is filled or emptied. (You could define a +one-character buffer to force the manager to be invoked for each byte, but +that would be rather inefficient.) The buffer's size and location are +controlled by the manager, not by the library. For example, if you desired to +decompress a JPEG datastream that was all in memory, you could just make the +buffer pointer and length point to the original data in memory. Then the +buffer-reload procedure would be invoked only if the decompressor ran off the +end of the datastream, which would indicate an erroneous datastream. + +The work buffer is defined as an array of datatype JOCTET, which is generally +"char" or "unsigned char". On a machine where char is not exactly 8 bits +wide, you must define JOCTET as a wider data type and then modify the data +source and destination modules to transcribe the work arrays into 8-bit units +on external storage. + +A data destination manager struct contains a pointer and count defining the +next byte to write in the work buffer and the remaining free space: + + JOCTET * next_output_byte; /* => next byte to write in buffer */ + size_t free_in_buffer; /* # of byte spaces remaining in buffer */ + +The library increments the pointer and decrements the count until the buffer +is filled. The manager's empty_output_buffer method must reset the pointer +and count. The manager is expected to remember the buffer's starting address +and total size in private fields not visible to the library. + +A data destination manager provides three methods: + +init_destination (j_compress_ptr cinfo) + Initialize destination. This is called by jpeg_start_compress() + before any data is actually written. It must initialize + next_output_byte and free_in_buffer. free_in_buffer must be + initialized to a positive value. + +empty_output_buffer (j_compress_ptr cinfo) + This is called whenever the buffer has filled (free_in_buffer + reaches zero). In typical applications, it should write out the + *entire* buffer (use the saved start address and buffer length; + ignore the current state of next_output_byte and free_in_buffer). + Then reset the pointer & count to the start of the buffer, and + return TRUE indicating that the buffer has been dumped. + free_in_buffer must be set to a positive value when TRUE is + returned. A FALSE return should only be used when I/O suspension is + desired (this operating mode is discussed in the next section). + +term_destination (j_compress_ptr cinfo) + Terminate destination --- called by jpeg_finish_compress() after all + data has been written. In most applications, this must flush any + data remaining in the buffer. Use either next_output_byte or + free_in_buffer to determine how much data is in the buffer. + +term_destination() is NOT called by jpeg_abort() or jpeg_destroy(). If you +want the destination manager to be cleaned up during an abort, you must do it +yourself. + +You will also need code to create a jpeg_destination_mgr struct, fill in its +method pointers, and insert a pointer to the struct into the "dest" field of +the JPEG compression object. This can be done in-line in your setup code if +you like, but it's probably cleaner to provide a separate routine similar to +the jpeg_stdio_dest() routine of the supplied destination manager. + +Decompression source managers follow a parallel design, but with some +additional frammishes. The source manager struct contains a pointer and count +defining the next byte to read from the work buffer and the number of bytes +remaining: + + const JOCTET * next_input_byte; /* => next byte to read from buffer */ + size_t bytes_in_buffer; /* # of bytes remaining in buffer */ + +The library increments the pointer and decrements the count until the buffer +is emptied. The manager's fill_input_buffer method must reset the pointer and +count. In most applications, the manager must remember the buffer's starting +address and total size in private fields not visible to the library. + +A data source manager provides five methods: + +init_source (j_decompress_ptr cinfo) + Initialize source. This is called by jpeg_read_header() before any + data is actually read. Unlike init_destination(), it may leave + bytes_in_buffer set to 0 (in which case a fill_input_buffer() call + will occur immediately). + +fill_input_buffer (j_decompress_ptr cinfo) + This is called whenever bytes_in_buffer has reached zero and more + data is wanted. In typical applications, it should read fresh data + into the buffer (ignoring the current state of next_input_byte and + bytes_in_buffer), reset the pointer & count to the start of the + buffer, and return TRUE indicating that the buffer has been reloaded. + It is not necessary to fill the buffer entirely, only to obtain at + least one more byte. bytes_in_buffer MUST be set to a positive value + if TRUE is returned. A FALSE return should only be used when I/O + suspension is desired (this mode is discussed in the next section). + +skip_input_data (j_decompress_ptr cinfo, long num_bytes) + Skip num_bytes worth of data. The buffer pointer and count should + be advanced over num_bytes input bytes, refilling the buffer as + needed. This is used to skip over a potentially large amount of + uninteresting data (such as an APPn marker). In some applications + it may be possible to optimize away the reading of the skipped data, + but it's not clear that being smart is worth much trouble; large + skips are uncommon. bytes_in_buffer may be zero on return. + A zero or negative skip count should be treated as a no-op. + +resync_to_restart (j_decompress_ptr cinfo, int desired) + This routine is called only when the decompressor has failed to find + a restart (RSTn) marker where one is expected. Its mission is to + find a suitable point for resuming decompression. For most + applications, we recommend that you just use the default resync + procedure, jpeg_resync_to_restart(). However, if you are able to back + up in the input data stream, or if you have a-priori knowledge about + the likely location of restart markers, you may be able to do better. + Read the read_restart_marker() and jpeg_resync_to_restart() routines + in jdmarker.c if you think you'd like to implement your own resync + procedure. + +term_source (j_decompress_ptr cinfo) + Terminate source --- called by jpeg_finish_decompress() after all + data has been read. Often a no-op. + +For both fill_input_buffer() and skip_input_data(), there is no such thing +as an EOF return. If the end of the file has been reached, the routine has +a choice of exiting via ERREXIT() or inserting fake data into the buffer. +In most cases, generating a warning message and inserting a fake EOI marker +is the best course of action --- this will allow the decompressor to output +however much of the image is there. In pathological cases, the decompressor +may swallow the EOI and again demand data ... just keep feeding it fake EOIs. +jdatasrc.c illustrates the recommended error recovery behavior. + +term_source() is NOT called by jpeg_abort() or jpeg_destroy(). If you want +the source manager to be cleaned up during an abort, you must do it yourself. + +You will also need code to create a jpeg_source_mgr struct, fill in its method +pointers, and insert a pointer to the struct into the "src" field of the JPEG +decompression object. This can be done in-line in your setup code if you +like, but it's probably cleaner to provide a separate routine similar to the +jpeg_stdio_src() routine of the supplied source manager. + +For more information, consult the stdio source and destination managers +in jdatasrc.c and jdatadst.c. + + +I/O suspension +-------------- + +Some applications need to use the JPEG library as an incremental memory-to- +memory filter: when the compressed data buffer is filled or emptied, they want +control to return to the outer loop, rather than expecting that the buffer can +be emptied or reloaded within the data source/destination manager subroutine. +The library supports this need by providing an "I/O suspension" mode, which we +describe in this section. + +The I/O suspension mode is not a panacea: nothing is guaranteed about the +maximum amount of time spent in any one call to the library, so it will not +eliminate response-time problems in single-threaded applications. If you +need guaranteed response time, we suggest you "bite the bullet" and implement +a real multi-tasking capability. + +To use I/O suspension, cooperation is needed between the calling application +and the data source or destination manager; you will always need a custom +source/destination manager. (Please read the previous section if you haven't +already.) The basic idea is that the empty_output_buffer() or +fill_input_buffer() routine is a no-op, merely returning FALSE to indicate +that it has done nothing. Upon seeing this, the JPEG library suspends +operation and returns to its caller. The surrounding application is +responsible for emptying or refilling the work buffer before calling the +JPEG library again. + +Compression suspension: + +For compression suspension, use an empty_output_buffer() routine that returns +FALSE; typically it will not do anything else. This will cause the +compressor to return to the caller of jpeg_write_scanlines(), with the return +value indicating that not all the supplied scanlines have been accepted. +The application must make more room in the output buffer, adjust the output +buffer pointer/count appropriately, and then call jpeg_write_scanlines() +again, pointing to the first unconsumed scanline. + +When forced to suspend, the compressor will backtrack to a convenient stopping +point (usually the start of the current MCU); it will regenerate some output +data when restarted. Therefore, although empty_output_buffer() is only +called when the buffer is filled, you should NOT write out the entire buffer +after a suspension. Write only the data up to the current position of +next_output_byte/free_in_buffer. The data beyond that point will be +regenerated after resumption. + +Because of the backtracking behavior, a good-size output buffer is essential +for efficiency; you don't want the compressor to suspend often. (In fact, an +overly small buffer could lead to infinite looping, if a single MCU required +more data than would fit in the buffer.) We recommend a buffer of at least +several Kbytes. You may want to insert explicit code to ensure that you don't +call jpeg_write_scanlines() unless there is a reasonable amount of space in +the output buffer; in other words, flush the buffer before trying to compress +more data. + +The compressor does not allow suspension while it is trying to write JPEG +markers at the beginning and end of the file. This means that: + * At the beginning of a compression operation, there must be enough free + space in the output buffer to hold the header markers (typically 600 or + so bytes). The recommended buffer size is bigger than this anyway, so + this is not a problem as long as you start with an empty buffer. However, + this restriction might catch you if you insert large special markers, such + as a JFIF thumbnail image, without flushing the buffer afterwards. + * When you call jpeg_finish_compress(), there must be enough space in the + output buffer to emit any buffered data and the final EOI marker. In the + current implementation, half a dozen bytes should suffice for this, but + for safety's sake we recommend ensuring that at least 100 bytes are free + before calling jpeg_finish_compress(). + +A more significant restriction is that jpeg_finish_compress() cannot suspend. +This means you cannot use suspension with multi-pass operating modes, namely +Huffman code optimization and multiple-scan output. Those modes write the +whole file during jpeg_finish_compress(), which will certainly result in +buffer overrun. (Note that this restriction applies only to compression, +not decompression. The decompressor supports input suspension in all of its +operating modes.) + +Decompression suspension: + +For decompression suspension, use a fill_input_buffer() routine that simply +returns FALSE (except perhaps during error recovery, as discussed below). +This will cause the decompressor to return to its caller with an indication +that suspension has occurred. This can happen at four places: + * jpeg_read_header(): will return JPEG_SUSPENDED. + * jpeg_start_decompress(): will return FALSE, rather than its usual TRUE. + * jpeg_read_scanlines(): will return the number of scanlines already + completed (possibly 0). + * jpeg_finish_decompress(): will return FALSE, rather than its usual TRUE. +The surrounding application must recognize these cases, load more data into +the input buffer, and repeat the call. In the case of jpeg_read_scanlines(), +increment the passed pointers past any scanlines successfully read. + +Just as with compression, the decompressor will typically backtrack to a +convenient restart point before suspending. When fill_input_buffer() is +called, next_input_byte/bytes_in_buffer point to the current restart point, +which is where the decompressor will backtrack to if FALSE is returned. +The data beyond that position must NOT be discarded if you suspend; it needs +to be re-read upon resumption. In most implementations, you'll need to shift +this data down to the start of your work buffer and then load more data after +it. Again, this behavior means that a several-Kbyte work buffer is essential +for decent performance; furthermore, you should load a reasonable amount of +new data before resuming decompression. (If you loaded, say, only one new +byte each time around, you could waste a LOT of cycles.) + +The skip_input_data() source manager routine requires special care in a +suspension scenario. This routine is NOT granted the ability to suspend the +decompressor; it can decrement bytes_in_buffer to zero, but no more. If the +requested skip distance exceeds the amount of data currently in the input +buffer, then skip_input_data() must set bytes_in_buffer to zero and record the +additional skip distance somewhere else. The decompressor will immediately +call fill_input_buffer(), which should return FALSE, which will cause a +suspension return. The surrounding application must then arrange to discard +the recorded number of bytes before it resumes loading the input buffer. +(Yes, this design is rather baroque, but it avoids complexity in the far more +common case where a non-suspending source manager is used.) + +If the input data has been exhausted, we recommend that you emit a warning +and insert dummy EOI markers just as a non-suspending data source manager +would do. This can be handled either in the surrounding application logic or +within fill_input_buffer(); the latter is probably more efficient. If +fill_input_buffer() knows that no more data is available, it can set the +pointer/count to point to a dummy EOI marker and then return TRUE just as +though it had read more data in a non-suspending situation. + +The decompressor does not attempt to suspend within standard JPEG markers; +instead it will backtrack to the start of the marker and reprocess the whole +marker next time. Hence the input buffer must be large enough to hold the +longest standard marker in the file. Standard JPEG markers should normally +not exceed a few hundred bytes each (DHT tables are typically the longest). +We recommend at least a 2K buffer for performance reasons, which is much +larger than any correct marker is likely to be. For robustness against +damaged marker length counts, you may wish to insert a test in your +application for the case that the input buffer is completely full and yet +the decoder has suspended without consuming any data --- otherwise, if this +situation did occur, it would lead to an endless loop. (The library can't +provide this test since it has no idea whether "the buffer is full", or +even whether there is a fixed-size input buffer.) + +The input buffer would need to be 64K to allow for arbitrary COM or APPn +markers, but these are handled specially: they are either saved into allocated +memory, or skipped over by calling skip_input_data(). In the former case, +suspension is handled correctly, and in the latter case, the problem of +buffer overrun is placed on skip_input_data's shoulders, as explained above. +Note that if you provide your own marker handling routine for large markers, +you should consider how to deal with buffer overflow. + +Multiple-buffer management: + +In some applications it is desirable to store the compressed data in a linked +list of buffer areas, so as to avoid data copying. This can be handled by +having empty_output_buffer() or fill_input_buffer() set the pointer and count +to reference the next available buffer; FALSE is returned only if no more +buffers are available. Although seemingly straightforward, there is a +pitfall in this approach: the backtrack that occurs when FALSE is returned +could back up into an earlier buffer. For example, when fill_input_buffer() +is called, the current pointer & count indicate the backtrack restart point. +Since fill_input_buffer() will set the pointer and count to refer to a new +buffer, the restart position must be saved somewhere else. Suppose a second +call to fill_input_buffer() occurs in the same library call, and no +additional input data is available, so fill_input_buffer must return FALSE. +If the JPEG library has not moved the pointer/count forward in the current +buffer, then *the correct restart point is the saved position in the prior +buffer*. Prior buffers may be discarded only after the library establishes +a restart point within a later buffer. Similar remarks apply for output into +a chain of buffers. + +The library will never attempt to backtrack over a skip_input_data() call, +so any skipped data can be permanently discarded. You still have to deal +with the case of skipping not-yet-received data, however. + +It's much simpler to use only a single buffer; when fill_input_buffer() is +called, move any unconsumed data (beyond the current pointer/count) down to +the beginning of this buffer and then load new data into the remaining buffer +space. This approach requires a little more data copying but is far easier +to get right. + + +Progressive JPEG support +------------------------ + +Progressive JPEG rearranges the stored data into a series of scans of +increasing quality. In situations where a JPEG file is transmitted across a +slow communications link, a decoder can generate a low-quality image very +quickly from the first scan, then gradually improve the displayed quality as +more scans are received. The final image after all scans are complete is +identical to that of a regular (sequential) JPEG file of the same quality +setting. Progressive JPEG files are often slightly smaller than equivalent +sequential JPEG files, but the possibility of incremental display is the main +reason for using progressive JPEG. + +The IJG encoder library generates progressive JPEG files when given a +suitable "scan script" defining how to divide the data into scans. +Creation of progressive JPEG files is otherwise transparent to the encoder. +Progressive JPEG files can also be read transparently by the decoder library. +If the decoding application simply uses the library as defined above, it +will receive a final decoded image without any indication that the file was +progressive. Of course, this approach does not allow incremental display. +To perform incremental display, an application needs to use the decoder +library's "buffered-image" mode, in which it receives a decoded image +multiple times. + +Each displayed scan requires about as much work to decode as a full JPEG +image of the same size, so the decoder must be fairly fast in relation to the +data transmission rate in order to make incremental display useful. However, +it is possible to skip displaying the image and simply add the incoming bits +to the decoder's coefficient buffer. This is fast because only Huffman +decoding need be done, not IDCT, upsampling, colorspace conversion, etc. +The IJG decoder library allows the application to switch dynamically between +displaying the image and simply absorbing the incoming bits. A properly +coded application can automatically adapt the number of display passes to +suit the time available as the image is received. Also, a final +higher-quality display cycle can be performed from the buffered data after +the end of the file is reached. + +Progressive compression: + +To create a progressive JPEG file (or a multiple-scan sequential JPEG file), +set the scan_info cinfo field to point to an array of scan descriptors, and +perform compression as usual. Instead of constructing your own scan list, +you can call the jpeg_simple_progression() helper routine to create a +recommended progression sequence; this method should be used by all +applications that don't want to get involved in the nitty-gritty of +progressive scan sequence design. (If you want to provide user control of +scan sequences, you may wish to borrow the scan script reading code found +in rdswitch.c, so that you can read scan script files just like cjpeg's.) +When scan_info is not NULL, the compression library will store DCT'd data +into a buffer array as jpeg_write_scanlines() is called, and will emit all +the requested scans during jpeg_finish_compress(). This implies that +multiple-scan output cannot be created with a suspending data destination +manager, since jpeg_finish_compress() does not support suspension. We +should also note that the compressor currently forces Huffman optimization +mode when creating a progressive JPEG file, because the default Huffman +tables are unsuitable for progressive files. + +Progressive decompression: + +When buffered-image mode is not used, the decoder library will read all of +a multi-scan file during jpeg_start_decompress(), so that it can provide a +final decoded image. (Here "multi-scan" means either progressive or +multi-scan sequential.) This makes multi-scan files transparent to the +decoding application. However, existing applications that used suspending +input with version 5 of the IJG library will need to be modified to check +for a suspension return from jpeg_start_decompress(). + +To perform incremental display, an application must use the library's +buffered-image mode. This is described in the next section. + + +Buffered-image mode +------------------- + +In buffered-image mode, the library stores the partially decoded image in a +coefficient buffer, from which it can be read out as many times as desired. +This mode is typically used for incremental display of progressive JPEG files, +but it can be used with any JPEG file. Each scan of a progressive JPEG file +adds more data (more detail) to the buffered image. The application can +display in lockstep with the source file (one display pass per input scan), +or it can allow input processing to outrun display processing. By making +input and display processing run independently, it is possible for the +application to adapt progressive display to a wide range of data transmission +rates. + +The basic control flow for buffered-image decoding is + + jpeg_create_decompress() + set data source + jpeg_read_header() + set overall decompression parameters + cinfo.buffered_image = TRUE; /* select buffered-image mode */ + jpeg_start_decompress() + for (each output pass) { + adjust output decompression parameters if required + jpeg_start_output() /* start a new output pass */ + for (all scanlines in image) { + jpeg_read_scanlines() + display scanlines + } + jpeg_finish_output() /* terminate output pass */ + } + jpeg_finish_decompress() + jpeg_destroy_decompress() + +This differs from ordinary unbuffered decoding in that there is an additional +level of looping. The application can choose how many output passes to make +and how to display each pass. + +The simplest approach to displaying progressive images is to do one display +pass for each scan appearing in the input file. In this case the outer loop +condition is typically + while (! jpeg_input_complete(&cinfo)) +and the start-output call should read + jpeg_start_output(&cinfo, cinfo.input_scan_number); +The second parameter to jpeg_start_output() indicates which scan of the input +file is to be displayed; the scans are numbered starting at 1 for this +purpose. (You can use a loop counter starting at 1 if you like, but using +the library's input scan counter is easier.) The library automatically reads +data as necessary to complete each requested scan, and jpeg_finish_output() +advances to the next scan or end-of-image marker (hence input_scan_number +will be incremented by the time control arrives back at jpeg_start_output()). +With this technique, data is read from the input file only as needed, and +input and output processing run in lockstep. + +After reading the final scan and reaching the end of the input file, the +buffered image remains available; it can be read additional times by +repeating the jpeg_start_output()/jpeg_read_scanlines()/jpeg_finish_output() +sequence. For example, a useful technique is to use fast one-pass color +quantization for display passes made while the image is arriving, followed by +a final display pass using two-pass quantization for highest quality. This +is done by changing the library parameters before the final output pass. +Changing parameters between passes is discussed in detail below. + +In general the last scan of a progressive file cannot be recognized as such +until after it is read, so a post-input display pass is the best approach if +you want special processing in the final pass. + +When done with the image, be sure to call jpeg_finish_decompress() to release +the buffered image (or just use jpeg_destroy_decompress()). + +If input data arrives faster than it can be displayed, the application can +cause the library to decode input data in advance of what's needed to produce +output. This is done by calling the routine jpeg_consume_input(). +The return value is one of the following: + JPEG_REACHED_SOS: reached an SOS marker (the start of a new scan) + JPEG_REACHED_EOI: reached the EOI marker (end of image) + JPEG_ROW_COMPLETED: completed reading one MCU row of compressed data + JPEG_SCAN_COMPLETED: completed reading last MCU row of current scan + JPEG_SUSPENDED: suspended before completing any of the above +(JPEG_SUSPENDED can occur only if a suspending data source is used.) This +routine can be called at any time after initializing the JPEG object. It +reads some additional data and returns when one of the indicated significant +events occurs. (If called after the EOI marker is reached, it will +immediately return JPEG_REACHED_EOI without attempting to read more data.) + +The library's output processing will automatically call jpeg_consume_input() +whenever the output processing overtakes the input; thus, simple lockstep +display requires no direct calls to jpeg_consume_input(). But by adding +calls to jpeg_consume_input(), you can absorb data in advance of what is +being displayed. This has two benefits: + * You can limit buildup of unprocessed data in your input buffer. + * You can eliminate extra display passes by paying attention to the + state of the library's input processing. + +The first of these benefits only requires interspersing calls to +jpeg_consume_input() with your display operations and any other processing +you may be doing. To avoid wasting cycles due to backtracking, it's best to +call jpeg_consume_input() only after a hundred or so new bytes have arrived. +This is discussed further under "I/O suspension", above. (Note: the JPEG +library currently is not thread-safe. You must not call jpeg_consume_input() +from one thread of control if a different library routine is working on the +same JPEG object in another thread.) + +When input arrives fast enough that more than one new scan is available +before you start a new output pass, you may as well skip the output pass +corresponding to the completed scan. This occurs for free if you pass +cinfo.input_scan_number as the target scan number to jpeg_start_output(). +The input_scan_number field is simply the index of the scan currently being +consumed by the input processor. You can ensure that this is up-to-date by +emptying the input buffer just before calling jpeg_start_output(): call +jpeg_consume_input() repeatedly until it returns JPEG_SUSPENDED or +JPEG_REACHED_EOI. + +The target scan number passed to jpeg_start_output() is saved in the +cinfo.output_scan_number field. The library's output processing calls +jpeg_consume_input() whenever the current input scan number and row within +that scan is less than or equal to the current output scan number and row. +Thus, input processing can "get ahead" of the output processing but is not +allowed to "fall behind". You can achieve several different effects by +manipulating this interlock rule. For example, if you pass a target scan +number greater than the current input scan number, the output processor will +wait until that scan starts to arrive before producing any output. (To avoid +an infinite loop, the target scan number is automatically reset to the last +scan number when the end of image is reached. Thus, if you specify a large +target scan number, the library will just absorb the entire input file and +then perform an output pass. This is effectively the same as what +jpeg_start_decompress() does when you don't select buffered-image mode.) +When you pass a target scan number equal to the current input scan number, +the image is displayed no faster than the current input scan arrives. The +final possibility is to pass a target scan number less than the current input +scan number; this disables the input/output interlock and causes the output +processor to simply display whatever it finds in the image buffer, without +waiting for input. (However, the library will not accept a target scan +number less than one, so you can't avoid waiting for the first scan.) + +When data is arriving faster than the output display processing can advance +through the image, jpeg_consume_input() will store data into the buffered +image beyond the point at which the output processing is reading data out +again. If the input arrives fast enough, it may "wrap around" the buffer to +the point where the input is more than one whole scan ahead of the output. +If the output processing simply proceeds through its display pass without +paying attention to the input, the effect seen on-screen is that the lower +part of the image is one or more scans better in quality than the upper part. +Then, when the next output scan is started, you have a choice of what target +scan number to use. The recommended choice is to use the current input scan +number at that time, which implies that you've skipped the output scans +corresponding to the input scans that were completed while you processed the +previous output scan. In this way, the decoder automatically adapts its +speed to the arriving data, by skipping output scans as necessary to keep up +with the arriving data. + +When using this strategy, you'll want to be sure that you perform a final +output pass after receiving all the data; otherwise your last display may not +be full quality across the whole screen. So the right outer loop logic is +something like this: + do { + absorb any waiting input by calling jpeg_consume_input() + final_pass = jpeg_input_complete(&cinfo); + adjust output decompression parameters if required + jpeg_start_output(&cinfo, cinfo.input_scan_number); + ... + jpeg_finish_output() + } while (! final_pass); +rather than quitting as soon as jpeg_input_complete() returns TRUE. This +arrangement makes it simple to use higher-quality decoding parameters +for the final pass. But if you don't want to use special parameters for +the final pass, the right loop logic is like this: + for (;;) { + absorb any waiting input by calling jpeg_consume_input() + jpeg_start_output(&cinfo, cinfo.input_scan_number); + ... + jpeg_finish_output() + if (jpeg_input_complete(&cinfo) && + cinfo.input_scan_number == cinfo.output_scan_number) + break; + } +In this case you don't need to know in advance whether an output pass is to +be the last one, so it's not necessary to have reached EOF before starting +the final output pass; rather, what you want to test is whether the output +pass was performed in sync with the final input scan. This form of the loop +will avoid an extra output pass whenever the decoder is able (or nearly able) +to keep up with the incoming data. + +When the data transmission speed is high, you might begin a display pass, +then find that much or all of the file has arrived before you can complete +the pass. (You can detect this by noting the JPEG_REACHED_EOI return code +from jpeg_consume_input(), or equivalently by testing jpeg_input_complete().) +In this situation you may wish to abort the current display pass and start a +new one using the newly arrived information. To do so, just call +jpeg_finish_output() and then start a new pass with jpeg_start_output(). + +A variant strategy is to abort and restart display if more than one complete +scan arrives during an output pass; this can be detected by noting +JPEG_REACHED_SOS returns and/or examining cinfo.input_scan_number. This +idea should be employed with caution, however, since the display process +might never get to the bottom of the image before being aborted, resulting +in the lower part of the screen being several passes worse than the upper. +In most cases it's probably best to abort an output pass only if the whole +file has arrived and you want to begin the final output pass immediately. + +When receiving data across a communication link, we recommend always using +the current input scan number for the output target scan number; if a +higher-quality final pass is to be done, it should be started (aborting any +incomplete output pass) as soon as the end of file is received. However, +many other strategies are possible. For example, the application can examine +the parameters of the current input scan and decide whether to display it or +not. If the scan contains only chroma data, one might choose not to use it +as the target scan, expecting that the scan will be small and will arrive +quickly. To skip to the next scan, call jpeg_consume_input() until it +returns JPEG_REACHED_SOS or JPEG_REACHED_EOI. Or just use the next higher +number as the target scan for jpeg_start_output(); but that method doesn't +let you inspect the next scan's parameters before deciding to display it. + + +In buffered-image mode, jpeg_start_decompress() never performs input and +thus never suspends. An application that uses input suspension with +buffered-image mode must be prepared for suspension returns from these +routines: +* jpeg_start_output() performs input only if you request 2-pass quantization + and the target scan isn't fully read yet. (This is discussed below.) +* jpeg_read_scanlines(), as always, returns the number of scanlines that it + was able to produce before suspending. +* jpeg_finish_output() will read any markers following the target scan, + up to the end of the file or the SOS marker that begins another scan. + (But it reads no input if jpeg_consume_input() has already reached the + end of the file or a SOS marker beyond the target output scan.) +* jpeg_finish_decompress() will read until the end of file, and thus can + suspend if the end hasn't already been reached (as can be tested by + calling jpeg_input_complete()). +jpeg_start_output(), jpeg_finish_output(), and jpeg_finish_decompress() +all return TRUE if they completed their tasks, FALSE if they had to suspend. +In the event of a FALSE return, the application must load more input data +and repeat the call. Applications that use non-suspending data sources need +not check the return values of these three routines. + + +It is possible to change decoding parameters between output passes in the +buffered-image mode. The decoder library currently supports only very +limited changes of parameters. ONLY THE FOLLOWING parameter changes are +allowed after jpeg_start_decompress() is called: +* dct_method can be changed before each call to jpeg_start_output(). + For example, one could use a fast DCT method for early scans, changing + to a higher quality method for the final scan. +* dither_mode can be changed before each call to jpeg_start_output(); + of course this has no impact if not using color quantization. Typically + one would use ordered dither for initial passes, then switch to + Floyd-Steinberg dither for the final pass. Caution: changing dither mode + can cause more memory to be allocated by the library. Although the amount + of memory involved is not large (a scanline or so), it may cause the + initial max_memory_to_use specification to be exceeded, which in the worst + case would result in an out-of-memory failure. +* do_block_smoothing can be changed before each call to jpeg_start_output(). + This setting is relevant only when decoding a progressive JPEG image. + During the first DC-only scan, block smoothing provides a very "fuzzy" look + instead of the very "blocky" look seen without it; which is better seems a + matter of personal taste. But block smoothing is nearly always a win + during later stages, especially when decoding a successive-approximation + image: smoothing helps to hide the slight blockiness that otherwise shows + up on smooth gradients until the lowest coefficient bits are sent. +* Color quantization mode can be changed under the rules described below. + You *cannot* change between full-color and quantized output (because that + would alter the required I/O buffer sizes), but you can change which + quantization method is used. + +When generating color-quantized output, changing quantization method is a +very useful way of switching between high-speed and high-quality display. +The library allows you to change among its three quantization methods: +1. Single-pass quantization to a fixed color cube. + Selected by cinfo.two_pass_quantize = FALSE and cinfo.colormap = NULL. +2. Single-pass quantization to an application-supplied colormap. + Selected by setting cinfo.colormap to point to the colormap (the value of + two_pass_quantize is ignored); also set cinfo.actual_number_of_colors. +3. Two-pass quantization to a colormap chosen specifically for the image. + Selected by cinfo.two_pass_quantize = TRUE and cinfo.colormap = NULL. + (This is the default setting selected by jpeg_read_header, but it is + probably NOT what you want for the first pass of progressive display!) +These methods offer successively better quality and lesser speed. However, +only the first method is available for quantizing in non-RGB color spaces. + +IMPORTANT: because the different quantizer methods have very different +working-storage requirements, the library requires you to indicate which +one(s) you intend to use before you call jpeg_start_decompress(). (If we did +not require this, the max_memory_to_use setting would be a complete fiction.) +You do this by setting one or more of these three cinfo fields to TRUE: + enable_1pass_quant Fixed color cube colormap + enable_external_quant Externally-supplied colormap + enable_2pass_quant Two-pass custom colormap +All three are initialized FALSE by jpeg_read_header(). But +jpeg_start_decompress() automatically sets TRUE the one selected by the +current two_pass_quantize and colormap settings, so you only need to set the +enable flags for any other quantization methods you plan to change to later. + +After setting the enable flags correctly at jpeg_start_decompress() time, you +can change to any enabled quantization method by setting two_pass_quantize +and colormap properly just before calling jpeg_start_output(). The following +special rules apply: +1. You must explicitly set cinfo.colormap to NULL when switching to 1-pass + or 2-pass mode from a different mode, or when you want the 2-pass + quantizer to be re-run to generate a new colormap. +2. To switch to an external colormap, or to change to a different external + colormap than was used on the prior pass, you must call + jpeg_new_colormap() after setting cinfo.colormap. +NOTE: if you want to use the same colormap as was used in the prior pass, +you should not do either of these things. This will save some nontrivial +switchover costs. +(These requirements exist because cinfo.colormap will always be non-NULL +after completing a prior output pass, since both the 1-pass and 2-pass +quantizers set it to point to their output colormaps. Thus you have to +do one of these two things to notify the library that something has changed. +Yup, it's a bit klugy, but it's necessary to do it this way for backwards +compatibility.) + +Note that in buffered-image mode, the library generates any requested colormap +during jpeg_start_output(), not during jpeg_start_decompress(). + +When using two-pass quantization, jpeg_start_output() makes a pass over the +buffered image to determine the optimum color map; it therefore may take a +significant amount of time, whereas ordinarily it does little work. The +progress monitor hook is called during this pass, if defined. It is also +important to realize that if the specified target scan number is greater than +or equal to the current input scan number, jpeg_start_output() will attempt +to consume input as it makes this pass. If you use a suspending data source, +you need to check for a FALSE return from jpeg_start_output() under these +conditions. The combination of 2-pass quantization and a not-yet-fully-read +target scan is the only case in which jpeg_start_output() will consume input. + + +Application authors who support buffered-image mode may be tempted to use it +for all JPEG images, even single-scan ones. This will work, but it is +inefficient: there is no need to create an image-sized coefficient buffer for +single-scan images. Requesting buffered-image mode for such an image wastes +memory. Worse, it can cost time on large images, since the buffered data has +to be swapped out or written to a temporary file. If you are concerned about +maximum performance on baseline JPEG files, you should use buffered-image +mode only when the incoming file actually has multiple scans. This can be +tested by calling jpeg_has_multiple_scans(), which will return a correct +result at any time after jpeg_read_header() completes. + +It is also worth noting that when you use jpeg_consume_input() to let input +processing get ahead of output processing, the resulting pattern of access to +the coefficient buffer is quite nonsequential. It's best to use the memory +manager jmemnobs.c if you can (ie, if you have enough real or virtual main +memory). If not, at least make sure that max_memory_to_use is set as high as +possible. If the JPEG memory manager has to use a temporary file, you will +probably see a lot of disk traffic and poor performance. (This could be +improved with additional work on the memory manager, but we haven't gotten +around to it yet.) + +In some applications it may be convenient to use jpeg_consume_input() for all +input processing, including reading the initial markers; that is, you may +wish to call jpeg_consume_input() instead of jpeg_read_header() during +startup. This works, but note that you must check for JPEG_REACHED_SOS and +JPEG_REACHED_EOI return codes as the equivalent of jpeg_read_header's codes. +Once the first SOS marker has been reached, you must call +jpeg_start_decompress() before jpeg_consume_input() will consume more input; +it'll just keep returning JPEG_REACHED_SOS until you do. If you read a +tables-only file this way, jpeg_consume_input() will return JPEG_REACHED_EOI +without ever returning JPEG_REACHED_SOS; be sure to check for this case. +If this happens, the decompressor will not read any more input until you call +jpeg_abort() to reset it. It is OK to call jpeg_consume_input() even when not +using buffered-image mode, but in that case it's basically a no-op after the +initial markers have been read: it will just return JPEG_SUSPENDED. + + +Abbreviated datastreams and multiple images +------------------------------------------- + +A JPEG compression or decompression object can be reused to process multiple +images. This saves a small amount of time per image by eliminating the +"create" and "destroy" operations, but that isn't the real purpose of the +feature. Rather, reuse of an object provides support for abbreviated JPEG +datastreams. Object reuse can also simplify processing a series of images in +a single input or output file. This section explains these features. + +A JPEG file normally contains several hundred bytes worth of quantization +and Huffman tables. In a situation where many images will be stored or +transmitted with identical tables, this may represent an annoying overhead. +The JPEG standard therefore permits tables to be omitted. The standard +defines three classes of JPEG datastreams: + * "Interchange" datastreams contain an image and all tables needed to decode + the image. These are the usual kind of JPEG file. + * "Abbreviated image" datastreams contain an image, but are missing some or + all of the tables needed to decode that image. + * "Abbreviated table specification" (henceforth "tables-only") datastreams + contain only table specifications. +To decode an abbreviated image, it is necessary to load the missing table(s) +into the decoder beforehand. This can be accomplished by reading a separate +tables-only file. A variant scheme uses a series of images in which the first +image is an interchange (complete) datastream, while subsequent ones are +abbreviated and rely on the tables loaded by the first image. It is assumed +that once the decoder has read a table, it will remember that table until a +new definition for the same table number is encountered. + +It is the application designer's responsibility to figure out how to associate +the correct tables with an abbreviated image. While abbreviated datastreams +can be useful in a closed environment, their use is strongly discouraged in +any situation where data exchange with other applications might be needed. +Caveat designer. + +The JPEG library provides support for reading and writing any combination of +tables-only datastreams and abbreviated images. In both compression and +decompression objects, a quantization or Huffman table will be retained for +the lifetime of the object, unless it is overwritten by a new table definition. + + +To create abbreviated image datastreams, it is only necessary to tell the +compressor not to emit some or all of the tables it is using. Each +quantization and Huffman table struct contains a boolean field "sent_table", +which normally is initialized to FALSE. For each table used by the image, the +header-writing process emits the table and sets sent_table = TRUE unless it is +already TRUE. (In normal usage, this prevents outputting the same table +definition multiple times, as would otherwise occur because the chroma +components typically share tables.) Thus, setting this field to TRUE before +calling jpeg_start_compress() will prevent the table from being written at +all. + +If you want to create a "pure" abbreviated image file containing no tables, +just call "jpeg_suppress_tables(&cinfo, TRUE)" after constructing all the +tables. If you want to emit some but not all tables, you'll need to set the +individual sent_table fields directly. + +To create an abbreviated image, you must also call jpeg_start_compress() +with a second parameter of FALSE, not TRUE. Otherwise jpeg_start_compress() +will force all the sent_table fields to FALSE. (This is a safety feature to +prevent abbreviated images from being created accidentally.) + +To create a tables-only file, perform the same parameter setup that you +normally would, but instead of calling jpeg_start_compress() and so on, call +jpeg_write_tables(&cinfo). This will write an abbreviated datastream +containing only SOI, DQT and/or DHT markers, and EOI. All the quantization +and Huffman tables that are currently defined in the compression object will +be emitted unless their sent_tables flag is already TRUE, and then all the +sent_tables flags will be set TRUE. + +A sure-fire way to create matching tables-only and abbreviated image files +is to proceed as follows: + + create JPEG compression object + set JPEG parameters + set destination to tables-only file + jpeg_write_tables(&cinfo); + set destination to image file + jpeg_start_compress(&cinfo, FALSE); + write data... + jpeg_finish_compress(&cinfo); + +Since the JPEG parameters are not altered between writing the table file and +the abbreviated image file, the same tables are sure to be used. Of course, +you can repeat the jpeg_start_compress() ... jpeg_finish_compress() sequence +many times to produce many abbreviated image files matching the table file. + +You cannot suppress output of the computed Huffman tables when Huffman +optimization is selected. (If you could, there'd be no way to decode the +image...) Generally, you don't want to set optimize_coding = TRUE when +you are trying to produce abbreviated files. + +In some cases you might want to compress an image using tables which are +not stored in the application, but are defined in an interchange or +tables-only file readable by the application. This can be done by setting up +a JPEG decompression object to read the specification file, then copying the +tables into your compression object. See jpeg_copy_critical_parameters() +for an example of copying quantization tables. + + +To read abbreviated image files, you simply need to load the proper tables +into the decompression object before trying to read the abbreviated image. +If the proper tables are stored in the application program, you can just +allocate the table structs and fill in their contents directly. For example, +to load a fixed quantization table into table slot "n": + + if (cinfo.quant_tbl_ptrs[n] == NULL) + cinfo.quant_tbl_ptrs[n] = jpeg_alloc_quant_table((j_common_ptr) &cinfo); + quant_ptr = cinfo.quant_tbl_ptrs[n]; /* quant_ptr is JQUANT_TBL* */ + for (i = 0; i < 64; i++) { + /* Qtable[] is desired quantization table, in natural array order */ + quant_ptr->quantval[i] = Qtable[i]; + } + +Code to load a fixed Huffman table is typically (for AC table "n"): + + if (cinfo.ac_huff_tbl_ptrs[n] == NULL) + cinfo.ac_huff_tbl_ptrs[n] = jpeg_alloc_huff_table((j_common_ptr) &cinfo); + huff_ptr = cinfo.ac_huff_tbl_ptrs[n]; /* huff_ptr is JHUFF_TBL* */ + for (i = 1; i <= 16; i++) { + /* counts[i] is number of Huffman codes of length i bits, i=1..16 */ + huff_ptr->bits[i] = counts[i]; + } + for (i = 0; i < 256; i++) { + /* symbols[] is the list of Huffman symbols, in code-length order */ + huff_ptr->huffval[i] = symbols[i]; + } + +(Note that trying to set cinfo.quant_tbl_ptrs[n] to point directly at a +constant JQUANT_TBL object is not safe. If the incoming file happened to +contain a quantization table definition, your master table would get +overwritten! Instead allocate a working table copy and copy the master table +into it, as illustrated above. Ditto for Huffman tables, of course.) + +You might want to read the tables from a tables-only file, rather than +hard-wiring them into your application. The jpeg_read_header() call is +sufficient to read a tables-only file. You must pass a second parameter of +FALSE to indicate that you do not require an image to be present. Thus, the +typical scenario is + + create JPEG decompression object + set source to tables-only file + jpeg_read_header(&cinfo, FALSE); + set source to abbreviated image file + jpeg_read_header(&cinfo, TRUE); + set decompression parameters + jpeg_start_decompress(&cinfo); + read data... + jpeg_finish_decompress(&cinfo); + +In some cases, you may want to read a file without knowing whether it contains +an image or just tables. In that case, pass FALSE and check the return value +from jpeg_read_header(): it will be JPEG_HEADER_OK if an image was found, +JPEG_HEADER_TABLES_ONLY if only tables were found. (A third return value, +JPEG_SUSPENDED, is possible when using a suspending data source manager.) +Note that jpeg_read_header() will not complain if you read an abbreviated +image for which you haven't loaded the missing tables; the missing-table check +occurs later, in jpeg_start_decompress(). + + +It is possible to read a series of images from a single source file by +repeating the jpeg_read_header() ... jpeg_finish_decompress() sequence, +without releasing/recreating the JPEG object or the data source module. +(If you did reinitialize, any partial bufferload left in the data source +buffer at the end of one image would be discarded, causing you to lose the +start of the next image.) When you use this method, stored tables are +automatically carried forward, so some of the images can be abbreviated images +that depend on tables from earlier images. + +If you intend to write a series of images into a single destination file, +you might want to make a specialized data destination module that doesn't +flush the output buffer at term_destination() time. This would speed things +up by some trifling amount. Of course, you'd need to remember to flush the +buffer after the last image. You can make the later images be abbreviated +ones by passing FALSE to jpeg_start_compress(). + + +Special markers +--------------- + +Some applications may need to insert or extract special data in the JPEG +datastream. The JPEG standard provides marker types "COM" (comment) and +"APP0" through "APP15" (application) to hold application-specific data. +Unfortunately, the use of these markers is not specified by the standard. +COM markers are fairly widely used to hold user-supplied text. The JFIF file +format spec uses APP0 markers with specified initial strings to hold certain +data. Adobe applications use APP14 markers beginning with the string "Adobe" +for miscellaneous data. Other APPn markers are rarely seen, but might +contain almost anything. + +If you wish to store user-supplied text, we recommend you use COM markers +and place readable 7-bit ASCII text in them. Newline conventions are not +standardized --- expect to find LF (Unix style), CR/LF (DOS style), or CR +(Mac style). A robust COM reader should be able to cope with random binary +garbage, including nulls, since some applications generate COM markers +containing non-ASCII junk. (But yours should not be one of them.) + +For program-supplied data, use an APPn marker, and be sure to begin it with an +identifying string so that you can tell whether the marker is actually yours. +It's probably best to avoid using APP0 or APP14 for any private markers. +(NOTE: the upcoming SPIFF standard will use APP8 markers; we recommend you +not use APP8 markers for any private purposes, either.) + +Keep in mind that at most 65533 bytes can be put into one marker, but you +can have as many markers as you like. + +By default, the IJG compression library will write a JFIF APP0 marker if the +selected JPEG colorspace is grayscale or YCbCr, or an Adobe APP14 marker if +the selected colorspace is RGB, CMYK, or YCCK. You can disable this, but +we don't recommend it. The decompression library will recognize JFIF and +Adobe markers and will set the JPEG colorspace properly when one is found. + + +You can write special markers immediately following the datastream header by +calling jpeg_write_marker() after jpeg_start_compress() and before the first +call to jpeg_write_scanlines(). When you do this, the markers appear after +the SOI and the JFIF APP0 and Adobe APP14 markers (if written), but before +all else. Specify the marker type parameter as "JPEG_COM" for COM or +"JPEG_APP0 + n" for APPn. (Actually, jpeg_write_marker will let you write +any marker type, but we don't recommend writing any other kinds of marker.) +For example, to write a user comment string pointed to by comment_text: + jpeg_write_marker(cinfo, JPEG_COM, comment_text, strlen(comment_text)); + +If it's not convenient to store all the marker data in memory at once, +you can instead call jpeg_write_m_header() followed by multiple calls to +jpeg_write_m_byte(). If you do it this way, it's your responsibility to +call jpeg_write_m_byte() exactly the number of times given in the length +parameter to jpeg_write_m_header(). (This method lets you empty the +output buffer partway through a marker, which might be important when +using a suspending data destination module. In any case, if you are using +a suspending destination, you should flush its buffer after inserting +any special markers. See "I/O suspension".) + +Or, if you prefer to synthesize the marker byte sequence yourself, +you can just cram it straight into the data destination module. + +If you are writing JFIF 1.02 extension markers (thumbnail images), don't +forget to set cinfo.JFIF_minor_version = 2 so that the encoder will write the +correct JFIF version number in the JFIF header marker. The library's default +is to write version 1.01, but that's wrong if you insert any 1.02 extension +markers. (We could probably get away with just defaulting to 1.02, but there +used to be broken decoders that would complain about unknown minor version +numbers. To reduce compatibility risks it's safest not to write 1.02 unless +you are actually using 1.02 extensions.) + + +When reading, two methods of handling special markers are available: +1. You can ask the library to save the contents of COM and/or APPn markers +into memory, and then examine them at your leisure afterwards. +2. You can supply your own routine to process COM and/or APPn markers +on-the-fly as they are read. +The first method is simpler to use, especially if you are using a suspending +data source; writing a marker processor that copes with input suspension is +not easy (consider what happens if the marker is longer than your available +input buffer). However, the second method conserves memory since the marker +data need not be kept around after it's been processed. + +For either method, you'd normally set up marker handling after creating a +decompression object and before calling jpeg_read_header(), because the +markers of interest will typically be near the head of the file and so will +be scanned by jpeg_read_header. Once you've established a marker handling +method, it will be used for the life of that decompression object +(potentially many datastreams), unless you change it. Marker handling is +determined separately for COM markers and for each APPn marker code. + + +To save the contents of special markers in memory, call + jpeg_save_markers(cinfo, marker_code, length_limit) +where marker_code is the marker type to save, JPEG_COM or JPEG_APP0+n. +(To arrange to save all the special marker types, you need to call this +routine 17 times, for COM and APP0-APP15.) If the incoming marker is longer +than length_limit data bytes, only length_limit bytes will be saved; this +parameter allows you to avoid chewing up memory when you only need to see the +first few bytes of a potentially large marker. If you want to save all the +data, set length_limit to 0xFFFF; that is enough since marker lengths are only +16 bits. As a special case, setting length_limit to 0 prevents that marker +type from being saved at all. (That is the default behavior, in fact.) + +After jpeg_read_header() completes, you can examine the special markers by +following the cinfo->marker_list pointer chain. All the special markers in +the file appear in this list, in order of their occurrence in the file (but +omitting any markers of types you didn't ask for). Both the original data +length and the saved data length are recorded for each list entry; the latter +will not exceed length_limit for the particular marker type. Note that these +lengths exclude the marker length word, whereas the stored representation +within the JPEG file includes it. (Hence the maximum data length is really +only 65533.) + +It is possible that additional special markers appear in the file beyond the +SOS marker at which jpeg_read_header stops; if so, the marker list will be +extended during reading of the rest of the file. This is not expected to be +common, however. If you are short on memory you may want to reset the length +limit to zero for all marker types after finishing jpeg_read_header, to +ensure that the max_memory_to_use setting cannot be exceeded due to addition +of later markers. + +The marker list remains stored until you call jpeg_finish_decompress or +jpeg_abort, at which point the memory is freed and the list is set to empty. +(jpeg_destroy also releases the storage, of course.) + +Note that the library is internally interested in APP0 and APP14 markers; +if you try to set a small nonzero length limit on these types, the library +will silently force the length up to the minimum it wants. (But you can set +a zero length limit to prevent them from being saved at all.) Also, in a +16-bit environment, the maximum length limit may be constrained to less than +65533 by malloc() limitations. It is therefore best not to assume that the +effective length limit is exactly what you set it to be. + + +If you want to supply your own marker-reading routine, you do it by calling +jpeg_set_marker_processor(). A marker processor routine must have the +signature + boolean jpeg_marker_parser_method (j_decompress_ptr cinfo) +Although the marker code is not explicitly passed, the routine can find it +in cinfo->unread_marker. At the time of call, the marker proper has been +read from the data source module. The processor routine is responsible for +reading the marker length word and the remaining parameter bytes, if any. +Return TRUE to indicate success. (FALSE should be returned only if you are +using a suspending data source and it tells you to suspend. See the standard +marker processors in jdmarker.c for appropriate coding methods if you need to +use a suspending data source.) + +If you override the default APP0 or APP14 processors, it is up to you to +recognize JFIF and Adobe markers if you want colorspace recognition to occur +properly. We recommend copying and extending the default processors if you +want to do that. (A better idea is to save these marker types for later +examination by calling jpeg_save_markers(); that method doesn't interfere +with the library's own processing of these markers.) + +jpeg_set_marker_processor() and jpeg_save_markers() are mutually exclusive +--- if you call one it overrides any previous call to the other, for the +particular marker type specified. + +A simple example of an external COM processor can be found in djpeg.c. +Also, see jpegtran.c for an example of using jpeg_save_markers. + + +Raw (downsampled) image data +---------------------------- + +Some applications need to supply already-downsampled image data to the JPEG +compressor, or to receive raw downsampled data from the decompressor. The +library supports this requirement by allowing the application to write or +read raw data, bypassing the normal preprocessing or postprocessing steps. +The interface is different from the standard one and is somewhat harder to +use. If your interest is merely in bypassing color conversion, we recommend +that you use the standard interface and simply set jpeg_color_space = +in_color_space (or jpeg_color_space = out_color_space for decompression). +The mechanism described in this section is necessary only to supply or +receive downsampled image data, in which not all components have the same +dimensions. + + +To compress raw data, you must supply the data in the colorspace to be used +in the JPEG file (please read the earlier section on Special color spaces) +and downsampled to the sampling factors specified in the JPEG parameters. +You must supply the data in the format used internally by the JPEG library, +namely a JSAMPIMAGE array. This is an array of pointers to two-dimensional +arrays, each of type JSAMPARRAY. Each 2-D array holds the values for one +color component. This structure is necessary since the components are of +different sizes. If the image dimensions are not a multiple of the MCU size, +you must also pad the data correctly (usually, this is done by replicating +the last column and/or row). The data must be padded to a multiple of a DCT +block in each component: that is, each downsampled row must contain a +multiple of 8 valid samples, and there must be a multiple of 8 sample rows +for each component. (For applications such as conversion of digital TV +images, the standard image size is usually a multiple of the DCT block size, +so that no padding need actually be done.) + +The procedure for compression of raw data is basically the same as normal +compression, except that you call jpeg_write_raw_data() in place of +jpeg_write_scanlines(). Before calling jpeg_start_compress(), you must do +the following: + * Set cinfo->raw_data_in to TRUE. (It is set FALSE by jpeg_set_defaults().) + This notifies the library that you will be supplying raw data. + * Ensure jpeg_color_space is correct --- an explicit jpeg_set_colorspace() + call is a good idea. Note that since color conversion is bypassed, + in_color_space is ignored, except that jpeg_set_defaults() uses it to + choose the default jpeg_color_space setting. + * Ensure the sampling factors, cinfo->comp_info[i].h_samp_factor and + cinfo->comp_info[i].v_samp_factor, are correct. Since these indicate the + dimensions of the data you are supplying, it's wise to set them + explicitly, rather than assuming the library's defaults are what you want. + +To pass raw data to the library, call jpeg_write_raw_data() in place of +jpeg_write_scanlines(). The two routines work similarly except that +jpeg_write_raw_data takes a JSAMPIMAGE data array rather than JSAMPARRAY. +The scanlines count passed to and returned from jpeg_write_raw_data is +measured in terms of the component with the largest v_samp_factor. + +jpeg_write_raw_data() processes one MCU row per call, which is to say +v_samp_factor*DCTSIZE sample rows of each component. The passed num_lines +value must be at least max_v_samp_factor*DCTSIZE, and the return value will +be exactly that amount (or possibly some multiple of that amount, in future +library versions). This is true even on the last call at the bottom of the +image; don't forget to pad your data as necessary. + +The required dimensions of the supplied data can be computed for each +component as + cinfo->comp_info[i].width_in_blocks*DCTSIZE samples per row + cinfo->comp_info[i].height_in_blocks*DCTSIZE rows in image +after jpeg_start_compress() has initialized those fields. If the valid data +is smaller than this, it must be padded appropriately. For some sampling +factors and image sizes, additional dummy DCT blocks are inserted to make +the image a multiple of the MCU dimensions. The library creates such dummy +blocks itself; it does not read them from your supplied data. Therefore you +need never pad by more than DCTSIZE samples. An example may help here. +Assume 2h2v downsampling of YCbCr data, that is + cinfo->comp_info[0].h_samp_factor = 2 for Y + cinfo->comp_info[0].v_samp_factor = 2 + cinfo->comp_info[1].h_samp_factor = 1 for Cb + cinfo->comp_info[1].v_samp_factor = 1 + cinfo->comp_info[2].h_samp_factor = 1 for Cr + cinfo->comp_info[2].v_samp_factor = 1 +and suppose that the nominal image dimensions (cinfo->image_width and +cinfo->image_height) are 101x101 pixels. Then jpeg_start_compress() will +compute downsampled_width = 101 and width_in_blocks = 13 for Y, +downsampled_width = 51 and width_in_blocks = 7 for Cb and Cr (and the same +for the height fields). You must pad the Y data to at least 13*8 = 104 +columns and rows, the Cb/Cr data to at least 7*8 = 56 columns and rows. The +MCU height is max_v_samp_factor = 2 DCT rows so you must pass at least 16 +scanlines on each call to jpeg_write_raw_data(), which is to say 16 actual +sample rows of Y and 8 each of Cb and Cr. A total of 7 MCU rows are needed, +so you must pass a total of 7*16 = 112 "scanlines". The last DCT block row +of Y data is dummy, so it doesn't matter what you pass for it in the data +arrays, but the scanlines count must total up to 112 so that all of the Cb +and Cr data gets passed. + +Output suspension is supported with raw-data compression: if the data +destination module suspends, jpeg_write_raw_data() will return 0. +In this case the same data rows must be passed again on the next call. + + +Decompression with raw data output implies bypassing all postprocessing: +you cannot ask for rescaling or color quantization, for instance. More +seriously, you must deal with the color space and sampling factors present in +the incoming file. If your application only handles, say, 2h1v YCbCr data, +you must check for and fail on other color spaces or other sampling factors. +The library will not convert to a different color space for you. + +To obtain raw data output, set cinfo->raw_data_out = TRUE before +jpeg_start_decompress() (it is set FALSE by jpeg_read_header()). Be sure to +verify that the color space and sampling factors are ones you can handle. +Then call jpeg_read_raw_data() in place of jpeg_read_scanlines(). The +decompression process is otherwise the same as usual. + +jpeg_read_raw_data() returns one MCU row per call, and thus you must pass a +buffer of at least max_v_samp_factor*DCTSIZE scanlines (scanline counting is +the same as for raw-data compression). The buffer you pass must be large +enough to hold the actual data plus padding to DCT-block boundaries. As with +compression, any entirely dummy DCT blocks are not processed so you need not +allocate space for them, but the total scanline count includes them. The +above example of computing buffer dimensions for raw-data compression is +equally valid for decompression. + +Input suspension is supported with raw-data decompression: if the data source +module suspends, jpeg_read_raw_data() will return 0. You can also use +buffered-image mode to read raw data in multiple passes. + + +Really raw data: DCT coefficients +--------------------------------- + +It is possible to read or write the contents of a JPEG file as raw DCT +coefficients. This facility is mainly intended for use in lossless +transcoding between different JPEG file formats. Other possible applications +include lossless cropping of a JPEG image, lossless reassembly of a +multi-strip or multi-tile TIFF/JPEG file into a single JPEG datastream, etc. + +To read the contents of a JPEG file as DCT coefficients, open the file and do +jpeg_read_header() as usual. But instead of calling jpeg_start_decompress() +and jpeg_read_scanlines(), call jpeg_read_coefficients(). This will read the +entire image into a set of virtual coefficient-block arrays, one array per +component. The return value is a pointer to an array of virtual-array +descriptors. Each virtual array can be accessed directly using the JPEG +memory manager's access_virt_barray method (see Memory management, below, +and also read structure.doc's discussion of virtual array handling). Or, +for simple transcoding to a different JPEG file format, the array list can +just be handed directly to jpeg_write_coefficients(). + +Each block in the block arrays contains quantized coefficient values in +normal array order (not JPEG zigzag order). The block arrays contain only +DCT blocks containing real data; any entirely-dummy blocks added to fill out +interleaved MCUs at the right or bottom edges of the image are discarded +during reading and are not stored in the block arrays. (The size of each +block array can be determined from the width_in_blocks and height_in_blocks +fields of the component's comp_info entry.) This is also the data format +expected by jpeg_write_coefficients(). + +When you are done using the virtual arrays, call jpeg_finish_decompress() +to release the array storage and return the decompression object to an idle +state; or just call jpeg_destroy() if you don't need to reuse the object. + +If you use a suspending data source, jpeg_read_coefficients() will return +NULL if it is forced to suspend; a non-NULL return value indicates successful +completion. You need not test for a NULL return value when using a +non-suspending data source. + +It is also possible to call jpeg_read_coefficients() to obtain access to the +decoder's coefficient arrays during a normal decode cycle in buffered-image +mode. This frammish might be useful for progressively displaying an incoming +image and then re-encoding it without loss. To do this, decode in buffered- +image mode as discussed previously, then call jpeg_read_coefficients() after +the last jpeg_finish_output() call. The arrays will be available for your use +until you call jpeg_finish_decompress(). + + +To write the contents of a JPEG file as DCT coefficients, you must provide +the DCT coefficients stored in virtual block arrays. You can either pass +block arrays read from an input JPEG file by jpeg_read_coefficients(), or +allocate virtual arrays from the JPEG compression object and fill them +yourself. In either case, jpeg_write_coefficients() is substituted for +jpeg_start_compress() and jpeg_write_scanlines(). Thus the sequence is + * Create compression object + * Set all compression parameters as necessary + * Request virtual arrays if needed + * jpeg_write_coefficients() + * jpeg_finish_compress() + * Destroy or re-use compression object +jpeg_write_coefficients() is passed a pointer to an array of virtual block +array descriptors; the number of arrays is equal to cinfo.num_components. + +The virtual arrays need only have been requested, not realized, before +jpeg_write_coefficients() is called. A side-effect of +jpeg_write_coefficients() is to realize any virtual arrays that have been +requested from the compression object's memory manager. Thus, when obtaining +the virtual arrays from the compression object, you should fill the arrays +after calling jpeg_write_coefficients(). The data is actually written out +when you call jpeg_finish_compress(); jpeg_write_coefficients() only writes +the file header. + +When writing raw DCT coefficients, it is crucial that the JPEG quantization +tables and sampling factors match the way the data was encoded, or the +resulting file will be invalid. For transcoding from an existing JPEG file, +we recommend using jpeg_copy_critical_parameters(). This routine initializes +all the compression parameters to default values (like jpeg_set_defaults()), +then copies the critical information from a source decompression object. +The decompression object should have just been used to read the entire +JPEG input file --- that is, it should be awaiting jpeg_finish_decompress(). + +jpeg_write_coefficients() marks all tables stored in the compression object +as needing to be written to the output file (thus, it acts like +jpeg_start_compress(cinfo, TRUE)). This is for safety's sake, to avoid +emitting abbreviated JPEG files by accident. If you really want to emit an +abbreviated JPEG file, call jpeg_suppress_tables(), or set the tables' +individual sent_table flags, between calling jpeg_write_coefficients() and +jpeg_finish_compress(). + + +Progress monitoring +------------------- + +Some applications may need to regain control from the JPEG library every so +often. The typical use of this feature is to produce a percent-done bar or +other progress display. (For a simple example, see cjpeg.c or djpeg.c.) +Although you do get control back frequently during the data-transferring pass +(the jpeg_read_scanlines or jpeg_write_scanlines loop), any additional passes +will occur inside jpeg_finish_compress or jpeg_start_decompress; those +routines may take a long time to execute, and you don't get control back +until they are done. + +You can define a progress-monitor routine which will be called periodically +by the library. No guarantees are made about how often this call will occur, +so we don't recommend you use it for mouse tracking or anything like that. +At present, a call will occur once per MCU row, scanline, or sample row +group, whichever unit is convenient for the current processing mode; so the +wider the image, the longer the time between calls. During the data +transferring pass, only one call occurs per call of jpeg_read_scanlines or +jpeg_write_scanlines, so don't pass a large number of scanlines at once if +you want fine resolution in the progress count. (If you really need to use +the callback mechanism for time-critical tasks like mouse tracking, you could +insert additional calls inside some of the library's inner loops.) + +To establish a progress-monitor callback, create a struct jpeg_progress_mgr, +fill in its progress_monitor field with a pointer to your callback routine, +and set cinfo->progress to point to the struct. The callback will be called +whenever cinfo->progress is non-NULL. (This pointer is set to NULL by +jpeg_create_compress or jpeg_create_decompress; the library will not change +it thereafter. So if you allocate dynamic storage for the progress struct, +make sure it will live as long as the JPEG object does. Allocating from the +JPEG memory manager with lifetime JPOOL_PERMANENT will work nicely.) You +can use the same callback routine for both compression and decompression. + +The jpeg_progress_mgr struct contains four fields which are set by the library: + long pass_counter; /* work units completed in this pass */ + long pass_limit; /* total number of work units in this pass */ + int completed_passes; /* passes completed so far */ + int total_passes; /* total number of passes expected */ +During any one pass, pass_counter increases from 0 up to (not including) +pass_limit; the step size is usually but not necessarily 1. The pass_limit +value may change from one pass to another. The expected total number of +passes is in total_passes, and the number of passes already completed is in +completed_passes. Thus the fraction of work completed may be estimated as + completed_passes + (pass_counter/pass_limit) + -------------------------------------------- + total_passes +ignoring the fact that the passes may not be equal amounts of work. + +When decompressing, pass_limit can even change within a pass, because it +depends on the number of scans in the JPEG file, which isn't always known in +advance. The computed fraction-of-work-done may jump suddenly (if the library +discovers it has overestimated the number of scans) or even decrease (in the +opposite case). It is not wise to put great faith in the work estimate. + +When using the decompressor's buffered-image mode, the progress monitor work +estimate is likely to be completely unhelpful, because the library has no way +to know how many output passes will be demanded of it. Currently, the library +sets total_passes based on the assumption that there will be one more output +pass if the input file end hasn't yet been read (jpeg_input_complete() isn't +TRUE), but no more output passes if the file end has been reached when the +output pass is started. This means that total_passes will rise as additional +output passes are requested. If you have a way of determining the input file +size, estimating progress based on the fraction of the file that's been read +will probably be more useful than using the library's value. + + +Memory management +----------------- + +This section covers some key facts about the JPEG library's built-in memory +manager. For more info, please read structure.doc's section about the memory +manager, and consult the source code if necessary. + +All memory and temporary file allocation within the library is done via the +memory manager. If necessary, you can replace the "back end" of the memory +manager to control allocation yourself (for example, if you don't want the +library to use malloc() and free() for some reason). + +Some data is allocated "permanently" and will not be freed until the JPEG +object is destroyed. Most data is allocated "per image" and is freed by +jpeg_finish_compress, jpeg_finish_decompress, or jpeg_abort. You can call the +memory manager yourself to allocate structures that will automatically be +freed at these times. Typical code for this is + ptr = (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, size); +Use JPOOL_PERMANENT to get storage that lasts as long as the JPEG object. +Use alloc_large instead of alloc_small for anything bigger than a few Kbytes. +There are also alloc_sarray and alloc_barray routines that automatically +build 2-D sample or block arrays. + +The library's minimum space requirements to process an image depend on the +image's width, but not on its height, because the library ordinarily works +with "strip" buffers that are as wide as the image but just a few rows high. +Some operating modes (eg, two-pass color quantization) require full-image +buffers. Such buffers are treated as "virtual arrays": only the current strip +need be in memory, and the rest can be swapped out to a temporary file. + +If you use the simplest memory manager back end (jmemnobs.c), then no +temporary files are used; virtual arrays are simply malloc()'d. Images bigger +than memory can be processed only if your system supports virtual memory. +The other memory manager back ends support temporary files of various flavors +and thus work in machines without virtual memory. They may also be useful on +Unix machines if you need to process images that exceed available swap space. + +When using temporary files, the library will make the in-memory buffers for +its virtual arrays just big enough to stay within a "maximum memory" setting. +Your application can set this limit by setting cinfo->mem->max_memory_to_use +after creating the JPEG object. (Of course, there is still a minimum size for +the buffers, so the max-memory setting is effective only if it is bigger than +the minimum space needed.) If you allocate any large structures yourself, you +must allocate them before jpeg_start_compress() or jpeg_start_decompress() in +order to have them counted against the max memory limit. Also keep in mind +that space allocated with alloc_small() is ignored, on the assumption that +it's too small to be worth worrying about; so a reasonable safety margin +should be left when setting max_memory_to_use. + +If you use the jmemname.c or jmemdos.c memory manager back end, it is +important to clean up the JPEG object properly to ensure that the temporary +files get deleted. (This is especially crucial with jmemdos.c, where the +"temporary files" may be extended-memory segments; if they are not freed, +DOS will require a reboot to recover the memory.) Thus, with these memory +managers, it's a good idea to provide a signal handler that will trap any +early exit from your program. The handler should call either jpeg_abort() +or jpeg_destroy() for any active JPEG objects. A handler is not needed with +jmemnobs.c, and shouldn't be necessary with jmemansi.c or jmemmac.c either, +since the C library is supposed to take care of deleting files made with +tmpfile(). + + +Memory usage +------------ + +Working memory requirements while performing compression or decompression +depend on image dimensions, image characteristics (such as colorspace and +JPEG process), and operating mode (application-selected options). + +As of v6b, the decompressor requires: + 1. About 24K in more-or-less-fixed-size data. This varies a bit depending + on operating mode and image characteristics (particularly color vs. + grayscale), but it doesn't depend on image dimensions. + 2. Strip buffers (of size proportional to the image width) for IDCT and + upsampling results. The worst case for commonly used sampling factors + is about 34 bytes * width in pixels for a color image. A grayscale image + only needs about 8 bytes per pixel column. + 3. A full-image DCT coefficient buffer is needed to decode a multi-scan JPEG + file (including progressive JPEGs), or whenever you select buffered-image + mode. This takes 2 bytes/coefficient. At typical 2x2 sampling, that's + 3 bytes per pixel for a color image. Worst case (1x1 sampling) requires + 6 bytes/pixel. For grayscale, figure 2 bytes/pixel. + 4. To perform 2-pass color quantization, the decompressor also needs a + 128K color lookup table and a full-image pixel buffer (3 bytes/pixel). +This does not count any memory allocated by the application, such as a +buffer to hold the final output image. + +The above figures are valid for 8-bit JPEG data precision and a machine with +32-bit ints. For 12-bit JPEG data, double the size of the strip buffers and +quantization pixel buffer. The "fixed-size" data will be somewhat smaller +with 16-bit ints, larger with 64-bit ints. Also, CMYK or other unusual +color spaces will require different amounts of space. + +The full-image coefficient and pixel buffers, if needed at all, do not +have to be fully RAM resident; you can have the library use temporary +files instead when the total memory usage would exceed a limit you set. +(But if your OS supports virtual memory, it's probably better to just use +jmemnobs and let the OS do the swapping.) + +The compressor's memory requirements are similar, except that it has no need +for color quantization. Also, it needs a full-image DCT coefficient buffer +if Huffman-table optimization is asked for, even if progressive mode is not +requested. + +If you need more detailed information about memory usage in a particular +situation, you can enable the MEM_STATS code in jmemmgr.c. + + +Library compile-time options +---------------------------- + +A number of compile-time options are available by modifying jmorecfg.h. + +The JPEG standard provides for both the baseline 8-bit DCT process and +a 12-bit DCT process. The IJG code supports 12-bit lossy JPEG if you define +BITS_IN_JSAMPLE as 12 rather than 8. Note that this causes JSAMPLE to be +larger than a char, so it affects the surrounding application's image data. +The sample applications cjpeg and djpeg can support 12-bit mode only for PPM +and GIF file formats; you must disable the other file formats to compile a +12-bit cjpeg or djpeg. (install.doc has more information about that.) +At present, a 12-bit library can handle *only* 12-bit images, not both +precisions. (If you need to include both 8- and 12-bit libraries in a single +application, you could probably do it by defining NEED_SHORT_EXTERNAL_NAMES +for just one of the copies. You'd have to access the 8-bit and 12-bit copies +from separate application source files. This is untested ... if you try it, +we'd like to hear whether it works!) + +Note that a 12-bit library always compresses in Huffman optimization mode, +in order to generate valid Huffman tables. This is necessary because our +default Huffman tables only cover 8-bit data. If you need to output 12-bit +files in one pass, you'll have to supply suitable default Huffman tables. +You may also want to supply your own DCT quantization tables; the existing +quality-scaling code has been developed for 8-bit use, and probably doesn't +generate especially good tables for 12-bit. + +The maximum number of components (color channels) in the image is determined +by MAX_COMPONENTS. The JPEG standard allows up to 255 components, but we +expect that few applications will need more than four or so. + +On machines with unusual data type sizes, you may be able to improve +performance or reduce memory space by tweaking the various typedefs in +jmorecfg.h. In particular, on some RISC CPUs, access to arrays of "short"s +is quite slow; consider trading memory for speed by making JCOEF, INT16, and +UINT16 be "int" or "unsigned int". UINT8 is also a candidate to become int. +You probably don't want to make JSAMPLE be int unless you have lots of memory +to burn. + +You can reduce the size of the library by compiling out various optional +functions. To do this, undefine xxx_SUPPORTED symbols as necessary. + +You can also save a few K by not having text error messages in the library; +the standard error message table occupies about 5Kb. This is particularly +reasonable for embedded applications where there's no good way to display +a message anyway. To do this, remove the creation of the message table +(jpeg_std_message_table[]) from jerror.c, and alter format_message to do +something reasonable without it. You could output the numeric value of the +message code number, for example. If you do this, you can also save a couple +more K by modifying the TRACEMSn() macros in jerror.h to expand to nothing; +you don't need trace capability anyway, right? + + +Portability considerations +-------------------------- + +The JPEG library has been written to be extremely portable; the sample +applications cjpeg and djpeg are slightly less so. This section summarizes +the design goals in this area. (If you encounter any bugs that cause the +library to be less portable than is claimed here, we'd appreciate hearing +about them.) + +The code works fine on ANSI C, C++, and pre-ANSI C compilers, using any of +the popular system include file setups, and some not-so-popular ones too. +See install.doc for configuration procedures. + +The code is not dependent on the exact sizes of the C data types. As +distributed, we make the assumptions that + char is at least 8 bits wide + short is at least 16 bits wide + int is at least 16 bits wide + long is at least 32 bits wide +(These are the minimum requirements of the ANSI C standard.) Wider types will +work fine, although memory may be used inefficiently if char is much larger +than 8 bits or short is much bigger than 16 bits. The code should work +equally well with 16- or 32-bit ints. + +In a system where these assumptions are not met, you may be able to make the +code work by modifying the typedefs in jmorecfg.h. However, you will probably +have difficulty if int is less than 16 bits wide, since references to plain +int abound in the code. + +char can be either signed or unsigned, although the code runs faster if an +unsigned char type is available. If char is wider than 8 bits, you will need +to redefine JOCTET and/or provide custom data source/destination managers so +that JOCTET represents exactly 8 bits of data on external storage. + +The JPEG library proper does not assume ASCII representation of characters. +But some of the image file I/O modules in cjpeg/djpeg do have ASCII +dependencies in file-header manipulation; so does cjpeg's select_file_type() +routine. + +The JPEG library does not rely heavily on the C library. In particular, C +stdio is used only by the data source/destination modules and the error +handler, all of which are application-replaceable. (cjpeg/djpeg are more +heavily dependent on stdio.) malloc and free are called only from the memory +manager "back end" module, so you can use a different memory allocator by +replacing that one file. + +The code generally assumes that C names must be unique in the first 15 +characters. However, global function names can be made unique in the +first 6 characters by defining NEED_SHORT_EXTERNAL_NAMES. + +More info about porting the code may be gleaned by reading jconfig.doc, +jmorecfg.h, and jinclude.h. + + +Notes for MS-DOS implementors +----------------------------- + +The IJG code is designed to work efficiently in 80x86 "small" or "medium" +memory models (i.e., data pointers are 16 bits unless explicitly declared +"far"; code pointers can be either size). You may be able to use small +model to compile cjpeg or djpeg by itself, but you will probably have to use +medium model for any larger application. This won't make much difference in +performance. You *will* take a noticeable performance hit if you use a +large-data memory model (perhaps 10%-25%), and you should avoid "huge" model +if at all possible. + +The JPEG library typically needs 2Kb-3Kb of stack space. It will also +malloc about 20K-30K of near heap space while executing (and lots of far +heap, but that doesn't count in this calculation). This figure will vary +depending on selected operating mode, and to a lesser extent on image size. +There is also about 5Kb-6Kb of constant data which will be allocated in the +near data segment (about 4Kb of this is the error message table). +Thus you have perhaps 20K available for other modules' static data and near +heap space before you need to go to a larger memory model. The C library's +static data will account for several K of this, but that still leaves a good +deal for your needs. (If you are tight on space, you could reduce the sizes +of the I/O buffers allocated by jdatasrc.c and jdatadst.c, say from 4K to +1K. Another possibility is to move the error message table to far memory; +this should be doable with only localized hacking on jerror.c.) + +About 2K of the near heap space is "permanent" memory that will not be +released until you destroy the JPEG object. This is only an issue if you +save a JPEG object between compression or decompression operations. + +Far data space may also be a tight resource when you are dealing with large +images. The most memory-intensive case is decompression with two-pass color +quantization, or single-pass quantization to an externally supplied color +map. This requires a 128Kb color lookup table plus strip buffers amounting +to about 40 bytes per column for typical sampling ratios (eg, about 25600 +bytes for a 640-pixel-wide image). You may not be able to process wide +images if you have large data structures of your own. + +Of course, all of these concerns vanish if you use a 32-bit flat-memory-model +compiler, such as DJGPP or Watcom C. We highly recommend flat model if you +can use it; the JPEG library is significantly faster in flat model. diff --git a/dcmjpeg/docs/ijg_readme.txt b/dcmjpeg/docs/ijg_readme.txt new file mode 100644 index 00000000..24235947 --- /dev/null +++ b/dcmjpeg/docs/ijg_readme.txt @@ -0,0 +1,385 @@ +The Independent JPEG Group's JPEG software +========================================== + +README for release 6b of 27-Mar-1998 +==================================== + +This distribution contains the sixth public release of the Independent JPEG +Group's free JPEG software. You are welcome to redistribute this software and +to use it for any purpose, subject to the conditions under LEGAL ISSUES, below. + +Serious users of this software (particularly those incorporating it into +larger programs) should contact IJG at jpeg-info@uunet.uu.net to be added to +our electronic mailing list. Mailing list members are notified of updates +and have a chance to participate in technical discussions, etc. + +This software is the work of Tom Lane, Philip Gladstone, Jim Boucher, +Lee Crocker, Julian Minguillon, Luis Ortiz, George Phillips, Davide Rossi, +Guido Vollbeding, Ge' Weijers, and other members of the Independent JPEG +Group. + +IJG is not affiliated with the official ISO JPEG standards committee. + + +DOCUMENTATION ROADMAP +===================== + +This file contains the following sections: + +OVERVIEW General description of JPEG and the IJG software. +LEGAL ISSUES Copyright, lack of warranty, terms of distribution. +REFERENCES Where to learn more about JPEG. +ARCHIVE LOCATIONS Where to find newer versions of this software. +RELATED SOFTWARE Other stuff you should get. +FILE FORMAT WARS Software *not* to get. +TO DO Plans for future IJG releases. + +Other documentation files in the distribution are: + +User documentation: + install.doc How to configure and install the IJG software. + usage.doc Usage instructions for cjpeg, djpeg, jpegtran, + rdjpgcom, and wrjpgcom. + *.1 Unix-style man pages for programs (same info as usage.doc). + wizard.doc Advanced usage instructions for JPEG wizards only. + change.log Version-to-version change highlights. +Programmer and internal documentation: + libjpeg.doc How to use the JPEG library in your own programs. + example.c Sample code for calling the JPEG library. + structure.doc Overview of the JPEG library's internal structure. + filelist.doc Road map of IJG files. + coderules.doc Coding style rules --- please read if you contribute code. + +Please read at least the files install.doc and usage.doc. Useful information +can also be found in the JPEG FAQ (Frequently Asked Questions) article. See +ARCHIVE LOCATIONS below to find out where to obtain the FAQ article. + +If you want to understand how the JPEG code works, we suggest reading one or +more of the REFERENCES, then looking at the documentation files (in roughly +the order listed) before diving into the code. + + +OVERVIEW +======== + +This package contains C software to implement JPEG image compression and +decompression. JPEG (pronounced "jay-peg") is a standardized compression +method for full-color and gray-scale images. JPEG is intended for compressing +"real-world" scenes; line drawings, cartoons and other non-realistic images +are not its strong suit. JPEG is lossy, meaning that the output image is not +exactly identical to the input image. Hence you must not use JPEG if you +have to have identical output bits. However, on typical photographic images, +very good compression levels can be obtained with no visible change, and +remarkably high compression levels are possible if you can tolerate a +low-quality image. For more details, see the references, or just experiment +with various compression settings. + +This software implements JPEG baseline, extended-sequential, progressive +and lossless compression processes. Provision is made for supporting all +variants of these processes, although some uncommon parameter settings aren't +implemented yet. For legal reasons, we are not distributing code for the +arithmetic-coding variants of JPEG; see LEGAL ISSUES. We have made no +provision for supporting the hierarchical processes defined in the standard. + +We provide a set of library routines for reading and writing JPEG image files, +plus two sample applications "cjpeg" and "djpeg", which use the library to +perform conversion between JPEG and some other popular image file formats. +The library is intended to be reused in other applications. + +In order to support file conversion and viewing software, we have included +considerable functionality beyond the bare JPEG coding/decoding capability; +for example, the color quantization modules are not strictly part of JPEG +decoding, but they are essential for output to colormapped file formats or +colormapped displays. These extra functions can be compiled out of the +library if not required for a particular application. We have also included +"jpegtran", a utility for lossless transcoding between different JPEG +processes, and "rdjpgcom" and "wrjpgcom", two simple applications for +inserting and extracting textual comments in JFIF files. + +The emphasis in designing this software has been on achieving portability and +flexibility, while also making it fast enough to be useful. In particular, +the software is not intended to be read as a tutorial on JPEG. (See the +REFERENCES section for introductory material.) Rather, it is intended to +be reliable, portable, industrial-strength code. We do not claim to have +achieved that goal in every aspect of the software, but we strive for it. + +We welcome the use of this software as a component of commercial products. +No royalty is required, but we do ask for an acknowledgement in product +documentation, as described under LEGAL ISSUES. + + +LEGAL ISSUES +============ + +In plain English: + +1. We don't promise that this software works. (But if you find any bugs, + please let us know!) +2. You can use this software for whatever you want. You don't have to pay us. +3. You may not pretend that you wrote this software. If you use it in a + program, you must acknowledge somewhere in your documentation that + you've used the IJG code. + +In legalese: + +The authors make NO WARRANTY or representation, either express or implied, +with respect to this software, its quality, accuracy, merchantability, or +fitness for a particular purpose. This software is provided "AS IS", and you, +its user, assume the entire risk as to its quality and accuracy. + +This software is copyright (C) 1991-1998, Thomas G. Lane. +All Rights Reserved except as specified below. + +Permission is hereby granted to use, copy, modify, and distribute this +software (or portions thereof) for any purpose, without fee, subject to these +conditions: +(1) If any part of the source code for this software is distributed, then this +README file must be included, with this copyright and no-warranty notice +unaltered; and any additions, deletions, or changes to the original files +must be clearly indicated in accompanying documentation. +(2) If only executable code is distributed, then the accompanying +documentation must state that "this software is based in part on the work of +the Independent JPEG Group". +(3) Permission for use of this software is granted only if the user accepts +full responsibility for any undesirable consequences; the authors accept +NO LIABILITY for damages of any kind. + +These conditions apply to any software derived from or based on the IJG code, +not just to the unmodified library. If you use our work, you ought to +acknowledge us. + +Permission is NOT granted for the use of any IJG author's name or company name +in advertising or publicity relating to this software or products derived from +it. This software may be referred to only as "the Independent JPEG Group's +software". + +We specifically permit and encourage the use of this software as the basis of +commercial products, provided that all warranty or liability claims are +assumed by the product vendor. + + +ansi2knr.c is included in this distribution by permission of L. Peter Deutsch, +sole proprietor of its copyright holder, Aladdin Enterprises of Menlo Park, CA. +ansi2knr.c is NOT covered by the above copyright and conditions, but instead +by the usual distribution terms of the Free Software Foundation; principally, +that you must include source code if you redistribute it. (See the file +ansi2knr.c for full details.) However, since ansi2knr.c is not needed as part +of any program generated from the IJG code, this does not limit you more than +the foregoing paragraphs do. + +The Unix configuration script "configure" was produced with GNU Autoconf. +It is copyright by the Free Software Foundation but is freely distributable. +The same holds for its supporting scripts (config.guess, config.sub, +ltconfig, ltmain.sh). Another support script, install-sh, is copyright +by M.I.T. but is also freely distributable. + +It appears that the arithmetic coding option of the JPEG spec is covered by +patents owned by IBM, AT&T, and Mitsubishi. Hence arithmetic coding cannot +legally be used without obtaining one or more licenses. For this reason, +support for arithmetic coding has been removed from the free JPEG software. +(Since arithmetic coding provides only a marginal gain over the unpatented +Huffman mode, it is unlikely that very many implementations will support it.) +So far as we are aware, there are no patent restrictions on the remaining +code. + +The IJG distribution formerly included code to read and write GIF files. +To avoid entanglement with the Unisys LZW patent, GIF reading support has +been removed altogether, and the GIF writer has been simplified to produce +"uncompressed GIFs". This technique does not use the LZW algorithm; the +resulting GIF files are larger than usual, but are readable by all standard +GIF decoders. + +We are required to state that + "The Graphics Interchange Format(c) is the Copyright property of + CompuServe Incorporated. GIF(sm) is a Service Mark property of + CompuServe Incorporated." + + +REFERENCES +========== + +We highly recommend reading one or more of these references before trying to +understand the innards of the JPEG software. + +The best short technical introduction to the JPEG compression algorithm is + Wallace, Gregory K. "The JPEG Still Picture Compression Standard", + Communications of the ACM, April 1991 (vol. 34 no. 4), pp. 30-44. +(Adjacent articles in that issue discuss MPEG motion picture compression, +applications of JPEG, and related topics.) If you don't have the CACM issue +handy, a PostScript file containing a revised version of Wallace's article is +available at ftp://ftp.uu.net/graphics/jpeg/wallace.ps.gz. The file (actually +a preprint for an article that appeared in IEEE Trans. Consumer Electronics) +omits the sample images that appeared in CACM, but it includes corrections +and some added material. Note: the Wallace article is copyright ACM and IEEE, +and it may not be used for commercial purposes. + +A somewhat less technical, more leisurely introduction to JPEG can be found in +"The Data Compression Book" by Mark Nelson and Jean-loup Gailly, published by +M&T Books (New York), 2nd ed. 1996, ISBN 1-55851-434-1. This book provides +good explanations and example C code for a multitude of compression methods +including JPEG. It is an excellent source if you are comfortable reading C +code but don't know much about data compression in general. The book's JPEG +sample code is far from industrial-strength, but when you are ready to look +at a full implementation, you've got one here... + +The best full description of JPEG is the textbook "JPEG Still Image Data +Compression Standard" by William B. Pennebaker and Joan L. Mitchell, published +by Van Nostrand Reinhold, 1993, ISBN 0-442-01272-1. Price US$59.95, 638 pp. +The book includes the complete text of the ISO JPEG standards (DIS 10918-1 +and draft DIS 10918-2). This is by far the most complete exposition of JPEG +in existence, and we highly recommend it. + +The JPEG standard itself is not available electronically; you must order a +paper copy through ISO or ITU. (Unless you feel a need to own a certified +official copy, we recommend buying the Pennebaker and Mitchell book instead; +it's much cheaper and includes a great deal of useful explanatory material.) +In the USA, copies of the standard may be ordered from ANSI Sales at (212) +642-4900, or from Global Engineering Documents at (800) 854-7179. (ANSI +doesn't take credit card orders, but Global does.) It's not cheap: as of +1992, ANSI was charging $95 for Part 1 and $47 for Part 2, plus 7% +shipping/handling. The standard is divided into two parts, Part 1 being the +actual specification, while Part 2 covers compliance testing methods. Part 1 +is titled "Digital Compression and Coding of Continuous-tone Still Images, +Part 1: Requirements and guidelines" and has document numbers ISO/IEC IS +10918-1, ITU-T T.81. Part 2 is titled "Digital Compression and Coding of +Continuous-tone Still Images, Part 2: Compliance testing" and has document +numbers ISO/IEC IS 10918-2, ITU-T T.83. + +Some extensions to the original JPEG standard are defined in JPEG Part 3, +a newer ISO standard numbered ISO/IEC IS 10918-3 and ITU-T T.84. IJG +currently does not support any Part 3 extensions. + +The JPEG standard does not specify all details of an interchangeable file +format. For the omitted details we follow the "JFIF" conventions, revision +1.02. A copy of the JFIF spec is available from: + Literature Department + C-Cube Microsystems, Inc. + 1778 McCarthy Blvd. + Milpitas, CA 95035 + phone (408) 944-6300, fax (408) 944-6314 +A PostScript version of this document is available by FTP at +ftp://ftp.uu.net/graphics/jpeg/jfif.ps.gz. There is also a plain text +version at ftp://ftp.uu.net/graphics/jpeg/jfif.txt.gz, but it is missing +the figures. + +The TIFF 6.0 file format specification can be obtained by FTP from +ftp://ftp.sgi.com/graphics/tiff/TIFF6.ps.gz. The JPEG incorporation scheme +found in the TIFF 6.0 spec of 3-June-92 has a number of serious problems. +IJG does not recommend use of the TIFF 6.0 design (TIFF Compression tag 6). +Instead, we recommend the JPEG design proposed by TIFF Technical Note #2 +(Compression tag 7). Copies of this Note can be obtained from ftp.sgi.com or +from ftp://ftp.uu.net/graphics/jpeg/. It is expected that the next revision +of the TIFF spec will replace the 6.0 JPEG design with the Note's design. +Although IJG's own code does not support TIFF/JPEG, the free libtiff library +uses our library to implement TIFF/JPEG per the Note. libtiff is available +from ftp://ftp.sgi.com/graphics/tiff/. + + +ARCHIVE LOCATIONS +================= + +The "official" archive site for this software is ftp.uu.net (Internet +address 192.48.96.9). The most recent released version can always be found +there in directory graphics/jpeg. This particular version will be archived +as ftp://ftp.uu.net/graphics/jpeg/jpegsrc.v6b.tar.gz. If you don't have +direct Internet access, UUNET's archives are also available via UUCP; contact +help@uunet.uu.net for information on retrieving files that way. + +Numerous Internet sites maintain copies of the UUNET files. However, only +ftp.uu.net is guaranteed to have the latest official version. + +You can also obtain this software in DOS-compatible "zip" archive format from +the SimTel archives (ftp://ftp.simtel.net/pub/simtelnet/msdos/graphics/), or +on CompuServe in the Graphics Support forum (GO CIS:GRAPHSUP), library 12 +"JPEG Tools". Again, these versions may sometimes lag behind the ftp.uu.net +release. + +The JPEG FAQ (Frequently Asked Questions) article is a useful source of +general information about JPEG. It is updated constantly and therefore is +not included in this distribution. The FAQ is posted every two weeks to +Usenet newsgroups comp.graphics.misc, news.answers, and other groups. +It is available on the World Wide Web at http://www.faqs.org/faqs/jpeg-faq/ +and other news.answers archive sites, including the official news.answers +archive at rtfm.mit.edu: ftp://rtfm.mit.edu/pub/usenet/news.answers/jpeg-faq/. +If you don't have Web or FTP access, send e-mail to mail-server@rtfm.mit.edu +with body + send usenet/news.answers/jpeg-faq/part1 + send usenet/news.answers/jpeg-faq/part2 + + +RELATED SOFTWARE +================ + +Numerous viewing and image manipulation programs now support JPEG. (Quite a +few of them use this library to do so.) The JPEG FAQ described above lists +some of the more popular free and shareware viewers, and tells where to +obtain them on Internet. + +If you are on a Unix machine, we highly recommend Jef Poskanzer's free +PBMPLUS software, which provides many useful operations on PPM-format image +files. In particular, it can convert PPM images to and from a wide range of +other formats, thus making cjpeg/djpeg considerably more useful. The latest +version is distributed by the NetPBM group, and is available from numerous +sites, notably ftp://wuarchive.wustl.edu/graphics/graphics/packages/NetPBM/. +Unfortunately PBMPLUS/NETPBM is not nearly as portable as the IJG software is; +you are likely to have difficulty making it work on any non-Unix machine. + +A different free JPEG implementation, written by the PVRG group at Stanford, +is available from ftp://havefun.stanford.edu/pub/jpeg/. This program +is designed for research and experimentation rather than production use; +it is slower, harder to use, and less portable than the IJG code, but it +is easier to read and modify. Also, the PVRG code supports lossless JPEG, +which we do not. (On the other hand, it doesn't do progressive JPEG.) + + +FILE FORMAT WARS +================ + +Some JPEG programs produce files that are not compatible with our library. +The root of the problem is that the ISO JPEG committee failed to specify a +concrete file format. Some vendors "filled in the blanks" on their own, +creating proprietary formats that no one else could read. (For example, none +of the early commercial JPEG implementations for the Macintosh were able to +exchange compressed files.) + +The file format we have adopted is called JFIF (see REFERENCES). This format +has been agreed to by a number of major commercial JPEG vendors, and it has +become the de facto standard. JFIF is a minimal or "low end" representation. +We recommend the use of TIFF/JPEG (TIFF revision 6.0 as modified by TIFF +Technical Note #2) for "high end" applications that need to record a lot of +additional data about an image. TIFF/JPEG is fairly new and not yet widely +supported, unfortunately. + +The upcoming JPEG Part 3 standard defines a file format called SPIFF. +SPIFF is interoperable with JFIF, in the sense that most JFIF decoders should +be able to read the most common variant of SPIFF. SPIFF has some technical +advantages over JFIF, but its major claim to fame is simply that it is an +official standard rather than an informal one. At this point it is unclear +whether SPIFF will supersede JFIF or whether JFIF will remain the de-facto +standard. IJG intends to support SPIFF once the standard is frozen, but we +have not decided whether it should become our default output format or not. +(In any case, our decoder will remain capable of reading JFIF indefinitely.) + +Various proprietary file formats incorporating JPEG compression also exist. +We have little or no sympathy for the existence of these formats. Indeed, +one of the original reasons for developing this free software was to help +force convergence on common, open format standards for JPEG files. Don't +use a proprietary file format! + + +TO DO +===== + +The major thrust for v7 will probably be improvement of visual quality. +The current method for scaling the quantization tables is known not to be +very good at low Q values. We also intend to investigate block boundary +smoothing, "poor man's variable quantization", and other means of improving +quality-vs-file-size performance without sacrificing compatibility. + +In future versions, we are considering supporting some of the upcoming JPEG +Part 3 extensions --- principally, variable quantization and the SPIFF file +format. + +As always, speeding things up is of great interest. + +Please send bug reports, offers of help, etc. to jpeg-info@uunet.uu.net. diff --git a/dcmjpeg/docs/ijg_structure.txt b/dcmjpeg/docs/ijg_structure.txt new file mode 100644 index 00000000..3d62accf --- /dev/null +++ b/dcmjpeg/docs/ijg_structure.txt @@ -0,0 +1,1042 @@ +IJG JPEG LIBRARY: SYSTEM ARCHITECTURE + +Copyright (C) 1991-1995, Thomas G. Lane. +This file is part of the Independent JPEG Group's software. +For conditions of distribution and use, see the accompanying README file. + + +This file provides an overview of the architecture of the IJG JPEG software; +that is, the functions of the various modules in the system and the interfaces +between modules. For more precise details about any data structure or calling +convention, see the include files and comments in the source code. + +We assume that the reader is already somewhat familiar with the JPEG standard. +The README file includes references for learning about JPEG. The file +libjpeg.doc describes the library from the viewpoint of an application +programmer using the library; it's best to read that file before this one. +Also, the file coderules.doc describes the coding style conventions we use. + +In this document, JPEG-specific terminology follows the JPEG standard: + A "component" means a color channel, e.g., Red or Luminance. + A "sample" is a single component value (i.e., one number in the image data). + A "coefficient" is a frequency coefficient (a DCT transform output number). + A "block" is an 8x8 group of samples or coefficients. + A "data unit" is an abstract data type which is either a block for lossy + (DCT-based) codecs or a sample for lossless (predictive) codecs. + An "MCU" (minimum coded unit) is an interleaved set of data units of size + determined by the sampling factors, or a single data unit in a + noninterleaved scan. +We do not use the terms "pixel" and "sample" interchangeably. When we say +pixel, we mean an element of the full-size image, while a sample is an element +of the downsampled image. Thus the number of samples may vary across +components while the number of pixels does not. (This terminology is not used +rigorously throughout the code, but it is used in places where confusion would +otherwise result.) + + +*** System features *** + +The IJG distribution contains two parts: + * A subroutine library for JPEG compression and decompression. + * cjpeg/djpeg, two sample applications that use the library to transform + JFIF JPEG files to and from several other image formats. +cjpeg/djpeg are of no great intellectual complexity: they merely add a simple +command-line user interface and I/O routines for several uncompressed image +formats. This document concentrates on the library itself. + +We desire the library to be capable of supporting all JPEG baseline, extended +sequential, and progressive DCT processes, as well as the lossless (spatial) +process. Hierarchical processes are not supported. + +Within these limits, any set of compression parameters allowed by the JPEG +spec should be readable for decompression. (We can be more restrictive about +what formats we can generate.) Although the system design allows for all +parameter values, some uncommon settings are not yet implemented and may +never be; nonintegral sampling ratios are the prime example. Furthermore, +we treat 8-bit vs. 12-bit data precision as a compile-time switch, not a +run-time option, because most machines can store 8-bit pixels much more +compactly than 12-bit. + +For legal reasons, JPEG arithmetic coding is not currently supported, but +extending the library to include it would be straightforward. + +By itself, the library handles only interchange JPEG datastreams --- in +particular the widely used JFIF file format. The library can be used by +surrounding code to process interchange or abbreviated JPEG datastreams that +are embedded in more complex file formats. (For example, libtiff uses this +library to implement JPEG compression within the TIFF file format.) + +The library includes a substantial amount of code that is not covered by the +JPEG standard but is necessary for typical applications of JPEG. These +functions preprocess the image before JPEG compression or postprocess it after +decompression. They include colorspace conversion, downsampling/upsampling, +and color quantization. This code can be omitted if not needed. + +A wide range of quality vs. speed tradeoffs are possible in JPEG processing, +and even more so in decompression postprocessing. The decompression library +provides multiple implementations that cover most of the useful tradeoffs, +ranging from very-high-quality down to fast-preview operation. On the +compression side we have generally not provided low-quality choices, since +compression is normally less time-critical. It should be understood that the +low-quality modes may not meet the JPEG standard's accuracy requirements; +nonetheless, they are useful for viewers. + + +*** Portability issues *** + +Portability is an essential requirement for the library. The key portability +issues that show up at the level of system architecture are: + +1. Memory usage. We want the code to be able to run on PC-class machines +with limited memory. Images should therefore be processed sequentially (in +strips), to avoid holding the whole image in memory at once. Where a +full-image buffer is necessary, we should be able to use either virtual memory +or temporary files. + +2. Near/far pointer distinction. To run efficiently on 80x86 machines, the +code should distinguish "small" objects (kept in near data space) from +"large" ones (kept in far data space). This is an annoying restriction, but +fortunately it does not impact code quality for less brain-damaged machines, +and the source code clutter turns out to be minimal with sufficient use of +pointer typedefs. + +3. Data precision. We assume that "char" is at least 8 bits, "short" and +"int" at least 16, "long" at least 32. The code will work fine with larger +data sizes, although memory may be used inefficiently in some cases. However, +the JPEG compressed datastream must ultimately appear on external storage as a +sequence of 8-bit bytes if it is to conform to the standard. This may pose a +problem on machines where char is wider than 8 bits. The library represents +compressed data as an array of values of typedef JOCTET. If no data type +exactly 8 bits wide is available, custom data source and data destination +modules must be written to unpack and pack the chosen JOCTET datatype into +8-bit external representation. + + +*** System overview *** + +The compressor and decompressor are each divided into two main sections: +the JPEG compressor or decompressor proper, and the preprocessing or +postprocessing functions. The interface between these two sections is the +image data that the official JPEG spec regards as its input or output: this +data is in the colorspace to be used for compression, and it is downsampled +to the sampling factors to be used. The preprocessing and postprocessing +steps are responsible for converting a normal image representation to or from +this form. (Those few applications that want to deal with YCbCr downsampled +data can skip the preprocessing or postprocessing step.) + +Looking more closely, the compressor library contains the following main +elements: + + Preprocessing: + * Color space conversion (e.g., RGB to YCbCr). + * Edge expansion and downsampling. Optionally, this step can do simple + smoothing --- this is often helpful for low-quality source data. + Lossy JPEG proper: + * MCU assembly, DCT, quantization. + * Entropy coding (sequential or progressive, Huffman or arithmetic). + Lossless JPEG proper: + * Point transform. + * Prediction, differencing. + * Entropy coding (Huffman or arithmetic) + +In addition to these modules we need overall control, marker generation, +and support code (memory management & error handling). There is also a +module responsible for physically writing the output data --- typically +this is just an interface to fwrite(), but some applications may need to +do something else with the data. + +The decompressor library contains the following main elements: + + Lossy JPEG proper: + * Entropy decoding (sequential or progressive, Huffman or arithmetic). + * Dequantization, inverse DCT, MCU disassembly. + Lossless JPEG proper: + * Entropy decoding (Huffman or arithmetic). + * Prediction, undifferencing. + * Point transform, sample size scaling. + Postprocessing: + * Upsampling. Optionally, this step may be able to do more general + rescaling of the image. + * Color space conversion (e.g., YCbCr to RGB). This step may also + provide gamma adjustment [ currently it does not ]. + * Optional color quantization (e.g., reduction to 256 colors). + * Optional color precision reduction (e.g., 24-bit to 15-bit color). + [This feature is not currently implemented.] + +We also need overall control, marker parsing, and a data source module. +The support code (memory management & error handling) can be shared with +the compression half of the library. + +There may be several implementations of each of these elements, particularly +in the decompressor, where a wide range of speed/quality tradeoffs is very +useful. It must be understood that some of the best speedups involve +merging adjacent steps in the pipeline. For example, upsampling, color space +conversion, and color quantization might all be done at once when using a +low-quality ordered-dither technique. The system architecture is designed to +allow such merging where appropriate. + + +Note: it is convenient to regard edge expansion (padding to block boundaries) +as a preprocessing/postprocessing function, even though the JPEG spec includes +it in compression/decompression. We do this because downsampling/upsampling +can be simplified a little if they work on padded data: it's not necessary to +have special cases at the right and bottom edges. Therefore the interface +buffer is always an integral number of blocks wide and high, and we expect +compression preprocessing to pad the source data properly. Padding will occur +only to the next block (8-sample) boundary. In an interleaved-scan situation, +additional dummy blocks may be used to fill out MCUs, but the MCU assembly and +disassembly logic will create or discard these blocks internally. (This is +advantageous for speed reasons, since we avoid DCTing the dummy blocks. +It also permits a small reduction in file size, because the compressor can +choose dummy block contents so as to minimize their size in compressed form. +Finally, it makes the interface buffer specification independent of whether +the file is actually interleaved or not.) Applications that wish to deal +directly with the downsampled data must provide similar buffering and padding +for odd-sized images. + + +*** Poor man's object-oriented programming *** + +It should be clear by now that we have a lot of quasi-independent processing +steps, many of which have several possible behaviors. To avoid cluttering the +code with lots of switch statements, we use a simple form of object-style +programming to separate out the different possibilities. + +For example, two different color quantization algorithms could be implemented +as two separate modules that present the same external interface; at runtime, +the calling code will access the proper module indirectly through an "object". + +We can get the limited features we need while staying within portable C. +The basic tool is a function pointer. An "object" is just a struct +containing one or more function pointer fields, each of which corresponds to +a method name in real object-oriented languages. During initialization we +fill in the function pointers with references to whichever module we have +determined we need to use in this run. Then invocation of the module is done +by indirecting through a function pointer; on most machines this is no more +expensive than a switch statement, which would be the only other way of +making the required run-time choice. The really significant benefit, of +course, is keeping the source code clean and well structured. + +We can also arrange to have private storage that varies between different +implementations of the same kind of object. We do this by making all the +module-specific object structs be separately allocated entities, which will +be accessed via pointers in the master compression or decompression struct. +The "public" fields or methods for a given kind of object are specified by +a commonly known struct. But a module's initialization code can allocate +a larger struct that contains the common struct as its first member, plus +additional private fields. With appropriate pointer casting, the module's +internal functions can access these private fields. (For a simple example, +see jdatadst.c, which implements the external interface specified by struct +jpeg_destination_mgr, but adds extra fields.) + +(Of course this would all be a lot easier if we were using C++, but we are +not yet prepared to assume that everyone has a C++ compiler.) + +An important benefit of this scheme is that it is easy to provide multiple +versions of any method, each tuned to a particular case. While a lot of +precalculation might be done to select an optimal implementation of a method, +the cost per invocation is constant. For example, the upsampling step might +have a "generic" method, plus one or more "hardwired" methods for the most +popular sampling factors; the hardwired methods would be faster because they'd +use straight-line code instead of for-loops. The cost to determine which +method to use is paid only once, at startup, and the selection criteria are +hidden from the callers of the method. + +This plan differs a little bit from usual object-oriented structures, in that +only one instance of each object class will exist during execution. The +reason for having the class structure is that on different runs we may create +different instances (choose to execute different modules). You can think of +the term "method" as denoting the common interface presented by a particular +set of interchangeable functions, and "object" as denoting a group of related +methods, or the total shared interface behavior of a group of modules. + + +*** Overall control structure *** + +We previously mentioned the need for overall control logic in the compression +and decompression libraries. In IJG implementations prior to v5, overall +control was mostly provided by "pipeline control" modules, which proved to be +large, unwieldy, and hard to understand. To improve the situation, the +control logic has been subdivided into multiple modules. The control modules +consist of: + +1. Master control for module selection and initialization. This has two +responsibilities: + + 1A. Startup initialization at the beginning of image processing. + The individual processing modules to be used in this run are selected + and given initialization calls. + + 1B. Per-pass control. This determines how many passes will be performed + and calls each active processing module to configure itself + appropriately at the beginning of each pass. End-of-pass processing, + where necessary, is also invoked from the master control module. + + Method selection is partially distributed, in that a particular processing + module may contain several possible implementations of a particular method, + which it will select among when given its initialization call. The master + control code need only be concerned with decisions that affect more than + one module. + +2. Data buffering control. A separate control module exists for each + inter-processing-step data buffer. This module is responsible for + invoking the processing steps that write or read that data buffer. + +Each buffer controller sees the world as follows: + +input data => processing step A => buffer => processing step B => output data + | | | + ------------------ controller ------------------ + +The controller knows the dataflow requirements of steps A and B: how much data +they want to accept in one chunk and how much they output in one chunk. Its +function is to manage its buffer and call A and B at the proper times. + +A data buffer control module may itself be viewed as a processing step by a +higher-level control module; thus the control modules form a binary tree with +elementary processing steps at the leaves of the tree. + +The control modules are objects. A considerable amount of flexibility can +be had by replacing implementations of a control module. For example: +* Merging of adjacent steps in the pipeline is done by replacing a control + module and its pair of processing-step modules with a single processing- + step module. (Hence the possible merges are determined by the tree of + control modules.) +* In some processing modes, a given interstep buffer need only be a "strip" + buffer large enough to accommodate the desired data chunk sizes. In other + modes, a full-image buffer is needed and several passes are required. + The control module determines which kind of buffer is used and manipulates + virtual array buffers as needed. One or both processing steps may be + unaware of the multi-pass behavior. + +In theory, we might be able to make all of the data buffer controllers +interchangeable and provide just one set of implementations for all. In +practice, each one contains considerable special-case processing for its +particular job. The buffer controller concept should be regarded as an +overall system structuring principle, not as a complete description of the +task performed by any one controller. + + +*** Codec object structure *** + +As noted above, this library supports both the lossy (DCT-based) and lossless +JPEG processes. Because these processes have little in common with one another +(and their implementations share very little code), we need to provide a way to +isloate the underlying JPEG process from the rest of the library. This is +accomplished by introducing an abstract "codec object" which acts a generic +interface to the JPEG (de)compressor proper. + +Using the power of the object-oriented scheme described above, we build the +lossy and lossless modules as two separate implementations of the codec object. +Switching between lossy and lossless processes then becomes as trivial as +assigning the appropriate method pointers during initialization of the library. + + +*** Compression object structure *** + +Here is a sketch of the logical structure of the JPEG compression library: + + |-- Colorspace conversion + |-- Preprocessing controller --| + | |-- Downsampling + | +Main controller --| + | /--> Lossy codec + | / + |-- Compression codec < *OR* + \ + \--> Lossless codec + + +where the lossy codec looks like: + + |-- Forward DCT, quantize +<-- Coefficient controller --| + |-- Entropy encoding + + +and the lossless codec looks like: + + |-- Point transformation + | +<-- Difference controller --|-- Prediction, differencing + | + |-- Lossless entropy encoding + + +This sketch also describes the flow of control (subroutine calls) during +typical image data processing. Each of the components shown in the diagram is +an "object" which may have several different implementations available. One +or more source code files contain the actual implementation(s) of each object. + +The objects shown above are: + +* Main controller: buffer controller for the subsampled-data buffer, which + holds the preprocessed input data. This controller invokes preprocessing to + fill the subsampled-data buffer, and JPEG compression to empty it. There is + usually no need for a full-image buffer here; a strip buffer is adequate. + +* Preprocessing controller: buffer controller for the downsampling input data + buffer, which lies between colorspace conversion and downsampling. Note + that a unified conversion/downsampling module would probably replace this + controller entirely. + +* Colorspace conversion: converts application image data into the desired + JPEG color space; also changes the data from pixel-interleaved layout to + separate component planes. Processes one pixel row at a time. + +* Downsampling: performs reduction of chroma components as required. + Optionally may perform pixel-level smoothing as well. Processes a "row + group" at a time, where a row group is defined as Vmax pixel rows of each + component before downsampling, and Vk sample rows afterwards (remember Vk + differs across components). Some downsampling or smoothing algorithms may + require context rows above and below the current row group; the + preprocessing controller is responsible for supplying these rows via proper + buffering. The downsampler is responsible for edge expansion at the right + edge (i.e., extending each sample row to a multiple of 8 samples); but the + preprocessing controller is responsible for vertical edge expansion (i.e., + duplicating the bottom sample row as needed to make a multiple of 8 rows). + +* Coefficient controller: buffer controller for the DCT-coefficient data. + This controller handles MCU assembly, including insertion of dummy DCT + blocks when needed at the right or bottom edge. When performing + Huffman-code optimization or emitting a multiscan JPEG file, this + controller is responsible for buffering the full image. The equivalent of + one fully interleaved MCU row of subsampled data is processed per call, + even when the JPEG file is noninterleaved. + +* Forward DCT and quantization: Perform DCT, quantize, and emit coefficients. + Works on one or more DCT blocks at a time. (Note: the coefficients are now + emitted in normal array order, which the entropy encoder is expected to + convert to zigzag order as necessary. Prior versions of the IJG code did + the conversion to zigzag order within the quantization step.) + +* Entropy encoding: Perform Huffman or arithmetic entropy coding and emit the + coded data to the data destination module. Works on one MCU per call. + For progressive JPEG, the same DCT blocks are fed to the entropy coder + during each pass, and the coder must emit the appropriate subset of + coefficients. + +* Difference controller: buffer controller for the spatial difference data. + When emitting a multiscan JPEG file, this controller is responsible for + buffering the full image. The equivalent of one fully interleaved MCU row + of subsampled data is processed per call, even when the JPEG file is + noninterleaved. + +* Point transformation: Scale the data down by the point transformation + parameter. + +* Prediction and differencing: Calculate the predictor and subtract it + from the input. Works on one scanline per call. The difference + controller supplies the prior scanline which is used for prediction. + +* Lossless entropy encoding: Perform Huffman or arithmetic entropy coding and + emit the coded data to the data destination module. This module handles MCU + assembly. Works on one MCU-row per call. + +In addition to the above objects, the compression library includes these +objects: + +* Master control: determines the number of passes required, controls overall + and per-pass initialization of the other modules. + +* Marker writing: generates JPEG markers (except for RSTn, which is emitted + by the entropy encoder when needed). + +* Data destination manager: writes the output JPEG datastream to its final + destination (e.g., a file). The destination manager supplied with the + library knows how to write to a stdio stream; for other behaviors, the + surrounding application may provide its own destination manager. + +* Memory manager: allocates and releases memory, controls virtual arrays + (with backing store management, where required). + +* Error handler: performs formatting and output of error and trace messages; + determines handling of nonfatal errors. The surrounding application may + override some or all of this object's methods to change error handling. + +* Progress monitor: supports output of "percent-done" progress reports. + This object represents an optional callback to the surrounding application: + if wanted, it must be supplied by the application. + +The error handler, destination manager, and progress monitor objects are +defined as separate objects in order to simplify application-specific +customization of the JPEG library. A surrounding application may override +individual methods or supply its own all-new implementation of one of these +objects. The object interfaces for these objects are therefore treated as +part of the application interface of the library, whereas the other objects +are internal to the library. + +The error handler and memory manager are shared by JPEG compression and +decompression; the progress monitor, if used, may be shared as well. + + +*** Decompression object structure *** + +Here is a sketch of the logical structure of the JPEG decompression library: + + /--> Lossy codec + / + |-- Decompression codec < *OR* + | \ + | \--> Lossless codec +Main controller --| + | + | |-- Upsampling + |-- Postprocessing controller --| |-- Colorspace conversion + |-- Color quantization + |-- Color precision reduction + + +where the lossy codec looks like: + + |-- Entropy decoding +<-- Coefficient controller --| + |-- Dequantize, Inverse DCT + + +and the lossless codec looks like: + + |-- Lossless entropy decoding + | +<-- Difference controller --|-- Prediction, undifferencing + | + |-- Point transformation, sample size scaling + + +As before, this diagram also represents typical control flow. The objects +shown are: + +* Main controller: buffer controller for the subsampled-data buffer, which + holds the output of JPEG decompression proper. This controller's primary + task is to feed the postprocessing procedure. Some upsampling algorithms + may require context rows above and below the current row group; when this + is true, the main controller is responsible for managing its buffer so as + to make context rows available. In the current design, the main buffer is + always a strip buffer; a full-image buffer is never required. + +* Coefficient controller: buffer controller for the DCT-coefficient data. + This controller handles MCU disassembly, including deletion of any dummy + DCT blocks at the right or bottom edge. When reading a multiscan JPEG + file, this controller is responsible for buffering the full image. + (Buffering DCT coefficients, rather than samples, is necessary to support + progressive JPEG.) The equivalent of one fully interleaved MCU row of + subsampled data is processed per call, even when the source JPEG file is + noninterleaved. + +* Entropy decoding: Read coded data from the data source module and perform + Huffman or arithmetic entropy decoding. Works on one MCU per call. + For progressive JPEG decoding, the coefficient controller supplies the prior + coefficients of each MCU (initially all zeroes), which the entropy decoder + modifies in each scan. + +* Dequantization and inverse DCT: like it says. Note that the coefficients + buffered by the coefficient controller have NOT been dequantized; we + merge dequantization and inverse DCT into a single step for speed reasons. + When scaled-down output is asked for, simplified DCT algorithms may be used + that emit only 1x1, 2x2, or 4x4 samples per DCT block, not the full 8x8. + Works on one DCT block at a time. + +* Difference controller: buffer controller for the spatial difference data. + When reading a multiscan JPEG file, this controller is responsible for + buffering the full image. The equivalent of one fully interleaved MCU row + is processed per call, even when the source JPEG file is noninterleaved. + +* Lossless entropy decoding: Read coded data from the data source module and + perform Huffman or arithmetic entropy decoding. Works on one MCU-row per + call. + +* Prediction and undifferencing: Calculate the predictor and add it to the + decoded difference. Works on one scanline per call. The difference + controller supplies the prior scanline which is used for prediction. + +* Point transform and sample size scaling: Scale the data up by the point + transformation parameter and scale it down to fit into the compiled-in + sample size. + +* Postprocessing controller: buffer controller for the color quantization + input buffer, when quantization is in use. (Without quantization, this + controller just calls the upsampler.) For two-pass quantization, this + controller is responsible for buffering the full-image data. + +* Upsampling: restores chroma components to full size. (May support more + general output rescaling, too. Note that if undersized DCT outputs have + been emitted by the DCT module, this module must adjust so that properly + sized outputs are created.) Works on one row group at a time. This module + also calls the color conversion module, so its top level is effectively a + buffer controller for the upsampling->color conversion buffer. However, in + all but the highest-quality operating modes, upsampling and color + conversion are likely to be merged into a single step. + +* Colorspace conversion: convert from JPEG color space to output color space, + and change data layout from separate component planes to pixel-interleaved. + Works on one pixel row at a time. + +* Color quantization: reduce the data to colormapped form, using either an + externally specified colormap or an internally generated one. This module + is not used for full-color output. Works on one pixel row at a time; may + require two passes to generate a color map. Note that the output will + always be a single component representing colormap indexes. In the current + design, the output values are JSAMPLEs, so an 8-bit compilation cannot + quantize to more than 256 colors. This is unlikely to be a problem in + practice. + +* Color reduction: this module handles color precision reduction, e.g., + generating 15-bit color (5 bits/primary) from JPEG's 24-bit output. + Not quite clear yet how this should be handled... should we merge it with + colorspace conversion??? + +Note that some high-speed operating modes might condense the entire +postprocessing sequence to a single module (upsample, color convert, and +quantize in one step). + +In addition to the above objects, the decompression library includes these +objects: + +* Master control: determines the number of passes required, controls overall + and per-pass initialization of the other modules. This is subdivided into + input and output control: jdinput.c controls only input-side processing, + while jdmaster.c handles overall initialization and output-side control. + +* Marker reading: decodes JPEG markers (except for RSTn). + +* Data source manager: supplies the input JPEG datastream. The source + manager supplied with the library knows how to read from a stdio stream; + for other behaviors, the surrounding application may provide its own source + manager. + +* Memory manager: same as for compression library. + +* Error handler: same as for compression library. + +* Progress monitor: same as for compression library. + +As with compression, the data source manager, error handler, and progress +monitor are candidates for replacement by a surrounding application. + + +*** Decompression input and output separation *** + +To support efficient incremental display of progressive JPEG files, the +decompressor is divided into two sections that can run independently: + +1. Data input includes marker parsing, entropy decoding, and input into the + coefficient controller's DCT coefficient buffer. Note that this + processing is relatively cheap and fast. + +2. Data output reads from the DCT coefficient buffer and performs the IDCT + and all postprocessing steps. + +For a progressive JPEG file, the data input processing is allowed to get +arbitrarily far ahead of the data output processing. (This occurs only +if the application calls jpeg_consume_input(); otherwise input and output +run in lockstep, since the input section is called only when the output +section needs more data.) In this way the application can avoid making +extra display passes when data is arriving faster than the display pass +can run. Furthermore, it is possible to abort an output pass without +losing anything, since the coefficient buffer is read-only as far as the +output section is concerned. See libjpeg.doc for more detail. + +A full-image coefficient array is only created if the JPEG file has multiple +scans (or if the application specifies buffered-image mode anyway). When +reading a single-scan file, the coefficient controller normally creates only +a one-MCU buffer, so input and output processing must run in lockstep in this +case. jpeg_consume_input() is effectively a no-op in this situation. + +The main impact of dividing the decompressor in this fashion is that we must +be very careful with shared variables in the cinfo data structure. Each +variable that can change during the course of decompression must be +classified as belonging to data input or data output, and each section must +look only at its own variables. For example, the data output section may not +depend on any of the variables that describe the current scan in the JPEG +file, because these may change as the data input section advances into a new +scan. + +The progress monitor is (somewhat arbitrarily) defined to treat input of the +file as one pass when buffered-image mode is not used, and to ignore data +input work completely when buffered-image mode is used. Note that the +library has no reliable way to predict the number of passes when dealing +with a progressive JPEG file, nor can it predict the number of output passes +in buffered-image mode. So the work estimate is inherently bogus anyway. + +No comparable division is currently made in the compression library, because +there isn't any real need for it. + + +*** Data formats *** + +Arrays of pixel sample values use the following data structure: + + typedef something JSAMPLE; a pixel component value, 0..MAXJSAMPLE + typedef JSAMPLE *JSAMPROW; ptr to a row of samples + typedef JSAMPROW *JSAMPARRAY; ptr to a list of rows + typedef JSAMPARRAY *JSAMPIMAGE; ptr to a list of color-component arrays + +The basic element type JSAMPLE will typically be one of unsigned char, +(signed) char, or short. Short will be used if samples wider than 8 bits are +to be supported (this is a compile-time option). Otherwise, unsigned char is +used if possible. If the compiler only supports signed chars, then it is +necessary to mask off the value when reading. Thus, all reads of JSAMPLE +values must be coded as "GETJSAMPLE(value)", where the macro will be defined +as "((value) & 0xFF)" on signed-char machines and "((int) (value))" elsewhere. + +With these conventions, JSAMPLE values can be assumed to be >= 0. This helps +simplify correct rounding during downsampling, etc. The JPEG standard's +specification that sample values run from -128..127 is accommodated by +subtracting 128 just as the sample value is copied into the source array for +the DCT step (this will be an array of signed ints). Similarly, during +decompression the output of the IDCT step will be immediately shifted back to +0..255. (NB: different values are required when 12-bit samples are in use. +The code is written in terms of MAXJSAMPLE and CENTERJSAMPLE, which will be +defined as 255 and 128 respectively in an 8-bit implementation, and as 4095 +and 2048 in a 12-bit implementation.) + +We use a pointer per row, rather than a two-dimensional JSAMPLE array. This +choice costs only a small amount of memory and has several benefits: +* Code using the data structure doesn't need to know the allocated width of + the rows. This simplifies edge expansion/compression, since we can work + in an array that's wider than the logical picture width. +* Indexing doesn't require multiplication; this is a performance win on many + machines. +* Arrays with more than 64K total elements can be supported even on machines + where malloc() cannot allocate chunks larger than 64K. +* The rows forming a component array may be allocated at different times + without extra copying. This trick allows some speedups in smoothing steps + that need access to the previous and next rows. + +Note that each color component is stored in a separate array; we don't use the +traditional layout in which the components of a pixel are stored together. +This simplifies coding of modules that work on each component independently, +because they don't need to know how many components there are. Furthermore, +we can read or write each component to a temporary file independently, which +is helpful when dealing with noninterleaved JPEG files. + +In general, a specific sample value is accessed by code such as + GETJSAMPLE(image[colorcomponent][row][col]) +where col is measured from the image left edge, but row is measured from the +first sample row currently in memory. Either of the first two indexings can +be precomputed by copying the relevant pointer. + + +Since most image-processing applications prefer to work on images in which +the components of a pixel are stored together, the data passed to or from the +surrounding application uses the traditional convention: a single pixel is +represented by N consecutive JSAMPLE values, and an image row is an array of +(# of color components)*(image width) JSAMPLEs. One or more rows of data can +be represented by a pointer of type JSAMPARRAY in this scheme. This scheme is +converted to component-wise storage inside the JPEG library. (Applications +that want to skip JPEG preprocessing or postprocessing will have to contend +with component-wise storage.) + + +Arrays of DCT-coefficient values use the following data structure: + + typedef short JCOEF; a 16-bit signed integer + typedef JCOEF JBLOCK[DCTSIZE2]; an 8x8 block of coefficients + typedef JBLOCK *JBLOCKROW; ptr to one horizontal row of 8x8 blocks + typedef JBLOCKROW *JBLOCKARRAY; ptr to a list of such rows + typedef JBLOCKARRAY *JBLOCKIMAGE; ptr to a list of color component arrays + +The underlying type is at least a 16-bit signed integer; while "short" is big +enough on all machines of interest, on some machines it is preferable to use +"int" for speed reasons, despite the storage cost. Coefficients are grouped +into 8x8 blocks (but we always use #defines DCTSIZE and DCTSIZE2 rather than +"8" and "64"). + +The contents of a coefficient block may be in either "natural" or zigzagged +order, and may be true values or divided by the quantization coefficients, +depending on where the block is in the processing pipeline. In the current +library, coefficient blocks are kept in natural order everywhere; the entropy +codecs zigzag or dezigzag the data as it is written or read. The blocks +contain quantized coefficients everywhere outside the DCT/IDCT subsystems. +(This latter decision may need to be revisited to support variable +quantization a la JPEG Part 3.) + +Notice that the allocation unit is now a row of 8x8 blocks, corresponding to +eight rows of samples. Otherwise the structure is much the same as for +samples, and for the same reasons. + +On machines where malloc() can't handle a request bigger than 64Kb, this data +structure limits us to rows of less than 512 JBLOCKs, or a picture width of +4000+ pixels. This seems an acceptable restriction. + + +On 80x86 machines, the bottom-level pointer types (JSAMPROW and JBLOCKROW) +must be declared as "far" pointers, but the upper levels can be "near" +(implying that the pointer lists are allocated in the DS segment). +We use a #define symbol FAR, which expands to the "far" keyword when +compiling on 80x86 machines and to nothing elsewhere. + + +*** Suspendable processing *** + +In some applications it is desirable to use the JPEG library as an +incremental, memory-to-memory filter. In this situation the data source or +destination may be a limited-size buffer, and we can't rely on being able to +empty or refill the buffer at arbitrary times. Instead the application would +like to have control return from the library at buffer overflow/underrun, and +then resume compression or decompression at a later time. + +This scenario is supported for simple cases. (For anything more complex, we +recommend that the application "bite the bullet" and develop real multitasking +capability.) The libjpeg.doc file goes into more detail about the usage and +limitations of this capability; here we address the implications for library +structure. + +The essence of the problem is that the entropy codec (coder or decoder) must +be prepared to stop at arbitrary times. In turn, the controllers that call +the entropy codec must be able to stop before having produced or consumed all +the data that they normally would handle in one call. That part is reasonably +straightforward: we make the controller call interfaces include "progress +counters" which indicate the number of data chunks successfully processed, and +we require callers to test the counter rather than just assume all of the data +was processed. + +Rather than trying to restart at an arbitrary point, the current Huffman +codecs are designed to restart at the beginning of the current MCU after a +suspension due to buffer overflow/underrun. At the start of each call, the +codec's internal state is loaded from permanent storage (in the JPEG object +structures) into local variables. On successful completion of the MCU, the +permanent state is updated. (This copying is not very expensive, and may even +lead to *improved* performance if the local variables can be registerized.) +If a suspension occurs, the codec simply returns without updating the state, +thus effectively reverting to the start of the MCU. Note that this implies +leaving some data unprocessed in the source/destination buffer (ie, the +compressed partial MCU). The data source/destination module interfaces are +specified so as to make this possible. This also implies that the data buffer +must be large enough to hold a worst-case compressed MCU; a couple thousand +bytes should be enough. + +In a successive-approximation AC refinement scan, the progressive Huffman +decoder has to be able to undo assignments of newly nonzero coefficients if it +suspends before the MCU is complete, since decoding requires distinguishing +previously-zero and previously-nonzero coefficients. This is a bit tedious +but probably won't have much effect on performance. Other variants of Huffman +decoding need not worry about this, since they will just store the same values +again if forced to repeat the MCU. + +This approach would probably not work for an arithmetic codec, since its +modifiable state is quite large and couldn't be copied cheaply. Instead it +would have to suspend and resume exactly at the point of the buffer end. + +The JPEG marker reader is designed to cope with suspension at an arbitrary +point. It does so by backing up to the start of the marker parameter segment, +so the data buffer must be big enough to hold the largest marker of interest. +Again, a couple KB should be adequate. (A special "skip" convention is used +to bypass COM and APPn markers, so these can be larger than the buffer size +without causing problems; otherwise a 64K buffer would be needed in the worst +case.) + +The JPEG marker writer currently does *not* cope with suspension. I feel that +this is not necessary; it is much easier simply to require the application to +ensure there is enough buffer space before starting. (An empty 2K buffer is +more than sufficient for the header markers; and ensuring there are a dozen or +two bytes available before calling jpeg_finish_compress() will suffice for the +trailer.) This would not work for writing multi-scan JPEG files, but +we simply do not intend to support that capability with suspension. + + +*** Memory manager services *** + +The JPEG library's memory manager controls allocation and deallocation of +memory, and it manages large "virtual" data arrays on machines where the +operating system does not provide virtual memory. Note that the same +memory manager serves both compression and decompression operations. + +In all cases, allocated objects are tied to a particular compression or +decompression master record, and they will be released when that master +record is destroyed. + +The memory manager does not provide explicit deallocation of objects. +Instead, objects are created in "pools" of free storage, and a whole pool +can be freed at once. This approach helps prevent storage-leak bugs, and +it speeds up operations whenever malloc/free are slow (as they often are). +The pools can be regarded as lifetime identifiers for objects. Two +pools/lifetimes are defined: + * JPOOL_PERMANENT lasts until master record is destroyed + * JPOOL_IMAGE lasts until done with image (JPEG datastream) +Permanent lifetime is used for parameters and tables that should be carried +across from one datastream to another; this includes all application-visible +parameters. Image lifetime is used for everything else. (A third lifetime, +JPOOL_PASS = one processing pass, was originally planned. However it was +dropped as not being worthwhile. The actual usage patterns are such that the +peak memory usage would be about the same anyway; and having per-pass storage +substantially complicates the virtual memory allocation rules --- see below.) + +The memory manager deals with three kinds of object: +1. "Small" objects. Typically these require no more than 10K-20K total. +2. "Large" objects. These may require tens to hundreds of K depending on + image size. Semantically they behave the same as small objects, but we + distinguish them for two reasons: + * On MS-DOS machines, large objects are referenced by FAR pointers, + small objects by NEAR pointers. + * Pool allocation heuristics may differ for large and small objects. + Note that individual "large" objects cannot exceed the size allowed by + type size_t, which may be 64K or less on some machines. +3. "Virtual" objects. These are large 2-D arrays of JSAMPLEs or JBLOCKs + (typically large enough for the entire image being processed). The + memory manager provides stripwise access to these arrays. On machines + without virtual memory, the rest of the array may be swapped out to a + temporary file. + +(Note: JSAMPARRAY and JBLOCKARRAY data structures are a combination of large +objects for the data proper and small objects for the row pointers. For +convenience and speed, the memory manager provides single routines to create +these structures. Similarly, virtual arrays include a small control block +and a JSAMPARRAY or JBLOCKARRAY working buffer, all created with one call.) + +In the present implementation, virtual arrays are only permitted to have image +lifespan. (Permanent lifespan would not be reasonable, and pass lifespan is +not very useful since a virtual array's raison d'etre is to store data for +multiple passes through the image.) We also expect that only "small" objects +will be given permanent lifespan, though this restriction is not required by +the memory manager. + +In a non-virtual-memory machine, some performance benefit can be gained by +making the in-memory buffers for virtual arrays be as large as possible. +(For small images, the buffers might fit entirely in memory, so blind +swapping would be very wasteful.) The memory manager will adjust the height +of the buffers to fit within a prespecified maximum memory usage. In order +to do this in a reasonably optimal fashion, the manager needs to allocate all +of the virtual arrays at once. Therefore, there isn't a one-step allocation +routine for virtual arrays; instead, there is a "request" routine that simply +allocates the control block, and a "realize" routine (called just once) that +determines space allocation and creates all of the actual buffers. The +realize routine must allow for space occupied by non-virtual large objects. +(We don't bother to factor in the space needed for small objects, on the +grounds that it isn't worth the trouble.) + +To support all this, we establish the following protocol for doing business +with the memory manager: + 1. Modules must request virtual arrays (which may have only image lifespan) + during the initial setup phase, i.e., in their jinit_xxx routines. + 2. All "large" objects (including JSAMPARRAYs and JBLOCKARRAYs) must also be + allocated during initial setup. + 3. realize_virt_arrays will be called at the completion of initial setup. + The above conventions ensure that sufficient information is available + for it to choose a good size for virtual array buffers. +Small objects of any lifespan may be allocated at any time. We expect that +the total space used for small objects will be small enough to be negligible +in the realize_virt_arrays computation. + +In a virtual-memory machine, we simply pretend that the available space is +infinite, thus causing realize_virt_arrays to decide that it can allocate all +the virtual arrays as full-size in-memory buffers. The overhead of the +virtual-array access protocol is very small when no swapping occurs. + +A virtual array can be specified to be "pre-zeroed"; when this flag is set, +never-yet-written sections of the array are set to zero before being made +available to the caller. If this flag is not set, never-written sections +of the array contain garbage. (This feature exists primarily because the +equivalent logic would otherwise be needed in jdcoefct.c for progressive +JPEG mode; we may as well make it available for possible other uses.) + +The first write pass on a virtual array is required to occur in top-to-bottom +order; read passes, as well as any write passes after the first one, may +access the array in any order. This restriction exists partly to simplify +the virtual array control logic, and partly because some file systems may not +support seeking beyond the current end-of-file in a temporary file. The main +implication of this restriction is that rearrangement of rows (such as +converting top-to-bottom data order to bottom-to-top) must be handled while +reading data out of the virtual array, not while putting it in. + + +*** Memory manager internal structure *** + +To isolate system dependencies as much as possible, we have broken the +memory manager into two parts. There is a reasonably system-independent +"front end" (jmemmgr.c) and a "back end" that contains only the code +likely to change across systems. All of the memory management methods +outlined above are implemented by the front end. The back end provides +the following routines for use by the front end (none of these routines +are known to the rest of the JPEG code): + +jpeg_mem_init, jpeg_mem_term system-dependent initialization/shutdown + +jpeg_get_small, jpeg_free_small interface to malloc and free library routines + (or their equivalents) + +jpeg_get_large, jpeg_free_large interface to FAR malloc/free in MSDOS machines; + else usually the same as + jpeg_get_small/jpeg_free_small + +jpeg_mem_available estimate available memory + +jpeg_open_backing_store create a backing-store object + +read_backing_store, manipulate a backing-store object +write_backing_store, +close_backing_store + +On some systems there will be more than one type of backing-store object +(specifically, in MS-DOS a backing store file might be an area of extended +memory as well as a disk file). jpeg_open_backing_store is responsible for +choosing how to implement a given object. The read/write/close routines +are method pointers in the structure that describes a given object; this +lets them be different for different object types. + +It may be necessary to ensure that backing store objects are explicitly +released upon abnormal program termination. For example, MS-DOS won't free +extended memory by itself. To support this, we will expect the main program +or surrounding application to arrange to call self_destruct (typically via +jpeg_destroy) upon abnormal termination. This may require a SIGINT signal +handler or equivalent. We don't want to have the back end module install its +own signal handler, because that would pre-empt the surrounding application's +ability to control signal handling. + +The IJG distribution includes several memory manager back end implementations. +Usually the same back end should be suitable for all applications on a given +system, but it is possible for an application to supply its own back end at +need. + + +*** Implications of DNL marker *** + +Some JPEG files may use a DNL marker to postpone definition of the image +height (this would be useful for a fax-like scanner's output, for instance). +In these files the SOF marker claims the image height is 0, and you only +find out the true image height at the end of the first scan. + +We could read these files as follows: +1. Upon seeing zero image height, replace it by 65535 (the maximum allowed). +2. When the DNL is found, update the image height in the global image + descriptor. +This implies that control modules must avoid making copies of the image +height, and must re-test for termination after each MCU row. This would +be easy enough to do. + +In cases where image-size data structures are allocated, this approach will +result in very inefficient use of virtual memory or much-larger-than-necessary +temporary files. This seems acceptable for something that probably won't be a +mainstream usage. People might have to forgo use of memory-hogging options +(such as two-pass color quantization or noninterleaved JPEG files) if they +want efficient conversion of such files. (One could improve efficiency by +demanding a user-supplied upper bound for the height, less than 65536; in most +cases it could be much less.) + +The standard also permits the SOF marker to overestimate the image height, +with a DNL to give the true, smaller height at the end of the first scan. +This would solve the space problems if the overestimate wasn't too great. +However, it implies that you don't even know whether DNL will be used. + +This leads to a couple of very serious objections: +1. Testing for a DNL marker must occur in the inner loop of the decompressor's + Huffman decoder; this implies a speed penalty whether the feature is used + or not. +2. There is no way to hide the last-minute change in image height from an + application using the decoder. Thus *every* application using the IJG + library would suffer a complexity penalty whether it cared about DNL or + not. +We currently do not support DNL because of these problems. + +A different approach is to insist that DNL-using files be preprocessed by a +separate program that reads ahead to the DNL, then goes back and fixes the SOF +marker. This is a much simpler solution and is probably far more efficient. +Even if one wants piped input, buffering the first scan of the JPEG file needs +a lot smaller temp file than is implied by the maximum-height method. For +this approach we'd simply treat DNL as a no-op in the decompressor (at most, +check that it matches the SOF image height). + +We will not worry about making the compressor capable of outputting DNL. +Something similar to the first scheme above could be applied if anyone ever +wants to make that work. diff --git a/dcmjpeg/etc/Makefile.in b/dcmjpeg/etc/Makefile.in new file mode 100644 index 00000000..0a04313b --- /dev/null +++ b/dcmjpeg/etc/Makefile.in @@ -0,0 +1,23 @@ +# +# Makefile for dcmjpeg/etc +# + +@SET_MAKE@ + +SHELL = /bin/sh +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +configdir = @top_srcdir@/@configdir@ + +include $(configdir)/@common_makefile@ + + +all: + +install: + +clean: + rm -f $(TRASH) + +distclean: + rm -f $(DISTTRASH) diff --git a/dcmjpeg/include/CMakeLists.txt b/dcmjpeg/include/CMakeLists.txt new file mode 100644 index 00000000..e1c6aa4d --- /dev/null +++ b/dcmjpeg/include/CMakeLists.txt @@ -0,0 +1,2 @@ +# declare installation files +INSTALL(DIRECTORY dcmtk/dcmjpeg DESTINATION ${DCMTK_INSTALL_INCDIR}/dcmtk COMPONENT include FILES_MATCHING PATTERN "*.h") diff --git a/dcmjpeg/include/Makefile.in b/dcmjpeg/include/Makefile.in new file mode 100644 index 00000000..bf855808 --- /dev/null +++ b/dcmjpeg/include/Makefile.in @@ -0,0 +1,27 @@ +# +# Makefile for dcmjpeg/include +# + +@SET_MAKE@ + +SHELL = /bin/sh +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +configdir = @top_srcdir@/@configdir@ + +include $(configdir)/@common_makefile@ + + +all: + +install: + $(configdir)/mkinstalldirs $(DESTDIR)$(includedir)/dcmtk/dcmjpeg + for file in dcmtk/dcmjpeg/*.h ; do \ + $(INSTALL_DATA) $$file $(DESTDIR)$(includedir)/dcmtk/dcmjpeg ;\ + done + +clean: + rm -f $(TRASH) + +distclean: + rm -f $(DISTTRASH) diff --git a/dcmjpeg/include/dcmtk/dcmjpeg/ddpiimpl.h b/dcmjpeg/include/dcmtk/dcmjpeg/ddpiimpl.h new file mode 100644 index 00000000..0fa877d0 --- /dev/null +++ b/dcmjpeg/include/dcmtk/dcmjpeg/ddpiimpl.h @@ -0,0 +1,91 @@ +/* + * + * Copyright (C) 2003-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Joerg Riesmeier + * + * Purpose: Implementation of DICOMDIR image support (plugin) + * + */ + + +#ifndef DDPIIMPL_H +#define DDPIIMPL_H + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/dcmdata/dcddirif.h" + +#include "dcmtk/dcmjpeg/djdefine.h" + + +/*---------------------* + * class declaration * + *---------------------*/ + +/** Implementation of the plugable image support for the DICOMDIR class + */ +class DCMTK_DCMJPEG_EXPORT DicomDirImageImplementation + : public DicomDirImagePlugin +{ + public: + + /** constructor + */ + DicomDirImageImplementation(); + + /** destructor + */ + virtual ~DicomDirImageImplementation(); + + /** scale given pixel data (monochrome only). + * The destination pixel data array needs to be allocated by the caller. + * @param srcData source pixel data (byte array) + * @param srcWidth width of the source pixel data (in pixels) + * @param srcHeight height of the source pixel data (in pixels) + * @param dstData destination pixel data (resulting byte array, not NULL) + * @param dstWidth width of the scaled pixel data (in pixels) + * @param dstHeight height of the scaled pixel data (in pixels) + * @return OFTrue if successful, OFFalse otherwise + */ + virtual OFBool scaleData(const Uint8 *srcData, + const unsigned int srcWidth, + const unsigned int srcHeight, + Uint8 *dstData, + const unsigned int dstWidth, + const unsigned int dstHeight) const; + + /** get scaled pixel data from DICOM image. + * The resulting scaled image (pixel array) is always monochrome. + * The resulting pixel data array needs to be allocated by the caller. + * @param dataset DICOM dataset in which the DICOM image is stored + * @param pixel resulting pixel data array (not NULL) + * @param count number of pixels allocated for the resulting array + * @param frame index of the frame to be scaled (1..n) + * @param width width of the scaled image (in pixels) + * @param height height of the scaled image (in pixels) + * @param decompressAll always decompress complete pixel data if true + * @return OFTrue if successful, OFFalse otherwise + */ + virtual OFBool scaleImage(DcmItem *dataset, + Uint8 *pixel, + const unsigned long count, + const unsigned long frame, + const unsigned int width, + const unsigned int height, + const OFBool decompressAll = OFFalse) const; +}; + + +#endif diff --git a/dcmjpeg/include/dcmtk/dcmjpeg/dipijpeg.h b/dcmjpeg/include/dcmtk/dcmjpeg/dipijpeg.h new file mode 100644 index 00000000..1e624dcc --- /dev/null +++ b/dcmjpeg/include/dcmtk/dcmjpeg/dipijpeg.h @@ -0,0 +1,104 @@ +/* + * + * Copyright (C) 2001-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmjpeg + * + * Author: Joerg Riesmeier + * + * Purpose: Implements JPEG interface for plugable image formats + * + */ + + +#ifndef DIPIJPEG_H +#define DIPIJPEG_H + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/dcmimgle/diplugin.h" +#include "dcmtk/dcmjpeg/djutils.h" + + +/*------------------------* + * forward declarations * + *------------------------*/ + +class DiImage; + + +/*---------------------* + * class declaration * + *---------------------*/ + +/** Implementation of a JPEG plugin for the dcmimgle/dcmimage library + */ +class DCMTK_DCMJPEG_EXPORT DiJPEGPlugin + : public DiPluginFormat +{ + + public: + + /** constructor + */ + DiJPEGPlugin(); + + /** destructor + */ + virtual ~DiJPEGPlugin(); + + /** write given image to a file stream (JPEG format) + * @param image pointer to DICOM image object to be written + * @param stream stream to which the image is written (open in binary mode!) + * @param frame index of frame used for output (default: first frame = 0) + * @return true if successful, false otherwise + */ + virtual int write(DiImage *image, + FILE *stream, + const unsigned long frame = 0) const; + + /** set quality value for JPEG compression + * @param quality quality value (0..100, in percent) + */ + void setQuality(const unsigned int quality); + + /** set (sub) sampling for JPEG compression. + * Only used for color images. ESS_444 means no sub-sampling, ESS_422 horizontal + * subsampling of chroma components and ESS_422 horizontal and vertical subsampling + * of chroma components. + * @param sampling sampling (valid values: ESS_444, ESS_422 or ESS_411) + */ + void setSampling(const E_SubSampling sampling); + + /** callback function used to report IJG warning messages and the like. + * Should not be called by user code directly. + * @param arg opaque pointer to JPEG compress structure + */ + void outputMessage(void *arg) const; + + /** get version information of the TIFF library. + * Typical output format: "IJG, Version 6b 27-Mar-1998 (modified)" + * @return name and version number of the TIFF library + */ + static OFString getLibraryVersionString(); + + + private: + + /// quality value (0..100, in percent), default: 75 + unsigned int Quality; + /// (sub) sampling: ESS_444, ESS_422 (default), ESS_411 + E_SubSampling Sampling; +}; + + +#endif diff --git a/dcmjpeg/include/dcmtk/dcmjpeg/djcodecd.h b/dcmjpeg/include/dcmtk/dcmjpeg/djcodecd.h new file mode 100644 index 00000000..99b6e481 --- /dev/null +++ b/dcmjpeg/include/dcmtk/dcmjpeg/djcodecd.h @@ -0,0 +1,266 @@ +/* + * + * Copyright (C) 2001-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmjpeg + * + * Author: Marco Eichelberg, Norbert Olges + * + * Purpose: abstract codec class for JPEG decoders. + * + */ + +#ifndef DJCODECD_H +#define DJCODECD_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/ofstd/oftypes.h" +#include "dcmtk/dcmdata/dccodec.h" /* for class DcmCodec */ +#include "dcmtk/dcmjpeg/djutils.h" /* for enums */ +#include "dcmtk/ofstd/ofstring.h" /* for class OFString */ + + +class DataInterface; +class DJEncoder; +class DcmDataset; +class DcmItem; +class DJCodecParameter; +class DJDecoder; + +/** abstract codec class for JPEG decoders. + * This abstract class contains most of the application logic + * needed for a dcmdata codec object that implements a JPEG decoder + * using the DJDecoder interface to the underlying JPEG implementation. + * This class only supports decompression, it neither implements + * encoding nor transcoding. + */ +class DCMTK_DCMJPEG_EXPORT DJCodecDecoder : public DcmCodec +{ +public: + + /// default constructor + DJCodecDecoder(); + + /// destructor + virtual ~DJCodecDecoder(); + + /** decompresses the given pixel sequence and + * stores the result in the given uncompressedPixelData element. + * @param fromRepParam current representation parameter of compressed data, may be NULL + * @param pixSeq compressed pixel sequence + * @param uncompressedPixelData uncompressed pixel data stored in this element + * @param cp codec parameters for this codec + * @param objStack stack pointing to the location of the pixel data + * element in the current dataset. + * @return EC_Normal if successful, an error code otherwise. + */ + virtual OFCondition decode( + const DcmRepresentationParameter * fromRepParam, + DcmPixelSequence * pixSeq, + DcmPolymorphOBOW& uncompressedPixelData, + const DcmCodecParameter * cp, + const DcmStack& objStack) const; + + /** decompresses a single frame from the given pixel sequence and + * stores the result in the given buffer. + * @param fromParam representation parameter of current compressed + * representation, may be NULL. + * @param fromPixSeq compressed pixel sequence + * @param cp codec parameters for this codec + * @param dataset pointer to dataset in which pixel data element is contained + * @param frameNo number of frame, starting with 0 for the first frame + * @param startFragment index of the compressed fragment that contains + * all or the first part of the compressed bitstream for the given frameNo. + * Upon successful return this parameter is updated to contain the index + * of the first compressed fragment of the next frame. + * When unknown, zero should be passed. In this case the decompression + * algorithm will try to determine the index by itself, which will always + * work if frames are decompressed in increasing order from first to last, + * but may fail if frames are decompressed in random order, multiple fragments + * per frame and multiple frames are present in the dataset, and the offset + * table is empty. + * @param buffer pointer to buffer where frame is to be stored + * @param bufSize size of buffer in bytes + * @param decompressedColorModel upon successful return, the color model + * of the decompressed image (which may be different from the one used + * in the compressed images) is returned in this parameter. + * @return EC_Normal if successful, an error code otherwise. + */ + virtual OFCondition decodeFrame( + const DcmRepresentationParameter * fromParam, + DcmPixelSequence * fromPixSeq, + const DcmCodecParameter * cp, + DcmItem *dataset, + Uint32 frameNo, + Uint32& startFragment, + void *buffer, + Uint32 bufSize, + OFString& decompressedColorModel) const; + + /** compresses the given uncompressed DICOM image and stores + * the result in the given pixSeq element. + * @param pixelData pointer to the uncompressed image data in OW format + * and local byte order + * @param length of the pixel data field in bytes + * @param toRepParam representation parameter describing the desired + * compressed representation (e.g. JPEG quality) + * @param pixSeq compressed pixel sequence (pointer to new DcmPixelSequence object + * allocated on heap) returned in this parameter upon success. + * @param cp codec parameters for this codec + * @param objStack stack pointing to the location of the pixel data + * element in the current dataset. + * @return EC_Normal if successful, an error code otherwise. + */ + virtual OFCondition encode( + const Uint16 * pixelData, + const Uint32 length, + const DcmRepresentationParameter * toRepParam, + DcmPixelSequence * & pixSeq, + const DcmCodecParameter *cp, + DcmStack & objStack) const; + + /** transcodes (re-compresses) the given compressed DICOM image and stores + * the result in the given toPixSeq element. + * @param fromRepType current transfer syntax of the compressed image + * @param fromRepParam current representation parameter of compressed data, may be NULL + * @param fromPixSeq compressed pixel sequence + * @param toRepParam representation parameter describing the desired + * new compressed representation (e.g. JPEG quality) + * @param toPixSeq compressed pixel sequence (pointer to new DcmPixelSequence object + * allocated on heap) returned in this parameter upon success. + * @param cp codec parameters for this codec + * @param objStack stack pointing to the location of the pixel data + * element in the current dataset. + * @return EC_Normal if successful, an error code otherwise. + */ + virtual OFCondition encode( + const E_TransferSyntax fromRepType, + const DcmRepresentationParameter * fromRepParam, + DcmPixelSequence * fromPixSeq, + const DcmRepresentationParameter * toRepParam, + DcmPixelSequence * & toPixSeq, + const DcmCodecParameter * cp, + DcmStack & objStack) const; + + /** checks if this codec is able to convert from the + * given current transfer syntax to the given new + * transfer syntax + * @param oldRepType current transfer syntax + * @param newRepType desired new transfer syntax + * @return true if transformation is supported by this codec, false otherwise. + */ + virtual OFBool canChangeCoding( + const E_TransferSyntax oldRepType, + const E_TransferSyntax newRepType) const; + + /** determine color model of the decompressed image + * @param fromParam representation parameter of current compressed + * representation, may be NULL + * @param fromPixSeq compressed pixel sequence + * @param cp codec parameters for this codec + * @param dataset pointer to dataset in which pixel data element is contained + * @param dataset pointer to DICOM dataset in which this pixel data object + * is located. Used to access photometric interpretation. + * @param decompressedColorModel upon successful return, the color model + * of the decompressed image (which may be different from the one used + * in the compressed images) is returned in this parameter + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition determineDecompressedColorModel( + const DcmRepresentationParameter *fromParam, + DcmPixelSequence *fromPixSeq, + const DcmCodecParameter *cp, + DcmItem *dataset, + OFString &decompressedColorModel) const; + + /** returns the transfer syntax that this particular codec + * is able to decode. + * @return supported transfer syntax + */ + virtual E_TransferSyntax supportedTransferSyntax() const = 0; + +private: + + /** creates an instance of the compression library to be used for decoding. + * @param toRepParam representation parameter passed to decode() + * @param cp codec parameter passed to decode() + * @param bitsPerSample bits per sample for the image data + * @param isYBR flag indicating whether DICOM photometric interpretation is YCbCr + * @return pointer to newly allocated decoder object + */ + virtual DJDecoder *createDecoderInstance( + const DcmRepresentationParameter * toRepParam, + const DJCodecParameter *cp, + Uint8 bitsPerSample, + OFBool isYBR) const = 0; + + // static private helper methods + + /** scans the given block of JPEG data for a Start of Frame marker + * and returns the number of bits per pixel stored in the + * Start of Frame block. + * @param data pointer to array, must not be NULL + * @param fragmentLength size of array + * @return bit depth of JPEG data, 0 if no SOF marker found or parse error + */ + static Uint8 scanJpegDataForBitDepth( + const Uint8 *data, + const Uint32 fragmentLength); + + /** reads two bytes from the given array + * of little endian 16-bit values and returns + * the value as Uint16 in local byte order. + * @param data pointer to array, must not be NULL, must at least 2 bytes large + * @return Uint16 read from array + */ + static Uint16 readUint16(const Uint8 *data); + + /** converts an RGB or YBR frame with 8 bits/sample from + * color-by-pixel to color-by-plane planar configuration. + * @param imageFrame pointer to image frame, must contain + * at least 3*columns*rows bytes of pixel data. + * @param columns columns + * @param rows rows + * @return EC_Normal if successful, an error code otherwise + */ + static OFCondition createPlanarConfigurationByte( + Uint8 *imageFrame, + Uint16 columns, + Uint16 rows); + + /** converts an RGB or YBR frame with 16 bits/sample from + * color-by-pixel to color-by-plane planar configuration. + * @param imageFrame pointer to image frame, must contain + * at least 3*columns*rows words of pixel data. + * @param columns columns + * @param rows rows + * @return EC_Normal if successful, an error code otherwise + */ + static OFCondition createPlanarConfigurationWord( + Uint16 *imageFrame, + Uint16 columns, + Uint16 rows); + + /** examines if a given image requires color-by-plane planar configuration + * depending on SOP Class UID (DICOM IOD) and photometric interpretation. + * All SOP classes defined in the 2003 edition of the DICOM standard or earlier + * are handled correctly. + * @param sopClassUID SOP Class UID + * @param photometricInterpretation decompressed photometric interpretation + * @return true if color-by-plane is required, false otherwise. + */ + static OFBool requiresPlanarConfiguration( + const char *sopClassUID, + EP_Interpretation photometricInterpretation); +}; + +#endif diff --git a/dcmjpeg/include/dcmtk/dcmjpeg/djcodece.h b/dcmjpeg/include/dcmtk/dcmjpeg/djcodece.h new file mode 100644 index 00000000..9fda0226 --- /dev/null +++ b/dcmjpeg/include/dcmtk/dcmjpeg/djcodece.h @@ -0,0 +1,384 @@ +/* + * + * Copyright (C) 2001-2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmjpeg + * + * Author: Marco Eichelberg, Norbert Olges + * + * Purpose: abstract codec class for JPEG encoders. + * + */ + +#ifndef DJCODEC_H +#define DJCODEC_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/ofstd/oftypes.h" +#include "dcmtk/dcmdata/dccodec.h" /* for class DcmCodec */ +#include "dcmtk/dcmjpeg/djutils.h" /* for enums */ +#include "dcmtk/ofstd/oflist.h" +#include "dcmtk/ofstd/ofstring.h" /* for class OFString */ + +class DataInterface; +class DJEncoder; +class DcmDataset; +class DJCodecParameter; +class DJDecoder; +class DcmItem; +class DcmPixelItem; +class DicomImage; +class DcmTagKey; + + +/** abstract codec class for JPEG encoders. + * This abstract class contains most of the application logic + * needed for a dcmdata codec object that implements a JPEG encoder + * using the DJEncoder interface to the underlying JPEG implementation. + * This class only supports compression, it neither implements + * decoding nor transcoding. + */ +class DCMTK_DCMJPEG_EXPORT DJCodecEncoder : public DcmCodec +{ +public: + + /// default constructor + DJCodecEncoder(); + + /// destructor + virtual ~DJCodecEncoder(); + + /** decompresses the given pixel sequence and + * stores the result in the given uncompressedPixelData element. + * @param fromRepParam current representation parameter of compressed data, may be NULL + * @param pixSeq compressed pixel sequence + * @param uncompressedPixelData uncompressed pixel data stored in this element + * @param cp codec parameters for this codec + * @param objStack stack pointing to the location of the pixel data + * element in the current dataset. + * @return EC_Normal if successful, an error code otherwise. + */ + virtual OFCondition decode( + const DcmRepresentationParameter * fromRepParam, + DcmPixelSequence * pixSeq, + DcmPolymorphOBOW& uncompressedPixelData, + const DcmCodecParameter * cp, + const DcmStack& objStack) const; + + /** decompresses a single frame from the given pixel sequence and + * stores the result in the given buffer. + * @param fromParam representation parameter of current compressed + * representation, may be NULL. + * @param fromPixSeq compressed pixel sequence + * @param cp codec parameters for this codec + * @param dataset pointer to dataset in which pixel data element is contained + * @param frameNo number of frame, starting with 0 for the first frame + * @param startFragment index of the compressed fragment that contains + * all or the first part of the compressed bitstream for the given frameNo. + * Upon successful return this parameter is updated to contain the index + * of the first compressed fragment of the next frame. + * When unknown, zero should be passed. In this case the decompression + * algorithm will try to determine the index by itself, which will always + * work if frames are decompressed in increasing order from first to last, + * but may fail if frames are decompressed in random order, multiple fragments + * per frame and multiple frames are present in the dataset, and the offset + * table is empty. + * @param buffer pointer to buffer where frame is to be stored + * @param bufSize size of buffer in bytes + * @param decompressedColorModel upon successful return, the color model + * of the decompressed image (which may be different from the one used + * in the compressed images) is returned in this parameter. + * @return EC_Normal if successful, an error code otherwise. + */ + virtual OFCondition decodeFrame( + const DcmRepresentationParameter * fromParam, + DcmPixelSequence * fromPixSeq, + const DcmCodecParameter * cp, + DcmItem *dataset, + Uint32 frameNo, + Uint32& startFragment, + void *buffer, + Uint32 bufSize, + OFString& decompressedColorModel) const; + + /** compresses the given uncompressed DICOM image and stores + * the result in the given pixSeq element. + * @param pixelData pointer to the uncompressed image data in OW format + * and local byte order + * @param length of the pixel data field in bytes + * @param toRepParam representation parameter describing the desired + * compressed representation (e.g. JPEG quality) + * @param pixSeq compressed pixel sequence (pointer to new DcmPixelSequence object + * allocated on heap) returned in this parameter upon success. + * @param cp codec parameters for this codec + * @param objStack stack pointing to the location of the pixel data + * element in the current dataset. + * @return EC_Normal if successful, an error code otherwise. + */ + virtual OFCondition encode( + const Uint16 * pixelData, + const Uint32 length, + const DcmRepresentationParameter * toRepParam, + DcmPixelSequence * & pixSeq, + const DcmCodecParameter *cp, + DcmStack & objStack) const; + + /** transcodes (re-compresses) the given compressed DICOM image and stores + * the result in the given toPixSeq element. + * @param fromRepType current transfer syntax of the compressed image + * @param fromRepParam current representation parameter of compressed data, may be NULL + * @param fromPixSeq compressed pixel sequence + * @param toRepParam representation parameter describing the desired + * new compressed representation (e.g. JPEG quality) + * @param toPixSeq compressed pixel sequence (pointer to new DcmPixelSequence object + * allocated on heap) returned in this parameter upon success. + * @param cp codec parameters for this codec + * @param objStack stack pointing to the location of the pixel data + * element in the current dataset. + * @return EC_Normal if successful, an error code otherwise. + */ + virtual OFCondition encode( + const E_TransferSyntax fromRepType, + const DcmRepresentationParameter * fromRepParam, + DcmPixelSequence * fromPixSeq, + const DcmRepresentationParameter * toRepParam, + DcmPixelSequence * & toPixSeq, + const DcmCodecParameter * cp, + DcmStack & objStack) const; + + /** checks if this codec is able to convert from the + * given current transfer syntax to the given new + * transfer syntax + * @param oldRepType current transfer syntax + * @param newRepType desired new transfer syntax + * @return true if transformation is supported by this codec, false otherwise. + */ + virtual OFBool canChangeCoding( + const E_TransferSyntax oldRepType, + const E_TransferSyntax newRepType) const; + + /** determine color model of the decompressed image + * @param fromParam representation parameter of current compressed + * representation, may be NULL + * @param fromPixSeq compressed pixel sequence + * @param cp codec parameters for this codec + * @param dataset pointer to dataset in which pixel data element is contained + * @param dataset pointer to DICOM dataset in which this pixel data object + * is located. Used to access photometric interpretation. + * @param decompressedColorModel upon successful return, the color model + * of the decompressed image (which may be different from the one used + * in the compressed images) is returned in this parameter + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition determineDecompressedColorModel( + const DcmRepresentationParameter *fromParam, + DcmPixelSequence *fromPixSeq, + const DcmCodecParameter *cp, + DcmItem *dataset, + OFString &decompressedColorModel) const; + + /** returns the transfer syntax that this particular codec + * is able to encode and decode. + * @return supported transfer syntax + */ + virtual E_TransferSyntax supportedTransferSyntax() const = 0; + +protected: + + /** format compression ratio as string and append to given string object. + * @param arg string to append to + * @param ratio compression ratio + */ + static void appendCompressionRatio(OFString& arg, double ratio); + + /** toggles Planar Configuration of 8-bit pixel data from "by pixel" to + * "by plane" and vice versa. + * @param pixelData - [in/out] Original pixel data (input), contains + * pixel data with toggled Planar configuration after + * returning (output). + * @param numValues - [in] The number of 8 bit values in pixelData + * @param samplesPerPixel - [in] Number of components for one pixel + * @param oldPlanarConfig - [in] The old Planar Configuration, that should + * be toggled. 0 means "by pixel", 1 "by color" + * @return EC_Normal, if conversion was successful; error else + */ + static OFCondition togglePlanarConfiguration8( + Uint8 *pixelData, + const size_t numValues, + const Uint16 samplesPerPixel, + const Uint16 oldPlanarConfig); + + /** toggles Planar Configuration of 16-bit pixel data from "by pixel" to + * "by plane" and vice versa. + * @param pixelData - [in/out] Original pixel data (input), contains + * pixel data with toggled Planar configuration after + * returning (output). + * @param numValues - [in] The number of 16 bit values in pixelData + * @param samplesPerPixel - [in] Number of components for one pixel + * @param oldPlanarConfig - [in] The old Planar Configuration, that should + * be toggled. 0 means "by pixel", 1 "by color" + * @return EC_Normal, if conversion was successful; error else + */ + static OFCondition togglePlanarConfiguration16( + Uint16 *pixelData, + const size_t numValues, + const Uint16 samplesPerPixel, + const Uint16 oldPlanarConfig); + +private: + + /** compresses the given uncompressed DICOM color image and stores + * the result in the given pixSeq element. + * @param YBRmode true if the source image has YBR_FULL or YBR_FULL_422 + * photometric interpretation and can thus be compressed without color + * space conversion. + * @param dataset DICOM dataset containing the pixel data as well as + * descriptive attributes + * @param toRepParam representation parameter describing the desired + * compressed representation (e.g. JPEG quality) + * @param pixSeq compressed pixel sequence (pointer to new DcmPixelSequence object + * allocated on heap) returned in this parameter upon success. + * @param cp codec parameters for this codec + * @param compressionRatio compression ratio returned in this parameter + * if successful. + * @return EC_Normal if successful, an error code otherwise. + */ + virtual OFCondition encodeColorImage( + OFBool YBRmode, + DcmItem *dataset, + const DcmRepresentationParameter * toRepParam, + DcmPixelSequence * & pixSeq, + const DJCodecParameter *cp, + double& compressionRatio) const; + + /** compresses the given uncompressed monochrome DICOM image and stores + * the result in the given pixSeq element. + * @param dataset DICOM dataset containing the pixel data as well as + * descriptive attributes + * @param toRepParam representation parameter describing the desired + * compressed representation (e.g. JPEG quality) + * @param pixSeq compressed pixel sequence (pointer to new DcmPixelSequence object + * allocated on heap) returned in this parameter upon success. + * @param cp codec parameters for this codec + * @param compressionRatio compression ratio returned in this parameter + * if successful. + * @return EC_Normal if successful, an error code otherwise. + */ + virtual OFCondition encodeMonochromeImage( + DcmItem *dataset, + const DcmRepresentationParameter * toRepParam, + DcmPixelSequence * & pixSeq, + const DJCodecParameter *cp, + double& compressionRatio) const; + + /** compresses the given uncompressed DICOM image and stores + * the result in the given pixSeq element. No colorspace + * conversions, modality or windowing transformations are applied + * to guarantee, that the quality of the source image is fully preserved. + * @param toRepParam - [in] representation parameter describing the desired + * @param pixSeq - [out] compressed pixel sequence (pointer to new DcmPixelSequence + * object allocated on heap) returned in this parameter upon success + * @param cp - [in] codec parameters for this codec + * @param objStack - [in/out] stack pointing to the location of the pixel data + * element in the current dataset. + * @return EC_Normal if successful, an error code otherwise. + */ + virtual OFCondition encodeTrueLossless( + const DcmRepresentationParameter * toRepParam, + DcmPixelSequence * & pixSeq, + const DcmCodecParameter *cp, + DcmStack & objStack) const; + + /** create Lossy Image Compression and Lossy Image Compression Ratio. + * @param dataset dataset to be modified + * @param ratio image compression ratio > 1. This is not the "quality factor" + * but the real effective ratio between compressed and uncompressed image, + * i. e. 30 means a 30:1 lossy compression. + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition updateLossyCompressionRatio(DcmItem *dataset, double ratio) const; + + /** create Derivation Description. + * @param dataset dataset to be modified + * @param toRepParam representation parameter passed to encode() + * @param cp codec parameter passed to encode() + * @param bitsPerSample bits per sample of the original image data prior to compression + * @param ratio image compression ratio. This is not the "quality factor" + * but the real effective ratio between compressed and uncompressed image, + * i. e. 30 means a 30:1 lossy compression. + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition updateDerivationDescription( + DcmItem *dataset, + const DcmRepresentationParameter * toRepParam, + const DJCodecParameter *cp, + Uint8 bitsPerSample, + double ratio) const; + + /** for all overlay groups create (60xx,3000) Overlay Data. + * @param dataset dataset to be modified + * @param image DicomImage object for this dataset + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition adjustOverlays(DcmItem *dataset, DicomImage& image) const; + + /** returns true if the transfer syntax supported by this + * codec is lossless. + * @return lossless flag + */ + virtual OFBool isLosslessProcess() const = 0; + + /** creates 'derivation description' string after encoding. + * @param toRepParam representation parameter passed to encode() + * @param cp codec parameter passed to encode() + * @param bitsPerSample bits per sample of the original image data prior to compression + * @param ratio image compression ratio. This is not the "quality factor" + * but the real effective ratio between compressed and uncompressed image, + * i. e. 30 means a 30:1 lossy compression. + * @param derivation description returned in this + * parameter which is initially empty + */ + virtual void createDerivationDescription( + const DcmRepresentationParameter * toRepParam, + const DJCodecParameter *cp, + Uint8 bitsPerSample, + double ratio, + OFString& derivationDescription) const = 0; + + /** creates an instance of the compression library to be used + * for encoding/decoding. + * @param toRepParam representation parameter passed to encode() + * @param cp codec parameter passed to encode() + * @param bitsPerSample bits per sample for the image data + * @return pointer to newly allocated codec object + */ + virtual DJEncoder *createEncoderInstance( + const DcmRepresentationParameter * toRepParam, + const DJCodecParameter *cp, + Uint8 bitsPerSample) const = 0; + + /** modifies all VOI window center/width settings in the image. + * Modifications are based on the pixel value mapping + * f(x) = (x+voiOffset)*voiFactor + * @param dataset dataset to be updated + * @param voiOffset offset to be added to each pixel + * @param voiFactor factor to be multiplied + * @return EC_Normal if successful, an error code otherwise + */ + static OFCondition correctVOIWindows(DcmItem *dataset, double voiOffset, double voiFactor); + + OFCondition updatePlanarConfiguration( + DcmItem *item, + const Uint16 newPlanConf) const; +}; + +#endif diff --git a/dcmjpeg/include/dcmtk/dcmjpeg/djcparam.h b/dcmjpeg/include/dcmtk/dcmjpeg/djcparam.h new file mode 100644 index 00000000..d3f3bcca --- /dev/null +++ b/dcmjpeg/include/dcmtk/dcmjpeg/djcparam.h @@ -0,0 +1,403 @@ +/* + * + * Copyright (C) 1997-2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmjpeg + * + * Author: Norbert Olges, Marco Eichelberg + * + * Purpose: codec parameter class for dcmjpeg codecs + * + */ + +#ifndef DJCPARAM_H +#define DJCPARAM_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmdata/dccodec.h" /* for DcmCodecParameter */ +#include "dcmtk/dcmjpeg/djutils.h" /* for enums */ + +/** codec parameter for IJG codecs + */ +class DCMTK_DCMJPEG_EXPORT DJCodecParameter: public DcmCodecParameter +{ +public: + + /** constructor. + * @param pCompressionCSConversion color conversion mode for compression + * @param pDecompressionCSConversion color conversion mode for decompression + * @param pCreateSOPInstanceUID mode for SOP Instance UID creation + * @param pPlanarConfiguration flag describing how planar configuration of + * decompressed color images should be handled + * @param predictor6WorkaroundEnable enable workaround for buggy lossless compressed images with + * overflow in predictor 6 for images with 16 bits/pixel + * @param pOptimizeHuffman perform huffman table optimization for 8 bits/pixel compression? + * @param pSmoothingFactor smoothing factor for image compression, 0..100 + * @param pForcedBitDepth forced bit depth for image compression, 0 (auto) or 8/12/16 + * @param pFragmentSize maximum fragment size (in kbytes) for compression, 0 for unlimited. + * @param pCreateOffsetTable create offset table during image compression? + * @param pSampleFactors subsampling mode for color image compression + * @param pWriteYBR422 flag indicating whether a compressed YBR color stream should + * be marked as YBR_FULL or YBR_FULL_422 on DICOM level + * @param pConvertToSC flag indicating whether image should be converted to + * Secondary Capture upon compression + * @param pWindowType mode for VOI transformation of monochrome images + * @param pWindowParameter parameter for VOI transform of monochrome images, used in modes 1, 2, 4, 6 + * @param pVoiCenter VOI window center for mode 5 + * @param pVoiWidth VOI window width for mode 5 + * @param pRoiLeft Region of Interest left corner for for VOI transform of monochrome images, mode 7 + * @param pRoiTop Region of Interest upper corner for for VOI transform of monochrome images, mode 7 + * @param pRoiWidth Region of Interest width for for VOI transform of monochrome images, mode 7 + * @param pRoiHeight Region of Interest height for for VOI transform of monochrome images, mode 7 + * @param pUsePixelValues check smallest and largest pixel value and optimize compression, mode 0 only + * @param pUseModalityRescale create Rescale Slope/Intercept to scale back to original pixel range, mode 0 only + * @param pAcceptWrongPaletteTags accept wrong palette attribute tags (only "pseudo lossless" encoder) + * @param pAcrNemaCompatibility accept old ACR-NEMA images without photometric interpretation + * (only "pseudo" lossless encoder) + * @param pTrueLosslessMode Enables true lossless compression (replaces old "pseudo lossless" encoder) + */ + DJCodecParameter( + E_CompressionColorSpaceConversion pCompressionCSConversion, + E_DecompressionColorSpaceConversion pDecompressionCSConversion, + E_UIDCreation pCreateSOPInstanceUID, + E_PlanarConfiguration pPlanarConfiguration, + OFBool predictor6WorkaroundEnable = OFFalse, + OFBool pOptimizeHuffman = OFFalse, + int pSmoothingFactor = 0, + int pForcedBitDepth = 0, + Uint32 pFragmentSize = 0, + OFBool pCreateOffsetTable = OFTrue, + E_SubSampling pSampleFactors = ESS_444, + OFBool pWriteYBR422 = OFFalse, + OFBool pConvertToSC = OFFalse, + size_t pWindowType = 0, + size_t pWindowParameter = 0, + double pVoiCenter = 0.0, + double pVoiWidth = 0.0, + size_t pRoiLeft = 0, + size_t pRoiTop = 0, + size_t pRoiWidth = 0, + size_t pRoiHeight = 0, + OFBool pUsePixelValues = OFTrue, + OFBool pUseModalityRescale = OFFalse, + OFBool pAcceptWrongPaletteTags = OFFalse, + OFBool pAcrNemaCompatibility = OFFalse, + OFBool pTrueLosslessMode = OFTrue); + + /// copy constructor + DJCodecParameter(const DJCodecParameter& arg); + + /// destructor + virtual ~DJCodecParameter(); + + /** this methods creates a copy of type DcmCodecParameter * + * it must be overweritten in every subclass. + * @return copy of this object + */ + virtual DcmCodecParameter *clone() const; + + /** returns the class name as string. + * can be used as poor man's RTTI replacement. + */ + virtual const char *className() const; + + /** returns huffman table optimization flag for 8 bits/pixel compression + * @return huffman table optimization flag for 8 bits/pixel compression + */ + OFBool getOptimizeHuffmanCoding() const + { + return optimizeHuffman; + } + + /** returns smoothing factor for image compression, 0..100 + * @return smoothing factor for image compression, 0..100 + */ + int getSmoothingFactor() const + { + return smoothingFactor; + } + + /** returns forced bit depth for image compression, 0 (auto) or 8/12/16 + * @return forced bit depth for image compression + */ + int getForcedBitDepth() const + { + return forcedBitDepth; + } + + /** returns maximum fragment size (in kbytes) for compression, 0 for unlimited. + * @returnmaximum fragment size for compression + */ + Uint32 getFragmentSize() const + { + return fragmentSize; + } + + /** returns offset table creation flag + * @return offset table creation flag + */ + OFBool getCreateOffsetTable() const + { + return createOffsetTable; + } + + /** returns subsampling mode for color image compression + * @return subsampling mode for color image compression + */ + E_SubSampling getSampleFactors() const + { + return sampleFactors; + } + + /** returns flag indicating whether a compressed YBR color stream should be marked + * as YBR_FULL or YBR_FULL_422 on DICOM level + * @return YBR422 flag + */ + OFBool getWriteYBR422() const + { + return writeYBR422; + } + + /** returns secondary capture conversion flag + * @return secondary capture conversion flag + */ + OFBool getConvertToSC() const + { + return convertToSC; + } + + /** returns mode for SOP Instance UID creation + * @return mode for SOP Instance UID creation + */ + E_UIDCreation getUIDCreation() const + { + return uidCreation; + } + + /** returns mode for VOI transformation of monochrome images. + * @return mode for VOI transformation of monochrome images + */ + size_t getWindowType() const + { + return windowType; + } + + /** returns parameter for VOI transform of monochrome images, used in VOI modes 1, 2, 4, 6 + * @return parameter for VOI transform of monochrome images, used in VOI modes 1, 2, 4, 6 + */ + size_t getWindowParameter() const + { + return windowParameter; + } + + /** returns VOI window center and width for VOI mode 5 + * @param center VOI center returned in this parameter + * @param width VOI width returned in this parameter + */ + void getVOIWindow(double& center, double& width) const + { + center = voiCenter; + width = voiWidth; + } + + /** returns ROI coordinates for VOI mode 7 + * @param left_pos ROI left edge returned in this parameter + * @param top_pos ROI top edge returned in this parameter + * @param width ROI width returned in this parameter + * @param height ROI height returned in this parameter + */ + void getROI( + size_t& left_pos, + size_t& top_pos, + size_t& width, + size_t& height) const + { + left_pos = roiLeft; + top_pos = roiTop; + width = roiWidth; + height = roiHeight; + } + + /** returns planar configuration flag + * @return planar configuration flag + */ + E_PlanarConfiguration getPlanarConfiguration() const + { + return planarConfiguration; + } + + /** returns color conversion mode for compression + * @return color conversion mode for compression + */ + E_CompressionColorSpaceConversion getCompressionColorSpaceConversion() const + { + return compressionCSConversion; + } + + /** returns color conversion mode for compression + * @return color conversion mode for compression + */ + E_DecompressionColorSpaceConversion getDecompressionColorSpaceConversion() const + { + return decompressionCSConversion; + } + + /** returns flag indicating if compression to be optimized for real pixel values + * @return flag indicating if compression to be optimized for real pixel values + */ + OFBool getUsePixelValues() const + { + return usePixelValues; + } + + /** returns flag indicating if compression should compute Rescale Slope/Intercept + * @return flag indicating if compression should compute Rescale Slope/Intercept + */ + OFBool getUseModalityRescale() const + { + return useModalityRescale; + } + + /** Returns flag indicating if incorrect palette attribute tags should be accepted + * @return flag indicating if incorrect palette attribute tags should be accepted + */ + OFBool getAcceptWrongPaletteTags() const + { + return acceptWrongPaletteTags; + } + + /** Returns flag indicating if compatibility to old ACR-NEMA images without + * photometric interpretation is enabled. + * @return flag indicating if ACR-NEMA compatibility is enabled + */ + + OFBool getAcrNemaCompatibility() const + { + return acrNemaCompatibility; + } + + /** returns flag indicating if real lossless mode is enabled + * @return flag indicating if real lossless mode is enabled + */ + OFBool getTrueLosslessMode() const + { + return trueLosslessMode; + } + + /** returns flag indicating whether the workaround for buggy JPEG lossless images with incorrect predictor 6 is enabled + * @return flag indicating whether the workaround for buggy JPEG lossless images with incorrect predictor 6 is enabled + */ + OFBool predictor6WorkaroundEnabled() const + { + return predictor6WorkaroundEnabled_; + } + +private: + + /// private undefined copy assignment operator + DJCodecParameter& operator=(const DJCodecParameter&); + + /// color conversion mode for compression + E_CompressionColorSpaceConversion compressionCSConversion; + + /// color conversion mode for decompression + E_DecompressionColorSpaceConversion decompressionCSConversion; + + /// flag describing how planar configuration of decompressed color images should be handled + E_PlanarConfiguration planarConfiguration; + + /// perform huffman table optimization for 8 bits/pixel compression? + OFBool optimizeHuffman; + + /// smoothing factor for image compression, 0..100 + int smoothingFactor; + + /// forced bit depth for image compression, 0 (auto) or 8/12/16 + int forcedBitDepth; + + /// maximum fragment size (in kbytes) for compression, 0 for unlimited. + Uint32 fragmentSize; + + /// create offset table during image compression + OFBool createOffsetTable; + + /// subsampling mode for color image compression + E_SubSampling sampleFactors; + + /** flag indicating whether a compressed YBR color stream should be marked + * as YBR_FULL or YBR_FULL_422 on DICOM level + */ + OFBool writeYBR422; + + /// flag indicating whether image should be converted to Secondary Capture upon compression + OFBool convertToSC; + + /// mode for SOP Instance UID creation + E_UIDCreation uidCreation; + + /** mode for VOI transformation of monochrome images. possible values: + 0: no VOI transformation (default). See also variables + usePixelValues (default) or useModalityRescale denoting two + further variables tweaking compression behaviour. + 1: use the n-th VOI window from the image file (see variable windowType) + 2: use the n-th VOI look up table from the image file (see variable windowType) + 3: compute VOI window using min-max algorithm + 4: compute VOI window using Histogram algorithm, ignoring n percent + 5: compute VOI window using center r and width s + 6: compute VOI window using min-max algorithm ignoring extremes + 7: compute region of interest VOI window + */ + size_t windowType; + + /// parameter for VOI transform of monochrome images, used in modes 1, 2, 4, 6 + size_t windowParameter; + + /// VOI window center for mode 5 + double voiCenter; + + /// VOI window width for mode 5 + double voiWidth; + + /// Region of Interest left corner for for VOI transform of monochrome images, mode 7 + size_t roiLeft; + + /// Region of Interest upper corner for for VOI transform of monochrome images, mode 7 + size_t roiTop; + + /// Region of Interest width for for VOI transform of monochrome images, mode 7 + size_t roiWidth; + + /// Region of Interest height for for VOI transform of monochrome images, mode 7 + size_t roiHeight; + + /// Check smallest and largest pixel value and optimize compression, mode 0 only + OFBool usePixelValues; + + /// Create Rescale Slope/Intercept to scale back to original pixel range, mode 0 only + OFBool useModalityRescale; + + /// Accept wrong palette attribute tags + OFBool acceptWrongPaletteTags; + + /// Compatibility with old ACR-NEMA images without photometric interpretation + OFBool acrNemaCompatibility; + + /// True losless mode, replaces old "pseudo" lossless encoders, when true (default) + OFBool trueLosslessMode; + + /// flag indicating that the workaround for buggy JPEG lossless images with incorrect predictor 6 is enabled + OFBool predictor6WorkaroundEnabled_; + +}; + + +#endif diff --git a/dcmjpeg/include/dcmtk/dcmjpeg/djdecabs.h b/dcmjpeg/include/dcmtk/dcmjpeg/djdecabs.h new file mode 100644 index 00000000..3049e704 --- /dev/null +++ b/dcmjpeg/include/dcmtk/dcmjpeg/djdecabs.h @@ -0,0 +1,85 @@ +/* + * + * Copyright (C) 1997-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmjpeg + * + * Author: Norbert Olges, Marco Eichelberg + * + * Purpose: abstract base class for decompression classes + * + */ + +#ifndef DJDECABS_H +#define DJDECABS_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmdata/dctypes.h" +#include "dcmtk/dcmjpeg/djutils.h" /* for enums */ +#include "dcmtk/dcmimgle/diutils.h" /* for EP_Interpretation */ + +/** abstract base class for decompression classes. + * Implementations of this class must support suspended decompression + * in which compressed data for one frame is fed block by block + * into the decompression routine, see description below. + */ +class DCMTK_DCMJPEG_EXPORT DJDecoder +{ +public: + + /// default constructor + DJDecoder() + { + } + + /// destructor + virtual ~DJDecoder() + { + } + + /** initializes internal object structures. + * Must be called before a new frame is decompressed. + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition init() = 0; + + /** suspended decompression routine. Decompresses a JPEG frame + * until finished or out of data. Can be called with new data + * until a frame is complete. + * @param compressedFrameBuffer pointer to compressed input data, must not be NULL + * @param compressedFrameBufferSize size of buffer, in bytes + * @param uncompressedFrameBuffer pointer to uncompressed output data, must not be NULL. + * This buffer must not change between multiple decode() calls for a single frame. + * @param uncompressedFrameBufferSize size of buffer, in words??? + * Buffer must be large enough to contain a complete frame. + * @param isSigned OFTrue, if uncompressed pixel data is signed, OFFalse otherwise + * @return EC_Normal if successful, EC_Suspend if more data is needed, an error code otherwise. + */ + virtual OFCondition decode( + Uint8 *compressedFrameBuffer, + Uint32 compressedFrameBufferSize, + Uint8 *uncompressedFrameBuffer, + Uint32 uncompressedFrameBufferSize, + OFBool isSigned) = 0; + + /** returns the number of bytes per sample that will be written when decoding. + */ + virtual Uint16 bytesPerSample() const = 0; + + /** after successful compression, + * returns the color model of the decompressed image + */ + virtual EP_Interpretation getDecompressedColorModel() const = 0; + +}; + +#endif diff --git a/dcmjpeg/include/dcmtk/dcmjpeg/djdecbas.h b/dcmjpeg/include/dcmtk/dcmjpeg/djdecbas.h new file mode 100644 index 00000000..549839f7 --- /dev/null +++ b/dcmjpeg/include/dcmtk/dcmjpeg/djdecbas.h @@ -0,0 +1,63 @@ +/* + * + * Copyright (C) 1997-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmjpeg + * + * Author: Marco Eichelberg, Norbert Olges + * + * Purpose: Codec class for decoding JPEG Baseline (lossy, 8-bit) + * + */ + +#ifndef DJDECBAS_H +#define DJDECBAS_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmjpeg/djcodecd.h" /* for class DJCodecDecoder */ + +/** Decoder class for JPEG Baseline (lossy, 8-bit) + */ +class DCMTK_DCMJPEG_EXPORT DJDecoderBaseline : public DJCodecDecoder +{ +public: + + /// default constructor + DJDecoderBaseline(); + + /// destructor + virtual ~DJDecoderBaseline(); + + /** returns the transfer syntax that this particular codec + * is able to encode and decode. + * @return supported transfer syntax + */ + virtual E_TransferSyntax supportedTransferSyntax() const; + +private: + + /** creates an instance of the compression library to be used for decoding. + * @param toRepParam representation parameter passed to decode() + * @param cp codec parameter passed to decode() + * @param bitsPerSample bits per sample for the image data + * @param isYBR flag indicating whether DICOM photometric interpretation is YCbCr + * @return pointer to newly allocated decoder object + */ + virtual DJDecoder *createDecoderInstance( + const DcmRepresentationParameter * toRepParam, + const DJCodecParameter *cp, + Uint8 bitsPerSample, + OFBool isYBR) const; + +}; + +#endif diff --git a/dcmjpeg/include/dcmtk/dcmjpeg/djdecext.h b/dcmjpeg/include/dcmtk/dcmjpeg/djdecext.h new file mode 100644 index 00000000..a53b911e --- /dev/null +++ b/dcmjpeg/include/dcmtk/dcmjpeg/djdecext.h @@ -0,0 +1,64 @@ +/* + * + * Copyright (C) 1997-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmjpeg + * + * Author: Marco Eichelberg, Norbert Olges + * + * Purpose: Codec class for decoding JPEG Extended Sequential (lossy, 8/12-bit) + * + */ + +#ifndef DJDECEXT_H +#define DJDECEXT_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmjpeg/djcodecd.h" /* for class DJCodecDecoder */ + + +/** Decoder class for JPEG Extended Sequential (lossy, 8/12-bit) + */ +class DCMTK_DCMJPEG_EXPORT DJDecoderExtended : public DJCodecDecoder +{ +public: + + /// default constructor + DJDecoderExtended(); + + /// destructor + virtual ~DJDecoderExtended(); + + /** returns the transfer syntax that this particular codec + * is able to encode and decode. + * @return supported transfer syntax + */ + virtual E_TransferSyntax supportedTransferSyntax() const; + +private: + + /** creates an instance of the compression library to be used for decoding. + * @param toRepParam representation parameter passed to decode() + * @param cp codec parameter passed to decode() + * @param bitsPerSample bits per sample for the image data + * @param isYBR flag indicating whether DICOM photometric interpretation is YCbCr + * @return pointer to newly allocated decoder object + */ + virtual DJDecoder *createDecoderInstance( + const DcmRepresentationParameter * toRepParam, + const DJCodecParameter *cp, + Uint8 bitsPerSample, + OFBool isYBR) const; + +}; + +#endif diff --git a/dcmjpeg/include/dcmtk/dcmjpeg/djdeclol.h b/dcmjpeg/include/dcmtk/dcmjpeg/djdeclol.h new file mode 100644 index 00000000..220aea04 --- /dev/null +++ b/dcmjpeg/include/dcmtk/dcmjpeg/djdeclol.h @@ -0,0 +1,64 @@ +/* + * + * Copyright (C) 1997-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmjpeg + * + * Author: Marco Eichelberg, Norbert Olges + * + * Purpose: Codec class for decoding JPEG Lossless (8/12/16-bit) + * + */ + +#ifndef DJDECLOL_H +#define DJDECLOL_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmjpeg/djcodecd.h" /* for class DJCodecDecoder */ + + +/** Decoder class for JPEG Lossless (8/12/16-bit) + */ +class DCMTK_DCMJPEG_EXPORT DJDecoderLossless : public DJCodecDecoder +{ +public: + + /// default constructor + DJDecoderLossless(); + + /// destructor + virtual ~DJDecoderLossless(); + + /** returns the transfer syntax that this particular codec + * is able to encode and decode. + * @return supported transfer syntax + */ + virtual E_TransferSyntax supportedTransferSyntax() const; + +private: + + /** creates an instance of the compression library to be used for decoding. + * @param toRepParam representation parameter passed to decode() + * @param cp codec parameter passed to decode() + * @param bitsPerSample bits per sample for the image data + * @param isYBR flag indicating whether DICOM photometric interpretation is YCbCr + * @return pointer to newly allocated decoder object + */ + virtual DJDecoder *createDecoderInstance( + const DcmRepresentationParameter * toRepParam, + const DJCodecParameter *cp, + Uint8 bitsPerSample, + OFBool isYBR) const; + +}; + +#endif diff --git a/dcmjpeg/include/dcmtk/dcmjpeg/djdecode.h b/dcmjpeg/include/dcmtk/dcmjpeg/djdecode.h new file mode 100644 index 00000000..d626b9dd --- /dev/null +++ b/dcmjpeg/include/dcmtk/dcmjpeg/djdecode.h @@ -0,0 +1,93 @@ +/* + * + * Copyright (C) 1997-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmjpeg + * + * Author: Marco Eichelberg + * + * Purpose: singleton class that registers decoders for all supported JPEG processes. + * + */ + +#ifndef DJDECODE_H +#define DJDECODE_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/ofstd/oftypes.h" /* for OFBool */ +#include "dcmtk/dcmjpeg/djutils.h" + +class DJCodecParameter; +class DJDecoderBaseline; +class DJDecoderExtended; +class DJDecoderLossless; +class DJDecoderP14SV1; +class DJDecoderProgressive; +class DJDecoderSpectralSelection; + +/** singleton class that registers decoders for all supported JPEG processes. + */ +class DCMTK_DCMJPEG_EXPORT DJDecoderRegistration +{ +public: + /** registers decoders for all supported JPEG processes. + * If already registered, call is ignored unless cleanup() has + * been performed before. + * @param pCreateSOPInstanceUID flag indicating whether or not + * a new SOP Instance UID should be assigned upon decompression. + * @param pPlanarConfiguration flag indicating how planar configuration + * of color images should be encoded upon decompression. + * @param predictor6WorkaroundEnable enable workaround for buggy lossless compressed images with + * overflow in predictor 6 for images with 16 bits/pixel + */ + static void registerCodecs( + E_DecompressionColorSpaceConversion pDecompressionCSConversion = EDC_photometricInterpretation, + E_UIDCreation pCreateSOPInstanceUID = EUC_default, + E_PlanarConfiguration pPlanarConfiguration = EPC_default, + OFBool predictor6WorkaroundEnable = OFFalse); + + /** deregisters decoders. + * Attention: Must not be called while other threads might still use + * the registered codecs, e.g. because they are currently decoding + * DICOM data sets through dcmdata. + */ + static void cleanup(); + +private: + + /// flag indicating whether the decoders are already registered. + static OFBool registered; + + /// pointer to codec parameter shared by all decoders + static DJCodecParameter *cp; + + /// pointer to decoder for baseline JPEG + static DJDecoderBaseline *decbas; + + /// pointer to decoder for extended JPEG + static DJDecoderExtended *decext; + + /// pointer to decoder for spectral selection JPEG + static DJDecoderSpectralSelection *decsps; + + /// pointer to decoder for progressive JPEG + static DJDecoderProgressive *decpro; + + /// pointer to decoder for lossless SV1 JPEG + static DJDecoderP14SV1 *decsv1; + + /// pointer to decoder for lossless JPEG + static DJDecoderLossless *declol; + +}; + +#endif diff --git a/dcmjpeg/include/dcmtk/dcmjpeg/djdecpro.h b/dcmjpeg/include/dcmtk/dcmjpeg/djdecpro.h new file mode 100644 index 00000000..464251fa --- /dev/null +++ b/dcmjpeg/include/dcmtk/dcmjpeg/djdecpro.h @@ -0,0 +1,64 @@ +/* + * + * Copyright (C) 1997-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmjpeg + * + * Author: Marco Eichelberg, Norbert Olges + * + * Purpose: Codec class for decoding JPEG Progressive (lossy, 8/12-bit) + * + */ + +#ifndef DJDECPRO_H +#define DJDECPRO_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmjpeg/djcodecd.h" /* for class DJCodecDecoder */ + + +/** Decoder class for JPEG Progressive (lossy, 8/12-bit) + */ +class DCMTK_DCMJPEG_EXPORT DJDecoderProgressive : public DJCodecDecoder +{ +public: + + /// default constructor + DJDecoderProgressive(); + + /// destructor + virtual ~DJDecoderProgressive(); + + /** returns the transfer syntax that this particular codec + * is able to encode and decode. + * @return supported transfer syntax + */ + virtual E_TransferSyntax supportedTransferSyntax() const; + +private: + + /** creates an instance of the compression library to be used for decoding. + * @param toRepParam representation parameter passed to decode() + * @param cp codec parameter passed to decode() + * @param bitsPerSample bits per sample for the image data + * @param isYBR flag indicating whether DICOM photometric interpretation is YCbCr + * @return pointer to newly allocated decoder object + */ + virtual DJDecoder *createDecoderInstance( + const DcmRepresentationParameter * toRepParam, + const DJCodecParameter *cp, + Uint8 bitsPerSample, + OFBool isYBR) const; + +}; + +#endif diff --git a/dcmjpeg/include/dcmtk/dcmjpeg/djdecsps.h b/dcmjpeg/include/dcmtk/dcmjpeg/djdecsps.h new file mode 100644 index 00000000..6d7f25da --- /dev/null +++ b/dcmjpeg/include/dcmtk/dcmjpeg/djdecsps.h @@ -0,0 +1,64 @@ +/* + * + * Copyright (C) 1997-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmjpeg + * + * Author: Marco Eichelberg + * + * Purpose: Codec class for decoding JPEG Spectral Selection (lossy, 8/12-bit) + * + */ + +#ifndef DJDECSPS_H +#define DJDECSPS_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmjpeg/djcodecd.h" /* for class DJCodecDecoder */ + + +/** Decoder class for JPEG Spectral Selection (lossy, 8/12-bit) + */ +class DCMTK_DCMJPEG_EXPORT DJDecoderSpectralSelection : public DJCodecDecoder +{ +public: + + /// default constructor + DJDecoderSpectralSelection(); + + /// destructor + virtual ~DJDecoderSpectralSelection(); + + /** returns the transfer syntax that this particular codec + * is able to encode and decode. + * @return supported transfer syntax + */ + virtual E_TransferSyntax supportedTransferSyntax() const; + +private: + + /** creates an instance of the compression library to be used for decoding. + * @param toRepParam representation parameter passed to decode() + * @param cp codec parameter passed to decode() + * @param bitsPerSample bits per sample for the image data + * @param isYBR flag indicating whether DICOM photometric interpretation is YCbCr + * @return pointer to newly allocated decoder object + */ + virtual DJDecoder *createDecoderInstance( + const DcmRepresentationParameter * toRepParam, + const DJCodecParameter *cp, + Uint8 bitsPerSample, + OFBool isYBR) const; + +}; + +#endif diff --git a/dcmjpeg/include/dcmtk/dcmjpeg/djdecsv1.h b/dcmjpeg/include/dcmtk/dcmjpeg/djdecsv1.h new file mode 100644 index 00000000..5567bbb2 --- /dev/null +++ b/dcmjpeg/include/dcmtk/dcmjpeg/djdecsv1.h @@ -0,0 +1,64 @@ +/* + * + * Copyright (C) 1997-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmjpeg + * + * Author: Marco Eichelberg, Norbert Olges + * + * Purpose: Codec class for decoding JPEG Lossless Selection Value 1 (8/12/16-bit) + * + */ + +#ifndef DJDECSV1_H +#define DJDECSV1_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmjpeg/djcodecd.h" /* for class DJCodecDecoder */ + + +/** Decoder class for JPEG Lossless Selection Value 1 (8/12/16-bit) + */ +class DCMTK_DCMJPEG_EXPORT DJDecoderP14SV1: public DJCodecDecoder +{ +public: + + /// default constructor + DJDecoderP14SV1(); + + /// destructor + virtual ~DJDecoderP14SV1(); + + /** returns the transfer syntax that this particular codec + * is able to encode and decode. + * @return supported transfer syntax + */ + virtual E_TransferSyntax supportedTransferSyntax() const; + +private: + + /** creates an instance of the compression library to be used for decoding. + * @param toRepParam representation parameter passed to decode() + * @param cp codec parameter passed to decode() + * @param bitsPerSample bits per sample for the image data + * @param isYBR flag indicating whether DICOM photometric interpretation is YCbCr + * @return pointer to newly allocated decoder object + */ + virtual DJDecoder *createDecoderInstance( + const DcmRepresentationParameter * toRepParam, + const DJCodecParameter *cp, + Uint8 bitsPerSample, + OFBool isYBR) const; + +}; + +#endif diff --git a/dcmjpeg/include/dcmtk/dcmjpeg/djdefine.h b/dcmjpeg/include/dcmtk/dcmjpeg/djdefine.h new file mode 100644 index 00000000..4b6fcc0a --- /dev/null +++ b/dcmjpeg/include/dcmtk/dcmjpeg/djdefine.h @@ -0,0 +1,38 @@ +/* + * + * Copyright (C) 2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmjpeg + * + * Author: Uli Schlachter + * + * Purpose: Contains preprocessor definitions + * + */ + + +#ifndef DJDEFINE_H +#define DJDEFINE_H + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/ofstd/ofdefine.h" + + +#ifdef dcmjpeg_EXPORTS +#define DCMTK_DCMJPEG_EXPORT DCMTK_DECL_EXPORT +#else +#define DCMTK_DCMJPEG_EXPORT DCMTK_DECL_IMPORT +#endif + + +#endif diff --git a/dcmjpeg/include/dcmtk/dcmjpeg/djdijg12.h b/dcmjpeg/include/dcmtk/dcmjpeg/djdijg12.h new file mode 100644 index 00000000..4db55277 --- /dev/null +++ b/dcmjpeg/include/dcmtk/dcmjpeg/djdijg12.h @@ -0,0 +1,128 @@ +/* + * + * Copyright (C) 1997-2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmjpeg + * + * Author: Norbert Olges, Marco Eichelberg + * + * Purpose: decompression routines of the IJG JPEG library configured for 12 bits/sample. + * + */ + +#ifndef DJDIJG12_H +#define DJDIJG12_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmjpeg/djdecabs.h" /* for class DJDecoder */ + +extern "C" +{ + struct jpeg_decompress_struct; +} + +class DJCodecParameter; + +/** this class encapsulates the decompression routines of the + * IJG JPEG library configured for 12 bits/sample. + */ +class DCMTK_DCMJPEG_EXPORT DJDecompressIJG12Bit : public DJDecoder +{ +public: + + /** constructor + * @param cp codec parameters + * @param isYBR flag indicating if DICOM photometric interpretation is YCbCr + */ + DJDecompressIJG12Bit(const DJCodecParameter& cp, OFBool isYBR); + + /// destructor + virtual ~DJDecompressIJG12Bit(); + + /** initializes internal object structures. + * Must be called before a new frame is decompressed. + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition init(); + + /** suspended decompression routine. Decompresses a JPEG frame + * until finished or out of data. Can be called with new data + * until a frame is complete. + * @param compressedFrameBuffer pointer to compressed input data, must not be NULL + * @param compressedFrameBufferSize size of buffer, in bytes + * @param uncompressedFrameBuffer pointer to uncompressed output data, must not be NULL. + * This buffer must not change between multiple decode() calls for a single frame. + * @param uncompressedFrameBufferSize size of buffer, in bytes (!) + * Buffer must be large enough to contain a complete frame. + * @param isSigned OFTrue, if uncompressed pixel data is signed, OFFalse otherwise + * @return EC_Normal if successful, EC_Suspend if more data is needed, an error code otherwise. + */ + virtual OFCondition decode( + Uint8 *compressedFrameBuffer, + Uint32 compressedFrameBufferSize, + Uint8 *uncompressedFrameBuffer, + Uint32 uncompressedFrameBufferSize, + OFBool isSigned); + + /** returns the number of bytes per sample that will be written when decoding. + */ + virtual Uint16 bytesPerSample() const + { + return OFstatic_cast(Uint16, sizeof(Uint16)); + } + + /** after successful compression, + * returns the color model of the decompressed image + */ + virtual EP_Interpretation getDecompressedColorModel() const + { + return decompressedColorModel; + } + + /** callback function used to report warning messages and the like. + * Should not be called by user code directly. + * @param msg_level -1 for warnings, 0 and above for trace messages + */ + virtual void emitMessage(int msg_level) const; + +private: + + /// private undefined copy constructor + DJDecompressIJG12Bit(const DJDecompressIJG12Bit&); + + /// private undefined copy assignment operator + DJDecompressIJG12Bit& operator=(const DJDecompressIJG12Bit&); + + /// cleans up cinfo structure, called from destructor and error handlers + void cleanup(); + + /// codec parameters + const DJCodecParameter *cparam; + + /// decompression structure + jpeg_decompress_struct *cinfo; + + /// position of last suspend + int suspension; + + /// temporary storage for row buffer during suspension + void *jsampBuffer; + + /// Flag indicating if DICOM photometric interpretation is YCbCr + OFBool dicomPhotometricInterpretationIsYCbCr; + + /// color model after decompression + EP_Interpretation decompressedColorModel; + +}; + +#endif diff --git a/dcmjpeg/include/dcmtk/dcmjpeg/djdijg16.h b/dcmjpeg/include/dcmtk/dcmjpeg/djdijg16.h new file mode 100644 index 00000000..356f78ba --- /dev/null +++ b/dcmjpeg/include/dcmtk/dcmjpeg/djdijg16.h @@ -0,0 +1,128 @@ +/* + * + * Copyright (C) 1997-2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmjpeg + * + * Author: Norbert Olges, Marco Eichelberg + * + * Purpose: decompression routines of the IJG JPEG library configured for 16 bits/sample. + * + */ + +#ifndef DJDIJG16_H +#define DJDIJG16_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmjpeg/djdecabs.h" /* for class DJDecoder */ + +extern "C" +{ + struct jpeg_decompress_struct; +} + +class DJCodecParameter; + +/** this class encapsulates the decompression routines of the + * IJG JPEG library configured for 16 bits/sample. + */ +class DCMTK_DCMJPEG_EXPORT DJDecompressIJG16Bit : public DJDecoder +{ +public: + + /** constructor + * @param cp codec parameters + * @param isYBR flag indicating if DICOM photometric interpretation is YCbCr + */ + DJDecompressIJG16Bit(const DJCodecParameter& cp, OFBool isYBR); + + /// destructor + virtual ~DJDecompressIJG16Bit(); + + /** initializes internal object structures. + * Must be called before a new frame is decompressed. + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition init(); + + /** suspended decompression routine. Decompresses a JPEG frame + * until finished or out of data. Can be called with new data + * until a frame is complete. + * @param compressedFrameBuffer pointer to compressed input data, must not be NULL + * @param compressedFrameBufferSize size of buffer, in bytes + * @param uncompressedFrameBuffer pointer to uncompressed output data, must not be NULL. + * This buffer must not change between multiple decode() calls for a single frame. + * @param uncompressedFrameBufferSize size of buffer, in bytes (!) + * Buffer must be large enough to contain a complete frame. + * @param isSigned OFTrue, if uncompressed pixel data is signed, OFFalse otherwise + * @return EC_Normal if successful, EC_Suspend if more data is needed, an error code otherwise. + */ + virtual OFCondition decode( + Uint8 *compressedFrameBuffer, + Uint32 compressedFrameBufferSize, + Uint8 *uncompressedFrameBuffer, + Uint32 uncompressedFrameBufferSize, + OFBool isSigned); + + /** returns the number of bytes per sample that will be written when decoding. + */ + virtual Uint16 bytesPerSample() const + { + return OFstatic_cast(Uint16, sizeof(Uint16)); + } + + /** after successful compression, + * returns the color model of the decompressed image + */ + virtual EP_Interpretation getDecompressedColorModel() const + { + return decompressedColorModel; + } + + /** callback function used to report warning messages and the like. + * Should not be called by user code directly. + * @param msg_level -1 for warnings, 0 and above for trace messages + */ + virtual void emitMessage(int msg_level) const; + +private: + + /// private undefined copy constructor + DJDecompressIJG16Bit(const DJDecompressIJG16Bit&); + + /// private undefined copy assignment operator + DJDecompressIJG16Bit& operator=(const DJDecompressIJG16Bit&); + + /// cleans up cinfo structure, called from destructor and error handlers + void cleanup(); + + /// codec parameters + const DJCodecParameter *cparam; + + /// decompression structure + jpeg_decompress_struct *cinfo; + + /// position of last suspend + int suspension; + + /// temporary storage for row buffer during suspension + void *jsampBuffer; + + /// Flag indicating if DICOM photometric interpretation is YCbCr + OFBool dicomPhotometricInterpretationIsYCbCr; + + /// color model after decompression + EP_Interpretation decompressedColorModel; + +}; + +#endif diff --git a/dcmjpeg/include/dcmtk/dcmjpeg/djdijg8.h b/dcmjpeg/include/dcmtk/dcmjpeg/djdijg8.h new file mode 100644 index 00000000..8c8ef6dc --- /dev/null +++ b/dcmjpeg/include/dcmtk/dcmjpeg/djdijg8.h @@ -0,0 +1,128 @@ +/* + * + * Copyright (C) 1997-2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmjpeg + * + * Author: Norbert Olges, Marco Eichelberg + * + * Purpose: decompression routines of the IJG JPEG library configured for 8 bits/sample. + * + */ + +#ifndef DJDIJG8_H +#define DJDIJG8_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmjpeg/djdecabs.h" /* for class DJDecoder */ + +extern "C" +{ + struct jpeg_decompress_struct; +} + +class DJCodecParameter; + +/** this class encapsulates the decompression routines of the + * IJG JPEG library configured for 8 bits/sample. + */ +class DCMTK_DCMJPEG_EXPORT DJDecompressIJG8Bit : public DJDecoder +{ +public: + + /** constructor + * @param cp codec parameters + * @param isYBR flag indicating if DICOM photometric interpretation is YCbCr + */ + DJDecompressIJG8Bit(const DJCodecParameter& cp, OFBool isYBR); + + /// destructor + virtual ~DJDecompressIJG8Bit(); + + /** initializes internal object structures. + * Must be called before a new frame is decompressed. + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition init(); + + /** suspended decompression routine. Decompresses a JPEG frame + * until finished or out of data. Can be called with new data + * until a frame is complete. + * @param compressedFrameBuffer pointer to compressed input data, must not be NULL + * @param compressedFrameBufferSize size of buffer, in bytes + * @param uncompressedFrameBuffer pointer to uncompressed output data, must not be NULL. + * This buffer must not change between multiple decode() calls for a single frame. + * @param uncompressedFrameBufferSize size of buffer, in bytes (!) + * Buffer must be large enough to contain a complete frame. + * @param isSigned OFTrue, if uncompressed pixel data is signed, OFFalse otherwise + * @return EC_Normal if successful, EC_Suspend if more data is needed, an error code otherwise. + */ + virtual OFCondition decode( + Uint8 *compressedFrameBuffer, + Uint32 compressedFrameBufferSize, + Uint8 *uncompressedFrameBuffer, + Uint32 uncompressedFrameBufferSize, + OFBool isSigned); + + /** returns the number of bytes per sample that will be written when decoding. + */ + virtual Uint16 bytesPerSample() const + { + return OFstatic_cast(Uint16, sizeof(Uint8)); + } + + /** after successful compression, + * returns the color model of the decompressed image + */ + virtual EP_Interpretation getDecompressedColorModel() const + { + return decompressedColorModel; + } + + /** callback function used to report warning messages and the like. + * Should not be called by user code directly. + * @param msg_level -1 for warnings, 0 and above for trace messages + */ + virtual void emitMessage(int msg_level) const; + +private: + + /// private undefined copy constructor + DJDecompressIJG8Bit(const DJDecompressIJG8Bit&); + + /// private undefined copy assignment operator + DJDecompressIJG8Bit& operator=(const DJDecompressIJG8Bit&); + + /// cleans up cinfo structure, called from destructor and error handlers + void cleanup(); + + /// codec parameters + const DJCodecParameter *cparam; + + /// decompression structure + jpeg_decompress_struct *cinfo; + + /// position of last suspend + int suspension; + + /// temporary storage for row buffer during suspension + void *jsampBuffer; + + /// Flag indicating if DICOM photometric interpretation is YCbCr + OFBool dicomPhotometricInterpretationIsYCbCr; + + /// color model after decompression + EP_Interpretation decompressedColorModel; + +}; + +#endif diff --git a/dcmjpeg/include/dcmtk/dcmjpeg/djeijg12.h b/dcmjpeg/include/dcmtk/dcmjpeg/djeijg12.h new file mode 100644 index 00000000..ae9cf7ef --- /dev/null +++ b/dcmjpeg/include/dcmtk/dcmjpeg/djeijg12.h @@ -0,0 +1,173 @@ +/* + * + * Copyright (C) 1997-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmjpeg + * + * Author: Norbert Olges, Marco Eichelberg + * + * Purpose: compression routines of the IJG JPEG library configured for 12 bits/sample. + * + */ + +#ifndef DJEIJG12_H +#define DJEIJG12_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/ofstd/oflist.h" +#include "dcmtk/dcmjpeg/djencabs.h" + +extern "C" +{ + struct jpeg_compress_struct; + typedef struct jpeg_compress_struct * j_compress_ptr; + struct jpeg_decompress_struct; + typedef struct jpeg_decompress_struct * j_decompress_ptr; +} + +class DJCodecParameter; + + +/** this class encapsulates the compression routines of the + * IJG JPEG library configured for 12 bits/sample. + */ +class DCMTK_DCMJPEG_EXPORT DJCompressIJG12Bit: public DJEncoder +{ +public: + + /** constructor for lossy JPEG + * @param cp codec parameters + * @param mode mode of operation + * @param quality compression quality + */ + DJCompressIJG12Bit(const DJCodecParameter& cp, EJ_Mode mode, Uint8 quality); + + /** constructor for lossless JPEG + * @param cp codec parameters + * @param prediction predictor + * @param ptrans point transform + */ + DJCompressIJG12Bit(const DJCodecParameter& cp, EJ_Mode mode, int prediction, int ptrans); + + /// destructor + virtual ~DJCompressIJG12Bit(); + + /** single frame compression routine for 16-bit raw pixel data. + * May only be called if bytesPerSample() == 2. + * @param columns columns of frame + * @param rows rows of frame + * @param interpr photometric interpretation of input frame + * @param samplesPerPixel samples per pixel of input frame + * @param image_buffer pointer to frame buffer + * @param to compressed frame returned in this parameter upon success + * @param length length of compressed frame (in bytes) returned in this parameter + * upon success; length guaranteed to be always even. + * @return EC_Normal if successful, an error code otherwise. + */ + virtual OFCondition encode( + Uint16 columns, + Uint16 rows, + EP_Interpretation interpr, + Uint16 samplesPerPixel, + Uint16 *image_buffer, + Uint8 *&to, + Uint32 &length); + + /** single frame compression routine for 8-bit raw pixel data. + * May only be called if bytesPerSample() == 1. + * @param columns columns of frame + * @param rows rows of frame + * @param interpr photometric interpretation of input frame + * @param samplesPerPixel samples per pixel of input frame + * @param image_buffer pointer to frame buffer + * @param to compressed frame returned in this parameter upon success + * @param length length of compressed frame (in bytes) returned in this parameter + * upon success; length guaranteed to be always even. + * @return EC_Normal if successful, an error code otherwise. + */ + virtual OFCondition encode( + Uint16 columns, + Uint16 rows, + EP_Interpretation interpr, + Uint16 samplesPerPixel, + Uint8 *image_buffer, + Uint8 *&to, + Uint32 &length); + + /** returns the number of bytes per sample that will be expected when encoding. + */ + virtual Uint16 bytesPerSample() const { return 2; } + + /** returns the number of bits per sample that will be expected when encoding. + */ + virtual Uint16 bitsPerSample() const { return 12; } + + /** callback for IJG compress destination manager. + * Internal use only, not to be called by client code. + * @param cinfo pointer to compress info + */ + void initDestination(jpeg_compress_struct *cinfo); + + /** callback for IJG compress destination manager. + * Internal use only, not to be called by client code. + * @param cinfo pointer to compress info + */ + int emptyOutputBuffer(jpeg_compress_struct *cinfo); + + /** callback for IJG compress destination manager. + * Internal use only, not to be called by client code. + * @param cinfo pointer to compress info + */ + void termDestination(jpeg_compress_struct *cinfo); + + /** callback function used to report warning messages and the like. + * Should not be called by user code directly. + * @param arg opaque pointer to JPEG compress structure + * @param msg_level -1 for warnings, 0 and above for trace messages + */ + virtual void emitMessage(void *arg, int msg_level) const; + +private: + + /// private undefined copy constructor + DJCompressIJG12Bit(const DJCompressIJG12Bit&); + + /// private undefined copy assignment operator + DJCompressIJG12Bit& operator=(const DJCompressIJG12Bit&); + + /// cleans up pixelDataList, called from destructor and error handlers + void cleanup(); + + /// codec parameters + const DJCodecParameter *cparam; + + /// for lossy compression, defines compression quality factor + Uint8 quality; + + /// for lossless compression, defines selection value + int psv; + + /// for lossless compression, defines point transform + int pt; + + /// enum for mode of operation (baseline, sequential, progressive etc.) + EJ_Mode modeofOperation; + + /// list of compressed pixel data blocks + OFList pixelDataList; + + /// filled number of bytes in last block in pixelDataList + size_t bytesInLastBlock; + +}; + +#endif diff --git a/dcmjpeg/include/dcmtk/dcmjpeg/djeijg16.h b/dcmjpeg/include/dcmtk/dcmjpeg/djeijg16.h new file mode 100644 index 00000000..901dc981 --- /dev/null +++ b/dcmjpeg/include/dcmtk/dcmjpeg/djeijg16.h @@ -0,0 +1,163 @@ +/* + * + * Copyright (C) 1997-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmjpeg + * + * Author: Norbert Olges, Marco Eichelberg + * + * Purpose: compression routines of the IJG JPEG library configured for 16 bits/sample. + * + */ + +#ifndef DJEIJG16_H +#define DJEIJG16_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/ofstd/oflist.h" +#include "dcmtk/dcmjpeg/djencabs.h" + +extern "C" +{ + struct jpeg_compress_struct; + typedef struct jpeg_compress_struct * j_compress_ptr; + struct jpeg_decompress_struct; + typedef struct jpeg_decompress_struct * j_decompress_ptr; +} + +class DJCodecParameter; + + +/** this class encapsulates the compression routines of the + * IJG JPEG library configured for 16 bits/sample. + */ +class DCMTK_DCMJPEG_EXPORT DJCompressIJG16Bit: public DJEncoder +{ +public: + + /** constructor for lossless JPEG + * @param cp codec parameters + * @param prediction predictor + * @param ptrans point transform + */ + DJCompressIJG16Bit(const DJCodecParameter& cp, EJ_Mode mode, int prediction, int ptrans); + + /// destructor + virtual ~DJCompressIJG16Bit(); + + /** single frame compression routine for 16-bit raw pixel data. + * May only be called if bytesPerSample() == 2. + * @param columns columns of frame + * @param rows rows of frame + * @param interpr photometric interpretation of input frame + * @param samplesPerPixel samples per pixel of input frame + * @param image_buffer pointer to frame buffer + * @param to compressed frame returned in this parameter upon success + * @param length length of compressed frame (in bytes) returned in this parameter + * upon success; length guaranteed to be always even. + * @return EC_Normal if successful, an error code otherwise. + */ + virtual OFCondition encode( + Uint16 columns, + Uint16 rows, + EP_Interpretation interpr, + Uint16 samplesPerPixel, + Uint16 *image_buffer, + Uint8 *&to, + Uint32 &length); + + /** single frame compression routine for 8-bit raw pixel data. + * May only be called if bytesPerSample() == 1. + * @param columns columns of frame + * @param rows rows of frame + * @param interpr photometric interpretation of input frame + * @param samplesPerPixel samples per pixel of input frame + * @param image_buffer pointer to frame buffer + * @param to compressed frame returned in this parameter upon success + * @param length length of compressed frame (in bytes) returned in this parameter + * upon success; length guaranteed to be always even. + * @return EC_Normal if successful, an error code otherwise. + */ + virtual OFCondition encode( + Uint16 columns, + Uint16 rows, + EP_Interpretation interpr, + Uint16 samplesPerPixel, + Uint8 *image_buffer, + Uint8 *&to, + Uint32 &length); + + /** returns the number of bytes per sample that will be expected when encoding. + */ + virtual Uint16 bytesPerSample() const { return 2; } + + /** returns the number of bits per sample that will be expected when encoding. + */ + virtual Uint16 bitsPerSample() const { return 16; } + + /** callback for IJG compress destination manager. + * Internal use only, not to be called by client code. + * @param cinfo pointer to compress info + */ + void initDestination(jpeg_compress_struct *cinfo); + + /** callback for IJG compress destination manager. + * Internal use only, not to be called by client code. + * @param cinfo pointer to compress info + */ + int emptyOutputBuffer(jpeg_compress_struct *cinfo); + + /** callback for IJG compress destination manager. + * Internal use only, not to be called by client code. + * @param cinfo pointer to compress info + */ + void termDestination(jpeg_compress_struct *cinfo); + + /** callback function used to report warning messages and the like. + * Should not be called by user code directly. + * @param arg opaque pointer to JPEG compress structure + * @param msg_level -1 for warnings, 0 and above for trace messages + */ + virtual void emitMessage(void *arg, int msg_level) const; + +private: + + /// private undefined copy constructor + DJCompressIJG16Bit(const DJCompressIJG16Bit&); + + /// private undefined copy assignment operator + DJCompressIJG16Bit& operator=(const DJCompressIJG16Bit&); + + /// cleans up pixelDataList, called from destructor and error handlers + void cleanup(); + + /// codec parameters + const DJCodecParameter *cparam; + + /// for lossless compression, defines selection value + int psv; + + /// for lossless compression, defines point transform + int pt; + + /// enum for mode of operation (baseline, sequential, progressive etc.) + EJ_Mode modeofOperation; + + /// list of compressed pixel data blocks + OFList pixelDataList; + + /// filled number of bytes in last block in pixelDataList + size_t bytesInLastBlock; + +}; + +#endif diff --git a/dcmjpeg/include/dcmtk/dcmjpeg/djeijg8.h b/dcmjpeg/include/dcmtk/dcmjpeg/djeijg8.h new file mode 100644 index 00000000..0e78f964 --- /dev/null +++ b/dcmjpeg/include/dcmtk/dcmjpeg/djeijg8.h @@ -0,0 +1,169 @@ +/* + * + * Copyright (C) 1997-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmjpeg + * + * Author: Norbert Olges, Marco Eichelberg + * + * Purpose: compression routines of the IJG JPEG library configured for 8 bits/sample. + * + */ + +#ifndef DJEIJG8_H +#define DJEIJG8_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/ofstd/oflist.h" +#include "dcmtk/dcmjpeg/djencabs.h" + +extern "C" +{ + struct jpeg_compress_struct; +} + +class DJCodecParameter; + +/** this class encapsulates the compression routines of the + * IJG JPEG library configured for 8 bits/sample. + */ +class DCMTK_DCMJPEG_EXPORT DJCompressIJG8Bit: public DJEncoder +{ +public: + + /** constructor for lossy JPEG + * @param cp codec parameters + * @param mode mode of operation + * @param quality compression quality + */ + DJCompressIJG8Bit(const DJCodecParameter& cp, EJ_Mode mode, Uint8 quality); + + /** constructor for lossless JPEG + * @param cp codec parameters + * @param prediction predictor + * @param ptrans point transform + */ + DJCompressIJG8Bit(const DJCodecParameter& cp, EJ_Mode mode, int prediction, int ptrans); + + /// destructor + virtual ~DJCompressIJG8Bit(); + + /** single frame compression routine for 16-bit raw pixel data. + * May only be called if bytesPerSample() == 2. + * @param columns columns of frame + * @param rows rows of frame + * @param interpr photometric interpretation of input frame + * @param samplesPerPixel samples per pixel of input frame + * @param image_buffer pointer to frame buffer + * @param to compressed frame returned in this parameter upon success + * @param length length of compressed frame (in bytes) returned in this parameter + * upon success; length guaranteed to be always even. + * @return EC_Normal if successful, an error code otherwise. + */ + virtual OFCondition encode( + Uint16 columns, + Uint16 rows, + EP_Interpretation interpr, + Uint16 samplesPerPixel, + Uint16 *image_buffer, + Uint8 *&to, + Uint32 &length); + + /** single frame compression routine for 8-bit raw pixel data. + * May only be called if bytesPerSample() == 1. + * @param columns columns of frame + * @param rows rows of frame + * @param interpr photometric interpretation of input frame + * @param samplesPerPixel samples per pixel of input frame + * @param image_buffer pointer to frame buffer + * @param to compressed frame returned in this parameter upon success + * @param length length of compressed frame (in bytes) returned in this parameter + * upon success; length guaranteed to be always even. + * @return EC_Normal if successful, an error code otherwise. + */ + virtual OFCondition encode( + Uint16 columns, + Uint16 rows, + EP_Interpretation interpr, + Uint16 samplesPerPixel, + Uint8 *image_buffer, + Uint8 *&to, + Uint32 &length); + + /** returns the number of bytes per sample that will be expected when encoding. + */ + virtual Uint16 bytesPerSample() const { return 1; } + + /** returns the number of bits per sample that will be expected when encoding. + */ + virtual Uint16 bitsPerSample() const { return 8; } + + /** callback for IJG compress destination manager. + * Internal use only, not to be called by client code. + * @param cinfo pointer to compress info + */ + void initDestination(jpeg_compress_struct *cinfo); + + /** callback for IJG compress destination manager. + * Internal use only, not to be called by client code. + * @param cinfo pointer to compress info + */ + int emptyOutputBuffer(jpeg_compress_struct *cinfo); + + /** callback for IJG compress destination manager. + * Internal use only, not to be called by client code. + * @param cinfo pointer to compress info + */ + void termDestination(jpeg_compress_struct *cinfo); + + /** callback function used to report warning messages and the like. + * Should not be called by user code directly. + * @param arg opaque pointer to JPEG compress structure + * @param msg_level -1 for warnings, 0 and above for trace messages + */ + virtual void emitMessage(void *arg, int msg_level) const; + +private: + + /// private undefined copy constructor + DJCompressIJG8Bit(const DJCompressIJG8Bit&); + + /// private undefined copy assignment operator + DJCompressIJG8Bit& operator=(const DJCompressIJG8Bit&); + + /// cleans up pixelDataList, called from destructor and error handlers + void cleanup(); + + /// codec parameters + const DJCodecParameter *cparam; + + /// for lossy compression, defines compression quality factor + Uint8 quality; + + /// for lossless compression, defines selection value + int psv; + + /// for lossless compression, defines point transform + int pt; + + /// enum for mode of operation (baseline, sequential, progressive etc.) + EJ_Mode modeofOperation; + + /// list of compressed pixel data blocks + OFList pixelDataList; + + /// filled number of bytes in last block in pixelDataList + size_t bytesInLastBlock; + +}; + +#endif diff --git a/dcmjpeg/include/dcmtk/dcmjpeg/djencabs.h b/dcmjpeg/include/dcmtk/dcmjpeg/djencabs.h new file mode 100644 index 00000000..368de929 --- /dev/null +++ b/dcmjpeg/include/dcmtk/dcmjpeg/djencabs.h @@ -0,0 +1,99 @@ +/* + * + * Copyright (C) 1997-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmjpeg + * + * Author: Norbert Olges, Marco Eichelberg + * + * Purpose: abstract base class for compression classes + * + */ + +#ifndef DJENCABS_H +#define DJENCABS_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmdata/dctypes.h" +#include "dcmtk/dcmimgle/diutils.h" /* for EP_Interpretation */ +#include "dcmtk/dcmjpeg/djutils.h" /* for enums */ + +/** abstract base class for compression classes. + */ +class DCMTK_DCMJPEG_EXPORT DJEncoder +{ +public: + + /// default constructor + DJEncoder() + { + } + + /// destructor + virtual ~DJEncoder() + { + } + + /** single frame compression routine for 16-bit raw pixel data. + * May only be called if bytesPerSample() == 2. + * @param columns columns of frame + * @param rows rows of frame + * @param interpr photometric interpretation of input frame + * @param samplesPerPixel samples per pixel of input frame + * @param image_buffer pointer to frame buffer + * @param to compressed frame returned in this parameter upon success + * @param length length of compressed frame (in bytes) returned in this parameter + * upon success; length guaranteed to be always even. + * @return EC_Normal if successful, an error code otherwise. + */ + virtual OFCondition encode( + Uint16 columns, + Uint16 rows, + EP_Interpretation interpr, + Uint16 samplesPerPixel, + Uint16 *image_buffer, + Uint8 *&to, + Uint32 &length) = 0; + + /** single frame compression routine for 8-bit raw pixel data. + * May only be called if bytesPerSample() == 1. + * @param columns columns of frame + * @param rows rows of frame + * @param interpr photometric interpretation of input frame + * @param samplesPerPixel samples per pixel of input frame + * @param image_buffer pointer to frame buffer + * @param to compressed frame returned in this parameter upon success + * @param length length of compressed frame (in bytes) returned in this parameter + * upon success; length guaranteed to be always even. + * @return EC_Normal if successful, an error code otherwise. + */ + virtual OFCondition encode( + Uint16 columns, + Uint16 rows, + EP_Interpretation interpr, + Uint16 samplesPerPixel, + Uint8 *image_buffer, + Uint8 *&to, + Uint32 &length) = 0; + + /** returns the number of bytes per sample that will be expected when encoding. + */ + virtual Uint16 bytesPerSample() const = 0; + + /** returns the number of bits per sample that will be expected when encoding. + */ + virtual Uint16 bitsPerSample() const = 0; + +}; + + +#endif diff --git a/dcmjpeg/include/dcmtk/dcmjpeg/djencbas.h b/dcmjpeg/include/dcmtk/dcmjpeg/djencbas.h new file mode 100644 index 00000000..83f10dc7 --- /dev/null +++ b/dcmjpeg/include/dcmtk/dcmjpeg/djencbas.h @@ -0,0 +1,86 @@ +/* + * + * Copyright (C) 1997-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmjpeg + * + * Author: Marco Eichelberg, Norbert Olges + * + * Purpose: Codec class for encoding JPEG Baseline (lossy, 8-bit) + * + */ + +#ifndef DJENCBAS_H +#define DJENCBAS_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmjpeg/djcodece.h" /* for class DJCodecEncoder */ + + +/** Encoder class for JPEG Baseline (lossy, 8-bit) + */ +class DCMTK_DCMJPEG_EXPORT DJEncoderBaseline : public DJCodecEncoder +{ +public: + + /// default constructor + DJEncoderBaseline(); + + /// destructor + virtual ~DJEncoderBaseline(); + + /** returns the transfer syntax that this particular codec + * is able to encode and decode. + * @return supported transfer syntax + */ + virtual E_TransferSyntax supportedTransferSyntax() const; + +private: + + /** returns true if the transfer syntax supported by this + * codec is lossless. + * @return lossless flag + */ + virtual OFBool isLosslessProcess() const; + + /** creates 'derivation description' string after encoding. + * @param toRepParam representation parameter passed to encode() + * @param cp codec parameter passed to encode() + * @param bitsPerSample bits per sample of the original image data prior to compression + * @param ratio image compression ratio. This is not the "quality factor" + * but the real effective ratio between compressed and uncompressed image, + * i. e. 30 means a 30:1 lossy compression. + * @param imageComments image comments returned in this + * parameter which is initially empty + */ + virtual void createDerivationDescription( + const DcmRepresentationParameter * toRepParam, + const DJCodecParameter *cp, + Uint8 bitsPerSample, + double ratio, + OFString& derivationDescription) const; + + /** creates an instance of the compression library to be used + * for encoding/decoding. + * @param toRepParam representation parameter passed to encode() + * @param cp codec parameter passed to encode() + * @param bitsPerSample bits per sample for the image data + * @return pointer to newly allocated codec object + */ + virtual DJEncoder *createEncoderInstance( + const DcmRepresentationParameter * toRepParam, + const DJCodecParameter *cp, + Uint8 bitsPerSample) const; + +}; + +#endif diff --git a/dcmjpeg/include/dcmtk/dcmjpeg/djencext.h b/dcmjpeg/include/dcmtk/dcmjpeg/djencext.h new file mode 100644 index 00000000..d0a614fd --- /dev/null +++ b/dcmjpeg/include/dcmtk/dcmjpeg/djencext.h @@ -0,0 +1,86 @@ +/* + * + * Copyright (C) 1997-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmjpeg + * + * Author: Marco Eichelberg, Norbert Olges + * + * Purpose: Codec class for encoding JPEG Extended Sequential (lossy, 8/12-bit) + * + */ + +#ifndef DJENCEXT_H +#define DJENCEXT_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmjpeg/djcodece.h" /* for class DJCodecEncoder */ + + +/** Encoder class for JPEG Extended Sequential (lossy, 8/12-bit) + */ +class DCMTK_DCMJPEG_EXPORT DJEncoderExtended : public DJCodecEncoder +{ +public: + + /// default constructor + DJEncoderExtended(); + + /// destructor + virtual ~DJEncoderExtended(); + + /** returns the transfer syntax that this particular codec + * is able to encode and decode. + * @return supported transfer syntax + */ + virtual E_TransferSyntax supportedTransferSyntax() const; + +private: + + /** returns true if the transfer syntax supported by this + * codec is lossless. + * @return lossless flag + */ + virtual OFBool isLosslessProcess() const; + + /** creates 'derivation description' string after encoding. + * @param toRepParam representation parameter passed to encode() + * @param cp codec parameter passed to encode() + * @param bitsPerSample bits per sample of the original image data prior to compression + * @param ratio image compression ratio. This is not the "quality factor" + * but the real effective ratio between compressed and uncompressed image, + * i. e. 30 means a 30:1 lossy compression. + * @param imageComments image comments returned in this + * parameter which is initially empty + */ + virtual void createDerivationDescription( + const DcmRepresentationParameter * toRepParam, + const DJCodecParameter *cp, + Uint8 bitsPerSample, + double ratio, + OFString& derivationDescription) const; + + /** creates an instance of the compression library to be used + * for encoding/decoding. + * @param toRepParam representation parameter passed to encode() + * @param cp codec parameter passed to encode() + * @param bitsPerSample bits per sample for the image data + * @return pointer to newly allocated codec object + */ + virtual DJEncoder *createEncoderInstance( + const DcmRepresentationParameter * toRepParam, + const DJCodecParameter *cp, + Uint8 bitsPerSample) const; + +}; + +#endif diff --git a/dcmjpeg/include/dcmtk/dcmjpeg/djenclol.h b/dcmjpeg/include/dcmtk/dcmjpeg/djenclol.h new file mode 100644 index 00000000..2dc86e8f --- /dev/null +++ b/dcmjpeg/include/dcmtk/dcmjpeg/djenclol.h @@ -0,0 +1,86 @@ +/* + * + * Copyright (C) 1997-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmjpeg + * + * Author: Marco Eichelberg, Norbert Olges + * + * Purpose: Codec class for encoding JPEG Lossless (8/12/16-bit) + * + */ + +#ifndef DJENCLOL_H +#define DJENCLOL_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmjpeg/djcodece.h" /* for class DJCodecEncoder */ + + +/** Encoder class for JPEG Lossless (8/12/16-bit) + */ +class DCMTK_DCMJPEG_EXPORT DJEncoderLossless : public DJCodecEncoder +{ +public: + + /// default constructor + DJEncoderLossless(); + + /// destructor + virtual ~DJEncoderLossless(); + + /** returns the transfer syntax that this particular codec + * is able to encode and decode. + * @return supported transfer syntax + */ + virtual E_TransferSyntax supportedTransferSyntax() const; + +private: + + /** returns true if the transfer syntax supported by this + * codec is lossless. + * @return lossless flag + */ + virtual OFBool isLosslessProcess() const; + + /** creates 'derivation description' string after encoding. + * @param toRepParam representation parameter passed to encode() + * @param cp codec parameter passed to encode() + * @param bitsPerSample bits per sample of the original image data prior to compression + * @param ratio image compression ratio. This is not the "quality factor" + * but the real effective ratio between compressed and uncompressed image, + * i. e. 30 means a 30:1 lossy compression. + * @param imageComments image comments returned in this + * parameter which is initially empty + */ + virtual void createDerivationDescription( + const DcmRepresentationParameter * toRepParam, + const DJCodecParameter *cp, + Uint8 bitsPerSample, + double ratio, + OFString& derivationDescription) const; + + /** creates an instance of the compression library to be used + * for encoding/decoding. + * @param toRepParam representation parameter passed to encode() + * @param cp codec parameter passed to encode() + * @param bitsPerSample bits per sample for the image data + * @return pointer to newly allocated codec object + */ + virtual DJEncoder *createEncoderInstance( + const DcmRepresentationParameter * toRepParam, + const DJCodecParameter *cp, + Uint8 bitsPerSample) const; + +}; + +#endif diff --git a/dcmjpeg/include/dcmtk/dcmjpeg/djencode.h b/dcmjpeg/include/dcmtk/dcmjpeg/djencode.h new file mode 100644 index 00000000..207b7964 --- /dev/null +++ b/dcmjpeg/include/dcmtk/dcmjpeg/djencode.h @@ -0,0 +1,134 @@ +/* + * + * Copyright (C) 1997-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmjpeg + * + * Author: Marco Eichelberg + * + * Purpose: singleton class that registers encoders for all supported JPEG processes. + * + */ + +#ifndef DJENCODE_H +#define DJENCODE_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/ofstd/oftypes.h" /* for OFBool */ +#include "dcmtk/dcmjpeg/djutils.h" +#include "dcmtk/dcmdata/dctypes.h" /* for Uint32 */ + +class DJCodecParameter; +class DJEncoderBaseline; +class DJEncoderExtended; +class DJEncoderLossless; +class DJEncoderP14SV1; +class DJEncoderProgressive; +class DJEncoderSpectralSelection; + +/** singleton class that registers encoders for all supported JPEG processes. + */ +class DCMTK_DCMJPEG_EXPORT DJEncoderRegistration +{ +public: + + /** registers encoders for all supported JPEG processes. + * If already registered, call is ignored unless cleanup() has + * been performed before. + * @param pCompressionCSConversion color conversion mode for compression + * @param pCreateSOPInstanceUID mode for SOP Instance UID creation + * @param pOptimizeHuffman perform huffman table optimization for 8 bits/pixel compression? + * @param pSmoothingFactor smoothing factor for image compression, 0..100 + * @param pForcedBitDepth forced bit depth for image compression, 0 (auto) or 8/12/16 + * @param pFragmentSize maximum fragment size (in kbytes) for compression, 0 for unlimited. + * @param pCreateOffsetTable create offset table during image compression? + * @param pSampleFactors subsampling mode for color image compression + * @param pWriteYBR422 flag indicating whether a compressed YBR color stream should + * be marked as YBR_FULL or YBR_FULL_422 on DICOM level + * @param pConvertToSC flag indicating whether image should be converted to + * Secondary Capture upon compression + * @param pWindowType mode for VOI transformation of monochrome images + * @param pWindowParameter parameter for VOI transform of monochrome images, used in modes 1, 2, 4, 6 + * @param pVoiCenter VOI window center for mode 5 + * @param pVoiWidth VOI window width for mode 5 + * @param pRoiLeft Region of Interest left corner for for VOI transform of monochrome images, mode 7 + * @param pRoiTop Region of Interest upper corner for for VOI transform of monochrome images, mode 7 + * @param pRoiWidth Region of Interest width for for VOI transform of monochrome images, mode 7 + * @param pRoiHeight Region of Interest height for for VOI transform of monochrome images, mode 7 + * @param pUsePixelValues Check smallest and largest pixel value and optimize compression, mode 0 only + * @param pUseModalityRescale Create Rescale Slope/Intercept to scale back + * to original pixel range, mode 0 only + * @param pAcceptWrongPaletteTags Accept wrong palette attribute tags (only "pseudo lossless" encoder) + * @param pAcrNemaCompatibility Accept old ACR-NEMA images without photometric interpretation (only "pseudo lossless" encoder) + * @param pRealLossless Enables true lossless compression (replaces old "pseudo" lossless encoders) + */ + static void registerCodecs( + E_CompressionColorSpaceConversion pCompressionCSConversion = ECC_lossyYCbCr, + E_UIDCreation pCreateSOPInstanceUID = EUC_default, + OFBool pOptimizeHuffman = OFFalse, + int pSmoothingFactor = 0, + int pForcedBitDepth = 0, + Uint32 pFragmentSize = 0, + OFBool pCreateOffsetTable = OFTrue, + E_SubSampling pSampleFactors = ESS_444, + OFBool pWriteYBR422 = OFFalse, + OFBool pConvertToSC = OFFalse, + unsigned long pWindowType = 0, + unsigned long pWindowParameter = 0, + double pVoiCenter = 0.0, + double pVoiWidth = 0.0, + unsigned long pRoiLeft = 0, + unsigned long pRoiTop = 0, + unsigned long pRoiWidth = 0, + unsigned long pRoiHeight = 0, + OFBool pUsePixelValues = OFTrue, + OFBool pUseModalityRescale = OFFalse, + OFBool pAcceptWrongPaletteTags = OFFalse, + OFBool pAcrNemaCompatibility = OFFalse, + OFBool pRealLossless = OFTrue); + + /** deregisters encoders. + * Attention: Must not be called while other threads might still use + * the registered codecs, e.g. because they are currently encoding + * DICOM data sets through dcmdata. + */ + static void cleanup(); + +private: + + /// flag indicating whether the encoders are already registered. + static OFBool registered; + + /// pointer to codec parameter shared by all encoders + static DJCodecParameter *cp; + + /// pointer to encoder for baseline JPEG + static DJEncoderBaseline *encbas; + + /// pointer to encoder for extended JPEG + static DJEncoderExtended *encext; + + /// pointer to encoder for spectral selection JPEG + static DJEncoderSpectralSelection *encsps; + + /// pointer to encoder for progressive JPEG + static DJEncoderProgressive *encpro; + + /// pointer to encoder for lossless SV1 JPEG + static DJEncoderP14SV1 *encsv1; + + /// pointer to encoder for lossless JPEG + static DJEncoderLossless *enclol; + +}; + +#endif diff --git a/dcmjpeg/include/dcmtk/dcmjpeg/djencpro.h b/dcmjpeg/include/dcmtk/dcmjpeg/djencpro.h new file mode 100644 index 00000000..b385c824 --- /dev/null +++ b/dcmjpeg/include/dcmtk/dcmjpeg/djencpro.h @@ -0,0 +1,86 @@ +/* + * + * Copyright (C) 1997-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmjpeg + * + * Author: Marco Eichelberg, Norbert Olges + * + * Purpose: Codec class for encoding JPEG Progressive (lossy, 8/12-bit) + * + */ + +#ifndef DJENCPRO_H +#define DJENCPRO_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmjpeg/djcodece.h" /* for class DJCodecEncoder */ + + +/** Encoder class for JPEG Progressive (lossy, 8/12-bit) + */ +class DCMTK_DCMJPEG_EXPORT DJEncoderProgressive : public DJCodecEncoder +{ +public: + + /// default constructor + DJEncoderProgressive(); + + /// destructor + virtual ~DJEncoderProgressive(); + + /** returns the transfer syntax that this particular codec + * is able to encode and decode. + * @return supported transfer syntax + */ + virtual E_TransferSyntax supportedTransferSyntax() const; + +private: + + /** returns true if the transfer syntax supported by this + * codec is lossless. + * @return lossless flag + */ + virtual OFBool isLosslessProcess() const; + + /** creates 'derivation description' string after encoding. + * @param toRepParam representation parameter passed to encode() + * @param cp codec parameter passed to encode() + * @param bitsPerSample bits per sample of the original image data prior to compression + * @param ratio image compression ratio. This is not the "quality factor" + * but the real effective ratio between compressed and uncompressed image, + * i. e. 30 means a 30:1 lossy compression. + * @param imageComments image comments returned in this + * parameter which is initially empty + */ + virtual void createDerivationDescription( + const DcmRepresentationParameter * toRepParam, + const DJCodecParameter *cp, + Uint8 bitsPerSample, + double ratio, + OFString& derivationDescription) const; + + /** creates an instance of the compression library to be used + * for encoding/decoding. + * @param toRepParam representation parameter passed to encode() + * @param cp codec parameter passed to encode() + * @param bitsPerSample bits per sample for the image data + * @return pointer to newly allocated codec object + */ + virtual DJEncoder *createEncoderInstance( + const DcmRepresentationParameter * toRepParam, + const DJCodecParameter *cp, + Uint8 bitsPerSample) const; + +}; + +#endif diff --git a/dcmjpeg/include/dcmtk/dcmjpeg/djencsps.h b/dcmjpeg/include/dcmtk/dcmjpeg/djencsps.h new file mode 100644 index 00000000..de07fd78 --- /dev/null +++ b/dcmjpeg/include/dcmtk/dcmjpeg/djencsps.h @@ -0,0 +1,86 @@ +/* + * + * Copyright (C) 1997-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmjpeg + * + * Author: Marco Eichelberg + * + * Purpose: Codec class for encoding JPEG Spectral Selection (lossy, 8/12-bit) + * + */ + +#ifndef DJENCSPS_H +#define DJENCSPS_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmjpeg/djcodece.h" /* for class DJCodecEncoder */ + + +/** Encoder class for JPEG Spectral Selection (lossy, 8/12-bit) + */ +class DCMTK_DCMJPEG_EXPORT DJEncoderSpectralSelection : public DJCodecEncoder +{ +public: + + /// default constructor + DJEncoderSpectralSelection(); + + /// destructor + virtual ~DJEncoderSpectralSelection(); + + /** returns the transfer syntax that this particular codec + * is able to encode and decode. + * @return supported transfer syntax + */ + virtual E_TransferSyntax supportedTransferSyntax() const; + +private: + + /** returns true if the transfer syntax supported by this + * codec is lossless. + * @return lossless flag + */ + virtual OFBool isLosslessProcess() const; + + /** creates 'derivation description' string after encoding. + * @param toRepParam representation parameter passed to encode() + * @param cp codec parameter passed to encode() + * @param bitsPerSample bits per sample of the original image data prior to compression + * @param ratio image compression ratio. This is not the "quality factor" + * but the real effective ratio between compressed and uncompressed image, + * i. e. 30 means a 30:1 lossy compression. + * @param imageComments image comments returned in this + * parameter which is initially empty + */ + virtual void createDerivationDescription( + const DcmRepresentationParameter * toRepParam, + const DJCodecParameter *cp, + Uint8 bitsPerSample, + double ratio, + OFString& derivationDescription) const; + + /** creates an instance of the compression library to be used + * for encoding/decoding. + * @param toRepParam representation parameter passed to encode() + * @param cp codec parameter passed to encode() + * @param bitsPerSample bits per sample for the image data + * @return pointer to newly allocated codec object + */ + virtual DJEncoder *createEncoderInstance( + const DcmRepresentationParameter * toRepParam, + const DJCodecParameter *cp, + Uint8 bitsPerSample) const; + +}; + +#endif diff --git a/dcmjpeg/include/dcmtk/dcmjpeg/djencsv1.h b/dcmjpeg/include/dcmtk/dcmjpeg/djencsv1.h new file mode 100644 index 00000000..e0e91fbf --- /dev/null +++ b/dcmjpeg/include/dcmtk/dcmjpeg/djencsv1.h @@ -0,0 +1,86 @@ +/* + * + * Copyright (C) 1997-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmjpeg + * + * Author: Marco Eichelberg, Norbert Olges + * + * Purpose: Codec class for encoding JPEG Lossless Selection Value 1 (8/12/16-bit) + * + */ + +#ifndef DJENCSV1_H +#define DJENCSV1_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmjpeg/djcodece.h" /* for class DJCodecEncoder */ + + +/** Encoder class for JPEG Lossless Selection Value 1 (8/12/16-bit) + */ +class DCMTK_DCMJPEG_EXPORT DJEncoderP14SV1: public DJCodecEncoder +{ +public: + + /// default constructor + DJEncoderP14SV1(); + + /// destructor + virtual ~DJEncoderP14SV1(); + + /** returns the transfer syntax that this particular codec + * is able to encode and decode. + * @return supported transfer syntax + */ + virtual E_TransferSyntax supportedTransferSyntax() const; + +private: + + /** returns true if the transfer syntax supported by this + * codec is lossless. + * @return lossless flag + */ + virtual OFBool isLosslessProcess() const; + + /** creates 'derivation description' string after encoding. + * @param toRepParam representation parameter passed to encode() + * @param cp codec parameter passed to encode() + * @param bitsPerSample bits per sample of the original image data prior to compression + * @param ratio image compression ratio. This is not the "quality factor" + * but the real effective ratio between compressed and uncompressed image, + * i. e. 30 means a 30:1 lossy compression. + * @param imageComments image comments returned in this + * parameter which is initially empty + */ + virtual void createDerivationDescription( + const DcmRepresentationParameter * toRepParam, + const DJCodecParameter *cp, + Uint8 bitsPerSample, + double ratio, + OFString& derivationDescription) const; + + /** creates an instance of the compression library to be used + * for encoding/decoding. + * @param toRepParam representation parameter passed to encode() + * @param cp codec parameter passed to encode() + * @param bitsPerSample bits per sample for the image data + * @return pointer to newly allocated codec object + */ + virtual DJEncoder *createEncoderInstance( + const DcmRepresentationParameter * toRepParam, + const DJCodecParameter *cp, + Uint8 bitsPerSample) const; + +}; + +#endif diff --git a/dcmjpeg/include/dcmtk/dcmjpeg/djrplol.h b/dcmjpeg/include/dcmtk/dcmjpeg/djrplol.h new file mode 100644 index 00000000..199ea2b7 --- /dev/null +++ b/dcmjpeg/include/dcmtk/dcmjpeg/djrplol.h @@ -0,0 +1,90 @@ +/* + * + * Copyright (C) 1997-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmjpeg + * + * Author: Norbert Olges, Marco Eichelberg + * + * Purpose: representation parameter for lossless JPEG + * + */ + +#ifndef DJRPLOL_H +#define DJRPLOL_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmdata/dcpixel.h" /* for class DcmRepresentationParameter */ +#include "dcmtk/dcmjpeg/djdefine.h" + +/** representation parameter for lossless JPEG + */ +class DCMTK_DCMJPEG_EXPORT DJ_RPLossless : public DcmRepresentationParameter +{ +public: + + /** constructor + * @param aPrediction prediction value + * @param aPt point transform value + */ + DJ_RPLossless(int aPrediction=1, int aPt=0); + + /// copy constructor + DJ_RPLossless(const DJ_RPLossless& arg); + + /// destructor + virtual ~DJ_RPLossless(); + + /** this methods creates a copy of type DcmRepresentationParameter * + * it must be overweritten in every subclass. + * @return copy of this object + */ + virtual DcmRepresentationParameter *clone() const; + + /** returns the class name as string. + * can be used in operator== as poor man's RTTI replacement. + */ + virtual const char *className() const; + + /** compares an object to another DcmRepresentationParameter. + * Implementation must make sure that classes are comparable. + * @param arg representation parameter to compare with + * @return true if equal, false otherwise. + */ + virtual OFBool operator==(const DcmRepresentationParameter &arg) const; + + /** returns the prediction value + * @return prediction value + */ + int getPrediction() const + { + return prediction; + } + + /** returns the point transform + * @return point transform + */ + int getPointTransformation() const + { + return pt; + } + +private: + + /// prediction value + int prediction; + + /// point transform value + int pt; +}; + +#endif diff --git a/dcmjpeg/include/dcmtk/dcmjpeg/djrploss.h b/dcmjpeg/include/dcmtk/dcmjpeg/djrploss.h new file mode 100644 index 00000000..eebd6e83 --- /dev/null +++ b/dcmjpeg/include/dcmtk/dcmjpeg/djrploss.h @@ -0,0 +1,80 @@ +/* + * + * Copyright (C) 1997-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmjpeg + * + * Author: Norbert Olges, Marco Eichelberg + * + * Purpose: representation parameter for lossy JPEG + * + */ + +#ifndef DJRPLOSS_H +#define DJRPLOSS_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmdata/dcpixel.h" /* for class DcmRepresentationParameter */ +#include "dcmtk/dcmjpeg/djdefine.h" + +/** representation parameter for lossy JPEG + */ +class DCMTK_DCMJPEG_EXPORT DJ_RPLossy: public DcmRepresentationParameter +{ +public: + + /** constructor + * @param aQuality quality factor + */ + DJ_RPLossy(int aQuality=90); + + /// copy constructor + DJ_RPLossy(const DJ_RPLossy& arg); + + /// destructor + virtual ~DJ_RPLossy(); + + /** this methods creates a copy of type DcmRepresentationParameter * + * it must be overweritten in every subclass. + * @return copy of this object + */ + virtual DcmRepresentationParameter *clone() const; + + /** returns the class name as string. + * can be used in operator== as poor man's RTTI replacement. + */ + virtual const char *className() const; + + /** compares an object to another DcmRepresentationParameter. + * Implementation must make sure that classes are comparable. + * @param arg representation parameter to compare with + * @return true if equal, false otherwise. + */ + virtual OFBool operator==(const DcmRepresentationParameter &arg) const; + + /** returns the compression quality factor + * @return compression quality factor + */ + int getQuality() const + { + return quality; + } + +private: + + /// compression quality factor + int quality; + +}; + + +#endif diff --git a/dcmjpeg/include/dcmtk/dcmjpeg/djutils.h b/dcmjpeg/include/dcmtk/dcmjpeg/djutils.h new file mode 100644 index 00000000..80f7a743 --- /dev/null +++ b/dcmjpeg/include/dcmtk/dcmjpeg/djutils.h @@ -0,0 +1,223 @@ +/* + * + * Copyright (C) 1997-2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmjpeg + * + * Author: Norbert Olges, Marco Eichelberg + * + * Purpose: enumerations, error constants and helper functions for dcmjpeg + * + */ + +#ifndef DJUTILS_H +#define DJUTILS_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/ofstd/ofcond.h" /* for class OFCondition */ +#include "dcmtk/dcmimgle/diutils.h" /* for EP_Interpretation */ +#include "dcmtk/oflog/oflog.h" +#include "dcmtk/dcmjpeg/djdefine.h" + + +// global definitions for logging mechanism provided by the oflog module + +extern DCMTK_DCMJPEG_EXPORT OFLogger DCM_dcmjpegLogger; + +#define DCMJPEG_TRACE(msg) OFLOG_TRACE(DCM_dcmjpegLogger, msg) +#define DCMJPEG_DEBUG(msg) OFLOG_DEBUG(DCM_dcmjpegLogger, msg) +#define DCMJPEG_INFO(msg) OFLOG_INFO(DCM_dcmjpegLogger, msg) +#define DCMJPEG_WARN(msg) OFLOG_WARN(DCM_dcmjpegLogger, msg) +#define DCMJPEG_ERROR(msg) OFLOG_ERROR(DCM_dcmjpegLogger, msg) +#define DCMJPEG_FATAL(msg) OFLOG_FATAL(DCM_dcmjpegLogger, msg) + + +// include this file in doxygen documentation + +/** @file djutils.h + * @brief enumerations, error constants and helper functions for the dcmjpeg module + */ + + +// forward declarations + +class DcmItem; + + +/** describes the different modes of operation of a JPEG codec + */ +enum EJ_Mode +{ + /// JPEG baseline + EJM_baseline, + + /// JPEG extended sequential + EJM_sequential, + + /// JPEG spectral selection + EJM_spectralSelection, + + /// JPEG full progression + EJM_progressive, + + /// JPEG lossless + EJM_lossless +}; + +/** describes the different types of component sub-sampling + * to be used with lossy image compression. + */ +enum E_SubSampling +{ + /// 4:4:4 sampling (no subsampling) + ESS_444, + /// 4:2:2 sampling (horizontal subsampling of chroma components) + ESS_422, + /// 4:1:1 sampling (horizontal and vertical subsampling of chroma components) + ESS_411 +}; + +/** describes the condition under which a compressed or decompressed image + * receives a new SOP instance UID. + */ +enum E_UIDCreation +{ + /** Upon compression, assign new SOP instance UID if compression is lossy. + * Upon decompression never assign new SOP instance UID. + */ + EUC_default, + + /// always assign new SOP instance UID on compression and decompression + EUC_always, + + /// never assign new SOP instance UID + EUC_never +}; + +/** describes how the decoder should handle planar configuration of + * decompressed color images. + */ +enum E_PlanarConfiguration +{ + /** automatically determine whether color-by-plane is required from + * the SOP Class UID and decompressed photometric interpretation + */ + EPC_default, + + /// always create color-by-pixel planar configuration + EPC_colorByPixel, + + /// always create color-by-plane planar configuration + EPC_colorByPlane +}; + +/** describes how color space conversion should be handled + * during the conversion of an uncompressed DICOM image to + * a JPEG-compressed image + */ +enum E_CompressionColorSpaceConversion +{ + /** encode color images in YCbCr if lossy JPEG. + * If lossless JPEG, images are encoded as RGB unless the source + * image is YCbCr in which case no color conversion is performed. + */ + ECC_lossyYCbCr, + + /** encode color images in RGB unless the source + * image is YCbCr in which case no color conversion is performed. + */ + ECC_lossyRGB, + + /** convert color images to monochrome before compressing + */ + ECC_monochrome +}; + +/** describes how color space conversion should be handled + * during the conversion of a JPEG-compressed DICOM image to + * an uncompressed image + */ +enum E_DecompressionColorSpaceConversion +{ + /** perform color space conversion from YCbCr to RGB if + * DICOM photometric interpretation indicates YCbCr. + */ + EDC_photometricInterpretation, + + /** always perform color space conversion from YCbCr to + * RGB if JPEG data is color image and compression is lossy. + */ + EDC_lossyOnly, + + /** always perform color space conversion from YCbCr to + * RGB if JPEG data is color image. + */ + EDC_always, + + /** never perform any color space conversion. + */ + EDC_never, + + /** perform color space conversion from YCbCr to RGB if + * JPEG data is color image, compression is lossy, and + * the underlying JPEG library "guesses" the color space + * to be YCbCr. + */ + EDC_guessLossyOnly, + + /** perform color space conversion from YCbCr to RGB if + * JPEG data is color image, and the underlying JPEG + * library "guesses" the color space to be YCbCr. + */ + EDC_guess +}; + + +// CONDITION CONSTANTS + +/// IJG codec suspension return +extern DCMTK_DCMJPEG_EXPORT const OFConditionConst EJ_Suspension; +/// Buffer for decompressed image (8 bits/sample) too small +extern DCMTK_DCMJPEG_EXPORT const OFConditionConst EJ_IJG8_FrameBufferTooSmall; +/// Buffer for decompressed image (12 bits/sample) too small +extern DCMTK_DCMJPEG_EXPORT const OFConditionConst EJ_IJG12_FrameBufferTooSmall; +/// Buffer for decompressed image (16 bits/sample) too small +extern DCMTK_DCMJPEG_EXPORT const OFConditionConst EJ_IJG16_FrameBufferTooSmall; +/// Codec does not support this PhotometricInterpretation +extern DCMTK_DCMJPEG_EXPORT const OFConditionConst EJ_UnsupportedPhotometricInterpretation; +/// Codec does not support this kind of color conversion +extern DCMTK_DCMJPEG_EXPORT const OFConditionConst EJ_UnsupportedColorConversion; + +// reserved condition codes for IJG error messages +const unsigned short EJCode_IJG8_Compression = 0x0100; +const unsigned short EJCode_IJG8_Decompression = 0x0101; +const unsigned short EJCode_IJG12_Compression = 0x0102; +const unsigned short EJCode_IJG12_Decompression = 0x0103; +const unsigned short EJCode_IJG16_Compression = 0x0104; +const unsigned short EJCode_IJG16_Decompression = 0x0105; + +/** helper class with static methods used from different dcmjpeg classes + * (in particular from the encoder and the decoder part). + */ +class DCMTK_DCMJPEG_EXPORT DcmJpegHelper +{ +public: + + /** helper function that locates the photometric interpretation attribute + * in a DICOM dataset and returns a parsed value. + * @param item the dataset in which the element is searched + * @return photometric interpretation enum, EPI_Unknown if unknown string or attribute missing + */ + static EP_Interpretation getPhotometricInterpretation(DcmItem *item); +}; + +#endif diff --git a/dcmjpeg/libijg12/CMakeLists.txt b/dcmjpeg/libijg12/CMakeLists.txt new file mode 100644 index 00000000..6fe1a2b1 --- /dev/null +++ b/dcmjpeg/libijg12/CMakeLists.txt @@ -0,0 +1,2 @@ +# create library from source files +DCMTK_ADD_LIBRARY(ijg12 jaricom jcapimin jcapistd jcarith jccoefct jccolor jcdctmgr jcdiffct jchuff jcinit jclhuff jclossls jclossy jcmainct jcmarker jcmaster jcodec jcomapi jcparam jcphuff jcpred jcprepct jcsample jcscale jcshuff jctrans jdapimin jdapistd jdarith jdatadst jdatasrc jdcoefct jdcolor jddctmgr jddiffct jdhuff jdinput jdlhuff jdlossls jdlossy jdmainct jdmarker jdmaster jdmerge jdphuff jdpostct jdpred jdsample jdscale jdshuff jdtrans jerror jfdctflt jfdctfst jfdctint jidctflt jidctfst jidctint jidctred jmemmgr jmemnobs jquant1 jquant2 jutils) diff --git a/dcmjpeg/libijg12/Makefile.dep b/dcmjpeg/libijg12/Makefile.dep new file mode 100644 index 00000000..61366d2b --- /dev/null +++ b/dcmjpeg/libijg12/Makefile.dep @@ -0,0 +1,227 @@ +jaricom.o: jaricom.c jinclude12.h jconfig12.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib12.h jmorecfg12.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint12.h jerror12.h +jcapimin.o: jcapimin.c jinclude12.h jconfig12.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib12.h jmorecfg12.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint12.h jerror12.h +jcapistd.o: jcapistd.c jinclude12.h jconfig12.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib12.h jmorecfg12.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint12.h jerror12.h +jcarith.o: jcarith.c jinclude12.h jconfig12.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib12.h jmorecfg12.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint12.h jerror12.h +jccoefct.o: jccoefct.c jinclude12.h jconfig12.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib12.h jmorecfg12.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint12.h jerror12.h \ + jlossy12.h +jccolor.o: jccolor.c jinclude12.h jconfig12.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib12.h jmorecfg12.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint12.h jerror12.h +jcdctmgr.o: jcdctmgr.c jinclude12.h jconfig12.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib12.h jmorecfg12.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint12.h jerror12.h \ + jlossy12.h jdct12.h +jcdiffct.o: jcdiffct.c jinclude12.h jconfig12.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib12.h jmorecfg12.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint12.h jerror12.h \ + jlossls12.h +jchuff.o: jchuff.c jinclude12.h jconfig12.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib12.h jmorecfg12.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint12.h jerror12.h \ + jchuff12.h +jcinit.o: jcinit.c jinclude12.h jconfig12.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib12.h jmorecfg12.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint12.h jerror12.h +jclhuff.o: jclhuff.c jinclude12.h jconfig12.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib12.h jmorecfg12.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint12.h jerror12.h \ + jlossls12.h jchuff12.h +jclossls.o: jclossls.c jinclude12.h jconfig12.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib12.h jmorecfg12.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint12.h jerror12.h \ + jlossls12.h +jclossy.o: jclossy.c jinclude12.h jconfig12.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib12.h jmorecfg12.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint12.h jerror12.h \ + jlossy12.h +jcmainct.o: jcmainct.c jinclude12.h jconfig12.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib12.h jmorecfg12.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint12.h jerror12.h +jcmarker.o: jcmarker.c jinclude12.h jconfig12.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib12.h jmorecfg12.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint12.h jerror12.h +jcmaster.o: jcmaster.c jinclude12.h jconfig12.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib12.h jmorecfg12.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint12.h jerror12.h \ + jlossy12.h +jcodec.o: jcodec.c jinclude12.h jconfig12.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib12.h jmorecfg12.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint12.h jerror12.h \ + jlossy12.h jlossls12.h +jcomapi.o: jcomapi.c jinclude12.h jconfig12.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib12.h jmorecfg12.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint12.h jerror12.h +jcparam.o: jcparam.c jinclude12.h jconfig12.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib12.h jmorecfg12.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint12.h jerror12.h +jcphuff.o: jcphuff.c jinclude12.h jconfig12.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib12.h jmorecfg12.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint12.h jerror12.h \ + jlossy12.h jchuff12.h +jcpred.o: jcpred.c jinclude12.h jconfig12.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib12.h jmorecfg12.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint12.h jerror12.h \ + jlossls12.h +jcprepct.o: jcprepct.c jinclude12.h jconfig12.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib12.h jmorecfg12.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint12.h jerror12.h +jcsample.o: jcsample.c jinclude12.h jconfig12.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib12.h jmorecfg12.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint12.h jerror12.h +jcscale.o: jcscale.c jinclude12.h jconfig12.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib12.h jmorecfg12.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint12.h jerror12.h \ + jlossls12.h +jcshuff.o: jcshuff.c jinclude12.h jconfig12.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib12.h jmorecfg12.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint12.h jerror12.h \ + jlossy12.h jchuff12.h +jctrans.o: jctrans.c jinclude12.h jconfig12.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib12.h jmorecfg12.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint12.h jerror12.h \ + jlossy12.h +jdapimin.o: jdapimin.c jinclude12.h jconfig12.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib12.h jmorecfg12.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint12.h jerror12.h +jdapistd.o: jdapistd.c jinclude12.h jconfig12.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib12.h jmorecfg12.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint12.h jerror12.h +jdarith.o: jdarith.c jinclude12.h jconfig12.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib12.h jmorecfg12.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint12.h jerror12.h +jdatadst.o: jdatadst.c jinclude12.h jconfig12.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib12.h jmorecfg12.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jerror12.h +jdatasrc.o: jdatasrc.c jinclude12.h jconfig12.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib12.h jmorecfg12.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jerror12.h +jdcoefct.o: jdcoefct.c jinclude12.h jconfig12.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib12.h jmorecfg12.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint12.h jerror12.h \ + jlossy12.h +jdcolor.o: jdcolor.c jinclude12.h jconfig12.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib12.h jmorecfg12.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint12.h jerror12.h +jddctmgr.o: jddctmgr.c jinclude12.h jconfig12.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib12.h jmorecfg12.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint12.h jerror12.h \ + jlossy12.h jdct12.h +jddiffct.o: jddiffct.c jinclude12.h jconfig12.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib12.h jmorecfg12.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint12.h jerror12.h \ + jlossls12.h +jdhuff.o: jdhuff.c jinclude12.h jconfig12.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib12.h jmorecfg12.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint12.h jerror12.h \ + jlossy12.h jlossls12.h jdhuff12.h +jdinput.o: jdinput.c jinclude12.h jconfig12.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib12.h jmorecfg12.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint12.h jerror12.h +jdlhuff.o: jdlhuff.c jinclude12.h jconfig12.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib12.h jmorecfg12.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint12.h jerror12.h \ + jlossls12.h jdhuff12.h +jdlossls.o: jdlossls.c jinclude12.h jconfig12.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib12.h jmorecfg12.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint12.h jerror12.h \ + jlossls12.h +jdlossy.o: jdlossy.c jinclude12.h jconfig12.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib12.h jmorecfg12.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint12.h jerror12.h \ + jlossy12.h +jdmainct.o: jdmainct.c jinclude12.h jconfig12.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib12.h jmorecfg12.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint12.h jerror12.h +jdmarker.o: jdmarker.c jinclude12.h jconfig12.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib12.h jmorecfg12.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint12.h jerror12.h +jdmaster.o: jdmaster.c jinclude12.h jconfig12.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib12.h jmorecfg12.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint12.h jerror12.h +jdmerge.o: jdmerge.c jinclude12.h jconfig12.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib12.h jmorecfg12.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint12.h jerror12.h +jdphuff.o: jdphuff.c jinclude12.h jconfig12.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib12.h jmorecfg12.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint12.h jerror12.h \ + jlossy12.h jdhuff12.h +jdpostct.o: jdpostct.c jinclude12.h jconfig12.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib12.h jmorecfg12.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint12.h jerror12.h +jdpred.o: jdpred.c jinclude12.h jconfig12.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib12.h jmorecfg12.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint12.h jerror12.h \ + jlossls12.h +jdsample.o: jdsample.c jinclude12.h jconfig12.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib12.h jmorecfg12.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint12.h jerror12.h +jdscale.o: jdscale.c jinclude12.h jconfig12.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib12.h jmorecfg12.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint12.h jerror12.h \ + jlossls12.h +jdshuff.o: jdshuff.c jinclude12.h jconfig12.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib12.h jmorecfg12.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint12.h jerror12.h \ + jlossy12.h jdhuff12.h +jdtrans.o: jdtrans.c jinclude12.h jconfig12.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib12.h jmorecfg12.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint12.h jerror12.h \ + jlossy12.h +jerror.o: jerror.c jinclude12.h jconfig12.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib12.h jmorecfg12.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jversion12.h jerror12.h +jfdctflt.o: jfdctflt.c jinclude12.h jconfig12.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib12.h jmorecfg12.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint12.h jerror12.h \ + jdct12.h +jfdctfst.o: jfdctfst.c jinclude12.h jconfig12.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib12.h jmorecfg12.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint12.h jerror12.h \ + jdct12.h +jfdctint.o: jfdctint.c jinclude12.h jconfig12.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib12.h jmorecfg12.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint12.h jerror12.h \ + jdct12.h +jidctflt.o: jidctflt.c jinclude12.h jconfig12.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib12.h jmorecfg12.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint12.h jerror12.h \ + jdct12.h +jidctfst.o: jidctfst.c jinclude12.h jconfig12.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib12.h jmorecfg12.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint12.h jerror12.h \ + jdct12.h +jidctint.o: jidctint.c jinclude12.h jconfig12.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib12.h jmorecfg12.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint12.h jerror12.h \ + jdct12.h +jidctred.o: jidctred.c jinclude12.h jconfig12.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib12.h jmorecfg12.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint12.h jerror12.h \ + jdct12.h +jmemmgr.o: jmemmgr.c jinclude12.h jconfig12.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib12.h jmorecfg12.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint12.h jerror12.h \ + jmemsys12.h +jmemnobs.o: jmemnobs.c jinclude12.h jconfig12.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib12.h jmorecfg12.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint12.h jerror12.h \ + jmemsys12.h +jquant1.o: jquant1.c jinclude12.h jconfig12.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib12.h jmorecfg12.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint12.h jerror12.h +jquant2.o: jquant2.c jinclude12.h jconfig12.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib12.h jmorecfg12.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint12.h jerror12.h +jutils.o: jutils.c jinclude12.h jconfig12.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib12.h jmorecfg12.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint12.h jerror12.h diff --git a/dcmjpeg/libijg12/Makefile.in b/dcmjpeg/libijg12/Makefile.in new file mode 100644 index 00000000..3d07f014 --- /dev/null +++ b/dcmjpeg/libijg12/Makefile.in @@ -0,0 +1,59 @@ +# +# Makefile for dcmjpeg/libijg12 +# + +@SET_MAKE@ + +SHELL = /bin/sh +VPATH = @srcdir@:@top_srcdir@/include:@top_srcdir@/@configdir@/include +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +configdir = @top_srcdir@/@configdir@ + +include $(configdir)/@common_makefile@ + +ofstddir = $(top_srcdir)/../ofstd + +LOCALINCLUDES = -I$(ofstddir)/include +LOCALDEFS = -DWITH_ARITHMETIC_PATCH + +objs = jcomapi.o jcodec.o jutils.o jerror.o jmemmgr.o \ + jmemnobs.o jcapimin.o jcapistd.o jctrans.o jcparam.o \ + jdatadst.o jcinit.o jcmaster.o jcmarker.o jcmainct.o \ + jcprepct.o jclossls.o jclossy.o jccoefct.o jccolor.o \ + jcsample.o jchuff.o jcphuff.o jcshuff.o jclhuff.o \ + jcpred.o jcscale.o jcdiffct.o jcdctmgr.o jfdctfst.o \ + jfdctflt.o jfdctint.o jdapimin.o jdapistd.o jdtrans.o \ + jdatasrc.o jdmaster.o jdinput.o jdmarker.o jdlossls.o \ + jdlossy.o jdhuff.o jdlhuff.o jdphuff.o jdshuff.o \ + jdpred.o jdscale.o jddiffct.o jdmainct.o jdcoefct.o \ + jdpostct.o jddctmgr.o jidctfst.o jidctflt.o jidctint.o \ + jidctred.o jdsample.o jdcolor.o jquant1.o jquant2.o \ + jdmerge.o jcarith.o jdarith.o jaricom.o +library = libijg12.$(LIBEXT) + + +all: $(library) + +install: $(library) + $(configdir)/mkinstalldirs $(DESTDIR)$(libdir) + $(INSTALL_DATA) $(library) $(DESTDIR)$(libdir)/$(library) + $(RANLIB) $(DESTDIR)$(libdir)/$(library) + + +$(library): $(objs) + $(AR) $(ARFLAGS) $@ $(objs) + $(RANLIB) $@ + + +clean: + rm -f $(objs) $(library) $(TRASH) + +distclean: + rm -f $(objs) $(library) $(DISTTRASH) + + +dependencies: + $(CXX) -MM $(defines) $(includes) $(CPPFLAGS) $(CXXFLAGS) *.c > $(DEP) + +include $(DEP) diff --git a/dcmjpeg/libijg12/jaricom.c b/dcmjpeg/libijg12/jaricom.c new file mode 100644 index 00000000..207e692f --- /dev/null +++ b/dcmjpeg/libijg12/jaricom.c @@ -0,0 +1,15 @@ +/* + * jaricom.c + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file holds place for arithmetic entropy codec tables. + */ + +#define JPEG_INTERNALS +#include "jinclude12.h" +#include "jpeglib12.h" + +IJG_INT32 jaritab[1]; /* dummy table */ diff --git a/dcmjpeg/libijg12/jcapimin.c b/dcmjpeg/libijg12/jcapimin.c new file mode 100644 index 00000000..23441a92 --- /dev/null +++ b/dcmjpeg/libijg12/jcapimin.c @@ -0,0 +1,280 @@ +/* + * jcapimin.c + * + * Copyright (C) 1994-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains application interface code for the compression half + * of the JPEG library. These are the "minimum" API routines that may be + * needed in either the normal full-compression case or the transcoding-only + * case. + * + * Most of the routines intended to be called directly by an application + * are in this file or in jcapistd.c. But also see jcparam.c for + * parameter-setup helper routines, jcomapi.c for routines shared by + * compression and decompression, and jctrans.c for the transcoding case. + */ + +#define JPEG_INTERNALS +#include "jinclude12.h" +#include "jpeglib12.h" + + +/* + * Initialization of a JPEG compression object. + * The error manager must already be set up (in case memory manager fails). + */ + +GLOBAL(void) +jpeg_CreateCompress (j_compress_ptr cinfo, int version, size_t structsize) +{ + int i; + + /* Guard against version mismatches between library and caller. */ + cinfo->mem = NULL; /* so jpeg_destroy knows mem mgr not called */ + if (version != JPEG_LIB_VERSION) + ERREXIT2(cinfo, JERR_BAD_LIB_VERSION, JPEG_LIB_VERSION, version); + if (structsize != SIZEOF(struct jpeg_compress_struct)) + ERREXIT2(cinfo, JERR_BAD_STRUCT_SIZE, + (int) SIZEOF(struct jpeg_compress_struct), (int) structsize); + + /* For debugging purposes, we zero the whole master structure. + * But the application has already set the err pointer, and may have set + * client_data, so we have to save and restore those fields. + * Note: if application hasn't set client_data, tools like Purify may + * complain here. + */ + { + struct jpeg_error_mgr * err = cinfo->err; + void * client_data = cinfo->client_data; /* ignore Purify complaint here */ + MEMZERO(cinfo, SIZEOF(struct jpeg_compress_struct)); + cinfo->err = err; + cinfo->client_data = client_data; + } + cinfo->is_decompressor = FALSE; + + /* Initialize a memory manager instance for this object */ + jinit_memory_mgr((j_common_ptr) cinfo); + + /* Zero out pointers to permanent structures. */ + cinfo->progress = NULL; + cinfo->dest = NULL; + + cinfo->comp_info = NULL; + + for (i = 0; i < NUM_QUANT_TBLS; i++) + cinfo->quant_tbl_ptrs[i] = NULL; + + for (i = 0; i < NUM_HUFF_TBLS; i++) { + cinfo->dc_huff_tbl_ptrs[i] = NULL; + cinfo->ac_huff_tbl_ptrs[i] = NULL; + } + + cinfo->script_space = NULL; + + cinfo->input_gamma = 1.0; /* in case application forgets */ + + /* OK, I'm ready */ + cinfo->global_state = CSTATE_START; +} + + +/* + * Destruction of a JPEG compression object + */ + +GLOBAL(void) +jpeg_destroy_compress (j_compress_ptr cinfo) +{ + jpeg_destroy((j_common_ptr) cinfo); /* use common routine */ +} + + +/* + * Abort processing of a JPEG compression operation, + * but don't destroy the object itself. + */ + +GLOBAL(void) +jpeg_abort_compress (j_compress_ptr cinfo) +{ + jpeg_abort((j_common_ptr) cinfo); /* use common routine */ +} + + +/* + * Forcibly suppress or un-suppress all quantization and Huffman tables. + * Marks all currently defined tables as already written (if suppress) + * or not written (if !suppress). This will control whether they get emitted + * by a subsequent jpeg_start_compress call. + * + * This routine is exported for use by applications that want to produce + * abbreviated JPEG datastreams. It logically belongs in jcparam.c, but + * since it is called by jpeg_start_compress, we put it here --- otherwise + * jcparam.o would be linked whether the application used it or not. + */ + +GLOBAL(void) +jpeg_suppress_tables (j_compress_ptr cinfo, boolean suppress) +{ + int i; + JQUANT_TBL * qtbl; + JHUFF_TBL * htbl; + + for (i = 0; i < NUM_QUANT_TBLS; i++) { + if ((qtbl = cinfo->quant_tbl_ptrs[i]) != NULL) + qtbl->sent_table = suppress; + } + + for (i = 0; i < NUM_HUFF_TBLS; i++) { + if ((htbl = cinfo->dc_huff_tbl_ptrs[i]) != NULL) + htbl->sent_table = suppress; + if ((htbl = cinfo->ac_huff_tbl_ptrs[i]) != NULL) + htbl->sent_table = suppress; + } +} + + +/* + * Finish JPEG compression. + * + * If a multipass operating mode was selected, this may do a great deal of + * work including most of the actual output. + */ + +GLOBAL(void) +jpeg_finish_compress (j_compress_ptr cinfo) +{ + JDIMENSION iMCU_row; + + if (cinfo->global_state == CSTATE_SCANNING || + cinfo->global_state == CSTATE_RAW_OK) { + /* Terminate first pass */ + if (cinfo->next_scanline < cinfo->image_height) + ERREXIT(cinfo, JERR_TOO_LITTLE_DATA); + (*cinfo->master->finish_pass) (cinfo); + } else if (cinfo->global_state != CSTATE_WRCOEFS) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + /* Perform any remaining passes */ + while (! cinfo->master->is_last_pass) { + (*cinfo->master->prepare_for_pass) (cinfo); + for (iMCU_row = 0; iMCU_row < cinfo->total_iMCU_rows; iMCU_row++) { + if (cinfo->progress != NULL) { + cinfo->progress->pass_counter = (long) iMCU_row; + cinfo->progress->pass_limit = (long) cinfo->total_iMCU_rows; + (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); + } + /* We bypass the main controller and invoke coef controller directly; + * all work is being done from the coefficient buffer. + */ + if (! (*cinfo->codec->compress_data) (cinfo, (JSAMPIMAGE) NULL)) + ERREXIT(cinfo, JERR_CANT_SUSPEND); + } + (*cinfo->master->finish_pass) (cinfo); + } + /* Write EOI, do final cleanup */ + (*cinfo->marker->write_file_trailer) (cinfo); + (*cinfo->dest->term_destination) (cinfo); + /* We can use jpeg_abort to release memory and reset global_state */ + jpeg_abort((j_common_ptr) cinfo); +} + + +/* + * Write a special marker. + * This is only recommended for writing COM or APPn markers. + * Must be called after jpeg_start_compress() and before + * first call to jpeg_write_scanlines() or jpeg_write_raw_data(). + */ + +GLOBAL(void) +jpeg_write_marker (j_compress_ptr cinfo, int marker, + const JOCTET *dataptr, unsigned int datalen) +{ + JMETHOD(void, write_marker_byte, (j_compress_ptr info, int val)); + + if (cinfo->next_scanline != 0 || + (cinfo->global_state != CSTATE_SCANNING && + cinfo->global_state != CSTATE_RAW_OK && + cinfo->global_state != CSTATE_WRCOEFS)) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + + (*cinfo->marker->write_marker_header) (cinfo, marker, datalen); + write_marker_byte = cinfo->marker->write_marker_byte; /* copy for speed */ + while (datalen--) { + (*write_marker_byte) (cinfo, *dataptr); + dataptr++; + } +} + +/* Same, but piecemeal. */ + +GLOBAL(void) +jpeg_write_m_header (j_compress_ptr cinfo, int marker, unsigned int datalen) +{ + if (cinfo->next_scanline != 0 || + (cinfo->global_state != CSTATE_SCANNING && + cinfo->global_state != CSTATE_RAW_OK && + cinfo->global_state != CSTATE_WRCOEFS)) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + + (*cinfo->marker->write_marker_header) (cinfo, marker, datalen); +} + +GLOBAL(void) +jpeg_write_m_byte (j_compress_ptr cinfo, int val) +{ + (*cinfo->marker->write_marker_byte) (cinfo, val); +} + + +/* + * Alternate compression function: just write an abbreviated table file. + * Before calling this, all parameters and a data destination must be set up. + * + * To produce a pair of files containing abbreviated tables and abbreviated + * image data, one would proceed as follows: + * + * initialize JPEG object + * set JPEG parameters + * set destination to table file + * jpeg_write_tables(cinfo); + * set destination to image file + * jpeg_start_compress(cinfo, FALSE); + * write data... + * jpeg_finish_compress(cinfo); + * + * jpeg_write_tables has the side effect of marking all tables written + * (same as jpeg_suppress_tables(..., TRUE)). Thus a subsequent start_compress + * will not re-emit the tables unless it is passed write_all_tables=TRUE. + */ + +GLOBAL(void) +jpeg_write_tables (j_compress_ptr cinfo) +{ + if (cinfo->global_state != CSTATE_START) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + + /* (Re)initialize error mgr and destination modules */ + (*cinfo->err->reset_error_mgr) ((j_common_ptr) cinfo); + (*cinfo->dest->init_destination) (cinfo); + /* Initialize the marker writer ... bit of a crock to do it here. */ + jinit_marker_writer(cinfo); + /* Write them tables! */ + (*cinfo->marker->write_tables_only) (cinfo); + /* And clean up. */ + (*cinfo->dest->term_destination) (cinfo); + /* + * In library releases up through v6a, we called jpeg_abort() here to free + * any working memory allocated by the destination manager and marker + * writer. Some applications had a problem with that: they allocated space + * of their own from the library memory manager, and didn't want it to go + * away during write_tables. So now we do nothing. This will cause a + * memory leak if an app calls write_tables repeatedly without doing a full + * compression cycle or otherwise resetting the JPEG object. However, that + * seems less bad than unexpectedly freeing memory in the normal case. + * An app that prefers the old behavior can call jpeg_abort for itself after + * each call to jpeg_write_tables(). + */ +} diff --git a/dcmjpeg/libijg12/jcapistd.c b/dcmjpeg/libijg12/jcapistd.c new file mode 100644 index 00000000..d47c06d4 --- /dev/null +++ b/dcmjpeg/libijg12/jcapistd.c @@ -0,0 +1,161 @@ +/* + * jcapistd.c + * + * Copyright (C) 1994-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains application interface code for the compression half + * of the JPEG library. These are the "standard" API routines that are + * used in the normal full-compression case. They are not used by a + * transcoding-only application. Note that if an application links in + * jpeg_start_compress, it will end up linking in the entire compressor. + * We thus must separate this file from jcapimin.c to avoid linking the + * whole compression library into a transcoder. + */ + +#define JPEG_INTERNALS +#include "jinclude12.h" +#include "jpeglib12.h" + + +/* + * Compression initialization. + * Before calling this, all parameters and a data destination must be set up. + * + * We require a write_all_tables parameter as a failsafe check when writing + * multiple datastreams from the same compression object. Since prior runs + * will have left all the tables marked sent_table=TRUE, a subsequent run + * would emit an abbreviated stream (no tables) by default. This may be what + * is wanted, but for safety's sake it should not be the default behavior: + * programmers should have to make a deliberate choice to emit abbreviated + * images. Therefore the documentation and examples should encourage people + * to pass write_all_tables=TRUE; then it will take active thought to do the + * wrong thing. + */ + +GLOBAL(void) +jpeg_start_compress (j_compress_ptr cinfo, boolean write_all_tables) +{ + if (cinfo->global_state != CSTATE_START) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + + if (write_all_tables) + jpeg_suppress_tables(cinfo, FALSE); /* mark all tables to be written */ + + /* (Re)initialize error mgr and destination modules */ + (*cinfo->err->reset_error_mgr) ((j_common_ptr) cinfo); + (*cinfo->dest->init_destination) (cinfo); + /* Perform master selection of active modules */ + jinit_compress_master(cinfo); + /* Set up for the first pass */ + (*cinfo->master->prepare_for_pass) (cinfo); + /* Ready for application to drive first pass through jpeg_write_scanlines + * or jpeg_write_raw_data. + */ + cinfo->next_scanline = 0; + cinfo->global_state = (cinfo->raw_data_in ? CSTATE_RAW_OK : CSTATE_SCANNING); +} + + +/* + * Write some scanlines of data to the JPEG compressor. + * + * The return value will be the number of lines actually written. + * This should be less than the supplied num_lines only in case that + * the data destination module has requested suspension of the compressor, + * or if more than image_height scanlines are passed in. + * + * Note: we warn about excess calls to jpeg_write_scanlines() since + * this likely signals an application programmer error. However, + * excess scanlines passed in the last valid call are *silently* ignored, + * so that the application need not adjust num_lines for end-of-image + * when using a multiple-scanline buffer. + */ + +GLOBAL(JDIMENSION) +jpeg_write_scanlines (j_compress_ptr cinfo, JSAMPARRAY scanlines, + JDIMENSION num_lines) +{ + JDIMENSION row_ctr, rows_left; + + if (cinfo->global_state != CSTATE_SCANNING) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + if (cinfo->next_scanline >= cinfo->image_height) + WARNMS(cinfo, JWRN_TOO_MUCH_DATA); + + /* Call progress monitor hook if present */ + if (cinfo->progress != NULL) { + cinfo->progress->pass_counter = (long) cinfo->next_scanline; + cinfo->progress->pass_limit = (long) cinfo->image_height; + (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); + } + + /* Give master control module another chance if this is first call to + * jpeg_write_scanlines. This lets output of the frame/scan headers be + * delayed so that application can write COM, etc, markers between + * jpeg_start_compress and jpeg_write_scanlines. + */ + if (cinfo->master->call_pass_startup) + (*cinfo->master->pass_startup) (cinfo); + + /* Ignore any extra scanlines at bottom of image. */ + rows_left = cinfo->image_height - cinfo->next_scanline; + if (num_lines > rows_left) + num_lines = rows_left; + + row_ctr = 0; + (*cinfo->main->process_data) (cinfo, scanlines, &row_ctr, num_lines); + cinfo->next_scanline += row_ctr; + return row_ctr; +} + + +/* + * Alternate entry point to write raw data. + * Processes exactly one iMCU row per call, unless suspended. + */ + +GLOBAL(JDIMENSION) +jpeg_write_raw_data (j_compress_ptr cinfo, JSAMPIMAGE data, + JDIMENSION num_lines) +{ + JDIMENSION lines_per_iMCU_row; + + if (cinfo->global_state != CSTATE_RAW_OK) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + if (cinfo->next_scanline >= cinfo->image_height) { + WARNMS(cinfo, JWRN_TOO_MUCH_DATA); + return 0; + } + + /* Call progress monitor hook if present */ + if (cinfo->progress != NULL) { + cinfo->progress->pass_counter = (long) cinfo->next_scanline; + cinfo->progress->pass_limit = (long) cinfo->image_height; + (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); + } + + /* Give master control module another chance if this is first call to + * jpeg_write_raw_data. This lets output of the frame/scan headers be + * delayed so that application can write COM, etc, markers between + * jpeg_start_compress and jpeg_write_raw_data. + */ + if (cinfo->master->call_pass_startup) + (*cinfo->master->pass_startup) (cinfo); + + /* Verify that at least one iMCU row has been passed. */ + lines_per_iMCU_row = (JDIMENSION)(cinfo->max_v_samp_factor * cinfo->data_unit); + if (num_lines < lines_per_iMCU_row) + ERREXIT(cinfo, JERR_BUFFER_SIZE); + + /* Directly compress the row. */ + if (! (*cinfo->codec->compress_data) (cinfo, data)) { + /* If compressor did not consume the whole row, suspend processing. */ + return 0; + } + + /* OK, we processed one iMCU row. */ + cinfo->next_scanline += lines_per_iMCU_row; + return lines_per_iMCU_row; +} diff --git a/dcmjpeg/libijg12/jcarith.c b/dcmjpeg/libijg12/jcarith.c new file mode 100644 index 00000000..f5283dbf --- /dev/null +++ b/dcmjpeg/libijg12/jcarith.c @@ -0,0 +1,26 @@ +/* + * jcarith.c + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file holds place for arithmetic entropy encoding routines. + */ + +#define JPEG_INTERNALS +#include "jinclude12.h" +#include "jpeglib12.h" + + +/* + * Module initialization routine for arithmetic entropy encoding. + */ +GLOBAL(void) +jinit_arith_encoder (j_compress_ptr cinfo); + +GLOBAL(void) +jinit_arith_encoder (j_compress_ptr cinfo) +{ + ERREXIT(cinfo, JERR_ARITH_NOTIMPL); +} diff --git a/dcmjpeg/libijg12/jccoefct.c b/dcmjpeg/libijg12/jccoefct.c new file mode 100644 index 00000000..c07be212 --- /dev/null +++ b/dcmjpeg/libijg12/jccoefct.c @@ -0,0 +1,454 @@ +/* + * jccoefct.c + * + * Copyright (C) 1994-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains the coefficient buffer controller for compression. + * This controller is the top level of the JPEG compressor proper. + * The coefficient buffer lies between forward-DCT and entropy encoding steps. + */ + +#define JPEG_INTERNALS +#include "jinclude12.h" +#include "jpeglib12.h" +#include "jlossy12.h" /* Private declarations for lossy codec */ + + +/* We use a full-image coefficient buffer when doing Huffman optimization, + * and also for writing multiple-scan JPEG files. In all cases, the DCT + * step is run during the first pass, and subsequent passes need only read + * the buffered coefficients. + */ +#ifdef ENTROPY_OPT_SUPPORTED +#define FULL_COEF_BUFFER_SUPPORTED +#else +#ifdef C_MULTISCAN_FILES_SUPPORTED +#define FULL_COEF_BUFFER_SUPPORTED +#endif +#endif + + +/* Private buffer controller object */ + +typedef struct { + JDIMENSION iMCU_row_num; /* iMCU row # within image */ + JDIMENSION mcu_ctr; /* counts MCUs processed in current row */ + int MCU_vert_offset; /* counts MCU rows within iMCU row */ + int MCU_rows_per_iMCU_row; /* number of such rows needed */ + + /* For single-pass compression, it's sufficient to buffer just one MCU + * (although this may prove a bit slow in practice). We allocate a + * workspace of C_MAX_DATA_UNITS_IN_MCU coefficient blocks, and reuse it for + * each MCU constructed and sent. (On 80x86, the workspace is FAR even + * though it's not really very big; this is to keep the module interfaces + * unchanged when a large coefficient buffer is necessary.) + * In multi-pass modes, this array points to the current MCU's blocks + * within the virtual arrays. + */ + JBLOCKROW MCU_buffer[C_MAX_DATA_UNITS_IN_MCU]; + + /* In multi-pass modes, we need a virtual block array for each component. */ + jvirt_barray_ptr whole_image[MAX_COMPONENTS]; +} c_coef_controller; + +typedef c_coef_controller * c_coef_ptr; + + +/* Forward declarations */ +METHODDEF(boolean) compress_data + JPP((j_compress_ptr cinfo, JSAMPIMAGE input_buf)); +#ifdef FULL_COEF_BUFFER_SUPPORTED +METHODDEF(boolean) compress_first_pass + JPP((j_compress_ptr cinfo, JSAMPIMAGE input_buf)); +METHODDEF(boolean) compress_output + JPP((j_compress_ptr cinfo, JSAMPIMAGE input_buf)); +#endif + + +LOCAL(void) +start_iMCU_row (j_compress_ptr cinfo) +/* Reset within-iMCU-row counters for a new row */ +{ + j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; + c_coef_ptr coef = (c_coef_ptr) lossyc->coef_private; + + /* In an interleaved scan, an MCU row is the same as an iMCU row. + * In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows. + * But at the bottom of the image, process only what's left. + */ + if (cinfo->comps_in_scan > 1) { + coef->MCU_rows_per_iMCU_row = 1; + } else { + if (coef->iMCU_row_num < (cinfo->total_iMCU_rows-1)) + coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->v_samp_factor; + else + coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->last_row_height; + } + + coef->mcu_ctr = 0; + coef->MCU_vert_offset = 0; +} + + +/* + * Initialize for a processing pass. + */ + +METHODDEF(void) +start_pass_coef (j_compress_ptr cinfo, J_BUF_MODE pass_mode) +{ + j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; + c_coef_ptr coef = (c_coef_ptr) lossyc->coef_private; + + coef->iMCU_row_num = 0; + start_iMCU_row(cinfo); + + switch (pass_mode) { + case JBUF_PASS_THRU: + if (coef->whole_image[0] != NULL) + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + lossyc->pub.compress_data = compress_data; + break; +#ifdef FULL_COEF_BUFFER_SUPPORTED + case JBUF_SAVE_AND_PASS: + if (coef->whole_image[0] == NULL) + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + lossyc->pub.compress_data = compress_first_pass; + break; + case JBUF_CRANK_DEST: + if (coef->whole_image[0] == NULL) + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + lossyc->pub.compress_data = compress_output; + break; +#endif + default: + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + break; + } +} + + +/* + * Process some data in the single-pass case. + * We process the equivalent of one fully interleaved MCU row ("iMCU" row) + * per call, ie, v_samp_factor block rows for each component in the image. + * Returns TRUE if the iMCU row is completed, FALSE if suspended. + * + * NB: input_buf contains a plane for each component in image, + * which we index according to the component's SOF position. + */ + +METHODDEF(boolean) +compress_data (j_compress_ptr cinfo, JSAMPIMAGE input_buf) +{ + j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; + c_coef_ptr coef = (c_coef_ptr) lossyc->coef_private; + JDIMENSION MCU_col_num; /* index of current MCU within row */ + JDIMENSION last_MCU_col = cinfo->MCUs_per_row - 1; + JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; + int blkn, bi, ci, yindex, yoffset, blockcnt; + JDIMENSION ypos, xpos; + jpeg_component_info *compptr; + + /* Loop to write as much as one whole iMCU row */ + for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row; + yoffset++) { + for (MCU_col_num = coef->mcu_ctr; MCU_col_num <= last_MCU_col; + MCU_col_num++) { + /* Determine where data comes from in input_buf and do the DCT thing. + * Each call on forward_DCT processes a horizontal row of DCT blocks + * as wide as an MCU; we rely on having allocated the MCU_buffer[] blocks + * sequentially. Dummy blocks at the right or bottom edge are filled in + * specially. The data in them does not matter for image reconstruction, + * so we fill them with values that will encode to the smallest amount of + * data, viz: all zeroes in the AC entries, DC entries equal to previous + * block's DC value. (Thanks to Thomas Kinsman for this idea.) + */ + blkn = 0; + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + blockcnt = (MCU_col_num < last_MCU_col) ? compptr->MCU_width + : compptr->last_col_width; + xpos = MCU_col_num * (JDIMENSION)compptr->MCU_sample_width; + ypos = (JDIMENSION)(yoffset * DCTSIZE); /* ypos == (yoffset+yindex) * DCTSIZE */ + for (yindex = 0; yindex < compptr->MCU_height; yindex++) { + if (coef->iMCU_row_num < last_iMCU_row || + yoffset+yindex < compptr->last_row_height) { + (*lossyc->fdct_forward_DCT) (cinfo, compptr, + input_buf[compptr->component_index], + coef->MCU_buffer[blkn], + ypos, xpos, (JDIMENSION) blockcnt); + if (blockcnt < compptr->MCU_width) { + /* Create some dummy blocks at the right edge of the image. */ + jzero_far((void FAR *) coef->MCU_buffer[blkn + blockcnt], + (size_t)(compptr->MCU_width - blockcnt) * SIZEOF(JBLOCK)); + for (bi = blockcnt; bi < compptr->MCU_width; bi++) { + coef->MCU_buffer[blkn+bi][0][0] = coef->MCU_buffer[blkn+bi-1][0][0]; + } + } + } else { + /* Create a row of dummy blocks at the bottom of the image. */ + jzero_far((void FAR *) coef->MCU_buffer[blkn], + (size_t)compptr->MCU_width * SIZEOF(JBLOCK)); + for (bi = 0; bi < compptr->MCU_width; bi++) { + coef->MCU_buffer[blkn+bi][0][0] = coef->MCU_buffer[blkn-1][0][0]; + } + } + blkn += compptr->MCU_width; + ypos += DCTSIZE; + } + } + /* Try to write the MCU. In event of a suspension failure, we will + * re-DCT the MCU on restart (a bit inefficient, could be fixed...) + */ + if (! (*lossyc->entropy_encode_mcu) (cinfo, coef->MCU_buffer)) { + /* Suspension forced; update state counters and exit */ + coef->MCU_vert_offset = yoffset; + coef->mcu_ctr = MCU_col_num; + return FALSE; + } + } + /* Completed an MCU row, but perhaps not an iMCU row */ + coef->mcu_ctr = 0; + } + /* Completed the iMCU row, advance counters for next one */ + coef->iMCU_row_num++; + start_iMCU_row(cinfo); + return TRUE; +} + + +#ifdef FULL_COEF_BUFFER_SUPPORTED + +/* + * Process some data in the first pass of a multi-pass case. + * We process the equivalent of one fully interleaved MCU row ("iMCU" row) + * per call, ie, v_samp_factor block rows for each component in the image. + * This amount of data is read from the source buffer, DCT'd and quantized, + * and saved into the virtual arrays. We also generate suitable dummy blocks + * as needed at the right and lower edges. (The dummy blocks are constructed + * in the virtual arrays, which have been padded appropriately.) This makes + * it possible for subsequent passes not to worry about real vs. dummy blocks. + * + * We must also emit the data to the entropy encoder. This is conveniently + * done by calling compress_output() after we've loaded the current strip + * of the virtual arrays. + * + * NB: input_buf contains a plane for each component in image. All + * components are DCT'd and loaded into the virtual arrays in this pass. + * However, it may be that only a subset of the components are emitted to + * the entropy encoder during this first pass; be careful about looking + * at the scan-dependent variables (MCU dimensions, etc). + */ + +METHODDEF(boolean) +compress_first_pass (j_compress_ptr cinfo, JSAMPIMAGE input_buf) +{ + j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; + c_coef_ptr coef = (c_coef_ptr) lossyc->coef_private; + JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; + JDIMENSION blocks_across, MCUs_across, MCUindex; + int bi, ci, h_samp_factor, block_row, block_rows, ndummy; + JCOEF lastDC; + jpeg_component_info *compptr; + JBLOCKARRAY buffer; + JBLOCKROW thisblockrow, lastblockrow; + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + /* Align the virtual buffer for this component. */ + buffer = (*cinfo->mem->access_virt_barray) + ((j_common_ptr) cinfo, coef->whole_image[ci], + coef->iMCU_row_num * (JDIMENSION)compptr->v_samp_factor, + (JDIMENSION)compptr->v_samp_factor, TRUE); + /* Count non-dummy DCT block rows in this iMCU row. */ + if (coef->iMCU_row_num < last_iMCU_row) + block_rows = compptr->v_samp_factor; + else { + /* NB: can't use last_row_height here, since may not be set! */ + block_rows = (int)compptr->height_in_data_units % compptr->v_samp_factor; + if (block_rows == 0) block_rows = compptr->v_samp_factor; + } + blocks_across = (JDIMENSION)compptr->width_in_data_units; + h_samp_factor = compptr->h_samp_factor; + /* Count number of dummy blocks to be added at the right margin. */ + ndummy = (int)blocks_across % h_samp_factor; + if (ndummy > 0) + ndummy = h_samp_factor - ndummy; + /* Perform DCT for all non-dummy blocks in this iMCU row. Each call + * on forward_DCT processes a complete horizontal row of DCT blocks. + */ + for (block_row = 0; block_row < block_rows; block_row++) { + thisblockrow = buffer[block_row]; + (*lossyc->fdct_forward_DCT) (cinfo, compptr, + input_buf[ci], thisblockrow, + (JDIMENSION) (block_row * DCTSIZE), + (JDIMENSION) 0, blocks_across); + if (ndummy > 0) { + /* Create dummy blocks at the right edge of the image. */ + thisblockrow += blocks_across; /* => first dummy block */ + jzero_far((void FAR *) thisblockrow, (size_t)ndummy * SIZEOF(JBLOCK)); + lastDC = thisblockrow[-1][0]; + for (bi = 0; bi < ndummy; bi++) { + thisblockrow[bi][0] = lastDC; + } + } + } + /* If at end of image, create dummy block rows as needed. + * The tricky part here is that within each MCU, we want the DC values + * of the dummy blocks to match the last real block's DC value. + * This squeezes a few more bytes out of the resulting file... + */ + if (coef->iMCU_row_num == last_iMCU_row) { + blocks_across += (JDIMENSION)ndummy; /* include lower right corner */ + MCUs_across = blocks_across / (JDIMENSION)h_samp_factor; + for (block_row = block_rows; block_row < compptr->v_samp_factor; + block_row++) { + thisblockrow = buffer[block_row]; + lastblockrow = buffer[block_row-1]; + jzero_far((void FAR *) thisblockrow, + (size_t) (blocks_across * SIZEOF(JBLOCK))); + for (MCUindex = 0; MCUindex < MCUs_across; MCUindex++) { + lastDC = lastblockrow[h_samp_factor-1][0]; + for (bi = 0; bi < h_samp_factor; bi++) { + thisblockrow[bi][0] = lastDC; + } + thisblockrow += h_samp_factor; /* advance to next MCU in row */ + lastblockrow += h_samp_factor; + } + } + } + } + /* NB: compress_output will increment iMCU_row_num if successful. + * A suspension return will result in redoing all the work above next time. + */ + + /* Emit data to the entropy encoder, sharing code with subsequent passes */ + return compress_output(cinfo, input_buf); +} + + +/* + * Process some data in subsequent passes of a multi-pass case. + * We process the equivalent of one fully interleaved MCU row ("iMCU" row) + * per call, ie, v_samp_factor block rows for each component in the scan. + * The data is obtained from the virtual arrays and fed to the entropy coder. + * Returns TRUE if the iMCU row is completed, FALSE if suspended. + * + * NB: input_buf is ignored; it is likely to be a NULL pointer. + */ + +METHODDEF(boolean) +compress_output (j_compress_ptr cinfo, JSAMPIMAGE input_buf) +{ + j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; + c_coef_ptr coef = (c_coef_ptr) lossyc->coef_private; + JDIMENSION MCU_col_num; /* index of current MCU within row */ + int blkn, ci, xindex, yindex, yoffset; + JDIMENSION start_col; + JBLOCKARRAY buffer[MAX_COMPS_IN_SCAN]; + JBLOCKROW buffer_ptr; + jpeg_component_info *compptr; + + /* Align the virtual buffers for the components used in this scan. + * NB: during first pass, this is safe only because the buffers will + * already be aligned properly, so jmemmgr.c won't need to do any I/O. + */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + buffer[ci] = (*cinfo->mem->access_virt_barray) + ((j_common_ptr) cinfo, coef->whole_image[compptr->component_index], + coef->iMCU_row_num * (JDIMENSION)compptr->v_samp_factor, + (JDIMENSION)compptr->v_samp_factor, FALSE); + } + + /* Loop to process one whole iMCU row */ + for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row; + yoffset++) { + for (MCU_col_num = coef->mcu_ctr; MCU_col_num < cinfo->MCUs_per_row; + MCU_col_num++) { + /* Construct list of pointers to DCT blocks belonging to this MCU */ + blkn = 0; /* index of current DCT block within MCU */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + start_col = MCU_col_num * (JDIMENSION)compptr->MCU_width; + for (yindex = 0; yindex < compptr->MCU_height; yindex++) { + buffer_ptr = buffer[ci][yindex+yoffset] + start_col; + for (xindex = 0; xindex < compptr->MCU_width; xindex++) { + coef->MCU_buffer[blkn++] = buffer_ptr++; + } + } + } + /* Try to write the MCU. */ + if (! (*lossyc->entropy_encode_mcu) (cinfo, coef->MCU_buffer)) { + /* Suspension forced; update state counters and exit */ + coef->MCU_vert_offset = yoffset; + coef->mcu_ctr = MCU_col_num; + return FALSE; + } + } + /* Completed an MCU row, but perhaps not an iMCU row */ + coef->mcu_ctr = 0; + } + /* Completed the iMCU row, advance counters for next one */ + coef->iMCU_row_num++; + start_iMCU_row(cinfo); + return TRUE; +} + +#endif /* FULL_COEF_BUFFER_SUPPORTED */ + + +/* + * Initialize coefficient buffer controller. + */ + +GLOBAL(void) +jinit_c_coef_controller (j_compress_ptr cinfo, boolean need_full_buffer) +{ + j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; + c_coef_ptr coef; + + coef = (c_coef_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(c_coef_controller)); + lossyc->coef_private = (struct jpeg_c_coef_controller *) coef; + lossyc->coef_start_pass = start_pass_coef; + + /* Create the coefficient buffer. */ + if (need_full_buffer) { +#ifdef FULL_COEF_BUFFER_SUPPORTED + /* Allocate a full-image virtual array for each component, */ + /* padded to a multiple of samp_factor DCT blocks in each direction. */ + int ci; + jpeg_component_info *compptr; + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + coef->whole_image[ci] = (*cinfo->mem->request_virt_barray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE, + (JDIMENSION) jround_up((long) compptr->width_in_data_units, + (long) compptr->h_samp_factor), + (JDIMENSION) jround_up((long) compptr->height_in_data_units, + (long) compptr->v_samp_factor), + (JDIMENSION) compptr->v_samp_factor); + } +#else + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); +#endif + } else { + /* We only need a single-MCU buffer. */ + JBLOCKROW buffer; + int i; + + buffer = (JBLOCKROW) + (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE, + C_MAX_DATA_UNITS_IN_MCU * SIZEOF(JBLOCK)); + for (i = 0; i < C_MAX_DATA_UNITS_IN_MCU; i++) { + coef->MCU_buffer[i] = buffer + i; + } + coef->whole_image[0] = NULL; /* flag for no virtual arrays */ + } +} diff --git a/dcmjpeg/libijg12/jccolor.c b/dcmjpeg/libijg12/jccolor.c new file mode 100644 index 00000000..6e1f8496 --- /dev/null +++ b/dcmjpeg/libijg12/jccolor.c @@ -0,0 +1,459 @@ +/* + * jccolor.c + * + * Copyright (C) 1991-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains input colorspace conversion routines. + */ + +#define JPEG_INTERNALS +#include "jinclude12.h" +#include "jpeglib12.h" + + +/* Private subobject */ + +typedef struct { + struct jpeg_color_converter pub; /* public fields */ + + /* Private state for RGB->YCC conversion */ + IJG_INT32 * rgb_ycc_tab; /* => table for RGB to YCbCr conversion */ +} my_color_converter; + +typedef my_color_converter * my_cconvert_ptr; + + +/**************** RGB -> YCbCr conversion: most common case **************/ + +/* + * YCbCr is defined per CCIR 601-1, except that Cb and Cr are + * normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5. + * The conversion equations to be implemented are therefore + * Y = 0.29900 * R + 0.58700 * G + 0.11400 * B + * Cb = -0.16874 * R - 0.33126 * G + 0.50000 * B + CENTERJSAMPLE + * Cr = 0.50000 * R - 0.41869 * G - 0.08131 * B + CENTERJSAMPLE + * (These numbers are derived from TIFF 6.0 section 21, dated 3-June-92.) + * Note: older versions of the IJG code used a zero offset of MAXJSAMPLE/2, + * rather than CENTERJSAMPLE, for Cb and Cr. This gave equal positive and + * negative swings for Cb/Cr, but meant that grayscale values (Cb=Cr=0) + * were not represented exactly. Now we sacrifice exact representation of + * maximum red and maximum blue in order to get exact grayscales. + * + * To avoid floating-point arithmetic, we represent the fractional constants + * as integers scaled up by 2^16 (about 4 digits precision); we have to divide + * the products by 2^16, with appropriate rounding, to get the correct answer. + * + * For even more speed, we avoid doing any multiplications in the inner loop + * by precalculating the constants times R,G,B for all possible values. + * For 8-bit JSAMPLEs this is very reasonable (only 256 entries per table); + * for 12-bit samples it is still acceptable. It's not very reasonable for + * 16-bit samples, but if you want lossless storage you shouldn't be changing + * colorspace anyway. + * The CENTERJSAMPLE offsets and the rounding fudge-factor of 0.5 are included + * in the tables to save adding them separately in the inner loop. + */ + +#define SCALEBITS 16 /* speediest right-shift on some machines */ +#define CBCR_OFFSET ((IJG_INT32) CENTERJSAMPLE << SCALEBITS) +#define ONE_HALF ((IJG_INT32) 1 << (SCALEBITS-1)) +#define FIX(x) ((IJG_INT32) ((x) * (1L< Y section */ +#define G_Y_OFF (1*(MAXJSAMPLE+1)) /* offset to G => Y section */ +#define B_Y_OFF (2*(MAXJSAMPLE+1)) /* etc. */ +#define R_CB_OFF (3*(MAXJSAMPLE+1)) +#define G_CB_OFF (4*(MAXJSAMPLE+1)) +#define B_CB_OFF (5*(MAXJSAMPLE+1)) +#define R_CR_OFF B_CB_OFF /* B=>Cb, R=>Cr are the same */ +#define G_CR_OFF (6*(MAXJSAMPLE+1)) +#define B_CR_OFF (7*(MAXJSAMPLE+1)) +#define TABLE_SIZE (8*(MAXJSAMPLE+1)) + + +/* + * Initialize for RGB->YCC colorspace conversion. + */ + +METHODDEF(void) +rgb_ycc_start (j_compress_ptr cinfo) +{ + my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; + IJG_INT32 * rgb_ycc_tab; + IJG_INT32 i; + + /* Allocate and fill in the conversion tables. */ + cconvert->rgb_ycc_tab = rgb_ycc_tab = (IJG_INT32 *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (TABLE_SIZE * SIZEOF(IJG_INT32))); + + for (i = 0; i <= MAXJSAMPLE; i++) { + rgb_ycc_tab[i+R_Y_OFF] = FIX(0.29900) * i; + rgb_ycc_tab[i+G_Y_OFF] = FIX(0.58700) * i; + rgb_ycc_tab[i+B_Y_OFF] = FIX(0.11400) * i + ONE_HALF; + rgb_ycc_tab[i+R_CB_OFF] = (-FIX(0.16874)) * i; + rgb_ycc_tab[i+G_CB_OFF] = (-FIX(0.33126)) * i; + /* We use a rounding fudge-factor of 0.5-epsilon for Cb and Cr. + * This ensures that the maximum output will round to MAXJSAMPLE + * not MAXJSAMPLE+1, and thus that we don't have to range-limit. + */ + rgb_ycc_tab[i+B_CB_OFF] = FIX(0.50000) * i + CBCR_OFFSET + ONE_HALF-1; +/* B=>Cb and R=>Cr tables are the same + rgb_ycc_tab[i+R_CR_OFF] = FIX(0.50000) * i + CBCR_OFFSET + ONE_HALF-1; +*/ + rgb_ycc_tab[i+G_CR_OFF] = (-FIX(0.41869)) * i; + rgb_ycc_tab[i+B_CR_OFF] = (-FIX(0.08131)) * i; + } +} + + +/* + * Convert some rows of samples to the JPEG colorspace. + * + * Note that we change from the application's interleaved-pixel format + * to our internal noninterleaved, one-plane-per-component format. + * The input buffer is therefore three times as wide as the output buffer. + * + * A starting row offset is provided only for the output buffer. The caller + * can easily adjust the passed input_buf value to accommodate any row + * offset required on that side. + */ + +METHODDEF(void) +rgb_ycc_convert (j_compress_ptr cinfo, + JSAMPARRAY input_buf, JSAMPIMAGE output_buf, + JDIMENSION output_row, int num_rows) +{ + my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; + register int r, g, b; + register IJG_INT32 * ctab = cconvert->rgb_ycc_tab; + register JSAMPROW inptr; + register JSAMPROW outptr0, outptr1, outptr2; + register JDIMENSION col; + JDIMENSION num_cols = cinfo->image_width; + + while (--num_rows >= 0) { + inptr = *input_buf++; + outptr0 = output_buf[0][output_row]; + outptr1 = output_buf[1][output_row]; + outptr2 = output_buf[2][output_row]; + output_row++; + for (col = 0; col < num_cols; col++) { + r = GETJSAMPLE(inptr[RGB_RED]); + g = GETJSAMPLE(inptr[RGB_GREEN]); + b = GETJSAMPLE(inptr[RGB_BLUE]); + inptr += RGB_PIXELSIZE; + /* If the inputs are 0..MAXJSAMPLE, the outputs of these equations + * must be too; we do not need an explicit range-limiting operation. + * Hence the value being shifted is never negative, and we don't + * need the general RIGHT_SHIFT macro. + */ + /* Y */ + outptr0[col] = (JSAMPLE) + ((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF]) + >> SCALEBITS); + /* Cb */ + outptr1[col] = (JSAMPLE) + ((ctab[r+R_CB_OFF] + ctab[g+G_CB_OFF] + ctab[b+B_CB_OFF]) + >> SCALEBITS); + /* Cr */ + outptr2[col] = (JSAMPLE) + ((ctab[r+R_CR_OFF] + ctab[g+G_CR_OFF] + ctab[b+B_CR_OFF]) + >> SCALEBITS); + } + } +} + + +/**************** Cases other than RGB -> YCbCr **************/ + + +/* + * Convert some rows of samples to the JPEG colorspace. + * This version handles RGB->grayscale conversion, which is the same + * as the RGB->Y portion of RGB->YCbCr. + * We assume rgb_ycc_start has been called (we only use the Y tables). + */ + +METHODDEF(void) +rgb_gray_convert (j_compress_ptr cinfo, + JSAMPARRAY input_buf, JSAMPIMAGE output_buf, + JDIMENSION output_row, int num_rows) +{ + my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; + register int r, g, b; + register IJG_INT32 * ctab = cconvert->rgb_ycc_tab; + register JSAMPROW inptr; + register JSAMPROW outptr; + register JDIMENSION col; + JDIMENSION num_cols = cinfo->image_width; + + while (--num_rows >= 0) { + inptr = *input_buf++; + outptr = output_buf[0][output_row]; + output_row++; + for (col = 0; col < num_cols; col++) { + r = GETJSAMPLE(inptr[RGB_RED]); + g = GETJSAMPLE(inptr[RGB_GREEN]); + b = GETJSAMPLE(inptr[RGB_BLUE]); + inptr += RGB_PIXELSIZE; + /* Y */ + outptr[col] = (JSAMPLE) + ((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF]) + >> SCALEBITS); + } + } +} + + +/* + * Convert some rows of samples to the JPEG colorspace. + * This version handles Adobe-style CMYK->YCCK conversion, + * where we convert R=1-C, G=1-M, and B=1-Y to YCbCr using the same + * conversion as above, while passing K (black) unchanged. + * We assume rgb_ycc_start has been called. + */ + +METHODDEF(void) +cmyk_ycck_convert (j_compress_ptr cinfo, + JSAMPARRAY input_buf, JSAMPIMAGE output_buf, + JDIMENSION output_row, int num_rows) +{ + my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; + register int r, g, b; + register IJG_INT32 * ctab = cconvert->rgb_ycc_tab; + register JSAMPROW inptr; + register JSAMPROW outptr0, outptr1, outptr2, outptr3; + register JDIMENSION col; + JDIMENSION num_cols = cinfo->image_width; + + while (--num_rows >= 0) { + inptr = *input_buf++; + outptr0 = output_buf[0][output_row]; + outptr1 = output_buf[1][output_row]; + outptr2 = output_buf[2][output_row]; + outptr3 = output_buf[3][output_row]; + output_row++; + for (col = 0; col < num_cols; col++) { + r = MAXJSAMPLE - GETJSAMPLE(inptr[0]); + g = MAXJSAMPLE - GETJSAMPLE(inptr[1]); + b = MAXJSAMPLE - GETJSAMPLE(inptr[2]); + /* K passes through as-is */ + outptr3[col] = inptr[3]; /* don't need GETJSAMPLE here */ + inptr += 4; + /* If the inputs are 0..MAXJSAMPLE, the outputs of these equations + * must be too; we do not need an explicit range-limiting operation. + * Hence the value being shifted is never negative, and we don't + * need the general RIGHT_SHIFT macro. + */ + /* Y */ + outptr0[col] = (JSAMPLE) + ((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF]) + >> SCALEBITS); + /* Cb */ + outptr1[col] = (JSAMPLE) + ((ctab[r+R_CB_OFF] + ctab[g+G_CB_OFF] + ctab[b+B_CB_OFF]) + >> SCALEBITS); + /* Cr */ + outptr2[col] = (JSAMPLE) + ((ctab[r+R_CR_OFF] + ctab[g+G_CR_OFF] + ctab[b+B_CR_OFF]) + >> SCALEBITS); + } + } +} + + +/* + * Convert some rows of samples to the JPEG colorspace. + * This version handles grayscale output with no conversion. + * The source can be either plain grayscale or YCbCr (since Y == gray). + */ + +METHODDEF(void) +grayscale_convert (j_compress_ptr cinfo, + JSAMPARRAY input_buf, JSAMPIMAGE output_buf, + JDIMENSION output_row, int num_rows) +{ + register JSAMPROW inptr; + register JSAMPROW outptr; + register JDIMENSION col; + JDIMENSION num_cols = cinfo->image_width; + int instride = cinfo->input_components; + + while (--num_rows >= 0) { + inptr = *input_buf++; + outptr = output_buf[0][output_row]; + output_row++; + for (col = 0; col < num_cols; col++) { + outptr[col] = inptr[0]; /* don't need GETJSAMPLE() here */ + inptr += instride; + } + } +} + + +/* + * Convert some rows of samples to the JPEG colorspace. + * This version handles multi-component colorspaces without conversion. + * We assume input_components == num_components. + */ + +METHODDEF(void) +null_convert (j_compress_ptr cinfo, + JSAMPARRAY input_buf, JSAMPIMAGE output_buf, + JDIMENSION output_row, int num_rows) +{ + register JSAMPROW inptr; + register JSAMPROW outptr; + register JDIMENSION col; + register int ci; + int nc = cinfo->num_components; + JDIMENSION num_cols = cinfo->image_width; + + while (--num_rows >= 0) { + /* It seems fastest to make a separate pass for each component. */ + for (ci = 0; ci < nc; ci++) { + inptr = *input_buf; + outptr = output_buf[ci][output_row]; + for (col = 0; col < num_cols; col++) { + outptr[col] = inptr[ci]; /* don't need GETJSAMPLE() here */ + inptr += nc; + } + } + input_buf++; + output_row++; + } +} + + +/* + * Empty method for start_pass. + */ + +METHODDEF(void) +null_method (j_compress_ptr cinfo) +{ + /* no work needed */ +} + + +/* + * Module initialization routine for input colorspace conversion. + */ + +GLOBAL(void) +jinit_color_converter (j_compress_ptr cinfo) +{ + my_cconvert_ptr cconvert; + + cconvert = (my_cconvert_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_color_converter)); + cinfo->cconvert = (struct jpeg_color_converter *) cconvert; + /* set start_pass to null method until we find out differently */ + cconvert->pub.start_pass = null_method; + + /* Make sure input_components agrees with in_color_space */ + switch (cinfo->in_color_space) { + case JCS_GRAYSCALE: + if (cinfo->input_components != 1) + ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); + break; + + case JCS_RGB: +#if RGB_PIXELSIZE != 3 + if (cinfo->input_components != RGB_PIXELSIZE) + ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); + break; +#endif /* else share code with YCbCr */ + + case JCS_YCbCr: + if (cinfo->input_components != 3) + ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); + break; + + case JCS_CMYK: + case JCS_YCCK: + if (cinfo->input_components != 4) + ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); + break; + + default: /* JCS_UNKNOWN can be anything */ + if (cinfo->input_components < 1) + ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); + break; + } + + /* Check num_components, set conversion method based on requested space */ + switch (cinfo->jpeg_color_space) { + case JCS_GRAYSCALE: + if (cinfo->num_components != 1) + ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); + if (cinfo->in_color_space == JCS_GRAYSCALE) + cconvert->pub.color_convert = grayscale_convert; + else if (cinfo->in_color_space == JCS_RGB) { + cconvert->pub.start_pass = rgb_ycc_start; + cconvert->pub.color_convert = rgb_gray_convert; + } else if (cinfo->in_color_space == JCS_YCbCr) + cconvert->pub.color_convert = grayscale_convert; + else + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); + break; + + case JCS_RGB: + if (cinfo->num_components != 3) + ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); + if (cinfo->in_color_space == JCS_RGB && RGB_PIXELSIZE == 3) + cconvert->pub.color_convert = null_convert; + else + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); + break; + + case JCS_YCbCr: + if (cinfo->num_components != 3) + ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); + if (cinfo->in_color_space == JCS_RGB) { + cconvert->pub.start_pass = rgb_ycc_start; + cconvert->pub.color_convert = rgb_ycc_convert; + } else if (cinfo->in_color_space == JCS_YCbCr) + cconvert->pub.color_convert = null_convert; + else + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); + break; + + case JCS_CMYK: + if (cinfo->num_components != 4) + ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); + if (cinfo->in_color_space == JCS_CMYK) + cconvert->pub.color_convert = null_convert; + else + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); + break; + + case JCS_YCCK: + if (cinfo->num_components != 4) + ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); + if (cinfo->in_color_space == JCS_CMYK) { + cconvert->pub.start_pass = rgb_ycc_start; + cconvert->pub.color_convert = cmyk_ycck_convert; + } else if (cinfo->in_color_space == JCS_YCCK) + cconvert->pub.color_convert = null_convert; + else + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); + break; + + default: /* allow null conversion of JCS_UNKNOWN */ + if (cinfo->jpeg_color_space != cinfo->in_color_space || + cinfo->num_components != cinfo->input_components) + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); + cconvert->pub.color_convert = null_convert; + break; + } +} diff --git a/dcmjpeg/libijg12/jcdctmgr.c b/dcmjpeg/libijg12/jcdctmgr.c new file mode 100644 index 00000000..8ff7cae9 --- /dev/null +++ b/dcmjpeg/libijg12/jcdctmgr.c @@ -0,0 +1,390 @@ +/* + * jcdctmgr.c + * + * Copyright (C) 1994-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains the forward-DCT management logic. + * This code selects a particular DCT implementation to be used, + * and it performs related housekeeping chores including coefficient + * quantization. + */ + +#define JPEG_INTERNALS +#include "jinclude12.h" +#include "jpeglib12.h" +#include "jlossy12.h" /* Private declarations for lossy codec */ +#include "jdct12.h" /* Private declarations for DCT subsystem */ + + +/* Private subobject for this module */ + +typedef struct { + /* Pointer to the DCT routine actually in use */ + forward_DCT_method_ptr do_dct; + + /* The actual post-DCT divisors --- not identical to the quant table + * entries, because of scaling (especially for an unnormalized DCT). + * Each table is given in normal array order. + */ + DCTELEM * divisors[NUM_QUANT_TBLS]; + +#ifdef DCT_FLOAT_SUPPORTED + /* Same as above for the floating-point case. */ + float_DCT_method_ptr do_float_dct; + FAST_FLOAT * float_divisors[NUM_QUANT_TBLS]; +#endif +} fdct_controller; + +typedef fdct_controller * fdct_ptr; + + +/* + * Initialize for a processing pass. + * Verify that all referenced Q-tables are present, and set up + * the divisor table for each one. + * In the current implementation, DCT of all components is done during + * the first pass, even if only some components will be output in the + * first scan. Hence all components should be examined here. + */ + +METHODDEF(void) +start_pass_fdctmgr (j_compress_ptr cinfo) +{ + j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; + fdct_ptr fdct = (fdct_ptr) lossyc->fdct_private; + int ci, qtblno, i; + jpeg_component_info *compptr; + JQUANT_TBL * qtbl; + DCTELEM * dtbl; + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + qtblno = compptr->quant_tbl_no; + /* Make sure specified quantization table is present */ + if (qtblno < 0 || qtblno >= NUM_QUANT_TBLS || + cinfo->quant_tbl_ptrs[qtblno] == NULL) + ERREXIT1(cinfo, JERR_NO_QUANT_TABLE, qtblno); + qtbl = cinfo->quant_tbl_ptrs[qtblno]; + /* Compute divisors for this quant table */ + /* We may do this more than once for same table, but it's not a big deal */ + switch (cinfo->dct_method) { +#ifdef DCT_ISLOW_SUPPORTED + case JDCT_ISLOW: + /* For LL&M IDCT method, divisors are equal to raw quantization + * coefficients multiplied by 8 (to counteract scaling). + */ + if (fdct->divisors[qtblno] == NULL) { + fdct->divisors[qtblno] = (DCTELEM *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + DCTSIZE2 * SIZEOF(DCTELEM)); + } + dtbl = fdct->divisors[qtblno]; + for (i = 0; i < DCTSIZE2; i++) { + dtbl[i] = ((DCTELEM) qtbl->quantval[i]) << 3; + } + break; +#endif +#ifdef DCT_IFAST_SUPPORTED + case JDCT_IFAST: + { + /* For AA&N IDCT method, divisors are equal to quantization + * coefficients scaled by scalefactor[row]*scalefactor[col], where + * scalefactor[0] = 1 + * scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7 + * We apply a further scale factor of 8. + */ +#define CONST_BITS 14 + static const INT16 aanscales[DCTSIZE2] = { + /* precomputed values scaled up by 14 bits */ + 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520, + 22725, 31521, 29692, 26722, 22725, 17855, 12299, 6270, + 21407, 29692, 27969, 25172, 21407, 16819, 11585, 5906, + 19266, 26722, 25172, 22654, 19266, 15137, 10426, 5315, + 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520, + 12873, 17855, 16819, 15137, 12873, 10114, 6967, 3552, + 8867, 12299, 11585, 10426, 8867, 6967, 4799, 2446, + 4520, 6270, 5906, 5315, 4520, 3552, 2446, 1247 + }; + SHIFT_TEMPS + + if (fdct->divisors[qtblno] == NULL) { + fdct->divisors[qtblno] = (DCTELEM *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + DCTSIZE2 * SIZEOF(DCTELEM)); + } + dtbl = fdct->divisors[qtblno]; + for (i = 0; i < DCTSIZE2; i++) { + dtbl[i] = (DCTELEM) + DESCALE(MULTIPLY16V16((IJG_INT32) qtbl->quantval[i], + (IJG_INT32) aanscales[i]), + CONST_BITS-3); + } + } + break; +#endif +#ifdef DCT_FLOAT_SUPPORTED + case JDCT_FLOAT: + { + /* For float AA&N IDCT method, divisors are equal to quantization + * coefficients scaled by scalefactor[row]*scalefactor[col], where + * scalefactor[0] = 1 + * scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7 + * We apply a further scale factor of 8. + * What's actually stored is 1/divisor so that the inner loop can + * use a multiplication rather than a division. + */ + FAST_FLOAT * fdtbl; + int row, col; + static const double aanscalefactor[DCTSIZE] = { + 1.0, 1.387039845, 1.306562965, 1.175875602, + 1.0, 0.785694958, 0.541196100, 0.275899379 + }; + + if (fdct->float_divisors[qtblno] == NULL) { + fdct->float_divisors[qtblno] = (FAST_FLOAT *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + DCTSIZE2 * SIZEOF(FAST_FLOAT)); + } + fdtbl = fdct->float_divisors[qtblno]; + i = 0; + for (row = 0; row < DCTSIZE; row++) { + for (col = 0; col < DCTSIZE; col++) { + fdtbl[i] = (FAST_FLOAT) + (1.0 / (((double) qtbl->quantval[i] * + aanscalefactor[row] * aanscalefactor[col] * 8.0))); + i++; + } + } + } + break; +#endif + default: + ERREXIT(cinfo, JERR_NOT_COMPILED); + break; + } + } +} + + +/* + * Perform forward DCT on one or more blocks of a component. + * + * The input samples are taken from the sample_data[] array starting at + * position start_row/start_col, and moving to the right for any additional + * blocks. The quantized coefficients are returned in coef_blocks[]. + */ + +METHODDEF(void) +forward_DCT (j_compress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY sample_data, JBLOCKROW coef_blocks, + JDIMENSION start_row, JDIMENSION start_col, + JDIMENSION num_blocks) +/* This version is used for integer DCT implementations. */ +{ + /* This routine is heavily used, so it's worth coding it tightly. */ + j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; + fdct_ptr fdct = (fdct_ptr) lossyc->fdct_private; + forward_DCT_method_ptr do_dct = fdct->do_dct; + DCTELEM * divisors = fdct->divisors[compptr->quant_tbl_no]; + DCTELEM workspace[DCTSIZE2]; /* work area for FDCT subroutine */ + JDIMENSION bi; + + sample_data += start_row; /* fold in the vertical offset once */ + + for (bi = 0; bi < num_blocks; bi++, start_col += DCTSIZE) { + /* Load data into workspace, applying unsigned->signed conversion */ + { register DCTELEM *workspaceptr; + register JSAMPROW elemptr; + register int elemr; + + workspaceptr = workspace; + for (elemr = 0; elemr < DCTSIZE; elemr++) { + elemptr = sample_data[elemr] + start_col; +#if DCTSIZE == 8 /* unroll the inner loop */ + *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; + *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; + *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; + *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; + *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; + *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; + *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; + *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; +#else + { register int elemc; + for (elemc = DCTSIZE; elemc > 0; elemc--) { + *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; + } + } +#endif + } + } + + /* Perform the DCT */ + (*do_dct) (workspace); + + /* Quantize/descale the coefficients, and store into coef_blocks[] */ + { register DCTELEM temp, qval; + register int i; + register JCOEFPTR output_ptr = coef_blocks[bi]; + + for (i = 0; i < DCTSIZE2; i++) { + qval = divisors[i]; + temp = workspace[i]; + /* Divide the coefficient value by qval, ensuring proper rounding. + * Since C does not specify the direction of rounding for negative + * quotients, we have to force the dividend positive for portability. + * + * In most files, at least half of the output values will be zero + * (at default quantization settings, more like three-quarters...) + * so we should ensure that this case is fast. On many machines, + * a comparison is enough cheaper than a divide to make a special test + * a win. Since both inputs will be nonnegative, we need only test + * for a < b to discover whether a/b is 0. + * If your machine's division is fast enough, define FAST_DIVIDE. + */ +#ifdef FAST_DIVIDE +#define DIVIDE_BY(a,b) a /= b +#else +#define DIVIDE_BY(a,b) if (a >= b) a /= b; else a = 0 +#endif + if (temp < 0) { + temp = -temp; + temp += qval>>1; /* for rounding */ + DIVIDE_BY(temp, qval); + temp = -temp; + } else { + temp += qval>>1; /* for rounding */ + DIVIDE_BY(temp, qval); + } + output_ptr[i] = (JCOEF) temp; + } + } + } +} + + +#ifdef DCT_FLOAT_SUPPORTED + +METHODDEF(void) +forward_DCT_float (j_compress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY sample_data, JBLOCKROW coef_blocks, + JDIMENSION start_row, JDIMENSION start_col, + JDIMENSION num_blocks) +/* This version is used for floating-point DCT implementations. */ +{ + /* This routine is heavily used, so it's worth coding it tightly. */ + j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; + fdct_ptr fdct = (fdct_ptr) lossyc->fdct_private; + float_DCT_method_ptr do_dct = fdct->do_float_dct; + FAST_FLOAT * divisors = fdct->float_divisors[compptr->quant_tbl_no]; + FAST_FLOAT workspace[DCTSIZE2]; /* work area for FDCT subroutine */ + JDIMENSION bi; + + sample_data += start_row; /* fold in the vertical offset once */ + + for (bi = 0; bi < num_blocks; bi++, start_col += DCTSIZE) { + /* Load data into workspace, applying unsigned->signed conversion */ + { register FAST_FLOAT *workspaceptr; + register JSAMPROW elemptr; + register int elemr; + + workspaceptr = workspace; + for (elemr = 0; elemr < DCTSIZE; elemr++) { + elemptr = sample_data[elemr] + start_col; +#if DCTSIZE == 8 /* unroll the inner loop */ + *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); + *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); + *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); + *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); + *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); + *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); + *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); + *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); +#else + { register int elemc; + for (elemc = DCTSIZE; elemc > 0; elemc--) { + *workspaceptr++ = (FAST_FLOAT) + (GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); + } + } +#endif + } + } + + /* Perform the DCT */ + (*do_dct) (workspace); + + /* Quantize/descale the coefficients, and store into coef_blocks[] */ + { register FAST_FLOAT temp; + register int i; + register JCOEFPTR output_ptr = coef_blocks[bi]; + + for (i = 0; i < DCTSIZE2; i++) { + /* Apply the quantization and scaling factor */ + temp = workspace[i] * divisors[i]; + /* Round to nearest integer. + * Since C does not specify the direction of rounding for negative + * quotients, we have to force the dividend positive for portability. + * The maximum coefficient size is +-16K (for 12-bit data), so this + * code should work for either 16-bit or 32-bit ints. + */ + output_ptr[i] = (JCOEF) ((int) (temp + (FAST_FLOAT) 16384.5) - 16384); + } + } + } +} + +#endif /* DCT_FLOAT_SUPPORTED */ + + +/* + * Initialize FDCT manager. + */ + +GLOBAL(void) +jinit_forward_dct (j_compress_ptr cinfo) +{ + j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; + fdct_ptr fdct; + int i; + + fdct = (fdct_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(fdct_controller)); + lossyc->fdct_private = (struct jpeg_forward_dct *) fdct; + lossyc->fdct_start_pass = start_pass_fdctmgr; + + switch (cinfo->dct_method) { +#ifdef DCT_ISLOW_SUPPORTED + case JDCT_ISLOW: + lossyc->fdct_forward_DCT = forward_DCT; + fdct->do_dct = jpeg_fdct_islow; + break; +#endif +#ifdef DCT_IFAST_SUPPORTED + case JDCT_IFAST: + lossyc->fdct_forward_DCT = forward_DCT; + fdct->do_dct = jpeg_fdct_ifast; + break; +#endif +#ifdef DCT_FLOAT_SUPPORTED + case JDCT_FLOAT: + lossyc->fdct_forward_DCT = forward_DCT_float; + fdct->do_float_dct = jpeg_fdct_float; + break; +#endif + default: + ERREXIT(cinfo, JERR_NOT_COMPILED); + break; + } + + /* Mark divisor tables unallocated */ + for (i = 0; i < NUM_QUANT_TBLS; i++) { + fdct->divisors[i] = NULL; +#ifdef DCT_FLOAT_SUPPORTED + fdct->float_divisors[i] = NULL; +#endif + } +} diff --git a/dcmjpeg/libijg12/jcdiffct.c b/dcmjpeg/libijg12/jcdiffct.c new file mode 100644 index 00000000..25b75834 --- /dev/null +++ b/dcmjpeg/libijg12/jcdiffct.c @@ -0,0 +1,406 @@ +/* + * jcdiffct.c + * + * Copyright (C) 1994-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains the difference buffer controller for compression. + * This controller is the top level of the lossless JPEG compressor proper. + * The difference buffer lies between prediction/differencing and entropy + * encoding. + */ + +#define JPEG_INTERNALS +#include "jinclude12.h" +#include "jpeglib12.h" +#include "jlossls12.h" /* Private declarations for lossless codec */ + + +#ifdef C_LOSSLESS_SUPPORTED + +/* We use a full-image sample buffer when doing Huffman optimization, + * and also for writing multiple-scan JPEG files. In all cases, the + * full-image buffer is filled during the first pass, and the scaling, + * prediction and differencing steps are run during subsequent passes. + */ +#ifdef ENTROPY_OPT_SUPPORTED +#define FULL_SAMP_BUFFER_SUPPORTED +#else +#ifdef C_MULTISCAN_FILES_SUPPORTED +#define FULL_SAMP_BUFFER_SUPPORTED +#endif +#endif + + +/* Private buffer controller object */ + +typedef struct { + JDIMENSION iMCU_row_num; /* iMCU row # within image */ + JDIMENSION mcu_ctr; /* counts MCUs processed in current row */ + int MCU_vert_offset; /* counts MCU rows within iMCU row */ + int MCU_rows_per_iMCU_row; /* number of such rows needed */ + + JSAMPROW cur_row[MAX_COMPONENTS]; /* row of point transformed samples */ + JSAMPROW prev_row[MAX_COMPONENTS]; /* previous row of Pt'd samples */ + JDIFFARRAY diff_buf[MAX_COMPONENTS]; /* iMCU row of differences */ + + /* In multi-pass modes, we need a virtual sample array for each component. */ + jvirt_sarray_ptr whole_image[MAX_COMPONENTS]; +} c_diff_controller; + +typedef c_diff_controller * c_diff_ptr; + + +/* Forward declarations */ +METHODDEF(boolean) compress_data + JPP((j_compress_ptr cinfo, JSAMPIMAGE input_buf)); +#ifdef FULL_SAMP_BUFFER_SUPPORTED +METHODDEF(boolean) compress_first_pass + JPP((j_compress_ptr cinfo, JSAMPIMAGE input_buf)); +METHODDEF(boolean) compress_output + JPP((j_compress_ptr cinfo, JSAMPIMAGE input_buf)); +#endif + + +LOCAL(void) +start_iMCU_row (j_compress_ptr cinfo) +/* Reset within-iMCU-row counters for a new row */ +{ + j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec; + c_diff_ptr diff = (c_diff_ptr) losslsc->diff_private; + + /* In an interleaved scan, an MCU row is the same as an iMCU row. + * In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows. + * But at the bottom of the image, process only what's left. + */ + if (cinfo->comps_in_scan > 1) { + diff->MCU_rows_per_iMCU_row = 1; + } else { + if (diff->iMCU_row_num < (cinfo->total_iMCU_rows-1)) + diff->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->v_samp_factor; + else + diff->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->last_row_height; + } + + diff->mcu_ctr = 0; + diff->MCU_vert_offset = 0; +} + + +/* + * Initialize for a processing pass. + */ + +METHODDEF(void) +start_pass_diff (j_compress_ptr cinfo, J_BUF_MODE pass_mode) +{ + j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec; + c_diff_ptr diff = (c_diff_ptr) losslsc->diff_private; + + diff->iMCU_row_num = 0; + start_iMCU_row(cinfo); + + switch (pass_mode) { + case JBUF_PASS_THRU: + if (diff->whole_image[0] != NULL) + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + losslsc->pub.compress_data = compress_data; + break; +#ifdef FULL_SAMP_BUFFER_SUPPORTED + case JBUF_SAVE_AND_PASS: + if (diff->whole_image[0] == NULL) + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + losslsc->pub.compress_data = compress_first_pass; + break; + case JBUF_CRANK_DEST: + if (diff->whole_image[0] == NULL) + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + losslsc->pub.compress_data = compress_output; + break; +#endif + default: + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + break; + } +} + + +#define SWAP_ROWS(rowa,rowb) {JSAMPROW temp; temp=rowa; rowa=rowb; rowb=temp;} + +/* + * Process some data in the single-pass case. + * We process the equivalent of one fully interleaved MCU row ("iMCU" row) + * per call, ie, v_samp_factor rows for each component in the image. + * Returns TRUE if the iMCU row is completed, FALSE if suspended. + * + * NB: input_buf contains a plane for each component in image, + * which we index according to the component's SOF position. + */ + +METHODDEF(boolean) +compress_data (j_compress_ptr cinfo, JSAMPIMAGE input_buf) +{ + j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec; + c_diff_ptr diff = (c_diff_ptr) losslsc->diff_private; + JDIMENSION MCU_col_num; /* index of current MCU within row */ + JDIMENSION MCU_count; /* number of MCUs encoded */ + /* JDIMENSION last_MCU_col = cinfo->MCUs_per_row - 1; */ + JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; + int comp, ci, yoffset, samp_row, samp_rows, samps_across; + jpeg_component_info *compptr; + + /* Loop to write as much as one whole iMCU row */ + for (yoffset = diff->MCU_vert_offset; yoffset < diff->MCU_rows_per_iMCU_row; + yoffset++) { + + MCU_col_num = diff->mcu_ctr; + + /* Scale and predict each scanline of the MCU-row separately. + * + * Note: We only do this if we are at the start of a MCU-row, ie, + * we don't want to reprocess a row suspended by the output. + */ + if (MCU_col_num == 0) { + for (comp = 0; comp < cinfo->comps_in_scan; comp++) { + compptr = cinfo->cur_comp_info[comp]; + ci = compptr->component_index; + if (diff->iMCU_row_num < last_iMCU_row) + samp_rows = compptr->v_samp_factor; + else { + /* NB: can't use last_row_height here, since may not be set! */ + samp_rows = (int)compptr->height_in_data_units % compptr->v_samp_factor; + if (samp_rows == 0) samp_rows = compptr->v_samp_factor; + else { + /* Fill dummy difference rows at the bottom edge with zeros, which + * will encode to the smallest amount of data. + */ + for (samp_row = samp_rows; samp_row < compptr->v_samp_factor; + samp_row++) + MEMZERO(diff->diff_buf[ci][samp_row], + (size_t)jround_up((long) compptr->width_in_data_units, + (long) compptr->h_samp_factor) * SIZEOF(JDIFF)); + } + } + samps_across = (int)compptr->width_in_data_units; + + for (samp_row = 0; samp_row < samp_rows; samp_row++) { + (*losslsc->scaler_scale) (cinfo, + input_buf[ci][samp_row], + diff->cur_row[ci], (JDIMENSION)samps_across); + (*losslsc->predict_difference[ci]) (cinfo, ci, + diff->cur_row[ci], + diff->prev_row[ci], + diff->diff_buf[ci][samp_row], + (JDIMENSION)samps_across); + SWAP_ROWS(diff->cur_row[ci], diff->prev_row[ci]); + } + } + } + + /* Try to write the MCU-row (or remaining portion of suspended MCU-row). */ + MCU_count = + (*losslsc->entropy_encode_mcus) (cinfo, + diff->diff_buf, (JDIMENSION)yoffset, MCU_col_num, + (JDIMENSION)cinfo->MCUs_per_row - MCU_col_num); + if (MCU_count != cinfo->MCUs_per_row - MCU_col_num) { + /* Suspension forced; update state counters and exit */ + diff->MCU_vert_offset = yoffset; + diff->mcu_ctr += MCU_col_num; + return FALSE; + } + + /* Completed an MCU row, but perhaps not an iMCU row */ + diff->mcu_ctr = 0; + } + + /* Completed the iMCU row, advance counters for next one */ + diff->iMCU_row_num++; + start_iMCU_row(cinfo); + return TRUE; +} + + +#ifdef FULL_SAMP_BUFFER_SUPPORTED + +/* + * Process some data in the first pass of a multi-pass case. + * We process the equivalent of one fully interleaved MCU row ("iMCU" row) + * per call, ie, v_samp_factor rows for each component in the image. + * This amount of data is read from the source buffer and saved into the + * virtual arrays. + * + * We must also emit the data to the compressor. This is conveniently + * done by calling compress_output() after we've loaded the current strip + * of the virtual arrays. + * + * NB: input_buf contains a plane for each component in image. All components + * are loaded into the virtual arrays in this pass. However, it may be that + * only a subset of the components are emitted to the compressor during + * this first pass; be careful about looking at the scan-dependent variables + * (MCU dimensions, etc). + */ + +METHODDEF(boolean) +compress_first_pass (j_compress_ptr cinfo, JSAMPIMAGE input_buf) +{ + j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec; + c_diff_ptr diff = (c_diff_ptr) losslsc->diff_private; + JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; + JDIMENSION samps_across; + int ci, samp_row, samp_rows; + JSAMPARRAY buffer[MAX_COMPONENTS]; + jpeg_component_info *compptr; + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + /* Align the virtual buffers for this component. */ + buffer[ci] = (*cinfo->mem->access_virt_sarray) + ((j_common_ptr) cinfo, diff->whole_image[ci], + diff->iMCU_row_num * (JDIMENSION)compptr->v_samp_factor, + (JDIMENSION) compptr->v_samp_factor, TRUE); + + /* Count non-dummy sample rows in this iMCU row. */ + if (diff->iMCU_row_num < last_iMCU_row) + samp_rows = compptr->v_samp_factor; + else { + /* NB: can't use last_row_height here, since may not be set! */ + samp_rows = (int)compptr->height_in_data_units % compptr->v_samp_factor; + if (samp_rows == 0) samp_rows = compptr->v_samp_factor; + } + samps_across = compptr->width_in_data_units; + + /* Perform point transform scaling and prediction/differencing for all + * non-dummy rows in this iMCU row. Each call on these functions + * process a complete row of samples. + */ + for (samp_row = 0; samp_row < samp_rows; samp_row++) { + MEMCOPY(buffer[ci][samp_row], input_buf[ci][samp_row], + samps_across * SIZEOF(JSAMPLE)); + } + } + + /* NB: compress_output will increment iMCU_row_num if successful. + * A suspension return will result in redoing all the work above next time. + */ + + /* Emit data to the compressor, sharing code with subsequent passes */ + return compress_output(cinfo, input_buf); +} + + +/* + * Process some data in subsequent passes of a multi-pass case. + * We process the equivalent of one fully interleaved MCU row ("iMCU" row) + * per call, ie, v_samp_factor rows for each component in the scan. + * The data is obtained from the virtual arrays and fed to the compressor. + * Returns TRUE if the iMCU row is completed, FALSE if suspended. + * + * NB: input_buf is ignored; it is likely to be a NULL pointer. + */ + +METHODDEF(boolean) +compress_output (j_compress_ptr cinfo, JSAMPIMAGE input_buf) +{ + j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec; + c_diff_ptr diff = (c_diff_ptr) losslsc->diff_private; + /* JDIMENSION MCU_col_num; */ /* index of current MCU within row */ + /* JDIMENSION MCU_count; */ /* number of MCUs encoded */ + int comp, ci /* , yoffset */ ; + JSAMPARRAY buffer[MAX_COMPONENTS]; + jpeg_component_info *compptr; + + /* Align the virtual buffers for the components used in this scan. + * NB: during first pass, this is safe only because the buffers will + * already be aligned properly, so jmemmgr.c won't need to do any I/O. + */ + for (comp = 0; comp < cinfo->comps_in_scan; comp++) { + compptr = cinfo->cur_comp_info[comp]; + ci = compptr->component_index; + buffer[ci] = (*cinfo->mem->access_virt_sarray) + ((j_common_ptr) cinfo, diff->whole_image[ci], + diff->iMCU_row_num * (JDIMENSION)compptr->v_samp_factor, + (JDIMENSION) compptr->v_samp_factor, FALSE); + } + + return compress_data(cinfo, buffer); +} + +#endif /* FULL_SAMP_BUFFER_SUPPORTED */ + + +/* + * Initialize difference buffer controller. + */ + +GLOBAL(void) +jinit_c_diff_controller (j_compress_ptr cinfo, boolean need_full_buffer) +{ + j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec; + c_diff_ptr diff; + int ci, row; + jpeg_component_info *compptr; + + diff = (c_diff_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(c_diff_controller)); + losslsc->diff_private = (void *) diff; + losslsc->diff_start_pass = start_pass_diff; + + /* Create the prediction row buffers. */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + diff->cur_row[ci] = *(*cinfo->mem->alloc_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + (JDIMENSION) jround_up((long) compptr->width_in_data_units, + (long) compptr->h_samp_factor), + (JDIMENSION) 1); + diff->prev_row[ci] = *(*cinfo->mem->alloc_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + (JDIMENSION) jround_up((long) compptr->width_in_data_units, + (long) compptr->h_samp_factor), + (JDIMENSION) 1); + } + + /* Create the difference buffer. */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + diff->diff_buf[ci] = (*cinfo->mem->alloc_darray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + (JDIMENSION) jround_up((long) compptr->width_in_data_units, + (long) compptr->h_samp_factor), + (JDIMENSION) compptr->v_samp_factor); + /* Prefill difference rows with zeros. We do this because only actual + * data is placed in the buffers during prediction/differencing, leaving + * any dummy differences at the right edge as zeros, which will encode + * to the smallest amount of data. + */ + for (row = 0; row < compptr->v_samp_factor; row++) + MEMZERO(diff->diff_buf[ci][row], + (size_t)jround_up((long) compptr->width_in_data_units, + (long) compptr->h_samp_factor) * SIZEOF(JDIFF)); + } + + /* Create the sample buffer. */ + if (need_full_buffer) { +#ifdef FULL_SAMP_BUFFER_SUPPORTED + /* Allocate a full-image virtual array for each component, */ + /* padded to a multiple of samp_factor differences in each direction. */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + diff->whole_image[ci] = (*cinfo->mem->request_virt_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE, + (JDIMENSION) jround_up((long) compptr->width_in_data_units, + (long) compptr->h_samp_factor), + (JDIMENSION) jround_up((long) compptr->height_in_data_units, + (long) compptr->v_samp_factor), + (JDIMENSION) compptr->v_samp_factor); + } +#else + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); +#endif + } else + diff->whole_image[0] = NULL; /* flag for no virtual arrays */ +} + +#endif /* C_LOSSLESS_SUPPORTED */ diff --git a/dcmjpeg/libijg12/jchuff.c b/dcmjpeg/libijg12/jchuff.c new file mode 100644 index 00000000..1f318cf5 --- /dev/null +++ b/dcmjpeg/libijg12/jchuff.c @@ -0,0 +1,274 @@ +/* + * jchuff.c + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains Huffman entropy decoding routines which are shared + * by the sequential, progressive and lossless decoders. + */ + +#define JPEG_INTERNALS +#include "jinclude12.h" +#include "jpeglib12.h" +#include "jchuff12.h" /* Declarations shared with jc*huff.c */ + + +/* + * Compute the derived values for a Huffman table. + * This routine also performs some validation checks on the table. + */ + +GLOBAL(void) +jpeg_make_c_derived_tbl (j_compress_ptr cinfo, boolean isDC, int tblno, + c_derived_tbl ** pdtbl) +{ + JHUFF_TBL *htbl; + c_derived_tbl *dtbl; + int p, i, l, lastp, si, maxsymbol; + char huffsize[257]; + unsigned int huffcode[257]; + unsigned int code; + + /* Note that huffsize[] and huffcode[] are filled in code-length order, + * paralleling the order of the symbols themselves in htbl->huffval[]. + */ + + /* Find the input Huffman table */ + if (tblno < 0 || tblno >= NUM_HUFF_TBLS) + ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tblno); + htbl = + isDC ? cinfo->dc_huff_tbl_ptrs[tblno] : cinfo->ac_huff_tbl_ptrs[tblno]; + if (htbl == NULL) + ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tblno); + + /* Allocate a workspace if we haven't already done so. */ + if (*pdtbl == NULL) + *pdtbl = (c_derived_tbl *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(c_derived_tbl)); + dtbl = *pdtbl; + + /* Figure C.1: make table of Huffman code length for each symbol */ + + p = 0; + for (l = 1; l <= 16; l++) { + i = (int) htbl->bits[l]; + if (i < 0 || p + i > 256) /* protect against table overrun */ + ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); + while (i--) + huffsize[p++] = (char) l; + } + huffsize[p] = 0; + lastp = p; + + /* Figure C.2: generate the codes themselves */ + /* We also validate that the counts represent a legal Huffman code tree. */ + + code = 0; + si = huffsize[0]; + p = 0; + while (huffsize[p]) { + while (((int) huffsize[p]) == si) { + huffcode[p++] = code; + code++; + } + /* code is now 1 more than the last code used for codelength si; but + * it must still fit in si bits, since no code is allowed to be all ones. + * BUG FIX: Comparison must be >, not >= + */ + if (((IJG_INT32) code) > (((IJG_INT32) 1) << si)) + ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); + code <<= 1; + si++; + } + + /* Figure C.3: generate encoding tables */ + /* These are code and size indexed by symbol value */ + + /* Set all codeless symbols to have code length 0; + * this lets us detect duplicate VAL entries here, and later + * allows emit_bits to detect any attempt to emit such symbols. + */ + MEMZERO(dtbl->ehufsi, SIZEOF(dtbl->ehufsi)); + + /* This is also a convenient place to check for out-of-range + * and duplicated VAL entries. We allow 0..255 for AC symbols + * but only 0..16 for DC. (We could constrain them further + * based on data depth and mode, but this seems enough.) + */ + maxsymbol = isDC ? 16 : 255; + + for (p = 0; p < lastp; p++) { + i = htbl->huffval[p]; + if (i < 0 || i > maxsymbol || dtbl->ehufsi[i]) + ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); + dtbl->ehufco[i] = huffcode[p]; + dtbl->ehufsi[i] = huffsize[p]; + } +} + + +/* + * Generate the best Huffman code table for the given counts, fill htbl. + * + * The JPEG standard requires that no symbol be assigned a codeword of all + * one bits (so that padding bits added at the end of a compressed segment + * can't look like a valid code). Because of the canonical ordering of + * codewords, this just means that there must be an unused slot in the + * longest codeword length category. Section K.2 of the JPEG spec suggests + * reserving such a slot by pretending that symbol 256 is a valid symbol + * with count 1. In theory that's not optimal; giving it count zero but + * including it in the symbol set anyway should give a better Huffman code. + * But the theoretically better code actually seems to come out worse in + * practice, because it produces more all-ones bytes (which incur stuffed + * zero bytes in the final file). In any case the difference is tiny. + * + * The JPEG standard requires Huffman codes to be no more than 16 bits long. + * If some symbols have a very small but nonzero probability, the Huffman tree + * must be adjusted to meet the code length restriction. We currently use + * the adjustment method suggested in JPEG section K.2. This method is *not* + * optimal; it may not choose the best possible limited-length code. But + * typically only very-low-frequency symbols will be given less-than-optimal + * lengths, so the code is almost optimal. Experimental comparisons against + * an optimal limited-length-code algorithm indicate that the difference is + * microscopic --- usually less than a hundredth of a percent of total size. + * So the extra complexity of an optimal algorithm doesn't seem worthwhile. + */ + +GLOBAL(void) +jpeg_gen_optimal_table (j_compress_ptr cinfo, JHUFF_TBL * htbl, long freq[]) +{ +#define MAX_CLEN 32 /* assumed maximum initial code length */ + UINT8 bits[MAX_CLEN+1]; /* bits[k] = # of symbols with code length k */ + int codesize[257]; /* codesize[k] = code length of symbol k */ + int others[257]; /* next symbol in current branch of tree */ + int c1, c2; + int p, i, j; + long v; + + /* This algorithm is explained in section K.2 of the JPEG standard */ + + MEMZERO(bits, SIZEOF(bits)); + MEMZERO(codesize, SIZEOF(codesize)); + for (i = 0; i < 257; i++) + others[i] = -1; /* init links to empty */ + + freq[256] = 1; /* make sure 256 has a nonzero count */ + /* Including the pseudo-symbol 256 in the Huffman procedure guarantees + * that no real symbol is given code-value of all ones, because 256 + * will be placed last in the largest codeword category. + */ + + /* Huffman's basic algorithm to assign optimal code lengths to symbols */ + + for (;;) { + /* Find the smallest nonzero frequency, set c1 = its symbol */ + /* In case of ties, take the larger symbol number */ + c1 = -1; + v = 1000000000L; + for (i = 0; i <= 256; i++) { + if (freq[i] && freq[i] <= v) { + v = freq[i]; + c1 = i; + } + } + + /* Find the next smallest nonzero frequency, set c2 = its symbol */ + /* In case of ties, take the larger symbol number */ + c2 = -1; + v = 1000000000L; + for (i = 0; i <= 256; i++) { + if (freq[i] && freq[i] <= v && i != c1) { + v = freq[i]; + c2 = i; + } + } + + /* Done if we've merged everything into one frequency */ + if (c2 < 0) + break; + + /* Else merge the two counts/trees */ + freq[c1] += freq[c2]; + freq[c2] = 0; + + /* Increment the codesize of everything in c1's tree branch */ + codesize[c1]++; + while (others[c1] >= 0) { + c1 = others[c1]; + codesize[c1]++; + } + + others[c1] = c2; /* chain c2 onto c1's tree branch */ + + /* Increment the codesize of everything in c2's tree branch */ + codesize[c2]++; + while (others[c2] >= 0) { + c2 = others[c2]; + codesize[c2]++; + } + } + + /* Now count the number of symbols of each code length */ + for (i = 0; i <= 256; i++) { + if (codesize[i]) { + /* The JPEG standard seems to think that this can't happen, */ + /* but I'm paranoid... */ + if (codesize[i] > MAX_CLEN) + ERREXIT(cinfo, JERR_HUFF_CLEN_OVERFLOW); + + bits[codesize[i]]++; + } + } + + /* JPEG doesn't allow symbols with code lengths over 16 bits, so if the pure + * Huffman procedure assigned any such lengths, we must adjust the coding. + * Here is what the JPEG spec says about how this next bit works: + * Since symbols are paired for the longest Huffman code, the symbols are + * removed from this length category two at a time. The prefix for the pair + * (which is one bit shorter) is allocated to one of the pair; then, + * skipping the BITS entry for that prefix length, a code word from the next + * shortest nonzero BITS entry is converted into a prefix for two code words + * one bit longer. + */ + + for (i = MAX_CLEN; i > 16; i--) { + while (bits[i] > 0) { + j = i - 2; /* find length of new prefix to be used */ + while (bits[j] == 0) + j--; + + bits[i] = (UINT8)(bits[i] - 2); /* remove two symbols */ + bits[i-1]++; /* one goes in this length */ + bits[j+1] = (UINT8)(bits[j+1] + 2); /* two new symbols in this length */ + bits[j]--; /* symbol of this length is now a prefix */ + } + } + + /* Remove the count for the pseudo-symbol 256 from the largest codelength */ + while (bits[i] == 0) /* find largest codelength still in use */ + i--; + bits[i]--; + + /* Return final symbol counts (only for lengths 0..16) */ + MEMCOPY(htbl->bits, bits, SIZEOF(htbl->bits)); + + /* Return a list of the symbols sorted by code length */ + /* It's not real clear to me why we don't need to consider the codelength + * changes made above, but the JPEG spec seems to think this works. + */ + p = 0; + for (i = 1; i <= MAX_CLEN; i++) { + for (j = 0; j <= 255; j++) { + if (codesize[j] == i) { + htbl->huffval[p] = (UINT8) j; + p++; + } + } + } + + /* Set sent_table FALSE so updated table will be written to JPEG file. */ + htbl->sent_table = FALSE; +} diff --git a/dcmjpeg/libijg12/jchuff12.h b/dcmjpeg/libijg12/jchuff12.h new file mode 100644 index 00000000..addfb3ff --- /dev/null +++ b/dcmjpeg/libijg12/jchuff12.h @@ -0,0 +1,54 @@ +/* + * jchuff.h + * + * Copyright (C) 1991-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains declarations for Huffman entropy encoding routines + * that are shared between the sequential encoder (jchuff.c) and the + * progressive encoder (jcphuff.c). No other modules need to see these. + */ + +/* The legal range of a DCT coefficient is + * -1024 .. +1023 for 8-bit data; + * -16384 .. +16383 for 12-bit data. + * Hence the magnitude should always fit in 10 or 14 bits respectively. + */ + +#if BITS_IN_JSAMPLE == 8 +#define MAX_COEF_BITS 10 +#else +#define MAX_COEF_BITS 14 +#endif + +/* The legal range of a spatial difference is + * -32767 .. +32768. + * Hence the magnitude should always fit in 16 bits. + */ + +#define MAX_DIFF_BITS 16 + +/* Derived data constructed for each Huffman table */ + +typedef struct { + unsigned int ehufco[256]; /* code for each symbol */ + char ehufsi[256]; /* length of code for each symbol */ + /* If no code has been allocated for a symbol S, ehufsi[S] contains 0 */ +} c_derived_tbl; + +/* Short forms of external names for systems with brain-damaged linkers. */ + +#ifdef NEED_SHORT_EXTERNAL_NAMES +#define jpeg_make_c_derived_tbl jpeg12_make_c_derived_tbl +#define jpeg_gen_optimal_table jpeg12_gen_optimal_table +#endif /* NEED_SHORT_EXTERNAL_NAMES */ + +/* Expand a Huffman table definition into the derived format */ +EXTERN(void) jpeg_make_c_derived_tbl + JPP((j_compress_ptr cinfo, boolean isDC, int tblno, + c_derived_tbl ** pdtbl)); + +/* Generate an optimal table definition given the specified counts */ +EXTERN(void) jpeg_gen_optimal_table + JPP((j_compress_ptr cinfo, JHUFF_TBL * htbl, long freq[])); diff --git a/dcmjpeg/libijg12/jcinit.c b/dcmjpeg/libijg12/jcinit.c new file mode 100644 index 00000000..b2953380 --- /dev/null +++ b/dcmjpeg/libijg12/jcinit.c @@ -0,0 +1,57 @@ +/* + * jcinit.c + * + * Copyright (C) 1991-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains initialization logic for the JPEG compressor. + * This routine is in charge of selecting the modules to be executed and + * making an initialization call to each one. + * + * Logically, this code belongs in jcmaster.c. It's split out because + * linking this routine implies linking the entire compression library. + * For a transcoding-only application, we want to be able to use jcmaster.c + * without linking in the whole library. + */ + +#define JPEG_INTERNALS +#include "jinclude12.h" +#include "jpeglib12.h" + + +/* + * Master selection of compression modules. + * This is done once at the start of processing an image. We determine + * which modules will be used and give them appropriate initialization calls. + */ + +GLOBAL(void) +jinit_compress_master (j_compress_ptr cinfo) +{ + /* Initialize master control (includes parameter checking/processing) */ + jinit_c_master_control(cinfo, FALSE /* full compression */); + + /* Initialize compression codec */ + jinit_c_codec(cinfo); + + /* Preprocessing */ + if (! cinfo->raw_data_in) { + jinit_color_converter(cinfo); + jinit_downsampler(cinfo); + jinit_c_prep_controller(cinfo, FALSE /* never need full buffer here */); + } + + jinit_c_main_controller(cinfo, FALSE /* never need full buffer here */); + + jinit_marker_writer(cinfo); + + /* We can now tell the memory manager to allocate virtual arrays. */ + (*cinfo->mem->realize_virt_arrays) ((j_common_ptr) cinfo); + + /* Write the datastream header (SOI) immediately. + * Frame and scan headers are postponed till later. + * This lets application insert special markers after the SOI. + */ + (*cinfo->marker->write_file_header) (cinfo); +} diff --git a/dcmjpeg/libijg12/jclhuff.c b/dcmjpeg/libijg12/jclhuff.c new file mode 100644 index 00000000..5689a5ce --- /dev/null +++ b/dcmjpeg/libijg12/jclhuff.c @@ -0,0 +1,601 @@ +/* + * jclhuff.c + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains Huffman entropy encoding routines for lossless JPEG. + * + * Much of the complexity here has to do with supporting output suspension. + * If the data destination module demands suspension, we want to be able to + * back up to the start of the current MCU. To do this, we copy state + * variables into local working storage, and update them back to the + * permanent JPEG objects only upon successful completion of an MCU. + */ + +#define JPEG_INTERNALS +#include "jinclude12.h" +#include "jpeglib12.h" +#include "jlossls12.h" /* Private declarations for lossless codec */ +#include "jchuff12.h" /* Declarations shared with jc*huff.c */ + + +/* Expanded entropy encoder object for Huffman encoding. + * + * The savable_state subrecord contains fields that change within an MCU, + * but must not be updated permanently until we complete the MCU. + */ + +typedef struct { + IJG_INT32 put_buffer; /* current bit-accumulation buffer */ + int put_bits; /* # of bits now in it */ +} savable_state; + +/* This macro is to work around compilers with missing or broken + * structure assignment. You'll need to fix this code if you have + * such a compiler and you change MAX_COMPS_IN_SCAN. + */ + +#ifndef NO_STRUCT_ASSIGN +#define ASSIGN_STATE(dest,src) ((dest) = (src)) +#else +#define ASSIGN_STATE(dest,src) \ + ((dest).put_buffer = (src).put_buffer, \ + (dest).put_bits = (src).put_bits) +#endif + + +typedef struct { + int ci, yoffset, MCU_width; +} lhe_input_ptr_info; + + +typedef struct { + savable_state saved; /* Bit buffer at start of MCU */ + + /* These fields are NOT loaded into local working state. */ + unsigned int restarts_to_go; /* MCUs left in this restart interval */ + int next_restart_num; /* next restart number to write (0-7) */ + + /* Pointers to derived tables (these workspaces have image lifespan) */ + c_derived_tbl * derived_tbls[NUM_HUFF_TBLS]; + + /* Pointers to derived tables to be used for each data unit within an MCU */ + c_derived_tbl * cur_tbls[C_MAX_DATA_UNITS_IN_MCU]; + +#ifdef ENTROPY_OPT_SUPPORTED /* Statistics tables for optimization */ + long * count_ptrs[NUM_HUFF_TBLS]; + + /* Pointers to stats tables to be used for each data unit within an MCU */ + long * cur_counts[C_MAX_DATA_UNITS_IN_MCU]; +#endif + + /* Pointers to the proper input difference row for each group of data units + * within an MCU. For each component, there are Vi groups of Hi data units. + */ + JDIFFROW input_ptr[C_MAX_DATA_UNITS_IN_MCU]; + + /* Number of input pointers in use for the current MCU. This is the sum + * of all Vi in the MCU. + */ + int num_input_ptrs; + + /* Information used for positioning the input pointers within the input + * difference rows. + */ + lhe_input_ptr_info input_ptr_info[C_MAX_DATA_UNITS_IN_MCU]; + + /* Index of the proper input pointer for each data unit within an MCU */ + int input_ptr_index[C_MAX_DATA_UNITS_IN_MCU]; + +} lhuff_entropy_encoder; + +typedef lhuff_entropy_encoder * lhuff_entropy_ptr; + +/* Working state while writing an MCU. + * This struct contains all the fields that are needed by subroutines. + */ + +typedef struct { + JOCTET * next_output_byte; /* => next byte to write in buffer */ + size_t free_in_buffer; /* # of byte spaces remaining in buffer */ + savable_state cur; /* Current bit buffer & DC state */ + j_compress_ptr cinfo; /* dump_buffer needs access to this */ +} working_state; + + +/* Forward declarations */ +METHODDEF(JDIMENSION) encode_mcus_huff (j_compress_ptr cinfo, + JDIFFIMAGE diff_buf, + JDIMENSION MCU_row_num, + JDIMENSION MCU_col_num, + JDIMENSION nMCU); +METHODDEF(void) finish_pass_huff JPP((j_compress_ptr cinfo)); +#ifdef ENTROPY_OPT_SUPPORTED +METHODDEF(JDIMENSION) encode_mcus_gather (j_compress_ptr cinfo, + JDIFFIMAGE diff_buf, + JDIMENSION MCU_row_num, + JDIMENSION MCU_col_num, + JDIMENSION nMCU); +METHODDEF(void) finish_pass_gather JPP((j_compress_ptr cinfo)); +#endif + + +/* + * Initialize for a Huffman-compressed scan. + * If gather_statistics is TRUE, we do not output anything during the scan, + * just count the Huffman symbols used and generate Huffman code tables. + */ + +METHODDEF(void) +start_pass_huff (j_compress_ptr cinfo, boolean gather_statistics) +{ + j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec; + lhuff_entropy_ptr entropy = (lhuff_entropy_ptr) losslsc->entropy_private; + int ci, dctbl, sampn, ptrn, yoffset, xoffset; + jpeg_component_info * compptr; + + if (gather_statistics) { +#ifdef ENTROPY_OPT_SUPPORTED + losslsc->entropy_encode_mcus = encode_mcus_gather; + losslsc->pub.entropy_finish_pass = finish_pass_gather; +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } else { + losslsc->entropy_encode_mcus = encode_mcus_huff; + losslsc->pub.entropy_finish_pass = finish_pass_huff; + } + + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + dctbl = compptr->dc_tbl_no; + if (gather_statistics) { +#ifdef ENTROPY_OPT_SUPPORTED + /* Check for invalid table indexes */ + /* (make_c_derived_tbl does this in the other path) */ + if (dctbl < 0 || dctbl >= NUM_HUFF_TBLS) + ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, dctbl); + /* Allocate and zero the statistics tables */ + /* Note that jpeg_gen_optimal_table expects 257 entries in each table! */ + if (entropy->count_ptrs[dctbl] == NULL) + entropy->count_ptrs[dctbl] = (long *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + 257 * SIZEOF(long)); + MEMZERO(entropy->count_ptrs[dctbl], 257 * SIZEOF(long)); +#endif + } else { + /* Compute derived values for Huffman tables */ + /* We may do this more than once for a table, but it's not expensive */ + jpeg_make_c_derived_tbl(cinfo, TRUE, dctbl, + & entropy->derived_tbls[dctbl]); + } + } + + /* Precalculate encoding info for each sample in an MCU of this scan */ + for (sampn = 0, ptrn = 0; sampn < cinfo->data_units_in_MCU;) { + compptr = cinfo->cur_comp_info[cinfo->MCU_membership[sampn]]; + ci = compptr->component_index; + /* ci = cinfo->MCU_membership[sampn]; + compptr = cinfo->cur_comp_info[ci];*/ + for (yoffset = 0; yoffset < compptr->MCU_height; yoffset++, ptrn++) { + /* Precalculate the setup info for each input pointer */ + entropy->input_ptr_info[ptrn].ci = ci; + entropy->input_ptr_info[ptrn].yoffset = yoffset; + entropy->input_ptr_info[ptrn].MCU_width = compptr->MCU_width; + for (xoffset = 0; xoffset < compptr->MCU_width; xoffset++, sampn++) { + /* Precalculate the input pointer index for each sample */ + entropy->input_ptr_index[sampn] = ptrn; + /* Precalculate which tables to use for each sample */ + entropy->cur_tbls[sampn] = entropy->derived_tbls[compptr->dc_tbl_no]; + entropy->cur_counts[sampn] = entropy->count_ptrs[compptr->dc_tbl_no]; + } + } + } + entropy->num_input_ptrs = ptrn; + + /* Initialize bit buffer to empty */ + entropy->saved.put_buffer = 0; + entropy->saved.put_bits = 0; + + /* Initialize restart stuff */ + entropy->restarts_to_go = cinfo->restart_interval; + entropy->next_restart_num = 0; +} + + +/* Outputting bytes to the file */ + +/* Emit a byte, taking 'action' if must suspend. */ +#define emit_byte(state,val,action) \ + { *(state)->next_output_byte++ = (JOCTET) (val); \ + if (--(state)->free_in_buffer == 0) \ + if (! dump_buffer(state)) \ + { action; } } + + +LOCAL(boolean) +dump_buffer (working_state * state) +/* Empty the output buffer; return TRUE if successful, FALSE if must suspend */ +{ + struct jpeg_destination_mgr * dest = state->cinfo->dest; + + if (! (*dest->empty_output_buffer) (state->cinfo)) + return FALSE; + /* After a successful buffer dump, must reset buffer pointers */ + state->next_output_byte = dest->next_output_byte; + state->free_in_buffer = dest->free_in_buffer; + return TRUE; +} + + +/* Outputting bits to the file */ + +/* Only the right 24 bits of put_buffer are used; the valid bits are + * left-justified in this part. At most 16 bits can be passed to emit_bits + * in one call, and we never retain more than 7 bits in put_buffer + * between calls, so 24 bits are sufficient. + */ + +INLINE +LOCAL(boolean) +emit_bits (working_state * state, unsigned int code, int size) +/* Emit some bits; return TRUE if successful, FALSE if must suspend */ +{ + /* This routine is heavily used, so it's worth coding tightly. */ + register IJG_INT32 put_buffer = (IJG_INT32) code; + register int put_bits = state->cur.put_bits; + + /* if size is 0, caller used an invalid Huffman table entry */ + if (size == 0) + ERREXIT(state->cinfo, JERR_HUFF_MISSING_CODE); + + put_buffer &= (((IJG_INT32) 1)<cur.put_buffer; /* and merge with old buffer contents */ + + while (put_bits >= 8) { + int c = (int) ((put_buffer >> 16) & 0xFF); + + emit_byte(state, c, return FALSE); + if (c == 0xFF) { /* need to stuff a zero byte? */ + emit_byte(state, 0, return FALSE); + } + put_buffer <<= 8; + put_bits -= 8; + } + + state->cur.put_buffer = put_buffer; /* update state variables */ + state->cur.put_bits = put_bits; + + return TRUE; +} + + +LOCAL(boolean) +flush_bits (working_state * state) +{ + if (! emit_bits(state, 0x7F, 7)) /* fill any partial byte with ones */ + return FALSE; + state->cur.put_buffer = 0; /* and reset bit-buffer to empty */ + state->cur.put_bits = 0; + return TRUE; +} + + +/* + * Emit a restart marker & resynchronize predictions. + */ + +LOCAL(boolean) +emit_restart (working_state * state, int restart_num) +{ + /* int ci; */ + + if (! flush_bits(state)) + return FALSE; + + emit_byte(state, 0xFF, return FALSE); + emit_byte(state, JPEG_RST0 + restart_num, return FALSE); + + /* The restart counter is not updated until we successfully write the MCU. */ + + return TRUE; +} + + +/* + * Encode and output one nMCU's worth of Huffman-compressed differences. + */ + +METHODDEF(JDIMENSION) +encode_mcus_huff (j_compress_ptr cinfo, JDIFFIMAGE diff_buf, + JDIMENSION MCU_row_num, JDIMENSION MCU_col_num, + JDIMENSION nMCU) +{ + j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec; + lhuff_entropy_ptr entropy = (lhuff_entropy_ptr) losslsc->entropy_private; + working_state state; + unsigned int mcu_num; + int sampn, ci, yoffset, MCU_width, ptrn; + /* jpeg_component_info * compptr; */ + + /* Load up working state */ + state.next_output_byte = cinfo->dest->next_output_byte; + state.free_in_buffer = cinfo->dest->free_in_buffer; + ASSIGN_STATE(state.cur, entropy->saved); + state.cinfo = cinfo; + + /* Emit restart marker if needed */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) + if (! emit_restart(&state, entropy->next_restart_num)) + return 0; + } + + /* Set input pointer locations based on MCU_col_num */ + for (ptrn = 0; ptrn < entropy->num_input_ptrs; ptrn++) { + ci = entropy->input_ptr_info[ptrn].ci; + yoffset = entropy->input_ptr_info[ptrn].yoffset; + MCU_width = entropy->input_ptr_info[ptrn].MCU_width; + entropy->input_ptr[ptrn] = + diff_buf[ci][MCU_row_num + (size_t)yoffset] + MCU_col_num * (size_t)MCU_width; + } + + for (mcu_num = 0; mcu_num < nMCU; mcu_num++) { + + /* Inner loop handles the samples in the MCU */ + for (sampn = 0; sampn < cinfo->data_units_in_MCU; sampn++) { + register int temp, temp2 /* , temp3 */ ; + register int nbits; + c_derived_tbl *dctbl = entropy->cur_tbls[sampn]; + + /* Encode the difference per section H.1.2.2 */ + + /* Input the sample difference */ + temp = *entropy->input_ptr[entropy->input_ptr_index[sampn]]++; + + if (temp & 0x8000) { /* instead of temp < 0 */ + temp = (-temp) & 0x7FFF; /* absolute value, mod 2^16 */ + if (temp == 0) /* special case: magnitude = 32768 */ + temp2 = temp = 0x8000; + temp2 = ~ temp; /* one's complement of magnitude */ + } else { + temp &= 0x7FFF; /* abs value mod 2^16 */ + temp2 = temp; /* magnitude */ + } + + /* Find the number of bits needed for the magnitude of the difference */ + nbits = 0; + while (temp) { + nbits++; + temp >>= 1; + } + /* Check for out-of-range difference values. + */ + if (nbits > MAX_DIFF_BITS) + ERREXIT(cinfo, JERR_BAD_DIFF); + + /* Emit the Huffman-coded symbol for the number of bits */ + if (! emit_bits(&state, dctbl->ehufco[nbits], dctbl->ehufsi[nbits])) + return mcu_num; + + /* Emit that number of bits of the value, if positive, */ + /* or the complement of its magnitude, if negative. */ + if (nbits && /* emit_bits rejects calls with size 0 */ + nbits != 16) /* special case: no bits should be emitted */ + if (! emit_bits(&state, (unsigned int) temp2, nbits)) + return mcu_num; + } + + /* Completed MCU, so update state */ + cinfo->dest->next_output_byte = state.next_output_byte; + cinfo->dest->free_in_buffer = state.free_in_buffer; + ASSIGN_STATE(entropy->saved, state.cur); + + /* Update restart-interval state too */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) { + entropy->restarts_to_go = cinfo->restart_interval; + entropy->next_restart_num++; + entropy->next_restart_num &= 7; + } + entropy->restarts_to_go--; + } + + } + + return nMCU; +} + + +/* + * Finish up at the end of a Huffman-compressed scan. + */ + +METHODDEF(void) +finish_pass_huff (j_compress_ptr cinfo) +{ + j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec; + lhuff_entropy_ptr entropy = (lhuff_entropy_ptr) losslsc->entropy_private; + working_state state; + + /* Load up working state ... flush_bits needs it */ + state.next_output_byte = cinfo->dest->next_output_byte; + state.free_in_buffer = cinfo->dest->free_in_buffer; + ASSIGN_STATE(state.cur, entropy->saved); + state.cinfo = cinfo; + + /* Flush out the last data */ + if (! flush_bits(&state)) + ERREXIT(cinfo, JERR_CANT_SUSPEND); + + /* Update state */ + cinfo->dest->next_output_byte = state.next_output_byte; + cinfo->dest->free_in_buffer = state.free_in_buffer; + ASSIGN_STATE(entropy->saved, state.cur); +} + + +/* + * Huffman coding optimization. + * + * We first scan the supplied data and count the number of uses of each symbol + * that is to be Huffman-coded. (This process MUST agree with the code above.) + * Then we build a Huffman coding tree for the observed counts. + * Symbols which are not needed at all for the particular image are not + * assigned any code, which saves space in the DHT marker as well as in + * the compressed data. + */ + +#ifdef ENTROPY_OPT_SUPPORTED + +/* + * Trial-encode one nMCU's worth of Huffman-compressed differences. + * No data is actually output, so no suspension return is possible. + */ + +METHODDEF(JDIMENSION) +encode_mcus_gather (j_compress_ptr cinfo, JDIFFIMAGE diff_buf, + JDIMENSION MCU_row_num, JDIMENSION MCU_col_num, + JDIMENSION nMCU) +{ + j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec; + lhuff_entropy_ptr entropy = (lhuff_entropy_ptr) losslsc->entropy_private; + unsigned int mcu_num; + int sampn, ci, yoffset, MCU_width, ptrn; + /* jpeg_component_info * compptr; */ + + /* Take care of restart intervals if needed */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) { + /* Update restart state */ + entropy->restarts_to_go = cinfo->restart_interval; + } + entropy->restarts_to_go--; + } + + /* Set input pointer locations based on MCU_col_num */ + for (ptrn = 0; ptrn < entropy->num_input_ptrs; ptrn++) { + ci = entropy->input_ptr_info[ptrn].ci; + yoffset = entropy->input_ptr_info[ptrn].yoffset; + MCU_width = entropy->input_ptr_info[ptrn].MCU_width; + entropy->input_ptr[ptrn] = + diff_buf[ci][MCU_row_num + (size_t)yoffset] + MCU_col_num * (size_t)MCU_width; + } + + for (mcu_num = 0; mcu_num < nMCU; mcu_num++) { + + /* Inner loop handles the samples in the MCU */ + for (sampn = 0; sampn < cinfo->data_units_in_MCU; sampn++) { + register int temp; + register int nbits; + /* c_derived_tbl *dctbl = entropy->cur_tbls[sampn]; */ + long * counts = entropy->cur_counts[sampn]; + + /* Encode the difference per section H.1.2.2 */ + + /* Input the sample difference */ + temp = *entropy->input_ptr[entropy->input_ptr_index[sampn]]++; + + if (temp & 0x8000) { /* instead of temp < 0 */ + temp = (-temp) & 0x7FFF; /* absolute value, mod 2^16 */ + if (temp == 0) /* special case: magnitude = 32768 */ + temp = 0x8000; + } else + temp &= 0x7FFF; /* abs value mod 2^16 */ + + /* Find the number of bits needed for the magnitude of the difference */ + nbits = 0; + while (temp) { + nbits++; + temp >>= 1; + } + /* Check for out-of-range difference values. + */ + if (nbits > MAX_DIFF_BITS) + ERREXIT(cinfo, JERR_BAD_DIFF); + + /* Count the Huffman symbol for the number of bits */ + counts[nbits]++; + } + } + + return nMCU; +} + + +/* + * Finish up a statistics-gathering pass and create the new Huffman tables. + */ + +METHODDEF(void) +finish_pass_gather (j_compress_ptr cinfo) +{ + j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec; + lhuff_entropy_ptr entropy = (lhuff_entropy_ptr) losslsc->entropy_private; + int ci, dctbl; + jpeg_component_info * compptr; + JHUFF_TBL **htblptr; + boolean did_dc[NUM_HUFF_TBLS]; + + /* It's important not to apply jpeg_gen_optimal_table more than once + * per table, because it clobbers the input frequency counts! + */ + MEMZERO(did_dc, SIZEOF(did_dc)); + + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + dctbl = compptr->dc_tbl_no; + if (! did_dc[dctbl]) { + htblptr = & cinfo->dc_huff_tbl_ptrs[dctbl]; + if (*htblptr == NULL) + *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo); + jpeg_gen_optimal_table(cinfo, *htblptr, entropy->count_ptrs[dctbl]); + did_dc[dctbl] = TRUE; + } + } +} + + +#endif /* ENTROPY_OPT_SUPPORTED */ + + +METHODDEF(boolean) +need_optimization_pass (j_compress_ptr cinfo) +{ + return TRUE; +} + + +/* + * Module initialization routine for Huffman entropy encoding. + */ + +GLOBAL(void) +jinit_lhuff_encoder (j_compress_ptr cinfo) +{ + j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec; + lhuff_entropy_ptr entropy; + int i; + + entropy = (lhuff_entropy_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(lhuff_entropy_encoder)); + losslsc->entropy_private = (struct jpeg_entropy_encoder *) entropy; + losslsc->pub.entropy_start_pass = start_pass_huff; + losslsc->pub.need_optimization_pass = need_optimization_pass; + + /* Mark tables unallocated */ + for (i = 0; i < NUM_HUFF_TBLS; i++) { + entropy->derived_tbls[i] = NULL; +#ifdef ENTROPY_OPT_SUPPORTED + entropy->count_ptrs[i] = NULL; +#endif + } +} diff --git a/dcmjpeg/libijg12/jclossls.c b/dcmjpeg/libijg12/jclossls.c new file mode 100644 index 00000000..a4394bcf --- /dev/null +++ b/dcmjpeg/libijg12/jclossls.c @@ -0,0 +1,82 @@ +/* + * jclossls.c + * + * Copyright (C) 1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains the control logic for the lossless JPEG compressor. + */ + +#define JPEG_INTERNALS +#include "jinclude12.h" +#include "jpeglib12.h" +#include "jlossls12.h" + + +#ifdef C_LOSSLESS_SUPPORTED + +/* + * Initialize for a processing pass. + */ + +METHODDEF(void) +start_pass (j_compress_ptr cinfo, J_BUF_MODE pass_mode) +{ + j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec; + + (*losslsc->scaler_start_pass) (cinfo); + (*losslsc->predict_start_pass) (cinfo); + (*losslsc->diff_start_pass) (cinfo, pass_mode); +} + + +/* + * Initialize the lossless compression codec. + * This is called only once, during master selection. + */ + +GLOBAL(void) +jinit_lossless_c_codec(j_compress_ptr cinfo) +{ + j_lossless_c_ptr losslsc; + + /* Create subobject in permanent pool */ + losslsc = (j_lossless_c_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, + SIZEOF(jpeg_lossless_c_codec)); + cinfo->codec = (struct jpeg_c_codec *) losslsc; + + /* Initialize sub-modules */ + + /* Scaler */ + jinit_c_scaler(cinfo); + + /* Differencer */ + jinit_differencer(cinfo); + + /* Entropy encoding: either Huffman or arithmetic coding. */ + if (cinfo->arith_code) { +#ifdef WITH_ARITHMETIC_PATCH + jinit_arith_encoder(cinfo); +#else + ERREXIT(cinfo, JERR_ARITH_NOTIMPL); +#endif + } else { + jinit_lhuff_encoder(cinfo); + } + + /* Need a full-image difference buffer in any multi-pass mode. */ + jinit_c_diff_controller(cinfo, + (boolean) (cinfo->num_scans > 1 || + cinfo->optimize_coding)); + + /* Initialize method pointers. + * + * Note: entropy_start_pass and entropy_finish_pass are assigned in + * jclhuff.c and compress_data is assigned in jcdiffct.c. + */ + losslsc->pub.start_pass = start_pass; +} + +#endif /* C_LOSSLESS_SUPPORTED */ diff --git a/dcmjpeg/libijg12/jclossy.c b/dcmjpeg/libijg12/jclossy.c new file mode 100644 index 00000000..08272cd9 --- /dev/null +++ b/dcmjpeg/libijg12/jclossy.c @@ -0,0 +1,76 @@ +/* + * jclossy.c + * + * Copyright (C) 1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains the control logic for the lossy JPEG compressor. + */ + +#define JPEG_INTERNALS +#include "jinclude12.h" +#include "jpeglib12.h" +#include "jlossy12.h" + + +/* + * Initialize for a processing pass. + */ + +METHODDEF(void) +start_pass (j_compress_ptr cinfo, J_BUF_MODE pass_mode) +{ + j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; + + (*lossyc->fdct_start_pass) (cinfo); + (*lossyc->coef_start_pass) (cinfo, pass_mode); +} + + +/* + * Initialize the lossy compression codec. + * This is called only once, during master selection. + */ + +GLOBAL(void) +jinit_lossy_c_codec (j_compress_ptr cinfo) +{ + j_lossy_c_ptr lossyc; + + /* Create subobject in permanent pool */ + lossyc = (j_lossy_c_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, + SIZEOF(jpeg_lossy_c_codec)); + cinfo->codec = (struct jpeg_c_codec *) lossyc; + + /* Initialize sub-modules */ + + /* Forward DCT */ + jinit_forward_dct(cinfo); + /* Entropy encoding: either Huffman or arithmetic coding. */ + if (cinfo->arith_code) { + ERREXIT(cinfo, JERR_ARITH_NOTIMPL); + } else { + if (cinfo->process == JPROC_PROGRESSIVE) { +#ifdef C_PROGRESSIVE_SUPPORTED + jinit_phuff_encoder(cinfo); +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } else + jinit_shuff_encoder(cinfo); + } + + /* Need a full-image coefficient buffer in any multi-pass mode. */ + jinit_c_coef_controller(cinfo, + (boolean) (cinfo->num_scans > 1 || + cinfo->optimize_coding)); + + /* Initialize method pointers. + * + * Note: entropy_start_pass and entropy_finish_pass are assigned in + * jcshuff.c or jcphuff.c and compress_data is assigned in jccoefct.c. + */ + lossyc->pub.start_pass = start_pass; +} diff --git a/dcmjpeg/libijg12/jcmainct.c b/dcmjpeg/libijg12/jcmainct.c new file mode 100644 index 00000000..b9866560 --- /dev/null +++ b/dcmjpeg/libijg12/jcmainct.c @@ -0,0 +1,296 @@ +/* + * jcmainct.c + * + * Copyright (C) 1994-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains the main buffer controller for compression. + * The main buffer lies between the pre-processor and the JPEG + * compressor proper; it holds downsampled data in the JPEG colorspace. + */ + +#define JPEG_INTERNALS +#include "jinclude12.h" +#include "jpeglib12.h" + + +/* Note: currently, there is no operating mode in which a full-image buffer + * is needed at this step. If there were, that mode could not be used with + * "raw data" input, since this module is bypassed in that case. However, + * we've left the code here for possible use in special applications. + */ +#undef FULL_MAIN_BUFFER_SUPPORTED + + +/* Private buffer controller object */ + +typedef struct { + struct jpeg_c_main_controller pub; /* public fields */ + + JDIMENSION cur_iMCU_row; /* number of current iMCU row */ + JDIMENSION rowgroup_ctr; /* counts row groups received in iMCU row */ + boolean suspended; /* remember if we suspended output */ + J_BUF_MODE pass_mode; /* current operating mode */ + + /* If using just a strip buffer, this points to the entire set of buffers + * (we allocate one for each component). In the full-image case, this + * points to the currently accessible strips of the virtual arrays. + */ + JSAMPARRAY buffer[MAX_COMPONENTS]; + +#ifdef FULL_MAIN_BUFFER_SUPPORTED + /* If using full-image storage, this array holds pointers to virtual-array + * control blocks for each component. Unused if not full-image storage. + */ + jvirt_sarray_ptr whole_image[MAX_COMPONENTS]; +#endif +} my_main_controller; + +typedef my_main_controller * my_main_ptr; + + +/* Forward declarations */ +METHODDEF(void) process_data_simple_main + JPP((j_compress_ptr cinfo, JSAMPARRAY input_buf, + JDIMENSION *in_row_ctr, JDIMENSION in_rows_avail)); +#ifdef FULL_MAIN_BUFFER_SUPPORTED +METHODDEF(void) process_data_buffer_main + JPP((j_compress_ptr cinfo, JSAMPARRAY input_buf, + JDIMENSION *in_row_ctr, JDIMENSION in_rows_avail)); +#endif + + +/* + * Initialize for a processing pass. + */ + +METHODDEF(void) +start_pass_main (j_compress_ptr cinfo, J_BUF_MODE pass_mode) +{ + my_main_ptr mymain = (my_main_ptr) cinfo->main; + + /* Do nothing in raw-data mode. */ + if (cinfo->raw_data_in) + return; + + mymain->cur_iMCU_row = 0; /* initialize counters */ + mymain->rowgroup_ctr = 0; + mymain->suspended = FALSE; + mymain->pass_mode = pass_mode; /* save mode for use by process_data */ + + switch (pass_mode) { + case JBUF_PASS_THRU: +#ifdef FULL_MAIN_BUFFER_SUPPORTED + if (mymain->whole_image[0] != NULL) + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); +#endif + mymain->pub.process_data = process_data_simple_main; + break; +#ifdef FULL_MAIN_BUFFER_SUPPORTED + case JBUF_SAVE_SOURCE: + case JBUF_CRANK_DEST: + case JBUF_SAVE_AND_PASS: + if (mymain->whole_image[0] == NULL) + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + mymain->pub.process_data = process_data_buffer_main; + break; +#endif + default: + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + break; + } +} + + +/* + * Process some data. + * This routine handles the simple pass-through mode, + * where we have only a strip buffer. + */ + +METHODDEF(void) +process_data_simple_main (j_compress_ptr cinfo, + JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, + JDIMENSION in_rows_avail) +{ + my_main_ptr mymain = (my_main_ptr) cinfo->main; + JDIMENSION data_unit = (JDIMENSION)(cinfo->data_unit); + + while (mymain->cur_iMCU_row < cinfo->total_iMCU_rows) { + /* Read input data if we haven't filled the main buffer yet */ + if (mymain->rowgroup_ctr < data_unit) + (*cinfo->prep->pre_process_data) (cinfo, + input_buf, in_row_ctr, in_rows_avail, + mymain->buffer, &mymain->rowgroup_ctr, + (JDIMENSION) data_unit); + + /* If we don't have a full iMCU row buffered, return to application for + * more data. Note that preprocessor will always pad to fill the iMCU row + * at the bottom of the image. + */ + if (mymain->rowgroup_ctr != data_unit) + return; + + /* Send the completed row to the compressor */ + if (! (*cinfo->codec->compress_data) (cinfo, mymain->buffer)) { + /* If compressor did not consume the whole row, then we must need to + * suspend processing and return to the application. In this situation + * we pretend we didn't yet consume the last input row; otherwise, if + * it happened to be the last row of the image, the application would + * think we were done. + */ + if (! mymain->suspended) { + (*in_row_ctr)--; + mymain->suspended = TRUE; + } + return; + } + /* We did finish the row. Undo our little suspension hack if a previous + * call suspended; then mark the main buffer empty. + */ + if (mymain->suspended) { + (*in_row_ctr)++; + mymain->suspended = FALSE; + } + mymain->rowgroup_ctr = 0; + mymain->cur_iMCU_row++; + } +} + + +#ifdef FULL_MAIN_BUFFER_SUPPORTED + +/* + * Process some data. + * This routine handles all of the modes that use a full-size buffer. + */ + +METHODDEF(void) +process_data_buffer_main (j_compress_ptr cinfo, + JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, + JDIMENSION in_rows_avail) +{ + my_main_ptr mymain = (my_main_ptr) cinfo->main; + int ci; + jpeg_component_info *compptr; + boolean writing = (mymain->pass_mode != JBUF_CRANK_DEST); + JDIMENSION data_unit = (JDIMENSION)(cinfo->data_unit); + + while (mymain->cur_iMCU_row < cinfo->total_iMCU_rows) { + /* Realign the virtual buffers if at the start of an iMCU row. */ + if (mymain->rowgroup_ctr == 0) { + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + mymain->buffer[ci] = (*cinfo->mem->access_virt_sarray) + ((j_common_ptr) cinfo, mymain->whole_image[ci], + mymain->cur_iMCU_row * (compptr->v_samp_factor * data_unit), + (JDIMENSION) (compptr->v_samp_factor * data_unit), writing); + } + /* In a read pass, pretend we just read some source data. */ + if (! writing) { + *in_row_ctr += cinfo->max_v_samp_factor * data_unit; + mymain->rowgroup_ctr = data_unit; + } + } + + /* If a write pass, read input data until the current iMCU row is full. */ + /* Note: preprocessor will pad if necessary to fill the last iMCU row. */ + if (writing) { + (*cinfo->prep->pre_process_data) (cinfo, + input_buf, in_row_ctr, in_rows_avail, + mymain->buffer, &mymain->rowgroup_ctr, + (JDIMENSION) data_unit); + /* Return to application if we need more data to fill the iMCU row. */ + if (mymain->rowgroup_ctr < data_unit) + return; + } + + /* Emit data, unless this is a sink-only pass. */ + if (mymain->pass_mode != JBUF_SAVE_SOURCE) { + if (! (*cinfo->codec->compress_data) (cinfo, mymain->buffer)) { + /* If compressor did not consume the whole row, then we must need to + * suspend processing and return to the application. In this situation + * we pretend we didn't yet consume the last input row; otherwise, if + * it happened to be the last row of the image, the application would + * think we were done. + */ + if (! mymain->suspended) { + (*in_row_ctr)--; + mymain->suspended = TRUE; + } + return; + } + /* We did finish the row. Undo our little suspension hack if a previous + * call suspended; then mark the main buffer empty. + */ + if (mymain->suspended) { + (*in_row_ctr)++; + mymain->suspended = FALSE; + } + } + + /* If get here, we are done with this iMCU row. Mark buffer empty. */ + mymain->rowgroup_ctr = 0; + mymain->cur_iMCU_row++; + } +} + +#endif /* FULL_MAIN_BUFFER_SUPPORTED */ + + +/* + * Initialize main buffer controller. + */ + +GLOBAL(void) +jinit_c_main_controller (j_compress_ptr cinfo, boolean need_full_buffer) +{ + my_main_ptr mymain; + int ci; + jpeg_component_info *compptr; + int data_unit = cinfo->data_unit; + + mymain = (my_main_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_main_controller)); + cinfo->main = (struct jpeg_c_main_controller *) mymain; + mymain->pub.start_pass = start_pass_main; + + /* We don't need to create a buffer in raw-data mode. */ + if (cinfo->raw_data_in) + return; + + /* Create the buffer. It holds downsampled data, so each component + * may be of a different size. + */ + if (need_full_buffer) { +#ifdef FULL_MAIN_BUFFER_SUPPORTED + /* Allocate a full-image virtual array for each component */ + /* Note we pad the bottom to a multiple of the iMCU height */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + mymain->whole_image[ci] = (*cinfo->mem->request_virt_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE, + compptr->width_in_data_units * data_unit, + (JDIMENSION) jround_up((long) compptr->height_in_data_units, + (long) compptr->v_samp_factor) * data_unit, + (JDIMENSION) (compptr->v_samp_factor * data_unit)); + } +#else + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); +#endif + } else { +#ifdef FULL_MAIN_BUFFER_SUPPORTED + mymain->whole_image[0] = NULL; /* flag for no virtual arrays */ +#endif + /* Allocate a strip buffer for each component */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + mymain->buffer[ci] = (*cinfo->mem->alloc_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + compptr->width_in_data_units * (JDIMENSION)data_unit, + (JDIMENSION) (compptr->v_samp_factor * data_unit)); + } + } +} diff --git a/dcmjpeg/libijg12/jcmarker.c b/dcmjpeg/libijg12/jcmarker.c new file mode 100644 index 00000000..deb05963 --- /dev/null +++ b/dcmjpeg/libijg12/jcmarker.c @@ -0,0 +1,680 @@ +/* + * jcmarker.c + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains routines to write JPEG datastream markers. + */ + +#define JPEG_INTERNALS +#include "jinclude12.h" +#include "jpeglib12.h" + + +typedef enum { /* JPEG marker codes */ + M_SOF0 = 0xc0, + M_SOF1 = 0xc1, + M_SOF2 = 0xc2, + M_SOF3 = 0xc3, + + M_SOF5 = 0xc5, + M_SOF6 = 0xc6, + M_SOF7 = 0xc7, + + M_JPG = 0xc8, + M_SOF9 = 0xc9, + M_SOF10 = 0xca, + M_SOF11 = 0xcb, + + M_SOF13 = 0xcd, + M_SOF14 = 0xce, + M_SOF15 = 0xcf, + + M_DHT = 0xc4, + + M_DAC = 0xcc, + + M_RST0 = 0xd0, + M_RST1 = 0xd1, + M_RST2 = 0xd2, + M_RST3 = 0xd3, + M_RST4 = 0xd4, + M_RST5 = 0xd5, + M_RST6 = 0xd6, + M_RST7 = 0xd7, + + M_SOI = 0xd8, + M_EOI = 0xd9, + M_SOS = 0xda, + M_DQT = 0xdb, + M_DNL = 0xdc, + M_DRI = 0xdd, + M_DHP = 0xde, + M_EXP = 0xdf, + + M_APP0 = 0xe0, + M_APP1 = 0xe1, + M_APP2 = 0xe2, + M_APP3 = 0xe3, + M_APP4 = 0xe4, + M_APP5 = 0xe5, + M_APP6 = 0xe6, + M_APP7 = 0xe7, + M_APP8 = 0xe8, + M_APP9 = 0xe9, + M_APP10 = 0xea, + M_APP11 = 0xeb, + M_APP12 = 0xec, + M_APP13 = 0xed, + M_APP14 = 0xee, + M_APP15 = 0xef, + + M_JPG0 = 0xf0, + M_JPG13 = 0xfd, + M_COM = 0xfe, + + M_TEM = 0x01, + + M_ERROR = 0x100 +} JPEG_MARKER; + + +/* Private state */ + +typedef struct { + struct jpeg_marker_writer pub; /* public fields */ + + unsigned int last_restart_interval; /* last DRI value emitted; 0 after SOI */ +} my_marker_writer; + +typedef my_marker_writer * my_marker_ptr; + + +/* + * Basic output routines. + * + * Note that we do not support suspension while writing a marker. + * Therefore, an application using suspension must ensure that there is + * enough buffer space for the initial markers (typ. 600-700 bytes) before + * calling jpeg_start_compress, and enough space to write the trailing EOI + * (a few bytes) before calling jpeg_finish_compress. Multipass compression + * modes are not supported at all with suspension, so those two are the only + * points where markers will be written. + */ + +LOCAL(void) +emit_byte (j_compress_ptr cinfo, int val) +/* Emit a byte */ +{ + struct jpeg_destination_mgr * dest = cinfo->dest; + + *(dest->next_output_byte)++ = (JOCTET) val; + if (--dest->free_in_buffer == 0) { + if (! (*dest->empty_output_buffer) (cinfo)) + ERREXIT(cinfo, JERR_CANT_SUSPEND); + } +} + + +LOCAL(void) +emit_marker (j_compress_ptr cinfo, JPEG_MARKER mark) +/* Emit a marker code */ +{ + emit_byte(cinfo, 0xFF); + emit_byte(cinfo, (int) mark); +} + + +LOCAL(void) +emit_2bytes (j_compress_ptr cinfo, int value) +/* Emit a 2-byte integer; these are always MSB first in JPEG files */ +{ + emit_byte(cinfo, (value >> 8) & 0xFF); + emit_byte(cinfo, value & 0xFF); +} + + +/* + * Routines to write specific marker types. + */ + +LOCAL(int) +emit_dqt (j_compress_ptr cinfo, int idx) +/* Emit a DQT marker */ +/* Returns the precision used (0 = 8bits, 1 = 16bits) for baseline checking */ +{ + JQUANT_TBL * qtbl = cinfo->quant_tbl_ptrs[idx]; + int prec; + int i; + + if (qtbl == NULL) + ERREXIT1(cinfo, JERR_NO_QUANT_TABLE, idx); + + prec = 0; + for (i = 0; i < DCTSIZE2; i++) { + if (qtbl->quantval[i] > 255) + prec = 1; + } + + if (! qtbl->sent_table) { + emit_marker(cinfo, M_DQT); + + emit_2bytes(cinfo, prec ? DCTSIZE2*2 + 1 + 2 : DCTSIZE2 + 1 + 2); + + emit_byte(cinfo, idx + (prec<<4)); + + for (i = 0; i < DCTSIZE2; i++) { + /* The table entries must be emitted in zigzag order. */ + unsigned int qval = qtbl->quantval[jpeg_natural_order[i]]; + if (prec) + emit_byte(cinfo, (int) (qval >> 8)); + emit_byte(cinfo, (int) (qval & 0xFF)); + } + + qtbl->sent_table = TRUE; + } + + return prec; +} + + +LOCAL(void) +emit_dht (j_compress_ptr cinfo, int idx, boolean is_ac) +/* Emit a DHT marker */ +{ + JHUFF_TBL * htbl; + int length, i; + + if (is_ac) { + htbl = cinfo->ac_huff_tbl_ptrs[idx]; + idx += 0x10; /* output index has AC bit set */ + } else { + htbl = cinfo->dc_huff_tbl_ptrs[idx]; + } + + if (htbl == NULL) + ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, idx); + + if (! htbl->sent_table) { + emit_marker(cinfo, M_DHT); + + length = 0; + for (i = 1; i <= 16; i++) + length += htbl->bits[i]; + + emit_2bytes(cinfo, length + 2 + 1 + 16); + emit_byte(cinfo, idx); + + for (i = 1; i <= 16; i++) + emit_byte(cinfo, htbl->bits[i]); + + for (i = 0; i < length; i++) + emit_byte(cinfo, htbl->huffval[i]); + + htbl->sent_table = TRUE; + } +} + + +LOCAL(void) +emit_dac (j_compress_ptr cinfo) +/* Emit a DAC marker */ +/* Since the useful info is so small, we want to emit all the tables in */ +/* one DAC marker. Therefore this routine does its own scan of the table. */ +{ +#ifdef C_ARITH_CODING_SUPPORTED + char dc_in_use[NUM_ARITH_TBLS]; + char ac_in_use[NUM_ARITH_TBLS]; + int length, i; + jpeg_component_info *compptr; + + for (i = 0; i < NUM_ARITH_TBLS; i++) + dc_in_use[i] = ac_in_use[i] = 0; + + for (i = 0; i < cinfo->comps_in_scan; i++) { + compptr = cinfo->cur_comp_info[i]; + dc_in_use[compptr->dc_tbl_no] = 1; + ac_in_use[compptr->ac_tbl_no] = 1; + } + + length = 0; + for (i = 0; i < NUM_ARITH_TBLS; i++) + length += dc_in_use[i] + ac_in_use[i]; + + emit_marker(cinfo, M_DAC); + + emit_2bytes(cinfo, length*2 + 2); + + for (i = 0; i < NUM_ARITH_TBLS; i++) { + if (dc_in_use[i]) { + emit_byte(cinfo, i); + emit_byte(cinfo, cinfo->arith_dc_L[i] + (cinfo->arith_dc_U[i]<<4)); + } + if (ac_in_use[i]) { + emit_byte(cinfo, i + 0x10); + emit_byte(cinfo, cinfo->arith_ac_K[i]); + } + } +#endif /* C_ARITH_CODING_SUPPORTED */ +} + + +LOCAL(void) +emit_dri (j_compress_ptr cinfo) +/* Emit a DRI marker */ +{ + emit_marker(cinfo, M_DRI); + + emit_2bytes(cinfo, 4); /* fixed length */ + + emit_2bytes(cinfo, (int) cinfo->restart_interval); +} + + +LOCAL(void) +emit_sof (j_compress_ptr cinfo, JPEG_MARKER code) +/* Emit a SOF marker */ +{ + int ci; + jpeg_component_info *compptr; + + emit_marker(cinfo, code); + + emit_2bytes(cinfo, 3 * cinfo->num_components + 2 + 5 + 1); /* length */ + + /* Make sure image isn't bigger than SOF field can handle */ + if ((long) cinfo->image_height > 65535L || + (long) cinfo->image_width > 65535L) + ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, (unsigned int) 65535); + + emit_byte(cinfo, cinfo->data_precision); + emit_2bytes(cinfo, (int) cinfo->image_height); + emit_2bytes(cinfo, (int) cinfo->image_width); + + emit_byte(cinfo, cinfo->num_components); + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + emit_byte(cinfo, compptr->component_id); + emit_byte(cinfo, (compptr->h_samp_factor << 4) + compptr->v_samp_factor); + emit_byte(cinfo, compptr->quant_tbl_no); + } +} + + +LOCAL(void) +emit_sos (j_compress_ptr cinfo) +/* Emit a SOS marker */ +{ + int i, td, ta; + jpeg_component_info *compptr; + + emit_marker(cinfo, M_SOS); + + emit_2bytes(cinfo, 2 * cinfo->comps_in_scan + 2 + 1 + 3); /* length */ + + emit_byte(cinfo, cinfo->comps_in_scan); + + for (i = 0; i < cinfo->comps_in_scan; i++) { + compptr = cinfo->cur_comp_info[i]; + emit_byte(cinfo, compptr->component_id); + td = compptr->dc_tbl_no; + ta = compptr->ac_tbl_no; + if (cinfo->process == JPROC_PROGRESSIVE) { + /* Progressive mode: only DC or only AC tables are used in one scan; + * furthermore, Huffman coding of DC refinement uses no table at all. + * We emit 0 for unused field(s); this is recommended by the P&M text + * but does not seem to be specified in the standard. + */ + if (cinfo->Ss == 0) { + ta = 0; /* DC scan */ + if (cinfo->Ah != 0 && !cinfo->arith_code) + td = 0; /* no DC table either */ + } else { + td = 0; /* AC scan */ + } + } + emit_byte(cinfo, (td << 4) + ta); + } + + emit_byte(cinfo, cinfo->Ss); + emit_byte(cinfo, cinfo->Se); + emit_byte(cinfo, (cinfo->Ah << 4) + cinfo->Al); +} + + +LOCAL(void) +emit_jfif_app0 (j_compress_ptr cinfo) +/* Emit a JFIF-compliant APP0 marker */ +{ + /* + * Length of APP0 block (2 bytes) + * Block ID (4 bytes - ASCII "JFIF") + * Zero byte (1 byte to terminate the ID string) + * Version Major, Minor (2 bytes - major first) + * Units (1 byte - 0x00 = none, 0x01 = inch, 0x02 = cm) + * Xdpu (2 bytes - dots per unit horizontal) + * Ydpu (2 bytes - dots per unit vertical) + * Thumbnail X size (1 byte) + * Thumbnail Y size (1 byte) + */ + + emit_marker(cinfo, M_APP0); + + emit_2bytes(cinfo, 2 + 4 + 1 + 2 + 1 + 2 + 2 + 1 + 1); /* length */ + + emit_byte(cinfo, 0x4A); /* Identifier: ASCII "JFIF" */ + emit_byte(cinfo, 0x46); + emit_byte(cinfo, 0x49); + emit_byte(cinfo, 0x46); + emit_byte(cinfo, 0); + emit_byte(cinfo, cinfo->JFIF_major_version); /* Version fields */ + emit_byte(cinfo, cinfo->JFIF_minor_version); + emit_byte(cinfo, cinfo->density_unit); /* Pixel size information */ + emit_2bytes(cinfo, (int) cinfo->X_density); + emit_2bytes(cinfo, (int) cinfo->Y_density); + emit_byte(cinfo, 0); /* No thumbnail image */ + emit_byte(cinfo, 0); +} + + +LOCAL(void) +emit_adobe_app14 (j_compress_ptr cinfo) +/* Emit an Adobe APP14 marker */ +{ + /* + * Length of APP14 block (2 bytes) + * Block ID (5 bytes - ASCII "Adobe") + * Version Number (2 bytes - currently 100) + * Flags0 (2 bytes - currently 0) + * Flags1 (2 bytes - currently 0) + * Color transform (1 byte) + * + * Although Adobe TN 5116 mentions Version = 101, all the Adobe files + * now in circulation seem to use Version = 100, so that's what we write. + * + * We write the color transform byte as 1 if the JPEG color space is + * YCbCr, 2 if it's YCCK, 0 otherwise. Adobe's definition has to do with + * whether the encoder performed a transformation, which is pretty useless. + */ + + emit_marker(cinfo, M_APP14); + + emit_2bytes(cinfo, 2 + 5 + 2 + 2 + 2 + 1); /* length */ + + emit_byte(cinfo, 0x41); /* Identifier: ASCII "Adobe" */ + emit_byte(cinfo, 0x64); + emit_byte(cinfo, 0x6F); + emit_byte(cinfo, 0x62); + emit_byte(cinfo, 0x65); + emit_2bytes(cinfo, 100); /* Version */ + emit_2bytes(cinfo, 0); /* Flags0 */ + emit_2bytes(cinfo, 0); /* Flags1 */ + switch (cinfo->jpeg_color_space) { + case JCS_YCbCr: + emit_byte(cinfo, 1); /* Color transform = 1 */ + break; + case JCS_YCCK: + emit_byte(cinfo, 2); /* Color transform = 2 */ + break; + default: + emit_byte(cinfo, 0); /* Color transform = 0 */ + break; + } +} + + +/* + * These routines allow writing an arbitrary marker with parameters. + * The only intended use is to emit COM or APPn markers after calling + * write_file_header and before calling write_frame_header. + * Other uses are not guaranteed to produce desirable results. + * Counting the parameter bytes properly is the caller's responsibility. + */ + +METHODDEF(void) +write_marker_header (j_compress_ptr cinfo, int marker, unsigned int datalen) +/* Emit an arbitrary marker header */ +{ + if (datalen > (unsigned int) 65533) /* safety check */ + ERREXIT(cinfo, JERR_BAD_LENGTH); + + emit_marker(cinfo, (JPEG_MARKER) marker); + + emit_2bytes(cinfo, (int) (datalen + 2)); /* total length */ +} + +METHODDEF(void) +write_marker_byte (j_compress_ptr cinfo, int val) +/* Emit one byte of marker parameters following write_marker_header */ +{ + emit_byte(cinfo, val); +} + + +/* + * Write datastream header. + * This consists of an SOI and optional APPn markers. + * We recommend use of the JFIF marker, but not the Adobe marker, + * when using YCbCr or grayscale data. The JFIF marker should NOT + * be used for any other JPEG colorspace. The Adobe marker is helpful + * to distinguish RGB, CMYK, and YCCK colorspaces. + * Note that an application can write additional header markers after + * jpeg_start_compress returns. + */ + +METHODDEF(void) +write_file_header (j_compress_ptr cinfo) +{ + my_marker_ptr marker = (my_marker_ptr) cinfo->marker; + + emit_marker(cinfo, M_SOI); /* first the SOI */ + + /* SOI is defined to reset restart interval to 0 */ + marker->last_restart_interval = 0; + + if (cinfo->write_JFIF_header) /* next an optional JFIF APP0 */ + emit_jfif_app0(cinfo); + if (cinfo->write_Adobe_marker) /* next an optional Adobe APP14 */ + emit_adobe_app14(cinfo); +} + + +/* + * Write frame header. + * This consists of DQT and SOFn markers. + * Note that we do not emit the SOF until we have emitted the DQT(s). + * This avoids compatibility problems with incorrect implementations that + * try to error-check the quant table numbers as soon as they see the SOF. + */ + +METHODDEF(void) +write_frame_header (j_compress_ptr cinfo) +{ + int ci, prec; + boolean is_baseline; + jpeg_component_info *compptr; + + prec = 0; + if (cinfo->process != JPROC_LOSSLESS) { + /* Emit DQT for each quantization table. + * Note that emit_dqt() suppresses any duplicate tables. + */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + prec += emit_dqt(cinfo, compptr->quant_tbl_no); + } + /* now prec is nonzero iff there are any 16-bit quant tables. */ + } + + /* Check for a non-baseline specification. + * Note we assume that Huffman table numbers won't be changed later. + */ + if (cinfo->arith_code || cinfo->process != JPROC_SEQUENTIAL || + cinfo->data_precision != 8) { + is_baseline = FALSE; + } else { + is_baseline = TRUE; + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + if (compptr->dc_tbl_no > 1 || compptr->ac_tbl_no > 1) + is_baseline = FALSE; + } + if (prec && is_baseline) { + is_baseline = FALSE; + /* If it's baseline except for quantizer size, warn the user */ + TRACEMS(cinfo, 0, JTRC_16BIT_TABLES); + } + } + + /* Emit the proper SOF marker */ + if (cinfo->arith_code) { +#ifdef WITH_ARITHMETIC_PATCH + if (cinfo->process == JPROC_PROGRESSIVE) + emit_sof(cinfo, M_SOF10); /* SOF code for progressive arithmetic */ + else if (cinfo->process == JPROC_LOSSLESS) + emit_sof(cinfo, M_SOF11); /* SOF code for lossless arithmetic */ + else + emit_sof(cinfo, M_SOF9); /* SOF code for sequential arithmetic */ +#else + emit_sof(cinfo, M_SOF9); /* SOF code for arithmetic coding */ +#endif + } else { + if (cinfo->process == JPROC_PROGRESSIVE) + emit_sof(cinfo, M_SOF2); /* SOF code for progressive Huffman */ + else if (cinfo->process == JPROC_LOSSLESS) + emit_sof(cinfo, M_SOF3); /* SOF code for lossless Huffman */ + else if (is_baseline) + emit_sof(cinfo, M_SOF0); /* SOF code for baseline implementation */ + else + emit_sof(cinfo, M_SOF1); /* SOF code for non-baseline Huffman file */ + } +} + + +/* + * Write scan header. + * This consists of DHT or DAC markers, optional DRI, and SOS. + * Compressed data will be written following the SOS. + */ + +METHODDEF(void) +write_scan_header (j_compress_ptr cinfo) +{ + my_marker_ptr marker = (my_marker_ptr) cinfo->marker; + int i; + jpeg_component_info *compptr; + + if (cinfo->arith_code) { + /* Emit arith conditioning info. We may have some duplication + * if the file has multiple scans, but it's so small it's hardly + * worth worrying about. + */ + emit_dac(cinfo); + } else { + /* Emit Huffman tables. + * Note that emit_dht() suppresses any duplicate tables. + */ + for (i = 0; i < cinfo->comps_in_scan; i++) { + compptr = cinfo->cur_comp_info[i]; + if (cinfo->process == JPROC_PROGRESSIVE) { + /* Progressive mode: only DC or only AC tables are used in one scan */ + if (cinfo->Ss == 0) { + if (cinfo->Ah == 0) /* DC needs no table for refinement scan */ + emit_dht(cinfo, compptr->dc_tbl_no, FALSE); + } else { + emit_dht(cinfo, compptr->ac_tbl_no, TRUE); + } + } else if (cinfo->process == JPROC_LOSSLESS) { + /* Lossless mode: only DC tables are used */ + emit_dht(cinfo, compptr->dc_tbl_no, FALSE); + } else { + /* Sequential mode: need both DC and AC tables */ + emit_dht(cinfo, compptr->dc_tbl_no, FALSE); + emit_dht(cinfo, compptr->ac_tbl_no, TRUE); + } + } + } + + /* Emit DRI if required --- note that DRI value could change for each scan. + * We avoid wasting space with unnecessary DRIs, however. + */ + if (cinfo->restart_interval != marker->last_restart_interval) { + emit_dri(cinfo); + marker->last_restart_interval = cinfo->restart_interval; + } + + emit_sos(cinfo); +} + + +/* + * Write datastream trailer. + */ + +METHODDEF(void) +write_file_trailer (j_compress_ptr cinfo) +{ + emit_marker(cinfo, M_EOI); +} + + +/* + * Write an abbreviated table-specification datastream. + * This consists of SOI, DQT and DHT tables, and EOI. + * Any table that is defined and not marked sent_table = TRUE will be + * emitted. Note that all tables will be marked sent_table = TRUE at exit. + */ + +METHODDEF(void) +write_tables_only (j_compress_ptr cinfo) +{ + int i; + + emit_marker(cinfo, M_SOI); + + for (i = 0; i < NUM_QUANT_TBLS; i++) { + if (cinfo->quant_tbl_ptrs[i] != NULL) + (void) emit_dqt(cinfo, i); + } + + if (! cinfo->arith_code) { + for (i = 0; i < NUM_HUFF_TBLS; i++) { + if (cinfo->dc_huff_tbl_ptrs[i] != NULL) + emit_dht(cinfo, i, FALSE); + if (cinfo->ac_huff_tbl_ptrs[i] != NULL) + emit_dht(cinfo, i, TRUE); + } + } + + emit_marker(cinfo, M_EOI); +} + + +/* + * Initialize the marker writer module. + */ + +GLOBAL(void) +jinit_marker_writer (j_compress_ptr cinfo) +{ + my_marker_ptr marker; + + /* Create the subobject */ + marker = (my_marker_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_marker_writer)); + cinfo->marker = (struct jpeg_marker_writer *) marker; + /* Initialize method pointers */ + marker->pub.write_file_header = write_file_header; + marker->pub.write_frame_header = write_frame_header; + marker->pub.write_scan_header = write_scan_header; + marker->pub.write_file_trailer = write_file_trailer; + marker->pub.write_tables_only = write_tables_only; + marker->pub.write_marker_header = write_marker_header; + marker->pub.write_marker_byte = write_marker_byte; + /* Initialize private state */ + marker->last_restart_interval = 0; +} diff --git a/dcmjpeg/libijg12/jcmaster.c b/dcmjpeg/libijg12/jcmaster.c new file mode 100644 index 00000000..de524a9b --- /dev/null +++ b/dcmjpeg/libijg12/jcmaster.c @@ -0,0 +1,657 @@ +/* + * jcmaster.c + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains master control logic for the JPEG compressor. + * These routines are concerned with parameter validation, initial setup, + * and inter-pass control (determining the number of passes and the work + * to be done in each pass). + */ + +#define JPEG_INTERNALS +#include "jinclude12.h" +#include "jpeglib12.h" +#include "jlossy12.h" /* Private declarations for lossy codec */ + + +/* Private state */ + +typedef enum { + main_pass, /* input data, also do first output step */ + huff_opt_pass, /* Huffman code optimization pass */ + output_pass /* data output pass */ +} c_pass_type; + +typedef struct { + struct jpeg_comp_master pub; /* public fields */ + + c_pass_type pass_type; /* the type of the current pass */ + + int pass_number; /* # of passes completed */ + int total_passes; /* total # of passes needed */ + + int scan_number; /* current index in scan_info[] */ +} my_comp_master; + +typedef my_comp_master * my_master_ptr; + + +/* + * Support routines that do various essential calculations. + */ + +LOCAL(void) +initial_setup (j_compress_ptr cinfo) +/* Do computations that are needed before master selection phase */ +{ + int ci; + jpeg_component_info *compptr; + long samplesperrow; + JDIMENSION jd_samplesperrow; + int data_unit = cinfo->data_unit; + + /* Sanity check on image dimensions */ + if (cinfo->image_height <= 0 || cinfo->image_width <= 0 + || cinfo->num_components <= 0 || cinfo->input_components <= 0) + ERREXIT(cinfo, JERR_EMPTY_IMAGE); + + /* Make sure image isn't bigger than I can handle */ + if ((long) cinfo->image_height > (long) JPEG_MAX_DIMENSION || + (long) cinfo->image_width > (long) JPEG_MAX_DIMENSION) + ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, (unsigned int) JPEG_MAX_DIMENSION); + + /* Width of an input scanline must be representable as JDIMENSION. */ + samplesperrow = (long) cinfo->image_width * (long) cinfo->input_components; + jd_samplesperrow = (JDIMENSION) samplesperrow; + if ((long) jd_samplesperrow != samplesperrow) + ERREXIT(cinfo, JERR_WIDTH_OVERFLOW); + + /* For now, precision must match compiled-in value... */ + if (cinfo->data_precision != BITS_IN_JSAMPLE) + ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); + + /* Check that number of components won't exceed internal array sizes */ + if (cinfo->num_components > MAX_COMPONENTS) + ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components, + MAX_COMPONENTS); + + /* Compute maximum sampling factors; check factor validity */ + cinfo->max_h_samp_factor = 1; + cinfo->max_v_samp_factor = 1; + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + if (compptr->h_samp_factor<=0 || compptr->h_samp_factor>MAX_SAMP_FACTOR || + compptr->v_samp_factor<=0 || compptr->v_samp_factor>MAX_SAMP_FACTOR) + ERREXIT(cinfo, JERR_BAD_SAMPLING); + cinfo->max_h_samp_factor = MAX(cinfo->max_h_samp_factor, + compptr->h_samp_factor); + cinfo->max_v_samp_factor = MAX(cinfo->max_v_samp_factor, + compptr->v_samp_factor); + } + + /* Compute dimensions of components */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + /* Fill in the correct component_index value; don't rely on application */ + compptr->component_index = ci; + /* For compression, we never do any codec-based processing. */ + compptr->codec_data_unit = data_unit; + /* Size in data units */ + compptr->width_in_data_units = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor, + (long) (cinfo->max_h_samp_factor * data_unit)); + compptr->height_in_data_units = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor, + (long) (cinfo->max_v_samp_factor * data_unit)); + /* Size in samples */ + compptr->downsampled_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor, + (long) cinfo->max_h_samp_factor); + compptr->downsampled_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor, + (long) cinfo->max_v_samp_factor); + /* Mark component needed (this flag isn't actually used for compression) */ + compptr->component_needed = TRUE; + } + + /* Compute number of fully interleaved MCU rows (number of times that + * main controller will call coefficient controller). + */ + cinfo->total_iMCU_rows = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height, + (long) (cinfo->max_v_samp_factor*data_unit)); +} + +#ifdef C_MULTISCAN_FILES_SUPPORTED +#define NEED_SCAN_SCRIPT +#else +#ifdef C_LOSSLESS_SUPPORTED +#define NEED_SCAN_SCRIPT +#endif +#endif + +#ifdef NEED_SCAN_SCRIPT + +LOCAL(void) +validate_script (j_compress_ptr cinfo) +/* Verify that the scan script in cinfo->scan_info[] is valid; also + * determine whether it uses progressive JPEG, and set cinfo->process. + */ +{ + const jpeg_scan_info * scanptr; + int scanno, ncomps, ci, coefi, thisi; + int Ss, Se, Ah, Al; + boolean component_sent[MAX_COMPONENTS]; +#ifdef C_PROGRESSIVE_SUPPORTED + int * last_bitpos_ptr; + int last_bitpos[MAX_COMPONENTS][DCTSIZE2]; + /* -1 until that coefficient has been seen; then last Al for it */ +#endif + + if (cinfo->num_scans <= 0) + ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, 0); + +#ifndef C_MULTISCAN_FILES_SUPPORTED + if (cinfo->num_scans > 1) + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + + scanptr = cinfo->scan_info; + if (cinfo->lossless) { +#ifdef C_LOSSLESS_SUPPORTED + cinfo->process = JPROC_LOSSLESS; + for (ci = 0; ci < cinfo->num_components; ci++) + component_sent[ci] = FALSE; +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } + /* For sequential JPEG, all scans must have Ss=0, Se=DCTSIZE2-1; + * for progressive JPEG, no scan can have this. + */ + else if (scanptr->Ss != 0 || scanptr->Se != DCTSIZE2-1) { +#ifdef C_PROGRESSIVE_SUPPORTED + cinfo->process = JPROC_PROGRESSIVE; + last_bitpos_ptr = & last_bitpos[0][0]; + for (ci = 0; ci < cinfo->num_components; ci++) + for (coefi = 0; coefi < DCTSIZE2; coefi++) + *last_bitpos_ptr++ = -1; +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } else { + cinfo->process = JPROC_SEQUENTIAL; + for (ci = 0; ci < cinfo->num_components; ci++) + component_sent[ci] = FALSE; + } + + for (scanno = 1; scanno <= cinfo->num_scans; scanptr++, scanno++) { + /* Validate component indexes */ + ncomps = scanptr->comps_in_scan; + if (ncomps <= 0 || ncomps > MAX_COMPS_IN_SCAN) + ERREXIT2(cinfo, JERR_COMPONENT_COUNT, ncomps, MAX_COMPS_IN_SCAN); + for (ci = 0; ci < ncomps; ci++) { + thisi = scanptr->component_index[ci]; + if (thisi < 0 || thisi >= cinfo->num_components) + ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, scanno); + /* Components must appear in SOF order within each scan */ + if (ci > 0 && thisi <= scanptr->component_index[ci-1]) + ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, scanno); + } + /* Validate progression parameters */ + Ss = scanptr->Ss; + Se = scanptr->Se; + Ah = scanptr->Ah; + Al = scanptr->Al; + if (cinfo->process == JPROC_LOSSLESS) { +#ifdef C_LOSSLESS_SUPPORTED + /* The JPEG spec simply gives the range 0..15 for Al (Pt), but that + * seems wrong: the upper bound ought to depend on data precision. + * Perhaps they really meant 0..N-1 for N-bit precision, which is what + * we allow here. + */ + if (Ss < 1 || Ss > 7 || /* predictor selector */ + Se != 0 || Ah != 0 || + Al < 0 || Al >= cinfo->data_precision) /* point transform */ + ERREXIT1(cinfo, JERR_BAD_LOSSLESS_SCRIPT, scanno); + /* Make sure components are not sent twice */ + for (ci = 0; ci < ncomps; ci++) { + thisi = scanptr->component_index[ci]; + if (component_sent[thisi]) + ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, scanno); + component_sent[thisi] = TRUE; + } +#endif + } else if (cinfo->process == JPROC_PROGRESSIVE) { +#ifdef C_PROGRESSIVE_SUPPORTED + /* The JPEG spec simply gives the ranges 0..13 for Ah and Al, but that + * seems wrong: the upper bound ought to depend on data precision. + * Perhaps they really meant 0..N+1 for N-bit precision. + * Here we allow 0..10 for 8-bit data; Al larger than 10 results in + * out-of-range reconstructed DC values during the first DC scan, + * which might cause problems for some decoders. + */ +#if BITS_IN_JSAMPLE == 8 +#define MAX_AH_AL 10 +#else +#define MAX_AH_AL 13 +#endif + if (Ss < 0 || Ss >= DCTSIZE2 || Se < Ss || Se >= DCTSIZE2 || + Ah < 0 || Ah > MAX_AH_AL || Al < 0 || Al > MAX_AH_AL) + ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); + if (Ss == 0) { + if (Se != 0) /* DC and AC together not OK */ + ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); + } else { + if (ncomps != 1) /* AC scans must be for only one component */ + ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); + } + for (ci = 0; ci < ncomps; ci++) { + last_bitpos_ptr = & last_bitpos[scanptr->component_index[ci]][0]; + if (Ss != 0 && last_bitpos_ptr[0] < 0) /* AC without prior DC scan */ + ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); + for (coefi = Ss; coefi <= Se; coefi++) { + if (last_bitpos_ptr[coefi] < 0) { + /* first scan of this coefficient */ + if (Ah != 0) + ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); + } else { + /* not first scan */ + if (Ah != last_bitpos_ptr[coefi] || Al != Ah-1) + ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); + } + last_bitpos_ptr[coefi] = Al; + } + } +#endif + } else { + /* For sequential JPEG, all progression parameters must be these: */ + if (Ss != 0 || Se != DCTSIZE2-1 || Ah != 0 || Al != 0) + ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); + /* Make sure components are not sent twice */ + for (ci = 0; ci < ncomps; ci++) { + thisi = scanptr->component_index[ci]; + if (component_sent[thisi]) + ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, scanno); + component_sent[thisi] = TRUE; + } + } + } + + /* Now verify that everything got sent. */ + if (cinfo->process == JPROC_PROGRESSIVE) { +#ifdef C_PROGRESSIVE_SUPPORTED + /* For progressive mode, we only check that at least some DC data + * got sent for each component; the spec does not require that all bits + * of all coefficients be transmitted. Would it be wiser to enforce + * transmission of all coefficient bits?? + */ + for (ci = 0; ci < cinfo->num_components; ci++) { + if (last_bitpos[ci][0] < 0) + ERREXIT(cinfo, JERR_MISSING_DATA); + } +#endif + } else { + for (ci = 0; ci < cinfo->num_components; ci++) { + if (! component_sent[ci]) + ERREXIT(cinfo, JERR_MISSING_DATA); + } + } +} + +#endif /* NEED_SCAN_SCRIPT */ + + +LOCAL(void) +select_scan_parameters (j_compress_ptr cinfo) +/* Set up the scan parameters for the current scan */ +{ + int ci; + +#ifdef NEED_SCAN_SCRIPT + if (cinfo->scan_info != NULL) { + /* Prepare for current scan --- the script is already validated */ + my_master_ptr master = (my_master_ptr) cinfo->master; + const jpeg_scan_info * scanptr = cinfo->scan_info + master->scan_number; + + cinfo->comps_in_scan = scanptr->comps_in_scan; + for (ci = 0; ci < scanptr->comps_in_scan; ci++) { + cinfo->cur_comp_info[ci] = + &cinfo->comp_info[scanptr->component_index[ci]]; + } + cinfo->Ss = scanptr->Ss; + cinfo->Se = scanptr->Se; + cinfo->Ah = scanptr->Ah; + cinfo->Al = scanptr->Al; + } else +#endif + { + /* Prepare for single sequential-JPEG scan containing all components */ + if (cinfo->num_components > MAX_COMPS_IN_SCAN) + ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components, + MAX_COMPS_IN_SCAN); + cinfo->comps_in_scan = cinfo->num_components; + for (ci = 0; ci < cinfo->num_components; ci++) { + cinfo->cur_comp_info[ci] = &cinfo->comp_info[ci]; + } + if (cinfo->lossless) { +#ifdef C_LOSSLESS_SUPPORTED + /* If we fall through to here, the user specified lossless, but did not + * provide a scan script. + */ + ERREXIT(cinfo, JERR_NO_LOSSLESS_SCRIPT); +#endif + } else { + cinfo->process = JPROC_SEQUENTIAL; + cinfo->Ss = 0; + cinfo->Se = DCTSIZE2-1; + cinfo->Ah = 0; + cinfo->Al = 0; + } + } +} + + +LOCAL(void) +per_scan_setup (j_compress_ptr cinfo) +/* Do computations that are needed before processing a JPEG scan */ +/* cinfo->comps_in_scan and cinfo->cur_comp_info[] are already set */ +{ + int ci, mcublks, tmp; + jpeg_component_info *compptr; + int data_unit = cinfo->data_unit; + + if (cinfo->comps_in_scan == 1) { + + /* Noninterleaved (single-component) scan */ + compptr = cinfo->cur_comp_info[0]; + + /* Overall image size in MCUs */ + cinfo->MCUs_per_row = compptr->width_in_data_units; + cinfo->MCU_rows_in_scan = compptr->height_in_data_units; + + /* For noninterleaved scan, always one block per MCU */ + compptr->MCU_width = 1; + compptr->MCU_height = 1; + compptr->MCU_data_units = 1; + compptr->MCU_sample_width = data_unit; + compptr->last_col_width = 1; + /* For noninterleaved scans, it is convenient to define last_row_height + * as the number of block rows present in the last iMCU row. + */ + tmp = (int)compptr->height_in_data_units % compptr->v_samp_factor; + if (tmp == 0) tmp = compptr->v_samp_factor; + compptr->last_row_height = tmp; + + /* Prepare array describing MCU composition */ + cinfo->data_units_in_MCU = 1; + cinfo->MCU_membership[0] = 0; + + } else { + + /* Interleaved (multi-component) scan */ + if (cinfo->comps_in_scan <= 0 || cinfo->comps_in_scan > MAX_COMPS_IN_SCAN) + ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->comps_in_scan, + MAX_COMPS_IN_SCAN); + + /* Overall image size in MCUs */ + cinfo->MCUs_per_row = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width, + (long) (cinfo->max_h_samp_factor*data_unit)); + cinfo->MCU_rows_in_scan = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height, + (long) (cinfo->max_v_samp_factor*data_unit)); + + cinfo->data_units_in_MCU = 0; + + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + /* Sampling factors give # of blocks of component in each MCU */ + compptr->MCU_width = compptr->h_samp_factor; + compptr->MCU_height = compptr->v_samp_factor; + compptr->MCU_data_units = compptr->MCU_width * compptr->MCU_height; + compptr->MCU_sample_width = compptr->MCU_width * data_unit; + /* Figure number of non-dummy blocks in last MCU column & row */ + tmp = (int)compptr->width_in_data_units % compptr->MCU_width; + if (tmp == 0) tmp = compptr->MCU_width; + compptr->last_col_width = tmp; + tmp = (int)compptr->height_in_data_units % compptr->MCU_height; + if (tmp == 0) tmp = compptr->MCU_height; + compptr->last_row_height = tmp; + /* Prepare array describing MCU composition */ + mcublks = compptr->MCU_data_units; + if (cinfo->data_units_in_MCU + mcublks > C_MAX_DATA_UNITS_IN_MCU) + ERREXIT(cinfo, JERR_BAD_MCU_SIZE); + while (mcublks-- > 0) { + cinfo->MCU_membership[cinfo->data_units_in_MCU++] = ci; + } + } + + } + + /* Convert restart specified in rows to actual MCU count. */ + /* Note that count must fit in 16 bits, so we provide limiting. */ + if (cinfo->restart_in_rows > 0) { + long nominal = (long) cinfo->restart_in_rows * (long) cinfo->MCUs_per_row; + cinfo->restart_interval = (unsigned int) MIN(nominal, 65535L); + } +} + + +/* + * Per-pass setup. + * This is called at the beginning of each pass. We determine which modules + * will be active during this pass and give them appropriate start_pass calls. + * We also set is_last_pass to indicate whether any more passes will be + * required. + */ + +METHODDEF(void) +prepare_for_pass (j_compress_ptr cinfo) +{ + /* j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; */ + my_master_ptr master = (my_master_ptr) cinfo->master; + + switch (master->pass_type) { + case main_pass: + /* Initial pass: will collect input data, and do either Huffman + * optimization or data output for the first scan. + */ + select_scan_parameters(cinfo); + per_scan_setup(cinfo); + if (! cinfo->raw_data_in) { + (*cinfo->cconvert->start_pass) (cinfo); + (*cinfo->downsample->start_pass) (cinfo); + (*cinfo->prep->start_pass) (cinfo, JBUF_PASS_THRU); + } + (*cinfo->codec->entropy_start_pass) (cinfo, cinfo->optimize_coding); + (*cinfo->codec->start_pass) (cinfo, + (master->total_passes > 1 ? + JBUF_SAVE_AND_PASS : JBUF_PASS_THRU)); + (*cinfo->main->start_pass) (cinfo, JBUF_PASS_THRU); + if (cinfo->optimize_coding) { + /* No immediate data output; postpone writing frame/scan headers */ + master->pub.call_pass_startup = FALSE; + } else { + /* Will write frame/scan headers at first jpeg_write_scanlines call */ + master->pub.call_pass_startup = TRUE; + } + break; +#ifdef ENTROPY_OPT_SUPPORTED + case huff_opt_pass: + /* Do Huffman optimization for a scan after the first one. */ + select_scan_parameters(cinfo); + per_scan_setup(cinfo); +#ifdef WITH_ARITHMETIC_PATCH + if ((*cinfo->codec->need_optimization_pass) (cinfo)) { +#else + if ((*cinfo->codec->need_optimization_pass) (cinfo) || cinfo->arith_code) { +#endif + (*cinfo->codec->entropy_start_pass) (cinfo, TRUE); + (*cinfo->codec->start_pass) (cinfo, JBUF_CRANK_DEST); + master->pub.call_pass_startup = FALSE; + break; + } + /* Special case: Huffman DC refinement scans need no Huffman table + * and therefore we can skip the optimization pass for them. + */ + master->pass_type = output_pass; + master->pass_number++; + /*FALLTHROUGH*/ +#endif + case output_pass: + /* Do a data-output pass. */ + /* We need not repeat per-scan setup if prior optimization pass did it. */ + if (! cinfo->optimize_coding) { + select_scan_parameters(cinfo); + per_scan_setup(cinfo); + } + (*cinfo->codec->entropy_start_pass) (cinfo, FALSE); + (*cinfo->codec->start_pass) (cinfo, JBUF_CRANK_DEST); + /* We emit frame/scan headers now */ + if (master->scan_number == 0) + (*cinfo->marker->write_frame_header) (cinfo); + (*cinfo->marker->write_scan_header) (cinfo); + master->pub.call_pass_startup = FALSE; + break; + default: + ERREXIT(cinfo, JERR_NOT_COMPILED); + } + + master->pub.is_last_pass = (master->pass_number == master->total_passes-1); + + /* Set up progress monitor's pass info if present */ + if (cinfo->progress != NULL) { + cinfo->progress->completed_passes = master->pass_number; + cinfo->progress->total_passes = master->total_passes; + } +} + + +/* + * Special start-of-pass hook. + * This is called by jpeg_write_scanlines if call_pass_startup is TRUE. + * In single-pass processing, we need this hook because we don't want to + * write frame/scan headers during jpeg_start_compress; we want to let the + * application write COM markers etc. between jpeg_start_compress and the + * jpeg_write_scanlines loop. + * In multi-pass processing, this routine is not used. + */ + +METHODDEF(void) +pass_startup (j_compress_ptr cinfo) +{ + cinfo->master->call_pass_startup = FALSE; /* reset flag so call only once */ + + (*cinfo->marker->write_frame_header) (cinfo); + (*cinfo->marker->write_scan_header) (cinfo); +} + + +/* + * Finish up at end of pass. + */ + +METHODDEF(void) +finish_pass_master (j_compress_ptr cinfo) +{ + j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; + my_master_ptr master = (my_master_ptr) cinfo->master; + + /* The entropy coder always needs an end-of-pass call, + * either to analyze statistics or to flush its output buffer. + */ + (*lossyc->pub.entropy_finish_pass) (cinfo); + + /* Update state for next pass */ + switch (master->pass_type) { + case main_pass: + /* next pass is either output of scan 0 (after optimization) + * or output of scan 1 (if no optimization). + */ + master->pass_type = output_pass; + if (! cinfo->optimize_coding) + master->scan_number++; + break; + case huff_opt_pass: + /* next pass is always output of current scan */ + master->pass_type = output_pass; + break; + case output_pass: + /* next pass is either optimization or output of next scan */ + if (cinfo->optimize_coding) + master->pass_type = huff_opt_pass; + master->scan_number++; + break; + } + + master->pass_number++; +} + + +/* + * Initialize master compression control. + */ + +GLOBAL(void) +jinit_c_master_control (j_compress_ptr cinfo, boolean transcode_only) +{ + my_master_ptr master; + + master = (my_master_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_comp_master)); + cinfo->master = (struct jpeg_comp_master *) master; + master->pub.prepare_for_pass = prepare_for_pass; + master->pub.pass_startup = pass_startup; + master->pub.finish_pass = finish_pass_master; + master->pub.is_last_pass = FALSE; + + cinfo->data_unit = cinfo->lossless ? 1 : DCTSIZE; + + /* Validate parameters, determine derived values */ + initial_setup(cinfo); + + if (cinfo->scan_info != NULL) { +#ifdef NEED_SCAN_SCRIPT + validate_script(cinfo); +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } else { + cinfo->process = JPROC_SEQUENTIAL; + cinfo->num_scans = 1; + } + +#ifdef WITH_ARITHMETIC_PATCH + if ((cinfo->arith_code == 0) && + (cinfo->process == JPROC_PROGRESSIVE || /* TEMPORARY HACK ??? */ + cinfo->process == JPROC_LOSSLESS)) +#else + if (cinfo->process == JPROC_PROGRESSIVE || /* TEMPORARY HACK ??? */ + cinfo->process == JPROC_LOSSLESS) +#endif + cinfo->optimize_coding = TRUE; /* assume default tables no good for + * progressive mode or lossless mode */ + + /* Initialize my private state */ + if (transcode_only) { + /* no main pass in transcoding */ + if (cinfo->optimize_coding) + master->pass_type = huff_opt_pass; + else + master->pass_type = output_pass; + } else { + /* for normal compression, first pass is always this type: */ + master->pass_type = main_pass; + } + master->scan_number = 0; + master->pass_number = 0; + if (cinfo->optimize_coding) + master->total_passes = cinfo->num_scans * 2; + else + master->total_passes = cinfo->num_scans; +} diff --git a/dcmjpeg/libijg12/jcodec.c b/dcmjpeg/libijg12/jcodec.c new file mode 100644 index 00000000..e3b70297 --- /dev/null +++ b/dcmjpeg/libijg12/jcodec.c @@ -0,0 +1,53 @@ +/* + * jcodec.c + * + * Copyright (C) 1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains utility functions for the JPEG codec(s). + */ + +#define JPEG_INTERNALS +#include "jinclude12.h" +#include "jpeglib12.h" +#include "jlossy12.h" +#include "jlossls12.h" + + +/* + * Initialize the compression codec. + * This is called only once, during master selection. + */ + +GLOBAL(void) +jinit_c_codec (j_compress_ptr cinfo) +{ + if (cinfo->process == JPROC_LOSSLESS) { +#ifdef C_LOSSLESS_SUPPORTED + jinit_lossless_c_codec(cinfo); +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } else + jinit_lossy_c_codec(cinfo); +} + + +/* + * Initialize the decompression codec. + * This is called only once, during master selection. + */ + +GLOBAL(void) +jinit_d_codec (j_decompress_ptr cinfo) +{ + if (cinfo->process == JPROC_LOSSLESS) { +#ifdef D_LOSSLESS_SUPPORTED + jinit_lossless_d_codec(cinfo); +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } else + jinit_lossy_d_codec(cinfo); +} diff --git a/dcmjpeg/libijg12/jcomapi.c b/dcmjpeg/libijg12/jcomapi.c new file mode 100644 index 00000000..090bc85b --- /dev/null +++ b/dcmjpeg/libijg12/jcomapi.c @@ -0,0 +1,106 @@ +/* + * jcomapi.c + * + * Copyright (C) 1994-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains application interface routines that are used for both + * compression and decompression. + */ + +#define JPEG_INTERNALS +#include "jinclude12.h" +#include "jpeglib12.h" + + +/* + * Abort processing of a JPEG compression or decompression operation, + * but don't destroy the object itself. + * + * For this, we merely clean up all the nonpermanent memory pools. + * Note that temp files (virtual arrays) are not allowed to belong to + * the permanent pool, so we will be able to close all temp files here. + * Closing a data source or destination, if necessary, is the application's + * responsibility. + */ + +GLOBAL(void) +jpeg_abort (j_common_ptr cinfo) +{ + int pool; + + /* Do nothing if called on a not-initialized or destroyed JPEG object. */ + if (cinfo->mem == NULL) + return; + + /* Releasing pools in reverse order might help avoid fragmentation + * with some (brain-damaged) malloc libraries. + */ + for (pool = JPOOL_NUMPOOLS-1; pool > JPOOL_PERMANENT; pool--) { + (*cinfo->mem->free_pool) (cinfo, pool); + } + + /* Reset overall state for possible reuse of object */ + if (cinfo->is_decompressor) { + cinfo->global_state = DSTATE_START; + /* Try to keep application from accessing now-deleted marker list. + * A bit kludgy to do it here, but this is the most central place. + */ + ((j_decompress_ptr) cinfo)->marker_list = NULL; + } else { + cinfo->global_state = CSTATE_START; + } +} + + +/* + * Destruction of a JPEG object. + * + * Everything gets deallocated except the master jpeg_compress_struct itself + * and the error manager struct. Both of these are supplied by the application + * and must be freed, if necessary, by the application. (Often they are on + * the stack and so don't need to be freed anyway.) + * Closing a data source or destination, if necessary, is the application's + * responsibility. + */ + +GLOBAL(void) +jpeg_destroy (j_common_ptr cinfo) +{ + /* We need only tell the memory manager to release everything. */ + /* NB: mem pointer is NULL if memory mgr failed to initialize. */ + if (cinfo->mem != NULL) + (*cinfo->mem->self_destruct) (cinfo); + cinfo->mem = NULL; /* be safe if jpeg_destroy is called twice */ + cinfo->global_state = 0; /* mark it destroyed */ +} + + +/* + * Convenience routines for allocating quantization and Huffman tables. + * (Would jutils.c be a more reasonable place to put these?) + */ + +GLOBAL(JQUANT_TBL *) +jpeg_alloc_quant_table (j_common_ptr cinfo) +{ + JQUANT_TBL *tbl; + + tbl = (JQUANT_TBL *) + (*cinfo->mem->alloc_small) (cinfo, JPOOL_PERMANENT, SIZEOF(JQUANT_TBL)); + tbl->sent_table = FALSE; /* make sure this is false in any new table */ + return tbl; +} + + +GLOBAL(JHUFF_TBL *) +jpeg_alloc_huff_table (j_common_ptr cinfo) +{ + JHUFF_TBL *tbl; + + tbl = (JHUFF_TBL *) + (*cinfo->mem->alloc_small) (cinfo, JPOOL_PERMANENT, SIZEOF(JHUFF_TBL)); + tbl->sent_table = FALSE; /* make sure this is false in any new table */ + return tbl; +} diff --git a/dcmjpeg/libijg12/jconfig12.h b/dcmjpeg/libijg12/jconfig12.h new file mode 100644 index 00000000..4dd87d61 --- /dev/null +++ b/dcmjpeg/libijg12/jconfig12.h @@ -0,0 +1,73 @@ +/* + * + * Copyright (C) 1998-2010, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmjpeg + * + * Author: Marco Eichelberg + * + * Purpose: + * this file derives the preprocessor symbols required to compile + * the IJG library from the central DCMTK configuration file osconfig.h + * + */ + +#include "dcmtk/config/osconfig.h" + +/* We assume ANSI C and don't support DOS, + * so the following settings need not be tested + */ +#define HAVE_PROTOTYPES +#define HAVE_UNSIGNED_CHAR +#define HAVE_UNSIGNED_SHORT +#undef NEED_FAR_POINTERS +#undef INCOMPLETE_TYPES_BROKEN + +/* the following settings are derived from osconfig.h */ + +#ifndef HAVE_C_CONST +#define const +#endif + +#ifdef C_CHAR_UNSIGNED +#define CHAR_IS_UNSIGNED +#endif + +#ifdef HAVE_STRINGS_H +#ifndef HAVE_STRING_H +#define NEED_BSD_STRINGS +#endif +#endif + +#ifdef HAVE_SYS_TYPES_H +#define NEED_SYS_TYPES_H +#endif + +/* must always be defined for our implementation */ +#define NEED_SHORT_EXTERNAL_NAMES + +#ifdef JPEG_INTERNALS + +#ifdef C_RIGHTSHIFT_UNSIGNED +#define RIGHT_SHIFT_IS_UNSIGNED +#endif + +#define INLINE C_INLINE + +/* These are for configuring the JPEG memory manager. */ +#undef DEFAULT_MAX_MEM +#undef NO_MKTEMP + +/* We don't want to use getenv which is thread unsafe on some platforms */ +#define NO_GETENV + +#endif /* JPEG_INTERNALS */ diff --git a/dcmjpeg/libijg12/jcparam.c b/dcmjpeg/libijg12/jcparam.c new file mode 100644 index 00000000..974ddef3 --- /dev/null +++ b/dcmjpeg/libijg12/jcparam.c @@ -0,0 +1,687 @@ +/* + * jcparam.c + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains optional default-setting code for the JPEG compressor. + * Applications do not have to use this file, but those that don't use it + * must know a lot more about the innards of the JPEG code. + */ + +#define JPEG_INTERNALS +#include "jinclude12.h" +#include "jpeglib12.h" + + +/* + * Quantization table setup routines + */ + +GLOBAL(void) +jpeg_add_quant_table (j_compress_ptr cinfo, int which_tbl, + const unsigned int *basic_table, + int scale_factor, boolean force_baseline) +/* Define a quantization table equal to the basic_table times + * a scale factor (given as a percentage). + * If force_baseline is TRUE, the computed quantization table entries + * are limited to 1..255 for JPEG baseline compatibility. + */ +{ + JQUANT_TBL ** qtblptr; + int i; + long temp; + + /* Safety check to ensure start_compress not called yet. */ + if (cinfo->global_state != CSTATE_START) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + + if (which_tbl < 0 || which_tbl >= NUM_QUANT_TBLS) + ERREXIT1(cinfo, JERR_DQT_INDEX, which_tbl); + + qtblptr = & cinfo->quant_tbl_ptrs[which_tbl]; + + if (*qtblptr == NULL) + *qtblptr = jpeg_alloc_quant_table((j_common_ptr) cinfo); + + for (i = 0; i < DCTSIZE2; i++) { + temp = ((long) basic_table[i] * scale_factor + 50L) / 100L; + /* limit the values to the valid range */ + if (temp <= 0L) temp = 1L; + if (temp > 32767L) temp = 32767L; /* max quantizer needed for 12 bits */ + if (force_baseline && temp > 255L) + temp = 255L; /* limit to baseline range if requested */ + (*qtblptr)->quantval[i] = (UINT16) temp; + } + + /* Initialize sent_table FALSE so table will be written to JPEG file. */ + (*qtblptr)->sent_table = FALSE; +} + + +GLOBAL(void) +jpeg_set_linear_quality (j_compress_ptr cinfo, int scale_factor, + boolean force_baseline) +/* Set or change the 'quality' (quantization) setting, using default tables + * and a straight percentage-scaling quality scale. In most cases it's better + * to use jpeg_set_quality (below); this entry point is provided for + * applications that insist on a linear percentage scaling. + */ +{ + /* These are the sample quantization tables given in JPEG spec section K.1. + * The spec says that the values given produce "good" quality, and + * when divided by 2, "very good" quality. + */ + static const unsigned int std_luminance_quant_tbl[DCTSIZE2] = { + 16, 11, 10, 16, 24, 40, 51, 61, + 12, 12, 14, 19, 26, 58, 60, 55, + 14, 13, 16, 24, 40, 57, 69, 56, + 14, 17, 22, 29, 51, 87, 80, 62, + 18, 22, 37, 56, 68, 109, 103, 77, + 24, 35, 55, 64, 81, 104, 113, 92, + 49, 64, 78, 87, 103, 121, 120, 101, + 72, 92, 95, 98, 112, 100, 103, 99 + }; + static const unsigned int std_chrominance_quant_tbl[DCTSIZE2] = { + 17, 18, 24, 47, 99, 99, 99, 99, + 18, 21, 26, 66, 99, 99, 99, 99, + 24, 26, 56, 99, 99, 99, 99, 99, + 47, 66, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99 + }; + + /* Set up two quantization tables using the specified scaling */ + jpeg_add_quant_table(cinfo, 0, std_luminance_quant_tbl, + scale_factor, force_baseline); + jpeg_add_quant_table(cinfo, 1, std_chrominance_quant_tbl, + scale_factor, force_baseline); +} + + +GLOBAL(int) +jpeg_quality_scaling (int quality) +/* Convert a user-specified quality rating to a percentage scaling factor + * for an underlying quantization table, using our recommended scaling curve. + * The input 'quality' factor should be 0 (terrible) to 100 (very good). + */ +{ + /* Safety limit on quality factor. Convert 0 to 1 to avoid zero divide. */ + if (quality <= 0) quality = 1; + if (quality > 100) quality = 100; + + /* The basic table is used as-is (scaling 100) for a quality of 50. + * Qualities 50..100 are converted to scaling percentage 200 - 2*Q; + * note that at Q=100 the scaling is 0, which will cause jpeg_add_quant_table + * to make all the table entries 1 (hence, minimum quantization loss). + * Qualities 1..50 are converted to scaling percentage 5000/Q. + */ + if (quality < 50) + quality = 5000 / quality; + else + quality = 200 - quality*2; + + return quality; +} + + +GLOBAL(void) +jpeg_set_quality (j_compress_ptr cinfo, int quality, boolean force_baseline) +/* Set or change the 'quality' (quantization) setting, using default tables. + * This is the standard quality-adjusting entry point for typical user + * interfaces; only those who want detailed control over quantization tables + * would use the preceding three routines directly. + */ +{ + /* Convert user 0-100 rating to percentage scaling */ + quality = jpeg_quality_scaling(quality); + + /* Set up standard quality tables */ + jpeg_set_linear_quality(cinfo, quality, force_baseline); +} + + +/* + * Huffman table setup routines + */ + +LOCAL(void) +add_huff_table (j_compress_ptr cinfo, + JHUFF_TBL **htblptr, const UINT8 *bits, const UINT8 *val) +/* Define a Huffman table */ +{ + int nsymbols, len; + + if (*htblptr == NULL) + *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo); + + /* Copy the number-of-symbols-of-each-code-length counts */ + MEMCOPY((*htblptr)->bits, bits, SIZEOF((*htblptr)->bits)); + + /* Validate the counts. We do this here mainly so we can copy the right + * number of symbols from the val[] array, without risking marching off + * the end of memory. jchuff.c will do a more thorough test later. + */ + nsymbols = 0; + for (len = 1; len <= 16; len++) + nsymbols += bits[len]; + if (nsymbols < 1 || nsymbols > 256) + ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); + + MEMCOPY((*htblptr)->huffval, val, (size_t)nsymbols * SIZEOF(UINT8)); + + /* Initialize sent_table FALSE so table will be written to JPEG file. */ + (*htblptr)->sent_table = FALSE; +} + + +LOCAL(void) +std_huff_tables (j_compress_ptr cinfo) +/* Set up the standard Huffman tables (cf. JPEG standard section K.3) */ +/* IMPORTANT: these are only valid for 8-bit data precision! */ +{ + static const UINT8 bits_dc_luminance[17] = + { /* 0-base */ 0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 }; + static const UINT8 val_dc_luminance[] = + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }; + + static const UINT8 bits_dc_chrominance[17] = + { /* 0-base */ 0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 }; + static const UINT8 val_dc_chrominance[] = + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }; + + static const UINT8 bits_ac_luminance[17] = + { /* 0-base */ 0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d }; + static const UINT8 val_ac_luminance[] = + { 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, + 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, + 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08, + 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0, + 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16, + 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28, + 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, + 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, + 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, + 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, + 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, + 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, + 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, + 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, + 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, + 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, + 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, + 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2, + 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, + 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, + 0xf9, 0xfa }; + + static const UINT8 bits_ac_chrominance[17] = + { /* 0-base */ 0, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77 }; + static const UINT8 val_ac_chrominance[] = + { 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, + 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71, + 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, + 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0, + 0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34, + 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26, + 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38, + 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, + 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, + 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, + 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, + 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, + 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, + 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, + 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, + 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, + 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, + 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, + 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, + 0xf9, 0xfa }; + + add_huff_table(cinfo, &cinfo->dc_huff_tbl_ptrs[0], + bits_dc_luminance, val_dc_luminance); + add_huff_table(cinfo, &cinfo->ac_huff_tbl_ptrs[0], + bits_ac_luminance, val_ac_luminance); + add_huff_table(cinfo, &cinfo->dc_huff_tbl_ptrs[1], + bits_dc_chrominance, val_dc_chrominance); + add_huff_table(cinfo, &cinfo->ac_huff_tbl_ptrs[1], + bits_ac_chrominance, val_ac_chrominance); +} + + +/* + * Default parameter setup for compression. + * + * Applications that don't choose to use this routine must do their + * own setup of all these parameters. Alternately, you can call this + * to establish defaults and then alter parameters selectively. This + * is the recommended approach since, if we add any new parameters, + * your code will still work (they'll be set to reasonable defaults). + */ + +GLOBAL(void) +jpeg_set_defaults (j_compress_ptr cinfo) +{ + int i; + + /* Safety check to ensure start_compress not called yet. */ + if (cinfo->global_state != CSTATE_START) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + + /* Allocate comp_info array large enough for maximum component count. + * Array is made permanent in case application wants to compress + * multiple images at same param settings. + */ + if (cinfo->comp_info == NULL) + cinfo->comp_info = (jpeg_component_info *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, + MAX_COMPONENTS * SIZEOF(jpeg_component_info)); + + /* Initialize everything not dependent on the color space */ + + cinfo->lossless = FALSE; + cinfo->data_precision = BITS_IN_JSAMPLE; + /* Set up two quantization tables using default quality of 75 */ + jpeg_set_quality(cinfo, 75, TRUE); + /* Set up two Huffman tables */ + std_huff_tables(cinfo); + + /* Initialize default arithmetic coding conditioning */ + for (i = 0; i < NUM_ARITH_TBLS; i++) { + cinfo->arith_dc_L[i] = 0; + cinfo->arith_dc_U[i] = 1; + cinfo->arith_ac_K[i] = 5; + } + + /* Default is no multiple-scan output */ + cinfo->scan_info = NULL; + cinfo->num_scans = 0; + + /* Expect normal source image, not raw downsampled data */ + cinfo->raw_data_in = FALSE; + + /* Use Huffman coding, not arithmetic coding, by default */ + cinfo->arith_code = FALSE; + + /* By default, don't do extra passes to optimize entropy coding */ + cinfo->optimize_coding = FALSE; + /* The standard Huffman tables are only valid for 8-bit data precision. + * If the precision is higher, force optimization on so that usable + * tables will be computed. This test can be removed if default tables + * are supplied that are valid for the desired precision. + */ + if (cinfo->data_precision > 8) + cinfo->optimize_coding = TRUE; + + /* By default, use the simpler non-cosited sampling alignment */ + cinfo->CCIR601_sampling = FALSE; + + /* No input smoothing */ + cinfo->smoothing_factor = 0; + + /* DCT algorithm preference */ + cinfo->dct_method = JDCT_DEFAULT; + + /* No restart markers */ + cinfo->restart_interval = 0; + cinfo->restart_in_rows = 0; + + /* Fill in default JFIF marker parameters. Note that whether the marker + * will actually be written is determined by jpeg_set_colorspace. + * + * By default, the library emits JFIF version code 1.01. + * An application that wants to emit JFIF 1.02 extension markers should set + * JFIF_minor_version to 2. We could probably get away with just defaulting + * to 1.02, but there may still be some decoders in use that will complain + * about that; saying 1.01 should minimize compatibility problems. + */ + cinfo->JFIF_major_version = 1; /* Default JFIF version = 1.01 */ + cinfo->JFIF_minor_version = 1; + cinfo->density_unit = 0; /* Pixel size is unknown by default */ + cinfo->X_density = 1; /* Pixel aspect ratio is square by default */ + cinfo->Y_density = 1; + + /* Choose JPEG colorspace based on input space, set defaults accordingly */ + + jpeg_default_colorspace(cinfo); +} + + +/* + * Select an appropriate JPEG colorspace for in_color_space. + */ + +GLOBAL(void) +jpeg_default_colorspace (j_compress_ptr cinfo) +{ + if (cinfo->lossless) + jpeg_set_colorspace(cinfo, cinfo->in_color_space); + else { /* lossy */ + switch (cinfo->in_color_space) { + case JCS_GRAYSCALE: + jpeg_set_colorspace(cinfo, JCS_GRAYSCALE); + break; + case JCS_RGB: + jpeg_set_colorspace(cinfo, JCS_YCbCr); + break; + case JCS_YCbCr: + jpeg_set_colorspace(cinfo, JCS_YCbCr); + break; + case JCS_CMYK: + jpeg_set_colorspace(cinfo, JCS_CMYK); /* By default, no translation */ + break; + case JCS_YCCK: + jpeg_set_colorspace(cinfo, JCS_YCCK); + break; + case JCS_UNKNOWN: + jpeg_set_colorspace(cinfo, JCS_UNKNOWN); + break; + default: + ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); + } + } +} + + +/* + * Set the JPEG colorspace, and choose colorspace-dependent default values. + */ + +GLOBAL(void) +jpeg_set_colorspace (j_compress_ptr cinfo, J_COLOR_SPACE colorspace) +{ + jpeg_component_info * compptr; + int ci; + +#define SET_COMP(index,id,hsamp,vsamp,quant,dctbl,actbl) \ + (compptr = &cinfo->comp_info[index], \ + compptr->component_id = (id), \ + compptr->h_samp_factor = (hsamp), \ + compptr->v_samp_factor = (vsamp), \ + compptr->quant_tbl_no = (quant), \ + compptr->dc_tbl_no = (dctbl), \ + compptr->ac_tbl_no = (actbl) ) + + /* Safety check to ensure start_compress not called yet. */ + if (cinfo->global_state != CSTATE_START) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + + /* For all colorspaces, we use Q and Huff tables 0 for luminance components, + * tables 1 for chrominance components. + */ + + cinfo->jpeg_color_space = colorspace; + + cinfo->write_JFIF_header = FALSE; /* No marker for non-JFIF colorspaces */ + cinfo->write_Adobe_marker = FALSE; /* write no Adobe marker by default */ + + switch (colorspace) { + case JCS_GRAYSCALE: + cinfo->write_JFIF_header = TRUE; /* Write a JFIF marker */ + cinfo->num_components = 1; + /* JFIF specifies component ID 1 */ + SET_COMP(0, 1, 1,1, 0, 0,0); + break; + case JCS_RGB: + cinfo->write_Adobe_marker = TRUE; /* write Adobe marker to flag RGB */ + cinfo->num_components = 3; + SET_COMP(0, 0x52 /* 'R' */, 1,1, 0, 0,0); + SET_COMP(1, 0x47 /* 'G' */, 1,1, 0, 0,0); + SET_COMP(2, 0x42 /* 'B' */, 1,1, 0, 0,0); + break; + case JCS_YCbCr: + cinfo->write_JFIF_header = TRUE; /* Write a JFIF marker */ + cinfo->num_components = 3; + /* JFIF specifies component IDs 1,2,3 */ + if (cinfo->lossless) { + SET_COMP(0, 1, 1,1, 0, 0,0); + SET_COMP(1, 2, 1,1, 1, 1,1); + SET_COMP(2, 3, 1,1, 1, 1,1); + } else { /* lossy */ + /* We default to 2x2 subsamples of chrominance */ + SET_COMP(0, 1, 2,2, 0, 0,0); + SET_COMP(1, 2, 1,1, 1, 1,1); + SET_COMP(2, 3, 1,1, 1, 1,1); + } + break; + case JCS_CMYK: + cinfo->write_Adobe_marker = TRUE; /* write Adobe marker to flag CMYK */ + cinfo->num_components = 4; + SET_COMP(0, 0x43 /* 'C' */, 1,1, 0, 0,0); + SET_COMP(1, 0x4D /* 'M' */, 1,1, 0, 0,0); + SET_COMP(2, 0x59 /* 'Y' */, 1,1, 0, 0,0); + SET_COMP(3, 0x4B /* 'K' */, 1,1, 0, 0,0); + break; + case JCS_YCCK: + cinfo->write_Adobe_marker = TRUE; /* write Adobe marker to flag YCCK */ + cinfo->num_components = 4; + if (cinfo->lossless) { + SET_COMP(0, 1, 1,1, 0, 0,0); + SET_COMP(1, 2, 1,1, 1, 1,1); + SET_COMP(2, 3, 1,1, 1, 1,1); + SET_COMP(3, 4, 1,1, 0, 0,0); + } else { /* lossy */ + SET_COMP(0, 1, 2,2, 0, 0,0); + SET_COMP(1, 2, 1,1, 1, 1,1); + SET_COMP(2, 3, 1,1, 1, 1,1); + SET_COMP(3, 4, 2,2, 0, 0,0); + } + break; + case JCS_UNKNOWN: + cinfo->num_components = cinfo->input_components; + if (cinfo->num_components < 1 || cinfo->num_components > MAX_COMPONENTS) + ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components, + MAX_COMPONENTS); + for (ci = 0; ci < cinfo->num_components; ci++) { + SET_COMP(ci, ci, 1,1, 0, 0,0); + } + break; + default: + ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); + } +} + + +#ifdef C_PROGRESSIVE_SUPPORTED + +LOCAL(jpeg_scan_info *) +fill_scans (jpeg_scan_info * scanptr, int ncomps, + int Ss, int Se, int Ah, int Al) +/* Support routine: generate one scan for each component */ +{ + int ci; + + for (ci = 0; ci < ncomps; ci++) { + scanptr->comps_in_scan = 1; + scanptr->component_index[0] = ci; + scanptr->Ss = Ss; + scanptr->Se = Se; + scanptr->Ah = Ah; + scanptr->Al = Al; + scanptr++; + } + return scanptr; +} + + +LOCAL(jpeg_scan_info *) +fill_a_scan (jpeg_scan_info * scanptr, int ci, + int Ss, int Se, int Ah, int Al) +/* Support routine: generate one scan for specified component */ +{ + scanptr->comps_in_scan = 1; + scanptr->component_index[0] = ci; + scanptr->Ss = Ss; + scanptr->Se = Se; + scanptr->Ah = Ah; + scanptr->Al = Al; + scanptr++; + return scanptr; +} + +LOCAL(jpeg_scan_info *) +fill_dc_scans (jpeg_scan_info * scanptr, int ncomps, int Ah, int Al) +/* Support routine: generate interleaved DC scan if possible, else N scans */ +{ + int ci; + + if (ncomps <= MAX_COMPS_IN_SCAN) { + /* Single interleaved DC scan */ + scanptr->comps_in_scan = ncomps; + for (ci = 0; ci < ncomps; ci++) + scanptr->component_index[ci] = ci; + scanptr->Ss = scanptr->Se = 0; + scanptr->Ah = Ah; + scanptr->Al = Al; + scanptr++; + } else { + /* Noninterleaved DC scan for each component */ + scanptr = fill_scans(scanptr, ncomps, 0, 0, Ah, Al); + } + return scanptr; +} + + +/* + * Create a recommended progressive-JPEG script. + * cinfo->num_components and cinfo->jpeg_color_space must be correct. + */ + +GLOBAL(void) +jpeg_simple_progression (j_compress_ptr cinfo) +{ + int ncomps = cinfo->num_components; + int nscans; + jpeg_scan_info * scanptr; + + /* Safety check to ensure start_compress not called yet. */ + if (cinfo->global_state != CSTATE_START) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + + /* Figure space needed for script. Calculation must match code below! */ + if (ncomps == 3 && cinfo->jpeg_color_space == JCS_YCbCr) { + /* Custom script for YCbCr color images. */ + nscans = 10; + } else { + /* All-purpose script for other color spaces. */ + if (ncomps > MAX_COMPS_IN_SCAN) + nscans = 6 * ncomps; /* 2 DC + 4 AC scans per component */ + else + nscans = 2 + 4 * ncomps; /* 2 DC scans; 4 AC scans per component */ + } + + /* Allocate space for script. + * We need to put it in the permanent pool in case the application performs + * multiple compressions without changing the settings. To avoid a memory + * leak if jpeg_simple_progression is called repeatedly for the same JPEG + * object, we try to re-use previously allocated space, and we allocate + * enough space to handle YCbCr even if initially asked for grayscale. + */ + if (cinfo->script_space == NULL || cinfo->script_space_size < nscans) { + cinfo->script_space_size = MAX(nscans, 10); + cinfo->script_space = (jpeg_scan_info *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, + (size_t)cinfo->script_space_size * SIZEOF(jpeg_scan_info)); + } + scanptr = cinfo->script_space; + cinfo->scan_info = scanptr; + cinfo->num_scans = nscans; + + if (ncomps == 3 && cinfo->jpeg_color_space == JCS_YCbCr) { + /* Custom script for YCbCr color images. */ + /* Initial DC scan */ + scanptr = fill_dc_scans(scanptr, ncomps, 0, 1); + /* Initial AC scan: get some luma data out in a hurry */ + scanptr = fill_a_scan(scanptr, 0, 1, 5, 0, 2); + /* Chroma data is too small to be worth expending many scans on */ + scanptr = fill_a_scan(scanptr, 2, 1, 63, 0, 1); + scanptr = fill_a_scan(scanptr, 1, 1, 63, 0, 1); + /* Complete spectral selection for luma AC */ + scanptr = fill_a_scan(scanptr, 0, 6, 63, 0, 2); + /* Refine next bit of luma AC */ + scanptr = fill_a_scan(scanptr, 0, 1, 63, 2, 1); + /* Finish DC successive approximation */ + scanptr = fill_dc_scans(scanptr, ncomps, 1, 0); + /* Finish AC successive approximation */ + scanptr = fill_a_scan(scanptr, 2, 1, 63, 1, 0); + scanptr = fill_a_scan(scanptr, 1, 1, 63, 1, 0); + /* Luma bottom bit comes last since it's usually largest scan */ + scanptr = fill_a_scan(scanptr, 0, 1, 63, 1, 0); + } else { + /* All-purpose script for other color spaces. */ + /* Successive approximation first pass */ + scanptr = fill_dc_scans(scanptr, ncomps, 0, 1); + scanptr = fill_scans(scanptr, ncomps, 1, 5, 0, 2); + scanptr = fill_scans(scanptr, ncomps, 6, 63, 0, 2); + /* Successive approximation second pass */ + scanptr = fill_scans(scanptr, ncomps, 1, 63, 2, 1); + /* Successive approximation final pass */ + scanptr = fill_dc_scans(scanptr, ncomps, 1, 0); + scanptr = fill_scans(scanptr, ncomps, 1, 63, 1, 0); + } +} + +#endif /* C_PROGRESSIVE_SUPPORTED */ + + +#ifdef C_LOSSLESS_SUPPORTED + +/* + * Create a single-entry lossless-JPEG script containing all components. + * cinfo->num_components must be correct. + */ + +GLOBAL(void) +jpeg_simple_lossless (j_compress_ptr cinfo, int predictor, int point_transform) +{ + int ncomps = cinfo->num_components; + int nscans = 1; + int ci; + jpeg_scan_info * scanptr; + + /* Safety check to ensure start_compress not called yet. */ + if (cinfo->global_state != CSTATE_START) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + + cinfo->lossless = TRUE; + + /* Set jpeg_color_space. */ + jpeg_default_colorspace(cinfo); + + /* Check to ensure that all components will fit in one scan. */ + if (cinfo->num_components > MAX_COMPS_IN_SCAN) + ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components, + MAX_COMPS_IN_SCAN); + + /* Allocate space for script. + * We need to put it in the permanent pool in case the application performs + * multiple compressions without changing the settings. To avoid a memory + * leak if jpeg_simple_lossless is called repeatedly for the same JPEG + * object, we try to re-use previously allocated space. + */ + if (cinfo->script_space == NULL || cinfo->script_space_size < nscans) { + cinfo->script_space_size = nscans; + cinfo->script_space = (jpeg_scan_info *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, + (size_t)cinfo->script_space_size * SIZEOF(jpeg_scan_info)); + } + scanptr = cinfo->script_space; + cinfo->scan_info = scanptr; + cinfo->num_scans = nscans; + + /* Fill the script. */ + scanptr->comps_in_scan = ncomps; + for (ci = 0; ci < (int)ncomps; ci++) + scanptr->component_index[ci] = ci; + scanptr->Ss = predictor; + scanptr->Se = 0; + scanptr->Ah = 0; + scanptr->Al = point_transform; +} + +#endif /* C_LOSSLESS_SUPPORTED */ diff --git a/dcmjpeg/libijg12/jcphuff.c b/dcmjpeg/libijg12/jcphuff.c new file mode 100644 index 00000000..487958d6 --- /dev/null +++ b/dcmjpeg/libijg12/jcphuff.c @@ -0,0 +1,848 @@ +/* + * jcphuff.c + * + * Copyright (C) 1995-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains Huffman entropy encoding routines for progressive JPEG. + * + * We do not support output suspension in this module, since the library + * currently does not allow multiple-scan files to be written with output + * suspension. + */ + +#define JPEG_INTERNALS +#include "jinclude12.h" +#include "jpeglib12.h" +#include "jlossy12.h" /* Private declarations for lossy codec */ +#include "jchuff12.h" /* Declarations shared with jc*huff.c */ + +#ifdef C_PROGRESSIVE_SUPPORTED + +/* Expanded entropy encoder object for progressive Huffman encoding. */ + +typedef struct { + /* Mode flag: TRUE for optimization, FALSE for actual data output */ + boolean gather_statistics; + + /* Bit-level coding status. + * next_output_byte/free_in_buffer are local copies of cinfo->dest fields. + */ + JOCTET * next_output_byte; /* => next byte to write in buffer */ + size_t free_in_buffer; /* # of byte spaces remaining in buffer */ + IJG_INT32 put_buffer; /* current bit-accumulation buffer */ + int put_bits; /* # of bits now in it */ + j_compress_ptr cinfo; /* link to cinfo (needed for dump_buffer) */ + + /* Coding status for DC components */ + int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */ + + /* Coding status for AC components */ + int ac_tbl_no; /* the table number of the single component */ + unsigned int EOBRUN; /* run length of EOBs */ + unsigned int BE; /* # of buffered correction bits before MCU */ + char * bit_buffer; /* buffer for correction bits (1 per char) */ + /* packing correction bits tightly would save some space but cost time... */ + + unsigned int restarts_to_go; /* MCUs left in this restart interval */ + int next_restart_num; /* next restart number to write (0-7) */ + + /* Pointers to derived tables (these workspaces have image lifespan). + * Since any one scan codes only DC or only AC, we only need one set + * of tables, not one for DC and one for AC. + */ + c_derived_tbl * derived_tbls[NUM_HUFF_TBLS]; + + /* Statistics tables for optimization; again, one set is enough */ + long * count_ptrs[NUM_HUFF_TBLS]; +} phuff_entropy_encoder; + +typedef phuff_entropy_encoder * phuff_entropy_ptr; + +/* MAX_CORR_BITS is the number of bits the AC refinement correction-bit + * buffer can hold. Larger sizes may slightly improve compression, but + * 1000 is already well into the realm of overkill. + * The minimum safe size is 64 bits. + */ + +#define MAX_CORR_BITS 1000 /* Max # of correction bits I can buffer */ + +/* IRIGHT_SHIFT is like RIGHT_SHIFT, but works on int rather than IJG_INT32. + * We assume that int right shift is unsigned if IJG_INT32 right shift is, + * which should be safe. + */ + +#ifdef RIGHT_SHIFT_IS_UNSIGNED +#define ISHIFT_TEMPS int ishift_temp; +#define IRIGHT_SHIFT(x,shft) \ + ((ishift_temp = (x)) < 0 ? \ + (ishift_temp >> (shft)) | ((~0) << (16-(shft))) : \ + (ishift_temp >> (shft))) +#else +#define ISHIFT_TEMPS +#define IRIGHT_SHIFT(x,shft) ((x) >> (shft)) +#endif + +/* Forward declarations */ +METHODDEF(boolean) encode_mcu_DC_first JPP((j_compress_ptr cinfo, + JBLOCKROW *MCU_data)); +METHODDEF(boolean) encode_mcu_AC_first JPP((j_compress_ptr cinfo, + JBLOCKROW *MCU_data)); +METHODDEF(boolean) encode_mcu_DC_refine JPP((j_compress_ptr cinfo, + JBLOCKROW *MCU_data)); +METHODDEF(boolean) encode_mcu_AC_refine JPP((j_compress_ptr cinfo, + JBLOCKROW *MCU_data)); +METHODDEF(void) finish_pass_phuff JPP((j_compress_ptr cinfo)); +METHODDEF(void) finish_pass_gather_phuff JPP((j_compress_ptr cinfo)); + + +/* + * Initialize for a Huffman-compressed scan using progressive JPEG. + */ + +METHODDEF(void) +start_pass_phuff (j_compress_ptr cinfo, boolean gather_statistics) +{ + j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; + phuff_entropy_ptr entropy = (phuff_entropy_ptr) lossyc->entropy_private; + boolean is_DC_band; + int ci, tbl; + jpeg_component_info * compptr; + + entropy->cinfo = cinfo; + entropy->gather_statistics = gather_statistics; + + is_DC_band = (cinfo->Ss == 0); + + /* We assume jcmaster.c already validated the scan parameters. */ + + /* Select execution routines */ + if (cinfo->Ah == 0) { + if (is_DC_band) + lossyc->entropy_encode_mcu = encode_mcu_DC_first; + else + lossyc->entropy_encode_mcu = encode_mcu_AC_first; + } else { + if (is_DC_band) + lossyc->entropy_encode_mcu = encode_mcu_DC_refine; + else { + lossyc->entropy_encode_mcu = encode_mcu_AC_refine; + /* AC refinement needs a correction bit buffer */ + if (entropy->bit_buffer == NULL) + entropy->bit_buffer = (char *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + MAX_CORR_BITS * SIZEOF(char)); + } + } + if (gather_statistics) + lossyc->pub.entropy_finish_pass = finish_pass_gather_phuff; + else + lossyc->pub.entropy_finish_pass = finish_pass_phuff; + + /* Only DC coefficients may be interleaved, so cinfo->comps_in_scan = 1 + * for AC coefficients. + */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + /* Initialize DC predictions to 0 */ + entropy->last_dc_val[ci] = 0; + /* Get table index */ + if (is_DC_band) { + if (cinfo->Ah != 0) /* DC refinement needs no table */ + continue; + tbl = compptr->dc_tbl_no; + } else { + entropy->ac_tbl_no = tbl = compptr->ac_tbl_no; + } + if (gather_statistics) { + /* Check for invalid table index */ + /* (make_c_derived_tbl does this in the other path) */ + if (tbl < 0 || tbl >= NUM_HUFF_TBLS) + ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tbl); + /* Allocate and zero the statistics tables */ + /* Note that jpeg_gen_optimal_table expects 257 entries in each table! */ + if (entropy->count_ptrs[tbl] == NULL) + entropy->count_ptrs[tbl] = (long *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + 257 * SIZEOF(long)); + MEMZERO(entropy->count_ptrs[tbl], 257 * SIZEOF(long)); + } else { + /* Compute derived values for Huffman table */ + /* We may do this more than once for a table, but it's not expensive */ + jpeg_make_c_derived_tbl(cinfo, is_DC_band, tbl, + & entropy->derived_tbls[tbl]); + } + } + + /* Initialize AC stuff */ + entropy->EOBRUN = 0; + entropy->BE = 0; + + /* Initialize bit buffer to empty */ + entropy->put_buffer = 0; + entropy->put_bits = 0; + + /* Initialize restart stuff */ + entropy->restarts_to_go = cinfo->restart_interval; + entropy->next_restart_num = 0; +} + + +/* Outputting bytes to the file. + * NB: these must be called only when actually outputting, + * that is, entropy->gather_statistics == FALSE. + */ + +/* Emit a byte */ +#define emit_byte(entropy,val) \ + { *(entropy)->next_output_byte++ = (JOCTET) (val); \ + if (--(entropy)->free_in_buffer == 0) \ + dump_buffer(entropy); } + + +LOCAL(void) +dump_buffer (phuff_entropy_ptr entropy) +/* Empty the output buffer; we do not support suspension in this module. */ +{ + struct jpeg_destination_mgr * dest = entropy->cinfo->dest; + + if (! (*dest->empty_output_buffer) (entropy->cinfo)) + ERREXIT(entropy->cinfo, JERR_CANT_SUSPEND); + /* After a successful buffer dump, must reset buffer pointers */ + entropy->next_output_byte = dest->next_output_byte; + entropy->free_in_buffer = dest->free_in_buffer; +} + + +/* Outputting bits to the file */ + +/* Only the right 24 bits of put_buffer are used; the valid bits are + * left-justified in this part. At most 16 bits can be passed to emit_bits + * in one call, and we never retain more than 7 bits in put_buffer + * between calls, so 24 bits are sufficient. + */ + +INLINE +LOCAL(void) +emit_bits (phuff_entropy_ptr entropy, unsigned int code, int size) +/* Emit some bits, unless we are in gather mode */ +{ + /* This routine is heavily used, so it's worth coding tightly. */ + register IJG_INT32 put_buffer = (IJG_INT32) code; + register int put_bits = entropy->put_bits; + + /* if size is 0, caller used an invalid Huffman table entry */ + if (size == 0) + ERREXIT(entropy->cinfo, JERR_HUFF_MISSING_CODE); + + if (entropy->gather_statistics) + return; /* do nothing if we're only getting stats */ + + put_buffer &= (((IJG_INT32) 1)<put_buffer; /* and merge with old buffer contents */ + + while (put_bits >= 8) { + int c = (int) ((put_buffer >> 16) & 0xFF); + + emit_byte(entropy, c); + if (c == 0xFF) { /* need to stuff a zero byte? */ + emit_byte(entropy, 0); + } + put_buffer <<= 8; + put_bits -= 8; + } + + entropy->put_buffer = put_buffer; /* update variables */ + entropy->put_bits = put_bits; +} + + +LOCAL(void) +flush_bits (phuff_entropy_ptr entropy) +{ + emit_bits(entropy, 0x7F, 7); /* fill any partial byte with ones */ + entropy->put_buffer = 0; /* and reset bit-buffer to empty */ + entropy->put_bits = 0; +} + + +/* + * Emit (or just count) a Huffman symbol. + */ + +INLINE +LOCAL(void) +emit_symbol (phuff_entropy_ptr entropy, int tbl_no, int symbol) +{ + if (entropy->gather_statistics) + entropy->count_ptrs[tbl_no][symbol]++; + else { + c_derived_tbl * tbl = entropy->derived_tbls[tbl_no]; + emit_bits(entropy, tbl->ehufco[symbol], tbl->ehufsi[symbol]); + } +} + + +/* + * Emit bits from a correction bit buffer. + */ + +LOCAL(void) +emit_buffered_bits (phuff_entropy_ptr entropy, char * bufstart, + unsigned int nbits) +{ + if (entropy->gather_statistics) + return; /* no real work */ + + while (nbits > 0) { + emit_bits(entropy, (unsigned int) (*bufstart), 1); + bufstart++; + nbits--; + } +} + + +/* + * Emit any pending EOBRUN symbol. + */ + +LOCAL(void) +emit_eobrun (phuff_entropy_ptr entropy) +{ + register int temp, nbits; + + if (entropy->EOBRUN > 0) { /* if there is any pending EOBRUN */ + temp = (int)entropy->EOBRUN; + nbits = 0; + while ((temp >>= 1)) + nbits++; + /* safety check: shouldn't happen given limited correction-bit buffer */ + if (nbits > 14) + ERREXIT(entropy->cinfo, JERR_HUFF_MISSING_CODE); + + emit_symbol(entropy, entropy->ac_tbl_no, nbits << 4); + if (nbits) + emit_bits(entropy, entropy->EOBRUN, nbits); + + entropy->EOBRUN = 0; + + /* Emit any buffered correction bits */ + emit_buffered_bits(entropy, entropy->bit_buffer, entropy->BE); + entropy->BE = 0; + } +} + + +/* + * Emit a restart marker & resynchronize predictions. + */ + +LOCAL(void) +emit_restart (phuff_entropy_ptr entropy, int restart_num) +{ + int ci; + + emit_eobrun(entropy); + + if (! entropy->gather_statistics) { + flush_bits(entropy); + emit_byte(entropy, 0xFF); + emit_byte(entropy, JPEG_RST0 + restart_num); + } + + if (entropy->cinfo->Ss == 0) { + /* Re-initialize DC predictions to 0 */ + for (ci = 0; ci < entropy->cinfo->comps_in_scan; ci++) + entropy->last_dc_val[ci] = 0; + } else { + /* Re-initialize all AC-related fields to 0 */ + entropy->EOBRUN = 0; + entropy->BE = 0; + } +} + + +/* + * MCU encoding for DC initial scan (either spectral selection, + * or first pass of successive approximation). + */ + +METHODDEF(boolean) +encode_mcu_DC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data) +{ + j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; + phuff_entropy_ptr entropy = (phuff_entropy_ptr) lossyc->entropy_private; + register int temp, temp2; + register int nbits; + int blkn, ci; + int Al = cinfo->Al; + JBLOCKROW block; + jpeg_component_info * compptr; + ISHIFT_TEMPS + + entropy->next_output_byte = cinfo->dest->next_output_byte; + entropy->free_in_buffer = cinfo->dest->free_in_buffer; + + /* Emit restart marker if needed */ + if (cinfo->restart_interval) + if (entropy->restarts_to_go == 0) + emit_restart(entropy, entropy->next_restart_num); + + /* Encode the MCU data blocks */ + for (blkn = 0; blkn < cinfo->data_units_in_MCU; blkn++) { + block = MCU_data[blkn]; + ci = cinfo->MCU_membership[blkn]; + compptr = cinfo->cur_comp_info[ci]; + + /* Compute the DC value after the required point transform by Al. + * This is simply an arithmetic right shift. + */ + temp2 = IRIGHT_SHIFT((int) ((*block)[0]), Al); + + /* DC differences are figured on the point-transformed values. */ + temp = temp2 - entropy->last_dc_val[ci]; + entropy->last_dc_val[ci] = temp2; + + /* Encode the DC coefficient difference per section G.1.2.1 */ + temp2 = temp; + if (temp < 0) { + temp = -temp; /* temp is abs value of input */ + /* For a negative input, want temp2 = bitwise complement of abs(input) */ + /* This code assumes we are on a two's complement machine */ + temp2--; + } + + /* Find the number of bits needed for the magnitude of the coefficient */ + nbits = 0; + while (temp) { + nbits++; + temp >>= 1; + } + /* Check for out-of-range coefficient values. + * Since we're encoding a difference, the range limit is twice as much. + */ + if (nbits > MAX_COEF_BITS+1) + ERREXIT(cinfo, JERR_BAD_DCT_COEF); + + /* Count/emit the Huffman-coded symbol for the number of bits */ + emit_symbol(entropy, compptr->dc_tbl_no, nbits); + + /* Emit that number of bits of the value, if positive, */ + /* or the complement of its magnitude, if negative. */ + if (nbits) /* emit_bits rejects calls with size 0 */ + emit_bits(entropy, (unsigned int) temp2, nbits); + } + + cinfo->dest->next_output_byte = entropy->next_output_byte; + cinfo->dest->free_in_buffer = entropy->free_in_buffer; + + /* Update restart-interval state too */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) { + entropy->restarts_to_go = cinfo->restart_interval; + entropy->next_restart_num++; + entropy->next_restart_num &= 7; + } + entropy->restarts_to_go--; + } + + return TRUE; +} + + +/* + * MCU encoding for AC initial scan (either spectral selection, + * or first pass of successive approximation). + */ + +METHODDEF(boolean) +encode_mcu_AC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data) +{ + j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; + phuff_entropy_ptr entropy = (phuff_entropy_ptr) lossyc->entropy_private; + register int temp, temp2; + register int nbits; + register int r, k; + int Se = cinfo->Se; + int Al = cinfo->Al; + JBLOCKROW block; + + entropy->next_output_byte = cinfo->dest->next_output_byte; + entropy->free_in_buffer = cinfo->dest->free_in_buffer; + + /* Emit restart marker if needed */ + if (cinfo->restart_interval) + if (entropy->restarts_to_go == 0) + emit_restart(entropy, entropy->next_restart_num); + + /* Encode the MCU data block */ + block = MCU_data[0]; + + /* Encode the AC coefficients per section G.1.2.2, fig. G.3 */ + + r = 0; /* r = run length of zeros */ + + for (k = cinfo->Ss; k <= Se; k++) { + if ((temp = (*block)[jpeg_natural_order[k]]) == 0) { + r++; + continue; + } + /* We must apply the point transform by Al. For AC coefficients this + * is an integer division with rounding towards 0. To do this portably + * in C, we shift after obtaining the absolute value; so the code is + * interwoven with finding the abs value (temp) and output bits (temp2). + */ + if (temp < 0) { + temp = -temp; /* temp is abs value of input */ + temp >>= Al; /* apply the point transform */ + /* For a negative coef, want temp2 = bitwise complement of abs(coef) */ + temp2 = ~temp; + } else { + temp >>= Al; /* apply the point transform */ + temp2 = temp; + } + /* Watch out for case that nonzero coef is zero after point transform */ + if (temp == 0) { + r++; + continue; + } + + /* Emit any pending EOBRUN */ + if (entropy->EOBRUN > 0) + emit_eobrun(entropy); + /* if run length > 15, must emit special run-length-16 codes (0xF0) */ + while (r > 15) { + emit_symbol(entropy, entropy->ac_tbl_no, 0xF0); + r -= 16; + } + + /* Find the number of bits needed for the magnitude of the coefficient */ + nbits = 1; /* there must be at least one 1 bit */ + while ((temp >>= 1)) + nbits++; + /* Check for out-of-range coefficient values */ + if (nbits > MAX_COEF_BITS) + ERREXIT(cinfo, JERR_BAD_DCT_COEF); + + /* Count/emit Huffman symbol for run length / number of bits */ + emit_symbol(entropy, entropy->ac_tbl_no, (r << 4) + nbits); + + /* Emit that number of bits of the value, if positive, */ + /* or the complement of its magnitude, if negative. */ + emit_bits(entropy, (unsigned int) temp2, nbits); + + r = 0; /* reset zero run length */ + } + + if (r > 0) { /* If there are trailing zeroes, */ + entropy->EOBRUN++; /* count an EOB */ + if (entropy->EOBRUN == 0x7FFF) + emit_eobrun(entropy); /* force it out to avoid overflow */ + } + + cinfo->dest->next_output_byte = entropy->next_output_byte; + cinfo->dest->free_in_buffer = entropy->free_in_buffer; + + /* Update restart-interval state too */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) { + entropy->restarts_to_go = cinfo->restart_interval; + entropy->next_restart_num++; + entropy->next_restart_num &= 7; + } + entropy->restarts_to_go--; + } + + return TRUE; +} + + +/* + * MCU encoding for DC successive approximation refinement scan. + * Note: we assume such scans can be multi-component, although the spec + * is not very clear on the point. + */ + +METHODDEF(boolean) +encode_mcu_DC_refine (j_compress_ptr cinfo, JBLOCKROW *MCU_data) +{ + j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; + phuff_entropy_ptr entropy = (phuff_entropy_ptr) lossyc->entropy_private; + register int temp; + int blkn; + int Al = cinfo->Al; + JBLOCKROW block; + + entropy->next_output_byte = cinfo->dest->next_output_byte; + entropy->free_in_buffer = cinfo->dest->free_in_buffer; + + /* Emit restart marker if needed */ + if (cinfo->restart_interval) + if (entropy->restarts_to_go == 0) + emit_restart(entropy, entropy->next_restart_num); + + /* Encode the MCU data blocks */ + for (blkn = 0; blkn < cinfo->data_units_in_MCU; blkn++) { + block = MCU_data[blkn]; + + /* We simply emit the Al'th bit of the DC coefficient value. */ + temp = (*block)[0]; + emit_bits(entropy, (unsigned int) (temp >> Al), 1); + } + + cinfo->dest->next_output_byte = entropy->next_output_byte; + cinfo->dest->free_in_buffer = entropy->free_in_buffer; + + /* Update restart-interval state too */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) { + entropy->restarts_to_go = cinfo->restart_interval; + entropy->next_restart_num++; + entropy->next_restart_num &= 7; + } + entropy->restarts_to_go--; + } + + return TRUE; +} + + +/* + * MCU encoding for AC successive approximation refinement scan. + */ + +METHODDEF(boolean) +encode_mcu_AC_refine (j_compress_ptr cinfo, JBLOCKROW *MCU_data) +{ + j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; + phuff_entropy_ptr entropy = (phuff_entropy_ptr) lossyc->entropy_private; + register int temp; + register int r, k; + int EOB; + char *BR_buffer; + unsigned int BR; + int Se = cinfo->Se; + int Al = cinfo->Al; + JBLOCKROW block; + int absvalues[DCTSIZE2]; + + entropy->next_output_byte = cinfo->dest->next_output_byte; + entropy->free_in_buffer = cinfo->dest->free_in_buffer; + + /* Emit restart marker if needed */ + if (cinfo->restart_interval) + if (entropy->restarts_to_go == 0) + emit_restart(entropy, entropy->next_restart_num); + + /* Encode the MCU data block */ + block = MCU_data[0]; + + /* It is convenient to make a pre-pass to determine the transformed + * coefficients' absolute values and the EOB position. + */ + EOB = 0; + for (k = cinfo->Ss; k <= Se; k++) { + temp = (*block)[jpeg_natural_order[k]]; + /* We must apply the point transform by Al. For AC coefficients this + * is an integer division with rounding towards 0. To do this portably + * in C, we shift after obtaining the absolute value. + */ + if (temp < 0) + temp = -temp; /* temp is abs value of input */ + temp >>= Al; /* apply the point transform */ + absvalues[k] = temp; /* save abs value for main pass */ + if (temp == 1) + EOB = k; /* EOB = index of last newly-nonzero coef */ + } + + /* Encode the AC coefficients per section G.1.2.3, fig. G.7 */ + + r = 0; /* r = run length of zeros */ + BR = 0; /* BR = count of buffered bits added now */ + BR_buffer = entropy->bit_buffer + entropy->BE; /* Append bits to buffer */ + + for (k = cinfo->Ss; k <= Se; k++) { + if ((temp = absvalues[k]) == 0) { + r++; + continue; + } + + /* Emit any required ZRLs, but not if they can be folded into EOB */ + while (r > 15 && k <= EOB) { + /* emit any pending EOBRUN and the BE correction bits */ + emit_eobrun(entropy); + /* Emit ZRL */ + emit_symbol(entropy, entropy->ac_tbl_no, 0xF0); + r -= 16; + /* Emit buffered correction bits that must be associated with ZRL */ + emit_buffered_bits(entropy, BR_buffer, BR); + BR_buffer = entropy->bit_buffer; /* BE bits are gone now */ + BR = 0; + } + + /* If the coef was previously nonzero, it only needs a correction bit. + * NOTE: a straight translation of the spec's figure G.7 would suggest + * that we also need to test r > 15. But if r > 15, we can only get here + * if k > EOB, which implies that this coefficient is not 1. + */ + if (temp > 1) { + /* The correction bit is the next bit of the absolute value. */ + BR_buffer[BR++] = (char) (temp & 1); + continue; + } + + /* Emit any pending EOBRUN and the BE correction bits */ + emit_eobrun(entropy); + + /* Count/emit Huffman symbol for run length / number of bits */ + emit_symbol(entropy, entropy->ac_tbl_no, (r << 4) + 1); + + /* Emit output bit for newly-nonzero coef */ + temp = ((*block)[jpeg_natural_order[k]] < 0) ? 0 : 1; + emit_bits(entropy, (unsigned int) temp, 1); + + /* Emit buffered correction bits that must be associated with this code */ + emit_buffered_bits(entropy, BR_buffer, BR); + BR_buffer = entropy->bit_buffer; /* BE bits are gone now */ + BR = 0; + r = 0; /* reset zero run length */ + } + + if (r > 0 || BR > 0) { /* If there are trailing zeroes, */ + entropy->EOBRUN++; /* count an EOB */ + entropy->BE += BR; /* concat my correction bits to older ones */ + /* We force out the EOB if we risk either: + * 1. overflow of the EOB counter; + * 2. overflow of the correction bit buffer during the next MCU. + */ + if (entropy->EOBRUN == 0x7FFF || entropy->BE > (MAX_CORR_BITS-DCTSIZE2+1)) + emit_eobrun(entropy); + } + + cinfo->dest->next_output_byte = entropy->next_output_byte; + cinfo->dest->free_in_buffer = entropy->free_in_buffer; + + /* Update restart-interval state too */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) { + entropy->restarts_to_go = cinfo->restart_interval; + entropy->next_restart_num++; + entropy->next_restart_num &= 7; + } + entropy->restarts_to_go--; + } + + return TRUE; +} + + +/* + * Finish up at the end of a Huffman-compressed progressive scan. + */ + +METHODDEF(void) +finish_pass_phuff (j_compress_ptr cinfo) +{ + j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; + phuff_entropy_ptr entropy = (phuff_entropy_ptr) lossyc->entropy_private; + + entropy->next_output_byte = cinfo->dest->next_output_byte; + entropy->free_in_buffer = cinfo->dest->free_in_buffer; + + /* Flush out any buffered data */ + emit_eobrun(entropy); + flush_bits(entropy); + + cinfo->dest->next_output_byte = entropy->next_output_byte; + cinfo->dest->free_in_buffer = entropy->free_in_buffer; +} + + +/* + * Finish up a statistics-gathering pass and create the new Huffman tables. + */ + +METHODDEF(void) +finish_pass_gather_phuff (j_compress_ptr cinfo) +{ + j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; + phuff_entropy_ptr entropy = (phuff_entropy_ptr) lossyc->entropy_private; + boolean is_DC_band; + int ci, tbl; + jpeg_component_info * compptr; + JHUFF_TBL **htblptr; + boolean did[NUM_HUFF_TBLS]; + + /* Flush out buffered data (all we care about is counting the EOB symbol) */ + emit_eobrun(entropy); + + is_DC_band = (cinfo->Ss == 0); + + /* It's important not to apply jpeg_gen_optimal_table more than once + * per table, because it clobbers the input frequency counts! + */ + MEMZERO(did, SIZEOF(did)); + + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + if (is_DC_band) { + if (cinfo->Ah != 0) /* DC refinement needs no table */ + continue; + tbl = compptr->dc_tbl_no; + } else { + tbl = compptr->ac_tbl_no; + } + if (! did[tbl]) { + if (is_DC_band) + htblptr = & cinfo->dc_huff_tbl_ptrs[tbl]; + else + htblptr = & cinfo->ac_huff_tbl_ptrs[tbl]; + if (*htblptr == NULL) + *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo); + jpeg_gen_optimal_table(cinfo, *htblptr, entropy->count_ptrs[tbl]); + did[tbl] = TRUE; + } + } +} + + +METHODDEF(boolean) +need_optimization_pass (j_compress_ptr cinfo) +{ + return (cinfo->Ss != 0 || cinfo->Ah == 0); +} + + +/* + * Module initialization routine for progressive Huffman entropy encoding. + */ + +GLOBAL(void) +jinit_phuff_encoder (j_compress_ptr cinfo) +{ + j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; + phuff_entropy_ptr entropy; + int i; + + entropy = (phuff_entropy_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(phuff_entropy_encoder)); + lossyc->entropy_private = (struct jpeg_entropy_encoder *) entropy; + lossyc->pub.entropy_start_pass = start_pass_phuff; + lossyc->pub.need_optimization_pass = need_optimization_pass; + + /* Mark tables unallocated */ + for (i = 0; i < NUM_HUFF_TBLS; i++) { + entropy->derived_tbls[i] = NULL; + entropy->count_ptrs[i] = NULL; + } + entropy->bit_buffer = NULL; /* needed only in AC refinement scan */ +} + +#endif /* C_PROGRESSIVE_SUPPORTED */ diff --git a/dcmjpeg/libijg12/jcpred.c b/dcmjpeg/libijg12/jcpred.c new file mode 100644 index 00000000..e7a798c0 --- /dev/null +++ b/dcmjpeg/libijg12/jcpred.c @@ -0,0 +1,314 @@ +/* + * jcpred.c + * + * Copyright (C) 1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains sample differencing for lossless JPEG. + * + * In order to avoid paying the performance penalty of having to check the + * predictor being used and the row being processed for each call of the + * undifferencer, and to promote optimization, we have separate differencing + * functions for each case. + * + * We are able to avoid duplicating source code by implementing the predictors + * and differencers as macros. Each of the differencing functions are + * simply wrappers around a DIFFERENCE macro with the appropriate PREDICTOR + * macro passed as an argument. + */ + +#define JPEG_INTERNALS +#include "jinclude12.h" +#include "jpeglib12.h" +#include "jlossls12.h" /* Private declarations for lossless codec */ + + +#ifdef C_LOSSLESS_SUPPORTED + +/* Private predictor object */ + +typedef struct { + /* MCU-rows left in the restart interval for each component */ + unsigned int restart_rows_to_go[MAX_COMPONENTS]; +} c_predictor; + +typedef c_predictor * c_pred_ptr; + +/* Forward declarations */ +LOCAL(void) reset_predictor + JPP((j_compress_ptr cinfo, int ci)); +METHODDEF(void) start_pass + JPP((j_compress_ptr cinfo)); + + +/* Predictor for the first column of the first row: 2^(P-Pt-1) */ +#define INITIAL_PREDICTORx (1 << (cinfo->data_precision - cinfo->Al - 1)) + +/* Predictor for the first column of the remaining rows: Rb */ +#define INITIAL_PREDICTOR2 GETJSAMPLE(prev_row[0]) + + +/* + * 1-Dimensional differencer routine. + * + * This macro implements the 1-D horizontal predictor (1). INITIAL_PREDICTOR + * is used as the special case predictor for the first column, which must be + * either INITIAL_PREDICTOR2 or INITIAL_PREDICTORx. The remaining samples + * use PREDICTOR1. + */ + +#define DIFFERENCE_1D(INITIAL_PREDICTOR) \ + j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec; \ + c_pred_ptr pred = (c_pred_ptr) losslsc->pred_private; \ + boolean restart = FALSE; \ + unsigned int xindex; \ + int samp, Ra; \ + \ + samp = GETJSAMPLE(input_buf[0]); \ + diff_buf[0] = samp - INITIAL_PREDICTOR; \ + \ + for (xindex = 1; xindex < width; xindex++) { \ + Ra = samp; \ + samp = GETJSAMPLE(input_buf[xindex]); \ + diff_buf[xindex] = samp - PREDICTOR1; \ + } \ + \ + /* Account for restart interval (no-op if not using restarts) */ \ + if (cinfo->restart_interval) { \ + if (--(pred->restart_rows_to_go[ci]) == 0) { \ + reset_predictor(cinfo, ci); \ + restart = TRUE; \ + } \ + } + + +/* + * 2-Dimensional differencer routine. + * + * This macro implements the 2-D horizontal predictors (#2-7). PREDICTOR2 is + * used as the special case predictor for the first column. The remaining + * samples use PREDICTOR, which is a function of Ra, Rb, Rc. + * + * Because prev_row and output_buf may point to the same storage area (in an + * interleaved image with Vi=1, for example), we must take care to buffer Rb/Rc + * before writing the current reconstructed sample value into output_buf. + */ + +#define DIFFERENCE_2D(PREDICTOR) \ + j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec; \ + c_pred_ptr pred = (c_pred_ptr) losslsc->pred_private; \ + unsigned int xindex; \ + int samp, Ra, Rb, Rc; \ + \ + Rb = GETJSAMPLE(prev_row[0]); \ + samp = GETJSAMPLE(input_buf[0]); \ + diff_buf[0] = samp - PREDICTOR2; \ + \ + for (xindex = 1; xindex < width; xindex++) { \ + Rc = Rb; \ + Rb = GETJSAMPLE(prev_row[xindex]); \ + Ra = samp; \ + samp = GETJSAMPLE(input_buf[xindex]); \ + diff_buf[xindex] = samp - PREDICTOR; \ + } \ + \ + /* Account for restart interval (no-op if not using restarts) */ \ + if (cinfo->restart_interval) { \ + if (--pred->restart_rows_to_go[ci] == 0) \ + reset_predictor(cinfo, ci); \ + } + +#define JPEG_UNUSED(x) ((void)x) + +/* + * Differencers for the all rows but the first in a scan or restart interval. + * The first sample in the row is differenced using the vertical + * predictor (2). The rest of the samples are differenced using the + * predictor specified in the scan header. + */ + +METHODDEF(void) +jpeg_difference1(j_compress_ptr cinfo, int ci, + JSAMPROW input_buf, JSAMPROW prev_row, + JDIFFROW diff_buf, JDIMENSION width) +{ + DIFFERENCE_1D(INITIAL_PREDICTOR2); + JPEG_UNUSED(restart); +} + +METHODDEF(void) +jpeg_difference2(j_compress_ptr cinfo, int ci, + JSAMPROW input_buf, JSAMPROW prev_row, + JDIFFROW diff_buf, JDIMENSION width) +{ + DIFFERENCE_2D(PREDICTOR2); + JPEG_UNUSED(Rc); + JPEG_UNUSED(Ra); +} + +METHODDEF(void) +jpeg_difference3(j_compress_ptr cinfo, int ci, + JSAMPROW input_buf, JSAMPROW prev_row, + JDIFFROW diff_buf, JDIMENSION width) +{ + DIFFERENCE_2D(PREDICTOR3); + JPEG_UNUSED(Rc); + JPEG_UNUSED(Ra); +} + +METHODDEF(void) +jpeg_difference4(j_compress_ptr cinfo, int ci, + JSAMPROW input_buf, JSAMPROW prev_row, + JDIFFROW diff_buf, JDIMENSION width) +{ + DIFFERENCE_2D(PREDICTOR4); + JPEG_UNUSED(Rc); + JPEG_UNUSED(Ra); +} + +METHODDEF(void) +jpeg_difference5(j_compress_ptr cinfo, int ci, + JSAMPROW input_buf, JSAMPROW prev_row, + JDIFFROW diff_buf, JDIMENSION width) +{ + SHIFT_TEMPS + DIFFERENCE_2D(PREDICTOR5); + JPEG_UNUSED(Rc); + JPEG_UNUSED(Ra); +} + +METHODDEF(void) +jpeg_difference6(j_compress_ptr cinfo, int ci, + JSAMPROW input_buf, JSAMPROW prev_row, + JDIFFROW diff_buf, JDIMENSION width) +{ + SHIFT_TEMPS + DIFFERENCE_2D(PREDICTOR6); + JPEG_UNUSED(Rc); + JPEG_UNUSED(Ra); +} + +METHODDEF(void) +jpeg_difference7(j_compress_ptr cinfo, int ci, + JSAMPROW input_buf, JSAMPROW prev_row, + JDIFFROW diff_buf, JDIMENSION width) +{ + SHIFT_TEMPS + DIFFERENCE_2D(PREDICTOR7); + JPEG_UNUSED(Rc); + JPEG_UNUSED(Ra); +} + + +/* + * Differencer for the first row in a scan or restart interval. The first + * sample in the row is differenced using the special predictor constant + * x=2^(P-Pt-1). The rest of the samples are differenced using the + * 1-D horizontal predictor (1). + */ + +METHODDEF(void) +jpeg_difference_first_row(j_compress_ptr cinfo, int ci, + JSAMPROW input_buf, JSAMPROW prev_row, + JDIFFROW diff_buf, JDIMENSION width) +{ + DIFFERENCE_1D(INITIAL_PREDICTORx); + + /* + * Now that we have differenced the first row, we want to use the + * differencer which corresponds to the predictor specified in the + * scan header. + * + * Note that we don't to do this if we have just reset the predictor + * for a new restart interval. + */ + if (!restart) { + switch (cinfo->Ss) { + case 1: + losslsc->predict_difference[ci] = jpeg_difference1; + break; + case 2: + losslsc->predict_difference[ci] = jpeg_difference2; + break; + case 3: + losslsc->predict_difference[ci] = jpeg_difference3; + break; + case 4: + losslsc->predict_difference[ci] = jpeg_difference4; + break; + case 5: + losslsc->predict_difference[ci] = jpeg_difference5; + break; + case 6: + losslsc->predict_difference[ci] = jpeg_difference6; + break; + case 7: + losslsc->predict_difference[ci] = jpeg_difference7; + break; + } + } +} + +/* + * Reset predictor at the start of a pass or restart interval. + */ + +LOCAL(void) +reset_predictor (j_compress_ptr cinfo, int ci) +{ + j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec; + c_pred_ptr pred = (c_pred_ptr) losslsc->pred_private; + + /* Initialize restart counter */ + pred->restart_rows_to_go[ci] = + cinfo->restart_interval / cinfo->MCUs_per_row; + + /* Set difference function to first row function */ + losslsc->predict_difference[ci] = jpeg_difference_first_row; +} + + +/* + * Initialize for an input processing pass. + */ + +METHODDEF(void) +start_pass (j_compress_ptr cinfo) +{ + /* j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec; */ + /* c_pred_ptr pred = (c_pred_ptr) losslsc->pred_private; */ + int ci; + + /* Check that the restart interval is an integer multiple of the number + * of MCU in an MCU-row. + */ + if (cinfo->restart_interval % cinfo->MCUs_per_row != 0) + ERREXIT2(cinfo, JERR_BAD_RESTART, + (int)cinfo->restart_interval, (int)cinfo->MCUs_per_row); + + /* Set predictors for start of pass */ + for (ci = 0; ci < cinfo->num_components; ci++) + reset_predictor(cinfo, ci); +} + + +/* + * Module initialization routine for the differencer. + */ + +GLOBAL(void) +jinit_differencer (j_compress_ptr cinfo) +{ + j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec; + c_pred_ptr pred; + + pred = (c_pred_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(c_predictor)); + losslsc->pred_private = (void *) pred; + losslsc->predict_start_pass = start_pass; +} + +#endif /* C_LOSSLESS_SUPPORTED */ + diff --git a/dcmjpeg/libijg12/jcprepct.c b/dcmjpeg/libijg12/jcprepct.c new file mode 100644 index 00000000..36c5f88a --- /dev/null +++ b/dcmjpeg/libijg12/jcprepct.c @@ -0,0 +1,354 @@ +/* + * jcprepct.c + * + * Copyright (C) 1994-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains the compression preprocessing controller. + * This controller manages the color conversion, downsampling, + * and edge expansion steps. + * + * Most of the complexity here is associated with buffering input rows + * as required by the downsampler. See the comments at the head of + * jcsample.c for the downsampler's needs. + */ + +#define JPEG_INTERNALS +#include "jinclude12.h" +#include "jpeglib12.h" + + +/* At present, jcsample.c can request context rows only for smoothing. + * In the future, we might also need context rows for CCIR601 sampling + * or other more-complex downsampling procedures. The code to support + * context rows should be compiled only if needed. + */ +#ifdef INPUT_SMOOTHING_SUPPORTED +#define CONTEXT_ROWS_SUPPORTED +#endif + + +/* + * For the simple (no-context-row) case, we just need to buffer one + * row group's worth of pixels for the downsampling step. At the bottom of + * the image, we pad to a full row group by replicating the last pixel row. + * The downsampler's last output row is then replicated if needed to pad + * out to a full iMCU row. + * + * When providing context rows, we must buffer three row groups' worth of + * pixels. Three row groups are physically allocated, but the row pointer + * arrays are made five row groups high, with the extra pointers above and + * below "wrapping around" to point to the last and first real row groups. + * This allows the downsampler to access the proper context rows. + * At the top and bottom of the image, we create dummy context rows by + * copying the first or last real pixel row. This copying could be avoided + * by pointer hacking as is done in jdmainct.c, but it doesn't seem worth the + * trouble on the compression side. + */ + + +/* Private buffer controller object */ + +typedef struct { + struct jpeg_c_prep_controller pub; /* public fields */ + + /* Downsampling input buffer. This buffer holds color-converted data + * until we have enough to do a downsample step. + */ + JSAMPARRAY color_buf[MAX_COMPONENTS]; + + JDIMENSION rows_to_go; /* counts rows remaining in source image */ + int next_buf_row; /* index of next row to store in color_buf */ + +#ifdef CONTEXT_ROWS_SUPPORTED /* only needed for context case */ + int this_row_group; /* starting row index of group to process */ + int next_buf_stop; /* downsample when we reach this index */ +#endif +} my_prep_controller; + +typedef my_prep_controller * my_prep_ptr; + + +/* + * Initialize for a processing pass. + */ + +METHODDEF(void) +start_pass_prep (j_compress_ptr cinfo, J_BUF_MODE pass_mode) +{ + my_prep_ptr prep = (my_prep_ptr) cinfo->prep; + + if (pass_mode != JBUF_PASS_THRU) + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + + /* Initialize total-height counter for detecting bottom of image */ + prep->rows_to_go = cinfo->image_height; + /* Mark the conversion buffer empty */ + prep->next_buf_row = 0; +#ifdef CONTEXT_ROWS_SUPPORTED + /* Preset additional state variables for context mode. + * These aren't used in non-context mode, so we needn't test which mode. + */ + prep->this_row_group = 0; + /* Set next_buf_stop to stop after two row groups have been read in. */ + prep->next_buf_stop = 2 * cinfo->max_v_samp_factor; +#endif +} + + +/* + * Expand an image vertically from height input_rows to height output_rows, + * by duplicating the bottom row. + */ + +LOCAL(void) +expand_bottom_edge (JSAMPARRAY image_data, JDIMENSION num_cols, + int input_rows, int output_rows) +{ + register int row; + + for (row = input_rows; row < output_rows; row++) { + jcopy_sample_rows(image_data, input_rows-1, image_data, row, + 1, num_cols); + } +} + + +/* + * Process some data in the simple no-context case. + * + * Preprocessor output data is counted in "row groups". A row group + * is defined to be v_samp_factor sample rows of each component. + * Downsampling will produce this much data from each max_v_samp_factor + * input rows. + */ + +METHODDEF(void) +pre_process_data (j_compress_ptr cinfo, + JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, + JDIMENSION in_rows_avail, + JSAMPIMAGE output_buf, JDIMENSION *out_row_group_ctr, + JDIMENSION out_row_groups_avail) +{ + my_prep_ptr prep = (my_prep_ptr) cinfo->prep; + int numrows, ci; + JDIMENSION inrows; + jpeg_component_info * compptr; + + while (*in_row_ctr < in_rows_avail && + *out_row_group_ctr < out_row_groups_avail) { + /* Do color conversion to fill the conversion buffer. */ + inrows = in_rows_avail - *in_row_ctr; + numrows = cinfo->max_v_samp_factor - prep->next_buf_row; + numrows = (int) MIN((JDIMENSION) numrows, inrows); + (*cinfo->cconvert->color_convert) (cinfo, input_buf + *in_row_ctr, + prep->color_buf, + (JDIMENSION) prep->next_buf_row, + numrows); + *in_row_ctr += (JDIMENSION)numrows; + prep->next_buf_row += numrows; + prep->rows_to_go -= (JDIMENSION)numrows; + /* If at bottom of image, pad to fill the conversion buffer. */ + if (prep->rows_to_go == 0 && + prep->next_buf_row < cinfo->max_v_samp_factor) { + for (ci = 0; ci < cinfo->num_components; ci++) { + expand_bottom_edge(prep->color_buf[ci], cinfo->image_width, + prep->next_buf_row, cinfo->max_v_samp_factor); + } + prep->next_buf_row = cinfo->max_v_samp_factor; + } + /* If we've filled the conversion buffer, empty it. */ + if (prep->next_buf_row == cinfo->max_v_samp_factor) { + (*cinfo->downsample->downsample) (cinfo, + prep->color_buf, (JDIMENSION) 0, + output_buf, *out_row_group_ctr); + prep->next_buf_row = 0; + (*out_row_group_ctr)++; + } + /* If at bottom of image, pad the output to a full iMCU height. + * Note we assume the caller is providing a one-iMCU-height output buffer! + */ + if (prep->rows_to_go == 0 && + *out_row_group_ctr < out_row_groups_avail) { + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + expand_bottom_edge(output_buf[ci], + compptr->width_in_data_units * (JDIMENSION)cinfo->data_unit, + (int)*out_row_group_ctr * compptr->v_samp_factor, + (int)out_row_groups_avail * compptr->v_samp_factor); + } + *out_row_group_ctr = out_row_groups_avail; + break; /* can exit outer loop without test */ + } + } +} + + +#ifdef CONTEXT_ROWS_SUPPORTED + +/* + * Process some data in the context case. + */ + +METHODDEF(void) +pre_process_context (j_compress_ptr cinfo, + JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, + JDIMENSION in_rows_avail, + JSAMPIMAGE output_buf, JDIMENSION *out_row_group_ctr, + JDIMENSION out_row_groups_avail) +{ + my_prep_ptr prep = (my_prep_ptr) cinfo->prep; + int numrows, ci; + int buf_height = cinfo->max_v_samp_factor * 3; + JDIMENSION inrows; + + while (*out_row_group_ctr < out_row_groups_avail) { + if (*in_row_ctr < in_rows_avail) { + /* Do color conversion to fill the conversion buffer. */ + inrows = in_rows_avail - *in_row_ctr; + numrows = prep->next_buf_stop - prep->next_buf_row; + numrows = (int) MIN((JDIMENSION) numrows, inrows); + (*cinfo->cconvert->color_convert) (cinfo, input_buf + *in_row_ctr, + prep->color_buf, + (JDIMENSION) prep->next_buf_row, + numrows); + /* Pad at top of image, if first time through */ + if (prep->rows_to_go == cinfo->image_height) { + for (ci = 0; ci < cinfo->num_components; ci++) { + int row; + for (row = 1; row <= cinfo->max_v_samp_factor; row++) { + jcopy_sample_rows(prep->color_buf[ci], 0, + prep->color_buf[ci], -row, + 1, cinfo->image_width); + } + } + } + *in_row_ctr += (JDIMENSION)numrows; + prep->next_buf_row += numrows; + prep->rows_to_go -= (JDIMENSION)numrows; + } else { + /* Return for more data, unless we are at the bottom of the image. */ + if (prep->rows_to_go != 0) + break; + /* When at bottom of image, pad to fill the conversion buffer. */ + if (prep->next_buf_row < prep->next_buf_stop) { + for (ci = 0; ci < cinfo->num_components; ci++) { + expand_bottom_edge(prep->color_buf[ci], cinfo->image_width, + prep->next_buf_row, prep->next_buf_stop); + } + prep->next_buf_row = prep->next_buf_stop; + } + } + /* If we've gotten enough data, downsample a row group. */ + if (prep->next_buf_row == prep->next_buf_stop) { + (*cinfo->downsample->downsample) (cinfo, + prep->color_buf, + (JDIMENSION) prep->this_row_group, + output_buf, *out_row_group_ctr); + (*out_row_group_ctr)++; + /* Advance pointers with wraparound as necessary. */ + prep->this_row_group += cinfo->max_v_samp_factor; + if (prep->this_row_group >= buf_height) + prep->this_row_group = 0; + if (prep->next_buf_row >= buf_height) + prep->next_buf_row = 0; + prep->next_buf_stop = prep->next_buf_row + cinfo->max_v_samp_factor; + } + } +} + + +/* + * Create the wrapped-around downsampling input buffer needed for context mode. + */ + +LOCAL(void) +create_context_buffer (j_compress_ptr cinfo) +{ + my_prep_ptr prep = (my_prep_ptr) cinfo->prep; + int rgroup_height = cinfo->max_v_samp_factor; + int ci, i; + jpeg_component_info * compptr; + JSAMPARRAY true_buffer, fake_buffer; + + /* Grab enough space for fake row pointers for all the components; + * we need five row groups' worth of pointers for each component. + */ + fake_buffer = (JSAMPARRAY) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (size_t)(cinfo->num_components * 5 * rgroup_height) * + SIZEOF(JSAMPROW)); + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + /* Allocate the actual buffer space (3 row groups) for this component. + * We make the buffer wide enough to allow the downsampler to edge-expand + * horizontally within the buffer, if it so chooses. + */ + true_buffer = (*cinfo->mem->alloc_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + (JDIMENSION) (((long) compptr->width_in_data_units * cinfo->data_unit * + cinfo->max_h_samp_factor) / compptr->h_samp_factor), + (JDIMENSION) (3 * rgroup_height)); + /* Copy true buffer row pointers into the middle of the fake row array */ + MEMCOPY(fake_buffer + rgroup_height, true_buffer, + 3 * (size_t)rgroup_height * SIZEOF(JSAMPROW)); + /* Fill in the above and below wraparound pointers */ + for (i = 0; i < rgroup_height; i++) { + fake_buffer[i] = true_buffer[2 * rgroup_height + i]; + fake_buffer[4 * rgroup_height + i] = true_buffer[i]; + } + prep->color_buf[ci] = fake_buffer + rgroup_height; + fake_buffer += 5 * rgroup_height; /* point to space for next component */ + } +} + +#endif /* CONTEXT_ROWS_SUPPORTED */ + + +/* + * Initialize preprocessing controller. + */ + +GLOBAL(void) +jinit_c_prep_controller (j_compress_ptr cinfo, boolean need_full_buffer) +{ + my_prep_ptr prep; + int ci; + jpeg_component_info * compptr; + + if (need_full_buffer) /* safety check */ + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + + prep = (my_prep_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_prep_controller)); + cinfo->prep = (struct jpeg_c_prep_controller *) prep; + prep->pub.start_pass = start_pass_prep; + + /* Allocate the color conversion buffer. + * We make the buffer wide enough to allow the downsampler to edge-expand + * horizontally within the buffer, if it so chooses. + */ + if (cinfo->downsample->need_context_rows) { + /* Set up to provide context rows */ +#ifdef CONTEXT_ROWS_SUPPORTED + prep->pub.pre_process_data = pre_process_context; + create_context_buffer(cinfo); +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } else { + /* No context, just make it tall enough for one row group */ + prep->pub.pre_process_data = pre_process_data; + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + prep->color_buf[ci] = (*cinfo->mem->alloc_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + (JDIMENSION) (((long) compptr->width_in_data_units * cinfo->data_unit * + cinfo->max_h_samp_factor) / compptr->h_samp_factor), + (JDIMENSION) cinfo->max_v_samp_factor); + } + } +} diff --git a/dcmjpeg/libijg12/jcsample.c b/dcmjpeg/libijg12/jcsample.c new file mode 100644 index 00000000..4785e1c1 --- /dev/null +++ b/dcmjpeg/libijg12/jcsample.c @@ -0,0 +1,519 @@ +/* + * jcsample.c + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains downsampling routines. + * + * Downsampling input data is counted in "row groups". A row group + * is defined to be max_v_samp_factor pixel rows of each component, + * from which the downsampler produces v_samp_factor sample rows. + * A single row group is processed in each call to the downsampler module. + * + * The downsampler is responsible for edge-expansion of its output data + * to fill an integral number of DCT blocks horizontally. The source buffer + * may be modified if it is helpful for this purpose (the source buffer is + * allocated wide enough to correspond to the desired output width). + * The caller (the prep controller) is responsible for vertical padding. + * + * The downsampler may request "context rows" by setting need_context_rows + * during startup. In this case, the input arrays will contain at least + * one row group's worth of pixels above and below the passed-in data; + * the caller will create dummy rows at image top and bottom by replicating + * the first or last real pixel row. + * + * An excellent reference for image resampling is + * Digital Image Warping, George Wolberg, 1990. + * Pub. by IEEE Computer Society Press, Los Alamitos, CA. ISBN 0-8186-8944-7. + * + * The downsampling algorithm used here is a simple average of the source + * pixels covered by the output pixel. The hi-falutin sampling literature + * refers to this as a "box filter". In general the characteristics of a box + * filter are not very good, but for the specific cases we normally use (1:1 + * and 2:1 ratios) the box is equivalent to a "triangle filter" which is not + * nearly so bad. If you intend to use other sampling ratios, you'd be well + * advised to improve this code. + * + * A simple input-smoothing capability is provided. This is mainly intended + * for cleaning up color-dithered GIF input files (if you find it inadequate, + * we suggest using an external filtering program such as pnmconvol). When + * enabled, each input pixel P is replaced by a weighted sum of itself and its + * eight neighbors. P's weight is 1-8*SF and each neighbor's weight is SF, + * where SF = (smoothing_factor / 1024). + * Currently, smoothing is only supported for 2h2v sampling factors. + */ + +#define JPEG_INTERNALS +#include "jinclude12.h" +#include "jpeglib12.h" + + +/* Pointer to routine to downsample a single component */ +typedef JMETHOD(void, downsample1_ptr, + (j_compress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY input_data, JSAMPARRAY output_data)); + +/* Private subobject */ + +typedef struct { + struct jpeg_downsampler pub; /* public fields */ + + /* Downsampling method pointers, one per component */ + downsample1_ptr methods[MAX_COMPONENTS]; +} my_downsampler; + +typedef my_downsampler * my_downsample_ptr; + + +/* + * Initialize for a downsampling pass. + */ + +METHODDEF(void) +start_pass_downsample (j_compress_ptr cinfo) +{ + /* no work for now */ +} + + +/* + * Expand a component horizontally from width input_cols to width output_cols, + * by duplicating the rightmost samples. + */ + +LOCAL(void) +expand_right_edge (JSAMPARRAY image_data, int num_rows, + JDIMENSION input_cols, JDIMENSION output_cols) +{ + register JSAMPROW ptr; + register JSAMPLE pixval; + register int count; + int row; + int numcols = (int) (output_cols - input_cols); + + if (numcols > 0) { + for (row = 0; row < num_rows; row++) { + ptr = image_data[row] + input_cols; + pixval = ptr[-1]; /* don't need GETJSAMPLE() here */ + for (count = numcols; count > 0; count--) + *ptr++ = pixval; + } + } +} + + +/* + * Do downsampling for a whole row group (all components). + * + * In this version we simply downsample each component independently. + */ + +METHODDEF(void) +sep_downsample (j_compress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION in_row_index, + JSAMPIMAGE output_buf, JDIMENSION out_row_group_index) +{ + my_downsample_ptr downsample = (my_downsample_ptr) cinfo->downsample; + int ci; + jpeg_component_info * compptr; + JSAMPARRAY in_ptr, out_ptr; + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + in_ptr = input_buf[ci] + in_row_index; + out_ptr = output_buf[ci] + (out_row_group_index * (JDIMENSION)compptr->v_samp_factor); + (*downsample->methods[ci]) (cinfo, compptr, in_ptr, out_ptr); + } +} + + +/* + * Downsample pixel values of a single component. + * One row group is processed per call. + * This version handles arbitrary integral sampling ratios, without smoothing. + * Note that this version is not actually used for customary sampling ratios. + */ + +METHODDEF(void) +int_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY input_data, JSAMPARRAY output_data) +{ + int inrow, outrow, h_expand, v_expand, numpix, numpix2, h, v; + JDIMENSION outcol, outcol_h; /* outcol_h == outcol*h_expand */ + JDIMENSION output_cols = compptr->width_in_data_units * (JDIMENSION)cinfo->data_unit; + JSAMPROW inptr, outptr; + IJG_INT32 outvalue; + + h_expand = cinfo->max_h_samp_factor / compptr->h_samp_factor; + v_expand = cinfo->max_v_samp_factor / compptr->v_samp_factor; + numpix = h_expand * v_expand; + numpix2 = numpix/2; + + /* Expand input data enough to let all the output samples be generated + * by the standard loop. Special-casing padded output would be more + * efficient. + */ + expand_right_edge(input_data, cinfo->max_v_samp_factor, + cinfo->image_width, output_cols * (JDIMENSION)h_expand); + + inrow = 0; + for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) { + outptr = output_data[outrow]; + for (outcol = 0, outcol_h = 0; outcol < output_cols; + outcol++, outcol_h += (JDIMENSION)h_expand) { + outvalue = 0; + for (v = 0; v < v_expand; v++) { + inptr = input_data[inrow+v] + outcol_h; + for (h = 0; h < h_expand; h++) { + outvalue += (IJG_INT32) GETJSAMPLE(*inptr++); + } + } + *outptr++ = (JSAMPLE) ((outvalue + numpix2) / numpix); + } + inrow += v_expand; + } +} + + +/* + * Downsample pixel values of a single component. + * This version handles the special case of a full-size component, + * without smoothing. + */ + +METHODDEF(void) +fullsize_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY input_data, JSAMPARRAY output_data) +{ + /* Copy the data */ + jcopy_sample_rows(input_data, 0, output_data, 0, + cinfo->max_v_samp_factor, cinfo->image_width); + /* Edge-expand */ + expand_right_edge(output_data, cinfo->max_v_samp_factor, + cinfo->image_width, compptr->width_in_data_units * (JDIMENSION)cinfo->data_unit); +} + + +/* + * Downsample pixel values of a single component. + * This version handles the common case of 2:1 horizontal and 1:1 vertical, + * without smoothing. + * + * A note about the "bias" calculations: when rounding fractional values to + * integer, we do not want to always round 0.5 up to the next integer. + * If we did that, we'd introduce a noticeable bias towards larger values. + * Instead, this code is arranged so that 0.5 will be rounded up or down at + * alternate pixel locations (a simple ordered dither pattern). + */ + +METHODDEF(void) +h2v1_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY input_data, JSAMPARRAY output_data) +{ + int outrow; + JDIMENSION outcol; + JDIMENSION output_cols = compptr->width_in_data_units * (JDIMENSION)cinfo->data_unit; + register JSAMPROW inptr, outptr; + register int bias; + + /* Expand input data enough to let all the output samples be generated + * by the standard loop. Special-casing padded output would be more + * efficient. + */ + expand_right_edge(input_data, cinfo->max_v_samp_factor, + cinfo->image_width, output_cols * 2); + + for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) { + outptr = output_data[outrow]; + inptr = input_data[outrow]; + bias = 0; /* bias = 0,1,0,1,... for successive samples */ + for (outcol = 0; outcol < output_cols; outcol++) { + *outptr++ = (JSAMPLE) ((GETJSAMPLE(*inptr) + GETJSAMPLE(inptr[1]) + + bias) >> 1); + bias ^= 1; /* 0=>1, 1=>0 */ + inptr += 2; + } + } +} + + +/* + * Downsample pixel values of a single component. + * This version handles the standard case of 2:1 horizontal and 2:1 vertical, + * without smoothing. + */ + +METHODDEF(void) +h2v2_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY input_data, JSAMPARRAY output_data) +{ + int inrow, outrow; + JDIMENSION outcol; + JDIMENSION output_cols = compptr->width_in_data_units * (JDIMENSION)cinfo->data_unit; + register JSAMPROW inptr0, inptr1, outptr; + register int bias; + + /* Expand input data enough to let all the output samples be generated + * by the standard loop. Special-casing padded output would be more + * efficient. + */ + expand_right_edge(input_data, cinfo->max_v_samp_factor, + cinfo->image_width, output_cols * 2); + + inrow = 0; + for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) { + outptr = output_data[outrow]; + inptr0 = input_data[inrow]; + inptr1 = input_data[inrow+1]; + bias = 1; /* bias = 1,2,1,2,... for successive samples */ + for (outcol = 0; outcol < output_cols; outcol++) { + *outptr++ = (JSAMPLE) ((GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) + + GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]) + + bias) >> 2); + bias ^= 3; /* 1=>2, 2=>1 */ + inptr0 += 2; inptr1 += 2; + } + inrow += 2; + } +} + + +#ifdef INPUT_SMOOTHING_SUPPORTED + +/* + * Downsample pixel values of a single component. + * This version handles the standard case of 2:1 horizontal and 2:1 vertical, + * with smoothing. One row of context is required. + */ + +METHODDEF(void) +h2v2_smooth_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY input_data, JSAMPARRAY output_data) +{ + int inrow, outrow; + JDIMENSION colctr; + JDIMENSION output_cols = compptr->width_in_data_units * (JDIMENSION)cinfo->data_unit; + register JSAMPROW inptr0, inptr1, above_ptr, below_ptr, outptr; + IJG_INT32 membersum, neighsum, memberscale, neighscale; + + /* Expand input data enough to let all the output samples be generated + * by the standard loop. Special-casing padded output would be more + * efficient. + */ + expand_right_edge(input_data - 1, cinfo->max_v_samp_factor + 2, + cinfo->image_width, output_cols * 2); + + /* We don't bother to form the individual "smoothed" input pixel values; + * we can directly compute the output which is the average of the four + * smoothed values. Each of the four member pixels contributes a fraction + * (1-8*SF) to its own smoothed image and a fraction SF to each of the three + * other smoothed pixels, therefore a total fraction (1-5*SF)/4 to the final + * output. The four corner-adjacent neighbor pixels contribute a fraction + * SF to just one smoothed pixel, or SF/4 to the final output; while the + * eight edge-adjacent neighbors contribute SF to each of two smoothed + * pixels, or SF/2 overall. In order to use integer arithmetic, these + * factors are scaled by 2^16 = 65536. + * Also recall that SF = smoothing_factor / 1024. + */ + + memberscale = 16384 - cinfo->smoothing_factor * 80; /* scaled (1-5*SF)/4 */ + neighscale = cinfo->smoothing_factor * 16; /* scaled SF/4 */ + + inrow = 0; + for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) { + outptr = output_data[outrow]; + inptr0 = input_data[inrow]; + inptr1 = input_data[inrow+1]; + above_ptr = input_data[inrow-1]; + below_ptr = input_data[inrow+2]; + + /* Special case for first column: pretend column -1 is same as column 0 */ + membersum = GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) + + GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]); + neighsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[1]) + + GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) + + GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[2]) + + GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[2]); + neighsum += neighsum; + neighsum += GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[2]) + + GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[2]); + membersum = membersum * memberscale + neighsum * neighscale; + *outptr++ = (JSAMPLE) ((membersum + 32768) >> 16); + inptr0 += 2; inptr1 += 2; above_ptr += 2; below_ptr += 2; + + for (colctr = output_cols - 2; colctr > 0; colctr--) { + /* sum of pixels directly mapped to this output element */ + membersum = GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) + + GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]); + /* sum of edge-neighbor pixels */ + neighsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[1]) + + GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) + + GETJSAMPLE(inptr0[-1]) + GETJSAMPLE(inptr0[2]) + + GETJSAMPLE(inptr1[-1]) + GETJSAMPLE(inptr1[2]); + /* The edge-neighbors count twice as much as corner-neighbors */ + neighsum += neighsum; + /* Add in the corner-neighbors */ + neighsum += GETJSAMPLE(above_ptr[-1]) + GETJSAMPLE(above_ptr[2]) + + GETJSAMPLE(below_ptr[-1]) + GETJSAMPLE(below_ptr[2]); + /* form final output scaled up by 2^16 */ + membersum = membersum * memberscale + neighsum * neighscale; + /* round, descale and output it */ + *outptr++ = (JSAMPLE) ((membersum + 32768) >> 16); + inptr0 += 2; inptr1 += 2; above_ptr += 2; below_ptr += 2; + } + + /* Special case for last column */ + membersum = GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) + + GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]); + neighsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[1]) + + GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) + + GETJSAMPLE(inptr0[-1]) + GETJSAMPLE(inptr0[1]) + + GETJSAMPLE(inptr1[-1]) + GETJSAMPLE(inptr1[1]); + neighsum += neighsum; + neighsum += GETJSAMPLE(above_ptr[-1]) + GETJSAMPLE(above_ptr[1]) + + GETJSAMPLE(below_ptr[-1]) + GETJSAMPLE(below_ptr[1]); + membersum = membersum * memberscale + neighsum * neighscale; + *outptr = (JSAMPLE) ((membersum + 32768) >> 16); + + inrow += 2; + } +} + + +/* + * Downsample pixel values of a single component. + * This version handles the special case of a full-size component, + * with smoothing. One row of context is required. + */ + +METHODDEF(void) +fullsize_smooth_downsample (j_compress_ptr cinfo, jpeg_component_info *compptr, + JSAMPARRAY input_data, JSAMPARRAY output_data) +{ + int outrow; + JDIMENSION colctr; + JDIMENSION output_cols = compptr->width_in_data_units * (JDIMENSION)cinfo->data_unit; + register JSAMPROW inptr, above_ptr, below_ptr, outptr; + IJG_INT32 membersum, neighsum, memberscale, neighscale; + int colsum, lastcolsum, nextcolsum; + + /* Expand input data enough to let all the output samples be generated + * by the standard loop. Special-casing padded output would be more + * efficient. + */ + expand_right_edge(input_data - 1, cinfo->max_v_samp_factor + 2, + cinfo->image_width, output_cols); + + /* Each of the eight neighbor pixels contributes a fraction SF to the + * smoothed pixel, while the main pixel contributes (1-8*SF). In order + * to use integer arithmetic, these factors are multiplied by 2^16 = 65536. + * Also recall that SF = smoothing_factor / 1024. + */ + + memberscale = 65536L - cinfo->smoothing_factor * 512L; /* scaled 1-8*SF */ + neighscale = cinfo->smoothing_factor * 64; /* scaled SF */ + + for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) { + outptr = output_data[outrow]; + inptr = input_data[outrow]; + above_ptr = input_data[outrow-1]; + below_ptr = input_data[outrow+1]; + + /* Special case for first column */ + colsum = GETJSAMPLE(*above_ptr++) + GETJSAMPLE(*below_ptr++) + + GETJSAMPLE(*inptr); + membersum = GETJSAMPLE(*inptr++); + nextcolsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(*below_ptr) + + GETJSAMPLE(*inptr); + neighsum = colsum + (colsum - membersum) + nextcolsum; + membersum = membersum * memberscale + neighsum * neighscale; + *outptr++ = (JSAMPLE) ((membersum + 32768) >> 16); + lastcolsum = colsum; colsum = nextcolsum; + + for (colctr = output_cols - 2; colctr > 0; colctr--) { + membersum = GETJSAMPLE(*inptr++); + above_ptr++; below_ptr++; + nextcolsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(*below_ptr) + + GETJSAMPLE(*inptr); + neighsum = lastcolsum + (colsum - membersum) + nextcolsum; + membersum = membersum * memberscale + neighsum * neighscale; + *outptr++ = (JSAMPLE) ((membersum + 32768) >> 16); + lastcolsum = colsum; colsum = nextcolsum; + } + + /* Special case for last column */ + membersum = GETJSAMPLE(*inptr); + neighsum = lastcolsum + (colsum - membersum) + colsum; + membersum = membersum * memberscale + neighsum * neighscale; + *outptr = (JSAMPLE) ((membersum + 32768) >> 16); + + } +} + +#endif /* INPUT_SMOOTHING_SUPPORTED */ + + +/* + * Module initialization routine for downsampling. + * Note that we must select a routine for each component. + */ + +GLOBAL(void) +jinit_downsampler (j_compress_ptr cinfo) +{ + my_downsample_ptr downsample; + int ci; + jpeg_component_info * compptr; + boolean smoothok = TRUE; + + downsample = (my_downsample_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_downsampler)); + cinfo->downsample = (struct jpeg_downsampler *) downsample; + downsample->pub.start_pass = start_pass_downsample; + downsample->pub.downsample = sep_downsample; + downsample->pub.need_context_rows = FALSE; + + if (cinfo->CCIR601_sampling) + ERREXIT(cinfo, JERR_CCIR601_NOTIMPL); + + /* Verify we can handle the sampling factors, and set up method pointers */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + if (compptr->h_samp_factor == cinfo->max_h_samp_factor && + compptr->v_samp_factor == cinfo->max_v_samp_factor) { +#ifdef INPUT_SMOOTHING_SUPPORTED + if (cinfo->smoothing_factor) { + downsample->methods[ci] = fullsize_smooth_downsample; + downsample->pub.need_context_rows = TRUE; + } else +#endif + downsample->methods[ci] = fullsize_downsample; + } else if (compptr->h_samp_factor * 2 == cinfo->max_h_samp_factor && + compptr->v_samp_factor == cinfo->max_v_samp_factor) { + smoothok = FALSE; + downsample->methods[ci] = h2v1_downsample; + } else if (compptr->h_samp_factor * 2 == cinfo->max_h_samp_factor && + compptr->v_samp_factor * 2 == cinfo->max_v_samp_factor) { +#ifdef INPUT_SMOOTHING_SUPPORTED + if (cinfo->smoothing_factor) { + downsample->methods[ci] = h2v2_smooth_downsample; + downsample->pub.need_context_rows = TRUE; + } else +#endif + downsample->methods[ci] = h2v2_downsample; + } else if ((cinfo->max_h_samp_factor % compptr->h_samp_factor) == 0 && + (cinfo->max_v_samp_factor % compptr->v_samp_factor) == 0) { + smoothok = FALSE; + downsample->methods[ci] = int_downsample; + } else + ERREXIT(cinfo, JERR_FRACT_SAMPLE_NOTIMPL); + } + +#ifdef INPUT_SMOOTHING_SUPPORTED + if (cinfo->smoothing_factor && !smoothok) + TRACEMS(cinfo, 0, JTRC_SMOOTH_NOTIMPL); +#endif +} diff --git a/dcmjpeg/libijg12/jcscale.c b/dcmjpeg/libijg12/jcscale.c new file mode 100644 index 00000000..6ba9927c --- /dev/null +++ b/dcmjpeg/libijg12/jcscale.c @@ -0,0 +1,63 @@ +/* + * jcscale.c + * + * Copyright (C) 1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains sample downscaling by 2^Pt for lossless JPEG. + */ + +#define JPEG_INTERNALS +#include "jinclude12.h" +#include "jpeglib12.h" +#include "jlossls12.h" /* Private declarations for lossless codec */ + + +#ifdef C_LOSSLESS_SUPPORTED + +METHODDEF(void) +simple_downscale(j_compress_ptr cinfo, + JSAMPROW input_buf, JSAMPROW output_buf, JDIMENSION width) +{ + /* j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec; */ + unsigned int xindex; + SHIFT_TEMPS + + for (xindex = 0; xindex < width; xindex++) + output_buf[xindex] = (JSAMPLE) RIGHT_SHIFT(GETJSAMPLE(input_buf[xindex]), + cinfo->Al); +} + + +METHODDEF(void) +noscale(j_compress_ptr cinfo, + JSAMPROW input_buf, JSAMPROW output_buf, JDIMENSION width) +{ + MEMCOPY(output_buf, input_buf, width * SIZEOF(JSAMPLE)); + return; +} + + +METHODDEF(void) +scaler_start_pass (j_compress_ptr cinfo) +{ + j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec; + + /* Set scaler function based on Pt */ + if (cinfo->Al) + losslsc->scaler_scale = simple_downscale; + else + losslsc->scaler_scale = noscale; +} + + +GLOBAL(void) +jinit_c_scaler (j_compress_ptr cinfo) +{ + j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec; + + losslsc->scaler_start_pass = scaler_start_pass; +} + +#endif /* C_LOSSLESS_SUPPORTED */ diff --git a/dcmjpeg/libijg12/jcshuff.c b/dcmjpeg/libijg12/jcshuff.c new file mode 100644 index 00000000..61d6de35 --- /dev/null +++ b/dcmjpeg/libijg12/jcshuff.c @@ -0,0 +1,661 @@ +/* + * jcshuff.c + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains Huffman entropy encoding routines for sequential JPEG. + * + * Much of the complexity here has to do with supporting output suspension. + * If the data destination module demands suspension, we want to be able to + * back up to the start of the current MCU. To do this, we copy state + * variables into local working storage, and update them back to the + * permanent JPEG objects only upon successful completion of an MCU. + */ + +#define JPEG_INTERNALS +#include "jinclude12.h" +#include "jpeglib12.h" +#include "jlossy12.h" /* Private declarations for lossy codec */ +#include "jchuff12.h" /* Declarations shared with jc*huff.c */ + + +/* Expanded entropy encoder object for Huffman encoding. + * + * The savable_state subrecord contains fields that change within an MCU, + * but must not be updated permanently until we complete the MCU. + */ + +typedef struct { + IJG_INT32 put_buffer; /* current bit-accumulation buffer */ + int put_bits; /* # of bits now in it */ + int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */ +} savable_state; + +/* This macro is to work around compilers with missing or broken + * structure assignment. You'll need to fix this code if you have + * such a compiler and you change MAX_COMPS_IN_SCAN. + */ + +#ifndef NO_STRUCT_ASSIGN +#define ASSIGN_STATE(dest,src) ((dest) = (src)) +#else +#if MAX_COMPS_IN_SCAN == 4 +#define ASSIGN_STATE(dest,src) \ + ((dest).put_buffer = (src).put_buffer, \ + (dest).put_bits = (src).put_bits, \ + (dest).last_dc_val[0] = (src).last_dc_val[0], \ + (dest).last_dc_val[1] = (src).last_dc_val[1], \ + (dest).last_dc_val[2] = (src).last_dc_val[2], \ + (dest).last_dc_val[3] = (src).last_dc_val[3]) +#endif +#endif + + +typedef struct { + savable_state saved; /* Bit buffer & DC state at start of MCU */ + + /* These fields are NOT loaded into local working state. */ + unsigned int restarts_to_go; /* MCUs left in this restart interval */ + int next_restart_num; /* next restart number to write (0-7) */ + + /* Pointers to derived tables (these workspaces have image lifespan) */ + c_derived_tbl * dc_derived_tbls[NUM_HUFF_TBLS]; + c_derived_tbl * ac_derived_tbls[NUM_HUFF_TBLS]; + +#ifdef ENTROPY_OPT_SUPPORTED /* Statistics tables for optimization */ + long * dc_count_ptrs[NUM_HUFF_TBLS]; + long * ac_count_ptrs[NUM_HUFF_TBLS]; +#endif +} shuff_entropy_encoder; + +typedef shuff_entropy_encoder * shuff_entropy_ptr; + +/* Working state while writing an MCU. + * This struct contains all the fields that are needed by subroutines. + */ + +typedef struct { + JOCTET * next_output_byte; /* => next byte to write in buffer */ + size_t free_in_buffer; /* # of byte spaces remaining in buffer */ + savable_state cur; /* Current bit buffer & DC state */ + j_compress_ptr cinfo; /* dump_buffer needs access to this */ +} working_state; + + +/* Forward declarations */ +METHODDEF(boolean) encode_mcu_huff JPP((j_compress_ptr cinfo, + JBLOCKROW *MCU_data)); +METHODDEF(void) finish_pass_huff JPP((j_compress_ptr cinfo)); +#ifdef ENTROPY_OPT_SUPPORTED +METHODDEF(boolean) encode_mcu_gather JPP((j_compress_ptr cinfo, + JBLOCKROW *MCU_data)); +METHODDEF(void) finish_pass_gather JPP((j_compress_ptr cinfo)); +#endif + + +/* + * Initialize for a Huffman-compressed scan. + * If gather_statistics is TRUE, we do not output anything during the scan, + * just count the Huffman symbols used and generate Huffman code tables. + */ + +METHODDEF(void) +start_pass_huff (j_compress_ptr cinfo, boolean gather_statistics) +{ + j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; + shuff_entropy_ptr entropy = (shuff_entropy_ptr) lossyc->entropy_private; + int ci, dctbl, actbl; + jpeg_component_info * compptr; + + if (gather_statistics) { +#ifdef ENTROPY_OPT_SUPPORTED + lossyc->entropy_encode_mcu = encode_mcu_gather; + lossyc->pub.entropy_finish_pass = finish_pass_gather; +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } else { + lossyc->entropy_encode_mcu = encode_mcu_huff; + lossyc->pub.entropy_finish_pass = finish_pass_huff; + } + + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + dctbl = compptr->dc_tbl_no; + actbl = compptr->ac_tbl_no; + if (gather_statistics) { +#ifdef ENTROPY_OPT_SUPPORTED + /* Check for invalid table indexes */ + /* (make_c_derived_tbl does this in the other path) */ + if (dctbl < 0 || dctbl >= NUM_HUFF_TBLS) + ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, dctbl); + if (actbl < 0 || actbl >= NUM_HUFF_TBLS) + ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, actbl); + /* Allocate and zero the statistics tables */ + /* Note that jpeg_gen_optimal_table expects 257 entries in each table! */ + if (entropy->dc_count_ptrs[dctbl] == NULL) + entropy->dc_count_ptrs[dctbl] = (long *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + 257 * SIZEOF(long)); + MEMZERO(entropy->dc_count_ptrs[dctbl], 257 * SIZEOF(long)); + if (entropy->ac_count_ptrs[actbl] == NULL) + entropy->ac_count_ptrs[actbl] = (long *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + 257 * SIZEOF(long)); + MEMZERO(entropy->ac_count_ptrs[actbl], 257 * SIZEOF(long)); +#endif + } else { + /* Compute derived values for Huffman tables */ + /* We may do this more than once for a table, but it's not expensive */ + jpeg_make_c_derived_tbl(cinfo, TRUE, dctbl, + & entropy->dc_derived_tbls[dctbl]); + jpeg_make_c_derived_tbl(cinfo, FALSE, actbl, + & entropy->ac_derived_tbls[actbl]); + } + /* Initialize DC predictions to 0 */ + entropy->saved.last_dc_val[ci] = 0; + } + + /* Initialize bit buffer to empty */ + entropy->saved.put_buffer = 0; + entropy->saved.put_bits = 0; + + /* Initialize restart stuff */ + entropy->restarts_to_go = cinfo->restart_interval; + entropy->next_restart_num = 0; +} + + +/* Outputting bytes to the file */ + +/* Emit a byte, taking 'action' if must suspend. */ +#define emit_byte(state,val,action) \ + { *(state)->next_output_byte++ = (JOCTET) (val); \ + if (--(state)->free_in_buffer == 0) \ + if (! dump_buffer(state)) \ + { action; } } + + +LOCAL(boolean) +dump_buffer (working_state * state) +/* Empty the output buffer; return TRUE if successful, FALSE if must suspend */ +{ + struct jpeg_destination_mgr * dest = state->cinfo->dest; + + if (! (*dest->empty_output_buffer) (state->cinfo)) + return FALSE; + /* After a successful buffer dump, must reset buffer pointers */ + state->next_output_byte = dest->next_output_byte; + state->free_in_buffer = dest->free_in_buffer; + return TRUE; +} + + +/* Outputting bits to the file */ + +/* Only the right 24 bits of put_buffer are used; the valid bits are + * left-justified in this part. At most 16 bits can be passed to emit_bits + * in one call, and we never retain more than 7 bits in put_buffer + * between calls, so 24 bits are sufficient. + */ + +INLINE +LOCAL(boolean) +emit_bits (working_state * state, unsigned int code, int size) +/* Emit some bits; return TRUE if successful, FALSE if must suspend */ +{ + /* This routine is heavily used, so it's worth coding tightly. */ + register IJG_INT32 put_buffer = (IJG_INT32) code; + register int put_bits = state->cur.put_bits; + + /* if size is 0, caller used an invalid Huffman table entry */ + if (size == 0) + ERREXIT(state->cinfo, JERR_HUFF_MISSING_CODE); + + put_buffer &= (((IJG_INT32) 1)<cur.put_buffer; /* and merge with old buffer contents */ + + while (put_bits >= 8) { + int c = (int) ((put_buffer >> 16) & 0xFF); + + emit_byte(state, c, return FALSE); + if (c == 0xFF) { /* need to stuff a zero byte? */ + emit_byte(state, 0, return FALSE); + } + put_buffer <<= 8; + put_bits -= 8; + } + + state->cur.put_buffer = put_buffer; /* update state variables */ + state->cur.put_bits = put_bits; + + return TRUE; +} + + +LOCAL(boolean) +flush_bits (working_state * state) +{ + if (! emit_bits(state, 0x7F, 7)) /* fill any partial byte with ones */ + return FALSE; + state->cur.put_buffer = 0; /* and reset bit-buffer to empty */ + state->cur.put_bits = 0; + return TRUE; +} + + +/* Encode a single block's worth of coefficients */ + +LOCAL(boolean) +encode_one_block (working_state * state, JCOEFPTR block, int last_dc_val, + c_derived_tbl *dctbl, c_derived_tbl *actbl) +{ + register int temp, temp2; + register int nbits; + register int k, r, i; + + /* Encode the DC coefficient difference per section F.1.2.1 */ + + temp = temp2 = block[0] - last_dc_val; + + if (temp < 0) { + temp = -temp; /* temp is abs value of input */ + /* For a negative input, want temp2 = bitwise complement of abs(input) */ + /* This code assumes we are on a two's complement machine */ + temp2--; + } + + /* Find the number of bits needed for the magnitude of the coefficient */ + nbits = 0; + while (temp) { + nbits++; + temp >>= 1; + } + /* Check for out-of-range coefficient values. + * Since we're encoding a difference, the range limit is twice as much. + */ + if (nbits > MAX_COEF_BITS+1) + ERREXIT(state->cinfo, JERR_BAD_DCT_COEF); + + /* Emit the Huffman-coded symbol for the number of bits */ + if (! emit_bits(state, dctbl->ehufco[nbits], dctbl->ehufsi[nbits])) + return FALSE; + + /* Emit that number of bits of the value, if positive, */ + /* or the complement of its magnitude, if negative. */ + if (nbits) /* emit_bits rejects calls with size 0 */ + if (! emit_bits(state, (unsigned int) temp2, nbits)) + return FALSE; + + /* Encode the AC coefficients per section F.1.2.2 */ + + r = 0; /* r = run length of zeros */ + + for (k = 1; k < DCTSIZE2; k++) { + if ((temp = block[jpeg_natural_order[k]]) == 0) { + r++; + } else { + /* if run length > 15, must emit special run-length-16 codes (0xF0) */ + while (r > 15) { + if (! emit_bits(state, actbl->ehufco[0xF0], actbl->ehufsi[0xF0])) + return FALSE; + r -= 16; + } + + temp2 = temp; + if (temp < 0) { + temp = -temp; /* temp is abs value of input */ + /* This code assumes we are on a two's complement machine */ + temp2--; + } + + /* Find the number of bits needed for the magnitude of the coefficient */ + nbits = 1; /* there must be at least one 1 bit */ + while ((temp >>= 1)) + nbits++; + /* Check for out-of-range coefficient values */ + if (nbits > MAX_COEF_BITS) + ERREXIT(state->cinfo, JERR_BAD_DCT_COEF); + + /* Emit Huffman symbol for run length / number of bits */ + i = (r << 4) + nbits; + if (! emit_bits(state, actbl->ehufco[i], actbl->ehufsi[i])) + return FALSE; + + /* Emit that number of bits of the value, if positive, */ + /* or the complement of its magnitude, if negative. */ + if (! emit_bits(state, (unsigned int) temp2, nbits)) + return FALSE; + + r = 0; + } + } + + /* If the last coef(s) were zero, emit an end-of-block code */ + if (r > 0) + if (! emit_bits(state, actbl->ehufco[0], actbl->ehufsi[0])) + return FALSE; + + return TRUE; +} + + +/* + * Emit a restart marker & resynchronize predictions. + */ + +LOCAL(boolean) +emit_restart (working_state * state, int restart_num) +{ + int ci; + + if (! flush_bits(state)) + return FALSE; + + emit_byte(state, 0xFF, return FALSE); + emit_byte(state, JPEG_RST0 + restart_num, return FALSE); + + /* Re-initialize DC predictions to 0 */ + for (ci = 0; ci < state->cinfo->comps_in_scan; ci++) + state->cur.last_dc_val[ci] = 0; + + /* The restart counter is not updated until we successfully write the MCU. */ + + return TRUE; +} + + +/* + * Encode and output one MCU's worth of Huffman-compressed coefficients. + */ + +METHODDEF(boolean) +encode_mcu_huff (j_compress_ptr cinfo, JBLOCKROW *MCU_data) +{ + j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; + shuff_entropy_ptr entropy = (shuff_entropy_ptr) lossyc->entropy_private; + working_state state; + int blkn, ci; + jpeg_component_info * compptr; + + /* Load up working state */ + state.next_output_byte = cinfo->dest->next_output_byte; + state.free_in_buffer = cinfo->dest->free_in_buffer; + ASSIGN_STATE(state.cur, entropy->saved); + state.cinfo = cinfo; + + /* Emit restart marker if needed */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) + if (! emit_restart(&state, entropy->next_restart_num)) + return FALSE; + } + + /* Encode the MCU data blocks */ + for (blkn = 0; blkn < cinfo->data_units_in_MCU; blkn++) { + ci = cinfo->MCU_membership[blkn]; + compptr = cinfo->cur_comp_info[ci]; + if (! encode_one_block(&state, + MCU_data[blkn][0], state.cur.last_dc_val[ci], + entropy->dc_derived_tbls[compptr->dc_tbl_no], + entropy->ac_derived_tbls[compptr->ac_tbl_no])) + return FALSE; + /* Update last_dc_val */ + state.cur.last_dc_val[ci] = MCU_data[blkn][0][0]; + } + + /* Completed MCU, so update state */ + cinfo->dest->next_output_byte = state.next_output_byte; + cinfo->dest->free_in_buffer = state.free_in_buffer; + ASSIGN_STATE(entropy->saved, state.cur); + + /* Update restart-interval state too */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) { + entropy->restarts_to_go = cinfo->restart_interval; + entropy->next_restart_num++; + entropy->next_restart_num &= 7; + } + entropy->restarts_to_go--; + } + + return TRUE; +} + + +/* + * Finish up at the end of a Huffman-compressed scan. + */ + +METHODDEF(void) +finish_pass_huff (j_compress_ptr cinfo) +{ + j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; + shuff_entropy_ptr entropy = (shuff_entropy_ptr) lossyc->entropy_private; + working_state state; + + /* Load up working state ... flush_bits needs it */ + state.next_output_byte = cinfo->dest->next_output_byte; + state.free_in_buffer = cinfo->dest->free_in_buffer; + ASSIGN_STATE(state.cur, entropy->saved); + state.cinfo = cinfo; + + /* Flush out the last data */ + if (! flush_bits(&state)) + ERREXIT(cinfo, JERR_CANT_SUSPEND); + + /* Update state */ + cinfo->dest->next_output_byte = state.next_output_byte; + cinfo->dest->free_in_buffer = state.free_in_buffer; + ASSIGN_STATE(entropy->saved, state.cur); +} + + +/* + * Huffman coding optimization. + * + * We first scan the supplied data and count the number of uses of each symbol + * that is to be Huffman-coded. (This process MUST agree with the code above.) + * Then we build a Huffman coding tree for the observed counts. + * Symbols which are not needed at all for the particular image are not + * assigned any code, which saves space in the DHT marker as well as in + * the compressed data. + */ + +#ifdef ENTROPY_OPT_SUPPORTED + + +/* Process a single block's worth of coefficients */ + +LOCAL(void) +htest_one_block (j_compress_ptr cinfo, JCOEFPTR block, int last_dc_val, + long dc_counts[], long ac_counts[]) +{ + register int temp; + register int nbits; + register int k, r; + + /* Encode the DC coefficient difference per section F.1.2.1 */ + + temp = block[0] - last_dc_val; + if (temp < 0) + temp = -temp; + + /* Find the number of bits needed for the magnitude of the coefficient */ + nbits = 0; + while (temp) { + nbits++; + temp >>= 1; + } + /* Check for out-of-range coefficient values. + * Since we're encoding a difference, the range limit is twice as much. + */ + if (nbits > MAX_COEF_BITS+1) + ERREXIT(cinfo, JERR_BAD_DCT_COEF); + + /* Count the Huffman symbol for the number of bits */ + dc_counts[nbits]++; + + /* Encode the AC coefficients per section F.1.2.2 */ + + r = 0; /* r = run length of zeros */ + + for (k = 1; k < DCTSIZE2; k++) { + if ((temp = block[jpeg_natural_order[k]]) == 0) { + r++; + } else { + /* if run length > 15, must emit special run-length-16 codes (0xF0) */ + while (r > 15) { + ac_counts[0xF0]++; + r -= 16; + } + + /* Find the number of bits needed for the magnitude of the coefficient */ + if (temp < 0) + temp = -temp; + + /* Find the number of bits needed for the magnitude of the coefficient */ + nbits = 1; /* there must be at least one 1 bit */ + while ((temp >>= 1)) + nbits++; + /* Check for out-of-range coefficient values */ + if (nbits > MAX_COEF_BITS) + ERREXIT(cinfo, JERR_BAD_DCT_COEF); + + /* Count Huffman symbol for run length / number of bits */ + ac_counts[(r << 4) + nbits]++; + + r = 0; + } + } + + /* If the last coef(s) were zero, emit an end-of-block code */ + if (r > 0) + ac_counts[0]++; +} + + +/* + * Trial-encode one MCU's worth of Huffman-compressed coefficients. + * No data is actually output, so no suspension return is possible. + */ + +METHODDEF(boolean) +encode_mcu_gather (j_compress_ptr cinfo, JBLOCKROW *MCU_data) +{ + j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; + shuff_entropy_ptr entropy = (shuff_entropy_ptr) lossyc->entropy_private; + int blkn, ci; + jpeg_component_info * compptr; + + /* Take care of restart intervals if needed */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) { + /* Re-initialize DC predictions to 0 */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) + entropy->saved.last_dc_val[ci] = 0; + /* Update restart state */ + entropy->restarts_to_go = cinfo->restart_interval; + } + entropy->restarts_to_go--; + } + + for (blkn = 0; blkn < cinfo->data_units_in_MCU; blkn++) { + ci = cinfo->MCU_membership[blkn]; + compptr = cinfo->cur_comp_info[ci]; + htest_one_block(cinfo, MCU_data[blkn][0], entropy->saved.last_dc_val[ci], + entropy->dc_count_ptrs[compptr->dc_tbl_no], + entropy->ac_count_ptrs[compptr->ac_tbl_no]); + entropy->saved.last_dc_val[ci] = MCU_data[blkn][0][0]; + } + + return TRUE; +} + + +/* + * Finish up a statistics-gathering pass and create the new Huffman tables. + */ + +METHODDEF(void) +finish_pass_gather (j_compress_ptr cinfo) +{ + j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; + shuff_entropy_ptr entropy = (shuff_entropy_ptr) lossyc->entropy_private; + int ci, dctbl, actbl; + jpeg_component_info * compptr; + JHUFF_TBL **htblptr; + boolean did_dc[NUM_HUFF_TBLS]; + boolean did_ac[NUM_HUFF_TBLS]; + + /* It's important not to apply jpeg_gen_optimal_table more than once + * per table, because it clobbers the input frequency counts! + */ + MEMZERO(did_dc, SIZEOF(did_dc)); + MEMZERO(did_ac, SIZEOF(did_ac)); + + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + dctbl = compptr->dc_tbl_no; + actbl = compptr->ac_tbl_no; + if (! did_dc[dctbl]) { + htblptr = & cinfo->dc_huff_tbl_ptrs[dctbl]; + if (*htblptr == NULL) + *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo); + jpeg_gen_optimal_table(cinfo, *htblptr, entropy->dc_count_ptrs[dctbl]); + did_dc[dctbl] = TRUE; + } + if (! did_ac[actbl]) { + htblptr = & cinfo->ac_huff_tbl_ptrs[actbl]; + if (*htblptr == NULL) + *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo); + jpeg_gen_optimal_table(cinfo, *htblptr, entropy->ac_count_ptrs[actbl]); + did_ac[actbl] = TRUE; + } + } +} + + +#endif /* ENTROPY_OPT_SUPPORTED */ + + +METHODDEF(boolean) +need_optimization_pass (j_compress_ptr cinfo) +{ + return TRUE; +} + + +/* + * Module initialization routine for Huffman entropy encoding. + */ + +GLOBAL(void) +jinit_shuff_encoder (j_compress_ptr cinfo) +{ + j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; + shuff_entropy_ptr entropy; + int i; + + entropy = (shuff_entropy_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(shuff_entropy_encoder)); + lossyc->entropy_private = (struct jpeg_entropy_encoder *) entropy; + lossyc->pub.entropy_start_pass = start_pass_huff; + lossyc->pub.need_optimization_pass = need_optimization_pass; + + /* Mark tables unallocated */ + for (i = 0; i < NUM_HUFF_TBLS; i++) { + entropy->dc_derived_tbls[i] = entropy->ac_derived_tbls[i] = NULL; +#ifdef ENTROPY_OPT_SUPPORTED + entropy->dc_count_ptrs[i] = entropy->ac_count_ptrs[i] = NULL; +#endif + } +} diff --git a/dcmjpeg/libijg12/jctrans.c b/dcmjpeg/libijg12/jctrans.c new file mode 100644 index 00000000..711482de --- /dev/null +++ b/dcmjpeg/libijg12/jctrans.c @@ -0,0 +1,424 @@ +/* + * jctrans.c + * + * Copyright (C) 1995-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains library routines for transcoding compression, + * that is, writing raw DCT coefficient arrays to an output JPEG file. + * The routines in jcapimin.c will also be needed by a transcoder. + */ + +#define JPEG_INTERNALS +#include "jinclude12.h" +#include "jpeglib12.h" +#include "jlossy12.h" /* Private declarations for lossy codec */ + + +/* Forward declarations */ +LOCAL(void) transencode_master_selection + JPP((j_compress_ptr cinfo, jvirt_barray_ptr * coef_arrays)); +LOCAL(void) transencode_codec + JPP((j_compress_ptr cinfo, jvirt_barray_ptr * coef_arrays)); +LOCAL(void) transencode_coef_controller + JPP((j_compress_ptr cinfo, jvirt_barray_ptr * coef_arrays)); + + +/* + * Compression initialization for writing raw-coefficient data. + * Before calling this, all parameters and a data destination must be set up. + * Call jpeg_finish_compress() to actually write the data. + * + * The number of passed virtual arrays must match cinfo->num_components. + * Note that the virtual arrays need not be filled or even realized at + * the time write_coefficients is called; indeed, if the virtual arrays + * were requested from this compression object's memory manager, they + * typically will be realized during this routine and filled afterwards. + */ + +GLOBAL(void) +jpeg_write_coefficients (j_compress_ptr cinfo, jvirt_barray_ptr * coef_arrays) +{ + if (cinfo->global_state != CSTATE_START) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + /* Mark all tables to be written */ + jpeg_suppress_tables(cinfo, FALSE); + /* (Re)initialize error mgr and destination modules */ + (*cinfo->err->reset_error_mgr) ((j_common_ptr) cinfo); + (*cinfo->dest->init_destination) (cinfo); + /* Perform master selection of active modules */ + transencode_master_selection(cinfo, coef_arrays); + /* Wait for jpeg_finish_compress() call */ + cinfo->next_scanline = 0; /* so jpeg_write_marker works */ + cinfo->global_state = CSTATE_WRCOEFS; +} + + +/* + * Initialize the compression object with default parameters, + * then copy from the source object all parameters needed for lossless + * transcoding. Parameters that can be varied without loss (such as + * scan script and Huffman optimization) are left in their default states. + */ + +GLOBAL(void) +jpeg_copy_critical_parameters (j_decompress_ptr srcinfo, + j_compress_ptr dstinfo) +{ + JQUANT_TBL ** qtblptr; + jpeg_component_info *incomp, *outcomp; + JQUANT_TBL *c_quant, *slot_quant; + int tblno, ci, coefi; + + /* Safety check to ensure start_compress not called yet. */ + if (dstinfo->global_state != CSTATE_START) + ERREXIT1(dstinfo, JERR_BAD_STATE, dstinfo->global_state); + /* Copy fundamental image dimensions */ + dstinfo->image_width = srcinfo->image_width; + dstinfo->image_height = srcinfo->image_height; + dstinfo->input_components = srcinfo->num_components; + dstinfo->in_color_space = srcinfo->jpeg_color_space; + /* Initialize all parameters to default values */ + jpeg_set_defaults(dstinfo); + /* jpeg_set_defaults may choose wrong colorspace, eg YCbCr if input is RGB. + * Fix it to get the right header markers for the image colorspace. + */ + jpeg_set_colorspace(dstinfo, srcinfo->jpeg_color_space); + dstinfo->data_precision = srcinfo->data_precision; + dstinfo->CCIR601_sampling = srcinfo->CCIR601_sampling; + /* Copy the source's quantization tables. */ + for (tblno = 0; tblno < NUM_QUANT_TBLS; tblno++) { + if (srcinfo->quant_tbl_ptrs[tblno] != NULL) { + qtblptr = & dstinfo->quant_tbl_ptrs[tblno]; + if (*qtblptr == NULL) + *qtblptr = jpeg_alloc_quant_table((j_common_ptr) dstinfo); + MEMCOPY((*qtblptr)->quantval, + srcinfo->quant_tbl_ptrs[tblno]->quantval, + SIZEOF((*qtblptr)->quantval)); + (*qtblptr)->sent_table = FALSE; + } + } + /* Copy the source's per-component info. + * Note we assume jpeg_set_defaults has allocated the dest comp_info array. + */ + dstinfo->num_components = srcinfo->num_components; + if (dstinfo->num_components < 1 || dstinfo->num_components > MAX_COMPONENTS) + ERREXIT2(dstinfo, JERR_COMPONENT_COUNT, dstinfo->num_components, + MAX_COMPONENTS); + for (ci = 0, incomp = srcinfo->comp_info, outcomp = dstinfo->comp_info; + ci < dstinfo->num_components; ci++, incomp++, outcomp++) { + outcomp->component_id = incomp->component_id; + outcomp->h_samp_factor = incomp->h_samp_factor; + outcomp->v_samp_factor = incomp->v_samp_factor; + outcomp->quant_tbl_no = incomp->quant_tbl_no; + /* Make sure saved quantization table for component matches the qtable + * slot. If not, the input file re-used this qtable slot. + * IJG encoder currently cannot duplicate this. + */ + tblno = outcomp->quant_tbl_no; + if (tblno < 0 || tblno >= NUM_QUANT_TBLS || + srcinfo->quant_tbl_ptrs[tblno] == NULL) + ERREXIT1(dstinfo, JERR_NO_QUANT_TABLE, tblno); + slot_quant = srcinfo->quant_tbl_ptrs[tblno]; + c_quant = incomp->quant_table; + if (c_quant != NULL) { + for (coefi = 0; coefi < DCTSIZE2; coefi++) { + if (c_quant->quantval[coefi] != slot_quant->quantval[coefi]) + ERREXIT1(dstinfo, JERR_MISMATCHED_QUANT_TABLE, tblno); + } + } + /* Note: we do not copy the source's Huffman table assignments; + * instead we rely on jpeg_set_colorspace to have made a suitable choice. + */ + } + /* Also copy JFIF version and resolution information, if available. + * Strictly speaking this isn't "critical" info, but it's nearly + * always appropriate to copy it if available. In particular, + * if the application chooses to copy JFIF 1.02 extension markers from + * the source file, we need to copy the version to make sure we don't + * emit a file that has 1.02 extensions but a claimed version of 1.01. + * We will *not*, however, copy version info from mislabeled "2.01" files. + */ + if (srcinfo->saw_JFIF_marker) { + if (srcinfo->JFIF_major_version == 1) { + dstinfo->JFIF_major_version = srcinfo->JFIF_major_version; + dstinfo->JFIF_minor_version = srcinfo->JFIF_minor_version; + } + dstinfo->density_unit = srcinfo->density_unit; + dstinfo->X_density = srcinfo->X_density; + dstinfo->Y_density = srcinfo->Y_density; + } +} + + +/* + * Master selection of compression modules for transcoding. + * This substitutes for jcinit.c's initialization of the full compressor. + */ + +LOCAL(void) +transencode_master_selection (j_compress_ptr cinfo, + jvirt_barray_ptr * coef_arrays) +{ + cinfo->data_unit = DCTSIZE; + /* Although we don't actually use input_components for transcoding, + * jcmaster.c's initial_setup will complain if input_components is 0. + */ + cinfo->input_components = 1; + /* Initialize master control (includes parameter checking/processing) */ + jinit_c_master_control(cinfo, TRUE /* transcode only */); + + /* We need a special compression codec. */ + transencode_codec(cinfo, coef_arrays); + + jinit_marker_writer(cinfo); + + /* We can now tell the memory manager to allocate virtual arrays. */ + (*cinfo->mem->realize_virt_arrays) ((j_common_ptr) cinfo); + + /* Write the datastream header (SOI, JFIF) immediately. + * Frame and scan headers are postponed till later. + * This lets application insert special markers after the SOI. + */ + (*cinfo->marker->write_file_header) (cinfo); +} + + +/* + * The rest of this file is a special implementation of the coefficient + * buffer controller. This is similar to jccoefct.c, but it handles only + * output from presupplied virtual arrays. Furthermore, we generate any + * dummy padding blocks on-the-fly rather than expecting them to be present + * in the arrays. + */ + +/* Private buffer controller object */ + +typedef struct { + JDIMENSION iMCU_row_num; /* iMCU row # within image */ + JDIMENSION mcu_ctr; /* counts MCUs processed in current row */ + int MCU_vert_offset; /* counts MCU rows within iMCU row */ + int MCU_rows_per_iMCU_row; /* number of such rows needed */ + + /* Virtual block array for each component. */ + jvirt_barray_ptr * whole_image; + + /* Workspace for constructing dummy blocks at right/bottom edges. */ + JBLOCKROW dummy_buffer[C_MAX_DATA_UNITS_IN_MCU]; +} c_coef_controller; + +typedef c_coef_controller * c_coef_ptr; + + +LOCAL(void) +start_iMCU_row (j_compress_ptr cinfo) +/* Reset within-iMCU-row counters for a new row */ +{ + j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; + c_coef_ptr coef = (c_coef_ptr) lossyc->coef_private; + + /* In an interleaved scan, an MCU row is the same as an iMCU row. + * In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows. + * But at the bottom of the image, process only what's left. + */ + if (cinfo->comps_in_scan > 1) { + coef->MCU_rows_per_iMCU_row = 1; + } else { + if (coef->iMCU_row_num < (cinfo->total_iMCU_rows-1)) + coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->v_samp_factor; + else + coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->last_row_height; + } + + coef->mcu_ctr = 0; + coef->MCU_vert_offset = 0; +} + + +/* + * Initialize for a processing pass. + */ + +METHODDEF(void) +start_pass_coef (j_compress_ptr cinfo, J_BUF_MODE pass_mode) +{ + j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; + c_coef_ptr coef = (c_coef_ptr) lossyc->coef_private; + + if (pass_mode != JBUF_CRANK_DEST) + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + + coef->iMCU_row_num = 0; + start_iMCU_row(cinfo); +} + + +/* + * Process some data. + * We process the equivalent of one fully interleaved MCU row ("iMCU" row) + * per call, ie, v_samp_factor block rows for each component in the scan. + * The data is obtained from the virtual arrays and fed to the entropy coder. + * Returns TRUE if the iMCU row is completed, FALSE if suspended. + * + * NB: input_buf is ignored; it is likely to be a NULL pointer. + */ + +METHODDEF(boolean) +compress_output (j_compress_ptr cinfo, JSAMPIMAGE input_buf) +{ + j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; + c_coef_ptr coef = (c_coef_ptr) lossyc->coef_private; + JDIMENSION MCU_col_num; /* index of current MCU within row */ + JDIMENSION last_MCU_col = cinfo->MCUs_per_row - 1; + JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; + int blkn, ci, xindex, yindex, yoffset, blockcnt; + JDIMENSION start_col; + JBLOCKARRAY buffer[MAX_COMPS_IN_SCAN]; + JBLOCKROW MCU_buffer[C_MAX_DATA_UNITS_IN_MCU]; + JBLOCKROW buffer_ptr; + jpeg_component_info *compptr; + + /* Align the virtual buffers for the components used in this scan. */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + buffer[ci] = (*cinfo->mem->access_virt_barray) + ((j_common_ptr) cinfo, coef->whole_image[compptr->component_index], + coef->iMCU_row_num * (JDIMENSION) compptr->v_samp_factor, + (JDIMENSION) compptr->v_samp_factor, FALSE); + } + + /* Loop to process one whole iMCU row */ + for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row; + yoffset++) { + for (MCU_col_num = coef->mcu_ctr; MCU_col_num < cinfo->MCUs_per_row; + MCU_col_num++) { + /* Construct list of pointers to DCT blocks belonging to this MCU */ + blkn = 0; /* index of current DCT block within MCU */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + start_col = MCU_col_num * (JDIMENSION)compptr->MCU_width; + blockcnt = (MCU_col_num < last_MCU_col) ? compptr->MCU_width + : compptr->last_col_width; + for (yindex = 0; yindex < compptr->MCU_height; yindex++) { + if (coef->iMCU_row_num < last_iMCU_row || + yindex+yoffset < compptr->last_row_height) { + /* Fill in pointers to real blocks in this row */ + buffer_ptr = buffer[ci][yindex+yoffset] + start_col; + for (xindex = 0; xindex < blockcnt; xindex++) + MCU_buffer[blkn++] = buffer_ptr++; + } else { + /* At bottom of image, need a whole row of dummy blocks */ + xindex = 0; + } + /* Fill in any dummy blocks needed in this row. + * Dummy blocks are filled in the same way as in jccoefct.c: + * all zeroes in the AC entries, DC entries equal to previous + * block's DC value. The init routine has already zeroed the + * AC entries, so we need only set the DC entries correctly. + */ + for (; xindex < compptr->MCU_width; xindex++) { + MCU_buffer[blkn] = coef->dummy_buffer[blkn]; + MCU_buffer[blkn][0][0] = MCU_buffer[blkn-1][0][0]; + blkn++; + } + } + } + /* Try to write the MCU. */ + if (! (*lossyc->entropy_encode_mcu) (cinfo, MCU_buffer)) { + /* Suspension forced; update state counters and exit */ + coef->MCU_vert_offset = yoffset; + coef->mcu_ctr = MCU_col_num; + return FALSE; + } + } + /* Completed an MCU row, but perhaps not an iMCU row */ + coef->mcu_ctr = 0; + } + /* Completed the iMCU row, advance counters for next one */ + coef->iMCU_row_num++; + start_iMCU_row(cinfo); + return TRUE; +} + + +/* + * Initialize coefficient buffer controller. + * + * Each passed coefficient array must be the right size for that + * coefficient: width_in_data_units wide and height_in_data_units high, + * with unitheight at least v_samp_factor. + */ + +LOCAL(void) +transencode_coef_controller (j_compress_ptr cinfo, + jvirt_barray_ptr * coef_arrays) +{ + j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; + c_coef_ptr coef; + JBLOCKROW buffer; + int i; + + coef = (c_coef_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(c_coef_controller)); + lossyc->coef_private = (struct jpeg_c_coef_controller *) coef; + + /* Save pointer to virtual arrays */ + coef->whole_image = coef_arrays; + + /* Allocate and pre-zero space for dummy DCT blocks. */ + buffer = (JBLOCKROW) + (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE, + C_MAX_DATA_UNITS_IN_MCU * SIZEOF(JBLOCK)); + jzero_far((void FAR *) buffer, C_MAX_DATA_UNITS_IN_MCU * SIZEOF(JBLOCK)); + for (i = 0; i < C_MAX_DATA_UNITS_IN_MCU; i++) { + coef->dummy_buffer[i] = buffer + i; + } +} + + +/* + * Initialize the transencoer codec. + * This is called only once, during master selection. + */ + +LOCAL(void) +transencode_codec (j_compress_ptr cinfo, + jvirt_barray_ptr * coef_arrays) +{ + j_lossy_c_ptr lossyc; + + /* Create subobject in permanent pool */ + lossyc = (j_lossy_c_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, + SIZEOF(jpeg_lossy_c_codec)); + cinfo->codec = (struct jpeg_c_codec *) lossyc; + + /* Initialize sub-modules */ + + /* Entropy encoding: either Huffman or arithmetic coding. */ + if (cinfo->arith_code) { +#ifdef WITH_ARITHMETIC_PATCH + jinit_arith_encoder(cinfo); +#else + ERREXIT(cinfo, JERR_ARITH_NOTIMPL); +#endif + } else { + if (cinfo->process == JPROC_PROGRESSIVE) { +#ifdef C_PROGRESSIVE_SUPPORTED + jinit_phuff_encoder(cinfo); +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } else + jinit_shuff_encoder(cinfo); + } + + /* We need a special coefficient buffer controller. */ + transencode_coef_controller(cinfo, coef_arrays); + + /* Initialize method pointers */ + lossyc->pub.start_pass = start_pass_coef; + lossyc->pub.compress_data = compress_output; +} diff --git a/dcmjpeg/libijg12/jdapimin.c b/dcmjpeg/libijg12/jdapimin.c new file mode 100644 index 00000000..ee8cfa14 --- /dev/null +++ b/dcmjpeg/libijg12/jdapimin.c @@ -0,0 +1,401 @@ +/* + * jdapimin.c + * + * Copyright (C) 1994-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains application interface code for the decompression half + * of the JPEG library. These are the "minimum" API routines that may be + * needed in either the normal full-decompression case or the + * transcoding-only case. + * + * Most of the routines intended to be called directly by an application + * are in this file or in jdapistd.c. But also see jcomapi.c for routines + * shared by compression and decompression, and jdtrans.c for the transcoding + * case. + */ + +#define JPEG_INTERNALS +#include "jinclude12.h" +#include "jpeglib12.h" + + +/* + * Initialization of a JPEG decompression object. + * The error manager must already be set up (in case memory manager fails). + */ + +GLOBAL(void) +jpeg_CreateDecompress (j_decompress_ptr cinfo, int version, size_t structsize) +{ + int i; + + /* Guard against version mismatches between library and caller. */ + cinfo->mem = NULL; /* so jpeg_destroy knows mem mgr not called */ + if (version != JPEG_LIB_VERSION) + ERREXIT2(cinfo, JERR_BAD_LIB_VERSION, JPEG_LIB_VERSION, version); + if (structsize != SIZEOF(struct jpeg_decompress_struct)) + ERREXIT2(cinfo, JERR_BAD_STRUCT_SIZE, + (int) SIZEOF(struct jpeg_decompress_struct), (int) structsize); + + /* For debugging purposes, we zero the whole master structure. + * But the application has already set the err pointer, and may have set + * client_data, so we have to save and restore those fields. + * Note: if application hasn't set client_data, tools like Purify may + * complain here. + */ + { + struct jpeg_error_mgr * err = cinfo->err; + void * client_data = cinfo->client_data; /* ignore Purify complaint here */ + MEMZERO(cinfo, SIZEOF(struct jpeg_decompress_struct)); + cinfo->err = err; + cinfo->client_data = client_data; + } + cinfo->is_decompressor = TRUE; + + /* Initialize a memory manager instance for this object */ + jinit_memory_mgr((j_common_ptr) cinfo); + + /* Zero out pointers to permanent structures. */ + cinfo->progress = NULL; + cinfo->src = NULL; + + for (i = 0; i < NUM_QUANT_TBLS; i++) + cinfo->quant_tbl_ptrs[i] = NULL; + + for (i = 0; i < NUM_HUFF_TBLS; i++) { + cinfo->dc_huff_tbl_ptrs[i] = NULL; + cinfo->ac_huff_tbl_ptrs[i] = NULL; + } + + /* Initialize marker processor so application can override methods + * for COM, APPn markers before calling jpeg_read_header. + */ + cinfo->marker_list = NULL; + jinit_marker_reader(cinfo); + + /* And initialize the overall input controller. */ + jinit_input_controller(cinfo); + + /* OK, I'm ready */ + cinfo->global_state = DSTATE_START; +} + + +/* + * Destruction of a JPEG decompression object + */ + +GLOBAL(void) +jpeg_destroy_decompress (j_decompress_ptr cinfo) +{ + jpeg_destroy((j_common_ptr) cinfo); /* use common routine */ +} + + +/* + * Abort processing of a JPEG decompression operation, + * but don't destroy the object itself. + */ + +GLOBAL(void) +jpeg_abort_decompress (j_decompress_ptr cinfo) +{ + jpeg_abort((j_common_ptr) cinfo); /* use common routine */ +} + + +/* + * Set default decompression parameters. + */ + +LOCAL(void) +default_decompress_parms (j_decompress_ptr cinfo) +{ + /* Guess the input colorspace, and set output colorspace accordingly. */ + /* (Wish JPEG committee had provided a real way to specify this...) */ + /* Note application may override our guesses. */ + switch (cinfo->num_components) { + case 1: + cinfo->jpeg_color_space = JCS_GRAYSCALE; + cinfo->out_color_space = JCS_GRAYSCALE; + break; + + case 3: + if (cinfo->saw_JFIF_marker) { + cinfo->jpeg_color_space = JCS_YCbCr; /* JFIF implies YCbCr */ + } else if (cinfo->saw_Adobe_marker) { + switch (cinfo->Adobe_transform) { + case 0: + cinfo->jpeg_color_space = JCS_RGB; + break; + case 1: + cinfo->jpeg_color_space = JCS_YCbCr; + break; + default: + WARNMS1(cinfo, JWRN_ADOBE_XFORM, cinfo->Adobe_transform); + cinfo->jpeg_color_space = JCS_YCbCr; /* assume it's YCbCr */ + break; + } + } else { + /* Saw no special markers, try to guess from the component IDs */ + int cid0 = cinfo->comp_info[0].component_id; + int cid1 = cinfo->comp_info[1].component_id; + int cid2 = cinfo->comp_info[2].component_id; + + if (cid0 == 1 && cid1 == 2 && cid2 == 3) + cinfo->jpeg_color_space = JCS_YCbCr; /* assume JFIF w/out marker */ + else if (cid0 == 82 && cid1 == 71 && cid2 == 66) + cinfo->jpeg_color_space = JCS_RGB; /* ASCII 'R', 'G', 'B' */ + else { + if (cinfo->process == JPROC_LOSSLESS) { + TRACEMS3(cinfo, 1, JTRC_UNKNOWN_LOSSLESS_IDS, cid0, cid1, cid2); + cinfo->jpeg_color_space = JCS_RGB; /* assume it's RGB */ + } + else { /* Lossy processes */ + TRACEMS3(cinfo, 1, JTRC_UNKNOWN_LOSSY_IDS, cid0, cid1, cid2); + cinfo->jpeg_color_space = JCS_YCbCr; /* assume it's YCbCr */ + } + } + } + /* Always guess RGB is proper output colorspace. */ + cinfo->out_color_space = JCS_RGB; + break; + + case 4: + if (cinfo->saw_Adobe_marker) { + switch (cinfo->Adobe_transform) { + case 0: + cinfo->jpeg_color_space = JCS_CMYK; + break; + case 2: + cinfo->jpeg_color_space = JCS_YCCK; + break; + default: + WARNMS1(cinfo, JWRN_ADOBE_XFORM, cinfo->Adobe_transform); + cinfo->jpeg_color_space = JCS_YCCK; /* assume it's YCCK */ + break; + } + } else { + /* No special markers, assume straight CMYK. */ + cinfo->jpeg_color_space = JCS_CMYK; + } + cinfo->out_color_space = JCS_CMYK; + break; + + default: + cinfo->jpeg_color_space = JCS_UNKNOWN; + cinfo->out_color_space = JCS_UNKNOWN; + break; + } + + /* Set defaults for other decompression parameters. */ + cinfo->scale_num = 1; /* 1:1 scaling */ + cinfo->scale_denom = 1; + cinfo->output_gamma = 1.0; + cinfo->buffered_image = FALSE; + cinfo->raw_data_out = FALSE; + cinfo->dct_method = JDCT_DEFAULT; + cinfo->do_fancy_upsampling = TRUE; + cinfo->do_block_smoothing = TRUE; + cinfo->quantize_colors = FALSE; + /* We set these in case application only sets quantize_colors. */ + cinfo->dither_mode = JDITHER_FS; +#ifdef QUANT_2PASS_SUPPORTED + cinfo->two_pass_quantize = TRUE; +#else + cinfo->two_pass_quantize = FALSE; +#endif + cinfo->desired_number_of_colors = 256; + cinfo->colormap = NULL; + /* Initialize for no mode change in buffered-image mode. */ + cinfo->enable_1pass_quant = FALSE; + cinfo->enable_external_quant = FALSE; + cinfo->enable_2pass_quant = FALSE; +} + + +/* + * Decompression startup: read start of JPEG datastream to see what's there. + * Need only initialize JPEG object and supply a data source before calling. + * + * This routine will read as far as the first SOS marker (ie, actual start of + * compressed data), and will save all tables and parameters in the JPEG + * object. It will also initialize the decompression parameters to default + * values, and finally return JPEG_HEADER_OK. On return, the application may + * adjust the decompression parameters and then call jpeg_start_decompress. + * (Or, if the application only wanted to determine the image parameters, + * the data need not be decompressed. In that case, call jpeg_abort or + * jpeg_destroy to release any temporary space.) + * If an abbreviated (tables only) datastream is presented, the routine will + * return JPEG_HEADER_TABLES_ONLY upon reaching EOI. The application may then + * re-use the JPEG object to read the abbreviated image datastream(s). + * It is unnecessary (but OK) to call jpeg_abort in this case. + * The JPEG_SUSPENDED return code only occurs if the data source module + * requests suspension of the decompressor. In this case the application + * should load more source data and then re-call jpeg_read_header to resume + * processing. + * If a non-suspending data source is used and require_image is TRUE, then the + * return code need not be inspected since only JPEG_HEADER_OK is possible. + * + * This routine is now just a front end to jpeg_consume_input, with some + * extra error checking. + */ + +GLOBAL(int) +jpeg_read_header (j_decompress_ptr cinfo, boolean require_image) +{ + int retcode; + + if (cinfo->global_state != DSTATE_START && + cinfo->global_state != DSTATE_INHEADER) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + + retcode = jpeg_consume_input(cinfo); + + switch (retcode) { + case JPEG_REACHED_SOS: + retcode = JPEG_HEADER_OK; + break; + case JPEG_REACHED_EOI: + if (require_image) /* Complain if application wanted an image */ + ERREXIT(cinfo, JERR_NO_IMAGE); + /* Reset to start state; it would be safer to require the application to + * call jpeg_abort, but we can't change it now for compatibility reasons. + * A side effect is to free any temporary memory (there shouldn't be any). + */ + jpeg_abort((j_common_ptr) cinfo); /* sets state = DSTATE_START */ + retcode = JPEG_HEADER_TABLES_ONLY; + break; + case JPEG_SUSPENDED: + /* no work */ + break; + } + + return retcode; +} + + +/* + * Consume data in advance of what the decompressor requires. + * This can be called at any time once the decompressor object has + * been created and a data source has been set up. + * + * This routine is essentially a state machine that handles a couple + * of critical state-transition actions, namely initial setup and + * transition from header scanning to ready-for-start_decompress. + * All the actual input is done via the input controller's consume_input + * method. + */ + +GLOBAL(int) +jpeg_consume_input (j_decompress_ptr cinfo) +{ + int retcode = JPEG_SUSPENDED; + + /* NB: every possible DSTATE value should be listed in this switch */ + switch (cinfo->global_state) { + case DSTATE_START: + /* Start-of-datastream actions: reset appropriate modules */ + (*cinfo->inputctl->reset_input_controller) (cinfo); + /* Initialize application's data source module */ + (*cinfo->src->init_source) (cinfo); + cinfo->global_state = DSTATE_INHEADER; + /*FALLTHROUGH*/ + case DSTATE_INHEADER: + retcode = (*cinfo->inputctl->consume_input) (cinfo); + if (retcode == JPEG_REACHED_SOS) { /* Found SOS, prepare to decompress */ + /* Set up default parameters based on header data */ + default_decompress_parms(cinfo); + /* Set global state: ready for start_decompress */ + cinfo->global_state = DSTATE_READY; + } + break; + case DSTATE_READY: + /* Can't advance past first SOS until start_decompress is called */ + retcode = JPEG_REACHED_SOS; + break; + case DSTATE_PRELOAD: + case DSTATE_PRESCAN: + case DSTATE_SCANNING: + case DSTATE_RAW_OK: + case DSTATE_BUFIMAGE: + case DSTATE_BUFPOST: + case DSTATE_STOPPING: + retcode = (*cinfo->inputctl->consume_input) (cinfo); + break; + default: + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + } + return retcode; +} + + +/* + * Have we finished reading the input file? + */ + +GLOBAL(boolean) +jpeg_input_complete (j_decompress_ptr cinfo) +{ + /* Check for valid jpeg object */ + if (cinfo->global_state < DSTATE_START || + cinfo->global_state > DSTATE_STOPPING) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + return cinfo->inputctl->eoi_reached; +} + + +/* + * Is there more than one scan? + */ + +GLOBAL(boolean) +jpeg_has_multiple_scans (j_decompress_ptr cinfo) +{ + /* Only valid after jpeg_read_header completes */ + if (cinfo->global_state < DSTATE_READY || + cinfo->global_state > DSTATE_STOPPING) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + return cinfo->inputctl->has_multiple_scans; +} + + +/* + * Finish JPEG decompression. + * + * This will normally just verify the file trailer and release temp storage. + * + * Returns FALSE if suspended. The return value need be inspected only if + * a suspending data source is used. + */ + +GLOBAL(boolean) +jpeg_finish_decompress (j_decompress_ptr cinfo) +{ + if ((cinfo->global_state == DSTATE_SCANNING || + cinfo->global_state == DSTATE_RAW_OK) && ! cinfo->buffered_image) { + /* Terminate final pass of non-buffered mode */ + if (cinfo->output_scanline < cinfo->output_height) + ERREXIT(cinfo, JERR_TOO_LITTLE_DATA); + (*cinfo->master->finish_output_pass) (cinfo); + cinfo->global_state = DSTATE_STOPPING; + } else if (cinfo->global_state == DSTATE_BUFIMAGE) { + /* Finishing after a buffered-image operation */ + cinfo->global_state = DSTATE_STOPPING; + } else if (cinfo->global_state != DSTATE_STOPPING) { + /* STOPPING = repeat call after a suspension, anything else is error */ + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + } + /* Read until EOI */ + while (! cinfo->inputctl->eoi_reached) { + if ((*cinfo->inputctl->consume_input) (cinfo) == JPEG_SUSPENDED) + return FALSE; /* Suspend, come back later */ + } + /* Do final cleanup */ + (*cinfo->src->term_source) (cinfo); + /* We can use jpeg_abort to release memory and reset global_state */ + jpeg_abort((j_common_ptr) cinfo); + return TRUE; +} diff --git a/dcmjpeg/libijg12/jdapistd.c b/dcmjpeg/libijg12/jdapistd.c new file mode 100644 index 00000000..faa2dd7d --- /dev/null +++ b/dcmjpeg/libijg12/jdapistd.c @@ -0,0 +1,275 @@ +/* + * jdapistd.c + * + * Copyright (C) 1994-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains application interface code for the decompression half + * of the JPEG library. These are the "standard" API routines that are + * used in the normal full-decompression case. They are not used by a + * transcoding-only application. Note that if an application links in + * jpeg_start_decompress, it will end up linking in the entire decompressor. + * We thus must separate this file from jdapimin.c to avoid linking the + * whole decompression library into a transcoder. + */ + +#define JPEG_INTERNALS +#include "jinclude12.h" +#include "jpeglib12.h" + + +/* Forward declarations */ +LOCAL(boolean) output_pass_setup JPP((j_decompress_ptr cinfo)); + + +/* + * Decompression initialization. + * jpeg_read_header must be completed before calling this. + * + * If a multipass operating mode was selected, this will do all but the + * last pass, and thus may take a great deal of time. + * + * Returns FALSE if suspended. The return value need be inspected only if + * a suspending data source is used. + */ + +GLOBAL(boolean) +jpeg_start_decompress (j_decompress_ptr cinfo) +{ + if (cinfo->global_state == DSTATE_READY) { + /* First call: initialize master control, select active modules */ + jinit_master_decompress(cinfo); + if (cinfo->buffered_image) { + /* No more work here; expecting jpeg_start_output next */ + cinfo->global_state = DSTATE_BUFIMAGE; + return TRUE; + } + cinfo->global_state = DSTATE_PRELOAD; + } + if (cinfo->global_state == DSTATE_PRELOAD) { + /* If file has multiple scans, absorb them all into the coef buffer */ + if (cinfo->inputctl->has_multiple_scans) { +#ifdef D_MULTISCAN_FILES_SUPPORTED + for (;;) { + int retcode; + /* Call progress monitor hook if present */ + if (cinfo->progress != NULL) + (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); + /* Absorb some more input */ + retcode = (*cinfo->inputctl->consume_input) (cinfo); + if (retcode == JPEG_SUSPENDED) + return FALSE; + if (retcode == JPEG_REACHED_EOI) + break; + /* Advance progress counter if appropriate */ + if (cinfo->progress != NULL && + (retcode == JPEG_ROW_COMPLETED || retcode == JPEG_REACHED_SOS)) { + if (++cinfo->progress->pass_counter >= cinfo->progress->pass_limit) { + /* jdmaster underestimated number of scans; ratchet up one scan */ + cinfo->progress->pass_limit += (long) cinfo->total_iMCU_rows; + } + } + } +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif /* D_MULTISCAN_FILES_SUPPORTED */ + } + cinfo->output_scan_number = cinfo->input_scan_number; + } else if (cinfo->global_state != DSTATE_PRESCAN) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + /* Perform any dummy output passes, and set up for the final pass */ + return output_pass_setup(cinfo); +} + + +/* + * Set up for an output pass, and perform any dummy pass(es) needed. + * Common subroutine for jpeg_start_decompress and jpeg_start_output. + * Entry: global_state = DSTATE_PRESCAN only if previously suspended. + * Exit: If done, returns TRUE and sets global_state for proper output mode. + * If suspended, returns FALSE and sets global_state = DSTATE_PRESCAN. + */ + +LOCAL(boolean) +output_pass_setup (j_decompress_ptr cinfo) +{ + if (cinfo->global_state != DSTATE_PRESCAN) { + /* First call: do pass setup */ + (*cinfo->master->prepare_for_output_pass) (cinfo); + cinfo->output_scanline = 0; + cinfo->global_state = DSTATE_PRESCAN; + } + /* Loop over any required dummy passes */ + while (cinfo->master->is_dummy_pass) { +#ifdef QUANT_2PASS_SUPPORTED + /* Crank through the dummy pass */ + while (cinfo->output_scanline < cinfo->output_height) { + JDIMENSION last_scanline; + /* Call progress monitor hook if present */ + if (cinfo->progress != NULL) { + cinfo->progress->pass_counter = (long) cinfo->output_scanline; + cinfo->progress->pass_limit = (long) cinfo->output_height; + (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); + } + /* Process some data */ + last_scanline = cinfo->output_scanline; + (*cinfo->main->process_data) (cinfo, (JSAMPARRAY) NULL, + &cinfo->output_scanline, (JDIMENSION) 0); + if (cinfo->output_scanline == last_scanline) + return FALSE; /* No progress made, must suspend */ + } + /* Finish up dummy pass, and set up for another one */ + (*cinfo->master->finish_output_pass) (cinfo); + (*cinfo->master->prepare_for_output_pass) (cinfo); + cinfo->output_scanline = 0; +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif /* QUANT_2PASS_SUPPORTED */ + } + /* Ready for application to drive output pass through + * jpeg_read_scanlines or jpeg_read_raw_data. + */ + cinfo->global_state = cinfo->raw_data_out ? DSTATE_RAW_OK : DSTATE_SCANNING; + return TRUE; +} + + +/* + * Read some scanlines of data from the JPEG decompressor. + * + * The return value will be the number of lines actually read. + * This may be less than the number requested in several cases, + * including bottom of image, data source suspension, and operating + * modes that emit multiple scanlines at a time. + * + * Note: we warn about excess calls to jpeg_read_scanlines() since + * this likely signals an application programmer error. However, + * an oversize buffer (max_lines > scanlines remaining) is not an error. + */ + +GLOBAL(JDIMENSION) +jpeg_read_scanlines (j_decompress_ptr cinfo, JSAMPARRAY scanlines, + JDIMENSION max_lines) +{ + JDIMENSION row_ctr; + + if (cinfo->global_state != DSTATE_SCANNING) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + if (cinfo->output_scanline >= cinfo->output_height) { + WARNMS(cinfo, JWRN_TOO_MUCH_DATA); + return 0; + } + + /* Call progress monitor hook if present */ + if (cinfo->progress != NULL) { + cinfo->progress->pass_counter = (long) cinfo->output_scanline; + cinfo->progress->pass_limit = (long) cinfo->output_height; + (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); + } + + /* Process some data */ + row_ctr = 0; + (*cinfo->main->process_data) (cinfo, scanlines, &row_ctr, max_lines); + cinfo->output_scanline += row_ctr; + return row_ctr; +} + + +/* + * Alternate entry point to read raw data. + * Processes exactly one iMCU row per call, unless suspended. + */ + +GLOBAL(JDIMENSION) +jpeg_read_raw_data (j_decompress_ptr cinfo, JSAMPIMAGE data, + JDIMENSION max_lines) +{ + JDIMENSION lines_per_iMCU_row; + + if (cinfo->global_state != DSTATE_RAW_OK) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + if (cinfo->output_scanline >= cinfo->output_height) { + WARNMS(cinfo, JWRN_TOO_MUCH_DATA); + return 0; + } + + /* Call progress monitor hook if present */ + if (cinfo->progress != NULL) { + cinfo->progress->pass_counter = (long) cinfo->output_scanline; + cinfo->progress->pass_limit = (long) cinfo->output_height; + (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); + } + + /* Verify that at least one iMCU row can be returned. */ + lines_per_iMCU_row = (JDIMENSION)(cinfo->max_v_samp_factor * cinfo->min_codec_data_unit); + if (max_lines < lines_per_iMCU_row) + ERREXIT(cinfo, JERR_BUFFER_SIZE); + + /* Decompress directly into user's buffer. */ + if (! (*cinfo->codec->decompress_data) (cinfo, data)) + return 0; /* suspension forced, can do nothing more */ + + /* OK, we processed one iMCU row. */ + cinfo->output_scanline += lines_per_iMCU_row; + return lines_per_iMCU_row; +} + + +/* Additional entry points for buffered-image mode. */ + +#ifdef D_MULTISCAN_FILES_SUPPORTED + +/* + * Initialize for an output pass in buffered-image mode. + */ + +GLOBAL(boolean) +jpeg_start_output (j_decompress_ptr cinfo, int scan_number) +{ + if (cinfo->global_state != DSTATE_BUFIMAGE && + cinfo->global_state != DSTATE_PRESCAN) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + /* Limit scan number to valid range */ + if (scan_number <= 0) + scan_number = 1; + if (cinfo->inputctl->eoi_reached && + scan_number > cinfo->input_scan_number) + scan_number = cinfo->input_scan_number; + cinfo->output_scan_number = scan_number; + /* Perform any dummy output passes, and set up for the real pass */ + return output_pass_setup(cinfo); +} + + +/* + * Finish up after an output pass in buffered-image mode. + * + * Returns FALSE if suspended. The return value need be inspected only if + * a suspending data source is used. + */ + +GLOBAL(boolean) +jpeg_finish_output (j_decompress_ptr cinfo) +{ + if ((cinfo->global_state == DSTATE_SCANNING || + cinfo->global_state == DSTATE_RAW_OK) && cinfo->buffered_image) { + /* Terminate this pass. */ + /* We do not require the whole pass to have been completed. */ + (*cinfo->master->finish_output_pass) (cinfo); + cinfo->global_state = DSTATE_BUFPOST; + } else if (cinfo->global_state != DSTATE_BUFPOST) { + /* BUFPOST = repeat call after a suspension, anything else is error */ + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + } + /* Read markers looking for SOS or EOI */ + while (cinfo->input_scan_number <= cinfo->output_scan_number && + ! cinfo->inputctl->eoi_reached) { + if ((*cinfo->inputctl->consume_input) (cinfo) == JPEG_SUSPENDED) + return FALSE; /* Suspend, come back later */ + } + cinfo->global_state = DSTATE_BUFIMAGE; + return TRUE; +} + +#endif /* D_MULTISCAN_FILES_SUPPORTED */ diff --git a/dcmjpeg/libijg12/jdarith.c b/dcmjpeg/libijg12/jdarith.c new file mode 100644 index 00000000..b7e6f090 --- /dev/null +++ b/dcmjpeg/libijg12/jdarith.c @@ -0,0 +1,26 @@ +/* + * jdarith.c + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file holds place for arithmetic entropy decoding routines. + */ + +#define JPEG_INTERNALS +#include "jinclude12.h" +#include "jpeglib12.h" + + +/* + * Module initialization routine for arithmetic entropy decoding. + */ +GLOBAL(void) +jinit_arith_decoder (j_decompress_ptr cinfo); + +GLOBAL(void) +jinit_arith_decoder (j_decompress_ptr cinfo) +{ + ERREXIT(cinfo, JERR_ARITH_NOTIMPL); +} diff --git a/dcmjpeg/libijg12/jdatadst.c b/dcmjpeg/libijg12/jdatadst.c new file mode 100644 index 00000000..0db49910 --- /dev/null +++ b/dcmjpeg/libijg12/jdatadst.c @@ -0,0 +1,151 @@ +/* + * jdatadst.c + * + * Copyright (C) 1994-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains compression data destination routines for the case of + * emitting JPEG data to a file (or any stdio stream). While these routines + * are sufficient for most applications, some will want to use a different + * destination manager. + * IMPORTANT: we assume that fwrite() will correctly transcribe an array of + * JOCTETs into 8-bit-wide elements on external storage. If char is wider + * than 8 bits on your machine, you may need to do some tweaking. + */ + +/* this is not a core library module, so it doesn't define JPEG_INTERNALS */ +#include "jinclude12.h" +#include "jpeglib12.h" +#include "jerror12.h" + + +/* Expanded data destination object for stdio output */ + +typedef struct { + struct jpeg_destination_mgr pub; /* public fields */ + + FILE * outfile; /* target stream */ + JOCTET * buffer; /* start of buffer */ +} my_destination_mgr; + +typedef my_destination_mgr * my_dest_ptr; + +#define OUTPUT_BUF_SIZE 4096 /* choose an efficiently fwrite'able size */ + + +/* + * Initialize destination --- called by jpeg_start_compress + * before any data is actually written. + */ + +METHODDEF(void) +init_destination (j_compress_ptr cinfo) +{ + my_dest_ptr dest = (my_dest_ptr) cinfo->dest; + + /* Allocate the output buffer --- it will be released when done with image */ + dest->buffer = (JOCTET *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + OUTPUT_BUF_SIZE * SIZEOF(JOCTET)); + + dest->pub.next_output_byte = dest->buffer; + dest->pub.free_in_buffer = OUTPUT_BUF_SIZE; +} + + +/* + * Empty the output buffer --- called whenever buffer fills up. + * + * In typical applications, this should write the entire output buffer + * (ignoring the current state of next_output_byte & free_in_buffer), + * reset the pointer & count to the start of the buffer, and return TRUE + * indicating that the buffer has been dumped. + * + * In applications that need to be able to suspend compression due to output + * overrun, a FALSE return indicates that the buffer cannot be emptied now. + * In this situation, the compressor will return to its caller (possibly with + * an indication that it has not accepted all the supplied scanlines). The + * application should resume compression after it has made more room in the + * output buffer. Note that there are substantial restrictions on the use of + * suspension --- see the documentation. + * + * When suspending, the compressor will back up to a convenient restart point + * (typically the start of the current MCU). next_output_byte & free_in_buffer + * indicate where the restart point will be if the current call returns FALSE. + * Data beyond this point will be regenerated after resumption, so do not + * write it out when emptying the buffer externally. + */ + +METHODDEF(boolean) +empty_output_buffer (j_compress_ptr cinfo) +{ + my_dest_ptr dest = (my_dest_ptr) cinfo->dest; + + if (JFWRITE(dest->outfile, dest->buffer, OUTPUT_BUF_SIZE) != + (size_t) OUTPUT_BUF_SIZE) + ERREXIT(cinfo, JERR_FILE_WRITE); + + dest->pub.next_output_byte = dest->buffer; + dest->pub.free_in_buffer = OUTPUT_BUF_SIZE; + + return TRUE; +} + + +/* + * Terminate destination --- called by jpeg_finish_compress + * after all data has been written. Usually needs to flush buffer. + * + * NB: *not* called by jpeg_abort or jpeg_destroy; surrounding + * application must deal with any cleanup that should happen even + * for error exit. + */ + +METHODDEF(void) +term_destination (j_compress_ptr cinfo) +{ + my_dest_ptr dest = (my_dest_ptr) cinfo->dest; + size_t datacount = OUTPUT_BUF_SIZE - dest->pub.free_in_buffer; + + /* Write any data remaining in the buffer */ + if (datacount > 0) { + if (JFWRITE(dest->outfile, dest->buffer, datacount) != datacount) + ERREXIT(cinfo, JERR_FILE_WRITE); + } + fflush(dest->outfile); + /* Make sure we wrote the output file OK */ + if (ferror(dest->outfile)) + ERREXIT(cinfo, JERR_FILE_WRITE); +} + + +/* + * Prepare for output to a stdio stream. + * The caller must have already opened the stream, and is responsible + * for closing it after finishing compression. + */ + +GLOBAL(void) +jpeg_stdio_dest (j_compress_ptr cinfo, FILE * outfile) +{ + my_dest_ptr dest; + + /* The destination object is made permanent so that multiple JPEG images + * can be written to the same file without re-executing jpeg_stdio_dest. + * This makes it dangerous to use this manager and a different destination + * manager serially with the same JPEG object, because their private object + * sizes may be different. Caveat programmer. + */ + if (cinfo->dest == NULL) { /* first time for this JPEG object? */ + cinfo->dest = (struct jpeg_destination_mgr *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, + SIZEOF(my_destination_mgr)); + } + + dest = (my_dest_ptr) cinfo->dest; + dest->pub.init_destination = init_destination; + dest->pub.empty_output_buffer = empty_output_buffer; + dest->pub.term_destination = term_destination; + dest->outfile = outfile; +} diff --git a/dcmjpeg/libijg12/jdatasrc.c b/dcmjpeg/libijg12/jdatasrc.c new file mode 100644 index 00000000..f4d03dbb --- /dev/null +++ b/dcmjpeg/libijg12/jdatasrc.c @@ -0,0 +1,212 @@ +/* + * jdatasrc.c + * + * Copyright (C) 1994-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains decompression data source routines for the case of + * reading JPEG data from a file (or any stdio stream). While these routines + * are sufficient for most applications, some will want to use a different + * source manager. + * IMPORTANT: we assume that fread() will correctly transcribe an array of + * JOCTETs from 8-bit-wide elements on external storage. If char is wider + * than 8 bits on your machine, you may need to do some tweaking. + */ + +/* this is not a core library module, so it doesn't define JPEG_INTERNALS */ +#include "jinclude12.h" +#include "jpeglib12.h" +#include "jerror12.h" + + +/* Expanded data source object for stdio input */ + +typedef struct { + struct jpeg_source_mgr pub; /* public fields */ + + FILE * infile; /* source stream */ + JOCTET * buffer; /* start of buffer */ + boolean start_of_file; /* have we gotten any data yet? */ +} my_source_mgr; + +typedef my_source_mgr * my_src_ptr; + +#define INPUT_BUF_SIZE 4096 /* choose an efficiently fread'able size */ + + +/* + * Initialize source --- called by jpeg_read_header + * before any data is actually read. + */ + +METHODDEF(void) +init_source (j_decompress_ptr cinfo) +{ + my_src_ptr src = (my_src_ptr) cinfo->src; + + /* We reset the empty-input-file flag for each image, + * but we don't clear the input buffer. + * This is correct behavior for reading a series of images from one source. + */ + src->start_of_file = TRUE; +} + + +/* + * Fill the input buffer --- called whenever buffer is emptied. + * + * In typical applications, this should read fresh data into the buffer + * (ignoring the current state of next_input_byte & bytes_in_buffer), + * reset the pointer & count to the start of the buffer, and return TRUE + * indicating that the buffer has been reloaded. It is not necessary to + * fill the buffer entirely, only to obtain at least one more byte. + * + * There is no such thing as an EOF return. If the end of the file has been + * reached, the routine has a choice of ERREXIT() or inserting fake data into + * the buffer. In most cases, generating a warning message and inserting a + * fake EOI marker is the best course of action --- this will allow the + * decompressor to output however much of the image is there. However, + * the resulting error message is misleading if the real problem is an empty + * input file, so we handle that case specially. + * + * In applications that need to be able to suspend compression due to input + * not being available yet, a FALSE return indicates that no more data can be + * obtained right now, but more may be forthcoming later. In this situation, + * the decompressor will return to its caller (with an indication of the + * number of scanlines it has read, if any). The application should resume + * decompression after it has loaded more data into the input buffer. Note + * that there are substantial restrictions on the use of suspension --- see + * the documentation. + * + * When suspending, the decompressor will back up to a convenient restart point + * (typically the start of the current MCU). next_input_byte & bytes_in_buffer + * indicate where the restart point will be if the current call returns FALSE. + * Data beyond this point must be rescanned after resumption, so move it to + * the front of the buffer rather than discarding it. + */ + +METHODDEF(boolean) +fill_input_buffer (j_decompress_ptr cinfo) +{ + my_src_ptr src = (my_src_ptr) cinfo->src; + size_t nbytes; + + nbytes = JFREAD(src->infile, src->buffer, INPUT_BUF_SIZE); + + if (nbytes <= 0) { + if (src->start_of_file) /* Treat empty input file as fatal error */ + ERREXIT(cinfo, JERR_INPUT_EMPTY); + WARNMS(cinfo, JWRN_JPEG_EOF); + /* Insert a fake EOI marker */ + src->buffer[0] = (JOCTET) 0xFF; + src->buffer[1] = (JOCTET) JPEG_EOI; + nbytes = 2; + } + + src->pub.next_input_byte = src->buffer; + src->pub.bytes_in_buffer = nbytes; + src->start_of_file = FALSE; + + return TRUE; +} + + +/* + * Skip data --- used to skip over a potentially large amount of + * uninteresting data (such as an APPn marker). + * + * Writers of suspendable-input applications must note that skip_input_data + * is not granted the right to give a suspension return. If the skip extends + * beyond the data currently in the buffer, the buffer can be marked empty so + * that the next read will cause a fill_input_buffer call that can suspend. + * Arranging for additional bytes to be discarded before reloading the input + * buffer is the application writer's problem. + */ + +METHODDEF(void) +skip_input_data (j_decompress_ptr cinfo, long num_bytes) +{ + my_src_ptr src = (my_src_ptr) cinfo->src; + + /* Just a dumb implementation for now. Could use fseek() except + * it doesn't work on pipes. Not clear that being smart is worth + * any trouble anyway --- large skips are infrequent. + */ + if (num_bytes > 0) { + while (num_bytes > (long) src->pub.bytes_in_buffer) { + num_bytes -= (long) src->pub.bytes_in_buffer; + (void) fill_input_buffer(cinfo); + /* note we assume that fill_input_buffer will never return FALSE, + * so suspension need not be handled. + */ + } + src->pub.next_input_byte += (size_t) num_bytes; + src->pub.bytes_in_buffer -= (size_t) num_bytes; + } +} + + +/* + * An additional method that can be provided by data source modules is the + * resync_to_restart method for error recovery in the presence of RST markers. + * For the moment, this source module just uses the default resync method + * provided by the JPEG library. That method assumes that no backtracking + * is possible. + */ + + +/* + * Terminate source --- called by jpeg_finish_decompress + * after all data has been read. Often a no-op. + * + * NB: *not* called by jpeg_abort or jpeg_destroy; surrounding + * application must deal with any cleanup that should happen even + * for error exit. + */ + +METHODDEF(void) +term_source (j_decompress_ptr cinfo) +{ + /* no work necessary here */ +} + + +/* + * Prepare for input from a stdio stream. + * The caller must have already opened the stream, and is responsible + * for closing it after finishing decompression. + */ + +GLOBAL(void) +jpeg_stdio_src (j_decompress_ptr cinfo, FILE * infile) +{ + my_src_ptr src; + + /* The source object and input buffer are made permanent so that a series + * of JPEG images can be read from the same file by calling jpeg_stdio_src + * only before the first one. (If we discarded the buffer at the end of + * one image, we'd likely lose the start of the next one.) + * This makes it unsafe to use this manager and a different source + * manager serially with the same JPEG object. Caveat programmer. + */ + if (cinfo->src == NULL) { /* first time for this JPEG object? */ + cinfo->src = (struct jpeg_source_mgr *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, + SIZEOF(my_source_mgr)); + src = (my_src_ptr) cinfo->src; + src->buffer = (JOCTET *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, + INPUT_BUF_SIZE * SIZEOF(JOCTET)); + } + + src = (my_src_ptr) cinfo->src; + src->pub.init_source = init_source; + src->pub.fill_input_buffer = fill_input_buffer; + src->pub.skip_input_data = skip_input_data; + src->pub.resync_to_restart = jpeg_resync_to_restart; /* use default method */ + src->pub.term_source = term_source; + src->infile = infile; + src->pub.bytes_in_buffer = 0; /* forces fill_input_buffer on first read */ + src->pub.next_input_byte = NULL; /* until buffer loaded */ +} diff --git a/dcmjpeg/libijg12/jdcoefct.c b/dcmjpeg/libijg12/jdcoefct.c new file mode 100644 index 00000000..61e8b344 --- /dev/null +++ b/dcmjpeg/libijg12/jdcoefct.c @@ -0,0 +1,743 @@ +/* + * jdcoefct.c + * + * Copyright (C) 1994-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains the coefficient buffer controller for decompression. + * This controller is the top level of the lossy JPEG decompressor proper. + * The coefficient buffer lies between entropy decoding and inverse-DCT steps. + * + * In buffered-image mode, this controller is the interface between + * input-oriented processing and output-oriented processing. + * Also, the input side (only) is used when reading a file for transcoding. + */ + +#define JPEG_INTERNALS +#include "jinclude12.h" +#include "jpeglib12.h" +#include "jlossy12.h" + +/* Block smoothing is only applicable for progressive JPEG, so: */ +#ifndef D_PROGRESSIVE_SUPPORTED +#undef BLOCK_SMOOTHING_SUPPORTED +#endif + +/* Private buffer controller object */ + +typedef struct { + /* These variables keep track of the current location of the input side. */ + /* cinfo->input_iMCU_row is also used for this. */ + JDIMENSION MCU_ctr; /* counts MCUs processed in current row */ + int MCU_vert_offset; /* counts MCU rows within iMCU row */ + int MCU_rows_per_iMCU_row; /* number of such rows needed */ + + /* The output side's location is represented by cinfo->output_iMCU_row. */ + + /* In single-pass modes, it's sufficient to buffer just one MCU. + * We allocate a workspace of D_MAX_DATA_UNITS_IN_MCU coefficient blocks, + * and let the entropy decoder write into that workspace each time. + * (On 80x86, the workspace is FAR even though it's not really very big; + * this is to keep the module interfaces unchanged when a large coefficient + * buffer is necessary.) + * In multi-pass modes, this array points to the current MCU's blocks + * within the virtual arrays; it is used only by the input side. + */ + JBLOCKROW MCU_buffer[D_MAX_DATA_UNITS_IN_MCU]; + +#ifdef D_MULTISCAN_FILES_SUPPORTED + /* In multi-pass modes, we need a virtual block array for each component. */ + jvirt_barray_ptr whole_image[MAX_COMPONENTS]; +#endif + +#ifdef BLOCK_SMOOTHING_SUPPORTED + /* When doing block smoothing, we latch coefficient Al values here */ + int * coef_bits_latch; +#define SAVED_COEFS 6 /* we save coef_bits[0..5] */ +#endif +} d_coef_controller; + +typedef d_coef_controller * d_coef_ptr; + +/* Forward declarations */ +METHODDEF(int) decompress_onepass + JPP((j_decompress_ptr cinfo, JSAMPIMAGE output_buf)); +#ifdef D_MULTISCAN_FILES_SUPPORTED +METHODDEF(int) decompress_data + JPP((j_decompress_ptr cinfo, JSAMPIMAGE output_buf)); +#endif +#ifdef BLOCK_SMOOTHING_SUPPORTED +LOCAL(boolean) smoothing_ok JPP((j_decompress_ptr cinfo)); +METHODDEF(int) decompress_smooth_data + JPP((j_decompress_ptr cinfo, JSAMPIMAGE output_buf)); +#endif + + +LOCAL(void) +start_iMCU_row (j_decompress_ptr cinfo) +/* Reset within-iMCU-row counters for a new row (input side) */ +{ + j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec; + d_coef_ptr coef = (d_coef_ptr) lossyd->coef_private; + + /* In an interleaved scan, an MCU row is the same as an iMCU row. + * In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows. + * But at the bottom of the image, process only what's left. + */ + if (cinfo->comps_in_scan > 1) { + coef->MCU_rows_per_iMCU_row = 1; + } else { + if (cinfo->input_iMCU_row < (cinfo->total_iMCU_rows-1)) + coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->v_samp_factor; + else + coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->last_row_height; + } + + coef->MCU_ctr = 0; + coef->MCU_vert_offset = 0; +} + + +/* + * Initialize for an input processing pass. + */ + +METHODDEF(void) +start_input_pass (j_decompress_ptr cinfo) +{ + cinfo->input_iMCU_row = 0; + start_iMCU_row(cinfo); +} + + +/* + * Initialize for an output processing pass. + */ + +METHODDEF(void) +start_output_pass (j_decompress_ptr cinfo) +{ +#ifdef BLOCK_SMOOTHING_SUPPORTED + j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec; + /* d_coef_ptr coef = (d_coef_ptr) lossyd->coef_private; */ + + /* If multipass, check to see whether to use block smoothing on this pass */ + if (lossyd->coef_arrays != NULL) { + if (cinfo->do_block_smoothing && smoothing_ok(cinfo)) + lossyd->pub.decompress_data = decompress_smooth_data; + else + lossyd->pub.decompress_data = decompress_data; + } +#endif + cinfo->output_iMCU_row = 0; +} + + +/* + * Decompress and return some data in the single-pass case. + * Always attempts to emit one fully interleaved MCU row ("iMCU" row). + * Input and output must run in lockstep since we have only a one-MCU buffer. + * Return value is JPEG_ROW_COMPLETED, JPEG_SCAN_COMPLETED, or JPEG_SUSPENDED. + * + * NB: output_buf contains a plane for each component in image, + * which we index according to the component's SOF position. + */ + +METHODDEF(int) +decompress_onepass (j_decompress_ptr cinfo, JSAMPIMAGE output_buf) +{ + j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec; + d_coef_ptr coef = (d_coef_ptr) lossyd->coef_private; + JDIMENSION MCU_col_num; /* index of current MCU within row */ + JDIMENSION last_MCU_col = cinfo->MCUs_per_row - 1; + JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; + int blkn, ci, xindex, yindex, yoffset, useful_width; + JSAMPARRAY output_ptr; + JDIMENSION start_col, output_col; + jpeg_component_info *compptr; + inverse_DCT_method_ptr inverse_DCT; + + /* Loop to process as much as one whole iMCU row */ + for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row; + yoffset++) { + for (MCU_col_num = coef->MCU_ctr; MCU_col_num <= last_MCU_col; + MCU_col_num++) { + /* Try to fetch an MCU. Entropy decoder expects buffer to be zeroed. */ + jzero_far((void FAR *) coef->MCU_buffer[0], + (size_t)cinfo->data_units_in_MCU * SIZEOF(JBLOCK)); + if (! (*lossyd->entropy_decode_mcu) (cinfo, coef->MCU_buffer)) { + /* Suspension forced; update state counters and exit */ + coef->MCU_vert_offset = yoffset; + coef->MCU_ctr = MCU_col_num; + return JPEG_SUSPENDED; + } + /* Determine where data should go in output_buf and do the IDCT thing. + * We skip dummy blocks at the right and bottom edges (but blkn gets + * incremented past them!). Note the inner loop relies on having + * allocated the MCU_buffer[] blocks sequentially. + */ + blkn = 0; /* index of current DCT block within MCU */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + /* Don't bother to IDCT an uninteresting component. */ + if (! compptr->component_needed) { + blkn += compptr->MCU_data_units; + continue; + } + inverse_DCT = lossyd->inverse_DCT[compptr->component_index]; + useful_width = (MCU_col_num < last_MCU_col) ? compptr->MCU_width + : compptr->last_col_width; + output_ptr = output_buf[compptr->component_index] + + yoffset * compptr->codec_data_unit; + start_col = MCU_col_num * (JDIMENSION)compptr->MCU_sample_width; + for (yindex = 0; yindex < compptr->MCU_height; yindex++) { + if (cinfo->input_iMCU_row < last_iMCU_row || + yoffset+yindex < compptr->last_row_height) { + output_col = start_col; + for (xindex = 0; xindex < useful_width; xindex++) { + (*inverse_DCT) (cinfo, compptr, + (JCOEFPTR) coef->MCU_buffer[blkn+xindex], + output_ptr, output_col); + output_col += (JDIMENSION)compptr->codec_data_unit; + } + } + blkn += compptr->MCU_width; + output_ptr += compptr->codec_data_unit; + } + } + } + /* Completed an MCU row, but perhaps not an iMCU row */ + coef->MCU_ctr = 0; + } + /* Completed the iMCU row, advance counters for next one */ + cinfo->output_iMCU_row++; + if (++(cinfo->input_iMCU_row) < cinfo->total_iMCU_rows) { + start_iMCU_row(cinfo); + return JPEG_ROW_COMPLETED; + } + /* Completed the scan */ + (*cinfo->inputctl->finish_input_pass) (cinfo); + return JPEG_SCAN_COMPLETED; +} + + +/* + * Dummy consume-input routine for single-pass operation. + */ + +METHODDEF(int) +dummy_consume_data (j_decompress_ptr cinfo) +{ + return JPEG_SUSPENDED; /* Always indicate nothing was done */ +} + + +#ifdef D_MULTISCAN_FILES_SUPPORTED + +/* + * Consume input data and store it in the full-image coefficient buffer. + * We read as much as one fully interleaved MCU row ("iMCU" row) per call, + * ie, v_samp_factor block rows for each component in the scan. + * Return value is JPEG_ROW_COMPLETED, JPEG_SCAN_COMPLETED, or JPEG_SUSPENDED. + */ + +METHODDEF(int) +consume_data (j_decompress_ptr cinfo) +{ + j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec; + d_coef_ptr coef = (d_coef_ptr) lossyd->coef_private; + JDIMENSION MCU_col_num; /* index of current MCU within row */ + int blkn, ci, xindex, yindex, yoffset; + JDIMENSION start_col; + JBLOCKARRAY buffer[MAX_COMPS_IN_SCAN]; + JBLOCKROW buffer_ptr; + jpeg_component_info *compptr; + + /* Align the virtual buffers for the components used in this scan. */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + buffer[ci] = (*cinfo->mem->access_virt_barray) + ((j_common_ptr) cinfo, coef->whole_image[compptr->component_index], + cinfo->input_iMCU_row * (JDIMENSION)compptr->v_samp_factor, + (JDIMENSION) compptr->v_samp_factor, TRUE); + /* Note: entropy decoder expects buffer to be zeroed, + * but this is handled automatically by the memory manager + * because we requested a pre-zeroed array. + */ + } + + /* Loop to process one whole iMCU row */ + for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row; + yoffset++) { + for (MCU_col_num = coef->MCU_ctr; MCU_col_num < cinfo->MCUs_per_row; + MCU_col_num++) { + /* Construct list of pointers to DCT blocks belonging to this MCU */ + blkn = 0; /* index of current DCT block within MCU */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + start_col = MCU_col_num * (JDIMENSION)compptr->MCU_width; + for (yindex = 0; yindex < compptr->MCU_height; yindex++) { + buffer_ptr = buffer[ci][yindex+yoffset] + start_col; + for (xindex = 0; xindex < compptr->MCU_width; xindex++) { + coef->MCU_buffer[blkn++] = buffer_ptr++; + } + } + } + /* Try to fetch the MCU. */ + if (! (*lossyd->entropy_decode_mcu) (cinfo, coef->MCU_buffer)) { + /* Suspension forced; update state counters and exit */ + coef->MCU_vert_offset = yoffset; + coef->MCU_ctr = MCU_col_num; + return JPEG_SUSPENDED; + } + } + /* Completed an MCU row, but perhaps not an iMCU row */ + coef->MCU_ctr = 0; + } + /* Completed the iMCU row, advance counters for next one */ + if (++(cinfo->input_iMCU_row) < cinfo->total_iMCU_rows) { + start_iMCU_row(cinfo); + return JPEG_ROW_COMPLETED; + } + /* Completed the scan */ + (*cinfo->inputctl->finish_input_pass) (cinfo); + return JPEG_SCAN_COMPLETED; +} + + +/* + * Decompress and return some data in the multi-pass case. + * Always attempts to emit one fully interleaved MCU row ("iMCU" row). + * Return value is JPEG_ROW_COMPLETED, JPEG_SCAN_COMPLETED, or JPEG_SUSPENDED. + * + * NB: output_buf contains a plane for each component in image. + */ + +METHODDEF(int) +decompress_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf) +{ + j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec; + d_coef_ptr coef = (d_coef_ptr) lossyd->coef_private; + JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; + JDIMENSION block_num; + int ci, block_row, block_rows; + JBLOCKARRAY buffer; + JBLOCKROW buffer_ptr; + JSAMPARRAY output_ptr; + JDIMENSION output_col; + jpeg_component_info *compptr; + inverse_DCT_method_ptr inverse_DCT; + + /* Force some input to be done if we are getting ahead of the input. */ + while (cinfo->input_scan_number < cinfo->output_scan_number || + (cinfo->input_scan_number == cinfo->output_scan_number && + cinfo->input_iMCU_row <= cinfo->output_iMCU_row)) { + if ((*cinfo->inputctl->consume_input)(cinfo) == JPEG_SUSPENDED) + return JPEG_SUSPENDED; + } + + /* OK, output from the virtual arrays. */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + /* Don't bother to IDCT an uninteresting component. */ + if (! compptr->component_needed) + continue; + /* Align the virtual buffer for this component. */ + buffer = (*cinfo->mem->access_virt_barray) + ((j_common_ptr) cinfo, coef->whole_image[ci], + cinfo->output_iMCU_row * (JDIMENSION)compptr->v_samp_factor, + (JDIMENSION) compptr->v_samp_factor, FALSE); + /* Count non-dummy DCT block rows in this iMCU row. */ + if (cinfo->output_iMCU_row < last_iMCU_row) + block_rows = compptr->v_samp_factor; + else { + /* NB: can't use last_row_height here; it is input-side-dependent! */ + block_rows = (int)compptr->height_in_data_units % compptr->v_samp_factor; + if (block_rows == 0) block_rows = compptr->v_samp_factor; + } + inverse_DCT = lossyd->inverse_DCT[ci]; + output_ptr = output_buf[ci]; + /* Loop over all DCT blocks to be processed. */ + for (block_row = 0; block_row < block_rows; block_row++) { + buffer_ptr = buffer[block_row]; + output_col = 0; + for (block_num = 0; block_num < compptr->width_in_data_units; block_num++) { + (*inverse_DCT) (cinfo, compptr, (JCOEFPTR) buffer_ptr, + output_ptr, output_col); + buffer_ptr++; + output_col += (JDIMENSION)compptr->codec_data_unit; + } + output_ptr += compptr->codec_data_unit; + } + } + + if (++(cinfo->output_iMCU_row) < cinfo->total_iMCU_rows) + return JPEG_ROW_COMPLETED; + return JPEG_SCAN_COMPLETED; +} + +#endif /* D_MULTISCAN_FILES_SUPPORTED */ + + +#ifdef BLOCK_SMOOTHING_SUPPORTED + +/* + * This code applies interblock smoothing as described by section K.8 + * of the JPEG standard: the first 5 AC coefficients are estimated from + * the DC values of a DCT block and its 8 neighboring blocks. + * We apply smoothing only for progressive JPEG decoding, and only if + * the coefficients it can estimate are not yet known to full precision. + */ + +/* Natural-order array positions of the first 5 zigzag-order coefficients */ +#define Q01_POS 1 +#define Q10_POS 8 +#define Q20_POS 16 +#define Q11_POS 9 +#define Q02_POS 2 + +/* + * Determine whether block smoothing is applicable and safe. + * We also latch the current states of the coef_bits[] entries for the + * AC coefficients; otherwise, if the input side of the decompressor + * advances into a new scan, we might think the coefficients are known + * more accurately than they really are. + */ + +LOCAL(boolean) +smoothing_ok (j_decompress_ptr cinfo) +{ + j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec; + d_coef_ptr coef = (d_coef_ptr) lossyd->coef_private; + boolean smoothing_useful = FALSE; + int ci, coefi; + jpeg_component_info *compptr; + JQUANT_TBL * qtable; + int * coef_bits; + int * coef_bits_latch; + + if (! cinfo->process == JPROC_PROGRESSIVE || cinfo->coef_bits == NULL) + return FALSE; + + /* Allocate latch area if not already done */ + if (coef->coef_bits_latch == NULL) + coef->coef_bits_latch = (int *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (size_t)cinfo->num_components * + (SAVED_COEFS * SIZEOF(int))); + coef_bits_latch = coef->coef_bits_latch; + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + /* All components' quantization values must already be latched. */ + if ((qtable = compptr->quant_table) == NULL) + return FALSE; + /* Verify DC & first 5 AC quantizers are nonzero to avoid zero-divide. */ + if (qtable->quantval[0] == 0 || + qtable->quantval[Q01_POS] == 0 || + qtable->quantval[Q10_POS] == 0 || + qtable->quantval[Q20_POS] == 0 || + qtable->quantval[Q11_POS] == 0 || + qtable->quantval[Q02_POS] == 0) + return FALSE; + /* DC values must be at least partly known for all components. */ + coef_bits = cinfo->coef_bits[ci]; + if (coef_bits[0] < 0) + return FALSE; + /* Block smoothing is helpful if some AC coefficients remain inaccurate. */ + for (coefi = 1; coefi <= 5; coefi++) { + coef_bits_latch[coefi] = coef_bits[coefi]; + if (coef_bits[coefi] != 0) + smoothing_useful = TRUE; + } + coef_bits_latch += SAVED_COEFS; + } + + return smoothing_useful; +} + + +/* + * Variant of decompress_data for use when doing block smoothing. + */ + +METHODDEF(int) +decompress_smooth_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf) +{ + j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec; + d_coef_ptr coef = (d_coef_ptr) lossyd->coef_private; + JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; + JDIMENSION block_num, last_block_column; + int ci, block_row, block_rows, access_rows; + JBLOCKARRAY buffer; + JBLOCKROW buffer_ptr, prev_block_row, next_block_row; + JSAMPARRAY output_ptr; + JDIMENSION output_col; + jpeg_component_info *compptr; + inverse_DCT_method_ptr inverse_DCT; + boolean first_row, last_row; + JBLOCK workspace; + int *coef_bits; + JQUANT_TBL *quanttbl; + IJG_INT32 Q00,Q01,Q02,Q10,Q11,Q20, num; + int DC1,DC2,DC3,DC4,DC5,DC6,DC7,DC8,DC9; + int Al, pred; + + /* Force some input to be done if we are getting ahead of the input. */ + while (cinfo->input_scan_number <= cinfo->output_scan_number && + ! cinfo->inputctl->eoi_reached) { + if (cinfo->input_scan_number == cinfo->output_scan_number) { + /* If input is working on current scan, we ordinarily want it to + * have completed the current row. But if input scan is DC, + * we want it to keep one row ahead so that next block row's DC + * values are up to date. + */ + JDIMENSION delta = (cinfo->Ss == 0) ? 1 : 0; + if (cinfo->input_iMCU_row > cinfo->output_iMCU_row+delta) + break; + } + if ((*cinfo->inputctl->consume_input)(cinfo) == JPEG_SUSPENDED) + return JPEG_SUSPENDED; + } + + /* OK, output from the virtual arrays. */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + /* Don't bother to IDCT an uninteresting component. */ + if (! compptr->component_needed) + continue; + /* Count non-dummy DCT block rows in this iMCU row. */ + if (cinfo->output_iMCU_row < last_iMCU_row) { + block_rows = compptr->v_samp_factor; + access_rows = block_rows * 2; /* this and next iMCU row */ + last_row = FALSE; + } else { + /* NB: can't use last_row_height here; it is input-side-dependent! */ + block_rows = (int)compptr->height_in_data_units % compptr->v_samp_factor; + if (block_rows == 0) block_rows = compptr->v_samp_factor; + access_rows = block_rows; /* this iMCU row only */ + last_row = TRUE; + } + /* Align the virtual buffer for this component. */ + if (cinfo->output_iMCU_row > 0) { + access_rows += compptr->v_samp_factor; /* prior iMCU row too */ + buffer = (*cinfo->mem->access_virt_barray) + ((j_common_ptr) cinfo, coef->whole_image[ci], + (cinfo->output_iMCU_row - 1) * (JDIMENSION)compptr->v_samp_factor, + (JDIMENSION) access_rows, FALSE); + buffer += compptr->v_samp_factor; /* point to current iMCU row */ + first_row = FALSE; + } else { + buffer = (*cinfo->mem->access_virt_barray) + ((j_common_ptr) cinfo, coef->whole_image[ci], + (JDIMENSION) 0, (JDIMENSION) access_rows, FALSE); + first_row = TRUE; + } + /* Fetch component-dependent info */ + coef_bits = coef->coef_bits_latch + (ci * SAVED_COEFS); + quanttbl = compptr->quant_table; + Q00 = quanttbl->quantval[0]; + Q01 = quanttbl->quantval[Q01_POS]; + Q10 = quanttbl->quantval[Q10_POS]; + Q20 = quanttbl->quantval[Q20_POS]; + Q11 = quanttbl->quantval[Q11_POS]; + Q02 = quanttbl->quantval[Q02_POS]; + inverse_DCT = lossyd->inverse_DCT[ci]; + output_ptr = output_buf[ci]; + /* Loop over all DCT blocks to be processed. */ + for (block_row = 0; block_row < block_rows; block_row++) { + buffer_ptr = buffer[block_row]; + if (first_row && block_row == 0) + prev_block_row = buffer_ptr; + else + prev_block_row = buffer[block_row-1]; + if (last_row && block_row == block_rows-1) + next_block_row = buffer_ptr; + else + next_block_row = buffer[block_row+1]; + /* We fetch the surrounding DC values using a sliding-register approach. + * Initialize all nine here so as to do the right thing on narrow pics. + */ + DC1 = DC2 = DC3 = (int) prev_block_row[0][0]; + DC4 = DC5 = DC6 = (int) buffer_ptr[0][0]; + DC7 = DC8 = DC9 = (int) next_block_row[0][0]; + output_col = 0; + last_block_column = compptr->width_in_data_units - 1; + for (block_num = 0; block_num <= last_block_column; block_num++) { + /* Fetch current DCT block into workspace so we can modify it. */ + jcopy_block_row(buffer_ptr, (JBLOCKROW) workspace, (JDIMENSION) 1); + /* Update DC values */ + if (block_num < last_block_column) { + DC3 = (int) prev_block_row[1][0]; + DC6 = (int) buffer_ptr[1][0]; + DC9 = (int) next_block_row[1][0]; + } + /* Compute coefficient estimates per K.8. + * An estimate is applied only if coefficient is still zero, + * and is not known to be fully accurate. + */ + /* AC01 */ + if ((Al=coef_bits[1]) != 0 && workspace[1] == 0) { + num = 36 * Q00 * (DC4 - DC6); + if (num >= 0) { + pred = (int) (((Q01<<7) + num) / (Q01<<8)); + if (Al > 0 && pred >= (1< 0 && pred >= (1<= 0) { + pred = (int) (((Q10<<7) + num) / (Q10<<8)); + if (Al > 0 && pred >= (1< 0 && pred >= (1<= 0) { + pred = (int) (((Q20<<7) + num) / (Q20<<8)); + if (Al > 0 && pred >= (1< 0 && pred >= (1<= 0) { + pred = (int) (((Q11<<7) + num) / (Q11<<8)); + if (Al > 0 && pred >= (1< 0 && pred >= (1<= 0) { + pred = (int) (((Q02<<7) + num) / (Q02<<8)); + if (Al > 0 && pred >= (1< 0 && pred >= (1<codec_data_unit; + } + output_ptr += compptr->codec_data_unit; + } + } + + if (++(cinfo->output_iMCU_row) < cinfo->total_iMCU_rows) + return JPEG_ROW_COMPLETED; + return JPEG_SCAN_COMPLETED; +} + +#endif /* BLOCK_SMOOTHING_SUPPORTED */ + + +/* + * Initialize coefficient buffer controller. + */ + +GLOBAL(void) +jinit_d_coef_controller (j_decompress_ptr cinfo, boolean need_full_buffer) +{ + j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec; + d_coef_ptr coef; + + coef = (d_coef_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(d_coef_controller)); + lossyd->coef_private = (void *) coef; + lossyd->coef_start_input_pass = start_input_pass; + lossyd->coef_start_output_pass = start_output_pass; +#ifdef BLOCK_SMOOTHING_SUPPORTED + coef->coef_bits_latch = NULL; +#endif + + /* Create the coefficient buffer. */ + if (need_full_buffer) { +#ifdef D_MULTISCAN_FILES_SUPPORTED + /* Allocate a full-image virtual array for each component, */ + /* padded to a multiple of samp_factor DCT blocks in each direction. */ + /* Note we ask for a pre-zeroed array. */ + int ci, access_rows; + jpeg_component_info *compptr; + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + access_rows = compptr->v_samp_factor; +#ifdef BLOCK_SMOOTHING_SUPPORTED + /* If block smoothing could be used, need a bigger window */ + if (cinfo->process == JPROC_PROGRESSIVE) + access_rows *= 3; +#endif + coef->whole_image[ci] = (*cinfo->mem->request_virt_barray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, TRUE, + (JDIMENSION) jround_up((long) compptr->width_in_data_units, + (long) compptr->h_samp_factor), + (JDIMENSION) jround_up((long) compptr->height_in_data_units, + (long) compptr->v_samp_factor), + (JDIMENSION) access_rows); + } + lossyd->pub.consume_data = consume_data; + lossyd->pub.decompress_data = decompress_data; + lossyd->coef_arrays = coef->whole_image; /* link to virtual arrays */ +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } else { + /* We only need a single-MCU buffer. */ + JBLOCKROW buffer; + int i; + + buffer = (JBLOCKROW) + (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE, + D_MAX_DATA_UNITS_IN_MCU * SIZEOF(JBLOCK)); + for (i = 0; i < D_MAX_DATA_UNITS_IN_MCU; i++) { + coef->MCU_buffer[i] = buffer + i; + } + lossyd->pub.consume_data = dummy_consume_data; + lossyd->pub.decompress_data = decompress_onepass; + lossyd->coef_arrays = NULL; /* flag for no virtual arrays */ + } +} diff --git a/dcmjpeg/libijg12/jdcolor.c b/dcmjpeg/libijg12/jdcolor.c new file mode 100644 index 00000000..4ab46e4e --- /dev/null +++ b/dcmjpeg/libijg12/jdcolor.c @@ -0,0 +1,413 @@ +/* + * jdcolor.c + * + * Copyright (C) 1991-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains output colorspace conversion routines. + */ + +#define JPEG_INTERNALS +#include "jinclude12.h" +#include "jpeglib12.h" + + +/* Private subobject */ + +typedef struct { + struct jpeg_color_deconverter pub; /* public fields */ + + /* Private state for YCC->RGB conversion */ + int * Cr_r_tab; /* => table for Cr to R conversion */ + int * Cb_b_tab; /* => table for Cb to B conversion */ + IJG_INT32 * Cr_g_tab; /* => table for Cr to G conversion */ + IJG_INT32 * Cb_g_tab; /* => table for Cb to G conversion */ +} my_color_deconverter; + +typedef my_color_deconverter * my_cconvert_ptr; + + +/**************** YCbCr -> RGB conversion: most common case **************/ + +/* + * YCbCr is defined per CCIR 601-1, except that Cb and Cr are + * normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5. + * The conversion equations to be implemented are therefore + * R = Y + 1.40200 * Cr + * G = Y - 0.34414 * Cb - 0.71414 * Cr + * B = Y + 1.77200 * Cb + * where Cb and Cr represent the incoming values less CENTERJSAMPLE. + * (These numbers are derived from TIFF 6.0 section 21, dated 3-June-92.) + * + * To avoid floating-point arithmetic, we represent the fractional constants + * as integers scaled up by 2^16 (about 4 digits precision); we have to divide + * the products by 2^16, with appropriate rounding, to get the correct answer. + * Notice that Y, being an integral input, does not contribute any fraction + * so it need not participate in the rounding. + * + * For even more speed, we avoid doing any multiplications in the inner loop + * by precalculating the constants times Cb and Cr for all possible values. + * For 8-bit JSAMPLEs this is very reasonable (only 256 entries per table); + * for 12-bit samples it is still acceptable. It's not very reasonable for + * 16-bit samples, but if you want lossless storage you shouldn't be changing + * colorspace anyway. + * The Cr=>R and Cb=>B values can be rounded to integers in advance; the + * values for the G calculation are left scaled up, since we must add them + * together before rounding. + */ + +#define SCALEBITS 16 /* speediest right-shift on some machines */ +#define ONE_HALF ((IJG_INT32) 1 << (SCALEBITS-1)) +#define FIX(x) ((IJG_INT32) ((x) * (1L<RGB colorspace conversion. + */ + +LOCAL(void) +build_ycc_rgb_table (j_decompress_ptr cinfo) +{ + my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; + int i; + IJG_INT32 x; +#if BITS_IN_JSAMPLE == 16 + /* no need for temporaries */ +#else + SHIFT_TEMPS +#endif + + cconvert->Cr_r_tab = (int *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (MAXJSAMPLE+1) * SIZEOF(int)); + cconvert->Cb_b_tab = (int *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (MAXJSAMPLE+1) * SIZEOF(int)); + cconvert->Cr_g_tab = (IJG_INT32 *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (MAXJSAMPLE+1) * SIZEOF(IJG_INT32)); + cconvert->Cb_g_tab = (IJG_INT32 *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (MAXJSAMPLE+1) * SIZEOF(IJG_INT32)); + + for (i = 0, x = -CENTERJSAMPLE; i <= MAXJSAMPLE; i++, x++) { + /* i is the actual input pixel value, in the range 0..MAXJSAMPLE */ + /* The Cb or Cr value we are thinking of is x = i - CENTERJSAMPLE */ + +#if BITS_IN_JSAMPLE == 16 + /* Bug fix 2001-11-06 by Eichelberg: The integer routines below + produce an overflow when used with MAXJSAMPLE == 65535. + Use floating point calculation instead. */ + + /* Cr=>R value is nearest int to 1.40200 * x */ + cconvert->Cr_r_tab[i] = (int)(1.40200 * (double)x + 0.5); + /* Cb=>B value is nearest int to 1.77200 * x */ + cconvert->Cb_b_tab[i] = (int)(1.77200 * (double)x + 0.5); +#else + /* Cr=>R value is nearest int to 1.40200 * x */ + cconvert->Cr_r_tab[i] = (int) + RIGHT_SHIFT(FIX(1.40200) * x + ONE_HALF, SCALEBITS); + /* Cb=>B value is nearest int to 1.77200 * x */ + cconvert->Cb_b_tab[i] = (int) + RIGHT_SHIFT(FIX(1.77200) * x + ONE_HALF, SCALEBITS); +#endif + + /* Cr=>G value is scaled-up -0.71414 * x */ + cconvert->Cr_g_tab[i] = (- FIX(0.71414)) * x; + /* Cb=>G value is scaled-up -0.34414 * x */ + /* We also add in ONE_HALF so that need not do it in inner loop */ + cconvert->Cb_g_tab[i] = (- FIX(0.34414)) * x + ONE_HALF; + } +} + + +/* + * Convert some rows of samples to the output colorspace. + * + * Note that we change from noninterleaved, one-plane-per-component format + * to interleaved-pixel format. The output buffer is therefore three times + * as wide as the input buffer. + * A starting row offset is provided only for the input buffer. The caller + * can easily adjust the passed output_buf value to accommodate any row + * offset required on that side. + */ + +METHODDEF(void) +ycc_rgb_convert (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION input_row, + JSAMPARRAY output_buf, int num_rows) +{ + my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; + register int y, cb, cr; + register JSAMPROW outptr; + register JSAMPROW inptr0, inptr1, inptr2; + register JDIMENSION col; + JDIMENSION num_cols = cinfo->output_width; + /* copy these pointers into registers if possible */ + register JSAMPLE * range_limit = cinfo->sample_range_limit; + register int * Crrtab = cconvert->Cr_r_tab; + register int * Cbbtab = cconvert->Cb_b_tab; + register IJG_INT32 * Crgtab = cconvert->Cr_g_tab; + register IJG_INT32 * Cbgtab = cconvert->Cb_g_tab; + SHIFT_TEMPS + + while (--num_rows >= 0) { + inptr0 = input_buf[0][input_row]; + inptr1 = input_buf[1][input_row]; + inptr2 = input_buf[2][input_row]; + input_row++; + outptr = *output_buf++; + for (col = 0; col < num_cols; col++) { + y = GETJSAMPLE(inptr0[col]); + cb = GETJSAMPLE(inptr1[col]); + cr = GETJSAMPLE(inptr2[col]); + /* Range-limiting is essential due to noise introduced by DCT losses. */ + outptr[RGB_RED] = range_limit[y + Crrtab[cr]]; + outptr[RGB_GREEN] = range_limit[y + + ((int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], + SCALEBITS))]; + outptr[RGB_BLUE] = range_limit[y + Cbbtab[cb]]; + outptr += RGB_PIXELSIZE; + } + } +} + + +/**************** Cases other than YCbCr -> RGB **************/ + + +/* + * Color conversion for no colorspace change: just copy the data, + * converting from separate-planes to interleaved representation. + */ + +METHODDEF(void) +null_convert (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION input_row, + JSAMPARRAY output_buf, int num_rows) +{ + register JSAMPROW inptr, outptr; + register JDIMENSION count; + register int num_components = cinfo->num_components; + JDIMENSION num_cols = cinfo->output_width; + int ci; + + while (--num_rows >= 0) { + for (ci = 0; ci < num_components; ci++) { + inptr = input_buf[ci][input_row]; + outptr = output_buf[0] + ci; + for (count = num_cols; count > 0; count--) { + *outptr = *inptr++; /* needn't bother with GETJSAMPLE() here */ + outptr += num_components; + } + } + input_row++; + output_buf++; + } +} + + +/* + * Color conversion for grayscale: just copy the data. + * This also works for YCbCr -> grayscale conversion, in which + * we just copy the Y (luminance) component and ignore chrominance. + */ + +METHODDEF(void) +grayscale_convert (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION input_row, + JSAMPARRAY output_buf, int num_rows) +{ + jcopy_sample_rows(input_buf[0], (int) input_row, output_buf, 0, + num_rows, cinfo->output_width); +} + + +/* + * Convert grayscale to RGB: just duplicate the graylevel three times. + * This is provided to support applications that don't want to cope + * with grayscale as a separate case. + */ + +METHODDEF(void) +gray_rgb_convert (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION input_row, + JSAMPARRAY output_buf, int num_rows) +{ + register JSAMPROW inptr, outptr; + register JDIMENSION col; + JDIMENSION num_cols = cinfo->output_width; + + while (--num_rows >= 0) { + inptr = input_buf[0][input_row++]; + outptr = *output_buf++; + for (col = 0; col < num_cols; col++) { + /* We can dispense with GETJSAMPLE() here */ + outptr[RGB_RED] = outptr[RGB_GREEN] = outptr[RGB_BLUE] = inptr[col]; + outptr += RGB_PIXELSIZE; + } + } +} + + +/* + * Adobe-style YCCK->CMYK conversion. + * We convert YCbCr to R=1-C, G=1-M, and B=1-Y using the same + * conversion as above, while passing K (black) unchanged. + * We assume build_ycc_rgb_table has been called. + */ + +METHODDEF(void) +ycck_cmyk_convert (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION input_row, + JSAMPARRAY output_buf, int num_rows) +{ + my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; + register int y, cb, cr; + register JSAMPROW outptr; + register JSAMPROW inptr0, inptr1, inptr2, inptr3; + register JDIMENSION col; + JDIMENSION num_cols = cinfo->output_width; + /* copy these pointers into registers if possible */ + register JSAMPLE * range_limit = cinfo->sample_range_limit; + register int * Crrtab = cconvert->Cr_r_tab; + register int * Cbbtab = cconvert->Cb_b_tab; + register IJG_INT32 * Crgtab = cconvert->Cr_g_tab; + register IJG_INT32 * Cbgtab = cconvert->Cb_g_tab; + SHIFT_TEMPS + + while (--num_rows >= 0) { + inptr0 = input_buf[0][input_row]; + inptr1 = input_buf[1][input_row]; + inptr2 = input_buf[2][input_row]; + inptr3 = input_buf[3][input_row]; + input_row++; + outptr = *output_buf++; + for (col = 0; col < num_cols; col++) { + y = GETJSAMPLE(inptr0[col]); + cb = GETJSAMPLE(inptr1[col]); + cr = GETJSAMPLE(inptr2[col]); + /* Range-limiting is essential due to noise introduced by DCT losses. */ + outptr[0] = range_limit[MAXJSAMPLE - (y + Crrtab[cr])]; /* red */ + outptr[1] = range_limit[MAXJSAMPLE - (y + /* green */ + ((int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], + SCALEBITS)))]; + outptr[2] = range_limit[MAXJSAMPLE - (y + Cbbtab[cb])]; /* blue */ + /* K passes through unchanged */ + outptr[3] = inptr3[col]; /* don't need GETJSAMPLE here */ + outptr += 4; + } + } +} + + +/* + * Empty method for start_pass. + */ + +METHODDEF(void) +start_pass_dcolor (j_decompress_ptr cinfo) +{ + /* no work needed */ +} + + +/* + * Module initialization routine for output colorspace conversion. + */ + +GLOBAL(void) +jinit_color_deconverter (j_decompress_ptr cinfo) +{ + my_cconvert_ptr cconvert; + int ci; + + cconvert = (my_cconvert_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_color_deconverter)); + cinfo->cconvert = (struct jpeg_color_deconverter *) cconvert; + cconvert->pub.start_pass = start_pass_dcolor; + + /* Make sure num_components agrees with jpeg_color_space */ + switch (cinfo->jpeg_color_space) { + case JCS_GRAYSCALE: + if (cinfo->num_components != 1) + ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); + break; + + case JCS_RGB: + case JCS_YCbCr: + if (cinfo->num_components != 3) + ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); + break; + + case JCS_CMYK: + case JCS_YCCK: + if (cinfo->num_components != 4) + ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); + break; + + default: /* JCS_UNKNOWN can be anything */ + if (cinfo->num_components < 1) + ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); + break; + } + + /* Set out_color_components and conversion method based on requested space. + * Also clear the component_needed flags for any unused components, + * so that earlier pipeline stages can avoid useless computation. + */ + + switch (cinfo->out_color_space) { + case JCS_GRAYSCALE: + cinfo->out_color_components = 1; + if (cinfo->jpeg_color_space == JCS_GRAYSCALE || + cinfo->jpeg_color_space == JCS_YCbCr) { + cconvert->pub.color_convert = grayscale_convert; + /* For color->grayscale conversion, only the Y (0) component is needed */ + for (ci = 1; ci < cinfo->num_components; ci++) + cinfo->comp_info[ci].component_needed = FALSE; + } else + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); + break; + + case JCS_RGB: + cinfo->out_color_components = RGB_PIXELSIZE; + if (cinfo->jpeg_color_space == JCS_YCbCr) { + cconvert->pub.color_convert = ycc_rgb_convert; + build_ycc_rgb_table(cinfo); + } else if (cinfo->jpeg_color_space == JCS_GRAYSCALE) { + cconvert->pub.color_convert = gray_rgb_convert; + } else if (cinfo->jpeg_color_space == JCS_RGB && RGB_PIXELSIZE == 3) { + cconvert->pub.color_convert = null_convert; + } else + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); + break; + + case JCS_CMYK: + cinfo->out_color_components = 4; + if (cinfo->jpeg_color_space == JCS_YCCK) { + cconvert->pub.color_convert = ycck_cmyk_convert; + build_ycc_rgb_table(cinfo); + } else if (cinfo->jpeg_color_space == JCS_CMYK) { + cconvert->pub.color_convert = null_convert; + } else + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); + break; + + default: + /* Permit null conversion to same output space */ + if (cinfo->out_color_space == cinfo->jpeg_color_space) { + cinfo->out_color_components = cinfo->num_components; + cconvert->pub.color_convert = null_convert; + } else /* unsupported non-null conversion */ + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); + break; + } + + if (cinfo->quantize_colors) + cinfo->output_components = 1; /* single colormapped output component */ + else + cinfo->output_components = cinfo->out_color_components; +} diff --git a/dcmjpeg/libijg12/jdct12.h b/dcmjpeg/libijg12/jdct12.h new file mode 100644 index 00000000..0739983e --- /dev/null +++ b/dcmjpeg/libijg12/jdct12.h @@ -0,0 +1,176 @@ +/* + * jdct.h + * + * Copyright (C) 1994-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This include file contains common declarations for the forward and + * inverse DCT modules. These declarations are private to the DCT managers + * (jcdctmgr.c, jddctmgr.c) and the individual DCT algorithms. + * The individual DCT algorithms are kept in separate files to ease + * machine-dependent tuning (e.g., assembly coding). + */ + + +/* + * A forward DCT routine is given a pointer to a work area of type DCTELEM[]; + * the DCT is to be performed in-place in that buffer. Type DCTELEM is int + * for 8-bit samples, IJG_INT32 for 12-bit samples. (NOTE: Floating-point DCT + * implementations use an array of type FAST_FLOAT, instead.) + * The DCT inputs are expected to be signed (range +-CENTERJSAMPLE). + * The DCT outputs are returned scaled up by a factor of 8; they therefore + * have a range of +-8K for 8-bit data, +-128K for 12-bit data. This + * convention improves accuracy in integer implementations and saves some + * work in floating-point ones. + * Quantization of the output coefficients is done by jcdctmgr.c. + */ + +#if BITS_IN_JSAMPLE == 8 +typedef int DCTELEM; /* 16 or 32 bits is fine */ +#else +typedef IJG_INT32 DCTELEM; /* must have 32 bits */ +#endif + +typedef JMETHOD(void, forward_DCT_method_ptr, (DCTELEM * data)); +typedef JMETHOD(void, float_DCT_method_ptr, (FAST_FLOAT * data)); + + +/* + * An inverse DCT routine is given a pointer to the input JBLOCK and a pointer + * to an output sample array. The routine must dequantize the input data as + * well as perform the IDCT; for dequantization, it uses the multiplier table + * pointed to by compptr->dct_table. The output data is to be placed into the + * sample array starting at a specified column. (Any row offset needed will + * be applied to the array pointer before it is passed to the IDCT code.) + * Note that the number of samples emitted by the IDCT routine is + * DCT_scaled_size * DCT_scaled_size. + */ + +/* typedef inverse_DCT_method_ptr is declared in jpegint.h */ + +/* + * Each IDCT routine has its own ideas about the best dct_table element type. + */ + +typedef MULTIPLIER ISLOW_MULT_TYPE; /* short or int, whichever is faster */ +#if BITS_IN_JSAMPLE == 8 +typedef MULTIPLIER IFAST_MULT_TYPE; /* 16 bits is OK, use short if faster */ +#define IFAST_SCALE_BITS 2 /* fractional bits in scale factors */ +#else +typedef IJG_INT32 IFAST_MULT_TYPE; /* need 32 bits for scaled quantizers */ +#define IFAST_SCALE_BITS 13 /* fractional bits in scale factors */ +#endif +typedef FAST_FLOAT FLOAT_MULT_TYPE; /* preferred floating type */ + + +/* + * Each IDCT routine is responsible for range-limiting its results and + * converting them to unsigned form (0..MAXJSAMPLE). The raw outputs could + * be quite far out of range if the input data is corrupt, so a bulletproof + * range-limiting step is required. We use a mask-and-table-lookup method + * to do the combined operations quickly. See the comments with + * prepare_range_limit_table (in jdmaster.c) for more info. + */ + +#define IDCT_range_limit(cinfo) ((cinfo)->sample_range_limit + CENTERJSAMPLE) + +#define RANGE_MASK (MAXJSAMPLE * 4 + 3) /* 2 bits wider than legal samples */ + + +/* Short forms of external names for systems with brain-damaged linkers. */ + +#ifdef NEED_SHORT_EXTERNAL_NAMES +#define jpeg_fdct_islow jpeg12_fdct_islow +#define jpeg_fdct_ifast jpeg12_fdct_ifast +#define jpeg_fdct_float jpeg12_fdct_float +#define jpeg_idct_islow jpeg12_idct_islow +#define jpeg_idct_ifast jpeg12_idct_ifast +#define jpeg_idct_float jpeg12_idct_float +#define jpeg_idct_4x4 jpeg12_idct_4x4 +#define jpeg_idct_2x2 jpeg12_idct_2x2 +#define jpeg_idct_1x1 jpeg12_idct_1x1 +#endif /* NEED_SHORT_EXTERNAL_NAMES */ + +/* Extern declarations for the forward and inverse DCT routines. */ + +EXTERN(void) jpeg_fdct_islow JPP((DCTELEM * data)); +EXTERN(void) jpeg_fdct_ifast JPP((DCTELEM * data)); +EXTERN(void) jpeg_fdct_float JPP((FAST_FLOAT * data)); + +EXTERN(void) jpeg_idct_islow + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_ifast + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_float + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_4x4 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_2x2 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_1x1 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); + + +/* + * Macros for handling fixed-point arithmetic; these are used by many + * but not all of the DCT/IDCT modules. + * + * All values are expected to be of type IJG_INT32. + * Fractional constants are scaled left by CONST_BITS bits. + * CONST_BITS is defined within each module using these macros, + * and may differ from one module to the next. + */ + +#define ONE ((IJG_INT32) 1) +#define CONST_SCALE (ONE << CONST_BITS) + +/* Convert a positive real constant to an integer scaled by CONST_SCALE. + * Caution: some C compilers fail to reduce "FIX(constant)" at compile time, + * thus causing a lot of useless floating-point operations at run time. + */ + +#define FIX(x) ((IJG_INT32) ((x) * CONST_SCALE + 0.5)) + +/* Descale and correctly round an IJG_INT32 value that's scaled by N bits. + * We assume RIGHT_SHIFT rounds towards minus infinity, so adding + * the fudge factor is correct for either sign of X. + */ + +#define DESCALE(x,n) RIGHT_SHIFT((x) + (ONE << ((n)-1)), n) + +/* Multiply an IJG_INT32 variable by an IJG_INT32 constant to yield an IJG_INT32 result. + * This macro is used only when the two inputs will actually be no more than + * 16 bits wide, so that a 16x16->32 bit multiply can be used instead of a + * full 32x32 multiply. This provides a useful speedup on many machines. + * Unfortunately there is no way to specify a 16x16->32 multiply portably + * in C, but some C compilers will do the right thing if you provide the + * correct combination of casts. + */ + +#ifdef SHORTxSHORT_32 /* may work if 'int' is 32 bits */ +#define MULTIPLY16C16(var,const) (((INT16) (var)) * ((INT16) (const))) +#endif +#ifdef SHORTxLCONST_32 /* known to work with Microsoft C 6.0 */ +#define MULTIPLY16C16(var,const) (((INT16) (var)) * ((IJG_INT32) (const))) +#endif + +#ifndef MULTIPLY16C16 /* default definition */ +#define MULTIPLY16C16(var,const) ((var) * (const)) +#endif + +/* Same except both inputs are variables. */ + +#ifdef SHORTxSHORT_32 /* may work if 'int' is 32 bits */ +#define MULTIPLY16V16(var1,var2) (((INT16) (var1)) * ((INT16) (var2))) +#endif + +#ifndef MULTIPLY16V16 /* default definition */ +#define MULTIPLY16V16(var1,var2) ((var1) * (var2)) +#endif diff --git a/dcmjpeg/libijg12/jddctmgr.c b/dcmjpeg/libijg12/jddctmgr.c new file mode 100644 index 00000000..4b7cc6cf --- /dev/null +++ b/dcmjpeg/libijg12/jddctmgr.c @@ -0,0 +1,270 @@ +/* + * jddctmgr.c + * + * Copyright (C) 1994-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains the inverse-DCT management logic. + * This code selects a particular IDCT implementation to be used, + * and it performs related housekeeping chores. No code in this file + * is executed per IDCT step, only during output pass setup. + * + * Note that the IDCT routines are responsible for performing coefficient + * dequantization as well as the IDCT proper. This module sets up the + * dequantization multiplier table needed by the IDCT routine. + */ + +#define JPEG_INTERNALS +#include "jinclude12.h" +#include "jpeglib12.h" +#include "jlossy12.h" /* Private declarations for lossy subsystem */ +#include "jdct12.h" /* Private declarations for DCT subsystem */ + + +/* + * The decompressor input side (jdinput.c) saves away the appropriate + * quantization table for each component at the start of the first scan + * involving that component. (This is necessary in order to correctly + * decode files that reuse Q-table slots.) + * When we are ready to make an output pass, the saved Q-table is converted + * to a multiplier table that will actually be used by the IDCT routine. + * The multiplier table contents are IDCT-method-dependent. To support + * application changes in IDCT method between scans, we can remake the + * multiplier tables if necessary. + * In buffered-image mode, the first output pass may occur before any data + * has been seen for some components, and thus before their Q-tables have + * been saved away. To handle this case, multiplier tables are preset + * to zeroes; the result of the IDCT will be a neutral gray level. + */ + + +/* Private subobject for this module */ + +typedef struct { + /* This array contains the IDCT method code that each multiplier table + * is currently set up for, or -1 if it's not yet set up. + * The actual multiplier tables are pointed to by dct_table in the + * per-component comp_info structures. + */ + int cur_method[MAX_COMPONENTS]; +} idct_controller; + +typedef idct_controller * idct_ptr; + + +/* Allocated multiplier tables: big enough for any supported variant */ + +typedef union { + ISLOW_MULT_TYPE islow_array[DCTSIZE2]; +#ifdef DCT_IFAST_SUPPORTED + IFAST_MULT_TYPE ifast_array[DCTSIZE2]; +#endif +#ifdef DCT_FLOAT_SUPPORTED + FLOAT_MULT_TYPE float_array[DCTSIZE2]; +#endif +} multiplier_table; + + +/* The current scaled-IDCT routines require ISLOW-style multiplier tables, + * so be sure to compile that code if either ISLOW or SCALING is requested. + */ +#ifdef DCT_ISLOW_SUPPORTED +#define PROVIDE_ISLOW_TABLES +#else +#ifdef IDCT_SCALING_SUPPORTED +#define PROVIDE_ISLOW_TABLES +#endif +#endif + + +/* + * Prepare for an output pass. + * Here we select the proper IDCT routine for each component and build + * a matching multiplier table. + */ + +METHODDEF(void) +start_pass (j_decompress_ptr cinfo) +{ + j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec; + idct_ptr idct = (idct_ptr) lossyd->idct_private; + int ci, i; + jpeg_component_info *compptr; + int method = 0; + inverse_DCT_method_ptr method_ptr = NULL; + JQUANT_TBL * qtbl; + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + /* Select the proper IDCT routine for this component's scaling */ + switch (compptr->codec_data_unit) { +#ifdef IDCT_SCALING_SUPPORTED + case 1: + method_ptr = jpeg_idct_1x1; + method = JDCT_ISLOW; /* jidctred uses islow-style table */ + break; + case 2: + method_ptr = jpeg_idct_2x2; + method = JDCT_ISLOW; /* jidctred uses islow-style table */ + break; + case 4: + method_ptr = jpeg_idct_4x4; + method = JDCT_ISLOW; /* jidctred uses islow-style table */ + break; +#endif + case DCTSIZE: + switch (cinfo->dct_method) { +#ifdef DCT_ISLOW_SUPPORTED + case JDCT_ISLOW: + method_ptr = jpeg_idct_islow; + method = JDCT_ISLOW; + break; +#endif +#ifdef DCT_IFAST_SUPPORTED + case JDCT_IFAST: + method_ptr = jpeg_idct_ifast; + method = JDCT_IFAST; + break; +#endif +#ifdef DCT_FLOAT_SUPPORTED + case JDCT_FLOAT: + method_ptr = jpeg_idct_float; + method = JDCT_FLOAT; + break; +#endif + default: + ERREXIT(cinfo, JERR_NOT_COMPILED); + break; + } + break; + default: + ERREXIT1(cinfo, JERR_BAD_DCTSIZE, compptr->codec_data_unit); + break; + } + lossyd->inverse_DCT[ci] = method_ptr; + /* Create multiplier table from quant table. + * However, we can skip this if the component is uninteresting + * or if we already built the table. Also, if no quant table + * has yet been saved for the component, we leave the + * multiplier table all-zero; we'll be reading zeroes from the + * coefficient controller's buffer anyway. + */ + if (! compptr->component_needed || idct->cur_method[ci] == method) + continue; + qtbl = compptr->quant_table; + if (qtbl == NULL) /* happens if no data yet for component */ + continue; + idct->cur_method[ci] = method; + switch (method) { +#ifdef PROVIDE_ISLOW_TABLES + case JDCT_ISLOW: + { + /* For LL&M IDCT method, multipliers are equal to raw quantization + * coefficients, but are stored as ints to ensure access efficiency. + */ + ISLOW_MULT_TYPE * ismtbl = (ISLOW_MULT_TYPE *) compptr->dct_table; + for (i = 0; i < DCTSIZE2; i++) { + ismtbl[i] = (ISLOW_MULT_TYPE) qtbl->quantval[i]; + } + } + break; +#endif +#ifdef DCT_IFAST_SUPPORTED + case JDCT_IFAST: + { + /* For AA&N IDCT method, multipliers are equal to quantization + * coefficients scaled by scalefactor[row]*scalefactor[col], where + * scalefactor[0] = 1 + * scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7 + * For integer operation, the multiplier table is to be scaled by + * IFAST_SCALE_BITS. + */ + IFAST_MULT_TYPE * ifmtbl = (IFAST_MULT_TYPE *) compptr->dct_table; +#define CONST_BITS 14 + static const INT16 aanscales[DCTSIZE2] = { + /* precomputed values scaled up by 14 bits */ + 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520, + 22725, 31521, 29692, 26722, 22725, 17855, 12299, 6270, + 21407, 29692, 27969, 25172, 21407, 16819, 11585, 5906, + 19266, 26722, 25172, 22654, 19266, 15137, 10426, 5315, + 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520, + 12873, 17855, 16819, 15137, 12873, 10114, 6967, 3552, + 8867, 12299, 11585, 10426, 8867, 6967, 4799, 2446, + 4520, 6270, 5906, 5315, 4520, 3552, 2446, 1247 + }; + SHIFT_TEMPS + + for (i = 0; i < DCTSIZE2; i++) { + ifmtbl[i] = (IFAST_MULT_TYPE) + DESCALE(MULTIPLY16V16((IJG_INT32) qtbl->quantval[i], + (IJG_INT32) aanscales[i]), + CONST_BITS-IFAST_SCALE_BITS); + } + } + break; +#endif +#ifdef DCT_FLOAT_SUPPORTED + case JDCT_FLOAT: + { + /* For float AA&N IDCT method, multipliers are equal to quantization + * coefficients scaled by scalefactor[row]*scalefactor[col], where + * scalefactor[0] = 1 + * scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7 + */ + FLOAT_MULT_TYPE * fmtbl = (FLOAT_MULT_TYPE *) compptr->dct_table; + int row, col; + static const double aanscalefactor[DCTSIZE] = { + 1.0, 1.387039845, 1.306562965, 1.175875602, + 1.0, 0.785694958, 0.541196100, 0.275899379 + }; + + i = 0; + for (row = 0; row < DCTSIZE; row++) { + for (col = 0; col < DCTSIZE; col++) { + fmtbl[i] = (FLOAT_MULT_TYPE) + ((double) qtbl->quantval[i] * + aanscalefactor[row] * aanscalefactor[col]); + i++; + } + } + } + break; +#endif + default: + ERREXIT(cinfo, JERR_NOT_COMPILED); + break; + } + } +} + + +/* + * Initialize IDCT manager. + */ + +GLOBAL(void) +jinit_inverse_dct (j_decompress_ptr cinfo) +{ + j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec; + idct_ptr idct; + int ci; + jpeg_component_info *compptr; + + idct = (idct_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(idct_controller)); + lossyd->idct_private = (void *) idct; + lossyd->idct_start_pass = start_pass; + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + /* Allocate and pre-zero a multiplier table for each component */ + compptr->dct_table = + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(multiplier_table)); + MEMZERO(compptr->dct_table, SIZEOF(multiplier_table)); + /* Mark multiplier table not yet set up for any method */ + idct->cur_method[ci] = -1; + } +} diff --git a/dcmjpeg/libijg12/jddiffct.c b/dcmjpeg/libijg12/jddiffct.c new file mode 100644 index 00000000..cac77fbd --- /dev/null +++ b/dcmjpeg/libijg12/jddiffct.c @@ -0,0 +1,399 @@ +/* + * jddiffct.c + * + * Copyright (C) 1994-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains the [un]difference buffer controller for decompression. + * This controller is the top level of the lossless JPEG decompressor proper. + * The difference buffer lies between the entropy decoding and + * prediction/undifferencing steps. The undifference buffer lies between the + * prediction/undifferencing and scaling steps. + * + * In buffered-image mode, this controller is the interface between + * input-oriented processing and output-oriented processing. + */ + +#define JPEG_INTERNALS +#include "jinclude12.h" +#include "jpeglib12.h" +#include "jlossls12.h" + + +#ifdef D_LOSSLESS_SUPPORTED + +/* Private buffer controller object */ + +typedef struct { + /* These variables keep track of the current location of the input side. */ + /* cinfo->input_iMCU_row is also used for this. */ + JDIMENSION MCU_ctr; /* counts MCUs processed in current row */ + unsigned int restart_rows_to_go; /* MCU-rows left in this restart interval */ + unsigned int MCU_vert_offset; /* counts MCU rows within iMCU row */ + unsigned int MCU_rows_per_iMCU_row; /* number of such rows needed */ + + /* The output side's location is represented by cinfo->output_iMCU_row. */ + + JDIFFARRAY diff_buf[MAX_COMPONENTS]; /* iMCU row of differences */ + JDIFFARRAY undiff_buf[MAX_COMPONENTS]; /* iMCU row of undiff'd samples */ + +#ifdef D_MULTISCAN_FILES_SUPPORTED + /* In multi-pass modes, we need a virtual sample array for each component. */ + jvirt_sarray_ptr whole_image[MAX_COMPONENTS]; +#endif +} d_diff_controller; + +typedef d_diff_controller * d_diff_ptr; + +/* Forward declarations */ +METHODDEF(int) decompress_data + JPP((j_decompress_ptr cinfo, JSAMPIMAGE output_buf)); +#ifdef D_MULTISCAN_FILES_SUPPORTED +METHODDEF(int) output_data + JPP((j_decompress_ptr cinfo, JSAMPIMAGE output_buf)); +#endif + + +LOCAL(void) +start_iMCU_row (j_decompress_ptr cinfo) +/* Reset within-iMCU-row counters for a new row (input side) */ +{ + j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec; + d_diff_ptr diff = (d_diff_ptr) losslsd->diff_private; + + /* In an interleaved scan, an MCU row is the same as an iMCU row. + * In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows. + * But at the bottom of the image, process only what's left. + */ + if (cinfo->comps_in_scan > 1) { + diff->MCU_rows_per_iMCU_row = 1; + } else { + if (cinfo->input_iMCU_row < (cinfo->total_iMCU_rows-1)) + diff->MCU_rows_per_iMCU_row = (JDIMENSION)cinfo->cur_comp_info[0]->v_samp_factor; + else + diff->MCU_rows_per_iMCU_row = (JDIMENSION)cinfo->cur_comp_info[0]->last_row_height; + } + + diff->MCU_ctr = 0; + diff->MCU_vert_offset = 0; +} + + +/* + * Initialize for an input processing pass. + */ + +METHODDEF(void) +start_input_pass (j_decompress_ptr cinfo) +{ + j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec; + d_diff_ptr diff = (d_diff_ptr) losslsd->diff_private; + + /* Check that the restart interval is an integer multiple of the number + * of MCU in an MCU-row. + */ + if (cinfo->restart_interval % cinfo->MCUs_per_row != 0) + ERREXIT2(cinfo, JERR_BAD_RESTART, + (int)cinfo->restart_interval, (int)cinfo->MCUs_per_row); + + /* Initialize restart counter */ + diff->restart_rows_to_go = cinfo->restart_interval / cinfo->MCUs_per_row; + + cinfo->input_iMCU_row = 0; + start_iMCU_row(cinfo); +} + + +/* + * Check for a restart marker & resynchronize decoder, undifferencer. + * Returns FALSE if must suspend. + */ + +METHODDEF(boolean) +process_restart (j_decompress_ptr cinfo) +{ + j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec; + d_diff_ptr diff = (d_diff_ptr) losslsd->diff_private; + + if (! (*losslsd->entropy_process_restart) (cinfo)) + return FALSE; + + (*losslsd->predict_process_restart) (cinfo); + + /* Reset restart counter */ + diff->restart_rows_to_go = cinfo->restart_interval / cinfo->MCUs_per_row; + + return TRUE; +} + + +/* + * Initialize for an output processing pass. + */ + +METHODDEF(void) +start_output_pass (j_decompress_ptr cinfo) +{ + cinfo->output_iMCU_row = 0; +} + + +/* + * Decompress and return some data in the supplied buffer. + * Always attempts to emit one fully interleaved MCU row ("iMCU" row). + * Input and output must run in lockstep since we have only a one-MCU buffer. + * Return value is JPEG_ROW_COMPLETED, JPEG_SCAN_COMPLETED, or JPEG_SUSPENDED. + * + * NB: output_buf contains a plane for each component in image, + * which we index according to the component's SOF position. + */ + +METHODDEF(int) +decompress_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf) +{ + j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec; + d_diff_ptr diff = (d_diff_ptr) losslsd->diff_private; + JDIMENSION MCU_col_num; /* index of current MCU within row */ + JDIMENSION MCU_count; /* number of MCUs decoded */ + JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; + int comp, ci, row, prev_row; + unsigned int yoffset; + jpeg_component_info *compptr; + + /* Loop to process as much as one whole iMCU row */ + for (yoffset = diff->MCU_vert_offset; yoffset < diff->MCU_rows_per_iMCU_row; + yoffset++) { + + /* Process restart marker if needed; may have to suspend */ + if (cinfo->restart_interval) { + if (diff->restart_rows_to_go == 0) + if (! process_restart(cinfo)) + return JPEG_SUSPENDED; + } + + MCU_col_num = diff->MCU_ctr; + /* Try to fetch an MCU-row (or remaining portion of suspended MCU-row). */ + MCU_count = + (*losslsd->entropy_decode_mcus) (cinfo, + diff->diff_buf, yoffset, MCU_col_num, + cinfo->MCUs_per_row - MCU_col_num); + if (MCU_count != cinfo->MCUs_per_row - MCU_col_num) { + /* Suspension forced; update state counters and exit */ + diff->MCU_vert_offset = yoffset; + diff->MCU_ctr += MCU_count; + return JPEG_SUSPENDED; + } + + /* Account for restart interval (no-op if not using restarts) */ + diff->restart_rows_to_go--; + + /* Completed an MCU row, but perhaps not an iMCU row */ + diff->MCU_ctr = 0; + } + + /* + * Undifference and scale each scanline of the disassembled MCU-row + * separately. We do not process dummy samples at the end of a scanline + * or dummy rows at the end of the image. + */ + for (comp = 0; comp < cinfo->comps_in_scan; comp++) { + compptr = cinfo->cur_comp_info[comp]; + ci = compptr->component_index; + for (row = 0, prev_row = compptr->v_samp_factor - 1; + row < (cinfo->input_iMCU_row == last_iMCU_row ? + compptr->last_row_height : compptr->v_samp_factor); + prev_row = row, row++) { + (*losslsd->predict_undifference[ci]) (cinfo, ci, + diff->diff_buf[ci][row], + diff->undiff_buf[ci][prev_row], + diff->undiff_buf[ci][row], + compptr->width_in_data_units); + (*losslsd->scaler_scale) (cinfo, diff->undiff_buf[ci][row], + output_buf[ci][row], + compptr->width_in_data_units); + } + } + + /* Completed the iMCU row, advance counters for next one. + * + * NB: output_data will increment output_iMCU_row. + * This counter is not needed for the single-pass case + * or the input side of the multi-pass case. + */ + if (++(cinfo->input_iMCU_row) < cinfo->total_iMCU_rows) { + start_iMCU_row(cinfo); + return JPEG_ROW_COMPLETED; + } + /* Completed the scan */ + (*cinfo->inputctl->finish_input_pass) (cinfo); + return JPEG_SCAN_COMPLETED; +} + + +/* + * Dummy consume-input routine for single-pass operation. + */ + +METHODDEF(int) +dummy_consume_data (j_decompress_ptr cinfo) +{ + return JPEG_SUSPENDED; /* Always indicate nothing was done */ +} + + +#ifdef D_MULTISCAN_FILES_SUPPORTED + +/* + * Consume input data and store it in the full-image sample buffer. + * We read as much as one fully interleaved MCU row ("iMCU" row) per call, + * ie, v_samp_factor rows for each component in the scan. + * Return value is JPEG_ROW_COMPLETED, JPEG_SCAN_COMPLETED, or JPEG_SUSPENDED. + */ + +METHODDEF(int) +consume_data (j_decompress_ptr cinfo) +{ + j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec; + d_diff_ptr diff = (d_diff_ptr) losslsd->diff_private; + /* JDIMENSION MCU_col_num; */ /* index of current MCU within row */ + /* JDIMENSION MCU_count; */ /* number of MCUs decoded */ + /* JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; */ + int comp, ci /* , yoffset, row, prev_row */; + JSAMPARRAY buffer[MAX_COMPS_IN_SCAN]; + jpeg_component_info *compptr; + + /* Align the virtual buffers for the components used in this scan. */ + for (comp = 0; comp < cinfo->comps_in_scan; comp++) { + compptr = cinfo->cur_comp_info[comp]; + ci = compptr->component_index; + buffer[ci] = (*cinfo->mem->access_virt_sarray) + ((j_common_ptr) cinfo, diff->whole_image[ci], + cinfo->input_iMCU_row * (JDIMENSION)compptr->v_samp_factor, + (JDIMENSION) compptr->v_samp_factor, TRUE); + } + + return decompress_data(cinfo, buffer); +} + + +/* + * Output some data from the full-image buffer sample in the multi-pass case. + * Always attempts to emit one fully interleaved MCU row ("iMCU" row). + * Return value is JPEG_ROW_COMPLETED, JPEG_SCAN_COMPLETED, or JPEG_SUSPENDED. + * + * NB: output_buf contains a plane for each component in image. + */ + +METHODDEF(int) +output_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf) +{ + j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec; + d_diff_ptr diff = (d_diff_ptr) losslsd->diff_private; + JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; + int ci, samp_rows, row; + JSAMPARRAY buffer; + jpeg_component_info *compptr; + + /* Force some input to be done if we are getting ahead of the input. */ + while (cinfo->input_scan_number < cinfo->output_scan_number || + (cinfo->input_scan_number == cinfo->output_scan_number && + cinfo->input_iMCU_row <= cinfo->output_iMCU_row)) { + if ((*cinfo->inputctl->consume_input)(cinfo) == JPEG_SUSPENDED) + return JPEG_SUSPENDED; + } + + /* OK, output from the virtual arrays. */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + /* Align the virtual buffer for this component. */ + buffer = (*cinfo->mem->access_virt_sarray) + ((j_common_ptr) cinfo, diff->whole_image[ci], + cinfo->output_iMCU_row * (JDIMENSION)compptr->v_samp_factor, + (JDIMENSION) compptr->v_samp_factor, FALSE); + + if (cinfo->output_iMCU_row < last_iMCU_row) + samp_rows = compptr->v_samp_factor; + else { + /* NB: can't use last_row_height here; it is input-side-dependent! */ + samp_rows = (int)compptr->height_in_data_units % compptr->v_samp_factor; + if (samp_rows == 0) samp_rows = compptr->v_samp_factor; + } + + for (row = 0; row < samp_rows; row++) { + MEMCOPY(output_buf[ci][row], buffer[row], + compptr->width_in_data_units * SIZEOF(JSAMPLE)); + } + } + + if (++(cinfo->output_iMCU_row) < cinfo->total_iMCU_rows) + return JPEG_ROW_COMPLETED; + return JPEG_SCAN_COMPLETED; +} + +#endif /* D_MULTISCAN_FILES_SUPPORTED */ + + +/* + * Initialize difference buffer controller. + */ + +GLOBAL(void) +jinit_d_diff_controller (j_decompress_ptr cinfo, boolean need_full_buffer) +{ + j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec; + d_diff_ptr diff; + int ci; + jpeg_component_info *compptr; + + diff = (d_diff_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(d_diff_controller)); + losslsd->diff_private = (void *) diff; + losslsd->diff_start_input_pass = start_input_pass; + losslsd->pub.start_output_pass = start_output_pass; + + /* Create the [un]difference buffers. */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + diff->diff_buf[ci] = (*cinfo->mem->alloc_darray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + (JDIMENSION) jround_up((long) compptr->width_in_data_units, + (long) compptr->h_samp_factor), + (JDIMENSION) compptr->v_samp_factor); + diff->undiff_buf[ci] = (*cinfo->mem->alloc_darray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + (JDIMENSION) jround_up((long) compptr->width_in_data_units, + (long) compptr->h_samp_factor), + (JDIMENSION) compptr->v_samp_factor); + } + + if (need_full_buffer) { +#ifdef D_MULTISCAN_FILES_SUPPORTED + /* Allocate a full-image virtual array for each component. */ + int access_rows; + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + access_rows = compptr->v_samp_factor; + diff->whole_image[ci] = (*cinfo->mem->request_virt_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE, + (JDIMENSION) jround_up((long) compptr->width_in_data_units, + (long) compptr->h_samp_factor), + (JDIMENSION) jround_up((long) compptr->height_in_data_units, + (long) compptr->v_samp_factor), + (JDIMENSION) access_rows); + } + losslsd->pub.consume_data = consume_data; + losslsd->pub.decompress_data = output_data; +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } else { + losslsd->pub.consume_data = dummy_consume_data; + losslsd->pub.decompress_data = decompress_data; + diff->whole_image[0] = NULL; /* flag for no virtual arrays */ + } +} + +#endif /* D_LOSSLESS_SUPPORTED */ diff --git a/dcmjpeg/libijg12/jdhuff.c b/dcmjpeg/libijg12/jdhuff.c new file mode 100644 index 00000000..d2c98c81 --- /dev/null +++ b/dcmjpeg/libijg12/jdhuff.c @@ -0,0 +1,316 @@ +/* + * jdhuff.c + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains Huffman entropy decoding routines which are shared + * by the sequential, progressive and lossless decoders. + */ + +#define JPEG_INTERNALS +#include "jinclude12.h" +#include "jpeglib12.h" +#include "jlossy12.h" /* Private declarations for lossy codec */ +#include "jlossls12.h" /* Private declarations for lossless codec */ +#include "jdhuff12.h" /* Declarations shared with jd*huff.c */ + + +/* + * Compute the derived values for a Huffman table. + * This routine also performs some validation checks on the table. + */ + +GLOBAL(void) +jpeg_make_d_derived_tbl (j_decompress_ptr cinfo, boolean isDC, int tblno, + d_derived_tbl ** pdtbl) +{ + JHUFF_TBL *htbl; + d_derived_tbl *dtbl; + int p, i, l, si, numsymbols; + int lookbits, ctr; + char huffsize[257]; + unsigned int huffcode[257]; + unsigned int code; + + /* Note that huffsize[] and huffcode[] are filled in code-length order, + * paralleling the order of the symbols themselves in htbl->huffval[]. + */ + + /* Find the input Huffman table */ + if (tblno < 0 || tblno >= NUM_HUFF_TBLS) + ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tblno); + htbl = + isDC ? cinfo->dc_huff_tbl_ptrs[tblno] : cinfo->ac_huff_tbl_ptrs[tblno]; + if (htbl == NULL) + ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tblno); + + /* Allocate a workspace if we haven't already done so. */ + if (*pdtbl == NULL) + *pdtbl = (d_derived_tbl *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(d_derived_tbl)); + dtbl = *pdtbl; + dtbl->pub = htbl; /* fill in back link */ + + /* Figure C.1: make table of Huffman code length for each symbol */ + + p = 0; + for (l = 1; l <= 16; l++) { + i = (int) htbl->bits[l]; + if (i < 0 || p + i > 256) /* protect against table overrun */ + ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); + while (i--) + huffsize[p++] = (char) l; + } + huffsize[p] = 0; + numsymbols = p; + + /* Figure C.2: generate the codes themselves */ + /* We also validate that the counts represent a legal Huffman code tree. */ + + code = 0; + si = huffsize[0]; + p = 0; + while (huffsize[p]) { + while (((int) huffsize[p]) == si) { + huffcode[p++] = code; + code++; + } + /* code is now 1 more than the last code used for codelength si; but + * it must still fit in si bits, since no code is allowed to be all ones. + * BUG FIX: Comparison must be >, not >= + */ + if (((IJG_INT32) code) > (((IJG_INT32) 1) << si)) + ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); + code <<= 1; + si++; + } + + /* Figure F.15: generate decoding tables for bit-sequential decoding */ + + p = 0; + for (l = 1; l <= 16; l++) { + if (htbl->bits[l]) { + /* valoffset[l] = huffval[] index of 1st symbol of code length l, + * minus the minimum code of length l + */ + dtbl->valoffset[l] = (IJG_INT32) p - (IJG_INT32) huffcode[p]; + p += htbl->bits[l]; + dtbl->maxcode[l] = (IJG_INT32)huffcode[p-1]; /* maximum code of length l */ + } else { + dtbl->maxcode[l] = -1; /* -1 if no codes of this length */ + } + } + dtbl->maxcode[17] = 0xFFFFFL; /* ensures jpeg_huff_decode terminates */ + + /* Compute lookahead tables to speed up decoding. + * First we set all the table entries to 0, indicating "too long"; + * then we iterate through the Huffman codes that are short enough and + * fill in all the entries that correspond to bit sequences starting + * with that code. + */ + + MEMZERO(dtbl->look_nbits, SIZEOF(dtbl->look_nbits)); + + p = 0; + for (l = 1; l <= HUFF_LOOKAHEAD; l++) { + for (i = 1; i <= (int) htbl->bits[l]; i++, p++) { + /* l = current code's length, p = its index in huffcode[] & huffval[]. */ + /* Generate left-justified code followed by all possible bit sequences */ + lookbits = (int)huffcode[p] << (HUFF_LOOKAHEAD-l); + for (ctr = 1 << (HUFF_LOOKAHEAD-l); ctr > 0; ctr--) { + dtbl->look_nbits[lookbits] = l; + dtbl->look_sym[lookbits] = htbl->huffval[p]; + lookbits++; + } + } + } + + /* Validate symbols as being reasonable. + * For AC tables, we make no check, but accept all byte values 0..255. + * For DC tables, we require the symbols to be in range 0..16. + * (Tighter bounds could be applied depending on the data depth and mode, + * but this is sufficient to ensure safe decoding.) + */ + if (isDC) { + for (i = 0; i < numsymbols; i++) { + int sym = htbl->huffval[i]; + if (sym < 0 || sym > 16) + ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); + } + } +} + + +/* + * Out-of-line code for bit fetching. + * See jdhuff.h for info about usage. + * Note: current values of get_buffer and bits_left are passed as parameters, + * but are returned in the corresponding fields of the state struct. + * + * On most machines MIN_GET_BITS should be 25 to allow the full 32-bit width + * of get_buffer to be used. (On machines with wider words, an even larger + * buffer could be used.) However, on some machines 32-bit shifts are + * quite slow and take time proportional to the number of places shifted. + * (This is true with most PC compilers, for instance.) In this case it may + * be a win to set MIN_GET_BITS to the minimum value of 15. This reduces the + * average shift distance at the cost of more calls to jpeg_fill_bit_buffer. + */ + +#ifdef SLOW_SHIFT_32 +#define MIN_GET_BITS 15 /* minimum allowable value */ +#else +#define MIN_GET_BITS (BIT_BUF_SIZE-7) +#endif + + +GLOBAL(boolean) +jpeg_fill_bit_buffer (bitread_working_state * state, + register bit_buf_type get_buffer, register int bits_left, + int nbits) +/* Load up the bit buffer to a depth of at least nbits */ +{ + /* Copy heavily used state fields into locals (hopefully registers) */ + register const JOCTET * next_input_byte = state->next_input_byte; + register size_t bytes_in_buffer = state->bytes_in_buffer; + j_decompress_ptr cinfo = state->cinfo; + + /* Attempt to load at least MIN_GET_BITS bits into get_buffer. */ + /* (It is assumed that no request will be for more than that many bits.) */ + /* We fail to do so only if we hit a marker or are forced to suspend. */ + + if (cinfo->unread_marker == 0) { /* cannot advance past a marker */ + while (bits_left < MIN_GET_BITS) { + register int c; + + /* Attempt to read a byte */ + if (bytes_in_buffer == 0) { + if (! (*cinfo->src->fill_input_buffer) (cinfo)) + return FALSE; + next_input_byte = cinfo->src->next_input_byte; + bytes_in_buffer = cinfo->src->bytes_in_buffer; + } + bytes_in_buffer--; + c = GETJOCTET(*next_input_byte++); + + /* If it's 0xFF, check and discard stuffed zero byte */ + if (c == 0xFF) { + /* Loop here to discard any padding FF's on terminating marker, + * so that we can save a valid unread_marker value. NOTE: we will + * accept multiple FF's followed by a 0 as meaning a single FF data + * byte. This data pattern is not valid according to the standard. + */ + do { + if (bytes_in_buffer == 0) { + if (! (*cinfo->src->fill_input_buffer) (cinfo)) + return FALSE; + next_input_byte = cinfo->src->next_input_byte; + bytes_in_buffer = cinfo->src->bytes_in_buffer; + } + bytes_in_buffer--; + c = GETJOCTET(*next_input_byte++); + } while (c == 0xFF); + + if (c == 0) { + /* Found FF/00, which represents an FF data byte */ + c = 0xFF; + } else { + /* Oops, it's actually a marker indicating end of compressed data. + * Save the marker code for later use. + * Fine point: it might appear that we should save the marker into + * bitread working state, not straight into permanent state. But + * once we have hit a marker, we cannot need to suspend within the + * current MCU, because we will read no more bytes from the data + * source. So it is OK to update permanent state right away. + */ + cinfo->unread_marker = c; + /* See if we need to insert some fake zero bits. */ + goto no_more_bytes; + } + } + + /* OK, load c into get_buffer */ + get_buffer = (get_buffer << 8) | c; + bits_left += 8; + } /* end while */ + } else { + no_more_bytes: + /* We get here if we've read the marker that terminates the compressed + * data segment. There should be enough bits in the buffer register + * to satisfy the request; if so, no problem. + */ + if (nbits > bits_left) { + /* Uh-oh. Report corrupted data to user and stuff zeroes into + * the data stream, so that we can produce some kind of image. + * We use a nonvolatile flag to ensure that only one warning message + * appears per data segment. + */ + huffd_common_ptr huffd; + if (cinfo->process == JPROC_LOSSLESS) + huffd = (huffd_common_ptr) ((j_lossless_d_ptr) cinfo->codec)->entropy_private; + else + huffd = (huffd_common_ptr) ((j_lossy_d_ptr) cinfo->codec)->entropy_private; + if (! huffd->insufficient_data) { + WARNMS(cinfo, JWRN_HIT_MARKER); + huffd->insufficient_data = TRUE; + } + /* Fill the buffer with zero bits */ + get_buffer <<= MIN_GET_BITS - bits_left; + bits_left = MIN_GET_BITS; + } + } + + /* Unload the local registers */ + state->next_input_byte = next_input_byte; + state->bytes_in_buffer = bytes_in_buffer; + state->get_buffer = get_buffer; + state->bits_left = bits_left; + + return TRUE; +} + + +/* + * Out-of-line code for Huffman code decoding. + * See jdhuff.h for info about usage. + */ + +GLOBAL(int) +jpeg_huff_decode (bitread_working_state * state, + register bit_buf_type get_buffer, register int bits_left, + d_derived_tbl * htbl, int min_bits) +{ + register int l = min_bits; + register IJG_INT32 code; + + /* HUFF_DECODE has determined that the code is at least min_bits */ + /* bits long, so fetch that many bits in one swoop. */ + + CHECK_BIT_BUFFER(*state, l, return -1); + code = GET_BITS(l); + + /* Collect the rest of the Huffman code one bit at a time. */ + /* This is per Figure F.16 in the JPEG spec. */ + + while (code > htbl->maxcode[l]) { + code <<= 1; + CHECK_BIT_BUFFER(*state, 1, return -1); + code |= GET_BITS(1); + l++; + } + + /* Unload the local registers */ + state->get_buffer = get_buffer; + state->bits_left = bits_left; + + /* With garbage input we may reach the sentinel value l = 17. */ + + if (l > 16) { + WARNMS(state->cinfo, JWRN_HUFF_BAD_CODE); + return 0; /* fake a zero as the safest result */ + } + + return htbl->pub->huffval[ (int) (code + htbl->valoffset[l]) ]; +} diff --git a/dcmjpeg/libijg12/jdhuff12.h b/dcmjpeg/libijg12/jdhuff12.h new file mode 100644 index 00000000..b84c0921 --- /dev/null +++ b/dcmjpeg/libijg12/jdhuff12.h @@ -0,0 +1,229 @@ +/* + * jdhuff.h + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains declarations for Huffman entropy decoding routines + * that are shared between the sequential decoder (jdhuff.c), the + * progressive decoder (jdphuff.c) and the lossless decoder (jdlhuff.c). + * No other modules need to see these. + */ + +/* Short forms of external names for systems with brain-damaged linkers. */ + +#ifdef NEED_SHORT_EXTERNAL_NAMES +#define jpeg_make_d_derived_tbl jpeg12_make_d_derived_tbl +#define jpeg_fill_bit_buffer jpeg12_fill_bit_buffer +#define jpeg_huff_decode jpeg12_huff_decode +#endif /* NEED_SHORT_EXTERNAL_NAMES */ + + +/* Derived data constructed for each Huffman table */ + +#define HUFF_LOOKAHEAD 8 /* # of bits of lookahead */ + +typedef struct { + /* Basic tables: (element [0] of each array is unused) */ + IJG_INT32 maxcode[18]; /* largest code of length k (-1 if none) */ + /* (maxcode[17] is a sentinel to ensure jpeg_huff_decode terminates) */ + IJG_INT32 valoffset[17]; /* huffval[] offset for codes of length k */ + /* valoffset[k] = huffval[] index of 1st symbol of code length k, less + * the smallest code of length k; so given a code of length k, the + * corresponding symbol is huffval[code + valoffset[k]] + */ + + /* Link to public Huffman table (needed only in jpeg_huff_decode) */ + JHUFF_TBL *pub; + + /* Lookahead tables: indexed by the next HUFF_LOOKAHEAD bits of + * the input data stream. If the next Huffman code is no more + * than HUFF_LOOKAHEAD bits long, we can obtain its length and + * the corresponding symbol directly from these tables. + */ + int look_nbits[1< 32 bits on your machine, and shifting/masking longs is + * reasonably fast, making bit_buf_type be long and setting BIT_BUF_SIZE + * appropriately should be a win. Unfortunately we can't define the size + * with something like #define BIT_BUF_SIZE (sizeof(bit_buf_type)*8) + * because not all machines measure sizeof in 8-bit bytes. + */ + +typedef struct { /* Bitreading state saved across MCUs */ + bit_buf_type get_buffer; /* current bit-extraction buffer */ + int bits_left; /* # of unused bits in it */ +} bitread_perm_state; + +typedef struct { /* Bitreading working state within an MCU */ + /* Current data source location */ + /* We need a copy, rather than munging the original, in case of suspension */ + const JOCTET * next_input_byte; /* => next byte to read from source */ + size_t bytes_in_buffer; /* # of bytes remaining in source buffer */ + /* Bit input buffer --- note these values are kept in register variables, + * not in this struct, inside the inner loops. + */ + bit_buf_type get_buffer; /* current bit-extraction buffer */ + int bits_left; /* # of unused bits in it */ + /* Pointer needed by jpeg_fill_bit_buffer. */ + j_decompress_ptr cinfo; /* back link to decompress master record */ +} bitread_working_state; + +/* Macros to declare and load/save bitread local variables. */ +#define BITREAD_STATE_VARS \ + register bit_buf_type get_buffer; \ + register int bits_left; \ + bitread_working_state br_state + +#define BITREAD_LOAD_STATE(cinfop,permstate) \ + br_state.cinfo = cinfop; \ + br_state.next_input_byte = cinfop->src->next_input_byte; \ + br_state.bytes_in_buffer = cinfop->src->bytes_in_buffer; \ + get_buffer = permstate.get_buffer; \ + bits_left = permstate.bits_left; + +#define BITREAD_SAVE_STATE(cinfop,permstate) \ + cinfop->src->next_input_byte = br_state.next_input_byte; \ + cinfop->src->bytes_in_buffer = br_state.bytes_in_buffer; \ + permstate.get_buffer = get_buffer; \ + permstate.bits_left = bits_left + +/* + * These macros provide the in-line portion of bit fetching. + * Use CHECK_BIT_BUFFER to ensure there are N bits in get_buffer + * before using GET_BITS, PEEK_BITS, or DROP_BITS. + * The variables get_buffer and bits_left are assumed to be locals, + * but the state struct might not be (jpeg_huff_decode needs this). + * CHECK_BIT_BUFFER(state,n,action); + * Ensure there are N bits in get_buffer; if suspend, take action. + * val = GET_BITS(n); + * Fetch next N bits. + * val = PEEK_BITS(n); + * Fetch next N bits without removing them from the buffer. + * DROP_BITS(n); + * Discard next N bits. + * The value N should be a simple variable, not an expression, because it + * is evaluated multiple times. + */ + +#define CHECK_BIT_BUFFER(state,nbits,action) \ + { if (bits_left < (nbits)) { \ + if (! jpeg_fill_bit_buffer(&(state),get_buffer,bits_left,nbits)) \ + { action; } \ + get_buffer = (state).get_buffer; bits_left = (state).bits_left; } } + +#define GET_BITS(nbits) \ + (((int) (get_buffer >> (bits_left -= (nbits)))) & ((1<<(nbits))-1)) + +#define PEEK_BITS(nbits) \ + (((int) (get_buffer >> (bits_left - (nbits)))) & ((1<<(nbits))-1)) + +#define DROP_BITS(nbits) \ + (bits_left -= (nbits)) + +/* Load up the bit buffer to a depth of at least nbits */ +EXTERN(boolean) jpeg_fill_bit_buffer + JPP((bitread_working_state * state, register bit_buf_type get_buffer, + register int bits_left, int nbits)); + + +/* + * Code for extracting next Huffman-coded symbol from input bit stream. + * Again, this is time-critical and we make the main paths be macros. + * + * We use a lookahead table to process codes of up to HUFF_LOOKAHEAD bits + * without looping. Usually, more than 95% of the Huffman codes will be 8 + * or fewer bits long. The few overlength codes are handled with a loop, + * which need not be inline code. + * + * Notes about the HUFF_DECODE macro: + * 1. Near the end of the data segment, we may fail to get enough bits + * for a lookahead. In that case, we do it the hard way. + * 2. If the lookahead table contains no entry, the next code must be + * more than HUFF_LOOKAHEAD bits long. + * 3. jpeg_huff_decode returns -1 if forced to suspend. + */ + +#define HUFF_DECODE(result,state,htbl,failaction,slowlabel) \ +{ register int nb, look; \ + if (bits_left < HUFF_LOOKAHEAD) { \ + if (! jpeg_fill_bit_buffer(&state,get_buffer,bits_left, 0)) {failaction;} \ + get_buffer = state.get_buffer; bits_left = state.bits_left; \ + if (bits_left < HUFF_LOOKAHEAD) { \ + nb = 1; goto slowlabel; \ + } \ + } \ + look = PEEK_BITS(HUFF_LOOKAHEAD); \ + if ((nb = htbl->look_nbits[look]) != 0) { \ + DROP_BITS(nb); \ + result = htbl->look_sym[look]; \ + } else { \ + nb = HUFF_LOOKAHEAD+1; \ +slowlabel: \ + if ((result=jpeg_huff_decode(&state,get_buffer,bits_left,htbl,nb)) < 0) \ + { failaction; } \ + get_buffer = state.get_buffer; bits_left = state.bits_left; \ + } \ +} + +/* Out-of-line case for Huffman code fetching */ +EXTERN(int) jpeg_huff_decode + JPP((bitread_working_state * state, register bit_buf_type get_buffer, + register int bits_left, d_derived_tbl * htbl, int min_bits)); + + +/* Common fields between sequential, progressive and lossless Huffman entropy + * decoder master structs. + */ + +#define huffd_common_fields \ + boolean insufficient_data; /* set TRUE after emmitting warning */ \ + /* These fields are loaded into local variables at start of each MCU. \ + * In case of suspension, we exit WITHOUT updating them. \ + */ \ + bitread_perm_state bitstate /* Bit buffer at start of MCU */ + +/* Routines that are to be used by any or all of the entropy decoders are + * declared to receive a pointer to this structure. There are no actual + * instances of huffd_common_struct, only of shuff_entropy_decoder, + * phuff_entropy_decoder and lhuff_entropy_decoder. + */ +struct huffd_common_struct { + huffd_common_fields; /* Fields common to all decoder struct types */ + /* Additional fields follow in an actual shuff_entropy_decoder, + * phuff_entropy_decoder or lhuff_entropy_decoder struct. All four structs + * must agree on these initial fields! (This would be a lot cleaner in C++.) + */ +}; + +typedef struct huffd_common_struct * huffd_common_ptr; diff --git a/dcmjpeg/libijg12/jdinput.c b/dcmjpeg/libijg12/jdinput.c new file mode 100644 index 00000000..02aab71c --- /dev/null +++ b/dcmjpeg/libijg12/jdinput.c @@ -0,0 +1,347 @@ +/* + * jdinput.c + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains input control logic for the JPEG decompressor. + * These routines are concerned with controlling the decompressor's input + * processing (marker reading and coefficient/difference decoding). + * The actual input reading is done in jdmarker.c, jdhuff.c, jdphuff.c, + * and jdlhuff.c. + */ + +#define JPEG_INTERNALS +#include "jinclude12.h" +#include "jpeglib12.h" + + +/* Private state */ + +typedef struct { + struct jpeg_input_controller pub; /* public fields */ + + boolean inheaders; /* TRUE until first SOS is reached */ +} my_input_controller; + +typedef my_input_controller * my_inputctl_ptr; + + +/* Forward declarations */ +METHODDEF(int) consume_markers JPP((j_decompress_ptr cinfo)); + + +/* + * Routines to calculate various quantities related to the size of the image. + */ + +LOCAL(void) +initial_setup (j_decompress_ptr cinfo) +/* Called once, when first SOS marker is reached */ +{ + int ci; + jpeg_component_info *compptr; + + /* Make sure image isn't bigger than I can handle */ + if ((long) cinfo->image_height > (long) JPEG_MAX_DIMENSION || + (long) cinfo->image_width > (long) JPEG_MAX_DIMENSION) + ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, (unsigned int) JPEG_MAX_DIMENSION); + + if (cinfo->process == JPROC_LOSSLESS) { + /* If precision > compiled-in value, we must downscale */ + if (cinfo->data_precision > BITS_IN_JSAMPLE) + WARNMS2(cinfo, JWRN_MUST_DOWNSCALE, + cinfo->data_precision, BITS_IN_JSAMPLE); + } + else { /* Lossy processes */ + /* For now, precision must match compiled-in value... */ + if (cinfo->data_precision != BITS_IN_JSAMPLE) + ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); + } + + /* Check that number of components won't exceed internal array sizes */ + if (cinfo->num_components > MAX_COMPONENTS) + ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components, + MAX_COMPONENTS); + + /* Compute maximum sampling factors; check factor validity */ + cinfo->max_h_samp_factor = 1; + cinfo->max_v_samp_factor = 1; + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + if (compptr->h_samp_factor<=0 || compptr->h_samp_factor>MAX_SAMP_FACTOR || + compptr->v_samp_factor<=0 || compptr->v_samp_factor>MAX_SAMP_FACTOR) + ERREXIT(cinfo, JERR_BAD_SAMPLING); + cinfo->max_h_samp_factor = MAX(cinfo->max_h_samp_factor, + compptr->h_samp_factor); + cinfo->max_v_samp_factor = MAX(cinfo->max_v_samp_factor, + compptr->v_samp_factor); + } + + /* We initialize codec_data_unit and min_codec_data_unit to data_unit. + * In the full decompressor, this will be overridden by jdmaster.c; + * but in the transcoder, jdmaster.c is not used, so we must do it here. + */ + cinfo->min_codec_data_unit = cinfo->data_unit; + + /* Compute dimensions of components */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + compptr->codec_data_unit = cinfo->data_unit; + /* Size in data units */ + compptr->width_in_data_units = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor, + (long) (cinfo->max_h_samp_factor * cinfo->data_unit)); + compptr->height_in_data_units = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor, + (long) (cinfo->max_v_samp_factor * cinfo->data_unit)); + /* downsampled_width and downsampled_height will also be overridden by + * jdmaster.c if we are doing full decompression. The transcoder library + * doesn't use these values, but the calling application might. + */ + /* Size in samples */ + compptr->downsampled_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor, + (long) cinfo->max_h_samp_factor); + compptr->downsampled_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor, + (long) cinfo->max_v_samp_factor); + /* Mark component needed, until color conversion says otherwise */ + compptr->component_needed = TRUE; + /* Mark no quantization table yet saved for component */ + compptr->quant_table = NULL; + } + + /* Compute number of fully interleaved MCU rows. */ + cinfo->total_iMCU_rows = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height, + (long) (cinfo->max_v_samp_factor*cinfo->data_unit)); + + /* Decide whether file contains multiple scans */ + if (cinfo->comps_in_scan < cinfo->num_components || + cinfo->process == JPROC_PROGRESSIVE) + cinfo->inputctl->has_multiple_scans = TRUE; + else + cinfo->inputctl->has_multiple_scans = FALSE; +} + + +LOCAL(void) +per_scan_setup (j_decompress_ptr cinfo) +/* Do computations that are needed before processing a JPEG scan */ +/* cinfo->comps_in_scan and cinfo->cur_comp_info[] were set from SOS marker */ +{ + int ci, mcublks, tmp; + jpeg_component_info *compptr; + + if (cinfo->comps_in_scan == 1) { + + /* Noninterleaved (single-component) scan */ + compptr = cinfo->cur_comp_info[0]; + + /* Overall image size in MCUs */ + cinfo->MCUs_per_row = compptr->width_in_data_units; + cinfo->MCU_rows_in_scan = compptr->height_in_data_units; + + /* For noninterleaved scan, always one data unit per MCU */ + compptr->MCU_width = 1; + compptr->MCU_height = 1; + compptr->MCU_data_units = 1; + compptr->MCU_sample_width = compptr->codec_data_unit; + compptr->last_col_width = 1; + /* For noninterleaved scans, it is convenient to define last_row_height + * as the number of data unit rows present in the last iMCU row. + */ + tmp = (int)compptr->height_in_data_units % compptr->v_samp_factor; + if (tmp == 0) tmp = compptr->v_samp_factor; + compptr->last_row_height = tmp; + + /* Prepare array describing MCU composition */ + cinfo->data_units_in_MCU = 1; + cinfo->MCU_membership[0] = 0; + + } else { + + /* Interleaved (multi-component) scan */ + if (cinfo->comps_in_scan <= 0 || cinfo->comps_in_scan > MAX_COMPS_IN_SCAN) + ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->comps_in_scan, + MAX_COMPS_IN_SCAN); + + /* Overall image size in MCUs */ + cinfo->MCUs_per_row = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width, + (long) (cinfo->max_h_samp_factor*cinfo->data_unit)); + cinfo->MCU_rows_in_scan = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height, + (long) (cinfo->max_v_samp_factor*cinfo->data_unit)); + + cinfo->data_units_in_MCU = 0; + + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + /* Sampling factors give # of data units of component in each MCU */ + compptr->MCU_width = compptr->h_samp_factor; + compptr->MCU_height = compptr->v_samp_factor; + compptr->MCU_data_units = compptr->MCU_width * compptr->MCU_height; + compptr->MCU_sample_width = compptr->MCU_width * compptr->codec_data_unit; + /* Figure number of non-dummy data units in last MCU column & row */ + tmp = (int)compptr->width_in_data_units % compptr->MCU_width; + if (tmp == 0) tmp = compptr->MCU_width; + compptr->last_col_width = tmp; + tmp = (int)compptr->height_in_data_units % compptr->MCU_height; + if (tmp == 0) tmp = compptr->MCU_height; + compptr->last_row_height = tmp; + /* Prepare array describing MCU composition */ + mcublks = compptr->MCU_data_units; + if (cinfo->data_units_in_MCU + mcublks > D_MAX_DATA_UNITS_IN_MCU) + ERREXIT(cinfo, JERR_BAD_MCU_SIZE); + while (mcublks-- > 0) { + cinfo->MCU_membership[cinfo->data_units_in_MCU++] = ci; + } + } + + } +} + + +/* + * Initialize the input modules to read a scan of compressed data. + * The first call to this is done by jdmaster.c after initializing + * the entire decompressor (during jpeg_start_decompress). + * Subsequent calls come from consume_markers, below. + */ + +METHODDEF(void) +start_input_pass (j_decompress_ptr cinfo) +{ + per_scan_setup(cinfo); + (*cinfo->codec->start_input_pass) (cinfo); + cinfo->inputctl->consume_input = cinfo->codec->consume_data; +} + + +/* + * Finish up after inputting a compressed-data scan. + * This is called by the coefficient controller after it's read all + * the expected data of the scan. + */ + +METHODDEF(void) +finish_input_pass (j_decompress_ptr cinfo) +{ + cinfo->inputctl->consume_input = consume_markers; +} + + +/* + * Read JPEG markers before, between, or after compressed-data scans. + * Change state as necessary when a new scan is reached. + * Return value is JPEG_SUSPENDED, JPEG_REACHED_SOS, or JPEG_REACHED_EOI. + * + * The consume_input method pointer points either here or to the + * coefficient controller's consume_data routine, depending on whether + * we are reading a compressed data segment or inter-segment markers. + */ + +METHODDEF(int) +consume_markers (j_decompress_ptr cinfo) +{ + my_inputctl_ptr inputctl = (my_inputctl_ptr) cinfo->inputctl; + int val; + + if (inputctl->pub.eoi_reached) /* After hitting EOI, read no further */ + return JPEG_REACHED_EOI; + + val = (*cinfo->marker->read_markers) (cinfo); + + switch (val) { + case JPEG_REACHED_SOS: /* Found SOS */ + if (inputctl->inheaders) { /* 1st SOS */ + initial_setup(cinfo); + /* + * Initialize the decompression codec. We need to do this here so that + * any codec-specific fields and function pointers are available to + * the rest of the library. + */ + jinit_d_codec(cinfo); + inputctl->inheaders = FALSE; + /* Note: start_input_pass must be called by jdmaster.c + * before any more input can be consumed. jdapimin.c is + * responsible for enforcing this sequencing. + */ + } else { /* 2nd or later SOS marker */ + if (! inputctl->pub.has_multiple_scans) + ERREXIT(cinfo, JERR_EOI_EXPECTED); /* Oops, I wasn't expecting this! */ + start_input_pass(cinfo); + } + break; + case JPEG_REACHED_EOI: /* Found EOI */ + inputctl->pub.eoi_reached = TRUE; + if (inputctl->inheaders) { /* Tables-only datastream, apparently */ + if (cinfo->marker->saw_SOF) + ERREXIT(cinfo, JERR_SOF_NO_SOS); + } else { + /* Prevent infinite loop in coef ctlr's decompress_data routine + * if user set output_scan_number larger than number of scans. + */ + if (cinfo->output_scan_number > cinfo->input_scan_number) + cinfo->output_scan_number = cinfo->input_scan_number; + } + break; + case JPEG_SUSPENDED: + break; + } + + return val; +} + + +/* + * Reset state to begin a fresh datastream. + */ + +METHODDEF(void) +reset_input_controller (j_decompress_ptr cinfo) +{ + my_inputctl_ptr inputctl = (my_inputctl_ptr) cinfo->inputctl; + + inputctl->pub.consume_input = consume_markers; + inputctl->pub.has_multiple_scans = FALSE; /* "unknown" would be better */ + inputctl->pub.eoi_reached = FALSE; + inputctl->inheaders = TRUE; + /* Reset other modules */ + (*cinfo->err->reset_error_mgr) ((j_common_ptr) cinfo); + (*cinfo->marker->reset_marker_reader) (cinfo); + /* Reset progression state -- would be cleaner if entropy decoder did this */ + cinfo->coef_bits = NULL; +} + + +/* + * Initialize the input controller module. + * This is called only once, when the decompression object is created. + */ + +GLOBAL(void) +jinit_input_controller (j_decompress_ptr cinfo) +{ + my_inputctl_ptr inputctl; + + /* Create subobject in permanent pool */ + inputctl = (my_inputctl_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, + SIZEOF(my_input_controller)); + cinfo->inputctl = (struct jpeg_input_controller *) inputctl; + /* Initialize method pointers */ + inputctl->pub.consume_input = consume_markers; + inputctl->pub.reset_input_controller = reset_input_controller; + inputctl->pub.start_input_pass = start_input_pass; + inputctl->pub.finish_input_pass = finish_input_pass; + /* Initialize state: can't use reset_input_controller since we don't + * want to try to reset other modules yet. + */ + inputctl->pub.has_multiple_scans = FALSE; /* "unknown" would be better */ + inputctl->pub.eoi_reached = FALSE; + inputctl->inheaders = TRUE; +} diff --git a/dcmjpeg/libijg12/jdlhuff.c b/dcmjpeg/libijg12/jdlhuff.c new file mode 100644 index 00000000..0480878e --- /dev/null +++ b/dcmjpeg/libijg12/jdlhuff.c @@ -0,0 +1,291 @@ +/* + * jdlhuff.c + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains Huffman entropy decoding routines for lossless JPEG. + * + * Much of the complexity here has to do with supporting input suspension. + * If the data source module demands suspension, we want to be able to back + * up to the start of the current MCU. To do this, we copy state variables + * into local working storage, and update them back to the permanent + * storage only upon successful completion of an MCU. + */ + +#define JPEG_INTERNALS +#include "jinclude12.h" +#include "jpeglib12.h" +#include "jlossls12.h" /* Private declarations for lossless codec */ +#include "jdhuff12.h" /* Declarations shared with jd*huff.c */ + + +#ifdef D_LOSSLESS_SUPPORTED + +typedef struct { + int ci, yoffset, MCU_width; +} lhd_output_ptr_info; + +/* + * Private entropy decoder object for lossless Huffman decoding. + */ + +typedef struct { + huffd_common_fields; /* Fields shared with other entropy decoders */ + + /* Pointers to derived tables (these workspaces have image lifespan) */ + d_derived_tbl * derived_tbls[NUM_HUFF_TBLS]; + + /* Precalculated info set up by start_pass for use in decode_mcus: */ + + /* Pointers to derived tables to be used for each data unit within an MCU */ + d_derived_tbl * cur_tbls[D_MAX_DATA_UNITS_IN_MCU]; + + /* Pointers to the proper output difference row for each group of data units + * within an MCU. For each component, there are Vi groups of Hi data units. + */ + JDIFFROW output_ptr[D_MAX_DATA_UNITS_IN_MCU]; + + /* Number of output pointers in use for the current MCU. This is the sum + * of all Vi in the MCU. + */ + int num_output_ptrs; + + /* Information used for positioning the output pointers within the output + * difference rows. + */ + lhd_output_ptr_info output_ptr_info[D_MAX_DATA_UNITS_IN_MCU]; + + /* Index of the proper output pointer for each data unit within an MCU */ + int output_ptr_index[D_MAX_DATA_UNITS_IN_MCU]; + +} lhuff_entropy_decoder; + +typedef lhuff_entropy_decoder * lhuff_entropy_ptr; + + +/* + * Initialize for a Huffman-compressed scan. + */ + +METHODDEF(void) +start_pass_lhuff_decoder (j_decompress_ptr cinfo) +{ + j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec; + lhuff_entropy_ptr entropy = (lhuff_entropy_ptr) losslsd->entropy_private; + int ci, dctbl, sampn, ptrn, yoffset, xoffset; + jpeg_component_info * compptr; + + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + dctbl = compptr->dc_tbl_no; + /* Make sure requested tables are present */ + if (dctbl < 0 || dctbl >= NUM_HUFF_TBLS || + cinfo->dc_huff_tbl_ptrs[dctbl] == NULL) + ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, dctbl); + /* Compute derived values for Huffman tables */ + /* We may do this more than once for a table, but it's not expensive */ + jpeg_make_d_derived_tbl(cinfo, TRUE, dctbl, + & entropy->derived_tbls[dctbl]); + } + + /* Precalculate decoding info for each sample in an MCU of this scan */ + for (sampn = 0, ptrn = 0; sampn < cinfo->data_units_in_MCU;) { + compptr = cinfo->cur_comp_info[cinfo->MCU_membership[sampn]]; + ci = compptr->component_index; + for (yoffset = 0; yoffset < compptr->MCU_height; yoffset++, ptrn++) { + /* Precalculate the setup info for each output pointer */ + entropy->output_ptr_info[ptrn].ci = ci; + entropy->output_ptr_info[ptrn].yoffset = yoffset; + entropy->output_ptr_info[ptrn].MCU_width = compptr->MCU_width; + for (xoffset = 0; xoffset < compptr->MCU_width; xoffset++, sampn++) { + /* Precalculate the output pointer index for each sample */ + entropy->output_ptr_index[sampn] = ptrn; + /* Precalculate which table to use for each sample */ + entropy->cur_tbls[sampn] = entropy->derived_tbls[compptr->dc_tbl_no]; + } + } + } + entropy->num_output_ptrs = ptrn; + + /* Initialize bitread state variables */ + entropy->bitstate.bits_left = 0; + entropy->bitstate.get_buffer = 0; /* unnecessary, but keeps Purify quiet */ + entropy->insufficient_data = FALSE; +} + + +/* + * Figure F.12: extend sign bit. + * On some machines, a shift and add will be faster than a table lookup. + */ + +#ifdef AVOID_TABLES + +#define HUFF_EXTEND(x,s) ((x) < (1<<((s)-1)) ? (x) + (((-1)<<(s)) + 1) : (x)) + +#else + +#define HUFF_EXTEND(x,s) ((x) < extend_test[s] ? (x) + extend_offset[s] : (x)) + +static const int extend_test[16] = /* entry n is 2**(n-1) */ + { 0, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080, + 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000 }; + +static const int extend_offset[16] = /* entry n is (-1 << n) + 1 */ + { 0, ((-1)<<1) + 1, ((-1)<<2) + 1, ((-1)<<3) + 1, ((-1)<<4) + 1, + ((-1)<<5) + 1, ((-1)<<6) + 1, ((-1)<<7) + 1, ((-1)<<8) + 1, + ((-1)<<9) + 1, ((-1)<<10) + 1, ((-1)<<11) + 1, ((-1)<<12) + 1, + ((-1)<<13) + 1, ((-1)<<14) + 1, ((-1)<<15) + 1 }; + +#endif /* AVOID_TABLES */ + + +/* + * Check for a restart marker & resynchronize decoder. + * Returns FALSE if must suspend. + */ + +METHODDEF(boolean) +process_restart (j_decompress_ptr cinfo) +{ + j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec; + lhuff_entropy_ptr entropy = (lhuff_entropy_ptr) losslsd->entropy_private; + /* int ci; */ + + /* Throw away any unused bits remaining in bit buffer; */ + /* include any full bytes in next_marker's count of discarded bytes */ + cinfo->marker->discarded_bytes += (unsigned int)entropy->bitstate.bits_left / 8; + entropy->bitstate.bits_left = 0; + + /* Advance past the RSTn marker */ + if (! (*cinfo->marker->read_restart_marker) (cinfo)) + return FALSE; + + /* Reset out-of-data flag, unless read_restart_marker left us smack up + * against a marker. In that case we will end up treating the next data + * segment as empty, and we can avoid producing bogus output pixels by + * leaving the flag set. + */ + if (cinfo->unread_marker == 0) + entropy->insufficient_data = FALSE; + + return TRUE; +} + + +/* + * Decode and return nMCU's worth of Huffman-compressed differences. + * Each MCU is also disassembled and placed accordingly in diff_buf. + * + * MCU_col_num specifies the column of the first MCU being requested within + * the MCU-row. This tells us where to position the output row pointers in + * diff_buf. + * + * Returns the number of MCUs decoded. This may be less than nMCU if data + * source requested suspension. In that case no changes have been made to + * permanent state. (Exception: some output differences may already have + * been assigned. This is harmless for this module, since we'll just + * re-assign them on the next call.) + */ + +METHODDEF(JDIMENSION) +decode_mcus (j_decompress_ptr cinfo, JDIFFIMAGE diff_buf, + JDIMENSION MCU_row_num, JDIMENSION MCU_col_num, JDIMENSION nMCU) +{ + j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec; + lhuff_entropy_ptr entropy = (lhuff_entropy_ptr) losslsd->entropy_private; + unsigned int mcu_num; + int sampn, ci, yoffset, MCU_width, ptrn; + BITREAD_STATE_VARS; + + /* Set output pointer locations based on MCU_col_num */ + for (ptrn = 0; ptrn < entropy->num_output_ptrs; ptrn++) { + ci = entropy->output_ptr_info[ptrn].ci; + yoffset = entropy->output_ptr_info[ptrn].yoffset; + MCU_width = entropy->output_ptr_info[ptrn].MCU_width; + entropy->output_ptr[ptrn] = + diff_buf[ci][MCU_row_num + (JDIMENSION)yoffset] + MCU_col_num * (JDIMENSION)MCU_width; + } + + /* + * If we've run out of data, zero out the buffers and return. + * By resetting the undifferencer, the output samples will be CENTERJSAMPLE. + * + * NB: We should find a way to do this without interacting with the + * undifferencer module directly. + */ + if (entropy->insufficient_data) { + for (ptrn = 0; ptrn < entropy->num_output_ptrs; ptrn++) + jzero_far((void FAR *) entropy->output_ptr[ptrn], + nMCU * (size_t)entropy->output_ptr_info[ptrn].MCU_width * SIZEOF(JDIFF)); + + (*losslsd->predict_process_restart) (cinfo); + } + + else { + + /* Load up working state */ + BITREAD_LOAD_STATE(cinfo,entropy->bitstate); + + /* Outer loop handles the number of MCU requested */ + + for (mcu_num = 0; mcu_num < nMCU; mcu_num++) { + + /* Inner loop handles the samples in the MCU */ + for (sampn = 0; sampn < cinfo->data_units_in_MCU; sampn++) { + d_derived_tbl * dctbl = entropy->cur_tbls[sampn]; + register int s, r; + + /* Section H.2.2: decode the sample difference */ + HUFF_DECODE(s, br_state, dctbl, return mcu_num, label1); + if (s) { + if (s == 16) /* special case: always output 32768 */ + s = 32768; + else { /* normal case: fetch subsequent bits */ + CHECK_BIT_BUFFER(br_state, s, return mcu_num); + r = GET_BITS(s); + s = HUFF_EXTEND(r, s); + } + } + + /* Output the sample difference */ + *entropy->output_ptr[entropy->output_ptr_index[sampn]]++ = (JDIFF) s; + } + + /* Completed MCU, so update state */ + BITREAD_SAVE_STATE(cinfo,entropy->bitstate); + } + } + + return nMCU; +} + + +/* + * Module initialization routine for lossless Huffman entropy decoding. + */ + +GLOBAL(void) +jinit_lhuff_decoder (j_decompress_ptr cinfo) +{ + j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec; + lhuff_entropy_ptr entropy; + int i; + + entropy = (lhuff_entropy_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(lhuff_entropy_decoder)); + losslsd->entropy_private = (void *) entropy; + losslsd->entropy_start_pass = start_pass_lhuff_decoder; + losslsd->entropy_process_restart = process_restart; + losslsd->entropy_decode_mcus = decode_mcus; + + /* Mark tables unallocated */ + for (i = 0; i < NUM_HUFF_TBLS; i++) { + entropy->derived_tbls[i] = NULL; + } +} + +#endif /* D_LOSSLESS_SUPPORTED */ diff --git a/dcmjpeg/libijg12/jdlossls.c b/dcmjpeg/libijg12/jdlossls.c new file mode 100644 index 00000000..7ae65667 --- /dev/null +++ b/dcmjpeg/libijg12/jdlossls.c @@ -0,0 +1,98 @@ +/* + * jdlossls.c + * + * Copyright (C) 1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains the control logic for the lossless JPEG decompressor. + */ + +#define JPEG_INTERNALS +#include "jinclude12.h" +#include "jpeglib12.h" +#include "jlossls12.h" + + +#ifdef D_LOSSLESS_SUPPORTED + +/* + * Compute output image dimensions and related values. + */ + +METHODDEF(void) +calc_output_dimensions (j_decompress_ptr cinfo) +{ + /* Hardwire it to "no scaling" */ + cinfo->output_width = cinfo->image_width; + cinfo->output_height = cinfo->image_height; + /* jdinput.c has already initialized codec_data_unit to 1, + * and has computed unscaled downsampled_width and downsampled_height. + */ +} + + +/* + * Initialize for an input processing pass. + */ + +METHODDEF(void) +start_input_pass (j_decompress_ptr cinfo) +{ + j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec; + + (*losslsd->entropy_start_pass) (cinfo); + (*losslsd->predict_start_pass) (cinfo); + (*losslsd->scaler_start_pass) (cinfo); + (*losslsd->diff_start_input_pass) (cinfo); +} + + +/* + * Initialize the lossless decompression codec. + * This is called only once, during master selection. + */ + +GLOBAL(void) +jinit_lossless_d_codec(j_decompress_ptr cinfo) +{ + j_lossless_d_ptr losslsd; + boolean use_c_buffer; + + /* Create subobject in permanent pool */ + losslsd = (j_lossless_d_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, + SIZEOF(jpeg_lossless_d_codec)); + cinfo->codec = (struct jpeg_d_codec *) losslsd; + + /* Initialize sub-modules */ + /* Entropy decoding: either Huffman or arithmetic coding. */ + if (cinfo->arith_code) { +#ifdef WITH_ARITHMETIC_PATCH + jinit_arith_decoder(cinfo); +#else + ERREXIT(cinfo, JERR_ARITH_NOTIMPL); +#endif + } else { + jinit_lhuff_decoder(cinfo); + } + + /* Undifferencer */ + jinit_undifferencer(cinfo); + + /* Scaler */ + jinit_d_scaler(cinfo); + + use_c_buffer = cinfo->inputctl->has_multiple_scans || cinfo->buffered_image; + jinit_d_diff_controller(cinfo, use_c_buffer); + + /* Initialize method pointers. + * + * Note: consume_data, start_output_pass and decompress_data are + * assigned in jddiffct.c. + */ + losslsd->pub.calc_output_dimensions = calc_output_dimensions; + losslsd->pub.start_input_pass = start_input_pass; +} + +#endif /* D_LOSSLESS_SUPPORTED */ diff --git a/dcmjpeg/libijg12/jdlossy.c b/dcmjpeg/libijg12/jdlossy.c new file mode 100644 index 00000000..4d7bd50f --- /dev/null +++ b/dcmjpeg/libijg12/jdlossy.c @@ -0,0 +1,232 @@ +/* + * jdlossy.c + * + * Copyright (C) 1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains the control logic for the lossy JPEG decompressor. + */ + +#define JPEG_INTERNALS +#include "jinclude12.h" +#include "jpeglib12.h" +#include "jlossy12.h" + + +/* + * Compute output image dimensions and related values. + */ + +METHODDEF(void) +calc_output_dimensions (j_decompress_ptr cinfo) +{ +#ifdef IDCT_SCALING_SUPPORTED + int ci; + jpeg_component_info *compptr; + + /* Compute actual output image dimensions and DCT scaling choices. */ + if (cinfo->scale_num * 8 <= cinfo->scale_denom) { + /* Provide 1/8 scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width, 8L); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height, 8L); + cinfo->min_codec_data_unit = 1; + } else if (cinfo->scale_num * 4 <= cinfo->scale_denom) { + /* Provide 1/4 scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width, 4L); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height, 4L); + cinfo->min_codec_data_unit = 2; + } else if (cinfo->scale_num * 2 <= cinfo->scale_denom) { + /* Provide 1/2 scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width, 2L); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height, 2L); + cinfo->min_codec_data_unit = 4; + } else { + /* Provide 1/1 scaling */ + cinfo->output_width = cinfo->image_width; + cinfo->output_height = cinfo->image_height; + cinfo->min_codec_data_unit = DCTSIZE; + } + /* In selecting the actual DCT scaling for each component, we try to + * scale up the chroma components via IDCT scaling rather than upsampling. + * This saves time if the upsampler gets to use 1:1 scaling. + * Note this code assumes that the supported DCT scalings are powers of 2. + */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + int ssize = cinfo->min_codec_data_unit; + while (ssize < DCTSIZE && + (compptr->h_samp_factor * ssize * 2 <= + cinfo->max_h_samp_factor * cinfo->min_codec_data_unit) && + (compptr->v_samp_factor * ssize * 2 <= + cinfo->max_v_samp_factor * cinfo->min_codec_data_unit)) { + ssize = ssize * 2; + } + compptr->codec_data_unit = ssize; + } + + /* Recompute downsampled dimensions of components; + * application needs to know these if using raw downsampled data. + */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + /* Size in samples, after IDCT scaling */ + compptr->downsampled_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * + (long) (compptr->h_samp_factor * compptr->codec_data_unit), + (long) (cinfo->max_h_samp_factor * DCTSIZE)); + compptr->downsampled_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * + (long) (compptr->v_samp_factor * compptr->codec_data_unit), + (long) (cinfo->max_v_samp_factor * DCTSIZE)); + } + +#else /* !IDCT_SCALING_SUPPORTED */ + + /* Hardwire it to "no scaling" */ + cinfo->output_width = cinfo->image_width; + cinfo->output_height = cinfo->image_height; + /* jdinput.c has already initialized codec_data_unit to DCTSIZE, + * and has computed unscaled downsampled_width and downsampled_height. + */ + +#endif /* IDCT_SCALING_SUPPORTED */ +} + + +/* + * Save away a copy of the Q-table referenced by each component present + * in the current scan, unless already saved during a prior scan. + * + * In a multiple-scan JPEG file, the encoder could assign different components + * the same Q-table slot number, but change table definitions between scans + * so that each component uses a different Q-table. (The IJG encoder is not + * currently capable of doing this, but other encoders might.) Since we want + * to be able to dequantize all the components at the end of the file, this + * means that we have to save away the table actually used for each component. + * We do this by copying the table at the start of the first scan containing + * the component. + * The JPEG spec prohibits the encoder from changing the contents of a Q-table + * slot between scans of a component using that slot. If the encoder does so + * anyway, this decoder will simply use the Q-table values that were current + * at the start of the first scan for the component. + * + * The decompressor output side looks only at the saved quant tables, + * not at the current Q-table slots. + */ + +LOCAL(void) +latch_quant_tables (j_decompress_ptr cinfo) +{ + int ci, qtblno; + jpeg_component_info *compptr; + JQUANT_TBL * qtbl; + + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + /* No work if we already saved Q-table for this component */ + if (compptr->quant_table != NULL) + continue; + /* Make sure specified quantization table is present */ + qtblno = compptr->quant_tbl_no; + if (qtblno < 0 || qtblno >= NUM_QUANT_TBLS || + cinfo->quant_tbl_ptrs[qtblno] == NULL) + ERREXIT1(cinfo, JERR_NO_QUANT_TABLE, qtblno); + /* OK, save away the quantization table */ + qtbl = (JQUANT_TBL *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(JQUANT_TBL)); + MEMCOPY(qtbl, cinfo->quant_tbl_ptrs[qtblno], SIZEOF(JQUANT_TBL)); + compptr->quant_table = qtbl; + } +} + + +/* + * Initialize for an input processing pass. + */ + +METHODDEF(void) +start_input_pass (j_decompress_ptr cinfo) +{ + j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec; + + latch_quant_tables(cinfo); + (*lossyd->entropy_start_pass) (cinfo); + (*lossyd->coef_start_input_pass) (cinfo); +} + + +/* + * Initialize for an output processing pass. + */ + +METHODDEF(void) +start_output_pass (j_decompress_ptr cinfo) +{ + j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec; + + (*lossyd->idct_start_pass) (cinfo); + (*lossyd->coef_start_output_pass) (cinfo); +} + +/* + * Initialize the lossy decompression codec. + * This is called only once, during master selection. + */ + +GLOBAL(void) +jinit_lossy_d_codec (j_decompress_ptr cinfo) +{ + j_lossy_d_ptr lossyd; + boolean use_c_buffer; + + /* Create subobject in permanent pool */ + lossyd = (j_lossy_d_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, + SIZEOF(jpeg_lossy_d_codec)); + cinfo->codec = (struct jpeg_d_codec *) lossyd; + + /* Initialize sub-modules */ + + /* Inverse DCT */ + jinit_inverse_dct(cinfo); + /* Entropy decoding: either Huffman or arithmetic coding. */ + if (cinfo->arith_code) { +#ifdef WITH_ARITHMETIC_PATCH + jinit_arith_decoder(cinfo); +#else + ERREXIT(cinfo, JERR_ARITH_NOTIMPL); +#endif + } else { + if (cinfo->process == JPROC_PROGRESSIVE) { +#ifdef D_PROGRESSIVE_SUPPORTED + jinit_phuff_decoder(cinfo); +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } else + jinit_shuff_decoder(cinfo); + } + + use_c_buffer = cinfo->inputctl->has_multiple_scans || cinfo->buffered_image; + jinit_d_coef_controller(cinfo, use_c_buffer); + + /* Initialize method pointers. + * + * Note: consume_data and decompress_data are assigned in jdcoefct.c. + */ + lossyd->pub.calc_output_dimensions = calc_output_dimensions; + lossyd->pub.start_input_pass = start_input_pass; + lossyd->pub.start_output_pass = start_output_pass; +} + + + + diff --git a/dcmjpeg/libijg12/jdmainct.c b/dcmjpeg/libijg12/jdmainct.c new file mode 100644 index 00000000..f58a68c4 --- /dev/null +++ b/dcmjpeg/libijg12/jdmainct.c @@ -0,0 +1,512 @@ +/* + * jdmainct.c + * + * Copyright (C) 1994-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains the main buffer controller for decompression. + * The main buffer lies between the JPEG decompressor proper and the + * post-processor; it holds downsampled data in the JPEG colorspace. + * + * Note that this code is bypassed in raw-data mode, since the application + * supplies the equivalent of the main buffer in that case. + */ + +#define JPEG_INTERNALS +#include "jinclude12.h" +#include "jpeglib12.h" + + +/* + * In the current system design, the main buffer need never be a full-image + * buffer; any full-height buffers will be found inside the coefficient or + * postprocessing controllers. Nonetheless, the main controller is not + * trivial. Its responsibility is to provide context rows for upsampling/ + * rescaling, and doing this in an efficient fashion is a bit tricky. + * + * Postprocessor input data is counted in "row groups". A row group + * is defined to be (v_samp_factor * codec_data_unit / min_codec_data_unit) + * sample rows of each component. (We require codec_data_unit values to be + * chosen such that these numbers are integers. In practice codec_data_unit + * values will likely be powers of two, so we actually have the stronger + * condition that codec_data_unit / min_codec_data_unit is an integer.) + * Upsampling will typically produce max_v_samp_factor pixel rows from each + * row group (times any additional scale factor that the upsampler is + * applying). + * + * The decompression codec will deliver data to us one iMCU row at a time; + * each iMCU row contains v_samp_factor * codec_data_unit sample rows, or + * exactly min_codec_data_unit row groups. (This amount of data corresponds + * to one row of MCUs when the image is fully interleaved.) Note that the + * number of sample rows varies across components, but the number of row + * groups does not. Some garbage sample rows may be included in the last iMCU + * row at the bottom of the image. + * + * Depending on the vertical scaling algorithm used, the upsampler may need + * access to the sample row(s) above and below its current input row group. + * The upsampler is required to set need_context_rows TRUE at global selection + * time if so. When need_context_rows is FALSE, this controller can simply + * obtain one iMCU row at a time from the coefficient controller and dole it + * out as row groups to the postprocessor. + * + * When need_context_rows is TRUE, this controller guarantees that the buffer + * passed to postprocessing contains at least one row group's worth of samples + * above and below the row group(s) being processed. Note that the context + * rows "above" the first passed row group appear at negative row offsets in + * the passed buffer. At the top and bottom of the image, the required + * context rows are manufactured by duplicating the first or last real sample + * row; this avoids having special cases in the upsampling inner loops. + * + * The amount of context is fixed at one row group just because that's a + * convenient number for this controller to work with. The existing + * upsamplers really only need one sample row of context. An upsampler + * supporting arbitrary output rescaling might wish for more than one row + * group of context when shrinking the image; tough, we don't handle that. + * (This is justified by the assumption that downsizing will be handled mostly + * by adjusting the codec_data_unit values, so that the actual scale factor at + * the upsample step needn't be much less than one.) + * + * To provide the desired context, we have to retain the last two row groups + * of one iMCU row while reading in the next iMCU row. (The last row group + * can't be processed until we have another row group for its below-context, + * and so we have to save the next-to-last group too for its above-context.) + * We could do this most simply by copying data around in our buffer, but + * that'd be very slow. We can avoid copying any data by creating a rather + * strange pointer structure. Here's how it works. We allocate a workspace + * consisting of M+2 row groups (where M = min_codec_data_unit is the number + * of row groups per iMCU row). We create two sets of redundant pointers to + * the workspace. Labeling the physical row groups 0 to M+1, the synthesized + * pointer lists look like this: + * M+1 M-1 + * master pointer --> 0 master pointer --> 0 + * 1 1 + * ... ... + * M-3 M-3 + * M-2 M + * M-1 M+1 + * M M-2 + * M+1 M-1 + * 0 0 + * We read alternate iMCU rows using each master pointer; thus the last two + * row groups of the previous iMCU row remain un-overwritten in the workspace. + * The pointer lists are set up so that the required context rows appear to + * be adjacent to the proper places when we pass the pointer lists to the + * upsampler. + * + * The above pictures describe the normal state of the pointer lists. + * At top and bottom of the image, we diddle the pointer lists to duplicate + * the first or last sample row as necessary (this is cheaper than copying + * sample rows around). + * + * This scheme breaks down if M < 2, ie, min_codec_data_unit is 1. In that + * situation each iMCU row provides only one row group so the buffering logic + * must be different (eg, we must read two iMCU rows before we can emit the + * first row group). For now, we simply do not support providing context + * rows when min_codec_data_unit is 1. That combination seems unlikely to + * be worth providing --- if someone wants a 1/8th-size preview, they probably + * want it quick and dirty, so a context-free upsampler is sufficient. + */ + + +/* Private buffer controller object */ + +typedef struct { + struct jpeg_d_main_controller pub; /* public fields */ + + /* Pointer to allocated workspace (M or M+2 row groups). */ + JSAMPARRAY buffer[MAX_COMPONENTS]; + + boolean buffer_full; /* Have we gotten an iMCU row from decoder? */ + JDIMENSION rowgroup_ctr; /* counts row groups output to postprocessor */ + + /* Remaining fields are only used in the context case. */ + + /* These are the master pointers to the funny-order pointer lists. */ + JSAMPIMAGE xbuffer[2]; /* pointers to weird pointer lists */ + + int whichptr; /* indicates which pointer set is now in use */ + int context_state; /* process_data state machine status */ + JDIMENSION rowgroups_avail; /* row groups available to postprocessor */ + JDIMENSION iMCU_row_ctr; /* counts iMCU rows to detect image top/bot */ +} my_main_controller; + +typedef my_main_controller * my_main_ptr; + +/* context_state values: */ +#define CTX_PREPARE_FOR_IMCU 0 /* need to prepare for MCU row */ +#define CTX_PROCESS_IMCU 1 /* feeding iMCU to postprocessor */ +#define CTX_POSTPONED_ROW 2 /* feeding postponed row group */ + + +/* Forward declarations */ +METHODDEF(void) process_data_simple_main + JPP((j_decompress_ptr cinfo, JSAMPARRAY output_buf, + JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail)); +METHODDEF(void) process_data_context_main + JPP((j_decompress_ptr cinfo, JSAMPARRAY output_buf, + JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail)); +#ifdef QUANT_2PASS_SUPPORTED +METHODDEF(void) process_data_crank_post + JPP((j_decompress_ptr cinfo, JSAMPARRAY output_buf, + JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail)); +#endif + + +LOCAL(void) +alloc_funny_pointers (j_decompress_ptr cinfo) +/* Allocate space for the funny pointer lists. + * This is done only once, not once per pass. + */ +{ + my_main_ptr mymain = (my_main_ptr) cinfo->main; + int ci, rgroup; + int M = cinfo->min_codec_data_unit; + jpeg_component_info *compptr; + JSAMPARRAY xbuf; + + /* Get top-level space for component array pointers. + * We alloc both arrays with one call to save a few cycles. + */ + mymain->xbuffer[0] = (JSAMPIMAGE) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (size_t)cinfo->num_components * 2 * SIZEOF(JSAMPARRAY)); + mymain->xbuffer[1] = mymain->xbuffer[0] + cinfo->num_components; + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + rgroup = (compptr->v_samp_factor * compptr->codec_data_unit) / + cinfo->min_codec_data_unit; /* height of a row group of component */ + /* Get space for pointer lists --- M+4 row groups in each list. + * We alloc both pointer lists with one call to save a few cycles. + */ + xbuf = (JSAMPARRAY) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + 2 * (size_t)(rgroup * (M + 4)) * SIZEOF(JSAMPROW)); + xbuf += rgroup; /* want one row group at negative offsets */ + mymain->xbuffer[0][ci] = xbuf; + xbuf += rgroup * (M + 4); + mymain->xbuffer[1][ci] = xbuf; + } +} + + +LOCAL(void) +make_funny_pointers (j_decompress_ptr cinfo) +/* Create the funny pointer lists discussed in the comments above. + * The actual workspace is already allocated (in main->buffer), + * and the space for the pointer lists is allocated too. + * This routine just fills in the curiously ordered lists. + * This will be repeated at the beginning of each pass. + */ +{ + my_main_ptr mymain = (my_main_ptr) cinfo->main; + int ci, i, rgroup; + int M = cinfo->min_codec_data_unit; + jpeg_component_info *compptr; + JSAMPARRAY buf, xbuf0, xbuf1; + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + rgroup = (compptr->v_samp_factor * compptr->codec_data_unit) / + cinfo->min_codec_data_unit; /* height of a row group of component */ + xbuf0 = mymain->xbuffer[0][ci]; + xbuf1 = mymain->xbuffer[1][ci]; + /* First copy the workspace pointers as-is */ + buf = mymain->buffer[ci]; + for (i = 0; i < rgroup * (M + 2); i++) { + xbuf0[i] = xbuf1[i] = buf[i]; + } + /* In the second list, put the last four row groups in swapped order */ + for (i = 0; i < rgroup * 2; i++) { + xbuf1[rgroup*(M-2) + i] = buf[rgroup*M + i]; + xbuf1[rgroup*M + i] = buf[rgroup*(M-2) + i]; + } + /* The wraparound pointers at top and bottom will be filled later + * (see set_wraparound_pointers, below). Initially we want the "above" + * pointers to duplicate the first actual data line. This only needs + * to happen in xbuffer[0]. + */ + for (i = 0; i < rgroup; i++) { + xbuf0[i - rgroup] = xbuf0[0]; + } + } +} + + +LOCAL(void) +set_wraparound_pointers (j_decompress_ptr cinfo) +/* Set up the "wraparound" pointers at top and bottom of the pointer lists. + * This changes the pointer list state from top-of-image to the normal state. + */ +{ + my_main_ptr mymain = (my_main_ptr) cinfo->main; + int ci, i, rgroup; + int M = cinfo->min_codec_data_unit; + jpeg_component_info *compptr; + JSAMPARRAY xbuf0, xbuf1; + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + rgroup = (compptr->v_samp_factor * compptr->codec_data_unit) / + cinfo->min_codec_data_unit; /* height of a row group of component */ + xbuf0 = mymain->xbuffer[0][ci]; + xbuf1 = mymain->xbuffer[1][ci]; + for (i = 0; i < rgroup; i++) { + xbuf0[i - rgroup] = xbuf0[rgroup*(M+1) + i]; + xbuf1[i - rgroup] = xbuf1[rgroup*(M+1) + i]; + xbuf0[rgroup*(M+2) + i] = xbuf0[i]; + xbuf1[rgroup*(M+2) + i] = xbuf1[i]; + } + } +} + + +LOCAL(void) +set_bottom_pointers (j_decompress_ptr cinfo) +/* Change the pointer lists to duplicate the last sample row at the bottom + * of the image. whichptr indicates which xbuffer holds the final iMCU row. + * Also sets rowgroups_avail to indicate number of nondummy row groups in row. + */ +{ + my_main_ptr mymain = (my_main_ptr) cinfo->main; + int ci, i, rgroup, iMCUheight, rows_left; + jpeg_component_info *compptr; + JSAMPARRAY xbuf; + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + /* Count sample rows in one iMCU row and in one row group */ + iMCUheight = compptr->v_samp_factor * compptr->codec_data_unit; + rgroup = iMCUheight / cinfo->min_codec_data_unit; + /* Count nondummy sample rows remaining for this component */ + rows_left = (int) (compptr->downsampled_height % (JDIMENSION) iMCUheight); + if (rows_left == 0) rows_left = iMCUheight; + /* Count nondummy row groups. Should get same answer for each component, + * so we need only do it once. + */ + if (ci == 0) { + mymain->rowgroups_avail = (JDIMENSION) ((rows_left-1) / rgroup + 1); + } + /* Duplicate the last real sample row rgroup*2 times; this pads out the + * last partial rowgroup and ensures at least one full rowgroup of context. + */ + xbuf = mymain->xbuffer[mymain->whichptr][ci]; + for (i = 0; i < rgroup * 2; i++) { + xbuf[rows_left + i] = xbuf[rows_left-1]; + } + } +} + + +/* + * Initialize for a processing pass. + */ + +METHODDEF(void) +start_pass_main (j_decompress_ptr cinfo, J_BUF_MODE pass_mode) +{ + my_main_ptr mymain = (my_main_ptr) cinfo->main; + + switch (pass_mode) { + case JBUF_PASS_THRU: + if (cinfo->upsample->need_context_rows) { + mymain->pub.process_data = process_data_context_main; + make_funny_pointers(cinfo); /* Create the xbuffer[] lists */ + mymain->whichptr = 0; /* Read first iMCU row into xbuffer[0] */ + mymain->context_state = CTX_PREPARE_FOR_IMCU; + mymain->iMCU_row_ctr = 0; + } else { + /* Simple case with no context needed */ + mymain->pub.process_data = process_data_simple_main; + } + mymain->buffer_full = FALSE; /* Mark buffer empty */ + mymain->rowgroup_ctr = 0; + break; +#ifdef QUANT_2PASS_SUPPORTED + case JBUF_CRANK_DEST: + /* For last pass of 2-pass quantization, just crank the postprocessor */ + mymain->pub.process_data = process_data_crank_post; + break; +#endif + default: + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + break; + } +} + + +/* + * Process some data. + * This handles the simple case where no context is required. + */ + +METHODDEF(void) +process_data_simple_main (j_decompress_ptr cinfo, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail) +{ + my_main_ptr mymain = (my_main_ptr) cinfo->main; + JDIMENSION rowgroups_avail; + + /* Read input data if we haven't filled the main buffer yet */ + if (! mymain->buffer_full) { + if (! (*cinfo->codec->decompress_data) (cinfo, mymain->buffer)) + return; /* suspension forced, can do nothing more */ + mymain->buffer_full = TRUE; /* OK, we have an iMCU row to work with */ + } + + /* There are always min_codec_data_unit row groups in an iMCU row. */ + rowgroups_avail = (JDIMENSION) cinfo->min_codec_data_unit; + /* Note: at the bottom of the image, we may pass extra garbage row groups + * to the postprocessor. The postprocessor has to check for bottom + * of image anyway (at row resolution), so no point in us doing it too. + */ + + /* Feed the postprocessor */ + (*cinfo->post->post_process_data) (cinfo, mymain->buffer, + &mymain->rowgroup_ctr, rowgroups_avail, + output_buf, out_row_ctr, out_rows_avail); + + /* Has postprocessor consumed all the data yet? If so, mark buffer empty */ + if (mymain->rowgroup_ctr >= rowgroups_avail) { + mymain->buffer_full = FALSE; + mymain->rowgroup_ctr = 0; + } +} + + +/* + * Process some data. + * This handles the case where context rows must be provided. + */ + +METHODDEF(void) +process_data_context_main (j_decompress_ptr cinfo, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail) +{ + my_main_ptr mymain = (my_main_ptr) cinfo->main; + + /* Read input data if we haven't filled the main buffer yet */ + if (! mymain->buffer_full) { + if (! (*cinfo->codec->decompress_data) (cinfo, + mymain->xbuffer[mymain->whichptr])) + return; /* suspension forced, can do nothing more */ + mymain->buffer_full = TRUE; /* OK, we have an iMCU row to work with */ + mymain->iMCU_row_ctr++; /* count rows received */ + } + + /* Postprocessor typically will not swallow all the input data it is handed + * in one call (due to filling the output buffer first). Must be prepared + * to exit and restart. This switch lets us keep track of how far we got. + * Note that each case falls through to the next on successful completion. + */ + switch (mymain->context_state) { + case CTX_POSTPONED_ROW: + /* Call postprocessor using previously set pointers for postponed row */ + (*cinfo->post->post_process_data) (cinfo, mymain->xbuffer[mymain->whichptr], + &mymain->rowgroup_ctr, mymain->rowgroups_avail, + output_buf, out_row_ctr, out_rows_avail); + if (mymain->rowgroup_ctr < mymain->rowgroups_avail) + return; /* Need to suspend */ + mymain->context_state = CTX_PREPARE_FOR_IMCU; + if (*out_row_ctr >= out_rows_avail) + return; /* Postprocessor exactly filled output buf */ + /*FALLTHROUGH*/ + case CTX_PREPARE_FOR_IMCU: + /* Prepare to process first M-1 row groups of this iMCU row */ + mymain->rowgroup_ctr = 0; + mymain->rowgroups_avail = (JDIMENSION) (cinfo->min_codec_data_unit - 1); + /* Check for bottom of image: if so, tweak pointers to "duplicate" + * the last sample row, and adjust rowgroups_avail to ignore padding rows. + */ + if (mymain->iMCU_row_ctr == cinfo->total_iMCU_rows) + set_bottom_pointers(cinfo); + mymain->context_state = CTX_PROCESS_IMCU; + /*FALLTHROUGH*/ + case CTX_PROCESS_IMCU: + /* Call postprocessor using previously set pointers */ + (*cinfo->post->post_process_data) (cinfo, mymain->xbuffer[mymain->whichptr], + &mymain->rowgroup_ctr, mymain->rowgroups_avail, + output_buf, out_row_ctr, out_rows_avail); + if (mymain->rowgroup_ctr < mymain->rowgroups_avail) + return; /* Need to suspend */ + /* After the first iMCU, change wraparound pointers to normal state */ + if (mymain->iMCU_row_ctr == 1) + set_wraparound_pointers(cinfo); + /* Prepare to load new iMCU row using other xbuffer list */ + mymain->whichptr ^= 1; /* 0=>1 or 1=>0 */ + mymain->buffer_full = FALSE; + /* Still need to process last row group of this iMCU row, */ + /* which is saved at index M+1 of the other xbuffer */ + mymain->rowgroup_ctr = (JDIMENSION) (cinfo->min_codec_data_unit + 1); + mymain->rowgroups_avail = (JDIMENSION) (cinfo->min_codec_data_unit + 2); + mymain->context_state = CTX_POSTPONED_ROW; + } +} + + +/* + * Process some data. + * Final pass of two-pass quantization: just call the postprocessor. + * Source data will be the postprocessor controller's internal buffer. + */ + +#ifdef QUANT_2PASS_SUPPORTED + +METHODDEF(void) +process_data_crank_post (j_decompress_ptr cinfo, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail) +{ + (*cinfo->post->post_process_data) (cinfo, (JSAMPIMAGE) NULL, + (JDIMENSION *) NULL, (JDIMENSION) 0, + output_buf, out_row_ctr, out_rows_avail); +} + +#endif /* QUANT_2PASS_SUPPORTED */ + + +/* + * Initialize main buffer controller. + */ + +GLOBAL(void) +jinit_d_main_controller (j_decompress_ptr cinfo, boolean need_full_buffer) +{ + my_main_ptr mymain; + int ci, rgroup, ngroups; + jpeg_component_info *compptr; + + mymain = (my_main_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_main_controller)); + cinfo->main = (struct jpeg_d_main_controller *) mymain; + mymain->pub.start_pass = start_pass_main; + + if (need_full_buffer) /* shouldn't happen */ + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + + /* Allocate the workspace. + * ngroups is the number of row groups we need. + */ + if (cinfo->upsample->need_context_rows) { + if (cinfo->min_codec_data_unit < 2) /* unsupported, see comments above */ + ERREXIT(cinfo, JERR_NOTIMPL); + alloc_funny_pointers(cinfo); /* Alloc space for xbuffer[] lists */ + ngroups = cinfo->min_codec_data_unit + 2; + } else { + ngroups = cinfo->min_codec_data_unit; + } + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + rgroup = (compptr->v_samp_factor * compptr->codec_data_unit) / + cinfo->min_codec_data_unit; /* height of a row group of component */ + mymain->buffer[ci] = (*cinfo->mem->alloc_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + compptr->width_in_data_units * (JDIMENSION) compptr->codec_data_unit, + (JDIMENSION) (rgroup * ngroups)); + } +} diff --git a/dcmjpeg/libijg12/jdmarker.c b/dcmjpeg/libijg12/jdmarker.c new file mode 100644 index 00000000..b5d29c7a --- /dev/null +++ b/dcmjpeg/libijg12/jdmarker.c @@ -0,0 +1,1370 @@ +/* + * jdmarker.c + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains routines to decode JPEG datastream markers. + * Most of the complexity arises from our desire to support input + * suspension: if not all of the data for a marker is available, + * we must exit back to the application. On resumption, we reprocess + * the marker. + */ + +#define JPEG_INTERNALS +#include "jinclude12.h" +#include "jpeglib12.h" + + +typedef enum { /* JPEG marker codes */ + M_SOF0 = 0xc0, + M_SOF1 = 0xc1, + M_SOF2 = 0xc2, + M_SOF3 = 0xc3, + + M_SOF5 = 0xc5, + M_SOF6 = 0xc6, + M_SOF7 = 0xc7, + + M_JPG = 0xc8, + M_SOF9 = 0xc9, + M_SOF10 = 0xca, + M_SOF11 = 0xcb, + + M_SOF13 = 0xcd, + M_SOF14 = 0xce, + M_SOF15 = 0xcf, + + M_DHT = 0xc4, + + M_DAC = 0xcc, + + M_RST0 = 0xd0, + M_RST1 = 0xd1, + M_RST2 = 0xd2, + M_RST3 = 0xd3, + M_RST4 = 0xd4, + M_RST5 = 0xd5, + M_RST6 = 0xd6, + M_RST7 = 0xd7, + + M_SOI = 0xd8, + M_EOI = 0xd9, + M_SOS = 0xda, + M_DQT = 0xdb, + M_DNL = 0xdc, + M_DRI = 0xdd, + M_DHP = 0xde, + M_EXP = 0xdf, + + M_APP0 = 0xe0, + M_APP1 = 0xe1, + M_APP2 = 0xe2, + M_APP3 = 0xe3, + M_APP4 = 0xe4, + M_APP5 = 0xe5, + M_APP6 = 0xe6, + M_APP7 = 0xe7, + M_APP8 = 0xe8, + M_APP9 = 0xe9, + M_APP10 = 0xea, + M_APP11 = 0xeb, + M_APP12 = 0xec, + M_APP13 = 0xed, + M_APP14 = 0xee, + M_APP15 = 0xef, + + M_JPG0 = 0xf0, + M_JPG13 = 0xfd, + M_COM = 0xfe, + + M_TEM = 0x01, + + M_ERROR = 0x100 +} JPEG_MARKER; + + +/* Private state */ + +typedef struct { + struct jpeg_marker_reader pub; /* public fields */ + + /* Application-overridable marker processing methods */ + jpeg_marker_parser_method process_COM; + jpeg_marker_parser_method process_APPn[16]; + + /* Limit on marker data length to save for each marker type */ + unsigned int length_limit_COM; + unsigned int length_limit_APPn[16]; + + /* Status of COM/APPn marker saving */ + jpeg_saved_marker_ptr cur_marker; /* NULL if not processing a marker */ + unsigned int bytes_read; /* data bytes read so far in marker */ + /* Note: cur_marker is not linked into marker_list until it's all read. */ +} my_marker_reader; + +typedef my_marker_reader * my_marker_ptr; + + +/* + * Macros for fetching data from the data source module. + * + * At all times, cinfo->src->next_input_byte and ->bytes_in_buffer reflect + * the current restart point; we update them only when we have reached a + * suitable place to restart if a suspension occurs. + */ + +/* Declare and initialize local copies of input pointer/count */ +#define INPUT_VARS(cinfo) \ + struct jpeg_source_mgr * datasrc = (cinfo)->src; \ + const JOCTET * next_input_byte = datasrc->next_input_byte; \ + size_t bytes_in_buffer = datasrc->bytes_in_buffer + +/* Unload the local copies --- do this only at a restart boundary */ +#define INPUT_SYNC(cinfo) \ + ( datasrc->next_input_byte = next_input_byte, \ + datasrc->bytes_in_buffer = bytes_in_buffer ) + +/* Reload the local copies --- used only in MAKE_BYTE_AVAIL */ +#define INPUT_RELOAD(cinfo) \ + ( next_input_byte = datasrc->next_input_byte, \ + bytes_in_buffer = datasrc->bytes_in_buffer ) + +/* Internal macro for INPUT_BYTE and INPUT_2BYTES: make a byte available. + * Note we do *not* do INPUT_SYNC before calling fill_input_buffer, + * but we must reload the local copies after a successful fill. + */ +#define MAKE_BYTE_AVAIL(cinfo,action) \ + if (bytes_in_buffer == 0) { \ + if (! (*datasrc->fill_input_buffer) (cinfo)) \ + { action; } \ + INPUT_RELOAD(cinfo); \ + } + +/* Read a byte into variable V. + * If must suspend, take the specified action (typically "return FALSE"). + */ +#define INPUT_BYTE(cinfo,V,action) \ + MAKESTMT( MAKE_BYTE_AVAIL(cinfo,action); \ + bytes_in_buffer--; \ + V = GETJOCTET(*next_input_byte++); ) + +/* As above, but read two bytes interpreted as an unsigned 16-bit integer. + * V should be declared unsigned int or perhaps IJG_INT32. + */ +#define INPUT_2BYTES(cinfo,V,action) \ + MAKESTMT( MAKE_BYTE_AVAIL(cinfo,action); \ + bytes_in_buffer--; \ + V = ((unsigned int) GETJOCTET(*next_input_byte++)) << 8; \ + MAKE_BYTE_AVAIL(cinfo,action); \ + bytes_in_buffer--; \ + V += GETJOCTET(*next_input_byte++); ) + + +/* + * Routines to process JPEG markers. + * + * Entry condition: JPEG marker itself has been read and its code saved + * in cinfo->unread_marker; input restart point is just after the marker. + * + * Exit: if return TRUE, have read and processed any parameters, and have + * updated the restart point to point after the parameters. + * If return FALSE, was forced to suspend before reaching end of + * marker parameters; restart point has not been moved. Same routine + * will be called again after application supplies more input data. + * + * This approach to suspension assumes that all of a marker's parameters + * can fit into a single input bufferload. This should hold for "normal" + * markers. Some COM/APPn markers might have large parameter segments + * that might not fit. If we are simply dropping such a marker, we use + * skip_input_data to get past it, and thereby put the problem on the + * source manager's shoulders. If we are saving the marker's contents + * into memory, we use a slightly different convention: when forced to + * suspend, the marker processor updates the restart point to the end of + * what it's consumed (ie, the end of the buffer) before returning FALSE. + * On resumption, cinfo->unread_marker still contains the marker code, + * but the data source will point to the next chunk of marker data. + * The marker processor must retain internal state to deal with this. + * + * Note that we don't bother to avoid duplicate trace messages if a + * suspension occurs within marker parameters. Other side effects + * require more care. + */ + + +LOCAL(boolean) +get_soi (j_decompress_ptr cinfo) +/* Process an SOI marker */ +{ + int i; + + TRACEMS(cinfo, 1, JTRC_SOI); + + if (cinfo->marker->saw_SOI) + ERREXIT(cinfo, JERR_SOI_DUPLICATE); + + /* Reset all parameters that are defined to be reset by SOI */ + + for (i = 0; i < NUM_ARITH_TBLS; i++) { + cinfo->arith_dc_L[i] = 0; + cinfo->arith_dc_U[i] = 1; + cinfo->arith_ac_K[i] = 5; + } + cinfo->restart_interval = 0; + + /* Set initial assumptions for colorspace etc */ + + cinfo->jpeg_color_space = JCS_UNKNOWN; + cinfo->CCIR601_sampling = FALSE; /* Assume non-CCIR sampling??? */ + + cinfo->saw_JFIF_marker = FALSE; + cinfo->JFIF_major_version = 1; /* set default JFIF APP0 values */ + cinfo->JFIF_minor_version = 1; + cinfo->density_unit = 0; + cinfo->X_density = 1; + cinfo->Y_density = 1; + cinfo->saw_Adobe_marker = FALSE; + cinfo->Adobe_transform = 0; + + cinfo->marker->saw_SOI = TRUE; + + return TRUE; +} + + +LOCAL(boolean) +get_sof (j_decompress_ptr cinfo, J_CODEC_PROCESS process, boolean is_arith, + int data_unit) +/* Process a SOFn marker */ +{ + IJG_INT32 length; + int c, ci; + jpeg_component_info * compptr; + INPUT_VARS(cinfo); + + cinfo->data_unit = data_unit; + cinfo->process = process; + cinfo->arith_code = is_arith; + + INPUT_2BYTES(cinfo, length, return FALSE); + + INPUT_BYTE(cinfo, cinfo->data_precision, return FALSE); + INPUT_2BYTES(cinfo, cinfo->image_height, return FALSE); + INPUT_2BYTES(cinfo, cinfo->image_width, return FALSE); + INPUT_BYTE(cinfo, cinfo->num_components, return FALSE); + + length -= 8; + + TRACEMS4(cinfo, 1, JTRC_SOF, cinfo->unread_marker, + (int) cinfo->image_width, (int) cinfo->image_height, + cinfo->num_components); + + if (cinfo->marker->saw_SOF) + ERREXIT(cinfo, JERR_SOF_DUPLICATE); + + /* We don't support files in which the image height is initially specified */ + /* as 0 and is later redefined by DNL. As long as we have to check that, */ + /* might as well have a general sanity check. */ + if (cinfo->image_height <= 0 || cinfo->image_width <= 0 + || cinfo->num_components <= 0) + ERREXIT(cinfo, JERR_EMPTY_IMAGE); + + if (length != (cinfo->num_components * 3)) + ERREXIT(cinfo, JERR_BAD_LENGTH); + + if (cinfo->comp_info == NULL) /* do only once, even if suspend */ + cinfo->comp_info = (jpeg_component_info *) (*cinfo->mem->alloc_small) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + (size_t)cinfo->num_components * SIZEOF(jpeg_component_info)); + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + compptr->component_index = ci; + INPUT_BYTE(cinfo, compptr->component_id, return FALSE); + INPUT_BYTE(cinfo, c, return FALSE); + compptr->h_samp_factor = (c >> 4) & 15; + compptr->v_samp_factor = (c ) & 15; + INPUT_BYTE(cinfo, compptr->quant_tbl_no, return FALSE); + + TRACEMS4(cinfo, 1, JTRC_SOF_COMPONENT, + compptr->component_id, compptr->h_samp_factor, + compptr->v_samp_factor, compptr->quant_tbl_no); + } + + cinfo->marker->saw_SOF = TRUE; + + INPUT_SYNC(cinfo); + return TRUE; +} + + +LOCAL(boolean) +get_sos (j_decompress_ptr cinfo) +/* Process a SOS marker */ +{ + IJG_INT32 length; + int i, ci, n, c, cc; + jpeg_component_info * compptr; + INPUT_VARS(cinfo); + + if (! cinfo->marker->saw_SOF) + ERREXIT(cinfo, JERR_SOS_NO_SOF); + + INPUT_2BYTES(cinfo, length, return FALSE); + + INPUT_BYTE(cinfo, n, return FALSE); /* Number of components */ + + TRACEMS1(cinfo, 1, JTRC_SOS, n); + + if (length != (n * 2 + 6) || n < 1 || n > MAX_COMPS_IN_SCAN) + ERREXIT(cinfo, JERR_BAD_LENGTH); + + cinfo->comps_in_scan = n; + + /* Collect the component-spec parameters */ + + for (i = 0; i < n; i++) { + INPUT_BYTE(cinfo, cc, return FALSE); + INPUT_BYTE(cinfo, c, return FALSE); + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + if (cc == compptr->component_id) + goto id_found; + } + + ERREXIT1(cinfo, JERR_BAD_COMPONENT_ID, cc); + + id_found: + + cinfo->cur_comp_info[i] = compptr; + compptr->dc_tbl_no = (c >> 4) & 15; + compptr->ac_tbl_no = (c ) & 15; + + TRACEMS3(cinfo, 1, JTRC_SOS_COMPONENT, cc, + compptr->dc_tbl_no, compptr->ac_tbl_no); + } + + /* Collect the additional scan parameters Ss, Se, Ah/Al. */ + INPUT_BYTE(cinfo, c, return FALSE); + cinfo->Ss = c; + INPUT_BYTE(cinfo, c, return FALSE); + cinfo->Se = c; + INPUT_BYTE(cinfo, c, return FALSE); + cinfo->Ah = (c >> 4) & 15; + cinfo->Al = (c ) & 15; + + TRACEMS4(cinfo, 1, JTRC_SOS_PARAMS, cinfo->Ss, cinfo->Se, + cinfo->Ah, cinfo->Al); + + /* Prepare to scan data & restart markers */ + cinfo->marker->next_restart_num = 0; + + /* Count another SOS marker */ + cinfo->input_scan_number++; + + INPUT_SYNC(cinfo); + return TRUE; +} + + +#ifdef D_ARITH_CODING_SUPPORTED + +LOCAL(boolean) +get_dac (j_decompress_ptr cinfo) +/* Process a DAC marker */ +{ + IJG_INT32 length; + int index, val; + INPUT_VARS(cinfo); + + INPUT_2BYTES(cinfo, length, return FALSE); + length -= 2; + + while (length > 0) { + INPUT_BYTE(cinfo, index, return FALSE); + INPUT_BYTE(cinfo, val, return FALSE); + + length -= 2; + + TRACEMS2(cinfo, 1, JTRC_DAC, index, val); + + if (index < 0 || index >= (2*NUM_ARITH_TBLS)) + ERREXIT1(cinfo, JERR_DAC_INDEX, index); + + if (index >= NUM_ARITH_TBLS) { /* define AC table */ + cinfo->arith_ac_K[index-NUM_ARITH_TBLS] = (UINT8) val; + } else { /* define DC table */ + cinfo->arith_dc_L[index] = (UINT8) (val & 0x0F); + cinfo->arith_dc_U[index] = (UINT8) (val >> 4); + if (cinfo->arith_dc_L[index] > cinfo->arith_dc_U[index]) + ERREXIT1(cinfo, JERR_DAC_VALUE, val); + } + } + + if (length != 0) + ERREXIT(cinfo, JERR_BAD_LENGTH); + + INPUT_SYNC(cinfo); + return TRUE; +} + +#else /* ! D_ARITH_CODING_SUPPORTED */ + +#define get_dac(cinfo) skip_variable(cinfo) + +#endif /* D_ARITH_CODING_SUPPORTED */ + + +LOCAL(boolean) +get_dht (j_decompress_ptr cinfo) +/* Process a DHT marker */ +{ + IJG_INT32 length; + UINT8 bits[17]; + UINT8 huffval[256]; + int i, idx, count; + JHUFF_TBL **htblptr; + INPUT_VARS(cinfo); + + INPUT_2BYTES(cinfo, length, return FALSE); + length -= 2; + + while (length > 16) { + INPUT_BYTE(cinfo, idx, return FALSE); + + TRACEMS1(cinfo, 1, JTRC_DHT, idx); + + bits[0] = 0; + count = 0; + for (i = 1; i <= 16; i++) { + INPUT_BYTE(cinfo, bits[i], return FALSE); + count += bits[i]; + } + + length -= 1 + 16; + + TRACEMS8(cinfo, 2, JTRC_HUFFBITS, + bits[1], bits[2], bits[3], bits[4], + bits[5], bits[6], bits[7], bits[8]); + TRACEMS8(cinfo, 2, JTRC_HUFFBITS, + bits[9], bits[10], bits[11], bits[12], + bits[13], bits[14], bits[15], bits[16]); + + /* Here we just do minimal validation of the counts to avoid walking + * off the end of our table space. jdhuff.c will check more carefully. + */ + if (count > 256 || ((IJG_INT32) count) > length) + ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); + + for (i = 0; i < count; i++) + INPUT_BYTE(cinfo, huffval[i], return FALSE); + + length -= count; + + if (idx & 0x10) { /* AC table definition */ + idx -= 0x10; + htblptr = &cinfo->ac_huff_tbl_ptrs[idx]; + } else { /* DC table definition */ + htblptr = &cinfo->dc_huff_tbl_ptrs[idx]; + } + + if (idx < 0 || idx >= NUM_HUFF_TBLS) + ERREXIT1(cinfo, JERR_DHT_INDEX, idx); + + if (*htblptr == NULL) + *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo); + + MEMCOPY((*htblptr)->bits, bits, SIZEOF((*htblptr)->bits)); + MEMCOPY((*htblptr)->huffval, huffval, SIZEOF((*htblptr)->huffval)); + } + + if (length != 0) + ERREXIT(cinfo, JERR_BAD_LENGTH); + + INPUT_SYNC(cinfo); + return TRUE; +} + + +LOCAL(boolean) +get_dqt (j_decompress_ptr cinfo) +/* Process a DQT marker */ +{ + IJG_INT32 length; + int n, i, prec; + unsigned int tmp; + JQUANT_TBL *quant_ptr; + INPUT_VARS(cinfo); + + INPUT_2BYTES(cinfo, length, return FALSE); + length -= 2; + + while (length > 0) { + INPUT_BYTE(cinfo, n, return FALSE); + prec = n >> 4; + n &= 0x0F; + + TRACEMS2(cinfo, 1, JTRC_DQT, n, prec); + + if (n >= NUM_QUANT_TBLS) + ERREXIT1(cinfo, JERR_DQT_INDEX, n); + + if (cinfo->quant_tbl_ptrs[n] == NULL) + cinfo->quant_tbl_ptrs[n] = jpeg_alloc_quant_table((j_common_ptr) cinfo); + quant_ptr = cinfo->quant_tbl_ptrs[n]; + + for (i = 0; i < DCTSIZE2; i++) { + if (prec) + INPUT_2BYTES(cinfo, tmp, return FALSE); + else + INPUT_BYTE(cinfo, tmp, return FALSE); + /* We convert the zigzag-order table to natural array order. */ + quant_ptr->quantval[jpeg_natural_order[i]] = (UINT16) tmp; + } + + if (cinfo->err->trace_level >= 2) { + for (i = 0; i < DCTSIZE2; i += 8) { + TRACEMS8(cinfo, 2, JTRC_QUANTVALS, + quant_ptr->quantval[i], quant_ptr->quantval[i+1], + quant_ptr->quantval[i+2], quant_ptr->quantval[i+3], + quant_ptr->quantval[i+4], quant_ptr->quantval[i+5], + quant_ptr->quantval[i+6], quant_ptr->quantval[i+7]); + } + } + + length -= DCTSIZE2+1; + if (prec) length -= DCTSIZE2; + } + + if (length != 0) + ERREXIT(cinfo, JERR_BAD_LENGTH); + + INPUT_SYNC(cinfo); + return TRUE; +} + + +LOCAL(boolean) +get_dri (j_decompress_ptr cinfo) +/* Process a DRI marker */ +{ + IJG_INT32 length; + unsigned int tmp; + INPUT_VARS(cinfo); + + INPUT_2BYTES(cinfo, length, return FALSE); + + if (length != 4) + ERREXIT(cinfo, JERR_BAD_LENGTH); + + INPUT_2BYTES(cinfo, tmp, return FALSE); + + TRACEMS1(cinfo, 1, JTRC_DRI, (int)tmp); + + cinfo->restart_interval = tmp; + + INPUT_SYNC(cinfo); + return TRUE; +} + + +/* + * Routines for processing APPn and COM markers. + * These are either saved in memory or discarded, per application request. + * APP0 and APP14 are specially checked to see if they are + * JFIF and Adobe markers, respectively. + */ + +#define APP0_DATA_LEN 14 /* Length of interesting data in APP0 */ +#define APP14_DATA_LEN 12 /* Length of interesting data in APP14 */ +#define APPN_DATA_LEN 14 /* Must be the largest of the above!! */ + + +LOCAL(void) +examine_app0 (j_decompress_ptr cinfo, JOCTET FAR * data, + unsigned int datalen, IJG_INT32 remaining) +/* Examine first few bytes from an APP0. + * Take appropriate action if it is a JFIF marker. + * datalen is # of bytes at data[], remaining is length of rest of marker data. + */ +{ + IJG_INT32 totallen = (IJG_INT32) datalen + remaining; + + if (datalen >= APP0_DATA_LEN && + GETJOCTET(data[0]) == 0x4A && + GETJOCTET(data[1]) == 0x46 && + GETJOCTET(data[2]) == 0x49 && + GETJOCTET(data[3]) == 0x46 && + GETJOCTET(data[4]) == 0) { + /* Found JFIF APP0 marker: save info */ + cinfo->saw_JFIF_marker = TRUE; + cinfo->JFIF_major_version = GETJOCTET(data[5]); + cinfo->JFIF_minor_version = GETJOCTET(data[6]); + cinfo->density_unit = GETJOCTET(data[7]); + cinfo->X_density = (UINT16)((GETJOCTET(data[8]) << 8) + GETJOCTET(data[9])); + cinfo->Y_density = (UINT16)((GETJOCTET(data[10]) << 8) + GETJOCTET(data[11])); + /* Check version. + * Major version must be 1, anything else signals an incompatible change. + * (We used to treat this as an error, but now it's a nonfatal warning, + * because some bozo at Hijaak couldn't read the spec.) + * Minor version should be 0..2, but process anyway if newer. + */ + if (cinfo->JFIF_major_version != 1) + WARNMS2(cinfo, JWRN_JFIF_MAJOR, + cinfo->JFIF_major_version, cinfo->JFIF_minor_version); + /* Generate trace messages */ + TRACEMS5(cinfo, 1, JTRC_JFIF, + cinfo->JFIF_major_version, cinfo->JFIF_minor_version, + cinfo->X_density, cinfo->Y_density, cinfo->density_unit); + /* Validate thumbnail dimensions and issue appropriate messages */ + if (GETJOCTET(data[12]) | GETJOCTET(data[13])) + TRACEMS2(cinfo, 1, JTRC_JFIF_THUMBNAIL, + GETJOCTET(data[12]), GETJOCTET(data[13])); + totallen -= APP0_DATA_LEN; + if (totallen != + ((IJG_INT32)GETJOCTET(data[12]) * (IJG_INT32)GETJOCTET(data[13]) * (IJG_INT32) 3)) + TRACEMS1(cinfo, 1, JTRC_JFIF_BADTHUMBNAILSIZE, (int) totallen); + } else if (datalen >= 6 && + GETJOCTET(data[0]) == 0x4A && + GETJOCTET(data[1]) == 0x46 && + GETJOCTET(data[2]) == 0x58 && + GETJOCTET(data[3]) == 0x58 && + GETJOCTET(data[4]) == 0) { + /* Found JFIF "JFXX" extension APP0 marker */ + /* The library doesn't actually do anything with these, + * but we try to produce a helpful trace message. + */ + switch (GETJOCTET(data[5])) { + case 0x10: + TRACEMS1(cinfo, 1, JTRC_THUMB_JPEG, (int) totallen); + break; + case 0x11: + TRACEMS1(cinfo, 1, JTRC_THUMB_PALETTE, (int) totallen); + break; + case 0x13: + TRACEMS1(cinfo, 1, JTRC_THUMB_RGB, (int) totallen); + break; + default: + TRACEMS2(cinfo, 1, JTRC_JFIF_EXTENSION, + GETJOCTET(data[5]), (int) totallen); + break; + } + } else { + /* Start of APP0 does not match "JFIF" or "JFXX", or too short */ + TRACEMS1(cinfo, 1, JTRC_APP0, (int) totallen); + } +} + + +LOCAL(void) +examine_app14 (j_decompress_ptr cinfo, JOCTET FAR * data, + unsigned int datalen, IJG_INT32 remaining) +/* Examine first few bytes from an APP14. + * Take appropriate action if it is an Adobe marker. + * datalen is # of bytes at data[], remaining is length of rest of marker data. + */ +{ + unsigned int version, flags0, flags1, transform; + + if (datalen >= APP14_DATA_LEN && + GETJOCTET(data[0]) == 0x41 && + GETJOCTET(data[1]) == 0x64 && + GETJOCTET(data[2]) == 0x6F && + GETJOCTET(data[3]) == 0x62 && + GETJOCTET(data[4]) == 0x65) { + /* Found Adobe APP14 marker */ + version = (unsigned int)((GETJOCTET(data[5]) << 8) + GETJOCTET(data[6])); + flags0 = (unsigned int)((GETJOCTET(data[7]) << 8) + GETJOCTET(data[8])); + flags1 = (unsigned int)((GETJOCTET(data[9]) << 8) + GETJOCTET(data[10])); + transform = GETJOCTET(data[11]); + TRACEMS4(cinfo, 1, JTRC_ADOBE, (int)version, (int)flags0, (int)flags1, (int)transform); + cinfo->saw_Adobe_marker = TRUE; + cinfo->Adobe_transform = (UINT8) transform; + } else { + /* Start of APP14 does not match "Adobe", or too short */ + TRACEMS1(cinfo, 1, JTRC_APP14, (int) (datalen + remaining)); + } +} + + +METHODDEF(boolean) +get_interesting_appn (j_decompress_ptr cinfo) +/* Process an APP0 or APP14 marker without saving it */ +{ + IJG_INT32 length; + JOCTET b[APPN_DATA_LEN]; + unsigned int i, numtoread; + INPUT_VARS(cinfo); + + INPUT_2BYTES(cinfo, length, return FALSE); + length -= 2; + + /* get the interesting part of the marker data */ + if (length >= APPN_DATA_LEN) + numtoread = APPN_DATA_LEN; + else if (length > 0) + numtoread = (unsigned int) length; + else + numtoread = 0; + for (i = 0; i < numtoread; i++) + INPUT_BYTE(cinfo, b[i], return FALSE); + length -= numtoread; + + /* process it */ + switch (cinfo->unread_marker) { + case M_APP0: + examine_app0(cinfo, (JOCTET FAR *) b, numtoread, length); + break; + case M_APP14: + examine_app14(cinfo, (JOCTET FAR *) b, numtoread, length); + break; + default: + /* can't get here unless jpeg_save_markers chooses wrong processor */ + ERREXIT1(cinfo, JERR_UNKNOWN_MARKER, cinfo->unread_marker); + break; + } + + /* skip any remaining data -- could be lots */ + INPUT_SYNC(cinfo); + if (length > 0) + (*cinfo->src->skip_input_data) (cinfo, (long) length); + + return TRUE; +} + + +#ifdef SAVE_MARKERS_SUPPORTED + +METHODDEF(boolean) +save_marker (j_decompress_ptr cinfo) +/* Save an APPn or COM marker into the marker list */ +{ + my_marker_ptr marker = (my_marker_ptr) cinfo->marker; + jpeg_saved_marker_ptr cur_marker = marker->cur_marker; + unsigned int bytes_read, data_length; + JOCTET FAR * data; + IJG_INT32 length = 0; + INPUT_VARS(cinfo); + + if (cur_marker == NULL) { + /* begin reading a marker */ + INPUT_2BYTES(cinfo, length, return FALSE); + length -= 2; + if (length >= 0) { /* watch out for bogus length word */ + /* figure out how much we want to save */ + unsigned int limit; + if (cinfo->unread_marker == (int) M_COM) + limit = marker->length_limit_COM; + else + limit = marker->length_limit_APPn[cinfo->unread_marker - (int) M_APP0]; + if ((unsigned int) length < limit) + limit = (unsigned int) length; + /* allocate and initialize the marker item */ + cur_marker = (jpeg_saved_marker_ptr) + (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(struct jpeg_marker_struct) + limit); + cur_marker->next = NULL; + cur_marker->marker = (UINT8) cinfo->unread_marker; + cur_marker->original_length = (unsigned int) length; + cur_marker->data_length = limit; + /* data area is just beyond the jpeg_marker_struct */ + data = cur_marker->data = (JOCTET FAR *) (cur_marker + 1); + marker->cur_marker = cur_marker; + marker->bytes_read = 0; + bytes_read = 0; + data_length = limit; + } else { + /* deal with bogus length word */ + bytes_read = data_length = 0; + data = NULL; + } + } else { + /* resume reading a marker */ + bytes_read = marker->bytes_read; + data_length = cur_marker->data_length; + data = cur_marker->data + bytes_read; + } + + while (bytes_read < data_length) { + INPUT_SYNC(cinfo); /* move the restart point to here */ + marker->bytes_read = bytes_read; + /* If there's not at least one byte in buffer, suspend */ + MAKE_BYTE_AVAIL(cinfo, return FALSE); + /* Copy bytes with reasonable rapidity */ + while (bytes_read < data_length && bytes_in_buffer > 0) { + *data++ = *next_input_byte++; + bytes_in_buffer--; + bytes_read++; + } + } + + /* Done reading what we want to read */ + if (cur_marker != NULL) { /* will be NULL if bogus length word */ + /* Add new marker to end of list */ + if (cinfo->marker_list == NULL) { + cinfo->marker_list = cur_marker; + } else { + jpeg_saved_marker_ptr prev = cinfo->marker_list; + while (prev->next != NULL) + prev = prev->next; + prev->next = cur_marker; + } + /* Reset pointer & calc remaining data length */ + data = cur_marker->data; + length = cur_marker->original_length - data_length; + } + /* Reset to initial state for next marker */ + marker->cur_marker = NULL; + + /* Process the marker if interesting; else just make a generic trace msg */ + switch (cinfo->unread_marker) { + case M_APP0: + examine_app0(cinfo, data, data_length, length); + break; + case M_APP14: + examine_app14(cinfo, data, data_length, length); + break; + default: + TRACEMS2(cinfo, 1, JTRC_MISC_MARKER, cinfo->unread_marker, + (int) (data_length + length)); + break; + } + + /* skip any remaining data -- could be lots */ + INPUT_SYNC(cinfo); /* do before skip_input_data */ + if (length > 0) + (*cinfo->src->skip_input_data) (cinfo, (long) length); + + return TRUE; +} + +#endif /* SAVE_MARKERS_SUPPORTED */ + + +METHODDEF(boolean) +skip_variable (j_decompress_ptr cinfo) +/* Skip over an unknown or uninteresting variable-length marker */ +{ + IJG_INT32 length; + INPUT_VARS(cinfo); + + INPUT_2BYTES(cinfo, length, return FALSE); + length -= 2; + + TRACEMS2(cinfo, 1, JTRC_MISC_MARKER, cinfo->unread_marker, (int) length); + + INPUT_SYNC(cinfo); /* do before skip_input_data */ + if (length > 0) + (*cinfo->src->skip_input_data) (cinfo, (long) length); + + return TRUE; +} + + +/* + * Find the next JPEG marker, save it in cinfo->unread_marker. + * Returns FALSE if had to suspend before reaching a marker; + * in that case cinfo->unread_marker is unchanged. + * + * Note that the result might not be a valid marker code, + * but it will never be 0 or FF. + */ + +LOCAL(boolean) +next_marker (j_decompress_ptr cinfo) +{ + int c; + INPUT_VARS(cinfo); + + for (;;) { + INPUT_BYTE(cinfo, c, return FALSE); + /* Skip any non-FF bytes. + * This may look a bit inefficient, but it will not occur in a valid file. + * We sync after each discarded byte so that a suspending data source + * can discard the byte from its buffer. + */ + while (c != 0xFF) { + cinfo->marker->discarded_bytes++; + INPUT_SYNC(cinfo); + INPUT_BYTE(cinfo, c, return FALSE); + } + /* This loop swallows any duplicate FF bytes. Extra FFs are legal as + * pad bytes, so don't count them in discarded_bytes. We assume there + * will not be so many consecutive FF bytes as to overflow a suspending + * data source's input buffer. + */ + do { + INPUT_BYTE(cinfo, c, return FALSE); + } while (c == 0xFF); + if (c != 0) + break; /* found a valid marker, exit loop */ + /* Reach here if we found a stuffed-zero data sequence (FF/00). + * Discard it and loop back to try again. + */ + cinfo->marker->discarded_bytes += 2; + INPUT_SYNC(cinfo); + } + + if (cinfo->marker->discarded_bytes != 0) { + WARNMS2(cinfo, JWRN_EXTRANEOUS_DATA, (int)cinfo->marker->discarded_bytes, c); + cinfo->marker->discarded_bytes = 0; + } + + cinfo->unread_marker = c; + + INPUT_SYNC(cinfo); + return TRUE; +} + + +LOCAL(boolean) +first_marker (j_decompress_ptr cinfo) +/* Like next_marker, but used to obtain the initial SOI marker. */ +/* For this marker, we do not allow preceding garbage or fill; otherwise, + * we might well scan an entire input file before realizing it ain't JPEG. + * If an application wants to process non-JFIF files, it must seek to the + * SOI before calling the JPEG library. + */ +{ + int c, c2; + INPUT_VARS(cinfo); + + INPUT_BYTE(cinfo, c, return FALSE); + INPUT_BYTE(cinfo, c2, return FALSE); + if (c != 0xFF || c2 != (int) M_SOI) + ERREXIT2(cinfo, JERR_NO_SOI, c, c2); + + cinfo->unread_marker = c2; + + INPUT_SYNC(cinfo); + return TRUE; +} + + +/* + * Read markers until SOS or EOI. + * + * Returns same codes as are defined for jpeg_consume_input: + * JPEG_SUSPENDED, JPEG_REACHED_SOS, or JPEG_REACHED_EOI. + */ + +METHODDEF(int) +read_markers (j_decompress_ptr cinfo) +{ + /* Outer loop repeats once for each marker. */ + for (;;) { + /* Collect the marker proper, unless we already did. */ + /* NB: first_marker() enforces the requirement that SOI appear first. */ + if (cinfo->unread_marker == 0) { + if (! cinfo->marker->saw_SOI) { + if (! first_marker(cinfo)) + return JPEG_SUSPENDED; + } else { + if (! next_marker(cinfo)) + return JPEG_SUSPENDED; + } + } + /* At this point cinfo->unread_marker contains the marker code and the + * input point is just past the marker proper, but before any parameters. + * A suspension will cause us to return with this state still true. + */ + switch (cinfo->unread_marker) { + case M_SOI: + if (! get_soi(cinfo)) + return JPEG_SUSPENDED; + break; + + case M_SOF0: /* Baseline */ + case M_SOF1: /* Extended sequential, Huffman */ + if (! get_sof(cinfo, JPROC_SEQUENTIAL, FALSE, DCTSIZE)) + return JPEG_SUSPENDED; + break; + + case M_SOF2: /* Progressive, Huffman */ + if (! get_sof(cinfo, JPROC_PROGRESSIVE, FALSE, DCTSIZE)) + return JPEG_SUSPENDED; + break; + + case M_SOF3: /* Lossless, Huffman */ + if (! get_sof(cinfo, JPROC_LOSSLESS, FALSE, 1)) + return JPEG_SUSPENDED; + break; + + case M_SOF9: /* Extended sequential, arithmetic */ + if (! get_sof(cinfo, JPROC_SEQUENTIAL, TRUE, DCTSIZE)) + return JPEG_SUSPENDED; + break; + + case M_SOF10: /* Progressive, arithmetic */ + if (! get_sof(cinfo, JPROC_PROGRESSIVE, TRUE, DCTSIZE)) + return JPEG_SUSPENDED; + break; + + case M_SOF11: /* Lossless, arithmetic */ + if (! get_sof(cinfo, JPROC_LOSSLESS, TRUE, 1)) + return JPEG_SUSPENDED; + break; + + /* Currently unsupported SOFn types */ + case M_SOF5: /* Differential sequential, Huffman */ + case M_SOF6: /* Differential progressive, Huffman */ + case M_SOF7: /* Differential lossless, Huffman */ + case M_JPG: /* Reserved for JPEG extensions */ + case M_SOF13: /* Differential sequential, arithmetic */ + case M_SOF14: /* Differential progressive, arithmetic */ + case M_SOF15: /* Differential lossless, arithmetic */ + ERREXIT1(cinfo, JERR_SOF_UNSUPPORTED, cinfo->unread_marker); + break; + + case M_SOS: + if (! get_sos(cinfo)) + return JPEG_SUSPENDED; + cinfo->unread_marker = 0; /* processed the marker */ + return JPEG_REACHED_SOS; + + case M_EOI: + TRACEMS(cinfo, 1, JTRC_EOI); + cinfo->unread_marker = 0; /* processed the marker */ + return JPEG_REACHED_EOI; + + case M_DAC: + if (! get_dac(cinfo)) + return JPEG_SUSPENDED; + break; + + case M_DHT: + if (! get_dht(cinfo)) + return JPEG_SUSPENDED; + break; + + case M_DQT: + if (! get_dqt(cinfo)) + return JPEG_SUSPENDED; + break; + + case M_DRI: + if (! get_dri(cinfo)) + return JPEG_SUSPENDED; + break; + + case M_APP0: + case M_APP1: + case M_APP2: + case M_APP3: + case M_APP4: + case M_APP5: + case M_APP6: + case M_APP7: + case M_APP8: + case M_APP9: + case M_APP10: + case M_APP11: + case M_APP12: + case M_APP13: + case M_APP14: + case M_APP15: + if (! (*((my_marker_ptr) cinfo->marker)->process_APPn[ + cinfo->unread_marker - (int) M_APP0]) (cinfo)) + return JPEG_SUSPENDED; + break; + + case M_COM: + if (! (*((my_marker_ptr) cinfo->marker)->process_COM) (cinfo)) + return JPEG_SUSPENDED; + break; + + case M_RST0: /* these are all parameterless */ + case M_RST1: + case M_RST2: + case M_RST3: + case M_RST4: + case M_RST5: + case M_RST6: + case M_RST7: + case M_TEM: + TRACEMS1(cinfo, 1, JTRC_PARMLESS_MARKER, cinfo->unread_marker); + break; + + case M_DNL: /* Ignore DNL ... perhaps the wrong thing */ + if (! skip_variable(cinfo)) + return JPEG_SUSPENDED; + break; + + default: /* must be DHP, EXP, JPGn, or RESn */ + /* For now, we treat the reserved markers as fatal errors since they are + * likely to be used to signal incompatible JPEG Part 3 extensions. + * Once the JPEG 3 version-number marker is well defined, this code + * ought to change! + */ + ERREXIT1(cinfo, JERR_UNKNOWN_MARKER, cinfo->unread_marker); + break; + } + /* Successfully processed marker, so reset state variable */ + cinfo->unread_marker = 0; + } /* end loop */ +} + + +/* + * Read a restart marker, which is expected to appear next in the datastream; + * if the marker is not there, take appropriate recovery action. + * Returns FALSE if suspension is required. + * + * This is called by the entropy decoder after it has read an appropriate + * number of MCUs. cinfo->unread_marker may be nonzero if the entropy decoder + * has already read a marker from the data source. Under normal conditions + * cinfo->unread_marker will be reset to 0 before returning; if not reset, + * it holds a marker which the decoder will be unable to read past. + */ + +METHODDEF(boolean) +read_restart_marker (j_decompress_ptr cinfo) +{ + /* Obtain a marker unless we already did. */ + /* Note that next_marker will complain if it skips any data. */ + if (cinfo->unread_marker == 0) { + if (! next_marker(cinfo)) + return FALSE; + } + + if (cinfo->unread_marker == + ((int) M_RST0 + cinfo->marker->next_restart_num)) { + /* Normal case --- swallow the marker and let entropy decoder continue */ + TRACEMS1(cinfo, 3, JTRC_RST, cinfo->marker->next_restart_num); + cinfo->unread_marker = 0; + } else { + /* Uh-oh, the restart markers have been messed up. */ + /* Let the data source manager determine how to resync. */ + if (! (*cinfo->src->resync_to_restart) (cinfo, + cinfo->marker->next_restart_num)) + return FALSE; + } + + /* Update next-restart state */ + cinfo->marker->next_restart_num = (cinfo->marker->next_restart_num + 1) & 7; + + return TRUE; +} + + +/* + * This is the default resync_to_restart method for data source managers + * to use if they don't have any better approach. Some data source managers + * may be able to back up, or may have additional knowledge about the data + * which permits a more intelligent recovery strategy; such managers would + * presumably supply their own resync method. + * + * read_restart_marker calls resync_to_restart if it finds a marker other than + * the restart marker it was expecting. (This code is *not* used unless + * a nonzero restart interval has been declared.) cinfo->unread_marker is + * the marker code actually found (might be anything, except 0 or FF). + * The desired restart marker number (0..7) is passed as a parameter. + * This routine is supposed to apply whatever error recovery strategy seems + * appropriate in order to position the input stream to the next data segment. + * Note that cinfo->unread_marker is treated as a marker appearing before + * the current data-source input point; usually it should be reset to zero + * before returning. + * Returns FALSE if suspension is required. + * + * This implementation is substantially constrained by wanting to treat the + * input as a data stream; this means we can't back up. Therefore, we have + * only the following actions to work with: + * 1. Simply discard the marker and let the entropy decoder resume at next + * byte of file. + * 2. Read forward until we find another marker, discarding intervening + * data. (In theory we could look ahead within the current bufferload, + * without having to discard data if we don't find the desired marker. + * This idea is not implemented here, in part because it makes behavior + * dependent on buffer size and chance buffer-boundary positions.) + * 3. Leave the marker unread (by failing to zero cinfo->unread_marker). + * This will cause the entropy decoder to process an empty data segment, + * inserting dummy zeroes, and then we will reprocess the marker. + * + * #2 is appropriate if we think the desired marker lies ahead, while #3 is + * appropriate if the found marker is a future restart marker (indicating + * that we have missed the desired restart marker, probably because it got + * corrupted). + * We apply #2 or #3 if the found marker is a restart marker no more than + * two counts behind or ahead of the expected one. We also apply #2 if the + * found marker is not a legal JPEG marker code (it's certainly bogus data). + * If the found marker is a restart marker more than 2 counts away, we do #1 + * (too much risk that the marker is erroneous; with luck we will be able to + * resync at some future point). + * For any valid non-restart JPEG marker, we apply #3. This keeps us from + * overrunning the end of a scan. An implementation limited to single-scan + * files might find it better to apply #2 for markers other than EOI, since + * any other marker would have to be bogus data in that case. + */ + +GLOBAL(boolean) +jpeg_resync_to_restart (j_decompress_ptr cinfo, int desired) +{ + int marker = cinfo->unread_marker; + int action = 1; + + /* Always put up a warning. */ + WARNMS2(cinfo, JWRN_MUST_RESYNC, marker, desired); + + /* Outer loop handles repeated decision after scanning forward. */ + for (;;) { + if (marker < (int) M_SOF0) + action = 2; /* invalid marker */ + else if (marker < (int) M_RST0 || marker > (int) M_RST7) + action = 3; /* valid non-restart marker */ + else { + if (marker == ((int) M_RST0 + ((desired+1) & 7)) || + marker == ((int) M_RST0 + ((desired+2) & 7))) + action = 3; /* one of the next two expected restarts */ + else if (marker == ((int) M_RST0 + ((desired-1) & 7)) || + marker == ((int) M_RST0 + ((desired-2) & 7))) + action = 2; /* a prior restart, so advance */ + else + action = 1; /* desired restart or too far away */ + } + TRACEMS2(cinfo, 4, JTRC_RECOVERY_ACTION, marker, action); + switch (action) { + case 1: + /* Discard marker and let entropy decoder resume processing. */ + cinfo->unread_marker = 0; + return TRUE; + case 2: + /* Scan to the next marker, and repeat the decision loop. */ + if (! next_marker(cinfo)) + return FALSE; + marker = cinfo->unread_marker; + break; + case 3: + /* Return without advancing past this marker. */ + /* Entropy decoder will be forced to process an empty segment. */ + return TRUE; + } + } /* end loop */ +} + + +/* + * Reset marker processing state to begin a fresh datastream. + */ + +METHODDEF(void) +reset_marker_reader (j_decompress_ptr cinfo) +{ + my_marker_ptr marker = (my_marker_ptr) cinfo->marker; + + cinfo->comp_info = NULL; /* until allocated by get_sof */ + cinfo->input_scan_number = 0; /* no SOS seen yet */ + cinfo->unread_marker = 0; /* no pending marker */ + marker->pub.saw_SOI = FALSE; /* set internal state too */ + marker->pub.saw_SOF = FALSE; + marker->pub.discarded_bytes = 0; + marker->cur_marker = NULL; +} + + +/* + * Initialize the marker reader module. + * This is called only once, when the decompression object is created. + */ + +GLOBAL(void) +jinit_marker_reader (j_decompress_ptr cinfo) +{ + my_marker_ptr marker; + int i; + + /* Create subobject in permanent pool */ + marker = (my_marker_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, + SIZEOF(my_marker_reader)); + cinfo->marker = (struct jpeg_marker_reader *) marker; + /* Initialize public method pointers */ + marker->pub.reset_marker_reader = reset_marker_reader; + marker->pub.read_markers = read_markers; + marker->pub.read_restart_marker = read_restart_marker; + /* Initialize COM/APPn processing. + * By default, we examine and then discard APP0 and APP14, + * but simply discard COM and all other APPn. + */ + marker->process_COM = skip_variable; + marker->length_limit_COM = 0; + for (i = 0; i < 16; i++) { + marker->process_APPn[i] = skip_variable; + marker->length_limit_APPn[i] = 0; + } + marker->process_APPn[0] = get_interesting_appn; + marker->process_APPn[14] = get_interesting_appn; + /* Reset marker processing state */ + reset_marker_reader(cinfo); +} + + +/* + * Control saving of COM and APPn markers into marker_list. + */ + +#ifdef SAVE_MARKERS_SUPPORTED + +GLOBAL(void) +jpeg_save_markers (j_decompress_ptr cinfo, int marker_code, + unsigned int length_limit) +{ + my_marker_ptr marker = (my_marker_ptr) cinfo->marker; + long maxlength; + jpeg_marker_parser_method processor; + + /* Length limit mustn't be larger than what we can allocate + * (should only be a concern in a 16-bit environment). + */ + maxlength = cinfo->mem->max_alloc_chunk - (long)SIZEOF(struct jpeg_marker_struct); + if (((long) length_limit) > maxlength) + length_limit = (unsigned int) maxlength; + + /* Choose processor routine to use. + * APP0/APP14 have special requirements. + */ + if (length_limit) { + processor = save_marker; + /* If saving APP0/APP14, save at least enough for our internal use. */ + if (marker_code == (int) M_APP0 && length_limit < APP0_DATA_LEN) + length_limit = APP0_DATA_LEN; + else if (marker_code == (int) M_APP14 && length_limit < APP14_DATA_LEN) + length_limit = APP14_DATA_LEN; + } else { + processor = skip_variable; + /* If discarding APP0/APP14, use our regular on-the-fly processor. */ + if (marker_code == (int) M_APP0 || marker_code == (int) M_APP14) + processor = get_interesting_appn; + } + + if (marker_code == (int) M_COM) { + marker->process_COM = processor; + marker->length_limit_COM = length_limit; + } else if (marker_code >= (int) M_APP0 && marker_code <= (int) M_APP15) { + marker->process_APPn[marker_code - (int) M_APP0] = processor; + marker->length_limit_APPn[marker_code - (int) M_APP0] = length_limit; + } else + ERREXIT1(cinfo, JERR_UNKNOWN_MARKER, marker_code); +} + +#endif /* SAVE_MARKERS_SUPPORTED */ + + +/* + * Install a special processing method for COM or APPn markers. + */ + +GLOBAL(void) +jpeg_set_marker_processor (j_decompress_ptr cinfo, int marker_code, + jpeg_marker_parser_method routine) +{ + my_marker_ptr marker = (my_marker_ptr) cinfo->marker; + + if (marker_code == (int) M_COM) + marker->process_COM = routine; + else if (marker_code >= (int) M_APP0 && marker_code <= (int) M_APP15) + marker->process_APPn[marker_code - (int) M_APP0] = routine; + else + ERREXIT1(cinfo, JERR_UNKNOWN_MARKER, marker_code); +} diff --git a/dcmjpeg/libijg12/jdmaster.c b/dcmjpeg/libijg12/jdmaster.c new file mode 100644 index 00000000..b7a8936c --- /dev/null +++ b/dcmjpeg/libijg12/jdmaster.c @@ -0,0 +1,460 @@ +/* + * jdmaster.c + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains master control logic for the JPEG decompressor. + * These routines are concerned with selecting the modules to be executed + * and with determining the number of passes and the work to be done in each + * pass. + */ + +#define JPEG_INTERNALS +#include "jinclude12.h" +#include "jpeglib12.h" + + +/* Private state */ + +typedef struct { + struct jpeg_decomp_master pub; /* public fields */ + + int pass_number; /* # of passes completed */ + + boolean using_merged_upsample; /* TRUE if using merged upsample/cconvert */ + + /* Saved references to initialized quantizer modules, + * in case we need to switch modes. + */ + struct jpeg_color_quantizer * quantizer_1pass; + struct jpeg_color_quantizer * quantizer_2pass; +} my_decomp_master; + +typedef my_decomp_master * my_master_ptr; + + +/* + * Determine whether merged upsample/color conversion should be used. + * CRUCIAL: this must match the actual capabilities of jdmerge.c! + */ + +LOCAL(boolean) +use_merged_upsample (j_decompress_ptr cinfo) +{ +#ifdef UPSAMPLE_MERGING_SUPPORTED + /* Merging is the equivalent of plain box-filter upsampling */ + if (cinfo->do_fancy_upsampling || cinfo->CCIR601_sampling) + return FALSE; + /* jdmerge.c only supports YCC=>RGB color conversion */ + if (cinfo->jpeg_color_space != JCS_YCbCr || cinfo->num_components != 3 || + cinfo->out_color_space != JCS_RGB || + cinfo->out_color_components != RGB_PIXELSIZE) + return FALSE; + /* and it only handles 2h1v or 2h2v sampling ratios */ + if (cinfo->comp_info[0].h_samp_factor != 2 || + cinfo->comp_info[1].h_samp_factor != 1 || + cinfo->comp_info[2].h_samp_factor != 1 || + cinfo->comp_info[0].v_samp_factor > 2 || + cinfo->comp_info[1].v_samp_factor != 1 || + cinfo->comp_info[2].v_samp_factor != 1) + return FALSE; + /* furthermore, it doesn't work if each component has been + processed differently */ + if (cinfo->comp_info[0].codec_data_unit != cinfo->min_codec_data_unit || + cinfo->comp_info[1].codec_data_unit != cinfo->min_codec_data_unit || + cinfo->comp_info[2].codec_data_unit != cinfo->min_codec_data_unit) + return FALSE; + /* ??? also need to test for upsample-time rescaling, when & if supported */ + return TRUE; /* by golly, it'll work... */ +#else + return FALSE; +#endif +} + + +/* + * Compute output image dimensions and related values. + * NOTE: this is exported for possible use by application. + * Hence it mustn't do anything that can't be done twice. + * Also note that it may be called before the master module is initialized! + */ + +GLOBAL(void) +jpeg_calc_output_dimensions (j_decompress_ptr cinfo) +/* Do computations that are needed before master selection phase */ +{ + /* Prevent application from calling me at wrong times */ + if (cinfo->global_state != DSTATE_READY) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + + (*cinfo->codec->calc_output_dimensions) (cinfo); + + /* Report number of components in selected colorspace. */ + /* Probably this should be in the color conversion module... */ + switch (cinfo->out_color_space) { + case JCS_GRAYSCALE: + cinfo->out_color_components = 1; + break; + case JCS_RGB: +#if RGB_PIXELSIZE != 3 + cinfo->out_color_components = RGB_PIXELSIZE; + break; +#endif /* else share code with YCbCr */ + case JCS_YCbCr: + cinfo->out_color_components = 3; + break; + case JCS_CMYK: + case JCS_YCCK: + cinfo->out_color_components = 4; + break; + default: /* else must be same colorspace as in file */ + cinfo->out_color_components = cinfo->num_components; + break; + } + cinfo->output_components = (cinfo->quantize_colors ? 1 : + cinfo->out_color_components); + + /* See if upsampler will want to emit more than one row at a time */ + if (use_merged_upsample(cinfo)) + cinfo->rec_outbuf_height = cinfo->max_v_samp_factor; + else + cinfo->rec_outbuf_height = 1; +} + + +/* + * Several decompression processes need to range-limit values to the range + * 0..MAXJSAMPLE; the input value may fall somewhat outside this range + * due to noise introduced by quantization, roundoff error, etc. These + * processes are inner loops and need to be as fast as possible. On most + * machines, particularly CPUs with pipelines or instruction prefetch, + * a (subscript-check-less) C table lookup + * x = sample_range_limit[x]; + * is faster than explicit tests + * if (x < 0) x = 0; + * else if (x > MAXJSAMPLE) x = MAXJSAMPLE; + * These processes all use a common table prepared by the routine below. + * + * For most steps we can mathematically guarantee that the initial value + * of x is within MAXJSAMPLE+1 of the legal range, so a table running from + * -(MAXJSAMPLE+1) to 2*MAXJSAMPLE+1 is sufficient. But for the initial + * limiting step (just after the IDCT), a wildly out-of-range value is + * possible if the input data is corrupt. To avoid any chance of indexing + * off the end of memory and getting a bad-pointer trap, we perform the + * post-IDCT limiting thus: + * x = range_limit[x & MASK]; + * where MASK is 2 bits wider than legal sample data, ie 10 bits for 8-bit + * samples. Under normal circumstances this is more than enough range and + * a correct output will be generated; with bogus input data the mask will + * cause wraparound, and we will safely generate a bogus-but-in-range output. + * For the post-IDCT step, we want to convert the data from signed to unsigned + * representation by adding CENTERJSAMPLE at the same time that we limit it. + * So the post-IDCT limiting table ends up looking like this: + * CENTERJSAMPLE,CENTERJSAMPLE+1,...,MAXJSAMPLE, + * MAXJSAMPLE (repeat 2*(MAXJSAMPLE+1)-CENTERJSAMPLE times), + * 0 (repeat 2*(MAXJSAMPLE+1)-CENTERJSAMPLE times), + * 0,1,...,CENTERJSAMPLE-1 + * Negative inputs select values from the upper half of the table after + * masking. + * + * We can save some space by overlapping the start of the post-IDCT table + * with the simpler range limiting table. The post-IDCT table begins at + * sample_range_limit + CENTERJSAMPLE. + * + * Note that the table is allocated in near data space on PCs; it's small + * enough and used often enough to justify this. + */ + +LOCAL(void) +prepare_range_limit_table (j_decompress_ptr cinfo) +/* Allocate and fill in the sample_range_limit table */ +{ + JSAMPLE * table; + int i; + + table = (JSAMPLE *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (5 * (MAXJSAMPLE+1) + CENTERJSAMPLE) * SIZEOF(JSAMPLE)); + table += (MAXJSAMPLE+1); /* allow negative subscripts of simple table */ + cinfo->sample_range_limit = table; + /* First segment of "simple" table: limit[x] = 0 for x < 0 */ + MEMZERO(table - (MAXJSAMPLE+1), (MAXJSAMPLE+1) * SIZEOF(JSAMPLE)); + /* Main part of "simple" table: limit[x] = x */ + for (i = 0; i <= MAXJSAMPLE; i++) + table[i] = (JSAMPLE) i; + table += CENTERJSAMPLE; /* Point to where post-IDCT table starts */ + /* End of simple table, rest of first half of post-IDCT table */ + for (i = CENTERJSAMPLE; i < 2*(MAXJSAMPLE+1); i++) + table[i] = MAXJSAMPLE; + /* Second half of post-IDCT table */ + MEMZERO(table + (2 * (MAXJSAMPLE+1)), + (2 * (MAXJSAMPLE+1) - CENTERJSAMPLE) * SIZEOF(JSAMPLE)); + MEMCOPY(table + (4 * (MAXJSAMPLE+1) - CENTERJSAMPLE), + cinfo->sample_range_limit, CENTERJSAMPLE * SIZEOF(JSAMPLE)); +} + + +/* + * Master selection of decompression modules. + * This is done once at jpeg_start_decompress time. We determine + * which modules will be used and give them appropriate initialization calls. + * We also initialize the decompressor input side to begin consuming data. + * + * Since jpeg_read_header has finished, we know what is in the SOF + * and (first) SOS markers. We also have all the application parameter + * settings. + */ + +LOCAL(void) +master_selection (j_decompress_ptr cinfo) +{ + my_master_ptr master = (my_master_ptr) cinfo->master; + long samplesperrow; + JDIMENSION jd_samplesperrow; + + /* Initialize dimensions and other stuff */ + jpeg_calc_output_dimensions(cinfo); + prepare_range_limit_table(cinfo); + + /* Width of an output scanline must be representable as JDIMENSION. */ + samplesperrow = (long) cinfo->output_width * (long) cinfo->out_color_components; + jd_samplesperrow = (JDIMENSION) samplesperrow; + if ((long) jd_samplesperrow != samplesperrow) + ERREXIT(cinfo, JERR_WIDTH_OVERFLOW); + + /* Initialize my private state */ + master->pass_number = 0; + master->using_merged_upsample = use_merged_upsample(cinfo); + + /* Color quantizer selection */ + master->quantizer_1pass = NULL; + master->quantizer_2pass = NULL; + /* No mode changes if not using buffered-image mode. */ + if (! cinfo->quantize_colors || ! cinfo->buffered_image) { + cinfo->enable_1pass_quant = FALSE; + cinfo->enable_external_quant = FALSE; + cinfo->enable_2pass_quant = FALSE; + } + if (cinfo->quantize_colors) { + if (cinfo->raw_data_out) + ERREXIT(cinfo, JERR_NOTIMPL); + /* 2-pass quantizer only works in 3-component color space. */ + if (cinfo->out_color_components != 3) { + cinfo->enable_1pass_quant = TRUE; + cinfo->enable_external_quant = FALSE; + cinfo->enable_2pass_quant = FALSE; + cinfo->colormap = NULL; + } else if (cinfo->colormap != NULL) { + cinfo->enable_external_quant = TRUE; + } else if (cinfo->two_pass_quantize) { + cinfo->enable_2pass_quant = TRUE; + } else { + cinfo->enable_1pass_quant = TRUE; + } + + if (cinfo->enable_1pass_quant) { +#ifdef QUANT_1PASS_SUPPORTED + jinit_1pass_quantizer(cinfo); + master->quantizer_1pass = cinfo->cquantize; +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } + + /* We use the 2-pass code to map to external colormaps. */ + if (cinfo->enable_2pass_quant || cinfo->enable_external_quant) { +#ifdef QUANT_2PASS_SUPPORTED + jinit_2pass_quantizer(cinfo); + master->quantizer_2pass = cinfo->cquantize; +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } + /* If both quantizers are initialized, the 2-pass one is left active; + * this is necessary for starting with quantization to an external map. + */ + } + + /* Post-processing: in particular, color conversion first */ + if (! cinfo->raw_data_out) { + if (master->using_merged_upsample) { +#ifdef UPSAMPLE_MERGING_SUPPORTED + jinit_merged_upsampler(cinfo); /* does color conversion too */ +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } else { + jinit_color_deconverter(cinfo); + jinit_upsampler(cinfo); + } + jinit_d_post_controller(cinfo, cinfo->enable_2pass_quant); + } + + /* Initialize principal buffer controllers. */ + if (! cinfo->raw_data_out) + jinit_d_main_controller(cinfo, FALSE /* never need full buffer here */); + + /* We can now tell the memory manager to allocate virtual arrays. */ + (*cinfo->mem->realize_virt_arrays) ((j_common_ptr) cinfo); + + /* Initialize input side of decompressor to consume first scan. */ + (*cinfo->inputctl->start_input_pass) (cinfo); + +#ifdef D_MULTISCAN_FILES_SUPPORTED + /* If jpeg_start_decompress will read the whole file, initialize + * progress monitoring appropriately. The input step is counted + * as one pass. + */ + if (cinfo->progress != NULL && ! cinfo->buffered_image && + cinfo->inputctl->has_multiple_scans) { + int nscans; + /* Estimate number of scans to set pass_limit. */ + if (cinfo->process == JPROC_PROGRESSIVE) { + /* Arbitrarily estimate 2 interleaved DC scans + 3 AC scans/component. */ + nscans = 2 + 3 * cinfo->num_components; + } else { + /* For a nonprogressive multiscan file, estimate 1 scan per component. */ + nscans = cinfo->num_components; + } + cinfo->progress->pass_counter = 0L; + cinfo->progress->pass_limit = (long) cinfo->total_iMCU_rows * nscans; + cinfo->progress->completed_passes = 0; + cinfo->progress->total_passes = (cinfo->enable_2pass_quant ? 3 : 2); + /* Count the input pass as done */ + master->pass_number++; + } +#endif /* D_MULTISCAN_FILES_SUPPORTED */ +} + + +/* + * Per-pass setup. + * This is called at the beginning of each output pass. We determine which + * modules will be active during this pass and give them appropriate + * start_pass calls. We also set is_dummy_pass to indicate whether this + * is a "real" output pass or a dummy pass for color quantization. + * (In the latter case, jdapistd.c will crank the pass to completion.) + */ + +METHODDEF(void) +prepare_for_output_pass (j_decompress_ptr cinfo) +{ + my_master_ptr master = (my_master_ptr) cinfo->master; + + if (master->pub.is_dummy_pass) { +#ifdef QUANT_2PASS_SUPPORTED + /* Final pass of 2-pass quantization */ + master->pub.is_dummy_pass = FALSE; + (*cinfo->cquantize->start_pass) (cinfo, FALSE); + (*cinfo->post->start_pass) (cinfo, JBUF_CRANK_DEST); + (*cinfo->main->start_pass) (cinfo, JBUF_CRANK_DEST); +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif /* QUANT_2PASS_SUPPORTED */ + } else { + if (cinfo->quantize_colors && cinfo->colormap == NULL) { + /* Select new quantization method */ + if (cinfo->two_pass_quantize && cinfo->enable_2pass_quant) { + cinfo->cquantize = master->quantizer_2pass; + master->pub.is_dummy_pass = TRUE; + } else if (cinfo->enable_1pass_quant) { + cinfo->cquantize = master->quantizer_1pass; + } else { + ERREXIT(cinfo, JERR_MODE_CHANGE); + } + } + (*cinfo->codec->start_output_pass) (cinfo); + if (! cinfo->raw_data_out) { + if (! master->using_merged_upsample) + (*cinfo->cconvert->start_pass) (cinfo); + (*cinfo->upsample->start_pass) (cinfo); + if (cinfo->quantize_colors) + (*cinfo->cquantize->start_pass) (cinfo, master->pub.is_dummy_pass); + (*cinfo->post->start_pass) (cinfo, + (master->pub.is_dummy_pass ? JBUF_SAVE_AND_PASS : JBUF_PASS_THRU)); + (*cinfo->main->start_pass) (cinfo, JBUF_PASS_THRU); + } + } + + /* Set up progress monitor's pass info if present */ + if (cinfo->progress != NULL) { + cinfo->progress->completed_passes = master->pass_number; + cinfo->progress->total_passes = master->pass_number + + (master->pub.is_dummy_pass ? 2 : 1); + /* In buffered-image mode, we assume one more output pass if EOI not + * yet reached, but no more passes if EOI has been reached. + */ + if (cinfo->buffered_image && ! cinfo->inputctl->eoi_reached) { + cinfo->progress->total_passes += (cinfo->enable_2pass_quant ? 2 : 1); + } + } +} + + +/* + * Finish up at end of an output pass. + */ + +METHODDEF(void) +finish_output_pass (j_decompress_ptr cinfo) +{ + my_master_ptr master = (my_master_ptr) cinfo->master; + + if (cinfo->quantize_colors) + (*cinfo->cquantize->finish_pass) (cinfo); + master->pass_number++; +} + + +#ifdef D_MULTISCAN_FILES_SUPPORTED + +/* + * Switch to a new external colormap between output passes. + */ + +GLOBAL(void) +jpeg_new_colormap (j_decompress_ptr cinfo) +{ + my_master_ptr master = (my_master_ptr) cinfo->master; + + /* Prevent application from calling me at wrong times */ + if (cinfo->global_state != DSTATE_BUFIMAGE) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + + if (cinfo->quantize_colors && cinfo->enable_external_quant && + cinfo->colormap != NULL) { + /* Select 2-pass quantizer for external colormap use */ + cinfo->cquantize = master->quantizer_2pass; + /* Notify quantizer of colormap change */ + (*cinfo->cquantize->new_color_map) (cinfo); + master->pub.is_dummy_pass = FALSE; /* just in case */ + } else + ERREXIT(cinfo, JERR_MODE_CHANGE); +} + +#endif /* D_MULTISCAN_FILES_SUPPORTED */ + + +/* + * Initialize master decompression control and select active modules. + * This is performed at the start of jpeg_start_decompress. + */ + +GLOBAL(void) +jinit_master_decompress (j_decompress_ptr cinfo) +{ + my_master_ptr master; + + master = (my_master_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_decomp_master)); + cinfo->master = (struct jpeg_decomp_master *) master; + master->pub.prepare_for_output_pass = prepare_for_output_pass; + master->pub.finish_output_pass = finish_output_pass; + + master->pub.is_dummy_pass = FALSE; + + master_selection(cinfo); +} diff --git a/dcmjpeg/libijg12/jdmerge.c b/dcmjpeg/libijg12/jdmerge.c new file mode 100644 index 00000000..4a827fd3 --- /dev/null +++ b/dcmjpeg/libijg12/jdmerge.c @@ -0,0 +1,400 @@ +/* + * jdmerge.c + * + * Copyright (C) 1994-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains code for merged upsampling/color conversion. + * + * This file combines functions from jdsample.c and jdcolor.c; + * read those files first to understand what's going on. + * + * When the chroma components are to be upsampled by simple replication + * (ie, box filtering), we can save some work in color conversion by + * calculating all the output pixels corresponding to a pair of chroma + * samples at one time. In the conversion equations + * R = Y + K1 * Cr + * G = Y + K2 * Cb + K3 * Cr + * B = Y + K4 * Cb + * only the Y term varies among the group of pixels corresponding to a pair + * of chroma samples, so the rest of the terms can be calculated just once. + * At typical sampling ratios, this eliminates half or three-quarters of the + * multiplications needed for color conversion. + * + * This file currently provides implementations for the following cases: + * YCbCr => RGB color conversion only. + * Sampling ratios of 2h1v or 2h2v. + * No scaling needed at upsample time. + * Corner-aligned (non-CCIR601) sampling alignment. + * Other special cases could be added, but in most applications these are + * the only common cases. (For uncommon cases we fall back on the more + * general code in jdsample.c and jdcolor.c.) + */ + +#define JPEG_INTERNALS +#include "jinclude12.h" +#include "jpeglib12.h" + +#ifdef UPSAMPLE_MERGING_SUPPORTED + + +/* Private subobject */ + +typedef struct { + struct jpeg_upsampler pub; /* public fields */ + + /* Pointer to routine to do actual upsampling/conversion of one row group */ + JMETHOD(void, upmethod, (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr, + JSAMPARRAY output_buf)); + + /* Private state for YCC->RGB conversion */ + int * Cr_r_tab; /* => table for Cr to R conversion */ + int * Cb_b_tab; /* => table for Cb to B conversion */ + IJG_INT32 * Cr_g_tab; /* => table for Cr to G conversion */ + IJG_INT32 * Cb_g_tab; /* => table for Cb to G conversion */ + + /* For 2:1 vertical sampling, we produce two output rows at a time. + * We need a "spare" row buffer to hold the second output row if the + * application provides just a one-row buffer; we also use the spare + * to discard the dummy last row if the image height is odd. + */ + JSAMPROW spare_row; + boolean spare_full; /* T if spare buffer is occupied */ + + JDIMENSION out_row_width; /* samples per output row */ + JDIMENSION rows_to_go; /* counts rows remaining in image */ +} my_upsampler; + +typedef my_upsampler * my_upsample_ptr; + +#define SCALEBITS 16 /* speediest right-shift on some machines */ +#define ONE_HALF ((IJG_INT32) 1 << (SCALEBITS-1)) +#define FIX(x) ((IJG_INT32) ((x) * (1L<RGB colorspace conversion. + * This is taken directly from jdcolor.c; see that file for more info. + */ + +LOCAL(void) +build_ycc_rgb_table (j_decompress_ptr cinfo) +{ + my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; + int i; + IJG_INT32 x; + SHIFT_TEMPS + + upsample->Cr_r_tab = (int *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (MAXJSAMPLE+1) * SIZEOF(int)); + upsample->Cb_b_tab = (int *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (MAXJSAMPLE+1) * SIZEOF(int)); + upsample->Cr_g_tab = (IJG_INT32 *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (MAXJSAMPLE+1) * SIZEOF(IJG_INT32)); + upsample->Cb_g_tab = (IJG_INT32 *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (MAXJSAMPLE+1) * SIZEOF(IJG_INT32)); + + for (i = 0, x = -CENTERJSAMPLE; i <= MAXJSAMPLE; i++, x++) { + /* i is the actual input pixel value, in the range 0..MAXJSAMPLE */ + /* The Cb or Cr value we are thinking of is x = i - CENTERJSAMPLE */ + /* Cr=>R value is nearest int to 1.40200 * x */ + upsample->Cr_r_tab[i] = (int) + RIGHT_SHIFT(FIX(1.40200) * x + ONE_HALF, SCALEBITS); + /* Cb=>B value is nearest int to 1.77200 * x */ + upsample->Cb_b_tab[i] = (int) + RIGHT_SHIFT(FIX(1.77200) * x + ONE_HALF, SCALEBITS); + /* Cr=>G value is scaled-up -0.71414 * x */ + upsample->Cr_g_tab[i] = (- FIX(0.71414)) * x; + /* Cb=>G value is scaled-up -0.34414 * x */ + /* We also add in ONE_HALF so that need not do it in inner loop */ + upsample->Cb_g_tab[i] = (- FIX(0.34414)) * x + ONE_HALF; + } +} + + +/* + * Initialize for an upsampling pass. + */ + +METHODDEF(void) +start_pass_merged_upsample (j_decompress_ptr cinfo) +{ + my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; + + /* Mark the spare buffer empty */ + upsample->spare_full = FALSE; + /* Initialize total-height counter for detecting bottom of image */ + upsample->rows_to_go = cinfo->output_height; +} + + +/* + * Control routine to do upsampling (and color conversion). + * + * The control routine just handles the row buffering considerations. + */ + +METHODDEF(void) +merged_2v_upsample (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail) +/* 2:1 vertical sampling case: may need a spare row. */ +{ + my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; + JSAMPROW work_ptrs[2]; + JDIMENSION num_rows; /* number of rows returned to caller */ + + if (upsample->spare_full) { + /* If we have a spare row saved from a previous cycle, just return it. */ + jcopy_sample_rows(& upsample->spare_row, 0, output_buf + *out_row_ctr, 0, + 1, upsample->out_row_width); + num_rows = 1; + upsample->spare_full = FALSE; + } else { + /* Figure number of rows to return to caller. */ + num_rows = 2; + /* Not more than the distance to the end of the image. */ + if (num_rows > upsample->rows_to_go) + num_rows = upsample->rows_to_go; + /* And not more than what the client can accept: */ + out_rows_avail -= *out_row_ctr; + if (num_rows > out_rows_avail) + num_rows = out_rows_avail; + /* Create output pointer array for upsampler. */ + work_ptrs[0] = output_buf[*out_row_ctr]; + if (num_rows > 1) { + work_ptrs[1] = output_buf[*out_row_ctr + 1]; + } else { + work_ptrs[1] = upsample->spare_row; + upsample->spare_full = TRUE; + } + /* Now do the upsampling. */ + (*upsample->upmethod) (cinfo, input_buf, *in_row_group_ctr, work_ptrs); + } + + /* Adjust counts */ + *out_row_ctr += num_rows; + upsample->rows_to_go -= num_rows; + /* When the buffer is emptied, declare this input row group consumed */ + if (! upsample->spare_full) + (*in_row_group_ctr)++; +} + + +METHODDEF(void) +merged_1v_upsample (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail) +/* 1:1 vertical sampling case: much easier, never need a spare row. */ +{ + my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; + + /* Just do the upsampling. */ + (*upsample->upmethod) (cinfo, input_buf, *in_row_group_ctr, + output_buf + *out_row_ctr); + /* Adjust counts */ + (*out_row_ctr)++; + (*in_row_group_ctr)++; +} + + +/* + * These are the routines invoked by the control routines to do + * the actual upsampling/conversion. One row group is processed per call. + * + * Note: since we may be writing directly into application-supplied buffers, + * we have to be honest about the output width; we can't assume the buffer + * has been rounded up to an even width. + */ + + +/* + * Upsample and color convert for the case of 2:1 horizontal and 1:1 vertical. + */ + +METHODDEF(void) +h2v1_merged_upsample (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr, + JSAMPARRAY output_buf) +{ + my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; + register int y, cred, cgreen, cblue; + int cb, cr; + register JSAMPROW outptr; + JSAMPROW inptr0, inptr1, inptr2; + JDIMENSION col; + /* copy these pointers into registers if possible */ + register JSAMPLE * range_limit = cinfo->sample_range_limit; + int * Crrtab = upsample->Cr_r_tab; + int * Cbbtab = upsample->Cb_b_tab; + IJG_INT32 * Crgtab = upsample->Cr_g_tab; + IJG_INT32 * Cbgtab = upsample->Cb_g_tab; + SHIFT_TEMPS + + inptr0 = input_buf[0][in_row_group_ctr]; + inptr1 = input_buf[1][in_row_group_ctr]; + inptr2 = input_buf[2][in_row_group_ctr]; + outptr = output_buf[0]; + /* Loop for each pair of output pixels */ + for (col = cinfo->output_width >> 1; col > 0; col--) { + /* Do the chroma part of the calculation */ + cb = GETJSAMPLE(*inptr1++); + cr = GETJSAMPLE(*inptr2++); + cred = Crrtab[cr]; + cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS); + cblue = Cbbtab[cb]; + /* Fetch 2 Y values and emit 2 pixels */ + y = GETJSAMPLE(*inptr0++); + outptr[RGB_RED] = range_limit[y + cred]; + outptr[RGB_GREEN] = range_limit[y + cgreen]; + outptr[RGB_BLUE] = range_limit[y + cblue]; + outptr += RGB_PIXELSIZE; + y = GETJSAMPLE(*inptr0++); + outptr[RGB_RED] = range_limit[y + cred]; + outptr[RGB_GREEN] = range_limit[y + cgreen]; + outptr[RGB_BLUE] = range_limit[y + cblue]; + outptr += RGB_PIXELSIZE; + } + /* If image width is odd, do the last output column separately */ + if (cinfo->output_width & 1) { + cb = GETJSAMPLE(*inptr1); + cr = GETJSAMPLE(*inptr2); + cred = Crrtab[cr]; + cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS); + cblue = Cbbtab[cb]; + y = GETJSAMPLE(*inptr0); + outptr[RGB_RED] = range_limit[y + cred]; + outptr[RGB_GREEN] = range_limit[y + cgreen]; + outptr[RGB_BLUE] = range_limit[y + cblue]; + } +} + + +/* + * Upsample and color convert for the case of 2:1 horizontal and 2:1 vertical. + */ + +METHODDEF(void) +h2v2_merged_upsample (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr, + JSAMPARRAY output_buf) +{ + my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; + register int y, cred, cgreen, cblue; + int cb, cr; + register JSAMPROW outptr0, outptr1; + JSAMPROW inptr00, inptr01, inptr1, inptr2; + JDIMENSION col; + /* copy these pointers into registers if possible */ + register JSAMPLE * range_limit = cinfo->sample_range_limit; + int * Crrtab = upsample->Cr_r_tab; + int * Cbbtab = upsample->Cb_b_tab; + IJG_INT32 * Crgtab = upsample->Cr_g_tab; + IJG_INT32 * Cbgtab = upsample->Cb_g_tab; + SHIFT_TEMPS + + inptr00 = input_buf[0][in_row_group_ctr*2]; + inptr01 = input_buf[0][in_row_group_ctr*2 + 1]; + inptr1 = input_buf[1][in_row_group_ctr]; + inptr2 = input_buf[2][in_row_group_ctr]; + outptr0 = output_buf[0]; + outptr1 = output_buf[1]; + /* Loop for each group of output pixels */ + for (col = cinfo->output_width >> 1; col > 0; col--) { + /* Do the chroma part of the calculation */ + cb = GETJSAMPLE(*inptr1++); + cr = GETJSAMPLE(*inptr2++); + cred = Crrtab[cr]; + cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS); + cblue = Cbbtab[cb]; + /* Fetch 4 Y values and emit 4 pixels */ + y = GETJSAMPLE(*inptr00++); + outptr0[RGB_RED] = range_limit[y + cred]; + outptr0[RGB_GREEN] = range_limit[y + cgreen]; + outptr0[RGB_BLUE] = range_limit[y + cblue]; + outptr0 += RGB_PIXELSIZE; + y = GETJSAMPLE(*inptr00++); + outptr0[RGB_RED] = range_limit[y + cred]; + outptr0[RGB_GREEN] = range_limit[y + cgreen]; + outptr0[RGB_BLUE] = range_limit[y + cblue]; + outptr0 += RGB_PIXELSIZE; + y = GETJSAMPLE(*inptr01++); + outptr1[RGB_RED] = range_limit[y + cred]; + outptr1[RGB_GREEN] = range_limit[y + cgreen]; + outptr1[RGB_BLUE] = range_limit[y + cblue]; + outptr1 += RGB_PIXELSIZE; + y = GETJSAMPLE(*inptr01++); + outptr1[RGB_RED] = range_limit[y + cred]; + outptr1[RGB_GREEN] = range_limit[y + cgreen]; + outptr1[RGB_BLUE] = range_limit[y + cblue]; + outptr1 += RGB_PIXELSIZE; + } + /* If image width is odd, do the last output column separately */ + if (cinfo->output_width & 1) { + cb = GETJSAMPLE(*inptr1); + cr = GETJSAMPLE(*inptr2); + cred = Crrtab[cr]; + cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS); + cblue = Cbbtab[cb]; + y = GETJSAMPLE(*inptr00); + outptr0[RGB_RED] = range_limit[y + cred]; + outptr0[RGB_GREEN] = range_limit[y + cgreen]; + outptr0[RGB_BLUE] = range_limit[y + cblue]; + y = GETJSAMPLE(*inptr01); + outptr1[RGB_RED] = range_limit[y + cred]; + outptr1[RGB_GREEN] = range_limit[y + cgreen]; + outptr1[RGB_BLUE] = range_limit[y + cblue]; + } +} + + +/* + * Module initialization routine for merged upsampling/color conversion. + * + * NB: this is called under the conditions determined by use_merged_upsample() + * in jdmaster.c. That routine MUST correspond to the actual capabilities + * of this module; no safety checks are made here. + */ + +GLOBAL(void) +jinit_merged_upsampler (j_decompress_ptr cinfo) +{ + my_upsample_ptr upsample; + + upsample = (my_upsample_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_upsampler)); + cinfo->upsample = (struct jpeg_upsampler *) upsample; + upsample->pub.start_pass = start_pass_merged_upsample; + upsample->pub.need_context_rows = FALSE; + + upsample->out_row_width = cinfo->output_width * (JDIMENSION)cinfo->out_color_components; + + if (cinfo->max_v_samp_factor == 2) { + upsample->pub.upsample = merged_2v_upsample; + upsample->upmethod = h2v2_merged_upsample; + /* Allocate a spare row buffer */ + upsample->spare_row = (JSAMPROW) + (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (size_t) (upsample->out_row_width * SIZEOF(JSAMPLE))); + } else { + upsample->pub.upsample = merged_1v_upsample; + upsample->upmethod = h2v1_merged_upsample; + /* No spare row needed */ + upsample->spare_row = NULL; + } + + build_ycc_rgb_table(cinfo); +} + +#endif /* UPSAMPLE_MERGING_SUPPORTED */ diff --git a/dcmjpeg/libijg12/jdphuff.c b/dcmjpeg/libijg12/jdphuff.c new file mode 100644 index 00000000..5ed17320 --- /dev/null +++ b/dcmjpeg/libijg12/jdphuff.c @@ -0,0 +1,675 @@ +/* + * jdphuff.c + * + * Copyright (C) 1995-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains Huffman entropy decoding routines for progressive JPEG. + * + * Much of the complexity here has to do with supporting input suspension. + * If the data source module demands suspension, we want to be able to back + * up to the start of the current MCU. To do this, we copy state variables + * into local working storage, and update them back to the permanent + * storage only upon successful completion of an MCU. + */ + +#define JPEG_INTERNALS +#include "jinclude12.h" +#include "jpeglib12.h" +#include "jlossy12.h" /* Private declarations for lossy subsystem */ +#include "jdhuff12.h" /* Declarations shared with jd*huff.c */ + + +#ifdef D_PROGRESSIVE_SUPPORTED + +/* + * Private entropy decoder object for progressive Huffman decoding. + * + * The savable_state subrecord contains fields that change within an MCU, + * but must not be updated permanently until we complete the MCU. + */ + +typedef struct { + unsigned int EOBRUN; /* remaining EOBs in EOBRUN */ + int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */ +} savable_state; + +/* This macro is to work around compilers with missing or broken + * structure assignment. You'll need to fix this code if you have + * such a compiler and you change MAX_COMPS_IN_SCAN. + */ + +#ifndef NO_STRUCT_ASSIGN +#define ASSIGN_STATE(dest,src) ((dest) = (src)) +#else +#if MAX_COMPS_IN_SCAN == 4 +#define ASSIGN_STATE(dest,src) \ + ((dest).EOBRUN = (src).EOBRUN, \ + (dest).last_dc_val[0] = (src).last_dc_val[0], \ + (dest).last_dc_val[1] = (src).last_dc_val[1], \ + (dest).last_dc_val[2] = (src).last_dc_val[2], \ + (dest).last_dc_val[3] = (src).last_dc_val[3]) +#endif +#endif + + +typedef struct { + huffd_common_fields; /* Fields shared with other entropy decoders */ + + /* These fields are loaded into local variables at start of each MCU. + * In case of suspension, we exit WITHOUT updating them. + */ + savable_state saved; /* Other state at start of MCU */ + + /* These fields are NOT loaded into local working state. */ + unsigned int restarts_to_go; /* MCUs left in this restart interval */ + + /* Pointers to derived tables (these workspaces have image lifespan) */ + d_derived_tbl * derived_tbls[NUM_HUFF_TBLS]; + + d_derived_tbl * ac_derived_tbl; /* active table during an AC scan */ +} phuff_entropy_decoder; + +typedef phuff_entropy_decoder * phuff_entropy_ptr; + +/* Forward declarations */ +METHODDEF(boolean) decode_mcu_DC_first JPP((j_decompress_ptr cinfo, + JBLOCKROW *MCU_data)); +METHODDEF(boolean) decode_mcu_AC_first JPP((j_decompress_ptr cinfo, + JBLOCKROW *MCU_data)); +METHODDEF(boolean) decode_mcu_DC_refine JPP((j_decompress_ptr cinfo, + JBLOCKROW *MCU_data)); +METHODDEF(boolean) decode_mcu_AC_refine JPP((j_decompress_ptr cinfo, + JBLOCKROW *MCU_data)); + + +/* + * Initialize for a Huffman-compressed scan. + */ + +METHODDEF(void) +start_pass_phuff_decoder (j_decompress_ptr cinfo) +{ + j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec; + phuff_entropy_ptr entropy = (phuff_entropy_ptr) lossyd->entropy_private; + boolean is_DC_band, bad; + int ci, coefi, tbl; + int *coef_bit_ptr; + jpeg_component_info * compptr; + + is_DC_band = (cinfo->Ss == 0); + + /* Validate scan parameters */ + bad = FALSE; + if (is_DC_band) { + if (cinfo->Se != 0) + bad = TRUE; + } else { + /* need not check Ss/Se < 0 since they came from unsigned bytes */ + if (cinfo->Ss > cinfo->Se || cinfo->Se >= DCTSIZE2) + bad = TRUE; + /* AC scans may have only one component */ + if (cinfo->comps_in_scan != 1) + bad = TRUE; + } + if (cinfo->Ah != 0) { + /* Successive approximation refinement scan: must have Al = Ah-1. */ + if (cinfo->Al != cinfo->Ah-1) + bad = TRUE; + } + if (cinfo->Al > 13) /* need not check for < 0 */ + bad = TRUE; + /* Arguably the maximum Al value should be less than 13 for 8-bit precision, + * but the spec doesn't say so, and we try to be liberal about what we + * accept. Note: large Al values could result in out-of-range DC + * coefficients during early scans, leading to bizarre displays due to + * overflows in the IDCT math. But we won't crash. + */ + if (bad) + ERREXIT4(cinfo, JERR_BAD_PROGRESSION, + cinfo->Ss, cinfo->Se, cinfo->Ah, cinfo->Al); + /* Update progression status, and verify that scan order is legal. + * Note that inter-scan inconsistencies are treated as warnings + * not fatal errors ... not clear if this is right way to behave. + */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + int cindex = cinfo->cur_comp_info[ci]->component_index; + coef_bit_ptr = & cinfo->coef_bits[cindex][0]; + if (!is_DC_band && coef_bit_ptr[0] < 0) /* AC without prior DC scan */ + WARNMS2(cinfo, JWRN_BOGUS_PROGRESSION, cindex, 0); + for (coefi = cinfo->Ss; coefi <= cinfo->Se; coefi++) { + int expected = (coef_bit_ptr[coefi] < 0) ? 0 : coef_bit_ptr[coefi]; + if (cinfo->Ah != expected) + WARNMS2(cinfo, JWRN_BOGUS_PROGRESSION, cindex, coefi); + coef_bit_ptr[coefi] = cinfo->Al; + } + } + + /* Select MCU decoding routine */ + if (cinfo->Ah == 0) { + if (is_DC_band) + lossyd->entropy_decode_mcu = decode_mcu_DC_first; + else + lossyd->entropy_decode_mcu = decode_mcu_AC_first; + } else { + if (is_DC_band) + lossyd->entropy_decode_mcu = decode_mcu_DC_refine; + else + lossyd->entropy_decode_mcu = decode_mcu_AC_refine; + } + + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + /* Make sure requested tables are present, and compute derived tables. + * We may build same derived table more than once, but it's not expensive. + */ + if (is_DC_band) { + if (cinfo->Ah == 0) { /* DC refinement needs no table */ + tbl = compptr->dc_tbl_no; + jpeg_make_d_derived_tbl(cinfo, TRUE, tbl, + & entropy->derived_tbls[tbl]); + } + } else { + tbl = compptr->ac_tbl_no; + jpeg_make_d_derived_tbl(cinfo, FALSE, tbl, + & entropy->derived_tbls[tbl]); + /* remember the single active table */ + entropy->ac_derived_tbl = entropy->derived_tbls[tbl]; + } + /* Initialize DC predictions to 0 */ + entropy->saved.last_dc_val[ci] = 0; + } + + /* Initialize bitread state variables */ + entropy->bitstate.bits_left = 0; + entropy->bitstate.get_buffer = 0; /* unnecessary, but keeps Purify quiet */ + entropy->insufficient_data = FALSE; + + /* Initialize private state variables */ + entropy->saved.EOBRUN = 0; + + /* Initialize restart counter */ + entropy->restarts_to_go = cinfo->restart_interval; +} + + +/* + * Figure F.12: extend sign bit. + * On some machines, a shift and add will be faster than a table lookup. + */ + +#ifdef AVOID_TABLES + +#define HUFF_EXTEND(x,s) ((x) < (1<<((s)-1)) ? (x) + (((-1)<<(s)) + 1) : (x)) + +#else + +#define HUFF_EXTEND(x,s) ((x) < extend_test[s] ? (x) + extend_offset[s] : (x)) + +static const int extend_test[16] = /* entry n is 2**(n-1) */ + { 0, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080, + 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000 }; + +static const int extend_offset[16] = /* entry n is (-1 << n) + 1 */ + { 0, ((-1)<<1) + 1, ((-1)<<2) + 1, ((-1)<<3) + 1, ((-1)<<4) + 1, + ((-1)<<5) + 1, ((-1)<<6) + 1, ((-1)<<7) + 1, ((-1)<<8) + 1, + ((-1)<<9) + 1, ((-1)<<10) + 1, ((-1)<<11) + 1, ((-1)<<12) + 1, + ((-1)<<13) + 1, ((-1)<<14) + 1, ((-1)<<15) + 1 }; + +#endif /* AVOID_TABLES */ + + +/* + * Check for a restart marker & resynchronize decoder. + * Returns FALSE if must suspend. + */ + +LOCAL(boolean) +process_restart (j_decompress_ptr cinfo) +{ + j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec; + phuff_entropy_ptr entropy = (phuff_entropy_ptr) lossyd->entropy_private; + int ci; + + /* Throw away any unused bits remaining in bit buffer; */ + /* include any full bytes in next_marker's count of discarded bytes */ + cinfo->marker->discarded_bytes += (unsigned int)(entropy->bitstate.bits_left / 8); + entropy->bitstate.bits_left = 0; + + /* Advance past the RSTn marker */ + if (! (*cinfo->marker->read_restart_marker) (cinfo)) + return FALSE; + + /* Re-initialize DC predictions to 0 */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) + entropy->saved.last_dc_val[ci] = 0; + /* Re-init EOB run count, too */ + entropy->saved.EOBRUN = 0; + + /* Reset restart counter */ + entropy->restarts_to_go = cinfo->restart_interval; + + /* Reset out-of-data flag, unless read_restart_marker left us smack up + * against a marker. In that case we will end up treating the next data + * segment as empty, and we can avoid producing bogus output pixels by + * leaving the flag set. + */ + if (cinfo->unread_marker == 0) + entropy->insufficient_data = FALSE; + + return TRUE; +} + + +/* + * Huffman MCU decoding. + * Each of these routines decodes and returns one MCU's worth of + * Huffman-compressed coefficients. + * The coefficients are reordered from zigzag order into natural array order, + * but are not dequantized. + * + * The i'th block of the MCU is stored into the block pointed to by + * MCU_data[i]. WE ASSUME THIS AREA IS INITIALLY ZEROED BY THE CALLER. + * + * We return FALSE if data source requested suspension. In that case no + * changes have been made to permanent state. (Exception: some output + * coefficients may already have been assigned. This is harmless for + * spectral selection, since we'll just re-assign them on the next call. + * Successive approximation AC refinement has to be more careful, however.) + */ + +/* + * MCU decoding for DC initial scan (either spectral selection, + * or first pass of successive approximation). + */ + +METHODDEF(boolean) +decode_mcu_DC_first (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) +{ + j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec; + phuff_entropy_ptr entropy = (phuff_entropy_ptr) lossyd->entropy_private; + int Al = cinfo->Al; + register int s, r; + int blkn, ci; + JBLOCKROW block; + BITREAD_STATE_VARS; + savable_state state; + d_derived_tbl * tbl; + jpeg_component_info * compptr; + + /* Process restart marker if needed; may have to suspend */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) + if (! process_restart(cinfo)) + return FALSE; + } + + /* If we've run out of data, just leave the MCU set to zeroes. + * This way, we return uniform gray for the remainder of the segment. + */ + if (! entropy->insufficient_data) { + + /* Load up working state */ + BITREAD_LOAD_STATE(cinfo,entropy->bitstate); + ASSIGN_STATE(state, entropy->saved); + + /* Outer loop handles each block in the MCU */ + + for (blkn = 0; blkn < cinfo->data_units_in_MCU; blkn++) { + block = MCU_data[blkn]; + ci = cinfo->MCU_membership[blkn]; + compptr = cinfo->cur_comp_info[ci]; + tbl = entropy->derived_tbls[compptr->dc_tbl_no]; + + /* Decode a single block's worth of coefficients */ + + /* Section F.2.2.1: decode the DC coefficient difference */ + HUFF_DECODE(s, br_state, tbl, return FALSE, label1); + if (s) { + CHECK_BIT_BUFFER(br_state, s, return FALSE); + r = GET_BITS(s); + s = HUFF_EXTEND(r, s); + } + + /* Convert DC difference to actual value, update last_dc_val */ + s += state.last_dc_val[ci]; + state.last_dc_val[ci] = s; + /* Scale and output the coefficient (assumes jpeg_natural_order[0]=0) */ + (*block)[0] = (JCOEF) (s << Al); + } + + /* Completed MCU, so update state */ + BITREAD_SAVE_STATE(cinfo,entropy->bitstate); + ASSIGN_STATE(entropy->saved, state); + } + + /* Account for restart interval (no-op if not using restarts) */ + entropy->restarts_to_go--; + + return TRUE; +} + + +/* + * MCU decoding for AC initial scan (either spectral selection, + * or first pass of successive approximation). + */ + +METHODDEF(boolean) +decode_mcu_AC_first (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) +{ + j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec; + phuff_entropy_ptr entropy = (phuff_entropy_ptr) lossyd->entropy_private; + int Se = cinfo->Se; + int Al = cinfo->Al; + register int s, k, r; + unsigned int EOBRUN; + JBLOCKROW block; + BITREAD_STATE_VARS; + d_derived_tbl * tbl; + + /* Process restart marker if needed; may have to suspend */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) + if (! process_restart(cinfo)) + return FALSE; + } + + /* If we've run out of data, just leave the MCU set to zeroes. + * This way, we return uniform gray for the remainder of the segment. + */ + if (! entropy->insufficient_data) { + + /* Load up working state. + * We can avoid loading/saving bitread state if in an EOB run. + */ + EOBRUN = entropy->saved.EOBRUN; /* only part of saved state we need */ + + /* There is always only one block per MCU */ + + if (EOBRUN > 0) /* if it's a band of zeroes... */ + EOBRUN--; /* ...process it now (we do nothing) */ + else { + BITREAD_LOAD_STATE(cinfo,entropy->bitstate); + block = MCU_data[0]; + tbl = entropy->ac_derived_tbl; + + for (k = cinfo->Ss; k <= Se; k++) { + HUFF_DECODE(s, br_state, tbl, return FALSE, label2); + r = s >> 4; + s &= 15; + if (s) { + k += r; + CHECK_BIT_BUFFER(br_state, s, return FALSE); + r = GET_BITS(s); + s = HUFF_EXTEND(r, s); + /* Scale and output coefficient in natural (dezigzagged) order */ + (*block)[jpeg_natural_order[k]] = (JCOEF) (s << Al); + } else { + if (r == 15) { /* ZRL */ + k += 15; /* skip 15 zeroes in band */ + } else { /* EOBr, run length is 2^r + appended bits */ + EOBRUN = (unsigned int)(1 << r); + if (r) { /* EOBr, r > 0 */ + CHECK_BIT_BUFFER(br_state, r, return FALSE); + r = GET_BITS(r); + EOBRUN += (unsigned int)r; + } + EOBRUN--; /* this band is processed at this moment */ + break; /* force end-of-band */ + } + } + } + + BITREAD_SAVE_STATE(cinfo,entropy->bitstate); + } + + /* Completed MCU, so update state */ + entropy->saved.EOBRUN = EOBRUN; /* only part of saved state we need */ + } + + /* Account for restart interval (no-op if not using restarts) */ + entropy->restarts_to_go--; + + return TRUE; +} + + +/* + * MCU decoding for DC successive approximation refinement scan. + * Note: we assume such scans can be multi-component, although the spec + * is not very clear on the point. + */ + +METHODDEF(boolean) +decode_mcu_DC_refine (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) +{ + j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec; + phuff_entropy_ptr entropy = (phuff_entropy_ptr) lossyd->entropy_private; + int p1 = 1 << cinfo->Al; /* 1 in the bit position being coded */ + int blkn; + JBLOCKROW block; + BITREAD_STATE_VARS; + + /* Process restart marker if needed; may have to suspend */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) + if (! process_restart(cinfo)) + return FALSE; + } + + /* Not worth the cycles to check insufficient_data here, + * since we will not change the data anyway if we read zeroes. + */ + + /* Load up working state */ + BITREAD_LOAD_STATE(cinfo,entropy->bitstate); + + /* Outer loop handles each block in the MCU */ + + for (blkn = 0; blkn < cinfo->data_units_in_MCU; blkn++) { + block = MCU_data[blkn]; + + /* Encoded data is simply the next bit of the two's-complement DC value */ + CHECK_BIT_BUFFER(br_state, 1, return FALSE); + if (GET_BITS(1)) + (*block)[0] |= (JCOEF)p1; + /* Note: since we use |=, repeating the assignment later is safe */ + } + + /* Completed MCU, so update state */ + BITREAD_SAVE_STATE(cinfo,entropy->bitstate); + + /* Account for restart interval (no-op if not using restarts) */ + entropy->restarts_to_go--; + + return TRUE; +} + + +/* + * MCU decoding for AC successive approximation refinement scan. + */ + +METHODDEF(boolean) +decode_mcu_AC_refine (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) +{ + j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec; + phuff_entropy_ptr entropy = (phuff_entropy_ptr) lossyd->entropy_private; + int Se = cinfo->Se; + int p1 = 1 << cinfo->Al; /* 1 in the bit position being coded */ + int m1 = (-1) << cinfo->Al; /* -1 in the bit position being coded */ + register int s, k, r; + unsigned int EOBRUN; + JBLOCKROW block; + JCOEFPTR thiscoef; + BITREAD_STATE_VARS; + d_derived_tbl * tbl; + int num_newnz; + int newnz_pos[DCTSIZE2]; + + /* Process restart marker if needed; may have to suspend */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) + if (! process_restart(cinfo)) + return FALSE; + } + + /* If we've run out of data, don't modify the MCU. + */ + if (! entropy->insufficient_data) { + + /* Load up working state */ + BITREAD_LOAD_STATE(cinfo,entropy->bitstate); + EOBRUN = entropy->saved.EOBRUN; /* only part of saved state we need */ + + /* There is always only one block per MCU */ + block = MCU_data[0]; + tbl = entropy->ac_derived_tbl; + + /* If we are forced to suspend, we must undo the assignments to any newly + * nonzero coefficients in the block, because otherwise we'd get confused + * next time about which coefficients were already nonzero. + * But we need not undo addition of bits to already-nonzero coefficients; + * instead, we can test the current bit to see if we already did it. + */ + num_newnz = 0; + + /* initialize coefficient loop counter to start of band */ + k = cinfo->Ss; + + if (EOBRUN == 0) { + for (; k <= Se; k++) { + HUFF_DECODE(s, br_state, tbl, goto undoit, label3); + r = s >> 4; + s &= 15; + if (s) { + if (s != 1) /* size of new coef should always be 1 */ + WARNMS(cinfo, JWRN_HUFF_BAD_CODE); + CHECK_BIT_BUFFER(br_state, 1, goto undoit); + if (GET_BITS(1)) + s = p1; /* newly nonzero coef is positive */ + else + s = m1; /* newly nonzero coef is negative */ + } else { + if (r != 15) { + EOBRUN = (unsigned int)(1 << r); /* EOBr, run length is 2^r + appended bits */ + if (r) { + CHECK_BIT_BUFFER(br_state, r, goto undoit); + r = GET_BITS(r); + EOBRUN += (unsigned int)r; + } + break; /* rest of block is handled by EOB logic */ + } + /* note s = 0 for processing ZRL */ + } + /* Advance over already-nonzero coefs and r still-zero coefs, + * appending correction bits to the nonzeroes. A correction bit is 1 + * if the absolute value of the coefficient must be increased. + */ + do { + thiscoef = *block + jpeg_natural_order[k]; + if (*thiscoef != 0) { + CHECK_BIT_BUFFER(br_state, 1, goto undoit); + if (GET_BITS(1)) { + if ((*thiscoef & p1) == 0) { /* do nothing if already set it */ + if (*thiscoef >= 0) + *thiscoef = (JCOEF)(*thiscoef + p1); + else + *thiscoef = (JCOEF)(*thiscoef + m1); + } + } + } else { + if (--r < 0) + break; /* reached target zero coefficient */ + } + k++; + } while (k <= Se); + if (s) { + int pos = jpeg_natural_order[k]; + /* Output newly nonzero coefficient */ + (*block)[pos] = (JCOEF) s; + /* Remember its position in case we have to suspend */ + newnz_pos[num_newnz++] = pos; + } + } + } + + if (EOBRUN > 0) { + /* Scan any remaining coefficient positions after the end-of-band + * (the last newly nonzero coefficient, if any). Append a correction + * bit to each already-nonzero coefficient. A correction bit is 1 + * if the absolute value of the coefficient must be increased. + */ + for (; k <= Se; k++) { + thiscoef = *block + jpeg_natural_order[k]; + if (*thiscoef != 0) { + CHECK_BIT_BUFFER(br_state, 1, goto undoit); + if (GET_BITS(1)) { + if ((*thiscoef & p1) == 0) { /* do nothing if already changed it */ + if (*thiscoef >= 0) + *thiscoef = (JCOEF)(*thiscoef + p1); + else + *thiscoef = (JCOEF)(*thiscoef + m1); + } + } + } + } + /* Count one block completed in EOB run */ + EOBRUN--; + } + + /* Completed MCU, so update state */ + BITREAD_SAVE_STATE(cinfo,entropy->bitstate); + entropy->saved.EOBRUN = EOBRUN; /* only part of saved state we need */ + } + + /* Account for restart interval (no-op if not using restarts) */ + entropy->restarts_to_go--; + + return TRUE; + +undoit: + /* Re-zero any output coefficients that we made newly nonzero */ + while (num_newnz > 0) + (*block)[newnz_pos[--num_newnz]] = 0; + + return FALSE; +} + + +/* + * Module initialization routine for progressive Huffman entropy decoding. + */ + +GLOBAL(void) +jinit_phuff_decoder (j_decompress_ptr cinfo) +{ + j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec; + phuff_entropy_ptr entropy; + int *coef_bit_ptr; + int ci, i; + + entropy = (phuff_entropy_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(phuff_entropy_decoder)); + lossyd->entropy_private = (void *) entropy; + lossyd->entropy_start_pass = start_pass_phuff_decoder; + + /* Mark derived tables unallocated */ + for (i = 0; i < NUM_HUFF_TBLS; i++) { + entropy->derived_tbls[i] = NULL; + } + + /* Create progression status table */ + cinfo->coef_bits = (int (*)[DCTSIZE2]) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (size_t)cinfo->num_components*DCTSIZE2*SIZEOF(int)); + coef_bit_ptr = & cinfo->coef_bits[0][0]; + for (ci = 0; ci < cinfo->num_components; ci++) + for (i = 0; i < DCTSIZE2; i++) + *coef_bit_ptr++ = -1; +} + +#endif /* D_PROGRESSIVE_SUPPORTED */ diff --git a/dcmjpeg/libijg12/jdpostct.c b/dcmjpeg/libijg12/jdpostct.c new file mode 100644 index 00000000..c7f214be --- /dev/null +++ b/dcmjpeg/libijg12/jdpostct.c @@ -0,0 +1,290 @@ +/* + * jdpostct.c + * + * Copyright (C) 1994-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains the decompression postprocessing controller. + * This controller manages the upsampling, color conversion, and color + * quantization/reduction steps; specifically, it controls the buffering + * between upsample/color conversion and color quantization/reduction. + * + * If no color quantization/reduction is required, then this module has no + * work to do, and it just hands off to the upsample/color conversion code. + * An integrated upsample/convert/quantize process would replace this module + * entirely. + */ + +#define JPEG_INTERNALS +#include "jinclude12.h" +#include "jpeglib12.h" + + +/* Private buffer controller object */ + +typedef struct { + struct jpeg_d_post_controller pub; /* public fields */ + + /* Color quantization source buffer: this holds output data from + * the upsample/color conversion step to be passed to the quantizer. + * For two-pass color quantization, we need a full-image buffer; + * for one-pass operation, a strip buffer is sufficient. + */ + jvirt_sarray_ptr whole_image; /* virtual array, or NULL if one-pass */ + JSAMPARRAY buffer; /* strip buffer, or current strip of virtual */ + JDIMENSION strip_height; /* buffer size in rows */ + /* for two-pass mode only: */ + JDIMENSION starting_row; /* row # of first row in current strip */ + JDIMENSION next_row; /* index of next row to fill/empty in strip */ +} my_post_controller; + +typedef my_post_controller * my_post_ptr; + + +/* Forward declarations */ +METHODDEF(void) post_process_1pass + JPP((j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail)); +#ifdef QUANT_2PASS_SUPPORTED +METHODDEF(void) post_process_prepass + JPP((j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail)); +METHODDEF(void) post_process_2pass + JPP((j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail)); +#endif + + +/* + * Initialize for a processing pass. + */ + +METHODDEF(void) +start_pass_dpost (j_decompress_ptr cinfo, J_BUF_MODE pass_mode) +{ + my_post_ptr post = (my_post_ptr) cinfo->post; + + switch (pass_mode) { + case JBUF_PASS_THRU: + if (cinfo->quantize_colors) { + /* Single-pass processing with color quantization. */ + post->pub.post_process_data = post_process_1pass; + /* We could be doing buffered-image output before starting a 2-pass + * color quantization; in that case, jinit_d_post_controller did not + * allocate a strip buffer. Use the virtual-array buffer as workspace. + */ + if (post->buffer == NULL) { + post->buffer = (*cinfo->mem->access_virt_sarray) + ((j_common_ptr) cinfo, post->whole_image, + (JDIMENSION) 0, post->strip_height, TRUE); + } + } else { + /* For single-pass processing without color quantization, + * I have no work to do; just call the upsampler directly. + */ + post->pub.post_process_data = cinfo->upsample->upsample; + } + break; +#ifdef QUANT_2PASS_SUPPORTED + case JBUF_SAVE_AND_PASS: + /* First pass of 2-pass quantization */ + if (post->whole_image == NULL) + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + post->pub.post_process_data = post_process_prepass; + break; + case JBUF_CRANK_DEST: + /* Second pass of 2-pass quantization */ + if (post->whole_image == NULL) + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + post->pub.post_process_data = post_process_2pass; + break; +#endif /* QUANT_2PASS_SUPPORTED */ + default: + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + break; + } + post->starting_row = post->next_row = 0; +} + + +/* + * Process some data in the one-pass (strip buffer) case. + * This is used for color precision reduction as well as one-pass quantization. + */ + +METHODDEF(void) +post_process_1pass (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail) +{ + my_post_ptr post = (my_post_ptr) cinfo->post; + JDIMENSION num_rows, max_rows; + + /* Fill the buffer, but not more than what we can dump out in one go. */ + /* Note we rely on the upsampler to detect bottom of image. */ + max_rows = out_rows_avail - *out_row_ctr; + if (max_rows > post->strip_height) + max_rows = post->strip_height; + num_rows = 0; + (*cinfo->upsample->upsample) (cinfo, + input_buf, in_row_group_ctr, in_row_groups_avail, + post->buffer, &num_rows, max_rows); + /* Quantize and emit data. */ + (*cinfo->cquantize->color_quantize) (cinfo, + post->buffer, output_buf + *out_row_ctr, (int) num_rows); + *out_row_ctr += num_rows; +} + + +#ifdef QUANT_2PASS_SUPPORTED + +/* + * Process some data in the first pass of 2-pass quantization. + */ + +METHODDEF(void) +post_process_prepass (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail) +{ + my_post_ptr post = (my_post_ptr) cinfo->post; + JDIMENSION old_next_row, num_rows; + + /* Reposition virtual buffer if at start of strip. */ + if (post->next_row == 0) { + post->buffer = (*cinfo->mem->access_virt_sarray) + ((j_common_ptr) cinfo, post->whole_image, + post->starting_row, post->strip_height, TRUE); + } + + /* Upsample some data (up to a strip height's worth). */ + old_next_row = post->next_row; + (*cinfo->upsample->upsample) (cinfo, + input_buf, in_row_group_ctr, in_row_groups_avail, + post->buffer, &post->next_row, post->strip_height); + + /* Allow quantizer to scan new data. No data is emitted, */ + /* but we advance out_row_ctr so outer loop can tell when we're done. */ + if (post->next_row > old_next_row) { + num_rows = post->next_row - old_next_row; + (*cinfo->cquantize->color_quantize) (cinfo, post->buffer + old_next_row, + (JSAMPARRAY) NULL, (int) num_rows); + *out_row_ctr += num_rows; + } + + /* Advance if we filled the strip. */ + if (post->next_row >= post->strip_height) { + post->starting_row += post->strip_height; + post->next_row = 0; + } +} + + +/* + * Process some data in the second pass of 2-pass quantization. + */ + +METHODDEF(void) +post_process_2pass (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail) +{ + my_post_ptr post = (my_post_ptr) cinfo->post; + JDIMENSION num_rows, max_rows; + + /* Reposition virtual buffer if at start of strip. */ + if (post->next_row == 0) { + post->buffer = (*cinfo->mem->access_virt_sarray) + ((j_common_ptr) cinfo, post->whole_image, + post->starting_row, post->strip_height, FALSE); + } + + /* Determine number of rows to emit. */ + num_rows = post->strip_height - post->next_row; /* available in strip */ + max_rows = out_rows_avail - *out_row_ctr; /* available in output area */ + if (num_rows > max_rows) + num_rows = max_rows; + /* We have to check bottom of image here, can't depend on upsampler. */ + max_rows = cinfo->output_height - post->starting_row; + if (num_rows > max_rows) + num_rows = max_rows; + + /* Quantize and emit data. */ + (*cinfo->cquantize->color_quantize) (cinfo, + post->buffer + post->next_row, output_buf + *out_row_ctr, + (int) num_rows); + *out_row_ctr += num_rows; + + /* Advance if we filled the strip. */ + post->next_row += num_rows; + if (post->next_row >= post->strip_height) { + post->starting_row += post->strip_height; + post->next_row = 0; + } +} + +#endif /* QUANT_2PASS_SUPPORTED */ + + +/* + * Initialize postprocessing controller. + */ + +GLOBAL(void) +jinit_d_post_controller (j_decompress_ptr cinfo, boolean need_full_buffer) +{ + my_post_ptr post; + + post = (my_post_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_post_controller)); + cinfo->post = (struct jpeg_d_post_controller *) post; + post->pub.start_pass = start_pass_dpost; + post->whole_image = NULL; /* flag for no virtual arrays */ + post->buffer = NULL; /* flag for no strip buffer */ + + /* Create the quantization buffer, if needed */ + if (cinfo->quantize_colors) { + /* The buffer strip height is max_v_samp_factor, which is typically + * an efficient number of rows for upsampling to return. + * (In the presence of output rescaling, we might want to be smarter?) + */ + post->strip_height = (JDIMENSION) cinfo->max_v_samp_factor; + if (need_full_buffer) { + /* Two-pass color quantization: need full-image storage. */ + /* We round up the number of rows to a multiple of the strip height. */ +#ifdef QUANT_2PASS_SUPPORTED + post->whole_image = (*cinfo->mem->request_virt_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE, + cinfo->output_width * (JDIMENSION)cinfo->out_color_components, + (JDIMENSION) jround_up((long) cinfo->output_height, + (long) post->strip_height), + post->strip_height); +#else + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); +#endif /* QUANT_2PASS_SUPPORTED */ + } else { + /* One-pass color quantization: just make a strip buffer. */ + post->buffer = (*cinfo->mem->alloc_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + cinfo->output_width * (JDIMENSION)cinfo->out_color_components, + post->strip_height); + } + } +} diff --git a/dcmjpeg/libijg12/jdpred.c b/dcmjpeg/libijg12/jdpred.c new file mode 100644 index 00000000..066d5d53 --- /dev/null +++ b/dcmjpeg/libijg12/jdpred.c @@ -0,0 +1,263 @@ +/* + * jdpred.c + * + * Copyright (C) 1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains sample undifferencing (reconstruction) for lossless JPEG. + * + * In order to avoid paying the performance penalty of having to check the + * predictor being used and the row being processed for each call of the + * undifferencer, and to promote optimization, we have separate undifferencing + * functions for each case. + * + * We are able to avoid duplicating source code by implementing the predictors + * and undifferencers as macros. Each of the undifferencing functions are + * simply wrappers around an UNDIFFERENCE macro with the appropriate PREDICTOR + * macro passed as an argument. + */ + +#define JPEG_INTERNALS +#include "jinclude12.h" +#include "jpeglib12.h" +#include "jlossls12.h" /* Private declarations for lossless codec */ + + +#ifdef D_LOSSLESS_SUPPORTED + +/* Predictor for the first column of the first row: 2^(P-Pt-1) */ +#define INITIAL_PREDICTORx (1 << (cinfo->data_precision - cinfo->Al - 1)) + +/* Predictor for the first column of the remaining rows: Rb */ +#define INITIAL_PREDICTOR2 GETJSAMPLE(prev_row[0]) + + +/* + * 1-Dimensional undifferencer routine. + * + * This macro implements the 1-D horizontal predictor (1). INITIAL_PREDICTOR + * is used as the special case predictor for the first column, which must be + * either INITIAL_PREDICTOR2 or INITIAL_PREDICTORx. The remaining samples + * use PREDICTOR1. + * + * The reconstructed sample is supposed to be calculated modulo 2^16, so we + * logically AND the result with 0xFFFF. +*/ + +#define UNDIFFERENCE_1D(INITIAL_PREDICTOR) \ + unsigned int xindex; \ + int Ra; \ + \ + Ra = (diff_buf[0] + INITIAL_PREDICTOR) & 0xFFFF; \ + undiff_buf[0] = Ra; \ + \ + for (xindex = 1; xindex < width; xindex++) { \ + Ra = (diff_buf[xindex] + PREDICTOR1) & 0xFFFF; \ + undiff_buf[xindex] = Ra; \ + } + +/* + * 2-Dimensional undifferencer routine. + * + * This macro implements the 2-D horizontal predictors (#2-7). PREDICTOR2 is + * used as the special case predictor for the first column. The remaining + * samples use PREDICTOR, which is a function of Ra, Rb, Rc. + * + * Because prev_row and output_buf may point to the same storage area (in an + * interleaved image with Vi=1, for example), we must take care to buffer Rb/Rc + * before writing the current reconstructed sample value into output_buf. + * + * The reconstructed sample is supposed to be calculated modulo 2^16, so we + * logically AND the result with 0xFFFF. + */ + +#define UNDIFFERENCE_2D(PREDICTOR) \ + unsigned int xindex; \ + int Ra, Rb, Rc; \ + \ + Rb = GETJSAMPLE(prev_row[0]); \ + Ra = (diff_buf[0] + PREDICTOR2) & 0xFFFF; \ + undiff_buf[0] = Ra; \ + \ + for (xindex = 1; xindex < width; xindex++) { \ + Rc = Rb; \ + Rb = GETJSAMPLE(prev_row[xindex]); \ + Ra = (diff_buf[xindex] + PREDICTOR) & 0xFFFF; \ + undiff_buf[xindex] = Ra; \ + } + +#define JPEG_UNUSED(x) ((void)x) + +/* + * Undifferencers for the all rows but the first in a scan or restart interval. + * The first sample in the row is undifferenced using the vertical + * predictor (2). The rest of the samples are undifferenced using the + * predictor specified in the scan header. + */ + +METHODDEF(void) +jpeg_undifference1(j_decompress_ptr cinfo, int comp_index, + JDIFFROW diff_buf, JDIFFROW prev_row, + JDIFFROW undiff_buf, JDIMENSION width) +{ + UNDIFFERENCE_1D(INITIAL_PREDICTOR2); +} + +METHODDEF(void) +jpeg_undifference2(j_decompress_ptr cinfo, int comp_index, + JDIFFROW diff_buf, JDIFFROW prev_row, + JDIFFROW undiff_buf, JDIMENSION width) +{ + UNDIFFERENCE_2D(PREDICTOR2); + JPEG_UNUSED(Rc); + JPEG_UNUSED(Rb); +} + +METHODDEF(void) +jpeg_undifference3(j_decompress_ptr cinfo, int comp_index, + JDIFFROW diff_buf, JDIFFROW prev_row, + JDIFFROW undiff_buf, JDIMENSION width) +{ + UNDIFFERENCE_2D(PREDICTOR3); + JPEG_UNUSED(Rc); + JPEG_UNUSED(Rb); +} + +METHODDEF(void) +jpeg_undifference4(j_decompress_ptr cinfo, int comp_index, + JDIFFROW diff_buf, JDIFFROW prev_row, + JDIFFROW undiff_buf, JDIMENSION width) +{ + UNDIFFERENCE_2D(PREDICTOR4); + JPEG_UNUSED(Rc); + JPEG_UNUSED(Rb); +} + +METHODDEF(void) +jpeg_undifference5(j_decompress_ptr cinfo, int comp_index, + JDIFFROW diff_buf, JDIFFROW prev_row, + JDIFFROW undiff_buf, JDIMENSION width) +{ + SHIFT_TEMPS + UNDIFFERENCE_2D(PREDICTOR5); + JPEG_UNUSED(Rc); + JPEG_UNUSED(Rb); +} + +METHODDEF(void) +jpeg_undifference6(j_decompress_ptr cinfo, int comp_index, + JDIFFROW diff_buf, JDIFFROW prev_row, + JDIFFROW undiff_buf, JDIMENSION width) +{ + SHIFT_TEMPS + UNDIFFERENCE_2D(PREDICTOR6); + JPEG_UNUSED(Rc); + JPEG_UNUSED(Rb); +} + +METHODDEF(void) +jpeg_undifference7(j_decompress_ptr cinfo, int comp_index, + JDIFFROW diff_buf, JDIFFROW prev_row, + JDIFFROW undiff_buf, JDIMENSION width) +{ + SHIFT_TEMPS + UNDIFFERENCE_2D(PREDICTOR7); + JPEG_UNUSED(Rc); + JPEG_UNUSED(Rb); +} + + +/* + * Undifferencer for the first row in a scan or restart interval. The first + * sample in the row is undifferenced using the special predictor constant + * x=2^(P-Pt-1). The rest of the samples are undifferenced using the + * 1-D horizontal predictor (1). + */ + +METHODDEF(void) +jpeg_undifference_first_row(j_decompress_ptr cinfo, int comp_index, + JDIFFROW diff_buf, JDIFFROW prev_row, + JDIFFROW undiff_buf, JDIMENSION width) +{ + j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec; + + UNDIFFERENCE_1D(INITIAL_PREDICTORx); + + /* + * Now that we have undifferenced the first row, we want to use the + * undifferencer which corresponds to the predictor specified in the + * scan header. + */ + switch (cinfo->Ss) { + case 1: + losslsd->predict_undifference[comp_index] = jpeg_undifference1; + break; + case 2: + losslsd->predict_undifference[comp_index] = jpeg_undifference2; + break; + case 3: + losslsd->predict_undifference[comp_index] = jpeg_undifference3; + break; + case 4: + losslsd->predict_undifference[comp_index] = jpeg_undifference4; + break; + case 5: + losslsd->predict_undifference[comp_index] = jpeg_undifference5; + break; + case 6: + losslsd->predict_undifference[comp_index] = jpeg_undifference6; + break; + case 7: + losslsd->predict_undifference[comp_index] = jpeg_undifference7; + break; + } +} + + +/* + * Initialize for an input processing pass. + */ + +METHODDEF(void) +predict_start_pass (j_decompress_ptr cinfo) +{ + j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec; + int ci; + + /* Check that the scan parameters Ss, Se, Ah, Al are OK for lossless JPEG. + * + * Ss is the predictor selection value (psv). Legal values for sequential + * lossless JPEG are: 1 <= psv <= 7. + * + * Se and Ah are not used and should be zero. + * + * Al specifies the point transform (Pt). Legal values are: 0 <= Pt <= 15. + */ + if (cinfo->Ss < 1 || cinfo->Ss > 7 || + cinfo->Se != 0 || cinfo->Ah != 0 || + cinfo->Al > 15) /* need not check for < 0 */ + ERREXIT4(cinfo, JERR_BAD_LOSSLESS, + cinfo->Ss, cinfo->Se, cinfo->Ah, cinfo->Al); + + /* Set undifference functions to first row function */ + for (ci = 0; ci < cinfo->num_components; ci++) + losslsd->predict_undifference[ci] = jpeg_undifference_first_row; +} + + +/* + * Module initialization routine for the undifferencer. + */ + +GLOBAL(void) +jinit_undifferencer (j_decompress_ptr cinfo) +{ + j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec; + + losslsd->predict_start_pass = predict_start_pass; + losslsd->predict_process_restart = predict_start_pass; +} + +#endif /* D_LOSSLESS_SUPPORTED */ + diff --git a/dcmjpeg/libijg12/jdsample.c b/dcmjpeg/libijg12/jdsample.c new file mode 100644 index 00000000..6e8e7ea6 --- /dev/null +++ b/dcmjpeg/libijg12/jdsample.c @@ -0,0 +1,478 @@ +/* + * jdsample.c + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains upsampling routines. + * + * Upsampling input data is counted in "row groups". A row group + * is defined to be (v_samp_factor * codec_data_unit / min_codec_data_unit) + * sample rows of each component. Upsampling will normally produce + * max_v_samp_factor pixel rows from each row group (but this could vary + * if the upsampler is applying a scale factor of its own). + * + * An excellent reference for image resampling is + * Digital Image Warping, George Wolberg, 1990. + * Pub. by IEEE Computer Society Press, Los Alamitos, CA. ISBN 0-8186-8944-7. + */ + +#define JPEG_INTERNALS +#include "jinclude12.h" +#include "jpeglib12.h" + + +/* Pointer to routine to upsample a single component */ +typedef JMETHOD(void, upsample1_ptr, + (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr)); + +/* Private subobject */ + +typedef struct { + struct jpeg_upsampler pub; /* public fields */ + + /* Color conversion buffer. When using separate upsampling and color + * conversion steps, this buffer holds one upsampled row group until it + * has been color converted and output. + * Note: we do not allocate any storage for component(s) which are full-size, + * ie do not need rescaling. The corresponding entry of color_buf[] is + * simply set to point to the input data array, thereby avoiding copying. + */ + JSAMPARRAY color_buf[MAX_COMPONENTS]; + + /* Per-component upsampling method pointers */ + upsample1_ptr methods[MAX_COMPONENTS]; + + int next_row_out; /* counts rows emitted from color_buf */ + JDIMENSION rows_to_go; /* counts rows remaining in image */ + + /* Height of an input row group for each component. */ + int rowgroup_height[MAX_COMPONENTS]; + + /* These arrays save pixel expansion factors so that int_expand need not + * recompute them each time. They are unused for other upsampling methods. + */ + UINT8 h_expand[MAX_COMPONENTS]; + UINT8 v_expand[MAX_COMPONENTS]; +} my_upsampler; + +typedef my_upsampler * my_upsample_ptr; + + +/* + * Initialize for an upsampling pass. + */ + +METHODDEF(void) +start_pass_upsample (j_decompress_ptr cinfo) +{ + my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; + + /* Mark the conversion buffer empty */ + upsample->next_row_out = cinfo->max_v_samp_factor; + /* Initialize total-height counter for detecting bottom of image */ + upsample->rows_to_go = cinfo->output_height; +} + + +/* + * Control routine to do upsampling (and color conversion). + * + * In this version we upsample each component independently. + * We upsample one row group into the conversion buffer, then apply + * color conversion a row at a time. + */ + +METHODDEF(void) +sep_upsample (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail) +{ + my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; + int ci; + jpeg_component_info * compptr; + JDIMENSION num_rows; + + /* Fill the conversion buffer, if it's empty */ + if (upsample->next_row_out >= cinfo->max_v_samp_factor) { + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + /* Invoke per-component upsample method. Notice we pass a POINTER + * to color_buf[ci], so that fullsize_upsample can change it. + */ + (*upsample->methods[ci]) (cinfo, compptr, + input_buf[ci] + (*in_row_group_ctr * (JDIMENSION)upsample->rowgroup_height[ci]), + upsample->color_buf + ci); + } + upsample->next_row_out = 0; + } + + /* Color-convert and emit rows */ + + /* How many we have in the buffer: */ + num_rows = (JDIMENSION) (cinfo->max_v_samp_factor - upsample->next_row_out); + /* Not more than the distance to the end of the image. Need this test + * in case the image height is not a multiple of max_v_samp_factor: + */ + if (num_rows > upsample->rows_to_go) + num_rows = upsample->rows_to_go; + /* And not more than what the client can accept: */ + out_rows_avail -= *out_row_ctr; + if (num_rows > out_rows_avail) + num_rows = out_rows_avail; + + (*cinfo->cconvert->color_convert) (cinfo, upsample->color_buf, + (JDIMENSION) upsample->next_row_out, + output_buf + *out_row_ctr, + (int) num_rows); + + /* Adjust counts */ + *out_row_ctr += num_rows; + upsample->rows_to_go -= num_rows; + upsample->next_row_out += (int)num_rows; + /* When the buffer is emptied, declare this input row group consumed */ + if (upsample->next_row_out >= cinfo->max_v_samp_factor) + (*in_row_group_ctr)++; +} + + +/* + * These are the routines invoked by sep_upsample to upsample pixel values + * of a single component. One row group is processed per call. + */ + + +/* + * For full-size components, we just make color_buf[ci] point at the + * input buffer, and thus avoid copying any data. Note that this is + * safe only because sep_upsample doesn't declare the input row group + * "consumed" until we are done color converting and emitting it. + */ + +METHODDEF(void) +fullsize_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) +{ + *output_data_ptr = input_data; +} + + +/* + * This is a no-op version used for "uninteresting" components. + * These components will not be referenced by color conversion. + */ + +METHODDEF(void) +noop_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) +{ + *output_data_ptr = NULL; /* safety check */ +} + + +/* + * This version handles any integral sampling ratios. + * This is not used for typical JPEG files, so it need not be fast. + * Nor, for that matter, is it particularly accurate: the algorithm is + * simple replication of the input pixel onto the corresponding output + * pixels. The hi-falutin sampling literature refers to this as a + * "box filter". A box filter tends to introduce visible artifacts, + * so if you are actually going to use 3:1 or 4:1 sampling ratios + * you would be well advised to improve this code. + */ + +METHODDEF(void) +int_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) +{ + my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; + JSAMPARRAY output_data = *output_data_ptr; + register JSAMPROW inptr, outptr; + register JSAMPLE invalue; + register int h; + JSAMPROW outend; + int h_expand, v_expand; + int inrow, outrow; + + h_expand = upsample->h_expand[compptr->component_index]; + v_expand = upsample->v_expand[compptr->component_index]; + + inrow = outrow = 0; + while (outrow < cinfo->max_v_samp_factor) { + /* Generate one output row with proper horizontal expansion */ + inptr = input_data[inrow]; + outptr = output_data[outrow]; + outend = outptr + cinfo->output_width; + while (outptr < outend) { + invalue = *inptr++; /* don't need GETJSAMPLE() here */ + for (h = h_expand; h > 0; h--) { + *outptr++ = invalue; + } + } + /* Generate any additional output rows by duplicating the first one */ + if (v_expand > 1) { + jcopy_sample_rows(output_data, outrow, output_data, outrow+1, + v_expand-1, cinfo->output_width); + } + inrow++; + outrow += v_expand; + } +} + + +/* + * Fast processing for the common case of 2:1 horizontal and 1:1 vertical. + * It's still a box filter. + */ + +METHODDEF(void) +h2v1_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) +{ + JSAMPARRAY output_data = *output_data_ptr; + register JSAMPROW inptr, outptr; + register JSAMPLE invalue; + JSAMPROW outend; + int inrow; + + for (inrow = 0; inrow < cinfo->max_v_samp_factor; inrow++) { + inptr = input_data[inrow]; + outptr = output_data[inrow]; + outend = outptr + cinfo->output_width; + while (outptr < outend) { + invalue = *inptr++; /* don't need GETJSAMPLE() here */ + *outptr++ = invalue; + *outptr++ = invalue; + } + } +} + + +/* + * Fast processing for the common case of 2:1 horizontal and 2:1 vertical. + * It's still a box filter. + */ + +METHODDEF(void) +h2v2_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) +{ + JSAMPARRAY output_data = *output_data_ptr; + register JSAMPROW inptr, outptr; + register JSAMPLE invalue; + JSAMPROW outend; + int inrow, outrow; + + inrow = outrow = 0; + while (outrow < cinfo->max_v_samp_factor) { + inptr = input_data[inrow]; + outptr = output_data[outrow]; + outend = outptr + cinfo->output_width; + while (outptr < outend) { + invalue = *inptr++; /* don't need GETJSAMPLE() here */ + *outptr++ = invalue; + *outptr++ = invalue; + } + jcopy_sample_rows(output_data, outrow, output_data, outrow+1, + 1, cinfo->output_width); + inrow++; + outrow += 2; + } +} + + +/* + * Fancy processing for the common case of 2:1 horizontal and 1:1 vertical. + * + * The upsampling algorithm is linear interpolation between pixel centers, + * also known as a "triangle filter". This is a good compromise between + * speed and visual quality. The centers of the output pixels are 1/4 and 3/4 + * of the way between input pixel centers. + * + * A note about the "bias" calculations: when rounding fractional values to + * integer, we do not want to always round 0.5 up to the next integer. + * If we did that, we'd introduce a noticeable bias towards larger values. + * Instead, this code is arranged so that 0.5 will be rounded up or down at + * alternate pixel locations (a simple ordered dither pattern). + */ + +METHODDEF(void) +h2v1_fancy_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) +{ + JSAMPARRAY output_data = *output_data_ptr; + register JSAMPROW inptr, outptr; + register int invalue; + register JDIMENSION colctr; + int inrow; + + for (inrow = 0; inrow < cinfo->max_v_samp_factor; inrow++) { + inptr = input_data[inrow]; + outptr = output_data[inrow]; + /* Special case for first column */ + invalue = GETJSAMPLE(*inptr++); + *outptr++ = (JSAMPLE) invalue; + *outptr++ = (JSAMPLE) ((invalue * 3 + GETJSAMPLE(*inptr) + 2) >> 2); + + for (colctr = compptr->downsampled_width - 2; colctr > 0; colctr--) { + /* General case: 3/4 * nearer pixel + 1/4 * further pixel */ + invalue = GETJSAMPLE(*inptr++) * 3; + *outptr++ = (JSAMPLE) ((invalue + GETJSAMPLE(inptr[-2]) + 1) >> 2); + *outptr++ = (JSAMPLE) ((invalue + GETJSAMPLE(*inptr) + 2) >> 2); + } + + /* Special case for last column */ + invalue = GETJSAMPLE(*inptr); + *outptr++ = (JSAMPLE) ((invalue * 3 + GETJSAMPLE(inptr[-1]) + 1) >> 2); + *outptr++ = (JSAMPLE) invalue; + } +} + + +/* + * Fancy processing for the common case of 2:1 horizontal and 2:1 vertical. + * Again a triangle filter; see comments for h2v1 case, above. + * + * It is OK for us to reference the adjacent input rows because we demanded + * context from the main buffer controller (see initialization code). + */ + +METHODDEF(void) +h2v2_fancy_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) +{ + JSAMPARRAY output_data = *output_data_ptr; + register JSAMPROW inptr0, inptr1, outptr; +#if BITS_IN_JSAMPLE == 8 + register int thiscolsum, lastcolsum, nextcolsum; +#else + register IJG_INT32 thiscolsum, lastcolsum, nextcolsum; +#endif + register JDIMENSION colctr; + int inrow, outrow, v; + + inrow = outrow = 0; + while (outrow < cinfo->max_v_samp_factor) { + for (v = 0; v < 2; v++) { + /* inptr0 points to nearest input row, inptr1 points to next nearest */ + inptr0 = input_data[inrow]; + if (v == 0) /* next nearest is row above */ + inptr1 = input_data[inrow-1]; + else /* next nearest is row below */ + inptr1 = input_data[inrow+1]; + outptr = output_data[outrow++]; + + /* Special case for first column */ + thiscolsum = GETJSAMPLE(*inptr0++) * 3 + GETJSAMPLE(*inptr1++); + nextcolsum = GETJSAMPLE(*inptr0++) * 3 + GETJSAMPLE(*inptr1++); + *outptr++ = (JSAMPLE) ((thiscolsum * 4 + 8) >> 4); + *outptr++ = (JSAMPLE) ((thiscolsum * 3 + nextcolsum + 7) >> 4); + lastcolsum = thiscolsum; thiscolsum = nextcolsum; + + for (colctr = compptr->downsampled_width - 2; colctr > 0; colctr--) { + /* General case: 3/4 * nearer pixel + 1/4 * further pixel in each */ + /* dimension, thus 9/16, 3/16, 3/16, 1/16 overall */ + nextcolsum = GETJSAMPLE(*inptr0++) * 3 + GETJSAMPLE(*inptr1++); + *outptr++ = (JSAMPLE) ((thiscolsum * 3 + lastcolsum + 8) >> 4); + *outptr++ = (JSAMPLE) ((thiscolsum * 3 + nextcolsum + 7) >> 4); + lastcolsum = thiscolsum; thiscolsum = nextcolsum; + } + + /* Special case for last column */ + *outptr++ = (JSAMPLE) ((thiscolsum * 3 + lastcolsum + 8) >> 4); + *outptr++ = (JSAMPLE) ((thiscolsum * 4 + 7) >> 4); + } + inrow++; + } +} + + +/* + * Module initialization routine for upsampling. + */ + +GLOBAL(void) +jinit_upsampler (j_decompress_ptr cinfo) +{ + my_upsample_ptr upsample; + int ci; + jpeg_component_info * compptr; + boolean need_buffer, do_fancy; + int h_in_group, v_in_group, h_out_group, v_out_group; + + upsample = (my_upsample_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_upsampler)); + cinfo->upsample = (struct jpeg_upsampler *) upsample; + upsample->pub.start_pass = start_pass_upsample; + upsample->pub.upsample = sep_upsample; + upsample->pub.need_context_rows = FALSE; /* until we find out differently */ + + if (cinfo->CCIR601_sampling) /* this isn't supported */ + ERREXIT(cinfo, JERR_CCIR601_NOTIMPL); + + /* jdmainct.c doesn't support context rows when min_codec_data_unit = 1, + * so don't ask for it. + */ + do_fancy = cinfo->do_fancy_upsampling && cinfo->min_codec_data_unit > 1; + + /* Verify we can handle the sampling factors, select per-component methods, + * and create storage as needed. + */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + /* Compute size of an "input group" after IDCT scaling. This many samples + * are to be converted to max_h_samp_factor * max_v_samp_factor pixels. + */ + h_in_group = (compptr->h_samp_factor * compptr->codec_data_unit) / + cinfo->min_codec_data_unit; + v_in_group = (compptr->v_samp_factor * compptr->codec_data_unit) / + cinfo->min_codec_data_unit; + h_out_group = cinfo->max_h_samp_factor; + v_out_group = cinfo->max_v_samp_factor; + upsample->rowgroup_height[ci] = v_in_group; /* save for use later */ + need_buffer = TRUE; + if (! compptr->component_needed) { + /* Don't bother to upsample an uninteresting component. */ + upsample->methods[ci] = noop_upsample; + need_buffer = FALSE; + } else if (h_in_group == h_out_group && v_in_group == v_out_group) { + /* Fullsize components can be processed without any work. */ + upsample->methods[ci] = fullsize_upsample; + need_buffer = FALSE; + } else if (h_in_group * 2 == h_out_group && + v_in_group == v_out_group) { + /* Special cases for 2h1v upsampling */ + if (do_fancy && compptr->downsampled_width > 2) + upsample->methods[ci] = h2v1_fancy_upsample; + else + upsample->methods[ci] = h2v1_upsample; + } else if (h_in_group * 2 == h_out_group && + v_in_group * 2 == v_out_group) { + /* Special cases for 2h2v upsampling */ + if (do_fancy && compptr->downsampled_width > 2) { + upsample->methods[ci] = h2v2_fancy_upsample; + upsample->pub.need_context_rows = TRUE; + } else + upsample->methods[ci] = h2v2_upsample; + } else if ((h_out_group % h_in_group) == 0 && + (v_out_group % v_in_group) == 0) { + /* Generic integral-factors upsampling method */ + upsample->methods[ci] = int_upsample; + upsample->h_expand[ci] = (UINT8) (h_out_group / h_in_group); + upsample->v_expand[ci] = (UINT8) (v_out_group / v_in_group); + } else + ERREXIT(cinfo, JERR_FRACT_SAMPLE_NOTIMPL); + if (need_buffer) { + upsample->color_buf[ci] = (*cinfo->mem->alloc_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + (JDIMENSION) jround_up((long) cinfo->output_width, + (long) cinfo->max_h_samp_factor), + (JDIMENSION) cinfo->max_v_samp_factor); + } + } +} diff --git a/dcmjpeg/libijg12/jdscale.c b/dcmjpeg/libijg12/jdscale.c new file mode 100644 index 00000000..2ca6f942 --- /dev/null +++ b/dcmjpeg/libijg12/jdscale.c @@ -0,0 +1,119 @@ +/* + * jdscale.c + * + * Copyright (C) 1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains sample scaling for lossless JPEG. This is a + * combination of upscaling the undifferenced sample by 2^Pt and downscaling + * the sample to fit into JSAMPLE. + */ + +#define JPEG_INTERNALS +#include "jinclude12.h" +#include "jpeglib12.h" +#include "jlossls12.h" /* Private declarations for lossless codec */ + + +#ifdef D_LOSSLESS_SUPPORTED + +/* + * Private scaler object for lossless decoding. + */ + +typedef struct { + int scale_factor; +} scaler; + +typedef scaler * scaler_ptr; + + +/* + * Scalers for packing sample differences into JSAMPLEs. + */ + +METHODDEF(void) +simple_upscale(j_decompress_ptr cinfo, + JDIFFROW diff_buf, JSAMPROW output_buf, + JDIMENSION width) +{ + j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec; + scaler_ptr scale = (scaler_ptr) losslsd->scaler_private; + int scale_factor = scale->scale_factor; + unsigned int xindex; + + for (xindex = 0; xindex < width; xindex++) + output_buf[xindex] = (JSAMPLE) (diff_buf[xindex] << scale_factor); +} + +METHODDEF(void) +simple_downscale(j_decompress_ptr cinfo, + JDIFFROW diff_buf, JSAMPROW output_buf, + JDIMENSION width) +{ + j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec; + scaler_ptr scale = (scaler_ptr) losslsd->scaler_private; + int scale_factor = scale->scale_factor; + unsigned int xindex; + SHIFT_TEMPS + + for (xindex = 0; xindex < width; xindex++) + output_buf[xindex] = (JSAMPLE) RIGHT_SHIFT(diff_buf[xindex], scale_factor); +} + +METHODDEF(void) +noscale(j_decompress_ptr cinfo, + JDIFFROW diff_buf, JSAMPROW output_buf, + JDIMENSION width) +{ + unsigned int xindex; + + for (xindex = 0; xindex < width; xindex++) + output_buf[xindex] = (JSAMPLE) diff_buf[xindex]; +} + + +METHODDEF(void) +scaler_start_pass (j_decompress_ptr cinfo) +{ + j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec; + scaler_ptr scale = (scaler_ptr) losslsd->scaler_private; + int downscale; + + /* + * Downscale by the difference in the input vs. output precision. If the + * output precision >= input precision, then do not downscale. + */ + downscale = BITS_IN_JSAMPLE < cinfo->data_precision ? + cinfo->data_precision - BITS_IN_JSAMPLE : 0; + + scale->scale_factor = cinfo->Al - downscale; + + /* Set scale functions based on scale_factor (positive = left shift) */ + if (scale->scale_factor > 0) + losslsd->scaler_scale = simple_upscale; + else if (scale->scale_factor < 0) { + scale->scale_factor = -scale->scale_factor; + losslsd->scaler_scale = simple_downscale; + } + else + losslsd->scaler_scale = noscale; +} + + +GLOBAL(void) +jinit_d_scaler (j_decompress_ptr cinfo) +{ + j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec; + scaler_ptr scale; + + scale = (scaler_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(scaler)); + losslsd->scaler_private = (void *) scale; + losslsd->scaler_start_pass = scaler_start_pass; +} + +#endif /* D_LOSSLESS_SUPPORTED */ + diff --git a/dcmjpeg/libijg12/jdshuff.c b/dcmjpeg/libijg12/jdshuff.c new file mode 100644 index 00000000..5d2a043b --- /dev/null +++ b/dcmjpeg/libijg12/jdshuff.c @@ -0,0 +1,360 @@ +/* + * jdshuff.c + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains Huffman entropy decoding routines for sequential JPEG. + * + * Much of the complexity here has to do with supporting input suspension. + * If the data source module demands suspension, we want to be able to back + * up to the start of the current MCU. To do this, we copy state variables + * into local working storage, and update them back to the permanent + * storage only upon successful completion of an MCU. + */ + +#define JPEG_INTERNALS +#include "jinclude12.h" +#include "jpeglib12.h" +#include "jlossy12.h" /* Private declarations for lossy codec */ +#include "jdhuff12.h" /* Declarations shared with jd*huff.c */ + + +/* + * Private entropy decoder object for Huffman decoding. + * + * The savable_state subrecord contains fields that change within an MCU, + * but must not be updated permanently until we complete the MCU. + */ + +typedef struct { + int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */ +} savable_state; + +/* This macro is to work around compilers with missing or broken + * structure assignment. You'll need to fix this code if you have + * such a compiler and you change MAX_COMPS_IN_SCAN. + */ + +#ifndef NO_STRUCT_ASSIGN +#define ASSIGN_STATE(dest,src) ((dest) = (src)) +#else +#if MAX_COMPS_IN_SCAN == 4 +#define ASSIGN_STATE(dest,src) \ + ((dest).last_dc_val[0] = (src).last_dc_val[0], \ + (dest).last_dc_val[1] = (src).last_dc_val[1], \ + (dest).last_dc_val[2] = (src).last_dc_val[2], \ + (dest).last_dc_val[3] = (src).last_dc_val[3]) +#endif +#endif + + +typedef struct { + huffd_common_fields; /* Fields shared with other entropy decoders */ + + /* These fields are loaded into local variables at start of each MCU. + * In case of suspension, we exit WITHOUT updating them. + */ + savable_state saved; /* Other state at start of MCU */ + + /* These fields are NOT loaded into local working state. */ + unsigned int restarts_to_go; /* MCUs left in this restart interval */ + + /* Pointers to derived tables (these workspaces have image lifespan) */ + d_derived_tbl * dc_derived_tbls[NUM_HUFF_TBLS]; + d_derived_tbl * ac_derived_tbls[NUM_HUFF_TBLS]; + + /* Precalculated info set up by start_pass for use in decode_mcu: */ + + /* Pointers to derived tables to be used for each block within an MCU */ + d_derived_tbl * dc_cur_tbls[D_MAX_DATA_UNITS_IN_MCU]; + d_derived_tbl * ac_cur_tbls[D_MAX_DATA_UNITS_IN_MCU]; + /* Whether we care about the DC and AC coefficient values for each block */ + boolean dc_needed[D_MAX_DATA_UNITS_IN_MCU]; + boolean ac_needed[D_MAX_DATA_UNITS_IN_MCU]; +} shuff_entropy_decoder; + +typedef shuff_entropy_decoder * shuff_entropy_ptr; + + +/* + * Initialize for a Huffman-compressed scan. + */ + +METHODDEF(void) +start_pass_huff_decoder (j_decompress_ptr cinfo) +{ + j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec; + shuff_entropy_ptr entropy = (shuff_entropy_ptr) lossyd->entropy_private; + int ci, blkn, dctbl, actbl; + jpeg_component_info * compptr; + + /* Check that the scan parameters Ss, Se, Ah/Al are OK for sequential JPEG. + * This ought to be an error condition, but we make it a warning because + * there are some baseline files out there with all zeroes in these bytes. + */ + if (cinfo->Ss != 0 || cinfo->Se != DCTSIZE2-1 || + cinfo->Ah != 0 || cinfo->Al != 0) + WARNMS(cinfo, JWRN_NOT_SEQUENTIAL); + + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + dctbl = compptr->dc_tbl_no; + actbl = compptr->ac_tbl_no; + /* Compute derived values for Huffman tables */ + /* We may do this more than once for a table, but it's not expensive */ + jpeg_make_d_derived_tbl(cinfo, TRUE, dctbl, + & entropy->dc_derived_tbls[dctbl]); + jpeg_make_d_derived_tbl(cinfo, FALSE, actbl, + & entropy->ac_derived_tbls[actbl]); + /* Initialize DC predictions to 0 */ + entropy->saved.last_dc_val[ci] = 0; + } + + /* Precalculate decoding info for each block in an MCU of this scan */ + for (blkn = 0; blkn < cinfo->data_units_in_MCU; blkn++) { + ci = cinfo->MCU_membership[blkn]; + compptr = cinfo->cur_comp_info[ci]; + /* Precalculate which table to use for each block */ + entropy->dc_cur_tbls[blkn] = entropy->dc_derived_tbls[compptr->dc_tbl_no]; + entropy->ac_cur_tbls[blkn] = entropy->ac_derived_tbls[compptr->ac_tbl_no]; + /* Decide whether we really care about the coefficient values */ + if (compptr->component_needed) { + entropy->dc_needed[blkn] = TRUE; + /* we don't need the ACs if producing a 1/8th-size image */ + entropy->ac_needed[blkn] = (compptr->codec_data_unit > 1); + } else { + entropy->dc_needed[blkn] = entropy->ac_needed[blkn] = FALSE; + } + } + + /* Initialize bitread state variables */ + entropy->bitstate.bits_left = 0; + entropy->bitstate.get_buffer = 0; /* unnecessary, but keeps Purify quiet */ + entropy->insufficient_data = FALSE; + + /* Initialize restart counter */ + entropy->restarts_to_go = cinfo->restart_interval; +} + + +/* + * Figure F.12: extend sign bit. + * On some machines, a shift and add will be faster than a table lookup. + */ + +#ifdef AVOID_TABLES + +#define HUFF_EXTEND(x,s) ((x) < (1<<((s)-1)) ? (x) + (((-1)<<(s)) + 1) : (x)) + +#else + +#define HUFF_EXTEND(x,s) ((x) < extend_test[s] ? (x) + extend_offset[s] : (x)) + +static const int extend_test[16] = /* entry n is 2**(n-1) */ + { 0, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080, + 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000 }; + +static const int extend_offset[16] = /* entry n is (-1 << n) + 1 */ + { 0, ((-1)<<1) + 1, ((-1)<<2) + 1, ((-1)<<3) + 1, ((-1)<<4) + 1, + ((-1)<<5) + 1, ((-1)<<6) + 1, ((-1)<<7) + 1, ((-1)<<8) + 1, + ((-1)<<9) + 1, ((-1)<<10) + 1, ((-1)<<11) + 1, ((-1)<<12) + 1, + ((-1)<<13) + 1, ((-1)<<14) + 1, ((-1)<<15) + 1 }; + +#endif /* AVOID_TABLES */ + + +/* + * Check for a restart marker & resynchronize decoder. + * Returns FALSE if must suspend. + */ + +LOCAL(boolean) +process_restart (j_decompress_ptr cinfo) +{ + j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec; + shuff_entropy_ptr entropy = (shuff_entropy_ptr) lossyd->entropy_private; + int ci; + + /* Throw away any unused bits remaining in bit buffer; */ + /* include any full bytes in next_marker's count of discarded bytes */ + cinfo->marker->discarded_bytes += (unsigned int)(entropy->bitstate.bits_left / 8); + entropy->bitstate.bits_left = 0; + + /* Advance past the RSTn marker */ + if (! (*cinfo->marker->read_restart_marker) (cinfo)) + return FALSE; + + /* Re-initialize DC predictions to 0 */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) + entropy->saved.last_dc_val[ci] = 0; + + /* Reset restart counter */ + entropy->restarts_to_go = cinfo->restart_interval; + + /* Reset out-of-data flag, unless read_restart_marker left us smack up + * against a marker. In that case we will end up treating the next data + * segment as empty, and we can avoid producing bogus output pixels by + * leaving the flag set. + */ + if (cinfo->unread_marker == 0) + entropy->insufficient_data = FALSE; + + return TRUE; +} + + +/* + * Decode and return one MCU's worth of Huffman-compressed coefficients. + * The coefficients are reordered from zigzag order into natural array order, + * but are not dequantized. + * + * The i'th block of the MCU is stored into the block pointed to by + * MCU_data[i]. WE ASSUME THIS AREA HAS BEEN ZEROED BY THE CALLER. + * (Wholesale zeroing is usually a little faster than retail...) + * + * Returns FALSE if data source requested suspension. In that case no + * changes have been made to permanent state. (Exception: some output + * coefficients may already have been assigned. This is harmless for + * this module, since we'll just re-assign them on the next call.) + */ + +METHODDEF(boolean) +decode_mcu (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) +{ + j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec; + shuff_entropy_ptr entropy = (shuff_entropy_ptr) lossyd->entropy_private; + int blkn; + BITREAD_STATE_VARS; + savable_state state; + + /* Process restart marker if needed; may have to suspend */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) + if (! process_restart(cinfo)) + return FALSE; + } + + /* If we've run out of data, just leave the MCU set to zeroes. + * This way, we return uniform gray for the remainder of the segment. + */ + if (! entropy->insufficient_data) { + + /* Load up working state */ + BITREAD_LOAD_STATE(cinfo,entropy->bitstate); + ASSIGN_STATE(state, entropy->saved); + + /* Outer loop handles each block in the MCU */ + + for (blkn = 0; blkn < cinfo->data_units_in_MCU; blkn++) { + JBLOCKROW block = MCU_data[blkn]; + d_derived_tbl * dctbl = entropy->dc_cur_tbls[blkn]; + d_derived_tbl * actbl = entropy->ac_cur_tbls[blkn]; + register int s, k, r; + + /* Decode a single block's worth of coefficients */ + + /* Section F.2.2.1: decode the DC coefficient difference */ + HUFF_DECODE(s, br_state, dctbl, return FALSE, label1); + if (s) { + CHECK_BIT_BUFFER(br_state, s, return FALSE); + r = GET_BITS(s); + s = HUFF_EXTEND(r, s); + } + + if (entropy->dc_needed[blkn]) { + /* Convert DC difference to actual value, update last_dc_val */ + int ci = cinfo->MCU_membership[blkn]; + s += state.last_dc_val[ci]; + state.last_dc_val[ci] = s; + /* Output the DC coefficient (assumes jpeg_natural_order[0] = 0) */ + (*block)[0] = (JCOEF) s; + } + + if (entropy->ac_needed[blkn]) { + + /* Section F.2.2.2: decode the AC coefficients */ + /* Since zeroes are skipped, output area must be cleared beforehand */ + for (k = 1; k < DCTSIZE2; k++) { + HUFF_DECODE(s, br_state, actbl, return FALSE, label2); + + r = s >> 4; + s &= 15; + + if (s) { + k += r; + CHECK_BIT_BUFFER(br_state, s, return FALSE); + r = GET_BITS(s); + s = HUFF_EXTEND(r, s); + /* Output coefficient in natural (dezigzagged) order. + * Note: the extra entries in jpeg_natural_order[] will save us + * if k >= DCTSIZE2, which could happen if the data is corrupted. + */ + (*block)[jpeg_natural_order[k]] = (JCOEF) s; + } else { + if (r != 15) + break; + k += 15; + } + } + + } else { + + /* Section F.2.2.2: decode the AC coefficients */ + /* In this path we just discard the values */ + for (k = 1; k < DCTSIZE2; k++) { + HUFF_DECODE(s, br_state, actbl, return FALSE, label3); + + r = s >> 4; + s &= 15; + + if (s) { + k += r; + CHECK_BIT_BUFFER(br_state, s, return FALSE); + DROP_BITS(s); + } else { + if (r != 15) + break; + k += 15; + } + } + + } + } + + /* Completed MCU, so update state */ + BITREAD_SAVE_STATE(cinfo,entropy->bitstate); + ASSIGN_STATE(entropy->saved, state); + } + + /* Account for restart interval (no-op if not using restarts) */ + entropy->restarts_to_go--; + + return TRUE; +} + + +/* + * Module initialization routine for Huffman entropy decoding. + */ + +GLOBAL(void) +jinit_shuff_decoder (j_decompress_ptr cinfo) +{ + j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec; + shuff_entropy_ptr entropy; + int i; + + entropy = (shuff_entropy_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(shuff_entropy_decoder)); + lossyd->entropy_private = (void *) entropy; + lossyd->entropy_start_pass = start_pass_huff_decoder; + lossyd->entropy_decode_mcu = decode_mcu; + + /* Mark tables unallocated */ + for (i = 0; i < NUM_HUFF_TBLS; i++) { + entropy->dc_derived_tbls[i] = entropy->ac_derived_tbls[i] = NULL; + } +} diff --git a/dcmjpeg/libijg12/jdtrans.c b/dcmjpeg/libijg12/jdtrans.c new file mode 100644 index 00000000..ef40d86f --- /dev/null +++ b/dcmjpeg/libijg12/jdtrans.c @@ -0,0 +1,138 @@ +/* + * jdtrans.c + * + * Copyright (C) 1995-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains library routines for transcoding decompression, + * that is, reading raw DCT coefficient arrays from an input JPEG file. + * The routines in jdapimin.c will also be needed by a transcoder. + */ + +#define JPEG_INTERNALS +#include "jinclude12.h" +#include "jpeglib12.h" +#include "jlossy12.h" + + +/* Forward declarations */ +LOCAL(void) transdecode_master_selection JPP((j_decompress_ptr cinfo)); + + +/* + * Read the coefficient arrays from a JPEG file. + * jpeg_read_header must be completed before calling this. + * + * The entire image is read into a set of virtual coefficient-block arrays, + * one per component. The return value is a pointer to the array of + * virtual-array descriptors. These can be manipulated directly via the + * JPEG memory manager, or handed off to jpeg_write_coefficients(). + * To release the memory occupied by the virtual arrays, call + * jpeg_finish_decompress() when done with the data. + * + * An alternative usage is to simply obtain access to the coefficient arrays + * during a buffered-image-mode decompression operation. This is allowed + * after any jpeg_finish_output() call. The arrays can be accessed until + * jpeg_finish_decompress() is called. (Note that any call to the library + * may reposition the arrays, so don't rely on access_virt_barray() results + * to stay valid across library calls.) + * + * Returns NULL if suspended. This case need be checked only if + * a suspending data source is used. + */ + +GLOBAL(jvirt_barray_ptr *) +jpeg_read_coefficients (j_decompress_ptr cinfo) +{ + /* j_lossy_d_ptr decomp; */ + + /* Can't read coefficients from lossless streams */ + if (cinfo->process == JPROC_LOSSLESS) { + ERREXIT(cinfo, JERR_CANT_TRANSCODE); + return NULL; + } + + if (cinfo->global_state == DSTATE_READY) { + /* First call: initialize active modules */ + transdecode_master_selection(cinfo); + cinfo->global_state = DSTATE_RDCOEFS; + } + if (cinfo->global_state == DSTATE_RDCOEFS) { + /* Absorb whole file into the coef buffer */ + for (;;) { + int retcode; + /* Call progress monitor hook if present */ + if (cinfo->progress != NULL) + (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); + /* Absorb some more input */ + retcode = (*cinfo->inputctl->consume_input) (cinfo); + if (retcode == JPEG_SUSPENDED) + return NULL; + if (retcode == JPEG_REACHED_EOI) + break; + /* Advance progress counter if appropriate */ + if (cinfo->progress != NULL && + (retcode == JPEG_ROW_COMPLETED || retcode == JPEG_REACHED_SOS)) { + if (++cinfo->progress->pass_counter >= cinfo->progress->pass_limit) { + /* startup underestimated number of scans; ratchet up one scan */ + cinfo->progress->pass_limit += (long) cinfo->total_iMCU_rows; + } + } + } + /* Set state so that jpeg_finish_decompress does the right thing */ + cinfo->global_state = DSTATE_STOPPING; + } + /* At this point we should be in state DSTATE_STOPPING if being used + * standalone, or in state DSTATE_BUFIMAGE if being invoked to get access + * to the coefficients during a full buffered-image-mode decompression. + */ + if ((cinfo->global_state == DSTATE_STOPPING || + cinfo->global_state == DSTATE_BUFIMAGE) && cinfo->buffered_image) { + return ((j_lossy_d_ptr) cinfo->codec)->coef_arrays; + } + /* Oops, improper usage */ + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + return NULL; /* keep compiler happy */ +} + + +/* + * Master selection of decompression modules for transcoding. + * This substitutes for jdmaster.c's initialization of the full decompressor. + */ + +LOCAL(void) +transdecode_master_selection (j_decompress_ptr cinfo) +{ + /* This is effectively a buffered-image operation. */ + cinfo->buffered_image = TRUE; + + /* Initialize decompression codec */ + jinit_d_codec(cinfo); + + /* We can now tell the memory manager to allocate virtual arrays. */ + (*cinfo->mem->realize_virt_arrays) ((j_common_ptr) cinfo); + + /* Initialize input side of decompressor to consume first scan. */ + (*cinfo->inputctl->start_input_pass) (cinfo); + + /* Initialize progress monitoring. */ + if (cinfo->progress != NULL) { + int nscans; + /* Estimate number of scans to set pass_limit. */ + if (cinfo->process == JPROC_PROGRESSIVE) { + /* Arbitrarily estimate 2 interleaved DC scans + 3 AC scans/component. */ + nscans = 2 + 3 * cinfo->num_components; + } else if (cinfo->inputctl->has_multiple_scans) { + /* For a nonprogressive multiscan file, estimate 1 scan per component. */ + nscans = cinfo->num_components; + } else { + nscans = 1; + } + cinfo->progress->pass_counter = 0L; + cinfo->progress->pass_limit = (long) cinfo->total_iMCU_rows * nscans; + cinfo->progress->completed_passes = 0; + cinfo->progress->total_passes = 1; + } +} diff --git a/dcmjpeg/libijg12/jerror.c b/dcmjpeg/libijg12/jerror.c new file mode 100644 index 00000000..1b79aadc --- /dev/null +++ b/dcmjpeg/libijg12/jerror.c @@ -0,0 +1,252 @@ +/* + * jerror.c + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains simple error-reporting and trace-message routines. + * These are suitable for Unix-like systems and others where writing to + * stderr is the right thing to do. Many applications will want to replace + * some or all of these routines. + * + * If you define USE_WINDOWS_MESSAGEBOX in jconfig.h or in the makefile, + * you get a Windows-specific hack to display error messages in a dialog box. + * It ain't much, but it beats dropping error messages into the bit bucket, + * which is what happens to output to stderr under most Windows C compilers. + * + * These routines are used by both the compression and decompression code. + */ + +/* this is not a core library module, so it doesn't define JPEG_INTERNALS */ +#include "jinclude12.h" +#include "jpeglib12.h" +#include "jversion12.h" +#include "jerror12.h" + +#ifdef USE_WINDOWS_MESSAGEBOX +#include +#endif + +#ifndef EXIT_FAILURE /* define exit() codes if not provided */ +#define EXIT_FAILURE 1 +#endif + + +/* + * Create the message string table. + * We do this from the master message list in jerror.h by re-reading + * jerror.h with a suitable definition for macro JMESSAGE. + * The message table is made an external symbol just in case any applications + * want to refer to it directly. + */ + +#ifdef NEED_SHORT_EXTERNAL_NAMES +#define jpeg_std_message_table jpeg12_std_message_table +#endif + +#define JMESSAGE(code,string) string , + +const char * const jpeg_std_message_table[] = { +#include "jerror12.h" + NULL +}; + + +/* + * Error exit handler: must not return to caller. + * + * Applications may override this if they want to get control back after + * an error. Typically one would longjmp somewhere instead of exiting. + * The setjmp buffer can be made a private field within an expanded error + * handler object. Note that the info needed to generate an error message + * is stored in the error object, so you can generate the message now or + * later, at your convenience. + * You should make sure that the JPEG object is cleaned up (with jpeg_abort + * or jpeg_destroy) at some point. + */ + +METHODDEF(void) +error_exit (j_common_ptr cinfo) +{ + /* Always display the message */ + (*cinfo->err->output_message) (cinfo); + + /* Let the memory manager delete any temp files before we die */ + jpeg_destroy(cinfo); + + exit(EXIT_FAILURE); +} + + +/* + * Actual output of an error or trace message. + * Applications may override this method to send JPEG messages somewhere + * other than stderr. + * + * On Windows, printing to stderr is generally completely useless, + * so we provide optional code to produce an error-dialog popup. + * Most Windows applications will still prefer to override this routine, + * but if they don't, it'll do something at least marginally useful. + * + * NOTE: to use the library in an environment that doesn't support the + * C stdio library, you may have to delete the call to fprintf() entirely, + * not just not use this routine. + */ + +METHODDEF(void) +output_message (j_common_ptr cinfo) +{ + char buffer[JMSG_LENGTH_MAX]; + + /* Create the message */ + (*cinfo->err->format_message) (cinfo, buffer); + +#ifdef USE_WINDOWS_MESSAGEBOX + /* Display it in a message dialog box */ + MessageBox(GetActiveWindow(), buffer, "JPEG Library Error", + MB_OK | MB_ICONERROR); +#else + /* Send it to stderr, adding a newline */ + fprintf(stderr, "%s\n", buffer); +#endif +} + + +/* + * Decide whether to emit a trace or warning message. + * msg_level is one of: + * -1: recoverable corrupt-data warning, may want to abort. + * 0: important advisory messages (always display to user). + * 1: first level of tracing detail. + * 2,3,...: successively more detailed tracing messages. + * An application might override this method if it wanted to abort on warnings + * or change the policy about which messages to display. + */ + +METHODDEF(void) +emit_message (j_common_ptr cinfo, int msg_level) +{ + struct jpeg_error_mgr * err = cinfo->err; + + if (msg_level < 0) { + /* It's a warning message. Since corrupt files may generate many warnings, + * the policy implemented here is to show only the first warning, + * unless trace_level >= 3. + */ + if (err->num_warnings == 0 || err->trace_level >= 3) + (*err->output_message) (cinfo); + /* Always count warnings in num_warnings. */ + err->num_warnings++; + } else { + /* It's a trace message. Show it if trace_level >= msg_level. */ + if (err->trace_level >= msg_level) + (*err->output_message) (cinfo); + } +} + + +/* + * Format a message string for the most recent JPEG error or message. + * The message is stored into buffer, which should be at least JMSG_LENGTH_MAX + * characters. Note that no '\n' character is added to the string. + * Few applications should need to override this method. + */ + +METHODDEF(void) +format_message (j_common_ptr cinfo, char * buffer) +{ + struct jpeg_error_mgr * err = cinfo->err; + int msg_code = err->msg_code; + const char * msgtext = NULL; + const char * msgptr; + char ch; + boolean isstring; + + /* Look up message string in proper table */ + if (msg_code > 0 && msg_code <= err->last_jpeg_message) { + msgtext = err->jpeg_message_table[msg_code]; + } else if (err->addon_message_table != NULL && + msg_code >= err->first_addon_message && + msg_code <= err->last_addon_message) { + msgtext = err->addon_message_table[msg_code - err->first_addon_message]; + } + + /* Defend against bogus message number */ + if (msgtext == NULL) { + err->msg_parm.i[0] = msg_code; + msgtext = err->jpeg_message_table[0]; + } + + /* Check for string parameter, as indicated by %s in the message text */ + isstring = FALSE; + msgptr = msgtext; + while ((ch = *msgptr++) != '\0') { + if (ch == '%') { + if (*msgptr == 's') isstring = TRUE; + break; + } + } + + /* Format the message into the passed buffer */ + if (isstring) + sprintf(buffer, msgtext, err->msg_parm.s); + else + sprintf(buffer, msgtext, + err->msg_parm.i[0], err->msg_parm.i[1], + err->msg_parm.i[2], err->msg_parm.i[3], + err->msg_parm.i[4], err->msg_parm.i[5], + err->msg_parm.i[6], err->msg_parm.i[7]); +} + + +/* + * Reset error state variables at start of a new image. + * This is called during compression startup to reset trace/error + * processing to default state, without losing any application-specific + * method pointers. An application might possibly want to override + * this method if it has additional error processing state. + */ + +METHODDEF(void) +reset_error_mgr (j_common_ptr cinfo) +{ + cinfo->err->num_warnings = 0; + /* trace_level is not reset since it is an application-supplied parameter */ + cinfo->err->msg_code = 0; /* may be useful as a flag for "no error" */ +} + + +/* + * Fill in the standard error-handling methods in a jpeg_error_mgr object. + * Typical call is: + * struct jpeg_compress_struct cinfo; + * struct jpeg_error_mgr err; + * + * cinfo.err = jpeg_std_error(&err); + * after which the application may override some of the methods. + */ + +GLOBAL(struct jpeg_error_mgr *) +jpeg_std_error (struct jpeg_error_mgr * err) +{ + err->error_exit = error_exit; + err->emit_message = emit_message; + err->output_message = output_message; + err->format_message = format_message; + err->reset_error_mgr = reset_error_mgr; + + err->trace_level = 0; /* default = no tracing */ + err->num_warnings = 0; /* no warnings emitted yet */ + err->msg_code = 0; /* may be useful as a flag for "no error" */ + + /* Initialize message table pointers */ + err->jpeg_message_table = jpeg_std_message_table; + err->last_jpeg_message = (int) JMSG_LASTMSGCODE - 1; + + err->addon_message_table = NULL; + err->first_addon_message = 0; /* for safety */ + err->last_addon_message = 0; + + return err; +} diff --git a/dcmjpeg/libijg12/jerror12.h b/dcmjpeg/libijg12/jerror12.h new file mode 100644 index 00000000..d90bd1c1 --- /dev/null +++ b/dcmjpeg/libijg12/jerror12.h @@ -0,0 +1,310 @@ +/* + * jerror.h + * + * Copyright (C) 1994-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file defines the error and message codes for the JPEG library. + * Edit this file to add new codes, or to translate the message strings to + * some other language. + * A set of error-reporting macros are defined too. Some applications using + * the JPEG library may wish to include this file to get the error codes + * and/or the macros. + */ + +/* + * To define the enum list of message codes, include this file without + * defining macro JMESSAGE. To create a message string table, include it + * again with a suitable JMESSAGE definition (see jerror.c for an example). + */ +#ifndef JMESSAGE +#ifndef JERROR_H +/* First time through, define the enum list */ +#define JMAKE_ENUM_LIST +#else +/* Repeated inclusions of this file are no-ops unless JMESSAGE is defined */ +#define JMESSAGE(code,string) +#endif /* JERROR_H */ +#endif /* JMESSAGE */ + +#ifdef JMAKE_ENUM_LIST + +typedef enum { + +#define JMESSAGE(code,string) code , + +#endif /* JMAKE_ENUM_LIST */ + +JMESSAGE(JMSG_NOMESSAGE, "Bogus message code %d") /* Must be first entry! */ + +/* For maintenance convenience, list is alphabetical by message code name */ +JMESSAGE(JERR_ARITH_NOTIMPL, + "Sorry, there are legal restrictions on arithmetic coding") +JMESSAGE(JERR_BAD_ALIGN_TYPE, "ALIGN_TYPE is wrong, please fix") +JMESSAGE(JERR_BAD_ALLOC_CHUNK, "MAX_ALLOC_CHUNK is wrong, please fix") +JMESSAGE(JERR_BAD_BUFFER_MODE, "Bogus buffer control mode") +JMESSAGE(JERR_BAD_COMPONENT_ID, "Invalid component ID %d in SOS") +JMESSAGE(JERR_BAD_DCT_COEF, "DCT coefficient out of range") +JMESSAGE(JERR_BAD_DCTSIZE, "IDCT output block size %d not supported") +JMESSAGE(JERR_BAD_DIFF, "spatial difference out of range") +JMESSAGE(JERR_BAD_HUFF_TABLE, "Bogus Huffman table definition") +JMESSAGE(JERR_BAD_IN_COLORSPACE, "Bogus input colorspace") +JMESSAGE(JERR_BAD_J_COLORSPACE, "Bogus JPEG colorspace") +JMESSAGE(JERR_BAD_LENGTH, "Bogus marker length") +JMESSAGE(JERR_BAD_LIB_VERSION, + "Wrong JPEG library version: library is %d, caller expects %d") +JMESSAGE(JERR_BAD_LOSSLESS, + "Invalid lossless parameters Ss=%d Se=%d Ah=%d Al=%d") +JMESSAGE(JERR_BAD_LOSSLESS_SCRIPT, + "Invalid lossless parameters at scan script entry %d") +JMESSAGE(JERR_BAD_MCU_SIZE, "Sampling factors too large for interleaved scan") +JMESSAGE(JERR_BAD_POOL_ID, "Invalid memory pool code %d") +JMESSAGE(JERR_BAD_PRECISION, "Unsupported JPEG data precision %d") +JMESSAGE(JERR_BAD_PROGRESSION, + "Invalid progressive parameters Ss=%d Se=%d Ah=%d Al=%d") +JMESSAGE(JERR_BAD_PROG_SCRIPT, + "Invalid progressive parameters at scan script entry %d") +JMESSAGE(JERR_BAD_RESTART, "Invalid restart interval: %d, must be an integer multiple of the number of MCUs in an MCU_row (%d)") +JMESSAGE(JERR_BAD_SAMPLING, "Bogus sampling factors") +JMESSAGE(JERR_BAD_SCAN_SCRIPT, "Invalid scan script at entry %d") +JMESSAGE(JERR_BAD_STATE, "Improper call to JPEG library in state %d") +JMESSAGE(JERR_BAD_STRUCT_SIZE, + "JPEG parameter struct mismatch: library thinks size is %u, caller expects %u") +JMESSAGE(JERR_BAD_VIRTUAL_ACCESS, "Bogus virtual array access") +JMESSAGE(JERR_BUFFER_SIZE, "Buffer passed to JPEG library is too small") +JMESSAGE(JERR_CANT_SUSPEND, "Suspension not allowed here") +JMESSAGE(JERR_CANT_TRANSCODE, + "Cannot transcode to/from lossless JPEG datastreams") +JMESSAGE(JERR_CCIR601_NOTIMPL, "CCIR601 sampling not implemented yet") +JMESSAGE(JERR_COMPONENT_COUNT, "Too many color components: %d, max %d") +JMESSAGE(JERR_CONVERSION_NOTIMPL, "Unsupported color conversion request") +JMESSAGE(JERR_DAC_INDEX, "Bogus DAC index %d") +JMESSAGE(JERR_DAC_VALUE, "Bogus DAC value 0x%x") +JMESSAGE(JERR_DHT_INDEX, "Bogus DHT index %d") +JMESSAGE(JERR_DQT_INDEX, "Bogus DQT index %d") +JMESSAGE(JERR_EMPTY_IMAGE, "Empty JPEG image (DNL not supported)") +JMESSAGE(JERR_EMS_READ, "Read from EMS failed") +JMESSAGE(JERR_EMS_WRITE, "Write to EMS failed") +JMESSAGE(JERR_EOI_EXPECTED, "Didn't expect more than one scan") +JMESSAGE(JERR_FILE_READ, "Input file read error") +JMESSAGE(JERR_FILE_WRITE, "Output file write error --- out of disk space?") +JMESSAGE(JERR_FRACT_SAMPLE_NOTIMPL, "Fractional sampling not implemented yet") +JMESSAGE(JERR_HUFF_CLEN_OVERFLOW, "Huffman code size table overflow") +JMESSAGE(JERR_HUFF_MISSING_CODE, "Missing Huffman code table entry") +JMESSAGE(JERR_IMAGE_TOO_BIG, "Maximum supported image dimension is %u pixels") +JMESSAGE(JERR_INPUT_EMPTY, "Empty input file") +JMESSAGE(JERR_INPUT_EOF, "Premature end of input file") +JMESSAGE(JERR_MISMATCHED_QUANT_TABLE, + "Cannot transcode due to multiple use of quantization table %d") +JMESSAGE(JERR_MISSING_DATA, "Scan script does not transmit all data") +JMESSAGE(JERR_MODE_CHANGE, "Invalid color quantization mode change") +JMESSAGE(JERR_NOTIMPL, "Not implemented yet") +JMESSAGE(JERR_NOT_COMPILED, "Requested feature was omitted at compile time") +#ifdef WITH_ARITHMETIC_PATCH +JMESSAGE(JERR_NO_ARITH_TABLE, "Arithmetic table 0x%02x was not defined") +#endif +JMESSAGE(JERR_NO_BACKING_STORE, "Backing store not supported") +JMESSAGE(JERR_NO_HUFF_TABLE, "Huffman table 0x%02x was not defined") +JMESSAGE(JERR_NO_IMAGE, "JPEG datastream contains no image") +JMESSAGE(JERR_NO_LOSSLESS_SCRIPT, "Lossless encoding was requested but no scan script was supplied") +JMESSAGE(JERR_NO_QUANT_TABLE, "Quantization table 0x%02x was not defined") +JMESSAGE(JERR_NO_SOI, "Not a JPEG file: starts with 0x%02x 0x%02x") +JMESSAGE(JERR_OUT_OF_MEMORY, "Insufficient memory (case %d)") +JMESSAGE(JERR_QUANT_COMPONENTS, + "Cannot quantize more than %d color components") +JMESSAGE(JERR_QUANT_FEW_COLORS, "Cannot quantize to fewer than %d colors") +JMESSAGE(JERR_QUANT_MANY_COLORS, "Cannot quantize to more than %d colors") +JMESSAGE(JERR_SOF_DUPLICATE, "Invalid JPEG file structure: two SOF markers") +JMESSAGE(JERR_SOF_NO_SOS, "Invalid JPEG file structure: missing SOS marker") +JMESSAGE(JERR_SOF_UNSUPPORTED, "Unsupported JPEG process: SOF type 0x%02x") +JMESSAGE(JERR_SOI_DUPLICATE, "Invalid JPEG file structure: two SOI markers") +JMESSAGE(JERR_SOS_NO_SOF, "Invalid JPEG file structure: SOS before SOF") +JMESSAGE(JERR_TFILE_CREATE, "Failed to create temporary file %s") +JMESSAGE(JERR_TFILE_READ, "Read failed on temporary file") +JMESSAGE(JERR_TFILE_SEEK, "Seek failed on temporary file") +JMESSAGE(JERR_TFILE_WRITE, + "Write failed on temporary file --- out of disk space?") +JMESSAGE(JERR_TOO_LITTLE_DATA, "Application transferred too few scanlines") +JMESSAGE(JERR_UNKNOWN_MARKER, "Unsupported marker type 0x%02x") +JMESSAGE(JERR_VIRTUAL_BUG, "Virtual array controller messed up") +JMESSAGE(JERR_WIDTH_OVERFLOW, "Image too wide for this implementation") +JMESSAGE(JERR_XMS_READ, "Read from XMS failed") +JMESSAGE(JERR_XMS_WRITE, "Write to XMS failed") +JMESSAGE(JMSG_COPYRIGHT, JCOPYRIGHT) +JMESSAGE(JMSG_VERSION, JVERSION) +JMESSAGE(JTRC_16BIT_TABLES, + "Caution: quantization tables are too coarse for baseline JPEG") +JMESSAGE(JTRC_ADOBE, + "Adobe APP14 marker: version %d, flags 0x%04x 0x%04x, transform %d") +JMESSAGE(JTRC_APP0, "Unknown APP0 marker (not JFIF), length %u") +JMESSAGE(JTRC_APP14, "Unknown APP14 marker (not Adobe), length %u") +JMESSAGE(JTRC_DAC, "Define Arithmetic Table 0x%02x: 0x%02x") +JMESSAGE(JTRC_DHT, "Define Huffman Table 0x%02x") +JMESSAGE(JTRC_DQT, "Define Quantization Table %d precision %d") +JMESSAGE(JTRC_DRI, "Define Restart Interval %u") +JMESSAGE(JTRC_EMS_CLOSE, "Freed EMS handle %u") +JMESSAGE(JTRC_EMS_OPEN, "Obtained EMS handle %u") +JMESSAGE(JTRC_EOI, "End Of Image") +JMESSAGE(JTRC_HUFFBITS, " %3d %3d %3d %3d %3d %3d %3d %3d") +JMESSAGE(JTRC_JFIF, "JFIF APP0 marker: version %d.%02d, density %dx%d %d") +JMESSAGE(JTRC_JFIF_BADTHUMBNAILSIZE, + "Warning: thumbnail image size does not match data length %u") +JMESSAGE(JTRC_JFIF_EXTENSION, + "JFIF extension marker: type 0x%02x, length %u") +JMESSAGE(JTRC_JFIF_THUMBNAIL, " with %d x %d thumbnail image") +JMESSAGE(JTRC_MISC_MARKER, "Miscellaneous marker 0x%02x, length %u") +JMESSAGE(JTRC_PARMLESS_MARKER, "Unexpected marker 0x%02x") +JMESSAGE(JTRC_QUANTVALS, " %4u %4u %4u %4u %4u %4u %4u %4u") +JMESSAGE(JTRC_QUANT_3_NCOLORS, "Quantizing to %d = %d*%d*%d colors") +JMESSAGE(JTRC_QUANT_NCOLORS, "Quantizing to %d colors") +JMESSAGE(JTRC_QUANT_SELECTED, "Selected %d colors for quantization") +JMESSAGE(JTRC_RECOVERY_ACTION, "At marker 0x%02x, recovery action %d") +JMESSAGE(JTRC_RST, "RST%d") +JMESSAGE(JTRC_SMOOTH_NOTIMPL, + "Smoothing not supported with nonstandard sampling ratios") +JMESSAGE(JTRC_SOF, "Start Of Frame 0x%02x: width=%u, height=%u, components=%d") +JMESSAGE(JTRC_SOF_COMPONENT, " Component %d: %dhx%dv q=%d") +JMESSAGE(JTRC_SOI, "Start of Image") +JMESSAGE(JTRC_SOS, "Start Of Scan: %d components") +JMESSAGE(JTRC_SOS_COMPONENT, " Component %d: dc=%d ac=%d") +JMESSAGE(JTRC_SOS_PARAMS, " Ss=%d, Se=%d, Ah=%d, Al=%d") +JMESSAGE(JTRC_TFILE_CLOSE, "Closed temporary file %s") +JMESSAGE(JTRC_TFILE_OPEN, "Opened temporary file %s") +JMESSAGE(JTRC_THUMB_JPEG, + "JFIF extension marker: JPEG-compressed thumbnail image, length %u") +JMESSAGE(JTRC_THUMB_PALETTE, + "JFIF extension marker: palette thumbnail image, length %u") +JMESSAGE(JTRC_THUMB_RGB, + "JFIF extension marker: RGB thumbnail image, length %u") +JMESSAGE(JTRC_UNKNOWN_LOSSLESS_IDS, + "Unrecognized component IDs %d %d %d, assuming RGB") +JMESSAGE(JTRC_UNKNOWN_LOSSY_IDS, + "Unrecognized component IDs %d %d %d, assuming YCbCr") +JMESSAGE(JTRC_XMS_CLOSE, "Freed XMS handle %u") +JMESSAGE(JTRC_XMS_OPEN, "Obtained XMS handle %u") +JMESSAGE(JWRN_ADOBE_XFORM, "Unknown Adobe color transform code %d") +#ifdef WITH_ARITHMETIC_PATCH +JMESSAGE(JWRN_ARITH_BAD_CODE, "Corrupt JPEG data: bad arithmetic code") +#endif +JMESSAGE(JWRN_BOGUS_PROGRESSION, + "Inconsistent progression sequence for component %d coefficient %d") +JMESSAGE(JWRN_EXTRANEOUS_DATA, + "Corrupt JPEG data: %u extraneous bytes before marker 0x%02x") +JMESSAGE(JWRN_HIT_MARKER, "Corrupt JPEG data: premature end of data segment") +JMESSAGE(JWRN_HUFF_BAD_CODE, "Corrupt JPEG data: bad Huffman code") +JMESSAGE(JWRN_JFIF_MAJOR, "Warning: unknown JFIF revision number %d.%02d") +JMESSAGE(JWRN_JPEG_EOF, "Premature end of JPEG file") +JMESSAGE(JWRN_MUST_DOWNSCALE, + "Must downscale data from %d bits to %d") +JMESSAGE(JWRN_MUST_RESYNC, + "Corrupt JPEG data: found marker 0x%02x instead of RST%d") +JMESSAGE(JWRN_NOT_SEQUENTIAL, "Invalid SOS parameters for sequential JPEG") +JMESSAGE(JWRN_TOO_MUCH_DATA, "Application transferred too many scanlines") + +#ifdef JMAKE_ENUM_LIST + + JMSG_LASTMSGCODE +} J_MESSAGE_CODE; + +#undef JMAKE_ENUM_LIST +#endif /* JMAKE_ENUM_LIST */ + +/* Zap JMESSAGE macro so that future re-inclusions do nothing by default */ +#undef JMESSAGE + + +#ifndef JERROR_H +#define JERROR_H + +/* Macros to simplify using the error and trace message stuff */ +/* The first parameter is either type of cinfo pointer */ + +/* Fatal errors (print message and exit) */ +#define ERREXIT(cinfo,code) \ + ((cinfo)->err->msg_code = (code), \ + (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) +#define ERREXIT1(cinfo,code,p1) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) +#define ERREXIT2(cinfo,code,p1,p2) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) +#define ERREXIT3(cinfo,code,p1,p2,p3) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (cinfo)->err->msg_parm.i[2] = (p3), \ + (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) +#define ERREXIT4(cinfo,code,p1,p2,p3,p4) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (cinfo)->err->msg_parm.i[2] = (p3), \ + (cinfo)->err->msg_parm.i[3] = (p4), \ + (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) +#define ERREXITS(cinfo,code,str) \ + ((cinfo)->err->msg_code = (code), \ + strncpy((cinfo)->err->msg_parm.s, (str), JMSG_STR_PARM_MAX), \ + (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) + +#define MAKESTMT(stuff) do { stuff } while (0) + +/* Nonfatal errors (we can keep going, but the data is probably corrupt) */ +#define WARNMS(cinfo,code) \ + ((cinfo)->err->msg_code = (code), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1)) +#define WARNMS1(cinfo,code,p1) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1)) +#define WARNMS2(cinfo,code,p1,p2) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1)) + +/* Informational/debugging messages */ +#define TRACEMS(cinfo,lvl,code) \ + ((cinfo)->err->msg_code = (code), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl))) +#define TRACEMS1(cinfo,lvl,code,p1) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl))) +#define TRACEMS2(cinfo,lvl,code,p1,p2) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl))) +#define TRACEMS3(cinfo,lvl,code,p1,p2,p3) \ + MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \ + _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); \ + (cinfo)->err->msg_code = (code); \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); ) +#define TRACEMS4(cinfo,lvl,code,p1,p2,p3,p4) \ + MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \ + _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \ + (cinfo)->err->msg_code = (code); \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); ) +#define TRACEMS5(cinfo,lvl,code,p1,p2,p3,p4,p5) \ + MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \ + _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \ + _mp[4] = (p5); \ + (cinfo)->err->msg_code = (code); \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); ) +#define TRACEMS8(cinfo,lvl,code,p1,p2,p3,p4,p5,p6,p7,p8) \ + MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \ + _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \ + _mp[4] = (p5); _mp[5] = (p6); _mp[6] = (p7); _mp[7] = (p8); \ + (cinfo)->err->msg_code = (code); \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); ) +#define TRACEMSS(cinfo,lvl,code,str) \ + ((cinfo)->err->msg_code = (code), \ + strncpy((cinfo)->err->msg_parm.s, (str), JMSG_STR_PARM_MAX), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl))) + +#endif /* JERROR_H */ diff --git a/dcmjpeg/libijg12/jfdctflt.c b/dcmjpeg/libijg12/jfdctflt.c new file mode 100644 index 00000000..e3557a73 --- /dev/null +++ b/dcmjpeg/libijg12/jfdctflt.c @@ -0,0 +1,168 @@ +/* + * jfdctflt.c + * + * Copyright (C) 1994-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains a floating-point implementation of the + * forward DCT (Discrete Cosine Transform). + * + * This implementation should be more accurate than either of the integer + * DCT implementations. However, it may not give the same results on all + * machines because of differences in roundoff behavior. Speed will depend + * on the hardware's floating point capacity. + * + * A 2-D DCT can be done by 1-D DCT on each row followed by 1-D DCT + * on each column. Direct algorithms are also available, but they are + * much more complex and seem not to be any faster when reduced to code. + * + * This implementation is based on Arai, Agui, and Nakajima's algorithm for + * scaled DCT. Their original paper (Trans. IEICE E-71(11):1095) is in + * Japanese, but the algorithm is described in the Pennebaker & Mitchell + * JPEG textbook (see REFERENCES section in file README). The following code + * is based directly on figure 4-8 in P&M. + * While an 8-point DCT cannot be done in less than 11 multiplies, it is + * possible to arrange the computation so that many of the multiplies are + * simple scalings of the final outputs. These multiplies can then be + * folded into the multiplications or divisions by the JPEG quantization + * table entries. The AA&N method leaves only 5 multiplies and 29 adds + * to be done in the DCT itself. + * The primary disadvantage of this method is that with a fixed-point + * implementation, accuracy is lost due to imprecise representation of the + * scaled quantization values. However, that problem does not arise if + * we use floating point arithmetic. + */ + +#define JPEG_INTERNALS +#include "jinclude12.h" +#include "jpeglib12.h" +#include "jdct12.h" /* Private declarations for DCT subsystem */ + +#ifdef DCT_FLOAT_SUPPORTED + + +/* + * This module is specialized to the case DCTSIZE = 8. + */ + +#if DCTSIZE != 8 + Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */ +#endif + + +/* + * Perform the forward DCT on one block of samples. + */ + +GLOBAL(void) +jpeg_fdct_float (FAST_FLOAT * data) +{ + FAST_FLOAT tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + FAST_FLOAT tmp10, tmp11, tmp12, tmp13; + FAST_FLOAT z1, z2, z3, z4, z5, z11, z13; + FAST_FLOAT *dataptr; + int ctr; + + /* Pass 1: process rows. */ + + dataptr = data; + for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { + tmp0 = dataptr[0] + dataptr[7]; + tmp7 = dataptr[0] - dataptr[7]; + tmp1 = dataptr[1] + dataptr[6]; + tmp6 = dataptr[1] - dataptr[6]; + tmp2 = dataptr[2] + dataptr[5]; + tmp5 = dataptr[2] - dataptr[5]; + tmp3 = dataptr[3] + dataptr[4]; + tmp4 = dataptr[3] - dataptr[4]; + + /* Even part */ + + tmp10 = tmp0 + tmp3; /* phase 2 */ + tmp13 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp1 - tmp2; + + dataptr[0] = tmp10 + tmp11; /* phase 3 */ + dataptr[4] = tmp10 - tmp11; + + z1 = (tmp12 + tmp13) * ((FAST_FLOAT) 0.707106781); /* c4 */ + dataptr[2] = tmp13 + z1; /* phase 5 */ + dataptr[6] = tmp13 - z1; + + /* Odd part */ + + tmp10 = tmp4 + tmp5; /* phase 2 */ + tmp11 = tmp5 + tmp6; + tmp12 = tmp6 + tmp7; + + /* The rotator is modified from fig 4-8 to avoid extra negations. */ + z5 = (tmp10 - tmp12) * ((FAST_FLOAT) 0.382683433); /* c6 */ + z2 = ((FAST_FLOAT) 0.541196100) * tmp10 + z5; /* c2-c6 */ + z4 = ((FAST_FLOAT) 1.306562965) * tmp12 + z5; /* c2+c6 */ + z3 = tmp11 * ((FAST_FLOAT) 0.707106781); /* c4 */ + + z11 = tmp7 + z3; /* phase 5 */ + z13 = tmp7 - z3; + + dataptr[5] = z13 + z2; /* phase 6 */ + dataptr[3] = z13 - z2; + dataptr[1] = z11 + z4; + dataptr[7] = z11 - z4; + + dataptr += DCTSIZE; /* advance pointer to next row */ + } + + /* Pass 2: process columns. */ + + dataptr = data; + for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { + tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*7]; + tmp7 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*7]; + tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*6]; + tmp6 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*6]; + tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*5]; + tmp5 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*5]; + tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*4]; + tmp4 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*4]; + + /* Even part */ + + tmp10 = tmp0 + tmp3; /* phase 2 */ + tmp13 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp1 - tmp2; + + dataptr[DCTSIZE*0] = tmp10 + tmp11; /* phase 3 */ + dataptr[DCTSIZE*4] = tmp10 - tmp11; + + z1 = (tmp12 + tmp13) * ((FAST_FLOAT) 0.707106781); /* c4 */ + dataptr[DCTSIZE*2] = tmp13 + z1; /* phase 5 */ + dataptr[DCTSIZE*6] = tmp13 - z1; + + /* Odd part */ + + tmp10 = tmp4 + tmp5; /* phase 2 */ + tmp11 = tmp5 + tmp6; + tmp12 = tmp6 + tmp7; + + /* The rotator is modified from fig 4-8 to avoid extra negations. */ + z5 = (tmp10 - tmp12) * ((FAST_FLOAT) 0.382683433); /* c6 */ + z2 = ((FAST_FLOAT) 0.541196100) * tmp10 + z5; /* c2-c6 */ + z4 = ((FAST_FLOAT) 1.306562965) * tmp12 + z5; /* c2+c6 */ + z3 = tmp11 * ((FAST_FLOAT) 0.707106781); /* c4 */ + + z11 = tmp7 + z3; /* phase 5 */ + z13 = tmp7 - z3; + + dataptr[DCTSIZE*5] = z13 + z2; /* phase 6 */ + dataptr[DCTSIZE*3] = z13 - z2; + dataptr[DCTSIZE*1] = z11 + z4; + dataptr[DCTSIZE*7] = z11 - z4; + + dataptr++; /* advance pointer to next column */ + } +} + +#endif /* DCT_FLOAT_SUPPORTED */ diff --git a/dcmjpeg/libijg12/jfdctfst.c b/dcmjpeg/libijg12/jfdctfst.c new file mode 100644 index 00000000..8a69b7cc --- /dev/null +++ b/dcmjpeg/libijg12/jfdctfst.c @@ -0,0 +1,224 @@ +/* + * jfdctfst.c + * + * Copyright (C) 1994-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains a fast, not so accurate integer implementation of the + * forward DCT (Discrete Cosine Transform). + * + * A 2-D DCT can be done by 1-D DCT on each row followed by 1-D DCT + * on each column. Direct algorithms are also available, but they are + * much more complex and seem not to be any faster when reduced to code. + * + * This implementation is based on Arai, Agui, and Nakajima's algorithm for + * scaled DCT. Their original paper (Trans. IEICE E-71(11):1095) is in + * Japanese, but the algorithm is described in the Pennebaker & Mitchell + * JPEG textbook (see REFERENCES section in file README). The following code + * is based directly on figure 4-8 in P&M. + * While an 8-point DCT cannot be done in less than 11 multiplies, it is + * possible to arrange the computation so that many of the multiplies are + * simple scalings of the final outputs. These multiplies can then be + * folded into the multiplications or divisions by the JPEG quantization + * table entries. The AA&N method leaves only 5 multiplies and 29 adds + * to be done in the DCT itself. + * The primary disadvantage of this method is that with fixed-point math, + * accuracy is lost due to imprecise representation of the scaled + * quantization values. The smaller the quantization table entry, the less + * precise the scaled value, so this implementation does worse with high- + * quality-setting files than with low-quality ones. + */ + +#define JPEG_INTERNALS +#include "jinclude12.h" +#include "jpeglib12.h" +#include "jdct12.h" /* Private declarations for DCT subsystem */ + +#ifdef DCT_IFAST_SUPPORTED + + +/* + * This module is specialized to the case DCTSIZE = 8. + */ + +#if DCTSIZE != 8 + Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */ +#endif + + +/* Scaling decisions are generally the same as in the LL&M algorithm; + * see jfdctint.c for more details. However, we choose to descale + * (right shift) multiplication products as soon as they are formed, + * rather than carrying additional fractional bits into subsequent additions. + * This compromises accuracy slightly, but it lets us save a few shifts. + * More importantly, 16-bit arithmetic is then adequate (for 8-bit samples) + * everywhere except in the multiplications proper; this saves a good deal + * of work on 16-bit-int machines. + * + * Again to save a few shifts, the intermediate results between pass 1 and + * pass 2 are not upscaled, but are represented only to integral precision. + * + * A final compromise is to represent the multiplicative constants to only + * 8 fractional bits, rather than 13. This saves some shifting work on some + * machines, and may also reduce the cost of multiplication (since there + * are fewer one-bits in the constants). + */ + +#define CONST_BITS 8 + + +/* Some C compilers fail to reduce "FIX(constant)" at compile time, thus + * causing a lot of useless floating-point operations at run time. + * To get around this we use the following pre-calculated constants. + * If you change CONST_BITS you may want to add appropriate values. + * (With a reasonable C compiler, you can just rely on the FIX() macro...) + */ + +#if CONST_BITS == 8 +#define FIX_0_382683433 ((IJG_INT32) 98) /* FIX(0.382683433) */ +#define FIX_0_541196100 ((IJG_INT32) 139) /* FIX(0.541196100) */ +#define FIX_0_707106781 ((IJG_INT32) 181) /* FIX(0.707106781) */ +#define FIX_1_306562965 ((IJG_INT32) 334) /* FIX(1.306562965) */ +#else +#define FIX_0_382683433 FIX(0.382683433) +#define FIX_0_541196100 FIX(0.541196100) +#define FIX_0_707106781 FIX(0.707106781) +#define FIX_1_306562965 FIX(1.306562965) +#endif + + +/* We can gain a little more speed, with a further compromise in accuracy, + * by omitting the addition in a descaling shift. This yields an incorrectly + * rounded result half the time... + */ + +#ifndef USE_ACCURATE_ROUNDING +#undef DESCALE +#define DESCALE(x,n) RIGHT_SHIFT(x, n) +#endif + + +/* Multiply a DCTELEM variable by an IJG_INT32 constant, and immediately + * descale to yield a DCTELEM result. + */ + +#define MULTIPLY(var,const) ((DCTELEM) DESCALE((var) * (const), CONST_BITS)) + + +/* + * Perform the forward DCT on one block of samples. + */ + +GLOBAL(void) +jpeg_fdct_ifast (DCTELEM * data) +{ + DCTELEM tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + DCTELEM tmp10, tmp11, tmp12, tmp13; + DCTELEM z1, z2, z3, z4, z5, z11, z13; + DCTELEM *dataptr; + int ctr; + SHIFT_TEMPS + + /* Pass 1: process rows. */ + + dataptr = data; + for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { + tmp0 = dataptr[0] + dataptr[7]; + tmp7 = dataptr[0] - dataptr[7]; + tmp1 = dataptr[1] + dataptr[6]; + tmp6 = dataptr[1] - dataptr[6]; + tmp2 = dataptr[2] + dataptr[5]; + tmp5 = dataptr[2] - dataptr[5]; + tmp3 = dataptr[3] + dataptr[4]; + tmp4 = dataptr[3] - dataptr[4]; + + /* Even part */ + + tmp10 = tmp0 + tmp3; /* phase 2 */ + tmp13 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp1 - tmp2; + + dataptr[0] = tmp10 + tmp11; /* phase 3 */ + dataptr[4] = tmp10 - tmp11; + + z1 = MULTIPLY(tmp12 + tmp13, FIX_0_707106781); /* c4 */ + dataptr[2] = tmp13 + z1; /* phase 5 */ + dataptr[6] = tmp13 - z1; + + /* Odd part */ + + tmp10 = tmp4 + tmp5; /* phase 2 */ + tmp11 = tmp5 + tmp6; + tmp12 = tmp6 + tmp7; + + /* The rotator is modified from fig 4-8 to avoid extra negations. */ + z5 = MULTIPLY(tmp10 - tmp12, FIX_0_382683433); /* c6 */ + z2 = MULTIPLY(tmp10, FIX_0_541196100) + z5; /* c2-c6 */ + z4 = MULTIPLY(tmp12, FIX_1_306562965) + z5; /* c2+c6 */ + z3 = MULTIPLY(tmp11, FIX_0_707106781); /* c4 */ + + z11 = tmp7 + z3; /* phase 5 */ + z13 = tmp7 - z3; + + dataptr[5] = z13 + z2; /* phase 6 */ + dataptr[3] = z13 - z2; + dataptr[1] = z11 + z4; + dataptr[7] = z11 - z4; + + dataptr += DCTSIZE; /* advance pointer to next row */ + } + + /* Pass 2: process columns. */ + + dataptr = data; + for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { + tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*7]; + tmp7 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*7]; + tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*6]; + tmp6 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*6]; + tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*5]; + tmp5 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*5]; + tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*4]; + tmp4 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*4]; + + /* Even part */ + + tmp10 = tmp0 + tmp3; /* phase 2 */ + tmp13 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp1 - tmp2; + + dataptr[DCTSIZE*0] = tmp10 + tmp11; /* phase 3 */ + dataptr[DCTSIZE*4] = tmp10 - tmp11; + + z1 = MULTIPLY(tmp12 + tmp13, FIX_0_707106781); /* c4 */ + dataptr[DCTSIZE*2] = tmp13 + z1; /* phase 5 */ + dataptr[DCTSIZE*6] = tmp13 - z1; + + /* Odd part */ + + tmp10 = tmp4 + tmp5; /* phase 2 */ + tmp11 = tmp5 + tmp6; + tmp12 = tmp6 + tmp7; + + /* The rotator is modified from fig 4-8 to avoid extra negations. */ + z5 = MULTIPLY(tmp10 - tmp12, FIX_0_382683433); /* c6 */ + z2 = MULTIPLY(tmp10, FIX_0_541196100) + z5; /* c2-c6 */ + z4 = MULTIPLY(tmp12, FIX_1_306562965) + z5; /* c2+c6 */ + z3 = MULTIPLY(tmp11, FIX_0_707106781); /* c4 */ + + z11 = tmp7 + z3; /* phase 5 */ + z13 = tmp7 - z3; + + dataptr[DCTSIZE*5] = z13 + z2; /* phase 6 */ + dataptr[DCTSIZE*3] = z13 - z2; + dataptr[DCTSIZE*1] = z11 + z4; + dataptr[DCTSIZE*7] = z11 - z4; + + dataptr++; /* advance pointer to next column */ + } +} + +#endif /* DCT_IFAST_SUPPORTED */ diff --git a/dcmjpeg/libijg12/jfdctint.c b/dcmjpeg/libijg12/jfdctint.c new file mode 100644 index 00000000..c9d90859 --- /dev/null +++ b/dcmjpeg/libijg12/jfdctint.c @@ -0,0 +1,283 @@ +/* + * jfdctint.c + * + * Copyright (C) 1991-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains a slow-but-accurate integer implementation of the + * forward DCT (Discrete Cosine Transform). + * + * A 2-D DCT can be done by 1-D DCT on each row followed by 1-D DCT + * on each column. Direct algorithms are also available, but they are + * much more complex and seem not to be any faster when reduced to code. + * + * This implementation is based on an algorithm described in + * C. Loeffler, A. Ligtenberg and G. Moschytz, "Practical Fast 1-D DCT + * Algorithms with 11 Multiplications", Proc. Int'l. Conf. on Acoustics, + * Speech, and Signal Processing 1989 (ICASSP '89), pp. 988-991. + * The primary algorithm described there uses 11 multiplies and 29 adds. + * We use their alternate method with 12 multiplies and 32 adds. + * The advantage of this method is that no data path contains more than one + * multiplication; this allows a very simple and accurate implementation in + * scaled fixed-point arithmetic, with a minimal number of shifts. + */ + +#define JPEG_INTERNALS +#include "jinclude12.h" +#include "jpeglib12.h" +#include "jdct12.h" /* Private declarations for DCT subsystem */ + +#ifdef DCT_ISLOW_SUPPORTED + + +/* + * This module is specialized to the case DCTSIZE = 8. + */ + +#if DCTSIZE != 8 + Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */ +#endif + + +/* + * The poop on this scaling stuff is as follows: + * + * Each 1-D DCT step produces outputs which are a factor of sqrt(N) + * larger than the true DCT outputs. The final outputs are therefore + * a factor of N larger than desired; since N=8 this can be cured by + * a simple right shift at the end of the algorithm. The advantage of + * this arrangement is that we save two multiplications per 1-D DCT, + * because the y0 and y4 outputs need not be divided by sqrt(N). + * In the IJG code, this factor of 8 is removed by the quantization step + * (in jcdctmgr.c), NOT in this module. + * + * We have to do addition and subtraction of the integer inputs, which + * is no problem, and multiplication by fractional constants, which is + * a problem to do in integer arithmetic. We multiply all the constants + * by CONST_SCALE and convert them to integer constants (thus retaining + * CONST_BITS bits of precision in the constants). After doing a + * multiplication we have to divide the product by CONST_SCALE, with proper + * rounding, to produce the correct output. This division can be done + * cheaply as a right shift of CONST_BITS bits. We postpone shifting + * as long as possible so that partial sums can be added together with + * full fractional precision. + * + * The outputs of the first pass are scaled up by PASS1_BITS bits so that + * they are represented to better-than-integral precision. These outputs + * require BITS_IN_JSAMPLE + PASS1_BITS + 3 bits; this fits in a 16-bit word + * with the recommended scaling. (For 12-bit sample data, the intermediate + * array is IJG_INT32 anyway.) + * + * To avoid overflow of the 32-bit intermediate results in pass 2, we must + * have BITS_IN_JSAMPLE + CONST_BITS + PASS1_BITS <= 26. Error analysis + * shows that the values given below are the most effective. + */ + +#if BITS_IN_JSAMPLE == 8 +#define CONST_BITS 13 +#define PASS1_BITS 2 +#else +#define CONST_BITS 13 +#define PASS1_BITS 1 /* lose a little precision to avoid overflow */ +#endif + +/* Some C compilers fail to reduce "FIX(constant)" at compile time, thus + * causing a lot of useless floating-point operations at run time. + * To get around this we use the following pre-calculated constants. + * If you change CONST_BITS you may want to add appropriate values. + * (With a reasonable C compiler, you can just rely on the FIX() macro...) + */ + +#if CONST_BITS == 13 +#define FIX_0_298631336 ((IJG_INT32) 2446) /* FIX(0.298631336) */ +#define FIX_0_390180644 ((IJG_INT32) 3196) /* FIX(0.390180644) */ +#define FIX_0_541196100 ((IJG_INT32) 4433) /* FIX(0.541196100) */ +#define FIX_0_765366865 ((IJG_INT32) 6270) /* FIX(0.765366865) */ +#define FIX_0_899976223 ((IJG_INT32) 7373) /* FIX(0.899976223) */ +#define FIX_1_175875602 ((IJG_INT32) 9633) /* FIX(1.175875602) */ +#define FIX_1_501321110 ((IJG_INT32) 12299) /* FIX(1.501321110) */ +#define FIX_1_847759065 ((IJG_INT32) 15137) /* FIX(1.847759065) */ +#define FIX_1_961570560 ((IJG_INT32) 16069) /* FIX(1.961570560) */ +#define FIX_2_053119869 ((IJG_INT32) 16819) /* FIX(2.053119869) */ +#define FIX_2_562915447 ((IJG_INT32) 20995) /* FIX(2.562915447) */ +#define FIX_3_072711026 ((IJG_INT32) 25172) /* FIX(3.072711026) */ +#else +#define FIX_0_298631336 FIX(0.298631336) +#define FIX_0_390180644 FIX(0.390180644) +#define FIX_0_541196100 FIX(0.541196100) +#define FIX_0_765366865 FIX(0.765366865) +#define FIX_0_899976223 FIX(0.899976223) +#define FIX_1_175875602 FIX(1.175875602) +#define FIX_1_501321110 FIX(1.501321110) +#define FIX_1_847759065 FIX(1.847759065) +#define FIX_1_961570560 FIX(1.961570560) +#define FIX_2_053119869 FIX(2.053119869) +#define FIX_2_562915447 FIX(2.562915447) +#define FIX_3_072711026 FIX(3.072711026) +#endif + + +/* Multiply an IJG_INT32 variable by an IJG_INT32 constant to yield an IJG_INT32 result. + * For 8-bit samples with the recommended scaling, all the variable + * and constant values involved are no more than 16 bits wide, so a + * 16x16->32 bit multiply can be used instead of a full 32x32 multiply. + * For 12-bit samples, a full 32-bit multiplication will be needed. + */ + +#if BITS_IN_JSAMPLE == 8 +#define MULTIPLY(var,const) MULTIPLY16C16(var,const) +#else +#define MULTIPLY(var,const) ((var) * (const)) +#endif + + +/* + * Perform the forward DCT on one block of samples. + */ + +GLOBAL(void) +jpeg_fdct_islow (DCTELEM * data) +{ + IJG_INT32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + IJG_INT32 tmp10, tmp11, tmp12, tmp13; + IJG_INT32 z1, z2, z3, z4, z5; + DCTELEM *dataptr; + int ctr; + SHIFT_TEMPS + + /* Pass 1: process rows. */ + /* Note results are scaled up by sqrt(8) compared to a true DCT; */ + /* furthermore, we scale the results by 2**PASS1_BITS. */ + + dataptr = data; + for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { + tmp0 = dataptr[0] + dataptr[7]; + tmp7 = dataptr[0] - dataptr[7]; + tmp1 = dataptr[1] + dataptr[6]; + tmp6 = dataptr[1] - dataptr[6]; + tmp2 = dataptr[2] + dataptr[5]; + tmp5 = dataptr[2] - dataptr[5]; + tmp3 = dataptr[3] + dataptr[4]; + tmp4 = dataptr[3] - dataptr[4]; + + /* Even part per LL&M figure 1 --- note that published figure is faulty; + * rotator "sqrt(2)*c1" should be "sqrt(2)*c6". + */ + + tmp10 = tmp0 + tmp3; + tmp13 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp1 - tmp2; + + dataptr[0] = (DCTELEM) ((tmp10 + tmp11) << PASS1_BITS); + dataptr[4] = (DCTELEM) ((tmp10 - tmp11) << PASS1_BITS); + + z1 = MULTIPLY(tmp12 + tmp13, FIX_0_541196100); + dataptr[2] = (DCTELEM) DESCALE(z1 + MULTIPLY(tmp13, FIX_0_765366865), + CONST_BITS-PASS1_BITS); + dataptr[6] = (DCTELEM) DESCALE(z1 + MULTIPLY(tmp12, - FIX_1_847759065), + CONST_BITS-PASS1_BITS); + + /* Odd part per figure 8 --- note paper omits factor of sqrt(2). + * cK represents cos(K*pi/16). + * i0..i3 in the paper are tmp4..tmp7 here. + */ + + z1 = tmp4 + tmp7; + z2 = tmp5 + tmp6; + z3 = tmp4 + tmp6; + z4 = tmp5 + tmp7; + z5 = MULTIPLY(z3 + z4, FIX_1_175875602); /* sqrt(2) * c3 */ + + tmp4 = MULTIPLY(tmp4, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */ + tmp5 = MULTIPLY(tmp5, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */ + tmp6 = MULTIPLY(tmp6, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */ + tmp7 = MULTIPLY(tmp7, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */ + z1 = MULTIPLY(z1, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */ + z2 = MULTIPLY(z2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */ + z3 = MULTIPLY(z3, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */ + z4 = MULTIPLY(z4, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */ + + z3 += z5; + z4 += z5; + + dataptr[7] = (DCTELEM) DESCALE(tmp4 + z1 + z3, CONST_BITS-PASS1_BITS); + dataptr[5] = (DCTELEM) DESCALE(tmp5 + z2 + z4, CONST_BITS-PASS1_BITS); + dataptr[3] = (DCTELEM) DESCALE(tmp6 + z2 + z3, CONST_BITS-PASS1_BITS); + dataptr[1] = (DCTELEM) DESCALE(tmp7 + z1 + z4, CONST_BITS-PASS1_BITS); + + dataptr += DCTSIZE; /* advance pointer to next row */ + } + + /* Pass 2: process columns. + * We remove the PASS1_BITS scaling, but leave the results scaled up + * by an overall factor of 8. + */ + + dataptr = data; + for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { + tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*7]; + tmp7 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*7]; + tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*6]; + tmp6 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*6]; + tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*5]; + tmp5 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*5]; + tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*4]; + tmp4 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*4]; + + /* Even part per LL&M figure 1 --- note that published figure is faulty; + * rotator "sqrt(2)*c1" should be "sqrt(2)*c6". + */ + + tmp10 = tmp0 + tmp3; + tmp13 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp1 - tmp2; + + dataptr[DCTSIZE*0] = (DCTELEM) DESCALE(tmp10 + tmp11, PASS1_BITS); + dataptr[DCTSIZE*4] = (DCTELEM) DESCALE(tmp10 - tmp11, PASS1_BITS); + + z1 = MULTIPLY(tmp12 + tmp13, FIX_0_541196100); + dataptr[DCTSIZE*2] = (DCTELEM) DESCALE(z1 + MULTIPLY(tmp13, FIX_0_765366865), + CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*6] = (DCTELEM) DESCALE(z1 + MULTIPLY(tmp12, - FIX_1_847759065), + CONST_BITS+PASS1_BITS); + + /* Odd part per figure 8 --- note paper omits factor of sqrt(2). + * cK represents cos(K*pi/16). + * i0..i3 in the paper are tmp4..tmp7 here. + */ + + z1 = tmp4 + tmp7; + z2 = tmp5 + tmp6; + z3 = tmp4 + tmp6; + z4 = tmp5 + tmp7; + z5 = MULTIPLY(z3 + z4, FIX_1_175875602); /* sqrt(2) * c3 */ + + tmp4 = MULTIPLY(tmp4, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */ + tmp5 = MULTIPLY(tmp5, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */ + tmp6 = MULTIPLY(tmp6, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */ + tmp7 = MULTIPLY(tmp7, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */ + z1 = MULTIPLY(z1, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */ + z2 = MULTIPLY(z2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */ + z3 = MULTIPLY(z3, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */ + z4 = MULTIPLY(z4, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */ + + z3 += z5; + z4 += z5; + + dataptr[DCTSIZE*7] = (DCTELEM) DESCALE(tmp4 + z1 + z3, + CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*5] = (DCTELEM) DESCALE(tmp5 + z2 + z4, + CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp6 + z2 + z3, + CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(tmp7 + z1 + z4, + CONST_BITS+PASS1_BITS); + + dataptr++; /* advance pointer to next column */ + } +} + +#endif /* DCT_ISLOW_SUPPORTED */ diff --git a/dcmjpeg/libijg12/jidctflt.c b/dcmjpeg/libijg12/jidctflt.c new file mode 100644 index 00000000..972a1264 --- /dev/null +++ b/dcmjpeg/libijg12/jidctflt.c @@ -0,0 +1,242 @@ +/* + * jidctflt.c + * + * Copyright (C) 1994-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains a floating-point implementation of the + * inverse DCT (Discrete Cosine Transform). In the IJG code, this routine + * must also perform dequantization of the input coefficients. + * + * This implementation should be more accurate than either of the integer + * IDCT implementations. However, it may not give the same results on all + * machines because of differences in roundoff behavior. Speed will depend + * on the hardware's floating point capacity. + * + * A 2-D IDCT can be done by 1-D IDCT on each column followed by 1-D IDCT + * on each row (or vice versa, but it's more convenient to emit a row at + * a time). Direct algorithms are also available, but they are much more + * complex and seem not to be any faster when reduced to code. + * + * This implementation is based on Arai, Agui, and Nakajima's algorithm for + * scaled DCT. Their original paper (Trans. IEICE E-71(11):1095) is in + * Japanese, but the algorithm is described in the Pennebaker & Mitchell + * JPEG textbook (see REFERENCES section in file README). The following code + * is based directly on figure 4-8 in P&M. + * While an 8-point DCT cannot be done in less than 11 multiplies, it is + * possible to arrange the computation so that many of the multiplies are + * simple scalings of the final outputs. These multiplies can then be + * folded into the multiplications or divisions by the JPEG quantization + * table entries. The AA&N method leaves only 5 multiplies and 29 adds + * to be done in the DCT itself. + * The primary disadvantage of this method is that with a fixed-point + * implementation, accuracy is lost due to imprecise representation of the + * scaled quantization values. However, that problem does not arise if + * we use floating point arithmetic. + */ + +#define JPEG_INTERNALS +#include "jinclude12.h" +#include "jpeglib12.h" +#include "jdct12.h" /* Private declarations for DCT subsystem */ + +#ifdef DCT_FLOAT_SUPPORTED + + +/* + * This module is specialized to the case DCTSIZE = 8. + */ + +#if DCTSIZE != 8 + Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */ +#endif + + +/* Dequantize a coefficient by multiplying it by the multiplier-table + * entry; produce a float result. + */ + +#define DEQUANTIZE(coef,quantval) (((FAST_FLOAT) (coef)) * (quantval)) + + +/* + * Perform dequantization and inverse DCT on one block of coefficients. + */ + +GLOBAL(void) +jpeg_idct_float (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + FAST_FLOAT tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + FAST_FLOAT tmp10, tmp11, tmp12, tmp13; + FAST_FLOAT z5, z10, z11, z12, z13; + JCOEFPTR inptr; + FLOAT_MULT_TYPE * quantptr; + FAST_FLOAT * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + FAST_FLOAT workspace[DCTSIZE2]; /* buffers data between passes */ + SHIFT_TEMPS + + /* Pass 1: process columns from input, store into work array. */ + + inptr = coef_block; + quantptr = (FLOAT_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = DCTSIZE; ctr > 0; ctr--) { + /* Due to quantization, we will usually find that many of the input + * coefficients are zero, especially the AC terms. We can exploit this + * by short-circuiting the IDCT calculation for any column in which all + * the AC terms are zero. In that case each output is equal to the + * DC coefficient (with scale factor as needed). + * With typical images and quantization tables, half or more of the + * column DCT calculations can be simplified this way. + */ + + if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*2] == 0 && + inptr[DCTSIZE*3] == 0 && inptr[DCTSIZE*4] == 0 && + inptr[DCTSIZE*5] == 0 && inptr[DCTSIZE*6] == 0 && + inptr[DCTSIZE*7] == 0) { + /* AC terms all zero */ + FAST_FLOAT dcval = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + + wsptr[DCTSIZE*0] = dcval; + wsptr[DCTSIZE*1] = dcval; + wsptr[DCTSIZE*2] = dcval; + wsptr[DCTSIZE*3] = dcval; + wsptr[DCTSIZE*4] = dcval; + wsptr[DCTSIZE*5] = dcval; + wsptr[DCTSIZE*6] = dcval; + wsptr[DCTSIZE*7] = dcval; + + inptr++; /* advance pointers to next column */ + quantptr++; + wsptr++; + continue; + } + + /* Even part */ + + tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + tmp1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + tmp2 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); + tmp3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); + + tmp10 = tmp0 + tmp2; /* phase 3 */ + tmp11 = tmp0 - tmp2; + + tmp13 = tmp1 + tmp3; /* phases 5-3 */ + tmp12 = (tmp1 - tmp3) * ((FAST_FLOAT) 1.414213562) - tmp13; /* 2*c4 */ + + tmp0 = tmp10 + tmp13; /* phase 2 */ + tmp3 = tmp10 - tmp13; + tmp1 = tmp11 + tmp12; + tmp2 = tmp11 - tmp12; + + /* Odd part */ + + tmp4 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + tmp5 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + tmp6 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); + tmp7 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); + + z13 = tmp6 + tmp5; /* phase 6 */ + z10 = tmp6 - tmp5; + z11 = tmp4 + tmp7; + z12 = tmp4 - tmp7; + + tmp7 = z11 + z13; /* phase 5 */ + tmp11 = (z11 - z13) * ((FAST_FLOAT) 1.414213562); /* 2*c4 */ + + z5 = (z10 + z12) * ((FAST_FLOAT) 1.847759065); /* 2*c2 */ + tmp10 = ((FAST_FLOAT) 1.082392200) * z12 - z5; /* 2*(c2-c6) */ + tmp12 = ((FAST_FLOAT) -2.613125930) * z10 + z5; /* -2*(c2+c6) */ + + tmp6 = tmp12 - tmp7; /* phase 2 */ + tmp5 = tmp11 - tmp6; + tmp4 = tmp10 + tmp5; + + wsptr[DCTSIZE*0] = tmp0 + tmp7; + wsptr[DCTSIZE*7] = tmp0 - tmp7; + wsptr[DCTSIZE*1] = tmp1 + tmp6; + wsptr[DCTSIZE*6] = tmp1 - tmp6; + wsptr[DCTSIZE*2] = tmp2 + tmp5; + wsptr[DCTSIZE*5] = tmp2 - tmp5; + wsptr[DCTSIZE*4] = tmp3 + tmp4; + wsptr[DCTSIZE*3] = tmp3 - tmp4; + + inptr++; /* advance pointers to next column */ + quantptr++; + wsptr++; + } + + /* Pass 2: process rows from work array, store into output array. */ + /* Note that we must descale the results by a factor of 8 == 2**3. */ + + wsptr = workspace; + for (ctr = 0; ctr < DCTSIZE; ctr++) { + outptr = output_buf[ctr] + output_col; + /* Rows of zeroes can be exploited in the same way as we did with columns. + * However, the column calculation has created many nonzero AC terms, so + * the simplification applies less often (typically 5% to 10% of the time). + * And testing floats for zero is relatively expensive, so we don't bother. + */ + + /* Even part */ + + tmp10 = wsptr[0] + wsptr[4]; + tmp11 = wsptr[0] - wsptr[4]; + + tmp13 = wsptr[2] + wsptr[6]; + tmp12 = (wsptr[2] - wsptr[6]) * ((FAST_FLOAT) 1.414213562) - tmp13; + + tmp0 = tmp10 + tmp13; + tmp3 = tmp10 - tmp13; + tmp1 = tmp11 + tmp12; + tmp2 = tmp11 - tmp12; + + /* Odd part */ + + z13 = wsptr[5] + wsptr[3]; + z10 = wsptr[5] - wsptr[3]; + z11 = wsptr[1] + wsptr[7]; + z12 = wsptr[1] - wsptr[7]; + + tmp7 = z11 + z13; + tmp11 = (z11 - z13) * ((FAST_FLOAT) 1.414213562); + + z5 = (z10 + z12) * ((FAST_FLOAT) 1.847759065); /* 2*c2 */ + tmp10 = ((FAST_FLOAT) 1.082392200) * z12 - z5; /* 2*(c2-c6) */ + tmp12 = ((FAST_FLOAT) -2.613125930) * z10 + z5; /* -2*(c2+c6) */ + + tmp6 = tmp12 - tmp7; + tmp5 = tmp11 - tmp6; + tmp4 = tmp10 + tmp5; + + /* Final output stage: scale down by a factor of 8 and range-limit */ + + outptr[0] = range_limit[(int) DESCALE((IJG_INT32) (tmp0 + tmp7), 3) + & RANGE_MASK]; + outptr[7] = range_limit[(int) DESCALE((IJG_INT32) (tmp0 - tmp7), 3) + & RANGE_MASK]; + outptr[1] = range_limit[(int) DESCALE((IJG_INT32) (tmp1 + tmp6), 3) + & RANGE_MASK]; + outptr[6] = range_limit[(int) DESCALE((IJG_INT32) (tmp1 - tmp6), 3) + & RANGE_MASK]; + outptr[2] = range_limit[(int) DESCALE((IJG_INT32) (tmp2 + tmp5), 3) + & RANGE_MASK]; + outptr[5] = range_limit[(int) DESCALE((IJG_INT32) (tmp2 - tmp5), 3) + & RANGE_MASK]; + outptr[4] = range_limit[(int) DESCALE((IJG_INT32) (tmp3 + tmp4), 3) + & RANGE_MASK]; + outptr[3] = range_limit[(int) DESCALE((IJG_INT32) (tmp3 - tmp4), 3) + & RANGE_MASK]; + + wsptr += DCTSIZE; /* advance pointer to next row */ + } +} + +#endif /* DCT_FLOAT_SUPPORTED */ diff --git a/dcmjpeg/libijg12/jidctfst.c b/dcmjpeg/libijg12/jidctfst.c new file mode 100644 index 00000000..17997950 --- /dev/null +++ b/dcmjpeg/libijg12/jidctfst.c @@ -0,0 +1,368 @@ +/* + * jidctfst.c + * + * Copyright (C) 1994-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains a fast, not so accurate integer implementation of the + * inverse DCT (Discrete Cosine Transform). In the IJG code, this routine + * must also perform dequantization of the input coefficients. + * + * A 2-D IDCT can be done by 1-D IDCT on each column followed by 1-D IDCT + * on each row (or vice versa, but it's more convenient to emit a row at + * a time). Direct algorithms are also available, but they are much more + * complex and seem not to be any faster when reduced to code. + * + * This implementation is based on Arai, Agui, and Nakajima's algorithm for + * scaled DCT. Their original paper (Trans. IEICE E-71(11):1095) is in + * Japanese, but the algorithm is described in the Pennebaker & Mitchell + * JPEG textbook (see REFERENCES section in file README). The following code + * is based directly on figure 4-8 in P&M. + * While an 8-point DCT cannot be done in less than 11 multiplies, it is + * possible to arrange the computation so that many of the multiplies are + * simple scalings of the final outputs. These multiplies can then be + * folded into the multiplications or divisions by the JPEG quantization + * table entries. The AA&N method leaves only 5 multiplies and 29 adds + * to be done in the DCT itself. + * The primary disadvantage of this method is that with fixed-point math, + * accuracy is lost due to imprecise representation of the scaled + * quantization values. The smaller the quantization table entry, the less + * precise the scaled value, so this implementation does worse with high- + * quality-setting files than with low-quality ones. + */ + +#define JPEG_INTERNALS +#include "jinclude12.h" +#include "jpeglib12.h" +#include "jdct12.h" /* Private declarations for DCT subsystem */ + +#ifdef DCT_IFAST_SUPPORTED + + +/* + * This module is specialized to the case DCTSIZE = 8. + */ + +#if DCTSIZE != 8 + Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */ +#endif + + +/* Scaling decisions are generally the same as in the LL&M algorithm; + * see jidctint.c for more details. However, we choose to descale + * (right shift) multiplication products as soon as they are formed, + * rather than carrying additional fractional bits into subsequent additions. + * This compromises accuracy slightly, but it lets us save a few shifts. + * More importantly, 16-bit arithmetic is then adequate (for 8-bit samples) + * everywhere except in the multiplications proper; this saves a good deal + * of work on 16-bit-int machines. + * + * The dequantized coefficients are not integers because the AA&N scaling + * factors have been incorporated. We represent them scaled up by PASS1_BITS, + * so that the first and second IDCT rounds have the same input scaling. + * For 8-bit JSAMPLEs, we choose IFAST_SCALE_BITS = PASS1_BITS so as to + * avoid a descaling shift; this compromises accuracy rather drastically + * for small quantization table entries, but it saves a lot of shifts. + * For 12-bit JSAMPLEs, there's no hope of using 16x16 multiplies anyway, + * so we use a much larger scaling factor to preserve accuracy. + * + * A final compromise is to represent the multiplicative constants to only + * 8 fractional bits, rather than 13. This saves some shifting work on some + * machines, and may also reduce the cost of multiplication (since there + * are fewer one-bits in the constants). + */ + +#if BITS_IN_JSAMPLE == 8 +#define CONST_BITS 8 +#define PASS1_BITS 2 +#else +#define CONST_BITS 8 +#define PASS1_BITS 1 /* lose a little precision to avoid overflow */ +#endif + +/* Some C compilers fail to reduce "FIX(constant)" at compile time, thus + * causing a lot of useless floating-point operations at run time. + * To get around this we use the following pre-calculated constants. + * If you change CONST_BITS you may want to add appropriate values. + * (With a reasonable C compiler, you can just rely on the FIX() macro...) + */ + +#if CONST_BITS == 8 +#define FIX_1_082392200 ((IJG_INT32) 277) /* FIX(1.082392200) */ +#define FIX_1_414213562 ((IJG_INT32) 362) /* FIX(1.414213562) */ +#define FIX_1_847759065 ((IJG_INT32) 473) /* FIX(1.847759065) */ +#define FIX_2_613125930 ((IJG_INT32) 669) /* FIX(2.613125930) */ +#else +#define FIX_1_082392200 FIX(1.082392200) +#define FIX_1_414213562 FIX(1.414213562) +#define FIX_1_847759065 FIX(1.847759065) +#define FIX_2_613125930 FIX(2.613125930) +#endif + + +/* We can gain a little more speed, with a further compromise in accuracy, + * by omitting the addition in a descaling shift. This yields an incorrectly + * rounded result half the time... + */ + +#ifndef USE_ACCURATE_ROUNDING +#undef DESCALE +#define DESCALE(x,n) RIGHT_SHIFT(x, n) +#endif + + +/* Multiply a DCTELEM variable by an IJG_INT32 constant, and immediately + * descale to yield a DCTELEM result. + */ + +#define MULTIPLY(var,const) ((DCTELEM) DESCALE((var) * (const), CONST_BITS)) + + +/* Dequantize a coefficient by multiplying it by the multiplier-table + * entry; produce a DCTELEM result. For 8-bit data a 16x16->16 + * multiplication will do. For 12-bit data, the multiplier table is + * declared IJG_INT32, so a 32-bit multiply will be used. + */ + +#if BITS_IN_JSAMPLE == 8 +#define DEQUANTIZE(coef,quantval) (((IFAST_MULT_TYPE) (coef)) * (quantval)) +#else +#define DEQUANTIZE(coef,quantval) \ + DESCALE((coef)*(quantval), IFAST_SCALE_BITS-PASS1_BITS) +#endif + + +/* Like DESCALE, but applies to a DCTELEM and produces an int. + * We assume that int right shift is unsigned if IJG_INT32 right shift is. + */ + +#ifdef RIGHT_SHIFT_IS_UNSIGNED +#define ISHIFT_TEMPS DCTELEM ishift_temp; +#if BITS_IN_JSAMPLE == 8 +#define DCTELEMBITS 16 /* DCTELEM may be 16 or 32 bits */ +#else +#define DCTELEMBITS 32 /* DCTELEM must be 32 bits */ +#endif +#define IRIGHT_SHIFT(x,shft) \ + ((ishift_temp = (x)) < 0 ? \ + (ishift_temp >> (shft)) | ((~((DCTELEM) 0)) << (DCTELEMBITS-(shft))) : \ + (ishift_temp >> (shft))) +#else +#define ISHIFT_TEMPS +#define IRIGHT_SHIFT(x,shft) ((x) >> (shft)) +#endif + +#ifdef USE_ACCURATE_ROUNDING +#define IDESCALE(x,n) ((int) IRIGHT_SHIFT((x) + (1 << ((n)-1)), n)) +#else +#define IDESCALE(x,n) ((int) IRIGHT_SHIFT(x, n)) +#endif + + +/* + * Perform dequantization and inverse DCT on one block of coefficients. + */ + +GLOBAL(void) +jpeg_idct_ifast (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + DCTELEM tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + DCTELEM tmp10, tmp11, tmp12, tmp13; + DCTELEM z5, z10, z11, z12, z13; + JCOEFPTR inptr; + IFAST_MULT_TYPE * quantptr; + int * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + int workspace[DCTSIZE2]; /* buffers data between passes */ + SHIFT_TEMPS /* for DESCALE */ + ISHIFT_TEMPS /* for IDESCALE */ + + /* Pass 1: process columns from input, store into work array. */ + + inptr = coef_block; + quantptr = (IFAST_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = DCTSIZE; ctr > 0; ctr--) { + /* Due to quantization, we will usually find that many of the input + * coefficients are zero, especially the AC terms. We can exploit this + * by short-circuiting the IDCT calculation for any column in which all + * the AC terms are zero. In that case each output is equal to the + * DC coefficient (with scale factor as needed). + * With typical images and quantization tables, half or more of the + * column DCT calculations can be simplified this way. + */ + + if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*2] == 0 && + inptr[DCTSIZE*3] == 0 && inptr[DCTSIZE*4] == 0 && + inptr[DCTSIZE*5] == 0 && inptr[DCTSIZE*6] == 0 && + inptr[DCTSIZE*7] == 0) { + /* AC terms all zero */ + int dcval = (int) DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + + wsptr[DCTSIZE*0] = dcval; + wsptr[DCTSIZE*1] = dcval; + wsptr[DCTSIZE*2] = dcval; + wsptr[DCTSIZE*3] = dcval; + wsptr[DCTSIZE*4] = dcval; + wsptr[DCTSIZE*5] = dcval; + wsptr[DCTSIZE*6] = dcval; + wsptr[DCTSIZE*7] = dcval; + + inptr++; /* advance pointers to next column */ + quantptr++; + wsptr++; + continue; + } + + /* Even part */ + + tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + tmp1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + tmp2 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); + tmp3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); + + tmp10 = tmp0 + tmp2; /* phase 3 */ + tmp11 = tmp0 - tmp2; + + tmp13 = tmp1 + tmp3; /* phases 5-3 */ + tmp12 = MULTIPLY(tmp1 - tmp3, FIX_1_414213562) - tmp13; /* 2*c4 */ + + tmp0 = tmp10 + tmp13; /* phase 2 */ + tmp3 = tmp10 - tmp13; + tmp1 = tmp11 + tmp12; + tmp2 = tmp11 - tmp12; + + /* Odd part */ + + tmp4 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + tmp5 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + tmp6 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); + tmp7 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); + + z13 = tmp6 + tmp5; /* phase 6 */ + z10 = tmp6 - tmp5; + z11 = tmp4 + tmp7; + z12 = tmp4 - tmp7; + + tmp7 = z11 + z13; /* phase 5 */ + tmp11 = MULTIPLY(z11 - z13, FIX_1_414213562); /* 2*c4 */ + + z5 = MULTIPLY(z10 + z12, FIX_1_847759065); /* 2*c2 */ + tmp10 = MULTIPLY(z12, FIX_1_082392200) - z5; /* 2*(c2-c6) */ + tmp12 = MULTIPLY(z10, - FIX_2_613125930) + z5; /* -2*(c2+c6) */ + + tmp6 = tmp12 - tmp7; /* phase 2 */ + tmp5 = tmp11 - tmp6; + tmp4 = tmp10 + tmp5; + + wsptr[DCTSIZE*0] = (int) (tmp0 + tmp7); + wsptr[DCTSIZE*7] = (int) (tmp0 - tmp7); + wsptr[DCTSIZE*1] = (int) (tmp1 + tmp6); + wsptr[DCTSIZE*6] = (int) (tmp1 - tmp6); + wsptr[DCTSIZE*2] = (int) (tmp2 + tmp5); + wsptr[DCTSIZE*5] = (int) (tmp2 - tmp5); + wsptr[DCTSIZE*4] = (int) (tmp3 + tmp4); + wsptr[DCTSIZE*3] = (int) (tmp3 - tmp4); + + inptr++; /* advance pointers to next column */ + quantptr++; + wsptr++; + } + + /* Pass 2: process rows from work array, store into output array. */ + /* Note that we must descale the results by a factor of 8 == 2**3, */ + /* and also undo the PASS1_BITS scaling. */ + + wsptr = workspace; + for (ctr = 0; ctr < DCTSIZE; ctr++) { + outptr = output_buf[ctr] + output_col; + /* Rows of zeroes can be exploited in the same way as we did with columns. + * However, the column calculation has created many nonzero AC terms, so + * the simplification applies less often (typically 5% to 10% of the time). + * On machines with very fast multiplication, it's possible that the + * test takes more time than it's worth. In that case this section + * may be commented out. + */ + +#ifndef NO_ZERO_ROW_TEST + if (wsptr[1] == 0 && wsptr[2] == 0 && wsptr[3] == 0 && wsptr[4] == 0 && + wsptr[5] == 0 && wsptr[6] == 0 && wsptr[7] == 0) { + /* AC terms all zero */ + JSAMPLE dcval = range_limit[IDESCALE(wsptr[0], PASS1_BITS+3) + & RANGE_MASK]; + + outptr[0] = dcval; + outptr[1] = dcval; + outptr[2] = dcval; + outptr[3] = dcval; + outptr[4] = dcval; + outptr[5] = dcval; + outptr[6] = dcval; + outptr[7] = dcval; + + wsptr += DCTSIZE; /* advance pointer to next row */ + continue; + } +#endif + + /* Even part */ + + tmp10 = ((DCTELEM) wsptr[0] + (DCTELEM) wsptr[4]); + tmp11 = ((DCTELEM) wsptr[0] - (DCTELEM) wsptr[4]); + + tmp13 = ((DCTELEM) wsptr[2] + (DCTELEM) wsptr[6]); + tmp12 = MULTIPLY((DCTELEM) wsptr[2] - (DCTELEM) wsptr[6], FIX_1_414213562) + - tmp13; + + tmp0 = tmp10 + tmp13; + tmp3 = tmp10 - tmp13; + tmp1 = tmp11 + tmp12; + tmp2 = tmp11 - tmp12; + + /* Odd part */ + + z13 = (DCTELEM) wsptr[5] + (DCTELEM) wsptr[3]; + z10 = (DCTELEM) wsptr[5] - (DCTELEM) wsptr[3]; + z11 = (DCTELEM) wsptr[1] + (DCTELEM) wsptr[7]; + z12 = (DCTELEM) wsptr[1] - (DCTELEM) wsptr[7]; + + tmp7 = z11 + z13; /* phase 5 */ + tmp11 = MULTIPLY(z11 - z13, FIX_1_414213562); /* 2*c4 */ + + z5 = MULTIPLY(z10 + z12, FIX_1_847759065); /* 2*c2 */ + tmp10 = MULTIPLY(z12, FIX_1_082392200) - z5; /* 2*(c2-c6) */ + tmp12 = MULTIPLY(z10, - FIX_2_613125930) + z5; /* -2*(c2+c6) */ + + tmp6 = tmp12 - tmp7; /* phase 2 */ + tmp5 = tmp11 - tmp6; + tmp4 = tmp10 + tmp5; + + /* Final output stage: scale down by a factor of 8 and range-limit */ + + outptr[0] = range_limit[IDESCALE(tmp0 + tmp7, PASS1_BITS+3) + & RANGE_MASK]; + outptr[7] = range_limit[IDESCALE(tmp0 - tmp7, PASS1_BITS+3) + & RANGE_MASK]; + outptr[1] = range_limit[IDESCALE(tmp1 + tmp6, PASS1_BITS+3) + & RANGE_MASK]; + outptr[6] = range_limit[IDESCALE(tmp1 - tmp6, PASS1_BITS+3) + & RANGE_MASK]; + outptr[2] = range_limit[IDESCALE(tmp2 + tmp5, PASS1_BITS+3) + & RANGE_MASK]; + outptr[5] = range_limit[IDESCALE(tmp2 - tmp5, PASS1_BITS+3) + & RANGE_MASK]; + outptr[4] = range_limit[IDESCALE(tmp3 + tmp4, PASS1_BITS+3) + & RANGE_MASK]; + outptr[3] = range_limit[IDESCALE(tmp3 - tmp4, PASS1_BITS+3) + & RANGE_MASK]; + + wsptr += DCTSIZE; /* advance pointer to next row */ + } +} + +#endif /* DCT_IFAST_SUPPORTED */ diff --git a/dcmjpeg/libijg12/jidctint.c b/dcmjpeg/libijg12/jidctint.c new file mode 100644 index 00000000..83a77213 --- /dev/null +++ b/dcmjpeg/libijg12/jidctint.c @@ -0,0 +1,389 @@ +/* + * jidctint.c + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains a slow-but-accurate integer implementation of the + * inverse DCT (Discrete Cosine Transform). In the IJG code, this routine + * must also perform dequantization of the input coefficients. + * + * A 2-D IDCT can be done by 1-D IDCT on each column followed by 1-D IDCT + * on each row (or vice versa, but it's more convenient to emit a row at + * a time). Direct algorithms are also available, but they are much more + * complex and seem not to be any faster when reduced to code. + * + * This implementation is based on an algorithm described in + * C. Loeffler, A. Ligtenberg and G. Moschytz, "Practical Fast 1-D DCT + * Algorithms with 11 Multiplications", Proc. Int'l. Conf. on Acoustics, + * Speech, and Signal Processing 1989 (ICASSP '89), pp. 988-991. + * The primary algorithm described there uses 11 multiplies and 29 adds. + * We use their alternate method with 12 multiplies and 32 adds. + * The advantage of this method is that no data path contains more than one + * multiplication; this allows a very simple and accurate implementation in + * scaled fixed-point arithmetic, with a minimal number of shifts. + */ + +#define JPEG_INTERNALS +#include "jinclude12.h" +#include "jpeglib12.h" +#include "jdct12.h" /* Private declarations for DCT subsystem */ + +#ifdef DCT_ISLOW_SUPPORTED + + +/* + * This module is specialized to the case DCTSIZE = 8. + */ + +#if DCTSIZE != 8 + Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */ +#endif + + +/* + * The poop on this scaling stuff is as follows: + * + * Each 1-D IDCT step produces outputs which are a factor of sqrt(N) + * larger than the true IDCT outputs. The final outputs are therefore + * a factor of N larger than desired; since N=8 this can be cured by + * a simple right shift at the end of the algorithm. The advantage of + * this arrangement is that we save two multiplications per 1-D IDCT, + * because the y0 and y4 inputs need not be divided by sqrt(N). + * + * We have to do addition and subtraction of the integer inputs, which + * is no problem, and multiplication by fractional constants, which is + * a problem to do in integer arithmetic. We multiply all the constants + * by CONST_SCALE and convert them to integer constants (thus retaining + * CONST_BITS bits of precision in the constants). After doing a + * multiplication we have to divide the product by CONST_SCALE, with proper + * rounding, to produce the correct output. This division can be done + * cheaply as a right shift of CONST_BITS bits. We postpone shifting + * as long as possible so that partial sums can be added together with + * full fractional precision. + * + * The outputs of the first pass are scaled up by PASS1_BITS bits so that + * they are represented to better-than-integral precision. These outputs + * require BITS_IN_JSAMPLE + PASS1_BITS + 3 bits; this fits in a 16-bit word + * with the recommended scaling. (To scale up 12-bit sample data further, an + * intermediate IJG_INT32 array would be needed.) + * + * To avoid overflow of the 32-bit intermediate results in pass 2, we must + * have BITS_IN_JSAMPLE + CONST_BITS + PASS1_BITS <= 26. Error analysis + * shows that the values given below are the most effective. + */ + +#if BITS_IN_JSAMPLE == 8 +#define CONST_BITS 13 +#define PASS1_BITS 2 +#else +#define CONST_BITS 13 +#define PASS1_BITS 1 /* lose a little precision to avoid overflow */ +#endif + +/* Some C compilers fail to reduce "FIX(constant)" at compile time, thus + * causing a lot of useless floating-point operations at run time. + * To get around this we use the following pre-calculated constants. + * If you change CONST_BITS you may want to add appropriate values. + * (With a reasonable C compiler, you can just rely on the FIX() macro...) + */ + +#if CONST_BITS == 13 +#define FIX_0_298631336 ((IJG_INT32) 2446) /* FIX(0.298631336) */ +#define FIX_0_390180644 ((IJG_INT32) 3196) /* FIX(0.390180644) */ +#define FIX_0_541196100 ((IJG_INT32) 4433) /* FIX(0.541196100) */ +#define FIX_0_765366865 ((IJG_INT32) 6270) /* FIX(0.765366865) */ +#define FIX_0_899976223 ((IJG_INT32) 7373) /* FIX(0.899976223) */ +#define FIX_1_175875602 ((IJG_INT32) 9633) /* FIX(1.175875602) */ +#define FIX_1_501321110 ((IJG_INT32) 12299) /* FIX(1.501321110) */ +#define FIX_1_847759065 ((IJG_INT32) 15137) /* FIX(1.847759065) */ +#define FIX_1_961570560 ((IJG_INT32) 16069) /* FIX(1.961570560) */ +#define FIX_2_053119869 ((IJG_INT32) 16819) /* FIX(2.053119869) */ +#define FIX_2_562915447 ((IJG_INT32) 20995) /* FIX(2.562915447) */ +#define FIX_3_072711026 ((IJG_INT32) 25172) /* FIX(3.072711026) */ +#else +#define FIX_0_298631336 FIX(0.298631336) +#define FIX_0_390180644 FIX(0.390180644) +#define FIX_0_541196100 FIX(0.541196100) +#define FIX_0_765366865 FIX(0.765366865) +#define FIX_0_899976223 FIX(0.899976223) +#define FIX_1_175875602 FIX(1.175875602) +#define FIX_1_501321110 FIX(1.501321110) +#define FIX_1_847759065 FIX(1.847759065) +#define FIX_1_961570560 FIX(1.961570560) +#define FIX_2_053119869 FIX(2.053119869) +#define FIX_2_562915447 FIX(2.562915447) +#define FIX_3_072711026 FIX(3.072711026) +#endif + + +/* Multiply an IJG_INT32 variable by an IJG_INT32 constant to yield an IJG_INT32 result. + * For 8-bit samples with the recommended scaling, all the variable + * and constant values involved are no more than 16 bits wide, so a + * 16x16->32 bit multiply can be used instead of a full 32x32 multiply. + * For 12-bit samples, a full 32-bit multiplication will be needed. + */ + +#if BITS_IN_JSAMPLE == 8 +#define MULTIPLY(var,const) MULTIPLY16C16(var,const) +#else +#define MULTIPLY(var,const) ((var) * (const)) +#endif + + +/* Dequantize a coefficient by multiplying it by the multiplier-table + * entry; produce an int result. In this module, both inputs and result + * are 16 bits or less, so either int or short multiply will work. + */ + +#define DEQUANTIZE(coef,quantval) (((ISLOW_MULT_TYPE) (coef)) * (quantval)) + + +/* + * Perform dequantization and inverse DCT on one block of coefficients. + */ + +GLOBAL(void) +jpeg_idct_islow (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + IJG_INT32 tmp0, tmp1, tmp2, tmp3; + IJG_INT32 tmp10, tmp11, tmp12, tmp13; + IJG_INT32 z1, z2, z3, z4, z5; + JCOEFPTR inptr; + ISLOW_MULT_TYPE * quantptr; + int * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + int workspace[DCTSIZE2]; /* buffers data between passes */ + SHIFT_TEMPS + + /* Pass 1: process columns from input, store into work array. */ + /* Note results are scaled up by sqrt(8) compared to a true IDCT; */ + /* furthermore, we scale the results by 2**PASS1_BITS. */ + + inptr = coef_block; + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = DCTSIZE; ctr > 0; ctr--) { + /* Due to quantization, we will usually find that many of the input + * coefficients are zero, especially the AC terms. We can exploit this + * by short-circuiting the IDCT calculation for any column in which all + * the AC terms are zero. In that case each output is equal to the + * DC coefficient (with scale factor as needed). + * With typical images and quantization tables, half or more of the + * column DCT calculations can be simplified this way. + */ + + if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*2] == 0 && + inptr[DCTSIZE*3] == 0 && inptr[DCTSIZE*4] == 0 && + inptr[DCTSIZE*5] == 0 && inptr[DCTSIZE*6] == 0 && + inptr[DCTSIZE*7] == 0) { + /* AC terms all zero */ + int dcval = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]) << PASS1_BITS; + + wsptr[DCTSIZE*0] = dcval; + wsptr[DCTSIZE*1] = dcval; + wsptr[DCTSIZE*2] = dcval; + wsptr[DCTSIZE*3] = dcval; + wsptr[DCTSIZE*4] = dcval; + wsptr[DCTSIZE*5] = dcval; + wsptr[DCTSIZE*6] = dcval; + wsptr[DCTSIZE*7] = dcval; + + inptr++; /* advance pointers to next column */ + quantptr++; + wsptr++; + continue; + } + + /* Even part: reverse the even part of the forward DCT. */ + /* The rotator is sqrt(2)*c(-6). */ + + z2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + z3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); + + z1 = MULTIPLY(z2 + z3, FIX_0_541196100); + tmp2 = z1 + MULTIPLY(z3, - FIX_1_847759065); + tmp3 = z1 + MULTIPLY(z2, FIX_0_765366865); + + z2 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + z3 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); + + tmp0 = (z2 + z3) << CONST_BITS; + tmp1 = (z2 - z3) << CONST_BITS; + + tmp10 = tmp0 + tmp3; + tmp13 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp1 - tmp2; + + /* Odd part per figure 8; the matrix is unitary and hence its + * transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively. + */ + + tmp0 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); + tmp1 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); + tmp2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + tmp3 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + + z1 = tmp0 + tmp3; + z2 = tmp1 + tmp2; + z3 = tmp0 + tmp2; + z4 = tmp1 + tmp3; + z5 = MULTIPLY(z3 + z4, FIX_1_175875602); /* sqrt(2) * c3 */ + + tmp0 = MULTIPLY(tmp0, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */ + tmp1 = MULTIPLY(tmp1, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */ + tmp2 = MULTIPLY(tmp2, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */ + tmp3 = MULTIPLY(tmp3, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */ + z1 = MULTIPLY(z1, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */ + z2 = MULTIPLY(z2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */ + z3 = MULTIPLY(z3, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */ + z4 = MULTIPLY(z4, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */ + + z3 += z5; + z4 += z5; + + tmp0 += z1 + z3; + tmp1 += z2 + z4; + tmp2 += z2 + z3; + tmp3 += z1 + z4; + + /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */ + + wsptr[DCTSIZE*0] = (int) DESCALE(tmp10 + tmp3, CONST_BITS-PASS1_BITS); + wsptr[DCTSIZE*7] = (int) DESCALE(tmp10 - tmp3, CONST_BITS-PASS1_BITS); + wsptr[DCTSIZE*1] = (int) DESCALE(tmp11 + tmp2, CONST_BITS-PASS1_BITS); + wsptr[DCTSIZE*6] = (int) DESCALE(tmp11 - tmp2, CONST_BITS-PASS1_BITS); + wsptr[DCTSIZE*2] = (int) DESCALE(tmp12 + tmp1, CONST_BITS-PASS1_BITS); + wsptr[DCTSIZE*5] = (int) DESCALE(tmp12 - tmp1, CONST_BITS-PASS1_BITS); + wsptr[DCTSIZE*3] = (int) DESCALE(tmp13 + tmp0, CONST_BITS-PASS1_BITS); + wsptr[DCTSIZE*4] = (int) DESCALE(tmp13 - tmp0, CONST_BITS-PASS1_BITS); + + inptr++; /* advance pointers to next column */ + quantptr++; + wsptr++; + } + + /* Pass 2: process rows from work array, store into output array. */ + /* Note that we must descale the results by a factor of 8 == 2**3, */ + /* and also undo the PASS1_BITS scaling. */ + + wsptr = workspace; + for (ctr = 0; ctr < DCTSIZE; ctr++) { + outptr = output_buf[ctr] + output_col; + /* Rows of zeroes can be exploited in the same way as we did with columns. + * However, the column calculation has created many nonzero AC terms, so + * the simplification applies less often (typically 5% to 10% of the time). + * On machines with very fast multiplication, it's possible that the + * test takes more time than it's worth. In that case this section + * may be commented out. + */ + +#ifndef NO_ZERO_ROW_TEST + if (wsptr[1] == 0 && wsptr[2] == 0 && wsptr[3] == 0 && wsptr[4] == 0 && + wsptr[5] == 0 && wsptr[6] == 0 && wsptr[7] == 0) { + /* AC terms all zero */ + JSAMPLE dcval = range_limit[(int) DESCALE((IJG_INT32) wsptr[0], PASS1_BITS+3) + & RANGE_MASK]; + + outptr[0] = dcval; + outptr[1] = dcval; + outptr[2] = dcval; + outptr[3] = dcval; + outptr[4] = dcval; + outptr[5] = dcval; + outptr[6] = dcval; + outptr[7] = dcval; + + wsptr += DCTSIZE; /* advance pointer to next row */ + continue; + } +#endif + + /* Even part: reverse the even part of the forward DCT. */ + /* The rotator is sqrt(2)*c(-6). */ + + z2 = (IJG_INT32) wsptr[2]; + z3 = (IJG_INT32) wsptr[6]; + + z1 = MULTIPLY(z2 + z3, FIX_0_541196100); + tmp2 = z1 + MULTIPLY(z3, - FIX_1_847759065); + tmp3 = z1 + MULTIPLY(z2, FIX_0_765366865); + + tmp0 = ((IJG_INT32) wsptr[0] + (IJG_INT32) wsptr[4]) << CONST_BITS; + tmp1 = ((IJG_INT32) wsptr[0] - (IJG_INT32) wsptr[4]) << CONST_BITS; + + tmp10 = tmp0 + tmp3; + tmp13 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp1 - tmp2; + + /* Odd part per figure 8; the matrix is unitary and hence its + * transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively. + */ + + tmp0 = (IJG_INT32) wsptr[7]; + tmp1 = (IJG_INT32) wsptr[5]; + tmp2 = (IJG_INT32) wsptr[3]; + tmp3 = (IJG_INT32) wsptr[1]; + + z1 = tmp0 + tmp3; + z2 = tmp1 + tmp2; + z3 = tmp0 + tmp2; + z4 = tmp1 + tmp3; + z5 = MULTIPLY(z3 + z4, FIX_1_175875602); /* sqrt(2) * c3 */ + + tmp0 = MULTIPLY(tmp0, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */ + tmp1 = MULTIPLY(tmp1, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */ + tmp2 = MULTIPLY(tmp2, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */ + tmp3 = MULTIPLY(tmp3, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */ + z1 = MULTIPLY(z1, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */ + z2 = MULTIPLY(z2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */ + z3 = MULTIPLY(z3, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */ + z4 = MULTIPLY(z4, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */ + + z3 += z5; + z4 += z5; + + tmp0 += z1 + z3; + tmp1 += z2 + z4; + tmp2 += z2 + z3; + tmp3 += z1 + z4; + + /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */ + + outptr[0] = range_limit[(int) DESCALE(tmp10 + tmp3, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[7] = range_limit[(int) DESCALE(tmp10 - tmp3, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[1] = range_limit[(int) DESCALE(tmp11 + tmp2, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[6] = range_limit[(int) DESCALE(tmp11 - tmp2, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[2] = range_limit[(int) DESCALE(tmp12 + tmp1, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[5] = range_limit[(int) DESCALE(tmp12 - tmp1, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[3] = range_limit[(int) DESCALE(tmp13 + tmp0, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[4] = range_limit[(int) DESCALE(tmp13 - tmp0, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + + wsptr += DCTSIZE; /* advance pointer to next row */ + } +} + +#endif /* DCT_ISLOW_SUPPORTED */ diff --git a/dcmjpeg/libijg12/jidctred.c b/dcmjpeg/libijg12/jidctred.c new file mode 100644 index 00000000..527f1715 --- /dev/null +++ b/dcmjpeg/libijg12/jidctred.c @@ -0,0 +1,398 @@ +/* + * jidctred.c + * + * Copyright (C) 1994-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains inverse-DCT routines that produce reduced-size output: + * either 4x4, 2x2, or 1x1 pixels from an 8x8 DCT block. + * + * The implementation is based on the Loeffler, Ligtenberg and Moschytz (LL&M) + * algorithm used in jidctint.c. We simply replace each 8-to-8 1-D IDCT step + * with an 8-to-4 step that produces the four averages of two adjacent outputs + * (or an 8-to-2 step producing two averages of four outputs, for 2x2 output). + * These steps were derived by computing the corresponding values at the end + * of the normal LL&M code, then simplifying as much as possible. + * + * 1x1 is trivial: just take the DC coefficient divided by 8. + * + * See jidctint.c for additional comments. + */ + +#define JPEG_INTERNALS +#include "jinclude12.h" +#include "jpeglib12.h" +#include "jdct12.h" /* Private declarations for DCT subsystem */ + +#ifdef IDCT_SCALING_SUPPORTED + + +/* + * This module is specialized to the case DCTSIZE = 8. + */ + +#if DCTSIZE != 8 + Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */ +#endif + + +/* Scaling is the same as in jidctint.c. */ + +#if BITS_IN_JSAMPLE == 8 +#define CONST_BITS 13 +#define PASS1_BITS 2 +#else +#define CONST_BITS 13 +#define PASS1_BITS 1 /* lose a little precision to avoid overflow */ +#endif + +/* Some C compilers fail to reduce "FIX(constant)" at compile time, thus + * causing a lot of useless floating-point operations at run time. + * To get around this we use the following pre-calculated constants. + * If you change CONST_BITS you may want to add appropriate values. + * (With a reasonable C compiler, you can just rely on the FIX() macro...) + */ + +#if CONST_BITS == 13 +#define FIX_0_211164243 ((IJG_INT32) 1730) /* FIX(0.211164243) */ +#define FIX_0_509795579 ((IJG_INT32) 4176) /* FIX(0.509795579) */ +#define FIX_0_601344887 ((IJG_INT32) 4926) /* FIX(0.601344887) */ +#define FIX_0_720959822 ((IJG_INT32) 5906) /* FIX(0.720959822) */ +#define FIX_0_765366865 ((IJG_INT32) 6270) /* FIX(0.765366865) */ +#define FIX_0_850430095 ((IJG_INT32) 6967) /* FIX(0.850430095) */ +#define FIX_0_899976223 ((IJG_INT32) 7373) /* FIX(0.899976223) */ +#define FIX_1_061594337 ((IJG_INT32) 8697) /* FIX(1.061594337) */ +#define FIX_1_272758580 ((IJG_INT32) 10426) /* FIX(1.272758580) */ +#define FIX_1_451774981 ((IJG_INT32) 11893) /* FIX(1.451774981) */ +#define FIX_1_847759065 ((IJG_INT32) 15137) /* FIX(1.847759065) */ +#define FIX_2_172734803 ((IJG_INT32) 17799) /* FIX(2.172734803) */ +#define FIX_2_562915447 ((IJG_INT32) 20995) /* FIX(2.562915447) */ +#define FIX_3_624509785 ((IJG_INT32) 29692) /* FIX(3.624509785) */ +#else +#define FIX_0_211164243 FIX(0.211164243) +#define FIX_0_509795579 FIX(0.509795579) +#define FIX_0_601344887 FIX(0.601344887) +#define FIX_0_720959822 FIX(0.720959822) +#define FIX_0_765366865 FIX(0.765366865) +#define FIX_0_850430095 FIX(0.850430095) +#define FIX_0_899976223 FIX(0.899976223) +#define FIX_1_061594337 FIX(1.061594337) +#define FIX_1_272758580 FIX(1.272758580) +#define FIX_1_451774981 FIX(1.451774981) +#define FIX_1_847759065 FIX(1.847759065) +#define FIX_2_172734803 FIX(2.172734803) +#define FIX_2_562915447 FIX(2.562915447) +#define FIX_3_624509785 FIX(3.624509785) +#endif + + +/* Multiply an IJG_INT32 variable by an IJG_INT32 constant to yield an IJG_INT32 result. + * For 8-bit samples with the recommended scaling, all the variable + * and constant values involved are no more than 16 bits wide, so a + * 16x16->32 bit multiply can be used instead of a full 32x32 multiply. + * For 12-bit samples, a full 32-bit multiplication will be needed. + */ + +#if BITS_IN_JSAMPLE == 8 +#define MULTIPLY(var,const) MULTIPLY16C16(var,const) +#else +#define MULTIPLY(var,const) ((var) * (const)) +#endif + + +/* Dequantize a coefficient by multiplying it by the multiplier-table + * entry; produce an int result. In this module, both inputs and result + * are 16 bits or less, so either int or short multiply will work. + */ + +#define DEQUANTIZE(coef,quantval) (((ISLOW_MULT_TYPE) (coef)) * (quantval)) + + +/* + * Perform dequantization and inverse DCT on one block of coefficients, + * producing a reduced-size 4x4 output block. + */ + +GLOBAL(void) +jpeg_idct_4x4 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + IJG_INT32 tmp0, tmp2, tmp10, tmp12; + IJG_INT32 z1, z2, z3, z4; + JCOEFPTR inptr; + ISLOW_MULT_TYPE * quantptr; + int * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + int workspace[DCTSIZE*4]; /* buffers data between passes */ + SHIFT_TEMPS + + /* Pass 1: process columns from input, store into work array. */ + + inptr = coef_block; + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = DCTSIZE; ctr > 0; inptr++, quantptr++, wsptr++, ctr--) { + /* Don't bother to process column 4, because second pass won't use it */ + if (ctr == DCTSIZE-4) + continue; + if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*2] == 0 && + inptr[DCTSIZE*3] == 0 && inptr[DCTSIZE*5] == 0 && + inptr[DCTSIZE*6] == 0 && inptr[DCTSIZE*7] == 0) { + /* AC terms all zero; we need not examine term 4 for 4x4 output */ + int dcval = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]) << PASS1_BITS; + + wsptr[DCTSIZE*0] = dcval; + wsptr[DCTSIZE*1] = dcval; + wsptr[DCTSIZE*2] = dcval; + wsptr[DCTSIZE*3] = dcval; + + continue; + } + + /* Even part */ + + tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + tmp0 <<= (CONST_BITS+1); + + z2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + z3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); + + tmp2 = MULTIPLY(z2, FIX_1_847759065) + MULTIPLY(z3, - FIX_0_765366865); + + tmp10 = tmp0 + tmp2; + tmp12 = tmp0 - tmp2; + + /* Odd part */ + + z1 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); + z2 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); + z3 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + z4 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + + tmp0 = MULTIPLY(z1, - FIX_0_211164243) /* sqrt(2) * (c3-c1) */ + + MULTIPLY(z2, FIX_1_451774981) /* sqrt(2) * (c3+c7) */ + + MULTIPLY(z3, - FIX_2_172734803) /* sqrt(2) * (-c1-c5) */ + + MULTIPLY(z4, FIX_1_061594337); /* sqrt(2) * (c5+c7) */ + + tmp2 = MULTIPLY(z1, - FIX_0_509795579) /* sqrt(2) * (c7-c5) */ + + MULTIPLY(z2, - FIX_0_601344887) /* sqrt(2) * (c5-c1) */ + + MULTIPLY(z3, FIX_0_899976223) /* sqrt(2) * (c3-c7) */ + + MULTIPLY(z4, FIX_2_562915447); /* sqrt(2) * (c1+c3) */ + + /* Final output stage */ + + wsptr[DCTSIZE*0] = (int) DESCALE(tmp10 + tmp2, CONST_BITS-PASS1_BITS+1); + wsptr[DCTSIZE*3] = (int) DESCALE(tmp10 - tmp2, CONST_BITS-PASS1_BITS+1); + wsptr[DCTSIZE*1] = (int) DESCALE(tmp12 + tmp0, CONST_BITS-PASS1_BITS+1); + wsptr[DCTSIZE*2] = (int) DESCALE(tmp12 - tmp0, CONST_BITS-PASS1_BITS+1); + } + + /* Pass 2: process 4 rows from work array, store into output array. */ + + wsptr = workspace; + for (ctr = 0; ctr < 4; ctr++) { + outptr = output_buf[ctr] + output_col; + /* It's not clear whether a zero row test is worthwhile here ... */ + +#ifndef NO_ZERO_ROW_TEST + if (wsptr[1] == 0 && wsptr[2] == 0 && wsptr[3] == 0 && + wsptr[5] == 0 && wsptr[6] == 0 && wsptr[7] == 0) { + /* AC terms all zero */ + JSAMPLE dcval = range_limit[(int) DESCALE((IJG_INT32) wsptr[0], PASS1_BITS+3) + & RANGE_MASK]; + + outptr[0] = dcval; + outptr[1] = dcval; + outptr[2] = dcval; + outptr[3] = dcval; + + wsptr += DCTSIZE; /* advance pointer to next row */ + continue; + } +#endif + + /* Even part */ + + tmp0 = ((IJG_INT32) wsptr[0]) << (CONST_BITS+1); + + tmp2 = MULTIPLY((IJG_INT32) wsptr[2], FIX_1_847759065) + + MULTIPLY((IJG_INT32) wsptr[6], - FIX_0_765366865); + + tmp10 = tmp0 + tmp2; + tmp12 = tmp0 - tmp2; + + /* Odd part */ + + z1 = (IJG_INT32) wsptr[7]; + z2 = (IJG_INT32) wsptr[5]; + z3 = (IJG_INT32) wsptr[3]; + z4 = (IJG_INT32) wsptr[1]; + + tmp0 = MULTIPLY(z1, - FIX_0_211164243) /* sqrt(2) * (c3-c1) */ + + MULTIPLY(z2, FIX_1_451774981) /* sqrt(2) * (c3+c7) */ + + MULTIPLY(z3, - FIX_2_172734803) /* sqrt(2) * (-c1-c5) */ + + MULTIPLY(z4, FIX_1_061594337); /* sqrt(2) * (c5+c7) */ + + tmp2 = MULTIPLY(z1, - FIX_0_509795579) /* sqrt(2) * (c7-c5) */ + + MULTIPLY(z2, - FIX_0_601344887) /* sqrt(2) * (c5-c1) */ + + MULTIPLY(z3, FIX_0_899976223) /* sqrt(2) * (c3-c7) */ + + MULTIPLY(z4, FIX_2_562915447); /* sqrt(2) * (c1+c3) */ + + /* Final output stage */ + + outptr[0] = range_limit[(int) DESCALE(tmp10 + tmp2, + CONST_BITS+PASS1_BITS+3+1) + & RANGE_MASK]; + outptr[3] = range_limit[(int) DESCALE(tmp10 - tmp2, + CONST_BITS+PASS1_BITS+3+1) + & RANGE_MASK]; + outptr[1] = range_limit[(int) DESCALE(tmp12 + tmp0, + CONST_BITS+PASS1_BITS+3+1) + & RANGE_MASK]; + outptr[2] = range_limit[(int) DESCALE(tmp12 - tmp0, + CONST_BITS+PASS1_BITS+3+1) + & RANGE_MASK]; + + wsptr += DCTSIZE; /* advance pointer to next row */ + } +} + + +/* + * Perform dequantization and inverse DCT on one block of coefficients, + * producing a reduced-size 2x2 output block. + */ + +GLOBAL(void) +jpeg_idct_2x2 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + IJG_INT32 tmp0, tmp10, z1; + JCOEFPTR inptr; + ISLOW_MULT_TYPE * quantptr; + int * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + int workspace[DCTSIZE*2]; /* buffers data between passes */ + SHIFT_TEMPS + + /* Pass 1: process columns from input, store into work array. */ + + inptr = coef_block; + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = DCTSIZE; ctr > 0; inptr++, quantptr++, wsptr++, ctr--) { + /* Don't bother to process columns 2,4,6 */ + if (ctr == DCTSIZE-2 || ctr == DCTSIZE-4 || ctr == DCTSIZE-6) + continue; + if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*3] == 0 && + inptr[DCTSIZE*5] == 0 && inptr[DCTSIZE*7] == 0) { + /* AC terms all zero; we need not examine terms 2,4,6 for 2x2 output */ + int dcval = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]) << PASS1_BITS; + + wsptr[DCTSIZE*0] = dcval; + wsptr[DCTSIZE*1] = dcval; + + continue; + } + + /* Even part */ + + z1 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + tmp10 = z1 << (CONST_BITS+2); + + /* Odd part */ + + z1 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); + tmp0 = MULTIPLY(z1, - FIX_0_720959822); /* sqrt(2) * (c7-c5+c3-c1) */ + z1 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); + tmp0 += MULTIPLY(z1, FIX_0_850430095); /* sqrt(2) * (-c1+c3+c5+c7) */ + z1 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + tmp0 += MULTIPLY(z1, - FIX_1_272758580); /* sqrt(2) * (-c1+c3-c5-c7) */ + z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + tmp0 += MULTIPLY(z1, FIX_3_624509785); /* sqrt(2) * (c1+c3+c5+c7) */ + + /* Final output stage */ + + wsptr[DCTSIZE*0] = (int) DESCALE(tmp10 + tmp0, CONST_BITS-PASS1_BITS+2); + wsptr[DCTSIZE*1] = (int) DESCALE(tmp10 - tmp0, CONST_BITS-PASS1_BITS+2); + } + + /* Pass 2: process 2 rows from work array, store into output array. */ + + wsptr = workspace; + for (ctr = 0; ctr < 2; ctr++) { + outptr = output_buf[ctr] + output_col; + /* It's not clear whether a zero row test is worthwhile here ... */ + +#ifndef NO_ZERO_ROW_TEST + if (wsptr[1] == 0 && wsptr[3] == 0 && wsptr[5] == 0 && wsptr[7] == 0) { + /* AC terms all zero */ + JSAMPLE dcval = range_limit[(int) DESCALE((IJG_INT32) wsptr[0], PASS1_BITS+3) + & RANGE_MASK]; + + outptr[0] = dcval; + outptr[1] = dcval; + + wsptr += DCTSIZE; /* advance pointer to next row */ + continue; + } +#endif + + /* Even part */ + + tmp10 = ((IJG_INT32) wsptr[0]) << (CONST_BITS+2); + + /* Odd part */ + + tmp0 = MULTIPLY((IJG_INT32) wsptr[7], - FIX_0_720959822) /* sqrt(2) * (c7-c5+c3-c1) */ + + MULTIPLY((IJG_INT32) wsptr[5], FIX_0_850430095) /* sqrt(2) * (-c1+c3+c5+c7) */ + + MULTIPLY((IJG_INT32) wsptr[3], - FIX_1_272758580) /* sqrt(2) * (-c1+c3-c5-c7) */ + + MULTIPLY((IJG_INT32) wsptr[1], FIX_3_624509785); /* sqrt(2) * (c1+c3+c5+c7) */ + + /* Final output stage */ + + outptr[0] = range_limit[(int) DESCALE(tmp10 + tmp0, + CONST_BITS+PASS1_BITS+3+2) + & RANGE_MASK]; + outptr[1] = range_limit[(int) DESCALE(tmp10 - tmp0, + CONST_BITS+PASS1_BITS+3+2) + & RANGE_MASK]; + + wsptr += DCTSIZE; /* advance pointer to next row */ + } +} + + +/* + * Perform dequantization and inverse DCT on one block of coefficients, + * producing a reduced-size 1x1 output block. + */ + +GLOBAL(void) +jpeg_idct_1x1 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + int dcval; + ISLOW_MULT_TYPE * quantptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + SHIFT_TEMPS + + /* We hardly need an inverse DCT routine for this: just take the + * average pixel value, which is one-eighth of the DC coefficient. + */ + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + dcval = DEQUANTIZE(coef_block[0], quantptr[0]); + dcval = (int) DESCALE((IJG_INT32) dcval, 3); + + output_buf[0][output_col] = range_limit[dcval & RANGE_MASK]; +} + +#endif /* IDCT_SCALING_SUPPORTED */ diff --git a/dcmjpeg/libijg12/jinclude12.h b/dcmjpeg/libijg12/jinclude12.h new file mode 100644 index 00000000..f9ac222b --- /dev/null +++ b/dcmjpeg/libijg12/jinclude12.h @@ -0,0 +1,91 @@ +/* + * jinclude.h + * + * Copyright (C) 1991-1994, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file exists to provide a single place to fix any problems with + * including the wrong system include files. (Common problems are taken + * care of by the standard jconfig symbols, but on really weird systems + * you may have to edit this file.) + * + * NOTE: this file is NOT intended to be included by applications using the + * JPEG library. Most applications need only include jpeglib.h. + */ + + +/* Include auto-config file to find out which system include files we need. */ + +#include "jconfig12.h" /* auto configuration options */ +#define JCONFIG_INCLUDED /* so that jpeglib.h doesn't do it again */ + +/* + * We need the NULL macro and size_t typedef. + * On an ANSI-conforming system it is sufficient to include . + * Otherwise, we get them from or ; we may have to + * pull in as well. + * Note that the core JPEG library does not require ; + * only the default error handler and data source/destination modules do. + * But we must pull it in because of the references to FILE in jpeglib.h. + * You can remove those references if you want to compile without . + */ + +#ifdef HAVE_STDDEF_H +#include +#endif + +#ifdef HAVE_STDLIB_H +#include +#endif + +#ifdef NEED_SYS_TYPES_H +#include +#endif + +#include + +/* + * We need memory copying and zeroing functions, plus strncpy(). + * ANSI and System V implementations declare these in . + * BSD doesn't have the mem() functions, but it does have bcopy()/bzero(). + * Some systems may declare memset and memcpy in . + * + * NOTE: we assume the size parameters to these functions are of type size_t. + * Change the casts in these macros if not! + */ + +#ifdef NEED_BSD_STRINGS + +#include +#define MEMZERO(target,size) bzero((void *)(target), (size_t)(size)) +#define MEMCOPY(dest,src,size) bcopy((const void *)(src), (void *)(dest), (size_t)(size)) + +#else /* not BSD, assume ANSI/SysV string lib */ + +#include +#define MEMZERO(target,size) memset((void *)(target), 0, (size_t)(size)) +#define MEMCOPY(dest,src,size) memcpy((void *)(dest), (const void *)(src), (size_t)(size)) + +#endif + +/* + * In ANSI C, and indeed any rational implementation, size_t is also the + * type returned by sizeof(). However, it seems there are some irrational + * implementations out there, in which sizeof() returns an int even though + * size_t is defined as long or unsigned long. To ensure consistent results + * we always use this SIZEOF() macro in place of using sizeof() directly. + */ + +#define SIZEOF(object) ((size_t) sizeof(object)) + +/* + * The modules that use fread() and fwrite() always invoke them through + * these macros. On some systems you may need to twiddle the argument casts. + * CAUTION: argument order is different from underlying functions! + */ + +#define JFREAD(file,buf,sizeofbuf) \ + ((size_t) fread((void *) (buf), (size_t) 1, (size_t) (sizeofbuf), (file))) +#define JFWRITE(file,buf,sizeofbuf) \ + ((size_t) fwrite((const void *) (buf), (size_t) 1, (size_t) (sizeofbuf), (file))) diff --git a/dcmjpeg/libijg12/jlossls12.h b/dcmjpeg/libijg12/jlossls12.h new file mode 100644 index 00000000..547b02ea --- /dev/null +++ b/dcmjpeg/libijg12/jlossls12.h @@ -0,0 +1,151 @@ +/* + * jlossls.h + * + * Copyright (C) 1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This include file contains common declarations for the lossless JPEG + * codec modules. + */ + +#ifndef JLOSSLS_H +#define JLOSSLS_H + + +/* + * Table H.1: Predictors for lossless coding. + */ + +#define PREDICTOR1 Ra +#define PREDICTOR2 Rb +#define PREDICTOR3 Rc +#define PREDICTOR4 (int) ((IJG_INT32) Ra + (IJG_INT32) Rb - (IJG_INT32) Rc) +#define PREDICTOR5 (int) ((IJG_INT32) Ra + RIGHT_SHIFT((IJG_INT32) Rb - (IJG_INT32) Rc, 1)) +#define PREDICTOR6 (int) ((IJG_INT32) Rb + RIGHT_SHIFT((IJG_INT32) Ra - (IJG_INT32) Rc, 1)) +#define PREDICTOR7 (int) RIGHT_SHIFT((IJG_INT32) Ra + (IJG_INT32) Rb, 1) + + +typedef JMETHOD(void, predict_difference_method_ptr, + (j_compress_ptr cinfo, int ci, + JSAMPROW input_buf, JSAMPROW prev_row, + JDIFFROW diff_buf, JDIMENSION width)); + +typedef JMETHOD(void, scaler_method_ptr, + (j_compress_ptr cinfo, int ci, + JSAMPROW input_buf, JSAMPROW output_buf, + JDIMENSION width)); + +/* Lossless-specific compression codec (compressor proper) */ +typedef struct { + struct jpeg_c_codec pub; /* public fields */ + + + /* Difference buffer control */ + JMETHOD(void, diff_start_pass, (j_compress_ptr cinfo, + J_BUF_MODE pass_mode)); + + /* Pointer to data which is private to diff controller */ + void *diff_private; + + + /* Entropy encoding */ + JMETHOD(JDIMENSION, entropy_encode_mcus, (j_compress_ptr cinfo, + JDIFFIMAGE diff_buf, + JDIMENSION MCU_row_num, + JDIMENSION MCU_col_num, + JDIMENSION nMCU)); + + /* Pointer to data which is private to entropy module */ + void *entropy_private; + + + /* Prediction, differencing */ + JMETHOD(void, predict_start_pass, (j_compress_ptr cinfo)); + + /* It is useful to allow each component to have a separate diff method. */ + predict_difference_method_ptr predict_difference[MAX_COMPONENTS]; + + /* Pointer to data which is private to predictor module */ + void *pred_private; + + /* Sample scaling */ + JMETHOD(void, scaler_start_pass, (j_compress_ptr cinfo)); + JMETHOD(void, scaler_scale, (j_compress_ptr cinfo, + JSAMPROW input_buf, JSAMPROW output_buf, + JDIMENSION width)); + + /* Pointer to data which is private to scaler module */ + void *scaler_private; + +} jpeg_lossless_c_codec; + +typedef jpeg_lossless_c_codec * j_lossless_c_ptr; + + +typedef JMETHOD(void, predict_undifference_method_ptr, + (j_decompress_ptr cinfo, int comp_index, + JDIFFROW diff_buf, JDIFFROW prev_row, + JDIFFROW undiff_buf, JDIMENSION width)); + +/* Lossless-specific decompression codec (decompressor proper) */ +typedef struct { + struct jpeg_d_codec pub; /* public fields */ + + + /* Difference buffer control */ + JMETHOD(void, diff_start_input_pass, (j_decompress_ptr cinfo)); + + /* Pointer to data which is private to diff controller */ + void *diff_private; + + + /* Entropy decoding */ + JMETHOD(void, entropy_start_pass, (j_decompress_ptr cinfo)); + JMETHOD(boolean, entropy_process_restart, (j_decompress_ptr cinfo)); + JMETHOD(JDIMENSION, entropy_decode_mcus, (j_decompress_ptr cinfo, + JDIFFIMAGE diff_buf, + JDIMENSION MCU_row_num, + JDIMENSION MCU_col_num, + JDIMENSION nMCU)); + + /* Pointer to data which is private to entropy module */ + void *entropy_private; + + + /* Prediction, undifferencing */ + JMETHOD(void, predict_start_pass, (j_decompress_ptr cinfo)); + JMETHOD(void, predict_process_restart, (j_decompress_ptr cinfo)); + + /* It is useful to allow each component to have a separate undiff method. */ + predict_undifference_method_ptr predict_undifference[MAX_COMPONENTS]; + + /* Pointer to data which is private to predictor module */ + void *pred_private; + + /* Sample scaling */ + JMETHOD(void, scaler_start_pass, (j_decompress_ptr cinfo)); + JMETHOD(void, scaler_scale, (j_decompress_ptr cinfo, + JDIFFROW diff_buf, JSAMPROW output_buf, + JDIMENSION width)); + + /* Pointer to data which is private to scaler module */ + void *scaler_private; + +} jpeg_lossless_d_codec; + +typedef jpeg_lossless_d_codec * j_lossless_d_ptr; + + +/* Compression module initialization routines */ +EXTERN(void) jinit_lossless_c_codec JPP((j_compress_ptr cinfo)); +EXTERN(void) jinit_lhuff_encoder JPP((j_compress_ptr cinfo)); +EXTERN(void) jinit_differencer JPP((j_compress_ptr cinfo)); +EXTERN(void) jinit_c_scaler JPP((j_compress_ptr cinfo)); +/* Decompression module initialization routines */ +EXTERN(void) jinit_lossless_d_codec JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_lhuff_decoder JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_undifferencer JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_d_scaler JPP((j_decompress_ptr cinfo)); + +#endif /* JLOSSLS_H */ diff --git a/dcmjpeg/libijg12/jlossy12.h b/dcmjpeg/libijg12/jlossy12.h new file mode 100644 index 00000000..ad4d62b3 --- /dev/null +++ b/dcmjpeg/libijg12/jlossy12.h @@ -0,0 +1,120 @@ +/* + * jlossy.h + * + * Copyright (C) 1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This include file contains common declarations for the lossy (DCT-based) + * JPEG codec modules. + */ + +#ifndef JLOSSY_H +#define JLOSSY_H + + +/* Lossy-specific compression codec (compressor proper) */ +typedef struct { + struct jpeg_c_codec pub; /* public fields */ + + + /* Coefficient buffer control */ + JMETHOD(void, coef_start_pass, (j_compress_ptr cinfo, J_BUF_MODE pass_mode)); + /* JMETHOD(boolean, coef_compress_data, (j_compress_ptr cinfo, + JSAMPIMAGE input_buf));*/ + + /* Pointer to data which is private to coef module */ + void *coef_private; + + + /* Forward DCT (also controls coefficient quantization) */ + JMETHOD(void, fdct_start_pass, (j_compress_ptr cinfo)); + /* perhaps this should be an array??? */ + JMETHOD(void, fdct_forward_DCT, (j_compress_ptr cinfo, + jpeg_component_info * compptr, + JSAMPARRAY sample_data, JBLOCKROW coef_blocks, + JDIMENSION start_row, JDIMENSION start_col, + JDIMENSION num_blocks)); + + /* Pointer to data which is private to fdct module */ + void *fdct_private; + + + /* Entropy encoding */ + JMETHOD(boolean, entropy_encode_mcu, (j_compress_ptr cinfo, + JBLOCKROW *MCU_data)); + + /* Pointer to data which is private to entropy module */ + void *entropy_private; + +} jpeg_lossy_c_codec; + +typedef jpeg_lossy_c_codec * j_lossy_c_ptr; + + + +typedef JMETHOD(void, inverse_DCT_method_ptr, + (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col)); + +/* Lossy-specific decompression codec (decompressor proper) */ +typedef struct { + struct jpeg_d_codec pub; /* public fields */ + + + /* Coefficient buffer control */ + JMETHOD(void, coef_start_input_pass, (j_decompress_ptr cinfo)); + JMETHOD(void, coef_start_output_pass, (j_decompress_ptr cinfo)); + + /* Pointer to array of coefficient virtual arrays, or NULL if none */ + jvirt_barray_ptr *coef_arrays; + + /* Pointer to data which is private to coef module */ + void *coef_private; + + + /* Entropy decoding */ + JMETHOD(void, entropy_start_pass, (j_decompress_ptr cinfo)); + JMETHOD(boolean, entropy_decode_mcu, (j_decompress_ptr cinfo, + JBLOCKROW *MCU_data)); + + /* This is here to share code between baseline and progressive decoders; */ + /* other modules probably should not use it */ + boolean entropy_insufficient_data; /* set TRUE after emitting warning */ + + /* Pointer to data which is private to entropy module */ + void *entropy_private; + + + /* Inverse DCT (also performs dequantization) */ + JMETHOD(void, idct_start_pass, (j_decompress_ptr cinfo)); + + /* It is useful to allow each component to have a separate IDCT method. */ + inverse_DCT_method_ptr inverse_DCT[MAX_COMPONENTS]; + + /* Pointer to data which is private to idct module */ + void *idct_private; + +} jpeg_lossy_d_codec; + +typedef jpeg_lossy_d_codec * j_lossy_d_ptr; + + +/* Compression module initialization routines */ +EXTERN(void) jinit_lossy_c_codec JPP((j_compress_ptr cinfo)); +EXTERN(void) jinit_c_coef_controller JPP((j_compress_ptr cinfo, + boolean need_full_buffer)); +EXTERN(void) jinit_forward_dct JPP((j_compress_ptr cinfo)); +EXTERN(void) jinit_shuff_encoder JPP((j_compress_ptr cinfo)); +EXTERN(void) jinit_phuff_encoder JPP((j_compress_ptr cinfo)); + +/* Decompression module initialization routines */ +EXTERN(void) jinit_lossy_d_codec JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_d_coef_controller JPP((j_decompress_ptr cinfo, + boolean need_full_buffer)); +EXTERN(void) jinit_shuff_decoder JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_phuff_decoder JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_inverse_dct JPP((j_decompress_ptr cinfo)); + +#endif /* JLOSSY_H */ diff --git a/dcmjpeg/libijg12/jmemmgr.c b/dcmjpeg/libijg12/jmemmgr.c new file mode 100644 index 00000000..1ba53460 --- /dev/null +++ b/dcmjpeg/libijg12/jmemmgr.c @@ -0,0 +1,1174 @@ +/* + * jmemmgr.c + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains the JPEG system-independent memory management + * routines. This code is usable across a wide variety of machines; most + * of the system dependencies have been isolated in a separate file. + * The major functions provided here are: + * * pool-based allocation and freeing of memory; + * * policy decisions about how to divide available memory among the + * virtual arrays; + * * control logic for swapping virtual arrays between main memory and + * backing storage. + * The separate system-dependent file provides the actual backing-storage + * access code, and it contains the policy decision about how much total + * main memory to use. + * This file is system-dependent in the sense that some of its functions + * are unnecessary in some systems. For example, if there is enough virtual + * memory so that backing storage will never be used, much of the virtual + * array control logic could be removed. (Of course, if you have that much + * memory then you shouldn't care about a little bit of unused code...) + */ + +#define JPEG_INTERNALS +#define AM_MEMORY_MANAGER /* we define jvirt_Xarray_control structs */ +#include "jinclude12.h" +#include "jpeglib12.h" +#include "jmemsys12.h" /* import the system-dependent declarations */ + +#ifndef NO_GETENV +#ifndef HAVE_STDLIB_H /* should declare getenv() */ +extern char * getenv JPP((const char * name)); +#endif +#endif + + +/* + * Some important notes: + * The allocation routines provided here must never return NULL. + * They should exit to error_exit if unsuccessful. + * + * It's not a good idea to try to merge the sarray, barray and darray + * routines, even though they are textually almost the same, because + * samples are usually stored as bytes while coefficients and differenced + * are shorts or ints. Thus, in machines where byte pointers have a + * different representation from word pointers, the resulting machine + * code could not be the same. + */ + + +/* + * Many machines require storage alignment: longs must start on 4-byte + * boundaries, doubles on 8-byte boundaries, etc. On such machines, malloc() + * always returns pointers that are multiples of the worst-case alignment + * requirement, and we had better do so too. + * There isn't any really portable way to determine the worst-case alignment + * requirement. This module assumes that the alignment requirement is + * multiples of sizeof(ALIGN_TYPE). + * By default, we define ALIGN_TYPE as double. This is necessary on some + * workstations (where doubles really do need 8-byte alignment) and will work + * fine on nearly everything. If your machine has lesser alignment needs, + * you can save a few bytes by making ALIGN_TYPE smaller. + * The only place I know of where this will NOT work is certain Macintosh + * 680x0 compilers that define double as a 10-byte IEEE extended float. + * Doing 10-byte alignment is counterproductive because longwords won't be + * aligned well. Put "#define ALIGN_TYPE long" in jconfig.h if you have + * such a compiler. + */ + +#ifndef ALIGN_TYPE /* so can override from jconfig.h */ +#define ALIGN_TYPE double +#endif + + +/* + * We allocate objects from "pools", where each pool is gotten with a single + * request to jpeg_get_small() or jpeg_get_large(). There is no per-object + * overhead within a pool, except for alignment padding. Each pool has a + * header with a link to the next pool of the same class. + * Small and large pool headers are identical except that the latter's + * link pointer must be FAR on 80x86 machines. + * Notice that the "real" header fields are union'ed with a dummy ALIGN_TYPE + * field. This forces the compiler to make SIZEOF(small_pool_hdr) a multiple + * of the alignment requirement of ALIGN_TYPE. + */ + +typedef union small_pool_struct * small_pool_ptr; + +typedef union small_pool_struct { + struct { + small_pool_ptr next; /* next in list of pools */ + size_t bytes_used; /* how many bytes already used within pool */ + size_t bytes_left; /* bytes still available in this pool */ + } hdr; + ALIGN_TYPE dummy; /* included in union to ensure alignment */ +} small_pool_hdr; + +typedef union large_pool_struct FAR * large_pool_ptr; + +typedef union large_pool_struct { + struct { + large_pool_ptr next; /* next in list of pools */ + size_t bytes_used; /* how many bytes already used within pool */ + size_t bytes_left; /* bytes still available in this pool */ + } hdr; + ALIGN_TYPE dummy; /* included in union to ensure alignment */ +} large_pool_hdr; + + +/* + * Here is the full definition of a memory manager object. + */ + +typedef struct { + struct jpeg_memory_mgr pub; /* public fields */ + + /* Each pool identifier (lifetime class) names a linked list of pools. */ + small_pool_ptr small_list[JPOOL_NUMPOOLS]; + large_pool_ptr large_list[JPOOL_NUMPOOLS]; + + /* Since we only have one lifetime class of virtual arrays, only one + * linked list is necessary (for each datatype). Note that the virtual + * array control blocks being linked together are actually stored somewhere + * in the small-pool list. + */ + jvirt_sarray_ptr virt_sarray_list; + jvirt_barray_ptr virt_barray_list; + + /* This counts total space obtained from jpeg_get_small/large */ + long total_space_allocated; + + /* alloc_sarray and alloc_barray set this value for use by virtual + * array routines. + */ + JDIMENSION last_rowsperchunk; /* from most recent alloc_sarray/barray */ +} my_memory_mgr; + +typedef my_memory_mgr * my_mem_ptr; + + +/* + * The control blocks for virtual arrays. + * Note that these blocks are allocated in the "small" pool area. + * System-dependent info for the associated backing store (if any) is hidden + * inside the backing_store_info struct. + */ + +struct jvirt_sarray_control { + JSAMPARRAY mem_buffer; /* => the in-memory buffer */ + JDIMENSION rows_in_array; /* total virtual array height */ + JDIMENSION samplesperrow; /* width of array (and of memory buffer) */ + JDIMENSION maxaccess; /* max rows accessed by access_virt_sarray */ + JDIMENSION rows_in_mem; /* height of memory buffer */ + JDIMENSION rowsperchunk; /* allocation chunk size in mem_buffer */ + JDIMENSION cur_start_row; /* first logical row # in the buffer */ + JDIMENSION first_undef_row; /* row # of first uninitialized row */ + boolean pre_zero; /* pre-zero mode requested? */ + boolean dirty; /* do current buffer contents need written? */ + boolean b_s_open; /* is backing-store data valid? */ + jvirt_sarray_ptr next; /* link to next virtual sarray control block */ + backing_store_info b_s_info; /* System-dependent control info */ +}; + +struct jvirt_barray_control { + JBLOCKARRAY mem_buffer; /* => the in-memory buffer */ + JDIMENSION rows_in_array; /* total virtual array height */ + JDIMENSION blocksperrow; /* width of array (and of memory buffer) */ + JDIMENSION maxaccess; /* max rows accessed by access_virt_barray */ + JDIMENSION rows_in_mem; /* height of memory buffer */ + JDIMENSION rowsperchunk; /* allocation chunk size in mem_buffer */ + JDIMENSION cur_start_row; /* first logical row # in the buffer */ + JDIMENSION first_undef_row; /* row # of first uninitialized row */ + boolean pre_zero; /* pre-zero mode requested? */ + boolean dirty; /* do current buffer contents need written? */ + boolean b_s_open; /* is backing-store data valid? */ + jvirt_barray_ptr next; /* link to next virtual barray control block */ + backing_store_info b_s_info; /* System-dependent control info */ +}; + + +#ifdef MEM_STATS /* optional extra stuff for statistics */ + +LOCAL(void) +print_mem_stats (j_common_ptr cinfo, int pool_id) +{ + my_mem_ptr mem = (my_mem_ptr) cinfo->mem; + small_pool_ptr shdr_ptr; + large_pool_ptr lhdr_ptr; + + /* Since this is only a debugging stub, we can cheat a little by using + * fprintf directly rather than going through the trace message code. + * This is helpful because message parm array can't handle longs. + */ + fprintf(stderr, "Freeing pool %d, total space = %ld\n", + pool_id, mem->total_space_allocated); + + for (lhdr_ptr = mem->large_list[pool_id]; lhdr_ptr != NULL; + lhdr_ptr = lhdr_ptr->hdr.next) { + fprintf(stderr, " Large chunk used %ld\n", + (long) lhdr_ptr->hdr.bytes_used); + } + + for (shdr_ptr = mem->small_list[pool_id]; shdr_ptr != NULL; + shdr_ptr = shdr_ptr->hdr.next) { + fprintf(stderr, " Small chunk used %ld free %ld\n", + (long) shdr_ptr->hdr.bytes_used, + (long) shdr_ptr->hdr.bytes_left); + } +} + +#endif /* MEM_STATS */ + + +LOCAL(void) +out_of_memory (j_common_ptr cinfo, int which) +/* Report an out-of-memory error and stop execution */ +/* If we compiled MEM_STATS support, report alloc requests before dying */ +{ +#ifdef MEM_STATS + cinfo->err->trace_level = 2; /* force self_destruct to report stats */ +#endif + ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, which); +} + + +/* + * Allocation of "small" objects. + * + * For these, we use pooled storage. When a new pool must be created, + * we try to get enough space for the current request plus a "slop" factor, + * where the slop will be the amount of leftover space in the new pool. + * The speed vs. space tradeoff is largely determined by the slop values. + * A different slop value is provided for each pool class (lifetime), + * and we also distinguish the first pool of a class from later ones. + * NOTE: the values given work fairly well on both 16- and 32-bit-int + * machines, but may be too small if longs are 64 bits or more. + */ + +static const size_t first_pool_slop[JPOOL_NUMPOOLS] = +{ + 1600, /* first PERMANENT pool */ + 16000 /* first IMAGE pool */ +}; + +static const size_t extra_pool_slop[JPOOL_NUMPOOLS] = +{ + 0, /* additional PERMANENT pools */ + 5000 /* additional IMAGE pools */ +}; + +#define MIN_SLOP 50 /* greater than 0 to avoid futile looping */ + + +METHODDEF(void *) +alloc_small (j_common_ptr cinfo, int pool_id, size_t sizeofobject) +/* Allocate a "small" object */ +{ + my_mem_ptr mem = (my_mem_ptr) cinfo->mem; + small_pool_ptr hdr_ptr, prev_hdr_ptr; + char * data_ptr; + size_t odd_bytes, min_request, slop; + + /* Check for unsatisfiable request (do now to ensure no overflow below) */ + if (sizeofobject > (size_t) (MAX_ALLOC_CHUNK-SIZEOF(small_pool_hdr))) + out_of_memory(cinfo, 1); /* request exceeds malloc's ability */ + + /* Round up the requested size to a multiple of SIZEOF(ALIGN_TYPE) */ + odd_bytes = sizeofobject % SIZEOF(ALIGN_TYPE); + if (odd_bytes > 0) + sizeofobject += SIZEOF(ALIGN_TYPE) - odd_bytes; + + /* See if space is available in any existing pool */ + if (pool_id < 0 || pool_id >= JPOOL_NUMPOOLS) + ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */ + prev_hdr_ptr = NULL; + hdr_ptr = mem->small_list[pool_id]; + while (hdr_ptr != NULL) { + if (hdr_ptr->hdr.bytes_left >= sizeofobject) + break; /* found pool with enough space */ + prev_hdr_ptr = hdr_ptr; + hdr_ptr = hdr_ptr->hdr.next; + } + + /* Time to make a new pool? */ + if (hdr_ptr == NULL) { + /* min_request is what we need now, slop is what will be leftover */ + min_request = sizeofobject + SIZEOF(small_pool_hdr); + if (prev_hdr_ptr == NULL) /* first pool in class? */ + slop = first_pool_slop[pool_id]; + else + slop = extra_pool_slop[pool_id]; + /* Don't ask for more than MAX_ALLOC_CHUNK */ + if (slop > (size_t) (MAX_ALLOC_CHUNK-min_request)) + slop = (size_t) (MAX_ALLOC_CHUNK-min_request); + /* Try to get space, if fail reduce slop and try again */ + for (;;) { + hdr_ptr = (small_pool_ptr) jpeg_get_small(cinfo, min_request + slop); + if (hdr_ptr != NULL) + break; + slop /= 2; + if (slop < MIN_SLOP) /* give up when it gets real small */ + out_of_memory(cinfo, 2); /* jpeg_get_small failed */ + } + mem->total_space_allocated += (long)(min_request + slop); + /* Success, initialize the new pool header and add to end of list */ + hdr_ptr->hdr.next = NULL; + hdr_ptr->hdr.bytes_used = 0; + hdr_ptr->hdr.bytes_left = sizeofobject + slop; + if (prev_hdr_ptr == NULL) /* first pool in class? */ + mem->small_list[pool_id] = hdr_ptr; + else + prev_hdr_ptr->hdr.next = hdr_ptr; + } + + /* OK, allocate the object from the current pool */ + data_ptr = (char *) (hdr_ptr + 1); /* point to first data byte in pool */ + data_ptr += hdr_ptr->hdr.bytes_used; /* point to place for object */ + hdr_ptr->hdr.bytes_used += sizeofobject; + hdr_ptr->hdr.bytes_left -= sizeofobject; + + return (void *) data_ptr; +} + + +/* + * Allocation of "large" objects. + * + * The external semantics of these are the same as "small" objects, + * except that FAR pointers are used on 80x86. However the pool + * management heuristics are quite different. We assume that each + * request is large enough that it may as well be passed directly to + * jpeg_get_large; the pool management just links everything together + * so that we can free it all on demand. + * Note: the major use of "large" objects is in JSAMPARRAY and JBLOCKARRAY + * structures. The routines that create these structures (see below) + * deliberately bunch rows together to ensure a large request size. + */ + +METHODDEF(void FAR *) +alloc_large (j_common_ptr cinfo, int pool_id, size_t sizeofobject) +/* Allocate a "large" object */ +{ + my_mem_ptr mem = (my_mem_ptr) cinfo->mem; + large_pool_ptr hdr_ptr; + size_t odd_bytes; + + /* Check for unsatisfiable request (do now to ensure no overflow below) */ + if (sizeofobject > (size_t) (MAX_ALLOC_CHUNK-SIZEOF(large_pool_hdr))) + out_of_memory(cinfo, 3); /* request exceeds malloc's ability */ + + /* Round up the requested size to a multiple of SIZEOF(ALIGN_TYPE) */ + odd_bytes = sizeofobject % SIZEOF(ALIGN_TYPE); + if (odd_bytes > 0) + sizeofobject += SIZEOF(ALIGN_TYPE) - odd_bytes; + + /* Always make a new pool */ + if (pool_id < 0 || pool_id >= JPOOL_NUMPOOLS) + ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */ + + hdr_ptr = (large_pool_ptr) jpeg_get_large(cinfo, sizeofobject + + SIZEOF(large_pool_hdr)); + if (hdr_ptr == NULL) + out_of_memory(cinfo, 4); /* jpeg_get_large failed */ + mem->total_space_allocated += (long)(sizeofobject + SIZEOF(large_pool_hdr)); + + /* Success, initialize the new pool header and add to list */ + hdr_ptr->hdr.next = mem->large_list[pool_id]; + /* We maintain space counts in each pool header for statistical purposes, + * even though they are not needed for allocation. + */ + hdr_ptr->hdr.bytes_used = sizeofobject; + hdr_ptr->hdr.bytes_left = 0; + mem->large_list[pool_id] = hdr_ptr; + + return (void FAR *) (hdr_ptr + 1); /* point to first data byte in pool */ +} + + +/* + * Creation of 2-D sample arrays. + * The pointers are in near heap, the samples themselves in FAR heap. + * + * To minimize allocation overhead and to allow I/O of large contiguous + * blocks, we allocate the sample rows in groups of as many rows as possible + * without exceeding MAX_ALLOC_CHUNK total bytes per allocation request. + * NB: the virtual array control routines, later in this file, know about + * this chunking of rows. The rowsperchunk value is left in the mem manager + * object so that it can be saved away if this sarray is the workspace for + * a virtual array. + */ + +METHODDEF(JSAMPARRAY) +alloc_sarray (j_common_ptr cinfo, int pool_id, + JDIMENSION samplesperrow, JDIMENSION numrows) +/* Allocate a 2-D sample array */ +{ + my_mem_ptr mem = (my_mem_ptr) cinfo->mem; + JSAMPARRAY result; + JSAMPROW workspace; + JDIMENSION rowsperchunk, currow, i; + size_t ltemp; + + /* Calculate max # of rows allowed in one allocation chunk */ + ltemp = (MAX_ALLOC_CHUNK-SIZEOF(large_pool_hdr)) / + ((size_t) samplesperrow * SIZEOF(JSAMPLE)); + if (ltemp <= 0) + ERREXIT(cinfo, JERR_WIDTH_OVERFLOW); + if (ltemp < numrows) + rowsperchunk = (JDIMENSION) ltemp; + else + rowsperchunk = numrows; + mem->last_rowsperchunk = rowsperchunk; + + /* Get space for row pointers (small object) */ + result = (JSAMPARRAY) alloc_small(cinfo, pool_id, + (size_t) (numrows * SIZEOF(JSAMPROW))); + + /* Get the rows themselves (large objects) */ + currow = 0; + while (currow < numrows) { + rowsperchunk = MIN(rowsperchunk, numrows - currow); + workspace = (JSAMPROW) alloc_large(cinfo, pool_id, + (size_t) ((size_t) rowsperchunk * (size_t) samplesperrow + * SIZEOF(JSAMPLE))); + for (i = rowsperchunk; i > 0; i--) { + result[currow++] = workspace; + workspace += samplesperrow; + } + } + + return result; +} + + +/* + * Creation of 2-D coefficient-block arrays. + * This is essentially the same as the code for sample arrays, above. + */ + +METHODDEF(JBLOCKARRAY) +alloc_barray (j_common_ptr cinfo, int pool_id, + JDIMENSION blocksperrow, JDIMENSION numrows) +/* Allocate a 2-D coefficient-block array */ +{ + my_mem_ptr mem = (my_mem_ptr) cinfo->mem; + JBLOCKARRAY result; + JBLOCKROW workspace; + JDIMENSION rowsperchunk, currow, i; + size_t ltemp; + + /* Calculate max # of rows allowed in one allocation chunk */ + ltemp = (MAX_ALLOC_CHUNK-SIZEOF(large_pool_hdr)) / + ((size_t) blocksperrow * SIZEOF(JBLOCK)); + if (ltemp <= 0) + ERREXIT(cinfo, JERR_WIDTH_OVERFLOW); + if (ltemp < numrows) + rowsperchunk = (JDIMENSION) ltemp; + else + rowsperchunk = numrows; + mem->last_rowsperchunk = rowsperchunk; + + /* Get space for row pointers (small object) */ + result = (JBLOCKARRAY) alloc_small(cinfo, pool_id, + (size_t) (numrows * SIZEOF(JBLOCKROW))); + + /* Get the rows themselves (large objects) */ + currow = 0; + while (currow < numrows) { + rowsperchunk = MIN(rowsperchunk, numrows - currow); + workspace = (JBLOCKROW) alloc_large(cinfo, pool_id, + (size_t) ((size_t) rowsperchunk * (size_t) blocksperrow + * SIZEOF(JBLOCK))); + for (i = rowsperchunk; i > 0; i--) { + result[currow++] = workspace; + workspace += blocksperrow; + } + } + + return result; +} + + +#ifdef NEED_DARRAY + +/* + * Creation of 2-D difference arrays. + * This is essentially the same as the code for sample arrays, above. + */ + +METHODDEF(JDIFFARRAY) +alloc_darray (j_common_ptr cinfo, int pool_id, + JDIMENSION diffsperrow, JDIMENSION numrows) +/* Allocate a 2-D difference array */ +{ + my_mem_ptr mem = (my_mem_ptr) cinfo->mem; + JDIFFARRAY result; + JDIFFROW workspace; + JDIMENSION rowsperchunk, currow, i; + size_t ltemp; + + /* Calculate max # of rows allowed in one allocation chunk */ + ltemp = (MAX_ALLOC_CHUNK-SIZEOF(large_pool_hdr)) / + ((size_t) diffsperrow * SIZEOF(JDIFF)); + if (ltemp <= 0) + ERREXIT(cinfo, JERR_WIDTH_OVERFLOW); + if (ltemp < numrows) + rowsperchunk = (JDIMENSION) ltemp; + else + rowsperchunk = numrows; + mem->last_rowsperchunk = rowsperchunk; + + /* Get space for row pointers (small object) */ + result = (JDIFFARRAY) alloc_small(cinfo, pool_id, + (size_t) (numrows * SIZEOF(JDIFFROW))); + + /* Get the rows themselves (large objects) */ + currow = 0; + while (currow < numrows) { + rowsperchunk = MIN(rowsperchunk, numrows - currow); + workspace = (JDIFFROW) alloc_large(cinfo, pool_id, + (size_t) ((size_t) rowsperchunk * (size_t) diffsperrow + * SIZEOF(JDIFF))); + for (i = rowsperchunk; i > 0; i--) { + result[currow++] = workspace; + workspace += diffsperrow; + } + } + + return result; +} + +#endif + + +/* + * About virtual array management: + * + * The above "normal" array routines are only used to allocate strip buffers + * (as wide as the image, but just a few rows high). Full-image-sized buffers + * are handled as "virtual" arrays. The array is still accessed a strip at a + * time, but the memory manager must save the whole array for repeated + * accesses. The intended implementation is that there is a strip buffer in + * memory (as high as is possible given the desired memory limit), plus a + * backing file that holds the rest of the array. + * + * The request_virt_array routines are told the total size of the image and + * the maximum number of rows that will be accessed at once. The in-memory + * buffer must be at least as large as the maxaccess value. + * + * The request routines create control blocks but not the in-memory buffers. + * That is postponed until realize_virt_arrays is called. At that time the + * total amount of space needed is known (approximately, anyway), so free + * memory can be divided up fairly. + * + * The access_virt_array routines are responsible for making a specific strip + * area accessible (after reading or writing the backing file, if necessary). + * Note that the access routines are told whether the caller intends to modify + * the accessed strip; during a read-only pass this saves having to rewrite + * data to disk. The access routines are also responsible for pre-zeroing + * any newly accessed rows, if pre-zeroing was requested. + * + * In current usage, the access requests are usually for nonoverlapping + * strips; that is, successive access start_row numbers differ by exactly + * num_rows = maxaccess. This means we can get good performance with simple + * buffer dump/reload logic, by making the in-memory buffer be a multiple + * of the access height; then there will never be accesses across bufferload + * boundaries. The code will still work with overlapping access requests, + * but it doesn't handle bufferload overlaps very efficiently. + */ + + +METHODDEF(jvirt_sarray_ptr) +request_virt_sarray (j_common_ptr cinfo, int pool_id, boolean pre_zero, + JDIMENSION samplesperrow, JDIMENSION numrows, + JDIMENSION maxaccess) +/* Request a virtual 2-D sample array */ +{ + my_mem_ptr mem = (my_mem_ptr) cinfo->mem; + jvirt_sarray_ptr result; + + /* Only IMAGE-lifetime virtual arrays are currently supported */ + if (pool_id != JPOOL_IMAGE) + ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */ + + /* get control block */ + result = (jvirt_sarray_ptr) alloc_small(cinfo, pool_id, + SIZEOF(struct jvirt_sarray_control)); + + result->mem_buffer = NULL; /* marks array not yet realized */ + result->rows_in_array = numrows; + result->samplesperrow = samplesperrow; + result->maxaccess = maxaccess; + result->pre_zero = pre_zero; + result->b_s_open = FALSE; /* no associated backing-store object */ + result->next = mem->virt_sarray_list; /* add to list of virtual arrays */ + mem->virt_sarray_list = result; + + return result; +} + + +METHODDEF(jvirt_barray_ptr) +request_virt_barray (j_common_ptr cinfo, int pool_id, boolean pre_zero, + JDIMENSION blocksperrow, JDIMENSION numrows, + JDIMENSION maxaccess) +/* Request a virtual 2-D coefficient-block array */ +{ + my_mem_ptr mem = (my_mem_ptr) cinfo->mem; + jvirt_barray_ptr result; + + /* Only IMAGE-lifetime virtual arrays are currently supported */ + if (pool_id != JPOOL_IMAGE) + ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */ + + /* get control block */ + result = (jvirt_barray_ptr) alloc_small(cinfo, pool_id, + SIZEOF(struct jvirt_barray_control)); + + result->mem_buffer = NULL; /* marks array not yet realized */ + result->rows_in_array = numrows; + result->blocksperrow = blocksperrow; + result->maxaccess = maxaccess; + result->pre_zero = pre_zero; + result->b_s_open = FALSE; /* no associated backing-store object */ + result->next = mem->virt_barray_list; /* add to list of virtual arrays */ + mem->virt_barray_list = result; + + return result; +} + + +METHODDEF(void) +realize_virt_arrays (j_common_ptr cinfo) +/* Allocate the in-memory buffers for any unrealized virtual arrays */ +{ + my_mem_ptr mem = (my_mem_ptr) cinfo->mem; + size_t space_per_minheight, maximum_space, avail_mem; + size_t minheights, max_minheights; + jvirt_sarray_ptr sptr; + jvirt_barray_ptr bptr; + + /* Compute the minimum space needed (maxaccess rows in each buffer) + * and the maximum space needed (full image height in each buffer). + * These may be of use to the system-dependent jpeg_mem_available routine. + */ + space_per_minheight = 0; + maximum_space = 0; + for (sptr = mem->virt_sarray_list; sptr != NULL; sptr = sptr->next) { + if (sptr->mem_buffer == NULL) { /* if not realized yet */ + space_per_minheight += sptr->maxaccess * + sptr->samplesperrow * SIZEOF(JSAMPLE); + maximum_space += sptr->rows_in_array * + sptr->samplesperrow * SIZEOF(JSAMPLE); + } + } + for (bptr = mem->virt_barray_list; bptr != NULL; bptr = bptr->next) { + if (bptr->mem_buffer == NULL) { /* if not realized yet */ + space_per_minheight += bptr->maxaccess * + bptr->blocksperrow * SIZEOF(JBLOCK); + maximum_space += bptr->rows_in_array * + bptr->blocksperrow * SIZEOF(JBLOCK); + } + } + + if (space_per_minheight <= 0) + return; /* no unrealized arrays, no work */ + + /* Determine amount of memory to actually use; this is system-dependent. */ + avail_mem = (size_t)jpeg_mem_available(cinfo, (long)space_per_minheight, (long)maximum_space, + mem->total_space_allocated); + + /* If the maximum space needed is available, make all the buffers full + * height; otherwise parcel it out with the same number of minheights + * in each buffer. + */ + if (avail_mem >= maximum_space) + max_minheights = 1000000000L; + else { + max_minheights = avail_mem / space_per_minheight; + /* If there doesn't seem to be enough space, try to get the minimum + * anyway. This allows a "stub" implementation of jpeg_mem_available(). + */ + if (max_minheights <= 0) + max_minheights = 1; + } + + /* Allocate the in-memory buffers and initialize backing store as needed. */ + + for (sptr = mem->virt_sarray_list; sptr != NULL; sptr = sptr->next) { + if (sptr->mem_buffer == NULL) { /* if not realized yet */ + minheights = (size_t)((sptr->rows_in_array - 1L) / sptr->maxaccess + 1L); + if (minheights <= max_minheights) { + /* This buffer fits in memory */ + sptr->rows_in_mem = sptr->rows_in_array; + } else { + /* It doesn't fit in memory, create backing store. */ + sptr->rows_in_mem = (JDIMENSION)max_minheights * sptr->maxaccess; + jpeg_open_backing_store(cinfo, & sptr->b_s_info, + (long) sptr->rows_in_array * + (long) sptr->samplesperrow * + (long) SIZEOF(JSAMPLE)); + sptr->b_s_open = TRUE; + } + sptr->mem_buffer = alloc_sarray(cinfo, JPOOL_IMAGE, + sptr->samplesperrow, sptr->rows_in_mem); + sptr->rowsperchunk = mem->last_rowsperchunk; + sptr->cur_start_row = 0; + sptr->first_undef_row = 0; + sptr->dirty = FALSE; + } + } + + for (bptr = mem->virt_barray_list; bptr != NULL; bptr = bptr->next) { + if (bptr->mem_buffer == NULL) { /* if not realized yet */ + minheights = (size_t)((bptr->rows_in_array - 1L) / bptr->maxaccess + 1L); + if (minheights <= max_minheights) { + /* This buffer fits in memory */ + bptr->rows_in_mem = bptr->rows_in_array; + } else { + /* It doesn't fit in memory, create backing store. */ + bptr->rows_in_mem = (JDIMENSION)max_minheights * bptr->maxaccess; + jpeg_open_backing_store(cinfo, & bptr->b_s_info, + (long) bptr->rows_in_array * + (long) bptr->blocksperrow * + (long) SIZEOF(JBLOCK)); + bptr->b_s_open = TRUE; + } + bptr->mem_buffer = alloc_barray(cinfo, JPOOL_IMAGE, + bptr->blocksperrow, bptr->rows_in_mem); + bptr->rowsperchunk = mem->last_rowsperchunk; + bptr->cur_start_row = 0; + bptr->first_undef_row = 0; + bptr->dirty = FALSE; + } + } +} + + +LOCAL(void) +do_sarray_io (j_common_ptr cinfo, jvirt_sarray_ptr ptr, boolean writing) +/* Do backing store read or write of a virtual sample array */ +{ + size_t bytesperrow, file_offset, byte_count, rows, thisrow, i; + + bytesperrow = ptr->samplesperrow * SIZEOF(JSAMPLE); + file_offset = ptr->cur_start_row * bytesperrow; + /* Loop to read or write each allocation chunk in mem_buffer */ + for (i = 0; i < ptr->rows_in_mem; i += ptr->rowsperchunk) { + /* One chunk, but check for short chunk at end of buffer */ + rows = MIN(ptr->rowsperchunk, ptr->rows_in_mem - i); + /* Transfer no more than is currently defined */ + thisrow = ptr->cur_start_row + i; + rows = MIN(rows, ptr->first_undef_row - thisrow); + /* Transfer no more than fits in file */ + rows = MIN(rows, ptr->rows_in_array - thisrow); + if (rows <= 0) /* this chunk might be past end of file! */ + break; + byte_count = rows * bytesperrow; + if (writing) + (*ptr->b_s_info.write_backing_store) (cinfo, & ptr->b_s_info, + (void FAR *) ptr->mem_buffer[i], + (long)file_offset, (long)byte_count); + else + (*ptr->b_s_info.read_backing_store) (cinfo, & ptr->b_s_info, + (void FAR *) ptr->mem_buffer[i], + (long)file_offset, (long)byte_count); + file_offset += byte_count; + } +} + + +LOCAL(void) +do_barray_io (j_common_ptr cinfo, jvirt_barray_ptr ptr, boolean writing) +/* Do backing store read or write of a virtual coefficient-block array */ +{ + size_t bytesperrow, file_offset, byte_count, rows, thisrow, i; + + bytesperrow = ptr->blocksperrow * SIZEOF(JBLOCK); + file_offset = ptr->cur_start_row * bytesperrow; + /* Loop to read or write each allocation chunk in mem_buffer */ + for (i = 0; i < ptr->rows_in_mem; i += ptr->rowsperchunk) { + /* One chunk, but check for short chunk at end of buffer */ + rows = MIN(ptr->rowsperchunk, ptr->rows_in_mem - i); + /* Transfer no more than is currently defined */ + thisrow = ptr->cur_start_row + i; + rows = MIN(rows, ptr->first_undef_row - thisrow); + /* Transfer no more than fits in file */ + rows = MIN(rows, ptr->rows_in_array - thisrow); + if (rows <= 0) /* this chunk might be past end of file! */ + break; + byte_count = rows * bytesperrow; + if (writing) + (*ptr->b_s_info.write_backing_store) (cinfo, & ptr->b_s_info, + (void FAR *) ptr->mem_buffer[i], + (long)file_offset, (long)byte_count); + else + (*ptr->b_s_info.read_backing_store) (cinfo, & ptr->b_s_info, + (void FAR *) ptr->mem_buffer[i], + (long)file_offset, (long)byte_count); + file_offset += byte_count; + } +} + + +METHODDEF(JSAMPARRAY) +access_virt_sarray (j_common_ptr cinfo, jvirt_sarray_ptr ptr, + JDIMENSION start_row, JDIMENSION num_rows, + boolean writable) +/* Access the part of a virtual sample array starting at start_row */ +/* and extending for num_rows rows. writable is true if */ +/* caller intends to modify the accessed area. */ +{ + JDIMENSION end_row = start_row + num_rows; + JDIMENSION undef_row; + + /* debugging check */ + if (end_row > ptr->rows_in_array || num_rows > ptr->maxaccess || + ptr->mem_buffer == NULL) + ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS); + + /* Make the desired part of the virtual array accessible */ + if (start_row < ptr->cur_start_row || + end_row > ptr->cur_start_row+ptr->rows_in_mem) { + if (! ptr->b_s_open) + ERREXIT(cinfo, JERR_VIRTUAL_BUG); + /* Flush old buffer contents if necessary */ + if (ptr->dirty) { + do_sarray_io(cinfo, ptr, TRUE); + ptr->dirty = FALSE; + } + /* Decide what part of virtual array to access. + * Algorithm: if target address > current window, assume forward scan, + * load starting at target address. If target address < current window, + * assume backward scan, load so that target area is top of window. + * Note that when switching from forward write to forward read, will have + * start_row = 0, so the limiting case applies and we load from 0 anyway. + */ + if (start_row > ptr->cur_start_row) { + ptr->cur_start_row = start_row; + } else { + /* use long arithmetic here to avoid overflow & unsigned problems */ + long ltemp; + + ltemp = (long) end_row - (long) ptr->rows_in_mem; + if (ltemp < 0) + ltemp = 0; /* don't fall off front end of file */ + ptr->cur_start_row = (JDIMENSION) ltemp; + } + /* Read in the selected part of the array. + * During the initial write pass, we will do no actual read + * because the selected part is all undefined. + */ + do_sarray_io(cinfo, ptr, FALSE); + } + /* Ensure the accessed part of the array is defined; prezero if needed. + * To improve locality of access, we only prezero the part of the array + * that the caller is about to access, not the entire in-memory array. + */ + if (ptr->first_undef_row < end_row) { + if (ptr->first_undef_row < start_row) { + if (writable) /* writer skipped over a section of array */ + ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS); + undef_row = start_row; /* but reader is allowed to read ahead */ + } else { + undef_row = ptr->first_undef_row; + } + if (writable) + ptr->first_undef_row = end_row; + if (ptr->pre_zero) { + size_t bytesperrow = (size_t) ptr->samplesperrow * SIZEOF(JSAMPLE); + undef_row -= ptr->cur_start_row; /* make indexes relative to buffer */ + end_row -= ptr->cur_start_row; + while (undef_row < end_row) { + jzero_far((void FAR *) ptr->mem_buffer[undef_row], bytesperrow); + undef_row++; + } + } else { + if (! writable) /* reader looking at undefined data */ + ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS); + } + } + /* Flag the buffer dirty if caller will write in it */ + if (writable) + ptr->dirty = TRUE; + /* Return address of proper part of the buffer */ + return ptr->mem_buffer + (start_row - ptr->cur_start_row); +} + + +METHODDEF(JBLOCKARRAY) +access_virt_barray (j_common_ptr cinfo, jvirt_barray_ptr ptr, + JDIMENSION start_row, JDIMENSION num_rows, + boolean writable) +/* Access the part of a virtual block array starting at start_row */ +/* and extending for num_rows rows. writable is true if */ +/* caller intends to modify the accessed area. */ +{ + JDIMENSION end_row = start_row + num_rows; + JDIMENSION undef_row; + + /* debugging check */ + if (end_row > ptr->rows_in_array || num_rows > ptr->maxaccess || + ptr->mem_buffer == NULL) + ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS); + + /* Make the desired part of the virtual array accessible */ + if (start_row < ptr->cur_start_row || + end_row > ptr->cur_start_row+ptr->rows_in_mem) { + if (! ptr->b_s_open) + ERREXIT(cinfo, JERR_VIRTUAL_BUG); + /* Flush old buffer contents if necessary */ + if (ptr->dirty) { + do_barray_io(cinfo, ptr, TRUE); + ptr->dirty = FALSE; + } + /* Decide what part of virtual array to access. + * Algorithm: if target address > current window, assume forward scan, + * load starting at target address. If target address < current window, + * assume backward scan, load so that target area is top of window. + * Note that when switching from forward write to forward read, will have + * start_row = 0, so the limiting case applies and we load from 0 anyway. + */ + if (start_row > ptr->cur_start_row) { + ptr->cur_start_row = start_row; + } else { + /* use long arithmetic here to avoid overflow & unsigned problems */ + long ltemp; + + ltemp = (long) end_row - (long) ptr->rows_in_mem; + if (ltemp < 0) + ltemp = 0; /* don't fall off front end of file */ + ptr->cur_start_row = (JDIMENSION) ltemp; + } + /* Read in the selected part of the array. + * During the initial write pass, we will do no actual read + * because the selected part is all undefined. + */ + do_barray_io(cinfo, ptr, FALSE); + } + /* Ensure the accessed part of the array is defined; prezero if needed. + * To improve locality of access, we only prezero the part of the array + * that the caller is about to access, not the entire in-memory array. + */ + if (ptr->first_undef_row < end_row) { + if (ptr->first_undef_row < start_row) { + if (writable) /* writer skipped over a section of array */ + ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS); + undef_row = start_row; /* but reader is allowed to read ahead */ + } else { + undef_row = ptr->first_undef_row; + } + if (writable) + ptr->first_undef_row = end_row; + if (ptr->pre_zero) { + size_t bytesperrow = (size_t) ptr->blocksperrow * SIZEOF(JBLOCK); + undef_row -= ptr->cur_start_row; /* make indexes relative to buffer */ + end_row -= ptr->cur_start_row; + while (undef_row < end_row) { + jzero_far((void FAR *) ptr->mem_buffer[undef_row], bytesperrow); + undef_row++; + } + } else { + if (! writable) /* reader looking at undefined data */ + ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS); + } + } + /* Flag the buffer dirty if caller will write in it */ + if (writable) + ptr->dirty = TRUE; + /* Return address of proper part of the buffer */ + return ptr->mem_buffer + (start_row - ptr->cur_start_row); +} + + +/* + * Release all objects belonging to a specified pool. + */ + +METHODDEF(void) +free_pool (j_common_ptr cinfo, int pool_id) +{ + my_mem_ptr mem = (my_mem_ptr) cinfo->mem; + small_pool_ptr shdr_ptr; + large_pool_ptr lhdr_ptr; + size_t space_freed; + + if (pool_id < 0 || pool_id >= JPOOL_NUMPOOLS) + ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */ + +#ifdef MEM_STATS + if (cinfo->err->trace_level > 1) + print_mem_stats(cinfo, pool_id); /* print pool's memory usage statistics */ +#endif + + /* If freeing IMAGE pool, close any virtual arrays first */ + if (pool_id == JPOOL_IMAGE) { + jvirt_sarray_ptr sptr; + jvirt_barray_ptr bptr; + + for (sptr = mem->virt_sarray_list; sptr != NULL; sptr = sptr->next) { + if (sptr->b_s_open) { /* there may be no backing store */ + sptr->b_s_open = FALSE; /* prevent recursive close if error */ + (*sptr->b_s_info.close_backing_store) (cinfo, & sptr->b_s_info); + } + } + mem->virt_sarray_list = NULL; + for (bptr = mem->virt_barray_list; bptr != NULL; bptr = bptr->next) { + if (bptr->b_s_open) { /* there may be no backing store */ + bptr->b_s_open = FALSE; /* prevent recursive close if error */ + (*bptr->b_s_info.close_backing_store) (cinfo, & bptr->b_s_info); + } + } + mem->virt_barray_list = NULL; + } + + /* Release large objects */ + lhdr_ptr = mem->large_list[pool_id]; + mem->large_list[pool_id] = NULL; + + while (lhdr_ptr != NULL) { + large_pool_ptr next_lhdr_ptr = lhdr_ptr->hdr.next; + space_freed = lhdr_ptr->hdr.bytes_used + + lhdr_ptr->hdr.bytes_left + + SIZEOF(large_pool_hdr); + jpeg_free_large(cinfo, (void FAR *) lhdr_ptr, space_freed); + mem->total_space_allocated -= (long)space_freed; + lhdr_ptr = next_lhdr_ptr; + } + + /* Release small objects */ + shdr_ptr = mem->small_list[pool_id]; + mem->small_list[pool_id] = NULL; + + while (shdr_ptr != NULL) { + small_pool_ptr next_shdr_ptr = shdr_ptr->hdr.next; + space_freed = shdr_ptr->hdr.bytes_used + + shdr_ptr->hdr.bytes_left + + SIZEOF(small_pool_hdr); + jpeg_free_small(cinfo, (void *) shdr_ptr, space_freed); + mem->total_space_allocated -= (long)space_freed; + shdr_ptr = next_shdr_ptr; + } +} + + +/* + * Close up shop entirely. + * Note that this cannot be called unless cinfo->mem is non-NULL. + */ + +METHODDEF(void) +self_destruct (j_common_ptr cinfo) +{ + int pool; + + /* Close all backing store, release all memory. + * Releasing pools in reverse order might help avoid fragmentation + * with some (brain-damaged) malloc libraries. + */ + for (pool = JPOOL_NUMPOOLS-1; pool >= JPOOL_PERMANENT; pool--) { + free_pool(cinfo, pool); + } + + /* Release the memory manager control block too. */ + jpeg_free_small(cinfo, (void *) cinfo->mem, SIZEOF(my_memory_mgr)); + cinfo->mem = NULL; /* ensures I will be called only once */ + + jpeg_mem_term(cinfo); /* system-dependent cleanup */ +} + + +/* + * Memory manager initialization. + * When this is called, only the error manager pointer is valid in cinfo! + */ + +GLOBAL(void) +jinit_memory_mgr (j_common_ptr cinfo) +{ + my_mem_ptr mem; + long max_to_use; + int pool; + size_t test_mac; + + cinfo->mem = NULL; /* for safety if init fails */ + + /* Check for configuration errors. + * SIZEOF(ALIGN_TYPE) should be a power of 2; otherwise, it probably + * doesn't reflect any real hardware alignment requirement. + * The test is a little tricky: for X>0, X and X-1 have no one-bits + * in common if and only if X is a power of 2, ie has only one one-bit. + * Some compilers may give an "unreachable code" warning here; ignore it. + */ + if ((SIZEOF(ALIGN_TYPE) & (SIZEOF(ALIGN_TYPE)-1)) != 0) + ERREXIT(cinfo, JERR_BAD_ALIGN_TYPE); + /* MAX_ALLOC_CHUNK must be representable as type size_t, and must be + * a multiple of SIZEOF(ALIGN_TYPE). + * Again, an "unreachable code" warning may be ignored here. + * But a "constant too large" warning means you need to fix MAX_ALLOC_CHUNK. + */ + test_mac = (size_t) MAX_ALLOC_CHUNK; + if ((long) test_mac != MAX_ALLOC_CHUNK || + (MAX_ALLOC_CHUNK % SIZEOF(ALIGN_TYPE)) != 0) + ERREXIT(cinfo, JERR_BAD_ALLOC_CHUNK); + + max_to_use = jpeg_mem_init(cinfo); /* system-dependent initialization */ + + /* Attempt to allocate memory manager's control block */ + mem = (my_mem_ptr) jpeg_get_small(cinfo, SIZEOF(my_memory_mgr)); + + if (mem == NULL) { + jpeg_mem_term(cinfo); /* system-dependent cleanup */ + ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, 0); + } + + /* OK, fill in the method pointers */ + mem->pub.alloc_small = alloc_small; + mem->pub.alloc_large = alloc_large; + mem->pub.alloc_sarray = alloc_sarray; + mem->pub.alloc_barray = alloc_barray; +#ifdef NEED_DARRAY + mem->pub.alloc_darray = alloc_darray; +#endif + mem->pub.request_virt_sarray = request_virt_sarray; + mem->pub.request_virt_barray = request_virt_barray; + mem->pub.realize_virt_arrays = realize_virt_arrays; + mem->pub.access_virt_sarray = access_virt_sarray; + mem->pub.access_virt_barray = access_virt_barray; + mem->pub.free_pool = free_pool; + mem->pub.self_destruct = self_destruct; + + /* Make MAX_ALLOC_CHUNK accessible to other modules */ + mem->pub.max_alloc_chunk = MAX_ALLOC_CHUNK; + + /* Initialize working state */ + mem->pub.max_memory_to_use = max_to_use; + + for (pool = JPOOL_NUMPOOLS-1; pool >= JPOOL_PERMANENT; pool--) { + mem->small_list[pool] = NULL; + mem->large_list[pool] = NULL; + } + mem->virt_sarray_list = NULL; + mem->virt_barray_list = NULL; + + mem->total_space_allocated = SIZEOF(my_memory_mgr); + + /* Declare ourselves open for business */ + cinfo->mem = & mem->pub; + + /* Check for an environment variable JPEGMEM; if found, override the + * default max_memory setting from jpeg_mem_init. Note that the + * surrounding application may again override this value. + * If your system doesn't support getenv(), define NO_GETENV to disable + * this feature. + */ +#ifndef NO_GETENV + { char * memenv; + + if ((memenv = getenv("JPEGMEM")) != NULL) { + char ch = 'x'; + + if (sscanf(memenv, "%ld%c", &max_to_use, &ch) > 0) { + if (ch == 'm' || ch == 'M') + max_to_use *= 1000L; + mem->pub.max_memory_to_use = max_to_use * 1000L; + } + } + } +#endif + +} diff --git a/dcmjpeg/libijg12/jmemnobs.c b/dcmjpeg/libijg12/jmemnobs.c new file mode 100644 index 00000000..248d84db --- /dev/null +++ b/dcmjpeg/libijg12/jmemnobs.c @@ -0,0 +1,109 @@ +/* + * jmemnobs.c + * + * Copyright (C) 1992-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file provides a really simple implementation of the system- + * dependent portion of the JPEG memory manager. This implementation + * assumes that no backing-store files are needed: all required space + * can be obtained from malloc(). + * This is very portable in the sense that it'll compile on almost anything, + * but you'd better have lots of main memory (or virtual memory) if you want + * to process big images. + * Note that the max_memory_to_use option is ignored by this implementation. + */ + +#define JPEG_INTERNALS +#include "jinclude12.h" +#include "jpeglib12.h" +#include "jmemsys12.h" /* import the system-dependent declarations */ + +#ifndef HAVE_STDLIB_H /* should declare malloc(),free() */ +extern void * malloc JPP((size_t size)); +extern void free JPP((void *ptr)); +#endif + + +/* + * Memory allocation and freeing are controlled by the regular library + * routines malloc() and free(). + */ + +GLOBAL(void *) +jpeg_get_small (j_common_ptr cinfo, size_t sizeofobject) +{ + return (void *) malloc(sizeofobject); +} + +GLOBAL(void) +jpeg_free_small (j_common_ptr cinfo, void * object, size_t sizeofobject) +{ + free(object); +} + + +/* + * "Large" objects are treated the same as "small" ones. + * NB: although we include FAR keywords in the routine declarations, + * this file won't actually work in 80x86 small/medium model; at least, + * you probably won't be able to process useful-size images in only 64KB. + */ + +GLOBAL(void FAR *) +jpeg_get_large (j_common_ptr cinfo, size_t sizeofobject) +{ + return (void FAR *) malloc(sizeofobject); +} + +GLOBAL(void) +jpeg_free_large (j_common_ptr cinfo, void FAR * object, size_t sizeofobject) +{ + free(object); +} + + +/* + * This routine computes the total memory space available for allocation. + * Here we always say, "we got all you want bud!" + */ + +GLOBAL(long) +jpeg_mem_available (j_common_ptr cinfo, long min_bytes_needed, + long max_bytes_needed, long already_allocated) +{ + return max_bytes_needed; +} + + +/* + * Backing store (temporary file) management. + * Since jpeg_mem_available always promised the moon, + * this should never be called and we can just error out. + */ + +GLOBAL(void) +jpeg_open_backing_store (j_common_ptr cinfo, backing_store_ptr info, + long total_bytes_needed) +{ + ERREXIT(cinfo, JERR_NO_BACKING_STORE); +} + + +/* + * These routines take care of any system-dependent initialization and + * cleanup required. Here, there isn't any. + */ + +GLOBAL(long) +jpeg_mem_init (j_common_ptr cinfo) +{ + return 0; /* just set max_memory_to_use to 0 */ +} + +GLOBAL(void) +jpeg_mem_term (j_common_ptr cinfo) +{ + /* no work */ +} diff --git a/dcmjpeg/libijg12/jmemsys12.h b/dcmjpeg/libijg12/jmemsys12.h new file mode 100644 index 00000000..0e8daca4 --- /dev/null +++ b/dcmjpeg/libijg12/jmemsys12.h @@ -0,0 +1,198 @@ +/* + * jmemsys.h + * + * Copyright (C) 1992-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This include file defines the interface between the system-independent + * and system-dependent portions of the JPEG memory manager. No other + * modules need include it. (The system-independent portion is jmemmgr.c; + * there are several different versions of the system-dependent portion.) + * + * This file works as-is for the system-dependent memory managers supplied + * in the IJG distribution. You may need to modify it if you write a + * custom memory manager. If system-dependent changes are needed in + * this file, the best method is to #ifdef them based on a configuration + * symbol supplied in jconfig.h, as we have done with USE_MSDOS_MEMMGR + * and USE_MAC_MEMMGR. + */ + + +/* Short forms of external names for systems with brain-damaged linkers. */ + +#ifdef NEED_SHORT_EXTERNAL_NAMES +#define jpeg_get_small jpeg12_get_small +#define jpeg_free_small jpeg12_free_small +#define jpeg_get_large jpeg12_get_large +#define jpeg_free_large jpeg12_free_large +#define jpeg_mem_available jpeg12_mem_available +#define jpeg_open_backing_store jpeg12_open_backing_store +#define jpeg_mem_init jpeg12_mem_init +#define jpeg_mem_term jpeg12_mem_term +#endif /* NEED_SHORT_EXTERNAL_NAMES */ + + +/* + * These two functions are used to allocate and release small chunks of + * memory. (Typically the total amount requested through jpeg_get_small is + * no more than 20K or so; this will be requested in chunks of a few K each.) + * Behavior should be the same as for the standard library functions malloc + * and free; in particular, jpeg_get_small must return NULL on failure. + * On most systems, these ARE malloc and free. jpeg_free_small is passed the + * size of the object being freed, just in case it's needed. + * On an 80x86 machine using small-data memory model, these manage near heap. + */ + +EXTERN(void *) jpeg_get_small JPP((j_common_ptr cinfo, size_t sizeofobject)); +EXTERN(void) jpeg_free_small JPP((j_common_ptr cinfo, void * object, + size_t sizeofobject)); + +/* + * These two functions are used to allocate and release large chunks of + * memory (up to the total free space designated by jpeg_mem_available). + * The interface is the same as above, except that on an 80x86 machine, + * far pointers are used. On most other machines these are identical to + * the jpeg_get/free_small routines; but we keep them separate anyway, + * in case a different allocation strategy is desirable for large chunks. + */ + +EXTERN(void FAR *) jpeg_get_large JPP((j_common_ptr cinfo, + size_t sizeofobject)); +EXTERN(void) jpeg_free_large JPP((j_common_ptr cinfo, void FAR * object, + size_t sizeofobject)); + +/* + * The macro MAX_ALLOC_CHUNK designates the maximum number of bytes that may + * be requested in a single call to jpeg_get_large (and jpeg_get_small for that + * matter, but that case should never come into play). This macro is needed + * to model the 64Kb-segment-size limit of far addressing on 80x86 machines. + * On those machines, we expect that jconfig.h will provide a proper value. + * On machines with 32-bit flat address spaces, any large constant may be used. + * + * NB: jmemmgr.c expects that MAX_ALLOC_CHUNK will be representable as type + * size_t and will be a multiple of sizeof(align_type). + */ + +#ifndef MAX_ALLOC_CHUNK /* may be overridden in jconfig.h */ +#define MAX_ALLOC_CHUNK 1000000000L +#endif + +/* + * This routine computes the total space still available for allocation by + * jpeg_get_large. If more space than this is needed, backing store will be + * used. NOTE: any memory already allocated must not be counted. + * + * There is a minimum space requirement, corresponding to the minimum + * feasible buffer sizes; jmemmgr.c will request that much space even if + * jpeg_mem_available returns zero. The maximum space needed, enough to hold + * all working storage in memory, is also passed in case it is useful. + * Finally, the total space already allocated is passed. If no better + * method is available, cinfo->mem->max_memory_to_use - already_allocated + * is often a suitable calculation. + * + * It is OK for jpeg_mem_available to underestimate the space available + * (that'll just lead to more backing-store access than is really necessary). + * However, an overestimate will lead to failure. Hence it's wise to subtract + * a slop factor from the true available space. 5% should be enough. + * + * On machines with lots of virtual memory, any large constant may be returned. + * Conversely, zero may be returned to always use the minimum amount of memory. + */ + +EXTERN(long) jpeg_mem_available JPP((j_common_ptr cinfo, + long min_bytes_needed, + long max_bytes_needed, + long already_allocated)); + + +/* + * This structure holds whatever state is needed to access a single + * backing-store object. The read/write/close method pointers are called + * by jmemmgr.c to manipulate the backing-store object; all other fields + * are private to the system-dependent backing store routines. + */ + +#define TEMP_NAME_LENGTH 64 /* max length of a temporary file's name */ + + +#ifdef USE_MSDOS_MEMMGR /* DOS-specific junk */ + +typedef unsigned short XMSH; /* type of extended-memory handles */ +typedef unsigned short EMSH; /* type of expanded-memory handles */ + +typedef union { + short file_handle; /* DOS file handle if it's a temp file */ + XMSH xms_handle; /* handle if it's a chunk of XMS */ + EMSH ems_handle; /* handle if it's a chunk of EMS */ +} handle_union; + +#endif /* USE_MSDOS_MEMMGR */ + +#ifdef USE_MAC_MEMMGR /* Mac-specific junk */ +#include +#endif /* USE_MAC_MEMMGR */ + + +typedef struct backing_store_struct * backing_store_ptr; + +typedef struct backing_store_struct { + /* Methods for reading/writing/closing this backing-store object */ + JMETHOD(void, read_backing_store, (j_common_ptr cinfo, + backing_store_ptr info, + void FAR * buffer_address, + long file_offset, long byte_count)); + JMETHOD(void, write_backing_store, (j_common_ptr cinfo, + backing_store_ptr info, + void FAR * buffer_address, + long file_offset, long byte_count)); + JMETHOD(void, close_backing_store, (j_common_ptr cinfo, + backing_store_ptr info)); + + /* Private fields for system-dependent backing-store management */ +#ifdef USE_MSDOS_MEMMGR + /* For the MS-DOS manager (jmemdos.c), we need: */ + handle_union handle; /* reference to backing-store storage object */ + char temp_name[TEMP_NAME_LENGTH]; /* name if it's a file */ +#else +#ifdef USE_MAC_MEMMGR + /* For the Mac manager (jmemmac.c), we need: */ + short temp_file; /* file reference number to temp file */ + FSSpec tempSpec; /* the FSSpec for the temp file */ + char temp_name[TEMP_NAME_LENGTH]; /* name if it's a file */ +#else + /* For a typical implementation with temp files, we need: */ + FILE * temp_file; /* stdio reference to temp file */ + char temp_name[TEMP_NAME_LENGTH]; /* name of temp file */ +#endif +#endif +} backing_store_info; + + +/* + * Initial opening of a backing-store object. This must fill in the + * read/write/close pointers in the object. The read/write routines + * may take an error exit if the specified maximum file size is exceeded. + * (If jpeg_mem_available always returns a large value, this routine can + * just take an error exit.) + */ + +EXTERN(void) jpeg_open_backing_store JPP((j_common_ptr cinfo, + backing_store_ptr info, + long total_bytes_needed)); + + +/* + * These routines take care of any system-dependent initialization and + * cleanup required. jpeg_mem_init will be called before anything is + * allocated (and, therefore, nothing in cinfo is of use except the error + * manager pointer). It should return a suitable default value for + * max_memory_to_use; this may subsequently be overridden by the surrounding + * application. (Note that max_memory_to_use is only important if + * jpeg_mem_available chooses to consult it ... no one else will.) + * jpeg_mem_term may assume that all requested memory has been freed and that + * all opened backing-store objects have been closed. + */ + +EXTERN(long) jpeg_mem_init JPP((j_common_ptr cinfo)); +EXTERN(void) jpeg_mem_term JPP((j_common_ptr cinfo)); diff --git a/dcmjpeg/libijg12/jmorecfg12.h b/dcmjpeg/libijg12/jmorecfg12.h new file mode 100644 index 00000000..00873e79 --- /dev/null +++ b/dcmjpeg/libijg12/jmorecfg12.h @@ -0,0 +1,407 @@ +/* + * jmorecfg.h + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains additional configuration options that customize the + * JPEG software for special applications or support machine-dependent + * optimizations. Most users will not need to touch this file. + */ + + +#include "dcmtk/ofstd/ofexport.h" /* for DCMTK_DECL_EXPORT */ + +#ifdef ijg12_EXPORTS +#define DCMTK_IJG12_EXPORT DCMTK_DECL_EXPORT +#else +#define DCMTK_IJG12_EXPORT DCMTK_DECL_IMPORT +#endif + + +/* + * Define BITS_IN_JSAMPLE as either + * 8 for 8-bit sample values (the usual setting) + * 12 for 12-bit sample values + * Only 8 and 12 are legal data precisions for lossy JPEG according to the + * JPEG standard, and the IJG code does not support anything else! + * We do not support run-time selection of data precision, sorry. + */ + +#define BITS_IN_JSAMPLE 12 /* use 8 or 12 (or 16 for lossless) */ + + +/* + * Maximum number of components (color channels) allowed in JPEG image. + * To meet the letter of the JPEG spec, set this to 255. However, darn + * few applications need more than 4 channels (maybe 5 for CMYK + alpha + * mask). We recommend 10 as a reasonable compromise; use 4 if you are + * really short on memory. (Each allowed component costs a hundred or so + * bytes of storage, whether actually used in an image or not.) + */ + +#define MAX_COMPONENTS 10 /* maximum number of image components */ + + +/* + * Basic data types. + * You may need to change these if you have a machine with unusual data + * type sizes; for example, "char" not 8 bits, "short" not 16 bits, + * or "long" not 32 bits. We don't care whether "int" is 16 or 32 bits, + * but it had better be at least 16. + */ + +/* Representation of a single sample (pixel element value). + * We frequently allocate large arrays of these, so it's important to keep + * them small. But if you have memory to burn and access to char or short + * arrays is very slow on your hardware, you might want to change these. + */ + +#if BITS_IN_JSAMPLE == 8 +/* JSAMPLE should be the smallest type that will hold the values 0..255. + * You can use a signed char by having GETJSAMPLE mask it with 0xFF. + */ + +#ifdef HAVE_UNSIGNED_CHAR + +typedef unsigned char JSAMPLE; +#define GETJSAMPLE(value) ((int) (value)) + +#else /* not HAVE_UNSIGNED_CHAR */ + +typedef char JSAMPLE; +#ifdef CHAR_IS_UNSIGNED +#define GETJSAMPLE(value) ((int) (value)) +#else +#define GETJSAMPLE(value) ((int) (value) & 0xFF) +#endif /* CHAR_IS_UNSIGNED */ + +#endif /* HAVE_UNSIGNED_CHAR */ + +#define MAXJSAMPLE 255 +#define CENTERJSAMPLE 128 + +#endif /* BITS_IN_JSAMPLE == 8 */ + + +#if BITS_IN_JSAMPLE == 12 +/* JSAMPLE should be the smallest type that will hold the values 0..4095. + * On nearly all machines "short" will do nicely. + */ + +typedef short JSAMPLE; +#define GETJSAMPLE(value) ((int) (value)) + +#define MAXJSAMPLE 4095 +#define CENTERJSAMPLE 2048 + +#endif /* BITS_IN_JSAMPLE == 12 */ + + +#if BITS_IN_JSAMPLE == 16 +/* JSAMPLE should be the smallest type that will hold the values 0..65535. + * You can use a signed short by having GETJSAMPLE mask it with 0xFFFF. + */ + +#ifdef HAVE_UNSIGNED_SHORT + +typedef unsigned short JSAMPLE; +#define GETJSAMPLE(value) ((int) (value)) + +#else /* not HAVE_UNSIGNED_SHORT */ + +typedef short JSAMPLE; +#ifdef SHORT_IS_UNSIGNED +#define GETJSAMPLE(value) ((int) (value)) +#else +#define GETJSAMPLE(value) ((int) (value) & 0xFFFF) +#endif /* SHORT_IS_UNSIGNED */ + +#endif /* HAVE_UNSIGNED_SHORT */ + +#define MAXJSAMPLE 65535 +#define CENTERJSAMPLE 32768 + +#endif /* BITS_IN_JSAMPLE == 16 */ + + +/* Representation of a DCT frequency coefficient. + * This should be a signed value of at least 16 bits; "short" is usually OK. + * Again, we allocate large arrays of these, but you can change to int + * if you have memory to burn and "short" is really slow. + */ + +typedef short JCOEF; + + +/* Representation of a spatial difference value. + * This should be a signed value of at least 16 bits; int is usually OK. + */ + +typedef int JDIFF; + + +/* Compressed datastreams are represented as arrays of JOCTET. + * These must be EXACTLY 8 bits wide, at least once they are written to + * external storage. Note that when using the stdio data source/destination + * managers, this is also the data type passed to fread/fwrite. + */ + +#ifdef HAVE_UNSIGNED_CHAR + +typedef unsigned char JOCTET; +#define GETJOCTET(value) (value) + +#else /* not HAVE_UNSIGNED_CHAR */ + +typedef char JOCTET; +#ifdef CHAR_IS_UNSIGNED +#define GETJOCTET(value) (value) +#else +#define GETJOCTET(value) ((value) & 0xFF) +#endif /* CHAR_IS_UNSIGNED */ + +#endif /* HAVE_UNSIGNED_CHAR */ + + +/* These typedefs are used for various table entries and so forth. + * They must be at least as wide as specified; but making them too big + * won't cost a huge amount of memory, so we don't provide special + * extraction code like we did for JSAMPLE. (In other words, these + * typedefs live at a different point on the speed/space tradeoff curve.) + */ + +/* UINT8 must hold at least the values 0..255. */ + +#ifdef HAVE_UNSIGNED_CHAR +typedef unsigned char UINT8; +#else /* not HAVE_UNSIGNED_CHAR */ +#ifdef CHAR_IS_UNSIGNED +typedef char UINT8; +#else /* not CHAR_IS_UNSIGNED */ +typedef short UINT8; +#endif /* CHAR_IS_UNSIGNED */ +#endif /* HAVE_UNSIGNED_CHAR */ + +/* UINT16 must hold at least the values 0..65535. */ + +#ifdef HAVE_UNSIGNED_SHORT +typedef unsigned short UINT16; +#else /* not HAVE_UNSIGNED_SHORT */ +typedef unsigned int UINT16; +#endif /* HAVE_UNSIGNED_SHORT */ + +/* INT16 must hold at least the values -32768..32767. */ + +#ifndef XMD_H /* X11/xmd.h correctly defines INT16 */ +typedef short INT16; +#endif + +/* IJG_INT32 must hold at least signed 32-bit values. */ +typedef long IJG_INT32; + +/* Datatype used for image dimensions. The JPEG standard only supports + * images up to 64K*64K due to 16-bit fields in SOF markers. Therefore + * "unsigned int" is sufficient on all machines. However, if you need to + * handle larger images and you don't mind deviating from the spec, you + * can change this datatype. + */ + +typedef unsigned int JDIMENSION; + +#define JPEG_MAX_DIMENSION 65500L /* a tad under 64K to prevent overflows */ + + +/* These macros are used in all function definitions and extern declarations. + * You could modify them if you need to change function linkage conventions; + * in particular, you'll need to do that to make the library a Windows DLL. + * Another application is to make all functions global for use with debuggers + * or code profilers that require it. + */ + +/* a function called through method pointers: */ +#define METHODDEF(type) static type +/* a function used only in its module: */ +#define LOCAL(type) static type +/* a function referenced thru EXTERNs: */ +#define GLOBAL(type) type +/* a reference to a GLOBAL function: */ +#define EXTERN(type) extern DCMTK_IJG12_EXPORT type + + +/* This macro is used to declare a "method", that is, a function pointer. + * We want to supply prototype parameters if the compiler can cope. + * Note that the arglist parameter must be parenthesized! + * Again, you can customize this if you need special linkage keywords. + */ + +#ifdef HAVE_PROTOTYPES +#define JMETHOD(type,methodname,arglist) type (*methodname) arglist +#else +#define JMETHOD(type,methodname,arglist) type (*methodname) () +#endif + + +/* Here is the pseudo-keyword for declaring pointers that must be "far" + * on 80x86 machines. Most of the specialized coding for 80x86 is handled + * by just saying "FAR *" where such a pointer is needed. In a few places + * explicit coding is needed; see uses of the NEED_FAR_POINTERS symbol. + */ + +#undef FAR +#ifdef NEED_FAR_POINTERS +#define FAR far +#else +#define FAR +#endif + + +/* + * On a few systems, type boolean and/or its values FALSE, TRUE may appear + * in standard header files. Or you may have conflicts with application- + * specific header files that you want to include together with these files. + * Defining HAVE_BOOLEAN before including jpeglib.h should make it work. + */ + +#ifndef HAVE_BOOLEAN +typedef int boolean; +#endif +#ifndef FALSE /* in case these macros already exist */ +#define FALSE 0 /* values of boolean */ +#endif +#ifndef TRUE +#define TRUE 1 +#endif + + +/* + * The remaining options affect code selection within the JPEG library, + * but they don't need to be visible to most applications using the library. + * To minimize application namespace pollution, the symbols won't be + * defined unless JPEG_INTERNALS or JPEG_INTERNAL_OPTIONS has been defined. + */ + +#ifdef JPEG_INTERNALS +#define JPEG_INTERNAL_OPTIONS +#endif + +#ifdef JPEG_INTERNAL_OPTIONS + + +/* + * These defines indicate whether to include various optional functions. + * Undefining some of these symbols will produce a smaller but less capable + * library. Note that you can leave certain source files out of the + * compilation/linking process if you've #undef'd the corresponding symbols. + * (You may HAVE to do that if your compiler doesn't like null source files.) + */ + +/* Arithmetic coding is unsupported for legal reasons. Complaints to IBM. */ + +/* Capability options common to encoder and decoder: */ + +#define DCT_ISLOW_SUPPORTED /* slow but accurate integer algorithm */ +#define DCT_IFAST_SUPPORTED /* faster, less accurate integer method */ +#define DCT_FLOAT_SUPPORTED /* floating-point: accurate, fast on fast HW */ + +/* Encoder capability options: */ + +#undef C_ARITH_CODING_SUPPORTED /* Arithmetic coding back end? */ +#define C_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */ +#define C_PROGRESSIVE_SUPPORTED /* Progressive JPEG? (Requires MULTISCAN)*/ +#define C_LOSSLESS_SUPPORTED /* Lossless JPEG? */ +#define ENTROPY_OPT_SUPPORTED /* Optimization of entropy coding parms? */ +/* Note: if you selected 12-bit data precision, it is dangerous to turn off + * ENTROPY_OPT_SUPPORTED. The standard Huffman tables are only good for 8-bit + * precision, so jcshuff.c normally uses entropy optimization to compute + * usable tables for higher precision. If you don't want to do optimization, + * you'll have to supply different default Huffman tables. + * The exact same statements apply for progressive and lossless JPEG: + * the default tables don't work for progressive mode or lossless mode. + * (This may get fixed, however.) + */ +#define INPUT_SMOOTHING_SUPPORTED /* Input image smoothing option? */ + +/* Decoder capability options: */ + +#undef D_ARITH_CODING_SUPPORTED /* Arithmetic coding back end? */ +#define D_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */ +#define D_PROGRESSIVE_SUPPORTED /* Progressive JPEG? (Requires MULTISCAN)*/ +#define D_LOSSLESS_SUPPORTED /* Lossless JPEG? */ +#define SAVE_MARKERS_SUPPORTED /* jpeg_save_markers() needed? */ +#define BLOCK_SMOOTHING_SUPPORTED /* Block smoothing? (Progressive only) */ +#define IDCT_SCALING_SUPPORTED /* Output rescaling via IDCT? */ +#undef UPSAMPLE_SCALING_SUPPORTED /* Output rescaling at upsample stage? */ +#define UPSAMPLE_MERGING_SUPPORTED /* Fast path for sloppy upsampling? */ +#define QUANT_1PASS_SUPPORTED /* 1-pass color quantization? */ +#define QUANT_2PASS_SUPPORTED /* 2-pass color quantization? */ + +/* more capability options later, no doubt */ + + +/* + * Ordering of RGB data in scanlines passed to or from the application. + * If your application wants to deal with data in the order B,G,R, just + * change these macros. You can also deal with formats such as R,G,B,X + * (one extra byte per pixel) by changing RGB_PIXELSIZE. Note that changing + * the offsets will also change the order in which colormap data is organized. + * RESTRICTIONS: + * 1. The sample applications cjpeg,djpeg do NOT support modified RGB formats. + * 2. These macros only affect RGB<=>YCbCr color conversion, so they are not + * useful if you are using JPEG color spaces other than YCbCr or grayscale. + * 3. The color quantizer modules will not behave desirably if RGB_PIXELSIZE + * is not 3 (they don't understand about dummy color components!). So you + * can't use color quantization if you change that value. + */ + +#define RGB_RED 0 /* Offset of Red in an RGB scanline element */ +#define RGB_GREEN 1 /* Offset of Green */ +#define RGB_BLUE 2 /* Offset of Blue */ +#define RGB_PIXELSIZE 3 /* JSAMPLEs per RGB scanline element */ + + +/* Definitions for speed-related optimizations. */ + + +/* If your compiler supports inline functions, define INLINE + * as the inline keyword; otherwise define it as empty. + */ + +#ifndef INLINE +#ifdef __GNUC__ /* for instance, GNU C knows about inline */ +#define INLINE __inline__ +#endif +#ifndef INLINE +#define INLINE /* default is to define it as empty */ +#endif +#endif + + +/* On some machines (notably 68000 series) "int" is 32 bits, but multiplying + * two 16-bit shorts is faster than multiplying two ints. Define MULTIPLIER + * as short on such a machine. MULTIPLIER must be at least 16 bits wide. + */ + +#ifndef MULTIPLIER +#define MULTIPLIER int /* type for fastest integer multiply */ +#endif + + +/* FAST_FLOAT should be either float or double, whichever is done faster + * by your compiler. (Note that this type is only used in the floating point + * DCT routines, so it only matters if you've defined DCT_FLOAT_SUPPORTED.) + * Typically, float is faster in ANSI C compilers, while double is faster in + * pre-ANSI compilers (because they insist on converting to double anyway). + * The code below therefore chooses float if we have ANSI-style prototypes. + */ + +#ifndef FAST_FLOAT +#ifdef HAVE_PROTOTYPES +#define FAST_FLOAT float +#else +#define FAST_FLOAT double +#endif +#endif + +#endif /* JPEG_INTERNAL_OPTIONS */ diff --git a/dcmjpeg/libijg12/jpegint12.h b/dcmjpeg/libijg12/jpegint12.h new file mode 100644 index 00000000..d47b3264 --- /dev/null +++ b/dcmjpeg/libijg12/jpegint12.h @@ -0,0 +1,373 @@ +/* + * jpegint.h + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file provides common declarations for the various JPEG modules. + * These declarations are considered internal to the JPEG library; most + * applications using the library shouldn't need to include this file. + */ + + +/* Declarations for both compression & decompression */ + +typedef enum { /* Operating modes for buffer controllers */ + JBUF_PASS_THRU, /* Plain stripwise operation */ + /* Remaining modes require a full-image buffer to have been created */ + JBUF_SAVE_SOURCE, /* Run source subobject only, save output */ + JBUF_CRANK_DEST, /* Run dest subobject only, using saved data */ + JBUF_SAVE_AND_PASS /* Run both subobjects, save output */ +} J_BUF_MODE; + +/* Values of global_state field (jdapi.c has some dependencies on ordering!) */ +#define CSTATE_START 100 /* after create_compress */ +#define CSTATE_SCANNING 101 /* start_compress done, write_scanlines OK */ +#define CSTATE_RAW_OK 102 /* start_compress done, write_raw_data OK */ +#define CSTATE_WRCOEFS 103 /* jpeg_write_coefficients done */ +#define DSTATE_START 200 /* after create_decompress */ +#define DSTATE_INHEADER 201 /* reading header markers, no SOS yet */ +#define DSTATE_READY 202 /* found SOS, ready for start_decompress */ +#define DSTATE_PRELOAD 203 /* reading multiscan file in start_decompress*/ +#define DSTATE_PRESCAN 204 /* performing dummy pass for 2-pass quant */ +#define DSTATE_SCANNING 205 /* start_decompress done, read_scanlines OK */ +#define DSTATE_RAW_OK 206 /* start_decompress done, read_raw_data OK */ +#define DSTATE_BUFIMAGE 207 /* expecting jpeg_start_output */ +#define DSTATE_BUFPOST 208 /* looking for SOS/EOI in jpeg_finish_output */ +#define DSTATE_RDCOEFS 209 /* reading file in jpeg_read_coefficients */ +#define DSTATE_STOPPING 210 /* looking for EOI in jpeg_finish_decompress */ + + +/* Declarations for compression modules */ + +/* Master control module */ +struct jpeg_comp_master { + JMETHOD(void, prepare_for_pass, (j_compress_ptr cinfo)); + JMETHOD(void, pass_startup, (j_compress_ptr cinfo)); + JMETHOD(void, finish_pass, (j_compress_ptr cinfo)); + + /* State variables made visible to other modules */ + boolean call_pass_startup; /* True if pass_startup must be called */ + boolean is_last_pass; /* True during last pass */ +}; + +/* Main buffer control (downsampled-data buffer) */ +struct jpeg_c_main_controller { + JMETHOD(void, start_pass, (j_compress_ptr cinfo, J_BUF_MODE pass_mode)); + JMETHOD(void, process_data, (j_compress_ptr cinfo, + JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, + JDIMENSION in_rows_avail)); +}; + +/* Compression preprocessing (downsampling input buffer control) */ +struct jpeg_c_prep_controller { + JMETHOD(void, start_pass, (j_compress_ptr cinfo, J_BUF_MODE pass_mode)); + JMETHOD(void, pre_process_data, (j_compress_ptr cinfo, + JSAMPARRAY input_buf, + JDIMENSION *in_row_ctr, + JDIMENSION in_rows_avail, + JSAMPIMAGE output_buf, + JDIMENSION *out_row_group_ctr, + JDIMENSION out_row_groups_avail)); +}; + +/* Compression codec (compressor proper) */ +struct jpeg_c_codec { + JMETHOD(void, entropy_start_pass, (j_compress_ptr cinfo, + boolean gather_statistics)); + JMETHOD(void, entropy_finish_pass, (j_compress_ptr cinfo)); + JMETHOD(boolean, need_optimization_pass, (j_compress_ptr cinfo)); + JMETHOD(void, start_pass, (j_compress_ptr cinfo, J_BUF_MODE pass_mode)); + JMETHOD(boolean, compress_data, (j_compress_ptr cinfo, + JSAMPIMAGE input_buf)); +}; + +/* Colorspace conversion */ +struct jpeg_color_converter { + JMETHOD(void, start_pass, (j_compress_ptr cinfo)); + JMETHOD(void, color_convert, (j_compress_ptr cinfo, + JSAMPARRAY input_buf, JSAMPIMAGE output_buf, + JDIMENSION output_row, int num_rows)); +}; + +/* Downsampling */ +struct jpeg_downsampler { + JMETHOD(void, start_pass, (j_compress_ptr cinfo)); + JMETHOD(void, downsample, (j_compress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION in_row_index, + JSAMPIMAGE output_buf, + JDIMENSION out_row_group_index)); + + boolean need_context_rows; /* TRUE if need rows above & below */ +}; + +/* Marker writing */ +struct jpeg_marker_writer { + JMETHOD(void, write_file_header, (j_compress_ptr cinfo)); + JMETHOD(void, write_frame_header, (j_compress_ptr cinfo)); + JMETHOD(void, write_scan_header, (j_compress_ptr cinfo)); + JMETHOD(void, write_file_trailer, (j_compress_ptr cinfo)); + JMETHOD(void, write_tables_only, (j_compress_ptr cinfo)); + /* These routines are exported to allow insertion of extra markers */ + /* Probably only COM and APPn markers should be written this way */ + JMETHOD(void, write_marker_header, (j_compress_ptr cinfo, int marker, + unsigned int datalen)); + JMETHOD(void, write_marker_byte, (j_compress_ptr cinfo, int val)); +}; + + +/* Declarations for decompression modules */ + +/* Master control module */ +struct jpeg_decomp_master { + JMETHOD(void, prepare_for_output_pass, (j_decompress_ptr cinfo)); + JMETHOD(void, finish_output_pass, (j_decompress_ptr cinfo)); + + /* State variables made visible to other modules */ + boolean is_dummy_pass; /* True during 1st pass for 2-pass quant */ +}; + +/* Input control module */ +struct jpeg_input_controller { + JMETHOD(int, consume_input, (j_decompress_ptr cinfo)); + JMETHOD(void, reset_input_controller, (j_decompress_ptr cinfo)); + JMETHOD(void, start_input_pass, (j_decompress_ptr cinfo)); + JMETHOD(void, finish_input_pass, (j_decompress_ptr cinfo)); + + /* State variables made visible to other modules */ + boolean has_multiple_scans; /* True if file has multiple scans */ + boolean eoi_reached; /* True when EOI has been consumed */ +}; + +/* Main buffer control (downsampled-data buffer) */ +struct jpeg_d_main_controller { + JMETHOD(void, start_pass, (j_decompress_ptr cinfo, J_BUF_MODE pass_mode)); + JMETHOD(void, process_data, (j_decompress_ptr cinfo, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail)); +}; + +/* Decompression codec (decompressor proper) */ +struct jpeg_d_codec { + JMETHOD(void, calc_output_dimensions, (j_decompress_ptr cinfo)); + JMETHOD(void, start_input_pass, (j_decompress_ptr cinfo)); + JMETHOD(int, consume_data, (j_decompress_ptr cinfo)); + JMETHOD(void, start_output_pass, (j_decompress_ptr cinfo)); + JMETHOD(int, decompress_data, (j_decompress_ptr cinfo, + JSAMPIMAGE output_buf)); +}; + +/* Decompression postprocessing (color quantization buffer control) */ +struct jpeg_d_post_controller { + JMETHOD(void, start_pass, (j_decompress_ptr cinfo, J_BUF_MODE pass_mode)); + JMETHOD(void, post_process_data, (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, + JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + JSAMPARRAY output_buf, + JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail)); +}; + +/* Marker reading & parsing */ +struct jpeg_marker_reader { + JMETHOD(void, reset_marker_reader, (j_decompress_ptr cinfo)); + /* Read markers until SOS or EOI. + * Returns same codes as are defined for jpeg_consume_input: + * JPEG_SUSPENDED, JPEG_REACHED_SOS, or JPEG_REACHED_EOI. + */ + JMETHOD(int, read_markers, (j_decompress_ptr cinfo)); + /* Read a restart marker --- exported for use by entropy decoder only */ + jpeg_marker_parser_method read_restart_marker; + + /* State of marker reader --- nominally internal, but applications + * supplying COM or APPn handlers might like to know the state. + */ + boolean saw_SOI; /* found SOI? */ + boolean saw_SOF; /* found SOF? */ + int next_restart_num; /* next restart number expected (0-7) */ + unsigned int discarded_bytes; /* # of bytes skipped looking for a marker */ +}; + +/* Upsampling (note that upsampler must also call color converter) */ +struct jpeg_upsampler { + JMETHOD(void, start_pass, (j_decompress_ptr cinfo)); + JMETHOD(void, upsample, (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, + JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + JSAMPARRAY output_buf, + JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail)); + + boolean need_context_rows; /* TRUE if need rows above & below */ +}; + +/* Colorspace conversion */ +struct jpeg_color_deconverter { + JMETHOD(void, start_pass, (j_decompress_ptr cinfo)); + JMETHOD(void, color_convert, (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION input_row, + JSAMPARRAY output_buf, int num_rows)); +}; + +/* Color quantization or color precision reduction */ +struct jpeg_color_quantizer { + JMETHOD(void, start_pass, (j_decompress_ptr cinfo, boolean is_pre_scan)); + JMETHOD(void, color_quantize, (j_decompress_ptr cinfo, + JSAMPARRAY input_buf, JSAMPARRAY output_buf, + int num_rows)); + JMETHOD(void, finish_pass, (j_decompress_ptr cinfo)); + JMETHOD(void, new_color_map, (j_decompress_ptr cinfo)); +}; + + +/* Miscellaneous useful macros */ + +#undef MAX +#define MAX(a,b) ((a) > (b) ? (a) : (b)) +#undef MIN +#define MIN(a,b) ((a) < (b) ? (a) : (b)) + + +/* We assume that right shift corresponds to signed division by 2 with + * rounding towards minus infinity. This is correct for typical "arithmetic + * shift" instructions that shift in copies of the sign bit. But some + * C compilers implement >> with an unsigned shift. For these machines you + * must define RIGHT_SHIFT_IS_UNSIGNED. + * RIGHT_SHIFT provides a proper signed right shift of an IJG_INT32 quantity. + * It is only applied with constant shift counts. SHIFT_TEMPS must be + * included in the variables of any routine using RIGHT_SHIFT. + */ + +#ifdef RIGHT_SHIFT_IS_UNSIGNED +#define SHIFT_TEMPS IJG_INT32 shift_temp; +#define RIGHT_SHIFT(x,shft) \ + ((shift_temp = (x)) < 0 ? \ + (shift_temp >> (shft)) | ((~((IJG_INT32) 0)) << (32-(shft))) : \ + (shift_temp >> (shft))) +#else +#define SHIFT_TEMPS +#define RIGHT_SHIFT(x,shft) ((x) >> (shft)) +#endif + + +/* Short forms of external names for systems with brain-damaged linkers. */ + +#ifdef NEED_SHORT_EXTERNAL_NAMES +#define jinit_c_codec jinit12_c_codec +#define jinit_c_diff_controller jinit12_c_diff_controller +#define jinit_lossy_c_codec jinit12_lossy_c_codec +#define jinit_lossless_c_codec jinit12_lossless_c_codec +#define jinit_compress_master jinit12_compress_master +#define jinit_c_master_control jinit12_c_master_control +#define jinit_c_main_controller jinit12_c_main_controller +#define jinit_c_prep_controller jinit12_c_prep_controller +#define jinit_c_coef_controller jinit12_c_coef_controller +#define jinit_color_converter jinit12_color_converter +#define jinit_downsampler jinit12_downsampler +#define jinit_forward_dct jinit12_forward_dct +#define jinit_shuff_encoder jinit12_shuff_encoder +#define jinit_phuff_encoder jinit12_phuff_encoder +#ifdef WITH_ARITHMETIC_PATCH +#define jinit_arith_encoder jinit12_arith_encoder +#endif +#define jinit_marker_writer jinit12_marker_writer +#define jinit_d_codec jinit12_d_codec +#define jinit_lossy_d_codec jinit12_lossy_d_codec +#define jinit_lossless_d_codec jinit12_lossless_d_codec +#define jinit_master_decompress jinit12_master_decompress +#define jinit_d_main_controller jinit12_d_main_controller +#define jinit_d_coef_controller jinit12_d_coef_controller +#define jinit_d_diff_controller jinit12_d_diff_controller +#define jinit_d_post_controller jinit12_d_post_controller +#define jinit_input_controller jinit12_input_controller +#define jinit_marker_reader jinit12_marker_reader +#define jinit_shuff_decoder jinit12_shuff_decoder +#define jinit_phuff_decoder jinit12_phuff_decoder +#ifdef WITH_ARITHMETIC_PATCH +#define jinit_arith_decoder jinit12_arith_decoder +#endif +#define jinit_lhuff_decoder jinit12_lhuff_decoder +#define jinit_undifferencer jinit12_undifferencer +#define jinit_d_scaler jinit12_d_scaler +#define jinit_inverse_dct jinit12_inverse_dct +#define jinit_upsampler jinit12_upsampler +#define jinit_color_deconverter jinit12_color_deconverter +#define jinit_1pass_quantizer jinit12_1pass_quantizer +#define jinit_2pass_quantizer jinit12_2pass_quantizer +#define jinit_merged_upsampler jinit12_merged_upsampler +#define jinit_memory_mgr jinit12_memory_mgr +#define jdiv_round_up jdiv12_round_up +#define jround_up jround12_up +#define jcopy_sample_rows jcopy12_sample_rows +#define jcopy_block_row jcopy12_block_row +#define jzero_far jzero12_far +#define jpeg_zigzag_order jpeg12_zigzag_order +#define jpeg_natural_order jpeg12_natural_order +#endif /* NEED_SHORT_EXTERNAL_NAMES */ + + +/* Compression module initialization routines */ +EXTERN(void) jinit_c_codec JPP((j_compress_ptr cinfo)); +EXTERN(void) jinit_c_diff_controller JPP((j_compress_ptr cinfo, boolean need_full_buffer)); +EXTERN(void) jinit_compress_master JPP((j_compress_ptr cinfo)); +EXTERN(void) jinit_c_master_control JPP((j_compress_ptr cinfo, + boolean transcode_only)); +EXTERN(void) jinit_c_main_controller JPP((j_compress_ptr cinfo, + boolean need_full_buffer)); +EXTERN(void) jinit_c_prep_controller JPP((j_compress_ptr cinfo, + boolean need_full_buffer)); +EXTERN(void) jinit_compressor JPP((j_compress_ptr cinfo)); +EXTERN(void) jinit_color_converter JPP((j_compress_ptr cinfo)); +EXTERN(void) jinit_downsampler JPP((j_compress_ptr cinfo)); +EXTERN(void) jinit_marker_writer JPP((j_compress_ptr cinfo)); +#ifdef WITH_ARITHMETIC_PATCH +EXTERN(void) jinit_arith_encoder JPP((j_compress_ptr cinfo)); +#endif +/* Decompression module initialization routines */ +EXTERN(void) jinit_d_codec JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_d_diff_controller JPP((j_decompress_ptr cinfo, boolean need_full_buffer)); +EXTERN(void) jinit_master_decompress JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_d_main_controller JPP((j_decompress_ptr cinfo, + boolean need_full_buffer)); +EXTERN(void) jinit_decompressor JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_d_post_controller JPP((j_decompress_ptr cinfo, + boolean need_full_buffer)); +EXTERN(void) jinit_input_controller JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_marker_reader JPP((j_decompress_ptr cinfo)); +#ifdef WITH_ARITHMETIC_PATCH +EXTERN(void) jinit_arith_decoder JPP((j_decompress_ptr cinfo)); +#endif +EXTERN(void) jinit_upsampler JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_color_deconverter JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_1pass_quantizer JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_2pass_quantizer JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_merged_upsampler JPP((j_decompress_ptr cinfo)); +/* Memory manager initialization */ +EXTERN(void) jinit_memory_mgr JPP((j_common_ptr cinfo)); + +/* Utility routines in jutils.c */ +EXTERN(long) jdiv_round_up JPP((long a, long b)); +EXTERN(long) jround_up JPP((long a, long b)); +EXTERN(void) jcopy_sample_rows JPP((JSAMPARRAY input_array, int source_row, + JSAMPARRAY output_array, int dest_row, + int num_rows, JDIMENSION num_cols)); +EXTERN(void) jcopy_block_row JPP((JBLOCKROW input_row, JBLOCKROW output_row, + JDIMENSION num_blocks)); +EXTERN(void) jzero_far JPP((void FAR * target, size_t bytestozero)); +/* Constant tables in jutils.c */ +#if 0 /* This table is not actually needed in v6a */ +extern const int jpeg_zigzag_order[]; /* natural coef order to zigzag order */ +#endif +extern const int jpeg_natural_order[]; /* zigzag coef order to natural order */ + +/* Suppress undefined-structure complaints if necessary. */ + +#ifdef INCOMPLETE_TYPES_BROKEN +#ifndef AM_MEMORY_MANAGER /* only jmemmgr.c defines these */ +struct jvirt_sarray_control { long dummy; }; +struct jvirt_barray_control { long dummy; }; +#endif +#endif /* INCOMPLETE_TYPES_BROKEN */ diff --git a/dcmjpeg/libijg12/jpeglib12.h b/dcmjpeg/libijg12/jpeglib12.h new file mode 100644 index 00000000..0a0baa7b --- /dev/null +++ b/dcmjpeg/libijg12/jpeglib12.h @@ -0,0 +1,1203 @@ +/* + * jpeglib.h + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file defines the application interface for the JPEG library. + * Most applications using the library need only include this file, + * and perhaps jerror.h if they want to know the exact error codes. + */ + +#ifndef JPEGLIB_H +#define JPEGLIB_H + +/* + * First we include the configuration files that record how this + * installation of the JPEG library is set up. jconfig.h can be + * generated automatically for many systems. jmorecfg.h contains + * manual configuration options that most people need not worry about. + */ + +#ifndef JCONFIG_INCLUDED /* in case jinclude.h already did */ +#include "jconfig12.h" /* widely used configuration options */ +#endif +#include "jmorecfg12.h" /* seldom changed options */ + + +/* Version ID for the JPEG library. + * Might be useful for tests like "#if JPEG_LIB_VERSION >= 60". + */ + +#define JPEG_LIB_VERSION 62 /* Version 6b */ + + +/* Various constants determining the sizes of things. + * All of these are specified by the JPEG standard, so don't change them + * if you want to be compatible. + */ + +#define DCTSIZE 8 /* The basic DCT block is 8x8 samples */ +#define DCTSIZE2 64 /* DCTSIZE squared; # of elements in a block */ +#define NUM_QUANT_TBLS 4 /* Quantization tables are numbered 0..3 */ +#define NUM_HUFF_TBLS 4 /* Huffman tables are numbered 0..3 */ +#define NUM_ARITH_TBLS 16 /* Arith-coding tables are numbered 0..15 */ +#define MAX_COMPS_IN_SCAN 4 /* JPEG limit on # of components in one scan */ +#define MAX_SAMP_FACTOR 4 /* JPEG limit on sampling factors */ +/* Unfortunately, some bozo at Adobe saw no reason to be bound by the standard; + * the PostScript DCT filter can emit files with many more than 10 data units + * per MCU. + * If you happen to run across such a file, you can up D_MAX_DATA_UNITS_IN_MCU + * to handle it. We even let you do this from the jconfig.h file. However, + * we strongly discourage changing C_MAX_DATA_UNITS_IN_MCU; just because Adobe + * sometimes emits noncompliant files doesn't mean you should too. + */ +#define C_MAX_DATA_UNITS_IN_MCU 10 /* compressor's limit on data units/MCU */ +#ifndef D_MAX_DATA_UNITS_IN_MCU +#define D_MAX_DATA_UNITS_IN_MCU 10 /* decompressor's limit on data units/MCU */ +#endif + + +/* Data structures for images (arrays of samples and of DCT coefficients). + * On 80x86 machines, the image arrays are too big for near pointers, + * but the pointer arrays can fit in near memory. + */ + +typedef JSAMPLE FAR *JSAMPROW; /* ptr to one image row of pixel samples. */ +typedef JSAMPROW *JSAMPARRAY; /* ptr to some rows (a 2-D sample array) */ +typedef JSAMPARRAY *JSAMPIMAGE; /* a 3-D sample array: top index is color */ + +typedef JCOEF JBLOCK[DCTSIZE2]; /* one block of coefficients */ +typedef JBLOCK FAR *JBLOCKROW; /* pointer to one row of coefficient blocks */ +typedef JBLOCKROW *JBLOCKARRAY; /* a 2-D array of coefficient blocks */ +typedef JBLOCKARRAY *JBLOCKIMAGE; /* a 3-D array of coefficient blocks */ + +typedef JCOEF FAR *JCOEFPTR; /* useful in a couple of places */ + +typedef JDIFF FAR *JDIFFROW; /* pointer to one row of difference values */ +typedef JDIFFROW *JDIFFARRAY; /* ptr to some rows (a 2-D diff array) */ +typedef JDIFFARRAY *JDIFFIMAGE; /* a 3-D diff array: top index is color */ + + +/* Types for JPEG compression parameters and working tables. */ + + +/* DCT coefficient quantization tables. */ + +typedef struct { + /* This array gives the coefficient quantizers in natural array order + * (not the zigzag order in which they are stored in a JPEG DQT marker). + * CAUTION: IJG versions prior to v6a kept this array in zigzag order. + */ + UINT16 quantval[DCTSIZE2]; /* quantization step for each coefficient */ + /* This field is used only during compression. It's initialized FALSE when + * the table is created, and set TRUE when it's been output to the file. + * You could suppress output of a table by setting this to TRUE. + * (See jpeg_suppress_tables for an example.) + */ + boolean sent_table; /* TRUE when table has been output */ +} JQUANT_TBL; + + +/* Huffman coding tables. */ + +typedef struct { + /* These two fields directly represent the contents of a JPEG DHT marker */ + UINT8 bits[17]; /* bits[k] = # of symbols with codes of */ + /* length k bits; bits[0] is unused */ + UINT8 huffval[256]; /* The symbols, in order of incr code length */ + /* This field is used only during compression. It's initialized FALSE when + * the table is created, and set TRUE when it's been output to the file. + * You could suppress output of a table by setting this to TRUE. + * (See jpeg_suppress_tables for an example.) + */ + boolean sent_table; /* TRUE when table has been output */ +} JHUFF_TBL; + + +/* Basic info about one component (color channel). */ + +typedef struct { + /* These values are fixed over the whole image. */ + /* For compression, they must be supplied by parameter setup; */ + /* for decompression, they are read from the SOF marker. */ + int component_id; /* identifier for this component (0..255) */ + int component_index; /* its index in SOF or cinfo->comp_info[] */ + int h_samp_factor; /* horizontal sampling factor (1..4) */ + int v_samp_factor; /* vertical sampling factor (1..4) */ + int quant_tbl_no; /* quantization table selector (0..3) */ + /* These values may vary between scans. */ + /* For compression, they must be supplied by parameter setup; */ + /* for decompression, they are read from the SOS marker. */ + /* The decompressor output side may not use these variables. */ + int dc_tbl_no; /* DC entropy table selector (0..3) */ + int ac_tbl_no; /* AC entropy table selector (0..3) */ + + /* Remaining fields should be treated as private by applications. */ + + /* These values are computed during compression or decompression startup: */ + /* Component's size in data units. + * Any dummy data units added to complete an MCU are not counted; therefore + * these values do not depend on whether a scan is interleaved or not. + */ + JDIMENSION width_in_data_units; + JDIMENSION height_in_data_units; + /* Size of a data unit in/output by the codec (in samples). Always + * data_unit for compression. For decompression this is the size of the + * output from one data_unit, reflecting any processing performed by the + * codec. For example, in the DCT-based codec, scaling may be applied + * during the IDCT step. Values of 1,2,4,8 are likely to be supported. + * Note that different components may have different codec_data_unit sizes. + */ + int codec_data_unit; + /* The downsampled dimensions are the component's actual, unpadded number + * of samples at the main buffer (preprocessing/compression interface), thus + * downsampled_width = ceil(image_width * Hi/Hmax) + * and similarly for height. For decompression, codec-based processing is + * included (ie, IDCT scaling), so + * downsampled_width = ceil(image_width * Hi/Hmax * codec_data_unit/data_unit) + */ + JDIMENSION downsampled_width; /* actual width in samples */ + JDIMENSION downsampled_height; /* actual height in samples */ + /* This flag is used only for decompression. In cases where some of the + * components will be ignored (eg grayscale output from YCbCr image), + * we can skip most computations for the unused components. + */ + boolean component_needed; /* do we need the value of this component? */ + + /* These values are computed before starting a scan of the component. */ + /* The decompressor output side may not use these variables. */ + int MCU_width; /* number of data units per MCU, horizontally */ + int MCU_height; /* number of data units per MCU, vertically */ + int MCU_data_units; /* MCU_width * MCU_height */ + int MCU_sample_width; /* MCU width in samples, MCU_width*codec_data_unit */ + int last_col_width; /* # of non-dummy data_units across in last MCU */ + int last_row_height; /* # of non-dummy data_units down in last MCU */ + + /* Saved quantization table for component; NULL if none yet saved. + * See jdinput.c comments about the need for this information. + * This field is currently used only for decompression. + */ + JQUANT_TBL * quant_table; + + /* Private per-component storage for DCT or IDCT subsystem. */ + void * dct_table; +} jpeg_component_info; + + +/* The script for encoding a multiple-scan file is an array of these: */ + +typedef struct { + int comps_in_scan; /* number of components encoded in this scan */ + int component_index[MAX_COMPS_IN_SCAN]; /* their SOF/comp_info[] indexes */ + int Ss, Se; /* progressive JPEG spectral selection parms + lossless JPEG predictor select parm (Ss) */ + int Ah, Al; /* progressive JPEG successive approx. parms + lossless JPEG point transform parm (Al) */ +} jpeg_scan_info; + +/* The decompressor can save APPn and COM markers in a list of these: */ + +typedef struct jpeg_marker_struct FAR * jpeg_saved_marker_ptr; + +struct jpeg_marker_struct { + jpeg_saved_marker_ptr next; /* next in list, or NULL */ + UINT8 marker; /* marker code: JPEG_COM, or JPEG_APP0+n */ + unsigned int original_length; /* # bytes of data in the file */ + unsigned int data_length; /* # bytes of data saved at data[] */ + JOCTET FAR * data; /* the data contained in the marker */ + /* the marker length word is not counted in data_length or original_length */ +}; + +/* Known codec processes. */ + +typedef enum { + JPROC_SEQUENTIAL, /* baseline/extended sequential DCT */ + JPROC_PROGRESSIVE, /* progressive DCT */ + JPROC_LOSSLESS /* lossless (sequential) */ +} J_CODEC_PROCESS; + +/* Known color spaces. */ + +typedef enum { + JCS_UNKNOWN, /* error/unspecified */ + JCS_GRAYSCALE, /* monochrome */ + JCS_RGB, /* red/green/blue */ + JCS_YCbCr, /* Y/Cb/Cr (also known as YUV) */ + JCS_CMYK, /* C/M/Y/K */ + JCS_YCCK /* Y/Cb/Cr/K */ +} J_COLOR_SPACE; + +/* DCT/IDCT algorithm options. */ + +typedef enum { + JDCT_ISLOW, /* slow but accurate integer algorithm */ + JDCT_IFAST, /* faster, less accurate integer method */ + JDCT_FLOAT /* floating-point: accurate, fast on fast HW */ +} J_DCT_METHOD; + +#ifndef JDCT_DEFAULT /* may be overridden in jconfig.h */ +#define JDCT_DEFAULT JDCT_ISLOW +#endif +#ifndef JDCT_FASTEST /* may be overridden in jconfig.h */ +#define JDCT_FASTEST JDCT_IFAST +#endif + +/* Dithering options for decompression. */ + +typedef enum { + JDITHER_NONE, /* no dithering */ + JDITHER_ORDERED, /* simple ordered dither */ + JDITHER_FS /* Floyd-Steinberg error diffusion dither */ +} J_DITHER_MODE; + + +/* Common fields between JPEG compression and decompression master structs. */ + +#define jpeg_common_fields \ + struct jpeg_error_mgr * err; /* Error handler module */\ + struct jpeg_memory_mgr * mem; /* Memory manager module */\ + struct jpeg_progress_mgr * progress; /* Progress monitor, or NULL if none */\ + void * client_data; /* Available for use by application */\ + boolean is_decompressor; /* So common code can tell which is which */\ + int global_state /* For checking call sequence validity */ + +/* Routines that are to be used by both halves of the library are declared + * to receive a pointer to this structure. There are no actual instances of + * jpeg_common_struct, only of jpeg_compress_struct and jpeg_decompress_struct. + */ +struct jpeg_common_struct { + jpeg_common_fields; /* Fields common to both master struct types */ + /* Additional fields follow in an actual jpeg_compress_struct or + * jpeg_decompress_struct. All three structs must agree on these + * initial fields! (This would be a lot cleaner in C++.) + */ +}; + +typedef struct jpeg_common_struct * j_common_ptr; +typedef struct jpeg_compress_struct * j_compress_ptr; +typedef struct jpeg_decompress_struct * j_decompress_ptr; + + +/* Master record for a compression instance */ + +struct jpeg_compress_struct { + jpeg_common_fields; /* Fields shared with jpeg_decompress_struct */ + + /* Destination for compressed data */ + struct jpeg_destination_mgr * dest; + + /* Description of source image --- these fields must be filled in by + * outer application before starting compression. in_color_space must + * be correct before you can even call jpeg_set_defaults(). + */ + + JDIMENSION image_width; /* input image width */ + JDIMENSION image_height; /* input image height */ + int input_components; /* # of color components in input image */ + J_COLOR_SPACE in_color_space; /* colorspace of input image */ + + double input_gamma; /* image gamma of input image */ + + /* Compression parameters --- these fields must be set before calling + * jpeg_start_compress(). We recommend calling jpeg_set_defaults() to + * initialize everything to reasonable defaults, then changing anything + * the application specifically wants to change. That way you won't get + * burnt when new parameters are added. Also note that there are several + * helper routines to simplify changing parameters. + */ + + boolean lossless; /* TRUE=lossless encoding, FALSE=lossy */ + + int data_precision; /* bits of precision in image data */ + + int num_components; /* # of color components in JPEG image */ + J_COLOR_SPACE jpeg_color_space; /* colorspace of JPEG image */ + + jpeg_component_info * comp_info; + /* comp_info[i] describes component that appears i'th in SOF */ + + JQUANT_TBL * quant_tbl_ptrs[NUM_QUANT_TBLS]; + /* ptrs to coefficient quantization tables, or NULL if not defined */ + + JHUFF_TBL * dc_huff_tbl_ptrs[NUM_HUFF_TBLS]; + JHUFF_TBL * ac_huff_tbl_ptrs[NUM_HUFF_TBLS]; + /* ptrs to Huffman coding tables, or NULL if not defined */ + + UINT8 arith_dc_L[NUM_ARITH_TBLS]; /* L values for DC arith-coding tables */ + UINT8 arith_dc_U[NUM_ARITH_TBLS]; /* U values for DC arith-coding tables */ + UINT8 arith_ac_K[NUM_ARITH_TBLS]; /* Kx values for AC arith-coding tables */ + + int num_scans; /* # of entries in scan_info array */ + const jpeg_scan_info * scan_info; /* script for multi-scan file, or NULL */ + /* The default value of scan_info is NULL, which causes a single-scan + * sequential JPEG file to be emitted. To create a multi-scan file, + * set num_scans and scan_info to point to an array of scan definitions. + */ + + boolean raw_data_in; /* TRUE=caller supplies downsampled data */ + boolean arith_code; /* TRUE=arithmetic coding, FALSE=Huffman */ + boolean optimize_coding; /* TRUE=optimize entropy encoding parms */ + boolean CCIR601_sampling; /* TRUE=first samples are cosited */ + int smoothing_factor; /* 1..100, or 0 for no input smoothing */ + J_DCT_METHOD dct_method; /* DCT algorithm selector */ + + /* The restart interval can be specified in absolute MCUs by setting + * restart_interval, or in MCU rows by setting restart_in_rows + * (in which case the correct restart_interval will be figured + * for each scan). + */ + unsigned int restart_interval; /* MCUs per restart, or 0 for no restart */ + int restart_in_rows; /* if > 0, MCU rows per restart interval */ + + /* Parameters controlling emission of special markers. */ + + boolean write_JFIF_header; /* should a JFIF marker be written? */ + UINT8 JFIF_major_version; /* What to write for the JFIF version number */ + UINT8 JFIF_minor_version; + /* These three values are not used by the JPEG code, merely copied */ + /* into the JFIF APP0 marker. density_unit can be 0 for unknown, */ + /* 1 for dots/inch, or 2 for dots/cm. Note that the pixel aspect */ + /* ratio is defined by X_density/Y_density even when density_unit=0. */ + UINT8 density_unit; /* JFIF code for pixel size units */ + UINT16 X_density; /* Horizontal pixel density */ + UINT16 Y_density; /* Vertical pixel density */ + boolean write_Adobe_marker; /* should an Adobe marker be written? */ + + /* State variable: index of next scanline to be written to + * jpeg_write_scanlines(). Application may use this to control its + * processing loop, e.g., "while (next_scanline < image_height)". + */ + + JDIMENSION next_scanline; /* 0 .. image_height-1 */ + + /* Remaining fields are known throughout compressor, but generally + * should not be touched by a surrounding application. + */ + + /* + * These fields are computed during compression startup + */ + int data_unit; /* size of data unit in samples */ + J_CODEC_PROCESS process; /* encoding process of JPEG image */ + + int max_h_samp_factor; /* largest h_samp_factor */ + int max_v_samp_factor; /* largest v_samp_factor */ + + JDIMENSION total_iMCU_rows; /* # of iMCU rows to be input to codec */ + /* The codec receives data in units of MCU rows as defined for fully + * interleaved scans (whether the JPEG file is interleaved or not). + * There are v_samp_factor * data_unit sample rows of each component in an + * "iMCU" (interleaved MCU) row. + */ + + /* + * These fields are valid during any one scan. + * They describe the components and MCUs actually appearing in the scan. + */ + int comps_in_scan; /* # of JPEG components in this scan */ + jpeg_component_info * cur_comp_info[MAX_COMPS_IN_SCAN]; + /* *cur_comp_info[i] describes component that appears i'th in SOS */ + + JDIMENSION MCUs_per_row; /* # of MCUs across the image */ + JDIMENSION MCU_rows_in_scan; /* # of MCU rows in the image */ + + int data_units_in_MCU; /* # of data units per MCU */ + int MCU_membership[C_MAX_DATA_UNITS_IN_MCU]; + /* MCU_membership[i] is index in cur_comp_info of component owning */ + /* i'th block in an MCU */ + + int Ss, Se, Ah, Al; /* progressive/lossless JPEG parameters for scan */ + + /* + * Links to compression subobjects (methods and private variables of modules) + */ + struct jpeg_comp_master * master; + struct jpeg_c_main_controller * main; + struct jpeg_c_prep_controller * prep; + struct jpeg_c_codec * codec; + struct jpeg_marker_writer * marker; + struct jpeg_color_converter * cconvert; + struct jpeg_downsampler * downsample; + jpeg_scan_info * script_space; /* workspace for jpeg_simple_progression */ + int script_space_size; +}; + + +/* Master record for a decompression instance */ + +struct jpeg_decompress_struct { + jpeg_common_fields; /* Fields shared with jpeg_compress_struct */ + + /* Source of compressed data */ + struct jpeg_source_mgr * src; + + /* Basic description of image --- filled in by jpeg_read_header(). */ + /* Application may inspect these values to decide how to process image. */ + + JDIMENSION image_width; /* nominal image width (from SOF marker) */ + JDIMENSION image_height; /* nominal image height */ + int num_components; /* # of color components in JPEG image */ + J_COLOR_SPACE jpeg_color_space; /* colorspace of JPEG image */ + + /* Decompression processing parameters --- these fields must be set before + * calling jpeg_start_decompress(). Note that jpeg_read_header() initializes + * them to default values. + */ + + J_COLOR_SPACE out_color_space; /* colorspace for output */ + + unsigned int scale_num, scale_denom; /* fraction by which to scale image */ + + double output_gamma; /* image gamma wanted in output */ + + boolean buffered_image; /* TRUE=multiple output passes */ + boolean raw_data_out; /* TRUE=downsampled data wanted */ + + J_DCT_METHOD dct_method; /* IDCT algorithm selector */ + boolean do_fancy_upsampling; /* TRUE=apply fancy upsampling */ + boolean do_block_smoothing; /* TRUE=apply interblock smoothing */ + + boolean quantize_colors; /* TRUE=colormapped output wanted */ + /* the following are ignored if not quantize_colors: */ + J_DITHER_MODE dither_mode; /* type of color dithering to use */ + boolean two_pass_quantize; /* TRUE=use two-pass color quantization */ + int desired_number_of_colors; /* max # colors to use in created colormap */ + /* these are significant only in buffered-image mode: */ + boolean enable_1pass_quant; /* enable future use of 1-pass quantizer */ + boolean enable_external_quant;/* enable future use of external colormap */ + boolean enable_2pass_quant; /* enable future use of 2-pass quantizer */ + + /* Description of actual output image that will be returned to application. + * These fields are computed by jpeg_start_decompress(). + * You can also use jpeg_calc_output_dimensions() to determine these values + * in advance of calling jpeg_start_decompress(). + */ + + JDIMENSION output_width; /* scaled image width */ + JDIMENSION output_height; /* scaled image height */ + int out_color_components; /* # of color components in out_color_space */ + int output_components; /* # of color components returned */ + /* output_components is 1 (a colormap index) when quantizing colors; + * otherwise it equals out_color_components. + */ + int rec_outbuf_height; /* min recommended height of scanline buffer */ + /* If the buffer passed to jpeg_read_scanlines() is less than this many rows + * high, space and time will be wasted due to unnecessary data copying. + * Usually rec_outbuf_height will be 1 or 2, at most 4. + */ + + /* When quantizing colors, the output colormap is described by these fields. + * The application can supply a colormap by setting colormap non-NULL before + * calling jpeg_start_decompress; otherwise a colormap is created during + * jpeg_start_decompress or jpeg_start_output. + * The map has out_color_components rows and actual_number_of_colors columns. + */ + int actual_number_of_colors; /* number of entries in use */ + JSAMPARRAY colormap; /* The color map as a 2-D pixel array */ + + /* State variables: these variables indicate the progress of decompression. + * The application may examine these but must not modify them. + */ + + /* Row index of next scanline to be read from jpeg_read_scanlines(). + * Application may use this to control its processing loop, e.g., + * "while (output_scanline < output_height)". + */ + JDIMENSION output_scanline; /* 0 .. output_height-1 */ + + /* Current input scan number and number of iMCU rows completed in scan. + * These indicate the progress of the decompressor input side. + */ + int input_scan_number; /* Number of SOS markers seen so far */ + JDIMENSION input_iMCU_row; /* Number of iMCU rows completed */ + + /* The "output scan number" is the notional scan being displayed by the + * output side. The decompressor will not allow output scan/row number + * to get ahead of input scan/row, but it can fall arbitrarily far behind. + */ + int output_scan_number; /* Nominal scan number being displayed */ + JDIMENSION output_iMCU_row; /* Number of iMCU rows read */ + + /* Current progression status. coef_bits[c][i] indicates the precision + * with which component c's DCT coefficient i (in zigzag order) is known. + * It is -1 when no data has yet been received, otherwise it is the point + * transform (shift) value for the most recent scan of the coefficient + * (thus, 0 at completion of the progression). + * This pointer is NULL when reading a non-progressive file. + */ + int (*coef_bits)[DCTSIZE2]; /* -1 or current Al value for each coef */ + + /* Internal JPEG parameters --- the application usually need not look at + * these fields. Note that the decompressor output side may not use + * any parameters that can change between scans. + */ + + /* Quantization and Huffman tables are carried forward across input + * datastreams when processing abbreviated JPEG datastreams. + */ + + JQUANT_TBL * quant_tbl_ptrs[NUM_QUANT_TBLS]; + /* ptrs to coefficient quantization tables, or NULL if not defined */ + + JHUFF_TBL * dc_huff_tbl_ptrs[NUM_HUFF_TBLS]; + JHUFF_TBL * ac_huff_tbl_ptrs[NUM_HUFF_TBLS]; + /* ptrs to Huffman coding tables, or NULL if not defined */ + + /* These parameters are never carried across datastreams, since they + * are given in SOF/SOS markers or defined to be reset by SOI. + */ + + int data_precision; /* bits of precision in image data */ + + jpeg_component_info * comp_info; + /* comp_info[i] describes component that appears i'th in SOF */ + + boolean arith_code; /* TRUE=arithmetic coding, FALSE=Huffman */ + + UINT8 arith_dc_L[NUM_ARITH_TBLS]; /* L values for DC arith-coding tables */ + UINT8 arith_dc_U[NUM_ARITH_TBLS]; /* U values for DC arith-coding tables */ + UINT8 arith_ac_K[NUM_ARITH_TBLS]; /* Kx values for AC arith-coding tables */ + + unsigned int restart_interval; /* MCUs per restart interval, or 0 for no restart */ + + /* These fields record data obtained from optional markers recognized by + * the JPEG library. + */ + boolean saw_JFIF_marker; /* TRUE iff a JFIF APP0 marker was found */ + /* Data copied from JFIF marker; only valid if saw_JFIF_marker is TRUE: */ + UINT8 JFIF_major_version; /* JFIF version number */ + UINT8 JFIF_minor_version; + UINT8 density_unit; /* JFIF code for pixel size units */ + UINT16 X_density; /* Horizontal pixel density */ + UINT16 Y_density; /* Vertical pixel density */ + boolean saw_Adobe_marker; /* TRUE iff an Adobe APP14 marker was found */ + UINT8 Adobe_transform; /* Color transform code from Adobe marker */ + + boolean CCIR601_sampling; /* TRUE=first samples are cosited */ + + /* Aside from the specific data retained from APPn markers known to the + * library, the uninterpreted contents of any or all APPn and COM markers + * can be saved in a list for examination by the application. + */ + jpeg_saved_marker_ptr marker_list; /* Head of list of saved markers */ + + /* Remaining fields are known throughout decompressor, but generally + * should not be touched by a surrounding application. + */ + + /* + * These fields are computed during decompression startup + */ + int data_unit; /* size of data unit in samples */ + J_CODEC_PROCESS process; /* decoding process of JPEG image */ + + int max_h_samp_factor; /* largest h_samp_factor */ + int max_v_samp_factor; /* largest v_samp_factor */ + + int min_codec_data_unit; /* smallest codec_data_unit of any component */ + + JDIMENSION total_iMCU_rows; /* # of iMCU rows in image */ + /* The codec's input and output progress is measured in units of "iMCU" + * (interleaved MCU) rows. These are the same as MCU rows in fully + * interleaved JPEG scans, but are used whether the scan is interleaved + * or not. We define an iMCU row as v_samp_factor data_unit rows of each + * component. Therefore, the codec output contains + * v_samp_factor*codec_data_unit sample rows of a component per iMCU row. + */ + + JSAMPLE * sample_range_limit; /* table for fast range-limiting */ + + /* + * These fields are valid during any one scan. + * They describe the components and MCUs actually appearing in the scan. + * Note that the decompressor output side must not use these fields. + */ + int comps_in_scan; /* # of JPEG components in this scan */ + jpeg_component_info * cur_comp_info[MAX_COMPS_IN_SCAN]; + /* *cur_comp_info[i] describes component that appears i'th in SOS */ + + JDIMENSION MCUs_per_row; /* # of MCUs across the image */ + JDIMENSION MCU_rows_in_scan; /* # of MCU rows in the image */ + + int data_units_in_MCU; /* # of data _units per MCU */ + int MCU_membership[D_MAX_DATA_UNITS_IN_MCU]; + /* MCU_membership[i] is index in cur_comp_info of component owning */ + /* i'th data unit in an MCU */ + + int Ss, Se, Ah, Al; /* progressive/lossless JPEG parms for scan */ + + /* This field is shared between entropy decoder and marker parser. + * It is either zero or the code of a JPEG marker that has been + * read from the data source, but has not yet been processed. + */ + int unread_marker; + + /* + * Links to decompression subobjects (methods, private variables of modules) + */ + struct jpeg_decomp_master * master; + struct jpeg_d_main_controller * main; + struct jpeg_d_codec * codec; + struct jpeg_d_post_controller * post; + struct jpeg_input_controller * inputctl; + struct jpeg_marker_reader * marker; + struct jpeg_upsampler * upsample; + struct jpeg_color_deconverter * cconvert; + struct jpeg_color_quantizer * cquantize; +}; + + +/* "Object" declarations for JPEG modules that may be supplied or called + * directly by the surrounding application. + * As with all objects in the JPEG library, these structs only define the + * publicly visible methods and state variables of a module. Additional + * private fields may exist after the public ones. + */ + + +/* Error handler object */ + +struct jpeg_error_mgr { + /* Error exit handler: does not return to caller */ + JMETHOD(void, error_exit, (j_common_ptr cinfo)); + /* Conditionally emit a trace or warning message */ + JMETHOD(void, emit_message, (j_common_ptr cinfo, int msg_level)); + /* Routine that actually outputs a trace or error message */ + JMETHOD(void, output_message, (j_common_ptr cinfo)); + /* Format a message string for the most recent JPEG error or message */ + JMETHOD(void, format_message, (j_common_ptr cinfo, char * buffer)); +#define JMSG_LENGTH_MAX 200 /* recommended size of format_message buffer */ + /* Reset error state variables at start of a new image */ + JMETHOD(void, reset_error_mgr, (j_common_ptr cinfo)); + + /* The message ID code and any parameters are saved here. + * A message can have one string parameter or up to 8 int parameters. + */ + int msg_code; +#define JMSG_STR_PARM_MAX 80 + union { + int i[8]; + char s[JMSG_STR_PARM_MAX]; + } msg_parm; + + /* Standard state variables for error facility */ + + int trace_level; /* max msg_level that will be displayed */ + + /* For recoverable corrupt-data errors, we emit a warning message, + * but keep going unless emit_message chooses to abort. emit_message + * should count warnings in num_warnings. The surrounding application + * can check for bad data by seeing if num_warnings is nonzero at the + * end of processing. + */ + long num_warnings; /* number of corrupt-data warnings */ + + /* These fields point to the table(s) of error message strings. + * An application can change the table pointer to switch to a different + * message list (typically, to change the language in which errors are + * reported). Some applications may wish to add additional error codes + * that will be handled by the JPEG library error mechanism; the second + * table pointer is used for this purpose. + * + * First table includes all errors generated by JPEG library itself. + * Error code 0 is reserved for a "no such error string" message. + */ + const char * const * jpeg_message_table; /* Library errors */ + int last_jpeg_message; /* Table contains strings 0..last_jpeg_message */ + /* Second table can be added by application (see cjpeg/djpeg for example). + * It contains strings numbered first_addon_message..last_addon_message. + */ + const char * const * addon_message_table; /* Non-library errors */ + int first_addon_message; /* code for first string in addon table */ + int last_addon_message; /* code for last string in addon table */ +}; + + +/* Progress monitor object */ + +struct jpeg_progress_mgr { + JMETHOD(void, progress_monitor, (j_common_ptr cinfo)); + + long pass_counter; /* work units completed in this pass */ + long pass_limit; /* total number of work units in this pass */ + int completed_passes; /* passes completed so far */ + int total_passes; /* total number of passes expected */ +}; + + +/* Data destination object for compression */ + +struct jpeg_destination_mgr { + JOCTET * next_output_byte; /* => next byte to write in buffer */ + size_t free_in_buffer; /* # of byte spaces remaining in buffer */ + + JMETHOD(void, init_destination, (j_compress_ptr cinfo)); + JMETHOD(boolean, empty_output_buffer, (j_compress_ptr cinfo)); + JMETHOD(void, term_destination, (j_compress_ptr cinfo)); +}; + + +/* Data source object for decompression */ + +struct jpeg_source_mgr { + const JOCTET * next_input_byte; /* => next byte to read from buffer */ + size_t bytes_in_buffer; /* # of bytes remaining in buffer */ + + JMETHOD(void, init_source, (j_decompress_ptr cinfo)); + JMETHOD(boolean, fill_input_buffer, (j_decompress_ptr cinfo)); + JMETHOD(void, skip_input_data, (j_decompress_ptr cinfo, long num_bytes)); + JMETHOD(boolean, resync_to_restart, (j_decompress_ptr cinfo, int desired)); + JMETHOD(void, term_source, (j_decompress_ptr cinfo)); +}; + + +/* Memory manager object. + * Allocates "small" objects (a few K total), "large" objects (tens of K), + * and "really big" objects (virtual arrays with backing store if needed). + * The memory manager does not allow individual objects to be freed; rather, + * each created object is assigned to a pool, and whole pools can be freed + * at once. This is faster and more convenient than remembering exactly what + * to free, especially where malloc()/free() are not too speedy. + * NB: alloc routines never return NULL. They exit to error_exit if not + * successful. + */ + +#define JPOOL_PERMANENT 0 /* lasts until master record is destroyed */ +#define JPOOL_IMAGE 1 /* lasts until done with image/datastream */ +#define JPOOL_NUMPOOLS 2 + +typedef struct jvirt_sarray_control * jvirt_sarray_ptr; +typedef struct jvirt_barray_control * jvirt_barray_ptr; + + +#ifdef C_LOSSLESS_SUPPORTED +#define NEED_DARRAY +#else +#ifdef D_LOSSLESS_SUPPORTED +#define NEED_DARRAY +#endif +#endif + +struct jpeg_memory_mgr { + /* Method pointers */ + JMETHOD(void *, alloc_small, (j_common_ptr cinfo, int pool_id, + size_t sizeofobject)); + JMETHOD(void FAR *, alloc_large, (j_common_ptr cinfo, int pool_id, + size_t sizeofobject)); + JMETHOD(JSAMPARRAY, alloc_sarray, (j_common_ptr cinfo, int pool_id, + JDIMENSION samplesperrow, + JDIMENSION numrows)); + JMETHOD(JBLOCKARRAY, alloc_barray, (j_common_ptr cinfo, int pool_id, + JDIMENSION blocksperrow, + JDIMENSION numrows)); +#ifdef NEED_DARRAY + JMETHOD(JDIFFARRAY, alloc_darray, (j_common_ptr cinfo, int pool_id, + JDIMENSION diffsperrow, + JDIMENSION numrows)); +#endif + JMETHOD(jvirt_sarray_ptr, request_virt_sarray, (j_common_ptr cinfo, + int pool_id, + boolean pre_zero, + JDIMENSION samplesperrow, + JDIMENSION numrows, + JDIMENSION maxaccess)); + JMETHOD(jvirt_barray_ptr, request_virt_barray, (j_common_ptr cinfo, + int pool_id, + boolean pre_zero, + JDIMENSION blocksperrow, + JDIMENSION numrows, + JDIMENSION maxaccess)); + JMETHOD(void, realize_virt_arrays, (j_common_ptr cinfo)); + JMETHOD(JSAMPARRAY, access_virt_sarray, (j_common_ptr cinfo, + jvirt_sarray_ptr ptr, + JDIMENSION start_row, + JDIMENSION num_rows, + boolean writable)); + JMETHOD(JBLOCKARRAY, access_virt_barray, (j_common_ptr cinfo, + jvirt_barray_ptr ptr, + JDIMENSION start_row, + JDIMENSION num_rows, + boolean writable)); + JMETHOD(void, free_pool, (j_common_ptr cinfo, int pool_id)); + JMETHOD(void, self_destruct, (j_common_ptr cinfo)); + + /* Limit on memory allocation for this JPEG object. (Note that this is + * merely advisory, not a guaranteed maximum; it only affects the space + * used for virtual-array buffers.) May be changed by outer application + * after creating the JPEG object. + */ + long max_memory_to_use; + + /* Maximum allocation request accepted by alloc_large. */ + long max_alloc_chunk; +}; + + +/* Routine signature for application-supplied marker processing methods. + * Need not pass marker code since it is stored in cinfo->unread_marker. + */ +typedef JMETHOD(boolean, jpeg_marker_parser_method, (j_decompress_ptr cinfo)); + + +/* Declarations for routines called by application. + * The JPP macro hides prototype parameters from compilers that can't cope. + * Note JPP requires double parentheses. + */ + +#ifdef HAVE_PROTOTYPES +#define JPP(arglist) arglist +#else +#define JPP(arglist) () +#endif + + +/* Short forms of external names for systems with brain-damaged linkers. + * We shorten external names to be unique in the first six letters, which + * is good enough for all known systems. + * (If your compiler itself needs names to be unique in less than 15 + * characters, you are out of luck. Get a better compiler.) + */ + +/* MAKE SURE THAT ALL FUNCTIONS DECLARED GLOBAL() ARE RE-DEFINED HERE! */ + +#ifdef NEED_SHORT_EXTERNAL_NAMES +#define jcopy_block_row jcopy12_block_row +#define jcopy_sample_rows jcopy12_sample_rows +#define jdiv_round_up jdiv12_round_up +#define jinit_1pass_quantizer jinit12_1pass_quantizer +#define jinit_2pass_quantizer jinit12_2pass_quantizer +#define jinit_arith_decoder jinit12_arith_decoder +#define jinit_arith_encoder jinit12_arith_encoder +#define jinit_c_codec jinit12_c_codec +#define jinit_c_coef_controller jinit12_c_coef_controller +#define jinit_c_diff_controller jinit12_c_diff_controller +#define jinit_c_main_controller jinit12_c_main_controller +#define jinit_c_master_control jinit12_c_master_control +#define jinit_c_prep_controller jinit12_c_prep_controller +#define jinit_c_scaler jinit12_c_scaler +#define jinit_color_converter jinit12_color_converter +#define jinit_color_deconverter jinit12_color_deconverter +#define jinit_compress_master jinit12_compress_master +#define jinit_d_codec jinit12_d_codec +#define jinit_d_coef_controller jinit12_d_coef_controller +#define jinit_d_diff_controller jinit12_d_diff_controller +#define jinit_d_main_controller jinit12_d_main_controller +#define jinit_d_post_controller jinit12_d_post_controller +#define jinit_d_post_controller jinit12_d_post_controller +#define jinit_d_scaler jinit12_d_scaler +#define jinit_differencer jinit12_differencer +#define jinit_downsampler jinit12_downsampler +#define jinit_forward_dct jinit12_forward_dct +#define jinit_input_controller jinit12_input_controller +#define jinit_inverse_dct jinit12_inverse_dct +#define jinit_lhuff_decoder jinit12_lhuff_decoder +#define jinit_lhuff_encoder jinit12_lhuff_encoder +#define jinit_lossless_c_codec jinit12_lossless_c_codec +#define jinit_lossless_d_codec jinit12_lossless_d_codec +#define jinit_lossy_c_codec jinit12_lossy_c_codec +#define jinit_lossy_d_codec jinit12_lossy_d_codec +#define jinit_marker_reader jinit12_marker_reader +#define jinit_marker_writer jinit12_marker_writer +#define jinit_master_decompress jinit12_master_decompress +#define jinit_memory_mgr jinit12_memory_mgr +#define jinit_merged_upsampler jinit12_merged_upsampler +#define jinit_phuff_decoder jinit12_phuff_decoder +#define jinit_phuff_encoder jinit12_phuff_encoder +#define jinit_shuff_decoder jinit12_shuff_decoder +#define jinit_shuff_encoder jinit12_shuff_encoder +#define jinit_undifferencer jinit12_undifferencer +#define jinit_upsampler jinit12_upsampler +#define jpeg_CreateCompress jpeg12_CreateCompress +#define jpeg_CreateDecompress jpeg12_CreateDecompress +#define jpeg_abort jpeg12_abort +#define jpeg_abort_compress jpeg12_abort_compress +#define jpeg_abort_decompress jpeg12_abort_decompress +#define jpeg_add_quant_table jpeg12_add_quant_table +#define jpeg_alloc_huff_table jpeg12_alloc_huff_table +#define jpeg_alloc_quant_table jpeg12_alloc_quant_table +#define jpeg_calc_output_dimensions jpeg12_calc_output_dimensions +#define jpeg_consume_input jpeg12_consume_input +#define jpeg_copy_critical_parameters jpeg12_copy_critical_parameters +#define jpeg_default_colorspace jpeg12_default_colorspace +#define jpeg_destroy jpeg12_destroy +#define jpeg_destroy_compress jpeg12_destroy_compress +#define jpeg_destroy_decompress jpeg12_destroy_decompress +#define jpeg_fdct_float jpeg12_fdct_float +#define jpeg_fdct_ifast jpeg12_fdct_ifast +#define jpeg_fdct_islow jpeg12_fdct_islow +#define jpeg_fill_bit_buffer jpeg12_fill_bit_buffer +#define jpeg_finish_compress jpeg12_finish_compress +#define jpeg_finish_decompress jpeg12_finish_decompress +#define jpeg_finish_output jpeg12_finish_output +#define jpeg_free_large jpeg12_free_large +#define jpeg_free_small jpeg12_free_small +#define jpeg_gen_optimal_table jpeg12_gen_optimal_table +#define jpeg_get_large jpeg12_get_large +#define jpeg_get_small jpeg12_get_small +#define jpeg_has_multiple_scans jpeg12_has_multiple_scans +#define jpeg_huff_decode jpeg12_huff_decode +#define jpeg_idct_1x1 jpeg12_idct_1x1 +#define jpeg_idct_2x2 jpeg12_idct_2x2 +#define jpeg_idct_4x4 jpeg12_idct_4x4 +#define jpeg_idct_float jpeg12_idct_float +#define jpeg_idct_ifast jpeg12_idct_ifast +#define jpeg_idct_islow jpeg12_idct_islow +#define jpeg_input_complete jpeg12_input_complete +#define jpeg_make_c_derived_tbl jpeg12_make_c_derived_tbl +#define jpeg_make_d_derived_tbl jpeg12_make_d_derived_tbl +#define jpeg_mem_available jpeg12_mem_available +#define jpeg_mem_init jpeg12_mem_init +#define jpeg_mem_term jpeg12_mem_term +#define jpeg_new_colormap jpeg12_new_colormap +#define jpeg_open_backing_store jpeg12_open_backing_store +#define jpeg_quality_scaling jpeg12_quality_scaling +#define jpeg_read_coefficients jpeg12_read_coefficients +#define jpeg_read_header jpeg12_read_header +#define jpeg_read_raw_data jpeg12_read_raw_data +#define jpeg_read_scanlines jpeg12_read_scanlines +#define jpeg_resync_to_restart jpeg12_resync_to_restart +#define jpeg_save_markers jpeg12_save_markers +#define jpeg_set_colorspace jpeg12_set_colorspace +#define jpeg_set_defaults jpeg12_set_defaults +#define jpeg_set_linear_quality jpeg12_set_linear_quality +#define jpeg_set_marker_processor jpeg12_set_marker_processor +#define jpeg_set_quality jpeg12_set_quality +#define jpeg_simple_lossless jpeg12_simple_lossless +#define jpeg_simple_progression jpeg12_simple_progression +#define jpeg_start_compress jpeg12_start_compress +#define jpeg_start_decompress jpeg12_start_decompress +#define jpeg_start_output jpeg12_start_output +#define jpeg_std_error jpeg12_std_error +#define jpeg_stdio_dest jpeg12_stdio_dest +#define jpeg_stdio_src jpeg12_stdio_src +#define jpeg_suppress_tables jpeg12_suppress_tables +#define jpeg_write_coefficients jpeg12_write_coefficients +#define jpeg_write_m_byte jpeg12_write_m_byte +#define jpeg_write_m_header jpeg12_write_m_header +#define jpeg_write_marker jpeg12_write_marker +#define jpeg_write_raw_data jpeg12_write_raw_data +#define jpeg_write_scanlines jpeg12_write_scanlines +#define jpeg_write_tables jpeg12_write_tables +#define jround_up jround12_up +#define jzero_far jzero12_far +#endif /* NEED_SHORT_EXTERNAL_NAMES */ + + +/* Default error-management setup */ +EXTERN(struct jpeg_error_mgr *) jpeg_std_error + JPP((struct jpeg_error_mgr * err)); + +/* Initialization of JPEG compression objects. + * jpeg_create_compress() and jpeg_create_decompress() are the exported + * names that applications should call. These expand to calls on + * jpeg_CreateCompress and jpeg_CreateDecompress with additional information + * passed for version mismatch checking. + * NB: you must set up the error-manager BEFORE calling jpeg_create_xxx. + */ +#define jpeg_create_compress(cinfo) \ + jpeg_CreateCompress((cinfo), JPEG_LIB_VERSION, \ + (size_t) sizeof(struct jpeg_compress_struct)) +#define jpeg_create_decompress(cinfo) \ + jpeg_CreateDecompress((cinfo), JPEG_LIB_VERSION, \ + (size_t) sizeof(struct jpeg_decompress_struct)) +EXTERN(void) jpeg_CreateCompress JPP((j_compress_ptr cinfo, + int version, size_t structsize)); +EXTERN(void) jpeg_CreateDecompress JPP((j_decompress_ptr cinfo, + int version, size_t structsize)); +/* Destruction of JPEG compression objects */ +EXTERN(void) jpeg_destroy_compress JPP((j_compress_ptr cinfo)); +EXTERN(void) jpeg_destroy_decompress JPP((j_decompress_ptr cinfo)); + +/* Standard data source and destination managers: stdio streams. */ +/* Caller is responsible for opening the file before and closing after. */ +EXTERN(void) jpeg_stdio_dest JPP((j_compress_ptr cinfo, FILE * outfile)); +EXTERN(void) jpeg_stdio_src JPP((j_decompress_ptr cinfo, FILE * infile)); + +/* Default parameter setup for compression */ +EXTERN(void) jpeg_set_defaults JPP((j_compress_ptr cinfo)); +/* Compression parameter setup aids */ +EXTERN(void) jpeg_set_colorspace JPP((j_compress_ptr cinfo, + J_COLOR_SPACE colorspace)); +EXTERN(void) jpeg_default_colorspace JPP((j_compress_ptr cinfo)); +EXTERN(void) jpeg_set_quality JPP((j_compress_ptr cinfo, int quality, + boolean force_baseline)); +EXTERN(void) jpeg_set_linear_quality JPP((j_compress_ptr cinfo, + int scale_factor, + boolean force_baseline)); +EXTERN(void) jpeg_add_quant_table JPP((j_compress_ptr cinfo, int which_tbl, + const unsigned int *basic_table, + int scale_factor, + boolean force_baseline)); +EXTERN(int) jpeg_quality_scaling JPP((int quality)); +EXTERN(void) jpeg_simple_lossless JPP((j_compress_ptr cinfo, + int predictor, int point_transform)); +EXTERN(void) jpeg_simple_progression JPP((j_compress_ptr cinfo)); +EXTERN(void) jpeg_suppress_tables JPP((j_compress_ptr cinfo, + boolean suppress)); +EXTERN(JQUANT_TBL *) jpeg_alloc_quant_table JPP((j_common_ptr cinfo)); +EXTERN(JHUFF_TBL *) jpeg_alloc_huff_table JPP((j_common_ptr cinfo)); + +/* Main entry points for compression */ +EXTERN(void) jpeg_start_compress JPP((j_compress_ptr cinfo, + boolean write_all_tables)); +EXTERN(JDIMENSION) jpeg_write_scanlines JPP((j_compress_ptr cinfo, + JSAMPARRAY scanlines, + JDIMENSION num_lines)); +EXTERN(void) jpeg_finish_compress JPP((j_compress_ptr cinfo)); + +/* Replaces jpeg_write_scanlines when writing raw downsampled data. */ +EXTERN(JDIMENSION) jpeg_write_raw_data JPP((j_compress_ptr cinfo, + JSAMPIMAGE data, + JDIMENSION num_lines)); + +/* Write a special marker. See libjpeg.doc concerning safe usage. */ +EXTERN(void) jpeg_write_marker + JPP((j_compress_ptr cinfo, int marker, + const JOCTET * dataptr, unsigned int datalen)); +/* Same, but piecemeal. */ +EXTERN(void) jpeg_write_m_header + JPP((j_compress_ptr cinfo, int marker, unsigned int datalen)); +EXTERN(void) jpeg_write_m_byte + JPP((j_compress_ptr cinfo, int val)); + +/* Alternate compression function: just write an abbreviated table file */ +EXTERN(void) jpeg_write_tables JPP((j_compress_ptr cinfo)); + +/* Decompression startup: read start of JPEG datastream to see what's there */ +EXTERN(int) jpeg_read_header JPP((j_decompress_ptr cinfo, + boolean require_image)); +/* Return value is one of: */ +#define JPEG_SUSPENDED 0 /* Suspended due to lack of input data */ +#define JPEG_HEADER_OK 1 /* Found valid image datastream */ +#define JPEG_HEADER_TABLES_ONLY 2 /* Found valid table-specs-only datastream */ +/* If you pass require_image = TRUE (normal case), you need not check for + * a TABLES_ONLY return code; an abbreviated file will cause an error exit. + * JPEG_SUSPENDED is only possible if you use a data source module that can + * give a suspension return (the stdio source module doesn't). + */ + +/* Main entry points for decompression */ +EXTERN(boolean) jpeg_start_decompress JPP((j_decompress_ptr cinfo)); +EXTERN(JDIMENSION) jpeg_read_scanlines JPP((j_decompress_ptr cinfo, + JSAMPARRAY scanlines, + JDIMENSION max_lines)); +EXTERN(boolean) jpeg_finish_decompress JPP((j_decompress_ptr cinfo)); + +/* Replaces jpeg_read_scanlines when reading raw downsampled data. */ +EXTERN(JDIMENSION) jpeg_read_raw_data JPP((j_decompress_ptr cinfo, + JSAMPIMAGE data, + JDIMENSION max_lines)); + +/* Additional entry points for buffered-image mode. */ +EXTERN(boolean) jpeg_has_multiple_scans JPP((j_decompress_ptr cinfo)); +EXTERN(boolean) jpeg_start_output JPP((j_decompress_ptr cinfo, + int scan_number)); +EXTERN(boolean) jpeg_finish_output JPP((j_decompress_ptr cinfo)); +EXTERN(boolean) jpeg_input_complete JPP((j_decompress_ptr cinfo)); +EXTERN(void) jpeg_new_colormap JPP((j_decompress_ptr cinfo)); +EXTERN(int) jpeg_consume_input JPP((j_decompress_ptr cinfo)); +/* Return value is one of: */ +/* #define JPEG_SUSPENDED 0 Suspended due to lack of input data */ +#define JPEG_REACHED_SOS 1 /* Reached start of new scan */ +#define JPEG_REACHED_EOI 2 /* Reached end of image */ +#define JPEG_ROW_COMPLETED 3 /* Completed one iMCU row */ +#define JPEG_SCAN_COMPLETED 4 /* Completed last iMCU row of a scan */ + +/* Precalculate output dimensions for current decompression parameters. */ +EXTERN(void) jpeg_calc_output_dimensions JPP((j_decompress_ptr cinfo)); + +/* Control saving of COM and APPn markers into marker_list. */ +EXTERN(void) jpeg_save_markers + JPP((j_decompress_ptr cinfo, int marker_code, + unsigned int length_limit)); + +/* Install a special processing method for COM or APPn markers. */ +EXTERN(void) jpeg_set_marker_processor + JPP((j_decompress_ptr cinfo, int marker_code, + jpeg_marker_parser_method routine)); + +/* Read or write raw DCT coefficients --- useful for lossless transcoding. */ +EXTERN(jvirt_barray_ptr *) jpeg_read_coefficients JPP((j_decompress_ptr cinfo)); +EXTERN(void) jpeg_write_coefficients JPP((j_compress_ptr cinfo, + jvirt_barray_ptr * coef_arrays)); +EXTERN(void) jpeg_copy_critical_parameters JPP((j_decompress_ptr srcinfo, + j_compress_ptr dstinfo)); + +/* If you choose to abort compression or decompression before completing + * jpeg_finish_(de)compress, then you need to clean up to release memory, + * temporary files, etc. You can just call jpeg_destroy_(de)compress + * if you're done with the JPEG object, but if you want to clean it up and + * reuse it, call this: + */ +EXTERN(void) jpeg_abort_compress JPP((j_compress_ptr cinfo)); +EXTERN(void) jpeg_abort_decompress JPP((j_decompress_ptr cinfo)); + +/* Generic versions of jpeg_abort and jpeg_destroy that work on either + * flavor of JPEG object. These may be more convenient in some places. + */ +EXTERN(void) jpeg_abort JPP((j_common_ptr cinfo)); +EXTERN(void) jpeg_destroy JPP((j_common_ptr cinfo)); + +/* Default restart-marker-resync procedure for use by data source modules */ +EXTERN(boolean) jpeg_resync_to_restart JPP((j_decompress_ptr cinfo, + int desired)); + + +/* These marker codes are exported since applications and data source modules + * are likely to want to use them. + */ + +#define JPEG_RST0 0xD0 /* RST0 marker code */ +#define JPEG_EOI 0xD9 /* EOI marker code */ +#define JPEG_APP0 0xE0 /* APP0 marker code */ +#define JPEG_COM 0xFE /* COM marker code */ + + +/* If we have a brain-damaged compiler that emits warnings (or worse, errors) + * for structure definitions that are never filled in, keep it quiet by + * supplying dummy definitions for the various substructures. + */ + +#ifdef INCOMPLETE_TYPES_BROKEN +#ifndef JPEG_INTERNALS /* will be defined in jpegint.h */ +struct jvirt_sarray_control { long dummy; }; +struct jvirt_barray_control { long dummy; }; +struct jpeg_comp_master { long dummy; }; +struct jpeg_c_main_controller { long dummy; }; +struct jpeg_c_prep_controller { long dummy; }; +struct jpeg_c_coef_controller { long dummy; }; +struct jpeg_marker_writer { long dummy; }; +struct jpeg_color_converter { long dummy; }; +struct jpeg_downsampler { long dummy; }; +struct jpeg_forward_dct { long dummy; }; +struct jpeg_entropy_encoder { long dummy; }; +struct jpeg_decomp_master { long dummy; }; +struct jpeg_d_main_controller { long dummy; }; +struct jpeg_d_coef_controller { long dummy; }; +struct jpeg_d_post_controller { long dummy; }; +struct jpeg_input_controller { long dummy; }; +struct jpeg_marker_reader { long dummy; }; +struct jpeg_entropy_decoder { long dummy; }; +struct jpeg_inverse_dct { long dummy; }; +struct jpeg_upsampler { long dummy; }; +struct jpeg_color_deconverter { long dummy; }; +struct jpeg_color_quantizer { long dummy; }; +#endif /* JPEG_INTERNALS */ +#endif /* INCOMPLETE_TYPES_BROKEN */ + + +/* + * The JPEG library modules define JPEG_INTERNALS before including this file. + * The internal structure declarations are read only when that is true. + * Applications using the library should not include jpegint.h, but may wish + * to include jerror.h. + */ + +#ifdef JPEG_INTERNALS +#include "jpegint12.h" /* fetch private declarations */ +#include "jerror12.h" /* fetch error codes too */ +#endif + +#endif /* JPEGLIB_H */ diff --git a/dcmjpeg/libijg12/jquant1.c b/dcmjpeg/libijg12/jquant1.c new file mode 100644 index 00000000..e3433473 --- /dev/null +++ b/dcmjpeg/libijg12/jquant1.c @@ -0,0 +1,856 @@ +/* + * jquant1.c + * + * Copyright (C) 1991-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains 1-pass color quantization (color mapping) routines. + * These routines provide mapping to a fixed color map using equally spaced + * color values. Optional Floyd-Steinberg or ordered dithering is available. + */ + +#define JPEG_INTERNALS +#include "jinclude12.h" +#include "jpeglib12.h" + +#ifdef QUANT_1PASS_SUPPORTED + + +/* + * The main purpose of 1-pass quantization is to provide a fast, if not very + * high quality, colormapped output capability. A 2-pass quantizer usually + * gives better visual quality; however, for quantized grayscale output this + * quantizer is perfectly adequate. Dithering is highly recommended with this + * quantizer, though you can turn it off if you really want to. + * + * In 1-pass quantization the colormap must be chosen in advance of seeing the + * image. We use a map consisting of all combinations of Ncolors[i] color + * values for the i'th component. The Ncolors[] values are chosen so that + * their product, the total number of colors, is no more than that requested. + * (In most cases, the product will be somewhat less.) + * + * Since the colormap is orthogonal, the representative value for each color + * component can be determined without considering the other components; + * then these indexes can be combined into a colormap index by a standard + * N-dimensional-array-subscript calculation. Most of the arithmetic involved + * can be precalculated and stored in the lookup table colorindex[]. + * colorindex[i][j] maps pixel value j in component i to the nearest + * representative value (grid plane) for that component; this index is + * multiplied by the array stride for component i, so that the + * index of the colormap entry closest to a given pixel value is just + * sum( colorindex[component-number][pixel-component-value] ) + * Aside from being fast, this scheme allows for variable spacing between + * representative values with no additional lookup cost. + * + * If gamma correction has been applied in color conversion, it might be wise + * to adjust the color grid spacing so that the representative colors are + * equidistant in linear space. At this writing, gamma correction is not + * implemented by jdcolor, so nothing is done here. + */ + + +/* Declarations for ordered dithering. + * + * We use a standard 16x16 ordered dither array. The basic concept of ordered + * dithering is described in many references, for instance Dale Schumacher's + * chapter II.2 of Graphics Gems II (James Arvo, ed. Academic Press, 1991). + * In place of Schumacher's comparisons against a "threshold" value, we add a + * "dither" value to the input pixel and then round the result to the nearest + * output value. The dither value is equivalent to (0.5 - threshold) times + * the distance between output values. For ordered dithering, we assume that + * the output colors are equally spaced; if not, results will probably be + * worse, since the dither may be too much or too little at a given point. + * + * The normal calculation would be to form pixel value + dither, range-limit + * this to 0..MAXJSAMPLE, and then index into the colorindex table as usual. + * We can skip the separate range-limiting step by extending the colorindex + * table in both directions. + */ + +#define ODITHER_SIZE 16 /* dimension of dither matrix */ +/* NB: if ODITHER_SIZE is not a power of 2, ODITHER_MASK uses will break */ +#define ODITHER_CELLS (ODITHER_SIZE*ODITHER_SIZE) /* # cells in matrix */ +#define ODITHER_MASK (ODITHER_SIZE-1) /* mask for wrapping around counters */ + +typedef int ODITHER_MATRIX[ODITHER_SIZE][ODITHER_SIZE]; +typedef int (*ODITHER_MATRIX_PTR)[ODITHER_SIZE]; + +static const UINT8 base_dither_matrix[ODITHER_SIZE][ODITHER_SIZE] = { + /* Bayer's order-4 dither array. Generated by the code given in + * Stephen Hawley's article "Ordered Dithering" in Graphics Gems I. + * The values in this array must range from 0 to ODITHER_CELLS-1. + */ + { 0,192, 48,240, 12,204, 60,252, 3,195, 51,243, 15,207, 63,255 }, + { 128, 64,176,112,140, 76,188,124,131, 67,179,115,143, 79,191,127 }, + { 32,224, 16,208, 44,236, 28,220, 35,227, 19,211, 47,239, 31,223 }, + { 160, 96,144, 80,172,108,156, 92,163, 99,147, 83,175,111,159, 95 }, + { 8,200, 56,248, 4,196, 52,244, 11,203, 59,251, 7,199, 55,247 }, + { 136, 72,184,120,132, 68,180,116,139, 75,187,123,135, 71,183,119 }, + { 40,232, 24,216, 36,228, 20,212, 43,235, 27,219, 39,231, 23,215 }, + { 168,104,152, 88,164,100,148, 84,171,107,155, 91,167,103,151, 87 }, + { 2,194, 50,242, 14,206, 62,254, 1,193, 49,241, 13,205, 61,253 }, + { 130, 66,178,114,142, 78,190,126,129, 65,177,113,141, 77,189,125 }, + { 34,226, 18,210, 46,238, 30,222, 33,225, 17,209, 45,237, 29,221 }, + { 162, 98,146, 82,174,110,158, 94,161, 97,145, 81,173,109,157, 93 }, + { 10,202, 58,250, 6,198, 54,246, 9,201, 57,249, 5,197, 53,245 }, + { 138, 74,186,122,134, 70,182,118,137, 73,185,121,133, 69,181,117 }, + { 42,234, 26,218, 38,230, 22,214, 41,233, 25,217, 37,229, 21,213 }, + { 170,106,154, 90,166,102,150, 86,169,105,153, 89,165,101,149, 85 } +}; + + +/* Declarations for Floyd-Steinberg dithering. + * + * Errors are accumulated into the array fserrors[], at a resolution of + * 1/16th of a pixel count. The error at a given pixel is propagated + * to its not-yet-processed neighbors using the standard F-S fractions, + * ... (here) 7/16 + * 3/16 5/16 1/16 + * We work left-to-right on even rows, right-to-left on odd rows. + * + * We can get away with a single array (holding one row's worth of errors) + * by using it to store the current row's errors at pixel columns not yet + * processed, but the next row's errors at columns already processed. We + * need only a few extra variables to hold the errors immediately around the + * current column. (If we are lucky, those variables are in registers, but + * even if not, they're probably cheaper to access than array elements are.) + * + * The fserrors[] array is indexed [component#][position]. + * We provide (#columns + 2) entries per component; the extra entry at each + * end saves us from special-casing the first and last pixels. + * + * Note: on a wide image, we might not have enough room in a PC's near data + * segment to hold the error array; so it is allocated with alloc_large. + */ + +#if BITS_IN_JSAMPLE == 8 +typedef INT16 FSERROR; /* 16 bits should be enough */ +typedef int LOCFSERROR; /* use 'int' for calculation temps */ +#else +typedef IJG_INT32 FSERROR; /* may need more than 16 bits */ +typedef IJG_INT32 LOCFSERROR; /* be sure calculation temps are big enough */ +#endif + +typedef FSERROR FAR *FSERRPTR; /* pointer to error array (in FAR storage!) */ + + +/* Private subobject */ + +#define MAX_Q_COMPS 4 /* max components I can handle */ + +typedef struct { + struct jpeg_color_quantizer pub; /* public fields */ + + /* Initially allocated colormap is saved here */ + JSAMPARRAY sv_colormap; /* The color map as a 2-D pixel array */ + int sv_actual; /* number of entries in use */ + + JSAMPARRAY colorindex; /* Precomputed mapping for speed */ + /* colorindex[i][j] = index of color closest to pixel value j in component i, + * premultiplied as described above. Since colormap indexes must fit into + * JSAMPLEs, the entries of this array will too. + */ + boolean is_padded; /* is the colorindex padded for odither? */ + + int Ncolors[MAX_Q_COMPS]; /* # of values alloced to each component */ + + /* Variables for ordered dithering */ + int row_index; /* cur row's vertical index in dither matrix */ + ODITHER_MATRIX_PTR odither[MAX_Q_COMPS]; /* one dither array per component */ + + /* Variables for Floyd-Steinberg dithering */ + FSERRPTR fserrors[MAX_Q_COMPS]; /* accumulated errors */ + boolean on_odd_row; /* flag to remember which row we are on */ +} my_cquantizer; + +typedef my_cquantizer * my_cquantize_ptr; + + +/* + * Policy-making subroutines for create_colormap and create_colorindex. + * These routines determine the colormap to be used. The rest of the module + * only assumes that the colormap is orthogonal. + * + * * select_ncolors decides how to divvy up the available colors + * among the components. + * * output_value defines the set of representative values for a component. + * * largest_input_value defines the mapping from input values to + * representative values for a component. + * Note that the latter two routines may impose different policies for + * different components, though this is not currently done. + */ + + +LOCAL(int) +select_ncolors (j_decompress_ptr cinfo, int Ncolors[]) +/* Determine allocation of desired colors to components, */ +/* and fill in Ncolors[] array to indicate choice. */ +/* Return value is total number of colors (product of Ncolors[] values). */ +{ + int nc = cinfo->out_color_components; /* number of color components */ + int max_colors = cinfo->desired_number_of_colors; + int total_colors, iroot, i, j; + boolean changed; + long temp; + static const int RGB_order[3] = { RGB_GREEN, RGB_RED, RGB_BLUE }; + + /* We can allocate at least the nc'th root of max_colors per component. */ + /* Compute floor(nc'th root of max_colors). */ + iroot = 1; + do { + iroot++; + temp = iroot; /* set temp = iroot ** nc */ + for (i = 1; i < nc; i++) + temp *= iroot; + } while (temp <= (long) max_colors); /* repeat till iroot exceeds root */ + iroot--; /* now iroot = floor(root) */ + + /* Must have at least 2 color values per component */ + if (iroot < 2) + ERREXIT1(cinfo, JERR_QUANT_FEW_COLORS, (int) temp); + + /* Initialize to iroot color values for each component */ + total_colors = 1; + for (i = 0; i < nc; i++) { + Ncolors[i] = iroot; + total_colors *= iroot; + } + /* We may be able to increment the count for one or more components without + * exceeding max_colors, though we know not all can be incremented. + * Sometimes, the first component can be incremented more than once! + * (Example: for 16 colors, we start at 2*2*2, go to 3*2*2, then 4*2*2.) + * In RGB colorspace, try to increment G first, then R, then B. + */ + do { + changed = FALSE; + for (i = 0; i < nc; i++) { + j = (cinfo->out_color_space == JCS_RGB ? RGB_order[i] : i); + /* calculate new total_colors if Ncolors[j] is incremented */ + temp = total_colors / Ncolors[j]; + temp *= Ncolors[j]+1; /* done in long arith to avoid oflo */ + if (temp > (long) max_colors) + break; /* won't fit, done with this pass */ + Ncolors[j]++; /* OK, apply the increment */ + total_colors = (int) temp; + changed = TRUE; + } + } while (changed); + + return total_colors; +} + + +LOCAL(int) +output_value (j_decompress_ptr cinfo, int ci, int j, int maxj) +/* Return j'th output value, where j will range from 0 to maxj */ +/* The output values must fall in 0..MAXJSAMPLE in increasing order */ +{ + /* We always provide values 0 and MAXJSAMPLE for each component; + * any additional values are equally spaced between these limits. + * (Forcing the upper and lower values to the limits ensures that + * dithering can't produce a color outside the selected gamut.) + */ + return (int) (((IJG_INT32) j * MAXJSAMPLE + maxj/2) / maxj); +} + + +LOCAL(int) +largest_input_value (j_decompress_ptr cinfo, int ci, int j, int maxj) +/* Return largest input value that should map to j'th output value */ +/* Must have largest(j=0) >= 0, and largest(j=maxj) >= MAXJSAMPLE */ +{ + /* Breakpoints are halfway between values returned by output_value */ + return (int) (((IJG_INT32) (2*j + 1) * MAXJSAMPLE + maxj) / (2*maxj)); +} + + +/* + * Create the colormap. + */ + +LOCAL(void) +create_colormap (j_decompress_ptr cinfo) +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + JSAMPARRAY colormap; /* Created colormap */ + int total_colors; /* Number of distinct output colors */ + int i,j,k, nci, blksize, blkdist, ptr, val; + + /* Select number of colors for each component */ + total_colors = select_ncolors(cinfo, cquantize->Ncolors); + + /* Report selected color counts */ + if (cinfo->out_color_components == 3) + TRACEMS4(cinfo, 1, JTRC_QUANT_3_NCOLORS, + total_colors, cquantize->Ncolors[0], + cquantize->Ncolors[1], cquantize->Ncolors[2]); + else + TRACEMS1(cinfo, 1, JTRC_QUANT_NCOLORS, total_colors); + + /* Allocate and fill in the colormap. */ + /* The colors are ordered in the map in standard row-major order, */ + /* i.e. rightmost (highest-indexed) color changes most rapidly. */ + + colormap = (*cinfo->mem->alloc_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + (JDIMENSION) total_colors, (JDIMENSION) cinfo->out_color_components); + + /* blksize is number of adjacent repeated entries for a component */ + /* blkdist is distance between groups of identical entries for a component */ + blkdist = total_colors; + + for (i = 0; i < cinfo->out_color_components; i++) { + /* fill in colormap entries for i'th color component */ + nci = cquantize->Ncolors[i]; /* # of distinct values for this color */ + blksize = blkdist / nci; + for (j = 0; j < nci; j++) { + /* Compute j'th output value (out of nci) for component */ + val = output_value(cinfo, i, j, nci-1); + /* Fill in all colormap entries that have this value of this component */ + for (ptr = j * blksize; ptr < total_colors; ptr += blkdist) { + /* fill in blksize entries beginning at ptr */ + for (k = 0; k < blksize; k++) + colormap[i][ptr+k] = (JSAMPLE) val; + } + } + blkdist = blksize; /* blksize of this color is blkdist of next */ + } + + /* Save the colormap in private storage, + * where it will survive color quantization mode changes. + */ + cquantize->sv_colormap = colormap; + cquantize->sv_actual = total_colors; +} + + +/* + * Create the color index table. + */ + +LOCAL(void) +create_colorindex (j_decompress_ptr cinfo) +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + JSAMPROW indexptr; + int i,j,k, nci, blksize, val, pad; + + /* For ordered dither, we pad the color index tables by MAXJSAMPLE in + * each direction (input index values can be -MAXJSAMPLE .. 2*MAXJSAMPLE). + * This is not necessary in the other dithering modes. However, we + * flag whether it was done in case user changes dithering mode. + */ + if (cinfo->dither_mode == JDITHER_ORDERED) { + pad = MAXJSAMPLE*2; + cquantize->is_padded = TRUE; + } else { + pad = 0; + cquantize->is_padded = FALSE; + } + + cquantize->colorindex = (*cinfo->mem->alloc_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + (JDIMENSION) (MAXJSAMPLE+1 + pad), + (JDIMENSION) cinfo->out_color_components); + + /* blksize is number of adjacent repeated entries for a component */ + blksize = cquantize->sv_actual; + + for (i = 0; i < cinfo->out_color_components; i++) { + /* fill in colorindex entries for i'th color component */ + nci = cquantize->Ncolors[i]; /* # of distinct values for this color */ + blksize = blksize / nci; + + /* adjust colorindex pointers to provide padding at negative indexes. */ + if (pad) + cquantize->colorindex[i] += MAXJSAMPLE; + + /* in loop, val = index of current output value, */ + /* and k = largest j that maps to current val */ + indexptr = cquantize->colorindex[i]; + val = 0; + k = largest_input_value(cinfo, i, 0, nci-1); + for (j = 0; j <= MAXJSAMPLE; j++) { + while (j > k) /* advance val if past boundary */ + k = largest_input_value(cinfo, i, ++val, nci-1); + /* premultiply so that no multiplication needed in main processing */ + indexptr[j] = (JSAMPLE) (val * blksize); + } + /* Pad at both ends if necessary */ + if (pad) + for (j = 1; j <= MAXJSAMPLE; j++) { + indexptr[-j] = indexptr[0]; + indexptr[MAXJSAMPLE+j] = indexptr[MAXJSAMPLE]; + } + } +} + + +/* + * Create an ordered-dither array for a component having ncolors + * distinct output values. + */ + +LOCAL(ODITHER_MATRIX_PTR) +make_odither_array (j_decompress_ptr cinfo, int ncolors) +{ + ODITHER_MATRIX_PTR odither; + int j,k; + IJG_INT32 num,den; + + odither = (ODITHER_MATRIX_PTR) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(ODITHER_MATRIX)); + /* The inter-value distance for this color is MAXJSAMPLE/(ncolors-1). + * Hence the dither value for the matrix cell with fill order f + * (f=0..N-1) should be (N-1-2*f)/(2*N) * MAXJSAMPLE/(ncolors-1). + * On 16-bit-int machine, be careful to avoid overflow. + */ + den = 2 * ODITHER_CELLS * ((IJG_INT32) (ncolors - 1)); + for (j = 0; j < ODITHER_SIZE; j++) { + for (k = 0; k < ODITHER_SIZE; k++) { + num = ((IJG_INT32) (ODITHER_CELLS-1 - 2*((int)base_dither_matrix[j][k]))) + * MAXJSAMPLE; + /* Ensure round towards zero despite C's lack of consistency + * about rounding negative values in integer division... + */ + odither[j][k] = (int) (num<0 ? -((-num)/den) : num/den); + } + } + return odither; +} + + +/* + * Create the ordered-dither tables. + * Components having the same number of representative colors may + * share a dither table. + */ + +LOCAL(void) +create_odither_tables (j_decompress_ptr cinfo) +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + ODITHER_MATRIX_PTR odither; + int i, j, nci; + + for (i = 0; i < cinfo->out_color_components; i++) { + nci = cquantize->Ncolors[i]; /* # of distinct values for this color */ + odither = NULL; /* search for matching prior component */ + for (j = 0; j < i; j++) { + if (nci == cquantize->Ncolors[j]) { + odither = cquantize->odither[j]; + break; + } + } + if (odither == NULL) /* need a new table? */ + odither = make_odither_array(cinfo, nci); + cquantize->odither[i] = odither; + } +} + + +/* + * Map some rows of pixels to the output colormapped representation. + */ + +METHODDEF(void) +color_quantize (j_decompress_ptr cinfo, JSAMPARRAY input_buf, + JSAMPARRAY output_buf, int num_rows) +/* General case, no dithering */ +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + JSAMPARRAY colorindex = cquantize->colorindex; + register int pixcode, ci; + register JSAMPROW ptrin, ptrout; + int row; + JDIMENSION col; + JDIMENSION width = cinfo->output_width; + register int nc = cinfo->out_color_components; + + for (row = 0; row < num_rows; row++) { + ptrin = input_buf[row]; + ptrout = output_buf[row]; + for (col = width; col > 0; col--) { + pixcode = 0; + for (ci = 0; ci < nc; ci++) { + pixcode += GETJSAMPLE(colorindex[ci][GETJSAMPLE(*ptrin++)]); + } + *ptrout++ = (JSAMPLE) pixcode; + } + } +} + + +METHODDEF(void) +color_quantize3 (j_decompress_ptr cinfo, JSAMPARRAY input_buf, + JSAMPARRAY output_buf, int num_rows) +/* Fast path for out_color_components==3, no dithering */ +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + register int pixcode; + register JSAMPROW ptrin, ptrout; + JSAMPROW colorindex0 = cquantize->colorindex[0]; + JSAMPROW colorindex1 = cquantize->colorindex[1]; + JSAMPROW colorindex2 = cquantize->colorindex[2]; + int row; + JDIMENSION col; + JDIMENSION width = cinfo->output_width; + + for (row = 0; row < num_rows; row++) { + ptrin = input_buf[row]; + ptrout = output_buf[row]; + for (col = width; col > 0; col--) { + pixcode = GETJSAMPLE(colorindex0[GETJSAMPLE(*ptrin++)]); + pixcode += GETJSAMPLE(colorindex1[GETJSAMPLE(*ptrin++)]); + pixcode += GETJSAMPLE(colorindex2[GETJSAMPLE(*ptrin++)]); + *ptrout++ = (JSAMPLE) pixcode; + } + } +} + + +METHODDEF(void) +quantize_ord_dither (j_decompress_ptr cinfo, JSAMPARRAY input_buf, + JSAMPARRAY output_buf, int num_rows) +/* General case, with ordered dithering */ +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + register JSAMPROW input_ptr; + register JSAMPROW output_ptr; + JSAMPROW colorindex_ci; + int * dither; /* points to active row of dither matrix */ + int row_index, col_index; /* current indexes into dither matrix */ + int nc = cinfo->out_color_components; + int ci; + int row; + JDIMENSION col; + JDIMENSION width = cinfo->output_width; + + for (row = 0; row < num_rows; row++) { + /* Initialize output values to 0 so can process components separately */ + jzero_far((void FAR *) output_buf[row], + (size_t) (width * SIZEOF(JSAMPLE))); + row_index = cquantize->row_index; + for (ci = 0; ci < nc; ci++) { + input_ptr = input_buf[row] + ci; + output_ptr = output_buf[row]; + colorindex_ci = cquantize->colorindex[ci]; + dither = cquantize->odither[ci][row_index]; + col_index = 0; + + for (col = width; col > 0; col--) { + /* Form pixel value + dither, range-limit to 0..MAXJSAMPLE, + * select output value, accumulate into output code for this pixel. + * Range-limiting need not be done explicitly, as we have extended + * the colorindex table to produce the right answers for out-of-range + * inputs. The maximum dither is +- MAXJSAMPLE; this sets the + * required amount of padding. + */ + *output_ptr = (JSAMPLE)(*output_ptr + colorindex_ci[GETJSAMPLE(*input_ptr)+dither[col_index]]); + input_ptr += nc; + output_ptr++; + col_index = (col_index + 1) & ODITHER_MASK; + } + } + /* Advance row index for next row */ + row_index = (row_index + 1) & ODITHER_MASK; + cquantize->row_index = row_index; + } +} + + +METHODDEF(void) +quantize3_ord_dither (j_decompress_ptr cinfo, JSAMPARRAY input_buf, + JSAMPARRAY output_buf, int num_rows) +/* Fast path for out_color_components==3, with ordered dithering */ +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + register int pixcode; + register JSAMPROW input_ptr; + register JSAMPROW output_ptr; + JSAMPROW colorindex0 = cquantize->colorindex[0]; + JSAMPROW colorindex1 = cquantize->colorindex[1]; + JSAMPROW colorindex2 = cquantize->colorindex[2]; + int * dither0; /* points to active row of dither matrix */ + int * dither1; + int * dither2; + int row_index, col_index; /* current indexes into dither matrix */ + int row; + JDIMENSION col; + JDIMENSION width = cinfo->output_width; + + for (row = 0; row < num_rows; row++) { + row_index = cquantize->row_index; + input_ptr = input_buf[row]; + output_ptr = output_buf[row]; + dither0 = cquantize->odither[0][row_index]; + dither1 = cquantize->odither[1][row_index]; + dither2 = cquantize->odither[2][row_index]; + col_index = 0; + + for (col = width; col > 0; col--) { + pixcode = GETJSAMPLE(colorindex0[GETJSAMPLE(*input_ptr++) + + dither0[col_index]]); + pixcode += GETJSAMPLE(colorindex1[GETJSAMPLE(*input_ptr++) + + dither1[col_index]]); + pixcode += GETJSAMPLE(colorindex2[GETJSAMPLE(*input_ptr++) + + dither2[col_index]]); + *output_ptr++ = (JSAMPLE) pixcode; + col_index = (col_index + 1) & ODITHER_MASK; + } + row_index = (row_index + 1) & ODITHER_MASK; + cquantize->row_index = row_index; + } +} + + +METHODDEF(void) +quantize_fs_dither (j_decompress_ptr cinfo, JSAMPARRAY input_buf, + JSAMPARRAY output_buf, int num_rows) +/* General case, with Floyd-Steinberg dithering */ +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + register LOCFSERROR cur; /* current error or pixel value */ + LOCFSERROR belowerr; /* error for pixel below cur */ + LOCFSERROR bpreverr; /* error for below/prev col */ + LOCFSERROR bnexterr; /* error for below/next col */ + LOCFSERROR delta; + register FSERRPTR errorptr; /* => fserrors[] at column before current */ + register JSAMPROW input_ptr; + register JSAMPROW output_ptr; + JSAMPROW colorindex_ci; + JSAMPROW colormap_ci; + int pixcode; + int nc = cinfo->out_color_components; + int dir; /* 1 for left-to-right, -1 for right-to-left */ + int dirnc; /* dir * nc */ + int ci; + int row; + JDIMENSION col; + JDIMENSION width = cinfo->output_width; + JSAMPLE *range_limit = cinfo->sample_range_limit; + SHIFT_TEMPS + + for (row = 0; row < num_rows; row++) { + /* Initialize output values to 0 so can process components separately */ + jzero_far((void FAR *) output_buf[row], + (size_t) (width * SIZEOF(JSAMPLE))); + for (ci = 0; ci < nc; ci++) { + input_ptr = input_buf[row] + ci; + output_ptr = output_buf[row]; + if (cquantize->on_odd_row) { + /* work right to left in this row */ + input_ptr += (width-1) * (JDIMENSION)nc; /* so point to rightmost pixel */ + output_ptr += width-1; + dir = -1; + dirnc = -nc; + errorptr = cquantize->fserrors[ci] + (width+1); /* => entry after last column */ + } else { + /* work left to right in this row */ + dir = 1; + dirnc = nc; + errorptr = cquantize->fserrors[ci]; /* => entry before first column */ + } + colorindex_ci = cquantize->colorindex[ci]; + colormap_ci = cquantize->sv_colormap[ci]; + /* Preset error values: no error propagated to first pixel from left */ + cur = 0; + /* and no error propagated to row below yet */ + belowerr = bpreverr = 0; + + for (col = width; col > 0; col--) { + /* cur holds the error propagated from the previous pixel on the + * current line. Add the error propagated from the previous line + * to form the complete error correction term for this pixel, and + * round the error term (which is expressed * 16) to an integer. + * RIGHT_SHIFT rounds towards minus infinity, so adding 8 is correct + * for either sign of the error value. + * Note: errorptr points to *previous* column's array entry. + */ + cur = RIGHT_SHIFT(cur + errorptr[dir] + 8, 4); + /* Form pixel value + error, and range-limit to 0..MAXJSAMPLE. + * The maximum error is +- MAXJSAMPLE; this sets the required size + * of the range_limit array. + */ + cur += GETJSAMPLE(*input_ptr); + cur = GETJSAMPLE(range_limit[cur]); + /* Select output value, accumulate into output code for this pixel */ + pixcode = GETJSAMPLE(colorindex_ci[cur]); + *output_ptr = (JSAMPLE)(*output_ptr + pixcode); + /* Compute actual representation error at this pixel */ + /* Note: we can do this even though we don't have the final */ + /* pixel code, because the colormap is orthogonal. */ + cur -= GETJSAMPLE(colormap_ci[pixcode]); + /* Compute error fractions to be propagated to adjacent pixels. + * Add these into the running sums, and simultaneously shift the + * next-line error sums left by 1 column. + */ + bnexterr = cur; + delta = cur * 2; + cur += delta; /* form error * 3 */ + errorptr[0] = (FSERROR) (bpreverr + cur); + cur += delta; /* form error * 5 */ + bpreverr = belowerr + cur; + belowerr = bnexterr; + cur += delta; /* form error * 7 */ + /* At this point cur contains the 7/16 error value to be propagated + * to the next pixel on the current line, and all the errors for the + * next line have been shifted over. We are therefore ready to move on. + */ + input_ptr += dirnc; /* advance input ptr to next column */ + output_ptr += dir; /* advance output ptr to next column */ + errorptr += dir; /* advance errorptr to current column */ + } + /* Post-loop cleanup: we must unload the final error value into the + * final fserrors[] entry. Note we need not unload belowerr because + * it is for the dummy column before or after the actual array. + */ + errorptr[0] = (FSERROR) bpreverr; /* unload prev err into array */ + } + cquantize->on_odd_row = (cquantize->on_odd_row ? FALSE : TRUE); + } +} + + +/* + * Allocate workspace for Floyd-Steinberg errors. + */ + +LOCAL(void) +alloc_fs_workspace (j_decompress_ptr cinfo) +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + size_t arraysize; + int i; + + arraysize = (size_t) ((cinfo->output_width + 2) * SIZEOF(FSERROR)); + for (i = 0; i < cinfo->out_color_components; i++) { + cquantize->fserrors[i] = (FSERRPTR) + (*cinfo->mem->alloc_large)((j_common_ptr) cinfo, JPOOL_IMAGE, arraysize); + } +} + + +/* + * Initialize for one-pass color quantization. + */ + +METHODDEF(void) +start_pass_1_quant (j_decompress_ptr cinfo, boolean is_pre_scan) +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + size_t arraysize; + int i; + + /* Install my colormap. */ + cinfo->colormap = cquantize->sv_colormap; + cinfo->actual_number_of_colors = cquantize->sv_actual; + + /* Initialize for desired dithering mode. */ + switch (cinfo->dither_mode) { + case JDITHER_NONE: + if (cinfo->out_color_components == 3) + cquantize->pub.color_quantize = color_quantize3; + else + cquantize->pub.color_quantize = color_quantize; + break; + case JDITHER_ORDERED: + if (cinfo->out_color_components == 3) + cquantize->pub.color_quantize = quantize3_ord_dither; + else + cquantize->pub.color_quantize = quantize_ord_dither; + cquantize->row_index = 0; /* initialize state for ordered dither */ + /* If user changed to ordered dither from another mode, + * we must recreate the color index table with padding. + * This will cost extra space, but probably isn't very likely. + */ + if (! cquantize->is_padded) + create_colorindex(cinfo); + /* Create ordered-dither tables if we didn't already. */ + if (cquantize->odither[0] == NULL) + create_odither_tables(cinfo); + break; + case JDITHER_FS: + cquantize->pub.color_quantize = quantize_fs_dither; + cquantize->on_odd_row = FALSE; /* initialize state for F-S dither */ + /* Allocate Floyd-Steinberg workspace if didn't already. */ + if (cquantize->fserrors[0] == NULL) + alloc_fs_workspace(cinfo); + /* Initialize the propagated errors to zero. */ + arraysize = (size_t) ((cinfo->output_width + 2) * SIZEOF(FSERROR)); + for (i = 0; i < cinfo->out_color_components; i++) + jzero_far((void FAR *) cquantize->fserrors[i], arraysize); + break; + default: + ERREXIT(cinfo, JERR_NOT_COMPILED); + break; + } +} + + +/* + * Finish up at the end of the pass. + */ + +METHODDEF(void) +finish_pass_1_quant (j_decompress_ptr cinfo) +{ + /* no work in 1-pass case */ +} + + +/* + * Switch to a new external colormap between output passes. + * Shouldn't get to this module! + */ + +METHODDEF(void) +new_color_map_1_quant (j_decompress_ptr cinfo) +{ + ERREXIT(cinfo, JERR_MODE_CHANGE); +} + + +/* + * Module initialization routine for 1-pass color quantization. + */ + +GLOBAL(void) +jinit_1pass_quantizer (j_decompress_ptr cinfo) +{ + my_cquantize_ptr cquantize; + + cquantize = (my_cquantize_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_cquantizer)); + cinfo->cquantize = (struct jpeg_color_quantizer *) cquantize; + cquantize->pub.start_pass = start_pass_1_quant; + cquantize->pub.finish_pass = finish_pass_1_quant; + cquantize->pub.new_color_map = new_color_map_1_quant; + cquantize->fserrors[0] = NULL; /* Flag FS workspace not allocated */ + cquantize->odither[0] = NULL; /* Also flag odither arrays not allocated */ + + /* Make sure my internal arrays won't overflow */ + if (cinfo->out_color_components > MAX_Q_COMPS) + ERREXIT1(cinfo, JERR_QUANT_COMPONENTS, MAX_Q_COMPS); + /* Make sure colormap indexes can be represented by JSAMPLEs */ + if (cinfo->desired_number_of_colors > (MAXJSAMPLE+1)) + ERREXIT1(cinfo, JERR_QUANT_MANY_COLORS, MAXJSAMPLE+1); + + /* Create the colormap and color index table. */ + create_colormap(cinfo); + create_colorindex(cinfo); + + /* Allocate Floyd-Steinberg workspace now if requested. + * We do this now since it is FAR storage and may affect the memory + * manager's space calculations. If the user changes to FS dither + * mode in a later pass, we will allocate the space then, and will + * possibly overrun the max_memory_to_use setting. + */ + if (cinfo->dither_mode == JDITHER_FS) + alloc_fs_workspace(cinfo); +} + +#endif /* QUANT_1PASS_SUPPORTED */ diff --git a/dcmjpeg/libijg12/jquant2.c b/dcmjpeg/libijg12/jquant2.c new file mode 100644 index 00000000..7f8c8b52 --- /dev/null +++ b/dcmjpeg/libijg12/jquant2.c @@ -0,0 +1,1310 @@ +/* + * jquant2.c + * + * Copyright (C) 1991-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains 2-pass color quantization (color mapping) routines. + * These routines provide selection of a custom color map for an image, + * followed by mapping of the image to that color map, with optional + * Floyd-Steinberg dithering. + * It is also possible to use just the second pass to map to an arbitrary + * externally-given color map. + * + * Note: ordered dithering is not supported, since there isn't any fast + * way to compute intercolor distances; it's unclear that ordered dither's + * fundamental assumptions even hold with an irregularly spaced color map. + */ + +#define JPEG_INTERNALS +#include "jinclude12.h" +#include "jpeglib12.h" + +#ifdef QUANT_2PASS_SUPPORTED + + +/* + * This module implements the well-known Heckbert paradigm for color + * quantization. Most of the ideas used here can be traced back to + * Heckbert's seminal paper + * Heckbert, Paul. "Color Image Quantization for Frame Buffer Display", + * Proc. SIGGRAPH '82, Computer Graphics v.16 #3 (July 1982), pp 297-304. + * + * In the first pass over the image, we accumulate a histogram showing the + * usage count of each possible color. To keep the histogram to a reasonable + * size, we reduce the precision of the input; typical practice is to retain + * 5 or 6 bits per color, so that 8 or 4 different input values are counted + * in the same histogram cell. + * + * Next, the color-selection step begins with a box representing the whole + * color space, and repeatedly splits the "largest" remaining box until we + * have as many boxes as desired colors. Then the mean color in each + * remaining box becomes one of the possible output colors. + * + * The second pass over the image maps each input pixel to the closest output + * color (optionally after applying a Floyd-Steinberg dithering correction). + * This mapping is logically trivial, but making it go fast enough requires + * considerable care. + * + * Heckbert-style quantizers vary a good deal in their policies for choosing + * the "largest" box and deciding where to cut it. The particular policies + * used here have proved out well in experimental comparisons, but better ones + * may yet be found. + * + * In earlier versions of the IJG code, this module quantized in YCbCr color + * space, processing the raw upsampled data without a color conversion step. + * This allowed the color conversion math to be done only once per colormap + * entry, not once per pixel. However, that optimization precluded other + * useful optimizations (such as merging color conversion with upsampling) + * and it also interfered with desired capabilities such as quantizing to an + * externally-supplied colormap. We have therefore abandoned that approach. + * The present code works in the post-conversion color space, typically RGB. + * + * To improve the visual quality of the results, we actually work in scaled + * RGB space, giving G distances more weight than R, and R in turn more than + * B. To do everything in integer math, we must use integer scale factors. + * The 2/3/1 scale factors used here correspond loosely to the relative + * weights of the colors in the NTSC grayscale equation. + * If you want to use this code to quantize a non-RGB color space, you'll + * probably need to change these scale factors. + */ + +#define R_SCALE 2 /* scale R distances by this much */ +#define G_SCALE 3 /* scale G distances by this much */ +#define B_SCALE 1 /* and B by this much */ + +/* Relabel R/G/B as components 0/1/2, respecting the RGB ordering defined + * in jmorecfg.h. As the code stands, it will do the right thing for R,G,B + * and B,G,R orders. If you define some other weird order in jmorecfg.h, + * you'll get compile errors until you extend this logic. In that case + * you'll probably want to tweak the histogram sizes too. + */ + +#if RGB_RED == 0 +#define C0_SCALE R_SCALE +#endif +#if RGB_BLUE == 0 +#define C0_SCALE B_SCALE +#endif +#if RGB_GREEN == 1 +#define C1_SCALE G_SCALE +#endif +#if RGB_RED == 2 +#define C2_SCALE R_SCALE +#endif +#if RGB_BLUE == 2 +#define C2_SCALE B_SCALE +#endif + + +/* + * First we have the histogram data structure and routines for creating it. + * + * The number of bits of precision can be adjusted by changing these symbols. + * We recommend keeping 6 bits for G and 5 each for R and B. + * If you have plenty of memory and cycles, 6 bits all around gives marginally + * better results; if you are short of memory, 5 bits all around will save + * some space but degrade the results. + * To maintain a fully accurate histogram, we'd need to allocate a "long" + * (preferably unsigned long) for each cell. In practice this is overkill; + * we can get by with 16 bits per cell. Few of the cell counts will overflow, + * and clamping those that do overflow to the maximum value will give close- + * enough results. This reduces the recommended histogram size from 256Kb + * to 128Kb, which is a useful savings on PC-class machines. + * (In the second pass the histogram space is re-used for pixel mapping data; + * in that capacity, each cell must be able to store zero to the number of + * desired colors. 16 bits/cell is plenty for that too.) + * Since the JPEG code is intended to run in small memory model on 80x86 + * machines, we can't just allocate the histogram in one chunk. Instead + * of a true 3-D array, we use a row of pointers to 2-D arrays. Each + * pointer corresponds to a C0 value (typically 2^5 = 32 pointers) and + * each 2-D array has 2^6*2^5 = 2048 or 2^6*2^6 = 4096 entries. Note that + * on 80x86 machines, the pointer row is in near memory but the actual + * arrays are in far memory (same arrangement as we use for image arrays). + */ + +#define MAXNUMCOLORS (MAXJSAMPLE+1) /* maximum size of colormap */ + +/* These will do the right thing for either R,G,B or B,G,R color order, + * but you may not like the results for other color orders. + */ +#define HIST_C0_BITS 5 /* bits of precision in R/B histogram */ +#define HIST_C1_BITS 6 /* bits of precision in G histogram */ +#define HIST_C2_BITS 5 /* bits of precision in B/R histogram */ + +/* Number of elements along histogram axes. */ +#define HIST_C0_ELEMS (1<cquantize; + register JSAMPROW ptr; + register histptr histp; + register hist3d histogram = cquantize->histogram; + int row; + JDIMENSION col; + JDIMENSION width = cinfo->output_width; + + for (row = 0; row < num_rows; row++) { + ptr = input_buf[row]; + for (col = width; col > 0; col--) { + /* get pixel value and index into the histogram */ + histp = & histogram[GETJSAMPLE(ptr[0]) >> C0_SHIFT] + [GETJSAMPLE(ptr[1]) >> C1_SHIFT] + [GETJSAMPLE(ptr[2]) >> C2_SHIFT]; + /* increment, check for overflow and undo increment if so. */ + if (++(*histp) <= 0) + (*histp)--; + ptr += 3; + } + } +} + + +/* + * Next we have the really interesting routines: selection of a colormap + * given the completed histogram. + * These routines work with a list of "boxes", each representing a rectangular + * subset of the input color space (to histogram precision). + */ + +typedef struct { + /* The bounds of the box (inclusive); expressed as histogram indexes */ + int c0min, c0max; + int c1min, c1max; + int c2min, c2max; + /* The volume (actually 2-norm) of the box */ + IJG_INT32 volume; + /* The number of nonzero histogram cells within this box */ + long colorcount; +} box; + +typedef box * boxptr; + + +LOCAL(boxptr) +find_biggest_color_pop (boxptr boxlist, int numboxes) +/* Find the splittable box with the largest color population */ +/* Returns NULL if no splittable boxes remain */ +{ + register boxptr boxp; + register int i; + register long maxc = 0; + boxptr which = NULL; + + for (i = 0, boxp = boxlist; i < numboxes; i++, boxp++) { + if (boxp->colorcount > maxc && boxp->volume > 0) { + which = boxp; + maxc = boxp->colorcount; + } + } + return which; +} + + +LOCAL(boxptr) +find_biggest_volume (boxptr boxlist, int numboxes) +/* Find the splittable box with the largest (scaled) volume */ +/* Returns NULL if no splittable boxes remain */ +{ + register boxptr boxp; + register int i; + register IJG_INT32 maxv = 0; + boxptr which = NULL; + + for (i = 0, boxp = boxlist; i < numboxes; i++, boxp++) { + if (boxp->volume > maxv) { + which = boxp; + maxv = boxp->volume; + } + } + return which; +} + + +LOCAL(void) +update_box (j_decompress_ptr cinfo, boxptr boxp) +/* Shrink the min/max bounds of a box to enclose only nonzero elements, */ +/* and recompute its volume and population */ +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + hist3d histogram = cquantize->histogram; + histptr histp; + int c0,c1,c2; + int c0min,c0max,c1min,c1max,c2min,c2max; + IJG_INT32 dist0,dist1,dist2; + long ccount; + + c0min = boxp->c0min; c0max = boxp->c0max; + c1min = boxp->c1min; c1max = boxp->c1max; + c2min = boxp->c2min; c2max = boxp->c2max; + + if (c0max > c0min) + for (c0 = c0min; c0 <= c0max; c0++) + for (c1 = c1min; c1 <= c1max; c1++) { + histp = & histogram[c0][c1][c2min]; + for (c2 = c2min; c2 <= c2max; c2++) + if (*histp++ != 0) { + boxp->c0min = c0min = c0; + goto have_c0min; + } + } + have_c0min: + if (c0max > c0min) + for (c0 = c0max; c0 >= c0min; c0--) + for (c1 = c1min; c1 <= c1max; c1++) { + histp = & histogram[c0][c1][c2min]; + for (c2 = c2min; c2 <= c2max; c2++) + if (*histp++ != 0) { + boxp->c0max = c0max = c0; + goto have_c0max; + } + } + have_c0max: + if (c1max > c1min) + for (c1 = c1min; c1 <= c1max; c1++) + for (c0 = c0min; c0 <= c0max; c0++) { + histp = & histogram[c0][c1][c2min]; + for (c2 = c2min; c2 <= c2max; c2++) + if (*histp++ != 0) { + boxp->c1min = c1min = c1; + goto have_c1min; + } + } + have_c1min: + if (c1max > c1min) + for (c1 = c1max; c1 >= c1min; c1--) + for (c0 = c0min; c0 <= c0max; c0++) { + histp = & histogram[c0][c1][c2min]; + for (c2 = c2min; c2 <= c2max; c2++) + if (*histp++ != 0) { + boxp->c1max = c1max = c1; + goto have_c1max; + } + } + have_c1max: + if (c2max > c2min) + for (c2 = c2min; c2 <= c2max; c2++) + for (c0 = c0min; c0 <= c0max; c0++) { + histp = & histogram[c0][c1min][c2]; + for (c1 = c1min; c1 <= c1max; c1++, histp += HIST_C2_ELEMS) + if (*histp != 0) { + boxp->c2min = c2min = c2; + goto have_c2min; + } + } + have_c2min: + if (c2max > c2min) + for (c2 = c2max; c2 >= c2min; c2--) + for (c0 = c0min; c0 <= c0max; c0++) { + histp = & histogram[c0][c1min][c2]; + for (c1 = c1min; c1 <= c1max; c1++, histp += HIST_C2_ELEMS) + if (*histp != 0) { + boxp->c2max = c2max = c2; + goto have_c2max; + } + } + have_c2max: + + /* Update box volume. + * We use 2-norm rather than real volume here; this biases the method + * against making long narrow boxes, and it has the side benefit that + * a box is splittable iff norm > 0. + * Since the differences are expressed in histogram-cell units, + * we have to shift back to JSAMPLE units to get consistent distances; + * after which, we scale according to the selected distance scale factors. + */ + dist0 = ((c0max - c0min) << C0_SHIFT) * C0_SCALE; + dist1 = ((c1max - c1min) << C1_SHIFT) * C1_SCALE; + dist2 = ((c2max - c2min) << C2_SHIFT) * C2_SCALE; + boxp->volume = dist0*dist0 + dist1*dist1 + dist2*dist2; + + /* Now scan remaining volume of box and compute population */ + ccount = 0; + for (c0 = c0min; c0 <= c0max; c0++) + for (c1 = c1min; c1 <= c1max; c1++) { + histp = & histogram[c0][c1][c2min]; + for (c2 = c2min; c2 <= c2max; c2++, histp++) + if (*histp != 0) { + ccount++; + } + } + boxp->colorcount = ccount; +} + + +LOCAL(int) +median_cut (j_decompress_ptr cinfo, boxptr boxlist, int numboxes, + int desired_colors) +/* Repeatedly select and split the largest box until we have enough boxes */ +{ + int n,lb; + int c0,c1,c2,cmax; + register boxptr b1,b2; + + while (numboxes < desired_colors) { + /* Select box to split. + * Current algorithm: by population for first half, then by volume. + */ + if (numboxes*2 <= desired_colors) { + b1 = find_biggest_color_pop(boxlist, numboxes); + } else { + b1 = find_biggest_volume(boxlist, numboxes); + } + if (b1 == NULL) /* no splittable boxes left! */ + break; + b2 = &boxlist[numboxes]; /* where new box will go */ + /* Copy the color bounds to the new box. */ + b2->c0max = b1->c0max; b2->c1max = b1->c1max; b2->c2max = b1->c2max; + b2->c0min = b1->c0min; b2->c1min = b1->c1min; b2->c2min = b1->c2min; + /* Choose which axis to split the box on. + * Current algorithm: longest scaled axis. + * See notes in update_box about scaling distances. + */ + c0 = ((b1->c0max - b1->c0min) << C0_SHIFT) * C0_SCALE; + c1 = ((b1->c1max - b1->c1min) << C1_SHIFT) * C1_SCALE; + c2 = ((b1->c2max - b1->c2min) << C2_SHIFT) * C2_SCALE; + /* We want to break any ties in favor of green, then red, blue last. + * This code does the right thing for R,G,B or B,G,R color orders only. + */ +#if RGB_RED == 0 + cmax = c1; n = 1; + if (c0 > cmax) { cmax = c0; n = 0; } + if (c2 > cmax) { n = 2; } +#else + cmax = c1; n = 1; + if (c2 > cmax) { cmax = c2; n = 2; } + if (c0 > cmax) { n = 0; } +#endif + /* Choose split point along selected axis, and update box bounds. + * Current algorithm: split at halfway point. + * (Since the box has been shrunk to minimum volume, + * any split will produce two nonempty subboxes.) + * Note that lb value is max for lower box, so must be < old max. + */ + switch (n) { + case 0: + lb = (b1->c0max + b1->c0min) / 2; + b1->c0max = lb; + b2->c0min = lb+1; + break; + case 1: + lb = (b1->c1max + b1->c1min) / 2; + b1->c1max = lb; + b2->c1min = lb+1; + break; + case 2: + lb = (b1->c2max + b1->c2min) / 2; + b1->c2max = lb; + b2->c2min = lb+1; + break; + } + /* Update stats for boxes */ + update_box(cinfo, b1); + update_box(cinfo, b2); + numboxes++; + } + return numboxes; +} + + +LOCAL(void) +compute_color (j_decompress_ptr cinfo, boxptr boxp, int icolor) +/* Compute representative color for a box, put it in colormap[icolor] */ +{ + /* Current algorithm: mean weighted by pixels (not colors) */ + /* Note it is important to get the rounding correct! */ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + hist3d histogram = cquantize->histogram; + histptr histp; + int c0,c1,c2; + int c0min,c0max,c1min,c1max,c2min,c2max; + long count; + long total = 0; + long c0total = 0; + long c1total = 0; + long c2total = 0; + + c0min = boxp->c0min; c0max = boxp->c0max; + c1min = boxp->c1min; c1max = boxp->c1max; + c2min = boxp->c2min; c2max = boxp->c2max; + + for (c0 = c0min; c0 <= c0max; c0++) + for (c1 = c1min; c1 <= c1max; c1++) { + histp = & histogram[c0][c1][c2min]; + for (c2 = c2min; c2 <= c2max; c2++) { + if ((count = *histp++) != 0) { + total += count; + c0total += ((c0 << C0_SHIFT) + ((1<>1)) * count; + c1total += ((c1 << C1_SHIFT) + ((1<>1)) * count; + c2total += ((c2 << C2_SHIFT) + ((1<>1)) * count; + } + } + } + + cinfo->colormap[0][icolor] = (JSAMPLE) ((c0total + (total>>1)) / total); + cinfo->colormap[1][icolor] = (JSAMPLE) ((c1total + (total>>1)) / total); + cinfo->colormap[2][icolor] = (JSAMPLE) ((c2total + (total>>1)) / total); +} + + +LOCAL(void) +select_colors (j_decompress_ptr cinfo, int desired_colors) +/* Master routine for color selection */ +{ + boxptr boxlist; + int numboxes; + int i; + + /* Allocate workspace for box list */ + boxlist = (boxptr) (*cinfo->mem->alloc_small) + ((j_common_ptr) cinfo, JPOOL_IMAGE, (size_t)desired_colors * SIZEOF(box)); + /* Initialize one box containing whole space */ + numboxes = 1; + boxlist[0].c0min = 0; + boxlist[0].c0max = MAXJSAMPLE >> C0_SHIFT; + boxlist[0].c1min = 0; + boxlist[0].c1max = MAXJSAMPLE >> C1_SHIFT; + boxlist[0].c2min = 0; + boxlist[0].c2max = MAXJSAMPLE >> C2_SHIFT; + /* Shrink it to actually-used volume and set its statistics */ + update_box(cinfo, & boxlist[0]); + /* Perform median-cut to produce final box list */ + numboxes = median_cut(cinfo, boxlist, numboxes, desired_colors); + /* Compute the representative color for each box, fill colormap */ + for (i = 0; i < numboxes; i++) + compute_color(cinfo, & boxlist[i], i); + cinfo->actual_number_of_colors = numboxes; + TRACEMS1(cinfo, 1, JTRC_QUANT_SELECTED, numboxes); +} + + +/* + * These routines are concerned with the time-critical task of mapping input + * colors to the nearest color in the selected colormap. + * + * We re-use the histogram space as an "inverse color map", essentially a + * cache for the results of nearest-color searches. All colors within a + * histogram cell will be mapped to the same colormap entry, namely the one + * closest to the cell's center. This may not be quite the closest entry to + * the actual input color, but it's almost as good. A zero in the cache + * indicates we haven't found the nearest color for that cell yet; the array + * is cleared to zeroes before starting the mapping pass. When we find the + * nearest color for a cell, its colormap index plus one is recorded in the + * cache for future use. The pass2 scanning routines call fill_inverse_cmap + * when they need to use an unfilled entry in the cache. + * + * Our method of efficiently finding nearest colors is based on the "locally + * sorted search" idea described by Heckbert and on the incremental distance + * calculation described by Spencer W. Thomas in chapter III.1 of Graphics + * Gems II (James Arvo, ed. Academic Press, 1991). Thomas points out that + * the distances from a given colormap entry to each cell of the histogram can + * be computed quickly using an incremental method: the differences between + * distances to adjacent cells themselves differ by a constant. This allows a + * fairly fast implementation of the "brute force" approach of computing the + * distance from every colormap entry to every histogram cell. Unfortunately, + * it needs a work array to hold the best-distance-so-far for each histogram + * cell (because the inner loop has to be over cells, not colormap entries). + * The work array elements have to be IJG_INT32s, so the work array would need + * 256Kb at our recommended precision. This is not feasible in DOS machines. + * + * To get around these problems, we apply Thomas' method to compute the + * nearest colors for only the cells within a small subbox of the histogram. + * The work array need be only as big as the subbox, so the memory usage + * problem is solved. Furthermore, we need not fill subboxes that are never + * referenced in pass2; many images use only part of the color gamut, so a + * fair amount of work is saved. An additional advantage of this + * approach is that we can apply Heckbert's locality criterion to quickly + * eliminate colormap entries that are far away from the subbox; typically + * three-fourths of the colormap entries are rejected by Heckbert's criterion, + * and we need not compute their distances to individual cells in the subbox. + * The speed of this approach is heavily influenced by the subbox size: too + * small means too much overhead, too big loses because Heckbert's criterion + * can't eliminate as many colormap entries. Empirically the best subbox + * size seems to be about 1/512th of the histogram (1/8th in each direction). + * + * Thomas' article also describes a refined method which is asymptotically + * faster than the brute-force method, but it is also far more complex and + * cannot efficiently be applied to small subboxes. It is therefore not + * useful for programs intended to be portable to DOS machines. On machines + * with plenty of memory, filling the whole histogram in one shot with Thomas' + * refined method might be faster than the present code --- but then again, + * it might not be any faster, and it's certainly more complicated. + */ + + +/* log2(histogram cells in update box) for each axis; this can be adjusted */ +#define BOX_C0_LOG (HIST_C0_BITS-3) +#define BOX_C1_LOG (HIST_C1_BITS-3) +#define BOX_C2_LOG (HIST_C2_BITS-3) + +#define BOX_C0_ELEMS (1<actual_number_of_colors; + int maxc0, maxc1, maxc2; + int centerc0, centerc1, centerc2; + int i, x, ncolors; + IJG_INT32 minmaxdist, min_dist, max_dist, tdist; + IJG_INT32 mindist[MAXNUMCOLORS]; /* min distance to colormap entry i */ + + /* Compute true coordinates of update box's upper corner and center. + * Actually we compute the coordinates of the center of the upper-corner + * histogram cell, which are the upper bounds of the volume we care about. + * Note that since ">>" rounds down, the "center" values may be closer to + * min than to max; hence comparisons to them must be "<=", not "<". + */ + maxc0 = minc0 + ((1 << BOX_C0_SHIFT) - (1 << C0_SHIFT)); + centerc0 = (minc0 + maxc0) >> 1; + maxc1 = minc1 + ((1 << BOX_C1_SHIFT) - (1 << C1_SHIFT)); + centerc1 = (minc1 + maxc1) >> 1; + maxc2 = minc2 + ((1 << BOX_C2_SHIFT) - (1 << C2_SHIFT)); + centerc2 = (minc2 + maxc2) >> 1; + + /* For each color in colormap, find: + * 1. its minimum squared-distance to any point in the update box + * (zero if color is within update box); + * 2. its maximum squared-distance to any point in the update box. + * Both of these can be found by considering only the corners of the box. + * We save the minimum distance for each color in mindist[]; + * only the smallest maximum distance is of interest. + */ + minmaxdist = 0x7FFFFFFFL; + + for (i = 0; i < numcolors; i++) { + /* We compute the squared-c0-distance term, then add in the other two. */ + x = GETJSAMPLE(cinfo->colormap[0][i]); + if (x < minc0) { + tdist = (x - minc0) * C0_SCALE; + min_dist = tdist*tdist; + tdist = (x - maxc0) * C0_SCALE; + max_dist = tdist*tdist; + } else if (x > maxc0) { + tdist = (x - maxc0) * C0_SCALE; + min_dist = tdist*tdist; + tdist = (x - minc0) * C0_SCALE; + max_dist = tdist*tdist; + } else { + /* within cell range so no contribution to min_dist */ + min_dist = 0; + if (x <= centerc0) { + tdist = (x - maxc0) * C0_SCALE; + max_dist = tdist*tdist; + } else { + tdist = (x - minc0) * C0_SCALE; + max_dist = tdist*tdist; + } + } + + x = GETJSAMPLE(cinfo->colormap[1][i]); + if (x < minc1) { + tdist = (x - minc1) * C1_SCALE; + min_dist += tdist*tdist; + tdist = (x - maxc1) * C1_SCALE; + max_dist += tdist*tdist; + } else if (x > maxc1) { + tdist = (x - maxc1) * C1_SCALE; + min_dist += tdist*tdist; + tdist = (x - minc1) * C1_SCALE; + max_dist += tdist*tdist; + } else { + /* within cell range so no contribution to min_dist */ + if (x <= centerc1) { + tdist = (x - maxc1) * C1_SCALE; + max_dist += tdist*tdist; + } else { + tdist = (x - minc1) * C1_SCALE; + max_dist += tdist*tdist; + } + } + + x = GETJSAMPLE(cinfo->colormap[2][i]); + if (x < minc2) { + tdist = (x - minc2) * C2_SCALE; + min_dist += tdist*tdist; + tdist = (x - maxc2) * C2_SCALE; + max_dist += tdist*tdist; + } else if (x > maxc2) { + tdist = (x - maxc2) * C2_SCALE; + min_dist += tdist*tdist; + tdist = (x - minc2) * C2_SCALE; + max_dist += tdist*tdist; + } else { + /* within cell range so no contribution to min_dist */ + if (x <= centerc2) { + tdist = (x - maxc2) * C2_SCALE; + max_dist += tdist*tdist; + } else { + tdist = (x - minc2) * C2_SCALE; + max_dist += tdist*tdist; + } + } + + mindist[i] = min_dist; /* save away the results */ + if (max_dist < minmaxdist) + minmaxdist = max_dist; + } + + /* Now we know that no cell in the update box is more than minmaxdist + * away from some colormap entry. Therefore, only colors that are + * within minmaxdist of some part of the box need be considered. + */ + ncolors = 0; + for (i = 0; i < numcolors; i++) { + if (mindist[i] <= minmaxdist) + colorlist[ncolors++] = (JSAMPLE) i; + } + return ncolors; +} + + +LOCAL(void) +find_best_colors (j_decompress_ptr cinfo, int minc0, int minc1, int minc2, + int numcolors, JSAMPLE colorlist[], JSAMPLE bestcolor[]) +/* Find the closest colormap entry for each cell in the update box, + * given the list of candidate colors prepared by find_nearby_colors. + * Return the indexes of the closest entries in the bestcolor[] array. + * This routine uses Thomas' incremental distance calculation method to + * find the distance from a colormap entry to successive cells in the box. + */ +{ + int ic0, ic1, ic2; + int i, icolor; + register IJG_INT32 * bptr; /* pointer into bestdist[] array */ + JSAMPLE * cptr; /* pointer into bestcolor[] array */ + IJG_INT32 dist0, dist1; /* initial distance values */ + register IJG_INT32 dist2; /* current distance in inner loop */ + IJG_INT32 xx0, xx1; /* distance increments */ + register IJG_INT32 xx2; + IJG_INT32 inc0, inc1, inc2; /* initial values for increments */ + /* This array holds the distance to the nearest-so-far color for each cell */ + IJG_INT32 bestdist[BOX_C0_ELEMS * BOX_C1_ELEMS * BOX_C2_ELEMS]; + + /* Initialize best-distance for each cell of the update box */ + bptr = bestdist; + for (i = BOX_C0_ELEMS*BOX_C1_ELEMS*BOX_C2_ELEMS-1; i >= 0; i--) + *bptr++ = 0x7FFFFFFFL; + + /* For each color selected by find_nearby_colors, + * compute its distance to the center of each cell in the box. + * If that's less than best-so-far, update best distance and color number. + */ + + /* Nominal steps between cell centers ("x" in Thomas article) */ +#define STEP_C0 ((1 << C0_SHIFT) * C0_SCALE) +#define STEP_C1 ((1 << C1_SHIFT) * C1_SCALE) +#define STEP_C2 ((1 << C2_SHIFT) * C2_SCALE) + + for (i = 0; i < numcolors; i++) { + icolor = GETJSAMPLE(colorlist[i]); + /* Compute (square of) distance from minc0/c1/c2 to this color */ + inc0 = (minc0 - GETJSAMPLE(cinfo->colormap[0][icolor])) * C0_SCALE; + dist0 = inc0*inc0; + inc1 = (minc1 - GETJSAMPLE(cinfo->colormap[1][icolor])) * C1_SCALE; + dist0 += inc1*inc1; + inc2 = (minc2 - GETJSAMPLE(cinfo->colormap[2][icolor])) * C2_SCALE; + dist0 += inc2*inc2; + /* Form the initial difference increments */ + inc0 = inc0 * (2 * STEP_C0) + STEP_C0 * STEP_C0; + inc1 = inc1 * (2 * STEP_C1) + STEP_C1 * STEP_C1; + inc2 = inc2 * (2 * STEP_C2) + STEP_C2 * STEP_C2; + /* Now loop over all cells in box, updating distance per Thomas method */ + bptr = bestdist; + cptr = bestcolor; + xx0 = inc0; + for (ic0 = BOX_C0_ELEMS-1; ic0 >= 0; ic0--) { + dist1 = dist0; + xx1 = inc1; + for (ic1 = BOX_C1_ELEMS-1; ic1 >= 0; ic1--) { + dist2 = dist1; + xx2 = inc2; + for (ic2 = BOX_C2_ELEMS-1; ic2 >= 0; ic2--) { + if (dist2 < *bptr) { + *bptr = dist2; + *cptr = (JSAMPLE) icolor; + } + dist2 += xx2; + xx2 += 2 * STEP_C2 * STEP_C2; + bptr++; + cptr++; + } + dist1 += xx1; + xx1 += 2 * STEP_C1 * STEP_C1; + } + dist0 += xx0; + xx0 += 2 * STEP_C0 * STEP_C0; + } + } +} + + +LOCAL(void) +fill_inverse_cmap (j_decompress_ptr cinfo, int c0, int c1, int c2) +/* Fill the inverse-colormap entries in the update box that contains */ +/* histogram cell c0/c1/c2. (Only that one cell MUST be filled, but */ +/* we can fill as many others as we wish.) */ +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + hist3d histogram = cquantize->histogram; + int minc0, minc1, minc2; /* lower left corner of update box */ + int ic0, ic1, ic2; + register JSAMPLE * cptr; /* pointer into bestcolor[] array */ + register histptr cachep; /* pointer into main cache array */ + /* This array lists the candidate colormap indexes. */ + JSAMPLE colorlist[MAXNUMCOLORS]; + int numcolors; /* number of candidate colors */ + /* This array holds the actually closest colormap index for each cell. */ + JSAMPLE bestcolor[BOX_C0_ELEMS * BOX_C1_ELEMS * BOX_C2_ELEMS]; + + /* Convert cell coordinates to update box ID */ + c0 >>= BOX_C0_LOG; + c1 >>= BOX_C1_LOG; + c2 >>= BOX_C2_LOG; + + /* Compute true coordinates of update box's origin corner. + * Actually we compute the coordinates of the center of the corner + * histogram cell, which are the lower bounds of the volume we care about. + */ + minc0 = (c0 << BOX_C0_SHIFT) + ((1 << C0_SHIFT) >> 1); + minc1 = (c1 << BOX_C1_SHIFT) + ((1 << C1_SHIFT) >> 1); + minc2 = (c2 << BOX_C2_SHIFT) + ((1 << C2_SHIFT) >> 1); + + /* Determine which colormap entries are close enough to be candidates + * for the nearest entry to some cell in the update box. + */ + numcolors = find_nearby_colors(cinfo, minc0, minc1, minc2, colorlist); + + /* Determine the actually nearest colors. */ + find_best_colors(cinfo, minc0, minc1, minc2, numcolors, colorlist, + bestcolor); + + /* Save the best color numbers (plus 1) in the main cache array */ + c0 <<= BOX_C0_LOG; /* convert ID back to base cell indexes */ + c1 <<= BOX_C1_LOG; + c2 <<= BOX_C2_LOG; + cptr = bestcolor; + for (ic0 = 0; ic0 < BOX_C0_ELEMS; ic0++) { + for (ic1 = 0; ic1 < BOX_C1_ELEMS; ic1++) { + cachep = & histogram[c0+ic0][c1+ic1][c2]; + for (ic2 = 0; ic2 < BOX_C2_ELEMS; ic2++) { + *cachep++ = (histcell) (GETJSAMPLE(*cptr++) + 1); + } + } + } +} + + +/* + * Map some rows of pixels to the output colormapped representation. + */ + +METHODDEF(void) +pass2_no_dither (j_decompress_ptr cinfo, + JSAMPARRAY input_buf, JSAMPARRAY output_buf, int num_rows) +/* This version performs no dithering */ +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + hist3d histogram = cquantize->histogram; + register JSAMPROW inptr, outptr; + register histptr cachep; + register int c0, c1, c2; + int row; + JDIMENSION col; + JDIMENSION width = cinfo->output_width; + + for (row = 0; row < num_rows; row++) { + inptr = input_buf[row]; + outptr = output_buf[row]; + for (col = width; col > 0; col--) { + /* get pixel value and index into the cache */ + c0 = GETJSAMPLE(*inptr++) >> C0_SHIFT; + c1 = GETJSAMPLE(*inptr++) >> C1_SHIFT; + c2 = GETJSAMPLE(*inptr++) >> C2_SHIFT; + cachep = & histogram[c0][c1][c2]; + /* If we have not seen this color before, find nearest colormap entry */ + /* and update the cache */ + if (*cachep == 0) + fill_inverse_cmap(cinfo, c0,c1,c2); + /* Now emit the colormap index for this cell */ + *outptr++ = (JSAMPLE) (*cachep - 1); + } + } +} + + +METHODDEF(void) +pass2_fs_dither (j_decompress_ptr cinfo, + JSAMPARRAY input_buf, JSAMPARRAY output_buf, int num_rows) +/* This version performs Floyd-Steinberg dithering */ +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + hist3d histogram = cquantize->histogram; + register LOCFSERROR cur0, cur1, cur2; /* current error or pixel value */ + LOCFSERROR belowerr0, belowerr1, belowerr2; /* error for pixel below cur */ + LOCFSERROR bpreverr0, bpreverr1, bpreverr2; /* error for below/prev col */ + register FSERRPTR errorptr; /* => fserrors[] at column before current */ + JSAMPROW inptr; /* => current input pixel */ + JSAMPROW outptr; /* => current output pixel */ + histptr cachep; + int dir; /* +1 or -1 depending on direction */ + int dir3; /* 3*dir, for advancing inptr & errorptr */ + int row; + JDIMENSION col; + JDIMENSION width = cinfo->output_width; + JSAMPLE *range_limit = cinfo->sample_range_limit; + int *error_limit = cquantize->error_limiter; + JSAMPROW colormap0 = cinfo->colormap[0]; + JSAMPROW colormap1 = cinfo->colormap[1]; + JSAMPROW colormap2 = cinfo->colormap[2]; + SHIFT_TEMPS + + for (row = 0; row < num_rows; row++) { + inptr = input_buf[row]; + outptr = output_buf[row]; + if (cquantize->on_odd_row) { + /* work right to left in this row */ + inptr += (width-1) * 3; /* so point to rightmost pixel */ + outptr += width-1; + dir = -1; + dir3 = -3; + errorptr = cquantize->fserrors + (width+1)*3; /* => entry after last column */ + cquantize->on_odd_row = FALSE; /* flip for next time */ + } else { + /* work left to right in this row */ + dir = 1; + dir3 = 3; + errorptr = cquantize->fserrors; /* => entry before first real column */ + cquantize->on_odd_row = TRUE; /* flip for next time */ + } + /* Preset error values: no error propagated to first pixel from left */ + cur0 = cur1 = cur2 = 0; + /* and no error propagated to row below yet */ + belowerr0 = belowerr1 = belowerr2 = 0; + bpreverr0 = bpreverr1 = bpreverr2 = 0; + + for (col = width; col > 0; col--) { + /* curN holds the error propagated from the previous pixel on the + * current line. Add the error propagated from the previous line + * to form the complete error correction term for this pixel, and + * round the error term (which is expressed * 16) to an integer. + * RIGHT_SHIFT rounds towards minus infinity, so adding 8 is correct + * for either sign of the error value. + * Note: errorptr points to *previous* column's array entry. + */ + cur0 = RIGHT_SHIFT(cur0 + errorptr[dir3+0] + 8, 4); + cur1 = RIGHT_SHIFT(cur1 + errorptr[dir3+1] + 8, 4); + cur2 = RIGHT_SHIFT(cur2 + errorptr[dir3+2] + 8, 4); + /* Limit the error using transfer function set by init_error_limit. + * See comments with init_error_limit for rationale. + */ + cur0 = error_limit[cur0]; + cur1 = error_limit[cur1]; + cur2 = error_limit[cur2]; + /* Form pixel value + error, and range-limit to 0..MAXJSAMPLE. + * The maximum error is +- MAXJSAMPLE (or less with error limiting); + * this sets the required size of the range_limit array. + */ + cur0 += GETJSAMPLE(inptr[0]); + cur1 += GETJSAMPLE(inptr[1]); + cur2 += GETJSAMPLE(inptr[2]); + cur0 = GETJSAMPLE(range_limit[cur0]); + cur1 = GETJSAMPLE(range_limit[cur1]); + cur2 = GETJSAMPLE(range_limit[cur2]); + /* Index into the cache with adjusted pixel value */ + cachep = & histogram[cur0>>C0_SHIFT][cur1>>C1_SHIFT][cur2>>C2_SHIFT]; + /* If we have not seen this color before, find nearest colormap */ + /* entry and update the cache */ + if (*cachep == 0) + fill_inverse_cmap(cinfo, (int)(cur0>>C0_SHIFT),(int)(cur1>>C1_SHIFT),(int)(cur2>>C2_SHIFT)); + /* Now emit the colormap index for this cell */ + { register int pixcode = *cachep - 1; + *outptr = (JSAMPLE) pixcode; + /* Compute representation error for this pixel */ + cur0 -= GETJSAMPLE(colormap0[pixcode]); + cur1 -= GETJSAMPLE(colormap1[pixcode]); + cur2 -= GETJSAMPLE(colormap2[pixcode]); + } + /* Compute error fractions to be propagated to adjacent pixels. + * Add these into the running sums, and simultaneously shift the + * next-line error sums left by 1 column. + */ + { register LOCFSERROR bnexterr, delta; + + bnexterr = cur0; /* Process component 0 */ + delta = cur0 * 2; + cur0 += delta; /* form error * 3 */ + errorptr[0] = (FSERROR) (bpreverr0 + cur0); + cur0 += delta; /* form error * 5 */ + bpreverr0 = belowerr0 + cur0; + belowerr0 = bnexterr; + cur0 += delta; /* form error * 7 */ + bnexterr = cur1; /* Process component 1 */ + delta = cur1 * 2; + cur1 += delta; /* form error * 3 */ + errorptr[1] = (FSERROR) (bpreverr1 + cur1); + cur1 += delta; /* form error * 5 */ + bpreverr1 = belowerr1 + cur1; + belowerr1 = bnexterr; + cur1 += delta; /* form error * 7 */ + bnexterr = cur2; /* Process component 2 */ + delta = cur2 * 2; + cur2 += delta; /* form error * 3 */ + errorptr[2] = (FSERROR) (bpreverr2 + cur2); + cur2 += delta; /* form error * 5 */ + bpreverr2 = belowerr2 + cur2; + belowerr2 = bnexterr; + cur2 += delta; /* form error * 7 */ + } + /* At this point curN contains the 7/16 error value to be propagated + * to the next pixel on the current line, and all the errors for the + * next line have been shifted over. We are therefore ready to move on. + */ + inptr += dir3; /* Advance pixel pointers to next column */ + outptr += dir; + errorptr += dir3; /* advance errorptr to current column */ + } + /* Post-loop cleanup: we must unload the final error values into the + * final fserrors[] entry. Note we need not unload belowerrN because + * it is for the dummy column before or after the actual array. + */ + errorptr[0] = (FSERROR) bpreverr0; /* unload prev errs into array */ + errorptr[1] = (FSERROR) bpreverr1; + errorptr[2] = (FSERROR) bpreverr2; + } +} + + +/* + * Initialize the error-limiting transfer function (lookup table). + * The raw F-S error computation can potentially compute error values of up to + * +- MAXJSAMPLE. But we want the maximum correction applied to a pixel to be + * much less, otherwise obviously wrong pixels will be created. (Typical + * effects include weird fringes at color-area boundaries, isolated bright + * pixels in a dark area, etc.) The standard advice for avoiding this problem + * is to ensure that the "corners" of the color cube are allocated as output + * colors; then repeated errors in the same direction cannot cause cascading + * error buildup. However, that only prevents the error from getting + * completely out of hand; Aaron Giles reports that error limiting improves + * the results even with corner colors allocated. + * A simple clamping of the error values to about +- MAXJSAMPLE/8 works pretty + * well, but the smoother transfer function used below is even better. Thanks + * to Aaron Giles for this idea. + */ + +LOCAL(void) +init_error_limit (j_decompress_ptr cinfo) +/* Allocate and fill in the error_limiter table */ +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + int * table; + int in, out; + + table = (int *) (*cinfo->mem->alloc_small) + ((j_common_ptr) cinfo, JPOOL_IMAGE, (MAXJSAMPLE*2+1) * SIZEOF(int)); + table += MAXJSAMPLE; /* so can index -MAXJSAMPLE .. +MAXJSAMPLE */ + cquantize->error_limiter = table; + +#define STEPSIZE ((MAXJSAMPLE+1)/16) + /* Map errors 1:1 up to +- MAXJSAMPLE/16 */ + out = 0; + for (in = 0; in < STEPSIZE; in++, out++) { + table[in] = out; table[-in] = -out; + } + /* Map errors 1:2 up to +- 3*MAXJSAMPLE/16 */ + for (; in < STEPSIZE*3; in++, out += (in&1) ? 0 : 1) { + table[in] = out; table[-in] = -out; + } + /* Clamp the rest to final out value (which is (MAXJSAMPLE+1)/8) */ + for (; in <= MAXJSAMPLE; in++) { + table[in] = out; table[-in] = -out; + } +#undef STEPSIZE +} + + +/* + * Finish up at the end of each pass. + */ + +METHODDEF(void) +finish_pass1 (j_decompress_ptr cinfo) +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + + /* Select the representative colors and fill in cinfo->colormap */ + cinfo->colormap = cquantize->sv_colormap; + select_colors(cinfo, cquantize->desired); + /* Force next pass to zero the color index table */ + cquantize->needs_zeroed = TRUE; +} + + +METHODDEF(void) +finish_pass2 (j_decompress_ptr cinfo) +{ + /* no work */ +} + + +/* + * Initialize for each processing pass. + */ + +METHODDEF(void) +start_pass_2_quant (j_decompress_ptr cinfo, boolean is_pre_scan) +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + hist3d histogram = cquantize->histogram; + int i; + + /* Only F-S dithering or no dithering is supported. */ + /* If user asks for ordered dither, give him F-S. */ + if (cinfo->dither_mode != JDITHER_NONE) + cinfo->dither_mode = JDITHER_FS; + + if (is_pre_scan) { + /* Set up method pointers */ + cquantize->pub.color_quantize = prescan_quantize; + cquantize->pub.finish_pass = finish_pass1; + cquantize->needs_zeroed = TRUE; /* Always zero histogram */ + } else { + /* Set up method pointers */ + if (cinfo->dither_mode == JDITHER_FS) + cquantize->pub.color_quantize = pass2_fs_dither; + else + cquantize->pub.color_quantize = pass2_no_dither; + cquantize->pub.finish_pass = finish_pass2; + + /* Make sure color count is acceptable */ + i = cinfo->actual_number_of_colors; + if (i < 1) + ERREXIT1(cinfo, JERR_QUANT_FEW_COLORS, 1); + if (i > MAXNUMCOLORS) + ERREXIT1(cinfo, JERR_QUANT_MANY_COLORS, MAXNUMCOLORS); + + if (cinfo->dither_mode == JDITHER_FS) { + size_t arraysize = (size_t) ((cinfo->output_width + 2) * + (3 * SIZEOF(FSERROR))); + /* Allocate Floyd-Steinberg workspace if we didn't already. */ + if (cquantize->fserrors == NULL) + cquantize->fserrors = (FSERRPTR) (*cinfo->mem->alloc_large) + ((j_common_ptr) cinfo, JPOOL_IMAGE, arraysize); + /* Initialize the propagated errors to zero. */ + jzero_far((void FAR *) cquantize->fserrors, arraysize); + /* Make the error-limit table if we didn't already. */ + if (cquantize->error_limiter == NULL) + init_error_limit(cinfo); + cquantize->on_odd_row = FALSE; + } + + } + /* Zero the histogram or inverse color map, if necessary */ + if (cquantize->needs_zeroed) { + for (i = 0; i < HIST_C0_ELEMS; i++) { + jzero_far((void FAR *) histogram[i], + HIST_C1_ELEMS*HIST_C2_ELEMS * SIZEOF(histcell)); + } + cquantize->needs_zeroed = FALSE; + } +} + + +/* + * Switch to a new external colormap between output passes. + */ + +METHODDEF(void) +new_color_map_2_quant (j_decompress_ptr cinfo) +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + + /* Reset the inverse color map */ + cquantize->needs_zeroed = TRUE; +} + + +/* + * Module initialization routine for 2-pass color quantization. + */ + +GLOBAL(void) +jinit_2pass_quantizer (j_decompress_ptr cinfo) +{ + my_cquantize_ptr cquantize; + int i; + + cquantize = (my_cquantize_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_cquantizer)); + cinfo->cquantize = (struct jpeg_color_quantizer *) cquantize; + cquantize->pub.start_pass = start_pass_2_quant; + cquantize->pub.new_color_map = new_color_map_2_quant; + cquantize->fserrors = NULL; /* flag optional arrays not allocated */ + cquantize->error_limiter = NULL; + + /* Make sure jdmaster didn't give me a case I can't handle */ + if (cinfo->out_color_components != 3) + ERREXIT(cinfo, JERR_NOTIMPL); + + /* Allocate the histogram/inverse colormap storage */ + cquantize->histogram = (hist3d) (*cinfo->mem->alloc_small) + ((j_common_ptr) cinfo, JPOOL_IMAGE, HIST_C0_ELEMS * SIZEOF(hist2d)); + for (i = 0; i < HIST_C0_ELEMS; i++) { + cquantize->histogram[i] = (hist2d) (*cinfo->mem->alloc_large) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + HIST_C1_ELEMS*HIST_C2_ELEMS * SIZEOF(histcell)); + } + cquantize->needs_zeroed = TRUE; /* histogram is garbage now */ + + /* Allocate storage for the completed colormap, if required. + * We do this now since it is FAR storage and may affect + * the memory manager's space calculations. + */ + if (cinfo->enable_2pass_quant) { + /* Make sure color count is acceptable */ + int desired = cinfo->desired_number_of_colors; + /* Lower bound on # of colors ... somewhat arbitrary as long as > 0 */ + if (desired < 8) + ERREXIT1(cinfo, JERR_QUANT_FEW_COLORS, 8); + /* Make sure colormap indexes can be represented by JSAMPLEs */ + if (desired > MAXNUMCOLORS) + ERREXIT1(cinfo, JERR_QUANT_MANY_COLORS, MAXNUMCOLORS); + cquantize->sv_colormap = (*cinfo->mem->alloc_sarray) + ((j_common_ptr) cinfo,JPOOL_IMAGE, (JDIMENSION) desired, (JDIMENSION) 3); + cquantize->desired = desired; + } else + cquantize->sv_colormap = NULL; + + /* Only F-S dithering or no dithering is supported. */ + /* If user asks for ordered dither, give him F-S. */ + if (cinfo->dither_mode != JDITHER_NONE) + cinfo->dither_mode = JDITHER_FS; + + /* Allocate Floyd-Steinberg workspace if necessary. + * This isn't really needed until pass 2, but again it is FAR storage. + * Although we will cope with a later change in dither_mode, + * we do not promise to honor max_memory_to_use if dither_mode changes. + */ + if (cinfo->dither_mode == JDITHER_FS) { + cquantize->fserrors = (FSERRPTR) (*cinfo->mem->alloc_large) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + (size_t) ((cinfo->output_width + 2) * (3 * SIZEOF(FSERROR)))); + /* Might as well create the error-limiting table too. */ + init_error_limit(cinfo); + } +} + +#endif /* QUANT_2PASS_SUPPORTED */ diff --git a/dcmjpeg/libijg12/jutils.c b/dcmjpeg/libijg12/jutils.c new file mode 100644 index 00000000..8eaa8e97 --- /dev/null +++ b/dcmjpeg/libijg12/jutils.c @@ -0,0 +1,179 @@ +/* + * jutils.c + * + * Copyright (C) 1991-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains tables and miscellaneous utility routines needed + * for both compression and decompression. + * Note we prefix all global names with "j" to minimize conflicts with + * a surrounding application. + */ + +#define JPEG_INTERNALS +#include "jinclude12.h" +#include "jpeglib12.h" + + +/* + * jpeg_zigzag_order[i] is the zigzag-order position of the i'th element + * of a DCT block read in natural order (left to right, top to bottom). + */ + +#if 0 /* This table is not actually needed in v6a */ + +const int jpeg_zigzag_order[DCTSIZE2] = { + 0, 1, 5, 6, 14, 15, 27, 28, + 2, 4, 7, 13, 16, 26, 29, 42, + 3, 8, 12, 17, 25, 30, 41, 43, + 9, 11, 18, 24, 31, 40, 44, 53, + 10, 19, 23, 32, 39, 45, 52, 54, + 20, 22, 33, 38, 46, 51, 55, 60, + 21, 34, 37, 47, 50, 56, 59, 61, + 35, 36, 48, 49, 57, 58, 62, 63 +}; + +#endif + +/* + * jpeg_natural_order[i] is the natural-order position of the i'th element + * of zigzag order. + * + * When reading corrupted data, the Huffman decoders could attempt + * to reference an entry beyond the end of this array (if the decoded + * zero run length reaches past the end of the block). To prevent + * wild stores without adding an inner-loop test, we put some extra + * "63"s after the real entries. This will cause the extra coefficient + * to be stored in location 63 of the block, not somewhere random. + * The worst case would be a run-length of 15, which means we need 16 + * fake entries. + */ + +const int jpeg_natural_order[DCTSIZE2+16] = { + 0, 1, 8, 16, 9, 2, 3, 10, + 17, 24, 32, 25, 18, 11, 4, 5, + 12, 19, 26, 33, 40, 48, 41, 34, + 27, 20, 13, 6, 7, 14, 21, 28, + 35, 42, 49, 56, 57, 50, 43, 36, + 29, 22, 15, 23, 30, 37, 44, 51, + 58, 59, 52, 45, 38, 31, 39, 46, + 53, 60, 61, 54, 47, 55, 62, 63, + 63, 63, 63, 63, 63, 63, 63, 63, /* extra entries for safety in decoder */ + 63, 63, 63, 63, 63, 63, 63, 63 +}; + + +/* + * Arithmetic utilities + */ + +GLOBAL(long) +jdiv_round_up (long a, long b) +/* Compute a/b rounded up to next integer, ie, ceil(a/b) */ +/* Assumes a >= 0, b > 0 */ +{ + return (a + b - 1L) / b; +} + + +GLOBAL(long) +jround_up (long a, long b) +/* Compute a rounded up to next multiple of b, ie, ceil(a/b)*b */ +/* Assumes a >= 0, b > 0 */ +{ + a += b - 1L; + return a - (a % b); +} + + +/* On normal machines we can apply MEMCOPY() and MEMZERO() to sample arrays + * and coefficient-block arrays. This won't work on 80x86 because the arrays + * are FAR and we're assuming a small-pointer memory model. However, some + * DOS compilers provide far-pointer versions of memcpy() and memset() even + * in the small-model libraries. These will be used if USE_FMEM is defined. + * Otherwise, the routines below do it the hard way. (The performance cost + * is not all that great, because these routines aren't very heavily used.) + */ + +#ifndef NEED_FAR_POINTERS /* normal case, same as regular macros */ +#define FMEMCOPY(dest,src,size) MEMCOPY(dest,src,size) +#define FMEMZERO(target,size) MEMZERO(target,size) +#else /* 80x86 case, define if we can */ +#ifdef USE_FMEM +#define FMEMCOPY(dest,src,size) _fmemcpy((void FAR *)(dest), (const void FAR *)(src), (size_t)(size)) +#define FMEMZERO(target,size) _fmemset((void FAR *)(target), 0, (size_t)(size)) +#endif +#endif + + +GLOBAL(void) +jcopy_sample_rows (JSAMPARRAY input_array, int source_row, + JSAMPARRAY output_array, int dest_row, + int num_rows, JDIMENSION num_cols) +/* Copy some rows of samples from one place to another. + * num_rows rows are copied from input_array[source_row++] + * to output_array[dest_row++]; these areas may overlap for duplication. + * The source and destination arrays must be at least as wide as num_cols. + */ +{ + register JSAMPROW inptr, outptr; +#ifdef FMEMCOPY + register size_t count = (size_t) (num_cols * SIZEOF(JSAMPLE)); +#else + register JDIMENSION count; +#endif + register int row; + + input_array += source_row; + output_array += dest_row; + + for (row = num_rows; row > 0; row--) { + inptr = *input_array++; + outptr = *output_array++; +#ifdef FMEMCOPY + FMEMCOPY(outptr, inptr, count); +#else + for (count = num_cols; count > 0; count--) + *outptr++ = *inptr++; /* needn't bother with GETJSAMPLE() here */ +#endif + } +} + + +GLOBAL(void) +jcopy_block_row (JBLOCKROW input_row, JBLOCKROW output_row, + JDIMENSION num_blocks) +/* Copy a row of coefficient blocks from one place to another. */ +{ +#ifdef FMEMCOPY + FMEMCOPY(output_row, input_row, num_blocks * (DCTSIZE2 * SIZEOF(JCOEF))); +#else + register JCOEFPTR inptr, outptr; + register long count; + + inptr = (JCOEFPTR) input_row; + outptr = (JCOEFPTR) output_row; + for (count = (long) num_blocks * DCTSIZE2; count > 0; count--) { + *outptr++ = *inptr++; + } +#endif +} + + +GLOBAL(void) +jzero_far (void FAR * target, size_t bytestozero) +/* Zero out a chunk of FAR memory. */ +/* This might be sample-array data, block-array data, or alloc_large data. */ +{ +#ifdef FMEMZERO + FMEMZERO(target, bytestozero); +#else + register char FAR * ptr = (char FAR *) target; + register size_t count; + + for (count = bytestozero; count > 0; count--) { + *ptr++ = 0; + } +#endif +} diff --git a/dcmjpeg/libijg12/jversion12.h b/dcmjpeg/libijg12/jversion12.h new file mode 100644 index 00000000..6472c58d --- /dev/null +++ b/dcmjpeg/libijg12/jversion12.h @@ -0,0 +1,14 @@ +/* + * jversion.h + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains software version identification. + */ + + +#define JVERSION "6b 27-Mar-1998" + +#define JCOPYRIGHT "Copyright (C) 1998, Thomas G. Lane" diff --git a/dcmjpeg/libijg16/CMakeLists.txt b/dcmjpeg/libijg16/CMakeLists.txt new file mode 100644 index 00000000..ad532fe6 --- /dev/null +++ b/dcmjpeg/libijg16/CMakeLists.txt @@ -0,0 +1,2 @@ +# create library from source files +DCMTK_ADD_LIBRARY(ijg16 jaricom jcapimin jcapistd jcarith jccoefct jccolor jcdctmgr jcdiffct jchuff jcinit jclhuff jclossls jclossy jcmainct jcmarker jcmaster jcodec jcomapi jcparam jcphuff jcpred jcprepct jcsample jcscale jcshuff jctrans jdapimin jdapistd jdarith jdatadst jdatasrc jdcoefct jdcolor jddctmgr jddiffct jdhuff jdinput jdlhuff jdlossls jdlossy jdmainct jdmarker jdmaster jdmerge jdphuff jdpostct jdpred jdsample jdscale jdshuff jdtrans jerror jfdctflt jfdctfst jfdctint jidctflt jidctfst jidctint jidctred jmemmgr jmemnobs jquant1 jquant2 jutils) diff --git a/dcmjpeg/libijg16/Makefile.dep b/dcmjpeg/libijg16/Makefile.dep new file mode 100644 index 00000000..286959d4 --- /dev/null +++ b/dcmjpeg/libijg16/Makefile.dep @@ -0,0 +1,227 @@ +jaricom.o: jaricom.c jinclude16.h jconfig16.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib16.h jmorecfg16.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint16.h jerror16.h +jcapimin.o: jcapimin.c jinclude16.h jconfig16.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib16.h jmorecfg16.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint16.h jerror16.h +jcapistd.o: jcapistd.c jinclude16.h jconfig16.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib16.h jmorecfg16.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint16.h jerror16.h +jcarith.o: jcarith.c jinclude16.h jconfig16.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib16.h jmorecfg16.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint16.h jerror16.h +jccoefct.o: jccoefct.c jinclude16.h jconfig16.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib16.h jmorecfg16.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint16.h jerror16.h \ + jlossy16.h +jccolor.o: jccolor.c jinclude16.h jconfig16.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib16.h jmorecfg16.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint16.h jerror16.h +jcdctmgr.o: jcdctmgr.c jinclude16.h jconfig16.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib16.h jmorecfg16.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint16.h jerror16.h \ + jlossy16.h jdct16.h +jcdiffct.o: jcdiffct.c jinclude16.h jconfig16.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib16.h jmorecfg16.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint16.h jerror16.h \ + jlossls16.h +jchuff.o: jchuff.c jinclude16.h jconfig16.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib16.h jmorecfg16.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint16.h jerror16.h \ + jchuff16.h +jcinit.o: jcinit.c jinclude16.h jconfig16.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib16.h jmorecfg16.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint16.h jerror16.h +jclhuff.o: jclhuff.c jinclude16.h jconfig16.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib16.h jmorecfg16.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint16.h jerror16.h \ + jlossls16.h jchuff16.h +jclossls.o: jclossls.c jinclude16.h jconfig16.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib16.h jmorecfg16.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint16.h jerror16.h \ + jlossls16.h +jclossy.o: jclossy.c jinclude16.h jconfig16.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib16.h jmorecfg16.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint16.h jerror16.h \ + jlossy16.h +jcmainct.o: jcmainct.c jinclude16.h jconfig16.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib16.h jmorecfg16.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint16.h jerror16.h +jcmarker.o: jcmarker.c jinclude16.h jconfig16.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib16.h jmorecfg16.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint16.h jerror16.h +jcmaster.o: jcmaster.c jinclude16.h jconfig16.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib16.h jmorecfg16.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint16.h jerror16.h \ + jlossy16.h +jcodec.o: jcodec.c jinclude16.h jconfig16.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib16.h jmorecfg16.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint16.h jerror16.h \ + jlossy16.h jlossls16.h +jcomapi.o: jcomapi.c jinclude16.h jconfig16.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib16.h jmorecfg16.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint16.h jerror16.h +jcparam.o: jcparam.c jinclude16.h jconfig16.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib16.h jmorecfg16.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint16.h jerror16.h +jcphuff.o: jcphuff.c jinclude16.h jconfig16.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib16.h jmorecfg16.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint16.h jerror16.h \ + jlossy16.h jchuff16.h +jcpred.o: jcpred.c jinclude16.h jconfig16.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib16.h jmorecfg16.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint16.h jerror16.h \ + jlossls16.h +jcprepct.o: jcprepct.c jinclude16.h jconfig16.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib16.h jmorecfg16.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint16.h jerror16.h +jcsample.o: jcsample.c jinclude16.h jconfig16.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib16.h jmorecfg16.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint16.h jerror16.h +jcscale.o: jcscale.c jinclude16.h jconfig16.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib16.h jmorecfg16.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint16.h jerror16.h \ + jlossls16.h +jcshuff.o: jcshuff.c jinclude16.h jconfig16.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib16.h jmorecfg16.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint16.h jerror16.h \ + jlossy16.h jchuff16.h +jctrans.o: jctrans.c jinclude16.h jconfig16.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib16.h jmorecfg16.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint16.h jerror16.h \ + jlossy16.h +jdapimin.o: jdapimin.c jinclude16.h jconfig16.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib16.h jmorecfg16.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint16.h jerror16.h +jdapistd.o: jdapistd.c jinclude16.h jconfig16.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib16.h jmorecfg16.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint16.h jerror16.h +jdarith.o: jdarith.c jinclude16.h jconfig16.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib16.h jmorecfg16.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint16.h jerror16.h +jdatadst.o: jdatadst.c jinclude16.h jconfig16.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib16.h jmorecfg16.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jerror16.h +jdatasrc.o: jdatasrc.c jinclude16.h jconfig16.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib16.h jmorecfg16.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jerror16.h +jdcoefct.o: jdcoefct.c jinclude16.h jconfig16.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib16.h jmorecfg16.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint16.h jerror16.h \ + jlossy16.h +jdcolor.o: jdcolor.c jinclude16.h jconfig16.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib16.h jmorecfg16.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint16.h jerror16.h +jddctmgr.o: jddctmgr.c jinclude16.h jconfig16.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib16.h jmorecfg16.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint16.h jerror16.h \ + jlossy16.h jdct16.h +jddiffct.o: jddiffct.c jinclude16.h jconfig16.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib16.h jmorecfg16.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint16.h jerror16.h \ + jlossls16.h +jdhuff.o: jdhuff.c jinclude16.h jconfig16.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib16.h jmorecfg16.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint16.h jerror16.h \ + jlossy16.h jlossls16.h jdhuff16.h +jdinput.o: jdinput.c jinclude16.h jconfig16.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib16.h jmorecfg16.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint16.h jerror16.h +jdlhuff.o: jdlhuff.c jinclude16.h jconfig16.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib16.h jmorecfg16.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint16.h jerror16.h \ + jlossls16.h jdhuff16.h +jdlossls.o: jdlossls.c jinclude16.h jconfig16.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib16.h jmorecfg16.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint16.h jerror16.h \ + jlossls16.h +jdlossy.o: jdlossy.c jinclude16.h jconfig16.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib16.h jmorecfg16.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint16.h jerror16.h \ + jlossy16.h +jdmainct.o: jdmainct.c jinclude16.h jconfig16.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib16.h jmorecfg16.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint16.h jerror16.h +jdmarker.o: jdmarker.c jinclude16.h jconfig16.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib16.h jmorecfg16.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint16.h jerror16.h +jdmaster.o: jdmaster.c jinclude16.h jconfig16.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib16.h jmorecfg16.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint16.h jerror16.h +jdmerge.o: jdmerge.c jinclude16.h jconfig16.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib16.h jmorecfg16.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint16.h jerror16.h +jdphuff.o: jdphuff.c jinclude16.h jconfig16.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib16.h jmorecfg16.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint16.h jerror16.h \ + jlossy16.h jdhuff16.h +jdpostct.o: jdpostct.c jinclude16.h jconfig16.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib16.h jmorecfg16.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint16.h jerror16.h +jdpred.o: jdpred.c jinclude16.h jconfig16.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib16.h jmorecfg16.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint16.h jerror16.h \ + jlossls16.h +jdsample.o: jdsample.c jinclude16.h jconfig16.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib16.h jmorecfg16.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint16.h jerror16.h +jdscale.o: jdscale.c jinclude16.h jconfig16.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib16.h jmorecfg16.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint16.h jerror16.h \ + jlossls16.h +jdshuff.o: jdshuff.c jinclude16.h jconfig16.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib16.h jmorecfg16.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint16.h jerror16.h \ + jlossy16.h jdhuff16.h +jdtrans.o: jdtrans.c jinclude16.h jconfig16.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib16.h jmorecfg16.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint16.h jerror16.h \ + jlossy16.h +jerror.o: jerror.c jinclude16.h jconfig16.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib16.h jmorecfg16.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jversion16.h jerror16.h +jfdctflt.o: jfdctflt.c jinclude16.h jconfig16.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib16.h jmorecfg16.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint16.h jerror16.h \ + jdct16.h +jfdctfst.o: jfdctfst.c jinclude16.h jconfig16.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib16.h jmorecfg16.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint16.h jerror16.h \ + jdct16.h +jfdctint.o: jfdctint.c jinclude16.h jconfig16.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib16.h jmorecfg16.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint16.h jerror16.h \ + jdct16.h +jidctflt.o: jidctflt.c jinclude16.h jconfig16.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib16.h jmorecfg16.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint16.h jerror16.h \ + jdct16.h +jidctfst.o: jidctfst.c jinclude16.h jconfig16.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib16.h jmorecfg16.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint16.h jerror16.h \ + jdct16.h +jidctint.o: jidctint.c jinclude16.h jconfig16.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib16.h jmorecfg16.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint16.h jerror16.h \ + jdct16.h +jidctred.o: jidctred.c jinclude16.h jconfig16.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib16.h jmorecfg16.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint16.h jerror16.h \ + jdct16.h +jmemmgr.o: jmemmgr.c jinclude16.h jconfig16.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib16.h jmorecfg16.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint16.h jerror16.h \ + jmemsys16.h +jmemnobs.o: jmemnobs.c jinclude16.h jconfig16.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib16.h jmorecfg16.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint16.h jerror16.h \ + jmemsys16.h +jquant1.o: jquant1.c jinclude16.h jconfig16.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib16.h jmorecfg16.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint16.h jerror16.h +jquant2.o: jquant2.c jinclude16.h jconfig16.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib16.h jmorecfg16.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint16.h jerror16.h +jutils.o: jutils.c jinclude16.h jconfig16.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib16.h jmorecfg16.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint16.h jerror16.h diff --git a/dcmjpeg/libijg16/Makefile.in b/dcmjpeg/libijg16/Makefile.in new file mode 100644 index 00000000..58085f03 --- /dev/null +++ b/dcmjpeg/libijg16/Makefile.in @@ -0,0 +1,59 @@ +# +# Makefile for dcmjpeg/libijg16 +# + +@SET_MAKE@ + +SHELL = /bin/sh +VPATH = @srcdir@:@top_srcdir@/include:@top_srcdir@/@configdir@/include +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +configdir = @top_srcdir@/@configdir@ + +include $(configdir)/@common_makefile@ + +ofstddir = $(top_srcdir)/../ofstd + +LOCALINCLUDES = -I$(ofstddir)/include +LOCALDEFS = -DWITH_ARITHMETIC_PATCH + +objs = jcomapi.o jcodec.o jutils.o jerror.o jmemmgr.o \ + jmemnobs.o jcapimin.o jcapistd.o jctrans.o jcparam.o \ + jdatadst.o jcinit.o jcmaster.o jcmarker.o jcmainct.o \ + jcprepct.o jclossls.o jclossy.o jccoefct.o jccolor.o \ + jcsample.o jchuff.o jcphuff.o jcshuff.o jclhuff.o \ + jcpred.o jcscale.o jcdiffct.o jcdctmgr.o jfdctfst.o \ + jfdctflt.o jfdctint.o jdapimin.o jdapistd.o jdtrans.o \ + jdatasrc.o jdmaster.o jdinput.o jdmarker.o jdlossls.o \ + jdlossy.o jdhuff.o jdlhuff.o jdphuff.o jdshuff.o \ + jdpred.o jdscale.o jddiffct.o jdmainct.o jdcoefct.o \ + jdpostct.o jddctmgr.o jidctfst.o jidctflt.o jidctint.o \ + jidctred.o jdsample.o jdcolor.o jquant1.o jquant2.o \ + jdmerge.o jcarith.o jdarith.o jaricom.o +library = libijg16.$(LIBEXT) + + +all: $(library) + +install: $(library) + $(configdir)/mkinstalldirs $(DESTDIR)$(libdir) + $(INSTALL_DATA) $(library) $(DESTDIR)$(libdir)/$(library) + $(RANLIB) $(DESTDIR)$(libdir)/$(library) + + +$(library): $(objs) + $(AR) $(ARFLAGS) $@ $(objs) + $(RANLIB) $@ + + +clean: + rm -f $(objs) $(library) $(TRASH) + +distclean: + rm -f $(objs) $(library) $(DISTTRASH) + + +dependencies: + $(CXX) -MM $(defines) $(includes) $(CPPFLAGS) $(CXXFLAGS) *.c > $(DEP) + +include $(DEP) diff --git a/dcmjpeg/libijg16/jaricom.c b/dcmjpeg/libijg16/jaricom.c new file mode 100644 index 00000000..77d4fdc0 --- /dev/null +++ b/dcmjpeg/libijg16/jaricom.c @@ -0,0 +1,15 @@ +/* + * jaricom.c + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file holds place for arithmetic entropy codec tables. + */ + +#define JPEG_INTERNALS +#include "jinclude16.h" +#include "jpeglib16.h" + +IJG_INT32 jaritab[1]; /* dummy table */ diff --git a/dcmjpeg/libijg16/jcapimin.c b/dcmjpeg/libijg16/jcapimin.c new file mode 100644 index 00000000..8cc77371 --- /dev/null +++ b/dcmjpeg/libijg16/jcapimin.c @@ -0,0 +1,280 @@ +/* + * jcapimin.c + * + * Copyright (C) 1994-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains application interface code for the compression half + * of the JPEG library. These are the "minimum" API routines that may be + * needed in either the normal full-compression case or the transcoding-only + * case. + * + * Most of the routines intended to be called directly by an application + * are in this file or in jcapistd.c. But also see jcparam.c for + * parameter-setup helper routines, jcomapi.c for routines shared by + * compression and decompression, and jctrans.c for the transcoding case. + */ + +#define JPEG_INTERNALS +#include "jinclude16.h" +#include "jpeglib16.h" + + +/* + * Initialization of a JPEG compression object. + * The error manager must already be set up (in case memory manager fails). + */ + +GLOBAL(void) +jpeg_CreateCompress (j_compress_ptr cinfo, int version, size_t structsize) +{ + int i; + + /* Guard against version mismatches between library and caller. */ + cinfo->mem = NULL; /* so jpeg_destroy knows mem mgr not called */ + if (version != JPEG_LIB_VERSION) + ERREXIT2(cinfo, JERR_BAD_LIB_VERSION, JPEG_LIB_VERSION, version); + if (structsize != SIZEOF(struct jpeg_compress_struct)) + ERREXIT2(cinfo, JERR_BAD_STRUCT_SIZE, + (int) SIZEOF(struct jpeg_compress_struct), (int) structsize); + + /* For debugging purposes, we zero the whole master structure. + * But the application has already set the err pointer, and may have set + * client_data, so we have to save and restore those fields. + * Note: if application hasn't set client_data, tools like Purify may + * complain here. + */ + { + struct jpeg_error_mgr * err = cinfo->err; + void * client_data = cinfo->client_data; /* ignore Purify complaint here */ + MEMZERO(cinfo, SIZEOF(struct jpeg_compress_struct)); + cinfo->err = err; + cinfo->client_data = client_data; + } + cinfo->is_decompressor = FALSE; + + /* Initialize a memory manager instance for this object */ + jinit_memory_mgr((j_common_ptr) cinfo); + + /* Zero out pointers to permanent structures. */ + cinfo->progress = NULL; + cinfo->dest = NULL; + + cinfo->comp_info = NULL; + + for (i = 0; i < NUM_QUANT_TBLS; i++) + cinfo->quant_tbl_ptrs[i] = NULL; + + for (i = 0; i < NUM_HUFF_TBLS; i++) { + cinfo->dc_huff_tbl_ptrs[i] = NULL; + cinfo->ac_huff_tbl_ptrs[i] = NULL; + } + + cinfo->script_space = NULL; + + cinfo->input_gamma = 1.0; /* in case application forgets */ + + /* OK, I'm ready */ + cinfo->global_state = CSTATE_START; +} + + +/* + * Destruction of a JPEG compression object + */ + +GLOBAL(void) +jpeg_destroy_compress (j_compress_ptr cinfo) +{ + jpeg_destroy((j_common_ptr) cinfo); /* use common routine */ +} + + +/* + * Abort processing of a JPEG compression operation, + * but don't destroy the object itself. + */ + +GLOBAL(void) +jpeg_abort_compress (j_compress_ptr cinfo) +{ + jpeg_abort((j_common_ptr) cinfo); /* use common routine */ +} + + +/* + * Forcibly suppress or un-suppress all quantization and Huffman tables. + * Marks all currently defined tables as already written (if suppress) + * or not written (if !suppress). This will control whether they get emitted + * by a subsequent jpeg_start_compress call. + * + * This routine is exported for use by applications that want to produce + * abbreviated JPEG datastreams. It logically belongs in jcparam.c, but + * since it is called by jpeg_start_compress, we put it here --- otherwise + * jcparam.o would be linked whether the application used it or not. + */ + +GLOBAL(void) +jpeg_suppress_tables (j_compress_ptr cinfo, boolean suppress) +{ + int i; + JQUANT_TBL * qtbl; + JHUFF_TBL * htbl; + + for (i = 0; i < NUM_QUANT_TBLS; i++) { + if ((qtbl = cinfo->quant_tbl_ptrs[i]) != NULL) + qtbl->sent_table = suppress; + } + + for (i = 0; i < NUM_HUFF_TBLS; i++) { + if ((htbl = cinfo->dc_huff_tbl_ptrs[i]) != NULL) + htbl->sent_table = suppress; + if ((htbl = cinfo->ac_huff_tbl_ptrs[i]) != NULL) + htbl->sent_table = suppress; + } +} + + +/* + * Finish JPEG compression. + * + * If a multipass operating mode was selected, this may do a great deal of + * work including most of the actual output. + */ + +GLOBAL(void) +jpeg_finish_compress (j_compress_ptr cinfo) +{ + JDIMENSION iMCU_row; + + if (cinfo->global_state == CSTATE_SCANNING || + cinfo->global_state == CSTATE_RAW_OK) { + /* Terminate first pass */ + if (cinfo->next_scanline < cinfo->image_height) + ERREXIT(cinfo, JERR_TOO_LITTLE_DATA); + (*cinfo->master->finish_pass) (cinfo); + } else if (cinfo->global_state != CSTATE_WRCOEFS) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + /* Perform any remaining passes */ + while (! cinfo->master->is_last_pass) { + (*cinfo->master->prepare_for_pass) (cinfo); + for (iMCU_row = 0; iMCU_row < cinfo->total_iMCU_rows; iMCU_row++) { + if (cinfo->progress != NULL) { + cinfo->progress->pass_counter = (long) iMCU_row; + cinfo->progress->pass_limit = (long) cinfo->total_iMCU_rows; + (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); + } + /* We bypass the main controller and invoke coef controller directly; + * all work is being done from the coefficient buffer. + */ + if (! (*cinfo->codec->compress_data) (cinfo, (JSAMPIMAGE) NULL)) + ERREXIT(cinfo, JERR_CANT_SUSPEND); + } + (*cinfo->master->finish_pass) (cinfo); + } + /* Write EOI, do final cleanup */ + (*cinfo->marker->write_file_trailer) (cinfo); + (*cinfo->dest->term_destination) (cinfo); + /* We can use jpeg_abort to release memory and reset global_state */ + jpeg_abort((j_common_ptr) cinfo); +} + + +/* + * Write a special marker. + * This is only recommended for writing COM or APPn markers. + * Must be called after jpeg_start_compress() and before + * first call to jpeg_write_scanlines() or jpeg_write_raw_data(). + */ + +GLOBAL(void) +jpeg_write_marker (j_compress_ptr cinfo, int marker, + const JOCTET *dataptr, unsigned int datalen) +{ + JMETHOD(void, write_marker_byte, (j_compress_ptr info, int val)); + + if (cinfo->next_scanline != 0 || + (cinfo->global_state != CSTATE_SCANNING && + cinfo->global_state != CSTATE_RAW_OK && + cinfo->global_state != CSTATE_WRCOEFS)) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + + (*cinfo->marker->write_marker_header) (cinfo, marker, datalen); + write_marker_byte = cinfo->marker->write_marker_byte; /* copy for speed */ + while (datalen--) { + (*write_marker_byte) (cinfo, *dataptr); + dataptr++; + } +} + +/* Same, but piecemeal. */ + +GLOBAL(void) +jpeg_write_m_header (j_compress_ptr cinfo, int marker, unsigned int datalen) +{ + if (cinfo->next_scanline != 0 || + (cinfo->global_state != CSTATE_SCANNING && + cinfo->global_state != CSTATE_RAW_OK && + cinfo->global_state != CSTATE_WRCOEFS)) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + + (*cinfo->marker->write_marker_header) (cinfo, marker, datalen); +} + +GLOBAL(void) +jpeg_write_m_byte (j_compress_ptr cinfo, int val) +{ + (*cinfo->marker->write_marker_byte) (cinfo, val); +} + + +/* + * Alternate compression function: just write an abbreviated table file. + * Before calling this, all parameters and a data destination must be set up. + * + * To produce a pair of files containing abbreviated tables and abbreviated + * image data, one would proceed as follows: + * + * initialize JPEG object + * set JPEG parameters + * set destination to table file + * jpeg_write_tables(cinfo); + * set destination to image file + * jpeg_start_compress(cinfo, FALSE); + * write data... + * jpeg_finish_compress(cinfo); + * + * jpeg_write_tables has the side effect of marking all tables written + * (same as jpeg_suppress_tables(..., TRUE)). Thus a subsequent start_compress + * will not re-emit the tables unless it is passed write_all_tables=TRUE. + */ + +GLOBAL(void) +jpeg_write_tables (j_compress_ptr cinfo) +{ + if (cinfo->global_state != CSTATE_START) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + + /* (Re)initialize error mgr and destination modules */ + (*cinfo->err->reset_error_mgr) ((j_common_ptr) cinfo); + (*cinfo->dest->init_destination) (cinfo); + /* Initialize the marker writer ... bit of a crock to do it here. */ + jinit_marker_writer(cinfo); + /* Write them tables! */ + (*cinfo->marker->write_tables_only) (cinfo); + /* And clean up. */ + (*cinfo->dest->term_destination) (cinfo); + /* + * In library releases up through v6a, we called jpeg_abort() here to free + * any working memory allocated by the destination manager and marker + * writer. Some applications had a problem with that: they allocated space + * of their own from the library memory manager, and didn't want it to go + * away during write_tables. So now we do nothing. This will cause a + * memory leak if an app calls write_tables repeatedly without doing a full + * compression cycle or otherwise resetting the JPEG object. However, that + * seems less bad than unexpectedly freeing memory in the normal case. + * An app that prefers the old behavior can call jpeg_abort for itself after + * each call to jpeg_write_tables(). + */ +} diff --git a/dcmjpeg/libijg16/jcapistd.c b/dcmjpeg/libijg16/jcapistd.c new file mode 100644 index 00000000..a8e49a87 --- /dev/null +++ b/dcmjpeg/libijg16/jcapistd.c @@ -0,0 +1,161 @@ +/* + * jcapistd.c + * + * Copyright (C) 1994-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains application interface code for the compression half + * of the JPEG library. These are the "standard" API routines that are + * used in the normal full-compression case. They are not used by a + * transcoding-only application. Note that if an application links in + * jpeg_start_compress, it will end up linking in the entire compressor. + * We thus must separate this file from jcapimin.c to avoid linking the + * whole compression library into a transcoder. + */ + +#define JPEG_INTERNALS +#include "jinclude16.h" +#include "jpeglib16.h" + + +/* + * Compression initialization. + * Before calling this, all parameters and a data destination must be set up. + * + * We require a write_all_tables parameter as a failsafe check when writing + * multiple datastreams from the same compression object. Since prior runs + * will have left all the tables marked sent_table=TRUE, a subsequent run + * would emit an abbreviated stream (no tables) by default. This may be what + * is wanted, but for safety's sake it should not be the default behavior: + * programmers should have to make a deliberate choice to emit abbreviated + * images. Therefore the documentation and examples should encourage people + * to pass write_all_tables=TRUE; then it will take active thought to do the + * wrong thing. + */ + +GLOBAL(void) +jpeg_start_compress (j_compress_ptr cinfo, boolean write_all_tables) +{ + if (cinfo->global_state != CSTATE_START) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + + if (write_all_tables) + jpeg_suppress_tables(cinfo, FALSE); /* mark all tables to be written */ + + /* (Re)initialize error mgr and destination modules */ + (*cinfo->err->reset_error_mgr) ((j_common_ptr) cinfo); + (*cinfo->dest->init_destination) (cinfo); + /* Perform master selection of active modules */ + jinit_compress_master(cinfo); + /* Set up for the first pass */ + (*cinfo->master->prepare_for_pass) (cinfo); + /* Ready for application to drive first pass through jpeg_write_scanlines + * or jpeg_write_raw_data. + */ + cinfo->next_scanline = 0; + cinfo->global_state = (cinfo->raw_data_in ? CSTATE_RAW_OK : CSTATE_SCANNING); +} + + +/* + * Write some scanlines of data to the JPEG compressor. + * + * The return value will be the number of lines actually written. + * This should be less than the supplied num_lines only in case that + * the data destination module has requested suspension of the compressor, + * or if more than image_height scanlines are passed in. + * + * Note: we warn about excess calls to jpeg_write_scanlines() since + * this likely signals an application programmer error. However, + * excess scanlines passed in the last valid call are *silently* ignored, + * so that the application need not adjust num_lines for end-of-image + * when using a multiple-scanline buffer. + */ + +GLOBAL(JDIMENSION) +jpeg_write_scanlines (j_compress_ptr cinfo, JSAMPARRAY scanlines, + JDIMENSION num_lines) +{ + JDIMENSION row_ctr, rows_left; + + if (cinfo->global_state != CSTATE_SCANNING) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + if (cinfo->next_scanline >= cinfo->image_height) + WARNMS(cinfo, JWRN_TOO_MUCH_DATA); + + /* Call progress monitor hook if present */ + if (cinfo->progress != NULL) { + cinfo->progress->pass_counter = (long) cinfo->next_scanline; + cinfo->progress->pass_limit = (long) cinfo->image_height; + (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); + } + + /* Give master control module another chance if this is first call to + * jpeg_write_scanlines. This lets output of the frame/scan headers be + * delayed so that application can write COM, etc, markers between + * jpeg_start_compress and jpeg_write_scanlines. + */ + if (cinfo->master->call_pass_startup) + (*cinfo->master->pass_startup) (cinfo); + + /* Ignore any extra scanlines at bottom of image. */ + rows_left = cinfo->image_height - cinfo->next_scanline; + if (num_lines > rows_left) + num_lines = rows_left; + + row_ctr = 0; + (*cinfo->main->process_data) (cinfo, scanlines, &row_ctr, num_lines); + cinfo->next_scanline += row_ctr; + return row_ctr; +} + + +/* + * Alternate entry point to write raw data. + * Processes exactly one iMCU row per call, unless suspended. + */ + +GLOBAL(JDIMENSION) +jpeg_write_raw_data (j_compress_ptr cinfo, JSAMPIMAGE data, + JDIMENSION num_lines) +{ + JDIMENSION lines_per_iMCU_row; + + if (cinfo->global_state != CSTATE_RAW_OK) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + if (cinfo->next_scanline >= cinfo->image_height) { + WARNMS(cinfo, JWRN_TOO_MUCH_DATA); + return 0; + } + + /* Call progress monitor hook if present */ + if (cinfo->progress != NULL) { + cinfo->progress->pass_counter = (long) cinfo->next_scanline; + cinfo->progress->pass_limit = (long) cinfo->image_height; + (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); + } + + /* Give master control module another chance if this is first call to + * jpeg_write_raw_data. This lets output of the frame/scan headers be + * delayed so that application can write COM, etc, markers between + * jpeg_start_compress and jpeg_write_raw_data. + */ + if (cinfo->master->call_pass_startup) + (*cinfo->master->pass_startup) (cinfo); + + /* Verify that at least one iMCU row has been passed. */ + lines_per_iMCU_row = (JDIMENSION)(cinfo->max_v_samp_factor * cinfo->data_unit); + if (num_lines < lines_per_iMCU_row) + ERREXIT(cinfo, JERR_BUFFER_SIZE); + + /* Directly compress the row. */ + if (! (*cinfo->codec->compress_data) (cinfo, data)) { + /* If compressor did not consume the whole row, suspend processing. */ + return 0; + } + + /* OK, we processed one iMCU row. */ + cinfo->next_scanline += lines_per_iMCU_row; + return lines_per_iMCU_row; +} diff --git a/dcmjpeg/libijg16/jcarith.c b/dcmjpeg/libijg16/jcarith.c new file mode 100644 index 00000000..79109fd1 --- /dev/null +++ b/dcmjpeg/libijg16/jcarith.c @@ -0,0 +1,26 @@ +/* + * jcarith.c + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file holds place for arithmetic entropy encoding routines. + */ + +#define JPEG_INTERNALS +#include "jinclude16.h" +#include "jpeglib16.h" + + +/* + * Module initialization routine for arithmetic entropy encoding. + */ +GLOBAL(void) +jinit_arith_encoder (j_compress_ptr cinfo); + +GLOBAL(void) +jinit_arith_encoder (j_compress_ptr cinfo) +{ + ERREXIT(cinfo, JERR_ARITH_NOTIMPL); +} diff --git a/dcmjpeg/libijg16/jccoefct.c b/dcmjpeg/libijg16/jccoefct.c new file mode 100644 index 00000000..77f28d38 --- /dev/null +++ b/dcmjpeg/libijg16/jccoefct.c @@ -0,0 +1,454 @@ +/* + * jccoefct.c + * + * Copyright (C) 1994-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains the coefficient buffer controller for compression. + * This controller is the top level of the JPEG compressor proper. + * The coefficient buffer lies between forward-DCT and entropy encoding steps. + */ + +#define JPEG_INTERNALS +#include "jinclude16.h" +#include "jpeglib16.h" +#include "jlossy16.h" /* Private declarations for lossy codec */ + + +/* We use a full-image coefficient buffer when doing Huffman optimization, + * and also for writing multiple-scan JPEG files. In all cases, the DCT + * step is run during the first pass, and subsequent passes need only read + * the buffered coefficients. + */ +#ifdef ENTROPY_OPT_SUPPORTED +#define FULL_COEF_BUFFER_SUPPORTED +#else +#ifdef C_MULTISCAN_FILES_SUPPORTED +#define FULL_COEF_BUFFER_SUPPORTED +#endif +#endif + + +/* Private buffer controller object */ + +typedef struct { + JDIMENSION iMCU_row_num; /* iMCU row # within image */ + JDIMENSION mcu_ctr; /* counts MCUs processed in current row */ + int MCU_vert_offset; /* counts MCU rows within iMCU row */ + int MCU_rows_per_iMCU_row; /* number of such rows needed */ + + /* For single-pass compression, it's sufficient to buffer just one MCU + * (although this may prove a bit slow in practice). We allocate a + * workspace of C_MAX_DATA_UNITS_IN_MCU coefficient blocks, and reuse it for + * each MCU constructed and sent. (On 80x86, the workspace is FAR even + * though it's not really very big; this is to keep the module interfaces + * unchanged when a large coefficient buffer is necessary.) + * In multi-pass modes, this array points to the current MCU's blocks + * within the virtual arrays. + */ + JBLOCKROW MCU_buffer[C_MAX_DATA_UNITS_IN_MCU]; + + /* In multi-pass modes, we need a virtual block array for each component. */ + jvirt_barray_ptr whole_image[MAX_COMPONENTS]; +} c_coef_controller; + +typedef c_coef_controller * c_coef_ptr; + + +/* Forward declarations */ +METHODDEF(boolean) compress_data + JPP((j_compress_ptr cinfo, JSAMPIMAGE input_buf)); +#ifdef FULL_COEF_BUFFER_SUPPORTED +METHODDEF(boolean) compress_first_pass + JPP((j_compress_ptr cinfo, JSAMPIMAGE input_buf)); +METHODDEF(boolean) compress_output + JPP((j_compress_ptr cinfo, JSAMPIMAGE input_buf)); +#endif + + +LOCAL(void) +start_iMCU_row (j_compress_ptr cinfo) +/* Reset within-iMCU-row counters for a new row */ +{ + j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; + c_coef_ptr coef = (c_coef_ptr) lossyc->coef_private; + + /* In an interleaved scan, an MCU row is the same as an iMCU row. + * In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows. + * But at the bottom of the image, process only what's left. + */ + if (cinfo->comps_in_scan > 1) { + coef->MCU_rows_per_iMCU_row = 1; + } else { + if (coef->iMCU_row_num < (cinfo->total_iMCU_rows-1)) + coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->v_samp_factor; + else + coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->last_row_height; + } + + coef->mcu_ctr = 0; + coef->MCU_vert_offset = 0; +} + + +/* + * Initialize for a processing pass. + */ + +METHODDEF(void) +start_pass_coef (j_compress_ptr cinfo, J_BUF_MODE pass_mode) +{ + j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; + c_coef_ptr coef = (c_coef_ptr) lossyc->coef_private; + + coef->iMCU_row_num = 0; + start_iMCU_row(cinfo); + + switch (pass_mode) { + case JBUF_PASS_THRU: + if (coef->whole_image[0] != NULL) + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + lossyc->pub.compress_data = compress_data; + break; +#ifdef FULL_COEF_BUFFER_SUPPORTED + case JBUF_SAVE_AND_PASS: + if (coef->whole_image[0] == NULL) + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + lossyc->pub.compress_data = compress_first_pass; + break; + case JBUF_CRANK_DEST: + if (coef->whole_image[0] == NULL) + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + lossyc->pub.compress_data = compress_output; + break; +#endif + default: + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + break; + } +} + + +/* + * Process some data in the single-pass case. + * We process the equivalent of one fully interleaved MCU row ("iMCU" row) + * per call, ie, v_samp_factor block rows for each component in the image. + * Returns TRUE if the iMCU row is completed, FALSE if suspended. + * + * NB: input_buf contains a plane for each component in image, + * which we index according to the component's SOF position. + */ + +METHODDEF(boolean) +compress_data (j_compress_ptr cinfo, JSAMPIMAGE input_buf) +{ + j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; + c_coef_ptr coef = (c_coef_ptr) lossyc->coef_private; + JDIMENSION MCU_col_num; /* index of current MCU within row */ + JDIMENSION last_MCU_col = cinfo->MCUs_per_row - 1; + JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; + int blkn, bi, ci, yindex, yoffset, blockcnt; + JDIMENSION ypos, xpos; + jpeg_component_info *compptr; + + /* Loop to write as much as one whole iMCU row */ + for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row; + yoffset++) { + for (MCU_col_num = coef->mcu_ctr; MCU_col_num <= last_MCU_col; + MCU_col_num++) { + /* Determine where data comes from in input_buf and do the DCT thing. + * Each call on forward_DCT processes a horizontal row of DCT blocks + * as wide as an MCU; we rely on having allocated the MCU_buffer[] blocks + * sequentially. Dummy blocks at the right or bottom edge are filled in + * specially. The data in them does not matter for image reconstruction, + * so we fill them with values that will encode to the smallest amount of + * data, viz: all zeroes in the AC entries, DC entries equal to previous + * block's DC value. (Thanks to Thomas Kinsman for this idea.) + */ + blkn = 0; + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + blockcnt = (MCU_col_num < last_MCU_col) ? compptr->MCU_width + : compptr->last_col_width; + xpos = MCU_col_num * (JDIMENSION)compptr->MCU_sample_width; + ypos = (JDIMENSION)(yoffset * DCTSIZE); /* ypos == (yoffset+yindex) * DCTSIZE */ + for (yindex = 0; yindex < compptr->MCU_height; yindex++) { + if (coef->iMCU_row_num < last_iMCU_row || + yoffset+yindex < compptr->last_row_height) { + (*lossyc->fdct_forward_DCT) (cinfo, compptr, + input_buf[compptr->component_index], + coef->MCU_buffer[blkn], + ypos, xpos, (JDIMENSION) blockcnt); + if (blockcnt < compptr->MCU_width) { + /* Create some dummy blocks at the right edge of the image. */ + jzero_far((void FAR *) coef->MCU_buffer[blkn + blockcnt], + (size_t)(compptr->MCU_width - blockcnt) * SIZEOF(JBLOCK)); + for (bi = blockcnt; bi < compptr->MCU_width; bi++) { + coef->MCU_buffer[blkn+bi][0][0] = coef->MCU_buffer[blkn+bi-1][0][0]; + } + } + } else { + /* Create a row of dummy blocks at the bottom of the image. */ + jzero_far((void FAR *) coef->MCU_buffer[blkn], + (size_t)compptr->MCU_width * SIZEOF(JBLOCK)); + for (bi = 0; bi < compptr->MCU_width; bi++) { + coef->MCU_buffer[blkn+bi][0][0] = coef->MCU_buffer[blkn-1][0][0]; + } + } + blkn += compptr->MCU_width; + ypos += DCTSIZE; + } + } + /* Try to write the MCU. In event of a suspension failure, we will + * re-DCT the MCU on restart (a bit inefficient, could be fixed...) + */ + if (! (*lossyc->entropy_encode_mcu) (cinfo, coef->MCU_buffer)) { + /* Suspension forced; update state counters and exit */ + coef->MCU_vert_offset = yoffset; + coef->mcu_ctr = MCU_col_num; + return FALSE; + } + } + /* Completed an MCU row, but perhaps not an iMCU row */ + coef->mcu_ctr = 0; + } + /* Completed the iMCU row, advance counters for next one */ + coef->iMCU_row_num++; + start_iMCU_row(cinfo); + return TRUE; +} + + +#ifdef FULL_COEF_BUFFER_SUPPORTED + +/* + * Process some data in the first pass of a multi-pass case. + * We process the equivalent of one fully interleaved MCU row ("iMCU" row) + * per call, ie, v_samp_factor block rows for each component in the image. + * This amount of data is read from the source buffer, DCT'd and quantized, + * and saved into the virtual arrays. We also generate suitable dummy blocks + * as needed at the right and lower edges. (The dummy blocks are constructed + * in the virtual arrays, which have been padded appropriately.) This makes + * it possible for subsequent passes not to worry about real vs. dummy blocks. + * + * We must also emit the data to the entropy encoder. This is conveniently + * done by calling compress_output() after we've loaded the current strip + * of the virtual arrays. + * + * NB: input_buf contains a plane for each component in image. All + * components are DCT'd and loaded into the virtual arrays in this pass. + * However, it may be that only a subset of the components are emitted to + * the entropy encoder during this first pass; be careful about looking + * at the scan-dependent variables (MCU dimensions, etc). + */ + +METHODDEF(boolean) +compress_first_pass (j_compress_ptr cinfo, JSAMPIMAGE input_buf) +{ + j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; + c_coef_ptr coef = (c_coef_ptr) lossyc->coef_private; + JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; + JDIMENSION blocks_across, MCUs_across, MCUindex; + int bi, ci, h_samp_factor, block_row, block_rows, ndummy; + JCOEF lastDC; + jpeg_component_info *compptr; + JBLOCKARRAY buffer; + JBLOCKROW thisblockrow, lastblockrow; + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + /* Align the virtual buffer for this component. */ + buffer = (*cinfo->mem->access_virt_barray) + ((j_common_ptr) cinfo, coef->whole_image[ci], + coef->iMCU_row_num * (JDIMENSION)compptr->v_samp_factor, + (JDIMENSION)compptr->v_samp_factor, TRUE); + /* Count non-dummy DCT block rows in this iMCU row. */ + if (coef->iMCU_row_num < last_iMCU_row) + block_rows = compptr->v_samp_factor; + else { + /* NB: can't use last_row_height here, since may not be set! */ + block_rows = (int)compptr->height_in_data_units % compptr->v_samp_factor; + if (block_rows == 0) block_rows = compptr->v_samp_factor; + } + blocks_across = (JDIMENSION)compptr->width_in_data_units; + h_samp_factor = compptr->h_samp_factor; + /* Count number of dummy blocks to be added at the right margin. */ + ndummy = (int)blocks_across % h_samp_factor; + if (ndummy > 0) + ndummy = h_samp_factor - ndummy; + /* Perform DCT for all non-dummy blocks in this iMCU row. Each call + * on forward_DCT processes a complete horizontal row of DCT blocks. + */ + for (block_row = 0; block_row < block_rows; block_row++) { + thisblockrow = buffer[block_row]; + (*lossyc->fdct_forward_DCT) (cinfo, compptr, + input_buf[ci], thisblockrow, + (JDIMENSION) (block_row * DCTSIZE), + (JDIMENSION) 0, blocks_across); + if (ndummy > 0) { + /* Create dummy blocks at the right edge of the image. */ + thisblockrow += blocks_across; /* => first dummy block */ + jzero_far((void FAR *) thisblockrow, (size_t)ndummy * SIZEOF(JBLOCK)); + lastDC = thisblockrow[-1][0]; + for (bi = 0; bi < ndummy; bi++) { + thisblockrow[bi][0] = lastDC; + } + } + } + /* If at end of image, create dummy block rows as needed. + * The tricky part here is that within each MCU, we want the DC values + * of the dummy blocks to match the last real block's DC value. + * This squeezes a few more bytes out of the resulting file... + */ + if (coef->iMCU_row_num == last_iMCU_row) { + blocks_across += (JDIMENSION)ndummy; /* include lower right corner */ + MCUs_across = blocks_across / (JDIMENSION)h_samp_factor; + for (block_row = block_rows; block_row < compptr->v_samp_factor; + block_row++) { + thisblockrow = buffer[block_row]; + lastblockrow = buffer[block_row-1]; + jzero_far((void FAR *) thisblockrow, + (size_t) (blocks_across * SIZEOF(JBLOCK))); + for (MCUindex = 0; MCUindex < MCUs_across; MCUindex++) { + lastDC = lastblockrow[h_samp_factor-1][0]; + for (bi = 0; bi < h_samp_factor; bi++) { + thisblockrow[bi][0] = lastDC; + } + thisblockrow += h_samp_factor; /* advance to next MCU in row */ + lastblockrow += h_samp_factor; + } + } + } + } + /* NB: compress_output will increment iMCU_row_num if successful. + * A suspension return will result in redoing all the work above next time. + */ + + /* Emit data to the entropy encoder, sharing code with subsequent passes */ + return compress_output(cinfo, input_buf); +} + + +/* + * Process some data in subsequent passes of a multi-pass case. + * We process the equivalent of one fully interleaved MCU row ("iMCU" row) + * per call, ie, v_samp_factor block rows for each component in the scan. + * The data is obtained from the virtual arrays and fed to the entropy coder. + * Returns TRUE if the iMCU row is completed, FALSE if suspended. + * + * NB: input_buf is ignored; it is likely to be a NULL pointer. + */ + +METHODDEF(boolean) +compress_output (j_compress_ptr cinfo, JSAMPIMAGE input_buf) +{ + j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; + c_coef_ptr coef = (c_coef_ptr) lossyc->coef_private; + JDIMENSION MCU_col_num; /* index of current MCU within row */ + int blkn, ci, xindex, yindex, yoffset; + JDIMENSION start_col; + JBLOCKARRAY buffer[MAX_COMPS_IN_SCAN]; + JBLOCKROW buffer_ptr; + jpeg_component_info *compptr; + + /* Align the virtual buffers for the components used in this scan. + * NB: during first pass, this is safe only because the buffers will + * already be aligned properly, so jmemmgr.c won't need to do any I/O. + */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + buffer[ci] = (*cinfo->mem->access_virt_barray) + ((j_common_ptr) cinfo, coef->whole_image[compptr->component_index], + coef->iMCU_row_num * (JDIMENSION)compptr->v_samp_factor, + (JDIMENSION)compptr->v_samp_factor, FALSE); + } + + /* Loop to process one whole iMCU row */ + for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row; + yoffset++) { + for (MCU_col_num = coef->mcu_ctr; MCU_col_num < cinfo->MCUs_per_row; + MCU_col_num++) { + /* Construct list of pointers to DCT blocks belonging to this MCU */ + blkn = 0; /* index of current DCT block within MCU */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + start_col = MCU_col_num * (JDIMENSION)compptr->MCU_width; + for (yindex = 0; yindex < compptr->MCU_height; yindex++) { + buffer_ptr = buffer[ci][yindex+yoffset] + start_col; + for (xindex = 0; xindex < compptr->MCU_width; xindex++) { + coef->MCU_buffer[blkn++] = buffer_ptr++; + } + } + } + /* Try to write the MCU. */ + if (! (*lossyc->entropy_encode_mcu) (cinfo, coef->MCU_buffer)) { + /* Suspension forced; update state counters and exit */ + coef->MCU_vert_offset = yoffset; + coef->mcu_ctr = MCU_col_num; + return FALSE; + } + } + /* Completed an MCU row, but perhaps not an iMCU row */ + coef->mcu_ctr = 0; + } + /* Completed the iMCU row, advance counters for next one */ + coef->iMCU_row_num++; + start_iMCU_row(cinfo); + return TRUE; +} + +#endif /* FULL_COEF_BUFFER_SUPPORTED */ + + +/* + * Initialize coefficient buffer controller. + */ + +GLOBAL(void) +jinit_c_coef_controller (j_compress_ptr cinfo, boolean need_full_buffer) +{ + j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; + c_coef_ptr coef; + + coef = (c_coef_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(c_coef_controller)); + lossyc->coef_private = (struct jpeg_c_coef_controller *) coef; + lossyc->coef_start_pass = start_pass_coef; + + /* Create the coefficient buffer. */ + if (need_full_buffer) { +#ifdef FULL_COEF_BUFFER_SUPPORTED + /* Allocate a full-image virtual array for each component, */ + /* padded to a multiple of samp_factor DCT blocks in each direction. */ + int ci; + jpeg_component_info *compptr; + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + coef->whole_image[ci] = (*cinfo->mem->request_virt_barray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE, + (JDIMENSION) jround_up((long) compptr->width_in_data_units, + (long) compptr->h_samp_factor), + (JDIMENSION) jround_up((long) compptr->height_in_data_units, + (long) compptr->v_samp_factor), + (JDIMENSION) compptr->v_samp_factor); + } +#else + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); +#endif + } else { + /* We only need a single-MCU buffer. */ + JBLOCKROW buffer; + int i; + + buffer = (JBLOCKROW) + (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE, + C_MAX_DATA_UNITS_IN_MCU * SIZEOF(JBLOCK)); + for (i = 0; i < C_MAX_DATA_UNITS_IN_MCU; i++) { + coef->MCU_buffer[i] = buffer + i; + } + coef->whole_image[0] = NULL; /* flag for no virtual arrays */ + } +} diff --git a/dcmjpeg/libijg16/jccolor.c b/dcmjpeg/libijg16/jccolor.c new file mode 100644 index 00000000..55e484c8 --- /dev/null +++ b/dcmjpeg/libijg16/jccolor.c @@ -0,0 +1,470 @@ +/* + * jccolor.c + * + * Copyright (C) 1991-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains input colorspace conversion routines. + */ + +#define JPEG_INTERNALS +#include "jinclude16.h" +#include "jpeglib16.h" + + +/* Private subobject */ + +typedef struct { + struct jpeg_color_converter pub; /* public fields */ + + /* Private state for RGB->YCC conversion */ + IJG_INT32 * rgb_ycc_tab; /* => table for RGB to YCbCr conversion */ +} my_color_converter; + +typedef my_color_converter * my_cconvert_ptr; + + +/**************** RGB -> YCbCr conversion: most common case **************/ + +/* + * YCbCr is defined per CCIR 601-1, except that Cb and Cr are + * normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5. + * The conversion equations to be implemented are therefore + * Y = 0.29900 * R + 0.58700 * G + 0.11400 * B + * Cb = -0.16874 * R - 0.33126 * G + 0.50000 * B + CENTERJSAMPLE + * Cr = 0.50000 * R - 0.41869 * G - 0.08131 * B + CENTERJSAMPLE + * (These numbers are derived from TIFF 6.0 section 21, dated 3-June-92.) + * Note: older versions of the IJG code used a zero offset of MAXJSAMPLE/2, + * rather than CENTERJSAMPLE, for Cb and Cr. This gave equal positive and + * negative swings for Cb/Cr, but meant that grayscale values (Cb=Cr=0) + * were not represented exactly. Now we sacrifice exact representation of + * maximum red and maximum blue in order to get exact grayscales. + * + * To avoid floating-point arithmetic, we represent the fractional constants + * as integers scaled up by 2^16 (about 4 digits precision); we have to divide + * the products by 2^16, with appropriate rounding, to get the correct answer. + * + * For even more speed, we avoid doing any multiplications in the inner loop + * by precalculating the constants times R,G,B for all possible values. + * For 8-bit JSAMPLEs this is very reasonable (only 256 entries per table); + * for 12-bit samples it is still acceptable. It's not very reasonable for + * 16-bit samples, but if you want lossless storage you shouldn't be changing + * colorspace anyway. + * The CENTERJSAMPLE offsets and the rounding fudge-factor of 0.5 are included + * in the tables to save adding them separately in the inner loop. + */ + +/* + * SCALEBITS has been changed from 16 to 15 in this particular file. + * The problem is that for 16-bit images SCALEBITS=16 leads to an + * IJG_INT32 integer overflow in rgb_ycc_start(). + * SCALEBITS=15 avoids the overflow at the expense of precision + * and possibly a slight increase in CPU time. + * WARNING: This modification has not really been tested since + * we're never actually converting 16-bit images from RGB to YCC: + * 16-bit per pixel is used with lossless JPEG only, and we don't convert + * RGB to YCC in lossless mode. + */ +#define SCALEBITS 15 +#define CBCR_OFFSET ((IJG_INT32) CENTERJSAMPLE << SCALEBITS) +#define ONE_HALF ((IJG_INT32) 1 << (SCALEBITS-1)) +#define FIX(x) ((IJG_INT32) ((x) * (1L< Y section */ +#define G_Y_OFF (1*(MAXJSAMPLE+1)) /* offset to G => Y section */ +#define B_Y_OFF (2*(MAXJSAMPLE+1)) /* etc. */ +#define R_CB_OFF (3*(MAXJSAMPLE+1)) +#define G_CB_OFF (4*(MAXJSAMPLE+1)) +#define B_CB_OFF (5*(MAXJSAMPLE+1)) +#define R_CR_OFF B_CB_OFF /* B=>Cb, R=>Cr are the same */ +#define G_CR_OFF (6*(MAXJSAMPLE+1)) +#define B_CR_OFF (7*(MAXJSAMPLE+1)) +#define TABLE_SIZE (8*(MAXJSAMPLE+1)) + + +/* + * Initialize for RGB->YCC colorspace conversion. + */ + +METHODDEF(void) +rgb_ycc_start (j_compress_ptr cinfo) +{ + my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; + IJG_INT32 * rgb_ycc_tab; + IJG_INT32 i; + + /* Allocate and fill in the conversion tables. */ + cconvert->rgb_ycc_tab = rgb_ycc_tab = (IJG_INT32 *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (TABLE_SIZE * SIZEOF(IJG_INT32))); + + for (i = 0; i <= MAXJSAMPLE; i++) { + rgb_ycc_tab[i+R_Y_OFF] = FIX(0.29900) * i; + rgb_ycc_tab[i+G_Y_OFF] = FIX(0.58700) * i; + rgb_ycc_tab[i+B_Y_OFF] = FIX(0.11400) * i + ONE_HALF; + rgb_ycc_tab[i+R_CB_OFF] = (-FIX(0.16874)) * i; + rgb_ycc_tab[i+G_CB_OFF] = (-FIX(0.33126)) * i; + /* We use a rounding fudge-factor of 0.5-epsilon for Cb and Cr. + * This ensures that the maximum output will round to MAXJSAMPLE + * not MAXJSAMPLE+1, and thus that we don't have to range-limit. + */ + rgb_ycc_tab[i+B_CB_OFF] = FIX(0.50000) * i + CBCR_OFFSET + ONE_HALF-1; +/* B=>Cb and R=>Cr tables are the same + rgb_ycc_tab[i+R_CR_OFF] = FIX(0.50000) * i + CBCR_OFFSET + ONE_HALF-1; +*/ + rgb_ycc_tab[i+G_CR_OFF] = (-FIX(0.41869)) * i; + rgb_ycc_tab[i+B_CR_OFF] = (-FIX(0.08131)) * i; + } +} + + +/* + * Convert some rows of samples to the JPEG colorspace. + * + * Note that we change from the application's interleaved-pixel format + * to our internal noninterleaved, one-plane-per-component format. + * The input buffer is therefore three times as wide as the output buffer. + * + * A starting row offset is provided only for the output buffer. The caller + * can easily adjust the passed input_buf value to accommodate any row + * offset required on that side. + */ + +METHODDEF(void) +rgb_ycc_convert (j_compress_ptr cinfo, + JSAMPARRAY input_buf, JSAMPIMAGE output_buf, + JDIMENSION output_row, int num_rows) +{ + my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; + register int r, g, b; + register IJG_INT32 * ctab = cconvert->rgb_ycc_tab; + register JSAMPROW inptr; + register JSAMPROW outptr0, outptr1, outptr2; + register JDIMENSION col; + JDIMENSION num_cols = cinfo->image_width; + + while (--num_rows >= 0) { + inptr = *input_buf++; + outptr0 = output_buf[0][output_row]; + outptr1 = output_buf[1][output_row]; + outptr2 = output_buf[2][output_row]; + output_row++; + for (col = 0; col < num_cols; col++) { + r = GETJSAMPLE(inptr[RGB_RED]); + g = GETJSAMPLE(inptr[RGB_GREEN]); + b = GETJSAMPLE(inptr[RGB_BLUE]); + inptr += RGB_PIXELSIZE; + /* If the inputs are 0..MAXJSAMPLE, the outputs of these equations + * must be too; we do not need an explicit range-limiting operation. + * Hence the value being shifted is never negative, and we don't + * need the general RIGHT_SHIFT macro. + */ + /* Y */ + outptr0[col] = (JSAMPLE) + ((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF]) + >> SCALEBITS); + /* Cb */ + outptr1[col] = (JSAMPLE) + ((ctab[r+R_CB_OFF] + ctab[g+G_CB_OFF] + ctab[b+B_CB_OFF]) + >> SCALEBITS); + /* Cr */ + outptr2[col] = (JSAMPLE) + ((ctab[r+R_CR_OFF] + ctab[g+G_CR_OFF] + ctab[b+B_CR_OFF]) + >> SCALEBITS); + } + } +} + + +/**************** Cases other than RGB -> YCbCr **************/ + + +/* + * Convert some rows of samples to the JPEG colorspace. + * This version handles RGB->grayscale conversion, which is the same + * as the RGB->Y portion of RGB->YCbCr. + * We assume rgb_ycc_start has been called (we only use the Y tables). + */ + +METHODDEF(void) +rgb_gray_convert (j_compress_ptr cinfo, + JSAMPARRAY input_buf, JSAMPIMAGE output_buf, + JDIMENSION output_row, int num_rows) +{ + my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; + register int r, g, b; + register IJG_INT32 * ctab = cconvert->rgb_ycc_tab; + register JSAMPROW inptr; + register JSAMPROW outptr; + register JDIMENSION col; + JDIMENSION num_cols = cinfo->image_width; + + while (--num_rows >= 0) { + inptr = *input_buf++; + outptr = output_buf[0][output_row]; + output_row++; + for (col = 0; col < num_cols; col++) { + r = GETJSAMPLE(inptr[RGB_RED]); + g = GETJSAMPLE(inptr[RGB_GREEN]); + b = GETJSAMPLE(inptr[RGB_BLUE]); + inptr += RGB_PIXELSIZE; + /* Y */ + outptr[col] = (JSAMPLE) + ((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF]) + >> SCALEBITS); + } + } +} + + +/* + * Convert some rows of samples to the JPEG colorspace. + * This version handles Adobe-style CMYK->YCCK conversion, + * where we convert R=1-C, G=1-M, and B=1-Y to YCbCr using the same + * conversion as above, while passing K (black) unchanged. + * We assume rgb_ycc_start has been called. + */ + +METHODDEF(void) +cmyk_ycck_convert (j_compress_ptr cinfo, + JSAMPARRAY input_buf, JSAMPIMAGE output_buf, + JDIMENSION output_row, int num_rows) +{ + my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; + register int r, g, b; + register IJG_INT32 * ctab = cconvert->rgb_ycc_tab; + register JSAMPROW inptr; + register JSAMPROW outptr0, outptr1, outptr2, outptr3; + register JDIMENSION col; + JDIMENSION num_cols = cinfo->image_width; + + while (--num_rows >= 0) { + inptr = *input_buf++; + outptr0 = output_buf[0][output_row]; + outptr1 = output_buf[1][output_row]; + outptr2 = output_buf[2][output_row]; + outptr3 = output_buf[3][output_row]; + output_row++; + for (col = 0; col < num_cols; col++) { + r = MAXJSAMPLE - GETJSAMPLE(inptr[0]); + g = MAXJSAMPLE - GETJSAMPLE(inptr[1]); + b = MAXJSAMPLE - GETJSAMPLE(inptr[2]); + /* K passes through as-is */ + outptr3[col] = inptr[3]; /* don't need GETJSAMPLE here */ + inptr += 4; + /* If the inputs are 0..MAXJSAMPLE, the outputs of these equations + * must be too; we do not need an explicit range-limiting operation. + * Hence the value being shifted is never negative, and we don't + * need the general RIGHT_SHIFT macro. + */ + /* Y */ + outptr0[col] = (JSAMPLE) + ((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF]) + >> SCALEBITS); + /* Cb */ + outptr1[col] = (JSAMPLE) + ((ctab[r+R_CB_OFF] + ctab[g+G_CB_OFF] + ctab[b+B_CB_OFF]) + >> SCALEBITS); + /* Cr */ + outptr2[col] = (JSAMPLE) + ((ctab[r+R_CR_OFF] + ctab[g+G_CR_OFF] + ctab[b+B_CR_OFF]) + >> SCALEBITS); + } + } +} + + +/* + * Convert some rows of samples to the JPEG colorspace. + * This version handles grayscale output with no conversion. + * The source can be either plain grayscale or YCbCr (since Y == gray). + */ + +METHODDEF(void) +grayscale_convert (j_compress_ptr cinfo, + JSAMPARRAY input_buf, JSAMPIMAGE output_buf, + JDIMENSION output_row, int num_rows) +{ + register JSAMPROW inptr; + register JSAMPROW outptr; + register JDIMENSION col; + JDIMENSION num_cols = cinfo->image_width; + int instride = cinfo->input_components; + + while (--num_rows >= 0) { + inptr = *input_buf++; + outptr = output_buf[0][output_row]; + output_row++; + for (col = 0; col < num_cols; col++) { + outptr[col] = inptr[0]; /* don't need GETJSAMPLE() here */ + inptr += instride; + } + } +} + + +/* + * Convert some rows of samples to the JPEG colorspace. + * This version handles multi-component colorspaces without conversion. + * We assume input_components == num_components. + */ + +METHODDEF(void) +null_convert (j_compress_ptr cinfo, + JSAMPARRAY input_buf, JSAMPIMAGE output_buf, + JDIMENSION output_row, int num_rows) +{ + register JSAMPROW inptr; + register JSAMPROW outptr; + register JDIMENSION col; + register int ci; + int nc = cinfo->num_components; + JDIMENSION num_cols = cinfo->image_width; + + while (--num_rows >= 0) { + /* It seems fastest to make a separate pass for each component. */ + for (ci = 0; ci < nc; ci++) { + inptr = *input_buf; + outptr = output_buf[ci][output_row]; + for (col = 0; col < num_cols; col++) { + outptr[col] = inptr[ci]; /* don't need GETJSAMPLE() here */ + inptr += nc; + } + } + input_buf++; + output_row++; + } +} + + +/* + * Empty method for start_pass. + */ + +METHODDEF(void) +null_method (j_compress_ptr cinfo) +{ + /* no work needed */ +} + + +/* + * Module initialization routine for input colorspace conversion. + */ + +GLOBAL(void) +jinit_color_converter (j_compress_ptr cinfo) +{ + my_cconvert_ptr cconvert; + + cconvert = (my_cconvert_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_color_converter)); + cinfo->cconvert = (struct jpeg_color_converter *) cconvert; + /* set start_pass to null method until we find out differently */ + cconvert->pub.start_pass = null_method; + + /* Make sure input_components agrees with in_color_space */ + switch (cinfo->in_color_space) { + case JCS_GRAYSCALE: + if (cinfo->input_components != 1) + ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); + break; + + case JCS_RGB: +#if RGB_PIXELSIZE != 3 + if (cinfo->input_components != RGB_PIXELSIZE) + ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); + break; +#endif /* else share code with YCbCr */ + + case JCS_YCbCr: + if (cinfo->input_components != 3) + ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); + break; + + case JCS_CMYK: + case JCS_YCCK: + if (cinfo->input_components != 4) + ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); + break; + + default: /* JCS_UNKNOWN can be anything */ + if (cinfo->input_components < 1) + ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); + break; + } + + /* Check num_components, set conversion method based on requested space */ + switch (cinfo->jpeg_color_space) { + case JCS_GRAYSCALE: + if (cinfo->num_components != 1) + ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); + if (cinfo->in_color_space == JCS_GRAYSCALE) + cconvert->pub.color_convert = grayscale_convert; + else if (cinfo->in_color_space == JCS_RGB) { + cconvert->pub.start_pass = rgb_ycc_start; + cconvert->pub.color_convert = rgb_gray_convert; + } else if (cinfo->in_color_space == JCS_YCbCr) + cconvert->pub.color_convert = grayscale_convert; + else + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); + break; + + case JCS_RGB: + if (cinfo->num_components != 3) + ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); + if (cinfo->in_color_space == JCS_RGB && RGB_PIXELSIZE == 3) + cconvert->pub.color_convert = null_convert; + else + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); + break; + + case JCS_YCbCr: + if (cinfo->num_components != 3) + ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); + if (cinfo->in_color_space == JCS_RGB) { + cconvert->pub.start_pass = rgb_ycc_start; + cconvert->pub.color_convert = rgb_ycc_convert; + } else if (cinfo->in_color_space == JCS_YCbCr) + cconvert->pub.color_convert = null_convert; + else + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); + break; + + case JCS_CMYK: + if (cinfo->num_components != 4) + ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); + if (cinfo->in_color_space == JCS_CMYK) + cconvert->pub.color_convert = null_convert; + else + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); + break; + + case JCS_YCCK: + if (cinfo->num_components != 4) + ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); + if (cinfo->in_color_space == JCS_CMYK) { + cconvert->pub.start_pass = rgb_ycc_start; + cconvert->pub.color_convert = cmyk_ycck_convert; + } else if (cinfo->in_color_space == JCS_YCCK) + cconvert->pub.color_convert = null_convert; + else + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); + break; + + default: /* allow null conversion of JCS_UNKNOWN */ + if (cinfo->jpeg_color_space != cinfo->in_color_space || + cinfo->num_components != cinfo->input_components) + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); + cconvert->pub.color_convert = null_convert; + break; + } +} diff --git a/dcmjpeg/libijg16/jcdctmgr.c b/dcmjpeg/libijg16/jcdctmgr.c new file mode 100644 index 00000000..4211d611 --- /dev/null +++ b/dcmjpeg/libijg16/jcdctmgr.c @@ -0,0 +1,390 @@ +/* + * jcdctmgr.c + * + * Copyright (C) 1994-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains the forward-DCT management logic. + * This code selects a particular DCT implementation to be used, + * and it performs related housekeeping chores including coefficient + * quantization. + */ + +#define JPEG_INTERNALS +#include "jinclude16.h" +#include "jpeglib16.h" +#include "jlossy16.h" /* Private declarations for lossy codec */ +#include "jdct16.h" /* Private declarations for DCT subsystem */ + + +/* Private subobject for this module */ + +typedef struct { + /* Pointer to the DCT routine actually in use */ + forward_DCT_method_ptr do_dct; + + /* The actual post-DCT divisors --- not identical to the quant table + * entries, because of scaling (especially for an unnormalized DCT). + * Each table is given in normal array order. + */ + DCTELEM * divisors[NUM_QUANT_TBLS]; + +#ifdef DCT_FLOAT_SUPPORTED + /* Same as above for the floating-point case. */ + float_DCT_method_ptr do_float_dct; + FAST_FLOAT * float_divisors[NUM_QUANT_TBLS]; +#endif +} fdct_controller; + +typedef fdct_controller * fdct_ptr; + + +/* + * Initialize for a processing pass. + * Verify that all referenced Q-tables are present, and set up + * the divisor table for each one. + * In the current implementation, DCT of all components is done during + * the first pass, even if only some components will be output in the + * first scan. Hence all components should be examined here. + */ + +METHODDEF(void) +start_pass_fdctmgr (j_compress_ptr cinfo) +{ + j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; + fdct_ptr fdct = (fdct_ptr) lossyc->fdct_private; + int ci, qtblno, i; + jpeg_component_info *compptr; + JQUANT_TBL * qtbl; + DCTELEM * dtbl; + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + qtblno = compptr->quant_tbl_no; + /* Make sure specified quantization table is present */ + if (qtblno < 0 || qtblno >= NUM_QUANT_TBLS || + cinfo->quant_tbl_ptrs[qtblno] == NULL) + ERREXIT1(cinfo, JERR_NO_QUANT_TABLE, qtblno); + qtbl = cinfo->quant_tbl_ptrs[qtblno]; + /* Compute divisors for this quant table */ + /* We may do this more than once for same table, but it's not a big deal */ + switch (cinfo->dct_method) { +#ifdef DCT_ISLOW_SUPPORTED + case JDCT_ISLOW: + /* For LL&M IDCT method, divisors are equal to raw quantization + * coefficients multiplied by 8 (to counteract scaling). + */ + if (fdct->divisors[qtblno] == NULL) { + fdct->divisors[qtblno] = (DCTELEM *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + DCTSIZE2 * SIZEOF(DCTELEM)); + } + dtbl = fdct->divisors[qtblno]; + for (i = 0; i < DCTSIZE2; i++) { + dtbl[i] = ((DCTELEM) qtbl->quantval[i]) << 3; + } + break; +#endif +#ifdef DCT_IFAST_SUPPORTED + case JDCT_IFAST: + { + /* For AA&N IDCT method, divisors are equal to quantization + * coefficients scaled by scalefactor[row]*scalefactor[col], where + * scalefactor[0] = 1 + * scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7 + * We apply a further scale factor of 8. + */ +#define CONST_BITS 14 + static const INT16 aanscales[DCTSIZE2] = { + /* precomputed values scaled up by 14 bits */ + 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520, + 22725, 31521, 29692, 26722, 22725, 17855, 12299, 6270, + 21407, 29692, 27969, 25172, 21407, 16819, 11585, 5906, + 19266, 26722, 25172, 22654, 19266, 15137, 10426, 5315, + 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520, + 12873, 17855, 16819, 15137, 12873, 10114, 6967, 3552, + 8867, 12299, 11585, 10426, 8867, 6967, 4799, 2446, + 4520, 6270, 5906, 5315, 4520, 3552, 2446, 1247 + }; + SHIFT_TEMPS + + if (fdct->divisors[qtblno] == NULL) { + fdct->divisors[qtblno] = (DCTELEM *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + DCTSIZE2 * SIZEOF(DCTELEM)); + } + dtbl = fdct->divisors[qtblno]; + for (i = 0; i < DCTSIZE2; i++) { + dtbl[i] = (DCTELEM) + DESCALE(MULTIPLY16V16((IJG_INT32) qtbl->quantval[i], + (IJG_INT32) aanscales[i]), + CONST_BITS-3); + } + } + break; +#endif +#ifdef DCT_FLOAT_SUPPORTED + case JDCT_FLOAT: + { + /* For float AA&N IDCT method, divisors are equal to quantization + * coefficients scaled by scalefactor[row]*scalefactor[col], where + * scalefactor[0] = 1 + * scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7 + * We apply a further scale factor of 8. + * What's actually stored is 1/divisor so that the inner loop can + * use a multiplication rather than a division. + */ + FAST_FLOAT * fdtbl; + int row, col; + static const double aanscalefactor[DCTSIZE] = { + 1.0, 1.387039845, 1.306562965, 1.175875602, + 1.0, 0.785694958, 0.541196100, 0.275899379 + }; + + if (fdct->float_divisors[qtblno] == NULL) { + fdct->float_divisors[qtblno] = (FAST_FLOAT *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + DCTSIZE2 * SIZEOF(FAST_FLOAT)); + } + fdtbl = fdct->float_divisors[qtblno]; + i = 0; + for (row = 0; row < DCTSIZE; row++) { + for (col = 0; col < DCTSIZE; col++) { + fdtbl[i] = (FAST_FLOAT) + (1.0 / (((double) qtbl->quantval[i] * + aanscalefactor[row] * aanscalefactor[col] * 8.0))); + i++; + } + } + } + break; +#endif + default: + ERREXIT(cinfo, JERR_NOT_COMPILED); + break; + } + } +} + + +/* + * Perform forward DCT on one or more blocks of a component. + * + * The input samples are taken from the sample_data[] array starting at + * position start_row/start_col, and moving to the right for any additional + * blocks. The quantized coefficients are returned in coef_blocks[]. + */ + +METHODDEF(void) +forward_DCT (j_compress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY sample_data, JBLOCKROW coef_blocks, + JDIMENSION start_row, JDIMENSION start_col, + JDIMENSION num_blocks) +/* This version is used for integer DCT implementations. */ +{ + /* This routine is heavily used, so it's worth coding it tightly. */ + j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; + fdct_ptr fdct = (fdct_ptr) lossyc->fdct_private; + forward_DCT_method_ptr do_dct = fdct->do_dct; + DCTELEM * divisors = fdct->divisors[compptr->quant_tbl_no]; + DCTELEM workspace[DCTSIZE2]; /* work area for FDCT subroutine */ + JDIMENSION bi; + + sample_data += start_row; /* fold in the vertical offset once */ + + for (bi = 0; bi < num_blocks; bi++, start_col += DCTSIZE) { + /* Load data into workspace, applying unsigned->signed conversion */ + { register DCTELEM *workspaceptr; + register JSAMPROW elemptr; + register int elemr; + + workspaceptr = workspace; + for (elemr = 0; elemr < DCTSIZE; elemr++) { + elemptr = sample_data[elemr] + start_col; +#if DCTSIZE == 8 /* unroll the inner loop */ + *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; + *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; + *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; + *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; + *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; + *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; + *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; + *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; +#else + { register int elemc; + for (elemc = DCTSIZE; elemc > 0; elemc--) { + *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; + } + } +#endif + } + } + + /* Perform the DCT */ + (*do_dct) (workspace); + + /* Quantize/descale the coefficients, and store into coef_blocks[] */ + { register DCTELEM temp, qval; + register int i; + register JCOEFPTR output_ptr = coef_blocks[bi]; + + for (i = 0; i < DCTSIZE2; i++) { + qval = divisors[i]; + temp = workspace[i]; + /* Divide the coefficient value by qval, ensuring proper rounding. + * Since C does not specify the direction of rounding for negative + * quotients, we have to force the dividend positive for portability. + * + * In most files, at least half of the output values will be zero + * (at default quantization settings, more like three-quarters...) + * so we should ensure that this case is fast. On many machines, + * a comparison is enough cheaper than a divide to make a special test + * a win. Since both inputs will be nonnegative, we need only test + * for a < b to discover whether a/b is 0. + * If your machine's division is fast enough, define FAST_DIVIDE. + */ +#ifdef FAST_DIVIDE +#define DIVIDE_BY(a,b) a /= b +#else +#define DIVIDE_BY(a,b) if (a >= b) a /= b; else a = 0 +#endif + if (temp < 0) { + temp = -temp; + temp += qval>>1; /* for rounding */ + DIVIDE_BY(temp, qval); + temp = -temp; + } else { + temp += qval>>1; /* for rounding */ + DIVIDE_BY(temp, qval); + } + output_ptr[i] = (JCOEF) temp; + } + } + } +} + + +#ifdef DCT_FLOAT_SUPPORTED + +METHODDEF(void) +forward_DCT_float (j_compress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY sample_data, JBLOCKROW coef_blocks, + JDIMENSION start_row, JDIMENSION start_col, + JDIMENSION num_blocks) +/* This version is used for floating-point DCT implementations. */ +{ + /* This routine is heavily used, so it's worth coding it tightly. */ + j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; + fdct_ptr fdct = (fdct_ptr) lossyc->fdct_private; + float_DCT_method_ptr do_dct = fdct->do_float_dct; + FAST_FLOAT * divisors = fdct->float_divisors[compptr->quant_tbl_no]; + FAST_FLOAT workspace[DCTSIZE2]; /* work area for FDCT subroutine */ + JDIMENSION bi; + + sample_data += start_row; /* fold in the vertical offset once */ + + for (bi = 0; bi < num_blocks; bi++, start_col += DCTSIZE) { + /* Load data into workspace, applying unsigned->signed conversion */ + { register FAST_FLOAT *workspaceptr; + register JSAMPROW elemptr; + register int elemr; + + workspaceptr = workspace; + for (elemr = 0; elemr < DCTSIZE; elemr++) { + elemptr = sample_data[elemr] + start_col; +#if DCTSIZE == 8 /* unroll the inner loop */ + *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); + *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); + *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); + *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); + *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); + *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); + *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); + *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); +#else + { register int elemc; + for (elemc = DCTSIZE; elemc > 0; elemc--) { + *workspaceptr++ = (FAST_FLOAT) + (GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); + } + } +#endif + } + } + + /* Perform the DCT */ + (*do_dct) (workspace); + + /* Quantize/descale the coefficients, and store into coef_blocks[] */ + { register FAST_FLOAT temp; + register int i; + register JCOEFPTR output_ptr = coef_blocks[bi]; + + for (i = 0; i < DCTSIZE2; i++) { + /* Apply the quantization and scaling factor */ + temp = workspace[i] * divisors[i]; + /* Round to nearest integer. + * Since C does not specify the direction of rounding for negative + * quotients, we have to force the dividend positive for portability. + * The maximum coefficient size is +-16K (for 12-bit data), so this + * code should work for either 16-bit or 32-bit ints. + */ + output_ptr[i] = (JCOEF) ((int) (temp + (FAST_FLOAT) 16384.5) - 16384); + } + } + } +} + +#endif /* DCT_FLOAT_SUPPORTED */ + + +/* + * Initialize FDCT manager. + */ + +GLOBAL(void) +jinit_forward_dct (j_compress_ptr cinfo) +{ + j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; + fdct_ptr fdct; + int i; + + fdct = (fdct_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(fdct_controller)); + lossyc->fdct_private = (struct jpeg_forward_dct *) fdct; + lossyc->fdct_start_pass = start_pass_fdctmgr; + + switch (cinfo->dct_method) { +#ifdef DCT_ISLOW_SUPPORTED + case JDCT_ISLOW: + lossyc->fdct_forward_DCT = forward_DCT; + fdct->do_dct = jpeg_fdct_islow; + break; +#endif +#ifdef DCT_IFAST_SUPPORTED + case JDCT_IFAST: + lossyc->fdct_forward_DCT = forward_DCT; + fdct->do_dct = jpeg_fdct_ifast; + break; +#endif +#ifdef DCT_FLOAT_SUPPORTED + case JDCT_FLOAT: + lossyc->fdct_forward_DCT = forward_DCT_float; + fdct->do_float_dct = jpeg_fdct_float; + break; +#endif + default: + ERREXIT(cinfo, JERR_NOT_COMPILED); + break; + } + + /* Mark divisor tables unallocated */ + for (i = 0; i < NUM_QUANT_TBLS; i++) { + fdct->divisors[i] = NULL; +#ifdef DCT_FLOAT_SUPPORTED + fdct->float_divisors[i] = NULL; +#endif + } +} diff --git a/dcmjpeg/libijg16/jcdiffct.c b/dcmjpeg/libijg16/jcdiffct.c new file mode 100644 index 00000000..b0eebd10 --- /dev/null +++ b/dcmjpeg/libijg16/jcdiffct.c @@ -0,0 +1,406 @@ +/* + * jcdiffct.c + * + * Copyright (C) 1994-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains the difference buffer controller for compression. + * This controller is the top level of the lossless JPEG compressor proper. + * The difference buffer lies between prediction/differencing and entropy + * encoding. + */ + +#define JPEG_INTERNALS +#include "jinclude16.h" +#include "jpeglib16.h" +#include "jlossls16.h" /* Private declarations for lossless codec */ + + +#ifdef C_LOSSLESS_SUPPORTED + +/* We use a full-image sample buffer when doing Huffman optimization, + * and also for writing multiple-scan JPEG files. In all cases, the + * full-image buffer is filled during the first pass, and the scaling, + * prediction and differencing steps are run during subsequent passes. + */ +#ifdef ENTROPY_OPT_SUPPORTED +#define FULL_SAMP_BUFFER_SUPPORTED +#else +#ifdef C_MULTISCAN_FILES_SUPPORTED +#define FULL_SAMP_BUFFER_SUPPORTED +#endif +#endif + + +/* Private buffer controller object */ + +typedef struct { + JDIMENSION iMCU_row_num; /* iMCU row # within image */ + JDIMENSION mcu_ctr; /* counts MCUs processed in current row */ + int MCU_vert_offset; /* counts MCU rows within iMCU row */ + int MCU_rows_per_iMCU_row; /* number of such rows needed */ + + JSAMPROW cur_row[MAX_COMPONENTS]; /* row of point transformed samples */ + JSAMPROW prev_row[MAX_COMPONENTS]; /* previous row of Pt'd samples */ + JDIFFARRAY diff_buf[MAX_COMPONENTS]; /* iMCU row of differences */ + + /* In multi-pass modes, we need a virtual sample array for each component. */ + jvirt_sarray_ptr whole_image[MAX_COMPONENTS]; +} c_diff_controller; + +typedef c_diff_controller * c_diff_ptr; + + +/* Forward declarations */ +METHODDEF(boolean) compress_data + JPP((j_compress_ptr cinfo, JSAMPIMAGE input_buf)); +#ifdef FULL_SAMP_BUFFER_SUPPORTED +METHODDEF(boolean) compress_first_pass + JPP((j_compress_ptr cinfo, JSAMPIMAGE input_buf)); +METHODDEF(boolean) compress_output + JPP((j_compress_ptr cinfo, JSAMPIMAGE input_buf)); +#endif + + +LOCAL(void) +start_iMCU_row (j_compress_ptr cinfo) +/* Reset within-iMCU-row counters for a new row */ +{ + j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec; + c_diff_ptr diff = (c_diff_ptr) losslsc->diff_private; + + /* In an interleaved scan, an MCU row is the same as an iMCU row. + * In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows. + * But at the bottom of the image, process only what's left. + */ + if (cinfo->comps_in_scan > 1) { + diff->MCU_rows_per_iMCU_row = 1; + } else { + if (diff->iMCU_row_num < (cinfo->total_iMCU_rows-1)) + diff->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->v_samp_factor; + else + diff->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->last_row_height; + } + + diff->mcu_ctr = 0; + diff->MCU_vert_offset = 0; +} + + +/* + * Initialize for a processing pass. + */ + +METHODDEF(void) +start_pass_diff (j_compress_ptr cinfo, J_BUF_MODE pass_mode) +{ + j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec; + c_diff_ptr diff = (c_diff_ptr) losslsc->diff_private; + + diff->iMCU_row_num = 0; + start_iMCU_row(cinfo); + + switch (pass_mode) { + case JBUF_PASS_THRU: + if (diff->whole_image[0] != NULL) + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + losslsc->pub.compress_data = compress_data; + break; +#ifdef FULL_SAMP_BUFFER_SUPPORTED + case JBUF_SAVE_AND_PASS: + if (diff->whole_image[0] == NULL) + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + losslsc->pub.compress_data = compress_first_pass; + break; + case JBUF_CRANK_DEST: + if (diff->whole_image[0] == NULL) + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + losslsc->pub.compress_data = compress_output; + break; +#endif + default: + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + break; + } +} + + +#define SWAP_ROWS(rowa,rowb) {JSAMPROW temp; temp=rowa; rowa=rowb; rowb=temp;} + +/* + * Process some data in the single-pass case. + * We process the equivalent of one fully interleaved MCU row ("iMCU" row) + * per call, ie, v_samp_factor rows for each component in the image. + * Returns TRUE if the iMCU row is completed, FALSE if suspended. + * + * NB: input_buf contains a plane for each component in image, + * which we index according to the component's SOF position. + */ + +METHODDEF(boolean) +compress_data (j_compress_ptr cinfo, JSAMPIMAGE input_buf) +{ + j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec; + c_diff_ptr diff = (c_diff_ptr) losslsc->diff_private; + JDIMENSION MCU_col_num; /* index of current MCU within row */ + JDIMENSION MCU_count; /* number of MCUs encoded */ + /* JDIMENSION last_MCU_col = cinfo->MCUs_per_row - 1; */ + JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; + int comp, ci, yoffset, samp_row, samp_rows, samps_across; + jpeg_component_info *compptr; + + /* Loop to write as much as one whole iMCU row */ + for (yoffset = diff->MCU_vert_offset; yoffset < diff->MCU_rows_per_iMCU_row; + yoffset++) { + + MCU_col_num = diff->mcu_ctr; + + /* Scale and predict each scanline of the MCU-row separately. + * + * Note: We only do this if we are at the start of a MCU-row, ie, + * we don't want to reprocess a row suspended by the output. + */ + if (MCU_col_num == 0) { + for (comp = 0; comp < cinfo->comps_in_scan; comp++) { + compptr = cinfo->cur_comp_info[comp]; + ci = compptr->component_index; + if (diff->iMCU_row_num < last_iMCU_row) + samp_rows = compptr->v_samp_factor; + else { + /* NB: can't use last_row_height here, since may not be set! */ + samp_rows = (int)compptr->height_in_data_units % compptr->v_samp_factor; + if (samp_rows == 0) samp_rows = compptr->v_samp_factor; + else { + /* Fill dummy difference rows at the bottom edge with zeros, which + * will encode to the smallest amount of data. + */ + for (samp_row = samp_rows; samp_row < compptr->v_samp_factor; + samp_row++) + MEMZERO(diff->diff_buf[ci][samp_row], + (size_t)jround_up((long) compptr->width_in_data_units, + (long) compptr->h_samp_factor) * SIZEOF(JDIFF)); + } + } + samps_across = (int)compptr->width_in_data_units; + + for (samp_row = 0; samp_row < samp_rows; samp_row++) { + (*losslsc->scaler_scale) (cinfo, + input_buf[ci][samp_row], + diff->cur_row[ci], (JDIMENSION)samps_across); + (*losslsc->predict_difference[ci]) (cinfo, ci, + diff->cur_row[ci], + diff->prev_row[ci], + diff->diff_buf[ci][samp_row], + (JDIMENSION)samps_across); + SWAP_ROWS(diff->cur_row[ci], diff->prev_row[ci]); + } + } + } + + /* Try to write the MCU-row (or remaining portion of suspended MCU-row). */ + MCU_count = + (*losslsc->entropy_encode_mcus) (cinfo, + diff->diff_buf, (JDIMENSION)yoffset, MCU_col_num, + (JDIMENSION)cinfo->MCUs_per_row - MCU_col_num); + if (MCU_count != cinfo->MCUs_per_row - MCU_col_num) { + /* Suspension forced; update state counters and exit */ + diff->MCU_vert_offset = yoffset; + diff->mcu_ctr += MCU_col_num; + return FALSE; + } + + /* Completed an MCU row, but perhaps not an iMCU row */ + diff->mcu_ctr = 0; + } + + /* Completed the iMCU row, advance counters for next one */ + diff->iMCU_row_num++; + start_iMCU_row(cinfo); + return TRUE; +} + + +#ifdef FULL_SAMP_BUFFER_SUPPORTED + +/* + * Process some data in the first pass of a multi-pass case. + * We process the equivalent of one fully interleaved MCU row ("iMCU" row) + * per call, ie, v_samp_factor rows for each component in the image. + * This amount of data is read from the source buffer and saved into the + * virtual arrays. + * + * We must also emit the data to the compressor. This is conveniently + * done by calling compress_output() after we've loaded the current strip + * of the virtual arrays. + * + * NB: input_buf contains a plane for each component in image. All components + * are loaded into the virtual arrays in this pass. However, it may be that + * only a subset of the components are emitted to the compressor during + * this first pass; be careful about looking at the scan-dependent variables + * (MCU dimensions, etc). + */ + +METHODDEF(boolean) +compress_first_pass (j_compress_ptr cinfo, JSAMPIMAGE input_buf) +{ + j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec; + c_diff_ptr diff = (c_diff_ptr) losslsc->diff_private; + JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; + JDIMENSION samps_across; + int ci, samp_row, samp_rows; + JSAMPARRAY buffer[MAX_COMPONENTS]; + jpeg_component_info *compptr; + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + /* Align the virtual buffers for this component. */ + buffer[ci] = (*cinfo->mem->access_virt_sarray) + ((j_common_ptr) cinfo, diff->whole_image[ci], + diff->iMCU_row_num * (JDIMENSION)compptr->v_samp_factor, + (JDIMENSION) compptr->v_samp_factor, TRUE); + + /* Count non-dummy sample rows in this iMCU row. */ + if (diff->iMCU_row_num < last_iMCU_row) + samp_rows = compptr->v_samp_factor; + else { + /* NB: can't use last_row_height here, since may not be set! */ + samp_rows = (int)compptr->height_in_data_units % compptr->v_samp_factor; + if (samp_rows == 0) samp_rows = compptr->v_samp_factor; + } + samps_across = compptr->width_in_data_units; + + /* Perform point transform scaling and prediction/differencing for all + * non-dummy rows in this iMCU row. Each call on these functions + * process a complete row of samples. + */ + for (samp_row = 0; samp_row < samp_rows; samp_row++) { + MEMCOPY(buffer[ci][samp_row], input_buf[ci][samp_row], + samps_across * SIZEOF(JSAMPLE)); + } + } + + /* NB: compress_output will increment iMCU_row_num if successful. + * A suspension return will result in redoing all the work above next time. + */ + + /* Emit data to the compressor, sharing code with subsequent passes */ + return compress_output(cinfo, input_buf); +} + + +/* + * Process some data in subsequent passes of a multi-pass case. + * We process the equivalent of one fully interleaved MCU row ("iMCU" row) + * per call, ie, v_samp_factor rows for each component in the scan. + * The data is obtained from the virtual arrays and fed to the compressor. + * Returns TRUE if the iMCU row is completed, FALSE if suspended. + * + * NB: input_buf is ignored; it is likely to be a NULL pointer. + */ + +METHODDEF(boolean) +compress_output (j_compress_ptr cinfo, JSAMPIMAGE input_buf) +{ + j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec; + c_diff_ptr diff = (c_diff_ptr) losslsc->diff_private; + /* JDIMENSION MCU_col_num; */ /* index of current MCU within row */ + /* JDIMENSION MCU_count; */ /* number of MCUs encoded */ + int comp, ci /* , yoffset */ ; + JSAMPARRAY buffer[MAX_COMPONENTS]; + jpeg_component_info *compptr; + + /* Align the virtual buffers for the components used in this scan. + * NB: during first pass, this is safe only because the buffers will + * already be aligned properly, so jmemmgr.c won't need to do any I/O. + */ + for (comp = 0; comp < cinfo->comps_in_scan; comp++) { + compptr = cinfo->cur_comp_info[comp]; + ci = compptr->component_index; + buffer[ci] = (*cinfo->mem->access_virt_sarray) + ((j_common_ptr) cinfo, diff->whole_image[ci], + diff->iMCU_row_num * (JDIMENSION)compptr->v_samp_factor, + (JDIMENSION) compptr->v_samp_factor, FALSE); + } + + return compress_data(cinfo, buffer); +} + +#endif /* FULL_SAMP_BUFFER_SUPPORTED */ + + +/* + * Initialize difference buffer controller. + */ + +GLOBAL(void) +jinit_c_diff_controller (j_compress_ptr cinfo, boolean need_full_buffer) +{ + j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec; + c_diff_ptr diff; + int ci, row; + jpeg_component_info *compptr; + + diff = (c_diff_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(c_diff_controller)); + losslsc->diff_private = (void *) diff; + losslsc->diff_start_pass = start_pass_diff; + + /* Create the prediction row buffers. */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + diff->cur_row[ci] = *(*cinfo->mem->alloc_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + (JDIMENSION) jround_up((long) compptr->width_in_data_units, + (long) compptr->h_samp_factor), + (JDIMENSION) 1); + diff->prev_row[ci] = *(*cinfo->mem->alloc_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + (JDIMENSION) jround_up((long) compptr->width_in_data_units, + (long) compptr->h_samp_factor), + (JDIMENSION) 1); + } + + /* Create the difference buffer. */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + diff->diff_buf[ci] = (*cinfo->mem->alloc_darray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + (JDIMENSION) jround_up((long) compptr->width_in_data_units, + (long) compptr->h_samp_factor), + (JDIMENSION) compptr->v_samp_factor); + /* Prefill difference rows with zeros. We do this because only actual + * data is placed in the buffers during prediction/differencing, leaving + * any dummy differences at the right edge as zeros, which will encode + * to the smallest amount of data. + */ + for (row = 0; row < compptr->v_samp_factor; row++) + MEMZERO(diff->diff_buf[ci][row], + (size_t)jround_up((long) compptr->width_in_data_units, + (long) compptr->h_samp_factor) * SIZEOF(JDIFF)); + } + + /* Create the sample buffer. */ + if (need_full_buffer) { +#ifdef FULL_SAMP_BUFFER_SUPPORTED + /* Allocate a full-image virtual array for each component, */ + /* padded to a multiple of samp_factor differences in each direction. */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + diff->whole_image[ci] = (*cinfo->mem->request_virt_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE, + (JDIMENSION) jround_up((long) compptr->width_in_data_units, + (long) compptr->h_samp_factor), + (JDIMENSION) jround_up((long) compptr->height_in_data_units, + (long) compptr->v_samp_factor), + (JDIMENSION) compptr->v_samp_factor); + } +#else + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); +#endif + } else + diff->whole_image[0] = NULL; /* flag for no virtual arrays */ +} + +#endif /* C_LOSSLESS_SUPPORTED */ diff --git a/dcmjpeg/libijg16/jchuff.c b/dcmjpeg/libijg16/jchuff.c new file mode 100644 index 00000000..7c2f8d2a --- /dev/null +++ b/dcmjpeg/libijg16/jchuff.c @@ -0,0 +1,274 @@ +/* + * jchuff.c + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains Huffman entropy decoding routines which are shared + * by the sequential, progressive and lossless decoders. + */ + +#define JPEG_INTERNALS +#include "jinclude16.h" +#include "jpeglib16.h" +#include "jchuff16.h" /* Declarations shared with jc*huff.c */ + + +/* + * Compute the derived values for a Huffman table. + * This routine also performs some validation checks on the table. + */ + +GLOBAL(void) +jpeg_make_c_derived_tbl (j_compress_ptr cinfo, boolean isDC, int tblno, + c_derived_tbl ** pdtbl) +{ + JHUFF_TBL *htbl; + c_derived_tbl *dtbl; + int p, i, l, lastp, si, maxsymbol; + char huffsize[257]; + unsigned int huffcode[257]; + unsigned int code; + + /* Note that huffsize[] and huffcode[] are filled in code-length order, + * paralleling the order of the symbols themselves in htbl->huffval[]. + */ + + /* Find the input Huffman table */ + if (tblno < 0 || tblno >= NUM_HUFF_TBLS) + ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tblno); + htbl = + isDC ? cinfo->dc_huff_tbl_ptrs[tblno] : cinfo->ac_huff_tbl_ptrs[tblno]; + if (htbl == NULL) + ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tblno); + + /* Allocate a workspace if we haven't already done so. */ + if (*pdtbl == NULL) + *pdtbl = (c_derived_tbl *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(c_derived_tbl)); + dtbl = *pdtbl; + + /* Figure C.1: make table of Huffman code length for each symbol */ + + p = 0; + for (l = 1; l <= 16; l++) { + i = (int) htbl->bits[l]; + if (i < 0 || p + i > 256) /* protect against table overrun */ + ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); + while (i--) + huffsize[p++] = (char) l; + } + huffsize[p] = 0; + lastp = p; + + /* Figure C.2: generate the codes themselves */ + /* We also validate that the counts represent a legal Huffman code tree. */ + + code = 0; + si = huffsize[0]; + p = 0; + while (huffsize[p]) { + while (((int) huffsize[p]) == si) { + huffcode[p++] = code; + code++; + } + /* code is now 1 more than the last code used for codelength si; but + * it must still fit in si bits, since no code is allowed to be all ones. + * BUG FIX: Comparison must be >, not >= + */ + if (((IJG_INT32) code) > (((IJG_INT32) 1) << si)) + ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); + code <<= 1; + si++; + } + + /* Figure C.3: generate encoding tables */ + /* These are code and size indexed by symbol value */ + + /* Set all codeless symbols to have code length 0; + * this lets us detect duplicate VAL entries here, and later + * allows emit_bits to detect any attempt to emit such symbols. + */ + MEMZERO(dtbl->ehufsi, SIZEOF(dtbl->ehufsi)); + + /* This is also a convenient place to check for out-of-range + * and duplicated VAL entries. We allow 0..255 for AC symbols + * but only 0..16 for DC. (We could constrain them further + * based on data depth and mode, but this seems enough.) + */ + maxsymbol = isDC ? 16 : 255; + + for (p = 0; p < lastp; p++) { + i = htbl->huffval[p]; + if (i < 0 || i > maxsymbol || dtbl->ehufsi[i]) + ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); + dtbl->ehufco[i] = huffcode[p]; + dtbl->ehufsi[i] = huffsize[p]; + } +} + + +/* + * Generate the best Huffman code table for the given counts, fill htbl. + * + * The JPEG standard requires that no symbol be assigned a codeword of all + * one bits (so that padding bits added at the end of a compressed segment + * can't look like a valid code). Because of the canonical ordering of + * codewords, this just means that there must be an unused slot in the + * longest codeword length category. Section K.2 of the JPEG spec suggests + * reserving such a slot by pretending that symbol 256 is a valid symbol + * with count 1. In theory that's not optimal; giving it count zero but + * including it in the symbol set anyway should give a better Huffman code. + * But the theoretically better code actually seems to come out worse in + * practice, because it produces more all-ones bytes (which incur stuffed + * zero bytes in the final file). In any case the difference is tiny. + * + * The JPEG standard requires Huffman codes to be no more than 16 bits long. + * If some symbols have a very small but nonzero probability, the Huffman tree + * must be adjusted to meet the code length restriction. We currently use + * the adjustment method suggested in JPEG section K.2. This method is *not* + * optimal; it may not choose the best possible limited-length code. But + * typically only very-low-frequency symbols will be given less-than-optimal + * lengths, so the code is almost optimal. Experimental comparisons against + * an optimal limited-length-code algorithm indicate that the difference is + * microscopic --- usually less than a hundredth of a percent of total size. + * So the extra complexity of an optimal algorithm doesn't seem worthwhile. + */ + +GLOBAL(void) +jpeg_gen_optimal_table (j_compress_ptr cinfo, JHUFF_TBL * htbl, long freq[]) +{ +#define MAX_CLEN 32 /* assumed maximum initial code length */ + UINT8 bits[MAX_CLEN+1]; /* bits[k] = # of symbols with code length k */ + int codesize[257]; /* codesize[k] = code length of symbol k */ + int others[257]; /* next symbol in current branch of tree */ + int c1, c2; + int p, i, j; + long v; + + /* This algorithm is explained in section K.2 of the JPEG standard */ + + MEMZERO(bits, SIZEOF(bits)); + MEMZERO(codesize, SIZEOF(codesize)); + for (i = 0; i < 257; i++) + others[i] = -1; /* init links to empty */ + + freq[256] = 1; /* make sure 256 has a nonzero count */ + /* Including the pseudo-symbol 256 in the Huffman procedure guarantees + * that no real symbol is given code-value of all ones, because 256 + * will be placed last in the largest codeword category. + */ + + /* Huffman's basic algorithm to assign optimal code lengths to symbols */ + + for (;;) { + /* Find the smallest nonzero frequency, set c1 = its symbol */ + /* In case of ties, take the larger symbol number */ + c1 = -1; + v = 1000000000L; + for (i = 0; i <= 256; i++) { + if (freq[i] && freq[i] <= v) { + v = freq[i]; + c1 = i; + } + } + + /* Find the next smallest nonzero frequency, set c2 = its symbol */ + /* In case of ties, take the larger symbol number */ + c2 = -1; + v = 1000000000L; + for (i = 0; i <= 256; i++) { + if (freq[i] && freq[i] <= v && i != c1) { + v = freq[i]; + c2 = i; + } + } + + /* Done if we've merged everything into one frequency */ + if (c2 < 0) + break; + + /* Else merge the two counts/trees */ + freq[c1] += freq[c2]; + freq[c2] = 0; + + /* Increment the codesize of everything in c1's tree branch */ + codesize[c1]++; + while (others[c1] >= 0) { + c1 = others[c1]; + codesize[c1]++; + } + + others[c1] = c2; /* chain c2 onto c1's tree branch */ + + /* Increment the codesize of everything in c2's tree branch */ + codesize[c2]++; + while (others[c2] >= 0) { + c2 = others[c2]; + codesize[c2]++; + } + } + + /* Now count the number of symbols of each code length */ + for (i = 0; i <= 256; i++) { + if (codesize[i]) { + /* The JPEG standard seems to think that this can't happen, */ + /* but I'm paranoid... */ + if (codesize[i] > MAX_CLEN) + ERREXIT(cinfo, JERR_HUFF_CLEN_OVERFLOW); + + bits[codesize[i]]++; + } + } + + /* JPEG doesn't allow symbols with code lengths over 16 bits, so if the pure + * Huffman procedure assigned any such lengths, we must adjust the coding. + * Here is what the JPEG spec says about how this next bit works: + * Since symbols are paired for the longest Huffman code, the symbols are + * removed from this length category two at a time. The prefix for the pair + * (which is one bit shorter) is allocated to one of the pair; then, + * skipping the BITS entry for that prefix length, a code word from the next + * shortest nonzero BITS entry is converted into a prefix for two code words + * one bit longer. + */ + + for (i = MAX_CLEN; i > 16; i--) { + while (bits[i] > 0) { + j = i - 2; /* find length of new prefix to be used */ + while (bits[j] == 0) + j--; + + bits[i] = (UINT8)(bits[i] - 2); /* remove two symbols */ + bits[i-1]++; /* one goes in this length */ + bits[j+1] = (UINT8)(bits[j+1] + 2); /* two new symbols in this length */ + bits[j]--; /* symbol of this length is now a prefix */ + } + } + + /* Remove the count for the pseudo-symbol 256 from the largest codelength */ + while (bits[i] == 0) /* find largest codelength still in use */ + i--; + bits[i]--; + + /* Return final symbol counts (only for lengths 0..16) */ + MEMCOPY(htbl->bits, bits, SIZEOF(htbl->bits)); + + /* Return a list of the symbols sorted by code length */ + /* It's not real clear to me why we don't need to consider the codelength + * changes made above, but the JPEG spec seems to think this works. + */ + p = 0; + for (i = 1; i <= MAX_CLEN; i++) { + for (j = 0; j <= 255; j++) { + if (codesize[j] == i) { + htbl->huffval[p] = (UINT8) j; + p++; + } + } + } + + /* Set sent_table FALSE so updated table will be written to JPEG file. */ + htbl->sent_table = FALSE; +} diff --git a/dcmjpeg/libijg16/jchuff16.h b/dcmjpeg/libijg16/jchuff16.h new file mode 100644 index 00000000..ae20505f --- /dev/null +++ b/dcmjpeg/libijg16/jchuff16.h @@ -0,0 +1,54 @@ +/* + * jchuff.h + * + * Copyright (C) 1991-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains declarations for Huffman entropy encoding routines + * that are shared between the sequential encoder (jchuff.c) and the + * progressive encoder (jcphuff.c). No other modules need to see these. + */ + +/* The legal range of a DCT coefficient is + * -1024 .. +1023 for 8-bit data; + * -16384 .. +16383 for 12-bit data. + * Hence the magnitude should always fit in 10 or 14 bits respectively. + */ + +#if BITS_IN_JSAMPLE == 8 +#define MAX_COEF_BITS 10 +#else +#define MAX_COEF_BITS 14 +#endif + +/* The legal range of a spatial difference is + * -32767 .. +32768. + * Hence the magnitude should always fit in 16 bits. + */ + +#define MAX_DIFF_BITS 16 + +/* Derived data constructed for each Huffman table */ + +typedef struct { + unsigned int ehufco[256]; /* code for each symbol */ + char ehufsi[256]; /* length of code for each symbol */ + /* If no code has been allocated for a symbol S, ehufsi[S] contains 0 */ +} c_derived_tbl; + +/* Short forms of external names for systems with brain-damaged linkers. */ + +#ifdef NEED_SHORT_EXTERNAL_NAMES +#define jpeg_make_c_derived_tbl jpeg16_make_c_derived_tbl +#define jpeg_gen_optimal_table jpeg16_gen_optimal_table +#endif /* NEED_SHORT_EXTERNAL_NAMES */ + +/* Expand a Huffman table definition into the derived format */ +EXTERN(void) jpeg_make_c_derived_tbl + JPP((j_compress_ptr cinfo, boolean isDC, int tblno, + c_derived_tbl ** pdtbl)); + +/* Generate an optimal table definition given the specified counts */ +EXTERN(void) jpeg_gen_optimal_table + JPP((j_compress_ptr cinfo, JHUFF_TBL * htbl, long freq[])); diff --git a/dcmjpeg/libijg16/jcinit.c b/dcmjpeg/libijg16/jcinit.c new file mode 100644 index 00000000..93fe7021 --- /dev/null +++ b/dcmjpeg/libijg16/jcinit.c @@ -0,0 +1,57 @@ +/* + * jcinit.c + * + * Copyright (C) 1991-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains initialization logic for the JPEG compressor. + * This routine is in charge of selecting the modules to be executed and + * making an initialization call to each one. + * + * Logically, this code belongs in jcmaster.c. It's split out because + * linking this routine implies linking the entire compression library. + * For a transcoding-only application, we want to be able to use jcmaster.c + * without linking in the whole library. + */ + +#define JPEG_INTERNALS +#include "jinclude16.h" +#include "jpeglib16.h" + + +/* + * Master selection of compression modules. + * This is done once at the start of processing an image. We determine + * which modules will be used and give them appropriate initialization calls. + */ + +GLOBAL(void) +jinit_compress_master (j_compress_ptr cinfo) +{ + /* Initialize master control (includes parameter checking/processing) */ + jinit_c_master_control(cinfo, FALSE /* full compression */); + + /* Initialize compression codec */ + jinit_c_codec(cinfo); + + /* Preprocessing */ + if (! cinfo->raw_data_in) { + jinit_color_converter(cinfo); + jinit_downsampler(cinfo); + jinit_c_prep_controller(cinfo, FALSE /* never need full buffer here */); + } + + jinit_c_main_controller(cinfo, FALSE /* never need full buffer here */); + + jinit_marker_writer(cinfo); + + /* We can now tell the memory manager to allocate virtual arrays. */ + (*cinfo->mem->realize_virt_arrays) ((j_common_ptr) cinfo); + + /* Write the datastream header (SOI) immediately. + * Frame and scan headers are postponed till later. + * This lets application insert special markers after the SOI. + */ + (*cinfo->marker->write_file_header) (cinfo); +} diff --git a/dcmjpeg/libijg16/jclhuff.c b/dcmjpeg/libijg16/jclhuff.c new file mode 100644 index 00000000..93554b20 --- /dev/null +++ b/dcmjpeg/libijg16/jclhuff.c @@ -0,0 +1,601 @@ +/* + * jclhuff.c + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains Huffman entropy encoding routines for lossless JPEG. + * + * Much of the complexity here has to do with supporting output suspension. + * If the data destination module demands suspension, we want to be able to + * back up to the start of the current MCU. To do this, we copy state + * variables into local working storage, and update them back to the + * permanent JPEG objects only upon successful completion of an MCU. + */ + +#define JPEG_INTERNALS +#include "jinclude16.h" +#include "jpeglib16.h" +#include "jlossls16.h" /* Private declarations for lossless codec */ +#include "jchuff16.h" /* Declarations shared with jc*huff.c */ + + +/* Expanded entropy encoder object for Huffman encoding. + * + * The savable_state subrecord contains fields that change within an MCU, + * but must not be updated permanently until we complete the MCU. + */ + +typedef struct { + IJG_INT32 put_buffer; /* current bit-accumulation buffer */ + int put_bits; /* # of bits now in it */ +} savable_state; + +/* This macro is to work around compilers with missing or broken + * structure assignment. You'll need to fix this code if you have + * such a compiler and you change MAX_COMPS_IN_SCAN. + */ + +#ifndef NO_STRUCT_ASSIGN +#define ASSIGN_STATE(dest,src) ((dest) = (src)) +#else +#define ASSIGN_STATE(dest,src) \ + ((dest).put_buffer = (src).put_buffer, \ + (dest).put_bits = (src).put_bits) +#endif + + +typedef struct { + int ci, yoffset, MCU_width; +} lhe_input_ptr_info; + + +typedef struct { + savable_state saved; /* Bit buffer at start of MCU */ + + /* These fields are NOT loaded into local working state. */ + unsigned int restarts_to_go; /* MCUs left in this restart interval */ + int next_restart_num; /* next restart number to write (0-7) */ + + /* Pointers to derived tables (these workspaces have image lifespan) */ + c_derived_tbl * derived_tbls[NUM_HUFF_TBLS]; + + /* Pointers to derived tables to be used for each data unit within an MCU */ + c_derived_tbl * cur_tbls[C_MAX_DATA_UNITS_IN_MCU]; + +#ifdef ENTROPY_OPT_SUPPORTED /* Statistics tables for optimization */ + long * count_ptrs[NUM_HUFF_TBLS]; + + /* Pointers to stats tables to be used for each data unit within an MCU */ + long * cur_counts[C_MAX_DATA_UNITS_IN_MCU]; +#endif + + /* Pointers to the proper input difference row for each group of data units + * within an MCU. For each component, there are Vi groups of Hi data units. + */ + JDIFFROW input_ptr[C_MAX_DATA_UNITS_IN_MCU]; + + /* Number of input pointers in use for the current MCU. This is the sum + * of all Vi in the MCU. + */ + int num_input_ptrs; + + /* Information used for positioning the input pointers within the input + * difference rows. + */ + lhe_input_ptr_info input_ptr_info[C_MAX_DATA_UNITS_IN_MCU]; + + /* Index of the proper input pointer for each data unit within an MCU */ + int input_ptr_index[C_MAX_DATA_UNITS_IN_MCU]; + +} lhuff_entropy_encoder; + +typedef lhuff_entropy_encoder * lhuff_entropy_ptr; + +/* Working state while writing an MCU. + * This struct contains all the fields that are needed by subroutines. + */ + +typedef struct { + JOCTET * next_output_byte; /* => next byte to write in buffer */ + size_t free_in_buffer; /* # of byte spaces remaining in buffer */ + savable_state cur; /* Current bit buffer & DC state */ + j_compress_ptr cinfo; /* dump_buffer needs access to this */ +} working_state; + + +/* Forward declarations */ +METHODDEF(JDIMENSION) encode_mcus_huff (j_compress_ptr cinfo, + JDIFFIMAGE diff_buf, + JDIMENSION MCU_row_num, + JDIMENSION MCU_col_num, + JDIMENSION nMCU); +METHODDEF(void) finish_pass_huff JPP((j_compress_ptr cinfo)); +#ifdef ENTROPY_OPT_SUPPORTED +METHODDEF(JDIMENSION) encode_mcus_gather (j_compress_ptr cinfo, + JDIFFIMAGE diff_buf, + JDIMENSION MCU_row_num, + JDIMENSION MCU_col_num, + JDIMENSION nMCU); +METHODDEF(void) finish_pass_gather JPP((j_compress_ptr cinfo)); +#endif + + +/* + * Initialize for a Huffman-compressed scan. + * If gather_statistics is TRUE, we do not output anything during the scan, + * just count the Huffman symbols used and generate Huffman code tables. + */ + +METHODDEF(void) +start_pass_huff (j_compress_ptr cinfo, boolean gather_statistics) +{ + j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec; + lhuff_entropy_ptr entropy = (lhuff_entropy_ptr) losslsc->entropy_private; + int ci, dctbl, sampn, ptrn, yoffset, xoffset; + jpeg_component_info * compptr; + + if (gather_statistics) { +#ifdef ENTROPY_OPT_SUPPORTED + losslsc->entropy_encode_mcus = encode_mcus_gather; + losslsc->pub.entropy_finish_pass = finish_pass_gather; +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } else { + losslsc->entropy_encode_mcus = encode_mcus_huff; + losslsc->pub.entropy_finish_pass = finish_pass_huff; + } + + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + dctbl = compptr->dc_tbl_no; + if (gather_statistics) { +#ifdef ENTROPY_OPT_SUPPORTED + /* Check for invalid table indexes */ + /* (make_c_derived_tbl does this in the other path) */ + if (dctbl < 0 || dctbl >= NUM_HUFF_TBLS) + ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, dctbl); + /* Allocate and zero the statistics tables */ + /* Note that jpeg_gen_optimal_table expects 257 entries in each table! */ + if (entropy->count_ptrs[dctbl] == NULL) + entropy->count_ptrs[dctbl] = (long *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + 257 * SIZEOF(long)); + MEMZERO(entropy->count_ptrs[dctbl], 257 * SIZEOF(long)); +#endif + } else { + /* Compute derived values for Huffman tables */ + /* We may do this more than once for a table, but it's not expensive */ + jpeg_make_c_derived_tbl(cinfo, TRUE, dctbl, + & entropy->derived_tbls[dctbl]); + } + } + + /* Precalculate encoding info for each sample in an MCU of this scan */ + for (sampn = 0, ptrn = 0; sampn < cinfo->data_units_in_MCU;) { + compptr = cinfo->cur_comp_info[cinfo->MCU_membership[sampn]]; + ci = compptr->component_index; + /* ci = cinfo->MCU_membership[sampn]; + compptr = cinfo->cur_comp_info[ci];*/ + for (yoffset = 0; yoffset < compptr->MCU_height; yoffset++, ptrn++) { + /* Precalculate the setup info for each input pointer */ + entropy->input_ptr_info[ptrn].ci = ci; + entropy->input_ptr_info[ptrn].yoffset = yoffset; + entropy->input_ptr_info[ptrn].MCU_width = compptr->MCU_width; + for (xoffset = 0; xoffset < compptr->MCU_width; xoffset++, sampn++) { + /* Precalculate the input pointer index for each sample */ + entropy->input_ptr_index[sampn] = ptrn; + /* Precalculate which tables to use for each sample */ + entropy->cur_tbls[sampn] = entropy->derived_tbls[compptr->dc_tbl_no]; + entropy->cur_counts[sampn] = entropy->count_ptrs[compptr->dc_tbl_no]; + } + } + } + entropy->num_input_ptrs = ptrn; + + /* Initialize bit buffer to empty */ + entropy->saved.put_buffer = 0; + entropy->saved.put_bits = 0; + + /* Initialize restart stuff */ + entropy->restarts_to_go = cinfo->restart_interval; + entropy->next_restart_num = 0; +} + + +/* Outputting bytes to the file */ + +/* Emit a byte, taking 'action' if must suspend. */ +#define emit_byte(state,val,action) \ + { *(state)->next_output_byte++ = (JOCTET) (val); \ + if (--(state)->free_in_buffer == 0) \ + if (! dump_buffer(state)) \ + { action; } } + + +LOCAL(boolean) +dump_buffer (working_state * state) +/* Empty the output buffer; return TRUE if successful, FALSE if must suspend */ +{ + struct jpeg_destination_mgr * dest = state->cinfo->dest; + + if (! (*dest->empty_output_buffer) (state->cinfo)) + return FALSE; + /* After a successful buffer dump, must reset buffer pointers */ + state->next_output_byte = dest->next_output_byte; + state->free_in_buffer = dest->free_in_buffer; + return TRUE; +} + + +/* Outputting bits to the file */ + +/* Only the right 24 bits of put_buffer are used; the valid bits are + * left-justified in this part. At most 16 bits can be passed to emit_bits + * in one call, and we never retain more than 7 bits in put_buffer + * between calls, so 24 bits are sufficient. + */ + +INLINE +LOCAL(boolean) +emit_bits (working_state * state, unsigned int code, int size) +/* Emit some bits; return TRUE if successful, FALSE if must suspend */ +{ + /* This routine is heavily used, so it's worth coding tightly. */ + register IJG_INT32 put_buffer = (IJG_INT32) code; + register int put_bits = state->cur.put_bits; + + /* if size is 0, caller used an invalid Huffman table entry */ + if (size == 0) + ERREXIT(state->cinfo, JERR_HUFF_MISSING_CODE); + + put_buffer &= (((IJG_INT32) 1)<cur.put_buffer; /* and merge with old buffer contents */ + + while (put_bits >= 8) { + int c = (int) ((put_buffer >> 16) & 0xFF); + + emit_byte(state, c, return FALSE); + if (c == 0xFF) { /* need to stuff a zero byte? */ + emit_byte(state, 0, return FALSE); + } + put_buffer <<= 8; + put_bits -= 8; + } + + state->cur.put_buffer = put_buffer; /* update state variables */ + state->cur.put_bits = put_bits; + + return TRUE; +} + + +LOCAL(boolean) +flush_bits (working_state * state) +{ + if (! emit_bits(state, 0x7F, 7)) /* fill any partial byte with ones */ + return FALSE; + state->cur.put_buffer = 0; /* and reset bit-buffer to empty */ + state->cur.put_bits = 0; + return TRUE; +} + + +/* + * Emit a restart marker & resynchronize predictions. + */ + +LOCAL(boolean) +emit_restart (working_state * state, int restart_num) +{ + /* int ci; */ + + if (! flush_bits(state)) + return FALSE; + + emit_byte(state, 0xFF, return FALSE); + emit_byte(state, JPEG_RST0 + restart_num, return FALSE); + + /* The restart counter is not updated until we successfully write the MCU. */ + + return TRUE; +} + + +/* + * Encode and output one nMCU's worth of Huffman-compressed differences. + */ + +METHODDEF(JDIMENSION) +encode_mcus_huff (j_compress_ptr cinfo, JDIFFIMAGE diff_buf, + JDIMENSION MCU_row_num, JDIMENSION MCU_col_num, + JDIMENSION nMCU) +{ + j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec; + lhuff_entropy_ptr entropy = (lhuff_entropy_ptr) losslsc->entropy_private; + working_state state; + unsigned int mcu_num; + int sampn, ci, yoffset, MCU_width, ptrn; + /* jpeg_component_info * compptr; */ + + /* Load up working state */ + state.next_output_byte = cinfo->dest->next_output_byte; + state.free_in_buffer = cinfo->dest->free_in_buffer; + ASSIGN_STATE(state.cur, entropy->saved); + state.cinfo = cinfo; + + /* Emit restart marker if needed */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) + if (! emit_restart(&state, entropy->next_restart_num)) + return 0; + } + + /* Set input pointer locations based on MCU_col_num */ + for (ptrn = 0; ptrn < entropy->num_input_ptrs; ptrn++) { + ci = entropy->input_ptr_info[ptrn].ci; + yoffset = entropy->input_ptr_info[ptrn].yoffset; + MCU_width = entropy->input_ptr_info[ptrn].MCU_width; + entropy->input_ptr[ptrn] = + diff_buf[ci][MCU_row_num + (size_t)yoffset] + MCU_col_num * (size_t)MCU_width; + } + + for (mcu_num = 0; mcu_num < nMCU; mcu_num++) { + + /* Inner loop handles the samples in the MCU */ + for (sampn = 0; sampn < cinfo->data_units_in_MCU; sampn++) { + register int temp, temp2 /* , temp3 */ ; + register int nbits; + c_derived_tbl *dctbl = entropy->cur_tbls[sampn]; + + /* Encode the difference per section H.1.2.2 */ + + /* Input the sample difference */ + temp = *entropy->input_ptr[entropy->input_ptr_index[sampn]]++; + + if (temp & 0x8000) { /* instead of temp < 0 */ + temp = (-temp) & 0x7FFF; /* absolute value, mod 2^16 */ + if (temp == 0) /* special case: magnitude = 32768 */ + temp2 = temp = 0x8000; + temp2 = ~ temp; /* one's complement of magnitude */ + } else { + temp &= 0x7FFF; /* abs value mod 2^16 */ + temp2 = temp; /* magnitude */ + } + + /* Find the number of bits needed for the magnitude of the difference */ + nbits = 0; + while (temp) { + nbits++; + temp >>= 1; + } + /* Check for out-of-range difference values. + */ + if (nbits > MAX_DIFF_BITS) + ERREXIT(cinfo, JERR_BAD_DIFF); + + /* Emit the Huffman-coded symbol for the number of bits */ + if (! emit_bits(&state, dctbl->ehufco[nbits], dctbl->ehufsi[nbits])) + return mcu_num; + + /* Emit that number of bits of the value, if positive, */ + /* or the complement of its magnitude, if negative. */ + if (nbits && /* emit_bits rejects calls with size 0 */ + nbits != 16) /* special case: no bits should be emitted */ + if (! emit_bits(&state, (unsigned int) temp2, nbits)) + return mcu_num; + } + + /* Completed MCU, so update state */ + cinfo->dest->next_output_byte = state.next_output_byte; + cinfo->dest->free_in_buffer = state.free_in_buffer; + ASSIGN_STATE(entropy->saved, state.cur); + + /* Update restart-interval state too */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) { + entropy->restarts_to_go = cinfo->restart_interval; + entropy->next_restart_num++; + entropy->next_restart_num &= 7; + } + entropy->restarts_to_go--; + } + + } + + return nMCU; +} + + +/* + * Finish up at the end of a Huffman-compressed scan. + */ + +METHODDEF(void) +finish_pass_huff (j_compress_ptr cinfo) +{ + j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec; + lhuff_entropy_ptr entropy = (lhuff_entropy_ptr) losslsc->entropy_private; + working_state state; + + /* Load up working state ... flush_bits needs it */ + state.next_output_byte = cinfo->dest->next_output_byte; + state.free_in_buffer = cinfo->dest->free_in_buffer; + ASSIGN_STATE(state.cur, entropy->saved); + state.cinfo = cinfo; + + /* Flush out the last data */ + if (! flush_bits(&state)) + ERREXIT(cinfo, JERR_CANT_SUSPEND); + + /* Update state */ + cinfo->dest->next_output_byte = state.next_output_byte; + cinfo->dest->free_in_buffer = state.free_in_buffer; + ASSIGN_STATE(entropy->saved, state.cur); +} + + +/* + * Huffman coding optimization. + * + * We first scan the supplied data and count the number of uses of each symbol + * that is to be Huffman-coded. (This process MUST agree with the code above.) + * Then we build a Huffman coding tree for the observed counts. + * Symbols which are not needed at all for the particular image are not + * assigned any code, which saves space in the DHT marker as well as in + * the compressed data. + */ + +#ifdef ENTROPY_OPT_SUPPORTED + +/* + * Trial-encode one nMCU's worth of Huffman-compressed differences. + * No data is actually output, so no suspension return is possible. + */ + +METHODDEF(JDIMENSION) +encode_mcus_gather (j_compress_ptr cinfo, JDIFFIMAGE diff_buf, + JDIMENSION MCU_row_num, JDIMENSION MCU_col_num, + JDIMENSION nMCU) +{ + j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec; + lhuff_entropy_ptr entropy = (lhuff_entropy_ptr) losslsc->entropy_private; + unsigned int mcu_num; + int sampn, ci, yoffset, MCU_width, ptrn; + /* jpeg_component_info * compptr; */ + + /* Take care of restart intervals if needed */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) { + /* Update restart state */ + entropy->restarts_to_go = cinfo->restart_interval; + } + entropy->restarts_to_go--; + } + + /* Set input pointer locations based on MCU_col_num */ + for (ptrn = 0; ptrn < entropy->num_input_ptrs; ptrn++) { + ci = entropy->input_ptr_info[ptrn].ci; + yoffset = entropy->input_ptr_info[ptrn].yoffset; + MCU_width = entropy->input_ptr_info[ptrn].MCU_width; + entropy->input_ptr[ptrn] = + diff_buf[ci][MCU_row_num + (size_t)yoffset] + MCU_col_num * (size_t)MCU_width; + } + + for (mcu_num = 0; mcu_num < nMCU; mcu_num++) { + + /* Inner loop handles the samples in the MCU */ + for (sampn = 0; sampn < cinfo->data_units_in_MCU; sampn++) { + register int temp; + register int nbits; + /* c_derived_tbl *dctbl = entropy->cur_tbls[sampn]; */ + long * counts = entropy->cur_counts[sampn]; + + /* Encode the difference per section H.1.2.2 */ + + /* Input the sample difference */ + temp = *entropy->input_ptr[entropy->input_ptr_index[sampn]]++; + + if (temp & 0x8000) { /* instead of temp < 0 */ + temp = (-temp) & 0x7FFF; /* absolute value, mod 2^16 */ + if (temp == 0) /* special case: magnitude = 32768 */ + temp = 0x8000; + } else + temp &= 0x7FFF; /* abs value mod 2^16 */ + + /* Find the number of bits needed for the magnitude of the difference */ + nbits = 0; + while (temp) { + nbits++; + temp >>= 1; + } + /* Check for out-of-range difference values. + */ + if (nbits > MAX_DIFF_BITS) + ERREXIT(cinfo, JERR_BAD_DIFF); + + /* Count the Huffman symbol for the number of bits */ + counts[nbits]++; + } + } + + return nMCU; +} + + +/* + * Finish up a statistics-gathering pass and create the new Huffman tables. + */ + +METHODDEF(void) +finish_pass_gather (j_compress_ptr cinfo) +{ + j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec; + lhuff_entropy_ptr entropy = (lhuff_entropy_ptr) losslsc->entropy_private; + int ci, dctbl; + jpeg_component_info * compptr; + JHUFF_TBL **htblptr; + boolean did_dc[NUM_HUFF_TBLS]; + + /* It's important not to apply jpeg_gen_optimal_table more than once + * per table, because it clobbers the input frequency counts! + */ + MEMZERO(did_dc, SIZEOF(did_dc)); + + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + dctbl = compptr->dc_tbl_no; + if (! did_dc[dctbl]) { + htblptr = & cinfo->dc_huff_tbl_ptrs[dctbl]; + if (*htblptr == NULL) + *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo); + jpeg_gen_optimal_table(cinfo, *htblptr, entropy->count_ptrs[dctbl]); + did_dc[dctbl] = TRUE; + } + } +} + + +#endif /* ENTROPY_OPT_SUPPORTED */ + + +METHODDEF(boolean) +need_optimization_pass (j_compress_ptr cinfo) +{ + return TRUE; +} + + +/* + * Module initialization routine for Huffman entropy encoding. + */ + +GLOBAL(void) +jinit_lhuff_encoder (j_compress_ptr cinfo) +{ + j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec; + lhuff_entropy_ptr entropy; + int i; + + entropy = (lhuff_entropy_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(lhuff_entropy_encoder)); + losslsc->entropy_private = (struct jpeg_entropy_encoder *) entropy; + losslsc->pub.entropy_start_pass = start_pass_huff; + losslsc->pub.need_optimization_pass = need_optimization_pass; + + /* Mark tables unallocated */ + for (i = 0; i < NUM_HUFF_TBLS; i++) { + entropy->derived_tbls[i] = NULL; +#ifdef ENTROPY_OPT_SUPPORTED + entropy->count_ptrs[i] = NULL; +#endif + } +} diff --git a/dcmjpeg/libijg16/jclossls.c b/dcmjpeg/libijg16/jclossls.c new file mode 100644 index 00000000..0ccc72cb --- /dev/null +++ b/dcmjpeg/libijg16/jclossls.c @@ -0,0 +1,82 @@ +/* + * jclossls.c + * + * Copyright (C) 1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains the control logic for the lossless JPEG compressor. + */ + +#define JPEG_INTERNALS +#include "jinclude16.h" +#include "jpeglib16.h" +#include "jlossls16.h" + + +#ifdef C_LOSSLESS_SUPPORTED + +/* + * Initialize for a processing pass. + */ + +METHODDEF(void) +start_pass (j_compress_ptr cinfo, J_BUF_MODE pass_mode) +{ + j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec; + + (*losslsc->scaler_start_pass) (cinfo); + (*losslsc->predict_start_pass) (cinfo); + (*losslsc->diff_start_pass) (cinfo, pass_mode); +} + + +/* + * Initialize the lossless compression codec. + * This is called only once, during master selection. + */ + +GLOBAL(void) +jinit_lossless_c_codec(j_compress_ptr cinfo) +{ + j_lossless_c_ptr losslsc; + + /* Create subobject in permanent pool */ + losslsc = (j_lossless_c_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, + SIZEOF(jpeg_lossless_c_codec)); + cinfo->codec = (struct jpeg_c_codec *) losslsc; + + /* Initialize sub-modules */ + + /* Scaler */ + jinit_c_scaler(cinfo); + + /* Differencer */ + jinit_differencer(cinfo); + + /* Entropy encoding: either Huffman or arithmetic coding. */ + if (cinfo->arith_code) { +#ifdef WITH_ARITHMETIC_PATCH + jinit_arith_encoder(cinfo); +#else + ERREXIT(cinfo, JERR_ARITH_NOTIMPL); +#endif + } else { + jinit_lhuff_encoder(cinfo); + } + + /* Need a full-image difference buffer in any multi-pass mode. */ + jinit_c_diff_controller(cinfo, + (boolean) (cinfo->num_scans > 1 || + cinfo->optimize_coding)); + + /* Initialize method pointers. + * + * Note: entropy_start_pass and entropy_finish_pass are assigned in + * jclhuff.c and compress_data is assigned in jcdiffct.c. + */ + losslsc->pub.start_pass = start_pass; +} + +#endif /* C_LOSSLESS_SUPPORTED */ diff --git a/dcmjpeg/libijg16/jclossy.c b/dcmjpeg/libijg16/jclossy.c new file mode 100644 index 00000000..2602f8be --- /dev/null +++ b/dcmjpeg/libijg16/jclossy.c @@ -0,0 +1,76 @@ +/* + * jclossy.c + * + * Copyright (C) 1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains the control logic for the lossy JPEG compressor. + */ + +#define JPEG_INTERNALS +#include "jinclude16.h" +#include "jpeglib16.h" +#include "jlossy16.h" + + +/* + * Initialize for a processing pass. + */ + +METHODDEF(void) +start_pass (j_compress_ptr cinfo, J_BUF_MODE pass_mode) +{ + j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; + + (*lossyc->fdct_start_pass) (cinfo); + (*lossyc->coef_start_pass) (cinfo, pass_mode); +} + + +/* + * Initialize the lossy compression codec. + * This is called only once, during master selection. + */ + +GLOBAL(void) +jinit_lossy_c_codec (j_compress_ptr cinfo) +{ + j_lossy_c_ptr lossyc; + + /* Create subobject in permanent pool */ + lossyc = (j_lossy_c_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, + SIZEOF(jpeg_lossy_c_codec)); + cinfo->codec = (struct jpeg_c_codec *) lossyc; + + /* Initialize sub-modules */ + + /* Forward DCT */ + jinit_forward_dct(cinfo); + /* Entropy encoding: either Huffman or arithmetic coding. */ + if (cinfo->arith_code) { + ERREXIT(cinfo, JERR_ARITH_NOTIMPL); + } else { + if (cinfo->process == JPROC_PROGRESSIVE) { +#ifdef C_PROGRESSIVE_SUPPORTED + jinit_phuff_encoder(cinfo); +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } else + jinit_shuff_encoder(cinfo); + } + + /* Need a full-image coefficient buffer in any multi-pass mode. */ + jinit_c_coef_controller(cinfo, + (boolean) (cinfo->num_scans > 1 || + cinfo->optimize_coding)); + + /* Initialize method pointers. + * + * Note: entropy_start_pass and entropy_finish_pass are assigned in + * jcshuff.c or jcphuff.c and compress_data is assigned in jccoefct.c. + */ + lossyc->pub.start_pass = start_pass; +} diff --git a/dcmjpeg/libijg16/jcmainct.c b/dcmjpeg/libijg16/jcmainct.c new file mode 100644 index 00000000..0a360aad --- /dev/null +++ b/dcmjpeg/libijg16/jcmainct.c @@ -0,0 +1,296 @@ +/* + * jcmainct.c + * + * Copyright (C) 1994-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains the main buffer controller for compression. + * The main buffer lies between the pre-processor and the JPEG + * compressor proper; it holds downsampled data in the JPEG colorspace. + */ + +#define JPEG_INTERNALS +#include "jinclude16.h" +#include "jpeglib16.h" + + +/* Note: currently, there is no operating mode in which a full-image buffer + * is needed at this step. If there were, that mode could not be used with + * "raw data" input, since this module is bypassed in that case. However, + * we've left the code here for possible use in special applications. + */ +#undef FULL_MAIN_BUFFER_SUPPORTED + + +/* Private buffer controller object */ + +typedef struct { + struct jpeg_c_main_controller pub; /* public fields */ + + JDIMENSION cur_iMCU_row; /* number of current iMCU row */ + JDIMENSION rowgroup_ctr; /* counts row groups received in iMCU row */ + boolean suspended; /* remember if we suspended output */ + J_BUF_MODE pass_mode; /* current operating mode */ + + /* If using just a strip buffer, this points to the entire set of buffers + * (we allocate one for each component). In the full-image case, this + * points to the currently accessible strips of the virtual arrays. + */ + JSAMPARRAY buffer[MAX_COMPONENTS]; + +#ifdef FULL_MAIN_BUFFER_SUPPORTED + /* If using full-image storage, this array holds pointers to virtual-array + * control blocks for each component. Unused if not full-image storage. + */ + jvirt_sarray_ptr whole_image[MAX_COMPONENTS]; +#endif +} my_main_controller; + +typedef my_main_controller * my_main_ptr; + + +/* Forward declarations */ +METHODDEF(void) process_data_simple_main + JPP((j_compress_ptr cinfo, JSAMPARRAY input_buf, + JDIMENSION *in_row_ctr, JDIMENSION in_rows_avail)); +#ifdef FULL_MAIN_BUFFER_SUPPORTED +METHODDEF(void) process_data_buffer_main + JPP((j_compress_ptr cinfo, JSAMPARRAY input_buf, + JDIMENSION *in_row_ctr, JDIMENSION in_rows_avail)); +#endif + + +/* + * Initialize for a processing pass. + */ + +METHODDEF(void) +start_pass_main (j_compress_ptr cinfo, J_BUF_MODE pass_mode) +{ + my_main_ptr mymain = (my_main_ptr) cinfo->main; + + /* Do nothing in raw-data mode. */ + if (cinfo->raw_data_in) + return; + + mymain->cur_iMCU_row = 0; /* initialize counters */ + mymain->rowgroup_ctr = 0; + mymain->suspended = FALSE; + mymain->pass_mode = pass_mode; /* save mode for use by process_data */ + + switch (pass_mode) { + case JBUF_PASS_THRU: +#ifdef FULL_MAIN_BUFFER_SUPPORTED + if (mymain->whole_image[0] != NULL) + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); +#endif + mymain->pub.process_data = process_data_simple_main; + break; +#ifdef FULL_MAIN_BUFFER_SUPPORTED + case JBUF_SAVE_SOURCE: + case JBUF_CRANK_DEST: + case JBUF_SAVE_AND_PASS: + if (mymain->whole_image[0] == NULL) + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + mymain->pub.process_data = process_data_buffer_main; + break; +#endif + default: + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + break; + } +} + + +/* + * Process some data. + * This routine handles the simple pass-through mode, + * where we have only a strip buffer. + */ + +METHODDEF(void) +process_data_simple_main (j_compress_ptr cinfo, + JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, + JDIMENSION in_rows_avail) +{ + my_main_ptr mymain = (my_main_ptr) cinfo->main; + JDIMENSION data_unit = (JDIMENSION)(cinfo->data_unit); + + while (mymain->cur_iMCU_row < cinfo->total_iMCU_rows) { + /* Read input data if we haven't filled the main buffer yet */ + if (mymain->rowgroup_ctr < data_unit) + (*cinfo->prep->pre_process_data) (cinfo, + input_buf, in_row_ctr, in_rows_avail, + mymain->buffer, &mymain->rowgroup_ctr, + (JDIMENSION) data_unit); + + /* If we don't have a full iMCU row buffered, return to application for + * more data. Note that preprocessor will always pad to fill the iMCU row + * at the bottom of the image. + */ + if (mymain->rowgroup_ctr != data_unit) + return; + + /* Send the completed row to the compressor */ + if (! (*cinfo->codec->compress_data) (cinfo, mymain->buffer)) { + /* If compressor did not consume the whole row, then we must need to + * suspend processing and return to the application. In this situation + * we pretend we didn't yet consume the last input row; otherwise, if + * it happened to be the last row of the image, the application would + * think we were done. + */ + if (! mymain->suspended) { + (*in_row_ctr)--; + mymain->suspended = TRUE; + } + return; + } + /* We did finish the row. Undo our little suspension hack if a previous + * call suspended; then mark the main buffer empty. + */ + if (mymain->suspended) { + (*in_row_ctr)++; + mymain->suspended = FALSE; + } + mymain->rowgroup_ctr = 0; + mymain->cur_iMCU_row++; + } +} + + +#ifdef FULL_MAIN_BUFFER_SUPPORTED + +/* + * Process some data. + * This routine handles all of the modes that use a full-size buffer. + */ + +METHODDEF(void) +process_data_buffer_main (j_compress_ptr cinfo, + JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, + JDIMENSION in_rows_avail) +{ + my_main_ptr mymain = (my_main_ptr) cinfo->main; + int ci; + jpeg_component_info *compptr; + boolean writing = (mymain->pass_mode != JBUF_CRANK_DEST); + JDIMENSION data_unit = (JDIMENSION)(cinfo->data_unit); + + while (mymain->cur_iMCU_row < cinfo->total_iMCU_rows) { + /* Realign the virtual buffers if at the start of an iMCU row. */ + if (mymain->rowgroup_ctr == 0) { + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + mymain->buffer[ci] = (*cinfo->mem->access_virt_sarray) + ((j_common_ptr) cinfo, mymain->whole_image[ci], + mymain->cur_iMCU_row * (compptr->v_samp_factor * data_unit), + (JDIMENSION) (compptr->v_samp_factor * data_unit), writing); + } + /* In a read pass, pretend we just read some source data. */ + if (! writing) { + *in_row_ctr += cinfo->max_v_samp_factor * data_unit; + mymain->rowgroup_ctr = data_unit; + } + } + + /* If a write pass, read input data until the current iMCU row is full. */ + /* Note: preprocessor will pad if necessary to fill the last iMCU row. */ + if (writing) { + (*cinfo->prep->pre_process_data) (cinfo, + input_buf, in_row_ctr, in_rows_avail, + mymain->buffer, &mymain->rowgroup_ctr, + (JDIMENSION) data_unit); + /* Return to application if we need more data to fill the iMCU row. */ + if (mymain->rowgroup_ctr < data_unit) + return; + } + + /* Emit data, unless this is a sink-only pass. */ + if (mymain->pass_mode != JBUF_SAVE_SOURCE) { + if (! (*cinfo->codec->compress_data) (cinfo, mymain->buffer)) { + /* If compressor did not consume the whole row, then we must need to + * suspend processing and return to the application. In this situation + * we pretend we didn't yet consume the last input row; otherwise, if + * it happened to be the last row of the image, the application would + * think we were done. + */ + if (! mymain->suspended) { + (*in_row_ctr)--; + mymain->suspended = TRUE; + } + return; + } + /* We did finish the row. Undo our little suspension hack if a previous + * call suspended; then mark the main buffer empty. + */ + if (mymain->suspended) { + (*in_row_ctr)++; + mymain->suspended = FALSE; + } + } + + /* If get here, we are done with this iMCU row. Mark buffer empty. */ + mymain->rowgroup_ctr = 0; + mymain->cur_iMCU_row++; + } +} + +#endif /* FULL_MAIN_BUFFER_SUPPORTED */ + + +/* + * Initialize main buffer controller. + */ + +GLOBAL(void) +jinit_c_main_controller (j_compress_ptr cinfo, boolean need_full_buffer) +{ + my_main_ptr mymain; + int ci; + jpeg_component_info *compptr; + int data_unit = cinfo->data_unit; + + mymain = (my_main_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_main_controller)); + cinfo->main = (struct jpeg_c_main_controller *) mymain; + mymain->pub.start_pass = start_pass_main; + + /* We don't need to create a buffer in raw-data mode. */ + if (cinfo->raw_data_in) + return; + + /* Create the buffer. It holds downsampled data, so each component + * may be of a different size. + */ + if (need_full_buffer) { +#ifdef FULL_MAIN_BUFFER_SUPPORTED + /* Allocate a full-image virtual array for each component */ + /* Note we pad the bottom to a multiple of the iMCU height */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + mymain->whole_image[ci] = (*cinfo->mem->request_virt_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE, + compptr->width_in_data_units * data_unit, + (JDIMENSION) jround_up((long) compptr->height_in_data_units, + (long) compptr->v_samp_factor) * data_unit, + (JDIMENSION) (compptr->v_samp_factor * data_unit)); + } +#else + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); +#endif + } else { +#ifdef FULL_MAIN_BUFFER_SUPPORTED + mymain->whole_image[0] = NULL; /* flag for no virtual arrays */ +#endif + /* Allocate a strip buffer for each component */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + mymain->buffer[ci] = (*cinfo->mem->alloc_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + compptr->width_in_data_units * (JDIMENSION)data_unit, + (JDIMENSION) (compptr->v_samp_factor * data_unit)); + } + } +} diff --git a/dcmjpeg/libijg16/jcmarker.c b/dcmjpeg/libijg16/jcmarker.c new file mode 100644 index 00000000..2432ca9d --- /dev/null +++ b/dcmjpeg/libijg16/jcmarker.c @@ -0,0 +1,680 @@ +/* + * jcmarker.c + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains routines to write JPEG datastream markers. + */ + +#define JPEG_INTERNALS +#include "jinclude16.h" +#include "jpeglib16.h" + + +typedef enum { /* JPEG marker codes */ + M_SOF0 = 0xc0, + M_SOF1 = 0xc1, + M_SOF2 = 0xc2, + M_SOF3 = 0xc3, + + M_SOF5 = 0xc5, + M_SOF6 = 0xc6, + M_SOF7 = 0xc7, + + M_JPG = 0xc8, + M_SOF9 = 0xc9, + M_SOF10 = 0xca, + M_SOF11 = 0xcb, + + M_SOF13 = 0xcd, + M_SOF14 = 0xce, + M_SOF15 = 0xcf, + + M_DHT = 0xc4, + + M_DAC = 0xcc, + + M_RST0 = 0xd0, + M_RST1 = 0xd1, + M_RST2 = 0xd2, + M_RST3 = 0xd3, + M_RST4 = 0xd4, + M_RST5 = 0xd5, + M_RST6 = 0xd6, + M_RST7 = 0xd7, + + M_SOI = 0xd8, + M_EOI = 0xd9, + M_SOS = 0xda, + M_DQT = 0xdb, + M_DNL = 0xdc, + M_DRI = 0xdd, + M_DHP = 0xde, + M_EXP = 0xdf, + + M_APP0 = 0xe0, + M_APP1 = 0xe1, + M_APP2 = 0xe2, + M_APP3 = 0xe3, + M_APP4 = 0xe4, + M_APP5 = 0xe5, + M_APP6 = 0xe6, + M_APP7 = 0xe7, + M_APP8 = 0xe8, + M_APP9 = 0xe9, + M_APP10 = 0xea, + M_APP11 = 0xeb, + M_APP12 = 0xec, + M_APP13 = 0xed, + M_APP14 = 0xee, + M_APP15 = 0xef, + + M_JPG0 = 0xf0, + M_JPG13 = 0xfd, + M_COM = 0xfe, + + M_TEM = 0x01, + + M_ERROR = 0x100 +} JPEG_MARKER; + + +/* Private state */ + +typedef struct { + struct jpeg_marker_writer pub; /* public fields */ + + unsigned int last_restart_interval; /* last DRI value emitted; 0 after SOI */ +} my_marker_writer; + +typedef my_marker_writer * my_marker_ptr; + + +/* + * Basic output routines. + * + * Note that we do not support suspension while writing a marker. + * Therefore, an application using suspension must ensure that there is + * enough buffer space for the initial markers (typ. 600-700 bytes) before + * calling jpeg_start_compress, and enough space to write the trailing EOI + * (a few bytes) before calling jpeg_finish_compress. Multipass compression + * modes are not supported at all with suspension, so those two are the only + * points where markers will be written. + */ + +LOCAL(void) +emit_byte (j_compress_ptr cinfo, int val) +/* Emit a byte */ +{ + struct jpeg_destination_mgr * dest = cinfo->dest; + + *(dest->next_output_byte)++ = (JOCTET) val; + if (--dest->free_in_buffer == 0) { + if (! (*dest->empty_output_buffer) (cinfo)) + ERREXIT(cinfo, JERR_CANT_SUSPEND); + } +} + + +LOCAL(void) +emit_marker (j_compress_ptr cinfo, JPEG_MARKER mark) +/* Emit a marker code */ +{ + emit_byte(cinfo, 0xFF); + emit_byte(cinfo, (int) mark); +} + + +LOCAL(void) +emit_2bytes (j_compress_ptr cinfo, int value) +/* Emit a 2-byte integer; these are always MSB first in JPEG files */ +{ + emit_byte(cinfo, (value >> 8) & 0xFF); + emit_byte(cinfo, value & 0xFF); +} + + +/* + * Routines to write specific marker types. + */ + +LOCAL(int) +emit_dqt (j_compress_ptr cinfo, int idx) +/* Emit a DQT marker */ +/* Returns the precision used (0 = 8bits, 1 = 16bits) for baseline checking */ +{ + JQUANT_TBL * qtbl = cinfo->quant_tbl_ptrs[idx]; + int prec; + int i; + + if (qtbl == NULL) + ERREXIT1(cinfo, JERR_NO_QUANT_TABLE, idx); + + prec = 0; + for (i = 0; i < DCTSIZE2; i++) { + if (qtbl->quantval[i] > 255) + prec = 1; + } + + if (! qtbl->sent_table) { + emit_marker(cinfo, M_DQT); + + emit_2bytes(cinfo, prec ? DCTSIZE2*2 + 1 + 2 : DCTSIZE2 + 1 + 2); + + emit_byte(cinfo, idx + (prec<<4)); + + for (i = 0; i < DCTSIZE2; i++) { + /* The table entries must be emitted in zigzag order. */ + unsigned int qval = qtbl->quantval[jpeg_natural_order[i]]; + if (prec) + emit_byte(cinfo, (int) (qval >> 8)); + emit_byte(cinfo, (int) (qval & 0xFF)); + } + + qtbl->sent_table = TRUE; + } + + return prec; +} + + +LOCAL(void) +emit_dht (j_compress_ptr cinfo, int idx, boolean is_ac) +/* Emit a DHT marker */ +{ + JHUFF_TBL * htbl; + int length, i; + + if (is_ac) { + htbl = cinfo->ac_huff_tbl_ptrs[idx]; + idx += 0x10; /* output index has AC bit set */ + } else { + htbl = cinfo->dc_huff_tbl_ptrs[idx]; + } + + if (htbl == NULL) + ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, idx); + + if (! htbl->sent_table) { + emit_marker(cinfo, M_DHT); + + length = 0; + for (i = 1; i <= 16; i++) + length += htbl->bits[i]; + + emit_2bytes(cinfo, length + 2 + 1 + 16); + emit_byte(cinfo, idx); + + for (i = 1; i <= 16; i++) + emit_byte(cinfo, htbl->bits[i]); + + for (i = 0; i < length; i++) + emit_byte(cinfo, htbl->huffval[i]); + + htbl->sent_table = TRUE; + } +} + + +LOCAL(void) +emit_dac (j_compress_ptr cinfo) +/* Emit a DAC marker */ +/* Since the useful info is so small, we want to emit all the tables in */ +/* one DAC marker. Therefore this routine does its own scan of the table. */ +{ +#ifdef C_ARITH_CODING_SUPPORTED + char dc_in_use[NUM_ARITH_TBLS]; + char ac_in_use[NUM_ARITH_TBLS]; + int length, i; + jpeg_component_info *compptr; + + for (i = 0; i < NUM_ARITH_TBLS; i++) + dc_in_use[i] = ac_in_use[i] = 0; + + for (i = 0; i < cinfo->comps_in_scan; i++) { + compptr = cinfo->cur_comp_info[i]; + dc_in_use[compptr->dc_tbl_no] = 1; + ac_in_use[compptr->ac_tbl_no] = 1; + } + + length = 0; + for (i = 0; i < NUM_ARITH_TBLS; i++) + length += dc_in_use[i] + ac_in_use[i]; + + emit_marker(cinfo, M_DAC); + + emit_2bytes(cinfo, length*2 + 2); + + for (i = 0; i < NUM_ARITH_TBLS; i++) { + if (dc_in_use[i]) { + emit_byte(cinfo, i); + emit_byte(cinfo, cinfo->arith_dc_L[i] + (cinfo->arith_dc_U[i]<<4)); + } + if (ac_in_use[i]) { + emit_byte(cinfo, i + 0x10); + emit_byte(cinfo, cinfo->arith_ac_K[i]); + } + } +#endif /* C_ARITH_CODING_SUPPORTED */ +} + + +LOCAL(void) +emit_dri (j_compress_ptr cinfo) +/* Emit a DRI marker */ +{ + emit_marker(cinfo, M_DRI); + + emit_2bytes(cinfo, 4); /* fixed length */ + + emit_2bytes(cinfo, (int) cinfo->restart_interval); +} + + +LOCAL(void) +emit_sof (j_compress_ptr cinfo, JPEG_MARKER code) +/* Emit a SOF marker */ +{ + int ci; + jpeg_component_info *compptr; + + emit_marker(cinfo, code); + + emit_2bytes(cinfo, 3 * cinfo->num_components + 2 + 5 + 1); /* length */ + + /* Make sure image isn't bigger than SOF field can handle */ + if ((long) cinfo->image_height > 65535L || + (long) cinfo->image_width > 65535L) + ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, (unsigned int) 65535); + + emit_byte(cinfo, cinfo->data_precision); + emit_2bytes(cinfo, (int) cinfo->image_height); + emit_2bytes(cinfo, (int) cinfo->image_width); + + emit_byte(cinfo, cinfo->num_components); + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + emit_byte(cinfo, compptr->component_id); + emit_byte(cinfo, (compptr->h_samp_factor << 4) + compptr->v_samp_factor); + emit_byte(cinfo, compptr->quant_tbl_no); + } +} + + +LOCAL(void) +emit_sos (j_compress_ptr cinfo) +/* Emit a SOS marker */ +{ + int i, td, ta; + jpeg_component_info *compptr; + + emit_marker(cinfo, M_SOS); + + emit_2bytes(cinfo, 2 * cinfo->comps_in_scan + 2 + 1 + 3); /* length */ + + emit_byte(cinfo, cinfo->comps_in_scan); + + for (i = 0; i < cinfo->comps_in_scan; i++) { + compptr = cinfo->cur_comp_info[i]; + emit_byte(cinfo, compptr->component_id); + td = compptr->dc_tbl_no; + ta = compptr->ac_tbl_no; + if (cinfo->process == JPROC_PROGRESSIVE) { + /* Progressive mode: only DC or only AC tables are used in one scan; + * furthermore, Huffman coding of DC refinement uses no table at all. + * We emit 0 for unused field(s); this is recommended by the P&M text + * but does not seem to be specified in the standard. + */ + if (cinfo->Ss == 0) { + ta = 0; /* DC scan */ + if (cinfo->Ah != 0 && !cinfo->arith_code) + td = 0; /* no DC table either */ + } else { + td = 0; /* AC scan */ + } + } + emit_byte(cinfo, (td << 4) + ta); + } + + emit_byte(cinfo, cinfo->Ss); + emit_byte(cinfo, cinfo->Se); + emit_byte(cinfo, (cinfo->Ah << 4) + cinfo->Al); +} + + +LOCAL(void) +emit_jfif_app0 (j_compress_ptr cinfo) +/* Emit a JFIF-compliant APP0 marker */ +{ + /* + * Length of APP0 block (2 bytes) + * Block ID (4 bytes - ASCII "JFIF") + * Zero byte (1 byte to terminate the ID string) + * Version Major, Minor (2 bytes - major first) + * Units (1 byte - 0x00 = none, 0x01 = inch, 0x02 = cm) + * Xdpu (2 bytes - dots per unit horizontal) + * Ydpu (2 bytes - dots per unit vertical) + * Thumbnail X size (1 byte) + * Thumbnail Y size (1 byte) + */ + + emit_marker(cinfo, M_APP0); + + emit_2bytes(cinfo, 2 + 4 + 1 + 2 + 1 + 2 + 2 + 1 + 1); /* length */ + + emit_byte(cinfo, 0x4A); /* Identifier: ASCII "JFIF" */ + emit_byte(cinfo, 0x46); + emit_byte(cinfo, 0x49); + emit_byte(cinfo, 0x46); + emit_byte(cinfo, 0); + emit_byte(cinfo, cinfo->JFIF_major_version); /* Version fields */ + emit_byte(cinfo, cinfo->JFIF_minor_version); + emit_byte(cinfo, cinfo->density_unit); /* Pixel size information */ + emit_2bytes(cinfo, (int) cinfo->X_density); + emit_2bytes(cinfo, (int) cinfo->Y_density); + emit_byte(cinfo, 0); /* No thumbnail image */ + emit_byte(cinfo, 0); +} + + +LOCAL(void) +emit_adobe_app14 (j_compress_ptr cinfo) +/* Emit an Adobe APP14 marker */ +{ + /* + * Length of APP14 block (2 bytes) + * Block ID (5 bytes - ASCII "Adobe") + * Version Number (2 bytes - currently 100) + * Flags0 (2 bytes - currently 0) + * Flags1 (2 bytes - currently 0) + * Color transform (1 byte) + * + * Although Adobe TN 5116 mentions Version = 101, all the Adobe files + * now in circulation seem to use Version = 100, so that's what we write. + * + * We write the color transform byte as 1 if the JPEG color space is + * YCbCr, 2 if it's YCCK, 0 otherwise. Adobe's definition has to do with + * whether the encoder performed a transformation, which is pretty useless. + */ + + emit_marker(cinfo, M_APP14); + + emit_2bytes(cinfo, 2 + 5 + 2 + 2 + 2 + 1); /* length */ + + emit_byte(cinfo, 0x41); /* Identifier: ASCII "Adobe" */ + emit_byte(cinfo, 0x64); + emit_byte(cinfo, 0x6F); + emit_byte(cinfo, 0x62); + emit_byte(cinfo, 0x65); + emit_2bytes(cinfo, 100); /* Version */ + emit_2bytes(cinfo, 0); /* Flags0 */ + emit_2bytes(cinfo, 0); /* Flags1 */ + switch (cinfo->jpeg_color_space) { + case JCS_YCbCr: + emit_byte(cinfo, 1); /* Color transform = 1 */ + break; + case JCS_YCCK: + emit_byte(cinfo, 2); /* Color transform = 2 */ + break; + default: + emit_byte(cinfo, 0); /* Color transform = 0 */ + break; + } +} + + +/* + * These routines allow writing an arbitrary marker with parameters. + * The only intended use is to emit COM or APPn markers after calling + * write_file_header and before calling write_frame_header. + * Other uses are not guaranteed to produce desirable results. + * Counting the parameter bytes properly is the caller's responsibility. + */ + +METHODDEF(void) +write_marker_header (j_compress_ptr cinfo, int marker, unsigned int datalen) +/* Emit an arbitrary marker header */ +{ + if (datalen > (unsigned int) 65533) /* safety check */ + ERREXIT(cinfo, JERR_BAD_LENGTH); + + emit_marker(cinfo, (JPEG_MARKER) marker); + + emit_2bytes(cinfo, (int) (datalen + 2)); /* total length */ +} + +METHODDEF(void) +write_marker_byte (j_compress_ptr cinfo, int val) +/* Emit one byte of marker parameters following write_marker_header */ +{ + emit_byte(cinfo, val); +} + + +/* + * Write datastream header. + * This consists of an SOI and optional APPn markers. + * We recommend use of the JFIF marker, but not the Adobe marker, + * when using YCbCr or grayscale data. The JFIF marker should NOT + * be used for any other JPEG colorspace. The Adobe marker is helpful + * to distinguish RGB, CMYK, and YCCK colorspaces. + * Note that an application can write additional header markers after + * jpeg_start_compress returns. + */ + +METHODDEF(void) +write_file_header (j_compress_ptr cinfo) +{ + my_marker_ptr marker = (my_marker_ptr) cinfo->marker; + + emit_marker(cinfo, M_SOI); /* first the SOI */ + + /* SOI is defined to reset restart interval to 0 */ + marker->last_restart_interval = 0; + + if (cinfo->write_JFIF_header) /* next an optional JFIF APP0 */ + emit_jfif_app0(cinfo); + if (cinfo->write_Adobe_marker) /* next an optional Adobe APP14 */ + emit_adobe_app14(cinfo); +} + + +/* + * Write frame header. + * This consists of DQT and SOFn markers. + * Note that we do not emit the SOF until we have emitted the DQT(s). + * This avoids compatibility problems with incorrect implementations that + * try to error-check the quant table numbers as soon as they see the SOF. + */ + +METHODDEF(void) +write_frame_header (j_compress_ptr cinfo) +{ + int ci, prec; + boolean is_baseline; + jpeg_component_info *compptr; + + prec = 0; + if (cinfo->process != JPROC_LOSSLESS) { + /* Emit DQT for each quantization table. + * Note that emit_dqt() suppresses any duplicate tables. + */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + prec += emit_dqt(cinfo, compptr->quant_tbl_no); + } + /* now prec is nonzero iff there are any 16-bit quant tables. */ + } + + /* Check for a non-baseline specification. + * Note we assume that Huffman table numbers won't be changed later. + */ + if (cinfo->arith_code || cinfo->process != JPROC_SEQUENTIAL || + cinfo->data_precision != 8) { + is_baseline = FALSE; + } else { + is_baseline = TRUE; + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + if (compptr->dc_tbl_no > 1 || compptr->ac_tbl_no > 1) + is_baseline = FALSE; + } + if (prec && is_baseline) { + is_baseline = FALSE; + /* If it's baseline except for quantizer size, warn the user */ + TRACEMS(cinfo, 0, JTRC_16BIT_TABLES); + } + } + + /* Emit the proper SOF marker */ + if (cinfo->arith_code) { +#ifdef WITH_ARITHMETIC_PATCH + if (cinfo->process == JPROC_PROGRESSIVE) + emit_sof(cinfo, M_SOF10); /* SOF code for progressive arithmetic */ + else if (cinfo->process == JPROC_LOSSLESS) + emit_sof(cinfo, M_SOF11); /* SOF code for lossless arithmetic */ + else + emit_sof(cinfo, M_SOF9); /* SOF code for sequential arithmetic */ +#else + emit_sof(cinfo, M_SOF9); /* SOF code for arithmetic coding */ +#endif + } else { + if (cinfo->process == JPROC_PROGRESSIVE) + emit_sof(cinfo, M_SOF2); /* SOF code for progressive Huffman */ + else if (cinfo->process == JPROC_LOSSLESS) + emit_sof(cinfo, M_SOF3); /* SOF code for lossless Huffman */ + else if (is_baseline) + emit_sof(cinfo, M_SOF0); /* SOF code for baseline implementation */ + else + emit_sof(cinfo, M_SOF1); /* SOF code for non-baseline Huffman file */ + } +} + + +/* + * Write scan header. + * This consists of DHT or DAC markers, optional DRI, and SOS. + * Compressed data will be written following the SOS. + */ + +METHODDEF(void) +write_scan_header (j_compress_ptr cinfo) +{ + my_marker_ptr marker = (my_marker_ptr) cinfo->marker; + int i; + jpeg_component_info *compptr; + + if (cinfo->arith_code) { + /* Emit arith conditioning info. We may have some duplication + * if the file has multiple scans, but it's so small it's hardly + * worth worrying about. + */ + emit_dac(cinfo); + } else { + /* Emit Huffman tables. + * Note that emit_dht() suppresses any duplicate tables. + */ + for (i = 0; i < cinfo->comps_in_scan; i++) { + compptr = cinfo->cur_comp_info[i]; + if (cinfo->process == JPROC_PROGRESSIVE) { + /* Progressive mode: only DC or only AC tables are used in one scan */ + if (cinfo->Ss == 0) { + if (cinfo->Ah == 0) /* DC needs no table for refinement scan */ + emit_dht(cinfo, compptr->dc_tbl_no, FALSE); + } else { + emit_dht(cinfo, compptr->ac_tbl_no, TRUE); + } + } else if (cinfo->process == JPROC_LOSSLESS) { + /* Lossless mode: only DC tables are used */ + emit_dht(cinfo, compptr->dc_tbl_no, FALSE); + } else { + /* Sequential mode: need both DC and AC tables */ + emit_dht(cinfo, compptr->dc_tbl_no, FALSE); + emit_dht(cinfo, compptr->ac_tbl_no, TRUE); + } + } + } + + /* Emit DRI if required --- note that DRI value could change for each scan. + * We avoid wasting space with unnecessary DRIs, however. + */ + if (cinfo->restart_interval != marker->last_restart_interval) { + emit_dri(cinfo); + marker->last_restart_interval = cinfo->restart_interval; + } + + emit_sos(cinfo); +} + + +/* + * Write datastream trailer. + */ + +METHODDEF(void) +write_file_trailer (j_compress_ptr cinfo) +{ + emit_marker(cinfo, M_EOI); +} + + +/* + * Write an abbreviated table-specification datastream. + * This consists of SOI, DQT and DHT tables, and EOI. + * Any table that is defined and not marked sent_table = TRUE will be + * emitted. Note that all tables will be marked sent_table = TRUE at exit. + */ + +METHODDEF(void) +write_tables_only (j_compress_ptr cinfo) +{ + int i; + + emit_marker(cinfo, M_SOI); + + for (i = 0; i < NUM_QUANT_TBLS; i++) { + if (cinfo->quant_tbl_ptrs[i] != NULL) + (void) emit_dqt(cinfo, i); + } + + if (! cinfo->arith_code) { + for (i = 0; i < NUM_HUFF_TBLS; i++) { + if (cinfo->dc_huff_tbl_ptrs[i] != NULL) + emit_dht(cinfo, i, FALSE); + if (cinfo->ac_huff_tbl_ptrs[i] != NULL) + emit_dht(cinfo, i, TRUE); + } + } + + emit_marker(cinfo, M_EOI); +} + + +/* + * Initialize the marker writer module. + */ + +GLOBAL(void) +jinit_marker_writer (j_compress_ptr cinfo) +{ + my_marker_ptr marker; + + /* Create the subobject */ + marker = (my_marker_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_marker_writer)); + cinfo->marker = (struct jpeg_marker_writer *) marker; + /* Initialize method pointers */ + marker->pub.write_file_header = write_file_header; + marker->pub.write_frame_header = write_frame_header; + marker->pub.write_scan_header = write_scan_header; + marker->pub.write_file_trailer = write_file_trailer; + marker->pub.write_tables_only = write_tables_only; + marker->pub.write_marker_header = write_marker_header; + marker->pub.write_marker_byte = write_marker_byte; + /* Initialize private state */ + marker->last_restart_interval = 0; +} diff --git a/dcmjpeg/libijg16/jcmaster.c b/dcmjpeg/libijg16/jcmaster.c new file mode 100644 index 00000000..4df9b58c --- /dev/null +++ b/dcmjpeg/libijg16/jcmaster.c @@ -0,0 +1,657 @@ +/* + * jcmaster.c + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains master control logic for the JPEG compressor. + * These routines are concerned with parameter validation, initial setup, + * and inter-pass control (determining the number of passes and the work + * to be done in each pass). + */ + +#define JPEG_INTERNALS +#include "jinclude16.h" +#include "jpeglib16.h" +#include "jlossy16.h" /* Private declarations for lossy codec */ + + +/* Private state */ + +typedef enum { + main_pass, /* input data, also do first output step */ + huff_opt_pass, /* Huffman code optimization pass */ + output_pass /* data output pass */ +} c_pass_type; + +typedef struct { + struct jpeg_comp_master pub; /* public fields */ + + c_pass_type pass_type; /* the type of the current pass */ + + int pass_number; /* # of passes completed */ + int total_passes; /* total # of passes needed */ + + int scan_number; /* current index in scan_info[] */ +} my_comp_master; + +typedef my_comp_master * my_master_ptr; + + +/* + * Support routines that do various essential calculations. + */ + +LOCAL(void) +initial_setup (j_compress_ptr cinfo) +/* Do computations that are needed before master selection phase */ +{ + int ci; + jpeg_component_info *compptr; + long samplesperrow; + JDIMENSION jd_samplesperrow; + int data_unit = cinfo->data_unit; + + /* Sanity check on image dimensions */ + if (cinfo->image_height <= 0 || cinfo->image_width <= 0 + || cinfo->num_components <= 0 || cinfo->input_components <= 0) + ERREXIT(cinfo, JERR_EMPTY_IMAGE); + + /* Make sure image isn't bigger than I can handle */ + if ((long) cinfo->image_height > (long) JPEG_MAX_DIMENSION || + (long) cinfo->image_width > (long) JPEG_MAX_DIMENSION) + ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, (unsigned int) JPEG_MAX_DIMENSION); + + /* Width of an input scanline must be representable as JDIMENSION. */ + samplesperrow = (long) cinfo->image_width * (long) cinfo->input_components; + jd_samplesperrow = (JDIMENSION) samplesperrow; + if ((long) jd_samplesperrow != samplesperrow) + ERREXIT(cinfo, JERR_WIDTH_OVERFLOW); + + /* For now, precision must match compiled-in value... */ + if (cinfo->data_precision != BITS_IN_JSAMPLE) + ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); + + /* Check that number of components won't exceed internal array sizes */ + if (cinfo->num_components > MAX_COMPONENTS) + ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components, + MAX_COMPONENTS); + + /* Compute maximum sampling factors; check factor validity */ + cinfo->max_h_samp_factor = 1; + cinfo->max_v_samp_factor = 1; + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + if (compptr->h_samp_factor<=0 || compptr->h_samp_factor>MAX_SAMP_FACTOR || + compptr->v_samp_factor<=0 || compptr->v_samp_factor>MAX_SAMP_FACTOR) + ERREXIT(cinfo, JERR_BAD_SAMPLING); + cinfo->max_h_samp_factor = MAX(cinfo->max_h_samp_factor, + compptr->h_samp_factor); + cinfo->max_v_samp_factor = MAX(cinfo->max_v_samp_factor, + compptr->v_samp_factor); + } + + /* Compute dimensions of components */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + /* Fill in the correct component_index value; don't rely on application */ + compptr->component_index = ci; + /* For compression, we never do any codec-based processing. */ + compptr->codec_data_unit = data_unit; + /* Size in data units */ + compptr->width_in_data_units = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor, + (long) (cinfo->max_h_samp_factor * data_unit)); + compptr->height_in_data_units = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor, + (long) (cinfo->max_v_samp_factor * data_unit)); + /* Size in samples */ + compptr->downsampled_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor, + (long) cinfo->max_h_samp_factor); + compptr->downsampled_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor, + (long) cinfo->max_v_samp_factor); + /* Mark component needed (this flag isn't actually used for compression) */ + compptr->component_needed = TRUE; + } + + /* Compute number of fully interleaved MCU rows (number of times that + * main controller will call coefficient controller). + */ + cinfo->total_iMCU_rows = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height, + (long) (cinfo->max_v_samp_factor*data_unit)); +} + +#ifdef C_MULTISCAN_FILES_SUPPORTED +#define NEED_SCAN_SCRIPT +#else +#ifdef C_LOSSLESS_SUPPORTED +#define NEED_SCAN_SCRIPT +#endif +#endif + +#ifdef NEED_SCAN_SCRIPT + +LOCAL(void) +validate_script (j_compress_ptr cinfo) +/* Verify that the scan script in cinfo->scan_info[] is valid; also + * determine whether it uses progressive JPEG, and set cinfo->process. + */ +{ + const jpeg_scan_info * scanptr; + int scanno, ncomps, ci, coefi, thisi; + int Ss, Se, Ah, Al; + boolean component_sent[MAX_COMPONENTS]; +#ifdef C_PROGRESSIVE_SUPPORTED + int * last_bitpos_ptr; + int last_bitpos[MAX_COMPONENTS][DCTSIZE2]; + /* -1 until that coefficient has been seen; then last Al for it */ +#endif + + if (cinfo->num_scans <= 0) + ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, 0); + +#ifndef C_MULTISCAN_FILES_SUPPORTED + if (cinfo->num_scans > 1) + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + + scanptr = cinfo->scan_info; + if (cinfo->lossless) { +#ifdef C_LOSSLESS_SUPPORTED + cinfo->process = JPROC_LOSSLESS; + for (ci = 0; ci < cinfo->num_components; ci++) + component_sent[ci] = FALSE; +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } + /* For sequential JPEG, all scans must have Ss=0, Se=DCTSIZE2-1; + * for progressive JPEG, no scan can have this. + */ + else if (scanptr->Ss != 0 || scanptr->Se != DCTSIZE2-1) { +#ifdef C_PROGRESSIVE_SUPPORTED + cinfo->process = JPROC_PROGRESSIVE; + last_bitpos_ptr = & last_bitpos[0][0]; + for (ci = 0; ci < cinfo->num_components; ci++) + for (coefi = 0; coefi < DCTSIZE2; coefi++) + *last_bitpos_ptr++ = -1; +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } else { + cinfo->process = JPROC_SEQUENTIAL; + for (ci = 0; ci < cinfo->num_components; ci++) + component_sent[ci] = FALSE; + } + + for (scanno = 1; scanno <= cinfo->num_scans; scanptr++, scanno++) { + /* Validate component indexes */ + ncomps = scanptr->comps_in_scan; + if (ncomps <= 0 || ncomps > MAX_COMPS_IN_SCAN) + ERREXIT2(cinfo, JERR_COMPONENT_COUNT, ncomps, MAX_COMPS_IN_SCAN); + for (ci = 0; ci < ncomps; ci++) { + thisi = scanptr->component_index[ci]; + if (thisi < 0 || thisi >= cinfo->num_components) + ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, scanno); + /* Components must appear in SOF order within each scan */ + if (ci > 0 && thisi <= scanptr->component_index[ci-1]) + ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, scanno); + } + /* Validate progression parameters */ + Ss = scanptr->Ss; + Se = scanptr->Se; + Ah = scanptr->Ah; + Al = scanptr->Al; + if (cinfo->process == JPROC_LOSSLESS) { +#ifdef C_LOSSLESS_SUPPORTED + /* The JPEG spec simply gives the range 0..15 for Al (Pt), but that + * seems wrong: the upper bound ought to depend on data precision. + * Perhaps they really meant 0..N-1 for N-bit precision, which is what + * we allow here. + */ + if (Ss < 1 || Ss > 7 || /* predictor selector */ + Se != 0 || Ah != 0 || + Al < 0 || Al >= cinfo->data_precision) /* point transform */ + ERREXIT1(cinfo, JERR_BAD_LOSSLESS_SCRIPT, scanno); + /* Make sure components are not sent twice */ + for (ci = 0; ci < ncomps; ci++) { + thisi = scanptr->component_index[ci]; + if (component_sent[thisi]) + ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, scanno); + component_sent[thisi] = TRUE; + } +#endif + } else if (cinfo->process == JPROC_PROGRESSIVE) { +#ifdef C_PROGRESSIVE_SUPPORTED + /* The JPEG spec simply gives the ranges 0..13 for Ah and Al, but that + * seems wrong: the upper bound ought to depend on data precision. + * Perhaps they really meant 0..N+1 for N-bit precision. + * Here we allow 0..10 for 8-bit data; Al larger than 10 results in + * out-of-range reconstructed DC values during the first DC scan, + * which might cause problems for some decoders. + */ +#if BITS_IN_JSAMPLE == 8 +#define MAX_AH_AL 10 +#else +#define MAX_AH_AL 13 +#endif + if (Ss < 0 || Ss >= DCTSIZE2 || Se < Ss || Se >= DCTSIZE2 || + Ah < 0 || Ah > MAX_AH_AL || Al < 0 || Al > MAX_AH_AL) + ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); + if (Ss == 0) { + if (Se != 0) /* DC and AC together not OK */ + ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); + } else { + if (ncomps != 1) /* AC scans must be for only one component */ + ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); + } + for (ci = 0; ci < ncomps; ci++) { + last_bitpos_ptr = & last_bitpos[scanptr->component_index[ci]][0]; + if (Ss != 0 && last_bitpos_ptr[0] < 0) /* AC without prior DC scan */ + ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); + for (coefi = Ss; coefi <= Se; coefi++) { + if (last_bitpos_ptr[coefi] < 0) { + /* first scan of this coefficient */ + if (Ah != 0) + ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); + } else { + /* not first scan */ + if (Ah != last_bitpos_ptr[coefi] || Al != Ah-1) + ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); + } + last_bitpos_ptr[coefi] = Al; + } + } +#endif + } else { + /* For sequential JPEG, all progression parameters must be these: */ + if (Ss != 0 || Se != DCTSIZE2-1 || Ah != 0 || Al != 0) + ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); + /* Make sure components are not sent twice */ + for (ci = 0; ci < ncomps; ci++) { + thisi = scanptr->component_index[ci]; + if (component_sent[thisi]) + ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, scanno); + component_sent[thisi] = TRUE; + } + } + } + + /* Now verify that everything got sent. */ + if (cinfo->process == JPROC_PROGRESSIVE) { +#ifdef C_PROGRESSIVE_SUPPORTED + /* For progressive mode, we only check that at least some DC data + * got sent for each component; the spec does not require that all bits + * of all coefficients be transmitted. Would it be wiser to enforce + * transmission of all coefficient bits?? + */ + for (ci = 0; ci < cinfo->num_components; ci++) { + if (last_bitpos[ci][0] < 0) + ERREXIT(cinfo, JERR_MISSING_DATA); + } +#endif + } else { + for (ci = 0; ci < cinfo->num_components; ci++) { + if (! component_sent[ci]) + ERREXIT(cinfo, JERR_MISSING_DATA); + } + } +} + +#endif /* NEED_SCAN_SCRIPT */ + + +LOCAL(void) +select_scan_parameters (j_compress_ptr cinfo) +/* Set up the scan parameters for the current scan */ +{ + int ci; + +#ifdef NEED_SCAN_SCRIPT + if (cinfo->scan_info != NULL) { + /* Prepare for current scan --- the script is already validated */ + my_master_ptr master = (my_master_ptr) cinfo->master; + const jpeg_scan_info * scanptr = cinfo->scan_info + master->scan_number; + + cinfo->comps_in_scan = scanptr->comps_in_scan; + for (ci = 0; ci < scanptr->comps_in_scan; ci++) { + cinfo->cur_comp_info[ci] = + &cinfo->comp_info[scanptr->component_index[ci]]; + } + cinfo->Ss = scanptr->Ss; + cinfo->Se = scanptr->Se; + cinfo->Ah = scanptr->Ah; + cinfo->Al = scanptr->Al; + } else +#endif + { + /* Prepare for single sequential-JPEG scan containing all components */ + if (cinfo->num_components > MAX_COMPS_IN_SCAN) + ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components, + MAX_COMPS_IN_SCAN); + cinfo->comps_in_scan = cinfo->num_components; + for (ci = 0; ci < cinfo->num_components; ci++) { + cinfo->cur_comp_info[ci] = &cinfo->comp_info[ci]; + } + if (cinfo->lossless) { +#ifdef C_LOSSLESS_SUPPORTED + /* If we fall through to here, the user specified lossless, but did not + * provide a scan script. + */ + ERREXIT(cinfo, JERR_NO_LOSSLESS_SCRIPT); +#endif + } else { + cinfo->process = JPROC_SEQUENTIAL; + cinfo->Ss = 0; + cinfo->Se = DCTSIZE2-1; + cinfo->Ah = 0; + cinfo->Al = 0; + } + } +} + + +LOCAL(void) +per_scan_setup (j_compress_ptr cinfo) +/* Do computations that are needed before processing a JPEG scan */ +/* cinfo->comps_in_scan and cinfo->cur_comp_info[] are already set */ +{ + int ci, mcublks, tmp; + jpeg_component_info *compptr; + int data_unit = cinfo->data_unit; + + if (cinfo->comps_in_scan == 1) { + + /* Noninterleaved (single-component) scan */ + compptr = cinfo->cur_comp_info[0]; + + /* Overall image size in MCUs */ + cinfo->MCUs_per_row = compptr->width_in_data_units; + cinfo->MCU_rows_in_scan = compptr->height_in_data_units; + + /* For noninterleaved scan, always one block per MCU */ + compptr->MCU_width = 1; + compptr->MCU_height = 1; + compptr->MCU_data_units = 1; + compptr->MCU_sample_width = data_unit; + compptr->last_col_width = 1; + /* For noninterleaved scans, it is convenient to define last_row_height + * as the number of block rows present in the last iMCU row. + */ + tmp = (int)compptr->height_in_data_units % compptr->v_samp_factor; + if (tmp == 0) tmp = compptr->v_samp_factor; + compptr->last_row_height = tmp; + + /* Prepare array describing MCU composition */ + cinfo->data_units_in_MCU = 1; + cinfo->MCU_membership[0] = 0; + + } else { + + /* Interleaved (multi-component) scan */ + if (cinfo->comps_in_scan <= 0 || cinfo->comps_in_scan > MAX_COMPS_IN_SCAN) + ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->comps_in_scan, + MAX_COMPS_IN_SCAN); + + /* Overall image size in MCUs */ + cinfo->MCUs_per_row = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width, + (long) (cinfo->max_h_samp_factor*data_unit)); + cinfo->MCU_rows_in_scan = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height, + (long) (cinfo->max_v_samp_factor*data_unit)); + + cinfo->data_units_in_MCU = 0; + + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + /* Sampling factors give # of blocks of component in each MCU */ + compptr->MCU_width = compptr->h_samp_factor; + compptr->MCU_height = compptr->v_samp_factor; + compptr->MCU_data_units = compptr->MCU_width * compptr->MCU_height; + compptr->MCU_sample_width = compptr->MCU_width * data_unit; + /* Figure number of non-dummy blocks in last MCU column & row */ + tmp = (int)compptr->width_in_data_units % compptr->MCU_width; + if (tmp == 0) tmp = compptr->MCU_width; + compptr->last_col_width = tmp; + tmp = (int)compptr->height_in_data_units % compptr->MCU_height; + if (tmp == 0) tmp = compptr->MCU_height; + compptr->last_row_height = tmp; + /* Prepare array describing MCU composition */ + mcublks = compptr->MCU_data_units; + if (cinfo->data_units_in_MCU + mcublks > C_MAX_DATA_UNITS_IN_MCU) + ERREXIT(cinfo, JERR_BAD_MCU_SIZE); + while (mcublks-- > 0) { + cinfo->MCU_membership[cinfo->data_units_in_MCU++] = ci; + } + } + + } + + /* Convert restart specified in rows to actual MCU count. */ + /* Note that count must fit in 16 bits, so we provide limiting. */ + if (cinfo->restart_in_rows > 0) { + long nominal = (long) cinfo->restart_in_rows * (long) cinfo->MCUs_per_row; + cinfo->restart_interval = (unsigned int) MIN(nominal, 65535L); + } +} + + +/* + * Per-pass setup. + * This is called at the beginning of each pass. We determine which modules + * will be active during this pass and give them appropriate start_pass calls. + * We also set is_last_pass to indicate whether any more passes will be + * required. + */ + +METHODDEF(void) +prepare_for_pass (j_compress_ptr cinfo) +{ + /* j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; */ + my_master_ptr master = (my_master_ptr) cinfo->master; + + switch (master->pass_type) { + case main_pass: + /* Initial pass: will collect input data, and do either Huffman + * optimization or data output for the first scan. + */ + select_scan_parameters(cinfo); + per_scan_setup(cinfo); + if (! cinfo->raw_data_in) { + (*cinfo->cconvert->start_pass) (cinfo); + (*cinfo->downsample->start_pass) (cinfo); + (*cinfo->prep->start_pass) (cinfo, JBUF_PASS_THRU); + } + (*cinfo->codec->entropy_start_pass) (cinfo, cinfo->optimize_coding); + (*cinfo->codec->start_pass) (cinfo, + (master->total_passes > 1 ? + JBUF_SAVE_AND_PASS : JBUF_PASS_THRU)); + (*cinfo->main->start_pass) (cinfo, JBUF_PASS_THRU); + if (cinfo->optimize_coding) { + /* No immediate data output; postpone writing frame/scan headers */ + master->pub.call_pass_startup = FALSE; + } else { + /* Will write frame/scan headers at first jpeg_write_scanlines call */ + master->pub.call_pass_startup = TRUE; + } + break; +#ifdef ENTROPY_OPT_SUPPORTED + case huff_opt_pass: + /* Do Huffman optimization for a scan after the first one. */ + select_scan_parameters(cinfo); + per_scan_setup(cinfo); +#ifdef WITH_ARITHMETIC_PATCH + if ((*cinfo->codec->need_optimization_pass) (cinfo)) { +#else + if ((*cinfo->codec->need_optimization_pass) (cinfo) || cinfo->arith_code) { +#endif + (*cinfo->codec->entropy_start_pass) (cinfo, TRUE); + (*cinfo->codec->start_pass) (cinfo, JBUF_CRANK_DEST); + master->pub.call_pass_startup = FALSE; + break; + } + /* Special case: Huffman DC refinement scans need no Huffman table + * and therefore we can skip the optimization pass for them. + */ + master->pass_type = output_pass; + master->pass_number++; + /*FALLTHROUGH*/ +#endif + case output_pass: + /* Do a data-output pass. */ + /* We need not repeat per-scan setup if prior optimization pass did it. */ + if (! cinfo->optimize_coding) { + select_scan_parameters(cinfo); + per_scan_setup(cinfo); + } + (*cinfo->codec->entropy_start_pass) (cinfo, FALSE); + (*cinfo->codec->start_pass) (cinfo, JBUF_CRANK_DEST); + /* We emit frame/scan headers now */ + if (master->scan_number == 0) + (*cinfo->marker->write_frame_header) (cinfo); + (*cinfo->marker->write_scan_header) (cinfo); + master->pub.call_pass_startup = FALSE; + break; + default: + ERREXIT(cinfo, JERR_NOT_COMPILED); + } + + master->pub.is_last_pass = (master->pass_number == master->total_passes-1); + + /* Set up progress monitor's pass info if present */ + if (cinfo->progress != NULL) { + cinfo->progress->completed_passes = master->pass_number; + cinfo->progress->total_passes = master->total_passes; + } +} + + +/* + * Special start-of-pass hook. + * This is called by jpeg_write_scanlines if call_pass_startup is TRUE. + * In single-pass processing, we need this hook because we don't want to + * write frame/scan headers during jpeg_start_compress; we want to let the + * application write COM markers etc. between jpeg_start_compress and the + * jpeg_write_scanlines loop. + * In multi-pass processing, this routine is not used. + */ + +METHODDEF(void) +pass_startup (j_compress_ptr cinfo) +{ + cinfo->master->call_pass_startup = FALSE; /* reset flag so call only once */ + + (*cinfo->marker->write_frame_header) (cinfo); + (*cinfo->marker->write_scan_header) (cinfo); +} + + +/* + * Finish up at end of pass. + */ + +METHODDEF(void) +finish_pass_master (j_compress_ptr cinfo) +{ + j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; + my_master_ptr master = (my_master_ptr) cinfo->master; + + /* The entropy coder always needs an end-of-pass call, + * either to analyze statistics or to flush its output buffer. + */ + (*lossyc->pub.entropy_finish_pass) (cinfo); + + /* Update state for next pass */ + switch (master->pass_type) { + case main_pass: + /* next pass is either output of scan 0 (after optimization) + * or output of scan 1 (if no optimization). + */ + master->pass_type = output_pass; + if (! cinfo->optimize_coding) + master->scan_number++; + break; + case huff_opt_pass: + /* next pass is always output of current scan */ + master->pass_type = output_pass; + break; + case output_pass: + /* next pass is either optimization or output of next scan */ + if (cinfo->optimize_coding) + master->pass_type = huff_opt_pass; + master->scan_number++; + break; + } + + master->pass_number++; +} + + +/* + * Initialize master compression control. + */ + +GLOBAL(void) +jinit_c_master_control (j_compress_ptr cinfo, boolean transcode_only) +{ + my_master_ptr master; + + master = (my_master_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_comp_master)); + cinfo->master = (struct jpeg_comp_master *) master; + master->pub.prepare_for_pass = prepare_for_pass; + master->pub.pass_startup = pass_startup; + master->pub.finish_pass = finish_pass_master; + master->pub.is_last_pass = FALSE; + + cinfo->data_unit = cinfo->lossless ? 1 : DCTSIZE; + + /* Validate parameters, determine derived values */ + initial_setup(cinfo); + + if (cinfo->scan_info != NULL) { +#ifdef NEED_SCAN_SCRIPT + validate_script(cinfo); +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } else { + cinfo->process = JPROC_SEQUENTIAL; + cinfo->num_scans = 1; + } + +#ifdef WITH_ARITHMETIC_PATCH + if ((cinfo->arith_code == 0) && + (cinfo->process == JPROC_PROGRESSIVE || /* TEMPORARY HACK ??? */ + cinfo->process == JPROC_LOSSLESS)) +#else + if (cinfo->process == JPROC_PROGRESSIVE || /* TEMPORARY HACK ??? */ + cinfo->process == JPROC_LOSSLESS) +#endif + cinfo->optimize_coding = TRUE; /* assume default tables no good for + * progressive mode or lossless mode */ + + /* Initialize my private state */ + if (transcode_only) { + /* no main pass in transcoding */ + if (cinfo->optimize_coding) + master->pass_type = huff_opt_pass; + else + master->pass_type = output_pass; + } else { + /* for normal compression, first pass is always this type: */ + master->pass_type = main_pass; + } + master->scan_number = 0; + master->pass_number = 0; + if (cinfo->optimize_coding) + master->total_passes = cinfo->num_scans * 2; + else + master->total_passes = cinfo->num_scans; +} diff --git a/dcmjpeg/libijg16/jcodec.c b/dcmjpeg/libijg16/jcodec.c new file mode 100644 index 00000000..5fbc9fc1 --- /dev/null +++ b/dcmjpeg/libijg16/jcodec.c @@ -0,0 +1,53 @@ +/* + * jcodec.c + * + * Copyright (C) 1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains utility functions for the JPEG codec(s). + */ + +#define JPEG_INTERNALS +#include "jinclude16.h" +#include "jpeglib16.h" +#include "jlossy16.h" +#include "jlossls16.h" + + +/* + * Initialize the compression codec. + * This is called only once, during master selection. + */ + +GLOBAL(void) +jinit_c_codec (j_compress_ptr cinfo) +{ + if (cinfo->process == JPROC_LOSSLESS) { +#ifdef C_LOSSLESS_SUPPORTED + jinit_lossless_c_codec(cinfo); +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } else + jinit_lossy_c_codec(cinfo); +} + + +/* + * Initialize the decompression codec. + * This is called only once, during master selection. + */ + +GLOBAL(void) +jinit_d_codec (j_decompress_ptr cinfo) +{ + if (cinfo->process == JPROC_LOSSLESS) { +#ifdef D_LOSSLESS_SUPPORTED + jinit_lossless_d_codec(cinfo); +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } else + jinit_lossy_d_codec(cinfo); +} diff --git a/dcmjpeg/libijg16/jcomapi.c b/dcmjpeg/libijg16/jcomapi.c new file mode 100644 index 00000000..872c8469 --- /dev/null +++ b/dcmjpeg/libijg16/jcomapi.c @@ -0,0 +1,106 @@ +/* + * jcomapi.c + * + * Copyright (C) 1994-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains application interface routines that are used for both + * compression and decompression. + */ + +#define JPEG_INTERNALS +#include "jinclude16.h" +#include "jpeglib16.h" + + +/* + * Abort processing of a JPEG compression or decompression operation, + * but don't destroy the object itself. + * + * For this, we merely clean up all the nonpermanent memory pools. + * Note that temp files (virtual arrays) are not allowed to belong to + * the permanent pool, so we will be able to close all temp files here. + * Closing a data source or destination, if necessary, is the application's + * responsibility. + */ + +GLOBAL(void) +jpeg_abort (j_common_ptr cinfo) +{ + int pool; + + /* Do nothing if called on a not-initialized or destroyed JPEG object. */ + if (cinfo->mem == NULL) + return; + + /* Releasing pools in reverse order might help avoid fragmentation + * with some (brain-damaged) malloc libraries. + */ + for (pool = JPOOL_NUMPOOLS-1; pool > JPOOL_PERMANENT; pool--) { + (*cinfo->mem->free_pool) (cinfo, pool); + } + + /* Reset overall state for possible reuse of object */ + if (cinfo->is_decompressor) { + cinfo->global_state = DSTATE_START; + /* Try to keep application from accessing now-deleted marker list. + * A bit kludgy to do it here, but this is the most central place. + */ + ((j_decompress_ptr) cinfo)->marker_list = NULL; + } else { + cinfo->global_state = CSTATE_START; + } +} + + +/* + * Destruction of a JPEG object. + * + * Everything gets deallocated except the master jpeg_compress_struct itself + * and the error manager struct. Both of these are supplied by the application + * and must be freed, if necessary, by the application. (Often they are on + * the stack and so don't need to be freed anyway.) + * Closing a data source or destination, if necessary, is the application's + * responsibility. + */ + +GLOBAL(void) +jpeg_destroy (j_common_ptr cinfo) +{ + /* We need only tell the memory manager to release everything. */ + /* NB: mem pointer is NULL if memory mgr failed to initialize. */ + if (cinfo->mem != NULL) + (*cinfo->mem->self_destruct) (cinfo); + cinfo->mem = NULL; /* be safe if jpeg_destroy is called twice */ + cinfo->global_state = 0; /* mark it destroyed */ +} + + +/* + * Convenience routines for allocating quantization and Huffman tables. + * (Would jutils.c be a more reasonable place to put these?) + */ + +GLOBAL(JQUANT_TBL *) +jpeg_alloc_quant_table (j_common_ptr cinfo) +{ + JQUANT_TBL *tbl; + + tbl = (JQUANT_TBL *) + (*cinfo->mem->alloc_small) (cinfo, JPOOL_PERMANENT, SIZEOF(JQUANT_TBL)); + tbl->sent_table = FALSE; /* make sure this is false in any new table */ + return tbl; +} + + +GLOBAL(JHUFF_TBL *) +jpeg_alloc_huff_table (j_common_ptr cinfo) +{ + JHUFF_TBL *tbl; + + tbl = (JHUFF_TBL *) + (*cinfo->mem->alloc_small) (cinfo, JPOOL_PERMANENT, SIZEOF(JHUFF_TBL)); + tbl->sent_table = FALSE; /* make sure this is false in any new table */ + return tbl; +} diff --git a/dcmjpeg/libijg16/jconfig16.h b/dcmjpeg/libijg16/jconfig16.h new file mode 100644 index 00000000..4dd87d61 --- /dev/null +++ b/dcmjpeg/libijg16/jconfig16.h @@ -0,0 +1,73 @@ +/* + * + * Copyright (C) 1998-2010, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmjpeg + * + * Author: Marco Eichelberg + * + * Purpose: + * this file derives the preprocessor symbols required to compile + * the IJG library from the central DCMTK configuration file osconfig.h + * + */ + +#include "dcmtk/config/osconfig.h" + +/* We assume ANSI C and don't support DOS, + * so the following settings need not be tested + */ +#define HAVE_PROTOTYPES +#define HAVE_UNSIGNED_CHAR +#define HAVE_UNSIGNED_SHORT +#undef NEED_FAR_POINTERS +#undef INCOMPLETE_TYPES_BROKEN + +/* the following settings are derived from osconfig.h */ + +#ifndef HAVE_C_CONST +#define const +#endif + +#ifdef C_CHAR_UNSIGNED +#define CHAR_IS_UNSIGNED +#endif + +#ifdef HAVE_STRINGS_H +#ifndef HAVE_STRING_H +#define NEED_BSD_STRINGS +#endif +#endif + +#ifdef HAVE_SYS_TYPES_H +#define NEED_SYS_TYPES_H +#endif + +/* must always be defined for our implementation */ +#define NEED_SHORT_EXTERNAL_NAMES + +#ifdef JPEG_INTERNALS + +#ifdef C_RIGHTSHIFT_UNSIGNED +#define RIGHT_SHIFT_IS_UNSIGNED +#endif + +#define INLINE C_INLINE + +/* These are for configuring the JPEG memory manager. */ +#undef DEFAULT_MAX_MEM +#undef NO_MKTEMP + +/* We don't want to use getenv which is thread unsafe on some platforms */ +#define NO_GETENV + +#endif /* JPEG_INTERNALS */ diff --git a/dcmjpeg/libijg16/jcparam.c b/dcmjpeg/libijg16/jcparam.c new file mode 100644 index 00000000..28c1dabf --- /dev/null +++ b/dcmjpeg/libijg16/jcparam.c @@ -0,0 +1,687 @@ +/* + * jcparam.c + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains optional default-setting code for the JPEG compressor. + * Applications do not have to use this file, but those that don't use it + * must know a lot more about the innards of the JPEG code. + */ + +#define JPEG_INTERNALS +#include "jinclude16.h" +#include "jpeglib16.h" + + +/* + * Quantization table setup routines + */ + +GLOBAL(void) +jpeg_add_quant_table (j_compress_ptr cinfo, int which_tbl, + const unsigned int *basic_table, + int scale_factor, boolean force_baseline) +/* Define a quantization table equal to the basic_table times + * a scale factor (given as a percentage). + * If force_baseline is TRUE, the computed quantization table entries + * are limited to 1..255 for JPEG baseline compatibility. + */ +{ + JQUANT_TBL ** qtblptr; + int i; + long temp; + + /* Safety check to ensure start_compress not called yet. */ + if (cinfo->global_state != CSTATE_START) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + + if (which_tbl < 0 || which_tbl >= NUM_QUANT_TBLS) + ERREXIT1(cinfo, JERR_DQT_INDEX, which_tbl); + + qtblptr = & cinfo->quant_tbl_ptrs[which_tbl]; + + if (*qtblptr == NULL) + *qtblptr = jpeg_alloc_quant_table((j_common_ptr) cinfo); + + for (i = 0; i < DCTSIZE2; i++) { + temp = ((long) basic_table[i] * scale_factor + 50L) / 100L; + /* limit the values to the valid range */ + if (temp <= 0L) temp = 1L; + if (temp > 32767L) temp = 32767L; /* max quantizer needed for 12 bits */ + if (force_baseline && temp > 255L) + temp = 255L; /* limit to baseline range if requested */ + (*qtblptr)->quantval[i] = (UINT16) temp; + } + + /* Initialize sent_table FALSE so table will be written to JPEG file. */ + (*qtblptr)->sent_table = FALSE; +} + + +GLOBAL(void) +jpeg_set_linear_quality (j_compress_ptr cinfo, int scale_factor, + boolean force_baseline) +/* Set or change the 'quality' (quantization) setting, using default tables + * and a straight percentage-scaling quality scale. In most cases it's better + * to use jpeg_set_quality (below); this entry point is provided for + * applications that insist on a linear percentage scaling. + */ +{ + /* These are the sample quantization tables given in JPEG spec section K.1. + * The spec says that the values given produce "good" quality, and + * when divided by 2, "very good" quality. + */ + static const unsigned int std_luminance_quant_tbl[DCTSIZE2] = { + 16, 11, 10, 16, 24, 40, 51, 61, + 12, 12, 14, 19, 26, 58, 60, 55, + 14, 13, 16, 24, 40, 57, 69, 56, + 14, 17, 22, 29, 51, 87, 80, 62, + 18, 22, 37, 56, 68, 109, 103, 77, + 24, 35, 55, 64, 81, 104, 113, 92, + 49, 64, 78, 87, 103, 121, 120, 101, + 72, 92, 95, 98, 112, 100, 103, 99 + }; + static const unsigned int std_chrominance_quant_tbl[DCTSIZE2] = { + 17, 18, 24, 47, 99, 99, 99, 99, + 18, 21, 26, 66, 99, 99, 99, 99, + 24, 26, 56, 99, 99, 99, 99, 99, + 47, 66, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99 + }; + + /* Set up two quantization tables using the specified scaling */ + jpeg_add_quant_table(cinfo, 0, std_luminance_quant_tbl, + scale_factor, force_baseline); + jpeg_add_quant_table(cinfo, 1, std_chrominance_quant_tbl, + scale_factor, force_baseline); +} + + +GLOBAL(int) +jpeg_quality_scaling (int quality) +/* Convert a user-specified quality rating to a percentage scaling factor + * for an underlying quantization table, using our recommended scaling curve. + * The input 'quality' factor should be 0 (terrible) to 100 (very good). + */ +{ + /* Safety limit on quality factor. Convert 0 to 1 to avoid zero divide. */ + if (quality <= 0) quality = 1; + if (quality > 100) quality = 100; + + /* The basic table is used as-is (scaling 100) for a quality of 50. + * Qualities 50..100 are converted to scaling percentage 200 - 2*Q; + * note that at Q=100 the scaling is 0, which will cause jpeg_add_quant_table + * to make all the table entries 1 (hence, minimum quantization loss). + * Qualities 1..50 are converted to scaling percentage 5000/Q. + */ + if (quality < 50) + quality = 5000 / quality; + else + quality = 200 - quality*2; + + return quality; +} + + +GLOBAL(void) +jpeg_set_quality (j_compress_ptr cinfo, int quality, boolean force_baseline) +/* Set or change the 'quality' (quantization) setting, using default tables. + * This is the standard quality-adjusting entry point for typical user + * interfaces; only those who want detailed control over quantization tables + * would use the preceding three routines directly. + */ +{ + /* Convert user 0-100 rating to percentage scaling */ + quality = jpeg_quality_scaling(quality); + + /* Set up standard quality tables */ + jpeg_set_linear_quality(cinfo, quality, force_baseline); +} + + +/* + * Huffman table setup routines + */ + +LOCAL(void) +add_huff_table (j_compress_ptr cinfo, + JHUFF_TBL **htblptr, const UINT8 *bits, const UINT8 *val) +/* Define a Huffman table */ +{ + int nsymbols, len; + + if (*htblptr == NULL) + *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo); + + /* Copy the number-of-symbols-of-each-code-length counts */ + MEMCOPY((*htblptr)->bits, bits, SIZEOF((*htblptr)->bits)); + + /* Validate the counts. We do this here mainly so we can copy the right + * number of symbols from the val[] array, without risking marching off + * the end of memory. jchuff.c will do a more thorough test later. + */ + nsymbols = 0; + for (len = 1; len <= 16; len++) + nsymbols += bits[len]; + if (nsymbols < 1 || nsymbols > 256) + ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); + + MEMCOPY((*htblptr)->huffval, val, (size_t)nsymbols * SIZEOF(UINT8)); + + /* Initialize sent_table FALSE so table will be written to JPEG file. */ + (*htblptr)->sent_table = FALSE; +} + + +LOCAL(void) +std_huff_tables (j_compress_ptr cinfo) +/* Set up the standard Huffman tables (cf. JPEG standard section K.3) */ +/* IMPORTANT: these are only valid for 8-bit data precision! */ +{ + static const UINT8 bits_dc_luminance[17] = + { /* 0-base */ 0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 }; + static const UINT8 val_dc_luminance[] = + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }; + + static const UINT8 bits_dc_chrominance[17] = + { /* 0-base */ 0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 }; + static const UINT8 val_dc_chrominance[] = + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }; + + static const UINT8 bits_ac_luminance[17] = + { /* 0-base */ 0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d }; + static const UINT8 val_ac_luminance[] = + { 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, + 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, + 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08, + 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0, + 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16, + 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28, + 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, + 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, + 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, + 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, + 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, + 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, + 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, + 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, + 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, + 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, + 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, + 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2, + 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, + 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, + 0xf9, 0xfa }; + + static const UINT8 bits_ac_chrominance[17] = + { /* 0-base */ 0, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77 }; + static const UINT8 val_ac_chrominance[] = + { 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, + 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71, + 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, + 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0, + 0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34, + 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26, + 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38, + 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, + 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, + 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, + 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, + 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, + 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, + 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, + 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, + 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, + 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, + 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, + 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, + 0xf9, 0xfa }; + + add_huff_table(cinfo, &cinfo->dc_huff_tbl_ptrs[0], + bits_dc_luminance, val_dc_luminance); + add_huff_table(cinfo, &cinfo->ac_huff_tbl_ptrs[0], + bits_ac_luminance, val_ac_luminance); + add_huff_table(cinfo, &cinfo->dc_huff_tbl_ptrs[1], + bits_dc_chrominance, val_dc_chrominance); + add_huff_table(cinfo, &cinfo->ac_huff_tbl_ptrs[1], + bits_ac_chrominance, val_ac_chrominance); +} + + +/* + * Default parameter setup for compression. + * + * Applications that don't choose to use this routine must do their + * own setup of all these parameters. Alternately, you can call this + * to establish defaults and then alter parameters selectively. This + * is the recommended approach since, if we add any new parameters, + * your code will still work (they'll be set to reasonable defaults). + */ + +GLOBAL(void) +jpeg_set_defaults (j_compress_ptr cinfo) +{ + int i; + + /* Safety check to ensure start_compress not called yet. */ + if (cinfo->global_state != CSTATE_START) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + + /* Allocate comp_info array large enough for maximum component count. + * Array is made permanent in case application wants to compress + * multiple images at same param settings. + */ + if (cinfo->comp_info == NULL) + cinfo->comp_info = (jpeg_component_info *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, + MAX_COMPONENTS * SIZEOF(jpeg_component_info)); + + /* Initialize everything not dependent on the color space */ + + cinfo->lossless = FALSE; + cinfo->data_precision = BITS_IN_JSAMPLE; + /* Set up two quantization tables using default quality of 75 */ + jpeg_set_quality(cinfo, 75, TRUE); + /* Set up two Huffman tables */ + std_huff_tables(cinfo); + + /* Initialize default arithmetic coding conditioning */ + for (i = 0; i < NUM_ARITH_TBLS; i++) { + cinfo->arith_dc_L[i] = 0; + cinfo->arith_dc_U[i] = 1; + cinfo->arith_ac_K[i] = 5; + } + + /* Default is no multiple-scan output */ + cinfo->scan_info = NULL; + cinfo->num_scans = 0; + + /* Expect normal source image, not raw downsampled data */ + cinfo->raw_data_in = FALSE; + + /* Use Huffman coding, not arithmetic coding, by default */ + cinfo->arith_code = FALSE; + + /* By default, don't do extra passes to optimize entropy coding */ + cinfo->optimize_coding = FALSE; + /* The standard Huffman tables are only valid for 8-bit data precision. + * If the precision is higher, force optimization on so that usable + * tables will be computed. This test can be removed if default tables + * are supplied that are valid for the desired precision. + */ + if (cinfo->data_precision > 8) + cinfo->optimize_coding = TRUE; + + /* By default, use the simpler non-cosited sampling alignment */ + cinfo->CCIR601_sampling = FALSE; + + /* No input smoothing */ + cinfo->smoothing_factor = 0; + + /* DCT algorithm preference */ + cinfo->dct_method = JDCT_DEFAULT; + + /* No restart markers */ + cinfo->restart_interval = 0; + cinfo->restart_in_rows = 0; + + /* Fill in default JFIF marker parameters. Note that whether the marker + * will actually be written is determined by jpeg_set_colorspace. + * + * By default, the library emits JFIF version code 1.01. + * An application that wants to emit JFIF 1.02 extension markers should set + * JFIF_minor_version to 2. We could probably get away with just defaulting + * to 1.02, but there may still be some decoders in use that will complain + * about that; saying 1.01 should minimize compatibility problems. + */ + cinfo->JFIF_major_version = 1; /* Default JFIF version = 1.01 */ + cinfo->JFIF_minor_version = 1; + cinfo->density_unit = 0; /* Pixel size is unknown by default */ + cinfo->X_density = 1; /* Pixel aspect ratio is square by default */ + cinfo->Y_density = 1; + + /* Choose JPEG colorspace based on input space, set defaults accordingly */ + + jpeg_default_colorspace(cinfo); +} + + +/* + * Select an appropriate JPEG colorspace for in_color_space. + */ + +GLOBAL(void) +jpeg_default_colorspace (j_compress_ptr cinfo) +{ + if (cinfo->lossless) + jpeg_set_colorspace(cinfo, cinfo->in_color_space); + else { /* lossy */ + switch (cinfo->in_color_space) { + case JCS_GRAYSCALE: + jpeg_set_colorspace(cinfo, JCS_GRAYSCALE); + break; + case JCS_RGB: + jpeg_set_colorspace(cinfo, JCS_YCbCr); + break; + case JCS_YCbCr: + jpeg_set_colorspace(cinfo, JCS_YCbCr); + break; + case JCS_CMYK: + jpeg_set_colorspace(cinfo, JCS_CMYK); /* By default, no translation */ + break; + case JCS_YCCK: + jpeg_set_colorspace(cinfo, JCS_YCCK); + break; + case JCS_UNKNOWN: + jpeg_set_colorspace(cinfo, JCS_UNKNOWN); + break; + default: + ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); + } + } +} + + +/* + * Set the JPEG colorspace, and choose colorspace-dependent default values. + */ + +GLOBAL(void) +jpeg_set_colorspace (j_compress_ptr cinfo, J_COLOR_SPACE colorspace) +{ + jpeg_component_info * compptr; + int ci; + +#define SET_COMP(index,id,hsamp,vsamp,quant,dctbl,actbl) \ + (compptr = &cinfo->comp_info[index], \ + compptr->component_id = (id), \ + compptr->h_samp_factor = (hsamp), \ + compptr->v_samp_factor = (vsamp), \ + compptr->quant_tbl_no = (quant), \ + compptr->dc_tbl_no = (dctbl), \ + compptr->ac_tbl_no = (actbl) ) + + /* Safety check to ensure start_compress not called yet. */ + if (cinfo->global_state != CSTATE_START) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + + /* For all colorspaces, we use Q and Huff tables 0 for luminance components, + * tables 1 for chrominance components. + */ + + cinfo->jpeg_color_space = colorspace; + + cinfo->write_JFIF_header = FALSE; /* No marker for non-JFIF colorspaces */ + cinfo->write_Adobe_marker = FALSE; /* write no Adobe marker by default */ + + switch (colorspace) { + case JCS_GRAYSCALE: + cinfo->write_JFIF_header = TRUE; /* Write a JFIF marker */ + cinfo->num_components = 1; + /* JFIF specifies component ID 1 */ + SET_COMP(0, 1, 1,1, 0, 0,0); + break; + case JCS_RGB: + cinfo->write_Adobe_marker = TRUE; /* write Adobe marker to flag RGB */ + cinfo->num_components = 3; + SET_COMP(0, 0x52 /* 'R' */, 1,1, 0, 0,0); + SET_COMP(1, 0x47 /* 'G' */, 1,1, 0, 0,0); + SET_COMP(2, 0x42 /* 'B' */, 1,1, 0, 0,0); + break; + case JCS_YCbCr: + cinfo->write_JFIF_header = TRUE; /* Write a JFIF marker */ + cinfo->num_components = 3; + /* JFIF specifies component IDs 1,2,3 */ + if (cinfo->lossless) { + SET_COMP(0, 1, 1,1, 0, 0,0); + SET_COMP(1, 2, 1,1, 1, 1,1); + SET_COMP(2, 3, 1,1, 1, 1,1); + } else { /* lossy */ + /* We default to 2x2 subsamples of chrominance */ + SET_COMP(0, 1, 2,2, 0, 0,0); + SET_COMP(1, 2, 1,1, 1, 1,1); + SET_COMP(2, 3, 1,1, 1, 1,1); + } + break; + case JCS_CMYK: + cinfo->write_Adobe_marker = TRUE; /* write Adobe marker to flag CMYK */ + cinfo->num_components = 4; + SET_COMP(0, 0x43 /* 'C' */, 1,1, 0, 0,0); + SET_COMP(1, 0x4D /* 'M' */, 1,1, 0, 0,0); + SET_COMP(2, 0x59 /* 'Y' */, 1,1, 0, 0,0); + SET_COMP(3, 0x4B /* 'K' */, 1,1, 0, 0,0); + break; + case JCS_YCCK: + cinfo->write_Adobe_marker = TRUE; /* write Adobe marker to flag YCCK */ + cinfo->num_components = 4; + if (cinfo->lossless) { + SET_COMP(0, 1, 1,1, 0, 0,0); + SET_COMP(1, 2, 1,1, 1, 1,1); + SET_COMP(2, 3, 1,1, 1, 1,1); + SET_COMP(3, 4, 1,1, 0, 0,0); + } else { /* lossy */ + SET_COMP(0, 1, 2,2, 0, 0,0); + SET_COMP(1, 2, 1,1, 1, 1,1); + SET_COMP(2, 3, 1,1, 1, 1,1); + SET_COMP(3, 4, 2,2, 0, 0,0); + } + break; + case JCS_UNKNOWN: + cinfo->num_components = cinfo->input_components; + if (cinfo->num_components < 1 || cinfo->num_components > MAX_COMPONENTS) + ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components, + MAX_COMPONENTS); + for (ci = 0; ci < cinfo->num_components; ci++) { + SET_COMP(ci, ci, 1,1, 0, 0,0); + } + break; + default: + ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); + } +} + + +#ifdef C_PROGRESSIVE_SUPPORTED + +LOCAL(jpeg_scan_info *) +fill_scans (jpeg_scan_info * scanptr, int ncomps, + int Ss, int Se, int Ah, int Al) +/* Support routine: generate one scan for each component */ +{ + int ci; + + for (ci = 0; ci < ncomps; ci++) { + scanptr->comps_in_scan = 1; + scanptr->component_index[0] = ci; + scanptr->Ss = Ss; + scanptr->Se = Se; + scanptr->Ah = Ah; + scanptr->Al = Al; + scanptr++; + } + return scanptr; +} + + +LOCAL(jpeg_scan_info *) +fill_a_scan (jpeg_scan_info * scanptr, int ci, + int Ss, int Se, int Ah, int Al) +/* Support routine: generate one scan for specified component */ +{ + scanptr->comps_in_scan = 1; + scanptr->component_index[0] = ci; + scanptr->Ss = Ss; + scanptr->Se = Se; + scanptr->Ah = Ah; + scanptr->Al = Al; + scanptr++; + return scanptr; +} + +LOCAL(jpeg_scan_info *) +fill_dc_scans (jpeg_scan_info * scanptr, int ncomps, int Ah, int Al) +/* Support routine: generate interleaved DC scan if possible, else N scans */ +{ + int ci; + + if (ncomps <= MAX_COMPS_IN_SCAN) { + /* Single interleaved DC scan */ + scanptr->comps_in_scan = ncomps; + for (ci = 0; ci < ncomps; ci++) + scanptr->component_index[ci] = ci; + scanptr->Ss = scanptr->Se = 0; + scanptr->Ah = Ah; + scanptr->Al = Al; + scanptr++; + } else { + /* Noninterleaved DC scan for each component */ + scanptr = fill_scans(scanptr, ncomps, 0, 0, Ah, Al); + } + return scanptr; +} + + +/* + * Create a recommended progressive-JPEG script. + * cinfo->num_components and cinfo->jpeg_color_space must be correct. + */ + +GLOBAL(void) +jpeg_simple_progression (j_compress_ptr cinfo) +{ + int ncomps = cinfo->num_components; + int nscans; + jpeg_scan_info * scanptr; + + /* Safety check to ensure start_compress not called yet. */ + if (cinfo->global_state != CSTATE_START) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + + /* Figure space needed for script. Calculation must match code below! */ + if (ncomps == 3 && cinfo->jpeg_color_space == JCS_YCbCr) { + /* Custom script for YCbCr color images. */ + nscans = 10; + } else { + /* All-purpose script for other color spaces. */ + if (ncomps > MAX_COMPS_IN_SCAN) + nscans = 6 * ncomps; /* 2 DC + 4 AC scans per component */ + else + nscans = 2 + 4 * ncomps; /* 2 DC scans; 4 AC scans per component */ + } + + /* Allocate space for script. + * We need to put it in the permanent pool in case the application performs + * multiple compressions without changing the settings. To avoid a memory + * leak if jpeg_simple_progression is called repeatedly for the same JPEG + * object, we try to re-use previously allocated space, and we allocate + * enough space to handle YCbCr even if initially asked for grayscale. + */ + if (cinfo->script_space == NULL || cinfo->script_space_size < nscans) { + cinfo->script_space_size = MAX(nscans, 10); + cinfo->script_space = (jpeg_scan_info *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, + (size_t)cinfo->script_space_size * SIZEOF(jpeg_scan_info)); + } + scanptr = cinfo->script_space; + cinfo->scan_info = scanptr; + cinfo->num_scans = nscans; + + if (ncomps == 3 && cinfo->jpeg_color_space == JCS_YCbCr) { + /* Custom script for YCbCr color images. */ + /* Initial DC scan */ + scanptr = fill_dc_scans(scanptr, ncomps, 0, 1); + /* Initial AC scan: get some luma data out in a hurry */ + scanptr = fill_a_scan(scanptr, 0, 1, 5, 0, 2); + /* Chroma data is too small to be worth expending many scans on */ + scanptr = fill_a_scan(scanptr, 2, 1, 63, 0, 1); + scanptr = fill_a_scan(scanptr, 1, 1, 63, 0, 1); + /* Complete spectral selection for luma AC */ + scanptr = fill_a_scan(scanptr, 0, 6, 63, 0, 2); + /* Refine next bit of luma AC */ + scanptr = fill_a_scan(scanptr, 0, 1, 63, 2, 1); + /* Finish DC successive approximation */ + scanptr = fill_dc_scans(scanptr, ncomps, 1, 0); + /* Finish AC successive approximation */ + scanptr = fill_a_scan(scanptr, 2, 1, 63, 1, 0); + scanptr = fill_a_scan(scanptr, 1, 1, 63, 1, 0); + /* Luma bottom bit comes last since it's usually largest scan */ + scanptr = fill_a_scan(scanptr, 0, 1, 63, 1, 0); + } else { + /* All-purpose script for other color spaces. */ + /* Successive approximation first pass */ + scanptr = fill_dc_scans(scanptr, ncomps, 0, 1); + scanptr = fill_scans(scanptr, ncomps, 1, 5, 0, 2); + scanptr = fill_scans(scanptr, ncomps, 6, 63, 0, 2); + /* Successive approximation second pass */ + scanptr = fill_scans(scanptr, ncomps, 1, 63, 2, 1); + /* Successive approximation final pass */ + scanptr = fill_dc_scans(scanptr, ncomps, 1, 0); + scanptr = fill_scans(scanptr, ncomps, 1, 63, 1, 0); + } +} + +#endif /* C_PROGRESSIVE_SUPPORTED */ + + +#ifdef C_LOSSLESS_SUPPORTED + +/* + * Create a single-entry lossless-JPEG script containing all components. + * cinfo->num_components must be correct. + */ + +GLOBAL(void) +jpeg_simple_lossless (j_compress_ptr cinfo, int predictor, int point_transform) +{ + int ncomps = cinfo->num_components; + int nscans = 1; + int ci; + jpeg_scan_info * scanptr; + + /* Safety check to ensure start_compress not called yet. */ + if (cinfo->global_state != CSTATE_START) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + + cinfo->lossless = TRUE; + + /* Set jpeg_color_space. */ + jpeg_default_colorspace(cinfo); + + /* Check to ensure that all components will fit in one scan. */ + if (cinfo->num_components > MAX_COMPS_IN_SCAN) + ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components, + MAX_COMPS_IN_SCAN); + + /* Allocate space for script. + * We need to put it in the permanent pool in case the application performs + * multiple compressions without changing the settings. To avoid a memory + * leak if jpeg_simple_lossless is called repeatedly for the same JPEG + * object, we try to re-use previously allocated space. + */ + if (cinfo->script_space == NULL || cinfo->script_space_size < nscans) { + cinfo->script_space_size = nscans; + cinfo->script_space = (jpeg_scan_info *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, + (size_t)cinfo->script_space_size * SIZEOF(jpeg_scan_info)); + } + scanptr = cinfo->script_space; + cinfo->scan_info = scanptr; + cinfo->num_scans = nscans; + + /* Fill the script. */ + scanptr->comps_in_scan = ncomps; + for (ci = 0; ci < (int)ncomps; ci++) + scanptr->component_index[ci] = ci; + scanptr->Ss = predictor; + scanptr->Se = 0; + scanptr->Ah = 0; + scanptr->Al = point_transform; +} + +#endif /* C_LOSSLESS_SUPPORTED */ diff --git a/dcmjpeg/libijg16/jcphuff.c b/dcmjpeg/libijg16/jcphuff.c new file mode 100644 index 00000000..a2bfab47 --- /dev/null +++ b/dcmjpeg/libijg16/jcphuff.c @@ -0,0 +1,848 @@ +/* + * jcphuff.c + * + * Copyright (C) 1995-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains Huffman entropy encoding routines for progressive JPEG. + * + * We do not support output suspension in this module, since the library + * currently does not allow multiple-scan files to be written with output + * suspension. + */ + +#define JPEG_INTERNALS +#include "jinclude16.h" +#include "jpeglib16.h" +#include "jlossy16.h" /* Private declarations for lossy codec */ +#include "jchuff16.h" /* Declarations shared with jc*huff.c */ + +#ifdef C_PROGRESSIVE_SUPPORTED + +/* Expanded entropy encoder object for progressive Huffman encoding. */ + +typedef struct { + /* Mode flag: TRUE for optimization, FALSE for actual data output */ + boolean gather_statistics; + + /* Bit-level coding status. + * next_output_byte/free_in_buffer are local copies of cinfo->dest fields. + */ + JOCTET * next_output_byte; /* => next byte to write in buffer */ + size_t free_in_buffer; /* # of byte spaces remaining in buffer */ + IJG_INT32 put_buffer; /* current bit-accumulation buffer */ + int put_bits; /* # of bits now in it */ + j_compress_ptr cinfo; /* link to cinfo (needed for dump_buffer) */ + + /* Coding status for DC components */ + int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */ + + /* Coding status for AC components */ + int ac_tbl_no; /* the table number of the single component */ + unsigned int EOBRUN; /* run length of EOBs */ + unsigned int BE; /* # of buffered correction bits before MCU */ + char * bit_buffer; /* buffer for correction bits (1 per char) */ + /* packing correction bits tightly would save some space but cost time... */ + + unsigned int restarts_to_go; /* MCUs left in this restart interval */ + int next_restart_num; /* next restart number to write (0-7) */ + + /* Pointers to derived tables (these workspaces have image lifespan). + * Since any one scan codes only DC or only AC, we only need one set + * of tables, not one for DC and one for AC. + */ + c_derived_tbl * derived_tbls[NUM_HUFF_TBLS]; + + /* Statistics tables for optimization; again, one set is enough */ + long * count_ptrs[NUM_HUFF_TBLS]; +} phuff_entropy_encoder; + +typedef phuff_entropy_encoder * phuff_entropy_ptr; + +/* MAX_CORR_BITS is the number of bits the AC refinement correction-bit + * buffer can hold. Larger sizes may slightly improve compression, but + * 1000 is already well into the realm of overkill. + * The minimum safe size is 64 bits. + */ + +#define MAX_CORR_BITS 1000 /* Max # of correction bits I can buffer */ + +/* IRIGHT_SHIFT is like RIGHT_SHIFT, but works on int rather than IJG_INT32. + * We assume that int right shift is unsigned if IJG_INT32 right shift is, + * which should be safe. + */ + +#ifdef RIGHT_SHIFT_IS_UNSIGNED +#define ISHIFT_TEMPS int ishift_temp; +#define IRIGHT_SHIFT(x,shft) \ + ((ishift_temp = (x)) < 0 ? \ + (ishift_temp >> (shft)) | ((~0) << (16-(shft))) : \ + (ishift_temp >> (shft))) +#else +#define ISHIFT_TEMPS +#define IRIGHT_SHIFT(x,shft) ((x) >> (shft)) +#endif + +/* Forward declarations */ +METHODDEF(boolean) encode_mcu_DC_first JPP((j_compress_ptr cinfo, + JBLOCKROW *MCU_data)); +METHODDEF(boolean) encode_mcu_AC_first JPP((j_compress_ptr cinfo, + JBLOCKROW *MCU_data)); +METHODDEF(boolean) encode_mcu_DC_refine JPP((j_compress_ptr cinfo, + JBLOCKROW *MCU_data)); +METHODDEF(boolean) encode_mcu_AC_refine JPP((j_compress_ptr cinfo, + JBLOCKROW *MCU_data)); +METHODDEF(void) finish_pass_phuff JPP((j_compress_ptr cinfo)); +METHODDEF(void) finish_pass_gather_phuff JPP((j_compress_ptr cinfo)); + + +/* + * Initialize for a Huffman-compressed scan using progressive JPEG. + */ + +METHODDEF(void) +start_pass_phuff (j_compress_ptr cinfo, boolean gather_statistics) +{ + j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; + phuff_entropy_ptr entropy = (phuff_entropy_ptr) lossyc->entropy_private; + boolean is_DC_band; + int ci, tbl; + jpeg_component_info * compptr; + + entropy->cinfo = cinfo; + entropy->gather_statistics = gather_statistics; + + is_DC_band = (cinfo->Ss == 0); + + /* We assume jcmaster.c already validated the scan parameters. */ + + /* Select execution routines */ + if (cinfo->Ah == 0) { + if (is_DC_band) + lossyc->entropy_encode_mcu = encode_mcu_DC_first; + else + lossyc->entropy_encode_mcu = encode_mcu_AC_first; + } else { + if (is_DC_band) + lossyc->entropy_encode_mcu = encode_mcu_DC_refine; + else { + lossyc->entropy_encode_mcu = encode_mcu_AC_refine; + /* AC refinement needs a correction bit buffer */ + if (entropy->bit_buffer == NULL) + entropy->bit_buffer = (char *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + MAX_CORR_BITS * SIZEOF(char)); + } + } + if (gather_statistics) + lossyc->pub.entropy_finish_pass = finish_pass_gather_phuff; + else + lossyc->pub.entropy_finish_pass = finish_pass_phuff; + + /* Only DC coefficients may be interleaved, so cinfo->comps_in_scan = 1 + * for AC coefficients. + */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + /* Initialize DC predictions to 0 */ + entropy->last_dc_val[ci] = 0; + /* Get table index */ + if (is_DC_band) { + if (cinfo->Ah != 0) /* DC refinement needs no table */ + continue; + tbl = compptr->dc_tbl_no; + } else { + entropy->ac_tbl_no = tbl = compptr->ac_tbl_no; + } + if (gather_statistics) { + /* Check for invalid table index */ + /* (make_c_derived_tbl does this in the other path) */ + if (tbl < 0 || tbl >= NUM_HUFF_TBLS) + ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tbl); + /* Allocate and zero the statistics tables */ + /* Note that jpeg_gen_optimal_table expects 257 entries in each table! */ + if (entropy->count_ptrs[tbl] == NULL) + entropy->count_ptrs[tbl] = (long *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + 257 * SIZEOF(long)); + MEMZERO(entropy->count_ptrs[tbl], 257 * SIZEOF(long)); + } else { + /* Compute derived values for Huffman table */ + /* We may do this more than once for a table, but it's not expensive */ + jpeg_make_c_derived_tbl(cinfo, is_DC_band, tbl, + & entropy->derived_tbls[tbl]); + } + } + + /* Initialize AC stuff */ + entropy->EOBRUN = 0; + entropy->BE = 0; + + /* Initialize bit buffer to empty */ + entropy->put_buffer = 0; + entropy->put_bits = 0; + + /* Initialize restart stuff */ + entropy->restarts_to_go = cinfo->restart_interval; + entropy->next_restart_num = 0; +} + + +/* Outputting bytes to the file. + * NB: these must be called only when actually outputting, + * that is, entropy->gather_statistics == FALSE. + */ + +/* Emit a byte */ +#define emit_byte(entropy,val) \ + { *(entropy)->next_output_byte++ = (JOCTET) (val); \ + if (--(entropy)->free_in_buffer == 0) \ + dump_buffer(entropy); } + + +LOCAL(void) +dump_buffer (phuff_entropy_ptr entropy) +/* Empty the output buffer; we do not support suspension in this module. */ +{ + struct jpeg_destination_mgr * dest = entropy->cinfo->dest; + + if (! (*dest->empty_output_buffer) (entropy->cinfo)) + ERREXIT(entropy->cinfo, JERR_CANT_SUSPEND); + /* After a successful buffer dump, must reset buffer pointers */ + entropy->next_output_byte = dest->next_output_byte; + entropy->free_in_buffer = dest->free_in_buffer; +} + + +/* Outputting bits to the file */ + +/* Only the right 24 bits of put_buffer are used; the valid bits are + * left-justified in this part. At most 16 bits can be passed to emit_bits + * in one call, and we never retain more than 7 bits in put_buffer + * between calls, so 24 bits are sufficient. + */ + +INLINE +LOCAL(void) +emit_bits (phuff_entropy_ptr entropy, unsigned int code, int size) +/* Emit some bits, unless we are in gather mode */ +{ + /* This routine is heavily used, so it's worth coding tightly. */ + register IJG_INT32 put_buffer = (IJG_INT32) code; + register int put_bits = entropy->put_bits; + + /* if size is 0, caller used an invalid Huffman table entry */ + if (size == 0) + ERREXIT(entropy->cinfo, JERR_HUFF_MISSING_CODE); + + if (entropy->gather_statistics) + return; /* do nothing if we're only getting stats */ + + put_buffer &= (((IJG_INT32) 1)<put_buffer; /* and merge with old buffer contents */ + + while (put_bits >= 8) { + int c = (int) ((put_buffer >> 16) & 0xFF); + + emit_byte(entropy, c); + if (c == 0xFF) { /* need to stuff a zero byte? */ + emit_byte(entropy, 0); + } + put_buffer <<= 8; + put_bits -= 8; + } + + entropy->put_buffer = put_buffer; /* update variables */ + entropy->put_bits = put_bits; +} + + +LOCAL(void) +flush_bits (phuff_entropy_ptr entropy) +{ + emit_bits(entropy, 0x7F, 7); /* fill any partial byte with ones */ + entropy->put_buffer = 0; /* and reset bit-buffer to empty */ + entropy->put_bits = 0; +} + + +/* + * Emit (or just count) a Huffman symbol. + */ + +INLINE +LOCAL(void) +emit_symbol (phuff_entropy_ptr entropy, int tbl_no, int symbol) +{ + if (entropy->gather_statistics) + entropy->count_ptrs[tbl_no][symbol]++; + else { + c_derived_tbl * tbl = entropy->derived_tbls[tbl_no]; + emit_bits(entropy, tbl->ehufco[symbol], tbl->ehufsi[symbol]); + } +} + + +/* + * Emit bits from a correction bit buffer. + */ + +LOCAL(void) +emit_buffered_bits (phuff_entropy_ptr entropy, char * bufstart, + unsigned int nbits) +{ + if (entropy->gather_statistics) + return; /* no real work */ + + while (nbits > 0) { + emit_bits(entropy, (unsigned int) (*bufstart), 1); + bufstart++; + nbits--; + } +} + + +/* + * Emit any pending EOBRUN symbol. + */ + +LOCAL(void) +emit_eobrun (phuff_entropy_ptr entropy) +{ + register int temp, nbits; + + if (entropy->EOBRUN > 0) { /* if there is any pending EOBRUN */ + temp = (int)entropy->EOBRUN; + nbits = 0; + while ((temp >>= 1)) + nbits++; + /* safety check: shouldn't happen given limited correction-bit buffer */ + if (nbits > 14) + ERREXIT(entropy->cinfo, JERR_HUFF_MISSING_CODE); + + emit_symbol(entropy, entropy->ac_tbl_no, nbits << 4); + if (nbits) + emit_bits(entropy, entropy->EOBRUN, nbits); + + entropy->EOBRUN = 0; + + /* Emit any buffered correction bits */ + emit_buffered_bits(entropy, entropy->bit_buffer, entropy->BE); + entropy->BE = 0; + } +} + + +/* + * Emit a restart marker & resynchronize predictions. + */ + +LOCAL(void) +emit_restart (phuff_entropy_ptr entropy, int restart_num) +{ + int ci; + + emit_eobrun(entropy); + + if (! entropy->gather_statistics) { + flush_bits(entropy); + emit_byte(entropy, 0xFF); + emit_byte(entropy, JPEG_RST0 + restart_num); + } + + if (entropy->cinfo->Ss == 0) { + /* Re-initialize DC predictions to 0 */ + for (ci = 0; ci < entropy->cinfo->comps_in_scan; ci++) + entropy->last_dc_val[ci] = 0; + } else { + /* Re-initialize all AC-related fields to 0 */ + entropy->EOBRUN = 0; + entropy->BE = 0; + } +} + + +/* + * MCU encoding for DC initial scan (either spectral selection, + * or first pass of successive approximation). + */ + +METHODDEF(boolean) +encode_mcu_DC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data) +{ + j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; + phuff_entropy_ptr entropy = (phuff_entropy_ptr) lossyc->entropy_private; + register int temp, temp2; + register int nbits; + int blkn, ci; + int Al = cinfo->Al; + JBLOCKROW block; + jpeg_component_info * compptr; + ISHIFT_TEMPS + + entropy->next_output_byte = cinfo->dest->next_output_byte; + entropy->free_in_buffer = cinfo->dest->free_in_buffer; + + /* Emit restart marker if needed */ + if (cinfo->restart_interval) + if (entropy->restarts_to_go == 0) + emit_restart(entropy, entropy->next_restart_num); + + /* Encode the MCU data blocks */ + for (blkn = 0; blkn < cinfo->data_units_in_MCU; blkn++) { + block = MCU_data[blkn]; + ci = cinfo->MCU_membership[blkn]; + compptr = cinfo->cur_comp_info[ci]; + + /* Compute the DC value after the required point transform by Al. + * This is simply an arithmetic right shift. + */ + temp2 = IRIGHT_SHIFT((int) ((*block)[0]), Al); + + /* DC differences are figured on the point-transformed values. */ + temp = temp2 - entropy->last_dc_val[ci]; + entropy->last_dc_val[ci] = temp2; + + /* Encode the DC coefficient difference per section G.1.2.1 */ + temp2 = temp; + if (temp < 0) { + temp = -temp; /* temp is abs value of input */ + /* For a negative input, want temp2 = bitwise complement of abs(input) */ + /* This code assumes we are on a two's complement machine */ + temp2--; + } + + /* Find the number of bits needed for the magnitude of the coefficient */ + nbits = 0; + while (temp) { + nbits++; + temp >>= 1; + } + /* Check for out-of-range coefficient values. + * Since we're encoding a difference, the range limit is twice as much. + */ + if (nbits > MAX_COEF_BITS+1) + ERREXIT(cinfo, JERR_BAD_DCT_COEF); + + /* Count/emit the Huffman-coded symbol for the number of bits */ + emit_symbol(entropy, compptr->dc_tbl_no, nbits); + + /* Emit that number of bits of the value, if positive, */ + /* or the complement of its magnitude, if negative. */ + if (nbits) /* emit_bits rejects calls with size 0 */ + emit_bits(entropy, (unsigned int) temp2, nbits); + } + + cinfo->dest->next_output_byte = entropy->next_output_byte; + cinfo->dest->free_in_buffer = entropy->free_in_buffer; + + /* Update restart-interval state too */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) { + entropy->restarts_to_go = cinfo->restart_interval; + entropy->next_restart_num++; + entropy->next_restart_num &= 7; + } + entropy->restarts_to_go--; + } + + return TRUE; +} + + +/* + * MCU encoding for AC initial scan (either spectral selection, + * or first pass of successive approximation). + */ + +METHODDEF(boolean) +encode_mcu_AC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data) +{ + j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; + phuff_entropy_ptr entropy = (phuff_entropy_ptr) lossyc->entropy_private; + register int temp, temp2; + register int nbits; + register int r, k; + int Se = cinfo->Se; + int Al = cinfo->Al; + JBLOCKROW block; + + entropy->next_output_byte = cinfo->dest->next_output_byte; + entropy->free_in_buffer = cinfo->dest->free_in_buffer; + + /* Emit restart marker if needed */ + if (cinfo->restart_interval) + if (entropy->restarts_to_go == 0) + emit_restart(entropy, entropy->next_restart_num); + + /* Encode the MCU data block */ + block = MCU_data[0]; + + /* Encode the AC coefficients per section G.1.2.2, fig. G.3 */ + + r = 0; /* r = run length of zeros */ + + for (k = cinfo->Ss; k <= Se; k++) { + if ((temp = (*block)[jpeg_natural_order[k]]) == 0) { + r++; + continue; + } + /* We must apply the point transform by Al. For AC coefficients this + * is an integer division with rounding towards 0. To do this portably + * in C, we shift after obtaining the absolute value; so the code is + * interwoven with finding the abs value (temp) and output bits (temp2). + */ + if (temp < 0) { + temp = -temp; /* temp is abs value of input */ + temp >>= Al; /* apply the point transform */ + /* For a negative coef, want temp2 = bitwise complement of abs(coef) */ + temp2 = ~temp; + } else { + temp >>= Al; /* apply the point transform */ + temp2 = temp; + } + /* Watch out for case that nonzero coef is zero after point transform */ + if (temp == 0) { + r++; + continue; + } + + /* Emit any pending EOBRUN */ + if (entropy->EOBRUN > 0) + emit_eobrun(entropy); + /* if run length > 15, must emit special run-length-16 codes (0xF0) */ + while (r > 15) { + emit_symbol(entropy, entropy->ac_tbl_no, 0xF0); + r -= 16; + } + + /* Find the number of bits needed for the magnitude of the coefficient */ + nbits = 1; /* there must be at least one 1 bit */ + while ((temp >>= 1)) + nbits++; + /* Check for out-of-range coefficient values */ + if (nbits > MAX_COEF_BITS) + ERREXIT(cinfo, JERR_BAD_DCT_COEF); + + /* Count/emit Huffman symbol for run length / number of bits */ + emit_symbol(entropy, entropy->ac_tbl_no, (r << 4) + nbits); + + /* Emit that number of bits of the value, if positive, */ + /* or the complement of its magnitude, if negative. */ + emit_bits(entropy, (unsigned int) temp2, nbits); + + r = 0; /* reset zero run length */ + } + + if (r > 0) { /* If there are trailing zeroes, */ + entropy->EOBRUN++; /* count an EOB */ + if (entropy->EOBRUN == 0x7FFF) + emit_eobrun(entropy); /* force it out to avoid overflow */ + } + + cinfo->dest->next_output_byte = entropy->next_output_byte; + cinfo->dest->free_in_buffer = entropy->free_in_buffer; + + /* Update restart-interval state too */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) { + entropy->restarts_to_go = cinfo->restart_interval; + entropy->next_restart_num++; + entropy->next_restart_num &= 7; + } + entropy->restarts_to_go--; + } + + return TRUE; +} + + +/* + * MCU encoding for DC successive approximation refinement scan. + * Note: we assume such scans can be multi-component, although the spec + * is not very clear on the point. + */ + +METHODDEF(boolean) +encode_mcu_DC_refine (j_compress_ptr cinfo, JBLOCKROW *MCU_data) +{ + j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; + phuff_entropy_ptr entropy = (phuff_entropy_ptr) lossyc->entropy_private; + register int temp; + int blkn; + int Al = cinfo->Al; + JBLOCKROW block; + + entropy->next_output_byte = cinfo->dest->next_output_byte; + entropy->free_in_buffer = cinfo->dest->free_in_buffer; + + /* Emit restart marker if needed */ + if (cinfo->restart_interval) + if (entropy->restarts_to_go == 0) + emit_restart(entropy, entropy->next_restart_num); + + /* Encode the MCU data blocks */ + for (blkn = 0; blkn < cinfo->data_units_in_MCU; blkn++) { + block = MCU_data[blkn]; + + /* We simply emit the Al'th bit of the DC coefficient value. */ + temp = (*block)[0]; + emit_bits(entropy, (unsigned int) (temp >> Al), 1); + } + + cinfo->dest->next_output_byte = entropy->next_output_byte; + cinfo->dest->free_in_buffer = entropy->free_in_buffer; + + /* Update restart-interval state too */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) { + entropy->restarts_to_go = cinfo->restart_interval; + entropy->next_restart_num++; + entropy->next_restart_num &= 7; + } + entropy->restarts_to_go--; + } + + return TRUE; +} + + +/* + * MCU encoding for AC successive approximation refinement scan. + */ + +METHODDEF(boolean) +encode_mcu_AC_refine (j_compress_ptr cinfo, JBLOCKROW *MCU_data) +{ + j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; + phuff_entropy_ptr entropy = (phuff_entropy_ptr) lossyc->entropy_private; + register int temp; + register int r, k; + int EOB; + char *BR_buffer; + unsigned int BR; + int Se = cinfo->Se; + int Al = cinfo->Al; + JBLOCKROW block; + int absvalues[DCTSIZE2]; + + entropy->next_output_byte = cinfo->dest->next_output_byte; + entropy->free_in_buffer = cinfo->dest->free_in_buffer; + + /* Emit restart marker if needed */ + if (cinfo->restart_interval) + if (entropy->restarts_to_go == 0) + emit_restart(entropy, entropy->next_restart_num); + + /* Encode the MCU data block */ + block = MCU_data[0]; + + /* It is convenient to make a pre-pass to determine the transformed + * coefficients' absolute values and the EOB position. + */ + EOB = 0; + for (k = cinfo->Ss; k <= Se; k++) { + temp = (*block)[jpeg_natural_order[k]]; + /* We must apply the point transform by Al. For AC coefficients this + * is an integer division with rounding towards 0. To do this portably + * in C, we shift after obtaining the absolute value. + */ + if (temp < 0) + temp = -temp; /* temp is abs value of input */ + temp >>= Al; /* apply the point transform */ + absvalues[k] = temp; /* save abs value for main pass */ + if (temp == 1) + EOB = k; /* EOB = index of last newly-nonzero coef */ + } + + /* Encode the AC coefficients per section G.1.2.3, fig. G.7 */ + + r = 0; /* r = run length of zeros */ + BR = 0; /* BR = count of buffered bits added now */ + BR_buffer = entropy->bit_buffer + entropy->BE; /* Append bits to buffer */ + + for (k = cinfo->Ss; k <= Se; k++) { + if ((temp = absvalues[k]) == 0) { + r++; + continue; + } + + /* Emit any required ZRLs, but not if they can be folded into EOB */ + while (r > 15 && k <= EOB) { + /* emit any pending EOBRUN and the BE correction bits */ + emit_eobrun(entropy); + /* Emit ZRL */ + emit_symbol(entropy, entropy->ac_tbl_no, 0xF0); + r -= 16; + /* Emit buffered correction bits that must be associated with ZRL */ + emit_buffered_bits(entropy, BR_buffer, BR); + BR_buffer = entropy->bit_buffer; /* BE bits are gone now */ + BR = 0; + } + + /* If the coef was previously nonzero, it only needs a correction bit. + * NOTE: a straight translation of the spec's figure G.7 would suggest + * that we also need to test r > 15. But if r > 15, we can only get here + * if k > EOB, which implies that this coefficient is not 1. + */ + if (temp > 1) { + /* The correction bit is the next bit of the absolute value. */ + BR_buffer[BR++] = (char) (temp & 1); + continue; + } + + /* Emit any pending EOBRUN and the BE correction bits */ + emit_eobrun(entropy); + + /* Count/emit Huffman symbol for run length / number of bits */ + emit_symbol(entropy, entropy->ac_tbl_no, (r << 4) + 1); + + /* Emit output bit for newly-nonzero coef */ + temp = ((*block)[jpeg_natural_order[k]] < 0) ? 0 : 1; + emit_bits(entropy, (unsigned int) temp, 1); + + /* Emit buffered correction bits that must be associated with this code */ + emit_buffered_bits(entropy, BR_buffer, BR); + BR_buffer = entropy->bit_buffer; /* BE bits are gone now */ + BR = 0; + r = 0; /* reset zero run length */ + } + + if (r > 0 || BR > 0) { /* If there are trailing zeroes, */ + entropy->EOBRUN++; /* count an EOB */ + entropy->BE += BR; /* concat my correction bits to older ones */ + /* We force out the EOB if we risk either: + * 1. overflow of the EOB counter; + * 2. overflow of the correction bit buffer during the next MCU. + */ + if (entropy->EOBRUN == 0x7FFF || entropy->BE > (MAX_CORR_BITS-DCTSIZE2+1)) + emit_eobrun(entropy); + } + + cinfo->dest->next_output_byte = entropy->next_output_byte; + cinfo->dest->free_in_buffer = entropy->free_in_buffer; + + /* Update restart-interval state too */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) { + entropy->restarts_to_go = cinfo->restart_interval; + entropy->next_restart_num++; + entropy->next_restart_num &= 7; + } + entropy->restarts_to_go--; + } + + return TRUE; +} + + +/* + * Finish up at the end of a Huffman-compressed progressive scan. + */ + +METHODDEF(void) +finish_pass_phuff (j_compress_ptr cinfo) +{ + j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; + phuff_entropy_ptr entropy = (phuff_entropy_ptr) lossyc->entropy_private; + + entropy->next_output_byte = cinfo->dest->next_output_byte; + entropy->free_in_buffer = cinfo->dest->free_in_buffer; + + /* Flush out any buffered data */ + emit_eobrun(entropy); + flush_bits(entropy); + + cinfo->dest->next_output_byte = entropy->next_output_byte; + cinfo->dest->free_in_buffer = entropy->free_in_buffer; +} + + +/* + * Finish up a statistics-gathering pass and create the new Huffman tables. + */ + +METHODDEF(void) +finish_pass_gather_phuff (j_compress_ptr cinfo) +{ + j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; + phuff_entropy_ptr entropy = (phuff_entropy_ptr) lossyc->entropy_private; + boolean is_DC_band; + int ci, tbl; + jpeg_component_info * compptr; + JHUFF_TBL **htblptr; + boolean did[NUM_HUFF_TBLS]; + + /* Flush out buffered data (all we care about is counting the EOB symbol) */ + emit_eobrun(entropy); + + is_DC_band = (cinfo->Ss == 0); + + /* It's important not to apply jpeg_gen_optimal_table more than once + * per table, because it clobbers the input frequency counts! + */ + MEMZERO(did, SIZEOF(did)); + + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + if (is_DC_band) { + if (cinfo->Ah != 0) /* DC refinement needs no table */ + continue; + tbl = compptr->dc_tbl_no; + } else { + tbl = compptr->ac_tbl_no; + } + if (! did[tbl]) { + if (is_DC_band) + htblptr = & cinfo->dc_huff_tbl_ptrs[tbl]; + else + htblptr = & cinfo->ac_huff_tbl_ptrs[tbl]; + if (*htblptr == NULL) + *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo); + jpeg_gen_optimal_table(cinfo, *htblptr, entropy->count_ptrs[tbl]); + did[tbl] = TRUE; + } + } +} + + +METHODDEF(boolean) +need_optimization_pass (j_compress_ptr cinfo) +{ + return (cinfo->Ss != 0 || cinfo->Ah == 0); +} + + +/* + * Module initialization routine for progressive Huffman entropy encoding. + */ + +GLOBAL(void) +jinit_phuff_encoder (j_compress_ptr cinfo) +{ + j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; + phuff_entropy_ptr entropy; + int i; + + entropy = (phuff_entropy_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(phuff_entropy_encoder)); + lossyc->entropy_private = (struct jpeg_entropy_encoder *) entropy; + lossyc->pub.entropy_start_pass = start_pass_phuff; + lossyc->pub.need_optimization_pass = need_optimization_pass; + + /* Mark tables unallocated */ + for (i = 0; i < NUM_HUFF_TBLS; i++) { + entropy->derived_tbls[i] = NULL; + entropy->count_ptrs[i] = NULL; + } + entropy->bit_buffer = NULL; /* needed only in AC refinement scan */ +} + +#endif /* C_PROGRESSIVE_SUPPORTED */ diff --git a/dcmjpeg/libijg16/jcpred.c b/dcmjpeg/libijg16/jcpred.c new file mode 100644 index 00000000..192e3e8a --- /dev/null +++ b/dcmjpeg/libijg16/jcpred.c @@ -0,0 +1,314 @@ +/* + * jcpred.c + * + * Copyright (C) 1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains sample differencing for lossless JPEG. + * + * In order to avoid paying the performance penalty of having to check the + * predictor being used and the row being processed for each call of the + * undifferencer, and to promote optimization, we have separate differencing + * functions for each case. + * + * We are able to avoid duplicating source code by implementing the predictors + * and differencers as macros. Each of the differencing functions are + * simply wrappers around a DIFFERENCE macro with the appropriate PREDICTOR + * macro passed as an argument. + */ + +#define JPEG_INTERNALS +#include "jinclude16.h" +#include "jpeglib16.h" +#include "jlossls16.h" /* Private declarations for lossless codec */ + + +#ifdef C_LOSSLESS_SUPPORTED + +/* Private predictor object */ + +typedef struct { + /* MCU-rows left in the restart interval for each component */ + unsigned int restart_rows_to_go[MAX_COMPONENTS]; +} c_predictor; + +typedef c_predictor * c_pred_ptr; + +/* Forward declarations */ +LOCAL(void) reset_predictor + JPP((j_compress_ptr cinfo, int ci)); +METHODDEF(void) start_pass + JPP((j_compress_ptr cinfo)); + + +/* Predictor for the first column of the first row: 2^(P-Pt-1) */ +#define INITIAL_PREDICTORx (1 << (cinfo->data_precision - cinfo->Al - 1)) + +/* Predictor for the first column of the remaining rows: Rb */ +#define INITIAL_PREDICTOR2 GETJSAMPLE(prev_row[0]) + + +/* + * 1-Dimensional differencer routine. + * + * This macro implements the 1-D horizontal predictor (1). INITIAL_PREDICTOR + * is used as the special case predictor for the first column, which must be + * either INITIAL_PREDICTOR2 or INITIAL_PREDICTORx. The remaining samples + * use PREDICTOR1. + */ + +#define DIFFERENCE_1D(INITIAL_PREDICTOR) \ + j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec; \ + c_pred_ptr pred = (c_pred_ptr) losslsc->pred_private; \ + boolean restart = FALSE; \ + unsigned int xindex; \ + int samp, Ra; \ + \ + samp = GETJSAMPLE(input_buf[0]); \ + diff_buf[0] = samp - INITIAL_PREDICTOR; \ + \ + for (xindex = 1; xindex < width; xindex++) { \ + Ra = samp; \ + samp = GETJSAMPLE(input_buf[xindex]); \ + diff_buf[xindex] = samp - PREDICTOR1; \ + } \ + \ + /* Account for restart interval (no-op if not using restarts) */ \ + if (cinfo->restart_interval) { \ + if (--(pred->restart_rows_to_go[ci]) == 0) { \ + reset_predictor(cinfo, ci); \ + restart = TRUE; \ + } \ + } + + +/* + * 2-Dimensional differencer routine. + * + * This macro implements the 2-D horizontal predictors (#2-7). PREDICTOR2 is + * used as the special case predictor for the first column. The remaining + * samples use PREDICTOR, which is a function of Ra, Rb, Rc. + * + * Because prev_row and output_buf may point to the same storage area (in an + * interleaved image with Vi=1, for example), we must take care to buffer Rb/Rc + * before writing the current reconstructed sample value into output_buf. + */ + +#define DIFFERENCE_2D(PREDICTOR) \ + j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec; \ + c_pred_ptr pred = (c_pred_ptr) losslsc->pred_private; \ + unsigned int xindex; \ + int samp, Ra, Rb, Rc; \ + \ + Rb = GETJSAMPLE(prev_row[0]); \ + samp = GETJSAMPLE(input_buf[0]); \ + diff_buf[0] = samp - PREDICTOR2; \ + \ + for (xindex = 1; xindex < width; xindex++) { \ + Rc = Rb; \ + Rb = GETJSAMPLE(prev_row[xindex]); \ + Ra = samp; \ + samp = GETJSAMPLE(input_buf[xindex]); \ + diff_buf[xindex] = samp - PREDICTOR; \ + } \ + \ + /* Account for restart interval (no-op if not using restarts) */ \ + if (cinfo->restart_interval) { \ + if (--pred->restart_rows_to_go[ci] == 0) \ + reset_predictor(cinfo, ci); \ + } + +#define JPEG_UNUSED(x) ((void)x) + +/* + * Differencers for the all rows but the first in a scan or restart interval. + * The first sample in the row is differenced using the vertical + * predictor (2). The rest of the samples are differenced using the + * predictor specified in the scan header. + */ + +METHODDEF(void) +jpeg_difference1(j_compress_ptr cinfo, int ci, + JSAMPROW input_buf, JSAMPROW prev_row, + JDIFFROW diff_buf, JDIMENSION width) +{ + DIFFERENCE_1D(INITIAL_PREDICTOR2); + JPEG_UNUSED(restart); +} + +METHODDEF(void) +jpeg_difference2(j_compress_ptr cinfo, int ci, + JSAMPROW input_buf, JSAMPROW prev_row, + JDIFFROW diff_buf, JDIMENSION width) +{ + DIFFERENCE_2D(PREDICTOR2); + JPEG_UNUSED(Rc); + JPEG_UNUSED(Ra); +} + +METHODDEF(void) +jpeg_difference3(j_compress_ptr cinfo, int ci, + JSAMPROW input_buf, JSAMPROW prev_row, + JDIFFROW diff_buf, JDIMENSION width) +{ + DIFFERENCE_2D(PREDICTOR3); + JPEG_UNUSED(Rc); + JPEG_UNUSED(Ra); +} + +METHODDEF(void) +jpeg_difference4(j_compress_ptr cinfo, int ci, + JSAMPROW input_buf, JSAMPROW prev_row, + JDIFFROW diff_buf, JDIMENSION width) +{ + DIFFERENCE_2D(PREDICTOR4); + JPEG_UNUSED(Rc); + JPEG_UNUSED(Ra); +} + +METHODDEF(void) +jpeg_difference5(j_compress_ptr cinfo, int ci, + JSAMPROW input_buf, JSAMPROW prev_row, + JDIFFROW diff_buf, JDIMENSION width) +{ + SHIFT_TEMPS + DIFFERENCE_2D(PREDICTOR5); + JPEG_UNUSED(Rc); + JPEG_UNUSED(Ra); +} + +METHODDEF(void) +jpeg_difference6(j_compress_ptr cinfo, int ci, + JSAMPROW input_buf, JSAMPROW prev_row, + JDIFFROW diff_buf, JDIMENSION width) +{ + SHIFT_TEMPS + DIFFERENCE_2D(PREDICTOR6); + JPEG_UNUSED(Rc); + JPEG_UNUSED(Ra); +} + +METHODDEF(void) +jpeg_difference7(j_compress_ptr cinfo, int ci, + JSAMPROW input_buf, JSAMPROW prev_row, + JDIFFROW diff_buf, JDIMENSION width) +{ + SHIFT_TEMPS + DIFFERENCE_2D(PREDICTOR7); + JPEG_UNUSED(Rc); + JPEG_UNUSED(Ra); +} + + +/* + * Differencer for the first row in a scan or restart interval. The first + * sample in the row is differenced using the special predictor constant + * x=2^(P-Pt-1). The rest of the samples are differenced using the + * 1-D horizontal predictor (1). + */ + +METHODDEF(void) +jpeg_difference_first_row(j_compress_ptr cinfo, int ci, + JSAMPROW input_buf, JSAMPROW prev_row, + JDIFFROW diff_buf, JDIMENSION width) +{ + DIFFERENCE_1D(INITIAL_PREDICTORx); + + /* + * Now that we have differenced the first row, we want to use the + * differencer which corresponds to the predictor specified in the + * scan header. + * + * Note that we don't to do this if we have just reset the predictor + * for a new restart interval. + */ + if (!restart) { + switch (cinfo->Ss) { + case 1: + losslsc->predict_difference[ci] = jpeg_difference1; + break; + case 2: + losslsc->predict_difference[ci] = jpeg_difference2; + break; + case 3: + losslsc->predict_difference[ci] = jpeg_difference3; + break; + case 4: + losslsc->predict_difference[ci] = jpeg_difference4; + break; + case 5: + losslsc->predict_difference[ci] = jpeg_difference5; + break; + case 6: + losslsc->predict_difference[ci] = jpeg_difference6; + break; + case 7: + losslsc->predict_difference[ci] = jpeg_difference7; + break; + } + } +} + +/* + * Reset predictor at the start of a pass or restart interval. + */ + +LOCAL(void) +reset_predictor (j_compress_ptr cinfo, int ci) +{ + j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec; + c_pred_ptr pred = (c_pred_ptr) losslsc->pred_private; + + /* Initialize restart counter */ + pred->restart_rows_to_go[ci] = + cinfo->restart_interval / cinfo->MCUs_per_row; + + /* Set difference function to first row function */ + losslsc->predict_difference[ci] = jpeg_difference_first_row; +} + + +/* + * Initialize for an input processing pass. + */ + +METHODDEF(void) +start_pass (j_compress_ptr cinfo) +{ + /* j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec; */ + /* c_pred_ptr pred = (c_pred_ptr) losslsc->pred_private; */ + int ci; + + /* Check that the restart interval is an integer multiple of the number + * of MCU in an MCU-row. + */ + if (cinfo->restart_interval % cinfo->MCUs_per_row != 0) + ERREXIT2(cinfo, JERR_BAD_RESTART, + (int)cinfo->restart_interval, (int)cinfo->MCUs_per_row); + + /* Set predictors for start of pass */ + for (ci = 0; ci < cinfo->num_components; ci++) + reset_predictor(cinfo, ci); +} + + +/* + * Module initialization routine for the differencer. + */ + +GLOBAL(void) +jinit_differencer (j_compress_ptr cinfo) +{ + j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec; + c_pred_ptr pred; + + pred = (c_pred_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(c_predictor)); + losslsc->pred_private = (void *) pred; + losslsc->predict_start_pass = start_pass; +} + +#endif /* C_LOSSLESS_SUPPORTED */ + diff --git a/dcmjpeg/libijg16/jcprepct.c b/dcmjpeg/libijg16/jcprepct.c new file mode 100644 index 00000000..6ff73f67 --- /dev/null +++ b/dcmjpeg/libijg16/jcprepct.c @@ -0,0 +1,354 @@ +/* + * jcprepct.c + * + * Copyright (C) 1994-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains the compression preprocessing controller. + * This controller manages the color conversion, downsampling, + * and edge expansion steps. + * + * Most of the complexity here is associated with buffering input rows + * as required by the downsampler. See the comments at the head of + * jcsample.c for the downsampler's needs. + */ + +#define JPEG_INTERNALS +#include "jinclude16.h" +#include "jpeglib16.h" + + +/* At present, jcsample.c can request context rows only for smoothing. + * In the future, we might also need context rows for CCIR601 sampling + * or other more-complex downsampling procedures. The code to support + * context rows should be compiled only if needed. + */ +#ifdef INPUT_SMOOTHING_SUPPORTED +#define CONTEXT_ROWS_SUPPORTED +#endif + + +/* + * For the simple (no-context-row) case, we just need to buffer one + * row group's worth of pixels for the downsampling step. At the bottom of + * the image, we pad to a full row group by replicating the last pixel row. + * The downsampler's last output row is then replicated if needed to pad + * out to a full iMCU row. + * + * When providing context rows, we must buffer three row groups' worth of + * pixels. Three row groups are physically allocated, but the row pointer + * arrays are made five row groups high, with the extra pointers above and + * below "wrapping around" to point to the last and first real row groups. + * This allows the downsampler to access the proper context rows. + * At the top and bottom of the image, we create dummy context rows by + * copying the first or last real pixel row. This copying could be avoided + * by pointer hacking as is done in jdmainct.c, but it doesn't seem worth the + * trouble on the compression side. + */ + + +/* Private buffer controller object */ + +typedef struct { + struct jpeg_c_prep_controller pub; /* public fields */ + + /* Downsampling input buffer. This buffer holds color-converted data + * until we have enough to do a downsample step. + */ + JSAMPARRAY color_buf[MAX_COMPONENTS]; + + JDIMENSION rows_to_go; /* counts rows remaining in source image */ + int next_buf_row; /* index of next row to store in color_buf */ + +#ifdef CONTEXT_ROWS_SUPPORTED /* only needed for context case */ + int this_row_group; /* starting row index of group to process */ + int next_buf_stop; /* downsample when we reach this index */ +#endif +} my_prep_controller; + +typedef my_prep_controller * my_prep_ptr; + + +/* + * Initialize for a processing pass. + */ + +METHODDEF(void) +start_pass_prep (j_compress_ptr cinfo, J_BUF_MODE pass_mode) +{ + my_prep_ptr prep = (my_prep_ptr) cinfo->prep; + + if (pass_mode != JBUF_PASS_THRU) + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + + /* Initialize total-height counter for detecting bottom of image */ + prep->rows_to_go = cinfo->image_height; + /* Mark the conversion buffer empty */ + prep->next_buf_row = 0; +#ifdef CONTEXT_ROWS_SUPPORTED + /* Preset additional state variables for context mode. + * These aren't used in non-context mode, so we needn't test which mode. + */ + prep->this_row_group = 0; + /* Set next_buf_stop to stop after two row groups have been read in. */ + prep->next_buf_stop = 2 * cinfo->max_v_samp_factor; +#endif +} + + +/* + * Expand an image vertically from height input_rows to height output_rows, + * by duplicating the bottom row. + */ + +LOCAL(void) +expand_bottom_edge (JSAMPARRAY image_data, JDIMENSION num_cols, + int input_rows, int output_rows) +{ + register int row; + + for (row = input_rows; row < output_rows; row++) { + jcopy_sample_rows(image_data, input_rows-1, image_data, row, + 1, num_cols); + } +} + + +/* + * Process some data in the simple no-context case. + * + * Preprocessor output data is counted in "row groups". A row group + * is defined to be v_samp_factor sample rows of each component. + * Downsampling will produce this much data from each max_v_samp_factor + * input rows. + */ + +METHODDEF(void) +pre_process_data (j_compress_ptr cinfo, + JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, + JDIMENSION in_rows_avail, + JSAMPIMAGE output_buf, JDIMENSION *out_row_group_ctr, + JDIMENSION out_row_groups_avail) +{ + my_prep_ptr prep = (my_prep_ptr) cinfo->prep; + int numrows, ci; + JDIMENSION inrows; + jpeg_component_info * compptr; + + while (*in_row_ctr < in_rows_avail && + *out_row_group_ctr < out_row_groups_avail) { + /* Do color conversion to fill the conversion buffer. */ + inrows = in_rows_avail - *in_row_ctr; + numrows = cinfo->max_v_samp_factor - prep->next_buf_row; + numrows = (int) MIN((JDIMENSION) numrows, inrows); + (*cinfo->cconvert->color_convert) (cinfo, input_buf + *in_row_ctr, + prep->color_buf, + (JDIMENSION) prep->next_buf_row, + numrows); + *in_row_ctr += (JDIMENSION)numrows; + prep->next_buf_row += numrows; + prep->rows_to_go -= (JDIMENSION)numrows; + /* If at bottom of image, pad to fill the conversion buffer. */ + if (prep->rows_to_go == 0 && + prep->next_buf_row < cinfo->max_v_samp_factor) { + for (ci = 0; ci < cinfo->num_components; ci++) { + expand_bottom_edge(prep->color_buf[ci], cinfo->image_width, + prep->next_buf_row, cinfo->max_v_samp_factor); + } + prep->next_buf_row = cinfo->max_v_samp_factor; + } + /* If we've filled the conversion buffer, empty it. */ + if (prep->next_buf_row == cinfo->max_v_samp_factor) { + (*cinfo->downsample->downsample) (cinfo, + prep->color_buf, (JDIMENSION) 0, + output_buf, *out_row_group_ctr); + prep->next_buf_row = 0; + (*out_row_group_ctr)++; + } + /* If at bottom of image, pad the output to a full iMCU height. + * Note we assume the caller is providing a one-iMCU-height output buffer! + */ + if (prep->rows_to_go == 0 && + *out_row_group_ctr < out_row_groups_avail) { + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + expand_bottom_edge(output_buf[ci], + compptr->width_in_data_units * (JDIMENSION)cinfo->data_unit, + (int)*out_row_group_ctr * compptr->v_samp_factor, + (int)out_row_groups_avail * compptr->v_samp_factor); + } + *out_row_group_ctr = out_row_groups_avail; + break; /* can exit outer loop without test */ + } + } +} + + +#ifdef CONTEXT_ROWS_SUPPORTED + +/* + * Process some data in the context case. + */ + +METHODDEF(void) +pre_process_context (j_compress_ptr cinfo, + JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, + JDIMENSION in_rows_avail, + JSAMPIMAGE output_buf, JDIMENSION *out_row_group_ctr, + JDIMENSION out_row_groups_avail) +{ + my_prep_ptr prep = (my_prep_ptr) cinfo->prep; + int numrows, ci; + int buf_height = cinfo->max_v_samp_factor * 3; + JDIMENSION inrows; + + while (*out_row_group_ctr < out_row_groups_avail) { + if (*in_row_ctr < in_rows_avail) { + /* Do color conversion to fill the conversion buffer. */ + inrows = in_rows_avail - *in_row_ctr; + numrows = prep->next_buf_stop - prep->next_buf_row; + numrows = (int) MIN((JDIMENSION) numrows, inrows); + (*cinfo->cconvert->color_convert) (cinfo, input_buf + *in_row_ctr, + prep->color_buf, + (JDIMENSION) prep->next_buf_row, + numrows); + /* Pad at top of image, if first time through */ + if (prep->rows_to_go == cinfo->image_height) { + for (ci = 0; ci < cinfo->num_components; ci++) { + int row; + for (row = 1; row <= cinfo->max_v_samp_factor; row++) { + jcopy_sample_rows(prep->color_buf[ci], 0, + prep->color_buf[ci], -row, + 1, cinfo->image_width); + } + } + } + *in_row_ctr += (JDIMENSION)numrows; + prep->next_buf_row += numrows; + prep->rows_to_go -= (JDIMENSION)numrows; + } else { + /* Return for more data, unless we are at the bottom of the image. */ + if (prep->rows_to_go != 0) + break; + /* When at bottom of image, pad to fill the conversion buffer. */ + if (prep->next_buf_row < prep->next_buf_stop) { + for (ci = 0; ci < cinfo->num_components; ci++) { + expand_bottom_edge(prep->color_buf[ci], cinfo->image_width, + prep->next_buf_row, prep->next_buf_stop); + } + prep->next_buf_row = prep->next_buf_stop; + } + } + /* If we've gotten enough data, downsample a row group. */ + if (prep->next_buf_row == prep->next_buf_stop) { + (*cinfo->downsample->downsample) (cinfo, + prep->color_buf, + (JDIMENSION) prep->this_row_group, + output_buf, *out_row_group_ctr); + (*out_row_group_ctr)++; + /* Advance pointers with wraparound as necessary. */ + prep->this_row_group += cinfo->max_v_samp_factor; + if (prep->this_row_group >= buf_height) + prep->this_row_group = 0; + if (prep->next_buf_row >= buf_height) + prep->next_buf_row = 0; + prep->next_buf_stop = prep->next_buf_row + cinfo->max_v_samp_factor; + } + } +} + + +/* + * Create the wrapped-around downsampling input buffer needed for context mode. + */ + +LOCAL(void) +create_context_buffer (j_compress_ptr cinfo) +{ + my_prep_ptr prep = (my_prep_ptr) cinfo->prep; + int rgroup_height = cinfo->max_v_samp_factor; + int ci, i; + jpeg_component_info * compptr; + JSAMPARRAY true_buffer, fake_buffer; + + /* Grab enough space for fake row pointers for all the components; + * we need five row groups' worth of pointers for each component. + */ + fake_buffer = (JSAMPARRAY) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (size_t)(cinfo->num_components * 5 * rgroup_height) * + SIZEOF(JSAMPROW)); + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + /* Allocate the actual buffer space (3 row groups) for this component. + * We make the buffer wide enough to allow the downsampler to edge-expand + * horizontally within the buffer, if it so chooses. + */ + true_buffer = (*cinfo->mem->alloc_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + (JDIMENSION) (((long) compptr->width_in_data_units * cinfo->data_unit * + cinfo->max_h_samp_factor) / compptr->h_samp_factor), + (JDIMENSION) (3 * rgroup_height)); + /* Copy true buffer row pointers into the middle of the fake row array */ + MEMCOPY(fake_buffer + rgroup_height, true_buffer, + 3 * (size_t)rgroup_height * SIZEOF(JSAMPROW)); + /* Fill in the above and below wraparound pointers */ + for (i = 0; i < rgroup_height; i++) { + fake_buffer[i] = true_buffer[2 * rgroup_height + i]; + fake_buffer[4 * rgroup_height + i] = true_buffer[i]; + } + prep->color_buf[ci] = fake_buffer + rgroup_height; + fake_buffer += 5 * rgroup_height; /* point to space for next component */ + } +} + +#endif /* CONTEXT_ROWS_SUPPORTED */ + + +/* + * Initialize preprocessing controller. + */ + +GLOBAL(void) +jinit_c_prep_controller (j_compress_ptr cinfo, boolean need_full_buffer) +{ + my_prep_ptr prep; + int ci; + jpeg_component_info * compptr; + + if (need_full_buffer) /* safety check */ + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + + prep = (my_prep_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_prep_controller)); + cinfo->prep = (struct jpeg_c_prep_controller *) prep; + prep->pub.start_pass = start_pass_prep; + + /* Allocate the color conversion buffer. + * We make the buffer wide enough to allow the downsampler to edge-expand + * horizontally within the buffer, if it so chooses. + */ + if (cinfo->downsample->need_context_rows) { + /* Set up to provide context rows */ +#ifdef CONTEXT_ROWS_SUPPORTED + prep->pub.pre_process_data = pre_process_context; + create_context_buffer(cinfo); +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } else { + /* No context, just make it tall enough for one row group */ + prep->pub.pre_process_data = pre_process_data; + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + prep->color_buf[ci] = (*cinfo->mem->alloc_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + (JDIMENSION) (((long) compptr->width_in_data_units * cinfo->data_unit * + cinfo->max_h_samp_factor) / compptr->h_samp_factor), + (JDIMENSION) cinfo->max_v_samp_factor); + } + } +} diff --git a/dcmjpeg/libijg16/jcsample.c b/dcmjpeg/libijg16/jcsample.c new file mode 100644 index 00000000..80766490 --- /dev/null +++ b/dcmjpeg/libijg16/jcsample.c @@ -0,0 +1,519 @@ +/* + * jcsample.c + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains downsampling routines. + * + * Downsampling input data is counted in "row groups". A row group + * is defined to be max_v_samp_factor pixel rows of each component, + * from which the downsampler produces v_samp_factor sample rows. + * A single row group is processed in each call to the downsampler module. + * + * The downsampler is responsible for edge-expansion of its output data + * to fill an integral number of DCT blocks horizontally. The source buffer + * may be modified if it is helpful for this purpose (the source buffer is + * allocated wide enough to correspond to the desired output width). + * The caller (the prep controller) is responsible for vertical padding. + * + * The downsampler may request "context rows" by setting need_context_rows + * during startup. In this case, the input arrays will contain at least + * one row group's worth of pixels above and below the passed-in data; + * the caller will create dummy rows at image top and bottom by replicating + * the first or last real pixel row. + * + * An excellent reference for image resampling is + * Digital Image Warping, George Wolberg, 1990. + * Pub. by IEEE Computer Society Press, Los Alamitos, CA. ISBN 0-8186-8944-7. + * + * The downsampling algorithm used here is a simple average of the source + * pixels covered by the output pixel. The hi-falutin sampling literature + * refers to this as a "box filter". In general the characteristics of a box + * filter are not very good, but for the specific cases we normally use (1:1 + * and 2:1 ratios) the box is equivalent to a "triangle filter" which is not + * nearly so bad. If you intend to use other sampling ratios, you'd be well + * advised to improve this code. + * + * A simple input-smoothing capability is provided. This is mainly intended + * for cleaning up color-dithered GIF input files (if you find it inadequate, + * we suggest using an external filtering program such as pnmconvol). When + * enabled, each input pixel P is replaced by a weighted sum of itself and its + * eight neighbors. P's weight is 1-8*SF and each neighbor's weight is SF, + * where SF = (smoothing_factor / 1024). + * Currently, smoothing is only supported for 2h2v sampling factors. + */ + +#define JPEG_INTERNALS +#include "jinclude16.h" +#include "jpeglib16.h" + + +/* Pointer to routine to downsample a single component */ +typedef JMETHOD(void, downsample1_ptr, + (j_compress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY input_data, JSAMPARRAY output_data)); + +/* Private subobject */ + +typedef struct { + struct jpeg_downsampler pub; /* public fields */ + + /* Downsampling method pointers, one per component */ + downsample1_ptr methods[MAX_COMPONENTS]; +} my_downsampler; + +typedef my_downsampler * my_downsample_ptr; + + +/* + * Initialize for a downsampling pass. + */ + +METHODDEF(void) +start_pass_downsample (j_compress_ptr cinfo) +{ + /* no work for now */ +} + + +/* + * Expand a component horizontally from width input_cols to width output_cols, + * by duplicating the rightmost samples. + */ + +LOCAL(void) +expand_right_edge (JSAMPARRAY image_data, int num_rows, + JDIMENSION input_cols, JDIMENSION output_cols) +{ + register JSAMPROW ptr; + register JSAMPLE pixval; + register int count; + int row; + int numcols = (int) (output_cols - input_cols); + + if (numcols > 0) { + for (row = 0; row < num_rows; row++) { + ptr = image_data[row] + input_cols; + pixval = ptr[-1]; /* don't need GETJSAMPLE() here */ + for (count = numcols; count > 0; count--) + *ptr++ = pixval; + } + } +} + + +/* + * Do downsampling for a whole row group (all components). + * + * In this version we simply downsample each component independently. + */ + +METHODDEF(void) +sep_downsample (j_compress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION in_row_index, + JSAMPIMAGE output_buf, JDIMENSION out_row_group_index) +{ + my_downsample_ptr downsample = (my_downsample_ptr) cinfo->downsample; + int ci; + jpeg_component_info * compptr; + JSAMPARRAY in_ptr, out_ptr; + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + in_ptr = input_buf[ci] + in_row_index; + out_ptr = output_buf[ci] + (out_row_group_index * (JDIMENSION)compptr->v_samp_factor); + (*downsample->methods[ci]) (cinfo, compptr, in_ptr, out_ptr); + } +} + + +/* + * Downsample pixel values of a single component. + * One row group is processed per call. + * This version handles arbitrary integral sampling ratios, without smoothing. + * Note that this version is not actually used for customary sampling ratios. + */ + +METHODDEF(void) +int_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY input_data, JSAMPARRAY output_data) +{ + int inrow, outrow, h_expand, v_expand, numpix, numpix2, h, v; + JDIMENSION outcol, outcol_h; /* outcol_h == outcol*h_expand */ + JDIMENSION output_cols = compptr->width_in_data_units * (JDIMENSION)cinfo->data_unit; + JSAMPROW inptr, outptr; + IJG_INT32 outvalue; + + h_expand = cinfo->max_h_samp_factor / compptr->h_samp_factor; + v_expand = cinfo->max_v_samp_factor / compptr->v_samp_factor; + numpix = h_expand * v_expand; + numpix2 = numpix/2; + + /* Expand input data enough to let all the output samples be generated + * by the standard loop. Special-casing padded output would be more + * efficient. + */ + expand_right_edge(input_data, cinfo->max_v_samp_factor, + cinfo->image_width, output_cols * (JDIMENSION)h_expand); + + inrow = 0; + for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) { + outptr = output_data[outrow]; + for (outcol = 0, outcol_h = 0; outcol < output_cols; + outcol++, outcol_h += (JDIMENSION)h_expand) { + outvalue = 0; + for (v = 0; v < v_expand; v++) { + inptr = input_data[inrow+v] + outcol_h; + for (h = 0; h < h_expand; h++) { + outvalue += (IJG_INT32) GETJSAMPLE(*inptr++); + } + } + *outptr++ = (JSAMPLE) ((outvalue + numpix2) / numpix); + } + inrow += v_expand; + } +} + + +/* + * Downsample pixel values of a single component. + * This version handles the special case of a full-size component, + * without smoothing. + */ + +METHODDEF(void) +fullsize_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY input_data, JSAMPARRAY output_data) +{ + /* Copy the data */ + jcopy_sample_rows(input_data, 0, output_data, 0, + cinfo->max_v_samp_factor, cinfo->image_width); + /* Edge-expand */ + expand_right_edge(output_data, cinfo->max_v_samp_factor, + cinfo->image_width, compptr->width_in_data_units * (JDIMENSION)cinfo->data_unit); +} + + +/* + * Downsample pixel values of a single component. + * This version handles the common case of 2:1 horizontal and 1:1 vertical, + * without smoothing. + * + * A note about the "bias" calculations: when rounding fractional values to + * integer, we do not want to always round 0.5 up to the next integer. + * If we did that, we'd introduce a noticeable bias towards larger values. + * Instead, this code is arranged so that 0.5 will be rounded up or down at + * alternate pixel locations (a simple ordered dither pattern). + */ + +METHODDEF(void) +h2v1_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY input_data, JSAMPARRAY output_data) +{ + int outrow; + JDIMENSION outcol; + JDIMENSION output_cols = compptr->width_in_data_units * (JDIMENSION)cinfo->data_unit; + register JSAMPROW inptr, outptr; + register int bias; + + /* Expand input data enough to let all the output samples be generated + * by the standard loop. Special-casing padded output would be more + * efficient. + */ + expand_right_edge(input_data, cinfo->max_v_samp_factor, + cinfo->image_width, output_cols * 2); + + for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) { + outptr = output_data[outrow]; + inptr = input_data[outrow]; + bias = 0; /* bias = 0,1,0,1,... for successive samples */ + for (outcol = 0; outcol < output_cols; outcol++) { + *outptr++ = (JSAMPLE) ((GETJSAMPLE(*inptr) + GETJSAMPLE(inptr[1]) + + bias) >> 1); + bias ^= 1; /* 0=>1, 1=>0 */ + inptr += 2; + } + } +} + + +/* + * Downsample pixel values of a single component. + * This version handles the standard case of 2:1 horizontal and 2:1 vertical, + * without smoothing. + */ + +METHODDEF(void) +h2v2_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY input_data, JSAMPARRAY output_data) +{ + int inrow, outrow; + JDIMENSION outcol; + JDIMENSION output_cols = compptr->width_in_data_units * (JDIMENSION)cinfo->data_unit; + register JSAMPROW inptr0, inptr1, outptr; + register int bias; + + /* Expand input data enough to let all the output samples be generated + * by the standard loop. Special-casing padded output would be more + * efficient. + */ + expand_right_edge(input_data, cinfo->max_v_samp_factor, + cinfo->image_width, output_cols * 2); + + inrow = 0; + for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) { + outptr = output_data[outrow]; + inptr0 = input_data[inrow]; + inptr1 = input_data[inrow+1]; + bias = 1; /* bias = 1,2,1,2,... for successive samples */ + for (outcol = 0; outcol < output_cols; outcol++) { + *outptr++ = (JSAMPLE) ((GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) + + GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]) + + bias) >> 2); + bias ^= 3; /* 1=>2, 2=>1 */ + inptr0 += 2; inptr1 += 2; + } + inrow += 2; + } +} + + +#ifdef INPUT_SMOOTHING_SUPPORTED + +/* + * Downsample pixel values of a single component. + * This version handles the standard case of 2:1 horizontal and 2:1 vertical, + * with smoothing. One row of context is required. + */ + +METHODDEF(void) +h2v2_smooth_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY input_data, JSAMPARRAY output_data) +{ + int inrow, outrow; + JDIMENSION colctr; + JDIMENSION output_cols = compptr->width_in_data_units * (JDIMENSION)cinfo->data_unit; + register JSAMPROW inptr0, inptr1, above_ptr, below_ptr, outptr; + IJG_INT32 membersum, neighsum, memberscale, neighscale; + + /* Expand input data enough to let all the output samples be generated + * by the standard loop. Special-casing padded output would be more + * efficient. + */ + expand_right_edge(input_data - 1, cinfo->max_v_samp_factor + 2, + cinfo->image_width, output_cols * 2); + + /* We don't bother to form the individual "smoothed" input pixel values; + * we can directly compute the output which is the average of the four + * smoothed values. Each of the four member pixels contributes a fraction + * (1-8*SF) to its own smoothed image and a fraction SF to each of the three + * other smoothed pixels, therefore a total fraction (1-5*SF)/4 to the final + * output. The four corner-adjacent neighbor pixels contribute a fraction + * SF to just one smoothed pixel, or SF/4 to the final output; while the + * eight edge-adjacent neighbors contribute SF to each of two smoothed + * pixels, or SF/2 overall. In order to use integer arithmetic, these + * factors are scaled by 2^16 = 65536. + * Also recall that SF = smoothing_factor / 1024. + */ + + memberscale = 16384 - cinfo->smoothing_factor * 80; /* scaled (1-5*SF)/4 */ + neighscale = cinfo->smoothing_factor * 16; /* scaled SF/4 */ + + inrow = 0; + for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) { + outptr = output_data[outrow]; + inptr0 = input_data[inrow]; + inptr1 = input_data[inrow+1]; + above_ptr = input_data[inrow-1]; + below_ptr = input_data[inrow+2]; + + /* Special case for first column: pretend column -1 is same as column 0 */ + membersum = GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) + + GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]); + neighsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[1]) + + GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) + + GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[2]) + + GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[2]); + neighsum += neighsum; + neighsum += GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[2]) + + GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[2]); + membersum = membersum * memberscale + neighsum * neighscale; + *outptr++ = (JSAMPLE) ((membersum + 32768) >> 16); + inptr0 += 2; inptr1 += 2; above_ptr += 2; below_ptr += 2; + + for (colctr = output_cols - 2; colctr > 0; colctr--) { + /* sum of pixels directly mapped to this output element */ + membersum = GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) + + GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]); + /* sum of edge-neighbor pixels */ + neighsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[1]) + + GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) + + GETJSAMPLE(inptr0[-1]) + GETJSAMPLE(inptr0[2]) + + GETJSAMPLE(inptr1[-1]) + GETJSAMPLE(inptr1[2]); + /* The edge-neighbors count twice as much as corner-neighbors */ + neighsum += neighsum; + /* Add in the corner-neighbors */ + neighsum += GETJSAMPLE(above_ptr[-1]) + GETJSAMPLE(above_ptr[2]) + + GETJSAMPLE(below_ptr[-1]) + GETJSAMPLE(below_ptr[2]); + /* form final output scaled up by 2^16 */ + membersum = membersum * memberscale + neighsum * neighscale; + /* round, descale and output it */ + *outptr++ = (JSAMPLE) ((membersum + 32768) >> 16); + inptr0 += 2; inptr1 += 2; above_ptr += 2; below_ptr += 2; + } + + /* Special case for last column */ + membersum = GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) + + GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]); + neighsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[1]) + + GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) + + GETJSAMPLE(inptr0[-1]) + GETJSAMPLE(inptr0[1]) + + GETJSAMPLE(inptr1[-1]) + GETJSAMPLE(inptr1[1]); + neighsum += neighsum; + neighsum += GETJSAMPLE(above_ptr[-1]) + GETJSAMPLE(above_ptr[1]) + + GETJSAMPLE(below_ptr[-1]) + GETJSAMPLE(below_ptr[1]); + membersum = membersum * memberscale + neighsum * neighscale; + *outptr = (JSAMPLE) ((membersum + 32768) >> 16); + + inrow += 2; + } +} + + +/* + * Downsample pixel values of a single component. + * This version handles the special case of a full-size component, + * with smoothing. One row of context is required. + */ + +METHODDEF(void) +fullsize_smooth_downsample (j_compress_ptr cinfo, jpeg_component_info *compptr, + JSAMPARRAY input_data, JSAMPARRAY output_data) +{ + int outrow; + JDIMENSION colctr; + JDIMENSION output_cols = compptr->width_in_data_units * (JDIMENSION)cinfo->data_unit; + register JSAMPROW inptr, above_ptr, below_ptr, outptr; + IJG_INT32 membersum, neighsum, memberscale, neighscale; + int colsum, lastcolsum, nextcolsum; + + /* Expand input data enough to let all the output samples be generated + * by the standard loop. Special-casing padded output would be more + * efficient. + */ + expand_right_edge(input_data - 1, cinfo->max_v_samp_factor + 2, + cinfo->image_width, output_cols); + + /* Each of the eight neighbor pixels contributes a fraction SF to the + * smoothed pixel, while the main pixel contributes (1-8*SF). In order + * to use integer arithmetic, these factors are multiplied by 2^16 = 65536. + * Also recall that SF = smoothing_factor / 1024. + */ + + memberscale = 65536L - cinfo->smoothing_factor * 512L; /* scaled 1-8*SF */ + neighscale = cinfo->smoothing_factor * 64; /* scaled SF */ + + for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) { + outptr = output_data[outrow]; + inptr = input_data[outrow]; + above_ptr = input_data[outrow-1]; + below_ptr = input_data[outrow+1]; + + /* Special case for first column */ + colsum = GETJSAMPLE(*above_ptr++) + GETJSAMPLE(*below_ptr++) + + GETJSAMPLE(*inptr); + membersum = GETJSAMPLE(*inptr++); + nextcolsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(*below_ptr) + + GETJSAMPLE(*inptr); + neighsum = colsum + (colsum - membersum) + nextcolsum; + membersum = membersum * memberscale + neighsum * neighscale; + *outptr++ = (JSAMPLE) ((membersum + 32768) >> 16); + lastcolsum = colsum; colsum = nextcolsum; + + for (colctr = output_cols - 2; colctr > 0; colctr--) { + membersum = GETJSAMPLE(*inptr++); + above_ptr++; below_ptr++; + nextcolsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(*below_ptr) + + GETJSAMPLE(*inptr); + neighsum = lastcolsum + (colsum - membersum) + nextcolsum; + membersum = membersum * memberscale + neighsum * neighscale; + *outptr++ = (JSAMPLE) ((membersum + 32768) >> 16); + lastcolsum = colsum; colsum = nextcolsum; + } + + /* Special case for last column */ + membersum = GETJSAMPLE(*inptr); + neighsum = lastcolsum + (colsum - membersum) + colsum; + membersum = membersum * memberscale + neighsum * neighscale; + *outptr = (JSAMPLE) ((membersum + 32768) >> 16); + + } +} + +#endif /* INPUT_SMOOTHING_SUPPORTED */ + + +/* + * Module initialization routine for downsampling. + * Note that we must select a routine for each component. + */ + +GLOBAL(void) +jinit_downsampler (j_compress_ptr cinfo) +{ + my_downsample_ptr downsample; + int ci; + jpeg_component_info * compptr; + boolean smoothok = TRUE; + + downsample = (my_downsample_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_downsampler)); + cinfo->downsample = (struct jpeg_downsampler *) downsample; + downsample->pub.start_pass = start_pass_downsample; + downsample->pub.downsample = sep_downsample; + downsample->pub.need_context_rows = FALSE; + + if (cinfo->CCIR601_sampling) + ERREXIT(cinfo, JERR_CCIR601_NOTIMPL); + + /* Verify we can handle the sampling factors, and set up method pointers */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + if (compptr->h_samp_factor == cinfo->max_h_samp_factor && + compptr->v_samp_factor == cinfo->max_v_samp_factor) { +#ifdef INPUT_SMOOTHING_SUPPORTED + if (cinfo->smoothing_factor) { + downsample->methods[ci] = fullsize_smooth_downsample; + downsample->pub.need_context_rows = TRUE; + } else +#endif + downsample->methods[ci] = fullsize_downsample; + } else if (compptr->h_samp_factor * 2 == cinfo->max_h_samp_factor && + compptr->v_samp_factor == cinfo->max_v_samp_factor) { + smoothok = FALSE; + downsample->methods[ci] = h2v1_downsample; + } else if (compptr->h_samp_factor * 2 == cinfo->max_h_samp_factor && + compptr->v_samp_factor * 2 == cinfo->max_v_samp_factor) { +#ifdef INPUT_SMOOTHING_SUPPORTED + if (cinfo->smoothing_factor) { + downsample->methods[ci] = h2v2_smooth_downsample; + downsample->pub.need_context_rows = TRUE; + } else +#endif + downsample->methods[ci] = h2v2_downsample; + } else if ((cinfo->max_h_samp_factor % compptr->h_samp_factor) == 0 && + (cinfo->max_v_samp_factor % compptr->v_samp_factor) == 0) { + smoothok = FALSE; + downsample->methods[ci] = int_downsample; + } else + ERREXIT(cinfo, JERR_FRACT_SAMPLE_NOTIMPL); + } + +#ifdef INPUT_SMOOTHING_SUPPORTED + if (cinfo->smoothing_factor && !smoothok) + TRACEMS(cinfo, 0, JTRC_SMOOTH_NOTIMPL); +#endif +} diff --git a/dcmjpeg/libijg16/jcscale.c b/dcmjpeg/libijg16/jcscale.c new file mode 100644 index 00000000..dc2ed92e --- /dev/null +++ b/dcmjpeg/libijg16/jcscale.c @@ -0,0 +1,63 @@ +/* + * jcscale.c + * + * Copyright (C) 1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains sample downscaling by 2^Pt for lossless JPEG. + */ + +#define JPEG_INTERNALS +#include "jinclude16.h" +#include "jpeglib16.h" +#include "jlossls16.h" /* Private declarations for lossless codec */ + + +#ifdef C_LOSSLESS_SUPPORTED + +METHODDEF(void) +simple_downscale(j_compress_ptr cinfo, + JSAMPROW input_buf, JSAMPROW output_buf, JDIMENSION width) +{ + /* j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec; */ + unsigned int xindex; + SHIFT_TEMPS + + for (xindex = 0; xindex < width; xindex++) + output_buf[xindex] = (JSAMPLE) RIGHT_SHIFT(GETJSAMPLE(input_buf[xindex]), + cinfo->Al); +} + + +METHODDEF(void) +noscale(j_compress_ptr cinfo, + JSAMPROW input_buf, JSAMPROW output_buf, JDIMENSION width) +{ + MEMCOPY(output_buf, input_buf, width * SIZEOF(JSAMPLE)); + return; +} + + +METHODDEF(void) +scaler_start_pass (j_compress_ptr cinfo) +{ + j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec; + + /* Set scaler function based on Pt */ + if (cinfo->Al) + losslsc->scaler_scale = simple_downscale; + else + losslsc->scaler_scale = noscale; +} + + +GLOBAL(void) +jinit_c_scaler (j_compress_ptr cinfo) +{ + j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec; + + losslsc->scaler_start_pass = scaler_start_pass; +} + +#endif /* C_LOSSLESS_SUPPORTED */ diff --git a/dcmjpeg/libijg16/jcshuff.c b/dcmjpeg/libijg16/jcshuff.c new file mode 100644 index 00000000..2ba6d86e --- /dev/null +++ b/dcmjpeg/libijg16/jcshuff.c @@ -0,0 +1,661 @@ +/* + * jcshuff.c + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains Huffman entropy encoding routines for sequential JPEG. + * + * Much of the complexity here has to do with supporting output suspension. + * If the data destination module demands suspension, we want to be able to + * back up to the start of the current MCU. To do this, we copy state + * variables into local working storage, and update them back to the + * permanent JPEG objects only upon successful completion of an MCU. + */ + +#define JPEG_INTERNALS +#include "jinclude16.h" +#include "jpeglib16.h" +#include "jlossy16.h" /* Private declarations for lossy codec */ +#include "jchuff16.h" /* Declarations shared with jc*huff.c */ + + +/* Expanded entropy encoder object for Huffman encoding. + * + * The savable_state subrecord contains fields that change within an MCU, + * but must not be updated permanently until we complete the MCU. + */ + +typedef struct { + IJG_INT32 put_buffer; /* current bit-accumulation buffer */ + int put_bits; /* # of bits now in it */ + int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */ +} savable_state; + +/* This macro is to work around compilers with missing or broken + * structure assignment. You'll need to fix this code if you have + * such a compiler and you change MAX_COMPS_IN_SCAN. + */ + +#ifndef NO_STRUCT_ASSIGN +#define ASSIGN_STATE(dest,src) ((dest) = (src)) +#else +#if MAX_COMPS_IN_SCAN == 4 +#define ASSIGN_STATE(dest,src) \ + ((dest).put_buffer = (src).put_buffer, \ + (dest).put_bits = (src).put_bits, \ + (dest).last_dc_val[0] = (src).last_dc_val[0], \ + (dest).last_dc_val[1] = (src).last_dc_val[1], \ + (dest).last_dc_val[2] = (src).last_dc_val[2], \ + (dest).last_dc_val[3] = (src).last_dc_val[3]) +#endif +#endif + + +typedef struct { + savable_state saved; /* Bit buffer & DC state at start of MCU */ + + /* These fields are NOT loaded into local working state. */ + unsigned int restarts_to_go; /* MCUs left in this restart interval */ + int next_restart_num; /* next restart number to write (0-7) */ + + /* Pointers to derived tables (these workspaces have image lifespan) */ + c_derived_tbl * dc_derived_tbls[NUM_HUFF_TBLS]; + c_derived_tbl * ac_derived_tbls[NUM_HUFF_TBLS]; + +#ifdef ENTROPY_OPT_SUPPORTED /* Statistics tables for optimization */ + long * dc_count_ptrs[NUM_HUFF_TBLS]; + long * ac_count_ptrs[NUM_HUFF_TBLS]; +#endif +} shuff_entropy_encoder; + +typedef shuff_entropy_encoder * shuff_entropy_ptr; + +/* Working state while writing an MCU. + * This struct contains all the fields that are needed by subroutines. + */ + +typedef struct { + JOCTET * next_output_byte; /* => next byte to write in buffer */ + size_t free_in_buffer; /* # of byte spaces remaining in buffer */ + savable_state cur; /* Current bit buffer & DC state */ + j_compress_ptr cinfo; /* dump_buffer needs access to this */ +} working_state; + + +/* Forward declarations */ +METHODDEF(boolean) encode_mcu_huff JPP((j_compress_ptr cinfo, + JBLOCKROW *MCU_data)); +METHODDEF(void) finish_pass_huff JPP((j_compress_ptr cinfo)); +#ifdef ENTROPY_OPT_SUPPORTED +METHODDEF(boolean) encode_mcu_gather JPP((j_compress_ptr cinfo, + JBLOCKROW *MCU_data)); +METHODDEF(void) finish_pass_gather JPP((j_compress_ptr cinfo)); +#endif + + +/* + * Initialize for a Huffman-compressed scan. + * If gather_statistics is TRUE, we do not output anything during the scan, + * just count the Huffman symbols used and generate Huffman code tables. + */ + +METHODDEF(void) +start_pass_huff (j_compress_ptr cinfo, boolean gather_statistics) +{ + j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; + shuff_entropy_ptr entropy = (shuff_entropy_ptr) lossyc->entropy_private; + int ci, dctbl, actbl; + jpeg_component_info * compptr; + + if (gather_statistics) { +#ifdef ENTROPY_OPT_SUPPORTED + lossyc->entropy_encode_mcu = encode_mcu_gather; + lossyc->pub.entropy_finish_pass = finish_pass_gather; +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } else { + lossyc->entropy_encode_mcu = encode_mcu_huff; + lossyc->pub.entropy_finish_pass = finish_pass_huff; + } + + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + dctbl = compptr->dc_tbl_no; + actbl = compptr->ac_tbl_no; + if (gather_statistics) { +#ifdef ENTROPY_OPT_SUPPORTED + /* Check for invalid table indexes */ + /* (make_c_derived_tbl does this in the other path) */ + if (dctbl < 0 || dctbl >= NUM_HUFF_TBLS) + ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, dctbl); + if (actbl < 0 || actbl >= NUM_HUFF_TBLS) + ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, actbl); + /* Allocate and zero the statistics tables */ + /* Note that jpeg_gen_optimal_table expects 257 entries in each table! */ + if (entropy->dc_count_ptrs[dctbl] == NULL) + entropy->dc_count_ptrs[dctbl] = (long *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + 257 * SIZEOF(long)); + MEMZERO(entropy->dc_count_ptrs[dctbl], 257 * SIZEOF(long)); + if (entropy->ac_count_ptrs[actbl] == NULL) + entropy->ac_count_ptrs[actbl] = (long *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + 257 * SIZEOF(long)); + MEMZERO(entropy->ac_count_ptrs[actbl], 257 * SIZEOF(long)); +#endif + } else { + /* Compute derived values for Huffman tables */ + /* We may do this more than once for a table, but it's not expensive */ + jpeg_make_c_derived_tbl(cinfo, TRUE, dctbl, + & entropy->dc_derived_tbls[dctbl]); + jpeg_make_c_derived_tbl(cinfo, FALSE, actbl, + & entropy->ac_derived_tbls[actbl]); + } + /* Initialize DC predictions to 0 */ + entropy->saved.last_dc_val[ci] = 0; + } + + /* Initialize bit buffer to empty */ + entropy->saved.put_buffer = 0; + entropy->saved.put_bits = 0; + + /* Initialize restart stuff */ + entropy->restarts_to_go = cinfo->restart_interval; + entropy->next_restart_num = 0; +} + + +/* Outputting bytes to the file */ + +/* Emit a byte, taking 'action' if must suspend. */ +#define emit_byte(state,val,action) \ + { *(state)->next_output_byte++ = (JOCTET) (val); \ + if (--(state)->free_in_buffer == 0) \ + if (! dump_buffer(state)) \ + { action; } } + + +LOCAL(boolean) +dump_buffer (working_state * state) +/* Empty the output buffer; return TRUE if successful, FALSE if must suspend */ +{ + struct jpeg_destination_mgr * dest = state->cinfo->dest; + + if (! (*dest->empty_output_buffer) (state->cinfo)) + return FALSE; + /* After a successful buffer dump, must reset buffer pointers */ + state->next_output_byte = dest->next_output_byte; + state->free_in_buffer = dest->free_in_buffer; + return TRUE; +} + + +/* Outputting bits to the file */ + +/* Only the right 24 bits of put_buffer are used; the valid bits are + * left-justified in this part. At most 16 bits can be passed to emit_bits + * in one call, and we never retain more than 7 bits in put_buffer + * between calls, so 24 bits are sufficient. + */ + +INLINE +LOCAL(boolean) +emit_bits (working_state * state, unsigned int code, int size) +/* Emit some bits; return TRUE if successful, FALSE if must suspend */ +{ + /* This routine is heavily used, so it's worth coding tightly. */ + register IJG_INT32 put_buffer = (IJG_INT32) code; + register int put_bits = state->cur.put_bits; + + /* if size is 0, caller used an invalid Huffman table entry */ + if (size == 0) + ERREXIT(state->cinfo, JERR_HUFF_MISSING_CODE); + + put_buffer &= (((IJG_INT32) 1)<cur.put_buffer; /* and merge with old buffer contents */ + + while (put_bits >= 8) { + int c = (int) ((put_buffer >> 16) & 0xFF); + + emit_byte(state, c, return FALSE); + if (c == 0xFF) { /* need to stuff a zero byte? */ + emit_byte(state, 0, return FALSE); + } + put_buffer <<= 8; + put_bits -= 8; + } + + state->cur.put_buffer = put_buffer; /* update state variables */ + state->cur.put_bits = put_bits; + + return TRUE; +} + + +LOCAL(boolean) +flush_bits (working_state * state) +{ + if (! emit_bits(state, 0x7F, 7)) /* fill any partial byte with ones */ + return FALSE; + state->cur.put_buffer = 0; /* and reset bit-buffer to empty */ + state->cur.put_bits = 0; + return TRUE; +} + + +/* Encode a single block's worth of coefficients */ + +LOCAL(boolean) +encode_one_block (working_state * state, JCOEFPTR block, int last_dc_val, + c_derived_tbl *dctbl, c_derived_tbl *actbl) +{ + register int temp, temp2; + register int nbits; + register int k, r, i; + + /* Encode the DC coefficient difference per section F.1.2.1 */ + + temp = temp2 = block[0] - last_dc_val; + + if (temp < 0) { + temp = -temp; /* temp is abs value of input */ + /* For a negative input, want temp2 = bitwise complement of abs(input) */ + /* This code assumes we are on a two's complement machine */ + temp2--; + } + + /* Find the number of bits needed for the magnitude of the coefficient */ + nbits = 0; + while (temp) { + nbits++; + temp >>= 1; + } + /* Check for out-of-range coefficient values. + * Since we're encoding a difference, the range limit is twice as much. + */ + if (nbits > MAX_COEF_BITS+1) + ERREXIT(state->cinfo, JERR_BAD_DCT_COEF); + + /* Emit the Huffman-coded symbol for the number of bits */ + if (! emit_bits(state, dctbl->ehufco[nbits], dctbl->ehufsi[nbits])) + return FALSE; + + /* Emit that number of bits of the value, if positive, */ + /* or the complement of its magnitude, if negative. */ + if (nbits) /* emit_bits rejects calls with size 0 */ + if (! emit_bits(state, (unsigned int) temp2, nbits)) + return FALSE; + + /* Encode the AC coefficients per section F.1.2.2 */ + + r = 0; /* r = run length of zeros */ + + for (k = 1; k < DCTSIZE2; k++) { + if ((temp = block[jpeg_natural_order[k]]) == 0) { + r++; + } else { + /* if run length > 15, must emit special run-length-16 codes (0xF0) */ + while (r > 15) { + if (! emit_bits(state, actbl->ehufco[0xF0], actbl->ehufsi[0xF0])) + return FALSE; + r -= 16; + } + + temp2 = temp; + if (temp < 0) { + temp = -temp; /* temp is abs value of input */ + /* This code assumes we are on a two's complement machine */ + temp2--; + } + + /* Find the number of bits needed for the magnitude of the coefficient */ + nbits = 1; /* there must be at least one 1 bit */ + while ((temp >>= 1)) + nbits++; + /* Check for out-of-range coefficient values */ + if (nbits > MAX_COEF_BITS) + ERREXIT(state->cinfo, JERR_BAD_DCT_COEF); + + /* Emit Huffman symbol for run length / number of bits */ + i = (r << 4) + nbits; + if (! emit_bits(state, actbl->ehufco[i], actbl->ehufsi[i])) + return FALSE; + + /* Emit that number of bits of the value, if positive, */ + /* or the complement of its magnitude, if negative. */ + if (! emit_bits(state, (unsigned int) temp2, nbits)) + return FALSE; + + r = 0; + } + } + + /* If the last coef(s) were zero, emit an end-of-block code */ + if (r > 0) + if (! emit_bits(state, actbl->ehufco[0], actbl->ehufsi[0])) + return FALSE; + + return TRUE; +} + + +/* + * Emit a restart marker & resynchronize predictions. + */ + +LOCAL(boolean) +emit_restart (working_state * state, int restart_num) +{ + int ci; + + if (! flush_bits(state)) + return FALSE; + + emit_byte(state, 0xFF, return FALSE); + emit_byte(state, JPEG_RST0 + restart_num, return FALSE); + + /* Re-initialize DC predictions to 0 */ + for (ci = 0; ci < state->cinfo->comps_in_scan; ci++) + state->cur.last_dc_val[ci] = 0; + + /* The restart counter is not updated until we successfully write the MCU. */ + + return TRUE; +} + + +/* + * Encode and output one MCU's worth of Huffman-compressed coefficients. + */ + +METHODDEF(boolean) +encode_mcu_huff (j_compress_ptr cinfo, JBLOCKROW *MCU_data) +{ + j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; + shuff_entropy_ptr entropy = (shuff_entropy_ptr) lossyc->entropy_private; + working_state state; + int blkn, ci; + jpeg_component_info * compptr; + + /* Load up working state */ + state.next_output_byte = cinfo->dest->next_output_byte; + state.free_in_buffer = cinfo->dest->free_in_buffer; + ASSIGN_STATE(state.cur, entropy->saved); + state.cinfo = cinfo; + + /* Emit restart marker if needed */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) + if (! emit_restart(&state, entropy->next_restart_num)) + return FALSE; + } + + /* Encode the MCU data blocks */ + for (blkn = 0; blkn < cinfo->data_units_in_MCU; blkn++) { + ci = cinfo->MCU_membership[blkn]; + compptr = cinfo->cur_comp_info[ci]; + if (! encode_one_block(&state, + MCU_data[blkn][0], state.cur.last_dc_val[ci], + entropy->dc_derived_tbls[compptr->dc_tbl_no], + entropy->ac_derived_tbls[compptr->ac_tbl_no])) + return FALSE; + /* Update last_dc_val */ + state.cur.last_dc_val[ci] = MCU_data[blkn][0][0]; + } + + /* Completed MCU, so update state */ + cinfo->dest->next_output_byte = state.next_output_byte; + cinfo->dest->free_in_buffer = state.free_in_buffer; + ASSIGN_STATE(entropy->saved, state.cur); + + /* Update restart-interval state too */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) { + entropy->restarts_to_go = cinfo->restart_interval; + entropy->next_restart_num++; + entropy->next_restart_num &= 7; + } + entropy->restarts_to_go--; + } + + return TRUE; +} + + +/* + * Finish up at the end of a Huffman-compressed scan. + */ + +METHODDEF(void) +finish_pass_huff (j_compress_ptr cinfo) +{ + j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; + shuff_entropy_ptr entropy = (shuff_entropy_ptr) lossyc->entropy_private; + working_state state; + + /* Load up working state ... flush_bits needs it */ + state.next_output_byte = cinfo->dest->next_output_byte; + state.free_in_buffer = cinfo->dest->free_in_buffer; + ASSIGN_STATE(state.cur, entropy->saved); + state.cinfo = cinfo; + + /* Flush out the last data */ + if (! flush_bits(&state)) + ERREXIT(cinfo, JERR_CANT_SUSPEND); + + /* Update state */ + cinfo->dest->next_output_byte = state.next_output_byte; + cinfo->dest->free_in_buffer = state.free_in_buffer; + ASSIGN_STATE(entropy->saved, state.cur); +} + + +/* + * Huffman coding optimization. + * + * We first scan the supplied data and count the number of uses of each symbol + * that is to be Huffman-coded. (This process MUST agree with the code above.) + * Then we build a Huffman coding tree for the observed counts. + * Symbols which are not needed at all for the particular image are not + * assigned any code, which saves space in the DHT marker as well as in + * the compressed data. + */ + +#ifdef ENTROPY_OPT_SUPPORTED + + +/* Process a single block's worth of coefficients */ + +LOCAL(void) +htest_one_block (j_compress_ptr cinfo, JCOEFPTR block, int last_dc_val, + long dc_counts[], long ac_counts[]) +{ + register int temp; + register int nbits; + register int k, r; + + /* Encode the DC coefficient difference per section F.1.2.1 */ + + temp = block[0] - last_dc_val; + if (temp < 0) + temp = -temp; + + /* Find the number of bits needed for the magnitude of the coefficient */ + nbits = 0; + while (temp) { + nbits++; + temp >>= 1; + } + /* Check for out-of-range coefficient values. + * Since we're encoding a difference, the range limit is twice as much. + */ + if (nbits > MAX_COEF_BITS+1) + ERREXIT(cinfo, JERR_BAD_DCT_COEF); + + /* Count the Huffman symbol for the number of bits */ + dc_counts[nbits]++; + + /* Encode the AC coefficients per section F.1.2.2 */ + + r = 0; /* r = run length of zeros */ + + for (k = 1; k < DCTSIZE2; k++) { + if ((temp = block[jpeg_natural_order[k]]) == 0) { + r++; + } else { + /* if run length > 15, must emit special run-length-16 codes (0xF0) */ + while (r > 15) { + ac_counts[0xF0]++; + r -= 16; + } + + /* Find the number of bits needed for the magnitude of the coefficient */ + if (temp < 0) + temp = -temp; + + /* Find the number of bits needed for the magnitude of the coefficient */ + nbits = 1; /* there must be at least one 1 bit */ + while ((temp >>= 1)) + nbits++; + /* Check for out-of-range coefficient values */ + if (nbits > MAX_COEF_BITS) + ERREXIT(cinfo, JERR_BAD_DCT_COEF); + + /* Count Huffman symbol for run length / number of bits */ + ac_counts[(r << 4) + nbits]++; + + r = 0; + } + } + + /* If the last coef(s) were zero, emit an end-of-block code */ + if (r > 0) + ac_counts[0]++; +} + + +/* + * Trial-encode one MCU's worth of Huffman-compressed coefficients. + * No data is actually output, so no suspension return is possible. + */ + +METHODDEF(boolean) +encode_mcu_gather (j_compress_ptr cinfo, JBLOCKROW *MCU_data) +{ + j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; + shuff_entropy_ptr entropy = (shuff_entropy_ptr) lossyc->entropy_private; + int blkn, ci; + jpeg_component_info * compptr; + + /* Take care of restart intervals if needed */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) { + /* Re-initialize DC predictions to 0 */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) + entropy->saved.last_dc_val[ci] = 0; + /* Update restart state */ + entropy->restarts_to_go = cinfo->restart_interval; + } + entropy->restarts_to_go--; + } + + for (blkn = 0; blkn < cinfo->data_units_in_MCU; blkn++) { + ci = cinfo->MCU_membership[blkn]; + compptr = cinfo->cur_comp_info[ci]; + htest_one_block(cinfo, MCU_data[blkn][0], entropy->saved.last_dc_val[ci], + entropy->dc_count_ptrs[compptr->dc_tbl_no], + entropy->ac_count_ptrs[compptr->ac_tbl_no]); + entropy->saved.last_dc_val[ci] = MCU_data[blkn][0][0]; + } + + return TRUE; +} + + +/* + * Finish up a statistics-gathering pass and create the new Huffman tables. + */ + +METHODDEF(void) +finish_pass_gather (j_compress_ptr cinfo) +{ + j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; + shuff_entropy_ptr entropy = (shuff_entropy_ptr) lossyc->entropy_private; + int ci, dctbl, actbl; + jpeg_component_info * compptr; + JHUFF_TBL **htblptr; + boolean did_dc[NUM_HUFF_TBLS]; + boolean did_ac[NUM_HUFF_TBLS]; + + /* It's important not to apply jpeg_gen_optimal_table more than once + * per table, because it clobbers the input frequency counts! + */ + MEMZERO(did_dc, SIZEOF(did_dc)); + MEMZERO(did_ac, SIZEOF(did_ac)); + + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + dctbl = compptr->dc_tbl_no; + actbl = compptr->ac_tbl_no; + if (! did_dc[dctbl]) { + htblptr = & cinfo->dc_huff_tbl_ptrs[dctbl]; + if (*htblptr == NULL) + *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo); + jpeg_gen_optimal_table(cinfo, *htblptr, entropy->dc_count_ptrs[dctbl]); + did_dc[dctbl] = TRUE; + } + if (! did_ac[actbl]) { + htblptr = & cinfo->ac_huff_tbl_ptrs[actbl]; + if (*htblptr == NULL) + *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo); + jpeg_gen_optimal_table(cinfo, *htblptr, entropy->ac_count_ptrs[actbl]); + did_ac[actbl] = TRUE; + } + } +} + + +#endif /* ENTROPY_OPT_SUPPORTED */ + + +METHODDEF(boolean) +need_optimization_pass (j_compress_ptr cinfo) +{ + return TRUE; +} + + +/* + * Module initialization routine for Huffman entropy encoding. + */ + +GLOBAL(void) +jinit_shuff_encoder (j_compress_ptr cinfo) +{ + j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; + shuff_entropy_ptr entropy; + int i; + + entropy = (shuff_entropy_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(shuff_entropy_encoder)); + lossyc->entropy_private = (struct jpeg_entropy_encoder *) entropy; + lossyc->pub.entropy_start_pass = start_pass_huff; + lossyc->pub.need_optimization_pass = need_optimization_pass; + + /* Mark tables unallocated */ + for (i = 0; i < NUM_HUFF_TBLS; i++) { + entropy->dc_derived_tbls[i] = entropy->ac_derived_tbls[i] = NULL; +#ifdef ENTROPY_OPT_SUPPORTED + entropy->dc_count_ptrs[i] = entropy->ac_count_ptrs[i] = NULL; +#endif + } +} diff --git a/dcmjpeg/libijg16/jctrans.c b/dcmjpeg/libijg16/jctrans.c new file mode 100644 index 00000000..046a704b --- /dev/null +++ b/dcmjpeg/libijg16/jctrans.c @@ -0,0 +1,424 @@ +/* + * jctrans.c + * + * Copyright (C) 1995-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains library routines for transcoding compression, + * that is, writing raw DCT coefficient arrays to an output JPEG file. + * The routines in jcapimin.c will also be needed by a transcoder. + */ + +#define JPEG_INTERNALS +#include "jinclude16.h" +#include "jpeglib16.h" +#include "jlossy16.h" /* Private declarations for lossy codec */ + + +/* Forward declarations */ +LOCAL(void) transencode_master_selection + JPP((j_compress_ptr cinfo, jvirt_barray_ptr * coef_arrays)); +LOCAL(void) transencode_codec + JPP((j_compress_ptr cinfo, jvirt_barray_ptr * coef_arrays)); +LOCAL(void) transencode_coef_controller + JPP((j_compress_ptr cinfo, jvirt_barray_ptr * coef_arrays)); + + +/* + * Compression initialization for writing raw-coefficient data. + * Before calling this, all parameters and a data destination must be set up. + * Call jpeg_finish_compress() to actually write the data. + * + * The number of passed virtual arrays must match cinfo->num_components. + * Note that the virtual arrays need not be filled or even realized at + * the time write_coefficients is called; indeed, if the virtual arrays + * were requested from this compression object's memory manager, they + * typically will be realized during this routine and filled afterwards. + */ + +GLOBAL(void) +jpeg_write_coefficients (j_compress_ptr cinfo, jvirt_barray_ptr * coef_arrays) +{ + if (cinfo->global_state != CSTATE_START) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + /* Mark all tables to be written */ + jpeg_suppress_tables(cinfo, FALSE); + /* (Re)initialize error mgr and destination modules */ + (*cinfo->err->reset_error_mgr) ((j_common_ptr) cinfo); + (*cinfo->dest->init_destination) (cinfo); + /* Perform master selection of active modules */ + transencode_master_selection(cinfo, coef_arrays); + /* Wait for jpeg_finish_compress() call */ + cinfo->next_scanline = 0; /* so jpeg_write_marker works */ + cinfo->global_state = CSTATE_WRCOEFS; +} + + +/* + * Initialize the compression object with default parameters, + * then copy from the source object all parameters needed for lossless + * transcoding. Parameters that can be varied without loss (such as + * scan script and Huffman optimization) are left in their default states. + */ + +GLOBAL(void) +jpeg_copy_critical_parameters (j_decompress_ptr srcinfo, + j_compress_ptr dstinfo) +{ + JQUANT_TBL ** qtblptr; + jpeg_component_info *incomp, *outcomp; + JQUANT_TBL *c_quant, *slot_quant; + int tblno, ci, coefi; + + /* Safety check to ensure start_compress not called yet. */ + if (dstinfo->global_state != CSTATE_START) + ERREXIT1(dstinfo, JERR_BAD_STATE, dstinfo->global_state); + /* Copy fundamental image dimensions */ + dstinfo->image_width = srcinfo->image_width; + dstinfo->image_height = srcinfo->image_height; + dstinfo->input_components = srcinfo->num_components; + dstinfo->in_color_space = srcinfo->jpeg_color_space; + /* Initialize all parameters to default values */ + jpeg_set_defaults(dstinfo); + /* jpeg_set_defaults may choose wrong colorspace, eg YCbCr if input is RGB. + * Fix it to get the right header markers for the image colorspace. + */ + jpeg_set_colorspace(dstinfo, srcinfo->jpeg_color_space); + dstinfo->data_precision = srcinfo->data_precision; + dstinfo->CCIR601_sampling = srcinfo->CCIR601_sampling; + /* Copy the source's quantization tables. */ + for (tblno = 0; tblno < NUM_QUANT_TBLS; tblno++) { + if (srcinfo->quant_tbl_ptrs[tblno] != NULL) { + qtblptr = & dstinfo->quant_tbl_ptrs[tblno]; + if (*qtblptr == NULL) + *qtblptr = jpeg_alloc_quant_table((j_common_ptr) dstinfo); + MEMCOPY((*qtblptr)->quantval, + srcinfo->quant_tbl_ptrs[tblno]->quantval, + SIZEOF((*qtblptr)->quantval)); + (*qtblptr)->sent_table = FALSE; + } + } + /* Copy the source's per-component info. + * Note we assume jpeg_set_defaults has allocated the dest comp_info array. + */ + dstinfo->num_components = srcinfo->num_components; + if (dstinfo->num_components < 1 || dstinfo->num_components > MAX_COMPONENTS) + ERREXIT2(dstinfo, JERR_COMPONENT_COUNT, dstinfo->num_components, + MAX_COMPONENTS); + for (ci = 0, incomp = srcinfo->comp_info, outcomp = dstinfo->comp_info; + ci < dstinfo->num_components; ci++, incomp++, outcomp++) { + outcomp->component_id = incomp->component_id; + outcomp->h_samp_factor = incomp->h_samp_factor; + outcomp->v_samp_factor = incomp->v_samp_factor; + outcomp->quant_tbl_no = incomp->quant_tbl_no; + /* Make sure saved quantization table for component matches the qtable + * slot. If not, the input file re-used this qtable slot. + * IJG encoder currently cannot duplicate this. + */ + tblno = outcomp->quant_tbl_no; + if (tblno < 0 || tblno >= NUM_QUANT_TBLS || + srcinfo->quant_tbl_ptrs[tblno] == NULL) + ERREXIT1(dstinfo, JERR_NO_QUANT_TABLE, tblno); + slot_quant = srcinfo->quant_tbl_ptrs[tblno]; + c_quant = incomp->quant_table; + if (c_quant != NULL) { + for (coefi = 0; coefi < DCTSIZE2; coefi++) { + if (c_quant->quantval[coefi] != slot_quant->quantval[coefi]) + ERREXIT1(dstinfo, JERR_MISMATCHED_QUANT_TABLE, tblno); + } + } + /* Note: we do not copy the source's Huffman table assignments; + * instead we rely on jpeg_set_colorspace to have made a suitable choice. + */ + } + /* Also copy JFIF version and resolution information, if available. + * Strictly speaking this isn't "critical" info, but it's nearly + * always appropriate to copy it if available. In particular, + * if the application chooses to copy JFIF 1.02 extension markers from + * the source file, we need to copy the version to make sure we don't + * emit a file that has 1.02 extensions but a claimed version of 1.01. + * We will *not*, however, copy version info from mislabeled "2.01" files. + */ + if (srcinfo->saw_JFIF_marker) { + if (srcinfo->JFIF_major_version == 1) { + dstinfo->JFIF_major_version = srcinfo->JFIF_major_version; + dstinfo->JFIF_minor_version = srcinfo->JFIF_minor_version; + } + dstinfo->density_unit = srcinfo->density_unit; + dstinfo->X_density = srcinfo->X_density; + dstinfo->Y_density = srcinfo->Y_density; + } +} + + +/* + * Master selection of compression modules for transcoding. + * This substitutes for jcinit.c's initialization of the full compressor. + */ + +LOCAL(void) +transencode_master_selection (j_compress_ptr cinfo, + jvirt_barray_ptr * coef_arrays) +{ + cinfo->data_unit = DCTSIZE; + /* Although we don't actually use input_components for transcoding, + * jcmaster.c's initial_setup will complain if input_components is 0. + */ + cinfo->input_components = 1; + /* Initialize master control (includes parameter checking/processing) */ + jinit_c_master_control(cinfo, TRUE /* transcode only */); + + /* We need a special compression codec. */ + transencode_codec(cinfo, coef_arrays); + + jinit_marker_writer(cinfo); + + /* We can now tell the memory manager to allocate virtual arrays. */ + (*cinfo->mem->realize_virt_arrays) ((j_common_ptr) cinfo); + + /* Write the datastream header (SOI, JFIF) immediately. + * Frame and scan headers are postponed till later. + * This lets application insert special markers after the SOI. + */ + (*cinfo->marker->write_file_header) (cinfo); +} + + +/* + * The rest of this file is a special implementation of the coefficient + * buffer controller. This is similar to jccoefct.c, but it handles only + * output from presupplied virtual arrays. Furthermore, we generate any + * dummy padding blocks on-the-fly rather than expecting them to be present + * in the arrays. + */ + +/* Private buffer controller object */ + +typedef struct { + JDIMENSION iMCU_row_num; /* iMCU row # within image */ + JDIMENSION mcu_ctr; /* counts MCUs processed in current row */ + int MCU_vert_offset; /* counts MCU rows within iMCU row */ + int MCU_rows_per_iMCU_row; /* number of such rows needed */ + + /* Virtual block array for each component. */ + jvirt_barray_ptr * whole_image; + + /* Workspace for constructing dummy blocks at right/bottom edges. */ + JBLOCKROW dummy_buffer[C_MAX_DATA_UNITS_IN_MCU]; +} c_coef_controller; + +typedef c_coef_controller * c_coef_ptr; + + +LOCAL(void) +start_iMCU_row (j_compress_ptr cinfo) +/* Reset within-iMCU-row counters for a new row */ +{ + j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; + c_coef_ptr coef = (c_coef_ptr) lossyc->coef_private; + + /* In an interleaved scan, an MCU row is the same as an iMCU row. + * In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows. + * But at the bottom of the image, process only what's left. + */ + if (cinfo->comps_in_scan > 1) { + coef->MCU_rows_per_iMCU_row = 1; + } else { + if (coef->iMCU_row_num < (cinfo->total_iMCU_rows-1)) + coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->v_samp_factor; + else + coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->last_row_height; + } + + coef->mcu_ctr = 0; + coef->MCU_vert_offset = 0; +} + + +/* + * Initialize for a processing pass. + */ + +METHODDEF(void) +start_pass_coef (j_compress_ptr cinfo, J_BUF_MODE pass_mode) +{ + j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; + c_coef_ptr coef = (c_coef_ptr) lossyc->coef_private; + + if (pass_mode != JBUF_CRANK_DEST) + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + + coef->iMCU_row_num = 0; + start_iMCU_row(cinfo); +} + + +/* + * Process some data. + * We process the equivalent of one fully interleaved MCU row ("iMCU" row) + * per call, ie, v_samp_factor block rows for each component in the scan. + * The data is obtained from the virtual arrays and fed to the entropy coder. + * Returns TRUE if the iMCU row is completed, FALSE if suspended. + * + * NB: input_buf is ignored; it is likely to be a NULL pointer. + */ + +METHODDEF(boolean) +compress_output (j_compress_ptr cinfo, JSAMPIMAGE input_buf) +{ + j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; + c_coef_ptr coef = (c_coef_ptr) lossyc->coef_private; + JDIMENSION MCU_col_num; /* index of current MCU within row */ + JDIMENSION last_MCU_col = cinfo->MCUs_per_row - 1; + JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; + int blkn, ci, xindex, yindex, yoffset, blockcnt; + JDIMENSION start_col; + JBLOCKARRAY buffer[MAX_COMPS_IN_SCAN]; + JBLOCKROW MCU_buffer[C_MAX_DATA_UNITS_IN_MCU]; + JBLOCKROW buffer_ptr; + jpeg_component_info *compptr; + + /* Align the virtual buffers for the components used in this scan. */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + buffer[ci] = (*cinfo->mem->access_virt_barray) + ((j_common_ptr) cinfo, coef->whole_image[compptr->component_index], + coef->iMCU_row_num * (JDIMENSION) compptr->v_samp_factor, + (JDIMENSION) compptr->v_samp_factor, FALSE); + } + + /* Loop to process one whole iMCU row */ + for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row; + yoffset++) { + for (MCU_col_num = coef->mcu_ctr; MCU_col_num < cinfo->MCUs_per_row; + MCU_col_num++) { + /* Construct list of pointers to DCT blocks belonging to this MCU */ + blkn = 0; /* index of current DCT block within MCU */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + start_col = MCU_col_num * (JDIMENSION)compptr->MCU_width; + blockcnt = (MCU_col_num < last_MCU_col) ? compptr->MCU_width + : compptr->last_col_width; + for (yindex = 0; yindex < compptr->MCU_height; yindex++) { + if (coef->iMCU_row_num < last_iMCU_row || + yindex+yoffset < compptr->last_row_height) { + /* Fill in pointers to real blocks in this row */ + buffer_ptr = buffer[ci][yindex+yoffset] + start_col; + for (xindex = 0; xindex < blockcnt; xindex++) + MCU_buffer[blkn++] = buffer_ptr++; + } else { + /* At bottom of image, need a whole row of dummy blocks */ + xindex = 0; + } + /* Fill in any dummy blocks needed in this row. + * Dummy blocks are filled in the same way as in jccoefct.c: + * all zeroes in the AC entries, DC entries equal to previous + * block's DC value. The init routine has already zeroed the + * AC entries, so we need only set the DC entries correctly. + */ + for (; xindex < compptr->MCU_width; xindex++) { + MCU_buffer[blkn] = coef->dummy_buffer[blkn]; + MCU_buffer[blkn][0][0] = MCU_buffer[blkn-1][0][0]; + blkn++; + } + } + } + /* Try to write the MCU. */ + if (! (*lossyc->entropy_encode_mcu) (cinfo, MCU_buffer)) { + /* Suspension forced; update state counters and exit */ + coef->MCU_vert_offset = yoffset; + coef->mcu_ctr = MCU_col_num; + return FALSE; + } + } + /* Completed an MCU row, but perhaps not an iMCU row */ + coef->mcu_ctr = 0; + } + /* Completed the iMCU row, advance counters for next one */ + coef->iMCU_row_num++; + start_iMCU_row(cinfo); + return TRUE; +} + + +/* + * Initialize coefficient buffer controller. + * + * Each passed coefficient array must be the right size for that + * coefficient: width_in_data_units wide and height_in_data_units high, + * with unitheight at least v_samp_factor. + */ + +LOCAL(void) +transencode_coef_controller (j_compress_ptr cinfo, + jvirt_barray_ptr * coef_arrays) +{ + j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; + c_coef_ptr coef; + JBLOCKROW buffer; + int i; + + coef = (c_coef_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(c_coef_controller)); + lossyc->coef_private = (struct jpeg_c_coef_controller *) coef; + + /* Save pointer to virtual arrays */ + coef->whole_image = coef_arrays; + + /* Allocate and pre-zero space for dummy DCT blocks. */ + buffer = (JBLOCKROW) + (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE, + C_MAX_DATA_UNITS_IN_MCU * SIZEOF(JBLOCK)); + jzero_far((void FAR *) buffer, C_MAX_DATA_UNITS_IN_MCU * SIZEOF(JBLOCK)); + for (i = 0; i < C_MAX_DATA_UNITS_IN_MCU; i++) { + coef->dummy_buffer[i] = buffer + i; + } +} + + +/* + * Initialize the transencoer codec. + * This is called only once, during master selection. + */ + +LOCAL(void) +transencode_codec (j_compress_ptr cinfo, + jvirt_barray_ptr * coef_arrays) +{ + j_lossy_c_ptr lossyc; + + /* Create subobject in permanent pool */ + lossyc = (j_lossy_c_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, + SIZEOF(jpeg_lossy_c_codec)); + cinfo->codec = (struct jpeg_c_codec *) lossyc; + + /* Initialize sub-modules */ + + /* Entropy encoding: either Huffman or arithmetic coding. */ + if (cinfo->arith_code) { +#ifdef WITH_ARITHMETIC_PATCH + jinit_arith_encoder(cinfo); +#else + ERREXIT(cinfo, JERR_ARITH_NOTIMPL); +#endif + } else { + if (cinfo->process == JPROC_PROGRESSIVE) { +#ifdef C_PROGRESSIVE_SUPPORTED + jinit_phuff_encoder(cinfo); +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } else + jinit_shuff_encoder(cinfo); + } + + /* We need a special coefficient buffer controller. */ + transencode_coef_controller(cinfo, coef_arrays); + + /* Initialize method pointers */ + lossyc->pub.start_pass = start_pass_coef; + lossyc->pub.compress_data = compress_output; +} diff --git a/dcmjpeg/libijg16/jdapimin.c b/dcmjpeg/libijg16/jdapimin.c new file mode 100644 index 00000000..c123e9f6 --- /dev/null +++ b/dcmjpeg/libijg16/jdapimin.c @@ -0,0 +1,401 @@ +/* + * jdapimin.c + * + * Copyright (C) 1994-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains application interface code for the decompression half + * of the JPEG library. These are the "minimum" API routines that may be + * needed in either the normal full-decompression case or the + * transcoding-only case. + * + * Most of the routines intended to be called directly by an application + * are in this file or in jdapistd.c. But also see jcomapi.c for routines + * shared by compression and decompression, and jdtrans.c for the transcoding + * case. + */ + +#define JPEG_INTERNALS +#include "jinclude16.h" +#include "jpeglib16.h" + + +/* + * Initialization of a JPEG decompression object. + * The error manager must already be set up (in case memory manager fails). + */ + +GLOBAL(void) +jpeg_CreateDecompress (j_decompress_ptr cinfo, int version, size_t structsize) +{ + int i; + + /* Guard against version mismatches between library and caller. */ + cinfo->mem = NULL; /* so jpeg_destroy knows mem mgr not called */ + if (version != JPEG_LIB_VERSION) + ERREXIT2(cinfo, JERR_BAD_LIB_VERSION, JPEG_LIB_VERSION, version); + if (structsize != SIZEOF(struct jpeg_decompress_struct)) + ERREXIT2(cinfo, JERR_BAD_STRUCT_SIZE, + (int) SIZEOF(struct jpeg_decompress_struct), (int) structsize); + + /* For debugging purposes, we zero the whole master structure. + * But the application has already set the err pointer, and may have set + * client_data, so we have to save and restore those fields. + * Note: if application hasn't set client_data, tools like Purify may + * complain here. + */ + { + struct jpeg_error_mgr * err = cinfo->err; + void * client_data = cinfo->client_data; /* ignore Purify complaint here */ + MEMZERO(cinfo, SIZEOF(struct jpeg_decompress_struct)); + cinfo->err = err; + cinfo->client_data = client_data; + } + cinfo->is_decompressor = TRUE; + + /* Initialize a memory manager instance for this object */ + jinit_memory_mgr((j_common_ptr) cinfo); + + /* Zero out pointers to permanent structures. */ + cinfo->progress = NULL; + cinfo->src = NULL; + + for (i = 0; i < NUM_QUANT_TBLS; i++) + cinfo->quant_tbl_ptrs[i] = NULL; + + for (i = 0; i < NUM_HUFF_TBLS; i++) { + cinfo->dc_huff_tbl_ptrs[i] = NULL; + cinfo->ac_huff_tbl_ptrs[i] = NULL; + } + + /* Initialize marker processor so application can override methods + * for COM, APPn markers before calling jpeg_read_header. + */ + cinfo->marker_list = NULL; + jinit_marker_reader(cinfo); + + /* And initialize the overall input controller. */ + jinit_input_controller(cinfo); + + /* OK, I'm ready */ + cinfo->global_state = DSTATE_START; +} + + +/* + * Destruction of a JPEG decompression object + */ + +GLOBAL(void) +jpeg_destroy_decompress (j_decompress_ptr cinfo) +{ + jpeg_destroy((j_common_ptr) cinfo); /* use common routine */ +} + + +/* + * Abort processing of a JPEG decompression operation, + * but don't destroy the object itself. + */ + +GLOBAL(void) +jpeg_abort_decompress (j_decompress_ptr cinfo) +{ + jpeg_abort((j_common_ptr) cinfo); /* use common routine */ +} + + +/* + * Set default decompression parameters. + */ + +LOCAL(void) +default_decompress_parms (j_decompress_ptr cinfo) +{ + /* Guess the input colorspace, and set output colorspace accordingly. */ + /* (Wish JPEG committee had provided a real way to specify this...) */ + /* Note application may override our guesses. */ + switch (cinfo->num_components) { + case 1: + cinfo->jpeg_color_space = JCS_GRAYSCALE; + cinfo->out_color_space = JCS_GRAYSCALE; + break; + + case 3: + if (cinfo->saw_JFIF_marker) { + cinfo->jpeg_color_space = JCS_YCbCr; /* JFIF implies YCbCr */ + } else if (cinfo->saw_Adobe_marker) { + switch (cinfo->Adobe_transform) { + case 0: + cinfo->jpeg_color_space = JCS_RGB; + break; + case 1: + cinfo->jpeg_color_space = JCS_YCbCr; + break; + default: + WARNMS1(cinfo, JWRN_ADOBE_XFORM, cinfo->Adobe_transform); + cinfo->jpeg_color_space = JCS_YCbCr; /* assume it's YCbCr */ + break; + } + } else { + /* Saw no special markers, try to guess from the component IDs */ + int cid0 = cinfo->comp_info[0].component_id; + int cid1 = cinfo->comp_info[1].component_id; + int cid2 = cinfo->comp_info[2].component_id; + + if (cid0 == 1 && cid1 == 2 && cid2 == 3) + cinfo->jpeg_color_space = JCS_YCbCr; /* assume JFIF w/out marker */ + else if (cid0 == 82 && cid1 == 71 && cid2 == 66) + cinfo->jpeg_color_space = JCS_RGB; /* ASCII 'R', 'G', 'B' */ + else { + if (cinfo->process == JPROC_LOSSLESS) { + TRACEMS3(cinfo, 1, JTRC_UNKNOWN_LOSSLESS_IDS, cid0, cid1, cid2); + cinfo->jpeg_color_space = JCS_RGB; /* assume it's RGB */ + } + else { /* Lossy processes */ + TRACEMS3(cinfo, 1, JTRC_UNKNOWN_LOSSY_IDS, cid0, cid1, cid2); + cinfo->jpeg_color_space = JCS_YCbCr; /* assume it's YCbCr */ + } + } + } + /* Always guess RGB is proper output colorspace. */ + cinfo->out_color_space = JCS_RGB; + break; + + case 4: + if (cinfo->saw_Adobe_marker) { + switch (cinfo->Adobe_transform) { + case 0: + cinfo->jpeg_color_space = JCS_CMYK; + break; + case 2: + cinfo->jpeg_color_space = JCS_YCCK; + break; + default: + WARNMS1(cinfo, JWRN_ADOBE_XFORM, cinfo->Adobe_transform); + cinfo->jpeg_color_space = JCS_YCCK; /* assume it's YCCK */ + break; + } + } else { + /* No special markers, assume straight CMYK. */ + cinfo->jpeg_color_space = JCS_CMYK; + } + cinfo->out_color_space = JCS_CMYK; + break; + + default: + cinfo->jpeg_color_space = JCS_UNKNOWN; + cinfo->out_color_space = JCS_UNKNOWN; + break; + } + + /* Set defaults for other decompression parameters. */ + cinfo->scale_num = 1; /* 1:1 scaling */ + cinfo->scale_denom = 1; + cinfo->output_gamma = 1.0; + cinfo->buffered_image = FALSE; + cinfo->raw_data_out = FALSE; + cinfo->dct_method = JDCT_DEFAULT; + cinfo->do_fancy_upsampling = TRUE; + cinfo->do_block_smoothing = TRUE; + cinfo->quantize_colors = FALSE; + /* We set these in case application only sets quantize_colors. */ + cinfo->dither_mode = JDITHER_FS; +#ifdef QUANT_2PASS_SUPPORTED + cinfo->two_pass_quantize = TRUE; +#else + cinfo->two_pass_quantize = FALSE; +#endif + cinfo->desired_number_of_colors = 256; + cinfo->colormap = NULL; + /* Initialize for no mode change in buffered-image mode. */ + cinfo->enable_1pass_quant = FALSE; + cinfo->enable_external_quant = FALSE; + cinfo->enable_2pass_quant = FALSE; +} + + +/* + * Decompression startup: read start of JPEG datastream to see what's there. + * Need only initialize JPEG object and supply a data source before calling. + * + * This routine will read as far as the first SOS marker (ie, actual start of + * compressed data), and will save all tables and parameters in the JPEG + * object. It will also initialize the decompression parameters to default + * values, and finally return JPEG_HEADER_OK. On return, the application may + * adjust the decompression parameters and then call jpeg_start_decompress. + * (Or, if the application only wanted to determine the image parameters, + * the data need not be decompressed. In that case, call jpeg_abort or + * jpeg_destroy to release any temporary space.) + * If an abbreviated (tables only) datastream is presented, the routine will + * return JPEG_HEADER_TABLES_ONLY upon reaching EOI. The application may then + * re-use the JPEG object to read the abbreviated image datastream(s). + * It is unnecessary (but OK) to call jpeg_abort in this case. + * The JPEG_SUSPENDED return code only occurs if the data source module + * requests suspension of the decompressor. In this case the application + * should load more source data and then re-call jpeg_read_header to resume + * processing. + * If a non-suspending data source is used and require_image is TRUE, then the + * return code need not be inspected since only JPEG_HEADER_OK is possible. + * + * This routine is now just a front end to jpeg_consume_input, with some + * extra error checking. + */ + +GLOBAL(int) +jpeg_read_header (j_decompress_ptr cinfo, boolean require_image) +{ + int retcode; + + if (cinfo->global_state != DSTATE_START && + cinfo->global_state != DSTATE_INHEADER) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + + retcode = jpeg_consume_input(cinfo); + + switch (retcode) { + case JPEG_REACHED_SOS: + retcode = JPEG_HEADER_OK; + break; + case JPEG_REACHED_EOI: + if (require_image) /* Complain if application wanted an image */ + ERREXIT(cinfo, JERR_NO_IMAGE); + /* Reset to start state; it would be safer to require the application to + * call jpeg_abort, but we can't change it now for compatibility reasons. + * A side effect is to free any temporary memory (there shouldn't be any). + */ + jpeg_abort((j_common_ptr) cinfo); /* sets state = DSTATE_START */ + retcode = JPEG_HEADER_TABLES_ONLY; + break; + case JPEG_SUSPENDED: + /* no work */ + break; + } + + return retcode; +} + + +/* + * Consume data in advance of what the decompressor requires. + * This can be called at any time once the decompressor object has + * been created and a data source has been set up. + * + * This routine is essentially a state machine that handles a couple + * of critical state-transition actions, namely initial setup and + * transition from header scanning to ready-for-start_decompress. + * All the actual input is done via the input controller's consume_input + * method. + */ + +GLOBAL(int) +jpeg_consume_input (j_decompress_ptr cinfo) +{ + int retcode = JPEG_SUSPENDED; + + /* NB: every possible DSTATE value should be listed in this switch */ + switch (cinfo->global_state) { + case DSTATE_START: + /* Start-of-datastream actions: reset appropriate modules */ + (*cinfo->inputctl->reset_input_controller) (cinfo); + /* Initialize application's data source module */ + (*cinfo->src->init_source) (cinfo); + cinfo->global_state = DSTATE_INHEADER; + /*FALLTHROUGH*/ + case DSTATE_INHEADER: + retcode = (*cinfo->inputctl->consume_input) (cinfo); + if (retcode == JPEG_REACHED_SOS) { /* Found SOS, prepare to decompress */ + /* Set up default parameters based on header data */ + default_decompress_parms(cinfo); + /* Set global state: ready for start_decompress */ + cinfo->global_state = DSTATE_READY; + } + break; + case DSTATE_READY: + /* Can't advance past first SOS until start_decompress is called */ + retcode = JPEG_REACHED_SOS; + break; + case DSTATE_PRELOAD: + case DSTATE_PRESCAN: + case DSTATE_SCANNING: + case DSTATE_RAW_OK: + case DSTATE_BUFIMAGE: + case DSTATE_BUFPOST: + case DSTATE_STOPPING: + retcode = (*cinfo->inputctl->consume_input) (cinfo); + break; + default: + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + } + return retcode; +} + + +/* + * Have we finished reading the input file? + */ + +GLOBAL(boolean) +jpeg_input_complete (j_decompress_ptr cinfo) +{ + /* Check for valid jpeg object */ + if (cinfo->global_state < DSTATE_START || + cinfo->global_state > DSTATE_STOPPING) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + return cinfo->inputctl->eoi_reached; +} + + +/* + * Is there more than one scan? + */ + +GLOBAL(boolean) +jpeg_has_multiple_scans (j_decompress_ptr cinfo) +{ + /* Only valid after jpeg_read_header completes */ + if (cinfo->global_state < DSTATE_READY || + cinfo->global_state > DSTATE_STOPPING) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + return cinfo->inputctl->has_multiple_scans; +} + + +/* + * Finish JPEG decompression. + * + * This will normally just verify the file trailer and release temp storage. + * + * Returns FALSE if suspended. The return value need be inspected only if + * a suspending data source is used. + */ + +GLOBAL(boolean) +jpeg_finish_decompress (j_decompress_ptr cinfo) +{ + if ((cinfo->global_state == DSTATE_SCANNING || + cinfo->global_state == DSTATE_RAW_OK) && ! cinfo->buffered_image) { + /* Terminate final pass of non-buffered mode */ + if (cinfo->output_scanline < cinfo->output_height) + ERREXIT(cinfo, JERR_TOO_LITTLE_DATA); + (*cinfo->master->finish_output_pass) (cinfo); + cinfo->global_state = DSTATE_STOPPING; + } else if (cinfo->global_state == DSTATE_BUFIMAGE) { + /* Finishing after a buffered-image operation */ + cinfo->global_state = DSTATE_STOPPING; + } else if (cinfo->global_state != DSTATE_STOPPING) { + /* STOPPING = repeat call after a suspension, anything else is error */ + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + } + /* Read until EOI */ + while (! cinfo->inputctl->eoi_reached) { + if ((*cinfo->inputctl->consume_input) (cinfo) == JPEG_SUSPENDED) + return FALSE; /* Suspend, come back later */ + } + /* Do final cleanup */ + (*cinfo->src->term_source) (cinfo); + /* We can use jpeg_abort to release memory and reset global_state */ + jpeg_abort((j_common_ptr) cinfo); + return TRUE; +} diff --git a/dcmjpeg/libijg16/jdapistd.c b/dcmjpeg/libijg16/jdapistd.c new file mode 100644 index 00000000..961eb438 --- /dev/null +++ b/dcmjpeg/libijg16/jdapistd.c @@ -0,0 +1,275 @@ +/* + * jdapistd.c + * + * Copyright (C) 1994-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains application interface code for the decompression half + * of the JPEG library. These are the "standard" API routines that are + * used in the normal full-decompression case. They are not used by a + * transcoding-only application. Note that if an application links in + * jpeg_start_decompress, it will end up linking in the entire decompressor. + * We thus must separate this file from jdapimin.c to avoid linking the + * whole decompression library into a transcoder. + */ + +#define JPEG_INTERNALS +#include "jinclude16.h" +#include "jpeglib16.h" + + +/* Forward declarations */ +LOCAL(boolean) output_pass_setup JPP((j_decompress_ptr cinfo)); + + +/* + * Decompression initialization. + * jpeg_read_header must be completed before calling this. + * + * If a multipass operating mode was selected, this will do all but the + * last pass, and thus may take a great deal of time. + * + * Returns FALSE if suspended. The return value need be inspected only if + * a suspending data source is used. + */ + +GLOBAL(boolean) +jpeg_start_decompress (j_decompress_ptr cinfo) +{ + if (cinfo->global_state == DSTATE_READY) { + /* First call: initialize master control, select active modules */ + jinit_master_decompress(cinfo); + if (cinfo->buffered_image) { + /* No more work here; expecting jpeg_start_output next */ + cinfo->global_state = DSTATE_BUFIMAGE; + return TRUE; + } + cinfo->global_state = DSTATE_PRELOAD; + } + if (cinfo->global_state == DSTATE_PRELOAD) { + /* If file has multiple scans, absorb them all into the coef buffer */ + if (cinfo->inputctl->has_multiple_scans) { +#ifdef D_MULTISCAN_FILES_SUPPORTED + for (;;) { + int retcode; + /* Call progress monitor hook if present */ + if (cinfo->progress != NULL) + (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); + /* Absorb some more input */ + retcode = (*cinfo->inputctl->consume_input) (cinfo); + if (retcode == JPEG_SUSPENDED) + return FALSE; + if (retcode == JPEG_REACHED_EOI) + break; + /* Advance progress counter if appropriate */ + if (cinfo->progress != NULL && + (retcode == JPEG_ROW_COMPLETED || retcode == JPEG_REACHED_SOS)) { + if (++cinfo->progress->pass_counter >= cinfo->progress->pass_limit) { + /* jdmaster underestimated number of scans; ratchet up one scan */ + cinfo->progress->pass_limit += (long) cinfo->total_iMCU_rows; + } + } + } +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif /* D_MULTISCAN_FILES_SUPPORTED */ + } + cinfo->output_scan_number = cinfo->input_scan_number; + } else if (cinfo->global_state != DSTATE_PRESCAN) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + /* Perform any dummy output passes, and set up for the final pass */ + return output_pass_setup(cinfo); +} + + +/* + * Set up for an output pass, and perform any dummy pass(es) needed. + * Common subroutine for jpeg_start_decompress and jpeg_start_output. + * Entry: global_state = DSTATE_PRESCAN only if previously suspended. + * Exit: If done, returns TRUE and sets global_state for proper output mode. + * If suspended, returns FALSE and sets global_state = DSTATE_PRESCAN. + */ + +LOCAL(boolean) +output_pass_setup (j_decompress_ptr cinfo) +{ + if (cinfo->global_state != DSTATE_PRESCAN) { + /* First call: do pass setup */ + (*cinfo->master->prepare_for_output_pass) (cinfo); + cinfo->output_scanline = 0; + cinfo->global_state = DSTATE_PRESCAN; + } + /* Loop over any required dummy passes */ + while (cinfo->master->is_dummy_pass) { +#ifdef QUANT_2PASS_SUPPORTED + /* Crank through the dummy pass */ + while (cinfo->output_scanline < cinfo->output_height) { + JDIMENSION last_scanline; + /* Call progress monitor hook if present */ + if (cinfo->progress != NULL) { + cinfo->progress->pass_counter = (long) cinfo->output_scanline; + cinfo->progress->pass_limit = (long) cinfo->output_height; + (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); + } + /* Process some data */ + last_scanline = cinfo->output_scanline; + (*cinfo->main->process_data) (cinfo, (JSAMPARRAY) NULL, + &cinfo->output_scanline, (JDIMENSION) 0); + if (cinfo->output_scanline == last_scanline) + return FALSE; /* No progress made, must suspend */ + } + /* Finish up dummy pass, and set up for another one */ + (*cinfo->master->finish_output_pass) (cinfo); + (*cinfo->master->prepare_for_output_pass) (cinfo); + cinfo->output_scanline = 0; +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif /* QUANT_2PASS_SUPPORTED */ + } + /* Ready for application to drive output pass through + * jpeg_read_scanlines or jpeg_read_raw_data. + */ + cinfo->global_state = cinfo->raw_data_out ? DSTATE_RAW_OK : DSTATE_SCANNING; + return TRUE; +} + + +/* + * Read some scanlines of data from the JPEG decompressor. + * + * The return value will be the number of lines actually read. + * This may be less than the number requested in several cases, + * including bottom of image, data source suspension, and operating + * modes that emit multiple scanlines at a time. + * + * Note: we warn about excess calls to jpeg_read_scanlines() since + * this likely signals an application programmer error. However, + * an oversize buffer (max_lines > scanlines remaining) is not an error. + */ + +GLOBAL(JDIMENSION) +jpeg_read_scanlines (j_decompress_ptr cinfo, JSAMPARRAY scanlines, + JDIMENSION max_lines) +{ + JDIMENSION row_ctr; + + if (cinfo->global_state != DSTATE_SCANNING) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + if (cinfo->output_scanline >= cinfo->output_height) { + WARNMS(cinfo, JWRN_TOO_MUCH_DATA); + return 0; + } + + /* Call progress monitor hook if present */ + if (cinfo->progress != NULL) { + cinfo->progress->pass_counter = (long) cinfo->output_scanline; + cinfo->progress->pass_limit = (long) cinfo->output_height; + (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); + } + + /* Process some data */ + row_ctr = 0; + (*cinfo->main->process_data) (cinfo, scanlines, &row_ctr, max_lines); + cinfo->output_scanline += row_ctr; + return row_ctr; +} + + +/* + * Alternate entry point to read raw data. + * Processes exactly one iMCU row per call, unless suspended. + */ + +GLOBAL(JDIMENSION) +jpeg_read_raw_data (j_decompress_ptr cinfo, JSAMPIMAGE data, + JDIMENSION max_lines) +{ + JDIMENSION lines_per_iMCU_row; + + if (cinfo->global_state != DSTATE_RAW_OK) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + if (cinfo->output_scanline >= cinfo->output_height) { + WARNMS(cinfo, JWRN_TOO_MUCH_DATA); + return 0; + } + + /* Call progress monitor hook if present */ + if (cinfo->progress != NULL) { + cinfo->progress->pass_counter = (long) cinfo->output_scanline; + cinfo->progress->pass_limit = (long) cinfo->output_height; + (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); + } + + /* Verify that at least one iMCU row can be returned. */ + lines_per_iMCU_row = (JDIMENSION)(cinfo->max_v_samp_factor * cinfo->min_codec_data_unit); + if (max_lines < lines_per_iMCU_row) + ERREXIT(cinfo, JERR_BUFFER_SIZE); + + /* Decompress directly into user's buffer. */ + if (! (*cinfo->codec->decompress_data) (cinfo, data)) + return 0; /* suspension forced, can do nothing more */ + + /* OK, we processed one iMCU row. */ + cinfo->output_scanline += lines_per_iMCU_row; + return lines_per_iMCU_row; +} + + +/* Additional entry points for buffered-image mode. */ + +#ifdef D_MULTISCAN_FILES_SUPPORTED + +/* + * Initialize for an output pass in buffered-image mode. + */ + +GLOBAL(boolean) +jpeg_start_output (j_decompress_ptr cinfo, int scan_number) +{ + if (cinfo->global_state != DSTATE_BUFIMAGE && + cinfo->global_state != DSTATE_PRESCAN) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + /* Limit scan number to valid range */ + if (scan_number <= 0) + scan_number = 1; + if (cinfo->inputctl->eoi_reached && + scan_number > cinfo->input_scan_number) + scan_number = cinfo->input_scan_number; + cinfo->output_scan_number = scan_number; + /* Perform any dummy output passes, and set up for the real pass */ + return output_pass_setup(cinfo); +} + + +/* + * Finish up after an output pass in buffered-image mode. + * + * Returns FALSE if suspended. The return value need be inspected only if + * a suspending data source is used. + */ + +GLOBAL(boolean) +jpeg_finish_output (j_decompress_ptr cinfo) +{ + if ((cinfo->global_state == DSTATE_SCANNING || + cinfo->global_state == DSTATE_RAW_OK) && cinfo->buffered_image) { + /* Terminate this pass. */ + /* We do not require the whole pass to have been completed. */ + (*cinfo->master->finish_output_pass) (cinfo); + cinfo->global_state = DSTATE_BUFPOST; + } else if (cinfo->global_state != DSTATE_BUFPOST) { + /* BUFPOST = repeat call after a suspension, anything else is error */ + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + } + /* Read markers looking for SOS or EOI */ + while (cinfo->input_scan_number <= cinfo->output_scan_number && + ! cinfo->inputctl->eoi_reached) { + if ((*cinfo->inputctl->consume_input) (cinfo) == JPEG_SUSPENDED) + return FALSE; /* Suspend, come back later */ + } + cinfo->global_state = DSTATE_BUFIMAGE; + return TRUE; +} + +#endif /* D_MULTISCAN_FILES_SUPPORTED */ diff --git a/dcmjpeg/libijg16/jdarith.c b/dcmjpeg/libijg16/jdarith.c new file mode 100644 index 00000000..8bacb66a --- /dev/null +++ b/dcmjpeg/libijg16/jdarith.c @@ -0,0 +1,26 @@ +/* + * jdarith.c + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file holds place for arithmetic entropy decoding routines. + */ + +#define JPEG_INTERNALS +#include "jinclude16.h" +#include "jpeglib16.h" + + +/* + * Module initialization routine for arithmetic entropy decoding. + */ +GLOBAL(void) +jinit_arith_decoder (j_decompress_ptr cinfo); + +GLOBAL(void) +jinit_arith_decoder (j_decompress_ptr cinfo) +{ + ERREXIT(cinfo, JERR_ARITH_NOTIMPL); +} diff --git a/dcmjpeg/libijg16/jdatadst.c b/dcmjpeg/libijg16/jdatadst.c new file mode 100644 index 00000000..d429d07c --- /dev/null +++ b/dcmjpeg/libijg16/jdatadst.c @@ -0,0 +1,151 @@ +/* + * jdatadst.c + * + * Copyright (C) 1994-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains compression data destination routines for the case of + * emitting JPEG data to a file (or any stdio stream). While these routines + * are sufficient for most applications, some will want to use a different + * destination manager. + * IMPORTANT: we assume that fwrite() will correctly transcribe an array of + * JOCTETs into 8-bit-wide elements on external storage. If char is wider + * than 8 bits on your machine, you may need to do some tweaking. + */ + +/* this is not a core library module, so it doesn't define JPEG_INTERNALS */ +#include "jinclude16.h" +#include "jpeglib16.h" +#include "jerror16.h" + + +/* Expanded data destination object for stdio output */ + +typedef struct { + struct jpeg_destination_mgr pub; /* public fields */ + + FILE * outfile; /* target stream */ + JOCTET * buffer; /* start of buffer */ +} my_destination_mgr; + +typedef my_destination_mgr * my_dest_ptr; + +#define OUTPUT_BUF_SIZE 4096 /* choose an efficiently fwrite'able size */ + + +/* + * Initialize destination --- called by jpeg_start_compress + * before any data is actually written. + */ + +METHODDEF(void) +init_destination (j_compress_ptr cinfo) +{ + my_dest_ptr dest = (my_dest_ptr) cinfo->dest; + + /* Allocate the output buffer --- it will be released when done with image */ + dest->buffer = (JOCTET *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + OUTPUT_BUF_SIZE * SIZEOF(JOCTET)); + + dest->pub.next_output_byte = dest->buffer; + dest->pub.free_in_buffer = OUTPUT_BUF_SIZE; +} + + +/* + * Empty the output buffer --- called whenever buffer fills up. + * + * In typical applications, this should write the entire output buffer + * (ignoring the current state of next_output_byte & free_in_buffer), + * reset the pointer & count to the start of the buffer, and return TRUE + * indicating that the buffer has been dumped. + * + * In applications that need to be able to suspend compression due to output + * overrun, a FALSE return indicates that the buffer cannot be emptied now. + * In this situation, the compressor will return to its caller (possibly with + * an indication that it has not accepted all the supplied scanlines). The + * application should resume compression after it has made more room in the + * output buffer. Note that there are substantial restrictions on the use of + * suspension --- see the documentation. + * + * When suspending, the compressor will back up to a convenient restart point + * (typically the start of the current MCU). next_output_byte & free_in_buffer + * indicate where the restart point will be if the current call returns FALSE. + * Data beyond this point will be regenerated after resumption, so do not + * write it out when emptying the buffer externally. + */ + +METHODDEF(boolean) +empty_output_buffer (j_compress_ptr cinfo) +{ + my_dest_ptr dest = (my_dest_ptr) cinfo->dest; + + if (JFWRITE(dest->outfile, dest->buffer, OUTPUT_BUF_SIZE) != + (size_t) OUTPUT_BUF_SIZE) + ERREXIT(cinfo, JERR_FILE_WRITE); + + dest->pub.next_output_byte = dest->buffer; + dest->pub.free_in_buffer = OUTPUT_BUF_SIZE; + + return TRUE; +} + + +/* + * Terminate destination --- called by jpeg_finish_compress + * after all data has been written. Usually needs to flush buffer. + * + * NB: *not* called by jpeg_abort or jpeg_destroy; surrounding + * application must deal with any cleanup that should happen even + * for error exit. + */ + +METHODDEF(void) +term_destination (j_compress_ptr cinfo) +{ + my_dest_ptr dest = (my_dest_ptr) cinfo->dest; + size_t datacount = OUTPUT_BUF_SIZE - dest->pub.free_in_buffer; + + /* Write any data remaining in the buffer */ + if (datacount > 0) { + if (JFWRITE(dest->outfile, dest->buffer, datacount) != datacount) + ERREXIT(cinfo, JERR_FILE_WRITE); + } + fflush(dest->outfile); + /* Make sure we wrote the output file OK */ + if (ferror(dest->outfile)) + ERREXIT(cinfo, JERR_FILE_WRITE); +} + + +/* + * Prepare for output to a stdio stream. + * The caller must have already opened the stream, and is responsible + * for closing it after finishing compression. + */ + +GLOBAL(void) +jpeg_stdio_dest (j_compress_ptr cinfo, FILE * outfile) +{ + my_dest_ptr dest; + + /* The destination object is made permanent so that multiple JPEG images + * can be written to the same file without re-executing jpeg_stdio_dest. + * This makes it dangerous to use this manager and a different destination + * manager serially with the same JPEG object, because their private object + * sizes may be different. Caveat programmer. + */ + if (cinfo->dest == NULL) { /* first time for this JPEG object? */ + cinfo->dest = (struct jpeg_destination_mgr *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, + SIZEOF(my_destination_mgr)); + } + + dest = (my_dest_ptr) cinfo->dest; + dest->pub.init_destination = init_destination; + dest->pub.empty_output_buffer = empty_output_buffer; + dest->pub.term_destination = term_destination; + dest->outfile = outfile; +} diff --git a/dcmjpeg/libijg16/jdatasrc.c b/dcmjpeg/libijg16/jdatasrc.c new file mode 100644 index 00000000..99f8d13a --- /dev/null +++ b/dcmjpeg/libijg16/jdatasrc.c @@ -0,0 +1,212 @@ +/* + * jdatasrc.c + * + * Copyright (C) 1994-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains decompression data source routines for the case of + * reading JPEG data from a file (or any stdio stream). While these routines + * are sufficient for most applications, some will want to use a different + * source manager. + * IMPORTANT: we assume that fread() will correctly transcribe an array of + * JOCTETs from 8-bit-wide elements on external storage. If char is wider + * than 8 bits on your machine, you may need to do some tweaking. + */ + +/* this is not a core library module, so it doesn't define JPEG_INTERNALS */ +#include "jinclude16.h" +#include "jpeglib16.h" +#include "jerror16.h" + + +/* Expanded data source object for stdio input */ + +typedef struct { + struct jpeg_source_mgr pub; /* public fields */ + + FILE * infile; /* source stream */ + JOCTET * buffer; /* start of buffer */ + boolean start_of_file; /* have we gotten any data yet? */ +} my_source_mgr; + +typedef my_source_mgr * my_src_ptr; + +#define INPUT_BUF_SIZE 4096 /* choose an efficiently fread'able size */ + + +/* + * Initialize source --- called by jpeg_read_header + * before any data is actually read. + */ + +METHODDEF(void) +init_source (j_decompress_ptr cinfo) +{ + my_src_ptr src = (my_src_ptr) cinfo->src; + + /* We reset the empty-input-file flag for each image, + * but we don't clear the input buffer. + * This is correct behavior for reading a series of images from one source. + */ + src->start_of_file = TRUE; +} + + +/* + * Fill the input buffer --- called whenever buffer is emptied. + * + * In typical applications, this should read fresh data into the buffer + * (ignoring the current state of next_input_byte & bytes_in_buffer), + * reset the pointer & count to the start of the buffer, and return TRUE + * indicating that the buffer has been reloaded. It is not necessary to + * fill the buffer entirely, only to obtain at least one more byte. + * + * There is no such thing as an EOF return. If the end of the file has been + * reached, the routine has a choice of ERREXIT() or inserting fake data into + * the buffer. In most cases, generating a warning message and inserting a + * fake EOI marker is the best course of action --- this will allow the + * decompressor to output however much of the image is there. However, + * the resulting error message is misleading if the real problem is an empty + * input file, so we handle that case specially. + * + * In applications that need to be able to suspend compression due to input + * not being available yet, a FALSE return indicates that no more data can be + * obtained right now, but more may be forthcoming later. In this situation, + * the decompressor will return to its caller (with an indication of the + * number of scanlines it has read, if any). The application should resume + * decompression after it has loaded more data into the input buffer. Note + * that there are substantial restrictions on the use of suspension --- see + * the documentation. + * + * When suspending, the decompressor will back up to a convenient restart point + * (typically the start of the current MCU). next_input_byte & bytes_in_buffer + * indicate where the restart point will be if the current call returns FALSE. + * Data beyond this point must be rescanned after resumption, so move it to + * the front of the buffer rather than discarding it. + */ + +METHODDEF(boolean) +fill_input_buffer (j_decompress_ptr cinfo) +{ + my_src_ptr src = (my_src_ptr) cinfo->src; + size_t nbytes; + + nbytes = JFREAD(src->infile, src->buffer, INPUT_BUF_SIZE); + + if (nbytes <= 0) { + if (src->start_of_file) /* Treat empty input file as fatal error */ + ERREXIT(cinfo, JERR_INPUT_EMPTY); + WARNMS(cinfo, JWRN_JPEG_EOF); + /* Insert a fake EOI marker */ + src->buffer[0] = (JOCTET) 0xFF; + src->buffer[1] = (JOCTET) JPEG_EOI; + nbytes = 2; + } + + src->pub.next_input_byte = src->buffer; + src->pub.bytes_in_buffer = nbytes; + src->start_of_file = FALSE; + + return TRUE; +} + + +/* + * Skip data --- used to skip over a potentially large amount of + * uninteresting data (such as an APPn marker). + * + * Writers of suspendable-input applications must note that skip_input_data + * is not granted the right to give a suspension return. If the skip extends + * beyond the data currently in the buffer, the buffer can be marked empty so + * that the next read will cause a fill_input_buffer call that can suspend. + * Arranging for additional bytes to be discarded before reloading the input + * buffer is the application writer's problem. + */ + +METHODDEF(void) +skip_input_data (j_decompress_ptr cinfo, long num_bytes) +{ + my_src_ptr src = (my_src_ptr) cinfo->src; + + /* Just a dumb implementation for now. Could use fseek() except + * it doesn't work on pipes. Not clear that being smart is worth + * any trouble anyway --- large skips are infrequent. + */ + if (num_bytes > 0) { + while (num_bytes > (long) src->pub.bytes_in_buffer) { + num_bytes -= (long) src->pub.bytes_in_buffer; + (void) fill_input_buffer(cinfo); + /* note we assume that fill_input_buffer will never return FALSE, + * so suspension need not be handled. + */ + } + src->pub.next_input_byte += (size_t) num_bytes; + src->pub.bytes_in_buffer -= (size_t) num_bytes; + } +} + + +/* + * An additional method that can be provided by data source modules is the + * resync_to_restart method for error recovery in the presence of RST markers. + * For the moment, this source module just uses the default resync method + * provided by the JPEG library. That method assumes that no backtracking + * is possible. + */ + + +/* + * Terminate source --- called by jpeg_finish_decompress + * after all data has been read. Often a no-op. + * + * NB: *not* called by jpeg_abort or jpeg_destroy; surrounding + * application must deal with any cleanup that should happen even + * for error exit. + */ + +METHODDEF(void) +term_source (j_decompress_ptr cinfo) +{ + /* no work necessary here */ +} + + +/* + * Prepare for input from a stdio stream. + * The caller must have already opened the stream, and is responsible + * for closing it after finishing decompression. + */ + +GLOBAL(void) +jpeg_stdio_src (j_decompress_ptr cinfo, FILE * infile) +{ + my_src_ptr src; + + /* The source object and input buffer are made permanent so that a series + * of JPEG images can be read from the same file by calling jpeg_stdio_src + * only before the first one. (If we discarded the buffer at the end of + * one image, we'd likely lose the start of the next one.) + * This makes it unsafe to use this manager and a different source + * manager serially with the same JPEG object. Caveat programmer. + */ + if (cinfo->src == NULL) { /* first time for this JPEG object? */ + cinfo->src = (struct jpeg_source_mgr *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, + SIZEOF(my_source_mgr)); + src = (my_src_ptr) cinfo->src; + src->buffer = (JOCTET *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, + INPUT_BUF_SIZE * SIZEOF(JOCTET)); + } + + src = (my_src_ptr) cinfo->src; + src->pub.init_source = init_source; + src->pub.fill_input_buffer = fill_input_buffer; + src->pub.skip_input_data = skip_input_data; + src->pub.resync_to_restart = jpeg_resync_to_restart; /* use default method */ + src->pub.term_source = term_source; + src->infile = infile; + src->pub.bytes_in_buffer = 0; /* forces fill_input_buffer on first read */ + src->pub.next_input_byte = NULL; /* until buffer loaded */ +} diff --git a/dcmjpeg/libijg16/jdcoefct.c b/dcmjpeg/libijg16/jdcoefct.c new file mode 100644 index 00000000..fe0048c0 --- /dev/null +++ b/dcmjpeg/libijg16/jdcoefct.c @@ -0,0 +1,743 @@ +/* + * jdcoefct.c + * + * Copyright (C) 1994-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains the coefficient buffer controller for decompression. + * This controller is the top level of the lossy JPEG decompressor proper. + * The coefficient buffer lies between entropy decoding and inverse-DCT steps. + * + * In buffered-image mode, this controller is the interface between + * input-oriented processing and output-oriented processing. + * Also, the input side (only) is used when reading a file for transcoding. + */ + +#define JPEG_INTERNALS +#include "jinclude16.h" +#include "jpeglib16.h" +#include "jlossy16.h" + +/* Block smoothing is only applicable for progressive JPEG, so: */ +#ifndef D_PROGRESSIVE_SUPPORTED +#undef BLOCK_SMOOTHING_SUPPORTED +#endif + +/* Private buffer controller object */ + +typedef struct { + /* These variables keep track of the current location of the input side. */ + /* cinfo->input_iMCU_row is also used for this. */ + JDIMENSION MCU_ctr; /* counts MCUs processed in current row */ + int MCU_vert_offset; /* counts MCU rows within iMCU row */ + int MCU_rows_per_iMCU_row; /* number of such rows needed */ + + /* The output side's location is represented by cinfo->output_iMCU_row. */ + + /* In single-pass modes, it's sufficient to buffer just one MCU. + * We allocate a workspace of D_MAX_DATA_UNITS_IN_MCU coefficient blocks, + * and let the entropy decoder write into that workspace each time. + * (On 80x86, the workspace is FAR even though it's not really very big; + * this is to keep the module interfaces unchanged when a large coefficient + * buffer is necessary.) + * In multi-pass modes, this array points to the current MCU's blocks + * within the virtual arrays; it is used only by the input side. + */ + JBLOCKROW MCU_buffer[D_MAX_DATA_UNITS_IN_MCU]; + +#ifdef D_MULTISCAN_FILES_SUPPORTED + /* In multi-pass modes, we need a virtual block array for each component. */ + jvirt_barray_ptr whole_image[MAX_COMPONENTS]; +#endif + +#ifdef BLOCK_SMOOTHING_SUPPORTED + /* When doing block smoothing, we latch coefficient Al values here */ + int * coef_bits_latch; +#define SAVED_COEFS 6 /* we save coef_bits[0..5] */ +#endif +} d_coef_controller; + +typedef d_coef_controller * d_coef_ptr; + +/* Forward declarations */ +METHODDEF(int) decompress_onepass + JPP((j_decompress_ptr cinfo, JSAMPIMAGE output_buf)); +#ifdef D_MULTISCAN_FILES_SUPPORTED +METHODDEF(int) decompress_data + JPP((j_decompress_ptr cinfo, JSAMPIMAGE output_buf)); +#endif +#ifdef BLOCK_SMOOTHING_SUPPORTED +LOCAL(boolean) smoothing_ok JPP((j_decompress_ptr cinfo)); +METHODDEF(int) decompress_smooth_data + JPP((j_decompress_ptr cinfo, JSAMPIMAGE output_buf)); +#endif + + +LOCAL(void) +start_iMCU_row (j_decompress_ptr cinfo) +/* Reset within-iMCU-row counters for a new row (input side) */ +{ + j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec; + d_coef_ptr coef = (d_coef_ptr) lossyd->coef_private; + + /* In an interleaved scan, an MCU row is the same as an iMCU row. + * In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows. + * But at the bottom of the image, process only what's left. + */ + if (cinfo->comps_in_scan > 1) { + coef->MCU_rows_per_iMCU_row = 1; + } else { + if (cinfo->input_iMCU_row < (cinfo->total_iMCU_rows-1)) + coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->v_samp_factor; + else + coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->last_row_height; + } + + coef->MCU_ctr = 0; + coef->MCU_vert_offset = 0; +} + + +/* + * Initialize for an input processing pass. + */ + +METHODDEF(void) +start_input_pass (j_decompress_ptr cinfo) +{ + cinfo->input_iMCU_row = 0; + start_iMCU_row(cinfo); +} + + +/* + * Initialize for an output processing pass. + */ + +METHODDEF(void) +start_output_pass (j_decompress_ptr cinfo) +{ +#ifdef BLOCK_SMOOTHING_SUPPORTED + j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec; + /* d_coef_ptr coef = (d_coef_ptr) lossyd->coef_private; */ + + /* If multipass, check to see whether to use block smoothing on this pass */ + if (lossyd->coef_arrays != NULL) { + if (cinfo->do_block_smoothing && smoothing_ok(cinfo)) + lossyd->pub.decompress_data = decompress_smooth_data; + else + lossyd->pub.decompress_data = decompress_data; + } +#endif + cinfo->output_iMCU_row = 0; +} + + +/* + * Decompress and return some data in the single-pass case. + * Always attempts to emit one fully interleaved MCU row ("iMCU" row). + * Input and output must run in lockstep since we have only a one-MCU buffer. + * Return value is JPEG_ROW_COMPLETED, JPEG_SCAN_COMPLETED, or JPEG_SUSPENDED. + * + * NB: output_buf contains a plane for each component in image, + * which we index according to the component's SOF position. + */ + +METHODDEF(int) +decompress_onepass (j_decompress_ptr cinfo, JSAMPIMAGE output_buf) +{ + j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec; + d_coef_ptr coef = (d_coef_ptr) lossyd->coef_private; + JDIMENSION MCU_col_num; /* index of current MCU within row */ + JDIMENSION last_MCU_col = cinfo->MCUs_per_row - 1; + JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; + int blkn, ci, xindex, yindex, yoffset, useful_width; + JSAMPARRAY output_ptr; + JDIMENSION start_col, output_col; + jpeg_component_info *compptr; + inverse_DCT_method_ptr inverse_DCT; + + /* Loop to process as much as one whole iMCU row */ + for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row; + yoffset++) { + for (MCU_col_num = coef->MCU_ctr; MCU_col_num <= last_MCU_col; + MCU_col_num++) { + /* Try to fetch an MCU. Entropy decoder expects buffer to be zeroed. */ + jzero_far((void FAR *) coef->MCU_buffer[0], + (size_t)cinfo->data_units_in_MCU * SIZEOF(JBLOCK)); + if (! (*lossyd->entropy_decode_mcu) (cinfo, coef->MCU_buffer)) { + /* Suspension forced; update state counters and exit */ + coef->MCU_vert_offset = yoffset; + coef->MCU_ctr = MCU_col_num; + return JPEG_SUSPENDED; + } + /* Determine where data should go in output_buf and do the IDCT thing. + * We skip dummy blocks at the right and bottom edges (but blkn gets + * incremented past them!). Note the inner loop relies on having + * allocated the MCU_buffer[] blocks sequentially. + */ + blkn = 0; /* index of current DCT block within MCU */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + /* Don't bother to IDCT an uninteresting component. */ + if (! compptr->component_needed) { + blkn += compptr->MCU_data_units; + continue; + } + inverse_DCT = lossyd->inverse_DCT[compptr->component_index]; + useful_width = (MCU_col_num < last_MCU_col) ? compptr->MCU_width + : compptr->last_col_width; + output_ptr = output_buf[compptr->component_index] + + yoffset * compptr->codec_data_unit; + start_col = MCU_col_num * (JDIMENSION)compptr->MCU_sample_width; + for (yindex = 0; yindex < compptr->MCU_height; yindex++) { + if (cinfo->input_iMCU_row < last_iMCU_row || + yoffset+yindex < compptr->last_row_height) { + output_col = start_col; + for (xindex = 0; xindex < useful_width; xindex++) { + (*inverse_DCT) (cinfo, compptr, + (JCOEFPTR) coef->MCU_buffer[blkn+xindex], + output_ptr, output_col); + output_col += (JDIMENSION)compptr->codec_data_unit; + } + } + blkn += compptr->MCU_width; + output_ptr += compptr->codec_data_unit; + } + } + } + /* Completed an MCU row, but perhaps not an iMCU row */ + coef->MCU_ctr = 0; + } + /* Completed the iMCU row, advance counters for next one */ + cinfo->output_iMCU_row++; + if (++(cinfo->input_iMCU_row) < cinfo->total_iMCU_rows) { + start_iMCU_row(cinfo); + return JPEG_ROW_COMPLETED; + } + /* Completed the scan */ + (*cinfo->inputctl->finish_input_pass) (cinfo); + return JPEG_SCAN_COMPLETED; +} + + +/* + * Dummy consume-input routine for single-pass operation. + */ + +METHODDEF(int) +dummy_consume_data (j_decompress_ptr cinfo) +{ + return JPEG_SUSPENDED; /* Always indicate nothing was done */ +} + + +#ifdef D_MULTISCAN_FILES_SUPPORTED + +/* + * Consume input data and store it in the full-image coefficient buffer. + * We read as much as one fully interleaved MCU row ("iMCU" row) per call, + * ie, v_samp_factor block rows for each component in the scan. + * Return value is JPEG_ROW_COMPLETED, JPEG_SCAN_COMPLETED, or JPEG_SUSPENDED. + */ + +METHODDEF(int) +consume_data (j_decompress_ptr cinfo) +{ + j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec; + d_coef_ptr coef = (d_coef_ptr) lossyd->coef_private; + JDIMENSION MCU_col_num; /* index of current MCU within row */ + int blkn, ci, xindex, yindex, yoffset; + JDIMENSION start_col; + JBLOCKARRAY buffer[MAX_COMPS_IN_SCAN]; + JBLOCKROW buffer_ptr; + jpeg_component_info *compptr; + + /* Align the virtual buffers for the components used in this scan. */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + buffer[ci] = (*cinfo->mem->access_virt_barray) + ((j_common_ptr) cinfo, coef->whole_image[compptr->component_index], + cinfo->input_iMCU_row * (JDIMENSION)compptr->v_samp_factor, + (JDIMENSION) compptr->v_samp_factor, TRUE); + /* Note: entropy decoder expects buffer to be zeroed, + * but this is handled automatically by the memory manager + * because we requested a pre-zeroed array. + */ + } + + /* Loop to process one whole iMCU row */ + for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row; + yoffset++) { + for (MCU_col_num = coef->MCU_ctr; MCU_col_num < cinfo->MCUs_per_row; + MCU_col_num++) { + /* Construct list of pointers to DCT blocks belonging to this MCU */ + blkn = 0; /* index of current DCT block within MCU */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + start_col = MCU_col_num * (JDIMENSION)compptr->MCU_width; + for (yindex = 0; yindex < compptr->MCU_height; yindex++) { + buffer_ptr = buffer[ci][yindex+yoffset] + start_col; + for (xindex = 0; xindex < compptr->MCU_width; xindex++) { + coef->MCU_buffer[blkn++] = buffer_ptr++; + } + } + } + /* Try to fetch the MCU. */ + if (! (*lossyd->entropy_decode_mcu) (cinfo, coef->MCU_buffer)) { + /* Suspension forced; update state counters and exit */ + coef->MCU_vert_offset = yoffset; + coef->MCU_ctr = MCU_col_num; + return JPEG_SUSPENDED; + } + } + /* Completed an MCU row, but perhaps not an iMCU row */ + coef->MCU_ctr = 0; + } + /* Completed the iMCU row, advance counters for next one */ + if (++(cinfo->input_iMCU_row) < cinfo->total_iMCU_rows) { + start_iMCU_row(cinfo); + return JPEG_ROW_COMPLETED; + } + /* Completed the scan */ + (*cinfo->inputctl->finish_input_pass) (cinfo); + return JPEG_SCAN_COMPLETED; +} + + +/* + * Decompress and return some data in the multi-pass case. + * Always attempts to emit one fully interleaved MCU row ("iMCU" row). + * Return value is JPEG_ROW_COMPLETED, JPEG_SCAN_COMPLETED, or JPEG_SUSPENDED. + * + * NB: output_buf contains a plane for each component in image. + */ + +METHODDEF(int) +decompress_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf) +{ + j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec; + d_coef_ptr coef = (d_coef_ptr) lossyd->coef_private; + JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; + JDIMENSION block_num; + int ci, block_row, block_rows; + JBLOCKARRAY buffer; + JBLOCKROW buffer_ptr; + JSAMPARRAY output_ptr; + JDIMENSION output_col; + jpeg_component_info *compptr; + inverse_DCT_method_ptr inverse_DCT; + + /* Force some input to be done if we are getting ahead of the input. */ + while (cinfo->input_scan_number < cinfo->output_scan_number || + (cinfo->input_scan_number == cinfo->output_scan_number && + cinfo->input_iMCU_row <= cinfo->output_iMCU_row)) { + if ((*cinfo->inputctl->consume_input)(cinfo) == JPEG_SUSPENDED) + return JPEG_SUSPENDED; + } + + /* OK, output from the virtual arrays. */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + /* Don't bother to IDCT an uninteresting component. */ + if (! compptr->component_needed) + continue; + /* Align the virtual buffer for this component. */ + buffer = (*cinfo->mem->access_virt_barray) + ((j_common_ptr) cinfo, coef->whole_image[ci], + cinfo->output_iMCU_row * (JDIMENSION)compptr->v_samp_factor, + (JDIMENSION) compptr->v_samp_factor, FALSE); + /* Count non-dummy DCT block rows in this iMCU row. */ + if (cinfo->output_iMCU_row < last_iMCU_row) + block_rows = compptr->v_samp_factor; + else { + /* NB: can't use last_row_height here; it is input-side-dependent! */ + block_rows = (int)compptr->height_in_data_units % compptr->v_samp_factor; + if (block_rows == 0) block_rows = compptr->v_samp_factor; + } + inverse_DCT = lossyd->inverse_DCT[ci]; + output_ptr = output_buf[ci]; + /* Loop over all DCT blocks to be processed. */ + for (block_row = 0; block_row < block_rows; block_row++) { + buffer_ptr = buffer[block_row]; + output_col = 0; + for (block_num = 0; block_num < compptr->width_in_data_units; block_num++) { + (*inverse_DCT) (cinfo, compptr, (JCOEFPTR) buffer_ptr, + output_ptr, output_col); + buffer_ptr++; + output_col += (JDIMENSION)compptr->codec_data_unit; + } + output_ptr += compptr->codec_data_unit; + } + } + + if (++(cinfo->output_iMCU_row) < cinfo->total_iMCU_rows) + return JPEG_ROW_COMPLETED; + return JPEG_SCAN_COMPLETED; +} + +#endif /* D_MULTISCAN_FILES_SUPPORTED */ + + +#ifdef BLOCK_SMOOTHING_SUPPORTED + +/* + * This code applies interblock smoothing as described by section K.8 + * of the JPEG standard: the first 5 AC coefficients are estimated from + * the DC values of a DCT block and its 8 neighboring blocks. + * We apply smoothing only for progressive JPEG decoding, and only if + * the coefficients it can estimate are not yet known to full precision. + */ + +/* Natural-order array positions of the first 5 zigzag-order coefficients */ +#define Q01_POS 1 +#define Q10_POS 8 +#define Q20_POS 16 +#define Q11_POS 9 +#define Q02_POS 2 + +/* + * Determine whether block smoothing is applicable and safe. + * We also latch the current states of the coef_bits[] entries for the + * AC coefficients; otherwise, if the input side of the decompressor + * advances into a new scan, we might think the coefficients are known + * more accurately than they really are. + */ + +LOCAL(boolean) +smoothing_ok (j_decompress_ptr cinfo) +{ + j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec; + d_coef_ptr coef = (d_coef_ptr) lossyd->coef_private; + boolean smoothing_useful = FALSE; + int ci, coefi; + jpeg_component_info *compptr; + JQUANT_TBL * qtable; + int * coef_bits; + int * coef_bits_latch; + + if (! cinfo->process == JPROC_PROGRESSIVE || cinfo->coef_bits == NULL) + return FALSE; + + /* Allocate latch area if not already done */ + if (coef->coef_bits_latch == NULL) + coef->coef_bits_latch = (int *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (size_t)cinfo->num_components * + (SAVED_COEFS * SIZEOF(int))); + coef_bits_latch = coef->coef_bits_latch; + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + /* All components' quantization values must already be latched. */ + if ((qtable = compptr->quant_table) == NULL) + return FALSE; + /* Verify DC & first 5 AC quantizers are nonzero to avoid zero-divide. */ + if (qtable->quantval[0] == 0 || + qtable->quantval[Q01_POS] == 0 || + qtable->quantval[Q10_POS] == 0 || + qtable->quantval[Q20_POS] == 0 || + qtable->quantval[Q11_POS] == 0 || + qtable->quantval[Q02_POS] == 0) + return FALSE; + /* DC values must be at least partly known for all components. */ + coef_bits = cinfo->coef_bits[ci]; + if (coef_bits[0] < 0) + return FALSE; + /* Block smoothing is helpful if some AC coefficients remain inaccurate. */ + for (coefi = 1; coefi <= 5; coefi++) { + coef_bits_latch[coefi] = coef_bits[coefi]; + if (coef_bits[coefi] != 0) + smoothing_useful = TRUE; + } + coef_bits_latch += SAVED_COEFS; + } + + return smoothing_useful; +} + + +/* + * Variant of decompress_data for use when doing block smoothing. + */ + +METHODDEF(int) +decompress_smooth_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf) +{ + j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec; + d_coef_ptr coef = (d_coef_ptr) lossyd->coef_private; + JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; + JDIMENSION block_num, last_block_column; + int ci, block_row, block_rows, access_rows; + JBLOCKARRAY buffer; + JBLOCKROW buffer_ptr, prev_block_row, next_block_row; + JSAMPARRAY output_ptr; + JDIMENSION output_col; + jpeg_component_info *compptr; + inverse_DCT_method_ptr inverse_DCT; + boolean first_row, last_row; + JBLOCK workspace; + int *coef_bits; + JQUANT_TBL *quanttbl; + IJG_INT32 Q00,Q01,Q02,Q10,Q11,Q20, num; + int DC1,DC2,DC3,DC4,DC5,DC6,DC7,DC8,DC9; + int Al, pred; + + /* Force some input to be done if we are getting ahead of the input. */ + while (cinfo->input_scan_number <= cinfo->output_scan_number && + ! cinfo->inputctl->eoi_reached) { + if (cinfo->input_scan_number == cinfo->output_scan_number) { + /* If input is working on current scan, we ordinarily want it to + * have completed the current row. But if input scan is DC, + * we want it to keep one row ahead so that next block row's DC + * values are up to date. + */ + JDIMENSION delta = (cinfo->Ss == 0) ? 1 : 0; + if (cinfo->input_iMCU_row > cinfo->output_iMCU_row+delta) + break; + } + if ((*cinfo->inputctl->consume_input)(cinfo) == JPEG_SUSPENDED) + return JPEG_SUSPENDED; + } + + /* OK, output from the virtual arrays. */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + /* Don't bother to IDCT an uninteresting component. */ + if (! compptr->component_needed) + continue; + /* Count non-dummy DCT block rows in this iMCU row. */ + if (cinfo->output_iMCU_row < last_iMCU_row) { + block_rows = compptr->v_samp_factor; + access_rows = block_rows * 2; /* this and next iMCU row */ + last_row = FALSE; + } else { + /* NB: can't use last_row_height here; it is input-side-dependent! */ + block_rows = (int)compptr->height_in_data_units % compptr->v_samp_factor; + if (block_rows == 0) block_rows = compptr->v_samp_factor; + access_rows = block_rows; /* this iMCU row only */ + last_row = TRUE; + } + /* Align the virtual buffer for this component. */ + if (cinfo->output_iMCU_row > 0) { + access_rows += compptr->v_samp_factor; /* prior iMCU row too */ + buffer = (*cinfo->mem->access_virt_barray) + ((j_common_ptr) cinfo, coef->whole_image[ci], + (cinfo->output_iMCU_row - 1) * (JDIMENSION)compptr->v_samp_factor, + (JDIMENSION) access_rows, FALSE); + buffer += compptr->v_samp_factor; /* point to current iMCU row */ + first_row = FALSE; + } else { + buffer = (*cinfo->mem->access_virt_barray) + ((j_common_ptr) cinfo, coef->whole_image[ci], + (JDIMENSION) 0, (JDIMENSION) access_rows, FALSE); + first_row = TRUE; + } + /* Fetch component-dependent info */ + coef_bits = coef->coef_bits_latch + (ci * SAVED_COEFS); + quanttbl = compptr->quant_table; + Q00 = quanttbl->quantval[0]; + Q01 = quanttbl->quantval[Q01_POS]; + Q10 = quanttbl->quantval[Q10_POS]; + Q20 = quanttbl->quantval[Q20_POS]; + Q11 = quanttbl->quantval[Q11_POS]; + Q02 = quanttbl->quantval[Q02_POS]; + inverse_DCT = lossyd->inverse_DCT[ci]; + output_ptr = output_buf[ci]; + /* Loop over all DCT blocks to be processed. */ + for (block_row = 0; block_row < block_rows; block_row++) { + buffer_ptr = buffer[block_row]; + if (first_row && block_row == 0) + prev_block_row = buffer_ptr; + else + prev_block_row = buffer[block_row-1]; + if (last_row && block_row == block_rows-1) + next_block_row = buffer_ptr; + else + next_block_row = buffer[block_row+1]; + /* We fetch the surrounding DC values using a sliding-register approach. + * Initialize all nine here so as to do the right thing on narrow pics. + */ + DC1 = DC2 = DC3 = (int) prev_block_row[0][0]; + DC4 = DC5 = DC6 = (int) buffer_ptr[0][0]; + DC7 = DC8 = DC9 = (int) next_block_row[0][0]; + output_col = 0; + last_block_column = compptr->width_in_data_units - 1; + for (block_num = 0; block_num <= last_block_column; block_num++) { + /* Fetch current DCT block into workspace so we can modify it. */ + jcopy_block_row(buffer_ptr, (JBLOCKROW) workspace, (JDIMENSION) 1); + /* Update DC values */ + if (block_num < last_block_column) { + DC3 = (int) prev_block_row[1][0]; + DC6 = (int) buffer_ptr[1][0]; + DC9 = (int) next_block_row[1][0]; + } + /* Compute coefficient estimates per K.8. + * An estimate is applied only if coefficient is still zero, + * and is not known to be fully accurate. + */ + /* AC01 */ + if ((Al=coef_bits[1]) != 0 && workspace[1] == 0) { + num = 36 * Q00 * (DC4 - DC6); + if (num >= 0) { + pred = (int) (((Q01<<7) + num) / (Q01<<8)); + if (Al > 0 && pred >= (1< 0 && pred >= (1<= 0) { + pred = (int) (((Q10<<7) + num) / (Q10<<8)); + if (Al > 0 && pred >= (1< 0 && pred >= (1<= 0) { + pred = (int) (((Q20<<7) + num) / (Q20<<8)); + if (Al > 0 && pred >= (1< 0 && pred >= (1<= 0) { + pred = (int) (((Q11<<7) + num) / (Q11<<8)); + if (Al > 0 && pred >= (1< 0 && pred >= (1<= 0) { + pred = (int) (((Q02<<7) + num) / (Q02<<8)); + if (Al > 0 && pred >= (1< 0 && pred >= (1<codec_data_unit; + } + output_ptr += compptr->codec_data_unit; + } + } + + if (++(cinfo->output_iMCU_row) < cinfo->total_iMCU_rows) + return JPEG_ROW_COMPLETED; + return JPEG_SCAN_COMPLETED; +} + +#endif /* BLOCK_SMOOTHING_SUPPORTED */ + + +/* + * Initialize coefficient buffer controller. + */ + +GLOBAL(void) +jinit_d_coef_controller (j_decompress_ptr cinfo, boolean need_full_buffer) +{ + j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec; + d_coef_ptr coef; + + coef = (d_coef_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(d_coef_controller)); + lossyd->coef_private = (void *) coef; + lossyd->coef_start_input_pass = start_input_pass; + lossyd->coef_start_output_pass = start_output_pass; +#ifdef BLOCK_SMOOTHING_SUPPORTED + coef->coef_bits_latch = NULL; +#endif + + /* Create the coefficient buffer. */ + if (need_full_buffer) { +#ifdef D_MULTISCAN_FILES_SUPPORTED + /* Allocate a full-image virtual array for each component, */ + /* padded to a multiple of samp_factor DCT blocks in each direction. */ + /* Note we ask for a pre-zeroed array. */ + int ci, access_rows; + jpeg_component_info *compptr; + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + access_rows = compptr->v_samp_factor; +#ifdef BLOCK_SMOOTHING_SUPPORTED + /* If block smoothing could be used, need a bigger window */ + if (cinfo->process == JPROC_PROGRESSIVE) + access_rows *= 3; +#endif + coef->whole_image[ci] = (*cinfo->mem->request_virt_barray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, TRUE, + (JDIMENSION) jround_up((long) compptr->width_in_data_units, + (long) compptr->h_samp_factor), + (JDIMENSION) jround_up((long) compptr->height_in_data_units, + (long) compptr->v_samp_factor), + (JDIMENSION) access_rows); + } + lossyd->pub.consume_data = consume_data; + lossyd->pub.decompress_data = decompress_data; + lossyd->coef_arrays = coef->whole_image; /* link to virtual arrays */ +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } else { + /* We only need a single-MCU buffer. */ + JBLOCKROW buffer; + int i; + + buffer = (JBLOCKROW) + (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE, + D_MAX_DATA_UNITS_IN_MCU * SIZEOF(JBLOCK)); + for (i = 0; i < D_MAX_DATA_UNITS_IN_MCU; i++) { + coef->MCU_buffer[i] = buffer + i; + } + lossyd->pub.consume_data = dummy_consume_data; + lossyd->pub.decompress_data = decompress_onepass; + lossyd->coef_arrays = NULL; /* flag for no virtual arrays */ + } +} diff --git a/dcmjpeg/libijg16/jdcolor.c b/dcmjpeg/libijg16/jdcolor.c new file mode 100644 index 00000000..c9814eea --- /dev/null +++ b/dcmjpeg/libijg16/jdcolor.c @@ -0,0 +1,413 @@ +/* + * jdcolor.c + * + * Copyright (C) 1991-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains output colorspace conversion routines. + */ + +#define JPEG_INTERNALS +#include "jinclude16.h" +#include "jpeglib16.h" + + +/* Private subobject */ + +typedef struct { + struct jpeg_color_deconverter pub; /* public fields */ + + /* Private state for YCC->RGB conversion */ + int * Cr_r_tab; /* => table for Cr to R conversion */ + int * Cb_b_tab; /* => table for Cb to B conversion */ + IJG_INT32 * Cr_g_tab; /* => table for Cr to G conversion */ + IJG_INT32 * Cb_g_tab; /* => table for Cb to G conversion */ +} my_color_deconverter; + +typedef my_color_deconverter * my_cconvert_ptr; + + +/**************** YCbCr -> RGB conversion: most common case **************/ + +/* + * YCbCr is defined per CCIR 601-1, except that Cb and Cr are + * normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5. + * The conversion equations to be implemented are therefore + * R = Y + 1.40200 * Cr + * G = Y - 0.34414 * Cb - 0.71414 * Cr + * B = Y + 1.77200 * Cb + * where Cb and Cr represent the incoming values less CENTERJSAMPLE. + * (These numbers are derived from TIFF 6.0 section 21, dated 3-June-92.) + * + * To avoid floating-point arithmetic, we represent the fractional constants + * as integers scaled up by 2^16 (about 4 digits precision); we have to divide + * the products by 2^16, with appropriate rounding, to get the correct answer. + * Notice that Y, being an integral input, does not contribute any fraction + * so it need not participate in the rounding. + * + * For even more speed, we avoid doing any multiplications in the inner loop + * by precalculating the constants times Cb and Cr for all possible values. + * For 8-bit JSAMPLEs this is very reasonable (only 256 entries per table); + * for 12-bit samples it is still acceptable. It's not very reasonable for + * 16-bit samples, but if you want lossless storage you shouldn't be changing + * colorspace anyway. + * The Cr=>R and Cb=>B values can be rounded to integers in advance; the + * values for the G calculation are left scaled up, since we must add them + * together before rounding. + */ + +#define SCALEBITS 16 /* speediest right-shift on some machines */ +#define ONE_HALF ((IJG_INT32) 1 << (SCALEBITS-1)) +#define FIX(x) ((IJG_INT32) ((x) * (1L<RGB colorspace conversion. + */ + +LOCAL(void) +build_ycc_rgb_table (j_decompress_ptr cinfo) +{ + my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; + int i; + IJG_INT32 x; +#if BITS_IN_JSAMPLE == 16 + /* no need for temporaries */ +#else + SHIFT_TEMPS +#endif + + cconvert->Cr_r_tab = (int *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (MAXJSAMPLE+1) * SIZEOF(int)); + cconvert->Cb_b_tab = (int *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (MAXJSAMPLE+1) * SIZEOF(int)); + cconvert->Cr_g_tab = (IJG_INT32 *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (MAXJSAMPLE+1) * SIZEOF(IJG_INT32)); + cconvert->Cb_g_tab = (IJG_INT32 *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (MAXJSAMPLE+1) * SIZEOF(IJG_INT32)); + + for (i = 0, x = -CENTERJSAMPLE; i <= MAXJSAMPLE; i++, x++) { + /* i is the actual input pixel value, in the range 0..MAXJSAMPLE */ + /* The Cb or Cr value we are thinking of is x = i - CENTERJSAMPLE */ + +#if BITS_IN_JSAMPLE == 16 + /* Bug fix 2001-11-06 by Eichelberg: The integer routines below + produce an overflow when used with MAXJSAMPLE == 65535. + Use floating point calculation instead. */ + + /* Cr=>R value is nearest int to 1.40200 * x */ + cconvert->Cr_r_tab[i] = (int)(1.40200 * (double)x + 0.5); + /* Cb=>B value is nearest int to 1.77200 * x */ + cconvert->Cb_b_tab[i] = (int)(1.77200 * (double)x + 0.5); +#else + /* Cr=>R value is nearest int to 1.40200 * x */ + cconvert->Cr_r_tab[i] = (int) + RIGHT_SHIFT(FIX(1.40200) * x + ONE_HALF, SCALEBITS); + /* Cb=>B value is nearest int to 1.77200 * x */ + cconvert->Cb_b_tab[i] = (int) + RIGHT_SHIFT(FIX(1.77200) * x + ONE_HALF, SCALEBITS); +#endif + + /* Cr=>G value is scaled-up -0.71414 * x */ + cconvert->Cr_g_tab[i] = (- FIX(0.71414)) * x; + /* Cb=>G value is scaled-up -0.34414 * x */ + /* We also add in ONE_HALF so that need not do it in inner loop */ + cconvert->Cb_g_tab[i] = (- FIX(0.34414)) * x + ONE_HALF; + } +} + + +/* + * Convert some rows of samples to the output colorspace. + * + * Note that we change from noninterleaved, one-plane-per-component format + * to interleaved-pixel format. The output buffer is therefore three times + * as wide as the input buffer. + * A starting row offset is provided only for the input buffer. The caller + * can easily adjust the passed output_buf value to accommodate any row + * offset required on that side. + */ + +METHODDEF(void) +ycc_rgb_convert (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION input_row, + JSAMPARRAY output_buf, int num_rows) +{ + my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; + register int y, cb, cr; + register JSAMPROW outptr; + register JSAMPROW inptr0, inptr1, inptr2; + register JDIMENSION col; + JDIMENSION num_cols = cinfo->output_width; + /* copy these pointers into registers if possible */ + register JSAMPLE * range_limit = cinfo->sample_range_limit; + register int * Crrtab = cconvert->Cr_r_tab; + register int * Cbbtab = cconvert->Cb_b_tab; + register IJG_INT32 * Crgtab = cconvert->Cr_g_tab; + register IJG_INT32 * Cbgtab = cconvert->Cb_g_tab; + SHIFT_TEMPS + + while (--num_rows >= 0) { + inptr0 = input_buf[0][input_row]; + inptr1 = input_buf[1][input_row]; + inptr2 = input_buf[2][input_row]; + input_row++; + outptr = *output_buf++; + for (col = 0; col < num_cols; col++) { + y = GETJSAMPLE(inptr0[col]); + cb = GETJSAMPLE(inptr1[col]); + cr = GETJSAMPLE(inptr2[col]); + /* Range-limiting is essential due to noise introduced by DCT losses. */ + outptr[RGB_RED] = range_limit[y + Crrtab[cr]]; + outptr[RGB_GREEN] = range_limit[y + + ((int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], + SCALEBITS))]; + outptr[RGB_BLUE] = range_limit[y + Cbbtab[cb]]; + outptr += RGB_PIXELSIZE; + } + } +} + + +/**************** Cases other than YCbCr -> RGB **************/ + + +/* + * Color conversion for no colorspace change: just copy the data, + * converting from separate-planes to interleaved representation. + */ + +METHODDEF(void) +null_convert (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION input_row, + JSAMPARRAY output_buf, int num_rows) +{ + register JSAMPROW inptr, outptr; + register JDIMENSION count; + register int num_components = cinfo->num_components; + JDIMENSION num_cols = cinfo->output_width; + int ci; + + while (--num_rows >= 0) { + for (ci = 0; ci < num_components; ci++) { + inptr = input_buf[ci][input_row]; + outptr = output_buf[0] + ci; + for (count = num_cols; count > 0; count--) { + *outptr = *inptr++; /* needn't bother with GETJSAMPLE() here */ + outptr += num_components; + } + } + input_row++; + output_buf++; + } +} + + +/* + * Color conversion for grayscale: just copy the data. + * This also works for YCbCr -> grayscale conversion, in which + * we just copy the Y (luminance) component and ignore chrominance. + */ + +METHODDEF(void) +grayscale_convert (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION input_row, + JSAMPARRAY output_buf, int num_rows) +{ + jcopy_sample_rows(input_buf[0], (int) input_row, output_buf, 0, + num_rows, cinfo->output_width); +} + + +/* + * Convert grayscale to RGB: just duplicate the graylevel three times. + * This is provided to support applications that don't want to cope + * with grayscale as a separate case. + */ + +METHODDEF(void) +gray_rgb_convert (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION input_row, + JSAMPARRAY output_buf, int num_rows) +{ + register JSAMPROW inptr, outptr; + register JDIMENSION col; + JDIMENSION num_cols = cinfo->output_width; + + while (--num_rows >= 0) { + inptr = input_buf[0][input_row++]; + outptr = *output_buf++; + for (col = 0; col < num_cols; col++) { + /* We can dispense with GETJSAMPLE() here */ + outptr[RGB_RED] = outptr[RGB_GREEN] = outptr[RGB_BLUE] = inptr[col]; + outptr += RGB_PIXELSIZE; + } + } +} + + +/* + * Adobe-style YCCK->CMYK conversion. + * We convert YCbCr to R=1-C, G=1-M, and B=1-Y using the same + * conversion as above, while passing K (black) unchanged. + * We assume build_ycc_rgb_table has been called. + */ + +METHODDEF(void) +ycck_cmyk_convert (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION input_row, + JSAMPARRAY output_buf, int num_rows) +{ + my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; + register int y, cb, cr; + register JSAMPROW outptr; + register JSAMPROW inptr0, inptr1, inptr2, inptr3; + register JDIMENSION col; + JDIMENSION num_cols = cinfo->output_width; + /* copy these pointers into registers if possible */ + register JSAMPLE * range_limit = cinfo->sample_range_limit; + register int * Crrtab = cconvert->Cr_r_tab; + register int * Cbbtab = cconvert->Cb_b_tab; + register IJG_INT32 * Crgtab = cconvert->Cr_g_tab; + register IJG_INT32 * Cbgtab = cconvert->Cb_g_tab; + SHIFT_TEMPS + + while (--num_rows >= 0) { + inptr0 = input_buf[0][input_row]; + inptr1 = input_buf[1][input_row]; + inptr2 = input_buf[2][input_row]; + inptr3 = input_buf[3][input_row]; + input_row++; + outptr = *output_buf++; + for (col = 0; col < num_cols; col++) { + y = GETJSAMPLE(inptr0[col]); + cb = GETJSAMPLE(inptr1[col]); + cr = GETJSAMPLE(inptr2[col]); + /* Range-limiting is essential due to noise introduced by DCT losses. */ + outptr[0] = range_limit[MAXJSAMPLE - (y + Crrtab[cr])]; /* red */ + outptr[1] = range_limit[MAXJSAMPLE - (y + /* green */ + ((int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], + SCALEBITS)))]; + outptr[2] = range_limit[MAXJSAMPLE - (y + Cbbtab[cb])]; /* blue */ + /* K passes through unchanged */ + outptr[3] = inptr3[col]; /* don't need GETJSAMPLE here */ + outptr += 4; + } + } +} + + +/* + * Empty method for start_pass. + */ + +METHODDEF(void) +start_pass_dcolor (j_decompress_ptr cinfo) +{ + /* no work needed */ +} + + +/* + * Module initialization routine for output colorspace conversion. + */ + +GLOBAL(void) +jinit_color_deconverter (j_decompress_ptr cinfo) +{ + my_cconvert_ptr cconvert; + int ci; + + cconvert = (my_cconvert_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_color_deconverter)); + cinfo->cconvert = (struct jpeg_color_deconverter *) cconvert; + cconvert->pub.start_pass = start_pass_dcolor; + + /* Make sure num_components agrees with jpeg_color_space */ + switch (cinfo->jpeg_color_space) { + case JCS_GRAYSCALE: + if (cinfo->num_components != 1) + ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); + break; + + case JCS_RGB: + case JCS_YCbCr: + if (cinfo->num_components != 3) + ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); + break; + + case JCS_CMYK: + case JCS_YCCK: + if (cinfo->num_components != 4) + ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); + break; + + default: /* JCS_UNKNOWN can be anything */ + if (cinfo->num_components < 1) + ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); + break; + } + + /* Set out_color_components and conversion method based on requested space. + * Also clear the component_needed flags for any unused components, + * so that earlier pipeline stages can avoid useless computation. + */ + + switch (cinfo->out_color_space) { + case JCS_GRAYSCALE: + cinfo->out_color_components = 1; + if (cinfo->jpeg_color_space == JCS_GRAYSCALE || + cinfo->jpeg_color_space == JCS_YCbCr) { + cconvert->pub.color_convert = grayscale_convert; + /* For color->grayscale conversion, only the Y (0) component is needed */ + for (ci = 1; ci < cinfo->num_components; ci++) + cinfo->comp_info[ci].component_needed = FALSE; + } else + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); + break; + + case JCS_RGB: + cinfo->out_color_components = RGB_PIXELSIZE; + if (cinfo->jpeg_color_space == JCS_YCbCr) { + cconvert->pub.color_convert = ycc_rgb_convert; + build_ycc_rgb_table(cinfo); + } else if (cinfo->jpeg_color_space == JCS_GRAYSCALE) { + cconvert->pub.color_convert = gray_rgb_convert; + } else if (cinfo->jpeg_color_space == JCS_RGB && RGB_PIXELSIZE == 3) { + cconvert->pub.color_convert = null_convert; + } else + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); + break; + + case JCS_CMYK: + cinfo->out_color_components = 4; + if (cinfo->jpeg_color_space == JCS_YCCK) { + cconvert->pub.color_convert = ycck_cmyk_convert; + build_ycc_rgb_table(cinfo); + } else if (cinfo->jpeg_color_space == JCS_CMYK) { + cconvert->pub.color_convert = null_convert; + } else + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); + break; + + default: + /* Permit null conversion to same output space */ + if (cinfo->out_color_space == cinfo->jpeg_color_space) { + cinfo->out_color_components = cinfo->num_components; + cconvert->pub.color_convert = null_convert; + } else /* unsupported non-null conversion */ + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); + break; + } + + if (cinfo->quantize_colors) + cinfo->output_components = 1; /* single colormapped output component */ + else + cinfo->output_components = cinfo->out_color_components; +} diff --git a/dcmjpeg/libijg16/jdct16.h b/dcmjpeg/libijg16/jdct16.h new file mode 100644 index 00000000..792ab153 --- /dev/null +++ b/dcmjpeg/libijg16/jdct16.h @@ -0,0 +1,176 @@ +/* + * jdct.h + * + * Copyright (C) 1994-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This include file contains common declarations for the forward and + * inverse DCT modules. These declarations are private to the DCT managers + * (jcdctmgr.c, jddctmgr.c) and the individual DCT algorithms. + * The individual DCT algorithms are kept in separate files to ease + * machine-dependent tuning (e.g., assembly coding). + */ + + +/* + * A forward DCT routine is given a pointer to a work area of type DCTELEM[]; + * the DCT is to be performed in-place in that buffer. Type DCTELEM is int + * for 8-bit samples, IJG_INT32 for 12-bit samples. (NOTE: Floating-point DCT + * implementations use an array of type FAST_FLOAT, instead.) + * The DCT inputs are expected to be signed (range +-CENTERJSAMPLE). + * The DCT outputs are returned scaled up by a factor of 8; they therefore + * have a range of +-8K for 8-bit data, +-128K for 12-bit data. This + * convention improves accuracy in integer implementations and saves some + * work in floating-point ones. + * Quantization of the output coefficients is done by jcdctmgr.c. + */ + +#if BITS_IN_JSAMPLE == 8 +typedef int DCTELEM; /* 16 or 32 bits is fine */ +#else +typedef IJG_INT32 DCTELEM; /* must have 32 bits */ +#endif + +typedef JMETHOD(void, forward_DCT_method_ptr, (DCTELEM * data)); +typedef JMETHOD(void, float_DCT_method_ptr, (FAST_FLOAT * data)); + + +/* + * An inverse DCT routine is given a pointer to the input JBLOCK and a pointer + * to an output sample array. The routine must dequantize the input data as + * well as perform the IDCT; for dequantization, it uses the multiplier table + * pointed to by compptr->dct_table. The output data is to be placed into the + * sample array starting at a specified column. (Any row offset needed will + * be applied to the array pointer before it is passed to the IDCT code.) + * Note that the number of samples emitted by the IDCT routine is + * DCT_scaled_size * DCT_scaled_size. + */ + +/* typedef inverse_DCT_method_ptr is declared in jpegint.h */ + +/* + * Each IDCT routine has its own ideas about the best dct_table element type. + */ + +typedef MULTIPLIER ISLOW_MULT_TYPE; /* short or int, whichever is faster */ +#if BITS_IN_JSAMPLE == 8 +typedef MULTIPLIER IFAST_MULT_TYPE; /* 16 bits is OK, use short if faster */ +#define IFAST_SCALE_BITS 2 /* fractional bits in scale factors */ +#else +typedef IJG_INT32 IFAST_MULT_TYPE; /* need 32 bits for scaled quantizers */ +#define IFAST_SCALE_BITS 13 /* fractional bits in scale factors */ +#endif +typedef FAST_FLOAT FLOAT_MULT_TYPE; /* preferred floating type */ + + +/* + * Each IDCT routine is responsible for range-limiting its results and + * converting them to unsigned form (0..MAXJSAMPLE). The raw outputs could + * be quite far out of range if the input data is corrupt, so a bulletproof + * range-limiting step is required. We use a mask-and-table-lookup method + * to do the combined operations quickly. See the comments with + * prepare_range_limit_table (in jdmaster.c) for more info. + */ + +#define IDCT_range_limit(cinfo) ((cinfo)->sample_range_limit + CENTERJSAMPLE) + +#define RANGE_MASK (MAXJSAMPLE * 4 + 3) /* 2 bits wider than legal samples */ + + +/* Short forms of external names for systems with brain-damaged linkers. */ + +#ifdef NEED_SHORT_EXTERNAL_NAMES +#define jpeg_fdct_islow jpeg16_fdct_islow +#define jpeg_fdct_ifast jpeg16_fdct_ifast +#define jpeg_fdct_float jpeg16_fdct_float +#define jpeg_idct_islow jpeg16_idct_islow +#define jpeg_idct_ifast jpeg16_idct_ifast +#define jpeg_idct_float jpeg16_idct_float +#define jpeg_idct_4x4 jpeg16_idct_4x4 +#define jpeg_idct_2x2 jpeg16_idct_2x2 +#define jpeg_idct_1x1 jpeg16_idct_1x1 +#endif /* NEED_SHORT_EXTERNAL_NAMES */ + +/* Extern declarations for the forward and inverse DCT routines. */ + +EXTERN(void) jpeg_fdct_islow JPP((DCTELEM * data)); +EXTERN(void) jpeg_fdct_ifast JPP((DCTELEM * data)); +EXTERN(void) jpeg_fdct_float JPP((FAST_FLOAT * data)); + +EXTERN(void) jpeg_idct_islow + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_ifast + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_float + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_4x4 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_2x2 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_1x1 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); + + +/* + * Macros for handling fixed-point arithmetic; these are used by many + * but not all of the DCT/IDCT modules. + * + * All values are expected to be of type IJG_INT32. + * Fractional constants are scaled left by CONST_BITS bits. + * CONST_BITS is defined within each module using these macros, + * and may differ from one module to the next. + */ + +#define ONE ((IJG_INT32) 1) +#define CONST_SCALE (ONE << CONST_BITS) + +/* Convert a positive real constant to an integer scaled by CONST_SCALE. + * Caution: some C compilers fail to reduce "FIX(constant)" at compile time, + * thus causing a lot of useless floating-point operations at run time. + */ + +#define FIX(x) ((IJG_INT32) ((x) * CONST_SCALE + 0.5)) + +/* Descale and correctly round an IJG_INT32 value that's scaled by N bits. + * We assume RIGHT_SHIFT rounds towards minus infinity, so adding + * the fudge factor is correct for either sign of X. + */ + +#define DESCALE(x,n) RIGHT_SHIFT((x) + (ONE << ((n)-1)), n) + +/* Multiply an IJG_INT32 variable by an IJG_INT32 constant to yield an IJG_INT32 result. + * This macro is used only when the two inputs will actually be no more than + * 16 bits wide, so that a 16x16->32 bit multiply can be used instead of a + * full 32x32 multiply. This provides a useful speedup on many machines. + * Unfortunately there is no way to specify a 16x16->32 multiply portably + * in C, but some C compilers will do the right thing if you provide the + * correct combination of casts. + */ + +#ifdef SHORTxSHORT_32 /* may work if 'int' is 32 bits */ +#define MULTIPLY16C16(var,const) (((INT16) (var)) * ((INT16) (const))) +#endif +#ifdef SHORTxLCONST_32 /* known to work with Microsoft C 6.0 */ +#define MULTIPLY16C16(var,const) (((INT16) (var)) * ((IJG_INT32) (const))) +#endif + +#ifndef MULTIPLY16C16 /* default definition */ +#define MULTIPLY16C16(var,const) ((var) * (const)) +#endif + +/* Same except both inputs are variables. */ + +#ifdef SHORTxSHORT_32 /* may work if 'int' is 32 bits */ +#define MULTIPLY16V16(var1,var2) (((INT16) (var1)) * ((INT16) (var2))) +#endif + +#ifndef MULTIPLY16V16 /* default definition */ +#define MULTIPLY16V16(var1,var2) ((var1) * (var2)) +#endif diff --git a/dcmjpeg/libijg16/jddctmgr.c b/dcmjpeg/libijg16/jddctmgr.c new file mode 100644 index 00000000..081c5741 --- /dev/null +++ b/dcmjpeg/libijg16/jddctmgr.c @@ -0,0 +1,270 @@ +/* + * jddctmgr.c + * + * Copyright (C) 1994-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains the inverse-DCT management logic. + * This code selects a particular IDCT implementation to be used, + * and it performs related housekeeping chores. No code in this file + * is executed per IDCT step, only during output pass setup. + * + * Note that the IDCT routines are responsible for performing coefficient + * dequantization as well as the IDCT proper. This module sets up the + * dequantization multiplier table needed by the IDCT routine. + */ + +#define JPEG_INTERNALS +#include "jinclude16.h" +#include "jpeglib16.h" +#include "jlossy16.h" /* Private declarations for lossy subsystem */ +#include "jdct16.h" /* Private declarations for DCT subsystem */ + + +/* + * The decompressor input side (jdinput.c) saves away the appropriate + * quantization table for each component at the start of the first scan + * involving that component. (This is necessary in order to correctly + * decode files that reuse Q-table slots.) + * When we are ready to make an output pass, the saved Q-table is converted + * to a multiplier table that will actually be used by the IDCT routine. + * The multiplier table contents are IDCT-method-dependent. To support + * application changes in IDCT method between scans, we can remake the + * multiplier tables if necessary. + * In buffered-image mode, the first output pass may occur before any data + * has been seen for some components, and thus before their Q-tables have + * been saved away. To handle this case, multiplier tables are preset + * to zeroes; the result of the IDCT will be a neutral gray level. + */ + + +/* Private subobject for this module */ + +typedef struct { + /* This array contains the IDCT method code that each multiplier table + * is currently set up for, or -1 if it's not yet set up. + * The actual multiplier tables are pointed to by dct_table in the + * per-component comp_info structures. + */ + int cur_method[MAX_COMPONENTS]; +} idct_controller; + +typedef idct_controller * idct_ptr; + + +/* Allocated multiplier tables: big enough for any supported variant */ + +typedef union { + ISLOW_MULT_TYPE islow_array[DCTSIZE2]; +#ifdef DCT_IFAST_SUPPORTED + IFAST_MULT_TYPE ifast_array[DCTSIZE2]; +#endif +#ifdef DCT_FLOAT_SUPPORTED + FLOAT_MULT_TYPE float_array[DCTSIZE2]; +#endif +} multiplier_table; + + +/* The current scaled-IDCT routines require ISLOW-style multiplier tables, + * so be sure to compile that code if either ISLOW or SCALING is requested. + */ +#ifdef DCT_ISLOW_SUPPORTED +#define PROVIDE_ISLOW_TABLES +#else +#ifdef IDCT_SCALING_SUPPORTED +#define PROVIDE_ISLOW_TABLES +#endif +#endif + + +/* + * Prepare for an output pass. + * Here we select the proper IDCT routine for each component and build + * a matching multiplier table. + */ + +METHODDEF(void) +start_pass (j_decompress_ptr cinfo) +{ + j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec; + idct_ptr idct = (idct_ptr) lossyd->idct_private; + int ci, i; + jpeg_component_info *compptr; + int method = 0; + inverse_DCT_method_ptr method_ptr = NULL; + JQUANT_TBL * qtbl; + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + /* Select the proper IDCT routine for this component's scaling */ + switch (compptr->codec_data_unit) { +#ifdef IDCT_SCALING_SUPPORTED + case 1: + method_ptr = jpeg_idct_1x1; + method = JDCT_ISLOW; /* jidctred uses islow-style table */ + break; + case 2: + method_ptr = jpeg_idct_2x2; + method = JDCT_ISLOW; /* jidctred uses islow-style table */ + break; + case 4: + method_ptr = jpeg_idct_4x4; + method = JDCT_ISLOW; /* jidctred uses islow-style table */ + break; +#endif + case DCTSIZE: + switch (cinfo->dct_method) { +#ifdef DCT_ISLOW_SUPPORTED + case JDCT_ISLOW: + method_ptr = jpeg_idct_islow; + method = JDCT_ISLOW; + break; +#endif +#ifdef DCT_IFAST_SUPPORTED + case JDCT_IFAST: + method_ptr = jpeg_idct_ifast; + method = JDCT_IFAST; + break; +#endif +#ifdef DCT_FLOAT_SUPPORTED + case JDCT_FLOAT: + method_ptr = jpeg_idct_float; + method = JDCT_FLOAT; + break; +#endif + default: + ERREXIT(cinfo, JERR_NOT_COMPILED); + break; + } + break; + default: + ERREXIT1(cinfo, JERR_BAD_DCTSIZE, compptr->codec_data_unit); + break; + } + lossyd->inverse_DCT[ci] = method_ptr; + /* Create multiplier table from quant table. + * However, we can skip this if the component is uninteresting + * or if we already built the table. Also, if no quant table + * has yet been saved for the component, we leave the + * multiplier table all-zero; we'll be reading zeroes from the + * coefficient controller's buffer anyway. + */ + if (! compptr->component_needed || idct->cur_method[ci] == method) + continue; + qtbl = compptr->quant_table; + if (qtbl == NULL) /* happens if no data yet for component */ + continue; + idct->cur_method[ci] = method; + switch (method) { +#ifdef PROVIDE_ISLOW_TABLES + case JDCT_ISLOW: + { + /* For LL&M IDCT method, multipliers are equal to raw quantization + * coefficients, but are stored as ints to ensure access efficiency. + */ + ISLOW_MULT_TYPE * ismtbl = (ISLOW_MULT_TYPE *) compptr->dct_table; + for (i = 0; i < DCTSIZE2; i++) { + ismtbl[i] = (ISLOW_MULT_TYPE) qtbl->quantval[i]; + } + } + break; +#endif +#ifdef DCT_IFAST_SUPPORTED + case JDCT_IFAST: + { + /* For AA&N IDCT method, multipliers are equal to quantization + * coefficients scaled by scalefactor[row]*scalefactor[col], where + * scalefactor[0] = 1 + * scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7 + * For integer operation, the multiplier table is to be scaled by + * IFAST_SCALE_BITS. + */ + IFAST_MULT_TYPE * ifmtbl = (IFAST_MULT_TYPE *) compptr->dct_table; +#define CONST_BITS 14 + static const INT16 aanscales[DCTSIZE2] = { + /* precomputed values scaled up by 14 bits */ + 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520, + 22725, 31521, 29692, 26722, 22725, 17855, 12299, 6270, + 21407, 29692, 27969, 25172, 21407, 16819, 11585, 5906, + 19266, 26722, 25172, 22654, 19266, 15137, 10426, 5315, + 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520, + 12873, 17855, 16819, 15137, 12873, 10114, 6967, 3552, + 8867, 12299, 11585, 10426, 8867, 6967, 4799, 2446, + 4520, 6270, 5906, 5315, 4520, 3552, 2446, 1247 + }; + SHIFT_TEMPS + + for (i = 0; i < DCTSIZE2; i++) { + ifmtbl[i] = (IFAST_MULT_TYPE) + DESCALE(MULTIPLY16V16((IJG_INT32) qtbl->quantval[i], + (IJG_INT32) aanscales[i]), + CONST_BITS-IFAST_SCALE_BITS); + } + } + break; +#endif +#ifdef DCT_FLOAT_SUPPORTED + case JDCT_FLOAT: + { + /* For float AA&N IDCT method, multipliers are equal to quantization + * coefficients scaled by scalefactor[row]*scalefactor[col], where + * scalefactor[0] = 1 + * scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7 + */ + FLOAT_MULT_TYPE * fmtbl = (FLOAT_MULT_TYPE *) compptr->dct_table; + int row, col; + static const double aanscalefactor[DCTSIZE] = { + 1.0, 1.387039845, 1.306562965, 1.175875602, + 1.0, 0.785694958, 0.541196100, 0.275899379 + }; + + i = 0; + for (row = 0; row < DCTSIZE; row++) { + for (col = 0; col < DCTSIZE; col++) { + fmtbl[i] = (FLOAT_MULT_TYPE) + ((double) qtbl->quantval[i] * + aanscalefactor[row] * aanscalefactor[col]); + i++; + } + } + } + break; +#endif + default: + ERREXIT(cinfo, JERR_NOT_COMPILED); + break; + } + } +} + + +/* + * Initialize IDCT manager. + */ + +GLOBAL(void) +jinit_inverse_dct (j_decompress_ptr cinfo) +{ + j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec; + idct_ptr idct; + int ci; + jpeg_component_info *compptr; + + idct = (idct_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(idct_controller)); + lossyd->idct_private = (void *) idct; + lossyd->idct_start_pass = start_pass; + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + /* Allocate and pre-zero a multiplier table for each component */ + compptr->dct_table = + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(multiplier_table)); + MEMZERO(compptr->dct_table, SIZEOF(multiplier_table)); + /* Mark multiplier table not yet set up for any method */ + idct->cur_method[ci] = -1; + } +} diff --git a/dcmjpeg/libijg16/jddiffct.c b/dcmjpeg/libijg16/jddiffct.c new file mode 100644 index 00000000..63d13ea6 --- /dev/null +++ b/dcmjpeg/libijg16/jddiffct.c @@ -0,0 +1,399 @@ +/* + * jddiffct.c + * + * Copyright (C) 1994-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains the [un]difference buffer controller for decompression. + * This controller is the top level of the lossless JPEG decompressor proper. + * The difference buffer lies between the entropy decoding and + * prediction/undifferencing steps. The undifference buffer lies between the + * prediction/undifferencing and scaling steps. + * + * In buffered-image mode, this controller is the interface between + * input-oriented processing and output-oriented processing. + */ + +#define JPEG_INTERNALS +#include "jinclude16.h" +#include "jpeglib16.h" +#include "jlossls16.h" + + +#ifdef D_LOSSLESS_SUPPORTED + +/* Private buffer controller object */ + +typedef struct { + /* These variables keep track of the current location of the input side. */ + /* cinfo->input_iMCU_row is also used for this. */ + JDIMENSION MCU_ctr; /* counts MCUs processed in current row */ + unsigned int restart_rows_to_go; /* MCU-rows left in this restart interval */ + unsigned int MCU_vert_offset; /* counts MCU rows within iMCU row */ + unsigned int MCU_rows_per_iMCU_row; /* number of such rows needed */ + + /* The output side's location is represented by cinfo->output_iMCU_row. */ + + JDIFFARRAY diff_buf[MAX_COMPONENTS]; /* iMCU row of differences */ + JDIFFARRAY undiff_buf[MAX_COMPONENTS]; /* iMCU row of undiff'd samples */ + +#ifdef D_MULTISCAN_FILES_SUPPORTED + /* In multi-pass modes, we need a virtual sample array for each component. */ + jvirt_sarray_ptr whole_image[MAX_COMPONENTS]; +#endif +} d_diff_controller; + +typedef d_diff_controller * d_diff_ptr; + +/* Forward declarations */ +METHODDEF(int) decompress_data + JPP((j_decompress_ptr cinfo, JSAMPIMAGE output_buf)); +#ifdef D_MULTISCAN_FILES_SUPPORTED +METHODDEF(int) output_data + JPP((j_decompress_ptr cinfo, JSAMPIMAGE output_buf)); +#endif + + +LOCAL(void) +start_iMCU_row (j_decompress_ptr cinfo) +/* Reset within-iMCU-row counters for a new row (input side) */ +{ + j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec; + d_diff_ptr diff = (d_diff_ptr) losslsd->diff_private; + + /* In an interleaved scan, an MCU row is the same as an iMCU row. + * In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows. + * But at the bottom of the image, process only what's left. + */ + if (cinfo->comps_in_scan > 1) { + diff->MCU_rows_per_iMCU_row = 1; + } else { + if (cinfo->input_iMCU_row < (cinfo->total_iMCU_rows-1)) + diff->MCU_rows_per_iMCU_row = (JDIMENSION)cinfo->cur_comp_info[0]->v_samp_factor; + else + diff->MCU_rows_per_iMCU_row = (JDIMENSION)cinfo->cur_comp_info[0]->last_row_height; + } + + diff->MCU_ctr = 0; + diff->MCU_vert_offset = 0; +} + + +/* + * Initialize for an input processing pass. + */ + +METHODDEF(void) +start_input_pass (j_decompress_ptr cinfo) +{ + j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec; + d_diff_ptr diff = (d_diff_ptr) losslsd->diff_private; + + /* Check that the restart interval is an integer multiple of the number + * of MCU in an MCU-row. + */ + if (cinfo->restart_interval % cinfo->MCUs_per_row != 0) + ERREXIT2(cinfo, JERR_BAD_RESTART, + (int)cinfo->restart_interval, (int)cinfo->MCUs_per_row); + + /* Initialize restart counter */ + diff->restart_rows_to_go = cinfo->restart_interval / cinfo->MCUs_per_row; + + cinfo->input_iMCU_row = 0; + start_iMCU_row(cinfo); +} + + +/* + * Check for a restart marker & resynchronize decoder, undifferencer. + * Returns FALSE if must suspend. + */ + +METHODDEF(boolean) +process_restart (j_decompress_ptr cinfo) +{ + j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec; + d_diff_ptr diff = (d_diff_ptr) losslsd->diff_private; + + if (! (*losslsd->entropy_process_restart) (cinfo)) + return FALSE; + + (*losslsd->predict_process_restart) (cinfo); + + /* Reset restart counter */ + diff->restart_rows_to_go = cinfo->restart_interval / cinfo->MCUs_per_row; + + return TRUE; +} + + +/* + * Initialize for an output processing pass. + */ + +METHODDEF(void) +start_output_pass (j_decompress_ptr cinfo) +{ + cinfo->output_iMCU_row = 0; +} + + +/* + * Decompress and return some data in the supplied buffer. + * Always attempts to emit one fully interleaved MCU row ("iMCU" row). + * Input and output must run in lockstep since we have only a one-MCU buffer. + * Return value is JPEG_ROW_COMPLETED, JPEG_SCAN_COMPLETED, or JPEG_SUSPENDED. + * + * NB: output_buf contains a plane for each component in image, + * which we index according to the component's SOF position. + */ + +METHODDEF(int) +decompress_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf) +{ + j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec; + d_diff_ptr diff = (d_diff_ptr) losslsd->diff_private; + JDIMENSION MCU_col_num; /* index of current MCU within row */ + JDIMENSION MCU_count; /* number of MCUs decoded */ + JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; + int comp, ci, row, prev_row; + unsigned int yoffset; + jpeg_component_info *compptr; + + /* Loop to process as much as one whole iMCU row */ + for (yoffset = diff->MCU_vert_offset; yoffset < diff->MCU_rows_per_iMCU_row; + yoffset++) { + + /* Process restart marker if needed; may have to suspend */ + if (cinfo->restart_interval) { + if (diff->restart_rows_to_go == 0) + if (! process_restart(cinfo)) + return JPEG_SUSPENDED; + } + + MCU_col_num = diff->MCU_ctr; + /* Try to fetch an MCU-row (or remaining portion of suspended MCU-row). */ + MCU_count = + (*losslsd->entropy_decode_mcus) (cinfo, + diff->diff_buf, yoffset, MCU_col_num, + cinfo->MCUs_per_row - MCU_col_num); + if (MCU_count != cinfo->MCUs_per_row - MCU_col_num) { + /* Suspension forced; update state counters and exit */ + diff->MCU_vert_offset = yoffset; + diff->MCU_ctr += MCU_count; + return JPEG_SUSPENDED; + } + + /* Account for restart interval (no-op if not using restarts) */ + diff->restart_rows_to_go--; + + /* Completed an MCU row, but perhaps not an iMCU row */ + diff->MCU_ctr = 0; + } + + /* + * Undifference and scale each scanline of the disassembled MCU-row + * separately. We do not process dummy samples at the end of a scanline + * or dummy rows at the end of the image. + */ + for (comp = 0; comp < cinfo->comps_in_scan; comp++) { + compptr = cinfo->cur_comp_info[comp]; + ci = compptr->component_index; + for (row = 0, prev_row = compptr->v_samp_factor - 1; + row < (cinfo->input_iMCU_row == last_iMCU_row ? + compptr->last_row_height : compptr->v_samp_factor); + prev_row = row, row++) { + (*losslsd->predict_undifference[ci]) (cinfo, ci, + diff->diff_buf[ci][row], + diff->undiff_buf[ci][prev_row], + diff->undiff_buf[ci][row], + compptr->width_in_data_units); + (*losslsd->scaler_scale) (cinfo, diff->undiff_buf[ci][row], + output_buf[ci][row], + compptr->width_in_data_units); + } + } + + /* Completed the iMCU row, advance counters for next one. + * + * NB: output_data will increment output_iMCU_row. + * This counter is not needed for the single-pass case + * or the input side of the multi-pass case. + */ + if (++(cinfo->input_iMCU_row) < cinfo->total_iMCU_rows) { + start_iMCU_row(cinfo); + return JPEG_ROW_COMPLETED; + } + /* Completed the scan */ + (*cinfo->inputctl->finish_input_pass) (cinfo); + return JPEG_SCAN_COMPLETED; +} + + +/* + * Dummy consume-input routine for single-pass operation. + */ + +METHODDEF(int) +dummy_consume_data (j_decompress_ptr cinfo) +{ + return JPEG_SUSPENDED; /* Always indicate nothing was done */ +} + + +#ifdef D_MULTISCAN_FILES_SUPPORTED + +/* + * Consume input data and store it in the full-image sample buffer. + * We read as much as one fully interleaved MCU row ("iMCU" row) per call, + * ie, v_samp_factor rows for each component in the scan. + * Return value is JPEG_ROW_COMPLETED, JPEG_SCAN_COMPLETED, or JPEG_SUSPENDED. + */ + +METHODDEF(int) +consume_data (j_decompress_ptr cinfo) +{ + j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec; + d_diff_ptr diff = (d_diff_ptr) losslsd->diff_private; + /* JDIMENSION MCU_col_num; */ /* index of current MCU within row */ + /* JDIMENSION MCU_count; */ /* number of MCUs decoded */ + /* JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; */ + int comp, ci /* , yoffset, row, prev_row */; + JSAMPARRAY buffer[MAX_COMPS_IN_SCAN]; + jpeg_component_info *compptr; + + /* Align the virtual buffers for the components used in this scan. */ + for (comp = 0; comp < cinfo->comps_in_scan; comp++) { + compptr = cinfo->cur_comp_info[comp]; + ci = compptr->component_index; + buffer[ci] = (*cinfo->mem->access_virt_sarray) + ((j_common_ptr) cinfo, diff->whole_image[ci], + cinfo->input_iMCU_row * (JDIMENSION)compptr->v_samp_factor, + (JDIMENSION) compptr->v_samp_factor, TRUE); + } + + return decompress_data(cinfo, buffer); +} + + +/* + * Output some data from the full-image buffer sample in the multi-pass case. + * Always attempts to emit one fully interleaved MCU row ("iMCU" row). + * Return value is JPEG_ROW_COMPLETED, JPEG_SCAN_COMPLETED, or JPEG_SUSPENDED. + * + * NB: output_buf contains a plane for each component in image. + */ + +METHODDEF(int) +output_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf) +{ + j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec; + d_diff_ptr diff = (d_diff_ptr) losslsd->diff_private; + JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; + int ci, samp_rows, row; + JSAMPARRAY buffer; + jpeg_component_info *compptr; + + /* Force some input to be done if we are getting ahead of the input. */ + while (cinfo->input_scan_number < cinfo->output_scan_number || + (cinfo->input_scan_number == cinfo->output_scan_number && + cinfo->input_iMCU_row <= cinfo->output_iMCU_row)) { + if ((*cinfo->inputctl->consume_input)(cinfo) == JPEG_SUSPENDED) + return JPEG_SUSPENDED; + } + + /* OK, output from the virtual arrays. */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + /* Align the virtual buffer for this component. */ + buffer = (*cinfo->mem->access_virt_sarray) + ((j_common_ptr) cinfo, diff->whole_image[ci], + cinfo->output_iMCU_row * (JDIMENSION)compptr->v_samp_factor, + (JDIMENSION) compptr->v_samp_factor, FALSE); + + if (cinfo->output_iMCU_row < last_iMCU_row) + samp_rows = compptr->v_samp_factor; + else { + /* NB: can't use last_row_height here; it is input-side-dependent! */ + samp_rows = (int)compptr->height_in_data_units % compptr->v_samp_factor; + if (samp_rows == 0) samp_rows = compptr->v_samp_factor; + } + + for (row = 0; row < samp_rows; row++) { + MEMCOPY(output_buf[ci][row], buffer[row], + compptr->width_in_data_units * SIZEOF(JSAMPLE)); + } + } + + if (++(cinfo->output_iMCU_row) < cinfo->total_iMCU_rows) + return JPEG_ROW_COMPLETED; + return JPEG_SCAN_COMPLETED; +} + +#endif /* D_MULTISCAN_FILES_SUPPORTED */ + + +/* + * Initialize difference buffer controller. + */ + +GLOBAL(void) +jinit_d_diff_controller (j_decompress_ptr cinfo, boolean need_full_buffer) +{ + j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec; + d_diff_ptr diff; + int ci; + jpeg_component_info *compptr; + + diff = (d_diff_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(d_diff_controller)); + losslsd->diff_private = (void *) diff; + losslsd->diff_start_input_pass = start_input_pass; + losslsd->pub.start_output_pass = start_output_pass; + + /* Create the [un]difference buffers. */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + diff->diff_buf[ci] = (*cinfo->mem->alloc_darray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + (JDIMENSION) jround_up((long) compptr->width_in_data_units, + (long) compptr->h_samp_factor), + (JDIMENSION) compptr->v_samp_factor); + diff->undiff_buf[ci] = (*cinfo->mem->alloc_darray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + (JDIMENSION) jround_up((long) compptr->width_in_data_units, + (long) compptr->h_samp_factor), + (JDIMENSION) compptr->v_samp_factor); + } + + if (need_full_buffer) { +#ifdef D_MULTISCAN_FILES_SUPPORTED + /* Allocate a full-image virtual array for each component. */ + int access_rows; + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + access_rows = compptr->v_samp_factor; + diff->whole_image[ci] = (*cinfo->mem->request_virt_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE, + (JDIMENSION) jround_up((long) compptr->width_in_data_units, + (long) compptr->h_samp_factor), + (JDIMENSION) jround_up((long) compptr->height_in_data_units, + (long) compptr->v_samp_factor), + (JDIMENSION) access_rows); + } + losslsd->pub.consume_data = consume_data; + losslsd->pub.decompress_data = output_data; +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } else { + losslsd->pub.consume_data = dummy_consume_data; + losslsd->pub.decompress_data = decompress_data; + diff->whole_image[0] = NULL; /* flag for no virtual arrays */ + } +} + +#endif /* D_LOSSLESS_SUPPORTED */ diff --git a/dcmjpeg/libijg16/jdhuff.c b/dcmjpeg/libijg16/jdhuff.c new file mode 100644 index 00000000..f7194ba8 --- /dev/null +++ b/dcmjpeg/libijg16/jdhuff.c @@ -0,0 +1,316 @@ +/* + * jdhuff.c + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains Huffman entropy decoding routines which are shared + * by the sequential, progressive and lossless decoders. + */ + +#define JPEG_INTERNALS +#include "jinclude16.h" +#include "jpeglib16.h" +#include "jlossy16.h" /* Private declarations for lossy codec */ +#include "jlossls16.h" /* Private declarations for lossless codec */ +#include "jdhuff16.h" /* Declarations shared with jd*huff.c */ + + +/* + * Compute the derived values for a Huffman table. + * This routine also performs some validation checks on the table. + */ + +GLOBAL(void) +jpeg_make_d_derived_tbl (j_decompress_ptr cinfo, boolean isDC, int tblno, + d_derived_tbl ** pdtbl) +{ + JHUFF_TBL *htbl; + d_derived_tbl *dtbl; + int p, i, l, si, numsymbols; + int lookbits, ctr; + char huffsize[257]; + unsigned int huffcode[257]; + unsigned int code; + + /* Note that huffsize[] and huffcode[] are filled in code-length order, + * paralleling the order of the symbols themselves in htbl->huffval[]. + */ + + /* Find the input Huffman table */ + if (tblno < 0 || tblno >= NUM_HUFF_TBLS) + ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tblno); + htbl = + isDC ? cinfo->dc_huff_tbl_ptrs[tblno] : cinfo->ac_huff_tbl_ptrs[tblno]; + if (htbl == NULL) + ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tblno); + + /* Allocate a workspace if we haven't already done so. */ + if (*pdtbl == NULL) + *pdtbl = (d_derived_tbl *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(d_derived_tbl)); + dtbl = *pdtbl; + dtbl->pub = htbl; /* fill in back link */ + + /* Figure C.1: make table of Huffman code length for each symbol */ + + p = 0; + for (l = 1; l <= 16; l++) { + i = (int) htbl->bits[l]; + if (i < 0 || p + i > 256) /* protect against table overrun */ + ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); + while (i--) + huffsize[p++] = (char) l; + } + huffsize[p] = 0; + numsymbols = p; + + /* Figure C.2: generate the codes themselves */ + /* We also validate that the counts represent a legal Huffman code tree. */ + + code = 0; + si = huffsize[0]; + p = 0; + while (huffsize[p]) { + while (((int) huffsize[p]) == si) { + huffcode[p++] = code; + code++; + } + /* code is now 1 more than the last code used for codelength si; but + * it must still fit in si bits, since no code is allowed to be all ones. + * BUG FIX: Comparison must be >, not >= + */ + if (((IJG_INT32) code) > (((IJG_INT32) 1) << si)) + ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); + code <<= 1; + si++; + } + + /* Figure F.15: generate decoding tables for bit-sequential decoding */ + + p = 0; + for (l = 1; l <= 16; l++) { + if (htbl->bits[l]) { + /* valoffset[l] = huffval[] index of 1st symbol of code length l, + * minus the minimum code of length l + */ + dtbl->valoffset[l] = (IJG_INT32) p - (IJG_INT32) huffcode[p]; + p += htbl->bits[l]; + dtbl->maxcode[l] = (IJG_INT32)huffcode[p-1]; /* maximum code of length l */ + } else { + dtbl->maxcode[l] = -1; /* -1 if no codes of this length */ + } + } + dtbl->maxcode[17] = 0xFFFFFL; /* ensures jpeg_huff_decode terminates */ + + /* Compute lookahead tables to speed up decoding. + * First we set all the table entries to 0, indicating "too long"; + * then we iterate through the Huffman codes that are short enough and + * fill in all the entries that correspond to bit sequences starting + * with that code. + */ + + MEMZERO(dtbl->look_nbits, SIZEOF(dtbl->look_nbits)); + + p = 0; + for (l = 1; l <= HUFF_LOOKAHEAD; l++) { + for (i = 1; i <= (int) htbl->bits[l]; i++, p++) { + /* l = current code's length, p = its index in huffcode[] & huffval[]. */ + /* Generate left-justified code followed by all possible bit sequences */ + lookbits = (int)huffcode[p] << (HUFF_LOOKAHEAD-l); + for (ctr = 1 << (HUFF_LOOKAHEAD-l); ctr > 0; ctr--) { + dtbl->look_nbits[lookbits] = l; + dtbl->look_sym[lookbits] = htbl->huffval[p]; + lookbits++; + } + } + } + + /* Validate symbols as being reasonable. + * For AC tables, we make no check, but accept all byte values 0..255. + * For DC tables, we require the symbols to be in range 0..16. + * (Tighter bounds could be applied depending on the data depth and mode, + * but this is sufficient to ensure safe decoding.) + */ + if (isDC) { + for (i = 0; i < numsymbols; i++) { + int sym = htbl->huffval[i]; + if (sym < 0 || sym > 16) + ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); + } + } +} + + +/* + * Out-of-line code for bit fetching. + * See jdhuff.h for info about usage. + * Note: current values of get_buffer and bits_left are passed as parameters, + * but are returned in the corresponding fields of the state struct. + * + * On most machines MIN_GET_BITS should be 25 to allow the full 32-bit width + * of get_buffer to be used. (On machines with wider words, an even larger + * buffer could be used.) However, on some machines 32-bit shifts are + * quite slow and take time proportional to the number of places shifted. + * (This is true with most PC compilers, for instance.) In this case it may + * be a win to set MIN_GET_BITS to the minimum value of 15. This reduces the + * average shift distance at the cost of more calls to jpeg_fill_bit_buffer. + */ + +#ifdef SLOW_SHIFT_32 +#define MIN_GET_BITS 15 /* minimum allowable value */ +#else +#define MIN_GET_BITS (BIT_BUF_SIZE-7) +#endif + + +GLOBAL(boolean) +jpeg_fill_bit_buffer (bitread_working_state * state, + register bit_buf_type get_buffer, register int bits_left, + int nbits) +/* Load up the bit buffer to a depth of at least nbits */ +{ + /* Copy heavily used state fields into locals (hopefully registers) */ + register const JOCTET * next_input_byte = state->next_input_byte; + register size_t bytes_in_buffer = state->bytes_in_buffer; + j_decompress_ptr cinfo = state->cinfo; + + /* Attempt to load at least MIN_GET_BITS bits into get_buffer. */ + /* (It is assumed that no request will be for more than that many bits.) */ + /* We fail to do so only if we hit a marker or are forced to suspend. */ + + if (cinfo->unread_marker == 0) { /* cannot advance past a marker */ + while (bits_left < MIN_GET_BITS) { + register int c; + + /* Attempt to read a byte */ + if (bytes_in_buffer == 0) { + if (! (*cinfo->src->fill_input_buffer) (cinfo)) + return FALSE; + next_input_byte = cinfo->src->next_input_byte; + bytes_in_buffer = cinfo->src->bytes_in_buffer; + } + bytes_in_buffer--; + c = GETJOCTET(*next_input_byte++); + + /* If it's 0xFF, check and discard stuffed zero byte */ + if (c == 0xFF) { + /* Loop here to discard any padding FF's on terminating marker, + * so that we can save a valid unread_marker value. NOTE: we will + * accept multiple FF's followed by a 0 as meaning a single FF data + * byte. This data pattern is not valid according to the standard. + */ + do { + if (bytes_in_buffer == 0) { + if (! (*cinfo->src->fill_input_buffer) (cinfo)) + return FALSE; + next_input_byte = cinfo->src->next_input_byte; + bytes_in_buffer = cinfo->src->bytes_in_buffer; + } + bytes_in_buffer--; + c = GETJOCTET(*next_input_byte++); + } while (c == 0xFF); + + if (c == 0) { + /* Found FF/00, which represents an FF data byte */ + c = 0xFF; + } else { + /* Oops, it's actually a marker indicating end of compressed data. + * Save the marker code for later use. + * Fine point: it might appear that we should save the marker into + * bitread working state, not straight into permanent state. But + * once we have hit a marker, we cannot need to suspend within the + * current MCU, because we will read no more bytes from the data + * source. So it is OK to update permanent state right away. + */ + cinfo->unread_marker = c; + /* See if we need to insert some fake zero bits. */ + goto no_more_bytes; + } + } + + /* OK, load c into get_buffer */ + get_buffer = (get_buffer << 8) | c; + bits_left += 8; + } /* end while */ + } else { + no_more_bytes: + /* We get here if we've read the marker that terminates the compressed + * data segment. There should be enough bits in the buffer register + * to satisfy the request; if so, no problem. + */ + if (nbits > bits_left) { + /* Uh-oh. Report corrupted data to user and stuff zeroes into + * the data stream, so that we can produce some kind of image. + * We use a nonvolatile flag to ensure that only one warning message + * appears per data segment. + */ + huffd_common_ptr huffd; + if (cinfo->process == JPROC_LOSSLESS) + huffd = (huffd_common_ptr) ((j_lossless_d_ptr) cinfo->codec)->entropy_private; + else + huffd = (huffd_common_ptr) ((j_lossy_d_ptr) cinfo->codec)->entropy_private; + if (! huffd->insufficient_data) { + WARNMS(cinfo, JWRN_HIT_MARKER); + huffd->insufficient_data = TRUE; + } + /* Fill the buffer with zero bits */ + get_buffer <<= MIN_GET_BITS - bits_left; + bits_left = MIN_GET_BITS; + } + } + + /* Unload the local registers */ + state->next_input_byte = next_input_byte; + state->bytes_in_buffer = bytes_in_buffer; + state->get_buffer = get_buffer; + state->bits_left = bits_left; + + return TRUE; +} + + +/* + * Out-of-line code for Huffman code decoding. + * See jdhuff.h for info about usage. + */ + +GLOBAL(int) +jpeg_huff_decode (bitread_working_state * state, + register bit_buf_type get_buffer, register int bits_left, + d_derived_tbl * htbl, int min_bits) +{ + register int l = min_bits; + register IJG_INT32 code; + + /* HUFF_DECODE has determined that the code is at least min_bits */ + /* bits long, so fetch that many bits in one swoop. */ + + CHECK_BIT_BUFFER(*state, l, return -1); + code = GET_BITS(l); + + /* Collect the rest of the Huffman code one bit at a time. */ + /* This is per Figure F.16 in the JPEG spec. */ + + while (code > htbl->maxcode[l]) { + code <<= 1; + CHECK_BIT_BUFFER(*state, 1, return -1); + code |= GET_BITS(1); + l++; + } + + /* Unload the local registers */ + state->get_buffer = get_buffer; + state->bits_left = bits_left; + + /* With garbage input we may reach the sentinel value l = 17. */ + + if (l > 16) { + WARNMS(state->cinfo, JWRN_HUFF_BAD_CODE); + return 0; /* fake a zero as the safest result */ + } + + return htbl->pub->huffval[ (int) (code + htbl->valoffset[l]) ]; +} diff --git a/dcmjpeg/libijg16/jdhuff16.h b/dcmjpeg/libijg16/jdhuff16.h new file mode 100644 index 00000000..79cb24db --- /dev/null +++ b/dcmjpeg/libijg16/jdhuff16.h @@ -0,0 +1,229 @@ +/* + * jdhuff.h + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains declarations for Huffman entropy decoding routines + * that are shared between the sequential decoder (jdhuff.c), the + * progressive decoder (jdphuff.c) and the lossless decoder (jdlhuff.c). + * No other modules need to see these. + */ + +/* Short forms of external names for systems with brain-damaged linkers. */ + +#ifdef NEED_SHORT_EXTERNAL_NAMES +#define jpeg_make_d_derived_tbl jpeg16_make_d_derived_tbl +#define jpeg_fill_bit_buffer jpeg16_fill_bit_buffer +#define jpeg_huff_decode jpeg16_huff_decode +#endif /* NEED_SHORT_EXTERNAL_NAMES */ + + +/* Derived data constructed for each Huffman table */ + +#define HUFF_LOOKAHEAD 8 /* # of bits of lookahead */ + +typedef struct { + /* Basic tables: (element [0] of each array is unused) */ + IJG_INT32 maxcode[18]; /* largest code of length k (-1 if none) */ + /* (maxcode[17] is a sentinel to ensure jpeg_huff_decode terminates) */ + IJG_INT32 valoffset[17]; /* huffval[] offset for codes of length k */ + /* valoffset[k] = huffval[] index of 1st symbol of code length k, less + * the smallest code of length k; so given a code of length k, the + * corresponding symbol is huffval[code + valoffset[k]] + */ + + /* Link to public Huffman table (needed only in jpeg_huff_decode) */ + JHUFF_TBL *pub; + + /* Lookahead tables: indexed by the next HUFF_LOOKAHEAD bits of + * the input data stream. If the next Huffman code is no more + * than HUFF_LOOKAHEAD bits long, we can obtain its length and + * the corresponding symbol directly from these tables. + */ + int look_nbits[1< 32 bits on your machine, and shifting/masking longs is + * reasonably fast, making bit_buf_type be long and setting BIT_BUF_SIZE + * appropriately should be a win. Unfortunately we can't define the size + * with something like #define BIT_BUF_SIZE (sizeof(bit_buf_type)*8) + * because not all machines measure sizeof in 8-bit bytes. + */ + +typedef struct { /* Bitreading state saved across MCUs */ + bit_buf_type get_buffer; /* current bit-extraction buffer */ + int bits_left; /* # of unused bits in it */ +} bitread_perm_state; + +typedef struct { /* Bitreading working state within an MCU */ + /* Current data source location */ + /* We need a copy, rather than munging the original, in case of suspension */ + const JOCTET * next_input_byte; /* => next byte to read from source */ + size_t bytes_in_buffer; /* # of bytes remaining in source buffer */ + /* Bit input buffer --- note these values are kept in register variables, + * not in this struct, inside the inner loops. + */ + bit_buf_type get_buffer; /* current bit-extraction buffer */ + int bits_left; /* # of unused bits in it */ + /* Pointer needed by jpeg_fill_bit_buffer. */ + j_decompress_ptr cinfo; /* back link to decompress master record */ +} bitread_working_state; + +/* Macros to declare and load/save bitread local variables. */ +#define BITREAD_STATE_VARS \ + register bit_buf_type get_buffer; \ + register int bits_left; \ + bitread_working_state br_state + +#define BITREAD_LOAD_STATE(cinfop,permstate) \ + br_state.cinfo = cinfop; \ + br_state.next_input_byte = cinfop->src->next_input_byte; \ + br_state.bytes_in_buffer = cinfop->src->bytes_in_buffer; \ + get_buffer = permstate.get_buffer; \ + bits_left = permstate.bits_left; + +#define BITREAD_SAVE_STATE(cinfop,permstate) \ + cinfop->src->next_input_byte = br_state.next_input_byte; \ + cinfop->src->bytes_in_buffer = br_state.bytes_in_buffer; \ + permstate.get_buffer = get_buffer; \ + permstate.bits_left = bits_left + +/* + * These macros provide the in-line portion of bit fetching. + * Use CHECK_BIT_BUFFER to ensure there are N bits in get_buffer + * before using GET_BITS, PEEK_BITS, or DROP_BITS. + * The variables get_buffer and bits_left are assumed to be locals, + * but the state struct might not be (jpeg_huff_decode needs this). + * CHECK_BIT_BUFFER(state,n,action); + * Ensure there are N bits in get_buffer; if suspend, take action. + * val = GET_BITS(n); + * Fetch next N bits. + * val = PEEK_BITS(n); + * Fetch next N bits without removing them from the buffer. + * DROP_BITS(n); + * Discard next N bits. + * The value N should be a simple variable, not an expression, because it + * is evaluated multiple times. + */ + +#define CHECK_BIT_BUFFER(state,nbits,action) \ + { if (bits_left < (nbits)) { \ + if (! jpeg_fill_bit_buffer(&(state),get_buffer,bits_left,nbits)) \ + { action; } \ + get_buffer = (state).get_buffer; bits_left = (state).bits_left; } } + +#define GET_BITS(nbits) \ + (((int) (get_buffer >> (bits_left -= (nbits)))) & ((1<<(nbits))-1)) + +#define PEEK_BITS(nbits) \ + (((int) (get_buffer >> (bits_left - (nbits)))) & ((1<<(nbits))-1)) + +#define DROP_BITS(nbits) \ + (bits_left -= (nbits)) + +/* Load up the bit buffer to a depth of at least nbits */ +EXTERN(boolean) jpeg_fill_bit_buffer + JPP((bitread_working_state * state, register bit_buf_type get_buffer, + register int bits_left, int nbits)); + + +/* + * Code for extracting next Huffman-coded symbol from input bit stream. + * Again, this is time-critical and we make the main paths be macros. + * + * We use a lookahead table to process codes of up to HUFF_LOOKAHEAD bits + * without looping. Usually, more than 95% of the Huffman codes will be 8 + * or fewer bits long. The few overlength codes are handled with a loop, + * which need not be inline code. + * + * Notes about the HUFF_DECODE macro: + * 1. Near the end of the data segment, we may fail to get enough bits + * for a lookahead. In that case, we do it the hard way. + * 2. If the lookahead table contains no entry, the next code must be + * more than HUFF_LOOKAHEAD bits long. + * 3. jpeg_huff_decode returns -1 if forced to suspend. + */ + +#define HUFF_DECODE(result,state,htbl,failaction,slowlabel) \ +{ register int nb, look; \ + if (bits_left < HUFF_LOOKAHEAD) { \ + if (! jpeg_fill_bit_buffer(&state,get_buffer,bits_left, 0)) {failaction;} \ + get_buffer = state.get_buffer; bits_left = state.bits_left; \ + if (bits_left < HUFF_LOOKAHEAD) { \ + nb = 1; goto slowlabel; \ + } \ + } \ + look = PEEK_BITS(HUFF_LOOKAHEAD); \ + if ((nb = htbl->look_nbits[look]) != 0) { \ + DROP_BITS(nb); \ + result = htbl->look_sym[look]; \ + } else { \ + nb = HUFF_LOOKAHEAD+1; \ +slowlabel: \ + if ((result=jpeg_huff_decode(&state,get_buffer,bits_left,htbl,nb)) < 0) \ + { failaction; } \ + get_buffer = state.get_buffer; bits_left = state.bits_left; \ + } \ +} + +/* Out-of-line case for Huffman code fetching */ +EXTERN(int) jpeg_huff_decode + JPP((bitread_working_state * state, register bit_buf_type get_buffer, + register int bits_left, d_derived_tbl * htbl, int min_bits)); + + +/* Common fields between sequential, progressive and lossless Huffman entropy + * decoder master structs. + */ + +#define huffd_common_fields \ + boolean insufficient_data; /* set TRUE after emmitting warning */ \ + /* These fields are loaded into local variables at start of each MCU. \ + * In case of suspension, we exit WITHOUT updating them. \ + */ \ + bitread_perm_state bitstate /* Bit buffer at start of MCU */ + +/* Routines that are to be used by any or all of the entropy decoders are + * declared to receive a pointer to this structure. There are no actual + * instances of huffd_common_struct, only of shuff_entropy_decoder, + * phuff_entropy_decoder and lhuff_entropy_decoder. + */ +struct huffd_common_struct { + huffd_common_fields; /* Fields common to all decoder struct types */ + /* Additional fields follow in an actual shuff_entropy_decoder, + * phuff_entropy_decoder or lhuff_entropy_decoder struct. All four structs + * must agree on these initial fields! (This would be a lot cleaner in C++.) + */ +}; + +typedef struct huffd_common_struct * huffd_common_ptr; diff --git a/dcmjpeg/libijg16/jdinput.c b/dcmjpeg/libijg16/jdinput.c new file mode 100644 index 00000000..9de18b7d --- /dev/null +++ b/dcmjpeg/libijg16/jdinput.c @@ -0,0 +1,347 @@ +/* + * jdinput.c + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains input control logic for the JPEG decompressor. + * These routines are concerned with controlling the decompressor's input + * processing (marker reading and coefficient/difference decoding). + * The actual input reading is done in jdmarker.c, jdhuff.c, jdphuff.c, + * and jdlhuff.c. + */ + +#define JPEG_INTERNALS +#include "jinclude16.h" +#include "jpeglib16.h" + + +/* Private state */ + +typedef struct { + struct jpeg_input_controller pub; /* public fields */ + + boolean inheaders; /* TRUE until first SOS is reached */ +} my_input_controller; + +typedef my_input_controller * my_inputctl_ptr; + + +/* Forward declarations */ +METHODDEF(int) consume_markers JPP((j_decompress_ptr cinfo)); + + +/* + * Routines to calculate various quantities related to the size of the image. + */ + +LOCAL(void) +initial_setup (j_decompress_ptr cinfo) +/* Called once, when first SOS marker is reached */ +{ + int ci; + jpeg_component_info *compptr; + + /* Make sure image isn't bigger than I can handle */ + if ((long) cinfo->image_height > (long) JPEG_MAX_DIMENSION || + (long) cinfo->image_width > (long) JPEG_MAX_DIMENSION) + ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, (unsigned int) JPEG_MAX_DIMENSION); + + if (cinfo->process == JPROC_LOSSLESS) { + /* If precision > compiled-in value, we must downscale */ + if (cinfo->data_precision > BITS_IN_JSAMPLE) + WARNMS2(cinfo, JWRN_MUST_DOWNSCALE, + cinfo->data_precision, BITS_IN_JSAMPLE); + } + else { /* Lossy processes */ + /* For now, precision must match compiled-in value... */ + if (cinfo->data_precision != BITS_IN_JSAMPLE) + ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); + } + + /* Check that number of components won't exceed internal array sizes */ + if (cinfo->num_components > MAX_COMPONENTS) + ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components, + MAX_COMPONENTS); + + /* Compute maximum sampling factors; check factor validity */ + cinfo->max_h_samp_factor = 1; + cinfo->max_v_samp_factor = 1; + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + if (compptr->h_samp_factor<=0 || compptr->h_samp_factor>MAX_SAMP_FACTOR || + compptr->v_samp_factor<=0 || compptr->v_samp_factor>MAX_SAMP_FACTOR) + ERREXIT(cinfo, JERR_BAD_SAMPLING); + cinfo->max_h_samp_factor = MAX(cinfo->max_h_samp_factor, + compptr->h_samp_factor); + cinfo->max_v_samp_factor = MAX(cinfo->max_v_samp_factor, + compptr->v_samp_factor); + } + + /* We initialize codec_data_unit and min_codec_data_unit to data_unit. + * In the full decompressor, this will be overridden by jdmaster.c; + * but in the transcoder, jdmaster.c is not used, so we must do it here. + */ + cinfo->min_codec_data_unit = cinfo->data_unit; + + /* Compute dimensions of components */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + compptr->codec_data_unit = cinfo->data_unit; + /* Size in data units */ + compptr->width_in_data_units = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor, + (long) (cinfo->max_h_samp_factor * cinfo->data_unit)); + compptr->height_in_data_units = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor, + (long) (cinfo->max_v_samp_factor * cinfo->data_unit)); + /* downsampled_width and downsampled_height will also be overridden by + * jdmaster.c if we are doing full decompression. The transcoder library + * doesn't use these values, but the calling application might. + */ + /* Size in samples */ + compptr->downsampled_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor, + (long) cinfo->max_h_samp_factor); + compptr->downsampled_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor, + (long) cinfo->max_v_samp_factor); + /* Mark component needed, until color conversion says otherwise */ + compptr->component_needed = TRUE; + /* Mark no quantization table yet saved for component */ + compptr->quant_table = NULL; + } + + /* Compute number of fully interleaved MCU rows. */ + cinfo->total_iMCU_rows = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height, + (long) (cinfo->max_v_samp_factor*cinfo->data_unit)); + + /* Decide whether file contains multiple scans */ + if (cinfo->comps_in_scan < cinfo->num_components || + cinfo->process == JPROC_PROGRESSIVE) + cinfo->inputctl->has_multiple_scans = TRUE; + else + cinfo->inputctl->has_multiple_scans = FALSE; +} + + +LOCAL(void) +per_scan_setup (j_decompress_ptr cinfo) +/* Do computations that are needed before processing a JPEG scan */ +/* cinfo->comps_in_scan and cinfo->cur_comp_info[] were set from SOS marker */ +{ + int ci, mcublks, tmp; + jpeg_component_info *compptr; + + if (cinfo->comps_in_scan == 1) { + + /* Noninterleaved (single-component) scan */ + compptr = cinfo->cur_comp_info[0]; + + /* Overall image size in MCUs */ + cinfo->MCUs_per_row = compptr->width_in_data_units; + cinfo->MCU_rows_in_scan = compptr->height_in_data_units; + + /* For noninterleaved scan, always one data unit per MCU */ + compptr->MCU_width = 1; + compptr->MCU_height = 1; + compptr->MCU_data_units = 1; + compptr->MCU_sample_width = compptr->codec_data_unit; + compptr->last_col_width = 1; + /* For noninterleaved scans, it is convenient to define last_row_height + * as the number of data unit rows present in the last iMCU row. + */ + tmp = (int)compptr->height_in_data_units % compptr->v_samp_factor; + if (tmp == 0) tmp = compptr->v_samp_factor; + compptr->last_row_height = tmp; + + /* Prepare array describing MCU composition */ + cinfo->data_units_in_MCU = 1; + cinfo->MCU_membership[0] = 0; + + } else { + + /* Interleaved (multi-component) scan */ + if (cinfo->comps_in_scan <= 0 || cinfo->comps_in_scan > MAX_COMPS_IN_SCAN) + ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->comps_in_scan, + MAX_COMPS_IN_SCAN); + + /* Overall image size in MCUs */ + cinfo->MCUs_per_row = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width, + (long) (cinfo->max_h_samp_factor*cinfo->data_unit)); + cinfo->MCU_rows_in_scan = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height, + (long) (cinfo->max_v_samp_factor*cinfo->data_unit)); + + cinfo->data_units_in_MCU = 0; + + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + /* Sampling factors give # of data units of component in each MCU */ + compptr->MCU_width = compptr->h_samp_factor; + compptr->MCU_height = compptr->v_samp_factor; + compptr->MCU_data_units = compptr->MCU_width * compptr->MCU_height; + compptr->MCU_sample_width = compptr->MCU_width * compptr->codec_data_unit; + /* Figure number of non-dummy data units in last MCU column & row */ + tmp = (int)compptr->width_in_data_units % compptr->MCU_width; + if (tmp == 0) tmp = compptr->MCU_width; + compptr->last_col_width = tmp; + tmp = (int)compptr->height_in_data_units % compptr->MCU_height; + if (tmp == 0) tmp = compptr->MCU_height; + compptr->last_row_height = tmp; + /* Prepare array describing MCU composition */ + mcublks = compptr->MCU_data_units; + if (cinfo->data_units_in_MCU + mcublks > D_MAX_DATA_UNITS_IN_MCU) + ERREXIT(cinfo, JERR_BAD_MCU_SIZE); + while (mcublks-- > 0) { + cinfo->MCU_membership[cinfo->data_units_in_MCU++] = ci; + } + } + + } +} + + +/* + * Initialize the input modules to read a scan of compressed data. + * The first call to this is done by jdmaster.c after initializing + * the entire decompressor (during jpeg_start_decompress). + * Subsequent calls come from consume_markers, below. + */ + +METHODDEF(void) +start_input_pass (j_decompress_ptr cinfo) +{ + per_scan_setup(cinfo); + (*cinfo->codec->start_input_pass) (cinfo); + cinfo->inputctl->consume_input = cinfo->codec->consume_data; +} + + +/* + * Finish up after inputting a compressed-data scan. + * This is called by the coefficient controller after it's read all + * the expected data of the scan. + */ + +METHODDEF(void) +finish_input_pass (j_decompress_ptr cinfo) +{ + cinfo->inputctl->consume_input = consume_markers; +} + + +/* + * Read JPEG markers before, between, or after compressed-data scans. + * Change state as necessary when a new scan is reached. + * Return value is JPEG_SUSPENDED, JPEG_REACHED_SOS, or JPEG_REACHED_EOI. + * + * The consume_input method pointer points either here or to the + * coefficient controller's consume_data routine, depending on whether + * we are reading a compressed data segment or inter-segment markers. + */ + +METHODDEF(int) +consume_markers (j_decompress_ptr cinfo) +{ + my_inputctl_ptr inputctl = (my_inputctl_ptr) cinfo->inputctl; + int val; + + if (inputctl->pub.eoi_reached) /* After hitting EOI, read no further */ + return JPEG_REACHED_EOI; + + val = (*cinfo->marker->read_markers) (cinfo); + + switch (val) { + case JPEG_REACHED_SOS: /* Found SOS */ + if (inputctl->inheaders) { /* 1st SOS */ + initial_setup(cinfo); + /* + * Initialize the decompression codec. We need to do this here so that + * any codec-specific fields and function pointers are available to + * the rest of the library. + */ + jinit_d_codec(cinfo); + inputctl->inheaders = FALSE; + /* Note: start_input_pass must be called by jdmaster.c + * before any more input can be consumed. jdapimin.c is + * responsible for enforcing this sequencing. + */ + } else { /* 2nd or later SOS marker */ + if (! inputctl->pub.has_multiple_scans) + ERREXIT(cinfo, JERR_EOI_EXPECTED); /* Oops, I wasn't expecting this! */ + start_input_pass(cinfo); + } + break; + case JPEG_REACHED_EOI: /* Found EOI */ + inputctl->pub.eoi_reached = TRUE; + if (inputctl->inheaders) { /* Tables-only datastream, apparently */ + if (cinfo->marker->saw_SOF) + ERREXIT(cinfo, JERR_SOF_NO_SOS); + } else { + /* Prevent infinite loop in coef ctlr's decompress_data routine + * if user set output_scan_number larger than number of scans. + */ + if (cinfo->output_scan_number > cinfo->input_scan_number) + cinfo->output_scan_number = cinfo->input_scan_number; + } + break; + case JPEG_SUSPENDED: + break; + } + + return val; +} + + +/* + * Reset state to begin a fresh datastream. + */ + +METHODDEF(void) +reset_input_controller (j_decompress_ptr cinfo) +{ + my_inputctl_ptr inputctl = (my_inputctl_ptr) cinfo->inputctl; + + inputctl->pub.consume_input = consume_markers; + inputctl->pub.has_multiple_scans = FALSE; /* "unknown" would be better */ + inputctl->pub.eoi_reached = FALSE; + inputctl->inheaders = TRUE; + /* Reset other modules */ + (*cinfo->err->reset_error_mgr) ((j_common_ptr) cinfo); + (*cinfo->marker->reset_marker_reader) (cinfo); + /* Reset progression state -- would be cleaner if entropy decoder did this */ + cinfo->coef_bits = NULL; +} + + +/* + * Initialize the input controller module. + * This is called only once, when the decompression object is created. + */ + +GLOBAL(void) +jinit_input_controller (j_decompress_ptr cinfo) +{ + my_inputctl_ptr inputctl; + + /* Create subobject in permanent pool */ + inputctl = (my_inputctl_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, + SIZEOF(my_input_controller)); + cinfo->inputctl = (struct jpeg_input_controller *) inputctl; + /* Initialize method pointers */ + inputctl->pub.consume_input = consume_markers; + inputctl->pub.reset_input_controller = reset_input_controller; + inputctl->pub.start_input_pass = start_input_pass; + inputctl->pub.finish_input_pass = finish_input_pass; + /* Initialize state: can't use reset_input_controller since we don't + * want to try to reset other modules yet. + */ + inputctl->pub.has_multiple_scans = FALSE; /* "unknown" would be better */ + inputctl->pub.eoi_reached = FALSE; + inputctl->inheaders = TRUE; +} diff --git a/dcmjpeg/libijg16/jdlhuff.c b/dcmjpeg/libijg16/jdlhuff.c new file mode 100644 index 00000000..06797d88 --- /dev/null +++ b/dcmjpeg/libijg16/jdlhuff.c @@ -0,0 +1,291 @@ +/* + * jdlhuff.c + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains Huffman entropy decoding routines for lossless JPEG. + * + * Much of the complexity here has to do with supporting input suspension. + * If the data source module demands suspension, we want to be able to back + * up to the start of the current MCU. To do this, we copy state variables + * into local working storage, and update them back to the permanent + * storage only upon successful completion of an MCU. + */ + +#define JPEG_INTERNALS +#include "jinclude16.h" +#include "jpeglib16.h" +#include "jlossls16.h" /* Private declarations for lossless codec */ +#include "jdhuff16.h" /* Declarations shared with jd*huff.c */ + + +#ifdef D_LOSSLESS_SUPPORTED + +typedef struct { + int ci, yoffset, MCU_width; +} lhd_output_ptr_info; + +/* + * Private entropy decoder object for lossless Huffman decoding. + */ + +typedef struct { + huffd_common_fields; /* Fields shared with other entropy decoders */ + + /* Pointers to derived tables (these workspaces have image lifespan) */ + d_derived_tbl * derived_tbls[NUM_HUFF_TBLS]; + + /* Precalculated info set up by start_pass for use in decode_mcus: */ + + /* Pointers to derived tables to be used for each data unit within an MCU */ + d_derived_tbl * cur_tbls[D_MAX_DATA_UNITS_IN_MCU]; + + /* Pointers to the proper output difference row for each group of data units + * within an MCU. For each component, there are Vi groups of Hi data units. + */ + JDIFFROW output_ptr[D_MAX_DATA_UNITS_IN_MCU]; + + /* Number of output pointers in use for the current MCU. This is the sum + * of all Vi in the MCU. + */ + int num_output_ptrs; + + /* Information used for positioning the output pointers within the output + * difference rows. + */ + lhd_output_ptr_info output_ptr_info[D_MAX_DATA_UNITS_IN_MCU]; + + /* Index of the proper output pointer for each data unit within an MCU */ + int output_ptr_index[D_MAX_DATA_UNITS_IN_MCU]; + +} lhuff_entropy_decoder; + +typedef lhuff_entropy_decoder * lhuff_entropy_ptr; + + +/* + * Initialize for a Huffman-compressed scan. + */ + +METHODDEF(void) +start_pass_lhuff_decoder (j_decompress_ptr cinfo) +{ + j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec; + lhuff_entropy_ptr entropy = (lhuff_entropy_ptr) losslsd->entropy_private; + int ci, dctbl, sampn, ptrn, yoffset, xoffset; + jpeg_component_info * compptr; + + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + dctbl = compptr->dc_tbl_no; + /* Make sure requested tables are present */ + if (dctbl < 0 || dctbl >= NUM_HUFF_TBLS || + cinfo->dc_huff_tbl_ptrs[dctbl] == NULL) + ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, dctbl); + /* Compute derived values for Huffman tables */ + /* We may do this more than once for a table, but it's not expensive */ + jpeg_make_d_derived_tbl(cinfo, TRUE, dctbl, + & entropy->derived_tbls[dctbl]); + } + + /* Precalculate decoding info for each sample in an MCU of this scan */ + for (sampn = 0, ptrn = 0; sampn < cinfo->data_units_in_MCU;) { + compptr = cinfo->cur_comp_info[cinfo->MCU_membership[sampn]]; + ci = compptr->component_index; + for (yoffset = 0; yoffset < compptr->MCU_height; yoffset++, ptrn++) { + /* Precalculate the setup info for each output pointer */ + entropy->output_ptr_info[ptrn].ci = ci; + entropy->output_ptr_info[ptrn].yoffset = yoffset; + entropy->output_ptr_info[ptrn].MCU_width = compptr->MCU_width; + for (xoffset = 0; xoffset < compptr->MCU_width; xoffset++, sampn++) { + /* Precalculate the output pointer index for each sample */ + entropy->output_ptr_index[sampn] = ptrn; + /* Precalculate which table to use for each sample */ + entropy->cur_tbls[sampn] = entropy->derived_tbls[compptr->dc_tbl_no]; + } + } + } + entropy->num_output_ptrs = ptrn; + + /* Initialize bitread state variables */ + entropy->bitstate.bits_left = 0; + entropy->bitstate.get_buffer = 0; /* unnecessary, but keeps Purify quiet */ + entropy->insufficient_data = FALSE; +} + + +/* + * Figure F.12: extend sign bit. + * On some machines, a shift and add will be faster than a table lookup. + */ + +#ifdef AVOID_TABLES + +#define HUFF_EXTEND(x,s) ((x) < (1<<((s)-1)) ? (x) + (((-1)<<(s)) + 1) : (x)) + +#else + +#define HUFF_EXTEND(x,s) ((x) < extend_test[s] ? (x) + extend_offset[s] : (x)) + +static const int extend_test[16] = /* entry n is 2**(n-1) */ + { 0, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080, + 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000 }; + +static const int extend_offset[16] = /* entry n is (-1 << n) + 1 */ + { 0, ((-1)<<1) + 1, ((-1)<<2) + 1, ((-1)<<3) + 1, ((-1)<<4) + 1, + ((-1)<<5) + 1, ((-1)<<6) + 1, ((-1)<<7) + 1, ((-1)<<8) + 1, + ((-1)<<9) + 1, ((-1)<<10) + 1, ((-1)<<11) + 1, ((-1)<<12) + 1, + ((-1)<<13) + 1, ((-1)<<14) + 1, ((-1)<<15) + 1 }; + +#endif /* AVOID_TABLES */ + + +/* + * Check for a restart marker & resynchronize decoder. + * Returns FALSE if must suspend. + */ + +METHODDEF(boolean) +process_restart (j_decompress_ptr cinfo) +{ + j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec; + lhuff_entropy_ptr entropy = (lhuff_entropy_ptr) losslsd->entropy_private; + /* int ci; */ + + /* Throw away any unused bits remaining in bit buffer; */ + /* include any full bytes in next_marker's count of discarded bytes */ + cinfo->marker->discarded_bytes += (unsigned int)entropy->bitstate.bits_left / 8; + entropy->bitstate.bits_left = 0; + + /* Advance past the RSTn marker */ + if (! (*cinfo->marker->read_restart_marker) (cinfo)) + return FALSE; + + /* Reset out-of-data flag, unless read_restart_marker left us smack up + * against a marker. In that case we will end up treating the next data + * segment as empty, and we can avoid producing bogus output pixels by + * leaving the flag set. + */ + if (cinfo->unread_marker == 0) + entropy->insufficient_data = FALSE; + + return TRUE; +} + + +/* + * Decode and return nMCU's worth of Huffman-compressed differences. + * Each MCU is also disassembled and placed accordingly in diff_buf. + * + * MCU_col_num specifies the column of the first MCU being requested within + * the MCU-row. This tells us where to position the output row pointers in + * diff_buf. + * + * Returns the number of MCUs decoded. This may be less than nMCU if data + * source requested suspension. In that case no changes have been made to + * permanent state. (Exception: some output differences may already have + * been assigned. This is harmless for this module, since we'll just + * re-assign them on the next call.) + */ + +METHODDEF(JDIMENSION) +decode_mcus (j_decompress_ptr cinfo, JDIFFIMAGE diff_buf, + JDIMENSION MCU_row_num, JDIMENSION MCU_col_num, JDIMENSION nMCU) +{ + j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec; + lhuff_entropy_ptr entropy = (lhuff_entropy_ptr) losslsd->entropy_private; + unsigned int mcu_num; + int sampn, ci, yoffset, MCU_width, ptrn; + BITREAD_STATE_VARS; + + /* Set output pointer locations based on MCU_col_num */ + for (ptrn = 0; ptrn < entropy->num_output_ptrs; ptrn++) { + ci = entropy->output_ptr_info[ptrn].ci; + yoffset = entropy->output_ptr_info[ptrn].yoffset; + MCU_width = entropy->output_ptr_info[ptrn].MCU_width; + entropy->output_ptr[ptrn] = + diff_buf[ci][MCU_row_num + (JDIMENSION)yoffset] + MCU_col_num * (JDIMENSION)MCU_width; + } + + /* + * If we've run out of data, zero out the buffers and return. + * By resetting the undifferencer, the output samples will be CENTERJSAMPLE. + * + * NB: We should find a way to do this without interacting with the + * undifferencer module directly. + */ + if (entropy->insufficient_data) { + for (ptrn = 0; ptrn < entropy->num_output_ptrs; ptrn++) + jzero_far((void FAR *) entropy->output_ptr[ptrn], + nMCU * (size_t)entropy->output_ptr_info[ptrn].MCU_width * SIZEOF(JDIFF)); + + (*losslsd->predict_process_restart) (cinfo); + } + + else { + + /* Load up working state */ + BITREAD_LOAD_STATE(cinfo,entropy->bitstate); + + /* Outer loop handles the number of MCU requested */ + + for (mcu_num = 0; mcu_num < nMCU; mcu_num++) { + + /* Inner loop handles the samples in the MCU */ + for (sampn = 0; sampn < cinfo->data_units_in_MCU; sampn++) { + d_derived_tbl * dctbl = entropy->cur_tbls[sampn]; + register int s, r; + + /* Section H.2.2: decode the sample difference */ + HUFF_DECODE(s, br_state, dctbl, return mcu_num, label1); + if (s) { + if (s == 16) /* special case: always output 32768 */ + s = 32768; + else { /* normal case: fetch subsequent bits */ + CHECK_BIT_BUFFER(br_state, s, return mcu_num); + r = GET_BITS(s); + s = HUFF_EXTEND(r, s); + } + } + + /* Output the sample difference */ + *entropy->output_ptr[entropy->output_ptr_index[sampn]]++ = (JDIFF) s; + } + + /* Completed MCU, so update state */ + BITREAD_SAVE_STATE(cinfo,entropy->bitstate); + } + } + + return nMCU; +} + + +/* + * Module initialization routine for lossless Huffman entropy decoding. + */ + +GLOBAL(void) +jinit_lhuff_decoder (j_decompress_ptr cinfo) +{ + j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec; + lhuff_entropy_ptr entropy; + int i; + + entropy = (lhuff_entropy_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(lhuff_entropy_decoder)); + losslsd->entropy_private = (void *) entropy; + losslsd->entropy_start_pass = start_pass_lhuff_decoder; + losslsd->entropy_process_restart = process_restart; + losslsd->entropy_decode_mcus = decode_mcus; + + /* Mark tables unallocated */ + for (i = 0; i < NUM_HUFF_TBLS; i++) { + entropy->derived_tbls[i] = NULL; + } +} + +#endif /* D_LOSSLESS_SUPPORTED */ diff --git a/dcmjpeg/libijg16/jdlossls.c b/dcmjpeg/libijg16/jdlossls.c new file mode 100644 index 00000000..b311afaa --- /dev/null +++ b/dcmjpeg/libijg16/jdlossls.c @@ -0,0 +1,98 @@ +/* + * jdlossls.c + * + * Copyright (C) 1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains the control logic for the lossless JPEG decompressor. + */ + +#define JPEG_INTERNALS +#include "jinclude16.h" +#include "jpeglib16.h" +#include "jlossls16.h" + + +#ifdef D_LOSSLESS_SUPPORTED + +/* + * Compute output image dimensions and related values. + */ + +METHODDEF(void) +calc_output_dimensions (j_decompress_ptr cinfo) +{ + /* Hardwire it to "no scaling" */ + cinfo->output_width = cinfo->image_width; + cinfo->output_height = cinfo->image_height; + /* jdinput.c has already initialized codec_data_unit to 1, + * and has computed unscaled downsampled_width and downsampled_height. + */ +} + + +/* + * Initialize for an input processing pass. + */ + +METHODDEF(void) +start_input_pass (j_decompress_ptr cinfo) +{ + j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec; + + (*losslsd->entropy_start_pass) (cinfo); + (*losslsd->predict_start_pass) (cinfo); + (*losslsd->scaler_start_pass) (cinfo); + (*losslsd->diff_start_input_pass) (cinfo); +} + + +/* + * Initialize the lossless decompression codec. + * This is called only once, during master selection. + */ + +GLOBAL(void) +jinit_lossless_d_codec(j_decompress_ptr cinfo) +{ + j_lossless_d_ptr losslsd; + boolean use_c_buffer; + + /* Create subobject in permanent pool */ + losslsd = (j_lossless_d_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, + SIZEOF(jpeg_lossless_d_codec)); + cinfo->codec = (struct jpeg_d_codec *) losslsd; + + /* Initialize sub-modules */ + /* Entropy decoding: either Huffman or arithmetic coding. */ + if (cinfo->arith_code) { +#ifdef WITH_ARITHMETIC_PATCH + jinit_arith_decoder(cinfo); +#else + ERREXIT(cinfo, JERR_ARITH_NOTIMPL); +#endif + } else { + jinit_lhuff_decoder(cinfo); + } + + /* Undifferencer */ + jinit_undifferencer(cinfo); + + /* Scaler */ + jinit_d_scaler(cinfo); + + use_c_buffer = cinfo->inputctl->has_multiple_scans || cinfo->buffered_image; + jinit_d_diff_controller(cinfo, use_c_buffer); + + /* Initialize method pointers. + * + * Note: consume_data, start_output_pass and decompress_data are + * assigned in jddiffct.c. + */ + losslsd->pub.calc_output_dimensions = calc_output_dimensions; + losslsd->pub.start_input_pass = start_input_pass; +} + +#endif /* D_LOSSLESS_SUPPORTED */ diff --git a/dcmjpeg/libijg16/jdlossy.c b/dcmjpeg/libijg16/jdlossy.c new file mode 100644 index 00000000..a410e049 --- /dev/null +++ b/dcmjpeg/libijg16/jdlossy.c @@ -0,0 +1,232 @@ +/* + * jdlossy.c + * + * Copyright (C) 1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains the control logic for the lossy JPEG decompressor. + */ + +#define JPEG_INTERNALS +#include "jinclude16.h" +#include "jpeglib16.h" +#include "jlossy16.h" + + +/* + * Compute output image dimensions and related values. + */ + +METHODDEF(void) +calc_output_dimensions (j_decompress_ptr cinfo) +{ +#ifdef IDCT_SCALING_SUPPORTED + int ci; + jpeg_component_info *compptr; + + /* Compute actual output image dimensions and DCT scaling choices. */ + if (cinfo->scale_num * 8 <= cinfo->scale_denom) { + /* Provide 1/8 scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width, 8L); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height, 8L); + cinfo->min_codec_data_unit = 1; + } else if (cinfo->scale_num * 4 <= cinfo->scale_denom) { + /* Provide 1/4 scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width, 4L); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height, 4L); + cinfo->min_codec_data_unit = 2; + } else if (cinfo->scale_num * 2 <= cinfo->scale_denom) { + /* Provide 1/2 scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width, 2L); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height, 2L); + cinfo->min_codec_data_unit = 4; + } else { + /* Provide 1/1 scaling */ + cinfo->output_width = cinfo->image_width; + cinfo->output_height = cinfo->image_height; + cinfo->min_codec_data_unit = DCTSIZE; + } + /* In selecting the actual DCT scaling for each component, we try to + * scale up the chroma components via IDCT scaling rather than upsampling. + * This saves time if the upsampler gets to use 1:1 scaling. + * Note this code assumes that the supported DCT scalings are powers of 2. + */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + int ssize = cinfo->min_codec_data_unit; + while (ssize < DCTSIZE && + (compptr->h_samp_factor * ssize * 2 <= + cinfo->max_h_samp_factor * cinfo->min_codec_data_unit) && + (compptr->v_samp_factor * ssize * 2 <= + cinfo->max_v_samp_factor * cinfo->min_codec_data_unit)) { + ssize = ssize * 2; + } + compptr->codec_data_unit = ssize; + } + + /* Recompute downsampled dimensions of components; + * application needs to know these if using raw downsampled data. + */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + /* Size in samples, after IDCT scaling */ + compptr->downsampled_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * + (long) (compptr->h_samp_factor * compptr->codec_data_unit), + (long) (cinfo->max_h_samp_factor * DCTSIZE)); + compptr->downsampled_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * + (long) (compptr->v_samp_factor * compptr->codec_data_unit), + (long) (cinfo->max_v_samp_factor * DCTSIZE)); + } + +#else /* !IDCT_SCALING_SUPPORTED */ + + /* Hardwire it to "no scaling" */ + cinfo->output_width = cinfo->image_width; + cinfo->output_height = cinfo->image_height; + /* jdinput.c has already initialized codec_data_unit to DCTSIZE, + * and has computed unscaled downsampled_width and downsampled_height. + */ + +#endif /* IDCT_SCALING_SUPPORTED */ +} + + +/* + * Save away a copy of the Q-table referenced by each component present + * in the current scan, unless already saved during a prior scan. + * + * In a multiple-scan JPEG file, the encoder could assign different components + * the same Q-table slot number, but change table definitions between scans + * so that each component uses a different Q-table. (The IJG encoder is not + * currently capable of doing this, but other encoders might.) Since we want + * to be able to dequantize all the components at the end of the file, this + * means that we have to save away the table actually used for each component. + * We do this by copying the table at the start of the first scan containing + * the component. + * The JPEG spec prohibits the encoder from changing the contents of a Q-table + * slot between scans of a component using that slot. If the encoder does so + * anyway, this decoder will simply use the Q-table values that were current + * at the start of the first scan for the component. + * + * The decompressor output side looks only at the saved quant tables, + * not at the current Q-table slots. + */ + +LOCAL(void) +latch_quant_tables (j_decompress_ptr cinfo) +{ + int ci, qtblno; + jpeg_component_info *compptr; + JQUANT_TBL * qtbl; + + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + /* No work if we already saved Q-table for this component */ + if (compptr->quant_table != NULL) + continue; + /* Make sure specified quantization table is present */ + qtblno = compptr->quant_tbl_no; + if (qtblno < 0 || qtblno >= NUM_QUANT_TBLS || + cinfo->quant_tbl_ptrs[qtblno] == NULL) + ERREXIT1(cinfo, JERR_NO_QUANT_TABLE, qtblno); + /* OK, save away the quantization table */ + qtbl = (JQUANT_TBL *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(JQUANT_TBL)); + MEMCOPY(qtbl, cinfo->quant_tbl_ptrs[qtblno], SIZEOF(JQUANT_TBL)); + compptr->quant_table = qtbl; + } +} + + +/* + * Initialize for an input processing pass. + */ + +METHODDEF(void) +start_input_pass (j_decompress_ptr cinfo) +{ + j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec; + + latch_quant_tables(cinfo); + (*lossyd->entropy_start_pass) (cinfo); + (*lossyd->coef_start_input_pass) (cinfo); +} + + +/* + * Initialize for an output processing pass. + */ + +METHODDEF(void) +start_output_pass (j_decompress_ptr cinfo) +{ + j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec; + + (*lossyd->idct_start_pass) (cinfo); + (*lossyd->coef_start_output_pass) (cinfo); +} + +/* + * Initialize the lossy decompression codec. + * This is called only once, during master selection. + */ + +GLOBAL(void) +jinit_lossy_d_codec (j_decompress_ptr cinfo) +{ + j_lossy_d_ptr lossyd; + boolean use_c_buffer; + + /* Create subobject in permanent pool */ + lossyd = (j_lossy_d_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, + SIZEOF(jpeg_lossy_d_codec)); + cinfo->codec = (struct jpeg_d_codec *) lossyd; + + /* Initialize sub-modules */ + + /* Inverse DCT */ + jinit_inverse_dct(cinfo); + /* Entropy decoding: either Huffman or arithmetic coding. */ + if (cinfo->arith_code) { +#ifdef WITH_ARITHMETIC_PATCH + jinit_arith_decoder(cinfo); +#else + ERREXIT(cinfo, JERR_ARITH_NOTIMPL); +#endif + } else { + if (cinfo->process == JPROC_PROGRESSIVE) { +#ifdef D_PROGRESSIVE_SUPPORTED + jinit_phuff_decoder(cinfo); +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } else + jinit_shuff_decoder(cinfo); + } + + use_c_buffer = cinfo->inputctl->has_multiple_scans || cinfo->buffered_image; + jinit_d_coef_controller(cinfo, use_c_buffer); + + /* Initialize method pointers. + * + * Note: consume_data and decompress_data are assigned in jdcoefct.c. + */ + lossyd->pub.calc_output_dimensions = calc_output_dimensions; + lossyd->pub.start_input_pass = start_input_pass; + lossyd->pub.start_output_pass = start_output_pass; +} + + + + diff --git a/dcmjpeg/libijg16/jdmainct.c b/dcmjpeg/libijg16/jdmainct.c new file mode 100644 index 00000000..78329021 --- /dev/null +++ b/dcmjpeg/libijg16/jdmainct.c @@ -0,0 +1,512 @@ +/* + * jdmainct.c + * + * Copyright (C) 1994-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains the main buffer controller for decompression. + * The main buffer lies between the JPEG decompressor proper and the + * post-processor; it holds downsampled data in the JPEG colorspace. + * + * Note that this code is bypassed in raw-data mode, since the application + * supplies the equivalent of the main buffer in that case. + */ + +#define JPEG_INTERNALS +#include "jinclude16.h" +#include "jpeglib16.h" + + +/* + * In the current system design, the main buffer need never be a full-image + * buffer; any full-height buffers will be found inside the coefficient or + * postprocessing controllers. Nonetheless, the main controller is not + * trivial. Its responsibility is to provide context rows for upsampling/ + * rescaling, and doing this in an efficient fashion is a bit tricky. + * + * Postprocessor input data is counted in "row groups". A row group + * is defined to be (v_samp_factor * codec_data_unit / min_codec_data_unit) + * sample rows of each component. (We require codec_data_unit values to be + * chosen such that these numbers are integers. In practice codec_data_unit + * values will likely be powers of two, so we actually have the stronger + * condition that codec_data_unit / min_codec_data_unit is an integer.) + * Upsampling will typically produce max_v_samp_factor pixel rows from each + * row group (times any additional scale factor that the upsampler is + * applying). + * + * The decompression codec will deliver data to us one iMCU row at a time; + * each iMCU row contains v_samp_factor * codec_data_unit sample rows, or + * exactly min_codec_data_unit row groups. (This amount of data corresponds + * to one row of MCUs when the image is fully interleaved.) Note that the + * number of sample rows varies across components, but the number of row + * groups does not. Some garbage sample rows may be included in the last iMCU + * row at the bottom of the image. + * + * Depending on the vertical scaling algorithm used, the upsampler may need + * access to the sample row(s) above and below its current input row group. + * The upsampler is required to set need_context_rows TRUE at global selection + * time if so. When need_context_rows is FALSE, this controller can simply + * obtain one iMCU row at a time from the coefficient controller and dole it + * out as row groups to the postprocessor. + * + * When need_context_rows is TRUE, this controller guarantees that the buffer + * passed to postprocessing contains at least one row group's worth of samples + * above and below the row group(s) being processed. Note that the context + * rows "above" the first passed row group appear at negative row offsets in + * the passed buffer. At the top and bottom of the image, the required + * context rows are manufactured by duplicating the first or last real sample + * row; this avoids having special cases in the upsampling inner loops. + * + * The amount of context is fixed at one row group just because that's a + * convenient number for this controller to work with. The existing + * upsamplers really only need one sample row of context. An upsampler + * supporting arbitrary output rescaling might wish for more than one row + * group of context when shrinking the image; tough, we don't handle that. + * (This is justified by the assumption that downsizing will be handled mostly + * by adjusting the codec_data_unit values, so that the actual scale factor at + * the upsample step needn't be much less than one.) + * + * To provide the desired context, we have to retain the last two row groups + * of one iMCU row while reading in the next iMCU row. (The last row group + * can't be processed until we have another row group for its below-context, + * and so we have to save the next-to-last group too for its above-context.) + * We could do this most simply by copying data around in our buffer, but + * that'd be very slow. We can avoid copying any data by creating a rather + * strange pointer structure. Here's how it works. We allocate a workspace + * consisting of M+2 row groups (where M = min_codec_data_unit is the number + * of row groups per iMCU row). We create two sets of redundant pointers to + * the workspace. Labeling the physical row groups 0 to M+1, the synthesized + * pointer lists look like this: + * M+1 M-1 + * master pointer --> 0 master pointer --> 0 + * 1 1 + * ... ... + * M-3 M-3 + * M-2 M + * M-1 M+1 + * M M-2 + * M+1 M-1 + * 0 0 + * We read alternate iMCU rows using each master pointer; thus the last two + * row groups of the previous iMCU row remain un-overwritten in the workspace. + * The pointer lists are set up so that the required context rows appear to + * be adjacent to the proper places when we pass the pointer lists to the + * upsampler. + * + * The above pictures describe the normal state of the pointer lists. + * At top and bottom of the image, we diddle the pointer lists to duplicate + * the first or last sample row as necessary (this is cheaper than copying + * sample rows around). + * + * This scheme breaks down if M < 2, ie, min_codec_data_unit is 1. In that + * situation each iMCU row provides only one row group so the buffering logic + * must be different (eg, we must read two iMCU rows before we can emit the + * first row group). For now, we simply do not support providing context + * rows when min_codec_data_unit is 1. That combination seems unlikely to + * be worth providing --- if someone wants a 1/8th-size preview, they probably + * want it quick and dirty, so a context-free upsampler is sufficient. + */ + + +/* Private buffer controller object */ + +typedef struct { + struct jpeg_d_main_controller pub; /* public fields */ + + /* Pointer to allocated workspace (M or M+2 row groups). */ + JSAMPARRAY buffer[MAX_COMPONENTS]; + + boolean buffer_full; /* Have we gotten an iMCU row from decoder? */ + JDIMENSION rowgroup_ctr; /* counts row groups output to postprocessor */ + + /* Remaining fields are only used in the context case. */ + + /* These are the master pointers to the funny-order pointer lists. */ + JSAMPIMAGE xbuffer[2]; /* pointers to weird pointer lists */ + + int whichptr; /* indicates which pointer set is now in use */ + int context_state; /* process_data state machine status */ + JDIMENSION rowgroups_avail; /* row groups available to postprocessor */ + JDIMENSION iMCU_row_ctr; /* counts iMCU rows to detect image top/bot */ +} my_main_controller; + +typedef my_main_controller * my_main_ptr; + +/* context_state values: */ +#define CTX_PREPARE_FOR_IMCU 0 /* need to prepare for MCU row */ +#define CTX_PROCESS_IMCU 1 /* feeding iMCU to postprocessor */ +#define CTX_POSTPONED_ROW 2 /* feeding postponed row group */ + + +/* Forward declarations */ +METHODDEF(void) process_data_simple_main + JPP((j_decompress_ptr cinfo, JSAMPARRAY output_buf, + JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail)); +METHODDEF(void) process_data_context_main + JPP((j_decompress_ptr cinfo, JSAMPARRAY output_buf, + JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail)); +#ifdef QUANT_2PASS_SUPPORTED +METHODDEF(void) process_data_crank_post + JPP((j_decompress_ptr cinfo, JSAMPARRAY output_buf, + JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail)); +#endif + + +LOCAL(void) +alloc_funny_pointers (j_decompress_ptr cinfo) +/* Allocate space for the funny pointer lists. + * This is done only once, not once per pass. + */ +{ + my_main_ptr mymain = (my_main_ptr) cinfo->main; + int ci, rgroup; + int M = cinfo->min_codec_data_unit; + jpeg_component_info *compptr; + JSAMPARRAY xbuf; + + /* Get top-level space for component array pointers. + * We alloc both arrays with one call to save a few cycles. + */ + mymain->xbuffer[0] = (JSAMPIMAGE) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (size_t)cinfo->num_components * 2 * SIZEOF(JSAMPARRAY)); + mymain->xbuffer[1] = mymain->xbuffer[0] + cinfo->num_components; + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + rgroup = (compptr->v_samp_factor * compptr->codec_data_unit) / + cinfo->min_codec_data_unit; /* height of a row group of component */ + /* Get space for pointer lists --- M+4 row groups in each list. + * We alloc both pointer lists with one call to save a few cycles. + */ + xbuf = (JSAMPARRAY) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + 2 * (size_t)(rgroup * (M + 4)) * SIZEOF(JSAMPROW)); + xbuf += rgroup; /* want one row group at negative offsets */ + mymain->xbuffer[0][ci] = xbuf; + xbuf += rgroup * (M + 4); + mymain->xbuffer[1][ci] = xbuf; + } +} + + +LOCAL(void) +make_funny_pointers (j_decompress_ptr cinfo) +/* Create the funny pointer lists discussed in the comments above. + * The actual workspace is already allocated (in main->buffer), + * and the space for the pointer lists is allocated too. + * This routine just fills in the curiously ordered lists. + * This will be repeated at the beginning of each pass. + */ +{ + my_main_ptr mymain = (my_main_ptr) cinfo->main; + int ci, i, rgroup; + int M = cinfo->min_codec_data_unit; + jpeg_component_info *compptr; + JSAMPARRAY buf, xbuf0, xbuf1; + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + rgroup = (compptr->v_samp_factor * compptr->codec_data_unit) / + cinfo->min_codec_data_unit; /* height of a row group of component */ + xbuf0 = mymain->xbuffer[0][ci]; + xbuf1 = mymain->xbuffer[1][ci]; + /* First copy the workspace pointers as-is */ + buf = mymain->buffer[ci]; + for (i = 0; i < rgroup * (M + 2); i++) { + xbuf0[i] = xbuf1[i] = buf[i]; + } + /* In the second list, put the last four row groups in swapped order */ + for (i = 0; i < rgroup * 2; i++) { + xbuf1[rgroup*(M-2) + i] = buf[rgroup*M + i]; + xbuf1[rgroup*M + i] = buf[rgroup*(M-2) + i]; + } + /* The wraparound pointers at top and bottom will be filled later + * (see set_wraparound_pointers, below). Initially we want the "above" + * pointers to duplicate the first actual data line. This only needs + * to happen in xbuffer[0]. + */ + for (i = 0; i < rgroup; i++) { + xbuf0[i - rgroup] = xbuf0[0]; + } + } +} + + +LOCAL(void) +set_wraparound_pointers (j_decompress_ptr cinfo) +/* Set up the "wraparound" pointers at top and bottom of the pointer lists. + * This changes the pointer list state from top-of-image to the normal state. + */ +{ + my_main_ptr mymain = (my_main_ptr) cinfo->main; + int ci, i, rgroup; + int M = cinfo->min_codec_data_unit; + jpeg_component_info *compptr; + JSAMPARRAY xbuf0, xbuf1; + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + rgroup = (compptr->v_samp_factor * compptr->codec_data_unit) / + cinfo->min_codec_data_unit; /* height of a row group of component */ + xbuf0 = mymain->xbuffer[0][ci]; + xbuf1 = mymain->xbuffer[1][ci]; + for (i = 0; i < rgroup; i++) { + xbuf0[i - rgroup] = xbuf0[rgroup*(M+1) + i]; + xbuf1[i - rgroup] = xbuf1[rgroup*(M+1) + i]; + xbuf0[rgroup*(M+2) + i] = xbuf0[i]; + xbuf1[rgroup*(M+2) + i] = xbuf1[i]; + } + } +} + + +LOCAL(void) +set_bottom_pointers (j_decompress_ptr cinfo) +/* Change the pointer lists to duplicate the last sample row at the bottom + * of the image. whichptr indicates which xbuffer holds the final iMCU row. + * Also sets rowgroups_avail to indicate number of nondummy row groups in row. + */ +{ + my_main_ptr mymain = (my_main_ptr) cinfo->main; + int ci, i, rgroup, iMCUheight, rows_left; + jpeg_component_info *compptr; + JSAMPARRAY xbuf; + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + /* Count sample rows in one iMCU row and in one row group */ + iMCUheight = compptr->v_samp_factor * compptr->codec_data_unit; + rgroup = iMCUheight / cinfo->min_codec_data_unit; + /* Count nondummy sample rows remaining for this component */ + rows_left = (int) (compptr->downsampled_height % (JDIMENSION) iMCUheight); + if (rows_left == 0) rows_left = iMCUheight; + /* Count nondummy row groups. Should get same answer for each component, + * so we need only do it once. + */ + if (ci == 0) { + mymain->rowgroups_avail = (JDIMENSION) ((rows_left-1) / rgroup + 1); + } + /* Duplicate the last real sample row rgroup*2 times; this pads out the + * last partial rowgroup and ensures at least one full rowgroup of context. + */ + xbuf = mymain->xbuffer[mymain->whichptr][ci]; + for (i = 0; i < rgroup * 2; i++) { + xbuf[rows_left + i] = xbuf[rows_left-1]; + } + } +} + + +/* + * Initialize for a processing pass. + */ + +METHODDEF(void) +start_pass_main (j_decompress_ptr cinfo, J_BUF_MODE pass_mode) +{ + my_main_ptr mymain = (my_main_ptr) cinfo->main; + + switch (pass_mode) { + case JBUF_PASS_THRU: + if (cinfo->upsample->need_context_rows) { + mymain->pub.process_data = process_data_context_main; + make_funny_pointers(cinfo); /* Create the xbuffer[] lists */ + mymain->whichptr = 0; /* Read first iMCU row into xbuffer[0] */ + mymain->context_state = CTX_PREPARE_FOR_IMCU; + mymain->iMCU_row_ctr = 0; + } else { + /* Simple case with no context needed */ + mymain->pub.process_data = process_data_simple_main; + } + mymain->buffer_full = FALSE; /* Mark buffer empty */ + mymain->rowgroup_ctr = 0; + break; +#ifdef QUANT_2PASS_SUPPORTED + case JBUF_CRANK_DEST: + /* For last pass of 2-pass quantization, just crank the postprocessor */ + mymain->pub.process_data = process_data_crank_post; + break; +#endif + default: + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + break; + } +} + + +/* + * Process some data. + * This handles the simple case where no context is required. + */ + +METHODDEF(void) +process_data_simple_main (j_decompress_ptr cinfo, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail) +{ + my_main_ptr mymain = (my_main_ptr) cinfo->main; + JDIMENSION rowgroups_avail; + + /* Read input data if we haven't filled the main buffer yet */ + if (! mymain->buffer_full) { + if (! (*cinfo->codec->decompress_data) (cinfo, mymain->buffer)) + return; /* suspension forced, can do nothing more */ + mymain->buffer_full = TRUE; /* OK, we have an iMCU row to work with */ + } + + /* There are always min_codec_data_unit row groups in an iMCU row. */ + rowgroups_avail = (JDIMENSION) cinfo->min_codec_data_unit; + /* Note: at the bottom of the image, we may pass extra garbage row groups + * to the postprocessor. The postprocessor has to check for bottom + * of image anyway (at row resolution), so no point in us doing it too. + */ + + /* Feed the postprocessor */ + (*cinfo->post->post_process_data) (cinfo, mymain->buffer, + &mymain->rowgroup_ctr, rowgroups_avail, + output_buf, out_row_ctr, out_rows_avail); + + /* Has postprocessor consumed all the data yet? If so, mark buffer empty */ + if (mymain->rowgroup_ctr >= rowgroups_avail) { + mymain->buffer_full = FALSE; + mymain->rowgroup_ctr = 0; + } +} + + +/* + * Process some data. + * This handles the case where context rows must be provided. + */ + +METHODDEF(void) +process_data_context_main (j_decompress_ptr cinfo, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail) +{ + my_main_ptr mymain = (my_main_ptr) cinfo->main; + + /* Read input data if we haven't filled the main buffer yet */ + if (! mymain->buffer_full) { + if (! (*cinfo->codec->decompress_data) (cinfo, + mymain->xbuffer[mymain->whichptr])) + return; /* suspension forced, can do nothing more */ + mymain->buffer_full = TRUE; /* OK, we have an iMCU row to work with */ + mymain->iMCU_row_ctr++; /* count rows received */ + } + + /* Postprocessor typically will not swallow all the input data it is handed + * in one call (due to filling the output buffer first). Must be prepared + * to exit and restart. This switch lets us keep track of how far we got. + * Note that each case falls through to the next on successful completion. + */ + switch (mymain->context_state) { + case CTX_POSTPONED_ROW: + /* Call postprocessor using previously set pointers for postponed row */ + (*cinfo->post->post_process_data) (cinfo, mymain->xbuffer[mymain->whichptr], + &mymain->rowgroup_ctr, mymain->rowgroups_avail, + output_buf, out_row_ctr, out_rows_avail); + if (mymain->rowgroup_ctr < mymain->rowgroups_avail) + return; /* Need to suspend */ + mymain->context_state = CTX_PREPARE_FOR_IMCU; + if (*out_row_ctr >= out_rows_avail) + return; /* Postprocessor exactly filled output buf */ + /*FALLTHROUGH*/ + case CTX_PREPARE_FOR_IMCU: + /* Prepare to process first M-1 row groups of this iMCU row */ + mymain->rowgroup_ctr = 0; + mymain->rowgroups_avail = (JDIMENSION) (cinfo->min_codec_data_unit - 1); + /* Check for bottom of image: if so, tweak pointers to "duplicate" + * the last sample row, and adjust rowgroups_avail to ignore padding rows. + */ + if (mymain->iMCU_row_ctr == cinfo->total_iMCU_rows) + set_bottom_pointers(cinfo); + mymain->context_state = CTX_PROCESS_IMCU; + /*FALLTHROUGH*/ + case CTX_PROCESS_IMCU: + /* Call postprocessor using previously set pointers */ + (*cinfo->post->post_process_data) (cinfo, mymain->xbuffer[mymain->whichptr], + &mymain->rowgroup_ctr, mymain->rowgroups_avail, + output_buf, out_row_ctr, out_rows_avail); + if (mymain->rowgroup_ctr < mymain->rowgroups_avail) + return; /* Need to suspend */ + /* After the first iMCU, change wraparound pointers to normal state */ + if (mymain->iMCU_row_ctr == 1) + set_wraparound_pointers(cinfo); + /* Prepare to load new iMCU row using other xbuffer list */ + mymain->whichptr ^= 1; /* 0=>1 or 1=>0 */ + mymain->buffer_full = FALSE; + /* Still need to process last row group of this iMCU row, */ + /* which is saved at index M+1 of the other xbuffer */ + mymain->rowgroup_ctr = (JDIMENSION) (cinfo->min_codec_data_unit + 1); + mymain->rowgroups_avail = (JDIMENSION) (cinfo->min_codec_data_unit + 2); + mymain->context_state = CTX_POSTPONED_ROW; + } +} + + +/* + * Process some data. + * Final pass of two-pass quantization: just call the postprocessor. + * Source data will be the postprocessor controller's internal buffer. + */ + +#ifdef QUANT_2PASS_SUPPORTED + +METHODDEF(void) +process_data_crank_post (j_decompress_ptr cinfo, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail) +{ + (*cinfo->post->post_process_data) (cinfo, (JSAMPIMAGE) NULL, + (JDIMENSION *) NULL, (JDIMENSION) 0, + output_buf, out_row_ctr, out_rows_avail); +} + +#endif /* QUANT_2PASS_SUPPORTED */ + + +/* + * Initialize main buffer controller. + */ + +GLOBAL(void) +jinit_d_main_controller (j_decompress_ptr cinfo, boolean need_full_buffer) +{ + my_main_ptr mymain; + int ci, rgroup, ngroups; + jpeg_component_info *compptr; + + mymain = (my_main_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_main_controller)); + cinfo->main = (struct jpeg_d_main_controller *) mymain; + mymain->pub.start_pass = start_pass_main; + + if (need_full_buffer) /* shouldn't happen */ + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + + /* Allocate the workspace. + * ngroups is the number of row groups we need. + */ + if (cinfo->upsample->need_context_rows) { + if (cinfo->min_codec_data_unit < 2) /* unsupported, see comments above */ + ERREXIT(cinfo, JERR_NOTIMPL); + alloc_funny_pointers(cinfo); /* Alloc space for xbuffer[] lists */ + ngroups = cinfo->min_codec_data_unit + 2; + } else { + ngroups = cinfo->min_codec_data_unit; + } + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + rgroup = (compptr->v_samp_factor * compptr->codec_data_unit) / + cinfo->min_codec_data_unit; /* height of a row group of component */ + mymain->buffer[ci] = (*cinfo->mem->alloc_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + compptr->width_in_data_units * (JDIMENSION) compptr->codec_data_unit, + (JDIMENSION) (rgroup * ngroups)); + } +} diff --git a/dcmjpeg/libijg16/jdmarker.c b/dcmjpeg/libijg16/jdmarker.c new file mode 100644 index 00000000..6daa28a2 --- /dev/null +++ b/dcmjpeg/libijg16/jdmarker.c @@ -0,0 +1,1370 @@ +/* + * jdmarker.c + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains routines to decode JPEG datastream markers. + * Most of the complexity arises from our desire to support input + * suspension: if not all of the data for a marker is available, + * we must exit back to the application. On resumption, we reprocess + * the marker. + */ + +#define JPEG_INTERNALS +#include "jinclude16.h" +#include "jpeglib16.h" + + +typedef enum { /* JPEG marker codes */ + M_SOF0 = 0xc0, + M_SOF1 = 0xc1, + M_SOF2 = 0xc2, + M_SOF3 = 0xc3, + + M_SOF5 = 0xc5, + M_SOF6 = 0xc6, + M_SOF7 = 0xc7, + + M_JPG = 0xc8, + M_SOF9 = 0xc9, + M_SOF10 = 0xca, + M_SOF11 = 0xcb, + + M_SOF13 = 0xcd, + M_SOF14 = 0xce, + M_SOF15 = 0xcf, + + M_DHT = 0xc4, + + M_DAC = 0xcc, + + M_RST0 = 0xd0, + M_RST1 = 0xd1, + M_RST2 = 0xd2, + M_RST3 = 0xd3, + M_RST4 = 0xd4, + M_RST5 = 0xd5, + M_RST6 = 0xd6, + M_RST7 = 0xd7, + + M_SOI = 0xd8, + M_EOI = 0xd9, + M_SOS = 0xda, + M_DQT = 0xdb, + M_DNL = 0xdc, + M_DRI = 0xdd, + M_DHP = 0xde, + M_EXP = 0xdf, + + M_APP0 = 0xe0, + M_APP1 = 0xe1, + M_APP2 = 0xe2, + M_APP3 = 0xe3, + M_APP4 = 0xe4, + M_APP5 = 0xe5, + M_APP6 = 0xe6, + M_APP7 = 0xe7, + M_APP8 = 0xe8, + M_APP9 = 0xe9, + M_APP10 = 0xea, + M_APP11 = 0xeb, + M_APP12 = 0xec, + M_APP13 = 0xed, + M_APP14 = 0xee, + M_APP15 = 0xef, + + M_JPG0 = 0xf0, + M_JPG13 = 0xfd, + M_COM = 0xfe, + + M_TEM = 0x01, + + M_ERROR = 0x100 +} JPEG_MARKER; + + +/* Private state */ + +typedef struct { + struct jpeg_marker_reader pub; /* public fields */ + + /* Application-overridable marker processing methods */ + jpeg_marker_parser_method process_COM; + jpeg_marker_parser_method process_APPn[16]; + + /* Limit on marker data length to save for each marker type */ + unsigned int length_limit_COM; + unsigned int length_limit_APPn[16]; + + /* Status of COM/APPn marker saving */ + jpeg_saved_marker_ptr cur_marker; /* NULL if not processing a marker */ + unsigned int bytes_read; /* data bytes read so far in marker */ + /* Note: cur_marker is not linked into marker_list until it's all read. */ +} my_marker_reader; + +typedef my_marker_reader * my_marker_ptr; + + +/* + * Macros for fetching data from the data source module. + * + * At all times, cinfo->src->next_input_byte and ->bytes_in_buffer reflect + * the current restart point; we update them only when we have reached a + * suitable place to restart if a suspension occurs. + */ + +/* Declare and initialize local copies of input pointer/count */ +#define INPUT_VARS(cinfo) \ + struct jpeg_source_mgr * datasrc = (cinfo)->src; \ + const JOCTET * next_input_byte = datasrc->next_input_byte; \ + size_t bytes_in_buffer = datasrc->bytes_in_buffer + +/* Unload the local copies --- do this only at a restart boundary */ +#define INPUT_SYNC(cinfo) \ + ( datasrc->next_input_byte = next_input_byte, \ + datasrc->bytes_in_buffer = bytes_in_buffer ) + +/* Reload the local copies --- used only in MAKE_BYTE_AVAIL */ +#define INPUT_RELOAD(cinfo) \ + ( next_input_byte = datasrc->next_input_byte, \ + bytes_in_buffer = datasrc->bytes_in_buffer ) + +/* Internal macro for INPUT_BYTE and INPUT_2BYTES: make a byte available. + * Note we do *not* do INPUT_SYNC before calling fill_input_buffer, + * but we must reload the local copies after a successful fill. + */ +#define MAKE_BYTE_AVAIL(cinfo,action) \ + if (bytes_in_buffer == 0) { \ + if (! (*datasrc->fill_input_buffer) (cinfo)) \ + { action; } \ + INPUT_RELOAD(cinfo); \ + } + +/* Read a byte into variable V. + * If must suspend, take the specified action (typically "return FALSE"). + */ +#define INPUT_BYTE(cinfo,V,action) \ + MAKESTMT( MAKE_BYTE_AVAIL(cinfo,action); \ + bytes_in_buffer--; \ + V = GETJOCTET(*next_input_byte++); ) + +/* As above, but read two bytes interpreted as an unsigned 16-bit integer. + * V should be declared unsigned int or perhaps IJG_INT32. + */ +#define INPUT_2BYTES(cinfo,V,action) \ + MAKESTMT( MAKE_BYTE_AVAIL(cinfo,action); \ + bytes_in_buffer--; \ + V = ((unsigned int) GETJOCTET(*next_input_byte++)) << 8; \ + MAKE_BYTE_AVAIL(cinfo,action); \ + bytes_in_buffer--; \ + V += GETJOCTET(*next_input_byte++); ) + + +/* + * Routines to process JPEG markers. + * + * Entry condition: JPEG marker itself has been read and its code saved + * in cinfo->unread_marker; input restart point is just after the marker. + * + * Exit: if return TRUE, have read and processed any parameters, and have + * updated the restart point to point after the parameters. + * If return FALSE, was forced to suspend before reaching end of + * marker parameters; restart point has not been moved. Same routine + * will be called again after application supplies more input data. + * + * This approach to suspension assumes that all of a marker's parameters + * can fit into a single input bufferload. This should hold for "normal" + * markers. Some COM/APPn markers might have large parameter segments + * that might not fit. If we are simply dropping such a marker, we use + * skip_input_data to get past it, and thereby put the problem on the + * source manager's shoulders. If we are saving the marker's contents + * into memory, we use a slightly different convention: when forced to + * suspend, the marker processor updates the restart point to the end of + * what it's consumed (ie, the end of the buffer) before returning FALSE. + * On resumption, cinfo->unread_marker still contains the marker code, + * but the data source will point to the next chunk of marker data. + * The marker processor must retain internal state to deal with this. + * + * Note that we don't bother to avoid duplicate trace messages if a + * suspension occurs within marker parameters. Other side effects + * require more care. + */ + + +LOCAL(boolean) +get_soi (j_decompress_ptr cinfo) +/* Process an SOI marker */ +{ + int i; + + TRACEMS(cinfo, 1, JTRC_SOI); + + if (cinfo->marker->saw_SOI) + ERREXIT(cinfo, JERR_SOI_DUPLICATE); + + /* Reset all parameters that are defined to be reset by SOI */ + + for (i = 0; i < NUM_ARITH_TBLS; i++) { + cinfo->arith_dc_L[i] = 0; + cinfo->arith_dc_U[i] = 1; + cinfo->arith_ac_K[i] = 5; + } + cinfo->restart_interval = 0; + + /* Set initial assumptions for colorspace etc */ + + cinfo->jpeg_color_space = JCS_UNKNOWN; + cinfo->CCIR601_sampling = FALSE; /* Assume non-CCIR sampling??? */ + + cinfo->saw_JFIF_marker = FALSE; + cinfo->JFIF_major_version = 1; /* set default JFIF APP0 values */ + cinfo->JFIF_minor_version = 1; + cinfo->density_unit = 0; + cinfo->X_density = 1; + cinfo->Y_density = 1; + cinfo->saw_Adobe_marker = FALSE; + cinfo->Adobe_transform = 0; + + cinfo->marker->saw_SOI = TRUE; + + return TRUE; +} + + +LOCAL(boolean) +get_sof (j_decompress_ptr cinfo, J_CODEC_PROCESS process, boolean is_arith, + int data_unit) +/* Process a SOFn marker */ +{ + IJG_INT32 length; + int c, ci; + jpeg_component_info * compptr; + INPUT_VARS(cinfo); + + cinfo->data_unit = data_unit; + cinfo->process = process; + cinfo->arith_code = is_arith; + + INPUT_2BYTES(cinfo, length, return FALSE); + + INPUT_BYTE(cinfo, cinfo->data_precision, return FALSE); + INPUT_2BYTES(cinfo, cinfo->image_height, return FALSE); + INPUT_2BYTES(cinfo, cinfo->image_width, return FALSE); + INPUT_BYTE(cinfo, cinfo->num_components, return FALSE); + + length -= 8; + + TRACEMS4(cinfo, 1, JTRC_SOF, cinfo->unread_marker, + (int) cinfo->image_width, (int) cinfo->image_height, + cinfo->num_components); + + if (cinfo->marker->saw_SOF) + ERREXIT(cinfo, JERR_SOF_DUPLICATE); + + /* We don't support files in which the image height is initially specified */ + /* as 0 and is later redefined by DNL. As long as we have to check that, */ + /* might as well have a general sanity check. */ + if (cinfo->image_height <= 0 || cinfo->image_width <= 0 + || cinfo->num_components <= 0) + ERREXIT(cinfo, JERR_EMPTY_IMAGE); + + if (length != (cinfo->num_components * 3)) + ERREXIT(cinfo, JERR_BAD_LENGTH); + + if (cinfo->comp_info == NULL) /* do only once, even if suspend */ + cinfo->comp_info = (jpeg_component_info *) (*cinfo->mem->alloc_small) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + (size_t)cinfo->num_components * SIZEOF(jpeg_component_info)); + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + compptr->component_index = ci; + INPUT_BYTE(cinfo, compptr->component_id, return FALSE); + INPUT_BYTE(cinfo, c, return FALSE); + compptr->h_samp_factor = (c >> 4) & 15; + compptr->v_samp_factor = (c ) & 15; + INPUT_BYTE(cinfo, compptr->quant_tbl_no, return FALSE); + + TRACEMS4(cinfo, 1, JTRC_SOF_COMPONENT, + compptr->component_id, compptr->h_samp_factor, + compptr->v_samp_factor, compptr->quant_tbl_no); + } + + cinfo->marker->saw_SOF = TRUE; + + INPUT_SYNC(cinfo); + return TRUE; +} + + +LOCAL(boolean) +get_sos (j_decompress_ptr cinfo) +/* Process a SOS marker */ +{ + IJG_INT32 length; + int i, ci, n, c, cc; + jpeg_component_info * compptr; + INPUT_VARS(cinfo); + + if (! cinfo->marker->saw_SOF) + ERREXIT(cinfo, JERR_SOS_NO_SOF); + + INPUT_2BYTES(cinfo, length, return FALSE); + + INPUT_BYTE(cinfo, n, return FALSE); /* Number of components */ + + TRACEMS1(cinfo, 1, JTRC_SOS, n); + + if (length != (n * 2 + 6) || n < 1 || n > MAX_COMPS_IN_SCAN) + ERREXIT(cinfo, JERR_BAD_LENGTH); + + cinfo->comps_in_scan = n; + + /* Collect the component-spec parameters */ + + for (i = 0; i < n; i++) { + INPUT_BYTE(cinfo, cc, return FALSE); + INPUT_BYTE(cinfo, c, return FALSE); + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + if (cc == compptr->component_id) + goto id_found; + } + + ERREXIT1(cinfo, JERR_BAD_COMPONENT_ID, cc); + + id_found: + + cinfo->cur_comp_info[i] = compptr; + compptr->dc_tbl_no = (c >> 4) & 15; + compptr->ac_tbl_no = (c ) & 15; + + TRACEMS3(cinfo, 1, JTRC_SOS_COMPONENT, cc, + compptr->dc_tbl_no, compptr->ac_tbl_no); + } + + /* Collect the additional scan parameters Ss, Se, Ah/Al. */ + INPUT_BYTE(cinfo, c, return FALSE); + cinfo->Ss = c; + INPUT_BYTE(cinfo, c, return FALSE); + cinfo->Se = c; + INPUT_BYTE(cinfo, c, return FALSE); + cinfo->Ah = (c >> 4) & 15; + cinfo->Al = (c ) & 15; + + TRACEMS4(cinfo, 1, JTRC_SOS_PARAMS, cinfo->Ss, cinfo->Se, + cinfo->Ah, cinfo->Al); + + /* Prepare to scan data & restart markers */ + cinfo->marker->next_restart_num = 0; + + /* Count another SOS marker */ + cinfo->input_scan_number++; + + INPUT_SYNC(cinfo); + return TRUE; +} + + +#ifdef D_ARITH_CODING_SUPPORTED + +LOCAL(boolean) +get_dac (j_decompress_ptr cinfo) +/* Process a DAC marker */ +{ + IJG_INT32 length; + int idx, val; + INPUT_VARS(cinfo); + + INPUT_2BYTES(cinfo, length, return FALSE); + length -= 2; + + while (length > 0) { + INPUT_BYTE(cinfo, idx, return FALSE); + INPUT_BYTE(cinfo, val, return FALSE); + + length -= 2; + + TRACEMS2(cinfo, 1, JTRC_DAC, idx, val); + + if (idx < 0 || idx >= (2*NUM_ARITH_TBLS)) + ERREXIT1(cinfo, JERR_DAC_INDEX, idx); + + if (idx >= NUM_ARITH_TBLS) { /* define AC table */ + cinfo->arith_ac_K[idx-NUM_ARITH_TBLS] = (UINT8) val; + } else { /* define DC table */ + cinfo->arith_dc_L[idx] = (UINT8) (val & 0x0F); + cinfo->arith_dc_U[idx] = (UINT8) (val >> 4); + if (cinfo->arith_dc_L[idx] > cinfo->arith_dc_U[idx]) + ERREXIT1(cinfo, JERR_DAC_VALUE, val); + } + } + + if (length != 0) + ERREXIT(cinfo, JERR_BAD_LENGTH); + + INPUT_SYNC(cinfo); + return TRUE; +} + +#else /* ! D_ARITH_CODING_SUPPORTED */ + +#define get_dac(cinfo) skip_variable(cinfo) + +#endif /* D_ARITH_CODING_SUPPORTED */ + + +LOCAL(boolean) +get_dht (j_decompress_ptr cinfo) +/* Process a DHT marker */ +{ + IJG_INT32 length; + UINT8 bits[17]; + UINT8 huffval[256]; + int i, idx, count; + JHUFF_TBL **htblptr; + INPUT_VARS(cinfo); + + INPUT_2BYTES(cinfo, length, return FALSE); + length -= 2; + + while (length > 16) { + INPUT_BYTE(cinfo, idx, return FALSE); + + TRACEMS1(cinfo, 1, JTRC_DHT, idx); + + bits[0] = 0; + count = 0; + for (i = 1; i <= 16; i++) { + INPUT_BYTE(cinfo, bits[i], return FALSE); + count += bits[i]; + } + + length -= 1 + 16; + + TRACEMS8(cinfo, 2, JTRC_HUFFBITS, + bits[1], bits[2], bits[3], bits[4], + bits[5], bits[6], bits[7], bits[8]); + TRACEMS8(cinfo, 2, JTRC_HUFFBITS, + bits[9], bits[10], bits[11], bits[12], + bits[13], bits[14], bits[15], bits[16]); + + /* Here we just do minimal validation of the counts to avoid walking + * off the end of our table space. jdhuff.c will check more carefully. + */ + if (count > 256 || ((IJG_INT32) count) > length) + ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); + + for (i = 0; i < count; i++) + INPUT_BYTE(cinfo, huffval[i], return FALSE); + + length -= count; + + if (idx & 0x10) { /* AC table definition */ + idx -= 0x10; + htblptr = &cinfo->ac_huff_tbl_ptrs[idx]; + } else { /* DC table definition */ + htblptr = &cinfo->dc_huff_tbl_ptrs[idx]; + } + + if (idx < 0 || idx >= NUM_HUFF_TBLS) + ERREXIT1(cinfo, JERR_DHT_INDEX, idx); + + if (*htblptr == NULL) + *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo); + + MEMCOPY((*htblptr)->bits, bits, SIZEOF((*htblptr)->bits)); + MEMCOPY((*htblptr)->huffval, huffval, SIZEOF((*htblptr)->huffval)); + } + + if (length != 0) + ERREXIT(cinfo, JERR_BAD_LENGTH); + + INPUT_SYNC(cinfo); + return TRUE; +} + + +LOCAL(boolean) +get_dqt (j_decompress_ptr cinfo) +/* Process a DQT marker */ +{ + IJG_INT32 length; + int n, i, prec; + unsigned int tmp; + JQUANT_TBL *quant_ptr; + INPUT_VARS(cinfo); + + INPUT_2BYTES(cinfo, length, return FALSE); + length -= 2; + + while (length > 0) { + INPUT_BYTE(cinfo, n, return FALSE); + prec = n >> 4; + n &= 0x0F; + + TRACEMS2(cinfo, 1, JTRC_DQT, n, prec); + + if (n >= NUM_QUANT_TBLS) + ERREXIT1(cinfo, JERR_DQT_INDEX, n); + + if (cinfo->quant_tbl_ptrs[n] == NULL) + cinfo->quant_tbl_ptrs[n] = jpeg_alloc_quant_table((j_common_ptr) cinfo); + quant_ptr = cinfo->quant_tbl_ptrs[n]; + + for (i = 0; i < DCTSIZE2; i++) { + if (prec) + INPUT_2BYTES(cinfo, tmp, return FALSE); + else + INPUT_BYTE(cinfo, tmp, return FALSE); + /* We convert the zigzag-order table to natural array order. */ + quant_ptr->quantval[jpeg_natural_order[i]] = (UINT16) tmp; + } + + if (cinfo->err->trace_level >= 2) { + for (i = 0; i < DCTSIZE2; i += 8) { + TRACEMS8(cinfo, 2, JTRC_QUANTVALS, + quant_ptr->quantval[i], quant_ptr->quantval[i+1], + quant_ptr->quantval[i+2], quant_ptr->quantval[i+3], + quant_ptr->quantval[i+4], quant_ptr->quantval[i+5], + quant_ptr->quantval[i+6], quant_ptr->quantval[i+7]); + } + } + + length -= DCTSIZE2+1; + if (prec) length -= DCTSIZE2; + } + + if (length != 0) + ERREXIT(cinfo, JERR_BAD_LENGTH); + + INPUT_SYNC(cinfo); + return TRUE; +} + + +LOCAL(boolean) +get_dri (j_decompress_ptr cinfo) +/* Process a DRI marker */ +{ + IJG_INT32 length; + unsigned int tmp; + INPUT_VARS(cinfo); + + INPUT_2BYTES(cinfo, length, return FALSE); + + if (length != 4) + ERREXIT(cinfo, JERR_BAD_LENGTH); + + INPUT_2BYTES(cinfo, tmp, return FALSE); + + TRACEMS1(cinfo, 1, JTRC_DRI, (int)tmp); + + cinfo->restart_interval = tmp; + + INPUT_SYNC(cinfo); + return TRUE; +} + + +/* + * Routines for processing APPn and COM markers. + * These are either saved in memory or discarded, per application request. + * APP0 and APP14 are specially checked to see if they are + * JFIF and Adobe markers, respectively. + */ + +#define APP0_DATA_LEN 14 /* Length of interesting data in APP0 */ +#define APP14_DATA_LEN 12 /* Length of interesting data in APP14 */ +#define APPN_DATA_LEN 14 /* Must be the largest of the above!! */ + + +LOCAL(void) +examine_app0 (j_decompress_ptr cinfo, JOCTET FAR * data, + unsigned int datalen, IJG_INT32 remaining) +/* Examine first few bytes from an APP0. + * Take appropriate action if it is a JFIF marker. + * datalen is # of bytes at data[], remaining is length of rest of marker data. + */ +{ + IJG_INT32 totallen = (IJG_INT32) datalen + remaining; + + if (datalen >= APP0_DATA_LEN && + GETJOCTET(data[0]) == 0x4A && + GETJOCTET(data[1]) == 0x46 && + GETJOCTET(data[2]) == 0x49 && + GETJOCTET(data[3]) == 0x46 && + GETJOCTET(data[4]) == 0) { + /* Found JFIF APP0 marker: save info */ + cinfo->saw_JFIF_marker = TRUE; + cinfo->JFIF_major_version = GETJOCTET(data[5]); + cinfo->JFIF_minor_version = GETJOCTET(data[6]); + cinfo->density_unit = GETJOCTET(data[7]); + cinfo->X_density = (UINT16)((GETJOCTET(data[8]) << 8) + GETJOCTET(data[9])); + cinfo->Y_density = (UINT16)((GETJOCTET(data[10]) << 8) + GETJOCTET(data[11])); + /* Check version. + * Major version must be 1, anything else signals an incompatible change. + * (We used to treat this as an error, but now it's a nonfatal warning, + * because some bozo at Hijaak couldn't read the spec.) + * Minor version should be 0..2, but process anyway if newer. + */ + if (cinfo->JFIF_major_version != 1) + WARNMS2(cinfo, JWRN_JFIF_MAJOR, + cinfo->JFIF_major_version, cinfo->JFIF_minor_version); + /* Generate trace messages */ + TRACEMS5(cinfo, 1, JTRC_JFIF, + cinfo->JFIF_major_version, cinfo->JFIF_minor_version, + cinfo->X_density, cinfo->Y_density, cinfo->density_unit); + /* Validate thumbnail dimensions and issue appropriate messages */ + if (GETJOCTET(data[12]) | GETJOCTET(data[13])) + TRACEMS2(cinfo, 1, JTRC_JFIF_THUMBNAIL, + GETJOCTET(data[12]), GETJOCTET(data[13])); + totallen -= APP0_DATA_LEN; + if (totallen != + ((IJG_INT32)GETJOCTET(data[12]) * (IJG_INT32)GETJOCTET(data[13]) * (IJG_INT32) 3)) + TRACEMS1(cinfo, 1, JTRC_JFIF_BADTHUMBNAILSIZE, (int) totallen); + } else if (datalen >= 6 && + GETJOCTET(data[0]) == 0x4A && + GETJOCTET(data[1]) == 0x46 && + GETJOCTET(data[2]) == 0x58 && + GETJOCTET(data[3]) == 0x58 && + GETJOCTET(data[4]) == 0) { + /* Found JFIF "JFXX" extension APP0 marker */ + /* The library doesn't actually do anything with these, + * but we try to produce a helpful trace message. + */ + switch (GETJOCTET(data[5])) { + case 0x10: + TRACEMS1(cinfo, 1, JTRC_THUMB_JPEG, (int) totallen); + break; + case 0x11: + TRACEMS1(cinfo, 1, JTRC_THUMB_PALETTE, (int) totallen); + break; + case 0x13: + TRACEMS1(cinfo, 1, JTRC_THUMB_RGB, (int) totallen); + break; + default: + TRACEMS2(cinfo, 1, JTRC_JFIF_EXTENSION, + GETJOCTET(data[5]), (int) totallen); + break; + } + } else { + /* Start of APP0 does not match "JFIF" or "JFXX", or too short */ + TRACEMS1(cinfo, 1, JTRC_APP0, (int) totallen); + } +} + + +LOCAL(void) +examine_app14 (j_decompress_ptr cinfo, JOCTET FAR * data, + unsigned int datalen, IJG_INT32 remaining) +/* Examine first few bytes from an APP14. + * Take appropriate action if it is an Adobe marker. + * datalen is # of bytes at data[], remaining is length of rest of marker data. + */ +{ + unsigned int version, flags0, flags1, transform; + + if (datalen >= APP14_DATA_LEN && + GETJOCTET(data[0]) == 0x41 && + GETJOCTET(data[1]) == 0x64 && + GETJOCTET(data[2]) == 0x6F && + GETJOCTET(data[3]) == 0x62 && + GETJOCTET(data[4]) == 0x65) { + /* Found Adobe APP14 marker */ + version = (unsigned int)((GETJOCTET(data[5]) << 8) + GETJOCTET(data[6])); + flags0 = (unsigned int)((GETJOCTET(data[7]) << 8) + GETJOCTET(data[8])); + flags1 = (unsigned int)((GETJOCTET(data[9]) << 8) + GETJOCTET(data[10])); + transform = GETJOCTET(data[11]); + TRACEMS4(cinfo, 1, JTRC_ADOBE, (int)version, (int)flags0, (int)flags1, (int)transform); + cinfo->saw_Adobe_marker = TRUE; + cinfo->Adobe_transform = (UINT8) transform; + } else { + /* Start of APP14 does not match "Adobe", or too short */ + TRACEMS1(cinfo, 1, JTRC_APP14, (int) (datalen + remaining)); + } +} + + +METHODDEF(boolean) +get_interesting_appn (j_decompress_ptr cinfo) +/* Process an APP0 or APP14 marker without saving it */ +{ + IJG_INT32 length; + JOCTET b[APPN_DATA_LEN]; + unsigned int i, numtoread; + INPUT_VARS(cinfo); + + INPUT_2BYTES(cinfo, length, return FALSE); + length -= 2; + + /* get the interesting part of the marker data */ + if (length >= APPN_DATA_LEN) + numtoread = APPN_DATA_LEN; + else if (length > 0) + numtoread = (unsigned int) length; + else + numtoread = 0; + for (i = 0; i < numtoread; i++) + INPUT_BYTE(cinfo, b[i], return FALSE); + length -= numtoread; + + /* process it */ + switch (cinfo->unread_marker) { + case M_APP0: + examine_app0(cinfo, (JOCTET FAR *) b, numtoread, length); + break; + case M_APP14: + examine_app14(cinfo, (JOCTET FAR *) b, numtoread, length); + break; + default: + /* can't get here unless jpeg_save_markers chooses wrong processor */ + ERREXIT1(cinfo, JERR_UNKNOWN_MARKER, cinfo->unread_marker); + break; + } + + /* skip any remaining data -- could be lots */ + INPUT_SYNC(cinfo); + if (length > 0) + (*cinfo->src->skip_input_data) (cinfo, (long) length); + + return TRUE; +} + + +#ifdef SAVE_MARKERS_SUPPORTED + +METHODDEF(boolean) +save_marker (j_decompress_ptr cinfo) +/* Save an APPn or COM marker into the marker list */ +{ + my_marker_ptr marker = (my_marker_ptr) cinfo->marker; + jpeg_saved_marker_ptr cur_marker = marker->cur_marker; + unsigned int bytes_read, data_length; + JOCTET FAR * data; + IJG_INT32 length = 0; + INPUT_VARS(cinfo); + + if (cur_marker == NULL) { + /* begin reading a marker */ + INPUT_2BYTES(cinfo, length, return FALSE); + length -= 2; + if (length >= 0) { /* watch out for bogus length word */ + /* figure out how much we want to save */ + unsigned int limit; + if (cinfo->unread_marker == (int) M_COM) + limit = marker->length_limit_COM; + else + limit = marker->length_limit_APPn[cinfo->unread_marker - (int) M_APP0]; + if ((unsigned int) length < limit) + limit = (unsigned int) length; + /* allocate and initialize the marker item */ + cur_marker = (jpeg_saved_marker_ptr) + (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(struct jpeg_marker_struct) + limit); + cur_marker->next = NULL; + cur_marker->marker = (UINT8) cinfo->unread_marker; + cur_marker->original_length = (unsigned int) length; + cur_marker->data_length = limit; + /* data area is just beyond the jpeg_marker_struct */ + data = cur_marker->data = (JOCTET FAR *) (cur_marker + 1); + marker->cur_marker = cur_marker; + marker->bytes_read = 0; + bytes_read = 0; + data_length = limit; + } else { + /* deal with bogus length word */ + bytes_read = data_length = 0; + data = NULL; + } + } else { + /* resume reading a marker */ + bytes_read = marker->bytes_read; + data_length = cur_marker->data_length; + data = cur_marker->data + bytes_read; + } + + while (bytes_read < data_length) { + INPUT_SYNC(cinfo); /* move the restart point to here */ + marker->bytes_read = bytes_read; + /* If there's not at least one byte in buffer, suspend */ + MAKE_BYTE_AVAIL(cinfo, return FALSE); + /* Copy bytes with reasonable rapidity */ + while (bytes_read < data_length && bytes_in_buffer > 0) { + *data++ = *next_input_byte++; + bytes_in_buffer--; + bytes_read++; + } + } + + /* Done reading what we want to read */ + if (cur_marker != NULL) { /* will be NULL if bogus length word */ + /* Add new marker to end of list */ + if (cinfo->marker_list == NULL) { + cinfo->marker_list = cur_marker; + } else { + jpeg_saved_marker_ptr prev = cinfo->marker_list; + while (prev->next != NULL) + prev = prev->next; + prev->next = cur_marker; + } + /* Reset pointer & calc remaining data length */ + data = cur_marker->data; + length = cur_marker->original_length - data_length; + } + /* Reset to initial state for next marker */ + marker->cur_marker = NULL; + + /* Process the marker if interesting; else just make a generic trace msg */ + switch (cinfo->unread_marker) { + case M_APP0: + examine_app0(cinfo, data, data_length, length); + break; + case M_APP14: + examine_app14(cinfo, data, data_length, length); + break; + default: + TRACEMS2(cinfo, 1, JTRC_MISC_MARKER, cinfo->unread_marker, + (int) (data_length + length)); + break; + } + + /* skip any remaining data -- could be lots */ + INPUT_SYNC(cinfo); /* do before skip_input_data */ + if (length > 0) + (*cinfo->src->skip_input_data) (cinfo, (long) length); + + return TRUE; +} + +#endif /* SAVE_MARKERS_SUPPORTED */ + + +METHODDEF(boolean) +skip_variable (j_decompress_ptr cinfo) +/* Skip over an unknown or uninteresting variable-length marker */ +{ + IJG_INT32 length; + INPUT_VARS(cinfo); + + INPUT_2BYTES(cinfo, length, return FALSE); + length -= 2; + + TRACEMS2(cinfo, 1, JTRC_MISC_MARKER, cinfo->unread_marker, (int) length); + + INPUT_SYNC(cinfo); /* do before skip_input_data */ + if (length > 0) + (*cinfo->src->skip_input_data) (cinfo, (long) length); + + return TRUE; +} + + +/* + * Find the next JPEG marker, save it in cinfo->unread_marker. + * Returns FALSE if had to suspend before reaching a marker; + * in that case cinfo->unread_marker is unchanged. + * + * Note that the result might not be a valid marker code, + * but it will never be 0 or FF. + */ + +LOCAL(boolean) +next_marker (j_decompress_ptr cinfo) +{ + int c; + INPUT_VARS(cinfo); + + for (;;) { + INPUT_BYTE(cinfo, c, return FALSE); + /* Skip any non-FF bytes. + * This may look a bit inefficient, but it will not occur in a valid file. + * We sync after each discarded byte so that a suspending data source + * can discard the byte from its buffer. + */ + while (c != 0xFF) { + cinfo->marker->discarded_bytes++; + INPUT_SYNC(cinfo); + INPUT_BYTE(cinfo, c, return FALSE); + } + /* This loop swallows any duplicate FF bytes. Extra FFs are legal as + * pad bytes, so don't count them in discarded_bytes. We assume there + * will not be so many consecutive FF bytes as to overflow a suspending + * data source's input buffer. + */ + do { + INPUT_BYTE(cinfo, c, return FALSE); + } while (c == 0xFF); + if (c != 0) + break; /* found a valid marker, exit loop */ + /* Reach here if we found a stuffed-zero data sequence (FF/00). + * Discard it and loop back to try again. + */ + cinfo->marker->discarded_bytes += 2; + INPUT_SYNC(cinfo); + } + + if (cinfo->marker->discarded_bytes != 0) { + WARNMS2(cinfo, JWRN_EXTRANEOUS_DATA, (int)cinfo->marker->discarded_bytes, c); + cinfo->marker->discarded_bytes = 0; + } + + cinfo->unread_marker = c; + + INPUT_SYNC(cinfo); + return TRUE; +} + + +LOCAL(boolean) +first_marker (j_decompress_ptr cinfo) +/* Like next_marker, but used to obtain the initial SOI marker. */ +/* For this marker, we do not allow preceding garbage or fill; otherwise, + * we might well scan an entire input file before realizing it ain't JPEG. + * If an application wants to process non-JFIF files, it must seek to the + * SOI before calling the JPEG library. + */ +{ + int c, c2; + INPUT_VARS(cinfo); + + INPUT_BYTE(cinfo, c, return FALSE); + INPUT_BYTE(cinfo, c2, return FALSE); + if (c != 0xFF || c2 != (int) M_SOI) + ERREXIT2(cinfo, JERR_NO_SOI, c, c2); + + cinfo->unread_marker = c2; + + INPUT_SYNC(cinfo); + return TRUE; +} + + +/* + * Read markers until SOS or EOI. + * + * Returns same codes as are defined for jpeg_consume_input: + * JPEG_SUSPENDED, JPEG_REACHED_SOS, or JPEG_REACHED_EOI. + */ + +METHODDEF(int) +read_markers (j_decompress_ptr cinfo) +{ + /* Outer loop repeats once for each marker. */ + for (;;) { + /* Collect the marker proper, unless we already did. */ + /* NB: first_marker() enforces the requirement that SOI appear first. */ + if (cinfo->unread_marker == 0) { + if (! cinfo->marker->saw_SOI) { + if (! first_marker(cinfo)) + return JPEG_SUSPENDED; + } else { + if (! next_marker(cinfo)) + return JPEG_SUSPENDED; + } + } + /* At this point cinfo->unread_marker contains the marker code and the + * input point is just past the marker proper, but before any parameters. + * A suspension will cause us to return with this state still true. + */ + switch (cinfo->unread_marker) { + case M_SOI: + if (! get_soi(cinfo)) + return JPEG_SUSPENDED; + break; + + case M_SOF0: /* Baseline */ + case M_SOF1: /* Extended sequential, Huffman */ + if (! get_sof(cinfo, JPROC_SEQUENTIAL, FALSE, DCTSIZE)) + return JPEG_SUSPENDED; + break; + + case M_SOF2: /* Progressive, Huffman */ + if (! get_sof(cinfo, JPROC_PROGRESSIVE, FALSE, DCTSIZE)) + return JPEG_SUSPENDED; + break; + + case M_SOF3: /* Lossless, Huffman */ + if (! get_sof(cinfo, JPROC_LOSSLESS, FALSE, 1)) + return JPEG_SUSPENDED; + break; + + case M_SOF9: /* Extended sequential, arithmetic */ + if (! get_sof(cinfo, JPROC_SEQUENTIAL, TRUE, DCTSIZE)) + return JPEG_SUSPENDED; + break; + + case M_SOF10: /* Progressive, arithmetic */ + if (! get_sof(cinfo, JPROC_PROGRESSIVE, TRUE, DCTSIZE)) + return JPEG_SUSPENDED; + break; + + case M_SOF11: /* Lossless, arithmetic */ + if (! get_sof(cinfo, JPROC_LOSSLESS, TRUE, 1)) + return JPEG_SUSPENDED; + break; + + /* Currently unsupported SOFn types */ + case M_SOF5: /* Differential sequential, Huffman */ + case M_SOF6: /* Differential progressive, Huffman */ + case M_SOF7: /* Differential lossless, Huffman */ + case M_JPG: /* Reserved for JPEG extensions */ + case M_SOF13: /* Differential sequential, arithmetic */ + case M_SOF14: /* Differential progressive, arithmetic */ + case M_SOF15: /* Differential lossless, arithmetic */ + ERREXIT1(cinfo, JERR_SOF_UNSUPPORTED, cinfo->unread_marker); + break; + + case M_SOS: + if (! get_sos(cinfo)) + return JPEG_SUSPENDED; + cinfo->unread_marker = 0; /* processed the marker */ + return JPEG_REACHED_SOS; + + case M_EOI: + TRACEMS(cinfo, 1, JTRC_EOI); + cinfo->unread_marker = 0; /* processed the marker */ + return JPEG_REACHED_EOI; + + case M_DAC: + if (! get_dac(cinfo)) + return JPEG_SUSPENDED; + break; + + case M_DHT: + if (! get_dht(cinfo)) + return JPEG_SUSPENDED; + break; + + case M_DQT: + if (! get_dqt(cinfo)) + return JPEG_SUSPENDED; + break; + + case M_DRI: + if (! get_dri(cinfo)) + return JPEG_SUSPENDED; + break; + + case M_APP0: + case M_APP1: + case M_APP2: + case M_APP3: + case M_APP4: + case M_APP5: + case M_APP6: + case M_APP7: + case M_APP8: + case M_APP9: + case M_APP10: + case M_APP11: + case M_APP12: + case M_APP13: + case M_APP14: + case M_APP15: + if (! (*((my_marker_ptr) cinfo->marker)->process_APPn[ + cinfo->unread_marker - (int) M_APP0]) (cinfo)) + return JPEG_SUSPENDED; + break; + + case M_COM: + if (! (*((my_marker_ptr) cinfo->marker)->process_COM) (cinfo)) + return JPEG_SUSPENDED; + break; + + case M_RST0: /* these are all parameterless */ + case M_RST1: + case M_RST2: + case M_RST3: + case M_RST4: + case M_RST5: + case M_RST6: + case M_RST7: + case M_TEM: + TRACEMS1(cinfo, 1, JTRC_PARMLESS_MARKER, cinfo->unread_marker); + break; + + case M_DNL: /* Ignore DNL ... perhaps the wrong thing */ + if (! skip_variable(cinfo)) + return JPEG_SUSPENDED; + break; + + default: /* must be DHP, EXP, JPGn, or RESn */ + /* For now, we treat the reserved markers as fatal errors since they are + * likely to be used to signal incompatible JPEG Part 3 extensions. + * Once the JPEG 3 version-number marker is well defined, this code + * ought to change! + */ + ERREXIT1(cinfo, JERR_UNKNOWN_MARKER, cinfo->unread_marker); + break; + } + /* Successfully processed marker, so reset state variable */ + cinfo->unread_marker = 0; + } /* end loop */ +} + + +/* + * Read a restart marker, which is expected to appear next in the datastream; + * if the marker is not there, take appropriate recovery action. + * Returns FALSE if suspension is required. + * + * This is called by the entropy decoder after it has read an appropriate + * number of MCUs. cinfo->unread_marker may be nonzero if the entropy decoder + * has already read a marker from the data source. Under normal conditions + * cinfo->unread_marker will be reset to 0 before returning; if not reset, + * it holds a marker which the decoder will be unable to read past. + */ + +METHODDEF(boolean) +read_restart_marker (j_decompress_ptr cinfo) +{ + /* Obtain a marker unless we already did. */ + /* Note that next_marker will complain if it skips any data. */ + if (cinfo->unread_marker == 0) { + if (! next_marker(cinfo)) + return FALSE; + } + + if (cinfo->unread_marker == + ((int) M_RST0 + cinfo->marker->next_restart_num)) { + /* Normal case --- swallow the marker and let entropy decoder continue */ + TRACEMS1(cinfo, 3, JTRC_RST, cinfo->marker->next_restart_num); + cinfo->unread_marker = 0; + } else { + /* Uh-oh, the restart markers have been messed up. */ + /* Let the data source manager determine how to resync. */ + if (! (*cinfo->src->resync_to_restart) (cinfo, + cinfo->marker->next_restart_num)) + return FALSE; + } + + /* Update next-restart state */ + cinfo->marker->next_restart_num = (cinfo->marker->next_restart_num + 1) & 7; + + return TRUE; +} + + +/* + * This is the default resync_to_restart method for data source managers + * to use if they don't have any better approach. Some data source managers + * may be able to back up, or may have additional knowledge about the data + * which permits a more intelligent recovery strategy; such managers would + * presumably supply their own resync method. + * + * read_restart_marker calls resync_to_restart if it finds a marker other than + * the restart marker it was expecting. (This code is *not* used unless + * a nonzero restart interval has been declared.) cinfo->unread_marker is + * the marker code actually found (might be anything, except 0 or FF). + * The desired restart marker number (0..7) is passed as a parameter. + * This routine is supposed to apply whatever error recovery strategy seems + * appropriate in order to position the input stream to the next data segment. + * Note that cinfo->unread_marker is treated as a marker appearing before + * the current data-source input point; usually it should be reset to zero + * before returning. + * Returns FALSE if suspension is required. + * + * This implementation is substantially constrained by wanting to treat the + * input as a data stream; this means we can't back up. Therefore, we have + * only the following actions to work with: + * 1. Simply discard the marker and let the entropy decoder resume at next + * byte of file. + * 2. Read forward until we find another marker, discarding intervening + * data. (In theory we could look ahead within the current bufferload, + * without having to discard data if we don't find the desired marker. + * This idea is not implemented here, in part because it makes behavior + * dependent on buffer size and chance buffer-boundary positions.) + * 3. Leave the marker unread (by failing to zero cinfo->unread_marker). + * This will cause the entropy decoder to process an empty data segment, + * inserting dummy zeroes, and then we will reprocess the marker. + * + * #2 is appropriate if we think the desired marker lies ahead, while #3 is + * appropriate if the found marker is a future restart marker (indicating + * that we have missed the desired restart marker, probably because it got + * corrupted). + * We apply #2 or #3 if the found marker is a restart marker no more than + * two counts behind or ahead of the expected one. We also apply #2 if the + * found marker is not a legal JPEG marker code (it's certainly bogus data). + * If the found marker is a restart marker more than 2 counts away, we do #1 + * (too much risk that the marker is erroneous; with luck we will be able to + * resync at some future point). + * For any valid non-restart JPEG marker, we apply #3. This keeps us from + * overrunning the end of a scan. An implementation limited to single-scan + * files might find it better to apply #2 for markers other than EOI, since + * any other marker would have to be bogus data in that case. + */ + +GLOBAL(boolean) +jpeg_resync_to_restart (j_decompress_ptr cinfo, int desired) +{ + int marker = cinfo->unread_marker; + int action = 1; + + /* Always put up a warning. */ + WARNMS2(cinfo, JWRN_MUST_RESYNC, marker, desired); + + /* Outer loop handles repeated decision after scanning forward. */ + for (;;) { + if (marker < (int) M_SOF0) + action = 2; /* invalid marker */ + else if (marker < (int) M_RST0 || marker > (int) M_RST7) + action = 3; /* valid non-restart marker */ + else { + if (marker == ((int) M_RST0 + ((desired+1) & 7)) || + marker == ((int) M_RST0 + ((desired+2) & 7))) + action = 3; /* one of the next two expected restarts */ + else if (marker == ((int) M_RST0 + ((desired-1) & 7)) || + marker == ((int) M_RST0 + ((desired-2) & 7))) + action = 2; /* a prior restart, so advance */ + else + action = 1; /* desired restart or too far away */ + } + TRACEMS2(cinfo, 4, JTRC_RECOVERY_ACTION, marker, action); + switch (action) { + case 1: + /* Discard marker and let entropy decoder resume processing. */ + cinfo->unread_marker = 0; + return TRUE; + case 2: + /* Scan to the next marker, and repeat the decision loop. */ + if (! next_marker(cinfo)) + return FALSE; + marker = cinfo->unread_marker; + break; + case 3: + /* Return without advancing past this marker. */ + /* Entropy decoder will be forced to process an empty segment. */ + return TRUE; + } + } /* end loop */ +} + + +/* + * Reset marker processing state to begin a fresh datastream. + */ + +METHODDEF(void) +reset_marker_reader (j_decompress_ptr cinfo) +{ + my_marker_ptr marker = (my_marker_ptr) cinfo->marker; + + cinfo->comp_info = NULL; /* until allocated by get_sof */ + cinfo->input_scan_number = 0; /* no SOS seen yet */ + cinfo->unread_marker = 0; /* no pending marker */ + marker->pub.saw_SOI = FALSE; /* set internal state too */ + marker->pub.saw_SOF = FALSE; + marker->pub.discarded_bytes = 0; + marker->cur_marker = NULL; +} + + +/* + * Initialize the marker reader module. + * This is called only once, when the decompression object is created. + */ + +GLOBAL(void) +jinit_marker_reader (j_decompress_ptr cinfo) +{ + my_marker_ptr marker; + int i; + + /* Create subobject in permanent pool */ + marker = (my_marker_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, + SIZEOF(my_marker_reader)); + cinfo->marker = (struct jpeg_marker_reader *) marker; + /* Initialize public method pointers */ + marker->pub.reset_marker_reader = reset_marker_reader; + marker->pub.read_markers = read_markers; + marker->pub.read_restart_marker = read_restart_marker; + /* Initialize COM/APPn processing. + * By default, we examine and then discard APP0 and APP14, + * but simply discard COM and all other APPn. + */ + marker->process_COM = skip_variable; + marker->length_limit_COM = 0; + for (i = 0; i < 16; i++) { + marker->process_APPn[i] = skip_variable; + marker->length_limit_APPn[i] = 0; + } + marker->process_APPn[0] = get_interesting_appn; + marker->process_APPn[14] = get_interesting_appn; + /* Reset marker processing state */ + reset_marker_reader(cinfo); +} + + +/* + * Control saving of COM and APPn markers into marker_list. + */ + +#ifdef SAVE_MARKERS_SUPPORTED + +GLOBAL(void) +jpeg_save_markers (j_decompress_ptr cinfo, int marker_code, + unsigned int length_limit) +{ + my_marker_ptr marker = (my_marker_ptr) cinfo->marker; + long maxlength; + jpeg_marker_parser_method processor; + + /* Length limit mustn't be larger than what we can allocate + * (should only be a concern in a 16-bit environment). + */ + maxlength = cinfo->mem->max_alloc_chunk - (long)SIZEOF(struct jpeg_marker_struct); + if (((long) length_limit) > maxlength) + length_limit = (unsigned int) maxlength; + + /* Choose processor routine to use. + * APP0/APP14 have special requirements. + */ + if (length_limit) { + processor = save_marker; + /* If saving APP0/APP14, save at least enough for our internal use. */ + if (marker_code == (int) M_APP0 && length_limit < APP0_DATA_LEN) + length_limit = APP0_DATA_LEN; + else if (marker_code == (int) M_APP14 && length_limit < APP14_DATA_LEN) + length_limit = APP14_DATA_LEN; + } else { + processor = skip_variable; + /* If discarding APP0/APP14, use our regular on-the-fly processor. */ + if (marker_code == (int) M_APP0 || marker_code == (int) M_APP14) + processor = get_interesting_appn; + } + + if (marker_code == (int) M_COM) { + marker->process_COM = processor; + marker->length_limit_COM = length_limit; + } else if (marker_code >= (int) M_APP0 && marker_code <= (int) M_APP15) { + marker->process_APPn[marker_code - (int) M_APP0] = processor; + marker->length_limit_APPn[marker_code - (int) M_APP0] = length_limit; + } else + ERREXIT1(cinfo, JERR_UNKNOWN_MARKER, marker_code); +} + +#endif /* SAVE_MARKERS_SUPPORTED */ + + +/* + * Install a special processing method for COM or APPn markers. + */ + +GLOBAL(void) +jpeg_set_marker_processor (j_decompress_ptr cinfo, int marker_code, + jpeg_marker_parser_method routine) +{ + my_marker_ptr marker = (my_marker_ptr) cinfo->marker; + + if (marker_code == (int) M_COM) + marker->process_COM = routine; + else if (marker_code >= (int) M_APP0 && marker_code <= (int) M_APP15) + marker->process_APPn[marker_code - (int) M_APP0] = routine; + else + ERREXIT1(cinfo, JERR_UNKNOWN_MARKER, marker_code); +} diff --git a/dcmjpeg/libijg16/jdmaster.c b/dcmjpeg/libijg16/jdmaster.c new file mode 100644 index 00000000..970ae0e7 --- /dev/null +++ b/dcmjpeg/libijg16/jdmaster.c @@ -0,0 +1,460 @@ +/* + * jdmaster.c + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains master control logic for the JPEG decompressor. + * These routines are concerned with selecting the modules to be executed + * and with determining the number of passes and the work to be done in each + * pass. + */ + +#define JPEG_INTERNALS +#include "jinclude16.h" +#include "jpeglib16.h" + + +/* Private state */ + +typedef struct { + struct jpeg_decomp_master pub; /* public fields */ + + int pass_number; /* # of passes completed */ + + boolean using_merged_upsample; /* TRUE if using merged upsample/cconvert */ + + /* Saved references to initialized quantizer modules, + * in case we need to switch modes. + */ + struct jpeg_color_quantizer * quantizer_1pass; + struct jpeg_color_quantizer * quantizer_2pass; +} my_decomp_master; + +typedef my_decomp_master * my_master_ptr; + + +/* + * Determine whether merged upsample/color conversion should be used. + * CRUCIAL: this must match the actual capabilities of jdmerge.c! + */ + +LOCAL(boolean) +use_merged_upsample (j_decompress_ptr cinfo) +{ +#ifdef UPSAMPLE_MERGING_SUPPORTED + /* Merging is the equivalent of plain box-filter upsampling */ + if (cinfo->do_fancy_upsampling || cinfo->CCIR601_sampling) + return FALSE; + /* jdmerge.c only supports YCC=>RGB color conversion */ + if (cinfo->jpeg_color_space != JCS_YCbCr || cinfo->num_components != 3 || + cinfo->out_color_space != JCS_RGB || + cinfo->out_color_components != RGB_PIXELSIZE) + return FALSE; + /* and it only handles 2h1v or 2h2v sampling ratios */ + if (cinfo->comp_info[0].h_samp_factor != 2 || + cinfo->comp_info[1].h_samp_factor != 1 || + cinfo->comp_info[2].h_samp_factor != 1 || + cinfo->comp_info[0].v_samp_factor > 2 || + cinfo->comp_info[1].v_samp_factor != 1 || + cinfo->comp_info[2].v_samp_factor != 1) + return FALSE; + /* furthermore, it doesn't work if each component has been + processed differently */ + if (cinfo->comp_info[0].codec_data_unit != cinfo->min_codec_data_unit || + cinfo->comp_info[1].codec_data_unit != cinfo->min_codec_data_unit || + cinfo->comp_info[2].codec_data_unit != cinfo->min_codec_data_unit) + return FALSE; + /* ??? also need to test for upsample-time rescaling, when & if supported */ + return TRUE; /* by golly, it'll work... */ +#else + return FALSE; +#endif +} + + +/* + * Compute output image dimensions and related values. + * NOTE: this is exported for possible use by application. + * Hence it mustn't do anything that can't be done twice. + * Also note that it may be called before the master module is initialized! + */ + +GLOBAL(void) +jpeg_calc_output_dimensions (j_decompress_ptr cinfo) +/* Do computations that are needed before master selection phase */ +{ + /* Prevent application from calling me at wrong times */ + if (cinfo->global_state != DSTATE_READY) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + + (*cinfo->codec->calc_output_dimensions) (cinfo); + + /* Report number of components in selected colorspace. */ + /* Probably this should be in the color conversion module... */ + switch (cinfo->out_color_space) { + case JCS_GRAYSCALE: + cinfo->out_color_components = 1; + break; + case JCS_RGB: +#if RGB_PIXELSIZE != 3 + cinfo->out_color_components = RGB_PIXELSIZE; + break; +#endif /* else share code with YCbCr */ + case JCS_YCbCr: + cinfo->out_color_components = 3; + break; + case JCS_CMYK: + case JCS_YCCK: + cinfo->out_color_components = 4; + break; + default: /* else must be same colorspace as in file */ + cinfo->out_color_components = cinfo->num_components; + break; + } + cinfo->output_components = (cinfo->quantize_colors ? 1 : + cinfo->out_color_components); + + /* See if upsampler will want to emit more than one row at a time */ + if (use_merged_upsample(cinfo)) + cinfo->rec_outbuf_height = cinfo->max_v_samp_factor; + else + cinfo->rec_outbuf_height = 1; +} + + +/* + * Several decompression processes need to range-limit values to the range + * 0..MAXJSAMPLE; the input value may fall somewhat outside this range + * due to noise introduced by quantization, roundoff error, etc. These + * processes are inner loops and need to be as fast as possible. On most + * machines, particularly CPUs with pipelines or instruction prefetch, + * a (subscript-check-less) C table lookup + * x = sample_range_limit[x]; + * is faster than explicit tests + * if (x < 0) x = 0; + * else if (x > MAXJSAMPLE) x = MAXJSAMPLE; + * These processes all use a common table prepared by the routine below. + * + * For most steps we can mathematically guarantee that the initial value + * of x is within MAXJSAMPLE+1 of the legal range, so a table running from + * -(MAXJSAMPLE+1) to 2*MAXJSAMPLE+1 is sufficient. But for the initial + * limiting step (just after the IDCT), a wildly out-of-range value is + * possible if the input data is corrupt. To avoid any chance of indexing + * off the end of memory and getting a bad-pointer trap, we perform the + * post-IDCT limiting thus: + * x = range_limit[x & MASK]; + * where MASK is 2 bits wider than legal sample data, ie 10 bits for 8-bit + * samples. Under normal circumstances this is more than enough range and + * a correct output will be generated; with bogus input data the mask will + * cause wraparound, and we will safely generate a bogus-but-in-range output. + * For the post-IDCT step, we want to convert the data from signed to unsigned + * representation by adding CENTERJSAMPLE at the same time that we limit it. + * So the post-IDCT limiting table ends up looking like this: + * CENTERJSAMPLE,CENTERJSAMPLE+1,...,MAXJSAMPLE, + * MAXJSAMPLE (repeat 2*(MAXJSAMPLE+1)-CENTERJSAMPLE times), + * 0 (repeat 2*(MAXJSAMPLE+1)-CENTERJSAMPLE times), + * 0,1,...,CENTERJSAMPLE-1 + * Negative inputs select values from the upper half of the table after + * masking. + * + * We can save some space by overlapping the start of the post-IDCT table + * with the simpler range limiting table. The post-IDCT table begins at + * sample_range_limit + CENTERJSAMPLE. + * + * Note that the table is allocated in near data space on PCs; it's small + * enough and used often enough to justify this. + */ + +LOCAL(void) +prepare_range_limit_table (j_decompress_ptr cinfo) +/* Allocate and fill in the sample_range_limit table */ +{ + JSAMPLE * table; + int i; + + table = (JSAMPLE *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (5 * (MAXJSAMPLE+1) + CENTERJSAMPLE) * SIZEOF(JSAMPLE)); + table += (MAXJSAMPLE+1); /* allow negative subscripts of simple table */ + cinfo->sample_range_limit = table; + /* First segment of "simple" table: limit[x] = 0 for x < 0 */ + MEMZERO(table - (MAXJSAMPLE+1), (MAXJSAMPLE+1) * SIZEOF(JSAMPLE)); + /* Main part of "simple" table: limit[x] = x */ + for (i = 0; i <= MAXJSAMPLE; i++) + table[i] = (JSAMPLE) i; + table += CENTERJSAMPLE; /* Point to where post-IDCT table starts */ + /* End of simple table, rest of first half of post-IDCT table */ + for (i = CENTERJSAMPLE; i < 2*(MAXJSAMPLE+1); i++) + table[i] = MAXJSAMPLE; + /* Second half of post-IDCT table */ + MEMZERO(table + (2 * (MAXJSAMPLE+1)), + (2 * (MAXJSAMPLE+1) - CENTERJSAMPLE) * SIZEOF(JSAMPLE)); + MEMCOPY(table + (4 * (MAXJSAMPLE+1) - CENTERJSAMPLE), + cinfo->sample_range_limit, CENTERJSAMPLE * SIZEOF(JSAMPLE)); +} + + +/* + * Master selection of decompression modules. + * This is done once at jpeg_start_decompress time. We determine + * which modules will be used and give them appropriate initialization calls. + * We also initialize the decompressor input side to begin consuming data. + * + * Since jpeg_read_header has finished, we know what is in the SOF + * and (first) SOS markers. We also have all the application parameter + * settings. + */ + +LOCAL(void) +master_selection (j_decompress_ptr cinfo) +{ + my_master_ptr master = (my_master_ptr) cinfo->master; + long samplesperrow; + JDIMENSION jd_samplesperrow; + + /* Initialize dimensions and other stuff */ + jpeg_calc_output_dimensions(cinfo); + prepare_range_limit_table(cinfo); + + /* Width of an output scanline must be representable as JDIMENSION. */ + samplesperrow = (long) cinfo->output_width * (long) cinfo->out_color_components; + jd_samplesperrow = (JDIMENSION) samplesperrow; + if ((long) jd_samplesperrow != samplesperrow) + ERREXIT(cinfo, JERR_WIDTH_OVERFLOW); + + /* Initialize my private state */ + master->pass_number = 0; + master->using_merged_upsample = use_merged_upsample(cinfo); + + /* Color quantizer selection */ + master->quantizer_1pass = NULL; + master->quantizer_2pass = NULL; + /* No mode changes if not using buffered-image mode. */ + if (! cinfo->quantize_colors || ! cinfo->buffered_image) { + cinfo->enable_1pass_quant = FALSE; + cinfo->enable_external_quant = FALSE; + cinfo->enable_2pass_quant = FALSE; + } + if (cinfo->quantize_colors) { + if (cinfo->raw_data_out) + ERREXIT(cinfo, JERR_NOTIMPL); + /* 2-pass quantizer only works in 3-component color space. */ + if (cinfo->out_color_components != 3) { + cinfo->enable_1pass_quant = TRUE; + cinfo->enable_external_quant = FALSE; + cinfo->enable_2pass_quant = FALSE; + cinfo->colormap = NULL; + } else if (cinfo->colormap != NULL) { + cinfo->enable_external_quant = TRUE; + } else if (cinfo->two_pass_quantize) { + cinfo->enable_2pass_quant = TRUE; + } else { + cinfo->enable_1pass_quant = TRUE; + } + + if (cinfo->enable_1pass_quant) { +#ifdef QUANT_1PASS_SUPPORTED + jinit_1pass_quantizer(cinfo); + master->quantizer_1pass = cinfo->cquantize; +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } + + /* We use the 2-pass code to map to external colormaps. */ + if (cinfo->enable_2pass_quant || cinfo->enable_external_quant) { +#ifdef QUANT_2PASS_SUPPORTED + jinit_2pass_quantizer(cinfo); + master->quantizer_2pass = cinfo->cquantize; +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } + /* If both quantizers are initialized, the 2-pass one is left active; + * this is necessary for starting with quantization to an external map. + */ + } + + /* Post-processing: in particular, color conversion first */ + if (! cinfo->raw_data_out) { + if (master->using_merged_upsample) { +#ifdef UPSAMPLE_MERGING_SUPPORTED + jinit_merged_upsampler(cinfo); /* does color conversion too */ +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } else { + jinit_color_deconverter(cinfo); + jinit_upsampler(cinfo); + } + jinit_d_post_controller(cinfo, cinfo->enable_2pass_quant); + } + + /* Initialize principal buffer controllers. */ + if (! cinfo->raw_data_out) + jinit_d_main_controller(cinfo, FALSE /* never need full buffer here */); + + /* We can now tell the memory manager to allocate virtual arrays. */ + (*cinfo->mem->realize_virt_arrays) ((j_common_ptr) cinfo); + + /* Initialize input side of decompressor to consume first scan. */ + (*cinfo->inputctl->start_input_pass) (cinfo); + +#ifdef D_MULTISCAN_FILES_SUPPORTED + /* If jpeg_start_decompress will read the whole file, initialize + * progress monitoring appropriately. The input step is counted + * as one pass. + */ + if (cinfo->progress != NULL && ! cinfo->buffered_image && + cinfo->inputctl->has_multiple_scans) { + int nscans; + /* Estimate number of scans to set pass_limit. */ + if (cinfo->process == JPROC_PROGRESSIVE) { + /* Arbitrarily estimate 2 interleaved DC scans + 3 AC scans/component. */ + nscans = 2 + 3 * cinfo->num_components; + } else { + /* For a nonprogressive multiscan file, estimate 1 scan per component. */ + nscans = cinfo->num_components; + } + cinfo->progress->pass_counter = 0L; + cinfo->progress->pass_limit = (long) cinfo->total_iMCU_rows * nscans; + cinfo->progress->completed_passes = 0; + cinfo->progress->total_passes = (cinfo->enable_2pass_quant ? 3 : 2); + /* Count the input pass as done */ + master->pass_number++; + } +#endif /* D_MULTISCAN_FILES_SUPPORTED */ +} + + +/* + * Per-pass setup. + * This is called at the beginning of each output pass. We determine which + * modules will be active during this pass and give them appropriate + * start_pass calls. We also set is_dummy_pass to indicate whether this + * is a "real" output pass or a dummy pass for color quantization. + * (In the latter case, jdapistd.c will crank the pass to completion.) + */ + +METHODDEF(void) +prepare_for_output_pass (j_decompress_ptr cinfo) +{ + my_master_ptr master = (my_master_ptr) cinfo->master; + + if (master->pub.is_dummy_pass) { +#ifdef QUANT_2PASS_SUPPORTED + /* Final pass of 2-pass quantization */ + master->pub.is_dummy_pass = FALSE; + (*cinfo->cquantize->start_pass) (cinfo, FALSE); + (*cinfo->post->start_pass) (cinfo, JBUF_CRANK_DEST); + (*cinfo->main->start_pass) (cinfo, JBUF_CRANK_DEST); +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif /* QUANT_2PASS_SUPPORTED */ + } else { + if (cinfo->quantize_colors && cinfo->colormap == NULL) { + /* Select new quantization method */ + if (cinfo->two_pass_quantize && cinfo->enable_2pass_quant) { + cinfo->cquantize = master->quantizer_2pass; + master->pub.is_dummy_pass = TRUE; + } else if (cinfo->enable_1pass_quant) { + cinfo->cquantize = master->quantizer_1pass; + } else { + ERREXIT(cinfo, JERR_MODE_CHANGE); + } + } + (*cinfo->codec->start_output_pass) (cinfo); + if (! cinfo->raw_data_out) { + if (! master->using_merged_upsample) + (*cinfo->cconvert->start_pass) (cinfo); + (*cinfo->upsample->start_pass) (cinfo); + if (cinfo->quantize_colors) + (*cinfo->cquantize->start_pass) (cinfo, master->pub.is_dummy_pass); + (*cinfo->post->start_pass) (cinfo, + (master->pub.is_dummy_pass ? JBUF_SAVE_AND_PASS : JBUF_PASS_THRU)); + (*cinfo->main->start_pass) (cinfo, JBUF_PASS_THRU); + } + } + + /* Set up progress monitor's pass info if present */ + if (cinfo->progress != NULL) { + cinfo->progress->completed_passes = master->pass_number; + cinfo->progress->total_passes = master->pass_number + + (master->pub.is_dummy_pass ? 2 : 1); + /* In buffered-image mode, we assume one more output pass if EOI not + * yet reached, but no more passes if EOI has been reached. + */ + if (cinfo->buffered_image && ! cinfo->inputctl->eoi_reached) { + cinfo->progress->total_passes += (cinfo->enable_2pass_quant ? 2 : 1); + } + } +} + + +/* + * Finish up at end of an output pass. + */ + +METHODDEF(void) +finish_output_pass (j_decompress_ptr cinfo) +{ + my_master_ptr master = (my_master_ptr) cinfo->master; + + if (cinfo->quantize_colors) + (*cinfo->cquantize->finish_pass) (cinfo); + master->pass_number++; +} + + +#ifdef D_MULTISCAN_FILES_SUPPORTED + +/* + * Switch to a new external colormap between output passes. + */ + +GLOBAL(void) +jpeg_new_colormap (j_decompress_ptr cinfo) +{ + my_master_ptr master = (my_master_ptr) cinfo->master; + + /* Prevent application from calling me at wrong times */ + if (cinfo->global_state != DSTATE_BUFIMAGE) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + + if (cinfo->quantize_colors && cinfo->enable_external_quant && + cinfo->colormap != NULL) { + /* Select 2-pass quantizer for external colormap use */ + cinfo->cquantize = master->quantizer_2pass; + /* Notify quantizer of colormap change */ + (*cinfo->cquantize->new_color_map) (cinfo); + master->pub.is_dummy_pass = FALSE; /* just in case */ + } else + ERREXIT(cinfo, JERR_MODE_CHANGE); +} + +#endif /* D_MULTISCAN_FILES_SUPPORTED */ + + +/* + * Initialize master decompression control and select active modules. + * This is performed at the start of jpeg_start_decompress. + */ + +GLOBAL(void) +jinit_master_decompress (j_decompress_ptr cinfo) +{ + my_master_ptr master; + + master = (my_master_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_decomp_master)); + cinfo->master = (struct jpeg_decomp_master *) master; + master->pub.prepare_for_output_pass = prepare_for_output_pass; + master->pub.finish_output_pass = finish_output_pass; + + master->pub.is_dummy_pass = FALSE; + + master_selection(cinfo); +} diff --git a/dcmjpeg/libijg16/jdmerge.c b/dcmjpeg/libijg16/jdmerge.c new file mode 100644 index 00000000..cdf87b2b --- /dev/null +++ b/dcmjpeg/libijg16/jdmerge.c @@ -0,0 +1,400 @@ +/* + * jdmerge.c + * + * Copyright (C) 1994-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains code for merged upsampling/color conversion. + * + * This file combines functions from jdsample.c and jdcolor.c; + * read those files first to understand what's going on. + * + * When the chroma components are to be upsampled by simple replication + * (ie, box filtering), we can save some work in color conversion by + * calculating all the output pixels corresponding to a pair of chroma + * samples at one time. In the conversion equations + * R = Y + K1 * Cr + * G = Y + K2 * Cb + K3 * Cr + * B = Y + K4 * Cb + * only the Y term varies among the group of pixels corresponding to a pair + * of chroma samples, so the rest of the terms can be calculated just once. + * At typical sampling ratios, this eliminates half or three-quarters of the + * multiplications needed for color conversion. + * + * This file currently provides implementations for the following cases: + * YCbCr => RGB color conversion only. + * Sampling ratios of 2h1v or 2h2v. + * No scaling needed at upsample time. + * Corner-aligned (non-CCIR601) sampling alignment. + * Other special cases could be added, but in most applications these are + * the only common cases. (For uncommon cases we fall back on the more + * general code in jdsample.c and jdcolor.c.) + */ + +#define JPEG_INTERNALS +#include "jinclude16.h" +#include "jpeglib16.h" + +#ifdef UPSAMPLE_MERGING_SUPPORTED + + +/* Private subobject */ + +typedef struct { + struct jpeg_upsampler pub; /* public fields */ + + /* Pointer to routine to do actual upsampling/conversion of one row group */ + JMETHOD(void, upmethod, (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr, + JSAMPARRAY output_buf)); + + /* Private state for YCC->RGB conversion */ + int * Cr_r_tab; /* => table for Cr to R conversion */ + int * Cb_b_tab; /* => table for Cb to B conversion */ + IJG_INT32 * Cr_g_tab; /* => table for Cr to G conversion */ + IJG_INT32 * Cb_g_tab; /* => table for Cb to G conversion */ + + /* For 2:1 vertical sampling, we produce two output rows at a time. + * We need a "spare" row buffer to hold the second output row if the + * application provides just a one-row buffer; we also use the spare + * to discard the dummy last row if the image height is odd. + */ + JSAMPROW spare_row; + boolean spare_full; /* T if spare buffer is occupied */ + + JDIMENSION out_row_width; /* samples per output row */ + JDIMENSION rows_to_go; /* counts rows remaining in image */ +} my_upsampler; + +typedef my_upsampler * my_upsample_ptr; + +#define SCALEBITS 16 /* speediest right-shift on some machines */ +#define ONE_HALF ((IJG_INT32) 1 << (SCALEBITS-1)) +#define FIX(x) ((IJG_INT32) ((x) * (1L<RGB colorspace conversion. + * This is taken directly from jdcolor.c; see that file for more info. + */ + +LOCAL(void) +build_ycc_rgb_table (j_decompress_ptr cinfo) +{ + my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; + int i; + IJG_INT32 x; + SHIFT_TEMPS + + upsample->Cr_r_tab = (int *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (MAXJSAMPLE+1) * SIZEOF(int)); + upsample->Cb_b_tab = (int *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (MAXJSAMPLE+1) * SIZEOF(int)); + upsample->Cr_g_tab = (IJG_INT32 *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (MAXJSAMPLE+1) * SIZEOF(IJG_INT32)); + upsample->Cb_g_tab = (IJG_INT32 *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (MAXJSAMPLE+1) * SIZEOF(IJG_INT32)); + + for (i = 0, x = -CENTERJSAMPLE; i <= MAXJSAMPLE; i++, x++) { + /* i is the actual input pixel value, in the range 0..MAXJSAMPLE */ + /* The Cb or Cr value we are thinking of is x = i - CENTERJSAMPLE */ + /* Cr=>R value is nearest int to 1.40200 * x */ + upsample->Cr_r_tab[i] = (int) + RIGHT_SHIFT(FIX(1.40200) * x + ONE_HALF, SCALEBITS); + /* Cb=>B value is nearest int to 1.77200 * x */ + upsample->Cb_b_tab[i] = (int) + RIGHT_SHIFT(FIX(1.77200) * x + ONE_HALF, SCALEBITS); + /* Cr=>G value is scaled-up -0.71414 * x */ + upsample->Cr_g_tab[i] = (- FIX(0.71414)) * x; + /* Cb=>G value is scaled-up -0.34414 * x */ + /* We also add in ONE_HALF so that need not do it in inner loop */ + upsample->Cb_g_tab[i] = (- FIX(0.34414)) * x + ONE_HALF; + } +} + + +/* + * Initialize for an upsampling pass. + */ + +METHODDEF(void) +start_pass_merged_upsample (j_decompress_ptr cinfo) +{ + my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; + + /* Mark the spare buffer empty */ + upsample->spare_full = FALSE; + /* Initialize total-height counter for detecting bottom of image */ + upsample->rows_to_go = cinfo->output_height; +} + + +/* + * Control routine to do upsampling (and color conversion). + * + * The control routine just handles the row buffering considerations. + */ + +METHODDEF(void) +merged_2v_upsample (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail) +/* 2:1 vertical sampling case: may need a spare row. */ +{ + my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; + JSAMPROW work_ptrs[2]; + JDIMENSION num_rows; /* number of rows returned to caller */ + + if (upsample->spare_full) { + /* If we have a spare row saved from a previous cycle, just return it. */ + jcopy_sample_rows(& upsample->spare_row, 0, output_buf + *out_row_ctr, 0, + 1, upsample->out_row_width); + num_rows = 1; + upsample->spare_full = FALSE; + } else { + /* Figure number of rows to return to caller. */ + num_rows = 2; + /* Not more than the distance to the end of the image. */ + if (num_rows > upsample->rows_to_go) + num_rows = upsample->rows_to_go; + /* And not more than what the client can accept: */ + out_rows_avail -= *out_row_ctr; + if (num_rows > out_rows_avail) + num_rows = out_rows_avail; + /* Create output pointer array for upsampler. */ + work_ptrs[0] = output_buf[*out_row_ctr]; + if (num_rows > 1) { + work_ptrs[1] = output_buf[*out_row_ctr + 1]; + } else { + work_ptrs[1] = upsample->spare_row; + upsample->spare_full = TRUE; + } + /* Now do the upsampling. */ + (*upsample->upmethod) (cinfo, input_buf, *in_row_group_ctr, work_ptrs); + } + + /* Adjust counts */ + *out_row_ctr += num_rows; + upsample->rows_to_go -= num_rows; + /* When the buffer is emptied, declare this input row group consumed */ + if (! upsample->spare_full) + (*in_row_group_ctr)++; +} + + +METHODDEF(void) +merged_1v_upsample (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail) +/* 1:1 vertical sampling case: much easier, never need a spare row. */ +{ + my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; + + /* Just do the upsampling. */ + (*upsample->upmethod) (cinfo, input_buf, *in_row_group_ctr, + output_buf + *out_row_ctr); + /* Adjust counts */ + (*out_row_ctr)++; + (*in_row_group_ctr)++; +} + + +/* + * These are the routines invoked by the control routines to do + * the actual upsampling/conversion. One row group is processed per call. + * + * Note: since we may be writing directly into application-supplied buffers, + * we have to be honest about the output width; we can't assume the buffer + * has been rounded up to an even width. + */ + + +/* + * Upsample and color convert for the case of 2:1 horizontal and 1:1 vertical. + */ + +METHODDEF(void) +h2v1_merged_upsample (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr, + JSAMPARRAY output_buf) +{ + my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; + register int y, cred, cgreen, cblue; + int cb, cr; + register JSAMPROW outptr; + JSAMPROW inptr0, inptr1, inptr2; + JDIMENSION col; + /* copy these pointers into registers if possible */ + register JSAMPLE * range_limit = cinfo->sample_range_limit; + int * Crrtab = upsample->Cr_r_tab; + int * Cbbtab = upsample->Cb_b_tab; + IJG_INT32 * Crgtab = upsample->Cr_g_tab; + IJG_INT32 * Cbgtab = upsample->Cb_g_tab; + SHIFT_TEMPS + + inptr0 = input_buf[0][in_row_group_ctr]; + inptr1 = input_buf[1][in_row_group_ctr]; + inptr2 = input_buf[2][in_row_group_ctr]; + outptr = output_buf[0]; + /* Loop for each pair of output pixels */ + for (col = cinfo->output_width >> 1; col > 0; col--) { + /* Do the chroma part of the calculation */ + cb = GETJSAMPLE(*inptr1++); + cr = GETJSAMPLE(*inptr2++); + cred = Crrtab[cr]; + cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS); + cblue = Cbbtab[cb]; + /* Fetch 2 Y values and emit 2 pixels */ + y = GETJSAMPLE(*inptr0++); + outptr[RGB_RED] = range_limit[y + cred]; + outptr[RGB_GREEN] = range_limit[y + cgreen]; + outptr[RGB_BLUE] = range_limit[y + cblue]; + outptr += RGB_PIXELSIZE; + y = GETJSAMPLE(*inptr0++); + outptr[RGB_RED] = range_limit[y + cred]; + outptr[RGB_GREEN] = range_limit[y + cgreen]; + outptr[RGB_BLUE] = range_limit[y + cblue]; + outptr += RGB_PIXELSIZE; + } + /* If image width is odd, do the last output column separately */ + if (cinfo->output_width & 1) { + cb = GETJSAMPLE(*inptr1); + cr = GETJSAMPLE(*inptr2); + cred = Crrtab[cr]; + cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS); + cblue = Cbbtab[cb]; + y = GETJSAMPLE(*inptr0); + outptr[RGB_RED] = range_limit[y + cred]; + outptr[RGB_GREEN] = range_limit[y + cgreen]; + outptr[RGB_BLUE] = range_limit[y + cblue]; + } +} + + +/* + * Upsample and color convert for the case of 2:1 horizontal and 2:1 vertical. + */ + +METHODDEF(void) +h2v2_merged_upsample (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr, + JSAMPARRAY output_buf) +{ + my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; + register int y, cred, cgreen, cblue; + int cb, cr; + register JSAMPROW outptr0, outptr1; + JSAMPROW inptr00, inptr01, inptr1, inptr2; + JDIMENSION col; + /* copy these pointers into registers if possible */ + register JSAMPLE * range_limit = cinfo->sample_range_limit; + int * Crrtab = upsample->Cr_r_tab; + int * Cbbtab = upsample->Cb_b_tab; + IJG_INT32 * Crgtab = upsample->Cr_g_tab; + IJG_INT32 * Cbgtab = upsample->Cb_g_tab; + SHIFT_TEMPS + + inptr00 = input_buf[0][in_row_group_ctr*2]; + inptr01 = input_buf[0][in_row_group_ctr*2 + 1]; + inptr1 = input_buf[1][in_row_group_ctr]; + inptr2 = input_buf[2][in_row_group_ctr]; + outptr0 = output_buf[0]; + outptr1 = output_buf[1]; + /* Loop for each group of output pixels */ + for (col = cinfo->output_width >> 1; col > 0; col--) { + /* Do the chroma part of the calculation */ + cb = GETJSAMPLE(*inptr1++); + cr = GETJSAMPLE(*inptr2++); + cred = Crrtab[cr]; + cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS); + cblue = Cbbtab[cb]; + /* Fetch 4 Y values and emit 4 pixels */ + y = GETJSAMPLE(*inptr00++); + outptr0[RGB_RED] = range_limit[y + cred]; + outptr0[RGB_GREEN] = range_limit[y + cgreen]; + outptr0[RGB_BLUE] = range_limit[y + cblue]; + outptr0 += RGB_PIXELSIZE; + y = GETJSAMPLE(*inptr00++); + outptr0[RGB_RED] = range_limit[y + cred]; + outptr0[RGB_GREEN] = range_limit[y + cgreen]; + outptr0[RGB_BLUE] = range_limit[y + cblue]; + outptr0 += RGB_PIXELSIZE; + y = GETJSAMPLE(*inptr01++); + outptr1[RGB_RED] = range_limit[y + cred]; + outptr1[RGB_GREEN] = range_limit[y + cgreen]; + outptr1[RGB_BLUE] = range_limit[y + cblue]; + outptr1 += RGB_PIXELSIZE; + y = GETJSAMPLE(*inptr01++); + outptr1[RGB_RED] = range_limit[y + cred]; + outptr1[RGB_GREEN] = range_limit[y + cgreen]; + outptr1[RGB_BLUE] = range_limit[y + cblue]; + outptr1 += RGB_PIXELSIZE; + } + /* If image width is odd, do the last output column separately */ + if (cinfo->output_width & 1) { + cb = GETJSAMPLE(*inptr1); + cr = GETJSAMPLE(*inptr2); + cred = Crrtab[cr]; + cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS); + cblue = Cbbtab[cb]; + y = GETJSAMPLE(*inptr00); + outptr0[RGB_RED] = range_limit[y + cred]; + outptr0[RGB_GREEN] = range_limit[y + cgreen]; + outptr0[RGB_BLUE] = range_limit[y + cblue]; + y = GETJSAMPLE(*inptr01); + outptr1[RGB_RED] = range_limit[y + cred]; + outptr1[RGB_GREEN] = range_limit[y + cgreen]; + outptr1[RGB_BLUE] = range_limit[y + cblue]; + } +} + + +/* + * Module initialization routine for merged upsampling/color conversion. + * + * NB: this is called under the conditions determined by use_merged_upsample() + * in jdmaster.c. That routine MUST correspond to the actual capabilities + * of this module; no safety checks are made here. + */ + +GLOBAL(void) +jinit_merged_upsampler (j_decompress_ptr cinfo) +{ + my_upsample_ptr upsample; + + upsample = (my_upsample_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_upsampler)); + cinfo->upsample = (struct jpeg_upsampler *) upsample; + upsample->pub.start_pass = start_pass_merged_upsample; + upsample->pub.need_context_rows = FALSE; + + upsample->out_row_width = cinfo->output_width * (JDIMENSION)cinfo->out_color_components; + + if (cinfo->max_v_samp_factor == 2) { + upsample->pub.upsample = merged_2v_upsample; + upsample->upmethod = h2v2_merged_upsample; + /* Allocate a spare row buffer */ + upsample->spare_row = (JSAMPROW) + (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (size_t) (upsample->out_row_width * SIZEOF(JSAMPLE))); + } else { + upsample->pub.upsample = merged_1v_upsample; + upsample->upmethod = h2v1_merged_upsample; + /* No spare row needed */ + upsample->spare_row = NULL; + } + + build_ycc_rgb_table(cinfo); +} + +#endif /* UPSAMPLE_MERGING_SUPPORTED */ diff --git a/dcmjpeg/libijg16/jdphuff.c b/dcmjpeg/libijg16/jdphuff.c new file mode 100644 index 00000000..1367966b --- /dev/null +++ b/dcmjpeg/libijg16/jdphuff.c @@ -0,0 +1,675 @@ +/* + * jdphuff.c + * + * Copyright (C) 1995-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains Huffman entropy decoding routines for progressive JPEG. + * + * Much of the complexity here has to do with supporting input suspension. + * If the data source module demands suspension, we want to be able to back + * up to the start of the current MCU. To do this, we copy state variables + * into local working storage, and update them back to the permanent + * storage only upon successful completion of an MCU. + */ + +#define JPEG_INTERNALS +#include "jinclude16.h" +#include "jpeglib16.h" +#include "jlossy16.h" /* Private declarations for lossy subsystem */ +#include "jdhuff16.h" /* Declarations shared with jd*huff.c */ + + +#ifdef D_PROGRESSIVE_SUPPORTED + +/* + * Private entropy decoder object for progressive Huffman decoding. + * + * The savable_state subrecord contains fields that change within an MCU, + * but must not be updated permanently until we complete the MCU. + */ + +typedef struct { + unsigned int EOBRUN; /* remaining EOBs in EOBRUN */ + int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */ +} savable_state; + +/* This macro is to work around compilers with missing or broken + * structure assignment. You'll need to fix this code if you have + * such a compiler and you change MAX_COMPS_IN_SCAN. + */ + +#ifndef NO_STRUCT_ASSIGN +#define ASSIGN_STATE(dest,src) ((dest) = (src)) +#else +#if MAX_COMPS_IN_SCAN == 4 +#define ASSIGN_STATE(dest,src) \ + ((dest).EOBRUN = (src).EOBRUN, \ + (dest).last_dc_val[0] = (src).last_dc_val[0], \ + (dest).last_dc_val[1] = (src).last_dc_val[1], \ + (dest).last_dc_val[2] = (src).last_dc_val[2], \ + (dest).last_dc_val[3] = (src).last_dc_val[3]) +#endif +#endif + + +typedef struct { + huffd_common_fields; /* Fields shared with other entropy decoders */ + + /* These fields are loaded into local variables at start of each MCU. + * In case of suspension, we exit WITHOUT updating them. + */ + savable_state saved; /* Other state at start of MCU */ + + /* These fields are NOT loaded into local working state. */ + unsigned int restarts_to_go; /* MCUs left in this restart interval */ + + /* Pointers to derived tables (these workspaces have image lifespan) */ + d_derived_tbl * derived_tbls[NUM_HUFF_TBLS]; + + d_derived_tbl * ac_derived_tbl; /* active table during an AC scan */ +} phuff_entropy_decoder; + +typedef phuff_entropy_decoder * phuff_entropy_ptr; + +/* Forward declarations */ +METHODDEF(boolean) decode_mcu_DC_first JPP((j_decompress_ptr cinfo, + JBLOCKROW *MCU_data)); +METHODDEF(boolean) decode_mcu_AC_first JPP((j_decompress_ptr cinfo, + JBLOCKROW *MCU_data)); +METHODDEF(boolean) decode_mcu_DC_refine JPP((j_decompress_ptr cinfo, + JBLOCKROW *MCU_data)); +METHODDEF(boolean) decode_mcu_AC_refine JPP((j_decompress_ptr cinfo, + JBLOCKROW *MCU_data)); + + +/* + * Initialize for a Huffman-compressed scan. + */ + +METHODDEF(void) +start_pass_phuff_decoder (j_decompress_ptr cinfo) +{ + j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec; + phuff_entropy_ptr entropy = (phuff_entropy_ptr) lossyd->entropy_private; + boolean is_DC_band, bad; + int ci, coefi, tbl; + int *coef_bit_ptr; + jpeg_component_info * compptr; + + is_DC_band = (cinfo->Ss == 0); + + /* Validate scan parameters */ + bad = FALSE; + if (is_DC_band) { + if (cinfo->Se != 0) + bad = TRUE; + } else { + /* need not check Ss/Se < 0 since they came from unsigned bytes */ + if (cinfo->Ss > cinfo->Se || cinfo->Se >= DCTSIZE2) + bad = TRUE; + /* AC scans may have only one component */ + if (cinfo->comps_in_scan != 1) + bad = TRUE; + } + if (cinfo->Ah != 0) { + /* Successive approximation refinement scan: must have Al = Ah-1. */ + if (cinfo->Al != cinfo->Ah-1) + bad = TRUE; + } + if (cinfo->Al > 13) /* need not check for < 0 */ + bad = TRUE; + /* Arguably the maximum Al value should be less than 13 for 8-bit precision, + * but the spec doesn't say so, and we try to be liberal about what we + * accept. Note: large Al values could result in out-of-range DC + * coefficients during early scans, leading to bizarre displays due to + * overflows in the IDCT math. But we won't crash. + */ + if (bad) + ERREXIT4(cinfo, JERR_BAD_PROGRESSION, + cinfo->Ss, cinfo->Se, cinfo->Ah, cinfo->Al); + /* Update progression status, and verify that scan order is legal. + * Note that inter-scan inconsistencies are treated as warnings + * not fatal errors ... not clear if this is right way to behave. + */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + int cindex = cinfo->cur_comp_info[ci]->component_index; + coef_bit_ptr = & cinfo->coef_bits[cindex][0]; + if (!is_DC_band && coef_bit_ptr[0] < 0) /* AC without prior DC scan */ + WARNMS2(cinfo, JWRN_BOGUS_PROGRESSION, cindex, 0); + for (coefi = cinfo->Ss; coefi <= cinfo->Se; coefi++) { + int expected = (coef_bit_ptr[coefi] < 0) ? 0 : coef_bit_ptr[coefi]; + if (cinfo->Ah != expected) + WARNMS2(cinfo, JWRN_BOGUS_PROGRESSION, cindex, coefi); + coef_bit_ptr[coefi] = cinfo->Al; + } + } + + /* Select MCU decoding routine */ + if (cinfo->Ah == 0) { + if (is_DC_band) + lossyd->entropy_decode_mcu = decode_mcu_DC_first; + else + lossyd->entropy_decode_mcu = decode_mcu_AC_first; + } else { + if (is_DC_band) + lossyd->entropy_decode_mcu = decode_mcu_DC_refine; + else + lossyd->entropy_decode_mcu = decode_mcu_AC_refine; + } + + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + /* Make sure requested tables are present, and compute derived tables. + * We may build same derived table more than once, but it's not expensive. + */ + if (is_DC_band) { + if (cinfo->Ah == 0) { /* DC refinement needs no table */ + tbl = compptr->dc_tbl_no; + jpeg_make_d_derived_tbl(cinfo, TRUE, tbl, + & entropy->derived_tbls[tbl]); + } + } else { + tbl = compptr->ac_tbl_no; + jpeg_make_d_derived_tbl(cinfo, FALSE, tbl, + & entropy->derived_tbls[tbl]); + /* remember the single active table */ + entropy->ac_derived_tbl = entropy->derived_tbls[tbl]; + } + /* Initialize DC predictions to 0 */ + entropy->saved.last_dc_val[ci] = 0; + } + + /* Initialize bitread state variables */ + entropy->bitstate.bits_left = 0; + entropy->bitstate.get_buffer = 0; /* unnecessary, but keeps Purify quiet */ + entropy->insufficient_data = FALSE; + + /* Initialize private state variables */ + entropy->saved.EOBRUN = 0; + + /* Initialize restart counter */ + entropy->restarts_to_go = cinfo->restart_interval; +} + + +/* + * Figure F.12: extend sign bit. + * On some machines, a shift and add will be faster than a table lookup. + */ + +#ifdef AVOID_TABLES + +#define HUFF_EXTEND(x,s) ((x) < (1<<((s)-1)) ? (x) + (((-1)<<(s)) + 1) : (x)) + +#else + +#define HUFF_EXTEND(x,s) ((x) < extend_test[s] ? (x) + extend_offset[s] : (x)) + +static const int extend_test[16] = /* entry n is 2**(n-1) */ + { 0, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080, + 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000 }; + +static const int extend_offset[16] = /* entry n is (-1 << n) + 1 */ + { 0, ((-1)<<1) + 1, ((-1)<<2) + 1, ((-1)<<3) + 1, ((-1)<<4) + 1, + ((-1)<<5) + 1, ((-1)<<6) + 1, ((-1)<<7) + 1, ((-1)<<8) + 1, + ((-1)<<9) + 1, ((-1)<<10) + 1, ((-1)<<11) + 1, ((-1)<<12) + 1, + ((-1)<<13) + 1, ((-1)<<14) + 1, ((-1)<<15) + 1 }; + +#endif /* AVOID_TABLES */ + + +/* + * Check for a restart marker & resynchronize decoder. + * Returns FALSE if must suspend. + */ + +LOCAL(boolean) +process_restart (j_decompress_ptr cinfo) +{ + j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec; + phuff_entropy_ptr entropy = (phuff_entropy_ptr) lossyd->entropy_private; + int ci; + + /* Throw away any unused bits remaining in bit buffer; */ + /* include any full bytes in next_marker's count of discarded bytes */ + cinfo->marker->discarded_bytes += (unsigned int)(entropy->bitstate.bits_left / 8); + entropy->bitstate.bits_left = 0; + + /* Advance past the RSTn marker */ + if (! (*cinfo->marker->read_restart_marker) (cinfo)) + return FALSE; + + /* Re-initialize DC predictions to 0 */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) + entropy->saved.last_dc_val[ci] = 0; + /* Re-init EOB run count, too */ + entropy->saved.EOBRUN = 0; + + /* Reset restart counter */ + entropy->restarts_to_go = cinfo->restart_interval; + + /* Reset out-of-data flag, unless read_restart_marker left us smack up + * against a marker. In that case we will end up treating the next data + * segment as empty, and we can avoid producing bogus output pixels by + * leaving the flag set. + */ + if (cinfo->unread_marker == 0) + entropy->insufficient_data = FALSE; + + return TRUE; +} + + +/* + * Huffman MCU decoding. + * Each of these routines decodes and returns one MCU's worth of + * Huffman-compressed coefficients. + * The coefficients are reordered from zigzag order into natural array order, + * but are not dequantized. + * + * The i'th block of the MCU is stored into the block pointed to by + * MCU_data[i]. WE ASSUME THIS AREA IS INITIALLY ZEROED BY THE CALLER. + * + * We return FALSE if data source requested suspension. In that case no + * changes have been made to permanent state. (Exception: some output + * coefficients may already have been assigned. This is harmless for + * spectral selection, since we'll just re-assign them on the next call. + * Successive approximation AC refinement has to be more careful, however.) + */ + +/* + * MCU decoding for DC initial scan (either spectral selection, + * or first pass of successive approximation). + */ + +METHODDEF(boolean) +decode_mcu_DC_first (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) +{ + j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec; + phuff_entropy_ptr entropy = (phuff_entropy_ptr) lossyd->entropy_private; + int Al = cinfo->Al; + register int s, r; + int blkn, ci; + JBLOCKROW block; + BITREAD_STATE_VARS; + savable_state state; + d_derived_tbl * tbl; + jpeg_component_info * compptr; + + /* Process restart marker if needed; may have to suspend */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) + if (! process_restart(cinfo)) + return FALSE; + } + + /* If we've run out of data, just leave the MCU set to zeroes. + * This way, we return uniform gray for the remainder of the segment. + */ + if (! entropy->insufficient_data) { + + /* Load up working state */ + BITREAD_LOAD_STATE(cinfo,entropy->bitstate); + ASSIGN_STATE(state, entropy->saved); + + /* Outer loop handles each block in the MCU */ + + for (blkn = 0; blkn < cinfo->data_units_in_MCU; blkn++) { + block = MCU_data[blkn]; + ci = cinfo->MCU_membership[blkn]; + compptr = cinfo->cur_comp_info[ci]; + tbl = entropy->derived_tbls[compptr->dc_tbl_no]; + + /* Decode a single block's worth of coefficients */ + + /* Section F.2.2.1: decode the DC coefficient difference */ + HUFF_DECODE(s, br_state, tbl, return FALSE, label1); + if (s) { + CHECK_BIT_BUFFER(br_state, s, return FALSE); + r = GET_BITS(s); + s = HUFF_EXTEND(r, s); + } + + /* Convert DC difference to actual value, update last_dc_val */ + s += state.last_dc_val[ci]; + state.last_dc_val[ci] = s; + /* Scale and output the coefficient (assumes jpeg_natural_order[0]=0) */ + (*block)[0] = (JCOEF) (s << Al); + } + + /* Completed MCU, so update state */ + BITREAD_SAVE_STATE(cinfo,entropy->bitstate); + ASSIGN_STATE(entropy->saved, state); + } + + /* Account for restart interval (no-op if not using restarts) */ + entropy->restarts_to_go--; + + return TRUE; +} + + +/* + * MCU decoding for AC initial scan (either spectral selection, + * or first pass of successive approximation). + */ + +METHODDEF(boolean) +decode_mcu_AC_first (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) +{ + j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec; + phuff_entropy_ptr entropy = (phuff_entropy_ptr) lossyd->entropy_private; + int Se = cinfo->Se; + int Al = cinfo->Al; + register int s, k, r; + unsigned int EOBRUN; + JBLOCKROW block; + BITREAD_STATE_VARS; + d_derived_tbl * tbl; + + /* Process restart marker if needed; may have to suspend */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) + if (! process_restart(cinfo)) + return FALSE; + } + + /* If we've run out of data, just leave the MCU set to zeroes. + * This way, we return uniform gray for the remainder of the segment. + */ + if (! entropy->insufficient_data) { + + /* Load up working state. + * We can avoid loading/saving bitread state if in an EOB run. + */ + EOBRUN = entropy->saved.EOBRUN; /* only part of saved state we need */ + + /* There is always only one block per MCU */ + + if (EOBRUN > 0) /* if it's a band of zeroes... */ + EOBRUN--; /* ...process it now (we do nothing) */ + else { + BITREAD_LOAD_STATE(cinfo,entropy->bitstate); + block = MCU_data[0]; + tbl = entropy->ac_derived_tbl; + + for (k = cinfo->Ss; k <= Se; k++) { + HUFF_DECODE(s, br_state, tbl, return FALSE, label2); + r = s >> 4; + s &= 15; + if (s) { + k += r; + CHECK_BIT_BUFFER(br_state, s, return FALSE); + r = GET_BITS(s); + s = HUFF_EXTEND(r, s); + /* Scale and output coefficient in natural (dezigzagged) order */ + (*block)[jpeg_natural_order[k]] = (JCOEF) (s << Al); + } else { + if (r == 15) { /* ZRL */ + k += 15; /* skip 15 zeroes in band */ + } else { /* EOBr, run length is 2^r + appended bits */ + EOBRUN = (unsigned int)(1 << r); + if (r) { /* EOBr, r > 0 */ + CHECK_BIT_BUFFER(br_state, r, return FALSE); + r = GET_BITS(r); + EOBRUN += (unsigned int)r; + } + EOBRUN--; /* this band is processed at this moment */ + break; /* force end-of-band */ + } + } + } + + BITREAD_SAVE_STATE(cinfo,entropy->bitstate); + } + + /* Completed MCU, so update state */ + entropy->saved.EOBRUN = EOBRUN; /* only part of saved state we need */ + } + + /* Account for restart interval (no-op if not using restarts) */ + entropy->restarts_to_go--; + + return TRUE; +} + + +/* + * MCU decoding for DC successive approximation refinement scan. + * Note: we assume such scans can be multi-component, although the spec + * is not very clear on the point. + */ + +METHODDEF(boolean) +decode_mcu_DC_refine (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) +{ + j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec; + phuff_entropy_ptr entropy = (phuff_entropy_ptr) lossyd->entropy_private; + int p1 = 1 << cinfo->Al; /* 1 in the bit position being coded */ + int blkn; + JBLOCKROW block; + BITREAD_STATE_VARS; + + /* Process restart marker if needed; may have to suspend */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) + if (! process_restart(cinfo)) + return FALSE; + } + + /* Not worth the cycles to check insufficient_data here, + * since we will not change the data anyway if we read zeroes. + */ + + /* Load up working state */ + BITREAD_LOAD_STATE(cinfo,entropy->bitstate); + + /* Outer loop handles each block in the MCU */ + + for (blkn = 0; blkn < cinfo->data_units_in_MCU; blkn++) { + block = MCU_data[blkn]; + + /* Encoded data is simply the next bit of the two's-complement DC value */ + CHECK_BIT_BUFFER(br_state, 1, return FALSE); + if (GET_BITS(1)) + (*block)[0] |= (JCOEF)p1; + /* Note: since we use |=, repeating the assignment later is safe */ + } + + /* Completed MCU, so update state */ + BITREAD_SAVE_STATE(cinfo,entropy->bitstate); + + /* Account for restart interval (no-op if not using restarts) */ + entropy->restarts_to_go--; + + return TRUE; +} + + +/* + * MCU decoding for AC successive approximation refinement scan. + */ + +METHODDEF(boolean) +decode_mcu_AC_refine (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) +{ + j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec; + phuff_entropy_ptr entropy = (phuff_entropy_ptr) lossyd->entropy_private; + int Se = cinfo->Se; + int p1 = 1 << cinfo->Al; /* 1 in the bit position being coded */ + int m1 = (-1) << cinfo->Al; /* -1 in the bit position being coded */ + register int s, k, r; + unsigned int EOBRUN; + JBLOCKROW block; + JCOEFPTR thiscoef; + BITREAD_STATE_VARS; + d_derived_tbl * tbl; + int num_newnz; + int newnz_pos[DCTSIZE2]; + + /* Process restart marker if needed; may have to suspend */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) + if (! process_restart(cinfo)) + return FALSE; + } + + /* If we've run out of data, don't modify the MCU. + */ + if (! entropy->insufficient_data) { + + /* Load up working state */ + BITREAD_LOAD_STATE(cinfo,entropy->bitstate); + EOBRUN = entropy->saved.EOBRUN; /* only part of saved state we need */ + + /* There is always only one block per MCU */ + block = MCU_data[0]; + tbl = entropy->ac_derived_tbl; + + /* If we are forced to suspend, we must undo the assignments to any newly + * nonzero coefficients in the block, because otherwise we'd get confused + * next time about which coefficients were already nonzero. + * But we need not undo addition of bits to already-nonzero coefficients; + * instead, we can test the current bit to see if we already did it. + */ + num_newnz = 0; + + /* initialize coefficient loop counter to start of band */ + k = cinfo->Ss; + + if (EOBRUN == 0) { + for (; k <= Se; k++) { + HUFF_DECODE(s, br_state, tbl, goto undoit, label3); + r = s >> 4; + s &= 15; + if (s) { + if (s != 1) /* size of new coef should always be 1 */ + WARNMS(cinfo, JWRN_HUFF_BAD_CODE); + CHECK_BIT_BUFFER(br_state, 1, goto undoit); + if (GET_BITS(1)) + s = p1; /* newly nonzero coef is positive */ + else + s = m1; /* newly nonzero coef is negative */ + } else { + if (r != 15) { + EOBRUN = (unsigned int)(1 << r); /* EOBr, run length is 2^r + appended bits */ + if (r) { + CHECK_BIT_BUFFER(br_state, r, goto undoit); + r = GET_BITS(r); + EOBRUN += (unsigned int)r; + } + break; /* rest of block is handled by EOB logic */ + } + /* note s = 0 for processing ZRL */ + } + /* Advance over already-nonzero coefs and r still-zero coefs, + * appending correction bits to the nonzeroes. A correction bit is 1 + * if the absolute value of the coefficient must be increased. + */ + do { + thiscoef = *block + jpeg_natural_order[k]; + if (*thiscoef != 0) { + CHECK_BIT_BUFFER(br_state, 1, goto undoit); + if (GET_BITS(1)) { + if ((*thiscoef & p1) == 0) { /* do nothing if already set it */ + if (*thiscoef >= 0) + *thiscoef = (JCOEF)(*thiscoef + p1); + else + *thiscoef = (JCOEF)(*thiscoef + m1); + } + } + } else { + if (--r < 0) + break; /* reached target zero coefficient */ + } + k++; + } while (k <= Se); + if (s) { + int pos = jpeg_natural_order[k]; + /* Output newly nonzero coefficient */ + (*block)[pos] = (JCOEF) s; + /* Remember its position in case we have to suspend */ + newnz_pos[num_newnz++] = pos; + } + } + } + + if (EOBRUN > 0) { + /* Scan any remaining coefficient positions after the end-of-band + * (the last newly nonzero coefficient, if any). Append a correction + * bit to each already-nonzero coefficient. A correction bit is 1 + * if the absolute value of the coefficient must be increased. + */ + for (; k <= Se; k++) { + thiscoef = *block + jpeg_natural_order[k]; + if (*thiscoef != 0) { + CHECK_BIT_BUFFER(br_state, 1, goto undoit); + if (GET_BITS(1)) { + if ((*thiscoef & p1) == 0) { /* do nothing if already changed it */ + if (*thiscoef >= 0) + *thiscoef = (JCOEF)(*thiscoef + p1); + else + *thiscoef = (JCOEF)(*thiscoef + m1); + } + } + } + } + /* Count one block completed in EOB run */ + EOBRUN--; + } + + /* Completed MCU, so update state */ + BITREAD_SAVE_STATE(cinfo,entropy->bitstate); + entropy->saved.EOBRUN = EOBRUN; /* only part of saved state we need */ + } + + /* Account for restart interval (no-op if not using restarts) */ + entropy->restarts_to_go--; + + return TRUE; + +undoit: + /* Re-zero any output coefficients that we made newly nonzero */ + while (num_newnz > 0) + (*block)[newnz_pos[--num_newnz]] = 0; + + return FALSE; +} + + +/* + * Module initialization routine for progressive Huffman entropy decoding. + */ + +GLOBAL(void) +jinit_phuff_decoder (j_decompress_ptr cinfo) +{ + j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec; + phuff_entropy_ptr entropy; + int *coef_bit_ptr; + int ci, i; + + entropy = (phuff_entropy_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(phuff_entropy_decoder)); + lossyd->entropy_private = (void *) entropy; + lossyd->entropy_start_pass = start_pass_phuff_decoder; + + /* Mark derived tables unallocated */ + for (i = 0; i < NUM_HUFF_TBLS; i++) { + entropy->derived_tbls[i] = NULL; + } + + /* Create progression status table */ + cinfo->coef_bits = (int (*)[DCTSIZE2]) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (size_t)cinfo->num_components*DCTSIZE2*SIZEOF(int)); + coef_bit_ptr = & cinfo->coef_bits[0][0]; + for (ci = 0; ci < cinfo->num_components; ci++) + for (i = 0; i < DCTSIZE2; i++) + *coef_bit_ptr++ = -1; +} + +#endif /* D_PROGRESSIVE_SUPPORTED */ diff --git a/dcmjpeg/libijg16/jdpostct.c b/dcmjpeg/libijg16/jdpostct.c new file mode 100644 index 00000000..01c2b630 --- /dev/null +++ b/dcmjpeg/libijg16/jdpostct.c @@ -0,0 +1,290 @@ +/* + * jdpostct.c + * + * Copyright (C) 1994-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains the decompression postprocessing controller. + * This controller manages the upsampling, color conversion, and color + * quantization/reduction steps; specifically, it controls the buffering + * between upsample/color conversion and color quantization/reduction. + * + * If no color quantization/reduction is required, then this module has no + * work to do, and it just hands off to the upsample/color conversion code. + * An integrated upsample/convert/quantize process would replace this module + * entirely. + */ + +#define JPEG_INTERNALS +#include "jinclude16.h" +#include "jpeglib16.h" + + +/* Private buffer controller object */ + +typedef struct { + struct jpeg_d_post_controller pub; /* public fields */ + + /* Color quantization source buffer: this holds output data from + * the upsample/color conversion step to be passed to the quantizer. + * For two-pass color quantization, we need a full-image buffer; + * for one-pass operation, a strip buffer is sufficient. + */ + jvirt_sarray_ptr whole_image; /* virtual array, or NULL if one-pass */ + JSAMPARRAY buffer; /* strip buffer, or current strip of virtual */ + JDIMENSION strip_height; /* buffer size in rows */ + /* for two-pass mode only: */ + JDIMENSION starting_row; /* row # of first row in current strip */ + JDIMENSION next_row; /* index of next row to fill/empty in strip */ +} my_post_controller; + +typedef my_post_controller * my_post_ptr; + + +/* Forward declarations */ +METHODDEF(void) post_process_1pass + JPP((j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail)); +#ifdef QUANT_2PASS_SUPPORTED +METHODDEF(void) post_process_prepass + JPP((j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail)); +METHODDEF(void) post_process_2pass + JPP((j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail)); +#endif + + +/* + * Initialize for a processing pass. + */ + +METHODDEF(void) +start_pass_dpost (j_decompress_ptr cinfo, J_BUF_MODE pass_mode) +{ + my_post_ptr post = (my_post_ptr) cinfo->post; + + switch (pass_mode) { + case JBUF_PASS_THRU: + if (cinfo->quantize_colors) { + /* Single-pass processing with color quantization. */ + post->pub.post_process_data = post_process_1pass; + /* We could be doing buffered-image output before starting a 2-pass + * color quantization; in that case, jinit_d_post_controller did not + * allocate a strip buffer. Use the virtual-array buffer as workspace. + */ + if (post->buffer == NULL) { + post->buffer = (*cinfo->mem->access_virt_sarray) + ((j_common_ptr) cinfo, post->whole_image, + (JDIMENSION) 0, post->strip_height, TRUE); + } + } else { + /* For single-pass processing without color quantization, + * I have no work to do; just call the upsampler directly. + */ + post->pub.post_process_data = cinfo->upsample->upsample; + } + break; +#ifdef QUANT_2PASS_SUPPORTED + case JBUF_SAVE_AND_PASS: + /* First pass of 2-pass quantization */ + if (post->whole_image == NULL) + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + post->pub.post_process_data = post_process_prepass; + break; + case JBUF_CRANK_DEST: + /* Second pass of 2-pass quantization */ + if (post->whole_image == NULL) + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + post->pub.post_process_data = post_process_2pass; + break; +#endif /* QUANT_2PASS_SUPPORTED */ + default: + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + break; + } + post->starting_row = post->next_row = 0; +} + + +/* + * Process some data in the one-pass (strip buffer) case. + * This is used for color precision reduction as well as one-pass quantization. + */ + +METHODDEF(void) +post_process_1pass (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail) +{ + my_post_ptr post = (my_post_ptr) cinfo->post; + JDIMENSION num_rows, max_rows; + + /* Fill the buffer, but not more than what we can dump out in one go. */ + /* Note we rely on the upsampler to detect bottom of image. */ + max_rows = out_rows_avail - *out_row_ctr; + if (max_rows > post->strip_height) + max_rows = post->strip_height; + num_rows = 0; + (*cinfo->upsample->upsample) (cinfo, + input_buf, in_row_group_ctr, in_row_groups_avail, + post->buffer, &num_rows, max_rows); + /* Quantize and emit data. */ + (*cinfo->cquantize->color_quantize) (cinfo, + post->buffer, output_buf + *out_row_ctr, (int) num_rows); + *out_row_ctr += num_rows; +} + + +#ifdef QUANT_2PASS_SUPPORTED + +/* + * Process some data in the first pass of 2-pass quantization. + */ + +METHODDEF(void) +post_process_prepass (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail) +{ + my_post_ptr post = (my_post_ptr) cinfo->post; + JDIMENSION old_next_row, num_rows; + + /* Reposition virtual buffer if at start of strip. */ + if (post->next_row == 0) { + post->buffer = (*cinfo->mem->access_virt_sarray) + ((j_common_ptr) cinfo, post->whole_image, + post->starting_row, post->strip_height, TRUE); + } + + /* Upsample some data (up to a strip height's worth). */ + old_next_row = post->next_row; + (*cinfo->upsample->upsample) (cinfo, + input_buf, in_row_group_ctr, in_row_groups_avail, + post->buffer, &post->next_row, post->strip_height); + + /* Allow quantizer to scan new data. No data is emitted, */ + /* but we advance out_row_ctr so outer loop can tell when we're done. */ + if (post->next_row > old_next_row) { + num_rows = post->next_row - old_next_row; + (*cinfo->cquantize->color_quantize) (cinfo, post->buffer + old_next_row, + (JSAMPARRAY) NULL, (int) num_rows); + *out_row_ctr += num_rows; + } + + /* Advance if we filled the strip. */ + if (post->next_row >= post->strip_height) { + post->starting_row += post->strip_height; + post->next_row = 0; + } +} + + +/* + * Process some data in the second pass of 2-pass quantization. + */ + +METHODDEF(void) +post_process_2pass (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail) +{ + my_post_ptr post = (my_post_ptr) cinfo->post; + JDIMENSION num_rows, max_rows; + + /* Reposition virtual buffer if at start of strip. */ + if (post->next_row == 0) { + post->buffer = (*cinfo->mem->access_virt_sarray) + ((j_common_ptr) cinfo, post->whole_image, + post->starting_row, post->strip_height, FALSE); + } + + /* Determine number of rows to emit. */ + num_rows = post->strip_height - post->next_row; /* available in strip */ + max_rows = out_rows_avail - *out_row_ctr; /* available in output area */ + if (num_rows > max_rows) + num_rows = max_rows; + /* We have to check bottom of image here, can't depend on upsampler. */ + max_rows = cinfo->output_height - post->starting_row; + if (num_rows > max_rows) + num_rows = max_rows; + + /* Quantize and emit data. */ + (*cinfo->cquantize->color_quantize) (cinfo, + post->buffer + post->next_row, output_buf + *out_row_ctr, + (int) num_rows); + *out_row_ctr += num_rows; + + /* Advance if we filled the strip. */ + post->next_row += num_rows; + if (post->next_row >= post->strip_height) { + post->starting_row += post->strip_height; + post->next_row = 0; + } +} + +#endif /* QUANT_2PASS_SUPPORTED */ + + +/* + * Initialize postprocessing controller. + */ + +GLOBAL(void) +jinit_d_post_controller (j_decompress_ptr cinfo, boolean need_full_buffer) +{ + my_post_ptr post; + + post = (my_post_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_post_controller)); + cinfo->post = (struct jpeg_d_post_controller *) post; + post->pub.start_pass = start_pass_dpost; + post->whole_image = NULL; /* flag for no virtual arrays */ + post->buffer = NULL; /* flag for no strip buffer */ + + /* Create the quantization buffer, if needed */ + if (cinfo->quantize_colors) { + /* The buffer strip height is max_v_samp_factor, which is typically + * an efficient number of rows for upsampling to return. + * (In the presence of output rescaling, we might want to be smarter?) + */ + post->strip_height = (JDIMENSION) cinfo->max_v_samp_factor; + if (need_full_buffer) { + /* Two-pass color quantization: need full-image storage. */ + /* We round up the number of rows to a multiple of the strip height. */ +#ifdef QUANT_2PASS_SUPPORTED + post->whole_image = (*cinfo->mem->request_virt_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE, + cinfo->output_width * (JDIMENSION)cinfo->out_color_components, + (JDIMENSION) jround_up((long) cinfo->output_height, + (long) post->strip_height), + post->strip_height); +#else + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); +#endif /* QUANT_2PASS_SUPPORTED */ + } else { + /* One-pass color quantization: just make a strip buffer. */ + post->buffer = (*cinfo->mem->alloc_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + cinfo->output_width * (JDIMENSION)cinfo->out_color_components, + post->strip_height); + } + } +} diff --git a/dcmjpeg/libijg16/jdpred.c b/dcmjpeg/libijg16/jdpred.c new file mode 100644 index 00000000..78c182c5 --- /dev/null +++ b/dcmjpeg/libijg16/jdpred.c @@ -0,0 +1,279 @@ +/* + * jdpred.c + * + * Copyright (C) 1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains sample undifferencing (reconstruction) for lossless JPEG. + * + * In order to avoid paying the performance penalty of having to check the + * predictor being used and the row being processed for each call of the + * undifferencer, and to promote optimization, we have separate undifferencing + * functions for each case. + * + * We are able to avoid duplicating source code by implementing the predictors + * and undifferencers as macros. Each of the undifferencing functions are + * simply wrappers around an UNDIFFERENCE macro with the appropriate PREDICTOR + * macro passed as an argument. + */ + +#define JPEG_INTERNALS +#include "jinclude16.h" +#include "jpeglib16.h" +#include "jlossls16.h" /* Private declarations for lossless codec */ + + +#ifdef D_LOSSLESS_SUPPORTED + +/* Predictor for the first column of the first row: 2^(P-Pt-1) */ +#define INITIAL_PREDICTORx (1 << (cinfo->data_precision - cinfo->Al - 1)) + +/* Predictor for the first column of the remaining rows: Rb */ +#define INITIAL_PREDICTOR2 GETJSAMPLE(prev_row[0]) + + +/* + * 1-Dimensional undifferencer routine. + * + * This macro implements the 1-D horizontal predictor (1). INITIAL_PREDICTOR + * is used as the special case predictor for the first column, which must be + * either INITIAL_PREDICTOR2 or INITIAL_PREDICTORx. The remaining samples + * use PREDICTOR1. + * + * The reconstructed sample is supposed to be calculated modulo 2^16, so we + * logically AND the result with 0xFFFF. +*/ + +#define UNDIFFERENCE_1D(INITIAL_PREDICTOR) \ + unsigned int xindex; \ + int Ra; \ + \ + Ra = (diff_buf[0] + INITIAL_PREDICTOR) & 0xFFFF; \ + undiff_buf[0] = Ra; \ + \ + for (xindex = 1; xindex < width; xindex++) { \ + Ra = (diff_buf[xindex] + PREDICTOR1) & 0xFFFF; \ + undiff_buf[xindex] = Ra; \ + } + +/* + * 2-Dimensional undifferencer routine. + * + * This macro implements the 2-D horizontal predictors (#2-7). PREDICTOR2 is + * used as the special case predictor for the first column. The remaining + * samples use PREDICTOR, which is a function of Ra, Rb, Rc. + * + * Because prev_row and output_buf may point to the same storage area (in an + * interleaved image with Vi=1, for example), we must take care to buffer Rb/Rc + * before writing the current reconstructed sample value into output_buf. + * + * The reconstructed sample is supposed to be calculated modulo 2^16, so we + * logically AND the result with 0xFFFF. + */ + +#define UNDIFFERENCE_2D(PREDICTOR) \ + unsigned int xindex; \ + int Ra, Rb, Rc; \ + \ + Rb = GETJSAMPLE(prev_row[0]); \ + Ra = (diff_buf[0] + PREDICTOR2) & 0xFFFF; \ + undiff_buf[0] = Ra; \ + \ + for (xindex = 1; xindex < width; xindex++) { \ + Rc = Rb; \ + Rb = GETJSAMPLE(prev_row[xindex]); \ + Ra = (diff_buf[xindex] + PREDICTOR) & 0xFFFF; \ + undiff_buf[xindex] = Ra; \ + } + +#define JPEG_UNUSED(x) ((void)x) + +/* + * Undifferencers for the all rows but the first in a scan or restart interval. + * The first sample in the row is undifferenced using the vertical + * predictor (2). The rest of the samples are undifferenced using the + * predictor specified in the scan header. + */ + +METHODDEF(void) +jpeg_undifference1(j_decompress_ptr cinfo, int comp_index, + JDIFFROW diff_buf, JDIFFROW prev_row, + JDIFFROW undiff_buf, JDIMENSION width) +{ + UNDIFFERENCE_1D(INITIAL_PREDICTOR2); +} + +METHODDEF(void) +jpeg_undifference2(j_decompress_ptr cinfo, int comp_index, + JDIFFROW diff_buf, JDIFFROW prev_row, + JDIFFROW undiff_buf, JDIMENSION width) +{ + UNDIFFERENCE_2D(PREDICTOR2); + JPEG_UNUSED(Rc); + JPEG_UNUSED(Rb); +} + +METHODDEF(void) +jpeg_undifference3(j_decompress_ptr cinfo, int comp_index, + JDIFFROW diff_buf, JDIFFROW prev_row, + JDIFFROW undiff_buf, JDIMENSION width) +{ + UNDIFFERENCE_2D(PREDICTOR3); + JPEG_UNUSED(Rc); + JPEG_UNUSED(Rb); +} + +METHODDEF(void) +jpeg_undifference4(j_decompress_ptr cinfo, int comp_index, + JDIFFROW diff_buf, JDIFFROW prev_row, + JDIFFROW undiff_buf, JDIMENSION width) +{ + UNDIFFERENCE_2D(PREDICTOR4); + JPEG_UNUSED(Rc); + JPEG_UNUSED(Rb); +} + +METHODDEF(void) +jpeg_undifference5(j_decompress_ptr cinfo, int comp_index, + JDIFFROW diff_buf, JDIFFROW prev_row, + JDIFFROW undiff_buf, JDIMENSION width) +{ + SHIFT_TEMPS + UNDIFFERENCE_2D(PREDICTOR5); + JPEG_UNUSED(Rc); + JPEG_UNUSED(Rb); +} + +METHODDEF(void) +jpeg_undifference6(j_decompress_ptr cinfo, int comp_index, + JDIFFROW diff_buf, JDIFFROW prev_row, + JDIFFROW undiff_buf, JDIMENSION width) +{ + SHIFT_TEMPS + UNDIFFERENCE_2D(PREDICTOR6); + JPEG_UNUSED(Rc); + JPEG_UNUSED(Rb); +} + +METHODDEF(void) +jpeg_undifference6a(j_decompress_ptr cinfo, int comp_index, + JDIFFROW diff_buf, JDIFFROW prev_row, + JDIFFROW undiff_buf, JDIMENSION width) +{ + SHIFT_TEMPS + UNDIFFERENCE_2D(PREDICTOR6A); + JPEG_UNUSED(Rc); + JPEG_UNUSED(Rb); +} + +METHODDEF(void) +jpeg_undifference7(j_decompress_ptr cinfo, int comp_index, + JDIFFROW diff_buf, JDIFFROW prev_row, + JDIFFROW undiff_buf, JDIMENSION width) +{ + SHIFT_TEMPS + UNDIFFERENCE_2D(PREDICTOR7); + JPEG_UNUSED(Rc); + JPEG_UNUSED(Rb); +} + + +/* + * Undifferencer for the first row in a scan or restart interval. The first + * sample in the row is undifferenced using the special predictor constant + * x=2^(P-Pt-1). The rest of the samples are undifferenced using the + * 1-D horizontal predictor (1). + */ + +METHODDEF(void) +jpeg_undifference_first_row(j_decompress_ptr cinfo, int comp_index, + JDIFFROW diff_buf, JDIFFROW prev_row, + JDIFFROW undiff_buf, JDIMENSION width) +{ + j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec; + + UNDIFFERENCE_1D(INITIAL_PREDICTORx); + + /* + * Now that we have undifferenced the first row, we want to use the + * undifferencer which corresponds to the predictor specified in the + * scan header. + */ + switch (cinfo->Ss) { + case 1: + losslsd->predict_undifference[comp_index] = jpeg_undifference1; + break; + case 2: + losslsd->predict_undifference[comp_index] = jpeg_undifference2; + break; + case 3: + losslsd->predict_undifference[comp_index] = jpeg_undifference3; + break; + case 4: + losslsd->predict_undifference[comp_index] = jpeg_undifference4; + break; + case 5: + losslsd->predict_undifference[comp_index] = jpeg_undifference5; + break; + case 6: + /* DCMTK specific code that is only needed in the 16-bit library. + * Enables workaround for faulty images with integer overflow in predictor 6. + */ + if (cinfo->workaround_options & WORKAROUND_PREDICTOR6OVERFLOW) + losslsd->predict_undifference[comp_index] = jpeg_undifference6a; + else losslsd->predict_undifference[comp_index] = jpeg_undifference6; + break; + case 7: + losslsd->predict_undifference[comp_index] = jpeg_undifference7; + break; + } +} + + +/* + * Initialize for an input processing pass. + */ + +METHODDEF(void) +predict_start_pass (j_decompress_ptr cinfo) +{ + j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec; + int ci; + + /* Check that the scan parameters Ss, Se, Ah, Al are OK for lossless JPEG. + * + * Ss is the predictor selection value (psv). Legal values for sequential + * lossless JPEG are: 1 <= psv <= 7. + * + * Se and Ah are not used and should be zero. + * + * Al specifies the point transform (Pt). Legal values are: 0 <= Pt <= 15. + */ + if (cinfo->Ss < 1 || cinfo->Ss > 7 || + cinfo->Se != 0 || cinfo->Ah != 0 || + cinfo->Al > 15) /* need not check for < 0 */ + ERREXIT4(cinfo, JERR_BAD_LOSSLESS, + cinfo->Ss, cinfo->Se, cinfo->Ah, cinfo->Al); + + /* Set undifference functions to first row function */ + for (ci = 0; ci < cinfo->num_components; ci++) + losslsd->predict_undifference[ci] = jpeg_undifference_first_row; +} + + +/* + * Module initialization routine for the undifferencer. + */ + +GLOBAL(void) +jinit_undifferencer (j_decompress_ptr cinfo) +{ + j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec; + + losslsd->predict_start_pass = predict_start_pass; + losslsd->predict_process_restart = predict_start_pass; +} + +#endif /* D_LOSSLESS_SUPPORTED */ + diff --git a/dcmjpeg/libijg16/jdsample.c b/dcmjpeg/libijg16/jdsample.c new file mode 100644 index 00000000..cd3b60fa --- /dev/null +++ b/dcmjpeg/libijg16/jdsample.c @@ -0,0 +1,478 @@ +/* + * jdsample.c + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains upsampling routines. + * + * Upsampling input data is counted in "row groups". A row group + * is defined to be (v_samp_factor * codec_data_unit / min_codec_data_unit) + * sample rows of each component. Upsampling will normally produce + * max_v_samp_factor pixel rows from each row group (but this could vary + * if the upsampler is applying a scale factor of its own). + * + * An excellent reference for image resampling is + * Digital Image Warping, George Wolberg, 1990. + * Pub. by IEEE Computer Society Press, Los Alamitos, CA. ISBN 0-8186-8944-7. + */ + +#define JPEG_INTERNALS +#include "jinclude16.h" +#include "jpeglib16.h" + + +/* Pointer to routine to upsample a single component */ +typedef JMETHOD(void, upsample1_ptr, + (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr)); + +/* Private subobject */ + +typedef struct { + struct jpeg_upsampler pub; /* public fields */ + + /* Color conversion buffer. When using separate upsampling and color + * conversion steps, this buffer holds one upsampled row group until it + * has been color converted and output. + * Note: we do not allocate any storage for component(s) which are full-size, + * ie do not need rescaling. The corresponding entry of color_buf[] is + * simply set to point to the input data array, thereby avoiding copying. + */ + JSAMPARRAY color_buf[MAX_COMPONENTS]; + + /* Per-component upsampling method pointers */ + upsample1_ptr methods[MAX_COMPONENTS]; + + int next_row_out; /* counts rows emitted from color_buf */ + JDIMENSION rows_to_go; /* counts rows remaining in image */ + + /* Height of an input row group for each component. */ + int rowgroup_height[MAX_COMPONENTS]; + + /* These arrays save pixel expansion factors so that int_expand need not + * recompute them each time. They are unused for other upsampling methods. + */ + UINT8 h_expand[MAX_COMPONENTS]; + UINT8 v_expand[MAX_COMPONENTS]; +} my_upsampler; + +typedef my_upsampler * my_upsample_ptr; + + +/* + * Initialize for an upsampling pass. + */ + +METHODDEF(void) +start_pass_upsample (j_decompress_ptr cinfo) +{ + my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; + + /* Mark the conversion buffer empty */ + upsample->next_row_out = cinfo->max_v_samp_factor; + /* Initialize total-height counter for detecting bottom of image */ + upsample->rows_to_go = cinfo->output_height; +} + + +/* + * Control routine to do upsampling (and color conversion). + * + * In this version we upsample each component independently. + * We upsample one row group into the conversion buffer, then apply + * color conversion a row at a time. + */ + +METHODDEF(void) +sep_upsample (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail) +{ + my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; + int ci; + jpeg_component_info * compptr; + JDIMENSION num_rows; + + /* Fill the conversion buffer, if it's empty */ + if (upsample->next_row_out >= cinfo->max_v_samp_factor) { + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + /* Invoke per-component upsample method. Notice we pass a POINTER + * to color_buf[ci], so that fullsize_upsample can change it. + */ + (*upsample->methods[ci]) (cinfo, compptr, + input_buf[ci] + (*in_row_group_ctr * (JDIMENSION)upsample->rowgroup_height[ci]), + upsample->color_buf + ci); + } + upsample->next_row_out = 0; + } + + /* Color-convert and emit rows */ + + /* How many we have in the buffer: */ + num_rows = (JDIMENSION) (cinfo->max_v_samp_factor - upsample->next_row_out); + /* Not more than the distance to the end of the image. Need this test + * in case the image height is not a multiple of max_v_samp_factor: + */ + if (num_rows > upsample->rows_to_go) + num_rows = upsample->rows_to_go; + /* And not more than what the client can accept: */ + out_rows_avail -= *out_row_ctr; + if (num_rows > out_rows_avail) + num_rows = out_rows_avail; + + (*cinfo->cconvert->color_convert) (cinfo, upsample->color_buf, + (JDIMENSION) upsample->next_row_out, + output_buf + *out_row_ctr, + (int) num_rows); + + /* Adjust counts */ + *out_row_ctr += num_rows; + upsample->rows_to_go -= num_rows; + upsample->next_row_out += (int)num_rows; + /* When the buffer is emptied, declare this input row group consumed */ + if (upsample->next_row_out >= cinfo->max_v_samp_factor) + (*in_row_group_ctr)++; +} + + +/* + * These are the routines invoked by sep_upsample to upsample pixel values + * of a single component. One row group is processed per call. + */ + + +/* + * For full-size components, we just make color_buf[ci] point at the + * input buffer, and thus avoid copying any data. Note that this is + * safe only because sep_upsample doesn't declare the input row group + * "consumed" until we are done color converting and emitting it. + */ + +METHODDEF(void) +fullsize_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) +{ + *output_data_ptr = input_data; +} + + +/* + * This is a no-op version used for "uninteresting" components. + * These components will not be referenced by color conversion. + */ + +METHODDEF(void) +noop_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) +{ + *output_data_ptr = NULL; /* safety check */ +} + + +/* + * This version handles any integral sampling ratios. + * This is not used for typical JPEG files, so it need not be fast. + * Nor, for that matter, is it particularly accurate: the algorithm is + * simple replication of the input pixel onto the corresponding output + * pixels. The hi-falutin sampling literature refers to this as a + * "box filter". A box filter tends to introduce visible artifacts, + * so if you are actually going to use 3:1 or 4:1 sampling ratios + * you would be well advised to improve this code. + */ + +METHODDEF(void) +int_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) +{ + my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; + JSAMPARRAY output_data = *output_data_ptr; + register JSAMPROW inptr, outptr; + register JSAMPLE invalue; + register int h; + JSAMPROW outend; + int h_expand, v_expand; + int inrow, outrow; + + h_expand = upsample->h_expand[compptr->component_index]; + v_expand = upsample->v_expand[compptr->component_index]; + + inrow = outrow = 0; + while (outrow < cinfo->max_v_samp_factor) { + /* Generate one output row with proper horizontal expansion */ + inptr = input_data[inrow]; + outptr = output_data[outrow]; + outend = outptr + cinfo->output_width; + while (outptr < outend) { + invalue = *inptr++; /* don't need GETJSAMPLE() here */ + for (h = h_expand; h > 0; h--) { + *outptr++ = invalue; + } + } + /* Generate any additional output rows by duplicating the first one */ + if (v_expand > 1) { + jcopy_sample_rows(output_data, outrow, output_data, outrow+1, + v_expand-1, cinfo->output_width); + } + inrow++; + outrow += v_expand; + } +} + + +/* + * Fast processing for the common case of 2:1 horizontal and 1:1 vertical. + * It's still a box filter. + */ + +METHODDEF(void) +h2v1_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) +{ + JSAMPARRAY output_data = *output_data_ptr; + register JSAMPROW inptr, outptr; + register JSAMPLE invalue; + JSAMPROW outend; + int inrow; + + for (inrow = 0; inrow < cinfo->max_v_samp_factor; inrow++) { + inptr = input_data[inrow]; + outptr = output_data[inrow]; + outend = outptr + cinfo->output_width; + while (outptr < outend) { + invalue = *inptr++; /* don't need GETJSAMPLE() here */ + *outptr++ = invalue; + *outptr++ = invalue; + } + } +} + + +/* + * Fast processing for the common case of 2:1 horizontal and 2:1 vertical. + * It's still a box filter. + */ + +METHODDEF(void) +h2v2_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) +{ + JSAMPARRAY output_data = *output_data_ptr; + register JSAMPROW inptr, outptr; + register JSAMPLE invalue; + JSAMPROW outend; + int inrow, outrow; + + inrow = outrow = 0; + while (outrow < cinfo->max_v_samp_factor) { + inptr = input_data[inrow]; + outptr = output_data[outrow]; + outend = outptr + cinfo->output_width; + while (outptr < outend) { + invalue = *inptr++; /* don't need GETJSAMPLE() here */ + *outptr++ = invalue; + *outptr++ = invalue; + } + jcopy_sample_rows(output_data, outrow, output_data, outrow+1, + 1, cinfo->output_width); + inrow++; + outrow += 2; + } +} + + +/* + * Fancy processing for the common case of 2:1 horizontal and 1:1 vertical. + * + * The upsampling algorithm is linear interpolation between pixel centers, + * also known as a "triangle filter". This is a good compromise between + * speed and visual quality. The centers of the output pixels are 1/4 and 3/4 + * of the way between input pixel centers. + * + * A note about the "bias" calculations: when rounding fractional values to + * integer, we do not want to always round 0.5 up to the next integer. + * If we did that, we'd introduce a noticeable bias towards larger values. + * Instead, this code is arranged so that 0.5 will be rounded up or down at + * alternate pixel locations (a simple ordered dither pattern). + */ + +METHODDEF(void) +h2v1_fancy_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) +{ + JSAMPARRAY output_data = *output_data_ptr; + register JSAMPROW inptr, outptr; + register int invalue; + register JDIMENSION colctr; + int inrow; + + for (inrow = 0; inrow < cinfo->max_v_samp_factor; inrow++) { + inptr = input_data[inrow]; + outptr = output_data[inrow]; + /* Special case for first column */ + invalue = GETJSAMPLE(*inptr++); + *outptr++ = (JSAMPLE) invalue; + *outptr++ = (JSAMPLE) ((invalue * 3 + GETJSAMPLE(*inptr) + 2) >> 2); + + for (colctr = compptr->downsampled_width - 2; colctr > 0; colctr--) { + /* General case: 3/4 * nearer pixel + 1/4 * further pixel */ + invalue = GETJSAMPLE(*inptr++) * 3; + *outptr++ = (JSAMPLE) ((invalue + GETJSAMPLE(inptr[-2]) + 1) >> 2); + *outptr++ = (JSAMPLE) ((invalue + GETJSAMPLE(*inptr) + 2) >> 2); + } + + /* Special case for last column */ + invalue = GETJSAMPLE(*inptr); + *outptr++ = (JSAMPLE) ((invalue * 3 + GETJSAMPLE(inptr[-1]) + 1) >> 2); + *outptr++ = (JSAMPLE) invalue; + } +} + + +/* + * Fancy processing for the common case of 2:1 horizontal and 2:1 vertical. + * Again a triangle filter; see comments for h2v1 case, above. + * + * It is OK for us to reference the adjacent input rows because we demanded + * context from the main buffer controller (see initialization code). + */ + +METHODDEF(void) +h2v2_fancy_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) +{ + JSAMPARRAY output_data = *output_data_ptr; + register JSAMPROW inptr0, inptr1, outptr; +#if BITS_IN_JSAMPLE == 8 + register int thiscolsum, lastcolsum, nextcolsum; +#else + register IJG_INT32 thiscolsum, lastcolsum, nextcolsum; +#endif + register JDIMENSION colctr; + int inrow, outrow, v; + + inrow = outrow = 0; + while (outrow < cinfo->max_v_samp_factor) { + for (v = 0; v < 2; v++) { + /* inptr0 points to nearest input row, inptr1 points to next nearest */ + inptr0 = input_data[inrow]; + if (v == 0) /* next nearest is row above */ + inptr1 = input_data[inrow-1]; + else /* next nearest is row below */ + inptr1 = input_data[inrow+1]; + outptr = output_data[outrow++]; + + /* Special case for first column */ + thiscolsum = GETJSAMPLE(*inptr0++) * 3 + GETJSAMPLE(*inptr1++); + nextcolsum = GETJSAMPLE(*inptr0++) * 3 + GETJSAMPLE(*inptr1++); + *outptr++ = (JSAMPLE) ((thiscolsum * 4 + 8) >> 4); + *outptr++ = (JSAMPLE) ((thiscolsum * 3 + nextcolsum + 7) >> 4); + lastcolsum = thiscolsum; thiscolsum = nextcolsum; + + for (colctr = compptr->downsampled_width - 2; colctr > 0; colctr--) { + /* General case: 3/4 * nearer pixel + 1/4 * further pixel in each */ + /* dimension, thus 9/16, 3/16, 3/16, 1/16 overall */ + nextcolsum = GETJSAMPLE(*inptr0++) * 3 + GETJSAMPLE(*inptr1++); + *outptr++ = (JSAMPLE) ((thiscolsum * 3 + lastcolsum + 8) >> 4); + *outptr++ = (JSAMPLE) ((thiscolsum * 3 + nextcolsum + 7) >> 4); + lastcolsum = thiscolsum; thiscolsum = nextcolsum; + } + + /* Special case for last column */ + *outptr++ = (JSAMPLE) ((thiscolsum * 3 + lastcolsum + 8) >> 4); + *outptr++ = (JSAMPLE) ((thiscolsum * 4 + 7) >> 4); + } + inrow++; + } +} + + +/* + * Module initialization routine for upsampling. + */ + +GLOBAL(void) +jinit_upsampler (j_decompress_ptr cinfo) +{ + my_upsample_ptr upsample; + int ci; + jpeg_component_info * compptr; + boolean need_buffer, do_fancy; + int h_in_group, v_in_group, h_out_group, v_out_group; + + upsample = (my_upsample_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_upsampler)); + cinfo->upsample = (struct jpeg_upsampler *) upsample; + upsample->pub.start_pass = start_pass_upsample; + upsample->pub.upsample = sep_upsample; + upsample->pub.need_context_rows = FALSE; /* until we find out differently */ + + if (cinfo->CCIR601_sampling) /* this isn't supported */ + ERREXIT(cinfo, JERR_CCIR601_NOTIMPL); + + /* jdmainct.c doesn't support context rows when min_codec_data_unit = 1, + * so don't ask for it. + */ + do_fancy = cinfo->do_fancy_upsampling && cinfo->min_codec_data_unit > 1; + + /* Verify we can handle the sampling factors, select per-component methods, + * and create storage as needed. + */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + /* Compute size of an "input group" after IDCT scaling. This many samples + * are to be converted to max_h_samp_factor * max_v_samp_factor pixels. + */ + h_in_group = (compptr->h_samp_factor * compptr->codec_data_unit) / + cinfo->min_codec_data_unit; + v_in_group = (compptr->v_samp_factor * compptr->codec_data_unit) / + cinfo->min_codec_data_unit; + h_out_group = cinfo->max_h_samp_factor; + v_out_group = cinfo->max_v_samp_factor; + upsample->rowgroup_height[ci] = v_in_group; /* save for use later */ + need_buffer = TRUE; + if (! compptr->component_needed) { + /* Don't bother to upsample an uninteresting component. */ + upsample->methods[ci] = noop_upsample; + need_buffer = FALSE; + } else if (h_in_group == h_out_group && v_in_group == v_out_group) { + /* Fullsize components can be processed without any work. */ + upsample->methods[ci] = fullsize_upsample; + need_buffer = FALSE; + } else if (h_in_group * 2 == h_out_group && + v_in_group == v_out_group) { + /* Special cases for 2h1v upsampling */ + if (do_fancy && compptr->downsampled_width > 2) + upsample->methods[ci] = h2v1_fancy_upsample; + else + upsample->methods[ci] = h2v1_upsample; + } else if (h_in_group * 2 == h_out_group && + v_in_group * 2 == v_out_group) { + /* Special cases for 2h2v upsampling */ + if (do_fancy && compptr->downsampled_width > 2) { + upsample->methods[ci] = h2v2_fancy_upsample; + upsample->pub.need_context_rows = TRUE; + } else + upsample->methods[ci] = h2v2_upsample; + } else if ((h_out_group % h_in_group) == 0 && + (v_out_group % v_in_group) == 0) { + /* Generic integral-factors upsampling method */ + upsample->methods[ci] = int_upsample; + upsample->h_expand[ci] = (UINT8) (h_out_group / h_in_group); + upsample->v_expand[ci] = (UINT8) (v_out_group / v_in_group); + } else + ERREXIT(cinfo, JERR_FRACT_SAMPLE_NOTIMPL); + if (need_buffer) { + upsample->color_buf[ci] = (*cinfo->mem->alloc_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + (JDIMENSION) jround_up((long) cinfo->output_width, + (long) cinfo->max_h_samp_factor), + (JDIMENSION) cinfo->max_v_samp_factor); + } + } +} diff --git a/dcmjpeg/libijg16/jdscale.c b/dcmjpeg/libijg16/jdscale.c new file mode 100644 index 00000000..88e24c49 --- /dev/null +++ b/dcmjpeg/libijg16/jdscale.c @@ -0,0 +1,119 @@ +/* + * jdscale.c + * + * Copyright (C) 1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains sample scaling for lossless JPEG. This is a + * combination of upscaling the undifferenced sample by 2^Pt and downscaling + * the sample to fit into JSAMPLE. + */ + +#define JPEG_INTERNALS +#include "jinclude16.h" +#include "jpeglib16.h" +#include "jlossls16.h" /* Private declarations for lossless codec */ + + +#ifdef D_LOSSLESS_SUPPORTED + +/* + * Private scaler object for lossless decoding. + */ + +typedef struct { + int scale_factor; +} scaler; + +typedef scaler * scaler_ptr; + + +/* + * Scalers for packing sample differences into JSAMPLEs. + */ + +METHODDEF(void) +simple_upscale(j_decompress_ptr cinfo, + JDIFFROW diff_buf, JSAMPROW output_buf, + JDIMENSION width) +{ + j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec; + scaler_ptr scale = (scaler_ptr) losslsd->scaler_private; + int scale_factor = scale->scale_factor; + unsigned int xindex; + + for (xindex = 0; xindex < width; xindex++) + output_buf[xindex] = (JSAMPLE) (diff_buf[xindex] << scale_factor); +} + +METHODDEF(void) +simple_downscale(j_decompress_ptr cinfo, + JDIFFROW diff_buf, JSAMPROW output_buf, + JDIMENSION width) +{ + j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec; + scaler_ptr scale = (scaler_ptr) losslsd->scaler_private; + int scale_factor = scale->scale_factor; + unsigned int xindex; + SHIFT_TEMPS + + for (xindex = 0; xindex < width; xindex++) + output_buf[xindex] = (JSAMPLE) RIGHT_SHIFT(diff_buf[xindex], scale_factor); +} + +METHODDEF(void) +noscale(j_decompress_ptr cinfo, + JDIFFROW diff_buf, JSAMPROW output_buf, + JDIMENSION width) +{ + unsigned int xindex; + + for (xindex = 0; xindex < width; xindex++) + output_buf[xindex] = (JSAMPLE) diff_buf[xindex]; +} + + +METHODDEF(void) +scaler_start_pass (j_decompress_ptr cinfo) +{ + j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec; + scaler_ptr scale = (scaler_ptr) losslsd->scaler_private; + int downscale; + + /* + * Downscale by the difference in the input vs. output precision. If the + * output precision >= input precision, then do not downscale. + */ + downscale = BITS_IN_JSAMPLE < cinfo->data_precision ? + cinfo->data_precision - BITS_IN_JSAMPLE : 0; + + scale->scale_factor = cinfo->Al - downscale; + + /* Set scaler functions based on scale_factor (positive = left shift) */ + if (scale->scale_factor > 0) + losslsd->scaler_scale = simple_upscale; + else if (scale->scale_factor < 0) { + scale->scale_factor = -scale->scale_factor; + losslsd->scaler_scale = simple_downscale; + } + else + losslsd->scaler_scale = noscale; +} + + +GLOBAL(void) +jinit_d_scaler (j_decompress_ptr cinfo) +{ + j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec; + scaler_ptr scale; + + scale = (scaler_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(scaler)); + losslsd->scaler_private = (void *) scale; + losslsd->scaler_start_pass = scaler_start_pass; +} + +#endif /* D_LOSSLESS_SUPPORTED */ + diff --git a/dcmjpeg/libijg16/jdshuff.c b/dcmjpeg/libijg16/jdshuff.c new file mode 100644 index 00000000..342c5895 --- /dev/null +++ b/dcmjpeg/libijg16/jdshuff.c @@ -0,0 +1,360 @@ +/* + * jdshuff.c + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains Huffman entropy decoding routines for sequential JPEG. + * + * Much of the complexity here has to do with supporting input suspension. + * If the data source module demands suspension, we want to be able to back + * up to the start of the current MCU. To do this, we copy state variables + * into local working storage, and update them back to the permanent + * storage only upon successful completion of an MCU. + */ + +#define JPEG_INTERNALS +#include "jinclude16.h" +#include "jpeglib16.h" +#include "jlossy16.h" /* Private declarations for lossy codec */ +#include "jdhuff16.h" /* Declarations shared with jd*huff.c */ + + +/* + * Private entropy decoder object for Huffman decoding. + * + * The savable_state subrecord contains fields that change within an MCU, + * but must not be updated permanently until we complete the MCU. + */ + +typedef struct { + int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */ +} savable_state; + +/* This macro is to work around compilers with missing or broken + * structure assignment. You'll need to fix this code if you have + * such a compiler and you change MAX_COMPS_IN_SCAN. + */ + +#ifndef NO_STRUCT_ASSIGN +#define ASSIGN_STATE(dest,src) ((dest) = (src)) +#else +#if MAX_COMPS_IN_SCAN == 4 +#define ASSIGN_STATE(dest,src) \ + ((dest).last_dc_val[0] = (src).last_dc_val[0], \ + (dest).last_dc_val[1] = (src).last_dc_val[1], \ + (dest).last_dc_val[2] = (src).last_dc_val[2], \ + (dest).last_dc_val[3] = (src).last_dc_val[3]) +#endif +#endif + + +typedef struct { + huffd_common_fields; /* Fields shared with other entropy decoders */ + + /* These fields are loaded into local variables at start of each MCU. + * In case of suspension, we exit WITHOUT updating them. + */ + savable_state saved; /* Other state at start of MCU */ + + /* These fields are NOT loaded into local working state. */ + unsigned int restarts_to_go; /* MCUs left in this restart interval */ + + /* Pointers to derived tables (these workspaces have image lifespan) */ + d_derived_tbl * dc_derived_tbls[NUM_HUFF_TBLS]; + d_derived_tbl * ac_derived_tbls[NUM_HUFF_TBLS]; + + /* Precalculated info set up by start_pass for use in decode_mcu: */ + + /* Pointers to derived tables to be used for each block within an MCU */ + d_derived_tbl * dc_cur_tbls[D_MAX_DATA_UNITS_IN_MCU]; + d_derived_tbl * ac_cur_tbls[D_MAX_DATA_UNITS_IN_MCU]; + /* Whether we care about the DC and AC coefficient values for each block */ + boolean dc_needed[D_MAX_DATA_UNITS_IN_MCU]; + boolean ac_needed[D_MAX_DATA_UNITS_IN_MCU]; +} shuff_entropy_decoder; + +typedef shuff_entropy_decoder * shuff_entropy_ptr; + + +/* + * Initialize for a Huffman-compressed scan. + */ + +METHODDEF(void) +start_pass_huff_decoder (j_decompress_ptr cinfo) +{ + j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec; + shuff_entropy_ptr entropy = (shuff_entropy_ptr) lossyd->entropy_private; + int ci, blkn, dctbl, actbl; + jpeg_component_info * compptr; + + /* Check that the scan parameters Ss, Se, Ah/Al are OK for sequential JPEG. + * This ought to be an error condition, but we make it a warning because + * there are some baseline files out there with all zeroes in these bytes. + */ + if (cinfo->Ss != 0 || cinfo->Se != DCTSIZE2-1 || + cinfo->Ah != 0 || cinfo->Al != 0) + WARNMS(cinfo, JWRN_NOT_SEQUENTIAL); + + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + dctbl = compptr->dc_tbl_no; + actbl = compptr->ac_tbl_no; + /* Compute derived values for Huffman tables */ + /* We may do this more than once for a table, but it's not expensive */ + jpeg_make_d_derived_tbl(cinfo, TRUE, dctbl, + & entropy->dc_derived_tbls[dctbl]); + jpeg_make_d_derived_tbl(cinfo, FALSE, actbl, + & entropy->ac_derived_tbls[actbl]); + /* Initialize DC predictions to 0 */ + entropy->saved.last_dc_val[ci] = 0; + } + + /* Precalculate decoding info for each block in an MCU of this scan */ + for (blkn = 0; blkn < cinfo->data_units_in_MCU; blkn++) { + ci = cinfo->MCU_membership[blkn]; + compptr = cinfo->cur_comp_info[ci]; + /* Precalculate which table to use for each block */ + entropy->dc_cur_tbls[blkn] = entropy->dc_derived_tbls[compptr->dc_tbl_no]; + entropy->ac_cur_tbls[blkn] = entropy->ac_derived_tbls[compptr->ac_tbl_no]; + /* Decide whether we really care about the coefficient values */ + if (compptr->component_needed) { + entropy->dc_needed[blkn] = TRUE; + /* we don't need the ACs if producing a 1/8th-size image */ + entropy->ac_needed[blkn] = (compptr->codec_data_unit > 1); + } else { + entropy->dc_needed[blkn] = entropy->ac_needed[blkn] = FALSE; + } + } + + /* Initialize bitread state variables */ + entropy->bitstate.bits_left = 0; + entropy->bitstate.get_buffer = 0; /* unnecessary, but keeps Purify quiet */ + entropy->insufficient_data = FALSE; + + /* Initialize restart counter */ + entropy->restarts_to_go = cinfo->restart_interval; +} + + +/* + * Figure F.12: extend sign bit. + * On some machines, a shift and add will be faster than a table lookup. + */ + +#ifdef AVOID_TABLES + +#define HUFF_EXTEND(x,s) ((x) < (1<<((s)-1)) ? (x) + (((-1)<<(s)) + 1) : (x)) + +#else + +#define HUFF_EXTEND(x,s) ((x) < extend_test[s] ? (x) + extend_offset[s] : (x)) + +static const int extend_test[16] = /* entry n is 2**(n-1) */ + { 0, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080, + 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000 }; + +static const int extend_offset[16] = /* entry n is (-1 << n) + 1 */ + { 0, ((-1)<<1) + 1, ((-1)<<2) + 1, ((-1)<<3) + 1, ((-1)<<4) + 1, + ((-1)<<5) + 1, ((-1)<<6) + 1, ((-1)<<7) + 1, ((-1)<<8) + 1, + ((-1)<<9) + 1, ((-1)<<10) + 1, ((-1)<<11) + 1, ((-1)<<12) + 1, + ((-1)<<13) + 1, ((-1)<<14) + 1, ((-1)<<15) + 1 }; + +#endif /* AVOID_TABLES */ + + +/* + * Check for a restart marker & resynchronize decoder. + * Returns FALSE if must suspend. + */ + +LOCAL(boolean) +process_restart (j_decompress_ptr cinfo) +{ + j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec; + shuff_entropy_ptr entropy = (shuff_entropy_ptr) lossyd->entropy_private; + int ci; + + /* Throw away any unused bits remaining in bit buffer; */ + /* include any full bytes in next_marker's count of discarded bytes */ + cinfo->marker->discarded_bytes += (unsigned int)(entropy->bitstate.bits_left / 8); + entropy->bitstate.bits_left = 0; + + /* Advance past the RSTn marker */ + if (! (*cinfo->marker->read_restart_marker) (cinfo)) + return FALSE; + + /* Re-initialize DC predictions to 0 */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) + entropy->saved.last_dc_val[ci] = 0; + + /* Reset restart counter */ + entropy->restarts_to_go = cinfo->restart_interval; + + /* Reset out-of-data flag, unless read_restart_marker left us smack up + * against a marker. In that case we will end up treating the next data + * segment as empty, and we can avoid producing bogus output pixels by + * leaving the flag set. + */ + if (cinfo->unread_marker == 0) + entropy->insufficient_data = FALSE; + + return TRUE; +} + + +/* + * Decode and return one MCU's worth of Huffman-compressed coefficients. + * The coefficients are reordered from zigzag order into natural array order, + * but are not dequantized. + * + * The i'th block of the MCU is stored into the block pointed to by + * MCU_data[i]. WE ASSUME THIS AREA HAS BEEN ZEROED BY THE CALLER. + * (Wholesale zeroing is usually a little faster than retail...) + * + * Returns FALSE if data source requested suspension. In that case no + * changes have been made to permanent state. (Exception: some output + * coefficients may already have been assigned. This is harmless for + * this module, since we'll just re-assign them on the next call.) + */ + +METHODDEF(boolean) +decode_mcu (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) +{ + j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec; + shuff_entropy_ptr entropy = (shuff_entropy_ptr) lossyd->entropy_private; + int blkn; + BITREAD_STATE_VARS; + savable_state state; + + /* Process restart marker if needed; may have to suspend */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) + if (! process_restart(cinfo)) + return FALSE; + } + + /* If we've run out of data, just leave the MCU set to zeroes. + * This way, we return uniform gray for the remainder of the segment. + */ + if (! entropy->insufficient_data) { + + /* Load up working state */ + BITREAD_LOAD_STATE(cinfo,entropy->bitstate); + ASSIGN_STATE(state, entropy->saved); + + /* Outer loop handles each block in the MCU */ + + for (blkn = 0; blkn < cinfo->data_units_in_MCU; blkn++) { + JBLOCKROW block = MCU_data[blkn]; + d_derived_tbl * dctbl = entropy->dc_cur_tbls[blkn]; + d_derived_tbl * actbl = entropy->ac_cur_tbls[blkn]; + register int s, k, r; + + /* Decode a single block's worth of coefficients */ + + /* Section F.2.2.1: decode the DC coefficient difference */ + HUFF_DECODE(s, br_state, dctbl, return FALSE, label1); + if (s) { + CHECK_BIT_BUFFER(br_state, s, return FALSE); + r = GET_BITS(s); + s = HUFF_EXTEND(r, s); + } + + if (entropy->dc_needed[blkn]) { + /* Convert DC difference to actual value, update last_dc_val */ + int ci = cinfo->MCU_membership[blkn]; + s += state.last_dc_val[ci]; + state.last_dc_val[ci] = s; + /* Output the DC coefficient (assumes jpeg_natural_order[0] = 0) */ + (*block)[0] = (JCOEF) s; + } + + if (entropy->ac_needed[blkn]) { + + /* Section F.2.2.2: decode the AC coefficients */ + /* Since zeroes are skipped, output area must be cleared beforehand */ + for (k = 1; k < DCTSIZE2; k++) { + HUFF_DECODE(s, br_state, actbl, return FALSE, label2); + + r = s >> 4; + s &= 15; + + if (s) { + k += r; + CHECK_BIT_BUFFER(br_state, s, return FALSE); + r = GET_BITS(s); + s = HUFF_EXTEND(r, s); + /* Output coefficient in natural (dezigzagged) order. + * Note: the extra entries in jpeg_natural_order[] will save us + * if k >= DCTSIZE2, which could happen if the data is corrupted. + */ + (*block)[jpeg_natural_order[k]] = (JCOEF) s; + } else { + if (r != 15) + break; + k += 15; + } + } + + } else { + + /* Section F.2.2.2: decode the AC coefficients */ + /* In this path we just discard the values */ + for (k = 1; k < DCTSIZE2; k++) { + HUFF_DECODE(s, br_state, actbl, return FALSE, label3); + + r = s >> 4; + s &= 15; + + if (s) { + k += r; + CHECK_BIT_BUFFER(br_state, s, return FALSE); + DROP_BITS(s); + } else { + if (r != 15) + break; + k += 15; + } + } + + } + } + + /* Completed MCU, so update state */ + BITREAD_SAVE_STATE(cinfo,entropy->bitstate); + ASSIGN_STATE(entropy->saved, state); + } + + /* Account for restart interval (no-op if not using restarts) */ + entropy->restarts_to_go--; + + return TRUE; +} + + +/* + * Module initialization routine for Huffman entropy decoding. + */ + +GLOBAL(void) +jinit_shuff_decoder (j_decompress_ptr cinfo) +{ + j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec; + shuff_entropy_ptr entropy; + int i; + + entropy = (shuff_entropy_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(shuff_entropy_decoder)); + lossyd->entropy_private = (void *) entropy; + lossyd->entropy_start_pass = start_pass_huff_decoder; + lossyd->entropy_decode_mcu = decode_mcu; + + /* Mark tables unallocated */ + for (i = 0; i < NUM_HUFF_TBLS; i++) { + entropy->dc_derived_tbls[i] = entropy->ac_derived_tbls[i] = NULL; + } +} diff --git a/dcmjpeg/libijg16/jdtrans.c b/dcmjpeg/libijg16/jdtrans.c new file mode 100644 index 00000000..b4527f1f --- /dev/null +++ b/dcmjpeg/libijg16/jdtrans.c @@ -0,0 +1,138 @@ +/* + * jdtrans.c + * + * Copyright (C) 1995-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains library routines for transcoding decompression, + * that is, reading raw DCT coefficient arrays from an input JPEG file. + * The routines in jdapimin.c will also be needed by a transcoder. + */ + +#define JPEG_INTERNALS +#include "jinclude16.h" +#include "jpeglib16.h" +#include "jlossy16.h" + + +/* Forward declarations */ +LOCAL(void) transdecode_master_selection JPP((j_decompress_ptr cinfo)); + + +/* + * Read the coefficient arrays from a JPEG file. + * jpeg_read_header must be completed before calling this. + * + * The entire image is read into a set of virtual coefficient-block arrays, + * one per component. The return value is a pointer to the array of + * virtual-array descriptors. These can be manipulated directly via the + * JPEG memory manager, or handed off to jpeg_write_coefficients(). + * To release the memory occupied by the virtual arrays, call + * jpeg_finish_decompress() when done with the data. + * + * An alternative usage is to simply obtain access to the coefficient arrays + * during a buffered-image-mode decompression operation. This is allowed + * after any jpeg_finish_output() call. The arrays can be accessed until + * jpeg_finish_decompress() is called. (Note that any call to the library + * may reposition the arrays, so don't rely on access_virt_barray() results + * to stay valid across library calls.) + * + * Returns NULL if suspended. This case need be checked only if + * a suspending data source is used. + */ + +GLOBAL(jvirt_barray_ptr *) +jpeg_read_coefficients (j_decompress_ptr cinfo) +{ + /* j_lossy_d_ptr decomp; */ + + /* Can't read coefficients from lossless streams */ + if (cinfo->process == JPROC_LOSSLESS) { + ERREXIT(cinfo, JERR_CANT_TRANSCODE); + return NULL; + } + + if (cinfo->global_state == DSTATE_READY) { + /* First call: initialize active modules */ + transdecode_master_selection(cinfo); + cinfo->global_state = DSTATE_RDCOEFS; + } + if (cinfo->global_state == DSTATE_RDCOEFS) { + /* Absorb whole file into the coef buffer */ + for (;;) { + int retcode; + /* Call progress monitor hook if present */ + if (cinfo->progress != NULL) + (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); + /* Absorb some more input */ + retcode = (*cinfo->inputctl->consume_input) (cinfo); + if (retcode == JPEG_SUSPENDED) + return NULL; + if (retcode == JPEG_REACHED_EOI) + break; + /* Advance progress counter if appropriate */ + if (cinfo->progress != NULL && + (retcode == JPEG_ROW_COMPLETED || retcode == JPEG_REACHED_SOS)) { + if (++cinfo->progress->pass_counter >= cinfo->progress->pass_limit) { + /* startup underestimated number of scans; ratchet up one scan */ + cinfo->progress->pass_limit += (long) cinfo->total_iMCU_rows; + } + } + } + /* Set state so that jpeg_finish_decompress does the right thing */ + cinfo->global_state = DSTATE_STOPPING; + } + /* At this point we should be in state DSTATE_STOPPING if being used + * standalone, or in state DSTATE_BUFIMAGE if being invoked to get access + * to the coefficients during a full buffered-image-mode decompression. + */ + if ((cinfo->global_state == DSTATE_STOPPING || + cinfo->global_state == DSTATE_BUFIMAGE) && cinfo->buffered_image) { + return ((j_lossy_d_ptr) cinfo->codec)->coef_arrays; + } + /* Oops, improper usage */ + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + return NULL; /* keep compiler happy */ +} + + +/* + * Master selection of decompression modules for transcoding. + * This substitutes for jdmaster.c's initialization of the full decompressor. + */ + +LOCAL(void) +transdecode_master_selection (j_decompress_ptr cinfo) +{ + /* This is effectively a buffered-image operation. */ + cinfo->buffered_image = TRUE; + + /* Initialize decompression codec */ + jinit_d_codec(cinfo); + + /* We can now tell the memory manager to allocate virtual arrays. */ + (*cinfo->mem->realize_virt_arrays) ((j_common_ptr) cinfo); + + /* Initialize input side of decompressor to consume first scan. */ + (*cinfo->inputctl->start_input_pass) (cinfo); + + /* Initialize progress monitoring. */ + if (cinfo->progress != NULL) { + int nscans; + /* Estimate number of scans to set pass_limit. */ + if (cinfo->process == JPROC_PROGRESSIVE) { + /* Arbitrarily estimate 2 interleaved DC scans + 3 AC scans/component. */ + nscans = 2 + 3 * cinfo->num_components; + } else if (cinfo->inputctl->has_multiple_scans) { + /* For a nonprogressive multiscan file, estimate 1 scan per component. */ + nscans = cinfo->num_components; + } else { + nscans = 1; + } + cinfo->progress->pass_counter = 0L; + cinfo->progress->pass_limit = (long) cinfo->total_iMCU_rows * nscans; + cinfo->progress->completed_passes = 0; + cinfo->progress->total_passes = 1; + } +} diff --git a/dcmjpeg/libijg16/jerror.c b/dcmjpeg/libijg16/jerror.c new file mode 100644 index 00000000..140d50d5 --- /dev/null +++ b/dcmjpeg/libijg16/jerror.c @@ -0,0 +1,252 @@ +/* + * jerror.c + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains simple error-reporting and trace-message routines. + * These are suitable for Unix-like systems and others where writing to + * stderr is the right thing to do. Many applications will want to replace + * some or all of these routines. + * + * If you define USE_WINDOWS_MESSAGEBOX in jconfig.h or in the makefile, + * you get a Windows-specific hack to display error messages in a dialog box. + * It ain't much, but it beats dropping error messages into the bit bucket, + * which is what happens to output to stderr under most Windows C compilers. + * + * These routines are used by both the compression and decompression code. + */ + +/* this is not a core library module, so it doesn't define JPEG_INTERNALS */ +#include "jinclude16.h" +#include "jpeglib16.h" +#include "jversion16.h" +#include "jerror16.h" + +#ifdef USE_WINDOWS_MESSAGEBOX +#include +#endif + +#ifndef EXIT_FAILURE /* define exit() codes if not provided */ +#define EXIT_FAILURE 1 +#endif + + +/* + * Create the message string table. + * We do this from the master message list in jerror.h by re-reading + * jerror.h with a suitable definition for macro JMESSAGE. + * The message table is made an external symbol just in case any applications + * want to refer to it directly. + */ + +#ifdef NEED_SHORT_EXTERNAL_NAMES +#define jpeg_std_message_table jpeg16_std_message_table +#endif + +#define JMESSAGE(code,string) string , + +const char * const jpeg_std_message_table[] = { +#include "jerror16.h" + NULL +}; + + +/* + * Error exit handler: must not return to caller. + * + * Applications may override this if they want to get control back after + * an error. Typically one would longjmp somewhere instead of exiting. + * The setjmp buffer can be made a private field within an expanded error + * handler object. Note that the info needed to generate an error message + * is stored in the error object, so you can generate the message now or + * later, at your convenience. + * You should make sure that the JPEG object is cleaned up (with jpeg_abort + * or jpeg_destroy) at some point. + */ + +METHODDEF(void) +error_exit (j_common_ptr cinfo) +{ + /* Always display the message */ + (*cinfo->err->output_message) (cinfo); + + /* Let the memory manager delete any temp files before we die */ + jpeg_destroy(cinfo); + + exit(EXIT_FAILURE); +} + + +/* + * Actual output of an error or trace message. + * Applications may override this method to send JPEG messages somewhere + * other than stderr. + * + * On Windows, printing to stderr is generally completely useless, + * so we provide optional code to produce an error-dialog popup. + * Most Windows applications will still prefer to override this routine, + * but if they don't, it'll do something at least marginally useful. + * + * NOTE: to use the library in an environment that doesn't support the + * C stdio library, you may have to delete the call to fprintf() entirely, + * not just not use this routine. + */ + +METHODDEF(void) +output_message (j_common_ptr cinfo) +{ + char buffer[JMSG_LENGTH_MAX]; + + /* Create the message */ + (*cinfo->err->format_message) (cinfo, buffer); + +#ifdef USE_WINDOWS_MESSAGEBOX + /* Display it in a message dialog box */ + MessageBox(GetActiveWindow(), buffer, "JPEG Library Error", + MB_OK | MB_ICONERROR); +#else + /* Send it to stderr, adding a newline */ + fprintf(stderr, "%s\n", buffer); +#endif +} + + +/* + * Decide whether to emit a trace or warning message. + * msg_level is one of: + * -1: recoverable corrupt-data warning, may want to abort. + * 0: important advisory messages (always display to user). + * 1: first level of tracing detail. + * 2,3,...: successively more detailed tracing messages. + * An application might override this method if it wanted to abort on warnings + * or change the policy about which messages to display. + */ + +METHODDEF(void) +emit_message (j_common_ptr cinfo, int msg_level) +{ + struct jpeg_error_mgr * err = cinfo->err; + + if (msg_level < 0) { + /* It's a warning message. Since corrupt files may generate many warnings, + * the policy implemented here is to show only the first warning, + * unless trace_level >= 3. + */ + if (err->num_warnings == 0 || err->trace_level >= 3) + (*err->output_message) (cinfo); + /* Always count warnings in num_warnings. */ + err->num_warnings++; + } else { + /* It's a trace message. Show it if trace_level >= msg_level. */ + if (err->trace_level >= msg_level) + (*err->output_message) (cinfo); + } +} + + +/* + * Format a message string for the most recent JPEG error or message. + * The message is stored into buffer, which should be at least JMSG_LENGTH_MAX + * characters. Note that no '\n' character is added to the string. + * Few applications should need to override this method. + */ + +METHODDEF(void) +format_message (j_common_ptr cinfo, char * buffer) +{ + struct jpeg_error_mgr * err = cinfo->err; + int msg_code = err->msg_code; + const char * msgtext = NULL; + const char * msgptr; + char ch; + boolean isstring; + + /* Look up message string in proper table */ + if (msg_code > 0 && msg_code <= err->last_jpeg_message) { + msgtext = err->jpeg_message_table[msg_code]; + } else if (err->addon_message_table != NULL && + msg_code >= err->first_addon_message && + msg_code <= err->last_addon_message) { + msgtext = err->addon_message_table[msg_code - err->first_addon_message]; + } + + /* Defend against bogus message number */ + if (msgtext == NULL) { + err->msg_parm.i[0] = msg_code; + msgtext = err->jpeg_message_table[0]; + } + + /* Check for string parameter, as indicated by %s in the message text */ + isstring = FALSE; + msgptr = msgtext; + while ((ch = *msgptr++) != '\0') { + if (ch == '%') { + if (*msgptr == 's') isstring = TRUE; + break; + } + } + + /* Format the message into the passed buffer */ + if (isstring) + sprintf(buffer, msgtext, err->msg_parm.s); + else + sprintf(buffer, msgtext, + err->msg_parm.i[0], err->msg_parm.i[1], + err->msg_parm.i[2], err->msg_parm.i[3], + err->msg_parm.i[4], err->msg_parm.i[5], + err->msg_parm.i[6], err->msg_parm.i[7]); +} + + +/* + * Reset error state variables at start of a new image. + * This is called during compression startup to reset trace/error + * processing to default state, without losing any application-specific + * method pointers. An application might possibly want to override + * this method if it has additional error processing state. + */ + +METHODDEF(void) +reset_error_mgr (j_common_ptr cinfo) +{ + cinfo->err->num_warnings = 0; + /* trace_level is not reset since it is an application-supplied parameter */ + cinfo->err->msg_code = 0; /* may be useful as a flag for "no error" */ +} + + +/* + * Fill in the standard error-handling methods in a jpeg_error_mgr object. + * Typical call is: + * struct jpeg_compress_struct cinfo; + * struct jpeg_error_mgr err; + * + * cinfo.err = jpeg_std_error(&err); + * after which the application may override some of the methods. + */ + +GLOBAL(struct jpeg_error_mgr *) +jpeg_std_error (struct jpeg_error_mgr * err) +{ + err->error_exit = error_exit; + err->emit_message = emit_message; + err->output_message = output_message; + err->format_message = format_message; + err->reset_error_mgr = reset_error_mgr; + + err->trace_level = 0; /* default = no tracing */ + err->num_warnings = 0; /* no warnings emitted yet */ + err->msg_code = 0; /* may be useful as a flag for "no error" */ + + /* Initialize message table pointers */ + err->jpeg_message_table = jpeg_std_message_table; + err->last_jpeg_message = (int) JMSG_LASTMSGCODE - 1; + + err->addon_message_table = NULL; + err->first_addon_message = 0; /* for safety */ + err->last_addon_message = 0; + + return err; +} diff --git a/dcmjpeg/libijg16/jerror16.h b/dcmjpeg/libijg16/jerror16.h new file mode 100644 index 00000000..d90bd1c1 --- /dev/null +++ b/dcmjpeg/libijg16/jerror16.h @@ -0,0 +1,310 @@ +/* + * jerror.h + * + * Copyright (C) 1994-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file defines the error and message codes for the JPEG library. + * Edit this file to add new codes, or to translate the message strings to + * some other language. + * A set of error-reporting macros are defined too. Some applications using + * the JPEG library may wish to include this file to get the error codes + * and/or the macros. + */ + +/* + * To define the enum list of message codes, include this file without + * defining macro JMESSAGE. To create a message string table, include it + * again with a suitable JMESSAGE definition (see jerror.c for an example). + */ +#ifndef JMESSAGE +#ifndef JERROR_H +/* First time through, define the enum list */ +#define JMAKE_ENUM_LIST +#else +/* Repeated inclusions of this file are no-ops unless JMESSAGE is defined */ +#define JMESSAGE(code,string) +#endif /* JERROR_H */ +#endif /* JMESSAGE */ + +#ifdef JMAKE_ENUM_LIST + +typedef enum { + +#define JMESSAGE(code,string) code , + +#endif /* JMAKE_ENUM_LIST */ + +JMESSAGE(JMSG_NOMESSAGE, "Bogus message code %d") /* Must be first entry! */ + +/* For maintenance convenience, list is alphabetical by message code name */ +JMESSAGE(JERR_ARITH_NOTIMPL, + "Sorry, there are legal restrictions on arithmetic coding") +JMESSAGE(JERR_BAD_ALIGN_TYPE, "ALIGN_TYPE is wrong, please fix") +JMESSAGE(JERR_BAD_ALLOC_CHUNK, "MAX_ALLOC_CHUNK is wrong, please fix") +JMESSAGE(JERR_BAD_BUFFER_MODE, "Bogus buffer control mode") +JMESSAGE(JERR_BAD_COMPONENT_ID, "Invalid component ID %d in SOS") +JMESSAGE(JERR_BAD_DCT_COEF, "DCT coefficient out of range") +JMESSAGE(JERR_BAD_DCTSIZE, "IDCT output block size %d not supported") +JMESSAGE(JERR_BAD_DIFF, "spatial difference out of range") +JMESSAGE(JERR_BAD_HUFF_TABLE, "Bogus Huffman table definition") +JMESSAGE(JERR_BAD_IN_COLORSPACE, "Bogus input colorspace") +JMESSAGE(JERR_BAD_J_COLORSPACE, "Bogus JPEG colorspace") +JMESSAGE(JERR_BAD_LENGTH, "Bogus marker length") +JMESSAGE(JERR_BAD_LIB_VERSION, + "Wrong JPEG library version: library is %d, caller expects %d") +JMESSAGE(JERR_BAD_LOSSLESS, + "Invalid lossless parameters Ss=%d Se=%d Ah=%d Al=%d") +JMESSAGE(JERR_BAD_LOSSLESS_SCRIPT, + "Invalid lossless parameters at scan script entry %d") +JMESSAGE(JERR_BAD_MCU_SIZE, "Sampling factors too large for interleaved scan") +JMESSAGE(JERR_BAD_POOL_ID, "Invalid memory pool code %d") +JMESSAGE(JERR_BAD_PRECISION, "Unsupported JPEG data precision %d") +JMESSAGE(JERR_BAD_PROGRESSION, + "Invalid progressive parameters Ss=%d Se=%d Ah=%d Al=%d") +JMESSAGE(JERR_BAD_PROG_SCRIPT, + "Invalid progressive parameters at scan script entry %d") +JMESSAGE(JERR_BAD_RESTART, "Invalid restart interval: %d, must be an integer multiple of the number of MCUs in an MCU_row (%d)") +JMESSAGE(JERR_BAD_SAMPLING, "Bogus sampling factors") +JMESSAGE(JERR_BAD_SCAN_SCRIPT, "Invalid scan script at entry %d") +JMESSAGE(JERR_BAD_STATE, "Improper call to JPEG library in state %d") +JMESSAGE(JERR_BAD_STRUCT_SIZE, + "JPEG parameter struct mismatch: library thinks size is %u, caller expects %u") +JMESSAGE(JERR_BAD_VIRTUAL_ACCESS, "Bogus virtual array access") +JMESSAGE(JERR_BUFFER_SIZE, "Buffer passed to JPEG library is too small") +JMESSAGE(JERR_CANT_SUSPEND, "Suspension not allowed here") +JMESSAGE(JERR_CANT_TRANSCODE, + "Cannot transcode to/from lossless JPEG datastreams") +JMESSAGE(JERR_CCIR601_NOTIMPL, "CCIR601 sampling not implemented yet") +JMESSAGE(JERR_COMPONENT_COUNT, "Too many color components: %d, max %d") +JMESSAGE(JERR_CONVERSION_NOTIMPL, "Unsupported color conversion request") +JMESSAGE(JERR_DAC_INDEX, "Bogus DAC index %d") +JMESSAGE(JERR_DAC_VALUE, "Bogus DAC value 0x%x") +JMESSAGE(JERR_DHT_INDEX, "Bogus DHT index %d") +JMESSAGE(JERR_DQT_INDEX, "Bogus DQT index %d") +JMESSAGE(JERR_EMPTY_IMAGE, "Empty JPEG image (DNL not supported)") +JMESSAGE(JERR_EMS_READ, "Read from EMS failed") +JMESSAGE(JERR_EMS_WRITE, "Write to EMS failed") +JMESSAGE(JERR_EOI_EXPECTED, "Didn't expect more than one scan") +JMESSAGE(JERR_FILE_READ, "Input file read error") +JMESSAGE(JERR_FILE_WRITE, "Output file write error --- out of disk space?") +JMESSAGE(JERR_FRACT_SAMPLE_NOTIMPL, "Fractional sampling not implemented yet") +JMESSAGE(JERR_HUFF_CLEN_OVERFLOW, "Huffman code size table overflow") +JMESSAGE(JERR_HUFF_MISSING_CODE, "Missing Huffman code table entry") +JMESSAGE(JERR_IMAGE_TOO_BIG, "Maximum supported image dimension is %u pixels") +JMESSAGE(JERR_INPUT_EMPTY, "Empty input file") +JMESSAGE(JERR_INPUT_EOF, "Premature end of input file") +JMESSAGE(JERR_MISMATCHED_QUANT_TABLE, + "Cannot transcode due to multiple use of quantization table %d") +JMESSAGE(JERR_MISSING_DATA, "Scan script does not transmit all data") +JMESSAGE(JERR_MODE_CHANGE, "Invalid color quantization mode change") +JMESSAGE(JERR_NOTIMPL, "Not implemented yet") +JMESSAGE(JERR_NOT_COMPILED, "Requested feature was omitted at compile time") +#ifdef WITH_ARITHMETIC_PATCH +JMESSAGE(JERR_NO_ARITH_TABLE, "Arithmetic table 0x%02x was not defined") +#endif +JMESSAGE(JERR_NO_BACKING_STORE, "Backing store not supported") +JMESSAGE(JERR_NO_HUFF_TABLE, "Huffman table 0x%02x was not defined") +JMESSAGE(JERR_NO_IMAGE, "JPEG datastream contains no image") +JMESSAGE(JERR_NO_LOSSLESS_SCRIPT, "Lossless encoding was requested but no scan script was supplied") +JMESSAGE(JERR_NO_QUANT_TABLE, "Quantization table 0x%02x was not defined") +JMESSAGE(JERR_NO_SOI, "Not a JPEG file: starts with 0x%02x 0x%02x") +JMESSAGE(JERR_OUT_OF_MEMORY, "Insufficient memory (case %d)") +JMESSAGE(JERR_QUANT_COMPONENTS, + "Cannot quantize more than %d color components") +JMESSAGE(JERR_QUANT_FEW_COLORS, "Cannot quantize to fewer than %d colors") +JMESSAGE(JERR_QUANT_MANY_COLORS, "Cannot quantize to more than %d colors") +JMESSAGE(JERR_SOF_DUPLICATE, "Invalid JPEG file structure: two SOF markers") +JMESSAGE(JERR_SOF_NO_SOS, "Invalid JPEG file structure: missing SOS marker") +JMESSAGE(JERR_SOF_UNSUPPORTED, "Unsupported JPEG process: SOF type 0x%02x") +JMESSAGE(JERR_SOI_DUPLICATE, "Invalid JPEG file structure: two SOI markers") +JMESSAGE(JERR_SOS_NO_SOF, "Invalid JPEG file structure: SOS before SOF") +JMESSAGE(JERR_TFILE_CREATE, "Failed to create temporary file %s") +JMESSAGE(JERR_TFILE_READ, "Read failed on temporary file") +JMESSAGE(JERR_TFILE_SEEK, "Seek failed on temporary file") +JMESSAGE(JERR_TFILE_WRITE, + "Write failed on temporary file --- out of disk space?") +JMESSAGE(JERR_TOO_LITTLE_DATA, "Application transferred too few scanlines") +JMESSAGE(JERR_UNKNOWN_MARKER, "Unsupported marker type 0x%02x") +JMESSAGE(JERR_VIRTUAL_BUG, "Virtual array controller messed up") +JMESSAGE(JERR_WIDTH_OVERFLOW, "Image too wide for this implementation") +JMESSAGE(JERR_XMS_READ, "Read from XMS failed") +JMESSAGE(JERR_XMS_WRITE, "Write to XMS failed") +JMESSAGE(JMSG_COPYRIGHT, JCOPYRIGHT) +JMESSAGE(JMSG_VERSION, JVERSION) +JMESSAGE(JTRC_16BIT_TABLES, + "Caution: quantization tables are too coarse for baseline JPEG") +JMESSAGE(JTRC_ADOBE, + "Adobe APP14 marker: version %d, flags 0x%04x 0x%04x, transform %d") +JMESSAGE(JTRC_APP0, "Unknown APP0 marker (not JFIF), length %u") +JMESSAGE(JTRC_APP14, "Unknown APP14 marker (not Adobe), length %u") +JMESSAGE(JTRC_DAC, "Define Arithmetic Table 0x%02x: 0x%02x") +JMESSAGE(JTRC_DHT, "Define Huffman Table 0x%02x") +JMESSAGE(JTRC_DQT, "Define Quantization Table %d precision %d") +JMESSAGE(JTRC_DRI, "Define Restart Interval %u") +JMESSAGE(JTRC_EMS_CLOSE, "Freed EMS handle %u") +JMESSAGE(JTRC_EMS_OPEN, "Obtained EMS handle %u") +JMESSAGE(JTRC_EOI, "End Of Image") +JMESSAGE(JTRC_HUFFBITS, " %3d %3d %3d %3d %3d %3d %3d %3d") +JMESSAGE(JTRC_JFIF, "JFIF APP0 marker: version %d.%02d, density %dx%d %d") +JMESSAGE(JTRC_JFIF_BADTHUMBNAILSIZE, + "Warning: thumbnail image size does not match data length %u") +JMESSAGE(JTRC_JFIF_EXTENSION, + "JFIF extension marker: type 0x%02x, length %u") +JMESSAGE(JTRC_JFIF_THUMBNAIL, " with %d x %d thumbnail image") +JMESSAGE(JTRC_MISC_MARKER, "Miscellaneous marker 0x%02x, length %u") +JMESSAGE(JTRC_PARMLESS_MARKER, "Unexpected marker 0x%02x") +JMESSAGE(JTRC_QUANTVALS, " %4u %4u %4u %4u %4u %4u %4u %4u") +JMESSAGE(JTRC_QUANT_3_NCOLORS, "Quantizing to %d = %d*%d*%d colors") +JMESSAGE(JTRC_QUANT_NCOLORS, "Quantizing to %d colors") +JMESSAGE(JTRC_QUANT_SELECTED, "Selected %d colors for quantization") +JMESSAGE(JTRC_RECOVERY_ACTION, "At marker 0x%02x, recovery action %d") +JMESSAGE(JTRC_RST, "RST%d") +JMESSAGE(JTRC_SMOOTH_NOTIMPL, + "Smoothing not supported with nonstandard sampling ratios") +JMESSAGE(JTRC_SOF, "Start Of Frame 0x%02x: width=%u, height=%u, components=%d") +JMESSAGE(JTRC_SOF_COMPONENT, " Component %d: %dhx%dv q=%d") +JMESSAGE(JTRC_SOI, "Start of Image") +JMESSAGE(JTRC_SOS, "Start Of Scan: %d components") +JMESSAGE(JTRC_SOS_COMPONENT, " Component %d: dc=%d ac=%d") +JMESSAGE(JTRC_SOS_PARAMS, " Ss=%d, Se=%d, Ah=%d, Al=%d") +JMESSAGE(JTRC_TFILE_CLOSE, "Closed temporary file %s") +JMESSAGE(JTRC_TFILE_OPEN, "Opened temporary file %s") +JMESSAGE(JTRC_THUMB_JPEG, + "JFIF extension marker: JPEG-compressed thumbnail image, length %u") +JMESSAGE(JTRC_THUMB_PALETTE, + "JFIF extension marker: palette thumbnail image, length %u") +JMESSAGE(JTRC_THUMB_RGB, + "JFIF extension marker: RGB thumbnail image, length %u") +JMESSAGE(JTRC_UNKNOWN_LOSSLESS_IDS, + "Unrecognized component IDs %d %d %d, assuming RGB") +JMESSAGE(JTRC_UNKNOWN_LOSSY_IDS, + "Unrecognized component IDs %d %d %d, assuming YCbCr") +JMESSAGE(JTRC_XMS_CLOSE, "Freed XMS handle %u") +JMESSAGE(JTRC_XMS_OPEN, "Obtained XMS handle %u") +JMESSAGE(JWRN_ADOBE_XFORM, "Unknown Adobe color transform code %d") +#ifdef WITH_ARITHMETIC_PATCH +JMESSAGE(JWRN_ARITH_BAD_CODE, "Corrupt JPEG data: bad arithmetic code") +#endif +JMESSAGE(JWRN_BOGUS_PROGRESSION, + "Inconsistent progression sequence for component %d coefficient %d") +JMESSAGE(JWRN_EXTRANEOUS_DATA, + "Corrupt JPEG data: %u extraneous bytes before marker 0x%02x") +JMESSAGE(JWRN_HIT_MARKER, "Corrupt JPEG data: premature end of data segment") +JMESSAGE(JWRN_HUFF_BAD_CODE, "Corrupt JPEG data: bad Huffman code") +JMESSAGE(JWRN_JFIF_MAJOR, "Warning: unknown JFIF revision number %d.%02d") +JMESSAGE(JWRN_JPEG_EOF, "Premature end of JPEG file") +JMESSAGE(JWRN_MUST_DOWNSCALE, + "Must downscale data from %d bits to %d") +JMESSAGE(JWRN_MUST_RESYNC, + "Corrupt JPEG data: found marker 0x%02x instead of RST%d") +JMESSAGE(JWRN_NOT_SEQUENTIAL, "Invalid SOS parameters for sequential JPEG") +JMESSAGE(JWRN_TOO_MUCH_DATA, "Application transferred too many scanlines") + +#ifdef JMAKE_ENUM_LIST + + JMSG_LASTMSGCODE +} J_MESSAGE_CODE; + +#undef JMAKE_ENUM_LIST +#endif /* JMAKE_ENUM_LIST */ + +/* Zap JMESSAGE macro so that future re-inclusions do nothing by default */ +#undef JMESSAGE + + +#ifndef JERROR_H +#define JERROR_H + +/* Macros to simplify using the error and trace message stuff */ +/* The first parameter is either type of cinfo pointer */ + +/* Fatal errors (print message and exit) */ +#define ERREXIT(cinfo,code) \ + ((cinfo)->err->msg_code = (code), \ + (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) +#define ERREXIT1(cinfo,code,p1) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) +#define ERREXIT2(cinfo,code,p1,p2) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) +#define ERREXIT3(cinfo,code,p1,p2,p3) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (cinfo)->err->msg_parm.i[2] = (p3), \ + (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) +#define ERREXIT4(cinfo,code,p1,p2,p3,p4) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (cinfo)->err->msg_parm.i[2] = (p3), \ + (cinfo)->err->msg_parm.i[3] = (p4), \ + (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) +#define ERREXITS(cinfo,code,str) \ + ((cinfo)->err->msg_code = (code), \ + strncpy((cinfo)->err->msg_parm.s, (str), JMSG_STR_PARM_MAX), \ + (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) + +#define MAKESTMT(stuff) do { stuff } while (0) + +/* Nonfatal errors (we can keep going, but the data is probably corrupt) */ +#define WARNMS(cinfo,code) \ + ((cinfo)->err->msg_code = (code), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1)) +#define WARNMS1(cinfo,code,p1) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1)) +#define WARNMS2(cinfo,code,p1,p2) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1)) + +/* Informational/debugging messages */ +#define TRACEMS(cinfo,lvl,code) \ + ((cinfo)->err->msg_code = (code), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl))) +#define TRACEMS1(cinfo,lvl,code,p1) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl))) +#define TRACEMS2(cinfo,lvl,code,p1,p2) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl))) +#define TRACEMS3(cinfo,lvl,code,p1,p2,p3) \ + MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \ + _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); \ + (cinfo)->err->msg_code = (code); \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); ) +#define TRACEMS4(cinfo,lvl,code,p1,p2,p3,p4) \ + MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \ + _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \ + (cinfo)->err->msg_code = (code); \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); ) +#define TRACEMS5(cinfo,lvl,code,p1,p2,p3,p4,p5) \ + MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \ + _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \ + _mp[4] = (p5); \ + (cinfo)->err->msg_code = (code); \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); ) +#define TRACEMS8(cinfo,lvl,code,p1,p2,p3,p4,p5,p6,p7,p8) \ + MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \ + _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \ + _mp[4] = (p5); _mp[5] = (p6); _mp[6] = (p7); _mp[7] = (p8); \ + (cinfo)->err->msg_code = (code); \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); ) +#define TRACEMSS(cinfo,lvl,code,str) \ + ((cinfo)->err->msg_code = (code), \ + strncpy((cinfo)->err->msg_parm.s, (str), JMSG_STR_PARM_MAX), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl))) + +#endif /* JERROR_H */ diff --git a/dcmjpeg/libijg16/jfdctflt.c b/dcmjpeg/libijg16/jfdctflt.c new file mode 100644 index 00000000..113ed25e --- /dev/null +++ b/dcmjpeg/libijg16/jfdctflt.c @@ -0,0 +1,168 @@ +/* + * jfdctflt.c + * + * Copyright (C) 1994-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains a floating-point implementation of the + * forward DCT (Discrete Cosine Transform). + * + * This implementation should be more accurate than either of the integer + * DCT implementations. However, it may not give the same results on all + * machines because of differences in roundoff behavior. Speed will depend + * on the hardware's floating point capacity. + * + * A 2-D DCT can be done by 1-D DCT on each row followed by 1-D DCT + * on each column. Direct algorithms are also available, but they are + * much more complex and seem not to be any faster when reduced to code. + * + * This implementation is based on Arai, Agui, and Nakajima's algorithm for + * scaled DCT. Their original paper (Trans. IEICE E-71(11):1095) is in + * Japanese, but the algorithm is described in the Pennebaker & Mitchell + * JPEG textbook (see REFERENCES section in file README). The following code + * is based directly on figure 4-8 in P&M. + * While an 8-point DCT cannot be done in less than 11 multiplies, it is + * possible to arrange the computation so that many of the multiplies are + * simple scalings of the final outputs. These multiplies can then be + * folded into the multiplications or divisions by the JPEG quantization + * table entries. The AA&N method leaves only 5 multiplies and 29 adds + * to be done in the DCT itself. + * The primary disadvantage of this method is that with a fixed-point + * implementation, accuracy is lost due to imprecise representation of the + * scaled quantization values. However, that problem does not arise if + * we use floating point arithmetic. + */ + +#define JPEG_INTERNALS +#include "jinclude16.h" +#include "jpeglib16.h" +#include "jdct16.h" /* Private declarations for DCT subsystem */ + +#ifdef DCT_FLOAT_SUPPORTED + + +/* + * This module is specialized to the case DCTSIZE = 8. + */ + +#if DCTSIZE != 8 + Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */ +#endif + + +/* + * Perform the forward DCT on one block of samples. + */ + +GLOBAL(void) +jpeg_fdct_float (FAST_FLOAT * data) +{ + FAST_FLOAT tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + FAST_FLOAT tmp10, tmp11, tmp12, tmp13; + FAST_FLOAT z1, z2, z3, z4, z5, z11, z13; + FAST_FLOAT *dataptr; + int ctr; + + /* Pass 1: process rows. */ + + dataptr = data; + for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { + tmp0 = dataptr[0] + dataptr[7]; + tmp7 = dataptr[0] - dataptr[7]; + tmp1 = dataptr[1] + dataptr[6]; + tmp6 = dataptr[1] - dataptr[6]; + tmp2 = dataptr[2] + dataptr[5]; + tmp5 = dataptr[2] - dataptr[5]; + tmp3 = dataptr[3] + dataptr[4]; + tmp4 = dataptr[3] - dataptr[4]; + + /* Even part */ + + tmp10 = tmp0 + tmp3; /* phase 2 */ + tmp13 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp1 - tmp2; + + dataptr[0] = tmp10 + tmp11; /* phase 3 */ + dataptr[4] = tmp10 - tmp11; + + z1 = (tmp12 + tmp13) * ((FAST_FLOAT) 0.707106781); /* c4 */ + dataptr[2] = tmp13 + z1; /* phase 5 */ + dataptr[6] = tmp13 - z1; + + /* Odd part */ + + tmp10 = tmp4 + tmp5; /* phase 2 */ + tmp11 = tmp5 + tmp6; + tmp12 = tmp6 + tmp7; + + /* The rotator is modified from fig 4-8 to avoid extra negations. */ + z5 = (tmp10 - tmp12) * ((FAST_FLOAT) 0.382683433); /* c6 */ + z2 = ((FAST_FLOAT) 0.541196100) * tmp10 + z5; /* c2-c6 */ + z4 = ((FAST_FLOAT) 1.306562965) * tmp12 + z5; /* c2+c6 */ + z3 = tmp11 * ((FAST_FLOAT) 0.707106781); /* c4 */ + + z11 = tmp7 + z3; /* phase 5 */ + z13 = tmp7 - z3; + + dataptr[5] = z13 + z2; /* phase 6 */ + dataptr[3] = z13 - z2; + dataptr[1] = z11 + z4; + dataptr[7] = z11 - z4; + + dataptr += DCTSIZE; /* advance pointer to next row */ + } + + /* Pass 2: process columns. */ + + dataptr = data; + for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { + tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*7]; + tmp7 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*7]; + tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*6]; + tmp6 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*6]; + tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*5]; + tmp5 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*5]; + tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*4]; + tmp4 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*4]; + + /* Even part */ + + tmp10 = tmp0 + tmp3; /* phase 2 */ + tmp13 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp1 - tmp2; + + dataptr[DCTSIZE*0] = tmp10 + tmp11; /* phase 3 */ + dataptr[DCTSIZE*4] = tmp10 - tmp11; + + z1 = (tmp12 + tmp13) * ((FAST_FLOAT) 0.707106781); /* c4 */ + dataptr[DCTSIZE*2] = tmp13 + z1; /* phase 5 */ + dataptr[DCTSIZE*6] = tmp13 - z1; + + /* Odd part */ + + tmp10 = tmp4 + tmp5; /* phase 2 */ + tmp11 = tmp5 + tmp6; + tmp12 = tmp6 + tmp7; + + /* The rotator is modified from fig 4-8 to avoid extra negations. */ + z5 = (tmp10 - tmp12) * ((FAST_FLOAT) 0.382683433); /* c6 */ + z2 = ((FAST_FLOAT) 0.541196100) * tmp10 + z5; /* c2-c6 */ + z4 = ((FAST_FLOAT) 1.306562965) * tmp12 + z5; /* c2+c6 */ + z3 = tmp11 * ((FAST_FLOAT) 0.707106781); /* c4 */ + + z11 = tmp7 + z3; /* phase 5 */ + z13 = tmp7 - z3; + + dataptr[DCTSIZE*5] = z13 + z2; /* phase 6 */ + dataptr[DCTSIZE*3] = z13 - z2; + dataptr[DCTSIZE*1] = z11 + z4; + dataptr[DCTSIZE*7] = z11 - z4; + + dataptr++; /* advance pointer to next column */ + } +} + +#endif /* DCT_FLOAT_SUPPORTED */ diff --git a/dcmjpeg/libijg16/jfdctfst.c b/dcmjpeg/libijg16/jfdctfst.c new file mode 100644 index 00000000..88a12d5a --- /dev/null +++ b/dcmjpeg/libijg16/jfdctfst.c @@ -0,0 +1,224 @@ +/* + * jfdctfst.c + * + * Copyright (C) 1994-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains a fast, not so accurate integer implementation of the + * forward DCT (Discrete Cosine Transform). + * + * A 2-D DCT can be done by 1-D DCT on each row followed by 1-D DCT + * on each column. Direct algorithms are also available, but they are + * much more complex and seem not to be any faster when reduced to code. + * + * This implementation is based on Arai, Agui, and Nakajima's algorithm for + * scaled DCT. Their original paper (Trans. IEICE E-71(11):1095) is in + * Japanese, but the algorithm is described in the Pennebaker & Mitchell + * JPEG textbook (see REFERENCES section in file README). The following code + * is based directly on figure 4-8 in P&M. + * While an 8-point DCT cannot be done in less than 11 multiplies, it is + * possible to arrange the computation so that many of the multiplies are + * simple scalings of the final outputs. These multiplies can then be + * folded into the multiplications or divisions by the JPEG quantization + * table entries. The AA&N method leaves only 5 multiplies and 29 adds + * to be done in the DCT itself. + * The primary disadvantage of this method is that with fixed-point math, + * accuracy is lost due to imprecise representation of the scaled + * quantization values. The smaller the quantization table entry, the less + * precise the scaled value, so this implementation does worse with high- + * quality-setting files than with low-quality ones. + */ + +#define JPEG_INTERNALS +#include "jinclude16.h" +#include "jpeglib16.h" +#include "jdct16.h" /* Private declarations for DCT subsystem */ + +#ifdef DCT_IFAST_SUPPORTED + + +/* + * This module is specialized to the case DCTSIZE = 8. + */ + +#if DCTSIZE != 8 + Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */ +#endif + + +/* Scaling decisions are generally the same as in the LL&M algorithm; + * see jfdctint.c for more details. However, we choose to descale + * (right shift) multiplication products as soon as they are formed, + * rather than carrying additional fractional bits into subsequent additions. + * This compromises accuracy slightly, but it lets us save a few shifts. + * More importantly, 16-bit arithmetic is then adequate (for 8-bit samples) + * everywhere except in the multiplications proper; this saves a good deal + * of work on 16-bit-int machines. + * + * Again to save a few shifts, the intermediate results between pass 1 and + * pass 2 are not upscaled, but are represented only to integral precision. + * + * A final compromise is to represent the multiplicative constants to only + * 8 fractional bits, rather than 13. This saves some shifting work on some + * machines, and may also reduce the cost of multiplication (since there + * are fewer one-bits in the constants). + */ + +#define CONST_BITS 8 + + +/* Some C compilers fail to reduce "FIX(constant)" at compile time, thus + * causing a lot of useless floating-point operations at run time. + * To get around this we use the following pre-calculated constants. + * If you change CONST_BITS you may want to add appropriate values. + * (With a reasonable C compiler, you can just rely on the FIX() macro...) + */ + +#if CONST_BITS == 8 +#define FIX_0_382683433 ((IJG_INT32) 98) /* FIX(0.382683433) */ +#define FIX_0_541196100 ((IJG_INT32) 139) /* FIX(0.541196100) */ +#define FIX_0_707106781 ((IJG_INT32) 181) /* FIX(0.707106781) */ +#define FIX_1_306562965 ((IJG_INT32) 334) /* FIX(1.306562965) */ +#else +#define FIX_0_382683433 FIX(0.382683433) +#define FIX_0_541196100 FIX(0.541196100) +#define FIX_0_707106781 FIX(0.707106781) +#define FIX_1_306562965 FIX(1.306562965) +#endif + + +/* We can gain a little more speed, with a further compromise in accuracy, + * by omitting the addition in a descaling shift. This yields an incorrectly + * rounded result half the time... + */ + +#ifndef USE_ACCURATE_ROUNDING +#undef DESCALE +#define DESCALE(x,n) RIGHT_SHIFT(x, n) +#endif + + +/* Multiply a DCTELEM variable by an IJG_INT32 constant, and immediately + * descale to yield a DCTELEM result. + */ + +#define MULTIPLY(var,const) ((DCTELEM) DESCALE((var) * (const), CONST_BITS)) + + +/* + * Perform the forward DCT on one block of samples. + */ + +GLOBAL(void) +jpeg_fdct_ifast (DCTELEM * data) +{ + DCTELEM tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + DCTELEM tmp10, tmp11, tmp12, tmp13; + DCTELEM z1, z2, z3, z4, z5, z11, z13; + DCTELEM *dataptr; + int ctr; + SHIFT_TEMPS + + /* Pass 1: process rows. */ + + dataptr = data; + for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { + tmp0 = dataptr[0] + dataptr[7]; + tmp7 = dataptr[0] - dataptr[7]; + tmp1 = dataptr[1] + dataptr[6]; + tmp6 = dataptr[1] - dataptr[6]; + tmp2 = dataptr[2] + dataptr[5]; + tmp5 = dataptr[2] - dataptr[5]; + tmp3 = dataptr[3] + dataptr[4]; + tmp4 = dataptr[3] - dataptr[4]; + + /* Even part */ + + tmp10 = tmp0 + tmp3; /* phase 2 */ + tmp13 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp1 - tmp2; + + dataptr[0] = tmp10 + tmp11; /* phase 3 */ + dataptr[4] = tmp10 - tmp11; + + z1 = MULTIPLY(tmp12 + tmp13, FIX_0_707106781); /* c4 */ + dataptr[2] = tmp13 + z1; /* phase 5 */ + dataptr[6] = tmp13 - z1; + + /* Odd part */ + + tmp10 = tmp4 + tmp5; /* phase 2 */ + tmp11 = tmp5 + tmp6; + tmp12 = tmp6 + tmp7; + + /* The rotator is modified from fig 4-8 to avoid extra negations. */ + z5 = MULTIPLY(tmp10 - tmp12, FIX_0_382683433); /* c6 */ + z2 = MULTIPLY(tmp10, FIX_0_541196100) + z5; /* c2-c6 */ + z4 = MULTIPLY(tmp12, FIX_1_306562965) + z5; /* c2+c6 */ + z3 = MULTIPLY(tmp11, FIX_0_707106781); /* c4 */ + + z11 = tmp7 + z3; /* phase 5 */ + z13 = tmp7 - z3; + + dataptr[5] = z13 + z2; /* phase 6 */ + dataptr[3] = z13 - z2; + dataptr[1] = z11 + z4; + dataptr[7] = z11 - z4; + + dataptr += DCTSIZE; /* advance pointer to next row */ + } + + /* Pass 2: process columns. */ + + dataptr = data; + for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { + tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*7]; + tmp7 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*7]; + tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*6]; + tmp6 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*6]; + tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*5]; + tmp5 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*5]; + tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*4]; + tmp4 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*4]; + + /* Even part */ + + tmp10 = tmp0 + tmp3; /* phase 2 */ + tmp13 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp1 - tmp2; + + dataptr[DCTSIZE*0] = tmp10 + tmp11; /* phase 3 */ + dataptr[DCTSIZE*4] = tmp10 - tmp11; + + z1 = MULTIPLY(tmp12 + tmp13, FIX_0_707106781); /* c4 */ + dataptr[DCTSIZE*2] = tmp13 + z1; /* phase 5 */ + dataptr[DCTSIZE*6] = tmp13 - z1; + + /* Odd part */ + + tmp10 = tmp4 + tmp5; /* phase 2 */ + tmp11 = tmp5 + tmp6; + tmp12 = tmp6 + tmp7; + + /* The rotator is modified from fig 4-8 to avoid extra negations. */ + z5 = MULTIPLY(tmp10 - tmp12, FIX_0_382683433); /* c6 */ + z2 = MULTIPLY(tmp10, FIX_0_541196100) + z5; /* c2-c6 */ + z4 = MULTIPLY(tmp12, FIX_1_306562965) + z5; /* c2+c6 */ + z3 = MULTIPLY(tmp11, FIX_0_707106781); /* c4 */ + + z11 = tmp7 + z3; /* phase 5 */ + z13 = tmp7 - z3; + + dataptr[DCTSIZE*5] = z13 + z2; /* phase 6 */ + dataptr[DCTSIZE*3] = z13 - z2; + dataptr[DCTSIZE*1] = z11 + z4; + dataptr[DCTSIZE*7] = z11 - z4; + + dataptr++; /* advance pointer to next column */ + } +} + +#endif /* DCT_IFAST_SUPPORTED */ diff --git a/dcmjpeg/libijg16/jfdctint.c b/dcmjpeg/libijg16/jfdctint.c new file mode 100644 index 00000000..12d9ab25 --- /dev/null +++ b/dcmjpeg/libijg16/jfdctint.c @@ -0,0 +1,283 @@ +/* + * jfdctint.c + * + * Copyright (C) 1991-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains a slow-but-accurate integer implementation of the + * forward DCT (Discrete Cosine Transform). + * + * A 2-D DCT can be done by 1-D DCT on each row followed by 1-D DCT + * on each column. Direct algorithms are also available, but they are + * much more complex and seem not to be any faster when reduced to code. + * + * This implementation is based on an algorithm described in + * C. Loeffler, A. Ligtenberg and G. Moschytz, "Practical Fast 1-D DCT + * Algorithms with 11 Multiplications", Proc. Int'l. Conf. on Acoustics, + * Speech, and Signal Processing 1989 (ICASSP '89), pp. 988-991. + * The primary algorithm described there uses 11 multiplies and 29 adds. + * We use their alternate method with 12 multiplies and 32 adds. + * The advantage of this method is that no data path contains more than one + * multiplication; this allows a very simple and accurate implementation in + * scaled fixed-point arithmetic, with a minimal number of shifts. + */ + +#define JPEG_INTERNALS +#include "jinclude16.h" +#include "jpeglib16.h" +#include "jdct16.h" /* Private declarations for DCT subsystem */ + +#ifdef DCT_ISLOW_SUPPORTED + + +/* + * This module is specialized to the case DCTSIZE = 8. + */ + +#if DCTSIZE != 8 + Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */ +#endif + + +/* + * The poop on this scaling stuff is as follows: + * + * Each 1-D DCT step produces outputs which are a factor of sqrt(N) + * larger than the true DCT outputs. The final outputs are therefore + * a factor of N larger than desired; since N=8 this can be cured by + * a simple right shift at the end of the algorithm. The advantage of + * this arrangement is that we save two multiplications per 1-D DCT, + * because the y0 and y4 outputs need not be divided by sqrt(N). + * In the IJG code, this factor of 8 is removed by the quantization step + * (in jcdctmgr.c), NOT in this module. + * + * We have to do addition and subtraction of the integer inputs, which + * is no problem, and multiplication by fractional constants, which is + * a problem to do in integer arithmetic. We multiply all the constants + * by CONST_SCALE and convert them to integer constants (thus retaining + * CONST_BITS bits of precision in the constants). After doing a + * multiplication we have to divide the product by CONST_SCALE, with proper + * rounding, to produce the correct output. This division can be done + * cheaply as a right shift of CONST_BITS bits. We postpone shifting + * as long as possible so that partial sums can be added together with + * full fractional precision. + * + * The outputs of the first pass are scaled up by PASS1_BITS bits so that + * they are represented to better-than-integral precision. These outputs + * require BITS_IN_JSAMPLE + PASS1_BITS + 3 bits; this fits in a 16-bit word + * with the recommended scaling. (For 12-bit sample data, the intermediate + * array is IJG_INT32 anyway.) + * + * To avoid overflow of the 32-bit intermediate results in pass 2, we must + * have BITS_IN_JSAMPLE + CONST_BITS + PASS1_BITS <= 26. Error analysis + * shows that the values given below are the most effective. + */ + +#if BITS_IN_JSAMPLE == 8 +#define CONST_BITS 13 +#define PASS1_BITS 2 +#else +#define CONST_BITS 13 +#define PASS1_BITS 1 /* lose a little precision to avoid overflow */ +#endif + +/* Some C compilers fail to reduce "FIX(constant)" at compile time, thus + * causing a lot of useless floating-point operations at run time. + * To get around this we use the following pre-calculated constants. + * If you change CONST_BITS you may want to add appropriate values. + * (With a reasonable C compiler, you can just rely on the FIX() macro...) + */ + +#if CONST_BITS == 13 +#define FIX_0_298631336 ((IJG_INT32) 2446) /* FIX(0.298631336) */ +#define FIX_0_390180644 ((IJG_INT32) 3196) /* FIX(0.390180644) */ +#define FIX_0_541196100 ((IJG_INT32) 4433) /* FIX(0.541196100) */ +#define FIX_0_765366865 ((IJG_INT32) 6270) /* FIX(0.765366865) */ +#define FIX_0_899976223 ((IJG_INT32) 7373) /* FIX(0.899976223) */ +#define FIX_1_175875602 ((IJG_INT32) 9633) /* FIX(1.175875602) */ +#define FIX_1_501321110 ((IJG_INT32) 12299) /* FIX(1.501321110) */ +#define FIX_1_847759065 ((IJG_INT32) 15137) /* FIX(1.847759065) */ +#define FIX_1_961570560 ((IJG_INT32) 16069) /* FIX(1.961570560) */ +#define FIX_2_053119869 ((IJG_INT32) 16819) /* FIX(2.053119869) */ +#define FIX_2_562915447 ((IJG_INT32) 20995) /* FIX(2.562915447) */ +#define FIX_3_072711026 ((IJG_INT32) 25172) /* FIX(3.072711026) */ +#else +#define FIX_0_298631336 FIX(0.298631336) +#define FIX_0_390180644 FIX(0.390180644) +#define FIX_0_541196100 FIX(0.541196100) +#define FIX_0_765366865 FIX(0.765366865) +#define FIX_0_899976223 FIX(0.899976223) +#define FIX_1_175875602 FIX(1.175875602) +#define FIX_1_501321110 FIX(1.501321110) +#define FIX_1_847759065 FIX(1.847759065) +#define FIX_1_961570560 FIX(1.961570560) +#define FIX_2_053119869 FIX(2.053119869) +#define FIX_2_562915447 FIX(2.562915447) +#define FIX_3_072711026 FIX(3.072711026) +#endif + + +/* Multiply an IJG_INT32 variable by an IJG_INT32 constant to yield an IJG_INT32 result. + * For 8-bit samples with the recommended scaling, all the variable + * and constant values involved are no more than 16 bits wide, so a + * 16x16->32 bit multiply can be used instead of a full 32x32 multiply. + * For 12-bit samples, a full 32-bit multiplication will be needed. + */ + +#if BITS_IN_JSAMPLE == 8 +#define MULTIPLY(var,const) MULTIPLY16C16(var,const) +#else +#define MULTIPLY(var,const) ((var) * (const)) +#endif + + +/* + * Perform the forward DCT on one block of samples. + */ + +GLOBAL(void) +jpeg_fdct_islow (DCTELEM * data) +{ + IJG_INT32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + IJG_INT32 tmp10, tmp11, tmp12, tmp13; + IJG_INT32 z1, z2, z3, z4, z5; + DCTELEM *dataptr; + int ctr; + SHIFT_TEMPS + + /* Pass 1: process rows. */ + /* Note results are scaled up by sqrt(8) compared to a true DCT; */ + /* furthermore, we scale the results by 2**PASS1_BITS. */ + + dataptr = data; + for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { + tmp0 = dataptr[0] + dataptr[7]; + tmp7 = dataptr[0] - dataptr[7]; + tmp1 = dataptr[1] + dataptr[6]; + tmp6 = dataptr[1] - dataptr[6]; + tmp2 = dataptr[2] + dataptr[5]; + tmp5 = dataptr[2] - dataptr[5]; + tmp3 = dataptr[3] + dataptr[4]; + tmp4 = dataptr[3] - dataptr[4]; + + /* Even part per LL&M figure 1 --- note that published figure is faulty; + * rotator "sqrt(2)*c1" should be "sqrt(2)*c6". + */ + + tmp10 = tmp0 + tmp3; + tmp13 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp1 - tmp2; + + dataptr[0] = (DCTELEM) ((tmp10 + tmp11) << PASS1_BITS); + dataptr[4] = (DCTELEM) ((tmp10 - tmp11) << PASS1_BITS); + + z1 = MULTIPLY(tmp12 + tmp13, FIX_0_541196100); + dataptr[2] = (DCTELEM) DESCALE(z1 + MULTIPLY(tmp13, FIX_0_765366865), + CONST_BITS-PASS1_BITS); + dataptr[6] = (DCTELEM) DESCALE(z1 + MULTIPLY(tmp12, - FIX_1_847759065), + CONST_BITS-PASS1_BITS); + + /* Odd part per figure 8 --- note paper omits factor of sqrt(2). + * cK represents cos(K*pi/16). + * i0..i3 in the paper are tmp4..tmp7 here. + */ + + z1 = tmp4 + tmp7; + z2 = tmp5 + tmp6; + z3 = tmp4 + tmp6; + z4 = tmp5 + tmp7; + z5 = MULTIPLY(z3 + z4, FIX_1_175875602); /* sqrt(2) * c3 */ + + tmp4 = MULTIPLY(tmp4, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */ + tmp5 = MULTIPLY(tmp5, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */ + tmp6 = MULTIPLY(tmp6, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */ + tmp7 = MULTIPLY(tmp7, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */ + z1 = MULTIPLY(z1, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */ + z2 = MULTIPLY(z2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */ + z3 = MULTIPLY(z3, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */ + z4 = MULTIPLY(z4, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */ + + z3 += z5; + z4 += z5; + + dataptr[7] = (DCTELEM) DESCALE(tmp4 + z1 + z3, CONST_BITS-PASS1_BITS); + dataptr[5] = (DCTELEM) DESCALE(tmp5 + z2 + z4, CONST_BITS-PASS1_BITS); + dataptr[3] = (DCTELEM) DESCALE(tmp6 + z2 + z3, CONST_BITS-PASS1_BITS); + dataptr[1] = (DCTELEM) DESCALE(tmp7 + z1 + z4, CONST_BITS-PASS1_BITS); + + dataptr += DCTSIZE; /* advance pointer to next row */ + } + + /* Pass 2: process columns. + * We remove the PASS1_BITS scaling, but leave the results scaled up + * by an overall factor of 8. + */ + + dataptr = data; + for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { + tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*7]; + tmp7 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*7]; + tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*6]; + tmp6 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*6]; + tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*5]; + tmp5 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*5]; + tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*4]; + tmp4 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*4]; + + /* Even part per LL&M figure 1 --- note that published figure is faulty; + * rotator "sqrt(2)*c1" should be "sqrt(2)*c6". + */ + + tmp10 = tmp0 + tmp3; + tmp13 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp1 - tmp2; + + dataptr[DCTSIZE*0] = (DCTELEM) DESCALE(tmp10 + tmp11, PASS1_BITS); + dataptr[DCTSIZE*4] = (DCTELEM) DESCALE(tmp10 - tmp11, PASS1_BITS); + + z1 = MULTIPLY(tmp12 + tmp13, FIX_0_541196100); + dataptr[DCTSIZE*2] = (DCTELEM) DESCALE(z1 + MULTIPLY(tmp13, FIX_0_765366865), + CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*6] = (DCTELEM) DESCALE(z1 + MULTIPLY(tmp12, - FIX_1_847759065), + CONST_BITS+PASS1_BITS); + + /* Odd part per figure 8 --- note paper omits factor of sqrt(2). + * cK represents cos(K*pi/16). + * i0..i3 in the paper are tmp4..tmp7 here. + */ + + z1 = tmp4 + tmp7; + z2 = tmp5 + tmp6; + z3 = tmp4 + tmp6; + z4 = tmp5 + tmp7; + z5 = MULTIPLY(z3 + z4, FIX_1_175875602); /* sqrt(2) * c3 */ + + tmp4 = MULTIPLY(tmp4, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */ + tmp5 = MULTIPLY(tmp5, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */ + tmp6 = MULTIPLY(tmp6, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */ + tmp7 = MULTIPLY(tmp7, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */ + z1 = MULTIPLY(z1, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */ + z2 = MULTIPLY(z2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */ + z3 = MULTIPLY(z3, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */ + z4 = MULTIPLY(z4, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */ + + z3 += z5; + z4 += z5; + + dataptr[DCTSIZE*7] = (DCTELEM) DESCALE(tmp4 + z1 + z3, + CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*5] = (DCTELEM) DESCALE(tmp5 + z2 + z4, + CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp6 + z2 + z3, + CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(tmp7 + z1 + z4, + CONST_BITS+PASS1_BITS); + + dataptr++; /* advance pointer to next column */ + } +} + +#endif /* DCT_ISLOW_SUPPORTED */ diff --git a/dcmjpeg/libijg16/jidctflt.c b/dcmjpeg/libijg16/jidctflt.c new file mode 100644 index 00000000..64326cf4 --- /dev/null +++ b/dcmjpeg/libijg16/jidctflt.c @@ -0,0 +1,242 @@ +/* + * jidctflt.c + * + * Copyright (C) 1994-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains a floating-point implementation of the + * inverse DCT (Discrete Cosine Transform). In the IJG code, this routine + * must also perform dequantization of the input coefficients. + * + * This implementation should be more accurate than either of the integer + * IDCT implementations. However, it may not give the same results on all + * machines because of differences in roundoff behavior. Speed will depend + * on the hardware's floating point capacity. + * + * A 2-D IDCT can be done by 1-D IDCT on each column followed by 1-D IDCT + * on each row (or vice versa, but it's more convenient to emit a row at + * a time). Direct algorithms are also available, but they are much more + * complex and seem not to be any faster when reduced to code. + * + * This implementation is based on Arai, Agui, and Nakajima's algorithm for + * scaled DCT. Their original paper (Trans. IEICE E-71(11):1095) is in + * Japanese, but the algorithm is described in the Pennebaker & Mitchell + * JPEG textbook (see REFERENCES section in file README). The following code + * is based directly on figure 4-8 in P&M. + * While an 8-point DCT cannot be done in less than 11 multiplies, it is + * possible to arrange the computation so that many of the multiplies are + * simple scalings of the final outputs. These multiplies can then be + * folded into the multiplications or divisions by the JPEG quantization + * table entries. The AA&N method leaves only 5 multiplies and 29 adds + * to be done in the DCT itself. + * The primary disadvantage of this method is that with a fixed-point + * implementation, accuracy is lost due to imprecise representation of the + * scaled quantization values. However, that problem does not arise if + * we use floating point arithmetic. + */ + +#define JPEG_INTERNALS +#include "jinclude16.h" +#include "jpeglib16.h" +#include "jdct16.h" /* Private declarations for DCT subsystem */ + +#ifdef DCT_FLOAT_SUPPORTED + + +/* + * This module is specialized to the case DCTSIZE = 8. + */ + +#if DCTSIZE != 8 + Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */ +#endif + + +/* Dequantize a coefficient by multiplying it by the multiplier-table + * entry; produce a float result. + */ + +#define DEQUANTIZE(coef,quantval) (((FAST_FLOAT) (coef)) * (quantval)) + + +/* + * Perform dequantization and inverse DCT on one block of coefficients. + */ + +GLOBAL(void) +jpeg_idct_float (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + FAST_FLOAT tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + FAST_FLOAT tmp10, tmp11, tmp12, tmp13; + FAST_FLOAT z5, z10, z11, z12, z13; + JCOEFPTR inptr; + FLOAT_MULT_TYPE * quantptr; + FAST_FLOAT * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + FAST_FLOAT workspace[DCTSIZE2]; /* buffers data between passes */ + SHIFT_TEMPS + + /* Pass 1: process columns from input, store into work array. */ + + inptr = coef_block; + quantptr = (FLOAT_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = DCTSIZE; ctr > 0; ctr--) { + /* Due to quantization, we will usually find that many of the input + * coefficients are zero, especially the AC terms. We can exploit this + * by short-circuiting the IDCT calculation for any column in which all + * the AC terms are zero. In that case each output is equal to the + * DC coefficient (with scale factor as needed). + * With typical images and quantization tables, half or more of the + * column DCT calculations can be simplified this way. + */ + + if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*2] == 0 && + inptr[DCTSIZE*3] == 0 && inptr[DCTSIZE*4] == 0 && + inptr[DCTSIZE*5] == 0 && inptr[DCTSIZE*6] == 0 && + inptr[DCTSIZE*7] == 0) { + /* AC terms all zero */ + FAST_FLOAT dcval = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + + wsptr[DCTSIZE*0] = dcval; + wsptr[DCTSIZE*1] = dcval; + wsptr[DCTSIZE*2] = dcval; + wsptr[DCTSIZE*3] = dcval; + wsptr[DCTSIZE*4] = dcval; + wsptr[DCTSIZE*5] = dcval; + wsptr[DCTSIZE*6] = dcval; + wsptr[DCTSIZE*7] = dcval; + + inptr++; /* advance pointers to next column */ + quantptr++; + wsptr++; + continue; + } + + /* Even part */ + + tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + tmp1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + tmp2 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); + tmp3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); + + tmp10 = tmp0 + tmp2; /* phase 3 */ + tmp11 = tmp0 - tmp2; + + tmp13 = tmp1 + tmp3; /* phases 5-3 */ + tmp12 = (tmp1 - tmp3) * ((FAST_FLOAT) 1.414213562) - tmp13; /* 2*c4 */ + + tmp0 = tmp10 + tmp13; /* phase 2 */ + tmp3 = tmp10 - tmp13; + tmp1 = tmp11 + tmp12; + tmp2 = tmp11 - tmp12; + + /* Odd part */ + + tmp4 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + tmp5 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + tmp6 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); + tmp7 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); + + z13 = tmp6 + tmp5; /* phase 6 */ + z10 = tmp6 - tmp5; + z11 = tmp4 + tmp7; + z12 = tmp4 - tmp7; + + tmp7 = z11 + z13; /* phase 5 */ + tmp11 = (z11 - z13) * ((FAST_FLOAT) 1.414213562); /* 2*c4 */ + + z5 = (z10 + z12) * ((FAST_FLOAT) 1.847759065); /* 2*c2 */ + tmp10 = ((FAST_FLOAT) 1.082392200) * z12 - z5; /* 2*(c2-c6) */ + tmp12 = ((FAST_FLOAT) -2.613125930) * z10 + z5; /* -2*(c2+c6) */ + + tmp6 = tmp12 - tmp7; /* phase 2 */ + tmp5 = tmp11 - tmp6; + tmp4 = tmp10 + tmp5; + + wsptr[DCTSIZE*0] = tmp0 + tmp7; + wsptr[DCTSIZE*7] = tmp0 - tmp7; + wsptr[DCTSIZE*1] = tmp1 + tmp6; + wsptr[DCTSIZE*6] = tmp1 - tmp6; + wsptr[DCTSIZE*2] = tmp2 + tmp5; + wsptr[DCTSIZE*5] = tmp2 - tmp5; + wsptr[DCTSIZE*4] = tmp3 + tmp4; + wsptr[DCTSIZE*3] = tmp3 - tmp4; + + inptr++; /* advance pointers to next column */ + quantptr++; + wsptr++; + } + + /* Pass 2: process rows from work array, store into output array. */ + /* Note that we must descale the results by a factor of 8 == 2**3. */ + + wsptr = workspace; + for (ctr = 0; ctr < DCTSIZE; ctr++) { + outptr = output_buf[ctr] + output_col; + /* Rows of zeroes can be exploited in the same way as we did with columns. + * However, the column calculation has created many nonzero AC terms, so + * the simplification applies less often (typically 5% to 10% of the time). + * And testing floats for zero is relatively expensive, so we don't bother. + */ + + /* Even part */ + + tmp10 = wsptr[0] + wsptr[4]; + tmp11 = wsptr[0] - wsptr[4]; + + tmp13 = wsptr[2] + wsptr[6]; + tmp12 = (wsptr[2] - wsptr[6]) * ((FAST_FLOAT) 1.414213562) - tmp13; + + tmp0 = tmp10 + tmp13; + tmp3 = tmp10 - tmp13; + tmp1 = tmp11 + tmp12; + tmp2 = tmp11 - tmp12; + + /* Odd part */ + + z13 = wsptr[5] + wsptr[3]; + z10 = wsptr[5] - wsptr[3]; + z11 = wsptr[1] + wsptr[7]; + z12 = wsptr[1] - wsptr[7]; + + tmp7 = z11 + z13; + tmp11 = (z11 - z13) * ((FAST_FLOAT) 1.414213562); + + z5 = (z10 + z12) * ((FAST_FLOAT) 1.847759065); /* 2*c2 */ + tmp10 = ((FAST_FLOAT) 1.082392200) * z12 - z5; /* 2*(c2-c6) */ + tmp12 = ((FAST_FLOAT) -2.613125930) * z10 + z5; /* -2*(c2+c6) */ + + tmp6 = tmp12 - tmp7; + tmp5 = tmp11 - tmp6; + tmp4 = tmp10 + tmp5; + + /* Final output stage: scale down by a factor of 8 and range-limit */ + + outptr[0] = range_limit[(int) DESCALE((IJG_INT32) (tmp0 + tmp7), 3) + & RANGE_MASK]; + outptr[7] = range_limit[(int) DESCALE((IJG_INT32) (tmp0 - tmp7), 3) + & RANGE_MASK]; + outptr[1] = range_limit[(int) DESCALE((IJG_INT32) (tmp1 + tmp6), 3) + & RANGE_MASK]; + outptr[6] = range_limit[(int) DESCALE((IJG_INT32) (tmp1 - tmp6), 3) + & RANGE_MASK]; + outptr[2] = range_limit[(int) DESCALE((IJG_INT32) (tmp2 + tmp5), 3) + & RANGE_MASK]; + outptr[5] = range_limit[(int) DESCALE((IJG_INT32) (tmp2 - tmp5), 3) + & RANGE_MASK]; + outptr[4] = range_limit[(int) DESCALE((IJG_INT32) (tmp3 + tmp4), 3) + & RANGE_MASK]; + outptr[3] = range_limit[(int) DESCALE((IJG_INT32) (tmp3 - tmp4), 3) + & RANGE_MASK]; + + wsptr += DCTSIZE; /* advance pointer to next row */ + } +} + +#endif /* DCT_FLOAT_SUPPORTED */ diff --git a/dcmjpeg/libijg16/jidctfst.c b/dcmjpeg/libijg16/jidctfst.c new file mode 100644 index 00000000..239d3b05 --- /dev/null +++ b/dcmjpeg/libijg16/jidctfst.c @@ -0,0 +1,368 @@ +/* + * jidctfst.c + * + * Copyright (C) 1994-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains a fast, not so accurate integer implementation of the + * inverse DCT (Discrete Cosine Transform). In the IJG code, this routine + * must also perform dequantization of the input coefficients. + * + * A 2-D IDCT can be done by 1-D IDCT on each column followed by 1-D IDCT + * on each row (or vice versa, but it's more convenient to emit a row at + * a time). Direct algorithms are also available, but they are much more + * complex and seem not to be any faster when reduced to code. + * + * This implementation is based on Arai, Agui, and Nakajima's algorithm for + * scaled DCT. Their original paper (Trans. IEICE E-71(11):1095) is in + * Japanese, but the algorithm is described in the Pennebaker & Mitchell + * JPEG textbook (see REFERENCES section in file README). The following code + * is based directly on figure 4-8 in P&M. + * While an 8-point DCT cannot be done in less than 11 multiplies, it is + * possible to arrange the computation so that many of the multiplies are + * simple scalings of the final outputs. These multiplies can then be + * folded into the multiplications or divisions by the JPEG quantization + * table entries. The AA&N method leaves only 5 multiplies and 29 adds + * to be done in the DCT itself. + * The primary disadvantage of this method is that with fixed-point math, + * accuracy is lost due to imprecise representation of the scaled + * quantization values. The smaller the quantization table entry, the less + * precise the scaled value, so this implementation does worse with high- + * quality-setting files than with low-quality ones. + */ + +#define JPEG_INTERNALS +#include "jinclude16.h" +#include "jpeglib16.h" +#include "jdct16.h" /* Private declarations for DCT subsystem */ + +#ifdef DCT_IFAST_SUPPORTED + + +/* + * This module is specialized to the case DCTSIZE = 8. + */ + +#if DCTSIZE != 8 + Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */ +#endif + + +/* Scaling decisions are generally the same as in the LL&M algorithm; + * see jidctint.c for more details. However, we choose to descale + * (right shift) multiplication products as soon as they are formed, + * rather than carrying additional fractional bits into subsequent additions. + * This compromises accuracy slightly, but it lets us save a few shifts. + * More importantly, 16-bit arithmetic is then adequate (for 8-bit samples) + * everywhere except in the multiplications proper; this saves a good deal + * of work on 16-bit-int machines. + * + * The dequantized coefficients are not integers because the AA&N scaling + * factors have been incorporated. We represent them scaled up by PASS1_BITS, + * so that the first and second IDCT rounds have the same input scaling. + * For 8-bit JSAMPLEs, we choose IFAST_SCALE_BITS = PASS1_BITS so as to + * avoid a descaling shift; this compromises accuracy rather drastically + * for small quantization table entries, but it saves a lot of shifts. + * For 12-bit JSAMPLEs, there's no hope of using 16x16 multiplies anyway, + * so we use a much larger scaling factor to preserve accuracy. + * + * A final compromise is to represent the multiplicative constants to only + * 8 fractional bits, rather than 13. This saves some shifting work on some + * machines, and may also reduce the cost of multiplication (since there + * are fewer one-bits in the constants). + */ + +#if BITS_IN_JSAMPLE == 8 +#define CONST_BITS 8 +#define PASS1_BITS 2 +#else +#define CONST_BITS 8 +#define PASS1_BITS 1 /* lose a little precision to avoid overflow */ +#endif + +/* Some C compilers fail to reduce "FIX(constant)" at compile time, thus + * causing a lot of useless floating-point operations at run time. + * To get around this we use the following pre-calculated constants. + * If you change CONST_BITS you may want to add appropriate values. + * (With a reasonable C compiler, you can just rely on the FIX() macro...) + */ + +#if CONST_BITS == 8 +#define FIX_1_082392200 ((IJG_INT32) 277) /* FIX(1.082392200) */ +#define FIX_1_414213562 ((IJG_INT32) 362) /* FIX(1.414213562) */ +#define FIX_1_847759065 ((IJG_INT32) 473) /* FIX(1.847759065) */ +#define FIX_2_613125930 ((IJG_INT32) 669) /* FIX(2.613125930) */ +#else +#define FIX_1_082392200 FIX(1.082392200) +#define FIX_1_414213562 FIX(1.414213562) +#define FIX_1_847759065 FIX(1.847759065) +#define FIX_2_613125930 FIX(2.613125930) +#endif + + +/* We can gain a little more speed, with a further compromise in accuracy, + * by omitting the addition in a descaling shift. This yields an incorrectly + * rounded result half the time... + */ + +#ifndef USE_ACCURATE_ROUNDING +#undef DESCALE +#define DESCALE(x,n) RIGHT_SHIFT(x, n) +#endif + + +/* Multiply a DCTELEM variable by an IJG_INT32 constant, and immediately + * descale to yield a DCTELEM result. + */ + +#define MULTIPLY(var,const) ((DCTELEM) DESCALE((var) * (const), CONST_BITS)) + + +/* Dequantize a coefficient by multiplying it by the multiplier-table + * entry; produce a DCTELEM result. For 8-bit data a 16x16->16 + * multiplication will do. For 12-bit data, the multiplier table is + * declared IJG_INT32, so a 32-bit multiply will be used. + */ + +#if BITS_IN_JSAMPLE == 8 +#define DEQUANTIZE(coef,quantval) (((IFAST_MULT_TYPE) (coef)) * (quantval)) +#else +#define DEQUANTIZE(coef,quantval) \ + DESCALE((coef)*(quantval), IFAST_SCALE_BITS-PASS1_BITS) +#endif + + +/* Like DESCALE, but applies to a DCTELEM and produces an int. + * We assume that int right shift is unsigned if IJG_INT32 right shift is. + */ + +#ifdef RIGHT_SHIFT_IS_UNSIGNED +#define ISHIFT_TEMPS DCTELEM ishift_temp; +#if BITS_IN_JSAMPLE == 8 +#define DCTELEMBITS 16 /* DCTELEM may be 16 or 32 bits */ +#else +#define DCTELEMBITS 32 /* DCTELEM must be 32 bits */ +#endif +#define IRIGHT_SHIFT(x,shft) \ + ((ishift_temp = (x)) < 0 ? \ + (ishift_temp >> (shft)) | ((~((DCTELEM) 0)) << (DCTELEMBITS-(shft))) : \ + (ishift_temp >> (shft))) +#else +#define ISHIFT_TEMPS +#define IRIGHT_SHIFT(x,shft) ((x) >> (shft)) +#endif + +#ifdef USE_ACCURATE_ROUNDING +#define IDESCALE(x,n) ((int) IRIGHT_SHIFT((x) + (1 << ((n)-1)), n)) +#else +#define IDESCALE(x,n) ((int) IRIGHT_SHIFT(x, n)) +#endif + + +/* + * Perform dequantization and inverse DCT on one block of coefficients. + */ + +GLOBAL(void) +jpeg_idct_ifast (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + DCTELEM tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + DCTELEM tmp10, tmp11, tmp12, tmp13; + DCTELEM z5, z10, z11, z12, z13; + JCOEFPTR inptr; + IFAST_MULT_TYPE * quantptr; + int * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + int workspace[DCTSIZE2]; /* buffers data between passes */ + SHIFT_TEMPS /* for DESCALE */ + ISHIFT_TEMPS /* for IDESCALE */ + + /* Pass 1: process columns from input, store into work array. */ + + inptr = coef_block; + quantptr = (IFAST_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = DCTSIZE; ctr > 0; ctr--) { + /* Due to quantization, we will usually find that many of the input + * coefficients are zero, especially the AC terms. We can exploit this + * by short-circuiting the IDCT calculation for any column in which all + * the AC terms are zero. In that case each output is equal to the + * DC coefficient (with scale factor as needed). + * With typical images and quantization tables, half or more of the + * column DCT calculations can be simplified this way. + */ + + if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*2] == 0 && + inptr[DCTSIZE*3] == 0 && inptr[DCTSIZE*4] == 0 && + inptr[DCTSIZE*5] == 0 && inptr[DCTSIZE*6] == 0 && + inptr[DCTSIZE*7] == 0) { + /* AC terms all zero */ + int dcval = (int) DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + + wsptr[DCTSIZE*0] = dcval; + wsptr[DCTSIZE*1] = dcval; + wsptr[DCTSIZE*2] = dcval; + wsptr[DCTSIZE*3] = dcval; + wsptr[DCTSIZE*4] = dcval; + wsptr[DCTSIZE*5] = dcval; + wsptr[DCTSIZE*6] = dcval; + wsptr[DCTSIZE*7] = dcval; + + inptr++; /* advance pointers to next column */ + quantptr++; + wsptr++; + continue; + } + + /* Even part */ + + tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + tmp1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + tmp2 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); + tmp3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); + + tmp10 = tmp0 + tmp2; /* phase 3 */ + tmp11 = tmp0 - tmp2; + + tmp13 = tmp1 + tmp3; /* phases 5-3 */ + tmp12 = MULTIPLY(tmp1 - tmp3, FIX_1_414213562) - tmp13; /* 2*c4 */ + + tmp0 = tmp10 + tmp13; /* phase 2 */ + tmp3 = tmp10 - tmp13; + tmp1 = tmp11 + tmp12; + tmp2 = tmp11 - tmp12; + + /* Odd part */ + + tmp4 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + tmp5 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + tmp6 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); + tmp7 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); + + z13 = tmp6 + tmp5; /* phase 6 */ + z10 = tmp6 - tmp5; + z11 = tmp4 + tmp7; + z12 = tmp4 - tmp7; + + tmp7 = z11 + z13; /* phase 5 */ + tmp11 = MULTIPLY(z11 - z13, FIX_1_414213562); /* 2*c4 */ + + z5 = MULTIPLY(z10 + z12, FIX_1_847759065); /* 2*c2 */ + tmp10 = MULTIPLY(z12, FIX_1_082392200) - z5; /* 2*(c2-c6) */ + tmp12 = MULTIPLY(z10, - FIX_2_613125930) + z5; /* -2*(c2+c6) */ + + tmp6 = tmp12 - tmp7; /* phase 2 */ + tmp5 = tmp11 - tmp6; + tmp4 = tmp10 + tmp5; + + wsptr[DCTSIZE*0] = (int) (tmp0 + tmp7); + wsptr[DCTSIZE*7] = (int) (tmp0 - tmp7); + wsptr[DCTSIZE*1] = (int) (tmp1 + tmp6); + wsptr[DCTSIZE*6] = (int) (tmp1 - tmp6); + wsptr[DCTSIZE*2] = (int) (tmp2 + tmp5); + wsptr[DCTSIZE*5] = (int) (tmp2 - tmp5); + wsptr[DCTSIZE*4] = (int) (tmp3 + tmp4); + wsptr[DCTSIZE*3] = (int) (tmp3 - tmp4); + + inptr++; /* advance pointers to next column */ + quantptr++; + wsptr++; + } + + /* Pass 2: process rows from work array, store into output array. */ + /* Note that we must descale the results by a factor of 8 == 2**3, */ + /* and also undo the PASS1_BITS scaling. */ + + wsptr = workspace; + for (ctr = 0; ctr < DCTSIZE; ctr++) { + outptr = output_buf[ctr] + output_col; + /* Rows of zeroes can be exploited in the same way as we did with columns. + * However, the column calculation has created many nonzero AC terms, so + * the simplification applies less often (typically 5% to 10% of the time). + * On machines with very fast multiplication, it's possible that the + * test takes more time than it's worth. In that case this section + * may be commented out. + */ + +#ifndef NO_ZERO_ROW_TEST + if (wsptr[1] == 0 && wsptr[2] == 0 && wsptr[3] == 0 && wsptr[4] == 0 && + wsptr[5] == 0 && wsptr[6] == 0 && wsptr[7] == 0) { + /* AC terms all zero */ + JSAMPLE dcval = range_limit[IDESCALE(wsptr[0], PASS1_BITS+3) + & RANGE_MASK]; + + outptr[0] = dcval; + outptr[1] = dcval; + outptr[2] = dcval; + outptr[3] = dcval; + outptr[4] = dcval; + outptr[5] = dcval; + outptr[6] = dcval; + outptr[7] = dcval; + + wsptr += DCTSIZE; /* advance pointer to next row */ + continue; + } +#endif + + /* Even part */ + + tmp10 = ((DCTELEM) wsptr[0] + (DCTELEM) wsptr[4]); + tmp11 = ((DCTELEM) wsptr[0] - (DCTELEM) wsptr[4]); + + tmp13 = ((DCTELEM) wsptr[2] + (DCTELEM) wsptr[6]); + tmp12 = MULTIPLY((DCTELEM) wsptr[2] - (DCTELEM) wsptr[6], FIX_1_414213562) + - tmp13; + + tmp0 = tmp10 + tmp13; + tmp3 = tmp10 - tmp13; + tmp1 = tmp11 + tmp12; + tmp2 = tmp11 - tmp12; + + /* Odd part */ + + z13 = (DCTELEM) wsptr[5] + (DCTELEM) wsptr[3]; + z10 = (DCTELEM) wsptr[5] - (DCTELEM) wsptr[3]; + z11 = (DCTELEM) wsptr[1] + (DCTELEM) wsptr[7]; + z12 = (DCTELEM) wsptr[1] - (DCTELEM) wsptr[7]; + + tmp7 = z11 + z13; /* phase 5 */ + tmp11 = MULTIPLY(z11 - z13, FIX_1_414213562); /* 2*c4 */ + + z5 = MULTIPLY(z10 + z12, FIX_1_847759065); /* 2*c2 */ + tmp10 = MULTIPLY(z12, FIX_1_082392200) - z5; /* 2*(c2-c6) */ + tmp12 = MULTIPLY(z10, - FIX_2_613125930) + z5; /* -2*(c2+c6) */ + + tmp6 = tmp12 - tmp7; /* phase 2 */ + tmp5 = tmp11 - tmp6; + tmp4 = tmp10 + tmp5; + + /* Final output stage: scale down by a factor of 8 and range-limit */ + + outptr[0] = range_limit[IDESCALE(tmp0 + tmp7, PASS1_BITS+3) + & RANGE_MASK]; + outptr[7] = range_limit[IDESCALE(tmp0 - tmp7, PASS1_BITS+3) + & RANGE_MASK]; + outptr[1] = range_limit[IDESCALE(tmp1 + tmp6, PASS1_BITS+3) + & RANGE_MASK]; + outptr[6] = range_limit[IDESCALE(tmp1 - tmp6, PASS1_BITS+3) + & RANGE_MASK]; + outptr[2] = range_limit[IDESCALE(tmp2 + tmp5, PASS1_BITS+3) + & RANGE_MASK]; + outptr[5] = range_limit[IDESCALE(tmp2 - tmp5, PASS1_BITS+3) + & RANGE_MASK]; + outptr[4] = range_limit[IDESCALE(tmp3 + tmp4, PASS1_BITS+3) + & RANGE_MASK]; + outptr[3] = range_limit[IDESCALE(tmp3 - tmp4, PASS1_BITS+3) + & RANGE_MASK]; + + wsptr += DCTSIZE; /* advance pointer to next row */ + } +} + +#endif /* DCT_IFAST_SUPPORTED */ diff --git a/dcmjpeg/libijg16/jidctint.c b/dcmjpeg/libijg16/jidctint.c new file mode 100644 index 00000000..25785d8d --- /dev/null +++ b/dcmjpeg/libijg16/jidctint.c @@ -0,0 +1,389 @@ +/* + * jidctint.c + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains a slow-but-accurate integer implementation of the + * inverse DCT (Discrete Cosine Transform). In the IJG code, this routine + * must also perform dequantization of the input coefficients. + * + * A 2-D IDCT can be done by 1-D IDCT on each column followed by 1-D IDCT + * on each row (or vice versa, but it's more convenient to emit a row at + * a time). Direct algorithms are also available, but they are much more + * complex and seem not to be any faster when reduced to code. + * + * This implementation is based on an algorithm described in + * C. Loeffler, A. Ligtenberg and G. Moschytz, "Practical Fast 1-D DCT + * Algorithms with 11 Multiplications", Proc. Int'l. Conf. on Acoustics, + * Speech, and Signal Processing 1989 (ICASSP '89), pp. 988-991. + * The primary algorithm described there uses 11 multiplies and 29 adds. + * We use their alternate method with 12 multiplies and 32 adds. + * The advantage of this method is that no data path contains more than one + * multiplication; this allows a very simple and accurate implementation in + * scaled fixed-point arithmetic, with a minimal number of shifts. + */ + +#define JPEG_INTERNALS +#include "jinclude16.h" +#include "jpeglib16.h" +#include "jdct16.h" /* Private declarations for DCT subsystem */ + +#ifdef DCT_ISLOW_SUPPORTED + + +/* + * This module is specialized to the case DCTSIZE = 8. + */ + +#if DCTSIZE != 8 + Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */ +#endif + + +/* + * The poop on this scaling stuff is as follows: + * + * Each 1-D IDCT step produces outputs which are a factor of sqrt(N) + * larger than the true IDCT outputs. The final outputs are therefore + * a factor of N larger than desired; since N=8 this can be cured by + * a simple right shift at the end of the algorithm. The advantage of + * this arrangement is that we save two multiplications per 1-D IDCT, + * because the y0 and y4 inputs need not be divided by sqrt(N). + * + * We have to do addition and subtraction of the integer inputs, which + * is no problem, and multiplication by fractional constants, which is + * a problem to do in integer arithmetic. We multiply all the constants + * by CONST_SCALE and convert them to integer constants (thus retaining + * CONST_BITS bits of precision in the constants). After doing a + * multiplication we have to divide the product by CONST_SCALE, with proper + * rounding, to produce the correct output. This division can be done + * cheaply as a right shift of CONST_BITS bits. We postpone shifting + * as long as possible so that partial sums can be added together with + * full fractional precision. + * + * The outputs of the first pass are scaled up by PASS1_BITS bits so that + * they are represented to better-than-integral precision. These outputs + * require BITS_IN_JSAMPLE + PASS1_BITS + 3 bits; this fits in a 16-bit word + * with the recommended scaling. (To scale up 12-bit sample data further, an + * intermediate IJG_INT32 array would be needed.) + * + * To avoid overflow of the 32-bit intermediate results in pass 2, we must + * have BITS_IN_JSAMPLE + CONST_BITS + PASS1_BITS <= 26. Error analysis + * shows that the values given below are the most effective. + */ + +#if BITS_IN_JSAMPLE == 8 +#define CONST_BITS 13 +#define PASS1_BITS 2 +#else +#define CONST_BITS 13 +#define PASS1_BITS 1 /* lose a little precision to avoid overflow */ +#endif + +/* Some C compilers fail to reduce "FIX(constant)" at compile time, thus + * causing a lot of useless floating-point operations at run time. + * To get around this we use the following pre-calculated constants. + * If you change CONST_BITS you may want to add appropriate values. + * (With a reasonable C compiler, you can just rely on the FIX() macro...) + */ + +#if CONST_BITS == 13 +#define FIX_0_298631336 ((IJG_INT32) 2446) /* FIX(0.298631336) */ +#define FIX_0_390180644 ((IJG_INT32) 3196) /* FIX(0.390180644) */ +#define FIX_0_541196100 ((IJG_INT32) 4433) /* FIX(0.541196100) */ +#define FIX_0_765366865 ((IJG_INT32) 6270) /* FIX(0.765366865) */ +#define FIX_0_899976223 ((IJG_INT32) 7373) /* FIX(0.899976223) */ +#define FIX_1_175875602 ((IJG_INT32) 9633) /* FIX(1.175875602) */ +#define FIX_1_501321110 ((IJG_INT32) 12299) /* FIX(1.501321110) */ +#define FIX_1_847759065 ((IJG_INT32) 15137) /* FIX(1.847759065) */ +#define FIX_1_961570560 ((IJG_INT32) 16069) /* FIX(1.961570560) */ +#define FIX_2_053119869 ((IJG_INT32) 16819) /* FIX(2.053119869) */ +#define FIX_2_562915447 ((IJG_INT32) 20995) /* FIX(2.562915447) */ +#define FIX_3_072711026 ((IJG_INT32) 25172) /* FIX(3.072711026) */ +#else +#define FIX_0_298631336 FIX(0.298631336) +#define FIX_0_390180644 FIX(0.390180644) +#define FIX_0_541196100 FIX(0.541196100) +#define FIX_0_765366865 FIX(0.765366865) +#define FIX_0_899976223 FIX(0.899976223) +#define FIX_1_175875602 FIX(1.175875602) +#define FIX_1_501321110 FIX(1.501321110) +#define FIX_1_847759065 FIX(1.847759065) +#define FIX_1_961570560 FIX(1.961570560) +#define FIX_2_053119869 FIX(2.053119869) +#define FIX_2_562915447 FIX(2.562915447) +#define FIX_3_072711026 FIX(3.072711026) +#endif + + +/* Multiply an IJG_INT32 variable by an IJG_INT32 constant to yield an IJG_INT32 result. + * For 8-bit samples with the recommended scaling, all the variable + * and constant values involved are no more than 16 bits wide, so a + * 16x16->32 bit multiply can be used instead of a full 32x32 multiply. + * For 12-bit samples, a full 32-bit multiplication will be needed. + */ + +#if BITS_IN_JSAMPLE == 8 +#define MULTIPLY(var,const) MULTIPLY16C16(var,const) +#else +#define MULTIPLY(var,const) ((var) * (const)) +#endif + + +/* Dequantize a coefficient by multiplying it by the multiplier-table + * entry; produce an int result. In this module, both inputs and result + * are 16 bits or less, so either int or short multiply will work. + */ + +#define DEQUANTIZE(coef,quantval) (((ISLOW_MULT_TYPE) (coef)) * (quantval)) + + +/* + * Perform dequantization and inverse DCT on one block of coefficients. + */ + +GLOBAL(void) +jpeg_idct_islow (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + IJG_INT32 tmp0, tmp1, tmp2, tmp3; + IJG_INT32 tmp10, tmp11, tmp12, tmp13; + IJG_INT32 z1, z2, z3, z4, z5; + JCOEFPTR inptr; + ISLOW_MULT_TYPE * quantptr; + int * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + int workspace[DCTSIZE2]; /* buffers data between passes */ + SHIFT_TEMPS + + /* Pass 1: process columns from input, store into work array. */ + /* Note results are scaled up by sqrt(8) compared to a true IDCT; */ + /* furthermore, we scale the results by 2**PASS1_BITS. */ + + inptr = coef_block; + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = DCTSIZE; ctr > 0; ctr--) { + /* Due to quantization, we will usually find that many of the input + * coefficients are zero, especially the AC terms. We can exploit this + * by short-circuiting the IDCT calculation for any column in which all + * the AC terms are zero. In that case each output is equal to the + * DC coefficient (with scale factor as needed). + * With typical images and quantization tables, half or more of the + * column DCT calculations can be simplified this way. + */ + + if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*2] == 0 && + inptr[DCTSIZE*3] == 0 && inptr[DCTSIZE*4] == 0 && + inptr[DCTSIZE*5] == 0 && inptr[DCTSIZE*6] == 0 && + inptr[DCTSIZE*7] == 0) { + /* AC terms all zero */ + int dcval = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]) << PASS1_BITS; + + wsptr[DCTSIZE*0] = dcval; + wsptr[DCTSIZE*1] = dcval; + wsptr[DCTSIZE*2] = dcval; + wsptr[DCTSIZE*3] = dcval; + wsptr[DCTSIZE*4] = dcval; + wsptr[DCTSIZE*5] = dcval; + wsptr[DCTSIZE*6] = dcval; + wsptr[DCTSIZE*7] = dcval; + + inptr++; /* advance pointers to next column */ + quantptr++; + wsptr++; + continue; + } + + /* Even part: reverse the even part of the forward DCT. */ + /* The rotator is sqrt(2)*c(-6). */ + + z2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + z3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); + + z1 = MULTIPLY(z2 + z3, FIX_0_541196100); + tmp2 = z1 + MULTIPLY(z3, - FIX_1_847759065); + tmp3 = z1 + MULTIPLY(z2, FIX_0_765366865); + + z2 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + z3 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); + + tmp0 = (z2 + z3) << CONST_BITS; + tmp1 = (z2 - z3) << CONST_BITS; + + tmp10 = tmp0 + tmp3; + tmp13 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp1 - tmp2; + + /* Odd part per figure 8; the matrix is unitary and hence its + * transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively. + */ + + tmp0 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); + tmp1 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); + tmp2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + tmp3 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + + z1 = tmp0 + tmp3; + z2 = tmp1 + tmp2; + z3 = tmp0 + tmp2; + z4 = tmp1 + tmp3; + z5 = MULTIPLY(z3 + z4, FIX_1_175875602); /* sqrt(2) * c3 */ + + tmp0 = MULTIPLY(tmp0, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */ + tmp1 = MULTIPLY(tmp1, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */ + tmp2 = MULTIPLY(tmp2, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */ + tmp3 = MULTIPLY(tmp3, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */ + z1 = MULTIPLY(z1, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */ + z2 = MULTIPLY(z2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */ + z3 = MULTIPLY(z3, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */ + z4 = MULTIPLY(z4, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */ + + z3 += z5; + z4 += z5; + + tmp0 += z1 + z3; + tmp1 += z2 + z4; + tmp2 += z2 + z3; + tmp3 += z1 + z4; + + /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */ + + wsptr[DCTSIZE*0] = (int) DESCALE(tmp10 + tmp3, CONST_BITS-PASS1_BITS); + wsptr[DCTSIZE*7] = (int) DESCALE(tmp10 - tmp3, CONST_BITS-PASS1_BITS); + wsptr[DCTSIZE*1] = (int) DESCALE(tmp11 + tmp2, CONST_BITS-PASS1_BITS); + wsptr[DCTSIZE*6] = (int) DESCALE(tmp11 - tmp2, CONST_BITS-PASS1_BITS); + wsptr[DCTSIZE*2] = (int) DESCALE(tmp12 + tmp1, CONST_BITS-PASS1_BITS); + wsptr[DCTSIZE*5] = (int) DESCALE(tmp12 - tmp1, CONST_BITS-PASS1_BITS); + wsptr[DCTSIZE*3] = (int) DESCALE(tmp13 + tmp0, CONST_BITS-PASS1_BITS); + wsptr[DCTSIZE*4] = (int) DESCALE(tmp13 - tmp0, CONST_BITS-PASS1_BITS); + + inptr++; /* advance pointers to next column */ + quantptr++; + wsptr++; + } + + /* Pass 2: process rows from work array, store into output array. */ + /* Note that we must descale the results by a factor of 8 == 2**3, */ + /* and also undo the PASS1_BITS scaling. */ + + wsptr = workspace; + for (ctr = 0; ctr < DCTSIZE; ctr++) { + outptr = output_buf[ctr] + output_col; + /* Rows of zeroes can be exploited in the same way as we did with columns. + * However, the column calculation has created many nonzero AC terms, so + * the simplification applies less often (typically 5% to 10% of the time). + * On machines with very fast multiplication, it's possible that the + * test takes more time than it's worth. In that case this section + * may be commented out. + */ + +#ifndef NO_ZERO_ROW_TEST + if (wsptr[1] == 0 && wsptr[2] == 0 && wsptr[3] == 0 && wsptr[4] == 0 && + wsptr[5] == 0 && wsptr[6] == 0 && wsptr[7] == 0) { + /* AC terms all zero */ + JSAMPLE dcval = range_limit[(int) DESCALE((IJG_INT32) wsptr[0], PASS1_BITS+3) + & RANGE_MASK]; + + outptr[0] = dcval; + outptr[1] = dcval; + outptr[2] = dcval; + outptr[3] = dcval; + outptr[4] = dcval; + outptr[5] = dcval; + outptr[6] = dcval; + outptr[7] = dcval; + + wsptr += DCTSIZE; /* advance pointer to next row */ + continue; + } +#endif + + /* Even part: reverse the even part of the forward DCT. */ + /* The rotator is sqrt(2)*c(-6). */ + + z2 = (IJG_INT32) wsptr[2]; + z3 = (IJG_INT32) wsptr[6]; + + z1 = MULTIPLY(z2 + z3, FIX_0_541196100); + tmp2 = z1 + MULTIPLY(z3, - FIX_1_847759065); + tmp3 = z1 + MULTIPLY(z2, FIX_0_765366865); + + tmp0 = ((IJG_INT32) wsptr[0] + (IJG_INT32) wsptr[4]) << CONST_BITS; + tmp1 = ((IJG_INT32) wsptr[0] - (IJG_INT32) wsptr[4]) << CONST_BITS; + + tmp10 = tmp0 + tmp3; + tmp13 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp1 - tmp2; + + /* Odd part per figure 8; the matrix is unitary and hence its + * transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively. + */ + + tmp0 = (IJG_INT32) wsptr[7]; + tmp1 = (IJG_INT32) wsptr[5]; + tmp2 = (IJG_INT32) wsptr[3]; + tmp3 = (IJG_INT32) wsptr[1]; + + z1 = tmp0 + tmp3; + z2 = tmp1 + tmp2; + z3 = tmp0 + tmp2; + z4 = tmp1 + tmp3; + z5 = MULTIPLY(z3 + z4, FIX_1_175875602); /* sqrt(2) * c3 */ + + tmp0 = MULTIPLY(tmp0, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */ + tmp1 = MULTIPLY(tmp1, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */ + tmp2 = MULTIPLY(tmp2, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */ + tmp3 = MULTIPLY(tmp3, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */ + z1 = MULTIPLY(z1, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */ + z2 = MULTIPLY(z2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */ + z3 = MULTIPLY(z3, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */ + z4 = MULTIPLY(z4, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */ + + z3 += z5; + z4 += z5; + + tmp0 += z1 + z3; + tmp1 += z2 + z4; + tmp2 += z2 + z3; + tmp3 += z1 + z4; + + /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */ + + outptr[0] = range_limit[(int) DESCALE(tmp10 + tmp3, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[7] = range_limit[(int) DESCALE(tmp10 - tmp3, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[1] = range_limit[(int) DESCALE(tmp11 + tmp2, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[6] = range_limit[(int) DESCALE(tmp11 - tmp2, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[2] = range_limit[(int) DESCALE(tmp12 + tmp1, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[5] = range_limit[(int) DESCALE(tmp12 - tmp1, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[3] = range_limit[(int) DESCALE(tmp13 + tmp0, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[4] = range_limit[(int) DESCALE(tmp13 - tmp0, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + + wsptr += DCTSIZE; /* advance pointer to next row */ + } +} + +#endif /* DCT_ISLOW_SUPPORTED */ diff --git a/dcmjpeg/libijg16/jidctred.c b/dcmjpeg/libijg16/jidctred.c new file mode 100644 index 00000000..83bf83f3 --- /dev/null +++ b/dcmjpeg/libijg16/jidctred.c @@ -0,0 +1,398 @@ +/* + * jidctred.c + * + * Copyright (C) 1994-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains inverse-DCT routines that produce reduced-size output: + * either 4x4, 2x2, or 1x1 pixels from an 8x8 DCT block. + * + * The implementation is based on the Loeffler, Ligtenberg and Moschytz (LL&M) + * algorithm used in jidctint.c. We simply replace each 8-to-8 1-D IDCT step + * with an 8-to-4 step that produces the four averages of two adjacent outputs + * (or an 8-to-2 step producing two averages of four outputs, for 2x2 output). + * These steps were derived by computing the corresponding values at the end + * of the normal LL&M code, then simplifying as much as possible. + * + * 1x1 is trivial: just take the DC coefficient divided by 8. + * + * See jidctint.c for additional comments. + */ + +#define JPEG_INTERNALS +#include "jinclude16.h" +#include "jpeglib16.h" +#include "jdct16.h" /* Private declarations for DCT subsystem */ + +#ifdef IDCT_SCALING_SUPPORTED + + +/* + * This module is specialized to the case DCTSIZE = 8. + */ + +#if DCTSIZE != 8 + Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */ +#endif + + +/* Scaling is the same as in jidctint.c. */ + +#if BITS_IN_JSAMPLE == 8 +#define CONST_BITS 13 +#define PASS1_BITS 2 +#else +#define CONST_BITS 13 +#define PASS1_BITS 1 /* lose a little precision to avoid overflow */ +#endif + +/* Some C compilers fail to reduce "FIX(constant)" at compile time, thus + * causing a lot of useless floating-point operations at run time. + * To get around this we use the following pre-calculated constants. + * If you change CONST_BITS you may want to add appropriate values. + * (With a reasonable C compiler, you can just rely on the FIX() macro...) + */ + +#if CONST_BITS == 13 +#define FIX_0_211164243 ((IJG_INT32) 1730) /* FIX(0.211164243) */ +#define FIX_0_509795579 ((IJG_INT32) 4176) /* FIX(0.509795579) */ +#define FIX_0_601344887 ((IJG_INT32) 4926) /* FIX(0.601344887) */ +#define FIX_0_720959822 ((IJG_INT32) 5906) /* FIX(0.720959822) */ +#define FIX_0_765366865 ((IJG_INT32) 6270) /* FIX(0.765366865) */ +#define FIX_0_850430095 ((IJG_INT32) 6967) /* FIX(0.850430095) */ +#define FIX_0_899976223 ((IJG_INT32) 7373) /* FIX(0.899976223) */ +#define FIX_1_061594337 ((IJG_INT32) 8697) /* FIX(1.061594337) */ +#define FIX_1_272758580 ((IJG_INT32) 10426) /* FIX(1.272758580) */ +#define FIX_1_451774981 ((IJG_INT32) 11893) /* FIX(1.451774981) */ +#define FIX_1_847759065 ((IJG_INT32) 15137) /* FIX(1.847759065) */ +#define FIX_2_172734803 ((IJG_INT32) 17799) /* FIX(2.172734803) */ +#define FIX_2_562915447 ((IJG_INT32) 20995) /* FIX(2.562915447) */ +#define FIX_3_624509785 ((IJG_INT32) 29692) /* FIX(3.624509785) */ +#else +#define FIX_0_211164243 FIX(0.211164243) +#define FIX_0_509795579 FIX(0.509795579) +#define FIX_0_601344887 FIX(0.601344887) +#define FIX_0_720959822 FIX(0.720959822) +#define FIX_0_765366865 FIX(0.765366865) +#define FIX_0_850430095 FIX(0.850430095) +#define FIX_0_899976223 FIX(0.899976223) +#define FIX_1_061594337 FIX(1.061594337) +#define FIX_1_272758580 FIX(1.272758580) +#define FIX_1_451774981 FIX(1.451774981) +#define FIX_1_847759065 FIX(1.847759065) +#define FIX_2_172734803 FIX(2.172734803) +#define FIX_2_562915447 FIX(2.562915447) +#define FIX_3_624509785 FIX(3.624509785) +#endif + + +/* Multiply an IJG_INT32 variable by an IJG_INT32 constant to yield an IJG_INT32 result. + * For 8-bit samples with the recommended scaling, all the variable + * and constant values involved are no more than 16 bits wide, so a + * 16x16->32 bit multiply can be used instead of a full 32x32 multiply. + * For 12-bit samples, a full 32-bit multiplication will be needed. + */ + +#if BITS_IN_JSAMPLE == 8 +#define MULTIPLY(var,const) MULTIPLY16C16(var,const) +#else +#define MULTIPLY(var,const) ((var) * (const)) +#endif + + +/* Dequantize a coefficient by multiplying it by the multiplier-table + * entry; produce an int result. In this module, both inputs and result + * are 16 bits or less, so either int or short multiply will work. + */ + +#define DEQUANTIZE(coef,quantval) (((ISLOW_MULT_TYPE) (coef)) * (quantval)) + + +/* + * Perform dequantization and inverse DCT on one block of coefficients, + * producing a reduced-size 4x4 output block. + */ + +GLOBAL(void) +jpeg_idct_4x4 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + IJG_INT32 tmp0, tmp2, tmp10, tmp12; + IJG_INT32 z1, z2, z3, z4; + JCOEFPTR inptr; + ISLOW_MULT_TYPE * quantptr; + int * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + int workspace[DCTSIZE*4]; /* buffers data between passes */ + SHIFT_TEMPS + + /* Pass 1: process columns from input, store into work array. */ + + inptr = coef_block; + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = DCTSIZE; ctr > 0; inptr++, quantptr++, wsptr++, ctr--) { + /* Don't bother to process column 4, because second pass won't use it */ + if (ctr == DCTSIZE-4) + continue; + if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*2] == 0 && + inptr[DCTSIZE*3] == 0 && inptr[DCTSIZE*5] == 0 && + inptr[DCTSIZE*6] == 0 && inptr[DCTSIZE*7] == 0) { + /* AC terms all zero; we need not examine term 4 for 4x4 output */ + int dcval = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]) << PASS1_BITS; + + wsptr[DCTSIZE*0] = dcval; + wsptr[DCTSIZE*1] = dcval; + wsptr[DCTSIZE*2] = dcval; + wsptr[DCTSIZE*3] = dcval; + + continue; + } + + /* Even part */ + + tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + tmp0 <<= (CONST_BITS+1); + + z2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + z3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); + + tmp2 = MULTIPLY(z2, FIX_1_847759065) + MULTIPLY(z3, - FIX_0_765366865); + + tmp10 = tmp0 + tmp2; + tmp12 = tmp0 - tmp2; + + /* Odd part */ + + z1 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); + z2 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); + z3 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + z4 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + + tmp0 = MULTIPLY(z1, - FIX_0_211164243) /* sqrt(2) * (c3-c1) */ + + MULTIPLY(z2, FIX_1_451774981) /* sqrt(2) * (c3+c7) */ + + MULTIPLY(z3, - FIX_2_172734803) /* sqrt(2) * (-c1-c5) */ + + MULTIPLY(z4, FIX_1_061594337); /* sqrt(2) * (c5+c7) */ + + tmp2 = MULTIPLY(z1, - FIX_0_509795579) /* sqrt(2) * (c7-c5) */ + + MULTIPLY(z2, - FIX_0_601344887) /* sqrt(2) * (c5-c1) */ + + MULTIPLY(z3, FIX_0_899976223) /* sqrt(2) * (c3-c7) */ + + MULTIPLY(z4, FIX_2_562915447); /* sqrt(2) * (c1+c3) */ + + /* Final output stage */ + + wsptr[DCTSIZE*0] = (int) DESCALE(tmp10 + tmp2, CONST_BITS-PASS1_BITS+1); + wsptr[DCTSIZE*3] = (int) DESCALE(tmp10 - tmp2, CONST_BITS-PASS1_BITS+1); + wsptr[DCTSIZE*1] = (int) DESCALE(tmp12 + tmp0, CONST_BITS-PASS1_BITS+1); + wsptr[DCTSIZE*2] = (int) DESCALE(tmp12 - tmp0, CONST_BITS-PASS1_BITS+1); + } + + /* Pass 2: process 4 rows from work array, store into output array. */ + + wsptr = workspace; + for (ctr = 0; ctr < 4; ctr++) { + outptr = output_buf[ctr] + output_col; + /* It's not clear whether a zero row test is worthwhile here ... */ + +#ifndef NO_ZERO_ROW_TEST + if (wsptr[1] == 0 && wsptr[2] == 0 && wsptr[3] == 0 && + wsptr[5] == 0 && wsptr[6] == 0 && wsptr[7] == 0) { + /* AC terms all zero */ + JSAMPLE dcval = range_limit[(int) DESCALE((IJG_INT32) wsptr[0], PASS1_BITS+3) + & RANGE_MASK]; + + outptr[0] = dcval; + outptr[1] = dcval; + outptr[2] = dcval; + outptr[3] = dcval; + + wsptr += DCTSIZE; /* advance pointer to next row */ + continue; + } +#endif + + /* Even part */ + + tmp0 = ((IJG_INT32) wsptr[0]) << (CONST_BITS+1); + + tmp2 = MULTIPLY((IJG_INT32) wsptr[2], FIX_1_847759065) + + MULTIPLY((IJG_INT32) wsptr[6], - FIX_0_765366865); + + tmp10 = tmp0 + tmp2; + tmp12 = tmp0 - tmp2; + + /* Odd part */ + + z1 = (IJG_INT32) wsptr[7]; + z2 = (IJG_INT32) wsptr[5]; + z3 = (IJG_INT32) wsptr[3]; + z4 = (IJG_INT32) wsptr[1]; + + tmp0 = MULTIPLY(z1, - FIX_0_211164243) /* sqrt(2) * (c3-c1) */ + + MULTIPLY(z2, FIX_1_451774981) /* sqrt(2) * (c3+c7) */ + + MULTIPLY(z3, - FIX_2_172734803) /* sqrt(2) * (-c1-c5) */ + + MULTIPLY(z4, FIX_1_061594337); /* sqrt(2) * (c5+c7) */ + + tmp2 = MULTIPLY(z1, - FIX_0_509795579) /* sqrt(2) * (c7-c5) */ + + MULTIPLY(z2, - FIX_0_601344887) /* sqrt(2) * (c5-c1) */ + + MULTIPLY(z3, FIX_0_899976223) /* sqrt(2) * (c3-c7) */ + + MULTIPLY(z4, FIX_2_562915447); /* sqrt(2) * (c1+c3) */ + + /* Final output stage */ + + outptr[0] = range_limit[(int) DESCALE(tmp10 + tmp2, + CONST_BITS+PASS1_BITS+3+1) + & RANGE_MASK]; + outptr[3] = range_limit[(int) DESCALE(tmp10 - tmp2, + CONST_BITS+PASS1_BITS+3+1) + & RANGE_MASK]; + outptr[1] = range_limit[(int) DESCALE(tmp12 + tmp0, + CONST_BITS+PASS1_BITS+3+1) + & RANGE_MASK]; + outptr[2] = range_limit[(int) DESCALE(tmp12 - tmp0, + CONST_BITS+PASS1_BITS+3+1) + & RANGE_MASK]; + + wsptr += DCTSIZE; /* advance pointer to next row */ + } +} + + +/* + * Perform dequantization and inverse DCT on one block of coefficients, + * producing a reduced-size 2x2 output block. + */ + +GLOBAL(void) +jpeg_idct_2x2 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + IJG_INT32 tmp0, tmp10, z1; + JCOEFPTR inptr; + ISLOW_MULT_TYPE * quantptr; + int * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + int workspace[DCTSIZE*2]; /* buffers data between passes */ + SHIFT_TEMPS + + /* Pass 1: process columns from input, store into work array. */ + + inptr = coef_block; + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = DCTSIZE; ctr > 0; inptr++, quantptr++, wsptr++, ctr--) { + /* Don't bother to process columns 2,4,6 */ + if (ctr == DCTSIZE-2 || ctr == DCTSIZE-4 || ctr == DCTSIZE-6) + continue; + if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*3] == 0 && + inptr[DCTSIZE*5] == 0 && inptr[DCTSIZE*7] == 0) { + /* AC terms all zero; we need not examine terms 2,4,6 for 2x2 output */ + int dcval = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]) << PASS1_BITS; + + wsptr[DCTSIZE*0] = dcval; + wsptr[DCTSIZE*1] = dcval; + + continue; + } + + /* Even part */ + + z1 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + tmp10 = z1 << (CONST_BITS+2); + + /* Odd part */ + + z1 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); + tmp0 = MULTIPLY(z1, - FIX_0_720959822); /* sqrt(2) * (c7-c5+c3-c1) */ + z1 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); + tmp0 += MULTIPLY(z1, FIX_0_850430095); /* sqrt(2) * (-c1+c3+c5+c7) */ + z1 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + tmp0 += MULTIPLY(z1, - FIX_1_272758580); /* sqrt(2) * (-c1+c3-c5-c7) */ + z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + tmp0 += MULTIPLY(z1, FIX_3_624509785); /* sqrt(2) * (c1+c3+c5+c7) */ + + /* Final output stage */ + + wsptr[DCTSIZE*0] = (int) DESCALE(tmp10 + tmp0, CONST_BITS-PASS1_BITS+2); + wsptr[DCTSIZE*1] = (int) DESCALE(tmp10 - tmp0, CONST_BITS-PASS1_BITS+2); + } + + /* Pass 2: process 2 rows from work array, store into output array. */ + + wsptr = workspace; + for (ctr = 0; ctr < 2; ctr++) { + outptr = output_buf[ctr] + output_col; + /* It's not clear whether a zero row test is worthwhile here ... */ + +#ifndef NO_ZERO_ROW_TEST + if (wsptr[1] == 0 && wsptr[3] == 0 && wsptr[5] == 0 && wsptr[7] == 0) { + /* AC terms all zero */ + JSAMPLE dcval = range_limit[(int) DESCALE((IJG_INT32) wsptr[0], PASS1_BITS+3) + & RANGE_MASK]; + + outptr[0] = dcval; + outptr[1] = dcval; + + wsptr += DCTSIZE; /* advance pointer to next row */ + continue; + } +#endif + + /* Even part */ + + tmp10 = ((IJG_INT32) wsptr[0]) << (CONST_BITS+2); + + /* Odd part */ + + tmp0 = MULTIPLY((IJG_INT32) wsptr[7], - FIX_0_720959822) /* sqrt(2) * (c7-c5+c3-c1) */ + + MULTIPLY((IJG_INT32) wsptr[5], FIX_0_850430095) /* sqrt(2) * (-c1+c3+c5+c7) */ + + MULTIPLY((IJG_INT32) wsptr[3], - FIX_1_272758580) /* sqrt(2) * (-c1+c3-c5-c7) */ + + MULTIPLY((IJG_INT32) wsptr[1], FIX_3_624509785); /* sqrt(2) * (c1+c3+c5+c7) */ + + /* Final output stage */ + + outptr[0] = range_limit[(int) DESCALE(tmp10 + tmp0, + CONST_BITS+PASS1_BITS+3+2) + & RANGE_MASK]; + outptr[1] = range_limit[(int) DESCALE(tmp10 - tmp0, + CONST_BITS+PASS1_BITS+3+2) + & RANGE_MASK]; + + wsptr += DCTSIZE; /* advance pointer to next row */ + } +} + + +/* + * Perform dequantization and inverse DCT on one block of coefficients, + * producing a reduced-size 1x1 output block. + */ + +GLOBAL(void) +jpeg_idct_1x1 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + int dcval; + ISLOW_MULT_TYPE * quantptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + SHIFT_TEMPS + + /* We hardly need an inverse DCT routine for this: just take the + * average pixel value, which is one-eighth of the DC coefficient. + */ + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + dcval = DEQUANTIZE(coef_block[0], quantptr[0]); + dcval = (int) DESCALE((IJG_INT32) dcval, 3); + + output_buf[0][output_col] = range_limit[dcval & RANGE_MASK]; +} + +#endif /* IDCT_SCALING_SUPPORTED */ diff --git a/dcmjpeg/libijg16/jinclude16.h b/dcmjpeg/libijg16/jinclude16.h new file mode 100644 index 00000000..d15f5512 --- /dev/null +++ b/dcmjpeg/libijg16/jinclude16.h @@ -0,0 +1,91 @@ +/* + * jinclude.h + * + * Copyright (C) 1991-1994, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file exists to provide a single place to fix any problems with + * including the wrong system include files. (Common problems are taken + * care of by the standard jconfig symbols, but on really weird systems + * you may have to edit this file.) + * + * NOTE: this file is NOT intended to be included by applications using the + * JPEG library. Most applications need only include jpeglib.h. + */ + + +/* Include auto-config file to find out which system include files we need. */ + +#include "jconfig16.h" /* auto configuration options */ +#define JCONFIG_INCLUDED /* so that jpeglib.h doesn't do it again */ + +/* + * We need the NULL macro and size_t typedef. + * On an ANSI-conforming system it is sufficient to include . + * Otherwise, we get them from or ; we may have to + * pull in as well. + * Note that the core JPEG library does not require ; + * only the default error handler and data source/destination modules do. + * But we must pull it in because of the references to FILE in jpeglib.h. + * You can remove those references if you want to compile without . + */ + +#ifdef HAVE_STDDEF_H +#include +#endif + +#ifdef HAVE_STDLIB_H +#include +#endif + +#ifdef NEED_SYS_TYPES_H +#include +#endif + +#include + +/* + * We need memory copying and zeroing functions, plus strncpy(). + * ANSI and System V implementations declare these in . + * BSD doesn't have the mem() functions, but it does have bcopy()/bzero(). + * Some systems may declare memset and memcpy in . + * + * NOTE: we assume the size parameters to these functions are of type size_t. + * Change the casts in these macros if not! + */ + +#ifdef NEED_BSD_STRINGS + +#include +#define MEMZERO(target,size) bzero((void *)(target), (size_t)(size)) +#define MEMCOPY(dest,src,size) bcopy((const void *)(src), (void *)(dest), (size_t)(size)) + +#else /* not BSD, assume ANSI/SysV string lib */ + +#include +#define MEMZERO(target,size) memset((void *)(target), 0, (size_t)(size)) +#define MEMCOPY(dest,src,size) memcpy((void *)(dest), (const void *)(src), (size_t)(size)) + +#endif + +/* + * In ANSI C, and indeed any rational implementation, size_t is also the + * type returned by sizeof(). However, it seems there are some irrational + * implementations out there, in which sizeof() returns an int even though + * size_t is defined as long or unsigned long. To ensure consistent results + * we always use this SIZEOF() macro in place of using sizeof() directly. + */ + +#define SIZEOF(object) ((size_t) sizeof(object)) + +/* + * The modules that use fread() and fwrite() always invoke them through + * these macros. On some systems you may need to twiddle the argument casts. + * CAUTION: argument order is different from underlying functions! + */ + +#define JFREAD(file,buf,sizeofbuf) \ + ((size_t) fread((void *) (buf), (size_t) 1, (size_t) (sizeofbuf), (file))) +#define JFWRITE(file,buf,sizeofbuf) \ + ((size_t) fwrite((const void *) (buf), (size_t) 1, (size_t) (sizeofbuf), (file))) diff --git a/dcmjpeg/libijg16/jlossls16.h b/dcmjpeg/libijg16/jlossls16.h new file mode 100644 index 00000000..6c7ea9ac --- /dev/null +++ b/dcmjpeg/libijg16/jlossls16.h @@ -0,0 +1,157 @@ +/* + * jlossls.h + * + * Copyright (C) 1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This include file contains common declarations for the lossless JPEG + * codec modules. + */ + +#ifndef JLOSSLS_H +#define JLOSSLS_H + + +/* + * Table H.1: Predictors for lossless coding. + */ + +#define PREDICTOR1 Ra +#define PREDICTOR2 Rb +#define PREDICTOR3 Rc +#define PREDICTOR4 (int) ((IJG_INT32) Ra + (IJG_INT32) Rb - (IJG_INT32) Rc) +#define PREDICTOR5 (int) ((IJG_INT32) Ra + RIGHT_SHIFT((IJG_INT32) Rb - (IJG_INT32) Rc, 1)) +#define PREDICTOR6 (int) ((IJG_INT32) Rb + RIGHT_SHIFT((IJG_INT32) Ra - (IJG_INT32) Rc, 1)) +#define PREDICTOR7 (int) RIGHT_SHIFT((IJG_INT32) Ra + (IJG_INT32) Rb, 1) + +/* This is an incorrect predictor that causes an overflow for images with 16 bits/pixel. + * There is a known implementation of JPEG lossless that creates such incorrect images, + * and we need this predictor to be able to correctly decode such incorrect images. + */ +#define PREDICTOR6A (int) ((INT16) Rb + RIGHT_SHIFT((INT16) Ra - (INT16) Rc, 1)) + + +typedef JMETHOD(void, predict_difference_method_ptr, + (j_compress_ptr cinfo, int ci, + JSAMPROW input_buf, JSAMPROW prev_row, + JDIFFROW diff_buf, JDIMENSION width)); + +typedef JMETHOD(void, scaler_method_ptr, + (j_compress_ptr cinfo, int ci, + JSAMPROW input_buf, JSAMPROW output_buf, + JDIMENSION width)); + +/* Lossless-specific compression codec (compressor proper) */ +typedef struct { + struct jpeg_c_codec pub; /* public fields */ + + + /* Difference buffer control */ + JMETHOD(void, diff_start_pass, (j_compress_ptr cinfo, + J_BUF_MODE pass_mode)); + + /* Pointer to data which is private to diff controller */ + void *diff_private; + + + /* Entropy encoding */ + JMETHOD(JDIMENSION, entropy_encode_mcus, (j_compress_ptr cinfo, + JDIFFIMAGE diff_buf, + JDIMENSION MCU_row_num, + JDIMENSION MCU_col_num, + JDIMENSION nMCU)); + + /* Pointer to data which is private to entropy module */ + void *entropy_private; + + + /* Prediction, differencing */ + JMETHOD(void, predict_start_pass, (j_compress_ptr cinfo)); + + /* It is useful to allow each component to have a separate diff method. */ + predict_difference_method_ptr predict_difference[MAX_COMPONENTS]; + + /* Pointer to data which is private to predictor module */ + void *pred_private; + + /* Sample scaling */ + JMETHOD(void, scaler_start_pass, (j_compress_ptr cinfo)); + JMETHOD(void, scaler_scale, (j_compress_ptr cinfo, + JSAMPROW input_buf, JSAMPROW output_buf, + JDIMENSION width)); + + /* Pointer to data which is private to scaler module */ + void *scaler_private; + +} jpeg_lossless_c_codec; + +typedef jpeg_lossless_c_codec * j_lossless_c_ptr; + + +typedef JMETHOD(void, predict_undifference_method_ptr, + (j_decompress_ptr cinfo, int comp_index, + JDIFFROW diff_buf, JDIFFROW prev_row, + JDIFFROW undiff_buf, JDIMENSION width)); + +/* Lossless-specific decompression codec (decompressor proper) */ +typedef struct { + struct jpeg_d_codec pub; /* public fields */ + + + /* Difference buffer control */ + JMETHOD(void, diff_start_input_pass, (j_decompress_ptr cinfo)); + + /* Pointer to data which is private to diff controller */ + void *diff_private; + + + /* Entropy decoding */ + JMETHOD(void, entropy_start_pass, (j_decompress_ptr cinfo)); + JMETHOD(boolean, entropy_process_restart, (j_decompress_ptr cinfo)); + JMETHOD(JDIMENSION, entropy_decode_mcus, (j_decompress_ptr cinfo, + JDIFFIMAGE diff_buf, + JDIMENSION MCU_row_num, + JDIMENSION MCU_col_num, + JDIMENSION nMCU)); + + /* Pointer to data which is private to entropy module */ + void *entropy_private; + + + /* Prediction, undifferencing */ + JMETHOD(void, predict_start_pass, (j_decompress_ptr cinfo)); + JMETHOD(void, predict_process_restart, (j_decompress_ptr cinfo)); + + /* It is useful to allow each component to have a separate undiff method. */ + predict_undifference_method_ptr predict_undifference[MAX_COMPONENTS]; + + /* Pointer to data which is private to predictor module */ + void *pred_private; + + /* Sample scaling */ + JMETHOD(void, scaler_start_pass, (j_decompress_ptr cinfo)); + JMETHOD(void, scaler_scale, (j_decompress_ptr cinfo, + JDIFFROW diff_buf, JSAMPROW output_buf, + JDIMENSION width)); + + /* Pointer to data which is private to scaler module */ + void *scaler_private; + +} jpeg_lossless_d_codec; + +typedef jpeg_lossless_d_codec * j_lossless_d_ptr; + + +/* Compression module initialization routines */ +EXTERN(void) jinit_lossless_c_codec JPP((j_compress_ptr cinfo)); +EXTERN(void) jinit_lhuff_encoder JPP((j_compress_ptr cinfo)); +EXTERN(void) jinit_differencer JPP((j_compress_ptr cinfo)); +EXTERN(void) jinit_c_scaler JPP((j_compress_ptr cinfo)); +/* Decompression module initialization routines */ +EXTERN(void) jinit_lossless_d_codec JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_lhuff_decoder JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_undifferencer JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_d_scaler JPP((j_decompress_ptr cinfo)); + +#endif /* JLOSSLS_H */ diff --git a/dcmjpeg/libijg16/jlossy16.h b/dcmjpeg/libijg16/jlossy16.h new file mode 100644 index 00000000..ad4d62b3 --- /dev/null +++ b/dcmjpeg/libijg16/jlossy16.h @@ -0,0 +1,120 @@ +/* + * jlossy.h + * + * Copyright (C) 1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This include file contains common declarations for the lossy (DCT-based) + * JPEG codec modules. + */ + +#ifndef JLOSSY_H +#define JLOSSY_H + + +/* Lossy-specific compression codec (compressor proper) */ +typedef struct { + struct jpeg_c_codec pub; /* public fields */ + + + /* Coefficient buffer control */ + JMETHOD(void, coef_start_pass, (j_compress_ptr cinfo, J_BUF_MODE pass_mode)); + /* JMETHOD(boolean, coef_compress_data, (j_compress_ptr cinfo, + JSAMPIMAGE input_buf));*/ + + /* Pointer to data which is private to coef module */ + void *coef_private; + + + /* Forward DCT (also controls coefficient quantization) */ + JMETHOD(void, fdct_start_pass, (j_compress_ptr cinfo)); + /* perhaps this should be an array??? */ + JMETHOD(void, fdct_forward_DCT, (j_compress_ptr cinfo, + jpeg_component_info * compptr, + JSAMPARRAY sample_data, JBLOCKROW coef_blocks, + JDIMENSION start_row, JDIMENSION start_col, + JDIMENSION num_blocks)); + + /* Pointer to data which is private to fdct module */ + void *fdct_private; + + + /* Entropy encoding */ + JMETHOD(boolean, entropy_encode_mcu, (j_compress_ptr cinfo, + JBLOCKROW *MCU_data)); + + /* Pointer to data which is private to entropy module */ + void *entropy_private; + +} jpeg_lossy_c_codec; + +typedef jpeg_lossy_c_codec * j_lossy_c_ptr; + + + +typedef JMETHOD(void, inverse_DCT_method_ptr, + (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col)); + +/* Lossy-specific decompression codec (decompressor proper) */ +typedef struct { + struct jpeg_d_codec pub; /* public fields */ + + + /* Coefficient buffer control */ + JMETHOD(void, coef_start_input_pass, (j_decompress_ptr cinfo)); + JMETHOD(void, coef_start_output_pass, (j_decompress_ptr cinfo)); + + /* Pointer to array of coefficient virtual arrays, or NULL if none */ + jvirt_barray_ptr *coef_arrays; + + /* Pointer to data which is private to coef module */ + void *coef_private; + + + /* Entropy decoding */ + JMETHOD(void, entropy_start_pass, (j_decompress_ptr cinfo)); + JMETHOD(boolean, entropy_decode_mcu, (j_decompress_ptr cinfo, + JBLOCKROW *MCU_data)); + + /* This is here to share code between baseline and progressive decoders; */ + /* other modules probably should not use it */ + boolean entropy_insufficient_data; /* set TRUE after emitting warning */ + + /* Pointer to data which is private to entropy module */ + void *entropy_private; + + + /* Inverse DCT (also performs dequantization) */ + JMETHOD(void, idct_start_pass, (j_decompress_ptr cinfo)); + + /* It is useful to allow each component to have a separate IDCT method. */ + inverse_DCT_method_ptr inverse_DCT[MAX_COMPONENTS]; + + /* Pointer to data which is private to idct module */ + void *idct_private; + +} jpeg_lossy_d_codec; + +typedef jpeg_lossy_d_codec * j_lossy_d_ptr; + + +/* Compression module initialization routines */ +EXTERN(void) jinit_lossy_c_codec JPP((j_compress_ptr cinfo)); +EXTERN(void) jinit_c_coef_controller JPP((j_compress_ptr cinfo, + boolean need_full_buffer)); +EXTERN(void) jinit_forward_dct JPP((j_compress_ptr cinfo)); +EXTERN(void) jinit_shuff_encoder JPP((j_compress_ptr cinfo)); +EXTERN(void) jinit_phuff_encoder JPP((j_compress_ptr cinfo)); + +/* Decompression module initialization routines */ +EXTERN(void) jinit_lossy_d_codec JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_d_coef_controller JPP((j_decompress_ptr cinfo, + boolean need_full_buffer)); +EXTERN(void) jinit_shuff_decoder JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_phuff_decoder JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_inverse_dct JPP((j_decompress_ptr cinfo)); + +#endif /* JLOSSY_H */ diff --git a/dcmjpeg/libijg16/jmemmgr.c b/dcmjpeg/libijg16/jmemmgr.c new file mode 100644 index 00000000..9267fc1f --- /dev/null +++ b/dcmjpeg/libijg16/jmemmgr.c @@ -0,0 +1,1174 @@ +/* + * jmemmgr.c + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains the JPEG system-independent memory management + * routines. This code is usable across a wide variety of machines; most + * of the system dependencies have been isolated in a separate file. + * The major functions provided here are: + * * pool-based allocation and freeing of memory; + * * policy decisions about how to divide available memory among the + * virtual arrays; + * * control logic for swapping virtual arrays between main memory and + * backing storage. + * The separate system-dependent file provides the actual backing-storage + * access code, and it contains the policy decision about how much total + * main memory to use. + * This file is system-dependent in the sense that some of its functions + * are unnecessary in some systems. For example, if there is enough virtual + * memory so that backing storage will never be used, much of the virtual + * array control logic could be removed. (Of course, if you have that much + * memory then you shouldn't care about a little bit of unused code...) + */ + +#define JPEG_INTERNALS +#define AM_MEMORY_MANAGER /* we define jvirt_Xarray_control structs */ +#include "jinclude16.h" +#include "jpeglib16.h" +#include "jmemsys16.h" /* import the system-dependent declarations */ + +#ifndef NO_GETENV +#ifndef HAVE_STDLIB_H /* should declare getenv() */ +extern char * getenv JPP((const char * name)); +#endif +#endif + + +/* + * Some important notes: + * The allocation routines provided here must never return NULL. + * They should exit to error_exit if unsuccessful. + * + * It's not a good idea to try to merge the sarray, barray and darray + * routines, even though they are textually almost the same, because + * samples are usually stored as bytes while coefficients and differenced + * are shorts or ints. Thus, in machines where byte pointers have a + * different representation from word pointers, the resulting machine + * code could not be the same. + */ + + +/* + * Many machines require storage alignment: longs must start on 4-byte + * boundaries, doubles on 8-byte boundaries, etc. On such machines, malloc() + * always returns pointers that are multiples of the worst-case alignment + * requirement, and we had better do so too. + * There isn't any really portable way to determine the worst-case alignment + * requirement. This module assumes that the alignment requirement is + * multiples of sizeof(ALIGN_TYPE). + * By default, we define ALIGN_TYPE as double. This is necessary on some + * workstations (where doubles really do need 8-byte alignment) and will work + * fine on nearly everything. If your machine has lesser alignment needs, + * you can save a few bytes by making ALIGN_TYPE smaller. + * The only place I know of where this will NOT work is certain Macintosh + * 680x0 compilers that define double as a 10-byte IEEE extended float. + * Doing 10-byte alignment is counterproductive because longwords won't be + * aligned well. Put "#define ALIGN_TYPE long" in jconfig.h if you have + * such a compiler. + */ + +#ifndef ALIGN_TYPE /* so can override from jconfig.h */ +#define ALIGN_TYPE double +#endif + + +/* + * We allocate objects from "pools", where each pool is gotten with a single + * request to jpeg_get_small() or jpeg_get_large(). There is no per-object + * overhead within a pool, except for alignment padding. Each pool has a + * header with a link to the next pool of the same class. + * Small and large pool headers are identical except that the latter's + * link pointer must be FAR on 80x86 machines. + * Notice that the "real" header fields are union'ed with a dummy ALIGN_TYPE + * field. This forces the compiler to make SIZEOF(small_pool_hdr) a multiple + * of the alignment requirement of ALIGN_TYPE. + */ + +typedef union small_pool_struct * small_pool_ptr; + +typedef union small_pool_struct { + struct { + small_pool_ptr next; /* next in list of pools */ + size_t bytes_used; /* how many bytes already used within pool */ + size_t bytes_left; /* bytes still available in this pool */ + } hdr; + ALIGN_TYPE dummy; /* included in union to ensure alignment */ +} small_pool_hdr; + +typedef union large_pool_struct FAR * large_pool_ptr; + +typedef union large_pool_struct { + struct { + large_pool_ptr next; /* next in list of pools */ + size_t bytes_used; /* how many bytes already used within pool */ + size_t bytes_left; /* bytes still available in this pool */ + } hdr; + ALIGN_TYPE dummy; /* included in union to ensure alignment */ +} large_pool_hdr; + + +/* + * Here is the full definition of a memory manager object. + */ + +typedef struct { + struct jpeg_memory_mgr pub; /* public fields */ + + /* Each pool identifier (lifetime class) names a linked list of pools. */ + small_pool_ptr small_list[JPOOL_NUMPOOLS]; + large_pool_ptr large_list[JPOOL_NUMPOOLS]; + + /* Since we only have one lifetime class of virtual arrays, only one + * linked list is necessary (for each datatype). Note that the virtual + * array control blocks being linked together are actually stored somewhere + * in the small-pool list. + */ + jvirt_sarray_ptr virt_sarray_list; + jvirt_barray_ptr virt_barray_list; + + /* This counts total space obtained from jpeg_get_small/large */ + long total_space_allocated; + + /* alloc_sarray and alloc_barray set this value for use by virtual + * array routines. + */ + JDIMENSION last_rowsperchunk; /* from most recent alloc_sarray/barray */ +} my_memory_mgr; + +typedef my_memory_mgr * my_mem_ptr; + + +/* + * The control blocks for virtual arrays. + * Note that these blocks are allocated in the "small" pool area. + * System-dependent info for the associated backing store (if any) is hidden + * inside the backing_store_info struct. + */ + +struct jvirt_sarray_control { + JSAMPARRAY mem_buffer; /* => the in-memory buffer */ + JDIMENSION rows_in_array; /* total virtual array height */ + JDIMENSION samplesperrow; /* width of array (and of memory buffer) */ + JDIMENSION maxaccess; /* max rows accessed by access_virt_sarray */ + JDIMENSION rows_in_mem; /* height of memory buffer */ + JDIMENSION rowsperchunk; /* allocation chunk size in mem_buffer */ + JDIMENSION cur_start_row; /* first logical row # in the buffer */ + JDIMENSION first_undef_row; /* row # of first uninitialized row */ + boolean pre_zero; /* pre-zero mode requested? */ + boolean dirty; /* do current buffer contents need written? */ + boolean b_s_open; /* is backing-store data valid? */ + jvirt_sarray_ptr next; /* link to next virtual sarray control block */ + backing_store_info b_s_info; /* System-dependent control info */ +}; + +struct jvirt_barray_control { + JBLOCKARRAY mem_buffer; /* => the in-memory buffer */ + JDIMENSION rows_in_array; /* total virtual array height */ + JDIMENSION blocksperrow; /* width of array (and of memory buffer) */ + JDIMENSION maxaccess; /* max rows accessed by access_virt_barray */ + JDIMENSION rows_in_mem; /* height of memory buffer */ + JDIMENSION rowsperchunk; /* allocation chunk size in mem_buffer */ + JDIMENSION cur_start_row; /* first logical row # in the buffer */ + JDIMENSION first_undef_row; /* row # of first uninitialized row */ + boolean pre_zero; /* pre-zero mode requested? */ + boolean dirty; /* do current buffer contents need written? */ + boolean b_s_open; /* is backing-store data valid? */ + jvirt_barray_ptr next; /* link to next virtual barray control block */ + backing_store_info b_s_info; /* System-dependent control info */ +}; + + +#ifdef MEM_STATS /* optional extra stuff for statistics */ + +LOCAL(void) +print_mem_stats (j_common_ptr cinfo, int pool_id) +{ + my_mem_ptr mem = (my_mem_ptr) cinfo->mem; + small_pool_ptr shdr_ptr; + large_pool_ptr lhdr_ptr; + + /* Since this is only a debugging stub, we can cheat a little by using + * fprintf directly rather than going through the trace message code. + * This is helpful because message parm array can't handle longs. + */ + fprintf(stderr, "Freeing pool %d, total space = %ld\n", + pool_id, mem->total_space_allocated); + + for (lhdr_ptr = mem->large_list[pool_id]; lhdr_ptr != NULL; + lhdr_ptr = lhdr_ptr->hdr.next) { + fprintf(stderr, " Large chunk used %ld\n", + (long) lhdr_ptr->hdr.bytes_used); + } + + for (shdr_ptr = mem->small_list[pool_id]; shdr_ptr != NULL; + shdr_ptr = shdr_ptr->hdr.next) { + fprintf(stderr, " Small chunk used %ld free %ld\n", + (long) shdr_ptr->hdr.bytes_used, + (long) shdr_ptr->hdr.bytes_left); + } +} + +#endif /* MEM_STATS */ + + +LOCAL(void) +out_of_memory (j_common_ptr cinfo, int which) +/* Report an out-of-memory error and stop execution */ +/* If we compiled MEM_STATS support, report alloc requests before dying */ +{ +#ifdef MEM_STATS + cinfo->err->trace_level = 2; /* force self_destruct to report stats */ +#endif + ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, which); +} + + +/* + * Allocation of "small" objects. + * + * For these, we use pooled storage. When a new pool must be created, + * we try to get enough space for the current request plus a "slop" factor, + * where the slop will be the amount of leftover space in the new pool. + * The speed vs. space tradeoff is largely determined by the slop values. + * A different slop value is provided for each pool class (lifetime), + * and we also distinguish the first pool of a class from later ones. + * NOTE: the values given work fairly well on both 16- and 32-bit-int + * machines, but may be too small if longs are 64 bits or more. + */ + +static const size_t first_pool_slop[JPOOL_NUMPOOLS] = +{ + 1600, /* first PERMANENT pool */ + 16000 /* first IMAGE pool */ +}; + +static const size_t extra_pool_slop[JPOOL_NUMPOOLS] = +{ + 0, /* additional PERMANENT pools */ + 5000 /* additional IMAGE pools */ +}; + +#define MIN_SLOP 50 /* greater than 0 to avoid futile looping */ + + +METHODDEF(void *) +alloc_small (j_common_ptr cinfo, int pool_id, size_t sizeofobject) +/* Allocate a "small" object */ +{ + my_mem_ptr mem = (my_mem_ptr) cinfo->mem; + small_pool_ptr hdr_ptr, prev_hdr_ptr; + char * data_ptr; + size_t odd_bytes, min_request, slop; + + /* Check for unsatisfiable request (do now to ensure no overflow below) */ + if (sizeofobject > (size_t) (MAX_ALLOC_CHUNK-SIZEOF(small_pool_hdr))) + out_of_memory(cinfo, 1); /* request exceeds malloc's ability */ + + /* Round up the requested size to a multiple of SIZEOF(ALIGN_TYPE) */ + odd_bytes = sizeofobject % SIZEOF(ALIGN_TYPE); + if (odd_bytes > 0) + sizeofobject += SIZEOF(ALIGN_TYPE) - odd_bytes; + + /* See if space is available in any existing pool */ + if (pool_id < 0 || pool_id >= JPOOL_NUMPOOLS) + ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */ + prev_hdr_ptr = NULL; + hdr_ptr = mem->small_list[pool_id]; + while (hdr_ptr != NULL) { + if (hdr_ptr->hdr.bytes_left >= sizeofobject) + break; /* found pool with enough space */ + prev_hdr_ptr = hdr_ptr; + hdr_ptr = hdr_ptr->hdr.next; + } + + /* Time to make a new pool? */ + if (hdr_ptr == NULL) { + /* min_request is what we need now, slop is what will be leftover */ + min_request = sizeofobject + SIZEOF(small_pool_hdr); + if (prev_hdr_ptr == NULL) /* first pool in class? */ + slop = first_pool_slop[pool_id]; + else + slop = extra_pool_slop[pool_id]; + /* Don't ask for more than MAX_ALLOC_CHUNK */ + if (slop > (size_t) (MAX_ALLOC_CHUNK-min_request)) + slop = (size_t) (MAX_ALLOC_CHUNK-min_request); + /* Try to get space, if fail reduce slop and try again */ + for (;;) { + hdr_ptr = (small_pool_ptr) jpeg_get_small(cinfo, min_request + slop); + if (hdr_ptr != NULL) + break; + slop /= 2; + if (slop < MIN_SLOP) /* give up when it gets real small */ + out_of_memory(cinfo, 2); /* jpeg_get_small failed */ + } + mem->total_space_allocated += (long)(min_request + slop); + /* Success, initialize the new pool header and add to end of list */ + hdr_ptr->hdr.next = NULL; + hdr_ptr->hdr.bytes_used = 0; + hdr_ptr->hdr.bytes_left = sizeofobject + slop; + if (prev_hdr_ptr == NULL) /* first pool in class? */ + mem->small_list[pool_id] = hdr_ptr; + else + prev_hdr_ptr->hdr.next = hdr_ptr; + } + + /* OK, allocate the object from the current pool */ + data_ptr = (char *) (hdr_ptr + 1); /* point to first data byte in pool */ + data_ptr += hdr_ptr->hdr.bytes_used; /* point to place for object */ + hdr_ptr->hdr.bytes_used += sizeofobject; + hdr_ptr->hdr.bytes_left -= sizeofobject; + + return (void *) data_ptr; +} + + +/* + * Allocation of "large" objects. + * + * The external semantics of these are the same as "small" objects, + * except that FAR pointers are used on 80x86. However the pool + * management heuristics are quite different. We assume that each + * request is large enough that it may as well be passed directly to + * jpeg_get_large; the pool management just links everything together + * so that we can free it all on demand. + * Note: the major use of "large" objects is in JSAMPARRAY and JBLOCKARRAY + * structures. The routines that create these structures (see below) + * deliberately bunch rows together to ensure a large request size. + */ + +METHODDEF(void FAR *) +alloc_large (j_common_ptr cinfo, int pool_id, size_t sizeofobject) +/* Allocate a "large" object */ +{ + my_mem_ptr mem = (my_mem_ptr) cinfo->mem; + large_pool_ptr hdr_ptr; + size_t odd_bytes; + + /* Check for unsatisfiable request (do now to ensure no overflow below) */ + if (sizeofobject > (size_t) (MAX_ALLOC_CHUNK-SIZEOF(large_pool_hdr))) + out_of_memory(cinfo, 3); /* request exceeds malloc's ability */ + + /* Round up the requested size to a multiple of SIZEOF(ALIGN_TYPE) */ + odd_bytes = sizeofobject % SIZEOF(ALIGN_TYPE); + if (odd_bytes > 0) + sizeofobject += SIZEOF(ALIGN_TYPE) - odd_bytes; + + /* Always make a new pool */ + if (pool_id < 0 || pool_id >= JPOOL_NUMPOOLS) + ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */ + + hdr_ptr = (large_pool_ptr) jpeg_get_large(cinfo, sizeofobject + + SIZEOF(large_pool_hdr)); + if (hdr_ptr == NULL) + out_of_memory(cinfo, 4); /* jpeg_get_large failed */ + mem->total_space_allocated += (long)(sizeofobject + SIZEOF(large_pool_hdr)); + + /* Success, initialize the new pool header and add to list */ + hdr_ptr->hdr.next = mem->large_list[pool_id]; + /* We maintain space counts in each pool header for statistical purposes, + * even though they are not needed for allocation. + */ + hdr_ptr->hdr.bytes_used = sizeofobject; + hdr_ptr->hdr.bytes_left = 0; + mem->large_list[pool_id] = hdr_ptr; + + return (void FAR *) (hdr_ptr + 1); /* point to first data byte in pool */ +} + + +/* + * Creation of 2-D sample arrays. + * The pointers are in near heap, the samples themselves in FAR heap. + * + * To minimize allocation overhead and to allow I/O of large contiguous + * blocks, we allocate the sample rows in groups of as many rows as possible + * without exceeding MAX_ALLOC_CHUNK total bytes per allocation request. + * NB: the virtual array control routines, later in this file, know about + * this chunking of rows. The rowsperchunk value is left in the mem manager + * object so that it can be saved away if this sarray is the workspace for + * a virtual array. + */ + +METHODDEF(JSAMPARRAY) +alloc_sarray (j_common_ptr cinfo, int pool_id, + JDIMENSION samplesperrow, JDIMENSION numrows) +/* Allocate a 2-D sample array */ +{ + my_mem_ptr mem = (my_mem_ptr) cinfo->mem; + JSAMPARRAY result; + JSAMPROW workspace; + JDIMENSION rowsperchunk, currow, i; + size_t ltemp; + + /* Calculate max # of rows allowed in one allocation chunk */ + ltemp = (MAX_ALLOC_CHUNK-SIZEOF(large_pool_hdr)) / + ((size_t) samplesperrow * SIZEOF(JSAMPLE)); + if (ltemp <= 0) + ERREXIT(cinfo, JERR_WIDTH_OVERFLOW); + if (ltemp < numrows) + rowsperchunk = (JDIMENSION) ltemp; + else + rowsperchunk = numrows; + mem->last_rowsperchunk = rowsperchunk; + + /* Get space for row pointers (small object) */ + result = (JSAMPARRAY) alloc_small(cinfo, pool_id, + (size_t) (numrows * SIZEOF(JSAMPROW))); + + /* Get the rows themselves (large objects) */ + currow = 0; + while (currow < numrows) { + rowsperchunk = MIN(rowsperchunk, numrows - currow); + workspace = (JSAMPROW) alloc_large(cinfo, pool_id, + (size_t) ((size_t) rowsperchunk * (size_t) samplesperrow + * SIZEOF(JSAMPLE))); + for (i = rowsperchunk; i > 0; i--) { + result[currow++] = workspace; + workspace += samplesperrow; + } + } + + return result; +} + + +/* + * Creation of 2-D coefficient-block arrays. + * This is essentially the same as the code for sample arrays, above. + */ + +METHODDEF(JBLOCKARRAY) +alloc_barray (j_common_ptr cinfo, int pool_id, + JDIMENSION blocksperrow, JDIMENSION numrows) +/* Allocate a 2-D coefficient-block array */ +{ + my_mem_ptr mem = (my_mem_ptr) cinfo->mem; + JBLOCKARRAY result; + JBLOCKROW workspace; + JDIMENSION rowsperchunk, currow, i; + size_t ltemp; + + /* Calculate max # of rows allowed in one allocation chunk */ + ltemp = (MAX_ALLOC_CHUNK-SIZEOF(large_pool_hdr)) / + ((size_t) blocksperrow * SIZEOF(JBLOCK)); + if (ltemp <= 0) + ERREXIT(cinfo, JERR_WIDTH_OVERFLOW); + if (ltemp < numrows) + rowsperchunk = (JDIMENSION) ltemp; + else + rowsperchunk = numrows; + mem->last_rowsperchunk = rowsperchunk; + + /* Get space for row pointers (small object) */ + result = (JBLOCKARRAY) alloc_small(cinfo, pool_id, + (size_t) (numrows * SIZEOF(JBLOCKROW))); + + /* Get the rows themselves (large objects) */ + currow = 0; + while (currow < numrows) { + rowsperchunk = MIN(rowsperchunk, numrows - currow); + workspace = (JBLOCKROW) alloc_large(cinfo, pool_id, + (size_t) ((size_t) rowsperchunk * (size_t) blocksperrow + * SIZEOF(JBLOCK))); + for (i = rowsperchunk; i > 0; i--) { + result[currow++] = workspace; + workspace += blocksperrow; + } + } + + return result; +} + + +#ifdef NEED_DARRAY + +/* + * Creation of 2-D difference arrays. + * This is essentially the same as the code for sample arrays, above. + */ + +METHODDEF(JDIFFARRAY) +alloc_darray (j_common_ptr cinfo, int pool_id, + JDIMENSION diffsperrow, JDIMENSION numrows) +/* Allocate a 2-D difference array */ +{ + my_mem_ptr mem = (my_mem_ptr) cinfo->mem; + JDIFFARRAY result; + JDIFFROW workspace; + JDIMENSION rowsperchunk, currow, i; + size_t ltemp; + + /* Calculate max # of rows allowed in one allocation chunk */ + ltemp = (MAX_ALLOC_CHUNK-SIZEOF(large_pool_hdr)) / + ((size_t) diffsperrow * SIZEOF(JDIFF)); + if (ltemp <= 0) + ERREXIT(cinfo, JERR_WIDTH_OVERFLOW); + if (ltemp < numrows) + rowsperchunk = (JDIMENSION) ltemp; + else + rowsperchunk = numrows; + mem->last_rowsperchunk = rowsperchunk; + + /* Get space for row pointers (small object) */ + result = (JDIFFARRAY) alloc_small(cinfo, pool_id, + (size_t) (numrows * SIZEOF(JDIFFROW))); + + /* Get the rows themselves (large objects) */ + currow = 0; + while (currow < numrows) { + rowsperchunk = MIN(rowsperchunk, numrows - currow); + workspace = (JDIFFROW) alloc_large(cinfo, pool_id, + (size_t) ((size_t) rowsperchunk * (size_t) diffsperrow + * SIZEOF(JDIFF))); + for (i = rowsperchunk; i > 0; i--) { + result[currow++] = workspace; + workspace += diffsperrow; + } + } + + return result; +} + +#endif + + +/* + * About virtual array management: + * + * The above "normal" array routines are only used to allocate strip buffers + * (as wide as the image, but just a few rows high). Full-image-sized buffers + * are handled as "virtual" arrays. The array is still accessed a strip at a + * time, but the memory manager must save the whole array for repeated + * accesses. The intended implementation is that there is a strip buffer in + * memory (as high as is possible given the desired memory limit), plus a + * backing file that holds the rest of the array. + * + * The request_virt_array routines are told the total size of the image and + * the maximum number of rows that will be accessed at once. The in-memory + * buffer must be at least as large as the maxaccess value. + * + * The request routines create control blocks but not the in-memory buffers. + * That is postponed until realize_virt_arrays is called. At that time the + * total amount of space needed is known (approximately, anyway), so free + * memory can be divided up fairly. + * + * The access_virt_array routines are responsible for making a specific strip + * area accessible (after reading or writing the backing file, if necessary). + * Note that the access routines are told whether the caller intends to modify + * the accessed strip; during a read-only pass this saves having to rewrite + * data to disk. The access routines are also responsible for pre-zeroing + * any newly accessed rows, if pre-zeroing was requested. + * + * In current usage, the access requests are usually for nonoverlapping + * strips; that is, successive access start_row numbers differ by exactly + * num_rows = maxaccess. This means we can get good performance with simple + * buffer dump/reload logic, by making the in-memory buffer be a multiple + * of the access height; then there will never be accesses across bufferload + * boundaries. The code will still work with overlapping access requests, + * but it doesn't handle bufferload overlaps very efficiently. + */ + + +METHODDEF(jvirt_sarray_ptr) +request_virt_sarray (j_common_ptr cinfo, int pool_id, boolean pre_zero, + JDIMENSION samplesperrow, JDIMENSION numrows, + JDIMENSION maxaccess) +/* Request a virtual 2-D sample array */ +{ + my_mem_ptr mem = (my_mem_ptr) cinfo->mem; + jvirt_sarray_ptr result; + + /* Only IMAGE-lifetime virtual arrays are currently supported */ + if (pool_id != JPOOL_IMAGE) + ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */ + + /* get control block */ + result = (jvirt_sarray_ptr) alloc_small(cinfo, pool_id, + SIZEOF(struct jvirt_sarray_control)); + + result->mem_buffer = NULL; /* marks array not yet realized */ + result->rows_in_array = numrows; + result->samplesperrow = samplesperrow; + result->maxaccess = maxaccess; + result->pre_zero = pre_zero; + result->b_s_open = FALSE; /* no associated backing-store object */ + result->next = mem->virt_sarray_list; /* add to list of virtual arrays */ + mem->virt_sarray_list = result; + + return result; +} + + +METHODDEF(jvirt_barray_ptr) +request_virt_barray (j_common_ptr cinfo, int pool_id, boolean pre_zero, + JDIMENSION blocksperrow, JDIMENSION numrows, + JDIMENSION maxaccess) +/* Request a virtual 2-D coefficient-block array */ +{ + my_mem_ptr mem = (my_mem_ptr) cinfo->mem; + jvirt_barray_ptr result; + + /* Only IMAGE-lifetime virtual arrays are currently supported */ + if (pool_id != JPOOL_IMAGE) + ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */ + + /* get control block */ + result = (jvirt_barray_ptr) alloc_small(cinfo, pool_id, + SIZEOF(struct jvirt_barray_control)); + + result->mem_buffer = NULL; /* marks array not yet realized */ + result->rows_in_array = numrows; + result->blocksperrow = blocksperrow; + result->maxaccess = maxaccess; + result->pre_zero = pre_zero; + result->b_s_open = FALSE; /* no associated backing-store object */ + result->next = mem->virt_barray_list; /* add to list of virtual arrays */ + mem->virt_barray_list = result; + + return result; +} + + +METHODDEF(void) +realize_virt_arrays (j_common_ptr cinfo) +/* Allocate the in-memory buffers for any unrealized virtual arrays */ +{ + my_mem_ptr mem = (my_mem_ptr) cinfo->mem; + size_t space_per_minheight, maximum_space, avail_mem; + size_t minheights, max_minheights; + jvirt_sarray_ptr sptr; + jvirt_barray_ptr bptr; + + /* Compute the minimum space needed (maxaccess rows in each buffer) + * and the maximum space needed (full image height in each buffer). + * These may be of use to the system-dependent jpeg_mem_available routine. + */ + space_per_minheight = 0; + maximum_space = 0; + for (sptr = mem->virt_sarray_list; sptr != NULL; sptr = sptr->next) { + if (sptr->mem_buffer == NULL) { /* if not realized yet */ + space_per_minheight += sptr->maxaccess * + sptr->samplesperrow * SIZEOF(JSAMPLE); + maximum_space += sptr->rows_in_array * + sptr->samplesperrow * SIZEOF(JSAMPLE); + } + } + for (bptr = mem->virt_barray_list; bptr != NULL; bptr = bptr->next) { + if (bptr->mem_buffer == NULL) { /* if not realized yet */ + space_per_minheight += bptr->maxaccess * + bptr->blocksperrow * SIZEOF(JBLOCK); + maximum_space += bptr->rows_in_array * + bptr->blocksperrow * SIZEOF(JBLOCK); + } + } + + if (space_per_minheight <= 0) + return; /* no unrealized arrays, no work */ + + /* Determine amount of memory to actually use; this is system-dependent. */ + avail_mem = (size_t)jpeg_mem_available(cinfo, (long)space_per_minheight, (long)maximum_space, + mem->total_space_allocated); + + /* If the maximum space needed is available, make all the buffers full + * height; otherwise parcel it out with the same number of minheights + * in each buffer. + */ + if (avail_mem >= maximum_space) + max_minheights = 1000000000L; + else { + max_minheights = avail_mem / space_per_minheight; + /* If there doesn't seem to be enough space, try to get the minimum + * anyway. This allows a "stub" implementation of jpeg_mem_available(). + */ + if (max_minheights <= 0) + max_minheights = 1; + } + + /* Allocate the in-memory buffers and initialize backing store as needed. */ + + for (sptr = mem->virt_sarray_list; sptr != NULL; sptr = sptr->next) { + if (sptr->mem_buffer == NULL) { /* if not realized yet */ + minheights = (size_t)((sptr->rows_in_array - 1L) / sptr->maxaccess + 1L); + if (minheights <= max_minheights) { + /* This buffer fits in memory */ + sptr->rows_in_mem = sptr->rows_in_array; + } else { + /* It doesn't fit in memory, create backing store. */ + sptr->rows_in_mem = (JDIMENSION)max_minheights * sptr->maxaccess; + jpeg_open_backing_store(cinfo, & sptr->b_s_info, + (long) sptr->rows_in_array * + (long) sptr->samplesperrow * + (long) SIZEOF(JSAMPLE)); + sptr->b_s_open = TRUE; + } + sptr->mem_buffer = alloc_sarray(cinfo, JPOOL_IMAGE, + sptr->samplesperrow, sptr->rows_in_mem); + sptr->rowsperchunk = mem->last_rowsperchunk; + sptr->cur_start_row = 0; + sptr->first_undef_row = 0; + sptr->dirty = FALSE; + } + } + + for (bptr = mem->virt_barray_list; bptr != NULL; bptr = bptr->next) { + if (bptr->mem_buffer == NULL) { /* if not realized yet */ + minheights = (size_t)((bptr->rows_in_array - 1L) / bptr->maxaccess + 1L); + if (minheights <= max_minheights) { + /* This buffer fits in memory */ + bptr->rows_in_mem = bptr->rows_in_array; + } else { + /* It doesn't fit in memory, create backing store. */ + bptr->rows_in_mem = (JDIMENSION)max_minheights * bptr->maxaccess; + jpeg_open_backing_store(cinfo, & bptr->b_s_info, + (long) bptr->rows_in_array * + (long) bptr->blocksperrow * + (long) SIZEOF(JBLOCK)); + bptr->b_s_open = TRUE; + } + bptr->mem_buffer = alloc_barray(cinfo, JPOOL_IMAGE, + bptr->blocksperrow, bptr->rows_in_mem); + bptr->rowsperchunk = mem->last_rowsperchunk; + bptr->cur_start_row = 0; + bptr->first_undef_row = 0; + bptr->dirty = FALSE; + } + } +} + + +LOCAL(void) +do_sarray_io (j_common_ptr cinfo, jvirt_sarray_ptr ptr, boolean writing) +/* Do backing store read or write of a virtual sample array */ +{ + size_t bytesperrow, file_offset, byte_count, rows, thisrow, i; + + bytesperrow = ptr->samplesperrow * SIZEOF(JSAMPLE); + file_offset = ptr->cur_start_row * bytesperrow; + /* Loop to read or write each allocation chunk in mem_buffer */ + for (i = 0; i < ptr->rows_in_mem; i += ptr->rowsperchunk) { + /* One chunk, but check for short chunk at end of buffer */ + rows = MIN(ptr->rowsperchunk, ptr->rows_in_mem - i); + /* Transfer no more than is currently defined */ + thisrow = ptr->cur_start_row + i; + rows = MIN(rows, ptr->first_undef_row - thisrow); + /* Transfer no more than fits in file */ + rows = MIN(rows, ptr->rows_in_array - thisrow); + if (rows <= 0) /* this chunk might be past end of file! */ + break; + byte_count = rows * bytesperrow; + if (writing) + (*ptr->b_s_info.write_backing_store) (cinfo, & ptr->b_s_info, + (void FAR *) ptr->mem_buffer[i], + (long)file_offset, (long)byte_count); + else + (*ptr->b_s_info.read_backing_store) (cinfo, & ptr->b_s_info, + (void FAR *) ptr->mem_buffer[i], + (long)file_offset, (long)byte_count); + file_offset += byte_count; + } +} + + +LOCAL(void) +do_barray_io (j_common_ptr cinfo, jvirt_barray_ptr ptr, boolean writing) +/* Do backing store read or write of a virtual coefficient-block array */ +{ + size_t bytesperrow, file_offset, byte_count, rows, thisrow, i; + + bytesperrow = ptr->blocksperrow * SIZEOF(JBLOCK); + file_offset = ptr->cur_start_row * bytesperrow; + /* Loop to read or write each allocation chunk in mem_buffer */ + for (i = 0; i < ptr->rows_in_mem; i += ptr->rowsperchunk) { + /* One chunk, but check for short chunk at end of buffer */ + rows = MIN(ptr->rowsperchunk, ptr->rows_in_mem - i); + /* Transfer no more than is currently defined */ + thisrow = ptr->cur_start_row + i; + rows = MIN(rows, ptr->first_undef_row - thisrow); + /* Transfer no more than fits in file */ + rows = MIN(rows, ptr->rows_in_array - thisrow); + if (rows <= 0) /* this chunk might be past end of file! */ + break; + byte_count = rows * bytesperrow; + if (writing) + (*ptr->b_s_info.write_backing_store) (cinfo, & ptr->b_s_info, + (void FAR *) ptr->mem_buffer[i], + (long)file_offset, (long)byte_count); + else + (*ptr->b_s_info.read_backing_store) (cinfo, & ptr->b_s_info, + (void FAR *) ptr->mem_buffer[i], + (long)file_offset, (long)byte_count); + file_offset += byte_count; + } +} + + +METHODDEF(JSAMPARRAY) +access_virt_sarray (j_common_ptr cinfo, jvirt_sarray_ptr ptr, + JDIMENSION start_row, JDIMENSION num_rows, + boolean writable) +/* Access the part of a virtual sample array starting at start_row */ +/* and extending for num_rows rows. writable is true if */ +/* caller intends to modify the accessed area. */ +{ + JDIMENSION end_row = start_row + num_rows; + JDIMENSION undef_row; + + /* debugging check */ + if (end_row > ptr->rows_in_array || num_rows > ptr->maxaccess || + ptr->mem_buffer == NULL) + ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS); + + /* Make the desired part of the virtual array accessible */ + if (start_row < ptr->cur_start_row || + end_row > ptr->cur_start_row+ptr->rows_in_mem) { + if (! ptr->b_s_open) + ERREXIT(cinfo, JERR_VIRTUAL_BUG); + /* Flush old buffer contents if necessary */ + if (ptr->dirty) { + do_sarray_io(cinfo, ptr, TRUE); + ptr->dirty = FALSE; + } + /* Decide what part of virtual array to access. + * Algorithm: if target address > current window, assume forward scan, + * load starting at target address. If target address < current window, + * assume backward scan, load so that target area is top of window. + * Note that when switching from forward write to forward read, will have + * start_row = 0, so the limiting case applies and we load from 0 anyway. + */ + if (start_row > ptr->cur_start_row) { + ptr->cur_start_row = start_row; + } else { + /* use long arithmetic here to avoid overflow & unsigned problems */ + long ltemp; + + ltemp = (long) end_row - (long) ptr->rows_in_mem; + if (ltemp < 0) + ltemp = 0; /* don't fall off front end of file */ + ptr->cur_start_row = (JDIMENSION) ltemp; + } + /* Read in the selected part of the array. + * During the initial write pass, we will do no actual read + * because the selected part is all undefined. + */ + do_sarray_io(cinfo, ptr, FALSE); + } + /* Ensure the accessed part of the array is defined; prezero if needed. + * To improve locality of access, we only prezero the part of the array + * that the caller is about to access, not the entire in-memory array. + */ + if (ptr->first_undef_row < end_row) { + if (ptr->first_undef_row < start_row) { + if (writable) /* writer skipped over a section of array */ + ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS); + undef_row = start_row; /* but reader is allowed to read ahead */ + } else { + undef_row = ptr->first_undef_row; + } + if (writable) + ptr->first_undef_row = end_row; + if (ptr->pre_zero) { + size_t bytesperrow = (size_t) ptr->samplesperrow * SIZEOF(JSAMPLE); + undef_row -= ptr->cur_start_row; /* make indexes relative to buffer */ + end_row -= ptr->cur_start_row; + while (undef_row < end_row) { + jzero_far((void FAR *) ptr->mem_buffer[undef_row], bytesperrow); + undef_row++; + } + } else { + if (! writable) /* reader looking at undefined data */ + ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS); + } + } + /* Flag the buffer dirty if caller will write in it */ + if (writable) + ptr->dirty = TRUE; + /* Return address of proper part of the buffer */ + return ptr->mem_buffer + (start_row - ptr->cur_start_row); +} + + +METHODDEF(JBLOCKARRAY) +access_virt_barray (j_common_ptr cinfo, jvirt_barray_ptr ptr, + JDIMENSION start_row, JDIMENSION num_rows, + boolean writable) +/* Access the part of a virtual block array starting at start_row */ +/* and extending for num_rows rows. writable is true if */ +/* caller intends to modify the accessed area. */ +{ + JDIMENSION end_row = start_row + num_rows; + JDIMENSION undef_row; + + /* debugging check */ + if (end_row > ptr->rows_in_array || num_rows > ptr->maxaccess || + ptr->mem_buffer == NULL) + ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS); + + /* Make the desired part of the virtual array accessible */ + if (start_row < ptr->cur_start_row || + end_row > ptr->cur_start_row+ptr->rows_in_mem) { + if (! ptr->b_s_open) + ERREXIT(cinfo, JERR_VIRTUAL_BUG); + /* Flush old buffer contents if necessary */ + if (ptr->dirty) { + do_barray_io(cinfo, ptr, TRUE); + ptr->dirty = FALSE; + } + /* Decide what part of virtual array to access. + * Algorithm: if target address > current window, assume forward scan, + * load starting at target address. If target address < current window, + * assume backward scan, load so that target area is top of window. + * Note that when switching from forward write to forward read, will have + * start_row = 0, so the limiting case applies and we load from 0 anyway. + */ + if (start_row > ptr->cur_start_row) { + ptr->cur_start_row = start_row; + } else { + /* use long arithmetic here to avoid overflow & unsigned problems */ + long ltemp; + + ltemp = (long) end_row - (long) ptr->rows_in_mem; + if (ltemp < 0) + ltemp = 0; /* don't fall off front end of file */ + ptr->cur_start_row = (JDIMENSION) ltemp; + } + /* Read in the selected part of the array. + * During the initial write pass, we will do no actual read + * because the selected part is all undefined. + */ + do_barray_io(cinfo, ptr, FALSE); + } + /* Ensure the accessed part of the array is defined; prezero if needed. + * To improve locality of access, we only prezero the part of the array + * that the caller is about to access, not the entire in-memory array. + */ + if (ptr->first_undef_row < end_row) { + if (ptr->first_undef_row < start_row) { + if (writable) /* writer skipped over a section of array */ + ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS); + undef_row = start_row; /* but reader is allowed to read ahead */ + } else { + undef_row = ptr->first_undef_row; + } + if (writable) + ptr->first_undef_row = end_row; + if (ptr->pre_zero) { + size_t bytesperrow = (size_t) ptr->blocksperrow * SIZEOF(JBLOCK); + undef_row -= ptr->cur_start_row; /* make indexes relative to buffer */ + end_row -= ptr->cur_start_row; + while (undef_row < end_row) { + jzero_far((void FAR *) ptr->mem_buffer[undef_row], bytesperrow); + undef_row++; + } + } else { + if (! writable) /* reader looking at undefined data */ + ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS); + } + } + /* Flag the buffer dirty if caller will write in it */ + if (writable) + ptr->dirty = TRUE; + /* Return address of proper part of the buffer */ + return ptr->mem_buffer + (start_row - ptr->cur_start_row); +} + + +/* + * Release all objects belonging to a specified pool. + */ + +METHODDEF(void) +free_pool (j_common_ptr cinfo, int pool_id) +{ + my_mem_ptr mem = (my_mem_ptr) cinfo->mem; + small_pool_ptr shdr_ptr; + large_pool_ptr lhdr_ptr; + size_t space_freed; + + if (pool_id < 0 || pool_id >= JPOOL_NUMPOOLS) + ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */ + +#ifdef MEM_STATS + if (cinfo->err->trace_level > 1) + print_mem_stats(cinfo, pool_id); /* print pool's memory usage statistics */ +#endif + + /* If freeing IMAGE pool, close any virtual arrays first */ + if (pool_id == JPOOL_IMAGE) { + jvirt_sarray_ptr sptr; + jvirt_barray_ptr bptr; + + for (sptr = mem->virt_sarray_list; sptr != NULL; sptr = sptr->next) { + if (sptr->b_s_open) { /* there may be no backing store */ + sptr->b_s_open = FALSE; /* prevent recursive close if error */ + (*sptr->b_s_info.close_backing_store) (cinfo, & sptr->b_s_info); + } + } + mem->virt_sarray_list = NULL; + for (bptr = mem->virt_barray_list; bptr != NULL; bptr = bptr->next) { + if (bptr->b_s_open) { /* there may be no backing store */ + bptr->b_s_open = FALSE; /* prevent recursive close if error */ + (*bptr->b_s_info.close_backing_store) (cinfo, & bptr->b_s_info); + } + } + mem->virt_barray_list = NULL; + } + + /* Release large objects */ + lhdr_ptr = mem->large_list[pool_id]; + mem->large_list[pool_id] = NULL; + + while (lhdr_ptr != NULL) { + large_pool_ptr next_lhdr_ptr = lhdr_ptr->hdr.next; + space_freed = lhdr_ptr->hdr.bytes_used + + lhdr_ptr->hdr.bytes_left + + SIZEOF(large_pool_hdr); + jpeg_free_large(cinfo, (void FAR *) lhdr_ptr, space_freed); + mem->total_space_allocated -= (long)space_freed; + lhdr_ptr = next_lhdr_ptr; + } + + /* Release small objects */ + shdr_ptr = mem->small_list[pool_id]; + mem->small_list[pool_id] = NULL; + + while (shdr_ptr != NULL) { + small_pool_ptr next_shdr_ptr = shdr_ptr->hdr.next; + space_freed = shdr_ptr->hdr.bytes_used + + shdr_ptr->hdr.bytes_left + + SIZEOF(small_pool_hdr); + jpeg_free_small(cinfo, (void *) shdr_ptr, space_freed); + mem->total_space_allocated -= (long)space_freed; + shdr_ptr = next_shdr_ptr; + } +} + + +/* + * Close up shop entirely. + * Note that this cannot be called unless cinfo->mem is non-NULL. + */ + +METHODDEF(void) +self_destruct (j_common_ptr cinfo) +{ + int pool; + + /* Close all backing store, release all memory. + * Releasing pools in reverse order might help avoid fragmentation + * with some (brain-damaged) malloc libraries. + */ + for (pool = JPOOL_NUMPOOLS-1; pool >= JPOOL_PERMANENT; pool--) { + free_pool(cinfo, pool); + } + + /* Release the memory manager control block too. */ + jpeg_free_small(cinfo, (void *) cinfo->mem, SIZEOF(my_memory_mgr)); + cinfo->mem = NULL; /* ensures I will be called only once */ + + jpeg_mem_term(cinfo); /* system-dependent cleanup */ +} + + +/* + * Memory manager initialization. + * When this is called, only the error manager pointer is valid in cinfo! + */ + +GLOBAL(void) +jinit_memory_mgr (j_common_ptr cinfo) +{ + my_mem_ptr mem; + long max_to_use; + int pool; + size_t test_mac; + + cinfo->mem = NULL; /* for safety if init fails */ + + /* Check for configuration errors. + * SIZEOF(ALIGN_TYPE) should be a power of 2; otherwise, it probably + * doesn't reflect any real hardware alignment requirement. + * The test is a little tricky: for X>0, X and X-1 have no one-bits + * in common if and only if X is a power of 2, ie has only one one-bit. + * Some compilers may give an "unreachable code" warning here; ignore it. + */ + if ((SIZEOF(ALIGN_TYPE) & (SIZEOF(ALIGN_TYPE)-1)) != 0) + ERREXIT(cinfo, JERR_BAD_ALIGN_TYPE); + /* MAX_ALLOC_CHUNK must be representable as type size_t, and must be + * a multiple of SIZEOF(ALIGN_TYPE). + * Again, an "unreachable code" warning may be ignored here. + * But a "constant too large" warning means you need to fix MAX_ALLOC_CHUNK. + */ + test_mac = (size_t) MAX_ALLOC_CHUNK; + if ((long) test_mac != MAX_ALLOC_CHUNK || + (MAX_ALLOC_CHUNK % SIZEOF(ALIGN_TYPE)) != 0) + ERREXIT(cinfo, JERR_BAD_ALLOC_CHUNK); + + max_to_use = jpeg_mem_init(cinfo); /* system-dependent initialization */ + + /* Attempt to allocate memory manager's control block */ + mem = (my_mem_ptr) jpeg_get_small(cinfo, SIZEOF(my_memory_mgr)); + + if (mem == NULL) { + jpeg_mem_term(cinfo); /* system-dependent cleanup */ + ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, 0); + } + + /* OK, fill in the method pointers */ + mem->pub.alloc_small = alloc_small; + mem->pub.alloc_large = alloc_large; + mem->pub.alloc_sarray = alloc_sarray; + mem->pub.alloc_barray = alloc_barray; +#ifdef NEED_DARRAY + mem->pub.alloc_darray = alloc_darray; +#endif + mem->pub.request_virt_sarray = request_virt_sarray; + mem->pub.request_virt_barray = request_virt_barray; + mem->pub.realize_virt_arrays = realize_virt_arrays; + mem->pub.access_virt_sarray = access_virt_sarray; + mem->pub.access_virt_barray = access_virt_barray; + mem->pub.free_pool = free_pool; + mem->pub.self_destruct = self_destruct; + + /* Make MAX_ALLOC_CHUNK accessible to other modules */ + mem->pub.max_alloc_chunk = MAX_ALLOC_CHUNK; + + /* Initialize working state */ + mem->pub.max_memory_to_use = max_to_use; + + for (pool = JPOOL_NUMPOOLS-1; pool >= JPOOL_PERMANENT; pool--) { + mem->small_list[pool] = NULL; + mem->large_list[pool] = NULL; + } + mem->virt_sarray_list = NULL; + mem->virt_barray_list = NULL; + + mem->total_space_allocated = SIZEOF(my_memory_mgr); + + /* Declare ourselves open for business */ + cinfo->mem = & mem->pub; + + /* Check for an environment variable JPEGMEM; if found, override the + * default max_memory setting from jpeg_mem_init. Note that the + * surrounding application may again override this value. + * If your system doesn't support getenv(), define NO_GETENV to disable + * this feature. + */ +#ifndef NO_GETENV + { char * memenv; + + if ((memenv = getenv("JPEGMEM")) != NULL) { + char ch = 'x'; + + if (sscanf(memenv, "%ld%c", &max_to_use, &ch) > 0) { + if (ch == 'm' || ch == 'M') + max_to_use *= 1000L; + mem->pub.max_memory_to_use = max_to_use * 1000L; + } + } + } +#endif + +} diff --git a/dcmjpeg/libijg16/jmemnobs.c b/dcmjpeg/libijg16/jmemnobs.c new file mode 100644 index 00000000..6fa0e579 --- /dev/null +++ b/dcmjpeg/libijg16/jmemnobs.c @@ -0,0 +1,109 @@ +/* + * jmemnobs.c + * + * Copyright (C) 1992-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file provides a really simple implementation of the system- + * dependent portion of the JPEG memory manager. This implementation + * assumes that no backing-store files are needed: all required space + * can be obtained from malloc(). + * This is very portable in the sense that it'll compile on almost anything, + * but you'd better have lots of main memory (or virtual memory) if you want + * to process big images. + * Note that the max_memory_to_use option is ignored by this implementation. + */ + +#define JPEG_INTERNALS +#include "jinclude16.h" +#include "jpeglib16.h" +#include "jmemsys16.h" /* import the system-dependent declarations */ + +#ifndef HAVE_STDLIB_H /* should declare malloc(),free() */ +extern void * malloc JPP((size_t size)); +extern void free JPP((void *ptr)); +#endif + + +/* + * Memory allocation and freeing are controlled by the regular library + * routines malloc() and free(). + */ + +GLOBAL(void *) +jpeg_get_small (j_common_ptr cinfo, size_t sizeofobject) +{ + return (void *) malloc(sizeofobject); +} + +GLOBAL(void) +jpeg_free_small (j_common_ptr cinfo, void * object, size_t sizeofobject) +{ + free(object); +} + + +/* + * "Large" objects are treated the same as "small" ones. + * NB: although we include FAR keywords in the routine declarations, + * this file won't actually work in 80x86 small/medium model; at least, + * you probably won't be able to process useful-size images in only 64KB. + */ + +GLOBAL(void FAR *) +jpeg_get_large (j_common_ptr cinfo, size_t sizeofobject) +{ + return (void FAR *) malloc(sizeofobject); +} + +GLOBAL(void) +jpeg_free_large (j_common_ptr cinfo, void FAR * object, size_t sizeofobject) +{ + free(object); +} + + +/* + * This routine computes the total memory space available for allocation. + * Here we always say, "we got all you want bud!" + */ + +GLOBAL(long) +jpeg_mem_available (j_common_ptr cinfo, long min_bytes_needed, + long max_bytes_needed, long already_allocated) +{ + return max_bytes_needed; +} + + +/* + * Backing store (temporary file) management. + * Since jpeg_mem_available always promised the moon, + * this should never be called and we can just error out. + */ + +GLOBAL(void) +jpeg_open_backing_store (j_common_ptr cinfo, backing_store_ptr info, + long total_bytes_needed) +{ + ERREXIT(cinfo, JERR_NO_BACKING_STORE); +} + + +/* + * These routines take care of any system-dependent initialization and + * cleanup required. Here, there isn't any. + */ + +GLOBAL(long) +jpeg_mem_init (j_common_ptr cinfo) +{ + return 0; /* just set max_memory_to_use to 0 */ +} + +GLOBAL(void) +jpeg_mem_term (j_common_ptr cinfo) +{ + /* no work */ +} diff --git a/dcmjpeg/libijg16/jmemsys16.h b/dcmjpeg/libijg16/jmemsys16.h new file mode 100644 index 00000000..3a7a215e --- /dev/null +++ b/dcmjpeg/libijg16/jmemsys16.h @@ -0,0 +1,198 @@ +/* + * jmemsys.h + * + * Copyright (C) 1992-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This include file defines the interface between the system-independent + * and system-dependent portions of the JPEG memory manager. No other + * modules need include it. (The system-independent portion is jmemmgr.c; + * there are several different versions of the system-dependent portion.) + * + * This file works as-is for the system-dependent memory managers supplied + * in the IJG distribution. You may need to modify it if you write a + * custom memory manager. If system-dependent changes are needed in + * this file, the best method is to #ifdef them based on a configuration + * symbol supplied in jconfig.h, as we have done with USE_MSDOS_MEMMGR + * and USE_MAC_MEMMGR. + */ + + +/* Short forms of external names for systems with brain-damaged linkers. */ + +#ifdef NEED_SHORT_EXTERNAL_NAMES +#define jpeg_get_small jpeg16_get_small +#define jpeg_free_small jpeg16_free_small +#define jpeg_get_large jpeg16_get_large +#define jpeg_free_large jpeg16_free_large +#define jpeg_mem_available jpeg16_mem_available +#define jpeg_open_backing_store jpeg16_open_backing_store +#define jpeg_mem_init jpeg16_mem_init +#define jpeg_mem_term jpeg16_mem_term +#endif /* NEED_SHORT_EXTERNAL_NAMES */ + + +/* + * These two functions are used to allocate and release small chunks of + * memory. (Typically the total amount requested through jpeg_get_small is + * no more than 20K or so; this will be requested in chunks of a few K each.) + * Behavior should be the same as for the standard library functions malloc + * and free; in particular, jpeg_get_small must return NULL on failure. + * On most systems, these ARE malloc and free. jpeg_free_small is passed the + * size of the object being freed, just in case it's needed. + * On an 80x86 machine using small-data memory model, these manage near heap. + */ + +EXTERN(void *) jpeg_get_small JPP((j_common_ptr cinfo, size_t sizeofobject)); +EXTERN(void) jpeg_free_small JPP((j_common_ptr cinfo, void * object, + size_t sizeofobject)); + +/* + * These two functions are used to allocate and release large chunks of + * memory (up to the total free space designated by jpeg_mem_available). + * The interface is the same as above, except that on an 80x86 machine, + * far pointers are used. On most other machines these are identical to + * the jpeg_get/free_small routines; but we keep them separate anyway, + * in case a different allocation strategy is desirable for large chunks. + */ + +EXTERN(void FAR *) jpeg_get_large JPP((j_common_ptr cinfo, + size_t sizeofobject)); +EXTERN(void) jpeg_free_large JPP((j_common_ptr cinfo, void FAR * object, + size_t sizeofobject)); + +/* + * The macro MAX_ALLOC_CHUNK designates the maximum number of bytes that may + * be requested in a single call to jpeg_get_large (and jpeg_get_small for that + * matter, but that case should never come into play). This macro is needed + * to model the 64Kb-segment-size limit of far addressing on 80x86 machines. + * On those machines, we expect that jconfig.h will provide a proper value. + * On machines with 32-bit flat address spaces, any large constant may be used. + * + * NB: jmemmgr.c expects that MAX_ALLOC_CHUNK will be representable as type + * size_t and will be a multiple of sizeof(align_type). + */ + +#ifndef MAX_ALLOC_CHUNK /* may be overridden in jconfig.h */ +#define MAX_ALLOC_CHUNK 1000000000L +#endif + +/* + * This routine computes the total space still available for allocation by + * jpeg_get_large. If more space than this is needed, backing store will be + * used. NOTE: any memory already allocated must not be counted. + * + * There is a minimum space requirement, corresponding to the minimum + * feasible buffer sizes; jmemmgr.c will request that much space even if + * jpeg_mem_available returns zero. The maximum space needed, enough to hold + * all working storage in memory, is also passed in case it is useful. + * Finally, the total space already allocated is passed. If no better + * method is available, cinfo->mem->max_memory_to_use - already_allocated + * is often a suitable calculation. + * + * It is OK for jpeg_mem_available to underestimate the space available + * (that'll just lead to more backing-store access than is really necessary). + * However, an overestimate will lead to failure. Hence it's wise to subtract + * a slop factor from the true available space. 5% should be enough. + * + * On machines with lots of virtual memory, any large constant may be returned. + * Conversely, zero may be returned to always use the minimum amount of memory. + */ + +EXTERN(long) jpeg_mem_available JPP((j_common_ptr cinfo, + long min_bytes_needed, + long max_bytes_needed, + long already_allocated)); + + +/* + * This structure holds whatever state is needed to access a single + * backing-store object. The read/write/close method pointers are called + * by jmemmgr.c to manipulate the backing-store object; all other fields + * are private to the system-dependent backing store routines. + */ + +#define TEMP_NAME_LENGTH 64 /* max length of a temporary file's name */ + + +#ifdef USE_MSDOS_MEMMGR /* DOS-specific junk */ + +typedef unsigned short XMSH; /* type of extended-memory handles */ +typedef unsigned short EMSH; /* type of expanded-memory handles */ + +typedef union { + short file_handle; /* DOS file handle if it's a temp file */ + XMSH xms_handle; /* handle if it's a chunk of XMS */ + EMSH ems_handle; /* handle if it's a chunk of EMS */ +} handle_union; + +#endif /* USE_MSDOS_MEMMGR */ + +#ifdef USE_MAC_MEMMGR /* Mac-specific junk */ +#include +#endif /* USE_MAC_MEMMGR */ + + +typedef struct backing_store_struct * backing_store_ptr; + +typedef struct backing_store_struct { + /* Methods for reading/writing/closing this backing-store object */ + JMETHOD(void, read_backing_store, (j_common_ptr cinfo, + backing_store_ptr info, + void FAR * buffer_address, + long file_offset, long byte_count)); + JMETHOD(void, write_backing_store, (j_common_ptr cinfo, + backing_store_ptr info, + void FAR * buffer_address, + long file_offset, long byte_count)); + JMETHOD(void, close_backing_store, (j_common_ptr cinfo, + backing_store_ptr info)); + + /* Private fields for system-dependent backing-store management */ +#ifdef USE_MSDOS_MEMMGR + /* For the MS-DOS manager (jmemdos.c), we need: */ + handle_union handle; /* reference to backing-store storage object */ + char temp_name[TEMP_NAME_LENGTH]; /* name if it's a file */ +#else +#ifdef USE_MAC_MEMMGR + /* For the Mac manager (jmemmac.c), we need: */ + short temp_file; /* file reference number to temp file */ + FSSpec tempSpec; /* the FSSpec for the temp file */ + char temp_name[TEMP_NAME_LENGTH]; /* name if it's a file */ +#else + /* For a typical implementation with temp files, we need: */ + FILE * temp_file; /* stdio reference to temp file */ + char temp_name[TEMP_NAME_LENGTH]; /* name of temp file */ +#endif +#endif +} backing_store_info; + + +/* + * Initial opening of a backing-store object. This must fill in the + * read/write/close pointers in the object. The read/write routines + * may take an error exit if the specified maximum file size is exceeded. + * (If jpeg_mem_available always returns a large value, this routine can + * just take an error exit.) + */ + +EXTERN(void) jpeg_open_backing_store JPP((j_common_ptr cinfo, + backing_store_ptr info, + long total_bytes_needed)); + + +/* + * These routines take care of any system-dependent initialization and + * cleanup required. jpeg_mem_init will be called before anything is + * allocated (and, therefore, nothing in cinfo is of use except the error + * manager pointer). It should return a suitable default value for + * max_memory_to_use; this may subsequently be overridden by the surrounding + * application. (Note that max_memory_to_use is only important if + * jpeg_mem_available chooses to consult it ... no one else will.) + * jpeg_mem_term may assume that all requested memory has been freed and that + * all opened backing-store objects have been closed. + */ + +EXTERN(long) jpeg_mem_init JPP((j_common_ptr cinfo)); +EXTERN(void) jpeg_mem_term JPP((j_common_ptr cinfo)); diff --git a/dcmjpeg/libijg16/jmorecfg16.h b/dcmjpeg/libijg16/jmorecfg16.h new file mode 100644 index 00000000..bde21574 --- /dev/null +++ b/dcmjpeg/libijg16/jmorecfg16.h @@ -0,0 +1,407 @@ +/* + * jmorecfg.h + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains additional configuration options that customize the + * JPEG software for special applications or support machine-dependent + * optimizations. Most users will not need to touch this file. + */ + + +#include "dcmtk/ofstd/ofexport.h" /* for DCMTK_DECL_EXPORT */ + +#ifdef ijg16_EXPORTS +#define DCMTK_IJG16_EXPORT DCMTK_DECL_EXPORT +#else +#define DCMTK_IJG16_EXPORT DCMTK_DECL_IMPORT +#endif + + +/* + * Define BITS_IN_JSAMPLE as either + * 8 for 8-bit sample values (the usual setting) + * 12 for 12-bit sample values + * Only 8 and 12 are legal data precisions for lossy JPEG according to the + * JPEG standard, and the IJG code does not support anything else! + * We do not support run-time selection of data precision, sorry. + */ + +#define BITS_IN_JSAMPLE 16 /* use 8 or 12 (or 16 for lossless) */ + + +/* + * Maximum number of components (color channels) allowed in JPEG image. + * To meet the letter of the JPEG spec, set this to 255. However, darn + * few applications need more than 4 channels (maybe 5 for CMYK + alpha + * mask). We recommend 10 as a reasonable compromise; use 4 if you are + * really short on memory. (Each allowed component costs a hundred or so + * bytes of storage, whether actually used in an image or not.) + */ + +#define MAX_COMPONENTS 10 /* maximum number of image components */ + + +/* + * Basic data types. + * You may need to change these if you have a machine with unusual data + * type sizes; for example, "char" not 8 bits, "short" not 16 bits, + * or "long" not 32 bits. We don't care whether "int" is 16 or 32 bits, + * but it had better be at least 16. + */ + +/* Representation of a single sample (pixel element value). + * We frequently allocate large arrays of these, so it's important to keep + * them small. But if you have memory to burn and access to char or short + * arrays is very slow on your hardware, you might want to change these. + */ + +#if BITS_IN_JSAMPLE == 8 +/* JSAMPLE should be the smallest type that will hold the values 0..255. + * You can use a signed char by having GETJSAMPLE mask it with 0xFF. + */ + +#ifdef HAVE_UNSIGNED_CHAR + +typedef unsigned char JSAMPLE; +#define GETJSAMPLE(value) ((int) (value)) + +#else /* not HAVE_UNSIGNED_CHAR */ + +typedef char JSAMPLE; +#ifdef CHAR_IS_UNSIGNED +#define GETJSAMPLE(value) ((int) (value)) +#else +#define GETJSAMPLE(value) ((int) (value) & 0xFF) +#endif /* CHAR_IS_UNSIGNED */ + +#endif /* HAVE_UNSIGNED_CHAR */ + +#define MAXJSAMPLE 255 +#define CENTERJSAMPLE 128 + +#endif /* BITS_IN_JSAMPLE == 8 */ + + +#if BITS_IN_JSAMPLE == 12 +/* JSAMPLE should be the smallest type that will hold the values 0..4095. + * On nearly all machines "short" will do nicely. + */ + +typedef short JSAMPLE; +#define GETJSAMPLE(value) ((int) (value)) + +#define MAXJSAMPLE 4095 +#define CENTERJSAMPLE 2048 + +#endif /* BITS_IN_JSAMPLE == 12 */ + + +#if BITS_IN_JSAMPLE == 16 +/* JSAMPLE should be the smallest type that will hold the values 0..65535. + * You can use a signed short by having GETJSAMPLE mask it with 0xFFFF. + */ + +#ifdef HAVE_UNSIGNED_SHORT + +typedef unsigned short JSAMPLE; +#define GETJSAMPLE(value) ((int) (value)) + +#else /* not HAVE_UNSIGNED_SHORT */ + +typedef short JSAMPLE; +#ifdef SHORT_IS_UNSIGNED +#define GETJSAMPLE(value) ((int) (value)) +#else +#define GETJSAMPLE(value) ((int) (value) & 0xFFFF) +#endif /* SHORT_IS_UNSIGNED */ + +#endif /* HAVE_UNSIGNED_SHORT */ + +#define MAXJSAMPLE 65535 +#define CENTERJSAMPLE 32768 + +#endif /* BITS_IN_JSAMPLE == 16 */ + + +/* Representation of a DCT frequency coefficient. + * This should be a signed value of at least 16 bits; "short" is usually OK. + * Again, we allocate large arrays of these, but you can change to int + * if you have memory to burn and "short" is really slow. + */ + +typedef short JCOEF; + + +/* Representation of a spatial difference value. + * This should be a signed value of at least 16 bits; int is usually OK. + */ + +typedef int JDIFF; + + +/* Compressed datastreams are represented as arrays of JOCTET. + * These must be EXACTLY 8 bits wide, at least once they are written to + * external storage. Note that when using the stdio data source/destination + * managers, this is also the data type passed to fread/fwrite. + */ + +#ifdef HAVE_UNSIGNED_CHAR + +typedef unsigned char JOCTET; +#define GETJOCTET(value) (value) + +#else /* not HAVE_UNSIGNED_CHAR */ + +typedef char JOCTET; +#ifdef CHAR_IS_UNSIGNED +#define GETJOCTET(value) (value) +#else +#define GETJOCTET(value) ((value) & 0xFF) +#endif /* CHAR_IS_UNSIGNED */ + +#endif /* HAVE_UNSIGNED_CHAR */ + + +/* These typedefs are used for various table entries and so forth. + * They must be at least as wide as specified; but making them too big + * won't cost a huge amount of memory, so we don't provide special + * extraction code like we did for JSAMPLE. (In other words, these + * typedefs live at a different point on the speed/space tradeoff curve.) + */ + +/* UINT8 must hold at least the values 0..255. */ + +#ifdef HAVE_UNSIGNED_CHAR +typedef unsigned char UINT8; +#else /* not HAVE_UNSIGNED_CHAR */ +#ifdef CHAR_IS_UNSIGNED +typedef char UINT8; +#else /* not CHAR_IS_UNSIGNED */ +typedef short UINT8; +#endif /* CHAR_IS_UNSIGNED */ +#endif /* HAVE_UNSIGNED_CHAR */ + +/* UINT16 must hold at least the values 0..65535. */ + +#ifdef HAVE_UNSIGNED_SHORT +typedef unsigned short UINT16; +#else /* not HAVE_UNSIGNED_SHORT */ +typedef unsigned int UINT16; +#endif /* HAVE_UNSIGNED_SHORT */ + +/* INT16 must hold at least the values -32768..32767. */ + +#ifndef XMD_H /* X11/xmd.h correctly defines INT16 */ +typedef short INT16; +#endif + +/* IJG_INT32 must hold at least signed 32-bit values. */ +typedef long IJG_INT32; + +/* Datatype used for image dimensions. The JPEG standard only supports + * images up to 64K*64K due to 16-bit fields in SOF markers. Therefore + * "unsigned int" is sufficient on all machines. However, if you need to + * handle larger images and you don't mind deviating from the spec, you + * can change this datatype. + */ + +typedef unsigned int JDIMENSION; + +#define JPEG_MAX_DIMENSION 65500L /* a tad under 64K to prevent overflows */ + + +/* These macros are used in all function definitions and extern declarations. + * You could modify them if you need to change function linkage conventions; + * in particular, you'll need to do that to make the library a Windows DLL. + * Another application is to make all functions global for use with debuggers + * or code profilers that require it. + */ + +/* a function called through method pointers: */ +#define METHODDEF(type) static type +/* a function used only in its module: */ +#define LOCAL(type) static type +/* a function referenced thru EXTERNs: */ +#define GLOBAL(type) type +/* a reference to a GLOBAL function: */ +#define EXTERN(type) extern DCMTK_IJG16_EXPORT type + + +/* This macro is used to declare a "method", that is, a function pointer. + * We want to supply prototype parameters if the compiler can cope. + * Note that the arglist parameter must be parenthesized! + * Again, you can customize this if you need special linkage keywords. + */ + +#ifdef HAVE_PROTOTYPES +#define JMETHOD(type,methodname,arglist) type (*methodname) arglist +#else +#define JMETHOD(type,methodname,arglist) type (*methodname) () +#endif + + +/* Here is the pseudo-keyword for declaring pointers that must be "far" + * on 80x86 machines. Most of the specialized coding for 80x86 is handled + * by just saying "FAR *" where such a pointer is needed. In a few places + * explicit coding is needed; see uses of the NEED_FAR_POINTERS symbol. + */ + +#undef FAR +#ifdef NEED_FAR_POINTERS +#define FAR far +#else +#define FAR +#endif + + +/* + * On a few systems, type boolean and/or its values FALSE, TRUE may appear + * in standard header files. Or you may have conflicts with application- + * specific header files that you want to include together with these files. + * Defining HAVE_BOOLEAN before including jpeglib.h should make it work. + */ + +#ifndef HAVE_BOOLEAN +typedef int boolean; +#endif +#ifndef FALSE /* in case these macros already exist */ +#define FALSE 0 /* values of boolean */ +#endif +#ifndef TRUE +#define TRUE 1 +#endif + + +/* + * The remaining options affect code selection within the JPEG library, + * but they don't need to be visible to most applications using the library. + * To minimize application namespace pollution, the symbols won't be + * defined unless JPEG_INTERNALS or JPEG_INTERNAL_OPTIONS has been defined. + */ + +#ifdef JPEG_INTERNALS +#define JPEG_INTERNAL_OPTIONS +#endif + +#ifdef JPEG_INTERNAL_OPTIONS + + +/* + * These defines indicate whether to include various optional functions. + * Undefining some of these symbols will produce a smaller but less capable + * library. Note that you can leave certain source files out of the + * compilation/linking process if you've #undef'd the corresponding symbols. + * (You may HAVE to do that if your compiler doesn't like null source files.) + */ + +/* Arithmetic coding is unsupported for legal reasons. Complaints to IBM. */ + +/* Capability options common to encoder and decoder: */ + +#define DCT_ISLOW_SUPPORTED /* slow but accurate integer algorithm */ +#define DCT_IFAST_SUPPORTED /* faster, less accurate integer method */ +#define DCT_FLOAT_SUPPORTED /* floating-point: accurate, fast on fast HW */ + +/* Encoder capability options: */ + +#undef C_ARITH_CODING_SUPPORTED /* Arithmetic coding back end? */ +#define C_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */ +#define C_PROGRESSIVE_SUPPORTED /* Progressive JPEG? (Requires MULTISCAN)*/ +#define C_LOSSLESS_SUPPORTED /* Lossless JPEG? */ +#define ENTROPY_OPT_SUPPORTED /* Optimization of entropy coding parms? */ +/* Note: if you selected 12-bit data precision, it is dangerous to turn off + * ENTROPY_OPT_SUPPORTED. The standard Huffman tables are only good for 8-bit + * precision, so jcshuff.c normally uses entropy optimization to compute + * usable tables for higher precision. If you don't want to do optimization, + * you'll have to supply different default Huffman tables. + * The exact same statements apply for progressive and lossless JPEG: + * the default tables don't work for progressive mode or lossless mode. + * (This may get fixed, however.) + */ +#define INPUT_SMOOTHING_SUPPORTED /* Input image smoothing option? */ + +/* Decoder capability options: */ + +#undef D_ARITH_CODING_SUPPORTED /* Arithmetic coding back end? */ +#define D_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */ +#define D_PROGRESSIVE_SUPPORTED /* Progressive JPEG? (Requires MULTISCAN)*/ +#define D_LOSSLESS_SUPPORTED /* Lossless JPEG? */ +#define SAVE_MARKERS_SUPPORTED /* jpeg_save_markers() needed? */ +#define BLOCK_SMOOTHING_SUPPORTED /* Block smoothing? (Progressive only) */ +#define IDCT_SCALING_SUPPORTED /* Output rescaling via IDCT? */ +#undef UPSAMPLE_SCALING_SUPPORTED /* Output rescaling at upsample stage? */ +#define UPSAMPLE_MERGING_SUPPORTED /* Fast path for sloppy upsampling? */ +#define QUANT_1PASS_SUPPORTED /* 1-pass color quantization? */ +#define QUANT_2PASS_SUPPORTED /* 2-pass color quantization? */ + +/* more capability options later, no doubt */ + + +/* + * Ordering of RGB data in scanlines passed to or from the application. + * If your application wants to deal with data in the order B,G,R, just + * change these macros. You can also deal with formats such as R,G,B,X + * (one extra byte per pixel) by changing RGB_PIXELSIZE. Note that changing + * the offsets will also change the order in which colormap data is organized. + * RESTRICTIONS: + * 1. The sample applications cjpeg,djpeg do NOT support modified RGB formats. + * 2. These macros only affect RGB<=>YCbCr color conversion, so they are not + * useful if you are using JPEG color spaces other than YCbCr or grayscale. + * 3. The color quantizer modules will not behave desirably if RGB_PIXELSIZE + * is not 3 (they don't understand about dummy color components!). So you + * can't use color quantization if you change that value. + */ + +#define RGB_RED 0 /* Offset of Red in an RGB scanline element */ +#define RGB_GREEN 1 /* Offset of Green */ +#define RGB_BLUE 2 /* Offset of Blue */ +#define RGB_PIXELSIZE 3 /* JSAMPLEs per RGB scanline element */ + + +/* Definitions for speed-related optimizations. */ + + +/* If your compiler supports inline functions, define INLINE + * as the inline keyword; otherwise define it as empty. + */ + +#ifndef INLINE +#ifdef __GNUC__ /* for instance, GNU C knows about inline */ +#define INLINE __inline__ +#endif +#ifndef INLINE +#define INLINE /* default is to define it as empty */ +#endif +#endif + + +/* On some machines (notably 68000 series) "int" is 32 bits, but multiplying + * two 16-bit shorts is faster than multiplying two ints. Define MULTIPLIER + * as short on such a machine. MULTIPLIER must be at least 16 bits wide. + */ + +#ifndef MULTIPLIER +#define MULTIPLIER int /* type for fastest integer multiply */ +#endif + + +/* FAST_FLOAT should be either float or double, whichever is done faster + * by your compiler. (Note that this type is only used in the floating point + * DCT routines, so it only matters if you've defined DCT_FLOAT_SUPPORTED.) + * Typically, float is faster in ANSI C compilers, while double is faster in + * pre-ANSI compilers (because they insist on converting to double anyway). + * The code below therefore chooses float if we have ANSI-style prototypes. + */ + +#ifndef FAST_FLOAT +#ifdef HAVE_PROTOTYPES +#define FAST_FLOAT float +#else +#define FAST_FLOAT double +#endif +#endif + +#endif /* JPEG_INTERNAL_OPTIONS */ diff --git a/dcmjpeg/libijg16/jpegint16.h b/dcmjpeg/libijg16/jpegint16.h new file mode 100644 index 00000000..c50fa8a4 --- /dev/null +++ b/dcmjpeg/libijg16/jpegint16.h @@ -0,0 +1,373 @@ +/* + * jpegint.h + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file provides common declarations for the various JPEG modules. + * These declarations are considered internal to the JPEG library; most + * applications using the library shouldn't need to include this file. + */ + + +/* Declarations for both compression & decompression */ + +typedef enum { /* Operating modes for buffer controllers */ + JBUF_PASS_THRU, /* Plain stripwise operation */ + /* Remaining modes require a full-image buffer to have been created */ + JBUF_SAVE_SOURCE, /* Run source subobject only, save output */ + JBUF_CRANK_DEST, /* Run dest subobject only, using saved data */ + JBUF_SAVE_AND_PASS /* Run both subobjects, save output */ +} J_BUF_MODE; + +/* Values of global_state field (jdapi.c has some dependencies on ordering!) */ +#define CSTATE_START 100 /* after create_compress */ +#define CSTATE_SCANNING 101 /* start_compress done, write_scanlines OK */ +#define CSTATE_RAW_OK 102 /* start_compress done, write_raw_data OK */ +#define CSTATE_WRCOEFS 103 /* jpeg_write_coefficients done */ +#define DSTATE_START 200 /* after create_decompress */ +#define DSTATE_INHEADER 201 /* reading header markers, no SOS yet */ +#define DSTATE_READY 202 /* found SOS, ready for start_decompress */ +#define DSTATE_PRELOAD 203 /* reading multiscan file in start_decompress*/ +#define DSTATE_PRESCAN 204 /* performing dummy pass for 2-pass quant */ +#define DSTATE_SCANNING 205 /* start_decompress done, read_scanlines OK */ +#define DSTATE_RAW_OK 206 /* start_decompress done, read_raw_data OK */ +#define DSTATE_BUFIMAGE 207 /* expecting jpeg_start_output */ +#define DSTATE_BUFPOST 208 /* looking for SOS/EOI in jpeg_finish_output */ +#define DSTATE_RDCOEFS 209 /* reading file in jpeg_read_coefficients */ +#define DSTATE_STOPPING 210 /* looking for EOI in jpeg_finish_decompress */ + + +/* Declarations for compression modules */ + +/* Master control module */ +struct jpeg_comp_master { + JMETHOD(void, prepare_for_pass, (j_compress_ptr cinfo)); + JMETHOD(void, pass_startup, (j_compress_ptr cinfo)); + JMETHOD(void, finish_pass, (j_compress_ptr cinfo)); + + /* State variables made visible to other modules */ + boolean call_pass_startup; /* True if pass_startup must be called */ + boolean is_last_pass; /* True during last pass */ +}; + +/* Main buffer control (downsampled-data buffer) */ +struct jpeg_c_main_controller { + JMETHOD(void, start_pass, (j_compress_ptr cinfo, J_BUF_MODE pass_mode)); + JMETHOD(void, process_data, (j_compress_ptr cinfo, + JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, + JDIMENSION in_rows_avail)); +}; + +/* Compression preprocessing (downsampling input buffer control) */ +struct jpeg_c_prep_controller { + JMETHOD(void, start_pass, (j_compress_ptr cinfo, J_BUF_MODE pass_mode)); + JMETHOD(void, pre_process_data, (j_compress_ptr cinfo, + JSAMPARRAY input_buf, + JDIMENSION *in_row_ctr, + JDIMENSION in_rows_avail, + JSAMPIMAGE output_buf, + JDIMENSION *out_row_group_ctr, + JDIMENSION out_row_groups_avail)); +}; + +/* Compression codec (compressor proper) */ +struct jpeg_c_codec { + JMETHOD(void, entropy_start_pass, (j_compress_ptr cinfo, + boolean gather_statistics)); + JMETHOD(void, entropy_finish_pass, (j_compress_ptr cinfo)); + JMETHOD(boolean, need_optimization_pass, (j_compress_ptr cinfo)); + JMETHOD(void, start_pass, (j_compress_ptr cinfo, J_BUF_MODE pass_mode)); + JMETHOD(boolean, compress_data, (j_compress_ptr cinfo, + JSAMPIMAGE input_buf)); +}; + +/* Colorspace conversion */ +struct jpeg_color_converter { + JMETHOD(void, start_pass, (j_compress_ptr cinfo)); + JMETHOD(void, color_convert, (j_compress_ptr cinfo, + JSAMPARRAY input_buf, JSAMPIMAGE output_buf, + JDIMENSION output_row, int num_rows)); +}; + +/* Downsampling */ +struct jpeg_downsampler { + JMETHOD(void, start_pass, (j_compress_ptr cinfo)); + JMETHOD(void, downsample, (j_compress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION in_row_index, + JSAMPIMAGE output_buf, + JDIMENSION out_row_group_index)); + + boolean need_context_rows; /* TRUE if need rows above & below */ +}; + +/* Marker writing */ +struct jpeg_marker_writer { + JMETHOD(void, write_file_header, (j_compress_ptr cinfo)); + JMETHOD(void, write_frame_header, (j_compress_ptr cinfo)); + JMETHOD(void, write_scan_header, (j_compress_ptr cinfo)); + JMETHOD(void, write_file_trailer, (j_compress_ptr cinfo)); + JMETHOD(void, write_tables_only, (j_compress_ptr cinfo)); + /* These routines are exported to allow insertion of extra markers */ + /* Probably only COM and APPn markers should be written this way */ + JMETHOD(void, write_marker_header, (j_compress_ptr cinfo, int marker, + unsigned int datalen)); + JMETHOD(void, write_marker_byte, (j_compress_ptr cinfo, int val)); +}; + + +/* Declarations for decompression modules */ + +/* Master control module */ +struct jpeg_decomp_master { + JMETHOD(void, prepare_for_output_pass, (j_decompress_ptr cinfo)); + JMETHOD(void, finish_output_pass, (j_decompress_ptr cinfo)); + + /* State variables made visible to other modules */ + boolean is_dummy_pass; /* True during 1st pass for 2-pass quant */ +}; + +/* Input control module */ +struct jpeg_input_controller { + JMETHOD(int, consume_input, (j_decompress_ptr cinfo)); + JMETHOD(void, reset_input_controller, (j_decompress_ptr cinfo)); + JMETHOD(void, start_input_pass, (j_decompress_ptr cinfo)); + JMETHOD(void, finish_input_pass, (j_decompress_ptr cinfo)); + + /* State variables made visible to other modules */ + boolean has_multiple_scans; /* True if file has multiple scans */ + boolean eoi_reached; /* True when EOI has been consumed */ +}; + +/* Main buffer control (downsampled-data buffer) */ +struct jpeg_d_main_controller { + JMETHOD(void, start_pass, (j_decompress_ptr cinfo, J_BUF_MODE pass_mode)); + JMETHOD(void, process_data, (j_decompress_ptr cinfo, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail)); +}; + +/* Decompression codec (decompressor proper) */ +struct jpeg_d_codec { + JMETHOD(void, calc_output_dimensions, (j_decompress_ptr cinfo)); + JMETHOD(void, start_input_pass, (j_decompress_ptr cinfo)); + JMETHOD(int, consume_data, (j_decompress_ptr cinfo)); + JMETHOD(void, start_output_pass, (j_decompress_ptr cinfo)); + JMETHOD(int, decompress_data, (j_decompress_ptr cinfo, + JSAMPIMAGE output_buf)); +}; + +/* Decompression postprocessing (color quantization buffer control) */ +struct jpeg_d_post_controller { + JMETHOD(void, start_pass, (j_decompress_ptr cinfo, J_BUF_MODE pass_mode)); + JMETHOD(void, post_process_data, (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, + JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + JSAMPARRAY output_buf, + JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail)); +}; + +/* Marker reading & parsing */ +struct jpeg_marker_reader { + JMETHOD(void, reset_marker_reader, (j_decompress_ptr cinfo)); + /* Read markers until SOS or EOI. + * Returns same codes as are defined for jpeg_consume_input: + * JPEG_SUSPENDED, JPEG_REACHED_SOS, or JPEG_REACHED_EOI. + */ + JMETHOD(int, read_markers, (j_decompress_ptr cinfo)); + /* Read a restart marker --- exported for use by entropy decoder only */ + jpeg_marker_parser_method read_restart_marker; + + /* State of marker reader --- nominally internal, but applications + * supplying COM or APPn handlers might like to know the state. + */ + boolean saw_SOI; /* found SOI? */ + boolean saw_SOF; /* found SOF? */ + int next_restart_num; /* next restart number expected (0-7) */ + unsigned int discarded_bytes; /* # of bytes skipped looking for a marker */ +}; + +/* Upsampling (note that upsampler must also call color converter) */ +struct jpeg_upsampler { + JMETHOD(void, start_pass, (j_decompress_ptr cinfo)); + JMETHOD(void, upsample, (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, + JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + JSAMPARRAY output_buf, + JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail)); + + boolean need_context_rows; /* TRUE if need rows above & below */ +}; + +/* Colorspace conversion */ +struct jpeg_color_deconverter { + JMETHOD(void, start_pass, (j_decompress_ptr cinfo)); + JMETHOD(void, color_convert, (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION input_row, + JSAMPARRAY output_buf, int num_rows)); +}; + +/* Color quantization or color precision reduction */ +struct jpeg_color_quantizer { + JMETHOD(void, start_pass, (j_decompress_ptr cinfo, boolean is_pre_scan)); + JMETHOD(void, color_quantize, (j_decompress_ptr cinfo, + JSAMPARRAY input_buf, JSAMPARRAY output_buf, + int num_rows)); + JMETHOD(void, finish_pass, (j_decompress_ptr cinfo)); + JMETHOD(void, new_color_map, (j_decompress_ptr cinfo)); +}; + + +/* Miscellaneous useful macros */ + +#undef MAX +#define MAX(a,b) ((a) > (b) ? (a) : (b)) +#undef MIN +#define MIN(a,b) ((a) < (b) ? (a) : (b)) + + +/* We assume that right shift corresponds to signed division by 2 with + * rounding towards minus infinity. This is correct for typical "arithmetic + * shift" instructions that shift in copies of the sign bit. But some + * C compilers implement >> with an unsigned shift. For these machines you + * must define RIGHT_SHIFT_IS_UNSIGNED. + * RIGHT_SHIFT provides a proper signed right shift of an IJG_INT32 quantity. + * It is only applied with constant shift counts. SHIFT_TEMPS must be + * included in the variables of any routine using RIGHT_SHIFT. + */ + +#ifdef RIGHT_SHIFT_IS_UNSIGNED +#define SHIFT_TEMPS IJG_INT32 shift_temp; +#define RIGHT_SHIFT(x,shft) \ + ((shift_temp = (x)) < 0 ? \ + (shift_temp >> (shft)) | ((~((IJG_INT32) 0)) << (32-(shft))) : \ + (shift_temp >> (shft))) +#else +#define SHIFT_TEMPS +#define RIGHT_SHIFT(x,shft) ((x) >> (shft)) +#endif + + +/* Short forms of external names for systems with brain-damaged linkers. */ + +#ifdef NEED_SHORT_EXTERNAL_NAMES +#define jinit_c_codec jinit16_c_codec +#define jinit_c_diff_controller jinit16_c_diff_controller +#define jinit_lossy_c_codec jinit16_lossy_c_codec +#define jinit_lossless_c_codec jinit16_lossless_c_codec +#define jinit_compress_master jinit16_compress_master +#define jinit_c_master_control jinit16_c_master_control +#define jinit_c_main_controller jinit16_c_main_controller +#define jinit_c_prep_controller jinit16_c_prep_controller +#define jinit_c_coef_controller jinit16_c_coef_controller +#define jinit_color_converter jinit16_color_converter +#define jinit_downsampler jinit16_downsampler +#define jinit_forward_dct jinit16_forward_dct +#define jinit_shuff_encoder jinit16_shuff_encoder +#define jinit_phuff_encoder jinit16_phuff_encoder +#ifdef WITH_ARITHMETIC_PATCH +#define jinit_arith_encoder jinit16_arith_encoder +#endif +#define jinit_marker_writer jinit16_marker_writer +#define jinit_d_codec jinit16_d_codec +#define jinit_lossy_d_codec jinit16_lossy_d_codec +#define jinit_lossless_d_codec jinit16_lossless_d_codec +#define jinit_master_decompress jinit16_master_decompress +#define jinit_d_main_controller jinit16_d_main_controller +#define jinit_d_coef_controller jinit16_d_coef_controller +#define jinit_d_diff_controller jinit16_d_diff_controller +#define jinit_d_post_controller jinit16_d_post_controller +#define jinit_input_controller jinit16_input_controller +#define jinit_marker_reader jinit16_marker_reader +#define jinit_shuff_decoder jinit16_shuff_decoder +#define jinit_phuff_decoder jinit16_phuff_decoder +#ifdef WITH_ARITHMETIC_PATCH +#define jinit_arith_decoder jinit16_arith_decoder +#endif +#define jinit_lhuff_decoder jinit16_lhuff_decoder +#define jinit_undifferencer jinit16_undifferencer +#define jinit_d_scaler jinit16_d_scaler +#define jinit_inverse_dct jinit16_inverse_dct +#define jinit_upsampler jinit16_upsampler +#define jinit_color_deconverter jinit16_color_deconverter +#define jinit_1pass_quantizer jinit16_1pass_quantizer +#define jinit_2pass_quantizer jinit16_2pass_quantizer +#define jinit_merged_upsampler jinit16_merged_upsampler +#define jinit_memory_mgr jinit16_memory_mgr +#define jdiv_round_up jdiv16_round_up +#define jround_up jround16_up +#define jcopy_sample_rows jcopy16_sample_rows +#define jcopy_block_row jcopy16_block_row +#define jzero_far jzero16_far +#define jpeg_zigzag_order jpeg16_zigzag_order +#define jpeg_natural_order jpeg16_natural_order +#endif /* NEED_SHORT_EXTERNAL_NAMES */ + + +/* Compression module initialization routines */ +EXTERN(void) jinit_c_codec JPP((j_compress_ptr cinfo)); +EXTERN(void) jinit_c_diff_controller JPP((j_compress_ptr cinfo, boolean need_full_buffer)); +EXTERN(void) jinit_compress_master JPP((j_compress_ptr cinfo)); +EXTERN(void) jinit_c_master_control JPP((j_compress_ptr cinfo, + boolean transcode_only)); +EXTERN(void) jinit_c_main_controller JPP((j_compress_ptr cinfo, + boolean need_full_buffer)); +EXTERN(void) jinit_c_prep_controller JPP((j_compress_ptr cinfo, + boolean need_full_buffer)); +EXTERN(void) jinit_compressor JPP((j_compress_ptr cinfo)); +EXTERN(void) jinit_color_converter JPP((j_compress_ptr cinfo)); +EXTERN(void) jinit_downsampler JPP((j_compress_ptr cinfo)); +EXTERN(void) jinit_marker_writer JPP((j_compress_ptr cinfo)); +#ifdef WITH_ARITHMETIC_PATCH +EXTERN(void) jinit_arith_encoder JPP((j_compress_ptr cinfo)); +#endif +/* Decompression module initialization routines */ +EXTERN(void) jinit_d_codec JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_d_diff_controller JPP((j_decompress_ptr cinfo, boolean need_full_buffer)); +EXTERN(void) jinit_master_decompress JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_d_main_controller JPP((j_decompress_ptr cinfo, + boolean need_full_buffer)); +EXTERN(void) jinit_decompressor JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_d_post_controller JPP((j_decompress_ptr cinfo, + boolean need_full_buffer)); +EXTERN(void) jinit_input_controller JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_marker_reader JPP((j_decompress_ptr cinfo)); +#ifdef WITH_ARITHMETIC_PATCH +EXTERN(void) jinit_arith_decoder JPP((j_decompress_ptr cinfo)); +#endif +EXTERN(void) jinit_upsampler JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_color_deconverter JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_1pass_quantizer JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_2pass_quantizer JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_merged_upsampler JPP((j_decompress_ptr cinfo)); +/* Memory manager initialization */ +EXTERN(void) jinit_memory_mgr JPP((j_common_ptr cinfo)); + +/* Utility routines in jutils.c */ +EXTERN(long) jdiv_round_up JPP((long a, long b)); +EXTERN(long) jround_up JPP((long a, long b)); +EXTERN(void) jcopy_sample_rows JPP((JSAMPARRAY input_array, int source_row, + JSAMPARRAY output_array, int dest_row, + int num_rows, JDIMENSION num_cols)); +EXTERN(void) jcopy_block_row JPP((JBLOCKROW input_row, JBLOCKROW output_row, + JDIMENSION num_blocks)); +EXTERN(void) jzero_far JPP((void FAR * target, size_t bytestozero)); +/* Constant tables in jutils.c */ +#if 0 /* This table is not actually needed in v6a */ +extern const int jpeg_zigzag_order[]; /* natural coef order to zigzag order */ +#endif +extern const int jpeg_natural_order[]; /* zigzag coef order to natural order */ + +/* Suppress undefined-structure complaints if necessary. */ + +#ifdef INCOMPLETE_TYPES_BROKEN +#ifndef AM_MEMORY_MANAGER /* only jmemmgr.c defines these */ +struct jvirt_sarray_control { long dummy; }; +struct jvirt_barray_control { long dummy; }; +#endif +#endif /* INCOMPLETE_TYPES_BROKEN */ diff --git a/dcmjpeg/libijg16/jpeglib16.h b/dcmjpeg/libijg16/jpeglib16.h new file mode 100644 index 00000000..7c6c7198 --- /dev/null +++ b/dcmjpeg/libijg16/jpeglib16.h @@ -0,0 +1,1208 @@ +/* + * jpeglib.h + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file defines the application interface for the JPEG library. + * Most applications using the library need only include this file, + * and perhaps jerror.h if they want to know the exact error codes. + */ + +#ifndef JPEGLIB_H +#define JPEGLIB_H + +/* + * First we include the configuration files that record how this + * installation of the JPEG library is set up. jconfig.h can be + * generated automatically for many systems. jmorecfg.h contains + * manual configuration options that most people need not worry about. + */ + +#ifndef JCONFIG_INCLUDED /* in case jinclude.h already did */ +#include "jconfig16.h" /* widely used configuration options */ +#endif +#include "jmorecfg16.h" /* seldom changed options */ + + +/* Version ID for the JPEG library. + * Might be useful for tests like "#if JPEG_LIB_VERSION >= 60". + */ + +#define JPEG_LIB_VERSION 62 /* Version 6b */ + + +/* Various constants determining the sizes of things. + * All of these are specified by the JPEG standard, so don't change them + * if you want to be compatible. + */ + +#define DCTSIZE 8 /* The basic DCT block is 8x8 samples */ +#define DCTSIZE2 64 /* DCTSIZE squared; # of elements in a block */ +#define NUM_QUANT_TBLS 4 /* Quantization tables are numbered 0..3 */ +#define NUM_HUFF_TBLS 4 /* Huffman tables are numbered 0..3 */ +#define NUM_ARITH_TBLS 16 /* Arith-coding tables are numbered 0..15 */ +#define MAX_COMPS_IN_SCAN 4 /* JPEG limit on # of components in one scan */ +#define MAX_SAMP_FACTOR 4 /* JPEG limit on sampling factors */ +/* Unfortunately, some bozo at Adobe saw no reason to be bound by the standard; + * the PostScript DCT filter can emit files with many more than 10 data units + * per MCU. + * If you happen to run across such a file, you can up D_MAX_DATA_UNITS_IN_MCU + * to handle it. We even let you do this from the jconfig.h file. However, + * we strongly discourage changing C_MAX_DATA_UNITS_IN_MCU; just because Adobe + * sometimes emits noncompliant files doesn't mean you should too. + */ +#define C_MAX_DATA_UNITS_IN_MCU 10 /* compressor's limit on data units/MCU */ +#ifndef D_MAX_DATA_UNITS_IN_MCU +#define D_MAX_DATA_UNITS_IN_MCU 10 /* decompressor's limit on data units/MCU */ +#endif + + +/* Data structures for images (arrays of samples and of DCT coefficients). + * On 80x86 machines, the image arrays are too big for near pointers, + * but the pointer arrays can fit in near memory. + */ + +typedef JSAMPLE FAR *JSAMPROW; /* ptr to one image row of pixel samples. */ +typedef JSAMPROW *JSAMPARRAY; /* ptr to some rows (a 2-D sample array) */ +typedef JSAMPARRAY *JSAMPIMAGE; /* a 3-D sample array: top index is color */ + +typedef JCOEF JBLOCK[DCTSIZE2]; /* one block of coefficients */ +typedef JBLOCK FAR *JBLOCKROW; /* pointer to one row of coefficient blocks */ +typedef JBLOCKROW *JBLOCKARRAY; /* a 2-D array of coefficient blocks */ +typedef JBLOCKARRAY *JBLOCKIMAGE; /* a 3-D array of coefficient blocks */ + +typedef JCOEF FAR *JCOEFPTR; /* useful in a couple of places */ + +typedef JDIFF FAR *JDIFFROW; /* pointer to one row of difference values */ +typedef JDIFFROW *JDIFFARRAY; /* ptr to some rows (a 2-D diff array) */ +typedef JDIFFARRAY *JDIFFIMAGE; /* a 3-D diff array: top index is color */ + + +/* Types for JPEG compression parameters and working tables. */ + + +/* DCT coefficient quantization tables. */ + +typedef struct { + /* This array gives the coefficient quantizers in natural array order + * (not the zigzag order in which they are stored in a JPEG DQT marker). + * CAUTION: IJG versions prior to v6a kept this array in zigzag order. + */ + UINT16 quantval[DCTSIZE2]; /* quantization step for each coefficient */ + /* This field is used only during compression. It's initialized FALSE when + * the table is created, and set TRUE when it's been output to the file. + * You could suppress output of a table by setting this to TRUE. + * (See jpeg_suppress_tables for an example.) + */ + boolean sent_table; /* TRUE when table has been output */ +} JQUANT_TBL; + + +/* Huffman coding tables. */ + +typedef struct { + /* These two fields directly represent the contents of a JPEG DHT marker */ + UINT8 bits[17]; /* bits[k] = # of symbols with codes of */ + /* length k bits; bits[0] is unused */ + UINT8 huffval[256]; /* The symbols, in order of incr code length */ + /* This field is used only during compression. It's initialized FALSE when + * the table is created, and set TRUE when it's been output to the file. + * You could suppress output of a table by setting this to TRUE. + * (See jpeg_suppress_tables for an example.) + */ + boolean sent_table; /* TRUE when table has been output */ +} JHUFF_TBL; + + +/* Basic info about one component (color channel). */ + +typedef struct { + /* These values are fixed over the whole image. */ + /* For compression, they must be supplied by parameter setup; */ + /* for decompression, they are read from the SOF marker. */ + int component_id; /* identifier for this component (0..255) */ + int component_index; /* its index in SOF or cinfo->comp_info[] */ + int h_samp_factor; /* horizontal sampling factor (1..4) */ + int v_samp_factor; /* vertical sampling factor (1..4) */ + int quant_tbl_no; /* quantization table selector (0..3) */ + /* These values may vary between scans. */ + /* For compression, they must be supplied by parameter setup; */ + /* for decompression, they are read from the SOS marker. */ + /* The decompressor output side may not use these variables. */ + int dc_tbl_no; /* DC entropy table selector (0..3) */ + int ac_tbl_no; /* AC entropy table selector (0..3) */ + + /* Remaining fields should be treated as private by applications. */ + + /* These values are computed during compression or decompression startup: */ + /* Component's size in data units. + * Any dummy data units added to complete an MCU are not counted; therefore + * these values do not depend on whether a scan is interleaved or not. + */ + JDIMENSION width_in_data_units; + JDIMENSION height_in_data_units; + /* Size of a data unit in/output by the codec (in samples). Always + * data_unit for compression. For decompression this is the size of the + * output from one data_unit, reflecting any processing performed by the + * codec. For example, in the DCT-based codec, scaling may be applied + * during the IDCT step. Values of 1,2,4,8 are likely to be supported. + * Note that different components may have different codec_data_unit sizes. + */ + int codec_data_unit; + /* The downsampled dimensions are the component's actual, unpadded number + * of samples at the main buffer (preprocessing/compression interface), thus + * downsampled_width = ceil(image_width * Hi/Hmax) + * and similarly for height. For decompression, codec-based processing is + * included (ie, IDCT scaling), so + * downsampled_width = ceil(image_width * Hi/Hmax * codec_data_unit/data_unit) + */ + JDIMENSION downsampled_width; /* actual width in samples */ + JDIMENSION downsampled_height; /* actual height in samples */ + /* This flag is used only for decompression. In cases where some of the + * components will be ignored (eg grayscale output from YCbCr image), + * we can skip most computations for the unused components. + */ + boolean component_needed; /* do we need the value of this component? */ + + /* These values are computed before starting a scan of the component. */ + /* The decompressor output side may not use these variables. */ + int MCU_width; /* number of data units per MCU, horizontally */ + int MCU_height; /* number of data units per MCU, vertically */ + int MCU_data_units; /* MCU_width * MCU_height */ + int MCU_sample_width; /* MCU width in samples, MCU_width*codec_data_unit */ + int last_col_width; /* # of non-dummy data_units across in last MCU */ + int last_row_height; /* # of non-dummy data_units down in last MCU */ + + /* Saved quantization table for component; NULL if none yet saved. + * See jdinput.c comments about the need for this information. + * This field is currently used only for decompression. + */ + JQUANT_TBL * quant_table; + + /* Private per-component storage for DCT or IDCT subsystem. */ + void * dct_table; +} jpeg_component_info; + + +/* The script for encoding a multiple-scan file is an array of these: */ + +typedef struct { + int comps_in_scan; /* number of components encoded in this scan */ + int component_index[MAX_COMPS_IN_SCAN]; /* their SOF/comp_info[] indexes */ + int Ss, Se; /* progressive JPEG spectral selection parms + lossless JPEG predictor select parm (Ss) */ + int Ah, Al; /* progressive JPEG successive approx. parms + lossless JPEG point transform parm (Al) */ +} jpeg_scan_info; + +/* The decompressor can save APPn and COM markers in a list of these: */ + +typedef struct jpeg_marker_struct FAR * jpeg_saved_marker_ptr; + +struct jpeg_marker_struct { + jpeg_saved_marker_ptr next; /* next in list, or NULL */ + UINT8 marker; /* marker code: JPEG_COM, or JPEG_APP0+n */ + unsigned int original_length; /* # bytes of data in the file */ + unsigned int data_length; /* # bytes of data saved at data[] */ + JOCTET FAR * data; /* the data contained in the marker */ + /* the marker length word is not counted in data_length or original_length */ +}; + +/* Known codec processes. */ + +typedef enum { + JPROC_SEQUENTIAL, /* baseline/extended sequential DCT */ + JPROC_PROGRESSIVE, /* progressive DCT */ + JPROC_LOSSLESS /* lossless (sequential) */ +} J_CODEC_PROCESS; + +/* Known color spaces. */ + +typedef enum { + JCS_UNKNOWN, /* error/unspecified */ + JCS_GRAYSCALE, /* monochrome */ + JCS_RGB, /* red/green/blue */ + JCS_YCbCr, /* Y/Cb/Cr (also known as YUV) */ + JCS_CMYK, /* C/M/Y/K */ + JCS_YCCK /* Y/Cb/Cr/K */ +} J_COLOR_SPACE; + +/* DCT/IDCT algorithm options. */ + +typedef enum { + JDCT_ISLOW, /* slow but accurate integer algorithm */ + JDCT_IFAST, /* faster, less accurate integer method */ + JDCT_FLOAT /* floating-point: accurate, fast on fast HW */ +} J_DCT_METHOD; + +#ifndef JDCT_DEFAULT /* may be overridden in jconfig.h */ +#define JDCT_DEFAULT JDCT_ISLOW +#endif +#ifndef JDCT_FASTEST /* may be overridden in jconfig.h */ +#define JDCT_FASTEST JDCT_IFAST +#endif + +/* Dithering options for decompression. */ + +typedef enum { + JDITHER_NONE, /* no dithering */ + JDITHER_ORDERED, /* simple ordered dither */ + JDITHER_FS /* Floyd-Steinberg error diffusion dither */ +} J_DITHER_MODE; + + +/* Common fields between JPEG compression and decompression master structs. */ + +#define jpeg_common_fields \ + struct jpeg_error_mgr * err; /* Error handler module */\ + struct jpeg_memory_mgr * mem; /* Memory manager module */\ + struct jpeg_progress_mgr * progress; /* Progress monitor, or NULL if none */\ + void * client_data; /* Available for use by application */\ + boolean is_decompressor; /* So common code can tell which is which */\ + int global_state /* For checking call sequence validity */ + +/* Routines that are to be used by both halves of the library are declared + * to receive a pointer to this structure. There are no actual instances of + * jpeg_common_struct, only of jpeg_compress_struct and jpeg_decompress_struct. + */ +struct jpeg_common_struct { + jpeg_common_fields; /* Fields common to both master struct types */ + /* Additional fields follow in an actual jpeg_compress_struct or + * jpeg_decompress_struct. All three structs must agree on these + * initial fields! (This would be a lot cleaner in C++.) + */ +}; + +typedef struct jpeg_common_struct * j_common_ptr; +typedef struct jpeg_compress_struct * j_compress_ptr; +typedef struct jpeg_decompress_struct * j_decompress_ptr; + + +/* Master record for a compression instance */ + +struct jpeg_compress_struct { + jpeg_common_fields; /* Fields shared with jpeg_decompress_struct */ + + /* Destination for compressed data */ + struct jpeg_destination_mgr * dest; + + /* Description of source image --- these fields must be filled in by + * outer application before starting compression. in_color_space must + * be correct before you can even call jpeg_set_defaults(). + */ + + JDIMENSION image_width; /* input image width */ + JDIMENSION image_height; /* input image height */ + int input_components; /* # of color components in input image */ + J_COLOR_SPACE in_color_space; /* colorspace of input image */ + + double input_gamma; /* image gamma of input image */ + + /* Compression parameters --- these fields must be set before calling + * jpeg_start_compress(). We recommend calling jpeg_set_defaults() to + * initialize everything to reasonable defaults, then changing anything + * the application specifically wants to change. That way you won't get + * burnt when new parameters are added. Also note that there are several + * helper routines to simplify changing parameters. + */ + + boolean lossless; /* TRUE=lossless encoding, FALSE=lossy */ + + int data_precision; /* bits of precision in image data */ + + int num_components; /* # of color components in JPEG image */ + J_COLOR_SPACE jpeg_color_space; /* colorspace of JPEG image */ + + jpeg_component_info * comp_info; + /* comp_info[i] describes component that appears i'th in SOF */ + + JQUANT_TBL * quant_tbl_ptrs[NUM_QUANT_TBLS]; + /* ptrs to coefficient quantization tables, or NULL if not defined */ + + JHUFF_TBL * dc_huff_tbl_ptrs[NUM_HUFF_TBLS]; + JHUFF_TBL * ac_huff_tbl_ptrs[NUM_HUFF_TBLS]; + /* ptrs to Huffman coding tables, or NULL if not defined */ + + UINT8 arith_dc_L[NUM_ARITH_TBLS]; /* L values for DC arith-coding tables */ + UINT8 arith_dc_U[NUM_ARITH_TBLS]; /* U values for DC arith-coding tables */ + UINT8 arith_ac_K[NUM_ARITH_TBLS]; /* Kx values for AC arith-coding tables */ + + int num_scans; /* # of entries in scan_info array */ + const jpeg_scan_info * scan_info; /* script for multi-scan file, or NULL */ + /* The default value of scan_info is NULL, which causes a single-scan + * sequential JPEG file to be emitted. To create a multi-scan file, + * set num_scans and scan_info to point to an array of scan definitions. + */ + + boolean raw_data_in; /* TRUE=caller supplies downsampled data */ + boolean arith_code; /* TRUE=arithmetic coding, FALSE=Huffman */ + boolean optimize_coding; /* TRUE=optimize entropy encoding parms */ + boolean CCIR601_sampling; /* TRUE=first samples are cosited */ + int smoothing_factor; /* 1..100, or 0 for no input smoothing */ + J_DCT_METHOD dct_method; /* DCT algorithm selector */ + + /* The restart interval can be specified in absolute MCUs by setting + * restart_interval, or in MCU rows by setting restart_in_rows + * (in which case the correct restart_interval will be figured + * for each scan). + */ + unsigned int restart_interval; /* MCUs per restart, or 0 for no restart */ + int restart_in_rows; /* if > 0, MCU rows per restart interval */ + + /* Parameters controlling emission of special markers. */ + + boolean write_JFIF_header; /* should a JFIF marker be written? */ + UINT8 JFIF_major_version; /* What to write for the JFIF version number */ + UINT8 JFIF_minor_version; + /* These three values are not used by the JPEG code, merely copied */ + /* into the JFIF APP0 marker. density_unit can be 0 for unknown, */ + /* 1 for dots/inch, or 2 for dots/cm. Note that the pixel aspect */ + /* ratio is defined by X_density/Y_density even when density_unit=0. */ + UINT8 density_unit; /* JFIF code for pixel size units */ + UINT16 X_density; /* Horizontal pixel density */ + UINT16 Y_density; /* Vertical pixel density */ + boolean write_Adobe_marker; /* should an Adobe marker be written? */ + + /* State variable: index of next scanline to be written to + * jpeg_write_scanlines(). Application may use this to control its + * processing loop, e.g., "while (next_scanline < image_height)". + */ + + JDIMENSION next_scanline; /* 0 .. image_height-1 */ + + /* Remaining fields are known throughout compressor, but generally + * should not be touched by a surrounding application. + */ + + /* + * These fields are computed during compression startup + */ + int data_unit; /* size of data unit in samples */ + J_CODEC_PROCESS process; /* encoding process of JPEG image */ + + int max_h_samp_factor; /* largest h_samp_factor */ + int max_v_samp_factor; /* largest v_samp_factor */ + + JDIMENSION total_iMCU_rows; /* # of iMCU rows to be input to codec */ + /* The codec receives data in units of MCU rows as defined for fully + * interleaved scans (whether the JPEG file is interleaved or not). + * There are v_samp_factor * data_unit sample rows of each component in an + * "iMCU" (interleaved MCU) row. + */ + + /* + * These fields are valid during any one scan. + * They describe the components and MCUs actually appearing in the scan. + */ + int comps_in_scan; /* # of JPEG components in this scan */ + jpeg_component_info * cur_comp_info[MAX_COMPS_IN_SCAN]; + /* *cur_comp_info[i] describes component that appears i'th in SOS */ + + JDIMENSION MCUs_per_row; /* # of MCUs across the image */ + JDIMENSION MCU_rows_in_scan; /* # of MCU rows in the image */ + + int data_units_in_MCU; /* # of data units per MCU */ + int MCU_membership[C_MAX_DATA_UNITS_IN_MCU]; + /* MCU_membership[i] is index in cur_comp_info of component owning */ + /* i'th block in an MCU */ + + int Ss, Se, Ah, Al; /* progressive/lossless JPEG parameters for scan */ + + /* + * Links to compression subobjects (methods and private variables of modules) + */ + struct jpeg_comp_master * master; + struct jpeg_c_main_controller * main; + struct jpeg_c_prep_controller * prep; + struct jpeg_c_codec * codec; + struct jpeg_marker_writer * marker; + struct jpeg_color_converter * cconvert; + struct jpeg_downsampler * downsample; + jpeg_scan_info * script_space; /* workspace for jpeg_simple_progression */ + int script_space_size; +}; + + +/* Master record for a decompression instance */ + +struct jpeg_decompress_struct { + jpeg_common_fields; /* Fields shared with jpeg_compress_struct */ + + /* Source of compressed data */ + struct jpeg_source_mgr * src; + + /* Basic description of image --- filled in by jpeg_read_header(). */ + /* Application may inspect these values to decide how to process image. */ + + JDIMENSION image_width; /* nominal image width (from SOF marker) */ + JDIMENSION image_height; /* nominal image height */ + int num_components; /* # of color components in JPEG image */ + J_COLOR_SPACE jpeg_color_space; /* colorspace of JPEG image */ + + /* Decompression processing parameters --- these fields must be set before + * calling jpeg_start_decompress(). Note that jpeg_read_header() initializes + * them to default values. + */ + + J_COLOR_SPACE out_color_space; /* colorspace for output */ + + unsigned int scale_num, scale_denom; /* fraction by which to scale image */ + + double output_gamma; /* image gamma wanted in output */ + + boolean buffered_image; /* TRUE=multiple output passes */ + boolean raw_data_out; /* TRUE=downsampled data wanted */ + + J_DCT_METHOD dct_method; /* IDCT algorithm selector */ + boolean do_fancy_upsampling; /* TRUE=apply fancy upsampling */ + boolean do_block_smoothing; /* TRUE=apply interblock smoothing */ + + boolean quantize_colors; /* TRUE=colormapped output wanted */ + /* the following are ignored if not quantize_colors: */ + J_DITHER_MODE dither_mode; /* type of color dithering to use */ + boolean two_pass_quantize; /* TRUE=use two-pass color quantization */ + int desired_number_of_colors; /* max # colors to use in created colormap */ + /* these are significant only in buffered-image mode: */ + boolean enable_1pass_quant; /* enable future use of 1-pass quantizer */ + boolean enable_external_quant;/* enable future use of external colormap */ + boolean enable_2pass_quant; /* enable future use of 2-pass quantizer */ + + /* Description of actual output image that will be returned to application. + * These fields are computed by jpeg_start_decompress(). + * You can also use jpeg_calc_output_dimensions() to determine these values + * in advance of calling jpeg_start_decompress(). + */ + + JDIMENSION output_width; /* scaled image width */ + JDIMENSION output_height; /* scaled image height */ + int out_color_components; /* # of color components in out_color_space */ + int output_components; /* # of color components returned */ + /* output_components is 1 (a colormap index) when quantizing colors; + * otherwise it equals out_color_components. + */ + int rec_outbuf_height; /* min recommended height of scanline buffer */ + /* If the buffer passed to jpeg_read_scanlines() is less than this many rows + * high, space and time will be wasted due to unnecessary data copying. + * Usually rec_outbuf_height will be 1 or 2, at most 4. + */ + + /* When quantizing colors, the output colormap is described by these fields. + * The application can supply a colormap by setting colormap non-NULL before + * calling jpeg_start_decompress; otherwise a colormap is created during + * jpeg_start_decompress or jpeg_start_output. + * The map has out_color_components rows and actual_number_of_colors columns. + */ + int actual_number_of_colors; /* number of entries in use */ + JSAMPARRAY colormap; /* The color map as a 2-D pixel array */ + + /* State variables: these variables indicate the progress of decompression. + * The application may examine these but must not modify them. + */ + + /* Row index of next scanline to be read from jpeg_read_scanlines(). + * Application may use this to control its processing loop, e.g., + * "while (output_scanline < output_height)". + */ + JDIMENSION output_scanline; /* 0 .. output_height-1 */ + + /* Current input scan number and number of iMCU rows completed in scan. + * These indicate the progress of the decompressor input side. + */ + int input_scan_number; /* Number of SOS markers seen so far */ + JDIMENSION input_iMCU_row; /* Number of iMCU rows completed */ + + /* The "output scan number" is the notional scan being displayed by the + * output side. The decompressor will not allow output scan/row number + * to get ahead of input scan/row, but it can fall arbitrarily far behind. + */ + int output_scan_number; /* Nominal scan number being displayed */ + JDIMENSION output_iMCU_row; /* Number of iMCU rows read */ + + /* Current progression status. coef_bits[c][i] indicates the precision + * with which component c's DCT coefficient i (in zigzag order) is known. + * It is -1 when no data has yet been received, otherwise it is the point + * transform (shift) value for the most recent scan of the coefficient + * (thus, 0 at completion of the progression). + * This pointer is NULL when reading a non-progressive file. + */ + int (*coef_bits)[DCTSIZE2]; /* -1 or current Al value for each coef */ + + /* Internal JPEG parameters --- the application usually need not look at + * these fields. Note that the decompressor output side may not use + * any parameters that can change between scans. + */ + + /* Quantization and Huffman tables are carried forward across input + * datastreams when processing abbreviated JPEG datastreams. + */ + + JQUANT_TBL * quant_tbl_ptrs[NUM_QUANT_TBLS]; + /* ptrs to coefficient quantization tables, or NULL if not defined */ + + JHUFF_TBL * dc_huff_tbl_ptrs[NUM_HUFF_TBLS]; + JHUFF_TBL * ac_huff_tbl_ptrs[NUM_HUFF_TBLS]; + /* ptrs to Huffman coding tables, or NULL if not defined */ + + /* These parameters are never carried across datastreams, since they + * are given in SOF/SOS markers or defined to be reset by SOI. + */ + + int data_precision; /* bits of precision in image data */ + + jpeg_component_info * comp_info; + /* comp_info[i] describes component that appears i'th in SOF */ + + boolean arith_code; /* TRUE=arithmetic coding, FALSE=Huffman */ + + UINT8 arith_dc_L[NUM_ARITH_TBLS]; /* L values for DC arith-coding tables */ + UINT8 arith_dc_U[NUM_ARITH_TBLS]; /* U values for DC arith-coding tables */ + UINT8 arith_ac_K[NUM_ARITH_TBLS]; /* Kx values for AC arith-coding tables */ + + unsigned int restart_interval; /* MCUs per restart interval, or 0 for no restart */ + + /* These fields record data obtained from optional markers recognized by + * the JPEG library. + */ + boolean saw_JFIF_marker; /* TRUE iff a JFIF APP0 marker was found */ + /* Data copied from JFIF marker; only valid if saw_JFIF_marker is TRUE: */ + UINT8 JFIF_major_version; /* JFIF version number */ + UINT8 JFIF_minor_version; + UINT8 density_unit; /* JFIF code for pixel size units */ + UINT16 X_density; /* Horizontal pixel density */ + UINT16 Y_density; /* Vertical pixel density */ + boolean saw_Adobe_marker; /* TRUE iff an Adobe APP14 marker was found */ + UINT8 Adobe_transform; /* Color transform code from Adobe marker */ + + boolean CCIR601_sampling; /* TRUE=first samples are cosited */ + + /* Aside from the specific data retained from APPn markers known to the + * library, the uninterpreted contents of any or all APPn and COM markers + * can be saved in a list for examination by the application. + */ + jpeg_saved_marker_ptr marker_list; /* Head of list of saved markers */ + + /* Remaining fields are known throughout decompressor, but generally + * should not be touched by a surrounding application. + */ + + /* + * These fields are computed during decompression startup + */ + int data_unit; /* size of data unit in samples */ + J_CODEC_PROCESS process; /* decoding process of JPEG image */ + + int max_h_samp_factor; /* largest h_samp_factor */ + int max_v_samp_factor; /* largest v_samp_factor */ + + int min_codec_data_unit; /* smallest codec_data_unit of any component */ + + JDIMENSION total_iMCU_rows; /* # of iMCU rows in image */ + /* The codec's input and output progress is measured in units of "iMCU" + * (interleaved MCU) rows. These are the same as MCU rows in fully + * interleaved JPEG scans, but are used whether the scan is interleaved + * or not. We define an iMCU row as v_samp_factor data_unit rows of each + * component. Therefore, the codec output contains + * v_samp_factor*codec_data_unit sample rows of a component per iMCU row. + */ + + JSAMPLE * sample_range_limit; /* table for fast range-limiting */ + + /* + * These fields are valid during any one scan. + * They describe the components and MCUs actually appearing in the scan. + * Note that the decompressor output side must not use these fields. + */ + int comps_in_scan; /* # of JPEG components in this scan */ + jpeg_component_info * cur_comp_info[MAX_COMPS_IN_SCAN]; + /* *cur_comp_info[i] describes component that appears i'th in SOS */ + + JDIMENSION MCUs_per_row; /* # of MCUs across the image */ + JDIMENSION MCU_rows_in_scan; /* # of MCU rows in the image */ + + int data_units_in_MCU; /* # of data _units per MCU */ + int MCU_membership[D_MAX_DATA_UNITS_IN_MCU]; + /* MCU_membership[i] is index in cur_comp_info of component owning */ + /* i'th data unit in an MCU */ + + int Ss, Se, Ah, Al; /* progressive/lossless JPEG parms for scan */ + + /* This field is shared between entropy decoder and marker parser. + * It is either zero or the code of a JPEG marker that has been + * read from the data source, but has not yet been processed. + */ + int unread_marker; + + /* + * Links to decompression subobjects (methods, private variables of modules) + */ + struct jpeg_decomp_master * master; + struct jpeg_d_main_controller * main; + struct jpeg_d_codec * codec; + struct jpeg_d_post_controller * post; + struct jpeg_input_controller * inputctl; + struct jpeg_marker_reader * marker; + struct jpeg_upsampler * upsample; + struct jpeg_color_deconverter * cconvert; + struct jpeg_color_quantizer * cquantize; + + /* Options that enable or disable various workarounds */ + unsigned int workaround_options; +}; + +/* constants for workaround_options in struct jpeg_decompress_struct */ +#define WORKAROUND_PREDICTOR6OVERFLOW 1 + +/* "Object" declarations for JPEG modules that may be supplied or called + * directly by the surrounding application. + * As with all objects in the JPEG library, these structs only define the + * publicly visible methods and state variables of a module. Additional + * private fields may exist after the public ones. + */ + + +/* Error handler object */ + +struct jpeg_error_mgr { + /* Error exit handler: does not return to caller */ + JMETHOD(void, error_exit, (j_common_ptr cinfo)); + /* Conditionally emit a trace or warning message */ + JMETHOD(void, emit_message, (j_common_ptr cinfo, int msg_level)); + /* Routine that actually outputs a trace or error message */ + JMETHOD(void, output_message, (j_common_ptr cinfo)); + /* Format a message string for the most recent JPEG error or message */ + JMETHOD(void, format_message, (j_common_ptr cinfo, char * buffer)); +#define JMSG_LENGTH_MAX 200 /* recommended size of format_message buffer */ + /* Reset error state variables at start of a new image */ + JMETHOD(void, reset_error_mgr, (j_common_ptr cinfo)); + + /* The message ID code and any parameters are saved here. + * A message can have one string parameter or up to 8 int parameters. + */ + int msg_code; +#define JMSG_STR_PARM_MAX 80 + union { + int i[8]; + char s[JMSG_STR_PARM_MAX]; + } msg_parm; + + /* Standard state variables for error facility */ + + int trace_level; /* max msg_level that will be displayed */ + + /* For recoverable corrupt-data errors, we emit a warning message, + * but keep going unless emit_message chooses to abort. emit_message + * should count warnings in num_warnings. The surrounding application + * can check for bad data by seeing if num_warnings is nonzero at the + * end of processing. + */ + long num_warnings; /* number of corrupt-data warnings */ + + /* These fields point to the table(s) of error message strings. + * An application can change the table pointer to switch to a different + * message list (typically, to change the language in which errors are + * reported). Some applications may wish to add additional error codes + * that will be handled by the JPEG library error mechanism; the second + * table pointer is used for this purpose. + * + * First table includes all errors generated by JPEG library itself. + * Error code 0 is reserved for a "no such error string" message. + */ + const char * const * jpeg_message_table; /* Library errors */ + int last_jpeg_message; /* Table contains strings 0..last_jpeg_message */ + /* Second table can be added by application (see cjpeg/djpeg for example). + * It contains strings numbered first_addon_message..last_addon_message. + */ + const char * const * addon_message_table; /* Non-library errors */ + int first_addon_message; /* code for first string in addon table */ + int last_addon_message; /* code for last string in addon table */ +}; + + +/* Progress monitor object */ + +struct jpeg_progress_mgr { + JMETHOD(void, progress_monitor, (j_common_ptr cinfo)); + + long pass_counter; /* work units completed in this pass */ + long pass_limit; /* total number of work units in this pass */ + int completed_passes; /* passes completed so far */ + int total_passes; /* total number of passes expected */ +}; + + +/* Data destination object for compression */ + +struct jpeg_destination_mgr { + JOCTET * next_output_byte; /* => next byte to write in buffer */ + size_t free_in_buffer; /* # of byte spaces remaining in buffer */ + + JMETHOD(void, init_destination, (j_compress_ptr cinfo)); + JMETHOD(boolean, empty_output_buffer, (j_compress_ptr cinfo)); + JMETHOD(void, term_destination, (j_compress_ptr cinfo)); +}; + + +/* Data source object for decompression */ + +struct jpeg_source_mgr { + const JOCTET * next_input_byte; /* => next byte to read from buffer */ + size_t bytes_in_buffer; /* # of bytes remaining in buffer */ + + JMETHOD(void, init_source, (j_decompress_ptr cinfo)); + JMETHOD(boolean, fill_input_buffer, (j_decompress_ptr cinfo)); + JMETHOD(void, skip_input_data, (j_decompress_ptr cinfo, long num_bytes)); + JMETHOD(boolean, resync_to_restart, (j_decompress_ptr cinfo, int desired)); + JMETHOD(void, term_source, (j_decompress_ptr cinfo)); +}; + + +/* Memory manager object. + * Allocates "small" objects (a few K total), "large" objects (tens of K), + * and "really big" objects (virtual arrays with backing store if needed). + * The memory manager does not allow individual objects to be freed; rather, + * each created object is assigned to a pool, and whole pools can be freed + * at once. This is faster and more convenient than remembering exactly what + * to free, especially where malloc()/free() are not too speedy. + * NB: alloc routines never return NULL. They exit to error_exit if not + * successful. + */ + +#define JPOOL_PERMANENT 0 /* lasts until master record is destroyed */ +#define JPOOL_IMAGE 1 /* lasts until done with image/datastream */ +#define JPOOL_NUMPOOLS 2 + +typedef struct jvirt_sarray_control * jvirt_sarray_ptr; +typedef struct jvirt_barray_control * jvirt_barray_ptr; + + +#ifdef C_LOSSLESS_SUPPORTED +#define NEED_DARRAY +#else +#ifdef D_LOSSLESS_SUPPORTED +#define NEED_DARRAY +#endif +#endif + +struct jpeg_memory_mgr { + /* Method pointers */ + JMETHOD(void *, alloc_small, (j_common_ptr cinfo, int pool_id, + size_t sizeofobject)); + JMETHOD(void FAR *, alloc_large, (j_common_ptr cinfo, int pool_id, + size_t sizeofobject)); + JMETHOD(JSAMPARRAY, alloc_sarray, (j_common_ptr cinfo, int pool_id, + JDIMENSION samplesperrow, + JDIMENSION numrows)); + JMETHOD(JBLOCKARRAY, alloc_barray, (j_common_ptr cinfo, int pool_id, + JDIMENSION blocksperrow, + JDIMENSION numrows)); +#ifdef NEED_DARRAY + JMETHOD(JDIFFARRAY, alloc_darray, (j_common_ptr cinfo, int pool_id, + JDIMENSION diffsperrow, + JDIMENSION numrows)); +#endif + JMETHOD(jvirt_sarray_ptr, request_virt_sarray, (j_common_ptr cinfo, + int pool_id, + boolean pre_zero, + JDIMENSION samplesperrow, + JDIMENSION numrows, + JDIMENSION maxaccess)); + JMETHOD(jvirt_barray_ptr, request_virt_barray, (j_common_ptr cinfo, + int pool_id, + boolean pre_zero, + JDIMENSION blocksperrow, + JDIMENSION numrows, + JDIMENSION maxaccess)); + JMETHOD(void, realize_virt_arrays, (j_common_ptr cinfo)); + JMETHOD(JSAMPARRAY, access_virt_sarray, (j_common_ptr cinfo, + jvirt_sarray_ptr ptr, + JDIMENSION start_row, + JDIMENSION num_rows, + boolean writable)); + JMETHOD(JBLOCKARRAY, access_virt_barray, (j_common_ptr cinfo, + jvirt_barray_ptr ptr, + JDIMENSION start_row, + JDIMENSION num_rows, + boolean writable)); + JMETHOD(void, free_pool, (j_common_ptr cinfo, int pool_id)); + JMETHOD(void, self_destruct, (j_common_ptr cinfo)); + + /* Limit on memory allocation for this JPEG object. (Note that this is + * merely advisory, not a guaranteed maximum; it only affects the space + * used for virtual-array buffers.) May be changed by outer application + * after creating the JPEG object. + */ + long max_memory_to_use; + + /* Maximum allocation request accepted by alloc_large. */ + long max_alloc_chunk; +}; + + +/* Routine signature for application-supplied marker processing methods. + * Need not pass marker code since it is stored in cinfo->unread_marker. + */ +typedef JMETHOD(boolean, jpeg_marker_parser_method, (j_decompress_ptr cinfo)); + + +/* Declarations for routines called by application. + * The JPP macro hides prototype parameters from compilers that can't cope. + * Note JPP requires double parentheses. + */ + +#ifdef HAVE_PROTOTYPES +#define JPP(arglist) arglist +#else +#define JPP(arglist) () +#endif + + +/* Short forms of external names for systems with brain-damaged linkers. + * We shorten external names to be unique in the first six letters, which + * is good enough for all known systems. + * (If your compiler itself needs names to be unique in less than 15 + * characters, you are out of luck. Get a better compiler.) + */ + +/* MAKE SURE THAT ALL FUNCTIONS DECLARED GLOBAL() ARE RE-DEFINED HERE! */ + +#ifdef NEED_SHORT_EXTERNAL_NAMES +#define jcopy_block_row jcopy16_block_row +#define jcopy_sample_rows jcopy16_sample_rows +#define jdiv_round_up jdiv16_round_up +#define jinit_1pass_quantizer jinit16_1pass_quantizer +#define jinit_2pass_quantizer jinit16_2pass_quantizer +#define jinit_arith_decoder jinit16_arith_decoder +#define jinit_arith_encoder jinit16_arith_encoder +#define jinit_c_codec jinit16_c_codec +#define jinit_c_coef_controller jinit16_c_coef_controller +#define jinit_c_diff_controller jinit16_c_diff_controller +#define jinit_c_main_controller jinit16_c_main_controller +#define jinit_c_master_control jinit16_c_master_control +#define jinit_c_prep_controller jinit16_c_prep_controller +#define jinit_c_scaler jinit16_c_scaler +#define jinit_color_converter jinit16_color_converter +#define jinit_color_deconverter jinit16_color_deconverter +#define jinit_compress_master jinit16_compress_master +#define jinit_d_codec jinit16_d_codec +#define jinit_d_coef_controller jinit16_d_coef_controller +#define jinit_d_diff_controller jinit16_d_diff_controller +#define jinit_d_main_controller jinit16_d_main_controller +#define jinit_d_post_controller jinit16_d_post_controller +#define jinit_d_post_controller jinit16_d_post_controller +#define jinit_d_scaler jinit16_d_scaler +#define jinit_differencer jinit16_differencer +#define jinit_downsampler jinit16_downsampler +#define jinit_forward_dct jinit16_forward_dct +#define jinit_input_controller jinit16_input_controller +#define jinit_inverse_dct jinit16_inverse_dct +#define jinit_lhuff_decoder jinit16_lhuff_decoder +#define jinit_lhuff_encoder jinit16_lhuff_encoder +#define jinit_lossless_c_codec jinit16_lossless_c_codec +#define jinit_lossless_d_codec jinit16_lossless_d_codec +#define jinit_lossy_c_codec jinit16_lossy_c_codec +#define jinit_lossy_d_codec jinit16_lossy_d_codec +#define jinit_marker_reader jinit16_marker_reader +#define jinit_marker_writer jinit16_marker_writer +#define jinit_master_decompress jinit16_master_decompress +#define jinit_memory_mgr jinit16_memory_mgr +#define jinit_merged_upsampler jinit16_merged_upsampler +#define jinit_phuff_decoder jinit16_phuff_decoder +#define jinit_phuff_encoder jinit16_phuff_encoder +#define jinit_shuff_decoder jinit16_shuff_decoder +#define jinit_shuff_encoder jinit16_shuff_encoder +#define jinit_undifferencer jinit16_undifferencer +#define jinit_upsampler jinit16_upsampler +#define jpeg_CreateCompress jpeg16_CreateCompress +#define jpeg_CreateDecompress jpeg16_CreateDecompress +#define jpeg_abort jpeg16_abort +#define jpeg_abort_compress jpeg16_abort_compress +#define jpeg_abort_decompress jpeg16_abort_decompress +#define jpeg_add_quant_table jpeg16_add_quant_table +#define jpeg_alloc_huff_table jpeg16_alloc_huff_table +#define jpeg_alloc_quant_table jpeg16_alloc_quant_table +#define jpeg_calc_output_dimensions jpeg16_calc_output_dimensions +#define jpeg_consume_input jpeg16_consume_input +#define jpeg_copy_critical_parameters jpeg16_copy_critical_parameters +#define jpeg_default_colorspace jpeg16_default_colorspace +#define jpeg_destroy jpeg16_destroy +#define jpeg_destroy_compress jpeg16_destroy_compress +#define jpeg_destroy_decompress jpeg16_destroy_decompress +#define jpeg_fdct_float jpeg16_fdct_float +#define jpeg_fdct_ifast jpeg16_fdct_ifast +#define jpeg_fdct_islow jpeg16_fdct_islow +#define jpeg_fill_bit_buffer jpeg16_fill_bit_buffer +#define jpeg_finish_compress jpeg16_finish_compress +#define jpeg_finish_decompress jpeg16_finish_decompress +#define jpeg_finish_output jpeg16_finish_output +#define jpeg_free_large jpeg16_free_large +#define jpeg_free_small jpeg16_free_small +#define jpeg_gen_optimal_table jpeg16_gen_optimal_table +#define jpeg_get_large jpeg16_get_large +#define jpeg_get_small jpeg16_get_small +#define jpeg_has_multiple_scans jpeg16_has_multiple_scans +#define jpeg_huff_decode jpeg16_huff_decode +#define jpeg_idct_1x1 jpeg16_idct_1x1 +#define jpeg_idct_2x2 jpeg16_idct_2x2 +#define jpeg_idct_4x4 jpeg16_idct_4x4 +#define jpeg_idct_float jpeg16_idct_float +#define jpeg_idct_ifast jpeg16_idct_ifast +#define jpeg_idct_islow jpeg16_idct_islow +#define jpeg_input_complete jpeg16_input_complete +#define jpeg_make_c_derived_tbl jpeg16_make_c_derived_tbl +#define jpeg_make_d_derived_tbl jpeg16_make_d_derived_tbl +#define jpeg_mem_available jpeg16_mem_available +#define jpeg_mem_init jpeg16_mem_init +#define jpeg_mem_term jpeg16_mem_term +#define jpeg_new_colormap jpeg16_new_colormap +#define jpeg_open_backing_store jpeg16_open_backing_store +#define jpeg_quality_scaling jpeg16_quality_scaling +#define jpeg_read_coefficients jpeg16_read_coefficients +#define jpeg_read_header jpeg16_read_header +#define jpeg_read_raw_data jpeg16_read_raw_data +#define jpeg_read_scanlines jpeg16_read_scanlines +#define jpeg_resync_to_restart jpeg16_resync_to_restart +#define jpeg_save_markers jpeg16_save_markers +#define jpeg_set_colorspace jpeg16_set_colorspace +#define jpeg_set_defaults jpeg16_set_defaults +#define jpeg_set_linear_quality jpeg16_set_linear_quality +#define jpeg_set_marker_processor jpeg16_set_marker_processor +#define jpeg_set_quality jpeg16_set_quality +#define jpeg_simple_lossless jpeg16_simple_lossless +#define jpeg_simple_progression jpeg16_simple_progression +#define jpeg_start_compress jpeg16_start_compress +#define jpeg_start_decompress jpeg16_start_decompress +#define jpeg_start_output jpeg16_start_output +#define jpeg_std_error jpeg16_std_error +#define jpeg_stdio_dest jpeg16_stdio_dest +#define jpeg_stdio_src jpeg16_stdio_src +#define jpeg_suppress_tables jpeg16_suppress_tables +#define jpeg_write_coefficients jpeg16_write_coefficients +#define jpeg_write_m_byte jpeg16_write_m_byte +#define jpeg_write_m_header jpeg16_write_m_header +#define jpeg_write_marker jpeg16_write_marker +#define jpeg_write_raw_data jpeg16_write_raw_data +#define jpeg_write_scanlines jpeg16_write_scanlines +#define jpeg_write_tables jpeg16_write_tables +#define jround_up jround16_up +#define jzero_far jzero16_far +#endif /* NEED_SHORT_EXTERNAL_NAMES */ + + +/* Default error-management setup */ +EXTERN(struct jpeg_error_mgr *) jpeg_std_error + JPP((struct jpeg_error_mgr * err)); + +/* Initialization of JPEG compression objects. + * jpeg_create_compress() and jpeg_create_decompress() are the exported + * names that applications should call. These expand to calls on + * jpeg_CreateCompress and jpeg_CreateDecompress with additional information + * passed for version mismatch checking. + * NB: you must set up the error-manager BEFORE calling jpeg_create_xxx. + */ +#define jpeg_create_compress(cinfo) \ + jpeg_CreateCompress((cinfo), JPEG_LIB_VERSION, \ + (size_t) sizeof(struct jpeg_compress_struct)) +#define jpeg_create_decompress(cinfo) \ + jpeg_CreateDecompress((cinfo), JPEG_LIB_VERSION, \ + (size_t) sizeof(struct jpeg_decompress_struct)) +EXTERN(void) jpeg_CreateCompress JPP((j_compress_ptr cinfo, + int version, size_t structsize)); +EXTERN(void) jpeg_CreateDecompress JPP((j_decompress_ptr cinfo, + int version, size_t structsize)); +/* Destruction of JPEG compression objects */ +EXTERN(void) jpeg_destroy_compress JPP((j_compress_ptr cinfo)); +EXTERN(void) jpeg_destroy_decompress JPP((j_decompress_ptr cinfo)); + +/* Standard data source and destination managers: stdio streams. */ +/* Caller is responsible for opening the file before and closing after. */ +EXTERN(void) jpeg_stdio_dest JPP((j_compress_ptr cinfo, FILE * outfile)); +EXTERN(void) jpeg_stdio_src JPP((j_decompress_ptr cinfo, FILE * infile)); + +/* Default parameter setup for compression */ +EXTERN(void) jpeg_set_defaults JPP((j_compress_ptr cinfo)); +/* Compression parameter setup aids */ +EXTERN(void) jpeg_set_colorspace JPP((j_compress_ptr cinfo, + J_COLOR_SPACE colorspace)); +EXTERN(void) jpeg_default_colorspace JPP((j_compress_ptr cinfo)); +EXTERN(void) jpeg_set_quality JPP((j_compress_ptr cinfo, int quality, + boolean force_baseline)); +EXTERN(void) jpeg_set_linear_quality JPP((j_compress_ptr cinfo, + int scale_factor, + boolean force_baseline)); +EXTERN(void) jpeg_add_quant_table JPP((j_compress_ptr cinfo, int which_tbl, + const unsigned int *basic_table, + int scale_factor, + boolean force_baseline)); +EXTERN(int) jpeg_quality_scaling JPP((int quality)); +EXTERN(void) jpeg_simple_lossless JPP((j_compress_ptr cinfo, + int predictor, int point_transform)); +EXTERN(void) jpeg_simple_progression JPP((j_compress_ptr cinfo)); +EXTERN(void) jpeg_suppress_tables JPP((j_compress_ptr cinfo, + boolean suppress)); +EXTERN(JQUANT_TBL *) jpeg_alloc_quant_table JPP((j_common_ptr cinfo)); +EXTERN(JHUFF_TBL *) jpeg_alloc_huff_table JPP((j_common_ptr cinfo)); + +/* Main entry points for compression */ +EXTERN(void) jpeg_start_compress JPP((j_compress_ptr cinfo, + boolean write_all_tables)); +EXTERN(JDIMENSION) jpeg_write_scanlines JPP((j_compress_ptr cinfo, + JSAMPARRAY scanlines, + JDIMENSION num_lines)); +EXTERN(void) jpeg_finish_compress JPP((j_compress_ptr cinfo)); + +/* Replaces jpeg_write_scanlines when writing raw downsampled data. */ +EXTERN(JDIMENSION) jpeg_write_raw_data JPP((j_compress_ptr cinfo, + JSAMPIMAGE data, + JDIMENSION num_lines)); + +/* Write a special marker. See libjpeg.doc concerning safe usage. */ +EXTERN(void) jpeg_write_marker + JPP((j_compress_ptr cinfo, int marker, + const JOCTET * dataptr, unsigned int datalen)); +/* Same, but piecemeal. */ +EXTERN(void) jpeg_write_m_header + JPP((j_compress_ptr cinfo, int marker, unsigned int datalen)); +EXTERN(void) jpeg_write_m_byte + JPP((j_compress_ptr cinfo, int val)); + +/* Alternate compression function: just write an abbreviated table file */ +EXTERN(void) jpeg_write_tables JPP((j_compress_ptr cinfo)); + +/* Decompression startup: read start of JPEG datastream to see what's there */ +EXTERN(int) jpeg_read_header JPP((j_decompress_ptr cinfo, + boolean require_image)); +/* Return value is one of: */ +#define JPEG_SUSPENDED 0 /* Suspended due to lack of input data */ +#define JPEG_HEADER_OK 1 /* Found valid image datastream */ +#define JPEG_HEADER_TABLES_ONLY 2 /* Found valid table-specs-only datastream */ +/* If you pass require_image = TRUE (normal case), you need not check for + * a TABLES_ONLY return code; an abbreviated file will cause an error exit. + * JPEG_SUSPENDED is only possible if you use a data source module that can + * give a suspension return (the stdio source module doesn't). + */ + +/* Main entry points for decompression */ +EXTERN(boolean) jpeg_start_decompress JPP((j_decompress_ptr cinfo)); +EXTERN(JDIMENSION) jpeg_read_scanlines JPP((j_decompress_ptr cinfo, + JSAMPARRAY scanlines, + JDIMENSION max_lines)); +EXTERN(boolean) jpeg_finish_decompress JPP((j_decompress_ptr cinfo)); + +/* Replaces jpeg_read_scanlines when reading raw downsampled data. */ +EXTERN(JDIMENSION) jpeg_read_raw_data JPP((j_decompress_ptr cinfo, + JSAMPIMAGE data, + JDIMENSION max_lines)); + +/* Additional entry points for buffered-image mode. */ +EXTERN(boolean) jpeg_has_multiple_scans JPP((j_decompress_ptr cinfo)); +EXTERN(boolean) jpeg_start_output JPP((j_decompress_ptr cinfo, + int scan_number)); +EXTERN(boolean) jpeg_finish_output JPP((j_decompress_ptr cinfo)); +EXTERN(boolean) jpeg_input_complete JPP((j_decompress_ptr cinfo)); +EXTERN(void) jpeg_new_colormap JPP((j_decompress_ptr cinfo)); +EXTERN(int) jpeg_consume_input JPP((j_decompress_ptr cinfo)); +/* Return value is one of: */ +/* #define JPEG_SUSPENDED 0 Suspended due to lack of input data */ +#define JPEG_REACHED_SOS 1 /* Reached start of new scan */ +#define JPEG_REACHED_EOI 2 /* Reached end of image */ +#define JPEG_ROW_COMPLETED 3 /* Completed one iMCU row */ +#define JPEG_SCAN_COMPLETED 4 /* Completed last iMCU row of a scan */ + +/* Precalculate output dimensions for current decompression parameters. */ +EXTERN(void) jpeg_calc_output_dimensions JPP((j_decompress_ptr cinfo)); + +/* Control saving of COM and APPn markers into marker_list. */ +EXTERN(void) jpeg_save_markers + JPP((j_decompress_ptr cinfo, int marker_code, + unsigned int length_limit)); + +/* Install a special processing method for COM or APPn markers. */ +EXTERN(void) jpeg_set_marker_processor + JPP((j_decompress_ptr cinfo, int marker_code, + jpeg_marker_parser_method routine)); + +/* Read or write raw DCT coefficients --- useful for lossless transcoding. */ +EXTERN(jvirt_barray_ptr *) jpeg_read_coefficients JPP((j_decompress_ptr cinfo)); +EXTERN(void) jpeg_write_coefficients JPP((j_compress_ptr cinfo, + jvirt_barray_ptr * coef_arrays)); +EXTERN(void) jpeg_copy_critical_parameters JPP((j_decompress_ptr srcinfo, + j_compress_ptr dstinfo)); + +/* If you choose to abort compression or decompression before completing + * jpeg_finish_(de)compress, then you need to clean up to release memory, + * temporary files, etc. You can just call jpeg_destroy_(de)compress + * if you're done with the JPEG object, but if you want to clean it up and + * reuse it, call this: + */ +EXTERN(void) jpeg_abort_compress JPP((j_compress_ptr cinfo)); +EXTERN(void) jpeg_abort_decompress JPP((j_decompress_ptr cinfo)); + +/* Generic versions of jpeg_abort and jpeg_destroy that work on either + * flavor of JPEG object. These may be more convenient in some places. + */ +EXTERN(void) jpeg_abort JPP((j_common_ptr cinfo)); +EXTERN(void) jpeg_destroy JPP((j_common_ptr cinfo)); + +/* Default restart-marker-resync procedure for use by data source modules */ +EXTERN(boolean) jpeg_resync_to_restart JPP((j_decompress_ptr cinfo, + int desired)); + + +/* These marker codes are exported since applications and data source modules + * are likely to want to use them. + */ + +#define JPEG_RST0 0xD0 /* RST0 marker code */ +#define JPEG_EOI 0xD9 /* EOI marker code */ +#define JPEG_APP0 0xE0 /* APP0 marker code */ +#define JPEG_COM 0xFE /* COM marker code */ + + +/* If we have a brain-damaged compiler that emits warnings (or worse, errors) + * for structure definitions that are never filled in, keep it quiet by + * supplying dummy definitions for the various substructures. + */ + +#ifdef INCOMPLETE_TYPES_BROKEN +#ifndef JPEG_INTERNALS /* will be defined in jpegint.h */ +struct jvirt_sarray_control { long dummy; }; +struct jvirt_barray_control { long dummy; }; +struct jpeg_comp_master { long dummy; }; +struct jpeg_c_main_controller { long dummy; }; +struct jpeg_c_prep_controller { long dummy; }; +struct jpeg_c_coef_controller { long dummy; }; +struct jpeg_marker_writer { long dummy; }; +struct jpeg_color_converter { long dummy; }; +struct jpeg_downsampler { long dummy; }; +struct jpeg_forward_dct { long dummy; }; +struct jpeg_entropy_encoder { long dummy; }; +struct jpeg_decomp_master { long dummy; }; +struct jpeg_d_main_controller { long dummy; }; +struct jpeg_d_coef_controller { long dummy; }; +struct jpeg_d_post_controller { long dummy; }; +struct jpeg_input_controller { long dummy; }; +struct jpeg_marker_reader { long dummy; }; +struct jpeg_entropy_decoder { long dummy; }; +struct jpeg_inverse_dct { long dummy; }; +struct jpeg_upsampler { long dummy; }; +struct jpeg_color_deconverter { long dummy; }; +struct jpeg_color_quantizer { long dummy; }; +#endif /* JPEG_INTERNALS */ +#endif /* INCOMPLETE_TYPES_BROKEN */ + + +/* + * The JPEG library modules define JPEG_INTERNALS before including this file. + * The internal structure declarations are read only when that is true. + * Applications using the library should not include jpegint.h, but may wish + * to include jerror.h. + */ + +#ifdef JPEG_INTERNALS +#include "jpegint16.h" /* fetch private declarations */ +#include "jerror16.h" /* fetch error codes too */ +#endif + +#endif /* JPEGLIB_H */ diff --git a/dcmjpeg/libijg16/jquant1.c b/dcmjpeg/libijg16/jquant1.c new file mode 100644 index 00000000..4077fbb5 --- /dev/null +++ b/dcmjpeg/libijg16/jquant1.c @@ -0,0 +1,856 @@ +/* + * jquant1.c + * + * Copyright (C) 1991-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains 1-pass color quantization (color mapping) routines. + * These routines provide mapping to a fixed color map using equally spaced + * color values. Optional Floyd-Steinberg or ordered dithering is available. + */ + +#define JPEG_INTERNALS +#include "jinclude16.h" +#include "jpeglib16.h" + +#ifdef QUANT_1PASS_SUPPORTED + + +/* + * The main purpose of 1-pass quantization is to provide a fast, if not very + * high quality, colormapped output capability. A 2-pass quantizer usually + * gives better visual quality; however, for quantized grayscale output this + * quantizer is perfectly adequate. Dithering is highly recommended with this + * quantizer, though you can turn it off if you really want to. + * + * In 1-pass quantization the colormap must be chosen in advance of seeing the + * image. We use a map consisting of all combinations of Ncolors[i] color + * values for the i'th component. The Ncolors[] values are chosen so that + * their product, the total number of colors, is no more than that requested. + * (In most cases, the product will be somewhat less.) + * + * Since the colormap is orthogonal, the representative value for each color + * component can be determined without considering the other components; + * then these indexes can be combined into a colormap index by a standard + * N-dimensional-array-subscript calculation. Most of the arithmetic involved + * can be precalculated and stored in the lookup table colorindex[]. + * colorindex[i][j] maps pixel value j in component i to the nearest + * representative value (grid plane) for that component; this index is + * multiplied by the array stride for component i, so that the + * index of the colormap entry closest to a given pixel value is just + * sum( colorindex[component-number][pixel-component-value] ) + * Aside from being fast, this scheme allows for variable spacing between + * representative values with no additional lookup cost. + * + * If gamma correction has been applied in color conversion, it might be wise + * to adjust the color grid spacing so that the representative colors are + * equidistant in linear space. At this writing, gamma correction is not + * implemented by jdcolor, so nothing is done here. + */ + + +/* Declarations for ordered dithering. + * + * We use a standard 16x16 ordered dither array. The basic concept of ordered + * dithering is described in many references, for instance Dale Schumacher's + * chapter II.2 of Graphics Gems II (James Arvo, ed. Academic Press, 1991). + * In place of Schumacher's comparisons against a "threshold" value, we add a + * "dither" value to the input pixel and then round the result to the nearest + * output value. The dither value is equivalent to (0.5 - threshold) times + * the distance between output values. For ordered dithering, we assume that + * the output colors are equally spaced; if not, results will probably be + * worse, since the dither may be too much or too little at a given point. + * + * The normal calculation would be to form pixel value + dither, range-limit + * this to 0..MAXJSAMPLE, and then index into the colorindex table as usual. + * We can skip the separate range-limiting step by extending the colorindex + * table in both directions. + */ + +#define ODITHER_SIZE 16 /* dimension of dither matrix */ +/* NB: if ODITHER_SIZE is not a power of 2, ODITHER_MASK uses will break */ +#define ODITHER_CELLS (ODITHER_SIZE*ODITHER_SIZE) /* # cells in matrix */ +#define ODITHER_MASK (ODITHER_SIZE-1) /* mask for wrapping around counters */ + +typedef int ODITHER_MATRIX[ODITHER_SIZE][ODITHER_SIZE]; +typedef int (*ODITHER_MATRIX_PTR)[ODITHER_SIZE]; + +static const UINT8 base_dither_matrix[ODITHER_SIZE][ODITHER_SIZE] = { + /* Bayer's order-4 dither array. Generated by the code given in + * Stephen Hawley's article "Ordered Dithering" in Graphics Gems I. + * The values in this array must range from 0 to ODITHER_CELLS-1. + */ + { 0,192, 48,240, 12,204, 60,252, 3,195, 51,243, 15,207, 63,255 }, + { 128, 64,176,112,140, 76,188,124,131, 67,179,115,143, 79,191,127 }, + { 32,224, 16,208, 44,236, 28,220, 35,227, 19,211, 47,239, 31,223 }, + { 160, 96,144, 80,172,108,156, 92,163, 99,147, 83,175,111,159, 95 }, + { 8,200, 56,248, 4,196, 52,244, 11,203, 59,251, 7,199, 55,247 }, + { 136, 72,184,120,132, 68,180,116,139, 75,187,123,135, 71,183,119 }, + { 40,232, 24,216, 36,228, 20,212, 43,235, 27,219, 39,231, 23,215 }, + { 168,104,152, 88,164,100,148, 84,171,107,155, 91,167,103,151, 87 }, + { 2,194, 50,242, 14,206, 62,254, 1,193, 49,241, 13,205, 61,253 }, + { 130, 66,178,114,142, 78,190,126,129, 65,177,113,141, 77,189,125 }, + { 34,226, 18,210, 46,238, 30,222, 33,225, 17,209, 45,237, 29,221 }, + { 162, 98,146, 82,174,110,158, 94,161, 97,145, 81,173,109,157, 93 }, + { 10,202, 58,250, 6,198, 54,246, 9,201, 57,249, 5,197, 53,245 }, + { 138, 74,186,122,134, 70,182,118,137, 73,185,121,133, 69,181,117 }, + { 42,234, 26,218, 38,230, 22,214, 41,233, 25,217, 37,229, 21,213 }, + { 170,106,154, 90,166,102,150, 86,169,105,153, 89,165,101,149, 85 } +}; + + +/* Declarations for Floyd-Steinberg dithering. + * + * Errors are accumulated into the array fserrors[], at a resolution of + * 1/16th of a pixel count. The error at a given pixel is propagated + * to its not-yet-processed neighbors using the standard F-S fractions, + * ... (here) 7/16 + * 3/16 5/16 1/16 + * We work left-to-right on even rows, right-to-left on odd rows. + * + * We can get away with a single array (holding one row's worth of errors) + * by using it to store the current row's errors at pixel columns not yet + * processed, but the next row's errors at columns already processed. We + * need only a few extra variables to hold the errors immediately around the + * current column. (If we are lucky, those variables are in registers, but + * even if not, they're probably cheaper to access than array elements are.) + * + * The fserrors[] array is indexed [component#][position]. + * We provide (#columns + 2) entries per component; the extra entry at each + * end saves us from special-casing the first and last pixels. + * + * Note: on a wide image, we might not have enough room in a PC's near data + * segment to hold the error array; so it is allocated with alloc_large. + */ + +#if BITS_IN_JSAMPLE == 8 +typedef INT16 FSERROR; /* 16 bits should be enough */ +typedef int LOCFSERROR; /* use 'int' for calculation temps */ +#else +typedef IJG_INT32 FSERROR; /* may need more than 16 bits */ +typedef IJG_INT32 LOCFSERROR; /* be sure calculation temps are big enough */ +#endif + +typedef FSERROR FAR *FSERRPTR; /* pointer to error array (in FAR storage!) */ + + +/* Private subobject */ + +#define MAX_Q_COMPS 4 /* max components I can handle */ + +typedef struct { + struct jpeg_color_quantizer pub; /* public fields */ + + /* Initially allocated colormap is saved here */ + JSAMPARRAY sv_colormap; /* The color map as a 2-D pixel array */ + int sv_actual; /* number of entries in use */ + + JSAMPARRAY colorindex; /* Precomputed mapping for speed */ + /* colorindex[i][j] = index of color closest to pixel value j in component i, + * premultiplied as described above. Since colormap indexes must fit into + * JSAMPLEs, the entries of this array will too. + */ + boolean is_padded; /* is the colorindex padded for odither? */ + + int Ncolors[MAX_Q_COMPS]; /* # of values alloced to each component */ + + /* Variables for ordered dithering */ + int row_index; /* cur row's vertical index in dither matrix */ + ODITHER_MATRIX_PTR odither[MAX_Q_COMPS]; /* one dither array per component */ + + /* Variables for Floyd-Steinberg dithering */ + FSERRPTR fserrors[MAX_Q_COMPS]; /* accumulated errors */ + boolean on_odd_row; /* flag to remember which row we are on */ +} my_cquantizer; + +typedef my_cquantizer * my_cquantize_ptr; + + +/* + * Policy-making subroutines for create_colormap and create_colorindex. + * These routines determine the colormap to be used. The rest of the module + * only assumes that the colormap is orthogonal. + * + * * select_ncolors decides how to divvy up the available colors + * among the components. + * * output_value defines the set of representative values for a component. + * * largest_input_value defines the mapping from input values to + * representative values for a component. + * Note that the latter two routines may impose different policies for + * different components, though this is not currently done. + */ + + +LOCAL(int) +select_ncolors (j_decompress_ptr cinfo, int Ncolors[]) +/* Determine allocation of desired colors to components, */ +/* and fill in Ncolors[] array to indicate choice. */ +/* Return value is total number of colors (product of Ncolors[] values). */ +{ + int nc = cinfo->out_color_components; /* number of color components */ + int max_colors = cinfo->desired_number_of_colors; + int total_colors, iroot, i, j; + boolean changed; + long temp; + static const int RGB_order[3] = { RGB_GREEN, RGB_RED, RGB_BLUE }; + + /* We can allocate at least the nc'th root of max_colors per component. */ + /* Compute floor(nc'th root of max_colors). */ + iroot = 1; + do { + iroot++; + temp = iroot; /* set temp = iroot ** nc */ + for (i = 1; i < nc; i++) + temp *= iroot; + } while (temp <= (long) max_colors); /* repeat till iroot exceeds root */ + iroot--; /* now iroot = floor(root) */ + + /* Must have at least 2 color values per component */ + if (iroot < 2) + ERREXIT1(cinfo, JERR_QUANT_FEW_COLORS, (int) temp); + + /* Initialize to iroot color values for each component */ + total_colors = 1; + for (i = 0; i < nc; i++) { + Ncolors[i] = iroot; + total_colors *= iroot; + } + /* We may be able to increment the count for one or more components without + * exceeding max_colors, though we know not all can be incremented. + * Sometimes, the first component can be incremented more than once! + * (Example: for 16 colors, we start at 2*2*2, go to 3*2*2, then 4*2*2.) + * In RGB colorspace, try to increment G first, then R, then B. + */ + do { + changed = FALSE; + for (i = 0; i < nc; i++) { + j = (cinfo->out_color_space == JCS_RGB ? RGB_order[i] : i); + /* calculate new total_colors if Ncolors[j] is incremented */ + temp = total_colors / Ncolors[j]; + temp *= Ncolors[j]+1; /* done in long arith to avoid oflo */ + if (temp > (long) max_colors) + break; /* won't fit, done with this pass */ + Ncolors[j]++; /* OK, apply the increment */ + total_colors = (int) temp; + changed = TRUE; + } + } while (changed); + + return total_colors; +} + + +LOCAL(int) +output_value (j_decompress_ptr cinfo, int ci, int j, int maxj) +/* Return j'th output value, where j will range from 0 to maxj */ +/* The output values must fall in 0..MAXJSAMPLE in increasing order */ +{ + /* We always provide values 0 and MAXJSAMPLE for each component; + * any additional values are equally spaced between these limits. + * (Forcing the upper and lower values to the limits ensures that + * dithering can't produce a color outside the selected gamut.) + */ + return (int) (((IJG_INT32) j * MAXJSAMPLE + maxj/2) / maxj); +} + + +LOCAL(int) +largest_input_value (j_decompress_ptr cinfo, int ci, int j, int maxj) +/* Return largest input value that should map to j'th output value */ +/* Must have largest(j=0) >= 0, and largest(j=maxj) >= MAXJSAMPLE */ +{ + /* Breakpoints are halfway between values returned by output_value */ + return (int) (((IJG_INT32) (2*j + 1) * MAXJSAMPLE + maxj) / (2*maxj)); +} + + +/* + * Create the colormap. + */ + +LOCAL(void) +create_colormap (j_decompress_ptr cinfo) +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + JSAMPARRAY colormap; /* Created colormap */ + int total_colors; /* Number of distinct output colors */ + int i,j,k, nci, blksize, blkdist, ptr, val; + + /* Select number of colors for each component */ + total_colors = select_ncolors(cinfo, cquantize->Ncolors); + + /* Report selected color counts */ + if (cinfo->out_color_components == 3) + TRACEMS4(cinfo, 1, JTRC_QUANT_3_NCOLORS, + total_colors, cquantize->Ncolors[0], + cquantize->Ncolors[1], cquantize->Ncolors[2]); + else + TRACEMS1(cinfo, 1, JTRC_QUANT_NCOLORS, total_colors); + + /* Allocate and fill in the colormap. */ + /* The colors are ordered in the map in standard row-major order, */ + /* i.e. rightmost (highest-indexed) color changes most rapidly. */ + + colormap = (*cinfo->mem->alloc_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + (JDIMENSION) total_colors, (JDIMENSION) cinfo->out_color_components); + + /* blksize is number of adjacent repeated entries for a component */ + /* blkdist is distance between groups of identical entries for a component */ + blkdist = total_colors; + + for (i = 0; i < cinfo->out_color_components; i++) { + /* fill in colormap entries for i'th color component */ + nci = cquantize->Ncolors[i]; /* # of distinct values for this color */ + blksize = blkdist / nci; + for (j = 0; j < nci; j++) { + /* Compute j'th output value (out of nci) for component */ + val = output_value(cinfo, i, j, nci-1); + /* Fill in all colormap entries that have this value of this component */ + for (ptr = j * blksize; ptr < total_colors; ptr += blkdist) { + /* fill in blksize entries beginning at ptr */ + for (k = 0; k < blksize; k++) + colormap[i][ptr+k] = (JSAMPLE) val; + } + } + blkdist = blksize; /* blksize of this color is blkdist of next */ + } + + /* Save the colormap in private storage, + * where it will survive color quantization mode changes. + */ + cquantize->sv_colormap = colormap; + cquantize->sv_actual = total_colors; +} + + +/* + * Create the color index table. + */ + +LOCAL(void) +create_colorindex (j_decompress_ptr cinfo) +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + JSAMPROW indexptr; + int i,j,k, nci, blksize, val, pad; + + /* For ordered dither, we pad the color index tables by MAXJSAMPLE in + * each direction (input index values can be -MAXJSAMPLE .. 2*MAXJSAMPLE). + * This is not necessary in the other dithering modes. However, we + * flag whether it was done in case user changes dithering mode. + */ + if (cinfo->dither_mode == JDITHER_ORDERED) { + pad = MAXJSAMPLE*2; + cquantize->is_padded = TRUE; + } else { + pad = 0; + cquantize->is_padded = FALSE; + } + + cquantize->colorindex = (*cinfo->mem->alloc_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + (JDIMENSION) (MAXJSAMPLE+1 + pad), + (JDIMENSION) cinfo->out_color_components); + + /* blksize is number of adjacent repeated entries for a component */ + blksize = cquantize->sv_actual; + + for (i = 0; i < cinfo->out_color_components; i++) { + /* fill in colorindex entries for i'th color component */ + nci = cquantize->Ncolors[i]; /* # of distinct values for this color */ + blksize = blksize / nci; + + /* adjust colorindex pointers to provide padding at negative indexes. */ + if (pad) + cquantize->colorindex[i] += MAXJSAMPLE; + + /* in loop, val = index of current output value, */ + /* and k = largest j that maps to current val */ + indexptr = cquantize->colorindex[i]; + val = 0; + k = largest_input_value(cinfo, i, 0, nci-1); + for (j = 0; j <= MAXJSAMPLE; j++) { + while (j > k) /* advance val if past boundary */ + k = largest_input_value(cinfo, i, ++val, nci-1); + /* premultiply so that no multiplication needed in main processing */ + indexptr[j] = (JSAMPLE) (val * blksize); + } + /* Pad at both ends if necessary */ + if (pad) + for (j = 1; j <= MAXJSAMPLE; j++) { + indexptr[-j] = indexptr[0]; + indexptr[MAXJSAMPLE+j] = indexptr[MAXJSAMPLE]; + } + } +} + + +/* + * Create an ordered-dither array for a component having ncolors + * distinct output values. + */ + +LOCAL(ODITHER_MATRIX_PTR) +make_odither_array (j_decompress_ptr cinfo, int ncolors) +{ + ODITHER_MATRIX_PTR odither; + int j,k; + IJG_INT32 num,den; + + odither = (ODITHER_MATRIX_PTR) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(ODITHER_MATRIX)); + /* The inter-value distance for this color is MAXJSAMPLE/(ncolors-1). + * Hence the dither value for the matrix cell with fill order f + * (f=0..N-1) should be (N-1-2*f)/(2*N) * MAXJSAMPLE/(ncolors-1). + * On 16-bit-int machine, be careful to avoid overflow. + */ + den = 2 * ODITHER_CELLS * ((IJG_INT32) (ncolors - 1)); + for (j = 0; j < ODITHER_SIZE; j++) { + for (k = 0; k < ODITHER_SIZE; k++) { + num = ((IJG_INT32) (ODITHER_CELLS-1 - 2*((int)base_dither_matrix[j][k]))) + * MAXJSAMPLE; + /* Ensure round towards zero despite C's lack of consistency + * about rounding negative values in integer division... + */ + odither[j][k] = (int) (num<0 ? -((-num)/den) : num/den); + } + } + return odither; +} + + +/* + * Create the ordered-dither tables. + * Components having the same number of representative colors may + * share a dither table. + */ + +LOCAL(void) +create_odither_tables (j_decompress_ptr cinfo) +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + ODITHER_MATRIX_PTR odither; + int i, j, nci; + + for (i = 0; i < cinfo->out_color_components; i++) { + nci = cquantize->Ncolors[i]; /* # of distinct values for this color */ + odither = NULL; /* search for matching prior component */ + for (j = 0; j < i; j++) { + if (nci == cquantize->Ncolors[j]) { + odither = cquantize->odither[j]; + break; + } + } + if (odither == NULL) /* need a new table? */ + odither = make_odither_array(cinfo, nci); + cquantize->odither[i] = odither; + } +} + + +/* + * Map some rows of pixels to the output colormapped representation. + */ + +METHODDEF(void) +color_quantize (j_decompress_ptr cinfo, JSAMPARRAY input_buf, + JSAMPARRAY output_buf, int num_rows) +/* General case, no dithering */ +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + JSAMPARRAY colorindex = cquantize->colorindex; + register int pixcode, ci; + register JSAMPROW ptrin, ptrout; + int row; + JDIMENSION col; + JDIMENSION width = cinfo->output_width; + register int nc = cinfo->out_color_components; + + for (row = 0; row < num_rows; row++) { + ptrin = input_buf[row]; + ptrout = output_buf[row]; + for (col = width; col > 0; col--) { + pixcode = 0; + for (ci = 0; ci < nc; ci++) { + pixcode += GETJSAMPLE(colorindex[ci][GETJSAMPLE(*ptrin++)]); + } + *ptrout++ = (JSAMPLE) pixcode; + } + } +} + + +METHODDEF(void) +color_quantize3 (j_decompress_ptr cinfo, JSAMPARRAY input_buf, + JSAMPARRAY output_buf, int num_rows) +/* Fast path for out_color_components==3, no dithering */ +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + register int pixcode; + register JSAMPROW ptrin, ptrout; + JSAMPROW colorindex0 = cquantize->colorindex[0]; + JSAMPROW colorindex1 = cquantize->colorindex[1]; + JSAMPROW colorindex2 = cquantize->colorindex[2]; + int row; + JDIMENSION col; + JDIMENSION width = cinfo->output_width; + + for (row = 0; row < num_rows; row++) { + ptrin = input_buf[row]; + ptrout = output_buf[row]; + for (col = width; col > 0; col--) { + pixcode = GETJSAMPLE(colorindex0[GETJSAMPLE(*ptrin++)]); + pixcode += GETJSAMPLE(colorindex1[GETJSAMPLE(*ptrin++)]); + pixcode += GETJSAMPLE(colorindex2[GETJSAMPLE(*ptrin++)]); + *ptrout++ = (JSAMPLE) pixcode; + } + } +} + + +METHODDEF(void) +quantize_ord_dither (j_decompress_ptr cinfo, JSAMPARRAY input_buf, + JSAMPARRAY output_buf, int num_rows) +/* General case, with ordered dithering */ +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + register JSAMPROW input_ptr; + register JSAMPROW output_ptr; + JSAMPROW colorindex_ci; + int * dither; /* points to active row of dither matrix */ + int row_index, col_index; /* current indexes into dither matrix */ + int nc = cinfo->out_color_components; + int ci; + int row; + JDIMENSION col; + JDIMENSION width = cinfo->output_width; + + for (row = 0; row < num_rows; row++) { + /* Initialize output values to 0 so can process components separately */ + jzero_far((void FAR *) output_buf[row], + (size_t) (width * SIZEOF(JSAMPLE))); + row_index = cquantize->row_index; + for (ci = 0; ci < nc; ci++) { + input_ptr = input_buf[row] + ci; + output_ptr = output_buf[row]; + colorindex_ci = cquantize->colorindex[ci]; + dither = cquantize->odither[ci][row_index]; + col_index = 0; + + for (col = width; col > 0; col--) { + /* Form pixel value + dither, range-limit to 0..MAXJSAMPLE, + * select output value, accumulate into output code for this pixel. + * Range-limiting need not be done explicitly, as we have extended + * the colorindex table to produce the right answers for out-of-range + * inputs. The maximum dither is +- MAXJSAMPLE; this sets the + * required amount of padding. + */ + *output_ptr = (JSAMPLE)(*output_ptr + colorindex_ci[GETJSAMPLE(*input_ptr)+dither[col_index]]); + input_ptr += nc; + output_ptr++; + col_index = (col_index + 1) & ODITHER_MASK; + } + } + /* Advance row index for next row */ + row_index = (row_index + 1) & ODITHER_MASK; + cquantize->row_index = row_index; + } +} + + +METHODDEF(void) +quantize3_ord_dither (j_decompress_ptr cinfo, JSAMPARRAY input_buf, + JSAMPARRAY output_buf, int num_rows) +/* Fast path for out_color_components==3, with ordered dithering */ +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + register int pixcode; + register JSAMPROW input_ptr; + register JSAMPROW output_ptr; + JSAMPROW colorindex0 = cquantize->colorindex[0]; + JSAMPROW colorindex1 = cquantize->colorindex[1]; + JSAMPROW colorindex2 = cquantize->colorindex[2]; + int * dither0; /* points to active row of dither matrix */ + int * dither1; + int * dither2; + int row_index, col_index; /* current indexes into dither matrix */ + int row; + JDIMENSION col; + JDIMENSION width = cinfo->output_width; + + for (row = 0; row < num_rows; row++) { + row_index = cquantize->row_index; + input_ptr = input_buf[row]; + output_ptr = output_buf[row]; + dither0 = cquantize->odither[0][row_index]; + dither1 = cquantize->odither[1][row_index]; + dither2 = cquantize->odither[2][row_index]; + col_index = 0; + + for (col = width; col > 0; col--) { + pixcode = GETJSAMPLE(colorindex0[GETJSAMPLE(*input_ptr++) + + dither0[col_index]]); + pixcode += GETJSAMPLE(colorindex1[GETJSAMPLE(*input_ptr++) + + dither1[col_index]]); + pixcode += GETJSAMPLE(colorindex2[GETJSAMPLE(*input_ptr++) + + dither2[col_index]]); + *output_ptr++ = (JSAMPLE) pixcode; + col_index = (col_index + 1) & ODITHER_MASK; + } + row_index = (row_index + 1) & ODITHER_MASK; + cquantize->row_index = row_index; + } +} + + +METHODDEF(void) +quantize_fs_dither (j_decompress_ptr cinfo, JSAMPARRAY input_buf, + JSAMPARRAY output_buf, int num_rows) +/* General case, with Floyd-Steinberg dithering */ +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + register LOCFSERROR cur; /* current error or pixel value */ + LOCFSERROR belowerr; /* error for pixel below cur */ + LOCFSERROR bpreverr; /* error for below/prev col */ + LOCFSERROR bnexterr; /* error for below/next col */ + LOCFSERROR delta; + register FSERRPTR errorptr; /* => fserrors[] at column before current */ + register JSAMPROW input_ptr; + register JSAMPROW output_ptr; + JSAMPROW colorindex_ci; + JSAMPROW colormap_ci; + int pixcode; + int nc = cinfo->out_color_components; + int dir; /* 1 for left-to-right, -1 for right-to-left */ + int dirnc; /* dir * nc */ + int ci; + int row; + JDIMENSION col; + JDIMENSION width = cinfo->output_width; + JSAMPLE *range_limit = cinfo->sample_range_limit; + SHIFT_TEMPS + + for (row = 0; row < num_rows; row++) { + /* Initialize output values to 0 so can process components separately */ + jzero_far((void FAR *) output_buf[row], + (size_t) (width * SIZEOF(JSAMPLE))); + for (ci = 0; ci < nc; ci++) { + input_ptr = input_buf[row] + ci; + output_ptr = output_buf[row]; + if (cquantize->on_odd_row) { + /* work right to left in this row */ + input_ptr += (width-1) * (JDIMENSION)nc; /* so point to rightmost pixel */ + output_ptr += width-1; + dir = -1; + dirnc = -nc; + errorptr = cquantize->fserrors[ci] + (width+1); /* => entry after last column */ + } else { + /* work left to right in this row */ + dir = 1; + dirnc = nc; + errorptr = cquantize->fserrors[ci]; /* => entry before first column */ + } + colorindex_ci = cquantize->colorindex[ci]; + colormap_ci = cquantize->sv_colormap[ci]; + /* Preset error values: no error propagated to first pixel from left */ + cur = 0; + /* and no error propagated to row below yet */ + belowerr = bpreverr = 0; + + for (col = width; col > 0; col--) { + /* cur holds the error propagated from the previous pixel on the + * current line. Add the error propagated from the previous line + * to form the complete error correction term for this pixel, and + * round the error term (which is expressed * 16) to an integer. + * RIGHT_SHIFT rounds towards minus infinity, so adding 8 is correct + * for either sign of the error value. + * Note: errorptr points to *previous* column's array entry. + */ + cur = RIGHT_SHIFT(cur + errorptr[dir] + 8, 4); + /* Form pixel value + error, and range-limit to 0..MAXJSAMPLE. + * The maximum error is +- MAXJSAMPLE; this sets the required size + * of the range_limit array. + */ + cur += GETJSAMPLE(*input_ptr); + cur = GETJSAMPLE(range_limit[cur]); + /* Select output value, accumulate into output code for this pixel */ + pixcode = GETJSAMPLE(colorindex_ci[cur]); + *output_ptr = (JSAMPLE)(*output_ptr + pixcode); + /* Compute actual representation error at this pixel */ + /* Note: we can do this even though we don't have the final */ + /* pixel code, because the colormap is orthogonal. */ + cur -= GETJSAMPLE(colormap_ci[pixcode]); + /* Compute error fractions to be propagated to adjacent pixels. + * Add these into the running sums, and simultaneously shift the + * next-line error sums left by 1 column. + */ + bnexterr = cur; + delta = cur * 2; + cur += delta; /* form error * 3 */ + errorptr[0] = (FSERROR) (bpreverr + cur); + cur += delta; /* form error * 5 */ + bpreverr = belowerr + cur; + belowerr = bnexterr; + cur += delta; /* form error * 7 */ + /* At this point cur contains the 7/16 error value to be propagated + * to the next pixel on the current line, and all the errors for the + * next line have been shifted over. We are therefore ready to move on. + */ + input_ptr += dirnc; /* advance input ptr to next column */ + output_ptr += dir; /* advance output ptr to next column */ + errorptr += dir; /* advance errorptr to current column */ + } + /* Post-loop cleanup: we must unload the final error value into the + * final fserrors[] entry. Note we need not unload belowerr because + * it is for the dummy column before or after the actual array. + */ + errorptr[0] = (FSERROR) bpreverr; /* unload prev err into array */ + } + cquantize->on_odd_row = (cquantize->on_odd_row ? FALSE : TRUE); + } +} + + +/* + * Allocate workspace for Floyd-Steinberg errors. + */ + +LOCAL(void) +alloc_fs_workspace (j_decompress_ptr cinfo) +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + size_t arraysize; + int i; + + arraysize = (size_t) ((cinfo->output_width + 2) * SIZEOF(FSERROR)); + for (i = 0; i < cinfo->out_color_components; i++) { + cquantize->fserrors[i] = (FSERRPTR) + (*cinfo->mem->alloc_large)((j_common_ptr) cinfo, JPOOL_IMAGE, arraysize); + } +} + + +/* + * Initialize for one-pass color quantization. + */ + +METHODDEF(void) +start_pass_1_quant (j_decompress_ptr cinfo, boolean is_pre_scan) +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + size_t arraysize; + int i; + + /* Install my colormap. */ + cinfo->colormap = cquantize->sv_colormap; + cinfo->actual_number_of_colors = cquantize->sv_actual; + + /* Initialize for desired dithering mode. */ + switch (cinfo->dither_mode) { + case JDITHER_NONE: + if (cinfo->out_color_components == 3) + cquantize->pub.color_quantize = color_quantize3; + else + cquantize->pub.color_quantize = color_quantize; + break; + case JDITHER_ORDERED: + if (cinfo->out_color_components == 3) + cquantize->pub.color_quantize = quantize3_ord_dither; + else + cquantize->pub.color_quantize = quantize_ord_dither; + cquantize->row_index = 0; /* initialize state for ordered dither */ + /* If user changed to ordered dither from another mode, + * we must recreate the color index table with padding. + * This will cost extra space, but probably isn't very likely. + */ + if (! cquantize->is_padded) + create_colorindex(cinfo); + /* Create ordered-dither tables if we didn't already. */ + if (cquantize->odither[0] == NULL) + create_odither_tables(cinfo); + break; + case JDITHER_FS: + cquantize->pub.color_quantize = quantize_fs_dither; + cquantize->on_odd_row = FALSE; /* initialize state for F-S dither */ + /* Allocate Floyd-Steinberg workspace if didn't already. */ + if (cquantize->fserrors[0] == NULL) + alloc_fs_workspace(cinfo); + /* Initialize the propagated errors to zero. */ + arraysize = (size_t) ((cinfo->output_width + 2) * SIZEOF(FSERROR)); + for (i = 0; i < cinfo->out_color_components; i++) + jzero_far((void FAR *) cquantize->fserrors[i], arraysize); + break; + default: + ERREXIT(cinfo, JERR_NOT_COMPILED); + break; + } +} + + +/* + * Finish up at the end of the pass. + */ + +METHODDEF(void) +finish_pass_1_quant (j_decompress_ptr cinfo) +{ + /* no work in 1-pass case */ +} + + +/* + * Switch to a new external colormap between output passes. + * Shouldn't get to this module! + */ + +METHODDEF(void) +new_color_map_1_quant (j_decompress_ptr cinfo) +{ + ERREXIT(cinfo, JERR_MODE_CHANGE); +} + + +/* + * Module initialization routine for 1-pass color quantization. + */ + +GLOBAL(void) +jinit_1pass_quantizer (j_decompress_ptr cinfo) +{ + my_cquantize_ptr cquantize; + + cquantize = (my_cquantize_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_cquantizer)); + cinfo->cquantize = (struct jpeg_color_quantizer *) cquantize; + cquantize->pub.start_pass = start_pass_1_quant; + cquantize->pub.finish_pass = finish_pass_1_quant; + cquantize->pub.new_color_map = new_color_map_1_quant; + cquantize->fserrors[0] = NULL; /* Flag FS workspace not allocated */ + cquantize->odither[0] = NULL; /* Also flag odither arrays not allocated */ + + /* Make sure my internal arrays won't overflow */ + if (cinfo->out_color_components > MAX_Q_COMPS) + ERREXIT1(cinfo, JERR_QUANT_COMPONENTS, MAX_Q_COMPS); + /* Make sure colormap indexes can be represented by JSAMPLEs */ + if (cinfo->desired_number_of_colors > (MAXJSAMPLE+1)) + ERREXIT1(cinfo, JERR_QUANT_MANY_COLORS, MAXJSAMPLE+1); + + /* Create the colormap and color index table. */ + create_colormap(cinfo); + create_colorindex(cinfo); + + /* Allocate Floyd-Steinberg workspace now if requested. + * We do this now since it is FAR storage and may affect the memory + * manager's space calculations. If the user changes to FS dither + * mode in a later pass, we will allocate the space then, and will + * possibly overrun the max_memory_to_use setting. + */ + if (cinfo->dither_mode == JDITHER_FS) + alloc_fs_workspace(cinfo); +} + +#endif /* QUANT_1PASS_SUPPORTED */ diff --git a/dcmjpeg/libijg16/jquant2.c b/dcmjpeg/libijg16/jquant2.c new file mode 100644 index 00000000..5453e15a --- /dev/null +++ b/dcmjpeg/libijg16/jquant2.c @@ -0,0 +1,1310 @@ +/* + * jquant2.c + * + * Copyright (C) 1991-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains 2-pass color quantization (color mapping) routines. + * These routines provide selection of a custom color map for an image, + * followed by mapping of the image to that color map, with optional + * Floyd-Steinberg dithering. + * It is also possible to use just the second pass to map to an arbitrary + * externally-given color map. + * + * Note: ordered dithering is not supported, since there isn't any fast + * way to compute intercolor distances; it's unclear that ordered dither's + * fundamental assumptions even hold with an irregularly spaced color map. + */ + +#define JPEG_INTERNALS +#include "jinclude16.h" +#include "jpeglib16.h" + +#ifdef QUANT_2PASS_SUPPORTED + + +/* + * This module implements the well-known Heckbert paradigm for color + * quantization. Most of the ideas used here can be traced back to + * Heckbert's seminal paper + * Heckbert, Paul. "Color Image Quantization for Frame Buffer Display", + * Proc. SIGGRAPH '82, Computer Graphics v.16 #3 (July 1982), pp 297-304. + * + * In the first pass over the image, we accumulate a histogram showing the + * usage count of each possible color. To keep the histogram to a reasonable + * size, we reduce the precision of the input; typical practice is to retain + * 5 or 6 bits per color, so that 8 or 4 different input values are counted + * in the same histogram cell. + * + * Next, the color-selection step begins with a box representing the whole + * color space, and repeatedly splits the "largest" remaining box until we + * have as many boxes as desired colors. Then the mean color in each + * remaining box becomes one of the possible output colors. + * + * The second pass over the image maps each input pixel to the closest output + * color (optionally after applying a Floyd-Steinberg dithering correction). + * This mapping is logically trivial, but making it go fast enough requires + * considerable care. + * + * Heckbert-style quantizers vary a good deal in their policies for choosing + * the "largest" box and deciding where to cut it. The particular policies + * used here have proved out well in experimental comparisons, but better ones + * may yet be found. + * + * In earlier versions of the IJG code, this module quantized in YCbCr color + * space, processing the raw upsampled data without a color conversion step. + * This allowed the color conversion math to be done only once per colormap + * entry, not once per pixel. However, that optimization precluded other + * useful optimizations (such as merging color conversion with upsampling) + * and it also interfered with desired capabilities such as quantizing to an + * externally-supplied colormap. We have therefore abandoned that approach. + * The present code works in the post-conversion color space, typically RGB. + * + * To improve the visual quality of the results, we actually work in scaled + * RGB space, giving G distances more weight than R, and R in turn more than + * B. To do everything in integer math, we must use integer scale factors. + * The 2/3/1 scale factors used here correspond loosely to the relative + * weights of the colors in the NTSC grayscale equation. + * If you want to use this code to quantize a non-RGB color space, you'll + * probably need to change these scale factors. + */ + +#define R_SCALE 2 /* scale R distances by this much */ +#define G_SCALE 3 /* scale G distances by this much */ +#define B_SCALE 1 /* and B by this much */ + +/* Relabel R/G/B as components 0/1/2, respecting the RGB ordering defined + * in jmorecfg.h. As the code stands, it will do the right thing for R,G,B + * and B,G,R orders. If you define some other weird order in jmorecfg.h, + * you'll get compile errors until you extend this logic. In that case + * you'll probably want to tweak the histogram sizes too. + */ + +#if RGB_RED == 0 +#define C0_SCALE R_SCALE +#endif +#if RGB_BLUE == 0 +#define C0_SCALE B_SCALE +#endif +#if RGB_GREEN == 1 +#define C1_SCALE G_SCALE +#endif +#if RGB_RED == 2 +#define C2_SCALE R_SCALE +#endif +#if RGB_BLUE == 2 +#define C2_SCALE B_SCALE +#endif + + +/* + * First we have the histogram data structure and routines for creating it. + * + * The number of bits of precision can be adjusted by changing these symbols. + * We recommend keeping 6 bits for G and 5 each for R and B. + * If you have plenty of memory and cycles, 6 bits all around gives marginally + * better results; if you are short of memory, 5 bits all around will save + * some space but degrade the results. + * To maintain a fully accurate histogram, we'd need to allocate a "long" + * (preferably unsigned long) for each cell. In practice this is overkill; + * we can get by with 16 bits per cell. Few of the cell counts will overflow, + * and clamping those that do overflow to the maximum value will give close- + * enough results. This reduces the recommended histogram size from 256Kb + * to 128Kb, which is a useful savings on PC-class machines. + * (In the second pass the histogram space is re-used for pixel mapping data; + * in that capacity, each cell must be able to store zero to the number of + * desired colors. 16 bits/cell is plenty for that too.) + * Since the JPEG code is intended to run in small memory model on 80x86 + * machines, we can't just allocate the histogram in one chunk. Instead + * of a true 3-D array, we use a row of pointers to 2-D arrays. Each + * pointer corresponds to a C0 value (typically 2^5 = 32 pointers) and + * each 2-D array has 2^6*2^5 = 2048 or 2^6*2^6 = 4096 entries. Note that + * on 80x86 machines, the pointer row is in near memory but the actual + * arrays are in far memory (same arrangement as we use for image arrays). + */ + +#define MAXNUMCOLORS (MAXJSAMPLE+1) /* maximum size of colormap */ + +/* These will do the right thing for either R,G,B or B,G,R color order, + * but you may not like the results for other color orders. + */ +#define HIST_C0_BITS 5 /* bits of precision in R/B histogram */ +#define HIST_C1_BITS 6 /* bits of precision in G histogram */ +#define HIST_C2_BITS 5 /* bits of precision in B/R histogram */ + +/* Number of elements along histogram axes. */ +#define HIST_C0_ELEMS (1<cquantize; + register JSAMPROW ptr; + register histptr histp; + register hist3d histogram = cquantize->histogram; + int row; + JDIMENSION col; + JDIMENSION width = cinfo->output_width; + + for (row = 0; row < num_rows; row++) { + ptr = input_buf[row]; + for (col = width; col > 0; col--) { + /* get pixel value and index into the histogram */ + histp = & histogram[GETJSAMPLE(ptr[0]) >> C0_SHIFT] + [GETJSAMPLE(ptr[1]) >> C1_SHIFT] + [GETJSAMPLE(ptr[2]) >> C2_SHIFT]; + /* increment, check for overflow and undo increment if so. */ + if (++(*histp) <= 0) + (*histp)--; + ptr += 3; + } + } +} + + +/* + * Next we have the really interesting routines: selection of a colormap + * given the completed histogram. + * These routines work with a list of "boxes", each representing a rectangular + * subset of the input color space (to histogram precision). + */ + +typedef struct { + /* The bounds of the box (inclusive); expressed as histogram indexes */ + int c0min, c0max; + int c1min, c1max; + int c2min, c2max; + /* The volume (actually 2-norm) of the box */ + IJG_INT32 volume; + /* The number of nonzero histogram cells within this box */ + long colorcount; +} box; + +typedef box * boxptr; + + +LOCAL(boxptr) +find_biggest_color_pop (boxptr boxlist, int numboxes) +/* Find the splittable box with the largest color population */ +/* Returns NULL if no splittable boxes remain */ +{ + register boxptr boxp; + register int i; + register long maxc = 0; + boxptr which = NULL; + + for (i = 0, boxp = boxlist; i < numboxes; i++, boxp++) { + if (boxp->colorcount > maxc && boxp->volume > 0) { + which = boxp; + maxc = boxp->colorcount; + } + } + return which; +} + + +LOCAL(boxptr) +find_biggest_volume (boxptr boxlist, int numboxes) +/* Find the splittable box with the largest (scaled) volume */ +/* Returns NULL if no splittable boxes remain */ +{ + register boxptr boxp; + register int i; + register IJG_INT32 maxv = 0; + boxptr which = NULL; + + for (i = 0, boxp = boxlist; i < numboxes; i++, boxp++) { + if (boxp->volume > maxv) { + which = boxp; + maxv = boxp->volume; + } + } + return which; +} + + +LOCAL(void) +update_box (j_decompress_ptr cinfo, boxptr boxp) +/* Shrink the min/max bounds of a box to enclose only nonzero elements, */ +/* and recompute its volume and population */ +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + hist3d histogram = cquantize->histogram; + histptr histp; + int c0,c1,c2; + int c0min,c0max,c1min,c1max,c2min,c2max; + IJG_INT32 dist0,dist1,dist2; + long ccount; + + c0min = boxp->c0min; c0max = boxp->c0max; + c1min = boxp->c1min; c1max = boxp->c1max; + c2min = boxp->c2min; c2max = boxp->c2max; + + if (c0max > c0min) + for (c0 = c0min; c0 <= c0max; c0++) + for (c1 = c1min; c1 <= c1max; c1++) { + histp = & histogram[c0][c1][c2min]; + for (c2 = c2min; c2 <= c2max; c2++) + if (*histp++ != 0) { + boxp->c0min = c0min = c0; + goto have_c0min; + } + } + have_c0min: + if (c0max > c0min) + for (c0 = c0max; c0 >= c0min; c0--) + for (c1 = c1min; c1 <= c1max; c1++) { + histp = & histogram[c0][c1][c2min]; + for (c2 = c2min; c2 <= c2max; c2++) + if (*histp++ != 0) { + boxp->c0max = c0max = c0; + goto have_c0max; + } + } + have_c0max: + if (c1max > c1min) + for (c1 = c1min; c1 <= c1max; c1++) + for (c0 = c0min; c0 <= c0max; c0++) { + histp = & histogram[c0][c1][c2min]; + for (c2 = c2min; c2 <= c2max; c2++) + if (*histp++ != 0) { + boxp->c1min = c1min = c1; + goto have_c1min; + } + } + have_c1min: + if (c1max > c1min) + for (c1 = c1max; c1 >= c1min; c1--) + for (c0 = c0min; c0 <= c0max; c0++) { + histp = & histogram[c0][c1][c2min]; + for (c2 = c2min; c2 <= c2max; c2++) + if (*histp++ != 0) { + boxp->c1max = c1max = c1; + goto have_c1max; + } + } + have_c1max: + if (c2max > c2min) + for (c2 = c2min; c2 <= c2max; c2++) + for (c0 = c0min; c0 <= c0max; c0++) { + histp = & histogram[c0][c1min][c2]; + for (c1 = c1min; c1 <= c1max; c1++, histp += HIST_C2_ELEMS) + if (*histp != 0) { + boxp->c2min = c2min = c2; + goto have_c2min; + } + } + have_c2min: + if (c2max > c2min) + for (c2 = c2max; c2 >= c2min; c2--) + for (c0 = c0min; c0 <= c0max; c0++) { + histp = & histogram[c0][c1min][c2]; + for (c1 = c1min; c1 <= c1max; c1++, histp += HIST_C2_ELEMS) + if (*histp != 0) { + boxp->c2max = c2max = c2; + goto have_c2max; + } + } + have_c2max: + + /* Update box volume. + * We use 2-norm rather than real volume here; this biases the method + * against making long narrow boxes, and it has the side benefit that + * a box is splittable iff norm > 0. + * Since the differences are expressed in histogram-cell units, + * we have to shift back to JSAMPLE units to get consistent distances; + * after which, we scale according to the selected distance scale factors. + */ + dist0 = ((c0max - c0min) << C0_SHIFT) * C0_SCALE; + dist1 = ((c1max - c1min) << C1_SHIFT) * C1_SCALE; + dist2 = ((c2max - c2min) << C2_SHIFT) * C2_SCALE; + boxp->volume = dist0*dist0 + dist1*dist1 + dist2*dist2; + + /* Now scan remaining volume of box and compute population */ + ccount = 0; + for (c0 = c0min; c0 <= c0max; c0++) + for (c1 = c1min; c1 <= c1max; c1++) { + histp = & histogram[c0][c1][c2min]; + for (c2 = c2min; c2 <= c2max; c2++, histp++) + if (*histp != 0) { + ccount++; + } + } + boxp->colorcount = ccount; +} + + +LOCAL(int) +median_cut (j_decompress_ptr cinfo, boxptr boxlist, int numboxes, + int desired_colors) +/* Repeatedly select and split the largest box until we have enough boxes */ +{ + int n,lb; + int c0,c1,c2,cmax; + register boxptr b1,b2; + + while (numboxes < desired_colors) { + /* Select box to split. + * Current algorithm: by population for first half, then by volume. + */ + if (numboxes*2 <= desired_colors) { + b1 = find_biggest_color_pop(boxlist, numboxes); + } else { + b1 = find_biggest_volume(boxlist, numboxes); + } + if (b1 == NULL) /* no splittable boxes left! */ + break; + b2 = &boxlist[numboxes]; /* where new box will go */ + /* Copy the color bounds to the new box. */ + b2->c0max = b1->c0max; b2->c1max = b1->c1max; b2->c2max = b1->c2max; + b2->c0min = b1->c0min; b2->c1min = b1->c1min; b2->c2min = b1->c2min; + /* Choose which axis to split the box on. + * Current algorithm: longest scaled axis. + * See notes in update_box about scaling distances. + */ + c0 = ((b1->c0max - b1->c0min) << C0_SHIFT) * C0_SCALE; + c1 = ((b1->c1max - b1->c1min) << C1_SHIFT) * C1_SCALE; + c2 = ((b1->c2max - b1->c2min) << C2_SHIFT) * C2_SCALE; + /* We want to break any ties in favor of green, then red, blue last. + * This code does the right thing for R,G,B or B,G,R color orders only. + */ +#if RGB_RED == 0 + cmax = c1; n = 1; + if (c0 > cmax) { cmax = c0; n = 0; } + if (c2 > cmax) { n = 2; } +#else + cmax = c1; n = 1; + if (c2 > cmax) { cmax = c2; n = 2; } + if (c0 > cmax) { n = 0; } +#endif + /* Choose split point along selected axis, and update box bounds. + * Current algorithm: split at halfway point. + * (Since the box has been shrunk to minimum volume, + * any split will produce two nonempty subboxes.) + * Note that lb value is max for lower box, so must be < old max. + */ + switch (n) { + case 0: + lb = (b1->c0max + b1->c0min) / 2; + b1->c0max = lb; + b2->c0min = lb+1; + break; + case 1: + lb = (b1->c1max + b1->c1min) / 2; + b1->c1max = lb; + b2->c1min = lb+1; + break; + case 2: + lb = (b1->c2max + b1->c2min) / 2; + b1->c2max = lb; + b2->c2min = lb+1; + break; + } + /* Update stats for boxes */ + update_box(cinfo, b1); + update_box(cinfo, b2); + numboxes++; + } + return numboxes; +} + + +LOCAL(void) +compute_color (j_decompress_ptr cinfo, boxptr boxp, int icolor) +/* Compute representative color for a box, put it in colormap[icolor] */ +{ + /* Current algorithm: mean weighted by pixels (not colors) */ + /* Note it is important to get the rounding correct! */ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + hist3d histogram = cquantize->histogram; + histptr histp; + int c0,c1,c2; + int c0min,c0max,c1min,c1max,c2min,c2max; + long count; + long total = 0; + long c0total = 0; + long c1total = 0; + long c2total = 0; + + c0min = boxp->c0min; c0max = boxp->c0max; + c1min = boxp->c1min; c1max = boxp->c1max; + c2min = boxp->c2min; c2max = boxp->c2max; + + for (c0 = c0min; c0 <= c0max; c0++) + for (c1 = c1min; c1 <= c1max; c1++) { + histp = & histogram[c0][c1][c2min]; + for (c2 = c2min; c2 <= c2max; c2++) { + if ((count = *histp++) != 0) { + total += count; + c0total += ((c0 << C0_SHIFT) + ((1<>1)) * count; + c1total += ((c1 << C1_SHIFT) + ((1<>1)) * count; + c2total += ((c2 << C2_SHIFT) + ((1<>1)) * count; + } + } + } + + cinfo->colormap[0][icolor] = (JSAMPLE) ((c0total + (total>>1)) / total); + cinfo->colormap[1][icolor] = (JSAMPLE) ((c1total + (total>>1)) / total); + cinfo->colormap[2][icolor] = (JSAMPLE) ((c2total + (total>>1)) / total); +} + + +LOCAL(void) +select_colors (j_decompress_ptr cinfo, int desired_colors) +/* Master routine for color selection */ +{ + boxptr boxlist; + int numboxes; + int i; + + /* Allocate workspace for box list */ + boxlist = (boxptr) (*cinfo->mem->alloc_small) + ((j_common_ptr) cinfo, JPOOL_IMAGE, (size_t)desired_colors * SIZEOF(box)); + /* Initialize one box containing whole space */ + numboxes = 1; + boxlist[0].c0min = 0; + boxlist[0].c0max = MAXJSAMPLE >> C0_SHIFT; + boxlist[0].c1min = 0; + boxlist[0].c1max = MAXJSAMPLE >> C1_SHIFT; + boxlist[0].c2min = 0; + boxlist[0].c2max = MAXJSAMPLE >> C2_SHIFT; + /* Shrink it to actually-used volume and set its statistics */ + update_box(cinfo, & boxlist[0]); + /* Perform median-cut to produce final box list */ + numboxes = median_cut(cinfo, boxlist, numboxes, desired_colors); + /* Compute the representative color for each box, fill colormap */ + for (i = 0; i < numboxes; i++) + compute_color(cinfo, & boxlist[i], i); + cinfo->actual_number_of_colors = numboxes; + TRACEMS1(cinfo, 1, JTRC_QUANT_SELECTED, numboxes); +} + + +/* + * These routines are concerned with the time-critical task of mapping input + * colors to the nearest color in the selected colormap. + * + * We re-use the histogram space as an "inverse color map", essentially a + * cache for the results of nearest-color searches. All colors within a + * histogram cell will be mapped to the same colormap entry, namely the one + * closest to the cell's center. This may not be quite the closest entry to + * the actual input color, but it's almost as good. A zero in the cache + * indicates we haven't found the nearest color for that cell yet; the array + * is cleared to zeroes before starting the mapping pass. When we find the + * nearest color for a cell, its colormap index plus one is recorded in the + * cache for future use. The pass2 scanning routines call fill_inverse_cmap + * when they need to use an unfilled entry in the cache. + * + * Our method of efficiently finding nearest colors is based on the "locally + * sorted search" idea described by Heckbert and on the incremental distance + * calculation described by Spencer W. Thomas in chapter III.1 of Graphics + * Gems II (James Arvo, ed. Academic Press, 1991). Thomas points out that + * the distances from a given colormap entry to each cell of the histogram can + * be computed quickly using an incremental method: the differences between + * distances to adjacent cells themselves differ by a constant. This allows a + * fairly fast implementation of the "brute force" approach of computing the + * distance from every colormap entry to every histogram cell. Unfortunately, + * it needs a work array to hold the best-distance-so-far for each histogram + * cell (because the inner loop has to be over cells, not colormap entries). + * The work array elements have to be IJG_INT32s, so the work array would need + * 256Kb at our recommended precision. This is not feasible in DOS machines. + * + * To get around these problems, we apply Thomas' method to compute the + * nearest colors for only the cells within a small subbox of the histogram. + * The work array need be only as big as the subbox, so the memory usage + * problem is solved. Furthermore, we need not fill subboxes that are never + * referenced in pass2; many images use only part of the color gamut, so a + * fair amount of work is saved. An additional advantage of this + * approach is that we can apply Heckbert's locality criterion to quickly + * eliminate colormap entries that are far away from the subbox; typically + * three-fourths of the colormap entries are rejected by Heckbert's criterion, + * and we need not compute their distances to individual cells in the subbox. + * The speed of this approach is heavily influenced by the subbox size: too + * small means too much overhead, too big loses because Heckbert's criterion + * can't eliminate as many colormap entries. Empirically the best subbox + * size seems to be about 1/512th of the histogram (1/8th in each direction). + * + * Thomas' article also describes a refined method which is asymptotically + * faster than the brute-force method, but it is also far more complex and + * cannot efficiently be applied to small subboxes. It is therefore not + * useful for programs intended to be portable to DOS machines. On machines + * with plenty of memory, filling the whole histogram in one shot with Thomas' + * refined method might be faster than the present code --- but then again, + * it might not be any faster, and it's certainly more complicated. + */ + + +/* log2(histogram cells in update box) for each axis; this can be adjusted */ +#define BOX_C0_LOG (HIST_C0_BITS-3) +#define BOX_C1_LOG (HIST_C1_BITS-3) +#define BOX_C2_LOG (HIST_C2_BITS-3) + +#define BOX_C0_ELEMS (1<actual_number_of_colors; + int maxc0, maxc1, maxc2; + int centerc0, centerc1, centerc2; + int i, x, ncolors; + IJG_INT32 minmaxdist, min_dist, max_dist, tdist; + IJG_INT32 mindist[MAXNUMCOLORS]; /* min distance to colormap entry i */ + + /* Compute true coordinates of update box's upper corner and center. + * Actually we compute the coordinates of the center of the upper-corner + * histogram cell, which are the upper bounds of the volume we care about. + * Note that since ">>" rounds down, the "center" values may be closer to + * min than to max; hence comparisons to them must be "<=", not "<". + */ + maxc0 = minc0 + ((1 << BOX_C0_SHIFT) - (1 << C0_SHIFT)); + centerc0 = (minc0 + maxc0) >> 1; + maxc1 = minc1 + ((1 << BOX_C1_SHIFT) - (1 << C1_SHIFT)); + centerc1 = (minc1 + maxc1) >> 1; + maxc2 = minc2 + ((1 << BOX_C2_SHIFT) - (1 << C2_SHIFT)); + centerc2 = (minc2 + maxc2) >> 1; + + /* For each color in colormap, find: + * 1. its minimum squared-distance to any point in the update box + * (zero if color is within update box); + * 2. its maximum squared-distance to any point in the update box. + * Both of these can be found by considering only the corners of the box. + * We save the minimum distance for each color in mindist[]; + * only the smallest maximum distance is of interest. + */ + minmaxdist = 0x7FFFFFFFL; + + for (i = 0; i < numcolors; i++) { + /* We compute the squared-c0-distance term, then add in the other two. */ + x = GETJSAMPLE(cinfo->colormap[0][i]); + if (x < minc0) { + tdist = (x - minc0) * C0_SCALE; + min_dist = tdist*tdist; + tdist = (x - maxc0) * C0_SCALE; + max_dist = tdist*tdist; + } else if (x > maxc0) { + tdist = (x - maxc0) * C0_SCALE; + min_dist = tdist*tdist; + tdist = (x - minc0) * C0_SCALE; + max_dist = tdist*tdist; + } else { + /* within cell range so no contribution to min_dist */ + min_dist = 0; + if (x <= centerc0) { + tdist = (x - maxc0) * C0_SCALE; + max_dist = tdist*tdist; + } else { + tdist = (x - minc0) * C0_SCALE; + max_dist = tdist*tdist; + } + } + + x = GETJSAMPLE(cinfo->colormap[1][i]); + if (x < minc1) { + tdist = (x - minc1) * C1_SCALE; + min_dist += tdist*tdist; + tdist = (x - maxc1) * C1_SCALE; + max_dist += tdist*tdist; + } else if (x > maxc1) { + tdist = (x - maxc1) * C1_SCALE; + min_dist += tdist*tdist; + tdist = (x - minc1) * C1_SCALE; + max_dist += tdist*tdist; + } else { + /* within cell range so no contribution to min_dist */ + if (x <= centerc1) { + tdist = (x - maxc1) * C1_SCALE; + max_dist += tdist*tdist; + } else { + tdist = (x - minc1) * C1_SCALE; + max_dist += tdist*tdist; + } + } + + x = GETJSAMPLE(cinfo->colormap[2][i]); + if (x < minc2) { + tdist = (x - minc2) * C2_SCALE; + min_dist += tdist*tdist; + tdist = (x - maxc2) * C2_SCALE; + max_dist += tdist*tdist; + } else if (x > maxc2) { + tdist = (x - maxc2) * C2_SCALE; + min_dist += tdist*tdist; + tdist = (x - minc2) * C2_SCALE; + max_dist += tdist*tdist; + } else { + /* within cell range so no contribution to min_dist */ + if (x <= centerc2) { + tdist = (x - maxc2) * C2_SCALE; + max_dist += tdist*tdist; + } else { + tdist = (x - minc2) * C2_SCALE; + max_dist += tdist*tdist; + } + } + + mindist[i] = min_dist; /* save away the results */ + if (max_dist < minmaxdist) + minmaxdist = max_dist; + } + + /* Now we know that no cell in the update box is more than minmaxdist + * away from some colormap entry. Therefore, only colors that are + * within minmaxdist of some part of the box need be considered. + */ + ncolors = 0; + for (i = 0; i < numcolors; i++) { + if (mindist[i] <= minmaxdist) + colorlist[ncolors++] = (JSAMPLE) i; + } + return ncolors; +} + + +LOCAL(void) +find_best_colors (j_decompress_ptr cinfo, int minc0, int minc1, int minc2, + int numcolors, JSAMPLE colorlist[], JSAMPLE bestcolor[]) +/* Find the closest colormap entry for each cell in the update box, + * given the list of candidate colors prepared by find_nearby_colors. + * Return the indexes of the closest entries in the bestcolor[] array. + * This routine uses Thomas' incremental distance calculation method to + * find the distance from a colormap entry to successive cells in the box. + */ +{ + int ic0, ic1, ic2; + int i, icolor; + register IJG_INT32 * bptr; /* pointer into bestdist[] array */ + JSAMPLE * cptr; /* pointer into bestcolor[] array */ + IJG_INT32 dist0, dist1; /* initial distance values */ + register IJG_INT32 dist2; /* current distance in inner loop */ + IJG_INT32 xx0, xx1; /* distance increments */ + register IJG_INT32 xx2; + IJG_INT32 inc0, inc1, inc2; /* initial values for increments */ + /* This array holds the distance to the nearest-so-far color for each cell */ + IJG_INT32 bestdist[BOX_C0_ELEMS * BOX_C1_ELEMS * BOX_C2_ELEMS]; + + /* Initialize best-distance for each cell of the update box */ + bptr = bestdist; + for (i = BOX_C0_ELEMS*BOX_C1_ELEMS*BOX_C2_ELEMS-1; i >= 0; i--) + *bptr++ = 0x7FFFFFFFL; + + /* For each color selected by find_nearby_colors, + * compute its distance to the center of each cell in the box. + * If that's less than best-so-far, update best distance and color number. + */ + + /* Nominal steps between cell centers ("x" in Thomas article) */ +#define STEP_C0 ((1 << C0_SHIFT) * C0_SCALE) +#define STEP_C1 ((1 << C1_SHIFT) * C1_SCALE) +#define STEP_C2 ((1 << C2_SHIFT) * C2_SCALE) + + for (i = 0; i < numcolors; i++) { + icolor = GETJSAMPLE(colorlist[i]); + /* Compute (square of) distance from minc0/c1/c2 to this color */ + inc0 = (minc0 - GETJSAMPLE(cinfo->colormap[0][icolor])) * C0_SCALE; + dist0 = inc0*inc0; + inc1 = (minc1 - GETJSAMPLE(cinfo->colormap[1][icolor])) * C1_SCALE; + dist0 += inc1*inc1; + inc2 = (minc2 - GETJSAMPLE(cinfo->colormap[2][icolor])) * C2_SCALE; + dist0 += inc2*inc2; + /* Form the initial difference increments */ + inc0 = inc0 * (2 * STEP_C0) + STEP_C0 * STEP_C0; + inc1 = inc1 * (2 * STEP_C1) + STEP_C1 * STEP_C1; + inc2 = inc2 * (2 * STEP_C2) + STEP_C2 * STEP_C2; + /* Now loop over all cells in box, updating distance per Thomas method */ + bptr = bestdist; + cptr = bestcolor; + xx0 = inc0; + for (ic0 = BOX_C0_ELEMS-1; ic0 >= 0; ic0--) { + dist1 = dist0; + xx1 = inc1; + for (ic1 = BOX_C1_ELEMS-1; ic1 >= 0; ic1--) { + dist2 = dist1; + xx2 = inc2; + for (ic2 = BOX_C2_ELEMS-1; ic2 >= 0; ic2--) { + if (dist2 < *bptr) { + *bptr = dist2; + *cptr = (JSAMPLE) icolor; + } + dist2 += xx2; + xx2 += 2 * STEP_C2 * STEP_C2; + bptr++; + cptr++; + } + dist1 += xx1; + xx1 += 2 * STEP_C1 * STEP_C1; + } + dist0 += xx0; + xx0 += 2 * STEP_C0 * STEP_C0; + } + } +} + + +LOCAL(void) +fill_inverse_cmap (j_decompress_ptr cinfo, int c0, int c1, int c2) +/* Fill the inverse-colormap entries in the update box that contains */ +/* histogram cell c0/c1/c2. (Only that one cell MUST be filled, but */ +/* we can fill as many others as we wish.) */ +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + hist3d histogram = cquantize->histogram; + int minc0, minc1, minc2; /* lower left corner of update box */ + int ic0, ic1, ic2; + register JSAMPLE * cptr; /* pointer into bestcolor[] array */ + register histptr cachep; /* pointer into main cache array */ + /* This array lists the candidate colormap indexes. */ + JSAMPLE colorlist[MAXNUMCOLORS]; + int numcolors; /* number of candidate colors */ + /* This array holds the actually closest colormap index for each cell. */ + JSAMPLE bestcolor[BOX_C0_ELEMS * BOX_C1_ELEMS * BOX_C2_ELEMS]; + + /* Convert cell coordinates to update box ID */ + c0 >>= BOX_C0_LOG; + c1 >>= BOX_C1_LOG; + c2 >>= BOX_C2_LOG; + + /* Compute true coordinates of update box's origin corner. + * Actually we compute the coordinates of the center of the corner + * histogram cell, which are the lower bounds of the volume we care about. + */ + minc0 = (c0 << BOX_C0_SHIFT) + ((1 << C0_SHIFT) >> 1); + minc1 = (c1 << BOX_C1_SHIFT) + ((1 << C1_SHIFT) >> 1); + minc2 = (c2 << BOX_C2_SHIFT) + ((1 << C2_SHIFT) >> 1); + + /* Determine which colormap entries are close enough to be candidates + * for the nearest entry to some cell in the update box. + */ + numcolors = find_nearby_colors(cinfo, minc0, minc1, minc2, colorlist); + + /* Determine the actually nearest colors. */ + find_best_colors(cinfo, minc0, minc1, minc2, numcolors, colorlist, + bestcolor); + + /* Save the best color numbers (plus 1) in the main cache array */ + c0 <<= BOX_C0_LOG; /* convert ID back to base cell indexes */ + c1 <<= BOX_C1_LOG; + c2 <<= BOX_C2_LOG; + cptr = bestcolor; + for (ic0 = 0; ic0 < BOX_C0_ELEMS; ic0++) { + for (ic1 = 0; ic1 < BOX_C1_ELEMS; ic1++) { + cachep = & histogram[c0+ic0][c1+ic1][c2]; + for (ic2 = 0; ic2 < BOX_C2_ELEMS; ic2++) { + *cachep++ = (histcell) (GETJSAMPLE(*cptr++) + 1); + } + } + } +} + + +/* + * Map some rows of pixels to the output colormapped representation. + */ + +METHODDEF(void) +pass2_no_dither (j_decompress_ptr cinfo, + JSAMPARRAY input_buf, JSAMPARRAY output_buf, int num_rows) +/* This version performs no dithering */ +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + hist3d histogram = cquantize->histogram; + register JSAMPROW inptr, outptr; + register histptr cachep; + register int c0, c1, c2; + int row; + JDIMENSION col; + JDIMENSION width = cinfo->output_width; + + for (row = 0; row < num_rows; row++) { + inptr = input_buf[row]; + outptr = output_buf[row]; + for (col = width; col > 0; col--) { + /* get pixel value and index into the cache */ + c0 = GETJSAMPLE(*inptr++) >> C0_SHIFT; + c1 = GETJSAMPLE(*inptr++) >> C1_SHIFT; + c2 = GETJSAMPLE(*inptr++) >> C2_SHIFT; + cachep = & histogram[c0][c1][c2]; + /* If we have not seen this color before, find nearest colormap entry */ + /* and update the cache */ + if (*cachep == 0) + fill_inverse_cmap(cinfo, c0,c1,c2); + /* Now emit the colormap index for this cell */ + *outptr++ = (JSAMPLE) (*cachep - 1); + } + } +} + + +METHODDEF(void) +pass2_fs_dither (j_decompress_ptr cinfo, + JSAMPARRAY input_buf, JSAMPARRAY output_buf, int num_rows) +/* This version performs Floyd-Steinberg dithering */ +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + hist3d histogram = cquantize->histogram; + register LOCFSERROR cur0, cur1, cur2; /* current error or pixel value */ + LOCFSERROR belowerr0, belowerr1, belowerr2; /* error for pixel below cur */ + LOCFSERROR bpreverr0, bpreverr1, bpreverr2; /* error for below/prev col */ + register FSERRPTR errorptr; /* => fserrors[] at column before current */ + JSAMPROW inptr; /* => current input pixel */ + JSAMPROW outptr; /* => current output pixel */ + histptr cachep; + int dir; /* +1 or -1 depending on direction */ + int dir3; /* 3*dir, for advancing inptr & errorptr */ + int row; + JDIMENSION col; + JDIMENSION width = cinfo->output_width; + JSAMPLE *range_limit = cinfo->sample_range_limit; + int *error_limit = cquantize->error_limiter; + JSAMPROW colormap0 = cinfo->colormap[0]; + JSAMPROW colormap1 = cinfo->colormap[1]; + JSAMPROW colormap2 = cinfo->colormap[2]; + SHIFT_TEMPS + + for (row = 0; row < num_rows; row++) { + inptr = input_buf[row]; + outptr = output_buf[row]; + if (cquantize->on_odd_row) { + /* work right to left in this row */ + inptr += (width-1) * 3; /* so point to rightmost pixel */ + outptr += width-1; + dir = -1; + dir3 = -3; + errorptr = cquantize->fserrors + (width+1)*3; /* => entry after last column */ + cquantize->on_odd_row = FALSE; /* flip for next time */ + } else { + /* work left to right in this row */ + dir = 1; + dir3 = 3; + errorptr = cquantize->fserrors; /* => entry before first real column */ + cquantize->on_odd_row = TRUE; /* flip for next time */ + } + /* Preset error values: no error propagated to first pixel from left */ + cur0 = cur1 = cur2 = 0; + /* and no error propagated to row below yet */ + belowerr0 = belowerr1 = belowerr2 = 0; + bpreverr0 = bpreverr1 = bpreverr2 = 0; + + for (col = width; col > 0; col--) { + /* curN holds the error propagated from the previous pixel on the + * current line. Add the error propagated from the previous line + * to form the complete error correction term for this pixel, and + * round the error term (which is expressed * 16) to an integer. + * RIGHT_SHIFT rounds towards minus infinity, so adding 8 is correct + * for either sign of the error value. + * Note: errorptr points to *previous* column's array entry. + */ + cur0 = RIGHT_SHIFT(cur0 + errorptr[dir3+0] + 8, 4); + cur1 = RIGHT_SHIFT(cur1 + errorptr[dir3+1] + 8, 4); + cur2 = RIGHT_SHIFT(cur2 + errorptr[dir3+2] + 8, 4); + /* Limit the error using transfer function set by init_error_limit. + * See comments with init_error_limit for rationale. + */ + cur0 = error_limit[cur0]; + cur1 = error_limit[cur1]; + cur2 = error_limit[cur2]; + /* Form pixel value + error, and range-limit to 0..MAXJSAMPLE. + * The maximum error is +- MAXJSAMPLE (or less with error limiting); + * this sets the required size of the range_limit array. + */ + cur0 += GETJSAMPLE(inptr[0]); + cur1 += GETJSAMPLE(inptr[1]); + cur2 += GETJSAMPLE(inptr[2]); + cur0 = GETJSAMPLE(range_limit[cur0]); + cur1 = GETJSAMPLE(range_limit[cur1]); + cur2 = GETJSAMPLE(range_limit[cur2]); + /* Index into the cache with adjusted pixel value */ + cachep = & histogram[cur0>>C0_SHIFT][cur1>>C1_SHIFT][cur2>>C2_SHIFT]; + /* If we have not seen this color before, find nearest colormap */ + /* entry and update the cache */ + if (*cachep == 0) + fill_inverse_cmap(cinfo, (int)(cur0>>C0_SHIFT),(int)(cur1>>C1_SHIFT),(int)(cur2>>C2_SHIFT)); + /* Now emit the colormap index for this cell */ + { register int pixcode = *cachep - 1; + *outptr = (JSAMPLE) pixcode; + /* Compute representation error for this pixel */ + cur0 -= GETJSAMPLE(colormap0[pixcode]); + cur1 -= GETJSAMPLE(colormap1[pixcode]); + cur2 -= GETJSAMPLE(colormap2[pixcode]); + } + /* Compute error fractions to be propagated to adjacent pixels. + * Add these into the running sums, and simultaneously shift the + * next-line error sums left by 1 column. + */ + { register LOCFSERROR bnexterr, delta; + + bnexterr = cur0; /* Process component 0 */ + delta = cur0 * 2; + cur0 += delta; /* form error * 3 */ + errorptr[0] = (FSERROR) (bpreverr0 + cur0); + cur0 += delta; /* form error * 5 */ + bpreverr0 = belowerr0 + cur0; + belowerr0 = bnexterr; + cur0 += delta; /* form error * 7 */ + bnexterr = cur1; /* Process component 1 */ + delta = cur1 * 2; + cur1 += delta; /* form error * 3 */ + errorptr[1] = (FSERROR) (bpreverr1 + cur1); + cur1 += delta; /* form error * 5 */ + bpreverr1 = belowerr1 + cur1; + belowerr1 = bnexterr; + cur1 += delta; /* form error * 7 */ + bnexterr = cur2; /* Process component 2 */ + delta = cur2 * 2; + cur2 += delta; /* form error * 3 */ + errorptr[2] = (FSERROR) (bpreverr2 + cur2); + cur2 += delta; /* form error * 5 */ + bpreverr2 = belowerr2 + cur2; + belowerr2 = bnexterr; + cur2 += delta; /* form error * 7 */ + } + /* At this point curN contains the 7/16 error value to be propagated + * to the next pixel on the current line, and all the errors for the + * next line have been shifted over. We are therefore ready to move on. + */ + inptr += dir3; /* Advance pixel pointers to next column */ + outptr += dir; + errorptr += dir3; /* advance errorptr to current column */ + } + /* Post-loop cleanup: we must unload the final error values into the + * final fserrors[] entry. Note we need not unload belowerrN because + * it is for the dummy column before or after the actual array. + */ + errorptr[0] = (FSERROR) bpreverr0; /* unload prev errs into array */ + errorptr[1] = (FSERROR) bpreverr1; + errorptr[2] = (FSERROR) bpreverr2; + } +} + + +/* + * Initialize the error-limiting transfer function (lookup table). + * The raw F-S error computation can potentially compute error values of up to + * +- MAXJSAMPLE. But we want the maximum correction applied to a pixel to be + * much less, otherwise obviously wrong pixels will be created. (Typical + * effects include weird fringes at color-area boundaries, isolated bright + * pixels in a dark area, etc.) The standard advice for avoiding this problem + * is to ensure that the "corners" of the color cube are allocated as output + * colors; then repeated errors in the same direction cannot cause cascading + * error buildup. However, that only prevents the error from getting + * completely out of hand; Aaron Giles reports that error limiting improves + * the results even with corner colors allocated. + * A simple clamping of the error values to about +- MAXJSAMPLE/8 works pretty + * well, but the smoother transfer function used below is even better. Thanks + * to Aaron Giles for this idea. + */ + +LOCAL(void) +init_error_limit (j_decompress_ptr cinfo) +/* Allocate and fill in the error_limiter table */ +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + int * table; + int in, out; + + table = (int *) (*cinfo->mem->alloc_small) + ((j_common_ptr) cinfo, JPOOL_IMAGE, (MAXJSAMPLE*2+1) * SIZEOF(int)); + table += MAXJSAMPLE; /* so can index -MAXJSAMPLE .. +MAXJSAMPLE */ + cquantize->error_limiter = table; + +#define STEPSIZE ((MAXJSAMPLE+1)/16) + /* Map errors 1:1 up to +- MAXJSAMPLE/16 */ + out = 0; + for (in = 0; in < STEPSIZE; in++, out++) { + table[in] = out; table[-in] = -out; + } + /* Map errors 1:2 up to +- 3*MAXJSAMPLE/16 */ + for (; in < STEPSIZE*3; in++, out += (in&1) ? 0 : 1) { + table[in] = out; table[-in] = -out; + } + /* Clamp the rest to final out value (which is (MAXJSAMPLE+1)/8) */ + for (; in <= MAXJSAMPLE; in++) { + table[in] = out; table[-in] = -out; + } +#undef STEPSIZE +} + + +/* + * Finish up at the end of each pass. + */ + +METHODDEF(void) +finish_pass1 (j_decompress_ptr cinfo) +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + + /* Select the representative colors and fill in cinfo->colormap */ + cinfo->colormap = cquantize->sv_colormap; + select_colors(cinfo, cquantize->desired); + /* Force next pass to zero the color index table */ + cquantize->needs_zeroed = TRUE; +} + + +METHODDEF(void) +finish_pass2 (j_decompress_ptr cinfo) +{ + /* no work */ +} + + +/* + * Initialize for each processing pass. + */ + +METHODDEF(void) +start_pass_2_quant (j_decompress_ptr cinfo, boolean is_pre_scan) +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + hist3d histogram = cquantize->histogram; + int i; + + /* Only F-S dithering or no dithering is supported. */ + /* If user asks for ordered dither, give him F-S. */ + if (cinfo->dither_mode != JDITHER_NONE) + cinfo->dither_mode = JDITHER_FS; + + if (is_pre_scan) { + /* Set up method pointers */ + cquantize->pub.color_quantize = prescan_quantize; + cquantize->pub.finish_pass = finish_pass1; + cquantize->needs_zeroed = TRUE; /* Always zero histogram */ + } else { + /* Set up method pointers */ + if (cinfo->dither_mode == JDITHER_FS) + cquantize->pub.color_quantize = pass2_fs_dither; + else + cquantize->pub.color_quantize = pass2_no_dither; + cquantize->pub.finish_pass = finish_pass2; + + /* Make sure color count is acceptable */ + i = cinfo->actual_number_of_colors; + if (i < 1) + ERREXIT1(cinfo, JERR_QUANT_FEW_COLORS, 1); + if (i > MAXNUMCOLORS) + ERREXIT1(cinfo, JERR_QUANT_MANY_COLORS, MAXNUMCOLORS); + + if (cinfo->dither_mode == JDITHER_FS) { + size_t arraysize = (size_t) ((cinfo->output_width + 2) * + (3 * SIZEOF(FSERROR))); + /* Allocate Floyd-Steinberg workspace if we didn't already. */ + if (cquantize->fserrors == NULL) + cquantize->fserrors = (FSERRPTR) (*cinfo->mem->alloc_large) + ((j_common_ptr) cinfo, JPOOL_IMAGE, arraysize); + /* Initialize the propagated errors to zero. */ + jzero_far((void FAR *) cquantize->fserrors, arraysize); + /* Make the error-limit table if we didn't already. */ + if (cquantize->error_limiter == NULL) + init_error_limit(cinfo); + cquantize->on_odd_row = FALSE; + } + + } + /* Zero the histogram or inverse color map, if necessary */ + if (cquantize->needs_zeroed) { + for (i = 0; i < HIST_C0_ELEMS; i++) { + jzero_far((void FAR *) histogram[i], + HIST_C1_ELEMS*HIST_C2_ELEMS * SIZEOF(histcell)); + } + cquantize->needs_zeroed = FALSE; + } +} + + +/* + * Switch to a new external colormap between output passes. + */ + +METHODDEF(void) +new_color_map_2_quant (j_decompress_ptr cinfo) +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + + /* Reset the inverse color map */ + cquantize->needs_zeroed = TRUE; +} + + +/* + * Module initialization routine for 2-pass color quantization. + */ + +GLOBAL(void) +jinit_2pass_quantizer (j_decompress_ptr cinfo) +{ + my_cquantize_ptr cquantize; + int i; + + cquantize = (my_cquantize_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_cquantizer)); + cinfo->cquantize = (struct jpeg_color_quantizer *) cquantize; + cquantize->pub.start_pass = start_pass_2_quant; + cquantize->pub.new_color_map = new_color_map_2_quant; + cquantize->fserrors = NULL; /* flag optional arrays not allocated */ + cquantize->error_limiter = NULL; + + /* Make sure jdmaster didn't give me a case I can't handle */ + if (cinfo->out_color_components != 3) + ERREXIT(cinfo, JERR_NOTIMPL); + + /* Allocate the histogram/inverse colormap storage */ + cquantize->histogram = (hist3d) (*cinfo->mem->alloc_small) + ((j_common_ptr) cinfo, JPOOL_IMAGE, HIST_C0_ELEMS * SIZEOF(hist2d)); + for (i = 0; i < HIST_C0_ELEMS; i++) { + cquantize->histogram[i] = (hist2d) (*cinfo->mem->alloc_large) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + HIST_C1_ELEMS*HIST_C2_ELEMS * SIZEOF(histcell)); + } + cquantize->needs_zeroed = TRUE; /* histogram is garbage now */ + + /* Allocate storage for the completed colormap, if required. + * We do this now since it is FAR storage and may affect + * the memory manager's space calculations. + */ + if (cinfo->enable_2pass_quant) { + /* Make sure color count is acceptable */ + int desired = cinfo->desired_number_of_colors; + /* Lower bound on # of colors ... somewhat arbitrary as long as > 0 */ + if (desired < 8) + ERREXIT1(cinfo, JERR_QUANT_FEW_COLORS, 8); + /* Make sure colormap indexes can be represented by JSAMPLEs */ + if (desired > MAXNUMCOLORS) + ERREXIT1(cinfo, JERR_QUANT_MANY_COLORS, MAXNUMCOLORS); + cquantize->sv_colormap = (*cinfo->mem->alloc_sarray) + ((j_common_ptr) cinfo,JPOOL_IMAGE, (JDIMENSION) desired, (JDIMENSION) 3); + cquantize->desired = desired; + } else + cquantize->sv_colormap = NULL; + + /* Only F-S dithering or no dithering is supported. */ + /* If user asks for ordered dither, give him F-S. */ + if (cinfo->dither_mode != JDITHER_NONE) + cinfo->dither_mode = JDITHER_FS; + + /* Allocate Floyd-Steinberg workspace if necessary. + * This isn't really needed until pass 2, but again it is FAR storage. + * Although we will cope with a later change in dither_mode, + * we do not promise to honor max_memory_to_use if dither_mode changes. + */ + if (cinfo->dither_mode == JDITHER_FS) { + cquantize->fserrors = (FSERRPTR) (*cinfo->mem->alloc_large) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + (size_t) ((cinfo->output_width + 2) * (3 * SIZEOF(FSERROR)))); + /* Might as well create the error-limiting table too. */ + init_error_limit(cinfo); + } +} + +#endif /* QUANT_2PASS_SUPPORTED */ diff --git a/dcmjpeg/libijg16/jutils.c b/dcmjpeg/libijg16/jutils.c new file mode 100644 index 00000000..68de76fc --- /dev/null +++ b/dcmjpeg/libijg16/jutils.c @@ -0,0 +1,179 @@ +/* + * jutils.c + * + * Copyright (C) 1991-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains tables and miscellaneous utility routines needed + * for both compression and decompression. + * Note we prefix all global names with "j" to minimize conflicts with + * a surrounding application. + */ + +#define JPEG_INTERNALS +#include "jinclude16.h" +#include "jpeglib16.h" + + +/* + * jpeg_zigzag_order[i] is the zigzag-order position of the i'th element + * of a DCT block read in natural order (left to right, top to bottom). + */ + +#if 0 /* This table is not actually needed in v6a */ + +const int jpeg_zigzag_order[DCTSIZE2] = { + 0, 1, 5, 6, 14, 15, 27, 28, + 2, 4, 7, 13, 16, 26, 29, 42, + 3, 8, 12, 17, 25, 30, 41, 43, + 9, 11, 18, 24, 31, 40, 44, 53, + 10, 19, 23, 32, 39, 45, 52, 54, + 20, 22, 33, 38, 46, 51, 55, 60, + 21, 34, 37, 47, 50, 56, 59, 61, + 35, 36, 48, 49, 57, 58, 62, 63 +}; + +#endif + +/* + * jpeg_natural_order[i] is the natural-order position of the i'th element + * of zigzag order. + * + * When reading corrupted data, the Huffman decoders could attempt + * to reference an entry beyond the end of this array (if the decoded + * zero run length reaches past the end of the block). To prevent + * wild stores without adding an inner-loop test, we put some extra + * "63"s after the real entries. This will cause the extra coefficient + * to be stored in location 63 of the block, not somewhere random. + * The worst case would be a run-length of 15, which means we need 16 + * fake entries. + */ + +const int jpeg_natural_order[DCTSIZE2+16] = { + 0, 1, 8, 16, 9, 2, 3, 10, + 17, 24, 32, 25, 18, 11, 4, 5, + 12, 19, 26, 33, 40, 48, 41, 34, + 27, 20, 13, 6, 7, 14, 21, 28, + 35, 42, 49, 56, 57, 50, 43, 36, + 29, 22, 15, 23, 30, 37, 44, 51, + 58, 59, 52, 45, 38, 31, 39, 46, + 53, 60, 61, 54, 47, 55, 62, 63, + 63, 63, 63, 63, 63, 63, 63, 63, /* extra entries for safety in decoder */ + 63, 63, 63, 63, 63, 63, 63, 63 +}; + + +/* + * Arithmetic utilities + */ + +GLOBAL(long) +jdiv_round_up (long a, long b) +/* Compute a/b rounded up to next integer, ie, ceil(a/b) */ +/* Assumes a >= 0, b > 0 */ +{ + return (a + b - 1L) / b; +} + + +GLOBAL(long) +jround_up (long a, long b) +/* Compute a rounded up to next multiple of b, ie, ceil(a/b)*b */ +/* Assumes a >= 0, b > 0 */ +{ + a += b - 1L; + return a - (a % b); +} + + +/* On normal machines we can apply MEMCOPY() and MEMZERO() to sample arrays + * and coefficient-block arrays. This won't work on 80x86 because the arrays + * are FAR and we're assuming a small-pointer memory model. However, some + * DOS compilers provide far-pointer versions of memcpy() and memset() even + * in the small-model libraries. These will be used if USE_FMEM is defined. + * Otherwise, the routines below do it the hard way. (The performance cost + * is not all that great, because these routines aren't very heavily used.) + */ + +#ifndef NEED_FAR_POINTERS /* normal case, same as regular macros */ +#define FMEMCOPY(dest,src,size) MEMCOPY(dest,src,size) +#define FMEMZERO(target,size) MEMZERO(target,size) +#else /* 80x86 case, define if we can */ +#ifdef USE_FMEM +#define FMEMCOPY(dest,src,size) _fmemcpy((void FAR *)(dest), (const void FAR *)(src), (size_t)(size)) +#define FMEMZERO(target,size) _fmemset((void FAR *)(target), 0, (size_t)(size)) +#endif +#endif + + +GLOBAL(void) +jcopy_sample_rows (JSAMPARRAY input_array, int source_row, + JSAMPARRAY output_array, int dest_row, + int num_rows, JDIMENSION num_cols) +/* Copy some rows of samples from one place to another. + * num_rows rows are copied from input_array[source_row++] + * to output_array[dest_row++]; these areas may overlap for duplication. + * The source and destination arrays must be at least as wide as num_cols. + */ +{ + register JSAMPROW inptr, outptr; +#ifdef FMEMCOPY + register size_t count = (size_t) (num_cols * SIZEOF(JSAMPLE)); +#else + register JDIMENSION count; +#endif + register int row; + + input_array += source_row; + output_array += dest_row; + + for (row = num_rows; row > 0; row--) { + inptr = *input_array++; + outptr = *output_array++; +#ifdef FMEMCOPY + FMEMCOPY(outptr, inptr, count); +#else + for (count = num_cols; count > 0; count--) + *outptr++ = *inptr++; /* needn't bother with GETJSAMPLE() here */ +#endif + } +} + + +GLOBAL(void) +jcopy_block_row (JBLOCKROW input_row, JBLOCKROW output_row, + JDIMENSION num_blocks) +/* Copy a row of coefficient blocks from one place to another. */ +{ +#ifdef FMEMCOPY + FMEMCOPY(output_row, input_row, num_blocks * (DCTSIZE2 * SIZEOF(JCOEF))); +#else + register JCOEFPTR inptr, outptr; + register long count; + + inptr = (JCOEFPTR) input_row; + outptr = (JCOEFPTR) output_row; + for (count = (long) num_blocks * DCTSIZE2; count > 0; count--) { + *outptr++ = *inptr++; + } +#endif +} + + +GLOBAL(void) +jzero_far (void FAR * target, size_t bytestozero) +/* Zero out a chunk of FAR memory. */ +/* This might be sample-array data, block-array data, or alloc_large data. */ +{ +#ifdef FMEMZERO + FMEMZERO(target, bytestozero); +#else + register char FAR * ptr = (char FAR *) target; + register size_t count; + + for (count = bytestozero; count > 0; count--) { + *ptr++ = 0; + } +#endif +} diff --git a/dcmjpeg/libijg16/jversion16.h b/dcmjpeg/libijg16/jversion16.h new file mode 100644 index 00000000..6472c58d --- /dev/null +++ b/dcmjpeg/libijg16/jversion16.h @@ -0,0 +1,14 @@ +/* + * jversion.h + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains software version identification. + */ + + +#define JVERSION "6b 27-Mar-1998" + +#define JCOPYRIGHT "Copyright (C) 1998, Thomas G. Lane" diff --git a/dcmjpeg/libijg8/CMakeLists.txt b/dcmjpeg/libijg8/CMakeLists.txt new file mode 100644 index 00000000..e3f8f683 --- /dev/null +++ b/dcmjpeg/libijg8/CMakeLists.txt @@ -0,0 +1,2 @@ +# create library from source files +DCMTK_ADD_LIBRARY(ijg8 jaricom jcapimin jcapistd jcarith jccoefct jccolor jcdctmgr jcdiffct jchuff jcinit jclhuff jclossls jclossy jcmainct jcmarker jcmaster jcodec jcomapi jcparam jcphuff jcpred jcprepct jcsample jcscale jcshuff jctrans jdapimin jdapistd jdarith jdatadst jdatasrc jdcoefct jdcolor jddctmgr jddiffct jdhuff jdinput jdlhuff jdlossls jdlossy jdmainct jdmarker jdmaster jdmerge jdphuff jdpostct jdpred jdsample jdscale jdshuff jdtrans jerror jfdctflt jfdctfst jfdctint jidctflt jidctfst jidctint jidctred jmemmgr jmemnobs jquant1 jquant2 jutils) diff --git a/dcmjpeg/libijg8/Makefile.dep b/dcmjpeg/libijg8/Makefile.dep new file mode 100644 index 00000000..b4576e5d --- /dev/null +++ b/dcmjpeg/libijg8/Makefile.dep @@ -0,0 +1,220 @@ +jaricom.o: jaricom.c jinclude8.h jconfig8.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib8.h jmorecfg8.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint8.h jerror8.h +jcapimin.o: jcapimin.c jinclude8.h jconfig8.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib8.h jmorecfg8.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint8.h jerror8.h +jcapistd.o: jcapistd.c jinclude8.h jconfig8.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib8.h jmorecfg8.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint8.h jerror8.h +jcarith.o: jcarith.c jinclude8.h jconfig8.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib8.h jmorecfg8.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint8.h jerror8.h +jccoefct.o: jccoefct.c jinclude8.h jconfig8.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib8.h jmorecfg8.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint8.h jerror8.h \ + jlossy8.h +jccolor.o: jccolor.c jinclude8.h jconfig8.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib8.h jmorecfg8.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint8.h jerror8.h +jcdctmgr.o: jcdctmgr.c jinclude8.h jconfig8.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib8.h jmorecfg8.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint8.h jerror8.h \ + jlossy8.h jdct8.h +jcdiffct.o: jcdiffct.c jinclude8.h jconfig8.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib8.h jmorecfg8.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint8.h jerror8.h \ + jlossls8.h +jchuff.o: jchuff.c jinclude8.h jconfig8.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib8.h jmorecfg8.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint8.h jerror8.h \ + jchuff8.h +jcinit.o: jcinit.c jinclude8.h jconfig8.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib8.h jmorecfg8.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint8.h jerror8.h +jclhuff.o: jclhuff.c jinclude8.h jconfig8.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib8.h jmorecfg8.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint8.h jerror8.h \ + jlossls8.h jchuff8.h +jclossls.o: jclossls.c jinclude8.h jconfig8.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib8.h jmorecfg8.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint8.h jerror8.h \ + jlossls8.h +jclossy.o: jclossy.c jinclude8.h jconfig8.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib8.h jmorecfg8.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint8.h jerror8.h \ + jlossy8.h +jcmainct.o: jcmainct.c jinclude8.h jconfig8.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib8.h jmorecfg8.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint8.h jerror8.h +jcmarker.o: jcmarker.c jinclude8.h jconfig8.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib8.h jmorecfg8.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint8.h jerror8.h +jcmaster.o: jcmaster.c jinclude8.h jconfig8.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib8.h jmorecfg8.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint8.h jerror8.h \ + jlossy8.h +jcodec.o: jcodec.c jinclude8.h jconfig8.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib8.h jmorecfg8.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint8.h jerror8.h \ + jlossy8.h jlossls8.h +jcomapi.o: jcomapi.c jinclude8.h jconfig8.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib8.h jmorecfg8.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint8.h jerror8.h +jcparam.o: jcparam.c jinclude8.h jconfig8.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib8.h jmorecfg8.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint8.h jerror8.h +jcphuff.o: jcphuff.c jinclude8.h jconfig8.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib8.h jmorecfg8.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint8.h jerror8.h \ + jlossy8.h jchuff8.h +jcpred.o: jcpred.c jinclude8.h jconfig8.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib8.h jmorecfg8.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint8.h jerror8.h \ + jlossls8.h +jcprepct.o: jcprepct.c jinclude8.h jconfig8.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib8.h jmorecfg8.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint8.h jerror8.h +jcsample.o: jcsample.c jinclude8.h jconfig8.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib8.h jmorecfg8.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint8.h jerror8.h +jcscale.o: jcscale.c jinclude8.h jconfig8.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib8.h jmorecfg8.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint8.h jerror8.h \ + jlossls8.h +jcshuff.o: jcshuff.c jinclude8.h jconfig8.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib8.h jmorecfg8.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint8.h jerror8.h \ + jlossy8.h jchuff8.h +jctrans.o: jctrans.c jinclude8.h jconfig8.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib8.h jmorecfg8.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint8.h jerror8.h \ + jlossy8.h +jdapimin.o: jdapimin.c jinclude8.h jconfig8.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib8.h jmorecfg8.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint8.h jerror8.h +jdapistd.o: jdapistd.c jinclude8.h jconfig8.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib8.h jmorecfg8.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint8.h jerror8.h +jdarith.o: jdarith.c jinclude8.h jconfig8.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib8.h jmorecfg8.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint8.h jerror8.h +jdatadst.o: jdatadst.c jinclude8.h jconfig8.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib8.h jmorecfg8.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jerror8.h +jdatasrc.o: jdatasrc.c jinclude8.h jconfig8.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib8.h jmorecfg8.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jerror8.h +jdcoefct.o: jdcoefct.c jinclude8.h jconfig8.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib8.h jmorecfg8.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint8.h jerror8.h \ + jlossy8.h +jdcolor.o: jdcolor.c jinclude8.h jconfig8.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib8.h jmorecfg8.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint8.h jerror8.h +jddctmgr.o: jddctmgr.c jinclude8.h jconfig8.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib8.h jmorecfg8.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint8.h jerror8.h \ + jlossy8.h jdct8.h +jddiffct.o: jddiffct.c jinclude8.h jconfig8.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib8.h jmorecfg8.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint8.h jerror8.h \ + jlossls8.h +jdhuff.o: jdhuff.c jinclude8.h jconfig8.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib8.h jmorecfg8.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint8.h jerror8.h \ + jlossy8.h jlossls8.h jdhuff8.h +jdinput.o: jdinput.c jinclude8.h jconfig8.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib8.h jmorecfg8.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint8.h jerror8.h +jdlhuff.o: jdlhuff.c jinclude8.h jconfig8.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib8.h jmorecfg8.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint8.h jerror8.h \ + jlossls8.h jdhuff8.h +jdlossls.o: jdlossls.c jinclude8.h jconfig8.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib8.h jmorecfg8.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint8.h jerror8.h \ + jlossls8.h +jdlossy.o: jdlossy.c jinclude8.h jconfig8.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib8.h jmorecfg8.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint8.h jerror8.h \ + jlossy8.h +jdmainct.o: jdmainct.c jinclude8.h jconfig8.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib8.h jmorecfg8.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint8.h jerror8.h +jdmarker.o: jdmarker.c jinclude8.h jconfig8.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib8.h jmorecfg8.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint8.h jerror8.h +jdmaster.o: jdmaster.c jinclude8.h jconfig8.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib8.h jmorecfg8.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint8.h jerror8.h +jdmerge.o: jdmerge.c jinclude8.h jconfig8.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib8.h jmorecfg8.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint8.h jerror8.h +jdphuff.o: jdphuff.c jinclude8.h jconfig8.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib8.h jmorecfg8.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint8.h jerror8.h \ + jlossy8.h jdhuff8.h +jdpostct.o: jdpostct.c jinclude8.h jconfig8.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib8.h jmorecfg8.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint8.h jerror8.h +jdpred.o: jdpred.c jinclude8.h jconfig8.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib8.h jmorecfg8.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint8.h jerror8.h \ + jlossls8.h +jdsample.o: jdsample.c jinclude8.h jconfig8.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib8.h jmorecfg8.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint8.h jerror8.h +jdscale.o: jdscale.c jinclude8.h jconfig8.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib8.h jmorecfg8.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint8.h jerror8.h \ + jlossls8.h +jdshuff.o: jdshuff.c jinclude8.h jconfig8.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib8.h jmorecfg8.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint8.h jerror8.h \ + jlossy8.h jdhuff8.h +jdtrans.o: jdtrans.c jinclude8.h jconfig8.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib8.h jmorecfg8.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint8.h jerror8.h \ + jlossy8.h +jerror.o: jerror.c jinclude8.h jconfig8.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib8.h jmorecfg8.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jversion8.h jerror8.h +jfdctflt.o: jfdctflt.c jinclude8.h jconfig8.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib8.h jmorecfg8.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint8.h jerror8.h jdct8.h +jfdctfst.o: jfdctfst.c jinclude8.h jconfig8.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib8.h jmorecfg8.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint8.h jerror8.h jdct8.h +jfdctint.o: jfdctint.c jinclude8.h jconfig8.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib8.h jmorecfg8.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint8.h jerror8.h jdct8.h +jidctflt.o: jidctflt.c jinclude8.h jconfig8.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib8.h jmorecfg8.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint8.h jerror8.h jdct8.h +jidctfst.o: jidctfst.c jinclude8.h jconfig8.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib8.h jmorecfg8.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint8.h jerror8.h jdct8.h +jidctint.o: jidctint.c jinclude8.h jconfig8.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib8.h jmorecfg8.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint8.h jerror8.h jdct8.h +jidctred.o: jidctred.c jinclude8.h jconfig8.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib8.h jmorecfg8.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint8.h jerror8.h jdct8.h +jmemmgr.o: jmemmgr.c jinclude8.h jconfig8.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib8.h jmorecfg8.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint8.h jerror8.h \ + jmemsys8.h +jmemnobs.o: jmemnobs.c jinclude8.h jconfig8.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib8.h jmorecfg8.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint8.h jerror8.h \ + jmemsys8.h +jquant1.o: jquant1.c jinclude8.h jconfig8.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib8.h jmorecfg8.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint8.h jerror8.h +jquant2.o: jquant2.c jinclude8.h jconfig8.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib8.h jmorecfg8.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint8.h jerror8.h +jutils.o: jutils.c jinclude8.h jconfig8.h \ + ../../config/include/dcmtk/config/osconfig.h jpeglib8.h jmorecfg8.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h jpegint8.h jerror8.h diff --git a/dcmjpeg/libijg8/Makefile.in b/dcmjpeg/libijg8/Makefile.in new file mode 100644 index 00000000..58d52da3 --- /dev/null +++ b/dcmjpeg/libijg8/Makefile.in @@ -0,0 +1,59 @@ +# +# Makefile for dcmjpeg/libijg8 +# + +@SET_MAKE@ + +SHELL = /bin/sh +VPATH = @srcdir@:@top_srcdir@/include:@top_srcdir@/@configdir@/include +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +configdir = @top_srcdir@/@configdir@ + +include $(configdir)/@common_makefile@ + +ofstddir = $(top_srcdir)/../ofstd + +LOCALINCLUDES = -I$(ofstddir)/include +LOCALDEFS = -DWITH_ARITHMETIC_PATCH + +objs = jcomapi.o jcodec.o jutils.o jerror.o jmemmgr.o \ + jmemnobs.o jcapimin.o jcapistd.o jctrans.o jcparam.o \ + jdatadst.o jcinit.o jcmaster.o jcmarker.o jcmainct.o \ + jcprepct.o jclossls.o jclossy.o jccoefct.o jccolor.o \ + jcsample.o jchuff.o jcphuff.o jcshuff.o jclhuff.o \ + jcpred.o jcscale.o jcdiffct.o jcdctmgr.o jfdctfst.o \ + jfdctflt.o jfdctint.o jdapimin.o jdapistd.o jdtrans.o \ + jdatasrc.o jdmaster.o jdinput.o jdmarker.o jdlossls.o \ + jdlossy.o jdhuff.o jdlhuff.o jdphuff.o jdshuff.o \ + jdpred.o jdscale.o jddiffct.o jdmainct.o jdcoefct.o \ + jdpostct.o jddctmgr.o jidctfst.o jidctflt.o jidctint.o \ + jidctred.o jdsample.o jdcolor.o jquant1.o jquant2.o \ + jdmerge.o jcarith.o jdarith.o jaricom.o +library = libijg8.$(LIBEXT) + + +all: $(library) + +install: $(library) + $(configdir)/mkinstalldirs $(DESTDIR)$(libdir) + $(INSTALL_DATA) $(library) $(DESTDIR)$(libdir)/$(library) + $(RANLIB) $(DESTDIR)$(libdir)/$(library) + + +$(library): $(objs) + $(AR) $(ARFLAGS) $@ $(objs) + $(RANLIB) $@ + + +clean: + rm -f $(objs) $(library) $(TRASH) + +distclean: + rm -f $(objs) $(library) $(DISTTRASH) + + +dependencies: + $(CXX) -MM $(defines) $(includes) $(CPPFLAGS) $(CXXFLAGS) *.c > $(DEP) + +include $(DEP) diff --git a/dcmjpeg/libijg8/jaricom.c b/dcmjpeg/libijg8/jaricom.c new file mode 100644 index 00000000..12df3113 --- /dev/null +++ b/dcmjpeg/libijg8/jaricom.c @@ -0,0 +1,15 @@ +/* + * jaricom.c + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file holds place for arithmetic entropy codec tables. + */ + +#define JPEG_INTERNALS +#include "jinclude8.h" +#include "jpeglib8.h" + +IJG_INT32 jaritab[1]; /* dummy table */ diff --git a/dcmjpeg/libijg8/jcapimin.c b/dcmjpeg/libijg8/jcapimin.c new file mode 100644 index 00000000..96c9353f --- /dev/null +++ b/dcmjpeg/libijg8/jcapimin.c @@ -0,0 +1,280 @@ +/* + * jcapimin.c + * + * Copyright (C) 1994-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains application interface code for the compression half + * of the JPEG library. These are the "minimum" API routines that may be + * needed in either the normal full-compression case or the transcoding-only + * case. + * + * Most of the routines intended to be called directly by an application + * are in this file or in jcapistd.c. But also see jcparam.c for + * parameter-setup helper routines, jcomapi.c for routines shared by + * compression and decompression, and jctrans.c for the transcoding case. + */ + +#define JPEG_INTERNALS +#include "jinclude8.h" +#include "jpeglib8.h" + + +/* + * Initialization of a JPEG compression object. + * The error manager must already be set up (in case memory manager fails). + */ + +GLOBAL(void) +jpeg_CreateCompress (j_compress_ptr cinfo, int version, size_t structsize) +{ + int i; + + /* Guard against version mismatches between library and caller. */ + cinfo->mem = NULL; /* so jpeg_destroy knows mem mgr not called */ + if (version != JPEG_LIB_VERSION) + ERREXIT2(cinfo, JERR_BAD_LIB_VERSION, JPEG_LIB_VERSION, version); + if (structsize != SIZEOF(struct jpeg_compress_struct)) + ERREXIT2(cinfo, JERR_BAD_STRUCT_SIZE, + (int) SIZEOF(struct jpeg_compress_struct), (int) structsize); + + /* For debugging purposes, we zero the whole master structure. + * But the application has already set the err pointer, and may have set + * client_data, so we have to save and restore those fields. + * Note: if application hasn't set client_data, tools like Purify may + * complain here. + */ + { + struct jpeg_error_mgr * err = cinfo->err; + void * client_data = cinfo->client_data; /* ignore Purify complaint here */ + MEMZERO(cinfo, SIZEOF(struct jpeg_compress_struct)); + cinfo->err = err; + cinfo->client_data = client_data; + } + cinfo->is_decompressor = FALSE; + + /* Initialize a memory manager instance for this object */ + jinit_memory_mgr((j_common_ptr) cinfo); + + /* Zero out pointers to permanent structures. */ + cinfo->progress = NULL; + cinfo->dest = NULL; + + cinfo->comp_info = NULL; + + for (i = 0; i < NUM_QUANT_TBLS; i++) + cinfo->quant_tbl_ptrs[i] = NULL; + + for (i = 0; i < NUM_HUFF_TBLS; i++) { + cinfo->dc_huff_tbl_ptrs[i] = NULL; + cinfo->ac_huff_tbl_ptrs[i] = NULL; + } + + cinfo->script_space = NULL; + + cinfo->input_gamma = 1.0; /* in case application forgets */ + + /* OK, I'm ready */ + cinfo->global_state = CSTATE_START; +} + + +/* + * Destruction of a JPEG compression object + */ + +GLOBAL(void) +jpeg_destroy_compress (j_compress_ptr cinfo) +{ + jpeg_destroy((j_common_ptr) cinfo); /* use common routine */ +} + + +/* + * Abort processing of a JPEG compression operation, + * but don't destroy the object itself. + */ + +GLOBAL(void) +jpeg_abort_compress (j_compress_ptr cinfo) +{ + jpeg_abort((j_common_ptr) cinfo); /* use common routine */ +} + + +/* + * Forcibly suppress or un-suppress all quantization and Huffman tables. + * Marks all currently defined tables as already written (if suppress) + * or not written (if !suppress). This will control whether they get emitted + * by a subsequent jpeg_start_compress call. + * + * This routine is exported for use by applications that want to produce + * abbreviated JPEG datastreams. It logically belongs in jcparam.c, but + * since it is called by jpeg_start_compress, we put it here --- otherwise + * jcparam.o would be linked whether the application used it or not. + */ + +GLOBAL(void) +jpeg_suppress_tables (j_compress_ptr cinfo, boolean suppress) +{ + int i; + JQUANT_TBL * qtbl; + JHUFF_TBL * htbl; + + for (i = 0; i < NUM_QUANT_TBLS; i++) { + if ((qtbl = cinfo->quant_tbl_ptrs[i]) != NULL) + qtbl->sent_table = suppress; + } + + for (i = 0; i < NUM_HUFF_TBLS; i++) { + if ((htbl = cinfo->dc_huff_tbl_ptrs[i]) != NULL) + htbl->sent_table = suppress; + if ((htbl = cinfo->ac_huff_tbl_ptrs[i]) != NULL) + htbl->sent_table = suppress; + } +} + + +/* + * Finish JPEG compression. + * + * If a multipass operating mode was selected, this may do a great deal of + * work including most of the actual output. + */ + +GLOBAL(void) +jpeg_finish_compress (j_compress_ptr cinfo) +{ + JDIMENSION iMCU_row; + + if (cinfo->global_state == CSTATE_SCANNING || + cinfo->global_state == CSTATE_RAW_OK) { + /* Terminate first pass */ + if (cinfo->next_scanline < cinfo->image_height) + ERREXIT(cinfo, JERR_TOO_LITTLE_DATA); + (*cinfo->master->finish_pass) (cinfo); + } else if (cinfo->global_state != CSTATE_WRCOEFS) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + /* Perform any remaining passes */ + while (! cinfo->master->is_last_pass) { + (*cinfo->master->prepare_for_pass) (cinfo); + for (iMCU_row = 0; iMCU_row < cinfo->total_iMCU_rows; iMCU_row++) { + if (cinfo->progress != NULL) { + cinfo->progress->pass_counter = (long) iMCU_row; + cinfo->progress->pass_limit = (long) cinfo->total_iMCU_rows; + (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); + } + /* We bypass the main controller and invoke coef controller directly; + * all work is being done from the coefficient buffer. + */ + if (! (*cinfo->codec->compress_data) (cinfo, (JSAMPIMAGE) NULL)) + ERREXIT(cinfo, JERR_CANT_SUSPEND); + } + (*cinfo->master->finish_pass) (cinfo); + } + /* Write EOI, do final cleanup */ + (*cinfo->marker->write_file_trailer) (cinfo); + (*cinfo->dest->term_destination) (cinfo); + /* We can use jpeg_abort to release memory and reset global_state */ + jpeg_abort((j_common_ptr) cinfo); +} + + +/* + * Write a special marker. + * This is only recommended for writing COM or APPn markers. + * Must be called after jpeg_start_compress() and before + * first call to jpeg_write_scanlines() or jpeg_write_raw_data(). + */ + +GLOBAL(void) +jpeg_write_marker (j_compress_ptr cinfo, int marker, + const JOCTET *dataptr, unsigned int datalen) +{ + JMETHOD(void, write_marker_byte, (j_compress_ptr info, int val)); + + if (cinfo->next_scanline != 0 || + (cinfo->global_state != CSTATE_SCANNING && + cinfo->global_state != CSTATE_RAW_OK && + cinfo->global_state != CSTATE_WRCOEFS)) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + + (*cinfo->marker->write_marker_header) (cinfo, marker, datalen); + write_marker_byte = cinfo->marker->write_marker_byte; /* copy for speed */ + while (datalen--) { + (*write_marker_byte) (cinfo, *dataptr); + dataptr++; + } +} + +/* Same, but piecemeal. */ + +GLOBAL(void) +jpeg_write_m_header (j_compress_ptr cinfo, int marker, unsigned int datalen) +{ + if (cinfo->next_scanline != 0 || + (cinfo->global_state != CSTATE_SCANNING && + cinfo->global_state != CSTATE_RAW_OK && + cinfo->global_state != CSTATE_WRCOEFS)) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + + (*cinfo->marker->write_marker_header) (cinfo, marker, datalen); +} + +GLOBAL(void) +jpeg_write_m_byte (j_compress_ptr cinfo, int val) +{ + (*cinfo->marker->write_marker_byte) (cinfo, val); +} + + +/* + * Alternate compression function: just write an abbreviated table file. + * Before calling this, all parameters and a data destination must be set up. + * + * To produce a pair of files containing abbreviated tables and abbreviated + * image data, one would proceed as follows: + * + * initialize JPEG object + * set JPEG parameters + * set destination to table file + * jpeg_write_tables(cinfo); + * set destination to image file + * jpeg_start_compress(cinfo, FALSE); + * write data... + * jpeg_finish_compress(cinfo); + * + * jpeg_write_tables has the side effect of marking all tables written + * (same as jpeg_suppress_tables(..., TRUE)). Thus a subsequent start_compress + * will not re-emit the tables unless it is passed write_all_tables=TRUE. + */ + +GLOBAL(void) +jpeg_write_tables (j_compress_ptr cinfo) +{ + if (cinfo->global_state != CSTATE_START) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + + /* (Re)initialize error mgr and destination modules */ + (*cinfo->err->reset_error_mgr) ((j_common_ptr) cinfo); + (*cinfo->dest->init_destination) (cinfo); + /* Initialize the marker writer ... bit of a crock to do it here. */ + jinit_marker_writer(cinfo); + /* Write them tables! */ + (*cinfo->marker->write_tables_only) (cinfo); + /* And clean up. */ + (*cinfo->dest->term_destination) (cinfo); + /* + * In library releases up through v6a, we called jpeg_abort() here to free + * any working memory allocated by the destination manager and marker + * writer. Some applications had a problem with that: they allocated space + * of their own from the library memory manager, and didn't want it to go + * away during write_tables. So now we do nothing. This will cause a + * memory leak if an app calls write_tables repeatedly without doing a full + * compression cycle or otherwise resetting the JPEG object. However, that + * seems less bad than unexpectedly freeing memory in the normal case. + * An app that prefers the old behavior can call jpeg_abort for itself after + * each call to jpeg_write_tables(). + */ +} diff --git a/dcmjpeg/libijg8/jcapistd.c b/dcmjpeg/libijg8/jcapistd.c new file mode 100644 index 00000000..4ab80015 --- /dev/null +++ b/dcmjpeg/libijg8/jcapistd.c @@ -0,0 +1,161 @@ +/* + * jcapistd.c + * + * Copyright (C) 1994-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains application interface code for the compression half + * of the JPEG library. These are the "standard" API routines that are + * used in the normal full-compression case. They are not used by a + * transcoding-only application. Note that if an application links in + * jpeg_start_compress, it will end up linking in the entire compressor. + * We thus must separate this file from jcapimin.c to avoid linking the + * whole compression library into a transcoder. + */ + +#define JPEG_INTERNALS +#include "jinclude8.h" +#include "jpeglib8.h" + + +/* + * Compression initialization. + * Before calling this, all parameters and a data destination must be set up. + * + * We require a write_all_tables parameter as a failsafe check when writing + * multiple datastreams from the same compression object. Since prior runs + * will have left all the tables marked sent_table=TRUE, a subsequent run + * would emit an abbreviated stream (no tables) by default. This may be what + * is wanted, but for safety's sake it should not be the default behavior: + * programmers should have to make a deliberate choice to emit abbreviated + * images. Therefore the documentation and examples should encourage people + * to pass write_all_tables=TRUE; then it will take active thought to do the + * wrong thing. + */ + +GLOBAL(void) +jpeg_start_compress (j_compress_ptr cinfo, boolean write_all_tables) +{ + if (cinfo->global_state != CSTATE_START) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + + if (write_all_tables) + jpeg_suppress_tables(cinfo, FALSE); /* mark all tables to be written */ + + /* (Re)initialize error mgr and destination modules */ + (*cinfo->err->reset_error_mgr) ((j_common_ptr) cinfo); + (*cinfo->dest->init_destination) (cinfo); + /* Perform master selection of active modules */ + jinit_compress_master(cinfo); + /* Set up for the first pass */ + (*cinfo->master->prepare_for_pass) (cinfo); + /* Ready for application to drive first pass through jpeg_write_scanlines + * or jpeg_write_raw_data. + */ + cinfo->next_scanline = 0; + cinfo->global_state = (cinfo->raw_data_in ? CSTATE_RAW_OK : CSTATE_SCANNING); +} + + +/* + * Write some scanlines of data to the JPEG compressor. + * + * The return value will be the number of lines actually written. + * This should be less than the supplied num_lines only in case that + * the data destination module has requested suspension of the compressor, + * or if more than image_height scanlines are passed in. + * + * Note: we warn about excess calls to jpeg_write_scanlines() since + * this likely signals an application programmer error. However, + * excess scanlines passed in the last valid call are *silently* ignored, + * so that the application need not adjust num_lines for end-of-image + * when using a multiple-scanline buffer. + */ + +GLOBAL(JDIMENSION) +jpeg_write_scanlines (j_compress_ptr cinfo, JSAMPARRAY scanlines, + JDIMENSION num_lines) +{ + JDIMENSION row_ctr, rows_left; + + if (cinfo->global_state != CSTATE_SCANNING) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + if (cinfo->next_scanline >= cinfo->image_height) + WARNMS(cinfo, JWRN_TOO_MUCH_DATA); + + /* Call progress monitor hook if present */ + if (cinfo->progress != NULL) { + cinfo->progress->pass_counter = (long) cinfo->next_scanline; + cinfo->progress->pass_limit = (long) cinfo->image_height; + (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); + } + + /* Give master control module another chance if this is first call to + * jpeg_write_scanlines. This lets output of the frame/scan headers be + * delayed so that application can write COM, etc, markers between + * jpeg_start_compress and jpeg_write_scanlines. + */ + if (cinfo->master->call_pass_startup) + (*cinfo->master->pass_startup) (cinfo); + + /* Ignore any extra scanlines at bottom of image. */ + rows_left = cinfo->image_height - cinfo->next_scanline; + if (num_lines > rows_left) + num_lines = rows_left; + + row_ctr = 0; + (*cinfo->main->process_data) (cinfo, scanlines, &row_ctr, num_lines); + cinfo->next_scanline += row_ctr; + return row_ctr; +} + + +/* + * Alternate entry point to write raw data. + * Processes exactly one iMCU row per call, unless suspended. + */ + +GLOBAL(JDIMENSION) +jpeg_write_raw_data (j_compress_ptr cinfo, JSAMPIMAGE data, + JDIMENSION num_lines) +{ + JDIMENSION lines_per_iMCU_row; + + if (cinfo->global_state != CSTATE_RAW_OK) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + if (cinfo->next_scanline >= cinfo->image_height) { + WARNMS(cinfo, JWRN_TOO_MUCH_DATA); + return 0; + } + + /* Call progress monitor hook if present */ + if (cinfo->progress != NULL) { + cinfo->progress->pass_counter = (long) cinfo->next_scanline; + cinfo->progress->pass_limit = (long) cinfo->image_height; + (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); + } + + /* Give master control module another chance if this is first call to + * jpeg_write_raw_data. This lets output of the frame/scan headers be + * delayed so that application can write COM, etc, markers between + * jpeg_start_compress and jpeg_write_raw_data. + */ + if (cinfo->master->call_pass_startup) + (*cinfo->master->pass_startup) (cinfo); + + /* Verify that at least one iMCU row has been passed. */ + lines_per_iMCU_row = (JDIMENSION)(cinfo->max_v_samp_factor * cinfo->data_unit); + if (num_lines < lines_per_iMCU_row) + ERREXIT(cinfo, JERR_BUFFER_SIZE); + + /* Directly compress the row. */ + if (! (*cinfo->codec->compress_data) (cinfo, data)) { + /* If compressor did not consume the whole row, suspend processing. */ + return 0; + } + + /* OK, we processed one iMCU row. */ + cinfo->next_scanline += lines_per_iMCU_row; + return lines_per_iMCU_row; +} diff --git a/dcmjpeg/libijg8/jcarith.c b/dcmjpeg/libijg8/jcarith.c new file mode 100644 index 00000000..13dcc3f3 --- /dev/null +++ b/dcmjpeg/libijg8/jcarith.c @@ -0,0 +1,26 @@ +/* + * jcarith.c + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file holds place for arithmetic entropy encoding routines. + */ + +#define JPEG_INTERNALS +#include "jinclude8.h" +#include "jpeglib8.h" + + +/* + * Module initialization routine for arithmetic entropy encoding. + */ +GLOBAL(void) +jinit_arith_encoder (j_compress_ptr cinfo); + +GLOBAL(void) +jinit_arith_encoder (j_compress_ptr cinfo) +{ + ERREXIT(cinfo, JERR_ARITH_NOTIMPL); +} diff --git a/dcmjpeg/libijg8/jccoefct.c b/dcmjpeg/libijg8/jccoefct.c new file mode 100644 index 00000000..88b13a27 --- /dev/null +++ b/dcmjpeg/libijg8/jccoefct.c @@ -0,0 +1,454 @@ +/* + * jccoefct.c + * + * Copyright (C) 1994-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains the coefficient buffer controller for compression. + * This controller is the top level of the JPEG compressor proper. + * The coefficient buffer lies between forward-DCT and entropy encoding steps. + */ + +#define JPEG_INTERNALS +#include "jinclude8.h" +#include "jpeglib8.h" +#include "jlossy8.h" /* Private declarations for lossy codec */ + + +/* We use a full-image coefficient buffer when doing Huffman optimization, + * and also for writing multiple-scan JPEG files. In all cases, the DCT + * step is run during the first pass, and subsequent passes need only read + * the buffered coefficients. + */ +#ifdef ENTROPY_OPT_SUPPORTED +#define FULL_COEF_BUFFER_SUPPORTED +#else +#ifdef C_MULTISCAN_FILES_SUPPORTED +#define FULL_COEF_BUFFER_SUPPORTED +#endif +#endif + + +/* Private buffer controller object */ + +typedef struct { + JDIMENSION iMCU_row_num; /* iMCU row # within image */ + JDIMENSION mcu_ctr; /* counts MCUs processed in current row */ + int MCU_vert_offset; /* counts MCU rows within iMCU row */ + int MCU_rows_per_iMCU_row; /* number of such rows needed */ + + /* For single-pass compression, it's sufficient to buffer just one MCU + * (although this may prove a bit slow in practice). We allocate a + * workspace of C_MAX_DATA_UNITS_IN_MCU coefficient blocks, and reuse it for + * each MCU constructed and sent. (On 80x86, the workspace is FAR even + * though it's not really very big; this is to keep the module interfaces + * unchanged when a large coefficient buffer is necessary.) + * In multi-pass modes, this array points to the current MCU's blocks + * within the virtual arrays. + */ + JBLOCKROW MCU_buffer[C_MAX_DATA_UNITS_IN_MCU]; + + /* In multi-pass modes, we need a virtual block array for each component. */ + jvirt_barray_ptr whole_image[MAX_COMPONENTS]; +} c_coef_controller; + +typedef c_coef_controller * c_coef_ptr; + + +/* Forward declarations */ +METHODDEF(boolean) compress_data + JPP((j_compress_ptr cinfo, JSAMPIMAGE input_buf)); +#ifdef FULL_COEF_BUFFER_SUPPORTED +METHODDEF(boolean) compress_first_pass + JPP((j_compress_ptr cinfo, JSAMPIMAGE input_buf)); +METHODDEF(boolean) compress_output + JPP((j_compress_ptr cinfo, JSAMPIMAGE input_buf)); +#endif + + +LOCAL(void) +start_iMCU_row (j_compress_ptr cinfo) +/* Reset within-iMCU-row counters for a new row */ +{ + j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; + c_coef_ptr coef = (c_coef_ptr) lossyc->coef_private; + + /* In an interleaved scan, an MCU row is the same as an iMCU row. + * In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows. + * But at the bottom of the image, process only what's left. + */ + if (cinfo->comps_in_scan > 1) { + coef->MCU_rows_per_iMCU_row = 1; + } else { + if (coef->iMCU_row_num < (cinfo->total_iMCU_rows-1)) + coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->v_samp_factor; + else + coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->last_row_height; + } + + coef->mcu_ctr = 0; + coef->MCU_vert_offset = 0; +} + + +/* + * Initialize for a processing pass. + */ + +METHODDEF(void) +start_pass_coef (j_compress_ptr cinfo, J_BUF_MODE pass_mode) +{ + j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; + c_coef_ptr coef = (c_coef_ptr) lossyc->coef_private; + + coef->iMCU_row_num = 0; + start_iMCU_row(cinfo); + + switch (pass_mode) { + case JBUF_PASS_THRU: + if (coef->whole_image[0] != NULL) + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + lossyc->pub.compress_data = compress_data; + break; +#ifdef FULL_COEF_BUFFER_SUPPORTED + case JBUF_SAVE_AND_PASS: + if (coef->whole_image[0] == NULL) + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + lossyc->pub.compress_data = compress_first_pass; + break; + case JBUF_CRANK_DEST: + if (coef->whole_image[0] == NULL) + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + lossyc->pub.compress_data = compress_output; + break; +#endif + default: + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + break; + } +} + + +/* + * Process some data in the single-pass case. + * We process the equivalent of one fully interleaved MCU row ("iMCU" row) + * per call, ie, v_samp_factor block rows for each component in the image. + * Returns TRUE if the iMCU row is completed, FALSE if suspended. + * + * NB: input_buf contains a plane for each component in image, + * which we index according to the component's SOF position. + */ + +METHODDEF(boolean) +compress_data (j_compress_ptr cinfo, JSAMPIMAGE input_buf) +{ + j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; + c_coef_ptr coef = (c_coef_ptr) lossyc->coef_private; + JDIMENSION MCU_col_num; /* index of current MCU within row */ + JDIMENSION last_MCU_col = cinfo->MCUs_per_row - 1; + JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; + int blkn, bi, ci, yindex, yoffset, blockcnt; + JDIMENSION ypos, xpos; + jpeg_component_info *compptr; + + /* Loop to write as much as one whole iMCU row */ + for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row; + yoffset++) { + for (MCU_col_num = coef->mcu_ctr; MCU_col_num <= last_MCU_col; + MCU_col_num++) { + /* Determine where data comes from in input_buf and do the DCT thing. + * Each call on forward_DCT processes a horizontal row of DCT blocks + * as wide as an MCU; we rely on having allocated the MCU_buffer[] blocks + * sequentially. Dummy blocks at the right or bottom edge are filled in + * specially. The data in them does not matter for image reconstruction, + * so we fill them with values that will encode to the smallest amount of + * data, viz: all zeroes in the AC entries, DC entries equal to previous + * block's DC value. (Thanks to Thomas Kinsman for this idea.) + */ + blkn = 0; + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + blockcnt = (MCU_col_num < last_MCU_col) ? compptr->MCU_width + : compptr->last_col_width; + xpos = MCU_col_num * (JDIMENSION)compptr->MCU_sample_width; + ypos = (JDIMENSION)(yoffset * DCTSIZE); /* ypos == (yoffset+yindex) * DCTSIZE */ + for (yindex = 0; yindex < compptr->MCU_height; yindex++) { + if (coef->iMCU_row_num < last_iMCU_row || + yoffset+yindex < compptr->last_row_height) { + (*lossyc->fdct_forward_DCT) (cinfo, compptr, + input_buf[compptr->component_index], + coef->MCU_buffer[blkn], + ypos, xpos, (JDIMENSION) blockcnt); + if (blockcnt < compptr->MCU_width) { + /* Create some dummy blocks at the right edge of the image. */ + jzero_far((void FAR *) coef->MCU_buffer[blkn + blockcnt], + (size_t)(compptr->MCU_width - blockcnt) * SIZEOF(JBLOCK)); + for (bi = blockcnt; bi < compptr->MCU_width; bi++) { + coef->MCU_buffer[blkn+bi][0][0] = coef->MCU_buffer[blkn+bi-1][0][0]; + } + } + } else { + /* Create a row of dummy blocks at the bottom of the image. */ + jzero_far((void FAR *) coef->MCU_buffer[blkn], + (size_t)compptr->MCU_width * SIZEOF(JBLOCK)); + for (bi = 0; bi < compptr->MCU_width; bi++) { + coef->MCU_buffer[blkn+bi][0][0] = coef->MCU_buffer[blkn-1][0][0]; + } + } + blkn += compptr->MCU_width; + ypos += DCTSIZE; + } + } + /* Try to write the MCU. In event of a suspension failure, we will + * re-DCT the MCU on restart (a bit inefficient, could be fixed...) + */ + if (! (*lossyc->entropy_encode_mcu) (cinfo, coef->MCU_buffer)) { + /* Suspension forced; update state counters and exit */ + coef->MCU_vert_offset = yoffset; + coef->mcu_ctr = MCU_col_num; + return FALSE; + } + } + /* Completed an MCU row, but perhaps not an iMCU row */ + coef->mcu_ctr = 0; + } + /* Completed the iMCU row, advance counters for next one */ + coef->iMCU_row_num++; + start_iMCU_row(cinfo); + return TRUE; +} + + +#ifdef FULL_COEF_BUFFER_SUPPORTED + +/* + * Process some data in the first pass of a multi-pass case. + * We process the equivalent of one fully interleaved MCU row ("iMCU" row) + * per call, ie, v_samp_factor block rows for each component in the image. + * This amount of data is read from the source buffer, DCT'd and quantized, + * and saved into the virtual arrays. We also generate suitable dummy blocks + * as needed at the right and lower edges. (The dummy blocks are constructed + * in the virtual arrays, which have been padded appropriately.) This makes + * it possible for subsequent passes not to worry about real vs. dummy blocks. + * + * We must also emit the data to the entropy encoder. This is conveniently + * done by calling compress_output() after we've loaded the current strip + * of the virtual arrays. + * + * NB: input_buf contains a plane for each component in image. All + * components are DCT'd and loaded into the virtual arrays in this pass. + * However, it may be that only a subset of the components are emitted to + * the entropy encoder during this first pass; be careful about looking + * at the scan-dependent variables (MCU dimensions, etc). + */ + +METHODDEF(boolean) +compress_first_pass (j_compress_ptr cinfo, JSAMPIMAGE input_buf) +{ + j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; + c_coef_ptr coef = (c_coef_ptr) lossyc->coef_private; + JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; + JDIMENSION blocks_across, MCUs_across, MCUindex; + int bi, ci, h_samp_factor, block_row, block_rows, ndummy; + JCOEF lastDC; + jpeg_component_info *compptr; + JBLOCKARRAY buffer; + JBLOCKROW thisblockrow, lastblockrow; + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + /* Align the virtual buffer for this component. */ + buffer = (*cinfo->mem->access_virt_barray) + ((j_common_ptr) cinfo, coef->whole_image[ci], + coef->iMCU_row_num * (JDIMENSION)compptr->v_samp_factor, + (JDIMENSION)compptr->v_samp_factor, TRUE); + /* Count non-dummy DCT block rows in this iMCU row. */ + if (coef->iMCU_row_num < last_iMCU_row) + block_rows = compptr->v_samp_factor; + else { + /* NB: can't use last_row_height here, since may not be set! */ + block_rows = (int)compptr->height_in_data_units % compptr->v_samp_factor; + if (block_rows == 0) block_rows = compptr->v_samp_factor; + } + blocks_across = (JDIMENSION)compptr->width_in_data_units; + h_samp_factor = compptr->h_samp_factor; + /* Count number of dummy blocks to be added at the right margin. */ + ndummy = (int)blocks_across % h_samp_factor; + if (ndummy > 0) + ndummy = h_samp_factor - ndummy; + /* Perform DCT for all non-dummy blocks in this iMCU row. Each call + * on forward_DCT processes a complete horizontal row of DCT blocks. + */ + for (block_row = 0; block_row < block_rows; block_row++) { + thisblockrow = buffer[block_row]; + (*lossyc->fdct_forward_DCT) (cinfo, compptr, + input_buf[ci], thisblockrow, + (JDIMENSION) (block_row * DCTSIZE), + (JDIMENSION) 0, blocks_across); + if (ndummy > 0) { + /* Create dummy blocks at the right edge of the image. */ + thisblockrow += blocks_across; /* => first dummy block */ + jzero_far((void FAR *) thisblockrow, (size_t)ndummy * SIZEOF(JBLOCK)); + lastDC = thisblockrow[-1][0]; + for (bi = 0; bi < ndummy; bi++) { + thisblockrow[bi][0] = lastDC; + } + } + } + /* If at end of image, create dummy block rows as needed. + * The tricky part here is that within each MCU, we want the DC values + * of the dummy blocks to match the last real block's DC value. + * This squeezes a few more bytes out of the resulting file... + */ + if (coef->iMCU_row_num == last_iMCU_row) { + blocks_across += (JDIMENSION)ndummy; /* include lower right corner */ + MCUs_across = blocks_across / (JDIMENSION)h_samp_factor; + for (block_row = block_rows; block_row < compptr->v_samp_factor; + block_row++) { + thisblockrow = buffer[block_row]; + lastblockrow = buffer[block_row-1]; + jzero_far((void FAR *) thisblockrow, + (size_t) (blocks_across * SIZEOF(JBLOCK))); + for (MCUindex = 0; MCUindex < MCUs_across; MCUindex++) { + lastDC = lastblockrow[h_samp_factor-1][0]; + for (bi = 0; bi < h_samp_factor; bi++) { + thisblockrow[bi][0] = lastDC; + } + thisblockrow += h_samp_factor; /* advance to next MCU in row */ + lastblockrow += h_samp_factor; + } + } + } + } + /* NB: compress_output will increment iMCU_row_num if successful. + * A suspension return will result in redoing all the work above next time. + */ + + /* Emit data to the entropy encoder, sharing code with subsequent passes */ + return compress_output(cinfo, input_buf); +} + + +/* + * Process some data in subsequent passes of a multi-pass case. + * We process the equivalent of one fully interleaved MCU row ("iMCU" row) + * per call, ie, v_samp_factor block rows for each component in the scan. + * The data is obtained from the virtual arrays and fed to the entropy coder. + * Returns TRUE if the iMCU row is completed, FALSE if suspended. + * + * NB: input_buf is ignored; it is likely to be a NULL pointer. + */ + +METHODDEF(boolean) +compress_output (j_compress_ptr cinfo, JSAMPIMAGE input_buf) +{ + j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; + c_coef_ptr coef = (c_coef_ptr) lossyc->coef_private; + JDIMENSION MCU_col_num; /* index of current MCU within row */ + int blkn, ci, xindex, yindex, yoffset; + JDIMENSION start_col; + JBLOCKARRAY buffer[MAX_COMPS_IN_SCAN]; + JBLOCKROW buffer_ptr; + jpeg_component_info *compptr; + + /* Align the virtual buffers for the components used in this scan. + * NB: during first pass, this is safe only because the buffers will + * already be aligned properly, so jmemmgr.c won't need to do any I/O. + */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + buffer[ci] = (*cinfo->mem->access_virt_barray) + ((j_common_ptr) cinfo, coef->whole_image[compptr->component_index], + coef->iMCU_row_num * (JDIMENSION)compptr->v_samp_factor, + (JDIMENSION)compptr->v_samp_factor, FALSE); + } + + /* Loop to process one whole iMCU row */ + for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row; + yoffset++) { + for (MCU_col_num = coef->mcu_ctr; MCU_col_num < cinfo->MCUs_per_row; + MCU_col_num++) { + /* Construct list of pointers to DCT blocks belonging to this MCU */ + blkn = 0; /* index of current DCT block within MCU */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + start_col = MCU_col_num * (JDIMENSION)compptr->MCU_width; + for (yindex = 0; yindex < compptr->MCU_height; yindex++) { + buffer_ptr = buffer[ci][yindex+yoffset] + start_col; + for (xindex = 0; xindex < compptr->MCU_width; xindex++) { + coef->MCU_buffer[blkn++] = buffer_ptr++; + } + } + } + /* Try to write the MCU. */ + if (! (*lossyc->entropy_encode_mcu) (cinfo, coef->MCU_buffer)) { + /* Suspension forced; update state counters and exit */ + coef->MCU_vert_offset = yoffset; + coef->mcu_ctr = MCU_col_num; + return FALSE; + } + } + /* Completed an MCU row, but perhaps not an iMCU row */ + coef->mcu_ctr = 0; + } + /* Completed the iMCU row, advance counters for next one */ + coef->iMCU_row_num++; + start_iMCU_row(cinfo); + return TRUE; +} + +#endif /* FULL_COEF_BUFFER_SUPPORTED */ + + +/* + * Initialize coefficient buffer controller. + */ + +GLOBAL(void) +jinit_c_coef_controller (j_compress_ptr cinfo, boolean need_full_buffer) +{ + j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; + c_coef_ptr coef; + + coef = (c_coef_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(c_coef_controller)); + lossyc->coef_private = (struct jpeg_c_coef_controller *) coef; + lossyc->coef_start_pass = start_pass_coef; + + /* Create the coefficient buffer. */ + if (need_full_buffer) { +#ifdef FULL_COEF_BUFFER_SUPPORTED + /* Allocate a full-image virtual array for each component, */ + /* padded to a multiple of samp_factor DCT blocks in each direction. */ + int ci; + jpeg_component_info *compptr; + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + coef->whole_image[ci] = (*cinfo->mem->request_virt_barray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE, + (JDIMENSION) jround_up((long) compptr->width_in_data_units, + (long) compptr->h_samp_factor), + (JDIMENSION) jround_up((long) compptr->height_in_data_units, + (long) compptr->v_samp_factor), + (JDIMENSION) compptr->v_samp_factor); + } +#else + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); +#endif + } else { + /* We only need a single-MCU buffer. */ + JBLOCKROW buffer; + int i; + + buffer = (JBLOCKROW) + (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE, + C_MAX_DATA_UNITS_IN_MCU * SIZEOF(JBLOCK)); + for (i = 0; i < C_MAX_DATA_UNITS_IN_MCU; i++) { + coef->MCU_buffer[i] = buffer + i; + } + coef->whole_image[0] = NULL; /* flag for no virtual arrays */ + } +} diff --git a/dcmjpeg/libijg8/jccolor.c b/dcmjpeg/libijg8/jccolor.c new file mode 100644 index 00000000..a72fb445 --- /dev/null +++ b/dcmjpeg/libijg8/jccolor.c @@ -0,0 +1,459 @@ +/* + * jccolor.c + * + * Copyright (C) 1991-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains input colorspace conversion routines. + */ + +#define JPEG_INTERNALS +#include "jinclude8.h" +#include "jpeglib8.h" + + +/* Private subobject */ + +typedef struct { + struct jpeg_color_converter pub; /* public fields */ + + /* Private state for RGB->YCC conversion */ + IJG_INT32 * rgb_ycc_tab; /* => table for RGB to YCbCr conversion */ +} my_color_converter; + +typedef my_color_converter * my_cconvert_ptr; + + +/**************** RGB -> YCbCr conversion: most common case **************/ + +/* + * YCbCr is defined per CCIR 601-1, except that Cb and Cr are + * normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5. + * The conversion equations to be implemented are therefore + * Y = 0.29900 * R + 0.58700 * G + 0.11400 * B + * Cb = -0.16874 * R - 0.33126 * G + 0.50000 * B + CENTERJSAMPLE + * Cr = 0.50000 * R - 0.41869 * G - 0.08131 * B + CENTERJSAMPLE + * (These numbers are derived from TIFF 6.0 section 21, dated 3-June-92.) + * Note: older versions of the IJG code used a zero offset of MAXJSAMPLE/2, + * rather than CENTERJSAMPLE, for Cb and Cr. This gave equal positive and + * negative swings for Cb/Cr, but meant that grayscale values (Cb=Cr=0) + * were not represented exactly. Now we sacrifice exact representation of + * maximum red and maximum blue in order to get exact grayscales. + * + * To avoid floating-point arithmetic, we represent the fractional constants + * as integers scaled up by 2^16 (about 4 digits precision); we have to divide + * the products by 2^16, with appropriate rounding, to get the correct answer. + * + * For even more speed, we avoid doing any multiplications in the inner loop + * by precalculating the constants times R,G,B for all possible values. + * For 8-bit JSAMPLEs this is very reasonable (only 256 entries per table); + * for 12-bit samples it is still acceptable. It's not very reasonable for + * 16-bit samples, but if you want lossless storage you shouldn't be changing + * colorspace anyway. + * The CENTERJSAMPLE offsets and the rounding fudge-factor of 0.5 are included + * in the tables to save adding them separately in the inner loop. + */ + +#define SCALEBITS 16 /* speediest right-shift on some machines */ +#define CBCR_OFFSET ((IJG_INT32) CENTERJSAMPLE << SCALEBITS) +#define ONE_HALF ((IJG_INT32) 1 << (SCALEBITS-1)) +#define FIX(x) ((IJG_INT32) ((x) * (1L< Y section */ +#define G_Y_OFF (1*(MAXJSAMPLE+1)) /* offset to G => Y section */ +#define B_Y_OFF (2*(MAXJSAMPLE+1)) /* etc. */ +#define R_CB_OFF (3*(MAXJSAMPLE+1)) +#define G_CB_OFF (4*(MAXJSAMPLE+1)) +#define B_CB_OFF (5*(MAXJSAMPLE+1)) +#define R_CR_OFF B_CB_OFF /* B=>Cb, R=>Cr are the same */ +#define G_CR_OFF (6*(MAXJSAMPLE+1)) +#define B_CR_OFF (7*(MAXJSAMPLE+1)) +#define TABLE_SIZE (8*(MAXJSAMPLE+1)) + + +/* + * Initialize for RGB->YCC colorspace conversion. + */ + +METHODDEF(void) +rgb_ycc_start (j_compress_ptr cinfo) +{ + my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; + IJG_INT32 * rgb_ycc_tab; + IJG_INT32 i; + + /* Allocate and fill in the conversion tables. */ + cconvert->rgb_ycc_tab = rgb_ycc_tab = (IJG_INT32 *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (TABLE_SIZE * SIZEOF(IJG_INT32))); + + for (i = 0; i <= MAXJSAMPLE; i++) { + rgb_ycc_tab[i+R_Y_OFF] = FIX(0.29900) * i; + rgb_ycc_tab[i+G_Y_OFF] = FIX(0.58700) * i; + rgb_ycc_tab[i+B_Y_OFF] = FIX(0.11400) * i + ONE_HALF; + rgb_ycc_tab[i+R_CB_OFF] = (-FIX(0.16874)) * i; + rgb_ycc_tab[i+G_CB_OFF] = (-FIX(0.33126)) * i; + /* We use a rounding fudge-factor of 0.5-epsilon for Cb and Cr. + * This ensures that the maximum output will round to MAXJSAMPLE + * not MAXJSAMPLE+1, and thus that we don't have to range-limit. + */ + rgb_ycc_tab[i+B_CB_OFF] = FIX(0.50000) * i + CBCR_OFFSET + ONE_HALF-1; +/* B=>Cb and R=>Cr tables are the same + rgb_ycc_tab[i+R_CR_OFF] = FIX(0.50000) * i + CBCR_OFFSET + ONE_HALF-1; +*/ + rgb_ycc_tab[i+G_CR_OFF] = (-FIX(0.41869)) * i; + rgb_ycc_tab[i+B_CR_OFF] = (-FIX(0.08131)) * i; + } +} + + +/* + * Convert some rows of samples to the JPEG colorspace. + * + * Note that we change from the application's interleaved-pixel format + * to our internal noninterleaved, one-plane-per-component format. + * The input buffer is therefore three times as wide as the output buffer. + * + * A starting row offset is provided only for the output buffer. The caller + * can easily adjust the passed input_buf value to accommodate any row + * offset required on that side. + */ + +METHODDEF(void) +rgb_ycc_convert (j_compress_ptr cinfo, + JSAMPARRAY input_buf, JSAMPIMAGE output_buf, + JDIMENSION output_row, int num_rows) +{ + my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; + register int r, g, b; + register IJG_INT32 * ctab = cconvert->rgb_ycc_tab; + register JSAMPROW inptr; + register JSAMPROW outptr0, outptr1, outptr2; + register JDIMENSION col; + JDIMENSION num_cols = cinfo->image_width; + + while (--num_rows >= 0) { + inptr = *input_buf++; + outptr0 = output_buf[0][output_row]; + outptr1 = output_buf[1][output_row]; + outptr2 = output_buf[2][output_row]; + output_row++; + for (col = 0; col < num_cols; col++) { + r = GETJSAMPLE(inptr[RGB_RED]); + g = GETJSAMPLE(inptr[RGB_GREEN]); + b = GETJSAMPLE(inptr[RGB_BLUE]); + inptr += RGB_PIXELSIZE; + /* If the inputs are 0..MAXJSAMPLE, the outputs of these equations + * must be too; we do not need an explicit range-limiting operation. + * Hence the value being shifted is never negative, and we don't + * need the general RIGHT_SHIFT macro. + */ + /* Y */ + outptr0[col] = (JSAMPLE) + ((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF]) + >> SCALEBITS); + /* Cb */ + outptr1[col] = (JSAMPLE) + ((ctab[r+R_CB_OFF] + ctab[g+G_CB_OFF] + ctab[b+B_CB_OFF]) + >> SCALEBITS); + /* Cr */ + outptr2[col] = (JSAMPLE) + ((ctab[r+R_CR_OFF] + ctab[g+G_CR_OFF] + ctab[b+B_CR_OFF]) + >> SCALEBITS); + } + } +} + + +/**************** Cases other than RGB -> YCbCr **************/ + + +/* + * Convert some rows of samples to the JPEG colorspace. + * This version handles RGB->grayscale conversion, which is the same + * as the RGB->Y portion of RGB->YCbCr. + * We assume rgb_ycc_start has been called (we only use the Y tables). + */ + +METHODDEF(void) +rgb_gray_convert (j_compress_ptr cinfo, + JSAMPARRAY input_buf, JSAMPIMAGE output_buf, + JDIMENSION output_row, int num_rows) +{ + my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; + register int r, g, b; + register IJG_INT32 * ctab = cconvert->rgb_ycc_tab; + register JSAMPROW inptr; + register JSAMPROW outptr; + register JDIMENSION col; + JDIMENSION num_cols = cinfo->image_width; + + while (--num_rows >= 0) { + inptr = *input_buf++; + outptr = output_buf[0][output_row]; + output_row++; + for (col = 0; col < num_cols; col++) { + r = GETJSAMPLE(inptr[RGB_RED]); + g = GETJSAMPLE(inptr[RGB_GREEN]); + b = GETJSAMPLE(inptr[RGB_BLUE]); + inptr += RGB_PIXELSIZE; + /* Y */ + outptr[col] = (JSAMPLE) + ((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF]) + >> SCALEBITS); + } + } +} + + +/* + * Convert some rows of samples to the JPEG colorspace. + * This version handles Adobe-style CMYK->YCCK conversion, + * where we convert R=1-C, G=1-M, and B=1-Y to YCbCr using the same + * conversion as above, while passing K (black) unchanged. + * We assume rgb_ycc_start has been called. + */ + +METHODDEF(void) +cmyk_ycck_convert (j_compress_ptr cinfo, + JSAMPARRAY input_buf, JSAMPIMAGE output_buf, + JDIMENSION output_row, int num_rows) +{ + my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; + register int r, g, b; + register IJG_INT32 * ctab = cconvert->rgb_ycc_tab; + register JSAMPROW inptr; + register JSAMPROW outptr0, outptr1, outptr2, outptr3; + register JDIMENSION col; + JDIMENSION num_cols = cinfo->image_width; + + while (--num_rows >= 0) { + inptr = *input_buf++; + outptr0 = output_buf[0][output_row]; + outptr1 = output_buf[1][output_row]; + outptr2 = output_buf[2][output_row]; + outptr3 = output_buf[3][output_row]; + output_row++; + for (col = 0; col < num_cols; col++) { + r = MAXJSAMPLE - GETJSAMPLE(inptr[0]); + g = MAXJSAMPLE - GETJSAMPLE(inptr[1]); + b = MAXJSAMPLE - GETJSAMPLE(inptr[2]); + /* K passes through as-is */ + outptr3[col] = inptr[3]; /* don't need GETJSAMPLE here */ + inptr += 4; + /* If the inputs are 0..MAXJSAMPLE, the outputs of these equations + * must be too; we do not need an explicit range-limiting operation. + * Hence the value being shifted is never negative, and we don't + * need the general RIGHT_SHIFT macro. + */ + /* Y */ + outptr0[col] = (JSAMPLE) + ((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF]) + >> SCALEBITS); + /* Cb */ + outptr1[col] = (JSAMPLE) + ((ctab[r+R_CB_OFF] + ctab[g+G_CB_OFF] + ctab[b+B_CB_OFF]) + >> SCALEBITS); + /* Cr */ + outptr2[col] = (JSAMPLE) + ((ctab[r+R_CR_OFF] + ctab[g+G_CR_OFF] + ctab[b+B_CR_OFF]) + >> SCALEBITS); + } + } +} + + +/* + * Convert some rows of samples to the JPEG colorspace. + * This version handles grayscale output with no conversion. + * The source can be either plain grayscale or YCbCr (since Y == gray). + */ + +METHODDEF(void) +grayscale_convert (j_compress_ptr cinfo, + JSAMPARRAY input_buf, JSAMPIMAGE output_buf, + JDIMENSION output_row, int num_rows) +{ + register JSAMPROW inptr; + register JSAMPROW outptr; + register JDIMENSION col; + JDIMENSION num_cols = cinfo->image_width; + int instride = cinfo->input_components; + + while (--num_rows >= 0) { + inptr = *input_buf++; + outptr = output_buf[0][output_row]; + output_row++; + for (col = 0; col < num_cols; col++) { + outptr[col] = inptr[0]; /* don't need GETJSAMPLE() here */ + inptr += instride; + } + } +} + + +/* + * Convert some rows of samples to the JPEG colorspace. + * This version handles multi-component colorspaces without conversion. + * We assume input_components == num_components. + */ + +METHODDEF(void) +null_convert (j_compress_ptr cinfo, + JSAMPARRAY input_buf, JSAMPIMAGE output_buf, + JDIMENSION output_row, int num_rows) +{ + register JSAMPROW inptr; + register JSAMPROW outptr; + register JDIMENSION col; + register int ci; + int nc = cinfo->num_components; + JDIMENSION num_cols = cinfo->image_width; + + while (--num_rows >= 0) { + /* It seems fastest to make a separate pass for each component. */ + for (ci = 0; ci < nc; ci++) { + inptr = *input_buf; + outptr = output_buf[ci][output_row]; + for (col = 0; col < num_cols; col++) { + outptr[col] = inptr[ci]; /* don't need GETJSAMPLE() here */ + inptr += nc; + } + } + input_buf++; + output_row++; + } +} + + +/* + * Empty method for start_pass. + */ + +METHODDEF(void) +null_method (j_compress_ptr cinfo) +{ + /* no work needed */ +} + + +/* + * Module initialization routine for input colorspace conversion. + */ + +GLOBAL(void) +jinit_color_converter (j_compress_ptr cinfo) +{ + my_cconvert_ptr cconvert; + + cconvert = (my_cconvert_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_color_converter)); + cinfo->cconvert = (struct jpeg_color_converter *) cconvert; + /* set start_pass to null method until we find out differently */ + cconvert->pub.start_pass = null_method; + + /* Make sure input_components agrees with in_color_space */ + switch (cinfo->in_color_space) { + case JCS_GRAYSCALE: + if (cinfo->input_components != 1) + ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); + break; + + case JCS_RGB: +#if RGB_PIXELSIZE != 3 + if (cinfo->input_components != RGB_PIXELSIZE) + ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); + break; +#endif /* else share code with YCbCr */ + + case JCS_YCbCr: + if (cinfo->input_components != 3) + ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); + break; + + case JCS_CMYK: + case JCS_YCCK: + if (cinfo->input_components != 4) + ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); + break; + + default: /* JCS_UNKNOWN can be anything */ + if (cinfo->input_components < 1) + ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); + break; + } + + /* Check num_components, set conversion method based on requested space */ + switch (cinfo->jpeg_color_space) { + case JCS_GRAYSCALE: + if (cinfo->num_components != 1) + ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); + if (cinfo->in_color_space == JCS_GRAYSCALE) + cconvert->pub.color_convert = grayscale_convert; + else if (cinfo->in_color_space == JCS_RGB) { + cconvert->pub.start_pass = rgb_ycc_start; + cconvert->pub.color_convert = rgb_gray_convert; + } else if (cinfo->in_color_space == JCS_YCbCr) + cconvert->pub.color_convert = grayscale_convert; + else + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); + break; + + case JCS_RGB: + if (cinfo->num_components != 3) + ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); + if (cinfo->in_color_space == JCS_RGB && RGB_PIXELSIZE == 3) + cconvert->pub.color_convert = null_convert; + else + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); + break; + + case JCS_YCbCr: + if (cinfo->num_components != 3) + ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); + if (cinfo->in_color_space == JCS_RGB) { + cconvert->pub.start_pass = rgb_ycc_start; + cconvert->pub.color_convert = rgb_ycc_convert; + } else if (cinfo->in_color_space == JCS_YCbCr) + cconvert->pub.color_convert = null_convert; + else + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); + break; + + case JCS_CMYK: + if (cinfo->num_components != 4) + ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); + if (cinfo->in_color_space == JCS_CMYK) + cconvert->pub.color_convert = null_convert; + else + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); + break; + + case JCS_YCCK: + if (cinfo->num_components != 4) + ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); + if (cinfo->in_color_space == JCS_CMYK) { + cconvert->pub.start_pass = rgb_ycc_start; + cconvert->pub.color_convert = cmyk_ycck_convert; + } else if (cinfo->in_color_space == JCS_YCCK) + cconvert->pub.color_convert = null_convert; + else + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); + break; + + default: /* allow null conversion of JCS_UNKNOWN */ + if (cinfo->jpeg_color_space != cinfo->in_color_space || + cinfo->num_components != cinfo->input_components) + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); + cconvert->pub.color_convert = null_convert; + break; + } +} diff --git a/dcmjpeg/libijg8/jcdctmgr.c b/dcmjpeg/libijg8/jcdctmgr.c new file mode 100644 index 00000000..0e65a30e --- /dev/null +++ b/dcmjpeg/libijg8/jcdctmgr.c @@ -0,0 +1,390 @@ +/* + * jcdctmgr.c + * + * Copyright (C) 1994-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains the forward-DCT management logic. + * This code selects a particular DCT implementation to be used, + * and it performs related housekeeping chores including coefficient + * quantization. + */ + +#define JPEG_INTERNALS +#include "jinclude8.h" +#include "jpeglib8.h" +#include "jlossy8.h" /* Private declarations for lossy codec */ +#include "jdct8.h" /* Private declarations for DCT subsystem */ + + +/* Private subobject for this module */ + +typedef struct { + /* Pointer to the DCT routine actually in use */ + forward_DCT_method_ptr do_dct; + + /* The actual post-DCT divisors --- not identical to the quant table + * entries, because of scaling (especially for an unnormalized DCT). + * Each table is given in normal array order. + */ + DCTELEM * divisors[NUM_QUANT_TBLS]; + +#ifdef DCT_FLOAT_SUPPORTED + /* Same as above for the floating-point case. */ + float_DCT_method_ptr do_float_dct; + FAST_FLOAT * float_divisors[NUM_QUANT_TBLS]; +#endif +} fdct_controller; + +typedef fdct_controller * fdct_ptr; + + +/* + * Initialize for a processing pass. + * Verify that all referenced Q-tables are present, and set up + * the divisor table for each one. + * In the current implementation, DCT of all components is done during + * the first pass, even if only some components will be output in the + * first scan. Hence all components should be examined here. + */ + +METHODDEF(void) +start_pass_fdctmgr (j_compress_ptr cinfo) +{ + j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; + fdct_ptr fdct = (fdct_ptr) lossyc->fdct_private; + int ci, qtblno, i; + jpeg_component_info *compptr; + JQUANT_TBL * qtbl; + DCTELEM * dtbl; + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + qtblno = compptr->quant_tbl_no; + /* Make sure specified quantization table is present */ + if (qtblno < 0 || qtblno >= NUM_QUANT_TBLS || + cinfo->quant_tbl_ptrs[qtblno] == NULL) + ERREXIT1(cinfo, JERR_NO_QUANT_TABLE, qtblno); + qtbl = cinfo->quant_tbl_ptrs[qtblno]; + /* Compute divisors for this quant table */ + /* We may do this more than once for same table, but it's not a big deal */ + switch (cinfo->dct_method) { +#ifdef DCT_ISLOW_SUPPORTED + case JDCT_ISLOW: + /* For LL&M IDCT method, divisors are equal to raw quantization + * coefficients multiplied by 8 (to counteract scaling). + */ + if (fdct->divisors[qtblno] == NULL) { + fdct->divisors[qtblno] = (DCTELEM *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + DCTSIZE2 * SIZEOF(DCTELEM)); + } + dtbl = fdct->divisors[qtblno]; + for (i = 0; i < DCTSIZE2; i++) { + dtbl[i] = ((DCTELEM) qtbl->quantval[i]) << 3; + } + break; +#endif +#ifdef DCT_IFAST_SUPPORTED + case JDCT_IFAST: + { + /* For AA&N IDCT method, divisors are equal to quantization + * coefficients scaled by scalefactor[row]*scalefactor[col], where + * scalefactor[0] = 1 + * scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7 + * We apply a further scale factor of 8. + */ +#define CONST_BITS 14 + static const INT16 aanscales[DCTSIZE2] = { + /* precomputed values scaled up by 14 bits */ + 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520, + 22725, 31521, 29692, 26722, 22725, 17855, 12299, 6270, + 21407, 29692, 27969, 25172, 21407, 16819, 11585, 5906, + 19266, 26722, 25172, 22654, 19266, 15137, 10426, 5315, + 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520, + 12873, 17855, 16819, 15137, 12873, 10114, 6967, 3552, + 8867, 12299, 11585, 10426, 8867, 6967, 4799, 2446, + 4520, 6270, 5906, 5315, 4520, 3552, 2446, 1247 + }; + SHIFT_TEMPS + + if (fdct->divisors[qtblno] == NULL) { + fdct->divisors[qtblno] = (DCTELEM *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + DCTSIZE2 * SIZEOF(DCTELEM)); + } + dtbl = fdct->divisors[qtblno]; + for (i = 0; i < DCTSIZE2; i++) { + dtbl[i] = (DCTELEM) + DESCALE(MULTIPLY16V16((IJG_INT32) qtbl->quantval[i], + (IJG_INT32) aanscales[i]), + CONST_BITS-3); + } + } + break; +#endif +#ifdef DCT_FLOAT_SUPPORTED + case JDCT_FLOAT: + { + /* For float AA&N IDCT method, divisors are equal to quantization + * coefficients scaled by scalefactor[row]*scalefactor[col], where + * scalefactor[0] = 1 + * scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7 + * We apply a further scale factor of 8. + * What's actually stored is 1/divisor so that the inner loop can + * use a multiplication rather than a division. + */ + FAST_FLOAT * fdtbl; + int row, col; + static const double aanscalefactor[DCTSIZE] = { + 1.0, 1.387039845, 1.306562965, 1.175875602, + 1.0, 0.785694958, 0.541196100, 0.275899379 + }; + + if (fdct->float_divisors[qtblno] == NULL) { + fdct->float_divisors[qtblno] = (FAST_FLOAT *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + DCTSIZE2 * SIZEOF(FAST_FLOAT)); + } + fdtbl = fdct->float_divisors[qtblno]; + i = 0; + for (row = 0; row < DCTSIZE; row++) { + for (col = 0; col < DCTSIZE; col++) { + fdtbl[i] = (FAST_FLOAT) + (1.0 / (((double) qtbl->quantval[i] * + aanscalefactor[row] * aanscalefactor[col] * 8.0))); + i++; + } + } + } + break; +#endif + default: + ERREXIT(cinfo, JERR_NOT_COMPILED); + break; + } + } +} + + +/* + * Perform forward DCT on one or more blocks of a component. + * + * The input samples are taken from the sample_data[] array starting at + * position start_row/start_col, and moving to the right for any additional + * blocks. The quantized coefficients are returned in coef_blocks[]. + */ + +METHODDEF(void) +forward_DCT (j_compress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY sample_data, JBLOCKROW coef_blocks, + JDIMENSION start_row, JDIMENSION start_col, + JDIMENSION num_blocks) +/* This version is used for integer DCT implementations. */ +{ + /* This routine is heavily used, so it's worth coding it tightly. */ + j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; + fdct_ptr fdct = (fdct_ptr) lossyc->fdct_private; + forward_DCT_method_ptr do_dct = fdct->do_dct; + DCTELEM * divisors = fdct->divisors[compptr->quant_tbl_no]; + DCTELEM workspace[DCTSIZE2]; /* work area for FDCT subroutine */ + JDIMENSION bi; + + sample_data += start_row; /* fold in the vertical offset once */ + + for (bi = 0; bi < num_blocks; bi++, start_col += DCTSIZE) { + /* Load data into workspace, applying unsigned->signed conversion */ + { register DCTELEM *workspaceptr; + register JSAMPROW elemptr; + register int elemr; + + workspaceptr = workspace; + for (elemr = 0; elemr < DCTSIZE; elemr++) { + elemptr = sample_data[elemr] + start_col; +#if DCTSIZE == 8 /* unroll the inner loop */ + *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; + *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; + *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; + *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; + *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; + *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; + *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; + *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; +#else + { register int elemc; + for (elemc = DCTSIZE; elemc > 0; elemc--) { + *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; + } + } +#endif + } + } + + /* Perform the DCT */ + (*do_dct) (workspace); + + /* Quantize/descale the coefficients, and store into coef_blocks[] */ + { register DCTELEM temp, qval; + register int i; + register JCOEFPTR output_ptr = coef_blocks[bi]; + + for (i = 0; i < DCTSIZE2; i++) { + qval = divisors[i]; + temp = workspace[i]; + /* Divide the coefficient value by qval, ensuring proper rounding. + * Since C does not specify the direction of rounding for negative + * quotients, we have to force the dividend positive for portability. + * + * In most files, at least half of the output values will be zero + * (at default quantization settings, more like three-quarters...) + * so we should ensure that this case is fast. On many machines, + * a comparison is enough cheaper than a divide to make a special test + * a win. Since both inputs will be nonnegative, we need only test + * for a < b to discover whether a/b is 0. + * If your machine's division is fast enough, define FAST_DIVIDE. + */ +#ifdef FAST_DIVIDE +#define DIVIDE_BY(a,b) a /= b +#else +#define DIVIDE_BY(a,b) if (a >= b) a /= b; else a = 0 +#endif + if (temp < 0) { + temp = -temp; + temp += qval>>1; /* for rounding */ + DIVIDE_BY(temp, qval); + temp = -temp; + } else { + temp += qval>>1; /* for rounding */ + DIVIDE_BY(temp, qval); + } + output_ptr[i] = (JCOEF) temp; + } + } + } +} + + +#ifdef DCT_FLOAT_SUPPORTED + +METHODDEF(void) +forward_DCT_float (j_compress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY sample_data, JBLOCKROW coef_blocks, + JDIMENSION start_row, JDIMENSION start_col, + JDIMENSION num_blocks) +/* This version is used for floating-point DCT implementations. */ +{ + /* This routine is heavily used, so it's worth coding it tightly. */ + j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; + fdct_ptr fdct = (fdct_ptr) lossyc->fdct_private; + float_DCT_method_ptr do_dct = fdct->do_float_dct; + FAST_FLOAT * divisors = fdct->float_divisors[compptr->quant_tbl_no]; + FAST_FLOAT workspace[DCTSIZE2]; /* work area for FDCT subroutine */ + JDIMENSION bi; + + sample_data += start_row; /* fold in the vertical offset once */ + + for (bi = 0; bi < num_blocks; bi++, start_col += DCTSIZE) { + /* Load data into workspace, applying unsigned->signed conversion */ + { register FAST_FLOAT *workspaceptr; + register JSAMPROW elemptr; + register int elemr; + + workspaceptr = workspace; + for (elemr = 0; elemr < DCTSIZE; elemr++) { + elemptr = sample_data[elemr] + start_col; +#if DCTSIZE == 8 /* unroll the inner loop */ + *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); + *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); + *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); + *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); + *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); + *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); + *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); + *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); +#else + { register int elemc; + for (elemc = DCTSIZE; elemc > 0; elemc--) { + *workspaceptr++ = (FAST_FLOAT) + (GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); + } + } +#endif + } + } + + /* Perform the DCT */ + (*do_dct) (workspace); + + /* Quantize/descale the coefficients, and store into coef_blocks[] */ + { register FAST_FLOAT temp; + register int i; + register JCOEFPTR output_ptr = coef_blocks[bi]; + + for (i = 0; i < DCTSIZE2; i++) { + /* Apply the quantization and scaling factor */ + temp = workspace[i] * divisors[i]; + /* Round to nearest integer. + * Since C does not specify the direction of rounding for negative + * quotients, we have to force the dividend positive for portability. + * The maximum coefficient size is +-16K (for 12-bit data), so this + * code should work for either 16-bit or 32-bit ints. + */ + output_ptr[i] = (JCOEF) ((int) (temp + (FAST_FLOAT) 16384.5) - 16384); + } + } + } +} + +#endif /* DCT_FLOAT_SUPPORTED */ + + +/* + * Initialize FDCT manager. + */ + +GLOBAL(void) +jinit_forward_dct (j_compress_ptr cinfo) +{ + j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; + fdct_ptr fdct; + int i; + + fdct = (fdct_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(fdct_controller)); + lossyc->fdct_private = (struct jpeg_forward_dct *) fdct; + lossyc->fdct_start_pass = start_pass_fdctmgr; + + switch (cinfo->dct_method) { +#ifdef DCT_ISLOW_SUPPORTED + case JDCT_ISLOW: + lossyc->fdct_forward_DCT = forward_DCT; + fdct->do_dct = jpeg_fdct_islow; + break; +#endif +#ifdef DCT_IFAST_SUPPORTED + case JDCT_IFAST: + lossyc->fdct_forward_DCT = forward_DCT; + fdct->do_dct = jpeg_fdct_ifast; + break; +#endif +#ifdef DCT_FLOAT_SUPPORTED + case JDCT_FLOAT: + lossyc->fdct_forward_DCT = forward_DCT_float; + fdct->do_float_dct = jpeg_fdct_float; + break; +#endif + default: + ERREXIT(cinfo, JERR_NOT_COMPILED); + break; + } + + /* Mark divisor tables unallocated */ + for (i = 0; i < NUM_QUANT_TBLS; i++) { + fdct->divisors[i] = NULL; +#ifdef DCT_FLOAT_SUPPORTED + fdct->float_divisors[i] = NULL; +#endif + } +} diff --git a/dcmjpeg/libijg8/jcdiffct.c b/dcmjpeg/libijg8/jcdiffct.c new file mode 100644 index 00000000..07bd8427 --- /dev/null +++ b/dcmjpeg/libijg8/jcdiffct.c @@ -0,0 +1,406 @@ +/* + * jcdiffct.c + * + * Copyright (C) 1994-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains the difference buffer controller for compression. + * This controller is the top level of the lossless JPEG compressor proper. + * The difference buffer lies between prediction/differencing and entropy + * encoding. + */ + +#define JPEG_INTERNALS +#include "jinclude8.h" +#include "jpeglib8.h" +#include "jlossls8.h" /* Private declarations for lossless codec */ + + +#ifdef C_LOSSLESS_SUPPORTED + +/* We use a full-image sample buffer when doing Huffman optimization, + * and also for writing multiple-scan JPEG files. In all cases, the + * full-image buffer is filled during the first pass, and the scaling, + * prediction and differencing steps are run during subsequent passes. + */ +#ifdef ENTROPY_OPT_SUPPORTED +#define FULL_SAMP_BUFFER_SUPPORTED +#else +#ifdef C_MULTISCAN_FILES_SUPPORTED +#define FULL_SAMP_BUFFER_SUPPORTED +#endif +#endif + + +/* Private buffer controller object */ + +typedef struct { + JDIMENSION iMCU_row_num; /* iMCU row # within image */ + JDIMENSION mcu_ctr; /* counts MCUs processed in current row */ + int MCU_vert_offset; /* counts MCU rows within iMCU row */ + int MCU_rows_per_iMCU_row; /* number of such rows needed */ + + JSAMPROW cur_row[MAX_COMPONENTS]; /* row of point transformed samples */ + JSAMPROW prev_row[MAX_COMPONENTS]; /* previous row of Pt'd samples */ + JDIFFARRAY diff_buf[MAX_COMPONENTS]; /* iMCU row of differences */ + + /* In multi-pass modes, we need a virtual sample array for each component. */ + jvirt_sarray_ptr whole_image[MAX_COMPONENTS]; +} c_diff_controller; + +typedef c_diff_controller * c_diff_ptr; + + +/* Forward declarations */ +METHODDEF(boolean) compress_data + JPP((j_compress_ptr cinfo, JSAMPIMAGE input_buf)); +#ifdef FULL_SAMP_BUFFER_SUPPORTED +METHODDEF(boolean) compress_first_pass + JPP((j_compress_ptr cinfo, JSAMPIMAGE input_buf)); +METHODDEF(boolean) compress_output + JPP((j_compress_ptr cinfo, JSAMPIMAGE input_buf)); +#endif + + +LOCAL(void) +start_iMCU_row (j_compress_ptr cinfo) +/* Reset within-iMCU-row counters for a new row */ +{ + j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec; + c_diff_ptr diff = (c_diff_ptr) losslsc->diff_private; + + /* In an interleaved scan, an MCU row is the same as an iMCU row. + * In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows. + * But at the bottom of the image, process only what's left. + */ + if (cinfo->comps_in_scan > 1) { + diff->MCU_rows_per_iMCU_row = 1; + } else { + if (diff->iMCU_row_num < (cinfo->total_iMCU_rows-1)) + diff->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->v_samp_factor; + else + diff->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->last_row_height; + } + + diff->mcu_ctr = 0; + diff->MCU_vert_offset = 0; +} + + +/* + * Initialize for a processing pass. + */ + +METHODDEF(void) +start_pass_diff (j_compress_ptr cinfo, J_BUF_MODE pass_mode) +{ + j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec; + c_diff_ptr diff = (c_diff_ptr) losslsc->diff_private; + + diff->iMCU_row_num = 0; + start_iMCU_row(cinfo); + + switch (pass_mode) { + case JBUF_PASS_THRU: + if (diff->whole_image[0] != NULL) + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + losslsc->pub.compress_data = compress_data; + break; +#ifdef FULL_SAMP_BUFFER_SUPPORTED + case JBUF_SAVE_AND_PASS: + if (diff->whole_image[0] == NULL) + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + losslsc->pub.compress_data = compress_first_pass; + break; + case JBUF_CRANK_DEST: + if (diff->whole_image[0] == NULL) + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + losslsc->pub.compress_data = compress_output; + break; +#endif + default: + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + break; + } +} + + +#define SWAP_ROWS(rowa,rowb) {JSAMPROW temp; temp=rowa; rowa=rowb; rowb=temp;} + +/* + * Process some data in the single-pass case. + * We process the equivalent of one fully interleaved MCU row ("iMCU" row) + * per call, ie, v_samp_factor rows for each component in the image. + * Returns TRUE if the iMCU row is completed, FALSE if suspended. + * + * NB: input_buf contains a plane for each component in image, + * which we index according to the component's SOF position. + */ + +METHODDEF(boolean) +compress_data (j_compress_ptr cinfo, JSAMPIMAGE input_buf) +{ + j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec; + c_diff_ptr diff = (c_diff_ptr) losslsc->diff_private; + JDIMENSION MCU_col_num; /* index of current MCU within row */ + JDIMENSION MCU_count; /* number of MCUs encoded */ + /* JDIMENSION last_MCU_col = cinfo->MCUs_per_row - 1; */ + JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; + int comp, ci, yoffset, samp_row, samp_rows, samps_across; + jpeg_component_info *compptr; + + /* Loop to write as much as one whole iMCU row */ + for (yoffset = diff->MCU_vert_offset; yoffset < diff->MCU_rows_per_iMCU_row; + yoffset++) { + + MCU_col_num = diff->mcu_ctr; + + /* Scale and predict each scanline of the MCU-row separately. + * + * Note: We only do this if we are at the start of a MCU-row, ie, + * we don't want to reprocess a row suspended by the output. + */ + if (MCU_col_num == 0) { + for (comp = 0; comp < cinfo->comps_in_scan; comp++) { + compptr = cinfo->cur_comp_info[comp]; + ci = compptr->component_index; + if (diff->iMCU_row_num < last_iMCU_row) + samp_rows = compptr->v_samp_factor; + else { + /* NB: can't use last_row_height here, since may not be set! */ + samp_rows = (int)compptr->height_in_data_units % compptr->v_samp_factor; + if (samp_rows == 0) samp_rows = compptr->v_samp_factor; + else { + /* Fill dummy difference rows at the bottom edge with zeros, which + * will encode to the smallest amount of data. + */ + for (samp_row = samp_rows; samp_row < compptr->v_samp_factor; + samp_row++) + MEMZERO(diff->diff_buf[ci][samp_row], + (size_t)jround_up((long) compptr->width_in_data_units, + (long) compptr->h_samp_factor) * SIZEOF(JDIFF)); + } + } + samps_across = (int)compptr->width_in_data_units; + + for (samp_row = 0; samp_row < samp_rows; samp_row++) { + (*losslsc->scaler_scale) (cinfo, + input_buf[ci][samp_row], + diff->cur_row[ci], (JDIMENSION)samps_across); + (*losslsc->predict_difference[ci]) (cinfo, ci, + diff->cur_row[ci], + diff->prev_row[ci], + diff->diff_buf[ci][samp_row], + (JDIMENSION)samps_across); + SWAP_ROWS(diff->cur_row[ci], diff->prev_row[ci]); + } + } + } + + /* Try to write the MCU-row (or remaining portion of suspended MCU-row). */ + MCU_count = + (*losslsc->entropy_encode_mcus) (cinfo, + diff->diff_buf, (JDIMENSION)yoffset, MCU_col_num, + (JDIMENSION)cinfo->MCUs_per_row - MCU_col_num); + if (MCU_count != cinfo->MCUs_per_row - MCU_col_num) { + /* Suspension forced; update state counters and exit */ + diff->MCU_vert_offset = yoffset; + diff->mcu_ctr += MCU_col_num; + return FALSE; + } + + /* Completed an MCU row, but perhaps not an iMCU row */ + diff->mcu_ctr = 0; + } + + /* Completed the iMCU row, advance counters for next one */ + diff->iMCU_row_num++; + start_iMCU_row(cinfo); + return TRUE; +} + + +#ifdef FULL_SAMP_BUFFER_SUPPORTED + +/* + * Process some data in the first pass of a multi-pass case. + * We process the equivalent of one fully interleaved MCU row ("iMCU" row) + * per call, ie, v_samp_factor rows for each component in the image. + * This amount of data is read from the source buffer and saved into the + * virtual arrays. + * + * We must also emit the data to the compressor. This is conveniently + * done by calling compress_output() after we've loaded the current strip + * of the virtual arrays. + * + * NB: input_buf contains a plane for each component in image. All components + * are loaded into the virtual arrays in this pass. However, it may be that + * only a subset of the components are emitted to the compressor during + * this first pass; be careful about looking at the scan-dependent variables + * (MCU dimensions, etc). + */ + +METHODDEF(boolean) +compress_first_pass (j_compress_ptr cinfo, JSAMPIMAGE input_buf) +{ + j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec; + c_diff_ptr diff = (c_diff_ptr) losslsc->diff_private; + JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; + JDIMENSION samps_across; + int ci, samp_row, samp_rows; + JSAMPARRAY buffer[MAX_COMPONENTS]; + jpeg_component_info *compptr; + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + /* Align the virtual buffers for this component. */ + buffer[ci] = (*cinfo->mem->access_virt_sarray) + ((j_common_ptr) cinfo, diff->whole_image[ci], + diff->iMCU_row_num * (JDIMENSION)compptr->v_samp_factor, + (JDIMENSION) compptr->v_samp_factor, TRUE); + + /* Count non-dummy sample rows in this iMCU row. */ + if (diff->iMCU_row_num < last_iMCU_row) + samp_rows = compptr->v_samp_factor; + else { + /* NB: can't use last_row_height here, since may not be set! */ + samp_rows = (int)compptr->height_in_data_units % compptr->v_samp_factor; + if (samp_rows == 0) samp_rows = compptr->v_samp_factor; + } + samps_across = compptr->width_in_data_units; + + /* Perform point transform scaling and prediction/differencing for all + * non-dummy rows in this iMCU row. Each call on these functions + * process a complete row of samples. + */ + for (samp_row = 0; samp_row < samp_rows; samp_row++) { + MEMCOPY(buffer[ci][samp_row], input_buf[ci][samp_row], + samps_across * SIZEOF(JSAMPLE)); + } + } + + /* NB: compress_output will increment iMCU_row_num if successful. + * A suspension return will result in redoing all the work above next time. + */ + + /* Emit data to the compressor, sharing code with subsequent passes */ + return compress_output(cinfo, input_buf); +} + + +/* + * Process some data in subsequent passes of a multi-pass case. + * We process the equivalent of one fully interleaved MCU row ("iMCU" row) + * per call, ie, v_samp_factor rows for each component in the scan. + * The data is obtained from the virtual arrays and fed to the compressor. + * Returns TRUE if the iMCU row is completed, FALSE if suspended. + * + * NB: input_buf is ignored; it is likely to be a NULL pointer. + */ + +METHODDEF(boolean) +compress_output (j_compress_ptr cinfo, JSAMPIMAGE input_buf) +{ + j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec; + c_diff_ptr diff = (c_diff_ptr) losslsc->diff_private; + /* JDIMENSION MCU_col_num; */ /* index of current MCU within row */ + /* JDIMENSION MCU_count; */ /* number of MCUs encoded */ + int comp, ci /* , yoffset */ ; + JSAMPARRAY buffer[MAX_COMPONENTS]; + jpeg_component_info *compptr; + + /* Align the virtual buffers for the components used in this scan. + * NB: during first pass, this is safe only because the buffers will + * already be aligned properly, so jmemmgr.c won't need to do any I/O. + */ + for (comp = 0; comp < cinfo->comps_in_scan; comp++) { + compptr = cinfo->cur_comp_info[comp]; + ci = compptr->component_index; + buffer[ci] = (*cinfo->mem->access_virt_sarray) + ((j_common_ptr) cinfo, diff->whole_image[ci], + diff->iMCU_row_num * (JDIMENSION)compptr->v_samp_factor, + (JDIMENSION) compptr->v_samp_factor, FALSE); + } + + return compress_data(cinfo, buffer); +} + +#endif /* FULL_SAMP_BUFFER_SUPPORTED */ + + +/* + * Initialize difference buffer controller. + */ + +GLOBAL(void) +jinit_c_diff_controller (j_compress_ptr cinfo, boolean need_full_buffer) +{ + j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec; + c_diff_ptr diff; + int ci, row; + jpeg_component_info *compptr; + + diff = (c_diff_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(c_diff_controller)); + losslsc->diff_private = (void *) diff; + losslsc->diff_start_pass = start_pass_diff; + + /* Create the prediction row buffers. */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + diff->cur_row[ci] = *(*cinfo->mem->alloc_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + (JDIMENSION) jround_up((long) compptr->width_in_data_units, + (long) compptr->h_samp_factor), + (JDIMENSION) 1); + diff->prev_row[ci] = *(*cinfo->mem->alloc_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + (JDIMENSION) jround_up((long) compptr->width_in_data_units, + (long) compptr->h_samp_factor), + (JDIMENSION) 1); + } + + /* Create the difference buffer. */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + diff->diff_buf[ci] = (*cinfo->mem->alloc_darray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + (JDIMENSION) jround_up((long) compptr->width_in_data_units, + (long) compptr->h_samp_factor), + (JDIMENSION) compptr->v_samp_factor); + /* Prefill difference rows with zeros. We do this because only actual + * data is placed in the buffers during prediction/differencing, leaving + * any dummy differences at the right edge as zeros, which will encode + * to the smallest amount of data. + */ + for (row = 0; row < compptr->v_samp_factor; row++) + MEMZERO(diff->diff_buf[ci][row], + (size_t)jround_up((long) compptr->width_in_data_units, + (long) compptr->h_samp_factor) * SIZEOF(JDIFF)); + } + + /* Create the sample buffer. */ + if (need_full_buffer) { +#ifdef FULL_SAMP_BUFFER_SUPPORTED + /* Allocate a full-image virtual array for each component, */ + /* padded to a multiple of samp_factor differences in each direction. */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + diff->whole_image[ci] = (*cinfo->mem->request_virt_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE, + (JDIMENSION) jround_up((long) compptr->width_in_data_units, + (long) compptr->h_samp_factor), + (JDIMENSION) jround_up((long) compptr->height_in_data_units, + (long) compptr->v_samp_factor), + (JDIMENSION) compptr->v_samp_factor); + } +#else + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); +#endif + } else + diff->whole_image[0] = NULL; /* flag for no virtual arrays */ +} + +#endif /* C_LOSSLESS_SUPPORTED */ diff --git a/dcmjpeg/libijg8/jchuff.c b/dcmjpeg/libijg8/jchuff.c new file mode 100644 index 00000000..d741785a --- /dev/null +++ b/dcmjpeg/libijg8/jchuff.c @@ -0,0 +1,274 @@ +/* + * jchuff.c + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains Huffman entropy decoding routines which are shared + * by the sequential, progressive and lossless decoders. + */ + +#define JPEG_INTERNALS +#include "jinclude8.h" +#include "jpeglib8.h" +#include "jchuff8.h" /* Declarations shared with jc*huff.c */ + + +/* + * Compute the derived values for a Huffman table. + * This routine also performs some validation checks on the table. + */ + +GLOBAL(void) +jpeg_make_c_derived_tbl (j_compress_ptr cinfo, boolean isDC, int tblno, + c_derived_tbl ** pdtbl) +{ + JHUFF_TBL *htbl; + c_derived_tbl *dtbl; + int p, i, l, lastp, si, maxsymbol; + char huffsize[257]; + unsigned int huffcode[257]; + unsigned int code; + + /* Note that huffsize[] and huffcode[] are filled in code-length order, + * paralleling the order of the symbols themselves in htbl->huffval[]. + */ + + /* Find the input Huffman table */ + if (tblno < 0 || tblno >= NUM_HUFF_TBLS) + ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tblno); + htbl = + isDC ? cinfo->dc_huff_tbl_ptrs[tblno] : cinfo->ac_huff_tbl_ptrs[tblno]; + if (htbl == NULL) + ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tblno); + + /* Allocate a workspace if we haven't already done so. */ + if (*pdtbl == NULL) + *pdtbl = (c_derived_tbl *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(c_derived_tbl)); + dtbl = *pdtbl; + + /* Figure C.1: make table of Huffman code length for each symbol */ + + p = 0; + for (l = 1; l <= 16; l++) { + i = (int) htbl->bits[l]; + if (i < 0 || p + i > 256) /* protect against table overrun */ + ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); + while (i--) + huffsize[p++] = (char) l; + } + huffsize[p] = 0; + lastp = p; + + /* Figure C.2: generate the codes themselves */ + /* We also validate that the counts represent a legal Huffman code tree. */ + + code = 0; + si = huffsize[0]; + p = 0; + while (huffsize[p]) { + while (((int) huffsize[p]) == si) { + huffcode[p++] = code; + code++; + } + /* code is now 1 more than the last code used for codelength si; but + * it must still fit in si bits, since no code is allowed to be all ones. + * BUG FIX: Comparison must be >, not >= + */ + if (((IJG_INT32) code) > (((IJG_INT32) 1) << si)) + ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); + code <<= 1; + si++; + } + + /* Figure C.3: generate encoding tables */ + /* These are code and size indexed by symbol value */ + + /* Set all codeless symbols to have code length 0; + * this lets us detect duplicate VAL entries here, and later + * allows emit_bits to detect any attempt to emit such symbols. + */ + MEMZERO(dtbl->ehufsi, SIZEOF(dtbl->ehufsi)); + + /* This is also a convenient place to check for out-of-range + * and duplicated VAL entries. We allow 0..255 for AC symbols + * but only 0..16 for DC. (We could constrain them further + * based on data depth and mode, but this seems enough.) + */ + maxsymbol = isDC ? 16 : 255; + + for (p = 0; p < lastp; p++) { + i = htbl->huffval[p]; + if (i < 0 || i > maxsymbol || dtbl->ehufsi[i]) + ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); + dtbl->ehufco[i] = huffcode[p]; + dtbl->ehufsi[i] = huffsize[p]; + } +} + + +/* + * Generate the best Huffman code table for the given counts, fill htbl. + * + * The JPEG standard requires that no symbol be assigned a codeword of all + * one bits (so that padding bits added at the end of a compressed segment + * can't look like a valid code). Because of the canonical ordering of + * codewords, this just means that there must be an unused slot in the + * longest codeword length category. Section K.2 of the JPEG spec suggests + * reserving such a slot by pretending that symbol 256 is a valid symbol + * with count 1. In theory that's not optimal; giving it count zero but + * including it in the symbol set anyway should give a better Huffman code. + * But the theoretically better code actually seems to come out worse in + * practice, because it produces more all-ones bytes (which incur stuffed + * zero bytes in the final file). In any case the difference is tiny. + * + * The JPEG standard requires Huffman codes to be no more than 16 bits long. + * If some symbols have a very small but nonzero probability, the Huffman tree + * must be adjusted to meet the code length restriction. We currently use + * the adjustment method suggested in JPEG section K.2. This method is *not* + * optimal; it may not choose the best possible limited-length code. But + * typically only very-low-frequency symbols will be given less-than-optimal + * lengths, so the code is almost optimal. Experimental comparisons against + * an optimal limited-length-code algorithm indicate that the difference is + * microscopic --- usually less than a hundredth of a percent of total size. + * So the extra complexity of an optimal algorithm doesn't seem worthwhile. + */ + +GLOBAL(void) +jpeg_gen_optimal_table (j_compress_ptr cinfo, JHUFF_TBL * htbl, long freq[]) +{ +#define MAX_CLEN 32 /* assumed maximum initial code length */ + UINT8 bits[MAX_CLEN+1]; /* bits[k] = # of symbols with code length k */ + int codesize[257]; /* codesize[k] = code length of symbol k */ + int others[257]; /* next symbol in current branch of tree */ + int c1, c2; + int p, i, j; + long v; + + /* This algorithm is explained in section K.2 of the JPEG standard */ + + MEMZERO(bits, SIZEOF(bits)); + MEMZERO(codesize, SIZEOF(codesize)); + for (i = 0; i < 257; i++) + others[i] = -1; /* init links to empty */ + + freq[256] = 1; /* make sure 256 has a nonzero count */ + /* Including the pseudo-symbol 256 in the Huffman procedure guarantees + * that no real symbol is given code-value of all ones, because 256 + * will be placed last in the largest codeword category. + */ + + /* Huffman's basic algorithm to assign optimal code lengths to symbols */ + + for (;;) { + /* Find the smallest nonzero frequency, set c1 = its symbol */ + /* In case of ties, take the larger symbol number */ + c1 = -1; + v = 1000000000L; + for (i = 0; i <= 256; i++) { + if (freq[i] && freq[i] <= v) { + v = freq[i]; + c1 = i; + } + } + + /* Find the next smallest nonzero frequency, set c2 = its symbol */ + /* In case of ties, take the larger symbol number */ + c2 = -1; + v = 1000000000L; + for (i = 0; i <= 256; i++) { + if (freq[i] && freq[i] <= v && i != c1) { + v = freq[i]; + c2 = i; + } + } + + /* Done if we've merged everything into one frequency */ + if (c2 < 0) + break; + + /* Else merge the two counts/trees */ + freq[c1] += freq[c2]; + freq[c2] = 0; + + /* Increment the codesize of everything in c1's tree branch */ + codesize[c1]++; + while (others[c1] >= 0) { + c1 = others[c1]; + codesize[c1]++; + } + + others[c1] = c2; /* chain c2 onto c1's tree branch */ + + /* Increment the codesize of everything in c2's tree branch */ + codesize[c2]++; + while (others[c2] >= 0) { + c2 = others[c2]; + codesize[c2]++; + } + } + + /* Now count the number of symbols of each code length */ + for (i = 0; i <= 256; i++) { + if (codesize[i]) { + /* The JPEG standard seems to think that this can't happen, */ + /* but I'm paranoid... */ + if (codesize[i] > MAX_CLEN) + ERREXIT(cinfo, JERR_HUFF_CLEN_OVERFLOW); + + bits[codesize[i]]++; + } + } + + /* JPEG doesn't allow symbols with code lengths over 16 bits, so if the pure + * Huffman procedure assigned any such lengths, we must adjust the coding. + * Here is what the JPEG spec says about how this next bit works: + * Since symbols are paired for the longest Huffman code, the symbols are + * removed from this length category two at a time. The prefix for the pair + * (which is one bit shorter) is allocated to one of the pair; then, + * skipping the BITS entry for that prefix length, a code word from the next + * shortest nonzero BITS entry is converted into a prefix for two code words + * one bit longer. + */ + + for (i = MAX_CLEN; i > 16; i--) { + while (bits[i] > 0) { + j = i - 2; /* find length of new prefix to be used */ + while (bits[j] == 0) + j--; + + bits[i] = (UINT8)(bits[i] - 2); /* remove two symbols */ + bits[i-1]++; /* one goes in this length */ + bits[j+1] = (UINT8)(bits[j+1] + 2); /* two new symbols in this length */ + bits[j]--; /* symbol of this length is now a prefix */ + } + } + + /* Remove the count for the pseudo-symbol 256 from the largest codelength */ + while (bits[i] == 0) /* find largest codelength still in use */ + i--; + bits[i]--; + + /* Return final symbol counts (only for lengths 0..16) */ + MEMCOPY(htbl->bits, bits, SIZEOF(htbl->bits)); + + /* Return a list of the symbols sorted by code length */ + /* It's not real clear to me why we don't need to consider the codelength + * changes made above, but the JPEG spec seems to think this works. + */ + p = 0; + for (i = 1; i <= MAX_CLEN; i++) { + for (j = 0; j <= 255; j++) { + if (codesize[j] == i) { + htbl->huffval[p] = (UINT8) j; + p++; + } + } + } + + /* Set sent_table FALSE so updated table will be written to JPEG file. */ + htbl->sent_table = FALSE; +} diff --git a/dcmjpeg/libijg8/jchuff8.h b/dcmjpeg/libijg8/jchuff8.h new file mode 100644 index 00000000..cb088c26 --- /dev/null +++ b/dcmjpeg/libijg8/jchuff8.h @@ -0,0 +1,54 @@ +/* + * jchuff.h + * + * Copyright (C) 1991-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains declarations for Huffman entropy encoding routines + * that are shared between the sequential encoder (jchuff.c) and the + * progressive encoder (jcphuff.c). No other modules need to see these. + */ + +/* The legal range of a DCT coefficient is + * -1024 .. +1023 for 8-bit data; + * -16384 .. +16383 for 12-bit data. + * Hence the magnitude should always fit in 10 or 14 bits respectively. + */ + +#if BITS_IN_JSAMPLE == 8 +#define MAX_COEF_BITS 10 +#else +#define MAX_COEF_BITS 14 +#endif + +/* The legal range of a spatial difference is + * -32767 .. +32768. + * Hence the magnitude should always fit in 16 bits. + */ + +#define MAX_DIFF_BITS 16 + +/* Derived data constructed for each Huffman table */ + +typedef struct { + unsigned int ehufco[256]; /* code for each symbol */ + char ehufsi[256]; /* length of code for each symbol */ + /* If no code has been allocated for a symbol S, ehufsi[S] contains 0 */ +} c_derived_tbl; + +/* Short forms of external names for systems with brain-damaged linkers. */ + +#ifdef NEED_SHORT_EXTERNAL_NAMES +#define jpeg_make_c_derived_tbl jpeg8_make_c_derived_tbl +#define jpeg_gen_optimal_table jpeg8_gen_optimal_table +#endif /* NEED_SHORT_EXTERNAL_NAMES */ + +/* Expand a Huffman table definition into the derived format */ +EXTERN(void) jpeg_make_c_derived_tbl + JPP((j_compress_ptr cinfo, boolean isDC, int tblno, + c_derived_tbl ** pdtbl)); + +/* Generate an optimal table definition given the specified counts */ +EXTERN(void) jpeg_gen_optimal_table + JPP((j_compress_ptr cinfo, JHUFF_TBL * htbl, long freq[])); diff --git a/dcmjpeg/libijg8/jcinit.c b/dcmjpeg/libijg8/jcinit.c new file mode 100644 index 00000000..4df06d65 --- /dev/null +++ b/dcmjpeg/libijg8/jcinit.c @@ -0,0 +1,57 @@ +/* + * jcinit.c + * + * Copyright (C) 1991-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains initialization logic for the JPEG compressor. + * This routine is in charge of selecting the modules to be executed and + * making an initialization call to each one. + * + * Logically, this code belongs in jcmaster.c. It's split out because + * linking this routine implies linking the entire compression library. + * For a transcoding-only application, we want to be able to use jcmaster.c + * without linking in the whole library. + */ + +#define JPEG_INTERNALS +#include "jinclude8.h" +#include "jpeglib8.h" + + +/* + * Master selection of compression modules. + * This is done once at the start of processing an image. We determine + * which modules will be used and give them appropriate initialization calls. + */ + +GLOBAL(void) +jinit_compress_master (j_compress_ptr cinfo) +{ + /* Initialize master control (includes parameter checking/processing) */ + jinit_c_master_control(cinfo, FALSE /* full compression */); + + /* Initialize compression codec */ + jinit_c_codec(cinfo); + + /* Preprocessing */ + if (! cinfo->raw_data_in) { + jinit_color_converter(cinfo); + jinit_downsampler(cinfo); + jinit_c_prep_controller(cinfo, FALSE /* never need full buffer here */); + } + + jinit_c_main_controller(cinfo, FALSE /* never need full buffer here */); + + jinit_marker_writer(cinfo); + + /* We can now tell the memory manager to allocate virtual arrays. */ + (*cinfo->mem->realize_virt_arrays) ((j_common_ptr) cinfo); + + /* Write the datastream header (SOI) immediately. + * Frame and scan headers are postponed till later. + * This lets application insert special markers after the SOI. + */ + (*cinfo->marker->write_file_header) (cinfo); +} diff --git a/dcmjpeg/libijg8/jclhuff.c b/dcmjpeg/libijg8/jclhuff.c new file mode 100644 index 00000000..d53a626e --- /dev/null +++ b/dcmjpeg/libijg8/jclhuff.c @@ -0,0 +1,601 @@ +/* + * jclhuff.c + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains Huffman entropy encoding routines for lossless JPEG. + * + * Much of the complexity here has to do with supporting output suspension. + * If the data destination module demands suspension, we want to be able to + * back up to the start of the current MCU. To do this, we copy state + * variables into local working storage, and update them back to the + * permanent JPEG objects only upon successful completion of an MCU. + */ + +#define JPEG_INTERNALS +#include "jinclude8.h" +#include "jpeglib8.h" +#include "jlossls8.h" /* Private declarations for lossless codec */ +#include "jchuff8.h" /* Declarations shared with jc*huff.c */ + + +/* Expanded entropy encoder object for Huffman encoding. + * + * The savable_state subrecord contains fields that change within an MCU, + * but must not be updated permanently until we complete the MCU. + */ + +typedef struct { + IJG_INT32 put_buffer; /* current bit-accumulation buffer */ + int put_bits; /* # of bits now in it */ +} savable_state; + +/* This macro is to work around compilers with missing or broken + * structure assignment. You'll need to fix this code if you have + * such a compiler and you change MAX_COMPS_IN_SCAN. + */ + +#ifndef NO_STRUCT_ASSIGN +#define ASSIGN_STATE(dest,src) ((dest) = (src)) +#else +#define ASSIGN_STATE(dest,src) \ + ((dest).put_buffer = (src).put_buffer, \ + (dest).put_bits = (src).put_bits) +#endif + + +typedef struct { + int ci, yoffset, MCU_width; +} lhe_input_ptr_info; + + +typedef struct { + savable_state saved; /* Bit buffer at start of MCU */ + + /* These fields are NOT loaded into local working state. */ + unsigned int restarts_to_go; /* MCUs left in this restart interval */ + int next_restart_num; /* next restart number to write (0-7) */ + + /* Pointers to derived tables (these workspaces have image lifespan) */ + c_derived_tbl * derived_tbls[NUM_HUFF_TBLS]; + + /* Pointers to derived tables to be used for each data unit within an MCU */ + c_derived_tbl * cur_tbls[C_MAX_DATA_UNITS_IN_MCU]; + +#ifdef ENTROPY_OPT_SUPPORTED /* Statistics tables for optimization */ + long * count_ptrs[NUM_HUFF_TBLS]; + + /* Pointers to stats tables to be used for each data unit within an MCU */ + long * cur_counts[C_MAX_DATA_UNITS_IN_MCU]; +#endif + + /* Pointers to the proper input difference row for each group of data units + * within an MCU. For each component, there are Vi groups of Hi data units. + */ + JDIFFROW input_ptr[C_MAX_DATA_UNITS_IN_MCU]; + + /* Number of input pointers in use for the current MCU. This is the sum + * of all Vi in the MCU. + */ + int num_input_ptrs; + + /* Information used for positioning the input pointers within the input + * difference rows. + */ + lhe_input_ptr_info input_ptr_info[C_MAX_DATA_UNITS_IN_MCU]; + + /* Index of the proper input pointer for each data unit within an MCU */ + int input_ptr_index[C_MAX_DATA_UNITS_IN_MCU]; + +} lhuff_entropy_encoder; + +typedef lhuff_entropy_encoder * lhuff_entropy_ptr; + +/* Working state while writing an MCU. + * This struct contains all the fields that are needed by subroutines. + */ + +typedef struct { + JOCTET * next_output_byte; /* => next byte to write in buffer */ + size_t free_in_buffer; /* # of byte spaces remaining in buffer */ + savable_state cur; /* Current bit buffer & DC state */ + j_compress_ptr cinfo; /* dump_buffer needs access to this */ +} working_state; + + +/* Forward declarations */ +METHODDEF(JDIMENSION) encode_mcus_huff (j_compress_ptr cinfo, + JDIFFIMAGE diff_buf, + JDIMENSION MCU_row_num, + JDIMENSION MCU_col_num, + JDIMENSION nMCU); +METHODDEF(void) finish_pass_huff JPP((j_compress_ptr cinfo)); +#ifdef ENTROPY_OPT_SUPPORTED +METHODDEF(JDIMENSION) encode_mcus_gather (j_compress_ptr cinfo, + JDIFFIMAGE diff_buf, + JDIMENSION MCU_row_num, + JDIMENSION MCU_col_num, + JDIMENSION nMCU); +METHODDEF(void) finish_pass_gather JPP((j_compress_ptr cinfo)); +#endif + + +/* + * Initialize for a Huffman-compressed scan. + * If gather_statistics is TRUE, we do not output anything during the scan, + * just count the Huffman symbols used and generate Huffman code tables. + */ + +METHODDEF(void) +start_pass_huff (j_compress_ptr cinfo, boolean gather_statistics) +{ + j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec; + lhuff_entropy_ptr entropy = (lhuff_entropy_ptr) losslsc->entropy_private; + int ci, dctbl, sampn, ptrn, yoffset, xoffset; + jpeg_component_info * compptr; + + if (gather_statistics) { +#ifdef ENTROPY_OPT_SUPPORTED + losslsc->entropy_encode_mcus = encode_mcus_gather; + losslsc->pub.entropy_finish_pass = finish_pass_gather; +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } else { + losslsc->entropy_encode_mcus = encode_mcus_huff; + losslsc->pub.entropy_finish_pass = finish_pass_huff; + } + + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + dctbl = compptr->dc_tbl_no; + if (gather_statistics) { +#ifdef ENTROPY_OPT_SUPPORTED + /* Check for invalid table indexes */ + /* (make_c_derived_tbl does this in the other path) */ + if (dctbl < 0 || dctbl >= NUM_HUFF_TBLS) + ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, dctbl); + /* Allocate and zero the statistics tables */ + /* Note that jpeg_gen_optimal_table expects 257 entries in each table! */ + if (entropy->count_ptrs[dctbl] == NULL) + entropy->count_ptrs[dctbl] = (long *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + 257 * SIZEOF(long)); + MEMZERO(entropy->count_ptrs[dctbl], 257 * SIZEOF(long)); +#endif + } else { + /* Compute derived values for Huffman tables */ + /* We may do this more than once for a table, but it's not expensive */ + jpeg_make_c_derived_tbl(cinfo, TRUE, dctbl, + & entropy->derived_tbls[dctbl]); + } + } + + /* Precalculate encoding info for each sample in an MCU of this scan */ + for (sampn = 0, ptrn = 0; sampn < cinfo->data_units_in_MCU;) { + compptr = cinfo->cur_comp_info[cinfo->MCU_membership[sampn]]; + ci = compptr->component_index; + /* ci = cinfo->MCU_membership[sampn]; + compptr = cinfo->cur_comp_info[ci];*/ + for (yoffset = 0; yoffset < compptr->MCU_height; yoffset++, ptrn++) { + /* Precalculate the setup info for each input pointer */ + entropy->input_ptr_info[ptrn].ci = ci; + entropy->input_ptr_info[ptrn].yoffset = yoffset; + entropy->input_ptr_info[ptrn].MCU_width = compptr->MCU_width; + for (xoffset = 0; xoffset < compptr->MCU_width; xoffset++, sampn++) { + /* Precalculate the input pointer index for each sample */ + entropy->input_ptr_index[sampn] = ptrn; + /* Precalculate which tables to use for each sample */ + entropy->cur_tbls[sampn] = entropy->derived_tbls[compptr->dc_tbl_no]; + entropy->cur_counts[sampn] = entropy->count_ptrs[compptr->dc_tbl_no]; + } + } + } + entropy->num_input_ptrs = ptrn; + + /* Initialize bit buffer to empty */ + entropy->saved.put_buffer = 0; + entropy->saved.put_bits = 0; + + /* Initialize restart stuff */ + entropy->restarts_to_go = cinfo->restart_interval; + entropy->next_restart_num = 0; +} + + +/* Outputting bytes to the file */ + +/* Emit a byte, taking 'action' if must suspend. */ +#define emit_byte(state,val,action) \ + { *(state)->next_output_byte++ = (JOCTET) (val); \ + if (--(state)->free_in_buffer == 0) \ + if (! dump_buffer(state)) \ + { action; } } + + +LOCAL(boolean) +dump_buffer (working_state * state) +/* Empty the output buffer; return TRUE if successful, FALSE if must suspend */ +{ + struct jpeg_destination_mgr * dest = state->cinfo->dest; + + if (! (*dest->empty_output_buffer) (state->cinfo)) + return FALSE; + /* After a successful buffer dump, must reset buffer pointers */ + state->next_output_byte = dest->next_output_byte; + state->free_in_buffer = dest->free_in_buffer; + return TRUE; +} + + +/* Outputting bits to the file */ + +/* Only the right 24 bits of put_buffer are used; the valid bits are + * left-justified in this part. At most 16 bits can be passed to emit_bits + * in one call, and we never retain more than 7 bits in put_buffer + * between calls, so 24 bits are sufficient. + */ + +INLINE +LOCAL(boolean) +emit_bits (working_state * state, unsigned int code, int size) +/* Emit some bits; return TRUE if successful, FALSE if must suspend */ +{ + /* This routine is heavily used, so it's worth coding tightly. */ + register IJG_INT32 put_buffer = (IJG_INT32) code; + register int put_bits = state->cur.put_bits; + + /* if size is 0, caller used an invalid Huffman table entry */ + if (size == 0) + ERREXIT(state->cinfo, JERR_HUFF_MISSING_CODE); + + put_buffer &= (((IJG_INT32) 1)<cur.put_buffer; /* and merge with old buffer contents */ + + while (put_bits >= 8) { + int c = (int) ((put_buffer >> 16) & 0xFF); + + emit_byte(state, c, return FALSE); + if (c == 0xFF) { /* need to stuff a zero byte? */ + emit_byte(state, 0, return FALSE); + } + put_buffer <<= 8; + put_bits -= 8; + } + + state->cur.put_buffer = put_buffer; /* update state variables */ + state->cur.put_bits = put_bits; + + return TRUE; +} + + +LOCAL(boolean) +flush_bits (working_state * state) +{ + if (! emit_bits(state, 0x7F, 7)) /* fill any partial byte with ones */ + return FALSE; + state->cur.put_buffer = 0; /* and reset bit-buffer to empty */ + state->cur.put_bits = 0; + return TRUE; +} + + +/* + * Emit a restart marker & resynchronize predictions. + */ + +LOCAL(boolean) +emit_restart (working_state * state, int restart_num) +{ + /* int ci; */ + + if (! flush_bits(state)) + return FALSE; + + emit_byte(state, 0xFF, return FALSE); + emit_byte(state, JPEG_RST0 + restart_num, return FALSE); + + /* The restart counter is not updated until we successfully write the MCU. */ + + return TRUE; +} + + +/* + * Encode and output one nMCU's worth of Huffman-compressed differences. + */ + +METHODDEF(JDIMENSION) +encode_mcus_huff (j_compress_ptr cinfo, JDIFFIMAGE diff_buf, + JDIMENSION MCU_row_num, JDIMENSION MCU_col_num, + JDIMENSION nMCU) +{ + j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec; + lhuff_entropy_ptr entropy = (lhuff_entropy_ptr) losslsc->entropy_private; + working_state state; + unsigned int mcu_num; + int sampn, ci, yoffset, MCU_width, ptrn; + /* jpeg_component_info * compptr; */ + + /* Load up working state */ + state.next_output_byte = cinfo->dest->next_output_byte; + state.free_in_buffer = cinfo->dest->free_in_buffer; + ASSIGN_STATE(state.cur, entropy->saved); + state.cinfo = cinfo; + + /* Emit restart marker if needed */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) + if (! emit_restart(&state, entropy->next_restart_num)) + return 0; + } + + /* Set input pointer locations based on MCU_col_num */ + for (ptrn = 0; ptrn < entropy->num_input_ptrs; ptrn++) { + ci = entropy->input_ptr_info[ptrn].ci; + yoffset = entropy->input_ptr_info[ptrn].yoffset; + MCU_width = entropy->input_ptr_info[ptrn].MCU_width; + entropy->input_ptr[ptrn] = + diff_buf[ci][MCU_row_num + (size_t)yoffset] + MCU_col_num * (size_t)MCU_width; + } + + for (mcu_num = 0; mcu_num < nMCU; mcu_num++) { + + /* Inner loop handles the samples in the MCU */ + for (sampn = 0; sampn < cinfo->data_units_in_MCU; sampn++) { + register int temp, temp2 /* , temp3 */ ; + register int nbits; + c_derived_tbl *dctbl = entropy->cur_tbls[sampn]; + + /* Encode the difference per section H.1.2.2 */ + + /* Input the sample difference */ + temp = *entropy->input_ptr[entropy->input_ptr_index[sampn]]++; + + if (temp & 0x8000) { /* instead of temp < 0 */ + temp = (-temp) & 0x7FFF; /* absolute value, mod 2^16 */ + if (temp == 0) /* special case: magnitude = 32768 */ + temp2 = temp = 0x8000; + temp2 = ~ temp; /* one's complement of magnitude */ + } else { + temp &= 0x7FFF; /* abs value mod 2^16 */ + temp2 = temp; /* magnitude */ + } + + /* Find the number of bits needed for the magnitude of the difference */ + nbits = 0; + while (temp) { + nbits++; + temp >>= 1; + } + /* Check for out-of-range difference values. + */ + if (nbits > MAX_DIFF_BITS) + ERREXIT(cinfo, JERR_BAD_DIFF); + + /* Emit the Huffman-coded symbol for the number of bits */ + if (! emit_bits(&state, dctbl->ehufco[nbits], dctbl->ehufsi[nbits])) + return mcu_num; + + /* Emit that number of bits of the value, if positive, */ + /* or the complement of its magnitude, if negative. */ + if (nbits && /* emit_bits rejects calls with size 0 */ + nbits != 16) /* special case: no bits should be emitted */ + if (! emit_bits(&state, (unsigned int) temp2, nbits)) + return mcu_num; + } + + /* Completed MCU, so update state */ + cinfo->dest->next_output_byte = state.next_output_byte; + cinfo->dest->free_in_buffer = state.free_in_buffer; + ASSIGN_STATE(entropy->saved, state.cur); + + /* Update restart-interval state too */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) { + entropy->restarts_to_go = cinfo->restart_interval; + entropy->next_restart_num++; + entropy->next_restart_num &= 7; + } + entropy->restarts_to_go--; + } + + } + + return nMCU; +} + + +/* + * Finish up at the end of a Huffman-compressed scan. + */ + +METHODDEF(void) +finish_pass_huff (j_compress_ptr cinfo) +{ + j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec; + lhuff_entropy_ptr entropy = (lhuff_entropy_ptr) losslsc->entropy_private; + working_state state; + + /* Load up working state ... flush_bits needs it */ + state.next_output_byte = cinfo->dest->next_output_byte; + state.free_in_buffer = cinfo->dest->free_in_buffer; + ASSIGN_STATE(state.cur, entropy->saved); + state.cinfo = cinfo; + + /* Flush out the last data */ + if (! flush_bits(&state)) + ERREXIT(cinfo, JERR_CANT_SUSPEND); + + /* Update state */ + cinfo->dest->next_output_byte = state.next_output_byte; + cinfo->dest->free_in_buffer = state.free_in_buffer; + ASSIGN_STATE(entropy->saved, state.cur); +} + + +/* + * Huffman coding optimization. + * + * We first scan the supplied data and count the number of uses of each symbol + * that is to be Huffman-coded. (This process MUST agree with the code above.) + * Then we build a Huffman coding tree for the observed counts. + * Symbols which are not needed at all for the particular image are not + * assigned any code, which saves space in the DHT marker as well as in + * the compressed data. + */ + +#ifdef ENTROPY_OPT_SUPPORTED + +/* + * Trial-encode one nMCU's worth of Huffman-compressed differences. + * No data is actually output, so no suspension return is possible. + */ + +METHODDEF(JDIMENSION) +encode_mcus_gather (j_compress_ptr cinfo, JDIFFIMAGE diff_buf, + JDIMENSION MCU_row_num, JDIMENSION MCU_col_num, + JDIMENSION nMCU) +{ + j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec; + lhuff_entropy_ptr entropy = (lhuff_entropy_ptr) losslsc->entropy_private; + unsigned int mcu_num; + int sampn, ci, yoffset, MCU_width, ptrn; + /* jpeg_component_info * compptr; */ + + /* Take care of restart intervals if needed */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) { + /* Update restart state */ + entropy->restarts_to_go = cinfo->restart_interval; + } + entropy->restarts_to_go--; + } + + /* Set input pointer locations based on MCU_col_num */ + for (ptrn = 0; ptrn < entropy->num_input_ptrs; ptrn++) { + ci = entropy->input_ptr_info[ptrn].ci; + yoffset = entropy->input_ptr_info[ptrn].yoffset; + MCU_width = entropy->input_ptr_info[ptrn].MCU_width; + entropy->input_ptr[ptrn] = + diff_buf[ci][MCU_row_num + (size_t)yoffset] + MCU_col_num * (size_t)MCU_width; + } + + for (mcu_num = 0; mcu_num < nMCU; mcu_num++) { + + /* Inner loop handles the samples in the MCU */ + for (sampn = 0; sampn < cinfo->data_units_in_MCU; sampn++) { + register int temp; + register int nbits; + /* c_derived_tbl *dctbl = entropy->cur_tbls[sampn]; */ + long * counts = entropy->cur_counts[sampn]; + + /* Encode the difference per section H.1.2.2 */ + + /* Input the sample difference */ + temp = *entropy->input_ptr[entropy->input_ptr_index[sampn]]++; + + if (temp & 0x8000) { /* instead of temp < 0 */ + temp = (-temp) & 0x7FFF; /* absolute value, mod 2^16 */ + if (temp == 0) /* special case: magnitude = 32768 */ + temp = 0x8000; + } else + temp &= 0x7FFF; /* abs value mod 2^16 */ + + /* Find the number of bits needed for the magnitude of the difference */ + nbits = 0; + while (temp) { + nbits++; + temp >>= 1; + } + /* Check for out-of-range difference values. + */ + if (nbits > MAX_DIFF_BITS) + ERREXIT(cinfo, JERR_BAD_DIFF); + + /* Count the Huffman symbol for the number of bits */ + counts[nbits]++; + } + } + + return nMCU; +} + + +/* + * Finish up a statistics-gathering pass and create the new Huffman tables. + */ + +METHODDEF(void) +finish_pass_gather (j_compress_ptr cinfo) +{ + j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec; + lhuff_entropy_ptr entropy = (lhuff_entropy_ptr) losslsc->entropy_private; + int ci, dctbl; + jpeg_component_info * compptr; + JHUFF_TBL **htblptr; + boolean did_dc[NUM_HUFF_TBLS]; + + /* It's important not to apply jpeg_gen_optimal_table more than once + * per table, because it clobbers the input frequency counts! + */ + MEMZERO(did_dc, SIZEOF(did_dc)); + + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + dctbl = compptr->dc_tbl_no; + if (! did_dc[dctbl]) { + htblptr = & cinfo->dc_huff_tbl_ptrs[dctbl]; + if (*htblptr == NULL) + *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo); + jpeg_gen_optimal_table(cinfo, *htblptr, entropy->count_ptrs[dctbl]); + did_dc[dctbl] = TRUE; + } + } +} + + +#endif /* ENTROPY_OPT_SUPPORTED */ + + +METHODDEF(boolean) +need_optimization_pass (j_compress_ptr cinfo) +{ + return TRUE; +} + + +/* + * Module initialization routine for Huffman entropy encoding. + */ + +GLOBAL(void) +jinit_lhuff_encoder (j_compress_ptr cinfo) +{ + j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec; + lhuff_entropy_ptr entropy; + int i; + + entropy = (lhuff_entropy_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(lhuff_entropy_encoder)); + losslsc->entropy_private = (struct jpeg_entropy_encoder *) entropy; + losslsc->pub.entropy_start_pass = start_pass_huff; + losslsc->pub.need_optimization_pass = need_optimization_pass; + + /* Mark tables unallocated */ + for (i = 0; i < NUM_HUFF_TBLS; i++) { + entropy->derived_tbls[i] = NULL; +#ifdef ENTROPY_OPT_SUPPORTED + entropy->count_ptrs[i] = NULL; +#endif + } +} diff --git a/dcmjpeg/libijg8/jclossls.c b/dcmjpeg/libijg8/jclossls.c new file mode 100644 index 00000000..0b534c1e --- /dev/null +++ b/dcmjpeg/libijg8/jclossls.c @@ -0,0 +1,82 @@ +/* + * jclossls.c + * + * Copyright (C) 1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains the control logic for the lossless JPEG compressor. + */ + +#define JPEG_INTERNALS +#include "jinclude8.h" +#include "jpeglib8.h" +#include "jlossls8.h" + + +#ifdef C_LOSSLESS_SUPPORTED + +/* + * Initialize for a processing pass. + */ + +METHODDEF(void) +start_pass (j_compress_ptr cinfo, J_BUF_MODE pass_mode) +{ + j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec; + + (*losslsc->scaler_start_pass) (cinfo); + (*losslsc->predict_start_pass) (cinfo); + (*losslsc->diff_start_pass) (cinfo, pass_mode); +} + + +/* + * Initialize the lossless compression codec. + * This is called only once, during master selection. + */ + +GLOBAL(void) +jinit_lossless_c_codec(j_compress_ptr cinfo) +{ + j_lossless_c_ptr losslsc; + + /* Create subobject in permanent pool */ + losslsc = (j_lossless_c_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, + SIZEOF(jpeg_lossless_c_codec)); + cinfo->codec = (struct jpeg_c_codec *) losslsc; + + /* Initialize sub-modules */ + + /* Scaler */ + jinit_c_scaler(cinfo); + + /* Differencer */ + jinit_differencer(cinfo); + + /* Entropy encoding: either Huffman or arithmetic coding. */ + if (cinfo->arith_code) { +#ifdef WITH_ARITHMETIC_PATCH + jinit_arith_encoder(cinfo); +#else + ERREXIT(cinfo, JERR_ARITH_NOTIMPL); +#endif + } else { + jinit_lhuff_encoder(cinfo); + } + + /* Need a full-image difference buffer in any multi-pass mode. */ + jinit_c_diff_controller(cinfo, + (boolean) (cinfo->num_scans > 1 || + cinfo->optimize_coding)); + + /* Initialize method pointers. + * + * Note: entropy_start_pass and entropy_finish_pass are assigned in + * jclhuff.c and compress_data is assigned in jcdiffct.c. + */ + losslsc->pub.start_pass = start_pass; +} + +#endif /* C_LOSSLESS_SUPPORTED */ diff --git a/dcmjpeg/libijg8/jclossy.c b/dcmjpeg/libijg8/jclossy.c new file mode 100644 index 00000000..5d1c30c3 --- /dev/null +++ b/dcmjpeg/libijg8/jclossy.c @@ -0,0 +1,80 @@ +/* + * jclossy.c + * + * Copyright (C) 1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains the control logic for the lossy JPEG compressor. + */ + +#define JPEG_INTERNALS +#include "jinclude8.h" +#include "jpeglib8.h" +#include "jlossy8.h" + + +/* + * Initialize for a processing pass. + */ + +METHODDEF(void) +start_pass (j_compress_ptr cinfo, J_BUF_MODE pass_mode) +{ + j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; + + (*lossyc->fdct_start_pass) (cinfo); + (*lossyc->coef_start_pass) (cinfo, pass_mode); +} + + +/* + * Initialize the lossy compression codec. + * This is called only once, during master selection. + */ + +GLOBAL(void) +jinit_lossy_c_codec (j_compress_ptr cinfo) +{ + j_lossy_c_ptr lossyc; + + /* Create subobject in permanent pool */ + lossyc = (j_lossy_c_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, + SIZEOF(jpeg_lossy_c_codec)); + cinfo->codec = (struct jpeg_c_codec *) lossyc; + + /* Initialize sub-modules */ + + /* Forward DCT */ + jinit_forward_dct(cinfo); + /* Entropy encoding: either Huffman or arithmetic coding. */ + if (cinfo->arith_code) { +#ifdef WITH_ARITHMETIC_PATCH + jinit_arith_encoder(cinfo); +#else + ERREXIT(cinfo, JERR_ARITH_NOTIMPL); +#endif + } else { + if (cinfo->process == JPROC_PROGRESSIVE) { +#ifdef C_PROGRESSIVE_SUPPORTED + jinit_phuff_encoder(cinfo); +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } else + jinit_shuff_encoder(cinfo); + } + + /* Need a full-image coefficient buffer in any multi-pass mode. */ + jinit_c_coef_controller(cinfo, + (boolean) (cinfo->num_scans > 1 || + cinfo->optimize_coding)); + + /* Initialize method pointers. + * + * Note: entropy_start_pass and entropy_finish_pass are assigned in + * jcshuff.c or jcphuff.c and compress_data is assigned in jccoefct.c. + */ + lossyc->pub.start_pass = start_pass; +} diff --git a/dcmjpeg/libijg8/jcmainct.c b/dcmjpeg/libijg8/jcmainct.c new file mode 100644 index 00000000..64c95740 --- /dev/null +++ b/dcmjpeg/libijg8/jcmainct.c @@ -0,0 +1,296 @@ +/* + * jcmainct.c + * + * Copyright (C) 1994-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains the main buffer controller for compression. + * The main buffer lies between the pre-processor and the JPEG + * compressor proper; it holds downsampled data in the JPEG colorspace. + */ + +#define JPEG_INTERNALS +#include "jinclude8.h" +#include "jpeglib8.h" + + +/* Note: currently, there is no operating mode in which a full-image buffer + * is needed at this step. If there were, that mode could not be used with + * "raw data" input, since this module is bypassed in that case. However, + * we've left the code here for possible use in special applications. + */ +#undef FULL_MAIN_BUFFER_SUPPORTED + + +/* Private buffer controller object */ + +typedef struct { + struct jpeg_c_main_controller pub; /* public fields */ + + JDIMENSION cur_iMCU_row; /* number of current iMCU row */ + JDIMENSION rowgroup_ctr; /* counts row groups received in iMCU row */ + boolean suspended; /* remember if we suspended output */ + J_BUF_MODE pass_mode; /* current operating mode */ + + /* If using just a strip buffer, this points to the entire set of buffers + * (we allocate one for each component). In the full-image case, this + * points to the currently accessible strips of the virtual arrays. + */ + JSAMPARRAY buffer[MAX_COMPONENTS]; + +#ifdef FULL_MAIN_BUFFER_SUPPORTED + /* If using full-image storage, this array holds pointers to virtual-array + * control blocks for each component. Unused if not full-image storage. + */ + jvirt_sarray_ptr whole_image[MAX_COMPONENTS]; +#endif +} my_main_controller; + +typedef my_main_controller * my_main_ptr; + + +/* Forward declarations */ +METHODDEF(void) process_data_simple_main + JPP((j_compress_ptr cinfo, JSAMPARRAY input_buf, + JDIMENSION *in_row_ctr, JDIMENSION in_rows_avail)); +#ifdef FULL_MAIN_BUFFER_SUPPORTED +METHODDEF(void) process_data_buffer_main + JPP((j_compress_ptr cinfo, JSAMPARRAY input_buf, + JDIMENSION *in_row_ctr, JDIMENSION in_rows_avail)); +#endif + + +/* + * Initialize for a processing pass. + */ + +METHODDEF(void) +start_pass_main (j_compress_ptr cinfo, J_BUF_MODE pass_mode) +{ + my_main_ptr mymain = (my_main_ptr) cinfo->main; + + /* Do nothing in raw-data mode. */ + if (cinfo->raw_data_in) + return; + + mymain->cur_iMCU_row = 0; /* initialize counters */ + mymain->rowgroup_ctr = 0; + mymain->suspended = FALSE; + mymain->pass_mode = pass_mode; /* save mode for use by process_data */ + + switch (pass_mode) { + case JBUF_PASS_THRU: +#ifdef FULL_MAIN_BUFFER_SUPPORTED + if (mymain->whole_image[0] != NULL) + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); +#endif + mymain->pub.process_data = process_data_simple_main; + break; +#ifdef FULL_MAIN_BUFFER_SUPPORTED + case JBUF_SAVE_SOURCE: + case JBUF_CRANK_DEST: + case JBUF_SAVE_AND_PASS: + if (mymain->whole_image[0] == NULL) + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + mymain->pub.process_data = process_data_buffer_main; + break; +#endif + default: + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + break; + } +} + + +/* + * Process some data. + * This routine handles the simple pass-through mode, + * where we have only a strip buffer. + */ + +METHODDEF(void) +process_data_simple_main (j_compress_ptr cinfo, + JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, + JDIMENSION in_rows_avail) +{ + my_main_ptr mymain = (my_main_ptr) cinfo->main; + JDIMENSION data_unit = (JDIMENSION)(cinfo->data_unit); + + while (mymain->cur_iMCU_row < cinfo->total_iMCU_rows) { + /* Read input data if we haven't filled the main buffer yet */ + if (mymain->rowgroup_ctr < data_unit) + (*cinfo->prep->pre_process_data) (cinfo, + input_buf, in_row_ctr, in_rows_avail, + mymain->buffer, &mymain->rowgroup_ctr, + (JDIMENSION) data_unit); + + /* If we don't have a full iMCU row buffered, return to application for + * more data. Note that preprocessor will always pad to fill the iMCU row + * at the bottom of the image. + */ + if (mymain->rowgroup_ctr != data_unit) + return; + + /* Send the completed row to the compressor */ + if (! (*cinfo->codec->compress_data) (cinfo, mymain->buffer)) { + /* If compressor did not consume the whole row, then we must need to + * suspend processing and return to the application. In this situation + * we pretend we didn't yet consume the last input row; otherwise, if + * it happened to be the last row of the image, the application would + * think we were done. + */ + if (! mymain->suspended) { + (*in_row_ctr)--; + mymain->suspended = TRUE; + } + return; + } + /* We did finish the row. Undo our little suspension hack if a previous + * call suspended; then mark the main buffer empty. + */ + if (mymain->suspended) { + (*in_row_ctr)++; + mymain->suspended = FALSE; + } + mymain->rowgroup_ctr = 0; + mymain->cur_iMCU_row++; + } +} + + +#ifdef FULL_MAIN_BUFFER_SUPPORTED + +/* + * Process some data. + * This routine handles all of the modes that use a full-size buffer. + */ + +METHODDEF(void) +process_data_buffer_main (j_compress_ptr cinfo, + JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, + JDIMENSION in_rows_avail) +{ + my_main_ptr mymain = (my_main_ptr) cinfo->main; + int ci; + jpeg_component_info *compptr; + boolean writing = (mymain->pass_mode != JBUF_CRANK_DEST); + JDIMENSION data_unit = (JDIMENSION)(cinfo->data_unit); + + while (mymain->cur_iMCU_row < cinfo->total_iMCU_rows) { + /* Realign the virtual buffers if at the start of an iMCU row. */ + if (mymain->rowgroup_ctr == 0) { + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + mymain->buffer[ci] = (*cinfo->mem->access_virt_sarray) + ((j_common_ptr) cinfo, mymain->whole_image[ci], + mymain->cur_iMCU_row * (compptr->v_samp_factor * data_unit), + (JDIMENSION) (compptr->v_samp_factor * data_unit), writing); + } + /* In a read pass, pretend we just read some source data. */ + if (! writing) { + *in_row_ctr += cinfo->max_v_samp_factor * data_unit; + mymain->rowgroup_ctr = data_unit; + } + } + + /* If a write pass, read input data until the current iMCU row is full. */ + /* Note: preprocessor will pad if necessary to fill the last iMCU row. */ + if (writing) { + (*cinfo->prep->pre_process_data) (cinfo, + input_buf, in_row_ctr, in_rows_avail, + mymain->buffer, &mymain->rowgroup_ctr, + (JDIMENSION) data_unit); + /* Return to application if we need more data to fill the iMCU row. */ + if (mymain->rowgroup_ctr < data_unit) + return; + } + + /* Emit data, unless this is a sink-only pass. */ + if (mymain->pass_mode != JBUF_SAVE_SOURCE) { + if (! (*cinfo->codec->compress_data) (cinfo, mymain->buffer)) { + /* If compressor did not consume the whole row, then we must need to + * suspend processing and return to the application. In this situation + * we pretend we didn't yet consume the last input row; otherwise, if + * it happened to be the last row of the image, the application would + * think we were done. + */ + if (! mymain->suspended) { + (*in_row_ctr)--; + mymain->suspended = TRUE; + } + return; + } + /* We did finish the row. Undo our little suspension hack if a previous + * call suspended; then mark the main buffer empty. + */ + if (mymain->suspended) { + (*in_row_ctr)++; + mymain->suspended = FALSE; + } + } + + /* If get here, we are done with this iMCU row. Mark buffer empty. */ + mymain->rowgroup_ctr = 0; + mymain->cur_iMCU_row++; + } +} + +#endif /* FULL_MAIN_BUFFER_SUPPORTED */ + + +/* + * Initialize main buffer controller. + */ + +GLOBAL(void) +jinit_c_main_controller (j_compress_ptr cinfo, boolean need_full_buffer) +{ + my_main_ptr mymain; + int ci; + jpeg_component_info *compptr; + int data_unit = cinfo->data_unit; + + mymain = (my_main_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_main_controller)); + cinfo->main = (struct jpeg_c_main_controller *) mymain; + mymain->pub.start_pass = start_pass_main; + + /* We don't need to create a buffer in raw-data mode. */ + if (cinfo->raw_data_in) + return; + + /* Create the buffer. It holds downsampled data, so each component + * may be of a different size. + */ + if (need_full_buffer) { +#ifdef FULL_MAIN_BUFFER_SUPPORTED + /* Allocate a full-image virtual array for each component */ + /* Note we pad the bottom to a multiple of the iMCU height */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + mymain->whole_image[ci] = (*cinfo->mem->request_virt_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE, + compptr->width_in_data_units * data_unit, + (JDIMENSION) jround_up((long) compptr->height_in_data_units, + (long) compptr->v_samp_factor) * data_unit, + (JDIMENSION) (compptr->v_samp_factor * data_unit)); + } +#else + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); +#endif + } else { +#ifdef FULL_MAIN_BUFFER_SUPPORTED + mymain->whole_image[0] = NULL; /* flag for no virtual arrays */ +#endif + /* Allocate a strip buffer for each component */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + mymain->buffer[ci] = (*cinfo->mem->alloc_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + compptr->width_in_data_units * (JDIMENSION)data_unit, + (JDIMENSION) (compptr->v_samp_factor * data_unit)); + } + } +} diff --git a/dcmjpeg/libijg8/jcmarker.c b/dcmjpeg/libijg8/jcmarker.c new file mode 100644 index 00000000..857f22b1 --- /dev/null +++ b/dcmjpeg/libijg8/jcmarker.c @@ -0,0 +1,680 @@ +/* + * jcmarker.c + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains routines to write JPEG datastream markers. + */ + +#define JPEG_INTERNALS +#include "jinclude8.h" +#include "jpeglib8.h" + + +typedef enum { /* JPEG marker codes */ + M_SOF0 = 0xc0, + M_SOF1 = 0xc1, + M_SOF2 = 0xc2, + M_SOF3 = 0xc3, + + M_SOF5 = 0xc5, + M_SOF6 = 0xc6, + M_SOF7 = 0xc7, + + M_JPG = 0xc8, + M_SOF9 = 0xc9, + M_SOF10 = 0xca, + M_SOF11 = 0xcb, + + M_SOF13 = 0xcd, + M_SOF14 = 0xce, + M_SOF15 = 0xcf, + + M_DHT = 0xc4, + + M_DAC = 0xcc, + + M_RST0 = 0xd0, + M_RST1 = 0xd1, + M_RST2 = 0xd2, + M_RST3 = 0xd3, + M_RST4 = 0xd4, + M_RST5 = 0xd5, + M_RST6 = 0xd6, + M_RST7 = 0xd7, + + M_SOI = 0xd8, + M_EOI = 0xd9, + M_SOS = 0xda, + M_DQT = 0xdb, + M_DNL = 0xdc, + M_DRI = 0xdd, + M_DHP = 0xde, + M_EXP = 0xdf, + + M_APP0 = 0xe0, + M_APP1 = 0xe1, + M_APP2 = 0xe2, + M_APP3 = 0xe3, + M_APP4 = 0xe4, + M_APP5 = 0xe5, + M_APP6 = 0xe6, + M_APP7 = 0xe7, + M_APP8 = 0xe8, + M_APP9 = 0xe9, + M_APP10 = 0xea, + M_APP11 = 0xeb, + M_APP12 = 0xec, + M_APP13 = 0xed, + M_APP14 = 0xee, + M_APP15 = 0xef, + + M_JPG0 = 0xf0, + M_JPG13 = 0xfd, + M_COM = 0xfe, + + M_TEM = 0x01, + + M_ERROR = 0x100 +} JPEG_MARKER; + + +/* Private state */ + +typedef struct { + struct jpeg_marker_writer pub; /* public fields */ + + unsigned int last_restart_interval; /* last DRI value emitted; 0 after SOI */ +} my_marker_writer; + +typedef my_marker_writer * my_marker_ptr; + + +/* + * Basic output routines. + * + * Note that we do not support suspension while writing a marker. + * Therefore, an application using suspension must ensure that there is + * enough buffer space for the initial markers (typ. 600-700 bytes) before + * calling jpeg_start_compress, and enough space to write the trailing EOI + * (a few bytes) before calling jpeg_finish_compress. Multipass compression + * modes are not supported at all with suspension, so those two are the only + * points where markers will be written. + */ + +LOCAL(void) +emit_byte (j_compress_ptr cinfo, int val) +/* Emit a byte */ +{ + struct jpeg_destination_mgr * dest = cinfo->dest; + + *(dest->next_output_byte)++ = (JOCTET) val; + if (--dest->free_in_buffer == 0) { + if (! (*dest->empty_output_buffer) (cinfo)) + ERREXIT(cinfo, JERR_CANT_SUSPEND); + } +} + + +LOCAL(void) +emit_marker (j_compress_ptr cinfo, JPEG_MARKER mark) +/* Emit a marker code */ +{ + emit_byte(cinfo, 0xFF); + emit_byte(cinfo, (int) mark); +} + + +LOCAL(void) +emit_2bytes (j_compress_ptr cinfo, int value) +/* Emit a 2-byte integer; these are always MSB first in JPEG files */ +{ + emit_byte(cinfo, (value >> 8) & 0xFF); + emit_byte(cinfo, value & 0xFF); +} + + +/* + * Routines to write specific marker types. + */ + +LOCAL(int) +emit_dqt (j_compress_ptr cinfo, int idx) +/* Emit a DQT marker */ +/* Returns the precision used (0 = 8bits, 1 = 16bits) for baseline checking */ +{ + JQUANT_TBL * qtbl = cinfo->quant_tbl_ptrs[idx]; + int prec; + int i; + + if (qtbl == NULL) + ERREXIT1(cinfo, JERR_NO_QUANT_TABLE, idx); + + prec = 0; + for (i = 0; i < DCTSIZE2; i++) { + if (qtbl->quantval[i] > 255) + prec = 1; + } + + if (! qtbl->sent_table) { + emit_marker(cinfo, M_DQT); + + emit_2bytes(cinfo, prec ? DCTSIZE2*2 + 1 + 2 : DCTSIZE2 + 1 + 2); + + emit_byte(cinfo, idx + (prec<<4)); + + for (i = 0; i < DCTSIZE2; i++) { + /* The table entries must be emitted in zigzag order. */ + unsigned int qval = qtbl->quantval[jpeg_natural_order[i]]; + if (prec) + emit_byte(cinfo, (int) (qval >> 8)); + emit_byte(cinfo, (int) (qval & 0xFF)); + } + + qtbl->sent_table = TRUE; + } + + return prec; +} + + +LOCAL(void) +emit_dht (j_compress_ptr cinfo, int idx, boolean is_ac) +/* Emit a DHT marker */ +{ + JHUFF_TBL * htbl; + int length, i; + + if (is_ac) { + htbl = cinfo->ac_huff_tbl_ptrs[idx]; + idx += 0x10; /* output index has AC bit set */ + } else { + htbl = cinfo->dc_huff_tbl_ptrs[idx]; + } + + if (htbl == NULL) + ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, idx); + + if (! htbl->sent_table) { + emit_marker(cinfo, M_DHT); + + length = 0; + for (i = 1; i <= 16; i++) + length += htbl->bits[i]; + + emit_2bytes(cinfo, length + 2 + 1 + 16); + emit_byte(cinfo, idx); + + for (i = 1; i <= 16; i++) + emit_byte(cinfo, htbl->bits[i]); + + for (i = 0; i < length; i++) + emit_byte(cinfo, htbl->huffval[i]); + + htbl->sent_table = TRUE; + } +} + + +LOCAL(void) +emit_dac (j_compress_ptr cinfo) +/* Emit a DAC marker */ +/* Since the useful info is so small, we want to emit all the tables in */ +/* one DAC marker. Therefore this routine does its own scan of the table. */ +{ +#ifdef C_ARITH_CODING_SUPPORTED + char dc_in_use[NUM_ARITH_TBLS]; + char ac_in_use[NUM_ARITH_TBLS]; + int length, i; + jpeg_component_info *compptr; + + for (i = 0; i < NUM_ARITH_TBLS; i++) + dc_in_use[i] = ac_in_use[i] = 0; + + for (i = 0; i < cinfo->comps_in_scan; i++) { + compptr = cinfo->cur_comp_info[i]; + dc_in_use[compptr->dc_tbl_no] = 1; + ac_in_use[compptr->ac_tbl_no] = 1; + } + + length = 0; + for (i = 0; i < NUM_ARITH_TBLS; i++) + length += dc_in_use[i] + ac_in_use[i]; + + emit_marker(cinfo, M_DAC); + + emit_2bytes(cinfo, length*2 + 2); + + for (i = 0; i < NUM_ARITH_TBLS; i++) { + if (dc_in_use[i]) { + emit_byte(cinfo, i); + emit_byte(cinfo, cinfo->arith_dc_L[i] + (cinfo->arith_dc_U[i]<<4)); + } + if (ac_in_use[i]) { + emit_byte(cinfo, i + 0x10); + emit_byte(cinfo, cinfo->arith_ac_K[i]); + } + } +#endif /* C_ARITH_CODING_SUPPORTED */ +} + + +LOCAL(void) +emit_dri (j_compress_ptr cinfo) +/* Emit a DRI marker */ +{ + emit_marker(cinfo, M_DRI); + + emit_2bytes(cinfo, 4); /* fixed length */ + + emit_2bytes(cinfo, (int) cinfo->restart_interval); +} + + +LOCAL(void) +emit_sof (j_compress_ptr cinfo, JPEG_MARKER code) +/* Emit a SOF marker */ +{ + int ci; + jpeg_component_info *compptr; + + emit_marker(cinfo, code); + + emit_2bytes(cinfo, 3 * cinfo->num_components + 2 + 5 + 1); /* length */ + + /* Make sure image isn't bigger than SOF field can handle */ + if ((long) cinfo->image_height > 65535L || + (long) cinfo->image_width > 65535L) + ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, (unsigned int) 65535); + + emit_byte(cinfo, cinfo->data_precision); + emit_2bytes(cinfo, (int) cinfo->image_height); + emit_2bytes(cinfo, (int) cinfo->image_width); + + emit_byte(cinfo, cinfo->num_components); + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + emit_byte(cinfo, compptr->component_id); + emit_byte(cinfo, (compptr->h_samp_factor << 4) + compptr->v_samp_factor); + emit_byte(cinfo, compptr->quant_tbl_no); + } +} + + +LOCAL(void) +emit_sos (j_compress_ptr cinfo) +/* Emit a SOS marker */ +{ + int i, td, ta; + jpeg_component_info *compptr; + + emit_marker(cinfo, M_SOS); + + emit_2bytes(cinfo, 2 * cinfo->comps_in_scan + 2 + 1 + 3); /* length */ + + emit_byte(cinfo, cinfo->comps_in_scan); + + for (i = 0; i < cinfo->comps_in_scan; i++) { + compptr = cinfo->cur_comp_info[i]; + emit_byte(cinfo, compptr->component_id); + td = compptr->dc_tbl_no; + ta = compptr->ac_tbl_no; + if (cinfo->process == JPROC_PROGRESSIVE) { + /* Progressive mode: only DC or only AC tables are used in one scan; + * furthermore, Huffman coding of DC refinement uses no table at all. + * We emit 0 for unused field(s); this is recommended by the P&M text + * but does not seem to be specified in the standard. + */ + if (cinfo->Ss == 0) { + ta = 0; /* DC scan */ + if (cinfo->Ah != 0 && !cinfo->arith_code) + td = 0; /* no DC table either */ + } else { + td = 0; /* AC scan */ + } + } + emit_byte(cinfo, (td << 4) + ta); + } + + emit_byte(cinfo, cinfo->Ss); + emit_byte(cinfo, cinfo->Se); + emit_byte(cinfo, (cinfo->Ah << 4) + cinfo->Al); +} + + +LOCAL(void) +emit_jfif_app0 (j_compress_ptr cinfo) +/* Emit a JFIF-compliant APP0 marker */ +{ + /* + * Length of APP0 block (2 bytes) + * Block ID (4 bytes - ASCII "JFIF") + * Zero byte (1 byte to terminate the ID string) + * Version Major, Minor (2 bytes - major first) + * Units (1 byte - 0x00 = none, 0x01 = inch, 0x02 = cm) + * Xdpu (2 bytes - dots per unit horizontal) + * Ydpu (2 bytes - dots per unit vertical) + * Thumbnail X size (1 byte) + * Thumbnail Y size (1 byte) + */ + + emit_marker(cinfo, M_APP0); + + emit_2bytes(cinfo, 2 + 4 + 1 + 2 + 1 + 2 + 2 + 1 + 1); /* length */ + + emit_byte(cinfo, 0x4A); /* Identifier: ASCII "JFIF" */ + emit_byte(cinfo, 0x46); + emit_byte(cinfo, 0x49); + emit_byte(cinfo, 0x46); + emit_byte(cinfo, 0); + emit_byte(cinfo, cinfo->JFIF_major_version); /* Version fields */ + emit_byte(cinfo, cinfo->JFIF_minor_version); + emit_byte(cinfo, cinfo->density_unit); /* Pixel size information */ + emit_2bytes(cinfo, (int) cinfo->X_density); + emit_2bytes(cinfo, (int) cinfo->Y_density); + emit_byte(cinfo, 0); /* No thumbnail image */ + emit_byte(cinfo, 0); +} + + +LOCAL(void) +emit_adobe_app14 (j_compress_ptr cinfo) +/* Emit an Adobe APP14 marker */ +{ + /* + * Length of APP14 block (2 bytes) + * Block ID (5 bytes - ASCII "Adobe") + * Version Number (2 bytes - currently 100) + * Flags0 (2 bytes - currently 0) + * Flags1 (2 bytes - currently 0) + * Color transform (1 byte) + * + * Although Adobe TN 5116 mentions Version = 101, all the Adobe files + * now in circulation seem to use Version = 100, so that's what we write. + * + * We write the color transform byte as 1 if the JPEG color space is + * YCbCr, 2 if it's YCCK, 0 otherwise. Adobe's definition has to do with + * whether the encoder performed a transformation, which is pretty useless. + */ + + emit_marker(cinfo, M_APP14); + + emit_2bytes(cinfo, 2 + 5 + 2 + 2 + 2 + 1); /* length */ + + emit_byte(cinfo, 0x41); /* Identifier: ASCII "Adobe" */ + emit_byte(cinfo, 0x64); + emit_byte(cinfo, 0x6F); + emit_byte(cinfo, 0x62); + emit_byte(cinfo, 0x65); + emit_2bytes(cinfo, 100); /* Version */ + emit_2bytes(cinfo, 0); /* Flags0 */ + emit_2bytes(cinfo, 0); /* Flags1 */ + switch (cinfo->jpeg_color_space) { + case JCS_YCbCr: + emit_byte(cinfo, 1); /* Color transform = 1 */ + break; + case JCS_YCCK: + emit_byte(cinfo, 2); /* Color transform = 2 */ + break; + default: + emit_byte(cinfo, 0); /* Color transform = 0 */ + break; + } +} + + +/* + * These routines allow writing an arbitrary marker with parameters. + * The only intended use is to emit COM or APPn markers after calling + * write_file_header and before calling write_frame_header. + * Other uses are not guaranteed to produce desirable results. + * Counting the parameter bytes properly is the caller's responsibility. + */ + +METHODDEF(void) +write_marker_header (j_compress_ptr cinfo, int marker, unsigned int datalen) +/* Emit an arbitrary marker header */ +{ + if (datalen > (unsigned int) 65533) /* safety check */ + ERREXIT(cinfo, JERR_BAD_LENGTH); + + emit_marker(cinfo, (JPEG_MARKER) marker); + + emit_2bytes(cinfo, (int) (datalen + 2)); /* total length */ +} + +METHODDEF(void) +write_marker_byte (j_compress_ptr cinfo, int val) +/* Emit one byte of marker parameters following write_marker_header */ +{ + emit_byte(cinfo, val); +} + + +/* + * Write datastream header. + * This consists of an SOI and optional APPn markers. + * We recommend use of the JFIF marker, but not the Adobe marker, + * when using YCbCr or grayscale data. The JFIF marker should NOT + * be used for any other JPEG colorspace. The Adobe marker is helpful + * to distinguish RGB, CMYK, and YCCK colorspaces. + * Note that an application can write additional header markers after + * jpeg_start_compress returns. + */ + +METHODDEF(void) +write_file_header (j_compress_ptr cinfo) +{ + my_marker_ptr marker = (my_marker_ptr) cinfo->marker; + + emit_marker(cinfo, M_SOI); /* first the SOI */ + + /* SOI is defined to reset restart interval to 0 */ + marker->last_restart_interval = 0; + + if (cinfo->write_JFIF_header) /* next an optional JFIF APP0 */ + emit_jfif_app0(cinfo); + if (cinfo->write_Adobe_marker) /* next an optional Adobe APP14 */ + emit_adobe_app14(cinfo); +} + + +/* + * Write frame header. + * This consists of DQT and SOFn markers. + * Note that we do not emit the SOF until we have emitted the DQT(s). + * This avoids compatibility problems with incorrect implementations that + * try to error-check the quant table numbers as soon as they see the SOF. + */ + +METHODDEF(void) +write_frame_header (j_compress_ptr cinfo) +{ + int ci, prec; + boolean is_baseline; + jpeg_component_info *compptr; + + prec = 0; + if (cinfo->process != JPROC_LOSSLESS) { + /* Emit DQT for each quantization table. + * Note that emit_dqt() suppresses any duplicate tables. + */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + prec += emit_dqt(cinfo, compptr->quant_tbl_no); + } + /* now prec is nonzero iff there are any 16-bit quant tables. */ + } + + /* Check for a non-baseline specification. + * Note we assume that Huffman table numbers won't be changed later. + */ + if (cinfo->arith_code || cinfo->process != JPROC_SEQUENTIAL || + cinfo->data_precision != 8) { + is_baseline = FALSE; + } else { + is_baseline = TRUE; + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + if (compptr->dc_tbl_no > 1 || compptr->ac_tbl_no > 1) + is_baseline = FALSE; + } + if (prec && is_baseline) { + is_baseline = FALSE; + /* If it's baseline except for quantizer size, warn the user */ + TRACEMS(cinfo, 0, JTRC_16BIT_TABLES); + } + } + + /* Emit the proper SOF marker */ + if (cinfo->arith_code) { +#ifdef WITH_ARITHMETIC_PATCH + if (cinfo->process == JPROC_PROGRESSIVE) + emit_sof(cinfo, M_SOF10); /* SOF code for progressive arithmetic */ + else if (cinfo->process == JPROC_LOSSLESS) + emit_sof(cinfo, M_SOF11); /* SOF code for lossless arithmetic */ + else + emit_sof(cinfo, M_SOF9); /* SOF code for sequential arithmetic */ +#else + emit_sof(cinfo, M_SOF9); /* SOF code for arithmetic coding */ +#endif + } else { + if (cinfo->process == JPROC_PROGRESSIVE) + emit_sof(cinfo, M_SOF2); /* SOF code for progressive Huffman */ + else if (cinfo->process == JPROC_LOSSLESS) + emit_sof(cinfo, M_SOF3); /* SOF code for lossless Huffman */ + else if (is_baseline) + emit_sof(cinfo, M_SOF0); /* SOF code for baseline implementation */ + else + emit_sof(cinfo, M_SOF1); /* SOF code for non-baseline Huffman file */ + } +} + + +/* + * Write scan header. + * This consists of DHT or DAC markers, optional DRI, and SOS. + * Compressed data will be written following the SOS. + */ + +METHODDEF(void) +write_scan_header (j_compress_ptr cinfo) +{ + my_marker_ptr marker = (my_marker_ptr) cinfo->marker; + int i; + jpeg_component_info *compptr; + + if (cinfo->arith_code) { + /* Emit arith conditioning info. We may have some duplication + * if the file has multiple scans, but it's so small it's hardly + * worth worrying about. + */ + emit_dac(cinfo); + } else { + /* Emit Huffman tables. + * Note that emit_dht() suppresses any duplicate tables. + */ + for (i = 0; i < cinfo->comps_in_scan; i++) { + compptr = cinfo->cur_comp_info[i]; + if (cinfo->process == JPROC_PROGRESSIVE) { + /* Progressive mode: only DC or only AC tables are used in one scan */ + if (cinfo->Ss == 0) { + if (cinfo->Ah == 0) /* DC needs no table for refinement scan */ + emit_dht(cinfo, compptr->dc_tbl_no, FALSE); + } else { + emit_dht(cinfo, compptr->ac_tbl_no, TRUE); + } + } else if (cinfo->process == JPROC_LOSSLESS) { + /* Lossless mode: only DC tables are used */ + emit_dht(cinfo, compptr->dc_tbl_no, FALSE); + } else { + /* Sequential mode: need both DC and AC tables */ + emit_dht(cinfo, compptr->dc_tbl_no, FALSE); + emit_dht(cinfo, compptr->ac_tbl_no, TRUE); + } + } + } + + /* Emit DRI if required --- note that DRI value could change for each scan. + * We avoid wasting space with unnecessary DRIs, however. + */ + if (cinfo->restart_interval != marker->last_restart_interval) { + emit_dri(cinfo); + marker->last_restart_interval = cinfo->restart_interval; + } + + emit_sos(cinfo); +} + + +/* + * Write datastream trailer. + */ + +METHODDEF(void) +write_file_trailer (j_compress_ptr cinfo) +{ + emit_marker(cinfo, M_EOI); +} + + +/* + * Write an abbreviated table-specification datastream. + * This consists of SOI, DQT and DHT tables, and EOI. + * Any table that is defined and not marked sent_table = TRUE will be + * emitted. Note that all tables will be marked sent_table = TRUE at exit. + */ + +METHODDEF(void) +write_tables_only (j_compress_ptr cinfo) +{ + int i; + + emit_marker(cinfo, M_SOI); + + for (i = 0; i < NUM_QUANT_TBLS; i++) { + if (cinfo->quant_tbl_ptrs[i] != NULL) + (void) emit_dqt(cinfo, i); + } + + if (! cinfo->arith_code) { + for (i = 0; i < NUM_HUFF_TBLS; i++) { + if (cinfo->dc_huff_tbl_ptrs[i] != NULL) + emit_dht(cinfo, i, FALSE); + if (cinfo->ac_huff_tbl_ptrs[i] != NULL) + emit_dht(cinfo, i, TRUE); + } + } + + emit_marker(cinfo, M_EOI); +} + + +/* + * Initialize the marker writer module. + */ + +GLOBAL(void) +jinit_marker_writer (j_compress_ptr cinfo) +{ + my_marker_ptr marker; + + /* Create the subobject */ + marker = (my_marker_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_marker_writer)); + cinfo->marker = (struct jpeg_marker_writer *) marker; + /* Initialize method pointers */ + marker->pub.write_file_header = write_file_header; + marker->pub.write_frame_header = write_frame_header; + marker->pub.write_scan_header = write_scan_header; + marker->pub.write_file_trailer = write_file_trailer; + marker->pub.write_tables_only = write_tables_only; + marker->pub.write_marker_header = write_marker_header; + marker->pub.write_marker_byte = write_marker_byte; + /* Initialize private state */ + marker->last_restart_interval = 0; +} diff --git a/dcmjpeg/libijg8/jcmaster.c b/dcmjpeg/libijg8/jcmaster.c new file mode 100644 index 00000000..a1bf1b16 --- /dev/null +++ b/dcmjpeg/libijg8/jcmaster.c @@ -0,0 +1,657 @@ +/* + * jcmaster.c + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains master control logic for the JPEG compressor. + * These routines are concerned with parameter validation, initial setup, + * and inter-pass control (determining the number of passes and the work + * to be done in each pass). + */ + +#define JPEG_INTERNALS +#include "jinclude8.h" +#include "jpeglib8.h" +#include "jlossy8.h" /* Private declarations for lossy codec */ + + +/* Private state */ + +typedef enum { + main_pass, /* input data, also do first output step */ + huff_opt_pass, /* Huffman code optimization pass */ + output_pass /* data output pass */ +} c_pass_type; + +typedef struct { + struct jpeg_comp_master pub; /* public fields */ + + c_pass_type pass_type; /* the type of the current pass */ + + int pass_number; /* # of passes completed */ + int total_passes; /* total # of passes needed */ + + int scan_number; /* current index in scan_info[] */ +} my_comp_master; + +typedef my_comp_master * my_master_ptr; + + +/* + * Support routines that do various essential calculations. + */ + +LOCAL(void) +initial_setup (j_compress_ptr cinfo) +/* Do computations that are needed before master selection phase */ +{ + int ci; + jpeg_component_info *compptr; + long samplesperrow; + JDIMENSION jd_samplesperrow; + int data_unit = cinfo->data_unit; + + /* Sanity check on image dimensions */ + if (cinfo->image_height <= 0 || cinfo->image_width <= 0 + || cinfo->num_components <= 0 || cinfo->input_components <= 0) + ERREXIT(cinfo, JERR_EMPTY_IMAGE); + + /* Make sure image isn't bigger than I can handle */ + if ((long) cinfo->image_height > (long) JPEG_MAX_DIMENSION || + (long) cinfo->image_width > (long) JPEG_MAX_DIMENSION) + ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, (unsigned int) JPEG_MAX_DIMENSION); + + /* Width of an input scanline must be representable as JDIMENSION. */ + samplesperrow = (long) cinfo->image_width * (long) cinfo->input_components; + jd_samplesperrow = (JDIMENSION) samplesperrow; + if ((long) jd_samplesperrow != samplesperrow) + ERREXIT(cinfo, JERR_WIDTH_OVERFLOW); + + /* For now, precision must match compiled-in value... */ + if (cinfo->data_precision != BITS_IN_JSAMPLE) + ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); + + /* Check that number of components won't exceed internal array sizes */ + if (cinfo->num_components > MAX_COMPONENTS) + ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components, + MAX_COMPONENTS); + + /* Compute maximum sampling factors; check factor validity */ + cinfo->max_h_samp_factor = 1; + cinfo->max_v_samp_factor = 1; + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + if (compptr->h_samp_factor<=0 || compptr->h_samp_factor>MAX_SAMP_FACTOR || + compptr->v_samp_factor<=0 || compptr->v_samp_factor>MAX_SAMP_FACTOR) + ERREXIT(cinfo, JERR_BAD_SAMPLING); + cinfo->max_h_samp_factor = MAX(cinfo->max_h_samp_factor, + compptr->h_samp_factor); + cinfo->max_v_samp_factor = MAX(cinfo->max_v_samp_factor, + compptr->v_samp_factor); + } + + /* Compute dimensions of components */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + /* Fill in the correct component_index value; don't rely on application */ + compptr->component_index = ci; + /* For compression, we never do any codec-based processing. */ + compptr->codec_data_unit = data_unit; + /* Size in data units */ + compptr->width_in_data_units = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor, + (long) (cinfo->max_h_samp_factor * data_unit)); + compptr->height_in_data_units = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor, + (long) (cinfo->max_v_samp_factor * data_unit)); + /* Size in samples */ + compptr->downsampled_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor, + (long) cinfo->max_h_samp_factor); + compptr->downsampled_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor, + (long) cinfo->max_v_samp_factor); + /* Mark component needed (this flag isn't actually used for compression) */ + compptr->component_needed = TRUE; + } + + /* Compute number of fully interleaved MCU rows (number of times that + * main controller will call coefficient controller). + */ + cinfo->total_iMCU_rows = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height, + (long) (cinfo->max_v_samp_factor*data_unit)); +} + +#ifdef C_MULTISCAN_FILES_SUPPORTED +#define NEED_SCAN_SCRIPT +#else +#ifdef C_LOSSLESS_SUPPORTED +#define NEED_SCAN_SCRIPT +#endif +#endif + +#ifdef NEED_SCAN_SCRIPT + +LOCAL(void) +validate_script (j_compress_ptr cinfo) +/* Verify that the scan script in cinfo->scan_info[] is valid; also + * determine whether it uses progressive JPEG, and set cinfo->process. + */ +{ + const jpeg_scan_info * scanptr; + int scanno, ncomps, ci, coefi, thisi; + int Ss, Se, Ah, Al; + boolean component_sent[MAX_COMPONENTS]; +#ifdef C_PROGRESSIVE_SUPPORTED + int * last_bitpos_ptr; + int last_bitpos[MAX_COMPONENTS][DCTSIZE2]; + /* -1 until that coefficient has been seen; then last Al for it */ +#endif + + if (cinfo->num_scans <= 0) + ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, 0); + +#ifndef C_MULTISCAN_FILES_SUPPORTED + if (cinfo->num_scans > 1) + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + + scanptr = cinfo->scan_info; + if (cinfo->lossless) { +#ifdef C_LOSSLESS_SUPPORTED + cinfo->process = JPROC_LOSSLESS; + for (ci = 0; ci < cinfo->num_components; ci++) + component_sent[ci] = FALSE; +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } + /* For sequential JPEG, all scans must have Ss=0, Se=DCTSIZE2-1; + * for progressive JPEG, no scan can have this. + */ + else if (scanptr->Ss != 0 || scanptr->Se != DCTSIZE2-1) { +#ifdef C_PROGRESSIVE_SUPPORTED + cinfo->process = JPROC_PROGRESSIVE; + last_bitpos_ptr = & last_bitpos[0][0]; + for (ci = 0; ci < cinfo->num_components; ci++) + for (coefi = 0; coefi < DCTSIZE2; coefi++) + *last_bitpos_ptr++ = -1; +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } else { + cinfo->process = JPROC_SEQUENTIAL; + for (ci = 0; ci < cinfo->num_components; ci++) + component_sent[ci] = FALSE; + } + + for (scanno = 1; scanno <= cinfo->num_scans; scanptr++, scanno++) { + /* Validate component indexes */ + ncomps = scanptr->comps_in_scan; + if (ncomps <= 0 || ncomps > MAX_COMPS_IN_SCAN) + ERREXIT2(cinfo, JERR_COMPONENT_COUNT, ncomps, MAX_COMPS_IN_SCAN); + for (ci = 0; ci < ncomps; ci++) { + thisi = scanptr->component_index[ci]; + if (thisi < 0 || thisi >= cinfo->num_components) + ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, scanno); + /* Components must appear in SOF order within each scan */ + if (ci > 0 && thisi <= scanptr->component_index[ci-1]) + ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, scanno); + } + /* Validate progression parameters */ + Ss = scanptr->Ss; + Se = scanptr->Se; + Ah = scanptr->Ah; + Al = scanptr->Al; + if (cinfo->process == JPROC_LOSSLESS) { +#ifdef C_LOSSLESS_SUPPORTED + /* The JPEG spec simply gives the range 0..15 for Al (Pt), but that + * seems wrong: the upper bound ought to depend on data precision. + * Perhaps they really meant 0..N-1 for N-bit precision, which is what + * we allow here. + */ + if (Ss < 1 || Ss > 7 || /* predictor selector */ + Se != 0 || Ah != 0 || + Al < 0 || Al >= cinfo->data_precision) /* point transform */ + ERREXIT1(cinfo, JERR_BAD_LOSSLESS_SCRIPT, scanno); + /* Make sure components are not sent twice */ + for (ci = 0; ci < ncomps; ci++) { + thisi = scanptr->component_index[ci]; + if (component_sent[thisi]) + ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, scanno); + component_sent[thisi] = TRUE; + } +#endif + } else if (cinfo->process == JPROC_PROGRESSIVE) { +#ifdef C_PROGRESSIVE_SUPPORTED + /* The JPEG spec simply gives the ranges 0..13 for Ah and Al, but that + * seems wrong: the upper bound ought to depend on data precision. + * Perhaps they really meant 0..N+1 for N-bit precision. + * Here we allow 0..10 for 8-bit data; Al larger than 10 results in + * out-of-range reconstructed DC values during the first DC scan, + * which might cause problems for some decoders. + */ +#if BITS_IN_JSAMPLE == 8 +#define MAX_AH_AL 10 +#else +#define MAX_AH_AL 13 +#endif + if (Ss < 0 || Ss >= DCTSIZE2 || Se < Ss || Se >= DCTSIZE2 || + Ah < 0 || Ah > MAX_AH_AL || Al < 0 || Al > MAX_AH_AL) + ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); + if (Ss == 0) { + if (Se != 0) /* DC and AC together not OK */ + ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); + } else { + if (ncomps != 1) /* AC scans must be for only one component */ + ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); + } + for (ci = 0; ci < ncomps; ci++) { + last_bitpos_ptr = & last_bitpos[scanptr->component_index[ci]][0]; + if (Ss != 0 && last_bitpos_ptr[0] < 0) /* AC without prior DC scan */ + ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); + for (coefi = Ss; coefi <= Se; coefi++) { + if (last_bitpos_ptr[coefi] < 0) { + /* first scan of this coefficient */ + if (Ah != 0) + ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); + } else { + /* not first scan */ + if (Ah != last_bitpos_ptr[coefi] || Al != Ah-1) + ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); + } + last_bitpos_ptr[coefi] = Al; + } + } +#endif + } else { + /* For sequential JPEG, all progression parameters must be these: */ + if (Ss != 0 || Se != DCTSIZE2-1 || Ah != 0 || Al != 0) + ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); + /* Make sure components are not sent twice */ + for (ci = 0; ci < ncomps; ci++) { + thisi = scanptr->component_index[ci]; + if (component_sent[thisi]) + ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, scanno); + component_sent[thisi] = TRUE; + } + } + } + + /* Now verify that everything got sent. */ + if (cinfo->process == JPROC_PROGRESSIVE) { +#ifdef C_PROGRESSIVE_SUPPORTED + /* For progressive mode, we only check that at least some DC data + * got sent for each component; the spec does not require that all bits + * of all coefficients be transmitted. Would it be wiser to enforce + * transmission of all coefficient bits?? + */ + for (ci = 0; ci < cinfo->num_components; ci++) { + if (last_bitpos[ci][0] < 0) + ERREXIT(cinfo, JERR_MISSING_DATA); + } +#endif + } else { + for (ci = 0; ci < cinfo->num_components; ci++) { + if (! component_sent[ci]) + ERREXIT(cinfo, JERR_MISSING_DATA); + } + } +} + +#endif /* NEED_SCAN_SCRIPT */ + + +LOCAL(void) +select_scan_parameters (j_compress_ptr cinfo) +/* Set up the scan parameters for the current scan */ +{ + int ci; + +#ifdef NEED_SCAN_SCRIPT + if (cinfo->scan_info != NULL) { + /* Prepare for current scan --- the script is already validated */ + my_master_ptr master = (my_master_ptr) cinfo->master; + const jpeg_scan_info * scanptr = cinfo->scan_info + master->scan_number; + + cinfo->comps_in_scan = scanptr->comps_in_scan; + for (ci = 0; ci < scanptr->comps_in_scan; ci++) { + cinfo->cur_comp_info[ci] = + &cinfo->comp_info[scanptr->component_index[ci]]; + } + cinfo->Ss = scanptr->Ss; + cinfo->Se = scanptr->Se; + cinfo->Ah = scanptr->Ah; + cinfo->Al = scanptr->Al; + } else +#endif + { + /* Prepare for single sequential-JPEG scan containing all components */ + if (cinfo->num_components > MAX_COMPS_IN_SCAN) + ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components, + MAX_COMPS_IN_SCAN); + cinfo->comps_in_scan = cinfo->num_components; + for (ci = 0; ci < cinfo->num_components; ci++) { + cinfo->cur_comp_info[ci] = &cinfo->comp_info[ci]; + } + if (cinfo->lossless) { +#ifdef C_LOSSLESS_SUPPORTED + /* If we fall through to here, the user specified lossless, but did not + * provide a scan script. + */ + ERREXIT(cinfo, JERR_NO_LOSSLESS_SCRIPT); +#endif + } else { + cinfo->process = JPROC_SEQUENTIAL; + cinfo->Ss = 0; + cinfo->Se = DCTSIZE2-1; + cinfo->Ah = 0; + cinfo->Al = 0; + } + } +} + + +LOCAL(void) +per_scan_setup (j_compress_ptr cinfo) +/* Do computations that are needed before processing a JPEG scan */ +/* cinfo->comps_in_scan and cinfo->cur_comp_info[] are already set */ +{ + int ci, mcublks, tmp; + jpeg_component_info *compptr; + int data_unit = cinfo->data_unit; + + if (cinfo->comps_in_scan == 1) { + + /* Noninterleaved (single-component) scan */ + compptr = cinfo->cur_comp_info[0]; + + /* Overall image size in MCUs */ + cinfo->MCUs_per_row = compptr->width_in_data_units; + cinfo->MCU_rows_in_scan = compptr->height_in_data_units; + + /* For noninterleaved scan, always one block per MCU */ + compptr->MCU_width = 1; + compptr->MCU_height = 1; + compptr->MCU_data_units = 1; + compptr->MCU_sample_width = data_unit; + compptr->last_col_width = 1; + /* For noninterleaved scans, it is convenient to define last_row_height + * as the number of block rows present in the last iMCU row. + */ + tmp = (int)compptr->height_in_data_units % compptr->v_samp_factor; + if (tmp == 0) tmp = compptr->v_samp_factor; + compptr->last_row_height = tmp; + + /* Prepare array describing MCU composition */ + cinfo->data_units_in_MCU = 1; + cinfo->MCU_membership[0] = 0; + + } else { + + /* Interleaved (multi-component) scan */ + if (cinfo->comps_in_scan <= 0 || cinfo->comps_in_scan > MAX_COMPS_IN_SCAN) + ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->comps_in_scan, + MAX_COMPS_IN_SCAN); + + /* Overall image size in MCUs */ + cinfo->MCUs_per_row = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width, + (long) (cinfo->max_h_samp_factor*data_unit)); + cinfo->MCU_rows_in_scan = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height, + (long) (cinfo->max_v_samp_factor*data_unit)); + + cinfo->data_units_in_MCU = 0; + + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + /* Sampling factors give # of blocks of component in each MCU */ + compptr->MCU_width = compptr->h_samp_factor; + compptr->MCU_height = compptr->v_samp_factor; + compptr->MCU_data_units = compptr->MCU_width * compptr->MCU_height; + compptr->MCU_sample_width = compptr->MCU_width * data_unit; + /* Figure number of non-dummy blocks in last MCU column & row */ + tmp = (int)compptr->width_in_data_units % compptr->MCU_width; + if (tmp == 0) tmp = compptr->MCU_width; + compptr->last_col_width = tmp; + tmp = (int)compptr->height_in_data_units % compptr->MCU_height; + if (tmp == 0) tmp = compptr->MCU_height; + compptr->last_row_height = tmp; + /* Prepare array describing MCU composition */ + mcublks = compptr->MCU_data_units; + if (cinfo->data_units_in_MCU + mcublks > C_MAX_DATA_UNITS_IN_MCU) + ERREXIT(cinfo, JERR_BAD_MCU_SIZE); + while (mcublks-- > 0) { + cinfo->MCU_membership[cinfo->data_units_in_MCU++] = ci; + } + } + + } + + /* Convert restart specified in rows to actual MCU count. */ + /* Note that count must fit in 16 bits, so we provide limiting. */ + if (cinfo->restart_in_rows > 0) { + long nominal = (long) cinfo->restart_in_rows * (long) cinfo->MCUs_per_row; + cinfo->restart_interval = (unsigned int) MIN(nominal, 65535L); + } +} + + +/* + * Per-pass setup. + * This is called at the beginning of each pass. We determine which modules + * will be active during this pass and give them appropriate start_pass calls. + * We also set is_last_pass to indicate whether any more passes will be + * required. + */ + +METHODDEF(void) +prepare_for_pass (j_compress_ptr cinfo) +{ + /* j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; */ + my_master_ptr master = (my_master_ptr) cinfo->master; + + switch (master->pass_type) { + case main_pass: + /* Initial pass: will collect input data, and do either Huffman + * optimization or data output for the first scan. + */ + select_scan_parameters(cinfo); + per_scan_setup(cinfo); + if (! cinfo->raw_data_in) { + (*cinfo->cconvert->start_pass) (cinfo); + (*cinfo->downsample->start_pass) (cinfo); + (*cinfo->prep->start_pass) (cinfo, JBUF_PASS_THRU); + } + (*cinfo->codec->entropy_start_pass) (cinfo, cinfo->optimize_coding); + (*cinfo->codec->start_pass) (cinfo, + (master->total_passes > 1 ? + JBUF_SAVE_AND_PASS : JBUF_PASS_THRU)); + (*cinfo->main->start_pass) (cinfo, JBUF_PASS_THRU); + if (cinfo->optimize_coding) { + /* No immediate data output; postpone writing frame/scan headers */ + master->pub.call_pass_startup = FALSE; + } else { + /* Will write frame/scan headers at first jpeg_write_scanlines call */ + master->pub.call_pass_startup = TRUE; + } + break; +#ifdef ENTROPY_OPT_SUPPORTED + case huff_opt_pass: + /* Do Huffman optimization for a scan after the first one. */ + select_scan_parameters(cinfo); + per_scan_setup(cinfo); +#ifdef WITH_ARITHMETIC_PATCH + if ((*cinfo->codec->need_optimization_pass) (cinfo)) { +#else + if ((*cinfo->codec->need_optimization_pass) (cinfo) || cinfo->arith_code) { +#endif + (*cinfo->codec->entropy_start_pass) (cinfo, TRUE); + (*cinfo->codec->start_pass) (cinfo, JBUF_CRANK_DEST); + master->pub.call_pass_startup = FALSE; + break; + } + /* Special case: Huffman DC refinement scans need no Huffman table + * and therefore we can skip the optimization pass for them. + */ + master->pass_type = output_pass; + master->pass_number++; + /*FALLTHROUGH*/ +#endif + case output_pass: + /* Do a data-output pass. */ + /* We need not repeat per-scan setup if prior optimization pass did it. */ + if (! cinfo->optimize_coding) { + select_scan_parameters(cinfo); + per_scan_setup(cinfo); + } + (*cinfo->codec->entropy_start_pass) (cinfo, FALSE); + (*cinfo->codec->start_pass) (cinfo, JBUF_CRANK_DEST); + /* We emit frame/scan headers now */ + if (master->scan_number == 0) + (*cinfo->marker->write_frame_header) (cinfo); + (*cinfo->marker->write_scan_header) (cinfo); + master->pub.call_pass_startup = FALSE; + break; + default: + ERREXIT(cinfo, JERR_NOT_COMPILED); + } + + master->pub.is_last_pass = (master->pass_number == master->total_passes-1); + + /* Set up progress monitor's pass info if present */ + if (cinfo->progress != NULL) { + cinfo->progress->completed_passes = master->pass_number; + cinfo->progress->total_passes = master->total_passes; + } +} + + +/* + * Special start-of-pass hook. + * This is called by jpeg_write_scanlines if call_pass_startup is TRUE. + * In single-pass processing, we need this hook because we don't want to + * write frame/scan headers during jpeg_start_compress; we want to let the + * application write COM markers etc. between jpeg_start_compress and the + * jpeg_write_scanlines loop. + * In multi-pass processing, this routine is not used. + */ + +METHODDEF(void) +pass_startup (j_compress_ptr cinfo) +{ + cinfo->master->call_pass_startup = FALSE; /* reset flag so call only once */ + + (*cinfo->marker->write_frame_header) (cinfo); + (*cinfo->marker->write_scan_header) (cinfo); +} + + +/* + * Finish up at end of pass. + */ + +METHODDEF(void) +finish_pass_master (j_compress_ptr cinfo) +{ + j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; + my_master_ptr master = (my_master_ptr) cinfo->master; + + /* The entropy coder always needs an end-of-pass call, + * either to analyze statistics or to flush its output buffer. + */ + (*lossyc->pub.entropy_finish_pass) (cinfo); + + /* Update state for next pass */ + switch (master->pass_type) { + case main_pass: + /* next pass is either output of scan 0 (after optimization) + * or output of scan 1 (if no optimization). + */ + master->pass_type = output_pass; + if (! cinfo->optimize_coding) + master->scan_number++; + break; + case huff_opt_pass: + /* next pass is always output of current scan */ + master->pass_type = output_pass; + break; + case output_pass: + /* next pass is either optimization or output of next scan */ + if (cinfo->optimize_coding) + master->pass_type = huff_opt_pass; + master->scan_number++; + break; + } + + master->pass_number++; +} + + +/* + * Initialize master compression control. + */ + +GLOBAL(void) +jinit_c_master_control (j_compress_ptr cinfo, boolean transcode_only) +{ + my_master_ptr master; + + master = (my_master_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_comp_master)); + cinfo->master = (struct jpeg_comp_master *) master; + master->pub.prepare_for_pass = prepare_for_pass; + master->pub.pass_startup = pass_startup; + master->pub.finish_pass = finish_pass_master; + master->pub.is_last_pass = FALSE; + + cinfo->data_unit = cinfo->lossless ? 1 : DCTSIZE; + + /* Validate parameters, determine derived values */ + initial_setup(cinfo); + + if (cinfo->scan_info != NULL) { +#ifdef NEED_SCAN_SCRIPT + validate_script(cinfo); +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } else { + cinfo->process = JPROC_SEQUENTIAL; + cinfo->num_scans = 1; + } + +#ifdef WITH_ARITHMETIC_PATCH + if ((cinfo->arith_code == 0) && + (cinfo->process == JPROC_PROGRESSIVE || /* TEMPORARY HACK ??? */ + cinfo->process == JPROC_LOSSLESS)) +#else + if (cinfo->process == JPROC_PROGRESSIVE || /* TEMPORARY HACK ??? */ + cinfo->process == JPROC_LOSSLESS) +#endif + cinfo->optimize_coding = TRUE; /* assume default tables no good for + * progressive mode or lossless mode */ + + /* Initialize my private state */ + if (transcode_only) { + /* no main pass in transcoding */ + if (cinfo->optimize_coding) + master->pass_type = huff_opt_pass; + else + master->pass_type = output_pass; + } else { + /* for normal compression, first pass is always this type: */ + master->pass_type = main_pass; + } + master->scan_number = 0; + master->pass_number = 0; + if (cinfo->optimize_coding) + master->total_passes = cinfo->num_scans * 2; + else + master->total_passes = cinfo->num_scans; +} diff --git a/dcmjpeg/libijg8/jcodec.c b/dcmjpeg/libijg8/jcodec.c new file mode 100644 index 00000000..be0069d5 --- /dev/null +++ b/dcmjpeg/libijg8/jcodec.c @@ -0,0 +1,53 @@ +/* + * jcodec.c + * + * Copyright (C) 1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains utility functions for the JPEG codec(s). + */ + +#define JPEG_INTERNALS +#include "jinclude8.h" +#include "jpeglib8.h" +#include "jlossy8.h" +#include "jlossls8.h" + + +/* + * Initialize the compression codec. + * This is called only once, during master selection. + */ + +GLOBAL(void) +jinit_c_codec (j_compress_ptr cinfo) +{ + if (cinfo->process == JPROC_LOSSLESS) { +#ifdef C_LOSSLESS_SUPPORTED + jinit_lossless_c_codec(cinfo); +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } else + jinit_lossy_c_codec(cinfo); +} + + +/* + * Initialize the decompression codec. + * This is called only once, during master selection. + */ + +GLOBAL(void) +jinit_d_codec (j_decompress_ptr cinfo) +{ + if (cinfo->process == JPROC_LOSSLESS) { +#ifdef D_LOSSLESS_SUPPORTED + jinit_lossless_d_codec(cinfo); +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } else + jinit_lossy_d_codec(cinfo); +} diff --git a/dcmjpeg/libijg8/jcomapi.c b/dcmjpeg/libijg8/jcomapi.c new file mode 100644 index 00000000..c86bda49 --- /dev/null +++ b/dcmjpeg/libijg8/jcomapi.c @@ -0,0 +1,106 @@ +/* + * jcomapi.c + * + * Copyright (C) 1994-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains application interface routines that are used for both + * compression and decompression. + */ + +#define JPEG_INTERNALS +#include "jinclude8.h" +#include "jpeglib8.h" + + +/* + * Abort processing of a JPEG compression or decompression operation, + * but don't destroy the object itself. + * + * For this, we merely clean up all the nonpermanent memory pools. + * Note that temp files (virtual arrays) are not allowed to belong to + * the permanent pool, so we will be able to close all temp files here. + * Closing a data source or destination, if necessary, is the application's + * responsibility. + */ + +GLOBAL(void) +jpeg_abort (j_common_ptr cinfo) +{ + int pool; + + /* Do nothing if called on a not-initialized or destroyed JPEG object. */ + if (cinfo->mem == NULL) + return; + + /* Releasing pools in reverse order might help avoid fragmentation + * with some (brain-damaged) malloc libraries. + */ + for (pool = JPOOL_NUMPOOLS-1; pool > JPOOL_PERMANENT; pool--) { + (*cinfo->mem->free_pool) (cinfo, pool); + } + + /* Reset overall state for possible reuse of object */ + if (cinfo->is_decompressor) { + cinfo->global_state = DSTATE_START; + /* Try to keep application from accessing now-deleted marker list. + * A bit kludgy to do it here, but this is the most central place. + */ + ((j_decompress_ptr) cinfo)->marker_list = NULL; + } else { + cinfo->global_state = CSTATE_START; + } +} + + +/* + * Destruction of a JPEG object. + * + * Everything gets deallocated except the master jpeg_compress_struct itself + * and the error manager struct. Both of these are supplied by the application + * and must be freed, if necessary, by the application. (Often they are on + * the stack and so don't need to be freed anyway.) + * Closing a data source or destination, if necessary, is the application's + * responsibility. + */ + +GLOBAL(void) +jpeg_destroy (j_common_ptr cinfo) +{ + /* We need only tell the memory manager to release everything. */ + /* NB: mem pointer is NULL if memory mgr failed to initialize. */ + if (cinfo->mem != NULL) + (*cinfo->mem->self_destruct) (cinfo); + cinfo->mem = NULL; /* be safe if jpeg_destroy is called twice */ + cinfo->global_state = 0; /* mark it destroyed */ +} + + +/* + * Convenience routines for allocating quantization and Huffman tables. + * (Would jutils.c be a more reasonable place to put these?) + */ + +GLOBAL(JQUANT_TBL *) +jpeg_alloc_quant_table (j_common_ptr cinfo) +{ + JQUANT_TBL *tbl; + + tbl = (JQUANT_TBL *) + (*cinfo->mem->alloc_small) (cinfo, JPOOL_PERMANENT, SIZEOF(JQUANT_TBL)); + tbl->sent_table = FALSE; /* make sure this is false in any new table */ + return tbl; +} + + +GLOBAL(JHUFF_TBL *) +jpeg_alloc_huff_table (j_common_ptr cinfo) +{ + JHUFF_TBL *tbl; + + tbl = (JHUFF_TBL *) + (*cinfo->mem->alloc_small) (cinfo, JPOOL_PERMANENT, SIZEOF(JHUFF_TBL)); + tbl->sent_table = FALSE; /* make sure this is false in any new table */ + return tbl; +} diff --git a/dcmjpeg/libijg8/jconfig8.h b/dcmjpeg/libijg8/jconfig8.h new file mode 100644 index 00000000..4dd87d61 --- /dev/null +++ b/dcmjpeg/libijg8/jconfig8.h @@ -0,0 +1,73 @@ +/* + * + * Copyright (C) 1998-2010, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmjpeg + * + * Author: Marco Eichelberg + * + * Purpose: + * this file derives the preprocessor symbols required to compile + * the IJG library from the central DCMTK configuration file osconfig.h + * + */ + +#include "dcmtk/config/osconfig.h" + +/* We assume ANSI C and don't support DOS, + * so the following settings need not be tested + */ +#define HAVE_PROTOTYPES +#define HAVE_UNSIGNED_CHAR +#define HAVE_UNSIGNED_SHORT +#undef NEED_FAR_POINTERS +#undef INCOMPLETE_TYPES_BROKEN + +/* the following settings are derived from osconfig.h */ + +#ifndef HAVE_C_CONST +#define const +#endif + +#ifdef C_CHAR_UNSIGNED +#define CHAR_IS_UNSIGNED +#endif + +#ifdef HAVE_STRINGS_H +#ifndef HAVE_STRING_H +#define NEED_BSD_STRINGS +#endif +#endif + +#ifdef HAVE_SYS_TYPES_H +#define NEED_SYS_TYPES_H +#endif + +/* must always be defined for our implementation */ +#define NEED_SHORT_EXTERNAL_NAMES + +#ifdef JPEG_INTERNALS + +#ifdef C_RIGHTSHIFT_UNSIGNED +#define RIGHT_SHIFT_IS_UNSIGNED +#endif + +#define INLINE C_INLINE + +/* These are for configuring the JPEG memory manager. */ +#undef DEFAULT_MAX_MEM +#undef NO_MKTEMP + +/* We don't want to use getenv which is thread unsafe on some platforms */ +#define NO_GETENV + +#endif /* JPEG_INTERNALS */ diff --git a/dcmjpeg/libijg8/jcparam.c b/dcmjpeg/libijg8/jcparam.c new file mode 100644 index 00000000..d1279d0b --- /dev/null +++ b/dcmjpeg/libijg8/jcparam.c @@ -0,0 +1,687 @@ +/* + * jcparam.c + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains optional default-setting code for the JPEG compressor. + * Applications do not have to use this file, but those that don't use it + * must know a lot more about the innards of the JPEG code. + */ + +#define JPEG_INTERNALS +#include "jinclude8.h" +#include "jpeglib8.h" + + +/* + * Quantization table setup routines + */ + +GLOBAL(void) +jpeg_add_quant_table (j_compress_ptr cinfo, int which_tbl, + const unsigned int *basic_table, + int scale_factor, boolean force_baseline) +/* Define a quantization table equal to the basic_table times + * a scale factor (given as a percentage). + * If force_baseline is TRUE, the computed quantization table entries + * are limited to 1..255 for JPEG baseline compatibility. + */ +{ + JQUANT_TBL ** qtblptr; + int i; + long temp; + + /* Safety check to ensure start_compress not called yet. */ + if (cinfo->global_state != CSTATE_START) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + + if (which_tbl < 0 || which_tbl >= NUM_QUANT_TBLS) + ERREXIT1(cinfo, JERR_DQT_INDEX, which_tbl); + + qtblptr = & cinfo->quant_tbl_ptrs[which_tbl]; + + if (*qtblptr == NULL) + *qtblptr = jpeg_alloc_quant_table((j_common_ptr) cinfo); + + for (i = 0; i < DCTSIZE2; i++) { + temp = ((long) basic_table[i] * scale_factor + 50L) / 100L; + /* limit the values to the valid range */ + if (temp <= 0L) temp = 1L; + if (temp > 32767L) temp = 32767L; /* max quantizer needed for 12 bits */ + if (force_baseline && temp > 255L) + temp = 255L; /* limit to baseline range if requested */ + (*qtblptr)->quantval[i] = (UINT16) temp; + } + + /* Initialize sent_table FALSE so table will be written to JPEG file. */ + (*qtblptr)->sent_table = FALSE; +} + + +GLOBAL(void) +jpeg_set_linear_quality (j_compress_ptr cinfo, int scale_factor, + boolean force_baseline) +/* Set or change the 'quality' (quantization) setting, using default tables + * and a straight percentage-scaling quality scale. In most cases it's better + * to use jpeg_set_quality (below); this entry point is provided for + * applications that insist on a linear percentage scaling. + */ +{ + /* These are the sample quantization tables given in JPEG spec section K.1. + * The spec says that the values given produce "good" quality, and + * when divided by 2, "very good" quality. + */ + static const unsigned int std_luminance_quant_tbl[DCTSIZE2] = { + 16, 11, 10, 16, 24, 40, 51, 61, + 12, 12, 14, 19, 26, 58, 60, 55, + 14, 13, 16, 24, 40, 57, 69, 56, + 14, 17, 22, 29, 51, 87, 80, 62, + 18, 22, 37, 56, 68, 109, 103, 77, + 24, 35, 55, 64, 81, 104, 113, 92, + 49, 64, 78, 87, 103, 121, 120, 101, + 72, 92, 95, 98, 112, 100, 103, 99 + }; + static const unsigned int std_chrominance_quant_tbl[DCTSIZE2] = { + 17, 18, 24, 47, 99, 99, 99, 99, + 18, 21, 26, 66, 99, 99, 99, 99, + 24, 26, 56, 99, 99, 99, 99, 99, + 47, 66, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99 + }; + + /* Set up two quantization tables using the specified scaling */ + jpeg_add_quant_table(cinfo, 0, std_luminance_quant_tbl, + scale_factor, force_baseline); + jpeg_add_quant_table(cinfo, 1, std_chrominance_quant_tbl, + scale_factor, force_baseline); +} + + +GLOBAL(int) +jpeg_quality_scaling (int quality) +/* Convert a user-specified quality rating to a percentage scaling factor + * for an underlying quantization table, using our recommended scaling curve. + * The input 'quality' factor should be 0 (terrible) to 100 (very good). + */ +{ + /* Safety limit on quality factor. Convert 0 to 1 to avoid zero divide. */ + if (quality <= 0) quality = 1; + if (quality > 100) quality = 100; + + /* The basic table is used as-is (scaling 100) for a quality of 50. + * Qualities 50..100 are converted to scaling percentage 200 - 2*Q; + * note that at Q=100 the scaling is 0, which will cause jpeg_add_quant_table + * to make all the table entries 1 (hence, minimum quantization loss). + * Qualities 1..50 are converted to scaling percentage 5000/Q. + */ + if (quality < 50) + quality = 5000 / quality; + else + quality = 200 - quality*2; + + return quality; +} + + +GLOBAL(void) +jpeg_set_quality (j_compress_ptr cinfo, int quality, boolean force_baseline) +/* Set or change the 'quality' (quantization) setting, using default tables. + * This is the standard quality-adjusting entry point for typical user + * interfaces; only those who want detailed control over quantization tables + * would use the preceding three routines directly. + */ +{ + /* Convert user 0-100 rating to percentage scaling */ + quality = jpeg_quality_scaling(quality); + + /* Set up standard quality tables */ + jpeg_set_linear_quality(cinfo, quality, force_baseline); +} + + +/* + * Huffman table setup routines + */ + +LOCAL(void) +add_huff_table (j_compress_ptr cinfo, + JHUFF_TBL **htblptr, const UINT8 *bits, const UINT8 *val) +/* Define a Huffman table */ +{ + int nsymbols, len; + + if (*htblptr == NULL) + *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo); + + /* Copy the number-of-symbols-of-each-code-length counts */ + MEMCOPY((*htblptr)->bits, bits, SIZEOF((*htblptr)->bits)); + + /* Validate the counts. We do this here mainly so we can copy the right + * number of symbols from the val[] array, without risking marching off + * the end of memory. jchuff.c will do a more thorough test later. + */ + nsymbols = 0; + for (len = 1; len <= 16; len++) + nsymbols += bits[len]; + if (nsymbols < 1 || nsymbols > 256) + ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); + + MEMCOPY((*htblptr)->huffval, val, (size_t)nsymbols * SIZEOF(UINT8)); + + /* Initialize sent_table FALSE so table will be written to JPEG file. */ + (*htblptr)->sent_table = FALSE; +} + + +LOCAL(void) +std_huff_tables (j_compress_ptr cinfo) +/* Set up the standard Huffman tables (cf. JPEG standard section K.3) */ +/* IMPORTANT: these are only valid for 8-bit data precision! */ +{ + static const UINT8 bits_dc_luminance[17] = + { /* 0-base */ 0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 }; + static const UINT8 val_dc_luminance[] = + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }; + + static const UINT8 bits_dc_chrominance[17] = + { /* 0-base */ 0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 }; + static const UINT8 val_dc_chrominance[] = + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }; + + static const UINT8 bits_ac_luminance[17] = + { /* 0-base */ 0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d }; + static const UINT8 val_ac_luminance[] = + { 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, + 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, + 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08, + 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0, + 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16, + 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28, + 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, + 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, + 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, + 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, + 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, + 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, + 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, + 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, + 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, + 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, + 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, + 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2, + 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, + 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, + 0xf9, 0xfa }; + + static const UINT8 bits_ac_chrominance[17] = + { /* 0-base */ 0, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77 }; + static const UINT8 val_ac_chrominance[] = + { 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, + 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71, + 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, + 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0, + 0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34, + 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26, + 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38, + 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, + 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, + 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, + 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, + 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, + 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, + 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, + 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, + 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, + 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, + 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, + 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, + 0xf9, 0xfa }; + + add_huff_table(cinfo, &cinfo->dc_huff_tbl_ptrs[0], + bits_dc_luminance, val_dc_luminance); + add_huff_table(cinfo, &cinfo->ac_huff_tbl_ptrs[0], + bits_ac_luminance, val_ac_luminance); + add_huff_table(cinfo, &cinfo->dc_huff_tbl_ptrs[1], + bits_dc_chrominance, val_dc_chrominance); + add_huff_table(cinfo, &cinfo->ac_huff_tbl_ptrs[1], + bits_ac_chrominance, val_ac_chrominance); +} + + +/* + * Default parameter setup for compression. + * + * Applications that don't choose to use this routine must do their + * own setup of all these parameters. Alternately, you can call this + * to establish defaults and then alter parameters selectively. This + * is the recommended approach since, if we add any new parameters, + * your code will still work (they'll be set to reasonable defaults). + */ + +GLOBAL(void) +jpeg_set_defaults (j_compress_ptr cinfo) +{ + int i; + + /* Safety check to ensure start_compress not called yet. */ + if (cinfo->global_state != CSTATE_START) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + + /* Allocate comp_info array large enough for maximum component count. + * Array is made permanent in case application wants to compress + * multiple images at same param settings. + */ + if (cinfo->comp_info == NULL) + cinfo->comp_info = (jpeg_component_info *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, + MAX_COMPONENTS * SIZEOF(jpeg_component_info)); + + /* Initialize everything not dependent on the color space */ + + cinfo->lossless = FALSE; + cinfo->data_precision = BITS_IN_JSAMPLE; + /* Set up two quantization tables using default quality of 75 */ + jpeg_set_quality(cinfo, 75, TRUE); + /* Set up two Huffman tables */ + std_huff_tables(cinfo); + + /* Initialize default arithmetic coding conditioning */ + for (i = 0; i < NUM_ARITH_TBLS; i++) { + cinfo->arith_dc_L[i] = 0; + cinfo->arith_dc_U[i] = 1; + cinfo->arith_ac_K[i] = 5; + } + + /* Default is no multiple-scan output */ + cinfo->scan_info = NULL; + cinfo->num_scans = 0; + + /* Expect normal source image, not raw downsampled data */ + cinfo->raw_data_in = FALSE; + + /* Use Huffman coding, not arithmetic coding, by default */ + cinfo->arith_code = FALSE; + + /* By default, don't do extra passes to optimize entropy coding */ + cinfo->optimize_coding = FALSE; + /* The standard Huffman tables are only valid for 8-bit data precision. + * If the precision is higher, force optimization on so that usable + * tables will be computed. This test can be removed if default tables + * are supplied that are valid for the desired precision. + */ + if (cinfo->data_precision > 8) + cinfo->optimize_coding = TRUE; + + /* By default, use the simpler non-cosited sampling alignment */ + cinfo->CCIR601_sampling = FALSE; + + /* No input smoothing */ + cinfo->smoothing_factor = 0; + + /* DCT algorithm preference */ + cinfo->dct_method = JDCT_DEFAULT; + + /* No restart markers */ + cinfo->restart_interval = 0; + cinfo->restart_in_rows = 0; + + /* Fill in default JFIF marker parameters. Note that whether the marker + * will actually be written is determined by jpeg_set_colorspace. + * + * By default, the library emits JFIF version code 1.01. + * An application that wants to emit JFIF 1.02 extension markers should set + * JFIF_minor_version to 2. We could probably get away with just defaulting + * to 1.02, but there may still be some decoders in use that will complain + * about that; saying 1.01 should minimize compatibility problems. + */ + cinfo->JFIF_major_version = 1; /* Default JFIF version = 1.01 */ + cinfo->JFIF_minor_version = 1; + cinfo->density_unit = 0; /* Pixel size is unknown by default */ + cinfo->X_density = 1; /* Pixel aspect ratio is square by default */ + cinfo->Y_density = 1; + + /* Choose JPEG colorspace based on input space, set defaults accordingly */ + + jpeg_default_colorspace(cinfo); +} + + +/* + * Select an appropriate JPEG colorspace for in_color_space. + */ + +GLOBAL(void) +jpeg_default_colorspace (j_compress_ptr cinfo) +{ + if (cinfo->lossless) + jpeg_set_colorspace(cinfo, cinfo->in_color_space); + else { /* lossy */ + switch (cinfo->in_color_space) { + case JCS_GRAYSCALE: + jpeg_set_colorspace(cinfo, JCS_GRAYSCALE); + break; + case JCS_RGB: + jpeg_set_colorspace(cinfo, JCS_YCbCr); + break; + case JCS_YCbCr: + jpeg_set_colorspace(cinfo, JCS_YCbCr); + break; + case JCS_CMYK: + jpeg_set_colorspace(cinfo, JCS_CMYK); /* By default, no translation */ + break; + case JCS_YCCK: + jpeg_set_colorspace(cinfo, JCS_YCCK); + break; + case JCS_UNKNOWN: + jpeg_set_colorspace(cinfo, JCS_UNKNOWN); + break; + default: + ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); + } + } +} + + +/* + * Set the JPEG colorspace, and choose colorspace-dependent default values. + */ + +GLOBAL(void) +jpeg_set_colorspace (j_compress_ptr cinfo, J_COLOR_SPACE colorspace) +{ + jpeg_component_info * compptr; + int ci; + +#define SET_COMP(index,id,hsamp,vsamp,quant,dctbl,actbl) \ + (compptr = &cinfo->comp_info[index], \ + compptr->component_id = (id), \ + compptr->h_samp_factor = (hsamp), \ + compptr->v_samp_factor = (vsamp), \ + compptr->quant_tbl_no = (quant), \ + compptr->dc_tbl_no = (dctbl), \ + compptr->ac_tbl_no = (actbl) ) + + /* Safety check to ensure start_compress not called yet. */ + if (cinfo->global_state != CSTATE_START) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + + /* For all colorspaces, we use Q and Huff tables 0 for luminance components, + * tables 1 for chrominance components. + */ + + cinfo->jpeg_color_space = colorspace; + + cinfo->write_JFIF_header = FALSE; /* No marker for non-JFIF colorspaces */ + cinfo->write_Adobe_marker = FALSE; /* write no Adobe marker by default */ + + switch (colorspace) { + case JCS_GRAYSCALE: + cinfo->write_JFIF_header = TRUE; /* Write a JFIF marker */ + cinfo->num_components = 1; + /* JFIF specifies component ID 1 */ + SET_COMP(0, 1, 1,1, 0, 0,0); + break; + case JCS_RGB: + cinfo->write_Adobe_marker = TRUE; /* write Adobe marker to flag RGB */ + cinfo->num_components = 3; + SET_COMP(0, 0x52 /* 'R' */, 1,1, 0, 0,0); + SET_COMP(1, 0x47 /* 'G' */, 1,1, 0, 0,0); + SET_COMP(2, 0x42 /* 'B' */, 1,1, 0, 0,0); + break; + case JCS_YCbCr: + cinfo->write_JFIF_header = TRUE; /* Write a JFIF marker */ + cinfo->num_components = 3; + /* JFIF specifies component IDs 1,2,3 */ + if (cinfo->lossless) { + SET_COMP(0, 1, 1,1, 0, 0,0); + SET_COMP(1, 2, 1,1, 1, 1,1); + SET_COMP(2, 3, 1,1, 1, 1,1); + } else { /* lossy */ + /* We default to 2x2 subsamples of chrominance */ + SET_COMP(0, 1, 2,2, 0, 0,0); + SET_COMP(1, 2, 1,1, 1, 1,1); + SET_COMP(2, 3, 1,1, 1, 1,1); + } + break; + case JCS_CMYK: + cinfo->write_Adobe_marker = TRUE; /* write Adobe marker to flag CMYK */ + cinfo->num_components = 4; + SET_COMP(0, 0x43 /* 'C' */, 1,1, 0, 0,0); + SET_COMP(1, 0x4D /* 'M' */, 1,1, 0, 0,0); + SET_COMP(2, 0x59 /* 'Y' */, 1,1, 0, 0,0); + SET_COMP(3, 0x4B /* 'K' */, 1,1, 0, 0,0); + break; + case JCS_YCCK: + cinfo->write_Adobe_marker = TRUE; /* write Adobe marker to flag YCCK */ + cinfo->num_components = 4; + if (cinfo->lossless) { + SET_COMP(0, 1, 1,1, 0, 0,0); + SET_COMP(1, 2, 1,1, 1, 1,1); + SET_COMP(2, 3, 1,1, 1, 1,1); + SET_COMP(3, 4, 1,1, 0, 0,0); + } else { /* lossy */ + SET_COMP(0, 1, 2,2, 0, 0,0); + SET_COMP(1, 2, 1,1, 1, 1,1); + SET_COMP(2, 3, 1,1, 1, 1,1); + SET_COMP(3, 4, 2,2, 0, 0,0); + } + break; + case JCS_UNKNOWN: + cinfo->num_components = cinfo->input_components; + if (cinfo->num_components < 1 || cinfo->num_components > MAX_COMPONENTS) + ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components, + MAX_COMPONENTS); + for (ci = 0; ci < cinfo->num_components; ci++) { + SET_COMP(ci, ci, 1,1, 0, 0,0); + } + break; + default: + ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); + } +} + + +#ifdef C_PROGRESSIVE_SUPPORTED + +LOCAL(jpeg_scan_info *) +fill_scans (jpeg_scan_info * scanptr, int ncomps, + int Ss, int Se, int Ah, int Al) +/* Support routine: generate one scan for each component */ +{ + int ci; + + for (ci = 0; ci < ncomps; ci++) { + scanptr->comps_in_scan = 1; + scanptr->component_index[0] = ci; + scanptr->Ss = Ss; + scanptr->Se = Se; + scanptr->Ah = Ah; + scanptr->Al = Al; + scanptr++; + } + return scanptr; +} + + +LOCAL(jpeg_scan_info *) +fill_a_scan (jpeg_scan_info * scanptr, int ci, + int Ss, int Se, int Ah, int Al) +/* Support routine: generate one scan for specified component */ +{ + scanptr->comps_in_scan = 1; + scanptr->component_index[0] = ci; + scanptr->Ss = Ss; + scanptr->Se = Se; + scanptr->Ah = Ah; + scanptr->Al = Al; + scanptr++; + return scanptr; +} + +LOCAL(jpeg_scan_info *) +fill_dc_scans (jpeg_scan_info * scanptr, int ncomps, int Ah, int Al) +/* Support routine: generate interleaved DC scan if possible, else N scans */ +{ + int ci; + + if (ncomps <= MAX_COMPS_IN_SCAN) { + /* Single interleaved DC scan */ + scanptr->comps_in_scan = ncomps; + for (ci = 0; ci < ncomps; ci++) + scanptr->component_index[ci] = ci; + scanptr->Ss = scanptr->Se = 0; + scanptr->Ah = Ah; + scanptr->Al = Al; + scanptr++; + } else { + /* Noninterleaved DC scan for each component */ + scanptr = fill_scans(scanptr, ncomps, 0, 0, Ah, Al); + } + return scanptr; +} + + +/* + * Create a recommended progressive-JPEG script. + * cinfo->num_components and cinfo->jpeg_color_space must be correct. + */ + +GLOBAL(void) +jpeg_simple_progression (j_compress_ptr cinfo) +{ + int ncomps = cinfo->num_components; + int nscans; + jpeg_scan_info * scanptr; + + /* Safety check to ensure start_compress not called yet. */ + if (cinfo->global_state != CSTATE_START) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + + /* Figure space needed for script. Calculation must match code below! */ + if (ncomps == 3 && cinfo->jpeg_color_space == JCS_YCbCr) { + /* Custom script for YCbCr color images. */ + nscans = 10; + } else { + /* All-purpose script for other color spaces. */ + if (ncomps > MAX_COMPS_IN_SCAN) + nscans = 6 * ncomps; /* 2 DC + 4 AC scans per component */ + else + nscans = 2 + 4 * ncomps; /* 2 DC scans; 4 AC scans per component */ + } + + /* Allocate space for script. + * We need to put it in the permanent pool in case the application performs + * multiple compressions without changing the settings. To avoid a memory + * leak if jpeg_simple_progression is called repeatedly for the same JPEG + * object, we try to re-use previously allocated space, and we allocate + * enough space to handle YCbCr even if initially asked for grayscale. + */ + if (cinfo->script_space == NULL || cinfo->script_space_size < nscans) { + cinfo->script_space_size = MAX(nscans, 10); + cinfo->script_space = (jpeg_scan_info *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, + (size_t)cinfo->script_space_size * SIZEOF(jpeg_scan_info)); + } + scanptr = cinfo->script_space; + cinfo->scan_info = scanptr; + cinfo->num_scans = nscans; + + if (ncomps == 3 && cinfo->jpeg_color_space == JCS_YCbCr) { + /* Custom script for YCbCr color images. */ + /* Initial DC scan */ + scanptr = fill_dc_scans(scanptr, ncomps, 0, 1); + /* Initial AC scan: get some luma data out in a hurry */ + scanptr = fill_a_scan(scanptr, 0, 1, 5, 0, 2); + /* Chroma data is too small to be worth expending many scans on */ + scanptr = fill_a_scan(scanptr, 2, 1, 63, 0, 1); + scanptr = fill_a_scan(scanptr, 1, 1, 63, 0, 1); + /* Complete spectral selection for luma AC */ + scanptr = fill_a_scan(scanptr, 0, 6, 63, 0, 2); + /* Refine next bit of luma AC */ + scanptr = fill_a_scan(scanptr, 0, 1, 63, 2, 1); + /* Finish DC successive approximation */ + scanptr = fill_dc_scans(scanptr, ncomps, 1, 0); + /* Finish AC successive approximation */ + scanptr = fill_a_scan(scanptr, 2, 1, 63, 1, 0); + scanptr = fill_a_scan(scanptr, 1, 1, 63, 1, 0); + /* Luma bottom bit comes last since it's usually largest scan */ + scanptr = fill_a_scan(scanptr, 0, 1, 63, 1, 0); + } else { + /* All-purpose script for other color spaces. */ + /* Successive approximation first pass */ + scanptr = fill_dc_scans(scanptr, ncomps, 0, 1); + scanptr = fill_scans(scanptr, ncomps, 1, 5, 0, 2); + scanptr = fill_scans(scanptr, ncomps, 6, 63, 0, 2); + /* Successive approximation second pass */ + scanptr = fill_scans(scanptr, ncomps, 1, 63, 2, 1); + /* Successive approximation final pass */ + scanptr = fill_dc_scans(scanptr, ncomps, 1, 0); + scanptr = fill_scans(scanptr, ncomps, 1, 63, 1, 0); + } +} + +#endif /* C_PROGRESSIVE_SUPPORTED */ + + +#ifdef C_LOSSLESS_SUPPORTED + +/* + * Create a single-entry lossless-JPEG script containing all components. + * cinfo->num_components must be correct. + */ + +GLOBAL(void) +jpeg_simple_lossless (j_compress_ptr cinfo, int predictor, int point_transform) +{ + int ncomps = cinfo->num_components; + int nscans = 1; + int ci; + jpeg_scan_info * scanptr; + + /* Safety check to ensure start_compress not called yet. */ + if (cinfo->global_state != CSTATE_START) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + + cinfo->lossless = TRUE; + + /* Set jpeg_color_space. */ + jpeg_default_colorspace(cinfo); + + /* Check to ensure that all components will fit in one scan. */ + if (cinfo->num_components > MAX_COMPS_IN_SCAN) + ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components, + MAX_COMPS_IN_SCAN); + + /* Allocate space for script. + * We need to put it in the permanent pool in case the application performs + * multiple compressions without changing the settings. To avoid a memory + * leak if jpeg_simple_lossless is called repeatedly for the same JPEG + * object, we try to re-use previously allocated space. + */ + if (cinfo->script_space == NULL || cinfo->script_space_size < nscans) { + cinfo->script_space_size = nscans; + cinfo->script_space = (jpeg_scan_info *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, + (size_t)cinfo->script_space_size * SIZEOF(jpeg_scan_info)); + } + scanptr = cinfo->script_space; + cinfo->scan_info = scanptr; + cinfo->num_scans = nscans; + + /* Fill the script. */ + scanptr->comps_in_scan = ncomps; + for (ci = 0; ci < (int)ncomps; ci++) + scanptr->component_index[ci] = ci; + scanptr->Ss = predictor; + scanptr->Se = 0; + scanptr->Ah = 0; + scanptr->Al = point_transform; +} + +#endif /* C_LOSSLESS_SUPPORTED */ diff --git a/dcmjpeg/libijg8/jcphuff.c b/dcmjpeg/libijg8/jcphuff.c new file mode 100644 index 00000000..1bf2edeb --- /dev/null +++ b/dcmjpeg/libijg8/jcphuff.c @@ -0,0 +1,848 @@ +/* + * jcphuff.c + * + * Copyright (C) 1995-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains Huffman entropy encoding routines for progressive JPEG. + * + * We do not support output suspension in this module, since the library + * currently does not allow multiple-scan files to be written with output + * suspension. + */ + +#define JPEG_INTERNALS +#include "jinclude8.h" +#include "jpeglib8.h" +#include "jlossy8.h" /* Private declarations for lossy codec */ +#include "jchuff8.h" /* Declarations shared with jc*huff.c */ + +#ifdef C_PROGRESSIVE_SUPPORTED + +/* Expanded entropy encoder object for progressive Huffman encoding. */ + +typedef struct { + /* Mode flag: TRUE for optimization, FALSE for actual data output */ + boolean gather_statistics; + + /* Bit-level coding status. + * next_output_byte/free_in_buffer are local copies of cinfo->dest fields. + */ + JOCTET * next_output_byte; /* => next byte to write in buffer */ + size_t free_in_buffer; /* # of byte spaces remaining in buffer */ + IJG_INT32 put_buffer; /* current bit-accumulation buffer */ + int put_bits; /* # of bits now in it */ + j_compress_ptr cinfo; /* link to cinfo (needed for dump_buffer) */ + + /* Coding status for DC components */ + int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */ + + /* Coding status for AC components */ + int ac_tbl_no; /* the table number of the single component */ + unsigned int EOBRUN; /* run length of EOBs */ + unsigned int BE; /* # of buffered correction bits before MCU */ + char * bit_buffer; /* buffer for correction bits (1 per char) */ + /* packing correction bits tightly would save some space but cost time... */ + + unsigned int restarts_to_go; /* MCUs left in this restart interval */ + int next_restart_num; /* next restart number to write (0-7) */ + + /* Pointers to derived tables (these workspaces have image lifespan). + * Since any one scan codes only DC or only AC, we only need one set + * of tables, not one for DC and one for AC. + */ + c_derived_tbl * derived_tbls[NUM_HUFF_TBLS]; + + /* Statistics tables for optimization; again, one set is enough */ + long * count_ptrs[NUM_HUFF_TBLS]; +} phuff_entropy_encoder; + +typedef phuff_entropy_encoder * phuff_entropy_ptr; + +/* MAX_CORR_BITS is the number of bits the AC refinement correction-bit + * buffer can hold. Larger sizes may slightly improve compression, but + * 1000 is already well into the realm of overkill. + * The minimum safe size is 64 bits. + */ + +#define MAX_CORR_BITS 1000 /* Max # of correction bits I can buffer */ + +/* IRIGHT_SHIFT is like RIGHT_SHIFT, but works on int rather than IJG_INT32. + * We assume that int right shift is unsigned if IJG_INT32 right shift is, + * which should be safe. + */ + +#ifdef RIGHT_SHIFT_IS_UNSIGNED +#define ISHIFT_TEMPS int ishift_temp; +#define IRIGHT_SHIFT(x,shft) \ + ((ishift_temp = (x)) < 0 ? \ + (ishift_temp >> (shft)) | ((~0) << (16-(shft))) : \ + (ishift_temp >> (shft))) +#else +#define ISHIFT_TEMPS +#define IRIGHT_SHIFT(x,shft) ((x) >> (shft)) +#endif + +/* Forward declarations */ +METHODDEF(boolean) encode_mcu_DC_first JPP((j_compress_ptr cinfo, + JBLOCKROW *MCU_data)); +METHODDEF(boolean) encode_mcu_AC_first JPP((j_compress_ptr cinfo, + JBLOCKROW *MCU_data)); +METHODDEF(boolean) encode_mcu_DC_refine JPP((j_compress_ptr cinfo, + JBLOCKROW *MCU_data)); +METHODDEF(boolean) encode_mcu_AC_refine JPP((j_compress_ptr cinfo, + JBLOCKROW *MCU_data)); +METHODDEF(void) finish_pass_phuff JPP((j_compress_ptr cinfo)); +METHODDEF(void) finish_pass_gather_phuff JPP((j_compress_ptr cinfo)); + + +/* + * Initialize for a Huffman-compressed scan using progressive JPEG. + */ + +METHODDEF(void) +start_pass_phuff (j_compress_ptr cinfo, boolean gather_statistics) +{ + j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; + phuff_entropy_ptr entropy = (phuff_entropy_ptr) lossyc->entropy_private; + boolean is_DC_band; + int ci, tbl; + jpeg_component_info * compptr; + + entropy->cinfo = cinfo; + entropy->gather_statistics = gather_statistics; + + is_DC_band = (cinfo->Ss == 0); + + /* We assume jcmaster.c already validated the scan parameters. */ + + /* Select execution routines */ + if (cinfo->Ah == 0) { + if (is_DC_band) + lossyc->entropy_encode_mcu = encode_mcu_DC_first; + else + lossyc->entropy_encode_mcu = encode_mcu_AC_first; + } else { + if (is_DC_band) + lossyc->entropy_encode_mcu = encode_mcu_DC_refine; + else { + lossyc->entropy_encode_mcu = encode_mcu_AC_refine; + /* AC refinement needs a correction bit buffer */ + if (entropy->bit_buffer == NULL) + entropy->bit_buffer = (char *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + MAX_CORR_BITS * SIZEOF(char)); + } + } + if (gather_statistics) + lossyc->pub.entropy_finish_pass = finish_pass_gather_phuff; + else + lossyc->pub.entropy_finish_pass = finish_pass_phuff; + + /* Only DC coefficients may be interleaved, so cinfo->comps_in_scan = 1 + * for AC coefficients. + */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + /* Initialize DC predictions to 0 */ + entropy->last_dc_val[ci] = 0; + /* Get table index */ + if (is_DC_band) { + if (cinfo->Ah != 0) /* DC refinement needs no table */ + continue; + tbl = compptr->dc_tbl_no; + } else { + entropy->ac_tbl_no = tbl = compptr->ac_tbl_no; + } + if (gather_statistics) { + /* Check for invalid table index */ + /* (make_c_derived_tbl does this in the other path) */ + if (tbl < 0 || tbl >= NUM_HUFF_TBLS) + ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tbl); + /* Allocate and zero the statistics tables */ + /* Note that jpeg_gen_optimal_table expects 257 entries in each table! */ + if (entropy->count_ptrs[tbl] == NULL) + entropy->count_ptrs[tbl] = (long *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + 257 * SIZEOF(long)); + MEMZERO(entropy->count_ptrs[tbl], 257 * SIZEOF(long)); + } else { + /* Compute derived values for Huffman table */ + /* We may do this more than once for a table, but it's not expensive */ + jpeg_make_c_derived_tbl(cinfo, is_DC_band, tbl, + & entropy->derived_tbls[tbl]); + } + } + + /* Initialize AC stuff */ + entropy->EOBRUN = 0; + entropy->BE = 0; + + /* Initialize bit buffer to empty */ + entropy->put_buffer = 0; + entropy->put_bits = 0; + + /* Initialize restart stuff */ + entropy->restarts_to_go = cinfo->restart_interval; + entropy->next_restart_num = 0; +} + + +/* Outputting bytes to the file. + * NB: these must be called only when actually outputting, + * that is, entropy->gather_statistics == FALSE. + */ + +/* Emit a byte */ +#define emit_byte(entropy,val) \ + { *(entropy)->next_output_byte++ = (JOCTET) (val); \ + if (--(entropy)->free_in_buffer == 0) \ + dump_buffer(entropy); } + + +LOCAL(void) +dump_buffer (phuff_entropy_ptr entropy) +/* Empty the output buffer; we do not support suspension in this module. */ +{ + struct jpeg_destination_mgr * dest = entropy->cinfo->dest; + + if (! (*dest->empty_output_buffer) (entropy->cinfo)) + ERREXIT(entropy->cinfo, JERR_CANT_SUSPEND); + /* After a successful buffer dump, must reset buffer pointers */ + entropy->next_output_byte = dest->next_output_byte; + entropy->free_in_buffer = dest->free_in_buffer; +} + + +/* Outputting bits to the file */ + +/* Only the right 24 bits of put_buffer are used; the valid bits are + * left-justified in this part. At most 16 bits can be passed to emit_bits + * in one call, and we never retain more than 7 bits in put_buffer + * between calls, so 24 bits are sufficient. + */ + +INLINE +LOCAL(void) +emit_bits (phuff_entropy_ptr entropy, unsigned int code, int size) +/* Emit some bits, unless we are in gather mode */ +{ + /* This routine is heavily used, so it's worth coding tightly. */ + register IJG_INT32 put_buffer = (IJG_INT32) code; + register int put_bits = entropy->put_bits; + + /* if size is 0, caller used an invalid Huffman table entry */ + if (size == 0) + ERREXIT(entropy->cinfo, JERR_HUFF_MISSING_CODE); + + if (entropy->gather_statistics) + return; /* do nothing if we're only getting stats */ + + put_buffer &= (((IJG_INT32) 1)<put_buffer; /* and merge with old buffer contents */ + + while (put_bits >= 8) { + int c = (int) ((put_buffer >> 16) & 0xFF); + + emit_byte(entropy, c); + if (c == 0xFF) { /* need to stuff a zero byte? */ + emit_byte(entropy, 0); + } + put_buffer <<= 8; + put_bits -= 8; + } + + entropy->put_buffer = put_buffer; /* update variables */ + entropy->put_bits = put_bits; +} + + +LOCAL(void) +flush_bits (phuff_entropy_ptr entropy) +{ + emit_bits(entropy, 0x7F, 7); /* fill any partial byte with ones */ + entropy->put_buffer = 0; /* and reset bit-buffer to empty */ + entropy->put_bits = 0; +} + + +/* + * Emit (or just count) a Huffman symbol. + */ + +INLINE +LOCAL(void) +emit_symbol (phuff_entropy_ptr entropy, int tbl_no, int symbol) +{ + if (entropy->gather_statistics) + entropy->count_ptrs[tbl_no][symbol]++; + else { + c_derived_tbl * tbl = entropy->derived_tbls[tbl_no]; + emit_bits(entropy, tbl->ehufco[symbol], tbl->ehufsi[symbol]); + } +} + + +/* + * Emit bits from a correction bit buffer. + */ + +LOCAL(void) +emit_buffered_bits (phuff_entropy_ptr entropy, char * bufstart, + unsigned int nbits) +{ + if (entropy->gather_statistics) + return; /* no real work */ + + while (nbits > 0) { + emit_bits(entropy, (unsigned int) (*bufstart), 1); + bufstart++; + nbits--; + } +} + + +/* + * Emit any pending EOBRUN symbol. + */ + +LOCAL(void) +emit_eobrun (phuff_entropy_ptr entropy) +{ + register int temp, nbits; + + if (entropy->EOBRUN > 0) { /* if there is any pending EOBRUN */ + temp = (int)entropy->EOBRUN; + nbits = 0; + while ((temp >>= 1)) + nbits++; + /* safety check: shouldn't happen given limited correction-bit buffer */ + if (nbits > 14) + ERREXIT(entropy->cinfo, JERR_HUFF_MISSING_CODE); + + emit_symbol(entropy, entropy->ac_tbl_no, nbits << 4); + if (nbits) + emit_bits(entropy, entropy->EOBRUN, nbits); + + entropy->EOBRUN = 0; + + /* Emit any buffered correction bits */ + emit_buffered_bits(entropy, entropy->bit_buffer, entropy->BE); + entropy->BE = 0; + } +} + + +/* + * Emit a restart marker & resynchronize predictions. + */ + +LOCAL(void) +emit_restart (phuff_entropy_ptr entropy, int restart_num) +{ + int ci; + + emit_eobrun(entropy); + + if (! entropy->gather_statistics) { + flush_bits(entropy); + emit_byte(entropy, 0xFF); + emit_byte(entropy, JPEG_RST0 + restart_num); + } + + if (entropy->cinfo->Ss == 0) { + /* Re-initialize DC predictions to 0 */ + for (ci = 0; ci < entropy->cinfo->comps_in_scan; ci++) + entropy->last_dc_val[ci] = 0; + } else { + /* Re-initialize all AC-related fields to 0 */ + entropy->EOBRUN = 0; + entropy->BE = 0; + } +} + + +/* + * MCU encoding for DC initial scan (either spectral selection, + * or first pass of successive approximation). + */ + +METHODDEF(boolean) +encode_mcu_DC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data) +{ + j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; + phuff_entropy_ptr entropy = (phuff_entropy_ptr) lossyc->entropy_private; + register int temp, temp2; + register int nbits; + int blkn, ci; + int Al = cinfo->Al; + JBLOCKROW block; + jpeg_component_info * compptr; + ISHIFT_TEMPS + + entropy->next_output_byte = cinfo->dest->next_output_byte; + entropy->free_in_buffer = cinfo->dest->free_in_buffer; + + /* Emit restart marker if needed */ + if (cinfo->restart_interval) + if (entropy->restarts_to_go == 0) + emit_restart(entropy, entropy->next_restart_num); + + /* Encode the MCU data blocks */ + for (blkn = 0; blkn < cinfo->data_units_in_MCU; blkn++) { + block = MCU_data[blkn]; + ci = cinfo->MCU_membership[blkn]; + compptr = cinfo->cur_comp_info[ci]; + + /* Compute the DC value after the required point transform by Al. + * This is simply an arithmetic right shift. + */ + temp2 = IRIGHT_SHIFT((int) ((*block)[0]), Al); + + /* DC differences are figured on the point-transformed values. */ + temp = temp2 - entropy->last_dc_val[ci]; + entropy->last_dc_val[ci] = temp2; + + /* Encode the DC coefficient difference per section G.1.2.1 */ + temp2 = temp; + if (temp < 0) { + temp = -temp; /* temp is abs value of input */ + /* For a negative input, want temp2 = bitwise complement of abs(input) */ + /* This code assumes we are on a two's complement machine */ + temp2--; + } + + /* Find the number of bits needed for the magnitude of the coefficient */ + nbits = 0; + while (temp) { + nbits++; + temp >>= 1; + } + /* Check for out-of-range coefficient values. + * Since we're encoding a difference, the range limit is twice as much. + */ + if (nbits > MAX_COEF_BITS+1) + ERREXIT(cinfo, JERR_BAD_DCT_COEF); + + /* Count/emit the Huffman-coded symbol for the number of bits */ + emit_symbol(entropy, compptr->dc_tbl_no, nbits); + + /* Emit that number of bits of the value, if positive, */ + /* or the complement of its magnitude, if negative. */ + if (nbits) /* emit_bits rejects calls with size 0 */ + emit_bits(entropy, (unsigned int) temp2, nbits); + } + + cinfo->dest->next_output_byte = entropy->next_output_byte; + cinfo->dest->free_in_buffer = entropy->free_in_buffer; + + /* Update restart-interval state too */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) { + entropy->restarts_to_go = cinfo->restart_interval; + entropy->next_restart_num++; + entropy->next_restart_num &= 7; + } + entropy->restarts_to_go--; + } + + return TRUE; +} + + +/* + * MCU encoding for AC initial scan (either spectral selection, + * or first pass of successive approximation). + */ + +METHODDEF(boolean) +encode_mcu_AC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data) +{ + j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; + phuff_entropy_ptr entropy = (phuff_entropy_ptr) lossyc->entropy_private; + register int temp, temp2; + register int nbits; + register int r, k; + int Se = cinfo->Se; + int Al = cinfo->Al; + JBLOCKROW block; + + entropy->next_output_byte = cinfo->dest->next_output_byte; + entropy->free_in_buffer = cinfo->dest->free_in_buffer; + + /* Emit restart marker if needed */ + if (cinfo->restart_interval) + if (entropy->restarts_to_go == 0) + emit_restart(entropy, entropy->next_restart_num); + + /* Encode the MCU data block */ + block = MCU_data[0]; + + /* Encode the AC coefficients per section G.1.2.2, fig. G.3 */ + + r = 0; /* r = run length of zeros */ + + for (k = cinfo->Ss; k <= Se; k++) { + if ((temp = (*block)[jpeg_natural_order[k]]) == 0) { + r++; + continue; + } + /* We must apply the point transform by Al. For AC coefficients this + * is an integer division with rounding towards 0. To do this portably + * in C, we shift after obtaining the absolute value; so the code is + * interwoven with finding the abs value (temp) and output bits (temp2). + */ + if (temp < 0) { + temp = -temp; /* temp is abs value of input */ + temp >>= Al; /* apply the point transform */ + /* For a negative coef, want temp2 = bitwise complement of abs(coef) */ + temp2 = ~temp; + } else { + temp >>= Al; /* apply the point transform */ + temp2 = temp; + } + /* Watch out for case that nonzero coef is zero after point transform */ + if (temp == 0) { + r++; + continue; + } + + /* Emit any pending EOBRUN */ + if (entropy->EOBRUN > 0) + emit_eobrun(entropy); + /* if run length > 15, must emit special run-length-16 codes (0xF0) */ + while (r > 15) { + emit_symbol(entropy, entropy->ac_tbl_no, 0xF0); + r -= 16; + } + + /* Find the number of bits needed for the magnitude of the coefficient */ + nbits = 1; /* there must be at least one 1 bit */ + while ((temp >>= 1)) + nbits++; + /* Check for out-of-range coefficient values */ + if (nbits > MAX_COEF_BITS) + ERREXIT(cinfo, JERR_BAD_DCT_COEF); + + /* Count/emit Huffman symbol for run length / number of bits */ + emit_symbol(entropy, entropy->ac_tbl_no, (r << 4) + nbits); + + /* Emit that number of bits of the value, if positive, */ + /* or the complement of its magnitude, if negative. */ + emit_bits(entropy, (unsigned int) temp2, nbits); + + r = 0; /* reset zero run length */ + } + + if (r > 0) { /* If there are trailing zeroes, */ + entropy->EOBRUN++; /* count an EOB */ + if (entropy->EOBRUN == 0x7FFF) + emit_eobrun(entropy); /* force it out to avoid overflow */ + } + + cinfo->dest->next_output_byte = entropy->next_output_byte; + cinfo->dest->free_in_buffer = entropy->free_in_buffer; + + /* Update restart-interval state too */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) { + entropy->restarts_to_go = cinfo->restart_interval; + entropy->next_restart_num++; + entropy->next_restart_num &= 7; + } + entropy->restarts_to_go--; + } + + return TRUE; +} + + +/* + * MCU encoding for DC successive approximation refinement scan. + * Note: we assume such scans can be multi-component, although the spec + * is not very clear on the point. + */ + +METHODDEF(boolean) +encode_mcu_DC_refine (j_compress_ptr cinfo, JBLOCKROW *MCU_data) +{ + j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; + phuff_entropy_ptr entropy = (phuff_entropy_ptr) lossyc->entropy_private; + register int temp; + int blkn; + int Al = cinfo->Al; + JBLOCKROW block; + + entropy->next_output_byte = cinfo->dest->next_output_byte; + entropy->free_in_buffer = cinfo->dest->free_in_buffer; + + /* Emit restart marker if needed */ + if (cinfo->restart_interval) + if (entropy->restarts_to_go == 0) + emit_restart(entropy, entropy->next_restart_num); + + /* Encode the MCU data blocks */ + for (blkn = 0; blkn < cinfo->data_units_in_MCU; blkn++) { + block = MCU_data[blkn]; + + /* We simply emit the Al'th bit of the DC coefficient value. */ + temp = (*block)[0]; + emit_bits(entropy, (unsigned int) (temp >> Al), 1); + } + + cinfo->dest->next_output_byte = entropy->next_output_byte; + cinfo->dest->free_in_buffer = entropy->free_in_buffer; + + /* Update restart-interval state too */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) { + entropy->restarts_to_go = cinfo->restart_interval; + entropy->next_restart_num++; + entropy->next_restart_num &= 7; + } + entropy->restarts_to_go--; + } + + return TRUE; +} + + +/* + * MCU encoding for AC successive approximation refinement scan. + */ + +METHODDEF(boolean) +encode_mcu_AC_refine (j_compress_ptr cinfo, JBLOCKROW *MCU_data) +{ + j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; + phuff_entropy_ptr entropy = (phuff_entropy_ptr) lossyc->entropy_private; + register int temp; + register int r, k; + int EOB; + char *BR_buffer; + unsigned int BR; + int Se = cinfo->Se; + int Al = cinfo->Al; + JBLOCKROW block; + int absvalues[DCTSIZE2]; + + entropy->next_output_byte = cinfo->dest->next_output_byte; + entropy->free_in_buffer = cinfo->dest->free_in_buffer; + + /* Emit restart marker if needed */ + if (cinfo->restart_interval) + if (entropy->restarts_to_go == 0) + emit_restart(entropy, entropy->next_restart_num); + + /* Encode the MCU data block */ + block = MCU_data[0]; + + /* It is convenient to make a pre-pass to determine the transformed + * coefficients' absolute values and the EOB position. + */ + EOB = 0; + for (k = cinfo->Ss; k <= Se; k++) { + temp = (*block)[jpeg_natural_order[k]]; + /* We must apply the point transform by Al. For AC coefficients this + * is an integer division with rounding towards 0. To do this portably + * in C, we shift after obtaining the absolute value. + */ + if (temp < 0) + temp = -temp; /* temp is abs value of input */ + temp >>= Al; /* apply the point transform */ + absvalues[k] = temp; /* save abs value for main pass */ + if (temp == 1) + EOB = k; /* EOB = index of last newly-nonzero coef */ + } + + /* Encode the AC coefficients per section G.1.2.3, fig. G.7 */ + + r = 0; /* r = run length of zeros */ + BR = 0; /* BR = count of buffered bits added now */ + BR_buffer = entropy->bit_buffer + entropy->BE; /* Append bits to buffer */ + + for (k = cinfo->Ss; k <= Se; k++) { + if ((temp = absvalues[k]) == 0) { + r++; + continue; + } + + /* Emit any required ZRLs, but not if they can be folded into EOB */ + while (r > 15 && k <= EOB) { + /* emit any pending EOBRUN and the BE correction bits */ + emit_eobrun(entropy); + /* Emit ZRL */ + emit_symbol(entropy, entropy->ac_tbl_no, 0xF0); + r -= 16; + /* Emit buffered correction bits that must be associated with ZRL */ + emit_buffered_bits(entropy, BR_buffer, BR); + BR_buffer = entropy->bit_buffer; /* BE bits are gone now */ + BR = 0; + } + + /* If the coef was previously nonzero, it only needs a correction bit. + * NOTE: a straight translation of the spec's figure G.7 would suggest + * that we also need to test r > 15. But if r > 15, we can only get here + * if k > EOB, which implies that this coefficient is not 1. + */ + if (temp > 1) { + /* The correction bit is the next bit of the absolute value. */ + BR_buffer[BR++] = (char) (temp & 1); + continue; + } + + /* Emit any pending EOBRUN and the BE correction bits */ + emit_eobrun(entropy); + + /* Count/emit Huffman symbol for run length / number of bits */ + emit_symbol(entropy, entropy->ac_tbl_no, (r << 4) + 1); + + /* Emit output bit for newly-nonzero coef */ + temp = ((*block)[jpeg_natural_order[k]] < 0) ? 0 : 1; + emit_bits(entropy, (unsigned int) temp, 1); + + /* Emit buffered correction bits that must be associated with this code */ + emit_buffered_bits(entropy, BR_buffer, BR); + BR_buffer = entropy->bit_buffer; /* BE bits are gone now */ + BR = 0; + r = 0; /* reset zero run length */ + } + + if (r > 0 || BR > 0) { /* If there are trailing zeroes, */ + entropy->EOBRUN++; /* count an EOB */ + entropy->BE += BR; /* concat my correction bits to older ones */ + /* We force out the EOB if we risk either: + * 1. overflow of the EOB counter; + * 2. overflow of the correction bit buffer during the next MCU. + */ + if (entropy->EOBRUN == 0x7FFF || entropy->BE > (MAX_CORR_BITS-DCTSIZE2+1)) + emit_eobrun(entropy); + } + + cinfo->dest->next_output_byte = entropy->next_output_byte; + cinfo->dest->free_in_buffer = entropy->free_in_buffer; + + /* Update restart-interval state too */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) { + entropy->restarts_to_go = cinfo->restart_interval; + entropy->next_restart_num++; + entropy->next_restart_num &= 7; + } + entropy->restarts_to_go--; + } + + return TRUE; +} + + +/* + * Finish up at the end of a Huffman-compressed progressive scan. + */ + +METHODDEF(void) +finish_pass_phuff (j_compress_ptr cinfo) +{ + j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; + phuff_entropy_ptr entropy = (phuff_entropy_ptr) lossyc->entropy_private; + + entropy->next_output_byte = cinfo->dest->next_output_byte; + entropy->free_in_buffer = cinfo->dest->free_in_buffer; + + /* Flush out any buffered data */ + emit_eobrun(entropy); + flush_bits(entropy); + + cinfo->dest->next_output_byte = entropy->next_output_byte; + cinfo->dest->free_in_buffer = entropy->free_in_buffer; +} + + +/* + * Finish up a statistics-gathering pass and create the new Huffman tables. + */ + +METHODDEF(void) +finish_pass_gather_phuff (j_compress_ptr cinfo) +{ + j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; + phuff_entropy_ptr entropy = (phuff_entropy_ptr) lossyc->entropy_private; + boolean is_DC_band; + int ci, tbl; + jpeg_component_info * compptr; + JHUFF_TBL **htblptr; + boolean did[NUM_HUFF_TBLS]; + + /* Flush out buffered data (all we care about is counting the EOB symbol) */ + emit_eobrun(entropy); + + is_DC_band = (cinfo->Ss == 0); + + /* It's important not to apply jpeg_gen_optimal_table more than once + * per table, because it clobbers the input frequency counts! + */ + MEMZERO(did, SIZEOF(did)); + + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + if (is_DC_band) { + if (cinfo->Ah != 0) /* DC refinement needs no table */ + continue; + tbl = compptr->dc_tbl_no; + } else { + tbl = compptr->ac_tbl_no; + } + if (! did[tbl]) { + if (is_DC_band) + htblptr = & cinfo->dc_huff_tbl_ptrs[tbl]; + else + htblptr = & cinfo->ac_huff_tbl_ptrs[tbl]; + if (*htblptr == NULL) + *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo); + jpeg_gen_optimal_table(cinfo, *htblptr, entropy->count_ptrs[tbl]); + did[tbl] = TRUE; + } + } +} + + +METHODDEF(boolean) +need_optimization_pass (j_compress_ptr cinfo) +{ + return (cinfo->Ss != 0 || cinfo->Ah == 0); +} + + +/* + * Module initialization routine for progressive Huffman entropy encoding. + */ + +GLOBAL(void) +jinit_phuff_encoder (j_compress_ptr cinfo) +{ + j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; + phuff_entropy_ptr entropy; + int i; + + entropy = (phuff_entropy_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(phuff_entropy_encoder)); + lossyc->entropy_private = (struct jpeg_entropy_encoder *) entropy; + lossyc->pub.entropy_start_pass = start_pass_phuff; + lossyc->pub.need_optimization_pass = need_optimization_pass; + + /* Mark tables unallocated */ + for (i = 0; i < NUM_HUFF_TBLS; i++) { + entropy->derived_tbls[i] = NULL; + entropy->count_ptrs[i] = NULL; + } + entropy->bit_buffer = NULL; /* needed only in AC refinement scan */ +} + +#endif /* C_PROGRESSIVE_SUPPORTED */ diff --git a/dcmjpeg/libijg8/jcpred.c b/dcmjpeg/libijg8/jcpred.c new file mode 100644 index 00000000..503058ab --- /dev/null +++ b/dcmjpeg/libijg8/jcpred.c @@ -0,0 +1,314 @@ +/* + * jcpred.c + * + * Copyright (C) 1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains sample differencing for lossless JPEG. + * + * In order to avoid paying the performance penalty of having to check the + * predictor being used and the row being processed for each call of the + * undifferencer, and to promote optimization, we have separate differencing + * functions for each case. + * + * We are able to avoid duplicating source code by implementing the predictors + * and differencers as macros. Each of the differencing functions are + * simply wrappers around a DIFFERENCE macro with the appropriate PREDICTOR + * macro passed as an argument. + */ + +#define JPEG_INTERNALS +#include "jinclude8.h" +#include "jpeglib8.h" +#include "jlossls8.h" /* Private declarations for lossless codec */ + + +#ifdef C_LOSSLESS_SUPPORTED + +/* Private predictor object */ + +typedef struct { + /* MCU-rows left in the restart interval for each component */ + unsigned int restart_rows_to_go[MAX_COMPONENTS]; +} c_predictor; + +typedef c_predictor * c_pred_ptr; + +/* Forward declarations */ +LOCAL(void) reset_predictor + JPP((j_compress_ptr cinfo, int ci)); +METHODDEF(void) start_pass + JPP((j_compress_ptr cinfo)); + + +/* Predictor for the first column of the first row: 2^(P-Pt-1) */ +#define INITIAL_PREDICTORx (1 << (cinfo->data_precision - cinfo->Al - 1)) + +/* Predictor for the first column of the remaining rows: Rb */ +#define INITIAL_PREDICTOR2 GETJSAMPLE(prev_row[0]) + + +/* + * 1-Dimensional differencer routine. + * + * This macro implements the 1-D horizontal predictor (1). INITIAL_PREDICTOR + * is used as the special case predictor for the first column, which must be + * either INITIAL_PREDICTOR2 or INITIAL_PREDICTORx. The remaining samples + * use PREDICTOR1. + */ + +#define DIFFERENCE_1D(INITIAL_PREDICTOR) \ + j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec; \ + c_pred_ptr pred = (c_pred_ptr) losslsc->pred_private; \ + boolean restart = FALSE; \ + unsigned int xindex; \ + int samp, Ra; \ + \ + samp = GETJSAMPLE(input_buf[0]); \ + diff_buf[0] = samp - INITIAL_PREDICTOR; \ + \ + for (xindex = 1; xindex < width; xindex++) { \ + Ra = samp; \ + samp = GETJSAMPLE(input_buf[xindex]); \ + diff_buf[xindex] = samp - PREDICTOR1; \ + } \ + \ + /* Account for restart interval (no-op if not using restarts) */ \ + if (cinfo->restart_interval) { \ + if (--(pred->restart_rows_to_go[ci]) == 0) { \ + reset_predictor(cinfo, ci); \ + restart = TRUE; \ + } \ + } + + +/* + * 2-Dimensional differencer routine. + * + * This macro implements the 2-D horizontal predictors (#2-7). PREDICTOR2 is + * used as the special case predictor for the first column. The remaining + * samples use PREDICTOR, which is a function of Ra, Rb, Rc. + * + * Because prev_row and output_buf may point to the same storage area (in an + * interleaved image with Vi=1, for example), we must take care to buffer Rb/Rc + * before writing the current reconstructed sample value into output_buf. + */ + +#define DIFFERENCE_2D(PREDICTOR) \ + j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec; \ + c_pred_ptr pred = (c_pred_ptr) losslsc->pred_private; \ + unsigned int xindex; \ + int samp, Ra, Rb, Rc; \ + \ + Rb = GETJSAMPLE(prev_row[0]); \ + samp = GETJSAMPLE(input_buf[0]); \ + diff_buf[0] = samp - PREDICTOR2; \ + \ + for (xindex = 1; xindex < width; xindex++) { \ + Rc = Rb; \ + Rb = GETJSAMPLE(prev_row[xindex]); \ + Ra = samp; \ + samp = GETJSAMPLE(input_buf[xindex]); \ + diff_buf[xindex] = samp - PREDICTOR; \ + } \ + \ + /* Account for restart interval (no-op if not using restarts) */ \ + if (cinfo->restart_interval) { \ + if (--pred->restart_rows_to_go[ci] == 0) \ + reset_predictor(cinfo, ci); \ + } + +#define JPEG_UNUSED(x) ((void)x) + +/* + * Differencers for the all rows but the first in a scan or restart interval. + * The first sample in the row is differenced using the vertical + * predictor (2). The rest of the samples are differenced using the + * predictor specified in the scan header. + */ + +METHODDEF(void) +jpeg_difference1(j_compress_ptr cinfo, int ci, + JSAMPROW input_buf, JSAMPROW prev_row, + JDIFFROW diff_buf, JDIMENSION width) +{ + DIFFERENCE_1D(INITIAL_PREDICTOR2); + JPEG_UNUSED(restart); +} + +METHODDEF(void) +jpeg_difference2(j_compress_ptr cinfo, int ci, + JSAMPROW input_buf, JSAMPROW prev_row, + JDIFFROW diff_buf, JDIMENSION width) +{ + DIFFERENCE_2D(PREDICTOR2); + JPEG_UNUSED(Rc); + JPEG_UNUSED(Ra); +} + +METHODDEF(void) +jpeg_difference3(j_compress_ptr cinfo, int ci, + JSAMPROW input_buf, JSAMPROW prev_row, + JDIFFROW diff_buf, JDIMENSION width) +{ + DIFFERENCE_2D(PREDICTOR3); + JPEG_UNUSED(Rc); + JPEG_UNUSED(Ra); +} + +METHODDEF(void) +jpeg_difference4(j_compress_ptr cinfo, int ci, + JSAMPROW input_buf, JSAMPROW prev_row, + JDIFFROW diff_buf, JDIMENSION width) +{ + DIFFERENCE_2D(PREDICTOR4); + JPEG_UNUSED(Rc); + JPEG_UNUSED(Ra); +} + +METHODDEF(void) +jpeg_difference5(j_compress_ptr cinfo, int ci, + JSAMPROW input_buf, JSAMPROW prev_row, + JDIFFROW diff_buf, JDIMENSION width) +{ + SHIFT_TEMPS + DIFFERENCE_2D(PREDICTOR5); + JPEG_UNUSED(Rc); + JPEG_UNUSED(Ra); +} + +METHODDEF(void) +jpeg_difference6(j_compress_ptr cinfo, int ci, + JSAMPROW input_buf, JSAMPROW prev_row, + JDIFFROW diff_buf, JDIMENSION width) +{ + SHIFT_TEMPS + DIFFERENCE_2D(PREDICTOR6); + JPEG_UNUSED(Rc); + JPEG_UNUSED(Ra); +} + +METHODDEF(void) +jpeg_difference7(j_compress_ptr cinfo, int ci, + JSAMPROW input_buf, JSAMPROW prev_row, + JDIFFROW diff_buf, JDIMENSION width) +{ + SHIFT_TEMPS + DIFFERENCE_2D(PREDICTOR7); + JPEG_UNUSED(Rc); + JPEG_UNUSED(Ra); +} + + +/* + * Differencer for the first row in a scan or restart interval. The first + * sample in the row is differenced using the special predictor constant + * x=2^(P-Pt-1). The rest of the samples are differenced using the + * 1-D horizontal predictor (1). + */ + +METHODDEF(void) +jpeg_difference_first_row(j_compress_ptr cinfo, int ci, + JSAMPROW input_buf, JSAMPROW prev_row, + JDIFFROW diff_buf, JDIMENSION width) +{ + DIFFERENCE_1D(INITIAL_PREDICTORx); + + /* + * Now that we have differenced the first row, we want to use the + * differencer which corresponds to the predictor specified in the + * scan header. + * + * Note that we don't to do this if we have just reset the predictor + * for a new restart interval. + */ + if (!restart) { + switch (cinfo->Ss) { + case 1: + losslsc->predict_difference[ci] = jpeg_difference1; + break; + case 2: + losslsc->predict_difference[ci] = jpeg_difference2; + break; + case 3: + losslsc->predict_difference[ci] = jpeg_difference3; + break; + case 4: + losslsc->predict_difference[ci] = jpeg_difference4; + break; + case 5: + losslsc->predict_difference[ci] = jpeg_difference5; + break; + case 6: + losslsc->predict_difference[ci] = jpeg_difference6; + break; + case 7: + losslsc->predict_difference[ci] = jpeg_difference7; + break; + } + } +} + +/* + * Reset predictor at the start of a pass or restart interval. + */ + +LOCAL(void) +reset_predictor (j_compress_ptr cinfo, int ci) +{ + j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec; + c_pred_ptr pred = (c_pred_ptr) losslsc->pred_private; + + /* Initialize restart counter */ + pred->restart_rows_to_go[ci] = + cinfo->restart_interval / cinfo->MCUs_per_row; + + /* Set difference function to first row function */ + losslsc->predict_difference[ci] = jpeg_difference_first_row; +} + + +/* + * Initialize for an input processing pass. + */ + +METHODDEF(void) +start_pass (j_compress_ptr cinfo) +{ + /* j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec; */ + /* c_pred_ptr pred = (c_pred_ptr) losslsc->pred_private; */ + int ci; + + /* Check that the restart interval is an integer multiple of the number + * of MCU in an MCU-row. + */ + if (cinfo->restart_interval % cinfo->MCUs_per_row != 0) + ERREXIT2(cinfo, JERR_BAD_RESTART, + (int)cinfo->restart_interval, (int)cinfo->MCUs_per_row); + + /* Set predictors for start of pass */ + for (ci = 0; ci < cinfo->num_components; ci++) + reset_predictor(cinfo, ci); +} + + +/* + * Module initialization routine for the differencer. + */ + +GLOBAL(void) +jinit_differencer (j_compress_ptr cinfo) +{ + j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec; + c_pred_ptr pred; + + pred = (c_pred_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(c_predictor)); + losslsc->pred_private = (void *) pred; + losslsc->predict_start_pass = start_pass; +} + +#endif /* C_LOSSLESS_SUPPORTED */ + diff --git a/dcmjpeg/libijg8/jcprepct.c b/dcmjpeg/libijg8/jcprepct.c new file mode 100644 index 00000000..bb8834ff --- /dev/null +++ b/dcmjpeg/libijg8/jcprepct.c @@ -0,0 +1,354 @@ +/* + * jcprepct.c + * + * Copyright (C) 1994-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains the compression preprocessing controller. + * This controller manages the color conversion, downsampling, + * and edge expansion steps. + * + * Most of the complexity here is associated with buffering input rows + * as required by the downsampler. See the comments at the head of + * jcsample.c for the downsampler's needs. + */ + +#define JPEG_INTERNALS +#include "jinclude8.h" +#include "jpeglib8.h" + + +/* At present, jcsample.c can request context rows only for smoothing. + * In the future, we might also need context rows for CCIR601 sampling + * or other more-complex downsampling procedures. The code to support + * context rows should be compiled only if needed. + */ +#ifdef INPUT_SMOOTHING_SUPPORTED +#define CONTEXT_ROWS_SUPPORTED +#endif + + +/* + * For the simple (no-context-row) case, we just need to buffer one + * row group's worth of pixels for the downsampling step. At the bottom of + * the image, we pad to a full row group by replicating the last pixel row. + * The downsampler's last output row is then replicated if needed to pad + * out to a full iMCU row. + * + * When providing context rows, we must buffer three row groups' worth of + * pixels. Three row groups are physically allocated, but the row pointer + * arrays are made five row groups high, with the extra pointers above and + * below "wrapping around" to point to the last and first real row groups. + * This allows the downsampler to access the proper context rows. + * At the top and bottom of the image, we create dummy context rows by + * copying the first or last real pixel row. This copying could be avoided + * by pointer hacking as is done in jdmainct.c, but it doesn't seem worth the + * trouble on the compression side. + */ + + +/* Private buffer controller object */ + +typedef struct { + struct jpeg_c_prep_controller pub; /* public fields */ + + /* Downsampling input buffer. This buffer holds color-converted data + * until we have enough to do a downsample step. + */ + JSAMPARRAY color_buf[MAX_COMPONENTS]; + + JDIMENSION rows_to_go; /* counts rows remaining in source image */ + int next_buf_row; /* index of next row to store in color_buf */ + +#ifdef CONTEXT_ROWS_SUPPORTED /* only needed for context case */ + int this_row_group; /* starting row index of group to process */ + int next_buf_stop; /* downsample when we reach this index */ +#endif +} my_prep_controller; + +typedef my_prep_controller * my_prep_ptr; + + +/* + * Initialize for a processing pass. + */ + +METHODDEF(void) +start_pass_prep (j_compress_ptr cinfo, J_BUF_MODE pass_mode) +{ + my_prep_ptr prep = (my_prep_ptr) cinfo->prep; + + if (pass_mode != JBUF_PASS_THRU) + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + + /* Initialize total-height counter for detecting bottom of image */ + prep->rows_to_go = cinfo->image_height; + /* Mark the conversion buffer empty */ + prep->next_buf_row = 0; +#ifdef CONTEXT_ROWS_SUPPORTED + /* Preset additional state variables for context mode. + * These aren't used in non-context mode, so we needn't test which mode. + */ + prep->this_row_group = 0; + /* Set next_buf_stop to stop after two row groups have been read in. */ + prep->next_buf_stop = 2 * cinfo->max_v_samp_factor; +#endif +} + + +/* + * Expand an image vertically from height input_rows to height output_rows, + * by duplicating the bottom row. + */ + +LOCAL(void) +expand_bottom_edge (JSAMPARRAY image_data, JDIMENSION num_cols, + int input_rows, int output_rows) +{ + register int row; + + for (row = input_rows; row < output_rows; row++) { + jcopy_sample_rows(image_data, input_rows-1, image_data, row, + 1, num_cols); + } +} + + +/* + * Process some data in the simple no-context case. + * + * Preprocessor output data is counted in "row groups". A row group + * is defined to be v_samp_factor sample rows of each component. + * Downsampling will produce this much data from each max_v_samp_factor + * input rows. + */ + +METHODDEF(void) +pre_process_data (j_compress_ptr cinfo, + JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, + JDIMENSION in_rows_avail, + JSAMPIMAGE output_buf, JDIMENSION *out_row_group_ctr, + JDIMENSION out_row_groups_avail) +{ + my_prep_ptr prep = (my_prep_ptr) cinfo->prep; + int numrows, ci; + JDIMENSION inrows; + jpeg_component_info * compptr; + + while (*in_row_ctr < in_rows_avail && + *out_row_group_ctr < out_row_groups_avail) { + /* Do color conversion to fill the conversion buffer. */ + inrows = in_rows_avail - *in_row_ctr; + numrows = cinfo->max_v_samp_factor - prep->next_buf_row; + numrows = (int) MIN((JDIMENSION) numrows, inrows); + (*cinfo->cconvert->color_convert) (cinfo, input_buf + *in_row_ctr, + prep->color_buf, + (JDIMENSION) prep->next_buf_row, + numrows); + *in_row_ctr += (JDIMENSION)numrows; + prep->next_buf_row += numrows; + prep->rows_to_go -= (JDIMENSION)numrows; + /* If at bottom of image, pad to fill the conversion buffer. */ + if (prep->rows_to_go == 0 && + prep->next_buf_row < cinfo->max_v_samp_factor) { + for (ci = 0; ci < cinfo->num_components; ci++) { + expand_bottom_edge(prep->color_buf[ci], cinfo->image_width, + prep->next_buf_row, cinfo->max_v_samp_factor); + } + prep->next_buf_row = cinfo->max_v_samp_factor; + } + /* If we've filled the conversion buffer, empty it. */ + if (prep->next_buf_row == cinfo->max_v_samp_factor) { + (*cinfo->downsample->downsample) (cinfo, + prep->color_buf, (JDIMENSION) 0, + output_buf, *out_row_group_ctr); + prep->next_buf_row = 0; + (*out_row_group_ctr)++; + } + /* If at bottom of image, pad the output to a full iMCU height. + * Note we assume the caller is providing a one-iMCU-height output buffer! + */ + if (prep->rows_to_go == 0 && + *out_row_group_ctr < out_row_groups_avail) { + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + expand_bottom_edge(output_buf[ci], + compptr->width_in_data_units * (JDIMENSION)cinfo->data_unit, + (int)*out_row_group_ctr * compptr->v_samp_factor, + (int)out_row_groups_avail * compptr->v_samp_factor); + } + *out_row_group_ctr = out_row_groups_avail; + break; /* can exit outer loop without test */ + } + } +} + + +#ifdef CONTEXT_ROWS_SUPPORTED + +/* + * Process some data in the context case. + */ + +METHODDEF(void) +pre_process_context (j_compress_ptr cinfo, + JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, + JDIMENSION in_rows_avail, + JSAMPIMAGE output_buf, JDIMENSION *out_row_group_ctr, + JDIMENSION out_row_groups_avail) +{ + my_prep_ptr prep = (my_prep_ptr) cinfo->prep; + int numrows, ci; + int buf_height = cinfo->max_v_samp_factor * 3; + JDIMENSION inrows; + + while (*out_row_group_ctr < out_row_groups_avail) { + if (*in_row_ctr < in_rows_avail) { + /* Do color conversion to fill the conversion buffer. */ + inrows = in_rows_avail - *in_row_ctr; + numrows = prep->next_buf_stop - prep->next_buf_row; + numrows = (int) MIN((JDIMENSION) numrows, inrows); + (*cinfo->cconvert->color_convert) (cinfo, input_buf + *in_row_ctr, + prep->color_buf, + (JDIMENSION) prep->next_buf_row, + numrows); + /* Pad at top of image, if first time through */ + if (prep->rows_to_go == cinfo->image_height) { + for (ci = 0; ci < cinfo->num_components; ci++) { + int row; + for (row = 1; row <= cinfo->max_v_samp_factor; row++) { + jcopy_sample_rows(prep->color_buf[ci], 0, + prep->color_buf[ci], -row, + 1, cinfo->image_width); + } + } + } + *in_row_ctr += (JDIMENSION)numrows; + prep->next_buf_row += numrows; + prep->rows_to_go -= (JDIMENSION)numrows; + } else { + /* Return for more data, unless we are at the bottom of the image. */ + if (prep->rows_to_go != 0) + break; + /* When at bottom of image, pad to fill the conversion buffer. */ + if (prep->next_buf_row < prep->next_buf_stop) { + for (ci = 0; ci < cinfo->num_components; ci++) { + expand_bottom_edge(prep->color_buf[ci], cinfo->image_width, + prep->next_buf_row, prep->next_buf_stop); + } + prep->next_buf_row = prep->next_buf_stop; + } + } + /* If we've gotten enough data, downsample a row group. */ + if (prep->next_buf_row == prep->next_buf_stop) { + (*cinfo->downsample->downsample) (cinfo, + prep->color_buf, + (JDIMENSION) prep->this_row_group, + output_buf, *out_row_group_ctr); + (*out_row_group_ctr)++; + /* Advance pointers with wraparound as necessary. */ + prep->this_row_group += cinfo->max_v_samp_factor; + if (prep->this_row_group >= buf_height) + prep->this_row_group = 0; + if (prep->next_buf_row >= buf_height) + prep->next_buf_row = 0; + prep->next_buf_stop = prep->next_buf_row + cinfo->max_v_samp_factor; + } + } +} + + +/* + * Create the wrapped-around downsampling input buffer needed for context mode. + */ + +LOCAL(void) +create_context_buffer (j_compress_ptr cinfo) +{ + my_prep_ptr prep = (my_prep_ptr) cinfo->prep; + int rgroup_height = cinfo->max_v_samp_factor; + int ci, i; + jpeg_component_info * compptr; + JSAMPARRAY true_buffer, fake_buffer; + + /* Grab enough space for fake row pointers for all the components; + * we need five row groups' worth of pointers for each component. + */ + fake_buffer = (JSAMPARRAY) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (size_t)(cinfo->num_components * 5 * rgroup_height) * + SIZEOF(JSAMPROW)); + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + /* Allocate the actual buffer space (3 row groups) for this component. + * We make the buffer wide enough to allow the downsampler to edge-expand + * horizontally within the buffer, if it so chooses. + */ + true_buffer = (*cinfo->mem->alloc_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + (JDIMENSION) (((long) compptr->width_in_data_units * cinfo->data_unit * + cinfo->max_h_samp_factor) / compptr->h_samp_factor), + (JDIMENSION) (3 * rgroup_height)); + /* Copy true buffer row pointers into the middle of the fake row array */ + MEMCOPY(fake_buffer + rgroup_height, true_buffer, + 3 * (size_t)rgroup_height * SIZEOF(JSAMPROW)); + /* Fill in the above and below wraparound pointers */ + for (i = 0; i < rgroup_height; i++) { + fake_buffer[i] = true_buffer[2 * rgroup_height + i]; + fake_buffer[4 * rgroup_height + i] = true_buffer[i]; + } + prep->color_buf[ci] = fake_buffer + rgroup_height; + fake_buffer += 5 * rgroup_height; /* point to space for next component */ + } +} + +#endif /* CONTEXT_ROWS_SUPPORTED */ + + +/* + * Initialize preprocessing controller. + */ + +GLOBAL(void) +jinit_c_prep_controller (j_compress_ptr cinfo, boolean need_full_buffer) +{ + my_prep_ptr prep; + int ci; + jpeg_component_info * compptr; + + if (need_full_buffer) /* safety check */ + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + + prep = (my_prep_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_prep_controller)); + cinfo->prep = (struct jpeg_c_prep_controller *) prep; + prep->pub.start_pass = start_pass_prep; + + /* Allocate the color conversion buffer. + * We make the buffer wide enough to allow the downsampler to edge-expand + * horizontally within the buffer, if it so chooses. + */ + if (cinfo->downsample->need_context_rows) { + /* Set up to provide context rows */ +#ifdef CONTEXT_ROWS_SUPPORTED + prep->pub.pre_process_data = pre_process_context; + create_context_buffer(cinfo); +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } else { + /* No context, just make it tall enough for one row group */ + prep->pub.pre_process_data = pre_process_data; + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + prep->color_buf[ci] = (*cinfo->mem->alloc_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + (JDIMENSION) (((long) compptr->width_in_data_units * cinfo->data_unit * + cinfo->max_h_samp_factor) / compptr->h_samp_factor), + (JDIMENSION) cinfo->max_v_samp_factor); + } + } +} diff --git a/dcmjpeg/libijg8/jcsample.c b/dcmjpeg/libijg8/jcsample.c new file mode 100644 index 00000000..0ba08333 --- /dev/null +++ b/dcmjpeg/libijg8/jcsample.c @@ -0,0 +1,519 @@ +/* + * jcsample.c + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains downsampling routines. + * + * Downsampling input data is counted in "row groups". A row group + * is defined to be max_v_samp_factor pixel rows of each component, + * from which the downsampler produces v_samp_factor sample rows. + * A single row group is processed in each call to the downsampler module. + * + * The downsampler is responsible for edge-expansion of its output data + * to fill an integral number of DCT blocks horizontally. The source buffer + * may be modified if it is helpful for this purpose (the source buffer is + * allocated wide enough to correspond to the desired output width). + * The caller (the prep controller) is responsible for vertical padding. + * + * The downsampler may request "context rows" by setting need_context_rows + * during startup. In this case, the input arrays will contain at least + * one row group's worth of pixels above and below the passed-in data; + * the caller will create dummy rows at image top and bottom by replicating + * the first or last real pixel row. + * + * An excellent reference for image resampling is + * Digital Image Warping, George Wolberg, 1990. + * Pub. by IEEE Computer Society Press, Los Alamitos, CA. ISBN 0-8186-8944-7. + * + * The downsampling algorithm used here is a simple average of the source + * pixels covered by the output pixel. The hi-falutin sampling literature + * refers to this as a "box filter". In general the characteristics of a box + * filter are not very good, but for the specific cases we normally use (1:1 + * and 2:1 ratios) the box is equivalent to a "triangle filter" which is not + * nearly so bad. If you intend to use other sampling ratios, you'd be well + * advised to improve this code. + * + * A simple input-smoothing capability is provided. This is mainly intended + * for cleaning up color-dithered GIF input files (if you find it inadequate, + * we suggest using an external filtering program such as pnmconvol). When + * enabled, each input pixel P is replaced by a weighted sum of itself and its + * eight neighbors. P's weight is 1-8*SF and each neighbor's weight is SF, + * where SF = (smoothing_factor / 1024). + * Currently, smoothing is only supported for 2h2v sampling factors. + */ + +#define JPEG_INTERNALS +#include "jinclude8.h" +#include "jpeglib8.h" + + +/* Pointer to routine to downsample a single component */ +typedef JMETHOD(void, downsample1_ptr, + (j_compress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY input_data, JSAMPARRAY output_data)); + +/* Private subobject */ + +typedef struct { + struct jpeg_downsampler pub; /* public fields */ + + /* Downsampling method pointers, one per component */ + downsample1_ptr methods[MAX_COMPONENTS]; +} my_downsampler; + +typedef my_downsampler * my_downsample_ptr; + + +/* + * Initialize for a downsampling pass. + */ + +METHODDEF(void) +start_pass_downsample (j_compress_ptr cinfo) +{ + /* no work for now */ +} + + +/* + * Expand a component horizontally from width input_cols to width output_cols, + * by duplicating the rightmost samples. + */ + +LOCAL(void) +expand_right_edge (JSAMPARRAY image_data, int num_rows, + JDIMENSION input_cols, JDIMENSION output_cols) +{ + register JSAMPROW ptr; + register JSAMPLE pixval; + register int count; + int row; + int numcols = (int) (output_cols - input_cols); + + if (numcols > 0) { + for (row = 0; row < num_rows; row++) { + ptr = image_data[row] + input_cols; + pixval = ptr[-1]; /* don't need GETJSAMPLE() here */ + for (count = numcols; count > 0; count--) + *ptr++ = pixval; + } + } +} + + +/* + * Do downsampling for a whole row group (all components). + * + * In this version we simply downsample each component independently. + */ + +METHODDEF(void) +sep_downsample (j_compress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION in_row_index, + JSAMPIMAGE output_buf, JDIMENSION out_row_group_index) +{ + my_downsample_ptr downsample = (my_downsample_ptr) cinfo->downsample; + int ci; + jpeg_component_info * compptr; + JSAMPARRAY in_ptr, out_ptr; + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + in_ptr = input_buf[ci] + in_row_index; + out_ptr = output_buf[ci] + (out_row_group_index * (JDIMENSION)compptr->v_samp_factor); + (*downsample->methods[ci]) (cinfo, compptr, in_ptr, out_ptr); + } +} + + +/* + * Downsample pixel values of a single component. + * One row group is processed per call. + * This version handles arbitrary integral sampling ratios, without smoothing. + * Note that this version is not actually used for customary sampling ratios. + */ + +METHODDEF(void) +int_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY input_data, JSAMPARRAY output_data) +{ + int inrow, outrow, h_expand, v_expand, numpix, numpix2, h, v; + JDIMENSION outcol, outcol_h; /* outcol_h == outcol*h_expand */ + JDIMENSION output_cols = compptr->width_in_data_units * (JDIMENSION)cinfo->data_unit; + JSAMPROW inptr, outptr; + IJG_INT32 outvalue; + + h_expand = cinfo->max_h_samp_factor / compptr->h_samp_factor; + v_expand = cinfo->max_v_samp_factor / compptr->v_samp_factor; + numpix = h_expand * v_expand; + numpix2 = numpix/2; + + /* Expand input data enough to let all the output samples be generated + * by the standard loop. Special-casing padded output would be more + * efficient. + */ + expand_right_edge(input_data, cinfo->max_v_samp_factor, + cinfo->image_width, output_cols * (JDIMENSION)h_expand); + + inrow = 0; + for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) { + outptr = output_data[outrow]; + for (outcol = 0, outcol_h = 0; outcol < output_cols; + outcol++, outcol_h += (JDIMENSION)h_expand) { + outvalue = 0; + for (v = 0; v < v_expand; v++) { + inptr = input_data[inrow+v] + outcol_h; + for (h = 0; h < h_expand; h++) { + outvalue += (IJG_INT32) GETJSAMPLE(*inptr++); + } + } + *outptr++ = (JSAMPLE) ((outvalue + numpix2) / numpix); + } + inrow += v_expand; + } +} + + +/* + * Downsample pixel values of a single component. + * This version handles the special case of a full-size component, + * without smoothing. + */ + +METHODDEF(void) +fullsize_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY input_data, JSAMPARRAY output_data) +{ + /* Copy the data */ + jcopy_sample_rows(input_data, 0, output_data, 0, + cinfo->max_v_samp_factor, cinfo->image_width); + /* Edge-expand */ + expand_right_edge(output_data, cinfo->max_v_samp_factor, + cinfo->image_width, compptr->width_in_data_units * (JDIMENSION)cinfo->data_unit); +} + + +/* + * Downsample pixel values of a single component. + * This version handles the common case of 2:1 horizontal and 1:1 vertical, + * without smoothing. + * + * A note about the "bias" calculations: when rounding fractional values to + * integer, we do not want to always round 0.5 up to the next integer. + * If we did that, we'd introduce a noticeable bias towards larger values. + * Instead, this code is arranged so that 0.5 will be rounded up or down at + * alternate pixel locations (a simple ordered dither pattern). + */ + +METHODDEF(void) +h2v1_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY input_data, JSAMPARRAY output_data) +{ + int outrow; + JDIMENSION outcol; + JDIMENSION output_cols = compptr->width_in_data_units * (JDIMENSION)cinfo->data_unit; + register JSAMPROW inptr, outptr; + register int bias; + + /* Expand input data enough to let all the output samples be generated + * by the standard loop. Special-casing padded output would be more + * efficient. + */ + expand_right_edge(input_data, cinfo->max_v_samp_factor, + cinfo->image_width, output_cols * 2); + + for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) { + outptr = output_data[outrow]; + inptr = input_data[outrow]; + bias = 0; /* bias = 0,1,0,1,... for successive samples */ + for (outcol = 0; outcol < output_cols; outcol++) { + *outptr++ = (JSAMPLE) ((GETJSAMPLE(*inptr) + GETJSAMPLE(inptr[1]) + + bias) >> 1); + bias ^= 1; /* 0=>1, 1=>0 */ + inptr += 2; + } + } +} + + +/* + * Downsample pixel values of a single component. + * This version handles the standard case of 2:1 horizontal and 2:1 vertical, + * without smoothing. + */ + +METHODDEF(void) +h2v2_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY input_data, JSAMPARRAY output_data) +{ + int inrow, outrow; + JDIMENSION outcol; + JDIMENSION output_cols = compptr->width_in_data_units * (JDIMENSION)cinfo->data_unit; + register JSAMPROW inptr0, inptr1, outptr; + register int bias; + + /* Expand input data enough to let all the output samples be generated + * by the standard loop. Special-casing padded output would be more + * efficient. + */ + expand_right_edge(input_data, cinfo->max_v_samp_factor, + cinfo->image_width, output_cols * 2); + + inrow = 0; + for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) { + outptr = output_data[outrow]; + inptr0 = input_data[inrow]; + inptr1 = input_data[inrow+1]; + bias = 1; /* bias = 1,2,1,2,... for successive samples */ + for (outcol = 0; outcol < output_cols; outcol++) { + *outptr++ = (JSAMPLE) ((GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) + + GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]) + + bias) >> 2); + bias ^= 3; /* 1=>2, 2=>1 */ + inptr0 += 2; inptr1 += 2; + } + inrow += 2; + } +} + + +#ifdef INPUT_SMOOTHING_SUPPORTED + +/* + * Downsample pixel values of a single component. + * This version handles the standard case of 2:1 horizontal and 2:1 vertical, + * with smoothing. One row of context is required. + */ + +METHODDEF(void) +h2v2_smooth_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY input_data, JSAMPARRAY output_data) +{ + int inrow, outrow; + JDIMENSION colctr; + JDIMENSION output_cols = compptr->width_in_data_units * (JDIMENSION)cinfo->data_unit; + register JSAMPROW inptr0, inptr1, above_ptr, below_ptr, outptr; + IJG_INT32 membersum, neighsum, memberscale, neighscale; + + /* Expand input data enough to let all the output samples be generated + * by the standard loop. Special-casing padded output would be more + * efficient. + */ + expand_right_edge(input_data - 1, cinfo->max_v_samp_factor + 2, + cinfo->image_width, output_cols * 2); + + /* We don't bother to form the individual "smoothed" input pixel values; + * we can directly compute the output which is the average of the four + * smoothed values. Each of the four member pixels contributes a fraction + * (1-8*SF) to its own smoothed image and a fraction SF to each of the three + * other smoothed pixels, therefore a total fraction (1-5*SF)/4 to the final + * output. The four corner-adjacent neighbor pixels contribute a fraction + * SF to just one smoothed pixel, or SF/4 to the final output; while the + * eight edge-adjacent neighbors contribute SF to each of two smoothed + * pixels, or SF/2 overall. In order to use integer arithmetic, these + * factors are scaled by 2^16 = 65536. + * Also recall that SF = smoothing_factor / 1024. + */ + + memberscale = 16384 - cinfo->smoothing_factor * 80; /* scaled (1-5*SF)/4 */ + neighscale = cinfo->smoothing_factor * 16; /* scaled SF/4 */ + + inrow = 0; + for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) { + outptr = output_data[outrow]; + inptr0 = input_data[inrow]; + inptr1 = input_data[inrow+1]; + above_ptr = input_data[inrow-1]; + below_ptr = input_data[inrow+2]; + + /* Special case for first column: pretend column -1 is same as column 0 */ + membersum = GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) + + GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]); + neighsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[1]) + + GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) + + GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[2]) + + GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[2]); + neighsum += neighsum; + neighsum += GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[2]) + + GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[2]); + membersum = membersum * memberscale + neighsum * neighscale; + *outptr++ = (JSAMPLE) ((membersum + 32768) >> 16); + inptr0 += 2; inptr1 += 2; above_ptr += 2; below_ptr += 2; + + for (colctr = output_cols - 2; colctr > 0; colctr--) { + /* sum of pixels directly mapped to this output element */ + membersum = GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) + + GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]); + /* sum of edge-neighbor pixels */ + neighsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[1]) + + GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) + + GETJSAMPLE(inptr0[-1]) + GETJSAMPLE(inptr0[2]) + + GETJSAMPLE(inptr1[-1]) + GETJSAMPLE(inptr1[2]); + /* The edge-neighbors count twice as much as corner-neighbors */ + neighsum += neighsum; + /* Add in the corner-neighbors */ + neighsum += GETJSAMPLE(above_ptr[-1]) + GETJSAMPLE(above_ptr[2]) + + GETJSAMPLE(below_ptr[-1]) + GETJSAMPLE(below_ptr[2]); + /* form final output scaled up by 2^16 */ + membersum = membersum * memberscale + neighsum * neighscale; + /* round, descale and output it */ + *outptr++ = (JSAMPLE) ((membersum + 32768) >> 16); + inptr0 += 2; inptr1 += 2; above_ptr += 2; below_ptr += 2; + } + + /* Special case for last column */ + membersum = GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) + + GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]); + neighsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[1]) + + GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) + + GETJSAMPLE(inptr0[-1]) + GETJSAMPLE(inptr0[1]) + + GETJSAMPLE(inptr1[-1]) + GETJSAMPLE(inptr1[1]); + neighsum += neighsum; + neighsum += GETJSAMPLE(above_ptr[-1]) + GETJSAMPLE(above_ptr[1]) + + GETJSAMPLE(below_ptr[-1]) + GETJSAMPLE(below_ptr[1]); + membersum = membersum * memberscale + neighsum * neighscale; + *outptr = (JSAMPLE) ((membersum + 32768) >> 16); + + inrow += 2; + } +} + + +/* + * Downsample pixel values of a single component. + * This version handles the special case of a full-size component, + * with smoothing. One row of context is required. + */ + +METHODDEF(void) +fullsize_smooth_downsample (j_compress_ptr cinfo, jpeg_component_info *compptr, + JSAMPARRAY input_data, JSAMPARRAY output_data) +{ + int outrow; + JDIMENSION colctr; + JDIMENSION output_cols = compptr->width_in_data_units * (JDIMENSION)cinfo->data_unit; + register JSAMPROW inptr, above_ptr, below_ptr, outptr; + IJG_INT32 membersum, neighsum, memberscale, neighscale; + int colsum, lastcolsum, nextcolsum; + + /* Expand input data enough to let all the output samples be generated + * by the standard loop. Special-casing padded output would be more + * efficient. + */ + expand_right_edge(input_data - 1, cinfo->max_v_samp_factor + 2, + cinfo->image_width, output_cols); + + /* Each of the eight neighbor pixels contributes a fraction SF to the + * smoothed pixel, while the main pixel contributes (1-8*SF). In order + * to use integer arithmetic, these factors are multiplied by 2^16 = 65536. + * Also recall that SF = smoothing_factor / 1024. + */ + + memberscale = 65536L - cinfo->smoothing_factor * 512L; /* scaled 1-8*SF */ + neighscale = cinfo->smoothing_factor * 64; /* scaled SF */ + + for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) { + outptr = output_data[outrow]; + inptr = input_data[outrow]; + above_ptr = input_data[outrow-1]; + below_ptr = input_data[outrow+1]; + + /* Special case for first column */ + colsum = GETJSAMPLE(*above_ptr++) + GETJSAMPLE(*below_ptr++) + + GETJSAMPLE(*inptr); + membersum = GETJSAMPLE(*inptr++); + nextcolsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(*below_ptr) + + GETJSAMPLE(*inptr); + neighsum = colsum + (colsum - membersum) + nextcolsum; + membersum = membersum * memberscale + neighsum * neighscale; + *outptr++ = (JSAMPLE) ((membersum + 32768) >> 16); + lastcolsum = colsum; colsum = nextcolsum; + + for (colctr = output_cols - 2; colctr > 0; colctr--) { + membersum = GETJSAMPLE(*inptr++); + above_ptr++; below_ptr++; + nextcolsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(*below_ptr) + + GETJSAMPLE(*inptr); + neighsum = lastcolsum + (colsum - membersum) + nextcolsum; + membersum = membersum * memberscale + neighsum * neighscale; + *outptr++ = (JSAMPLE) ((membersum + 32768) >> 16); + lastcolsum = colsum; colsum = nextcolsum; + } + + /* Special case for last column */ + membersum = GETJSAMPLE(*inptr); + neighsum = lastcolsum + (colsum - membersum) + colsum; + membersum = membersum * memberscale + neighsum * neighscale; + *outptr = (JSAMPLE) ((membersum + 32768) >> 16); + + } +} + +#endif /* INPUT_SMOOTHING_SUPPORTED */ + + +/* + * Module initialization routine for downsampling. + * Note that we must select a routine for each component. + */ + +GLOBAL(void) +jinit_downsampler (j_compress_ptr cinfo) +{ + my_downsample_ptr downsample; + int ci; + jpeg_component_info * compptr; + boolean smoothok = TRUE; + + downsample = (my_downsample_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_downsampler)); + cinfo->downsample = (struct jpeg_downsampler *) downsample; + downsample->pub.start_pass = start_pass_downsample; + downsample->pub.downsample = sep_downsample; + downsample->pub.need_context_rows = FALSE; + + if (cinfo->CCIR601_sampling) + ERREXIT(cinfo, JERR_CCIR601_NOTIMPL); + + /* Verify we can handle the sampling factors, and set up method pointers */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + if (compptr->h_samp_factor == cinfo->max_h_samp_factor && + compptr->v_samp_factor == cinfo->max_v_samp_factor) { +#ifdef INPUT_SMOOTHING_SUPPORTED + if (cinfo->smoothing_factor) { + downsample->methods[ci] = fullsize_smooth_downsample; + downsample->pub.need_context_rows = TRUE; + } else +#endif + downsample->methods[ci] = fullsize_downsample; + } else if (compptr->h_samp_factor * 2 == cinfo->max_h_samp_factor && + compptr->v_samp_factor == cinfo->max_v_samp_factor) { + smoothok = FALSE; + downsample->methods[ci] = h2v1_downsample; + } else if (compptr->h_samp_factor * 2 == cinfo->max_h_samp_factor && + compptr->v_samp_factor * 2 == cinfo->max_v_samp_factor) { +#ifdef INPUT_SMOOTHING_SUPPORTED + if (cinfo->smoothing_factor) { + downsample->methods[ci] = h2v2_smooth_downsample; + downsample->pub.need_context_rows = TRUE; + } else +#endif + downsample->methods[ci] = h2v2_downsample; + } else if ((cinfo->max_h_samp_factor % compptr->h_samp_factor) == 0 && + (cinfo->max_v_samp_factor % compptr->v_samp_factor) == 0) { + smoothok = FALSE; + downsample->methods[ci] = int_downsample; + } else + ERREXIT(cinfo, JERR_FRACT_SAMPLE_NOTIMPL); + } + +#ifdef INPUT_SMOOTHING_SUPPORTED + if (cinfo->smoothing_factor && !smoothok) + TRACEMS(cinfo, 0, JTRC_SMOOTH_NOTIMPL); +#endif +} diff --git a/dcmjpeg/libijg8/jcscale.c b/dcmjpeg/libijg8/jcscale.c new file mode 100644 index 00000000..620ac3cf --- /dev/null +++ b/dcmjpeg/libijg8/jcscale.c @@ -0,0 +1,63 @@ +/* + * jcscale.c + * + * Copyright (C) 1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains sample downscaling by 2^Pt for lossless JPEG. + */ + +#define JPEG_INTERNALS +#include "jinclude8.h" +#include "jpeglib8.h" +#include "jlossls8.h" /* Private declarations for lossless codec */ + + +#ifdef C_LOSSLESS_SUPPORTED + +METHODDEF(void) +simple_downscale(j_compress_ptr cinfo, + JSAMPROW input_buf, JSAMPROW output_buf, JDIMENSION width) +{ + /* j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec; */ + unsigned int xindex; + SHIFT_TEMPS + + for (xindex = 0; xindex < width; xindex++) + output_buf[xindex] = (JSAMPLE) RIGHT_SHIFT(GETJSAMPLE(input_buf[xindex]), + cinfo->Al); +} + + +METHODDEF(void) +noscale(j_compress_ptr cinfo, + JSAMPROW input_buf, JSAMPROW output_buf, JDIMENSION width) +{ + MEMCOPY(output_buf, input_buf, width * SIZEOF(JSAMPLE)); + return; +} + + +METHODDEF(void) +scaler_start_pass (j_compress_ptr cinfo) +{ + j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec; + + /* Set scaler function based on Pt */ + if (cinfo->Al) + losslsc->scaler_scale = simple_downscale; + else + losslsc->scaler_scale = noscale; +} + + +GLOBAL(void) +jinit_c_scaler (j_compress_ptr cinfo) +{ + j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec; + + losslsc->scaler_start_pass = scaler_start_pass; +} + +#endif /* C_LOSSLESS_SUPPORTED */ diff --git a/dcmjpeg/libijg8/jcshuff.c b/dcmjpeg/libijg8/jcshuff.c new file mode 100644 index 00000000..0a55ced8 --- /dev/null +++ b/dcmjpeg/libijg8/jcshuff.c @@ -0,0 +1,661 @@ +/* + * jcshuff.c + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains Huffman entropy encoding routines for sequential JPEG. + * + * Much of the complexity here has to do with supporting output suspension. + * If the data destination module demands suspension, we want to be able to + * back up to the start of the current MCU. To do this, we copy state + * variables into local working storage, and update them back to the + * permanent JPEG objects only upon successful completion of an MCU. + */ + +#define JPEG_INTERNALS +#include "jinclude8.h" +#include "jpeglib8.h" +#include "jlossy8.h" /* Private declarations for lossy codec */ +#include "jchuff8.h" /* Declarations shared with jc*huff.c */ + + +/* Expanded entropy encoder object for Huffman encoding. + * + * The savable_state subrecord contains fields that change within an MCU, + * but must not be updated permanently until we complete the MCU. + */ + +typedef struct { + IJG_INT32 put_buffer; /* current bit-accumulation buffer */ + int put_bits; /* # of bits now in it */ + int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */ +} savable_state; + +/* This macro is to work around compilers with missing or broken + * structure assignment. You'll need to fix this code if you have + * such a compiler and you change MAX_COMPS_IN_SCAN. + */ + +#ifndef NO_STRUCT_ASSIGN +#define ASSIGN_STATE(dest,src) ((dest) = (src)) +#else +#if MAX_COMPS_IN_SCAN == 4 +#define ASSIGN_STATE(dest,src) \ + ((dest).put_buffer = (src).put_buffer, \ + (dest).put_bits = (src).put_bits, \ + (dest).last_dc_val[0] = (src).last_dc_val[0], \ + (dest).last_dc_val[1] = (src).last_dc_val[1], \ + (dest).last_dc_val[2] = (src).last_dc_val[2], \ + (dest).last_dc_val[3] = (src).last_dc_val[3]) +#endif +#endif + + +typedef struct { + savable_state saved; /* Bit buffer & DC state at start of MCU */ + + /* These fields are NOT loaded into local working state. */ + unsigned int restarts_to_go; /* MCUs left in this restart interval */ + int next_restart_num; /* next restart number to write (0-7) */ + + /* Pointers to derived tables (these workspaces have image lifespan) */ + c_derived_tbl * dc_derived_tbls[NUM_HUFF_TBLS]; + c_derived_tbl * ac_derived_tbls[NUM_HUFF_TBLS]; + +#ifdef ENTROPY_OPT_SUPPORTED /* Statistics tables for optimization */ + long * dc_count_ptrs[NUM_HUFF_TBLS]; + long * ac_count_ptrs[NUM_HUFF_TBLS]; +#endif +} shuff_entropy_encoder; + +typedef shuff_entropy_encoder * shuff_entropy_ptr; + +/* Working state while writing an MCU. + * This struct contains all the fields that are needed by subroutines. + */ + +typedef struct { + JOCTET * next_output_byte; /* => next byte to write in buffer */ + size_t free_in_buffer; /* # of byte spaces remaining in buffer */ + savable_state cur; /* Current bit buffer & DC state */ + j_compress_ptr cinfo; /* dump_buffer needs access to this */ +} working_state; + + +/* Forward declarations */ +METHODDEF(boolean) encode_mcu_huff JPP((j_compress_ptr cinfo, + JBLOCKROW *MCU_data)); +METHODDEF(void) finish_pass_huff JPP((j_compress_ptr cinfo)); +#ifdef ENTROPY_OPT_SUPPORTED +METHODDEF(boolean) encode_mcu_gather JPP((j_compress_ptr cinfo, + JBLOCKROW *MCU_data)); +METHODDEF(void) finish_pass_gather JPP((j_compress_ptr cinfo)); +#endif + + +/* + * Initialize for a Huffman-compressed scan. + * If gather_statistics is TRUE, we do not output anything during the scan, + * just count the Huffman symbols used and generate Huffman code tables. + */ + +METHODDEF(void) +start_pass_huff (j_compress_ptr cinfo, boolean gather_statistics) +{ + j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; + shuff_entropy_ptr entropy = (shuff_entropy_ptr) lossyc->entropy_private; + int ci, dctbl, actbl; + jpeg_component_info * compptr; + + if (gather_statistics) { +#ifdef ENTROPY_OPT_SUPPORTED + lossyc->entropy_encode_mcu = encode_mcu_gather; + lossyc->pub.entropy_finish_pass = finish_pass_gather; +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } else { + lossyc->entropy_encode_mcu = encode_mcu_huff; + lossyc->pub.entropy_finish_pass = finish_pass_huff; + } + + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + dctbl = compptr->dc_tbl_no; + actbl = compptr->ac_tbl_no; + if (gather_statistics) { +#ifdef ENTROPY_OPT_SUPPORTED + /* Check for invalid table indexes */ + /* (make_c_derived_tbl does this in the other path) */ + if (dctbl < 0 || dctbl >= NUM_HUFF_TBLS) + ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, dctbl); + if (actbl < 0 || actbl >= NUM_HUFF_TBLS) + ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, actbl); + /* Allocate and zero the statistics tables */ + /* Note that jpeg_gen_optimal_table expects 257 entries in each table! */ + if (entropy->dc_count_ptrs[dctbl] == NULL) + entropy->dc_count_ptrs[dctbl] = (long *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + 257 * SIZEOF(long)); + MEMZERO(entropy->dc_count_ptrs[dctbl], 257 * SIZEOF(long)); + if (entropy->ac_count_ptrs[actbl] == NULL) + entropy->ac_count_ptrs[actbl] = (long *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + 257 * SIZEOF(long)); + MEMZERO(entropy->ac_count_ptrs[actbl], 257 * SIZEOF(long)); +#endif + } else { + /* Compute derived values for Huffman tables */ + /* We may do this more than once for a table, but it's not expensive */ + jpeg_make_c_derived_tbl(cinfo, TRUE, dctbl, + & entropy->dc_derived_tbls[dctbl]); + jpeg_make_c_derived_tbl(cinfo, FALSE, actbl, + & entropy->ac_derived_tbls[actbl]); + } + /* Initialize DC predictions to 0 */ + entropy->saved.last_dc_val[ci] = 0; + } + + /* Initialize bit buffer to empty */ + entropy->saved.put_buffer = 0; + entropy->saved.put_bits = 0; + + /* Initialize restart stuff */ + entropy->restarts_to_go = cinfo->restart_interval; + entropy->next_restart_num = 0; +} + + +/* Outputting bytes to the file */ + +/* Emit a byte, taking 'action' if must suspend. */ +#define emit_byte(state,val,action) \ + { *(state)->next_output_byte++ = (JOCTET) (val); \ + if (--(state)->free_in_buffer == 0) \ + if (! dump_buffer(state)) \ + { action; } } + + +LOCAL(boolean) +dump_buffer (working_state * state) +/* Empty the output buffer; return TRUE if successful, FALSE if must suspend */ +{ + struct jpeg_destination_mgr * dest = state->cinfo->dest; + + if (! (*dest->empty_output_buffer) (state->cinfo)) + return FALSE; + /* After a successful buffer dump, must reset buffer pointers */ + state->next_output_byte = dest->next_output_byte; + state->free_in_buffer = dest->free_in_buffer; + return TRUE; +} + + +/* Outputting bits to the file */ + +/* Only the right 24 bits of put_buffer are used; the valid bits are + * left-justified in this part. At most 16 bits can be passed to emit_bits + * in one call, and we never retain more than 7 bits in put_buffer + * between calls, so 24 bits are sufficient. + */ + +INLINE +LOCAL(boolean) +emit_bits (working_state * state, unsigned int code, int size) +/* Emit some bits; return TRUE if successful, FALSE if must suspend */ +{ + /* This routine is heavily used, so it's worth coding tightly. */ + register IJG_INT32 put_buffer = (IJG_INT32) code; + register int put_bits = state->cur.put_bits; + + /* if size is 0, caller used an invalid Huffman table entry */ + if (size == 0) + ERREXIT(state->cinfo, JERR_HUFF_MISSING_CODE); + + put_buffer &= (((IJG_INT32) 1)<cur.put_buffer; /* and merge with old buffer contents */ + + while (put_bits >= 8) { + int c = (int) ((put_buffer >> 16) & 0xFF); + + emit_byte(state, c, return FALSE); + if (c == 0xFF) { /* need to stuff a zero byte? */ + emit_byte(state, 0, return FALSE); + } + put_buffer <<= 8; + put_bits -= 8; + } + + state->cur.put_buffer = put_buffer; /* update state variables */ + state->cur.put_bits = put_bits; + + return TRUE; +} + + +LOCAL(boolean) +flush_bits (working_state * state) +{ + if (! emit_bits(state, 0x7F, 7)) /* fill any partial byte with ones */ + return FALSE; + state->cur.put_buffer = 0; /* and reset bit-buffer to empty */ + state->cur.put_bits = 0; + return TRUE; +} + + +/* Encode a single block's worth of coefficients */ + +LOCAL(boolean) +encode_one_block (working_state * state, JCOEFPTR block, int last_dc_val, + c_derived_tbl *dctbl, c_derived_tbl *actbl) +{ + register int temp, temp2; + register int nbits; + register int k, r, i; + + /* Encode the DC coefficient difference per section F.1.2.1 */ + + temp = temp2 = block[0] - last_dc_val; + + if (temp < 0) { + temp = -temp; /* temp is abs value of input */ + /* For a negative input, want temp2 = bitwise complement of abs(input) */ + /* This code assumes we are on a two's complement machine */ + temp2--; + } + + /* Find the number of bits needed for the magnitude of the coefficient */ + nbits = 0; + while (temp) { + nbits++; + temp >>= 1; + } + /* Check for out-of-range coefficient values. + * Since we're encoding a difference, the range limit is twice as much. + */ + if (nbits > MAX_COEF_BITS+1) + ERREXIT(state->cinfo, JERR_BAD_DCT_COEF); + + /* Emit the Huffman-coded symbol for the number of bits */ + if (! emit_bits(state, dctbl->ehufco[nbits], dctbl->ehufsi[nbits])) + return FALSE; + + /* Emit that number of bits of the value, if positive, */ + /* or the complement of its magnitude, if negative. */ + if (nbits) /* emit_bits rejects calls with size 0 */ + if (! emit_bits(state, (unsigned int) temp2, nbits)) + return FALSE; + + /* Encode the AC coefficients per section F.1.2.2 */ + + r = 0; /* r = run length of zeros */ + + for (k = 1; k < DCTSIZE2; k++) { + if ((temp = block[jpeg_natural_order[k]]) == 0) { + r++; + } else { + /* if run length > 15, must emit special run-length-16 codes (0xF0) */ + while (r > 15) { + if (! emit_bits(state, actbl->ehufco[0xF0], actbl->ehufsi[0xF0])) + return FALSE; + r -= 16; + } + + temp2 = temp; + if (temp < 0) { + temp = -temp; /* temp is abs value of input */ + /* This code assumes we are on a two's complement machine */ + temp2--; + } + + /* Find the number of bits needed for the magnitude of the coefficient */ + nbits = 1; /* there must be at least one 1 bit */ + while ((temp >>= 1)) + nbits++; + /* Check for out-of-range coefficient values */ + if (nbits > MAX_COEF_BITS) + ERREXIT(state->cinfo, JERR_BAD_DCT_COEF); + + /* Emit Huffman symbol for run length / number of bits */ + i = (r << 4) + nbits; + if (! emit_bits(state, actbl->ehufco[i], actbl->ehufsi[i])) + return FALSE; + + /* Emit that number of bits of the value, if positive, */ + /* or the complement of its magnitude, if negative. */ + if (! emit_bits(state, (unsigned int) temp2, nbits)) + return FALSE; + + r = 0; + } + } + + /* If the last coef(s) were zero, emit an end-of-block code */ + if (r > 0) + if (! emit_bits(state, actbl->ehufco[0], actbl->ehufsi[0])) + return FALSE; + + return TRUE; +} + + +/* + * Emit a restart marker & resynchronize predictions. + */ + +LOCAL(boolean) +emit_restart (working_state * state, int restart_num) +{ + int ci; + + if (! flush_bits(state)) + return FALSE; + + emit_byte(state, 0xFF, return FALSE); + emit_byte(state, JPEG_RST0 + restart_num, return FALSE); + + /* Re-initialize DC predictions to 0 */ + for (ci = 0; ci < state->cinfo->comps_in_scan; ci++) + state->cur.last_dc_val[ci] = 0; + + /* The restart counter is not updated until we successfully write the MCU. */ + + return TRUE; +} + + +/* + * Encode and output one MCU's worth of Huffman-compressed coefficients. + */ + +METHODDEF(boolean) +encode_mcu_huff (j_compress_ptr cinfo, JBLOCKROW *MCU_data) +{ + j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; + shuff_entropy_ptr entropy = (shuff_entropy_ptr) lossyc->entropy_private; + working_state state; + int blkn, ci; + jpeg_component_info * compptr; + + /* Load up working state */ + state.next_output_byte = cinfo->dest->next_output_byte; + state.free_in_buffer = cinfo->dest->free_in_buffer; + ASSIGN_STATE(state.cur, entropy->saved); + state.cinfo = cinfo; + + /* Emit restart marker if needed */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) + if (! emit_restart(&state, entropy->next_restart_num)) + return FALSE; + } + + /* Encode the MCU data blocks */ + for (blkn = 0; blkn < cinfo->data_units_in_MCU; blkn++) { + ci = cinfo->MCU_membership[blkn]; + compptr = cinfo->cur_comp_info[ci]; + if (! encode_one_block(&state, + MCU_data[blkn][0], state.cur.last_dc_val[ci], + entropy->dc_derived_tbls[compptr->dc_tbl_no], + entropy->ac_derived_tbls[compptr->ac_tbl_no])) + return FALSE; + /* Update last_dc_val */ + state.cur.last_dc_val[ci] = MCU_data[blkn][0][0]; + } + + /* Completed MCU, so update state */ + cinfo->dest->next_output_byte = state.next_output_byte; + cinfo->dest->free_in_buffer = state.free_in_buffer; + ASSIGN_STATE(entropy->saved, state.cur); + + /* Update restart-interval state too */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) { + entropy->restarts_to_go = cinfo->restart_interval; + entropy->next_restart_num++; + entropy->next_restart_num &= 7; + } + entropy->restarts_to_go--; + } + + return TRUE; +} + + +/* + * Finish up at the end of a Huffman-compressed scan. + */ + +METHODDEF(void) +finish_pass_huff (j_compress_ptr cinfo) +{ + j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; + shuff_entropy_ptr entropy = (shuff_entropy_ptr) lossyc->entropy_private; + working_state state; + + /* Load up working state ... flush_bits needs it */ + state.next_output_byte = cinfo->dest->next_output_byte; + state.free_in_buffer = cinfo->dest->free_in_buffer; + ASSIGN_STATE(state.cur, entropy->saved); + state.cinfo = cinfo; + + /* Flush out the last data */ + if (! flush_bits(&state)) + ERREXIT(cinfo, JERR_CANT_SUSPEND); + + /* Update state */ + cinfo->dest->next_output_byte = state.next_output_byte; + cinfo->dest->free_in_buffer = state.free_in_buffer; + ASSIGN_STATE(entropy->saved, state.cur); +} + + +/* + * Huffman coding optimization. + * + * We first scan the supplied data and count the number of uses of each symbol + * that is to be Huffman-coded. (This process MUST agree with the code above.) + * Then we build a Huffman coding tree for the observed counts. + * Symbols which are not needed at all for the particular image are not + * assigned any code, which saves space in the DHT marker as well as in + * the compressed data. + */ + +#ifdef ENTROPY_OPT_SUPPORTED + + +/* Process a single block's worth of coefficients */ + +LOCAL(void) +htest_one_block (j_compress_ptr cinfo, JCOEFPTR block, int last_dc_val, + long dc_counts[], long ac_counts[]) +{ + register int temp; + register int nbits; + register int k, r; + + /* Encode the DC coefficient difference per section F.1.2.1 */ + + temp = block[0] - last_dc_val; + if (temp < 0) + temp = -temp; + + /* Find the number of bits needed for the magnitude of the coefficient */ + nbits = 0; + while (temp) { + nbits++; + temp >>= 1; + } + /* Check for out-of-range coefficient values. + * Since we're encoding a difference, the range limit is twice as much. + */ + if (nbits > MAX_COEF_BITS+1) + ERREXIT(cinfo, JERR_BAD_DCT_COEF); + + /* Count the Huffman symbol for the number of bits */ + dc_counts[nbits]++; + + /* Encode the AC coefficients per section F.1.2.2 */ + + r = 0; /* r = run length of zeros */ + + for (k = 1; k < DCTSIZE2; k++) { + if ((temp = block[jpeg_natural_order[k]]) == 0) { + r++; + } else { + /* if run length > 15, must emit special run-length-16 codes (0xF0) */ + while (r > 15) { + ac_counts[0xF0]++; + r -= 16; + } + + /* Find the number of bits needed for the magnitude of the coefficient */ + if (temp < 0) + temp = -temp; + + /* Find the number of bits needed for the magnitude of the coefficient */ + nbits = 1; /* there must be at least one 1 bit */ + while ((temp >>= 1)) + nbits++; + /* Check for out-of-range coefficient values */ + if (nbits > MAX_COEF_BITS) + ERREXIT(cinfo, JERR_BAD_DCT_COEF); + + /* Count Huffman symbol for run length / number of bits */ + ac_counts[(r << 4) + nbits]++; + + r = 0; + } + } + + /* If the last coef(s) were zero, emit an end-of-block code */ + if (r > 0) + ac_counts[0]++; +} + + +/* + * Trial-encode one MCU's worth of Huffman-compressed coefficients. + * No data is actually output, so no suspension return is possible. + */ + +METHODDEF(boolean) +encode_mcu_gather (j_compress_ptr cinfo, JBLOCKROW *MCU_data) +{ + j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; + shuff_entropy_ptr entropy = (shuff_entropy_ptr) lossyc->entropy_private; + int blkn, ci; + jpeg_component_info * compptr; + + /* Take care of restart intervals if needed */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) { + /* Re-initialize DC predictions to 0 */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) + entropy->saved.last_dc_val[ci] = 0; + /* Update restart state */ + entropy->restarts_to_go = cinfo->restart_interval; + } + entropy->restarts_to_go--; + } + + for (blkn = 0; blkn < cinfo->data_units_in_MCU; blkn++) { + ci = cinfo->MCU_membership[blkn]; + compptr = cinfo->cur_comp_info[ci]; + htest_one_block(cinfo, MCU_data[blkn][0], entropy->saved.last_dc_val[ci], + entropy->dc_count_ptrs[compptr->dc_tbl_no], + entropy->ac_count_ptrs[compptr->ac_tbl_no]); + entropy->saved.last_dc_val[ci] = MCU_data[blkn][0][0]; + } + + return TRUE; +} + + +/* + * Finish up a statistics-gathering pass and create the new Huffman tables. + */ + +METHODDEF(void) +finish_pass_gather (j_compress_ptr cinfo) +{ + j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; + shuff_entropy_ptr entropy = (shuff_entropy_ptr) lossyc->entropy_private; + int ci, dctbl, actbl; + jpeg_component_info * compptr; + JHUFF_TBL **htblptr; + boolean did_dc[NUM_HUFF_TBLS]; + boolean did_ac[NUM_HUFF_TBLS]; + + /* It's important not to apply jpeg_gen_optimal_table more than once + * per table, because it clobbers the input frequency counts! + */ + MEMZERO(did_dc, SIZEOF(did_dc)); + MEMZERO(did_ac, SIZEOF(did_ac)); + + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + dctbl = compptr->dc_tbl_no; + actbl = compptr->ac_tbl_no; + if (! did_dc[dctbl]) { + htblptr = & cinfo->dc_huff_tbl_ptrs[dctbl]; + if (*htblptr == NULL) + *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo); + jpeg_gen_optimal_table(cinfo, *htblptr, entropy->dc_count_ptrs[dctbl]); + did_dc[dctbl] = TRUE; + } + if (! did_ac[actbl]) { + htblptr = & cinfo->ac_huff_tbl_ptrs[actbl]; + if (*htblptr == NULL) + *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo); + jpeg_gen_optimal_table(cinfo, *htblptr, entropy->ac_count_ptrs[actbl]); + did_ac[actbl] = TRUE; + } + } +} + + +#endif /* ENTROPY_OPT_SUPPORTED */ + + +METHODDEF(boolean) +need_optimization_pass (j_compress_ptr cinfo) +{ + return TRUE; +} + + +/* + * Module initialization routine for Huffman entropy encoding. + */ + +GLOBAL(void) +jinit_shuff_encoder (j_compress_ptr cinfo) +{ + j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; + shuff_entropy_ptr entropy; + int i; + + entropy = (shuff_entropy_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(shuff_entropy_encoder)); + lossyc->entropy_private = (struct jpeg_entropy_encoder *) entropy; + lossyc->pub.entropy_start_pass = start_pass_huff; + lossyc->pub.need_optimization_pass = need_optimization_pass; + + /* Mark tables unallocated */ + for (i = 0; i < NUM_HUFF_TBLS; i++) { + entropy->dc_derived_tbls[i] = entropy->ac_derived_tbls[i] = NULL; +#ifdef ENTROPY_OPT_SUPPORTED + entropy->dc_count_ptrs[i] = entropy->ac_count_ptrs[i] = NULL; +#endif + } +} diff --git a/dcmjpeg/libijg8/jctrans.c b/dcmjpeg/libijg8/jctrans.c new file mode 100644 index 00000000..902401b1 --- /dev/null +++ b/dcmjpeg/libijg8/jctrans.c @@ -0,0 +1,424 @@ +/* + * jctrans.c + * + * Copyright (C) 1995-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains library routines for transcoding compression, + * that is, writing raw DCT coefficient arrays to an output JPEG file. + * The routines in jcapimin.c will also be needed by a transcoder. + */ + +#define JPEG_INTERNALS +#include "jinclude8.h" +#include "jpeglib8.h" +#include "jlossy8.h" /* Private declarations for lossy codec */ + + +/* Forward declarations */ +LOCAL(void) transencode_master_selection + JPP((j_compress_ptr cinfo, jvirt_barray_ptr * coef_arrays)); +LOCAL(void) transencode_codec + JPP((j_compress_ptr cinfo, jvirt_barray_ptr * coef_arrays)); +LOCAL(void) transencode_coef_controller + JPP((j_compress_ptr cinfo, jvirt_barray_ptr * coef_arrays)); + + +/* + * Compression initialization for writing raw-coefficient data. + * Before calling this, all parameters and a data destination must be set up. + * Call jpeg_finish_compress() to actually write the data. + * + * The number of passed virtual arrays must match cinfo->num_components. + * Note that the virtual arrays need not be filled or even realized at + * the time write_coefficients is called; indeed, if the virtual arrays + * were requested from this compression object's memory manager, they + * typically will be realized during this routine and filled afterwards. + */ + +GLOBAL(void) +jpeg_write_coefficients (j_compress_ptr cinfo, jvirt_barray_ptr * coef_arrays) +{ + if (cinfo->global_state != CSTATE_START) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + /* Mark all tables to be written */ + jpeg_suppress_tables(cinfo, FALSE); + /* (Re)initialize error mgr and destination modules */ + (*cinfo->err->reset_error_mgr) ((j_common_ptr) cinfo); + (*cinfo->dest->init_destination) (cinfo); + /* Perform master selection of active modules */ + transencode_master_selection(cinfo, coef_arrays); + /* Wait for jpeg_finish_compress() call */ + cinfo->next_scanline = 0; /* so jpeg_write_marker works */ + cinfo->global_state = CSTATE_WRCOEFS; +} + + +/* + * Initialize the compression object with default parameters, + * then copy from the source object all parameters needed for lossless + * transcoding. Parameters that can be varied without loss (such as + * scan script and Huffman optimization) are left in their default states. + */ + +GLOBAL(void) +jpeg_copy_critical_parameters (j_decompress_ptr srcinfo, + j_compress_ptr dstinfo) +{ + JQUANT_TBL ** qtblptr; + jpeg_component_info *incomp, *outcomp; + JQUANT_TBL *c_quant, *slot_quant; + int tblno, ci, coefi; + + /* Safety check to ensure start_compress not called yet. */ + if (dstinfo->global_state != CSTATE_START) + ERREXIT1(dstinfo, JERR_BAD_STATE, dstinfo->global_state); + /* Copy fundamental image dimensions */ + dstinfo->image_width = srcinfo->image_width; + dstinfo->image_height = srcinfo->image_height; + dstinfo->input_components = srcinfo->num_components; + dstinfo->in_color_space = srcinfo->jpeg_color_space; + /* Initialize all parameters to default values */ + jpeg_set_defaults(dstinfo); + /* jpeg_set_defaults may choose wrong colorspace, eg YCbCr if input is RGB. + * Fix it to get the right header markers for the image colorspace. + */ + jpeg_set_colorspace(dstinfo, srcinfo->jpeg_color_space); + dstinfo->data_precision = srcinfo->data_precision; + dstinfo->CCIR601_sampling = srcinfo->CCIR601_sampling; + /* Copy the source's quantization tables. */ + for (tblno = 0; tblno < NUM_QUANT_TBLS; tblno++) { + if (srcinfo->quant_tbl_ptrs[tblno] != NULL) { + qtblptr = & dstinfo->quant_tbl_ptrs[tblno]; + if (*qtblptr == NULL) + *qtblptr = jpeg_alloc_quant_table((j_common_ptr) dstinfo); + MEMCOPY((*qtblptr)->quantval, + srcinfo->quant_tbl_ptrs[tblno]->quantval, + SIZEOF((*qtblptr)->quantval)); + (*qtblptr)->sent_table = FALSE; + } + } + /* Copy the source's per-component info. + * Note we assume jpeg_set_defaults has allocated the dest comp_info array. + */ + dstinfo->num_components = srcinfo->num_components; + if (dstinfo->num_components < 1 || dstinfo->num_components > MAX_COMPONENTS) + ERREXIT2(dstinfo, JERR_COMPONENT_COUNT, dstinfo->num_components, + MAX_COMPONENTS); + for (ci = 0, incomp = srcinfo->comp_info, outcomp = dstinfo->comp_info; + ci < dstinfo->num_components; ci++, incomp++, outcomp++) { + outcomp->component_id = incomp->component_id; + outcomp->h_samp_factor = incomp->h_samp_factor; + outcomp->v_samp_factor = incomp->v_samp_factor; + outcomp->quant_tbl_no = incomp->quant_tbl_no; + /* Make sure saved quantization table for component matches the qtable + * slot. If not, the input file re-used this qtable slot. + * IJG encoder currently cannot duplicate this. + */ + tblno = outcomp->quant_tbl_no; + if (tblno < 0 || tblno >= NUM_QUANT_TBLS || + srcinfo->quant_tbl_ptrs[tblno] == NULL) + ERREXIT1(dstinfo, JERR_NO_QUANT_TABLE, tblno); + slot_quant = srcinfo->quant_tbl_ptrs[tblno]; + c_quant = incomp->quant_table; + if (c_quant != NULL) { + for (coefi = 0; coefi < DCTSIZE2; coefi++) { + if (c_quant->quantval[coefi] != slot_quant->quantval[coefi]) + ERREXIT1(dstinfo, JERR_MISMATCHED_QUANT_TABLE, tblno); + } + } + /* Note: we do not copy the source's Huffman table assignments; + * instead we rely on jpeg_set_colorspace to have made a suitable choice. + */ + } + /* Also copy JFIF version and resolution information, if available. + * Strictly speaking this isn't "critical" info, but it's nearly + * always appropriate to copy it if available. In particular, + * if the application chooses to copy JFIF 1.02 extension markers from + * the source file, we need to copy the version to make sure we don't + * emit a file that has 1.02 extensions but a claimed version of 1.01. + * We will *not*, however, copy version info from mislabeled "2.01" files. + */ + if (srcinfo->saw_JFIF_marker) { + if (srcinfo->JFIF_major_version == 1) { + dstinfo->JFIF_major_version = srcinfo->JFIF_major_version; + dstinfo->JFIF_minor_version = srcinfo->JFIF_minor_version; + } + dstinfo->density_unit = srcinfo->density_unit; + dstinfo->X_density = srcinfo->X_density; + dstinfo->Y_density = srcinfo->Y_density; + } +} + + +/* + * Master selection of compression modules for transcoding. + * This substitutes for jcinit.c's initialization of the full compressor. + */ + +LOCAL(void) +transencode_master_selection (j_compress_ptr cinfo, + jvirt_barray_ptr * coef_arrays) +{ + cinfo->data_unit = DCTSIZE; + /* Although we don't actually use input_components for transcoding, + * jcmaster.c's initial_setup will complain if input_components is 0. + */ + cinfo->input_components = 1; + /* Initialize master control (includes parameter checking/processing) */ + jinit_c_master_control(cinfo, TRUE /* transcode only */); + + /* We need a special compression codec. */ + transencode_codec(cinfo, coef_arrays); + + jinit_marker_writer(cinfo); + + /* We can now tell the memory manager to allocate virtual arrays. */ + (*cinfo->mem->realize_virt_arrays) ((j_common_ptr) cinfo); + + /* Write the datastream header (SOI, JFIF) immediately. + * Frame and scan headers are postponed till later. + * This lets application insert special markers after the SOI. + */ + (*cinfo->marker->write_file_header) (cinfo); +} + + +/* + * The rest of this file is a special implementation of the coefficient + * buffer controller. This is similar to jccoefct.c, but it handles only + * output from presupplied virtual arrays. Furthermore, we generate any + * dummy padding blocks on-the-fly rather than expecting them to be present + * in the arrays. + */ + +/* Private buffer controller object */ + +typedef struct { + JDIMENSION iMCU_row_num; /* iMCU row # within image */ + JDIMENSION mcu_ctr; /* counts MCUs processed in current row */ + int MCU_vert_offset; /* counts MCU rows within iMCU row */ + int MCU_rows_per_iMCU_row; /* number of such rows needed */ + + /* Virtual block array for each component. */ + jvirt_barray_ptr * whole_image; + + /* Workspace for constructing dummy blocks at right/bottom edges. */ + JBLOCKROW dummy_buffer[C_MAX_DATA_UNITS_IN_MCU]; +} c_coef_controller; + +typedef c_coef_controller * c_coef_ptr; + + +LOCAL(void) +start_iMCU_row (j_compress_ptr cinfo) +/* Reset within-iMCU-row counters for a new row */ +{ + j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; + c_coef_ptr coef = (c_coef_ptr) lossyc->coef_private; + + /* In an interleaved scan, an MCU row is the same as an iMCU row. + * In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows. + * But at the bottom of the image, process only what's left. + */ + if (cinfo->comps_in_scan > 1) { + coef->MCU_rows_per_iMCU_row = 1; + } else { + if (coef->iMCU_row_num < (cinfo->total_iMCU_rows-1)) + coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->v_samp_factor; + else + coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->last_row_height; + } + + coef->mcu_ctr = 0; + coef->MCU_vert_offset = 0; +} + + +/* + * Initialize for a processing pass. + */ + +METHODDEF(void) +start_pass_coef (j_compress_ptr cinfo, J_BUF_MODE pass_mode) +{ + j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; + c_coef_ptr coef = (c_coef_ptr) lossyc->coef_private; + + if (pass_mode != JBUF_CRANK_DEST) + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + + coef->iMCU_row_num = 0; + start_iMCU_row(cinfo); +} + + +/* + * Process some data. + * We process the equivalent of one fully interleaved MCU row ("iMCU" row) + * per call, ie, v_samp_factor block rows for each component in the scan. + * The data is obtained from the virtual arrays and fed to the entropy coder. + * Returns TRUE if the iMCU row is completed, FALSE if suspended. + * + * NB: input_buf is ignored; it is likely to be a NULL pointer. + */ + +METHODDEF(boolean) +compress_output (j_compress_ptr cinfo, JSAMPIMAGE input_buf) +{ + j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; + c_coef_ptr coef = (c_coef_ptr) lossyc->coef_private; + JDIMENSION MCU_col_num; /* index of current MCU within row */ + JDIMENSION last_MCU_col = cinfo->MCUs_per_row - 1; + JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; + int blkn, ci, xindex, yindex, yoffset, blockcnt; + JDIMENSION start_col; + JBLOCKARRAY buffer[MAX_COMPS_IN_SCAN]; + JBLOCKROW MCU_buffer[C_MAX_DATA_UNITS_IN_MCU]; + JBLOCKROW buffer_ptr; + jpeg_component_info *compptr; + + /* Align the virtual buffers for the components used in this scan. */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + buffer[ci] = (*cinfo->mem->access_virt_barray) + ((j_common_ptr) cinfo, coef->whole_image[compptr->component_index], + coef->iMCU_row_num * (JDIMENSION) compptr->v_samp_factor, + (JDIMENSION) compptr->v_samp_factor, FALSE); + } + + /* Loop to process one whole iMCU row */ + for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row; + yoffset++) { + for (MCU_col_num = coef->mcu_ctr; MCU_col_num < cinfo->MCUs_per_row; + MCU_col_num++) { + /* Construct list of pointers to DCT blocks belonging to this MCU */ + blkn = 0; /* index of current DCT block within MCU */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + start_col = MCU_col_num * (JDIMENSION)compptr->MCU_width; + blockcnt = (MCU_col_num < last_MCU_col) ? compptr->MCU_width + : compptr->last_col_width; + for (yindex = 0; yindex < compptr->MCU_height; yindex++) { + if (coef->iMCU_row_num < last_iMCU_row || + yindex+yoffset < compptr->last_row_height) { + /* Fill in pointers to real blocks in this row */ + buffer_ptr = buffer[ci][yindex+yoffset] + start_col; + for (xindex = 0; xindex < blockcnt; xindex++) + MCU_buffer[blkn++] = buffer_ptr++; + } else { + /* At bottom of image, need a whole row of dummy blocks */ + xindex = 0; + } + /* Fill in any dummy blocks needed in this row. + * Dummy blocks are filled in the same way as in jccoefct.c: + * all zeroes in the AC entries, DC entries equal to previous + * block's DC value. The init routine has already zeroed the + * AC entries, so we need only set the DC entries correctly. + */ + for (; xindex < compptr->MCU_width; xindex++) { + MCU_buffer[blkn] = coef->dummy_buffer[blkn]; + MCU_buffer[blkn][0][0] = MCU_buffer[blkn-1][0][0]; + blkn++; + } + } + } + /* Try to write the MCU. */ + if (! (*lossyc->entropy_encode_mcu) (cinfo, MCU_buffer)) { + /* Suspension forced; update state counters and exit */ + coef->MCU_vert_offset = yoffset; + coef->mcu_ctr = MCU_col_num; + return FALSE; + } + } + /* Completed an MCU row, but perhaps not an iMCU row */ + coef->mcu_ctr = 0; + } + /* Completed the iMCU row, advance counters for next one */ + coef->iMCU_row_num++; + start_iMCU_row(cinfo); + return TRUE; +} + + +/* + * Initialize coefficient buffer controller. + * + * Each passed coefficient array must be the right size for that + * coefficient: width_in_data_units wide and height_in_data_units high, + * with unitheight at least v_samp_factor. + */ + +LOCAL(void) +transencode_coef_controller (j_compress_ptr cinfo, + jvirt_barray_ptr * coef_arrays) +{ + j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; + c_coef_ptr coef; + JBLOCKROW buffer; + int i; + + coef = (c_coef_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(c_coef_controller)); + lossyc->coef_private = (struct jpeg_c_coef_controller *) coef; + + /* Save pointer to virtual arrays */ + coef->whole_image = coef_arrays; + + /* Allocate and pre-zero space for dummy DCT blocks. */ + buffer = (JBLOCKROW) + (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE, + C_MAX_DATA_UNITS_IN_MCU * SIZEOF(JBLOCK)); + jzero_far((void FAR *) buffer, C_MAX_DATA_UNITS_IN_MCU * SIZEOF(JBLOCK)); + for (i = 0; i < C_MAX_DATA_UNITS_IN_MCU; i++) { + coef->dummy_buffer[i] = buffer + i; + } +} + + +/* + * Initialize the transencoer codec. + * This is called only once, during master selection. + */ + +LOCAL(void) +transencode_codec (j_compress_ptr cinfo, + jvirt_barray_ptr * coef_arrays) +{ + j_lossy_c_ptr lossyc; + + /* Create subobject in permanent pool */ + lossyc = (j_lossy_c_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, + SIZEOF(jpeg_lossy_c_codec)); + cinfo->codec = (struct jpeg_c_codec *) lossyc; + + /* Initialize sub-modules */ + + /* Entropy encoding: either Huffman or arithmetic coding. */ + if (cinfo->arith_code) { +#ifdef WITH_ARITHMETIC_PATCH + jinit_arith_encoder(cinfo); +#else + ERREXIT(cinfo, JERR_ARITH_NOTIMPL); +#endif + } else { + if (cinfo->process == JPROC_PROGRESSIVE) { +#ifdef C_PROGRESSIVE_SUPPORTED + jinit_phuff_encoder(cinfo); +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } else + jinit_shuff_encoder(cinfo); + } + + /* We need a special coefficient buffer controller. */ + transencode_coef_controller(cinfo, coef_arrays); + + /* Initialize method pointers */ + lossyc->pub.start_pass = start_pass_coef; + lossyc->pub.compress_data = compress_output; +} diff --git a/dcmjpeg/libijg8/jdapimin.c b/dcmjpeg/libijg8/jdapimin.c new file mode 100644 index 00000000..3935c324 --- /dev/null +++ b/dcmjpeg/libijg8/jdapimin.c @@ -0,0 +1,401 @@ +/* + * jdapimin.c + * + * Copyright (C) 1994-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains application interface code for the decompression half + * of the JPEG library. These are the "minimum" API routines that may be + * needed in either the normal full-decompression case or the + * transcoding-only case. + * + * Most of the routines intended to be called directly by an application + * are in this file or in jdapistd.c. But also see jcomapi.c for routines + * shared by compression and decompression, and jdtrans.c for the transcoding + * case. + */ + +#define JPEG_INTERNALS +#include "jinclude8.h" +#include "jpeglib8.h" + + +/* + * Initialization of a JPEG decompression object. + * The error manager must already be set up (in case memory manager fails). + */ + +GLOBAL(void) +jpeg_CreateDecompress (j_decompress_ptr cinfo, int version, size_t structsize) +{ + int i; + + /* Guard against version mismatches between library and caller. */ + cinfo->mem = NULL; /* so jpeg_destroy knows mem mgr not called */ + if (version != JPEG_LIB_VERSION) + ERREXIT2(cinfo, JERR_BAD_LIB_VERSION, JPEG_LIB_VERSION, version); + if (structsize != SIZEOF(struct jpeg_decompress_struct)) + ERREXIT2(cinfo, JERR_BAD_STRUCT_SIZE, + (int) SIZEOF(struct jpeg_decompress_struct), (int) structsize); + + /* For debugging purposes, we zero the whole master structure. + * But the application has already set the err pointer, and may have set + * client_data, so we have to save and restore those fields. + * Note: if application hasn't set client_data, tools like Purify may + * complain here. + */ + { + struct jpeg_error_mgr * err = cinfo->err; + void * client_data = cinfo->client_data; /* ignore Purify complaint here */ + MEMZERO(cinfo, SIZEOF(struct jpeg_decompress_struct)); + cinfo->err = err; + cinfo->client_data = client_data; + } + cinfo->is_decompressor = TRUE; + + /* Initialize a memory manager instance for this object */ + jinit_memory_mgr((j_common_ptr) cinfo); + + /* Zero out pointers to permanent structures. */ + cinfo->progress = NULL; + cinfo->src = NULL; + + for (i = 0; i < NUM_QUANT_TBLS; i++) + cinfo->quant_tbl_ptrs[i] = NULL; + + for (i = 0; i < NUM_HUFF_TBLS; i++) { + cinfo->dc_huff_tbl_ptrs[i] = NULL; + cinfo->ac_huff_tbl_ptrs[i] = NULL; + } + + /* Initialize marker processor so application can override methods + * for COM, APPn markers before calling jpeg_read_header. + */ + cinfo->marker_list = NULL; + jinit_marker_reader(cinfo); + + /* And initialize the overall input controller. */ + jinit_input_controller(cinfo); + + /* OK, I'm ready */ + cinfo->global_state = DSTATE_START; +} + + +/* + * Destruction of a JPEG decompression object + */ + +GLOBAL(void) +jpeg_destroy_decompress (j_decompress_ptr cinfo) +{ + jpeg_destroy((j_common_ptr) cinfo); /* use common routine */ +} + + +/* + * Abort processing of a JPEG decompression operation, + * but don't destroy the object itself. + */ + +GLOBAL(void) +jpeg_abort_decompress (j_decompress_ptr cinfo) +{ + jpeg_abort((j_common_ptr) cinfo); /* use common routine */ +} + + +/* + * Set default decompression parameters. + */ + +LOCAL(void) +default_decompress_parms (j_decompress_ptr cinfo) +{ + /* Guess the input colorspace, and set output colorspace accordingly. */ + /* (Wish JPEG committee had provided a real way to specify this...) */ + /* Note application may override our guesses. */ + switch (cinfo->num_components) { + case 1: + cinfo->jpeg_color_space = JCS_GRAYSCALE; + cinfo->out_color_space = JCS_GRAYSCALE; + break; + + case 3: + if (cinfo->saw_JFIF_marker) { + cinfo->jpeg_color_space = JCS_YCbCr; /* JFIF implies YCbCr */ + } else if (cinfo->saw_Adobe_marker) { + switch (cinfo->Adobe_transform) { + case 0: + cinfo->jpeg_color_space = JCS_RGB; + break; + case 1: + cinfo->jpeg_color_space = JCS_YCbCr; + break; + default: + WARNMS1(cinfo, JWRN_ADOBE_XFORM, cinfo->Adobe_transform); + cinfo->jpeg_color_space = JCS_YCbCr; /* assume it's YCbCr */ + break; + } + } else { + /* Saw no special markers, try to guess from the component IDs */ + int cid0 = cinfo->comp_info[0].component_id; + int cid1 = cinfo->comp_info[1].component_id; + int cid2 = cinfo->comp_info[2].component_id; + + if (cid0 == 1 && cid1 == 2 && cid2 == 3) + cinfo->jpeg_color_space = JCS_YCbCr; /* assume JFIF w/out marker */ + else if (cid0 == 82 && cid1 == 71 && cid2 == 66) + cinfo->jpeg_color_space = JCS_RGB; /* ASCII 'R', 'G', 'B' */ + else { + if (cinfo->process == JPROC_LOSSLESS) { + TRACEMS3(cinfo, 1, JTRC_UNKNOWN_LOSSLESS_IDS, cid0, cid1, cid2); + cinfo->jpeg_color_space = JCS_RGB; /* assume it's RGB */ + } + else { /* Lossy processes */ + TRACEMS3(cinfo, 1, JTRC_UNKNOWN_LOSSY_IDS, cid0, cid1, cid2); + cinfo->jpeg_color_space = JCS_YCbCr; /* assume it's YCbCr */ + } + } + } + /* Always guess RGB is proper output colorspace. */ + cinfo->out_color_space = JCS_RGB; + break; + + case 4: + if (cinfo->saw_Adobe_marker) { + switch (cinfo->Adobe_transform) { + case 0: + cinfo->jpeg_color_space = JCS_CMYK; + break; + case 2: + cinfo->jpeg_color_space = JCS_YCCK; + break; + default: + WARNMS1(cinfo, JWRN_ADOBE_XFORM, cinfo->Adobe_transform); + cinfo->jpeg_color_space = JCS_YCCK; /* assume it's YCCK */ + break; + } + } else { + /* No special markers, assume straight CMYK. */ + cinfo->jpeg_color_space = JCS_CMYK; + } + cinfo->out_color_space = JCS_CMYK; + break; + + default: + cinfo->jpeg_color_space = JCS_UNKNOWN; + cinfo->out_color_space = JCS_UNKNOWN; + break; + } + + /* Set defaults for other decompression parameters. */ + cinfo->scale_num = 1; /* 1:1 scaling */ + cinfo->scale_denom = 1; + cinfo->output_gamma = 1.0; + cinfo->buffered_image = FALSE; + cinfo->raw_data_out = FALSE; + cinfo->dct_method = JDCT_DEFAULT; + cinfo->do_fancy_upsampling = TRUE; + cinfo->do_block_smoothing = TRUE; + cinfo->quantize_colors = FALSE; + /* We set these in case application only sets quantize_colors. */ + cinfo->dither_mode = JDITHER_FS; +#ifdef QUANT_2PASS_SUPPORTED + cinfo->two_pass_quantize = TRUE; +#else + cinfo->two_pass_quantize = FALSE; +#endif + cinfo->desired_number_of_colors = 256; + cinfo->colormap = NULL; + /* Initialize for no mode change in buffered-image mode. */ + cinfo->enable_1pass_quant = FALSE; + cinfo->enable_external_quant = FALSE; + cinfo->enable_2pass_quant = FALSE; +} + + +/* + * Decompression startup: read start of JPEG datastream to see what's there. + * Need only initialize JPEG object and supply a data source before calling. + * + * This routine will read as far as the first SOS marker (ie, actual start of + * compressed data), and will save all tables and parameters in the JPEG + * object. It will also initialize the decompression parameters to default + * values, and finally return JPEG_HEADER_OK. On return, the application may + * adjust the decompression parameters and then call jpeg_start_decompress. + * (Or, if the application only wanted to determine the image parameters, + * the data need not be decompressed. In that case, call jpeg_abort or + * jpeg_destroy to release any temporary space.) + * If an abbreviated (tables only) datastream is presented, the routine will + * return JPEG_HEADER_TABLES_ONLY upon reaching EOI. The application may then + * re-use the JPEG object to read the abbreviated image datastream(s). + * It is unnecessary (but OK) to call jpeg_abort in this case. + * The JPEG_SUSPENDED return code only occurs if the data source module + * requests suspension of the decompressor. In this case the application + * should load more source data and then re-call jpeg_read_header to resume + * processing. + * If a non-suspending data source is used and require_image is TRUE, then the + * return code need not be inspected since only JPEG_HEADER_OK is possible. + * + * This routine is now just a front end to jpeg_consume_input, with some + * extra error checking. + */ + +GLOBAL(int) +jpeg_read_header (j_decompress_ptr cinfo, boolean require_image) +{ + int retcode; + + if (cinfo->global_state != DSTATE_START && + cinfo->global_state != DSTATE_INHEADER) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + + retcode = jpeg_consume_input(cinfo); + + switch (retcode) { + case JPEG_REACHED_SOS: + retcode = JPEG_HEADER_OK; + break; + case JPEG_REACHED_EOI: + if (require_image) /* Complain if application wanted an image */ + ERREXIT(cinfo, JERR_NO_IMAGE); + /* Reset to start state; it would be safer to require the application to + * call jpeg_abort, but we can't change it now for compatibility reasons. + * A side effect is to free any temporary memory (there shouldn't be any). + */ + jpeg_abort((j_common_ptr) cinfo); /* sets state = DSTATE_START */ + retcode = JPEG_HEADER_TABLES_ONLY; + break; + case JPEG_SUSPENDED: + /* no work */ + break; + } + + return retcode; +} + + +/* + * Consume data in advance of what the decompressor requires. + * This can be called at any time once the decompressor object has + * been created and a data source has been set up. + * + * This routine is essentially a state machine that handles a couple + * of critical state-transition actions, namely initial setup and + * transition from header scanning to ready-for-start_decompress. + * All the actual input is done via the input controller's consume_input + * method. + */ + +GLOBAL(int) +jpeg_consume_input (j_decompress_ptr cinfo) +{ + int retcode = JPEG_SUSPENDED; + + /* NB: every possible DSTATE value should be listed in this switch */ + switch (cinfo->global_state) { + case DSTATE_START: + /* Start-of-datastream actions: reset appropriate modules */ + (*cinfo->inputctl->reset_input_controller) (cinfo); + /* Initialize application's data source module */ + (*cinfo->src->init_source) (cinfo); + cinfo->global_state = DSTATE_INHEADER; + /*FALLTHROUGH*/ + case DSTATE_INHEADER: + retcode = (*cinfo->inputctl->consume_input) (cinfo); + if (retcode == JPEG_REACHED_SOS) { /* Found SOS, prepare to decompress */ + /* Set up default parameters based on header data */ + default_decompress_parms(cinfo); + /* Set global state: ready for start_decompress */ + cinfo->global_state = DSTATE_READY; + } + break; + case DSTATE_READY: + /* Can't advance past first SOS until start_decompress is called */ + retcode = JPEG_REACHED_SOS; + break; + case DSTATE_PRELOAD: + case DSTATE_PRESCAN: + case DSTATE_SCANNING: + case DSTATE_RAW_OK: + case DSTATE_BUFIMAGE: + case DSTATE_BUFPOST: + case DSTATE_STOPPING: + retcode = (*cinfo->inputctl->consume_input) (cinfo); + break; + default: + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + } + return retcode; +} + + +/* + * Have we finished reading the input file? + */ + +GLOBAL(boolean) +jpeg_input_complete (j_decompress_ptr cinfo) +{ + /* Check for valid jpeg object */ + if (cinfo->global_state < DSTATE_START || + cinfo->global_state > DSTATE_STOPPING) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + return cinfo->inputctl->eoi_reached; +} + + +/* + * Is there more than one scan? + */ + +GLOBAL(boolean) +jpeg_has_multiple_scans (j_decompress_ptr cinfo) +{ + /* Only valid after jpeg_read_header completes */ + if (cinfo->global_state < DSTATE_READY || + cinfo->global_state > DSTATE_STOPPING) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + return cinfo->inputctl->has_multiple_scans; +} + + +/* + * Finish JPEG decompression. + * + * This will normally just verify the file trailer and release temp storage. + * + * Returns FALSE if suspended. The return value need be inspected only if + * a suspending data source is used. + */ + +GLOBAL(boolean) +jpeg_finish_decompress (j_decompress_ptr cinfo) +{ + if ((cinfo->global_state == DSTATE_SCANNING || + cinfo->global_state == DSTATE_RAW_OK) && ! cinfo->buffered_image) { + /* Terminate final pass of non-buffered mode */ + if (cinfo->output_scanline < cinfo->output_height) + ERREXIT(cinfo, JERR_TOO_LITTLE_DATA); + (*cinfo->master->finish_output_pass) (cinfo); + cinfo->global_state = DSTATE_STOPPING; + } else if (cinfo->global_state == DSTATE_BUFIMAGE) { + /* Finishing after a buffered-image operation */ + cinfo->global_state = DSTATE_STOPPING; + } else if (cinfo->global_state != DSTATE_STOPPING) { + /* STOPPING = repeat call after a suspension, anything else is error */ + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + } + /* Read until EOI */ + while (! cinfo->inputctl->eoi_reached) { + if ((*cinfo->inputctl->consume_input) (cinfo) == JPEG_SUSPENDED) + return FALSE; /* Suspend, come back later */ + } + /* Do final cleanup */ + (*cinfo->src->term_source) (cinfo); + /* We can use jpeg_abort to release memory and reset global_state */ + jpeg_abort((j_common_ptr) cinfo); + return TRUE; +} diff --git a/dcmjpeg/libijg8/jdapistd.c b/dcmjpeg/libijg8/jdapistd.c new file mode 100644 index 00000000..1b6d8c51 --- /dev/null +++ b/dcmjpeg/libijg8/jdapistd.c @@ -0,0 +1,275 @@ +/* + * jdapistd.c + * + * Copyright (C) 1994-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains application interface code for the decompression half + * of the JPEG library. These are the "standard" API routines that are + * used in the normal full-decompression case. They are not used by a + * transcoding-only application. Note that if an application links in + * jpeg_start_decompress, it will end up linking in the entire decompressor. + * We thus must separate this file from jdapimin.c to avoid linking the + * whole decompression library into a transcoder. + */ + +#define JPEG_INTERNALS +#include "jinclude8.h" +#include "jpeglib8.h" + + +/* Forward declarations */ +LOCAL(boolean) output_pass_setup JPP((j_decompress_ptr cinfo)); + + +/* + * Decompression initialization. + * jpeg_read_header must be completed before calling this. + * + * If a multipass operating mode was selected, this will do all but the + * last pass, and thus may take a great deal of time. + * + * Returns FALSE if suspended. The return value need be inspected only if + * a suspending data source is used. + */ + +GLOBAL(boolean) +jpeg_start_decompress (j_decompress_ptr cinfo) +{ + if (cinfo->global_state == DSTATE_READY) { + /* First call: initialize master control, select active modules */ + jinit_master_decompress(cinfo); + if (cinfo->buffered_image) { + /* No more work here; expecting jpeg_start_output next */ + cinfo->global_state = DSTATE_BUFIMAGE; + return TRUE; + } + cinfo->global_state = DSTATE_PRELOAD; + } + if (cinfo->global_state == DSTATE_PRELOAD) { + /* If file has multiple scans, absorb them all into the coef buffer */ + if (cinfo->inputctl->has_multiple_scans) { +#ifdef D_MULTISCAN_FILES_SUPPORTED + for (;;) { + int retcode; + /* Call progress monitor hook if present */ + if (cinfo->progress != NULL) + (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); + /* Absorb some more input */ + retcode = (*cinfo->inputctl->consume_input) (cinfo); + if (retcode == JPEG_SUSPENDED) + return FALSE; + if (retcode == JPEG_REACHED_EOI) + break; + /* Advance progress counter if appropriate */ + if (cinfo->progress != NULL && + (retcode == JPEG_ROW_COMPLETED || retcode == JPEG_REACHED_SOS)) { + if (++cinfo->progress->pass_counter >= cinfo->progress->pass_limit) { + /* jdmaster underestimated number of scans; ratchet up one scan */ + cinfo->progress->pass_limit += (long) cinfo->total_iMCU_rows; + } + } + } +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif /* D_MULTISCAN_FILES_SUPPORTED */ + } + cinfo->output_scan_number = cinfo->input_scan_number; + } else if (cinfo->global_state != DSTATE_PRESCAN) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + /* Perform any dummy output passes, and set up for the final pass */ + return output_pass_setup(cinfo); +} + + +/* + * Set up for an output pass, and perform any dummy pass(es) needed. + * Common subroutine for jpeg_start_decompress and jpeg_start_output. + * Entry: global_state = DSTATE_PRESCAN only if previously suspended. + * Exit: If done, returns TRUE and sets global_state for proper output mode. + * If suspended, returns FALSE and sets global_state = DSTATE_PRESCAN. + */ + +LOCAL(boolean) +output_pass_setup (j_decompress_ptr cinfo) +{ + if (cinfo->global_state != DSTATE_PRESCAN) { + /* First call: do pass setup */ + (*cinfo->master->prepare_for_output_pass) (cinfo); + cinfo->output_scanline = 0; + cinfo->global_state = DSTATE_PRESCAN; + } + /* Loop over any required dummy passes */ + while (cinfo->master->is_dummy_pass) { +#ifdef QUANT_2PASS_SUPPORTED + /* Crank through the dummy pass */ + while (cinfo->output_scanline < cinfo->output_height) { + JDIMENSION last_scanline; + /* Call progress monitor hook if present */ + if (cinfo->progress != NULL) { + cinfo->progress->pass_counter = (long) cinfo->output_scanline; + cinfo->progress->pass_limit = (long) cinfo->output_height; + (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); + } + /* Process some data */ + last_scanline = cinfo->output_scanline; + (*cinfo->main->process_data) (cinfo, (JSAMPARRAY) NULL, + &cinfo->output_scanline, (JDIMENSION) 0); + if (cinfo->output_scanline == last_scanline) + return FALSE; /* No progress made, must suspend */ + } + /* Finish up dummy pass, and set up for another one */ + (*cinfo->master->finish_output_pass) (cinfo); + (*cinfo->master->prepare_for_output_pass) (cinfo); + cinfo->output_scanline = 0; +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif /* QUANT_2PASS_SUPPORTED */ + } + /* Ready for application to drive output pass through + * jpeg_read_scanlines or jpeg_read_raw_data. + */ + cinfo->global_state = cinfo->raw_data_out ? DSTATE_RAW_OK : DSTATE_SCANNING; + return TRUE; +} + + +/* + * Read some scanlines of data from the JPEG decompressor. + * + * The return value will be the number of lines actually read. + * This may be less than the number requested in several cases, + * including bottom of image, data source suspension, and operating + * modes that emit multiple scanlines at a time. + * + * Note: we warn about excess calls to jpeg_read_scanlines() since + * this likely signals an application programmer error. However, + * an oversize buffer (max_lines > scanlines remaining) is not an error. + */ + +GLOBAL(JDIMENSION) +jpeg_read_scanlines (j_decompress_ptr cinfo, JSAMPARRAY scanlines, + JDIMENSION max_lines) +{ + JDIMENSION row_ctr; + + if (cinfo->global_state != DSTATE_SCANNING) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + if (cinfo->output_scanline >= cinfo->output_height) { + WARNMS(cinfo, JWRN_TOO_MUCH_DATA); + return 0; + } + + /* Call progress monitor hook if present */ + if (cinfo->progress != NULL) { + cinfo->progress->pass_counter = (long) cinfo->output_scanline; + cinfo->progress->pass_limit = (long) cinfo->output_height; + (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); + } + + /* Process some data */ + row_ctr = 0; + (*cinfo->main->process_data) (cinfo, scanlines, &row_ctr, max_lines); + cinfo->output_scanline += row_ctr; + return row_ctr; +} + + +/* + * Alternate entry point to read raw data. + * Processes exactly one iMCU row per call, unless suspended. + */ + +GLOBAL(JDIMENSION) +jpeg_read_raw_data (j_decompress_ptr cinfo, JSAMPIMAGE data, + JDIMENSION max_lines) +{ + JDIMENSION lines_per_iMCU_row; + + if (cinfo->global_state != DSTATE_RAW_OK) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + if (cinfo->output_scanline >= cinfo->output_height) { + WARNMS(cinfo, JWRN_TOO_MUCH_DATA); + return 0; + } + + /* Call progress monitor hook if present */ + if (cinfo->progress != NULL) { + cinfo->progress->pass_counter = (long) cinfo->output_scanline; + cinfo->progress->pass_limit = (long) cinfo->output_height; + (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); + } + + /* Verify that at least one iMCU row can be returned. */ + lines_per_iMCU_row = (JDIMENSION)(cinfo->max_v_samp_factor * cinfo->min_codec_data_unit); + if (max_lines < lines_per_iMCU_row) + ERREXIT(cinfo, JERR_BUFFER_SIZE); + + /* Decompress directly into user's buffer. */ + if (! (*cinfo->codec->decompress_data) (cinfo, data)) + return 0; /* suspension forced, can do nothing more */ + + /* OK, we processed one iMCU row. */ + cinfo->output_scanline += lines_per_iMCU_row; + return lines_per_iMCU_row; +} + + +/* Additional entry points for buffered-image mode. */ + +#ifdef D_MULTISCAN_FILES_SUPPORTED + +/* + * Initialize for an output pass in buffered-image mode. + */ + +GLOBAL(boolean) +jpeg_start_output (j_decompress_ptr cinfo, int scan_number) +{ + if (cinfo->global_state != DSTATE_BUFIMAGE && + cinfo->global_state != DSTATE_PRESCAN) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + /* Limit scan number to valid range */ + if (scan_number <= 0) + scan_number = 1; + if (cinfo->inputctl->eoi_reached && + scan_number > cinfo->input_scan_number) + scan_number = cinfo->input_scan_number; + cinfo->output_scan_number = scan_number; + /* Perform any dummy output passes, and set up for the real pass */ + return output_pass_setup(cinfo); +} + + +/* + * Finish up after an output pass in buffered-image mode. + * + * Returns FALSE if suspended. The return value need be inspected only if + * a suspending data source is used. + */ + +GLOBAL(boolean) +jpeg_finish_output (j_decompress_ptr cinfo) +{ + if ((cinfo->global_state == DSTATE_SCANNING || + cinfo->global_state == DSTATE_RAW_OK) && cinfo->buffered_image) { + /* Terminate this pass. */ + /* We do not require the whole pass to have been completed. */ + (*cinfo->master->finish_output_pass) (cinfo); + cinfo->global_state = DSTATE_BUFPOST; + } else if (cinfo->global_state != DSTATE_BUFPOST) { + /* BUFPOST = repeat call after a suspension, anything else is error */ + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + } + /* Read markers looking for SOS or EOI */ + while (cinfo->input_scan_number <= cinfo->output_scan_number && + ! cinfo->inputctl->eoi_reached) { + if ((*cinfo->inputctl->consume_input) (cinfo) == JPEG_SUSPENDED) + return FALSE; /* Suspend, come back later */ + } + cinfo->global_state = DSTATE_BUFIMAGE; + return TRUE; +} + +#endif /* D_MULTISCAN_FILES_SUPPORTED */ diff --git a/dcmjpeg/libijg8/jdarith.c b/dcmjpeg/libijg8/jdarith.c new file mode 100644 index 00000000..8146e723 --- /dev/null +++ b/dcmjpeg/libijg8/jdarith.c @@ -0,0 +1,26 @@ +/* + * jdarith.c + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file holds place for arithmetic entropy decoding routines. + */ + +#define JPEG_INTERNALS +#include "jinclude8.h" +#include "jpeglib8.h" + + +/* + * Module initialization routine for arithmetic entropy decoding. + */ +GLOBAL(void) +jinit_arith_decoder (j_decompress_ptr cinfo); + +GLOBAL(void) +jinit_arith_decoder (j_decompress_ptr cinfo) +{ + ERREXIT(cinfo, JERR_ARITH_NOTIMPL); +} diff --git a/dcmjpeg/libijg8/jdatadst.c b/dcmjpeg/libijg8/jdatadst.c new file mode 100644 index 00000000..7a9274d7 --- /dev/null +++ b/dcmjpeg/libijg8/jdatadst.c @@ -0,0 +1,151 @@ +/* + * jdatadst.c + * + * Copyright (C) 1994-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains compression data destination routines for the case of + * emitting JPEG data to a file (or any stdio stream). While these routines + * are sufficient for most applications, some will want to use a different + * destination manager. + * IMPORTANT: we assume that fwrite() will correctly transcribe an array of + * JOCTETs into 8-bit-wide elements on external storage. If char is wider + * than 8 bits on your machine, you may need to do some tweaking. + */ + +/* this is not a core library module, so it doesn't define JPEG_INTERNALS */ +#include "jinclude8.h" +#include "jpeglib8.h" +#include "jerror8.h" + + +/* Expanded data destination object for stdio output */ + +typedef struct { + struct jpeg_destination_mgr pub; /* public fields */ + + FILE * outfile; /* target stream */ + JOCTET * buffer; /* start of buffer */ +} my_destination_mgr; + +typedef my_destination_mgr * my_dest_ptr; + +#define OUTPUT_BUF_SIZE 4096 /* choose an efficiently fwrite'able size */ + + +/* + * Initialize destination --- called by jpeg_start_compress + * before any data is actually written. + */ + +METHODDEF(void) +init_destination (j_compress_ptr cinfo) +{ + my_dest_ptr dest = (my_dest_ptr) cinfo->dest; + + /* Allocate the output buffer --- it will be released when done with image */ + dest->buffer = (JOCTET *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + OUTPUT_BUF_SIZE * SIZEOF(JOCTET)); + + dest->pub.next_output_byte = dest->buffer; + dest->pub.free_in_buffer = OUTPUT_BUF_SIZE; +} + + +/* + * Empty the output buffer --- called whenever buffer fills up. + * + * In typical applications, this should write the entire output buffer + * (ignoring the current state of next_output_byte & free_in_buffer), + * reset the pointer & count to the start of the buffer, and return TRUE + * indicating that the buffer has been dumped. + * + * In applications that need to be able to suspend compression due to output + * overrun, a FALSE return indicates that the buffer cannot be emptied now. + * In this situation, the compressor will return to its caller (possibly with + * an indication that it has not accepted all the supplied scanlines). The + * application should resume compression after it has made more room in the + * output buffer. Note that there are substantial restrictions on the use of + * suspension --- see the documentation. + * + * When suspending, the compressor will back up to a convenient restart point + * (typically the start of the current MCU). next_output_byte & free_in_buffer + * indicate where the restart point will be if the current call returns FALSE. + * Data beyond this point will be regenerated after resumption, so do not + * write it out when emptying the buffer externally. + */ + +METHODDEF(boolean) +empty_output_buffer (j_compress_ptr cinfo) +{ + my_dest_ptr dest = (my_dest_ptr) cinfo->dest; + + if (JFWRITE(dest->outfile, dest->buffer, OUTPUT_BUF_SIZE) != + (size_t) OUTPUT_BUF_SIZE) + ERREXIT(cinfo, JERR_FILE_WRITE); + + dest->pub.next_output_byte = dest->buffer; + dest->pub.free_in_buffer = OUTPUT_BUF_SIZE; + + return TRUE; +} + + +/* + * Terminate destination --- called by jpeg_finish_compress + * after all data has been written. Usually needs to flush buffer. + * + * NB: *not* called by jpeg_abort or jpeg_destroy; surrounding + * application must deal with any cleanup that should happen even + * for error exit. + */ + +METHODDEF(void) +term_destination (j_compress_ptr cinfo) +{ + my_dest_ptr dest = (my_dest_ptr) cinfo->dest; + size_t datacount = OUTPUT_BUF_SIZE - dest->pub.free_in_buffer; + + /* Write any data remaining in the buffer */ + if (datacount > 0) { + if (JFWRITE(dest->outfile, dest->buffer, datacount) != datacount) + ERREXIT(cinfo, JERR_FILE_WRITE); + } + fflush(dest->outfile); + /* Make sure we wrote the output file OK */ + if (ferror(dest->outfile)) + ERREXIT(cinfo, JERR_FILE_WRITE); +} + + +/* + * Prepare for output to a stdio stream. + * The caller must have already opened the stream, and is responsible + * for closing it after finishing compression. + */ + +GLOBAL(void) +jpeg_stdio_dest (j_compress_ptr cinfo, FILE * outfile) +{ + my_dest_ptr dest; + + /* The destination object is made permanent so that multiple JPEG images + * can be written to the same file without re-executing jpeg_stdio_dest. + * This makes it dangerous to use this manager and a different destination + * manager serially with the same JPEG object, because their private object + * sizes may be different. Caveat programmer. + */ + if (cinfo->dest == NULL) { /* first time for this JPEG object? */ + cinfo->dest = (struct jpeg_destination_mgr *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, + SIZEOF(my_destination_mgr)); + } + + dest = (my_dest_ptr) cinfo->dest; + dest->pub.init_destination = init_destination; + dest->pub.empty_output_buffer = empty_output_buffer; + dest->pub.term_destination = term_destination; + dest->outfile = outfile; +} diff --git a/dcmjpeg/libijg8/jdatasrc.c b/dcmjpeg/libijg8/jdatasrc.c new file mode 100644 index 00000000..7296ff8f --- /dev/null +++ b/dcmjpeg/libijg8/jdatasrc.c @@ -0,0 +1,212 @@ +/* + * jdatasrc.c + * + * Copyright (C) 1994-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains decompression data source routines for the case of + * reading JPEG data from a file (or any stdio stream). While these routines + * are sufficient for most applications, some will want to use a different + * source manager. + * IMPORTANT: we assume that fread() will correctly transcribe an array of + * JOCTETs from 8-bit-wide elements on external storage. If char is wider + * than 8 bits on your machine, you may need to do some tweaking. + */ + +/* this is not a core library module, so it doesn't define JPEG_INTERNALS */ +#include "jinclude8.h" +#include "jpeglib8.h" +#include "jerror8.h" + + +/* Expanded data source object for stdio input */ + +typedef struct { + struct jpeg_source_mgr pub; /* public fields */ + + FILE * infile; /* source stream */ + JOCTET * buffer; /* start of buffer */ + boolean start_of_file; /* have we gotten any data yet? */ +} my_source_mgr; + +typedef my_source_mgr * my_src_ptr; + +#define INPUT_BUF_SIZE 4096 /* choose an efficiently fread'able size */ + + +/* + * Initialize source --- called by jpeg_read_header + * before any data is actually read. + */ + +METHODDEF(void) +init_source (j_decompress_ptr cinfo) +{ + my_src_ptr src = (my_src_ptr) cinfo->src; + + /* We reset the empty-input-file flag for each image, + * but we don't clear the input buffer. + * This is correct behavior for reading a series of images from one source. + */ + src->start_of_file = TRUE; +} + + +/* + * Fill the input buffer --- called whenever buffer is emptied. + * + * In typical applications, this should read fresh data into the buffer + * (ignoring the current state of next_input_byte & bytes_in_buffer), + * reset the pointer & count to the start of the buffer, and return TRUE + * indicating that the buffer has been reloaded. It is not necessary to + * fill the buffer entirely, only to obtain at least one more byte. + * + * There is no such thing as an EOF return. If the end of the file has been + * reached, the routine has a choice of ERREXIT() or inserting fake data into + * the buffer. In most cases, generating a warning message and inserting a + * fake EOI marker is the best course of action --- this will allow the + * decompressor to output however much of the image is there. However, + * the resulting error message is misleading if the real problem is an empty + * input file, so we handle that case specially. + * + * In applications that need to be able to suspend compression due to input + * not being available yet, a FALSE return indicates that no more data can be + * obtained right now, but more may be forthcoming later. In this situation, + * the decompressor will return to its caller (with an indication of the + * number of scanlines it has read, if any). The application should resume + * decompression after it has loaded more data into the input buffer. Note + * that there are substantial restrictions on the use of suspension --- see + * the documentation. + * + * When suspending, the decompressor will back up to a convenient restart point + * (typically the start of the current MCU). next_input_byte & bytes_in_buffer + * indicate where the restart point will be if the current call returns FALSE. + * Data beyond this point must be rescanned after resumption, so move it to + * the front of the buffer rather than discarding it. + */ + +METHODDEF(boolean) +fill_input_buffer (j_decompress_ptr cinfo) +{ + my_src_ptr src = (my_src_ptr) cinfo->src; + size_t nbytes; + + nbytes = JFREAD(src->infile, src->buffer, INPUT_BUF_SIZE); + + if (nbytes <= 0) { + if (src->start_of_file) /* Treat empty input file as fatal error */ + ERREXIT(cinfo, JERR_INPUT_EMPTY); + WARNMS(cinfo, JWRN_JPEG_EOF); + /* Insert a fake EOI marker */ + src->buffer[0] = (JOCTET) 0xFF; + src->buffer[1] = (JOCTET) JPEG_EOI; + nbytes = 2; + } + + src->pub.next_input_byte = src->buffer; + src->pub.bytes_in_buffer = nbytes; + src->start_of_file = FALSE; + + return TRUE; +} + + +/* + * Skip data --- used to skip over a potentially large amount of + * uninteresting data (such as an APPn marker). + * + * Writers of suspendable-input applications must note that skip_input_data + * is not granted the right to give a suspension return. If the skip extends + * beyond the data currently in the buffer, the buffer can be marked empty so + * that the next read will cause a fill_input_buffer call that can suspend. + * Arranging for additional bytes to be discarded before reloading the input + * buffer is the application writer's problem. + */ + +METHODDEF(void) +skip_input_data (j_decompress_ptr cinfo, long num_bytes) +{ + my_src_ptr src = (my_src_ptr) cinfo->src; + + /* Just a dumb implementation for now. Could use fseek() except + * it doesn't work on pipes. Not clear that being smart is worth + * any trouble anyway --- large skips are infrequent. + */ + if (num_bytes > 0) { + while (num_bytes > (long) src->pub.bytes_in_buffer) { + num_bytes -= (long) src->pub.bytes_in_buffer; + (void) fill_input_buffer(cinfo); + /* note we assume that fill_input_buffer will never return FALSE, + * so suspension need not be handled. + */ + } + src->pub.next_input_byte += (size_t) num_bytes; + src->pub.bytes_in_buffer -= (size_t) num_bytes; + } +} + + +/* + * An additional method that can be provided by data source modules is the + * resync_to_restart method for error recovery in the presence of RST markers. + * For the moment, this source module just uses the default resync method + * provided by the JPEG library. That method assumes that no backtracking + * is possible. + */ + + +/* + * Terminate source --- called by jpeg_finish_decompress + * after all data has been read. Often a no-op. + * + * NB: *not* called by jpeg_abort or jpeg_destroy; surrounding + * application must deal with any cleanup that should happen even + * for error exit. + */ + +METHODDEF(void) +term_source (j_decompress_ptr cinfo) +{ + /* no work necessary here */ +} + + +/* + * Prepare for input from a stdio stream. + * The caller must have already opened the stream, and is responsible + * for closing it after finishing decompression. + */ + +GLOBAL(void) +jpeg_stdio_src (j_decompress_ptr cinfo, FILE * infile) +{ + my_src_ptr src; + + /* The source object and input buffer are made permanent so that a series + * of JPEG images can be read from the same file by calling jpeg_stdio_src + * only before the first one. (If we discarded the buffer at the end of + * one image, we'd likely lose the start of the next one.) + * This makes it unsafe to use this manager and a different source + * manager serially with the same JPEG object. Caveat programmer. + */ + if (cinfo->src == NULL) { /* first time for this JPEG object? */ + cinfo->src = (struct jpeg_source_mgr *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, + SIZEOF(my_source_mgr)); + src = (my_src_ptr) cinfo->src; + src->buffer = (JOCTET *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, + INPUT_BUF_SIZE * SIZEOF(JOCTET)); + } + + src = (my_src_ptr) cinfo->src; + src->pub.init_source = init_source; + src->pub.fill_input_buffer = fill_input_buffer; + src->pub.skip_input_data = skip_input_data; + src->pub.resync_to_restart = jpeg_resync_to_restart; /* use default method */ + src->pub.term_source = term_source; + src->infile = infile; + src->pub.bytes_in_buffer = 0; /* forces fill_input_buffer on first read */ + src->pub.next_input_byte = NULL; /* until buffer loaded */ +} diff --git a/dcmjpeg/libijg8/jdcoefct.c b/dcmjpeg/libijg8/jdcoefct.c new file mode 100644 index 00000000..ce9c2002 --- /dev/null +++ b/dcmjpeg/libijg8/jdcoefct.c @@ -0,0 +1,743 @@ +/* + * jdcoefct.c + * + * Copyright (C) 1994-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains the coefficient buffer controller for decompression. + * This controller is the top level of the lossy JPEG decompressor proper. + * The coefficient buffer lies between entropy decoding and inverse-DCT steps. + * + * In buffered-image mode, this controller is the interface between + * input-oriented processing and output-oriented processing. + * Also, the input side (only) is used when reading a file for transcoding. + */ + +#define JPEG_INTERNALS +#include "jinclude8.h" +#include "jpeglib8.h" +#include "jlossy8.h" + +/* Block smoothing is only applicable for progressive JPEG, so: */ +#ifndef D_PROGRESSIVE_SUPPORTED +#undef BLOCK_SMOOTHING_SUPPORTED +#endif + +/* Private buffer controller object */ + +typedef struct { + /* These variables keep track of the current location of the input side. */ + /* cinfo->input_iMCU_row is also used for this. */ + JDIMENSION MCU_ctr; /* counts MCUs processed in current row */ + int MCU_vert_offset; /* counts MCU rows within iMCU row */ + int MCU_rows_per_iMCU_row; /* number of such rows needed */ + + /* The output side's location is represented by cinfo->output_iMCU_row. */ + + /* In single-pass modes, it's sufficient to buffer just one MCU. + * We allocate a workspace of D_MAX_DATA_UNITS_IN_MCU coefficient blocks, + * and let the entropy decoder write into that workspace each time. + * (On 80x86, the workspace is FAR even though it's not really very big; + * this is to keep the module interfaces unchanged when a large coefficient + * buffer is necessary.) + * In multi-pass modes, this array points to the current MCU's blocks + * within the virtual arrays; it is used only by the input side. + */ + JBLOCKROW MCU_buffer[D_MAX_DATA_UNITS_IN_MCU]; + +#ifdef D_MULTISCAN_FILES_SUPPORTED + /* In multi-pass modes, we need a virtual block array for each component. */ + jvirt_barray_ptr whole_image[MAX_COMPONENTS]; +#endif + +#ifdef BLOCK_SMOOTHING_SUPPORTED + /* When doing block smoothing, we latch coefficient Al values here */ + int * coef_bits_latch; +#define SAVED_COEFS 6 /* we save coef_bits[0..5] */ +#endif +} d_coef_controller; + +typedef d_coef_controller * d_coef_ptr; + +/* Forward declarations */ +METHODDEF(int) decompress_onepass + JPP((j_decompress_ptr cinfo, JSAMPIMAGE output_buf)); +#ifdef D_MULTISCAN_FILES_SUPPORTED +METHODDEF(int) decompress_data + JPP((j_decompress_ptr cinfo, JSAMPIMAGE output_buf)); +#endif +#ifdef BLOCK_SMOOTHING_SUPPORTED +LOCAL(boolean) smoothing_ok JPP((j_decompress_ptr cinfo)); +METHODDEF(int) decompress_smooth_data + JPP((j_decompress_ptr cinfo, JSAMPIMAGE output_buf)); +#endif + + +LOCAL(void) +start_iMCU_row (j_decompress_ptr cinfo) +/* Reset within-iMCU-row counters for a new row (input side) */ +{ + j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec; + d_coef_ptr coef = (d_coef_ptr) lossyd->coef_private; + + /* In an interleaved scan, an MCU row is the same as an iMCU row. + * In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows. + * But at the bottom of the image, process only what's left. + */ + if (cinfo->comps_in_scan > 1) { + coef->MCU_rows_per_iMCU_row = 1; + } else { + if (cinfo->input_iMCU_row < (cinfo->total_iMCU_rows-1)) + coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->v_samp_factor; + else + coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->last_row_height; + } + + coef->MCU_ctr = 0; + coef->MCU_vert_offset = 0; +} + + +/* + * Initialize for an input processing pass. + */ + +METHODDEF(void) +start_input_pass (j_decompress_ptr cinfo) +{ + cinfo->input_iMCU_row = 0; + start_iMCU_row(cinfo); +} + + +/* + * Initialize for an output processing pass. + */ + +METHODDEF(void) +start_output_pass (j_decompress_ptr cinfo) +{ +#ifdef BLOCK_SMOOTHING_SUPPORTED + j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec; + /* d_coef_ptr coef = (d_coef_ptr) lossyd->coef_private; */ + + /* If multipass, check to see whether to use block smoothing on this pass */ + if (lossyd->coef_arrays != NULL) { + if (cinfo->do_block_smoothing && smoothing_ok(cinfo)) + lossyd->pub.decompress_data = decompress_smooth_data; + else + lossyd->pub.decompress_data = decompress_data; + } +#endif + cinfo->output_iMCU_row = 0; +} + + +/* + * Decompress and return some data in the single-pass case. + * Always attempts to emit one fully interleaved MCU row ("iMCU" row). + * Input and output must run in lockstep since we have only a one-MCU buffer. + * Return value is JPEG_ROW_COMPLETED, JPEG_SCAN_COMPLETED, or JPEG_SUSPENDED. + * + * NB: output_buf contains a plane for each component in image, + * which we index according to the component's SOF position. + */ + +METHODDEF(int) +decompress_onepass (j_decompress_ptr cinfo, JSAMPIMAGE output_buf) +{ + j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec; + d_coef_ptr coef = (d_coef_ptr) lossyd->coef_private; + JDIMENSION MCU_col_num; /* index of current MCU within row */ + JDIMENSION last_MCU_col = cinfo->MCUs_per_row - 1; + JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; + int blkn, ci, xindex, yindex, yoffset, useful_width; + JSAMPARRAY output_ptr; + JDIMENSION start_col, output_col; + jpeg_component_info *compptr; + inverse_DCT_method_ptr inverse_DCT; + + /* Loop to process as much as one whole iMCU row */ + for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row; + yoffset++) { + for (MCU_col_num = coef->MCU_ctr; MCU_col_num <= last_MCU_col; + MCU_col_num++) { + /* Try to fetch an MCU. Entropy decoder expects buffer to be zeroed. */ + jzero_far((void FAR *) coef->MCU_buffer[0], + (size_t)cinfo->data_units_in_MCU * SIZEOF(JBLOCK)); + if (! (*lossyd->entropy_decode_mcu) (cinfo, coef->MCU_buffer)) { + /* Suspension forced; update state counters and exit */ + coef->MCU_vert_offset = yoffset; + coef->MCU_ctr = MCU_col_num; + return JPEG_SUSPENDED; + } + /* Determine where data should go in output_buf and do the IDCT thing. + * We skip dummy blocks at the right and bottom edges (but blkn gets + * incremented past them!). Note the inner loop relies on having + * allocated the MCU_buffer[] blocks sequentially. + */ + blkn = 0; /* index of current DCT block within MCU */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + /* Don't bother to IDCT an uninteresting component. */ + if (! compptr->component_needed) { + blkn += compptr->MCU_data_units; + continue; + } + inverse_DCT = lossyd->inverse_DCT[compptr->component_index]; + useful_width = (MCU_col_num < last_MCU_col) ? compptr->MCU_width + : compptr->last_col_width; + output_ptr = output_buf[compptr->component_index] + + yoffset * compptr->codec_data_unit; + start_col = MCU_col_num * (JDIMENSION)compptr->MCU_sample_width; + for (yindex = 0; yindex < compptr->MCU_height; yindex++) { + if (cinfo->input_iMCU_row < last_iMCU_row || + yoffset+yindex < compptr->last_row_height) { + output_col = start_col; + for (xindex = 0; xindex < useful_width; xindex++) { + (*inverse_DCT) (cinfo, compptr, + (JCOEFPTR) coef->MCU_buffer[blkn+xindex], + output_ptr, output_col); + output_col += (JDIMENSION)compptr->codec_data_unit; + } + } + blkn += compptr->MCU_width; + output_ptr += compptr->codec_data_unit; + } + } + } + /* Completed an MCU row, but perhaps not an iMCU row */ + coef->MCU_ctr = 0; + } + /* Completed the iMCU row, advance counters for next one */ + cinfo->output_iMCU_row++; + if (++(cinfo->input_iMCU_row) < cinfo->total_iMCU_rows) { + start_iMCU_row(cinfo); + return JPEG_ROW_COMPLETED; + } + /* Completed the scan */ + (*cinfo->inputctl->finish_input_pass) (cinfo); + return JPEG_SCAN_COMPLETED; +} + + +/* + * Dummy consume-input routine for single-pass operation. + */ + +METHODDEF(int) +dummy_consume_data (j_decompress_ptr cinfo) +{ + return JPEG_SUSPENDED; /* Always indicate nothing was done */ +} + + +#ifdef D_MULTISCAN_FILES_SUPPORTED + +/* + * Consume input data and store it in the full-image coefficient buffer. + * We read as much as one fully interleaved MCU row ("iMCU" row) per call, + * ie, v_samp_factor block rows for each component in the scan. + * Return value is JPEG_ROW_COMPLETED, JPEG_SCAN_COMPLETED, or JPEG_SUSPENDED. + */ + +METHODDEF(int) +consume_data (j_decompress_ptr cinfo) +{ + j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec; + d_coef_ptr coef = (d_coef_ptr) lossyd->coef_private; + JDIMENSION MCU_col_num; /* index of current MCU within row */ + int blkn, ci, xindex, yindex, yoffset; + JDIMENSION start_col; + JBLOCKARRAY buffer[MAX_COMPS_IN_SCAN]; + JBLOCKROW buffer_ptr; + jpeg_component_info *compptr; + + /* Align the virtual buffers for the components used in this scan. */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + buffer[ci] = (*cinfo->mem->access_virt_barray) + ((j_common_ptr) cinfo, coef->whole_image[compptr->component_index], + cinfo->input_iMCU_row * (JDIMENSION)compptr->v_samp_factor, + (JDIMENSION) compptr->v_samp_factor, TRUE); + /* Note: entropy decoder expects buffer to be zeroed, + * but this is handled automatically by the memory manager + * because we requested a pre-zeroed array. + */ + } + + /* Loop to process one whole iMCU row */ + for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row; + yoffset++) { + for (MCU_col_num = coef->MCU_ctr; MCU_col_num < cinfo->MCUs_per_row; + MCU_col_num++) { + /* Construct list of pointers to DCT blocks belonging to this MCU */ + blkn = 0; /* index of current DCT block within MCU */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + start_col = MCU_col_num * (JDIMENSION)compptr->MCU_width; + for (yindex = 0; yindex < compptr->MCU_height; yindex++) { + buffer_ptr = buffer[ci][yindex+yoffset] + start_col; + for (xindex = 0; xindex < compptr->MCU_width; xindex++) { + coef->MCU_buffer[blkn++] = buffer_ptr++; + } + } + } + /* Try to fetch the MCU. */ + if (! (*lossyd->entropy_decode_mcu) (cinfo, coef->MCU_buffer)) { + /* Suspension forced; update state counters and exit */ + coef->MCU_vert_offset = yoffset; + coef->MCU_ctr = MCU_col_num; + return JPEG_SUSPENDED; + } + } + /* Completed an MCU row, but perhaps not an iMCU row */ + coef->MCU_ctr = 0; + } + /* Completed the iMCU row, advance counters for next one */ + if (++(cinfo->input_iMCU_row) < cinfo->total_iMCU_rows) { + start_iMCU_row(cinfo); + return JPEG_ROW_COMPLETED; + } + /* Completed the scan */ + (*cinfo->inputctl->finish_input_pass) (cinfo); + return JPEG_SCAN_COMPLETED; +} + + +/* + * Decompress and return some data in the multi-pass case. + * Always attempts to emit one fully interleaved MCU row ("iMCU" row). + * Return value is JPEG_ROW_COMPLETED, JPEG_SCAN_COMPLETED, or JPEG_SUSPENDED. + * + * NB: output_buf contains a plane for each component in image. + */ + +METHODDEF(int) +decompress_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf) +{ + j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec; + d_coef_ptr coef = (d_coef_ptr) lossyd->coef_private; + JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; + JDIMENSION block_num; + int ci, block_row, block_rows; + JBLOCKARRAY buffer; + JBLOCKROW buffer_ptr; + JSAMPARRAY output_ptr; + JDIMENSION output_col; + jpeg_component_info *compptr; + inverse_DCT_method_ptr inverse_DCT; + + /* Force some input to be done if we are getting ahead of the input. */ + while (cinfo->input_scan_number < cinfo->output_scan_number || + (cinfo->input_scan_number == cinfo->output_scan_number && + cinfo->input_iMCU_row <= cinfo->output_iMCU_row)) { + if ((*cinfo->inputctl->consume_input)(cinfo) == JPEG_SUSPENDED) + return JPEG_SUSPENDED; + } + + /* OK, output from the virtual arrays. */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + /* Don't bother to IDCT an uninteresting component. */ + if (! compptr->component_needed) + continue; + /* Align the virtual buffer for this component. */ + buffer = (*cinfo->mem->access_virt_barray) + ((j_common_ptr) cinfo, coef->whole_image[ci], + cinfo->output_iMCU_row * (JDIMENSION)compptr->v_samp_factor, + (JDIMENSION) compptr->v_samp_factor, FALSE); + /* Count non-dummy DCT block rows in this iMCU row. */ + if (cinfo->output_iMCU_row < last_iMCU_row) + block_rows = compptr->v_samp_factor; + else { + /* NB: can't use last_row_height here; it is input-side-dependent! */ + block_rows = (int)compptr->height_in_data_units % compptr->v_samp_factor; + if (block_rows == 0) block_rows = compptr->v_samp_factor; + } + inverse_DCT = lossyd->inverse_DCT[ci]; + output_ptr = output_buf[ci]; + /* Loop over all DCT blocks to be processed. */ + for (block_row = 0; block_row < block_rows; block_row++) { + buffer_ptr = buffer[block_row]; + output_col = 0; + for (block_num = 0; block_num < compptr->width_in_data_units; block_num++) { + (*inverse_DCT) (cinfo, compptr, (JCOEFPTR) buffer_ptr, + output_ptr, output_col); + buffer_ptr++; + output_col += (JDIMENSION)compptr->codec_data_unit; + } + output_ptr += compptr->codec_data_unit; + } + } + + if (++(cinfo->output_iMCU_row) < cinfo->total_iMCU_rows) + return JPEG_ROW_COMPLETED; + return JPEG_SCAN_COMPLETED; +} + +#endif /* D_MULTISCAN_FILES_SUPPORTED */ + + +#ifdef BLOCK_SMOOTHING_SUPPORTED + +/* + * This code applies interblock smoothing as described by section K.8 + * of the JPEG standard: the first 5 AC coefficients are estimated from + * the DC values of a DCT block and its 8 neighboring blocks. + * We apply smoothing only for progressive JPEG decoding, and only if + * the coefficients it can estimate are not yet known to full precision. + */ + +/* Natural-order array positions of the first 5 zigzag-order coefficients */ +#define Q01_POS 1 +#define Q10_POS 8 +#define Q20_POS 16 +#define Q11_POS 9 +#define Q02_POS 2 + +/* + * Determine whether block smoothing is applicable and safe. + * We also latch the current states of the coef_bits[] entries for the + * AC coefficients; otherwise, if the input side of the decompressor + * advances into a new scan, we might think the coefficients are known + * more accurately than they really are. + */ + +LOCAL(boolean) +smoothing_ok (j_decompress_ptr cinfo) +{ + j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec; + d_coef_ptr coef = (d_coef_ptr) lossyd->coef_private; + boolean smoothing_useful = FALSE; + int ci, coefi; + jpeg_component_info *compptr; + JQUANT_TBL * qtable; + int * coef_bits; + int * coef_bits_latch; + + if (! cinfo->process == JPROC_PROGRESSIVE || cinfo->coef_bits == NULL) + return FALSE; + + /* Allocate latch area if not already done */ + if (coef->coef_bits_latch == NULL) + coef->coef_bits_latch = (int *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (size_t)cinfo->num_components * + (SAVED_COEFS * SIZEOF(int))); + coef_bits_latch = coef->coef_bits_latch; + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + /* All components' quantization values must already be latched. */ + if ((qtable = compptr->quant_table) == NULL) + return FALSE; + /* Verify DC & first 5 AC quantizers are nonzero to avoid zero-divide. */ + if (qtable->quantval[0] == 0 || + qtable->quantval[Q01_POS] == 0 || + qtable->quantval[Q10_POS] == 0 || + qtable->quantval[Q20_POS] == 0 || + qtable->quantval[Q11_POS] == 0 || + qtable->quantval[Q02_POS] == 0) + return FALSE; + /* DC values must be at least partly known for all components. */ + coef_bits = cinfo->coef_bits[ci]; + if (coef_bits[0] < 0) + return FALSE; + /* Block smoothing is helpful if some AC coefficients remain inaccurate. */ + for (coefi = 1; coefi <= 5; coefi++) { + coef_bits_latch[coefi] = coef_bits[coefi]; + if (coef_bits[coefi] != 0) + smoothing_useful = TRUE; + } + coef_bits_latch += SAVED_COEFS; + } + + return smoothing_useful; +} + + +/* + * Variant of decompress_data for use when doing block smoothing. + */ + +METHODDEF(int) +decompress_smooth_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf) +{ + j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec; + d_coef_ptr coef = (d_coef_ptr) lossyd->coef_private; + JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; + JDIMENSION block_num, last_block_column; + int ci, block_row, block_rows, access_rows; + JBLOCKARRAY buffer; + JBLOCKROW buffer_ptr, prev_block_row, next_block_row; + JSAMPARRAY output_ptr; + JDIMENSION output_col; + jpeg_component_info *compptr; + inverse_DCT_method_ptr inverse_DCT; + boolean first_row, last_row; + JBLOCK workspace; + int *coef_bits; + JQUANT_TBL *quanttbl; + IJG_INT32 Q00,Q01,Q02,Q10,Q11,Q20, num; + int DC1,DC2,DC3,DC4,DC5,DC6,DC7,DC8,DC9; + int Al, pred; + + /* Force some input to be done if we are getting ahead of the input. */ + while (cinfo->input_scan_number <= cinfo->output_scan_number && + ! cinfo->inputctl->eoi_reached) { + if (cinfo->input_scan_number == cinfo->output_scan_number) { + /* If input is working on current scan, we ordinarily want it to + * have completed the current row. But if input scan is DC, + * we want it to keep one row ahead so that next block row's DC + * values are up to date. + */ + JDIMENSION delta = (cinfo->Ss == 0) ? 1 : 0; + if (cinfo->input_iMCU_row > cinfo->output_iMCU_row+delta) + break; + } + if ((*cinfo->inputctl->consume_input)(cinfo) == JPEG_SUSPENDED) + return JPEG_SUSPENDED; + } + + /* OK, output from the virtual arrays. */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + /* Don't bother to IDCT an uninteresting component. */ + if (! compptr->component_needed) + continue; + /* Count non-dummy DCT block rows in this iMCU row. */ + if (cinfo->output_iMCU_row < last_iMCU_row) { + block_rows = compptr->v_samp_factor; + access_rows = block_rows * 2; /* this and next iMCU row */ + last_row = FALSE; + } else { + /* NB: can't use last_row_height here; it is input-side-dependent! */ + block_rows = (int)compptr->height_in_data_units % compptr->v_samp_factor; + if (block_rows == 0) block_rows = compptr->v_samp_factor; + access_rows = block_rows; /* this iMCU row only */ + last_row = TRUE; + } + /* Align the virtual buffer for this component. */ + if (cinfo->output_iMCU_row > 0) { + access_rows += compptr->v_samp_factor; /* prior iMCU row too */ + buffer = (*cinfo->mem->access_virt_barray) + ((j_common_ptr) cinfo, coef->whole_image[ci], + (cinfo->output_iMCU_row - 1) * (JDIMENSION)compptr->v_samp_factor, + (JDIMENSION) access_rows, FALSE); + buffer += compptr->v_samp_factor; /* point to current iMCU row */ + first_row = FALSE; + } else { + buffer = (*cinfo->mem->access_virt_barray) + ((j_common_ptr) cinfo, coef->whole_image[ci], + (JDIMENSION) 0, (JDIMENSION) access_rows, FALSE); + first_row = TRUE; + } + /* Fetch component-dependent info */ + coef_bits = coef->coef_bits_latch + (ci * SAVED_COEFS); + quanttbl = compptr->quant_table; + Q00 = quanttbl->quantval[0]; + Q01 = quanttbl->quantval[Q01_POS]; + Q10 = quanttbl->quantval[Q10_POS]; + Q20 = quanttbl->quantval[Q20_POS]; + Q11 = quanttbl->quantval[Q11_POS]; + Q02 = quanttbl->quantval[Q02_POS]; + inverse_DCT = lossyd->inverse_DCT[ci]; + output_ptr = output_buf[ci]; + /* Loop over all DCT blocks to be processed. */ + for (block_row = 0; block_row < block_rows; block_row++) { + buffer_ptr = buffer[block_row]; + if (first_row && block_row == 0) + prev_block_row = buffer_ptr; + else + prev_block_row = buffer[block_row-1]; + if (last_row && block_row == block_rows-1) + next_block_row = buffer_ptr; + else + next_block_row = buffer[block_row+1]; + /* We fetch the surrounding DC values using a sliding-register approach. + * Initialize all nine here so as to do the right thing on narrow pics. + */ + DC1 = DC2 = DC3 = (int) prev_block_row[0][0]; + DC4 = DC5 = DC6 = (int) buffer_ptr[0][0]; + DC7 = DC8 = DC9 = (int) next_block_row[0][0]; + output_col = 0; + last_block_column = compptr->width_in_data_units - 1; + for (block_num = 0; block_num <= last_block_column; block_num++) { + /* Fetch current DCT block into workspace so we can modify it. */ + jcopy_block_row(buffer_ptr, (JBLOCKROW) workspace, (JDIMENSION) 1); + /* Update DC values */ + if (block_num < last_block_column) { + DC3 = (int) prev_block_row[1][0]; + DC6 = (int) buffer_ptr[1][0]; + DC9 = (int) next_block_row[1][0]; + } + /* Compute coefficient estimates per K.8. + * An estimate is applied only if coefficient is still zero, + * and is not known to be fully accurate. + */ + /* AC01 */ + if ((Al=coef_bits[1]) != 0 && workspace[1] == 0) { + num = 36 * Q00 * (DC4 - DC6); + if (num >= 0) { + pred = (int) (((Q01<<7) + num) / (Q01<<8)); + if (Al > 0 && pred >= (1< 0 && pred >= (1<= 0) { + pred = (int) (((Q10<<7) + num) / (Q10<<8)); + if (Al > 0 && pred >= (1< 0 && pred >= (1<= 0) { + pred = (int) (((Q20<<7) + num) / (Q20<<8)); + if (Al > 0 && pred >= (1< 0 && pred >= (1<= 0) { + pred = (int) (((Q11<<7) + num) / (Q11<<8)); + if (Al > 0 && pred >= (1< 0 && pred >= (1<= 0) { + pred = (int) (((Q02<<7) + num) / (Q02<<8)); + if (Al > 0 && pred >= (1< 0 && pred >= (1<codec_data_unit; + } + output_ptr += compptr->codec_data_unit; + } + } + + if (++(cinfo->output_iMCU_row) < cinfo->total_iMCU_rows) + return JPEG_ROW_COMPLETED; + return JPEG_SCAN_COMPLETED; +} + +#endif /* BLOCK_SMOOTHING_SUPPORTED */ + + +/* + * Initialize coefficient buffer controller. + */ + +GLOBAL(void) +jinit_d_coef_controller (j_decompress_ptr cinfo, boolean need_full_buffer) +{ + j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec; + d_coef_ptr coef; + + coef = (d_coef_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(d_coef_controller)); + lossyd->coef_private = (void *) coef; + lossyd->coef_start_input_pass = start_input_pass; + lossyd->coef_start_output_pass = start_output_pass; +#ifdef BLOCK_SMOOTHING_SUPPORTED + coef->coef_bits_latch = NULL; +#endif + + /* Create the coefficient buffer. */ + if (need_full_buffer) { +#ifdef D_MULTISCAN_FILES_SUPPORTED + /* Allocate a full-image virtual array for each component, */ + /* padded to a multiple of samp_factor DCT blocks in each direction. */ + /* Note we ask for a pre-zeroed array. */ + int ci, access_rows; + jpeg_component_info *compptr; + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + access_rows = compptr->v_samp_factor; +#ifdef BLOCK_SMOOTHING_SUPPORTED + /* If block smoothing could be used, need a bigger window */ + if (cinfo->process == JPROC_PROGRESSIVE) + access_rows *= 3; +#endif + coef->whole_image[ci] = (*cinfo->mem->request_virt_barray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, TRUE, + (JDIMENSION) jround_up((long) compptr->width_in_data_units, + (long) compptr->h_samp_factor), + (JDIMENSION) jround_up((long) compptr->height_in_data_units, + (long) compptr->v_samp_factor), + (JDIMENSION) access_rows); + } + lossyd->pub.consume_data = consume_data; + lossyd->pub.decompress_data = decompress_data; + lossyd->coef_arrays = coef->whole_image; /* link to virtual arrays */ +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } else { + /* We only need a single-MCU buffer. */ + JBLOCKROW buffer; + int i; + + buffer = (JBLOCKROW) + (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE, + D_MAX_DATA_UNITS_IN_MCU * SIZEOF(JBLOCK)); + for (i = 0; i < D_MAX_DATA_UNITS_IN_MCU; i++) { + coef->MCU_buffer[i] = buffer + i; + } + lossyd->pub.consume_data = dummy_consume_data; + lossyd->pub.decompress_data = decompress_onepass; + lossyd->coef_arrays = NULL; /* flag for no virtual arrays */ + } +} diff --git a/dcmjpeg/libijg8/jdcolor.c b/dcmjpeg/libijg8/jdcolor.c new file mode 100644 index 00000000..91a679ce --- /dev/null +++ b/dcmjpeg/libijg8/jdcolor.c @@ -0,0 +1,413 @@ +/* + * jdcolor.c + * + * Copyright (C) 1991-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains output colorspace conversion routines. + */ + +#define JPEG_INTERNALS +#include "jinclude8.h" +#include "jpeglib8.h" + + +/* Private subobject */ + +typedef struct { + struct jpeg_color_deconverter pub; /* public fields */ + + /* Private state for YCC->RGB conversion */ + int * Cr_r_tab; /* => table for Cr to R conversion */ + int * Cb_b_tab; /* => table for Cb to B conversion */ + IJG_INT32 * Cr_g_tab; /* => table for Cr to G conversion */ + IJG_INT32 * Cb_g_tab; /* => table for Cb to G conversion */ +} my_color_deconverter; + +typedef my_color_deconverter * my_cconvert_ptr; + + +/**************** YCbCr -> RGB conversion: most common case **************/ + +/* + * YCbCr is defined per CCIR 601-1, except that Cb and Cr are + * normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5. + * The conversion equations to be implemented are therefore + * R = Y + 1.40200 * Cr + * G = Y - 0.34414 * Cb - 0.71414 * Cr + * B = Y + 1.77200 * Cb + * where Cb and Cr represent the incoming values less CENTERJSAMPLE. + * (These numbers are derived from TIFF 6.0 section 21, dated 3-June-92.) + * + * To avoid floating-point arithmetic, we represent the fractional constants + * as integers scaled up by 2^16 (about 4 digits precision); we have to divide + * the products by 2^16, with appropriate rounding, to get the correct answer. + * Notice that Y, being an integral input, does not contribute any fraction + * so it need not participate in the rounding. + * + * For even more speed, we avoid doing any multiplications in the inner loop + * by precalculating the constants times Cb and Cr for all possible values. + * For 8-bit JSAMPLEs this is very reasonable (only 256 entries per table); + * for 12-bit samples it is still acceptable. It's not very reasonable for + * 16-bit samples, but if you want lossless storage you shouldn't be changing + * colorspace anyway. + * The Cr=>R and Cb=>B values can be rounded to integers in advance; the + * values for the G calculation are left scaled up, since we must add them + * together before rounding. + */ + +#define SCALEBITS 16 /* speediest right-shift on some machines */ +#define ONE_HALF ((IJG_INT32) 1 << (SCALEBITS-1)) +#define FIX(x) ((IJG_INT32) ((x) * (1L<RGB colorspace conversion. + */ + +LOCAL(void) +build_ycc_rgb_table (j_decompress_ptr cinfo) +{ + my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; + int i; + IJG_INT32 x; +#if BITS_IN_JSAMPLE == 16 + /* no need for temporaries */ +#else + SHIFT_TEMPS +#endif + + cconvert->Cr_r_tab = (int *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (MAXJSAMPLE+1) * SIZEOF(int)); + cconvert->Cb_b_tab = (int *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (MAXJSAMPLE+1) * SIZEOF(int)); + cconvert->Cr_g_tab = (IJG_INT32 *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (MAXJSAMPLE+1) * SIZEOF(IJG_INT32)); + cconvert->Cb_g_tab = (IJG_INT32 *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (MAXJSAMPLE+1) * SIZEOF(IJG_INT32)); + + for (i = 0, x = -CENTERJSAMPLE; i <= MAXJSAMPLE; i++, x++) { + /* i is the actual input pixel value, in the range 0..MAXJSAMPLE */ + /* The Cb or Cr value we are thinking of is x = i - CENTERJSAMPLE */ + +#if BITS_IN_JSAMPLE == 16 + /* Bug fix 2001-11-06 by Eichelberg: The integer routines below + produce an overflow when used with MAXJSAMPLE == 65535. + Use floating point calculation instead. */ + + /* Cr=>R value is nearest int to 1.40200 * x */ + cconvert->Cr_r_tab[i] = (int)(1.40200 * (double)x + 0.5); + /* Cb=>B value is nearest int to 1.77200 * x */ + cconvert->Cb_b_tab[i] = (int)(1.77200 * (double)x + 0.5); +#else + /* Cr=>R value is nearest int to 1.40200 * x */ + cconvert->Cr_r_tab[i] = (int) + RIGHT_SHIFT(FIX(1.40200) * x + ONE_HALF, SCALEBITS); + /* Cb=>B value is nearest int to 1.77200 * x */ + cconvert->Cb_b_tab[i] = (int) + RIGHT_SHIFT(FIX(1.77200) * x + ONE_HALF, SCALEBITS); +#endif + + /* Cr=>G value is scaled-up -0.71414 * x */ + cconvert->Cr_g_tab[i] = (- FIX(0.71414)) * x; + /* Cb=>G value is scaled-up -0.34414 * x */ + /* We also add in ONE_HALF so that need not do it in inner loop */ + cconvert->Cb_g_tab[i] = (- FIX(0.34414)) * x + ONE_HALF; + } +} + + +/* + * Convert some rows of samples to the output colorspace. + * + * Note that we change from noninterleaved, one-plane-per-component format + * to interleaved-pixel format. The output buffer is therefore three times + * as wide as the input buffer. + * A starting row offset is provided only for the input buffer. The caller + * can easily adjust the passed output_buf value to accommodate any row + * offset required on that side. + */ + +METHODDEF(void) +ycc_rgb_convert (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION input_row, + JSAMPARRAY output_buf, int num_rows) +{ + my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; + register int y, cb, cr; + register JSAMPROW outptr; + register JSAMPROW inptr0, inptr1, inptr2; + register JDIMENSION col; + JDIMENSION num_cols = cinfo->output_width; + /* copy these pointers into registers if possible */ + register JSAMPLE * range_limit = cinfo->sample_range_limit; + register int * Crrtab = cconvert->Cr_r_tab; + register int * Cbbtab = cconvert->Cb_b_tab; + register IJG_INT32 * Crgtab = cconvert->Cr_g_tab; + register IJG_INT32 * Cbgtab = cconvert->Cb_g_tab; + SHIFT_TEMPS + + while (--num_rows >= 0) { + inptr0 = input_buf[0][input_row]; + inptr1 = input_buf[1][input_row]; + inptr2 = input_buf[2][input_row]; + input_row++; + outptr = *output_buf++; + for (col = 0; col < num_cols; col++) { + y = GETJSAMPLE(inptr0[col]); + cb = GETJSAMPLE(inptr1[col]); + cr = GETJSAMPLE(inptr2[col]); + /* Range-limiting is essential due to noise introduced by DCT losses. */ + outptr[RGB_RED] = range_limit[y + Crrtab[cr]]; + outptr[RGB_GREEN] = range_limit[y + + ((int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], + SCALEBITS))]; + outptr[RGB_BLUE] = range_limit[y + Cbbtab[cb]]; + outptr += RGB_PIXELSIZE; + } + } +} + + +/**************** Cases other than YCbCr -> RGB **************/ + + +/* + * Color conversion for no colorspace change: just copy the data, + * converting from separate-planes to interleaved representation. + */ + +METHODDEF(void) +null_convert (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION input_row, + JSAMPARRAY output_buf, int num_rows) +{ + register JSAMPROW inptr, outptr; + register JDIMENSION count; + register int num_components = cinfo->num_components; + JDIMENSION num_cols = cinfo->output_width; + int ci; + + while (--num_rows >= 0) { + for (ci = 0; ci < num_components; ci++) { + inptr = input_buf[ci][input_row]; + outptr = output_buf[0] + ci; + for (count = num_cols; count > 0; count--) { + *outptr = *inptr++; /* needn't bother with GETJSAMPLE() here */ + outptr += num_components; + } + } + input_row++; + output_buf++; + } +} + + +/* + * Color conversion for grayscale: just copy the data. + * This also works for YCbCr -> grayscale conversion, in which + * we just copy the Y (luminance) component and ignore chrominance. + */ + +METHODDEF(void) +grayscale_convert (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION input_row, + JSAMPARRAY output_buf, int num_rows) +{ + jcopy_sample_rows(input_buf[0], (int) input_row, output_buf, 0, + num_rows, cinfo->output_width); +} + + +/* + * Convert grayscale to RGB: just duplicate the graylevel three times. + * This is provided to support applications that don't want to cope + * with grayscale as a separate case. + */ + +METHODDEF(void) +gray_rgb_convert (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION input_row, + JSAMPARRAY output_buf, int num_rows) +{ + register JSAMPROW inptr, outptr; + register JDIMENSION col; + JDIMENSION num_cols = cinfo->output_width; + + while (--num_rows >= 0) { + inptr = input_buf[0][input_row++]; + outptr = *output_buf++; + for (col = 0; col < num_cols; col++) { + /* We can dispense with GETJSAMPLE() here */ + outptr[RGB_RED] = outptr[RGB_GREEN] = outptr[RGB_BLUE] = inptr[col]; + outptr += RGB_PIXELSIZE; + } + } +} + + +/* + * Adobe-style YCCK->CMYK conversion. + * We convert YCbCr to R=1-C, G=1-M, and B=1-Y using the same + * conversion as above, while passing K (black) unchanged. + * We assume build_ycc_rgb_table has been called. + */ + +METHODDEF(void) +ycck_cmyk_convert (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION input_row, + JSAMPARRAY output_buf, int num_rows) +{ + my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; + register int y, cb, cr; + register JSAMPROW outptr; + register JSAMPROW inptr0, inptr1, inptr2, inptr3; + register JDIMENSION col; + JDIMENSION num_cols = cinfo->output_width; + /* copy these pointers into registers if possible */ + register JSAMPLE * range_limit = cinfo->sample_range_limit; + register int * Crrtab = cconvert->Cr_r_tab; + register int * Cbbtab = cconvert->Cb_b_tab; + register IJG_INT32 * Crgtab = cconvert->Cr_g_tab; + register IJG_INT32 * Cbgtab = cconvert->Cb_g_tab; + SHIFT_TEMPS + + while (--num_rows >= 0) { + inptr0 = input_buf[0][input_row]; + inptr1 = input_buf[1][input_row]; + inptr2 = input_buf[2][input_row]; + inptr3 = input_buf[3][input_row]; + input_row++; + outptr = *output_buf++; + for (col = 0; col < num_cols; col++) { + y = GETJSAMPLE(inptr0[col]); + cb = GETJSAMPLE(inptr1[col]); + cr = GETJSAMPLE(inptr2[col]); + /* Range-limiting is essential due to noise introduced by DCT losses. */ + outptr[0] = range_limit[MAXJSAMPLE - (y + Crrtab[cr])]; /* red */ + outptr[1] = range_limit[MAXJSAMPLE - (y + /* green */ + ((int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], + SCALEBITS)))]; + outptr[2] = range_limit[MAXJSAMPLE - (y + Cbbtab[cb])]; /* blue */ + /* K passes through unchanged */ + outptr[3] = inptr3[col]; /* don't need GETJSAMPLE here */ + outptr += 4; + } + } +} + + +/* + * Empty method for start_pass. + */ + +METHODDEF(void) +start_pass_dcolor (j_decompress_ptr cinfo) +{ + /* no work needed */ +} + + +/* + * Module initialization routine for output colorspace conversion. + */ + +GLOBAL(void) +jinit_color_deconverter (j_decompress_ptr cinfo) +{ + my_cconvert_ptr cconvert; + int ci; + + cconvert = (my_cconvert_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_color_deconverter)); + cinfo->cconvert = (struct jpeg_color_deconverter *) cconvert; + cconvert->pub.start_pass = start_pass_dcolor; + + /* Make sure num_components agrees with jpeg_color_space */ + switch (cinfo->jpeg_color_space) { + case JCS_GRAYSCALE: + if (cinfo->num_components != 1) + ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); + break; + + case JCS_RGB: + case JCS_YCbCr: + if (cinfo->num_components != 3) + ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); + break; + + case JCS_CMYK: + case JCS_YCCK: + if (cinfo->num_components != 4) + ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); + break; + + default: /* JCS_UNKNOWN can be anything */ + if (cinfo->num_components < 1) + ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); + break; + } + + /* Set out_color_components and conversion method based on requested space. + * Also clear the component_needed flags for any unused components, + * so that earlier pipeline stages can avoid useless computation. + */ + + switch (cinfo->out_color_space) { + case JCS_GRAYSCALE: + cinfo->out_color_components = 1; + if (cinfo->jpeg_color_space == JCS_GRAYSCALE || + cinfo->jpeg_color_space == JCS_YCbCr) { + cconvert->pub.color_convert = grayscale_convert; + /* For color->grayscale conversion, only the Y (0) component is needed */ + for (ci = 1; ci < cinfo->num_components; ci++) + cinfo->comp_info[ci].component_needed = FALSE; + } else + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); + break; + + case JCS_RGB: + cinfo->out_color_components = RGB_PIXELSIZE; + if (cinfo->jpeg_color_space == JCS_YCbCr) { + cconvert->pub.color_convert = ycc_rgb_convert; + build_ycc_rgb_table(cinfo); + } else if (cinfo->jpeg_color_space == JCS_GRAYSCALE) { + cconvert->pub.color_convert = gray_rgb_convert; + } else if (cinfo->jpeg_color_space == JCS_RGB && RGB_PIXELSIZE == 3) { + cconvert->pub.color_convert = null_convert; + } else + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); + break; + + case JCS_CMYK: + cinfo->out_color_components = 4; + if (cinfo->jpeg_color_space == JCS_YCCK) { + cconvert->pub.color_convert = ycck_cmyk_convert; + build_ycc_rgb_table(cinfo); + } else if (cinfo->jpeg_color_space == JCS_CMYK) { + cconvert->pub.color_convert = null_convert; + } else + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); + break; + + default: + /* Permit null conversion to same output space */ + if (cinfo->out_color_space == cinfo->jpeg_color_space) { + cinfo->out_color_components = cinfo->num_components; + cconvert->pub.color_convert = null_convert; + } else /* unsupported non-null conversion */ + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); + break; + } + + if (cinfo->quantize_colors) + cinfo->output_components = 1; /* single colormapped output component */ + else + cinfo->output_components = cinfo->out_color_components; +} diff --git a/dcmjpeg/libijg8/jdct8.h b/dcmjpeg/libijg8/jdct8.h new file mode 100644 index 00000000..55ed102c --- /dev/null +++ b/dcmjpeg/libijg8/jdct8.h @@ -0,0 +1,176 @@ +/* + * jdct.h + * + * Copyright (C) 1994-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This include file contains common declarations for the forward and + * inverse DCT modules. These declarations are private to the DCT managers + * (jcdctmgr.c, jddctmgr.c) and the individual DCT algorithms. + * The individual DCT algorithms are kept in separate files to ease + * machine-dependent tuning (e.g., assembly coding). + */ + + +/* + * A forward DCT routine is given a pointer to a work area of type DCTELEM[]; + * the DCT is to be performed in-place in that buffer. Type DCTELEM is int + * for 8-bit samples, IJG_INT32 for 12-bit samples. (NOTE: Floating-point DCT + * implementations use an array of type FAST_FLOAT, instead.) + * The DCT inputs are expected to be signed (range +-CENTERJSAMPLE). + * The DCT outputs are returned scaled up by a factor of 8; they therefore + * have a range of +-8K for 8-bit data, +-128K for 12-bit data. This + * convention improves accuracy in integer implementations and saves some + * work in floating-point ones. + * Quantization of the output coefficients is done by jcdctmgr.c. + */ + +#if BITS_IN_JSAMPLE == 8 +typedef int DCTELEM; /* 16 or 32 bits is fine */ +#else +typedef IJG_INT32 DCTELEM; /* must have 32 bits */ +#endif + +typedef JMETHOD(void, forward_DCT_method_ptr, (DCTELEM * data)); +typedef JMETHOD(void, float_DCT_method_ptr, (FAST_FLOAT * data)); + + +/* + * An inverse DCT routine is given a pointer to the input JBLOCK and a pointer + * to an output sample array. The routine must dequantize the input data as + * well as perform the IDCT; for dequantization, it uses the multiplier table + * pointed to by compptr->dct_table. The output data is to be placed into the + * sample array starting at a specified column. (Any row offset needed will + * be applied to the array pointer before it is passed to the IDCT code.) + * Note that the number of samples emitted by the IDCT routine is + * DCT_scaled_size * DCT_scaled_size. + */ + +/* typedef inverse_DCT_method_ptr is declared in jpegint.h */ + +/* + * Each IDCT routine has its own ideas about the best dct_table element type. + */ + +typedef MULTIPLIER ISLOW_MULT_TYPE; /* short or int, whichever is faster */ +#if BITS_IN_JSAMPLE == 8 +typedef MULTIPLIER IFAST_MULT_TYPE; /* 16 bits is OK, use short if faster */ +#define IFAST_SCALE_BITS 2 /* fractional bits in scale factors */ +#else +typedef IJG_INT32 IFAST_MULT_TYPE; /* need 32 bits for scaled quantizers */ +#define IFAST_SCALE_BITS 13 /* fractional bits in scale factors */ +#endif +typedef FAST_FLOAT FLOAT_MULT_TYPE; /* preferred floating type */ + + +/* + * Each IDCT routine is responsible for range-limiting its results and + * converting them to unsigned form (0..MAXJSAMPLE). The raw outputs could + * be quite far out of range if the input data is corrupt, so a bulletproof + * range-limiting step is required. We use a mask-and-table-lookup method + * to do the combined operations quickly. See the comments with + * prepare_range_limit_table (in jdmaster.c) for more info. + */ + +#define IDCT_range_limit(cinfo) ((cinfo)->sample_range_limit + CENTERJSAMPLE) + +#define RANGE_MASK (MAXJSAMPLE * 4 + 3) /* 2 bits wider than legal samples */ + + +/* Short forms of external names for systems with brain-damaged linkers. */ + +#ifdef NEED_SHORT_EXTERNAL_NAMES +#define jpeg_fdct_islow jpeg8_fdct_islow +#define jpeg_fdct_ifast jpeg8_fdct_ifast +#define jpeg_fdct_float jpeg8_fdct_float +#define jpeg_idct_islow jpeg8_idct_islow +#define jpeg_idct_ifast jpeg8_idct_ifast +#define jpeg_idct_float jpeg8_idct_float +#define jpeg_idct_4x4 jpeg8_idct_4x4 +#define jpeg_idct_2x2 jpeg8_idct_2x2 +#define jpeg_idct_1x1 jpeg8_idct_1x1 +#endif /* NEED_SHORT_EXTERNAL_NAMES */ + +/* Extern declarations for the forward and inverse DCT routines. */ + +EXTERN(void) jpeg_fdct_islow JPP((DCTELEM * data)); +EXTERN(void) jpeg_fdct_ifast JPP((DCTELEM * data)); +EXTERN(void) jpeg_fdct_float JPP((FAST_FLOAT * data)); + +EXTERN(void) jpeg_idct_islow + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_ifast + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_float + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_4x4 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_2x2 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_1x1 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); + + +/* + * Macros for handling fixed-point arithmetic; these are used by many + * but not all of the DCT/IDCT modules. + * + * All values are expected to be of type IJG_INT32. + * Fractional constants are scaled left by CONST_BITS bits. + * CONST_BITS is defined within each module using these macros, + * and may differ from one module to the next. + */ + +#define ONE ((IJG_INT32) 1) +#define CONST_SCALE (ONE << CONST_BITS) + +/* Convert a positive real constant to an integer scaled by CONST_SCALE. + * Caution: some C compilers fail to reduce "FIX(constant)" at compile time, + * thus causing a lot of useless floating-point operations at run time. + */ + +#define FIX(x) ((IJG_INT32) ((x) * CONST_SCALE + 0.5)) + +/* Descale and correctly round an IJG_INT32 value that's scaled by N bits. + * We assume RIGHT_SHIFT rounds towards minus infinity, so adding + * the fudge factor is correct for either sign of X. + */ + +#define DESCALE(x,n) RIGHT_SHIFT((x) + (ONE << ((n)-1)), n) + +/* Multiply an IJG_INT32 variable by an IJG_INT32 constant to yield an IJG_INT32 result. + * This macro is used only when the two inputs will actually be no more than + * 16 bits wide, so that a 16x16->32 bit multiply can be used instead of a + * full 32x32 multiply. This provides a useful speedup on many machines. + * Unfortunately there is no way to specify a 16x16->32 multiply portably + * in C, but some C compilers will do the right thing if you provide the + * correct combination of casts. + */ + +#ifdef SHORTxSHORT_32 /* may work if 'int' is 32 bits */ +#define MULTIPLY16C16(var,const) (((INT16) (var)) * ((INT16) (const))) +#endif +#ifdef SHORTxLCONST_32 /* known to work with Microsoft C 6.0 */ +#define MULTIPLY16C16(var,const) (((INT16) (var)) * ((IJG_INT32) (const))) +#endif + +#ifndef MULTIPLY16C16 /* default definition */ +#define MULTIPLY16C16(var,const) ((var) * (const)) +#endif + +/* Same except both inputs are variables. */ + +#ifdef SHORTxSHORT_32 /* may work if 'int' is 32 bits */ +#define MULTIPLY16V16(var1,var2) (((INT16) (var1)) * ((INT16) (var2))) +#endif + +#ifndef MULTIPLY16V16 /* default definition */ +#define MULTIPLY16V16(var1,var2) ((var1) * (var2)) +#endif diff --git a/dcmjpeg/libijg8/jddctmgr.c b/dcmjpeg/libijg8/jddctmgr.c new file mode 100644 index 00000000..ac053ffa --- /dev/null +++ b/dcmjpeg/libijg8/jddctmgr.c @@ -0,0 +1,270 @@ +/* + * jddctmgr.c + * + * Copyright (C) 1994-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains the inverse-DCT management logic. + * This code selects a particular IDCT implementation to be used, + * and it performs related housekeeping chores. No code in this file + * is executed per IDCT step, only during output pass setup. + * + * Note that the IDCT routines are responsible for performing coefficient + * dequantization as well as the IDCT proper. This module sets up the + * dequantization multiplier table needed by the IDCT routine. + */ + +#define JPEG_INTERNALS +#include "jinclude8.h" +#include "jpeglib8.h" +#include "jlossy8.h" /* Private declarations for lossy subsystem */ +#include "jdct8.h" /* Private declarations for DCT subsystem */ + + +/* + * The decompressor input side (jdinput.c) saves away the appropriate + * quantization table for each component at the start of the first scan + * involving that component. (This is necessary in order to correctly + * decode files that reuse Q-table slots.) + * When we are ready to make an output pass, the saved Q-table is converted + * to a multiplier table that will actually be used by the IDCT routine. + * The multiplier table contents are IDCT-method-dependent. To support + * application changes in IDCT method between scans, we can remake the + * multiplier tables if necessary. + * In buffered-image mode, the first output pass may occur before any data + * has been seen for some components, and thus before their Q-tables have + * been saved away. To handle this case, multiplier tables are preset + * to zeroes; the result of the IDCT will be a neutral gray level. + */ + + +/* Private subobject for this module */ + +typedef struct { + /* This array contains the IDCT method code that each multiplier table + * is currently set up for, or -1 if it's not yet set up. + * The actual multiplier tables are pointed to by dct_table in the + * per-component comp_info structures. + */ + int cur_method[MAX_COMPONENTS]; +} idct_controller; + +typedef idct_controller * idct_ptr; + + +/* Allocated multiplier tables: big enough for any supported variant */ + +typedef union { + ISLOW_MULT_TYPE islow_array[DCTSIZE2]; +#ifdef DCT_IFAST_SUPPORTED + IFAST_MULT_TYPE ifast_array[DCTSIZE2]; +#endif +#ifdef DCT_FLOAT_SUPPORTED + FLOAT_MULT_TYPE float_array[DCTSIZE2]; +#endif +} multiplier_table; + + +/* The current scaled-IDCT routines require ISLOW-style multiplier tables, + * so be sure to compile that code if either ISLOW or SCALING is requested. + */ +#ifdef DCT_ISLOW_SUPPORTED +#define PROVIDE_ISLOW_TABLES +#else +#ifdef IDCT_SCALING_SUPPORTED +#define PROVIDE_ISLOW_TABLES +#endif +#endif + + +/* + * Prepare for an output pass. + * Here we select the proper IDCT routine for each component and build + * a matching multiplier table. + */ + +METHODDEF(void) +start_pass (j_decompress_ptr cinfo) +{ + j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec; + idct_ptr idct = (idct_ptr) lossyd->idct_private; + int ci, i; + jpeg_component_info *compptr; + int method = 0; + inverse_DCT_method_ptr method_ptr = NULL; + JQUANT_TBL * qtbl; + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + /* Select the proper IDCT routine for this component's scaling */ + switch (compptr->codec_data_unit) { +#ifdef IDCT_SCALING_SUPPORTED + case 1: + method_ptr = jpeg_idct_1x1; + method = JDCT_ISLOW; /* jidctred uses islow-style table */ + break; + case 2: + method_ptr = jpeg_idct_2x2; + method = JDCT_ISLOW; /* jidctred uses islow-style table */ + break; + case 4: + method_ptr = jpeg_idct_4x4; + method = JDCT_ISLOW; /* jidctred uses islow-style table */ + break; +#endif + case DCTSIZE: + switch (cinfo->dct_method) { +#ifdef DCT_ISLOW_SUPPORTED + case JDCT_ISLOW: + method_ptr = jpeg_idct_islow; + method = JDCT_ISLOW; + break; +#endif +#ifdef DCT_IFAST_SUPPORTED + case JDCT_IFAST: + method_ptr = jpeg_idct_ifast; + method = JDCT_IFAST; + break; +#endif +#ifdef DCT_FLOAT_SUPPORTED + case JDCT_FLOAT: + method_ptr = jpeg_idct_float; + method = JDCT_FLOAT; + break; +#endif + default: + ERREXIT(cinfo, JERR_NOT_COMPILED); + break; + } + break; + default: + ERREXIT1(cinfo, JERR_BAD_DCTSIZE, compptr->codec_data_unit); + break; + } + lossyd->inverse_DCT[ci] = method_ptr; + /* Create multiplier table from quant table. + * However, we can skip this if the component is uninteresting + * or if we already built the table. Also, if no quant table + * has yet been saved for the component, we leave the + * multiplier table all-zero; we'll be reading zeroes from the + * coefficient controller's buffer anyway. + */ + if (! compptr->component_needed || idct->cur_method[ci] == method) + continue; + qtbl = compptr->quant_table; + if (qtbl == NULL) /* happens if no data yet for component */ + continue; + idct->cur_method[ci] = method; + switch (method) { +#ifdef PROVIDE_ISLOW_TABLES + case JDCT_ISLOW: + { + /* For LL&M IDCT method, multipliers are equal to raw quantization + * coefficients, but are stored as ints to ensure access efficiency. + */ + ISLOW_MULT_TYPE * ismtbl = (ISLOW_MULT_TYPE *) compptr->dct_table; + for (i = 0; i < DCTSIZE2; i++) { + ismtbl[i] = (ISLOW_MULT_TYPE) qtbl->quantval[i]; + } + } + break; +#endif +#ifdef DCT_IFAST_SUPPORTED + case JDCT_IFAST: + { + /* For AA&N IDCT method, multipliers are equal to quantization + * coefficients scaled by scalefactor[row]*scalefactor[col], where + * scalefactor[0] = 1 + * scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7 + * For integer operation, the multiplier table is to be scaled by + * IFAST_SCALE_BITS. + */ + IFAST_MULT_TYPE * ifmtbl = (IFAST_MULT_TYPE *) compptr->dct_table; +#define CONST_BITS 14 + static const INT16 aanscales[DCTSIZE2] = { + /* precomputed values scaled up by 14 bits */ + 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520, + 22725, 31521, 29692, 26722, 22725, 17855, 12299, 6270, + 21407, 29692, 27969, 25172, 21407, 16819, 11585, 5906, + 19266, 26722, 25172, 22654, 19266, 15137, 10426, 5315, + 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520, + 12873, 17855, 16819, 15137, 12873, 10114, 6967, 3552, + 8867, 12299, 11585, 10426, 8867, 6967, 4799, 2446, + 4520, 6270, 5906, 5315, 4520, 3552, 2446, 1247 + }; + SHIFT_TEMPS + + for (i = 0; i < DCTSIZE2; i++) { + ifmtbl[i] = (IFAST_MULT_TYPE) + DESCALE(MULTIPLY16V16((IJG_INT32) qtbl->quantval[i], + (IJG_INT32) aanscales[i]), + CONST_BITS-IFAST_SCALE_BITS); + } + } + break; +#endif +#ifdef DCT_FLOAT_SUPPORTED + case JDCT_FLOAT: + { + /* For float AA&N IDCT method, multipliers are equal to quantization + * coefficients scaled by scalefactor[row]*scalefactor[col], where + * scalefactor[0] = 1 + * scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7 + */ + FLOAT_MULT_TYPE * fmtbl = (FLOAT_MULT_TYPE *) compptr->dct_table; + int row, col; + static const double aanscalefactor[DCTSIZE] = { + 1.0, 1.387039845, 1.306562965, 1.175875602, + 1.0, 0.785694958, 0.541196100, 0.275899379 + }; + + i = 0; + for (row = 0; row < DCTSIZE; row++) { + for (col = 0; col < DCTSIZE; col++) { + fmtbl[i] = (FLOAT_MULT_TYPE) + ((double) qtbl->quantval[i] * + aanscalefactor[row] * aanscalefactor[col]); + i++; + } + } + } + break; +#endif + default: + ERREXIT(cinfo, JERR_NOT_COMPILED); + break; + } + } +} + + +/* + * Initialize IDCT manager. + */ + +GLOBAL(void) +jinit_inverse_dct (j_decompress_ptr cinfo) +{ + j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec; + idct_ptr idct; + int ci; + jpeg_component_info *compptr; + + idct = (idct_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(idct_controller)); + lossyd->idct_private = (void *) idct; + lossyd->idct_start_pass = start_pass; + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + /* Allocate and pre-zero a multiplier table for each component */ + compptr->dct_table = + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(multiplier_table)); + MEMZERO(compptr->dct_table, SIZEOF(multiplier_table)); + /* Mark multiplier table not yet set up for any method */ + idct->cur_method[ci] = -1; + } +} diff --git a/dcmjpeg/libijg8/jddiffct.c b/dcmjpeg/libijg8/jddiffct.c new file mode 100644 index 00000000..3988c82d --- /dev/null +++ b/dcmjpeg/libijg8/jddiffct.c @@ -0,0 +1,399 @@ +/* + * jddiffct.c + * + * Copyright (C) 1994-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains the [un]difference buffer controller for decompression. + * This controller is the top level of the lossless JPEG decompressor proper. + * The difference buffer lies between the entropy decoding and + * prediction/undifferencing steps. The undifference buffer lies between the + * prediction/undifferencing and scaling steps. + * + * In buffered-image mode, this controller is the interface between + * input-oriented processing and output-oriented processing. + */ + +#define JPEG_INTERNALS +#include "jinclude8.h" +#include "jpeglib8.h" +#include "jlossls8.h" + + +#ifdef D_LOSSLESS_SUPPORTED + +/* Private buffer controller object */ + +typedef struct { + /* These variables keep track of the current location of the input side. */ + /* cinfo->input_iMCU_row is also used for this. */ + JDIMENSION MCU_ctr; /* counts MCUs processed in current row */ + unsigned int restart_rows_to_go; /* MCU-rows left in this restart interval */ + unsigned int MCU_vert_offset; /* counts MCU rows within iMCU row */ + unsigned int MCU_rows_per_iMCU_row; /* number of such rows needed */ + + /* The output side's location is represented by cinfo->output_iMCU_row. */ + + JDIFFARRAY diff_buf[MAX_COMPONENTS]; /* iMCU row of differences */ + JDIFFARRAY undiff_buf[MAX_COMPONENTS]; /* iMCU row of undiff'd samples */ + +#ifdef D_MULTISCAN_FILES_SUPPORTED + /* In multi-pass modes, we need a virtual sample array for each component. */ + jvirt_sarray_ptr whole_image[MAX_COMPONENTS]; +#endif +} d_diff_controller; + +typedef d_diff_controller * d_diff_ptr; + +/* Forward declarations */ +METHODDEF(int) decompress_data + JPP((j_decompress_ptr cinfo, JSAMPIMAGE output_buf)); +#ifdef D_MULTISCAN_FILES_SUPPORTED +METHODDEF(int) output_data + JPP((j_decompress_ptr cinfo, JSAMPIMAGE output_buf)); +#endif + + +LOCAL(void) +start_iMCU_row (j_decompress_ptr cinfo) +/* Reset within-iMCU-row counters for a new row (input side) */ +{ + j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec; + d_diff_ptr diff = (d_diff_ptr) losslsd->diff_private; + + /* In an interleaved scan, an MCU row is the same as an iMCU row. + * In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows. + * But at the bottom of the image, process only what's left. + */ + if (cinfo->comps_in_scan > 1) { + diff->MCU_rows_per_iMCU_row = 1; + } else { + if (cinfo->input_iMCU_row < (cinfo->total_iMCU_rows-1)) + diff->MCU_rows_per_iMCU_row = (JDIMENSION)cinfo->cur_comp_info[0]->v_samp_factor; + else + diff->MCU_rows_per_iMCU_row = (JDIMENSION)cinfo->cur_comp_info[0]->last_row_height; + } + + diff->MCU_ctr = 0; + diff->MCU_vert_offset = 0; +} + + +/* + * Initialize for an input processing pass. + */ + +METHODDEF(void) +start_input_pass (j_decompress_ptr cinfo) +{ + j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec; + d_diff_ptr diff = (d_diff_ptr) losslsd->diff_private; + + /* Check that the restart interval is an integer multiple of the number + * of MCU in an MCU-row. + */ + if (cinfo->restart_interval % cinfo->MCUs_per_row != 0) + ERREXIT2(cinfo, JERR_BAD_RESTART, + (int)cinfo->restart_interval, (int)cinfo->MCUs_per_row); + + /* Initialize restart counter */ + diff->restart_rows_to_go = cinfo->restart_interval / cinfo->MCUs_per_row; + + cinfo->input_iMCU_row = 0; + start_iMCU_row(cinfo); +} + + +/* + * Check for a restart marker & resynchronize decoder, undifferencer. + * Returns FALSE if must suspend. + */ + +METHODDEF(boolean) +process_restart (j_decompress_ptr cinfo) +{ + j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec; + d_diff_ptr diff = (d_diff_ptr) losslsd->diff_private; + + if (! (*losslsd->entropy_process_restart) (cinfo)) + return FALSE; + + (*losslsd->predict_process_restart) (cinfo); + + /* Reset restart counter */ + diff->restart_rows_to_go = cinfo->restart_interval / cinfo->MCUs_per_row; + + return TRUE; +} + + +/* + * Initialize for an output processing pass. + */ + +METHODDEF(void) +start_output_pass (j_decompress_ptr cinfo) +{ + cinfo->output_iMCU_row = 0; +} + + +/* + * Decompress and return some data in the supplied buffer. + * Always attempts to emit one fully interleaved MCU row ("iMCU" row). + * Input and output must run in lockstep since we have only a one-MCU buffer. + * Return value is JPEG_ROW_COMPLETED, JPEG_SCAN_COMPLETED, or JPEG_SUSPENDED. + * + * NB: output_buf contains a plane for each component in image, + * which we index according to the component's SOF position. + */ + +METHODDEF(int) +decompress_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf) +{ + j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec; + d_diff_ptr diff = (d_diff_ptr) losslsd->diff_private; + JDIMENSION MCU_col_num; /* index of current MCU within row */ + JDIMENSION MCU_count; /* number of MCUs decoded */ + JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; + int comp, ci, row, prev_row; + unsigned int yoffset; + jpeg_component_info *compptr; + + /* Loop to process as much as one whole iMCU row */ + for (yoffset = diff->MCU_vert_offset; yoffset < diff->MCU_rows_per_iMCU_row; + yoffset++) { + + /* Process restart marker if needed; may have to suspend */ + if (cinfo->restart_interval) { + if (diff->restart_rows_to_go == 0) + if (! process_restart(cinfo)) + return JPEG_SUSPENDED; + } + + MCU_col_num = diff->MCU_ctr; + /* Try to fetch an MCU-row (or remaining portion of suspended MCU-row). */ + MCU_count = + (*losslsd->entropy_decode_mcus) (cinfo, + diff->diff_buf, yoffset, MCU_col_num, + cinfo->MCUs_per_row - MCU_col_num); + if (MCU_count != cinfo->MCUs_per_row - MCU_col_num) { + /* Suspension forced; update state counters and exit */ + diff->MCU_vert_offset = yoffset; + diff->MCU_ctr += MCU_count; + return JPEG_SUSPENDED; + } + + /* Account for restart interval (no-op if not using restarts) */ + diff->restart_rows_to_go--; + + /* Completed an MCU row, but perhaps not an iMCU row */ + diff->MCU_ctr = 0; + } + + /* + * Undifference and scale each scanline of the disassembled MCU-row + * separately. We do not process dummy samples at the end of a scanline + * or dummy rows at the end of the image. + */ + for (comp = 0; comp < cinfo->comps_in_scan; comp++) { + compptr = cinfo->cur_comp_info[comp]; + ci = compptr->component_index; + for (row = 0, prev_row = compptr->v_samp_factor - 1; + row < (cinfo->input_iMCU_row == last_iMCU_row ? + compptr->last_row_height : compptr->v_samp_factor); + prev_row = row, row++) { + (*losslsd->predict_undifference[ci]) (cinfo, ci, + diff->diff_buf[ci][row], + diff->undiff_buf[ci][prev_row], + diff->undiff_buf[ci][row], + compptr->width_in_data_units); + (*losslsd->scaler_scale) (cinfo, diff->undiff_buf[ci][row], + output_buf[ci][row], + compptr->width_in_data_units); + } + } + + /* Completed the iMCU row, advance counters for next one. + * + * NB: output_data will increment output_iMCU_row. + * This counter is not needed for the single-pass case + * or the input side of the multi-pass case. + */ + if (++(cinfo->input_iMCU_row) < cinfo->total_iMCU_rows) { + start_iMCU_row(cinfo); + return JPEG_ROW_COMPLETED; + } + /* Completed the scan */ + (*cinfo->inputctl->finish_input_pass) (cinfo); + return JPEG_SCAN_COMPLETED; +} + + +/* + * Dummy consume-input routine for single-pass operation. + */ + +METHODDEF(int) +dummy_consume_data (j_decompress_ptr cinfo) +{ + return JPEG_SUSPENDED; /* Always indicate nothing was done */ +} + + +#ifdef D_MULTISCAN_FILES_SUPPORTED + +/* + * Consume input data and store it in the full-image sample buffer. + * We read as much as one fully interleaved MCU row ("iMCU" row) per call, + * ie, v_samp_factor rows for each component in the scan. + * Return value is JPEG_ROW_COMPLETED, JPEG_SCAN_COMPLETED, or JPEG_SUSPENDED. + */ + +METHODDEF(int) +consume_data (j_decompress_ptr cinfo) +{ + j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec; + d_diff_ptr diff = (d_diff_ptr) losslsd->diff_private; + /* JDIMENSION MCU_col_num; */ /* index of current MCU within row */ + /* JDIMENSION MCU_count; */ /* number of MCUs decoded */ + /* JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; */ + int comp, ci /* , yoffset, row, prev_row */; + JSAMPARRAY buffer[MAX_COMPS_IN_SCAN]; + jpeg_component_info *compptr; + + /* Align the virtual buffers for the components used in this scan. */ + for (comp = 0; comp < cinfo->comps_in_scan; comp++) { + compptr = cinfo->cur_comp_info[comp]; + ci = compptr->component_index; + buffer[ci] = (*cinfo->mem->access_virt_sarray) + ((j_common_ptr) cinfo, diff->whole_image[ci], + cinfo->input_iMCU_row * (JDIMENSION)compptr->v_samp_factor, + (JDIMENSION) compptr->v_samp_factor, TRUE); + } + + return decompress_data(cinfo, buffer); +} + + +/* + * Output some data from the full-image buffer sample in the multi-pass case. + * Always attempts to emit one fully interleaved MCU row ("iMCU" row). + * Return value is JPEG_ROW_COMPLETED, JPEG_SCAN_COMPLETED, or JPEG_SUSPENDED. + * + * NB: output_buf contains a plane for each component in image. + */ + +METHODDEF(int) +output_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf) +{ + j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec; + d_diff_ptr diff = (d_diff_ptr) losslsd->diff_private; + JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; + int ci, samp_rows, row; + JSAMPARRAY buffer; + jpeg_component_info *compptr; + + /* Force some input to be done if we are getting ahead of the input. */ + while (cinfo->input_scan_number < cinfo->output_scan_number || + (cinfo->input_scan_number == cinfo->output_scan_number && + cinfo->input_iMCU_row <= cinfo->output_iMCU_row)) { + if ((*cinfo->inputctl->consume_input)(cinfo) == JPEG_SUSPENDED) + return JPEG_SUSPENDED; + } + + /* OK, output from the virtual arrays. */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + /* Align the virtual buffer for this component. */ + buffer = (*cinfo->mem->access_virt_sarray) + ((j_common_ptr) cinfo, diff->whole_image[ci], + cinfo->output_iMCU_row * (JDIMENSION)compptr->v_samp_factor, + (JDIMENSION) compptr->v_samp_factor, FALSE); + + if (cinfo->output_iMCU_row < last_iMCU_row) + samp_rows = compptr->v_samp_factor; + else { + /* NB: can't use last_row_height here; it is input-side-dependent! */ + samp_rows = (int)compptr->height_in_data_units % compptr->v_samp_factor; + if (samp_rows == 0) samp_rows = compptr->v_samp_factor; + } + + for (row = 0; row < samp_rows; row++) { + MEMCOPY(output_buf[ci][row], buffer[row], + compptr->width_in_data_units * SIZEOF(JSAMPLE)); + } + } + + if (++(cinfo->output_iMCU_row) < cinfo->total_iMCU_rows) + return JPEG_ROW_COMPLETED; + return JPEG_SCAN_COMPLETED; +} + +#endif /* D_MULTISCAN_FILES_SUPPORTED */ + + +/* + * Initialize difference buffer controller. + */ + +GLOBAL(void) +jinit_d_diff_controller (j_decompress_ptr cinfo, boolean need_full_buffer) +{ + j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec; + d_diff_ptr diff; + int ci; + jpeg_component_info *compptr; + + diff = (d_diff_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(d_diff_controller)); + losslsd->diff_private = (void *) diff; + losslsd->diff_start_input_pass = start_input_pass; + losslsd->pub.start_output_pass = start_output_pass; + + /* Create the [un]difference buffers. */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + diff->diff_buf[ci] = (*cinfo->mem->alloc_darray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + (JDIMENSION) jround_up((long) compptr->width_in_data_units, + (long) compptr->h_samp_factor), + (JDIMENSION) compptr->v_samp_factor); + diff->undiff_buf[ci] = (*cinfo->mem->alloc_darray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + (JDIMENSION) jround_up((long) compptr->width_in_data_units, + (long) compptr->h_samp_factor), + (JDIMENSION) compptr->v_samp_factor); + } + + if (need_full_buffer) { +#ifdef D_MULTISCAN_FILES_SUPPORTED + /* Allocate a full-image virtual array for each component. */ + int access_rows; + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + access_rows = compptr->v_samp_factor; + diff->whole_image[ci] = (*cinfo->mem->request_virt_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE, + (JDIMENSION) jround_up((long) compptr->width_in_data_units, + (long) compptr->h_samp_factor), + (JDIMENSION) jround_up((long) compptr->height_in_data_units, + (long) compptr->v_samp_factor), + (JDIMENSION) access_rows); + } + losslsd->pub.consume_data = consume_data; + losslsd->pub.decompress_data = output_data; +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } else { + losslsd->pub.consume_data = dummy_consume_data; + losslsd->pub.decompress_data = decompress_data; + diff->whole_image[0] = NULL; /* flag for no virtual arrays */ + } +} + +#endif /* D_LOSSLESS_SUPPORTED */ diff --git a/dcmjpeg/libijg8/jdhuff.c b/dcmjpeg/libijg8/jdhuff.c new file mode 100644 index 00000000..dc21e48f --- /dev/null +++ b/dcmjpeg/libijg8/jdhuff.c @@ -0,0 +1,316 @@ +/* + * jdhuff.c + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains Huffman entropy decoding routines which are shared + * by the sequential, progressive and lossless decoders. + */ + +#define JPEG_INTERNALS +#include "jinclude8.h" +#include "jpeglib8.h" +#include "jlossy8.h" /* Private declarations for lossy codec */ +#include "jlossls8.h" /* Private declarations for lossless codec */ +#include "jdhuff8.h" /* Declarations shared with jd*huff.c */ + + +/* + * Compute the derived values for a Huffman table. + * This routine also performs some validation checks on the table. + */ + +GLOBAL(void) +jpeg_make_d_derived_tbl (j_decompress_ptr cinfo, boolean isDC, int tblno, + d_derived_tbl ** pdtbl) +{ + JHUFF_TBL *htbl; + d_derived_tbl *dtbl; + int p, i, l, si, numsymbols; + int lookbits, ctr; + char huffsize[257]; + unsigned int huffcode[257]; + unsigned int code; + + /* Note that huffsize[] and huffcode[] are filled in code-length order, + * paralleling the order of the symbols themselves in htbl->huffval[]. + */ + + /* Find the input Huffman table */ + if (tblno < 0 || tblno >= NUM_HUFF_TBLS) + ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tblno); + htbl = + isDC ? cinfo->dc_huff_tbl_ptrs[tblno] : cinfo->ac_huff_tbl_ptrs[tblno]; + if (htbl == NULL) + ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tblno); + + /* Allocate a workspace if we haven't already done so. */ + if (*pdtbl == NULL) + *pdtbl = (d_derived_tbl *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(d_derived_tbl)); + dtbl = *pdtbl; + dtbl->pub = htbl; /* fill in back link */ + + /* Figure C.1: make table of Huffman code length for each symbol */ + + p = 0; + for (l = 1; l <= 16; l++) { + i = (int) htbl->bits[l]; + if (i < 0 || p + i > 256) /* protect against table overrun */ + ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); + while (i--) + huffsize[p++] = (char) l; + } + huffsize[p] = 0; + numsymbols = p; + + /* Figure C.2: generate the codes themselves */ + /* We also validate that the counts represent a legal Huffman code tree. */ + + code = 0; + si = huffsize[0]; + p = 0; + while (huffsize[p]) { + while (((int) huffsize[p]) == si) { + huffcode[p++] = code; + code++; + } + /* code is now 1 more than the last code used for codelength si; but + * it must still fit in si bits, since no code is allowed to be all ones. + * BUG FIX: Comparison must be >, not >= + */ + if (((IJG_INT32) code) > (((IJG_INT32) 1) << si)) + ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); + code <<= 1; + si++; + } + + /* Figure F.15: generate decoding tables for bit-sequential decoding */ + + p = 0; + for (l = 1; l <= 16; l++) { + if (htbl->bits[l]) { + /* valoffset[l] = huffval[] index of 1st symbol of code length l, + * minus the minimum code of length l + */ + dtbl->valoffset[l] = (IJG_INT32) p - (IJG_INT32) huffcode[p]; + p += htbl->bits[l]; + dtbl->maxcode[l] = (IJG_INT32)huffcode[p-1]; /* maximum code of length l */ + } else { + dtbl->maxcode[l] = -1; /* -1 if no codes of this length */ + } + } + dtbl->maxcode[17] = 0xFFFFFL; /* ensures jpeg_huff_decode terminates */ + + /* Compute lookahead tables to speed up decoding. + * First we set all the table entries to 0, indicating "too long"; + * then we iterate through the Huffman codes that are short enough and + * fill in all the entries that correspond to bit sequences starting + * with that code. + */ + + MEMZERO(dtbl->look_nbits, SIZEOF(dtbl->look_nbits)); + + p = 0; + for (l = 1; l <= HUFF_LOOKAHEAD; l++) { + for (i = 1; i <= (int) htbl->bits[l]; i++, p++) { + /* l = current code's length, p = its index in huffcode[] & huffval[]. */ + /* Generate left-justified code followed by all possible bit sequences */ + lookbits = (int)huffcode[p] << (HUFF_LOOKAHEAD-l); + for (ctr = 1 << (HUFF_LOOKAHEAD-l); ctr > 0; ctr--) { + dtbl->look_nbits[lookbits] = l; + dtbl->look_sym[lookbits] = htbl->huffval[p]; + lookbits++; + } + } + } + + /* Validate symbols as being reasonable. + * For AC tables, we make no check, but accept all byte values 0..255. + * For DC tables, we require the symbols to be in range 0..16. + * (Tighter bounds could be applied depending on the data depth and mode, + * but this is sufficient to ensure safe decoding.) + */ + if (isDC) { + for (i = 0; i < numsymbols; i++) { + int sym = htbl->huffval[i]; + if (sym < 0 || sym > 16) + ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); + } + } +} + + +/* + * Out-of-line code for bit fetching. + * See jdhuff.h for info about usage. + * Note: current values of get_buffer and bits_left are passed as parameters, + * but are returned in the corresponding fields of the state struct. + * + * On most machines MIN_GET_BITS should be 25 to allow the full 32-bit width + * of get_buffer to be used. (On machines with wider words, an even larger + * buffer could be used.) However, on some machines 32-bit shifts are + * quite slow and take time proportional to the number of places shifted. + * (This is true with most PC compilers, for instance.) In this case it may + * be a win to set MIN_GET_BITS to the minimum value of 15. This reduces the + * average shift distance at the cost of more calls to jpeg_fill_bit_buffer. + */ + +#ifdef SLOW_SHIFT_32 +#define MIN_GET_BITS 15 /* minimum allowable value */ +#else +#define MIN_GET_BITS (BIT_BUF_SIZE-7) +#endif + + +GLOBAL(boolean) +jpeg_fill_bit_buffer (bitread_working_state * state, + register bit_buf_type get_buffer, register int bits_left, + int nbits) +/* Load up the bit buffer to a depth of at least nbits */ +{ + /* Copy heavily used state fields into locals (hopefully registers) */ + register const JOCTET * next_input_byte = state->next_input_byte; + register size_t bytes_in_buffer = state->bytes_in_buffer; + j_decompress_ptr cinfo = state->cinfo; + + /* Attempt to load at least MIN_GET_BITS bits into get_buffer. */ + /* (It is assumed that no request will be for more than that many bits.) */ + /* We fail to do so only if we hit a marker or are forced to suspend. */ + + if (cinfo->unread_marker == 0) { /* cannot advance past a marker */ + while (bits_left < MIN_GET_BITS) { + register int c; + + /* Attempt to read a byte */ + if (bytes_in_buffer == 0) { + if (! (*cinfo->src->fill_input_buffer) (cinfo)) + return FALSE; + next_input_byte = cinfo->src->next_input_byte; + bytes_in_buffer = cinfo->src->bytes_in_buffer; + } + bytes_in_buffer--; + c = GETJOCTET(*next_input_byte++); + + /* If it's 0xFF, check and discard stuffed zero byte */ + if (c == 0xFF) { + /* Loop here to discard any padding FF's on terminating marker, + * so that we can save a valid unread_marker value. NOTE: we will + * accept multiple FF's followed by a 0 as meaning a single FF data + * byte. This data pattern is not valid according to the standard. + */ + do { + if (bytes_in_buffer == 0) { + if (! (*cinfo->src->fill_input_buffer) (cinfo)) + return FALSE; + next_input_byte = cinfo->src->next_input_byte; + bytes_in_buffer = cinfo->src->bytes_in_buffer; + } + bytes_in_buffer--; + c = GETJOCTET(*next_input_byte++); + } while (c == 0xFF); + + if (c == 0) { + /* Found FF/00, which represents an FF data byte */ + c = 0xFF; + } else { + /* Oops, it's actually a marker indicating end of compressed data. + * Save the marker code for later use. + * Fine point: it might appear that we should save the marker into + * bitread working state, not straight into permanent state. But + * once we have hit a marker, we cannot need to suspend within the + * current MCU, because we will read no more bytes from the data + * source. So it is OK to update permanent state right away. + */ + cinfo->unread_marker = c; + /* See if we need to insert some fake zero bits. */ + goto no_more_bytes; + } + } + + /* OK, load c into get_buffer */ + get_buffer = (get_buffer << 8) | c; + bits_left += 8; + } /* end while */ + } else { + no_more_bytes: + /* We get here if we've read the marker that terminates the compressed + * data segment. There should be enough bits in the buffer register + * to satisfy the request; if so, no problem. + */ + if (nbits > bits_left) { + /* Uh-oh. Report corrupted data to user and stuff zeroes into + * the data stream, so that we can produce some kind of image. + * We use a nonvolatile flag to ensure that only one warning message + * appears per data segment. + */ + huffd_common_ptr huffd; + if (cinfo->process == JPROC_LOSSLESS) + huffd = (huffd_common_ptr) ((j_lossless_d_ptr) cinfo->codec)->entropy_private; + else + huffd = (huffd_common_ptr) ((j_lossy_d_ptr) cinfo->codec)->entropy_private; + if (! huffd->insufficient_data) { + WARNMS(cinfo, JWRN_HIT_MARKER); + huffd->insufficient_data = TRUE; + } + /* Fill the buffer with zero bits */ + get_buffer <<= MIN_GET_BITS - bits_left; + bits_left = MIN_GET_BITS; + } + } + + /* Unload the local registers */ + state->next_input_byte = next_input_byte; + state->bytes_in_buffer = bytes_in_buffer; + state->get_buffer = get_buffer; + state->bits_left = bits_left; + + return TRUE; +} + + +/* + * Out-of-line code for Huffman code decoding. + * See jdhuff.h for info about usage. + */ + +GLOBAL(int) +jpeg_huff_decode (bitread_working_state * state, + register bit_buf_type get_buffer, register int bits_left, + d_derived_tbl * htbl, int min_bits) +{ + register int l = min_bits; + register IJG_INT32 code; + + /* HUFF_DECODE has determined that the code is at least min_bits */ + /* bits long, so fetch that many bits in one swoop. */ + + CHECK_BIT_BUFFER(*state, l, return -1); + code = GET_BITS(l); + + /* Collect the rest of the Huffman code one bit at a time. */ + /* This is per Figure F.16 in the JPEG spec. */ + + while (code > htbl->maxcode[l]) { + code <<= 1; + CHECK_BIT_BUFFER(*state, 1, return -1); + code |= GET_BITS(1); + l++; + } + + /* Unload the local registers */ + state->get_buffer = get_buffer; + state->bits_left = bits_left; + + /* With garbage input we may reach the sentinel value l = 17. */ + + if (l > 16) { + WARNMS(state->cinfo, JWRN_HUFF_BAD_CODE); + return 0; /* fake a zero as the safest result */ + } + + return htbl->pub->huffval[ (int) (code + htbl->valoffset[l]) ]; +} diff --git a/dcmjpeg/libijg8/jdhuff8.h b/dcmjpeg/libijg8/jdhuff8.h new file mode 100644 index 00000000..e61f6816 --- /dev/null +++ b/dcmjpeg/libijg8/jdhuff8.h @@ -0,0 +1,229 @@ +/* + * jdhuff.h + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains declarations for Huffman entropy decoding routines + * that are shared between the sequential decoder (jdhuff.c), the + * progressive decoder (jdphuff.c) and the lossless decoder (jdlhuff.c). + * No other modules need to see these. + */ + +/* Short forms of external names for systems with brain-damaged linkers. */ + +#ifdef NEED_SHORT_EXTERNAL_NAMES +#define jpeg_make_d_derived_tbl jpeg8_make_d_derived_tbl +#define jpeg_fill_bit_buffer jpeg8_fill_bit_buffer +#define jpeg_huff_decode jpeg8_huff_decode +#endif /* NEED_SHORT_EXTERNAL_NAMES */ + + +/* Derived data constructed for each Huffman table */ + +#define HUFF_LOOKAHEAD 8 /* # of bits of lookahead */ + +typedef struct { + /* Basic tables: (element [0] of each array is unused) */ + IJG_INT32 maxcode[18]; /* largest code of length k (-1 if none) */ + /* (maxcode[17] is a sentinel to ensure jpeg_huff_decode terminates) */ + IJG_INT32 valoffset[17]; /* huffval[] offset for codes of length k */ + /* valoffset[k] = huffval[] index of 1st symbol of code length k, less + * the smallest code of length k; so given a code of length k, the + * corresponding symbol is huffval[code + valoffset[k]] + */ + + /* Link to public Huffman table (needed only in jpeg_huff_decode) */ + JHUFF_TBL *pub; + + /* Lookahead tables: indexed by the next HUFF_LOOKAHEAD bits of + * the input data stream. If the next Huffman code is no more + * than HUFF_LOOKAHEAD bits long, we can obtain its length and + * the corresponding symbol directly from these tables. + */ + int look_nbits[1< 32 bits on your machine, and shifting/masking longs is + * reasonably fast, making bit_buf_type be long and setting BIT_BUF_SIZE + * appropriately should be a win. Unfortunately we can't define the size + * with something like #define BIT_BUF_SIZE (sizeof(bit_buf_type)*8) + * because not all machines measure sizeof in 8-bit bytes. + */ + +typedef struct { /* Bitreading state saved across MCUs */ + bit_buf_type get_buffer; /* current bit-extraction buffer */ + int bits_left; /* # of unused bits in it */ +} bitread_perm_state; + +typedef struct { /* Bitreading working state within an MCU */ + /* Current data source location */ + /* We need a copy, rather than munging the original, in case of suspension */ + const JOCTET * next_input_byte; /* => next byte to read from source */ + size_t bytes_in_buffer; /* # of bytes remaining in source buffer */ + /* Bit input buffer --- note these values are kept in register variables, + * not in this struct, inside the inner loops. + */ + bit_buf_type get_buffer; /* current bit-extraction buffer */ + int bits_left; /* # of unused bits in it */ + /* Pointer needed by jpeg_fill_bit_buffer. */ + j_decompress_ptr cinfo; /* back link to decompress master record */ +} bitread_working_state; + +/* Macros to declare and load/save bitread local variables. */ +#define BITREAD_STATE_VARS \ + register bit_buf_type get_buffer; \ + register int bits_left; \ + bitread_working_state br_state + +#define BITREAD_LOAD_STATE(cinfop,permstate) \ + br_state.cinfo = cinfop; \ + br_state.next_input_byte = cinfop->src->next_input_byte; \ + br_state.bytes_in_buffer = cinfop->src->bytes_in_buffer; \ + get_buffer = permstate.get_buffer; \ + bits_left = permstate.bits_left; + +#define BITREAD_SAVE_STATE(cinfop,permstate) \ + cinfop->src->next_input_byte = br_state.next_input_byte; \ + cinfop->src->bytes_in_buffer = br_state.bytes_in_buffer; \ + permstate.get_buffer = get_buffer; \ + permstate.bits_left = bits_left + +/* + * These macros provide the in-line portion of bit fetching. + * Use CHECK_BIT_BUFFER to ensure there are N bits in get_buffer + * before using GET_BITS, PEEK_BITS, or DROP_BITS. + * The variables get_buffer and bits_left are assumed to be locals, + * but the state struct might not be (jpeg_huff_decode needs this). + * CHECK_BIT_BUFFER(state,n,action); + * Ensure there are N bits in get_buffer; if suspend, take action. + * val = GET_BITS(n); + * Fetch next N bits. + * val = PEEK_BITS(n); + * Fetch next N bits without removing them from the buffer. + * DROP_BITS(n); + * Discard next N bits. + * The value N should be a simple variable, not an expression, because it + * is evaluated multiple times. + */ + +#define CHECK_BIT_BUFFER(state,nbits,action) \ + { if (bits_left < (nbits)) { \ + if (! jpeg_fill_bit_buffer(&(state),get_buffer,bits_left,nbits)) \ + { action; } \ + get_buffer = (state).get_buffer; bits_left = (state).bits_left; } } + +#define GET_BITS(nbits) \ + (((int) (get_buffer >> (bits_left -= (nbits)))) & ((1<<(nbits))-1)) + +#define PEEK_BITS(nbits) \ + (((int) (get_buffer >> (bits_left - (nbits)))) & ((1<<(nbits))-1)) + +#define DROP_BITS(nbits) \ + (bits_left -= (nbits)) + +/* Load up the bit buffer to a depth of at least nbits */ +EXTERN(boolean) jpeg_fill_bit_buffer + JPP((bitread_working_state * state, register bit_buf_type get_buffer, + register int bits_left, int nbits)); + + +/* + * Code for extracting next Huffman-coded symbol from input bit stream. + * Again, this is time-critical and we make the main paths be macros. + * + * We use a lookahead table to process codes of up to HUFF_LOOKAHEAD bits + * without looping. Usually, more than 95% of the Huffman codes will be 8 + * or fewer bits long. The few overlength codes are handled with a loop, + * which need not be inline code. + * + * Notes about the HUFF_DECODE macro: + * 1. Near the end of the data segment, we may fail to get enough bits + * for a lookahead. In that case, we do it the hard way. + * 2. If the lookahead table contains no entry, the next code must be + * more than HUFF_LOOKAHEAD bits long. + * 3. jpeg_huff_decode returns -1 if forced to suspend. + */ + +#define HUFF_DECODE(result,state,htbl,failaction,slowlabel) \ +{ register int nb, look; \ + if (bits_left < HUFF_LOOKAHEAD) { \ + if (! jpeg_fill_bit_buffer(&state,get_buffer,bits_left, 0)) {failaction;} \ + get_buffer = state.get_buffer; bits_left = state.bits_left; \ + if (bits_left < HUFF_LOOKAHEAD) { \ + nb = 1; goto slowlabel; \ + } \ + } \ + look = PEEK_BITS(HUFF_LOOKAHEAD); \ + if ((nb = htbl->look_nbits[look]) != 0) { \ + DROP_BITS(nb); \ + result = htbl->look_sym[look]; \ + } else { \ + nb = HUFF_LOOKAHEAD+1; \ +slowlabel: \ + if ((result=jpeg_huff_decode(&state,get_buffer,bits_left,htbl,nb)) < 0) \ + { failaction; } \ + get_buffer = state.get_buffer; bits_left = state.bits_left; \ + } \ +} + +/* Out-of-line case for Huffman code fetching */ +EXTERN(int) jpeg_huff_decode + JPP((bitread_working_state * state, register bit_buf_type get_buffer, + register int bits_left, d_derived_tbl * htbl, int min_bits)); + + +/* Common fields between sequential, progressive and lossless Huffman entropy + * decoder master structs. + */ + +#define huffd_common_fields \ + boolean insufficient_data; /* set TRUE after emmitting warning */ \ + /* These fields are loaded into local variables at start of each MCU. \ + * In case of suspension, we exit WITHOUT updating them. \ + */ \ + bitread_perm_state bitstate /* Bit buffer at start of MCU */ + +/* Routines that are to be used by any or all of the entropy decoders are + * declared to receive a pointer to this structure. There are no actual + * instances of huffd_common_struct, only of shuff_entropy_decoder, + * phuff_entropy_decoder and lhuff_entropy_decoder. + */ +struct huffd_common_struct { + huffd_common_fields; /* Fields common to all decoder struct types */ + /* Additional fields follow in an actual shuff_entropy_decoder, + * phuff_entropy_decoder or lhuff_entropy_decoder struct. All four structs + * must agree on these initial fields! (This would be a lot cleaner in C++.) + */ +}; + +typedef struct huffd_common_struct * huffd_common_ptr; diff --git a/dcmjpeg/libijg8/jdinput.c b/dcmjpeg/libijg8/jdinput.c new file mode 100644 index 00000000..1fc88c8f --- /dev/null +++ b/dcmjpeg/libijg8/jdinput.c @@ -0,0 +1,347 @@ +/* + * jdinput.c + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains input control logic for the JPEG decompressor. + * These routines are concerned with controlling the decompressor's input + * processing (marker reading and coefficient/difference decoding). + * The actual input reading is done in jdmarker.c, jdhuff.c, jdphuff.c, + * and jdlhuff.c. + */ + +#define JPEG_INTERNALS +#include "jinclude8.h" +#include "jpeglib8.h" + + +/* Private state */ + +typedef struct { + struct jpeg_input_controller pub; /* public fields */ + + boolean inheaders; /* TRUE until first SOS is reached */ +} my_input_controller; + +typedef my_input_controller * my_inputctl_ptr; + + +/* Forward declarations */ +METHODDEF(int) consume_markers JPP((j_decompress_ptr cinfo)); + + +/* + * Routines to calculate various quantities related to the size of the image. + */ + +LOCAL(void) +initial_setup (j_decompress_ptr cinfo) +/* Called once, when first SOS marker is reached */ +{ + int ci; + jpeg_component_info *compptr; + + /* Make sure image isn't bigger than I can handle */ + if ((long) cinfo->image_height > (long) JPEG_MAX_DIMENSION || + (long) cinfo->image_width > (long) JPEG_MAX_DIMENSION) + ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, (unsigned int) JPEG_MAX_DIMENSION); + + if (cinfo->process == JPROC_LOSSLESS) { + /* If precision > compiled-in value, we must downscale */ + if (cinfo->data_precision > BITS_IN_JSAMPLE) + WARNMS2(cinfo, JWRN_MUST_DOWNSCALE, + cinfo->data_precision, BITS_IN_JSAMPLE); + } + else { /* Lossy processes */ + /* For now, precision must match compiled-in value... */ + if (cinfo->data_precision != BITS_IN_JSAMPLE) + ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); + } + + /* Check that number of components won't exceed internal array sizes */ + if (cinfo->num_components > MAX_COMPONENTS) + ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components, + MAX_COMPONENTS); + + /* Compute maximum sampling factors; check factor validity */ + cinfo->max_h_samp_factor = 1; + cinfo->max_v_samp_factor = 1; + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + if (compptr->h_samp_factor<=0 || compptr->h_samp_factor>MAX_SAMP_FACTOR || + compptr->v_samp_factor<=0 || compptr->v_samp_factor>MAX_SAMP_FACTOR) + ERREXIT(cinfo, JERR_BAD_SAMPLING); + cinfo->max_h_samp_factor = MAX(cinfo->max_h_samp_factor, + compptr->h_samp_factor); + cinfo->max_v_samp_factor = MAX(cinfo->max_v_samp_factor, + compptr->v_samp_factor); + } + + /* We initialize codec_data_unit and min_codec_data_unit to data_unit. + * In the full decompressor, this will be overridden by jdmaster.c; + * but in the transcoder, jdmaster.c is not used, so we must do it here. + */ + cinfo->min_codec_data_unit = cinfo->data_unit; + + /* Compute dimensions of components */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + compptr->codec_data_unit = cinfo->data_unit; + /* Size in data units */ + compptr->width_in_data_units = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor, + (long) (cinfo->max_h_samp_factor * cinfo->data_unit)); + compptr->height_in_data_units = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor, + (long) (cinfo->max_v_samp_factor * cinfo->data_unit)); + /* downsampled_width and downsampled_height will also be overridden by + * jdmaster.c if we are doing full decompression. The transcoder library + * doesn't use these values, but the calling application might. + */ + /* Size in samples */ + compptr->downsampled_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor, + (long) cinfo->max_h_samp_factor); + compptr->downsampled_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor, + (long) cinfo->max_v_samp_factor); + /* Mark component needed, until color conversion says otherwise */ + compptr->component_needed = TRUE; + /* Mark no quantization table yet saved for component */ + compptr->quant_table = NULL; + } + + /* Compute number of fully interleaved MCU rows. */ + cinfo->total_iMCU_rows = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height, + (long) (cinfo->max_v_samp_factor*cinfo->data_unit)); + + /* Decide whether file contains multiple scans */ + if (cinfo->comps_in_scan < cinfo->num_components || + cinfo->process == JPROC_PROGRESSIVE) + cinfo->inputctl->has_multiple_scans = TRUE; + else + cinfo->inputctl->has_multiple_scans = FALSE; +} + + +LOCAL(void) +per_scan_setup (j_decompress_ptr cinfo) +/* Do computations that are needed before processing a JPEG scan */ +/* cinfo->comps_in_scan and cinfo->cur_comp_info[] were set from SOS marker */ +{ + int ci, mcublks, tmp; + jpeg_component_info *compptr; + + if (cinfo->comps_in_scan == 1) { + + /* Noninterleaved (single-component) scan */ + compptr = cinfo->cur_comp_info[0]; + + /* Overall image size in MCUs */ + cinfo->MCUs_per_row = compptr->width_in_data_units; + cinfo->MCU_rows_in_scan = compptr->height_in_data_units; + + /* For noninterleaved scan, always one data unit per MCU */ + compptr->MCU_width = 1; + compptr->MCU_height = 1; + compptr->MCU_data_units = 1; + compptr->MCU_sample_width = compptr->codec_data_unit; + compptr->last_col_width = 1; + /* For noninterleaved scans, it is convenient to define last_row_height + * as the number of data unit rows present in the last iMCU row. + */ + tmp = (int)compptr->height_in_data_units % compptr->v_samp_factor; + if (tmp == 0) tmp = compptr->v_samp_factor; + compptr->last_row_height = tmp; + + /* Prepare array describing MCU composition */ + cinfo->data_units_in_MCU = 1; + cinfo->MCU_membership[0] = 0; + + } else { + + /* Interleaved (multi-component) scan */ + if (cinfo->comps_in_scan <= 0 || cinfo->comps_in_scan > MAX_COMPS_IN_SCAN) + ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->comps_in_scan, + MAX_COMPS_IN_SCAN); + + /* Overall image size in MCUs */ + cinfo->MCUs_per_row = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width, + (long) (cinfo->max_h_samp_factor*cinfo->data_unit)); + cinfo->MCU_rows_in_scan = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height, + (long) (cinfo->max_v_samp_factor*cinfo->data_unit)); + + cinfo->data_units_in_MCU = 0; + + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + /* Sampling factors give # of data units of component in each MCU */ + compptr->MCU_width = compptr->h_samp_factor; + compptr->MCU_height = compptr->v_samp_factor; + compptr->MCU_data_units = compptr->MCU_width * compptr->MCU_height; + compptr->MCU_sample_width = compptr->MCU_width * compptr->codec_data_unit; + /* Figure number of non-dummy data units in last MCU column & row */ + tmp = (int)compptr->width_in_data_units % compptr->MCU_width; + if (tmp == 0) tmp = compptr->MCU_width; + compptr->last_col_width = tmp; + tmp = (int)compptr->height_in_data_units % compptr->MCU_height; + if (tmp == 0) tmp = compptr->MCU_height; + compptr->last_row_height = tmp; + /* Prepare array describing MCU composition */ + mcublks = compptr->MCU_data_units; + if (cinfo->data_units_in_MCU + mcublks > D_MAX_DATA_UNITS_IN_MCU) + ERREXIT(cinfo, JERR_BAD_MCU_SIZE); + while (mcublks-- > 0) { + cinfo->MCU_membership[cinfo->data_units_in_MCU++] = ci; + } + } + + } +} + + +/* + * Initialize the input modules to read a scan of compressed data. + * The first call to this is done by jdmaster.c after initializing + * the entire decompressor (during jpeg_start_decompress). + * Subsequent calls come from consume_markers, below. + */ + +METHODDEF(void) +start_input_pass (j_decompress_ptr cinfo) +{ + per_scan_setup(cinfo); + (*cinfo->codec->start_input_pass) (cinfo); + cinfo->inputctl->consume_input = cinfo->codec->consume_data; +} + + +/* + * Finish up after inputting a compressed-data scan. + * This is called by the coefficient controller after it's read all + * the expected data of the scan. + */ + +METHODDEF(void) +finish_input_pass (j_decompress_ptr cinfo) +{ + cinfo->inputctl->consume_input = consume_markers; +} + + +/* + * Read JPEG markers before, between, or after compressed-data scans. + * Change state as necessary when a new scan is reached. + * Return value is JPEG_SUSPENDED, JPEG_REACHED_SOS, or JPEG_REACHED_EOI. + * + * The consume_input method pointer points either here or to the + * coefficient controller's consume_data routine, depending on whether + * we are reading a compressed data segment or inter-segment markers. + */ + +METHODDEF(int) +consume_markers (j_decompress_ptr cinfo) +{ + my_inputctl_ptr inputctl = (my_inputctl_ptr) cinfo->inputctl; + int val; + + if (inputctl->pub.eoi_reached) /* After hitting EOI, read no further */ + return JPEG_REACHED_EOI; + + val = (*cinfo->marker->read_markers) (cinfo); + + switch (val) { + case JPEG_REACHED_SOS: /* Found SOS */ + if (inputctl->inheaders) { /* 1st SOS */ + initial_setup(cinfo); + /* + * Initialize the decompression codec. We need to do this here so that + * any codec-specific fields and function pointers are available to + * the rest of the library. + */ + jinit_d_codec(cinfo); + inputctl->inheaders = FALSE; + /* Note: start_input_pass must be called by jdmaster.c + * before any more input can be consumed. jdapimin.c is + * responsible for enforcing this sequencing. + */ + } else { /* 2nd or later SOS marker */ + if (! inputctl->pub.has_multiple_scans) + ERREXIT(cinfo, JERR_EOI_EXPECTED); /* Oops, I wasn't expecting this! */ + start_input_pass(cinfo); + } + break; + case JPEG_REACHED_EOI: /* Found EOI */ + inputctl->pub.eoi_reached = TRUE; + if (inputctl->inheaders) { /* Tables-only datastream, apparently */ + if (cinfo->marker->saw_SOF) + ERREXIT(cinfo, JERR_SOF_NO_SOS); + } else { + /* Prevent infinite loop in coef ctlr's decompress_data routine + * if user set output_scan_number larger than number of scans. + */ + if (cinfo->output_scan_number > cinfo->input_scan_number) + cinfo->output_scan_number = cinfo->input_scan_number; + } + break; + case JPEG_SUSPENDED: + break; + } + + return val; +} + + +/* + * Reset state to begin a fresh datastream. + */ + +METHODDEF(void) +reset_input_controller (j_decompress_ptr cinfo) +{ + my_inputctl_ptr inputctl = (my_inputctl_ptr) cinfo->inputctl; + + inputctl->pub.consume_input = consume_markers; + inputctl->pub.has_multiple_scans = FALSE; /* "unknown" would be better */ + inputctl->pub.eoi_reached = FALSE; + inputctl->inheaders = TRUE; + /* Reset other modules */ + (*cinfo->err->reset_error_mgr) ((j_common_ptr) cinfo); + (*cinfo->marker->reset_marker_reader) (cinfo); + /* Reset progression state -- would be cleaner if entropy decoder did this */ + cinfo->coef_bits = NULL; +} + + +/* + * Initialize the input controller module. + * This is called only once, when the decompression object is created. + */ + +GLOBAL(void) +jinit_input_controller (j_decompress_ptr cinfo) +{ + my_inputctl_ptr inputctl; + + /* Create subobject in permanent pool */ + inputctl = (my_inputctl_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, + SIZEOF(my_input_controller)); + cinfo->inputctl = (struct jpeg_input_controller *) inputctl; + /* Initialize method pointers */ + inputctl->pub.consume_input = consume_markers; + inputctl->pub.reset_input_controller = reset_input_controller; + inputctl->pub.start_input_pass = start_input_pass; + inputctl->pub.finish_input_pass = finish_input_pass; + /* Initialize state: can't use reset_input_controller since we don't + * want to try to reset other modules yet. + */ + inputctl->pub.has_multiple_scans = FALSE; /* "unknown" would be better */ + inputctl->pub.eoi_reached = FALSE; + inputctl->inheaders = TRUE; +} diff --git a/dcmjpeg/libijg8/jdlhuff.c b/dcmjpeg/libijg8/jdlhuff.c new file mode 100644 index 00000000..21bd09aa --- /dev/null +++ b/dcmjpeg/libijg8/jdlhuff.c @@ -0,0 +1,291 @@ +/* + * jdlhuff.c + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains Huffman entropy decoding routines for lossless JPEG. + * + * Much of the complexity here has to do with supporting input suspension. + * If the data source module demands suspension, we want to be able to back + * up to the start of the current MCU. To do this, we copy state variables + * into local working storage, and update them back to the permanent + * storage only upon successful completion of an MCU. + */ + +#define JPEG_INTERNALS +#include "jinclude8.h" +#include "jpeglib8.h" +#include "jlossls8.h" /* Private declarations for lossless codec */ +#include "jdhuff8.h" /* Declarations shared with jd*huff.c */ + + +#ifdef D_LOSSLESS_SUPPORTED + +typedef struct { + int ci, yoffset, MCU_width; +} lhd_output_ptr_info; + +/* + * Private entropy decoder object for lossless Huffman decoding. + */ + +typedef struct { + huffd_common_fields; /* Fields shared with other entropy decoders */ + + /* Pointers to derived tables (these workspaces have image lifespan) */ + d_derived_tbl * derived_tbls[NUM_HUFF_TBLS]; + + /* Precalculated info set up by start_pass for use in decode_mcus: */ + + /* Pointers to derived tables to be used for each data unit within an MCU */ + d_derived_tbl * cur_tbls[D_MAX_DATA_UNITS_IN_MCU]; + + /* Pointers to the proper output difference row for each group of data units + * within an MCU. For each component, there are Vi groups of Hi data units. + */ + JDIFFROW output_ptr[D_MAX_DATA_UNITS_IN_MCU]; + + /* Number of output pointers in use for the current MCU. This is the sum + * of all Vi in the MCU. + */ + int num_output_ptrs; + + /* Information used for positioning the output pointers within the output + * difference rows. + */ + lhd_output_ptr_info output_ptr_info[D_MAX_DATA_UNITS_IN_MCU]; + + /* Index of the proper output pointer for each data unit within an MCU */ + int output_ptr_index[D_MAX_DATA_UNITS_IN_MCU]; + +} lhuff_entropy_decoder; + +typedef lhuff_entropy_decoder * lhuff_entropy_ptr; + + +/* + * Initialize for a Huffman-compressed scan. + */ + +METHODDEF(void) +start_pass_lhuff_decoder (j_decompress_ptr cinfo) +{ + j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec; + lhuff_entropy_ptr entropy = (lhuff_entropy_ptr) losslsd->entropy_private; + int ci, dctbl, sampn, ptrn, yoffset, xoffset; + jpeg_component_info * compptr; + + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + dctbl = compptr->dc_tbl_no; + /* Make sure requested tables are present */ + if (dctbl < 0 || dctbl >= NUM_HUFF_TBLS || + cinfo->dc_huff_tbl_ptrs[dctbl] == NULL) + ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, dctbl); + /* Compute derived values for Huffman tables */ + /* We may do this more than once for a table, but it's not expensive */ + jpeg_make_d_derived_tbl(cinfo, TRUE, dctbl, + & entropy->derived_tbls[dctbl]); + } + + /* Precalculate decoding info for each sample in an MCU of this scan */ + for (sampn = 0, ptrn = 0; sampn < cinfo->data_units_in_MCU;) { + compptr = cinfo->cur_comp_info[cinfo->MCU_membership[sampn]]; + ci = compptr->component_index; + for (yoffset = 0; yoffset < compptr->MCU_height; yoffset++, ptrn++) { + /* Precalculate the setup info for each output pointer */ + entropy->output_ptr_info[ptrn].ci = ci; + entropy->output_ptr_info[ptrn].yoffset = yoffset; + entropy->output_ptr_info[ptrn].MCU_width = compptr->MCU_width; + for (xoffset = 0; xoffset < compptr->MCU_width; xoffset++, sampn++) { + /* Precalculate the output pointer index for each sample */ + entropy->output_ptr_index[sampn] = ptrn; + /* Precalculate which table to use for each sample */ + entropy->cur_tbls[sampn] = entropy->derived_tbls[compptr->dc_tbl_no]; + } + } + } + entropy->num_output_ptrs = ptrn; + + /* Initialize bitread state variables */ + entropy->bitstate.bits_left = 0; + entropy->bitstate.get_buffer = 0; /* unnecessary, but keeps Purify quiet */ + entropy->insufficient_data = FALSE; +} + + +/* + * Figure F.12: extend sign bit. + * On some machines, a shift and add will be faster than a table lookup. + */ + +#ifdef AVOID_TABLES + +#define HUFF_EXTEND(x,s) ((x) < (1<<((s)-1)) ? (x) + (((-1)<<(s)) + 1) : (x)) + +#else + +#define HUFF_EXTEND(x,s) ((x) < extend_test[s] ? (x) + extend_offset[s] : (x)) + +static const int extend_test[16] = /* entry n is 2**(n-1) */ + { 0, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080, + 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000 }; + +static const int extend_offset[16] = /* entry n is (-1 << n) + 1 */ + { 0, ((-1)<<1) + 1, ((-1)<<2) + 1, ((-1)<<3) + 1, ((-1)<<4) + 1, + ((-1)<<5) + 1, ((-1)<<6) + 1, ((-1)<<7) + 1, ((-1)<<8) + 1, + ((-1)<<9) + 1, ((-1)<<10) + 1, ((-1)<<11) + 1, ((-1)<<12) + 1, + ((-1)<<13) + 1, ((-1)<<14) + 1, ((-1)<<15) + 1 }; + +#endif /* AVOID_TABLES */ + + +/* + * Check for a restart marker & resynchronize decoder. + * Returns FALSE if must suspend. + */ + +METHODDEF(boolean) +process_restart (j_decompress_ptr cinfo) +{ + j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec; + lhuff_entropy_ptr entropy = (lhuff_entropy_ptr) losslsd->entropy_private; + /* int ci; */ + + /* Throw away any unused bits remaining in bit buffer; */ + /* include any full bytes in next_marker's count of discarded bytes */ + cinfo->marker->discarded_bytes += (unsigned int)entropy->bitstate.bits_left / 8; + entropy->bitstate.bits_left = 0; + + /* Advance past the RSTn marker */ + if (! (*cinfo->marker->read_restart_marker) (cinfo)) + return FALSE; + + /* Reset out-of-data flag, unless read_restart_marker left us smack up + * against a marker. In that case we will end up treating the next data + * segment as empty, and we can avoid producing bogus output pixels by + * leaving the flag set. + */ + if (cinfo->unread_marker == 0) + entropy->insufficient_data = FALSE; + + return TRUE; +} + + +/* + * Decode and return nMCU's worth of Huffman-compressed differences. + * Each MCU is also disassembled and placed accordingly in diff_buf. + * + * MCU_col_num specifies the column of the first MCU being requested within + * the MCU-row. This tells us where to position the output row pointers in + * diff_buf. + * + * Returns the number of MCUs decoded. This may be less than nMCU if data + * source requested suspension. In that case no changes have been made to + * permanent state. (Exception: some output differences may already have + * been assigned. This is harmless for this module, since we'll just + * re-assign them on the next call.) + */ + +METHODDEF(JDIMENSION) +decode_mcus (j_decompress_ptr cinfo, JDIFFIMAGE diff_buf, + JDIMENSION MCU_row_num, JDIMENSION MCU_col_num, JDIMENSION nMCU) +{ + j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec; + lhuff_entropy_ptr entropy = (lhuff_entropy_ptr) losslsd->entropy_private; + unsigned int mcu_num; + int sampn, ci, yoffset, MCU_width, ptrn; + BITREAD_STATE_VARS; + + /* Set output pointer locations based on MCU_col_num */ + for (ptrn = 0; ptrn < entropy->num_output_ptrs; ptrn++) { + ci = entropy->output_ptr_info[ptrn].ci; + yoffset = entropy->output_ptr_info[ptrn].yoffset; + MCU_width = entropy->output_ptr_info[ptrn].MCU_width; + entropy->output_ptr[ptrn] = + diff_buf[ci][MCU_row_num + (JDIMENSION)yoffset] + MCU_col_num * (JDIMENSION)MCU_width; + } + + /* + * If we've run out of data, zero out the buffers and return. + * By resetting the undifferencer, the output samples will be CENTERJSAMPLE. + * + * NB: We should find a way to do this without interacting with the + * undifferencer module directly. + */ + if (entropy->insufficient_data) { + for (ptrn = 0; ptrn < entropy->num_output_ptrs; ptrn++) + jzero_far((void FAR *) entropy->output_ptr[ptrn], + nMCU * (size_t)entropy->output_ptr_info[ptrn].MCU_width * SIZEOF(JDIFF)); + + (*losslsd->predict_process_restart) (cinfo); + } + + else { + + /* Load up working state */ + BITREAD_LOAD_STATE(cinfo,entropy->bitstate); + + /* Outer loop handles the number of MCU requested */ + + for (mcu_num = 0; mcu_num < nMCU; mcu_num++) { + + /* Inner loop handles the samples in the MCU */ + for (sampn = 0; sampn < cinfo->data_units_in_MCU; sampn++) { + d_derived_tbl * dctbl = entropy->cur_tbls[sampn]; + register int s, r; + + /* Section H.2.2: decode the sample difference */ + HUFF_DECODE(s, br_state, dctbl, return mcu_num, label1); + if (s) { + if (s == 16) /* special case: always output 32768 */ + s = 32768; + else { /* normal case: fetch subsequent bits */ + CHECK_BIT_BUFFER(br_state, s, return mcu_num); + r = GET_BITS(s); + s = HUFF_EXTEND(r, s); + } + } + + /* Output the sample difference */ + *entropy->output_ptr[entropy->output_ptr_index[sampn]]++ = (JDIFF) s; + } + + /* Completed MCU, so update state */ + BITREAD_SAVE_STATE(cinfo,entropy->bitstate); + } + } + + return nMCU; +} + + +/* + * Module initialization routine for lossless Huffman entropy decoding. + */ + +GLOBAL(void) +jinit_lhuff_decoder (j_decompress_ptr cinfo) +{ + j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec; + lhuff_entropy_ptr entropy; + int i; + + entropy = (lhuff_entropy_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(lhuff_entropy_decoder)); + losslsd->entropy_private = (void *) entropy; + losslsd->entropy_start_pass = start_pass_lhuff_decoder; + losslsd->entropy_process_restart = process_restart; + losslsd->entropy_decode_mcus = decode_mcus; + + /* Mark tables unallocated */ + for (i = 0; i < NUM_HUFF_TBLS; i++) { + entropy->derived_tbls[i] = NULL; + } +} + +#endif /* D_LOSSLESS_SUPPORTED */ diff --git a/dcmjpeg/libijg8/jdlossls.c b/dcmjpeg/libijg8/jdlossls.c new file mode 100644 index 00000000..ff329172 --- /dev/null +++ b/dcmjpeg/libijg8/jdlossls.c @@ -0,0 +1,98 @@ +/* + * jdlossls.c + * + * Copyright (C) 1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains the control logic for the lossless JPEG decompressor. + */ + +#define JPEG_INTERNALS +#include "jinclude8.h" +#include "jpeglib8.h" +#include "jlossls8.h" + + +#ifdef D_LOSSLESS_SUPPORTED + +/* + * Compute output image dimensions and related values. + */ + +METHODDEF(void) +calc_output_dimensions (j_decompress_ptr cinfo) +{ + /* Hardwire it to "no scaling" */ + cinfo->output_width = cinfo->image_width; + cinfo->output_height = cinfo->image_height; + /* jdinput.c has already initialized codec_data_unit to 1, + * and has computed unscaled downsampled_width and downsampled_height. + */ +} + + +/* + * Initialize for an input processing pass. + */ + +METHODDEF(void) +start_input_pass (j_decompress_ptr cinfo) +{ + j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec; + + (*losslsd->entropy_start_pass) (cinfo); + (*losslsd->predict_start_pass) (cinfo); + (*losslsd->scaler_start_pass) (cinfo); + (*losslsd->diff_start_input_pass) (cinfo); +} + + +/* + * Initialize the lossless decompression codec. + * This is called only once, during master selection. + */ + +GLOBAL(void) +jinit_lossless_d_codec(j_decompress_ptr cinfo) +{ + j_lossless_d_ptr losslsd; + boolean use_c_buffer; + + /* Create subobject in permanent pool */ + losslsd = (j_lossless_d_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, + SIZEOF(jpeg_lossless_d_codec)); + cinfo->codec = (struct jpeg_d_codec *) losslsd; + + /* Initialize sub-modules */ + /* Entropy decoding: either Huffman or arithmetic coding. */ + if (cinfo->arith_code) { +#ifdef WITH_ARITHMETIC_PATCH + jinit_arith_decoder(cinfo); +#else + ERREXIT(cinfo, JERR_ARITH_NOTIMPL); +#endif + } else { + jinit_lhuff_decoder(cinfo); + } + + /* Undifferencer */ + jinit_undifferencer(cinfo); + + /* Scaler */ + jinit_d_scaler(cinfo); + + use_c_buffer = cinfo->inputctl->has_multiple_scans || cinfo->buffered_image; + jinit_d_diff_controller(cinfo, use_c_buffer); + + /* Initialize method pointers. + * + * Note: consume_data, start_output_pass and decompress_data are + * assigned in jddiffct.c. + */ + losslsd->pub.calc_output_dimensions = calc_output_dimensions; + losslsd->pub.start_input_pass = start_input_pass; +} + +#endif /* D_LOSSLESS_SUPPORTED */ diff --git a/dcmjpeg/libijg8/jdlossy.c b/dcmjpeg/libijg8/jdlossy.c new file mode 100644 index 00000000..39009085 --- /dev/null +++ b/dcmjpeg/libijg8/jdlossy.c @@ -0,0 +1,232 @@ +/* + * jdlossy.c + * + * Copyright (C) 1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains the control logic for the lossy JPEG decompressor. + */ + +#define JPEG_INTERNALS +#include "jinclude8.h" +#include "jpeglib8.h" +#include "jlossy8.h" + + +/* + * Compute output image dimensions and related values. + */ + +METHODDEF(void) +calc_output_dimensions (j_decompress_ptr cinfo) +{ +#ifdef IDCT_SCALING_SUPPORTED + int ci; + jpeg_component_info *compptr; + + /* Compute actual output image dimensions and DCT scaling choices. */ + if (cinfo->scale_num * 8 <= cinfo->scale_denom) { + /* Provide 1/8 scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width, 8L); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height, 8L); + cinfo->min_codec_data_unit = 1; + } else if (cinfo->scale_num * 4 <= cinfo->scale_denom) { + /* Provide 1/4 scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width, 4L); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height, 4L); + cinfo->min_codec_data_unit = 2; + } else if (cinfo->scale_num * 2 <= cinfo->scale_denom) { + /* Provide 1/2 scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width, 2L); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height, 2L); + cinfo->min_codec_data_unit = 4; + } else { + /* Provide 1/1 scaling */ + cinfo->output_width = cinfo->image_width; + cinfo->output_height = cinfo->image_height; + cinfo->min_codec_data_unit = DCTSIZE; + } + /* In selecting the actual DCT scaling for each component, we try to + * scale up the chroma components via IDCT scaling rather than upsampling. + * This saves time if the upsampler gets to use 1:1 scaling. + * Note this code assumes that the supported DCT scalings are powers of 2. + */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + int ssize = cinfo->min_codec_data_unit; + while (ssize < DCTSIZE && + (compptr->h_samp_factor * ssize * 2 <= + cinfo->max_h_samp_factor * cinfo->min_codec_data_unit) && + (compptr->v_samp_factor * ssize * 2 <= + cinfo->max_v_samp_factor * cinfo->min_codec_data_unit)) { + ssize = ssize * 2; + } + compptr->codec_data_unit = ssize; + } + + /* Recompute downsampled dimensions of components; + * application needs to know these if using raw downsampled data. + */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + /* Size in samples, after IDCT scaling */ + compptr->downsampled_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * + (long) (compptr->h_samp_factor * compptr->codec_data_unit), + (long) (cinfo->max_h_samp_factor * DCTSIZE)); + compptr->downsampled_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * + (long) (compptr->v_samp_factor * compptr->codec_data_unit), + (long) (cinfo->max_v_samp_factor * DCTSIZE)); + } + +#else /* !IDCT_SCALING_SUPPORTED */ + + /* Hardwire it to "no scaling" */ + cinfo->output_width = cinfo->image_width; + cinfo->output_height = cinfo->image_height; + /* jdinput.c has already initialized codec_data_unit to DCTSIZE, + * and has computed unscaled downsampled_width and downsampled_height. + */ + +#endif /* IDCT_SCALING_SUPPORTED */ +} + + +/* + * Save away a copy of the Q-table referenced by each component present + * in the current scan, unless already saved during a prior scan. + * + * In a multiple-scan JPEG file, the encoder could assign different components + * the same Q-table slot number, but change table definitions between scans + * so that each component uses a different Q-table. (The IJG encoder is not + * currently capable of doing this, but other encoders might.) Since we want + * to be able to dequantize all the components at the end of the file, this + * means that we have to save away the table actually used for each component. + * We do this by copying the table at the start of the first scan containing + * the component. + * The JPEG spec prohibits the encoder from changing the contents of a Q-table + * slot between scans of a component using that slot. If the encoder does so + * anyway, this decoder will simply use the Q-table values that were current + * at the start of the first scan for the component. + * + * The decompressor output side looks only at the saved quant tables, + * not at the current Q-table slots. + */ + +LOCAL(void) +latch_quant_tables (j_decompress_ptr cinfo) +{ + int ci, qtblno; + jpeg_component_info *compptr; + JQUANT_TBL * qtbl; + + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + /* No work if we already saved Q-table for this component */ + if (compptr->quant_table != NULL) + continue; + /* Make sure specified quantization table is present */ + qtblno = compptr->quant_tbl_no; + if (qtblno < 0 || qtblno >= NUM_QUANT_TBLS || + cinfo->quant_tbl_ptrs[qtblno] == NULL) + ERREXIT1(cinfo, JERR_NO_QUANT_TABLE, qtblno); + /* OK, save away the quantization table */ + qtbl = (JQUANT_TBL *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(JQUANT_TBL)); + MEMCOPY(qtbl, cinfo->quant_tbl_ptrs[qtblno], SIZEOF(JQUANT_TBL)); + compptr->quant_table = qtbl; + } +} + + +/* + * Initialize for an input processing pass. + */ + +METHODDEF(void) +start_input_pass (j_decompress_ptr cinfo) +{ + j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec; + + latch_quant_tables(cinfo); + (*lossyd->entropy_start_pass) (cinfo); + (*lossyd->coef_start_input_pass) (cinfo); +} + + +/* + * Initialize for an output processing pass. + */ + +METHODDEF(void) +start_output_pass (j_decompress_ptr cinfo) +{ + j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec; + + (*lossyd->idct_start_pass) (cinfo); + (*lossyd->coef_start_output_pass) (cinfo); +} + +/* + * Initialize the lossy decompression codec. + * This is called only once, during master selection. + */ + +GLOBAL(void) +jinit_lossy_d_codec (j_decompress_ptr cinfo) +{ + j_lossy_d_ptr lossyd; + boolean use_c_buffer; + + /* Create subobject in permanent pool */ + lossyd = (j_lossy_d_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, + SIZEOF(jpeg_lossy_d_codec)); + cinfo->codec = (struct jpeg_d_codec *) lossyd; + + /* Initialize sub-modules */ + + /* Inverse DCT */ + jinit_inverse_dct(cinfo); + /* Entropy decoding: either Huffman or arithmetic coding. */ + if (cinfo->arith_code) { +#ifdef WITH_ARITHMETIC_PATCH + jinit_arith_decoder(cinfo); +#else + ERREXIT(cinfo, JERR_ARITH_NOTIMPL); +#endif + } else { + if (cinfo->process == JPROC_PROGRESSIVE) { +#ifdef D_PROGRESSIVE_SUPPORTED + jinit_phuff_decoder(cinfo); +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } else + jinit_shuff_decoder(cinfo); + } + + use_c_buffer = cinfo->inputctl->has_multiple_scans || cinfo->buffered_image; + jinit_d_coef_controller(cinfo, use_c_buffer); + + /* Initialize method pointers. + * + * Note: consume_data and decompress_data are assigned in jdcoefct.c. + */ + lossyd->pub.calc_output_dimensions = calc_output_dimensions; + lossyd->pub.start_input_pass = start_input_pass; + lossyd->pub.start_output_pass = start_output_pass; +} + + + + diff --git a/dcmjpeg/libijg8/jdmainct.c b/dcmjpeg/libijg8/jdmainct.c new file mode 100644 index 00000000..f205f86f --- /dev/null +++ b/dcmjpeg/libijg8/jdmainct.c @@ -0,0 +1,512 @@ +/* + * jdmainct.c + * + * Copyright (C) 1994-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains the main buffer controller for decompression. + * The main buffer lies between the JPEG decompressor proper and the + * post-processor; it holds downsampled data in the JPEG colorspace. + * + * Note that this code is bypassed in raw-data mode, since the application + * supplies the equivalent of the main buffer in that case. + */ + +#define JPEG_INTERNALS +#include "jinclude8.h" +#include "jpeglib8.h" + + +/* + * In the current system design, the main buffer need never be a full-image + * buffer; any full-height buffers will be found inside the coefficient or + * postprocessing controllers. Nonetheless, the main controller is not + * trivial. Its responsibility is to provide context rows for upsampling/ + * rescaling, and doing this in an efficient fashion is a bit tricky. + * + * Postprocessor input data is counted in "row groups". A row group + * is defined to be (v_samp_factor * codec_data_unit / min_codec_data_unit) + * sample rows of each component. (We require codec_data_unit values to be + * chosen such that these numbers are integers. In practice codec_data_unit + * values will likely be powers of two, so we actually have the stronger + * condition that codec_data_unit / min_codec_data_unit is an integer.) + * Upsampling will typically produce max_v_samp_factor pixel rows from each + * row group (times any additional scale factor that the upsampler is + * applying). + * + * The decompression codec will deliver data to us one iMCU row at a time; + * each iMCU row contains v_samp_factor * codec_data_unit sample rows, or + * exactly min_codec_data_unit row groups. (This amount of data corresponds + * to one row of MCUs when the image is fully interleaved.) Note that the + * number of sample rows varies across components, but the number of row + * groups does not. Some garbage sample rows may be included in the last iMCU + * row at the bottom of the image. + * + * Depending on the vertical scaling algorithm used, the upsampler may need + * access to the sample row(s) above and below its current input row group. + * The upsampler is required to set need_context_rows TRUE at global selection + * time if so. When need_context_rows is FALSE, this controller can simply + * obtain one iMCU row at a time from the coefficient controller and dole it + * out as row groups to the postprocessor. + * + * When need_context_rows is TRUE, this controller guarantees that the buffer + * passed to postprocessing contains at least one row group's worth of samples + * above and below the row group(s) being processed. Note that the context + * rows "above" the first passed row group appear at negative row offsets in + * the passed buffer. At the top and bottom of the image, the required + * context rows are manufactured by duplicating the first or last real sample + * row; this avoids having special cases in the upsampling inner loops. + * + * The amount of context is fixed at one row group just because that's a + * convenient number for this controller to work with. The existing + * upsamplers really only need one sample row of context. An upsampler + * supporting arbitrary output rescaling might wish for more than one row + * group of context when shrinking the image; tough, we don't handle that. + * (This is justified by the assumption that downsizing will be handled mostly + * by adjusting the codec_data_unit values, so that the actual scale factor at + * the upsample step needn't be much less than one.) + * + * To provide the desired context, we have to retain the last two row groups + * of one iMCU row while reading in the next iMCU row. (The last row group + * can't be processed until we have another row group for its below-context, + * and so we have to save the next-to-last group too for its above-context.) + * We could do this most simply by copying data around in our buffer, but + * that'd be very slow. We can avoid copying any data by creating a rather + * strange pointer structure. Here's how it works. We allocate a workspace + * consisting of M+2 row groups (where M = min_codec_data_unit is the number + * of row groups per iMCU row). We create two sets of redundant pointers to + * the workspace. Labeling the physical row groups 0 to M+1, the synthesized + * pointer lists look like this: + * M+1 M-1 + * master pointer --> 0 master pointer --> 0 + * 1 1 + * ... ... + * M-3 M-3 + * M-2 M + * M-1 M+1 + * M M-2 + * M+1 M-1 + * 0 0 + * We read alternate iMCU rows using each master pointer; thus the last two + * row groups of the previous iMCU row remain un-overwritten in the workspace. + * The pointer lists are set up so that the required context rows appear to + * be adjacent to the proper places when we pass the pointer lists to the + * upsampler. + * + * The above pictures describe the normal state of the pointer lists. + * At top and bottom of the image, we diddle the pointer lists to duplicate + * the first or last sample row as necessary (this is cheaper than copying + * sample rows around). + * + * This scheme breaks down if M < 2, ie, min_codec_data_unit is 1. In that + * situation each iMCU row provides only one row group so the buffering logic + * must be different (eg, we must read two iMCU rows before we can emit the + * first row group). For now, we simply do not support providing context + * rows when min_codec_data_unit is 1. That combination seems unlikely to + * be worth providing --- if someone wants a 1/8th-size preview, they probably + * want it quick and dirty, so a context-free upsampler is sufficient. + */ + + +/* Private buffer controller object */ + +typedef struct { + struct jpeg_d_main_controller pub; /* public fields */ + + /* Pointer to allocated workspace (M or M+2 row groups). */ + JSAMPARRAY buffer[MAX_COMPONENTS]; + + boolean buffer_full; /* Have we gotten an iMCU row from decoder? */ + JDIMENSION rowgroup_ctr; /* counts row groups output to postprocessor */ + + /* Remaining fields are only used in the context case. */ + + /* These are the master pointers to the funny-order pointer lists. */ + JSAMPIMAGE xbuffer[2]; /* pointers to weird pointer lists */ + + int whichptr; /* indicates which pointer set is now in use */ + int context_state; /* process_data state machine status */ + JDIMENSION rowgroups_avail; /* row groups available to postprocessor */ + JDIMENSION iMCU_row_ctr; /* counts iMCU rows to detect image top/bot */ +} my_main_controller; + +typedef my_main_controller * my_main_ptr; + +/* context_state values: */ +#define CTX_PREPARE_FOR_IMCU 0 /* need to prepare for MCU row */ +#define CTX_PROCESS_IMCU 1 /* feeding iMCU to postprocessor */ +#define CTX_POSTPONED_ROW 2 /* feeding postponed row group */ + + +/* Forward declarations */ +METHODDEF(void) process_data_simple_main + JPP((j_decompress_ptr cinfo, JSAMPARRAY output_buf, + JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail)); +METHODDEF(void) process_data_context_main + JPP((j_decompress_ptr cinfo, JSAMPARRAY output_buf, + JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail)); +#ifdef QUANT_2PASS_SUPPORTED +METHODDEF(void) process_data_crank_post + JPP((j_decompress_ptr cinfo, JSAMPARRAY output_buf, + JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail)); +#endif + + +LOCAL(void) +alloc_funny_pointers (j_decompress_ptr cinfo) +/* Allocate space for the funny pointer lists. + * This is done only once, not once per pass. + */ +{ + my_main_ptr mymain = (my_main_ptr) cinfo->main; + int ci, rgroup; + int M = cinfo->min_codec_data_unit; + jpeg_component_info *compptr; + JSAMPARRAY xbuf; + + /* Get top-level space for component array pointers. + * We alloc both arrays with one call to save a few cycles. + */ + mymain->xbuffer[0] = (JSAMPIMAGE) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (size_t)cinfo->num_components * 2 * SIZEOF(JSAMPARRAY)); + mymain->xbuffer[1] = mymain->xbuffer[0] + cinfo->num_components; + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + rgroup = (compptr->v_samp_factor * compptr->codec_data_unit) / + cinfo->min_codec_data_unit; /* height of a row group of component */ + /* Get space for pointer lists --- M+4 row groups in each list. + * We alloc both pointer lists with one call to save a few cycles. + */ + xbuf = (JSAMPARRAY) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + 2 * (size_t)(rgroup * (M + 4)) * SIZEOF(JSAMPROW)); + xbuf += rgroup; /* want one row group at negative offsets */ + mymain->xbuffer[0][ci] = xbuf; + xbuf += rgroup * (M + 4); + mymain->xbuffer[1][ci] = xbuf; + } +} + + +LOCAL(void) +make_funny_pointers (j_decompress_ptr cinfo) +/* Create the funny pointer lists discussed in the comments above. + * The actual workspace is already allocated (in main->buffer), + * and the space for the pointer lists is allocated too. + * This routine just fills in the curiously ordered lists. + * This will be repeated at the beginning of each pass. + */ +{ + my_main_ptr mymain = (my_main_ptr) cinfo->main; + int ci, i, rgroup; + int M = cinfo->min_codec_data_unit; + jpeg_component_info *compptr; + JSAMPARRAY buf, xbuf0, xbuf1; + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + rgroup = (compptr->v_samp_factor * compptr->codec_data_unit) / + cinfo->min_codec_data_unit; /* height of a row group of component */ + xbuf0 = mymain->xbuffer[0][ci]; + xbuf1 = mymain->xbuffer[1][ci]; + /* First copy the workspace pointers as-is */ + buf = mymain->buffer[ci]; + for (i = 0; i < rgroup * (M + 2); i++) { + xbuf0[i] = xbuf1[i] = buf[i]; + } + /* In the second list, put the last four row groups in swapped order */ + for (i = 0; i < rgroup * 2; i++) { + xbuf1[rgroup*(M-2) + i] = buf[rgroup*M + i]; + xbuf1[rgroup*M + i] = buf[rgroup*(M-2) + i]; + } + /* The wraparound pointers at top and bottom will be filled later + * (see set_wraparound_pointers, below). Initially we want the "above" + * pointers to duplicate the first actual data line. This only needs + * to happen in xbuffer[0]. + */ + for (i = 0; i < rgroup; i++) { + xbuf0[i - rgroup] = xbuf0[0]; + } + } +} + + +LOCAL(void) +set_wraparound_pointers (j_decompress_ptr cinfo) +/* Set up the "wraparound" pointers at top and bottom of the pointer lists. + * This changes the pointer list state from top-of-image to the normal state. + */ +{ + my_main_ptr mymain = (my_main_ptr) cinfo->main; + int ci, i, rgroup; + int M = cinfo->min_codec_data_unit; + jpeg_component_info *compptr; + JSAMPARRAY xbuf0, xbuf1; + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + rgroup = (compptr->v_samp_factor * compptr->codec_data_unit) / + cinfo->min_codec_data_unit; /* height of a row group of component */ + xbuf0 = mymain->xbuffer[0][ci]; + xbuf1 = mymain->xbuffer[1][ci]; + for (i = 0; i < rgroup; i++) { + xbuf0[i - rgroup] = xbuf0[rgroup*(M+1) + i]; + xbuf1[i - rgroup] = xbuf1[rgroup*(M+1) + i]; + xbuf0[rgroup*(M+2) + i] = xbuf0[i]; + xbuf1[rgroup*(M+2) + i] = xbuf1[i]; + } + } +} + + +LOCAL(void) +set_bottom_pointers (j_decompress_ptr cinfo) +/* Change the pointer lists to duplicate the last sample row at the bottom + * of the image. whichptr indicates which xbuffer holds the final iMCU row. + * Also sets rowgroups_avail to indicate number of nondummy row groups in row. + */ +{ + my_main_ptr mymain = (my_main_ptr) cinfo->main; + int ci, i, rgroup, iMCUheight, rows_left; + jpeg_component_info *compptr; + JSAMPARRAY xbuf; + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + /* Count sample rows in one iMCU row and in one row group */ + iMCUheight = compptr->v_samp_factor * compptr->codec_data_unit; + rgroup = iMCUheight / cinfo->min_codec_data_unit; + /* Count nondummy sample rows remaining for this component */ + rows_left = (int) (compptr->downsampled_height % (JDIMENSION) iMCUheight); + if (rows_left == 0) rows_left = iMCUheight; + /* Count nondummy row groups. Should get same answer for each component, + * so we need only do it once. + */ + if (ci == 0) { + mymain->rowgroups_avail = (JDIMENSION) ((rows_left-1) / rgroup + 1); + } + /* Duplicate the last real sample row rgroup*2 times; this pads out the + * last partial rowgroup and ensures at least one full rowgroup of context. + */ + xbuf = mymain->xbuffer[mymain->whichptr][ci]; + for (i = 0; i < rgroup * 2; i++) { + xbuf[rows_left + i] = xbuf[rows_left-1]; + } + } +} + + +/* + * Initialize for a processing pass. + */ + +METHODDEF(void) +start_pass_main (j_decompress_ptr cinfo, J_BUF_MODE pass_mode) +{ + my_main_ptr mymain = (my_main_ptr) cinfo->main; + + switch (pass_mode) { + case JBUF_PASS_THRU: + if (cinfo->upsample->need_context_rows) { + mymain->pub.process_data = process_data_context_main; + make_funny_pointers(cinfo); /* Create the xbuffer[] lists */ + mymain->whichptr = 0; /* Read first iMCU row into xbuffer[0] */ + mymain->context_state = CTX_PREPARE_FOR_IMCU; + mymain->iMCU_row_ctr = 0; + } else { + /* Simple case with no context needed */ + mymain->pub.process_data = process_data_simple_main; + } + mymain->buffer_full = FALSE; /* Mark buffer empty */ + mymain->rowgroup_ctr = 0; + break; +#ifdef QUANT_2PASS_SUPPORTED + case JBUF_CRANK_DEST: + /* For last pass of 2-pass quantization, just crank the postprocessor */ + mymain->pub.process_data = process_data_crank_post; + break; +#endif + default: + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + break; + } +} + + +/* + * Process some data. + * This handles the simple case where no context is required. + */ + +METHODDEF(void) +process_data_simple_main (j_decompress_ptr cinfo, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail) +{ + my_main_ptr mymain = (my_main_ptr) cinfo->main; + JDIMENSION rowgroups_avail; + + /* Read input data if we haven't filled the main buffer yet */ + if (! mymain->buffer_full) { + if (! (*cinfo->codec->decompress_data) (cinfo, mymain->buffer)) + return; /* suspension forced, can do nothing more */ + mymain->buffer_full = TRUE; /* OK, we have an iMCU row to work with */ + } + + /* There are always min_codec_data_unit row groups in an iMCU row. */ + rowgroups_avail = (JDIMENSION) cinfo->min_codec_data_unit; + /* Note: at the bottom of the image, we may pass extra garbage row groups + * to the postprocessor. The postprocessor has to check for bottom + * of image anyway (at row resolution), so no point in us doing it too. + */ + + /* Feed the postprocessor */ + (*cinfo->post->post_process_data) (cinfo, mymain->buffer, + &mymain->rowgroup_ctr, rowgroups_avail, + output_buf, out_row_ctr, out_rows_avail); + + /* Has postprocessor consumed all the data yet? If so, mark buffer empty */ + if (mymain->rowgroup_ctr >= rowgroups_avail) { + mymain->buffer_full = FALSE; + mymain->rowgroup_ctr = 0; + } +} + + +/* + * Process some data. + * This handles the case where context rows must be provided. + */ + +METHODDEF(void) +process_data_context_main (j_decompress_ptr cinfo, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail) +{ + my_main_ptr mymain = (my_main_ptr) cinfo->main; + + /* Read input data if we haven't filled the main buffer yet */ + if (! mymain->buffer_full) { + if (! (*cinfo->codec->decompress_data) (cinfo, + mymain->xbuffer[mymain->whichptr])) + return; /* suspension forced, can do nothing more */ + mymain->buffer_full = TRUE; /* OK, we have an iMCU row to work with */ + mymain->iMCU_row_ctr++; /* count rows received */ + } + + /* Postprocessor typically will not swallow all the input data it is handed + * in one call (due to filling the output buffer first). Must be prepared + * to exit and restart. This switch lets us keep track of how far we got. + * Note that each case falls through to the next on successful completion. + */ + switch (mymain->context_state) { + case CTX_POSTPONED_ROW: + /* Call postprocessor using previously set pointers for postponed row */ + (*cinfo->post->post_process_data) (cinfo, mymain->xbuffer[mymain->whichptr], + &mymain->rowgroup_ctr, mymain->rowgroups_avail, + output_buf, out_row_ctr, out_rows_avail); + if (mymain->rowgroup_ctr < mymain->rowgroups_avail) + return; /* Need to suspend */ + mymain->context_state = CTX_PREPARE_FOR_IMCU; + if (*out_row_ctr >= out_rows_avail) + return; /* Postprocessor exactly filled output buf */ + /*FALLTHROUGH*/ + case CTX_PREPARE_FOR_IMCU: + /* Prepare to process first M-1 row groups of this iMCU row */ + mymain->rowgroup_ctr = 0; + mymain->rowgroups_avail = (JDIMENSION) (cinfo->min_codec_data_unit - 1); + /* Check for bottom of image: if so, tweak pointers to "duplicate" + * the last sample row, and adjust rowgroups_avail to ignore padding rows. + */ + if (mymain->iMCU_row_ctr == cinfo->total_iMCU_rows) + set_bottom_pointers(cinfo); + mymain->context_state = CTX_PROCESS_IMCU; + /*FALLTHROUGH*/ + case CTX_PROCESS_IMCU: + /* Call postprocessor using previously set pointers */ + (*cinfo->post->post_process_data) (cinfo, mymain->xbuffer[mymain->whichptr], + &mymain->rowgroup_ctr, mymain->rowgroups_avail, + output_buf, out_row_ctr, out_rows_avail); + if (mymain->rowgroup_ctr < mymain->rowgroups_avail) + return; /* Need to suspend */ + /* After the first iMCU, change wraparound pointers to normal state */ + if (mymain->iMCU_row_ctr == 1) + set_wraparound_pointers(cinfo); + /* Prepare to load new iMCU row using other xbuffer list */ + mymain->whichptr ^= 1; /* 0=>1 or 1=>0 */ + mymain->buffer_full = FALSE; + /* Still need to process last row group of this iMCU row, */ + /* which is saved at index M+1 of the other xbuffer */ + mymain->rowgroup_ctr = (JDIMENSION) (cinfo->min_codec_data_unit + 1); + mymain->rowgroups_avail = (JDIMENSION) (cinfo->min_codec_data_unit + 2); + mymain->context_state = CTX_POSTPONED_ROW; + } +} + + +/* + * Process some data. + * Final pass of two-pass quantization: just call the postprocessor. + * Source data will be the postprocessor controller's internal buffer. + */ + +#ifdef QUANT_2PASS_SUPPORTED + +METHODDEF(void) +process_data_crank_post (j_decompress_ptr cinfo, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail) +{ + (*cinfo->post->post_process_data) (cinfo, (JSAMPIMAGE) NULL, + (JDIMENSION *) NULL, (JDIMENSION) 0, + output_buf, out_row_ctr, out_rows_avail); +} + +#endif /* QUANT_2PASS_SUPPORTED */ + + +/* + * Initialize main buffer controller. + */ + +GLOBAL(void) +jinit_d_main_controller (j_decompress_ptr cinfo, boolean need_full_buffer) +{ + my_main_ptr mymain; + int ci, rgroup, ngroups; + jpeg_component_info *compptr; + + mymain = (my_main_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_main_controller)); + cinfo->main = (struct jpeg_d_main_controller *) mymain; + mymain->pub.start_pass = start_pass_main; + + if (need_full_buffer) /* shouldn't happen */ + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + + /* Allocate the workspace. + * ngroups is the number of row groups we need. + */ + if (cinfo->upsample->need_context_rows) { + if (cinfo->min_codec_data_unit < 2) /* unsupported, see comments above */ + ERREXIT(cinfo, JERR_NOTIMPL); + alloc_funny_pointers(cinfo); /* Alloc space for xbuffer[] lists */ + ngroups = cinfo->min_codec_data_unit + 2; + } else { + ngroups = cinfo->min_codec_data_unit; + } + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + rgroup = (compptr->v_samp_factor * compptr->codec_data_unit) / + cinfo->min_codec_data_unit; /* height of a row group of component */ + mymain->buffer[ci] = (*cinfo->mem->alloc_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + compptr->width_in_data_units * (JDIMENSION) compptr->codec_data_unit, + (JDIMENSION) (rgroup * ngroups)); + } +} diff --git a/dcmjpeg/libijg8/jdmarker.c b/dcmjpeg/libijg8/jdmarker.c new file mode 100644 index 00000000..23ee2b02 --- /dev/null +++ b/dcmjpeg/libijg8/jdmarker.c @@ -0,0 +1,1370 @@ +/* + * jdmarker.c + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains routines to decode JPEG datastream markers. + * Most of the complexity arises from our desire to support input + * suspension: if not all of the data for a marker is available, + * we must exit back to the application. On resumption, we reprocess + * the marker. + */ + +#define JPEG_INTERNALS +#include "jinclude8.h" +#include "jpeglib8.h" + + +typedef enum { /* JPEG marker codes */ + M_SOF0 = 0xc0, + M_SOF1 = 0xc1, + M_SOF2 = 0xc2, + M_SOF3 = 0xc3, + + M_SOF5 = 0xc5, + M_SOF6 = 0xc6, + M_SOF7 = 0xc7, + + M_JPG = 0xc8, + M_SOF9 = 0xc9, + M_SOF10 = 0xca, + M_SOF11 = 0xcb, + + M_SOF13 = 0xcd, + M_SOF14 = 0xce, + M_SOF15 = 0xcf, + + M_DHT = 0xc4, + + M_DAC = 0xcc, + + M_RST0 = 0xd0, + M_RST1 = 0xd1, + M_RST2 = 0xd2, + M_RST3 = 0xd3, + M_RST4 = 0xd4, + M_RST5 = 0xd5, + M_RST6 = 0xd6, + M_RST7 = 0xd7, + + M_SOI = 0xd8, + M_EOI = 0xd9, + M_SOS = 0xda, + M_DQT = 0xdb, + M_DNL = 0xdc, + M_DRI = 0xdd, + M_DHP = 0xde, + M_EXP = 0xdf, + + M_APP0 = 0xe0, + M_APP1 = 0xe1, + M_APP2 = 0xe2, + M_APP3 = 0xe3, + M_APP4 = 0xe4, + M_APP5 = 0xe5, + M_APP6 = 0xe6, + M_APP7 = 0xe7, + M_APP8 = 0xe8, + M_APP9 = 0xe9, + M_APP10 = 0xea, + M_APP11 = 0xeb, + M_APP12 = 0xec, + M_APP13 = 0xed, + M_APP14 = 0xee, + M_APP15 = 0xef, + + M_JPG0 = 0xf0, + M_JPG13 = 0xfd, + M_COM = 0xfe, + + M_TEM = 0x01, + + M_ERROR = 0x100 +} JPEG_MARKER; + + +/* Private state */ + +typedef struct { + struct jpeg_marker_reader pub; /* public fields */ + + /* Application-overridable marker processing methods */ + jpeg_marker_parser_method process_COM; + jpeg_marker_parser_method process_APPn[16]; + + /* Limit on marker data length to save for each marker type */ + unsigned int length_limit_COM; + unsigned int length_limit_APPn[16]; + + /* Status of COM/APPn marker saving */ + jpeg_saved_marker_ptr cur_marker; /* NULL if not processing a marker */ + unsigned int bytes_read; /* data bytes read so far in marker */ + /* Note: cur_marker is not linked into marker_list until it's all read. */ +} my_marker_reader; + +typedef my_marker_reader * my_marker_ptr; + + +/* + * Macros for fetching data from the data source module. + * + * At all times, cinfo->src->next_input_byte and ->bytes_in_buffer reflect + * the current restart point; we update them only when we have reached a + * suitable place to restart if a suspension occurs. + */ + +/* Declare and initialize local copies of input pointer/count */ +#define INPUT_VARS(cinfo) \ + struct jpeg_source_mgr * datasrc = (cinfo)->src; \ + const JOCTET * next_input_byte = datasrc->next_input_byte; \ + size_t bytes_in_buffer = datasrc->bytes_in_buffer + +/* Unload the local copies --- do this only at a restart boundary */ +#define INPUT_SYNC(cinfo) \ + ( datasrc->next_input_byte = next_input_byte, \ + datasrc->bytes_in_buffer = bytes_in_buffer ) + +/* Reload the local copies --- used only in MAKE_BYTE_AVAIL */ +#define INPUT_RELOAD(cinfo) \ + ( next_input_byte = datasrc->next_input_byte, \ + bytes_in_buffer = datasrc->bytes_in_buffer ) + +/* Internal macro for INPUT_BYTE and INPUT_2BYTES: make a byte available. + * Note we do *not* do INPUT_SYNC before calling fill_input_buffer, + * but we must reload the local copies after a successful fill. + */ +#define MAKE_BYTE_AVAIL(cinfo,action) \ + if (bytes_in_buffer == 0) { \ + if (! (*datasrc->fill_input_buffer) (cinfo)) \ + { action; } \ + INPUT_RELOAD(cinfo); \ + } + +/* Read a byte into variable V. + * If must suspend, take the specified action (typically "return FALSE"). + */ +#define INPUT_BYTE(cinfo,V,action) \ + MAKESTMT( MAKE_BYTE_AVAIL(cinfo,action); \ + bytes_in_buffer--; \ + V = GETJOCTET(*next_input_byte++); ) + +/* As above, but read two bytes interpreted as an unsigned 16-bit integer. + * V should be declared unsigned int or perhaps IJG_INT32. + */ +#define INPUT_2BYTES(cinfo,V,action) \ + MAKESTMT( MAKE_BYTE_AVAIL(cinfo,action); \ + bytes_in_buffer--; \ + V = ((unsigned int) GETJOCTET(*next_input_byte++)) << 8; \ + MAKE_BYTE_AVAIL(cinfo,action); \ + bytes_in_buffer--; \ + V += GETJOCTET(*next_input_byte++); ) + + +/* + * Routines to process JPEG markers. + * + * Entry condition: JPEG marker itself has been read and its code saved + * in cinfo->unread_marker; input restart point is just after the marker. + * + * Exit: if return TRUE, have read and processed any parameters, and have + * updated the restart point to point after the parameters. + * If return FALSE, was forced to suspend before reaching end of + * marker parameters; restart point has not been moved. Same routine + * will be called again after application supplies more input data. + * + * This approach to suspension assumes that all of a marker's parameters + * can fit into a single input bufferload. This should hold for "normal" + * markers. Some COM/APPn markers might have large parameter segments + * that might not fit. If we are simply dropping such a marker, we use + * skip_input_data to get past it, and thereby put the problem on the + * source manager's shoulders. If we are saving the marker's contents + * into memory, we use a slightly different convention: when forced to + * suspend, the marker processor updates the restart point to the end of + * what it's consumed (ie, the end of the buffer) before returning FALSE. + * On resumption, cinfo->unread_marker still contains the marker code, + * but the data source will point to the next chunk of marker data. + * The marker processor must retain internal state to deal with this. + * + * Note that we don't bother to avoid duplicate trace messages if a + * suspension occurs within marker parameters. Other side effects + * require more care. + */ + + +LOCAL(boolean) +get_soi (j_decompress_ptr cinfo) +/* Process an SOI marker */ +{ + int i; + + TRACEMS(cinfo, 1, JTRC_SOI); + + if (cinfo->marker->saw_SOI) + ERREXIT(cinfo, JERR_SOI_DUPLICATE); + + /* Reset all parameters that are defined to be reset by SOI */ + + for (i = 0; i < NUM_ARITH_TBLS; i++) { + cinfo->arith_dc_L[i] = 0; + cinfo->arith_dc_U[i] = 1; + cinfo->arith_ac_K[i] = 5; + } + cinfo->restart_interval = 0; + + /* Set initial assumptions for colorspace etc */ + + cinfo->jpeg_color_space = JCS_UNKNOWN; + cinfo->CCIR601_sampling = FALSE; /* Assume non-CCIR sampling??? */ + + cinfo->saw_JFIF_marker = FALSE; + cinfo->JFIF_major_version = 1; /* set default JFIF APP0 values */ + cinfo->JFIF_minor_version = 1; + cinfo->density_unit = 0; + cinfo->X_density = 1; + cinfo->Y_density = 1; + cinfo->saw_Adobe_marker = FALSE; + cinfo->Adobe_transform = 0; + + cinfo->marker->saw_SOI = TRUE; + + return TRUE; +} + + +LOCAL(boolean) +get_sof (j_decompress_ptr cinfo, J_CODEC_PROCESS process, boolean is_arith, + int data_unit) +/* Process a SOFn marker */ +{ + IJG_INT32 length; + int c, ci; + jpeg_component_info * compptr; + INPUT_VARS(cinfo); + + cinfo->data_unit = data_unit; + cinfo->process = process; + cinfo->arith_code = is_arith; + + INPUT_2BYTES(cinfo, length, return FALSE); + + INPUT_BYTE(cinfo, cinfo->data_precision, return FALSE); + INPUT_2BYTES(cinfo, cinfo->image_height, return FALSE); + INPUT_2BYTES(cinfo, cinfo->image_width, return FALSE); + INPUT_BYTE(cinfo, cinfo->num_components, return FALSE); + + length -= 8; + + TRACEMS4(cinfo, 1, JTRC_SOF, cinfo->unread_marker, + (int) cinfo->image_width, (int) cinfo->image_height, + cinfo->num_components); + + if (cinfo->marker->saw_SOF) + ERREXIT(cinfo, JERR_SOF_DUPLICATE); + + /* We don't support files in which the image height is initially specified */ + /* as 0 and is later redefined by DNL. As long as we have to check that, */ + /* might as well have a general sanity check. */ + if (cinfo->image_height <= 0 || cinfo->image_width <= 0 + || cinfo->num_components <= 0) + ERREXIT(cinfo, JERR_EMPTY_IMAGE); + + if (length != (cinfo->num_components * 3)) + ERREXIT(cinfo, JERR_BAD_LENGTH); + + if (cinfo->comp_info == NULL) /* do only once, even if suspend */ + cinfo->comp_info = (jpeg_component_info *) (*cinfo->mem->alloc_small) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + (size_t)cinfo->num_components * SIZEOF(jpeg_component_info)); + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + compptr->component_index = ci; + INPUT_BYTE(cinfo, compptr->component_id, return FALSE); + INPUT_BYTE(cinfo, c, return FALSE); + compptr->h_samp_factor = (c >> 4) & 15; + compptr->v_samp_factor = (c ) & 15; + INPUT_BYTE(cinfo, compptr->quant_tbl_no, return FALSE); + + TRACEMS4(cinfo, 1, JTRC_SOF_COMPONENT, + compptr->component_id, compptr->h_samp_factor, + compptr->v_samp_factor, compptr->quant_tbl_no); + } + + cinfo->marker->saw_SOF = TRUE; + + INPUT_SYNC(cinfo); + return TRUE; +} + + +LOCAL(boolean) +get_sos (j_decompress_ptr cinfo) +/* Process a SOS marker */ +{ + IJG_INT32 length; + int i, ci, n, c, cc; + jpeg_component_info * compptr; + INPUT_VARS(cinfo); + + if (! cinfo->marker->saw_SOF) + ERREXIT(cinfo, JERR_SOS_NO_SOF); + + INPUT_2BYTES(cinfo, length, return FALSE); + + INPUT_BYTE(cinfo, n, return FALSE); /* Number of components */ + + TRACEMS1(cinfo, 1, JTRC_SOS, n); + + if (length != (n * 2 + 6) || n < 1 || n > MAX_COMPS_IN_SCAN) + ERREXIT(cinfo, JERR_BAD_LENGTH); + + cinfo->comps_in_scan = n; + + /* Collect the component-spec parameters */ + + for (i = 0; i < n; i++) { + INPUT_BYTE(cinfo, cc, return FALSE); + INPUT_BYTE(cinfo, c, return FALSE); + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + if (cc == compptr->component_id) + goto id_found; + } + + ERREXIT1(cinfo, JERR_BAD_COMPONENT_ID, cc); + + id_found: + + cinfo->cur_comp_info[i] = compptr; + compptr->dc_tbl_no = (c >> 4) & 15; + compptr->ac_tbl_no = (c ) & 15; + + TRACEMS3(cinfo, 1, JTRC_SOS_COMPONENT, cc, + compptr->dc_tbl_no, compptr->ac_tbl_no); + } + + /* Collect the additional scan parameters Ss, Se, Ah/Al. */ + INPUT_BYTE(cinfo, c, return FALSE); + cinfo->Ss = c; + INPUT_BYTE(cinfo, c, return FALSE); + cinfo->Se = c; + INPUT_BYTE(cinfo, c, return FALSE); + cinfo->Ah = (c >> 4) & 15; + cinfo->Al = (c ) & 15; + + TRACEMS4(cinfo, 1, JTRC_SOS_PARAMS, cinfo->Ss, cinfo->Se, + cinfo->Ah, cinfo->Al); + + /* Prepare to scan data & restart markers */ + cinfo->marker->next_restart_num = 0; + + /* Count another SOS marker */ + cinfo->input_scan_number++; + + INPUT_SYNC(cinfo); + return TRUE; +} + + +#ifdef D_ARITH_CODING_SUPPORTED + +LOCAL(boolean) +get_dac (j_decompress_ptr cinfo) +/* Process a DAC marker */ +{ + IJG_INT32 length; + int idx, val; + INPUT_VARS(cinfo); + + INPUT_2BYTES(cinfo, length, return FALSE); + length -= 2; + + while (length > 0) { + INPUT_BYTE(cinfo, idx, return FALSE); + INPUT_BYTE(cinfo, val, return FALSE); + + length -= 2; + + TRACEMS2(cinfo, 1, JTRC_DAC, idx, val); + + if (idx < 0 || idx >= (2*NUM_ARITH_TBLS)) + ERREXIT1(cinfo, JERR_DAC_INDEX, idx); + + if (idx >= NUM_ARITH_TBLS) { /* define AC table */ + cinfo->arith_ac_K[idx-NUM_ARITH_TBLS] = (UINT8) val; + } else { /* define DC table */ + cinfo->arith_dc_L[idx] = (UINT8) (val & 0x0F); + cinfo->arith_dc_U[idx] = (UINT8) (val >> 4); + if (cinfo->arith_dc_L[idx] > cinfo->arith_dc_U[idx]) + ERREXIT1(cinfo, JERR_DAC_VALUE, val); + } + } + + if (length != 0) + ERREXIT(cinfo, JERR_BAD_LENGTH); + + INPUT_SYNC(cinfo); + return TRUE; +} + +#else /* ! D_ARITH_CODING_SUPPORTED */ + +#define get_dac(cinfo) skip_variable(cinfo) + +#endif /* D_ARITH_CODING_SUPPORTED */ + + +LOCAL(boolean) +get_dht (j_decompress_ptr cinfo) +/* Process a DHT marker */ +{ + IJG_INT32 length; + UINT8 bits[17]; + UINT8 huffval[256]; + int i, idx, count; + JHUFF_TBL **htblptr; + INPUT_VARS(cinfo); + + INPUT_2BYTES(cinfo, length, return FALSE); + length -= 2; + + while (length > 16) { + INPUT_BYTE(cinfo, idx, return FALSE); + + TRACEMS1(cinfo, 1, JTRC_DHT, idx); + + bits[0] = 0; + count = 0; + for (i = 1; i <= 16; i++) { + INPUT_BYTE(cinfo, bits[i], return FALSE); + count += bits[i]; + } + + length -= 1 + 16; + + TRACEMS8(cinfo, 2, JTRC_HUFFBITS, + bits[1], bits[2], bits[3], bits[4], + bits[5], bits[6], bits[7], bits[8]); + TRACEMS8(cinfo, 2, JTRC_HUFFBITS, + bits[9], bits[10], bits[11], bits[12], + bits[13], bits[14], bits[15], bits[16]); + + /* Here we just do minimal validation of the counts to avoid walking + * off the end of our table space. jdhuff.c will check more carefully. + */ + if (count > 256 || ((IJG_INT32) count) > length) + ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); + + for (i = 0; i < count; i++) + INPUT_BYTE(cinfo, huffval[i], return FALSE); + + length -= count; + + if (idx & 0x10) { /* AC table definition */ + idx -= 0x10; + htblptr = &cinfo->ac_huff_tbl_ptrs[idx]; + } else { /* DC table definition */ + htblptr = &cinfo->dc_huff_tbl_ptrs[idx]; + } + + if (idx < 0 || idx >= NUM_HUFF_TBLS) + ERREXIT1(cinfo, JERR_DHT_INDEX, idx); + + if (*htblptr == NULL) + *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo); + + MEMCOPY((*htblptr)->bits, bits, SIZEOF((*htblptr)->bits)); + MEMCOPY((*htblptr)->huffval, huffval, SIZEOF((*htblptr)->huffval)); + } + + if (length != 0) + ERREXIT(cinfo, JERR_BAD_LENGTH); + + INPUT_SYNC(cinfo); + return TRUE; +} + + +LOCAL(boolean) +get_dqt (j_decompress_ptr cinfo) +/* Process a DQT marker */ +{ + IJG_INT32 length; + int n, i, prec; + unsigned int tmp; + JQUANT_TBL *quant_ptr; + INPUT_VARS(cinfo); + + INPUT_2BYTES(cinfo, length, return FALSE); + length -= 2; + + while (length > 0) { + INPUT_BYTE(cinfo, n, return FALSE); + prec = n >> 4; + n &= 0x0F; + + TRACEMS2(cinfo, 1, JTRC_DQT, n, prec); + + if (n >= NUM_QUANT_TBLS) + ERREXIT1(cinfo, JERR_DQT_INDEX, n); + + if (cinfo->quant_tbl_ptrs[n] == NULL) + cinfo->quant_tbl_ptrs[n] = jpeg_alloc_quant_table((j_common_ptr) cinfo); + quant_ptr = cinfo->quant_tbl_ptrs[n]; + + for (i = 0; i < DCTSIZE2; i++) { + if (prec) + INPUT_2BYTES(cinfo, tmp, return FALSE); + else + INPUT_BYTE(cinfo, tmp, return FALSE); + /* We convert the zigzag-order table to natural array order. */ + quant_ptr->quantval[jpeg_natural_order[i]] = (UINT16) tmp; + } + + if (cinfo->err->trace_level >= 2) { + for (i = 0; i < DCTSIZE2; i += 8) { + TRACEMS8(cinfo, 2, JTRC_QUANTVALS, + quant_ptr->quantval[i], quant_ptr->quantval[i+1], + quant_ptr->quantval[i+2], quant_ptr->quantval[i+3], + quant_ptr->quantval[i+4], quant_ptr->quantval[i+5], + quant_ptr->quantval[i+6], quant_ptr->quantval[i+7]); + } + } + + length -= DCTSIZE2+1; + if (prec) length -= DCTSIZE2; + } + + if (length != 0) + ERREXIT(cinfo, JERR_BAD_LENGTH); + + INPUT_SYNC(cinfo); + return TRUE; +} + + +LOCAL(boolean) +get_dri (j_decompress_ptr cinfo) +/* Process a DRI marker */ +{ + IJG_INT32 length; + unsigned int tmp; + INPUT_VARS(cinfo); + + INPUT_2BYTES(cinfo, length, return FALSE); + + if (length != 4) + ERREXIT(cinfo, JERR_BAD_LENGTH); + + INPUT_2BYTES(cinfo, tmp, return FALSE); + + TRACEMS1(cinfo, 1, JTRC_DRI, (int)tmp); + + cinfo->restart_interval = tmp; + + INPUT_SYNC(cinfo); + return TRUE; +} + + +/* + * Routines for processing APPn and COM markers. + * These are either saved in memory or discarded, per application request. + * APP0 and APP14 are specially checked to see if they are + * JFIF and Adobe markers, respectively. + */ + +#define APP0_DATA_LEN 14 /* Length of interesting data in APP0 */ +#define APP14_DATA_LEN 12 /* Length of interesting data in APP14 */ +#define APPN_DATA_LEN 14 /* Must be the largest of the above!! */ + + +LOCAL(void) +examine_app0 (j_decompress_ptr cinfo, JOCTET FAR * data, + unsigned int datalen, IJG_INT32 remaining) +/* Examine first few bytes from an APP0. + * Take appropriate action if it is a JFIF marker. + * datalen is # of bytes at data[], remaining is length of rest of marker data. + */ +{ + IJG_INT32 totallen = (IJG_INT32) datalen + remaining; + + if (datalen >= APP0_DATA_LEN && + GETJOCTET(data[0]) == 0x4A && + GETJOCTET(data[1]) == 0x46 && + GETJOCTET(data[2]) == 0x49 && + GETJOCTET(data[3]) == 0x46 && + GETJOCTET(data[4]) == 0) { + /* Found JFIF APP0 marker: save info */ + cinfo->saw_JFIF_marker = TRUE; + cinfo->JFIF_major_version = GETJOCTET(data[5]); + cinfo->JFIF_minor_version = GETJOCTET(data[6]); + cinfo->density_unit = GETJOCTET(data[7]); + cinfo->X_density = (UINT16)((GETJOCTET(data[8]) << 8) + GETJOCTET(data[9])); + cinfo->Y_density = (UINT16)((GETJOCTET(data[10]) << 8) + GETJOCTET(data[11])); + /* Check version. + * Major version must be 1, anything else signals an incompatible change. + * (We used to treat this as an error, but now it's a nonfatal warning, + * because some bozo at Hijaak couldn't read the spec.) + * Minor version should be 0..2, but process anyway if newer. + */ + if (cinfo->JFIF_major_version != 1) + WARNMS2(cinfo, JWRN_JFIF_MAJOR, + cinfo->JFIF_major_version, cinfo->JFIF_minor_version); + /* Generate trace messages */ + TRACEMS5(cinfo, 1, JTRC_JFIF, + cinfo->JFIF_major_version, cinfo->JFIF_minor_version, + cinfo->X_density, cinfo->Y_density, cinfo->density_unit); + /* Validate thumbnail dimensions and issue appropriate messages */ + if (GETJOCTET(data[12]) | GETJOCTET(data[13])) + TRACEMS2(cinfo, 1, JTRC_JFIF_THUMBNAIL, + GETJOCTET(data[12]), GETJOCTET(data[13])); + totallen -= APP0_DATA_LEN; + if (totallen != + ((IJG_INT32)GETJOCTET(data[12]) * (IJG_INT32)GETJOCTET(data[13]) * (IJG_INT32) 3)) + TRACEMS1(cinfo, 1, JTRC_JFIF_BADTHUMBNAILSIZE, (int) totallen); + } else if (datalen >= 6 && + GETJOCTET(data[0]) == 0x4A && + GETJOCTET(data[1]) == 0x46 && + GETJOCTET(data[2]) == 0x58 && + GETJOCTET(data[3]) == 0x58 && + GETJOCTET(data[4]) == 0) { + /* Found JFIF "JFXX" extension APP0 marker */ + /* The library doesn't actually do anything with these, + * but we try to produce a helpful trace message. + */ + switch (GETJOCTET(data[5])) { + case 0x10: + TRACEMS1(cinfo, 1, JTRC_THUMB_JPEG, (int) totallen); + break; + case 0x11: + TRACEMS1(cinfo, 1, JTRC_THUMB_PALETTE, (int) totallen); + break; + case 0x13: + TRACEMS1(cinfo, 1, JTRC_THUMB_RGB, (int) totallen); + break; + default: + TRACEMS2(cinfo, 1, JTRC_JFIF_EXTENSION, + GETJOCTET(data[5]), (int) totallen); + break; + } + } else { + /* Start of APP0 does not match "JFIF" or "JFXX", or too short */ + TRACEMS1(cinfo, 1, JTRC_APP0, (int) totallen); + } +} + + +LOCAL(void) +examine_app14 (j_decompress_ptr cinfo, JOCTET FAR * data, + unsigned int datalen, IJG_INT32 remaining) +/* Examine first few bytes from an APP14. + * Take appropriate action if it is an Adobe marker. + * datalen is # of bytes at data[], remaining is length of rest of marker data. + */ +{ + unsigned int version, flags0, flags1, transform; + + if (datalen >= APP14_DATA_LEN && + GETJOCTET(data[0]) == 0x41 && + GETJOCTET(data[1]) == 0x64 && + GETJOCTET(data[2]) == 0x6F && + GETJOCTET(data[3]) == 0x62 && + GETJOCTET(data[4]) == 0x65) { + /* Found Adobe APP14 marker */ + version = (unsigned int)((GETJOCTET(data[5]) << 8) + GETJOCTET(data[6])); + flags0 = (unsigned int)((GETJOCTET(data[7]) << 8) + GETJOCTET(data[8])); + flags1 = (unsigned int)((GETJOCTET(data[9]) << 8) + GETJOCTET(data[10])); + transform = GETJOCTET(data[11]); + TRACEMS4(cinfo, 1, JTRC_ADOBE, (int)version, (int)flags0, (int)flags1, (int)transform); + cinfo->saw_Adobe_marker = TRUE; + cinfo->Adobe_transform = (UINT8) transform; + } else { + /* Start of APP14 does not match "Adobe", or too short */ + TRACEMS1(cinfo, 1, JTRC_APP14, (int) (datalen + remaining)); + } +} + + +METHODDEF(boolean) +get_interesting_appn (j_decompress_ptr cinfo) +/* Process an APP0 or APP14 marker without saving it */ +{ + IJG_INT32 length; + JOCTET b[APPN_DATA_LEN]; + unsigned int i, numtoread; + INPUT_VARS(cinfo); + + INPUT_2BYTES(cinfo, length, return FALSE); + length -= 2; + + /* get the interesting part of the marker data */ + if (length >= APPN_DATA_LEN) + numtoread = APPN_DATA_LEN; + else if (length > 0) + numtoread = (unsigned int) length; + else + numtoread = 0; + for (i = 0; i < numtoread; i++) + INPUT_BYTE(cinfo, b[i], return FALSE); + length -= numtoread; + + /* process it */ + switch (cinfo->unread_marker) { + case M_APP0: + examine_app0(cinfo, (JOCTET FAR *) b, numtoread, length); + break; + case M_APP14: + examine_app14(cinfo, (JOCTET FAR *) b, numtoread, length); + break; + default: + /* can't get here unless jpeg_save_markers chooses wrong processor */ + ERREXIT1(cinfo, JERR_UNKNOWN_MARKER, cinfo->unread_marker); + break; + } + + /* skip any remaining data -- could be lots */ + INPUT_SYNC(cinfo); + if (length > 0) + (*cinfo->src->skip_input_data) (cinfo, (long) length); + + return TRUE; +} + + +#ifdef SAVE_MARKERS_SUPPORTED + +METHODDEF(boolean) +save_marker (j_decompress_ptr cinfo) +/* Save an APPn or COM marker into the marker list */ +{ + my_marker_ptr marker = (my_marker_ptr) cinfo->marker; + jpeg_saved_marker_ptr cur_marker = marker->cur_marker; + unsigned int bytes_read, data_length; + JOCTET FAR * data; + IJG_INT32 length = 0; + INPUT_VARS(cinfo); + + if (cur_marker == NULL) { + /* begin reading a marker */ + INPUT_2BYTES(cinfo, length, return FALSE); + length -= 2; + if (length >= 0) { /* watch out for bogus length word */ + /* figure out how much we want to save */ + unsigned int limit; + if (cinfo->unread_marker == (int) M_COM) + limit = marker->length_limit_COM; + else + limit = marker->length_limit_APPn[cinfo->unread_marker - (int) M_APP0]; + if ((unsigned int) length < limit) + limit = (unsigned int) length; + /* allocate and initialize the marker item */ + cur_marker = (jpeg_saved_marker_ptr) + (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(struct jpeg_marker_struct) + limit); + cur_marker->next = NULL; + cur_marker->marker = (UINT8) cinfo->unread_marker; + cur_marker->original_length = (unsigned int) length; + cur_marker->data_length = limit; + /* data area is just beyond the jpeg_marker_struct */ + data = cur_marker->data = (JOCTET FAR *) (cur_marker + 1); + marker->cur_marker = cur_marker; + marker->bytes_read = 0; + bytes_read = 0; + data_length = limit; + } else { + /* deal with bogus length word */ + bytes_read = data_length = 0; + data = NULL; + } + } else { + /* resume reading a marker */ + bytes_read = marker->bytes_read; + data_length = cur_marker->data_length; + data = cur_marker->data + bytes_read; + } + + while (bytes_read < data_length) { + INPUT_SYNC(cinfo); /* move the restart point to here */ + marker->bytes_read = bytes_read; + /* If there's not at least one byte in buffer, suspend */ + MAKE_BYTE_AVAIL(cinfo, return FALSE); + /* Copy bytes with reasonable rapidity */ + while (bytes_read < data_length && bytes_in_buffer > 0) { + *data++ = *next_input_byte++; + bytes_in_buffer--; + bytes_read++; + } + } + + /* Done reading what we want to read */ + if (cur_marker != NULL) { /* will be NULL if bogus length word */ + /* Add new marker to end of list */ + if (cinfo->marker_list == NULL) { + cinfo->marker_list = cur_marker; + } else { + jpeg_saved_marker_ptr prev = cinfo->marker_list; + while (prev->next != NULL) + prev = prev->next; + prev->next = cur_marker; + } + /* Reset pointer & calc remaining data length */ + data = cur_marker->data; + length = cur_marker->original_length - data_length; + } + /* Reset to initial state for next marker */ + marker->cur_marker = NULL; + + /* Process the marker if interesting; else just make a generic trace msg */ + switch (cinfo->unread_marker) { + case M_APP0: + examine_app0(cinfo, data, data_length, length); + break; + case M_APP14: + examine_app14(cinfo, data, data_length, length); + break; + default: + TRACEMS2(cinfo, 1, JTRC_MISC_MARKER, cinfo->unread_marker, + (int) (data_length + length)); + break; + } + + /* skip any remaining data -- could be lots */ + INPUT_SYNC(cinfo); /* do before skip_input_data */ + if (length > 0) + (*cinfo->src->skip_input_data) (cinfo, (long) length); + + return TRUE; +} + +#endif /* SAVE_MARKERS_SUPPORTED */ + + +METHODDEF(boolean) +skip_variable (j_decompress_ptr cinfo) +/* Skip over an unknown or uninteresting variable-length marker */ +{ + IJG_INT32 length; + INPUT_VARS(cinfo); + + INPUT_2BYTES(cinfo, length, return FALSE); + length -= 2; + + TRACEMS2(cinfo, 1, JTRC_MISC_MARKER, cinfo->unread_marker, (int) length); + + INPUT_SYNC(cinfo); /* do before skip_input_data */ + if (length > 0) + (*cinfo->src->skip_input_data) (cinfo, (long) length); + + return TRUE; +} + + +/* + * Find the next JPEG marker, save it in cinfo->unread_marker. + * Returns FALSE if had to suspend before reaching a marker; + * in that case cinfo->unread_marker is unchanged. + * + * Note that the result might not be a valid marker code, + * but it will never be 0 or FF. + */ + +LOCAL(boolean) +next_marker (j_decompress_ptr cinfo) +{ + int c; + INPUT_VARS(cinfo); + + for (;;) { + INPUT_BYTE(cinfo, c, return FALSE); + /* Skip any non-FF bytes. + * This may look a bit inefficient, but it will not occur in a valid file. + * We sync after each discarded byte so that a suspending data source + * can discard the byte from its buffer. + */ + while (c != 0xFF) { + cinfo->marker->discarded_bytes++; + INPUT_SYNC(cinfo); + INPUT_BYTE(cinfo, c, return FALSE); + } + /* This loop swallows any duplicate FF bytes. Extra FFs are legal as + * pad bytes, so don't count them in discarded_bytes. We assume there + * will not be so many consecutive FF bytes as to overflow a suspending + * data source's input buffer. + */ + do { + INPUT_BYTE(cinfo, c, return FALSE); + } while (c == 0xFF); + if (c != 0) + break; /* found a valid marker, exit loop */ + /* Reach here if we found a stuffed-zero data sequence (FF/00). + * Discard it and loop back to try again. + */ + cinfo->marker->discarded_bytes += 2; + INPUT_SYNC(cinfo); + } + + if (cinfo->marker->discarded_bytes != 0) { + WARNMS2(cinfo, JWRN_EXTRANEOUS_DATA, (int)cinfo->marker->discarded_bytes, c); + cinfo->marker->discarded_bytes = 0; + } + + cinfo->unread_marker = c; + + INPUT_SYNC(cinfo); + return TRUE; +} + + +LOCAL(boolean) +first_marker (j_decompress_ptr cinfo) +/* Like next_marker, but used to obtain the initial SOI marker. */ +/* For this marker, we do not allow preceding garbage or fill; otherwise, + * we might well scan an entire input file before realizing it ain't JPEG. + * If an application wants to process non-JFIF files, it must seek to the + * SOI before calling the JPEG library. + */ +{ + int c, c2; + INPUT_VARS(cinfo); + + INPUT_BYTE(cinfo, c, return FALSE); + INPUT_BYTE(cinfo, c2, return FALSE); + if (c != 0xFF || c2 != (int) M_SOI) + ERREXIT2(cinfo, JERR_NO_SOI, c, c2); + + cinfo->unread_marker = c2; + + INPUT_SYNC(cinfo); + return TRUE; +} + + +/* + * Read markers until SOS or EOI. + * + * Returns same codes as are defined for jpeg_consume_input: + * JPEG_SUSPENDED, JPEG_REACHED_SOS, or JPEG_REACHED_EOI. + */ + +METHODDEF(int) +read_markers (j_decompress_ptr cinfo) +{ + /* Outer loop repeats once for each marker. */ + for (;;) { + /* Collect the marker proper, unless we already did. */ + /* NB: first_marker() enforces the requirement that SOI appear first. */ + if (cinfo->unread_marker == 0) { + if (! cinfo->marker->saw_SOI) { + if (! first_marker(cinfo)) + return JPEG_SUSPENDED; + } else { + if (! next_marker(cinfo)) + return JPEG_SUSPENDED; + } + } + /* At this point cinfo->unread_marker contains the marker code and the + * input point is just past the marker proper, but before any parameters. + * A suspension will cause us to return with this state still true. + */ + switch (cinfo->unread_marker) { + case M_SOI: + if (! get_soi(cinfo)) + return JPEG_SUSPENDED; + break; + + case M_SOF0: /* Baseline */ + case M_SOF1: /* Extended sequential, Huffman */ + if (! get_sof(cinfo, JPROC_SEQUENTIAL, FALSE, DCTSIZE)) + return JPEG_SUSPENDED; + break; + + case M_SOF2: /* Progressive, Huffman */ + if (! get_sof(cinfo, JPROC_PROGRESSIVE, FALSE, DCTSIZE)) + return JPEG_SUSPENDED; + break; + + case M_SOF3: /* Lossless, Huffman */ + if (! get_sof(cinfo, JPROC_LOSSLESS, FALSE, 1)) + return JPEG_SUSPENDED; + break; + + case M_SOF9: /* Extended sequential, arithmetic */ + if (! get_sof(cinfo, JPROC_SEQUENTIAL, TRUE, DCTSIZE)) + return JPEG_SUSPENDED; + break; + + case M_SOF10: /* Progressive, arithmetic */ + if (! get_sof(cinfo, JPROC_PROGRESSIVE, TRUE, DCTSIZE)) + return JPEG_SUSPENDED; + break; + + case M_SOF11: /* Lossless, arithmetic */ + if (! get_sof(cinfo, JPROC_LOSSLESS, TRUE, 1)) + return JPEG_SUSPENDED; + break; + + /* Currently unsupported SOFn types */ + case M_SOF5: /* Differential sequential, Huffman */ + case M_SOF6: /* Differential progressive, Huffman */ + case M_SOF7: /* Differential lossless, Huffman */ + case M_JPG: /* Reserved for JPEG extensions */ + case M_SOF13: /* Differential sequential, arithmetic */ + case M_SOF14: /* Differential progressive, arithmetic */ + case M_SOF15: /* Differential lossless, arithmetic */ + ERREXIT1(cinfo, JERR_SOF_UNSUPPORTED, cinfo->unread_marker); + break; + + case M_SOS: + if (! get_sos(cinfo)) + return JPEG_SUSPENDED; + cinfo->unread_marker = 0; /* processed the marker */ + return JPEG_REACHED_SOS; + + case M_EOI: + TRACEMS(cinfo, 1, JTRC_EOI); + cinfo->unread_marker = 0; /* processed the marker */ + return JPEG_REACHED_EOI; + + case M_DAC: + if (! get_dac(cinfo)) + return JPEG_SUSPENDED; + break; + + case M_DHT: + if (! get_dht(cinfo)) + return JPEG_SUSPENDED; + break; + + case M_DQT: + if (! get_dqt(cinfo)) + return JPEG_SUSPENDED; + break; + + case M_DRI: + if (! get_dri(cinfo)) + return JPEG_SUSPENDED; + break; + + case M_APP0: + case M_APP1: + case M_APP2: + case M_APP3: + case M_APP4: + case M_APP5: + case M_APP6: + case M_APP7: + case M_APP8: + case M_APP9: + case M_APP10: + case M_APP11: + case M_APP12: + case M_APP13: + case M_APP14: + case M_APP15: + if (! (*((my_marker_ptr) cinfo->marker)->process_APPn[ + cinfo->unread_marker - (int) M_APP0]) (cinfo)) + return JPEG_SUSPENDED; + break; + + case M_COM: + if (! (*((my_marker_ptr) cinfo->marker)->process_COM) (cinfo)) + return JPEG_SUSPENDED; + break; + + case M_RST0: /* these are all parameterless */ + case M_RST1: + case M_RST2: + case M_RST3: + case M_RST4: + case M_RST5: + case M_RST6: + case M_RST7: + case M_TEM: + TRACEMS1(cinfo, 1, JTRC_PARMLESS_MARKER, cinfo->unread_marker); + break; + + case M_DNL: /* Ignore DNL ... perhaps the wrong thing */ + if (! skip_variable(cinfo)) + return JPEG_SUSPENDED; + break; + + default: /* must be DHP, EXP, JPGn, or RESn */ + /* For now, we treat the reserved markers as fatal errors since they are + * likely to be used to signal incompatible JPEG Part 3 extensions. + * Once the JPEG 3 version-number marker is well defined, this code + * ought to change! + */ + ERREXIT1(cinfo, JERR_UNKNOWN_MARKER, cinfo->unread_marker); + break; + } + /* Successfully processed marker, so reset state variable */ + cinfo->unread_marker = 0; + } /* end loop */ +} + + +/* + * Read a restart marker, which is expected to appear next in the datastream; + * if the marker is not there, take appropriate recovery action. + * Returns FALSE if suspension is required. + * + * This is called by the entropy decoder after it has read an appropriate + * number of MCUs. cinfo->unread_marker may be nonzero if the entropy decoder + * has already read a marker from the data source. Under normal conditions + * cinfo->unread_marker will be reset to 0 before returning; if not reset, + * it holds a marker which the decoder will be unable to read past. + */ + +METHODDEF(boolean) +read_restart_marker (j_decompress_ptr cinfo) +{ + /* Obtain a marker unless we already did. */ + /* Note that next_marker will complain if it skips any data. */ + if (cinfo->unread_marker == 0) { + if (! next_marker(cinfo)) + return FALSE; + } + + if (cinfo->unread_marker == + ((int) M_RST0 + cinfo->marker->next_restart_num)) { + /* Normal case --- swallow the marker and let entropy decoder continue */ + TRACEMS1(cinfo, 3, JTRC_RST, cinfo->marker->next_restart_num); + cinfo->unread_marker = 0; + } else { + /* Uh-oh, the restart markers have been messed up. */ + /* Let the data source manager determine how to resync. */ + if (! (*cinfo->src->resync_to_restart) (cinfo, + cinfo->marker->next_restart_num)) + return FALSE; + } + + /* Update next-restart state */ + cinfo->marker->next_restart_num = (cinfo->marker->next_restart_num + 1) & 7; + + return TRUE; +} + + +/* + * This is the default resync_to_restart method for data source managers + * to use if they don't have any better approach. Some data source managers + * may be able to back up, or may have additional knowledge about the data + * which permits a more intelligent recovery strategy; such managers would + * presumably supply their own resync method. + * + * read_restart_marker calls resync_to_restart if it finds a marker other than + * the restart marker it was expecting. (This code is *not* used unless + * a nonzero restart interval has been declared.) cinfo->unread_marker is + * the marker code actually found (might be anything, except 0 or FF). + * The desired restart marker number (0..7) is passed as a parameter. + * This routine is supposed to apply whatever error recovery strategy seems + * appropriate in order to position the input stream to the next data segment. + * Note that cinfo->unread_marker is treated as a marker appearing before + * the current data-source input point; usually it should be reset to zero + * before returning. + * Returns FALSE if suspension is required. + * + * This implementation is substantially constrained by wanting to treat the + * input as a data stream; this means we can't back up. Therefore, we have + * only the following actions to work with: + * 1. Simply discard the marker and let the entropy decoder resume at next + * byte of file. + * 2. Read forward until we find another marker, discarding intervening + * data. (In theory we could look ahead within the current bufferload, + * without having to discard data if we don't find the desired marker. + * This idea is not implemented here, in part because it makes behavior + * dependent on buffer size and chance buffer-boundary positions.) + * 3. Leave the marker unread (by failing to zero cinfo->unread_marker). + * This will cause the entropy decoder to process an empty data segment, + * inserting dummy zeroes, and then we will reprocess the marker. + * + * #2 is appropriate if we think the desired marker lies ahead, while #3 is + * appropriate if the found marker is a future restart marker (indicating + * that we have missed the desired restart marker, probably because it got + * corrupted). + * We apply #2 or #3 if the found marker is a restart marker no more than + * two counts behind or ahead of the expected one. We also apply #2 if the + * found marker is not a legal JPEG marker code (it's certainly bogus data). + * If the found marker is a restart marker more than 2 counts away, we do #1 + * (too much risk that the marker is erroneous; with luck we will be able to + * resync at some future point). + * For any valid non-restart JPEG marker, we apply #3. This keeps us from + * overrunning the end of a scan. An implementation limited to single-scan + * files might find it better to apply #2 for markers other than EOI, since + * any other marker would have to be bogus data in that case. + */ + +GLOBAL(boolean) +jpeg_resync_to_restart (j_decompress_ptr cinfo, int desired) +{ + int marker = cinfo->unread_marker; + int action = 1; + + /* Always put up a warning. */ + WARNMS2(cinfo, JWRN_MUST_RESYNC, marker, desired); + + /* Outer loop handles repeated decision after scanning forward. */ + for (;;) { + if (marker < (int) M_SOF0) + action = 2; /* invalid marker */ + else if (marker < (int) M_RST0 || marker > (int) M_RST7) + action = 3; /* valid non-restart marker */ + else { + if (marker == ((int) M_RST0 + ((desired+1) & 7)) || + marker == ((int) M_RST0 + ((desired+2) & 7))) + action = 3; /* one of the next two expected restarts */ + else if (marker == ((int) M_RST0 + ((desired-1) & 7)) || + marker == ((int) M_RST0 + ((desired-2) & 7))) + action = 2; /* a prior restart, so advance */ + else + action = 1; /* desired restart or too far away */ + } + TRACEMS2(cinfo, 4, JTRC_RECOVERY_ACTION, marker, action); + switch (action) { + case 1: + /* Discard marker and let entropy decoder resume processing. */ + cinfo->unread_marker = 0; + return TRUE; + case 2: + /* Scan to the next marker, and repeat the decision loop. */ + if (! next_marker(cinfo)) + return FALSE; + marker = cinfo->unread_marker; + break; + case 3: + /* Return without advancing past this marker. */ + /* Entropy decoder will be forced to process an empty segment. */ + return TRUE; + } + } /* end loop */ +} + + +/* + * Reset marker processing state to begin a fresh datastream. + */ + +METHODDEF(void) +reset_marker_reader (j_decompress_ptr cinfo) +{ + my_marker_ptr marker = (my_marker_ptr) cinfo->marker; + + cinfo->comp_info = NULL; /* until allocated by get_sof */ + cinfo->input_scan_number = 0; /* no SOS seen yet */ + cinfo->unread_marker = 0; /* no pending marker */ + marker->pub.saw_SOI = FALSE; /* set internal state too */ + marker->pub.saw_SOF = FALSE; + marker->pub.discarded_bytes = 0; + marker->cur_marker = NULL; +} + + +/* + * Initialize the marker reader module. + * This is called only once, when the decompression object is created. + */ + +GLOBAL(void) +jinit_marker_reader (j_decompress_ptr cinfo) +{ + my_marker_ptr marker; + int i; + + /* Create subobject in permanent pool */ + marker = (my_marker_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, + SIZEOF(my_marker_reader)); + cinfo->marker = (struct jpeg_marker_reader *) marker; + /* Initialize public method pointers */ + marker->pub.reset_marker_reader = reset_marker_reader; + marker->pub.read_markers = read_markers; + marker->pub.read_restart_marker = read_restart_marker; + /* Initialize COM/APPn processing. + * By default, we examine and then discard APP0 and APP14, + * but simply discard COM and all other APPn. + */ + marker->process_COM = skip_variable; + marker->length_limit_COM = 0; + for (i = 0; i < 16; i++) { + marker->process_APPn[i] = skip_variable; + marker->length_limit_APPn[i] = 0; + } + marker->process_APPn[0] = get_interesting_appn; + marker->process_APPn[14] = get_interesting_appn; + /* Reset marker processing state */ + reset_marker_reader(cinfo); +} + + +/* + * Control saving of COM and APPn markers into marker_list. + */ + +#ifdef SAVE_MARKERS_SUPPORTED + +GLOBAL(void) +jpeg_save_markers (j_decompress_ptr cinfo, int marker_code, + unsigned int length_limit) +{ + my_marker_ptr marker = (my_marker_ptr) cinfo->marker; + long maxlength; + jpeg_marker_parser_method processor; + + /* Length limit mustn't be larger than what we can allocate + * (should only be a concern in a 16-bit environment). + */ + maxlength = cinfo->mem->max_alloc_chunk - (long)SIZEOF(struct jpeg_marker_struct); + if (((long) length_limit) > maxlength) + length_limit = (unsigned int) maxlength; + + /* Choose processor routine to use. + * APP0/APP14 have special requirements. + */ + if (length_limit) { + processor = save_marker; + /* If saving APP0/APP14, save at least enough for our internal use. */ + if (marker_code == (int) M_APP0 && length_limit < APP0_DATA_LEN) + length_limit = APP0_DATA_LEN; + else if (marker_code == (int) M_APP14 && length_limit < APP14_DATA_LEN) + length_limit = APP14_DATA_LEN; + } else { + processor = skip_variable; + /* If discarding APP0/APP14, use our regular on-the-fly processor. */ + if (marker_code == (int) M_APP0 || marker_code == (int) M_APP14) + processor = get_interesting_appn; + } + + if (marker_code == (int) M_COM) { + marker->process_COM = processor; + marker->length_limit_COM = length_limit; + } else if (marker_code >= (int) M_APP0 && marker_code <= (int) M_APP15) { + marker->process_APPn[marker_code - (int) M_APP0] = processor; + marker->length_limit_APPn[marker_code - (int) M_APP0] = length_limit; + } else + ERREXIT1(cinfo, JERR_UNKNOWN_MARKER, marker_code); +} + +#endif /* SAVE_MARKERS_SUPPORTED */ + + +/* + * Install a special processing method for COM or APPn markers. + */ + +GLOBAL(void) +jpeg_set_marker_processor (j_decompress_ptr cinfo, int marker_code, + jpeg_marker_parser_method routine) +{ + my_marker_ptr marker = (my_marker_ptr) cinfo->marker; + + if (marker_code == (int) M_COM) + marker->process_COM = routine; + else if (marker_code >= (int) M_APP0 && marker_code <= (int) M_APP15) + marker->process_APPn[marker_code - (int) M_APP0] = routine; + else + ERREXIT1(cinfo, JERR_UNKNOWN_MARKER, marker_code); +} diff --git a/dcmjpeg/libijg8/jdmaster.c b/dcmjpeg/libijg8/jdmaster.c new file mode 100644 index 00000000..5b5b15e5 --- /dev/null +++ b/dcmjpeg/libijg8/jdmaster.c @@ -0,0 +1,460 @@ +/* + * jdmaster.c + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains master control logic for the JPEG decompressor. + * These routines are concerned with selecting the modules to be executed + * and with determining the number of passes and the work to be done in each + * pass. + */ + +#define JPEG_INTERNALS +#include "jinclude8.h" +#include "jpeglib8.h" + + +/* Private state */ + +typedef struct { + struct jpeg_decomp_master pub; /* public fields */ + + int pass_number; /* # of passes completed */ + + boolean using_merged_upsample; /* TRUE if using merged upsample/cconvert */ + + /* Saved references to initialized quantizer modules, + * in case we need to switch modes. + */ + struct jpeg_color_quantizer * quantizer_1pass; + struct jpeg_color_quantizer * quantizer_2pass; +} my_decomp_master; + +typedef my_decomp_master * my_master_ptr; + + +/* + * Determine whether merged upsample/color conversion should be used. + * CRUCIAL: this must match the actual capabilities of jdmerge.c! + */ + +LOCAL(boolean) +use_merged_upsample (j_decompress_ptr cinfo) +{ +#ifdef UPSAMPLE_MERGING_SUPPORTED + /* Merging is the equivalent of plain box-filter upsampling */ + if (cinfo->do_fancy_upsampling || cinfo->CCIR601_sampling) + return FALSE; + /* jdmerge.c only supports YCC=>RGB color conversion */ + if (cinfo->jpeg_color_space != JCS_YCbCr || cinfo->num_components != 3 || + cinfo->out_color_space != JCS_RGB || + cinfo->out_color_components != RGB_PIXELSIZE) + return FALSE; + /* and it only handles 2h1v or 2h2v sampling ratios */ + if (cinfo->comp_info[0].h_samp_factor != 2 || + cinfo->comp_info[1].h_samp_factor != 1 || + cinfo->comp_info[2].h_samp_factor != 1 || + cinfo->comp_info[0].v_samp_factor > 2 || + cinfo->comp_info[1].v_samp_factor != 1 || + cinfo->comp_info[2].v_samp_factor != 1) + return FALSE; + /* furthermore, it doesn't work if each component has been + processed differently */ + if (cinfo->comp_info[0].codec_data_unit != cinfo->min_codec_data_unit || + cinfo->comp_info[1].codec_data_unit != cinfo->min_codec_data_unit || + cinfo->comp_info[2].codec_data_unit != cinfo->min_codec_data_unit) + return FALSE; + /* ??? also need to test for upsample-time rescaling, when & if supported */ + return TRUE; /* by golly, it'll work... */ +#else + return FALSE; +#endif +} + + +/* + * Compute output image dimensions and related values. + * NOTE: this is exported for possible use by application. + * Hence it mustn't do anything that can't be done twice. + * Also note that it may be called before the master module is initialized! + */ + +GLOBAL(void) +jpeg_calc_output_dimensions (j_decompress_ptr cinfo) +/* Do computations that are needed before master selection phase */ +{ + /* Prevent application from calling me at wrong times */ + if (cinfo->global_state != DSTATE_READY) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + + (*cinfo->codec->calc_output_dimensions) (cinfo); + + /* Report number of components in selected colorspace. */ + /* Probably this should be in the color conversion module... */ + switch (cinfo->out_color_space) { + case JCS_GRAYSCALE: + cinfo->out_color_components = 1; + break; + case JCS_RGB: +#if RGB_PIXELSIZE != 3 + cinfo->out_color_components = RGB_PIXELSIZE; + break; +#endif /* else share code with YCbCr */ + case JCS_YCbCr: + cinfo->out_color_components = 3; + break; + case JCS_CMYK: + case JCS_YCCK: + cinfo->out_color_components = 4; + break; + default: /* else must be same colorspace as in file */ + cinfo->out_color_components = cinfo->num_components; + break; + } + cinfo->output_components = (cinfo->quantize_colors ? 1 : + cinfo->out_color_components); + + /* See if upsampler will want to emit more than one row at a time */ + if (use_merged_upsample(cinfo)) + cinfo->rec_outbuf_height = cinfo->max_v_samp_factor; + else + cinfo->rec_outbuf_height = 1; +} + + +/* + * Several decompression processes need to range-limit values to the range + * 0..MAXJSAMPLE; the input value may fall somewhat outside this range + * due to noise introduced by quantization, roundoff error, etc. These + * processes are inner loops and need to be as fast as possible. On most + * machines, particularly CPUs with pipelines or instruction prefetch, + * a (subscript-check-less) C table lookup + * x = sample_range_limit[x]; + * is faster than explicit tests + * if (x < 0) x = 0; + * else if (x > MAXJSAMPLE) x = MAXJSAMPLE; + * These processes all use a common table prepared by the routine below. + * + * For most steps we can mathematically guarantee that the initial value + * of x is within MAXJSAMPLE+1 of the legal range, so a table running from + * -(MAXJSAMPLE+1) to 2*MAXJSAMPLE+1 is sufficient. But for the initial + * limiting step (just after the IDCT), a wildly out-of-range value is + * possible if the input data is corrupt. To avoid any chance of indexing + * off the end of memory and getting a bad-pointer trap, we perform the + * post-IDCT limiting thus: + * x = range_limit[x & MASK]; + * where MASK is 2 bits wider than legal sample data, ie 10 bits for 8-bit + * samples. Under normal circumstances this is more than enough range and + * a correct output will be generated; with bogus input data the mask will + * cause wraparound, and we will safely generate a bogus-but-in-range output. + * For the post-IDCT step, we want to convert the data from signed to unsigned + * representation by adding CENTERJSAMPLE at the same time that we limit it. + * So the post-IDCT limiting table ends up looking like this: + * CENTERJSAMPLE,CENTERJSAMPLE+1,...,MAXJSAMPLE, + * MAXJSAMPLE (repeat 2*(MAXJSAMPLE+1)-CENTERJSAMPLE times), + * 0 (repeat 2*(MAXJSAMPLE+1)-CENTERJSAMPLE times), + * 0,1,...,CENTERJSAMPLE-1 + * Negative inputs select values from the upper half of the table after + * masking. + * + * We can save some space by overlapping the start of the post-IDCT table + * with the simpler range limiting table. The post-IDCT table begins at + * sample_range_limit + CENTERJSAMPLE. + * + * Note that the table is allocated in near data space on PCs; it's small + * enough and used often enough to justify this. + */ + +LOCAL(void) +prepare_range_limit_table (j_decompress_ptr cinfo) +/* Allocate and fill in the sample_range_limit table */ +{ + JSAMPLE * table; + int i; + + table = (JSAMPLE *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (5 * (MAXJSAMPLE+1) + CENTERJSAMPLE) * SIZEOF(JSAMPLE)); + table += (MAXJSAMPLE+1); /* allow negative subscripts of simple table */ + cinfo->sample_range_limit = table; + /* First segment of "simple" table: limit[x] = 0 for x < 0 */ + MEMZERO(table - (MAXJSAMPLE+1), (MAXJSAMPLE+1) * SIZEOF(JSAMPLE)); + /* Main part of "simple" table: limit[x] = x */ + for (i = 0; i <= MAXJSAMPLE; i++) + table[i] = (JSAMPLE) i; + table += CENTERJSAMPLE; /* Point to where post-IDCT table starts */ + /* End of simple table, rest of first half of post-IDCT table */ + for (i = CENTERJSAMPLE; i < 2*(MAXJSAMPLE+1); i++) + table[i] = MAXJSAMPLE; + /* Second half of post-IDCT table */ + MEMZERO(table + (2 * (MAXJSAMPLE+1)), + (2 * (MAXJSAMPLE+1) - CENTERJSAMPLE) * SIZEOF(JSAMPLE)); + MEMCOPY(table + (4 * (MAXJSAMPLE+1) - CENTERJSAMPLE), + cinfo->sample_range_limit, CENTERJSAMPLE * SIZEOF(JSAMPLE)); +} + + +/* + * Master selection of decompression modules. + * This is done once at jpeg_start_decompress time. We determine + * which modules will be used and give them appropriate initialization calls. + * We also initialize the decompressor input side to begin consuming data. + * + * Since jpeg_read_header has finished, we know what is in the SOF + * and (first) SOS markers. We also have all the application parameter + * settings. + */ + +LOCAL(void) +master_selection (j_decompress_ptr cinfo) +{ + my_master_ptr master = (my_master_ptr) cinfo->master; + long samplesperrow; + JDIMENSION jd_samplesperrow; + + /* Initialize dimensions and other stuff */ + jpeg_calc_output_dimensions(cinfo); + prepare_range_limit_table(cinfo); + + /* Width of an output scanline must be representable as JDIMENSION. */ + samplesperrow = (long) cinfo->output_width * (long) cinfo->out_color_components; + jd_samplesperrow = (JDIMENSION) samplesperrow; + if ((long) jd_samplesperrow != samplesperrow) + ERREXIT(cinfo, JERR_WIDTH_OVERFLOW); + + /* Initialize my private state */ + master->pass_number = 0; + master->using_merged_upsample = use_merged_upsample(cinfo); + + /* Color quantizer selection */ + master->quantizer_1pass = NULL; + master->quantizer_2pass = NULL; + /* No mode changes if not using buffered-image mode. */ + if (! cinfo->quantize_colors || ! cinfo->buffered_image) { + cinfo->enable_1pass_quant = FALSE; + cinfo->enable_external_quant = FALSE; + cinfo->enable_2pass_quant = FALSE; + } + if (cinfo->quantize_colors) { + if (cinfo->raw_data_out) + ERREXIT(cinfo, JERR_NOTIMPL); + /* 2-pass quantizer only works in 3-component color space. */ + if (cinfo->out_color_components != 3) { + cinfo->enable_1pass_quant = TRUE; + cinfo->enable_external_quant = FALSE; + cinfo->enable_2pass_quant = FALSE; + cinfo->colormap = NULL; + } else if (cinfo->colormap != NULL) { + cinfo->enable_external_quant = TRUE; + } else if (cinfo->two_pass_quantize) { + cinfo->enable_2pass_quant = TRUE; + } else { + cinfo->enable_1pass_quant = TRUE; + } + + if (cinfo->enable_1pass_quant) { +#ifdef QUANT_1PASS_SUPPORTED + jinit_1pass_quantizer(cinfo); + master->quantizer_1pass = cinfo->cquantize; +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } + + /* We use the 2-pass code to map to external colormaps. */ + if (cinfo->enable_2pass_quant || cinfo->enable_external_quant) { +#ifdef QUANT_2PASS_SUPPORTED + jinit_2pass_quantizer(cinfo); + master->quantizer_2pass = cinfo->cquantize; +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } + /* If both quantizers are initialized, the 2-pass one is left active; + * this is necessary for starting with quantization to an external map. + */ + } + + /* Post-processing: in particular, color conversion first */ + if (! cinfo->raw_data_out) { + if (master->using_merged_upsample) { +#ifdef UPSAMPLE_MERGING_SUPPORTED + jinit_merged_upsampler(cinfo); /* does color conversion too */ +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } else { + jinit_color_deconverter(cinfo); + jinit_upsampler(cinfo); + } + jinit_d_post_controller(cinfo, cinfo->enable_2pass_quant); + } + + /* Initialize principal buffer controllers. */ + if (! cinfo->raw_data_out) + jinit_d_main_controller(cinfo, FALSE /* never need full buffer here */); + + /* We can now tell the memory manager to allocate virtual arrays. */ + (*cinfo->mem->realize_virt_arrays) ((j_common_ptr) cinfo); + + /* Initialize input side of decompressor to consume first scan. */ + (*cinfo->inputctl->start_input_pass) (cinfo); + +#ifdef D_MULTISCAN_FILES_SUPPORTED + /* If jpeg_start_decompress will read the whole file, initialize + * progress monitoring appropriately. The input step is counted + * as one pass. + */ + if (cinfo->progress != NULL && ! cinfo->buffered_image && + cinfo->inputctl->has_multiple_scans) { + int nscans; + /* Estimate number of scans to set pass_limit. */ + if (cinfo->process == JPROC_PROGRESSIVE) { + /* Arbitrarily estimate 2 interleaved DC scans + 3 AC scans/component. */ + nscans = 2 + 3 * cinfo->num_components; + } else { + /* For a nonprogressive multiscan file, estimate 1 scan per component. */ + nscans = cinfo->num_components; + } + cinfo->progress->pass_counter = 0L; + cinfo->progress->pass_limit = (long) cinfo->total_iMCU_rows * nscans; + cinfo->progress->completed_passes = 0; + cinfo->progress->total_passes = (cinfo->enable_2pass_quant ? 3 : 2); + /* Count the input pass as done */ + master->pass_number++; + } +#endif /* D_MULTISCAN_FILES_SUPPORTED */ +} + + +/* + * Per-pass setup. + * This is called at the beginning of each output pass. We determine which + * modules will be active during this pass and give them appropriate + * start_pass calls. We also set is_dummy_pass to indicate whether this + * is a "real" output pass or a dummy pass for color quantization. + * (In the latter case, jdapistd.c will crank the pass to completion.) + */ + +METHODDEF(void) +prepare_for_output_pass (j_decompress_ptr cinfo) +{ + my_master_ptr master = (my_master_ptr) cinfo->master; + + if (master->pub.is_dummy_pass) { +#ifdef QUANT_2PASS_SUPPORTED + /* Final pass of 2-pass quantization */ + master->pub.is_dummy_pass = FALSE; + (*cinfo->cquantize->start_pass) (cinfo, FALSE); + (*cinfo->post->start_pass) (cinfo, JBUF_CRANK_DEST); + (*cinfo->main->start_pass) (cinfo, JBUF_CRANK_DEST); +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif /* QUANT_2PASS_SUPPORTED */ + } else { + if (cinfo->quantize_colors && cinfo->colormap == NULL) { + /* Select new quantization method */ + if (cinfo->two_pass_quantize && cinfo->enable_2pass_quant) { + cinfo->cquantize = master->quantizer_2pass; + master->pub.is_dummy_pass = TRUE; + } else if (cinfo->enable_1pass_quant) { + cinfo->cquantize = master->quantizer_1pass; + } else { + ERREXIT(cinfo, JERR_MODE_CHANGE); + } + } + (*cinfo->codec->start_output_pass) (cinfo); + if (! cinfo->raw_data_out) { + if (! master->using_merged_upsample) + (*cinfo->cconvert->start_pass) (cinfo); + (*cinfo->upsample->start_pass) (cinfo); + if (cinfo->quantize_colors) + (*cinfo->cquantize->start_pass) (cinfo, master->pub.is_dummy_pass); + (*cinfo->post->start_pass) (cinfo, + (master->pub.is_dummy_pass ? JBUF_SAVE_AND_PASS : JBUF_PASS_THRU)); + (*cinfo->main->start_pass) (cinfo, JBUF_PASS_THRU); + } + } + + /* Set up progress monitor's pass info if present */ + if (cinfo->progress != NULL) { + cinfo->progress->completed_passes = master->pass_number; + cinfo->progress->total_passes = master->pass_number + + (master->pub.is_dummy_pass ? 2 : 1); + /* In buffered-image mode, we assume one more output pass if EOI not + * yet reached, but no more passes if EOI has been reached. + */ + if (cinfo->buffered_image && ! cinfo->inputctl->eoi_reached) { + cinfo->progress->total_passes += (cinfo->enable_2pass_quant ? 2 : 1); + } + } +} + + +/* + * Finish up at end of an output pass. + */ + +METHODDEF(void) +finish_output_pass (j_decompress_ptr cinfo) +{ + my_master_ptr master = (my_master_ptr) cinfo->master; + + if (cinfo->quantize_colors) + (*cinfo->cquantize->finish_pass) (cinfo); + master->pass_number++; +} + + +#ifdef D_MULTISCAN_FILES_SUPPORTED + +/* + * Switch to a new external colormap between output passes. + */ + +GLOBAL(void) +jpeg_new_colormap (j_decompress_ptr cinfo) +{ + my_master_ptr master = (my_master_ptr) cinfo->master; + + /* Prevent application from calling me at wrong times */ + if (cinfo->global_state != DSTATE_BUFIMAGE) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + + if (cinfo->quantize_colors && cinfo->enable_external_quant && + cinfo->colormap != NULL) { + /* Select 2-pass quantizer for external colormap use */ + cinfo->cquantize = master->quantizer_2pass; + /* Notify quantizer of colormap change */ + (*cinfo->cquantize->new_color_map) (cinfo); + master->pub.is_dummy_pass = FALSE; /* just in case */ + } else + ERREXIT(cinfo, JERR_MODE_CHANGE); +} + +#endif /* D_MULTISCAN_FILES_SUPPORTED */ + + +/* + * Initialize master decompression control and select active modules. + * This is performed at the start of jpeg_start_decompress. + */ + +GLOBAL(void) +jinit_master_decompress (j_decompress_ptr cinfo) +{ + my_master_ptr master; + + master = (my_master_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_decomp_master)); + cinfo->master = (struct jpeg_decomp_master *) master; + master->pub.prepare_for_output_pass = prepare_for_output_pass; + master->pub.finish_output_pass = finish_output_pass; + + master->pub.is_dummy_pass = FALSE; + + master_selection(cinfo); +} diff --git a/dcmjpeg/libijg8/jdmerge.c b/dcmjpeg/libijg8/jdmerge.c new file mode 100644 index 00000000..1a74ca5e --- /dev/null +++ b/dcmjpeg/libijg8/jdmerge.c @@ -0,0 +1,400 @@ +/* + * jdmerge.c + * + * Copyright (C) 1994-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains code for merged upsampling/color conversion. + * + * This file combines functions from jdsample.c and jdcolor.c; + * read those files first to understand what's going on. + * + * When the chroma components are to be upsampled by simple replication + * (ie, box filtering), we can save some work in color conversion by + * calculating all the output pixels corresponding to a pair of chroma + * samples at one time. In the conversion equations + * R = Y + K1 * Cr + * G = Y + K2 * Cb + K3 * Cr + * B = Y + K4 * Cb + * only the Y term varies among the group of pixels corresponding to a pair + * of chroma samples, so the rest of the terms can be calculated just once. + * At typical sampling ratios, this eliminates half or three-quarters of the + * multiplications needed for color conversion. + * + * This file currently provides implementations for the following cases: + * YCbCr => RGB color conversion only. + * Sampling ratios of 2h1v or 2h2v. + * No scaling needed at upsample time. + * Corner-aligned (non-CCIR601) sampling alignment. + * Other special cases could be added, but in most applications these are + * the only common cases. (For uncommon cases we fall back on the more + * general code in jdsample.c and jdcolor.c.) + */ + +#define JPEG_INTERNALS +#include "jinclude8.h" +#include "jpeglib8.h" + +#ifdef UPSAMPLE_MERGING_SUPPORTED + + +/* Private subobject */ + +typedef struct { + struct jpeg_upsampler pub; /* public fields */ + + /* Pointer to routine to do actual upsampling/conversion of one row group */ + JMETHOD(void, upmethod, (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr, + JSAMPARRAY output_buf)); + + /* Private state for YCC->RGB conversion */ + int * Cr_r_tab; /* => table for Cr to R conversion */ + int * Cb_b_tab; /* => table for Cb to B conversion */ + IJG_INT32 * Cr_g_tab; /* => table for Cr to G conversion */ + IJG_INT32 * Cb_g_tab; /* => table for Cb to G conversion */ + + /* For 2:1 vertical sampling, we produce two output rows at a time. + * We need a "spare" row buffer to hold the second output row if the + * application provides just a one-row buffer; we also use the spare + * to discard the dummy last row if the image height is odd. + */ + JSAMPROW spare_row; + boolean spare_full; /* T if spare buffer is occupied */ + + JDIMENSION out_row_width; /* samples per output row */ + JDIMENSION rows_to_go; /* counts rows remaining in image */ +} my_upsampler; + +typedef my_upsampler * my_upsample_ptr; + +#define SCALEBITS 16 /* speediest right-shift on some machines */ +#define ONE_HALF ((IJG_INT32) 1 << (SCALEBITS-1)) +#define FIX(x) ((IJG_INT32) ((x) * (1L<RGB colorspace conversion. + * This is taken directly from jdcolor.c; see that file for more info. + */ + +LOCAL(void) +build_ycc_rgb_table (j_decompress_ptr cinfo) +{ + my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; + int i; + IJG_INT32 x; + SHIFT_TEMPS + + upsample->Cr_r_tab = (int *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (MAXJSAMPLE+1) * SIZEOF(int)); + upsample->Cb_b_tab = (int *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (MAXJSAMPLE+1) * SIZEOF(int)); + upsample->Cr_g_tab = (IJG_INT32 *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (MAXJSAMPLE+1) * SIZEOF(IJG_INT32)); + upsample->Cb_g_tab = (IJG_INT32 *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (MAXJSAMPLE+1) * SIZEOF(IJG_INT32)); + + for (i = 0, x = -CENTERJSAMPLE; i <= MAXJSAMPLE; i++, x++) { + /* i is the actual input pixel value, in the range 0..MAXJSAMPLE */ + /* The Cb or Cr value we are thinking of is x = i - CENTERJSAMPLE */ + /* Cr=>R value is nearest int to 1.40200 * x */ + upsample->Cr_r_tab[i] = (int) + RIGHT_SHIFT(FIX(1.40200) * x + ONE_HALF, SCALEBITS); + /* Cb=>B value is nearest int to 1.77200 * x */ + upsample->Cb_b_tab[i] = (int) + RIGHT_SHIFT(FIX(1.77200) * x + ONE_HALF, SCALEBITS); + /* Cr=>G value is scaled-up -0.71414 * x */ + upsample->Cr_g_tab[i] = (- FIX(0.71414)) * x; + /* Cb=>G value is scaled-up -0.34414 * x */ + /* We also add in ONE_HALF so that need not do it in inner loop */ + upsample->Cb_g_tab[i] = (- FIX(0.34414)) * x + ONE_HALF; + } +} + + +/* + * Initialize for an upsampling pass. + */ + +METHODDEF(void) +start_pass_merged_upsample (j_decompress_ptr cinfo) +{ + my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; + + /* Mark the spare buffer empty */ + upsample->spare_full = FALSE; + /* Initialize total-height counter for detecting bottom of image */ + upsample->rows_to_go = cinfo->output_height; +} + + +/* + * Control routine to do upsampling (and color conversion). + * + * The control routine just handles the row buffering considerations. + */ + +METHODDEF(void) +merged_2v_upsample (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail) +/* 2:1 vertical sampling case: may need a spare row. */ +{ + my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; + JSAMPROW work_ptrs[2]; + JDIMENSION num_rows; /* number of rows returned to caller */ + + if (upsample->spare_full) { + /* If we have a spare row saved from a previous cycle, just return it. */ + jcopy_sample_rows(& upsample->spare_row, 0, output_buf + *out_row_ctr, 0, + 1, upsample->out_row_width); + num_rows = 1; + upsample->spare_full = FALSE; + } else { + /* Figure number of rows to return to caller. */ + num_rows = 2; + /* Not more than the distance to the end of the image. */ + if (num_rows > upsample->rows_to_go) + num_rows = upsample->rows_to_go; + /* And not more than what the client can accept: */ + out_rows_avail -= *out_row_ctr; + if (num_rows > out_rows_avail) + num_rows = out_rows_avail; + /* Create output pointer array for upsampler. */ + work_ptrs[0] = output_buf[*out_row_ctr]; + if (num_rows > 1) { + work_ptrs[1] = output_buf[*out_row_ctr + 1]; + } else { + work_ptrs[1] = upsample->spare_row; + upsample->spare_full = TRUE; + } + /* Now do the upsampling. */ + (*upsample->upmethod) (cinfo, input_buf, *in_row_group_ctr, work_ptrs); + } + + /* Adjust counts */ + *out_row_ctr += num_rows; + upsample->rows_to_go -= num_rows; + /* When the buffer is emptied, declare this input row group consumed */ + if (! upsample->spare_full) + (*in_row_group_ctr)++; +} + + +METHODDEF(void) +merged_1v_upsample (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail) +/* 1:1 vertical sampling case: much easier, never need a spare row. */ +{ + my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; + + /* Just do the upsampling. */ + (*upsample->upmethod) (cinfo, input_buf, *in_row_group_ctr, + output_buf + *out_row_ctr); + /* Adjust counts */ + (*out_row_ctr)++; + (*in_row_group_ctr)++; +} + + +/* + * These are the routines invoked by the control routines to do + * the actual upsampling/conversion. One row group is processed per call. + * + * Note: since we may be writing directly into application-supplied buffers, + * we have to be honest about the output width; we can't assume the buffer + * has been rounded up to an even width. + */ + + +/* + * Upsample and color convert for the case of 2:1 horizontal and 1:1 vertical. + */ + +METHODDEF(void) +h2v1_merged_upsample (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr, + JSAMPARRAY output_buf) +{ + my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; + register int y, cred, cgreen, cblue; + int cb, cr; + register JSAMPROW outptr; + JSAMPROW inptr0, inptr1, inptr2; + JDIMENSION col; + /* copy these pointers into registers if possible */ + register JSAMPLE * range_limit = cinfo->sample_range_limit; + int * Crrtab = upsample->Cr_r_tab; + int * Cbbtab = upsample->Cb_b_tab; + IJG_INT32 * Crgtab = upsample->Cr_g_tab; + IJG_INT32 * Cbgtab = upsample->Cb_g_tab; + SHIFT_TEMPS + + inptr0 = input_buf[0][in_row_group_ctr]; + inptr1 = input_buf[1][in_row_group_ctr]; + inptr2 = input_buf[2][in_row_group_ctr]; + outptr = output_buf[0]; + /* Loop for each pair of output pixels */ + for (col = cinfo->output_width >> 1; col > 0; col--) { + /* Do the chroma part of the calculation */ + cb = GETJSAMPLE(*inptr1++); + cr = GETJSAMPLE(*inptr2++); + cred = Crrtab[cr]; + cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS); + cblue = Cbbtab[cb]; + /* Fetch 2 Y values and emit 2 pixels */ + y = GETJSAMPLE(*inptr0++); + outptr[RGB_RED] = range_limit[y + cred]; + outptr[RGB_GREEN] = range_limit[y + cgreen]; + outptr[RGB_BLUE] = range_limit[y + cblue]; + outptr += RGB_PIXELSIZE; + y = GETJSAMPLE(*inptr0++); + outptr[RGB_RED] = range_limit[y + cred]; + outptr[RGB_GREEN] = range_limit[y + cgreen]; + outptr[RGB_BLUE] = range_limit[y + cblue]; + outptr += RGB_PIXELSIZE; + } + /* If image width is odd, do the last output column separately */ + if (cinfo->output_width & 1) { + cb = GETJSAMPLE(*inptr1); + cr = GETJSAMPLE(*inptr2); + cred = Crrtab[cr]; + cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS); + cblue = Cbbtab[cb]; + y = GETJSAMPLE(*inptr0); + outptr[RGB_RED] = range_limit[y + cred]; + outptr[RGB_GREEN] = range_limit[y + cgreen]; + outptr[RGB_BLUE] = range_limit[y + cblue]; + } +} + + +/* + * Upsample and color convert for the case of 2:1 horizontal and 2:1 vertical. + */ + +METHODDEF(void) +h2v2_merged_upsample (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr, + JSAMPARRAY output_buf) +{ + my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; + register int y, cred, cgreen, cblue; + int cb, cr; + register JSAMPROW outptr0, outptr1; + JSAMPROW inptr00, inptr01, inptr1, inptr2; + JDIMENSION col; + /* copy these pointers into registers if possible */ + register JSAMPLE * range_limit = cinfo->sample_range_limit; + int * Crrtab = upsample->Cr_r_tab; + int * Cbbtab = upsample->Cb_b_tab; + IJG_INT32 * Crgtab = upsample->Cr_g_tab; + IJG_INT32 * Cbgtab = upsample->Cb_g_tab; + SHIFT_TEMPS + + inptr00 = input_buf[0][in_row_group_ctr*2]; + inptr01 = input_buf[0][in_row_group_ctr*2 + 1]; + inptr1 = input_buf[1][in_row_group_ctr]; + inptr2 = input_buf[2][in_row_group_ctr]; + outptr0 = output_buf[0]; + outptr1 = output_buf[1]; + /* Loop for each group of output pixels */ + for (col = cinfo->output_width >> 1; col > 0; col--) { + /* Do the chroma part of the calculation */ + cb = GETJSAMPLE(*inptr1++); + cr = GETJSAMPLE(*inptr2++); + cred = Crrtab[cr]; + cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS); + cblue = Cbbtab[cb]; + /* Fetch 4 Y values and emit 4 pixels */ + y = GETJSAMPLE(*inptr00++); + outptr0[RGB_RED] = range_limit[y + cred]; + outptr0[RGB_GREEN] = range_limit[y + cgreen]; + outptr0[RGB_BLUE] = range_limit[y + cblue]; + outptr0 += RGB_PIXELSIZE; + y = GETJSAMPLE(*inptr00++); + outptr0[RGB_RED] = range_limit[y + cred]; + outptr0[RGB_GREEN] = range_limit[y + cgreen]; + outptr0[RGB_BLUE] = range_limit[y + cblue]; + outptr0 += RGB_PIXELSIZE; + y = GETJSAMPLE(*inptr01++); + outptr1[RGB_RED] = range_limit[y + cred]; + outptr1[RGB_GREEN] = range_limit[y + cgreen]; + outptr1[RGB_BLUE] = range_limit[y + cblue]; + outptr1 += RGB_PIXELSIZE; + y = GETJSAMPLE(*inptr01++); + outptr1[RGB_RED] = range_limit[y + cred]; + outptr1[RGB_GREEN] = range_limit[y + cgreen]; + outptr1[RGB_BLUE] = range_limit[y + cblue]; + outptr1 += RGB_PIXELSIZE; + } + /* If image width is odd, do the last output column separately */ + if (cinfo->output_width & 1) { + cb = GETJSAMPLE(*inptr1); + cr = GETJSAMPLE(*inptr2); + cred = Crrtab[cr]; + cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS); + cblue = Cbbtab[cb]; + y = GETJSAMPLE(*inptr00); + outptr0[RGB_RED] = range_limit[y + cred]; + outptr0[RGB_GREEN] = range_limit[y + cgreen]; + outptr0[RGB_BLUE] = range_limit[y + cblue]; + y = GETJSAMPLE(*inptr01); + outptr1[RGB_RED] = range_limit[y + cred]; + outptr1[RGB_GREEN] = range_limit[y + cgreen]; + outptr1[RGB_BLUE] = range_limit[y + cblue]; + } +} + + +/* + * Module initialization routine for merged upsampling/color conversion. + * + * NB: this is called under the conditions determined by use_merged_upsample() + * in jdmaster.c. That routine MUST correspond to the actual capabilities + * of this module; no safety checks are made here. + */ + +GLOBAL(void) +jinit_merged_upsampler (j_decompress_ptr cinfo) +{ + my_upsample_ptr upsample; + + upsample = (my_upsample_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_upsampler)); + cinfo->upsample = (struct jpeg_upsampler *) upsample; + upsample->pub.start_pass = start_pass_merged_upsample; + upsample->pub.need_context_rows = FALSE; + + upsample->out_row_width = cinfo->output_width * (JDIMENSION)cinfo->out_color_components; + + if (cinfo->max_v_samp_factor == 2) { + upsample->pub.upsample = merged_2v_upsample; + upsample->upmethod = h2v2_merged_upsample; + /* Allocate a spare row buffer */ + upsample->spare_row = (JSAMPROW) + (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (size_t) (upsample->out_row_width * SIZEOF(JSAMPLE))); + } else { + upsample->pub.upsample = merged_1v_upsample; + upsample->upmethod = h2v1_merged_upsample; + /* No spare row needed */ + upsample->spare_row = NULL; + } + + build_ycc_rgb_table(cinfo); +} + +#endif /* UPSAMPLE_MERGING_SUPPORTED */ diff --git a/dcmjpeg/libijg8/jdphuff.c b/dcmjpeg/libijg8/jdphuff.c new file mode 100644 index 00000000..3f0cf165 --- /dev/null +++ b/dcmjpeg/libijg8/jdphuff.c @@ -0,0 +1,675 @@ +/* + * jdphuff.c + * + * Copyright (C) 1995-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains Huffman entropy decoding routines for progressive JPEG. + * + * Much of the complexity here has to do with supporting input suspension. + * If the data source module demands suspension, we want to be able to back + * up to the start of the current MCU. To do this, we copy state variables + * into local working storage, and update them back to the permanent + * storage only upon successful completion of an MCU. + */ + +#define JPEG_INTERNALS +#include "jinclude8.h" +#include "jpeglib8.h" +#include "jlossy8.h" /* Private declarations for lossy subsystem */ +#include "jdhuff8.h" /* Declarations shared with jd*huff.c */ + + +#ifdef D_PROGRESSIVE_SUPPORTED + +/* + * Private entropy decoder object for progressive Huffman decoding. + * + * The savable_state subrecord contains fields that change within an MCU, + * but must not be updated permanently until we complete the MCU. + */ + +typedef struct { + unsigned int EOBRUN; /* remaining EOBs in EOBRUN */ + int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */ +} savable_state; + +/* This macro is to work around compilers with missing or broken + * structure assignment. You'll need to fix this code if you have + * such a compiler and you change MAX_COMPS_IN_SCAN. + */ + +#ifndef NO_STRUCT_ASSIGN +#define ASSIGN_STATE(dest,src) ((dest) = (src)) +#else +#if MAX_COMPS_IN_SCAN == 4 +#define ASSIGN_STATE(dest,src) \ + ((dest).EOBRUN = (src).EOBRUN, \ + (dest).last_dc_val[0] = (src).last_dc_val[0], \ + (dest).last_dc_val[1] = (src).last_dc_val[1], \ + (dest).last_dc_val[2] = (src).last_dc_val[2], \ + (dest).last_dc_val[3] = (src).last_dc_val[3]) +#endif +#endif + + +typedef struct { + huffd_common_fields; /* Fields shared with other entropy decoders */ + + /* These fields are loaded into local variables at start of each MCU. + * In case of suspension, we exit WITHOUT updating them. + */ + savable_state saved; /* Other state at start of MCU */ + + /* These fields are NOT loaded into local working state. */ + unsigned int restarts_to_go; /* MCUs left in this restart interval */ + + /* Pointers to derived tables (these workspaces have image lifespan) */ + d_derived_tbl * derived_tbls[NUM_HUFF_TBLS]; + + d_derived_tbl * ac_derived_tbl; /* active table during an AC scan */ +} phuff_entropy_decoder; + +typedef phuff_entropy_decoder * phuff_entropy_ptr; + +/* Forward declarations */ +METHODDEF(boolean) decode_mcu_DC_first JPP((j_decompress_ptr cinfo, + JBLOCKROW *MCU_data)); +METHODDEF(boolean) decode_mcu_AC_first JPP((j_decompress_ptr cinfo, + JBLOCKROW *MCU_data)); +METHODDEF(boolean) decode_mcu_DC_refine JPP((j_decompress_ptr cinfo, + JBLOCKROW *MCU_data)); +METHODDEF(boolean) decode_mcu_AC_refine JPP((j_decompress_ptr cinfo, + JBLOCKROW *MCU_data)); + + +/* + * Initialize for a Huffman-compressed scan. + */ + +METHODDEF(void) +start_pass_phuff_decoder (j_decompress_ptr cinfo) +{ + j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec; + phuff_entropy_ptr entropy = (phuff_entropy_ptr) lossyd->entropy_private; + boolean is_DC_band, bad; + int ci, coefi, tbl; + int *coef_bit_ptr; + jpeg_component_info * compptr; + + is_DC_band = (cinfo->Ss == 0); + + /* Validate scan parameters */ + bad = FALSE; + if (is_DC_band) { + if (cinfo->Se != 0) + bad = TRUE; + } else { + /* need not check Ss/Se < 0 since they came from unsigned bytes */ + if (cinfo->Ss > cinfo->Se || cinfo->Se >= DCTSIZE2) + bad = TRUE; + /* AC scans may have only one component */ + if (cinfo->comps_in_scan != 1) + bad = TRUE; + } + if (cinfo->Ah != 0) { + /* Successive approximation refinement scan: must have Al = Ah-1. */ + if (cinfo->Al != cinfo->Ah-1) + bad = TRUE; + } + if (cinfo->Al > 13) /* need not check for < 0 */ + bad = TRUE; + /* Arguably the maximum Al value should be less than 13 for 8-bit precision, + * but the spec doesn't say so, and we try to be liberal about what we + * accept. Note: large Al values could result in out-of-range DC + * coefficients during early scans, leading to bizarre displays due to + * overflows in the IDCT math. But we won't crash. + */ + if (bad) + ERREXIT4(cinfo, JERR_BAD_PROGRESSION, + cinfo->Ss, cinfo->Se, cinfo->Ah, cinfo->Al); + /* Update progression status, and verify that scan order is legal. + * Note that inter-scan inconsistencies are treated as warnings + * not fatal errors ... not clear if this is right way to behave. + */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + int cindex = cinfo->cur_comp_info[ci]->component_index; + coef_bit_ptr = & cinfo->coef_bits[cindex][0]; + if (!is_DC_band && coef_bit_ptr[0] < 0) /* AC without prior DC scan */ + WARNMS2(cinfo, JWRN_BOGUS_PROGRESSION, cindex, 0); + for (coefi = cinfo->Ss; coefi <= cinfo->Se; coefi++) { + int expected = (coef_bit_ptr[coefi] < 0) ? 0 : coef_bit_ptr[coefi]; + if (cinfo->Ah != expected) + WARNMS2(cinfo, JWRN_BOGUS_PROGRESSION, cindex, coefi); + coef_bit_ptr[coefi] = cinfo->Al; + } + } + + /* Select MCU decoding routine */ + if (cinfo->Ah == 0) { + if (is_DC_band) + lossyd->entropy_decode_mcu = decode_mcu_DC_first; + else + lossyd->entropy_decode_mcu = decode_mcu_AC_first; + } else { + if (is_DC_band) + lossyd->entropy_decode_mcu = decode_mcu_DC_refine; + else + lossyd->entropy_decode_mcu = decode_mcu_AC_refine; + } + + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + /* Make sure requested tables are present, and compute derived tables. + * We may build same derived table more than once, but it's not expensive. + */ + if (is_DC_band) { + if (cinfo->Ah == 0) { /* DC refinement needs no table */ + tbl = compptr->dc_tbl_no; + jpeg_make_d_derived_tbl(cinfo, TRUE, tbl, + & entropy->derived_tbls[tbl]); + } + } else { + tbl = compptr->ac_tbl_no; + jpeg_make_d_derived_tbl(cinfo, FALSE, tbl, + & entropy->derived_tbls[tbl]); + /* remember the single active table */ + entropy->ac_derived_tbl = entropy->derived_tbls[tbl]; + } + /* Initialize DC predictions to 0 */ + entropy->saved.last_dc_val[ci] = 0; + } + + /* Initialize bitread state variables */ + entropy->bitstate.bits_left = 0; + entropy->bitstate.get_buffer = 0; /* unnecessary, but keeps Purify quiet */ + entropy->insufficient_data = FALSE; + + /* Initialize private state variables */ + entropy->saved.EOBRUN = 0; + + /* Initialize restart counter */ + entropy->restarts_to_go = cinfo->restart_interval; +} + + +/* + * Figure F.12: extend sign bit. + * On some machines, a shift and add will be faster than a table lookup. + */ + +#ifdef AVOID_TABLES + +#define HUFF_EXTEND(x,s) ((x) < (1<<((s)-1)) ? (x) + (((-1)<<(s)) + 1) : (x)) + +#else + +#define HUFF_EXTEND(x,s) ((x) < extend_test[s] ? (x) + extend_offset[s] : (x)) + +static const int extend_test[16] = /* entry n is 2**(n-1) */ + { 0, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080, + 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000 }; + +static const int extend_offset[16] = /* entry n is (-1 << n) + 1 */ + { 0, ((-1)<<1) + 1, ((-1)<<2) + 1, ((-1)<<3) + 1, ((-1)<<4) + 1, + ((-1)<<5) + 1, ((-1)<<6) + 1, ((-1)<<7) + 1, ((-1)<<8) + 1, + ((-1)<<9) + 1, ((-1)<<10) + 1, ((-1)<<11) + 1, ((-1)<<12) + 1, + ((-1)<<13) + 1, ((-1)<<14) + 1, ((-1)<<15) + 1 }; + +#endif /* AVOID_TABLES */ + + +/* + * Check for a restart marker & resynchronize decoder. + * Returns FALSE if must suspend. + */ + +LOCAL(boolean) +process_restart (j_decompress_ptr cinfo) +{ + j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec; + phuff_entropy_ptr entropy = (phuff_entropy_ptr) lossyd->entropy_private; + int ci; + + /* Throw away any unused bits remaining in bit buffer; */ + /* include any full bytes in next_marker's count of discarded bytes */ + cinfo->marker->discarded_bytes += (unsigned int)(entropy->bitstate.bits_left / 8); + entropy->bitstate.bits_left = 0; + + /* Advance past the RSTn marker */ + if (! (*cinfo->marker->read_restart_marker) (cinfo)) + return FALSE; + + /* Re-initialize DC predictions to 0 */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) + entropy->saved.last_dc_val[ci] = 0; + /* Re-init EOB run count, too */ + entropy->saved.EOBRUN = 0; + + /* Reset restart counter */ + entropy->restarts_to_go = cinfo->restart_interval; + + /* Reset out-of-data flag, unless read_restart_marker left us smack up + * against a marker. In that case we will end up treating the next data + * segment as empty, and we can avoid producing bogus output pixels by + * leaving the flag set. + */ + if (cinfo->unread_marker == 0) + entropy->insufficient_data = FALSE; + + return TRUE; +} + + +/* + * Huffman MCU decoding. + * Each of these routines decodes and returns one MCU's worth of + * Huffman-compressed coefficients. + * The coefficients are reordered from zigzag order into natural array order, + * but are not dequantized. + * + * The i'th block of the MCU is stored into the block pointed to by + * MCU_data[i]. WE ASSUME THIS AREA IS INITIALLY ZEROED BY THE CALLER. + * + * We return FALSE if data source requested suspension. In that case no + * changes have been made to permanent state. (Exception: some output + * coefficients may already have been assigned. This is harmless for + * spectral selection, since we'll just re-assign them on the next call. + * Successive approximation AC refinement has to be more careful, however.) + */ + +/* + * MCU decoding for DC initial scan (either spectral selection, + * or first pass of successive approximation). + */ + +METHODDEF(boolean) +decode_mcu_DC_first (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) +{ + j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec; + phuff_entropy_ptr entropy = (phuff_entropy_ptr) lossyd->entropy_private; + int Al = cinfo->Al; + register int s, r; + int blkn, ci; + JBLOCKROW block; + BITREAD_STATE_VARS; + savable_state state; + d_derived_tbl * tbl; + jpeg_component_info * compptr; + + /* Process restart marker if needed; may have to suspend */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) + if (! process_restart(cinfo)) + return FALSE; + } + + /* If we've run out of data, just leave the MCU set to zeroes. + * This way, we return uniform gray for the remainder of the segment. + */ + if (! entropy->insufficient_data) { + + /* Load up working state */ + BITREAD_LOAD_STATE(cinfo,entropy->bitstate); + ASSIGN_STATE(state, entropy->saved); + + /* Outer loop handles each block in the MCU */ + + for (blkn = 0; blkn < cinfo->data_units_in_MCU; blkn++) { + block = MCU_data[blkn]; + ci = cinfo->MCU_membership[blkn]; + compptr = cinfo->cur_comp_info[ci]; + tbl = entropy->derived_tbls[compptr->dc_tbl_no]; + + /* Decode a single block's worth of coefficients */ + + /* Section F.2.2.1: decode the DC coefficient difference */ + HUFF_DECODE(s, br_state, tbl, return FALSE, label1); + if (s) { + CHECK_BIT_BUFFER(br_state, s, return FALSE); + r = GET_BITS(s); + s = HUFF_EXTEND(r, s); + } + + /* Convert DC difference to actual value, update last_dc_val */ + s += state.last_dc_val[ci]; + state.last_dc_val[ci] = s; + /* Scale and output the coefficient (assumes jpeg_natural_order[0]=0) */ + (*block)[0] = (JCOEF) (s << Al); + } + + /* Completed MCU, so update state */ + BITREAD_SAVE_STATE(cinfo,entropy->bitstate); + ASSIGN_STATE(entropy->saved, state); + } + + /* Account for restart interval (no-op if not using restarts) */ + entropy->restarts_to_go--; + + return TRUE; +} + + +/* + * MCU decoding for AC initial scan (either spectral selection, + * or first pass of successive approximation). + */ + +METHODDEF(boolean) +decode_mcu_AC_first (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) +{ + j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec; + phuff_entropy_ptr entropy = (phuff_entropy_ptr) lossyd->entropy_private; + int Se = cinfo->Se; + int Al = cinfo->Al; + register int s, k, r; + unsigned int EOBRUN; + JBLOCKROW block; + BITREAD_STATE_VARS; + d_derived_tbl * tbl; + + /* Process restart marker if needed; may have to suspend */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) + if (! process_restart(cinfo)) + return FALSE; + } + + /* If we've run out of data, just leave the MCU set to zeroes. + * This way, we return uniform gray for the remainder of the segment. + */ + if (! entropy->insufficient_data) { + + /* Load up working state. + * We can avoid loading/saving bitread state if in an EOB run. + */ + EOBRUN = entropy->saved.EOBRUN; /* only part of saved state we need */ + + /* There is always only one block per MCU */ + + if (EOBRUN > 0) /* if it's a band of zeroes... */ + EOBRUN--; /* ...process it now (we do nothing) */ + else { + BITREAD_LOAD_STATE(cinfo,entropy->bitstate); + block = MCU_data[0]; + tbl = entropy->ac_derived_tbl; + + for (k = cinfo->Ss; k <= Se; k++) { + HUFF_DECODE(s, br_state, tbl, return FALSE, label2); + r = s >> 4; + s &= 15; + if (s) { + k += r; + CHECK_BIT_BUFFER(br_state, s, return FALSE); + r = GET_BITS(s); + s = HUFF_EXTEND(r, s); + /* Scale and output coefficient in natural (dezigzagged) order */ + (*block)[jpeg_natural_order[k]] = (JCOEF) (s << Al); + } else { + if (r == 15) { /* ZRL */ + k += 15; /* skip 15 zeroes in band */ + } else { /* EOBr, run length is 2^r + appended bits */ + EOBRUN = (unsigned int)(1 << r); + if (r) { /* EOBr, r > 0 */ + CHECK_BIT_BUFFER(br_state, r, return FALSE); + r = GET_BITS(r); + EOBRUN += (unsigned int)r; + } + EOBRUN--; /* this band is processed at this moment */ + break; /* force end-of-band */ + } + } + } + + BITREAD_SAVE_STATE(cinfo,entropy->bitstate); + } + + /* Completed MCU, so update state */ + entropy->saved.EOBRUN = EOBRUN; /* only part of saved state we need */ + } + + /* Account for restart interval (no-op if not using restarts) */ + entropy->restarts_to_go--; + + return TRUE; +} + + +/* + * MCU decoding for DC successive approximation refinement scan. + * Note: we assume such scans can be multi-component, although the spec + * is not very clear on the point. + */ + +METHODDEF(boolean) +decode_mcu_DC_refine (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) +{ + j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec; + phuff_entropy_ptr entropy = (phuff_entropy_ptr) lossyd->entropy_private; + int p1 = 1 << cinfo->Al; /* 1 in the bit position being coded */ + int blkn; + JBLOCKROW block; + BITREAD_STATE_VARS; + + /* Process restart marker if needed; may have to suspend */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) + if (! process_restart(cinfo)) + return FALSE; + } + + /* Not worth the cycles to check insufficient_data here, + * since we will not change the data anyway if we read zeroes. + */ + + /* Load up working state */ + BITREAD_LOAD_STATE(cinfo,entropy->bitstate); + + /* Outer loop handles each block in the MCU */ + + for (blkn = 0; blkn < cinfo->data_units_in_MCU; blkn++) { + block = MCU_data[blkn]; + + /* Encoded data is simply the next bit of the two's-complement DC value */ + CHECK_BIT_BUFFER(br_state, 1, return FALSE); + if (GET_BITS(1)) + (*block)[0] |= (JCOEF)p1; + /* Note: since we use |=, repeating the assignment later is safe */ + } + + /* Completed MCU, so update state */ + BITREAD_SAVE_STATE(cinfo,entropy->bitstate); + + /* Account for restart interval (no-op if not using restarts) */ + entropy->restarts_to_go--; + + return TRUE; +} + + +/* + * MCU decoding for AC successive approximation refinement scan. + */ + +METHODDEF(boolean) +decode_mcu_AC_refine (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) +{ + j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec; + phuff_entropy_ptr entropy = (phuff_entropy_ptr) lossyd->entropy_private; + int Se = cinfo->Se; + int p1 = 1 << cinfo->Al; /* 1 in the bit position being coded */ + int m1 = (-1) << cinfo->Al; /* -1 in the bit position being coded */ + register int s, k, r; + unsigned int EOBRUN; + JBLOCKROW block; + JCOEFPTR thiscoef; + BITREAD_STATE_VARS; + d_derived_tbl * tbl; + int num_newnz; + int newnz_pos[DCTSIZE2]; + + /* Process restart marker if needed; may have to suspend */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) + if (! process_restart(cinfo)) + return FALSE; + } + + /* If we've run out of data, don't modify the MCU. + */ + if (! entropy->insufficient_data) { + + /* Load up working state */ + BITREAD_LOAD_STATE(cinfo,entropy->bitstate); + EOBRUN = entropy->saved.EOBRUN; /* only part of saved state we need */ + + /* There is always only one block per MCU */ + block = MCU_data[0]; + tbl = entropy->ac_derived_tbl; + + /* If we are forced to suspend, we must undo the assignments to any newly + * nonzero coefficients in the block, because otherwise we'd get confused + * next time about which coefficients were already nonzero. + * But we need not undo addition of bits to already-nonzero coefficients; + * instead, we can test the current bit to see if we already did it. + */ + num_newnz = 0; + + /* initialize coefficient loop counter to start of band */ + k = cinfo->Ss; + + if (EOBRUN == 0) { + for (; k <= Se; k++) { + HUFF_DECODE(s, br_state, tbl, goto undoit, label3); + r = s >> 4; + s &= 15; + if (s) { + if (s != 1) /* size of new coef should always be 1 */ + WARNMS(cinfo, JWRN_HUFF_BAD_CODE); + CHECK_BIT_BUFFER(br_state, 1, goto undoit); + if (GET_BITS(1)) + s = p1; /* newly nonzero coef is positive */ + else + s = m1; /* newly nonzero coef is negative */ + } else { + if (r != 15) { + EOBRUN = (unsigned int)(1 << r); /* EOBr, run length is 2^r + appended bits */ + if (r) { + CHECK_BIT_BUFFER(br_state, r, goto undoit); + r = GET_BITS(r); + EOBRUN += (unsigned int)r; + } + break; /* rest of block is handled by EOB logic */ + } + /* note s = 0 for processing ZRL */ + } + /* Advance over already-nonzero coefs and r still-zero coefs, + * appending correction bits to the nonzeroes. A correction bit is 1 + * if the absolute value of the coefficient must be increased. + */ + do { + thiscoef = *block + jpeg_natural_order[k]; + if (*thiscoef != 0) { + CHECK_BIT_BUFFER(br_state, 1, goto undoit); + if (GET_BITS(1)) { + if ((*thiscoef & p1) == 0) { /* do nothing if already set it */ + if (*thiscoef >= 0) + *thiscoef = (JCOEF)(*thiscoef + p1); + else + *thiscoef = (JCOEF)(*thiscoef + m1); + } + } + } else { + if (--r < 0) + break; /* reached target zero coefficient */ + } + k++; + } while (k <= Se); + if (s) { + int pos = jpeg_natural_order[k]; + /* Output newly nonzero coefficient */ + (*block)[pos] = (JCOEF) s; + /* Remember its position in case we have to suspend */ + newnz_pos[num_newnz++] = pos; + } + } + } + + if (EOBRUN > 0) { + /* Scan any remaining coefficient positions after the end-of-band + * (the last newly nonzero coefficient, if any). Append a correction + * bit to each already-nonzero coefficient. A correction bit is 1 + * if the absolute value of the coefficient must be increased. + */ + for (; k <= Se; k++) { + thiscoef = *block + jpeg_natural_order[k]; + if (*thiscoef != 0) { + CHECK_BIT_BUFFER(br_state, 1, goto undoit); + if (GET_BITS(1)) { + if ((*thiscoef & p1) == 0) { /* do nothing if already changed it */ + if (*thiscoef >= 0) + *thiscoef = (JCOEF)(*thiscoef + p1); + else + *thiscoef = (JCOEF)(*thiscoef + m1); + } + } + } + } + /* Count one block completed in EOB run */ + EOBRUN--; + } + + /* Completed MCU, so update state */ + BITREAD_SAVE_STATE(cinfo,entropy->bitstate); + entropy->saved.EOBRUN = EOBRUN; /* only part of saved state we need */ + } + + /* Account for restart interval (no-op if not using restarts) */ + entropy->restarts_to_go--; + + return TRUE; + +undoit: + /* Re-zero any output coefficients that we made newly nonzero */ + while (num_newnz > 0) + (*block)[newnz_pos[--num_newnz]] = 0; + + return FALSE; +} + + +/* + * Module initialization routine for progressive Huffman entropy decoding. + */ + +GLOBAL(void) +jinit_phuff_decoder (j_decompress_ptr cinfo) +{ + j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec; + phuff_entropy_ptr entropy; + int *coef_bit_ptr; + int ci, i; + + entropy = (phuff_entropy_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(phuff_entropy_decoder)); + lossyd->entropy_private = (void *) entropy; + lossyd->entropy_start_pass = start_pass_phuff_decoder; + + /* Mark derived tables unallocated */ + for (i = 0; i < NUM_HUFF_TBLS; i++) { + entropy->derived_tbls[i] = NULL; + } + + /* Create progression status table */ + cinfo->coef_bits = (int (*)[DCTSIZE2]) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (size_t)cinfo->num_components*DCTSIZE2*SIZEOF(int)); + coef_bit_ptr = & cinfo->coef_bits[0][0]; + for (ci = 0; ci < cinfo->num_components; ci++) + for (i = 0; i < DCTSIZE2; i++) + *coef_bit_ptr++ = -1; +} + +#endif /* D_PROGRESSIVE_SUPPORTED */ diff --git a/dcmjpeg/libijg8/jdpostct.c b/dcmjpeg/libijg8/jdpostct.c new file mode 100644 index 00000000..2804cbb1 --- /dev/null +++ b/dcmjpeg/libijg8/jdpostct.c @@ -0,0 +1,290 @@ +/* + * jdpostct.c + * + * Copyright (C) 1994-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains the decompression postprocessing controller. + * This controller manages the upsampling, color conversion, and color + * quantization/reduction steps; specifically, it controls the buffering + * between upsample/color conversion and color quantization/reduction. + * + * If no color quantization/reduction is required, then this module has no + * work to do, and it just hands off to the upsample/color conversion code. + * An integrated upsample/convert/quantize process would replace this module + * entirely. + */ + +#define JPEG_INTERNALS +#include "jinclude8.h" +#include "jpeglib8.h" + + +/* Private buffer controller object */ + +typedef struct { + struct jpeg_d_post_controller pub; /* public fields */ + + /* Color quantization source buffer: this holds output data from + * the upsample/color conversion step to be passed to the quantizer. + * For two-pass color quantization, we need a full-image buffer; + * for one-pass operation, a strip buffer is sufficient. + */ + jvirt_sarray_ptr whole_image; /* virtual array, or NULL if one-pass */ + JSAMPARRAY buffer; /* strip buffer, or current strip of virtual */ + JDIMENSION strip_height; /* buffer size in rows */ + /* for two-pass mode only: */ + JDIMENSION starting_row; /* row # of first row in current strip */ + JDIMENSION next_row; /* index of next row to fill/empty in strip */ +} my_post_controller; + +typedef my_post_controller * my_post_ptr; + + +/* Forward declarations */ +METHODDEF(void) post_process_1pass + JPP((j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail)); +#ifdef QUANT_2PASS_SUPPORTED +METHODDEF(void) post_process_prepass + JPP((j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail)); +METHODDEF(void) post_process_2pass + JPP((j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail)); +#endif + + +/* + * Initialize for a processing pass. + */ + +METHODDEF(void) +start_pass_dpost (j_decompress_ptr cinfo, J_BUF_MODE pass_mode) +{ + my_post_ptr post = (my_post_ptr) cinfo->post; + + switch (pass_mode) { + case JBUF_PASS_THRU: + if (cinfo->quantize_colors) { + /* Single-pass processing with color quantization. */ + post->pub.post_process_data = post_process_1pass; + /* We could be doing buffered-image output before starting a 2-pass + * color quantization; in that case, jinit_d_post_controller did not + * allocate a strip buffer. Use the virtual-array buffer as workspace. + */ + if (post->buffer == NULL) { + post->buffer = (*cinfo->mem->access_virt_sarray) + ((j_common_ptr) cinfo, post->whole_image, + (JDIMENSION) 0, post->strip_height, TRUE); + } + } else { + /* For single-pass processing without color quantization, + * I have no work to do; just call the upsampler directly. + */ + post->pub.post_process_data = cinfo->upsample->upsample; + } + break; +#ifdef QUANT_2PASS_SUPPORTED + case JBUF_SAVE_AND_PASS: + /* First pass of 2-pass quantization */ + if (post->whole_image == NULL) + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + post->pub.post_process_data = post_process_prepass; + break; + case JBUF_CRANK_DEST: + /* Second pass of 2-pass quantization */ + if (post->whole_image == NULL) + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + post->pub.post_process_data = post_process_2pass; + break; +#endif /* QUANT_2PASS_SUPPORTED */ + default: + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + break; + } + post->starting_row = post->next_row = 0; +} + + +/* + * Process some data in the one-pass (strip buffer) case. + * This is used for color precision reduction as well as one-pass quantization. + */ + +METHODDEF(void) +post_process_1pass (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail) +{ + my_post_ptr post = (my_post_ptr) cinfo->post; + JDIMENSION num_rows, max_rows; + + /* Fill the buffer, but not more than what we can dump out in one go. */ + /* Note we rely on the upsampler to detect bottom of image. */ + max_rows = out_rows_avail - *out_row_ctr; + if (max_rows > post->strip_height) + max_rows = post->strip_height; + num_rows = 0; + (*cinfo->upsample->upsample) (cinfo, + input_buf, in_row_group_ctr, in_row_groups_avail, + post->buffer, &num_rows, max_rows); + /* Quantize and emit data. */ + (*cinfo->cquantize->color_quantize) (cinfo, + post->buffer, output_buf + *out_row_ctr, (int) num_rows); + *out_row_ctr += num_rows; +} + + +#ifdef QUANT_2PASS_SUPPORTED + +/* + * Process some data in the first pass of 2-pass quantization. + */ + +METHODDEF(void) +post_process_prepass (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail) +{ + my_post_ptr post = (my_post_ptr) cinfo->post; + JDIMENSION old_next_row, num_rows; + + /* Reposition virtual buffer if at start of strip. */ + if (post->next_row == 0) { + post->buffer = (*cinfo->mem->access_virt_sarray) + ((j_common_ptr) cinfo, post->whole_image, + post->starting_row, post->strip_height, TRUE); + } + + /* Upsample some data (up to a strip height's worth). */ + old_next_row = post->next_row; + (*cinfo->upsample->upsample) (cinfo, + input_buf, in_row_group_ctr, in_row_groups_avail, + post->buffer, &post->next_row, post->strip_height); + + /* Allow quantizer to scan new data. No data is emitted, */ + /* but we advance out_row_ctr so outer loop can tell when we're done. */ + if (post->next_row > old_next_row) { + num_rows = post->next_row - old_next_row; + (*cinfo->cquantize->color_quantize) (cinfo, post->buffer + old_next_row, + (JSAMPARRAY) NULL, (int) num_rows); + *out_row_ctr += num_rows; + } + + /* Advance if we filled the strip. */ + if (post->next_row >= post->strip_height) { + post->starting_row += post->strip_height; + post->next_row = 0; + } +} + + +/* + * Process some data in the second pass of 2-pass quantization. + */ + +METHODDEF(void) +post_process_2pass (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail) +{ + my_post_ptr post = (my_post_ptr) cinfo->post; + JDIMENSION num_rows, max_rows; + + /* Reposition virtual buffer if at start of strip. */ + if (post->next_row == 0) { + post->buffer = (*cinfo->mem->access_virt_sarray) + ((j_common_ptr) cinfo, post->whole_image, + post->starting_row, post->strip_height, FALSE); + } + + /* Determine number of rows to emit. */ + num_rows = post->strip_height - post->next_row; /* available in strip */ + max_rows = out_rows_avail - *out_row_ctr; /* available in output area */ + if (num_rows > max_rows) + num_rows = max_rows; + /* We have to check bottom of image here, can't depend on upsampler. */ + max_rows = cinfo->output_height - post->starting_row; + if (num_rows > max_rows) + num_rows = max_rows; + + /* Quantize and emit data. */ + (*cinfo->cquantize->color_quantize) (cinfo, + post->buffer + post->next_row, output_buf + *out_row_ctr, + (int) num_rows); + *out_row_ctr += num_rows; + + /* Advance if we filled the strip. */ + post->next_row += num_rows; + if (post->next_row >= post->strip_height) { + post->starting_row += post->strip_height; + post->next_row = 0; + } +} + +#endif /* QUANT_2PASS_SUPPORTED */ + + +/* + * Initialize postprocessing controller. + */ + +GLOBAL(void) +jinit_d_post_controller (j_decompress_ptr cinfo, boolean need_full_buffer) +{ + my_post_ptr post; + + post = (my_post_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_post_controller)); + cinfo->post = (struct jpeg_d_post_controller *) post; + post->pub.start_pass = start_pass_dpost; + post->whole_image = NULL; /* flag for no virtual arrays */ + post->buffer = NULL; /* flag for no strip buffer */ + + /* Create the quantization buffer, if needed */ + if (cinfo->quantize_colors) { + /* The buffer strip height is max_v_samp_factor, which is typically + * an efficient number of rows for upsampling to return. + * (In the presence of output rescaling, we might want to be smarter?) + */ + post->strip_height = (JDIMENSION) cinfo->max_v_samp_factor; + if (need_full_buffer) { + /* Two-pass color quantization: need full-image storage. */ + /* We round up the number of rows to a multiple of the strip height. */ +#ifdef QUANT_2PASS_SUPPORTED + post->whole_image = (*cinfo->mem->request_virt_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE, + cinfo->output_width * (JDIMENSION)cinfo->out_color_components, + (JDIMENSION) jround_up((long) cinfo->output_height, + (long) post->strip_height), + post->strip_height); +#else + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); +#endif /* QUANT_2PASS_SUPPORTED */ + } else { + /* One-pass color quantization: just make a strip buffer. */ + post->buffer = (*cinfo->mem->alloc_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + cinfo->output_width * (JDIMENSION)cinfo->out_color_components, + post->strip_height); + } + } +} diff --git a/dcmjpeg/libijg8/jdpred.c b/dcmjpeg/libijg8/jdpred.c new file mode 100644 index 00000000..b815ed80 --- /dev/null +++ b/dcmjpeg/libijg8/jdpred.c @@ -0,0 +1,263 @@ +/* + * jdpred.c + * + * Copyright (C) 1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains sample undifferencing (reconstruction) for lossless JPEG. + * + * In order to avoid paying the performance penalty of having to check the + * predictor being used and the row being processed for each call of the + * undifferencer, and to promote optimization, we have separate undifferencing + * functions for each case. + * + * We are able to avoid duplicating source code by implementing the predictors + * and undifferencers as macros. Each of the undifferencing functions are + * simply wrappers around an UNDIFFERENCE macro with the appropriate PREDICTOR + * macro passed as an argument. + */ + +#define JPEG_INTERNALS +#include "jinclude8.h" +#include "jpeglib8.h" +#include "jlossls8.h" /* Private declarations for lossless codec */ + + +#ifdef D_LOSSLESS_SUPPORTED + +/* Predictor for the first column of the first row: 2^(P-Pt-1) */ +#define INITIAL_PREDICTORx (1 << (cinfo->data_precision - cinfo->Al - 1)) + +/* Predictor for the first column of the remaining rows: Rb */ +#define INITIAL_PREDICTOR2 GETJSAMPLE(prev_row[0]) + + +/* + * 1-Dimensional undifferencer routine. + * + * This macro implements the 1-D horizontal predictor (1). INITIAL_PREDICTOR + * is used as the special case predictor for the first column, which must be + * either INITIAL_PREDICTOR2 or INITIAL_PREDICTORx. The remaining samples + * use PREDICTOR1. + * + * The reconstructed sample is supposed to be calculated modulo 2^16, so we + * logically AND the result with 0xFFFF. +*/ + +#define UNDIFFERENCE_1D(INITIAL_PREDICTOR) \ + unsigned int xindex; \ + int Ra; \ + \ + Ra = (diff_buf[0] + INITIAL_PREDICTOR) & 0xFFFF; \ + undiff_buf[0] = Ra; \ + \ + for (xindex = 1; xindex < width; xindex++) { \ + Ra = (diff_buf[xindex] + PREDICTOR1) & 0xFFFF; \ + undiff_buf[xindex] = Ra; \ + } + +/* + * 2-Dimensional undifferencer routine. + * + * This macro implements the 2-D horizontal predictors (#2-7). PREDICTOR2 is + * used as the special case predictor for the first column. The remaining + * samples use PREDICTOR, which is a function of Ra, Rb, Rc. + * + * Because prev_row and output_buf may point to the same storage area (in an + * interleaved image with Vi=1, for example), we must take care to buffer Rb/Rc + * before writing the current reconstructed sample value into output_buf. + * + * The reconstructed sample is supposed to be calculated modulo 2^16, so we + * logically AND the result with 0xFFFF. + */ + +#define UNDIFFERENCE_2D(PREDICTOR) \ + unsigned int xindex; \ + int Ra, Rb, Rc; \ + \ + Rb = GETJSAMPLE(prev_row[0]); \ + Ra = (diff_buf[0] + PREDICTOR2) & 0xFFFF; \ + undiff_buf[0] = Ra; \ + \ + for (xindex = 1; xindex < width; xindex++) { \ + Rc = Rb; \ + Rb = GETJSAMPLE(prev_row[xindex]); \ + Ra = (diff_buf[xindex] + PREDICTOR) & 0xFFFF; \ + undiff_buf[xindex] = Ra; \ + } + +#define JPEG_UNUSED(x) ((void)x) + +/* + * Undifferencers for the all rows but the first in a scan or restart interval. + * The first sample in the row is undifferenced using the vertical + * predictor (2). The rest of the samples are undifferenced using the + * predictor specified in the scan header. + */ + +METHODDEF(void) +jpeg_undifference1(j_decompress_ptr cinfo, int comp_index, + JDIFFROW diff_buf, JDIFFROW prev_row, + JDIFFROW undiff_buf, JDIMENSION width) +{ + UNDIFFERENCE_1D(INITIAL_PREDICTOR2); +} + +METHODDEF(void) +jpeg_undifference2(j_decompress_ptr cinfo, int comp_index, + JDIFFROW diff_buf, JDIFFROW prev_row, + JDIFFROW undiff_buf, JDIMENSION width) +{ + UNDIFFERENCE_2D(PREDICTOR2); + JPEG_UNUSED(Rc); + JPEG_UNUSED(Rb); +} + +METHODDEF(void) +jpeg_undifference3(j_decompress_ptr cinfo, int comp_index, + JDIFFROW diff_buf, JDIFFROW prev_row, + JDIFFROW undiff_buf, JDIMENSION width) +{ + UNDIFFERENCE_2D(PREDICTOR3); + JPEG_UNUSED(Rc); + JPEG_UNUSED(Rb); +} + +METHODDEF(void) +jpeg_undifference4(j_decompress_ptr cinfo, int comp_index, + JDIFFROW diff_buf, JDIFFROW prev_row, + JDIFFROW undiff_buf, JDIMENSION width) +{ + UNDIFFERENCE_2D(PREDICTOR4); + JPEG_UNUSED(Rc); + JPEG_UNUSED(Rb); +} + +METHODDEF(void) +jpeg_undifference5(j_decompress_ptr cinfo, int comp_index, + JDIFFROW diff_buf, JDIFFROW prev_row, + JDIFFROW undiff_buf, JDIMENSION width) +{ + SHIFT_TEMPS + UNDIFFERENCE_2D(PREDICTOR5); + JPEG_UNUSED(Rc); + JPEG_UNUSED(Rb); +} + +METHODDEF(void) +jpeg_undifference6(j_decompress_ptr cinfo, int comp_index, + JDIFFROW diff_buf, JDIFFROW prev_row, + JDIFFROW undiff_buf, JDIMENSION width) +{ + SHIFT_TEMPS + UNDIFFERENCE_2D(PREDICTOR6); + JPEG_UNUSED(Rc); + JPEG_UNUSED(Rb); +} + +METHODDEF(void) +jpeg_undifference7(j_decompress_ptr cinfo, int comp_index, + JDIFFROW diff_buf, JDIFFROW prev_row, + JDIFFROW undiff_buf, JDIMENSION width) +{ + SHIFT_TEMPS + UNDIFFERENCE_2D(PREDICTOR7); + JPEG_UNUSED(Rc); + JPEG_UNUSED(Rb); +} + + +/* + * Undifferencer for the first row in a scan or restart interval. The first + * sample in the row is undifferenced using the special predictor constant + * x=2^(P-Pt-1). The rest of the samples are undifferenced using the + * 1-D horizontal predictor (1). + */ + +METHODDEF(void) +jpeg_undifference_first_row(j_decompress_ptr cinfo, int comp_index, + JDIFFROW diff_buf, JDIFFROW prev_row, + JDIFFROW undiff_buf, JDIMENSION width) +{ + j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec; + + UNDIFFERENCE_1D(INITIAL_PREDICTORx); + + /* + * Now that we have undifferenced the first row, we want to use the + * undifferencer which corresponds to the predictor specified in the + * scan header. + */ + switch (cinfo->Ss) { + case 1: + losslsd->predict_undifference[comp_index] = jpeg_undifference1; + break; + case 2: + losslsd->predict_undifference[comp_index] = jpeg_undifference2; + break; + case 3: + losslsd->predict_undifference[comp_index] = jpeg_undifference3; + break; + case 4: + losslsd->predict_undifference[comp_index] = jpeg_undifference4; + break; + case 5: + losslsd->predict_undifference[comp_index] = jpeg_undifference5; + break; + case 6: + losslsd->predict_undifference[comp_index] = jpeg_undifference6; + break; + case 7: + losslsd->predict_undifference[comp_index] = jpeg_undifference7; + break; + } +} + + +/* + * Initialize for an input processing pass. + */ + +METHODDEF(void) +predict_start_pass (j_decompress_ptr cinfo) +{ + j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec; + int ci; + + /* Check that the scan parameters Ss, Se, Ah, Al are OK for lossless JPEG. + * + * Ss is the predictor selection value (psv). Legal values for sequential + * lossless JPEG are: 1 <= psv <= 7. + * + * Se and Ah are not used and should be zero. + * + * Al specifies the point transform (Pt). Legal values are: 0 <= Pt <= 15. + */ + if (cinfo->Ss < 1 || cinfo->Ss > 7 || + cinfo->Se != 0 || cinfo->Ah != 0 || + cinfo->Al > 15) /* need not check for < 0 */ + ERREXIT4(cinfo, JERR_BAD_LOSSLESS, + cinfo->Ss, cinfo->Se, cinfo->Ah, cinfo->Al); + + /* Set undifference functions to first row function */ + for (ci = 0; ci < cinfo->num_components; ci++) + losslsd->predict_undifference[ci] = jpeg_undifference_first_row; +} + + +/* + * Module initialization routine for the undifferencer. + */ + +GLOBAL(void) +jinit_undifferencer (j_decompress_ptr cinfo) +{ + j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec; + + losslsd->predict_start_pass = predict_start_pass; + losslsd->predict_process_restart = predict_start_pass; +} + +#endif /* D_LOSSLESS_SUPPORTED */ + diff --git a/dcmjpeg/libijg8/jdsample.c b/dcmjpeg/libijg8/jdsample.c new file mode 100644 index 00000000..024f2966 --- /dev/null +++ b/dcmjpeg/libijg8/jdsample.c @@ -0,0 +1,478 @@ +/* + * jdsample.c + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains upsampling routines. + * + * Upsampling input data is counted in "row groups". A row group + * is defined to be (v_samp_factor * codec_data_unit / min_codec_data_unit) + * sample rows of each component. Upsampling will normally produce + * max_v_samp_factor pixel rows from each row group (but this could vary + * if the upsampler is applying a scale factor of its own). + * + * An excellent reference for image resampling is + * Digital Image Warping, George Wolberg, 1990. + * Pub. by IEEE Computer Society Press, Los Alamitos, CA. ISBN 0-8186-8944-7. + */ + +#define JPEG_INTERNALS +#include "jinclude8.h" +#include "jpeglib8.h" + + +/* Pointer to routine to upsample a single component */ +typedef JMETHOD(void, upsample1_ptr, + (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr)); + +/* Private subobject */ + +typedef struct { + struct jpeg_upsampler pub; /* public fields */ + + /* Color conversion buffer. When using separate upsampling and color + * conversion steps, this buffer holds one upsampled row group until it + * has been color converted and output. + * Note: we do not allocate any storage for component(s) which are full-size, + * ie do not need rescaling. The corresponding entry of color_buf[] is + * simply set to point to the input data array, thereby avoiding copying. + */ + JSAMPARRAY color_buf[MAX_COMPONENTS]; + + /* Per-component upsampling method pointers */ + upsample1_ptr methods[MAX_COMPONENTS]; + + int next_row_out; /* counts rows emitted from color_buf */ + JDIMENSION rows_to_go; /* counts rows remaining in image */ + + /* Height of an input row group for each component. */ + int rowgroup_height[MAX_COMPONENTS]; + + /* These arrays save pixel expansion factors so that int_expand need not + * recompute them each time. They are unused for other upsampling methods. + */ + UINT8 h_expand[MAX_COMPONENTS]; + UINT8 v_expand[MAX_COMPONENTS]; +} my_upsampler; + +typedef my_upsampler * my_upsample_ptr; + + +/* + * Initialize for an upsampling pass. + */ + +METHODDEF(void) +start_pass_upsample (j_decompress_ptr cinfo) +{ + my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; + + /* Mark the conversion buffer empty */ + upsample->next_row_out = cinfo->max_v_samp_factor; + /* Initialize total-height counter for detecting bottom of image */ + upsample->rows_to_go = cinfo->output_height; +} + + +/* + * Control routine to do upsampling (and color conversion). + * + * In this version we upsample each component independently. + * We upsample one row group into the conversion buffer, then apply + * color conversion a row at a time. + */ + +METHODDEF(void) +sep_upsample (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail) +{ + my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; + int ci; + jpeg_component_info * compptr; + JDIMENSION num_rows; + + /* Fill the conversion buffer, if it's empty */ + if (upsample->next_row_out >= cinfo->max_v_samp_factor) { + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + /* Invoke per-component upsample method. Notice we pass a POINTER + * to color_buf[ci], so that fullsize_upsample can change it. + */ + (*upsample->methods[ci]) (cinfo, compptr, + input_buf[ci] + (*in_row_group_ctr * (JDIMENSION)upsample->rowgroup_height[ci]), + upsample->color_buf + ci); + } + upsample->next_row_out = 0; + } + + /* Color-convert and emit rows */ + + /* How many we have in the buffer: */ + num_rows = (JDIMENSION) (cinfo->max_v_samp_factor - upsample->next_row_out); + /* Not more than the distance to the end of the image. Need this test + * in case the image height is not a multiple of max_v_samp_factor: + */ + if (num_rows > upsample->rows_to_go) + num_rows = upsample->rows_to_go; + /* And not more than what the client can accept: */ + out_rows_avail -= *out_row_ctr; + if (num_rows > out_rows_avail) + num_rows = out_rows_avail; + + (*cinfo->cconvert->color_convert) (cinfo, upsample->color_buf, + (JDIMENSION) upsample->next_row_out, + output_buf + *out_row_ctr, + (int) num_rows); + + /* Adjust counts */ + *out_row_ctr += num_rows; + upsample->rows_to_go -= num_rows; + upsample->next_row_out += (int)num_rows; + /* When the buffer is emptied, declare this input row group consumed */ + if (upsample->next_row_out >= cinfo->max_v_samp_factor) + (*in_row_group_ctr)++; +} + + +/* + * These are the routines invoked by sep_upsample to upsample pixel values + * of a single component. One row group is processed per call. + */ + + +/* + * For full-size components, we just make color_buf[ci] point at the + * input buffer, and thus avoid copying any data. Note that this is + * safe only because sep_upsample doesn't declare the input row group + * "consumed" until we are done color converting and emitting it. + */ + +METHODDEF(void) +fullsize_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) +{ + *output_data_ptr = input_data; +} + + +/* + * This is a no-op version used for "uninteresting" components. + * These components will not be referenced by color conversion. + */ + +METHODDEF(void) +noop_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) +{ + *output_data_ptr = NULL; /* safety check */ +} + + +/* + * This version handles any integral sampling ratios. + * This is not used for typical JPEG files, so it need not be fast. + * Nor, for that matter, is it particularly accurate: the algorithm is + * simple replication of the input pixel onto the corresponding output + * pixels. The hi-falutin sampling literature refers to this as a + * "box filter". A box filter tends to introduce visible artifacts, + * so if you are actually going to use 3:1 or 4:1 sampling ratios + * you would be well advised to improve this code. + */ + +METHODDEF(void) +int_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) +{ + my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; + JSAMPARRAY output_data = *output_data_ptr; + register JSAMPROW inptr, outptr; + register JSAMPLE invalue; + register int h; + JSAMPROW outend; + int h_expand, v_expand; + int inrow, outrow; + + h_expand = upsample->h_expand[compptr->component_index]; + v_expand = upsample->v_expand[compptr->component_index]; + + inrow = outrow = 0; + while (outrow < cinfo->max_v_samp_factor) { + /* Generate one output row with proper horizontal expansion */ + inptr = input_data[inrow]; + outptr = output_data[outrow]; + outend = outptr + cinfo->output_width; + while (outptr < outend) { + invalue = *inptr++; /* don't need GETJSAMPLE() here */ + for (h = h_expand; h > 0; h--) { + *outptr++ = invalue; + } + } + /* Generate any additional output rows by duplicating the first one */ + if (v_expand > 1) { + jcopy_sample_rows(output_data, outrow, output_data, outrow+1, + v_expand-1, cinfo->output_width); + } + inrow++; + outrow += v_expand; + } +} + + +/* + * Fast processing for the common case of 2:1 horizontal and 1:1 vertical. + * It's still a box filter. + */ + +METHODDEF(void) +h2v1_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) +{ + JSAMPARRAY output_data = *output_data_ptr; + register JSAMPROW inptr, outptr; + register JSAMPLE invalue; + JSAMPROW outend; + int inrow; + + for (inrow = 0; inrow < cinfo->max_v_samp_factor; inrow++) { + inptr = input_data[inrow]; + outptr = output_data[inrow]; + outend = outptr + cinfo->output_width; + while (outptr < outend) { + invalue = *inptr++; /* don't need GETJSAMPLE() here */ + *outptr++ = invalue; + *outptr++ = invalue; + } + } +} + + +/* + * Fast processing for the common case of 2:1 horizontal and 2:1 vertical. + * It's still a box filter. + */ + +METHODDEF(void) +h2v2_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) +{ + JSAMPARRAY output_data = *output_data_ptr; + register JSAMPROW inptr, outptr; + register JSAMPLE invalue; + JSAMPROW outend; + int inrow, outrow; + + inrow = outrow = 0; + while (outrow < cinfo->max_v_samp_factor) { + inptr = input_data[inrow]; + outptr = output_data[outrow]; + outend = outptr + cinfo->output_width; + while (outptr < outend) { + invalue = *inptr++; /* don't need GETJSAMPLE() here */ + *outptr++ = invalue; + *outptr++ = invalue; + } + jcopy_sample_rows(output_data, outrow, output_data, outrow+1, + 1, cinfo->output_width); + inrow++; + outrow += 2; + } +} + + +/* + * Fancy processing for the common case of 2:1 horizontal and 1:1 vertical. + * + * The upsampling algorithm is linear interpolation between pixel centers, + * also known as a "triangle filter". This is a good compromise between + * speed and visual quality. The centers of the output pixels are 1/4 and 3/4 + * of the way between input pixel centers. + * + * A note about the "bias" calculations: when rounding fractional values to + * integer, we do not want to always round 0.5 up to the next integer. + * If we did that, we'd introduce a noticeable bias towards larger values. + * Instead, this code is arranged so that 0.5 will be rounded up or down at + * alternate pixel locations (a simple ordered dither pattern). + */ + +METHODDEF(void) +h2v1_fancy_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) +{ + JSAMPARRAY output_data = *output_data_ptr; + register JSAMPROW inptr, outptr; + register int invalue; + register JDIMENSION colctr; + int inrow; + + for (inrow = 0; inrow < cinfo->max_v_samp_factor; inrow++) { + inptr = input_data[inrow]; + outptr = output_data[inrow]; + /* Special case for first column */ + invalue = GETJSAMPLE(*inptr++); + *outptr++ = (JSAMPLE) invalue; + *outptr++ = (JSAMPLE) ((invalue * 3 + GETJSAMPLE(*inptr) + 2) >> 2); + + for (colctr = compptr->downsampled_width - 2; colctr > 0; colctr--) { + /* General case: 3/4 * nearer pixel + 1/4 * further pixel */ + invalue = GETJSAMPLE(*inptr++) * 3; + *outptr++ = (JSAMPLE) ((invalue + GETJSAMPLE(inptr[-2]) + 1) >> 2); + *outptr++ = (JSAMPLE) ((invalue + GETJSAMPLE(*inptr) + 2) >> 2); + } + + /* Special case for last column */ + invalue = GETJSAMPLE(*inptr); + *outptr++ = (JSAMPLE) ((invalue * 3 + GETJSAMPLE(inptr[-1]) + 1) >> 2); + *outptr++ = (JSAMPLE) invalue; + } +} + + +/* + * Fancy processing for the common case of 2:1 horizontal and 2:1 vertical. + * Again a triangle filter; see comments for h2v1 case, above. + * + * It is OK for us to reference the adjacent input rows because we demanded + * context from the main buffer controller (see initialization code). + */ + +METHODDEF(void) +h2v2_fancy_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) +{ + JSAMPARRAY output_data = *output_data_ptr; + register JSAMPROW inptr0, inptr1, outptr; +#if BITS_IN_JSAMPLE == 8 + register int thiscolsum, lastcolsum, nextcolsum; +#else + register IJG_INT32 thiscolsum, lastcolsum, nextcolsum; +#endif + register JDIMENSION colctr; + int inrow, outrow, v; + + inrow = outrow = 0; + while (outrow < cinfo->max_v_samp_factor) { + for (v = 0; v < 2; v++) { + /* inptr0 points to nearest input row, inptr1 points to next nearest */ + inptr0 = input_data[inrow]; + if (v == 0) /* next nearest is row above */ + inptr1 = input_data[inrow-1]; + else /* next nearest is row below */ + inptr1 = input_data[inrow+1]; + outptr = output_data[outrow++]; + + /* Special case for first column */ + thiscolsum = GETJSAMPLE(*inptr0++) * 3 + GETJSAMPLE(*inptr1++); + nextcolsum = GETJSAMPLE(*inptr0++) * 3 + GETJSAMPLE(*inptr1++); + *outptr++ = (JSAMPLE) ((thiscolsum * 4 + 8) >> 4); + *outptr++ = (JSAMPLE) ((thiscolsum * 3 + nextcolsum + 7) >> 4); + lastcolsum = thiscolsum; thiscolsum = nextcolsum; + + for (colctr = compptr->downsampled_width - 2; colctr > 0; colctr--) { + /* General case: 3/4 * nearer pixel + 1/4 * further pixel in each */ + /* dimension, thus 9/16, 3/16, 3/16, 1/16 overall */ + nextcolsum = GETJSAMPLE(*inptr0++) * 3 + GETJSAMPLE(*inptr1++); + *outptr++ = (JSAMPLE) ((thiscolsum * 3 + lastcolsum + 8) >> 4); + *outptr++ = (JSAMPLE) ((thiscolsum * 3 + nextcolsum + 7) >> 4); + lastcolsum = thiscolsum; thiscolsum = nextcolsum; + } + + /* Special case for last column */ + *outptr++ = (JSAMPLE) ((thiscolsum * 3 + lastcolsum + 8) >> 4); + *outptr++ = (JSAMPLE) ((thiscolsum * 4 + 7) >> 4); + } + inrow++; + } +} + + +/* + * Module initialization routine for upsampling. + */ + +GLOBAL(void) +jinit_upsampler (j_decompress_ptr cinfo) +{ + my_upsample_ptr upsample; + int ci; + jpeg_component_info * compptr; + boolean need_buffer, do_fancy; + int h_in_group, v_in_group, h_out_group, v_out_group; + + upsample = (my_upsample_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_upsampler)); + cinfo->upsample = (struct jpeg_upsampler *) upsample; + upsample->pub.start_pass = start_pass_upsample; + upsample->pub.upsample = sep_upsample; + upsample->pub.need_context_rows = FALSE; /* until we find out differently */ + + if (cinfo->CCIR601_sampling) /* this isn't supported */ + ERREXIT(cinfo, JERR_CCIR601_NOTIMPL); + + /* jdmainct.c doesn't support context rows when min_codec_data_unit = 1, + * so don't ask for it. + */ + do_fancy = cinfo->do_fancy_upsampling && cinfo->min_codec_data_unit > 1; + + /* Verify we can handle the sampling factors, select per-component methods, + * and create storage as needed. + */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + /* Compute size of an "input group" after IDCT scaling. This many samples + * are to be converted to max_h_samp_factor * max_v_samp_factor pixels. + */ + h_in_group = (compptr->h_samp_factor * compptr->codec_data_unit) / + cinfo->min_codec_data_unit; + v_in_group = (compptr->v_samp_factor * compptr->codec_data_unit) / + cinfo->min_codec_data_unit; + h_out_group = cinfo->max_h_samp_factor; + v_out_group = cinfo->max_v_samp_factor; + upsample->rowgroup_height[ci] = v_in_group; /* save for use later */ + need_buffer = TRUE; + if (! compptr->component_needed) { + /* Don't bother to upsample an uninteresting component. */ + upsample->methods[ci] = noop_upsample; + need_buffer = FALSE; + } else if (h_in_group == h_out_group && v_in_group == v_out_group) { + /* Fullsize components can be processed without any work. */ + upsample->methods[ci] = fullsize_upsample; + need_buffer = FALSE; + } else if (h_in_group * 2 == h_out_group && + v_in_group == v_out_group) { + /* Special cases for 2h1v upsampling */ + if (do_fancy && compptr->downsampled_width > 2) + upsample->methods[ci] = h2v1_fancy_upsample; + else + upsample->methods[ci] = h2v1_upsample; + } else if (h_in_group * 2 == h_out_group && + v_in_group * 2 == v_out_group) { + /* Special cases for 2h2v upsampling */ + if (do_fancy && compptr->downsampled_width > 2) { + upsample->methods[ci] = h2v2_fancy_upsample; + upsample->pub.need_context_rows = TRUE; + } else + upsample->methods[ci] = h2v2_upsample; + } else if ((h_out_group % h_in_group) == 0 && + (v_out_group % v_in_group) == 0) { + /* Generic integral-factors upsampling method */ + upsample->methods[ci] = int_upsample; + upsample->h_expand[ci] = (UINT8) (h_out_group / h_in_group); + upsample->v_expand[ci] = (UINT8) (v_out_group / v_in_group); + } else + ERREXIT(cinfo, JERR_FRACT_SAMPLE_NOTIMPL); + if (need_buffer) { + upsample->color_buf[ci] = (*cinfo->mem->alloc_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + (JDIMENSION) jround_up((long) cinfo->output_width, + (long) cinfo->max_h_samp_factor), + (JDIMENSION) cinfo->max_v_samp_factor); + } + } +} diff --git a/dcmjpeg/libijg8/jdscale.c b/dcmjpeg/libijg8/jdscale.c new file mode 100644 index 00000000..c49689c2 --- /dev/null +++ b/dcmjpeg/libijg8/jdscale.c @@ -0,0 +1,119 @@ +/* + * jdscale.c + * + * Copyright (C) 1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains sample scaling for lossless JPEG. This is a + * combination of upscaling the undifferenced sample by 2^Pt and downscaling + * the sample to fit into JSAMPLE. + */ + +#define JPEG_INTERNALS +#include "jinclude8.h" +#include "jpeglib8.h" +#include "jlossls8.h" /* Private declarations for lossless codec */ + + +#ifdef D_LOSSLESS_SUPPORTED + +/* + * Private scaler object for lossless decoding. + */ + +typedef struct { + int scale_factor; +} scaler; + +typedef scaler * scaler_ptr; + + +/* + * Scalers for packing sample differences into JSAMPLEs. + */ + +METHODDEF(void) +simple_upscale(j_decompress_ptr cinfo, + JDIFFROW diff_buf, JSAMPROW output_buf, + JDIMENSION width) +{ + j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec; + scaler_ptr scale = (scaler_ptr) losslsd->scaler_private; + int scale_factor = scale->scale_factor; + unsigned int xindex; + + for (xindex = 0; xindex < width; xindex++) + output_buf[xindex] = (JSAMPLE) (diff_buf[xindex] << scale_factor); +} + +METHODDEF(void) +simple_downscale(j_decompress_ptr cinfo, + JDIFFROW diff_buf, JSAMPROW output_buf, + JDIMENSION width) +{ + j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec; + scaler_ptr scale = (scaler_ptr) losslsd->scaler_private; + int scale_factor = scale->scale_factor; + unsigned int xindex; + SHIFT_TEMPS + + for (xindex = 0; xindex < width; xindex++) + output_buf[xindex] = (JSAMPLE) RIGHT_SHIFT(diff_buf[xindex], scale_factor); +} + +METHODDEF(void) +noscale(j_decompress_ptr cinfo, + JDIFFROW diff_buf, JSAMPROW output_buf, + JDIMENSION width) +{ + unsigned int xindex; + + for (xindex = 0; xindex < width; xindex++) + output_buf[xindex] = (JSAMPLE) diff_buf[xindex]; +} + + +METHODDEF(void) +scaler_start_pass (j_decompress_ptr cinfo) +{ + j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec; + scaler_ptr scale = (scaler_ptr) losslsd->scaler_private; + int downscale; + + /* + * Downscale by the difference in the input vs. output precision. If the + * output precision >= input precision, then do not downscale. + */ + downscale = BITS_IN_JSAMPLE < cinfo->data_precision ? + cinfo->data_precision - BITS_IN_JSAMPLE : 0; + + scale->scale_factor = cinfo->Al - downscale; + + /* Set scaler functions based on scale_factor (positive = left shift) */ + if (scale->scale_factor > 0) + losslsd->scaler_scale = simple_upscale; + else if (scale->scale_factor < 0) { + scale->scale_factor = -scale->scale_factor; + losslsd->scaler_scale = simple_downscale; + } + else + losslsd->scaler_scale = noscale; +} + + +GLOBAL(void) +jinit_d_scaler (j_decompress_ptr cinfo) +{ + j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec; + scaler_ptr scale; + + scale = (scaler_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(scaler)); + losslsd->scaler_private = (void *) scale; + losslsd->scaler_start_pass = scaler_start_pass; +} + +#endif /* D_LOSSLESS_SUPPORTED */ + diff --git a/dcmjpeg/libijg8/jdshuff.c b/dcmjpeg/libijg8/jdshuff.c new file mode 100644 index 00000000..930f8c95 --- /dev/null +++ b/dcmjpeg/libijg8/jdshuff.c @@ -0,0 +1,360 @@ +/* + * jdshuff.c + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains Huffman entropy decoding routines for sequential JPEG. + * + * Much of the complexity here has to do with supporting input suspension. + * If the data source module demands suspension, we want to be able to back + * up to the start of the current MCU. To do this, we copy state variables + * into local working storage, and update them back to the permanent + * storage only upon successful completion of an MCU. + */ + +#define JPEG_INTERNALS +#include "jinclude8.h" +#include "jpeglib8.h" +#include "jlossy8.h" /* Private declarations for lossy codec */ +#include "jdhuff8.h" /* Declarations shared with jd*huff.c */ + + +/* + * Private entropy decoder object for Huffman decoding. + * + * The savable_state subrecord contains fields that change within an MCU, + * but must not be updated permanently until we complete the MCU. + */ + +typedef struct { + int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */ +} savable_state; + +/* This macro is to work around compilers with missing or broken + * structure assignment. You'll need to fix this code if you have + * such a compiler and you change MAX_COMPS_IN_SCAN. + */ + +#ifndef NO_STRUCT_ASSIGN +#define ASSIGN_STATE(dest,src) ((dest) = (src)) +#else +#if MAX_COMPS_IN_SCAN == 4 +#define ASSIGN_STATE(dest,src) \ + ((dest).last_dc_val[0] = (src).last_dc_val[0], \ + (dest).last_dc_val[1] = (src).last_dc_val[1], \ + (dest).last_dc_val[2] = (src).last_dc_val[2], \ + (dest).last_dc_val[3] = (src).last_dc_val[3]) +#endif +#endif + + +typedef struct { + huffd_common_fields; /* Fields shared with other entropy decoders */ + + /* These fields are loaded into local variables at start of each MCU. + * In case of suspension, we exit WITHOUT updating them. + */ + savable_state saved; /* Other state at start of MCU */ + + /* These fields are NOT loaded into local working state. */ + unsigned int restarts_to_go; /* MCUs left in this restart interval */ + + /* Pointers to derived tables (these workspaces have image lifespan) */ + d_derived_tbl * dc_derived_tbls[NUM_HUFF_TBLS]; + d_derived_tbl * ac_derived_tbls[NUM_HUFF_TBLS]; + + /* Precalculated info set up by start_pass for use in decode_mcu: */ + + /* Pointers to derived tables to be used for each block within an MCU */ + d_derived_tbl * dc_cur_tbls[D_MAX_DATA_UNITS_IN_MCU]; + d_derived_tbl * ac_cur_tbls[D_MAX_DATA_UNITS_IN_MCU]; + /* Whether we care about the DC and AC coefficient values for each block */ + boolean dc_needed[D_MAX_DATA_UNITS_IN_MCU]; + boolean ac_needed[D_MAX_DATA_UNITS_IN_MCU]; +} shuff_entropy_decoder; + +typedef shuff_entropy_decoder * shuff_entropy_ptr; + + +/* + * Initialize for a Huffman-compressed scan. + */ + +METHODDEF(void) +start_pass_huff_decoder (j_decompress_ptr cinfo) +{ + j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec; + shuff_entropy_ptr entropy = (shuff_entropy_ptr) lossyd->entropy_private; + int ci, blkn, dctbl, actbl; + jpeg_component_info * compptr; + + /* Check that the scan parameters Ss, Se, Ah/Al are OK for sequential JPEG. + * This ought to be an error condition, but we make it a warning because + * there are some baseline files out there with all zeroes in these bytes. + */ + if (cinfo->Ss != 0 || cinfo->Se != DCTSIZE2-1 || + cinfo->Ah != 0 || cinfo->Al != 0) + WARNMS(cinfo, JWRN_NOT_SEQUENTIAL); + + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + dctbl = compptr->dc_tbl_no; + actbl = compptr->ac_tbl_no; + /* Compute derived values for Huffman tables */ + /* We may do this more than once for a table, but it's not expensive */ + jpeg_make_d_derived_tbl(cinfo, TRUE, dctbl, + & entropy->dc_derived_tbls[dctbl]); + jpeg_make_d_derived_tbl(cinfo, FALSE, actbl, + & entropy->ac_derived_tbls[actbl]); + /* Initialize DC predictions to 0 */ + entropy->saved.last_dc_val[ci] = 0; + } + + /* Precalculate decoding info for each block in an MCU of this scan */ + for (blkn = 0; blkn < cinfo->data_units_in_MCU; blkn++) { + ci = cinfo->MCU_membership[blkn]; + compptr = cinfo->cur_comp_info[ci]; + /* Precalculate which table to use for each block */ + entropy->dc_cur_tbls[blkn] = entropy->dc_derived_tbls[compptr->dc_tbl_no]; + entropy->ac_cur_tbls[blkn] = entropy->ac_derived_tbls[compptr->ac_tbl_no]; + /* Decide whether we really care about the coefficient values */ + if (compptr->component_needed) { + entropy->dc_needed[blkn] = TRUE; + /* we don't need the ACs if producing a 1/8th-size image */ + entropy->ac_needed[blkn] = (compptr->codec_data_unit > 1); + } else { + entropy->dc_needed[blkn] = entropy->ac_needed[blkn] = FALSE; + } + } + + /* Initialize bitread state variables */ + entropy->bitstate.bits_left = 0; + entropy->bitstate.get_buffer = 0; /* unnecessary, but keeps Purify quiet */ + entropy->insufficient_data = FALSE; + + /* Initialize restart counter */ + entropy->restarts_to_go = cinfo->restart_interval; +} + + +/* + * Figure F.12: extend sign bit. + * On some machines, a shift and add will be faster than a table lookup. + */ + +#ifdef AVOID_TABLES + +#define HUFF_EXTEND(x,s) ((x) < (1<<((s)-1)) ? (x) + (((-1)<<(s)) + 1) : (x)) + +#else + +#define HUFF_EXTEND(x,s) ((x) < extend_test[s] ? (x) + extend_offset[s] : (x)) + +static const int extend_test[16] = /* entry n is 2**(n-1) */ + { 0, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080, + 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000 }; + +static const int extend_offset[16] = /* entry n is (-1 << n) + 1 */ + { 0, ((-1)<<1) + 1, ((-1)<<2) + 1, ((-1)<<3) + 1, ((-1)<<4) + 1, + ((-1)<<5) + 1, ((-1)<<6) + 1, ((-1)<<7) + 1, ((-1)<<8) + 1, + ((-1)<<9) + 1, ((-1)<<10) + 1, ((-1)<<11) + 1, ((-1)<<12) + 1, + ((-1)<<13) + 1, ((-1)<<14) + 1, ((-1)<<15) + 1 }; + +#endif /* AVOID_TABLES */ + + +/* + * Check for a restart marker & resynchronize decoder. + * Returns FALSE if must suspend. + */ + +LOCAL(boolean) +process_restart (j_decompress_ptr cinfo) +{ + j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec; + shuff_entropy_ptr entropy = (shuff_entropy_ptr) lossyd->entropy_private; + int ci; + + /* Throw away any unused bits remaining in bit buffer; */ + /* include any full bytes in next_marker's count of discarded bytes */ + cinfo->marker->discarded_bytes += (unsigned int)(entropy->bitstate.bits_left / 8); + entropy->bitstate.bits_left = 0; + + /* Advance past the RSTn marker */ + if (! (*cinfo->marker->read_restart_marker) (cinfo)) + return FALSE; + + /* Re-initialize DC predictions to 0 */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) + entropy->saved.last_dc_val[ci] = 0; + + /* Reset restart counter */ + entropy->restarts_to_go = cinfo->restart_interval; + + /* Reset out-of-data flag, unless read_restart_marker left us smack up + * against a marker. In that case we will end up treating the next data + * segment as empty, and we can avoid producing bogus output pixels by + * leaving the flag set. + */ + if (cinfo->unread_marker == 0) + entropy->insufficient_data = FALSE; + + return TRUE; +} + + +/* + * Decode and return one MCU's worth of Huffman-compressed coefficients. + * The coefficients are reordered from zigzag order into natural array order, + * but are not dequantized. + * + * The i'th block of the MCU is stored into the block pointed to by + * MCU_data[i]. WE ASSUME THIS AREA HAS BEEN ZEROED BY THE CALLER. + * (Wholesale zeroing is usually a little faster than retail...) + * + * Returns FALSE if data source requested suspension. In that case no + * changes have been made to permanent state. (Exception: some output + * coefficients may already have been assigned. This is harmless for + * this module, since we'll just re-assign them on the next call.) + */ + +METHODDEF(boolean) +decode_mcu (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) +{ + j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec; + shuff_entropy_ptr entropy = (shuff_entropy_ptr) lossyd->entropy_private; + int blkn; + BITREAD_STATE_VARS; + savable_state state; + + /* Process restart marker if needed; may have to suspend */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) + if (! process_restart(cinfo)) + return FALSE; + } + + /* If we've run out of data, just leave the MCU set to zeroes. + * This way, we return uniform gray for the remainder of the segment. + */ + if (! entropy->insufficient_data) { + + /* Load up working state */ + BITREAD_LOAD_STATE(cinfo,entropy->bitstate); + ASSIGN_STATE(state, entropy->saved); + + /* Outer loop handles each block in the MCU */ + + for (blkn = 0; blkn < cinfo->data_units_in_MCU; blkn++) { + JBLOCKROW block = MCU_data[blkn]; + d_derived_tbl * dctbl = entropy->dc_cur_tbls[blkn]; + d_derived_tbl * actbl = entropy->ac_cur_tbls[blkn]; + register int s, k, r; + + /* Decode a single block's worth of coefficients */ + + /* Section F.2.2.1: decode the DC coefficient difference */ + HUFF_DECODE(s, br_state, dctbl, return FALSE, label1); + if (s) { + CHECK_BIT_BUFFER(br_state, s, return FALSE); + r = GET_BITS(s); + s = HUFF_EXTEND(r, s); + } + + if (entropy->dc_needed[blkn]) { + /* Convert DC difference to actual value, update last_dc_val */ + int ci = cinfo->MCU_membership[blkn]; + s += state.last_dc_val[ci]; + state.last_dc_val[ci] = s; + /* Output the DC coefficient (assumes jpeg_natural_order[0] = 0) */ + (*block)[0] = (JCOEF) s; + } + + if (entropy->ac_needed[blkn]) { + + /* Section F.2.2.2: decode the AC coefficients */ + /* Since zeroes are skipped, output area must be cleared beforehand */ + for (k = 1; k < DCTSIZE2; k++) { + HUFF_DECODE(s, br_state, actbl, return FALSE, label2); + + r = s >> 4; + s &= 15; + + if (s) { + k += r; + CHECK_BIT_BUFFER(br_state, s, return FALSE); + r = GET_BITS(s); + s = HUFF_EXTEND(r, s); + /* Output coefficient in natural (dezigzagged) order. + * Note: the extra entries in jpeg_natural_order[] will save us + * if k >= DCTSIZE2, which could happen if the data is corrupted. + */ + (*block)[jpeg_natural_order[k]] = (JCOEF) s; + } else { + if (r != 15) + break; + k += 15; + } + } + + } else { + + /* Section F.2.2.2: decode the AC coefficients */ + /* In this path we just discard the values */ + for (k = 1; k < DCTSIZE2; k++) { + HUFF_DECODE(s, br_state, actbl, return FALSE, label3); + + r = s >> 4; + s &= 15; + + if (s) { + k += r; + CHECK_BIT_BUFFER(br_state, s, return FALSE); + DROP_BITS(s); + } else { + if (r != 15) + break; + k += 15; + } + } + + } + } + + /* Completed MCU, so update state */ + BITREAD_SAVE_STATE(cinfo,entropy->bitstate); + ASSIGN_STATE(entropy->saved, state); + } + + /* Account for restart interval (no-op if not using restarts) */ + entropy->restarts_to_go--; + + return TRUE; +} + + +/* + * Module initialization routine for Huffman entropy decoding. + */ + +GLOBAL(void) +jinit_shuff_decoder (j_decompress_ptr cinfo) +{ + j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec; + shuff_entropy_ptr entropy; + int i; + + entropy = (shuff_entropy_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(shuff_entropy_decoder)); + lossyd->entropy_private = (void *) entropy; + lossyd->entropy_start_pass = start_pass_huff_decoder; + lossyd->entropy_decode_mcu = decode_mcu; + + /* Mark tables unallocated */ + for (i = 0; i < NUM_HUFF_TBLS; i++) { + entropy->dc_derived_tbls[i] = entropy->ac_derived_tbls[i] = NULL; + } +} diff --git a/dcmjpeg/libijg8/jdtrans.c b/dcmjpeg/libijg8/jdtrans.c new file mode 100644 index 00000000..53e603f8 --- /dev/null +++ b/dcmjpeg/libijg8/jdtrans.c @@ -0,0 +1,138 @@ +/* + * jdtrans.c + * + * Copyright (C) 1995-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains library routines for transcoding decompression, + * that is, reading raw DCT coefficient arrays from an input JPEG file. + * The routines in jdapimin.c will also be needed by a transcoder. + */ + +#define JPEG_INTERNALS +#include "jinclude8.h" +#include "jpeglib8.h" +#include "jlossy8.h" + + +/* Forward declarations */ +LOCAL(void) transdecode_master_selection JPP((j_decompress_ptr cinfo)); + + +/* + * Read the coefficient arrays from a JPEG file. + * jpeg_read_header must be completed before calling this. + * + * The entire image is read into a set of virtual coefficient-block arrays, + * one per component. The return value is a pointer to the array of + * virtual-array descriptors. These can be manipulated directly via the + * JPEG memory manager, or handed off to jpeg_write_coefficients(). + * To release the memory occupied by the virtual arrays, call + * jpeg_finish_decompress() when done with the data. + * + * An alternative usage is to simply obtain access to the coefficient arrays + * during a buffered-image-mode decompression operation. This is allowed + * after any jpeg_finish_output() call. The arrays can be accessed until + * jpeg_finish_decompress() is called. (Note that any call to the library + * may reposition the arrays, so don't rely on access_virt_barray() results + * to stay valid across library calls.) + * + * Returns NULL if suspended. This case need be checked only if + * a suspending data source is used. + */ + +GLOBAL(jvirt_barray_ptr *) +jpeg_read_coefficients (j_decompress_ptr cinfo) +{ + /* j_lossy_d_ptr decomp; */ + + /* Can't read coefficients from lossless streams */ + if (cinfo->process == JPROC_LOSSLESS) { + ERREXIT(cinfo, JERR_CANT_TRANSCODE); + return NULL; + } + + if (cinfo->global_state == DSTATE_READY) { + /* First call: initialize active modules */ + transdecode_master_selection(cinfo); + cinfo->global_state = DSTATE_RDCOEFS; + } + if (cinfo->global_state == DSTATE_RDCOEFS) { + /* Absorb whole file into the coef buffer */ + for (;;) { + int retcode; + /* Call progress monitor hook if present */ + if (cinfo->progress != NULL) + (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); + /* Absorb some more input */ + retcode = (*cinfo->inputctl->consume_input) (cinfo); + if (retcode == JPEG_SUSPENDED) + return NULL; + if (retcode == JPEG_REACHED_EOI) + break; + /* Advance progress counter if appropriate */ + if (cinfo->progress != NULL && + (retcode == JPEG_ROW_COMPLETED || retcode == JPEG_REACHED_SOS)) { + if (++cinfo->progress->pass_counter >= cinfo->progress->pass_limit) { + /* startup underestimated number of scans; ratchet up one scan */ + cinfo->progress->pass_limit += (long) cinfo->total_iMCU_rows; + } + } + } + /* Set state so that jpeg_finish_decompress does the right thing */ + cinfo->global_state = DSTATE_STOPPING; + } + /* At this point we should be in state DSTATE_STOPPING if being used + * standalone, or in state DSTATE_BUFIMAGE if being invoked to get access + * to the coefficients during a full buffered-image-mode decompression. + */ + if ((cinfo->global_state == DSTATE_STOPPING || + cinfo->global_state == DSTATE_BUFIMAGE) && cinfo->buffered_image) { + return ((j_lossy_d_ptr) cinfo->codec)->coef_arrays; + } + /* Oops, improper usage */ + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + return NULL; /* keep compiler happy */ +} + + +/* + * Master selection of decompression modules for transcoding. + * This substitutes for jdmaster.c's initialization of the full decompressor. + */ + +LOCAL(void) +transdecode_master_selection (j_decompress_ptr cinfo) +{ + /* This is effectively a buffered-image operation. */ + cinfo->buffered_image = TRUE; + + /* Initialize decompression codec */ + jinit_d_codec(cinfo); + + /* We can now tell the memory manager to allocate virtual arrays. */ + (*cinfo->mem->realize_virt_arrays) ((j_common_ptr) cinfo); + + /* Initialize input side of decompressor to consume first scan. */ + (*cinfo->inputctl->start_input_pass) (cinfo); + + /* Initialize progress monitoring. */ + if (cinfo->progress != NULL) { + int nscans; + /* Estimate number of scans to set pass_limit. */ + if (cinfo->process == JPROC_PROGRESSIVE) { + /* Arbitrarily estimate 2 interleaved DC scans + 3 AC scans/component. */ + nscans = 2 + 3 * cinfo->num_components; + } else if (cinfo->inputctl->has_multiple_scans) { + /* For a nonprogressive multiscan file, estimate 1 scan per component. */ + nscans = cinfo->num_components; + } else { + nscans = 1; + } + cinfo->progress->pass_counter = 0L; + cinfo->progress->pass_limit = (long) cinfo->total_iMCU_rows * nscans; + cinfo->progress->completed_passes = 0; + cinfo->progress->total_passes = 1; + } +} diff --git a/dcmjpeg/libijg8/jerror.c b/dcmjpeg/libijg8/jerror.c new file mode 100644 index 00000000..2850aab0 --- /dev/null +++ b/dcmjpeg/libijg8/jerror.c @@ -0,0 +1,252 @@ +/* + * jerror.c + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains simple error-reporting and trace-message routines. + * These are suitable for Unix-like systems and others where writing to + * stderr is the right thing to do. Many applications will want to replace + * some or all of these routines. + * + * If you define USE_WINDOWS_MESSAGEBOX in jconfig.h or in the makefile, + * you get a Windows-specific hack to display error messages in a dialog box. + * It ain't much, but it beats dropping error messages into the bit bucket, + * which is what happens to output to stderr under most Windows C compilers. + * + * These routines are used by both the compression and decompression code. + */ + +/* this is not a core library module, so it doesn't define JPEG_INTERNALS */ +#include "jinclude8.h" +#include "jpeglib8.h" +#include "jversion8.h" +#include "jerror8.h" + +#ifdef USE_WINDOWS_MESSAGEBOX +#include +#endif + +#ifndef EXIT_FAILURE /* define exit() codes if not provided */ +#define EXIT_FAILURE 1 +#endif + + +/* + * Create the message string table. + * We do this from the master message list in jerror.h by re-reading + * jerror.h with a suitable definition for macro JMESSAGE. + * The message table is made an external symbol just in case any applications + * want to refer to it directly. + */ + +#ifdef NEED_SHORT_EXTERNAL_NAMES +#define jpeg_std_message_table jpeg8_std_message_table +#endif + +#define JMESSAGE(code,string) string , + +const char * const jpeg_std_message_table[] = { +#include "jerror8.h" + NULL +}; + + +/* + * Error exit handler: must not return to caller. + * + * Applications may override this if they want to get control back after + * an error. Typically one would longjmp somewhere instead of exiting. + * The setjmp buffer can be made a private field within an expanded error + * handler object. Note that the info needed to generate an error message + * is stored in the error object, so you can generate the message now or + * later, at your convenience. + * You should make sure that the JPEG object is cleaned up (with jpeg_abort + * or jpeg_destroy) at some point. + */ + +METHODDEF(void) +error_exit (j_common_ptr cinfo) +{ + /* Always display the message */ + (*cinfo->err->output_message) (cinfo); + + /* Let the memory manager delete any temp files before we die */ + jpeg_destroy(cinfo); + + exit(EXIT_FAILURE); +} + + +/* + * Actual output of an error or trace message. + * Applications may override this method to send JPEG messages somewhere + * other than stderr. + * + * On Windows, printing to stderr is generally completely useless, + * so we provide optional code to produce an error-dialog popup. + * Most Windows applications will still prefer to override this routine, + * but if they don't, it'll do something at least marginally useful. + * + * NOTE: to use the library in an environment that doesn't support the + * C stdio library, you may have to delete the call to fprintf() entirely, + * not just not use this routine. + */ + +METHODDEF(void) +output_message (j_common_ptr cinfo) +{ + char buffer[JMSG_LENGTH_MAX]; + + /* Create the message */ + (*cinfo->err->format_message) (cinfo, buffer); + +#ifdef USE_WINDOWS_MESSAGEBOX + /* Display it in a message dialog box */ + MessageBox(GetActiveWindow(), buffer, "JPEG Library Error", + MB_OK | MB_ICONERROR); +#else + /* Send it to stderr, adding a newline */ + fprintf(stderr, "%s\n", buffer); +#endif +} + + +/* + * Decide whether to emit a trace or warning message. + * msg_level is one of: + * -1: recoverable corrupt-data warning, may want to abort. + * 0: important advisory messages (always display to user). + * 1: first level of tracing detail. + * 2,3,...: successively more detailed tracing messages. + * An application might override this method if it wanted to abort on warnings + * or change the policy about which messages to display. + */ + +METHODDEF(void) +emit_message (j_common_ptr cinfo, int msg_level) +{ + struct jpeg_error_mgr * err = cinfo->err; + + if (msg_level < 0) { + /* It's a warning message. Since corrupt files may generate many warnings, + * the policy implemented here is to show only the first warning, + * unless trace_level >= 3. + */ + if (err->num_warnings == 0 || err->trace_level >= 3) + (*err->output_message) (cinfo); + /* Always count warnings in num_warnings. */ + err->num_warnings++; + } else { + /* It's a trace message. Show it if trace_level >= msg_level. */ + if (err->trace_level >= msg_level) + (*err->output_message) (cinfo); + } +} + + +/* + * Format a message string for the most recent JPEG error or message. + * The message is stored into buffer, which should be at least JMSG_LENGTH_MAX + * characters. Note that no '\n' character is added to the string. + * Few applications should need to override this method. + */ + +METHODDEF(void) +format_message (j_common_ptr cinfo, char * buffer) +{ + struct jpeg_error_mgr * err = cinfo->err; + int msg_code = err->msg_code; + const char * msgtext = NULL; + const char * msgptr; + char ch; + boolean isstring; + + /* Look up message string in proper table */ + if (msg_code > 0 && msg_code <= err->last_jpeg_message) { + msgtext = err->jpeg_message_table[msg_code]; + } else if (err->addon_message_table != NULL && + msg_code >= err->first_addon_message && + msg_code <= err->last_addon_message) { + msgtext = err->addon_message_table[msg_code - err->first_addon_message]; + } + + /* Defend against bogus message number */ + if (msgtext == NULL) { + err->msg_parm.i[0] = msg_code; + msgtext = err->jpeg_message_table[0]; + } + + /* Check for string parameter, as indicated by %s in the message text */ + isstring = FALSE; + msgptr = msgtext; + while ((ch = *msgptr++) != '\0') { + if (ch == '%') { + if (*msgptr == 's') isstring = TRUE; + break; + } + } + + /* Format the message into the passed buffer */ + if (isstring) + sprintf(buffer, msgtext, err->msg_parm.s); + else + sprintf(buffer, msgtext, + err->msg_parm.i[0], err->msg_parm.i[1], + err->msg_parm.i[2], err->msg_parm.i[3], + err->msg_parm.i[4], err->msg_parm.i[5], + err->msg_parm.i[6], err->msg_parm.i[7]); +} + + +/* + * Reset error state variables at start of a new image. + * This is called during compression startup to reset trace/error + * processing to default state, without losing any application-specific + * method pointers. An application might possibly want to override + * this method if it has additional error processing state. + */ + +METHODDEF(void) +reset_error_mgr (j_common_ptr cinfo) +{ + cinfo->err->num_warnings = 0; + /* trace_level is not reset since it is an application-supplied parameter */ + cinfo->err->msg_code = 0; /* may be useful as a flag for "no error" */ +} + + +/* + * Fill in the standard error-handling methods in a jpeg_error_mgr object. + * Typical call is: + * struct jpeg_compress_struct cinfo; + * struct jpeg_error_mgr err; + * + * cinfo.err = jpeg_std_error(&err); + * after which the application may override some of the methods. + */ + +GLOBAL(struct jpeg_error_mgr *) +jpeg_std_error (struct jpeg_error_mgr * err) +{ + err->error_exit = error_exit; + err->emit_message = emit_message; + err->output_message = output_message; + err->format_message = format_message; + err->reset_error_mgr = reset_error_mgr; + + err->trace_level = 0; /* default = no tracing */ + err->num_warnings = 0; /* no warnings emitted yet */ + err->msg_code = 0; /* may be useful as a flag for "no error" */ + + /* Initialize message table pointers */ + err->jpeg_message_table = jpeg_std_message_table; + err->last_jpeg_message = (int) JMSG_LASTMSGCODE - 1; + + err->addon_message_table = NULL; + err->first_addon_message = 0; /* for safety */ + err->last_addon_message = 0; + + return err; +} diff --git a/dcmjpeg/libijg8/jerror8.h b/dcmjpeg/libijg8/jerror8.h new file mode 100644 index 00000000..d90bd1c1 --- /dev/null +++ b/dcmjpeg/libijg8/jerror8.h @@ -0,0 +1,310 @@ +/* + * jerror.h + * + * Copyright (C) 1994-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file defines the error and message codes for the JPEG library. + * Edit this file to add new codes, or to translate the message strings to + * some other language. + * A set of error-reporting macros are defined too. Some applications using + * the JPEG library may wish to include this file to get the error codes + * and/or the macros. + */ + +/* + * To define the enum list of message codes, include this file without + * defining macro JMESSAGE. To create a message string table, include it + * again with a suitable JMESSAGE definition (see jerror.c for an example). + */ +#ifndef JMESSAGE +#ifndef JERROR_H +/* First time through, define the enum list */ +#define JMAKE_ENUM_LIST +#else +/* Repeated inclusions of this file are no-ops unless JMESSAGE is defined */ +#define JMESSAGE(code,string) +#endif /* JERROR_H */ +#endif /* JMESSAGE */ + +#ifdef JMAKE_ENUM_LIST + +typedef enum { + +#define JMESSAGE(code,string) code , + +#endif /* JMAKE_ENUM_LIST */ + +JMESSAGE(JMSG_NOMESSAGE, "Bogus message code %d") /* Must be first entry! */ + +/* For maintenance convenience, list is alphabetical by message code name */ +JMESSAGE(JERR_ARITH_NOTIMPL, + "Sorry, there are legal restrictions on arithmetic coding") +JMESSAGE(JERR_BAD_ALIGN_TYPE, "ALIGN_TYPE is wrong, please fix") +JMESSAGE(JERR_BAD_ALLOC_CHUNK, "MAX_ALLOC_CHUNK is wrong, please fix") +JMESSAGE(JERR_BAD_BUFFER_MODE, "Bogus buffer control mode") +JMESSAGE(JERR_BAD_COMPONENT_ID, "Invalid component ID %d in SOS") +JMESSAGE(JERR_BAD_DCT_COEF, "DCT coefficient out of range") +JMESSAGE(JERR_BAD_DCTSIZE, "IDCT output block size %d not supported") +JMESSAGE(JERR_BAD_DIFF, "spatial difference out of range") +JMESSAGE(JERR_BAD_HUFF_TABLE, "Bogus Huffman table definition") +JMESSAGE(JERR_BAD_IN_COLORSPACE, "Bogus input colorspace") +JMESSAGE(JERR_BAD_J_COLORSPACE, "Bogus JPEG colorspace") +JMESSAGE(JERR_BAD_LENGTH, "Bogus marker length") +JMESSAGE(JERR_BAD_LIB_VERSION, + "Wrong JPEG library version: library is %d, caller expects %d") +JMESSAGE(JERR_BAD_LOSSLESS, + "Invalid lossless parameters Ss=%d Se=%d Ah=%d Al=%d") +JMESSAGE(JERR_BAD_LOSSLESS_SCRIPT, + "Invalid lossless parameters at scan script entry %d") +JMESSAGE(JERR_BAD_MCU_SIZE, "Sampling factors too large for interleaved scan") +JMESSAGE(JERR_BAD_POOL_ID, "Invalid memory pool code %d") +JMESSAGE(JERR_BAD_PRECISION, "Unsupported JPEG data precision %d") +JMESSAGE(JERR_BAD_PROGRESSION, + "Invalid progressive parameters Ss=%d Se=%d Ah=%d Al=%d") +JMESSAGE(JERR_BAD_PROG_SCRIPT, + "Invalid progressive parameters at scan script entry %d") +JMESSAGE(JERR_BAD_RESTART, "Invalid restart interval: %d, must be an integer multiple of the number of MCUs in an MCU_row (%d)") +JMESSAGE(JERR_BAD_SAMPLING, "Bogus sampling factors") +JMESSAGE(JERR_BAD_SCAN_SCRIPT, "Invalid scan script at entry %d") +JMESSAGE(JERR_BAD_STATE, "Improper call to JPEG library in state %d") +JMESSAGE(JERR_BAD_STRUCT_SIZE, + "JPEG parameter struct mismatch: library thinks size is %u, caller expects %u") +JMESSAGE(JERR_BAD_VIRTUAL_ACCESS, "Bogus virtual array access") +JMESSAGE(JERR_BUFFER_SIZE, "Buffer passed to JPEG library is too small") +JMESSAGE(JERR_CANT_SUSPEND, "Suspension not allowed here") +JMESSAGE(JERR_CANT_TRANSCODE, + "Cannot transcode to/from lossless JPEG datastreams") +JMESSAGE(JERR_CCIR601_NOTIMPL, "CCIR601 sampling not implemented yet") +JMESSAGE(JERR_COMPONENT_COUNT, "Too many color components: %d, max %d") +JMESSAGE(JERR_CONVERSION_NOTIMPL, "Unsupported color conversion request") +JMESSAGE(JERR_DAC_INDEX, "Bogus DAC index %d") +JMESSAGE(JERR_DAC_VALUE, "Bogus DAC value 0x%x") +JMESSAGE(JERR_DHT_INDEX, "Bogus DHT index %d") +JMESSAGE(JERR_DQT_INDEX, "Bogus DQT index %d") +JMESSAGE(JERR_EMPTY_IMAGE, "Empty JPEG image (DNL not supported)") +JMESSAGE(JERR_EMS_READ, "Read from EMS failed") +JMESSAGE(JERR_EMS_WRITE, "Write to EMS failed") +JMESSAGE(JERR_EOI_EXPECTED, "Didn't expect more than one scan") +JMESSAGE(JERR_FILE_READ, "Input file read error") +JMESSAGE(JERR_FILE_WRITE, "Output file write error --- out of disk space?") +JMESSAGE(JERR_FRACT_SAMPLE_NOTIMPL, "Fractional sampling not implemented yet") +JMESSAGE(JERR_HUFF_CLEN_OVERFLOW, "Huffman code size table overflow") +JMESSAGE(JERR_HUFF_MISSING_CODE, "Missing Huffman code table entry") +JMESSAGE(JERR_IMAGE_TOO_BIG, "Maximum supported image dimension is %u pixels") +JMESSAGE(JERR_INPUT_EMPTY, "Empty input file") +JMESSAGE(JERR_INPUT_EOF, "Premature end of input file") +JMESSAGE(JERR_MISMATCHED_QUANT_TABLE, + "Cannot transcode due to multiple use of quantization table %d") +JMESSAGE(JERR_MISSING_DATA, "Scan script does not transmit all data") +JMESSAGE(JERR_MODE_CHANGE, "Invalid color quantization mode change") +JMESSAGE(JERR_NOTIMPL, "Not implemented yet") +JMESSAGE(JERR_NOT_COMPILED, "Requested feature was omitted at compile time") +#ifdef WITH_ARITHMETIC_PATCH +JMESSAGE(JERR_NO_ARITH_TABLE, "Arithmetic table 0x%02x was not defined") +#endif +JMESSAGE(JERR_NO_BACKING_STORE, "Backing store not supported") +JMESSAGE(JERR_NO_HUFF_TABLE, "Huffman table 0x%02x was not defined") +JMESSAGE(JERR_NO_IMAGE, "JPEG datastream contains no image") +JMESSAGE(JERR_NO_LOSSLESS_SCRIPT, "Lossless encoding was requested but no scan script was supplied") +JMESSAGE(JERR_NO_QUANT_TABLE, "Quantization table 0x%02x was not defined") +JMESSAGE(JERR_NO_SOI, "Not a JPEG file: starts with 0x%02x 0x%02x") +JMESSAGE(JERR_OUT_OF_MEMORY, "Insufficient memory (case %d)") +JMESSAGE(JERR_QUANT_COMPONENTS, + "Cannot quantize more than %d color components") +JMESSAGE(JERR_QUANT_FEW_COLORS, "Cannot quantize to fewer than %d colors") +JMESSAGE(JERR_QUANT_MANY_COLORS, "Cannot quantize to more than %d colors") +JMESSAGE(JERR_SOF_DUPLICATE, "Invalid JPEG file structure: two SOF markers") +JMESSAGE(JERR_SOF_NO_SOS, "Invalid JPEG file structure: missing SOS marker") +JMESSAGE(JERR_SOF_UNSUPPORTED, "Unsupported JPEG process: SOF type 0x%02x") +JMESSAGE(JERR_SOI_DUPLICATE, "Invalid JPEG file structure: two SOI markers") +JMESSAGE(JERR_SOS_NO_SOF, "Invalid JPEG file structure: SOS before SOF") +JMESSAGE(JERR_TFILE_CREATE, "Failed to create temporary file %s") +JMESSAGE(JERR_TFILE_READ, "Read failed on temporary file") +JMESSAGE(JERR_TFILE_SEEK, "Seek failed on temporary file") +JMESSAGE(JERR_TFILE_WRITE, + "Write failed on temporary file --- out of disk space?") +JMESSAGE(JERR_TOO_LITTLE_DATA, "Application transferred too few scanlines") +JMESSAGE(JERR_UNKNOWN_MARKER, "Unsupported marker type 0x%02x") +JMESSAGE(JERR_VIRTUAL_BUG, "Virtual array controller messed up") +JMESSAGE(JERR_WIDTH_OVERFLOW, "Image too wide for this implementation") +JMESSAGE(JERR_XMS_READ, "Read from XMS failed") +JMESSAGE(JERR_XMS_WRITE, "Write to XMS failed") +JMESSAGE(JMSG_COPYRIGHT, JCOPYRIGHT) +JMESSAGE(JMSG_VERSION, JVERSION) +JMESSAGE(JTRC_16BIT_TABLES, + "Caution: quantization tables are too coarse for baseline JPEG") +JMESSAGE(JTRC_ADOBE, + "Adobe APP14 marker: version %d, flags 0x%04x 0x%04x, transform %d") +JMESSAGE(JTRC_APP0, "Unknown APP0 marker (not JFIF), length %u") +JMESSAGE(JTRC_APP14, "Unknown APP14 marker (not Adobe), length %u") +JMESSAGE(JTRC_DAC, "Define Arithmetic Table 0x%02x: 0x%02x") +JMESSAGE(JTRC_DHT, "Define Huffman Table 0x%02x") +JMESSAGE(JTRC_DQT, "Define Quantization Table %d precision %d") +JMESSAGE(JTRC_DRI, "Define Restart Interval %u") +JMESSAGE(JTRC_EMS_CLOSE, "Freed EMS handle %u") +JMESSAGE(JTRC_EMS_OPEN, "Obtained EMS handle %u") +JMESSAGE(JTRC_EOI, "End Of Image") +JMESSAGE(JTRC_HUFFBITS, " %3d %3d %3d %3d %3d %3d %3d %3d") +JMESSAGE(JTRC_JFIF, "JFIF APP0 marker: version %d.%02d, density %dx%d %d") +JMESSAGE(JTRC_JFIF_BADTHUMBNAILSIZE, + "Warning: thumbnail image size does not match data length %u") +JMESSAGE(JTRC_JFIF_EXTENSION, + "JFIF extension marker: type 0x%02x, length %u") +JMESSAGE(JTRC_JFIF_THUMBNAIL, " with %d x %d thumbnail image") +JMESSAGE(JTRC_MISC_MARKER, "Miscellaneous marker 0x%02x, length %u") +JMESSAGE(JTRC_PARMLESS_MARKER, "Unexpected marker 0x%02x") +JMESSAGE(JTRC_QUANTVALS, " %4u %4u %4u %4u %4u %4u %4u %4u") +JMESSAGE(JTRC_QUANT_3_NCOLORS, "Quantizing to %d = %d*%d*%d colors") +JMESSAGE(JTRC_QUANT_NCOLORS, "Quantizing to %d colors") +JMESSAGE(JTRC_QUANT_SELECTED, "Selected %d colors for quantization") +JMESSAGE(JTRC_RECOVERY_ACTION, "At marker 0x%02x, recovery action %d") +JMESSAGE(JTRC_RST, "RST%d") +JMESSAGE(JTRC_SMOOTH_NOTIMPL, + "Smoothing not supported with nonstandard sampling ratios") +JMESSAGE(JTRC_SOF, "Start Of Frame 0x%02x: width=%u, height=%u, components=%d") +JMESSAGE(JTRC_SOF_COMPONENT, " Component %d: %dhx%dv q=%d") +JMESSAGE(JTRC_SOI, "Start of Image") +JMESSAGE(JTRC_SOS, "Start Of Scan: %d components") +JMESSAGE(JTRC_SOS_COMPONENT, " Component %d: dc=%d ac=%d") +JMESSAGE(JTRC_SOS_PARAMS, " Ss=%d, Se=%d, Ah=%d, Al=%d") +JMESSAGE(JTRC_TFILE_CLOSE, "Closed temporary file %s") +JMESSAGE(JTRC_TFILE_OPEN, "Opened temporary file %s") +JMESSAGE(JTRC_THUMB_JPEG, + "JFIF extension marker: JPEG-compressed thumbnail image, length %u") +JMESSAGE(JTRC_THUMB_PALETTE, + "JFIF extension marker: palette thumbnail image, length %u") +JMESSAGE(JTRC_THUMB_RGB, + "JFIF extension marker: RGB thumbnail image, length %u") +JMESSAGE(JTRC_UNKNOWN_LOSSLESS_IDS, + "Unrecognized component IDs %d %d %d, assuming RGB") +JMESSAGE(JTRC_UNKNOWN_LOSSY_IDS, + "Unrecognized component IDs %d %d %d, assuming YCbCr") +JMESSAGE(JTRC_XMS_CLOSE, "Freed XMS handle %u") +JMESSAGE(JTRC_XMS_OPEN, "Obtained XMS handle %u") +JMESSAGE(JWRN_ADOBE_XFORM, "Unknown Adobe color transform code %d") +#ifdef WITH_ARITHMETIC_PATCH +JMESSAGE(JWRN_ARITH_BAD_CODE, "Corrupt JPEG data: bad arithmetic code") +#endif +JMESSAGE(JWRN_BOGUS_PROGRESSION, + "Inconsistent progression sequence for component %d coefficient %d") +JMESSAGE(JWRN_EXTRANEOUS_DATA, + "Corrupt JPEG data: %u extraneous bytes before marker 0x%02x") +JMESSAGE(JWRN_HIT_MARKER, "Corrupt JPEG data: premature end of data segment") +JMESSAGE(JWRN_HUFF_BAD_CODE, "Corrupt JPEG data: bad Huffman code") +JMESSAGE(JWRN_JFIF_MAJOR, "Warning: unknown JFIF revision number %d.%02d") +JMESSAGE(JWRN_JPEG_EOF, "Premature end of JPEG file") +JMESSAGE(JWRN_MUST_DOWNSCALE, + "Must downscale data from %d bits to %d") +JMESSAGE(JWRN_MUST_RESYNC, + "Corrupt JPEG data: found marker 0x%02x instead of RST%d") +JMESSAGE(JWRN_NOT_SEQUENTIAL, "Invalid SOS parameters for sequential JPEG") +JMESSAGE(JWRN_TOO_MUCH_DATA, "Application transferred too many scanlines") + +#ifdef JMAKE_ENUM_LIST + + JMSG_LASTMSGCODE +} J_MESSAGE_CODE; + +#undef JMAKE_ENUM_LIST +#endif /* JMAKE_ENUM_LIST */ + +/* Zap JMESSAGE macro so that future re-inclusions do nothing by default */ +#undef JMESSAGE + + +#ifndef JERROR_H +#define JERROR_H + +/* Macros to simplify using the error and trace message stuff */ +/* The first parameter is either type of cinfo pointer */ + +/* Fatal errors (print message and exit) */ +#define ERREXIT(cinfo,code) \ + ((cinfo)->err->msg_code = (code), \ + (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) +#define ERREXIT1(cinfo,code,p1) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) +#define ERREXIT2(cinfo,code,p1,p2) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) +#define ERREXIT3(cinfo,code,p1,p2,p3) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (cinfo)->err->msg_parm.i[2] = (p3), \ + (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) +#define ERREXIT4(cinfo,code,p1,p2,p3,p4) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (cinfo)->err->msg_parm.i[2] = (p3), \ + (cinfo)->err->msg_parm.i[3] = (p4), \ + (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) +#define ERREXITS(cinfo,code,str) \ + ((cinfo)->err->msg_code = (code), \ + strncpy((cinfo)->err->msg_parm.s, (str), JMSG_STR_PARM_MAX), \ + (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) + +#define MAKESTMT(stuff) do { stuff } while (0) + +/* Nonfatal errors (we can keep going, but the data is probably corrupt) */ +#define WARNMS(cinfo,code) \ + ((cinfo)->err->msg_code = (code), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1)) +#define WARNMS1(cinfo,code,p1) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1)) +#define WARNMS2(cinfo,code,p1,p2) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1)) + +/* Informational/debugging messages */ +#define TRACEMS(cinfo,lvl,code) \ + ((cinfo)->err->msg_code = (code), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl))) +#define TRACEMS1(cinfo,lvl,code,p1) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl))) +#define TRACEMS2(cinfo,lvl,code,p1,p2) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl))) +#define TRACEMS3(cinfo,lvl,code,p1,p2,p3) \ + MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \ + _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); \ + (cinfo)->err->msg_code = (code); \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); ) +#define TRACEMS4(cinfo,lvl,code,p1,p2,p3,p4) \ + MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \ + _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \ + (cinfo)->err->msg_code = (code); \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); ) +#define TRACEMS5(cinfo,lvl,code,p1,p2,p3,p4,p5) \ + MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \ + _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \ + _mp[4] = (p5); \ + (cinfo)->err->msg_code = (code); \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); ) +#define TRACEMS8(cinfo,lvl,code,p1,p2,p3,p4,p5,p6,p7,p8) \ + MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \ + _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \ + _mp[4] = (p5); _mp[5] = (p6); _mp[6] = (p7); _mp[7] = (p8); \ + (cinfo)->err->msg_code = (code); \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); ) +#define TRACEMSS(cinfo,lvl,code,str) \ + ((cinfo)->err->msg_code = (code), \ + strncpy((cinfo)->err->msg_parm.s, (str), JMSG_STR_PARM_MAX), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl))) + +#endif /* JERROR_H */ diff --git a/dcmjpeg/libijg8/jfdctflt.c b/dcmjpeg/libijg8/jfdctflt.c new file mode 100644 index 00000000..988a6a67 --- /dev/null +++ b/dcmjpeg/libijg8/jfdctflt.c @@ -0,0 +1,168 @@ +/* + * jfdctflt.c + * + * Copyright (C) 1994-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains a floating-point implementation of the + * forward DCT (Discrete Cosine Transform). + * + * This implementation should be more accurate than either of the integer + * DCT implementations. However, it may not give the same results on all + * machines because of differences in roundoff behavior. Speed will depend + * on the hardware's floating point capacity. + * + * A 2-D DCT can be done by 1-D DCT on each row followed by 1-D DCT + * on each column. Direct algorithms are also available, but they are + * much more complex and seem not to be any faster when reduced to code. + * + * This implementation is based on Arai, Agui, and Nakajima's algorithm for + * scaled DCT. Their original paper (Trans. IEICE E-71(11):1095) is in + * Japanese, but the algorithm is described in the Pennebaker & Mitchell + * JPEG textbook (see REFERENCES section in file README). The following code + * is based directly on figure 4-8 in P&M. + * While an 8-point DCT cannot be done in less than 11 multiplies, it is + * possible to arrange the computation so that many of the multiplies are + * simple scalings of the final outputs. These multiplies can then be + * folded into the multiplications or divisions by the JPEG quantization + * table entries. The AA&N method leaves only 5 multiplies and 29 adds + * to be done in the DCT itself. + * The primary disadvantage of this method is that with a fixed-point + * implementation, accuracy is lost due to imprecise representation of the + * scaled quantization values. However, that problem does not arise if + * we use floating point arithmetic. + */ + +#define JPEG_INTERNALS +#include "jinclude8.h" +#include "jpeglib8.h" +#include "jdct8.h" /* Private declarations for DCT subsystem */ + +#ifdef DCT_FLOAT_SUPPORTED + + +/* + * This module is specialized to the case DCTSIZE = 8. + */ + +#if DCTSIZE != 8 + Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */ +#endif + + +/* + * Perform the forward DCT on one block of samples. + */ + +GLOBAL(void) +jpeg_fdct_float (FAST_FLOAT * data) +{ + FAST_FLOAT tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + FAST_FLOAT tmp10, tmp11, tmp12, tmp13; + FAST_FLOAT z1, z2, z3, z4, z5, z11, z13; + FAST_FLOAT *dataptr; + int ctr; + + /* Pass 1: process rows. */ + + dataptr = data; + for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { + tmp0 = dataptr[0] + dataptr[7]; + tmp7 = dataptr[0] - dataptr[7]; + tmp1 = dataptr[1] + dataptr[6]; + tmp6 = dataptr[1] - dataptr[6]; + tmp2 = dataptr[2] + dataptr[5]; + tmp5 = dataptr[2] - dataptr[5]; + tmp3 = dataptr[3] + dataptr[4]; + tmp4 = dataptr[3] - dataptr[4]; + + /* Even part */ + + tmp10 = tmp0 + tmp3; /* phase 2 */ + tmp13 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp1 - tmp2; + + dataptr[0] = tmp10 + tmp11; /* phase 3 */ + dataptr[4] = tmp10 - tmp11; + + z1 = (tmp12 + tmp13) * ((FAST_FLOAT) 0.707106781); /* c4 */ + dataptr[2] = tmp13 + z1; /* phase 5 */ + dataptr[6] = tmp13 - z1; + + /* Odd part */ + + tmp10 = tmp4 + tmp5; /* phase 2 */ + tmp11 = tmp5 + tmp6; + tmp12 = tmp6 + tmp7; + + /* The rotator is modified from fig 4-8 to avoid extra negations. */ + z5 = (tmp10 - tmp12) * ((FAST_FLOAT) 0.382683433); /* c6 */ + z2 = ((FAST_FLOAT) 0.541196100) * tmp10 + z5; /* c2-c6 */ + z4 = ((FAST_FLOAT) 1.306562965) * tmp12 + z5; /* c2+c6 */ + z3 = tmp11 * ((FAST_FLOAT) 0.707106781); /* c4 */ + + z11 = tmp7 + z3; /* phase 5 */ + z13 = tmp7 - z3; + + dataptr[5] = z13 + z2; /* phase 6 */ + dataptr[3] = z13 - z2; + dataptr[1] = z11 + z4; + dataptr[7] = z11 - z4; + + dataptr += DCTSIZE; /* advance pointer to next row */ + } + + /* Pass 2: process columns. */ + + dataptr = data; + for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { + tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*7]; + tmp7 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*7]; + tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*6]; + tmp6 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*6]; + tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*5]; + tmp5 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*5]; + tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*4]; + tmp4 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*4]; + + /* Even part */ + + tmp10 = tmp0 + tmp3; /* phase 2 */ + tmp13 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp1 - tmp2; + + dataptr[DCTSIZE*0] = tmp10 + tmp11; /* phase 3 */ + dataptr[DCTSIZE*4] = tmp10 - tmp11; + + z1 = (tmp12 + tmp13) * ((FAST_FLOAT) 0.707106781); /* c4 */ + dataptr[DCTSIZE*2] = tmp13 + z1; /* phase 5 */ + dataptr[DCTSIZE*6] = tmp13 - z1; + + /* Odd part */ + + tmp10 = tmp4 + tmp5; /* phase 2 */ + tmp11 = tmp5 + tmp6; + tmp12 = tmp6 + tmp7; + + /* The rotator is modified from fig 4-8 to avoid extra negations. */ + z5 = (tmp10 - tmp12) * ((FAST_FLOAT) 0.382683433); /* c6 */ + z2 = ((FAST_FLOAT) 0.541196100) * tmp10 + z5; /* c2-c6 */ + z4 = ((FAST_FLOAT) 1.306562965) * tmp12 + z5; /* c2+c6 */ + z3 = tmp11 * ((FAST_FLOAT) 0.707106781); /* c4 */ + + z11 = tmp7 + z3; /* phase 5 */ + z13 = tmp7 - z3; + + dataptr[DCTSIZE*5] = z13 + z2; /* phase 6 */ + dataptr[DCTSIZE*3] = z13 - z2; + dataptr[DCTSIZE*1] = z11 + z4; + dataptr[DCTSIZE*7] = z11 - z4; + + dataptr++; /* advance pointer to next column */ + } +} + +#endif /* DCT_FLOAT_SUPPORTED */ diff --git a/dcmjpeg/libijg8/jfdctfst.c b/dcmjpeg/libijg8/jfdctfst.c new file mode 100644 index 00000000..1c124bda --- /dev/null +++ b/dcmjpeg/libijg8/jfdctfst.c @@ -0,0 +1,224 @@ +/* + * jfdctfst.c + * + * Copyright (C) 1994-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains a fast, not so accurate integer implementation of the + * forward DCT (Discrete Cosine Transform). + * + * A 2-D DCT can be done by 1-D DCT on each row followed by 1-D DCT + * on each column. Direct algorithms are also available, but they are + * much more complex and seem not to be any faster when reduced to code. + * + * This implementation is based on Arai, Agui, and Nakajima's algorithm for + * scaled DCT. Their original paper (Trans. IEICE E-71(11):1095) is in + * Japanese, but the algorithm is described in the Pennebaker & Mitchell + * JPEG textbook (see REFERENCES section in file README). The following code + * is based directly on figure 4-8 in P&M. + * While an 8-point DCT cannot be done in less than 11 multiplies, it is + * possible to arrange the computation so that many of the multiplies are + * simple scalings of the final outputs. These multiplies can then be + * folded into the multiplications or divisions by the JPEG quantization + * table entries. The AA&N method leaves only 5 multiplies and 29 adds + * to be done in the DCT itself. + * The primary disadvantage of this method is that with fixed-point math, + * accuracy is lost due to imprecise representation of the scaled + * quantization values. The smaller the quantization table entry, the less + * precise the scaled value, so this implementation does worse with high- + * quality-setting files than with low-quality ones. + */ + +#define JPEG_INTERNALS +#include "jinclude8.h" +#include "jpeglib8.h" +#include "jdct8.h" /* Private declarations for DCT subsystem */ + +#ifdef DCT_IFAST_SUPPORTED + + +/* + * This module is specialized to the case DCTSIZE = 8. + */ + +#if DCTSIZE != 8 + Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */ +#endif + + +/* Scaling decisions are generally the same as in the LL&M algorithm; + * see jfdctint.c for more details. However, we choose to descale + * (right shift) multiplication products as soon as they are formed, + * rather than carrying additional fractional bits into subsequent additions. + * This compromises accuracy slightly, but it lets us save a few shifts. + * More importantly, 16-bit arithmetic is then adequate (for 8-bit samples) + * everywhere except in the multiplications proper; this saves a good deal + * of work on 16-bit-int machines. + * + * Again to save a few shifts, the intermediate results between pass 1 and + * pass 2 are not upscaled, but are represented only to integral precision. + * + * A final compromise is to represent the multiplicative constants to only + * 8 fractional bits, rather than 13. This saves some shifting work on some + * machines, and may also reduce the cost of multiplication (since there + * are fewer one-bits in the constants). + */ + +#define CONST_BITS 8 + + +/* Some C compilers fail to reduce "FIX(constant)" at compile time, thus + * causing a lot of useless floating-point operations at run time. + * To get around this we use the following pre-calculated constants. + * If you change CONST_BITS you may want to add appropriate values. + * (With a reasonable C compiler, you can just rely on the FIX() macro...) + */ + +#if CONST_BITS == 8 +#define FIX_0_382683433 ((IJG_INT32) 98) /* FIX(0.382683433) */ +#define FIX_0_541196100 ((IJG_INT32) 139) /* FIX(0.541196100) */ +#define FIX_0_707106781 ((IJG_INT32) 181) /* FIX(0.707106781) */ +#define FIX_1_306562965 ((IJG_INT32) 334) /* FIX(1.306562965) */ +#else +#define FIX_0_382683433 FIX(0.382683433) +#define FIX_0_541196100 FIX(0.541196100) +#define FIX_0_707106781 FIX(0.707106781) +#define FIX_1_306562965 FIX(1.306562965) +#endif + + +/* We can gain a little more speed, with a further compromise in accuracy, + * by omitting the addition in a descaling shift. This yields an incorrectly + * rounded result half the time... + */ + +#ifndef USE_ACCURATE_ROUNDING +#undef DESCALE +#define DESCALE(x,n) RIGHT_SHIFT(x, n) +#endif + + +/* Multiply a DCTELEM variable by an IJG_INT32 constant, and immediately + * descale to yield a DCTELEM result. + */ + +#define MULTIPLY(var,const) ((DCTELEM) DESCALE((var) * (const), CONST_BITS)) + + +/* + * Perform the forward DCT on one block of samples. + */ + +GLOBAL(void) +jpeg_fdct_ifast (DCTELEM * data) +{ + DCTELEM tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + DCTELEM tmp10, tmp11, tmp12, tmp13; + DCTELEM z1, z2, z3, z4, z5, z11, z13; + DCTELEM *dataptr; + int ctr; + SHIFT_TEMPS + + /* Pass 1: process rows. */ + + dataptr = data; + for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { + tmp0 = dataptr[0] + dataptr[7]; + tmp7 = dataptr[0] - dataptr[7]; + tmp1 = dataptr[1] + dataptr[6]; + tmp6 = dataptr[1] - dataptr[6]; + tmp2 = dataptr[2] + dataptr[5]; + tmp5 = dataptr[2] - dataptr[5]; + tmp3 = dataptr[3] + dataptr[4]; + tmp4 = dataptr[3] - dataptr[4]; + + /* Even part */ + + tmp10 = tmp0 + tmp3; /* phase 2 */ + tmp13 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp1 - tmp2; + + dataptr[0] = tmp10 + tmp11; /* phase 3 */ + dataptr[4] = tmp10 - tmp11; + + z1 = MULTIPLY(tmp12 + tmp13, FIX_0_707106781); /* c4 */ + dataptr[2] = tmp13 + z1; /* phase 5 */ + dataptr[6] = tmp13 - z1; + + /* Odd part */ + + tmp10 = tmp4 + tmp5; /* phase 2 */ + tmp11 = tmp5 + tmp6; + tmp12 = tmp6 + tmp7; + + /* The rotator is modified from fig 4-8 to avoid extra negations. */ + z5 = MULTIPLY(tmp10 - tmp12, FIX_0_382683433); /* c6 */ + z2 = MULTIPLY(tmp10, FIX_0_541196100) + z5; /* c2-c6 */ + z4 = MULTIPLY(tmp12, FIX_1_306562965) + z5; /* c2+c6 */ + z3 = MULTIPLY(tmp11, FIX_0_707106781); /* c4 */ + + z11 = tmp7 + z3; /* phase 5 */ + z13 = tmp7 - z3; + + dataptr[5] = z13 + z2; /* phase 6 */ + dataptr[3] = z13 - z2; + dataptr[1] = z11 + z4; + dataptr[7] = z11 - z4; + + dataptr += DCTSIZE; /* advance pointer to next row */ + } + + /* Pass 2: process columns. */ + + dataptr = data; + for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { + tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*7]; + tmp7 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*7]; + tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*6]; + tmp6 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*6]; + tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*5]; + tmp5 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*5]; + tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*4]; + tmp4 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*4]; + + /* Even part */ + + tmp10 = tmp0 + tmp3; /* phase 2 */ + tmp13 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp1 - tmp2; + + dataptr[DCTSIZE*0] = tmp10 + tmp11; /* phase 3 */ + dataptr[DCTSIZE*4] = tmp10 - tmp11; + + z1 = MULTIPLY(tmp12 + tmp13, FIX_0_707106781); /* c4 */ + dataptr[DCTSIZE*2] = tmp13 + z1; /* phase 5 */ + dataptr[DCTSIZE*6] = tmp13 - z1; + + /* Odd part */ + + tmp10 = tmp4 + tmp5; /* phase 2 */ + tmp11 = tmp5 + tmp6; + tmp12 = tmp6 + tmp7; + + /* The rotator is modified from fig 4-8 to avoid extra negations. */ + z5 = MULTIPLY(tmp10 - tmp12, FIX_0_382683433); /* c6 */ + z2 = MULTIPLY(tmp10, FIX_0_541196100) + z5; /* c2-c6 */ + z4 = MULTIPLY(tmp12, FIX_1_306562965) + z5; /* c2+c6 */ + z3 = MULTIPLY(tmp11, FIX_0_707106781); /* c4 */ + + z11 = tmp7 + z3; /* phase 5 */ + z13 = tmp7 - z3; + + dataptr[DCTSIZE*5] = z13 + z2; /* phase 6 */ + dataptr[DCTSIZE*3] = z13 - z2; + dataptr[DCTSIZE*1] = z11 + z4; + dataptr[DCTSIZE*7] = z11 - z4; + + dataptr++; /* advance pointer to next column */ + } +} + +#endif /* DCT_IFAST_SUPPORTED */ diff --git a/dcmjpeg/libijg8/jfdctint.c b/dcmjpeg/libijg8/jfdctint.c new file mode 100644 index 00000000..984c2208 --- /dev/null +++ b/dcmjpeg/libijg8/jfdctint.c @@ -0,0 +1,283 @@ +/* + * jfdctint.c + * + * Copyright (C) 1991-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains a slow-but-accurate integer implementation of the + * forward DCT (Discrete Cosine Transform). + * + * A 2-D DCT can be done by 1-D DCT on each row followed by 1-D DCT + * on each column. Direct algorithms are also available, but they are + * much more complex and seem not to be any faster when reduced to code. + * + * This implementation is based on an algorithm described in + * C. Loeffler, A. Ligtenberg and G. Moschytz, "Practical Fast 1-D DCT + * Algorithms with 11 Multiplications", Proc. Int'l. Conf. on Acoustics, + * Speech, and Signal Processing 1989 (ICASSP '89), pp. 988-991. + * The primary algorithm described there uses 11 multiplies and 29 adds. + * We use their alternate method with 12 multiplies and 32 adds. + * The advantage of this method is that no data path contains more than one + * multiplication; this allows a very simple and accurate implementation in + * scaled fixed-point arithmetic, with a minimal number of shifts. + */ + +#define JPEG_INTERNALS +#include "jinclude8.h" +#include "jpeglib8.h" +#include "jdct8.h" /* Private declarations for DCT subsystem */ + +#ifdef DCT_ISLOW_SUPPORTED + + +/* + * This module is specialized to the case DCTSIZE = 8. + */ + +#if DCTSIZE != 8 + Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */ +#endif + + +/* + * The poop on this scaling stuff is as follows: + * + * Each 1-D DCT step produces outputs which are a factor of sqrt(N) + * larger than the true DCT outputs. The final outputs are therefore + * a factor of N larger than desired; since N=8 this can be cured by + * a simple right shift at the end of the algorithm. The advantage of + * this arrangement is that we save two multiplications per 1-D DCT, + * because the y0 and y4 outputs need not be divided by sqrt(N). + * In the IJG code, this factor of 8 is removed by the quantization step + * (in jcdctmgr.c), NOT in this module. + * + * We have to do addition and subtraction of the integer inputs, which + * is no problem, and multiplication by fractional constants, which is + * a problem to do in integer arithmetic. We multiply all the constants + * by CONST_SCALE and convert them to integer constants (thus retaining + * CONST_BITS bits of precision in the constants). After doing a + * multiplication we have to divide the product by CONST_SCALE, with proper + * rounding, to produce the correct output. This division can be done + * cheaply as a right shift of CONST_BITS bits. We postpone shifting + * as long as possible so that partial sums can be added together with + * full fractional precision. + * + * The outputs of the first pass are scaled up by PASS1_BITS bits so that + * they are represented to better-than-integral precision. These outputs + * require BITS_IN_JSAMPLE + PASS1_BITS + 3 bits; this fits in a 16-bit word + * with the recommended scaling. (For 12-bit sample data, the intermediate + * array is IJG_INT32 anyway.) + * + * To avoid overflow of the 32-bit intermediate results in pass 2, we must + * have BITS_IN_JSAMPLE + CONST_BITS + PASS1_BITS <= 26. Error analysis + * shows that the values given below are the most effective. + */ + +#if BITS_IN_JSAMPLE == 8 +#define CONST_BITS 13 +#define PASS1_BITS 2 +#else +#define CONST_BITS 13 +#define PASS1_BITS 1 /* lose a little precision to avoid overflow */ +#endif + +/* Some C compilers fail to reduce "FIX(constant)" at compile time, thus + * causing a lot of useless floating-point operations at run time. + * To get around this we use the following pre-calculated constants. + * If you change CONST_BITS you may want to add appropriate values. + * (With a reasonable C compiler, you can just rely on the FIX() macro...) + */ + +#if CONST_BITS == 13 +#define FIX_0_298631336 ((IJG_INT32) 2446) /* FIX(0.298631336) */ +#define FIX_0_390180644 ((IJG_INT32) 3196) /* FIX(0.390180644) */ +#define FIX_0_541196100 ((IJG_INT32) 4433) /* FIX(0.541196100) */ +#define FIX_0_765366865 ((IJG_INT32) 6270) /* FIX(0.765366865) */ +#define FIX_0_899976223 ((IJG_INT32) 7373) /* FIX(0.899976223) */ +#define FIX_1_175875602 ((IJG_INT32) 9633) /* FIX(1.175875602) */ +#define FIX_1_501321110 ((IJG_INT32) 12299) /* FIX(1.501321110) */ +#define FIX_1_847759065 ((IJG_INT32) 15137) /* FIX(1.847759065) */ +#define FIX_1_961570560 ((IJG_INT32) 16069) /* FIX(1.961570560) */ +#define FIX_2_053119869 ((IJG_INT32) 16819) /* FIX(2.053119869) */ +#define FIX_2_562915447 ((IJG_INT32) 20995) /* FIX(2.562915447) */ +#define FIX_3_072711026 ((IJG_INT32) 25172) /* FIX(3.072711026) */ +#else +#define FIX_0_298631336 FIX(0.298631336) +#define FIX_0_390180644 FIX(0.390180644) +#define FIX_0_541196100 FIX(0.541196100) +#define FIX_0_765366865 FIX(0.765366865) +#define FIX_0_899976223 FIX(0.899976223) +#define FIX_1_175875602 FIX(1.175875602) +#define FIX_1_501321110 FIX(1.501321110) +#define FIX_1_847759065 FIX(1.847759065) +#define FIX_1_961570560 FIX(1.961570560) +#define FIX_2_053119869 FIX(2.053119869) +#define FIX_2_562915447 FIX(2.562915447) +#define FIX_3_072711026 FIX(3.072711026) +#endif + + +/* Multiply an IJG_INT32 variable by an IJG_INT32 constant to yield an IJG_INT32 result. + * For 8-bit samples with the recommended scaling, all the variable + * and constant values involved are no more than 16 bits wide, so a + * 16x16->32 bit multiply can be used instead of a full 32x32 multiply. + * For 12-bit samples, a full 32-bit multiplication will be needed. + */ + +#if BITS_IN_JSAMPLE == 8 +#define MULTIPLY(var,const) MULTIPLY16C16(var,const) +#else +#define MULTIPLY(var,const) ((var) * (const)) +#endif + + +/* + * Perform the forward DCT on one block of samples. + */ + +GLOBAL(void) +jpeg_fdct_islow (DCTELEM * data) +{ + IJG_INT32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + IJG_INT32 tmp10, tmp11, tmp12, tmp13; + IJG_INT32 z1, z2, z3, z4, z5; + DCTELEM *dataptr; + int ctr; + SHIFT_TEMPS + + /* Pass 1: process rows. */ + /* Note results are scaled up by sqrt(8) compared to a true DCT; */ + /* furthermore, we scale the results by 2**PASS1_BITS. */ + + dataptr = data; + for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { + tmp0 = dataptr[0] + dataptr[7]; + tmp7 = dataptr[0] - dataptr[7]; + tmp1 = dataptr[1] + dataptr[6]; + tmp6 = dataptr[1] - dataptr[6]; + tmp2 = dataptr[2] + dataptr[5]; + tmp5 = dataptr[2] - dataptr[5]; + tmp3 = dataptr[3] + dataptr[4]; + tmp4 = dataptr[3] - dataptr[4]; + + /* Even part per LL&M figure 1 --- note that published figure is faulty; + * rotator "sqrt(2)*c1" should be "sqrt(2)*c6". + */ + + tmp10 = tmp0 + tmp3; + tmp13 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp1 - tmp2; + + dataptr[0] = (DCTELEM) ((tmp10 + tmp11) << PASS1_BITS); + dataptr[4] = (DCTELEM) ((tmp10 - tmp11) << PASS1_BITS); + + z1 = MULTIPLY(tmp12 + tmp13, FIX_0_541196100); + dataptr[2] = (DCTELEM) DESCALE(z1 + MULTIPLY(tmp13, FIX_0_765366865), + CONST_BITS-PASS1_BITS); + dataptr[6] = (DCTELEM) DESCALE(z1 + MULTIPLY(tmp12, - FIX_1_847759065), + CONST_BITS-PASS1_BITS); + + /* Odd part per figure 8 --- note paper omits factor of sqrt(2). + * cK represents cos(K*pi/16). + * i0..i3 in the paper are tmp4..tmp7 here. + */ + + z1 = tmp4 + tmp7; + z2 = tmp5 + tmp6; + z3 = tmp4 + tmp6; + z4 = tmp5 + tmp7; + z5 = MULTIPLY(z3 + z4, FIX_1_175875602); /* sqrt(2) * c3 */ + + tmp4 = MULTIPLY(tmp4, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */ + tmp5 = MULTIPLY(tmp5, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */ + tmp6 = MULTIPLY(tmp6, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */ + tmp7 = MULTIPLY(tmp7, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */ + z1 = MULTIPLY(z1, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */ + z2 = MULTIPLY(z2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */ + z3 = MULTIPLY(z3, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */ + z4 = MULTIPLY(z4, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */ + + z3 += z5; + z4 += z5; + + dataptr[7] = (DCTELEM) DESCALE(tmp4 + z1 + z3, CONST_BITS-PASS1_BITS); + dataptr[5] = (DCTELEM) DESCALE(tmp5 + z2 + z4, CONST_BITS-PASS1_BITS); + dataptr[3] = (DCTELEM) DESCALE(tmp6 + z2 + z3, CONST_BITS-PASS1_BITS); + dataptr[1] = (DCTELEM) DESCALE(tmp7 + z1 + z4, CONST_BITS-PASS1_BITS); + + dataptr += DCTSIZE; /* advance pointer to next row */ + } + + /* Pass 2: process columns. + * We remove the PASS1_BITS scaling, but leave the results scaled up + * by an overall factor of 8. + */ + + dataptr = data; + for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { + tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*7]; + tmp7 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*7]; + tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*6]; + tmp6 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*6]; + tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*5]; + tmp5 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*5]; + tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*4]; + tmp4 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*4]; + + /* Even part per LL&M figure 1 --- note that published figure is faulty; + * rotator "sqrt(2)*c1" should be "sqrt(2)*c6". + */ + + tmp10 = tmp0 + tmp3; + tmp13 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp1 - tmp2; + + dataptr[DCTSIZE*0] = (DCTELEM) DESCALE(tmp10 + tmp11, PASS1_BITS); + dataptr[DCTSIZE*4] = (DCTELEM) DESCALE(tmp10 - tmp11, PASS1_BITS); + + z1 = MULTIPLY(tmp12 + tmp13, FIX_0_541196100); + dataptr[DCTSIZE*2] = (DCTELEM) DESCALE(z1 + MULTIPLY(tmp13, FIX_0_765366865), + CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*6] = (DCTELEM) DESCALE(z1 + MULTIPLY(tmp12, - FIX_1_847759065), + CONST_BITS+PASS1_BITS); + + /* Odd part per figure 8 --- note paper omits factor of sqrt(2). + * cK represents cos(K*pi/16). + * i0..i3 in the paper are tmp4..tmp7 here. + */ + + z1 = tmp4 + tmp7; + z2 = tmp5 + tmp6; + z3 = tmp4 + tmp6; + z4 = tmp5 + tmp7; + z5 = MULTIPLY(z3 + z4, FIX_1_175875602); /* sqrt(2) * c3 */ + + tmp4 = MULTIPLY(tmp4, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */ + tmp5 = MULTIPLY(tmp5, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */ + tmp6 = MULTIPLY(tmp6, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */ + tmp7 = MULTIPLY(tmp7, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */ + z1 = MULTIPLY(z1, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */ + z2 = MULTIPLY(z2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */ + z3 = MULTIPLY(z3, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */ + z4 = MULTIPLY(z4, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */ + + z3 += z5; + z4 += z5; + + dataptr[DCTSIZE*7] = (DCTELEM) DESCALE(tmp4 + z1 + z3, + CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*5] = (DCTELEM) DESCALE(tmp5 + z2 + z4, + CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp6 + z2 + z3, + CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(tmp7 + z1 + z4, + CONST_BITS+PASS1_BITS); + + dataptr++; /* advance pointer to next column */ + } +} + +#endif /* DCT_ISLOW_SUPPORTED */ diff --git a/dcmjpeg/libijg8/jidctflt.c b/dcmjpeg/libijg8/jidctflt.c new file mode 100644 index 00000000..a57f6dba --- /dev/null +++ b/dcmjpeg/libijg8/jidctflt.c @@ -0,0 +1,242 @@ +/* + * jidctflt.c + * + * Copyright (C) 1994-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains a floating-point implementation of the + * inverse DCT (Discrete Cosine Transform). In the IJG code, this routine + * must also perform dequantization of the input coefficients. + * + * This implementation should be more accurate than either of the integer + * IDCT implementations. However, it may not give the same results on all + * machines because of differences in roundoff behavior. Speed will depend + * on the hardware's floating point capacity. + * + * A 2-D IDCT can be done by 1-D IDCT on each column followed by 1-D IDCT + * on each row (or vice versa, but it's more convenient to emit a row at + * a time). Direct algorithms are also available, but they are much more + * complex and seem not to be any faster when reduced to code. + * + * This implementation is based on Arai, Agui, and Nakajima's algorithm for + * scaled DCT. Their original paper (Trans. IEICE E-71(11):1095) is in + * Japanese, but the algorithm is described in the Pennebaker & Mitchell + * JPEG textbook (see REFERENCES section in file README). The following code + * is based directly on figure 4-8 in P&M. + * While an 8-point DCT cannot be done in less than 11 multiplies, it is + * possible to arrange the computation so that many of the multiplies are + * simple scalings of the final outputs. These multiplies can then be + * folded into the multiplications or divisions by the JPEG quantization + * table entries. The AA&N method leaves only 5 multiplies and 29 adds + * to be done in the DCT itself. + * The primary disadvantage of this method is that with a fixed-point + * implementation, accuracy is lost due to imprecise representation of the + * scaled quantization values. However, that problem does not arise if + * we use floating point arithmetic. + */ + +#define JPEG_INTERNALS +#include "jinclude8.h" +#include "jpeglib8.h" +#include "jdct8.h" /* Private declarations for DCT subsystem */ + +#ifdef DCT_FLOAT_SUPPORTED + + +/* + * This module is specialized to the case DCTSIZE = 8. + */ + +#if DCTSIZE != 8 + Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */ +#endif + + +/* Dequantize a coefficient by multiplying it by the multiplier-table + * entry; produce a float result. + */ + +#define DEQUANTIZE(coef,quantval) (((FAST_FLOAT) (coef)) * (quantval)) + + +/* + * Perform dequantization and inverse DCT on one block of coefficients. + */ + +GLOBAL(void) +jpeg_idct_float (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + FAST_FLOAT tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + FAST_FLOAT tmp10, tmp11, tmp12, tmp13; + FAST_FLOAT z5, z10, z11, z12, z13; + JCOEFPTR inptr; + FLOAT_MULT_TYPE * quantptr; + FAST_FLOAT * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + FAST_FLOAT workspace[DCTSIZE2]; /* buffers data between passes */ + SHIFT_TEMPS + + /* Pass 1: process columns from input, store into work array. */ + + inptr = coef_block; + quantptr = (FLOAT_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = DCTSIZE; ctr > 0; ctr--) { + /* Due to quantization, we will usually find that many of the input + * coefficients are zero, especially the AC terms. We can exploit this + * by short-circuiting the IDCT calculation for any column in which all + * the AC terms are zero. In that case each output is equal to the + * DC coefficient (with scale factor as needed). + * With typical images and quantization tables, half or more of the + * column DCT calculations can be simplified this way. + */ + + if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*2] == 0 && + inptr[DCTSIZE*3] == 0 && inptr[DCTSIZE*4] == 0 && + inptr[DCTSIZE*5] == 0 && inptr[DCTSIZE*6] == 0 && + inptr[DCTSIZE*7] == 0) { + /* AC terms all zero */ + FAST_FLOAT dcval = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + + wsptr[DCTSIZE*0] = dcval; + wsptr[DCTSIZE*1] = dcval; + wsptr[DCTSIZE*2] = dcval; + wsptr[DCTSIZE*3] = dcval; + wsptr[DCTSIZE*4] = dcval; + wsptr[DCTSIZE*5] = dcval; + wsptr[DCTSIZE*6] = dcval; + wsptr[DCTSIZE*7] = dcval; + + inptr++; /* advance pointers to next column */ + quantptr++; + wsptr++; + continue; + } + + /* Even part */ + + tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + tmp1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + tmp2 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); + tmp3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); + + tmp10 = tmp0 + tmp2; /* phase 3 */ + tmp11 = tmp0 - tmp2; + + tmp13 = tmp1 + tmp3; /* phases 5-3 */ + tmp12 = (tmp1 - tmp3) * ((FAST_FLOAT) 1.414213562) - tmp13; /* 2*c4 */ + + tmp0 = tmp10 + tmp13; /* phase 2 */ + tmp3 = tmp10 - tmp13; + tmp1 = tmp11 + tmp12; + tmp2 = tmp11 - tmp12; + + /* Odd part */ + + tmp4 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + tmp5 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + tmp6 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); + tmp7 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); + + z13 = tmp6 + tmp5; /* phase 6 */ + z10 = tmp6 - tmp5; + z11 = tmp4 + tmp7; + z12 = tmp4 - tmp7; + + tmp7 = z11 + z13; /* phase 5 */ + tmp11 = (z11 - z13) * ((FAST_FLOAT) 1.414213562); /* 2*c4 */ + + z5 = (z10 + z12) * ((FAST_FLOAT) 1.847759065); /* 2*c2 */ + tmp10 = ((FAST_FLOAT) 1.082392200) * z12 - z5; /* 2*(c2-c6) */ + tmp12 = ((FAST_FLOAT) -2.613125930) * z10 + z5; /* -2*(c2+c6) */ + + tmp6 = tmp12 - tmp7; /* phase 2 */ + tmp5 = tmp11 - tmp6; + tmp4 = tmp10 + tmp5; + + wsptr[DCTSIZE*0] = tmp0 + tmp7; + wsptr[DCTSIZE*7] = tmp0 - tmp7; + wsptr[DCTSIZE*1] = tmp1 + tmp6; + wsptr[DCTSIZE*6] = tmp1 - tmp6; + wsptr[DCTSIZE*2] = tmp2 + tmp5; + wsptr[DCTSIZE*5] = tmp2 - tmp5; + wsptr[DCTSIZE*4] = tmp3 + tmp4; + wsptr[DCTSIZE*3] = tmp3 - tmp4; + + inptr++; /* advance pointers to next column */ + quantptr++; + wsptr++; + } + + /* Pass 2: process rows from work array, store into output array. */ + /* Note that we must descale the results by a factor of 8 == 2**3. */ + + wsptr = workspace; + for (ctr = 0; ctr < DCTSIZE; ctr++) { + outptr = output_buf[ctr] + output_col; + /* Rows of zeroes can be exploited in the same way as we did with columns. + * However, the column calculation has created many nonzero AC terms, so + * the simplification applies less often (typically 5% to 10% of the time). + * And testing floats for zero is relatively expensive, so we don't bother. + */ + + /* Even part */ + + tmp10 = wsptr[0] + wsptr[4]; + tmp11 = wsptr[0] - wsptr[4]; + + tmp13 = wsptr[2] + wsptr[6]; + tmp12 = (wsptr[2] - wsptr[6]) * ((FAST_FLOAT) 1.414213562) - tmp13; + + tmp0 = tmp10 + tmp13; + tmp3 = tmp10 - tmp13; + tmp1 = tmp11 + tmp12; + tmp2 = tmp11 - tmp12; + + /* Odd part */ + + z13 = wsptr[5] + wsptr[3]; + z10 = wsptr[5] - wsptr[3]; + z11 = wsptr[1] + wsptr[7]; + z12 = wsptr[1] - wsptr[7]; + + tmp7 = z11 + z13; + tmp11 = (z11 - z13) * ((FAST_FLOAT) 1.414213562); + + z5 = (z10 + z12) * ((FAST_FLOAT) 1.847759065); /* 2*c2 */ + tmp10 = ((FAST_FLOAT) 1.082392200) * z12 - z5; /* 2*(c2-c6) */ + tmp12 = ((FAST_FLOAT) -2.613125930) * z10 + z5; /* -2*(c2+c6) */ + + tmp6 = tmp12 - tmp7; + tmp5 = tmp11 - tmp6; + tmp4 = tmp10 + tmp5; + + /* Final output stage: scale down by a factor of 8 and range-limit */ + + outptr[0] = range_limit[(int) DESCALE((IJG_INT32) (tmp0 + tmp7), 3) + & RANGE_MASK]; + outptr[7] = range_limit[(int) DESCALE((IJG_INT32) (tmp0 - tmp7), 3) + & RANGE_MASK]; + outptr[1] = range_limit[(int) DESCALE((IJG_INT32) (tmp1 + tmp6), 3) + & RANGE_MASK]; + outptr[6] = range_limit[(int) DESCALE((IJG_INT32) (tmp1 - tmp6), 3) + & RANGE_MASK]; + outptr[2] = range_limit[(int) DESCALE((IJG_INT32) (tmp2 + tmp5), 3) + & RANGE_MASK]; + outptr[5] = range_limit[(int) DESCALE((IJG_INT32) (tmp2 - tmp5), 3) + & RANGE_MASK]; + outptr[4] = range_limit[(int) DESCALE((IJG_INT32) (tmp3 + tmp4), 3) + & RANGE_MASK]; + outptr[3] = range_limit[(int) DESCALE((IJG_INT32) (tmp3 - tmp4), 3) + & RANGE_MASK]; + + wsptr += DCTSIZE; /* advance pointer to next row */ + } +} + +#endif /* DCT_FLOAT_SUPPORTED */ diff --git a/dcmjpeg/libijg8/jidctfst.c b/dcmjpeg/libijg8/jidctfst.c new file mode 100644 index 00000000..3d19e3c6 --- /dev/null +++ b/dcmjpeg/libijg8/jidctfst.c @@ -0,0 +1,368 @@ +/* + * jidctfst.c + * + * Copyright (C) 1994-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains a fast, not so accurate integer implementation of the + * inverse DCT (Discrete Cosine Transform). In the IJG code, this routine + * must also perform dequantization of the input coefficients. + * + * A 2-D IDCT can be done by 1-D IDCT on each column followed by 1-D IDCT + * on each row (or vice versa, but it's more convenient to emit a row at + * a time). Direct algorithms are also available, but they are much more + * complex and seem not to be any faster when reduced to code. + * + * This implementation is based on Arai, Agui, and Nakajima's algorithm for + * scaled DCT. Their original paper (Trans. IEICE E-71(11):1095) is in + * Japanese, but the algorithm is described in the Pennebaker & Mitchell + * JPEG textbook (see REFERENCES section in file README). The following code + * is based directly on figure 4-8 in P&M. + * While an 8-point DCT cannot be done in less than 11 multiplies, it is + * possible to arrange the computation so that many of the multiplies are + * simple scalings of the final outputs. These multiplies can then be + * folded into the multiplications or divisions by the JPEG quantization + * table entries. The AA&N method leaves only 5 multiplies and 29 adds + * to be done in the DCT itself. + * The primary disadvantage of this method is that with fixed-point math, + * accuracy is lost due to imprecise representation of the scaled + * quantization values. The smaller the quantization table entry, the less + * precise the scaled value, so this implementation does worse with high- + * quality-setting files than with low-quality ones. + */ + +#define JPEG_INTERNALS +#include "jinclude8.h" +#include "jpeglib8.h" +#include "jdct8.h" /* Private declarations for DCT subsystem */ + +#ifdef DCT_IFAST_SUPPORTED + + +/* + * This module is specialized to the case DCTSIZE = 8. + */ + +#if DCTSIZE != 8 + Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */ +#endif + + +/* Scaling decisions are generally the same as in the LL&M algorithm; + * see jidctint.c for more details. However, we choose to descale + * (right shift) multiplication products as soon as they are formed, + * rather than carrying additional fractional bits into subsequent additions. + * This compromises accuracy slightly, but it lets us save a few shifts. + * More importantly, 16-bit arithmetic is then adequate (for 8-bit samples) + * everywhere except in the multiplications proper; this saves a good deal + * of work on 16-bit-int machines. + * + * The dequantized coefficients are not integers because the AA&N scaling + * factors have been incorporated. We represent them scaled up by PASS1_BITS, + * so that the first and second IDCT rounds have the same input scaling. + * For 8-bit JSAMPLEs, we choose IFAST_SCALE_BITS = PASS1_BITS so as to + * avoid a descaling shift; this compromises accuracy rather drastically + * for small quantization table entries, but it saves a lot of shifts. + * For 12-bit JSAMPLEs, there's no hope of using 16x16 multiplies anyway, + * so we use a much larger scaling factor to preserve accuracy. + * + * A final compromise is to represent the multiplicative constants to only + * 8 fractional bits, rather than 13. This saves some shifting work on some + * machines, and may also reduce the cost of multiplication (since there + * are fewer one-bits in the constants). + */ + +#if BITS_IN_JSAMPLE == 8 +#define CONST_BITS 8 +#define PASS1_BITS 2 +#else +#define CONST_BITS 8 +#define PASS1_BITS 1 /* lose a little precision to avoid overflow */ +#endif + +/* Some C compilers fail to reduce "FIX(constant)" at compile time, thus + * causing a lot of useless floating-point operations at run time. + * To get around this we use the following pre-calculated constants. + * If you change CONST_BITS you may want to add appropriate values. + * (With a reasonable C compiler, you can just rely on the FIX() macro...) + */ + +#if CONST_BITS == 8 +#define FIX_1_082392200 ((IJG_INT32) 277) /* FIX(1.082392200) */ +#define FIX_1_414213562 ((IJG_INT32) 362) /* FIX(1.414213562) */ +#define FIX_1_847759065 ((IJG_INT32) 473) /* FIX(1.847759065) */ +#define FIX_2_613125930 ((IJG_INT32) 669) /* FIX(2.613125930) */ +#else +#define FIX_1_082392200 FIX(1.082392200) +#define FIX_1_414213562 FIX(1.414213562) +#define FIX_1_847759065 FIX(1.847759065) +#define FIX_2_613125930 FIX(2.613125930) +#endif + + +/* We can gain a little more speed, with a further compromise in accuracy, + * by omitting the addition in a descaling shift. This yields an incorrectly + * rounded result half the time... + */ + +#ifndef USE_ACCURATE_ROUNDING +#undef DESCALE +#define DESCALE(x,n) RIGHT_SHIFT(x, n) +#endif + + +/* Multiply a DCTELEM variable by an IJG_INT32 constant, and immediately + * descale to yield a DCTELEM result. + */ + +#define MULTIPLY(var,const) ((DCTELEM) DESCALE((var) * (const), CONST_BITS)) + + +/* Dequantize a coefficient by multiplying it by the multiplier-table + * entry; produce a DCTELEM result. For 8-bit data a 16x16->16 + * multiplication will do. For 12-bit data, the multiplier table is + * declared IJG_INT32, so a 32-bit multiply will be used. + */ + +#if BITS_IN_JSAMPLE == 8 +#define DEQUANTIZE(coef,quantval) (((IFAST_MULT_TYPE) (coef)) * (quantval)) +#else +#define DEQUANTIZE(coef,quantval) \ + DESCALE((coef)*(quantval), IFAST_SCALE_BITS-PASS1_BITS) +#endif + + +/* Like DESCALE, but applies to a DCTELEM and produces an int. + * We assume that int right shift is unsigned if IJG_INT32 right shift is. + */ + +#ifdef RIGHT_SHIFT_IS_UNSIGNED +#define ISHIFT_TEMPS DCTELEM ishift_temp; +#if BITS_IN_JSAMPLE == 8 +#define DCTELEMBITS 16 /* DCTELEM may be 16 or 32 bits */ +#else +#define DCTELEMBITS 32 /* DCTELEM must be 32 bits */ +#endif +#define IRIGHT_SHIFT(x,shft) \ + ((ishift_temp = (x)) < 0 ? \ + (ishift_temp >> (shft)) | ((~((DCTELEM) 0)) << (DCTELEMBITS-(shft))) : \ + (ishift_temp >> (shft))) +#else +#define ISHIFT_TEMPS +#define IRIGHT_SHIFT(x,shft) ((x) >> (shft)) +#endif + +#ifdef USE_ACCURATE_ROUNDING +#define IDESCALE(x,n) ((int) IRIGHT_SHIFT((x) + (1 << ((n)-1)), n)) +#else +#define IDESCALE(x,n) ((int) IRIGHT_SHIFT(x, n)) +#endif + + +/* + * Perform dequantization and inverse DCT on one block of coefficients. + */ + +GLOBAL(void) +jpeg_idct_ifast (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + DCTELEM tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + DCTELEM tmp10, tmp11, tmp12, tmp13; + DCTELEM z5, z10, z11, z12, z13; + JCOEFPTR inptr; + IFAST_MULT_TYPE * quantptr; + int * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + int workspace[DCTSIZE2]; /* buffers data between passes */ + SHIFT_TEMPS /* for DESCALE */ + ISHIFT_TEMPS /* for IDESCALE */ + + /* Pass 1: process columns from input, store into work array. */ + + inptr = coef_block; + quantptr = (IFAST_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = DCTSIZE; ctr > 0; ctr--) { + /* Due to quantization, we will usually find that many of the input + * coefficients are zero, especially the AC terms. We can exploit this + * by short-circuiting the IDCT calculation for any column in which all + * the AC terms are zero. In that case each output is equal to the + * DC coefficient (with scale factor as needed). + * With typical images and quantization tables, half or more of the + * column DCT calculations can be simplified this way. + */ + + if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*2] == 0 && + inptr[DCTSIZE*3] == 0 && inptr[DCTSIZE*4] == 0 && + inptr[DCTSIZE*5] == 0 && inptr[DCTSIZE*6] == 0 && + inptr[DCTSIZE*7] == 0) { + /* AC terms all zero */ + int dcval = (int) DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + + wsptr[DCTSIZE*0] = dcval; + wsptr[DCTSIZE*1] = dcval; + wsptr[DCTSIZE*2] = dcval; + wsptr[DCTSIZE*3] = dcval; + wsptr[DCTSIZE*4] = dcval; + wsptr[DCTSIZE*5] = dcval; + wsptr[DCTSIZE*6] = dcval; + wsptr[DCTSIZE*7] = dcval; + + inptr++; /* advance pointers to next column */ + quantptr++; + wsptr++; + continue; + } + + /* Even part */ + + tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + tmp1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + tmp2 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); + tmp3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); + + tmp10 = tmp0 + tmp2; /* phase 3 */ + tmp11 = tmp0 - tmp2; + + tmp13 = tmp1 + tmp3; /* phases 5-3 */ + tmp12 = MULTIPLY(tmp1 - tmp3, FIX_1_414213562) - tmp13; /* 2*c4 */ + + tmp0 = tmp10 + tmp13; /* phase 2 */ + tmp3 = tmp10 - tmp13; + tmp1 = tmp11 + tmp12; + tmp2 = tmp11 - tmp12; + + /* Odd part */ + + tmp4 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + tmp5 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + tmp6 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); + tmp7 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); + + z13 = tmp6 + tmp5; /* phase 6 */ + z10 = tmp6 - tmp5; + z11 = tmp4 + tmp7; + z12 = tmp4 - tmp7; + + tmp7 = z11 + z13; /* phase 5 */ + tmp11 = MULTIPLY(z11 - z13, FIX_1_414213562); /* 2*c4 */ + + z5 = MULTIPLY(z10 + z12, FIX_1_847759065); /* 2*c2 */ + tmp10 = MULTIPLY(z12, FIX_1_082392200) - z5; /* 2*(c2-c6) */ + tmp12 = MULTIPLY(z10, - FIX_2_613125930) + z5; /* -2*(c2+c6) */ + + tmp6 = tmp12 - tmp7; /* phase 2 */ + tmp5 = tmp11 - tmp6; + tmp4 = tmp10 + tmp5; + + wsptr[DCTSIZE*0] = (int) (tmp0 + tmp7); + wsptr[DCTSIZE*7] = (int) (tmp0 - tmp7); + wsptr[DCTSIZE*1] = (int) (tmp1 + tmp6); + wsptr[DCTSIZE*6] = (int) (tmp1 - tmp6); + wsptr[DCTSIZE*2] = (int) (tmp2 + tmp5); + wsptr[DCTSIZE*5] = (int) (tmp2 - tmp5); + wsptr[DCTSIZE*4] = (int) (tmp3 + tmp4); + wsptr[DCTSIZE*3] = (int) (tmp3 - tmp4); + + inptr++; /* advance pointers to next column */ + quantptr++; + wsptr++; + } + + /* Pass 2: process rows from work array, store into output array. */ + /* Note that we must descale the results by a factor of 8 == 2**3, */ + /* and also undo the PASS1_BITS scaling. */ + + wsptr = workspace; + for (ctr = 0; ctr < DCTSIZE; ctr++) { + outptr = output_buf[ctr] + output_col; + /* Rows of zeroes can be exploited in the same way as we did with columns. + * However, the column calculation has created many nonzero AC terms, so + * the simplification applies less often (typically 5% to 10% of the time). + * On machines with very fast multiplication, it's possible that the + * test takes more time than it's worth. In that case this section + * may be commented out. + */ + +#ifndef NO_ZERO_ROW_TEST + if (wsptr[1] == 0 && wsptr[2] == 0 && wsptr[3] == 0 && wsptr[4] == 0 && + wsptr[5] == 0 && wsptr[6] == 0 && wsptr[7] == 0) { + /* AC terms all zero */ + JSAMPLE dcval = range_limit[IDESCALE(wsptr[0], PASS1_BITS+3) + & RANGE_MASK]; + + outptr[0] = dcval; + outptr[1] = dcval; + outptr[2] = dcval; + outptr[3] = dcval; + outptr[4] = dcval; + outptr[5] = dcval; + outptr[6] = dcval; + outptr[7] = dcval; + + wsptr += DCTSIZE; /* advance pointer to next row */ + continue; + } +#endif + + /* Even part */ + + tmp10 = ((DCTELEM) wsptr[0] + (DCTELEM) wsptr[4]); + tmp11 = ((DCTELEM) wsptr[0] - (DCTELEM) wsptr[4]); + + tmp13 = ((DCTELEM) wsptr[2] + (DCTELEM) wsptr[6]); + tmp12 = MULTIPLY((DCTELEM) wsptr[2] - (DCTELEM) wsptr[6], FIX_1_414213562) + - tmp13; + + tmp0 = tmp10 + tmp13; + tmp3 = tmp10 - tmp13; + tmp1 = tmp11 + tmp12; + tmp2 = tmp11 - tmp12; + + /* Odd part */ + + z13 = (DCTELEM) wsptr[5] + (DCTELEM) wsptr[3]; + z10 = (DCTELEM) wsptr[5] - (DCTELEM) wsptr[3]; + z11 = (DCTELEM) wsptr[1] + (DCTELEM) wsptr[7]; + z12 = (DCTELEM) wsptr[1] - (DCTELEM) wsptr[7]; + + tmp7 = z11 + z13; /* phase 5 */ + tmp11 = MULTIPLY(z11 - z13, FIX_1_414213562); /* 2*c4 */ + + z5 = MULTIPLY(z10 + z12, FIX_1_847759065); /* 2*c2 */ + tmp10 = MULTIPLY(z12, FIX_1_082392200) - z5; /* 2*(c2-c6) */ + tmp12 = MULTIPLY(z10, - FIX_2_613125930) + z5; /* -2*(c2+c6) */ + + tmp6 = tmp12 - tmp7; /* phase 2 */ + tmp5 = tmp11 - tmp6; + tmp4 = tmp10 + tmp5; + + /* Final output stage: scale down by a factor of 8 and range-limit */ + + outptr[0] = range_limit[IDESCALE(tmp0 + tmp7, PASS1_BITS+3) + & RANGE_MASK]; + outptr[7] = range_limit[IDESCALE(tmp0 - tmp7, PASS1_BITS+3) + & RANGE_MASK]; + outptr[1] = range_limit[IDESCALE(tmp1 + tmp6, PASS1_BITS+3) + & RANGE_MASK]; + outptr[6] = range_limit[IDESCALE(tmp1 - tmp6, PASS1_BITS+3) + & RANGE_MASK]; + outptr[2] = range_limit[IDESCALE(tmp2 + tmp5, PASS1_BITS+3) + & RANGE_MASK]; + outptr[5] = range_limit[IDESCALE(tmp2 - tmp5, PASS1_BITS+3) + & RANGE_MASK]; + outptr[4] = range_limit[IDESCALE(tmp3 + tmp4, PASS1_BITS+3) + & RANGE_MASK]; + outptr[3] = range_limit[IDESCALE(tmp3 - tmp4, PASS1_BITS+3) + & RANGE_MASK]; + + wsptr += DCTSIZE; /* advance pointer to next row */ + } +} + +#endif /* DCT_IFAST_SUPPORTED */ diff --git a/dcmjpeg/libijg8/jidctint.c b/dcmjpeg/libijg8/jidctint.c new file mode 100644 index 00000000..75a36c46 --- /dev/null +++ b/dcmjpeg/libijg8/jidctint.c @@ -0,0 +1,389 @@ +/* + * jidctint.c + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains a slow-but-accurate integer implementation of the + * inverse DCT (Discrete Cosine Transform). In the IJG code, this routine + * must also perform dequantization of the input coefficients. + * + * A 2-D IDCT can be done by 1-D IDCT on each column followed by 1-D IDCT + * on each row (or vice versa, but it's more convenient to emit a row at + * a time). Direct algorithms are also available, but they are much more + * complex and seem not to be any faster when reduced to code. + * + * This implementation is based on an algorithm described in + * C. Loeffler, A. Ligtenberg and G. Moschytz, "Practical Fast 1-D DCT + * Algorithms with 11 Multiplications", Proc. Int'l. Conf. on Acoustics, + * Speech, and Signal Processing 1989 (ICASSP '89), pp. 988-991. + * The primary algorithm described there uses 11 multiplies and 29 adds. + * We use their alternate method with 12 multiplies and 32 adds. + * The advantage of this method is that no data path contains more than one + * multiplication; this allows a very simple and accurate implementation in + * scaled fixed-point arithmetic, with a minimal number of shifts. + */ + +#define JPEG_INTERNALS +#include "jinclude8.h" +#include "jpeglib8.h" +#include "jdct8.h" /* Private declarations for DCT subsystem */ + +#ifdef DCT_ISLOW_SUPPORTED + + +/* + * This module is specialized to the case DCTSIZE = 8. + */ + +#if DCTSIZE != 8 + Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */ +#endif + + +/* + * The poop on this scaling stuff is as follows: + * + * Each 1-D IDCT step produces outputs which are a factor of sqrt(N) + * larger than the true IDCT outputs. The final outputs are therefore + * a factor of N larger than desired; since N=8 this can be cured by + * a simple right shift at the end of the algorithm. The advantage of + * this arrangement is that we save two multiplications per 1-D IDCT, + * because the y0 and y4 inputs need not be divided by sqrt(N). + * + * We have to do addition and subtraction of the integer inputs, which + * is no problem, and multiplication by fractional constants, which is + * a problem to do in integer arithmetic. We multiply all the constants + * by CONST_SCALE and convert them to integer constants (thus retaining + * CONST_BITS bits of precision in the constants). After doing a + * multiplication we have to divide the product by CONST_SCALE, with proper + * rounding, to produce the correct output. This division can be done + * cheaply as a right shift of CONST_BITS bits. We postpone shifting + * as long as possible so that partial sums can be added together with + * full fractional precision. + * + * The outputs of the first pass are scaled up by PASS1_BITS bits so that + * they are represented to better-than-integral precision. These outputs + * require BITS_IN_JSAMPLE + PASS1_BITS + 3 bits; this fits in a 16-bit word + * with the recommended scaling. (To scale up 12-bit sample data further, an + * intermediate IJG_INT32 array would be needed.) + * + * To avoid overflow of the 32-bit intermediate results in pass 2, we must + * have BITS_IN_JSAMPLE + CONST_BITS + PASS1_BITS <= 26. Error analysis + * shows that the values given below are the most effective. + */ + +#if BITS_IN_JSAMPLE == 8 +#define CONST_BITS 13 +#define PASS1_BITS 2 +#else +#define CONST_BITS 13 +#define PASS1_BITS 1 /* lose a little precision to avoid overflow */ +#endif + +/* Some C compilers fail to reduce "FIX(constant)" at compile time, thus + * causing a lot of useless floating-point operations at run time. + * To get around this we use the following pre-calculated constants. + * If you change CONST_BITS you may want to add appropriate values. + * (With a reasonable C compiler, you can just rely on the FIX() macro...) + */ + +#if CONST_BITS == 13 +#define FIX_0_298631336 ((IJG_INT32) 2446) /* FIX(0.298631336) */ +#define FIX_0_390180644 ((IJG_INT32) 3196) /* FIX(0.390180644) */ +#define FIX_0_541196100 ((IJG_INT32) 4433) /* FIX(0.541196100) */ +#define FIX_0_765366865 ((IJG_INT32) 6270) /* FIX(0.765366865) */ +#define FIX_0_899976223 ((IJG_INT32) 7373) /* FIX(0.899976223) */ +#define FIX_1_175875602 ((IJG_INT32) 9633) /* FIX(1.175875602) */ +#define FIX_1_501321110 ((IJG_INT32) 12299) /* FIX(1.501321110) */ +#define FIX_1_847759065 ((IJG_INT32) 15137) /* FIX(1.847759065) */ +#define FIX_1_961570560 ((IJG_INT32) 16069) /* FIX(1.961570560) */ +#define FIX_2_053119869 ((IJG_INT32) 16819) /* FIX(2.053119869) */ +#define FIX_2_562915447 ((IJG_INT32) 20995) /* FIX(2.562915447) */ +#define FIX_3_072711026 ((IJG_INT32) 25172) /* FIX(3.072711026) */ +#else +#define FIX_0_298631336 FIX(0.298631336) +#define FIX_0_390180644 FIX(0.390180644) +#define FIX_0_541196100 FIX(0.541196100) +#define FIX_0_765366865 FIX(0.765366865) +#define FIX_0_899976223 FIX(0.899976223) +#define FIX_1_175875602 FIX(1.175875602) +#define FIX_1_501321110 FIX(1.501321110) +#define FIX_1_847759065 FIX(1.847759065) +#define FIX_1_961570560 FIX(1.961570560) +#define FIX_2_053119869 FIX(2.053119869) +#define FIX_2_562915447 FIX(2.562915447) +#define FIX_3_072711026 FIX(3.072711026) +#endif + + +/* Multiply an IJG_INT32 variable by an IJG_INT32 constant to yield an IJG_INT32 result. + * For 8-bit samples with the recommended scaling, all the variable + * and constant values involved are no more than 16 bits wide, so a + * 16x16->32 bit multiply can be used instead of a full 32x32 multiply. + * For 12-bit samples, a full 32-bit multiplication will be needed. + */ + +#if BITS_IN_JSAMPLE == 8 +#define MULTIPLY(var,const) MULTIPLY16C16(var,const) +#else +#define MULTIPLY(var,const) ((var) * (const)) +#endif + + +/* Dequantize a coefficient by multiplying it by the multiplier-table + * entry; produce an int result. In this module, both inputs and result + * are 16 bits or less, so either int or short multiply will work. + */ + +#define DEQUANTIZE(coef,quantval) (((ISLOW_MULT_TYPE) (coef)) * (quantval)) + + +/* + * Perform dequantization and inverse DCT on one block of coefficients. + */ + +GLOBAL(void) +jpeg_idct_islow (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + IJG_INT32 tmp0, tmp1, tmp2, tmp3; + IJG_INT32 tmp10, tmp11, tmp12, tmp13; + IJG_INT32 z1, z2, z3, z4, z5; + JCOEFPTR inptr; + ISLOW_MULT_TYPE * quantptr; + int * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + int workspace[DCTSIZE2]; /* buffers data between passes */ + SHIFT_TEMPS + + /* Pass 1: process columns from input, store into work array. */ + /* Note results are scaled up by sqrt(8) compared to a true IDCT; */ + /* furthermore, we scale the results by 2**PASS1_BITS. */ + + inptr = coef_block; + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = DCTSIZE; ctr > 0; ctr--) { + /* Due to quantization, we will usually find that many of the input + * coefficients are zero, especially the AC terms. We can exploit this + * by short-circuiting the IDCT calculation for any column in which all + * the AC terms are zero. In that case each output is equal to the + * DC coefficient (with scale factor as needed). + * With typical images and quantization tables, half or more of the + * column DCT calculations can be simplified this way. + */ + + if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*2] == 0 && + inptr[DCTSIZE*3] == 0 && inptr[DCTSIZE*4] == 0 && + inptr[DCTSIZE*5] == 0 && inptr[DCTSIZE*6] == 0 && + inptr[DCTSIZE*7] == 0) { + /* AC terms all zero */ + int dcval = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]) << PASS1_BITS; + + wsptr[DCTSIZE*0] = dcval; + wsptr[DCTSIZE*1] = dcval; + wsptr[DCTSIZE*2] = dcval; + wsptr[DCTSIZE*3] = dcval; + wsptr[DCTSIZE*4] = dcval; + wsptr[DCTSIZE*5] = dcval; + wsptr[DCTSIZE*6] = dcval; + wsptr[DCTSIZE*7] = dcval; + + inptr++; /* advance pointers to next column */ + quantptr++; + wsptr++; + continue; + } + + /* Even part: reverse the even part of the forward DCT. */ + /* The rotator is sqrt(2)*c(-6). */ + + z2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + z3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); + + z1 = MULTIPLY(z2 + z3, FIX_0_541196100); + tmp2 = z1 + MULTIPLY(z3, - FIX_1_847759065); + tmp3 = z1 + MULTIPLY(z2, FIX_0_765366865); + + z2 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + z3 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); + + tmp0 = (z2 + z3) << CONST_BITS; + tmp1 = (z2 - z3) << CONST_BITS; + + tmp10 = tmp0 + tmp3; + tmp13 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp1 - tmp2; + + /* Odd part per figure 8; the matrix is unitary and hence its + * transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively. + */ + + tmp0 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); + tmp1 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); + tmp2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + tmp3 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + + z1 = tmp0 + tmp3; + z2 = tmp1 + tmp2; + z3 = tmp0 + tmp2; + z4 = tmp1 + tmp3; + z5 = MULTIPLY(z3 + z4, FIX_1_175875602); /* sqrt(2) * c3 */ + + tmp0 = MULTIPLY(tmp0, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */ + tmp1 = MULTIPLY(tmp1, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */ + tmp2 = MULTIPLY(tmp2, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */ + tmp3 = MULTIPLY(tmp3, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */ + z1 = MULTIPLY(z1, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */ + z2 = MULTIPLY(z2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */ + z3 = MULTIPLY(z3, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */ + z4 = MULTIPLY(z4, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */ + + z3 += z5; + z4 += z5; + + tmp0 += z1 + z3; + tmp1 += z2 + z4; + tmp2 += z2 + z3; + tmp3 += z1 + z4; + + /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */ + + wsptr[DCTSIZE*0] = (int) DESCALE(tmp10 + tmp3, CONST_BITS-PASS1_BITS); + wsptr[DCTSIZE*7] = (int) DESCALE(tmp10 - tmp3, CONST_BITS-PASS1_BITS); + wsptr[DCTSIZE*1] = (int) DESCALE(tmp11 + tmp2, CONST_BITS-PASS1_BITS); + wsptr[DCTSIZE*6] = (int) DESCALE(tmp11 - tmp2, CONST_BITS-PASS1_BITS); + wsptr[DCTSIZE*2] = (int) DESCALE(tmp12 + tmp1, CONST_BITS-PASS1_BITS); + wsptr[DCTSIZE*5] = (int) DESCALE(tmp12 - tmp1, CONST_BITS-PASS1_BITS); + wsptr[DCTSIZE*3] = (int) DESCALE(tmp13 + tmp0, CONST_BITS-PASS1_BITS); + wsptr[DCTSIZE*4] = (int) DESCALE(tmp13 - tmp0, CONST_BITS-PASS1_BITS); + + inptr++; /* advance pointers to next column */ + quantptr++; + wsptr++; + } + + /* Pass 2: process rows from work array, store into output array. */ + /* Note that we must descale the results by a factor of 8 == 2**3, */ + /* and also undo the PASS1_BITS scaling. */ + + wsptr = workspace; + for (ctr = 0; ctr < DCTSIZE; ctr++) { + outptr = output_buf[ctr] + output_col; + /* Rows of zeroes can be exploited in the same way as we did with columns. + * However, the column calculation has created many nonzero AC terms, so + * the simplification applies less often (typically 5% to 10% of the time). + * On machines with very fast multiplication, it's possible that the + * test takes more time than it's worth. In that case this section + * may be commented out. + */ + +#ifndef NO_ZERO_ROW_TEST + if (wsptr[1] == 0 && wsptr[2] == 0 && wsptr[3] == 0 && wsptr[4] == 0 && + wsptr[5] == 0 && wsptr[6] == 0 && wsptr[7] == 0) { + /* AC terms all zero */ + JSAMPLE dcval = range_limit[(int) DESCALE((IJG_INT32) wsptr[0], PASS1_BITS+3) + & RANGE_MASK]; + + outptr[0] = dcval; + outptr[1] = dcval; + outptr[2] = dcval; + outptr[3] = dcval; + outptr[4] = dcval; + outptr[5] = dcval; + outptr[6] = dcval; + outptr[7] = dcval; + + wsptr += DCTSIZE; /* advance pointer to next row */ + continue; + } +#endif + + /* Even part: reverse the even part of the forward DCT. */ + /* The rotator is sqrt(2)*c(-6). */ + + z2 = (IJG_INT32) wsptr[2]; + z3 = (IJG_INT32) wsptr[6]; + + z1 = MULTIPLY(z2 + z3, FIX_0_541196100); + tmp2 = z1 + MULTIPLY(z3, - FIX_1_847759065); + tmp3 = z1 + MULTIPLY(z2, FIX_0_765366865); + + tmp0 = ((IJG_INT32) wsptr[0] + (IJG_INT32) wsptr[4]) << CONST_BITS; + tmp1 = ((IJG_INT32) wsptr[0] - (IJG_INT32) wsptr[4]) << CONST_BITS; + + tmp10 = tmp0 + tmp3; + tmp13 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp1 - tmp2; + + /* Odd part per figure 8; the matrix is unitary and hence its + * transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively. + */ + + tmp0 = (IJG_INT32) wsptr[7]; + tmp1 = (IJG_INT32) wsptr[5]; + tmp2 = (IJG_INT32) wsptr[3]; + tmp3 = (IJG_INT32) wsptr[1]; + + z1 = tmp0 + tmp3; + z2 = tmp1 + tmp2; + z3 = tmp0 + tmp2; + z4 = tmp1 + tmp3; + z5 = MULTIPLY(z3 + z4, FIX_1_175875602); /* sqrt(2) * c3 */ + + tmp0 = MULTIPLY(tmp0, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */ + tmp1 = MULTIPLY(tmp1, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */ + tmp2 = MULTIPLY(tmp2, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */ + tmp3 = MULTIPLY(tmp3, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */ + z1 = MULTIPLY(z1, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */ + z2 = MULTIPLY(z2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */ + z3 = MULTIPLY(z3, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */ + z4 = MULTIPLY(z4, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */ + + z3 += z5; + z4 += z5; + + tmp0 += z1 + z3; + tmp1 += z2 + z4; + tmp2 += z2 + z3; + tmp3 += z1 + z4; + + /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */ + + outptr[0] = range_limit[(int) DESCALE(tmp10 + tmp3, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[7] = range_limit[(int) DESCALE(tmp10 - tmp3, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[1] = range_limit[(int) DESCALE(tmp11 + tmp2, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[6] = range_limit[(int) DESCALE(tmp11 - tmp2, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[2] = range_limit[(int) DESCALE(tmp12 + tmp1, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[5] = range_limit[(int) DESCALE(tmp12 - tmp1, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[3] = range_limit[(int) DESCALE(tmp13 + tmp0, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[4] = range_limit[(int) DESCALE(tmp13 - tmp0, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + + wsptr += DCTSIZE; /* advance pointer to next row */ + } +} + +#endif /* DCT_ISLOW_SUPPORTED */ diff --git a/dcmjpeg/libijg8/jidctred.c b/dcmjpeg/libijg8/jidctred.c new file mode 100644 index 00000000..e035a749 --- /dev/null +++ b/dcmjpeg/libijg8/jidctred.c @@ -0,0 +1,398 @@ +/* + * jidctred.c + * + * Copyright (C) 1994-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains inverse-DCT routines that produce reduced-size output: + * either 4x4, 2x2, or 1x1 pixels from an 8x8 DCT block. + * + * The implementation is based on the Loeffler, Ligtenberg and Moschytz (LL&M) + * algorithm used in jidctint.c. We simply replace each 8-to-8 1-D IDCT step + * with an 8-to-4 step that produces the four averages of two adjacent outputs + * (or an 8-to-2 step producing two averages of four outputs, for 2x2 output). + * These steps were derived by computing the corresponding values at the end + * of the normal LL&M code, then simplifying as much as possible. + * + * 1x1 is trivial: just take the DC coefficient divided by 8. + * + * See jidctint.c for additional comments. + */ + +#define JPEG_INTERNALS +#include "jinclude8.h" +#include "jpeglib8.h" +#include "jdct8.h" /* Private declarations for DCT subsystem */ + +#ifdef IDCT_SCALING_SUPPORTED + + +/* + * This module is specialized to the case DCTSIZE = 8. + */ + +#if DCTSIZE != 8 + Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */ +#endif + + +/* Scaling is the same as in jidctint.c. */ + +#if BITS_IN_JSAMPLE == 8 +#define CONST_BITS 13 +#define PASS1_BITS 2 +#else +#define CONST_BITS 13 +#define PASS1_BITS 1 /* lose a little precision to avoid overflow */ +#endif + +/* Some C compilers fail to reduce "FIX(constant)" at compile time, thus + * causing a lot of useless floating-point operations at run time. + * To get around this we use the following pre-calculated constants. + * If you change CONST_BITS you may want to add appropriate values. + * (With a reasonable C compiler, you can just rely on the FIX() macro...) + */ + +#if CONST_BITS == 13 +#define FIX_0_211164243 ((IJG_INT32) 1730) /* FIX(0.211164243) */ +#define FIX_0_509795579 ((IJG_INT32) 4176) /* FIX(0.509795579) */ +#define FIX_0_601344887 ((IJG_INT32) 4926) /* FIX(0.601344887) */ +#define FIX_0_720959822 ((IJG_INT32) 5906) /* FIX(0.720959822) */ +#define FIX_0_765366865 ((IJG_INT32) 6270) /* FIX(0.765366865) */ +#define FIX_0_850430095 ((IJG_INT32) 6967) /* FIX(0.850430095) */ +#define FIX_0_899976223 ((IJG_INT32) 7373) /* FIX(0.899976223) */ +#define FIX_1_061594337 ((IJG_INT32) 8697) /* FIX(1.061594337) */ +#define FIX_1_272758580 ((IJG_INT32) 10426) /* FIX(1.272758580) */ +#define FIX_1_451774981 ((IJG_INT32) 11893) /* FIX(1.451774981) */ +#define FIX_1_847759065 ((IJG_INT32) 15137) /* FIX(1.847759065) */ +#define FIX_2_172734803 ((IJG_INT32) 17799) /* FIX(2.172734803) */ +#define FIX_2_562915447 ((IJG_INT32) 20995) /* FIX(2.562915447) */ +#define FIX_3_624509785 ((IJG_INT32) 29692) /* FIX(3.624509785) */ +#else +#define FIX_0_211164243 FIX(0.211164243) +#define FIX_0_509795579 FIX(0.509795579) +#define FIX_0_601344887 FIX(0.601344887) +#define FIX_0_720959822 FIX(0.720959822) +#define FIX_0_765366865 FIX(0.765366865) +#define FIX_0_850430095 FIX(0.850430095) +#define FIX_0_899976223 FIX(0.899976223) +#define FIX_1_061594337 FIX(1.061594337) +#define FIX_1_272758580 FIX(1.272758580) +#define FIX_1_451774981 FIX(1.451774981) +#define FIX_1_847759065 FIX(1.847759065) +#define FIX_2_172734803 FIX(2.172734803) +#define FIX_2_562915447 FIX(2.562915447) +#define FIX_3_624509785 FIX(3.624509785) +#endif + + +/* Multiply an IJG_INT32 variable by an IJG_INT32 constant to yield an IJG_INT32 result. + * For 8-bit samples with the recommended scaling, all the variable + * and constant values involved are no more than 16 bits wide, so a + * 16x16->32 bit multiply can be used instead of a full 32x32 multiply. + * For 12-bit samples, a full 32-bit multiplication will be needed. + */ + +#if BITS_IN_JSAMPLE == 8 +#define MULTIPLY(var,const) MULTIPLY16C16(var,const) +#else +#define MULTIPLY(var,const) ((var) * (const)) +#endif + + +/* Dequantize a coefficient by multiplying it by the multiplier-table + * entry; produce an int result. In this module, both inputs and result + * are 16 bits or less, so either int or short multiply will work. + */ + +#define DEQUANTIZE(coef,quantval) (((ISLOW_MULT_TYPE) (coef)) * (quantval)) + + +/* + * Perform dequantization and inverse DCT on one block of coefficients, + * producing a reduced-size 4x4 output block. + */ + +GLOBAL(void) +jpeg_idct_4x4 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + IJG_INT32 tmp0, tmp2, tmp10, tmp12; + IJG_INT32 z1, z2, z3, z4; + JCOEFPTR inptr; + ISLOW_MULT_TYPE * quantptr; + int * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + int workspace[DCTSIZE*4]; /* buffers data between passes */ + SHIFT_TEMPS + + /* Pass 1: process columns from input, store into work array. */ + + inptr = coef_block; + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = DCTSIZE; ctr > 0; inptr++, quantptr++, wsptr++, ctr--) { + /* Don't bother to process column 4, because second pass won't use it */ + if (ctr == DCTSIZE-4) + continue; + if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*2] == 0 && + inptr[DCTSIZE*3] == 0 && inptr[DCTSIZE*5] == 0 && + inptr[DCTSIZE*6] == 0 && inptr[DCTSIZE*7] == 0) { + /* AC terms all zero; we need not examine term 4 for 4x4 output */ + int dcval = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]) << PASS1_BITS; + + wsptr[DCTSIZE*0] = dcval; + wsptr[DCTSIZE*1] = dcval; + wsptr[DCTSIZE*2] = dcval; + wsptr[DCTSIZE*3] = dcval; + + continue; + } + + /* Even part */ + + tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + tmp0 <<= (CONST_BITS+1); + + z2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + z3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); + + tmp2 = MULTIPLY(z2, FIX_1_847759065) + MULTIPLY(z3, - FIX_0_765366865); + + tmp10 = tmp0 + tmp2; + tmp12 = tmp0 - tmp2; + + /* Odd part */ + + z1 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); + z2 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); + z3 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + z4 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + + tmp0 = MULTIPLY(z1, - FIX_0_211164243) /* sqrt(2) * (c3-c1) */ + + MULTIPLY(z2, FIX_1_451774981) /* sqrt(2) * (c3+c7) */ + + MULTIPLY(z3, - FIX_2_172734803) /* sqrt(2) * (-c1-c5) */ + + MULTIPLY(z4, FIX_1_061594337); /* sqrt(2) * (c5+c7) */ + + tmp2 = MULTIPLY(z1, - FIX_0_509795579) /* sqrt(2) * (c7-c5) */ + + MULTIPLY(z2, - FIX_0_601344887) /* sqrt(2) * (c5-c1) */ + + MULTIPLY(z3, FIX_0_899976223) /* sqrt(2) * (c3-c7) */ + + MULTIPLY(z4, FIX_2_562915447); /* sqrt(2) * (c1+c3) */ + + /* Final output stage */ + + wsptr[DCTSIZE*0] = (int) DESCALE(tmp10 + tmp2, CONST_BITS-PASS1_BITS+1); + wsptr[DCTSIZE*3] = (int) DESCALE(tmp10 - tmp2, CONST_BITS-PASS1_BITS+1); + wsptr[DCTSIZE*1] = (int) DESCALE(tmp12 + tmp0, CONST_BITS-PASS1_BITS+1); + wsptr[DCTSIZE*2] = (int) DESCALE(tmp12 - tmp0, CONST_BITS-PASS1_BITS+1); + } + + /* Pass 2: process 4 rows from work array, store into output array. */ + + wsptr = workspace; + for (ctr = 0; ctr < 4; ctr++) { + outptr = output_buf[ctr] + output_col; + /* It's not clear whether a zero row test is worthwhile here ... */ + +#ifndef NO_ZERO_ROW_TEST + if (wsptr[1] == 0 && wsptr[2] == 0 && wsptr[3] == 0 && + wsptr[5] == 0 && wsptr[6] == 0 && wsptr[7] == 0) { + /* AC terms all zero */ + JSAMPLE dcval = range_limit[(int) DESCALE((IJG_INT32) wsptr[0], PASS1_BITS+3) + & RANGE_MASK]; + + outptr[0] = dcval; + outptr[1] = dcval; + outptr[2] = dcval; + outptr[3] = dcval; + + wsptr += DCTSIZE; /* advance pointer to next row */ + continue; + } +#endif + + /* Even part */ + + tmp0 = ((IJG_INT32) wsptr[0]) << (CONST_BITS+1); + + tmp2 = MULTIPLY((IJG_INT32) wsptr[2], FIX_1_847759065) + + MULTIPLY((IJG_INT32) wsptr[6], - FIX_0_765366865); + + tmp10 = tmp0 + tmp2; + tmp12 = tmp0 - tmp2; + + /* Odd part */ + + z1 = (IJG_INT32) wsptr[7]; + z2 = (IJG_INT32) wsptr[5]; + z3 = (IJG_INT32) wsptr[3]; + z4 = (IJG_INT32) wsptr[1]; + + tmp0 = MULTIPLY(z1, - FIX_0_211164243) /* sqrt(2) * (c3-c1) */ + + MULTIPLY(z2, FIX_1_451774981) /* sqrt(2) * (c3+c7) */ + + MULTIPLY(z3, - FIX_2_172734803) /* sqrt(2) * (-c1-c5) */ + + MULTIPLY(z4, FIX_1_061594337); /* sqrt(2) * (c5+c7) */ + + tmp2 = MULTIPLY(z1, - FIX_0_509795579) /* sqrt(2) * (c7-c5) */ + + MULTIPLY(z2, - FIX_0_601344887) /* sqrt(2) * (c5-c1) */ + + MULTIPLY(z3, FIX_0_899976223) /* sqrt(2) * (c3-c7) */ + + MULTIPLY(z4, FIX_2_562915447); /* sqrt(2) * (c1+c3) */ + + /* Final output stage */ + + outptr[0] = range_limit[(int) DESCALE(tmp10 + tmp2, + CONST_BITS+PASS1_BITS+3+1) + & RANGE_MASK]; + outptr[3] = range_limit[(int) DESCALE(tmp10 - tmp2, + CONST_BITS+PASS1_BITS+3+1) + & RANGE_MASK]; + outptr[1] = range_limit[(int) DESCALE(tmp12 + tmp0, + CONST_BITS+PASS1_BITS+3+1) + & RANGE_MASK]; + outptr[2] = range_limit[(int) DESCALE(tmp12 - tmp0, + CONST_BITS+PASS1_BITS+3+1) + & RANGE_MASK]; + + wsptr += DCTSIZE; /* advance pointer to next row */ + } +} + + +/* + * Perform dequantization and inverse DCT on one block of coefficients, + * producing a reduced-size 2x2 output block. + */ + +GLOBAL(void) +jpeg_idct_2x2 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + IJG_INT32 tmp0, tmp10, z1; + JCOEFPTR inptr; + ISLOW_MULT_TYPE * quantptr; + int * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + int workspace[DCTSIZE*2]; /* buffers data between passes */ + SHIFT_TEMPS + + /* Pass 1: process columns from input, store into work array. */ + + inptr = coef_block; + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = DCTSIZE; ctr > 0; inptr++, quantptr++, wsptr++, ctr--) { + /* Don't bother to process columns 2,4,6 */ + if (ctr == DCTSIZE-2 || ctr == DCTSIZE-4 || ctr == DCTSIZE-6) + continue; + if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*3] == 0 && + inptr[DCTSIZE*5] == 0 && inptr[DCTSIZE*7] == 0) { + /* AC terms all zero; we need not examine terms 2,4,6 for 2x2 output */ + int dcval = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]) << PASS1_BITS; + + wsptr[DCTSIZE*0] = dcval; + wsptr[DCTSIZE*1] = dcval; + + continue; + } + + /* Even part */ + + z1 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + tmp10 = z1 << (CONST_BITS+2); + + /* Odd part */ + + z1 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); + tmp0 = MULTIPLY(z1, - FIX_0_720959822); /* sqrt(2) * (c7-c5+c3-c1) */ + z1 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); + tmp0 += MULTIPLY(z1, FIX_0_850430095); /* sqrt(2) * (-c1+c3+c5+c7) */ + z1 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + tmp0 += MULTIPLY(z1, - FIX_1_272758580); /* sqrt(2) * (-c1+c3-c5-c7) */ + z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + tmp0 += MULTIPLY(z1, FIX_3_624509785); /* sqrt(2) * (c1+c3+c5+c7) */ + + /* Final output stage */ + + wsptr[DCTSIZE*0] = (int) DESCALE(tmp10 + tmp0, CONST_BITS-PASS1_BITS+2); + wsptr[DCTSIZE*1] = (int) DESCALE(tmp10 - tmp0, CONST_BITS-PASS1_BITS+2); + } + + /* Pass 2: process 2 rows from work array, store into output array. */ + + wsptr = workspace; + for (ctr = 0; ctr < 2; ctr++) { + outptr = output_buf[ctr] + output_col; + /* It's not clear whether a zero row test is worthwhile here ... */ + +#ifndef NO_ZERO_ROW_TEST + if (wsptr[1] == 0 && wsptr[3] == 0 && wsptr[5] == 0 && wsptr[7] == 0) { + /* AC terms all zero */ + JSAMPLE dcval = range_limit[(int) DESCALE((IJG_INT32) wsptr[0], PASS1_BITS+3) + & RANGE_MASK]; + + outptr[0] = dcval; + outptr[1] = dcval; + + wsptr += DCTSIZE; /* advance pointer to next row */ + continue; + } +#endif + + /* Even part */ + + tmp10 = ((IJG_INT32) wsptr[0]) << (CONST_BITS+2); + + /* Odd part */ + + tmp0 = MULTIPLY((IJG_INT32) wsptr[7], - FIX_0_720959822) /* sqrt(2) * (c7-c5+c3-c1) */ + + MULTIPLY((IJG_INT32) wsptr[5], FIX_0_850430095) /* sqrt(2) * (-c1+c3+c5+c7) */ + + MULTIPLY((IJG_INT32) wsptr[3], - FIX_1_272758580) /* sqrt(2) * (-c1+c3-c5-c7) */ + + MULTIPLY((IJG_INT32) wsptr[1], FIX_3_624509785); /* sqrt(2) * (c1+c3+c5+c7) */ + + /* Final output stage */ + + outptr[0] = range_limit[(int) DESCALE(tmp10 + tmp0, + CONST_BITS+PASS1_BITS+3+2) + & RANGE_MASK]; + outptr[1] = range_limit[(int) DESCALE(tmp10 - tmp0, + CONST_BITS+PASS1_BITS+3+2) + & RANGE_MASK]; + + wsptr += DCTSIZE; /* advance pointer to next row */ + } +} + + +/* + * Perform dequantization and inverse DCT on one block of coefficients, + * producing a reduced-size 1x1 output block. + */ + +GLOBAL(void) +jpeg_idct_1x1 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + int dcval; + ISLOW_MULT_TYPE * quantptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + SHIFT_TEMPS + + /* We hardly need an inverse DCT routine for this: just take the + * average pixel value, which is one-eighth of the DC coefficient. + */ + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + dcval = DEQUANTIZE(coef_block[0], quantptr[0]); + dcval = (int) DESCALE((IJG_INT32) dcval, 3); + + output_buf[0][output_col] = range_limit[dcval & RANGE_MASK]; +} + +#endif /* IDCT_SCALING_SUPPORTED */ diff --git a/dcmjpeg/libijg8/jinclude8.h b/dcmjpeg/libijg8/jinclude8.h new file mode 100644 index 00000000..cae1f6cc --- /dev/null +++ b/dcmjpeg/libijg8/jinclude8.h @@ -0,0 +1,91 @@ +/* + * jinclude.h + * + * Copyright (C) 1991-1994, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file exists to provide a single place to fix any problems with + * including the wrong system include files. (Common problems are taken + * care of by the standard jconfig symbols, but on really weird systems + * you may have to edit this file.) + * + * NOTE: this file is NOT intended to be included by applications using the + * JPEG library. Most applications need only include jpeglib.h. + */ + + +/* Include auto-config file to find out which system include files we need. */ + +#include "jconfig8.h" /* auto configuration options */ +#define JCONFIG_INCLUDED /* so that jpeglib.h doesn't do it again */ + +/* + * We need the NULL macro and size_t typedef. + * On an ANSI-conforming system it is sufficient to include . + * Otherwise, we get them from or ; we may have to + * pull in as well. + * Note that the core JPEG library does not require ; + * only the default error handler and data source/destination modules do. + * But we must pull it in because of the references to FILE in jpeglib.h. + * You can remove those references if you want to compile without . + */ + +#ifdef HAVE_STDDEF_H +#include +#endif + +#ifdef HAVE_STDLIB_H +#include +#endif + +#ifdef NEED_SYS_TYPES_H +#include +#endif + +#include + +/* + * We need memory copying and zeroing functions, plus strncpy(). + * ANSI and System V implementations declare these in . + * BSD doesn't have the mem() functions, but it does have bcopy()/bzero(). + * Some systems may declare memset and memcpy in . + * + * NOTE: we assume the size parameters to these functions are of type size_t. + * Change the casts in these macros if not! + */ + +#ifdef NEED_BSD_STRINGS + +#include +#define MEMZERO(target,size) bzero((void *)(target), (size_t)(size)) +#define MEMCOPY(dest,src,size) bcopy((const void *)(src), (void *)(dest), (size_t)(size)) + +#else /* not BSD, assume ANSI/SysV string lib */ + +#include +#define MEMZERO(target,size) memset((void *)(target), 0, (size_t)(size)) +#define MEMCOPY(dest,src,size) memcpy((void *)(dest), (const void *)(src), (size_t)(size)) + +#endif + +/* + * In ANSI C, and indeed any rational implementation, size_t is also the + * type returned by sizeof(). However, it seems there are some irrational + * implementations out there, in which sizeof() returns an int even though + * size_t is defined as long or unsigned long. To ensure consistent results + * we always use this SIZEOF() macro in place of using sizeof() directly. + */ + +#define SIZEOF(object) ((size_t) sizeof(object)) + +/* + * The modules that use fread() and fwrite() always invoke them through + * these macros. On some systems you may need to twiddle the argument casts. + * CAUTION: argument order is different from underlying functions! + */ + +#define JFREAD(file,buf,sizeofbuf) \ + ((size_t) fread((void *) (buf), (size_t) 1, (size_t) (sizeofbuf), (file))) +#define JFWRITE(file,buf,sizeofbuf) \ + ((size_t) fwrite((const void *) (buf), (size_t) 1, (size_t) (sizeofbuf), (file))) diff --git a/dcmjpeg/libijg8/jlossls8.h b/dcmjpeg/libijg8/jlossls8.h new file mode 100644 index 00000000..547b02ea --- /dev/null +++ b/dcmjpeg/libijg8/jlossls8.h @@ -0,0 +1,151 @@ +/* + * jlossls.h + * + * Copyright (C) 1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This include file contains common declarations for the lossless JPEG + * codec modules. + */ + +#ifndef JLOSSLS_H +#define JLOSSLS_H + + +/* + * Table H.1: Predictors for lossless coding. + */ + +#define PREDICTOR1 Ra +#define PREDICTOR2 Rb +#define PREDICTOR3 Rc +#define PREDICTOR4 (int) ((IJG_INT32) Ra + (IJG_INT32) Rb - (IJG_INT32) Rc) +#define PREDICTOR5 (int) ((IJG_INT32) Ra + RIGHT_SHIFT((IJG_INT32) Rb - (IJG_INT32) Rc, 1)) +#define PREDICTOR6 (int) ((IJG_INT32) Rb + RIGHT_SHIFT((IJG_INT32) Ra - (IJG_INT32) Rc, 1)) +#define PREDICTOR7 (int) RIGHT_SHIFT((IJG_INT32) Ra + (IJG_INT32) Rb, 1) + + +typedef JMETHOD(void, predict_difference_method_ptr, + (j_compress_ptr cinfo, int ci, + JSAMPROW input_buf, JSAMPROW prev_row, + JDIFFROW diff_buf, JDIMENSION width)); + +typedef JMETHOD(void, scaler_method_ptr, + (j_compress_ptr cinfo, int ci, + JSAMPROW input_buf, JSAMPROW output_buf, + JDIMENSION width)); + +/* Lossless-specific compression codec (compressor proper) */ +typedef struct { + struct jpeg_c_codec pub; /* public fields */ + + + /* Difference buffer control */ + JMETHOD(void, diff_start_pass, (j_compress_ptr cinfo, + J_BUF_MODE pass_mode)); + + /* Pointer to data which is private to diff controller */ + void *diff_private; + + + /* Entropy encoding */ + JMETHOD(JDIMENSION, entropy_encode_mcus, (j_compress_ptr cinfo, + JDIFFIMAGE diff_buf, + JDIMENSION MCU_row_num, + JDIMENSION MCU_col_num, + JDIMENSION nMCU)); + + /* Pointer to data which is private to entropy module */ + void *entropy_private; + + + /* Prediction, differencing */ + JMETHOD(void, predict_start_pass, (j_compress_ptr cinfo)); + + /* It is useful to allow each component to have a separate diff method. */ + predict_difference_method_ptr predict_difference[MAX_COMPONENTS]; + + /* Pointer to data which is private to predictor module */ + void *pred_private; + + /* Sample scaling */ + JMETHOD(void, scaler_start_pass, (j_compress_ptr cinfo)); + JMETHOD(void, scaler_scale, (j_compress_ptr cinfo, + JSAMPROW input_buf, JSAMPROW output_buf, + JDIMENSION width)); + + /* Pointer to data which is private to scaler module */ + void *scaler_private; + +} jpeg_lossless_c_codec; + +typedef jpeg_lossless_c_codec * j_lossless_c_ptr; + + +typedef JMETHOD(void, predict_undifference_method_ptr, + (j_decompress_ptr cinfo, int comp_index, + JDIFFROW diff_buf, JDIFFROW prev_row, + JDIFFROW undiff_buf, JDIMENSION width)); + +/* Lossless-specific decompression codec (decompressor proper) */ +typedef struct { + struct jpeg_d_codec pub; /* public fields */ + + + /* Difference buffer control */ + JMETHOD(void, diff_start_input_pass, (j_decompress_ptr cinfo)); + + /* Pointer to data which is private to diff controller */ + void *diff_private; + + + /* Entropy decoding */ + JMETHOD(void, entropy_start_pass, (j_decompress_ptr cinfo)); + JMETHOD(boolean, entropy_process_restart, (j_decompress_ptr cinfo)); + JMETHOD(JDIMENSION, entropy_decode_mcus, (j_decompress_ptr cinfo, + JDIFFIMAGE diff_buf, + JDIMENSION MCU_row_num, + JDIMENSION MCU_col_num, + JDIMENSION nMCU)); + + /* Pointer to data which is private to entropy module */ + void *entropy_private; + + + /* Prediction, undifferencing */ + JMETHOD(void, predict_start_pass, (j_decompress_ptr cinfo)); + JMETHOD(void, predict_process_restart, (j_decompress_ptr cinfo)); + + /* It is useful to allow each component to have a separate undiff method. */ + predict_undifference_method_ptr predict_undifference[MAX_COMPONENTS]; + + /* Pointer to data which is private to predictor module */ + void *pred_private; + + /* Sample scaling */ + JMETHOD(void, scaler_start_pass, (j_decompress_ptr cinfo)); + JMETHOD(void, scaler_scale, (j_decompress_ptr cinfo, + JDIFFROW diff_buf, JSAMPROW output_buf, + JDIMENSION width)); + + /* Pointer to data which is private to scaler module */ + void *scaler_private; + +} jpeg_lossless_d_codec; + +typedef jpeg_lossless_d_codec * j_lossless_d_ptr; + + +/* Compression module initialization routines */ +EXTERN(void) jinit_lossless_c_codec JPP((j_compress_ptr cinfo)); +EXTERN(void) jinit_lhuff_encoder JPP((j_compress_ptr cinfo)); +EXTERN(void) jinit_differencer JPP((j_compress_ptr cinfo)); +EXTERN(void) jinit_c_scaler JPP((j_compress_ptr cinfo)); +/* Decompression module initialization routines */ +EXTERN(void) jinit_lossless_d_codec JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_lhuff_decoder JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_undifferencer JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_d_scaler JPP((j_decompress_ptr cinfo)); + +#endif /* JLOSSLS_H */ diff --git a/dcmjpeg/libijg8/jlossy8.h b/dcmjpeg/libijg8/jlossy8.h new file mode 100644 index 00000000..ad4d62b3 --- /dev/null +++ b/dcmjpeg/libijg8/jlossy8.h @@ -0,0 +1,120 @@ +/* + * jlossy.h + * + * Copyright (C) 1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This include file contains common declarations for the lossy (DCT-based) + * JPEG codec modules. + */ + +#ifndef JLOSSY_H +#define JLOSSY_H + + +/* Lossy-specific compression codec (compressor proper) */ +typedef struct { + struct jpeg_c_codec pub; /* public fields */ + + + /* Coefficient buffer control */ + JMETHOD(void, coef_start_pass, (j_compress_ptr cinfo, J_BUF_MODE pass_mode)); + /* JMETHOD(boolean, coef_compress_data, (j_compress_ptr cinfo, + JSAMPIMAGE input_buf));*/ + + /* Pointer to data which is private to coef module */ + void *coef_private; + + + /* Forward DCT (also controls coefficient quantization) */ + JMETHOD(void, fdct_start_pass, (j_compress_ptr cinfo)); + /* perhaps this should be an array??? */ + JMETHOD(void, fdct_forward_DCT, (j_compress_ptr cinfo, + jpeg_component_info * compptr, + JSAMPARRAY sample_data, JBLOCKROW coef_blocks, + JDIMENSION start_row, JDIMENSION start_col, + JDIMENSION num_blocks)); + + /* Pointer to data which is private to fdct module */ + void *fdct_private; + + + /* Entropy encoding */ + JMETHOD(boolean, entropy_encode_mcu, (j_compress_ptr cinfo, + JBLOCKROW *MCU_data)); + + /* Pointer to data which is private to entropy module */ + void *entropy_private; + +} jpeg_lossy_c_codec; + +typedef jpeg_lossy_c_codec * j_lossy_c_ptr; + + + +typedef JMETHOD(void, inverse_DCT_method_ptr, + (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col)); + +/* Lossy-specific decompression codec (decompressor proper) */ +typedef struct { + struct jpeg_d_codec pub; /* public fields */ + + + /* Coefficient buffer control */ + JMETHOD(void, coef_start_input_pass, (j_decompress_ptr cinfo)); + JMETHOD(void, coef_start_output_pass, (j_decompress_ptr cinfo)); + + /* Pointer to array of coefficient virtual arrays, or NULL if none */ + jvirt_barray_ptr *coef_arrays; + + /* Pointer to data which is private to coef module */ + void *coef_private; + + + /* Entropy decoding */ + JMETHOD(void, entropy_start_pass, (j_decompress_ptr cinfo)); + JMETHOD(boolean, entropy_decode_mcu, (j_decompress_ptr cinfo, + JBLOCKROW *MCU_data)); + + /* This is here to share code between baseline and progressive decoders; */ + /* other modules probably should not use it */ + boolean entropy_insufficient_data; /* set TRUE after emitting warning */ + + /* Pointer to data which is private to entropy module */ + void *entropy_private; + + + /* Inverse DCT (also performs dequantization) */ + JMETHOD(void, idct_start_pass, (j_decompress_ptr cinfo)); + + /* It is useful to allow each component to have a separate IDCT method. */ + inverse_DCT_method_ptr inverse_DCT[MAX_COMPONENTS]; + + /* Pointer to data which is private to idct module */ + void *idct_private; + +} jpeg_lossy_d_codec; + +typedef jpeg_lossy_d_codec * j_lossy_d_ptr; + + +/* Compression module initialization routines */ +EXTERN(void) jinit_lossy_c_codec JPP((j_compress_ptr cinfo)); +EXTERN(void) jinit_c_coef_controller JPP((j_compress_ptr cinfo, + boolean need_full_buffer)); +EXTERN(void) jinit_forward_dct JPP((j_compress_ptr cinfo)); +EXTERN(void) jinit_shuff_encoder JPP((j_compress_ptr cinfo)); +EXTERN(void) jinit_phuff_encoder JPP((j_compress_ptr cinfo)); + +/* Decompression module initialization routines */ +EXTERN(void) jinit_lossy_d_codec JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_d_coef_controller JPP((j_decompress_ptr cinfo, + boolean need_full_buffer)); +EXTERN(void) jinit_shuff_decoder JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_phuff_decoder JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_inverse_dct JPP((j_decompress_ptr cinfo)); + +#endif /* JLOSSY_H */ diff --git a/dcmjpeg/libijg8/jmemmgr.c b/dcmjpeg/libijg8/jmemmgr.c new file mode 100644 index 00000000..c0ed4248 --- /dev/null +++ b/dcmjpeg/libijg8/jmemmgr.c @@ -0,0 +1,1174 @@ +/* + * jmemmgr.c + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains the JPEG system-independent memory management + * routines. This code is usable across a wide variety of machines; most + * of the system dependencies have been isolated in a separate file. + * The major functions provided here are: + * * pool-based allocation and freeing of memory; + * * policy decisions about how to divide available memory among the + * virtual arrays; + * * control logic for swapping virtual arrays between main memory and + * backing storage. + * The separate system-dependent file provides the actual backing-storage + * access code, and it contains the policy decision about how much total + * main memory to use. + * This file is system-dependent in the sense that some of its functions + * are unnecessary in some systems. For example, if there is enough virtual + * memory so that backing storage will never be used, much of the virtual + * array control logic could be removed. (Of course, if you have that much + * memory then you shouldn't care about a little bit of unused code...) + */ + +#define JPEG_INTERNALS +#define AM_MEMORY_MANAGER /* we define jvirt_Xarray_control structs */ +#include "jinclude8.h" +#include "jpeglib8.h" +#include "jmemsys8.h" /* import the system-dependent declarations */ + +#ifndef NO_GETENV +#ifndef HAVE_STDLIB_H /* should declare getenv() */ +extern char * getenv JPP((const char * name)); +#endif +#endif + + +/* + * Some important notes: + * The allocation routines provided here must never return NULL. + * They should exit to error_exit if unsuccessful. + * + * It's not a good idea to try to merge the sarray, barray and darray + * routines, even though they are textually almost the same, because + * samples are usually stored as bytes while coefficients and differenced + * are shorts or ints. Thus, in machines where byte pointers have a + * different representation from word pointers, the resulting machine + * code could not be the same. + */ + + +/* + * Many machines require storage alignment: longs must start on 4-byte + * boundaries, doubles on 8-byte boundaries, etc. On such machines, malloc() + * always returns pointers that are multiples of the worst-case alignment + * requirement, and we had better do so too. + * There isn't any really portable way to determine the worst-case alignment + * requirement. This module assumes that the alignment requirement is + * multiples of sizeof(ALIGN_TYPE). + * By default, we define ALIGN_TYPE as double. This is necessary on some + * workstations (where doubles really do need 8-byte alignment) and will work + * fine on nearly everything. If your machine has lesser alignment needs, + * you can save a few bytes by making ALIGN_TYPE smaller. + * The only place I know of where this will NOT work is certain Macintosh + * 680x0 compilers that define double as a 10-byte IEEE extended float. + * Doing 10-byte alignment is counterproductive because longwords won't be + * aligned well. Put "#define ALIGN_TYPE long" in jconfig.h if you have + * such a compiler. + */ + +#ifndef ALIGN_TYPE /* so can override from jconfig.h */ +#define ALIGN_TYPE double +#endif + + +/* + * We allocate objects from "pools", where each pool is gotten with a single + * request to jpeg_get_small() or jpeg_get_large(). There is no per-object + * overhead within a pool, except for alignment padding. Each pool has a + * header with a link to the next pool of the same class. + * Small and large pool headers are identical except that the latter's + * link pointer must be FAR on 80x86 machines. + * Notice that the "real" header fields are union'ed with a dummy ALIGN_TYPE + * field. This forces the compiler to make SIZEOF(small_pool_hdr) a multiple + * of the alignment requirement of ALIGN_TYPE. + */ + +typedef union small_pool_struct * small_pool_ptr; + +typedef union small_pool_struct { + struct { + small_pool_ptr next; /* next in list of pools */ + size_t bytes_used; /* how many bytes already used within pool */ + size_t bytes_left; /* bytes still available in this pool */ + } hdr; + ALIGN_TYPE dummy; /* included in union to ensure alignment */ +} small_pool_hdr; + +typedef union large_pool_struct FAR * large_pool_ptr; + +typedef union large_pool_struct { + struct { + large_pool_ptr next; /* next in list of pools */ + size_t bytes_used; /* how many bytes already used within pool */ + size_t bytes_left; /* bytes still available in this pool */ + } hdr; + ALIGN_TYPE dummy; /* included in union to ensure alignment */ +} large_pool_hdr; + + +/* + * Here is the full definition of a memory manager object. + */ + +typedef struct { + struct jpeg_memory_mgr pub; /* public fields */ + + /* Each pool identifier (lifetime class) names a linked list of pools. */ + small_pool_ptr small_list[JPOOL_NUMPOOLS]; + large_pool_ptr large_list[JPOOL_NUMPOOLS]; + + /* Since we only have one lifetime class of virtual arrays, only one + * linked list is necessary (for each datatype). Note that the virtual + * array control blocks being linked together are actually stored somewhere + * in the small-pool list. + */ + jvirt_sarray_ptr virt_sarray_list; + jvirt_barray_ptr virt_barray_list; + + /* This counts total space obtained from jpeg_get_small/large */ + long total_space_allocated; + + /* alloc_sarray and alloc_barray set this value for use by virtual + * array routines. + */ + JDIMENSION last_rowsperchunk; /* from most recent alloc_sarray/barray */ +} my_memory_mgr; + +typedef my_memory_mgr * my_mem_ptr; + + +/* + * The control blocks for virtual arrays. + * Note that these blocks are allocated in the "small" pool area. + * System-dependent info for the associated backing store (if any) is hidden + * inside the backing_store_info struct. + */ + +struct jvirt_sarray_control { + JSAMPARRAY mem_buffer; /* => the in-memory buffer */ + JDIMENSION rows_in_array; /* total virtual array height */ + JDIMENSION samplesperrow; /* width of array (and of memory buffer) */ + JDIMENSION maxaccess; /* max rows accessed by access_virt_sarray */ + JDIMENSION rows_in_mem; /* height of memory buffer */ + JDIMENSION rowsperchunk; /* allocation chunk size in mem_buffer */ + JDIMENSION cur_start_row; /* first logical row # in the buffer */ + JDIMENSION first_undef_row; /* row # of first uninitialized row */ + boolean pre_zero; /* pre-zero mode requested? */ + boolean dirty; /* do current buffer contents need written? */ + boolean b_s_open; /* is backing-store data valid? */ + jvirt_sarray_ptr next; /* link to next virtual sarray control block */ + backing_store_info b_s_info; /* System-dependent control info */ +}; + +struct jvirt_barray_control { + JBLOCKARRAY mem_buffer; /* => the in-memory buffer */ + JDIMENSION rows_in_array; /* total virtual array height */ + JDIMENSION blocksperrow; /* width of array (and of memory buffer) */ + JDIMENSION maxaccess; /* max rows accessed by access_virt_barray */ + JDIMENSION rows_in_mem; /* height of memory buffer */ + JDIMENSION rowsperchunk; /* allocation chunk size in mem_buffer */ + JDIMENSION cur_start_row; /* first logical row # in the buffer */ + JDIMENSION first_undef_row; /* row # of first uninitialized row */ + boolean pre_zero; /* pre-zero mode requested? */ + boolean dirty; /* do current buffer contents need written? */ + boolean b_s_open; /* is backing-store data valid? */ + jvirt_barray_ptr next; /* link to next virtual barray control block */ + backing_store_info b_s_info; /* System-dependent control info */ +}; + + +#ifdef MEM_STATS /* optional extra stuff for statistics */ + +LOCAL(void) +print_mem_stats (j_common_ptr cinfo, int pool_id) +{ + my_mem_ptr mem = (my_mem_ptr) cinfo->mem; + small_pool_ptr shdr_ptr; + large_pool_ptr lhdr_ptr; + + /* Since this is only a debugging stub, we can cheat a little by using + * fprintf directly rather than going through the trace message code. + * This is helpful because message parm array can't handle longs. + */ + fprintf(stderr, "Freeing pool %d, total space = %ld\n", + pool_id, mem->total_space_allocated); + + for (lhdr_ptr = mem->large_list[pool_id]; lhdr_ptr != NULL; + lhdr_ptr = lhdr_ptr->hdr.next) { + fprintf(stderr, " Large chunk used %ld\n", + (long) lhdr_ptr->hdr.bytes_used); + } + + for (shdr_ptr = mem->small_list[pool_id]; shdr_ptr != NULL; + shdr_ptr = shdr_ptr->hdr.next) { + fprintf(stderr, " Small chunk used %ld free %ld\n", + (long) shdr_ptr->hdr.bytes_used, + (long) shdr_ptr->hdr.bytes_left); + } +} + +#endif /* MEM_STATS */ + + +LOCAL(void) +out_of_memory (j_common_ptr cinfo, int which) +/* Report an out-of-memory error and stop execution */ +/* If we compiled MEM_STATS support, report alloc requests before dying */ +{ +#ifdef MEM_STATS + cinfo->err->trace_level = 2; /* force self_destruct to report stats */ +#endif + ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, which); +} + + +/* + * Allocation of "small" objects. + * + * For these, we use pooled storage. When a new pool must be created, + * we try to get enough space for the current request plus a "slop" factor, + * where the slop will be the amount of leftover space in the new pool. + * The speed vs. space tradeoff is largely determined by the slop values. + * A different slop value is provided for each pool class (lifetime), + * and we also distinguish the first pool of a class from later ones. + * NOTE: the values given work fairly well on both 16- and 32-bit-int + * machines, but may be too small if longs are 64 bits or more. + */ + +static const size_t first_pool_slop[JPOOL_NUMPOOLS] = +{ + 1600, /* first PERMANENT pool */ + 16000 /* first IMAGE pool */ +}; + +static const size_t extra_pool_slop[JPOOL_NUMPOOLS] = +{ + 0, /* additional PERMANENT pools */ + 5000 /* additional IMAGE pools */ +}; + +#define MIN_SLOP 50 /* greater than 0 to avoid futile looping */ + + +METHODDEF(void *) +alloc_small (j_common_ptr cinfo, int pool_id, size_t sizeofobject) +/* Allocate a "small" object */ +{ + my_mem_ptr mem = (my_mem_ptr) cinfo->mem; + small_pool_ptr hdr_ptr, prev_hdr_ptr; + char * data_ptr; + size_t odd_bytes, min_request, slop; + + /* Check for unsatisfiable request (do now to ensure no overflow below) */ + if (sizeofobject > (size_t) (MAX_ALLOC_CHUNK-SIZEOF(small_pool_hdr))) + out_of_memory(cinfo, 1); /* request exceeds malloc's ability */ + + /* Round up the requested size to a multiple of SIZEOF(ALIGN_TYPE) */ + odd_bytes = sizeofobject % SIZEOF(ALIGN_TYPE); + if (odd_bytes > 0) + sizeofobject += SIZEOF(ALIGN_TYPE) - odd_bytes; + + /* See if space is available in any existing pool */ + if (pool_id < 0 || pool_id >= JPOOL_NUMPOOLS) + ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */ + prev_hdr_ptr = NULL; + hdr_ptr = mem->small_list[pool_id]; + while (hdr_ptr != NULL) { + if (hdr_ptr->hdr.bytes_left >= sizeofobject) + break; /* found pool with enough space */ + prev_hdr_ptr = hdr_ptr; + hdr_ptr = hdr_ptr->hdr.next; + } + + /* Time to make a new pool? */ + if (hdr_ptr == NULL) { + /* min_request is what we need now, slop is what will be leftover */ + min_request = sizeofobject + SIZEOF(small_pool_hdr); + if (prev_hdr_ptr == NULL) /* first pool in class? */ + slop = first_pool_slop[pool_id]; + else + slop = extra_pool_slop[pool_id]; + /* Don't ask for more than MAX_ALLOC_CHUNK */ + if (slop > (size_t) (MAX_ALLOC_CHUNK-min_request)) + slop = (size_t) (MAX_ALLOC_CHUNK-min_request); + /* Try to get space, if fail reduce slop and try again */ + for (;;) { + hdr_ptr = (small_pool_ptr) jpeg_get_small(cinfo, min_request + slop); + if (hdr_ptr != NULL) + break; + slop /= 2; + if (slop < MIN_SLOP) /* give up when it gets real small */ + out_of_memory(cinfo, 2); /* jpeg_get_small failed */ + } + mem->total_space_allocated += (long)(min_request + slop); + /* Success, initialize the new pool header and add to end of list */ + hdr_ptr->hdr.next = NULL; + hdr_ptr->hdr.bytes_used = 0; + hdr_ptr->hdr.bytes_left = sizeofobject + slop; + if (prev_hdr_ptr == NULL) /* first pool in class? */ + mem->small_list[pool_id] = hdr_ptr; + else + prev_hdr_ptr->hdr.next = hdr_ptr; + } + + /* OK, allocate the object from the current pool */ + data_ptr = (char *) (hdr_ptr + 1); /* point to first data byte in pool */ + data_ptr += hdr_ptr->hdr.bytes_used; /* point to place for object */ + hdr_ptr->hdr.bytes_used += sizeofobject; + hdr_ptr->hdr.bytes_left -= sizeofobject; + + return (void *) data_ptr; +} + + +/* + * Allocation of "large" objects. + * + * The external semantics of these are the same as "small" objects, + * except that FAR pointers are used on 80x86. However the pool + * management heuristics are quite different. We assume that each + * request is large enough that it may as well be passed directly to + * jpeg_get_large; the pool management just links everything together + * so that we can free it all on demand. + * Note: the major use of "large" objects is in JSAMPARRAY and JBLOCKARRAY + * structures. The routines that create these structures (see below) + * deliberately bunch rows together to ensure a large request size. + */ + +METHODDEF(void FAR *) +alloc_large (j_common_ptr cinfo, int pool_id, size_t sizeofobject) +/* Allocate a "large" object */ +{ + my_mem_ptr mem = (my_mem_ptr) cinfo->mem; + large_pool_ptr hdr_ptr; + size_t odd_bytes; + + /* Check for unsatisfiable request (do now to ensure no overflow below) */ + if (sizeofobject > (size_t) (MAX_ALLOC_CHUNK-SIZEOF(large_pool_hdr))) + out_of_memory(cinfo, 3); /* request exceeds malloc's ability */ + + /* Round up the requested size to a multiple of SIZEOF(ALIGN_TYPE) */ + odd_bytes = sizeofobject % SIZEOF(ALIGN_TYPE); + if (odd_bytes > 0) + sizeofobject += SIZEOF(ALIGN_TYPE) - odd_bytes; + + /* Always make a new pool */ + if (pool_id < 0 || pool_id >= JPOOL_NUMPOOLS) + ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */ + + hdr_ptr = (large_pool_ptr) jpeg_get_large(cinfo, sizeofobject + + SIZEOF(large_pool_hdr)); + if (hdr_ptr == NULL) + out_of_memory(cinfo, 4); /* jpeg_get_large failed */ + mem->total_space_allocated += (long)(sizeofobject + SIZEOF(large_pool_hdr)); + + /* Success, initialize the new pool header and add to list */ + hdr_ptr->hdr.next = mem->large_list[pool_id]; + /* We maintain space counts in each pool header for statistical purposes, + * even though they are not needed for allocation. + */ + hdr_ptr->hdr.bytes_used = sizeofobject; + hdr_ptr->hdr.bytes_left = 0; + mem->large_list[pool_id] = hdr_ptr; + + return (void FAR *) (hdr_ptr + 1); /* point to first data byte in pool */ +} + + +/* + * Creation of 2-D sample arrays. + * The pointers are in near heap, the samples themselves in FAR heap. + * + * To minimize allocation overhead and to allow I/O of large contiguous + * blocks, we allocate the sample rows in groups of as many rows as possible + * without exceeding MAX_ALLOC_CHUNK total bytes per allocation request. + * NB: the virtual array control routines, later in this file, know about + * this chunking of rows. The rowsperchunk value is left in the mem manager + * object so that it can be saved away if this sarray is the workspace for + * a virtual array. + */ + +METHODDEF(JSAMPARRAY) +alloc_sarray (j_common_ptr cinfo, int pool_id, + JDIMENSION samplesperrow, JDIMENSION numrows) +/* Allocate a 2-D sample array */ +{ + my_mem_ptr mem = (my_mem_ptr) cinfo->mem; + JSAMPARRAY result; + JSAMPROW workspace; + JDIMENSION rowsperchunk, currow, i; + size_t ltemp; + + /* Calculate max # of rows allowed in one allocation chunk */ + ltemp = (MAX_ALLOC_CHUNK-SIZEOF(large_pool_hdr)) / + ((size_t) samplesperrow * SIZEOF(JSAMPLE)); + if (ltemp <= 0) + ERREXIT(cinfo, JERR_WIDTH_OVERFLOW); + if (ltemp < numrows) + rowsperchunk = (JDIMENSION) ltemp; + else + rowsperchunk = numrows; + mem->last_rowsperchunk = rowsperchunk; + + /* Get space for row pointers (small object) */ + result = (JSAMPARRAY) alloc_small(cinfo, pool_id, + (size_t) (numrows * SIZEOF(JSAMPROW))); + + /* Get the rows themselves (large objects) */ + currow = 0; + while (currow < numrows) { + rowsperchunk = MIN(rowsperchunk, numrows - currow); + workspace = (JSAMPROW) alloc_large(cinfo, pool_id, + (size_t) ((size_t) rowsperchunk * (size_t) samplesperrow + * SIZEOF(JSAMPLE))); + for (i = rowsperchunk; i > 0; i--) { + result[currow++] = workspace; + workspace += samplesperrow; + } + } + + return result; +} + + +/* + * Creation of 2-D coefficient-block arrays. + * This is essentially the same as the code for sample arrays, above. + */ + +METHODDEF(JBLOCKARRAY) +alloc_barray (j_common_ptr cinfo, int pool_id, + JDIMENSION blocksperrow, JDIMENSION numrows) +/* Allocate a 2-D coefficient-block array */ +{ + my_mem_ptr mem = (my_mem_ptr) cinfo->mem; + JBLOCKARRAY result; + JBLOCKROW workspace; + JDIMENSION rowsperchunk, currow, i; + size_t ltemp; + + /* Calculate max # of rows allowed in one allocation chunk */ + ltemp = (MAX_ALLOC_CHUNK-SIZEOF(large_pool_hdr)) / + ((size_t) blocksperrow * SIZEOF(JBLOCK)); + if (ltemp <= 0) + ERREXIT(cinfo, JERR_WIDTH_OVERFLOW); + if (ltemp < numrows) + rowsperchunk = (JDIMENSION) ltemp; + else + rowsperchunk = numrows; + mem->last_rowsperchunk = rowsperchunk; + + /* Get space for row pointers (small object) */ + result = (JBLOCKARRAY) alloc_small(cinfo, pool_id, + (size_t) (numrows * SIZEOF(JBLOCKROW))); + + /* Get the rows themselves (large objects) */ + currow = 0; + while (currow < numrows) { + rowsperchunk = MIN(rowsperchunk, numrows - currow); + workspace = (JBLOCKROW) alloc_large(cinfo, pool_id, + (size_t) ((size_t) rowsperchunk * (size_t) blocksperrow + * SIZEOF(JBLOCK))); + for (i = rowsperchunk; i > 0; i--) { + result[currow++] = workspace; + workspace += blocksperrow; + } + } + + return result; +} + + +#ifdef NEED_DARRAY + +/* + * Creation of 2-D difference arrays. + * This is essentially the same as the code for sample arrays, above. + */ + +METHODDEF(JDIFFARRAY) +alloc_darray (j_common_ptr cinfo, int pool_id, + JDIMENSION diffsperrow, JDIMENSION numrows) +/* Allocate a 2-D difference array */ +{ + my_mem_ptr mem = (my_mem_ptr) cinfo->mem; + JDIFFARRAY result; + JDIFFROW workspace; + JDIMENSION rowsperchunk, currow, i; + size_t ltemp; + + /* Calculate max # of rows allowed in one allocation chunk */ + ltemp = (MAX_ALLOC_CHUNK-SIZEOF(large_pool_hdr)) / + ((size_t) diffsperrow * SIZEOF(JDIFF)); + if (ltemp <= 0) + ERREXIT(cinfo, JERR_WIDTH_OVERFLOW); + if (ltemp < numrows) + rowsperchunk = (JDIMENSION) ltemp; + else + rowsperchunk = numrows; + mem->last_rowsperchunk = rowsperchunk; + + /* Get space for row pointers (small object) */ + result = (JDIFFARRAY) alloc_small(cinfo, pool_id, + (size_t) (numrows * SIZEOF(JDIFFROW))); + + /* Get the rows themselves (large objects) */ + currow = 0; + while (currow < numrows) { + rowsperchunk = MIN(rowsperchunk, numrows - currow); + workspace = (JDIFFROW) alloc_large(cinfo, pool_id, + (size_t) ((size_t) rowsperchunk * (size_t) diffsperrow + * SIZEOF(JDIFF))); + for (i = rowsperchunk; i > 0; i--) { + result[currow++] = workspace; + workspace += diffsperrow; + } + } + + return result; +} + +#endif + + +/* + * About virtual array management: + * + * The above "normal" array routines are only used to allocate strip buffers + * (as wide as the image, but just a few rows high). Full-image-sized buffers + * are handled as "virtual" arrays. The array is still accessed a strip at a + * time, but the memory manager must save the whole array for repeated + * accesses. The intended implementation is that there is a strip buffer in + * memory (as high as is possible given the desired memory limit), plus a + * backing file that holds the rest of the array. + * + * The request_virt_array routines are told the total size of the image and + * the maximum number of rows that will be accessed at once. The in-memory + * buffer must be at least as large as the maxaccess value. + * + * The request routines create control blocks but not the in-memory buffers. + * That is postponed until realize_virt_arrays is called. At that time the + * total amount of space needed is known (approximately, anyway), so free + * memory can be divided up fairly. + * + * The access_virt_array routines are responsible for making a specific strip + * area accessible (after reading or writing the backing file, if necessary). + * Note that the access routines are told whether the caller intends to modify + * the accessed strip; during a read-only pass this saves having to rewrite + * data to disk. The access routines are also responsible for pre-zeroing + * any newly accessed rows, if pre-zeroing was requested. + * + * In current usage, the access requests are usually for nonoverlapping + * strips; that is, successive access start_row numbers differ by exactly + * num_rows = maxaccess. This means we can get good performance with simple + * buffer dump/reload logic, by making the in-memory buffer be a multiple + * of the access height; then there will never be accesses across bufferload + * boundaries. The code will still work with overlapping access requests, + * but it doesn't handle bufferload overlaps very efficiently. + */ + + +METHODDEF(jvirt_sarray_ptr) +request_virt_sarray (j_common_ptr cinfo, int pool_id, boolean pre_zero, + JDIMENSION samplesperrow, JDIMENSION numrows, + JDIMENSION maxaccess) +/* Request a virtual 2-D sample array */ +{ + my_mem_ptr mem = (my_mem_ptr) cinfo->mem; + jvirt_sarray_ptr result; + + /* Only IMAGE-lifetime virtual arrays are currently supported */ + if (pool_id != JPOOL_IMAGE) + ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */ + + /* get control block */ + result = (jvirt_sarray_ptr) alloc_small(cinfo, pool_id, + SIZEOF(struct jvirt_sarray_control)); + + result->mem_buffer = NULL; /* marks array not yet realized */ + result->rows_in_array = numrows; + result->samplesperrow = samplesperrow; + result->maxaccess = maxaccess; + result->pre_zero = pre_zero; + result->b_s_open = FALSE; /* no associated backing-store object */ + result->next = mem->virt_sarray_list; /* add to list of virtual arrays */ + mem->virt_sarray_list = result; + + return result; +} + + +METHODDEF(jvirt_barray_ptr) +request_virt_barray (j_common_ptr cinfo, int pool_id, boolean pre_zero, + JDIMENSION blocksperrow, JDIMENSION numrows, + JDIMENSION maxaccess) +/* Request a virtual 2-D coefficient-block array */ +{ + my_mem_ptr mem = (my_mem_ptr) cinfo->mem; + jvirt_barray_ptr result; + + /* Only IMAGE-lifetime virtual arrays are currently supported */ + if (pool_id != JPOOL_IMAGE) + ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */ + + /* get control block */ + result = (jvirt_barray_ptr) alloc_small(cinfo, pool_id, + SIZEOF(struct jvirt_barray_control)); + + result->mem_buffer = NULL; /* marks array not yet realized */ + result->rows_in_array = numrows; + result->blocksperrow = blocksperrow; + result->maxaccess = maxaccess; + result->pre_zero = pre_zero; + result->b_s_open = FALSE; /* no associated backing-store object */ + result->next = mem->virt_barray_list; /* add to list of virtual arrays */ + mem->virt_barray_list = result; + + return result; +} + + +METHODDEF(void) +realize_virt_arrays (j_common_ptr cinfo) +/* Allocate the in-memory buffers for any unrealized virtual arrays */ +{ + my_mem_ptr mem = (my_mem_ptr) cinfo->mem; + size_t space_per_minheight, maximum_space, avail_mem; + size_t minheights, max_minheights; + jvirt_sarray_ptr sptr; + jvirt_barray_ptr bptr; + + /* Compute the minimum space needed (maxaccess rows in each buffer) + * and the maximum space needed (full image height in each buffer). + * These may be of use to the system-dependent jpeg_mem_available routine. + */ + space_per_minheight = 0; + maximum_space = 0; + for (sptr = mem->virt_sarray_list; sptr != NULL; sptr = sptr->next) { + if (sptr->mem_buffer == NULL) { /* if not realized yet */ + space_per_minheight += sptr->maxaccess * + sptr->samplesperrow * SIZEOF(JSAMPLE); + maximum_space += sptr->rows_in_array * + sptr->samplesperrow * SIZEOF(JSAMPLE); + } + } + for (bptr = mem->virt_barray_list; bptr != NULL; bptr = bptr->next) { + if (bptr->mem_buffer == NULL) { /* if not realized yet */ + space_per_minheight += bptr->maxaccess * + bptr->blocksperrow * SIZEOF(JBLOCK); + maximum_space += bptr->rows_in_array * + bptr->blocksperrow * SIZEOF(JBLOCK); + } + } + + if (space_per_minheight <= 0) + return; /* no unrealized arrays, no work */ + + /* Determine amount of memory to actually use; this is system-dependent. */ + avail_mem = (size_t)jpeg_mem_available(cinfo, (long)space_per_minheight, (long)maximum_space, + mem->total_space_allocated); + + /* If the maximum space needed is available, make all the buffers full + * height; otherwise parcel it out with the same number of minheights + * in each buffer. + */ + if (avail_mem >= maximum_space) + max_minheights = 1000000000L; + else { + max_minheights = avail_mem / space_per_minheight; + /* If there doesn't seem to be enough space, try to get the minimum + * anyway. This allows a "stub" implementation of jpeg_mem_available(). + */ + if (max_minheights <= 0) + max_minheights = 1; + } + + /* Allocate the in-memory buffers and initialize backing store as needed. */ + + for (sptr = mem->virt_sarray_list; sptr != NULL; sptr = sptr->next) { + if (sptr->mem_buffer == NULL) { /* if not realized yet */ + minheights = (size_t)((sptr->rows_in_array - 1L) / sptr->maxaccess + 1L); + if (minheights <= max_minheights) { + /* This buffer fits in memory */ + sptr->rows_in_mem = sptr->rows_in_array; + } else { + /* It doesn't fit in memory, create backing store. */ + sptr->rows_in_mem = (JDIMENSION)max_minheights * sptr->maxaccess; + jpeg_open_backing_store(cinfo, & sptr->b_s_info, + (long) sptr->rows_in_array * + (long) sptr->samplesperrow * + (long) SIZEOF(JSAMPLE)); + sptr->b_s_open = TRUE; + } + sptr->mem_buffer = alloc_sarray(cinfo, JPOOL_IMAGE, + sptr->samplesperrow, sptr->rows_in_mem); + sptr->rowsperchunk = mem->last_rowsperchunk; + sptr->cur_start_row = 0; + sptr->first_undef_row = 0; + sptr->dirty = FALSE; + } + } + + for (bptr = mem->virt_barray_list; bptr != NULL; bptr = bptr->next) { + if (bptr->mem_buffer == NULL) { /* if not realized yet */ + minheights = (size_t)((bptr->rows_in_array - 1L) / bptr->maxaccess + 1L); + if (minheights <= max_minheights) { + /* This buffer fits in memory */ + bptr->rows_in_mem = bptr->rows_in_array; + } else { + /* It doesn't fit in memory, create backing store. */ + bptr->rows_in_mem = (JDIMENSION)max_minheights * bptr->maxaccess; + jpeg_open_backing_store(cinfo, & bptr->b_s_info, + (long) bptr->rows_in_array * + (long) bptr->blocksperrow * + (long) SIZEOF(JBLOCK)); + bptr->b_s_open = TRUE; + } + bptr->mem_buffer = alloc_barray(cinfo, JPOOL_IMAGE, + bptr->blocksperrow, bptr->rows_in_mem); + bptr->rowsperchunk = mem->last_rowsperchunk; + bptr->cur_start_row = 0; + bptr->first_undef_row = 0; + bptr->dirty = FALSE; + } + } +} + + +LOCAL(void) +do_sarray_io (j_common_ptr cinfo, jvirt_sarray_ptr ptr, boolean writing) +/* Do backing store read or write of a virtual sample array */ +{ + size_t bytesperrow, file_offset, byte_count, rows, thisrow, i; + + bytesperrow = ptr->samplesperrow * SIZEOF(JSAMPLE); + file_offset = ptr->cur_start_row * bytesperrow; + /* Loop to read or write each allocation chunk in mem_buffer */ + for (i = 0; i < ptr->rows_in_mem; i += ptr->rowsperchunk) { + /* One chunk, but check for short chunk at end of buffer */ + rows = MIN(ptr->rowsperchunk, ptr->rows_in_mem - i); + /* Transfer no more than is currently defined */ + thisrow = ptr->cur_start_row + i; + rows = MIN(rows, ptr->first_undef_row - thisrow); + /* Transfer no more than fits in file */ + rows = MIN(rows, ptr->rows_in_array - thisrow); + if (rows <= 0) /* this chunk might be past end of file! */ + break; + byte_count = rows * bytesperrow; + if (writing) + (*ptr->b_s_info.write_backing_store) (cinfo, & ptr->b_s_info, + (void FAR *) ptr->mem_buffer[i], + (long)file_offset, (long)byte_count); + else + (*ptr->b_s_info.read_backing_store) (cinfo, & ptr->b_s_info, + (void FAR *) ptr->mem_buffer[i], + (long)file_offset, (long)byte_count); + file_offset += byte_count; + } +} + + +LOCAL(void) +do_barray_io (j_common_ptr cinfo, jvirt_barray_ptr ptr, boolean writing) +/* Do backing store read or write of a virtual coefficient-block array */ +{ + size_t bytesperrow, file_offset, byte_count, rows, thisrow, i; + + bytesperrow = ptr->blocksperrow * SIZEOF(JBLOCK); + file_offset = ptr->cur_start_row * bytesperrow; + /* Loop to read or write each allocation chunk in mem_buffer */ + for (i = 0; i < ptr->rows_in_mem; i += ptr->rowsperchunk) { + /* One chunk, but check for short chunk at end of buffer */ + rows = MIN(ptr->rowsperchunk, ptr->rows_in_mem - i); + /* Transfer no more than is currently defined */ + thisrow = ptr->cur_start_row + i; + rows = MIN(rows, ptr->first_undef_row - thisrow); + /* Transfer no more than fits in file */ + rows = MIN(rows, ptr->rows_in_array - thisrow); + if (rows <= 0) /* this chunk might be past end of file! */ + break; + byte_count = rows * bytesperrow; + if (writing) + (*ptr->b_s_info.write_backing_store) (cinfo, & ptr->b_s_info, + (void FAR *) ptr->mem_buffer[i], + (long)file_offset, (long)byte_count); + else + (*ptr->b_s_info.read_backing_store) (cinfo, & ptr->b_s_info, + (void FAR *) ptr->mem_buffer[i], + (long)file_offset, (long)byte_count); + file_offset += byte_count; + } +} + + +METHODDEF(JSAMPARRAY) +access_virt_sarray (j_common_ptr cinfo, jvirt_sarray_ptr ptr, + JDIMENSION start_row, JDIMENSION num_rows, + boolean writable) +/* Access the part of a virtual sample array starting at start_row */ +/* and extending for num_rows rows. writable is true if */ +/* caller intends to modify the accessed area. */ +{ + JDIMENSION end_row = start_row + num_rows; + JDIMENSION undef_row; + + /* debugging check */ + if (end_row > ptr->rows_in_array || num_rows > ptr->maxaccess || + ptr->mem_buffer == NULL) + ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS); + + /* Make the desired part of the virtual array accessible */ + if (start_row < ptr->cur_start_row || + end_row > ptr->cur_start_row+ptr->rows_in_mem) { + if (! ptr->b_s_open) + ERREXIT(cinfo, JERR_VIRTUAL_BUG); + /* Flush old buffer contents if necessary */ + if (ptr->dirty) { + do_sarray_io(cinfo, ptr, TRUE); + ptr->dirty = FALSE; + } + /* Decide what part of virtual array to access. + * Algorithm: if target address > current window, assume forward scan, + * load starting at target address. If target address < current window, + * assume backward scan, load so that target area is top of window. + * Note that when switching from forward write to forward read, will have + * start_row = 0, so the limiting case applies and we load from 0 anyway. + */ + if (start_row > ptr->cur_start_row) { + ptr->cur_start_row = start_row; + } else { + /* use long arithmetic here to avoid overflow & unsigned problems */ + long ltemp; + + ltemp = (long) end_row - (long) ptr->rows_in_mem; + if (ltemp < 0) + ltemp = 0; /* don't fall off front end of file */ + ptr->cur_start_row = (JDIMENSION) ltemp; + } + /* Read in the selected part of the array. + * During the initial write pass, we will do no actual read + * because the selected part is all undefined. + */ + do_sarray_io(cinfo, ptr, FALSE); + } + /* Ensure the accessed part of the array is defined; prezero if needed. + * To improve locality of access, we only prezero the part of the array + * that the caller is about to access, not the entire in-memory array. + */ + if (ptr->first_undef_row < end_row) { + if (ptr->first_undef_row < start_row) { + if (writable) /* writer skipped over a section of array */ + ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS); + undef_row = start_row; /* but reader is allowed to read ahead */ + } else { + undef_row = ptr->first_undef_row; + } + if (writable) + ptr->first_undef_row = end_row; + if (ptr->pre_zero) { + size_t bytesperrow = (size_t) ptr->samplesperrow * SIZEOF(JSAMPLE); + undef_row -= ptr->cur_start_row; /* make indexes relative to buffer */ + end_row -= ptr->cur_start_row; + while (undef_row < end_row) { + jzero_far((void FAR *) ptr->mem_buffer[undef_row], bytesperrow); + undef_row++; + } + } else { + if (! writable) /* reader looking at undefined data */ + ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS); + } + } + /* Flag the buffer dirty if caller will write in it */ + if (writable) + ptr->dirty = TRUE; + /* Return address of proper part of the buffer */ + return ptr->mem_buffer + (start_row - ptr->cur_start_row); +} + + +METHODDEF(JBLOCKARRAY) +access_virt_barray (j_common_ptr cinfo, jvirt_barray_ptr ptr, + JDIMENSION start_row, JDIMENSION num_rows, + boolean writable) +/* Access the part of a virtual block array starting at start_row */ +/* and extending for num_rows rows. writable is true if */ +/* caller intends to modify the accessed area. */ +{ + JDIMENSION end_row = start_row + num_rows; + JDIMENSION undef_row; + + /* debugging check */ + if (end_row > ptr->rows_in_array || num_rows > ptr->maxaccess || + ptr->mem_buffer == NULL) + ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS); + + /* Make the desired part of the virtual array accessible */ + if (start_row < ptr->cur_start_row || + end_row > ptr->cur_start_row+ptr->rows_in_mem) { + if (! ptr->b_s_open) + ERREXIT(cinfo, JERR_VIRTUAL_BUG); + /* Flush old buffer contents if necessary */ + if (ptr->dirty) { + do_barray_io(cinfo, ptr, TRUE); + ptr->dirty = FALSE; + } + /* Decide what part of virtual array to access. + * Algorithm: if target address > current window, assume forward scan, + * load starting at target address. If target address < current window, + * assume backward scan, load so that target area is top of window. + * Note that when switching from forward write to forward read, will have + * start_row = 0, so the limiting case applies and we load from 0 anyway. + */ + if (start_row > ptr->cur_start_row) { + ptr->cur_start_row = start_row; + } else { + /* use long arithmetic here to avoid overflow & unsigned problems */ + long ltemp; + + ltemp = (long) end_row - (long) ptr->rows_in_mem; + if (ltemp < 0) + ltemp = 0; /* don't fall off front end of file */ + ptr->cur_start_row = (JDIMENSION) ltemp; + } + /* Read in the selected part of the array. + * During the initial write pass, we will do no actual read + * because the selected part is all undefined. + */ + do_barray_io(cinfo, ptr, FALSE); + } + /* Ensure the accessed part of the array is defined; prezero if needed. + * To improve locality of access, we only prezero the part of the array + * that the caller is about to access, not the entire in-memory array. + */ + if (ptr->first_undef_row < end_row) { + if (ptr->first_undef_row < start_row) { + if (writable) /* writer skipped over a section of array */ + ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS); + undef_row = start_row; /* but reader is allowed to read ahead */ + } else { + undef_row = ptr->first_undef_row; + } + if (writable) + ptr->first_undef_row = end_row; + if (ptr->pre_zero) { + size_t bytesperrow = (size_t) ptr->blocksperrow * SIZEOF(JBLOCK); + undef_row -= ptr->cur_start_row; /* make indexes relative to buffer */ + end_row -= ptr->cur_start_row; + while (undef_row < end_row) { + jzero_far((void FAR *) ptr->mem_buffer[undef_row], bytesperrow); + undef_row++; + } + } else { + if (! writable) /* reader looking at undefined data */ + ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS); + } + } + /* Flag the buffer dirty if caller will write in it */ + if (writable) + ptr->dirty = TRUE; + /* Return address of proper part of the buffer */ + return ptr->mem_buffer + (start_row - ptr->cur_start_row); +} + + +/* + * Release all objects belonging to a specified pool. + */ + +METHODDEF(void) +free_pool (j_common_ptr cinfo, int pool_id) +{ + my_mem_ptr mem = (my_mem_ptr) cinfo->mem; + small_pool_ptr shdr_ptr; + large_pool_ptr lhdr_ptr; + size_t space_freed; + + if (pool_id < 0 || pool_id >= JPOOL_NUMPOOLS) + ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */ + +#ifdef MEM_STATS + if (cinfo->err->trace_level > 1) + print_mem_stats(cinfo, pool_id); /* print pool's memory usage statistics */ +#endif + + /* If freeing IMAGE pool, close any virtual arrays first */ + if (pool_id == JPOOL_IMAGE) { + jvirt_sarray_ptr sptr; + jvirt_barray_ptr bptr; + + for (sptr = mem->virt_sarray_list; sptr != NULL; sptr = sptr->next) { + if (sptr->b_s_open) { /* there may be no backing store */ + sptr->b_s_open = FALSE; /* prevent recursive close if error */ + (*sptr->b_s_info.close_backing_store) (cinfo, & sptr->b_s_info); + } + } + mem->virt_sarray_list = NULL; + for (bptr = mem->virt_barray_list; bptr != NULL; bptr = bptr->next) { + if (bptr->b_s_open) { /* there may be no backing store */ + bptr->b_s_open = FALSE; /* prevent recursive close if error */ + (*bptr->b_s_info.close_backing_store) (cinfo, & bptr->b_s_info); + } + } + mem->virt_barray_list = NULL; + } + + /* Release large objects */ + lhdr_ptr = mem->large_list[pool_id]; + mem->large_list[pool_id] = NULL; + + while (lhdr_ptr != NULL) { + large_pool_ptr next_lhdr_ptr = lhdr_ptr->hdr.next; + space_freed = lhdr_ptr->hdr.bytes_used + + lhdr_ptr->hdr.bytes_left + + SIZEOF(large_pool_hdr); + jpeg_free_large(cinfo, (void FAR *) lhdr_ptr, space_freed); + mem->total_space_allocated -= (long)space_freed; + lhdr_ptr = next_lhdr_ptr; + } + + /* Release small objects */ + shdr_ptr = mem->small_list[pool_id]; + mem->small_list[pool_id] = NULL; + + while (shdr_ptr != NULL) { + small_pool_ptr next_shdr_ptr = shdr_ptr->hdr.next; + space_freed = shdr_ptr->hdr.bytes_used + + shdr_ptr->hdr.bytes_left + + SIZEOF(small_pool_hdr); + jpeg_free_small(cinfo, (void *) shdr_ptr, space_freed); + mem->total_space_allocated -= (long)space_freed; + shdr_ptr = next_shdr_ptr; + } +} + + +/* + * Close up shop entirely. + * Note that this cannot be called unless cinfo->mem is non-NULL. + */ + +METHODDEF(void) +self_destruct (j_common_ptr cinfo) +{ + int pool; + + /* Close all backing store, release all memory. + * Releasing pools in reverse order might help avoid fragmentation + * with some (brain-damaged) malloc libraries. + */ + for (pool = JPOOL_NUMPOOLS-1; pool >= JPOOL_PERMANENT; pool--) { + free_pool(cinfo, pool); + } + + /* Release the memory manager control block too. */ + jpeg_free_small(cinfo, (void *) cinfo->mem, SIZEOF(my_memory_mgr)); + cinfo->mem = NULL; /* ensures I will be called only once */ + + jpeg_mem_term(cinfo); /* system-dependent cleanup */ +} + + +/* + * Memory manager initialization. + * When this is called, only the error manager pointer is valid in cinfo! + */ + +GLOBAL(void) +jinit_memory_mgr (j_common_ptr cinfo) +{ + my_mem_ptr mem; + long max_to_use; + int pool; + size_t test_mac; + + cinfo->mem = NULL; /* for safety if init fails */ + + /* Check for configuration errors. + * SIZEOF(ALIGN_TYPE) should be a power of 2; otherwise, it probably + * doesn't reflect any real hardware alignment requirement. + * The test is a little tricky: for X>0, X and X-1 have no one-bits + * in common if and only if X is a power of 2, ie has only one one-bit. + * Some compilers may give an "unreachable code" warning here; ignore it. + */ + if ((SIZEOF(ALIGN_TYPE) & (SIZEOF(ALIGN_TYPE)-1)) != 0) + ERREXIT(cinfo, JERR_BAD_ALIGN_TYPE); + /* MAX_ALLOC_CHUNK must be representable as type size_t, and must be + * a multiple of SIZEOF(ALIGN_TYPE). + * Again, an "unreachable code" warning may be ignored here. + * But a "constant too large" warning means you need to fix MAX_ALLOC_CHUNK. + */ + test_mac = (size_t) MAX_ALLOC_CHUNK; + if ((long) test_mac != MAX_ALLOC_CHUNK || + (MAX_ALLOC_CHUNK % SIZEOF(ALIGN_TYPE)) != 0) + ERREXIT(cinfo, JERR_BAD_ALLOC_CHUNK); + + max_to_use = jpeg_mem_init(cinfo); /* system-dependent initialization */ + + /* Attempt to allocate memory manager's control block */ + mem = (my_mem_ptr) jpeg_get_small(cinfo, SIZEOF(my_memory_mgr)); + + if (mem == NULL) { + jpeg_mem_term(cinfo); /* system-dependent cleanup */ + ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, 0); + } + + /* OK, fill in the method pointers */ + mem->pub.alloc_small = alloc_small; + mem->pub.alloc_large = alloc_large; + mem->pub.alloc_sarray = alloc_sarray; + mem->pub.alloc_barray = alloc_barray; +#ifdef NEED_DARRAY + mem->pub.alloc_darray = alloc_darray; +#endif + mem->pub.request_virt_sarray = request_virt_sarray; + mem->pub.request_virt_barray = request_virt_barray; + mem->pub.realize_virt_arrays = realize_virt_arrays; + mem->pub.access_virt_sarray = access_virt_sarray; + mem->pub.access_virt_barray = access_virt_barray; + mem->pub.free_pool = free_pool; + mem->pub.self_destruct = self_destruct; + + /* Make MAX_ALLOC_CHUNK accessible to other modules */ + mem->pub.max_alloc_chunk = MAX_ALLOC_CHUNK; + + /* Initialize working state */ + mem->pub.max_memory_to_use = max_to_use; + + for (pool = JPOOL_NUMPOOLS-1; pool >= JPOOL_PERMANENT; pool--) { + mem->small_list[pool] = NULL; + mem->large_list[pool] = NULL; + } + mem->virt_sarray_list = NULL; + mem->virt_barray_list = NULL; + + mem->total_space_allocated = SIZEOF(my_memory_mgr); + + /* Declare ourselves open for business */ + cinfo->mem = & mem->pub; + + /* Check for an environment variable JPEGMEM; if found, override the + * default max_memory setting from jpeg_mem_init. Note that the + * surrounding application may again override this value. + * If your system doesn't support getenv(), define NO_GETENV to disable + * this feature. + */ +#ifndef NO_GETENV + { char * memenv; + + if ((memenv = getenv("JPEGMEM")) != NULL) { + char ch = 'x'; + + if (sscanf(memenv, "%ld%c", &max_to_use, &ch) > 0) { + if (ch == 'm' || ch == 'M') + max_to_use *= 1000L; + mem->pub.max_memory_to_use = max_to_use * 1000L; + } + } + } +#endif + +} diff --git a/dcmjpeg/libijg8/jmemnobs.c b/dcmjpeg/libijg8/jmemnobs.c new file mode 100644 index 00000000..78ae56f7 --- /dev/null +++ b/dcmjpeg/libijg8/jmemnobs.c @@ -0,0 +1,110 @@ +/* + * jmemnobs.c + * + * Copyright (C) 1992-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file provides a really simple implementation of the system- + * dependent portion of the JPEG memory manager. This implementation + * assumes that no backing-store files are needed: all required space + * can be obtained from malloc(). + * This is very portable in the sense that it'll compile on almost anything, + * but you'd better have lots of main memory (or virtual memory) if you want + * to process big images. + * Note that the max_memory_to_use option is ignored by this implementation. + */ + +#define JPEG_INTERNALS +#include "jinclude8.h" +#include "jpeglib8.h" +#include "jmemsys8.h" /* import the system-dependent declarations */ + +#ifndef HAVE_STDLIB_H /* should declare malloc(),free() */ +extern void * malloc JPP((size_t size)); +extern void free JPP((void *ptr)); +#endif + + +/* + * Memory allocation and freeing are controlled by the regular library + * routines malloc() and free(). + */ + +GLOBAL(void *) +jpeg_get_small (j_common_ptr cinfo, size_t sizeofobject) +{ + return (void *) malloc(sizeofobject); +} + +GLOBAL(void) +jpeg_free_small (j_common_ptr cinfo, void * object, size_t sizeofobject) +{ + free(object); +} + + +/* + * "Large" objects are treated the same as "small" ones. + * NB: although we include FAR keywords in the routine declarations, + * this file won't actually work in 80x86 small/medium model; at least, + * you probably won't be able to process useful-size images in only 64KB. + */ + +GLOBAL(void FAR *) +jpeg_get_large (j_common_ptr cinfo, size_t sizeofobject) +{ + return (void FAR *) malloc(sizeofobject); +} + +GLOBAL(void) +jpeg_free_large (j_common_ptr cinfo, void FAR * object, size_t sizeofobject) +{ + + free(object); +} + + +/* + * This routine computes the total memory space available for allocation. + * Here we always say, "we got all you want bud!" + */ + +GLOBAL(long) +jpeg_mem_available (j_common_ptr cinfo, long min_bytes_needed, + long max_bytes_needed, long already_allocated) +{ + return max_bytes_needed; +} + + +/* + * Backing store (temporary file) management. + * Since jpeg_mem_available always promised the moon, + * this should never be called and we can just error out. + */ + +GLOBAL(void) +jpeg_open_backing_store (j_common_ptr cinfo, backing_store_ptr info, + long total_bytes_needed) +{ + ERREXIT(cinfo, JERR_NO_BACKING_STORE); +} + + +/* + * These routines take care of any system-dependent initialization and + * cleanup required. Here, there isn't any. + */ + +GLOBAL(long) +jpeg_mem_init (j_common_ptr cinfo) +{ + return 0; /* just set max_memory_to_use to 0 */ +} + +GLOBAL(void) +jpeg_mem_term (j_common_ptr cinfo) +{ + /* no work */ +} diff --git a/dcmjpeg/libijg8/jmemsys8.h b/dcmjpeg/libijg8/jmemsys8.h new file mode 100644 index 00000000..fc59f420 --- /dev/null +++ b/dcmjpeg/libijg8/jmemsys8.h @@ -0,0 +1,198 @@ +/* + * jmemsys.h + * + * Copyright (C) 1992-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This include file defines the interface between the system-independent + * and system-dependent portions of the JPEG memory manager. No other + * modules need include it. (The system-independent portion is jmemmgr.c; + * there are several different versions of the system-dependent portion.) + * + * This file works as-is for the system-dependent memory managers supplied + * in the IJG distribution. You may need to modify it if you write a + * custom memory manager. If system-dependent changes are needed in + * this file, the best method is to #ifdef them based on a configuration + * symbol supplied in jconfig.h, as we have done with USE_MSDOS_MEMMGR + * and USE_MAC_MEMMGR. + */ + + +/* Short forms of external names for systems with brain-damaged linkers. */ + +#ifdef NEED_SHORT_EXTERNAL_NAMES +#define jpeg_get_small jpeg8_get_small +#define jpeg_free_small jpeg8_free_small +#define jpeg_get_large jpeg8_get_large +#define jpeg_free_large jpeg8_free_large +#define jpeg_mem_available jpeg8_mem_available +#define jpeg_open_backing_store jpeg8_open_backing_store +#define jpeg_mem_init jpeg8_mem_init +#define jpeg_mem_term jpeg8_mem_term +#endif /* NEED_SHORT_EXTERNAL_NAMES */ + + +/* + * These two functions are used to allocate and release small chunks of + * memory. (Typically the total amount requested through jpeg_get_small is + * no more than 20K or so; this will be requested in chunks of a few K each.) + * Behavior should be the same as for the standard library functions malloc + * and free; in particular, jpeg_get_small must return NULL on failure. + * On most systems, these ARE malloc and free. jpeg_free_small is passed the + * size of the object being freed, just in case it's needed. + * On an 80x86 machine using small-data memory model, these manage near heap. + */ + +EXTERN(void *) jpeg_get_small JPP((j_common_ptr cinfo, size_t sizeofobject)); +EXTERN(void) jpeg_free_small JPP((j_common_ptr cinfo, void * object, + size_t sizeofobject)); + +/* + * These two functions are used to allocate and release large chunks of + * memory (up to the total free space designated by jpeg_mem_available). + * The interface is the same as above, except that on an 80x86 machine, + * far pointers are used. On most other machines these are identical to + * the jpeg_get/free_small routines; but we keep them separate anyway, + * in case a different allocation strategy is desirable for large chunks. + */ + +EXTERN(void FAR *) jpeg_get_large JPP((j_common_ptr cinfo, + size_t sizeofobject)); +EXTERN(void) jpeg_free_large JPP((j_common_ptr cinfo, void FAR * object, + size_t sizeofobject)); + +/* + * The macro MAX_ALLOC_CHUNK designates the maximum number of bytes that may + * be requested in a single call to jpeg_get_large (and jpeg_get_small for that + * matter, but that case should never come into play). This macro is needed + * to model the 64Kb-segment-size limit of far addressing on 80x86 machines. + * On those machines, we expect that jconfig.h will provide a proper value. + * On machines with 32-bit flat address spaces, any large constant may be used. + * + * NB: jmemmgr.c expects that MAX_ALLOC_CHUNK will be representable as type + * size_t and will be a multiple of sizeof(align_type). + */ + +#ifndef MAX_ALLOC_CHUNK /* may be overridden in jconfig.h */ +#define MAX_ALLOC_CHUNK 1000000000L +#endif + +/* + * This routine computes the total space still available for allocation by + * jpeg_get_large. If more space than this is needed, backing store will be + * used. NOTE: any memory already allocated must not be counted. + * + * There is a minimum space requirement, corresponding to the minimum + * feasible buffer sizes; jmemmgr.c will request that much space even if + * jpeg_mem_available returns zero. The maximum space needed, enough to hold + * all working storage in memory, is also passed in case it is useful. + * Finally, the total space already allocated is passed. If no better + * method is available, cinfo->mem->max_memory_to_use - already_allocated + * is often a suitable calculation. + * + * It is OK for jpeg_mem_available to underestimate the space available + * (that'll just lead to more backing-store access than is really necessary). + * However, an overestimate will lead to failure. Hence it's wise to subtract + * a slop factor from the true available space. 5% should be enough. + * + * On machines with lots of virtual memory, any large constant may be returned. + * Conversely, zero may be returned to always use the minimum amount of memory. + */ + +EXTERN(long) jpeg_mem_available JPP((j_common_ptr cinfo, + long min_bytes_needed, + long max_bytes_needed, + long already_allocated)); + + +/* + * This structure holds whatever state is needed to access a single + * backing-store object. The read/write/close method pointers are called + * by jmemmgr.c to manipulate the backing-store object; all other fields + * are private to the system-dependent backing store routines. + */ + +#define TEMP_NAME_LENGTH 64 /* max length of a temporary file's name */ + + +#ifdef USE_MSDOS_MEMMGR /* DOS-specific junk */ + +typedef unsigned short XMSH; /* type of extended-memory handles */ +typedef unsigned short EMSH; /* type of expanded-memory handles */ + +typedef union { + short file_handle; /* DOS file handle if it's a temp file */ + XMSH xms_handle; /* handle if it's a chunk of XMS */ + EMSH ems_handle; /* handle if it's a chunk of EMS */ +} handle_union; + +#endif /* USE_MSDOS_MEMMGR */ + +#ifdef USE_MAC_MEMMGR /* Mac-specific junk */ +#include +#endif /* USE_MAC_MEMMGR */ + + +typedef struct backing_store_struct * backing_store_ptr; + +typedef struct backing_store_struct { + /* Methods for reading/writing/closing this backing-store object */ + JMETHOD(void, read_backing_store, (j_common_ptr cinfo, + backing_store_ptr info, + void FAR * buffer_address, + long file_offset, long byte_count)); + JMETHOD(void, write_backing_store, (j_common_ptr cinfo, + backing_store_ptr info, + void FAR * buffer_address, + long file_offset, long byte_count)); + JMETHOD(void, close_backing_store, (j_common_ptr cinfo, + backing_store_ptr info)); + + /* Private fields for system-dependent backing-store management */ +#ifdef USE_MSDOS_MEMMGR + /* For the MS-DOS manager (jmemdos.c), we need: */ + handle_union handle; /* reference to backing-store storage object */ + char temp_name[TEMP_NAME_LENGTH]; /* name if it's a file */ +#else +#ifdef USE_MAC_MEMMGR + /* For the Mac manager (jmemmac.c), we need: */ + short temp_file; /* file reference number to temp file */ + FSSpec tempSpec; /* the FSSpec for the temp file */ + char temp_name[TEMP_NAME_LENGTH]; /* name if it's a file */ +#else + /* For a typical implementation with temp files, we need: */ + FILE * temp_file; /* stdio reference to temp file */ + char temp_name[TEMP_NAME_LENGTH]; /* name of temp file */ +#endif +#endif +} backing_store_info; + + +/* + * Initial opening of a backing-store object. This must fill in the + * read/write/close pointers in the object. The read/write routines + * may take an error exit if the specified maximum file size is exceeded. + * (If jpeg_mem_available always returns a large value, this routine can + * just take an error exit.) + */ + +EXTERN(void) jpeg_open_backing_store JPP((j_common_ptr cinfo, + backing_store_ptr info, + long total_bytes_needed)); + + +/* + * These routines take care of any system-dependent initialization and + * cleanup required. jpeg_mem_init will be called before anything is + * allocated (and, therefore, nothing in cinfo is of use except the error + * manager pointer). It should return a suitable default value for + * max_memory_to_use; this may subsequently be overridden by the surrounding + * application. (Note that max_memory_to_use is only important if + * jpeg_mem_available chooses to consult it ... no one else will.) + * jpeg_mem_term may assume that all requested memory has been freed and that + * all opened backing-store objects have been closed. + */ + +EXTERN(long) jpeg_mem_init JPP((j_common_ptr cinfo)); +EXTERN(void) jpeg_mem_term JPP((j_common_ptr cinfo)); diff --git a/dcmjpeg/libijg8/jmorecfg8.h b/dcmjpeg/libijg8/jmorecfg8.h new file mode 100644 index 00000000..26970dbb --- /dev/null +++ b/dcmjpeg/libijg8/jmorecfg8.h @@ -0,0 +1,407 @@ +/* + * jmorecfg.h + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains additional configuration options that customize the + * JPEG software for special applications or support machine-dependent + * optimizations. Most users will not need to touch this file. + */ + + +#include "dcmtk/ofstd/ofexport.h" /* for DCMTK_DECL_EXPORT */ + +#ifdef ijg8_EXPORTS +#define DCMTK_IJG8_EXPORT DCMTK_DECL_EXPORT +#else +#define DCMTK_IJG8_EXPORT DCMTK_DECL_IMPORT +#endif + + +/* + * Define BITS_IN_JSAMPLE as either + * 8 for 8-bit sample values (the usual setting) + * 12 for 12-bit sample values + * Only 8 and 12 are legal data precisions for lossy JPEG according to the + * JPEG standard, and the IJG code does not support anything else! + * We do not support run-time selection of data precision, sorry. + */ + +#define BITS_IN_JSAMPLE 8 /* use 8 or 12 (or 16 for lossless) */ + + +/* + * Maximum number of components (color channels) allowed in JPEG image. + * To meet the letter of the JPEG spec, set this to 255. However, darn + * few applications need more than 4 channels (maybe 5 for CMYK + alpha + * mask). We recommend 10 as a reasonable compromise; use 4 if you are + * really short on memory. (Each allowed component costs a hundred or so + * bytes of storage, whether actually used in an image or not.) + */ + +#define MAX_COMPONENTS 10 /* maximum number of image components */ + + +/* + * Basic data types. + * You may need to change these if you have a machine with unusual data + * type sizes; for example, "char" not 8 bits, "short" not 16 bits, + * or "long" not 32 bits. We don't care whether "int" is 16 or 32 bits, + * but it had better be at least 16. + */ + +/* Representation of a single sample (pixel element value). + * We frequently allocate large arrays of these, so it's important to keep + * them small. But if you have memory to burn and access to char or short + * arrays is very slow on your hardware, you might want to change these. + */ + +#if BITS_IN_JSAMPLE == 8 +/* JSAMPLE should be the smallest type that will hold the values 0..255. + * You can use a signed char by having GETJSAMPLE mask it with 0xFF. + */ + +#ifdef HAVE_UNSIGNED_CHAR + +typedef unsigned char JSAMPLE; +#define GETJSAMPLE(value) ((int) (value)) + +#else /* not HAVE_UNSIGNED_CHAR */ + +typedef char JSAMPLE; +#ifdef CHAR_IS_UNSIGNED +#define GETJSAMPLE(value) ((int) (value)) +#else +#define GETJSAMPLE(value) ((int) (value) & 0xFF) +#endif /* CHAR_IS_UNSIGNED */ + +#endif /* HAVE_UNSIGNED_CHAR */ + +#define MAXJSAMPLE 255 +#define CENTERJSAMPLE 128 + +#endif /* BITS_IN_JSAMPLE == 8 */ + + +#if BITS_IN_JSAMPLE == 12 +/* JSAMPLE should be the smallest type that will hold the values 0..4095. + * On nearly all machines "short" will do nicely. + */ + +typedef short JSAMPLE; +#define GETJSAMPLE(value) ((int) (value)) + +#define MAXJSAMPLE 4095 +#define CENTERJSAMPLE 2048 + +#endif /* BITS_IN_JSAMPLE == 12 */ + + +#if BITS_IN_JSAMPLE == 16 +/* JSAMPLE should be the smallest type that will hold the values 0..65535. + * You can use a signed short by having GETJSAMPLE mask it with 0xFFFF. + */ + +#ifdef HAVE_UNSIGNED_SHORT + +typedef unsigned short JSAMPLE; +#define GETJSAMPLE(value) ((int) (value)) + +#else /* not HAVE_UNSIGNED_SHORT */ + +typedef short JSAMPLE; +#ifdef SHORT_IS_UNSIGNED +#define GETJSAMPLE(value) ((int) (value)) +#else +#define GETJSAMPLE(value) ((int) (value) & 0xFFFF) +#endif /* SHORT_IS_UNSIGNED */ + +#endif /* HAVE_UNSIGNED_SHORT */ + +#define MAXJSAMPLE 65535 +#define CENTERJSAMPLE 32768 + +#endif /* BITS_IN_JSAMPLE == 16 */ + + +/* Representation of a DCT frequency coefficient. + * This should be a signed value of at least 16 bits; "short" is usually OK. + * Again, we allocate large arrays of these, but you can change to int + * if you have memory to burn and "short" is really slow. + */ + +typedef short JCOEF; + + +/* Representation of a spatial difference value. + * This should be a signed value of at least 16 bits; int is usually OK. + */ + +typedef int JDIFF; + + +/* Compressed datastreams are represented as arrays of JOCTET. + * These must be EXACTLY 8 bits wide, at least once they are written to + * external storage. Note that when using the stdio data source/destination + * managers, this is also the data type passed to fread/fwrite. + */ + +#ifdef HAVE_UNSIGNED_CHAR + +typedef unsigned char JOCTET; +#define GETJOCTET(value) (value) + +#else /* not HAVE_UNSIGNED_CHAR */ + +typedef char JOCTET; +#ifdef CHAR_IS_UNSIGNED +#define GETJOCTET(value) (value) +#else +#define GETJOCTET(value) ((value) & 0xFF) +#endif /* CHAR_IS_UNSIGNED */ + +#endif /* HAVE_UNSIGNED_CHAR */ + + +/* These typedefs are used for various table entries and so forth. + * They must be at least as wide as specified; but making them too big + * won't cost a huge amount of memory, so we don't provide special + * extraction code like we did for JSAMPLE. (In other words, these + * typedefs live at a different point on the speed/space tradeoff curve.) + */ + +/* UINT8 must hold at least the values 0..255. */ + +#ifdef HAVE_UNSIGNED_CHAR +typedef unsigned char UINT8; +#else /* not HAVE_UNSIGNED_CHAR */ +#ifdef CHAR_IS_UNSIGNED +typedef char UINT8; +#else /* not CHAR_IS_UNSIGNED */ +typedef short UINT8; +#endif /* CHAR_IS_UNSIGNED */ +#endif /* HAVE_UNSIGNED_CHAR */ + +/* UINT16 must hold at least the values 0..65535. */ + +#ifdef HAVE_UNSIGNED_SHORT +typedef unsigned short UINT16; +#else /* not HAVE_UNSIGNED_SHORT */ +typedef unsigned int UINT16; +#endif /* HAVE_UNSIGNED_SHORT */ + +/* INT16 must hold at least the values -32768..32767. */ + +#ifndef XMD_H /* X11/xmd.h correctly defines INT16 */ +typedef short INT16; +#endif + +/* IJG_INT32 must hold at least signed 32-bit values. */ +typedef long IJG_INT32; + +/* Datatype used for image dimensions. The JPEG standard only supports + * images up to 64K*64K due to 16-bit fields in SOF markers. Therefore + * "unsigned int" is sufficient on all machines. However, if you need to + * handle larger images and you don't mind deviating from the spec, you + * can change this datatype. + */ + +typedef unsigned int JDIMENSION; + +#define JPEG_MAX_DIMENSION 65500L /* a tad under 64K to prevent overflows */ + + +/* These macros are used in all function definitions and extern declarations. + * You could modify them if you need to change function linkage conventions; + * in particular, you'll need to do that to make the library a Windows DLL. + * Another application is to make all functions global for use with debuggers + * or code profilers that require it. + */ + +/* a function called through method pointers: */ +#define METHODDEF(type) static type +/* a function used only in its module: */ +#define LOCAL(type) static type +/* a function referenced thru EXTERNs: */ +#define GLOBAL(type) type +/* a reference to a GLOBAL function: */ +#define EXTERN(type) extern DCMTK_IJG8_EXPORT type + + +/* This macro is used to declare a "method", that is, a function pointer. + * We want to supply prototype parameters if the compiler can cope. + * Note that the arglist parameter must be parenthesized! + * Again, you can customize this if you need special linkage keywords. + */ + +#ifdef HAVE_PROTOTYPES +#define JMETHOD(type,methodname,arglist) type (*methodname) arglist +#else +#define JMETHOD(type,methodname,arglist) type (*methodname) () +#endif + + +/* Here is the pseudo-keyword for declaring pointers that must be "far" + * on 80x86 machines. Most of the specialized coding for 80x86 is handled + * by just saying "FAR *" where such a pointer is needed. In a few places + * explicit coding is needed; see uses of the NEED_FAR_POINTERS symbol. + */ + +#undef FAR +#ifdef NEED_FAR_POINTERS +#define FAR far +#else +#define FAR +#endif + + +/* + * On a few systems, type boolean and/or its values FALSE, TRUE may appear + * in standard header files. Or you may have conflicts with application- + * specific header files that you want to include together with these files. + * Defining HAVE_BOOLEAN before including jpeglib.h should make it work. + */ + +#ifndef HAVE_BOOLEAN +typedef int boolean; +#endif +#ifndef FALSE /* in case these macros already exist */ +#define FALSE 0 /* values of boolean */ +#endif +#ifndef TRUE +#define TRUE 1 +#endif + + +/* + * The remaining options affect code selection within the JPEG library, + * but they don't need to be visible to most applications using the library. + * To minimize application namespace pollution, the symbols won't be + * defined unless JPEG_INTERNALS or JPEG_INTERNAL_OPTIONS has been defined. + */ + +#ifdef JPEG_INTERNALS +#define JPEG_INTERNAL_OPTIONS +#endif + +#ifdef JPEG_INTERNAL_OPTIONS + + +/* + * These defines indicate whether to include various optional functions. + * Undefining some of these symbols will produce a smaller but less capable + * library. Note that you can leave certain source files out of the + * compilation/linking process if you've #undef'd the corresponding symbols. + * (You may HAVE to do that if your compiler doesn't like null source files.) + */ + +/* Arithmetic coding is unsupported for legal reasons. Complaints to IBM. */ + +/* Capability options common to encoder and decoder: */ + +#define DCT_ISLOW_SUPPORTED /* slow but accurate integer algorithm */ +#define DCT_IFAST_SUPPORTED /* faster, less accurate integer method */ +#define DCT_FLOAT_SUPPORTED /* floating-point: accurate, fast on fast HW */ + +/* Encoder capability options: */ + +#undef C_ARITH_CODING_SUPPORTED /* Arithmetic coding back end? */ +#define C_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */ +#define C_PROGRESSIVE_SUPPORTED /* Progressive JPEG? (Requires MULTISCAN)*/ +#define C_LOSSLESS_SUPPORTED /* Lossless JPEG? */ +#define ENTROPY_OPT_SUPPORTED /* Optimization of entropy coding parms? */ +/* Note: if you selected 12-bit data precision, it is dangerous to turn off + * ENTROPY_OPT_SUPPORTED. The standard Huffman tables are only good for 8-bit + * precision, so jcshuff.c normally uses entropy optimization to compute + * usable tables for higher precision. If you don't want to do optimization, + * you'll have to supply different default Huffman tables. + * The exact same statements apply for progressive and lossless JPEG: + * the default tables don't work for progressive mode or lossless mode. + * (This may get fixed, however.) + */ +#define INPUT_SMOOTHING_SUPPORTED /* Input image smoothing option? */ + +/* Decoder capability options: */ + +#undef D_ARITH_CODING_SUPPORTED /* Arithmetic coding back end? */ +#define D_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */ +#define D_PROGRESSIVE_SUPPORTED /* Progressive JPEG? (Requires MULTISCAN)*/ +#define D_LOSSLESS_SUPPORTED /* Lossless JPEG? */ +#define SAVE_MARKERS_SUPPORTED /* jpeg_save_markers() needed? */ +#define BLOCK_SMOOTHING_SUPPORTED /* Block smoothing? (Progressive only) */ +#define IDCT_SCALING_SUPPORTED /* Output rescaling via IDCT? */ +#undef UPSAMPLE_SCALING_SUPPORTED /* Output rescaling at upsample stage? */ +#define UPSAMPLE_MERGING_SUPPORTED /* Fast path for sloppy upsampling? */ +#define QUANT_1PASS_SUPPORTED /* 1-pass color quantization? */ +#define QUANT_2PASS_SUPPORTED /* 2-pass color quantization? */ + +/* more capability options later, no doubt */ + + +/* + * Ordering of RGB data in scanlines passed to or from the application. + * If your application wants to deal with data in the order B,G,R, just + * change these macros. You can also deal with formats such as R,G,B,X + * (one extra byte per pixel) by changing RGB_PIXELSIZE. Note that changing + * the offsets will also change the order in which colormap data is organized. + * RESTRICTIONS: + * 1. The sample applications cjpeg,djpeg do NOT support modified RGB formats. + * 2. These macros only affect RGB<=>YCbCr color conversion, so they are not + * useful if you are using JPEG color spaces other than YCbCr or grayscale. + * 3. The color quantizer modules will not behave desirably if RGB_PIXELSIZE + * is not 3 (they don't understand about dummy color components!). So you + * can't use color quantization if you change that value. + */ + +#define RGB_RED 0 /* Offset of Red in an RGB scanline element */ +#define RGB_GREEN 1 /* Offset of Green */ +#define RGB_BLUE 2 /* Offset of Blue */ +#define RGB_PIXELSIZE 3 /* JSAMPLEs per RGB scanline element */ + + +/* Definitions for speed-related optimizations. */ + + +/* If your compiler supports inline functions, define INLINE + * as the inline keyword; otherwise define it as empty. + */ + +#ifndef INLINE +#ifdef __GNUC__ /* for instance, GNU C knows about inline */ +#define INLINE __inline__ +#endif +#ifndef INLINE +#define INLINE /* default is to define it as empty */ +#endif +#endif + + +/* On some machines (notably 68000 series) "int" is 32 bits, but multiplying + * two 16-bit shorts is faster than multiplying two ints. Define MULTIPLIER + * as short on such a machine. MULTIPLIER must be at least 16 bits wide. + */ + +#ifndef MULTIPLIER +#define MULTIPLIER int /* type for fastest integer multiply */ +#endif + + +/* FAST_FLOAT should be either float or double, whichever is done faster + * by your compiler. (Note that this type is only used in the floating point + * DCT routines, so it only matters if you've defined DCT_FLOAT_SUPPORTED.) + * Typically, float is faster in ANSI C compilers, while double is faster in + * pre-ANSI compilers (because they insist on converting to double anyway). + * The code below therefore chooses float if we have ANSI-style prototypes. + */ + +#ifndef FAST_FLOAT +#ifdef HAVE_PROTOTYPES +#define FAST_FLOAT float +#else +#define FAST_FLOAT double +#endif +#endif + +#endif /* JPEG_INTERNAL_OPTIONS */ diff --git a/dcmjpeg/libijg8/jpegint8.h b/dcmjpeg/libijg8/jpegint8.h new file mode 100644 index 00000000..0218018c --- /dev/null +++ b/dcmjpeg/libijg8/jpegint8.h @@ -0,0 +1,373 @@ +/* + * jpegint.h + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file provides common declarations for the various JPEG modules. + * These declarations are considered internal to the JPEG library; most + * applications using the library shouldn't need to include this file. + */ + + +/* Declarations for both compression & decompression */ + +typedef enum { /* Operating modes for buffer controllers */ + JBUF_PASS_THRU, /* Plain stripwise operation */ + /* Remaining modes require a full-image buffer to have been created */ + JBUF_SAVE_SOURCE, /* Run source subobject only, save output */ + JBUF_CRANK_DEST, /* Run dest subobject only, using saved data */ + JBUF_SAVE_AND_PASS /* Run both subobjects, save output */ +} J_BUF_MODE; + +/* Values of global_state field (jdapi.c has some dependencies on ordering!) */ +#define CSTATE_START 100 /* after create_compress */ +#define CSTATE_SCANNING 101 /* start_compress done, write_scanlines OK */ +#define CSTATE_RAW_OK 102 /* start_compress done, write_raw_data OK */ +#define CSTATE_WRCOEFS 103 /* jpeg_write_coefficients done */ +#define DSTATE_START 200 /* after create_decompress */ +#define DSTATE_INHEADER 201 /* reading header markers, no SOS yet */ +#define DSTATE_READY 202 /* found SOS, ready for start_decompress */ +#define DSTATE_PRELOAD 203 /* reading multiscan file in start_decompress*/ +#define DSTATE_PRESCAN 204 /* performing dummy pass for 2-pass quant */ +#define DSTATE_SCANNING 205 /* start_decompress done, read_scanlines OK */ +#define DSTATE_RAW_OK 206 /* start_decompress done, read_raw_data OK */ +#define DSTATE_BUFIMAGE 207 /* expecting jpeg_start_output */ +#define DSTATE_BUFPOST 208 /* looking for SOS/EOI in jpeg_finish_output */ +#define DSTATE_RDCOEFS 209 /* reading file in jpeg_read_coefficients */ +#define DSTATE_STOPPING 210 /* looking for EOI in jpeg_finish_decompress */ + + +/* Declarations for compression modules */ + +/* Master control module */ +struct jpeg_comp_master { + JMETHOD(void, prepare_for_pass, (j_compress_ptr cinfo)); + JMETHOD(void, pass_startup, (j_compress_ptr cinfo)); + JMETHOD(void, finish_pass, (j_compress_ptr cinfo)); + + /* State variables made visible to other modules */ + boolean call_pass_startup; /* True if pass_startup must be called */ + boolean is_last_pass; /* True during last pass */ +}; + +/* Main buffer control (downsampled-data buffer) */ +struct jpeg_c_main_controller { + JMETHOD(void, start_pass, (j_compress_ptr cinfo, J_BUF_MODE pass_mode)); + JMETHOD(void, process_data, (j_compress_ptr cinfo, + JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, + JDIMENSION in_rows_avail)); +}; + +/* Compression preprocessing (downsampling input buffer control) */ +struct jpeg_c_prep_controller { + JMETHOD(void, start_pass, (j_compress_ptr cinfo, J_BUF_MODE pass_mode)); + JMETHOD(void, pre_process_data, (j_compress_ptr cinfo, + JSAMPARRAY input_buf, + JDIMENSION *in_row_ctr, + JDIMENSION in_rows_avail, + JSAMPIMAGE output_buf, + JDIMENSION *out_row_group_ctr, + JDIMENSION out_row_groups_avail)); +}; + +/* Compression codec (compressor proper) */ +struct jpeg_c_codec { + JMETHOD(void, entropy_start_pass, (j_compress_ptr cinfo, + boolean gather_statistics)); + JMETHOD(void, entropy_finish_pass, (j_compress_ptr cinfo)); + JMETHOD(boolean, need_optimization_pass, (j_compress_ptr cinfo)); + JMETHOD(void, start_pass, (j_compress_ptr cinfo, J_BUF_MODE pass_mode)); + JMETHOD(boolean, compress_data, (j_compress_ptr cinfo, + JSAMPIMAGE input_buf)); +}; + +/* Colorspace conversion */ +struct jpeg_color_converter { + JMETHOD(void, start_pass, (j_compress_ptr cinfo)); + JMETHOD(void, color_convert, (j_compress_ptr cinfo, + JSAMPARRAY input_buf, JSAMPIMAGE output_buf, + JDIMENSION output_row, int num_rows)); +}; + +/* Downsampling */ +struct jpeg_downsampler { + JMETHOD(void, start_pass, (j_compress_ptr cinfo)); + JMETHOD(void, downsample, (j_compress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION in_row_index, + JSAMPIMAGE output_buf, + JDIMENSION out_row_group_index)); + + boolean need_context_rows; /* TRUE if need rows above & below */ +}; + +/* Marker writing */ +struct jpeg_marker_writer { + JMETHOD(void, write_file_header, (j_compress_ptr cinfo)); + JMETHOD(void, write_frame_header, (j_compress_ptr cinfo)); + JMETHOD(void, write_scan_header, (j_compress_ptr cinfo)); + JMETHOD(void, write_file_trailer, (j_compress_ptr cinfo)); + JMETHOD(void, write_tables_only, (j_compress_ptr cinfo)); + /* These routines are exported to allow insertion of extra markers */ + /* Probably only COM and APPn markers should be written this way */ + JMETHOD(void, write_marker_header, (j_compress_ptr cinfo, int marker, + unsigned int datalen)); + JMETHOD(void, write_marker_byte, (j_compress_ptr cinfo, int val)); +}; + + +/* Declarations for decompression modules */ + +/* Master control module */ +struct jpeg_decomp_master { + JMETHOD(void, prepare_for_output_pass, (j_decompress_ptr cinfo)); + JMETHOD(void, finish_output_pass, (j_decompress_ptr cinfo)); + + /* State variables made visible to other modules */ + boolean is_dummy_pass; /* True during 1st pass for 2-pass quant */ +}; + +/* Input control module */ +struct jpeg_input_controller { + JMETHOD(int, consume_input, (j_decompress_ptr cinfo)); + JMETHOD(void, reset_input_controller, (j_decompress_ptr cinfo)); + JMETHOD(void, start_input_pass, (j_decompress_ptr cinfo)); + JMETHOD(void, finish_input_pass, (j_decompress_ptr cinfo)); + + /* State variables made visible to other modules */ + boolean has_multiple_scans; /* True if file has multiple scans */ + boolean eoi_reached; /* True when EOI has been consumed */ +}; + +/* Main buffer control (downsampled-data buffer) */ +struct jpeg_d_main_controller { + JMETHOD(void, start_pass, (j_decompress_ptr cinfo, J_BUF_MODE pass_mode)); + JMETHOD(void, process_data, (j_decompress_ptr cinfo, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail)); +}; + +/* Decompression codec (decompressor proper) */ +struct jpeg_d_codec { + JMETHOD(void, calc_output_dimensions, (j_decompress_ptr cinfo)); + JMETHOD(void, start_input_pass, (j_decompress_ptr cinfo)); + JMETHOD(int, consume_data, (j_decompress_ptr cinfo)); + JMETHOD(void, start_output_pass, (j_decompress_ptr cinfo)); + JMETHOD(int, decompress_data, (j_decompress_ptr cinfo, + JSAMPIMAGE output_buf)); +}; + +/* Decompression postprocessing (color quantization buffer control) */ +struct jpeg_d_post_controller { + JMETHOD(void, start_pass, (j_decompress_ptr cinfo, J_BUF_MODE pass_mode)); + JMETHOD(void, post_process_data, (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, + JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + JSAMPARRAY output_buf, + JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail)); +}; + +/* Marker reading & parsing */ +struct jpeg_marker_reader { + JMETHOD(void, reset_marker_reader, (j_decompress_ptr cinfo)); + /* Read markers until SOS or EOI. + * Returns same codes as are defined for jpeg_consume_input: + * JPEG_SUSPENDED, JPEG_REACHED_SOS, or JPEG_REACHED_EOI. + */ + JMETHOD(int, read_markers, (j_decompress_ptr cinfo)); + /* Read a restart marker --- exported for use by entropy decoder only */ + jpeg_marker_parser_method read_restart_marker; + + /* State of marker reader --- nominally internal, but applications + * supplying COM or APPn handlers might like to know the state. + */ + boolean saw_SOI; /* found SOI? */ + boolean saw_SOF; /* found SOF? */ + int next_restart_num; /* next restart number expected (0-7) */ + unsigned int discarded_bytes; /* # of bytes skipped looking for a marker */ +}; + +/* Upsampling (note that upsampler must also call color converter) */ +struct jpeg_upsampler { + JMETHOD(void, start_pass, (j_decompress_ptr cinfo)); + JMETHOD(void, upsample, (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, + JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + JSAMPARRAY output_buf, + JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail)); + + boolean need_context_rows; /* TRUE if need rows above & below */ +}; + +/* Colorspace conversion */ +struct jpeg_color_deconverter { + JMETHOD(void, start_pass, (j_decompress_ptr cinfo)); + JMETHOD(void, color_convert, (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION input_row, + JSAMPARRAY output_buf, int num_rows)); +}; + +/* Color quantization or color precision reduction */ +struct jpeg_color_quantizer { + JMETHOD(void, start_pass, (j_decompress_ptr cinfo, boolean is_pre_scan)); + JMETHOD(void, color_quantize, (j_decompress_ptr cinfo, + JSAMPARRAY input_buf, JSAMPARRAY output_buf, + int num_rows)); + JMETHOD(void, finish_pass, (j_decompress_ptr cinfo)); + JMETHOD(void, new_color_map, (j_decompress_ptr cinfo)); +}; + + +/* Miscellaneous useful macros */ + +#undef MAX +#define MAX(a,b) ((a) > (b) ? (a) : (b)) +#undef MIN +#define MIN(a,b) ((a) < (b) ? (a) : (b)) + + +/* We assume that right shift corresponds to signed division by 2 with + * rounding towards minus infinity. This is correct for typical "arithmetic + * shift" instructions that shift in copies of the sign bit. But some + * C compilers implement >> with an unsigned shift. For these machines you + * must define RIGHT_SHIFT_IS_UNSIGNED. + * RIGHT_SHIFT provides a proper signed right shift of an IJG_INT32 quantity. + * It is only applied with constant shift counts. SHIFT_TEMPS must be + * included in the variables of any routine using RIGHT_SHIFT. + */ + +#ifdef RIGHT_SHIFT_IS_UNSIGNED +#define SHIFT_TEMPS IJG_INT32 shift_temp; +#define RIGHT_SHIFT(x,shft) \ + ((shift_temp = (x)) < 0 ? \ + (shift_temp >> (shft)) | ((~((IJG_INT32) 0)) << (32-(shft))) : \ + (shift_temp >> (shft))) +#else +#define SHIFT_TEMPS +#define RIGHT_SHIFT(x,shft) ((x) >> (shft)) +#endif + + +/* Short forms of external names for systems with brain-damaged linkers. */ + +#ifdef NEED_SHORT_EXTERNAL_NAMES +#define jinit_c_codec jinit8_c_codec +#define jinit_c_diff_controller jinit8_c_diff_controller +#define jinit_lossy_c_codec jinit8_lossy_c_codec +#define jinit_lossless_c_codec jinit8_lossless_c_codec +#define jinit_compress_master jinit8_compress_master +#define jinit_c_master_control jinit8_c_master_control +#define jinit_c_main_controller jinit8_c_main_controller +#define jinit_c_prep_controller jinit8_c_prep_controller +#define jinit_c_coef_controller jinit8_c_coef_controller +#define jinit_color_converter jinit8_color_converter +#define jinit_downsampler jinit8_downsampler +#define jinit_forward_dct jinit8_forward_dct +#define jinit_shuff_encoder jinit8_shuff_encoder +#define jinit_phuff_encoder jinit8_phuff_encoder +#ifdef WITH_ARITHMETIC_PATCH +#define jinit_arith_encoder jinit8_arith_encoder +#endif +#define jinit_marker_writer jinit8_marker_writer +#define jinit_d_codec jinit8_d_codec +#define jinit_lossy_d_codec jinit8_lossy_d_codec +#define jinit_lossless_d_codec jinit8_lossless_d_codec +#define jinit_master_decompress jinit8_master_decompress +#define jinit_d_main_controller jinit8_d_main_controller +#define jinit_d_coef_controller jinit8_d_coef_controller +#define jinit_d_diff_controller jinit8_d_diff_controller +#define jinit_d_post_controller jinit8_d_post_controller +#define jinit_input_controller jinit8_input_controller +#define jinit_marker_reader jinit8_marker_reader +#define jinit_shuff_decoder jinit8_shuff_decoder +#define jinit_phuff_decoder jinit8_phuff_decoder +#ifdef WITH_ARITHMETIC_PATCH +#define jinit_arith_decoder jinit8_arith_decoder +#endif +#define jinit_lhuff_decoder jinit8_lhuff_decoder +#define jinit_undifferencer jinit8_undifferencer +#define jinit_d_scaler jinit8_d_scaler +#define jinit_inverse_dct jinit8_inverse_dct +#define jinit_upsampler jinit8_upsampler +#define jinit_color_deconverter jinit8_color_deconverter +#define jinit_1pass_quantizer jinit8_1pass_quantizer +#define jinit_2pass_quantizer jinit8_2pass_quantizer +#define jinit_merged_upsampler jinit8_merged_upsampler +#define jinit_memory_mgr jinit8_memory_mgr +#define jdiv_round_up jdiv8_round_up +#define jround_up jround8_up +#define jcopy_sample_rows jcopy8_sample_rows +#define jcopy_block_row jcopy8_block_row +#define jzero_far jzero8_far +#define jpeg_zigzag_order jpeg8_zigzag_order +#define jpeg_natural_order jpeg8_natural_order +#endif /* NEED_SHORT_EXTERNAL_NAMES */ + + +/* Compression module initialization routines */ +EXTERN(void) jinit_c_codec JPP((j_compress_ptr cinfo)); +EXTERN(void) jinit_c_diff_controller JPP((j_compress_ptr cinfo, boolean need_full_buffer)); +EXTERN(void) jinit_compress_master JPP((j_compress_ptr cinfo)); +EXTERN(void) jinit_c_master_control JPP((j_compress_ptr cinfo, + boolean transcode_only)); +EXTERN(void) jinit_c_main_controller JPP((j_compress_ptr cinfo, + boolean need_full_buffer)); +EXTERN(void) jinit_c_prep_controller JPP((j_compress_ptr cinfo, + boolean need_full_buffer)); +EXTERN(void) jinit_compressor JPP((j_compress_ptr cinfo)); +EXTERN(void) jinit_color_converter JPP((j_compress_ptr cinfo)); +EXTERN(void) jinit_downsampler JPP((j_compress_ptr cinfo)); +EXTERN(void) jinit_marker_writer JPP((j_compress_ptr cinfo)); +#ifdef WITH_ARITHMETIC_PATCH +EXTERN(void) jinit_arith_encoder JPP((j_compress_ptr cinfo)); +#endif +/* Decompression module initialization routines */ +EXTERN(void) jinit_d_codec JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_d_diff_controller JPP((j_decompress_ptr cinfo, boolean need_full_buffer)); +EXTERN(void) jinit_master_decompress JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_d_main_controller JPP((j_decompress_ptr cinfo, + boolean need_full_buffer)); +EXTERN(void) jinit_decompressor JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_d_post_controller JPP((j_decompress_ptr cinfo, + boolean need_full_buffer)); +EXTERN(void) jinit_input_controller JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_marker_reader JPP((j_decompress_ptr cinfo)); +#ifdef WITH_ARITHMETIC_PATCH +EXTERN(void) jinit_arith_decoder JPP((j_decompress_ptr cinfo)); +#endif +EXTERN(void) jinit_upsampler JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_color_deconverter JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_1pass_quantizer JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_2pass_quantizer JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_merged_upsampler JPP((j_decompress_ptr cinfo)); +/* Memory manager initialization */ +EXTERN(void) jinit_memory_mgr JPP((j_common_ptr cinfo)); + +/* Utility routines in jutils.c */ +EXTERN(long) jdiv_round_up JPP((long a, long b)); +EXTERN(long) jround_up JPP((long a, long b)); +EXTERN(void) jcopy_sample_rows JPP((JSAMPARRAY input_array, int source_row, + JSAMPARRAY output_array, int dest_row, + int num_rows, JDIMENSION num_cols)); +EXTERN(void) jcopy_block_row JPP((JBLOCKROW input_row, JBLOCKROW output_row, + JDIMENSION num_blocks)); +EXTERN(void) jzero_far JPP((void FAR * target, size_t bytestozero)); +/* Constant tables in jutils.c */ +#if 0 /* This table is not actually needed in v6a */ +extern const int jpeg_zigzag_order[]; /* natural coef order to zigzag order */ +#endif +extern const int jpeg_natural_order[]; /* zigzag coef order to natural order */ + +/* Suppress undefined-structure complaints if necessary. */ + +#ifdef INCOMPLETE_TYPES_BROKEN +#ifndef AM_MEMORY_MANAGER /* only jmemmgr.c defines these */ +struct jvirt_sarray_control { long dummy; }; +struct jvirt_barray_control { long dummy; }; +#endif +#endif /* INCOMPLETE_TYPES_BROKEN */ diff --git a/dcmjpeg/libijg8/jpeglib8.h b/dcmjpeg/libijg8/jpeglib8.h new file mode 100644 index 00000000..ec8595cc --- /dev/null +++ b/dcmjpeg/libijg8/jpeglib8.h @@ -0,0 +1,1203 @@ +/* + * jpeglib.h + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file defines the application interface for the JPEG library. + * Most applications using the library need only include this file, + * and perhaps jerror.h if they want to know the exact error codes. + */ + +#ifndef JPEGLIB_H +#define JPEGLIB_H + +/* + * First we include the configuration files that record how this + * installation of the JPEG library is set up. jconfig.h can be + * generated automatically for many systems. jmorecfg.h contains + * manual configuration options that most people need not worry about. + */ + +#ifndef JCONFIG_INCLUDED /* in case jinclude.h already did */ +#include "jconfig8.h" /* widely used configuration options */ +#endif +#include "jmorecfg8.h" /* seldom changed options */ + + +/* Version ID for the JPEG library. + * Might be useful for tests like "#if JPEG_LIB_VERSION >= 60". + */ + +#define JPEG_LIB_VERSION 62 /* Version 6b */ + + +/* Various constants determining the sizes of things. + * All of these are specified by the JPEG standard, so don't change them + * if you want to be compatible. + */ + +#define DCTSIZE 8 /* The basic DCT block is 8x8 samples */ +#define DCTSIZE2 64 /* DCTSIZE squared; # of elements in a block */ +#define NUM_QUANT_TBLS 4 /* Quantization tables are numbered 0..3 */ +#define NUM_HUFF_TBLS 4 /* Huffman tables are numbered 0..3 */ +#define NUM_ARITH_TBLS 16 /* Arith-coding tables are numbered 0..15 */ +#define MAX_COMPS_IN_SCAN 4 /* JPEG limit on # of components in one scan */ +#define MAX_SAMP_FACTOR 4 /* JPEG limit on sampling factors */ +/* Unfortunately, some bozo at Adobe saw no reason to be bound by the standard; + * the PostScript DCT filter can emit files with many more than 10 data units + * per MCU. + * If you happen to run across such a file, you can up D_MAX_DATA_UNITS_IN_MCU + * to handle it. We even let you do this from the jconfig.h file. However, + * we strongly discourage changing C_MAX_DATA_UNITS_IN_MCU; just because Adobe + * sometimes emits noncompliant files doesn't mean you should too. + */ +#define C_MAX_DATA_UNITS_IN_MCU 10 /* compressor's limit on data units/MCU */ +#ifndef D_MAX_DATA_UNITS_IN_MCU +#define D_MAX_DATA_UNITS_IN_MCU 10 /* decompressor's limit on data units/MCU */ +#endif + + +/* Data structures for images (arrays of samples and of DCT coefficients). + * On 80x86 machines, the image arrays are too big for near pointers, + * but the pointer arrays can fit in near memory. + */ + +typedef JSAMPLE FAR *JSAMPROW; /* ptr to one image row of pixel samples. */ +typedef JSAMPROW *JSAMPARRAY; /* ptr to some rows (a 2-D sample array) */ +typedef JSAMPARRAY *JSAMPIMAGE; /* a 3-D sample array: top index is color */ + +typedef JCOEF JBLOCK[DCTSIZE2]; /* one block of coefficients */ +typedef JBLOCK FAR *JBLOCKROW; /* pointer to one row of coefficient blocks */ +typedef JBLOCKROW *JBLOCKARRAY; /* a 2-D array of coefficient blocks */ +typedef JBLOCKARRAY *JBLOCKIMAGE; /* a 3-D array of coefficient blocks */ + +typedef JCOEF FAR *JCOEFPTR; /* useful in a couple of places */ + +typedef JDIFF FAR *JDIFFROW; /* pointer to one row of difference values */ +typedef JDIFFROW *JDIFFARRAY; /* ptr to some rows (a 2-D diff array) */ +typedef JDIFFARRAY *JDIFFIMAGE; /* a 3-D diff array: top index is color */ + + +/* Types for JPEG compression parameters and working tables. */ + + +/* DCT coefficient quantization tables. */ + +typedef struct { + /* This array gives the coefficient quantizers in natural array order + * (not the zigzag order in which they are stored in a JPEG DQT marker). + * CAUTION: IJG versions prior to v6a kept this array in zigzag order. + */ + UINT16 quantval[DCTSIZE2]; /* quantization step for each coefficient */ + /* This field is used only during compression. It's initialized FALSE when + * the table is created, and set TRUE when it's been output to the file. + * You could suppress output of a table by setting this to TRUE. + * (See jpeg_suppress_tables for an example.) + */ + boolean sent_table; /* TRUE when table has been output */ +} JQUANT_TBL; + + +/* Huffman coding tables. */ + +typedef struct { + /* These two fields directly represent the contents of a JPEG DHT marker */ + UINT8 bits[17]; /* bits[k] = # of symbols with codes of */ + /* length k bits; bits[0] is unused */ + UINT8 huffval[256]; /* The symbols, in order of incr code length */ + /* This field is used only during compression. It's initialized FALSE when + * the table is created, and set TRUE when it's been output to the file. + * You could suppress output of a table by setting this to TRUE. + * (See jpeg_suppress_tables for an example.) + */ + boolean sent_table; /* TRUE when table has been output */ +} JHUFF_TBL; + + +/* Basic info about one component (color channel). */ + +typedef struct { + /* These values are fixed over the whole image. */ + /* For compression, they must be supplied by parameter setup; */ + /* for decompression, they are read from the SOF marker. */ + int component_id; /* identifier for this component (0..255) */ + int component_index; /* its index in SOF or cinfo->comp_info[] */ + int h_samp_factor; /* horizontal sampling factor (1..4) */ + int v_samp_factor; /* vertical sampling factor (1..4) */ + int quant_tbl_no; /* quantization table selector (0..3) */ + /* These values may vary between scans. */ + /* For compression, they must be supplied by parameter setup; */ + /* for decompression, they are read from the SOS marker. */ + /* The decompressor output side may not use these variables. */ + int dc_tbl_no; /* DC entropy table selector (0..3) */ + int ac_tbl_no; /* AC entropy table selector (0..3) */ + + /* Remaining fields should be treated as private by applications. */ + + /* These values are computed during compression or decompression startup: */ + /* Component's size in data units. + * Any dummy data units added to complete an MCU are not counted; therefore + * these values do not depend on whether a scan is interleaved or not. + */ + JDIMENSION width_in_data_units; + JDIMENSION height_in_data_units; + /* Size of a data unit in/output by the codec (in samples). Always + * data_unit for compression. For decompression this is the size of the + * output from one data_unit, reflecting any processing performed by the + * codec. For example, in the DCT-based codec, scaling may be applied + * during the IDCT step. Values of 1,2,4,8 are likely to be supported. + * Note that different components may have different codec_data_unit sizes. + */ + int codec_data_unit; + /* The downsampled dimensions are the component's actual, unpadded number + * of samples at the main buffer (preprocessing/compression interface), thus + * downsampled_width = ceil(image_width * Hi/Hmax) + * and similarly for height. For decompression, codec-based processing is + * included (ie, IDCT scaling), so + * downsampled_width = ceil(image_width * Hi/Hmax * codec_data_unit/data_unit) + */ + JDIMENSION downsampled_width; /* actual width in samples */ + JDIMENSION downsampled_height; /* actual height in samples */ + /* This flag is used only for decompression. In cases where some of the + * components will be ignored (eg grayscale output from YCbCr image), + * we can skip most computations for the unused components. + */ + boolean component_needed; /* do we need the value of this component? */ + + /* These values are computed before starting a scan of the component. */ + /* The decompressor output side may not use these variables. */ + int MCU_width; /* number of data units per MCU, horizontally */ + int MCU_height; /* number of data units per MCU, vertically */ + int MCU_data_units; /* MCU_width * MCU_height */ + int MCU_sample_width; /* MCU width in samples, MCU_width*codec_data_unit */ + int last_col_width; /* # of non-dummy data_units across in last MCU */ + int last_row_height; /* # of non-dummy data_units down in last MCU */ + + /* Saved quantization table for component; NULL if none yet saved. + * See jdinput.c comments about the need for this information. + * This field is currently used only for decompression. + */ + JQUANT_TBL * quant_table; + + /* Private per-component storage for DCT or IDCT subsystem. */ + void * dct_table; +} jpeg_component_info; + + +/* The script for encoding a multiple-scan file is an array of these: */ + +typedef struct { + int comps_in_scan; /* number of components encoded in this scan */ + int component_index[MAX_COMPS_IN_SCAN]; /* their SOF/comp_info[] indexes */ + int Ss, Se; /* progressive JPEG spectral selection parms + lossless JPEG predictor select parm (Ss) */ + int Ah, Al; /* progressive JPEG successive approx. parms + lossless JPEG point transform parm (Al) */ +} jpeg_scan_info; + +/* The decompressor can save APPn and COM markers in a list of these: */ + +typedef struct jpeg_marker_struct FAR * jpeg_saved_marker_ptr; + +struct jpeg_marker_struct { + jpeg_saved_marker_ptr next; /* next in list, or NULL */ + UINT8 marker; /* marker code: JPEG_COM, or JPEG_APP0+n */ + unsigned int original_length; /* # bytes of data in the file */ + unsigned int data_length; /* # bytes of data saved at data[] */ + JOCTET FAR * data; /* the data contained in the marker */ + /* the marker length word is not counted in data_length or original_length */ +}; + +/* Known codec processes. */ + +typedef enum { + JPROC_SEQUENTIAL, /* baseline/extended sequential DCT */ + JPROC_PROGRESSIVE, /* progressive DCT */ + JPROC_LOSSLESS /* lossless (sequential) */ +} J_CODEC_PROCESS; + +/* Known color spaces. */ + +typedef enum { + JCS_UNKNOWN, /* error/unspecified */ + JCS_GRAYSCALE, /* monochrome */ + JCS_RGB, /* red/green/blue */ + JCS_YCbCr, /* Y/Cb/Cr (also known as YUV) */ + JCS_CMYK, /* C/M/Y/K */ + JCS_YCCK /* Y/Cb/Cr/K */ +} J_COLOR_SPACE; + +/* DCT/IDCT algorithm options. */ + +typedef enum { + JDCT_ISLOW, /* slow but accurate integer algorithm */ + JDCT_IFAST, /* faster, less accurate integer method */ + JDCT_FLOAT /* floating-point: accurate, fast on fast HW */ +} J_DCT_METHOD; + +#ifndef JDCT_DEFAULT /* may be overridden in jconfig.h */ +#define JDCT_DEFAULT JDCT_ISLOW +#endif +#ifndef JDCT_FASTEST /* may be overridden in jconfig.h */ +#define JDCT_FASTEST JDCT_IFAST +#endif + +/* Dithering options for decompression. */ + +typedef enum { + JDITHER_NONE, /* no dithering */ + JDITHER_ORDERED, /* simple ordered dither */ + JDITHER_FS /* Floyd-Steinberg error diffusion dither */ +} J_DITHER_MODE; + + +/* Common fields between JPEG compression and decompression master structs. */ + +#define jpeg_common_fields \ + struct jpeg_error_mgr * err; /* Error handler module */\ + struct jpeg_memory_mgr * mem; /* Memory manager module */\ + struct jpeg_progress_mgr * progress; /* Progress monitor, or NULL if none */\ + void * client_data; /* Available for use by application */\ + boolean is_decompressor; /* So common code can tell which is which */\ + int global_state /* For checking call sequence validity */ + +/* Routines that are to be used by both halves of the library are declared + * to receive a pointer to this structure. There are no actual instances of + * jpeg_common_struct, only of jpeg_compress_struct and jpeg_decompress_struct. + */ +struct jpeg_common_struct { + jpeg_common_fields; /* Fields common to both master struct types */ + /* Additional fields follow in an actual jpeg_compress_struct or + * jpeg_decompress_struct. All three structs must agree on these + * initial fields! (This would be a lot cleaner in C++.) + */ +}; + +typedef struct jpeg_common_struct * j_common_ptr; +typedef struct jpeg_compress_struct * j_compress_ptr; +typedef struct jpeg_decompress_struct * j_decompress_ptr; + + +/* Master record for a compression instance */ + +struct jpeg_compress_struct { + jpeg_common_fields; /* Fields shared with jpeg_decompress_struct */ + + /* Destination for compressed data */ + struct jpeg_destination_mgr * dest; + + /* Description of source image --- these fields must be filled in by + * outer application before starting compression. in_color_space must + * be correct before you can even call jpeg_set_defaults(). + */ + + JDIMENSION image_width; /* input image width */ + JDIMENSION image_height; /* input image height */ + int input_components; /* # of color components in input image */ + J_COLOR_SPACE in_color_space; /* colorspace of input image */ + + double input_gamma; /* image gamma of input image */ + + /* Compression parameters --- these fields must be set before calling + * jpeg_start_compress(). We recommend calling jpeg_set_defaults() to + * initialize everything to reasonable defaults, then changing anything + * the application specifically wants to change. That way you won't get + * burnt when new parameters are added. Also note that there are several + * helper routines to simplify changing parameters. + */ + + boolean lossless; /* TRUE=lossless encoding, FALSE=lossy */ + + int data_precision; /* bits of precision in image data */ + + int num_components; /* # of color components in JPEG image */ + J_COLOR_SPACE jpeg_color_space; /* colorspace of JPEG image */ + + jpeg_component_info * comp_info; + /* comp_info[i] describes component that appears i'th in SOF */ + + JQUANT_TBL * quant_tbl_ptrs[NUM_QUANT_TBLS]; + /* ptrs to coefficient quantization tables, or NULL if not defined */ + + JHUFF_TBL * dc_huff_tbl_ptrs[NUM_HUFF_TBLS]; + JHUFF_TBL * ac_huff_tbl_ptrs[NUM_HUFF_TBLS]; + /* ptrs to Huffman coding tables, or NULL if not defined */ + + UINT8 arith_dc_L[NUM_ARITH_TBLS]; /* L values for DC arith-coding tables */ + UINT8 arith_dc_U[NUM_ARITH_TBLS]; /* U values for DC arith-coding tables */ + UINT8 arith_ac_K[NUM_ARITH_TBLS]; /* Kx values for AC arith-coding tables */ + + int num_scans; /* # of entries in scan_info array */ + const jpeg_scan_info * scan_info; /* script for multi-scan file, or NULL */ + /* The default value of scan_info is NULL, which causes a single-scan + * sequential JPEG file to be emitted. To create a multi-scan file, + * set num_scans and scan_info to point to an array of scan definitions. + */ + + boolean raw_data_in; /* TRUE=caller supplies downsampled data */ + boolean arith_code; /* TRUE=arithmetic coding, FALSE=Huffman */ + boolean optimize_coding; /* TRUE=optimize entropy encoding parms */ + boolean CCIR601_sampling; /* TRUE=first samples are cosited */ + int smoothing_factor; /* 1..100, or 0 for no input smoothing */ + J_DCT_METHOD dct_method; /* DCT algorithm selector */ + + /* The restart interval can be specified in absolute MCUs by setting + * restart_interval, or in MCU rows by setting restart_in_rows + * (in which case the correct restart_interval will be figured + * for each scan). + */ + unsigned int restart_interval; /* MCUs per restart, or 0 for no restart */ + int restart_in_rows; /* if > 0, MCU rows per restart interval */ + + /* Parameters controlling emission of special markers. */ + + boolean write_JFIF_header; /* should a JFIF marker be written? */ + UINT8 JFIF_major_version; /* What to write for the JFIF version number */ + UINT8 JFIF_minor_version; + /* These three values are not used by the JPEG code, merely copied */ + /* into the JFIF APP0 marker. density_unit can be 0 for unknown, */ + /* 1 for dots/inch, or 2 for dots/cm. Note that the pixel aspect */ + /* ratio is defined by X_density/Y_density even when density_unit=0. */ + UINT8 density_unit; /* JFIF code for pixel size units */ + UINT16 X_density; /* Horizontal pixel density */ + UINT16 Y_density; /* Vertical pixel density */ + boolean write_Adobe_marker; /* should an Adobe marker be written? */ + + /* State variable: index of next scanline to be written to + * jpeg_write_scanlines(). Application may use this to control its + * processing loop, e.g., "while (next_scanline < image_height)". + */ + + JDIMENSION next_scanline; /* 0 .. image_height-1 */ + + /* Remaining fields are known throughout compressor, but generally + * should not be touched by a surrounding application. + */ + + /* + * These fields are computed during compression startup + */ + int data_unit; /* size of data unit in samples */ + J_CODEC_PROCESS process; /* encoding process of JPEG image */ + + int max_h_samp_factor; /* largest h_samp_factor */ + int max_v_samp_factor; /* largest v_samp_factor */ + + JDIMENSION total_iMCU_rows; /* # of iMCU rows to be input to codec */ + /* The codec receives data in units of MCU rows as defined for fully + * interleaved scans (whether the JPEG file is interleaved or not). + * There are v_samp_factor * data_unit sample rows of each component in an + * "iMCU" (interleaved MCU) row. + */ + + /* + * These fields are valid during any one scan. + * They describe the components and MCUs actually appearing in the scan. + */ + int comps_in_scan; /* # of JPEG components in this scan */ + jpeg_component_info * cur_comp_info[MAX_COMPS_IN_SCAN]; + /* *cur_comp_info[i] describes component that appears i'th in SOS */ + + JDIMENSION MCUs_per_row; /* # of MCUs across the image */ + JDIMENSION MCU_rows_in_scan; /* # of MCU rows in the image */ + + int data_units_in_MCU; /* # of data units per MCU */ + int MCU_membership[C_MAX_DATA_UNITS_IN_MCU]; + /* MCU_membership[i] is index in cur_comp_info of component owning */ + /* i'th block in an MCU */ + + int Ss, Se, Ah, Al; /* progressive/lossless JPEG parameters for scan */ + + /* + * Links to compression subobjects (methods and private variables of modules) + */ + struct jpeg_comp_master * master; + struct jpeg_c_main_controller * main; + struct jpeg_c_prep_controller * prep; + struct jpeg_c_codec * codec; + struct jpeg_marker_writer * marker; + struct jpeg_color_converter * cconvert; + struct jpeg_downsampler * downsample; + jpeg_scan_info * script_space; /* workspace for jpeg_simple_progression */ + int script_space_size; +}; + + +/* Master record for a decompression instance */ + +struct jpeg_decompress_struct { + jpeg_common_fields; /* Fields shared with jpeg_compress_struct */ + + /* Source of compressed data */ + struct jpeg_source_mgr * src; + + /* Basic description of image --- filled in by jpeg_read_header(). */ + /* Application may inspect these values to decide how to process image. */ + + JDIMENSION image_width; /* nominal image width (from SOF marker) */ + JDIMENSION image_height; /* nominal image height */ + int num_components; /* # of color components in JPEG image */ + J_COLOR_SPACE jpeg_color_space; /* colorspace of JPEG image */ + + /* Decompression processing parameters --- these fields must be set before + * calling jpeg_start_decompress(). Note that jpeg_read_header() initializes + * them to default values. + */ + + J_COLOR_SPACE out_color_space; /* colorspace for output */ + + unsigned int scale_num, scale_denom; /* fraction by which to scale image */ + + double output_gamma; /* image gamma wanted in output */ + + boolean buffered_image; /* TRUE=multiple output passes */ + boolean raw_data_out; /* TRUE=downsampled data wanted */ + + J_DCT_METHOD dct_method; /* IDCT algorithm selector */ + boolean do_fancy_upsampling; /* TRUE=apply fancy upsampling */ + boolean do_block_smoothing; /* TRUE=apply interblock smoothing */ + + boolean quantize_colors; /* TRUE=colormapped output wanted */ + /* the following are ignored if not quantize_colors: */ + J_DITHER_MODE dither_mode; /* type of color dithering to use */ + boolean two_pass_quantize; /* TRUE=use two-pass color quantization */ + int desired_number_of_colors; /* max # colors to use in created colormap */ + /* these are significant only in buffered-image mode: */ + boolean enable_1pass_quant; /* enable future use of 1-pass quantizer */ + boolean enable_external_quant;/* enable future use of external colormap */ + boolean enable_2pass_quant; /* enable future use of 2-pass quantizer */ + + /* Description of actual output image that will be returned to application. + * These fields are computed by jpeg_start_decompress(). + * You can also use jpeg_calc_output_dimensions() to determine these values + * in advance of calling jpeg_start_decompress(). + */ + + JDIMENSION output_width; /* scaled image width */ + JDIMENSION output_height; /* scaled image height */ + int out_color_components; /* # of color components in out_color_space */ + int output_components; /* # of color components returned */ + /* output_components is 1 (a colormap index) when quantizing colors; + * otherwise it equals out_color_components. + */ + int rec_outbuf_height; /* min recommended height of scanline buffer */ + /* If the buffer passed to jpeg_read_scanlines() is less than this many rows + * high, space and time will be wasted due to unnecessary data copying. + * Usually rec_outbuf_height will be 1 or 2, at most 4. + */ + + /* When quantizing colors, the output colormap is described by these fields. + * The application can supply a colormap by setting colormap non-NULL before + * calling jpeg_start_decompress; otherwise a colormap is created during + * jpeg_start_decompress or jpeg_start_output. + * The map has out_color_components rows and actual_number_of_colors columns. + */ + int actual_number_of_colors; /* number of entries in use */ + JSAMPARRAY colormap; /* The color map as a 2-D pixel array */ + + /* State variables: these variables indicate the progress of decompression. + * The application may examine these but must not modify them. + */ + + /* Row index of next scanline to be read from jpeg_read_scanlines(). + * Application may use this to control its processing loop, e.g., + * "while (output_scanline < output_height)". + */ + JDIMENSION output_scanline; /* 0 .. output_height-1 */ + + /* Current input scan number and number of iMCU rows completed in scan. + * These indicate the progress of the decompressor input side. + */ + int input_scan_number; /* Number of SOS markers seen so far */ + JDIMENSION input_iMCU_row; /* Number of iMCU rows completed */ + + /* The "output scan number" is the notional scan being displayed by the + * output side. The decompressor will not allow output scan/row number + * to get ahead of input scan/row, but it can fall arbitrarily far behind. + */ + int output_scan_number; /* Nominal scan number being displayed */ + JDIMENSION output_iMCU_row; /* Number of iMCU rows read */ + + /* Current progression status. coef_bits[c][i] indicates the precision + * with which component c's DCT coefficient i (in zigzag order) is known. + * It is -1 when no data has yet been received, otherwise it is the point + * transform (shift) value for the most recent scan of the coefficient + * (thus, 0 at completion of the progression). + * This pointer is NULL when reading a non-progressive file. + */ + int (*coef_bits)[DCTSIZE2]; /* -1 or current Al value for each coef */ + + /* Internal JPEG parameters --- the application usually need not look at + * these fields. Note that the decompressor output side may not use + * any parameters that can change between scans. + */ + + /* Quantization and Huffman tables are carried forward across input + * datastreams when processing abbreviated JPEG datastreams. + */ + + JQUANT_TBL * quant_tbl_ptrs[NUM_QUANT_TBLS]; + /* ptrs to coefficient quantization tables, or NULL if not defined */ + + JHUFF_TBL * dc_huff_tbl_ptrs[NUM_HUFF_TBLS]; + JHUFF_TBL * ac_huff_tbl_ptrs[NUM_HUFF_TBLS]; + /* ptrs to Huffman coding tables, or NULL if not defined */ + + /* These parameters are never carried across datastreams, since they + * are given in SOF/SOS markers or defined to be reset by SOI. + */ + + int data_precision; /* bits of precision in image data */ + + jpeg_component_info * comp_info; + /* comp_info[i] describes component that appears i'th in SOF */ + + boolean arith_code; /* TRUE=arithmetic coding, FALSE=Huffman */ + + UINT8 arith_dc_L[NUM_ARITH_TBLS]; /* L values for DC arith-coding tables */ + UINT8 arith_dc_U[NUM_ARITH_TBLS]; /* U values for DC arith-coding tables */ + UINT8 arith_ac_K[NUM_ARITH_TBLS]; /* Kx values for AC arith-coding tables */ + + unsigned int restart_interval; /* MCUs per restart interval, or 0 for no restart */ + + /* These fields record data obtained from optional markers recognized by + * the JPEG library. + */ + boolean saw_JFIF_marker; /* TRUE iff a JFIF APP0 marker was found */ + /* Data copied from JFIF marker; only valid if saw_JFIF_marker is TRUE: */ + UINT8 JFIF_major_version; /* JFIF version number */ + UINT8 JFIF_minor_version; + UINT8 density_unit; /* JFIF code for pixel size units */ + UINT16 X_density; /* Horizontal pixel density */ + UINT16 Y_density; /* Vertical pixel density */ + boolean saw_Adobe_marker; /* TRUE iff an Adobe APP14 marker was found */ + UINT8 Adobe_transform; /* Color transform code from Adobe marker */ + + boolean CCIR601_sampling; /* TRUE=first samples are cosited */ + + /* Aside from the specific data retained from APPn markers known to the + * library, the uninterpreted contents of any or all APPn and COM markers + * can be saved in a list for examination by the application. + */ + jpeg_saved_marker_ptr marker_list; /* Head of list of saved markers */ + + /* Remaining fields are known throughout decompressor, but generally + * should not be touched by a surrounding application. + */ + + /* + * These fields are computed during decompression startup + */ + int data_unit; /* size of data unit in samples */ + J_CODEC_PROCESS process; /* decoding process of JPEG image */ + + int max_h_samp_factor; /* largest h_samp_factor */ + int max_v_samp_factor; /* largest v_samp_factor */ + + int min_codec_data_unit; /* smallest codec_data_unit of any component */ + + JDIMENSION total_iMCU_rows; /* # of iMCU rows in image */ + /* The codec's input and output progress is measured in units of "iMCU" + * (interleaved MCU) rows. These are the same as MCU rows in fully + * interleaved JPEG scans, but are used whether the scan is interleaved + * or not. We define an iMCU row as v_samp_factor data_unit rows of each + * component. Therefore, the codec output contains + * v_samp_factor*codec_data_unit sample rows of a component per iMCU row. + */ + + JSAMPLE * sample_range_limit; /* table for fast range-limiting */ + + /* + * These fields are valid during any one scan. + * They describe the components and MCUs actually appearing in the scan. + * Note that the decompressor output side must not use these fields. + */ + int comps_in_scan; /* # of JPEG components in this scan */ + jpeg_component_info * cur_comp_info[MAX_COMPS_IN_SCAN]; + /* *cur_comp_info[i] describes component that appears i'th in SOS */ + + JDIMENSION MCUs_per_row; /* # of MCUs across the image */ + JDIMENSION MCU_rows_in_scan; /* # of MCU rows in the image */ + + int data_units_in_MCU; /* # of data _units per MCU */ + int MCU_membership[D_MAX_DATA_UNITS_IN_MCU]; + /* MCU_membership[i] is index in cur_comp_info of component owning */ + /* i'th data unit in an MCU */ + + int Ss, Se, Ah, Al; /* progressive/lossless JPEG parms for scan */ + + /* This field is shared between entropy decoder and marker parser. + * It is either zero or the code of a JPEG marker that has been + * read from the data source, but has not yet been processed. + */ + int unread_marker; + + /* + * Links to decompression subobjects (methods, private variables of modules) + */ + struct jpeg_decomp_master * master; + struct jpeg_d_main_controller * main; + struct jpeg_d_codec * codec; + struct jpeg_d_post_controller * post; + struct jpeg_input_controller * inputctl; + struct jpeg_marker_reader * marker; + struct jpeg_upsampler * upsample; + struct jpeg_color_deconverter * cconvert; + struct jpeg_color_quantizer * cquantize; +}; + + +/* "Object" declarations for JPEG modules that may be supplied or called + * directly by the surrounding application. + * As with all objects in the JPEG library, these structs only define the + * publicly visible methods and state variables of a module. Additional + * private fields may exist after the public ones. + */ + + +/* Error handler object */ + +struct jpeg_error_mgr { + /* Error exit handler: does not return to caller */ + JMETHOD(void, error_exit, (j_common_ptr cinfo)); + /* Conditionally emit a trace or warning message */ + JMETHOD(void, emit_message, (j_common_ptr cinfo, int msg_level)); + /* Routine that actually outputs a trace or error message */ + JMETHOD(void, output_message, (j_common_ptr cinfo)); + /* Format a message string for the most recent JPEG error or message */ + JMETHOD(void, format_message, (j_common_ptr cinfo, char * buffer)); +#define JMSG_LENGTH_MAX 200 /* recommended size of format_message buffer */ + /* Reset error state variables at start of a new image */ + JMETHOD(void, reset_error_mgr, (j_common_ptr cinfo)); + + /* The message ID code and any parameters are saved here. + * A message can have one string parameter or up to 8 int parameters. + */ + int msg_code; +#define JMSG_STR_PARM_MAX 80 + union { + int i[8]; + char s[JMSG_STR_PARM_MAX]; + } msg_parm; + + /* Standard state variables for error facility */ + + int trace_level; /* max msg_level that will be displayed */ + + /* For recoverable corrupt-data errors, we emit a warning message, + * but keep going unless emit_message chooses to abort. emit_message + * should count warnings in num_warnings. The surrounding application + * can check for bad data by seeing if num_warnings is nonzero at the + * end of processing. + */ + long num_warnings; /* number of corrupt-data warnings */ + + /* These fields point to the table(s) of error message strings. + * An application can change the table pointer to switch to a different + * message list (typically, to change the language in which errors are + * reported). Some applications may wish to add additional error codes + * that will be handled by the JPEG library error mechanism; the second + * table pointer is used for this purpose. + * + * First table includes all errors generated by JPEG library itself. + * Error code 0 is reserved for a "no such error string" message. + */ + const char * const * jpeg_message_table; /* Library errors */ + int last_jpeg_message; /* Table contains strings 0..last_jpeg_message */ + /* Second table can be added by application (see cjpeg/djpeg for example). + * It contains strings numbered first_addon_message..last_addon_message. + */ + const char * const * addon_message_table; /* Non-library errors */ + int first_addon_message; /* code for first string in addon table */ + int last_addon_message; /* code for last string in addon table */ +}; + + +/* Progress monitor object */ + +struct jpeg_progress_mgr { + JMETHOD(void, progress_monitor, (j_common_ptr cinfo)); + + long pass_counter; /* work units completed in this pass */ + long pass_limit; /* total number of work units in this pass */ + int completed_passes; /* passes completed so far */ + int total_passes; /* total number of passes expected */ +}; + + +/* Data destination object for compression */ + +struct jpeg_destination_mgr { + JOCTET * next_output_byte; /* => next byte to write in buffer */ + size_t free_in_buffer; /* # of byte spaces remaining in buffer */ + + JMETHOD(void, init_destination, (j_compress_ptr cinfo)); + JMETHOD(boolean, empty_output_buffer, (j_compress_ptr cinfo)); + JMETHOD(void, term_destination, (j_compress_ptr cinfo)); +}; + + +/* Data source object for decompression */ + +struct jpeg_source_mgr { + const JOCTET * next_input_byte; /* => next byte to read from buffer */ + size_t bytes_in_buffer; /* # of bytes remaining in buffer */ + + JMETHOD(void, init_source, (j_decompress_ptr cinfo)); + JMETHOD(boolean, fill_input_buffer, (j_decompress_ptr cinfo)); + JMETHOD(void, skip_input_data, (j_decompress_ptr cinfo, long num_bytes)); + JMETHOD(boolean, resync_to_restart, (j_decompress_ptr cinfo, int desired)); + JMETHOD(void, term_source, (j_decompress_ptr cinfo)); +}; + + +/* Memory manager object. + * Allocates "small" objects (a few K total), "large" objects (tens of K), + * and "really big" objects (virtual arrays with backing store if needed). + * The memory manager does not allow individual objects to be freed; rather, + * each created object is assigned to a pool, and whole pools can be freed + * at once. This is faster and more convenient than remembering exactly what + * to free, especially where malloc()/free() are not too speedy. + * NB: alloc routines never return NULL. They exit to error_exit if not + * successful. + */ + +#define JPOOL_PERMANENT 0 /* lasts until master record is destroyed */ +#define JPOOL_IMAGE 1 /* lasts until done with image/datastream */ +#define JPOOL_NUMPOOLS 2 + +typedef struct jvirt_sarray_control * jvirt_sarray_ptr; +typedef struct jvirt_barray_control * jvirt_barray_ptr; + + +#ifdef C_LOSSLESS_SUPPORTED +#define NEED_DARRAY +#else +#ifdef D_LOSSLESS_SUPPORTED +#define NEED_DARRAY +#endif +#endif + +struct jpeg_memory_mgr { + /* Method pointers */ + JMETHOD(void *, alloc_small, (j_common_ptr cinfo, int pool_id, + size_t sizeofobject)); + JMETHOD(void FAR *, alloc_large, (j_common_ptr cinfo, int pool_id, + size_t sizeofobject)); + JMETHOD(JSAMPARRAY, alloc_sarray, (j_common_ptr cinfo, int pool_id, + JDIMENSION samplesperrow, + JDIMENSION numrows)); + JMETHOD(JBLOCKARRAY, alloc_barray, (j_common_ptr cinfo, int pool_id, + JDIMENSION blocksperrow, + JDIMENSION numrows)); +#ifdef NEED_DARRAY + JMETHOD(JDIFFARRAY, alloc_darray, (j_common_ptr cinfo, int pool_id, + JDIMENSION diffsperrow, + JDIMENSION numrows)); +#endif + JMETHOD(jvirt_sarray_ptr, request_virt_sarray, (j_common_ptr cinfo, + int pool_id, + boolean pre_zero, + JDIMENSION samplesperrow, + JDIMENSION numrows, + JDIMENSION maxaccess)); + JMETHOD(jvirt_barray_ptr, request_virt_barray, (j_common_ptr cinfo, + int pool_id, + boolean pre_zero, + JDIMENSION blocksperrow, + JDIMENSION numrows, + JDIMENSION maxaccess)); + JMETHOD(void, realize_virt_arrays, (j_common_ptr cinfo)); + JMETHOD(JSAMPARRAY, access_virt_sarray, (j_common_ptr cinfo, + jvirt_sarray_ptr ptr, + JDIMENSION start_row, + JDIMENSION num_rows, + boolean writable)); + JMETHOD(JBLOCKARRAY, access_virt_barray, (j_common_ptr cinfo, + jvirt_barray_ptr ptr, + JDIMENSION start_row, + JDIMENSION num_rows, + boolean writable)); + JMETHOD(void, free_pool, (j_common_ptr cinfo, int pool_id)); + JMETHOD(void, self_destruct, (j_common_ptr cinfo)); + + /* Limit on memory allocation for this JPEG object. (Note that this is + * merely advisory, not a guaranteed maximum; it only affects the space + * used for virtual-array buffers.) May be changed by outer application + * after creating the JPEG object. + */ + long max_memory_to_use; + + /* Maximum allocation request accepted by alloc_large. */ + long max_alloc_chunk; +}; + + +/* Routine signature for application-supplied marker processing methods. + * Need not pass marker code since it is stored in cinfo->unread_marker. + */ +typedef JMETHOD(boolean, jpeg_marker_parser_method, (j_decompress_ptr cinfo)); + + +/* Declarations for routines called by application. + * The JPP macro hides prototype parameters from compilers that can't cope. + * Note JPP requires double parentheses. + */ + +#ifdef HAVE_PROTOTYPES +#define JPP(arglist) arglist +#else +#define JPP(arglist) () +#endif + + +/* Short forms of external names for systems with brain-damaged linkers. + * We shorten external names to be unique in the first six letters, which + * is good enough for all known systems. + * (If your compiler itself needs names to be unique in less than 15 + * characters, you are out of luck. Get a better compiler.) + */ + +/* MAKE SURE THAT ALL FUNCTIONS DECLARED GLOBAL() ARE RE-DEFINED HERE! */ + +#ifdef NEED_SHORT_EXTERNAL_NAMES +#define jcopy_block_row jcopy8_block_row +#define jcopy_sample_rows jcopy8_sample_rows +#define jdiv_round_up jdiv8_round_up +#define jinit_1pass_quantizer jinit8_1pass_quantizer +#define jinit_2pass_quantizer jinit8_2pass_quantizer +#define jinit_arith_decoder jinit8_arith_decoder +#define jinit_arith_encoder jinit8_arith_encoder +#define jinit_c_codec jinit8_c_codec +#define jinit_c_coef_controller jinit8_c_coef_controller +#define jinit_c_diff_controller jinit8_c_diff_controller +#define jinit_c_main_controller jinit8_c_main_controller +#define jinit_c_master_control jinit8_c_master_control +#define jinit_c_prep_controller jinit8_c_prep_controller +#define jinit_c_scaler jinit8_c_scaler +#define jinit_color_converter jinit8_color_converter +#define jinit_color_deconverter jinit8_color_deconverter +#define jinit_compress_master jinit8_compress_master +#define jinit_d_codec jinit8_d_codec +#define jinit_d_coef_controller jinit8_d_coef_controller +#define jinit_d_diff_controller jinit8_d_diff_controller +#define jinit_d_main_controller jinit8_d_main_controller +#define jinit_d_post_controller jinit8_d_post_controller +#define jinit_d_post_controller jinit8_d_post_controller +#define jinit_d_scaler jinit8_d_scaler +#define jinit_differencer jinit8_differencer +#define jinit_downsampler jinit8_downsampler +#define jinit_forward_dct jinit8_forward_dct +#define jinit_input_controller jinit8_input_controller +#define jinit_inverse_dct jinit8_inverse_dct +#define jinit_lhuff_decoder jinit8_lhuff_decoder +#define jinit_lhuff_encoder jinit8_lhuff_encoder +#define jinit_lossless_c_codec jinit8_lossless_c_codec +#define jinit_lossless_d_codec jinit8_lossless_d_codec +#define jinit_lossy_c_codec jinit8_lossy_c_codec +#define jinit_lossy_d_codec jinit8_lossy_d_codec +#define jinit_marker_reader jinit8_marker_reader +#define jinit_marker_writer jinit8_marker_writer +#define jinit_master_decompress jinit8_master_decompress +#define jinit_memory_mgr jinit8_memory_mgr +#define jinit_merged_upsampler jinit8_merged_upsampler +#define jinit_phuff_decoder jinit8_phuff_decoder +#define jinit_phuff_encoder jinit8_phuff_encoder +#define jinit_shuff_decoder jinit8_shuff_decoder +#define jinit_shuff_encoder jinit8_shuff_encoder +#define jinit_undifferencer jinit8_undifferencer +#define jinit_upsampler jinit8_upsampler +#define jpeg_CreateCompress jpeg8_CreateCompress +#define jpeg_CreateDecompress jpeg8_CreateDecompress +#define jpeg_abort jpeg8_abort +#define jpeg_abort_compress jpeg8_abort_compress +#define jpeg_abort_decompress jpeg8_abort_decompress +#define jpeg_add_quant_table jpeg8_add_quant_table +#define jpeg_alloc_huff_table jpeg8_alloc_huff_table +#define jpeg_alloc_quant_table jpeg8_alloc_quant_table +#define jpeg_calc_output_dimensions jpeg8_calc_output_dimensions +#define jpeg_consume_input jpeg8_consume_input +#define jpeg_copy_critical_parameters jpeg8_copy_critical_parameters +#define jpeg_default_colorspace jpeg8_default_colorspace +#define jpeg_destroy jpeg8_destroy +#define jpeg_destroy_compress jpeg8_destroy_compress +#define jpeg_destroy_decompress jpeg8_destroy_decompress +#define jpeg_fdct_float jpeg8_fdct_float +#define jpeg_fdct_ifast jpeg8_fdct_ifast +#define jpeg_fdct_islow jpeg8_fdct_islow +#define jpeg_fill_bit_buffer jpeg8_fill_bit_buffer +#define jpeg_finish_compress jpeg8_finish_compress +#define jpeg_finish_decompress jpeg8_finish_decompress +#define jpeg_finish_output jpeg8_finish_output +#define jpeg_free_large jpeg8_free_large +#define jpeg_free_small jpeg8_free_small +#define jpeg_gen_optimal_table jpeg8_gen_optimal_table +#define jpeg_get_large jpeg8_get_large +#define jpeg_get_small jpeg8_get_small +#define jpeg_has_multiple_scans jpeg8_has_multiple_scans +#define jpeg_huff_decode jpeg8_huff_decode +#define jpeg_idct_1x1 jpeg8_idct_1x1 +#define jpeg_idct_2x2 jpeg8_idct_2x2 +#define jpeg_idct_4x4 jpeg8_idct_4x4 +#define jpeg_idct_float jpeg8_idct_float +#define jpeg_idct_ifast jpeg8_idct_ifast +#define jpeg_idct_islow jpeg8_idct_islow +#define jpeg_input_complete jpeg8_input_complete +#define jpeg_make_c_derived_tbl jpeg8_make_c_derived_tbl +#define jpeg_make_d_derived_tbl jpeg8_make_d_derived_tbl +#define jpeg_mem_available jpeg8_mem_available +#define jpeg_mem_init jpeg8_mem_init +#define jpeg_mem_term jpeg8_mem_term +#define jpeg_new_colormap jpeg8_new_colormap +#define jpeg_open_backing_store jpeg8_open_backing_store +#define jpeg_quality_scaling jpeg8_quality_scaling +#define jpeg_read_coefficients jpeg8_read_coefficients +#define jpeg_read_header jpeg8_read_header +#define jpeg_read_raw_data jpeg8_read_raw_data +#define jpeg_read_scanlines jpeg8_read_scanlines +#define jpeg_resync_to_restart jpeg8_resync_to_restart +#define jpeg_save_markers jpeg8_save_markers +#define jpeg_set_colorspace jpeg8_set_colorspace +#define jpeg_set_defaults jpeg8_set_defaults +#define jpeg_set_linear_quality jpeg8_set_linear_quality +#define jpeg_set_marker_processor jpeg8_set_marker_processor +#define jpeg_set_quality jpeg8_set_quality +#define jpeg_simple_lossless jpeg8_simple_lossless +#define jpeg_simple_progression jpeg8_simple_progression +#define jpeg_start_compress jpeg8_start_compress +#define jpeg_start_decompress jpeg8_start_decompress +#define jpeg_start_output jpeg8_start_output +#define jpeg_std_error jpeg8_std_error +#define jpeg_stdio_dest jpeg8_stdio_dest +#define jpeg_stdio_src jpeg8_stdio_src +#define jpeg_suppress_tables jpeg8_suppress_tables +#define jpeg_write_coefficients jpeg8_write_coefficients +#define jpeg_write_m_byte jpeg8_write_m_byte +#define jpeg_write_m_header jpeg8_write_m_header +#define jpeg_write_marker jpeg8_write_marker +#define jpeg_write_raw_data jpeg8_write_raw_data +#define jpeg_write_scanlines jpeg8_write_scanlines +#define jpeg_write_tables jpeg8_write_tables +#define jround_up jround8_up +#define jzero_far jzero8_far +#endif /* NEED_SHORT_EXTERNAL_NAMES */ + + +/* Default error-management setup */ +EXTERN(struct jpeg_error_mgr *) jpeg_std_error + JPP((struct jpeg_error_mgr * err)); + +/* Initialization of JPEG compression objects. + * jpeg_create_compress() and jpeg_create_decompress() are the exported + * names that applications should call. These expand to calls on + * jpeg_CreateCompress and jpeg_CreateDecompress with additional information + * passed for version mismatch checking. + * NB: you must set up the error-manager BEFORE calling jpeg_create_xxx. + */ +#define jpeg_create_compress(cinfo) \ + jpeg_CreateCompress((cinfo), JPEG_LIB_VERSION, \ + (size_t) sizeof(struct jpeg_compress_struct)) +#define jpeg_create_decompress(cinfo) \ + jpeg_CreateDecompress((cinfo), JPEG_LIB_VERSION, \ + (size_t) sizeof(struct jpeg_decompress_struct)) +EXTERN(void) jpeg_CreateCompress JPP((j_compress_ptr cinfo, + int version, size_t structsize)); +EXTERN(void) jpeg_CreateDecompress JPP((j_decompress_ptr cinfo, + int version, size_t structsize)); +/* Destruction of JPEG compression objects */ +EXTERN(void) jpeg_destroy_compress JPP((j_compress_ptr cinfo)); +EXTERN(void) jpeg_destroy_decompress JPP((j_decompress_ptr cinfo)); + +/* Standard data source and destination managers: stdio streams. */ +/* Caller is responsible for opening the file before and closing after. */ +EXTERN(void) jpeg_stdio_dest JPP((j_compress_ptr cinfo, FILE * outfile)); +EXTERN(void) jpeg_stdio_src JPP((j_decompress_ptr cinfo, FILE * infile)); + +/* Default parameter setup for compression */ +EXTERN(void) jpeg_set_defaults JPP((j_compress_ptr cinfo)); +/* Compression parameter setup aids */ +EXTERN(void) jpeg_set_colorspace JPP((j_compress_ptr cinfo, + J_COLOR_SPACE colorspace)); +EXTERN(void) jpeg_default_colorspace JPP((j_compress_ptr cinfo)); +EXTERN(void) jpeg_set_quality JPP((j_compress_ptr cinfo, int quality, + boolean force_baseline)); +EXTERN(void) jpeg_set_linear_quality JPP((j_compress_ptr cinfo, + int scale_factor, + boolean force_baseline)); +EXTERN(void) jpeg_add_quant_table JPP((j_compress_ptr cinfo, int which_tbl, + const unsigned int *basic_table, + int scale_factor, + boolean force_baseline)); +EXTERN(int) jpeg_quality_scaling JPP((int quality)); +EXTERN(void) jpeg_simple_lossless JPP((j_compress_ptr cinfo, + int predictor, int point_transform)); +EXTERN(void) jpeg_simple_progression JPP((j_compress_ptr cinfo)); +EXTERN(void) jpeg_suppress_tables JPP((j_compress_ptr cinfo, + boolean suppress)); +EXTERN(JQUANT_TBL *) jpeg_alloc_quant_table JPP((j_common_ptr cinfo)); +EXTERN(JHUFF_TBL *) jpeg_alloc_huff_table JPP((j_common_ptr cinfo)); + +/* Main entry points for compression */ +EXTERN(void) jpeg_start_compress JPP((j_compress_ptr cinfo, + boolean write_all_tables)); +EXTERN(JDIMENSION) jpeg_write_scanlines JPP((j_compress_ptr cinfo, + JSAMPARRAY scanlines, + JDIMENSION num_lines)); +EXTERN(void) jpeg_finish_compress JPP((j_compress_ptr cinfo)); + +/* Replaces jpeg_write_scanlines when writing raw downsampled data. */ +EXTERN(JDIMENSION) jpeg_write_raw_data JPP((j_compress_ptr cinfo, + JSAMPIMAGE data, + JDIMENSION num_lines)); + +/* Write a special marker. See libjpeg.doc concerning safe usage. */ +EXTERN(void) jpeg_write_marker + JPP((j_compress_ptr cinfo, int marker, + const JOCTET * dataptr, unsigned int datalen)); +/* Same, but piecemeal. */ +EXTERN(void) jpeg_write_m_header + JPP((j_compress_ptr cinfo, int marker, unsigned int datalen)); +EXTERN(void) jpeg_write_m_byte + JPP((j_compress_ptr cinfo, int val)); + +/* Alternate compression function: just write an abbreviated table file */ +EXTERN(void) jpeg_write_tables JPP((j_compress_ptr cinfo)); + +/* Decompression startup: read start of JPEG datastream to see what's there */ +EXTERN(int) jpeg_read_header JPP((j_decompress_ptr cinfo, + boolean require_image)); +/* Return value is one of: */ +#define JPEG_SUSPENDED 0 /* Suspended due to lack of input data */ +#define JPEG_HEADER_OK 1 /* Found valid image datastream */ +#define JPEG_HEADER_TABLES_ONLY 2 /* Found valid table-specs-only datastream */ +/* If you pass require_image = TRUE (normal case), you need not check for + * a TABLES_ONLY return code; an abbreviated file will cause an error exit. + * JPEG_SUSPENDED is only possible if you use a data source module that can + * give a suspension return (the stdio source module doesn't). + */ + +/* Main entry points for decompression */ +EXTERN(boolean) jpeg_start_decompress JPP((j_decompress_ptr cinfo)); +EXTERN(JDIMENSION) jpeg_read_scanlines JPP((j_decompress_ptr cinfo, + JSAMPARRAY scanlines, + JDIMENSION max_lines)); +EXTERN(boolean) jpeg_finish_decompress JPP((j_decompress_ptr cinfo)); + +/* Replaces jpeg_read_scanlines when reading raw downsampled data. */ +EXTERN(JDIMENSION) jpeg_read_raw_data JPP((j_decompress_ptr cinfo, + JSAMPIMAGE data, + JDIMENSION max_lines)); + +/* Additional entry points for buffered-image mode. */ +EXTERN(boolean) jpeg_has_multiple_scans JPP((j_decompress_ptr cinfo)); +EXTERN(boolean) jpeg_start_output JPP((j_decompress_ptr cinfo, + int scan_number)); +EXTERN(boolean) jpeg_finish_output JPP((j_decompress_ptr cinfo)); +EXTERN(boolean) jpeg_input_complete JPP((j_decompress_ptr cinfo)); +EXTERN(void) jpeg_new_colormap JPP((j_decompress_ptr cinfo)); +EXTERN(int) jpeg_consume_input JPP((j_decompress_ptr cinfo)); +/* Return value is one of: */ +/* #define JPEG_SUSPENDED 0 Suspended due to lack of input data */ +#define JPEG_REACHED_SOS 1 /* Reached start of new scan */ +#define JPEG_REACHED_EOI 2 /* Reached end of image */ +#define JPEG_ROW_COMPLETED 3 /* Completed one iMCU row */ +#define JPEG_SCAN_COMPLETED 4 /* Completed last iMCU row of a scan */ + +/* Precalculate output dimensions for current decompression parameters. */ +EXTERN(void) jpeg_calc_output_dimensions JPP((j_decompress_ptr cinfo)); + +/* Control saving of COM and APPn markers into marker_list. */ +EXTERN(void) jpeg_save_markers + JPP((j_decompress_ptr cinfo, int marker_code, + unsigned int length_limit)); + +/* Install a special processing method for COM or APPn markers. */ +EXTERN(void) jpeg_set_marker_processor + JPP((j_decompress_ptr cinfo, int marker_code, + jpeg_marker_parser_method routine)); + +/* Read or write raw DCT coefficients --- useful for lossless transcoding. */ +EXTERN(jvirt_barray_ptr *) jpeg_read_coefficients JPP((j_decompress_ptr cinfo)); +EXTERN(void) jpeg_write_coefficients JPP((j_compress_ptr cinfo, + jvirt_barray_ptr * coef_arrays)); +EXTERN(void) jpeg_copy_critical_parameters JPP((j_decompress_ptr srcinfo, + j_compress_ptr dstinfo)); + +/* If you choose to abort compression or decompression before completing + * jpeg_finish_(de)compress, then you need to clean up to release memory, + * temporary files, etc. You can just call jpeg_destroy_(de)compress + * if you're done with the JPEG object, but if you want to clean it up and + * reuse it, call this: + */ +EXTERN(void) jpeg_abort_compress JPP((j_compress_ptr cinfo)); +EXTERN(void) jpeg_abort_decompress JPP((j_decompress_ptr cinfo)); + +/* Generic versions of jpeg_abort and jpeg_destroy that work on either + * flavor of JPEG object. These may be more convenient in some places. + */ +EXTERN(void) jpeg_abort JPP((j_common_ptr cinfo)); +EXTERN(void) jpeg_destroy JPP((j_common_ptr cinfo)); + +/* Default restart-marker-resync procedure for use by data source modules */ +EXTERN(boolean) jpeg_resync_to_restart JPP((j_decompress_ptr cinfo, + int desired)); + + +/* These marker codes are exported since applications and data source modules + * are likely to want to use them. + */ + +#define JPEG_RST0 0xD0 /* RST0 marker code */ +#define JPEG_EOI 0xD9 /* EOI marker code */ +#define JPEG_APP0 0xE0 /* APP0 marker code */ +#define JPEG_COM 0xFE /* COM marker code */ + + +/* If we have a brain-damaged compiler that emits warnings (or worse, errors) + * for structure definitions that are never filled in, keep it quiet by + * supplying dummy definitions for the various substructures. + */ + +#ifdef INCOMPLETE_TYPES_BROKEN +#ifndef JPEG_INTERNALS /* will be defined in jpegint.h */ +struct jvirt_sarray_control { long dummy; }; +struct jvirt_barray_control { long dummy; }; +struct jpeg_comp_master { long dummy; }; +struct jpeg_c_main_controller { long dummy; }; +struct jpeg_c_prep_controller { long dummy; }; +struct jpeg_c_coef_controller { long dummy; }; +struct jpeg_marker_writer { long dummy; }; +struct jpeg_color_converter { long dummy; }; +struct jpeg_downsampler { long dummy; }; +struct jpeg_forward_dct { long dummy; }; +struct jpeg_entropy_encoder { long dummy; }; +struct jpeg_decomp_master { long dummy; }; +struct jpeg_d_main_controller { long dummy; }; +struct jpeg_d_coef_controller { long dummy; }; +struct jpeg_d_post_controller { long dummy; }; +struct jpeg_input_controller { long dummy; }; +struct jpeg_marker_reader { long dummy; }; +struct jpeg_entropy_decoder { long dummy; }; +struct jpeg_inverse_dct { long dummy; }; +struct jpeg_upsampler { long dummy; }; +struct jpeg_color_deconverter { long dummy; }; +struct jpeg_color_quantizer { long dummy; }; +#endif /* JPEG_INTERNALS */ +#endif /* INCOMPLETE_TYPES_BROKEN */ + + +/* + * The JPEG library modules define JPEG_INTERNALS before including this file. + * The internal structure declarations are read only when that is true. + * Applications using the library should not include jpegint.h, but may wish + * to include jerror.h. + */ + +#ifdef JPEG_INTERNALS +#include "jpegint8.h" /* fetch private declarations */ +#include "jerror8.h" /* fetch error codes too */ +#endif + +#endif /* JPEGLIB_H */ diff --git a/dcmjpeg/libijg8/jquant1.c b/dcmjpeg/libijg8/jquant1.c new file mode 100644 index 00000000..90a209c1 --- /dev/null +++ b/dcmjpeg/libijg8/jquant1.c @@ -0,0 +1,856 @@ +/* + * jquant1.c + * + * Copyright (C) 1991-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains 1-pass color quantization (color mapping) routines. + * These routines provide mapping to a fixed color map using equally spaced + * color values. Optional Floyd-Steinberg or ordered dithering is available. + */ + +#define JPEG_INTERNALS +#include "jinclude8.h" +#include "jpeglib8.h" + +#ifdef QUANT_1PASS_SUPPORTED + + +/* + * The main purpose of 1-pass quantization is to provide a fast, if not very + * high quality, colormapped output capability. A 2-pass quantizer usually + * gives better visual quality; however, for quantized grayscale output this + * quantizer is perfectly adequate. Dithering is highly recommended with this + * quantizer, though you can turn it off if you really want to. + * + * In 1-pass quantization the colormap must be chosen in advance of seeing the + * image. We use a map consisting of all combinations of Ncolors[i] color + * values for the i'th component. The Ncolors[] values are chosen so that + * their product, the total number of colors, is no more than that requested. + * (In most cases, the product will be somewhat less.) + * + * Since the colormap is orthogonal, the representative value for each color + * component can be determined without considering the other components; + * then these indexes can be combined into a colormap index by a standard + * N-dimensional-array-subscript calculation. Most of the arithmetic involved + * can be precalculated and stored in the lookup table colorindex[]. + * colorindex[i][j] maps pixel value j in component i to the nearest + * representative value (grid plane) for that component; this index is + * multiplied by the array stride for component i, so that the + * index of the colormap entry closest to a given pixel value is just + * sum( colorindex[component-number][pixel-component-value] ) + * Aside from being fast, this scheme allows for variable spacing between + * representative values with no additional lookup cost. + * + * If gamma correction has been applied in color conversion, it might be wise + * to adjust the color grid spacing so that the representative colors are + * equidistant in linear space. At this writing, gamma correction is not + * implemented by jdcolor, so nothing is done here. + */ + + +/* Declarations for ordered dithering. + * + * We use a standard 16x16 ordered dither array. The basic concept of ordered + * dithering is described in many references, for instance Dale Schumacher's + * chapter II.2 of Graphics Gems II (James Arvo, ed. Academic Press, 1991). + * In place of Schumacher's comparisons against a "threshold" value, we add a + * "dither" value to the input pixel and then round the result to the nearest + * output value. The dither value is equivalent to (0.5 - threshold) times + * the distance between output values. For ordered dithering, we assume that + * the output colors are equally spaced; if not, results will probably be + * worse, since the dither may be too much or too little at a given point. + * + * The normal calculation would be to form pixel value + dither, range-limit + * this to 0..MAXJSAMPLE, and then index into the colorindex table as usual. + * We can skip the separate range-limiting step by extending the colorindex + * table in both directions. + */ + +#define ODITHER_SIZE 16 /* dimension of dither matrix */ +/* NB: if ODITHER_SIZE is not a power of 2, ODITHER_MASK uses will break */ +#define ODITHER_CELLS (ODITHER_SIZE*ODITHER_SIZE) /* # cells in matrix */ +#define ODITHER_MASK (ODITHER_SIZE-1) /* mask for wrapping around counters */ + +typedef int ODITHER_MATRIX[ODITHER_SIZE][ODITHER_SIZE]; +typedef int (*ODITHER_MATRIX_PTR)[ODITHER_SIZE]; + +static const UINT8 base_dither_matrix[ODITHER_SIZE][ODITHER_SIZE] = { + /* Bayer's order-4 dither array. Generated by the code given in + * Stephen Hawley's article "Ordered Dithering" in Graphics Gems I. + * The values in this array must range from 0 to ODITHER_CELLS-1. + */ + { 0,192, 48,240, 12,204, 60,252, 3,195, 51,243, 15,207, 63,255 }, + { 128, 64,176,112,140, 76,188,124,131, 67,179,115,143, 79,191,127 }, + { 32,224, 16,208, 44,236, 28,220, 35,227, 19,211, 47,239, 31,223 }, + { 160, 96,144, 80,172,108,156, 92,163, 99,147, 83,175,111,159, 95 }, + { 8,200, 56,248, 4,196, 52,244, 11,203, 59,251, 7,199, 55,247 }, + { 136, 72,184,120,132, 68,180,116,139, 75,187,123,135, 71,183,119 }, + { 40,232, 24,216, 36,228, 20,212, 43,235, 27,219, 39,231, 23,215 }, + { 168,104,152, 88,164,100,148, 84,171,107,155, 91,167,103,151, 87 }, + { 2,194, 50,242, 14,206, 62,254, 1,193, 49,241, 13,205, 61,253 }, + { 130, 66,178,114,142, 78,190,126,129, 65,177,113,141, 77,189,125 }, + { 34,226, 18,210, 46,238, 30,222, 33,225, 17,209, 45,237, 29,221 }, + { 162, 98,146, 82,174,110,158, 94,161, 97,145, 81,173,109,157, 93 }, + { 10,202, 58,250, 6,198, 54,246, 9,201, 57,249, 5,197, 53,245 }, + { 138, 74,186,122,134, 70,182,118,137, 73,185,121,133, 69,181,117 }, + { 42,234, 26,218, 38,230, 22,214, 41,233, 25,217, 37,229, 21,213 }, + { 170,106,154, 90,166,102,150, 86,169,105,153, 89,165,101,149, 85 } +}; + + +/* Declarations for Floyd-Steinberg dithering. + * + * Errors are accumulated into the array fserrors[], at a resolution of + * 1/16th of a pixel count. The error at a given pixel is propagated + * to its not-yet-processed neighbors using the standard F-S fractions, + * ... (here) 7/16 + * 3/16 5/16 1/16 + * We work left-to-right on even rows, right-to-left on odd rows. + * + * We can get away with a single array (holding one row's worth of errors) + * by using it to store the current row's errors at pixel columns not yet + * processed, but the next row's errors at columns already processed. We + * need only a few extra variables to hold the errors immediately around the + * current column. (If we are lucky, those variables are in registers, but + * even if not, they're probably cheaper to access than array elements are.) + * + * The fserrors[] array is indexed [component#][position]. + * We provide (#columns + 2) entries per component; the extra entry at each + * end saves us from special-casing the first and last pixels. + * + * Note: on a wide image, we might not have enough room in a PC's near data + * segment to hold the error array; so it is allocated with alloc_large. + */ + +#if BITS_IN_JSAMPLE == 8 +typedef INT16 FSERROR; /* 16 bits should be enough */ +typedef int LOCFSERROR; /* use 'int' for calculation temps */ +#else +typedef IJG_INT32 FSERROR; /* may need more than 16 bits */ +typedef IJG_INT32 LOCFSERROR; /* be sure calculation temps are big enough */ +#endif + +typedef FSERROR FAR *FSERRPTR; /* pointer to error array (in FAR storage!) */ + + +/* Private subobject */ + +#define MAX_Q_COMPS 4 /* max components I can handle */ + +typedef struct { + struct jpeg_color_quantizer pub; /* public fields */ + + /* Initially allocated colormap is saved here */ + JSAMPARRAY sv_colormap; /* The color map as a 2-D pixel array */ + int sv_actual; /* number of entries in use */ + + JSAMPARRAY colorindex; /* Precomputed mapping for speed */ + /* colorindex[i][j] = index of color closest to pixel value j in component i, + * premultiplied as described above. Since colormap indexes must fit into + * JSAMPLEs, the entries of this array will too. + */ + boolean is_padded; /* is the colorindex padded for odither? */ + + int Ncolors[MAX_Q_COMPS]; /* # of values alloced to each component */ + + /* Variables for ordered dithering */ + int row_index; /* cur row's vertical index in dither matrix */ + ODITHER_MATRIX_PTR odither[MAX_Q_COMPS]; /* one dither array per component */ + + /* Variables for Floyd-Steinberg dithering */ + FSERRPTR fserrors[MAX_Q_COMPS]; /* accumulated errors */ + boolean on_odd_row; /* flag to remember which row we are on */ +} my_cquantizer; + +typedef my_cquantizer * my_cquantize_ptr; + + +/* + * Policy-making subroutines for create_colormap and create_colorindex. + * These routines determine the colormap to be used. The rest of the module + * only assumes that the colormap is orthogonal. + * + * * select_ncolors decides how to divvy up the available colors + * among the components. + * * output_value defines the set of representative values for a component. + * * largest_input_value defines the mapping from input values to + * representative values for a component. + * Note that the latter two routines may impose different policies for + * different components, though this is not currently done. + */ + + +LOCAL(int) +select_ncolors (j_decompress_ptr cinfo, int Ncolors[]) +/* Determine allocation of desired colors to components, */ +/* and fill in Ncolors[] array to indicate choice. */ +/* Return value is total number of colors (product of Ncolors[] values). */ +{ + int nc = cinfo->out_color_components; /* number of color components */ + int max_colors = cinfo->desired_number_of_colors; + int total_colors, iroot, i, j; + boolean changed; + long temp; + static const int RGB_order[3] = { RGB_GREEN, RGB_RED, RGB_BLUE }; + + /* We can allocate at least the nc'th root of max_colors per component. */ + /* Compute floor(nc'th root of max_colors). */ + iroot = 1; + do { + iroot++; + temp = iroot; /* set temp = iroot ** nc */ + for (i = 1; i < nc; i++) + temp *= iroot; + } while (temp <= (long) max_colors); /* repeat till iroot exceeds root */ + iroot--; /* now iroot = floor(root) */ + + /* Must have at least 2 color values per component */ + if (iroot < 2) + ERREXIT1(cinfo, JERR_QUANT_FEW_COLORS, (int) temp); + + /* Initialize to iroot color values for each component */ + total_colors = 1; + for (i = 0; i < nc; i++) { + Ncolors[i] = iroot; + total_colors *= iroot; + } + /* We may be able to increment the count for one or more components without + * exceeding max_colors, though we know not all can be incremented. + * Sometimes, the first component can be incremented more than once! + * (Example: for 16 colors, we start at 2*2*2, go to 3*2*2, then 4*2*2.) + * In RGB colorspace, try to increment G first, then R, then B. + */ + do { + changed = FALSE; + for (i = 0; i < nc; i++) { + j = (cinfo->out_color_space == JCS_RGB ? RGB_order[i] : i); + /* calculate new total_colors if Ncolors[j] is incremented */ + temp = total_colors / Ncolors[j]; + temp *= Ncolors[j]+1; /* done in long arith to avoid oflo */ + if (temp > (long) max_colors) + break; /* won't fit, done with this pass */ + Ncolors[j]++; /* OK, apply the increment */ + total_colors = (int) temp; + changed = TRUE; + } + } while (changed); + + return total_colors; +} + + +LOCAL(int) +output_value (j_decompress_ptr cinfo, int ci, int j, int maxj) +/* Return j'th output value, where j will range from 0 to maxj */ +/* The output values must fall in 0..MAXJSAMPLE in increasing order */ +{ + /* We always provide values 0 and MAXJSAMPLE for each component; + * any additional values are equally spaced between these limits. + * (Forcing the upper and lower values to the limits ensures that + * dithering can't produce a color outside the selected gamut.) + */ + return (int) (((IJG_INT32) j * MAXJSAMPLE + maxj/2) / maxj); +} + + +LOCAL(int) +largest_input_value (j_decompress_ptr cinfo, int ci, int j, int maxj) +/* Return largest input value that should map to j'th output value */ +/* Must have largest(j=0) >= 0, and largest(j=maxj) >= MAXJSAMPLE */ +{ + /* Breakpoints are halfway between values returned by output_value */ + return (int) (((IJG_INT32) (2*j + 1) * MAXJSAMPLE + maxj) / (2*maxj)); +} + + +/* + * Create the colormap. + */ + +LOCAL(void) +create_colormap (j_decompress_ptr cinfo) +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + JSAMPARRAY colormap; /* Created colormap */ + int total_colors; /* Number of distinct output colors */ + int i,j,k, nci, blksize, blkdist, ptr, val; + + /* Select number of colors for each component */ + total_colors = select_ncolors(cinfo, cquantize->Ncolors); + + /* Report selected color counts */ + if (cinfo->out_color_components == 3) + TRACEMS4(cinfo, 1, JTRC_QUANT_3_NCOLORS, + total_colors, cquantize->Ncolors[0], + cquantize->Ncolors[1], cquantize->Ncolors[2]); + else + TRACEMS1(cinfo, 1, JTRC_QUANT_NCOLORS, total_colors); + + /* Allocate and fill in the colormap. */ + /* The colors are ordered in the map in standard row-major order, */ + /* i.e. rightmost (highest-indexed) color changes most rapidly. */ + + colormap = (*cinfo->mem->alloc_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + (JDIMENSION) total_colors, (JDIMENSION) cinfo->out_color_components); + + /* blksize is number of adjacent repeated entries for a component */ + /* blkdist is distance between groups of identical entries for a component */ + blkdist = total_colors; + + for (i = 0; i < cinfo->out_color_components; i++) { + /* fill in colormap entries for i'th color component */ + nci = cquantize->Ncolors[i]; /* # of distinct values for this color */ + blksize = blkdist / nci; + for (j = 0; j < nci; j++) { + /* Compute j'th output value (out of nci) for component */ + val = output_value(cinfo, i, j, nci-1); + /* Fill in all colormap entries that have this value of this component */ + for (ptr = j * blksize; ptr < total_colors; ptr += blkdist) { + /* fill in blksize entries beginning at ptr */ + for (k = 0; k < blksize; k++) + colormap[i][ptr+k] = (JSAMPLE) val; + } + } + blkdist = blksize; /* blksize of this color is blkdist of next */ + } + + /* Save the colormap in private storage, + * where it will survive color quantization mode changes. + */ + cquantize->sv_colormap = colormap; + cquantize->sv_actual = total_colors; +} + + +/* + * Create the color index table. + */ + +LOCAL(void) +create_colorindex (j_decompress_ptr cinfo) +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + JSAMPROW indexptr; + int i,j,k, nci, blksize, val, pad; + + /* For ordered dither, we pad the color index tables by MAXJSAMPLE in + * each direction (input index values can be -MAXJSAMPLE .. 2*MAXJSAMPLE). + * This is not necessary in the other dithering modes. However, we + * flag whether it was done in case user changes dithering mode. + */ + if (cinfo->dither_mode == JDITHER_ORDERED) { + pad = MAXJSAMPLE*2; + cquantize->is_padded = TRUE; + } else { + pad = 0; + cquantize->is_padded = FALSE; + } + + cquantize->colorindex = (*cinfo->mem->alloc_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + (JDIMENSION) (MAXJSAMPLE+1 + pad), + (JDIMENSION) cinfo->out_color_components); + + /* blksize is number of adjacent repeated entries for a component */ + blksize = cquantize->sv_actual; + + for (i = 0; i < cinfo->out_color_components; i++) { + /* fill in colorindex entries for i'th color component */ + nci = cquantize->Ncolors[i]; /* # of distinct values for this color */ + blksize = blksize / nci; + + /* adjust colorindex pointers to provide padding at negative indexes. */ + if (pad) + cquantize->colorindex[i] += MAXJSAMPLE; + + /* in loop, val = index of current output value, */ + /* and k = largest j that maps to current val */ + indexptr = cquantize->colorindex[i]; + val = 0; + k = largest_input_value(cinfo, i, 0, nci-1); + for (j = 0; j <= MAXJSAMPLE; j++) { + while (j > k) /* advance val if past boundary */ + k = largest_input_value(cinfo, i, ++val, nci-1); + /* premultiply so that no multiplication needed in main processing */ + indexptr[j] = (JSAMPLE) (val * blksize); + } + /* Pad at both ends if necessary */ + if (pad) + for (j = 1; j <= MAXJSAMPLE; j++) { + indexptr[-j] = indexptr[0]; + indexptr[MAXJSAMPLE+j] = indexptr[MAXJSAMPLE]; + } + } +} + + +/* + * Create an ordered-dither array for a component having ncolors + * distinct output values. + */ + +LOCAL(ODITHER_MATRIX_PTR) +make_odither_array (j_decompress_ptr cinfo, int ncolors) +{ + ODITHER_MATRIX_PTR odither; + int j,k; + IJG_INT32 num,den; + + odither = (ODITHER_MATRIX_PTR) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(ODITHER_MATRIX)); + /* The inter-value distance for this color is MAXJSAMPLE/(ncolors-1). + * Hence the dither value for the matrix cell with fill order f + * (f=0..N-1) should be (N-1-2*f)/(2*N) * MAXJSAMPLE/(ncolors-1). + * On 16-bit-int machine, be careful to avoid overflow. + */ + den = 2 * ODITHER_CELLS * ((IJG_INT32) (ncolors - 1)); + for (j = 0; j < ODITHER_SIZE; j++) { + for (k = 0; k < ODITHER_SIZE; k++) { + num = ((IJG_INT32) (ODITHER_CELLS-1 - 2*((int)base_dither_matrix[j][k]))) + * MAXJSAMPLE; + /* Ensure round towards zero despite C's lack of consistency + * about rounding negative values in integer division... + */ + odither[j][k] = (int) (num<0 ? -((-num)/den) : num/den); + } + } + return odither; +} + + +/* + * Create the ordered-dither tables. + * Components having the same number of representative colors may + * share a dither table. + */ + +LOCAL(void) +create_odither_tables (j_decompress_ptr cinfo) +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + ODITHER_MATRIX_PTR odither; + int i, j, nci; + + for (i = 0; i < cinfo->out_color_components; i++) { + nci = cquantize->Ncolors[i]; /* # of distinct values for this color */ + odither = NULL; /* search for matching prior component */ + for (j = 0; j < i; j++) { + if (nci == cquantize->Ncolors[j]) { + odither = cquantize->odither[j]; + break; + } + } + if (odither == NULL) /* need a new table? */ + odither = make_odither_array(cinfo, nci); + cquantize->odither[i] = odither; + } +} + + +/* + * Map some rows of pixels to the output colormapped representation. + */ + +METHODDEF(void) +color_quantize (j_decompress_ptr cinfo, JSAMPARRAY input_buf, + JSAMPARRAY output_buf, int num_rows) +/* General case, no dithering */ +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + JSAMPARRAY colorindex = cquantize->colorindex; + register int pixcode, ci; + register JSAMPROW ptrin, ptrout; + int row; + JDIMENSION col; + JDIMENSION width = cinfo->output_width; + register int nc = cinfo->out_color_components; + + for (row = 0; row < num_rows; row++) { + ptrin = input_buf[row]; + ptrout = output_buf[row]; + for (col = width; col > 0; col--) { + pixcode = 0; + for (ci = 0; ci < nc; ci++) { + pixcode += GETJSAMPLE(colorindex[ci][GETJSAMPLE(*ptrin++)]); + } + *ptrout++ = (JSAMPLE) pixcode; + } + } +} + + +METHODDEF(void) +color_quantize3 (j_decompress_ptr cinfo, JSAMPARRAY input_buf, + JSAMPARRAY output_buf, int num_rows) +/* Fast path for out_color_components==3, no dithering */ +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + register int pixcode; + register JSAMPROW ptrin, ptrout; + JSAMPROW colorindex0 = cquantize->colorindex[0]; + JSAMPROW colorindex1 = cquantize->colorindex[1]; + JSAMPROW colorindex2 = cquantize->colorindex[2]; + int row; + JDIMENSION col; + JDIMENSION width = cinfo->output_width; + + for (row = 0; row < num_rows; row++) { + ptrin = input_buf[row]; + ptrout = output_buf[row]; + for (col = width; col > 0; col--) { + pixcode = GETJSAMPLE(colorindex0[GETJSAMPLE(*ptrin++)]); + pixcode += GETJSAMPLE(colorindex1[GETJSAMPLE(*ptrin++)]); + pixcode += GETJSAMPLE(colorindex2[GETJSAMPLE(*ptrin++)]); + *ptrout++ = (JSAMPLE) pixcode; + } + } +} + + +METHODDEF(void) +quantize_ord_dither (j_decompress_ptr cinfo, JSAMPARRAY input_buf, + JSAMPARRAY output_buf, int num_rows) +/* General case, with ordered dithering */ +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + register JSAMPROW input_ptr; + register JSAMPROW output_ptr; + JSAMPROW colorindex_ci; + int * dither; /* points to active row of dither matrix */ + int row_index, col_index; /* current indexes into dither matrix */ + int nc = cinfo->out_color_components; + int ci; + int row; + JDIMENSION col; + JDIMENSION width = cinfo->output_width; + + for (row = 0; row < num_rows; row++) { + /* Initialize output values to 0 so can process components separately */ + jzero_far((void FAR *) output_buf[row], + (size_t) (width * SIZEOF(JSAMPLE))); + row_index = cquantize->row_index; + for (ci = 0; ci < nc; ci++) { + input_ptr = input_buf[row] + ci; + output_ptr = output_buf[row]; + colorindex_ci = cquantize->colorindex[ci]; + dither = cquantize->odither[ci][row_index]; + col_index = 0; + + for (col = width; col > 0; col--) { + /* Form pixel value + dither, range-limit to 0..MAXJSAMPLE, + * select output value, accumulate into output code for this pixel. + * Range-limiting need not be done explicitly, as we have extended + * the colorindex table to produce the right answers for out-of-range + * inputs. The maximum dither is +- MAXJSAMPLE; this sets the + * required amount of padding. + */ + *output_ptr = (JSAMPLE)(*output_ptr + colorindex_ci[GETJSAMPLE(*input_ptr)+dither[col_index]]); + input_ptr += nc; + output_ptr++; + col_index = (col_index + 1) & ODITHER_MASK; + } + } + /* Advance row index for next row */ + row_index = (row_index + 1) & ODITHER_MASK; + cquantize->row_index = row_index; + } +} + + +METHODDEF(void) +quantize3_ord_dither (j_decompress_ptr cinfo, JSAMPARRAY input_buf, + JSAMPARRAY output_buf, int num_rows) +/* Fast path for out_color_components==3, with ordered dithering */ +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + register int pixcode; + register JSAMPROW input_ptr; + register JSAMPROW output_ptr; + JSAMPROW colorindex0 = cquantize->colorindex[0]; + JSAMPROW colorindex1 = cquantize->colorindex[1]; + JSAMPROW colorindex2 = cquantize->colorindex[2]; + int * dither0; /* points to active row of dither matrix */ + int * dither1; + int * dither2; + int row_index, col_index; /* current indexes into dither matrix */ + int row; + JDIMENSION col; + JDIMENSION width = cinfo->output_width; + + for (row = 0; row < num_rows; row++) { + row_index = cquantize->row_index; + input_ptr = input_buf[row]; + output_ptr = output_buf[row]; + dither0 = cquantize->odither[0][row_index]; + dither1 = cquantize->odither[1][row_index]; + dither2 = cquantize->odither[2][row_index]; + col_index = 0; + + for (col = width; col > 0; col--) { + pixcode = GETJSAMPLE(colorindex0[GETJSAMPLE(*input_ptr++) + + dither0[col_index]]); + pixcode += GETJSAMPLE(colorindex1[GETJSAMPLE(*input_ptr++) + + dither1[col_index]]); + pixcode += GETJSAMPLE(colorindex2[GETJSAMPLE(*input_ptr++) + + dither2[col_index]]); + *output_ptr++ = (JSAMPLE) pixcode; + col_index = (col_index + 1) & ODITHER_MASK; + } + row_index = (row_index + 1) & ODITHER_MASK; + cquantize->row_index = row_index; + } +} + + +METHODDEF(void) +quantize_fs_dither (j_decompress_ptr cinfo, JSAMPARRAY input_buf, + JSAMPARRAY output_buf, int num_rows) +/* General case, with Floyd-Steinberg dithering */ +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + register LOCFSERROR cur; /* current error or pixel value */ + LOCFSERROR belowerr; /* error for pixel below cur */ + LOCFSERROR bpreverr; /* error for below/prev col */ + LOCFSERROR bnexterr; /* error for below/next col */ + LOCFSERROR delta; + register FSERRPTR errorptr; /* => fserrors[] at column before current */ + register JSAMPROW input_ptr; + register JSAMPROW output_ptr; + JSAMPROW colorindex_ci; + JSAMPROW colormap_ci; + int pixcode; + int nc = cinfo->out_color_components; + int dir; /* 1 for left-to-right, -1 for right-to-left */ + int dirnc; /* dir * nc */ + int ci; + int row; + JDIMENSION col; + JDIMENSION width = cinfo->output_width; + JSAMPLE *range_limit = cinfo->sample_range_limit; + SHIFT_TEMPS + + for (row = 0; row < num_rows; row++) { + /* Initialize output values to 0 so can process components separately */ + jzero_far((void FAR *) output_buf[row], + (size_t) (width * SIZEOF(JSAMPLE))); + for (ci = 0; ci < nc; ci++) { + input_ptr = input_buf[row] + ci; + output_ptr = output_buf[row]; + if (cquantize->on_odd_row) { + /* work right to left in this row */ + input_ptr += (width-1) * (JDIMENSION)nc; /* so point to rightmost pixel */ + output_ptr += width-1; + dir = -1; + dirnc = -nc; + errorptr = cquantize->fserrors[ci] + (width+1); /* => entry after last column */ + } else { + /* work left to right in this row */ + dir = 1; + dirnc = nc; + errorptr = cquantize->fserrors[ci]; /* => entry before first column */ + } + colorindex_ci = cquantize->colorindex[ci]; + colormap_ci = cquantize->sv_colormap[ci]; + /* Preset error values: no error propagated to first pixel from left */ + cur = 0; + /* and no error propagated to row below yet */ + belowerr = bpreverr = 0; + + for (col = width; col > 0; col--) { + /* cur holds the error propagated from the previous pixel on the + * current line. Add the error propagated from the previous line + * to form the complete error correction term for this pixel, and + * round the error term (which is expressed * 16) to an integer. + * RIGHT_SHIFT rounds towards minus infinity, so adding 8 is correct + * for either sign of the error value. + * Note: errorptr points to *previous* column's array entry. + */ + cur = RIGHT_SHIFT(cur + errorptr[dir] + 8, 4); + /* Form pixel value + error, and range-limit to 0..MAXJSAMPLE. + * The maximum error is +- MAXJSAMPLE; this sets the required size + * of the range_limit array. + */ + cur += GETJSAMPLE(*input_ptr); + cur = GETJSAMPLE(range_limit[cur]); + /* Select output value, accumulate into output code for this pixel */ + pixcode = GETJSAMPLE(colorindex_ci[cur]); + *output_ptr = (JSAMPLE)(*output_ptr + pixcode); + /* Compute actual representation error at this pixel */ + /* Note: we can do this even though we don't have the final */ + /* pixel code, because the colormap is orthogonal. */ + cur -= GETJSAMPLE(colormap_ci[pixcode]); + /* Compute error fractions to be propagated to adjacent pixels. + * Add these into the running sums, and simultaneously shift the + * next-line error sums left by 1 column. + */ + bnexterr = cur; + delta = cur * 2; + cur += delta; /* form error * 3 */ + errorptr[0] = (FSERROR) (bpreverr + cur); + cur += delta; /* form error * 5 */ + bpreverr = belowerr + cur; + belowerr = bnexterr; + cur += delta; /* form error * 7 */ + /* At this point cur contains the 7/16 error value to be propagated + * to the next pixel on the current line, and all the errors for the + * next line have been shifted over. We are therefore ready to move on. + */ + input_ptr += dirnc; /* advance input ptr to next column */ + output_ptr += dir; /* advance output ptr to next column */ + errorptr += dir; /* advance errorptr to current column */ + } + /* Post-loop cleanup: we must unload the final error value into the + * final fserrors[] entry. Note we need not unload belowerr because + * it is for the dummy column before or after the actual array. + */ + errorptr[0] = (FSERROR) bpreverr; /* unload prev err into array */ + } + cquantize->on_odd_row = (cquantize->on_odd_row ? FALSE : TRUE); + } +} + + +/* + * Allocate workspace for Floyd-Steinberg errors. + */ + +LOCAL(void) +alloc_fs_workspace (j_decompress_ptr cinfo) +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + size_t arraysize; + int i; + + arraysize = (size_t) ((cinfo->output_width + 2) * SIZEOF(FSERROR)); + for (i = 0; i < cinfo->out_color_components; i++) { + cquantize->fserrors[i] = (FSERRPTR) + (*cinfo->mem->alloc_large)((j_common_ptr) cinfo, JPOOL_IMAGE, arraysize); + } +} + + +/* + * Initialize for one-pass color quantization. + */ + +METHODDEF(void) +start_pass_1_quant (j_decompress_ptr cinfo, boolean is_pre_scan) +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + size_t arraysize; + int i; + + /* Install my colormap. */ + cinfo->colormap = cquantize->sv_colormap; + cinfo->actual_number_of_colors = cquantize->sv_actual; + + /* Initialize for desired dithering mode. */ + switch (cinfo->dither_mode) { + case JDITHER_NONE: + if (cinfo->out_color_components == 3) + cquantize->pub.color_quantize = color_quantize3; + else + cquantize->pub.color_quantize = color_quantize; + break; + case JDITHER_ORDERED: + if (cinfo->out_color_components == 3) + cquantize->pub.color_quantize = quantize3_ord_dither; + else + cquantize->pub.color_quantize = quantize_ord_dither; + cquantize->row_index = 0; /* initialize state for ordered dither */ + /* If user changed to ordered dither from another mode, + * we must recreate the color index table with padding. + * This will cost extra space, but probably isn't very likely. + */ + if (! cquantize->is_padded) + create_colorindex(cinfo); + /* Create ordered-dither tables if we didn't already. */ + if (cquantize->odither[0] == NULL) + create_odither_tables(cinfo); + break; + case JDITHER_FS: + cquantize->pub.color_quantize = quantize_fs_dither; + cquantize->on_odd_row = FALSE; /* initialize state for F-S dither */ + /* Allocate Floyd-Steinberg workspace if didn't already. */ + if (cquantize->fserrors[0] == NULL) + alloc_fs_workspace(cinfo); + /* Initialize the propagated errors to zero. */ + arraysize = (size_t) ((cinfo->output_width + 2) * SIZEOF(FSERROR)); + for (i = 0; i < cinfo->out_color_components; i++) + jzero_far((void FAR *) cquantize->fserrors[i], arraysize); + break; + default: + ERREXIT(cinfo, JERR_NOT_COMPILED); + break; + } +} + + +/* + * Finish up at the end of the pass. + */ + +METHODDEF(void) +finish_pass_1_quant (j_decompress_ptr cinfo) +{ + /* no work in 1-pass case */ +} + + +/* + * Switch to a new external colormap between output passes. + * Shouldn't get to this module! + */ + +METHODDEF(void) +new_color_map_1_quant (j_decompress_ptr cinfo) +{ + ERREXIT(cinfo, JERR_MODE_CHANGE); +} + + +/* + * Module initialization routine for 1-pass color quantization. + */ + +GLOBAL(void) +jinit_1pass_quantizer (j_decompress_ptr cinfo) +{ + my_cquantize_ptr cquantize; + + cquantize = (my_cquantize_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_cquantizer)); + cinfo->cquantize = (struct jpeg_color_quantizer *) cquantize; + cquantize->pub.start_pass = start_pass_1_quant; + cquantize->pub.finish_pass = finish_pass_1_quant; + cquantize->pub.new_color_map = new_color_map_1_quant; + cquantize->fserrors[0] = NULL; /* Flag FS workspace not allocated */ + cquantize->odither[0] = NULL; /* Also flag odither arrays not allocated */ + + /* Make sure my internal arrays won't overflow */ + if (cinfo->out_color_components > MAX_Q_COMPS) + ERREXIT1(cinfo, JERR_QUANT_COMPONENTS, MAX_Q_COMPS); + /* Make sure colormap indexes can be represented by JSAMPLEs */ + if (cinfo->desired_number_of_colors > (MAXJSAMPLE+1)) + ERREXIT1(cinfo, JERR_QUANT_MANY_COLORS, MAXJSAMPLE+1); + + /* Create the colormap and color index table. */ + create_colormap(cinfo); + create_colorindex(cinfo); + + /* Allocate Floyd-Steinberg workspace now if requested. + * We do this now since it is FAR storage and may affect the memory + * manager's space calculations. If the user changes to FS dither + * mode in a later pass, we will allocate the space then, and will + * possibly overrun the max_memory_to_use setting. + */ + if (cinfo->dither_mode == JDITHER_FS) + alloc_fs_workspace(cinfo); +} + +#endif /* QUANT_1PASS_SUPPORTED */ diff --git a/dcmjpeg/libijg8/jquant2.c b/dcmjpeg/libijg8/jquant2.c new file mode 100644 index 00000000..aacc2740 --- /dev/null +++ b/dcmjpeg/libijg8/jquant2.c @@ -0,0 +1,1310 @@ +/* + * jquant2.c + * + * Copyright (C) 1991-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains 2-pass color quantization (color mapping) routines. + * These routines provide selection of a custom color map for an image, + * followed by mapping of the image to that color map, with optional + * Floyd-Steinberg dithering. + * It is also possible to use just the second pass to map to an arbitrary + * externally-given color map. + * + * Note: ordered dithering is not supported, since there isn't any fast + * way to compute intercolor distances; it's unclear that ordered dither's + * fundamental assumptions even hold with an irregularly spaced color map. + */ + +#define JPEG_INTERNALS +#include "jinclude8.h" +#include "jpeglib8.h" + +#ifdef QUANT_2PASS_SUPPORTED + + +/* + * This module implements the well-known Heckbert paradigm for color + * quantization. Most of the ideas used here can be traced back to + * Heckbert's seminal paper + * Heckbert, Paul. "Color Image Quantization for Frame Buffer Display", + * Proc. SIGGRAPH '82, Computer Graphics v.16 #3 (July 1982), pp 297-304. + * + * In the first pass over the image, we accumulate a histogram showing the + * usage count of each possible color. To keep the histogram to a reasonable + * size, we reduce the precision of the input; typical practice is to retain + * 5 or 6 bits per color, so that 8 or 4 different input values are counted + * in the same histogram cell. + * + * Next, the color-selection step begins with a box representing the whole + * color space, and repeatedly splits the "largest" remaining box until we + * have as many boxes as desired colors. Then the mean color in each + * remaining box becomes one of the possible output colors. + * + * The second pass over the image maps each input pixel to the closest output + * color (optionally after applying a Floyd-Steinberg dithering correction). + * This mapping is logically trivial, but making it go fast enough requires + * considerable care. + * + * Heckbert-style quantizers vary a good deal in their policies for choosing + * the "largest" box and deciding where to cut it. The particular policies + * used here have proved out well in experimental comparisons, but better ones + * may yet be found. + * + * In earlier versions of the IJG code, this module quantized in YCbCr color + * space, processing the raw upsampled data without a color conversion step. + * This allowed the color conversion math to be done only once per colormap + * entry, not once per pixel. However, that optimization precluded other + * useful optimizations (such as merging color conversion with upsampling) + * and it also interfered with desired capabilities such as quantizing to an + * externally-supplied colormap. We have therefore abandoned that approach. + * The present code works in the post-conversion color space, typically RGB. + * + * To improve the visual quality of the results, we actually work in scaled + * RGB space, giving G distances more weight than R, and R in turn more than + * B. To do everything in integer math, we must use integer scale factors. + * The 2/3/1 scale factors used here correspond loosely to the relative + * weights of the colors in the NTSC grayscale equation. + * If you want to use this code to quantize a non-RGB color space, you'll + * probably need to change these scale factors. + */ + +#define R_SCALE 2 /* scale R distances by this much */ +#define G_SCALE 3 /* scale G distances by this much */ +#define B_SCALE 1 /* and B by this much */ + +/* Relabel R/G/B as components 0/1/2, respecting the RGB ordering defined + * in jmorecfg.h. As the code stands, it will do the right thing for R,G,B + * and B,G,R orders. If you define some other weird order in jmorecfg.h, + * you'll get compile errors until you extend this logic. In that case + * you'll probably want to tweak the histogram sizes too. + */ + +#if RGB_RED == 0 +#define C0_SCALE R_SCALE +#endif +#if RGB_BLUE == 0 +#define C0_SCALE B_SCALE +#endif +#if RGB_GREEN == 1 +#define C1_SCALE G_SCALE +#endif +#if RGB_RED == 2 +#define C2_SCALE R_SCALE +#endif +#if RGB_BLUE == 2 +#define C2_SCALE B_SCALE +#endif + + +/* + * First we have the histogram data structure and routines for creating it. + * + * The number of bits of precision can be adjusted by changing these symbols. + * We recommend keeping 6 bits for G and 5 each for R and B. + * If you have plenty of memory and cycles, 6 bits all around gives marginally + * better results; if you are short of memory, 5 bits all around will save + * some space but degrade the results. + * To maintain a fully accurate histogram, we'd need to allocate a "long" + * (preferably unsigned long) for each cell. In practice this is overkill; + * we can get by with 16 bits per cell. Few of the cell counts will overflow, + * and clamping those that do overflow to the maximum value will give close- + * enough results. This reduces the recommended histogram size from 256Kb + * to 128Kb, which is a useful savings on PC-class machines. + * (In the second pass the histogram space is re-used for pixel mapping data; + * in that capacity, each cell must be able to store zero to the number of + * desired colors. 16 bits/cell is plenty for that too.) + * Since the JPEG code is intended to run in small memory model on 80x86 + * machines, we can't just allocate the histogram in one chunk. Instead + * of a true 3-D array, we use a row of pointers to 2-D arrays. Each + * pointer corresponds to a C0 value (typically 2^5 = 32 pointers) and + * each 2-D array has 2^6*2^5 = 2048 or 2^6*2^6 = 4096 entries. Note that + * on 80x86 machines, the pointer row is in near memory but the actual + * arrays are in far memory (same arrangement as we use for image arrays). + */ + +#define MAXNUMCOLORS (MAXJSAMPLE+1) /* maximum size of colormap */ + +/* These will do the right thing for either R,G,B or B,G,R color order, + * but you may not like the results for other color orders. + */ +#define HIST_C0_BITS 5 /* bits of precision in R/B histogram */ +#define HIST_C1_BITS 6 /* bits of precision in G histogram */ +#define HIST_C2_BITS 5 /* bits of precision in B/R histogram */ + +/* Number of elements along histogram axes. */ +#define HIST_C0_ELEMS (1<cquantize; + register JSAMPROW ptr; + register histptr histp; + register hist3d histogram = cquantize->histogram; + int row; + JDIMENSION col; + JDIMENSION width = cinfo->output_width; + + for (row = 0; row < num_rows; row++) { + ptr = input_buf[row]; + for (col = width; col > 0; col--) { + /* get pixel value and index into the histogram */ + histp = & histogram[GETJSAMPLE(ptr[0]) >> C0_SHIFT] + [GETJSAMPLE(ptr[1]) >> C1_SHIFT] + [GETJSAMPLE(ptr[2]) >> C2_SHIFT]; + /* increment, check for overflow and undo increment if so. */ + if (++(*histp) <= 0) + (*histp)--; + ptr += 3; + } + } +} + + +/* + * Next we have the really interesting routines: selection of a colormap + * given the completed histogram. + * These routines work with a list of "boxes", each representing a rectangular + * subset of the input color space (to histogram precision). + */ + +typedef struct { + /* The bounds of the box (inclusive); expressed as histogram indexes */ + int c0min, c0max; + int c1min, c1max; + int c2min, c2max; + /* The volume (actually 2-norm) of the box */ + IJG_INT32 volume; + /* The number of nonzero histogram cells within this box */ + long colorcount; +} box; + +typedef box * boxptr; + + +LOCAL(boxptr) +find_biggest_color_pop (boxptr boxlist, int numboxes) +/* Find the splittable box with the largest color population */ +/* Returns NULL if no splittable boxes remain */ +{ + register boxptr boxp; + register int i; + register long maxc = 0; + boxptr which = NULL; + + for (i = 0, boxp = boxlist; i < numboxes; i++, boxp++) { + if (boxp->colorcount > maxc && boxp->volume > 0) { + which = boxp; + maxc = boxp->colorcount; + } + } + return which; +} + + +LOCAL(boxptr) +find_biggest_volume (boxptr boxlist, int numboxes) +/* Find the splittable box with the largest (scaled) volume */ +/* Returns NULL if no splittable boxes remain */ +{ + register boxptr boxp; + register int i; + register IJG_INT32 maxv = 0; + boxptr which = NULL; + + for (i = 0, boxp = boxlist; i < numboxes; i++, boxp++) { + if (boxp->volume > maxv) { + which = boxp; + maxv = boxp->volume; + } + } + return which; +} + + +LOCAL(void) +update_box (j_decompress_ptr cinfo, boxptr boxp) +/* Shrink the min/max bounds of a box to enclose only nonzero elements, */ +/* and recompute its volume and population */ +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + hist3d histogram = cquantize->histogram; + histptr histp; + int c0,c1,c2; + int c0min,c0max,c1min,c1max,c2min,c2max; + IJG_INT32 dist0,dist1,dist2; + long ccount; + + c0min = boxp->c0min; c0max = boxp->c0max; + c1min = boxp->c1min; c1max = boxp->c1max; + c2min = boxp->c2min; c2max = boxp->c2max; + + if (c0max > c0min) + for (c0 = c0min; c0 <= c0max; c0++) + for (c1 = c1min; c1 <= c1max; c1++) { + histp = & histogram[c0][c1][c2min]; + for (c2 = c2min; c2 <= c2max; c2++) + if (*histp++ != 0) { + boxp->c0min = c0min = c0; + goto have_c0min; + } + } + have_c0min: + if (c0max > c0min) + for (c0 = c0max; c0 >= c0min; c0--) + for (c1 = c1min; c1 <= c1max; c1++) { + histp = & histogram[c0][c1][c2min]; + for (c2 = c2min; c2 <= c2max; c2++) + if (*histp++ != 0) { + boxp->c0max = c0max = c0; + goto have_c0max; + } + } + have_c0max: + if (c1max > c1min) + for (c1 = c1min; c1 <= c1max; c1++) + for (c0 = c0min; c0 <= c0max; c0++) { + histp = & histogram[c0][c1][c2min]; + for (c2 = c2min; c2 <= c2max; c2++) + if (*histp++ != 0) { + boxp->c1min = c1min = c1; + goto have_c1min; + } + } + have_c1min: + if (c1max > c1min) + for (c1 = c1max; c1 >= c1min; c1--) + for (c0 = c0min; c0 <= c0max; c0++) { + histp = & histogram[c0][c1][c2min]; + for (c2 = c2min; c2 <= c2max; c2++) + if (*histp++ != 0) { + boxp->c1max = c1max = c1; + goto have_c1max; + } + } + have_c1max: + if (c2max > c2min) + for (c2 = c2min; c2 <= c2max; c2++) + for (c0 = c0min; c0 <= c0max; c0++) { + histp = & histogram[c0][c1min][c2]; + for (c1 = c1min; c1 <= c1max; c1++, histp += HIST_C2_ELEMS) + if (*histp != 0) { + boxp->c2min = c2min = c2; + goto have_c2min; + } + } + have_c2min: + if (c2max > c2min) + for (c2 = c2max; c2 >= c2min; c2--) + for (c0 = c0min; c0 <= c0max; c0++) { + histp = & histogram[c0][c1min][c2]; + for (c1 = c1min; c1 <= c1max; c1++, histp += HIST_C2_ELEMS) + if (*histp != 0) { + boxp->c2max = c2max = c2; + goto have_c2max; + } + } + have_c2max: + + /* Update box volume. + * We use 2-norm rather than real volume here; this biases the method + * against making long narrow boxes, and it has the side benefit that + * a box is splittable iff norm > 0. + * Since the differences are expressed in histogram-cell units, + * we have to shift back to JSAMPLE units to get consistent distances; + * after which, we scale according to the selected distance scale factors. + */ + dist0 = ((c0max - c0min) << C0_SHIFT) * C0_SCALE; + dist1 = ((c1max - c1min) << C1_SHIFT) * C1_SCALE; + dist2 = ((c2max - c2min) << C2_SHIFT) * C2_SCALE; + boxp->volume = dist0*dist0 + dist1*dist1 + dist2*dist2; + + /* Now scan remaining volume of box and compute population */ + ccount = 0; + for (c0 = c0min; c0 <= c0max; c0++) + for (c1 = c1min; c1 <= c1max; c1++) { + histp = & histogram[c0][c1][c2min]; + for (c2 = c2min; c2 <= c2max; c2++, histp++) + if (*histp != 0) { + ccount++; + } + } + boxp->colorcount = ccount; +} + + +LOCAL(int) +median_cut (j_decompress_ptr cinfo, boxptr boxlist, int numboxes, + int desired_colors) +/* Repeatedly select and split the largest box until we have enough boxes */ +{ + int n,lb; + int c0,c1,c2,cmax; + register boxptr b1,b2; + + while (numboxes < desired_colors) { + /* Select box to split. + * Current algorithm: by population for first half, then by volume. + */ + if (numboxes*2 <= desired_colors) { + b1 = find_biggest_color_pop(boxlist, numboxes); + } else { + b1 = find_biggest_volume(boxlist, numboxes); + } + if (b1 == NULL) /* no splittable boxes left! */ + break; + b2 = &boxlist[numboxes]; /* where new box will go */ + /* Copy the color bounds to the new box. */ + b2->c0max = b1->c0max; b2->c1max = b1->c1max; b2->c2max = b1->c2max; + b2->c0min = b1->c0min; b2->c1min = b1->c1min; b2->c2min = b1->c2min; + /* Choose which axis to split the box on. + * Current algorithm: longest scaled axis. + * See notes in update_box about scaling distances. + */ + c0 = ((b1->c0max - b1->c0min) << C0_SHIFT) * C0_SCALE; + c1 = ((b1->c1max - b1->c1min) << C1_SHIFT) * C1_SCALE; + c2 = ((b1->c2max - b1->c2min) << C2_SHIFT) * C2_SCALE; + /* We want to break any ties in favor of green, then red, blue last. + * This code does the right thing for R,G,B or B,G,R color orders only. + */ +#if RGB_RED == 0 + cmax = c1; n = 1; + if (c0 > cmax) { cmax = c0; n = 0; } + if (c2 > cmax) { n = 2; } +#else + cmax = c1; n = 1; + if (c2 > cmax) { cmax = c2; n = 2; } + if (c0 > cmax) { n = 0; } +#endif + /* Choose split point along selected axis, and update box bounds. + * Current algorithm: split at halfway point. + * (Since the box has been shrunk to minimum volume, + * any split will produce two nonempty subboxes.) + * Note that lb value is max for lower box, so must be < old max. + */ + switch (n) { + case 0: + lb = (b1->c0max + b1->c0min) / 2; + b1->c0max = lb; + b2->c0min = lb+1; + break; + case 1: + lb = (b1->c1max + b1->c1min) / 2; + b1->c1max = lb; + b2->c1min = lb+1; + break; + case 2: + lb = (b1->c2max + b1->c2min) / 2; + b1->c2max = lb; + b2->c2min = lb+1; + break; + } + /* Update stats for boxes */ + update_box(cinfo, b1); + update_box(cinfo, b2); + numboxes++; + } + return numboxes; +} + + +LOCAL(void) +compute_color (j_decompress_ptr cinfo, boxptr boxp, int icolor) +/* Compute representative color for a box, put it in colormap[icolor] */ +{ + /* Current algorithm: mean weighted by pixels (not colors) */ + /* Note it is important to get the rounding correct! */ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + hist3d histogram = cquantize->histogram; + histptr histp; + int c0,c1,c2; + int c0min,c0max,c1min,c1max,c2min,c2max; + long count; + long total = 0; + long c0total = 0; + long c1total = 0; + long c2total = 0; + + c0min = boxp->c0min; c0max = boxp->c0max; + c1min = boxp->c1min; c1max = boxp->c1max; + c2min = boxp->c2min; c2max = boxp->c2max; + + for (c0 = c0min; c0 <= c0max; c0++) + for (c1 = c1min; c1 <= c1max; c1++) { + histp = & histogram[c0][c1][c2min]; + for (c2 = c2min; c2 <= c2max; c2++) { + if ((count = *histp++) != 0) { + total += count; + c0total += ((c0 << C0_SHIFT) + ((1<>1)) * count; + c1total += ((c1 << C1_SHIFT) + ((1<>1)) * count; + c2total += ((c2 << C2_SHIFT) + ((1<>1)) * count; + } + } + } + + cinfo->colormap[0][icolor] = (JSAMPLE) ((c0total + (total>>1)) / total); + cinfo->colormap[1][icolor] = (JSAMPLE) ((c1total + (total>>1)) / total); + cinfo->colormap[2][icolor] = (JSAMPLE) ((c2total + (total>>1)) / total); +} + + +LOCAL(void) +select_colors (j_decompress_ptr cinfo, int desired_colors) +/* Master routine for color selection */ +{ + boxptr boxlist; + int numboxes; + int i; + + /* Allocate workspace for box list */ + boxlist = (boxptr) (*cinfo->mem->alloc_small) + ((j_common_ptr) cinfo, JPOOL_IMAGE, (size_t)desired_colors * SIZEOF(box)); + /* Initialize one box containing whole space */ + numboxes = 1; + boxlist[0].c0min = 0; + boxlist[0].c0max = MAXJSAMPLE >> C0_SHIFT; + boxlist[0].c1min = 0; + boxlist[0].c1max = MAXJSAMPLE >> C1_SHIFT; + boxlist[0].c2min = 0; + boxlist[0].c2max = MAXJSAMPLE >> C2_SHIFT; + /* Shrink it to actually-used volume and set its statistics */ + update_box(cinfo, & boxlist[0]); + /* Perform median-cut to produce final box list */ + numboxes = median_cut(cinfo, boxlist, numboxes, desired_colors); + /* Compute the representative color for each box, fill colormap */ + for (i = 0; i < numboxes; i++) + compute_color(cinfo, & boxlist[i], i); + cinfo->actual_number_of_colors = numboxes; + TRACEMS1(cinfo, 1, JTRC_QUANT_SELECTED, numboxes); +} + + +/* + * These routines are concerned with the time-critical task of mapping input + * colors to the nearest color in the selected colormap. + * + * We re-use the histogram space as an "inverse color map", essentially a + * cache for the results of nearest-color searches. All colors within a + * histogram cell will be mapped to the same colormap entry, namely the one + * closest to the cell's center. This may not be quite the closest entry to + * the actual input color, but it's almost as good. A zero in the cache + * indicates we haven't found the nearest color for that cell yet; the array + * is cleared to zeroes before starting the mapping pass. When we find the + * nearest color for a cell, its colormap index plus one is recorded in the + * cache for future use. The pass2 scanning routines call fill_inverse_cmap + * when they need to use an unfilled entry in the cache. + * + * Our method of efficiently finding nearest colors is based on the "locally + * sorted search" idea described by Heckbert and on the incremental distance + * calculation described by Spencer W. Thomas in chapter III.1 of Graphics + * Gems II (James Arvo, ed. Academic Press, 1991). Thomas points out that + * the distances from a given colormap entry to each cell of the histogram can + * be computed quickly using an incremental method: the differences between + * distances to adjacent cells themselves differ by a constant. This allows a + * fairly fast implementation of the "brute force" approach of computing the + * distance from every colormap entry to every histogram cell. Unfortunately, + * it needs a work array to hold the best-distance-so-far for each histogram + * cell (because the inner loop has to be over cells, not colormap entries). + * The work array elements have to be IJG_INT32s, so the work array would need + * 256Kb at our recommended precision. This is not feasible in DOS machines. + * + * To get around these problems, we apply Thomas' method to compute the + * nearest colors for only the cells within a small subbox of the histogram. + * The work array need be only as big as the subbox, so the memory usage + * problem is solved. Furthermore, we need not fill subboxes that are never + * referenced in pass2; many images use only part of the color gamut, so a + * fair amount of work is saved. An additional advantage of this + * approach is that we can apply Heckbert's locality criterion to quickly + * eliminate colormap entries that are far away from the subbox; typically + * three-fourths of the colormap entries are rejected by Heckbert's criterion, + * and we need not compute their distances to individual cells in the subbox. + * The speed of this approach is heavily influenced by the subbox size: too + * small means too much overhead, too big loses because Heckbert's criterion + * can't eliminate as many colormap entries. Empirically the best subbox + * size seems to be about 1/512th of the histogram (1/8th in each direction). + * + * Thomas' article also describes a refined method which is asymptotically + * faster than the brute-force method, but it is also far more complex and + * cannot efficiently be applied to small subboxes. It is therefore not + * useful for programs intended to be portable to DOS machines. On machines + * with plenty of memory, filling the whole histogram in one shot with Thomas' + * refined method might be faster than the present code --- but then again, + * it might not be any faster, and it's certainly more complicated. + */ + + +/* log2(histogram cells in update box) for each axis; this can be adjusted */ +#define BOX_C0_LOG (HIST_C0_BITS-3) +#define BOX_C1_LOG (HIST_C1_BITS-3) +#define BOX_C2_LOG (HIST_C2_BITS-3) + +#define BOX_C0_ELEMS (1<actual_number_of_colors; + int maxc0, maxc1, maxc2; + int centerc0, centerc1, centerc2; + int i, x, ncolors; + IJG_INT32 minmaxdist, min_dist, max_dist, tdist; + IJG_INT32 mindist[MAXNUMCOLORS]; /* min distance to colormap entry i */ + + /* Compute true coordinates of update box's upper corner and center. + * Actually we compute the coordinates of the center of the upper-corner + * histogram cell, which are the upper bounds of the volume we care about. + * Note that since ">>" rounds down, the "center" values may be closer to + * min than to max; hence comparisons to them must be "<=", not "<". + */ + maxc0 = minc0 + ((1 << BOX_C0_SHIFT) - (1 << C0_SHIFT)); + centerc0 = (minc0 + maxc0) >> 1; + maxc1 = minc1 + ((1 << BOX_C1_SHIFT) - (1 << C1_SHIFT)); + centerc1 = (minc1 + maxc1) >> 1; + maxc2 = minc2 + ((1 << BOX_C2_SHIFT) - (1 << C2_SHIFT)); + centerc2 = (minc2 + maxc2) >> 1; + + /* For each color in colormap, find: + * 1. its minimum squared-distance to any point in the update box + * (zero if color is within update box); + * 2. its maximum squared-distance to any point in the update box. + * Both of these can be found by considering only the corners of the box. + * We save the minimum distance for each color in mindist[]; + * only the smallest maximum distance is of interest. + */ + minmaxdist = 0x7FFFFFFFL; + + for (i = 0; i < numcolors; i++) { + /* We compute the squared-c0-distance term, then add in the other two. */ + x = GETJSAMPLE(cinfo->colormap[0][i]); + if (x < minc0) { + tdist = (x - minc0) * C0_SCALE; + min_dist = tdist*tdist; + tdist = (x - maxc0) * C0_SCALE; + max_dist = tdist*tdist; + } else if (x > maxc0) { + tdist = (x - maxc0) * C0_SCALE; + min_dist = tdist*tdist; + tdist = (x - minc0) * C0_SCALE; + max_dist = tdist*tdist; + } else { + /* within cell range so no contribution to min_dist */ + min_dist = 0; + if (x <= centerc0) { + tdist = (x - maxc0) * C0_SCALE; + max_dist = tdist*tdist; + } else { + tdist = (x - minc0) * C0_SCALE; + max_dist = tdist*tdist; + } + } + + x = GETJSAMPLE(cinfo->colormap[1][i]); + if (x < minc1) { + tdist = (x - minc1) * C1_SCALE; + min_dist += tdist*tdist; + tdist = (x - maxc1) * C1_SCALE; + max_dist += tdist*tdist; + } else if (x > maxc1) { + tdist = (x - maxc1) * C1_SCALE; + min_dist += tdist*tdist; + tdist = (x - minc1) * C1_SCALE; + max_dist += tdist*tdist; + } else { + /* within cell range so no contribution to min_dist */ + if (x <= centerc1) { + tdist = (x - maxc1) * C1_SCALE; + max_dist += tdist*tdist; + } else { + tdist = (x - minc1) * C1_SCALE; + max_dist += tdist*tdist; + } + } + + x = GETJSAMPLE(cinfo->colormap[2][i]); + if (x < minc2) { + tdist = (x - minc2) * C2_SCALE; + min_dist += tdist*tdist; + tdist = (x - maxc2) * C2_SCALE; + max_dist += tdist*tdist; + } else if (x > maxc2) { + tdist = (x - maxc2) * C2_SCALE; + min_dist += tdist*tdist; + tdist = (x - minc2) * C2_SCALE; + max_dist += tdist*tdist; + } else { + /* within cell range so no contribution to min_dist */ + if (x <= centerc2) { + tdist = (x - maxc2) * C2_SCALE; + max_dist += tdist*tdist; + } else { + tdist = (x - minc2) * C2_SCALE; + max_dist += tdist*tdist; + } + } + + mindist[i] = min_dist; /* save away the results */ + if (max_dist < minmaxdist) + minmaxdist = max_dist; + } + + /* Now we know that no cell in the update box is more than minmaxdist + * away from some colormap entry. Therefore, only colors that are + * within minmaxdist of some part of the box need be considered. + */ + ncolors = 0; + for (i = 0; i < numcolors; i++) { + if (mindist[i] <= minmaxdist) + colorlist[ncolors++] = (JSAMPLE) i; + } + return ncolors; +} + + +LOCAL(void) +find_best_colors (j_decompress_ptr cinfo, int minc0, int minc1, int minc2, + int numcolors, JSAMPLE colorlist[], JSAMPLE bestcolor[]) +/* Find the closest colormap entry for each cell in the update box, + * given the list of candidate colors prepared by find_nearby_colors. + * Return the indexes of the closest entries in the bestcolor[] array. + * This routine uses Thomas' incremental distance calculation method to + * find the distance from a colormap entry to successive cells in the box. + */ +{ + int ic0, ic1, ic2; + int i, icolor; + register IJG_INT32 * bptr; /* pointer into bestdist[] array */ + JSAMPLE * cptr; /* pointer into bestcolor[] array */ + IJG_INT32 dist0, dist1; /* initial distance values */ + register IJG_INT32 dist2; /* current distance in inner loop */ + IJG_INT32 xx0, xx1; /* distance increments */ + register IJG_INT32 xx2; + IJG_INT32 inc0, inc1, inc2; /* initial values for increments */ + /* This array holds the distance to the nearest-so-far color for each cell */ + IJG_INT32 bestdist[BOX_C0_ELEMS * BOX_C1_ELEMS * BOX_C2_ELEMS]; + + /* Initialize best-distance for each cell of the update box */ + bptr = bestdist; + for (i = BOX_C0_ELEMS*BOX_C1_ELEMS*BOX_C2_ELEMS-1; i >= 0; i--) + *bptr++ = 0x7FFFFFFFL; + + /* For each color selected by find_nearby_colors, + * compute its distance to the center of each cell in the box. + * If that's less than best-so-far, update best distance and color number. + */ + + /* Nominal steps between cell centers ("x" in Thomas article) */ +#define STEP_C0 ((1 << C0_SHIFT) * C0_SCALE) +#define STEP_C1 ((1 << C1_SHIFT) * C1_SCALE) +#define STEP_C2 ((1 << C2_SHIFT) * C2_SCALE) + + for (i = 0; i < numcolors; i++) { + icolor = GETJSAMPLE(colorlist[i]); + /* Compute (square of) distance from minc0/c1/c2 to this color */ + inc0 = (minc0 - GETJSAMPLE(cinfo->colormap[0][icolor])) * C0_SCALE; + dist0 = inc0*inc0; + inc1 = (minc1 - GETJSAMPLE(cinfo->colormap[1][icolor])) * C1_SCALE; + dist0 += inc1*inc1; + inc2 = (minc2 - GETJSAMPLE(cinfo->colormap[2][icolor])) * C2_SCALE; + dist0 += inc2*inc2; + /* Form the initial difference increments */ + inc0 = inc0 * (2 * STEP_C0) + STEP_C0 * STEP_C0; + inc1 = inc1 * (2 * STEP_C1) + STEP_C1 * STEP_C1; + inc2 = inc2 * (2 * STEP_C2) + STEP_C2 * STEP_C2; + /* Now loop over all cells in box, updating distance per Thomas method */ + bptr = bestdist; + cptr = bestcolor; + xx0 = inc0; + for (ic0 = BOX_C0_ELEMS-1; ic0 >= 0; ic0--) { + dist1 = dist0; + xx1 = inc1; + for (ic1 = BOX_C1_ELEMS-1; ic1 >= 0; ic1--) { + dist2 = dist1; + xx2 = inc2; + for (ic2 = BOX_C2_ELEMS-1; ic2 >= 0; ic2--) { + if (dist2 < *bptr) { + *bptr = dist2; + *cptr = (JSAMPLE) icolor; + } + dist2 += xx2; + xx2 += 2 * STEP_C2 * STEP_C2; + bptr++; + cptr++; + } + dist1 += xx1; + xx1 += 2 * STEP_C1 * STEP_C1; + } + dist0 += xx0; + xx0 += 2 * STEP_C0 * STEP_C0; + } + } +} + + +LOCAL(void) +fill_inverse_cmap (j_decompress_ptr cinfo, int c0, int c1, int c2) +/* Fill the inverse-colormap entries in the update box that contains */ +/* histogram cell c0/c1/c2. (Only that one cell MUST be filled, but */ +/* we can fill as many others as we wish.) */ +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + hist3d histogram = cquantize->histogram; + int minc0, minc1, minc2; /* lower left corner of update box */ + int ic0, ic1, ic2; + register JSAMPLE * cptr; /* pointer into bestcolor[] array */ + register histptr cachep; /* pointer into main cache array */ + /* This array lists the candidate colormap indexes. */ + JSAMPLE colorlist[MAXNUMCOLORS]; + int numcolors; /* number of candidate colors */ + /* This array holds the actually closest colormap index for each cell. */ + JSAMPLE bestcolor[BOX_C0_ELEMS * BOX_C1_ELEMS * BOX_C2_ELEMS]; + + /* Convert cell coordinates to update box ID */ + c0 >>= BOX_C0_LOG; + c1 >>= BOX_C1_LOG; + c2 >>= BOX_C2_LOG; + + /* Compute true coordinates of update box's origin corner. + * Actually we compute the coordinates of the center of the corner + * histogram cell, which are the lower bounds of the volume we care about. + */ + minc0 = (c0 << BOX_C0_SHIFT) + ((1 << C0_SHIFT) >> 1); + minc1 = (c1 << BOX_C1_SHIFT) + ((1 << C1_SHIFT) >> 1); + minc2 = (c2 << BOX_C2_SHIFT) + ((1 << C2_SHIFT) >> 1); + + /* Determine which colormap entries are close enough to be candidates + * for the nearest entry to some cell in the update box. + */ + numcolors = find_nearby_colors(cinfo, minc0, minc1, minc2, colorlist); + + /* Determine the actually nearest colors. */ + find_best_colors(cinfo, minc0, minc1, minc2, numcolors, colorlist, + bestcolor); + + /* Save the best color numbers (plus 1) in the main cache array */ + c0 <<= BOX_C0_LOG; /* convert ID back to base cell indexes */ + c1 <<= BOX_C1_LOG; + c2 <<= BOX_C2_LOG; + cptr = bestcolor; + for (ic0 = 0; ic0 < BOX_C0_ELEMS; ic0++) { + for (ic1 = 0; ic1 < BOX_C1_ELEMS; ic1++) { + cachep = & histogram[c0+ic0][c1+ic1][c2]; + for (ic2 = 0; ic2 < BOX_C2_ELEMS; ic2++) { + *cachep++ = (histcell) (GETJSAMPLE(*cptr++) + 1); + } + } + } +} + + +/* + * Map some rows of pixels to the output colormapped representation. + */ + +METHODDEF(void) +pass2_no_dither (j_decompress_ptr cinfo, + JSAMPARRAY input_buf, JSAMPARRAY output_buf, int num_rows) +/* This version performs no dithering */ +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + hist3d histogram = cquantize->histogram; + register JSAMPROW inptr, outptr; + register histptr cachep; + register int c0, c1, c2; + int row; + JDIMENSION col; + JDIMENSION width = cinfo->output_width; + + for (row = 0; row < num_rows; row++) { + inptr = input_buf[row]; + outptr = output_buf[row]; + for (col = width; col > 0; col--) { + /* get pixel value and index into the cache */ + c0 = GETJSAMPLE(*inptr++) >> C0_SHIFT; + c1 = GETJSAMPLE(*inptr++) >> C1_SHIFT; + c2 = GETJSAMPLE(*inptr++) >> C2_SHIFT; + cachep = & histogram[c0][c1][c2]; + /* If we have not seen this color before, find nearest colormap entry */ + /* and update the cache */ + if (*cachep == 0) + fill_inverse_cmap(cinfo, c0,c1,c2); + /* Now emit the colormap index for this cell */ + *outptr++ = (JSAMPLE) (*cachep - 1); + } + } +} + + +METHODDEF(void) +pass2_fs_dither (j_decompress_ptr cinfo, + JSAMPARRAY input_buf, JSAMPARRAY output_buf, int num_rows) +/* This version performs Floyd-Steinberg dithering */ +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + hist3d histogram = cquantize->histogram; + register LOCFSERROR cur0, cur1, cur2; /* current error or pixel value */ + LOCFSERROR belowerr0, belowerr1, belowerr2; /* error for pixel below cur */ + LOCFSERROR bpreverr0, bpreverr1, bpreverr2; /* error for below/prev col */ + register FSERRPTR errorptr; /* => fserrors[] at column before current */ + JSAMPROW inptr; /* => current input pixel */ + JSAMPROW outptr; /* => current output pixel */ + histptr cachep; + int dir; /* +1 or -1 depending on direction */ + int dir3; /* 3*dir, for advancing inptr & errorptr */ + int row; + JDIMENSION col; + JDIMENSION width = cinfo->output_width; + JSAMPLE *range_limit = cinfo->sample_range_limit; + int *error_limit = cquantize->error_limiter; + JSAMPROW colormap0 = cinfo->colormap[0]; + JSAMPROW colormap1 = cinfo->colormap[1]; + JSAMPROW colormap2 = cinfo->colormap[2]; + SHIFT_TEMPS + + for (row = 0; row < num_rows; row++) { + inptr = input_buf[row]; + outptr = output_buf[row]; + if (cquantize->on_odd_row) { + /* work right to left in this row */ + inptr += (width-1) * 3; /* so point to rightmost pixel */ + outptr += width-1; + dir = -1; + dir3 = -3; + errorptr = cquantize->fserrors + (width+1)*3; /* => entry after last column */ + cquantize->on_odd_row = FALSE; /* flip for next time */ + } else { + /* work left to right in this row */ + dir = 1; + dir3 = 3; + errorptr = cquantize->fserrors; /* => entry before first real column */ + cquantize->on_odd_row = TRUE; /* flip for next time */ + } + /* Preset error values: no error propagated to first pixel from left */ + cur0 = cur1 = cur2 = 0; + /* and no error propagated to row below yet */ + belowerr0 = belowerr1 = belowerr2 = 0; + bpreverr0 = bpreverr1 = bpreverr2 = 0; + + for (col = width; col > 0; col--) { + /* curN holds the error propagated from the previous pixel on the + * current line. Add the error propagated from the previous line + * to form the complete error correction term for this pixel, and + * round the error term (which is expressed * 16) to an integer. + * RIGHT_SHIFT rounds towards minus infinity, so adding 8 is correct + * for either sign of the error value. + * Note: errorptr points to *previous* column's array entry. + */ + cur0 = RIGHT_SHIFT(cur0 + errorptr[dir3+0] + 8, 4); + cur1 = RIGHT_SHIFT(cur1 + errorptr[dir3+1] + 8, 4); + cur2 = RIGHT_SHIFT(cur2 + errorptr[dir3+2] + 8, 4); + /* Limit the error using transfer function set by init_error_limit. + * See comments with init_error_limit for rationale. + */ + cur0 = error_limit[cur0]; + cur1 = error_limit[cur1]; + cur2 = error_limit[cur2]; + /* Form pixel value + error, and range-limit to 0..MAXJSAMPLE. + * The maximum error is +- MAXJSAMPLE (or less with error limiting); + * this sets the required size of the range_limit array. + */ + cur0 += GETJSAMPLE(inptr[0]); + cur1 += GETJSAMPLE(inptr[1]); + cur2 += GETJSAMPLE(inptr[2]); + cur0 = GETJSAMPLE(range_limit[cur0]); + cur1 = GETJSAMPLE(range_limit[cur1]); + cur2 = GETJSAMPLE(range_limit[cur2]); + /* Index into the cache with adjusted pixel value */ + cachep = & histogram[cur0>>C0_SHIFT][cur1>>C1_SHIFT][cur2>>C2_SHIFT]; + /* If we have not seen this color before, find nearest colormap */ + /* entry and update the cache */ + if (*cachep == 0) + fill_inverse_cmap(cinfo, (int)(cur0>>C0_SHIFT),(int)(cur1>>C1_SHIFT),(int)(cur2>>C2_SHIFT)); + /* Now emit the colormap index for this cell */ + { register int pixcode = *cachep - 1; + *outptr = (JSAMPLE) pixcode; + /* Compute representation error for this pixel */ + cur0 -= GETJSAMPLE(colormap0[pixcode]); + cur1 -= GETJSAMPLE(colormap1[pixcode]); + cur2 -= GETJSAMPLE(colormap2[pixcode]); + } + /* Compute error fractions to be propagated to adjacent pixels. + * Add these into the running sums, and simultaneously shift the + * next-line error sums left by 1 column. + */ + { register LOCFSERROR bnexterr, delta; + + bnexterr = cur0; /* Process component 0 */ + delta = cur0 * 2; + cur0 += delta; /* form error * 3 */ + errorptr[0] = (FSERROR) (bpreverr0 + cur0); + cur0 += delta; /* form error * 5 */ + bpreverr0 = belowerr0 + cur0; + belowerr0 = bnexterr; + cur0 += delta; /* form error * 7 */ + bnexterr = cur1; /* Process component 1 */ + delta = cur1 * 2; + cur1 += delta; /* form error * 3 */ + errorptr[1] = (FSERROR) (bpreverr1 + cur1); + cur1 += delta; /* form error * 5 */ + bpreverr1 = belowerr1 + cur1; + belowerr1 = bnexterr; + cur1 += delta; /* form error * 7 */ + bnexterr = cur2; /* Process component 2 */ + delta = cur2 * 2; + cur2 += delta; /* form error * 3 */ + errorptr[2] = (FSERROR) (bpreverr2 + cur2); + cur2 += delta; /* form error * 5 */ + bpreverr2 = belowerr2 + cur2; + belowerr2 = bnexterr; + cur2 += delta; /* form error * 7 */ + } + /* At this point curN contains the 7/16 error value to be propagated + * to the next pixel on the current line, and all the errors for the + * next line have been shifted over. We are therefore ready to move on. + */ + inptr += dir3; /* Advance pixel pointers to next column */ + outptr += dir; + errorptr += dir3; /* advance errorptr to current column */ + } + /* Post-loop cleanup: we must unload the final error values into the + * final fserrors[] entry. Note we need not unload belowerrN because + * it is for the dummy column before or after the actual array. + */ + errorptr[0] = (FSERROR) bpreverr0; /* unload prev errs into array */ + errorptr[1] = (FSERROR) bpreverr1; + errorptr[2] = (FSERROR) bpreverr2; + } +} + + +/* + * Initialize the error-limiting transfer function (lookup table). + * The raw F-S error computation can potentially compute error values of up to + * +- MAXJSAMPLE. But we want the maximum correction applied to a pixel to be + * much less, otherwise obviously wrong pixels will be created. (Typical + * effects include weird fringes at color-area boundaries, isolated bright + * pixels in a dark area, etc.) The standard advice for avoiding this problem + * is to ensure that the "corners" of the color cube are allocated as output + * colors; then repeated errors in the same direction cannot cause cascading + * error buildup. However, that only prevents the error from getting + * completely out of hand; Aaron Giles reports that error limiting improves + * the results even with corner colors allocated. + * A simple clamping of the error values to about +- MAXJSAMPLE/8 works pretty + * well, but the smoother transfer function used below is even better. Thanks + * to Aaron Giles for this idea. + */ + +LOCAL(void) +init_error_limit (j_decompress_ptr cinfo) +/* Allocate and fill in the error_limiter table */ +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + int * table; + int in, out; + + table = (int *) (*cinfo->mem->alloc_small) + ((j_common_ptr) cinfo, JPOOL_IMAGE, (MAXJSAMPLE*2+1) * SIZEOF(int)); + table += MAXJSAMPLE; /* so can index -MAXJSAMPLE .. +MAXJSAMPLE */ + cquantize->error_limiter = table; + +#define STEPSIZE ((MAXJSAMPLE+1)/16) + /* Map errors 1:1 up to +- MAXJSAMPLE/16 */ + out = 0; + for (in = 0; in < STEPSIZE; in++, out++) { + table[in] = out; table[-in] = -out; + } + /* Map errors 1:2 up to +- 3*MAXJSAMPLE/16 */ + for (; in < STEPSIZE*3; in++, out += (in&1) ? 0 : 1) { + table[in] = out; table[-in] = -out; + } + /* Clamp the rest to final out value (which is (MAXJSAMPLE+1)/8) */ + for (; in <= MAXJSAMPLE; in++) { + table[in] = out; table[-in] = -out; + } +#undef STEPSIZE +} + + +/* + * Finish up at the end of each pass. + */ + +METHODDEF(void) +finish_pass1 (j_decompress_ptr cinfo) +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + + /* Select the representative colors and fill in cinfo->colormap */ + cinfo->colormap = cquantize->sv_colormap; + select_colors(cinfo, cquantize->desired); + /* Force next pass to zero the color index table */ + cquantize->needs_zeroed = TRUE; +} + + +METHODDEF(void) +finish_pass2 (j_decompress_ptr cinfo) +{ + /* no work */ +} + + +/* + * Initialize for each processing pass. + */ + +METHODDEF(void) +start_pass_2_quant (j_decompress_ptr cinfo, boolean is_pre_scan) +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + hist3d histogram = cquantize->histogram; + int i; + + /* Only F-S dithering or no dithering is supported. */ + /* If user asks for ordered dither, give him F-S. */ + if (cinfo->dither_mode != JDITHER_NONE) + cinfo->dither_mode = JDITHER_FS; + + if (is_pre_scan) { + /* Set up method pointers */ + cquantize->pub.color_quantize = prescan_quantize; + cquantize->pub.finish_pass = finish_pass1; + cquantize->needs_zeroed = TRUE; /* Always zero histogram */ + } else { + /* Set up method pointers */ + if (cinfo->dither_mode == JDITHER_FS) + cquantize->pub.color_quantize = pass2_fs_dither; + else + cquantize->pub.color_quantize = pass2_no_dither; + cquantize->pub.finish_pass = finish_pass2; + + /* Make sure color count is acceptable */ + i = cinfo->actual_number_of_colors; + if (i < 1) + ERREXIT1(cinfo, JERR_QUANT_FEW_COLORS, 1); + if (i > MAXNUMCOLORS) + ERREXIT1(cinfo, JERR_QUANT_MANY_COLORS, MAXNUMCOLORS); + + if (cinfo->dither_mode == JDITHER_FS) { + size_t arraysize = (size_t) ((cinfo->output_width + 2) * + (3 * SIZEOF(FSERROR))); + /* Allocate Floyd-Steinberg workspace if we didn't already. */ + if (cquantize->fserrors == NULL) + cquantize->fserrors = (FSERRPTR) (*cinfo->mem->alloc_large) + ((j_common_ptr) cinfo, JPOOL_IMAGE, arraysize); + /* Initialize the propagated errors to zero. */ + jzero_far((void FAR *) cquantize->fserrors, arraysize); + /* Make the error-limit table if we didn't already. */ + if (cquantize->error_limiter == NULL) + init_error_limit(cinfo); + cquantize->on_odd_row = FALSE; + } + + } + /* Zero the histogram or inverse color map, if necessary */ + if (cquantize->needs_zeroed) { + for (i = 0; i < HIST_C0_ELEMS; i++) { + jzero_far((void FAR *) histogram[i], + HIST_C1_ELEMS*HIST_C2_ELEMS * SIZEOF(histcell)); + } + cquantize->needs_zeroed = FALSE; + } +} + + +/* + * Switch to a new external colormap between output passes. + */ + +METHODDEF(void) +new_color_map_2_quant (j_decompress_ptr cinfo) +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + + /* Reset the inverse color map */ + cquantize->needs_zeroed = TRUE; +} + + +/* + * Module initialization routine for 2-pass color quantization. + */ + +GLOBAL(void) +jinit_2pass_quantizer (j_decompress_ptr cinfo) +{ + my_cquantize_ptr cquantize; + int i; + + cquantize = (my_cquantize_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_cquantizer)); + cinfo->cquantize = (struct jpeg_color_quantizer *) cquantize; + cquantize->pub.start_pass = start_pass_2_quant; + cquantize->pub.new_color_map = new_color_map_2_quant; + cquantize->fserrors = NULL; /* flag optional arrays not allocated */ + cquantize->error_limiter = NULL; + + /* Make sure jdmaster didn't give me a case I can't handle */ + if (cinfo->out_color_components != 3) + ERREXIT(cinfo, JERR_NOTIMPL); + + /* Allocate the histogram/inverse colormap storage */ + cquantize->histogram = (hist3d) (*cinfo->mem->alloc_small) + ((j_common_ptr) cinfo, JPOOL_IMAGE, HIST_C0_ELEMS * SIZEOF(hist2d)); + for (i = 0; i < HIST_C0_ELEMS; i++) { + cquantize->histogram[i] = (hist2d) (*cinfo->mem->alloc_large) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + HIST_C1_ELEMS*HIST_C2_ELEMS * SIZEOF(histcell)); + } + cquantize->needs_zeroed = TRUE; /* histogram is garbage now */ + + /* Allocate storage for the completed colormap, if required. + * We do this now since it is FAR storage and may affect + * the memory manager's space calculations. + */ + if (cinfo->enable_2pass_quant) { + /* Make sure color count is acceptable */ + int desired = cinfo->desired_number_of_colors; + /* Lower bound on # of colors ... somewhat arbitrary as long as > 0 */ + if (desired < 8) + ERREXIT1(cinfo, JERR_QUANT_FEW_COLORS, 8); + /* Make sure colormap indexes can be represented by JSAMPLEs */ + if (desired > MAXNUMCOLORS) + ERREXIT1(cinfo, JERR_QUANT_MANY_COLORS, MAXNUMCOLORS); + cquantize->sv_colormap = (*cinfo->mem->alloc_sarray) + ((j_common_ptr) cinfo,JPOOL_IMAGE, (JDIMENSION) desired, (JDIMENSION) 3); + cquantize->desired = desired; + } else + cquantize->sv_colormap = NULL; + + /* Only F-S dithering or no dithering is supported. */ + /* If user asks for ordered dither, give him F-S. */ + if (cinfo->dither_mode != JDITHER_NONE) + cinfo->dither_mode = JDITHER_FS; + + /* Allocate Floyd-Steinberg workspace if necessary. + * This isn't really needed until pass 2, but again it is FAR storage. + * Although we will cope with a later change in dither_mode, + * we do not promise to honor max_memory_to_use if dither_mode changes. + */ + if (cinfo->dither_mode == JDITHER_FS) { + cquantize->fserrors = (FSERRPTR) (*cinfo->mem->alloc_large) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + (size_t) ((cinfo->output_width + 2) * (3 * SIZEOF(FSERROR)))); + /* Might as well create the error-limiting table too. */ + init_error_limit(cinfo); + } +} + +#endif /* QUANT_2PASS_SUPPORTED */ diff --git a/dcmjpeg/libijg8/jutils.c b/dcmjpeg/libijg8/jutils.c new file mode 100644 index 00000000..1a19f37f --- /dev/null +++ b/dcmjpeg/libijg8/jutils.c @@ -0,0 +1,179 @@ +/* + * jutils.c + * + * Copyright (C) 1991-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains tables and miscellaneous utility routines needed + * for both compression and decompression. + * Note we prefix all global names with "j" to minimize conflicts with + * a surrounding application. + */ + +#define JPEG_INTERNALS +#include "jinclude8.h" +#include "jpeglib8.h" + + +/* + * jpeg_zigzag_order[i] is the zigzag-order position of the i'th element + * of a DCT block read in natural order (left to right, top to bottom). + */ + +#if 0 /* This table is not actually needed in v6a */ + +const int jpeg_zigzag_order[DCTSIZE2] = { + 0, 1, 5, 6, 14, 15, 27, 28, + 2, 4, 7, 13, 16, 26, 29, 42, + 3, 8, 12, 17, 25, 30, 41, 43, + 9, 11, 18, 24, 31, 40, 44, 53, + 10, 19, 23, 32, 39, 45, 52, 54, + 20, 22, 33, 38, 46, 51, 55, 60, + 21, 34, 37, 47, 50, 56, 59, 61, + 35, 36, 48, 49, 57, 58, 62, 63 +}; + +#endif + +/* + * jpeg_natural_order[i] is the natural-order position of the i'th element + * of zigzag order. + * + * When reading corrupted data, the Huffman decoders could attempt + * to reference an entry beyond the end of this array (if the decoded + * zero run length reaches past the end of the block). To prevent + * wild stores without adding an inner-loop test, we put some extra + * "63"s after the real entries. This will cause the extra coefficient + * to be stored in location 63 of the block, not somewhere random. + * The worst case would be a run-length of 15, which means we need 16 + * fake entries. + */ + +const int jpeg_natural_order[DCTSIZE2+16] = { + 0, 1, 8, 16, 9, 2, 3, 10, + 17, 24, 32, 25, 18, 11, 4, 5, + 12, 19, 26, 33, 40, 48, 41, 34, + 27, 20, 13, 6, 7, 14, 21, 28, + 35, 42, 49, 56, 57, 50, 43, 36, + 29, 22, 15, 23, 30, 37, 44, 51, + 58, 59, 52, 45, 38, 31, 39, 46, + 53, 60, 61, 54, 47, 55, 62, 63, + 63, 63, 63, 63, 63, 63, 63, 63, /* extra entries for safety in decoder */ + 63, 63, 63, 63, 63, 63, 63, 63 +}; + + +/* + * Arithmetic utilities + */ + +GLOBAL(long) +jdiv_round_up (long a, long b) +/* Compute a/b rounded up to next integer, ie, ceil(a/b) */ +/* Assumes a >= 0, b > 0 */ +{ + return (a + b - 1L) / b; +} + + +GLOBAL(long) +jround_up (long a, long b) +/* Compute a rounded up to next multiple of b, ie, ceil(a/b)*b */ +/* Assumes a >= 0, b > 0 */ +{ + a += b - 1L; + return a - (a % b); +} + + +/* On normal machines we can apply MEMCOPY() and MEMZERO() to sample arrays + * and coefficient-block arrays. This won't work on 80x86 because the arrays + * are FAR and we're assuming a small-pointer memory model. However, some + * DOS compilers provide far-pointer versions of memcpy() and memset() even + * in the small-model libraries. These will be used if USE_FMEM is defined. + * Otherwise, the routines below do it the hard way. (The performance cost + * is not all that great, because these routines aren't very heavily used.) + */ + +#ifndef NEED_FAR_POINTERS /* normal case, same as regular macros */ +#define FMEMCOPY(dest,src,size) MEMCOPY(dest,src,size) +#define FMEMZERO(target,size) MEMZERO(target,size) +#else /* 80x86 case, define if we can */ +#ifdef USE_FMEM +#define FMEMCOPY(dest,src,size) _fmemcpy((void FAR *)(dest), (const void FAR *)(src), (size_t)(size)) +#define FMEMZERO(target,size) _fmemset((void FAR *)(target), 0, (size_t)(size)) +#endif +#endif + + +GLOBAL(void) +jcopy_sample_rows (JSAMPARRAY input_array, int source_row, + JSAMPARRAY output_array, int dest_row, + int num_rows, JDIMENSION num_cols) +/* Copy some rows of samples from one place to another. + * num_rows rows are copied from input_array[source_row++] + * to output_array[dest_row++]; these areas may overlap for duplication. + * The source and destination arrays must be at least as wide as num_cols. + */ +{ + register JSAMPROW inptr, outptr; +#ifdef FMEMCOPY + register size_t count = (size_t) (num_cols * SIZEOF(JSAMPLE)); +#else + register JDIMENSION count; +#endif + register int row; + + input_array += source_row; + output_array += dest_row; + + for (row = num_rows; row > 0; row--) { + inptr = *input_array++; + outptr = *output_array++; +#ifdef FMEMCOPY + FMEMCOPY(outptr, inptr, count); +#else + for (count = num_cols; count > 0; count--) + *outptr++ = *inptr++; /* needn't bother with GETJSAMPLE() here */ +#endif + } +} + + +GLOBAL(void) +jcopy_block_row (JBLOCKROW input_row, JBLOCKROW output_row, + JDIMENSION num_blocks) +/* Copy a row of coefficient blocks from one place to another. */ +{ +#ifdef FMEMCOPY + FMEMCOPY(output_row, input_row, num_blocks * (DCTSIZE2 * SIZEOF(JCOEF))); +#else + register JCOEFPTR inptr, outptr; + register long count; + + inptr = (JCOEFPTR) input_row; + outptr = (JCOEFPTR) output_row; + for (count = (long) num_blocks * DCTSIZE2; count > 0; count--) { + *outptr++ = *inptr++; + } +#endif +} + + +GLOBAL(void) +jzero_far (void FAR * target, size_t bytestozero) +/* Zero out a chunk of FAR memory. */ +/* This might be sample-array data, block-array data, or alloc_large data. */ +{ +#ifdef FMEMZERO + FMEMZERO(target, bytestozero); +#else + register char FAR * ptr = (char FAR *) target; + register size_t count; + + for (count = bytestozero; count > 0; count--) { + *ptr++ = 0; + } +#endif +} diff --git a/dcmjpeg/libijg8/jversion8.h b/dcmjpeg/libijg8/jversion8.h new file mode 100644 index 00000000..6472c58d --- /dev/null +++ b/dcmjpeg/libijg8/jversion8.h @@ -0,0 +1,14 @@ +/* + * jversion.h + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains software version identification. + */ + + +#define JVERSION "6b 27-Mar-1998" + +#define JCOPYRIGHT "Copyright (C) 1998, Thomas G. Lane" diff --git a/dcmjpeg/libsrc/CMakeLists.txt b/dcmjpeg/libsrc/CMakeLists.txt new file mode 100644 index 00000000..08da1209 --- /dev/null +++ b/dcmjpeg/libsrc/CMakeLists.txt @@ -0,0 +1,7 @@ +# declare additional include directories +INCLUDE_DIRECTORIES(${dcmjpeg_SOURCE_DIR}/include ${ofstd_SOURCE_DIR}/include ${oflog_SOURCE_DIR}/include ${dcmdata_SOURCE_DIR}/include ${dcmimgle_SOURCE_DIR}/include ${dcmimage_SOURCE_DIR}/include ${dcmjpeg_SOURCE_DIR}/libijg8 ${dcmjpeg_SOURCE_DIR}/libijg12 ${dcmjpeg_SOURCE_DIR}/libijg16 ${ZLIB_INCDIR}) + +# create library from source files +DCMTK_ADD_LIBRARY(dcmjpeg ddpiimpl dipijpeg djcodecd djcodece djcparam djdecbas djdecext djdeclol djdecode djdecpro djdecsps djdecsv1 djdijg12 djdijg8 djdijg16 djeijg12 djeijg8 djeijg16 djencbas djencext djenclol djencode djencpro djencsps djencsv1 djrplol djrploss djutils) + +DCMTK_TARGET_LINK_MODULES(dcmjpeg ofstd oflog dcmdata dcmimgle dcmimage ijg8 ijg12 ijg16) diff --git a/dcmjpeg/libsrc/Makefile.dep b/dcmjpeg/libsrc/Makefile.dep new file mode 100644 index 00000000..a6e247d7 --- /dev/null +++ b/dcmjpeg/libsrc/Makefile.dep @@ -0,0 +1,1710 @@ +ddpiimpl.o: ddpiimpl.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmjpeg/ddpiimpl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcddirif.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicdir.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdirrec.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrulup.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrul.h \ + ../include/dcmtk/dcmjpeg/djdefine.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/dcmimage.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/dimoimg.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diimage.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diovlay.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diobjcou.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/didefine.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diovdat.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diovpln.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diutils.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/dimopx.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/dipixel.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/dimomod.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diluptab.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/dibaslut.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/dimoopx.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/didispfn.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/discalet.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/ditranst.h \ + ../../ofstd/include/dcmtk/ofstd/ofbmanip.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/dipxrept.h +dipijpeg.o: dipijpeg.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diimage.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diovlay.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diobjcou.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/didefine.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diovdat.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diovpln.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diutils.h \ + ../include/dcmtk/dcmjpeg/dipijpeg.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diplugin.h \ + ../include/dcmtk/dcmjpeg/djutils.h ../include/dcmtk/dcmjpeg/djdefine.h \ + ../../dcmjpeg/libijg8/jpeglib8.h ../../dcmjpeg/libijg8/jconfig8.h \ + ../../dcmjpeg/libijg8/jmorecfg8.h ../../dcmjpeg/libijg8/jerror8.h \ + ../../dcmjpeg/libijg8/jpegint8.h ../../dcmjpeg/libijg8/jversion8.h +djcodecd.o: djcodecd.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmjpeg/djcodecd.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../dcmdata/include/dcmtk/dcmdata/dccodec.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../include/dcmtk/dcmjpeg/djutils.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diutils.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/didefine.h \ + ../include/dcmtk/dcmjpeg/djdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixseq.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcofsetl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpxitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpobw.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ + ../include/dcmtk/dcmjpeg/djcparam.h ../include/dcmtk/dcmjpeg/djdecabs.h +djcodece.o: djcodece.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmjpeg/djcodece.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../dcmdata/include/dcmtk/dcmdata/dccodec.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../include/dcmtk/dcmjpeg/djutils.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diutils.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/didefine.h \ + ../include/dcmtk/dcmjpeg/djdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcovlay.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpobw.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixseq.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcofsetl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpxitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrds.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlt.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcchrstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrst.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrus.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ + ../include/dcmtk/dcmjpeg/djcparam.h ../include/dcmtk/dcmjpeg/djencabs.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/dcmimage.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/dimoimg.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diimage.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diovlay.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diobjcou.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diovdat.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diovpln.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/dimopx.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/dipixel.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/dimomod.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diluptab.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/dibaslut.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/dimoopx.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/didispfn.h +djcparam.o: djcparam.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmjpeg/djcparam.h \ + ../../dcmdata/include/dcmtk/dcmdata/dccodec.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../include/dcmtk/dcmjpeg/djutils.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diutils.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/didefine.h \ + ../include/dcmtk/dcmjpeg/djdefine.h +djdecbas.o: djdecbas.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmjpeg/djdecbas.h ../include/dcmtk/dcmjpeg/djcodecd.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../dcmdata/include/dcmtk/dcmdata/dccodec.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../include/dcmtk/dcmjpeg/djutils.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diutils.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/didefine.h \ + ../include/dcmtk/dcmjpeg/djdefine.h ../include/dcmtk/dcmjpeg/djcparam.h \ + ../include/dcmtk/dcmjpeg/djrploss.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixel.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpobw.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../include/dcmtk/dcmjpeg/djdijg8.h ../include/dcmtk/dcmjpeg/djdecabs.h +djdecext.o: djdecext.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmjpeg/djdecext.h ../include/dcmtk/dcmjpeg/djcodecd.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../dcmdata/include/dcmtk/dcmdata/dccodec.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../include/dcmtk/dcmjpeg/djutils.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diutils.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/didefine.h \ + ../include/dcmtk/dcmjpeg/djdefine.h ../include/dcmtk/dcmjpeg/djcparam.h \ + ../include/dcmtk/dcmjpeg/djrploss.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixel.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpobw.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../include/dcmtk/dcmjpeg/djdijg8.h ../include/dcmtk/dcmjpeg/djdecabs.h \ + ../include/dcmtk/dcmjpeg/djdijg12.h +djdeclol.o: djdeclol.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmjpeg/djdeclol.h ../include/dcmtk/dcmjpeg/djcodecd.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../dcmdata/include/dcmtk/dcmdata/dccodec.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../include/dcmtk/dcmjpeg/djutils.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diutils.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/didefine.h \ + ../include/dcmtk/dcmjpeg/djdefine.h ../include/dcmtk/dcmjpeg/djcparam.h \ + ../include/dcmtk/dcmjpeg/djrplol.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixel.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpobw.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../include/dcmtk/dcmjpeg/djdijg8.h ../include/dcmtk/dcmjpeg/djdecabs.h \ + ../include/dcmtk/dcmjpeg/djdijg12.h ../include/dcmtk/dcmjpeg/djdijg16.h +djdecode.o: djdecode.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmjpeg/djdecode.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../include/dcmtk/dcmjpeg/djutils.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diutils.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/didefine.h \ + ../include/dcmtk/dcmjpeg/djdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dccodec.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../include/dcmtk/dcmjpeg/djdecbas.h ../include/dcmtk/dcmjpeg/djcodecd.h \ + ../include/dcmtk/dcmjpeg/djdecext.h ../include/dcmtk/dcmjpeg/djdecsps.h \ + ../include/dcmtk/dcmjpeg/djdecpro.h ../include/dcmtk/dcmjpeg/djdecsv1.h \ + ../include/dcmtk/dcmjpeg/djdeclol.h ../include/dcmtk/dcmjpeg/djcparam.h +djdecpro.o: djdecpro.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmjpeg/djdecpro.h ../include/dcmtk/dcmjpeg/djcodecd.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../dcmdata/include/dcmtk/dcmdata/dccodec.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../include/dcmtk/dcmjpeg/djutils.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diutils.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/didefine.h \ + ../include/dcmtk/dcmjpeg/djdefine.h ../include/dcmtk/dcmjpeg/djcparam.h \ + ../include/dcmtk/dcmjpeg/djrploss.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixel.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpobw.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../include/dcmtk/dcmjpeg/djdijg8.h ../include/dcmtk/dcmjpeg/djdecabs.h \ + ../include/dcmtk/dcmjpeg/djdijg12.h +djdecsps.o: djdecsps.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmjpeg/djdecsps.h ../include/dcmtk/dcmjpeg/djcodecd.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../dcmdata/include/dcmtk/dcmdata/dccodec.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../include/dcmtk/dcmjpeg/djutils.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diutils.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/didefine.h \ + ../include/dcmtk/dcmjpeg/djdefine.h ../include/dcmtk/dcmjpeg/djcparam.h \ + ../include/dcmtk/dcmjpeg/djrploss.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixel.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpobw.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../include/dcmtk/dcmjpeg/djdijg8.h ../include/dcmtk/dcmjpeg/djdecabs.h \ + ../include/dcmtk/dcmjpeg/djdijg12.h +djdecsv1.o: djdecsv1.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmjpeg/djdecsv1.h ../include/dcmtk/dcmjpeg/djcodecd.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../dcmdata/include/dcmtk/dcmdata/dccodec.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../include/dcmtk/dcmjpeg/djutils.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diutils.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/didefine.h \ + ../include/dcmtk/dcmjpeg/djdefine.h ../include/dcmtk/dcmjpeg/djcparam.h \ + ../include/dcmtk/dcmjpeg/djrplol.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixel.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpobw.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../include/dcmtk/dcmjpeg/djdijg8.h ../include/dcmtk/dcmjpeg/djdecabs.h \ + ../include/dcmtk/dcmjpeg/djdijg12.h ../include/dcmtk/dcmjpeg/djdijg16.h +djdijg12.o: djdijg12.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmjpeg/djdijg12.h ../include/dcmtk/dcmjpeg/djdecabs.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../include/dcmtk/dcmjpeg/djutils.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diutils.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/didefine.h \ + ../include/dcmtk/dcmjpeg/djdefine.h ../include/dcmtk/dcmjpeg/djcparam.h \ + ../../dcmdata/include/dcmtk/dcmdata/dccodec.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmjpeg/libijg12/jpeglib12.h ../../dcmjpeg/libijg12/jconfig12.h \ + ../../dcmjpeg/libijg12/jmorecfg12.h ../../dcmjpeg/libijg12/jerror12.h +djdijg16.o: djdijg16.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmjpeg/djdijg16.h ../include/dcmtk/dcmjpeg/djdecabs.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../include/dcmtk/dcmjpeg/djutils.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diutils.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/didefine.h \ + ../include/dcmtk/dcmjpeg/djdefine.h ../include/dcmtk/dcmjpeg/djcparam.h \ + ../../dcmdata/include/dcmtk/dcmdata/dccodec.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmjpeg/libijg16/jpeglib16.h ../../dcmjpeg/libijg16/jconfig16.h \ + ../../dcmjpeg/libijg16/jmorecfg16.h ../../dcmjpeg/libijg16/jerror16.h +djdijg8.o: djdijg8.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmjpeg/djdijg8.h ../include/dcmtk/dcmjpeg/djdecabs.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../include/dcmtk/dcmjpeg/djutils.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diutils.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/didefine.h \ + ../include/dcmtk/dcmjpeg/djdefine.h ../include/dcmtk/dcmjpeg/djcparam.h \ + ../../dcmdata/include/dcmtk/dcmdata/dccodec.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmjpeg/libijg8/jpeglib8.h ../../dcmjpeg/libijg8/jconfig8.h \ + ../../dcmjpeg/libijg8/jmorecfg8.h ../../dcmjpeg/libijg8/jerror8.h +djeijg12.o: djeijg12.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmjpeg/djeijg12.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../include/dcmtk/dcmjpeg/djencabs.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diutils.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/didefine.h \ + ../include/dcmtk/dcmjpeg/djutils.h ../include/dcmtk/dcmjpeg/djdefine.h \ + ../include/dcmtk/dcmjpeg/djcparam.h \ + ../../dcmdata/include/dcmtk/dcmdata/dccodec.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmjpeg/libijg12/jpeglib12.h ../../dcmjpeg/libijg12/jconfig12.h \ + ../../dcmjpeg/libijg12/jmorecfg12.h ../../dcmjpeg/libijg12/jerror12.h \ + ../../dcmjpeg/libijg12/jpegint12.h +djeijg16.o: djeijg16.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmjpeg/djeijg16.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../include/dcmtk/dcmjpeg/djencabs.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diutils.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/didefine.h \ + ../include/dcmtk/dcmjpeg/djutils.h ../include/dcmtk/dcmjpeg/djdefine.h \ + ../include/dcmtk/dcmjpeg/djcparam.h \ + ../../dcmdata/include/dcmtk/dcmdata/dccodec.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmjpeg/libijg16/jpeglib16.h ../../dcmjpeg/libijg16/jconfig16.h \ + ../../dcmjpeg/libijg16/jmorecfg16.h ../../dcmjpeg/libijg16/jerror16.h \ + ../../dcmjpeg/libijg16/jpegint16.h +djeijg8.o: djeijg8.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmjpeg/djeijg8.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../include/dcmtk/dcmjpeg/djencabs.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diutils.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/didefine.h \ + ../include/dcmtk/dcmjpeg/djutils.h ../include/dcmtk/dcmjpeg/djdefine.h \ + ../include/dcmtk/dcmjpeg/djcparam.h \ + ../../dcmdata/include/dcmtk/dcmdata/dccodec.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmjpeg/libijg8/jpeglib8.h ../../dcmjpeg/libijg8/jconfig8.h \ + ../../dcmjpeg/libijg8/jmorecfg8.h ../../dcmjpeg/libijg8/jerror8.h \ + ../../dcmjpeg/libijg8/jpegint8.h +djencbas.o: djencbas.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmjpeg/djencbas.h ../include/dcmtk/dcmjpeg/djcodece.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../dcmdata/include/dcmtk/dcmdata/dccodec.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../include/dcmtk/dcmjpeg/djutils.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diutils.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/didefine.h \ + ../include/dcmtk/dcmjpeg/djdefine.h ../include/dcmtk/dcmjpeg/djcparam.h \ + ../include/dcmtk/dcmjpeg/djrploss.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixel.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpobw.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../include/dcmtk/dcmjpeg/djeijg8.h ../include/dcmtk/dcmjpeg/djencabs.h +djencext.o: djencext.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmjpeg/djencext.h ../include/dcmtk/dcmjpeg/djcodece.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../dcmdata/include/dcmtk/dcmdata/dccodec.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../include/dcmtk/dcmjpeg/djutils.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diutils.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/didefine.h \ + ../include/dcmtk/dcmjpeg/djdefine.h ../include/dcmtk/dcmjpeg/djcparam.h \ + ../include/dcmtk/dcmjpeg/djrploss.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixel.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpobw.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../include/dcmtk/dcmjpeg/djeijg8.h ../include/dcmtk/dcmjpeg/djencabs.h \ + ../include/dcmtk/dcmjpeg/djeijg12.h +djenclol.o: djenclol.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmjpeg/djenclol.h ../include/dcmtk/dcmjpeg/djcodece.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../dcmdata/include/dcmtk/dcmdata/dccodec.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../include/dcmtk/dcmjpeg/djutils.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diutils.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/didefine.h \ + ../include/dcmtk/dcmjpeg/djdefine.h ../include/dcmtk/dcmjpeg/djcparam.h \ + ../include/dcmtk/dcmjpeg/djrplol.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixel.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpobw.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../include/dcmtk/dcmjpeg/djeijg8.h ../include/dcmtk/dcmjpeg/djencabs.h \ + ../include/dcmtk/dcmjpeg/djeijg12.h ../include/dcmtk/dcmjpeg/djeijg16.h +djencode.o: djencode.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmjpeg/djencode.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../include/dcmtk/dcmjpeg/djutils.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diutils.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/didefine.h \ + ../include/dcmtk/dcmjpeg/djdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dccodec.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../include/dcmtk/dcmjpeg/djencbas.h ../include/dcmtk/dcmjpeg/djcodece.h \ + ../include/dcmtk/dcmjpeg/djencext.h ../include/dcmtk/dcmjpeg/djencsps.h \ + ../include/dcmtk/dcmjpeg/djencpro.h ../include/dcmtk/dcmjpeg/djencsv1.h \ + ../include/dcmtk/dcmjpeg/djenclol.h ../include/dcmtk/dcmjpeg/djcparam.h +djencpro.o: djencpro.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmjpeg/djencpro.h ../include/dcmtk/dcmjpeg/djcodece.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../dcmdata/include/dcmtk/dcmdata/dccodec.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../include/dcmtk/dcmjpeg/djutils.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diutils.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/didefine.h \ + ../include/dcmtk/dcmjpeg/djdefine.h ../include/dcmtk/dcmjpeg/djcparam.h \ + ../include/dcmtk/dcmjpeg/djrploss.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixel.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpobw.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../include/dcmtk/dcmjpeg/djeijg8.h ../include/dcmtk/dcmjpeg/djencabs.h \ + ../include/dcmtk/dcmjpeg/djeijg12.h +djencsps.o: djencsps.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmjpeg/djencsps.h ../include/dcmtk/dcmjpeg/djcodece.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../dcmdata/include/dcmtk/dcmdata/dccodec.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../include/dcmtk/dcmjpeg/djutils.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diutils.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/didefine.h \ + ../include/dcmtk/dcmjpeg/djdefine.h ../include/dcmtk/dcmjpeg/djcparam.h \ + ../include/dcmtk/dcmjpeg/djrploss.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixel.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpobw.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../include/dcmtk/dcmjpeg/djeijg8.h ../include/dcmtk/dcmjpeg/djencabs.h \ + ../include/dcmtk/dcmjpeg/djeijg12.h +djencsv1.o: djencsv1.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmjpeg/djencsv1.h ../include/dcmtk/dcmjpeg/djcodece.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../dcmdata/include/dcmtk/dcmdata/dccodec.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../include/dcmtk/dcmjpeg/djutils.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diutils.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/didefine.h \ + ../include/dcmtk/dcmjpeg/djdefine.h ../include/dcmtk/dcmjpeg/djcparam.h \ + ../include/dcmtk/dcmjpeg/djrplol.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixel.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpobw.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../include/dcmtk/dcmjpeg/djeijg8.h ../include/dcmtk/dcmjpeg/djencabs.h \ + ../include/dcmtk/dcmjpeg/djeijg12.h ../include/dcmtk/dcmjpeg/djeijg16.h +djrplol.o: djrplol.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmjpeg/djrplol.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixel.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpobw.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../include/dcmtk/dcmjpeg/djdefine.h +djrploss.o: djrploss.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmjpeg/djrploss.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixel.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpobw.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../include/dcmtk/dcmjpeg/djdefine.h +djutils.o: djutils.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmjpeg/djutils.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diutils.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/didefine.h \ + ../include/dcmtk/dcmjpeg/djdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h diff --git a/dcmjpeg/libsrc/Makefile.in b/dcmjpeg/libsrc/Makefile.in new file mode 100644 index 00000000..c78946ad --- /dev/null +++ b/dcmjpeg/libsrc/Makefile.in @@ -0,0 +1,55 @@ +# +# Makefile for dcmjpeg/libsrc +# + +@SET_MAKE@ + +SHELL = /bin/sh +VPATH = @srcdir@:@top_srcdir@/include:@top_srcdir@/@configdir@/include +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +configdir = @top_srcdir@/@configdir@ + +include $(configdir)/@common_makefile@ + +ofstddir = $(top_srcdir)/../ofstd +oflogdir = $(top_srcdir)/../oflog +dcmdatadir = $(top_srcdir)/../dcmdata +dcmimgledir = $(top_srcdir)/../dcmimgle +dcmjpegdir = $(top_srcdir)/../dcmjpeg + +LOCALINCLUDES = -I$(ofstddir)/include -I$(dcmdatadir)/include -I$(dcmimgledir)/include \ + -I$(dcmjpegdir)/libijg8 -I$(dcmjpegdir)/libijg12 -I$(dcmjpegdir)/libijg16 -I$(oflogdir)/include +LOCALDEFS = + +objs = djutils.o djencode.o djrplol.o djrploss.o djcparam.o djeijg8.o djdijg8.o \ + djcodecd.o djdecbas.o djdecext.o djdecpro.o djdecsps.o djdeclol.o djdecsv1.o \ + djcodece.o djencbas.o djencext.o djencpro.o djencsps.o djenclol.o djencsv1.o \ + djeijg12.o djdijg12.o djeijg16.o djdijg16.o djdecode.o dipijpeg.o ddpiimpl.o +library = libdcmjpeg.$(LIBEXT) + + +all: $(library) + +install: $(library) + $(configdir)/mkinstalldirs $(DESTDIR)$(libdir) + $(INSTALL_DATA) $(library) $(DESTDIR)$(libdir)/$(library) + $(RANLIB) $(DESTDIR)$(libdir)/$(library) + + +$(library): $(objs) + $(AR) $(ARFLAGS) $@ $(objs) + $(RANLIB) $@ + + +clean: + rm -f $(objs) $(library) $(TRASH) + +distclean: + rm -f $(objs) $(library) $(DISTTRASH) + + +dependencies: + $(CXX) -MM $(defines) $(includes) $(CPPFLAGS) $(CXXFLAGS) *.cc > $(DEP) + +include $(DEP) diff --git a/dcmjpeg/libsrc/ddpiimpl.cc b/dcmjpeg/libsrc/ddpiimpl.cc new file mode 100644 index 00000000..8935e3f0 --- /dev/null +++ b/dcmjpeg/libsrc/ddpiimpl.cc @@ -0,0 +1,119 @@ +/* + * + * Copyright (C) 2003-2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdata + * + * Author: Joerg Riesmeier + * + * Purpose: Implementation of DICOMDIR image support (plugin) + * + */ + + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/dcmjpeg/ddpiimpl.h" +#include "dcmtk/dcmimgle/dcmimage.h" /* for class DicomImage */ +#include "dcmtk/dcmimgle/discalet.h" /* for direct image scaling */ + +#include "dcmtk/ofstd/ofcast.h" + + +/*------------------* + * implementation * + *------------------*/ + +// constructor +DicomDirImageImplementation::DicomDirImageImplementation() +{ +} + + +// destructor +DicomDirImageImplementation::~DicomDirImageImplementation() +{ +} + + +// scale pixel data +OFBool DicomDirImageImplementation::scaleData(const Uint8 *srcData, + const unsigned int srcWidth, + const unsigned int srcHeight, + Uint8 *dstData, + const unsigned int dstWidth, + const unsigned int dstHeight) const +{ + OFBool result = OFFalse; + /* check parameters (at least the pointers) */ + if ((srcData != NULL) && (dstData != NULL)) + { + DiScaleTemplate scale(1, OFstatic_cast(Uint16, srcWidth), OFstatic_cast(Uint16, srcHeight), + OFstatic_cast(Uint16, dstWidth), OFstatic_cast(Uint16, dstHeight), 1); + scale.scaleData(OFstatic_cast(const Uint8 **, &srcData), &dstData, 1 /* interpolate */); + result = OFTrue; + } + return result; +} + + +// get scaled pixel data from DICOM image (monochrome only) +OFBool DicomDirImageImplementation::scaleImage(DcmItem *dataset, + Uint8 *pixel, + const unsigned long count, + const unsigned long frame, + const unsigned int width, + const unsigned int height, + const OFBool decompressAll) const +{ + OFBool result = OFFalse; + /* check parameters (at least the pointers) */ + if ((dataset != NULL) && (pixel != NULL) && (frame > 0)) + { + size_t flags = CIF_UsePartialAccessToPixelData | CIF_NeverAccessEmbeddedOverlays; + if (decompressAll) + flags |= CIF_DecompressCompletePixelData; + /* open referenced image */ + DicomImage *image = new DicomImage(dataset, EXS_Unknown, flags, frame - 1 /*fstart*/, 1 /*fcount*/); + if ((image != NULL) && (image->getStatus() == EIS_Normal)) + { + /* check if image is monochrome */ + if (!image->isMonochrome()) + { + /* ... if not create one */ + DicomImage *mono = image->createMonochromeImage(); + /* replace image by monochrome one */ + delete image; + image = mono; + } + if (image != NULL) + { + /* create icon */ + DicomImage *scaled = image->createScaledImage(OFstatic_cast(unsigned long, width), + OFstatic_cast(unsigned long, height), 1 /*interpolate*/); + if (scaled != NULL) + { + /* set VOI window */ + if (!scaled->setWindow(0)) + scaled->setMinMaxWindow(); + /* get pixel data */ + void *data = OFstatic_cast(void *, pixel); + if (scaled->getOutputData(data, count, 8)) + result = OFTrue; + delete scaled; + } + } + } + delete image; + } + return result; +} diff --git a/dcmjpeg/libsrc/dipijpeg.cc b/dcmjpeg/libsrc/dipijpeg.cc new file mode 100644 index 00000000..9f38c031 --- /dev/null +++ b/dcmjpeg/libsrc/dipijpeg.cc @@ -0,0 +1,247 @@ +/* + * + * Copyright (C) 2001-2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmjpeg + * + * Author: Joerg Riesmeier + * + * Purpose: Implements JPEG interface for plugable image formats + * + */ + + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmdata/dctypes.h" +#include "dcmtk/dcmimgle/diimage.h" +#include "dcmtk/dcmjpeg/dipijpeg.h" + +#define INCLUDE_CSETJMP +#define INCLUDE_CSTDIO +#include "dcmtk/ofstd/ofstdinc.h" + +BEGIN_EXTERN_C +#define boolean ijg_boolean +#include "jpeglib8.h" +#include "jerror8.h" +#include "jpegint8.h" +#include "jversion8.h" +#undef boolean + +// disable any preprocessor magic the IJG library might be doing with the "const" keyword +#ifdef const +#undef const +#endif + +#ifdef USE_STD_CXX_INCLUDES +// Solaris defines longjmp() in namespace std, other compilers don't... +namespace std { } +using namespace std; +#endif + +// private error handler struct +struct DIEIJG8ErrorStruct +{ + // the standard IJG error handler object + struct jpeg_error_mgr pub; + // our jump buffer + jmp_buf setjmp_buffer; + // pointer to this + const DiJPEGPlugin *instance; +}; + +// callback forward declarations +void DIEIJG8ErrorExit(j_common_ptr); +void DIEIJG8OutputMessage(j_common_ptr cinfo); + +// helper method to fix old-style casts warnings +static void OFjpeg_create_compress(j_compress_ptr cinfo) +{ + jpeg_create_compress(cinfo); +} + +END_EXTERN_C + + +/*-------------* + * callbacks * + *-------------*/ + +// error handler, executes longjmp +void DIEIJG8ErrorExit(j_common_ptr cinfo) +{ + DIEIJG8ErrorStruct *myerr = OFreinterpret_cast(DIEIJG8ErrorStruct*, cinfo->err); + longjmp(myerr->setjmp_buffer, 1); +} + +// message handler for warning messages and the like +void DIEIJG8OutputMessage(j_common_ptr cinfo) +{ + DIEIJG8ErrorStruct *myerr = OFreinterpret_cast(DIEIJG8ErrorStruct*, cinfo->err); + myerr->instance->outputMessage(cinfo); +} + + +/*----------------* + * constructors * + *----------------*/ + +DiJPEGPlugin::DiJPEGPlugin() + : DiPluginFormat(), + Quality(75), + Sampling(ESS_444) +{ +} + + +DiJPEGPlugin::~DiJPEGPlugin() +{ +} + + +/*------------------* + * implementation * + *------------------*/ + +void DiJPEGPlugin::setQuality(const unsigned int quality) +{ + /* valid range: 0..100 (percent) */ + if (Quality <= 100) + Quality = quality; +} + + +void DiJPEGPlugin::setSampling(const E_SubSampling sampling) +{ + Sampling = sampling; +} + + +void DiJPEGPlugin::outputMessage(void *arg) const +{ + jpeg_common_struct *cinfo = OFreinterpret_cast(jpeg_common_struct*, arg); + if (cinfo && DCM_dcmjpegLogger.isEnabledFor(OFLogger::WARN_LOG_LEVEL)) + { + char buffer[JMSG_LENGTH_MAX]; + (*cinfo->err->format_message)(cinfo, buffer); /* Create the message */ + DCMJPEG_WARN(buffer); + } +} + + +int DiJPEGPlugin::write(DiImage *image, + FILE *stream, + const unsigned long frame) const +{ + int result = 0; + if ((image != NULL) && (stream != NULL)) + { + /* create bitmap with 8 bits per sample */ + const void *data = image->getOutputData(frame, 8 /*bits*/, 0 /*planar*/); + if (data != NULL) + { + const OFBool isMono = (image->getInternalColorModel() == EPI_Monochrome1) || + (image->getInternalColorModel() == EPI_Monochrome2); + + /* code derived from "cjpeg.c" (IJG) and "djeijg8.cc" (DCMJPEG) */ + struct jpeg_compress_struct cinfo; + OFjpeg_create_compress(&cinfo); + /* Initialize JPEG parameters. */ + cinfo.image_width = image->getColumns(); + cinfo.image_height = image->getRows(); + cinfo.input_components = (isMono) ? 1 : 3; + cinfo.in_color_space = (isMono) ? JCS_GRAYSCALE : ((image->getInternalColorModel() == EPI_YBR_Full) ? JCS_YCbCr : JCS_RGB); + + /* Set up the error handling. This has to be after all uses of isMono */ + struct DIEIJG8ErrorStruct jerr; + /* Initialize the JPEG compression object with default error handling. */ + cinfo.err = jpeg_std_error(&jerr.pub); + /* overwrite with specific error handling */ + jerr.instance = this; + jerr.pub.error_exit = DIEIJG8ErrorExit; + jerr.pub.output_message = DIEIJG8OutputMessage; + if (setjmp(jerr.setjmp_buffer)) + { + // the IJG error handler will cause the following code to be executed + char buffer[JMSG_LENGTH_MAX]; + /* Create the message */ + (*cinfo.err->format_message)(OFreinterpret_cast(jpeg_common_struct*, &cinfo), buffer); + /* Release memory */ + jpeg_destroy_compress(&cinfo); + image->deleteOutputData(); + /* return error code */ + return 0; + } + jpeg_set_defaults(&cinfo); + cinfo.optimize_coding = TRUE; + /* Set quantization tables for selected quality. */ + jpeg_set_quality(&cinfo, Quality, TRUE /*force_baseline*/); + /* Specify data destination for compression */ + jpeg_stdio_dest(&cinfo, stream); + /* initialize sampling factors */ + if (cinfo.jpeg_color_space == JCS_YCbCr) + { + switch(Sampling) + { + case ESS_444: /* 4:4:4 sampling (no subsampling) */ + cinfo.comp_info[0].h_samp_factor = 1; + cinfo.comp_info[0].v_samp_factor = 1; + break; + case ESS_422: /* 4:2:2 sampling (horizontal subsampling of chroma components) */ + cinfo.comp_info[0].h_samp_factor = 2; + cinfo.comp_info[0].v_samp_factor = 1; + break; + case ESS_411: /* 4:1:1 sampling (horizontal and vertical subsampling of chroma components) */ + cinfo.comp_info[0].h_samp_factor = 2; + cinfo.comp_info[0].v_samp_factor = 2; + break; + } + } else { + // JPEG color space is not YCbCr, disable subsampling. + cinfo.comp_info[0].h_samp_factor = 1; + cinfo.comp_info[0].v_samp_factor = 1; + } + // all other components are set to 1x1 + for (int sfi = 1; sfi < MAX_COMPONENTS; sfi++) + { + cinfo.comp_info[sfi].h_samp_factor = 1; + cinfo.comp_info[sfi].v_samp_factor = 1; + } + /* Start compressor */ + jpeg_start_compress(&cinfo, TRUE); + /* Process data */ + JSAMPROW row_pointer[1]; + Uint8 *image_buffer = OFreinterpret_cast(Uint8*, OFconst_cast(void*, data)); + const size_t row_stride = cinfo.image_width * cinfo.input_components; + while (cinfo.next_scanline < cinfo.image_height) + { + row_pointer[0] = &image_buffer[cinfo.next_scanline * row_stride]; + (void)jpeg_write_scanlines(&cinfo, row_pointer, 1); + } + /* Finish compression and release memory */ + jpeg_finish_compress(&cinfo); + jpeg_destroy_compress(&cinfo); + /* All done. */ + result = 1; + } + /* delete pixel data */ + image->deleteOutputData(); + } + return result; +} + + +OFString DiJPEGPlugin::getLibraryVersionString() +{ + /* create version information */ + return "IJG, Version " JVERSION " (modified)"; +} diff --git a/dcmjpeg/libsrc/djcodecd.cc b/dcmjpeg/libsrc/djcodecd.cc new file mode 100644 index 00000000..319c8e6d --- /dev/null +++ b/dcmjpeg/libsrc/djcodecd.cc @@ -0,0 +1,840 @@ +/* + * + * Copyright (C) 2001-2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmjpeg + * + * Author: Marco Eichelberg, Norbert Olges + * + * Purpose: Abstract base class for IJG JPEG decoder + * + */ + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmjpeg/djcodecd.h" + +// dcmdata includes +#include "dcmtk/dcmdata/dcdatset.h" /* for class DcmDataset */ +#include "dcmtk/dcmdata/dcdeftag.h" /* for tag constants */ +#include "dcmtk/dcmdata/dcpixseq.h" /* for class DcmPixelSequence */ +#include "dcmtk/dcmdata/dcpxitem.h" /* for class DcmPixelItem */ +#include "dcmtk/dcmdata/dcvrpobw.h" /* for class DcmPolymorphOBOW */ +#include "dcmtk/dcmdata/dcswap.h" /* for swapIfNecessary() */ +#include "dcmtk/dcmdata/dcuid.h" /* for dcmGenerateUniqueIdentifer()*/ + +// dcmjpeg includes +#include "dcmtk/dcmjpeg/djcparam.h" /* for class DJCodecParameter */ +#include "dcmtk/dcmjpeg/djdecabs.h" /* for class DJDecoder */ + + +DJCodecDecoder::DJCodecDecoder() +: DcmCodec() +{ +} + + +DJCodecDecoder::~DJCodecDecoder() +{ +} + + +OFBool DJCodecDecoder::canChangeCoding( + const E_TransferSyntax oldRepType, + const E_TransferSyntax newRepType) const +{ + E_TransferSyntax myXfer = supportedTransferSyntax(); + DcmXfer newRep(newRepType); + if (newRep.isNotEncapsulated() && (oldRepType == myXfer)) return OFTrue; // decompress requested + + // we don't support re-coding for now. + return OFFalse; +} + + +OFCondition DJCodecDecoder::decode( + const DcmRepresentationParameter * fromRepParam, + DcmPixelSequence * pixSeq, + DcmPolymorphOBOW& uncompressedPixelData, + const DcmCodecParameter * cp, + const DcmStack& objStack) const +{ + OFCondition result = EC_Normal; + // assume we can cast the codec parameter to what we need + const DJCodecParameter *djcp = OFreinterpret_cast(const DJCodecParameter*, cp); + + DcmStack localStack(objStack); + (void)localStack.pop(); // pop pixel data element from stack + DcmObject *dataset = localStack.pop(); // this is the item in which the pixel data is located + if ((!dataset)||((dataset->ident()!= EVR_dataset) && (dataset->ident()!= EVR_item))) result = EC_InvalidTag; + else + { + Uint16 imageSamplesPerPixel = 0; + Uint16 imageRows = 0; + Uint16 imageColumns = 0; + Sint32 imageFrames = 1; + Uint16 imageBitsAllocated = 0; + Uint16 imageBitsStored = 0; + Uint16 imageHighBit = 0; + const char *sopClassUID = NULL; + OFBool createPlanarConfiguration = OFFalse; + OFBool createPlanarConfigurationInitialized = OFFalse; + EP_Interpretation colorModel = EPI_Unknown; + OFBool isSigned = OFFalse; + Uint16 pixelRep = 0; // needed to decline color conversion of signed pixel data to RGB + OFBool numberOfFramesPresent = OFFalse; + + if (result.good()) result = OFreinterpret_cast(DcmItem*, dataset)->findAndGetUint16(DCM_SamplesPerPixel, imageSamplesPerPixel); + if (result.good()) result = OFreinterpret_cast(DcmItem*, dataset)->findAndGetUint16(DCM_Rows, imageRows); + if (result.good()) result = OFreinterpret_cast(DcmItem*, dataset)->findAndGetUint16(DCM_Columns, imageColumns); + if (result.good()) result = OFreinterpret_cast(DcmItem*, dataset)->findAndGetUint16(DCM_BitsAllocated, imageBitsAllocated); + if (result.good()) result = OFreinterpret_cast(DcmItem*, dataset)->findAndGetUint16(DCM_BitsStored, imageBitsStored); + if (result.good()) result = OFreinterpret_cast(DcmItem*, dataset)->findAndGetUint16(DCM_HighBit, imageHighBit); + if (result.good()) result = OFreinterpret_cast(DcmItem*, dataset)->findAndGetUint16(DCM_PixelRepresentation, pixelRep); + isSigned = (pixelRep == 0) ? OFFalse : OFTrue; + + // number of frames is an optional attribute - we don't mind if it isn't present. + if (result.good()) + { + if (OFreinterpret_cast(DcmItem*, dataset)->findAndGetSint32(DCM_NumberOfFrames, imageFrames).good()) numberOfFramesPresent = OFTrue; + } + + // we consider SOP Class UID as optional since we only need it to determine SOP Class specific + // encoding rules for planar configuration. + if (result.good()) (void) OFreinterpret_cast(DcmItem*, dataset)->findAndGetString(DCM_SOPClassUID, sopClassUID); + + EP_Interpretation dicomPI = DcmJpegHelper::getPhotometricInterpretation(OFreinterpret_cast(DcmItem*, dataset)); + + OFBool isYBR = OFFalse; + if ((dicomPI == EPI_YBR_Full)||(dicomPI == EPI_YBR_Full_422)||(dicomPI == EPI_YBR_Partial_422)) isYBR = OFTrue; + + if (imageFrames >= OFstatic_cast(Sint32, pixSeq->card())) + imageFrames = OFstatic_cast(Sint32, pixSeq->card() - 1); // limit number of frames to number of pixel items - 1 + if (imageFrames < 1) + imageFrames = 1; // default in case the number of frames attribute contains garbage + + if (result.good()) + { + DcmPixelItem *pixItem = NULL; + Uint8 * jpegData = NULL; + result = pixSeq->getItem(pixItem, 1); // first item is offset table, use second item + if (result.good()) + { + Uint32 fragmentLength = pixItem->getLength(); + result = pixItem->getUint8Array(jpegData); + if (result.good()) + { + if (jpegData == NULL) result = EC_CorruptedData; // JPEG data stream is empty/absent + else + { + Uint8 precision = scanJpegDataForBitDepth(jpegData, fragmentLength); + if (precision == 0) result = EC_CannotChangeRepresentation; // something has gone wrong, bail out + else + { + DJDecoder *jpeg = createDecoderInstance(fromRepParam, djcp, precision, isYBR); + if (jpeg == NULL) result = EC_MemoryExhausted; + else + { + size_t frameSize = ((precision > 8) ? sizeof(Uint16) : sizeof(Uint8)) * imageRows * imageColumns * imageSamplesPerPixel; + size_t totalSize = frameSize * imageFrames; + if (totalSize & 1) totalSize++; // align on 16-bit word boundary + Uint16 *imageData16 = NULL; + Sint32 currentFrame = 0; + size_t currentItem = 1; // ignore offset table + + if (isYBR && (imageBitsStored < imageBitsAllocated)) // check for a special case that is currently not handled properly + { + if (djcp->getDecompressionColorSpaceConversion() != EDC_never) + { + DCMJPEG_WARN("BitsStored < BitsAllocated for JPEG compressed image with YCbCr color model, color space conversion will probably not work properly"); + DCMJPEG_DEBUG("workaround: use option --conv-never (for command line tools) or EDC_never (for the DJDecoderRegistration::registerCodecs() call)"); + } + } + + result = uncompressedPixelData.createUint16Array(OFstatic_cast(Uint32, totalSize / sizeof(Uint16)), imageData16); + if (result.good()) + { + Uint8 *imageData8 = OFreinterpret_cast(Uint8*, imageData16); + + while ((currentFrame < imageFrames)&&(result.good())) + { + result = jpeg->init(); + if (result.good()) + { + result = EJ_Suspension; + while (EJ_Suspension == result) + { + result = pixSeq->getItem(pixItem, OFstatic_cast(Uint32, currentItem++)); + if (result.good()) + { + fragmentLength = pixItem->getLength(); + result = pixItem->getUint8Array(jpegData); + if (result.good()) + { + result = jpeg->decode(jpegData, fragmentLength, imageData8, OFstatic_cast(Uint32, frameSize), isSigned); + } + } + } + if (result.good()) + { + if (! createPlanarConfigurationInitialized) + { + // we need to know the decompressed photometric interpretation in order + // to determine the final planar configuration. However, this is only + // known after the first call to jpeg->decode(), i.e. here. + colorModel = jpeg->getDecompressedColorModel(); + if (colorModel == EPI_Unknown) + { + // derive color model from DICOM photometric interpretation + if ((dicomPI == EPI_YBR_Full_422)||(dicomPI == EPI_YBR_Partial_422)) colorModel = EPI_YBR_Full; + else colorModel = dicomPI; + } + + switch (djcp->getPlanarConfiguration()) + { + case EPC_default: + createPlanarConfiguration = requiresPlanarConfiguration(sopClassUID, colorModel); + break; + case EPC_colorByPixel: + createPlanarConfiguration = OFFalse; + break; + case EPC_colorByPlane: + createPlanarConfiguration = OFTrue; + break; + } + createPlanarConfigurationInitialized = OFTrue; + } + + // convert planar configuration if necessary + if ((imageSamplesPerPixel == 3) && createPlanarConfiguration) + { + if (precision > 8) + result = createPlanarConfigurationWord(OFreinterpret_cast(Uint16*, imageData8), imageColumns, imageRows); + else result = createPlanarConfigurationByte(imageData8, imageColumns, imageRows); + } + currentFrame++; + imageData8 += frameSize; + } + } + } + + if (result.good()) + { + // decompression is complete, finally adjust byte order if necessary + if (jpeg->bytesPerSample() == 1) // we're writing bytes into words + { + result = swapIfNecessary(gLocalByteOrder, EBO_LittleEndian, imageData16, + OFstatic_cast(Uint32, totalSize), sizeof(Uint16)); + } + } + + // adjust photometric interpretation depending on what conversion has taken place + if (result.good()) + { + switch (colorModel) + { + case EPI_Monochrome2: + result = OFreinterpret_cast(DcmItem*, dataset)->putAndInsertString(DCM_PhotometricInterpretation, "MONOCHROME2"); + if (result.good()) + { + imageSamplesPerPixel = 1; + result = OFreinterpret_cast(DcmItem*, dataset)->putAndInsertUint16(DCM_SamplesPerPixel, imageSamplesPerPixel); + } + break; + case EPI_YBR_Full: + result = OFreinterpret_cast(DcmItem*, dataset)->putAndInsertString(DCM_PhotometricInterpretation, "YBR_FULL"); + if (result.good()) + { + imageSamplesPerPixel = 3; + result = OFreinterpret_cast(DcmItem*, dataset)->putAndInsertUint16(DCM_SamplesPerPixel, imageSamplesPerPixel); + } + break; + case EPI_RGB: + result = OFreinterpret_cast(DcmItem*, dataset)->putAndInsertString(DCM_PhotometricInterpretation, "RGB"); + if (result.good()) + { + imageSamplesPerPixel = 3; + result = OFreinterpret_cast(DcmItem*, dataset)->putAndInsertUint16(DCM_SamplesPerPixel, imageSamplesPerPixel); + } + break; + default: + /* leave photometric interpretation untouched unless it is YBR_FULL_422 + * or YBR_PARTIAL_422. In this case, replace by YBR_FULL since decompression + * eliminates the subsampling. + */ + if ((dicomPI == EPI_YBR_Full_422)||(dicomPI == EPI_YBR_Partial_422)) + { + result = OFreinterpret_cast(DcmItem*, dataset)->putAndInsertString(DCM_PhotometricInterpretation, "YBR_FULL"); + } + break; + } + } + + // Bits Allocated is now either 8 or 16 + if (result.good()) + { + if (precision > 8) result = OFreinterpret_cast(DcmItem*, dataset)->putAndInsertUint16(DCM_BitsAllocated, 16); + else result = OFreinterpret_cast(DcmItem*, dataset)->putAndInsertUint16(DCM_BitsAllocated, 8); + } + + // Planar Configuration depends on the createPlanarConfiguration flag + if ((result.good()) && (imageSamplesPerPixel > 1)) + { + result = OFreinterpret_cast(DcmItem*, dataset)->putAndInsertUint16(DCM_PlanarConfiguration, (createPlanarConfiguration ? 1 : 0)); + } + + // Bits Stored cannot be larger than precision + if ((result.good()) && (imageBitsStored > precision)) + { + result = OFreinterpret_cast(DcmItem*, dataset)->putAndInsertUint16(DCM_BitsStored, precision); + } + + // High Bit cannot be larger than precision - 1 + if ((result.good()) && (imageHighBit >= precision)) + { + result = OFreinterpret_cast(DcmItem*, dataset)->putAndInsertUint16(DCM_HighBit, OFstatic_cast(Uint16, precision-1)); + } + + // Number of Frames might have changed in case the previous value was wrong + if (result.good() && (numberOfFramesPresent || (imageFrames > 1))) + { + char numBuf[20]; + sprintf(numBuf, "%ld", OFstatic_cast(long, imageFrames)); + result = OFreinterpret_cast(DcmItem*, dataset)->putAndInsertString(DCM_NumberOfFrames, numBuf); + } + + // Pixel Representation could be signed if lossless JPEG. For now, we just believe what we get. + } + delete jpeg; + } + } + } + } + } + } + + // the following operations do not affect the Image Pixel Module + // but other modules such as SOP Common. We only perform these + // changes if we're on the main level of the dataset, + // which should always identify itself as dataset, not as item. + if (dataset->ident() == EVR_dataset) + { + // create new SOP instance UID if codec parameters require so + if (result.good() && (djcp->getUIDCreation() == EUC_always)) + result = DcmCodec::newInstance(OFreinterpret_cast(DcmItem*, dataset), NULL, NULL, NULL); + } + + } + return result; +} + + +OFCondition DJCodecDecoder::decodeFrame( + const DcmRepresentationParameter *fromParam, + DcmPixelSequence *fromPixSeq, + const DcmCodecParameter *cp, + DcmItem *dataset, + Uint32 frameNo, + Uint32& startFragment, + void *buffer, + Uint32 bufSize, + OFString& decompressedColorModel) const +{ + + OFCondition result = EC_Normal; + // assume we can cast the codec parameter to what we need + const DJCodecParameter *djcp = OFreinterpret_cast(const DJCodecParameter*, cp); + + if ((!dataset)||((dataset->ident()!= EVR_dataset) && (dataset->ident()!= EVR_item))) result = EC_InvalidTag; + else + { + Uint16 imageSamplesPerPixel = 0; + Uint16 imageRows = 0; + Uint16 imageColumns = 0; + Sint32 imageFrames = 1; + Uint16 imageBitsAllocated = 0; + Uint16 imageBitsStored = 0; + Uint16 imageHighBit = 0; + Uint16 planarConfig = 0; + OFString photometricInterpretation; + OFBool isSigned = OFFalse; + Uint16 pixelRep = 0; // needed to decline color conversion of signed pixel data to RGB + + if (result.good()) result = dataset->findAndGetUint16(DCM_SamplesPerPixel, imageSamplesPerPixel); + if (result.good()) result = dataset->findAndGetUint16(DCM_Rows, imageRows); + if (result.good()) result = dataset->findAndGetUint16(DCM_Columns, imageColumns); + if (result.good()) result = dataset->findAndGetUint16(DCM_BitsAllocated, imageBitsAllocated); + if (result.good()) result = dataset->findAndGetUint16(DCM_BitsStored, imageBitsStored); + if (result.good()) result = dataset->findAndGetUint16(DCM_HighBit, imageHighBit); + if (result.good()) result = dataset->findAndGetUint16(DCM_PixelRepresentation, pixelRep); + if (result.good()) result = dataset->findAndGetOFString(DCM_PhotometricInterpretation, photometricInterpretation); + if (imageSamplesPerPixel > 1) + { + if (result.good()) result = dataset->findAndGetUint16(DCM_PlanarConfiguration, planarConfig); + } + + isSigned = (pixelRep == 0) ? OFFalse : OFTrue; + + // number of frames is an optional attribute - we don't mind if it isn't present. + if (result.good()) dataset->findAndGetSint32(DCM_NumberOfFrames, imageFrames); + + EP_Interpretation dicomPI = DcmJpegHelper::getPhotometricInterpretation(dataset); + + OFBool isYBR = OFFalse; + if ((dicomPI == EPI_YBR_Full)||(dicomPI == EPI_YBR_Full_422)||(dicomPI == EPI_YBR_Partial_422)) isYBR = OFTrue; + + if (imageFrames < 1) imageFrames = 1; // default in case this attribute contains garbage + + // determine the corresponding item (first fragment) for this frame + Uint32 currentItem = startFragment; + + // if the user has provided this information, we trust him. + // If the user has passed a zero, try to find out ourselves. + if (currentItem == 0 && result.good()) + { + result = determineStartFragment(frameNo, imageFrames, fromPixSeq, currentItem); + } + + // book-keeping needed to clean-up memory the end of this routine + Uint32 firstFragmentUsed = currentItem; + Uint32 pastLastFragmentUsed = firstFragmentUsed; + + // now access and decompress the frame starting at the item we have identified + if (result.good()) + { + DcmPixelItem *pixItem = NULL; + Uint8 * jpegData = NULL; + result = fromPixSeq->getItem(pixItem, currentItem); + if (result.good()) + { + size_t fragmentLength = pixItem->getLength(); + result = pixItem->getUint8Array(jpegData); + if (result.good()) + { + if (jpegData == NULL) result = EC_CorruptedData; // JPEG data stream is empty/absent + else + { + Uint8 precision = scanJpegDataForBitDepth(jpegData, OFstatic_cast(Uint32, fragmentLength)); + if (precision == 0) result = EC_CannotChangeRepresentation; // something has gone wrong, bail out + else + { + size_t frameSize = ((precision > 8) ? sizeof(Uint16) : sizeof(Uint8)) * imageRows * imageColumns * imageSamplesPerPixel; + if (frameSize > bufSize) return EC_IllegalCall; + + DJDecoder *jpeg = createDecoderInstance(fromParam, djcp, precision, isYBR); + if (jpeg == NULL) result = EC_MemoryExhausted; + else + { + if (isYBR && (imageBitsStored < imageBitsAllocated)) // check for a special case that is currently not handled properly + { + if (djcp->getDecompressionColorSpaceConversion() != EDC_never) + { + DCMJPEG_WARN("BitsStored < BitsAllocated for JPEG compressed image with YCbCr color model, color space conversion will probably not work properly"); + DCMJPEG_DEBUG("workaround: use option --conv-never (for command line tools) or EDC_never (for the DJDecoderRegistration::registerCodecs() call)"); + } + } + + result = jpeg->init(); + if (result.good()) + { + result = EJ_Suspension; + while (EJ_Suspension == result) + { + result = fromPixSeq->getItem(pixItem, currentItem++); + if (result.good()) + { + fragmentLength = pixItem->getLength(); + result = pixItem->getUint8Array(jpegData); + if (result.good()) + { + result = jpeg->decode(jpegData, OFstatic_cast(Uint32, fragmentLength), OFreinterpret_cast(Uint8*, buffer), OFstatic_cast(Uint32, frameSize), isSigned); + pastLastFragmentUsed = currentItem; + } + } + } + if (result.good()) + { + // convert planar configuration to color by plane if necessary + if ((imageSamplesPerPixel == 3) && (planarConfig == 1)) + { + if (precision > 8) + result = createPlanarConfigurationWord(OFreinterpret_cast(Uint16*, buffer), imageColumns, imageRows); + else result = createPlanarConfigurationByte(OFreinterpret_cast(Uint8*, buffer), imageColumns, imageRows); + } + } + + if (result.good()) + { + // decompression is complete, finally adjust byte order if necessary + if (jpeg->bytesPerSample() == 1) // we're writing bytes into words + { + result = swapIfNecessary(gLocalByteOrder, EBO_LittleEndian, OFreinterpret_cast(Uint16*, buffer), OFstatic_cast(Uint32, frameSize), sizeof(Uint16)); + } + } + + if (result.good()) + { + // compression was successful. Now update output parameters + startFragment = pastLastFragmentUsed; + decompressedColorModel = photometricInterpretation; // this is the default + + // now see if we have to change the photometric interpretation + // because the decompression has changed something + switch (jpeg->getDecompressedColorModel()) + { + case EPI_Monochrome2: + decompressedColorModel = "MONOCHROME2"; + break; + case EPI_YBR_Full: + decompressedColorModel = "YBR_FULL"; + break; + case EPI_RGB: + decompressedColorModel = "RGB"; + break; + default: + if ((dicomPI == EPI_YBR_Full_422)||(dicomPI == EPI_YBR_Partial_422)) + { + // decompression always eliminates subsampling + decompressedColorModel = "YBR_FULL"; + } + break; + } + } + + delete jpeg; + + /* remove all used fragments from memory */ + while (firstFragmentUsed < pastLastFragmentUsed) + { + fromPixSeq->getItem(pixItem, firstFragmentUsed++); + pixItem->compact(); + } + } + } + } + } + } + } + } + } + return result; +} + + +OFCondition DJCodecDecoder::encode( + const Uint16 * /* pixelData */, + const Uint32 /* length */, + const DcmRepresentationParameter * /* toRepParam */, + DcmPixelSequence * & /* pixSeq */, + const DcmCodecParameter * /* cp */, + DcmStack & /* objStack */) const +{ + // we are a decoder only + return EC_IllegalCall; +} + + +OFCondition DJCodecDecoder::encode( + const E_TransferSyntax /* fromRepType */, + const DcmRepresentationParameter * /* fromRepParam */, + DcmPixelSequence * /* fromPixSeq */, + const DcmRepresentationParameter * /* toRepParam */, + DcmPixelSequence * & /* toPixSeq */, + const DcmCodecParameter * /* cp */, + DcmStack & /* objStack */) const +{ + // we don't support re-coding for now + return EC_IllegalCall; +} + + +OFCondition DJCodecDecoder::determineDecompressedColorModel( + const DcmRepresentationParameter *fromParam, + DcmPixelSequence *fromPixSeq, + const DcmCodecParameter *cp, + DcmItem *dataset, + OFString &decompressedColorModel) const +{ + OFCondition result = EC_CorruptedData; + if ((dataset != NULL) && (fromPixSeq != NULL)) + { + // the first frame always starts with the second fragment + Uint32 startFragment = 1; + Uint32 bufSize = 0; + // determine size of uncompressed frame + if ((fromPixSeq->getUncompressedFrameSize(dataset, bufSize).good()) && (bufSize > 0)) + { + // allocate temporary buffer for a single frame + Uint8 *buffer = new Uint8[bufSize]; + if (buffer != NULL) + { + DCMJPEG_DEBUG("decompressing first frame to determine the decompressed color model"); + // simple approach: decode first frame in order to determine the uncompressed color model + result = decodeFrame(fromParam, fromPixSeq, cp, dataset, 0 /* frameNo */, startFragment, + OFstatic_cast(void *, buffer), bufSize, decompressedColorModel); + } else + result = EC_MemoryExhausted; + delete[] buffer; + } + } + if (result.bad()) + DCMJPEG_ERROR("can't decompress first frame: " << result.text()); + return result; +} + + +Uint16 DJCodecDecoder::readUint16(const Uint8 *data) +{ + return OFstatic_cast(Uint16, (OFstatic_cast(Uint16, *data) << 8) | OFstatic_cast(Uint16, *(data+1))); +} + + +Uint8 DJCodecDecoder::scanJpegDataForBitDepth( + const Uint8 *data, + const Uint32 fragmentLength) +{ + // first, check whether there is any JPEG data at all + if (data == NULL) return 0; + Uint32 offset = 0; + while(offset+4 < fragmentLength) + { + switch(readUint16(data+offset)) + { + case 0xffc0: // SOF_0: JPEG baseline + return data[offset+4]; + /* break; */ + case 0xffc1: // SOF_1: JPEG extended sequential DCT + return data[offset+4]; + /* break; */ + case 0xffc2: // SOF_2: JPEG progressive DCT + return data[offset+4]; + /* break; */ + case 0xffc3 : // SOF_3: JPEG lossless sequential + return data[offset+4]; + /* break; */ + case 0xffc5: // SOF_5: differential (hierarchical) extended sequential, Huffman + return data[offset+4]; + /* break; */ + case 0xffc6: // SOF_6: differential (hierarchical) progressive, Huffman + return data[offset+4]; + /* break; */ + case 0xffc7: // SOF_7: differential (hierarchical) lossless, Huffman + return data[offset+4]; + /* break; */ + case 0xffc8: // Reserved for JPEG extentions + offset += readUint16(data+offset+2)+2; + break; + case 0xffc9: // SOF_9: extended sequential, arithmetic + return data[offset+4]; + /* break; */ + case 0xffca: // SOF_10: progressive, arithmetic + return data[offset+4]; + /* break; */ + case 0xffcb: // SOF_11: lossless, arithmetic + return data[offset+4]; + /* break; */ + case 0xffcd: // SOF_13: differential (hierarchical) extended sequential, arithmetic + return data[offset+4]; + /* break; */ + case 0xffce: // SOF_14: differential (hierarchical) progressive, arithmetic + return data[offset+4]; + /* break; */ + case 0xffcf: // SOF_15: differential (hierarchical) lossless, arithmetic + return data[offset+4]; + /* break; */ + case 0xffc4: // DHT + offset += readUint16(data+offset+2)+2; + break; + case 0xffcc: // DAC + offset += readUint16(data+offset+2)+2; + break; + case 0xffd0: // RST m + case 0xffd1: + case 0xffd2: + case 0xffd3: + case 0xffd4: + case 0xffd5: + case 0xffd6: + case 0xffd7: + offset +=2; + break; + case 0xffd8: // SOI + offset +=2; + break; + case 0xffd9: // EOI + offset +=2; + break; + case 0xffda: // SOS + offset += readUint16(data+offset+2)+2; + break; + case 0xffdb: // DQT + offset += readUint16(data+offset+2)+2; + break; + case 0xffdc: // DNL + offset += readUint16(data+offset+2)+2; + break; + case 0xffdd: // DRI + offset += readUint16(data+offset+2)+2; + break; + case 0xffde: // DHP + offset += readUint16(data+offset+2)+2; + break; + case 0xffdf: // EXP + offset += readUint16(data+offset+2)+2; + break; + case 0xffe0: // APPn + case 0xffe1: + case 0xffe2: + case 0xffe3: + case 0xffe4: + case 0xffe5: + case 0xffe6: + case 0xffe7: + case 0xffe8: + case 0xffe9: + case 0xffea: + case 0xffeb: + case 0xffec: + case 0xffed: + case 0xffee: + case 0xffef: + offset += readUint16(data+offset+2)+2; + break; + case 0xfff0: // JPGn + case 0xfff1: + case 0xfff2: + case 0xfff3: + case 0xfff4: + case 0xfff5: + case 0xfff6: + case 0xfff7: + case 0xfff8: + case 0xfff9: + case 0xfffa: + case 0xfffb: + case 0xfffc: + case 0xfffd: + offset += readUint16(data+offset+2)+2; + break; + case 0xfffe: // COM + offset += readUint16(data+offset+2)+2; + break; + case 0xffff: // fill byte 0xff (skip one byte only) + offset += 1; + break; + case 0xff01: // TEM + break; + default: + if ((data[offset]==0xff) && (data[offset+1]>2) && (data[offset+1] <= 0xbf)) // RES reserved markers + { + offset += 2; + } + else + { + DCMJPEG_ERROR("found invalid marker in JPEG stream while scanning for bit depth: 0x" + << STD_NAMESPACE hex << STD_NAMESPACE setfill('0') + << STD_NAMESPACE setw(2) << OFstatic_cast(int, data[offset]) + << STD_NAMESPACE setw(2) << OFstatic_cast(int, data[offset+1]) + << STD_NAMESPACE dec << STD_NAMESPACE setfill(' ')); + return 0; // syntax error, stop parsing + } + break; + } + } // while + return 0; // no SOF marker found +} + + +OFCondition DJCodecDecoder::createPlanarConfigurationByte( + Uint8 *imageFrame, + Uint16 columns, + Uint16 rows) +{ + if (imageFrame == NULL) return EC_IllegalCall; + + size_t numPixels = columns * rows; + if (numPixels == 0) return EC_IllegalCall; + + Uint8 *buf = new Uint8[3*numPixels + 3]; + if (buf) + { + memcpy(buf, imageFrame, 3*numPixels); + register Uint8 *s = buf; // source + register Uint8 *r = imageFrame; // red plane + register Uint8 *g = imageFrame + numPixels; // green plane + register Uint8 *b = imageFrame + (2*numPixels); // blue plane + for (register size_t i=numPixels; i; i--) + { + *r++ = *s++; + *g++ = *s++; + *b++ = *s++; + } + delete[] buf; + } else return EC_MemoryExhausted; + return EC_Normal; +} + +OFCondition DJCodecDecoder::createPlanarConfigurationWord( + Uint16 *imageFrame, + Uint16 columns, + Uint16 rows) +{ + if (imageFrame == NULL) return EC_IllegalCall; + + size_t numPixels = columns * rows; + if (numPixels == 0) return EC_IllegalCall; + + Uint16 *buf = new Uint16[3*numPixels + 3]; + if (buf) + { + memcpy(buf, imageFrame, 3*numPixels*sizeof(Uint16)); + register Uint16 *s = buf; // source + register Uint16 *r = imageFrame; // red plane + register Uint16 *g = imageFrame + numPixels; // green plane + register Uint16 *b = imageFrame + (2*numPixels); // blue plane + for (register size_t i=numPixels; i; i--) + { + *r++ = *s++; + *g++ = *s++; + *b++ = *s++; + } + delete[] buf; + } else return EC_MemoryExhausted; + return EC_Normal; +} + +/* This method examines if a given image requires color-by-plane planar configuration + * depending on SOP Class UID (DICOM IOD) and photometric interpretation. + * All SOP classes defined in the 2001 edition of the DICOM standard or earlier + * are handled correctly. + */ + +OFBool DJCodecDecoder::requiresPlanarConfiguration( + const char *sopClassUID, + EP_Interpretation photometricInterpretation) +{ + if (sopClassUID) + { + OFString sopClass(sopClassUID); + + // Hardcopy Color Image always requires color-by-plane + if (sopClass == UID_RETIRED_HardcopyColorImageStorage) return OFTrue; + + // The 1996 Ultrasound Image IODs require color-by-plane if color model is YBR_FULL. + if (photometricInterpretation == EPI_YBR_Full) + { + if ((sopClass == UID_UltrasoundMultiframeImageStorage) + ||(sopClass == UID_UltrasoundImageStorage)) return OFTrue; + } + + } + return OFFalse; +} diff --git a/dcmjpeg/libsrc/djcodece.cc b/dcmjpeg/libsrc/djcodece.cc new file mode 100644 index 00000000..72c0404e --- /dev/null +++ b/dcmjpeg/libsrc/djcodece.cc @@ -0,0 +1,1491 @@ +/* + * + * Copyright (C) 2001-2015, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmjpeg + * + * Author: Marco Eichelberg, Norbert Olges + * + * Purpose: abstract codec class for JPEG encoders. + * + */ + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmjpeg/djcodece.h" + +// ofstd includes +#include "dcmtk/ofstd/oflist.h" +#include "dcmtk/ofstd/ofstd.h" + +// dcmdata includes +#include "dcmtk/dcmdata/dcdatset.h" /* for class DcmDataset */ +#include "dcmtk/dcmdata/dcdeftag.h" /* for tag constants */ +#include "dcmtk/dcmdata/dcovlay.h" /* for class DcmOverlayData */ +#include "dcmtk/dcmdata/dcpixseq.h" /* for class DcmPixelSequence */ +#include "dcmtk/dcmdata/dcpxitem.h" /* for class DcmPixelItem */ +#include "dcmtk/dcmdata/dcuid.h" /* for dcmGenerateUniqueIdentifer()*/ +#include "dcmtk/dcmdata/dcvrcs.h" /* for class DcmCodeString */ +#include "dcmtk/dcmdata/dcvrds.h" /* for class DcmDecimalString */ +#include "dcmtk/dcmdata/dcvrlt.h" /* for class DcmLongText */ +#include "dcmtk/dcmdata/dcvrst.h" /* for class DcmShortText */ +#include "dcmtk/dcmdata/dcvrus.h" /* for class DcmUnsignedShort */ +#include "dcmtk/dcmdata/dcswap.h" /* for swapIfNecessary */ + +// dcmjpeg includes +#include "dcmtk/dcmjpeg/djcparam.h" /* for class DJCodecParameter */ +#include "dcmtk/dcmjpeg/djencabs.h" /* for class DJEncoder */ + +// dcmimgle includes +#include "dcmtk/dcmimgle/dcmimage.h" /* for class DicomImage */ + +#define INCLUDE_CMATH +#include "dcmtk/ofstd/ofstdinc.h" + + +DJCodecEncoder::DJCodecEncoder() +: DcmCodec() +{ +} + + +DJCodecEncoder::~DJCodecEncoder() +{ +} + + +OFBool DJCodecEncoder::canChangeCoding( + const E_TransferSyntax oldRepType, + const E_TransferSyntax newRepType) const +{ + E_TransferSyntax myXfer = supportedTransferSyntax(); + DcmXfer newRep(newRepType); + DcmXfer oldRep(oldRepType); + if (oldRep.isNotEncapsulated() && (newRepType == myXfer)) return OFTrue; // compress requested + + // we don't support re-coding for now + return OFFalse; +} + + +OFCondition DJCodecEncoder::decode( + const DcmRepresentationParameter * /* fromRepParam */, + DcmPixelSequence * /* pixSeq */, + DcmPolymorphOBOW& /* uncompressedPixelData */, + const DcmCodecParameter * /* cp */, + const DcmStack& /* objStack */) const +{ + // we are an encoder only + return EC_IllegalCall; +} + + +OFCondition DJCodecEncoder::decodeFrame( + const DcmRepresentationParameter * /* fromParam */ , + DcmPixelSequence * /* fromPixSeq */ , + const DcmCodecParameter * /* cp */ , + DcmItem * /* dataset */ , + Uint32 /* frameNo */ , + Uint32& /* startFragment */ , + void * /* buffer */ , + Uint32 /* bufSize */ , + OFString& /* decompressedColorModel */ ) const +{ + // we are an encoder only + return EC_IllegalCall; +} + + +OFCondition DJCodecEncoder::encode( + const E_TransferSyntax /* fromRepType */, + const DcmRepresentationParameter * /* fromRepParam */, + DcmPixelSequence * /* fromPixSeq */, + const DcmRepresentationParameter * /* toRepParam */, + DcmPixelSequence * & /* toPixSeq */, + const DcmCodecParameter * /* cp */, + DcmStack & /* objStack */) const +{ + // we don't support re-coding for now + return EC_IllegalCall; +} + + +OFCondition DJCodecEncoder::encode( + const Uint16 * /* pixelData */, + const Uint32 /* length */, + const DcmRepresentationParameter * toRepParam, + DcmPixelSequence * & pixSeq, + const DcmCodecParameter *cp, + DcmStack & objStack) const +{ + OFCondition result = EC_Normal; + // assume we can cast the codec parameter to what we need + const DJCodecParameter *djcp = OFreinterpret_cast(const DJCodecParameter*, cp); + + // if true lossless mode is enabled, and we're supposed to do lossless compression, + // call the "true lossless encoding"-engine + if (isLosslessProcess() && (djcp->getTrueLosslessMode())) + return encodeTrueLossless(toRepParam, pixSeq, cp, objStack); + + DcmStack localStack(objStack); + (void)localStack.pop(); // pop pixel data element from stack + DcmObject *dataset = localStack.pop(); // this is the item in which the pixel data is located + + if ((!dataset)||((dataset->ident()!= EVR_dataset) && (dataset->ident()!= EVR_item))) result = EC_InvalidTag; + else + { + double compressionRatio = 0.0; + EP_Interpretation photometricInterpretation = DcmJpegHelper::getPhotometricInterpretation(OFreinterpret_cast(DcmItem*, dataset)); + switch (photometricInterpretation) + { + case EPI_Monochrome1: + case EPI_Monochrome2: + // monochrome image + result = encodeMonochromeImage(OFreinterpret_cast(DcmItem*, dataset), toRepParam, pixSeq, djcp, compressionRatio); + break; + case EPI_PaletteColor: + case EPI_RGB: + case EPI_HSV: + case EPI_ARGB: + case EPI_CMYK: + case EPI_YBR_Partial_422: + // color image except YCbCr which receives special treatment + result = encodeColorImage(OFFalse, OFreinterpret_cast(DcmItem*, dataset), toRepParam, pixSeq, djcp, compressionRatio); + break; + case EPI_YBR_Full: + case EPI_YBR_Full_422: + // YCbCr color image + result = encodeColorImage(OFTrue, OFreinterpret_cast(DcmItem*, dataset), toRepParam, pixSeq, djcp, compressionRatio); + break; + case EPI_Unknown: + case EPI_Missing: + // unknown color model - bail out + result = EJ_UnsupportedPhotometricInterpretation; + break; + } + + // the following operations do not affect the Image Pixel Module + // but other modules such as SOP Common. We only perform these + // changes if we're on the main level of the dataset, + // which should always identify itself as dataset, not as item. + if (dataset->ident() == EVR_dataset) + { + + // update image type + if (result.good()) result = DcmCodec::updateImageType(OFreinterpret_cast(DcmItem*, dataset)); + + // determine compressed bit depth passed to JPEG codec + Uint16 compressedBits = OFstatic_cast(Uint16, djcp->getForcedBitDepth()); + if (result.good()) + { + if (compressedBits == 0) + { + result = OFreinterpret_cast(DcmItem*, dataset)->findAndGetUint16(DCM_BitsStored, compressedBits); + } + } + + // update derivation description + if (result.good()) result = updateDerivationDescription(OFreinterpret_cast(DcmItem*, dataset), toRepParam, + djcp, OFstatic_cast(Uint8, compressedBits), compressionRatio); + + if (result.good()) + { + // lossy process - create new UID unless mode is EUC_never and we're not converting to Secondary Capture + // (pseudo-lossless mode may also result in lossy compression, so treat it the same way) + if (djcp->getConvertToSC() || (djcp->getUIDCreation() != EUC_never)) + result = DcmCodec::newInstance(OFreinterpret_cast(DcmItem*, dataset), "DCM", "121320", "Uncompressed predecessor"); + + // update lossy compression ratio + if (result.good()) result = updateLossyCompressionRatio(OFreinterpret_cast(DcmItem*, dataset), compressionRatio); + } + + // convert to Secondary Capture if requested by user. + // This method creates a new SOP class UID, so it should be executed + // after the call to newInstance() which creates a Source Image Sequence. + if (result.good() && djcp->getConvertToSC()) result = DcmCodec::convertToSecondaryCapture(OFreinterpret_cast(DcmItem*, dataset)); + } + } + return result; +} + + +OFCondition DJCodecEncoder::determineDecompressedColorModel( + const DcmRepresentationParameter * /* fromParam */, + DcmPixelSequence * /* fromPixSeq */, + const DcmCodecParameter * /* cp */, + DcmItem * /* dataset */, + OFString & /* decompressedColorModel */) const +{ + return EC_IllegalCall; +} + + +OFCondition DJCodecEncoder::encodeColorImage( + OFBool YBRmode, + DcmItem *dataset, + const DcmRepresentationParameter * toRepParam, + DcmPixelSequence * & pixSeq, + const DJCodecParameter *cp, + double& compressionRatio) const +{ + OFCondition result = EC_Normal; + DcmOffsetList offsetList; + DcmPixelSequence *pixelSequence = NULL; + DcmPixelItem *offsetTable = NULL; + unsigned short bitsPerSample = 0; + compressionRatio = 0.0; // initialize if something goes wrong + size_t compressedSize = 0; + double uncompressedSize = 0.0; + Uint16 compressedBits = OFstatic_cast(Uint16, cp->getForcedBitDepth()); + + // initialize settings with defaults for RGB mode + OFBool monochromeMode = OFFalse; + size_t flags = 0; // flags for initialization of DicomImage + EP_Interpretation interpr = EPI_RGB; + Uint16 samplesPerPixel = 3; + const char *photometricInterpretation = "RGB"; + if ((cp->getCompressionColorSpaceConversion() == ECC_lossyYCbCr) && (!isLosslessProcess())) + { + if (cp->getWriteYBR422()) photometricInterpretation = "YBR_FULL_422"; + else photometricInterpretation = "YBR_FULL"; + } + + // check mode and adjust settings + if (cp->getCompressionColorSpaceConversion() == ECC_monochrome) + { + monochromeMode = OFTrue; + flags = 0; + interpr = EPI_Monochrome2; + samplesPerPixel = 1; + photometricInterpretation = "MONOCHROME2"; + } + else if (YBRmode) + { + monochromeMode = OFFalse; + flags = CIF_KeepYCbCrColorModel; // keep YCbCr color model + interpr = EPI_YBR_Full; + if (cp->getWriteYBR422()) photometricInterpretation = "YBR_FULL_422"; + else photometricInterpretation = "YBR_FULL"; + } + + // integrate DicomImage flags transported by DJCodecParameter into "flags"-variable + if (cp->getAcceptWrongPaletteTags()) + flags |= CIF_WrongPaletteAttributeTags; + if (cp->getAcrNemaCompatibility()) + flags |= CIF_AcrNemaCompatibility; + + // create dcmimage object. Will fail if dcmimage has not been activated in main(). + // transfer syntax can be any uncompressed one. + DicomImage *dimage = NULL; + if (monochromeMode) + { + DicomImage colorimage(dataset, EXS_LittleEndianImplicit, flags); // read all frames + if (colorimage.getStatus() == EIS_Normal) dimage = colorimage.createMonochromeImage(); + if (dimage) dimage->setNoVoiTransformation(); + } + else + { + dimage = new DicomImage(dataset, EXS_LittleEndianImplicit, flags); // read all frames + } + + if (dimage == NULL) result = EC_MemoryExhausted; + else if (dimage->getStatus() != EIS_Normal) result = EC_IllegalCall; // should return dimage->getStatus() + + // don't render overlays + if (result.good()) + { + dimage->hideAllOverlays(); + } + + // create initial pixel sequence + if (result.good()) + { + pixelSequence = new DcmPixelSequence(DCM_PixelSequenceTag); + if (pixelSequence == NULL) result = EC_MemoryExhausted; + else + { + // create empty offset table + offsetTable = new DcmPixelItem(DCM_PixelItemTag); + if (offsetTable == NULL) result = EC_MemoryExhausted; + else pixelSequence->insert(offsetTable); + } + } + + // select bit depth + if (result.good()) + { + if (compressedBits == 0) + { + result = OFreinterpret_cast(DcmItem*, dataset)->findAndGetUint16(DCM_BitsStored, compressedBits); + } + } + + // create codec instance + if (result.good()) + { + DJEncoder *jpeg = createEncoderInstance(toRepParam, cp, OFstatic_cast(Uint8, compressedBits)); + if (jpeg) + { + // render and compress each frame + bitsPerSample = jpeg->bitsPerSample(); + size_t frameCount = dimage->getFrameCount(); + unsigned short bytesPerSample = jpeg->bytesPerSample(); + unsigned short columns = OFstatic_cast(unsigned short, dimage->getWidth()); + unsigned short rows = OFstatic_cast(unsigned short, dimage->getHeight()); + Uint8 *jpegData = NULL; + Uint32 jpegLen = 0; + const void *frame = NULL; + + // compute original image size in bytes, ignoring any padding bits. + uncompressedSize = OFstatic_cast(double, columns * rows * dimage->getDepth() * frameCount * samplesPerPixel) / 8.0; + for (size_t i=0; (igetOutputData(bitsPerSample, i, 0); + if (frame == NULL) result = EC_MemoryExhausted; + else + { + // compress frame + jpegData = NULL; + if (bytesPerSample == 1) + { + result = jpeg->encode(columns, rows, interpr, samplesPerPixel, OFreinterpret_cast(Uint8*, OFconst_cast(void*, frame)), jpegData, jpegLen); + } else { + result = jpeg->encode(columns, rows, interpr, samplesPerPixel, OFreinterpret_cast(Uint16*, OFconst_cast(void*, frame)), jpegData, jpegLen); + } + + // store frame + if (result.good()) + { + result = pixelSequence->storeCompressedFrame(offsetList, jpegData, jpegLen, cp->getFragmentSize()); + } + + // delete block of JPEG data + delete[] jpegData; + compressedSize += jpegLen; + } + } + delete jpeg; + } else result = EC_MemoryExhausted; + } + + // store pixel sequence if everything was successful + if (result.good()) pixSeq = pixelSequence; + else + { + delete pixelSequence; + pixSeq = NULL; + } + + if ((result.good()) && (cp->getCreateOffsetTable())) + { + // create offset table + result = offsetTable->createOffsetTable(offsetList); + } + + if (result.good()) + { + // adapt attributes in image pixel module + if (result.good()) result = dataset->putAndInsertUint16(DCM_SamplesPerPixel, samplesPerPixel); + if (result.good()) result = dataset->putAndInsertString(DCM_PhotometricInterpretation, photometricInterpretation); + if (result.good()) + { + if (bitsPerSample > 8) + result = dataset->putAndInsertUint16(DCM_BitsAllocated, 16); + else + result = dataset->putAndInsertUint16(DCM_BitsAllocated, 8); + } + if (result.good()) result = dataset->putAndInsertUint16(DCM_BitsStored, bitsPerSample); + if (result.good()) result = dataset->putAndInsertUint16(DCM_HighBit, OFstatic_cast(Uint16, bitsPerSample-1)); + if (result.good()) result = dataset->putAndInsertUint16(DCM_PixelRepresentation, 0); + if (result.good()) + { + if (monochromeMode) delete dataset->remove(DCM_PlanarConfiguration); + else result = dataset->putAndInsertUint16(DCM_PlanarConfiguration, 0); + } + delete dataset->remove(DCM_SmallestImagePixelValue); + delete dataset->remove(DCM_LargestImagePixelValue); + delete dataset->remove(DCM_RedPaletteColorLookupTableDescriptor); + delete dataset->remove(DCM_GreenPaletteColorLookupTableDescriptor); + delete dataset->remove(DCM_BluePaletteColorLookupTableDescriptor); + delete dataset->remove(DCM_RedPaletteColorLookupTableData); + delete dataset->remove(DCM_GreenPaletteColorLookupTableData); + delete dataset->remove(DCM_BluePaletteColorLookupTableData); + delete dataset->remove(DCM_PixelPaddingValue); + delete dataset->remove(DCM_PixelPaddingRangeLimit); + delete dataset->remove(DCM_SmallestPixelValueInSeries); + delete dataset->remove(DCM_LargestPixelValueInSeries); + delete dataset->remove(DCM_PaletteColorLookupTableUID); + delete dataset->remove(DCM_SegmentedRedPaletteColorLookupTableData); + delete dataset->remove(DCM_SegmentedGreenPaletteColorLookupTableData); + delete dataset->remove(DCM_SegmentedBluePaletteColorLookupTableData); + } + if (compressedSize > 0) compressionRatio = OFstatic_cast(double, uncompressedSize) / OFstatic_cast(double, compressedSize); + + delete dimage; + return result; +} + + +OFCondition DJCodecEncoder::encodeTrueLossless( + const DcmRepresentationParameter * toRepParam, + DcmPixelSequence * & pixSeq, + const DcmCodecParameter *cp, + DcmStack & objStack) const +{ + OFCondition result = EC_Normal; + // assume we can cast the codec parameter to what we need + DJCodecParameter *djcp = OFreinterpret_cast(DJCodecParameter*, OFconst_cast(DcmCodecParameter*, cp)); + // get dataset from stack + DcmStack localStack(objStack); + (void)localStack.pop(); + DcmObject *dataset = localStack.pop(); + + // check whether dataset was on top of the stack + if ((!dataset)||((dataset->ident()!= EVR_dataset) && (dataset->ident()!= EVR_item))) + return EC_InvalidTag; + else + { + DcmItem *datsetItem = OFreinterpret_cast(DcmItem*, dataset); + double compressionRatio = 0.0; + const Uint16* pixelData; + size_t length = 0; + Uint16 bitsAllocated = 0; + Uint16 bitsStored = 0; + Uint16 bytesAllocated = 0; + Uint16 samplesPerPixel = 0; + Uint16 planarConfiguration = 0; + Uint16 columns = 0; + Uint16 rows = 0; + Sint32 numberOfFrames = 1; + EP_Interpretation interpr = EPI_Unknown; + Uint8 *jpegData = NULL; + Uint32 jpegLen = 0; + OFBool byteSwapped = OFFalse; // true if we have byte-swapped the original pixel data + OFBool planConfSwitched = OFFalse; // true if planar configuration was toggled + DcmOffsetList offsetList; + OFString photometricInterpretation; + DcmElement *dummyElem; + + // get relevant attributes for encoding from dataset + result = datsetItem->findAndGetUint16(DCM_BitsStored, bitsStored); + if (result.good()) result = datsetItem->findAndGetUint16(DCM_BitsAllocated, bitsAllocated); + if (result.good()) result = datsetItem->findAndGetUint16(DCM_SamplesPerPixel, samplesPerPixel); + if (result.good()) result = datsetItem->findAndGetUint16(DCM_Columns, columns); + if (result.good()) result = datsetItem->findAndGetUint16(DCM_Rows, rows); + if (result.good()) result = datsetItem->findAndGetOFString(DCM_PhotometricInterpretation, photometricInterpretation); + if (result.good()) result = datsetItem->findAndGetUint16Array(DCM_PixelData, pixelData, NULL, OFFalse); + if (result.good()) result = datsetItem->findAndGetElement(DCM_PixelData, dummyElem); + if (result.good()) length = dummyElem->getLength(); + if (result.good()) + { + result = datsetItem->findAndGetSint32(DCM_NumberOfFrames, numberOfFrames); + if (result.bad() || numberOfFrames < 1) numberOfFrames = 1; + result = EC_Normal; + } + if (result.bad()) + { + DCMJPEG_ERROR("True lossless encoder: Unable to get relevant attributes from dataset"); + return result; + } + + // check, whether bit depth is supported + if (bitsAllocated == 8) + bytesAllocated = 1; + else if (bitsAllocated == 16) + bytesAllocated = 2; + else + { + DCMJPEG_ERROR("True lossless encoder: Only 8 or 16 bits allocated supported"); + return EC_IllegalParameter; + } + + // make sure that all the descriptive attributes have sensible values + if ((columns < 1)||(rows < 1)||(samplesPerPixel < 1)) + { + DCMJPEG_ERROR("True lossless encoder: Invalid attribute values in pixel module"); + return EC_CannotChangeRepresentation; + } + + /* Set and check photometric interpretation (up to now: EPI_RGB) + * Only photometric interpretations, that are explicetly "supported" by the + * IJG lib are set. For all others "unknown" is set. Some are even rejected here. + */ + if (photometricInterpretation == "MONOCHROME1") + interpr = EPI_Monochrome1; + else if (photometricInterpretation == "MONOCHROME2") + interpr = EPI_Monochrome2; + else if (photometricInterpretation == "YBR_FULL") + interpr = EPI_YBR_Full; + // some photometric interpretations are not supported: + else if ( (photometricInterpretation == "YBR_FULL_422") || + (photometricInterpretation == "YBR_PARTIAL_422") || + (photometricInterpretation == "YBR_PARTIAL_420") || + (photometricInterpretation == "YBR_ICT") || + (photometricInterpretation == "YBR_RCT") ) + { + DCMJPEG_ERROR("True lossless encoder: Photometric interpretation not supported: " << photometricInterpretation); + return EC_IllegalParameter; + } + else // Palette, HSV, ARGB, CMYK + interpr = EPI_Unknown; + + // IJG libs need "color by pixel", transform if required + if (result.good() && (samplesPerPixel > 1) ) + { + result = datsetItem->findAndGetUint16(DCM_PlanarConfiguration, planarConfiguration); + if ( result.good() && (planarConfiguration == 1) ) + { + if (bytesAllocated == 1) + result = togglePlanarConfiguration8(OFreinterpret_cast(Uint8*, OFconst_cast(Uint16*, pixelData)), length, samplesPerPixel, OFstatic_cast(Uint16, 1) /* switch to "by pixel"*/); + else + result = togglePlanarConfiguration16(OFconst_cast(Uint16*, pixelData), length/2 /*16 bit*/, samplesPerPixel, OFstatic_cast(Uint16, 1) /* switch to "by pixel"*/); + planConfSwitched = OFTrue; + } + } + if (result.bad()) + { + DCMJPEG_ERROR("True lossless encoder: Unable to change Planar Configuration from 'by plane' to 'by pixel' for encoding"); + return result; + } + + // check whether enough raw data is available for encoding + if (bytesAllocated * samplesPerPixel * columns * rows * OFstatic_cast(size_t,numberOfFrames) > length) + { + DCMJPEG_ERROR("True lossless encoder: Cannot change representation, not enough data"); + return EC_CannotChangeRepresentation; + } + + // byte swap pixel data to little endian if bits allocated is 8 + if ((gLocalByteOrder == EBO_BigEndian) && (bitsAllocated == 8)) + { + result = swapIfNecessary(EBO_LittleEndian, gLocalByteOrder, OFconst_cast(Uint16*, pixelData), OFstatic_cast(Uint32, length), sizeof(Uint16)); + if ( result.bad() ) + { + DCMJPEG_ERROR("True lossless encoder: Unable to swap bytes to respect local byte ordering"); + return EC_CannotChangeRepresentation; + } + byteSwapped = OFTrue; + } + + // create initial pixel sequence with empty offset table + DcmPixelSequence *pixelSequence = NULL; + DcmPixelItem *offsetTable = NULL; + if (result.good()) + { + pixelSequence = new DcmPixelSequence(DCM_PixelSequenceTag); + if (pixelSequence == NULL) result = EC_MemoryExhausted; + else + { + // create empty offset table + offsetTable = new DcmPixelItem(DCM_PixelItemTag); + if (offsetTable == NULL) result = EC_MemoryExhausted; + else pixelSequence->insert(offsetTable); + } + } + + // prepare some variables for encoding + size_t frameCount = OFstatic_cast(size_t, numberOfFrames); + size_t frameSize = columns * rows * samplesPerPixel * bytesAllocated; + const Uint8 *framePointer = OFreinterpret_cast(const Uint8 *, pixelData); + size_t compressedSize = 0; + + // create encoder corresponding to bit depth (8 or 16 bit) + DJEncoder *jpeg = createEncoderInstance(toRepParam, djcp, OFstatic_cast(Uint8, bitsAllocated)); + if (jpeg) + { + // main loop for compression: compress each frame + for (unsigned int i=0; iencode(columns, rows, interpr, samplesPerPixel, OFconst_cast(Uint8*, framePointer), jpegData, jpegLen); + } + else if (bitsAllocated == 16) + { + jpeg->encode(columns, rows, interpr, samplesPerPixel, OFreinterpret_cast(Uint16*, OFconst_cast(Uint8*, framePointer)), jpegData, jpegLen); + } + // update variables + compressedSize+=jpegLen; + framePointer+=frameSize; + if (jpegLen == 0) + { + DCMJPEG_ERROR("True lossless encoder: Error encoding frame"); + result = EC_CannotChangeRepresentation; + } + else + { + result = pixelSequence->storeCompressedFrame(offsetList, jpegData, jpegLen, djcp->getFragmentSize()); + } + // free memory + delete[] jpegData; + } + } + else + { + DCMJPEG_ERROR("True lossless encoder: Cannot allocate encoder instance"); + result = EC_IllegalCall; + } + if (result.good()) + { + compressionRatio = OFstatic_cast(double, bytesAllocated * samplesPerPixel * columns * rows * numberOfFrames) / OFstatic_cast(double, compressedSize); + pixSeq = pixelSequence; + } + else + delete pixelSequence; + delete jpeg; // encoder no longer in use + + if ((result.good()) && (djcp->getCreateOffsetTable())) + { + // create offset table + result = offsetTable->createOffsetTable(offsetList); + } + + // the following operations do not affect the Image Pixel Module + // but other modules such as SOP Common. We only perform these + // changes if we're on the main level of the datsetItem, + // which should always identify itself as datsetItem, not as item. + + // update derivation description reflecting the JPEG compression applied + result = updateDerivationDescription(datsetItem, toRepParam, djcp, OFstatic_cast(Uint8, bitsAllocated), compressionRatio); + + if ( (datsetItem->ident() == EVR_dataset) && result.good() ) + { + // convert to Secondary Capture if requested by user. + // This method creates a new SOP class UID, so it should be executed + // after the call to newInstance() which creates a Source Image Sequence. + if ( djcp->getConvertToSC() || (djcp->getUIDCreation() == EUC_always) ) + { + if (djcp->getConvertToSC()) + { + result = DcmCodec::convertToSecondaryCapture(datsetItem); + } + // update image type (set to DERIVED) + if (result.good()) + result = DcmCodec::updateImageType(datsetItem); + if (result.good()) + result = DcmCodec::newInstance(OFreinterpret_cast(DcmItem*, datsetItem), "DCM", "121320", "Uncompressed predecessor"); + } + } + // switch _original_ pixel data back to "color by plane", if required + if (planConfSwitched) + { + if (bytesAllocated == 1) + result = togglePlanarConfiguration8(OFreinterpret_cast(Uint8*, OFconst_cast(Uint16*, pixelData)), length, samplesPerPixel, OFstatic_cast(Uint16, 0) /*switch to "by plane"*/); + else + result = togglePlanarConfiguration16(OFconst_cast(Uint16*, pixelData), length/2, samplesPerPixel, OFstatic_cast(Uint16, 0) /*switch to "by plane"*/); + if (result.good()) + { + // update Planar Configuration in dataset + result = updatePlanarConfiguration(datsetItem, 0 /* update to "by pixel" */); + } + else + { + DCMJPEG_ERROR("True lossless encoder: Cannot switch back to original planar configuration of the pixel data"); + result = EC_CannotChangeRepresentation; + } + } + // byte swap pixel data back to local endian if necessary + if (byteSwapped) + swapIfNecessary(gLocalByteOrder, EBO_LittleEndian, OFconst_cast(Uint16*, pixelData), OFstatic_cast(Uint32, length), sizeof(Uint16)); + } + return result; +} + + +void DJCodecEncoder::appendCompressionRatio( + OFString& arg, + double ratio) +{ + char buf[64]; + OFStandard::ftoa(buf, sizeof(buf), ratio, OFStandard::ftoa_uppercase, 0, 5); + arg += buf; +} + + +OFCondition DJCodecEncoder::updateLossyCompressionRatio( + DcmItem *dataset, + double ratio) const +{ + if (dataset == NULL) return EC_IllegalCall; + + // set Lossy Image Compression to "01" (see DICOM part 3, C.7.6.1.1.5) + OFCondition result = dataset->putAndInsertString(DCM_LossyImageCompression, "01"); + if (result.bad()) return result; + + // set Lossy Image Compression Ratio + OFString s; + const char *oldRatio = NULL; + if ((dataset->findAndGetString(DCM_LossyImageCompressionRatio, oldRatio)).good() && oldRatio) + { + s = oldRatio; + s += "\\"; + } + appendCompressionRatio(s, ratio); + + result = dataset->putAndInsertString(DCM_LossyImageCompressionRatio, s.c_str()); + if (result.bad()) return result; + + // count VM of lossy image compression ratio + size_t i; + size_t s_vm = 0; + size_t s_sz = s.size(); + for (i = 0; i < s_sz; ++i) + if (s[i] == '\\') ++s_vm; + + // set Lossy Image Compression Method + const char *oldMethod = NULL; + OFString m; + if ((dataset->findAndGetString(DCM_LossyImageCompressionMethod, oldMethod)).good() && oldMethod) + { + m = oldMethod; + m += "\\"; + } + + // count VM of lossy image compression method + size_t m_vm = 0; + size_t m_sz = m.size(); + for (i = 0; i < m_sz; ++i) + if (m[i] == '\\') ++m_vm; + + // make sure that VM of Compression Method is not smaller than VM of Compression Ratio + while (m_vm++ < s_vm) m += "\\"; + + m += "ISO_10918_1"; + return dataset->putAndInsertString(DCM_LossyImageCompressionMethod, m.c_str()); +} + + +OFCondition DJCodecEncoder::updateDerivationDescription( + DcmItem *dataset, + const DcmRepresentationParameter * toRepParam, + const DJCodecParameter *cp, + Uint8 bitsPerSample, + double ratio) const +{ + OFString derivationDescription; + + // create new Derivation Description + createDerivationDescription(toRepParam, cp, bitsPerSample, ratio, derivationDescription); + + // append old Derivation Description, if any + const char *oldDerivation = NULL; + if ((dataset->findAndGetString(DCM_DerivationDescription, oldDerivation)).good() && oldDerivation) + { + derivationDescription += " ["; + derivationDescription += oldDerivation; + derivationDescription += "]"; + if (derivationDescription.length() > 1024) + { + // ST is limited to 1024 characters, cut off tail + derivationDescription.erase(1020); + derivationDescription += "...]"; + } + } + + OFCondition result = dataset->putAndInsertString(DCM_DerivationDescription, derivationDescription.c_str()); + if (result.good()) + { + // assume we can cast the codec parameter to what we need + DJCodecParameter *djcp = OFconst_cast(DJCodecParameter*, cp); + + if (djcp->getTrueLosslessMode()) + result = DcmCodec::insertCodeSequence(dataset, DCM_DerivationCodeSequence, "DCM", "121327", "Full fidelity image"); + else // pseudo-lossless mode may also result in lossy compression + result = DcmCodec::insertCodeSequence(dataset, DCM_DerivationCodeSequence, "DCM", "113040", "Lossy Compression"); + } + return result; +} + + +OFCondition DJCodecEncoder::adjustOverlays( + DcmItem *dataset, + DicomImage& image) const +{ + if (dataset == NULL) return EC_IllegalCall; + + unsigned int overlayCount = image.getOverlayCount(); + if (overlayCount > 0) + { + Uint16 group = 0; + DcmStack stack; + size_t bytesAllocated = 0; + Uint8 *buffer = NULL; + unsigned int width = 0; + unsigned int height = 0; + long unsigned int frames = 0; + DcmElement *elem = NULL; + OFCondition result = EC_Normal; + + // adjust overlays (prior to grayscale compression) + for (unsigned int i=0; i < overlayCount; i++) + { + // check if current overlay is embedded in pixel data + group = OFstatic_cast(Uint16, image.getOverlayGroupNumber(i)); + stack.clear(); + if ((dataset->search(DcmTagKey(group, 0x3000), stack, ESM_fromHere, OFFalse)).bad()) + { + // separate Overlay Data not found. Assume overlay is embedded. + bytesAllocated = image.create6xxx3000OverlayData(buffer, i, width, height, frames); + if (bytesAllocated > 0) + { + elem = new DcmOverlayData(DcmTagKey(group, 0x3000)); // DCM_OverlayData + if (elem) + { + result = elem->putUint8Array(buffer, OFstatic_cast(Uint32, bytesAllocated)); + delete[] buffer; + if (result.good()) + { + dataset->insert(elem, OFTrue /*replaceOld*/); + // DCM_OverlayBitsAllocated + result = dataset->putAndInsertUint16(DcmTagKey(group, 0x0100), 1); + // DCM_OverlayBitPosition + if (result.good()) result = dataset->putAndInsertUint16(DcmTagKey(group, 0x0102), 0); + } + else + { + delete elem; + return result; + } + } + else + { + delete[] buffer; + return EC_MemoryExhausted; + } + } + else return EC_IllegalCall; + } + } + } + return EC_Normal; +} + + +OFCondition DJCodecEncoder::encodeMonochromeImage( + DcmItem *dataset, + const DcmRepresentationParameter * toRepParam, + DcmPixelSequence * & pixSeq, + const DJCodecParameter *cp, + double& compressionRatio) const +{ + OFCondition result = EC_Normal; + DcmOffsetList offsetList; + DcmPixelSequence *pixelSequence = NULL; + DcmPixelItem *offsetTable = NULL; + unsigned short bitsPerSample = 0; + compressionRatio = 0.0; // initialize if something goes wrong + size_t compressedSize = 0; + double uncompressedSize = 0.0; + size_t flags = 0; // flags for initialization of DicomImage + + // variables needed if VOI mode is 0 + double minRange = 0.0; + double maxRange = 0.0; + double minUsed = 0.0; + double maxUsed = 0.0; + double rescaleSlope = 1.0; + double rescaleIntercept = 0.0; + double voiFactor = 1.0; + double voiOffset = 0.0; + double windowCenter = 0.0; + double windowWidth = 0.0; + OFBool deleteVOILUT = OFFalse; + OFBool mode_XA = OFFalse; // true if the current SOP class uses the X-Ray Image Module + OFBool mode_CT = OFFalse; // true if the current SOP class uses the CT Image Module + + // Modes of operation (if VOI mode is 0) + OFBool mode_usePixelValues = cp->getUsePixelValues(); + OFBool mode_useModalityRescale = cp->getUseModalityRescale(); + + //create flags for DicomImage corresponding to DJCodecParameter options + if (cp->getAcceptWrongPaletteTags()) + flags |= CIF_WrongPaletteAttributeTags; + if (cp->getAcrNemaCompatibility()) + flags |= CIF_AcrNemaCompatibility; + + // create DicomImage object. Will fail if dcmimage has not been activated in main(). + // transfer syntax can be any uncompressed one. + DicomImage dimage(dataset, EXS_LittleEndianImplicit, flags); // read all frames + if (dimage.getStatus() != EIS_Normal) result = EC_IllegalCall; // should return dimage.getStatus() + + // don't render overlays + dimage.hideAllOverlays(); + + // actual pixel depth of source image which can be different from Bits Stored + // e. g. when Modality LUT (if enabled) shifts pixel values to a smaller + // range or if the pixel values itself do not make use of the "Bits Stored" + // full range available. + int pixelDepth = dimage.getDepth(); + + // create overlay data for embedded overlays + if (result.good()) result = adjustOverlays(dataset, dimage); + + // VOI transformations should only be applied on the dataset level, not + // in nested items such as the Icon Image Sequence where we don't exect + // a VOI window or LUT to be present + size_t windowType = 0; + if (dataset->ident() == EVR_dataset) + { + windowType = cp->getWindowType(); + } + + // set VOI transformation + if (result.good()) + { + switch (windowType) + { + case 0: // no VOI transformation + { + // disable correction of polarity or any other presentation LUT transformation + dimage.setPresentationLutShape(ESP_Identity); + + // disable VOI transformation + dimage.setNoVoiTransformation(); + + // look up SOP Class UID, if any + const char *classUID = NULL; + dataset->findAndGetString(DCM_SOPClassUID, classUID); + + // SOP Class specifics. + if (classUID && ! cp->getConvertToSC()) + { + // these three SOP classes use the X-Ray Image Module in which the meaning + // of the Modality LUT transformation is "inversersed" and, therefore, + // needs special handling. This is not an issue if we're converting to + // secondary capture anyway. + if ((0 == strcmp(classUID, UID_XRayAngiographicImageStorage)) || + (0 == strcmp(classUID, UID_XRayRadiofluoroscopicImageStorage)) || + (0 == strcmp(classUID, UID_RETIRED_XRayAngiographicBiPlaneImageStorage))) + { + mode_XA = OFTrue; + mode_useModalityRescale = OFFalse; // inverse definition of Modality LUT Module + } + + // CT is also a special case because the Modality LUT is required here + // to convert to Hounsfield units. Again, this is not an issue if we're + // converting to SC anyway. + if (0 == strcmp(classUID, UID_CTImageStorage)) + { + mode_CT = OFTrue; + mode_useModalityRescale = OFTrue; // required for Hounsfield units + } + } + + // query image range and extreme values + if (result.good()) + { + // technically possible min/max values + if (! dimage.getMinMaxValues(minRange, maxRange, 1)) result = EC_IllegalCall; + if (maxRange <= minRange) result = EC_IllegalCall; + } + + if (result.good()) + { + // actually present min/max values in pixel data + if (! dimage.getMinMaxValues(minUsed, maxUsed, 0)) result = EC_IllegalCall; + if (maxUsed < minUsed) result = EC_IllegalCall; + } + } + break; + case 1: // use the n-th VOI window from the image file + { + size_t windowParameter = cp->getWindowParameter(); + if ((windowParameter < 1) || (windowParameter > dimage.getWindowCount())) result = EC_IllegalCall; + if (!dimage.setWindow(windowParameter - 1)) result = EC_IllegalCall; + } + break; + case 2: // use the n-th VOI look up table from the image file + { + size_t windowParameter = cp->getWindowParameter(); + if ((windowParameter < 1) || (windowParameter > dimage.getVoiLutCount())) result = EC_IllegalCall; + if (!dimage.setVoiLut(windowParameter - 1)) result = EC_IllegalCall; + } + break; + case 3: // Compute VOI window using min-max algorithm + if (!dimage.setMinMaxWindow(0)) result = EC_IllegalCall; + break; + case 4: // Compute VOI window using Histogram algorithm, ignoring n percent + { + size_t windowParameter = cp->getWindowParameter(); + if (!dimage.setHistogramWindow(OFstatic_cast(double, windowParameter)/100.0)) result = EC_IllegalCall; + } + break; + case 5: // Compute VOI window using center r and width s + { + double winCenter=0.0, winWidth=0.0; + cp->getVOIWindow(winCenter, winWidth); + if (!dimage.setWindow(winCenter, winWidth)) result = EC_IllegalCall; + } + break; + case 6: // Compute VOI window using min-max algorithm ignoring extremes + if (!dimage.setMinMaxWindow(1)) result = EC_IllegalCall; + break; + case 7: // Compute region of interest VOI window + { + size_t left_pos=0, top_pos=0, width=0, height=0; + cp->getROI(left_pos, top_pos, width, height); + if (!dimage.setRoiWindow(left_pos, top_pos, width, height)) result = EC_IllegalCall; + } + break; + default: // includes case 0, which must not occur here + result = EC_IllegalCall; + break; + } + } + + // create initial pixel sequence + if (result.good()) + { + pixelSequence = new DcmPixelSequence(DCM_PixelSequenceTag); + if (pixelSequence == NULL) result = EC_MemoryExhausted; + else + { + // create empty offset table + offsetTable = new DcmPixelItem(DCM_PixelItemTag); + if (offsetTable == NULL) result = EC_MemoryExhausted; + else pixelSequence->insert(offsetTable); + } + } + + // select bit depth + Uint16 compressedBits = OFstatic_cast(Uint16, cp->getForcedBitDepth()); + if (result.good()) + { + if (compressedBits == 0) + { + result = OFreinterpret_cast(DcmItem*, dataset)->findAndGetUint16(DCM_BitsStored, compressedBits); + } + } + + // create codec instance + if (result.good()) + { + DJEncoder *jpeg = createEncoderInstance(toRepParam, cp, OFstatic_cast(Uint8, compressedBits)); + if (jpeg) + { + bitsPerSample = jpeg->bitsPerSample(); + + if (windowType == 0) + { + // perform image computations + if (mode_usePixelValues) + { + double z = minUsed; + if (z >= 0) z = floor(z); else z = ceil(z-1023.0); + double rangeUsed = maxUsed - minUsed + 1; // range that must be covered by window + + // compute optimum window width + if (pixelDepth < bitsPerSample) windowWidth = 1 << pixelDepth; + else windowWidth = 1 << bitsPerSample; + while (windowWidth < rangeUsed) windowWidth *= 2; + + windowCenter = windowWidth * 0.5; + if ((z + windowWidth) > maxUsed) windowCenter += z; else windowCenter += minUsed; + dimage.setWindow(windowCenter, windowWidth); + } + + // perform image computations + if (mode_useModalityRescale) + { + // Use Rescale Slope/Intercept to map the decompressed image data + // back to the original value range, keeping all VOI transformations valid. + if (mode_usePixelValues) + { + rescaleSlope = (windowWidth-1)/((1<bytesPerSample(); + unsigned short columns = OFstatic_cast(unsigned short, dimage.getWidth()); + unsigned short rows = OFstatic_cast(unsigned short, dimage.getHeight()); + Uint8 *jpegData = NULL; + Uint32 jpegLen = 0; + const void *frame = NULL; + + // compute original image size in bytes, ignoring any padding bits. + Uint16 samplesPerPixel = 0; + if ((dataset->findAndGetUint16(DCM_SamplesPerPixel, samplesPerPixel)).bad()) samplesPerPixel = 1; + uncompressedSize = OFstatic_cast(double, columns * rows * pixelDepth * frameCount * samplesPerPixel) / 8.0; + for (size_t i=0; (iencode(columns, rows, EPI_Monochrome2, 1, OFreinterpret_cast(Uint8*, OFconst_cast(void*, frame)), jpegData, jpegLen); + } else { + result = jpeg->encode(columns, rows, EPI_Monochrome2, 1, OFreinterpret_cast(Uint16*, OFconst_cast(void*, frame)), jpegData, jpegLen); + } + + // store frame + if (result.good()) + { + result = pixelSequence->storeCompressedFrame(offsetList, jpegData, jpegLen, cp->getFragmentSize()); + } + + // delete block of JPEG data + delete[] jpegData; + compressedSize += jpegLen; + } + } + delete jpeg; + } else result = EC_MemoryExhausted; + } + + // store pixel sequence if everything went well. + if (result.good()) pixSeq = pixelSequence; + else + { + delete pixelSequence; + pixSeq = NULL; + } + + if ((result.good()) && (cp->getCreateOffsetTable())) + { + // create offset table + result = offsetTable->createOffsetTable(offsetList); + } + + if (result.good()) + { + // adapt attributes in image pixel module + if (result.good()) result = dataset->putAndInsertUint16(DCM_SamplesPerPixel, 1); + if (result.good() && (windowType != 0)) result = dataset->putAndInsertString(DCM_PhotometricInterpretation, "MONOCHROME2"); + if (result.good()) + { + if (bitsPerSample > 8) + result = dataset->putAndInsertUint16(DCM_BitsAllocated, 16); + else + result = dataset->putAndInsertUint16(DCM_BitsAllocated, 8); + } + if (result.good()) result = dataset->putAndInsertUint16(DCM_BitsStored, bitsPerSample); + if (result.good()) result = dataset->putAndInsertUint16(DCM_HighBit, OFstatic_cast(Uint16, bitsPerSample-1)); + if (result.good()) result = dataset->putAndInsertUint16(DCM_PixelRepresentation, 0); + delete dataset->remove(DCM_PlanarConfiguration); + delete dataset->remove(DCM_SmallestImagePixelValue); + delete dataset->remove(DCM_LargestImagePixelValue); + delete dataset->remove(DCM_RedPaletteColorLookupTableDescriptor); + delete dataset->remove(DCM_GreenPaletteColorLookupTableDescriptor); + delete dataset->remove(DCM_BluePaletteColorLookupTableDescriptor); + delete dataset->remove(DCM_RedPaletteColorLookupTableData); + delete dataset->remove(DCM_GreenPaletteColorLookupTableData); + delete dataset->remove(DCM_BluePaletteColorLookupTableData); + delete dataset->remove(DCM_PixelPaddingValue); + delete dataset->remove(DCM_SmallestPixelValueInSeries); + delete dataset->remove(DCM_LargestPixelValueInSeries); + delete dataset->remove(DCM_PaletteColorLookupTableUID); + delete dataset->remove(DCM_SegmentedRedPaletteColorLookupTableData); + delete dataset->remove(DCM_SegmentedGreenPaletteColorLookupTableData); + delete dataset->remove(DCM_SegmentedBluePaletteColorLookupTableData); + + // check if either Modality LUT Sequence or Rescale Slope are present + DcmStack stack; + OFBool foundModalityLUT = OFFalse; + if ((dataset->search(DCM_ModalityLUTSequence, stack, ESM_fromHere, OFFalse)).good()) foundModalityLUT = OFTrue; + if (! foundModalityLUT) + { + stack.clear(); + if ((dataset->search(DCM_RescaleSlope, stack, ESM_fromHere, OFFalse)).good()) foundModalityLUT = OFTrue; + } + + // delete old Modality transformation + delete dataset->remove(DCM_ModalityLUTSequence); + delete dataset->remove(DCM_RescaleIntercept); + delete dataset->remove(DCM_RescaleSlope); + delete dataset->remove(DCM_RescaleType); + + // update Modality LUT Module and Pixel Intensity Relationship + if (windowType == 0) + { + if (mode_XA) // XA needs special handling + { + // XA Mode: set Pixel Intensity Relationship to "DISP", no Modality LUT + if (result.good()) result = dataset->putAndInsertString(DCM_PixelIntensityRelationship, "DISP"); + } + /* else if we had a modality LUT before, a LUT is inserted again. + or if specific rescale slope/intercept has been computed, use that in image + */ + else if (foundModalityLUT || rescaleSlope != 1.0 || rescaleIntercept != 0.0) + { + char buf[64]; + OFStandard::ftoa(buf, sizeof(buf), rescaleIntercept, OFStandard::ftoa_uppercase, 0, 6); + if (result.good()) result = dataset->putAndInsertString(DCM_RescaleIntercept, buf); + OFStandard::ftoa(buf, sizeof(buf), rescaleSlope, OFStandard::ftoa_uppercase, 0, 6); + if (result.good()) result = dataset->putAndInsertString(DCM_RescaleSlope, buf); + if (result.good()) + { + if (mode_CT) result = dataset->putAndInsertString(DCM_RescaleType, "HU"); // Hounsfield units + else result = dataset->putAndInsertString(DCM_RescaleType, "US"); // unspecified + } + } + } + else + { + // if we had found a Modality LUT Transformation, create a identity LUT transformation + if (foundModalityLUT) + { + if (result.good()) result = dataset->putAndInsertString(DCM_RescaleIntercept, "0"); + if (result.good()) result = dataset->putAndInsertString(DCM_RescaleSlope, "1"); + if (result.good()) result = dataset->putAndInsertString(DCM_RescaleType, "US"); // unspecified + } + + // Adjust Pixel Intensity Relationship (needed for XA). If present, set value to "DISP". + stack.clear(); + if ((dataset->search(DCM_PixelIntensityRelationship, stack, ESM_fromHere, OFFalse)).good()) + { + if (result.good()) result = dataset->putAndInsertString(DCM_PixelIntensityRelationship, "DISP"); + } + } + + // Adjust VOI LUT and Presentation LUT transformation + if (windowType == 0) + { + if (deleteVOILUT) delete dataset->remove(DCM_VOILUTSequence); + + // Adjust window center/width + if (result.good()) result = correctVOIWindows(dataset, voiOffset, voiFactor); + + // Don't modify Presentation LUT transformations (if any) + } + else + { + delete dataset->remove(DCM_VOILUTSequence); + delete dataset->remove(DCM_WindowCenter); + delete dataset->remove(DCM_WindowWidth); + delete dataset->remove(DCM_WindowCenterWidthExplanation); + + // Adjust Presentation LUT Transformation. + stack.clear(); + OFBool foundPresentationLUT = OFFalse; + if ((dataset->search(DCM_PresentationLUTSequence, stack, ESM_fromHere, OFFalse)).good()) foundPresentationLUT = OFTrue; + if (! foundPresentationLUT) + { + stack.clear(); + if ((dataset->search(DCM_PresentationLUTShape, stack, ESM_fromHere, OFFalse)).good()) foundPresentationLUT = OFTrue; + } + + // delete old Presentation LUT transformation + delete dataset->remove(DCM_PresentationLUTSequence); + delete dataset->remove(DCM_PresentationLUTShape); + + // if we had found a Presentation LUT Transformation, create a new identity transformation + if (foundPresentationLUT) + { + if (result.good()) result = dataset->putAndInsertString(DCM_PresentationLUTShape, "IDENTITY"); + } + } + } + + // determine compression ratio + if (compressedSize > 0) compressionRatio = OFstatic_cast(double, uncompressedSize) / OFstatic_cast(double, compressedSize); + return result; +} + + +OFCondition DJCodecEncoder::correctVOIWindows( + DcmItem *dataset, + double voiOffset, + double voiFactor) +{ + if (voiOffset == 0.0 && voiFactor == 1.0) return EC_Normal; + + OFCondition result = EC_Normal; + DcmElement *center = NULL; + DcmElement *width = NULL; + DcmElement *explanation = NULL; + + DcmStack stack; + if ((dataset->search(DCM_WindowCenter, stack, ESM_fromHere, OFFalse)).good()) + { + center = OFreinterpret_cast(DcmElement*, stack.top()); + } + stack.clear(); + if ((dataset->search(DCM_WindowWidth, stack, ESM_fromHere, OFFalse)).good()) + { + width = OFreinterpret_cast(DcmElement*, stack.top()); + } + stack.clear(); + if ((dataset->search(DCM_WindowCenterWidthExplanation, stack, ESM_fromHere, OFFalse)).good()) + { + explanation = OFreinterpret_cast(DcmElement*, stack.top()); + } + + OFString newCenter; + OFString newWidth; + OFString newExplanation; + Float64 currentCenter = 0.0; + Float64 currentWidth = 0.0; + OFString currentExplanation; + double tempCenter = 0.0; + double tempWidth = 0.0; + char buf[64]; + + if (center && width) + { + size_t numWindows = center->getVM(); + // iterate over all defined VOI windows + for (size_t i=0; igetFloat64(currentCenter,OFstatic_cast(Uint32, i))).good()) && ((width->getFloat64(currentWidth,OFstatic_cast(Uint32, i))).good())) + { + // found one pair of values, adapt them to value range shifted pixel data + tempCenter = (currentCenter+voiOffset)*voiFactor; + tempWidth = currentWidth * voiFactor; + // add this window to the attribute values that are later replacing old windows + OFStandard::ftoa(buf, sizeof(buf), tempCenter, OFStandard::ftoa_uppercase, 0, 6); + if (!newCenter.empty()) newCenter += "\\"; + newCenter += buf; + OFStandard::ftoa(buf, sizeof(buf), tempWidth, OFStandard::ftoa_uppercase, 0, 6); + if (!newWidth.empty()) newWidth += "\\"; + newWidth += buf; + + if (!newExplanation.empty()) newExplanation += "\\"; + if (explanation && ((explanation->getOFString(currentExplanation,OFstatic_cast(Uint32, i))).good())) + newExplanation += currentExplanation; + else + { + newExplanation += "center="; + OFStandard::ftoa(buf, sizeof(buf), tempCenter, OFStandard::ftoa_uppercase, 0, 6); + newExplanation += buf; + newExplanation += "/width="; + OFStandard::ftoa(buf, sizeof(buf), tempWidth, OFStandard::ftoa_uppercase, 0, 6); + newExplanation += buf; + } + } + } + } + + // remove old windows + delete dataset->remove(DCM_WindowCenter); + delete dataset->remove(DCM_WindowWidth); + delete dataset->remove(DCM_WindowCenterWidthExplanation); + + // and insert newly computed ones if necessary + if (!newCenter.empty()) + { + if (result.good()) result = dataset->putAndInsertString(DCM_WindowCenter, newCenter.c_str()); + if (result.good()) result = dataset->putAndInsertString(DCM_WindowWidth, newWidth.c_str()); + if (result.good()) result = dataset->putAndInsertString(DCM_WindowCenterWidthExplanation, newExplanation.c_str()); + } + + return result; +} + + +OFCondition DJCodecEncoder::togglePlanarConfiguration8( + Uint8 *pixelData, + const size_t numValues, + const Uint16 samplesPerPixel, + const Uint16 oldPlanarConfig) +{ + if ( (pixelData == NULL) || (numValues%samplesPerPixel != 0) ) + return EC_IllegalParameter; + // allocate target buffer + Uint8* px8 = new Uint8[numValues]; + if (!px8) + return EC_MemoryExhausted; + size_t numPixels = numValues / samplesPerPixel; + if (oldPlanarConfig == 1) // change from "by plane" to "by pixel" + { + for (size_t n=0; n < numPixels; n++) + { + for (Uint16 s=0; s < samplesPerPixel; s++) + px8[n*samplesPerPixel+s] = pixelData[n+numPixels*s]; + } + } + else //change from "by pixel" to "by plane" + { + for (size_t n=0; n < numPixels; n++) + { + for (Uint16 s=0; s < samplesPerPixel; s++) + px8[n+numPixels*s] = pixelData[n*samplesPerPixel+s]; + } + } + // copy filled buffer to pixel data and free memory + memcpy(pixelData, px8, OFstatic_cast(size_t, numValues)); + delete[] px8; + return EC_Normal; +} + + +OFCondition DJCodecEncoder::togglePlanarConfiguration16( + Uint16 *pixelData, + const size_t numValues, //number of 16-bit components + const Uint16 samplesPerPixel, + const Uint16 oldPlanarConfig) +{ + if ( (pixelData == NULL) || (numValues%samplesPerPixel != 0) ) + return EC_IllegalParameter; + // allocate target buffer + Uint16* px16 = new Uint16[numValues]; + if (!px16) + return EC_MemoryExhausted; + size_t numPixels = numValues / samplesPerPixel; + if (oldPlanarConfig == 1) // change from "by plane" to "by pixel" + { + for (size_t n=0; n < numPixels; n++) + { + for (Uint16 s=0; s < samplesPerPixel; s++) + px16[n*samplesPerPixel+s] = pixelData[n+numPixels*s]; + } + } + else //change from "by pixel" to "by plane" + { + for (size_t n=0; n < numPixels; n++) + { + for (Uint16 s=0; s < samplesPerPixel; s++) + px16[n+numPixels*s] = pixelData[n*samplesPerPixel+s]; + } + } + // copy filled buffer to pixel data and free memory + memcpy(pixelData, px16, OFstatic_cast(size_t, numValues*2)); + delete[] px16; + return EC_Normal; +} + + +OFCondition DJCodecEncoder::updatePlanarConfiguration( + DcmItem *item, + const Uint16 newPlanConf) const +{ + if ( (item == NULL) || (newPlanConf) > 1) + return EC_IllegalParameter; + return item->putAndInsertUint16(DCM_PlanarConfiguration, newPlanConf); +} diff --git a/dcmjpeg/libsrc/djcparam.cc b/dcmjpeg/libsrc/djcparam.cc new file mode 100644 index 00000000..37bc442b --- /dev/null +++ b/dcmjpeg/libsrc/djcparam.cc @@ -0,0 +1,126 @@ +/* + * + * Copyright (C) 1997-2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmjpeg + * + * Author: Norbert Olges, Marco Eichelberg + * + * Purpose: codec parameter class for dcmjpeg codecs + * + */ + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmjpeg/djcparam.h" + +DJCodecParameter::DJCodecParameter( + E_CompressionColorSpaceConversion pCompressionCSConversion, + E_DecompressionColorSpaceConversion pDecompressionCSConversion, + E_UIDCreation pCreateSOPInstanceUID, + E_PlanarConfiguration pPlanarConfiguration, + OFBool predictor6WorkaroundEnable, + OFBool pOptimizeHuffman, + int pSmoothingFactor, + int pForcedBitDepth, + Uint32 pFragmentSize, + OFBool pCreateOffsetTable, + E_SubSampling pSampleFactors, + OFBool pWriteYBR422, + OFBool pConvertToSC, + size_t pWindowType, + size_t pWindowParameter, + double pVoiCenter, + double pVoiWidth, + size_t pRoiLeft, + size_t pRoiTop, + size_t pRoiWidth, + size_t pRoiHeight, + OFBool pUsePixelValues, + OFBool pUseModalityRescale, + OFBool pAcceptWrongPaletteTags, + OFBool pAcrNemaCompatibility, + OFBool pTrueLosslessMode) +: DcmCodecParameter() +, compressionCSConversion(pCompressionCSConversion) +, decompressionCSConversion(pDecompressionCSConversion) +, planarConfiguration(pPlanarConfiguration) +, optimizeHuffman(pOptimizeHuffman) +, smoothingFactor(pSmoothingFactor) +, forcedBitDepth(pForcedBitDepth) +, fragmentSize(pFragmentSize) +, createOffsetTable(pCreateOffsetTable) +, sampleFactors(pSampleFactors) +, writeYBR422(pWriteYBR422) +, convertToSC(pConvertToSC) +, uidCreation(pCreateSOPInstanceUID) +, windowType(pWindowType) +, windowParameter(pWindowParameter) +, voiCenter(pVoiCenter) +, voiWidth(pVoiWidth) +, roiLeft(pRoiLeft) +, roiTop(pRoiTop) +, roiWidth(pRoiWidth) +, roiHeight(pRoiHeight) +, usePixelValues(pUsePixelValues) +, useModalityRescale(pUseModalityRescale) +, acceptWrongPaletteTags(pAcceptWrongPaletteTags) +, acrNemaCompatibility(pAcrNemaCompatibility) +, trueLosslessMode(pTrueLosslessMode) +, predictor6WorkaroundEnabled_(predictor6WorkaroundEnable) +{ +} + + +DJCodecParameter::DJCodecParameter(const DJCodecParameter& arg) +: DcmCodecParameter(arg) +, compressionCSConversion(arg.compressionCSConversion) +, decompressionCSConversion(arg.decompressionCSConversion) +, planarConfiguration(arg.planarConfiguration) +, optimizeHuffman(arg.optimizeHuffman) +, smoothingFactor(arg.smoothingFactor) +, forcedBitDepth(arg.forcedBitDepth) +, fragmentSize(arg.fragmentSize) +, createOffsetTable(arg.createOffsetTable) +, sampleFactors(arg.sampleFactors) +, writeYBR422(arg.writeYBR422) +, convertToSC(arg.convertToSC) +, uidCreation(arg.uidCreation) +, windowType(arg.windowType) +, windowParameter(arg.windowParameter) +, voiCenter(arg.voiCenter) +, voiWidth(arg.voiWidth) +, roiLeft(arg.roiLeft) +, roiTop(arg.roiTop) +, roiWidth(arg.roiWidth) +, roiHeight(arg.roiHeight) +, usePixelValues(arg.usePixelValues) +, useModalityRescale(arg.useModalityRescale) +, acceptWrongPaletteTags(arg.acceptWrongPaletteTags) +, acrNemaCompatibility(arg.acrNemaCompatibility) +, trueLosslessMode(arg.trueLosslessMode) +, predictor6WorkaroundEnabled_(arg.predictor6WorkaroundEnabled_) +{ +} + +DJCodecParameter::~DJCodecParameter() +{ +} + +DcmCodecParameter *DJCodecParameter::clone() const +{ + return new DJCodecParameter(*this); +} + +const char *DJCodecParameter::className() const +{ + return "DJCodecParameter"; +} diff --git a/dcmjpeg/libsrc/djdecbas.cc b/dcmjpeg/libsrc/djdecbas.cc new file mode 100644 index 00000000..19bfa67c --- /dev/null +++ b/dcmjpeg/libsrc/djdecbas.cc @@ -0,0 +1,54 @@ +/* + * + * Copyright (C) 2001-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmjpeg + * + * Author: Marco Eichelberg, Norbert Olges + * + * Purpose: Codec class for decoding JPEG Baseline (lossy, 8-bit) + * + */ + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmjpeg/djdecbas.h" +#include "dcmtk/dcmjpeg/djcparam.h" +#include "dcmtk/dcmjpeg/djrploss.h" + +#include "dcmtk/dcmjpeg/djdijg8.h" + + +DJDecoderBaseline::DJDecoderBaseline() +: DJCodecDecoder() +{ +} + + +DJDecoderBaseline::~DJDecoderBaseline() +{ +} + + +E_TransferSyntax DJDecoderBaseline::supportedTransferSyntax() const +{ + return EXS_JPEGProcess1; +} + + +DJDecoder *DJDecoderBaseline::createDecoderInstance( + const DcmRepresentationParameter * /* toRepParam */, + const DJCodecParameter *cp, + Uint8 /* bitsPerSample */, + OFBool isYBR) const +{ + return new DJDecompressIJG8Bit(*cp, isYBR); +} diff --git a/dcmjpeg/libsrc/djdecext.cc b/dcmjpeg/libsrc/djdecext.cc new file mode 100644 index 00000000..7efd99cb --- /dev/null +++ b/dcmjpeg/libsrc/djdecext.cc @@ -0,0 +1,55 @@ +/* + * + * Copyright (C) 2001-2010, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmjpeg + * + * Author: Marco Eichelberg, Norbert Olges + * + * Purpose: Codec class for decoding JPEG Extended Sequential (lossy, 8/12-bit) + * + */ + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmjpeg/djdecext.h" +#include "dcmtk/dcmjpeg/djcparam.h" +#include "dcmtk/dcmjpeg/djrploss.h" +#include "dcmtk/dcmjpeg/djdijg8.h" +#include "dcmtk/dcmjpeg/djdijg12.h" + + +DJDecoderExtended::DJDecoderExtended() +: DJCodecDecoder() +{ +} + + +DJDecoderExtended::~DJDecoderExtended() +{ +} + + +E_TransferSyntax DJDecoderExtended::supportedTransferSyntax() const +{ + return EXS_JPEGProcess2_4; +} + + +DJDecoder *DJDecoderExtended::createDecoderInstance( + const DcmRepresentationParameter * /* toRepParam */, + const DJCodecParameter *cp, + Uint8 bitsPerSample, + OFBool isYBR) const +{ + if (bitsPerSample > 8) return new DJDecompressIJG12Bit(*cp, isYBR); + else return new DJDecompressIJG8Bit(*cp, isYBR); +} diff --git a/dcmjpeg/libsrc/djdeclol.cc b/dcmjpeg/libsrc/djdeclol.cc new file mode 100644 index 00000000..0d5f49ac --- /dev/null +++ b/dcmjpeg/libsrc/djdeclol.cc @@ -0,0 +1,56 @@ +/* + * + * Copyright (C) 2001-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmjpeg + * + * Author: Marco Eichelberg, Norbert Olges + * + * Purpose: Codec class for decoding JPEG Lossless (8/12/16-bit) + * + */ + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmjpeg/djdeclol.h" +#include "dcmtk/dcmjpeg/djcparam.h" +#include "dcmtk/dcmjpeg/djrplol.h" +#include "dcmtk/dcmjpeg/djdijg8.h" +#include "dcmtk/dcmjpeg/djdijg12.h" +#include "dcmtk/dcmjpeg/djdijg16.h" + +DJDecoderLossless::DJDecoderLossless() +: DJCodecDecoder() +{ +} + + +DJDecoderLossless::~DJDecoderLossless() +{ +} + + +E_TransferSyntax DJDecoderLossless::supportedTransferSyntax() const +{ + return EXS_JPEGProcess14; +} + + +DJDecoder *DJDecoderLossless::createDecoderInstance( + const DcmRepresentationParameter * /* toRepParam */, + const DJCodecParameter *cp, + Uint8 bitsPerSample, + OFBool isYBR) const +{ + if (bitsPerSample > 12) return new DJDecompressIJG16Bit(*cp, isYBR); + else if (bitsPerSample > 8) return new DJDecompressIJG12Bit(*cp, isYBR); + else return new DJDecompressIJG8Bit(*cp, isYBR); +} diff --git a/dcmjpeg/libsrc/djdecode.cc b/dcmjpeg/libsrc/djdecode.cc new file mode 100644 index 00000000..80ae7933 --- /dev/null +++ b/dcmjpeg/libsrc/djdecode.cc @@ -0,0 +1,119 @@ +/* + * + * Copyright (C) 1997-2010, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmjpeg + * + * Author: Marco Eichelberg + * + * Purpose: singleton class that registers decoders for all supported JPEG processes. + * + */ + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmjpeg/djdecode.h" + +#include "dcmtk/dcmdata/dccodec.h" /* for DcmCodecStruct */ +#include "dcmtk/dcmjpeg/djdecbas.h" +#include "dcmtk/dcmjpeg/djdecext.h" +#include "dcmtk/dcmjpeg/djdecsps.h" +#include "dcmtk/dcmjpeg/djdecpro.h" +#include "dcmtk/dcmjpeg/djdecsv1.h" +#include "dcmtk/dcmjpeg/djdeclol.h" +#include "dcmtk/dcmjpeg/djcparam.h" + +// initialization of static members +OFBool DJDecoderRegistration::registered = OFFalse; +DJCodecParameter *DJDecoderRegistration::cp = NULL; +DJDecoderBaseline *DJDecoderRegistration::decbas = NULL; +DJDecoderExtended *DJDecoderRegistration::decext = NULL; +DJDecoderSpectralSelection *DJDecoderRegistration::decsps = NULL; +DJDecoderProgressive *DJDecoderRegistration::decpro = NULL; +DJDecoderP14SV1 *DJDecoderRegistration::decsv1 = NULL; +DJDecoderLossless *DJDecoderRegistration::declol = NULL; + +void DJDecoderRegistration::registerCodecs( + E_DecompressionColorSpaceConversion pDecompressionCSConversion, + E_UIDCreation pCreateSOPInstanceUID, + E_PlanarConfiguration pPlanarConfiguration, + OFBool predictor6WorkaroundEnable) +{ + if (! registered) + { + cp = new DJCodecParameter( + ECC_lossyYCbCr, // ignored, compression only + pDecompressionCSConversion, + pCreateSOPInstanceUID, + pPlanarConfiguration, + predictor6WorkaroundEnable); + if (cp) + { + // baseline JPEG + decbas = new DJDecoderBaseline(); + if (decbas) DcmCodecList::registerCodec(decbas, NULL, cp); + + // extended JPEG + decext = new DJDecoderExtended(); + if (decext) DcmCodecList::registerCodec(decext, NULL, cp); + + // spectral selection JPEG + decsps = new DJDecoderSpectralSelection(); + if (decsps) DcmCodecList::registerCodec(decsps, NULL, cp); + + // progressive JPEG + decpro = new DJDecoderProgressive(); + if (decpro) DcmCodecList::registerCodec(decpro, NULL, cp); + + // lossless SV1 JPEG + decsv1 = new DJDecoderP14SV1(); + if (decsv1) DcmCodecList::registerCodec(decsv1, NULL, cp); + + // lossless JPEG + declol = new DJDecoderLossless(); + if (declol) DcmCodecList::registerCodec(declol, NULL, cp); + + registered = OFTrue; + } + } +} + +void DJDecoderRegistration::cleanup() +{ + if (registered) + { + DcmCodecList::deregisterCodec(decbas); + delete decbas; + DcmCodecList::deregisterCodec(decext); + delete decext; + DcmCodecList::deregisterCodec(decsps); + delete decsps; + DcmCodecList::deregisterCodec(decpro); + delete decpro; + DcmCodecList::deregisterCodec(decsv1); + delete decsv1; + DcmCodecList::deregisterCodec(declol); + delete declol; + delete cp; + registered = OFFalse; +#ifdef DEBUG + // not needed but useful for debugging purposes + decbas = NULL; + decext = NULL; + decsps = NULL; + decpro = NULL; + decsv1 = NULL; + declol = NULL; + cp = NULL; +#endif + + } +} diff --git a/dcmjpeg/libsrc/djdecpro.cc b/dcmjpeg/libsrc/djdecpro.cc new file mode 100644 index 00000000..c99581a7 --- /dev/null +++ b/dcmjpeg/libsrc/djdecpro.cc @@ -0,0 +1,55 @@ +/* + * + * Copyright (C) 2001-2010, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmjpeg + * + * Author: Marco Eichelberg, Norbert Olges + * + * Purpose: Codec class for decoding JPEG Progressive (lossy, 8/12-bit) + * + */ + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmjpeg/djdecpro.h" +#include "dcmtk/dcmjpeg/djcparam.h" +#include "dcmtk/dcmjpeg/djrploss.h" +#include "dcmtk/dcmjpeg/djdijg8.h" +#include "dcmtk/dcmjpeg/djdijg12.h" + + +DJDecoderProgressive::DJDecoderProgressive() +: DJCodecDecoder() +{ +} + + +DJDecoderProgressive::~DJDecoderProgressive() +{ +} + + +E_TransferSyntax DJDecoderProgressive::supportedTransferSyntax() const +{ + return EXS_JPEGProcess10_12; +} + + +DJDecoder *DJDecoderProgressive::createDecoderInstance( + const DcmRepresentationParameter * /* toRepParam */, + const DJCodecParameter *cp, + Uint8 bitsPerSample, + OFBool isYBR) const +{ + if (bitsPerSample > 8) return new DJDecompressIJG12Bit(*cp, isYBR); + else return new DJDecompressIJG8Bit(*cp, isYBR); +} diff --git a/dcmjpeg/libsrc/djdecsps.cc b/dcmjpeg/libsrc/djdecsps.cc new file mode 100644 index 00000000..22bfbb7d --- /dev/null +++ b/dcmjpeg/libsrc/djdecsps.cc @@ -0,0 +1,55 @@ +/* + * + * Copyright (C) 2001-2010, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmjpeg + * + * Author: Marco Eichelberg + * + * Purpose: Codec class for decoding JPEG Spectral Selection (lossy, 8/12-bit) + * + */ + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmjpeg/djdecsps.h" +#include "dcmtk/dcmjpeg/djcparam.h" +#include "dcmtk/dcmjpeg/djrploss.h" +#include "dcmtk/dcmjpeg/djdijg8.h" +#include "dcmtk/dcmjpeg/djdijg12.h" + + +DJDecoderSpectralSelection::DJDecoderSpectralSelection() +: DJCodecDecoder() +{ +} + + +DJDecoderSpectralSelection::~DJDecoderSpectralSelection() +{ +} + + +E_TransferSyntax DJDecoderSpectralSelection::supportedTransferSyntax() const +{ + return EXS_JPEGProcess6_8; +} + + +DJDecoder *DJDecoderSpectralSelection::createDecoderInstance( + const DcmRepresentationParameter * /* toRepParam */, + const DJCodecParameter *cp, + Uint8 bitsPerSample, + OFBool isYBR) const +{ + if (bitsPerSample > 8) return new DJDecompressIJG12Bit(*cp, isYBR); + else return new DJDecompressIJG8Bit(*cp, isYBR); +} diff --git a/dcmjpeg/libsrc/djdecsv1.cc b/dcmjpeg/libsrc/djdecsv1.cc new file mode 100644 index 00000000..04b2e395 --- /dev/null +++ b/dcmjpeg/libsrc/djdecsv1.cc @@ -0,0 +1,57 @@ +/* + * + * Copyright (C) 2001-2010, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmjpeg + * + * Author: Marco Eichelberg, Norbert Olges + * + * Purpose: Codec class for decoding JPEG Lossless Selection Value 1 (8/12/16-bit) + * + */ + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmjpeg/djdecsv1.h" +#include "dcmtk/dcmjpeg/djcparam.h" +#include "dcmtk/dcmjpeg/djrplol.h" +#include "dcmtk/dcmjpeg/djdijg8.h" +#include "dcmtk/dcmjpeg/djdijg12.h" +#include "dcmtk/dcmjpeg/djdijg16.h" + + +DJDecoderP14SV1::DJDecoderP14SV1() +: DJCodecDecoder() +{ +} + + +DJDecoderP14SV1::~DJDecoderP14SV1() +{ +} + + +E_TransferSyntax DJDecoderP14SV1::supportedTransferSyntax() const +{ + return EXS_JPEGProcess14SV1; +} + + +DJDecoder *DJDecoderP14SV1::createDecoderInstance( + const DcmRepresentationParameter * /* toRepParam */, + const DJCodecParameter *cp, + Uint8 bitsPerSample, + OFBool isYBR) const +{ + if (bitsPerSample > 12) return new DJDecompressIJG16Bit(*cp, isYBR); + else if (bitsPerSample > 8) return new DJDecompressIJG12Bit(*cp, isYBR); + else return new DJDecompressIJG8Bit(*cp, isYBR); +} diff --git a/dcmjpeg/libsrc/djdijg12.cc b/dcmjpeg/libsrc/djdijg12.cc new file mode 100644 index 00000000..a4f7382e --- /dev/null +++ b/dcmjpeg/libsrc/djdijg12.cc @@ -0,0 +1,480 @@ +/* + * + * Copyright (C) 2001-2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmjpeg + * + * Author: Norbert Olges, Marco Eichelberg + * + * Purpose: decompression routines of the IJG JPEG library configured for 12 bits/sample. + * + */ + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmjpeg/djdijg12.h" +#include "dcmtk/dcmjpeg/djcparam.h" +#include "dcmtk/dcmdata/dcerror.h" + +#define INCLUDE_CSTDIO +#define INCLUDE_CSETJMP +#define INCLUDE_CSTRING +#include "dcmtk/ofstd/ofstdinc.h" + +// These two macros are re-defined in the IJG header files. +// We undefine them here and hope that IJG's configure has +// come to the same conclusion that we have... +#ifdef HAVE_STDLIB_H +#undef HAVE_STDLIB_H +#endif +#ifdef HAVE_STDDEF_H +#undef HAVE_STDDEF_H +#endif + +BEGIN_EXTERN_C +#define boolean ijg_boolean +#include "jpeglib12.h" +#include "jerror12.h" +#undef boolean + +// disable any preprocessor magic the IJG library might be doing with the "const" keyword +#ifdef const +#undef const +#endif + +#ifdef USE_STD_CXX_INCLUDES +// Solaris defines longjmp() in namespace std, other compilers don't... +namespace std { } +using namespace std; +#endif + +// private error handler struct +struct DJDIJG12ErrorStruct +{ + // the standard IJG error handler object + struct jpeg_error_mgr pub; + + // our jump buffer + jmp_buf setjmp_buffer; + + // pointer to this + DJDecompressIJG12Bit *instance; +}; + +// private source manager struct +struct DJDIJG12SourceManagerStruct +{ + // the standard IJG source manager object + struct jpeg_source_mgr pub; + + // number of bytes to skip at start of buffer + long skip_bytes; + + // buffer from which reading will continue as soon as the current buffer is empty + Uint8 *next_buffer; + + // buffer size + Uint32 next_buffer_size; +}; + +// callback forward declarations +void DJDIJG12ErrorExit(j_common_ptr); +void DJDIJG12EmitMessage(j_common_ptr cinfo, int msg_level); +void DJDIJG12initSource(j_decompress_ptr); +ijg_boolean DJDIJG12fillInputBuffer(j_decompress_ptr); +void DJDIJG12skipInputData(j_decompress_ptr, long); +void DJDIJG12termSource(j_decompress_ptr); + +// helper method to fix old-style casts warnings +static void OFjpeg_create_decompress(j_decompress_ptr cinfo) +{ + jpeg_create_decompress(cinfo); +} + +END_EXTERN_C + + +// error handler, executes longjmp +void DJDIJG12ErrorExit(j_common_ptr cinfo) +{ + DJDIJG12ErrorStruct *myerr = OFreinterpret_cast(DJDIJG12ErrorStruct*, cinfo->err); + longjmp(myerr->setjmp_buffer, 1); +} + +// message handler for warning messages and the like +void DJDIJG12EmitMessage(j_common_ptr cinfo, int msg_level) +{ + DJDIJG12ErrorStruct *myerr = OFreinterpret_cast(DJDIJG12ErrorStruct*, cinfo->err); + myerr->instance->emitMessage(msg_level); +} + + +// methods for decompress-source-manager + +void DJDIJG12initSource(j_decompress_ptr /* cinfo */) +{ +} + +ijg_boolean DJDIJG12fillInputBuffer(j_decompress_ptr cinfo) +{ + DJDIJG12SourceManagerStruct *src = OFreinterpret_cast(DJDIJG12SourceManagerStruct*, cinfo->src); + + // if we already have the next buffer, switch buffers + if (src->next_buffer) + { + src->pub.next_input_byte = src->next_buffer; + src->pub.bytes_in_buffer = OFstatic_cast(unsigned int, src->next_buffer_size); + src->next_buffer = NULL; + src->next_buffer_size = 0; + + // The suspension was caused by DJDIJG12skipInputData iff src->skip_bytes > 0. + // In this case we must skip the remaining number of bytes here. + if (src->skip_bytes > 0) + { + if (src->pub.bytes_in_buffer < OFstatic_cast(unsigned long, src->skip_bytes)) + { + src->skip_bytes -= OFstatic_cast(Uint32, src->pub.bytes_in_buffer); + src->pub.next_input_byte += src->pub.bytes_in_buffer; + src->pub.bytes_in_buffer = 0; + // cause a suspension return + return FALSE; + } + else + { + src->pub.bytes_in_buffer -= OFstatic_cast(unsigned int, src->skip_bytes); + src->pub.next_input_byte += src->skip_bytes; + src->skip_bytes = 0; + } + } + return TRUE; + } + + // otherwise cause a suspension return + return FALSE; +} + +void DJDIJG12skipInputData( + j_decompress_ptr cinfo, + long num_bytes) +{ + DJDIJG12SourceManagerStruct *src = OFreinterpret_cast(DJDIJG12SourceManagerStruct*, cinfo->src); + + if (src->pub.bytes_in_buffer < OFstatic_cast(size_t, num_bytes)) + { + src->skip_bytes = num_bytes - OFstatic_cast(Uint32, src->pub.bytes_in_buffer); + src->pub.next_input_byte += src->pub.bytes_in_buffer; + src->pub.bytes_in_buffer = 0; // causes a suspension return + } + else + { + src->pub.bytes_in_buffer -= OFstatic_cast(unsigned int, num_bytes); + src->pub.next_input_byte += num_bytes; + src->skip_bytes = 0; + } +} + +void DJDIJG12termSource(j_decompress_ptr /* cinfo */) +{ +} + + +DJDecompressIJG12Bit::DJDecompressIJG12Bit(const DJCodecParameter& cp, OFBool isYBR) +: DJDecoder() +, cparam(&cp) +, cinfo(NULL) +, suspension(0) +, jsampBuffer(NULL) +, dicomPhotometricInterpretationIsYCbCr(isYBR) +, decompressedColorModel(EPI_Unknown) +{ +} + +DJDecompressIJG12Bit::~DJDecompressIJG12Bit() +{ + cleanup(); +} + + +OFCondition DJDecompressIJG12Bit::init() +{ + suspension = 0; + decompressedColorModel = EPI_Unknown; + cleanup(); // prevent double initialization + + cinfo = new jpeg_decompress_struct(); + if (cinfo) + { + volatile DJDIJG12SourceManagerStruct *src = NULL; + volatile DJDIJG12ErrorStruct *jerr = new DJDIJG12ErrorStruct(); + if (jerr) + { + src = new DJDIJG12SourceManagerStruct(); + if (src) + { + // Specify the source of the compressed data + src->pub.init_source = DJDIJG12initSource; + src->pub.fill_input_buffer = DJDIJG12fillInputBuffer; + src->pub.skip_input_data = DJDIJG12skipInputData; + src->pub.resync_to_restart = jpeg_resync_to_restart; + src->pub.term_source = DJDIJG12termSource; + src->pub.bytes_in_buffer = 0; + src->pub.next_input_byte = NULL; + src->skip_bytes = 0; + src->next_buffer = NULL; + src->next_buffer_size = 0; + } + else + { + delete OFconst_cast(DJDIJG12ErrorStruct *, jerr); + delete cinfo; + cinfo = NULL; + return EC_MemoryExhausted; + } + cinfo->err = jpeg_std_error(& OFconst_cast(DJDIJG12ErrorStruct *, jerr)->pub); + jerr->instance = this; + jerr->pub.error_exit = DJDIJG12ErrorExit; + jerr->pub.emit_message = DJDIJG12EmitMessage; + if (setjmp(OFconst_cast(DJDIJG12ErrorStruct *, jerr)->setjmp_buffer)) + { + // the IJG error handler will cause the following code to be executed + char buffer[JMSG_LENGTH_MAX]; + (*cinfo->err->format_message)(OFreinterpret_cast(jpeg_common_struct*, cinfo), buffer); /* Create the message */ + cleanup(); + delete OFconst_cast(DJDIJG12SourceManagerStruct *, src); + return makeOFCondition(OFM_dcmjpeg, EJCode_IJG12_Decompression, OF_error, buffer); + } + } + else + { + delete cinfo; + cinfo = NULL; + return EC_MemoryExhausted; + } + OFjpeg_create_decompress(cinfo); + cinfo->src = &OFconst_cast(DJDIJG12SourceManagerStruct *, src)->pub; + } else return EC_MemoryExhausted; + + // everything OK + return EC_Normal; +} + + +void DJDecompressIJG12Bit::cleanup() +{ + if (cinfo) + { + jpeg_destroy_decompress(cinfo); + delete OFreinterpret_cast(DJDIJG12ErrorStruct*, cinfo->err); + delete OFreinterpret_cast(DJDIJG12SourceManagerStruct*, cinfo->src); + delete cinfo; + cinfo = NULL; + } +} + + +OFCondition DJDecompressIJG12Bit::decode( + Uint8 *compressedFrameBuffer, + Uint32 compressedFrameBufferSize, + Uint8 *uncompressedFrameBuffer, + Uint32 uncompressedFrameBufferSize, + OFBool isSigned) +{ + + if (cinfo==NULL || compressedFrameBuffer==NULL || uncompressedFrameBuffer==NULL) return EC_IllegalCall; + + if (setjmp(OFreinterpret_cast(DJDIJG12ErrorStruct*, cinfo->err)->setjmp_buffer)) + { + // the IJG error handler will cause the following code to be executed + char buffer[JMSG_LENGTH_MAX]; + (*cinfo->err->format_message)(OFreinterpret_cast(jpeg_common_struct*, cinfo), buffer); /* Create the message */ + cleanup(); + return makeOFCondition(OFM_dcmjpeg, EJCode_IJG12_Decompression, OF_error, buffer); + } + + // feed compressed buffer into cinfo structure. + // The buffer will be activated by the next call to DJDIJG12fillInputBuffer. + DJDIJG12SourceManagerStruct *src = OFreinterpret_cast(DJDIJG12SourceManagerStruct*, cinfo->src); + src->next_buffer = compressedFrameBuffer; + src->next_buffer_size = compressedFrameBufferSize; + + // Obtain image info + if (suspension < 2) + { + if (JPEG_SUSPENDED == jpeg_read_header(cinfo, TRUE)) + { + suspension = 1; + return EJ_Suspension; + } + + // check if color space conversion is enabled + OFBool colorSpaceConversion = OFFalse; + // check whether to use the IJG library guess for the JPEG color space + OFBool colorSpaceGuess = OFFalse; + switch (cparam->getDecompressionColorSpaceConversion()) + { + case EDC_photometricInterpretation: // color space conversion if DICOM photometric interpretation is YCbCr + colorSpaceConversion = dicomPhotometricInterpretationIsYCbCr; + break; + case EDC_lossyOnly: // color space conversion if lossy JPEG + if (cinfo->process != JPROC_LOSSLESS) + colorSpaceConversion = OFTrue; + break; + case EDC_always: // always do color space conversion + colorSpaceConversion = OFTrue; + break; + case EDC_never: // never do color space conversion + break; + case EDC_guessLossyOnly: // use color space guess by IJG library if lossy JPEG + if (cinfo->process != JPROC_LOSSLESS) + { + colorSpaceGuess = OFTrue; + if (cinfo->jpeg_color_space == JCS_YCbCr) + colorSpaceConversion = OFTrue; + } + break; + case EDC_guess: // always use color space guess by IJG library + colorSpaceGuess = OFTrue; + if (cinfo->jpeg_color_space == JCS_YCbCr) + colorSpaceConversion = OFTrue; + break; + } + // decline color space conversion to RGB for signed pixel data, + // because IJG can handle only unsigned + if (colorSpaceConversion && isSigned) + return EJ_UnsupportedColorConversion; + + // let the IJG library guess the JPEG color space + if (colorSpaceGuess) + { + switch (cinfo->jpeg_color_space) + { + case JCS_GRAYSCALE: + // cinfo->out_color_space = JCS_GRAYSCALE; + decompressedColorModel = EPI_Monochrome2; + break; + case JCS_YCbCr: // enforce conversion YCbCr to RGB + cinfo->out_color_space = JCS_RGB; + decompressedColorModel = EPI_RGB; + break; + case JCS_RGB: + // cinfo->out_color_space = JCS_RGB; + decompressedColorModel = EPI_RGB; + break; + default: + decompressedColorModel = EPI_Unknown; + break; + } + } + // set color space for decompression + else if (colorSpaceConversion) + { + switch (cinfo->out_color_space) + { + case JCS_GRAYSCALE: + decompressedColorModel = EPI_Monochrome2; + break; + case JCS_YCbCr: // enforce conversion YCbCr to RGB + cinfo->jpeg_color_space = JCS_YCbCr; + cinfo->out_color_space = JCS_RGB; + decompressedColorModel = EPI_RGB; + break; + case JCS_RGB: // enforce conversion YCbCr to RGB + cinfo->jpeg_color_space = JCS_YCbCr; + decompressedColorModel = EPI_RGB; + break; + default: + decompressedColorModel = EPI_Unknown; + break; + } + } + else + { + decompressedColorModel = EPI_Unknown; + // prevent the library from performing any color space conversion + cinfo->jpeg_color_space = JCS_UNKNOWN; + cinfo->out_color_space = JCS_UNKNOWN; + } + } + + JSAMPARRAY buffer = NULL; + int bufsize = 0; + size_t rowsize = 0; + + if (suspension < 3) + { + if (FALSE == jpeg_start_decompress(cinfo)) + { + suspension = 2; + return EJ_Suspension; + } + bufsize = cinfo->output_width * cinfo->output_components; // number of JSAMPLEs per row + rowsize = bufsize * sizeof(JSAMPLE); // number of bytes per row + buffer = (*cinfo->mem->alloc_sarray)(OFreinterpret_cast(j_common_ptr, cinfo), JPOOL_IMAGE, bufsize, 1); + if (buffer == NULL) return EC_MemoryExhausted; + jsampBuffer = buffer; + } + else + { + bufsize = cinfo->output_width * cinfo->output_components; + rowsize = bufsize * sizeof(JSAMPLE); + buffer = OFreinterpret_cast(JSAMPARRAY, jsampBuffer); + } + + if (uncompressedFrameBufferSize < rowsize * cinfo->output_height) return EJ_IJG12_FrameBufferTooSmall; + + while (cinfo->output_scanline < cinfo->output_height) + { + if (0 == jpeg_read_scanlines(cinfo, buffer, 1)) + { + suspension = 3; + return EJ_Suspension; + } + memcpy(uncompressedFrameBuffer + (cinfo->output_scanline-1) * rowsize, *buffer, rowsize); + } + + if (FALSE == jpeg_finish_decompress(cinfo)) + { + suspension = 4; + return EJ_Suspension; + } + + return EC_Normal; +} + +void DJDecompressIJG12Bit::emitMessage(int msg_level) const +{ + // This is how we map the message levels: + // -1 - 0: Warning (could also be errors, but no way to find out) + // 1 : Debug + // Everything else: Trace (No point in splitting this further up) + OFLogger::LogLevel level; + + switch (msg_level) + { + case -1: + case 0: + level = OFLogger::WARN_LOG_LEVEL; + break; + case 1: + level = OFLogger::DEBUG_LOG_LEVEL; + break; + default: + level = OFLogger::TRACE_LOG_LEVEL; + break; + } + + if (cinfo && DCM_dcmjpegLogger.isEnabledFor(level)) + { + char buffer[JMSG_LENGTH_MAX]; + (*cinfo->err->format_message)(OFreinterpret_cast(jpeg_common_struct*, cinfo), buffer); /* Create the message */ + DCM_dcmjpegLogger.forcedLog(level, buffer, __FILE__, __LINE__); + } +} diff --git a/dcmjpeg/libsrc/djdijg16.cc b/dcmjpeg/libsrc/djdijg16.cc new file mode 100644 index 00000000..ff479ebf --- /dev/null +++ b/dcmjpeg/libsrc/djdijg16.cc @@ -0,0 +1,482 @@ +/* + * + * Copyright (C) 2001-2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmjpeg + * + * Author: Norbert Olges, Marco Eichelberg + * + * Purpose: decompression routines of the IJG JPEG library configured for 16 bits/sample. + * + */ + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmjpeg/djdijg16.h" +#include "dcmtk/dcmjpeg/djcparam.h" +#include "dcmtk/dcmdata/dcerror.h" + +#define INCLUDE_CSTDIO +#define INCLUDE_CSETJMP +#define INCLUDE_CSTRING +#include "dcmtk/ofstd/ofstdinc.h" + +// These two macros are re-defined in the IJG header files. +// We undefine them here and hope that IJG's configure has +// come to the same conclusion that we have... +#ifdef HAVE_STDLIB_H +#undef HAVE_STDLIB_H +#endif +#ifdef HAVE_STDDEF_H +#undef HAVE_STDDEF_H +#endif + +BEGIN_EXTERN_C +#define boolean ijg_boolean +#include "jpeglib16.h" +#include "jerror16.h" +#undef boolean + +// disable any preprocessor magic the IJG library might be doing with the "const" keyword +#ifdef const +#undef const +#endif + +#ifdef USE_STD_CXX_INCLUDES +// Solaris defines longjmp() in namespace std, other compilers don't... +namespace std { } +using namespace std; +#endif + +// private error handler struct +struct DJDIJG16ErrorStruct +{ + // the standard IJG error handler object + struct jpeg_error_mgr pub; + + // our jump buffer + jmp_buf setjmp_buffer; + + // pointer to this + DJDecompressIJG16Bit *instance; +}; + +// private source manager struct +struct DJDIJG16SourceManagerStruct +{ + // the standard IJG source manager object + struct jpeg_source_mgr pub; + + // number of bytes to skip at start of buffer + long skip_bytes; + + // buffer from which reading will continue as soon as the current buffer is empty + Uint8 *next_buffer; + + // buffer size + Uint32 next_buffer_size; +}; + +// callback forward declarations +void DJDIJG16ErrorExit(j_common_ptr); +void DJDIJG16EmitMessage(j_common_ptr cinfo, int msg_level); +void DJDIJG16initSource(j_decompress_ptr); +ijg_boolean DJDIJG16fillInputBuffer(j_decompress_ptr); +void DJDIJG16skipInputData(j_decompress_ptr, long); +void DJDIJG16termSource(j_decompress_ptr); + +// helper method to fix old-style casts warnings +static void OFjpeg_create_decompress(j_decompress_ptr cinfo) +{ + jpeg_create_decompress(cinfo); +} + +END_EXTERN_C + + +// error handler, executes longjmp +void DJDIJG16ErrorExit(j_common_ptr cinfo) +{ + DJDIJG16ErrorStruct *myerr = OFreinterpret_cast(DJDIJG16ErrorStruct*, cinfo->err); + longjmp(myerr->setjmp_buffer, 1); +} + +// message handler for warning messages and the like +void DJDIJG16EmitMessage(j_common_ptr cinfo, int msg_level) +{ + DJDIJG16ErrorStruct *myerr = OFreinterpret_cast(DJDIJG16ErrorStruct*, cinfo->err); + myerr->instance->emitMessage(msg_level); +} + + +// methods for decompress-source-manager + +void DJDIJG16initSource(j_decompress_ptr /* cinfo */) +{ +} + +ijg_boolean DJDIJG16fillInputBuffer(j_decompress_ptr cinfo) +{ + DJDIJG16SourceManagerStruct *src = OFreinterpret_cast(DJDIJG16SourceManagerStruct*, cinfo->src); + + // if we already have the next buffer, switch buffers + if (src->next_buffer) + { + src->pub.next_input_byte = src->next_buffer; + src->pub.bytes_in_buffer = OFstatic_cast(unsigned int, src->next_buffer_size); + src->next_buffer = NULL; + src->next_buffer_size = 0; + + // The suspension was caused by DJDIJG16skipInputData iff src->skip_bytes > 0. + // In this case we must skip the remaining number of bytes here. + if (src->skip_bytes > 0) + { + if (src->pub.bytes_in_buffer < OFstatic_cast(unsigned long, src->skip_bytes)) + { + src->skip_bytes -= OFstatic_cast(Uint32, src->pub.bytes_in_buffer); + src->pub.next_input_byte += src->pub.bytes_in_buffer; + src->pub.bytes_in_buffer = 0; + // cause a suspension return + return FALSE; + } + else + { + src->pub.bytes_in_buffer -= OFstatic_cast(unsigned int, src->skip_bytes); + src->pub.next_input_byte += src->skip_bytes; + src->skip_bytes = 0; + } + } + return TRUE; + } + + // otherwise cause a suspension return + return FALSE; +} + +void DJDIJG16skipInputData( + j_decompress_ptr cinfo, + long num_bytes) +{ + DJDIJG16SourceManagerStruct *src = OFreinterpret_cast(DJDIJG16SourceManagerStruct*, cinfo->src); + + if (src->pub.bytes_in_buffer < OFstatic_cast(size_t, num_bytes)) + { + src->skip_bytes = num_bytes - OFstatic_cast(Uint32, src->pub.bytes_in_buffer); + src->pub.next_input_byte += src->pub.bytes_in_buffer; + src->pub.bytes_in_buffer = 0; // causes a suspension return + } + else + { + src->pub.bytes_in_buffer -= OFstatic_cast(unsigned int, num_bytes); + src->pub.next_input_byte += num_bytes; + src->skip_bytes = 0; + } +} + +void DJDIJG16termSource(j_decompress_ptr /* cinfo */) +{ +} + + +DJDecompressIJG16Bit::DJDecompressIJG16Bit(const DJCodecParameter& cp, OFBool isYBR) +: DJDecoder() +, cparam(&cp) +, cinfo(NULL) +, suspension(0) +, jsampBuffer(NULL) +, dicomPhotometricInterpretationIsYCbCr(isYBR) +, decompressedColorModel(EPI_Unknown) +{ +} + +DJDecompressIJG16Bit::~DJDecompressIJG16Bit() +{ + cleanup(); +} + + +OFCondition DJDecompressIJG16Bit::init() +{ + suspension = 0; + decompressedColorModel = EPI_Unknown; + cleanup(); // prevent double initialization + + cinfo = new jpeg_decompress_struct(); + if (cinfo) + { + volatile DJDIJG16SourceManagerStruct *src = NULL; + volatile DJDIJG16ErrorStruct *jerr = new DJDIJG16ErrorStruct(); + if (jerr) + { + src = new DJDIJG16SourceManagerStruct(); + if (src) + { + // Specify the source of the compressed data + src->pub.init_source = DJDIJG16initSource; + src->pub.fill_input_buffer = DJDIJG16fillInputBuffer; + src->pub.skip_input_data = DJDIJG16skipInputData; + src->pub.resync_to_restart = jpeg_resync_to_restart; + src->pub.term_source = DJDIJG16termSource; + src->pub.bytes_in_buffer = 0; + src->pub.next_input_byte = NULL; + src->skip_bytes = 0; + src->next_buffer = NULL; + src->next_buffer_size = 0; + } + else + { + delete OFconst_cast(DJDIJG16ErrorStruct *, jerr); + delete cinfo; + cinfo = NULL; + return EC_MemoryExhausted; + } + cinfo->err = jpeg_std_error(& OFconst_cast(DJDIJG16ErrorStruct *, jerr)->pub); + jerr->instance = this; + jerr->pub.error_exit = DJDIJG16ErrorExit; + jerr->pub.emit_message = DJDIJG16EmitMessage; + if (setjmp(OFconst_cast(DJDIJG16ErrorStruct *, jerr)->setjmp_buffer)) + { + // the IJG error handler will cause the following code to be executed + char buffer[JMSG_LENGTH_MAX]; + (*cinfo->err->format_message)(OFreinterpret_cast(jpeg_common_struct*, cinfo), buffer); /* Create the message */ + cleanup(); + delete OFconst_cast(DJDIJG16SourceManagerStruct *, src); + return makeOFCondition(OFM_dcmjpeg, EJCode_IJG16_Decompression, OF_error, buffer); + } + } + else + { + delete cinfo; + cinfo = NULL; + return EC_MemoryExhausted; + } + OFjpeg_create_decompress(cinfo); + cinfo->src = &OFconst_cast(DJDIJG16SourceManagerStruct*, src)->pub; + cinfo->workaround_options = 0; + if (cparam->predictor6WorkaroundEnabled()) cinfo->workaround_options |= WORKAROUND_PREDICTOR6OVERFLOW; + } else return EC_MemoryExhausted; + + // everything OK + return EC_Normal; +} + + +void DJDecompressIJG16Bit::cleanup() +{ + if (cinfo) + { + jpeg_destroy_decompress(cinfo); + delete OFreinterpret_cast(DJDIJG16ErrorStruct*, cinfo->err); + delete OFreinterpret_cast(DJDIJG16SourceManagerStruct*, cinfo->src); + delete cinfo; + cinfo = NULL; + } +} + + +OFCondition DJDecompressIJG16Bit::decode( + Uint8 *compressedFrameBuffer, + Uint32 compressedFrameBufferSize, + Uint8 *uncompressedFrameBuffer, + Uint32 uncompressedFrameBufferSize, + OFBool isSigned) +{ + + if (cinfo==NULL || compressedFrameBuffer==NULL || uncompressedFrameBuffer==NULL) return EC_IllegalCall; + + if (setjmp(OFreinterpret_cast(DJDIJG16ErrorStruct*, cinfo->err)->setjmp_buffer)) + { + // the IJG error handler will cause the following code to be executed + char buffer[JMSG_LENGTH_MAX]; + (*cinfo->err->format_message)(OFreinterpret_cast(jpeg_common_struct*, cinfo), buffer); /* Create the message */ + cleanup(); + return makeOFCondition(OFM_dcmjpeg, EJCode_IJG16_Decompression, OF_error, buffer); + } + + // feed compressed buffer into cinfo structure. + // The buffer will be activated by the next call to DJDIJG16fillInputBuffer. + DJDIJG16SourceManagerStruct *src = OFreinterpret_cast(DJDIJG16SourceManagerStruct*, cinfo->src); + src->next_buffer = compressedFrameBuffer; + src->next_buffer_size = compressedFrameBufferSize; + + // Obtain image info + if (suspension < 2) + { + if (JPEG_SUSPENDED == jpeg_read_header(cinfo, TRUE)) + { + suspension = 1; + return EJ_Suspension; + } + + // check if color space conversion is enabled + OFBool colorSpaceConversion = OFFalse; + // check whether to use the IJG library guess for the JPEG color space + OFBool colorSpaceGuess = OFFalse; + switch (cparam->getDecompressionColorSpaceConversion()) + { + case EDC_photometricInterpretation: // color space conversion if DICOM photometric interpretation is YCbCr + colorSpaceConversion = dicomPhotometricInterpretationIsYCbCr; + break; + case EDC_lossyOnly: // color space conversion if lossy JPEG + if (cinfo->process != JPROC_LOSSLESS) + colorSpaceConversion = OFTrue; + break; + case EDC_always: // always do color space conversion + colorSpaceConversion = OFTrue; + break; + case EDC_never: // never do color space conversion + break; + case EDC_guessLossyOnly: // use color space guess by IJG library if lossy JPEG + if (cinfo->process != JPROC_LOSSLESS) + { + colorSpaceGuess = OFTrue; + if (cinfo->jpeg_color_space == JCS_YCbCr) + colorSpaceConversion = OFTrue; + } + break; + case EDC_guess: // always use color space guess by IJG library + colorSpaceGuess = OFTrue; + if (cinfo->jpeg_color_space == JCS_YCbCr) + colorSpaceConversion = OFTrue; + break; + } + // decline color space conversion to RGB for signed pixel data, + // because IJG can handle only unsigned + if (colorSpaceConversion && isSigned) + return EJ_UnsupportedColorConversion; + + // let the IJG library guess the JPEG color space + if (colorSpaceGuess) + { + switch (cinfo->jpeg_color_space) + { + case JCS_GRAYSCALE: + // cinfo->out_color_space = JCS_GRAYSCALE; + decompressedColorModel = EPI_Monochrome2; + break; + case JCS_YCbCr: // enforce conversion YCbCr to RGB + cinfo->out_color_space = JCS_RGB; + decompressedColorModel = EPI_RGB; + break; + case JCS_RGB: + // cinfo->out_color_space = JCS_RGB; + decompressedColorModel = EPI_RGB; + break; + default: + decompressedColorModel = EPI_Unknown; + break; + } + } + // set color space for decompression + else if (colorSpaceConversion) + { + switch (cinfo->out_color_space) + { + case JCS_GRAYSCALE: + decompressedColorModel = EPI_Monochrome2; + break; + case JCS_YCbCr: // enforce conversion YCbCr to RGB + cinfo->jpeg_color_space = JCS_YCbCr; + cinfo->out_color_space = JCS_RGB; + decompressedColorModel = EPI_RGB; + break; + case JCS_RGB: // enforce conversion YCbCr to RGB + cinfo->jpeg_color_space = JCS_YCbCr; + decompressedColorModel = EPI_RGB; + break; + default: + decompressedColorModel = EPI_Unknown; + break; + } + } + else + { + decompressedColorModel = EPI_Unknown; + // prevent the library from performing any color space conversion + cinfo->jpeg_color_space = JCS_UNKNOWN; + cinfo->out_color_space = JCS_UNKNOWN; + } + } + + JSAMPARRAY buffer = NULL; + int bufsize = 0; + size_t rowsize = 0; + + if (suspension < 3) + { + if (FALSE == jpeg_start_decompress(cinfo)) + { + suspension = 2; + return EJ_Suspension; + } + bufsize = cinfo->output_width * cinfo->output_components; // number of JSAMPLEs per row + rowsize = bufsize * sizeof(JSAMPLE); // number of bytes per row + buffer = (*cinfo->mem->alloc_sarray)(OFreinterpret_cast(j_common_ptr, cinfo), JPOOL_IMAGE, bufsize, 1); + if (buffer == NULL) return EC_MemoryExhausted; + jsampBuffer = buffer; + } + else + { + bufsize = cinfo->output_width * cinfo->output_components; + rowsize = bufsize * sizeof(JSAMPLE); + buffer = OFreinterpret_cast(JSAMPARRAY, jsampBuffer); + } + + if (uncompressedFrameBufferSize < rowsize * cinfo->output_height) return EJ_IJG16_FrameBufferTooSmall; + + while (cinfo->output_scanline < cinfo->output_height) + { + if (0 == jpeg_read_scanlines(cinfo, buffer, 1)) + { + suspension = 3; + return EJ_Suspension; + } + memcpy(uncompressedFrameBuffer + (cinfo->output_scanline-1) * rowsize, *buffer, rowsize); + } + + if (FALSE == jpeg_finish_decompress(cinfo)) + { + suspension = 4; + return EJ_Suspension; + } + + return EC_Normal; +} + +void DJDecompressIJG16Bit::emitMessage(int msg_level) const +{ + // This is how we map the message levels: + // -1 - 0: Warning (could also be errors, but no way to find out) + // 1 : Debug + // Everything else: Trace (No point in splitting this further up) + OFLogger::LogLevel level; + + switch (msg_level) + { + case -1: + case 0: + level = OFLogger::WARN_LOG_LEVEL; + break; + case 1: + level = OFLogger::DEBUG_LOG_LEVEL; + break; + default: + level = OFLogger::TRACE_LOG_LEVEL; + break; + } + + if (cinfo && DCM_dcmjpegLogger.isEnabledFor(level)) + { + char buffer[JMSG_LENGTH_MAX]; + (*cinfo->err->format_message)(OFreinterpret_cast(jpeg_common_struct*, cinfo), buffer); /* Create the message */ + DCM_dcmjpegLogger.forcedLog(level, buffer, __FILE__, __LINE__); + } +} diff --git a/dcmjpeg/libsrc/djdijg8.cc b/dcmjpeg/libsrc/djdijg8.cc new file mode 100644 index 00000000..b8ad8d3a --- /dev/null +++ b/dcmjpeg/libsrc/djdijg8.cc @@ -0,0 +1,480 @@ +/* + * + * Copyright (C) 2001-2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmjpeg + * + * Author: Norbert Olges, Marco Eichelberg + * + * Purpose: decompression routines of the IJG JPEG library configured for 8 bits/sample. + * + */ + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmjpeg/djdijg8.h" +#include "dcmtk/dcmjpeg/djcparam.h" +#include "dcmtk/dcmdata/dcerror.h" + +#define INCLUDE_CSTDIO +#define INCLUDE_CSETJMP +#define INCLUDE_CSTRING +#include "dcmtk/ofstd/ofstdinc.h" + +// These two macros are re-defined in the IJG header files. +// We undefine them here and hope that IJG's configure has +// come to the same conclusion that we have... +#ifdef HAVE_STDLIB_H +#undef HAVE_STDLIB_H +#endif +#ifdef HAVE_STDDEF_H +#undef HAVE_STDDEF_H +#endif + +BEGIN_EXTERN_C +#define boolean ijg_boolean +#include "jpeglib8.h" +#include "jerror8.h" +#undef boolean + +// disable any preprocessor magic the IJG library might be doing with the "const" keyword +#ifdef const +#undef const +#endif + +#ifdef USE_STD_CXX_INCLUDES +// Solaris defines longjmp() in namespace std, other compilers don't... +namespace std { } +using namespace std; +#endif + +// private error handler struct +struct DJDIJG8ErrorStruct +{ + // the standard IJG error handler object + struct jpeg_error_mgr pub; + + // our jump buffer + jmp_buf setjmp_buffer; + + // pointer to this + DJDecompressIJG8Bit *instance; +}; + +// private source manager struct +struct DJDIJG8SourceManagerStruct +{ + // the standard IJG source manager object + struct jpeg_source_mgr pub; + + // number of bytes to skip at start of buffer + long skip_bytes; + + // buffer from which reading will continue as soon as the current buffer is empty + Uint8 *next_buffer; + + // buffer size + Uint32 next_buffer_size; +}; + +// callback forward declarations +void DJDIJG8ErrorExit(j_common_ptr); +void DJDIJG8EmitMessage(j_common_ptr cinfo, int msg_level); +void DJDIJG8initSource(j_decompress_ptr); +ijg_boolean DJDIJG8fillInputBuffer(j_decompress_ptr); +void DJDIJG8skipInputData(j_decompress_ptr, long); +void DJDIJG8termSource(j_decompress_ptr); + +// helper method to fix old-style casts warnings +static void OFjpeg_create_decompress(j_decompress_ptr cinfo) +{ + jpeg_create_decompress(cinfo); +} + +END_EXTERN_C + + +// error handler, executes longjmp +void DJDIJG8ErrorExit(j_common_ptr cinfo) +{ + DJDIJG8ErrorStruct *myerr = OFreinterpret_cast(DJDIJG8ErrorStruct*, cinfo->err); + longjmp(myerr->setjmp_buffer, 1); +} + +// message handler for warning messages and the like +void DJDIJG8EmitMessage(j_common_ptr cinfo, int msg_level) +{ + DJDIJG8ErrorStruct *myerr = OFreinterpret_cast(DJDIJG8ErrorStruct*, cinfo->err); + myerr->instance->emitMessage(msg_level); +} + + +// methods for decompress-source-manager + +void DJDIJG8initSource(j_decompress_ptr /* cinfo */) +{ +} + +ijg_boolean DJDIJG8fillInputBuffer(j_decompress_ptr cinfo) +{ + DJDIJG8SourceManagerStruct *src = OFreinterpret_cast(DJDIJG8SourceManagerStruct*, cinfo->src); + + // if we already have the next buffer, switch buffers + if (src->next_buffer) + { + src->pub.next_input_byte = src->next_buffer; + src->pub.bytes_in_buffer = OFstatic_cast(unsigned int, src->next_buffer_size); + src->next_buffer = NULL; + src->next_buffer_size = 0; + + // The suspension was caused by DJDIJG8skipInputData iff src->skip_bytes > 0. + // In this case we must skip the remaining number of bytes here. + if (src->skip_bytes > 0) + { + if (src->pub.bytes_in_buffer < OFstatic_cast(unsigned long, src->skip_bytes)) + { + src->skip_bytes -= OFstatic_cast(Uint32, src->pub.bytes_in_buffer); + src->pub.next_input_byte += src->pub.bytes_in_buffer; + src->pub.bytes_in_buffer = 0; + // cause a suspension return + return FALSE; + } + else + { + src->pub.bytes_in_buffer -= OFstatic_cast(unsigned int, src->skip_bytes); + src->pub.next_input_byte += src->skip_bytes; + src->skip_bytes = 0; + } + } + return TRUE; + } + + // otherwise cause a suspension return + return FALSE; +} + +void DJDIJG8skipInputData( + j_decompress_ptr cinfo, + long num_bytes) +{ + DJDIJG8SourceManagerStruct *src = OFreinterpret_cast(DJDIJG8SourceManagerStruct*, cinfo->src); + + if (src->pub.bytes_in_buffer < OFstatic_cast(size_t, num_bytes)) + { + src->skip_bytes = num_bytes - OFstatic_cast(Uint32, src->pub.bytes_in_buffer); + src->pub.next_input_byte += src->pub.bytes_in_buffer; + src->pub.bytes_in_buffer = 0; // causes a suspension return + } + else + { + src->pub.bytes_in_buffer -= OFstatic_cast(unsigned int, num_bytes); + src->pub.next_input_byte += num_bytes; + src->skip_bytes = 0; + } +} + +void DJDIJG8termSource(j_decompress_ptr /* cinfo */) +{ +} + + +DJDecompressIJG8Bit::DJDecompressIJG8Bit(const DJCodecParameter& cp, OFBool isYBR) +: DJDecoder() +, cparam(&cp) +, cinfo(NULL) +, suspension(0) +, jsampBuffer(NULL) +, dicomPhotometricInterpretationIsYCbCr(isYBR) +, decompressedColorModel(EPI_Unknown) +{ +} + +DJDecompressIJG8Bit::~DJDecompressIJG8Bit() +{ + cleanup(); +} + + +OFCondition DJDecompressIJG8Bit::init() +{ + suspension = 0; + decompressedColorModel = EPI_Unknown; + cleanup(); // prevent double initialization + + cinfo = new jpeg_decompress_struct(); + if (cinfo) + { + volatile DJDIJG8SourceManagerStruct *src = NULL; + volatile DJDIJG8ErrorStruct *jerr = new DJDIJG8ErrorStruct(); + if (jerr) + { + src = new DJDIJG8SourceManagerStruct(); + if (src) + { + // Specify the source of the compressed data + src->pub.init_source = DJDIJG8initSource; + src->pub.fill_input_buffer = DJDIJG8fillInputBuffer; + src->pub.skip_input_data = DJDIJG8skipInputData; + src->pub.resync_to_restart = jpeg_resync_to_restart; + src->pub.term_source = DJDIJG8termSource; + src->pub.bytes_in_buffer = 0; + src->pub.next_input_byte = NULL; + src->skip_bytes = 0; + src->next_buffer = NULL; + src->next_buffer_size = 0; + } + else + { + delete OFconst_cast(DJDIJG8ErrorStruct *, jerr); + delete cinfo; + cinfo = NULL; + return EC_MemoryExhausted; + } + cinfo->err = jpeg_std_error(& OFconst_cast(DJDIJG8ErrorStruct *, jerr)->pub); + jerr->instance = this; + jerr->pub.error_exit = DJDIJG8ErrorExit; + jerr->pub.emit_message = DJDIJG8EmitMessage; + if (setjmp(OFconst_cast(DJDIJG8ErrorStruct *, jerr)->setjmp_buffer)) + { + // the IJG error handler will cause the following code to be executed + char buffer[JMSG_LENGTH_MAX]; + (*cinfo->err->format_message)(OFreinterpret_cast(jpeg_common_struct*, cinfo), buffer); /* Create the message */ + cleanup(); + delete OFconst_cast(DJDIJG8SourceManagerStruct *, src); + return makeOFCondition(OFM_dcmjpeg, EJCode_IJG8_Decompression, OF_error, buffer); + } + } + else + { + delete cinfo; + cinfo = NULL; + return EC_MemoryExhausted; + } + OFjpeg_create_decompress(cinfo); + cinfo->src = &OFconst_cast(DJDIJG8SourceManagerStruct *, src)->pub; + } else return EC_MemoryExhausted; + + // everything OK + return EC_Normal; +} + + +void DJDecompressIJG8Bit::cleanup() +{ + if (cinfo) + { + jpeg_destroy_decompress(cinfo); + delete OFreinterpret_cast(DJDIJG8ErrorStruct*, cinfo->err); + delete OFreinterpret_cast(DJDIJG8SourceManagerStruct*, cinfo->src); + delete cinfo; + cinfo = NULL; + } +} + + +OFCondition DJDecompressIJG8Bit::decode( + Uint8 *compressedFrameBuffer, + Uint32 compressedFrameBufferSize, + Uint8 *uncompressedFrameBuffer, + Uint32 uncompressedFrameBufferSize, + OFBool isSigned) +{ + + if (cinfo==NULL || compressedFrameBuffer==NULL || uncompressedFrameBuffer==NULL) return EC_IllegalCall; + + if (setjmp(OFreinterpret_cast(DJDIJG8ErrorStruct*, cinfo->err)->setjmp_buffer)) + { + // the IJG error handler will cause the following code to be executed + char buffer[JMSG_LENGTH_MAX]; + (*cinfo->err->format_message)(OFreinterpret_cast(jpeg_common_struct*, cinfo), buffer); /* Create the message */ + cleanup(); + return makeOFCondition(OFM_dcmjpeg, EJCode_IJG8_Decompression, OF_error, buffer); + } + + // feed compressed buffer into cinfo structure. + // The buffer will be activated by the next call to DJDIJG8fillInputBuffer. + DJDIJG8SourceManagerStruct *src = OFreinterpret_cast(DJDIJG8SourceManagerStruct*, cinfo->src); + src->next_buffer = compressedFrameBuffer; + src->next_buffer_size = compressedFrameBufferSize; + + // Obtain image info + if (suspension < 2) + { + if (JPEG_SUSPENDED == jpeg_read_header(cinfo, TRUE)) + { + suspension = 1; + return EJ_Suspension; + } + + // check if color space conversion is enabled + OFBool colorSpaceConversion = OFFalse; + // check whether to use the IJG library guess for the JPEG color space + OFBool colorSpaceGuess = OFFalse; + switch (cparam->getDecompressionColorSpaceConversion()) + { + case EDC_photometricInterpretation: // color space conversion if DICOM photometric interpretation is YCbCr + colorSpaceConversion = dicomPhotometricInterpretationIsYCbCr; + break; + case EDC_lossyOnly: // color space conversion if lossy JPEG + if (cinfo->process != JPROC_LOSSLESS) + colorSpaceConversion = OFTrue; + break; + case EDC_always: // always do color space conversion + colorSpaceConversion = OFTrue; + break; + case EDC_never: // never do color space conversion + break; + case EDC_guessLossyOnly: // use color space guess by IJG library if lossy JPEG + if (cinfo->process != JPROC_LOSSLESS) + { + colorSpaceGuess = OFTrue; + if (cinfo->jpeg_color_space == JCS_YCbCr) + colorSpaceConversion = OFTrue; + } + break; + case EDC_guess: // always use color space guess by IJG library + colorSpaceGuess = OFTrue; + if (cinfo->jpeg_color_space == JCS_YCbCr) + colorSpaceConversion = OFTrue; + break; + } + // decline color space conversion to RGB for signed pixel data, + // because IJG can handle only unsigned + if (colorSpaceConversion && isSigned) + return EJ_UnsupportedColorConversion; + + // let the IJG library guess the JPEG color space + if (colorSpaceGuess) + { + switch (cinfo->jpeg_color_space) + { + case JCS_GRAYSCALE: + // cinfo->out_color_space = JCS_GRAYSCALE; + decompressedColorModel = EPI_Monochrome2; + break; + case JCS_YCbCr: // enforce conversion YCbCr to RGB + cinfo->out_color_space = JCS_RGB; + decompressedColorModel = EPI_RGB; + break; + case JCS_RGB: + // cinfo->out_color_space = JCS_RGB; + decompressedColorModel = EPI_RGB; + break; + default: + decompressedColorModel = EPI_Unknown; + break; + } + } + // set color space for decompression + else if (colorSpaceConversion) + { + switch (cinfo->out_color_space) + { + case JCS_GRAYSCALE: + decompressedColorModel = EPI_Monochrome2; + break; + case JCS_YCbCr: // enforce conversion YCbCr to RGB + cinfo->jpeg_color_space = JCS_YCbCr; + cinfo->out_color_space = JCS_RGB; + decompressedColorModel = EPI_RGB; + break; + case JCS_RGB: // enforce conversion YCbCr to RGB + cinfo->jpeg_color_space = JCS_YCbCr; + decompressedColorModel = EPI_RGB; + break; + default: + decompressedColorModel = EPI_Unknown; + break; + } + } + else + { + decompressedColorModel = EPI_Unknown; + // prevent the library from performing any color space conversion + cinfo->jpeg_color_space = JCS_UNKNOWN; + cinfo->out_color_space = JCS_UNKNOWN; + } + } + + JSAMPARRAY buffer = NULL; + int bufsize = 0; + size_t rowsize = 0; + + if (suspension < 3) + { + if (FALSE == jpeg_start_decompress(cinfo)) + { + suspension = 2; + return EJ_Suspension; + } + bufsize = cinfo->output_width * cinfo->output_components; // number of JSAMPLEs per row + rowsize = bufsize * sizeof(JSAMPLE); // number of bytes per row + buffer = (*cinfo->mem->alloc_sarray)(OFreinterpret_cast(j_common_ptr, cinfo), JPOOL_IMAGE, bufsize, 1); + if (buffer == NULL) return EC_MemoryExhausted; + jsampBuffer = buffer; + } + else + { + bufsize = cinfo->output_width * cinfo->output_components; + rowsize = bufsize * sizeof(JSAMPLE); + buffer = OFreinterpret_cast(JSAMPARRAY, jsampBuffer); + } + + if (uncompressedFrameBufferSize < rowsize * cinfo->output_height) return EJ_IJG8_FrameBufferTooSmall; + + while (cinfo->output_scanline < cinfo->output_height) + { + if (0 == jpeg_read_scanlines(cinfo, buffer, 1)) + { + suspension = 3; + return EJ_Suspension; + } + memcpy(uncompressedFrameBuffer + (cinfo->output_scanline-1) * rowsize, *buffer, rowsize); + } + + if (FALSE == jpeg_finish_decompress(cinfo)) + { + suspension = 4; + return EJ_Suspension; + } + + return EC_Normal; +} + +void DJDecompressIJG8Bit::emitMessage(int msg_level) const +{ + // This is how we map the message levels: + // -1 - 0: Warning (could also be errors, but no way to find out) + // 1 : Debug + // Everything else: Trace (No point in splitting this further up) + OFLogger::LogLevel level; + + switch (msg_level) + { + case -1: + case 0: + level = OFLogger::WARN_LOG_LEVEL; + break; + case 1: + level = OFLogger::DEBUG_LOG_LEVEL; + break; + default: + level = OFLogger::TRACE_LOG_LEVEL; + break; + } + + if (cinfo && DCM_dcmjpegLogger.isEnabledFor(level)) + { + char buffer[JMSG_LENGTH_MAX]; + (*cinfo->err->format_message)(OFreinterpret_cast(jpeg_common_struct*, cinfo), buffer); /* Create the message */ + DCM_dcmjpegLogger.forcedLog(level, buffer, __FILE__, __LINE__); + } +} diff --git a/dcmjpeg/libsrc/djeijg12.cc b/dcmjpeg/libsrc/djeijg12.cc new file mode 100644 index 00000000..7cad7374 --- /dev/null +++ b/dcmjpeg/libsrc/djeijg12.cc @@ -0,0 +1,574 @@ +/* + * + * Copyright (C) 1997-2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmjpeg + * + * Author: Marco Eichelberg, Norbert Olges + * + * Purpose: compression routines of the IJG JPEG library configured for 12 bits/sample. + * + */ + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmjpeg/djeijg12.h" +#include "dcmtk/dcmjpeg/djcparam.h" +#include "dcmtk/dcmdata/dcerror.h" + +#define INCLUDE_CSTDIO +#define INCLUDE_CSETJMP +#define INCLUDE_CSTRING +#include "dcmtk/ofstd/ofstdinc.h" + +// These two macros are re-defined in the IJG header files. +// We undefine them here and hope that IJG's configure has +// come to the same conclusion that we have... +#ifdef HAVE_STDLIB_H +#undef HAVE_STDLIB_H +#endif +#ifdef HAVE_STDDEF_H +#undef HAVE_STDDEF_H +#endif + +// use 16K blocks for temporary storage of compressed JPEG data +#define IJGE12_BLOCKSIZE 16384 + +BEGIN_EXTERN_C +#define boolean ijg_boolean +#include "jpeglib12.h" +#include "jerror12.h" +#include "jpegint12.h" +#undef boolean + +// disable any preprocessor magic the IJG library might be doing with the "const" keyword +#ifdef const +#undef const +#endif + +#ifdef USE_STD_CXX_INCLUDES +// Solaris defines longjmp() in namespace std, other compilers don't... +namespace std { } +using namespace std; +#endif + +// private error handler struct +struct DJEIJG12ErrorStruct +{ + // the standard IJG error handler object + struct jpeg_error_mgr pub; + + // our jump buffer + jmp_buf setjmp_buffer; + + // pointer to this + DJCompressIJG12Bit *instance; +}; + +// callback forward declarations +void DJEIJG12ErrorExit(j_common_ptr); +void DJEIJG12EmitMessage(j_common_ptr cinfo, int msg_level); +void DJEIJG12initDestination(j_compress_ptr cinfo); +ijg_boolean DJEIJG12emptyOutputBuffer(j_compress_ptr cinfo); +void DJEIJG12termDestination(j_compress_ptr cinfo); + +// helper methods to fix old-style casts warnings +static void OFjpeg_create_compress(j_compress_ptr cinfo) +{ + jpeg_create_compress(cinfo); +} + +static void OF_ERREXIT1(j_compress_ptr cinfo, int code, int p1) +{ + ERREXIT1(cinfo, code, p1); +} + +END_EXTERN_C + + +// error handler, executes longjmp + +void DJEIJG12ErrorExit(j_common_ptr cinfo) +{ + DJEIJG12ErrorStruct *myerr = OFreinterpret_cast(DJEIJG12ErrorStruct*, cinfo->err); + longjmp(myerr->setjmp_buffer, 1); +} + +// message handler for warning messages and the like +void DJEIJG12EmitMessage(j_common_ptr cinfo, int msg_level) +{ + DJEIJG12ErrorStruct *myerr = OFreinterpret_cast(DJEIJG12ErrorStruct*, cinfo->err); + myerr->instance->emitMessage(cinfo, msg_level); +} + +// callbacks for compress-destination-manager + +void DJEIJG12initDestination(j_compress_ptr cinfo) +{ + DJCompressIJG12Bit *encoder = OFreinterpret_cast(DJCompressIJG12Bit*, cinfo->client_data); + encoder->initDestination(cinfo); +} + +ijg_boolean DJEIJG12emptyOutputBuffer(j_compress_ptr cinfo) +{ + DJCompressIJG12Bit *encoder = OFreinterpret_cast(DJCompressIJG12Bit*, cinfo->client_data); + return encoder->emptyOutputBuffer(cinfo); +} + +void DJEIJG12termDestination(j_compress_ptr cinfo) +{ + DJCompressIJG12Bit *encoder = OFreinterpret_cast(DJCompressIJG12Bit*, cinfo->client_data); + encoder->termDestination(cinfo); +} + +/* + * jpeg_simple_spectral_selection() creates a scan script + * for progressive JPEG with spectral selection only, + * similar to jpeg_simple_progression() for full progression. + * The scan sequence for YCbCr is as proposed in the IJG documentation. + * The scan sequence for all other color models is somewhat arbitrary. + */ +static void jpeg_simple_spectral_selection(j_compress_ptr cinfo) +{ + int ncomps = cinfo->num_components; + jpeg_scan_info *scanptr = NULL; + int nscans = 0; + + /* Safety check to ensure start_compress not called yet. */ + if (cinfo->global_state != CSTATE_START) + { + OF_ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + } + + if (ncomps == 3 && cinfo->jpeg_color_space == JCS_YCbCr) nscans = 7; + else nscans = 1 + 2 * ncomps; /* 1 DC scan; 2 AC scans per component */ + + /* Allocate space for script. + * We need to put it in the permanent pool in case the application performs + * multiple compressions without changing the settings. To avoid a memory + * leak if jpeg_simple_spectral_selection is called repeatedly for the same JPEG + * object, we try to re-use previously allocated space, and we allocate + * enough space to handle YCbCr even if initially asked for grayscale. + */ + if (cinfo->script_space == NULL || cinfo->script_space_size < nscans) + { + cinfo->script_space_size = nscans > 7 ? nscans : 7; + cinfo->script_space = OFreinterpret_cast(jpeg_scan_info*, + (*cinfo->mem->alloc_small) (OFreinterpret_cast(j_common_ptr, cinfo), + JPOOL_PERMANENT, cinfo->script_space_size * sizeof(jpeg_scan_info))); + } + scanptr = cinfo->script_space; + cinfo->scan_info = scanptr; + cinfo->num_scans = nscans; + + if (ncomps == 3 && cinfo->jpeg_color_space == JCS_YCbCr) + { + /* Custom script for YCbCr color images. */ + + // Interleaved DC scan for Y,Cb,Cr: + scanptr[0].component_index[0] = 0; + scanptr[0].component_index[1] = 1; + scanptr[0].component_index[2] = 2; + scanptr[0].comps_in_scan = 3; + scanptr[0].Ss = 0; + scanptr[0].Se = 0; + scanptr[0].Ah = 0; + scanptr[0].Al = 0; + + // AC scans + // First two Y AC coefficients + scanptr[1].component_index[0] = 0; + scanptr[1].comps_in_scan = 1; + scanptr[1].Ss = 1; + scanptr[1].Se = 2; + scanptr[1].Ah = 0; + scanptr[1].Al = 0; + + // Three more + scanptr[2].component_index[0] = 0; + scanptr[2].comps_in_scan = 1; + scanptr[2].Ss = 3; + scanptr[2].Se = 5; + scanptr[2].Ah = 0; + scanptr[2].Al = 0; + + // All AC coefficients for Cb + scanptr[3].component_index[0] = 1; + scanptr[3].comps_in_scan = 1; + scanptr[3].Ss = 1; + scanptr[3].Se = 63; + scanptr[3].Ah = 0; + scanptr[3].Al = 0; + + // All AC coefficients for Cr + scanptr[4].component_index[0] = 2; + scanptr[4].comps_in_scan = 1; + scanptr[4].Ss = 1; + scanptr[4].Se = 63; + scanptr[4].Ah = 0; + scanptr[4].Al = 0; + + // More Y coefficients + scanptr[5].component_index[0] = 0; + scanptr[5].comps_in_scan = 1; + scanptr[5].Ss = 6; + scanptr[5].Se = 9; + scanptr[5].Ah = 0; + scanptr[5].Al = 0; + + // Remaining Y coefficients + scanptr[6].component_index[0] = 0; + scanptr[6].comps_in_scan = 1; + scanptr[6].Ss = 10; + scanptr[6].Se = 63; + scanptr[6].Ah = 0; + scanptr[6].Al = 0; + } + else + { + /* All-purpose script for other color spaces. */ + int j=0; + + // Interleaved DC scan for all components + for (j=0; jformat_message)(OFreinterpret_cast(jpeg_common_struct*, &cinfo), buffer); /* Create the message */ + jpeg_destroy_compress(&cinfo); + return makeOFCondition(OFM_dcmjpeg, EJCode_IJG12_Compression, OF_error, buffer); + } + OFjpeg_create_compress(&cinfo); + + // initialize client_data + cinfo.client_data = this; + + // Specify destination manager + jpeg_destination_mgr dest; + dest.init_destination = DJEIJG12initDestination; + dest.empty_output_buffer = DJEIJG12emptyOutputBuffer; + dest.term_destination = DJEIJG12termDestination; + cinfo.dest = &dest; + + cinfo.image_width = columns; + cinfo.image_height = rows; + cinfo.input_components = samplesPerPixel; + cinfo.in_color_space = getJpegColorSpace(colorSpace); + + jpeg_set_defaults(&cinfo); + + if (cparam->getCompressionColorSpaceConversion() != ECC_lossyYCbCr) + { + // prevent IJG library from doing any color space conversion + jpeg_set_colorspace (&cinfo, cinfo.in_color_space); + } + + cinfo.optimize_coding = OFTrue; // must always be true for 12 bit compression + + switch (modeofOperation) + { + case EJM_baseline: // baseline only supports 8 bits/sample. Assume sequential. + case EJM_sequential: + jpeg_set_quality(&cinfo, quality, 0); + break; + case EJM_spectralSelection: + jpeg_set_quality(&cinfo, quality, 0); + jpeg_simple_spectral_selection(&cinfo); + break; + case EJM_progressive: + jpeg_set_quality(&cinfo, quality, 0); + jpeg_simple_progression(&cinfo); + break; + case EJM_lossless: + // always disables any kind of color space conversion + jpeg_simple_lossless(&cinfo,psv,pt); + break; + } + + cinfo.smoothing_factor = cparam->getSmoothingFactor(); + + // initialize sampling factors + if (cinfo.jpeg_color_space == JCS_YCbCr) + { + switch(cparam->getSampleFactors()) + { + case ESS_444: /* 4:4:4 sampling (no subsampling) */ + cinfo.comp_info[0].h_samp_factor = 1; + cinfo.comp_info[0].v_samp_factor = 1; + break; + case ESS_422: /* 4:2:2 sampling (horizontal subsampling of chroma components) */ + cinfo.comp_info[0].h_samp_factor = 2; + cinfo.comp_info[0].v_samp_factor = 1; + break; + case ESS_411: /* 4:1:1 sampling (horizontal and vertical subsampling of chroma components) */ + cinfo.comp_info[0].h_samp_factor = 2; + cinfo.comp_info[0].v_samp_factor = 2; + break; + } + } + else + { + // JPEG color space is not YCbCr, disable subsampling. + cinfo.comp_info[0].h_samp_factor = 1; + cinfo.comp_info[0].v_samp_factor = 1; + } + + // all other components are set to 1x1 + for (int sfi=1; sfi< MAX_COMPONENTS; sfi++) + { + cinfo.comp_info[sfi].h_samp_factor = 1; + cinfo.comp_info[sfi].v_samp_factor = 1; + } + + JSAMPROW row_pointer[1]; + jpeg_start_compress(&cinfo,TRUE); + int row_stride = columns * samplesPerPixel; + while (cinfo.next_scanline < cinfo.image_height) + { + // JSAMPLE is signed, typecast to avoid a warning + row_pointer[0] = OFreinterpret_cast(JSAMPLE*, image_buffer + (cinfo.next_scanline * row_stride)); + jpeg_write_scanlines(&cinfo, row_pointer, 1); + } + jpeg_finish_compress(&cinfo); + jpeg_destroy_compress(&cinfo); + + length = OFstatic_cast(Uint32, bytesInLastBlock); + if (pixelDataList.size() > 1) length += OFstatic_cast(Uint32, (pixelDataList.size() - 1)*IJGE12_BLOCKSIZE); + if (length % 2) length++; // ensure even length + + to = new Uint8[length]; + if (to == NULL) return EC_MemoryExhausted; + if (length > 0) to[length-1] = 0; + + size_t offset=0; + OFListIterator(unsigned char *) first = pixelDataList.begin(); + OFListIterator(unsigned char *) last = pixelDataList.end(); + OFListIterator(unsigned char *) shortBlock = last; + --shortBlock; + while (first != last) + { + if (first == shortBlock) + { + memcpy(to+offset, *first, bytesInLastBlock); + offset += bytesInLastBlock; + } + else + { + memcpy(to+offset, *first, IJGE12_BLOCKSIZE); + offset += IJGE12_BLOCKSIZE; + } + ++first; + } + cleanup(); + + return EC_Normal; +} + +void DJCompressIJG12Bit::initDestination(jpeg_compress_struct *cinfo) +{ + cleanup(); // erase old list of compressed blocks, if any + + unsigned char *newBlock = new unsigned char[IJGE12_BLOCKSIZE]; + if (newBlock) + { + pixelDataList.push_back(newBlock); + cinfo->dest->next_output_byte = newBlock; + cinfo->dest->free_in_buffer = IJGE12_BLOCKSIZE; + } + else + { + cinfo->dest->next_output_byte = NULL; + cinfo->dest->free_in_buffer = 0; + } +} + +int DJCompressIJG12Bit::emptyOutputBuffer(jpeg_compress_struct *cinfo) +{ + bytesInLastBlock = 0; + unsigned char *newBlock = new unsigned char[IJGE12_BLOCKSIZE]; + if (newBlock) + { + pixelDataList.push_back(newBlock); + cinfo->dest->next_output_byte = newBlock; + cinfo->dest->free_in_buffer = IJGE12_BLOCKSIZE; + } + else + { + cinfo->dest->next_output_byte = NULL; + cinfo->dest->free_in_buffer = 0; + OF_ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, 0xFF); + } + return TRUE; +} + + +void DJCompressIJG12Bit::termDestination(jpeg_compress_struct *cinfo) +{ + bytesInLastBlock = IJGE12_BLOCKSIZE - cinfo->dest->free_in_buffer; +} + +void DJCompressIJG12Bit::cleanup() +{ + OFListIterator(unsigned char *) first = pixelDataList.begin(); + OFListIterator(unsigned char *) last = pixelDataList.end(); + while (first != last) + { + delete[] *first; + first = pixelDataList.erase(first); + } + bytesInLastBlock = 0; +} + +void DJCompressIJG12Bit::emitMessage(void *arg, int msg_level) const +{ + jpeg_common_struct *cinfo = OFreinterpret_cast(jpeg_common_struct*, arg); + + // This is how we map the message levels: + // -1 - 0: Warning (could also be errors, but no way to find out) + // 1 : Debug + // Everything else: Trace (No point in splitting this further up) + OFLogger::LogLevel level; + + switch (msg_level) + { + case -1: + case 0: + level = OFLogger::WARN_LOG_LEVEL; + break; + case 1: + level = OFLogger::DEBUG_LOG_LEVEL; + break; + default: + level = OFLogger::TRACE_LOG_LEVEL; + break; + } + + if (cinfo && DCM_dcmjpegLogger.isEnabledFor(level)) + { + char buffer[JMSG_LENGTH_MAX]; + (*cinfo->err->format_message)(cinfo, buffer); /* Create the message */ + DCM_dcmjpegLogger.forcedLog(level, buffer, __FILE__, __LINE__); + } +} diff --git a/dcmjpeg/libsrc/djeijg16.cc b/dcmjpeg/libsrc/djeijg16.cc new file mode 100644 index 00000000..e045cd0f --- /dev/null +++ b/dcmjpeg/libsrc/djeijg16.cc @@ -0,0 +1,410 @@ +/* + * + * Copyright (C) 1997-2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmjpeg + * + * Author: Marco Eichelberg, Norbert Olges + * + * Purpose: compression routines of the IJG JPEG library configured for 16 bits/sample. + * + */ + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmjpeg/djeijg16.h" +#include "dcmtk/dcmjpeg/djcparam.h" +#include "dcmtk/dcmdata/dcerror.h" + +#define INCLUDE_CSTDIO +#define INCLUDE_CSETJMP +#define INCLUDE_CSTRING +#include "dcmtk/ofstd/ofstdinc.h" + +// These two macros are re-defined in the IJG header files. +// We undefine them here and hope that IJG's configure has +// come to the same conclusion that we have... +#ifdef HAVE_STDLIB_H +#undef HAVE_STDLIB_H +#endif +#ifdef HAVE_STDDEF_H +#undef HAVE_STDDEF_H +#endif + +// use 16K blocks for temporary storage of compressed JPEG data +#define IJGE16_BLOCKSIZE 16384 + +BEGIN_EXTERN_C +#define boolean ijg_boolean +#include "jpeglib16.h" +#include "jerror16.h" +#include "jpegint16.h" +#undef boolean + +// disable any preprocessor magic the IJG library might be doing with the "const" keyword +#ifdef const +#undef const +#endif + +#ifdef USE_STD_CXX_INCLUDES +// Solaris defines longjmp() in namespace std, other compilers don't... +namespace std { } +using namespace std; +#endif + +// private error handler struct +struct DJEIJG16ErrorStruct +{ + // the standard IJG error handler object + struct jpeg_error_mgr pub; + + // our jump buffer + jmp_buf setjmp_buffer; + + // pointer to this + DJCompressIJG16Bit *instance; +}; + +// callback forward declarations +void DJEIJG16ErrorExit(j_common_ptr); +void DJEIJG16EmitMessage(j_common_ptr cinfo, int msg_level); +void DJEIJG16initDestination(j_compress_ptr cinfo); +ijg_boolean DJEIJG16emptyOutputBuffer(j_compress_ptr cinfo); +void DJEIJG16termDestination(j_compress_ptr cinfo); + +// helper methods to fix old-style casts warnings +static void OFjpeg_create_compress(j_compress_ptr cinfo) +{ + jpeg_create_compress(cinfo); +} + +static void OF_ERREXIT1(j_compress_ptr cinfo, int code, int p1) +{ + ERREXIT1(cinfo, code, p1); +} + +END_EXTERN_C + + +// error handler, executes longjmp + +void DJEIJG16ErrorExit(j_common_ptr cinfo) +{ + DJEIJG16ErrorStruct *myerr = OFreinterpret_cast(DJEIJG16ErrorStruct*, cinfo->err); + longjmp(myerr->setjmp_buffer, 1); +} + +// message handler for warning messages and the like +void DJEIJG16EmitMessage(j_common_ptr cinfo, int msg_level) +{ + DJEIJG16ErrorStruct *myerr = OFreinterpret_cast(DJEIJG16ErrorStruct*, cinfo->err); + myerr->instance->emitMessage(cinfo, msg_level); +} + + +// callbacks for compress-destination-manager + +void DJEIJG16initDestination(j_compress_ptr cinfo) +{ + DJCompressIJG16Bit *encoder = OFreinterpret_cast(DJCompressIJG16Bit*, cinfo->client_data); + encoder->initDestination(cinfo); +} + +ijg_boolean DJEIJG16emptyOutputBuffer(j_compress_ptr cinfo) +{ + DJCompressIJG16Bit *encoder = OFreinterpret_cast(DJCompressIJG16Bit*, cinfo->client_data); + return encoder->emptyOutputBuffer(cinfo); +} + +void DJEIJG16termDestination(j_compress_ptr cinfo) +{ + DJCompressIJG16Bit *encoder = OFreinterpret_cast(DJCompressIJG16Bit*, cinfo->client_data); + encoder->termDestination(cinfo); +} + + +// converts dcmtk color space to IJG color space + +static J_COLOR_SPACE getJpegColorSpace(EP_Interpretation interpr) +{ + switch (interpr) + { + case EPI_Unknown :return JCS_UNKNOWN; + case EPI_Monochrome1 : return JCS_GRAYSCALE; + case EPI_Monochrome2 : return JCS_GRAYSCALE; + case EPI_PaletteColor : return JCS_UNKNOWN; + case EPI_RGB : return JCS_RGB; + case EPI_HSV : return JCS_UNKNOWN; + case EPI_ARGB : return JCS_RGB; + case EPI_CMYK : return JCS_CMYK; + case EPI_YBR_Full : return JCS_YCbCr; + case EPI_YBR_Full_422 : return JCS_YCbCr; + case EPI_YBR_Partial_422 : return JCS_YCbCr; + default : return JCS_UNKNOWN; + } +} + +DJCompressIJG16Bit::DJCompressIJG16Bit(const DJCodecParameter& cp, EJ_Mode mode, int prediction, int ptrans) +: DJEncoder() +, cparam(&cp) +, psv(prediction) +, pt(ptrans) +, modeofOperation(mode) +, pixelDataList() +, bytesInLastBlock(0) +{ + assert(mode == EJM_lossless); +} + +DJCompressIJG16Bit::~DJCompressIJG16Bit() +{ + cleanup(); +} + +OFCondition DJCompressIJG16Bit::encode( + Uint16 /* columns */, + Uint16 /* rows */, + EP_Interpretation /* interpr */, + Uint16 /* samplesPerPixel */, + Uint8 * /* image_buffer */, + Uint8 *& /* to */, + Uint32 & /* length */) +{ + return EC_IllegalCall; +} + +OFCondition DJCompressIJG16Bit::encode( + Uint16 columns, + Uint16 rows, + EP_Interpretation colorSpace, + Uint16 samplesPerPixel, + Uint16 * image_buffer, + Uint8 * & to, + Uint32 & length) +{ + + struct jpeg_compress_struct cinfo; + struct DJEIJG16ErrorStruct jerr; + cinfo.err = jpeg_std_error(&jerr.pub); + jerr.instance = this; + jerr.pub.error_exit = DJEIJG16ErrorExit; + jerr.pub.emit_message = DJEIJG16EmitMessage; + if (setjmp(jerr.setjmp_buffer)) + { + // the IJG error handler will cause the following code to be executed + char buffer[JMSG_LENGTH_MAX]; + (*cinfo.err->format_message)(OFreinterpret_cast(jpeg_common_struct*, &cinfo), buffer); /* Create the message */ + jpeg_destroy_compress(&cinfo); + return makeOFCondition(OFM_dcmjpeg, EJCode_IJG16_Compression, OF_error, buffer); + } + OFjpeg_create_compress(&cinfo); + + // initialize client_data + cinfo.client_data = this; + + // Specify destination manager + jpeg_destination_mgr dest; + dest.init_destination = DJEIJG16initDestination; + dest.empty_output_buffer = DJEIJG16emptyOutputBuffer; + dest.term_destination = DJEIJG16termDestination; + cinfo.dest = &dest; + + cinfo.image_width = columns; + cinfo.image_height = rows; + cinfo.input_components = samplesPerPixel; + cinfo.in_color_space = getJpegColorSpace(colorSpace); + + jpeg_set_defaults(&cinfo); + + if (cparam->getCompressionColorSpaceConversion() != ECC_lossyYCbCr) + { + // prevent IJG library from doing any color space conversion + jpeg_set_colorspace (&cinfo, cinfo.in_color_space); + } + + cinfo.optimize_coding = OFTrue; // must always be true for 16 bit compression + + switch (modeofOperation) + { + case EJM_lossless: + // always disables any kind of color space conversion + jpeg_simple_lossless(&cinfo,psv,pt); + break; + default: + return makeOFCondition(OFM_dcmjpeg, EJCode_IJG16_Compression, OF_error, "JPEG with 16 bits/sample only allowed with lossless compression"); + /* break; */ + } + + cinfo.smoothing_factor = cparam->getSmoothingFactor(); + + // initialize sampling factors + if (cinfo.jpeg_color_space == JCS_YCbCr) + { + switch(cparam->getSampleFactors()) + { + case ESS_444: /* 4:4:4 sampling (no subsampling) */ + cinfo.comp_info[0].h_samp_factor = 1; + cinfo.comp_info[0].v_samp_factor = 1; + break; + case ESS_422: /* 4:2:2 sampling (horizontal subsampling of chroma components) */ + cinfo.comp_info[0].h_samp_factor = 2; + cinfo.comp_info[0].v_samp_factor = 1; + break; + case ESS_411: /* 4:1:1 sampling (horizontal and vertical subsampling of chroma components) */ + cinfo.comp_info[0].h_samp_factor = 2; + cinfo.comp_info[0].v_samp_factor = 2; + break; + } + } + else + { + // JPEG color space is not YCbCr, disable subsampling. + cinfo.comp_info[0].h_samp_factor = 1; + cinfo.comp_info[0].v_samp_factor = 1; + } + + // all other components are set to 1x1 + for (int sfi=1; sfi< MAX_COMPONENTS; sfi++) + { + cinfo.comp_info[sfi].h_samp_factor = 1; + cinfo.comp_info[sfi].v_samp_factor = 1; + } + + JSAMPROW row_pointer[1]; + jpeg_start_compress(&cinfo,TRUE); + int row_stride = columns * samplesPerPixel; + while (cinfo.next_scanline < cinfo.image_height) + { + // JSAMPLE might be signed, typecast to avoid a warning + row_pointer[0] = OFreinterpret_cast(JSAMPLE*, image_buffer + (cinfo.next_scanline * row_stride)); + jpeg_write_scanlines(&cinfo, row_pointer, 1); + } + jpeg_finish_compress(&cinfo); + jpeg_destroy_compress(&cinfo); + + length = OFstatic_cast(Uint32, bytesInLastBlock); + if (pixelDataList.size() > 1) length += OFstatic_cast(Uint32, (pixelDataList.size() - 1)*IJGE16_BLOCKSIZE); + if (length % 2) length++; // ensure even length + + to = new Uint8[length]; + if (to == NULL) return EC_MemoryExhausted; + if (length > 0) to[length-1] = 0; + + size_t offset=0; + OFListIterator(unsigned char *) first = pixelDataList.begin(); + OFListIterator(unsigned char *) last = pixelDataList.end(); + OFListIterator(unsigned char *) shortBlock = last; + --shortBlock; + while (first != last) + { + if (first == shortBlock) + { + memcpy(to+offset, *first, bytesInLastBlock); + offset += bytesInLastBlock; + } + else + { + memcpy(to+offset, *first, IJGE16_BLOCKSIZE); + offset += IJGE16_BLOCKSIZE; + } + ++first; + } + cleanup(); + + return EC_Normal; +} + +void DJCompressIJG16Bit::initDestination(jpeg_compress_struct *cinfo) +{ + cleanup(); // erase old list of compressed blocks, if any + + unsigned char *newBlock = new unsigned char[IJGE16_BLOCKSIZE]; + if (newBlock) + { + pixelDataList.push_back(newBlock); + cinfo->dest->next_output_byte = newBlock; + cinfo->dest->free_in_buffer = IJGE16_BLOCKSIZE; + } + else + { + cinfo->dest->next_output_byte = NULL; + cinfo->dest->free_in_buffer = 0; + } +} + +int DJCompressIJG16Bit::emptyOutputBuffer(jpeg_compress_struct *cinfo) +{ + bytesInLastBlock = 0; + unsigned char *newBlock = new unsigned char[IJGE16_BLOCKSIZE]; + if (newBlock) + { + pixelDataList.push_back(newBlock); + cinfo->dest->next_output_byte = newBlock; + cinfo->dest->free_in_buffer = IJGE16_BLOCKSIZE; + } + else + { + cinfo->dest->next_output_byte = NULL; + cinfo->dest->free_in_buffer = 0; + OF_ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, 0xFF); + } + return TRUE; +} + + +void DJCompressIJG16Bit::termDestination(jpeg_compress_struct *cinfo) +{ + bytesInLastBlock = IJGE16_BLOCKSIZE - cinfo->dest->free_in_buffer; +} + +void DJCompressIJG16Bit::cleanup() +{ + OFListIterator(unsigned char *) first = pixelDataList.begin(); + OFListIterator(unsigned char *) last = pixelDataList.end(); + while (first != last) + { + delete[] *first; + first = pixelDataList.erase(first); + } + bytesInLastBlock = 0; +} + +void DJCompressIJG16Bit::emitMessage(void *arg, int msg_level) const +{ + jpeg_common_struct *cinfo = OFreinterpret_cast(jpeg_common_struct*, arg); + + // This is how we map the message levels: + // -1 - 0: Warning (could also be errors, but no way to find out) + // 1 : Debug + // Everything else: Trace (No point in splitting this further up) + OFLogger::LogLevel level; + + switch (msg_level) + { + case -1: + case 0: + level = OFLogger::WARN_LOG_LEVEL; + break; + case 1: + level = OFLogger::DEBUG_LOG_LEVEL; + break; + default: + level = OFLogger::TRACE_LOG_LEVEL; + break; + } + + if (cinfo && DCM_dcmjpegLogger.isEnabledFor(level)) + { + char buffer[JMSG_LENGTH_MAX]; + (*cinfo->err->format_message)(cinfo, buffer); /* Create the message */ + DCM_dcmjpegLogger.forcedLog(level, buffer, __FILE__, __LINE__); + } +} diff --git a/dcmjpeg/libsrc/djeijg8.cc b/dcmjpeg/libsrc/djeijg8.cc new file mode 100644 index 00000000..01d228a4 --- /dev/null +++ b/dcmjpeg/libsrc/djeijg8.cc @@ -0,0 +1,576 @@ +/* + * + * Copyright (C) 1997-2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmjpeg + * + * Author: Marco Eichelberg, Norbert Olges + * + * Purpose: compression routines of the IJG JPEG library configured for 8 bits/sample. + * + */ + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmjpeg/djeijg8.h" +#include "dcmtk/dcmjpeg/djcparam.h" +#include "dcmtk/dcmdata/dcerror.h" + +#define INCLUDE_CSTDIO +#define INCLUDE_CSETJMP +#define INCLUDE_CSTRING +#include "dcmtk/ofstd/ofstdinc.h" + +// These two macros are re-defined in the IJG header files. +// We undefine them here and hope that IJG's configure has +// come to the same conclusion that we have... +#ifdef HAVE_STDLIB_H +#undef HAVE_STDLIB_H +#endif +#ifdef HAVE_STDDEF_H +#undef HAVE_STDDEF_H +#endif + +// use 16K blocks for temporary storage of compressed JPEG data +#define IJGE8_BLOCKSIZE 16384 + +BEGIN_EXTERN_C +#define boolean ijg_boolean +#include "jpeglib8.h" +#include "jerror8.h" +#include "jpegint8.h" +#undef boolean + +// disable any preprocessor magic the IJG library might be doing with the "const" keyword +#ifdef const +#undef const +#endif + +#ifdef USE_STD_CXX_INCLUDES +// Solaris defines longjmp() in namespace std, other compilers don't... +namespace std { } +using namespace std; +#endif + +// private error handler struct +struct DJEIJG8ErrorStruct +{ + // the standard IJG error handler object + struct jpeg_error_mgr pub; + + // our jump buffer + jmp_buf setjmp_buffer; + + // pointer to this + DJCompressIJG8Bit *instance; +}; + +// callback forward declarations +void DJEIJG8ErrorExit(j_common_ptr); +void DJEIJG8EmitMessage(j_common_ptr cinfo, int msg_level); +void DJEIJG8initDestination(j_compress_ptr cinfo); +ijg_boolean DJEIJG8emptyOutputBuffer(j_compress_ptr cinfo); +void DJEIJG8termDestination(j_compress_ptr cinfo); + +// helper methods to fix old-style casts warnings +static void OFjpeg_create_compress(j_compress_ptr cinfo) +{ + jpeg_create_compress(cinfo); +} + +static void OF_ERREXIT1(j_compress_ptr cinfo, int code, int p1) +{ + ERREXIT1(cinfo, code, p1); +} + +END_EXTERN_C + + +// error handler, executes longjmp + +void DJEIJG8ErrorExit(j_common_ptr cinfo) +{ + DJEIJG8ErrorStruct *myerr = OFreinterpret_cast(DJEIJG8ErrorStruct*, cinfo->err); + longjmp(myerr->setjmp_buffer, 1); +} + +// message handler for warning messages and the like +void DJEIJG8EmitMessage(j_common_ptr cinfo, int msg_level) +{ + DJEIJG8ErrorStruct *myerr = OFreinterpret_cast(DJEIJG8ErrorStruct*, cinfo->err); + myerr->instance->emitMessage(cinfo, msg_level); +} + + +// callbacks for compress-destination-manager + +void DJEIJG8initDestination(j_compress_ptr cinfo) +{ + DJCompressIJG8Bit *encoder = OFreinterpret_cast(DJCompressIJG8Bit*, cinfo->client_data); + encoder->initDestination(cinfo); +} + +ijg_boolean DJEIJG8emptyOutputBuffer(j_compress_ptr cinfo) +{ + DJCompressIJG8Bit *encoder = OFreinterpret_cast(DJCompressIJG8Bit*, cinfo->client_data); + return encoder->emptyOutputBuffer(cinfo); +} + +void DJEIJG8termDestination(j_compress_ptr cinfo) +{ + DJCompressIJG8Bit *encoder = OFreinterpret_cast(DJCompressIJG8Bit*, cinfo->client_data); + encoder->termDestination(cinfo); +} + +/* + * jpeg_simple_spectral_selection() creates a scan script + * for progressive JPEG with spectral selection only, + * similar to jpeg_simple_progression() for full progression. + * The scan sequence for YCbCr is as proposed in the IJG documentation. + * The scan sequence for all other color models is somewhat arbitrary. + */ +static void jpeg_simple_spectral_selection(j_compress_ptr cinfo) +{ + int ncomps = cinfo->num_components; + jpeg_scan_info *scanptr = NULL; + int nscans = 0; + + /* Safety check to ensure start_compress not called yet. */ + if (cinfo->global_state != CSTATE_START) + { + OF_ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + } + + if (ncomps == 3 && cinfo->jpeg_color_space == JCS_YCbCr) nscans = 7; + else nscans = 1 + 2 * ncomps; /* 1 DC scan; 2 AC scans per component */ + + /* Allocate space for script. + * We need to put it in the permanent pool in case the application performs + * multiple compressions without changing the settings. To avoid a memory + * leak if jpeg_simple_spectral_selection is called repeatedly for the same JPEG + * object, we try to re-use previously allocated space, and we allocate + * enough space to handle YCbCr even if initially asked for grayscale. + */ + if (cinfo->script_space == NULL || cinfo->script_space_size < nscans) + { + cinfo->script_space_size = nscans > 7 ? nscans : 7; + cinfo->script_space = OFreinterpret_cast(jpeg_scan_info*, + (*cinfo->mem->alloc_small) (OFreinterpret_cast(j_common_ptr, cinfo), + JPOOL_PERMANENT, cinfo->script_space_size * sizeof(jpeg_scan_info))); + } + scanptr = cinfo->script_space; + cinfo->scan_info = scanptr; + cinfo->num_scans = nscans; + + if (ncomps == 3 && cinfo->jpeg_color_space == JCS_YCbCr) + { + /* Custom script for YCbCr color images. */ + + // Interleaved DC scan for Y,Cb,Cr: + scanptr[0].component_index[0] = 0; + scanptr[0].component_index[1] = 1; + scanptr[0].component_index[2] = 2; + scanptr[0].comps_in_scan = 3; + scanptr[0].Ss = 0; + scanptr[0].Se = 0; + scanptr[0].Ah = 0; + scanptr[0].Al = 0; + + // AC scans + // First two Y AC coefficients + scanptr[1].component_index[0] = 0; + scanptr[1].comps_in_scan = 1; + scanptr[1].Ss = 1; + scanptr[1].Se = 2; + scanptr[1].Ah = 0; + scanptr[1].Al = 0; + + // Three more + scanptr[2].component_index[0] = 0; + scanptr[2].comps_in_scan = 1; + scanptr[2].Ss = 3; + scanptr[2].Se = 5; + scanptr[2].Ah = 0; + scanptr[2].Al = 0; + + // All AC coefficients for Cb + scanptr[3].component_index[0] = 1; + scanptr[3].comps_in_scan = 1; + scanptr[3].Ss = 1; + scanptr[3].Se = 63; + scanptr[3].Ah = 0; + scanptr[3].Al = 0; + + // All AC coefficients for Cr + scanptr[4].component_index[0] = 2; + scanptr[4].comps_in_scan = 1; + scanptr[4].Ss = 1; + scanptr[4].Se = 63; + scanptr[4].Ah = 0; + scanptr[4].Al = 0; + + // More Y coefficients + scanptr[5].component_index[0] = 0; + scanptr[5].comps_in_scan = 1; + scanptr[5].Ss = 6; + scanptr[5].Se = 9; + scanptr[5].Ah = 0; + scanptr[5].Al = 0; + + // Remaining Y coefficients + scanptr[6].component_index[0] = 0; + scanptr[6].comps_in_scan = 1; + scanptr[6].Ss = 10; + scanptr[6].Se = 63; + scanptr[6].Ah = 0; + scanptr[6].Al = 0; + } + else + { + /* All-purpose script for other color spaces. */ + int j=0; + + // Interleaved DC scan for all components + for (j=0; jformat_message)(OFreinterpret_cast(jpeg_common_struct*, &cinfo), buffer); /* Create the message */ + jpeg_destroy_compress(&cinfo); + return makeOFCondition(OFM_dcmjpeg, EJCode_IJG8_Compression, OF_error, buffer); + } + OFjpeg_create_compress(&cinfo); + + // initialize client_data + cinfo.client_data = this; + + // Specify destination manager + jpeg_destination_mgr dest; + dest.init_destination = DJEIJG8initDestination; + dest.empty_output_buffer = DJEIJG8emptyOutputBuffer; + dest.term_destination = DJEIJG8termDestination; + cinfo.dest = &dest; + + cinfo.image_width = columns; + cinfo.image_height = rows; + cinfo.input_components = samplesPerPixel; + cinfo.in_color_space = getJpegColorSpace(colorSpace); + + jpeg_set_defaults(&cinfo); + + if (cparam->getCompressionColorSpaceConversion() != ECC_lossyYCbCr) + { + // prevent IJG library from doing any color space conversion + jpeg_set_colorspace (&cinfo, cinfo.in_color_space); + } + + cinfo.optimize_coding = cparam->getOptimizeHuffmanCoding(); + + switch (modeofOperation) + { + case EJM_baseline: + jpeg_set_quality(&cinfo, quality, 1); + break; + case EJM_sequential: + jpeg_set_quality(&cinfo, quality, 0); + break; + case EJM_spectralSelection: + jpeg_set_quality(&cinfo, quality, 0); + jpeg_simple_spectral_selection(&cinfo); + break; + case EJM_progressive: + jpeg_set_quality(&cinfo, quality, 0); + jpeg_simple_progression(&cinfo); + break; + case EJM_lossless: + // always disables any kind of color space conversion + jpeg_simple_lossless(&cinfo,psv,pt); + break; + } + + cinfo.smoothing_factor = cparam->getSmoothingFactor(); + + // initialize sampling factors + if (cinfo.jpeg_color_space == JCS_YCbCr) + { + switch(cparam->getSampleFactors()) + { + case ESS_444: /* 4:4:4 sampling (no subsampling) */ + cinfo.comp_info[0].h_samp_factor = 1; + cinfo.comp_info[0].v_samp_factor = 1; + break; + case ESS_422: /* 4:2:2 sampling (horizontal subsampling of chroma components) */ + cinfo.comp_info[0].h_samp_factor = 2; + cinfo.comp_info[0].v_samp_factor = 1; + break; + case ESS_411: /* 4:1:1 sampling (horizontal and vertical subsampling of chroma components) */ + cinfo.comp_info[0].h_samp_factor = 2; + cinfo.comp_info[0].v_samp_factor = 2; + break; + } + } + else + { + // JPEG color space is not YCbCr, disable subsampling. + cinfo.comp_info[0].h_samp_factor = 1; + cinfo.comp_info[0].v_samp_factor = 1; + } + + // all other components are set to 1x1 + for (int sfi=1; sfi< MAX_COMPONENTS; sfi++) + { + cinfo.comp_info[sfi].h_samp_factor = 1; + cinfo.comp_info[sfi].v_samp_factor = 1; + } + + JSAMPROW row_pointer[1]; + jpeg_start_compress(&cinfo,TRUE); + int row_stride = columns * samplesPerPixel; + while (cinfo.next_scanline < cinfo.image_height) + { + row_pointer[0] = & image_buffer[cinfo.next_scanline * row_stride]; + jpeg_write_scanlines(&cinfo, row_pointer, 1); + } + jpeg_finish_compress(&cinfo); + jpeg_destroy_compress(&cinfo); + + length = OFstatic_cast(Uint32, bytesInLastBlock); + if (pixelDataList.size() > 1) length += OFstatic_cast(Uint32, (pixelDataList.size() - 1)*IJGE8_BLOCKSIZE); + if (length % 2) length++; // ensure even length + + to = new Uint8[length]; + if (to == NULL) return EC_MemoryExhausted; + if (length > 0) to[length-1] = 0; + + size_t offset=0; + OFListIterator(unsigned char *) first = pixelDataList.begin(); + OFListIterator(unsigned char *) last = pixelDataList.end(); + OFListIterator(unsigned char *) shortBlock = last; + --shortBlock; + while (first != last) + { + if (first == shortBlock) + { + memcpy(to+offset, *first, bytesInLastBlock); + offset += bytesInLastBlock; + } + else + { + memcpy(to+offset, *first, IJGE8_BLOCKSIZE); + offset += IJGE8_BLOCKSIZE; + } + ++first; + } + cleanup(); + return EC_Normal; +} + +void DJCompressIJG8Bit::initDestination(jpeg_compress_struct *cinfo) +{ + cleanup(); // erase old list of compressed blocks, if any + + unsigned char *newBlock = new unsigned char[IJGE8_BLOCKSIZE]; + if (newBlock) + { + pixelDataList.push_back(newBlock); + cinfo->dest->next_output_byte = newBlock; + cinfo->dest->free_in_buffer = IJGE8_BLOCKSIZE; + } + else + { + cinfo->dest->next_output_byte = NULL; + cinfo->dest->free_in_buffer = 0; + } +} + +int DJCompressIJG8Bit::emptyOutputBuffer(jpeg_compress_struct *cinfo) +{ + bytesInLastBlock = 0; + unsigned char *newBlock = new unsigned char[IJGE8_BLOCKSIZE]; + if (newBlock) + { + pixelDataList.push_back(newBlock); + cinfo->dest->next_output_byte = newBlock; + cinfo->dest->free_in_buffer = IJGE8_BLOCKSIZE; + } + else + { + // should never happen + cinfo->dest->next_output_byte = NULL; + cinfo->dest->free_in_buffer = 0; + OF_ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, 0xFF); + } + return TRUE; +} + + +void DJCompressIJG8Bit::termDestination(jpeg_compress_struct *cinfo) +{ + bytesInLastBlock = IJGE8_BLOCKSIZE - cinfo->dest->free_in_buffer; +} + +void DJCompressIJG8Bit::cleanup() +{ + OFListIterator(unsigned char *) first = pixelDataList.begin(); + OFListIterator(unsigned char *) last = pixelDataList.end(); + while (first != last) + { + delete[] *first; + first = pixelDataList.erase(first); + } + bytesInLastBlock = 0; +} + +void DJCompressIJG8Bit::emitMessage(void *arg, int msg_level) const +{ + jpeg_common_struct *cinfo = OFreinterpret_cast(jpeg_common_struct*, arg); + + // This is how we map the message levels: + // -1 - 0: Warning (could also be errors, but no way to find out) + // 1 : Debug + // Everything else: Trace (No point in splitting this further up) + OFLogger::LogLevel level; + + switch (msg_level) + { + case -1: + case 0: + level = OFLogger::WARN_LOG_LEVEL; + break; + case 1: + level = OFLogger::DEBUG_LOG_LEVEL; + break; + default: + level = OFLogger::TRACE_LOG_LEVEL; + break; + } + + if (cinfo && DCM_dcmjpegLogger.isEnabledFor(level)) + { + char buffer[JMSG_LENGTH_MAX]; + (*cinfo->err->format_message)(cinfo, buffer); /* Create the message */ + DCM_dcmjpegLogger.forcedLog(level, buffer, __FILE__, __LINE__); + } +} diff --git a/dcmjpeg/libsrc/djencbas.cc b/dcmjpeg/libsrc/djencbas.cc new file mode 100644 index 00000000..e6d46155 --- /dev/null +++ b/dcmjpeg/libsrc/djencbas.cc @@ -0,0 +1,81 @@ +/* + * + * Copyright (C) 2001-2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmjpeg + * + * Author: Marco Eichelberg, Norbert Olges + * + * Purpose: Codec class for encoding JPEG Baseline (lossy, 8-bit) + * + */ + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmjpeg/djencbas.h" +#include "dcmtk/dcmjpeg/djcparam.h" +#include "dcmtk/dcmjpeg/djrploss.h" +#include "dcmtk/dcmjpeg/djeijg8.h" + + +DJEncoderBaseline::DJEncoderBaseline() +: DJCodecEncoder() +{ +} + + +DJEncoderBaseline::~DJEncoderBaseline() +{ +} + + +E_TransferSyntax DJEncoderBaseline::supportedTransferSyntax() const +{ + return EXS_JPEGProcess1; +} + + +OFBool DJEncoderBaseline::isLosslessProcess() const +{ + return OFFalse; +} + + +void DJEncoderBaseline::createDerivationDescription( + const DcmRepresentationParameter * toRepParam, + const DJCodecParameter * /* cp */, + Uint8 /* bitsPerSample */ , + double ratio, + OFString& derivationDescription) const +{ + DJ_RPLossy defaultRP; + const DJ_RPLossy *rp = toRepParam ? OFreinterpret_cast(const DJ_RPLossy*, toRepParam) : &defaultRP ; + char buf[64]; + + derivationDescription = "Lossy compression with JPEG baseline, IJG quality factor "; + sprintf(buf, "%u", rp->getQuality()); + derivationDescription += buf; + derivationDescription += ", compression ratio "; + appendCompressionRatio(derivationDescription, ratio); +} + + +DJEncoder *DJEncoderBaseline::createEncoderInstance( + const DcmRepresentationParameter * toRepParam, + const DJCodecParameter *cp, + Uint8 /* bitsPerSample */) const +{ + DJ_RPLossy defaultRP; + const DJ_RPLossy *rp = toRepParam ? OFreinterpret_cast(const DJ_RPLossy*, toRepParam) : &defaultRP ; + DJCompressIJG8Bit *result = new DJCompressIJG8Bit(*cp, EJM_baseline, OFstatic_cast(Uint8, rp->getQuality())); + + return result; +} diff --git a/dcmjpeg/libsrc/djencext.cc b/dcmjpeg/libsrc/djencext.cc new file mode 100644 index 00000000..172bcbfa --- /dev/null +++ b/dcmjpeg/libsrc/djencext.cc @@ -0,0 +1,86 @@ +/* + * + * Copyright (C) 2001-2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmjpeg + * + * Author: Marco Eichelberg, Norbert Olges + * + * Purpose: Codec class for encoding JPEG Extended Sequential (lossy, 8/12-bit) + * + */ + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmjpeg/djencext.h" +#include "dcmtk/dcmjpeg/djcparam.h" +#include "dcmtk/dcmjpeg/djrploss.h" +#include "dcmtk/dcmjpeg/djeijg8.h" +#include "dcmtk/dcmjpeg/djeijg12.h" + + +DJEncoderExtended::DJEncoderExtended() +: DJCodecEncoder() +{ +} + + +DJEncoderExtended::~DJEncoderExtended() +{ +} + + +E_TransferSyntax DJEncoderExtended::supportedTransferSyntax() const +{ + return EXS_JPEGProcess2_4; +} + + +OFBool DJEncoderExtended::isLosslessProcess() const +{ + return OFFalse; +} + +void DJEncoderExtended::createDerivationDescription( + const DcmRepresentationParameter * toRepParam, + const DJCodecParameter * /* cp */ , + Uint8 bitsPerSample, + double ratio, + OFString& derivationDescription) const +{ + DJ_RPLossy defaultRP; + const DJ_RPLossy *rp = toRepParam ? OFreinterpret_cast(const DJ_RPLossy*, toRepParam) : &defaultRP ; + char buf[64]; + + derivationDescription = "Lossy compression with JPEG extended sequential "; + if (bitsPerSample > 8) derivationDescription += "12 bit"; else derivationDescription += "8 bit"; + derivationDescription += ", IJG quality factor "; + sprintf(buf, "%u", rp->getQuality()); + derivationDescription += buf; + derivationDescription += ", compression ratio "; + appendCompressionRatio(derivationDescription, ratio); +} + + +DJEncoder *DJEncoderExtended::createEncoderInstance( + const DcmRepresentationParameter * toRepParam, + const DJCodecParameter *cp, + Uint8 bitsPerSample) const +{ + DJ_RPLossy defaultRP; + const DJ_RPLossy *rp = toRepParam ? OFreinterpret_cast(const DJ_RPLossy*, toRepParam) : &defaultRP ; + DJEncoder *result = NULL; + if (bitsPerSample > 8) + result = new DJCompressIJG12Bit(*cp, EJM_sequential, OFstatic_cast(Uint8, rp->getQuality())); + else + result = new DJCompressIJG8Bit(*cp, EJM_sequential, OFstatic_cast(Uint8, rp->getQuality())); + return result; +} diff --git a/dcmjpeg/libsrc/djenclol.cc b/dcmjpeg/libsrc/djenclol.cc new file mode 100644 index 00000000..c90ba955 --- /dev/null +++ b/dcmjpeg/libsrc/djenclol.cc @@ -0,0 +1,94 @@ +/* + * + * Copyright (C) 2001-2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmjpeg + * + * Author: Marco Eichelberg, Norbert Olges + * + * Purpose: Codec class for encoding JPEG Lossless (8/12/16-bit) + * + */ + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmjpeg/djenclol.h" +#include "dcmtk/dcmjpeg/djcparam.h" +#include "dcmtk/dcmjpeg/djrplol.h" +#include "dcmtk/dcmjpeg/djeijg8.h" +#include "dcmtk/dcmjpeg/djeijg12.h" +#include "dcmtk/dcmjpeg/djeijg16.h" + + +DJEncoderLossless::DJEncoderLossless() +: DJCodecEncoder() +{ +} + + +DJEncoderLossless::~DJEncoderLossless() +{ +} + + +E_TransferSyntax DJEncoderLossless::supportedTransferSyntax() const +{ + return EXS_JPEGProcess14; +} + + +OFBool DJEncoderLossless::isLosslessProcess() const +{ + return OFTrue; +} + + +void DJEncoderLossless::createDerivationDescription( + const DcmRepresentationParameter * toRepParam, + const DJCodecParameter *cp, + Uint8 /* bitsPerSample */ , + double ratio, + OFString& derivationDescription) const +{ + DJ_RPLossless defaultRP; + const DJ_RPLossless *rp = toRepParam ? OFreinterpret_cast(const DJ_RPLossless*, toRepParam) : &defaultRP ; + char buf[64]; + + if (cp->getTrueLosslessMode()) + derivationDescription = "Lossless JPEG compression, selection value "; + else + derivationDescription = "Pseudo-Lossless JPEG compression, selection value "; + sprintf(buf, "%u", rp->getPrediction()); + derivationDescription += buf; + derivationDescription += ", point transform "; + sprintf(buf, "%u", rp->getPointTransformation()); + derivationDescription += buf; + derivationDescription += ", compression ratio "; + appendCompressionRatio(derivationDescription, ratio); +} + + +DJEncoder *DJEncoderLossless::createEncoderInstance( + const DcmRepresentationParameter * toRepParam, + const DJCodecParameter *cp, + Uint8 bitsPerSample) const +{ + DJ_RPLossless defaultRP; + const DJ_RPLossless *rp = toRepParam ? OFreinterpret_cast(const DJ_RPLossless*, toRepParam) : &defaultRP ; + DJEncoder *result = NULL; + if (bitsPerSample > 12) + result = new DJCompressIJG16Bit(*cp, EJM_lossless, rp->getPrediction(), rp->getPointTransformation()); + else if (bitsPerSample > 8) + result = new DJCompressIJG12Bit(*cp, EJM_lossless, rp->getPrediction(), rp->getPointTransformation()); + else + result = new DJCompressIJG8Bit(*cp, EJM_lossless, rp->getPrediction(), rp->getPointTransformation()); + return result; +} diff --git a/dcmjpeg/libsrc/djencode.cc b/dcmjpeg/libsrc/djencode.cc new file mode 100644 index 00000000..ff55eb46 --- /dev/null +++ b/dcmjpeg/libsrc/djencode.cc @@ -0,0 +1,159 @@ +/* + * + * Copyright (C) 1997-2010, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmjpeg + * + * Author: Marco Eichelberg + * + * Purpose: singleton class that registers encoders for all supported JPEG processes. + * + */ + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmjpeg/djencode.h" + +#include "dcmtk/dcmdata/dccodec.h" /* for DcmCodecStruct */ +#include "dcmtk/dcmjpeg/djencbas.h" +#include "dcmtk/dcmjpeg/djencext.h" +#include "dcmtk/dcmjpeg/djencsps.h" +#include "dcmtk/dcmjpeg/djencpro.h" +#include "dcmtk/dcmjpeg/djencsv1.h" +#include "dcmtk/dcmjpeg/djenclol.h" +#include "dcmtk/dcmjpeg/djcparam.h" + +// initialization of static members +OFBool DJEncoderRegistration::registered = OFFalse; +DJCodecParameter *DJEncoderRegistration::cp = NULL; +DJEncoderBaseline *DJEncoderRegistration::encbas = NULL; +DJEncoderExtended *DJEncoderRegistration::encext = NULL; +DJEncoderSpectralSelection *DJEncoderRegistration::encsps = NULL; +DJEncoderProgressive *DJEncoderRegistration::encpro = NULL; +DJEncoderP14SV1 *DJEncoderRegistration::encsv1 = NULL; +DJEncoderLossless *DJEncoderRegistration::enclol = NULL; + +void DJEncoderRegistration::registerCodecs( + E_CompressionColorSpaceConversion pCompressionCSConversion, + E_UIDCreation pCreateSOPInstanceUID, + OFBool pOptimizeHuffman, + int pSmoothingFactor, + int pForcedBitDepth, + Uint32 pFragmentSize, + OFBool pCreateOffsetTable, + E_SubSampling pSampleFactors, + OFBool pWriteYBR422, + OFBool pConvertToSC, + unsigned long pWindowType, + unsigned long pWindowParameter, + double pVoiCenter, + double pVoiWidth, + unsigned long pRoiLeft, + unsigned long pRoiTop, + unsigned long pRoiWidth, + unsigned long pRoiHeight, + OFBool pUsePixelValues, + OFBool pUseModalityRescale, + OFBool pAcceptWrongPaletteTags, + OFBool pAcrNemaCompatibility, + OFBool pRealLossless) +{ + if (! registered) + { + cp = new DJCodecParameter( + pCompressionCSConversion, + EDC_photometricInterpretation, // not relevant, used for decompression only + pCreateSOPInstanceUID, + EPC_default, // not relevant, used for decompression only + OFFalse, // not relevant, used for decompression only + pOptimizeHuffman, + pSmoothingFactor, + pForcedBitDepth, + pFragmentSize, + pCreateOffsetTable, + pSampleFactors, + pWriteYBR422, + pConvertToSC, + pWindowType, + pWindowParameter, + pVoiCenter, + pVoiWidth, + pRoiLeft, + pRoiTop, + pRoiWidth, + pRoiHeight, + pUsePixelValues, + pUseModalityRescale, + pAcceptWrongPaletteTags, + pAcrNemaCompatibility, + pRealLossless); + if (cp) + { + // baseline JPEG + encbas = new DJEncoderBaseline(); + if (encbas) DcmCodecList::registerCodec(encbas, NULL, cp); + + // extended JPEG + encext = new DJEncoderExtended(); + if (encext) DcmCodecList::registerCodec(encext, NULL, cp); + + // spectral selection JPEG + encsps = new DJEncoderSpectralSelection(); + if (encsps) DcmCodecList::registerCodec(encsps, NULL, cp); + + // progressive JPEG + encpro = new DJEncoderProgressive(); + if (encpro) DcmCodecList::registerCodec(encpro, NULL, cp); + + // lossless SV1 JPEG + encsv1 = new DJEncoderP14SV1(); + if (encsv1) DcmCodecList::registerCodec(encsv1, NULL, cp); + + // lossless JPEG + enclol = new DJEncoderLossless(); + if (enclol) DcmCodecList::registerCodec(enclol, NULL, cp); + + registered = OFTrue; + } + } +} + +void DJEncoderRegistration::cleanup() +{ + if (registered) + { + DcmCodecList::deregisterCodec(encbas); + delete encbas; + DcmCodecList::deregisterCodec(encext); + delete encext; + DcmCodecList::deregisterCodec(encsps); + delete encsps; + DcmCodecList::deregisterCodec(encpro); + delete encpro; + DcmCodecList::deregisterCodec(encsv1); + delete encsv1; + DcmCodecList::deregisterCodec(enclol); + delete enclol; + delete cp; + registered = OFFalse; +#ifdef DEBUG + // not needed but useful for debugging purposes + encbas = NULL; + encext = NULL; + encsps = NULL; + encpro = NULL; + encsv1 = NULL; + enclol = NULL; + cp = NULL; +#endif + + } +} diff --git a/dcmjpeg/libsrc/djencpro.cc b/dcmjpeg/libsrc/djencpro.cc new file mode 100644 index 00000000..0d3a1109 --- /dev/null +++ b/dcmjpeg/libsrc/djencpro.cc @@ -0,0 +1,86 @@ +/* + * + * Copyright (C) 2001-2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmjpeg + * + * Author: Marco Eichelberg, Norbert Olges + * + * Purpose: Codec class for encoding JPEG Progressive (lossy, 8/12-bit) + * + */ + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmjpeg/djencpro.h" +#include "dcmtk/dcmjpeg/djcparam.h" +#include "dcmtk/dcmjpeg/djrploss.h" +#include "dcmtk/dcmjpeg/djeijg8.h" +#include "dcmtk/dcmjpeg/djeijg12.h" + + +DJEncoderProgressive::DJEncoderProgressive() +: DJCodecEncoder() +{ +} + + +DJEncoderProgressive::~DJEncoderProgressive() +{ +} + + +E_TransferSyntax DJEncoderProgressive::supportedTransferSyntax() const +{ + return EXS_JPEGProcess10_12; +} + + +OFBool DJEncoderProgressive::isLosslessProcess() const +{ + return OFFalse; +} + + +void DJEncoderProgressive::createDerivationDescription( + const DcmRepresentationParameter * toRepParam, + const DJCodecParameter * /* cp */ , + Uint8 bitsPerSample, + double ratio, + OFString& derivationDescription) const +{ + DJ_RPLossy defaultRP; + const DJ_RPLossy *rp = toRepParam ? OFreinterpret_cast(const DJ_RPLossy*, toRepParam) : &defaultRP ; + char buf[64]; + + derivationDescription = "Lossy compression with JPEG full progression "; + if (bitsPerSample > 8) derivationDescription += "12 bit"; else derivationDescription += "8 bit"; + derivationDescription += ", IJG quality factor "; + sprintf(buf, "%u", rp->getQuality()); + derivationDescription += buf; + derivationDescription += ", compression ratio "; + appendCompressionRatio(derivationDescription, ratio); +} + + +DJEncoder *DJEncoderProgressive::createEncoderInstance( + const DcmRepresentationParameter * toRepParam, + const DJCodecParameter *cp, + Uint8 bitsPerSample) const +{ + DJ_RPLossy defaultRP; + const DJ_RPLossy *rp = toRepParam ? OFreinterpret_cast(const DJ_RPLossy*, toRepParam) : &defaultRP ; + DJEncoder *result = NULL; + if (bitsPerSample > 8) + result = new DJCompressIJG12Bit(*cp, EJM_progressive, OFstatic_cast(Uint8, rp->getQuality())); + else result = new DJCompressIJG8Bit(*cp, EJM_progressive, OFstatic_cast(Uint8, rp->getQuality())); + return result; +} diff --git a/dcmjpeg/libsrc/djencsps.cc b/dcmjpeg/libsrc/djencsps.cc new file mode 100644 index 00000000..44d34b40 --- /dev/null +++ b/dcmjpeg/libsrc/djencsps.cc @@ -0,0 +1,87 @@ +/* + * + * Copyright (C) 2001-2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmjpeg + * + * Author: Marco Eichelberg + * + * Purpose: Codec class for encoding JPEG Spectral Selection (lossy, 8/12-bit) + * + */ + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmjpeg/djencsps.h" +#include "dcmtk/dcmjpeg/djcparam.h" +#include "dcmtk/dcmjpeg/djrploss.h" +#include "dcmtk/dcmjpeg/djeijg8.h" +#include "dcmtk/dcmjpeg/djeijg12.h" + + +DJEncoderSpectralSelection::DJEncoderSpectralSelection() +: DJCodecEncoder() +{ +} + + +DJEncoderSpectralSelection::~DJEncoderSpectralSelection() +{ +} + + +E_TransferSyntax DJEncoderSpectralSelection::supportedTransferSyntax() const +{ + return EXS_JPEGProcess6_8; +} + + +OFBool DJEncoderSpectralSelection::isLosslessProcess() const +{ + return OFFalse; +} + + +void DJEncoderSpectralSelection::createDerivationDescription( + const DcmRepresentationParameter * toRepParam, + const DJCodecParameter * /* cp */ , + Uint8 bitsPerSample, + double ratio, + OFString& derivationDescription) const +{ + DJ_RPLossy defaultRP; + const DJ_RPLossy *rp = toRepParam ? OFreinterpret_cast(const DJ_RPLossy*, toRepParam) : &defaultRP ; + char buf[64]; + + derivationDescription = "Lossy compression with JPEG spectral selection "; + if (bitsPerSample > 8) derivationDescription += "12 bit"; else derivationDescription += "8 bit"; + derivationDescription += ", IJG quality factor "; + sprintf(buf, "%u", rp->getQuality()); + derivationDescription += buf; + derivationDescription += ", compression ratio "; + appendCompressionRatio(derivationDescription, ratio); +} + + +DJEncoder *DJEncoderSpectralSelection::createEncoderInstance( + const DcmRepresentationParameter * toRepParam, + const DJCodecParameter *cp, + Uint8 bitsPerSample) const +{ + DJ_RPLossy defaultRP; + const DJ_RPLossy *rp = toRepParam ? OFreinterpret_cast(const DJ_RPLossy*, toRepParam) : &defaultRP ; + DJEncoder *result = NULL; + + if (bitsPerSample > 8) + result = new DJCompressIJG12Bit(*cp, EJM_spectralSelection, OFstatic_cast(Uint8, rp->getQuality())); + else result = new DJCompressIJG8Bit(*cp, EJM_spectralSelection, OFstatic_cast(Uint8, rp->getQuality())); + return result; +} diff --git a/dcmjpeg/libsrc/djencsv1.cc b/dcmjpeg/libsrc/djencsv1.cc new file mode 100644 index 00000000..548ded48 --- /dev/null +++ b/dcmjpeg/libsrc/djencsv1.cc @@ -0,0 +1,92 @@ +/* + * + * Copyright (C) 2001-2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmjpeg + * + * Author: Marco Eichelberg, Norbert Olges + * + * Purpose: Codec class for encoding JPEG Lossless Selection Value 1 (8/12/16-bit) + * + */ + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmjpeg/djencsv1.h" +#include "dcmtk/dcmjpeg/djcparam.h" +#include "dcmtk/dcmjpeg/djrplol.h" +#include "dcmtk/dcmjpeg/djeijg8.h" +#include "dcmtk/dcmjpeg/djeijg12.h" +#include "dcmtk/dcmjpeg/djeijg16.h" + + +DJEncoderP14SV1::DJEncoderP14SV1() +: DJCodecEncoder() +{ +} + + +DJEncoderP14SV1::~DJEncoderP14SV1() +{ +} + + +E_TransferSyntax DJEncoderP14SV1::supportedTransferSyntax() const +{ + return EXS_JPEGProcess14SV1; +} + + +OFBool DJEncoderP14SV1::isLosslessProcess() const +{ + return OFTrue; +} + + +void DJEncoderP14SV1::createDerivationDescription( + const DcmRepresentationParameter * toRepParam, + const DJCodecParameter *cp, + Uint8 /* bitsPerSample */, + double ratio, + OFString& derivationDescription) const +{ + DJ_RPLossless defaultRP; + const DJ_RPLossless *rp = toRepParam ? OFreinterpret_cast(const DJ_RPLossless*, toRepParam) : &defaultRP ; + char buf[64]; + + if (cp->getTrueLosslessMode()) + derivationDescription = "Lossless JPEG compression, selection value 1, point transform "; + else + derivationDescription = "Pseudo-Lossless JPEG compression, selection value 1, point transform "; + sprintf(buf, "%u", rp->getPointTransformation()); + derivationDescription += buf; + derivationDescription += ", compression ratio "; + appendCompressionRatio(derivationDescription, ratio); +} + + +DJEncoder *DJEncoderP14SV1::createEncoderInstance( + const DcmRepresentationParameter * toRepParam, + const DJCodecParameter *cp, + Uint8 bitsPerSample) const +{ + DJ_RPLossless defaultRP; + const DJ_RPLossless *rp = toRepParam ? OFreinterpret_cast(const DJ_RPLossless*, toRepParam) : &defaultRP ; + DJEncoder *result = NULL; + // prediction/selection value is always 1 for this transfer syntax + if (bitsPerSample > 12) + result = new DJCompressIJG16Bit(*cp, EJM_lossless, 1, rp->getPointTransformation()); + else if (bitsPerSample > 8) + result = new DJCompressIJG12Bit(*cp, EJM_lossless, 1, rp->getPointTransformation()); + else + result = new DJCompressIJG8Bit(*cp, EJM_lossless, 1, rp->getPointTransformation()); + return result; +} diff --git a/dcmjpeg/libsrc/djrplol.cc b/dcmjpeg/libsrc/djrplol.cc new file mode 100644 index 00000000..3891f14e --- /dev/null +++ b/dcmjpeg/libsrc/djrplol.cc @@ -0,0 +1,67 @@ +/* + * + * Copyright (C) 1997-2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmjpeg + * + * Author: Norbert Olges, Marco Eichelberg + * + * Purpose: representation parameter for lossless JPEG + * + */ + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmjpeg/djrplol.h" + + +DJ_RPLossless::DJ_RPLossless(int aPrediction, int aPt) +: DcmRepresentationParameter() +, prediction(aPrediction) +, pt(aPt) +{ +} + +DJ_RPLossless::DJ_RPLossless(const DJ_RPLossless& arg) +: DcmRepresentationParameter(arg) +, prediction(arg.prediction) +, pt(arg.pt) +{ +} + +DJ_RPLossless::~DJ_RPLossless() +{ +} + +DcmRepresentationParameter *DJ_RPLossless::clone() const +{ + return new DJ_RPLossless(*this); +} + +const char *DJ_RPLossless::className() const +{ + return "DJ_RPLossless"; +} + +OFBool DJ_RPLossless::operator==(const DcmRepresentationParameter &arg) const +{ + const char *argname = arg.className(); + if (argname) + { + OFString argstring(argname); + if (argstring == className()) + { + const DJ_RPLossless& argll = OFstatic_cast(const DJ_RPLossless&, arg); + if ((prediction == argll.prediction) && (pt == argll.pt)) return OFTrue; + } + } + return OFFalse; +} diff --git a/dcmjpeg/libsrc/djrploss.cc b/dcmjpeg/libsrc/djrploss.cc new file mode 100644 index 00000000..b591f93c --- /dev/null +++ b/dcmjpeg/libsrc/djrploss.cc @@ -0,0 +1,65 @@ +/* + * + * Copyright (C) 1997-2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmjpeg + * + * Author: Norbert Olges, Marco Eichelberg + * + * Purpose: representation parameter for lossy JPEG + * + */ + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmjpeg/djrploss.h" + + +DJ_RPLossy::DJ_RPLossy(int aQuality) +: DcmRepresentationParameter() +, quality(aQuality) +{ +} + +DJ_RPLossy::DJ_RPLossy(const DJ_RPLossy& arg) +: DcmRepresentationParameter(arg) +, quality(arg.quality) +{ +} + +DJ_RPLossy::~DJ_RPLossy() +{ +} + +DcmRepresentationParameter *DJ_RPLossy::clone() const +{ + return new DJ_RPLossy(*this); +} + +const char *DJ_RPLossy::className() const +{ + return "DJ_RPLossy"; +} + +OFBool DJ_RPLossy::operator==(const DcmRepresentationParameter &arg) const +{ + const char *argname = arg.className(); + if (argname) + { + OFString argstring(argname); + if (argstring == className()) + { + const DJ_RPLossy& argll = OFstatic_cast(const DJ_RPLossy&, arg); + if (quality == argll.quality) return OFTrue; + } + } + return OFFalse; +} diff --git a/dcmjpeg/libsrc/djutils.cc b/dcmjpeg/libsrc/djutils.cc new file mode 100644 index 00000000..893a510f --- /dev/null +++ b/dcmjpeg/libsrc/djutils.cc @@ -0,0 +1,70 @@ +/* + * + * Copyright (C) 1997-2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmjpeg + * + * Author: Norbert Olges, Marco Eichelberg + * + * Purpose: (STATUS: OK) + * + */ + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmjpeg/djutils.h" +#include "dcmtk/dcmdata/dcdeftag.h" /* for tag constants */ +#include "dcmtk/dcmdata/dcitem.h" /* for class DcmItem */ + +#define INCLUDE_CCTYPE +#include "dcmtk/ofstd/ofstdinc.h" + +OFLogger DCM_dcmjpegLogger = OFLog::getLogger("dcmtk.dcmjpeg"); + +makeOFConditionConst(EJ_Suspension, OFM_dcmjpeg, 1, OF_error, "IJG codec suspension return" ); +makeOFConditionConst(EJ_IJG8_FrameBufferTooSmall, OFM_dcmjpeg, 2, OF_error, "Buffer for decompressed image (8 bits/sample) too small" ); +makeOFConditionConst(EJ_IJG12_FrameBufferTooSmall, OFM_dcmjpeg, 3, OF_error, "Buffer for decompressed image (12 bits/sample) too small" ); +makeOFConditionConst(EJ_IJG16_FrameBufferTooSmall, OFM_dcmjpeg, 4, OF_error, "Buffer for decompressed image (16 bits/sample) too small" ); +makeOFConditionConst(EJ_UnsupportedPhotometricInterpretation, OFM_dcmjpeg, 5, OF_error, "Codec does not support this PhotometricInterpretation" ); +makeOFConditionConst(EJ_UnsupportedColorConversion, OFM_dcmjpeg, 6, OF_error, "Codec does not support this kind of color conversion" ); + +EP_Interpretation DcmJpegHelper::getPhotometricInterpretation(DcmItem *item) +{ + if (item) + { + OFString photometric; + if (item->findAndGetOFString(DCM_PhotometricInterpretation, photometric).good() && !photometric.empty()) + { + const char *c = photometric.c_str(); // guaranteed to be zero-terminated + char cp[17]; // legal CS cannot be larger than 16 characters plus 0 byte + int i=0; // current character index + unsigned char cur; // current character + while (*c && (i<16)) + { + cur = OFstatic_cast(unsigned char, *c); + if (isalpha(cur)) cp[i++] = OFstatic_cast(char, toupper(cur)); + else if (isdigit(cur)) cp[i++] = cur; + c++; + } + cp[i] = 0; // write terminating zero + photometric = cp; // copy back into OFString + + // now browse PhotometricInterpretationNames + i = 0; + while (PhotometricInterpretationNames[i].Name) + { + if (photometric == PhotometricInterpretationNames[i].Name) return PhotometricInterpretationNames[i].Type; + i++; + } + } + } + return EPI_Unknown; +} diff --git a/dcmjpeg/tests/Makefile.in b/dcmjpeg/tests/Makefile.in new file mode 100644 index 00000000..0433c72e --- /dev/null +++ b/dcmjpeg/tests/Makefile.in @@ -0,0 +1,29 @@ +# +# Makefile for dcmjpeg/tests +# + +@SET_MAKE@ + +SHELL = /bin/sh +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +configdir = @top_srcdir@/@configdir@ + +include $(configdir)/@common_makefile@ + + +all: + +check: + +check-exhaustive: + +install: + +clean: + rm -f $(TRASH) + +distclean: + rm -f $(DISTTRASH) + +dependencies: diff --git a/dcmjpls/CMakeLists.txt b/dcmjpls/CMakeLists.txt new file mode 100644 index 00000000..e1146637 --- /dev/null +++ b/dcmjpls/CMakeLists.txt @@ -0,0 +1,7 @@ +# declare project +PROJECT(dcmjpls) + +# recurse into subdirectories +FOREACH(SUBDIR libsrc libcharls apps include) + ADD_SUBDIRECTORY(${SUBDIR}) +ENDFOREACH(SUBDIR) diff --git a/dcmjpls/Makefile.in b/dcmjpls/Makefile.in new file mode 100644 index 00000000..aadfd734 --- /dev/null +++ b/dcmjpls/Makefile.in @@ -0,0 +1,102 @@ +# +# Makefile for dcmjpls +# + +@SET_MAKE@ + +SHELL = /bin/sh +VPATH = @srcdir@:@top_srcdir@/include:@top_srcdir@/@configdir@/include +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +configdir = @top_srcdir@/@configdir@ + +include $(configdir)/@common_makefile@ + + +all: include-all libsrc-all apps-all tests-all + +install: install-bin install-doc install-support + +install-bin: apps-install + +install-doc: docs-install + +install-data: data-install + +install-etc: etc-install + +install-include: include-install + +install-lib: libsrc-install install-include + +install-support: install-data install-etc + + +include-all: + (cd include && $(MAKE) ARCH="$(ARCH)" all) + +libsrc-all: include-all + (cd libcharls && $(MAKE) ARCH="$(ARCH)" all) + (cd libsrc && $(MAKE) ARCH="$(ARCH)" all) + +apps-all: libsrc-all + (cd apps && $(MAKE) ARCH="$(ARCH)" all) + +tests-all: libsrc-all + (cd tests && $(MAKE) ARCH="$(ARCH)" all) + + +check: tests-all + (cd tests && $(MAKE) check) + +check-exhaustive: tests-all + (cd tests && $(MAKE) check-exhaustive) + + +include-install: + (cd include && $(MAKE) ARCH="$(ARCH)" install) + +libsrc-install: libsrc-all + (cd libcharls && $(MAKE) ARCH="$(ARCH)" install) + (cd libsrc && $(MAKE) ARCH="$(ARCH)" install) + +apps-install: apps-all + (cd apps && $(MAKE) ARCH="$(ARCH)" install) + +docs-install: + (cd docs && $(MAKE) install) + +data-install: + (cd data && $(MAKE) install) + +etc-install: + (cd etc && $(MAKE) install) + + +clean: + (cd include && $(MAKE) clean) + (cd libcharls && $(MAKE) clean) + (cd libsrc && $(MAKE) clean) + (cd apps && $(MAKE) clean) + (cd tests && $(MAKE) clean) + (cd docs && $(MAKE) clean) + (cd data && $(MAKE) clean) + (cd etc && $(MAKE) clean) + rm -f $(TRASH) + +distclean: + (cd include && $(MAKE) distclean) + (cd libcharls && $(MAKE) distclean) + (cd libsrc && $(MAKE) distclean) + (cd apps && $(MAKE) distclean) + (cd tests && $(MAKE) distclean) + (cd docs && $(MAKE) distclean) + (cd data && $(MAKE) distclean) + (cd etc && $(MAKE) distclean) + rm -f $(DISTTRASH) + +dependencies: + (cd libcharls && touch $(DEP) && $(MAKE) dependencies) + (cd libsrc && touch $(DEP) && $(MAKE) dependencies) + (cd apps && touch $(DEP) && $(MAKE) dependencies) +# (cd tests && touch $(DEP) && $(MAKE) dependencies) diff --git a/dcmjpls/apps/CMakeLists.txt b/dcmjpls/apps/CMakeLists.txt new file mode 100644 index 00000000..2e881d72 --- /dev/null +++ b/dcmjpls/apps/CMakeLists.txt @@ -0,0 +1,12 @@ +# declare additional include directories +INCLUDE_DIRECTORIES(${dcmjpls_SOURCE_DIR}/include ${ofstd_SOURCE_DIR}/include ${oflog_SOURCE_DIR}/include ${dcmdata_SOURCE_DIR}/include ${dcmimgle_SOURCE_DIR}/include ${dcmimage_SOURCE_DIR}/include ${ZLIB_INCDIR} ${LIBTIFF_INCDIR} ${LIBPNG_INCDIR}) + +# declare executables +FOREACH(PROGRAM dcmcjpls dcmdjpls dcml2pnm) + DCMTK_ADD_EXECUTABLE(${PROGRAM} ${PROGRAM}) +ENDFOREACH(PROGRAM) + +# make sure executables are linked to the corresponding libraries +FOREACH(PROGRAM dcmcjpls dcmdjpls dcml2pnm) + DCMTK_TARGET_LINK_MODULES(${PROGRAM} dcmjpls charls dcmimage dcmimgle dcmdata oflog ofstd ofstd) +ENDFOREACH(PROGRAM) diff --git a/dcmjpls/apps/Makefile.dep b/dcmjpls/apps/Makefile.dep new file mode 100644 index 00000000..8b0228e7 --- /dev/null +++ b/dcmjpls/apps/Makefile.dep @@ -0,0 +1,377 @@ +dcmcjpls.o: dcmcjpls.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcostrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicent.h \ + ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcmetinf.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicdir.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdirrec.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrulup.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrul.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixseq.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcofsetl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrae.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvras.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrda.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrds.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrdt.h \ + ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvris.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrtm.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrur.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcchrstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlt.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpn.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsh.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrst.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvruc.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrut.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixel.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpobw.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcovlay.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrat.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrss.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrus.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfd.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrof.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrod.h \ + ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ + ../../dcmimage/include/dcmtk/dcmimage/diregist.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diregbas.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diutils.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/didefine.h \ + ../../dcmimage/include/dcmtk/dcmimage/dicdefin.h \ + ../include/dcmtk/dcmjpls/djlsutil.h ../include/dcmtk/dcmjpls/dldefine.h \ + ../include/dcmtk/dcmjpls/djencode.h ../include/dcmtk/dcmjpls/djcparam.h \ + ../../dcmdata/include/dcmtk/dcmdata/dccodec.h \ + ../include/dcmtk/dcmjpls/djrparam.h +dcmdjpls.o: dcmdjpls.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcostrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicent.h \ + ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcmetinf.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicdir.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdirrec.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrulup.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrul.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixseq.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcofsetl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrae.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvras.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrda.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrds.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrdt.h \ + ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvris.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrtm.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrur.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcchrstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlt.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpn.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsh.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrst.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvruc.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrut.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixel.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpobw.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcovlay.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrat.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrss.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrus.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfd.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrof.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrod.h \ + ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ + ../../dcmimage/include/dcmtk/dcmimage/diregist.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diregbas.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diutils.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/didefine.h \ + ../../dcmimage/include/dcmtk/dcmimage/dicdefin.h \ + ../include/dcmtk/dcmjpls/djlsutil.h ../include/dcmtk/dcmjpls/dldefine.h \ + ../include/dcmtk/dcmjpls/djdecode.h +dcml2pnm.o: dcml2pnm.cc ../../dcmimage/apps/dcm2pnm.cc \ + ../../config/include/dcmtk/config/osconfig.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcostrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicent.h \ + ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcmetinf.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicdir.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdirrec.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrulup.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrul.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixseq.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcofsetl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrae.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvras.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrda.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrds.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrdt.h \ + ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvris.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrtm.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrur.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcchrstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlt.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpn.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsh.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrst.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvruc.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrut.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixel.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpobw.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcovlay.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrat.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrss.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrus.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfd.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrof.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrod.h \ + ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcrledrg.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/dcmimage.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/dimoimg.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diimage.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfcache.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diovlay.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diobjcou.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/didefine.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diovdat.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diovpln.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diutils.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/dimopx.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/dipixel.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/dimomod.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diluptab.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/dibaslut.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/dimoopx.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/didispfn.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/digsdfn.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diciefn.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/dicielut.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/didislut.h \ + ../../dcmimage/include/dcmtk/dcmimage/diregist.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diregbas.h \ + ../../dcmimage/include/dcmtk/dcmimage/dicdefin.h \ + ../include/dcmtk/dcmjpls/djdecode.h ../include/dcmtk/dcmjpls/djlsutil.h \ + ../include/dcmtk/dcmjpls/dldefine.h \ + ../../dcmimage/include/dcmtk/dcmimage/dipitiff.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diplugin.h \ + ../../dcmimage/include/dcmtk/dcmimage/dipipng.h diff --git a/dcmjpls/apps/Makefile.in b/dcmjpls/apps/Makefile.in new file mode 100644 index 00000000..e348ff28 --- /dev/null +++ b/dcmjpls/apps/Makefile.in @@ -0,0 +1,87 @@ +# +# Makefile for dcmjpls/apps +# + +@SET_MAKE@ + +SHELL = /bin/sh +VPATH = @srcdir@:@top_srcdir@/include:@top_srcdir@/@configdir@/include +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +configdir = @top_srcdir@/@configdir@ + +include $(configdir)/@common_makefile@ + +ofstddir =$(top_srcdir)/../ofstd +ofstdinc = -I$(ofstddir)/include +ofstdlibdir = -L$(ofstddir)/libsrc +ofstdlib = -lofstd + +oflogdir = $(top_srcdir)/../oflog +ofloginc = -I$(oflogdir)/include +ofloglibdir = -L$(oflogdir)/libsrc +ofloglib = -loflog + +dcmdatadir = $(top_srcdir)/../dcmdata +dcmdatainc = -I$(dcmdatadir)/include +dcmdatalibdir = -L$(dcmdatadir)/libsrc +dcmdatalib = -ldcmdata + +dcmimgledir = $(top_srcdir)/../dcmimgle +dcmimgleinc = -I$(dcmimgledir)/include +dcmimglelibdir = -L$(dcmimgledir)/libsrc +dcmimglelib = -ldcmimgle + +dcmimagedir = $(top_srcdir)/../dcmimage +dcmimageinc = -I$(dcmimagedir)/include +dcmimagelibdir = -L$(dcmimagedir)/libsrc +dcmimagelib = -ldcmimage + +dcmjplsdir = $(top_srcdir)/../dcmjpls +dcmjplsinc = -I$(dcmjplsdir)/include +dcmjplslibdir = -L$(dcmjplsdir)/libsrc +dcmjplslib = -ldcmjpls + +libcharlsdir = $(dcmjplsdir) +libcharlslibdir = -L$(dcmjplsdir)/libcharls +libcharlslib = -lcharls + +LOCALINCLUDES = $(dcmjplsinc) $(ofstdinc) $(ofloginc) $(dcmdatainc) $(dcmimageinc) $(dcmimgleinc) +LIBDIRS = -L$(top_srcdir)/libsrc $(dcmjplslibdir) $(libcharlslibdir) $(dcmimagelibdir) \ + $(dcmimglelibdir) $(dcmdatalibdir) $(ofloglibdir) $(ofstdlibdir) +LOCALLIBS = $(dcmjplslib) $(dcmimagelib) $(dcmimglelib) $(dcmdatalib) $(ofloglib) $(ofstdlib) \ + $(libcharlslib) $(TIFFLIBS) $(PNGLIBS) $(ZLIBLIBS) $(ICONVLIBS) + +objs = dcmdjpls.o dcmcjpls.o dcml2pnm.o +progs = dcmdjpls dcmcjpls dcml2pnm + +all: $(progs) + +dcmdjpls: dcmdjpls.o + $(CXX) $(CXXFLAGS) $(LIBDIRS) $(LDFLAGS) -o $@ $@.o $(LOCALLIBS) $(MATHLIBS) $(LIBS) + +dcmcjpls: dcmcjpls.o + $(CXX) $(CXXFLAGS) $(LIBDIRS) $(LDFLAGS) -o $@ $@.o $(LOCALLIBS) $(MATHLIBS) $(LIBS) + +dcml2pnm: dcml2pnm.o + $(CXX) $(CXXFLAGS) $(LIBDIRS) $(LDFLAGS) -o $@ $@.o $(LOCALLIBS) $(MATHLIBS) $(LIBS) + + +install: all + $(configdir)/mkinstalldirs $(DESTDIR)$(bindir) + for prog in $(progs); do \ + $(INSTALL_PROGRAM) $$prog$(BINEXT) $(DESTDIR)$(bindir) && $(STRIP) $(DESTDIR)$(bindir)/$$prog$(BINEXT) ;\ + done + + +clean: + rm -f $(objs) $(progs) $(TRASH) + +distclean: + rm -f $(objs) $(progs) $(DISTTRASH) + + +dependencies: + $(CXX) -MM $(defines) $(includes) $(CPPFLAGS) $(CXXFLAGS) *.cc > $(DEP) + +include $(DEP) diff --git a/dcmjpls/apps/dcmcjpls.cc b/dcmjpls/apps/dcmcjpls.cc new file mode 100644 index 00000000..9d48be34 --- /dev/null +++ b/dcmjpls/apps/dcmcjpls.cc @@ -0,0 +1,509 @@ +/* + * + * Copyright (C) 2007-2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmcjpls + * + * Author: Martin Willkomm, Uli Schlachter + * + * Purpose: Compress DICOM file with JPEG-LS transfer syntax + * + */ + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#define INCLUDE_CSTDLIB +#define INCLUDE_CSTDIO +#define INCLUDE_CSTRING +#include "dcmtk/ofstd/ofstdinc.h" + +#ifdef HAVE_GUSI_H +#include +#endif + +#include "dcmtk/dcmdata/dctk.h" +#include "dcmtk/dcmdata/cmdlnarg.h" +#include "dcmtk/ofstd/ofconapp.h" +#include "dcmtk/dcmdata/dcuid.h" /* for dcmtk version name */ +#include "dcmtk/dcmimage/diregist.h" /* include to support color images */ +#include "dcmtk/dcmjpls/djlsutil.h" /* for dcmjpls typedefs */ +#include "dcmtk/dcmjpls/djencode.h" /* for class DJLSEncoderRegistration */ +#include "dcmtk/dcmjpls/djrparam.h" /* for class DJLSRepresentationParameter */ + +#ifdef WITH_ZLIB +#include /* for zlibVersion() */ +#endif + +#ifdef USE_LICENSE_FILE +#include "oflice.h" +#endif + +#ifndef OFFIS_CONSOLE_APPLICATION +#define OFFIS_CONSOLE_APPLICATION "dcmcjpls" +#endif + +static OFLogger dcmcjplsLogger = OFLog::getLogger("dcmtk.apps." OFFIS_CONSOLE_APPLICATION); + +static char rcsid[] = "$dcmtk: " OFFIS_CONSOLE_APPLICATION " v" + OFFIS_DCMTK_VERSION " " OFFIS_DCMTK_RELEASEDATE " $"; + +// ******************************************** + + +#define SHORTCOL 3 +#define LONGCOL 21 + +int main(int argc, char *argv[]) +{ + +#ifdef HAVE_GUSI_H + GUSISetup(GUSIwithSIOUXSockets); + GUSISetup(GUSIwithInternetSockets); +#endif + + const char *opt_ifname = NULL; + const char *opt_ofname = NULL; + + // input options + E_FileReadMode opt_readMode = ERM_autoDetect; + E_TransferSyntax opt_ixfer = EXS_Unknown; + + // JPEG-LS encoding options + E_TransferSyntax opt_oxfer = EXS_JPEGLSLossless; + OFBool opt_useLosslessProcess = OFTrue; + + OFCmdUnsignedInt opt_t1 = 3; + OFCmdUnsignedInt opt_t2 = 7; + OFCmdUnsignedInt opt_t3 = 21; + + OFCmdUnsignedInt opt_reset = 64; + OFCmdUnsignedInt opt_limit = 0; + + OFBool opt_use_custom_options = OFFalse; + + // JPEG-LS options + OFCmdUnsignedInt opt_nearlossless_deviation = 2; + OFBool opt_prefer_cooked = OFFalse; + DJLSCodecParameter::interleaveMode opt_interleaveMode = DJLSCodecParameter::interleaveLine; + + // encapsulated pixel data encoding options + OFCmdUnsignedInt opt_fragmentSize = 0; // 0=unlimited + OFBool opt_createOffsetTable = OFTrue; + JLS_UIDCreation opt_uidcreation = EJLSUC_default; + OFBool opt_secondarycapture = OFFalse; + + // output options + E_GrpLenEncoding opt_oglenc = EGL_recalcGL; + E_EncodingType opt_oenctype = EET_ExplicitLength; + E_PaddingEncoding opt_opadenc = EPD_noChange; + OFCmdUnsignedInt opt_filepad = 0; + OFCmdUnsignedInt opt_itempad = 0; + +#ifdef USE_LICENSE_FILE +LICENSE_FILE_DECLARATIONS +#endif + + OFConsoleApplication app(OFFIS_CONSOLE_APPLICATION, "Encode DICOM file to JPEG-LS transfer syntax", rcsid); + OFCommandLine cmd; + cmd.setOptionColumns(LONGCOL, SHORTCOL); + cmd.setParamColumn(LONGCOL + SHORTCOL + 4); + + cmd.addParam("dcmfile-in", "DICOM input filename to be converted"); + cmd.addParam("dcmfile-out", "DICOM output filename"); + + cmd.addGroup("general options:", LONGCOL, SHORTCOL + 2); + cmd.addOption("--help", "-h", "print this help text and exit", OFCommandLine::AF_Exclusive); + cmd.addOption("--version", "print version information and exit", OFCommandLine::AF_Exclusive); + OFLog::addOptions(cmd); + +#ifdef USE_LICENSE_FILE +LICENSE_FILE_DECLARE_COMMAND_LINE_OPTIONS +#endif + + cmd.addGroup("input options:"); + cmd.addSubGroup("input file format:"); + cmd.addOption("--read-file", "+f", "read file format or data set (default)"); + cmd.addOption("--read-file-only", "+fo", "read file format only"); + cmd.addOption("--read-dataset", "-f", "read data set without file meta information"); + cmd.addSubGroup("input transfer syntax:"); + cmd.addOption("--read-xfer-auto", "-t=", "use TS recognition (default)"); + cmd.addOption("--read-xfer-detect", "-td", "ignore TS specified in the file meta header"); + cmd.addOption("--read-xfer-little", "-te", "read with explicit VR little endian TS"); + cmd.addOption("--read-xfer-big", "-tb", "read with explicit VR big endian TS"); + cmd.addOption("--read-xfer-implicit", "-ti", "read with implicit VR little endian TS"); + + cmd.addGroup("JPEG-LS encoding options:"); + cmd.addSubGroup("JPEG-LS process:"); + cmd.addOption("--encode-lossless", "+el", "encode JPEG-LS lossless (default)"); + cmd.addOption("--encode-nearlossless", "+en", "encode JPEG-LS TS near-lossless (NEAR: 2)"); + cmd.addSubGroup("JPEG-LS bit rate (near-lossless only):"); + cmd.addOption("--max-deviation", "+md", 1, "[d]eviation: integer (default: 2)", + "defines maximum deviation for an encoded pixel"); + cmd.addSubGroup("lossless compression:"); + cmd.addOption("--prefer-raw", "+pr", "prefer raw encoder mode (default)"); + cmd.addOption("--prefer-cooked", "+pc", "prefer cooked encoder mode "); + + cmd.addSubGroup("JPEG-LS compression:"); + cmd.addOption("--threshold1", "+t1", 1, "[t]hreshhold: integer (default for 8 bpp: 3)", + "set JPEG-LS encoding parameter threshold 1"); + cmd.addOption("--threshold2", "+t2", 1, "[t]hreshhold: integer (default for 8 bpp: 7)", + "set JPEG-LS encoding parameter threshold 2"); + cmd.addOption("--threshold3", "+t3", 1, "[t]hreshhold: integer (default for 8 bpp: 21)", + "set JPEG-LS encoding parameter threshold 3"); + cmd.addOption("--reset", "+rs", 1, "[r]eset: integer (default: 64)", + "set JPEG-LS encoding parameter reset"); + cmd.addOption("--limit", "+lm", 1, "[l]imit: integer (default: 0)", + "set JPEG-LS encoding parameter limit"); + cmd.addSubGroup("JPEG-LS interleave:"); + cmd.addOption("--interleave-line", "+il", "force line-interleaved JPEG-LS images (default)"); + cmd.addOption("--interleave-sample", "+is", "force sample-interleaved JPEG-LS images"); + cmd.addOption("--interleave-none", "+in", "force uninterleaved JPEG-LS images"); + cmd.addOption("--interleave-default", "+iv", "use the fastest possible interleave mode"); + + cmd.addGroup("encapsulated pixel data encoding options:"); + cmd.addSubGroup("pixel data fragmentation:"); + cmd.addOption("--fragment-per-frame", "+ff", "encode each frame as one fragment (default)"); + cmd.addOption("--fragment-size", "+fs", 1, "[s]ize: integer", + "limit fragment size to s kbytes"); + cmd.addSubGroup("basic offset table encoding:"); + cmd.addOption("--offset-table-create", "+ot", "create offset table (default)"); + cmd.addOption("--offset-table-empty", "-ot", "leave offset table empty"); + cmd.addSubGroup("SOP Class UID:"); + cmd.addOption("--class-default", "+cd", "keep SOP Class UID (default)"); + cmd.addOption("--class-sc", "+cs", "convert to Secondary Capture Image\n(implies --uid-always)"); + cmd.addSubGroup("SOP Instance UID:"); + cmd.addOption("--uid-default", "+ud", "assign new UID if lossy compression (default)"); + cmd.addOption("--uid-always", "+ua", "always assign new UID"); + cmd.addOption("--uid-never", "+un", "never assign new UID"); + + cmd.addGroup("output options:"); + cmd.addSubGroup("post-1993 value representations:"); + cmd.addOption("--enable-new-vr", "+u", "enable support for new VRs (UN/UT) (default)"); + cmd.addOption("--disable-new-vr", "-u", "disable support for new VRs, convert to OB"); + cmd.addSubGroup("group length encoding:"); + cmd.addOption("--group-length-recalc", "+g=", "recalculate group lengths if present (default)"); + cmd.addOption("--group-length-create", "+g", "always write with group length elements"); + cmd.addOption("--group-length-remove", "-g", "always write without group length elements"); + cmd.addSubGroup("length encoding in sequences and items:"); + cmd.addOption("--length-explicit", "+e", "write with explicit lengths (default)"); + cmd.addOption("--length-undefined", "-e", "write with undefined lengths"); + cmd.addSubGroup("data set trailing padding:"); + cmd.addOption("--padding-retain", "-p=", "do not change padding (default)"); + cmd.addOption("--padding-off", "-p", "no padding"); + cmd.addOption("--padding-create", "+p", 2, "[f]ile-pad [i]tem-pad: integer", + "align file on multiple of f bytes\nand items on multiple of i byte"); + /* evaluate command line */ + prepareCmdLineArgs(argc, argv, OFFIS_CONSOLE_APPLICATION); + if (app.parseCommandLine(cmd, argc, argv)) + { + /* check exclusive options first */ + if (cmd.hasExclusiveOption()) + { + if (cmd.findOption("--version")) + { + app.printHeader(OFTrue /*print host identifier*/); + COUT << OFendl << "External libraries used:" << OFendl; +#ifdef WITH_ZLIB + COUT << "- ZLIB, Version " << zlibVersion() << OFendl; +#endif + COUT << "- " << DJLSEncoderRegistration::getLibraryVersionString() << OFendl; + return 0; + } + } + + /* command line parameters */ + + cmd.getParam(1, opt_ifname); + cmd.getParam(2, opt_ofname); + + // general options + OFLog::configureFromCommandLine(cmd, app); + +#ifdef USE_LICENSE_FILE +LICENSE_FILE_EVALUATE_COMMAND_LINE_OPTIONS +#endif + + // input options + // input file format + cmd.beginOptionBlock(); + if (cmd.findOption("--read-file")) opt_readMode = ERM_autoDetect; + if (cmd.findOption("--read-file-only")) opt_readMode = ERM_fileOnly; + if (cmd.findOption("--read-dataset")) opt_readMode = ERM_dataset; + cmd.endOptionBlock(); + + // input transfer syntax + cmd.beginOptionBlock(); + if (cmd.findOption("--read-xfer-auto")) + opt_ixfer = EXS_Unknown; + if (cmd.findOption("--read-xfer-detect")) + dcmAutoDetectDatasetXfer.set(OFTrue); + if (cmd.findOption("--read-xfer-little")) + { + app.checkDependence("--read-xfer-little", "--read-dataset", opt_readMode == ERM_dataset); + opt_ixfer = EXS_LittleEndianExplicit; + } + if (cmd.findOption("--read-xfer-big")) + { + app.checkDependence("--read-xfer-big", "--read-dataset", opt_readMode == ERM_dataset); + opt_ixfer = EXS_BigEndianExplicit; + } + if (cmd.findOption("--read-xfer-implicit")) + { + app.checkDependence("--read-xfer-implicit", "--read-dataset", opt_readMode == ERM_dataset); + opt_ixfer = EXS_LittleEndianImplicit; + } + cmd.endOptionBlock(); + + // JPEG-LS encoding options + // JPEG-LS process options + cmd.beginOptionBlock(); + if (cmd.findOption("--encode-lossless")) + { + opt_oxfer = EXS_JPEGLSLossless; + opt_useLosslessProcess = OFTrue; + } + if (cmd.findOption("--encode-nearlossless")) + { + opt_oxfer = EXS_JPEGLSLossy; + opt_useLosslessProcess = OFFalse; + opt_nearlossless_deviation = 2; // factor NEAR set to "2", this corresponds to the max. deviation of a pixel + } + cmd.endOptionBlock(); + + // JPEG-LS bit rate options + if (cmd.findOption("--max-deviation")) + { + app.checkConflict("--max-deviation", "--encode-lossless", opt_oxfer == EXS_JPEGLSLossless); + app.checkValue(cmd.getValueAndCheckMin(opt_nearlossless_deviation, 1)); + } + + // lossless compression options + cmd.beginOptionBlock(); + if (cmd.findOption("--prefer-raw")) + { + opt_prefer_cooked = OFFalse; + } + if (cmd.findOption("--prefer-cooked")) + { + opt_prefer_cooked = OFTrue; + } + cmd.endOptionBlock(); + + // thresholds and reset + cmd.beginOptionBlock(); + if (cmd.findOption("--threshold1")) + { + app.checkValue(cmd.getValueAndCheckMin(opt_t1, OFstatic_cast(OFCmdUnsignedInt, 1))); + opt_use_custom_options = OFTrue; + } + if (cmd.findOption("--threshold2")) + { + app.checkValue(cmd.getValueAndCheckMin(opt_t2, OFstatic_cast(OFCmdUnsignedInt, 1))); + opt_use_custom_options = OFTrue; + } + if (cmd.findOption("--threshold3")) + { + app.checkValue(cmd.getValueAndCheckMin(opt_t3, OFstatic_cast(OFCmdUnsignedInt, 1))); + opt_use_custom_options = OFTrue; + } + if (cmd.findOption("--reset")) + { + app.checkValue(cmd.getValueAndCheckMin(opt_reset, OFstatic_cast(OFCmdUnsignedInt, 1))); + opt_use_custom_options = OFTrue; + } + if (cmd.findOption("--limit")) + { + app.checkValue(cmd.getValue(opt_limit)); + opt_use_custom_options = OFTrue; + } + cmd.endOptionBlock(); + + // interleave mode + cmd.beginOptionBlock(); + if (cmd.findOption("--interleave-default")) + { + opt_interleaveMode = DJLSCodecParameter::interleaveDefault; + } + if (cmd.findOption("--interleave-sample")) + { + opt_interleaveMode = DJLSCodecParameter::interleaveSample; + } + if (cmd.findOption("--interleave-line")) + { + opt_interleaveMode = DJLSCodecParameter::interleaveLine; + } + if (cmd.findOption("--interleave-none")) + { + opt_interleaveMode = DJLSCodecParameter::interleaveNone; + } + cmd.endOptionBlock(); + + // encapsulated pixel data encoding options + // pixel data fragmentation options + cmd.beginOptionBlock(); + if (cmd.findOption("--fragment-per-frame")) opt_fragmentSize = 0; + if (cmd.findOption("--fragment-size")) + { + app.checkValue(cmd.getValueAndCheckMin(opt_fragmentSize, OFstatic_cast(OFCmdUnsignedInt, 1))); + } + cmd.endOptionBlock(); + + // basic offset table encoding options + cmd.beginOptionBlock(); + if (cmd.findOption("--offset-table-create")) opt_createOffsetTable = OFTrue; + if (cmd.findOption("--offset-table-empty")) opt_createOffsetTable = OFFalse; + cmd.endOptionBlock(); + + // SOP Class UID options + cmd.beginOptionBlock(); + if (cmd.findOption("--class-default")) opt_secondarycapture = OFFalse; + if (cmd.findOption("--class-sc")) opt_secondarycapture = OFTrue; + cmd.endOptionBlock(); + + // SOP Instance UID options + cmd.beginOptionBlock(); + if (cmd.findOption("--uid-default")) opt_uidcreation = EJLSUC_default; + if (cmd.findOption("--uid-always")) opt_uidcreation = EJLSUC_always; + if (cmd.findOption("--uid-never")) opt_uidcreation = EJLSUC_never; + cmd.endOptionBlock(); + + // output options + // post-1993 value representations + cmd.beginOptionBlock(); + if (cmd.findOption("--enable-new-vr")) dcmEnableGenerationOfNewVRs(); + if (cmd.findOption("--disable-new-vr")) dcmDisableGenerationOfNewVRs(); + cmd.endOptionBlock(); + + // group length encoding + cmd.beginOptionBlock(); + if (cmd.findOption("--group-length-recalc")) opt_oglenc = EGL_recalcGL; + if (cmd.findOption("--group-length-create")) opt_oglenc = EGL_withGL; + if (cmd.findOption("--group-length-remove")) opt_oglenc = EGL_withoutGL; + cmd.endOptionBlock(); + + // length encoding in sequences and items + cmd.beginOptionBlock(); + if (cmd.findOption("--length-explicit")) opt_oenctype = EET_ExplicitLength; + if (cmd.findOption("--length-undefined")) opt_oenctype = EET_UndefinedLength; + cmd.endOptionBlock(); + + // data set trailing padding + cmd.beginOptionBlock(); + if (cmd.findOption("--padding-retain")) opt_opadenc = EPD_noChange; + if (cmd.findOption("--padding-off")) opt_opadenc = EPD_withoutPadding; + if (cmd.findOption("--padding-create")) + { + app.checkValue(cmd.getValueAndCheckMin(opt_filepad, 0)); + app.checkValue(cmd.getValueAndCheckMin(opt_itempad, 0)); + opt_opadenc = EPD_withPadding; + } + cmd.endOptionBlock(); + } + + /* print resource identifier */ + OFLOG_DEBUG(dcmcjplsLogger, rcsid << OFendl); + + // register global compression codecs + DJLSEncoderRegistration::registerCodecs(opt_use_custom_options, + OFstatic_cast(Uint16, opt_t1), OFstatic_cast(Uint16, opt_t2), OFstatic_cast(Uint16, opt_t3), + OFstatic_cast(Uint16, opt_reset), OFstatic_cast(Uint16, opt_limit), + opt_prefer_cooked, opt_fragmentSize, opt_createOffsetTable, + opt_uidcreation, opt_secondarycapture, opt_interleaveMode); + + /* make sure data dictionary is loaded */ + if (!dcmDataDict.isDictionaryLoaded()) + { + OFLOG_WARN(dcmcjplsLogger, "no data dictionary loaded, " + << "check environment variable: " + << DCM_DICT_ENVIRONMENT_VARIABLE); + } + + // open inputfile + if ((opt_ifname == NULL) || (strlen(opt_ifname) == 0)) + { + OFLOG_FATAL(dcmcjplsLogger, "invalid filename: "); + return 1; + } + + OFLOG_INFO(dcmcjplsLogger, "reading input file " << opt_ifname); + + DcmFileFormat fileformat; + OFCondition error = fileformat.loadFile(opt_ifname, opt_ixfer, EGL_noChange, DCM_MaxReadLength, opt_readMode); + if (error.bad()) + { + OFLOG_FATAL(dcmcjplsLogger, error.text() << ": reading file: " << opt_ifname); + return 1; + } + DcmDataset *dataset = fileformat.getDataset(); + + DcmXfer original_xfer(dataset->getOriginalXfer()); + if (original_xfer.isEncapsulated()) + { + OFLOG_INFO(dcmcjplsLogger, "DICOM file is already compressed, converting to uncompressed transfer syntax first"); + if (EC_Normal != dataset->chooseRepresentation(EXS_LittleEndianExplicit, NULL)) + { + OFLOG_FATAL(dcmcjplsLogger, "No conversion from compressed original to uncompressed transfer syntax possible!"); + return 1; + } + } + + OFString sopClass; + if (fileformat.getMetaInfo()->findAndGetOFString(DCM_MediaStorageSOPClassUID, sopClass).good()) + { + /* check for DICOMDIR files */ + if (sopClass == UID_MediaStorageDirectoryStorage) + { + OFLOG_FATAL(dcmcjplsLogger, "DICOMDIR files (Media Storage Directory Storage SOP Class) cannot be compressed!"); + return 1; + } + } + + OFLOG_INFO(dcmcjplsLogger, "Convert DICOM file to compressed transfer syntax"); + + //create representation parameter + DJLSRepresentationParameter rp(OFstatic_cast(Uint16, opt_nearlossless_deviation), opt_useLosslessProcess); + DcmXfer opt_oxferSyn(opt_oxfer); + + // perform decoding process + OFCondition result = dataset->chooseRepresentation(opt_oxfer, &rp); + if (result.bad()) + { + OFLOG_FATAL(dcmcjplsLogger, result.text() << ": encoding file: " << opt_ifname); + return 1; + } + if (dataset->canWriteXfer(opt_oxfer)) + { + OFLOG_INFO(dcmcjplsLogger, "Output transfer syntax " << opt_oxferSyn.getXferName() << " can be written"); + } else { + OFLOG_FATAL(dcmcjplsLogger, "No conversion to transfer syntax " << opt_oxferSyn.getXferName() << " possible!"); + return 1; + } + + OFLOG_INFO(dcmcjplsLogger, "creating output file " << opt_ofname); + + fileformat.loadAllDataIntoMemory(); + error = fileformat.saveFile(opt_ofname, opt_oxfer, opt_oenctype, opt_oglenc, opt_opadenc, + OFstatic_cast(Uint32, opt_filepad), OFstatic_cast(Uint32, opt_itempad), EWM_updateMeta); + + if (error.bad()) + { + OFLOG_FATAL(dcmcjplsLogger, error.text() << ": writing file: " << opt_ofname); + return 1; + } + + OFLOG_INFO(dcmcjplsLogger, "conversion successful"); + + // deregister global codecs + DJLSEncoderRegistration::cleanup(); + + return 0; +} diff --git a/dcmjpls/apps/dcmdjpls.cc b/dcmjpls/apps/dcmdjpls.cc new file mode 100644 index 00000000..e50fdc7e --- /dev/null +++ b/dcmjpls/apps/dcmdjpls.cc @@ -0,0 +1,340 @@ +/* + * + * Copyright (C) 2007-2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmdjpls + * + * Author: Martin Willkomm + * + * Purpose: Decompress DICOM file with JPEG-LS transfer syntax + * + */ + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#define INCLUDE_CSTDLIB +#define INCLUDE_CSTDIO +#define INCLUDE_CSTRING +#include "dcmtk/ofstd/ofstdinc.h" + +#ifdef HAVE_GUSI_H +#include +#endif + +#include "dcmtk/dcmdata/dctk.h" +#include "dcmtk/dcmdata/cmdlnarg.h" +#include "dcmtk/ofstd/ofconapp.h" +#include "dcmtk/dcmdata/dcuid.h" /* for dcmtk version name */ +#include "dcmtk/dcmimage/diregist.h" /* include to support color images */ +#include "dcmtk/dcmjpls/djlsutil.h" /* for dcmjpgls typedefs */ +#include "dcmtk/dcmjpls/djdecode.h" /* for JPEG-LS decoder */ + +#ifdef WITH_ZLIB +#include /* for zlibVersion() */ +#endif + +#ifdef USE_LICENSE_FILE +#include "oflice.h" +#endif + +#ifndef OFFIS_CONSOLE_APPLICATION +#define OFFIS_CONSOLE_APPLICATION "dcmdjpls" +#endif + +static OFLogger dcmdjplsLogger = OFLog::getLogger("dcmtk.apps." OFFIS_CONSOLE_APPLICATION); + +static char rcsid[] = "$dcmtk: " OFFIS_CONSOLE_APPLICATION " v" + OFFIS_DCMTK_VERSION " " OFFIS_DCMTK_RELEASEDATE " $"; + +// ******************************************** + + +#define SHORTCOL 3 +#define LONGCOL 21 + +int main(int argc, char *argv[]) +{ + +#ifdef HAVE_GUSI_H + GUSISetup(GUSIwithSIOUXSockets); + GUSISetup(GUSIwithInternetSockets); +#endif + + const char *opt_ifname = NULL; + const char *opt_ofname = NULL; + + E_TransferSyntax opt_oxfer = EXS_LittleEndianExplicit; + E_GrpLenEncoding opt_oglenc = EGL_recalcGL; + E_EncodingType opt_oenctype = EET_ExplicitLength; + E_PaddingEncoding opt_opadenc = EPD_noChange; + OFCmdUnsignedInt opt_filepad = 0; + OFCmdUnsignedInt opt_itempad = 0; + E_FileReadMode opt_readMode = ERM_autoDetect; + E_FileWriteMode opt_writeMode = EWM_fileformat; + E_TransferSyntax opt_ixfer = EXS_Unknown; + + // parameter + JLS_UIDCreation opt_uidcreation = EJLSUC_default; + JLS_PlanarConfiguration opt_planarconfig = EJLSPC_restore; + OFBool opt_ignoreOffsetTable = OFFalse; + +#ifdef USE_LICENSE_FILE +LICENSE_FILE_DECLARATIONS +#endif + + OFConsoleApplication app(OFFIS_CONSOLE_APPLICATION, "Decode JPEG-LS compressed DICOM file", rcsid); + OFCommandLine cmd; + cmd.setOptionColumns(LONGCOL, SHORTCOL); + cmd.setParamColumn(LONGCOL + SHORTCOL + 4); + + cmd.addParam("dcmfile-in", "DICOM input filename to be converted"); + cmd.addParam("dcmfile-out", "DICOM output filename"); + + cmd.addGroup("general options:", LONGCOL, SHORTCOL + 2); + cmd.addOption("--help", "-h", "print this help text and exit", OFCommandLine::AF_Exclusive); + cmd.addOption("--version", "print version information and exit", OFCommandLine::AF_Exclusive); + OFLog::addOptions(cmd); + +#ifdef USE_LICENSE_FILE +LICENSE_FILE_DECLARE_COMMAND_LINE_OPTIONS +#endif + + cmd.addGroup("input options:"); + cmd.addSubGroup("input file format:"); + cmd.addOption("--read-file", "+f", "read file format or data set (default)"); + cmd.addOption("--read-file-only", "+fo", "read file format only"); + cmd.addOption("--read-dataset", "-f", "read data set without file meta information"); + + cmd.addGroup("processing options:"); + cmd.addSubGroup("planar configuration:"); + cmd.addOption("--planar-restore", "+pr", "restore original planar configuration (default)"); + cmd.addOption("--planar-auto", "+pa", "automatically determine planar configuration\nfrom SOP class and color space"); + cmd.addOption("--color-by-pixel", "+px", "always store color-by-pixel"); + cmd.addOption("--color-by-plane", "+pl", "always store color-by-plane"); + cmd.addSubGroup("SOP Instance UID:"); + cmd.addOption("--uid-default", "+ud", "keep same SOP Instance UID (default)"); + cmd.addOption("--uid-always", "+ua", "always assign new UID"); + cmd.addSubGroup("other processing options:"); + cmd.addOption("--ignore-offsettable", "+io", "ignore offset table when decompressing"); + + cmd.addGroup("output options:"); + cmd.addSubGroup("output file format:"); + cmd.addOption("--write-file", "+F", "write file format (default)"); + cmd.addOption("--write-dataset", "-F", "write data set without file meta information"); + cmd.addSubGroup("output transfer syntax:"); + cmd.addOption("--write-xfer-little", "+te", "write with explicit VR little endian (default)"); + cmd.addOption("--write-xfer-big", "+tb", "write with explicit VR big endian TS"); + cmd.addOption("--write-xfer-implicit", "+ti", "write with implicit VR little endian TS"); + cmd.addSubGroup("post-1993 value representations:"); + cmd.addOption("--enable-new-vr", "+u", "enable support for new VRs (UN/UT) (default)"); + cmd.addOption("--disable-new-vr", "-u", "disable support for new VRs, convert to OB"); + cmd.addSubGroup("group length encoding:"); + cmd.addOption("--group-length-recalc", "+g=", "recalculate group lengths if present (default)"); + cmd.addOption("--group-length-create", "+g", "always write with group length elements"); + cmd.addOption("--group-length-remove", "-g", "always write without group length elements"); + cmd.addSubGroup("length encoding in sequences and items:"); + cmd.addOption("--length-explicit", "+e", "write with explicit lengths (default)"); + cmd.addOption("--length-undefined", "-e", "write with undefined lengths"); + cmd.addSubGroup("data set trailing padding (not with --write-dataset):"); + cmd.addOption("--padding-retain", "-p=", "do not change padding (default)"); + cmd.addOption("--padding-off", "-p", "no padding (implicit if --write-dataset)"); + cmd.addOption("--padding-create", "+p", 2, "[f]ile-pad [i]tem-pad: integer", + "align file on multiple of f bytes\nand items on multiple of i bytes"); + + /* evaluate command line */ + prepareCmdLineArgs(argc, argv, OFFIS_CONSOLE_APPLICATION); + if (app.parseCommandLine(cmd, argc, argv)) + { + /* check exclusive options first */ + if (cmd.hasExclusiveOption()) + { + if (cmd.findOption("--version")) + { + app.printHeader(OFTrue /*print host identifier*/); + COUT << OFendl << "External libraries used:" << OFendl; +#ifdef WITH_ZLIB + COUT << "- ZLIB, Version " << zlibVersion() << OFendl; +#endif + COUT << "- " << DJLSDecoderRegistration::getLibraryVersionString() << OFendl; + return 0; + } + } + + /* command line parameters */ + + cmd.getParam(1, opt_ifname); + cmd.getParam(2, opt_ofname); + + /* options */ + + OFLog::configureFromCommandLine(cmd, app); + +#ifdef USE_LICENSE_FILE +LICENSE_FILE_EVALUATE_COMMAND_LINE_OPTIONS +#endif + + cmd.beginOptionBlock(); + if (cmd.findOption("--planar-restore")) opt_planarconfig = EJLSPC_restore; + if (cmd.findOption("--planar-auto")) opt_planarconfig = EJLSPC_auto; + if (cmd.findOption("--color-by-pixel")) opt_planarconfig = EJLSPC_colorByPixel; + if (cmd.findOption("--color-by-plane")) opt_planarconfig = EJLSPC_colorByPlane; + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--uid-default")) opt_uidcreation = EJLSUC_default; + if (cmd.findOption("--uid-always")) opt_uidcreation = EJLSUC_always; + cmd.endOptionBlock(); + + if (cmd.findOption("--ignore-offsettable")) opt_ignoreOffsetTable = OFTrue; + + cmd.beginOptionBlock(); + if (cmd.findOption("--read-file")) + { + opt_readMode = ERM_autoDetect; + opt_ixfer = EXS_Unknown; + } + if (cmd.findOption("--read-file-only")) + { + opt_readMode = ERM_fileOnly; + opt_ixfer = EXS_Unknown; + } + if (cmd.findOption("--read-dataset")) + { + opt_readMode = ERM_dataset; + + // This transfer syntax works as long as the content of encapsulated pixel + // sequences is some kind of JPEG-LS bitstream. hmm? + opt_ixfer = EXS_JPEGLSLossless; + } + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--write-file")) opt_writeMode = EWM_fileformat; + if (cmd.findOption("--write-dataset")) opt_writeMode = EWM_dataset; + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--write-xfer-little")) opt_oxfer = EXS_LittleEndianExplicit; + if (cmd.findOption("--write-xfer-big")) opt_oxfer = EXS_BigEndianExplicit; + if (cmd.findOption("--write-xfer-implicit")) opt_oxfer = EXS_LittleEndianImplicit; + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--enable-new-vr")) dcmEnableGenerationOfNewVRs(); + if (cmd.findOption("--disable-new-vr")) dcmDisableGenerationOfNewVRs(); + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--group-length-recalc")) opt_oglenc = EGL_recalcGL; + if (cmd.findOption("--group-length-create")) opt_oglenc = EGL_withGL; + if (cmd.findOption("--group-length-remove")) opt_oglenc = EGL_withoutGL; + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--length-explicit")) opt_oenctype = EET_ExplicitLength; + if (cmd.findOption("--length-undefined")) opt_oenctype = EET_UndefinedLength; + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--padding-retain")) + { + app.checkConflict("--padding-retain", "--write-dataset", opt_writeMode == EWM_dataset); + opt_opadenc = EPD_noChange; + } + if (cmd.findOption("--padding-off")) opt_opadenc = EPD_withoutPadding; + if (cmd.findOption("--padding-create")) + { + app.checkConflict("--padding-create", "--write-dataset", opt_writeMode == EWM_dataset); + app.checkValue(cmd.getValueAndCheckMin(opt_filepad, 0)); + app.checkValue(cmd.getValueAndCheckMin(opt_itempad, 0)); + opt_opadenc = EPD_withPadding; + } + cmd.endOptionBlock(); + } + + /* print resource identifier */ + OFLOG_DEBUG(dcmdjplsLogger, rcsid << OFendl); + + // register global decompression codecs + DJLSDecoderRegistration::registerCodecs(opt_uidcreation, opt_planarconfig, opt_ignoreOffsetTable); + + /* make sure data dictionary is loaded */ + if (!dcmDataDict.isDictionaryLoaded()) + { + OFLOG_WARN(dcmdjplsLogger, "no data dictionary loaded, " + << "check environment variable: " + << DCM_DICT_ENVIRONMENT_VARIABLE); + } + + // open input file + if ((opt_ifname == NULL) || (strlen(opt_ifname) == 0)) + { + OFLOG_FATAL(dcmdjplsLogger, "invalid filename: "); + return 1; + } + + DcmFileFormat fileformat; + + OFLOG_INFO(dcmdjplsLogger, "reading input file " << opt_ifname); + + OFCondition error = fileformat.loadFile(opt_ifname, opt_ixfer, EGL_noChange, DCM_MaxReadLength, opt_readMode); + if (error.bad()) + { + OFLOG_FATAL(dcmdjplsLogger, error.text() << ": reading file: " << opt_ifname); + return 1; + } + + DcmDataset *dataset = fileformat.getDataset(); + + OFLOG_INFO(dcmdjplsLogger, "decompressing file"); + + DcmXfer opt_oxferSyn(opt_oxfer); + DcmXfer original_xfer(dataset->getOriginalXfer()); + + error = dataset->chooseRepresentation(opt_oxfer, NULL); + if (error.bad()) + { + OFLOG_FATAL(dcmdjplsLogger, error.text() << ": decompressing file: " << opt_ifname); + if (error == EC_CannotChangeRepresentation) + OFLOG_FATAL(dcmdjplsLogger, "Input transfer syntax " << original_xfer.getXferName() << " not supported"); + return 1; + } + + if (! dataset->canWriteXfer(opt_oxfer)) + { + OFLOG_FATAL(dcmdjplsLogger, "no conversion to transfer syntax " << opt_oxferSyn.getXferName() << " possible"); + return 1; + } + + OFLOG_INFO(dcmdjplsLogger, "creating output file " << opt_ofname); + + // update file meta information with new SOP Instance UID + if (opt_uidcreation && (opt_writeMode == EWM_fileformat)) + opt_writeMode = EWM_updateMeta; + + fileformat.loadAllDataIntoMemory(); + error = fileformat.saveFile(opt_ofname, opt_oxfer, opt_oenctype, opt_oglenc, opt_opadenc, + OFstatic_cast(Uint32, opt_filepad), OFstatic_cast(Uint32, opt_itempad), opt_writeMode); + + if (error != EC_Normal) + { + OFLOG_FATAL(dcmdjplsLogger, error.text() << ": writing file: " << opt_ofname); + return 1; + } + + OFLOG_INFO(dcmdjplsLogger, "conversion successful"); + + // deregister global decompression codecs + DJLSDecoderRegistration::cleanup(); + + return 0; +} diff --git a/dcmjpls/apps/dcml2pnm.cc b/dcmjpls/apps/dcml2pnm.cc new file mode 100644 index 00000000..20b75dd6 --- /dev/null +++ b/dcmjpls/apps/dcml2pnm.cc @@ -0,0 +1,27 @@ +/* + * + * Copyright (C) 2001-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmjpls + * + * Author: Uli Schlachter + * + * Purpose: Convert DICOM Images to PPM or PGM using the dcmimage/dcmjpls library. + * + */ + + +// compile "dcm2pnm" with dcmjpls support +#define BUILD_DCM2PNM_AS_DCML2PNM + +// include full implementation of "dcm2pnm" +#include "../../dcmimage/apps/dcm2pnm.cc" diff --git a/dcmjpls/configure b/dcmjpls/configure new file mode 100755 index 00000000..396668ee --- /dev/null +++ b/dcmjpls/configure @@ -0,0 +1,56 @@ +#! /bin/sh + +parentdir=`pwd` +thisdir=$parentdir + +# The following test constructs relative path from the module +# directory to the configuration directory. If you know this path +# you can substitute this with +# configdir= +# It is very important that the configdir path is relative. + +configdir="configdir" + +while test "$parentdir" != "/" -a "$configdir" = "configdir"; do + if test -d "$parentdir/config" ; then + configdir=$parentdir/config + else + parentdir=`echo $parentdir | sed 's/\/[^\/]*$//'` + fi +done + +if test "$configdir" = "configdir" ; then + echo "Cannot find configure directory" + exit 1 +fi + +if test $# != 0; then + case $1 in + -a) + shift + cd "$configdir" + echo "running configure in config-directory" + ./configure $* + cd $thisdir + echo "running configure for this module" + sh "$configdir/confmod" --srcdir=. $* + ;; + -c) + shift + cd "$configdir" + echo "running configure in config-directory" + ./configure $* + ;; + *) + echo "running configure for this module" + sh "$configdir/confmod" --srcdir=. $* + ;; + esac +else + echo "running configure for this module" + sh "$configdir/confmod" --srcdir=. $* +fi + + + + diff --git a/dcmjpls/data/Makefile.in b/dcmjpls/data/Makefile.in new file mode 100644 index 00000000..9af028cc --- /dev/null +++ b/dcmjpls/data/Makefile.in @@ -0,0 +1,23 @@ +# +# Makefile for dcmjpls/data +# + +@SET_MAKE@ + +SHELL = /bin/sh +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +configdir = @top_srcdir@/@configdir@ + +include $(configdir)/@common_makefile@ + + +all: + +install: + +clean: + rm -f $(TRASH) + +distclean: + rm -f $(DISTTRASH) diff --git a/dcmjpls/docs/License.txt b/dcmjpls/docs/License.txt new file mode 100644 index 00000000..14950b7e --- /dev/null +++ b/dcmjpls/docs/License.txt @@ -0,0 +1,33 @@ +The libcharls library containing the JPEG-LS encoder and decoder in this +DCMTK module is based on the CharLS library (see http://charls.codeplex.com/). + +The CharLS library is available under the following license: +------------------------------------------------------------------------------- +Copyright (c) 2007-2010, Jan de Vaan +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of my employer, nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +------------------------------------------------------------------------------- diff --git a/dcmjpls/docs/Makefile.in b/dcmjpls/docs/Makefile.in new file mode 100644 index 00000000..57ff7cf8 --- /dev/null +++ b/dcmjpls/docs/Makefile.in @@ -0,0 +1,23 @@ +# +# Makefile for dcmjpls/docs +# + +@SET_MAKE@ + +SHELL = /bin/sh +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +configdir = @top_srcdir@/@configdir@ + +include $(configdir)/@common_makefile@ + + +all: + +install: + +clean: + rm -f $(TRASH) + +distclean: + rm -f $(DISTTRASH) diff --git a/dcmjpls/docs/dcmcjpls.man b/dcmjpls/docs/dcmcjpls.man new file mode 100644 index 00000000..ceb4a031 --- /dev/null +++ b/dcmjpls/docs/dcmcjpls.man @@ -0,0 +1,381 @@ +/*! + +\if MANPAGES +\page dcmcjpls Encode DICOM file to JPEG-LS transfer syntax +\else +\page dcmcjpls dcmcjpls: Encode DICOM file to JPEG-LS transfer syntax +\endif + +\section synopsis SYNOPSIS + +\verbatim +dcmcjpls [options] dcmfile-in dcmfile-out +\endverbatim + +\section description DESCRIPTION + +The \b dcmcjpls utility reads an uncompressed DICOM image (\e dcmfile-in), +performs a JPEG-LS compression (i. e. conversion to an encapsulated DICOM +transfer syntax) and writes the converted image to an output file +(\e dcmfile-out). + +\section parameters PARAMETERS + +\verbatim +dcmfile-in DICOM input filename to be converted + +dcmfile-out DICOM output filename +\endverbatim + +\section options OPTIONS + +\subsection general_options general options +\verbatim + -h --help + print this help text and exit + + --version + print version information and exit + + --arguments + print expanded command line arguments + + -q --quiet + quiet mode, print no warnings and errors + + -v --verbose + verbose mode, print processing details + + -d --debug + debug mode, print debug information + + -ll --log-level [l]evel: string constant + (fatal, error, warn, info, debug, trace) + use level l for the logger + + -lc --log-config [f]ilename: string + use config file f for the logger +\endverbatim + +\subsection input_options input options +\verbatim +input file format: + + +f --read-file + read file format or data set (default) + + +fo --read-file-only + read file format only + + -f --read-dataset + read data set without file meta information + +input transfer syntax: + + -t= --read-xfer-auto + use TS recognition (default) + + -td --read-xfer-detect + ignore TS specified in the file meta header + + -te --read-xfer-little + read with explicit VR little endian TS + + -tb --read-xfer-big + read with explicit VR big endian TS + + -ti --read-xfer-implicit + read with implicit VR little endian TS +\endverbatim + +\subsection JPEG_LS_encoding_options JPEG-LS encoding options +\verbatim +JPEG-LS process: + + +el --encode-lossless + encode JPEG-LS lossless only TS (default) + + # This options selects the JPEG-LS lossless only transfer syntax + # and performs a lossless compression. + + +en --encode-nearlossless + encode JPEG-LS near-lossless TS (NEAR: 2) + + # This options selects the JPEG-LS lossy transfer syntax + # and performs a near-lossless compression. + +JPEG-LS bit rate (near-lossless only): + + +md --max-deviation [d]eviation: integer (default: 2) + defines maximum deviation for an encoded pixel + + # This option specifies the maximum deviation for a single pixel from + # the original pixel value. + +lossless compression: + + +pr --prefer-raw + prefer raw encoder mode (default) + + # This option enables the raw encoder. The raw encoder encodes the + # complete pixel cell as it was read from the source image without + # performing any modifications. + + +pc --prefer-cooked + prefer cooked encoder mode + + # This option enables the cooked encoder. The cooked encoder moves + # overlay data to separate tags (60xx,3000) and only encodes the + # stored bits in each pixel. + +JPEG-LS compression: + + +t1 --threshold1 [t]hreshhold: integer (default for 8 bpp: 3) + set JPEG-LS encoding parameter threshold 1 + + +t2 --threshold2 [t]hreshhold: integer (default for 8 bpp: 7) + set JPEG-LS encoding parameter threshold 2 + + +t3 --threshold3 [t]hreshhold: integer (default for 8 bpp: 21) + set JPEG-LS encoding parameter threshold 3 + + +rs --reset [r]eset: integer (default: 64) + set JPEG-LS encoding parameter reset + + +lm --limit [l]imit: integer (default: 0) + set JPEG-LS encoding parameter limit + +JPEG-LS interleave: + + +il --interleave-line + force line-interleaved JPEG-LS images (default) + + # This flag forces line-interleaved mode for the resulting image. + # In line-interleave mode each line from the source image is + # compressed separately for each component and then the next line + # is encoded. + + +is --interleave-sample + force sample-interleaved JPEG-LS images + + # This flag forces sample-interleaved mode for the resulting image. + # In sample-interleave mode each pixel's components are encoded before + # the next pixe is encoded. + + +in --interleave-none + force uninterleaved JPEG-LS images + + # This flag forces uninterleaved mode for the resulting image. + # In this mode, each of the image's components are completely encoded + # before the next component is handled. + + +iv --interleave-default + use the fastest possible interleave mode + + # This flag selects an interleave mode based on the source image's mode. + # If possible, the image is not converted to a different interleave mode. +\endverbatim + +\subsection enc_pix_data_encoding_opt encapsulated pixel data encoding options +\verbatim +encapsulated pixel data fragmentation: + + +ff --fragment-per-frame + encode each frame as one fragment (default) + + # This option causes the creation of one compressed fragment for each + # frame (recommended). + + +fs --fragment-size [s]ize: integer + limit fragment size to s kbytes + + # This option limits the fragment size which may cause the creation of + # multiple fragments per frame. + +basic offset table encoding: + + +ot --offset-table-create + create offset table (default) + + # This option causes the creation of a valid offset table for the + # compressed JPEG fragments. + + -ot --offset-table-empty + leave offset table empty + + # This option causes the creation of an empty offset table + # for the compressed JPEG fragments. + +SOP Class UID: + + +cd --class-default + keep SOP Class UID (default) + + # Keep the SOP Class UID of the source image. + + +cs --class-sc + convert to Secondary Capture Image (implies --uid-always) + + # Convert the image to Secondary Capture. In addition to the SOP Class + # UID, all attributes required for a valid secondary capture image are + # added. A new SOP instance UID is always assigned. + +SOP Instance UID: + + +ud --uid-default + assign new UID if lossy compression (default) + + # Assigns a new SOP instance UID if the compression is lossy JPEG. + + +ua --uid-always + always assign new UID + + # Unconditionally assigns a new SOP instance UID. + + +un --uid-never + never assign new UID + + # Never assigns a new SOP instance UID. +\endverbatim + +\subsection output_options output options +\verbatim +post-1993 value representations: + + +u --enable-new-vr + enable support for new VRs (UN/UT) (default) + + -u --disable-new-vr + disable support for new VRs, convert to OB + +group length encoding: + + +g= --group-length-recalc + recalculate group lengths if present (default) + + +g --group-length-create + always write with group length elements + + -g --group-length-remove + always write without group length elements + +length encoding in sequences and items: + + +e --length-explicit + write with explicit lengths (default) + + -e --length-undefined + write with undefined lengths + +data set trailing padding: + + -p= --padding-retain + do not change padding (default) + + -p --padding-off + no padding + + +p --padding-create [f]ile-pad [i]tem-pad: integer + align file on multiple of f bytes + and items on multiple of i bytes +\endverbatim + +\section notes NOTES + +The \b dcmcjpls utility compresses DICOM images of all SOP classes. However, +\b dcmcjpls does not attempt to ensure that the compressed image still +complies with all restrictions of the object's IOD. + +The user is responsible for making sure that the compressed images he creates +are compliant with the DICOM standard. If in question, the \b dcmcjpls utility +allows one to convert an image to secondary capture - this SOP class does not +pose restrictions as the ones mentioned above. + +\section transfer_syntaxes TRANSFER SYNTAXES + +\b dcmcjpls supports the following transfer syntaxes for input +(\e dcmfile-in): + +\verbatim +LittleEndianImplicitTransferSyntax 1.2.840.10008.1.2 +LittleEndianExplicitTransferSyntax 1.2.840.10008.1.2.1 +DeflatedExplicitVRLittleEndianTransferSyntax 1.2.840.10008.1.2.1.99 (*) +BigEndianExplicitTransferSyntax 1.2.840.10008.1.2.2 +\endverbatim + +(*) if compiled with zlib support enabled + +\b dcmcjpls supports the following transfer syntaxes for output +(\e dcmfile-out): + +\verbatim +JPEGLSLosslessTransferSyntax 1.2.840.10008.1.2.4.80 +JPEGLSLossyTransferSyntax 1.2.840.10008.1.2.4.81 +\endverbatim + +\section logging LOGGING + +The level of logging output of the various command line tools and underlying +libraries can be specified by the user. By default, only errors and warnings +are written to the standard error stream. Using option \e --verbose also +informational messages like processing details are reported. Option +\e --debug can be used to get more details on the internal activity, e.g. for +debugging purposes. Other logging levels can be selected using option +\e --log-level. In \e --quiet mode only fatal errors are reported. In such +very severe error events, the application will usually terminate. For more +details on the different logging levels, see documentation of module "oflog". + +In case the logging output should be written to file (optionally with logfile +rotation), to syslog (Unix) or the event log (Windows) option \e --log-config +can be used. This configuration file also allows for directing only certain +messages to a particular output stream and for filtering certain messages +based on the module or application where they are generated. An example +configuration file is provided in \/logger.cfg. + +\section command_line COMMAND LINE + +All command line tools use the following notation for parameters: square +brackets enclose optional values (0-1), three trailing dots indicate that +multiple values are allowed (1-n), a combination of both means 0 to n values. + +Command line options are distinguished from parameters by a leading '+' or '-' +sign, respectively. Usually, order and position of command line options are +arbitrary (i.e. they can appear anywhere). However, if options are mutually +exclusive the rightmost appearance is used. This behavior conforms to the +standard evaluation rules of common Unix shells. + +In addition, one or more command files can be specified using an '@' sign as a +prefix to the filename (e.g. \@command.txt). Such a command argument +is replaced by the content of the corresponding text file (multiple +whitespaces are treated as a single separator unless they appear between two +quotation marks) prior to any further evaluation. Please note that a command +file cannot contain another command file. This simple but effective approach +allows one to summarize common combinations of options/parameters and avoids +longish and confusing command lines (an example is provided in file +\/dumppat.txt). + +\section environment ENVIRONMENT + +The \b dcmcjpls utility will attempt to load DICOM data dictionaries specified +in the \e DCMDICTPATH environment variable. By default, i.e. if the +\e DCMDICTPATH environment variable is not set, the file +\/dicom.dic will be loaded unless the dictionary is built +into the application (default for Windows). + +The default behavior should be preferred and the \e DCMDICTPATH environment +variable only used when alternative data dictionaries are required. The +\e DCMDICTPATH environment variable has the same format as the Unix shell +\e PATH variable in that a colon (":") separates entries. On Windows systems, +a semicolon (";") is used as a separator. The data dictionary code will +attempt to load each file specified in the \e DCMDICTPATH environment variable. +It is an error if no data dictionary can be loaded. + +\section see_also SEE ALSO + +dcmdjpls(1) + +\section copyright COPYRIGHT + +Copyright (C) 2009-2014 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany. + +*/ diff --git a/dcmjpls/docs/dcmdjpls.man b/dcmjpls/docs/dcmdjpls.man new file mode 100644 index 00000000..8003f0b4 --- /dev/null +++ b/dcmjpls/docs/dcmdjpls.man @@ -0,0 +1,280 @@ +/*! + +\if MANPAGES +\page dcmdjpls Decode JPEG-LS compressed DICOM file +\else +\page dcmdjpls dcmdjpls: Decode JPEG-LS compressed DICOM file +\endif + +\section synopsis SYNOPSIS + +\verbatim +dcmdjpls [options] dcmfile-in dcmfile-out +\endverbatim + +\section description DESCRIPTION + +The \b dcmdjpls utility reads a JPEG-ls compressed DICOM image (\e dcmfile-in), +decompresses the JPEG-LS data (i. e. conversion to a native DICOM transfer +syntax) and writes the converted image to an output file (\e dcmfile-out). + +\section parameters PARAMETERS + +\verbatim +dcmfile-in DICOM input filename to be converted + +dcmfile-out DICOM output filename +\endverbatim + +\section options OPTIONS + +\subsection general_options general options +\verbatim + -h --help + print this help text and exit + + --version + print version information and exit + + --arguments + print expanded command line arguments + + -q --quiet + quiet mode, print no warnings and errors + + -v --verbose + verbose mode, print processing details + + -d --debug + debug mode, print debug information + + -ll --log-level [l]evel: string constant + (fatal, error, warn, info, debug, trace) + use level l for the logger + + -lc --log-config [f]ilename: string + use config file f for the logger +\endverbatim + +\subsection input_options input options +\verbatim +input file format: + + +f --read-file + read file format or data set (default) + + +fo --read-file-only + read file format only + + -f --read-dataset + read data set without file meta information + + # This option allows one to decompress JPEG-LS compressed DICOM objects that have + # been stored as dataset without meta-header. Such a thing should not exist + # since the transfer syntax cannot be reliably determined without meta-header, + # but unfortunately it does. +\endverbatim + +\subsection processing_options processing options +\verbatim +planar configuration: + + +pr --planar-restore + restore original planar configuration (default) + + # If the compressed image is a color image, restore the planar + # configuration as described in the Planar Configuration attribute. + + +pa --planar-auto + automatically determine planar configuration + from SOP class and color space + + # If the compressed image is a color image, store in color-by-plane + # planar configuration if required by the SOP class and photometric + # interpretation. Hardcopy Color images are always stored color-by- + # plane, and the revised Ultrasound image objects are stored color-by- + # plane if the color model is YBR_FULL. Everything else is stored + # color-by-pixel. + + +px --color-by-pixel + always store color-by-pixel + + # If the compressed image is a color image, store in color-by-pixel + # planar configuration. + + +pl --color-by-plane + always store color-by-plane + + # If the compressed image is a color image, store in color-by-plane + # planar configuration. + +SOP Instance UID: + + +ud --uid-default + keep same SOP Instance UID (default) + + # Never assigns a new SOP instance UID. + + +ua --uid-always + always assign new UID + + # Always assigns a new SOP instance UID. + +other processing options: + + +io --ignore-offsettable + ignore offset table when decompressing +\endverbatim + +\subsection output_options output options +\verbatim +output file format: + + +F --write-file + write file format (default) + + -F --write-dataset + write data set without file meta information + +output transfer syntax: + + +te --write-xfer-little + write with explicit VR little endian (default) + + +tb --write-xfer-big + write with explicit VR big endian TS + + +ti --write-xfer-implicit + write with implicit VR little endian TS + +post-1993 value representations: + + +u --enable-new-vr + enable support for new VRs (UN/UT) (default) + + -u --disable-new-vr + disable support for new VRs, convert to OB + +group length encoding: + + +g= --group-length-recalc + recalculate group lengths if present (default) + + +g --group-length-create + always write with group length elements + + -g --group-length-remove + always write without group length elements + +length encoding in sequences and items: + + +e --length-explicit + write with explicit lengths (default) + + -e --length-undefined + write with undefined lengths + +data set trailing padding (not with --write-dataset): + + -p= --padding-retain + do not change padding (default if not --write-dataset) + + -p --padding-off + no padding (implicit if --write-dataset) + + +p --padding-create [f]ile-pad [i]tem-pad: integer + align file on multiple of f bytes + and items on multiple of i bytes +\endverbatim + +\section transfer_syntaxes TRANSFER SYNTAXES + +\b dcmdjpls supports the following transfer syntaxes for input +(\e dcmfile-in): + +\verbatim +LittleEndianImplicitTransferSyntax 1.2.840.10008.1.2 +LittleEndianExplicitTransferSyntax 1.2.840.10008.1.2.1 +DeflatedExplicitVRLittleEndianTransferSyntax 1.2.840.10008.1.2.1.99 (*) +BigEndianExplicitTransferSyntax 1.2.840.10008.1.2.2 +JPEGLSLosslessTransferSyntax 1.2.840.10008.1.2.4.80 +JPEGLSLossyTransferSyntax 1.2.840.10008.1.2.4.81 +\endverbatim + +(*) if compiled with zlib support enabled + +\b dcmdjpls supports the following transfer syntaxes for output +(\e dcmfile-out): + +\verbatim +LittleEndianImplicitTransferSyntax 1.2.840.10008.1.2 +LittleEndianExplicitTransferSyntax 1.2.840.10008.1.2.1 +BigEndianExplicitTransferSyntax 1.2.840.10008.1.2.2 +\endverbatim + +\section logging LOGGING + +The level of logging output of the various command line tools and underlying +libraries can be specified by the user. By default, only errors and warnings +are written to the standard error stream. Using option \e --verbose also +informational messages like processing details are reported. Option +\e --debug can be used to get more details on the internal activity, e.g. for +debugging purposes. Other logging levels can be selected using option +\e --log-level. In \e --quiet mode only fatal errors are reported. In such +very severe error events, the application will usually terminate. For more +details on the different logging levels, see documentation of module "oflog". + +In case the logging output should be written to file (optionally with logfile +rotation), to syslog (Unix) or the event log (Windows) option \e --log-config +can be used. This configuration file also allows for directing only certain +messages to a particular output stream and for filtering certain messages +based on the module or application where they are generated. An example +configuration file is provided in \/logger.cfg. + +\section command_line COMMAND LINE + +All command line tools use the following notation for parameters: square +brackets enclose optional values (0-1), three trailing dots indicate that +multiple values are allowed (1-n), a combination of both means 0 to n values. + +Command line options are distinguished from parameters by a leading '+' or '-' +sign, respectively. Usually, order and position of command line options are +arbitrary (i.e. they can appear anywhere). However, if options are mutually +exclusive the rightmost appearance is used. This behavior conforms to the +standard evaluation rules of common Unix shells. + +In addition, one or more command files can be specified using an '@' sign as a +prefix to the filename (e.g. \@command.txt). Such a command argument +is replaced by the content of the corresponding text file (multiple +whitespaces are treated as a single separator unless they appear between two +quotation marks) prior to any further evaluation. Please note that a command +file cannot contain another command file. This simple but effective approach +allows one to summarize common combinations of options/parameters and avoids +longish and confusing command lines (an example is provided in file +\/dumppat.txt). + +\section environment ENVIRONMENT + +The \b dcmdjpls utility will attempt to load DICOM data dictionaries specified +in the \e DCMDICTPATH environment variable. By default, i.e. if the +\e DCMDICTPATH environment variable is not set, the file +\/dicom.dic will be loaded unless the dictionary is built +into the application (default for Windows). + +The default behavior should be preferred and the \e DCMDICTPATH environment +variable only used when alternative data dictionaries are required. The +\e DCMDICTPATH environment variable has the same format as the Unix shell +\e PATH variable in that a colon (":") separates entries. On Windows systems, +a semicolon (";") is used as a separator. The data dictionary code will +attempt to load each file specified in the \e DCMDICTPATH environment variable. +It is an error if no data dictionary can be loaded. + +\section see_also SEE ALSO + +dcmcjpls(1) + +\section copyright COPYRIGHT + +Copyright (C) 2009-2014 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany. + +*/ diff --git a/dcmjpls/docs/dcmjpls.dox b/dcmjpls/docs/dcmjpls.dox new file mode 100644 index 00000000..d390d0bb --- /dev/null +++ b/dcmjpls/docs/dcmjpls.dox @@ -0,0 +1,77 @@ +/*! + +\page mod_dcmjpls dcmjpls: a compression/decompression library and utility apps + +This module contains classes that convert between uncompressed and +JPEG-LS compressed representations (transfer syntaxes) of a DICOM +image object. Both lossless and near-lossless JPEG-LS processes are +supported. This module implements a family of codecs that are derived +from class DcmCodec and can be registered in the codec list maintained +in module dcmdata. + +The main interface classes are: +\li \b DJLSEncoderRegistration +\li \b DJLSDecoderRegistration +\li \b DJLSEncoderBase +\li \b DJLSDecoderBase + +\section Tools + +This module contains the following command line tools: +\li \ref dcmcjpls +\li \ref dcmdjpls +\li \ref dcml2pnm + +\section Examples + +The following example shows how to compress a DICOM image file with lossless JPEG-LS: + +\code +DJLSEncoderRegistration::registerCodecs(); // register JPEG codecs +DcmFileFormat fileformat; +if (fileformat.loadFile("test.dcm").good()) +{ + DcmDataset *dataset = fileformat.getDataset(); + DcmItem *metaInfo = fileformat.getMetaInfo(); + DJLSRepresentationParameter rp(0, OFTrue); // parameters for lossless + + // this causes the lossless JPEG-LS version of the dataset to be created + dataset->chooseRepresentation(EXS_JPEGLSLossless, ¶ms); + + // check if everything went well + if (dataset->canWriteXfer(EXS_JPEGLSLossless)) + { + // force the meta-header UIDs to be re-generated when storing the file + // since the UIDs in the data set may have changed + delete metaInfo->remove(DCM_MediaStorageSOPClassUID); + delete metaInfo->remove(DCM_MediaStorageSOPInstanceUID); + + // store in lossless JPEG format + fileformat.saveFile("test_jpls.dcm", EXS_JPEGLSLossless); + } +} +DJLSEncoderRegistration::cleanup(); // deregister JPEG-LS codecs +\endcode + +The following example shows how to decompress a JPEG-LS compressed DICOM image file: + +\code +DJLSDecoderRegistration::registerCodecs(); // register JPEG-LS codecs +DcmFileFormat fileformat; +if (fileformat.loadFile("test_jpls.dcm").good()) +{ + DcmDataset *dataset = fileformat.getDataset(); + + // decompress data set if compressed + dataset->chooseRepresentation(EXS_LittleEndianExplicit, NULL); + + // check if everything went well + if (dataset->canWriteXfer(EXS_LittleEndianExplicit)) + { + fileformat.saveFile("test_decompressed.dcm", EXS_LittleEndianExplicit); + } +} +DJLSDecoderRegistration::cleanup(); // deregister JPEG-LS codecs +\endcode + +*/ diff --git a/dcmjpls/docs/dcml2pnm.man b/dcmjpls/docs/dcml2pnm.man new file mode 100644 index 00000000..58718ecf --- /dev/null +++ b/dcmjpls/docs/dcml2pnm.man @@ -0,0 +1,503 @@ +/*! + +\if MANPAGES +\page dcml2pnm Convert DICOM images to PGM/PPM, PNG, TIFF or BMP +\else +\page dcml2pnm dcml2pnm: Convert DICOM images to PGM/PPM, PNG, TIFF or BMP +\endif + +\section synopsis SYNOPSIS + +\verbatim +dcml2pnm [options] dcmfile-in [bitmap-out] +\endverbatim + +\section description DESCRIPTION + +The \b dcml2pnm utility reads a DICOM image, converts the pixel data according +to the selected image processing options and writes back an image in the +well-known PGM/PPM (portable gray map / portable pix map), PNG, TIFF or +Windows BMP format. This utility supports uncompressed as well as JPEG-LS +and RLE compressed DICOM images. + +\section parameters PARAMETERS + +\verbatim +dcmfile-in DICOM input filename to be converted + +bitmap-out output filename to be written (default: stdout) +\endverbatim + +\section options OPTIONS + +\subsection general_options general options +\verbatim + -h --help + print this help text and exit + + --version + print version information and exit + + --arguments + print expanded command line arguments + + -q --quiet + quiet mode, print no warnings and errors + + -v --verbose + verbose mode, print processing details + + -d --debug + debug mode, print debug information + + -ll --log-level [l]evel: string constant + (fatal, error, warn, info, debug, trace) + use level l for the logger + + -lc --log-config [f]ilename: string + use config file f for the logger +\endverbatim + +\subsection input_options input options +\verbatim +input file format: + + +f --read-file + read file format or data set (default) + + +fo --read-file-only + read file format only + + -f --read-dataset + read data set without file meta information + +input transfer syntax: + + -t= --read-xfer-auto + use TS recognition (default) + + -td --read-xfer-detect + ignore TS specified in the file meta header + + -te --read-xfer-little + read with explicit VR little endian TS + + -tb --read-xfer-big + read with explicit VR big endian TS + + -ti --read-xfer-implicit + read with implicit VR little endian TS +\endverbatim + +\subsection image_processing_options image processing options +\verbatim +frame selection: + + +F --frame [n]umber: integer + select specified frame (default: 1) + + +Fr --frame-range [n]umber [c]ount: integer + select c frames beginning with frame n + + +Fa --all-frames + select all frames + +rotation: + + +Rl --rotate-left + rotate image left (-90 degrees) + + +Rr --rotate-right + rotate image right (+90 degrees) + + +Rtd --rotate-top-down + rotate image top-down (180 degrees) + +flipping: + + +Lh --flip-horizontally + flip image horizontally + + +Lv --flip-vertically + flip image vertically + + +Lhv --flip-both-axes + flip image horizontally and vertically + +scaling: + + +a --recognize-aspect + recognize pixel aspect ratio (default) + + -a --ignore-aspect + ignore pixel aspect ratio when scaling + + +i --interpolate [n]umber of algorithm: integer + use interpolation when scaling (1..4, default: 1) + + -i --no-interpolation + no interpolation when scaling + + -S --no-scaling + no scaling, ignore pixel aspect ratio (default) + + +Sxf --scale-x-factor [f]actor: float + scale x axis by factor, auto-compute y axis + + +Syf --scale-y-factor [f]actor: float + scale y axis by factor, auto-compute x axis + + +Sxv --scale-x-size [n]umber: integer + scale x axis to n pixels, auto-compute y axis + + +Syv --scale-y-size [n]umber: integer + scale y axis to n pixels, auto-compute x axis + +modality LUT transformation: + + -M --no-modality + ignore stored modality LUT transformation + + +M --use-modality + use modality LUT transformation (default) + +VOI LUT transformation: + + -W --no-windowing + no VOI windowing (default) + + +Wi --use-window [n]umber: integer + use the n-th VOI window from image file + + +Wl --use-voi-lut [n]umber: integer + use the n-th VOI look up table from image file + + +Wm --min-max-window + compute VOI window using min-max algorithm + + +Wn --min-max-window-n + compute VOI window using min-max algorithm, + ignoring extreme values + + +Wr --roi-min-max-window [l]eft [t]op [w]idth [h]eight: integer + compute ROI window using min-max algorithm, + region of interest is specified by l,t,w,h + + +Wh --histogram-window [n]umber: integer + compute VOI window using Histogram algorithm, + ignoring n percent + + +Ww --set-window [c]enter [w]idth: float + compute VOI window using center c and width w + + +Wfl --linear-function + set VOI LUT function to LINEAR + + +Wfs --sigmoid-function + set VOI LUT function to SIGMOID + +presentation LUT transformation: + + +Pid --identity-shape + set presentation LUT shape to IDENTITY + + +Piv --inverse-shape + set presentation LUT shape to INVERSE + + +Pod --lin-od-shape + set presentation LUT shape to LIN OD + +overlay: + + -O --no-overlays + do not display overlays + + +O --display-overlay [n]umber: integer + display overlay n (0..16, 0=all, default: +O 0) + + +Omr --ovl-replace + use overlay mode "Replace" + (default for Graphic overlays) + + +Omt --ovl-threshold + use overlay mode "Threshold Replace" + + +Omc --ovl-complement + use overlay mode "Complement" + + +Omv --ovl-invert + use overlay mode "Invert Bitmap" + + +Omi --ovl-roi + use overlay mode "Region of Interest" + (default for ROI overlays) + + +Osf --set-foreground [d]ensity: float + set overlay foreground density (0..1, default: 1) + + +Ost --set-threshold [d]ensity: float + set overlay threshold density (0..1, default: 0.5) + +display LUT transformation: + + +Dm --monitor-file [f]ilename: string + calibrate output according to monitor characteristics + defined in f + + +Dp --printer-file [f]ilename: string + calibrate output according to printer characteristics + defined in f + + +Da --ambient-light [a]mbient light: float + ambient light value (cd/m^2, default: file f) + + +Di --illumination [i]llumination: float + illumination value (cd/m^2, default: file f) + + +Dn --min-density [m]inimum optical density: float + Dmin value (default: off, only with +Dp) + + +Dx --max-density [m]aximum optical density: float + Dmax value (default: off, only with +Dp) + + +Dg --gsd-function + use GSDF for calibration (default for +Dm/+Dp) + + +Dc --cielab-function + use CIELAB function for calibration + +compatibility: + + +Ma --accept-acr-nema + accept ACR-NEMA images without photometric + interpretation + + +Mp --accept-palettes + accept incorrect palette attribute tags + (0028,111x) and (0028,121x) + + +Mc --check-lut-depth + check 3rd value of the LUT descriptor, compare + with expected bit depth based on LUT data + + +Mm --ignore-mlut-depth + ignore 3rd value of the modality LUT descriptor, + determine bits per table entry automatically + + +Mv --ignore-vlut-depth + ignore 3rd value of the VOI LUT descriptor, + determine bits per table entry automatically + +TIFF format: + + +Tl --compr-lzw + LZW compression (default) + + +Tr --compr-rle + RLE compression + + +Tn --compr-none + uncompressed + + +Pd --predictor-default + no LZW predictor (default) + + +Pn --predictor-none + LZW predictor 1 (no prediction) + + +Ph --predictor-horz + LZW predictor 2 (horizontal differencing) + + +Rs --rows-per-strip [r]ows: integer (default: 0) + rows per strip, default 8K per strip + +PNG format: + + +il --interlace + create interlaced file (default) + + -il --nointerlace + create non-interlaced file + + +mf --meta-file + create PNG file meta information (default) + + -mf --meta-none + no PNG file meta information + +other transformations: + + +G --grayscale + convert to grayscale if necessary + + +P --change-polarity + change polarity (invert pixel output) + + +C --clip-region [l]eft [t]op [w]idth [h]eight: integer + clip image region (l, t, w, h) +\endverbatim + +\subsection output_options output options +\verbatim +general: + + -im --image-info + print image details (requires verbose mode) + + -o --no-output + do not create any output (useful with -im) + +filename generation (only with --frame-range or --all-frames): + + +Fc --use-frame-counter + use 0-based counter for filenames (default) + + +Fn --use-frame-number + use absolute frame number for filenames + +image format: + + +op --write-raw-pnm + write 8-bit binary PGM/PPM (default for files) + + +opb --write-8-bit-pnm + write 8-bit ASCII PGM/PPM (default for stdout) + + +opw --write-16-bit-pnm + write 16-bit ASCII PGM/PPM + + +opn --write-n-bit-pnm [n]umber: integer + write n-bit ASCII PGM/PPM (1..32) + + +ob --write-bmp + write 8-bit (monochrome) or 24-bit (color) BMP + + +obp --write-8-bit-bmp + write 8-bit palette BMP (monochrome only) + + +obt --write-24-bit-bmp + write 24-bit truecolor BMP + + +obr --write-32-bit-bmp + write 32-bit truecolor BMP + + +ot --write-tiff + write 8-bit (monochrome) or 24-bit (color) TIFF + + +on --write-png + write 8-bit (monochrome) or 24-bit (color) PNG + + +on2 --write-16-bit-png + write 16-bit (monochrome) or 48-bit (color) PNG +\endverbatim + +\section notes NOTES + +The following preferred interpolation algorithms can be selected using the +\e --interpolate option: + +\li 1 = free scaling algorithm with interpolation from pbmplus toolkit +\li 2 = free scaling algorithm with interpolation from c't magazine +\li 3 = magnification algorithm with bilinear interpolation from Eduard Stanescu +\li 4 = magnification algorithm with bicubic interpolation from Eduard Stanescu + +The \e --write-tiff option is only available when DCMTK has been configured +and compiled with support for the external \b libtiff TIFF library. The +availability of the TIFF compression options depends on the \b libtiff +configuration. In particular, the patented LZW algorithm may not be +available. + +The \e --write-png option is only available when DCMTK has been configured +and compiled with support for the external \b libpng PNG library. Option +\e --interlace enables progressive image view while loading the PNG file. +Only a few applications take care of the meta info (TEXT) in a PNG file. + +\section transfer_syntaxes TRANSFER SYNTAXES + +\b dcml2pnm supports the following transfer syntaxes for input (\e dcmfile-in): + +\verbatim +LittleEndianImplicitTransferSyntax 1.2.840.10008.1.2 +LittleEndianExplicitTransferSyntax 1.2.840.10008.1.2.1 +DeflatedExplicitVRLittleEndianTransferSyntax 1.2.840.10008.1.2.1.99 (*) +BigEndianExplicitTransferSyntax 1.2.840.10008.1.2.2 +JPEGLSLosslessTransferSyntax 1.2.840.10008.1.2.4.80 +JPEGLSLossyTransferSyntax 1.2.840.10008.1.2.4.81 +RLELosslessTransferSyntax 1.2.840.10008.1.2.5 +\endverbatim + +(*) if compiled with zlib support enabled + +\section logging LOGGING + +The level of logging output of the various command line tools and underlying +libraries can be specified by the user. By default, only errors and warnings +are written to the standard error stream. Using option \e --verbose also +informational messages like processing details are reported. Option +\e --debug can be used to get more details on the internal activity, e.g. for +debugging purposes. Other logging levels can be selected using option +\e --log-level. In \e --quiet mode only fatal errors are reported. In such +very severe error events, the application will usually terminate. For more +details on the different logging levels, see documentation of module "oflog". + +In case the logging output should be written to file (optionally with logfile +rotation), to syslog (Unix) or the event log (Windows) option \e --log-config +can be used. This configuration file also allows for directing only certain +messages to a particular output stream and for filtering certain messages +based on the module or application where they are generated. An example +configuration file is provided in \/logger.cfg. + +\section command_line COMMAND LINE + +All command line tools use the following notation for parameters: square +brackets enclose optional values (0-1), three trailing dots indicate that +multiple values are allowed (1-n), a combination of both means 0 to n values. + +Command line options are distinguished from parameters by a leading '+' or '-' +sign, respectively. Usually, order and position of command line options are +arbitrary (i.e. they can appear anywhere). However, if options are mutually +exclusive the rightmost appearance is used. This behavior conforms to the +standard evaluation rules of common Unix shells. + +In addition, one or more command files can be specified using an '@' sign as a +prefix to the filename (e.g. \@command.txt). Such a command argument +is replaced by the content of the corresponding text file (multiple +whitespaces are treated as a single separator unless they appear between two +quotation marks) prior to any further evaluation. Please note that a command +file cannot contain another command file. This simple but effective approach +allows one to summarize common combinations of options/parameters and avoids +longish and confusing command lines (an example is provided in file +\/dumppat.txt). + +\section environment ENVIRONMENT + +The \b dcml2pnm utility will attempt to load DICOM data dictionaries specified +in the \e DCMDICTPATH environment variable. By default, i.e. if the +\e DCMDICTPATH environment variable is not set, the file +\/dicom.dic will be loaded unless the dictionary is built +into the application (default for Windows). + +The default behavior should be preferred and the \e DCMDICTPATH environment +variable only used when alternative data dictionaries are required. The +\e DCMDICTPATH environment variable has the same format as the Unix shell +\e PATH variable in that a colon (":") separates entries. On Windows systems, +a semicolon (";") is used as a separator. The data dictionary code will +attempt to load each file specified in the \e DCMDICTPATH environment variable. +It is an error if no data dictionary can be loaded. + +\section files FILES + +\/camera.lut - sample characteristics file of a camera +\n\/monitor.lut - sample characteristics file of a monitor +\n\/printer.lut - sample characteristics file of a printer +\n\/scanner.lut - sample characteristics file of a scanner + +\section see_also SEE ALSO + +dcm2pnm(1), img2dcm(1) + +\section copyright COPYRIGHT + +Copyright (C) 2001-2014 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany. + +*/ diff --git a/dcmjpls/docs/readme.txt b/dcmjpls/docs/readme.txt new file mode 100644 index 00000000..9dc062de --- /dev/null +++ b/dcmjpls/docs/readme.txt @@ -0,0 +1,16 @@ +The libcharls library containing the JPEG-LS encoder and decoder in this +DCMTK module is based on the CharLS library (see http://charls.codeplex.com/). + +The CharLS library is available under the license that can be found in +dcmjpls/docs/License.txt. +------------------------------------------------------------------------------ + +The current CharLS version used is revision 55020 dated 2010-10-05. + +The following modifications have been applied to the library: +- removed "test" directory +- removed project files (CharLS.sln, CharLS.vcproj) +- renamed implementation file extensions from .cpp to .cc +- made file names fit into 8.3 characters +- converted file to use UNIX line feeds instead of Windows CR/LF +- removed trailing whitespace, purified tab usage diff --git a/dcmjpls/etc/Makefile.in b/dcmjpls/etc/Makefile.in new file mode 100644 index 00000000..86775aca --- /dev/null +++ b/dcmjpls/etc/Makefile.in @@ -0,0 +1,23 @@ +# +# Makefile for dcmjpls/etc +# + +@SET_MAKE@ + +SHELL = /bin/sh +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +configdir = @top_srcdir@/@configdir@ + +include $(configdir)/@common_makefile@ + + +all: + +install: + +clean: + rm -f $(TRASH) + +distclean: + rm -f $(DISTTRASH) diff --git a/dcmjpls/include/CMakeLists.txt b/dcmjpls/include/CMakeLists.txt new file mode 100644 index 00000000..52033b01 --- /dev/null +++ b/dcmjpls/include/CMakeLists.txt @@ -0,0 +1,2 @@ +# declare installation files +INSTALL(DIRECTORY dcmtk/dcmjpls DESTINATION ${DCMTK_INSTALL_INCDIR}/dcmtk COMPONENT include FILES_MATCHING PATTERN "*.h") diff --git a/dcmjpls/include/Makefile.in b/dcmjpls/include/Makefile.in new file mode 100644 index 00000000..887dd411 --- /dev/null +++ b/dcmjpls/include/Makefile.in @@ -0,0 +1,27 @@ +# +# Makefile for dcmjpls/include +# + +@SET_MAKE@ + +SHELL = /bin/sh +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +configdir = @top_srcdir@/@configdir@ + +include $(configdir)/@common_makefile@ + + +all: + +install: + $(configdir)/mkinstalldirs $(DESTDIR)$(includedir)/dcmtk/dcmjpls + for file in dcmtk/dcmjpls/*.h ; do \ + $(INSTALL_DATA) $$file $(DESTDIR)$(includedir)/dcmtk/dcmjpls ;\ + done + +clean: + rm -f $(TRASH) + +distclean: + rm -f $(DISTTRASH) diff --git a/dcmjpls/include/dcmtk/dcmjpls/djcodecd.h b/dcmjpls/include/dcmtk/dcmjpls/djcodecd.h new file mode 100644 index 00000000..062c0a75 --- /dev/null +++ b/dcmjpls/include/dcmtk/dcmjpls/djcodecd.h @@ -0,0 +1,335 @@ +/* + * + * Copyright (C) 2007-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmjpls + * + * Author: Martin Willkomm, Marco Eichelberg + * + * Purpose: codec classes for JPEG-LS decoders. + * + */ + +#ifndef DCMJPLS_DJCODECD_H +#define DCMJPLS_DJCODECD_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmdata/dccodec.h" /* for class DcmCodec */ +#include "dcmtk/ofstd/ofstring.h" +#include "dcmtk/dcmjpls/dldefine.h" + +/* forward declaration */ +class DJLSCodecParameter; + +/** abstract codec class for JPEG-LS decoders. + * This abstract class contains most of the application logic + * needed for a dcmdata codec object that implements a JPEG-LS decoder. + * This class only supports decompression, it neither implements + * encoding nor transcoding. + */ +class DCMTK_DCMJPLS_EXPORT DJLSDecoderBase: public DcmCodec +{ +public: + + /// default constructor + DJLSDecoderBase(); + + /// destructor + virtual ~DJLSDecoderBase(); + + /** decompresses the given pixel sequence and + * stores the result in the given uncompressedPixelData element. + * @param fromRepParam current representation parameter of compressed data, may be NULL + * @param pixSeq compressed pixel sequence + * @param uncompressedPixelData uncompressed pixel data stored in this element + * @param cp codec parameters for this codec + * @param objStack stack pointing to the location of the pixel data + * element in the current dataset. + * @return EC_Normal if successful, an error code otherwise. + */ + virtual OFCondition decode( + const DcmRepresentationParameter * fromRepParam, + DcmPixelSequence * pixSeq, + DcmPolymorphOBOW& uncompressedPixelData, + const DcmCodecParameter * cp, + const DcmStack& objStack) const; + + /** decompresses a single frame from the given pixel sequence and + * stores the result in the given buffer. + * @param fromParam representation parameter of current compressed + * representation, may be NULL. + * @param fromPixSeq compressed pixel sequence + * @param cp codec parameters for this codec + * @param dataset pointer to dataset in which pixel data element is contained + * @param frameNo number of frame, starting with 0 for the first frame + * @param startFragment index of the compressed fragment that contains + * all or the first part of the compressed bitstream for the given frameNo. + * Upon successful return this parameter is updated to contain the index + * of the first compressed fragment of the next frame. + * When unknown, zero should be passed. In this case the decompression + * algorithm will try to determine the index by itself, which will always + * work if frames are decompressed in increasing order from first to last, + * but may fail if frames are decompressed in random order, multiple fragments + * per frame and multiple frames are present in the dataset, and the offset + * table is empty. + * @param buffer pointer to buffer where frame is to be stored + * @param bufSize size of buffer in bytes + * @param decompressedColorModel upon successful return, the color model + * of the decompressed image (which may be different from the one used + * in the compressed images) is returned in this parameter. + * @return EC_Normal if successful, an error code otherwise. + */ + virtual OFCondition decodeFrame( + const DcmRepresentationParameter * fromParam, + DcmPixelSequence * fromPixSeq, + const DcmCodecParameter * cp, + DcmItem *dataset, + Uint32 frameNo, + Uint32& startFragment, + void *buffer, + Uint32 bufSize, + OFString& decompressedColorModel) const; + + /** compresses the given uncompressed DICOM image and stores + * the result in the given pixSeq element. + * @param pixelData pointer to the uncompressed image data in OW format + * and local byte order + * @param length of the pixel data field in bytes + * @param toRepParam representation parameter describing the desired + * compressed representation (e.g. JPEG quality) + * @param pixSeq compressed pixel sequence (pointer to new DcmPixelSequence object + * allocated on heap) returned in this parameter upon success. + * @param cp codec parameters for this codec + * @param objStack stack pointing to the location of the pixel data + * element in the current dataset. + * @return EC_Normal if successful, an error code otherwise. + */ + virtual OFCondition encode( + const Uint16 * pixelData, + const Uint32 length, + const DcmRepresentationParameter * toRepParam, + DcmPixelSequence * & pixSeq, + const DcmCodecParameter *cp, + DcmStack & objStack) const; + + /** transcodes (re-compresses) the given compressed DICOM image and stores + * the result in the given toPixSeq element. + * @param fromRepType current transfer syntax of the compressed image + * @param fromRepParam current representation parameter of compressed data, may be NULL + * @param fromPixSeq compressed pixel sequence + * @param toRepParam representation parameter describing the desired + * new compressed representation (e.g. JPEG quality) + * @param toPixSeq compressed pixel sequence (pointer to new DcmPixelSequence object + * allocated on heap) returned in this parameter upon success. + * @param cp codec parameters for this codec + * @param objStack stack pointing to the location of the pixel data + * element in the current dataset. + * @return EC_Normal if successful, an error code otherwise. + */ + virtual OFCondition encode( + const E_TransferSyntax fromRepType, + const DcmRepresentationParameter * fromRepParam, + DcmPixelSequence * fromPixSeq, + const DcmRepresentationParameter * toRepParam, + DcmPixelSequence * & toPixSeq, + const DcmCodecParameter * cp, + DcmStack & objStack) const; + + /** checks if this codec is able to convert from the + * given current transfer syntax to the given new + * transfer syntax + * @param oldRepType current transfer syntax + * @param newRepType desired new transfer syntax + * @return true if transformation is supported by this codec, false otherwise. + */ + virtual OFBool canChangeCoding( + const E_TransferSyntax oldRepType, + const E_TransferSyntax newRepType) const; + + /** determine color model of the decompressed image + * @param fromParam representation parameter of current compressed + * representation, may be NULL + * @param fromPixSeq compressed pixel sequence + * @param cp codec parameters for this codec + * @param dataset pointer to dataset in which pixel data element is contained + * @param dataset pointer to DICOM dataset in which this pixel data object + * is located. Used to access photometric interpretation. + * @param decompressedColorModel upon successful return, the color model + * of the decompressed image (which may be different from the one used + * in the compressed images) is returned in this parameter + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition determineDecompressedColorModel( + const DcmRepresentationParameter *fromParam, + DcmPixelSequence *fromPixSeq, + const DcmCodecParameter *cp, + DcmItem *dataset, + OFString &decompressedColorModel) const; + +private: + + // static private helper methods + + /** decompresses a single frame from the given pixel sequence and + * stores the result in the given buffer. + * @param fromPixSeq compressed pixel sequence + * @param cp codec parameters for this codec + * @param dataset pointer to dataset in which pixel data element is contained + * @param frameNo number of frame, starting with 0 for the first frame + * @param startFragment index of the compressed fragment that contains + * all or the first part of the compressed bitstream for the given frameNo. + * Upon successful return this parameter is updated to contain the index + * of the first compressed fragment of the next frame. + * When unknown, zero should be passed. In this case the decompression + * algorithm will try to determine the index by itself, which will always + * work if frames are decompressed in increasing order from first to last, + * but may fail if frames are decompressed in random order, multiple fragments + * per frame and multiple frames are present in the dataset, and the offset + * table is empty. + * @param buffer pointer to buffer where frame is to be stored + * @param bufSize size of buffer in bytes + * @param imageFrames number of frames in this image + * @param imageColumns number of columns for each frame + * @param imageRows number of rows for each frame + * @param imageSamplesPerPixel number of samples per pixel + * @param bytesPerSample number of bytes per sample + * @return EC_Normal if successful, an error code otherwise. + */ + static OFCondition decodeFrame( + DcmPixelSequence * fromPixSeq, + const DJLSCodecParameter *cp, + DcmItem *dataset, + Uint32 frameNo, + Uint32& startFragment, + void *buffer, + Uint32 bufSize, + Sint32 imageFrames, + Uint16 imageColumns, + Uint16 imageRows, + Uint16 imageSamplesPerPixel, + Uint16 bytesPerSample); + + /** determines if a given image requires color-by-plane planar configuration + * depending on SOP Class UID (DICOM IOD) and photometric interpretation. + * All SOP classes defined in the 2003 edition of the DICOM standard or earlier + * are handled correctly. + * @param sopClassUID SOP Class UID + * @param photometricInterpretation decompressed photometric interpretation + * @return legal value for planar configuration + */ + static Uint16 determinePlanarConfiguration( + const OFString& sopClassUID, + const OFString& photometricInterpretation); + + /** computes the number of fragments (pixel items) that comprise the current + * frame in the compressed pixel sequence. This method uses various approaches + * to compute the number of fragments for a frame, including a check of the + * offset table and checking the start of each fragment for JPEG SOI markers. + * @param numberOfFrames total number of frames of the DICOM object + * @param currentFrame index of current frame (0..numberOfFrames-1) + * @param startItem index of fragment (pixel item) the frame starts with + * @param ignoreOffsetTable flag instructing the method to ignore the offset table + * even if present and presumably useful + * @param pixSeq the compressed JPEG-LS pixel sequence + * @return number of fragments for the current frame, zero upon error + */ + static Uint32 computeNumberOfFragments( + Sint32 numberOfFrames, + Uint32 currentFrame, + Uint32 startItem, + OFBool ignoreOffsetTable, + DcmPixelSequence *pixSeq); + + /** check whether the given buffer contains a JPEG-LS start-of-image code + * @param fragmentData pointer to 4 or more bytes of JPEG-LS data + * @returns true if the first four bytes of the code stream indicate that + * this fragment is the start of a new JPEG-LS image, i.e. starts with + * an SOI marker followed by SOF, COM or APPn. + */ + static OFBool isJPEGLSStartOfImage(Uint8 *fragmentData); + + /** converts an RGB or YBR frame with 8 bits/sample from + * color-by-pixel to color-by-plane planar configuration. + * @param imageFrame pointer to image frame, must contain + * at least 3*columns*rows bytes of pixel data. + * @param columns columns + * @param rows rows + * @return EC_Normal if successful, an error code otherwise + */ + static OFCondition createPlanarConfiguration1Byte( + Uint8 *imageFrame, + Uint16 columns, + Uint16 rows); + + /** converts an RGB or YBR frame with 16 bits/sample from + * color-by-pixel to color-by-plane planar configuration. + * @param imageFrame pointer to image frame, must contain + * at least 3*columns*rows words of pixel data. + * @param columns columns + * @param rows rows + * @return EC_Normal if successful, an error code otherwise + */ + static OFCondition createPlanarConfiguration1Word( + Uint16 *imageFrame, + Uint16 columns, + Uint16 rows); + + /** converts an RGB or YBR frame with 8 bits/sample from + * color-by-plane to color-by-pixel planar configuration. + * @param imageFrame pointer to image frame, must contain + * at least 3*columns*rows bytes of pixel data. + * @param columns columns + * @param rows rows + * @return EC_Normal if successful, an error code otherwise + */ + static OFCondition createPlanarConfiguration0Byte( + Uint8 *imageFrame, + Uint16 columns, + Uint16 rows); + + /** converts an RGB or YBR frame with 16 bits/sample from + * color-by-plane to color-by-pixel planar configuration. + * @param imageFrame pointer to image frame, must contain + * at least 3*columns*rows words of pixel data. + * @param columns columns + * @param rows rows + * @return EC_Normal if successful, an error code otherwise + */ + static OFCondition createPlanarConfiguration0Word( + Uint16 *imageFrame, + Uint16 columns, + Uint16 rows); +}; + +/** codec class for JPEG-LS lossless only TS decoding + */ +class DCMTK_DCMJPLS_EXPORT DJLSLosslessDecoder : public DJLSDecoderBase +{ + /** returns the transfer syntax that this particular codec + * is able to Decode + * @return supported transfer syntax + */ + virtual E_TransferSyntax supportedTransferSyntax() const; +}; + +/** codec class for JPEG-LS lossy and lossless TS decoding + */ +class DCMTK_DCMJPLS_EXPORT DJLSNearLosslessDecoder : public DJLSDecoderBase +{ + /** returns the transfer syntax that this particular codec + * is able to encode + * @return supported transfer syntax + */ + virtual E_TransferSyntax supportedTransferSyntax() const; +}; + +#endif diff --git a/dcmjpls/include/dcmtk/dcmjpls/djcodece.h b/dcmjpls/include/dcmtk/dcmjpls/djcodece.h new file mode 100644 index 00000000..f0b79b5a --- /dev/null +++ b/dcmjpls/include/dcmtk/dcmjpls/djcodece.h @@ -0,0 +1,371 @@ +/* + * + * Copyright (C) 2007-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmjpls + * + * Author: Martin Willkomm, Uli Schlachter + * + * Purpose: codec classes for JPEG-LS encoders. + * + */ + +#ifndef DCMJPLS_DJCODEC_H +#define DCMJPLS_DJCODEC_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmdata/dccodec.h" /* for class DcmCodec */ +#include "dcmtk/dcmdata/dcofsetl.h" /* for struct DcmOffsetList */ +#include "dcmtk/ofstd/ofstring.h" /* for class OFString */ +#include "dcmtk/dcmjpls/dldefine.h" + +class DJLSRepresentationParameter; +class DJLSCodecParameter; +class DicomImage; + +/** abstract codec class for JPEG-LS encoders. + * This abstract class contains most of the application logic + * needed for a dcmdata codec object that implements a JPEG-LS encoder + * This class only supports compression, it neither implements + * decoding nor transcoding. + */ +class DCMTK_DCMJPLS_EXPORT DJLSEncoderBase : public DcmCodec +{ +public: + + /// default constructor + DJLSEncoderBase(); + + /// destructor + virtual ~DJLSEncoderBase(); + + /** decompresses the given pixel sequence and + * stores the result in the given uncompressedPixelData element. + * @param fromRepParam current representation parameter of compressed data, may be NULL + * @param pixSeq compressed pixel sequence + * @param uncompressedPixelData uncompressed pixel data stored in this element + * @param cp codec parameters for this codec + * @param objStack stack pointing to the location of the pixel data + * element in the current dataset. + * @return EC_Normal if successful, an error code otherwise. + */ + virtual OFCondition decode( + const DcmRepresentationParameter * fromRepParam, + DcmPixelSequence * pixSeq, + DcmPolymorphOBOW& uncompressedPixelData, + const DcmCodecParameter * cp, + const DcmStack& objStack) const; + + /** decompresses a single frame from the given pixel sequence and + * stores the result in the given buffer. + * @param fromParam representation parameter of current compressed + * representation, may be NULL. + * @param fromPixSeq compressed pixel sequence + * @param cp codec parameters for this codec + * @param dataset pointer to dataset in which pixel data element is contained + * @param frameNo number of frame, starting with 0 for the first frame + * @param startFragment index of the compressed fragment that contains + * all or the first part of the compressed bitstream for the given frameNo. + * Upon successful return this parameter is updated to contain the index + * of the first compressed fragment of the next frame. + * When unknown, zero should be passed. In this case the decompression + * algorithm will try to determine the index by itself, which will always + * work if frames are decompressed in increasing order from first to last, + * but may fail if frames are decompressed in random order, multiple fragments + * per frame and multiple frames are present in the dataset, and the offset + * table is empty. + * @param buffer pointer to buffer where frame is to be stored + * @param bufSize size of buffer in bytes + * @param decompressedColorModel upon successful return, the color model + * of the decompressed image (which may be different from the one used + * in the compressed images) is returned in this parameter. + * @return EC_Normal if successful, an error code otherwise. + */ + virtual OFCondition decodeFrame( + const DcmRepresentationParameter * fromParam, + DcmPixelSequence * fromPixSeq, + const DcmCodecParameter * cp, + DcmItem *dataset, + Uint32 frameNo, + Uint32& startFragment, + void *buffer, + Uint32 bufSize, + OFString& decompressedColorModel) const; + + /** compresses the given uncompressed DICOM image and stores + * the result in the given pixSeq element. + * @param pixelData pointer to the uncompressed image data in OW format + * and local byte order + * @param length of the pixel data field in bytes + * @param toRepParam representation parameter describing the desired + * compressed representation (e.g. JPEG quality) + * @param pixSeq compressed pixel sequence (pointer to new DcmPixelSequence object + * allocated on heap) returned in this parameter upon success. + * @param cp codec parameters for this codec + * @param objStack stack pointing to the location of the pixel data + * element in the current dataset. + * @return EC_Normal if successful, an error code otherwise. + */ + virtual OFCondition encode( + const Uint16 * pixelData, + const Uint32 length, + const DcmRepresentationParameter * toRepParam, + DcmPixelSequence * & pixSeq, + const DcmCodecParameter *cp, + DcmStack & objStack) const; + + /** transcodes (re-compresses) the given compressed DICOM image and stores + * the result in the given toPixSeq element. + * @param fromRepType current transfer syntax of the compressed image + * @param fromRepParam current representation parameter of compressed data, may be NULL + * @param fromPixSeq compressed pixel sequence + * @param toRepParam representation parameter describing the desired + * new compressed representation (e.g. JPEG quality) + * @param toPixSeq compressed pixel sequence (pointer to new DcmPixelSequence object + * allocated on heap) returned in this parameter upon success. + * @param cp codec parameters for this codec + * @param objStack stack pointing to the location of the pixel data + * element in the current dataset. + * @return EC_Normal if successful, an error code otherwise. + */ + virtual OFCondition encode( + const E_TransferSyntax fromRepType, + const DcmRepresentationParameter * fromRepParam, + DcmPixelSequence * fromPixSeq, + const DcmRepresentationParameter * toRepParam, + DcmPixelSequence * & toPixSeq, + const DcmCodecParameter * cp, + DcmStack & objStack) const; + + /** checks if this codec is able to convert from the + * given current transfer syntax to the given new + * transfer syntax + * @param oldRepType current transfer syntax + * @param newRepType desired new transfer syntax + * @return true if transformation is supported by this codec, false otherwise. + */ + virtual OFBool canChangeCoding( + const E_TransferSyntax oldRepType, + const E_TransferSyntax newRepType) const; + + /** determine color model of the decompressed image + * @param fromParam representation parameter of current compressed + * representation, may be NULL + * @param fromPixSeq compressed pixel sequence + * @param cp codec parameters for this codec + * @param dataset pointer to dataset in which pixel data element is contained + * @param dataset pointer to DICOM dataset in which this pixel data object + * is located. Used to access photometric interpretation. + * @param decompressedColorModel upon successful return, the color model + * of the decompressed image (which may be different from the one used + * in the compressed images) is returned in this parameter + * @return EC_Normal if successful, an error code otherwise + */ + virtual OFCondition determineDecompressedColorModel( + const DcmRepresentationParameter *fromParam, + DcmPixelSequence *fromPixSeq, + const DcmCodecParameter *cp, + DcmItem *dataset, + OFString &decompressedColorModel) const; + +private: + + /** returns the transfer syntax that this particular codec + * is able to encode + * @return supported transfer syntax + */ + virtual E_TransferSyntax supportedTransferSyntax() const = 0; + + /** lossless encoder that compresses the complete pixel cell + * (very much like the RLE encoder in module dcmdata). + * @param pixelData pointer to the uncompressed image data in OW format + * and local byte order + * @param length of the pixel data field in bytes + * @param dataset pointer to dataset containing image pixel module + * @param djrp representation parameter + * @param pixSeq pixel sequence to write to + * @param djcp codec parameter + * @param compressionRatio compression ratio returned upon success + * @return EC_Normal if successful, an error code otherwise. + */ + OFCondition losslessRawEncode( + const Uint16 *pixelData, + const Uint32 length, + DcmItem *dataset, + const DJLSRepresentationParameter *djrp, + DcmPixelSequence * & pixSeq, + const DJLSCodecParameter *djcp, + double& compressionRatio) const; + + /** lossless encoder that moves Overlays to (60xx,3000) and only + * compresses the stored bits of the pixel cell. + * @param pixelData pointer to the uncompressed image data in OW format + * and local byte order + * @param length of the pixel data field in bytes + * @param dataset pointer to dataset containing image pixel module + * @param djrp representation parameter + * @param pixSeq pixel sequence to write to + * @param djcp codec parameter + * @param compressionRatio compression ratio returned upon success + * @param nearLosslessDeviation maximum deviation for near-lossless encoding + * @return EC_Normal if successful, an error code otherwise. + */ + OFCondition losslessCookedEncode( + const Uint16 * pixelData, + const Uint32 length, + DcmItem *dataset, + const DJLSRepresentationParameter *djrp, + DcmPixelSequence * & pixSeq, + const DJLSCodecParameter *djcp, + double& compressionRatio, + Uint16 nearLosslessDeviation) const; + + /** for all overlay groups create (60xx,3000) Overlay Data. + * @param dataset dataset to be modified + * @param image DicomImage object for this dataset + * @return EC_Normal if successful, an error code otherwise + */ + OFCondition adjustOverlays( + DcmItem *dataset, + DicomImage& image) const; + + /** create Lossy Image Compression and Lossy Image Compression Ratio. + * @param dataset dataset to be modified + * @param ratio image compression ratio > 1. This is the real effective ratio + * between compressed and uncompressed image, + * i. e. 30 means a 30:1 lossy compression. + * @return EC_Normal if successful, an error code otherwise + */ + OFCondition updateLossyCompressionRatio( + DcmItem *dataset, + double ratio) const; + + /** create Derivation Description. + * @param dataset dataset to be modified + * @param djrp representation parameter passed to encode() + * @param ratio image compression ratio > 1. This is the real effective ratio + * between compressed and uncompressed image, + * i. e. 30 means a 30:1 lossy compression. + * @return EC_Normal if successful, an error code otherwise + */ + OFCondition updateDerivationDescription( + DcmItem *dataset, + const DJLSRepresentationParameter *djrp, + double ratio) const; + + /** perform the lossless raw compression of a single frame + * @param framePointer pointer to start of frame + * @param bitsAllocated number of bits allocated per pixel + * @param columns frame width + * @param rows frame height + * @param samplesPerPixel image samples per pixel + * @param planarConfiguration image planar configuration + * @param photometricInterpretation photometric interpretation of the DICOM dataset + * @param pixelSequence object in which the compressed frame is stored + * @param offsetList list of frame offsets updated in this parameter + * @param compressedSize size of compressed frame returned in this parameter + * @param djcp parameters for the codec + * @return EC_Normal if successful, an error code otherwise + */ + OFCondition compressRawFrame( + const Uint8 *framePointer, + Uint16 bitsAllocated, + Uint16 columns, + Uint16 rows, + Uint16 samplesPerPixel, + Uint16 planarConfiguration, + const OFString& photometricInterpretation, + DcmPixelSequence *pixelSequence, + DcmOffsetList &offsetList, + unsigned long &compressedSize, + const DJLSCodecParameter *djcp) const; + + /** perform the lossless cooked compression of a single frame + * @param pixelSequence object in which the compressed frame is stored + * @param dimage DicomImage instance used to process frame + * @param photometricInterpretation photometric interpretation of the DICOM dataset + * @param offsetList list of frame offsets updated in this parameter + * @param compressedSize size of compressed frame returned in this parameter + * @param djcp parameters for the codec + * @param frame frame index + * @param nearLosslessDeviation maximum deviation for near-lossless encoding + * @return EC_Normal if successful, an error code otherwise + */ + OFCondition compressCookedFrame( + DcmPixelSequence *pixelSequence, + DicomImage *dimage, + const OFString& photometricInterpretation, + DcmOffsetList &offsetList, + unsigned long &compressedSize, + const DJLSCodecParameter *djcp, + Uint32 frame, + Uint16 nearLosslessDeviation) const; + + /** Convert an image from sample interleaved to uninterleaved. + * @param target A buffer where the converted image will be stored + * @param source The image buffer to be converted + * @param components Color components used in the image + * @param width The width of the image + * @param height The height of the image + * @param bitsAllocated The number of bits allocated in the image. + * @return EC_Normal if succesful, an error code otherwise + */ + OFCondition convertToUninterleaved( + Uint8 *target, + const Uint8 *source, + Uint16 components, + Uint32 width, + Uint32 height, + Uint16 bitsAllocated) const; + + /** Convert an image from uninterleaved to sample interleaved. + * @param target A buffer where the converted image will be stored + * @param source The image buffer to be converted + * @param components Color components used in the image + * @param width The width of the image. + * @param height The height of the image. + * @param bitsAllocated The number of bits allocated in the image. + * @return EC_Normal if succesful, an error code otherwise + */ + OFCondition convertToSampleInterleaved( + Uint8 *target, + const Uint8 *source, + Uint16 components, + Uint32 width, + Uint32 height, + Uint16 bitsAllocated) const; +}; + + +/** codec class for JPEG-LS lossless only TS encoding + */ +class DCMTK_DCMJPLS_EXPORT DJLSLosslessEncoder : public DJLSEncoderBase +{ + /** returns the transfer syntax that this particular codec + * is able to encode + * @return supported transfer syntax + */ + virtual E_TransferSyntax supportedTransferSyntax() const; +}; + +/** codec class for JPEG-LS lossy and lossless TS encoding + */ +class DCMTK_DCMJPLS_EXPORT DJLSNearLosslessEncoder : public DJLSEncoderBase +{ + /** returns the transfer syntax that this particular codec + * is able to encode + * @return supported transfer syntax + */ + virtual E_TransferSyntax supportedTransferSyntax() const; +}; + +#endif diff --git a/dcmjpls/include/dcmtk/dcmjpls/djcparam.h b/dcmjpls/include/dcmtk/dcmjpls/djcparam.h new file mode 100644 index 00000000..be5eb9c6 --- /dev/null +++ b/dcmjpls/include/dcmtk/dcmjpls/djcparam.h @@ -0,0 +1,278 @@ +/* + * + * Copyright (C) 1997-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmjpls + * + * Author: Martin Willkomm, Uli Schlachter + * + * Purpose: codec parameter class JPEG-LS codecs + * + */ + +#ifndef DCMJPLS_DJCPARAM_H +#define DCMJPLS_DJCPARAM_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmdata/dccodec.h" /* for DcmCodecParameter */ +#include "dcmtk/dcmjpls/djlsutil.h" /* for enums */ + +/** codec parameter for JPEG-LS codecs + */ +class DCMTK_DCMJPLS_EXPORT DJLSCodecParameter: public DcmCodecParameter +{ +public: + + /** Constants describing the interleave mode which the encoder will use + */ + enum interleaveMode + { + /// Use same interleave mode as the DICOM header says in planarConfiguration, + /// if possible. The cooked encoder will force interleaveLine. + interleaveDefault, + /// Sample-interleaved (color-by-pixel) + interleaveSample, + /// Line-interleaved (color-by-line) + interleaveLine, + /// Uninterleaved (color-by-plane) + interleaveNone + }; + + /** constructor, for use with encoders. + * @param jpls_optionsEnabled enable/disable use of all five JPEG-LS parameters + * @param jpls_t1 JPEG-LS parameter "Threshold 1" (used for quantization) + * @param jpls_t2 JPEG-LS parameter "Threshold 2" + * @param jpls_t3 JPEG-LS parameter "Threshold 3" + * @param jpls_reset JPEG-LS parameter "RESET", i.e., value at which the counters A, B, and N are halved. + * @param jpls_limit JPEG-LS parameter "LIMIT" + * @param preferCookedEncoding true if the "cooked" lossless encoder should be preferred over the "raw" one + * @param fragmentSize maximum fragment size (in kbytes) for compression, 0 for unlimited. + * @param createOffsetTable create offset table during image compression + * @param uidCreation mode for SOP Instance UID creation + * @param convertToSC flag indicating whether image should be converted to Secondary Capture upon compression + * @param planarConfiguration flag describing how planar configuration of decompressed color images should be handled + * @param ignoreOffsetTable flag indicating whether to ignore the offset table when decompressing multiframe images + * @param jplsInterleaveMode flag describing which interleave the JPEG-LS datastream should use + */ + DJLSCodecParameter( + OFBool jpls_optionsEnabled, + Uint16 jpls_t1 = 3, // these are the defaults for 8bpp in lossless mode + Uint16 jpls_t2 = 7, + Uint16 jpls_t3 = 21, + Uint16 jpls_reset = 64, + Uint16 jpls_limit = 0, + OFBool preferCookedEncoding = OFTrue, + Uint32 fragmentSize = 0, + OFBool createOffsetTable = OFTrue, + JLS_UIDCreation uidCreation = EJLSUC_default, + OFBool convertToSC = OFFalse, + JLS_PlanarConfiguration planarConfiguration = EJLSPC_restore, + OFBool ignoreOffsetTable = OFFalse, + interleaveMode jplsInterleaveMode = interleaveLine); + + /** constructor, for use with decoders. Initializes all encoder options to defaults. + * @param uidCreation mode for SOP Instance UID creation (used both for encoding and decoding) + * @param planarConfiguration flag describing how planar configuration of decompressed color images should be handled + * @param ignoreOffsetTable flag indicating whether to ignore the offset table when decompressing multiframe images + */ + DJLSCodecParameter( + JLS_UIDCreation uidCreation = EJLSUC_default, + JLS_PlanarConfiguration planarConfiguration = EJLSPC_restore, + OFBool ignoreOffsetTable = OFFalse); + + /// copy constructor + DJLSCodecParameter(const DJLSCodecParameter& arg); + + /// destructor + virtual ~DJLSCodecParameter(); + + /** this methods creates a copy of type DcmCodecParameter * + * it must be overweritten in every subclass. + * @return copy of this object + */ + virtual DcmCodecParameter *clone() const; + + /** returns the class name as string. + * can be used as poor man's RTTI replacement. + */ + virtual const char *className() const; + + /** returns secondary capture conversion flag + * @return secondary capture conversion flag + */ + OFBool getConvertToSC() const + { + return convertToSC_; + } + + /** returns create offset table flag + * @return create offset table flag + */ + OFBool getCreateOffsetTable() const + { + return createOffsetTable_; + } + + /** returns mode for SOP Instance UID creation + * @return mode for SOP Instance UID creation + */ + JLS_UIDCreation getUIDCreation() const + { + return uidCreation_; + } + + /** returns mode for handling planar configuration + * @return mode for handling planar configuration + */ + JLS_PlanarConfiguration getPlanarConfiguration() const + { + return planarConfiguration_; + } + + /** returns flag indicating whether or not the "cooked" lossless encoder + * should be preferred over the "raw" one + * @return raw/cooked lossless encoding flag + */ + OFBool cookedEncodingPreferred() const + { + return preferCookedEncoding_; + } + + /** returns maximum fragment size (in kbytes) for compression, 0 for unlimited. + * @return maximum fragment size for compression + */ + Uint32 getFragmentSize() const + { + return fragmentSize_; + } + + /** returns JPEG-LS parameter T1 + * @return JPEG-LS parameter T1 + */ + Uint16 getT1() const + { + return jpls_t1_; + } + + /** returns JPEG-LS parameter T2 + * @return JPEG-LS parameter T2 + */ + Uint16 getT2() const + { + return jpls_t2_; + } + + /** returns JPEG-LS parameter T3 + * @return JPEG-LS parameter T3 + */ + Uint16 getT3() const + { + return jpls_t3_; + } + + /** returns JPEG-LS parameter RESET + * @return JPEG-LS parameter RESET + */ + Uint16 getReset() const + { + return jpls_reset_; + } + + /** returns JPEG-LS parameter LIMIT + * @return JPEG-LS parameter LIMIT + */ + Uint16 getLimit() const + { + return jpls_t1_; + } + + /** returns true if JPEG-LS parameters T1-T3, RESET and LIMIT are enabled, false otherwise + * @return true if JPEG-LS parameters T1-T3, RESET and LIMIT are enabled, false otherwise + */ + OFBool getUseCustomOptions() const + { + return jpls_optionsEnabled_; + } + + /** returns true if the offset table should be ignored when decompressing multiframe images + * @return true if the offset table should be ignored when decompressing multiframe images + */ + OFBool ignoreOffsetTable() const + { + return ignoreOffsetTable_; + } + + /** returns the interleave mode which the encoder should use + * @return the interleave mode which the encoder should use + */ + interleaveMode getJplsInterleaveMode() const + { + return jplsInterleaveMode_; + } + +private: + + /// private undefined copy assignment operator + DJLSCodecParameter& operator=(const DJLSCodecParameter&); + + // **************************************************** + // **** Parameters describing the encoding process **** + + /// enable/disable use of all five JPEG-LS parameters + OFBool jpls_optionsEnabled_; + + /// JPEG-LS parameter "Threshold 1" (used for quantization) + Uint16 jpls_t1_; + + /// JPEG-LS parameter "Threshold 2" + Uint16 jpls_t2_; + + /// JPEG-LS parameter "Threshold 3" + Uint16 jpls_t3_; + + /// JPEG-LS parameter "RESET", i.e., value at which the counters A, B, and N are halved. + Uint16 jpls_reset_; + + /// JPEG-LS parameter "LIMIT" + Uint16 jpls_limit_; + + /// maximum fragment size (in kbytes) for compression, 0 for unlimited. + Uint32 fragmentSize_; + + /// create offset table during image compression + OFBool createOffsetTable_; + + /// Flag indicating if the "cooked" lossless encoder should be preferred over the "raw" one + OFBool preferCookedEncoding_; + + /// mode for SOP Instance UID creation (used both for encoding and decoding) + JLS_UIDCreation uidCreation_; + + /// flag indicating whether image should be converted to Secondary Capture upon compression + OFBool convertToSC_; + + /// Flag describing the interleave mode which the encoder will use + interleaveMode jplsInterleaveMode_; + + // **************************************************** + // **** Parameters describing the decoding process **** + + /// flag describing how planar configuration of decompressed color images should be handled + JLS_PlanarConfiguration planarConfiguration_; + + /// flag indicating if temporary files should be kept, false if they should be deleted after use + OFBool ignoreOffsetTable_; + +}; + + +#endif diff --git a/dcmjpls/include/dcmtk/dcmjpls/djdecode.h b/dcmjpls/include/dcmtk/dcmjpls/djdecode.h new file mode 100644 index 00000000..6b62fd7e --- /dev/null +++ b/dcmjpls/include/dcmtk/dcmjpls/djdecode.h @@ -0,0 +1,82 @@ +/* + * + * Copyright (C) 1997-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmjpls + * + * Author: Martin Willkomm + * + * Purpose: singleton class that registers the decoder for all supported JPEG-LS processes. + * + */ + +#ifndef DCMJPLS_DJDECODE_H +#define DCMJPLS_DJDECODE_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/ofstd/oftypes.h" /* for OFBool */ +#include "dcmtk/dcmjpls/djlsutil.h" /* for enums */ + +class DJLSCodecParameter; +class DJLSLosslessDecoder; +class DJLSNearLosslessDecoder; + +/** singleton class that registers decoders for all supported JPEG-LS processes. + */ +class DCMTK_DCMJPLS_EXPORT DJLSDecoderRegistration +{ +public: + + /** registers decoder for all supported JPEG-LS processes. + * If already registered, call is ignored unless cleanup() has + * been performed before. + * @param uidcreation flag indicating whether or not + * a new SOP Instance UID should be assigned upon decompression. + * @param planarconfig flag indicating how planar configuration + * of color images should be encoded upon decompression. + * @param ignoreOffsetTable flag indicating whether to ignore the offset table when decompressing multiframe images + */ + static void registerCodecs( + JLS_UIDCreation uidcreation = EJLSUC_default, + JLS_PlanarConfiguration planarconfig = EJLSPC_restore, + OFBool ignoreOffsetTable = OFFalse); + + /** deregisters decoders. + * Attention: Must not be called while other threads might still use + * the registered codecs, e.g. because they are currently decoding + * DICOM data sets through dcmdata. + */ + static void cleanup(); + + /** get version information of the CharLS library. + * Typical output format: "CharLS, Revision 55020 (modified)" + * @return name and version number of the CharLS library + */ + static OFString getLibraryVersionString(); + +private: + + /// flag indicating whether the decoders are already registered. + static OFBool registered_; + + /// pointer to codec parameter shared by all decoders + static DJLSCodecParameter *cp_; + + /// pointer to losslessdecoder + static DJLSLosslessDecoder *losslessdecoder_; + + /// pointer to near-lossless encoder + static DJLSNearLosslessDecoder *nearlosslessdecoder_; + +}; + +#endif diff --git a/dcmjpls/include/dcmtk/dcmjpls/djencode.h b/dcmjpls/include/dcmtk/dcmjpls/djencode.h new file mode 100644 index 00000000..6db8537a --- /dev/null +++ b/dcmjpls/include/dcmtk/dcmjpls/djencode.h @@ -0,0 +1,100 @@ +/* + * + * Copyright (C) 1997-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmjpls + * + * Author: Martin Willkomm, Uli Schlachter + * + * Purpose: singleton class that registers encoders for all supported JPEG-LS processes. + * + */ + +#ifndef DCMJPLS_DJENCODE_H +#define DCMJPLS_DJENCODE_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/ofstd/oftypes.h" /* for OFBool */ +#include "dcmtk/dcmjpls/djlsutil.h" +#include "dcmtk/dcmdata/dctypes.h" /* for Uint32 */ +#include "dcmtk/dcmjpls/djcparam.h" /* for class DJLSCodecParameter */ + +class DJLSCodecParameter; +class DJLSLosslessEncoder; +class DJLSNearLosslessEncoder; + +/** singleton class that registers encoders for all supported JPEG-LS processes. + */ +class DCMTK_DCMJPLS_EXPORT DJLSEncoderRegistration +{ +public: + + /** registers encoders for all supported JPEG-LS processes. + * If already registered, call is ignored unless cleanup() has + * been performed before. + * @param jpls_optionsEnabled enable/disable use of all five JPEG-LS parameters + * @param jpls_t1 JPEG-LS parameter "Threshold 1" (used for quantization) + * @param jpls_t2 JPEG-LS parameter "Threshold 2" + * @param jpls_t3 JPEG-LS parameter "Threshold 3" + * @param jpls_reset JPEG-LS parameter "RESET", i.e., value at which the counters A, B, and N are halved. + * @param jpls_limit JPEG-LS parameter "LIMIT" + * @param preferCookedEncoding true if the "cooked" lossless encoder should be preferred over the "raw" one + * @param fragmentSize maximum fragment size (in kbytes) for compression, 0 for unlimited. + * @param createOffsetTable create offset table during image compression + * @param uidCreation mode for SOP Instance UID creation + * @param convertToSC flag indicating whether image should be converted to Secondary Capture upon compression + * @param jplsInterleaveMode flag describing which interleave the JPEG-LS datastream should use + */ + static void registerCodecs( + OFBool jpls_optionsEnabled = OFFalse, + Uint16 jpls_t1 = 3, + Uint16 jpls_t2 = 7, + Uint16 jpls_t3 = 21, + Uint16 jpls_reset = 64, + Uint16 jpls_limit = 0, + OFBool preferCookedEncoding = OFTrue, + Uint32 fragmentSize = 0, + OFBool createOffsetTable = OFTrue, + JLS_UIDCreation uidCreation = EJLSUC_default, + OFBool convertToSC = OFFalse, + DJLSCodecParameter::interleaveMode jplsInterleaveMode = DJLSCodecParameter::interleaveDefault); + + /** deregisters encoders. + * Attention: Must not be called while other threads might still use + * the registered codecs, e.g. because they are currently encoding + * DICOM data sets through dcmdata. + */ + static void cleanup(); + + /** get version information of the CharLS library. + * Typical output format: "CharLS, Revision 55020 (modified)" + * @return name and version number of the CharLS library + */ + static OFString getLibraryVersionString(); + +private: + + /// flag indicating whether the encoders are already registered. + static OFBool registered_; + + /// pointer to codec parameter shared by all encoders + static DJLSCodecParameter *cp_; + + /// pointer to encoder for lossless JPEG-LS + static DJLSLosslessEncoder *losslessencoder_; + + /// pointer to encoder for lossy JPEG-LS + static DJLSNearLosslessEncoder *nearlosslessencoder_; + +}; + +#endif diff --git a/dcmjpls/include/dcmtk/dcmjpls/djlsutil.h b/dcmjpls/include/dcmtk/dcmjpls/djlsutil.h new file mode 100644 index 00000000..92f67e99 --- /dev/null +++ b/dcmjpls/include/dcmtk/dcmjpls/djlsutil.h @@ -0,0 +1,158 @@ +/* + * + * Copyright (C) 1997-2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmjpls + * + * Author: Martin Willkomm, Uli Schlachter + * + * Purpose: enumerations, error constants and helper functions for dcmjpls + * + */ + +#ifndef DCMJPLS_DJLSUTILS_H +#define DCMJPLS_DJLSUTILS_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/ofstd/ofcond.h" /* for class OFCondition */ +#include "dcmtk/oflog/oflog.h" +#include "dcmtk/dcmjpls/dldefine.h" + + +#define DCMJPLS_CHARLS_VERSION_STRING "CharLS, Version 1.0 (modified)" + + +// global definitions for logging mechanism provided by the oflog module + +extern DCMTK_DCMJPLS_EXPORT OFLogger DCM_dcmjplsLogger; + +#define DCMJPLS_TRACE(msg) OFLOG_TRACE(DCM_dcmjplsLogger, msg) +#define DCMJPLS_DEBUG(msg) OFLOG_DEBUG(DCM_dcmjplsLogger, msg) +#define DCMJPLS_INFO(msg) OFLOG_INFO(DCM_dcmjplsLogger, msg) +#define DCMJPLS_WARN(msg) OFLOG_WARN(DCM_dcmjplsLogger, msg) +#define DCMJPLS_ERROR(msg) OFLOG_ERROR(DCM_dcmjplsLogger, msg) +#define DCMJPLS_FATAL(msg) OFLOG_FATAL(DCM_dcmjplsLogger, msg) + + +// include this file in doxygen documentation + +/** @file djlsutil.h + * @brief enumerations, error constants and helper functions for the dcmjpls module + */ + + +/** describes the condition under which a compressed or decompressed image + * receives a new SOP instance UID. + */ +enum JLS_UIDCreation +{ + /** Upon compression, assign new SOP instance UID if compression is lossy. + * Upon decompression never assign new SOP instance UID. + */ + EJLSUC_default, + + /// always assign new SOP instance UID on compression and decompression + EJLSUC_always, + + /// never assign new SOP instance UID + EJLSUC_never +}; + +/** describes how the decoder should handle planar configuration of + * decompressed color images. + */ +enum JLS_PlanarConfiguration +{ + /// restore planar configuration as indicated in data set + EJLSPC_restore, + + /** automatically determine whether color-by-plane is required from + * the SOP Class UID and decompressed photometric interpretation + */ + EJLSPC_auto, + + /// always create color-by-pixel planar configuration + EJLSPC_colorByPixel, + + /// always create color-by-plane planar configuration + EJLSPC_colorByPlane +}; + +/** describes how the encoder handles the image bit depth + * upon lossy compression. + */ +enum JLS_CompressionBitDepth +{ + /// keep original bit depth + EJLSBD_original, + + /** limit bit depth to a certain value, i.e. scale down + * if the original image bit depth is larger + */ + EJLSBD_limit, + + /** force bit depth to a certain value, i.e. scale up + * or scale down the original image to match the given + * bit depth. + */ + EJLSBD_force +}; + + +// CONDITION CONSTANTS + +/// error condition constant: Too small buffer used for image data (internal error) +extern DCMTK_DCMJPLS_EXPORT const OFConditionConst EC_JLSUncompressedBufferTooSmall; + +/// error condition constant: Too small buffer used for compressed image data (internal error) +extern DCMTK_DCMJPLS_EXPORT const OFConditionConst EC_JLSCompressedBufferTooSmall; + +/// error condition constant: The image uses some features which the codec does not support +extern DCMTK_DCMJPLS_EXPORT const OFConditionConst EC_JLSCodecUnsupportedImageType; + +/// error condition constant: The codec was fed with invalid parameters (e.g. height = -1) +extern DCMTK_DCMJPLS_EXPORT const OFConditionConst EC_JLSCodecInvalidParameters; + +/// error condition constant: The codec was fed with unsupported parameters (e.g. 32 bit per sample) +extern DCMTK_DCMJPLS_EXPORT const OFConditionConst EC_JLSCodecUnsupportedValue; + +/// error condition constant: The compressed image is invalid +extern DCMTK_DCMJPLS_EXPORT const OFConditionConst EC_JLSInvalidCompressedData; + +/// error condition constant: The images' color transformation is not supported in this bit depth +extern DCMTK_DCMJPLS_EXPORT const OFConditionConst EC_JLSUnsupportedBitDepthForTransform; + +/// error condition constant: The images' color transformation is not supported +extern DCMTK_DCMJPLS_EXPORT const OFConditionConst EC_JLSUnsupportedColorTransform; + +/// error condition constant: Unsupported bit depth in JPEG-LS transfer syntax +extern DCMTK_DCMJPLS_EXPORT const OFConditionConst EC_JLSUnsupportedBitDepth; + +/// error condition constant: Cannot compute number of fragments for JPEG-LS frame +extern DCMTK_DCMJPLS_EXPORT const OFConditionConst EC_JLSCannotComputeNumberOfFragments; + +/// error condition constant: Image data mismatch between DICOM header and JPEG-LS bitstream +extern DCMTK_DCMJPLS_EXPORT const OFConditionConst EC_JLSImageDataMismatch; + +/// error condition constant: Unsupported photometric interpretation for near-lossless JPEG-LS compression +extern DCMTK_DCMJPLS_EXPORT const OFConditionConst EC_JLSUnsupportedPhotometricInterpretation; + +/// error condition constant: Unsupported pixel representation for near-lossless JPEG-LS compression +extern DCMTK_DCMJPLS_EXPORT const OFConditionConst EC_JLSUnsupportedPixelRepresentation; + +/// error condition constant: Unsupported type of image for JPEG-LS compression +extern DCMTK_DCMJPLS_EXPORT const OFConditionConst EC_JLSUnsupportedImageType; + +/// error condition constant: Trailing data after image +extern DCMTK_DCMJPLS_EXPORT const OFConditionConst EC_JLSTooMuchCompressedData; + +#endif diff --git a/dcmjpls/include/dcmtk/dcmjpls/djrparam.h b/dcmjpls/include/dcmtk/dcmjpls/djrparam.h new file mode 100644 index 00000000..906a79c8 --- /dev/null +++ b/dcmjpls/include/dcmtk/dcmjpls/djrparam.h @@ -0,0 +1,97 @@ +/* + * + * Copyright (C) 1997-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmjpls + * + * Author: Martin Willkomm + * + * Purpose: representation parameters for JPEG-LS + * + */ + +#ifndef DCMJPLS_DJRPARAM_H +#define DCMJPLS_DJRPARAM_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmdata/dcpixel.h" /* for class DcmRepresentationParameter */ +#include "dcmtk/dcmjpls/dldefine.h" + +/** representation parameter for JPEG-LS + */ +class DCMTK_DCMJPLS_EXPORT DJLSRepresentationParameter: public DcmRepresentationParameter +{ +public: + + /** constructor + * @param nearlosslessDeviation used as parameter NEAR in JPEG-LS nearlossless-encoding process + * @param losslessProcess true if lossless process is requested + */ + DJLSRepresentationParameter( + Uint16 nearlosslessDeviation = 2, + OFBool losslessProcess = OFTrue); + + /// copy constructor + DJLSRepresentationParameter(const DJLSRepresentationParameter& arg); + + /// destructor + virtual ~DJLSRepresentationParameter(); + + /** this methods creates a copy of type DcmRepresentationParameter * + * it must be overweritten in every subclass. + * @return copy of this object + */ + virtual DcmRepresentationParameter *clone() const; + + /** returns the class name as string. + * can be used in operator== as poor man's RTTI replacement. + */ + virtual const char *className() const; + + /** compares an object to another DcmRepresentationParameter. + * Implementation must make sure that classes are comparable. + * @param arg representation parameter to compare with + * @return true if equal, false otherwise. + */ + virtual OFBool operator==(const DcmRepresentationParameter &arg) const; + + /** returns the desired NEAR parameter + * @return return desired NEAR-Parameter + */ + Uint16 getnearlosslessDeviation() const + { + return nearlosslessDeviation_; + } + + /** returns true if lossless compression is desired + * @return true if lossless compression is desired + */ + OFBool useLosslessProcess() const + { + return losslessProcess_; + } + +private: + + /** desired NEAR parameter + * Default is 0 (lossless compression). + * Ignored during lossless compression. + */ + Uint16 nearlosslessDeviation_; + + /// true if lossless process should be used even in lossy transfer syntax + OFBool losslessProcess_; + +}; + + +#endif diff --git a/dcmjpls/include/dcmtk/dcmjpls/dldefine.h b/dcmjpls/include/dcmtk/dcmjpls/dldefine.h new file mode 100644 index 00000000..7ec9f034 --- /dev/null +++ b/dcmjpls/include/dcmtk/dcmjpls/dldefine.h @@ -0,0 +1,38 @@ +/* + * + * Copyright (C) 2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmjpls + * + * Author: Uli Schlachter + * + * Purpose: Contains preprocessor definitions + * + */ + + +#ifndef DLDEFINE_H +#define DLDEFINE_H + +#include "dcmtk/config/osconfig.h" + +#include "dcmtk/ofstd/ofdefine.h" + + +#ifdef dcmjpls_EXPORTS +#define DCMTK_DCMJPLS_EXPORT DCMTK_DECL_EXPORT +#else +#define DCMTK_DCMJPLS_EXPORT DCMTK_DECL_IMPORT +#endif + + +#endif diff --git a/dcmjpls/libcharls/CMakeLists.txt b/dcmjpls/libcharls/CMakeLists.txt new file mode 100644 index 00000000..99371f70 --- /dev/null +++ b/dcmjpls/libcharls/CMakeLists.txt @@ -0,0 +1,5 @@ +# declare additional include directories +INCLUDE_DIRECTORIES(${dcmjpls_SOURCE_DIR}/libcharls ${ofstd_SOURCE_DIR}/include) + +# create library from source files +DCMTK_ADD_LIBRARY(charls header intrface jpegls) diff --git a/dcmjpls/libcharls/Makefile.dep b/dcmjpls/libcharls/Makefile.dep new file mode 100644 index 00000000..09b842d6 --- /dev/null +++ b/dcmjpls/libcharls/Makefile.dep @@ -0,0 +1,45 @@ +header.o: header.cc config.h util.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../config/include/dcmtk/config/osconfig.h pubtypes.h header.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h streams.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofbmanip.h decodstr.h procline.h \ + clrtrans.h encodstr.h +intrface.o: intrface.cc config.h util.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../config/include/dcmtk/config/osconfig.h pubtypes.h intrface.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h header.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h streams.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../ofstd/include/dcmtk/ofstd/ofbmanip.h +jpegls.o: jpegls.cc config.h util.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../config/include/dcmtk/config/osconfig.h pubtypes.h streams.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofbmanip.h header.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h decodstr.h procline.h \ + clrtrans.h encodstr.h context.h ctxtrmod.h lokuptbl.h lltraits.h \ + deftrait.h scan.h ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h diff --git a/dcmjpls/libcharls/Makefile.in b/dcmjpls/libcharls/Makefile.in new file mode 100644 index 00000000..d26877c4 --- /dev/null +++ b/dcmjpls/libcharls/Makefile.in @@ -0,0 +1,45 @@ +# +# Makefile for dcmjpls/libcharls +# + +@SET_MAKE@ + +SHELL = /bin/sh +VPATH = @srcdir@:@top_srcdir@/include:@top_srcdir@/@configdir@/include +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +configdir = @top_srcdir@/@configdir@ + +include $(configdir)/@common_makefile@ + +ofstddir = $(top_srcdir)/../ofstd + +LOCALINCLUDES = -I$(ofstddir)/include +LOCALDEFS = + +objs = header.o intrface.o jpegls.o + +library = libcharls.$(LIBEXT) + +all: $(library) + +install: all + $(configdir)/mkinstalldirs $(DESTDIR)$(libdir) + $(INSTALL_DATA) $(library) $(DESTDIR)$(libdir)/$(library) + $(RANLIB) $(DESTDIR)$(libdir)/$(library) + +$(library): $(objs) + $(AR) $(ARFLAGS) $@ $(objs) + $(RANLIB) $@ + +clean: + rm -f $(objs) $(library) $(TRASH) + +distclean: + rm -f $(objs) $(library) $(DISTTRASH) + + +dependencies: + $(CC) -MM $(defines) $(includes) $(CPPFLAGS) $(CXXFLAGS) *.cc > $(DEP) + +include $(DEP) diff --git a/dcmjpls/libcharls/clrtrans.h b/dcmjpls/libcharls/clrtrans.h new file mode 100644 index 00000000..548e9935 --- /dev/null +++ b/dcmjpls/libcharls/clrtrans.h @@ -0,0 +1,180 @@ +// +// (C) Jan de Vaan 2007-2010, all rights reserved. See the accompanying "License.txt" for licensed use. +// +#ifndef CHARLS_COLORTRANSFORM +#define CHARLS_COLORTRANSFORM + +// +// This file defines simple classes that define (lossless) color transforms. +// They are invoked in processline.h to convert between decoded values and the internal line buffers. +// Color transforms work best for computer generated images. +// + +template +struct TransformNoneImpl +{ + typedef sample SAMPLE; + + inlinehint Triplet operator() (int v1, int v2, int v3) + { return Triplet(v1, v2, v3); } +}; + + +template +struct TransformNone : public TransformNoneImpl +{ + typedef struct TransformNoneImpl INVERSE; +}; + + + +template +struct TransformHp1 +{ + enum { RANGE = 1 << sizeof(sample)*8 }; + typedef sample SAMPLE; + + struct INVERSE + { + INVERSE(const TransformHp1&) {}; + + inlinehint Triplet operator() (int v1, int v2, int v3) + { return Triplet(v1 + v2 - RANGE/2, v2, v3 + v2 - RANGE/2); } + }; + + inlinehint Triplet operator() (int R, int G, int B) + { + Triplet hp1; + hp1.v2 = SAMPLE(G); + hp1.v1 = SAMPLE(R - G + RANGE/2); + hp1.v3 = SAMPLE(B - G + RANGE/2); + return hp1; + } +}; + + + + + +template +struct TransformHp2 +{ + enum { RANGE = 1 << sizeof(sample)*8 }; + typedef sample SAMPLE; + + struct INVERSE + { + INVERSE(const TransformHp2&) {}; + + inlinehint Triplet operator() (int v1, int v2, int v3) + { + Triplet rgb; + rgb.R = SAMPLE(v1 + v2 - RANGE/2); // new R + rgb.G = SAMPLE(v2); // new G + rgb.B = SAMPLE(v3 + ((rgb.R + rgb.G) >> 1) - RANGE/2); // new B + return rgb; + } + }; + + inlinehint Triplet operator() (int R, int G, int B) + { + return Triplet(R - G + RANGE/2, G, B - ((R+G )>>1) - RANGE/2); + } + + +}; + + + +template +struct TransformHp3 +{ + enum { RANGE = 1 << sizeof(sample)*8 }; + typedef sample SAMPLE; + + struct INVERSE + { + INVERSE(const TransformHp3&) {}; + + inlinehint Triplet operator() (int v1, int v2, int v3) + { + int G = v1 - ((v3 + v2)>>2) + RANGE/4; + Triplet rgb; + rgb.R = SAMPLE(v3 + G - RANGE/2); // new R + rgb.G = SAMPLE(G); // new G + rgb.B = SAMPLE(v2 + G - RANGE/2); // new B + return rgb; + } + }; + + inlinehint Triplet operator() (int R, int G, int B) + { + Triplet hp3; + hp3.v2 = SAMPLE(B - G + RANGE/2); + hp3.v3 = SAMPLE(R - G + RANGE/2); + hp3.v1 = SAMPLE(G + ((hp3.v2 + hp3.v3)>>2)) - RANGE/4; + return hp3; + } +}; + + +// Transform class that shifts bits towards the high bit when bitcount is not 8 or 16 +// needed to make the HP color transforms work correctly. + +template +struct TransformShifted +{ + typedef typename TRANSFORM::SAMPLE SAMPLE; + + struct INVERSE + { + INVERSE(const TransformShifted& transform) : + _shift(transform._shift), + _inverseTransform(transform._colortransform) + {} + + inlinehint Triplet operator() (int v1, int v2, int v3) + { + Triplet result = _inverseTransform(v1 << _shift, v2 << _shift, v3 << _shift); + + return Triplet(result.R >> _shift, result.G >> _shift, result.B >> _shift); + } + + inlinehint Quad operator() (int v1, int v2, int v3, int v4) + { + Triplet result = _inverseTransform(v1 << _shift, v2 << _shift, v3 << _shift); + + return Quad(result.R >> _shift, result.G >> _shift, result.B >> _shift, v4); + } + + int _shift; + typename TRANSFORM::INVERSE _inverseTransform; + }; + + + TransformShifted(int shift) : + _shift(shift) + { + } + + inlinehint Triplet operator() (int R, int G, int B) + { + Triplet result = _colortransform(R << _shift, G << _shift, B << _shift); + + return Triplet(result.R >> _shift, result.G >> _shift, result.B >> _shift); + } + + inlinehint Quad operator() (int R, int G, int B, int A) + { + Triplet result = _colortransform(R << _shift, G << _shift, B << _shift); + + return Quad(result.R >> _shift, result.G >> _shift, result.B >> _shift, A); + } + + int _shift; + TRANSFORM _colortransform; +}; + + + +#endif diff --git a/dcmjpls/libcharls/config.h b/dcmjpls/libcharls/config.h new file mode 100644 index 00000000..433206c1 --- /dev/null +++ b/dcmjpls/libcharls/config.h @@ -0,0 +1,63 @@ +// +// (C) Jan de Vaan 2007-2010, all rights reserved. See the accompanying "License.txt" for licensed use. +// + + +#ifndef CHARLS_CONFIG +#define CHARLS_CONFIG + +#ifdef NDEBUG +# ifndef ASSERT +# define ASSERT(t) { } +# endif +# ifndef assert +# define assert(t) { } +# endif +#else +#define INCLUDE_CASSERT +#include "dcmtk/ofstd/ofstdinc.h" +#define ASSERT(t) assert(t) +#endif + +#if defined(_WIN32) +#ifdef _MSC_VER +#pragma warning (disable:4512) +#endif + +#endif + +// Typedef used by Charls for the default integral type. +// charls will work correctly with 64 or 32 bit. +typedef long LONG; + +enum constants +{ + LONG_BITCOUNT = sizeof(LONG)*8 +}; + + +typedef unsigned char BYTE; +typedef unsigned short USHORT; + +#undef NEAR + +#ifndef inlinehint +# ifdef _MSC_VER +# ifdef NDEBUG +# define inlinehint __forceinline +# else +# define inlinehint +# endif +# elif defined(__GNUC__) && (__GNUC__ > 3 || __GNUC__ == 3 && __GNUC_MINOR__ > 0) +# define inlinehint inline +# else +# define inlinehint inline +# endif +#endif + +#if defined(i386) || defined(__i386__) || defined(_M_IX86) || defined(__amd64__) || defined(_M_X64) +#define ARCH_HAS_UNALIGNED_MEM_ACCESS /* TODO define this symbol for more architectures */ +#endif + +#endif + diff --git a/dcmjpls/libcharls/context.h b/dcmjpls/libcharls/context.h new file mode 100644 index 00000000..e97b268a --- /dev/null +++ b/dcmjpls/libcharls/context.h @@ -0,0 +1,122 @@ +// +// (C) Jan de Vaan 2007-2010, all rights reserved. See the accompanying "License.txt" for licensed use. +// + + +#ifndef CHARLS_CONTEXT +#define CHARLS_CONTEXT + + +// +// JlsContext: a JPEG-LS context with it's current statistics. +// +struct JlsContext +{ +public: + JlsContext() + {} + + JlsContext(LONG a) : + A(a), + B(0), + C(0), + N(1) + { + } + + LONG A; + LONG B; + short C; + short N; + + inlinehint LONG GetErrorCorrection(LONG k) const + { + if (k != 0) + return 0; + + return BitWiseSign(2 * B + N - 1); + } + + + inlinehint void UpdateVariables(LONG errorValue, LONG NEAR, LONG NRESET) + { + ASSERT(N != 0); + + // For performance work on copies of A,B,N (compiler will use registers). + int b = B + errorValue * (2 * NEAR + 1); + int a = A + ABS(errorValue); + int n = N; + + ASSERT(a < 65536 * 256); + ASSERT(ABS(b) < 65536 * 256); + + if (n == NRESET) + { + a = a >> 1; + b = b >> 1; + n = n >> 1; + } + + n = n + 1; + + if (b + n <= 0) + { + b = b + n; + if (b <= -n) + { + b = -n + 1; + } + C = _tableC[C - 1]; + } + else if (b > 0) + { + b = b - n; + if (b > 0) + { + b = 0; + } + C = _tableC[C + 1]; + } + A = a; + B = b; + N = (short)n; + ASSERT(N != 0); + } + + + + inlinehint LONG GetGolomb() const + { + LONG Ntest = N; + LONG Atest = A; + LONG k = 0; + for(; (Ntest << k) < Atest; k++) + { + ASSERT(k <= 32); + }; + return k; + } + + static signed char* CreateTableC() + { + static OFVector rgtableC; + + rgtableC.reserve(256 + 2); + + rgtableC.push_back(-128); + for (int i = -128; i < 128; i++) + { + rgtableC.push_back(char(i)); + } + rgtableC.push_back(127); + + signed char* pZero = &rgtableC[128 + 1]; + ASSERT(pZero[0] == 0); + return pZero; + } +private: + + static signed char* _tableC; +}; + +#endif diff --git a/dcmjpls/libcharls/ctxtrmod.h b/dcmjpls/libcharls/ctxtrmod.h new file mode 100644 index 00000000..0eac1e01 --- /dev/null +++ b/dcmjpls/libcharls/ctxtrmod.h @@ -0,0 +1,101 @@ +// +// (C) Jan de Vaan 2007-2010, all rights reserved. See the accompanying "License.txt" for licensed use. +// + + +#ifndef CHARLS_CONTEXTRUNMODE +#define CHARLS_CONTEXTRUNMODE + +// Implements statistical modelling for the run mode context. +// Computes model dependent parameters like the golomb code lengths + +struct CContextRunMode +{ + CContextRunMode(LONG a, LONG nRItype, LONG nReset) : + A(a), + N(1), + Nn(0), + _nRItype(nRItype), + _nReset((BYTE)nReset) + { + } + + LONG A; + BYTE N; + BYTE Nn; + LONG _nRItype; + BYTE _nReset; + + CContextRunMode() + {} + + + inlinehint LONG GetGolomb() const + { + LONG Ntest = N; + LONG TEMP = A + (N >> 1) * _nRItype; + LONG k = 0; + for(; Ntest < TEMP; k++) + { + Ntest <<= 1; + ASSERT(k <= 32); + }; + return k; + } + + + void UpdateVariables(LONG Errval, LONG EMErrval) + { + if (Errval < 0) + { + Nn = Nn + 1; + } + A = A + ((EMErrval + 1 - _nRItype) >> 1); + if (N == _nReset) + { + A = A >> 1; + N = N >> 1; + Nn = Nn >> 1; + } + N = N + 1; + } + + inlinehint LONG ComputeErrVal(LONG temp, LONG k) + { + bool map = temp & 1; + + LONG errvalabs = (temp + map) / 2; + + if ((k != 0 || (2 * Nn >= N)) == map) + { + ASSERT(map == ComputeMap(-errvalabs, k)); + return -errvalabs; + } + + ASSERT(map == ComputeMap(errvalabs, k)); + return errvalabs; + } + + + bool ComputeMap(LONG Errval, LONG k) const + { + if ((k == 0) && (Errval > 0) && (2 * Nn < N)) + return 1; + + else if ((Errval < 0) && (2 * Nn >= N)) + return 1; + + else if ((Errval < 0) && (k != 0)) + return 1; + + return 0; + } + + + inlinehint LONG ComputeMapNegativeE(LONG k) const + { + return k != 0 || (2 * Nn >= N ); + } +}; + +#endif diff --git a/dcmjpls/libcharls/decodstr.h b/dcmjpls/libcharls/decodstr.h new file mode 100644 index 00000000..772af6fc --- /dev/null +++ b/dcmjpls/libcharls/decodstr.h @@ -0,0 +1,285 @@ +// +// (C) Jan de Vaan 2007-2010, all rights reserved. See the accompanying "License.txt" for licensed use. +// + +#ifndef CHARLS_DECODERSTATEGY +#define CHARLS_DECODERSTATEGY + +#include "streams.h" +#include "procline.h" +#include "config.h" +#include "util.h" + +// Implements encoding to stream of bits. In encoding mode JpegLsCodec inherits from EncoderStrategy + + + +class DecoderStrategy +{ +public: + DecoderStrategy(const JlsParameters& info) : + _info(info), + _processLine(0), + _readCache(0), + _validBits(0), + _position(0) + { + } + + virtual ~DecoderStrategy() + { + } + + virtual void SetPresets(const JlsCustomParameters& presets) = 0; + virtual size_t DecodeScan(void* outputData, const JlsRect& size, const void* compressedData, size_t byteCount, bool bCheck) = 0; + + void Init(BYTE* compressedBytes, size_t byteCount) + { + _validBits = 0; + _readCache = 0; + _position = compressedBytes; + _endPosition = compressedBytes + byteCount; + _nextFFPosition = FindNextFF(); + MakeValid(); + } + + inlinehint void Skip(LONG length) + { + _validBits -= length; + _readCache = _readCache << length; + } + + + void OnLineBegin(LONG /*cpixel*/, void* /*ptypeBuffer*/, LONG /*pixelStride*/) + {} + + + void OnLineEnd(LONG pixelCount, const void* ptypeBuffer, LONG pixelStride) + { + _processLine->NewLineDecoded(ptypeBuffer, pixelCount, pixelStride); + } + + void EndScan() + { + if ((*_position) != 0xFF) + { + ReadBit(); + + if ((*_position) != 0xFF) + throw JlsException(TooMuchCompressedData); + } + + if (_readCache != 0) + throw JlsException(TooMuchCompressedData); + } + + + inlinehint bool OptimizedRead() + { + // Easy & fast: if there is no 0xFF byte in sight, we can read without bitstuffing + if (_position < _nextFFPosition - (sizeof(bufType)-1)) + { + _readCache |= FromBigEndian::Read(_position) >> _validBits; + int bytesToRead = (bufferbits - _validBits) >> 3; + _position += bytesToRead; + _validBits += bytesToRead * 8; + ASSERT(_validBits >= bufferbits - 8); + return true; + } + return false; + } + + typedef size_t bufType; + + enum { + bufferbits = sizeof( bufType ) * 8 + }; + + void MakeValid() + { + ASSERT(_validBits <=bufferbits - 8); + + if (OptimizedRead()) + return; + + do + { + if (_position >= _endPosition) + { + if (_validBits <= 0) + throw JlsException(InvalidCompressedData); + + return; + } + + bufType valnew = _position[0]; + + if (valnew == 0xFF) + { + // JPEG bitstream rule: no FF may be followed by 0x80 or higher + if (_position == _endPosition - 1 || (_position[1] & 0x80) != 0) + { + if (_validBits <= 0) + throw JlsException(InvalidCompressedData); + + return; + } + } + + _readCache |= valnew << (bufferbits - 8 - _validBits); + _position += 1; + _validBits += 8; + + if (valnew == 0xFF) + { + _validBits--; + } + } + while (_validBits < bufferbits - 8); + + _nextFFPosition = FindNextFF(); + return; + + } + + + BYTE* FindNextFF() + { + BYTE* pbyteNextFF = _position; + + while (pbyteNextFF < _endPosition) + { + if (*pbyteNextFF == 0xFF) + { + break; + } + pbyteNextFF++; + } + + + return pbyteNextFF; + } + + + BYTE* GetCurBytePos() const + { + LONG validBits = _validBits; + BYTE* compressedBytes = _position; + + for (;;) + { + LONG cbitLast = compressedBytes[-1] == 0xFF ? 7 : 8; + + if (validBits < cbitLast ) + return compressedBytes; + + validBits -= cbitLast; + compressedBytes--; + } + } + + + inlinehint LONG ReadValue(LONG length) + { + if (_validBits < length) + { + MakeValid(); + if (_validBits < length) + throw JlsException(InvalidCompressedData); + } + + ASSERT(length != 0 && length <= _validBits); + ASSERT(length < 32); + LONG result = LONG(_readCache >> (bufferbits - length)); + Skip(length); + return result; + } + + + inlinehint LONG PeekByte() + { + if (_validBits < 8) + { + MakeValid(); + } + + return _readCache >> (bufferbits - 8); + } + + + + inlinehint bool ReadBit() + { + if (_validBits <= 0) + { + MakeValid(); + } + + bool bSet = (_readCache & (bufType(1) << (bufferbits - 1))) != 0; + Skip(1); + return bSet; + } + + + + inlinehint LONG Peek0Bits() + { + if (_validBits < 16) + { + MakeValid(); + } + bufType valTest = _readCache; + + for (LONG count = 0; count < 16; count++) + { + if ((valTest & (bufType(1) << (bufferbits - 1))) != 0) + return count; + + valTest <<= 1; + } + return -1; + } + + + + inlinehint LONG ReadHighbits() + { + LONG count = Peek0Bits(); + if (count >= 0) + { + Skip(count + 1); + return count; + } + Skip(15); + + for (LONG highbits = 15; ; highbits++) + { + if (ReadBit()) + return highbits; + } + } + + + LONG ReadLongValue(LONG length) + { + if (length <= 24) + return ReadValue(length); + + return (ReadValue(length - 24) << 24) + ReadValue(24); + } + +protected: + JlsParameters _info; + OFauto_ptr _processLine; + +private: + // decoding + bufType _readCache; + LONG _validBits; + BYTE* _position; + BYTE* _nextFFPosition; + BYTE* _endPosition; +}; + + +#endif diff --git a/dcmjpls/libcharls/deftrait.h b/dcmjpls/libcharls/deftrait.h new file mode 100644 index 00000000..d577ab21 --- /dev/null +++ b/dcmjpls/libcharls/deftrait.h @@ -0,0 +1,126 @@ +// +// (C) Jan de Vaan 2007-2010, all rights reserved. See the accompanying "License.txt" for licensed use. +// + + +#ifndef CHARLS_DEFAULTTRAITS +#define CHARLS_DEFAULTTRAITS + +// Default traits that support all JPEG LS parameters: custom limit, near, maxval (not power of 2) + +// This traits class is used to initialize a coder/decoder. +// The coder/decoder also delegates some functions to the traits class. +// This is to allow the traits class to replace the default implementation here with optimized specific implementations. +// This is done for lossless coding/decoding: see losslesstraits.h + +template +struct DefaultTraitsT +{ +public: + typedef sample SAMPLE; + typedef pixel PIXEL; + + LONG MAXVAL; + LONG RANGE; + LONG NEAR; + LONG qbpp; + LONG bpp; + LONG LIMIT; + LONG RESET; + + DefaultTraitsT(const DefaultTraitsT& src) : + MAXVAL(src.MAXVAL), + RANGE(src.RANGE), + NEAR(src.NEAR), + qbpp(src.qbpp), + bpp(src.bpp), + LIMIT(src.LIMIT), + RESET(src.RESET) + { + } + + DefaultTraitsT(LONG max, LONG jls_near) + { + NEAR = jls_near; + MAXVAL = max; + RANGE = (MAXVAL + 2 * NEAR )/(2 * NEAR + 1) + 1; + bpp = log_2(max); + LIMIT = 2 * (bpp + MAX(8,bpp)); + qbpp = log_2(RANGE); + RESET = BASIC_RESET; + } + + + inlinehint LONG ComputeErrVal(LONG e) const + { + LONG q = Quantize(e); + return ModRange(q); + } + + inlinehint SAMPLE ComputeReconstructedSample(LONG Px, LONG ErrVal) + { + return FixReconstructedValue(Px + DeQuantize(ErrVal)); + } + + inlinehint bool IsNear(LONG lhs, LONG rhs) const + { return ABS(lhs-rhs) <=NEAR; } + + bool IsNear(Triplet lhs, Triplet rhs) const + { + return ABS(lhs.v1-rhs.v1) <=NEAR && + ABS(lhs.v2-rhs.v2) <=NEAR && + ABS(lhs.v3-rhs.v3) <=NEAR; + } + + inlinehint LONG CorrectPrediction(LONG Pxc) const + { + if ((Pxc & MAXVAL) == Pxc) + return Pxc; + + return (~(Pxc >> (LONG_BITCOUNT-1))) & MAXVAL; + } + + inlinehint LONG ModRange(LONG Errval) const + { + ASSERT(ABS(Errval) <= RANGE); + if (Errval < 0) + Errval = Errval + RANGE; + + if (Errval >= ((RANGE + 1) / 2)) + Errval = Errval - RANGE; + + ASSERT(ABS(Errval) <= RANGE/2); + + return Errval; + } + + +private: + LONG Quantize(LONG Errval) const + { + if (Errval > 0) + return (Errval + NEAR) / (2 * NEAR + 1); + else + return - (NEAR - Errval) / (2 * NEAR + 1); + } + + + inlinehint LONG DeQuantize(LONG Errval) const + { + return Errval * (2 * NEAR + 1); + } + + inlinehint SAMPLE FixReconstructedValue(LONG val) const + { + if (val < -NEAR) + val = val + RANGE*(2*NEAR+1); + else if (val > MAXVAL + NEAR) + val = val - RANGE*(2*NEAR+1); + + return SAMPLE(CorrectPrediction(val)); + } + +}; + + +#endif diff --git a/dcmjpls/libcharls/encodstr.h b/dcmjpls/libcharls/encodstr.h new file mode 100644 index 00000000..7cd32ead --- /dev/null +++ b/dcmjpls/libcharls/encodstr.h @@ -0,0 +1,162 @@ +// +// (C) Jan de Vaan 2007-2010, all rights reserved. See the accompanying "License.txt" for licensed use. +// + +#ifndef CHARLS_ENCODERSTRATEGY +#define CHARLS_ENCODERSTRATEGY + +#include "dcmtk/ofstd/ofaptr.h" +#include "procline.h" +#include "decodstr.h" + +// Implements encoding to stream of bits. In encoding mode JpegLsCodec inherits from EncoderStrategy + +class EncoderStrategy +{ + +public: + explicit EncoderStrategy(const JlsParameters& info) : + _qdecoder(0), + _info(info), + _processLine(0), + valcurrent(0), + bitpos(0), + _isFFWritten(false), + _bytesWritten(0) + + { + } + + virtual ~EncoderStrategy() + { + } + + LONG PeekByte(); + + void OnLineBegin(LONG cpixel, void* ptypeBuffer, LONG pixelStride) + { + _processLine->NewLineRequested(ptypeBuffer, cpixel, pixelStride); + } + + void OnLineEnd(LONG /*cpixel*/, void* /*ptypeBuffer*/, LONG /*pixelStride*/) { } + + virtual void SetPresets(const JlsCustomParameters& presets) = 0; + + virtual size_t EncodeScan(const void* pvoid, void* pvoidOut, size_t byteCount, void* pvoidCompare) = 0; + +protected: + + void Init(BYTE* compressedBytes, size_t byteCount) + { + bitpos = 32; + valcurrent = 0; + _position = compressedBytes; + _compressedLength = byteCount; + } + + + void AppendToBitStream(LONG value, LONG length) + { + ASSERT(length < 32 && length >= 0); + + ASSERT((_qdecoder.get() == NULL) || (length == 0 && value == 0) ||( _qdecoder->ReadLongValue(length) == value)); + +#ifndef NDEBUG + if (length < 32) + { + int mask = (1 << (length)) - 1; + ASSERT((value | mask) == mask); + } +#endif + + bitpos -= length; + if (bitpos > 0) + { + valcurrent = valcurrent | (value << bitpos); + return; + } + valcurrent |= value >> -bitpos; + + Flush(); + + ASSERT(bitpos >= 0); + if (bitpos < 32) + valcurrent |= value << bitpos; + } + + void EndScan() + { + Flush(); + + // if a 0xff was written, Flush() will force one unset bit anyway + if (_isFFWritten) + AppendToBitStream(0, (bitpos - 1) % 8); + else + AppendToBitStream(0, bitpos % 8); + + Flush(); + ASSERT(bitpos == 0x20); + } + + void Flush() + { + for (LONG i = 0; i < 4; ++i) + { + if (bitpos >= 32) + break; + + if (_isFFWritten) + { + // insert highmost bit + *_position = BYTE(valcurrent >> 25); + valcurrent = valcurrent << 7; + bitpos += 7; + _isFFWritten = false; + } + else + { + *_position = BYTE(valcurrent >> 24); + valcurrent = valcurrent << 8; + bitpos += 8; + _isFFWritten = *_position == 0xFF; + } + + _position++; + _compressedLength--; + _bytesWritten++; + + } + + } + + size_t GetLength() + { + return _bytesWritten - (bitpos -32)/8; + } + + + inlinehint void AppendOnesToBitStream(LONG length) + { + AppendToBitStream((1 << length) - 1, length); + } + + + OFauto_ptr _qdecoder; + +protected: + JlsParameters _info; + OFauto_ptr _processLine; +private: + + unsigned int valcurrent; + LONG bitpos; + size_t _compressedLength; + + // encoding + BYTE* _position; + bool _isFFWritten; + size_t _bytesWritten; + +}; + +#endif diff --git a/dcmjpls/libcharls/header.cc b/dcmjpls/libcharls/header.cc new file mode 100644 index 00000000..15f839ff --- /dev/null +++ b/dcmjpls/libcharls/header.cc @@ -0,0 +1,625 @@ +// +// (C) Jan de Vaan 2007-2010, all rights reserved. See the accompanying "License.txt" for licensed use. +// + +#include "config.h" +#include "util.h" +#include "header.h" +#include "streams.h" +#include "decodstr.h" +#include "encodstr.h" + + +bool IsDefault(const JlsCustomParameters* pcustom) +{ + if (pcustom->MAXVAL != 0) + return false; + + if (pcustom->T1 != 0) + return false; + + if (pcustom->T2 != 0) + return false; + + if (pcustom->T3 != 0) + return false; + + if (pcustom->RESET != 0) + return false; + + return true; +} + + +LONG CLAMP(LONG i, LONG j, LONG MAXVAL) +{ + if (i > MAXVAL || i < j) + return j; + + return i; +} + + +JlsCustomParameters ComputeDefault(LONG MAXVAL, LONG NEAR) +{ + JlsCustomParameters preset = JlsCustomParameters(); + + LONG FACTOR = (MIN(MAXVAL, 4095) + 128)/256; + + preset.T1 = CLAMP(FACTOR * (BASIC_T1 - 2) + 2 + 3*NEAR, NEAR + 1, MAXVAL); + preset.T2 = CLAMP(FACTOR * (BASIC_T2 - 3) + 3 + 5*NEAR, preset.T1, MAXVAL); + preset.T3 = CLAMP(FACTOR * (BASIC_T3 - 4) + 4 + 7*NEAR, preset.T2, MAXVAL); + preset.MAXVAL = MAXVAL; + preset.RESET = BASIC_RESET; + return preset; +} + + +JLS_ERROR CheckParameterCoherent(const JlsParameters* pparams) +{ + if (pparams->bitspersample < 6 || pparams->bitspersample > 16) + return ParameterValueNotSupported; + + if (pparams->ilv < 0 || pparams->ilv > 2) + throw JlsException(InvalidCompressedData); + + if (pparams->bitspersample < 6 || pparams->bitspersample > 16) + return ParameterValueNotSupported; + + switch (pparams->components) + { + case 4: return pparams->ilv == ILV_SAMPLE ? ParameterValueNotSupported : OK; + case 3: return OK; + case 1: return pparams->ilv != ILV_NONE ? ParameterValueNotSupported : OK; + case 0: return InvalidJlsParameters; + + default: return pparams->ilv != ILV_NONE ? ParameterValueNotSupported : OK; + } +} + +// +// JpegMarkerSegment +// +class JpegMarkerSegment : public JpegSegment +{ +public: + JpegMarkerSegment(BYTE marker, OFVector vecbyte) + { + _marker = marker; + _vecbyte.swap(vecbyte); + } + + virtual void Write(JLSOutputStream* pstream) + { + pstream->WriteByte(0xFF); + pstream->WriteByte(_marker); + pstream->WriteWord(USHORT(_vecbyte.size() + 2)); + pstream->WriteBytes(_vecbyte); + } + + BYTE _marker; + OFVector _vecbyte; +}; + + +// +// push_back() +// +void push_back(OFVector& vec, USHORT value) +{ + vec.push_back(BYTE(value / 0x100)); + vec.push_back(BYTE(value % 0x100)); +} + + +// +// CreateMarkerStartOfFrame() +// +JpegSegment* CreateMarkerStartOfFrame(Size size, LONG bitsPerSample, LONG ccomp) +{ + + OFVector vec; + vec.push_back(static_cast(bitsPerSample)); + push_back(vec, static_cast(size.cy)); + push_back(vec, static_cast(size.cx)); + + // components + vec.push_back(static_cast(ccomp)); + for (BYTE component = 0; component < ccomp; component++) + { + // rescaling + vec.push_back(component + 1); + vec.push_back(0x11); + //"Tq1" reserved, 0 + vec.push_back(0); + } + + return new JpegMarkerSegment(JPEG_SOF, vec); +} + + + + +// +// ctor() +// +JLSOutputStream::JLSOutputStream() : + _bCompare(false), + _pdata(NULL), + _cbyteOffset(0), + _cbyteLength(0), + _icompLast(0) +{ +} + + + +// +// dtor() +// +JLSOutputStream::~JLSOutputStream() +{ + for (size_t i = 0; i < _segments.size(); ++i) + { + delete _segments[i]; + } + _segments.empty(); +} + + + + +// +// Init() +// +void JLSOutputStream::Init(Size size, LONG bitsPerSample, LONG ccomp) +{ + _segments.push_back(CreateMarkerStartOfFrame(size, bitsPerSample, ccomp)); +} + + +void JLSOutputStream::AddColorTransform(int i) +{ + OFVector rgbyteXform; + rgbyteXform.push_back('m'); + rgbyteXform.push_back('r'); + rgbyteXform.push_back('f'); + rgbyteXform.push_back('x'); + rgbyteXform.push_back((BYTE)i); + + _segments.push_back(new JpegMarkerSegment(JPEG_APP8, rgbyteXform)); +} + + +// +// Write() +// +size_t JLSOutputStream::Write(BYTE* pdata, size_t cbyteLength) +{ + _pdata = pdata; + _cbyteLength = cbyteLength; + + WriteByte(0xFF); + WriteByte(JPEG_SOI); + + for (size_t i = 0; i < _segments.size(); ++i) + { + _segments[i]->Write(this); + } + + //_bCompare = false; + + WriteByte(0xFF); + WriteByte(JPEG_EOI); + + return _cbyteOffset; +} + + + +JLSInputStream::JLSInputStream(const BYTE* pdata, size_t cbyteLength) : + _pdata(pdata), + _cbyteOffset(0), + _cbyteLength(cbyteLength), + _bCompare(false), + _info(), + _rect() +{ + ::memset(&_info, 0, sizeof(_info)); +} + +// +// Read() +// +void JLSInputStream::Read(void* pvoid, size_t cbyteAvailable) +{ + ReadHeader(); + + JLS_ERROR error = CheckParameterCoherent(&_info); + if (error != OK) + throw JlsException(error); + + ReadPixels(pvoid, cbyteAvailable); +} + + + + + +// +// ReadPixels() +// +void JLSInputStream::ReadPixels(void* pvoid, size_t cbyteAvailable) +{ + + if (_rect.Width <= 0) + { + _rect.Width = _info.width; + _rect.Height = _info.height; + } + + size_t cbytePlane = (size_t)(_rect.Width) * _rect.Height * ((_info.bitspersample + 7)/8); + + if (cbyteAvailable < cbytePlane * _info.components) + throw JlsException(UncompressedBufferTooSmall); + + int scancount = _info.ilv == ILV_NONE ? _info.components : 1; + + BYTE* pbyte = (BYTE*)pvoid; + for (LONG scan = 0; scan < scancount; ++scan) + { + ReadScan(pbyte); + pbyte += cbytePlane; + } +} + +// ReadNBytes() +// +void JLSInputStream::ReadNBytes(OFVector& dst, int byteCount) +{ + for (int i = 0; i < byteCount; ++i) + { + dst.push_back((char)ReadByte()); + } +} + + +// +// ReadHeader() +// +void JLSInputStream::ReadHeader() +{ + if (ReadByte() != 0xFF) + throw JlsException(InvalidCompressedData); + + if (ReadByte() != JPEG_SOI) + throw JlsException(InvalidCompressedData); + + for (;;) + { + if (ReadByte() != 0xFF) + throw JlsException(InvalidCompressedData); + + BYTE marker = (BYTE)ReadByte(); + + size_t cbyteStart = _cbyteOffset; + LONG cbyteMarker = ReadWord(); + + switch (marker) + { + case JPEG_SOS: ReadStartOfScan(); break; + case JPEG_SOF: ReadStartOfFrame(); break; + case JPEG_COM: ReadComment(); break; + case JPEG_LSE: ReadPresetParameters(); break; + case JPEG_APP0: ReadJfif(); break; + case JPEG_APP7: ReadColorSpace(); break; + case JPEG_APP8: ReadColorXForm(); break; + // Other tags not supported (among which DNL DRI) + default: throw JlsException(ImageTypeNotSupported); + } + + if (marker == JPEG_SOS) + { + _cbyteOffset = cbyteStart - 2; + return; + } + _cbyteOffset = cbyteStart + cbyteMarker; + } +} + + +JpegMarkerSegment* EncodeStartOfScan(const JlsParameters* pparams, LONG icomponent) +{ + BYTE itable = 0; + + OFVector rgbyte; + + if (icomponent < 0) + { + rgbyte.push_back((BYTE)pparams->components); + for (LONG i = 0; i < pparams->components; ++i ) + { + rgbyte.push_back(BYTE(i + 1)); + rgbyte.push_back(itable); + } + } + else + { + rgbyte.push_back(1); + rgbyte.push_back((BYTE)icomponent); + rgbyte.push_back(itable); + } + + rgbyte.push_back(BYTE(pparams->allowedlossyerror)); + rgbyte.push_back(BYTE(pparams->ilv)); + rgbyte.push_back(0); // transform + + return new JpegMarkerSegment(JPEG_SOS, rgbyte); +} + + + +JpegMarkerSegment* CreateLSE(const JlsCustomParameters* pcustom) +{ + OFVector rgbyte; + + rgbyte.push_back(1); + push_back(rgbyte, (USHORT)pcustom->MAXVAL); + push_back(rgbyte, (USHORT)pcustom->T1); + push_back(rgbyte, (USHORT)pcustom->T2); + push_back(rgbyte, (USHORT)pcustom->T3); + push_back(rgbyte, (USHORT)pcustom->RESET); + + return new JpegMarkerSegment(JPEG_LSE, rgbyte); +} + +// +// ReadPresetParameters() +// +void JLSInputStream::ReadPresetParameters() +{ + LONG type = ReadByte(); + + + switch (type) + { + case 1: + { + _info.custom.MAXVAL = ReadWord(); + _info.custom.T1 = ReadWord(); + _info.custom.T2 = ReadWord(); + _info.custom.T3 = ReadWord(); + _info.custom.RESET = ReadWord(); + return; + } + } + + +} + + +// +// ReadStartOfScan() +// +void JLSInputStream::ReadStartOfScan() +{ + LONG ccomp = ReadByte(); + for (LONG i = 0; i < ccomp; ++i) + { + ReadByte(); + ReadByte(); + } + _info.allowedlossyerror = ReadByte(); + _info.ilv = interleavemode(ReadByte()); + + if(_info.bytesperline == 0) + { + int width = _rect.Width != 0 ? _rect.Width : _info.width; + int components = _info.ilv == ILV_NONE ? 1 : _info.components; + _info.bytesperline = components * width * ((_info.bitspersample + 7)/8); + } +} + + +// +// ReadComment() +// +void JLSInputStream::ReadComment() +{} + + +// +// ReadJfif() +// +void JLSInputStream::ReadJfif() +{ + const BYTE jfifID[] = {'J','F','I','F','\0'}; + for(int i = 0; i < (int)sizeof(jfifID); i++) + { + if(jfifID[i] != ReadByte()) + return; + } + _info.jfif.Ver = ReadWord(); + + // DPI or DPcm + _info.jfif.units = ReadByte(); + _info.jfif.XDensity = ReadWord(); + _info.jfif.YDensity = ReadWord(); + + // thumbnail + _info.jfif.Xthumb = ReadByte(); + _info.jfif.Ythumb = ReadByte(); + if(_info.jfif.Xthumb > 0 && _info.jfif.pdataThumbnail) + { + OFVector tempbuff((char*)_info.jfif.pdataThumbnail, (char*)_info.jfif.pdataThumbnail+3*_info.jfif.Xthumb*_info.jfif.Ythumb); + ReadNBytes(tempbuff, 3*_info.jfif.Xthumb*_info.jfif.Ythumb); + } +} + +// +// CreateJFIF() +// +JpegMarkerSegment* CreateJFIF(const JfifParameters* jfif) +{ + const BYTE jfifID[] = {'J','F','I','F','\0'}; + OFVector rgbyte; + for(int i = 0; i < (int)sizeof(jfifID); i++) + { + rgbyte.push_back(jfifID[i]); + } + + push_back(rgbyte, (USHORT)jfif->Ver); + + rgbyte.push_back(jfif->units); + push_back(rgbyte, (USHORT)jfif->XDensity); + push_back(rgbyte, (USHORT)jfif->YDensity); + + // thumbnail + rgbyte.push_back((BYTE)jfif->Xthumb); + rgbyte.push_back((BYTE)jfif->Ythumb); + if(jfif->Xthumb > 0) + { + if(jfif->pdataThumbnail) + throw JlsException(InvalidJlsParameters); + + rgbyte.insert(rgbyte.end(), (BYTE*)jfif->pdataThumbnail, (BYTE*)jfif->pdataThumbnail+3*jfif->Xthumb*jfif->Ythumb + ); + } + + return new JpegMarkerSegment(JPEG_APP0, rgbyte); +} + + +// +// ReadStartOfFrame() +// +void JLSInputStream::ReadStartOfFrame() +{ + _info.bitspersample = ReadByte(); + int cline = ReadWord(); + int ccol = ReadWord(); + _info.width = ccol; + _info.height = cline; + _info.components= ReadByte(); +} + + +// +// ReadByte() +// +BYTE JLSInputStream::ReadByte() +{ + if (_cbyteOffset >= _cbyteLength) + throw JlsException(InvalidCompressedData); + + return _pdata[_cbyteOffset++]; +} + + +// +// ReadWord() +// +int JLSInputStream::ReadWord() +{ + int i = ReadByte() * 256; + return i + ReadByte(); +} + + +void JLSInputStream::ReadScan(void* pvout) +{ + OFauto_ptr qcodec = JlsCodecFactory().GetCodec(_info, _info.custom); + + _cbyteOffset += qcodec->DecodeScan(pvout, _rect, _pdata + _cbyteOffset, _cbyteLength - _cbyteOffset, _bCompare); +} + + +class JpegImageDataSegment: public JpegSegment +{ +public: + JpegImageDataSegment(const void* pvoidRaw, const JlsParameters& info, LONG icompStart, int ccompScan) : + _ccompScan(ccompScan), + _icompStart(icompStart), + _pvoidRaw(pvoidRaw), + _info(info) + { + } + + void Write(JLSOutputStream* pstream) + { + JlsParameters info = _info; + info.components = _ccompScan; + OFauto_ptr qcodec =JlsCodecFactory().GetCodec(info, _info.custom); + size_t cbyteWritten = qcodec->EncodeScan((BYTE*)_pvoidRaw, pstream->GetPos(), pstream->GetLength(), pstream->_bCompare ? pstream->GetPos() : NULL); + pstream->Seek(cbyteWritten); + } + + + int _ccompScan; + LONG _icompStart; + const void* _pvoidRaw; + JlsParameters _info; +}; + + +void JLSOutputStream::AddScan(const void* compareData, const JlsParameters* pparams) +{ + if (pparams->jfif.Ver) + { + _segments.push_back(CreateJFIF(&pparams->jfif)); + } + if (!IsDefault(&pparams->custom)) + { + _segments.push_back(CreateLSE(&pparams->custom)); + } + else if (pparams->bitspersample > 12) + { + JlsCustomParameters preset = ComputeDefault((1 << pparams->bitspersample) - 1, pparams->allowedlossyerror); + _segments.push_back(CreateLSE(&preset)); + } + + _icompLast += 1; + _segments.push_back(EncodeStartOfScan(pparams,pparams->ilv == ILV_NONE ? _icompLast : -1)); + +// Size size = Size(pparams->width, pparams->height); + int ccomp = pparams->ilv == ILV_NONE ? 1 : pparams->components; + _segments.push_back(new JpegImageDataSegment(compareData, *pparams, _icompLast, ccomp)); +} + + +// +// ReadColorSpace() +// +void JLSInputStream::ReadColorSpace() +{} + + + +// +// ReadColorXForm() +// +void JLSInputStream::ReadColorXForm() +{ + OFVector sourceTag; + ReadNBytes(sourceTag, 4); + + if(strncmp(&sourceTag[0],"mrfx", 4) != 0) + return; + + int xform = ReadByte(); + switch(xform) + { + case COLORXFORM_NONE: + case COLORXFORM_HP1: + case COLORXFORM_HP2: + case COLORXFORM_HP3: + _info.colorTransform = xform; + return; + case COLORXFORM_RGB_AS_YUV_LOSSY: + case COLORXFORM_MATRIX: + throw JlsException(ImageTypeNotSupported); + default: + throw JlsException(InvalidCompressedData); + } +} + diff --git a/dcmjpls/libcharls/header.h b/dcmjpls/libcharls/header.h new file mode 100644 index 00000000..d0fc0f8c --- /dev/null +++ b/dcmjpls/libcharls/header.h @@ -0,0 +1,63 @@ +// +// (C) Jan de Vaan 2007-2010, all rights reserved. See the accompanying "License.txt" for licensed use. +// + + +#ifndef CHARLS_HEADER +#define CHARLS_HEADER + +#include "dcmtk/ofstd/ofaptr.h" +#include "streams.h" + +#define JPEG_SOI 0xD8 +#define JPEG_EOI 0xD9 +#define JPEG_SOS 0xDA + +#define JPEG_SOF 0xF7 +#define JPEG_LSE 0xF8 +#define JPEG_DNL 0xDC +#define JPEG_DRI 0xDD +#define JPEG_RSTm 0xD0 +#define JPEG_COM 0xFE +#define JPEG_APP0 0xE0 // JFIF +#define JPEG_APP7 0xE7 // colorspace +#define JPEG_APP8 0xE8 // colorXForm + + + +// Default bin sizes for JPEG-LS statistical modeling. Can be overridden at compression time, however this is rarely done. +const int BASIC_T1 = 3; +const int BASIC_T2 = 7; +const int BASIC_T3 = 21; + +const LONG BASIC_RESET = 64; + +class JLSOutputStream; + + +template +class JlsCodecFactory +{ +public: + OFauto_ptr GetCodec(const JlsParameters& info, const JlsCustomParameters&); +private: + STRATEGY* GetCodecImpl(const JlsParameters& info); +}; + +JLS_ERROR CheckParameterCoherent(const JlsParameters* pparams); + +JlsCustomParameters ComputeDefault(LONG MAXVAL, LONG NEAR); + +// +// JpegSegment +// +class JpegSegment +{ +protected: + JpegSegment() {} +public: + virtual ~JpegSegment() {} + virtual void Write(JLSOutputStream* pstream) = 0; +}; + +#endif diff --git a/dcmjpls/libcharls/intrface.cc b/dcmjpls/libcharls/intrface.cc new file mode 100644 index 00000000..91f75f1e --- /dev/null +++ b/dcmjpls/libcharls/intrface.cc @@ -0,0 +1,201 @@ +// +// (C) Jan de Vaan 2007-2010, all rights reserved. See the accompanying "License.txt" for licensed use. +// + + +#include "config.h" +#include "util.h" +#include "intrface.h" +#include "header.h" + + +JLS_ERROR CheckInput(const void* compressedData, size_t compressedLength, const void* uncompressedData, size_t uncompressedLength, const JlsParameters* pparams) +{ + if (pparams == NULL) + return InvalidJlsParameters; + + if (compressedLength == 0) + return InvalidJlsParameters; + + if (compressedData == NULL) + return InvalidJlsParameters; + + if (uncompressedData == NULL) + return InvalidJlsParameters; + + if (pparams->width < 1 || pparams->width > 65535) + return ParameterValueNotSupported; + + if (pparams->height < 1 || pparams->height > 65535) + return ParameterValueNotSupported; + + int bytesperline = pparams->bytesperline < 0 ? -pparams->bytesperline : pparams->bytesperline; + + if (uncompressedLength < size_t(bytesperline * pparams->height)) + return InvalidJlsParameters; + + return CheckParameterCoherent(pparams); +} + + + +extern "C" +{ + +CHARLS_IMEXPORT(JLS_ERROR) JpegLsEncode(void* compressedData, size_t compressedLength, size_t* pcbyteWritten, const void* uncompressedData, size_t uncompressedLength, struct JlsParameters* pparams) +{ + JlsParameters info = *pparams; + if(info.bytesperline == 0) + { + info.bytesperline = info.width * ((info.bitspersample + 7)/8); + if (info.ilv != ILV_NONE) + { + info.bytesperline *= info.components; + } + } + + JLS_ERROR parameterError = CheckInput(compressedData, compressedLength, uncompressedData, uncompressedLength, &info); + + if (parameterError != OK) + return parameterError; + + if (pcbyteWritten == NULL) + return InvalidJlsParameters; + + Size size = Size(info.width, info.height); + JLSOutputStream stream; + + stream.Init(size, info.bitspersample, info.components); + + if (info.colorTransform != 0) + { + stream.AddColorTransform(info.colorTransform); + } + + if (info.ilv == ILV_NONE) + { + LONG cbyteComp = size.cx*size.cy*((info.bitspersample +7)/8); + for (LONG component = 0; component < info.components; ++component) + { + const BYTE* compareData = static_cast(uncompressedData) + component*cbyteComp; + stream.AddScan(compareData, &info); + } + } + else + { + stream.AddScan(uncompressedData, &info); + } + + + stream.Write((BYTE*)compressedData, compressedLength); + + *pcbyteWritten = stream.GetBytesWritten(); + return OK; +} + +CHARLS_IMEXPORT(JLS_ERROR) JpegLsDecode(void* uncompressedData, size_t uncompressedLength, const void* compressedData, size_t compressedLength, JlsParameters* info) +{ + JLSInputStream reader((BYTE*)compressedData, compressedLength); + + if(info != NULL) + { + reader.SetInfo(info); + } + + try + { + reader.Read(uncompressedData, uncompressedLength); + return OK; + } + catch (JlsException& e) + { + return e._error; + } +} + + +CHARLS_IMEXPORT(JLS_ERROR) JpegLsDecodeRect(void* uncompressedData, size_t uncompressedLength, const void* compressedData, size_t compressedLength, JlsRect roi, JlsParameters* info) +{ + JLSInputStream reader((BYTE*)compressedData, compressedLength); + + if(info != NULL) + { + reader.SetInfo(info); + } + + reader.SetRect(roi); + + try + { + reader.Read(uncompressedData, uncompressedLength); + return OK; + } + catch (JlsException& e) + { + return e._error; + } +} + + +CHARLS_IMEXPORT(JLS_ERROR) JpegLsVerifyEncode(const void* uncompressedData, size_t uncompressedLength, const void* compressedData, size_t compressedLength) +{ + JlsParameters info = JlsParameters(); + + JLS_ERROR error = JpegLsReadHeader(compressedData, compressedLength, &info); + if (error != OK) + return error; + + error = CheckInput(compressedData, compressedLength, uncompressedData, uncompressedLength, &info); + + if (error != OK) + return error; + + Size size = Size(info.width, info.height); + + JLSOutputStream stream; + + stream.Init(size, info.bitspersample, info.components); + + if (info.ilv == ILV_NONE) + { + LONG cbyteComp = size.cx*size.cy*((info.bitspersample +7)/8); + for (LONG component = 0; component < info.components; ++component) + { + const BYTE* compareData = static_cast(uncompressedData) + component*cbyteComp; + stream.AddScan(compareData, &info); + } + } + else + { + stream.AddScan(uncompressedData, &info); + } + + OFVector rgbyteCompressed(compressedLength + 16); + + memcpy(&rgbyteCompressed[0], compressedData, compressedLength); + + stream.EnableCompare(true); + stream.Write(&rgbyteCompressed[0], compressedLength); + + return OK; +} + + +CHARLS_IMEXPORT(JLS_ERROR) JpegLsReadHeader(const void* compressedData, size_t compressedLength, JlsParameters* pparams) +{ + try + { + JLSInputStream reader((BYTE*)compressedData, compressedLength); + reader.ReadHeader(); + JlsParameters info = reader.GetMetadata(); + *pparams = info; + return OK; + } + catch (JlsException& e) + { + return e._error; + } + +} + +} diff --git a/dcmjpls/libcharls/intrface.h b/dcmjpls/libcharls/intrface.h new file mode 100644 index 00000000..5272affc --- /dev/null +++ b/dcmjpls/libcharls/intrface.h @@ -0,0 +1,50 @@ +// +// (C) Jan de Vaan 2007-2010, all rights reserved. See the accompanying "License.txt" for licensed use. +// + + +#ifndef JLS_INTERFACE +#define JLS_INTERFACE + +#include "pubtypes.h" +#include "dcmtk/ofstd/ofstd.h" /* for size_t */ +#include "dcmtk/ofstd/ofdefine.h" /* for DCMTK_DECL_EXPORT */ + +#ifdef charls_EXPORTS +#define DCMTK_CHARLS_EXPORT DCMTK_DECL_EXPORT +#else +#define DCMTK_CHARLS_EXPORT DCMTK_DECL_IMPORT +#endif + +#ifndef CHARLS_IMEXPORT +#define CHARLS_IMEXPORT(returntype) DCMTK_CHARLS_EXPORT returntype +#endif + + +#ifdef __cplusplus +extern "C" +{ +#endif + CHARLS_IMEXPORT(enum JLS_ERROR) JpegLsEncode(void* compressedData, size_t compressedLength, size_t* pcbyteWritten, + const void* uncompressedData, size_t uncompressedLength, struct JlsParameters* pparams); + + CHARLS_IMEXPORT(enum JLS_ERROR) JpegLsDecode(void* uncompressedData, size_t uncompressedLength, + const void* compressedData, size_t compressedLength, + struct JlsParameters* info); + + + CHARLS_IMEXPORT(enum JLS_ERROR) JpegLsDecodeRect(void* uncompressedData, size_t uncompressedLength, + const void* compressedData, size_t compressedLength, + struct JlsRect rect, struct JlsParameters* info); + + CHARLS_IMEXPORT(enum JLS_ERROR) JpegLsReadHeader(const void* compressedData, size_t compressedLength, + struct JlsParameters* pparams); + + CHARLS_IMEXPORT(enum JLS_ERROR) JpegLsVerifyEncode(const void* uncompressedData, size_t uncompressedLength, + const void* compressedData, size_t compressedLength); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/dcmjpls/libcharls/jpegls.cc b/dcmjpls/libcharls/jpegls.cc new file mode 100644 index 00000000..d7e05c61 --- /dev/null +++ b/dcmjpls/libcharls/jpegls.cc @@ -0,0 +1,165 @@ +// +// (C) Jan de Vaan 2007-2010, all rights reserved. See the accompanying "License.txt" for licensed use. +// + +#include "config.h" +#include "util.h" +#include "streams.h" +#include "header.h" + +#include "decodstr.h" +#include "encodstr.h" +#include "context.h" +#include "ctxtrmod.h" +#include "lokuptbl.h" + + +signed char* JlsContext::_tableC = CreateTableC(); + +// As defined in the JPEG-LS standard + +// used to determine how large runs should be encoded at a time. +const int J[32] = {0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 9, 10, 11, 12, 13, 14, 15}; + + + +#include "lltraits.h" +#include "deftrait.h" + +#include "scan.h" + +signed char QuantizeGratientOrg(const JlsCustomParameters& preset, LONG NEAR, LONG Di) +{ + if (Di <= -preset.T3) return -4; + if (Di <= -preset.T2) return -3; + if (Di <= -preset.T1) return -2; + if (Di < -NEAR) return -1; + if (Di <= NEAR) return 0; + if (Di < preset.T1) return 1; + if (Di < preset.T2) return 2; + if (Di < preset.T3) return 3; + + return 4; +} + + + +OFVector CreateQLutLossless(LONG cbit) +{ + JlsCustomParameters preset = ComputeDefault((1 << cbit) - 1, 0); + LONG range = preset.MAXVAL + 1; + + OFVector lut(range * 2); + + for (LONG diff = -range; diff < range; diff++) + { + lut[range + diff] = QuantizeGratientOrg(preset, 0,diff); + } + return lut; +} + +// Lookup tables to replace code with lookup tables. +// To avoid threading issues, all tables are created when the program is loaded. + + +// Lookup table: decode symbols that are smaller or equal to 8 bit (16 tables for each value of k) +CTable decodingTables[16] = { InitTable(0), InitTable(1), InitTable(2), InitTable(3), + InitTable(4), InitTable(5), InitTable(6), InitTable(7), + InitTable(8), InitTable(9), InitTable(10), InitTable(11), + InitTable(12), InitTable(13), InitTable(14),InitTable(15) }; + + +// Lookup tables: sample differences to bin indexes. +OFVector rgquant8Ll = CreateQLutLossless(8); +OFVector rgquant10Ll = CreateQLutLossless(10); +OFVector rgquant12Ll = CreateQLutLossless(12); +OFVector rgquant16Ll = CreateQLutLossless(16); + + + + +template +OFauto_ptr JlsCodecFactory::GetCodec(const JlsParameters& info, const JlsCustomParameters& presets) +{ + STRATEGY* pstrategy = NULL; + if (presets.RESET != 0 && presets.RESET != BASIC_RESET) + { + DefaultTraitsT traits((1 << info.bitspersample) - 1, info.allowedlossyerror); + traits.MAXVAL = presets.MAXVAL; + traits.RESET = presets.RESET; + pstrategy = new JlsCodec, STRATEGY>(traits, info); + } + else + { + pstrategy = GetCodecImpl(info); + } + + if (pstrategy != NULL) + { + pstrategy->SetPresets(presets); + } + return OFauto_ptr(pstrategy); +} + + + +template +STRATEGY* CreateCodec(const TRAITS& t, const STRATEGY*,const JlsParameters& info) +{ + return new JlsCodec(t, info); +} + + +template +STRATEGY* JlsCodecFactory::GetCodecImpl(const JlsParameters& info) +{ + STRATEGY* s = 0; + + if (info.ilv == ILV_SAMPLE && info.components != 3) + return NULL; + +#ifndef DISABLE_SPECIALIZATIONS + + // optimized lossless versions common formats + if (info.allowedlossyerror == 0) + { + if (info.ilv == ILV_SAMPLE) + { + if (info.bitspersample == 8) + return CreateCodec(LosslessTraitsT,8>(), s, info); + } + else + { + switch (info.bitspersample) + { + case 8: return CreateCodec(LosslessTraitsT(), s, info); + case 12: return CreateCodec(LosslessTraitsT(), s, info); + case 16: return CreateCodec(LosslessTraitsT(), s, info); + } + } + } + +#endif + + int maxval = (1 << info.bitspersample) - 1; + + if (info.bitspersample <= 8) + { + if (info.ilv == ILV_SAMPLE) + return CreateCodec(DefaultTraitsT >(maxval, info.allowedlossyerror), s, info); + + return CreateCodec(DefaultTraitsT((1 << info.bitspersample) - 1, info.allowedlossyerror), s, info); + } + else if (info.bitspersample <= 16) + { + if (info.ilv == ILV_SAMPLE) + return CreateCodec(DefaultTraitsT >(maxval, info.allowedlossyerror), s, info); + + return CreateCodec(DefaultTraitsT(maxval, info.allowedlossyerror), s, info); + } + return NULL; +} + + +template class JlsCodecFactory; +template class JlsCodecFactory; diff --git a/dcmjpls/libcharls/lltraits.h b/dcmjpls/libcharls/lltraits.h new file mode 100644 index 00000000..e08249ca --- /dev/null +++ b/dcmjpls/libcharls/lltraits.h @@ -0,0 +1,128 @@ +// +// (C) Jan de Vaan 2007-2010, all rights reserved. See the accompanying "License.txt" for licensed use. +// + + + +#ifndef CHARLS_LOSSLESSTRAITS +#define CHARLS_LOSSLESSTRAITS + +#include "header.h" + +// +// optimized trait classes for lossless compression of 8 bit color and 8/16 bit monochrome images. +// This class is assumes MAXVAL correspond to a whole number of bits, and no custom RESET value is set when encoding. +// The point of this is to have the most optimized code for the most common and most demanding scenario. + +template +struct LosslessTraitsImplT +{ + typedef sample SAMPLE; + enum { + NEAR = 0, + bpp = bitsperpixel, + qbpp = bitsperpixel, + RANGE = (1 << bpp), + MAXVAL= (1 << bpp) - 1, + LIMIT = 2 * (bitsperpixel + MAX(8,bitsperpixel)), + RESET = BASIC_RESET + }; + + static inlinehint LONG ComputeErrVal(LONG d) + { return ModRange(d); } + + static inlinehint bool IsNear(LONG lhs, LONG rhs) + { return lhs == rhs; } + + static inlinehint LONG ModRange(LONG Errval) + { + return LONG(Errval << (LONG_BITCOUNT - bpp)) >> (LONG_BITCOUNT - bpp); + } + + static inlinehint SAMPLE ComputeReconstructedSample(LONG Px, LONG ErrVal) + { + return SAMPLE(MAXVAL & (Px + ErrVal)); + } + + static inlinehint LONG CorrectPrediction(LONG Pxc) + { + if ((Pxc & MAXVAL) == Pxc) + return Pxc; + + return (~(Pxc >> (LONG_BITCOUNT-1))) & MAXVAL; + } + +}; + +// For some weird reason MSVC6 doesn't like these templates. +// xlC (compiler on AIX) tries to instantiate Triple > which +// causes compiler errors and is wrong (other compilers don't instantiate it). +#if (defined(_MSC_VER) && _MSC_VER <= 1200) || defined(__xlC__) +# define DISABLE_SPECIALIZATIONS +#else + +template +struct LosslessTraitsT : public LosslessTraitsImplT +{ + typedef SAMPLE PIXEL; +}; + + + +template<> +struct LosslessTraitsT : public LosslessTraitsImplT +{ + typedef SAMPLE PIXEL; + + static inlinehint signed char ModRange(LONG Errval) + { return (signed char)Errval; } + + static inlinehint LONG ComputeErrVal(LONG d) + { return (signed char)(d); } + + static inlinehint BYTE ComputeReconstructedSample(LONG Px, LONG ErrVal) + { return BYTE(Px + ErrVal); } + +}; + + + +template<> +struct LosslessTraitsT : public LosslessTraitsImplT +{ + typedef SAMPLE PIXEL; + + static inlinehint short ModRange(LONG Errval) + { return short(Errval); } + + static inlinehint LONG ComputeErrVal(LONG d) + { return short(d); } + + static inlinehint SAMPLE ComputeReconstructedSample(LONG Px, LONG ErrVal) + { return SAMPLE(Px + ErrVal); } + +}; + + + + +template +struct LosslessTraitsT,bpp> : public LosslessTraitsImplT +{ + typedef Triplet PIXEL; + + static inlinehint bool IsNear(LONG lhs, LONG rhs) + { return lhs == rhs; } + + static inlinehint bool IsNear(PIXEL lhs, PIXEL rhs) + { return lhs == rhs; } + + + static inlinehint SAMPLE ComputeReconstructedSample(LONG Px, LONG ErrVal) + { return SAMPLE(Px + ErrVal); } + + +}; +#endif + +#endif diff --git a/dcmjpls/libcharls/lokuptbl.h b/dcmjpls/libcharls/lokuptbl.h new file mode 100644 index 00000000..b37d104f --- /dev/null +++ b/dcmjpls/libcharls/lokuptbl.h @@ -0,0 +1,69 @@ +// +// (C) Jan de Vaan 2007-2010, all rights reserved. See the accompanying "License.txt" for licensed use. +// + + +#ifndef CHARLS_LOOKUPTABLE +#define CHARLS_LOOKUPTABLE + +// Tables for fast decoding of short Golomb Codes. + +struct Code +{ + Code() + { + } + + Code(LONG value, LONG length) : + _value(value), + _length(length) + { + } + + LONG GetValue() const + { return _value; } + LONG GetLength() const + { return _length; } + + LONG _value; + LONG _length; +}; + + + +class CTable +{ +public: + + enum { cbit = 8 } ; + + CTable() + { + ::memset(rgtype, 0, sizeof(rgtype)); + } + + void AddEntry(BYTE bvalue, Code c); + + inlinehint const Code& Get(LONG value) + { return rgtype[value]; } +private: + Code rgtype[1 << cbit]; +}; + + +// +// AddEntry +// +void CTable::AddEntry(BYTE bvalue, Code c) +{ + LONG length = c.GetLength(); + ASSERT(length <= cbit); + + for (LONG i = 0; i < LONG(1) << (cbit - length); ++i) + { + ASSERT(rgtype[(bvalue << (cbit - length)) + i].GetLength() == 0); + rgtype[(bvalue << (cbit - length)) + i] = c; + } +} + +#endif diff --git a/dcmjpls/libcharls/procline.h b/dcmjpls/libcharls/procline.h new file mode 100644 index 00000000..e9f9f09f --- /dev/null +++ b/dcmjpls/libcharls/procline.h @@ -0,0 +1,227 @@ +// +// (C) Jan de Vaan 2007-2010, all rights reserved. See the accompanying "License.txt" for licensed use. +// +#ifndef CHARLS_PROCESSLINE +#define CHARLS_PROCESSLINE + +#include "clrtrans.h" + +// +// This file defines the ProcessLine base class, its derivitives and helper functions. +// During coding/decoding, CharLS process one line at a time. The different Processline implementations +// convert the uncompressed format to and from the internal format for encoding. +// Conversions include color transforms, line interleaved vs sample interleaved, masking out unused bits, +// accounting for line padding etc. +// This mechanism could be used to encode/decode images as they are received. +// + +class ProcessLine +{ +public: + virtual ~ProcessLine() {} + virtual void NewLineDecoded(const void* pSrc, int pixelCount, int bytesperline) = 0; + virtual void NewLineRequested(void* pSrc, int pixelCount, int bytesperline) = 0; +}; + + +class PostProcesSingleComponent : public ProcessLine +{ +public: + PostProcesSingleComponent(void* pbyteOutput, const JlsParameters& info, int bytesPerPixel) : + _pbyteOutput((BYTE*)pbyteOutput), + _bytesPerPixel(bytesPerPixel), + _bytesPerLine(info.bytesperline) + { + } + + void NewLineRequested(void* pDst, int pixelCount, int /*byteStride*/) + { + OFBitmanipTemplate::copyMem(_pbyteOutput, (BYTE*) pDst, pixelCount * _bytesPerPixel); + _pbyteOutput += _bytesPerLine; + } + + void NewLineDecoded(const void* pSrc, int pixelCount, int /*byteStride*/) + { + OFBitmanipTemplate::copyMem((BYTE*) pSrc, _pbyteOutput, pixelCount * _bytesPerPixel); + _pbyteOutput += _bytesPerLine; + } + +private: + BYTE* _pbyteOutput; + int _bytesPerPixel; + int _bytesPerLine; +}; + + +template +void TransformLineToQuad(const SAMPLE* ptypeInput, LONG pixelStrideIn, Quad* pbyteBuffer, LONG pixelStride, TRANSFORM& transform) +{ + int cpixel = MIN(pixelStride, pixelStrideIn); + Quad* ptypeBuffer = (Quad*)pbyteBuffer; + + for (int x = 0; x < cpixel; ++x) + { + Quad pixel(transform(ptypeInput[x], ptypeInput[x + pixelStrideIn], ptypeInput[x + 2*pixelStrideIn]),ptypeInput[x + 3*pixelStrideIn]) ; + + ptypeBuffer[x] = pixel; + } +} + + +template +void TransformQuadToLine(const Quad* pbyteInput, LONG pixelStrideIn, SAMPLE* ptypeBuffer, LONG pixelStride, TRANSFORM& transform) +{ + int cpixel = MIN(pixelStride, pixelStrideIn); + const Quad* ptypeBufferIn = (Quad*)pbyteInput; + + for (int x = 0; x < cpixel; ++x) + { + Quad color = ptypeBufferIn[x]; + Quad colorTranformed(transform(color.v1, color.v2, color.v3), color.v4); + + ptypeBuffer[x] = colorTranformed.v1; + ptypeBuffer[x + pixelStride] = colorTranformed.v2; + ptypeBuffer[x + 2 *pixelStride] = colorTranformed.v3; + ptypeBuffer[x + 3 *pixelStride] = colorTranformed.v4; + } +} + + +template +void TransformRgbToBgr(SAMPLE* pDest, int samplesPerPixel, int pixelCount) +{ + for (int i = 0; i < pixelCount; ++i) + { + SAMPLE tmp = pDest[0]; + pDest[0] = pDest[2]; + pDest[2] = tmp; + pDest += samplesPerPixel; + } +} + + +template +void TransformLine(Triplet* pDest, const Triplet* pSrc, int pixelCount, TRANSFORM& transform) +{ + for (int i = 0; i < pixelCount; ++i) + { + pDest[i] = transform(pSrc[i].v1, pSrc[i].v2, pSrc[i].v3); + } +} + + +template +void TransformLineToTriplet(const SAMPLE* ptypeInput, LONG pixelStrideIn, Triplet* pbyteBuffer, LONG pixelStride, TRANSFORM& transform) +{ + int cpixel = MIN(pixelStride, pixelStrideIn); + Triplet* ptypeBuffer = (Triplet*)pbyteBuffer; + + for (int x = 0; x < cpixel; ++x) + { + ptypeBuffer[x] = transform(ptypeInput[x], ptypeInput[x + pixelStrideIn], ptypeInput[x + 2*pixelStrideIn]); + } +} + + +template +void TransformTripletToLine(const Triplet* pbyteInput, LONG pixelStrideIn, SAMPLE* ptypeBuffer, LONG pixelStride, TRANSFORM& transform) +{ + int cpixel = MIN(pixelStride, pixelStrideIn); + const Triplet* ptypeBufferIn = (Triplet*)pbyteInput; + + for (int x = 0; x < cpixel; ++x) + { + Triplet color = ptypeBufferIn[x]; + Triplet colorTranformed = transform(color.v1, color.v2, color.v3); + + ptypeBuffer[x] = colorTranformed.v1; + ptypeBuffer[x + pixelStride] = colorTranformed.v2; + ptypeBuffer[x + 2 *pixelStride] = colorTranformed.v3; + } +} + + +template +class ProcessTransformed : public ProcessLine +{ + typedef typename TRANSFORM::SAMPLE SAMPLE; + + ProcessTransformed(const ProcessTransformed&) {} +public: + ProcessTransformed(void* pbyteOutput, const JlsParameters& info, TRANSFORM transform) : + _pbyteOutput((BYTE*)pbyteOutput), + _info(info), + _templine(info.width * info.components), + _transform(transform), + _inverseTransform(transform) + { +// ASSERT(_info.components == sizeof(TRIPLET)/sizeof(TRIPLET::SAMPLE)); + } + + + void NewLineRequested(void* pDst, int pixelCount, int stride) + { + SAMPLE* pLine = (SAMPLE*)_pbyteOutput; + if (_info.outputBgr) + { + pLine = &_templine[0]; + memcpy(pLine, _pbyteOutput, sizeof(Triplet)*pixelCount); + TransformRgbToBgr(pLine, _info.components, pixelCount); + } + + if (_info.components == 3) + { + if (_info.ilv == ILV_SAMPLE) + { + TransformLine((Triplet*)pDst, (const Triplet*)pLine, pixelCount, _transform); + } + else + { + TransformTripletToLine((const Triplet*)pLine, pixelCount, (SAMPLE*)pDst, stride, _transform); + } + } + else if (_info.components == 4 && _info.ilv == ILV_LINE) + { + TransformQuadToLine((const Quad*)pLine, pixelCount, (SAMPLE*)pDst, stride, _transform); + } + _pbyteOutput += _info.bytesperline; + } + + + void NewLineDecoded(const void* pSrc, int pixelCount, int byteStride) + { + if (_info.components == 3) + { + if (_info.ilv == ILV_SAMPLE) + { + TransformLine((Triplet*)_pbyteOutput, (const Triplet*)pSrc, pixelCount, _inverseTransform); + } + else + { + TransformLineToTriplet((const SAMPLE*)pSrc, byteStride, (Triplet*)_pbyteOutput, pixelCount, _inverseTransform); + } + } + else if (_info.components == 4 && _info.ilv == ILV_LINE) + { + TransformLineToQuad((const SAMPLE*)pSrc, byteStride, (Quad*)_pbyteOutput, pixelCount, _inverseTransform); + } + + if (_info.outputBgr) + { + TransformRgbToBgr(_pbyteOutput, _info.components, pixelCount); + } + _pbyteOutput += _info.bytesperline; + } + + +private: + BYTE* _pbyteOutput; + const JlsParameters& _info; + OFVector _templine; + TRANSFORM _transform; + typename TRANSFORM::INVERSE _inverseTransform; +}; + + + +#endif diff --git a/dcmjpls/libcharls/pubtypes.h b/dcmjpls/libcharls/pubtypes.h new file mode 100644 index 00000000..612738cd --- /dev/null +++ b/dcmjpls/libcharls/pubtypes.h @@ -0,0 +1,76 @@ +// +// (C) Jan de Vaan 2007-2010, all rights reserved. See the accompanying "License.txt" for licensed use. +// +#ifndef CHARLS_PUBLICTYPES +#define CHARLS_PUBLICTYPES + +#include "config.h" + +enum JLS_ERROR +{ + OK = 0, + InvalidJlsParameters, + ParameterValueNotSupported, + UncompressedBufferTooSmall, + CompressedBufferTooSmall, + InvalidCompressedData, + TooMuchCompressedData, + ImageTypeNotSupported, + UnsupportedBitDepthForTransform, + UnsupportedColorTransform +}; + + +enum interleavemode +{ + ILV_NONE = 0, + ILV_LINE = 1, + ILV_SAMPLE = 2 +}; + + +struct JlsCustomParameters +{ + int MAXVAL; + int T1; + int T2; + int T3; + int RESET; +}; + + +struct JlsRect +{ + int X, Y; + int Width, Height; +}; + + +struct JfifParameters +{ + int Ver; + char units; + int XDensity; + int YDensity; + short Xthumb; + short Ythumb; + void* pdataThumbnail; // user must set buffer which size is Xthumb*Ythumb*3(RGB) before JpegLsDecode() +}; + + +struct JlsParameters +{ + int width; + int height; + int bitspersample; + int bytesperline; // for [source (at encoding)][decoded (at decoding)] pixel image in user buffer + int components; + int allowedlossyerror; + enum interleavemode ilv; + int colorTransform; + char outputBgr; + struct JlsCustomParameters custom; + struct JfifParameters jfif; +}; + +#endif diff --git a/dcmjpls/libcharls/scan.h b/dcmjpls/libcharls/scan.h new file mode 100644 index 00000000..589e299b --- /dev/null +++ b/dcmjpls/libcharls/scan.h @@ -0,0 +1,862 @@ +// +// (C) Jan de Vaan 2007-2010, all rights reserved. See the accompanying "License.txt" for licensed use. +// + +#ifndef CHARLS_SCAN +#define CHARLS_SCAN + +#include "dcmtk/ofstd/ofmap.h" /* For OFPair */ +#include "dcmtk/ofstd/oftypes.h" /* For OFTypename */ + +#include "lokuptbl.h" + +// This file contains the code for handling a "scan". Usually an image is encoded as a single scan. + + +#ifdef _MSC_VER +#pragma warning (disable: 4127) +#endif + + +extern CTable decodingTables[16]; +extern OFVector rgquant8Ll; +extern OFVector rgquant10Ll; +extern OFVector rgquant12Ll; +extern OFVector rgquant16Ll; +// +// Apply +// +inlinehint LONG ApplySign(LONG i, LONG sign) +{ return (sign ^ i) - sign; } + + + +// Two alternatives for GetPredictedValue() (second is slightly faster due to reduced branching) + +#if 0 + +inlinehint LONG GetPredictedValue(LONG Ra, LONG Rb, LONG Rc) +{ + if (Ra < Rb) + { + if (Rc < Ra) + return Rb; + + if (Rc > Rb) + return Ra; + } + else + { + if (Rc < Rb) + return Ra; + + if (Rc > Ra) + return Rb; + } + + return Ra + Rb - Rc; +} + +#else + +inlinehint LONG GetPredictedValue(LONG Ra, LONG Rb, LONG Rc) +{ + // sign trick reduces the number of if statements (branches) + LONG sgn = BitWiseSign(Rb - Ra); + + // is Ra between Rc and Rb? + if ((sgn ^ (Rc - Ra)) < 0) + { + return Rb; + } + else if ((sgn ^ (Rb - Rc)) < 0) + { + return Ra; + } + + // default case, valid if Rc element of [Ra,Rb] + return Ra + Rb - Rc; +} + +#endif + +inlinehint LONG UnMapErrVal(LONG mappedError) +{ + //LONG sign = ~((mappedError & 1) - 1); + LONG sign = LONG(mappedError << (LONG_BITCOUNT-1)) >> (LONG_BITCOUNT-1); + return sign ^ (mappedError >> 1); +} + + + +inlinehint LONG GetMappedErrVal(LONG Errval) +{ + LONG mappedError = (Errval >> (LONG_BITCOUNT-2)) ^ (2 * Errval); + return mappedError; +} + + + +inlinehint LONG ComputeContextID(LONG Q1, LONG Q2, LONG Q3) +{ return (Q1*9 + Q2)*9 + Q3; } + + +// +// +// +template +class JlsCodec : public STRATEGY +{ +public: + typedef typename TRAITS::PIXEL PIXEL; + typedef typename TRAITS::SAMPLE SAMPLE; + +public: + + JlsCodec(const TRAITS& inTraits, const JlsParameters& info) : STRATEGY(info), + traits(inTraits), + _rect(), + _width(0), + T1(0), + T2(0), + T3(0), + _RUNindex(0), + _pquant(0), + _bCompare(0) + + { + if (Info().ilv == ILV_NONE) + { + Info().components = 1; + } + } + + + void SetPresets(const JlsCustomParameters& presets) + { + JlsCustomParameters presetDefault = ComputeDefault(traits.MAXVAL, traits.NEAR); + + InitParams(presets.T1 != 0 ? presets.T1 : presetDefault.T1, + presets.T2 != 0 ? presets.T2 : presetDefault.T2, + presets.T3 != 0 ? presets.T3 : presetDefault.T3, + presets.RESET != 0 ? presets.RESET : presetDefault.RESET); + } + + + bool IsInterleaved() + { + if (Info().ilv == ILV_NONE) + return false; + + if (Info().components == 1) + return false; + + return true; + } + + JlsParameters& Info() { return STRATEGY::_info; } + + signed char QuantizeGratientOrg(LONG Di); + inlinehint LONG QuantizeGratient(LONG Di) + { + ASSERT(QuantizeGratientOrg(Di) == *(_pquant + Di)); + return *(_pquant + Di); + } + + void InitQuantizationLUT(); + + LONG DecodeValue(LONG k, LONG limit, LONG qbpp); + inlinehint void EncodeMappedValue(LONG k, LONG mappedError, LONG limit); + + void IncrementRunIndex() + { _RUNindex = MIN(31,_RUNindex + 1); } + void DecrementRunIndex() + { _RUNindex = MAX(0,_RUNindex - 1); } + + LONG DecodeRIError(CContextRunMode& ctx); + Triplet DecodeRIPixel(Triplet Ra, Triplet Rb); + SAMPLE DecodeRIPixel(LONG Ra, LONG Rb) + { + if (ABS(Ra - Rb) <= traits.NEAR) + { + LONG ErrVal = DecodeRIError(_contextRunmode[1]); + return static_cast(traits.ComputeReconstructedSample(Ra, ErrVal)); + } + else + { + LONG ErrVal = DecodeRIError(_contextRunmode[0]); + return static_cast(traits.ComputeReconstructedSample(Rb, ErrVal * Sign(Rb - Ra))); + } + } + + + LONG DecodeRunPixels(PIXEL Ra, PIXEL* ptype, LONG cpixelMac); + LONG DoRunMode(LONG index, DecoderStrategy*); + + void EncodeRIError(CContextRunMode& ctx, LONG Errval); + SAMPLE EncodeRIPixel(LONG x, LONG Ra, LONG Rb) + { + if (ABS(Ra - Rb) <= traits.NEAR) + { + LONG ErrVal = traits.ComputeErrVal(x - Ra); + EncodeRIError(_contextRunmode[1], ErrVal); + return static_cast(traits.ComputeReconstructedSample(Ra, ErrVal)); + } + else + { + LONG ErrVal = traits.ComputeErrVal((x - Rb) * Sign(Rb - Ra)); + EncodeRIError(_contextRunmode[0], ErrVal); + return static_cast(traits.ComputeReconstructedSample(Rb, ErrVal * Sign(Rb - Ra))); + } + } + + Triplet EncodeRIPixel(Triplet x, Triplet Ra, Triplet Rb); + void EncodeRunPixels(LONG runLength, bool bEndofline); + LONG DoRunMode(LONG index, EncoderStrategy*); + + // Encode/decode a single sample. Performancewise the #1 important functions + SAMPLE DoRegular(LONG Qs, LONG, LONG pred, DecoderStrategy*) + { + LONG sign = BitWiseSign(Qs); + JlsContext& ctx = _contexts[ApplySign(Qs, sign)]; + LONG k = ctx.GetGolomb(); + LONG Px = traits.CorrectPrediction(pred + ApplySign(ctx.C, sign)); + + LONG ErrVal; + const Code& code = decodingTables[k].Get(STRATEGY::PeekByte()); + if (code.GetLength() != 0) + { + STRATEGY::Skip(code.GetLength()); + ErrVal = code.GetValue(); + ASSERT(ABS(ErrVal) < 65535); + } + else + { + ErrVal = UnMapErrVal(DecodeValue(k, traits.LIMIT, traits.qbpp)); + if (ABS(ErrVal) > 65535) + throw JlsException(InvalidCompressedData); + } + ErrVal = ErrVal ^ ((traits.NEAR == 0) ? ctx.GetErrorCorrection(k) : 0); + ctx.UpdateVariables(ErrVal, traits.NEAR, traits.RESET); + ErrVal = ApplySign(ErrVal, sign); + return traits.ComputeReconstructedSample(Px, ErrVal); + } + + + SAMPLE DoRegular(LONG Qs, LONG x, LONG pred, EncoderStrategy*) + { + LONG sign = BitWiseSign(Qs); + JlsContext& ctx = _contexts[ApplySign(Qs, sign)]; + LONG k = ctx.GetGolomb(); + LONG Px = traits.CorrectPrediction(pred + ApplySign(ctx.C, sign)); + + LONG ErrVal = traits.ComputeErrVal(ApplySign(x - Px, sign)); + + EncodeMappedValue(k, GetMappedErrVal(ctx.GetErrorCorrection(k | traits.NEAR) ^ ErrVal), traits.LIMIT); + ctx.UpdateVariables(ErrVal, traits.NEAR, traits.RESET); + ASSERT(traits.IsNear(traits.ComputeReconstructedSample(Px, ApplySign(ErrVal, sign)), x)); + return static_cast(traits.ComputeReconstructedSample(Px, ApplySign(ErrVal, sign))); + } + + + + void DoLine(SAMPLE* pdummy); + void DoLine(Triplet* pdummy); + void DoScan(BYTE* compressedBytes, size_t compressedLength); + +public: + ProcessLine* CreateProcess(void* pvoidOut); + void InitDefault(); + void InitParams(LONG t1, LONG t2, LONG t3, LONG nReset); + + size_t EncodeScan(const void* rawData, void* pvoidOut, size_t compressedLength, void* pvoidCompare); + size_t DecodeScan(void* rawData, const JlsRect& size, const void* compressedData, size_t compressedLength, bool bCompare); + +protected: + // codec parameters + TRAITS traits; + JlsRect _rect; + int _width; + LONG T1; + LONG T2; + LONG T3; + + // compression context + JlsContext _contexts[365]; + CContextRunMode _contextRunmode[2]; + LONG _RUNindex; + PIXEL* _previousLine; // previous line ptr + PIXEL* _currentLine; // current line ptr + + + // quantization lookup table + signed char* _pquant; + OFVector _rgquant; + + // debugging + bool _bCompare; +}; + + +// Functions to build tables used to decode short golomb codes. + +inlinehint OFPair CreateEncodedValue(LONG k, LONG mappedError) +{ + LONG highbits = mappedError >> k; + return OFMake_pair(highbits + k + 1, (LONG(1) << k) | (mappedError & ((LONG(1) << k) - 1))); +} + + +CTable InitTable(LONG k) +{ + CTable table; + short nerr; + for (nerr = 0; ; nerr++) + { + // Q is not used when k != 0 + LONG merrval = GetMappedErrVal(nerr);//, k, -1); + OFPair paircode = CreateEncodedValue(k, merrval); + if (paircode.first > CTable::cbit) + break; + + Code code = Code( nerr, short(paircode.first) ); + table.AddEntry(BYTE(paircode.second), code); + } + + for (nerr = -1; ; nerr--) + { + // Q is not used when k != 0 + LONG merrval = GetMappedErrVal(nerr);//, k, -1); + OFPair paircode = CreateEncodedValue(k, merrval); + if (paircode.first > CTable::cbit) + break; + + Code code = Code(nerr, short(paircode.first)); + table.AddEntry(BYTE(paircode.second), code); + } + + return table; +} + + +// Encoding/decoding of golomb codes + +template +LONG JlsCodec::DecodeValue(LONG k, LONG limit, LONG qbpp) +{ + LONG highbits = STRATEGY::ReadHighbits(); + + if (highbits >= limit - (qbpp + 1)) + return STRATEGY::ReadValue(qbpp) + 1; + + if (k == 0) + return highbits; + + return (highbits << k) + STRATEGY::ReadValue(k); +} + + + +template +inlinehint void JlsCodec::EncodeMappedValue(LONG k, LONG mappedError, LONG limit) +{ + LONG highbits = mappedError >> k; + + if (highbits < limit - traits.qbpp - 1) + { + if (highbits + 1 > 31) + { + STRATEGY::AppendToBitStream(0, highbits / 2); + highbits = highbits - highbits / 2; + } + STRATEGY::AppendToBitStream(1, highbits + 1); + STRATEGY::AppendToBitStream((mappedError & ((1 << k) - 1)), k); + return; + } + + if (limit - traits.qbpp > 31) + { + STRATEGY::AppendToBitStream(0, 31); + STRATEGY::AppendToBitStream(1, limit - traits.qbpp - 31); + } + else + { + STRATEGY::AppendToBitStream(1, limit - traits.qbpp); + } + STRATEGY::AppendToBitStream((mappedError - 1) & ((1 << traits.qbpp) - 1), traits.qbpp); +} + + +// Sets up a lookup table to "Quantize" sample difference. + +template +void JlsCodec::InitQuantizationLUT() +{ + // for lossless mode with default parameters, we have precomputed te luts for bitcounts 8,10,12 and 16 + if (traits.NEAR == 0 && traits.MAXVAL == (1 << traits.bpp) - 1) + { + JlsCustomParameters presets = ComputeDefault(traits.MAXVAL, traits.NEAR); + if (presets.T1 == T1 && presets.T2 == T2 && presets.T3 == T3) + { + if (traits.bpp == 8) + { + _pquant = &rgquant8Ll[rgquant8Ll.size() / 2 ]; + return; + } + if (traits.bpp == 10) + { + _pquant = &rgquant10Ll[rgquant10Ll.size() / 2 ]; + return; + } + if (traits.bpp == 12) + { + _pquant = &rgquant12Ll[rgquant12Ll.size() / 2 ]; + return; + } + if (traits.bpp == 16) + { + _pquant = &rgquant16Ll[rgquant16Ll.size() / 2 ]; + return; + } + } + } + + LONG RANGE = 1 << traits.bpp; + + _rgquant.resize(RANGE * 2); + + _pquant = &_rgquant[RANGE]; + for (LONG i = -RANGE; i < RANGE; ++i) + { + _pquant[i] = QuantizeGratientOrg(i); + } +} + + +template +signed char JlsCodec::QuantizeGratientOrg(LONG Di) +{ + if (Di <= -T3) return -4; + if (Di <= -T2) return -3; + if (Di <= -T1) return -2; + if (Di < -traits.NEAR) return -1; + if (Di <= traits.NEAR) return 0; + if (Di < T1) return 1; + if (Di < T2) return 2; + if (Di < T3) return 3; + + return 4; +} + + + +// RI = Run interruption: functions that handle the sample terminating a run. + +template +LONG JlsCodec::DecodeRIError(CContextRunMode& ctx) +{ + LONG k = ctx.GetGolomb(); + LONG EMErrval = DecodeValue(k, traits.LIMIT - J[_RUNindex]-1, traits.qbpp); + LONG Errval = ctx.ComputeErrVal(EMErrval + ctx._nRItype, k); + ctx.UpdateVariables(Errval, EMErrval); + return Errval; +} + + + +template +void JlsCodec::EncodeRIError(CContextRunMode& ctx, LONG Errval) +{ + LONG k = ctx.GetGolomb(); + bool map = ctx.ComputeMap(Errval, k); + LONG EMErrval = 2 * ABS(Errval) - ctx._nRItype - map; + + ASSERT(Errval == ctx.ComputeErrVal(EMErrval + ctx._nRItype, k)); + EncodeMappedValue(k, EMErrval, traits.LIMIT-J[_RUNindex]-1); + ctx.UpdateVariables(Errval, EMErrval); +} + + +template +Triplet JlsCodec::DecodeRIPixel(Triplet Ra, Triplet Rb) +{ + LONG Errval1 = DecodeRIError(_contextRunmode[0]); + LONG Errval2 = DecodeRIError(_contextRunmode[0]); + LONG Errval3 = DecodeRIError(_contextRunmode[0]); + + return Triplet(traits.ComputeReconstructedSample(Rb.v1, Errval1 * Sign(Rb.v1 - Ra.v1)), + traits.ComputeReconstructedSample(Rb.v2, Errval2 * Sign(Rb.v2 - Ra.v2)), + traits.ComputeReconstructedSample(Rb.v3, Errval3 * Sign(Rb.v3 - Ra.v3))); +} + + + +template +Triplet JlsCodec::EncodeRIPixel(Triplet x, Triplet Ra, Triplet Rb) +{ + LONG errval1 = traits.ComputeErrVal(Sign(Rb.v1 - Ra.v1) * (x.v1 - Rb.v1)); + EncodeRIError(_contextRunmode[0], errval1); + + LONG errval2 = traits.ComputeErrVal(Sign(Rb.v2 - Ra.v2) * (x.v2 - Rb.v2)); + EncodeRIError(_contextRunmode[0], errval2); + + LONG errval3 = traits.ComputeErrVal(Sign(Rb.v3 - Ra.v3) * (x.v3 - Rb.v3)); + EncodeRIError(_contextRunmode[0], errval3); + + + return Triplet(traits.ComputeReconstructedSample(Rb.v1, errval1 * Sign(Rb.v1 - Ra.v1)), + traits.ComputeReconstructedSample(Rb.v2, errval2 * Sign(Rb.v2 - Ra.v2)), + traits.ComputeReconstructedSample(Rb.v3, errval3 * Sign(Rb.v3 - Ra.v3))); +} + + + +// RunMode: Functions that handle run-length encoding + +template +void JlsCodec::EncodeRunPixels(LONG runLength, bool endOfLine) +{ + while (runLength >= LONG(1 << J[_RUNindex])) + { + STRATEGY::AppendOnesToBitStream(1); + runLength = runLength - LONG(1 << J[_RUNindex]); + IncrementRunIndex(); + } + + if (endOfLine) + { + if (runLength != 0) + { + STRATEGY::AppendOnesToBitStream(1); + } + } + else + { + STRATEGY::AppendToBitStream(runLength, J[_RUNindex] + 1); // leading 0 + actual remaining length + } +} + + +template +LONG JlsCodec::DecodeRunPixels(PIXEL Ra, PIXEL* startPos, LONG cpixelMac) +{ + LONG index = 0; + while (STRATEGY::ReadBit()) + { + int count = MIN(1 << J[_RUNindex], int(cpixelMac - index)); + index += count; + ASSERT(index <= cpixelMac); + + if (count == (1 << J[_RUNindex])) + { + IncrementRunIndex(); + } + + if (index == cpixelMac) + break; + } + + + if (index != cpixelMac) + { + // incomplete run + index += (J[_RUNindex] > 0) ? STRATEGY::ReadValue(J[_RUNindex]) : 0; + } + + if (index > cpixelMac) + throw JlsException(InvalidCompressedData); + + for (LONG i = 0; i < index; ++i) + { + startPos[i] = Ra; + } + + return index; +} + +template +LONG JlsCodec::DoRunMode(LONG index, EncoderStrategy*) +{ + LONG ctypeRem = _width - index; + PIXEL* ptypeCurX = _currentLine + index; + PIXEL* ptypePrevX = _previousLine + index; + + PIXEL Ra = ptypeCurX[-1]; + + LONG runLength = 0; + + while (traits.IsNear(ptypeCurX[runLength],Ra)) + { + ptypeCurX[runLength] = Ra; + runLength++; + + if (runLength == ctypeRem) + break; + } + + EncodeRunPixels(runLength, runLength == ctypeRem); + + if (runLength == ctypeRem) + return runLength; + + ptypeCurX[runLength] = EncodeRIPixel(ptypeCurX[runLength], Ra, ptypePrevX[runLength]); + DecrementRunIndex(); + return runLength + 1; +} + + +template +LONG JlsCodec::DoRunMode(LONG startIndex, DecoderStrategy*) +{ + PIXEL Ra = _currentLine[startIndex-1]; + + LONG runLength = DecodeRunPixels(Ra, _currentLine + startIndex, _width - startIndex); + LONG endIndex = startIndex + runLength; + + if (endIndex == _width) + return endIndex - startIndex; + + // run interruption + PIXEL Rb = _previousLine[endIndex]; + _currentLine[endIndex] = DecodeRIPixel(Ra, Rb); + DecrementRunIndex(); + return endIndex - startIndex + 1; +} + + +// DoLine: Encodes/Decodes a scanline of samples + +template +void JlsCodec::DoLine(SAMPLE*) +{ + LONG index = 0; + LONG Rb = _previousLine[index-1]; + LONG Rd = _previousLine[index]; + + while(index < _width) + { + LONG Ra = _currentLine[index -1]; + LONG Rc = Rb; + Rb = Rd; + Rd = _previousLine[index + 1]; + + LONG Qs = ComputeContextID(QuantizeGratient(Rd - Rb), QuantizeGratient(Rb - Rc), QuantizeGratient(Rc - Ra)); + + if (Qs != 0) + { + _currentLine[index] = DoRegular(Qs, _currentLine[index], GetPredictedValue(Ra, Rb, Rc), (STRATEGY*)(NULL)); + index++; + } + else + { + index += DoRunMode(index, (STRATEGY*)(NULL)); + Rb = _previousLine[index-1]; + Rd = _previousLine[index]; + } + } +} + + +// DoLine: Encodes/Decodes a scanline of triplets in ILV_SAMPLE mode + +template +void JlsCodec::DoLine(Triplet*) +{ + LONG index = 0; + while(index < _width) + { + Triplet Ra = _currentLine[index -1]; + Triplet Rc = _previousLine[index-1]; + Triplet Rb = _previousLine[index]; + Triplet Rd = _previousLine[index + 1]; + + LONG Qs1 = ComputeContextID(QuantizeGratient(Rd.v1 - Rb.v1), QuantizeGratient(Rb.v1 - Rc.v1), QuantizeGratient(Rc.v1 - Ra.v1)); + LONG Qs2 = ComputeContextID(QuantizeGratient(Rd.v2 - Rb.v2), QuantizeGratient(Rb.v2 - Rc.v2), QuantizeGratient(Rc.v2 - Ra.v2)); + LONG Qs3 = ComputeContextID(QuantizeGratient(Rd.v3 - Rb.v3), QuantizeGratient(Rb.v3 - Rc.v3), QuantizeGratient(Rc.v3 - Ra.v3)); + + + if (Qs1 == 0 && Qs2 == 0 && Qs3 == 0) + { + index += DoRunMode(index, (STRATEGY*)(NULL)); + } + else + { + Triplet Rx; + Rx.v1 = DoRegular(Qs1, _currentLine[index].v1, GetPredictedValue(Ra.v1, Rb.v1, Rc.v1), (STRATEGY*)(NULL)); + Rx.v2 = DoRegular(Qs2, _currentLine[index].v2, GetPredictedValue(Ra.v2, Rb.v2, Rc.v2), (STRATEGY*)(NULL)); + Rx.v3 = DoRegular(Qs3, _currentLine[index].v3, GetPredictedValue(Ra.v3, Rb.v3, Rc.v3), (STRATEGY*)(NULL)); + _currentLine[index] = Rx; + index++; + } + } +} + + +// DoScan: Encodes or decodes a scan. +// In ILV_SAMPLE mode, multiple components are handled in DoLine +// In ILV_LINE mode, a call do DoLine is made for every component +// In ILV_NONE mode, DoScan is called for each component + +template +void JlsCodec::DoScan(BYTE* compressedBytes, size_t compressedLength) +{ + _width = Info().width; + + STRATEGY::Init(compressedBytes, compressedLength); + + LONG pixelstride = _width + 4; + int components = Info().ilv == ILV_LINE ? Info().components : 1; + + OFVector vectmp(2 * components * pixelstride); + OFVector rgRUNindex(components); + + for (LONG line = 0; line < Info().height; ++line) + { + _previousLine = &vectmp[1]; + _currentLine = &vectmp[1 + components * pixelstride]; + if ((line & 1) == 1) + { + PIXEL *tmp = _previousLine; + _previousLine = _currentLine; + _currentLine = tmp; + + } + + STRATEGY::OnLineBegin(_width, _currentLine, pixelstride); + + for (int component = 0; component < components; ++component) + { + _RUNindex = rgRUNindex[component]; + + // initialize edge pixels used for prediction + _previousLine[_width] = _previousLine[_width - 1]; + _currentLine[-1] = _previousLine[0]; + DoLine((PIXEL*) NULL); // dummy arg for overload resolution + + rgRUNindex[component] = _RUNindex; + _previousLine += pixelstride; + _currentLine += pixelstride; + } + + if (_rect.Y <= line && line < _rect.Y + _rect.Height) + { + STRATEGY::OnLineEnd(_rect.Width, _currentLine + _rect.X - (components * pixelstride), pixelstride); + } + } + + STRATEGY::EndScan(); +} + + +// Factory function for ProcessLine objects to copy/transform unencoded pixels to/from our scanline buffers. + +template +ProcessLine* JlsCodec::CreateProcess(void* pvoidOut) +{ + if (!IsInterleaved()) + return new PostProcesSingleComponent(pvoidOut, Info(), sizeof(typename TRAITS::PIXEL)); + + if (Info().colorTransform == 0) + return new ProcessTransformed >(pvoidOut, Info(), TransformNone()); + + if (Info().bitspersample == sizeof(SAMPLE)*8) + { + switch(Info().colorTransform) + { + case COLORXFORM_HP1 : return new ProcessTransformed >(pvoidOut, Info(), TransformHp1()); break; + case COLORXFORM_HP2 : return new ProcessTransformed >(pvoidOut, Info(), TransformHp2()); break; + case COLORXFORM_HP3 : return new ProcessTransformed >(pvoidOut, Info(), TransformHp3()); break; + default: throw JlsException(UnsupportedColorTransform); + } + } + else if (Info().bitspersample > 8) + { + int shift = 16 - Info().bitspersample; + switch(Info().colorTransform) + { + case COLORXFORM_HP1 : return new ProcessTransformed > >(pvoidOut, Info(), TransformShifted >(shift)); break; + case COLORXFORM_HP2 : return new ProcessTransformed > >(pvoidOut, Info(), TransformShifted >(shift)); break; + case COLORXFORM_HP3 : return new ProcessTransformed > >(pvoidOut, Info(), TransformShifted >(shift)); break; + default: throw JlsException(UnsupportedColorTransform); + } + } + throw JlsException(UnsupportedBitDepthForTransform); +} + + + +// Setup codec for encoding and calls DoScan + +template +size_t JlsCodec::EncodeScan(const void* rawData, void* compressedData, size_t compressedLength, void* pvoidCompare) +{ + STRATEGY::_processLine = OFauto_ptr(CreateProcess(const_cast(rawData))); + + BYTE* compressedBytes = static_cast(compressedData); + + if (pvoidCompare != NULL) + { + STRATEGY::_qdecoder = OFauto_ptr(new JlsCodec(traits, Info())); + STRATEGY::_qdecoder->Init((BYTE*)pvoidCompare, compressedLength); + } + + DoScan(compressedBytes, compressedLength); + + return STRATEGY::GetLength(); + +} + +// Setup codec for decoding and calls DoScan + +template +size_t JlsCodec::DecodeScan(void* rawData, const JlsRect& rect, const void* compressedData, size_t compressedLength, bool bCompare) +{ + STRATEGY::_processLine = OFauto_ptr(CreateProcess(rawData)); + + BYTE* compressedBytes = const_cast(static_cast(compressedData)); + _bCompare = bCompare; + + BYTE rgbyte[20]; + + size_t readBytes = 0; + ::memcpy(rgbyte, compressedBytes, 4); + readBytes += 4; + + size_t cbyteScanheader = rgbyte[3] - 2; + + if (cbyteScanheader > sizeof(rgbyte)) + throw JlsException(InvalidCompressedData); + + ::memcpy(rgbyte, compressedBytes, cbyteScanheader); + readBytes += cbyteScanheader; + + _rect = rect; + + DoScan(compressedBytes + readBytes, compressedLength - readBytes); + + return STRATEGY::GetCurBytePos() - compressedBytes; +} + +// Initialize the codec data structures. Depends on JPEG-LS parameters like T1-T3. + +template +void JlsCodec::InitParams(LONG t1, LONG t2, LONG t3, LONG nReset) +{ + T1 = t1; + T2 = t2; + T3 = t3; + + InitQuantizationLUT(); + + LONG A = MAX(2, (traits.RANGE + 32)/64); + for (unsigned int Q = 0; Q < sizeof(_contexts) / sizeof(_contexts[0]); ++Q) + { + _contexts[Q] = JlsContext(A); + } + + _contextRunmode[0] = CContextRunMode(MAX(2, (traits.RANGE + 32)/64), 0, nReset); + _contextRunmode[1] = CContextRunMode(MAX(2, (traits.RANGE + 32)/64), 1, nReset); + _RUNindex = 0; +} + +#endif diff --git a/dcmjpls/libcharls/streams.h b/dcmjpls/libcharls/streams.h new file mode 100644 index 00000000..ea8e8ceb --- /dev/null +++ b/dcmjpls/libcharls/streams.h @@ -0,0 +1,156 @@ +// +// (C) Jan de Vaan 2007-2010, all rights reserved. See the accompanying "License.txt" for licensed use. +// +#ifndef CHARLS_STREAMS +#define CHARLS_STREAMS + +#include "dcmtk/ofstd/ofvector.h" +#include "dcmtk/ofstd/ofbmanip.h" +#include "util.h" + + + +// This file defines JPEG-LS streams: The header and the actual pixel data. Header markers have fixed length, the pixeldata not. + + + +class JpegSegment; + +enum JPEGLS_ColorXForm +{ + // default (RGB) + COLORXFORM_NONE = 0, + + // Color transforms as defined by HP + COLORXFORM_HP1, + COLORXFORM_HP2, + COLORXFORM_HP3, + + // Defined by HP but not supported by CharLS + COLORXFORM_RGB_AS_YUV_LOSSY, + COLORXFORM_MATRIX +}; + +// +// JLSOutputStream: minimal implementation to write JPEG header streams +// +class JLSOutputStream +{ + friend class JpegMarkerSegment; + friend class JpegImageDataSegment; + +public: + JLSOutputStream(); + virtual ~JLSOutputStream(); + + void Init(Size size, LONG bitsPerSample, LONG ccomp); + void AddScan(const void* compareData, const JlsParameters* pparams); + void AddLSE(const JlsCustomParameters* pcustom); + void AddColorTransform(int i); + size_t GetBytesWritten() + { return _cbyteOffset; } + + size_t GetLength() + { return _cbyteLength - _cbyteOffset; } + + size_t Write(BYTE* pdata, size_t cbyteLength); + + void EnableCompare(bool bCompare) + { _bCompare = bCompare; } +private: + BYTE* GetPos() const + { return _pdata + _cbyteOffset; } + + void WriteByte(BYTE val) + { + ASSERT(!_bCompare || _pdata[_cbyteOffset] == val); + + _pdata[_cbyteOffset++] = val; + } + + void WriteBytes(const OFVector& rgbyte) + { + for (size_t i = 0; i < rgbyte.size(); ++i) + { + WriteByte(rgbyte[i]); + } + } + + void WriteWord(USHORT val) + { + WriteByte(BYTE(val / 0x100)); + WriteByte(BYTE(val % 0x100)); + } + + + void Seek(size_t byteCount) + { _cbyteOffset += byteCount; } + + bool _bCompare; + +private: + BYTE* _pdata; + size_t _cbyteOffset; + size_t _cbyteLength; + LONG _icompLast; + OFVector _segments; +}; + + +// +// JLSInputStream: minimal implementation to read JPEG header streams +// +class JLSInputStream +{ +public: + JLSInputStream(const BYTE* pdata, size_t cbyteLength); + + size_t GetBytesRead() + { return _cbyteOffset; } + + const JlsParameters& GetMetadata() const + { return _info; } + + const JlsCustomParameters& GetCustomPreset() const + { return _info.custom; } + + void Read(void* pvoid, size_t cbyteAvailable); + void ReadHeader(); + + void EnableCompare(bool bCompare) + { _bCompare = bCompare; } + + void SetInfo(JlsParameters* info) { _info = *info; } + + void SetRect(JlsRect rect) { _rect = rect; } + +private: + void ReadPixels(void* pvoid, size_t cbyteAvailable); + void ReadScan(void*); + void ReadStartOfScan(); + void ReadPresetParameters(); + void ReadComment(); + void ReadStartOfFrame(); + BYTE ReadByte(); + int ReadWord(); + void ReadNBytes(OFVector& dst, int byteCount); + + // JFIF + void ReadJfif(); + // Color Transform Application Markers & Code Stream (HP extension) + void ReadColorSpace(); + void ReadColorXForm(); + +private: + const BYTE* _pdata; + size_t _cbyteOffset; + size_t _cbyteLength; + bool _bCompare; + JlsParameters _info; + JlsRect _rect; +}; + + + + +#endif diff --git a/dcmjpls/libcharls/util.h b/dcmjpls/libcharls/util.h new file mode 100644 index 00000000..b2a02a4a --- /dev/null +++ b/dcmjpls/libcharls/util.h @@ -0,0 +1,152 @@ +// +// (C) Jan de Vaan 2007-2010, all rights reserved. See the accompanying "License.txt" for licensed use. +// + + +#ifndef CHARLS_UTIL +#define CHARLS_UTIL + +#define INCLUDE_CSTDDEF +#include "dcmtk/ofstd/ofstdinc.h" +#include "pubtypes.h" + +#ifndef MAX +#define MAX(a,b) (((a) > (b)) ? (a) : (b)) +#endif + +#ifndef MIN +#define MIN(a,b) (((a) < (b)) ? (a) : (b)) +#endif + +#ifndef ABS +#define ABS(a) (((a) > 0) ? (a) : -(a)) +#endif + + +inline LONG log_2(LONG n) +{ + LONG x = 0; + while (n > (LONG(1) << x)) + { + ++x; + } + return x; + +} + +struct Size +{ + Size(LONG width, LONG height) : + cx(width), + cy(height) + {} + LONG cx; + LONG cy; +}; + + + +inline LONG Sign(LONG n) + { return (n >> (LONG_BITCOUNT-1)) | 1;} + +inline LONG BitWiseSign(LONG i) + { return i >> (LONG_BITCOUNT-1); } + + +template +struct Triplet +{ + Triplet() : + v1(0), + v2(0), + v3(0) + {} + + Triplet(LONG x1, LONG x2, LONG x3) : + v1((SAMPLE)x1), + v2((SAMPLE)x2), + v3((SAMPLE)x3) + {} + + union + { + SAMPLE v1; + SAMPLE R; + }; + union + { + SAMPLE v2; + SAMPLE G; + }; + union + { + SAMPLE v3; + SAMPLE B; + }; +}; + +inline bool operator==(const Triplet& lhs, const Triplet& rhs) + { return lhs.v1 == rhs.v1 && lhs.v2 == rhs.v2 && lhs.v3 == rhs.v3; } + +inline bool operator!=(const Triplet& lhs, const Triplet& rhs) + { return !(lhs == rhs); } + + +template +struct Quad : public Triplet +{ + Quad() : + v4(0) + {} + + Quad(Triplet triplet, LONG alpha) : Triplet(triplet), A((sample)alpha) + {} + + union + { + sample v4; + sample A; + }; +}; + + + +template +struct FromBigEndian +{ +}; + +template <> +struct FromBigEndian<4> +{ + inlinehint static unsigned int Read(BYTE* pbyte) + { + return (pbyte[0] << 24) + (pbyte[1] << 16) + (pbyte[2] << 8) + (pbyte[3] << 0); + } +}; + + + +template <> +struct FromBigEndian<8> +{ + inlinehint static size_t Read(BYTE* pbyte) + { + size_t a = FromBigEndian<4>::Read(&pbyte[0]); + size_t b = FromBigEndian<4>::Read(&pbyte[4]); + return ((a << 16) << 16) + b; + } +}; + + +class JlsException +{ +public: + JlsException(JLS_ERROR error) : _error(error) + { } + + JLS_ERROR _error; +}; + + +#endif diff --git a/dcmjpls/libsrc/CMakeLists.txt b/dcmjpls/libsrc/CMakeLists.txt new file mode 100644 index 00000000..8a7b4e89 --- /dev/null +++ b/dcmjpls/libsrc/CMakeLists.txt @@ -0,0 +1,7 @@ +# declare additional include directories +INCLUDE_DIRECTORIES(${dcmjpls_SOURCE_DIR}/include ${ofstd_SOURCE_DIR}/include ${oflog_SOURCE_DIR}/include ${dcmdata_SOURCE_DIR}/include ${dcmimgle_SOURCE_DIR}/include ${dcmimage_SOURCE_DIR}/include ${dcmjpls_SOURCE_DIR}/libcharls ${ZLIB_INCDIR}) + +# create library from source files +DCMTK_ADD_LIBRARY(dcmjpls djcparam djdecode djencode djrparam djcodecd djutils djcodece) + +DCMTK_TARGET_LINK_MODULES(dcmjpls ofstd oflog dcmdata dcmimgle dcmimage charls) diff --git a/dcmjpls/libsrc/Makefile.dep b/dcmjpls/libsrc/Makefile.dep new file mode 100644 index 00000000..74e6ae3b --- /dev/null +++ b/dcmjpls/libsrc/Makefile.dep @@ -0,0 +1,412 @@ +djcodecd.o: djcodecd.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmjpls/djcodecd.h \ + ../../dcmdata/include/dcmtk/dcmdata/dccodec.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../include/dcmtk/dcmjpls/dldefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixseq.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcofsetl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpxitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpobw.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ + ../include/dcmtk/dcmjpls/djcparam.h ../include/dcmtk/dcmjpls/djlsutil.h \ + djerror.h ../../dcmjpls/libcharls/intrface.h \ + ../../dcmjpls/libcharls/pubtypes.h ../../dcmjpls/libcharls/config.h +djcodece.o: djcodece.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmjpls/djcodece.h \ + ../../dcmdata/include/dcmtk/dcmdata/dccodec.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcofsetl.h \ + ../include/dcmtk/dcmjpls/dldefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofbmanip.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcovlay.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpobw.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixseq.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpxitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrds.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlt.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcchrstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrst.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrus.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ + ../include/dcmtk/dcmjpls/djcparam.h ../include/dcmtk/dcmjpls/djlsutil.h \ + ../include/dcmtk/dcmjpls/djrparam.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixel.h djerror.h \ + ../../dcmjpls/libcharls/intrface.h ../../dcmjpls/libcharls/pubtypes.h \ + ../../dcmjpls/libcharls/config.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/dcmimage.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/dimoimg.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diimage.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diovlay.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diobjcou.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/didefine.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diovdat.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diovpln.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diutils.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/dimopx.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/dipixel.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/dimomod.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diluptab.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/dibaslut.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/dimoopx.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/didispfn.h +djcparam.o: djcparam.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmjpls/djcparam.h \ + ../../dcmdata/include/dcmtk/dcmdata/dccodec.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../include/dcmtk/dcmjpls/djlsutil.h ../include/dcmtk/dcmjpls/dldefine.h +djdecode.o: djdecode.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmjpls/djdecode.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../include/dcmtk/dcmjpls/djlsutil.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../include/dcmtk/dcmjpls/dldefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dccodec.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../include/dcmtk/dcmjpls/djcparam.h ../include/dcmtk/dcmjpls/djcodecd.h +djencode.o: djencode.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmjpls/djencode.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../include/dcmtk/dcmjpls/djlsutil.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../include/dcmtk/dcmjpls/dldefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../include/dcmtk/dcmjpls/djcparam.h \ + ../../dcmdata/include/dcmtk/dcmdata/dccodec.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../include/dcmtk/dcmjpls/djcodece.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcofsetl.h +djrparam.o: djrparam.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmjpls/djrparam.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixel.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpobw.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../include/dcmtk/dcmjpls/dldefine.h +djutils.o: djutils.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmjpls/djlsutil.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../include/dcmtk/dcmjpls/dldefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h diff --git a/dcmjpls/libsrc/Makefile.in b/dcmjpls/libsrc/Makefile.in new file mode 100644 index 00000000..21752238 --- /dev/null +++ b/dcmjpls/libsrc/Makefile.in @@ -0,0 +1,53 @@ +# +# Makefile for dcmjpls/libsrc +# + +@SET_MAKE@ + +SHELL = /bin/sh +VPATH = @srcdir@:@top_srcdir@/include:@top_srcdir@/@configdir@/include +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +configdir = @top_srcdir@/@configdir@ + +include $(configdir)/@common_makefile@ + +ofstddir = $(top_srcdir)/../ofstd +oflogdir = $(top_srcdir)/../oflog +dcmdatadir = $(top_srcdir)/../dcmdata +dcmimgledir = $(top_srcdir)/../dcmimgle +libcharlsdir = $(top_srcdir)/../dcmjpls/libcharls + +LOCALINCLUDES = -I$(ofstddir)/include -I$(oflogdir)/include -I$(dcmdatadir)/include \ + -I$(dcmimgledir)/include -I$(libcharlsdir) +LOCALDEFS = + +objs = djcodecd.o djcodece.o djcparam.o djdecode.o djencode.o djrparam.o djutils.o + +library = libdcmjpls.$(LIBEXT) + + +all: $(library) + +install: all + $(configdir)/mkinstalldirs $(DESTDIR)$(libdir) + $(INSTALL_DATA) $(library) $(DESTDIR)$(libdir)/$(library) + $(RANLIB) $(DESTDIR)$(libdir)/$(library) + + +$(library): $(objs) + $(AR) $(ARFLAGS) $@ $(objs) + $(RANLIB) $@ + + +clean: + rm -f $(objs) $(library) $(TRASH) + +distclean: + rm -f $(objs) $(library) $(DISTTRASH) + + +dependencies: + $(CXX) -MM $(defines) $(includes) $(CPPFLAGS) $(CXXFLAGS) *.cc > $(DEP) + +include $(DEP) diff --git a/dcmjpls/libsrc/djcodecd.cc b/dcmjpls/libsrc/djcodecd.cc new file mode 100644 index 00000000..a6c0c6fe --- /dev/null +++ b/dcmjpls/libsrc/djcodecd.cc @@ -0,0 +1,742 @@ +/* + * + * Copyright (C) 2007-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmjpls + * + * Author: Martin Willkomm, Marco Eichelberg, Uli Schlachter + * + * Purpose: codec classes for JPEG-LS decoders. + * + */ + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmjpls/djcodecd.h" + +#include "dcmtk/ofstd/ofstream.h" /* for ofstream */ +#include "dcmtk/ofstd/ofcast.h" /* for casts */ +#include "dcmtk/ofstd/offile.h" /* for class OFFile */ +#include "dcmtk/ofstd/ofstd.h" /* for class OFStandard */ +#include "dcmtk/dcmdata/dcdatset.h" /* for class DcmDataset */ +#include "dcmtk/dcmdata/dcdeftag.h" /* for tag constants */ +#include "dcmtk/dcmdata/dcpixseq.h" /* for class DcmPixelSequence */ +#include "dcmtk/dcmdata/dcpxitem.h" /* for class DcmPixelItem */ +#include "dcmtk/dcmdata/dcvrpobw.h" /* for class DcmPolymorphOBOW */ +#include "dcmtk/dcmdata/dcswap.h" /* for swapIfNecessary() */ +#include "dcmtk/dcmdata/dcuid.h" /* for dcmGenerateUniqueIdentifer()*/ +#include "dcmtk/dcmjpls/djcparam.h" /* for class DJLSCodecParameter */ +#include "djerror.h" /* for private class DJLSError */ + +// JPEG-LS library (CharLS) includes +#include "intrface.h" + +E_TransferSyntax DJLSLosslessDecoder::supportedTransferSyntax() const +{ + return EXS_JPEGLSLossless; +} + +E_TransferSyntax DJLSNearLosslessDecoder::supportedTransferSyntax() const +{ + return EXS_JPEGLSLossy; +} + +// -------------------------------------------------------------------------- + +DJLSDecoderBase::DJLSDecoderBase() +: DcmCodec() +{ +} + + +DJLSDecoderBase::~DJLSDecoderBase() +{ +} + + +OFBool DJLSDecoderBase::canChangeCoding( + const E_TransferSyntax oldRepType, + const E_TransferSyntax newRepType) const +{ + // this codec only handles conversion from JPEG-LS to uncompressed. + + DcmXfer newRep(newRepType); + if (newRep.isNotEncapsulated() && + ((oldRepType == EXS_JPEGLSLossless)||(oldRepType == EXS_JPEGLSLossy))) + return OFTrue; + + return OFFalse; +} + + +OFCondition DJLSDecoderBase::decode( + const DcmRepresentationParameter * /* fromRepParam */, + DcmPixelSequence * pixSeq, + DcmPolymorphOBOW& uncompressedPixelData, + const DcmCodecParameter * cp, + const DcmStack& objStack) const +{ + // retrieve pointer to dataset from parameter stack + DcmStack localStack(objStack); + (void)localStack.pop(); // pop pixel data element from stack + DcmObject *dobject = localStack.pop(); // this is the item in which the pixel data is located + if ((!dobject)||((dobject->ident()!= EVR_dataset) && (dobject->ident()!= EVR_item))) return EC_InvalidTag; + DcmItem *dataset = OFstatic_cast(DcmItem *, dobject); + OFBool numberOfFramesPresent = OFFalse; + + // determine properties of uncompressed dataset + Uint16 imageSamplesPerPixel = 0; + if (dataset->findAndGetUint16(DCM_SamplesPerPixel, imageSamplesPerPixel).bad()) return EC_TagNotFound; + // we only handle one or three samples per pixel + if ((imageSamplesPerPixel != 3) && (imageSamplesPerPixel != 1)) return EC_InvalidTag; + + Uint16 imageRows = 0; + if (dataset->findAndGetUint16(DCM_Rows, imageRows).bad()) return EC_TagNotFound; + if (imageRows < 1) return EC_InvalidTag; + + Uint16 imageColumns = 0; + if (dataset->findAndGetUint16(DCM_Columns, imageColumns).bad()) return EC_TagNotFound; + if (imageColumns < 1) return EC_InvalidTag; + + // number of frames is an optional attribute - we don't mind if it isn't present. + Sint32 imageFrames = 0; + if (dataset->findAndGetSint32(DCM_NumberOfFrames, imageFrames).good()) numberOfFramesPresent = OFTrue; + + if (imageFrames >= OFstatic_cast(Sint32, pixSeq->card())) + imageFrames = pixSeq->card() - 1; // limit number of frames to number of pixel items - 1 + if (imageFrames < 1) + imageFrames = 1; // default in case the number of frames attribute is absent or contains garbage + + Uint16 imageBitsStored = 0; + if (dataset->findAndGetUint16(DCM_BitsStored, imageBitsStored).bad()) return EC_TagNotFound; + + Uint16 imageBitsAllocated = 0; + if (dataset->findAndGetUint16(DCM_BitsAllocated, imageBitsAllocated).bad()) return EC_TagNotFound; + + Uint16 imageHighBit = 0; + if (dataset->findAndGetUint16(DCM_HighBit, imageHighBit).bad()) return EC_TagNotFound; + + //we only support up to 16 bits per sample + if ((imageBitsStored < 1) || (imageBitsStored > 16)) return EC_JLSUnsupportedBitDepth; + + // determine the number of bytes per sample (bits allocated) for the de-compressed object. + Uint16 bytesPerSample = 1; + if (imageBitsStored > 8) bytesPerSample = 2; + else if (imageBitsAllocated > 8) bytesPerSample = 2; + + // compute size of uncompressed frame, in bytes + Uint32 frameSize = bytesPerSample * imageRows * imageColumns * imageSamplesPerPixel; + + // compute size of pixel data attribute, in bytes + Uint32 totalSize = frameSize * imageFrames; + if (totalSize & 1) totalSize++; // align on 16-bit word boundary + + // assume we can cast the codec parameter to what we need + const DJLSCodecParameter *djcp = OFreinterpret_cast(const DJLSCodecParameter *, cp); + + // determine planar configuration for uncompressed data + OFString imageSopClass; + OFString imagePhotometricInterpretation; + dataset->findAndGetOFString(DCM_SOPClassUID, imageSopClass); + dataset->findAndGetOFString(DCM_PhotometricInterpretation, imagePhotometricInterpretation); + + // allocate space for uncompressed pixel data element + Uint16 *pixeldata16 = NULL; + OFCondition result = uncompressedPixelData.createUint16Array(totalSize/sizeof(Uint16), pixeldata16); + if (result.bad()) return result; + + Uint8 *pixeldata8 = OFreinterpret_cast(Uint8 *, pixeldata16); + Sint32 currentFrame = 0; + Uint32 currentItem = 1; // item 0 contains the offset table + OFBool done = OFFalse; + + while (result.good() && !done) + { + DCMJPLS_DEBUG("JPEG-LS decoder processes frame " << (currentFrame+1)); + + result = decodeFrame(pixSeq, djcp, dataset, currentFrame, currentItem, pixeldata8, frameSize, + imageFrames, imageColumns, imageRows, imageSamplesPerPixel, bytesPerSample); + + if (result.good()) + { + // increment frame number, check if we're finished + if (++currentFrame == imageFrames) done = OFTrue; + pixeldata8 += frameSize; + } + } + + // Number of Frames might have changed in case the previous value was wrong + if (result.good() && (numberOfFramesPresent || (imageFrames > 1))) + { + char numBuf[20]; + sprintf(numBuf, "%ld", OFstatic_cast(long, imageFrames)); + result = ((DcmItem *)dataset)->putAndInsertString(DCM_NumberOfFrames, numBuf); + } + + if (result.good()) + { + // the following operations do not affect the Image Pixel Module + // but other modules such as SOP Common. We only perform these + // changes if we're on the main level of the dataset, + // which should always identify itself as dataset, not as item. + if ((dataset->ident() == EVR_dataset) && (djcp->getUIDCreation() == EJLSUC_always)) + { + // create new SOP instance UID + result = DcmCodec::newInstance((DcmItem *)dataset, NULL, NULL, NULL); + } + } + + return result; +} + + +OFCondition DJLSDecoderBase::decodeFrame( + const DcmRepresentationParameter * /* fromParam */, + DcmPixelSequence *fromPixSeq, + const DcmCodecParameter *cp, + DcmItem *dataset, + Uint32 frameNo, + Uint32& currentItem, + void * buffer, + Uint32 bufSize, + OFString& decompressedColorModel) const +{ + OFCondition result = EC_Normal; + + // assume we can cast the codec parameter to what we need + const DJLSCodecParameter *djcp = OFreinterpret_cast(const DJLSCodecParameter *, cp); + + // determine properties of uncompressed dataset + Uint16 imageSamplesPerPixel = 0; + if (dataset->findAndGetUint16(DCM_SamplesPerPixel, imageSamplesPerPixel).bad()) return EC_TagNotFound; + // we only handle one or three samples per pixel + if ((imageSamplesPerPixel != 3) && (imageSamplesPerPixel != 1)) return EC_InvalidTag; + + Uint16 imageRows = 0; + if (dataset->findAndGetUint16(DCM_Rows, imageRows).bad()) return EC_TagNotFound; + if (imageRows < 1) return EC_InvalidTag; + + Uint16 imageColumns = 0; + if (dataset->findAndGetUint16(DCM_Columns, imageColumns).bad()) return EC_TagNotFound; + if (imageColumns < 1) return EC_InvalidTag; + + Uint16 imageBitsStored = 0; + if (dataset->findAndGetUint16(DCM_BitsStored, imageBitsStored).bad()) return EC_TagNotFound; + + Uint16 imageBitsAllocated = 0; + if (dataset->findAndGetUint16(DCM_BitsAllocated, imageBitsAllocated).bad()) return EC_TagNotFound; + + //we only support up to 16 bits per sample + if ((imageBitsStored < 1) || (imageBitsStored > 16)) return EC_JLSUnsupportedBitDepth; + + // determine the number of bytes per sample (bits allocated) for the de-compressed object. + Uint16 bytesPerSample = 1; + if (imageBitsStored > 8) bytesPerSample = 2; + else if (imageBitsAllocated > 8) bytesPerSample = 2; + + // number of frames is an optional attribute - we don't mind if it isn't present. + Sint32 imageFrames = 0; + dataset->findAndGetSint32(DCM_NumberOfFrames, imageFrames).good(); + + if (imageFrames >= OFstatic_cast(Sint32, fromPixSeq->card())) + imageFrames = fromPixSeq->card() - 1; // limit number of frames to number of pixel items - 1 + if (imageFrames < 1) + imageFrames = 1; // default in case the number of frames attribute is absent or contains garbage + + // if the user has provided this information, we trust him. + // If the user has passed a zero, try to find out ourselves. + if (currentItem == 0) + { + result = determineStartFragment(frameNo, imageFrames, fromPixSeq, currentItem); + } + + if (result.good()) + { + // We got all the data we need from the dataset, let's start decoding + DCMJPLS_DEBUG("Starting to decode frame " << frameNo << " with fragment " << currentItem); + result = decodeFrame(fromPixSeq, djcp, dataset, frameNo, currentItem, buffer, bufSize, + imageFrames, imageColumns, imageRows, imageSamplesPerPixel, bytesPerSample); + } + + if (result.good()) + { + // retrieve color model from given dataset + result = dataset->findAndGetOFString(DCM_PhotometricInterpretation, decompressedColorModel); + } + + return result; +} + +OFCondition DJLSDecoderBase::decodeFrame( + DcmPixelSequence * fromPixSeq, + const DJLSCodecParameter *cp, + DcmItem *dataset, + Uint32 frameNo, + Uint32& currentItem, + void * buffer, + Uint32 bufSize, + Sint32 imageFrames, + Uint16 imageColumns, + Uint16 imageRows, + Uint16 imageSamplesPerPixel, + Uint16 bytesPerSample) +{ + DcmPixelItem *pixItem = NULL; + Uint8 * jlsData = NULL; + Uint8 * jlsFragmentData = NULL; + Uint32 fragmentLength = 0; + size_t compressedSize = 0; + Uint32 fragmentsForThisFrame = 0; + OFCondition result = EC_Normal; + OFBool ignoreOffsetTable = cp->ignoreOffsetTable(); + + // compute the number of JPEG-LS fragments we need in order to decode the next frame + fragmentsForThisFrame = computeNumberOfFragments(imageFrames, frameNo, currentItem, ignoreOffsetTable, fromPixSeq); + if (fragmentsForThisFrame == 0) result = EC_JLSCannotComputeNumberOfFragments; + + // determine planar configuration for uncompressed data + OFString imageSopClass; + OFString imagePhotometricInterpretation; + dataset->findAndGetOFString(DCM_SOPClassUID, imageSopClass); + dataset->findAndGetOFString(DCM_PhotometricInterpretation, imagePhotometricInterpretation); + Uint16 imagePlanarConfiguration = 0; // 0 is color-by-pixel, 1 is color-by-plane + + if (imageSamplesPerPixel > 1) + { + switch (cp->getPlanarConfiguration()) + { + case EJLSPC_restore: + // get planar configuration from dataset + imagePlanarConfiguration = 2; // invalid value + dataset->findAndGetUint16(DCM_PlanarConfiguration, imagePlanarConfiguration); + // determine auto default if not found or invalid + if (imagePlanarConfiguration > 1) + imagePlanarConfiguration = determinePlanarConfiguration(imageSopClass, imagePhotometricInterpretation); + break; + case EJLSPC_auto: + imagePlanarConfiguration = determinePlanarConfiguration(imageSopClass, imagePhotometricInterpretation); + break; + case EJLSPC_colorByPixel: + imagePlanarConfiguration = 0; + break; + case EJLSPC_colorByPlane: + imagePlanarConfiguration = 1; + break; + } + } + + // get the size of all the fragments + if (result.good()) + { + // Don't modify the original values for now + Uint32 fragmentsForThisFrame2 = fragmentsForThisFrame; + Uint32 currentItem2 = currentItem; + + while (result.good() && fragmentsForThisFrame2--) + { + result = fromPixSeq->getItem(pixItem, currentItem2++); + if (result.good() && pixItem) + { + fragmentLength = pixItem->getLength(); + if (result.good()) + compressedSize += fragmentLength; + } + } /* while */ + } + + // get the compressed data + if (result.good()) + { + Uint32 offset = 0; + jlsData = new Uint8[compressedSize]; + + while (result.good() && fragmentsForThisFrame--) + { + result = fromPixSeq->getItem(pixItem, currentItem++); + if (result.good() && pixItem) + { + fragmentLength = pixItem->getLength(); + result = pixItem->getUint8Array(jlsFragmentData); + if (result.good() && jlsFragmentData) + { + memcpy(&jlsData[offset], jlsFragmentData, fragmentLength); + offset += fragmentLength; + } + } + } /* while */ + } + + if (result.good()) + { + JlsParameters params; + JLS_ERROR err; + + err = JpegLsReadHeader(jlsData, compressedSize, ¶ms); + result = DJLSError::convert(err); + + if (result.good()) + { + if (params.width != imageColumns) result = EC_JLSImageDataMismatch; + else if (params.height != imageRows) result = EC_JLSImageDataMismatch; + else if (params.components != imageSamplesPerPixel) result = EC_JLSImageDataMismatch; + else if ((bytesPerSample == 1) && (params.bitspersample > 8)) result = EC_JLSImageDataMismatch; + else if ((bytesPerSample == 2) && (params.bitspersample <= 8)) result = EC_JLSImageDataMismatch; + } + + if (!result.good()) + { + delete[] jlsData; + } + else + { + err = JpegLsDecode(buffer, bufSize, jlsData, compressedSize, ¶ms); + result = DJLSError::convert(err); + delete[] jlsData; + + if (result.good() && imageSamplesPerPixel == 3) + { + if (imagePlanarConfiguration == 1 && params.ilv != ILV_NONE) + { + // The dataset says this should be planarConfiguration == 1, but + // it isn't -> convert it. + DCMJPLS_WARN("different planar configuration in JPEG stream, converting to \"1\""); + if (bytesPerSample == 1) + result = createPlanarConfiguration1Byte(OFreinterpret_cast(Uint8*, buffer), imageColumns, imageRows); + else + result = createPlanarConfiguration1Word(OFreinterpret_cast(Uint16*, buffer), imageColumns, imageRows); + } + else if (imagePlanarConfiguration == 0 && params.ilv != ILV_SAMPLE && params.ilv != ILV_LINE) + { + // The dataset says this should be planarConfiguration == 0, but + // it isn't -> convert it. + DCMJPLS_WARN("different planar configuration in JPEG stream, converting to \"0\""); + if (bytesPerSample == 1) + result = createPlanarConfiguration0Byte(OFreinterpret_cast(Uint8*, buffer), imageColumns, imageRows); + else + result = createPlanarConfiguration0Word(OFreinterpret_cast(Uint16*, buffer), imageColumns, imageRows); + } + } + + if (result.good()) + { + // decompression is complete, finally adjust byte order if necessary + if (bytesPerSample == 1) // we're writing bytes into words + { + result = swapIfNecessary(gLocalByteOrder, EBO_LittleEndian, buffer, + bufSize, sizeof(Uint16)); + } + } + } + } + + return result; +} + + +OFCondition DJLSDecoderBase::encode( + const Uint16 * /* pixelData */, + const Uint32 /* length */, + const DcmRepresentationParameter * /* toRepParam */, + DcmPixelSequence * & /* pixSeq */, + const DcmCodecParameter * /* cp */, + DcmStack & /* objStack */) const +{ + // we are a decoder only + return EC_IllegalCall; +} + + +OFCondition DJLSDecoderBase::encode( + const E_TransferSyntax /* fromRepType */, + const DcmRepresentationParameter * /* fromRepParam */, + DcmPixelSequence * /* fromPixSeq */, + const DcmRepresentationParameter * /* toRepParam */, + DcmPixelSequence * & /* toPixSeq */, + const DcmCodecParameter * /* cp */, + DcmStack & /* objStack */) const +{ + // we don't support re-coding for now. + return EC_IllegalCall; +} + + +OFCondition DJLSDecoderBase::determineDecompressedColorModel( + const DcmRepresentationParameter * /* fromParam */, + DcmPixelSequence * /* fromPixSeq */, + const DcmCodecParameter * /* cp */, + DcmItem * dataset, + OFString & decompressedColorModel) const +{ + OFCondition result = EC_IllegalParameter; + if (dataset != NULL) + { + // retrieve color model from given dataset + result = dataset->findAndGetOFString(DCM_PhotometricInterpretation, decompressedColorModel); + } + return result; +} + + +Uint16 DJLSDecoderBase::determinePlanarConfiguration( + const OFString& sopClassUID, + const OFString& photometricInterpretation) +{ + // Hardcopy Color Image always requires color-by-plane + if (sopClassUID == UID_RETIRED_HardcopyColorImageStorage) return 1; + + // The 1996 Ultrasound Image IODs require color-by-plane if color model is YBR_FULL. + if (photometricInterpretation == "YBR_FULL") + { + if ((sopClassUID == UID_UltrasoundMultiframeImageStorage) + ||(sopClassUID == UID_UltrasoundImageStorage)) return 1; + } + + // default for all other cases + return 0; +} + +Uint32 DJLSDecoderBase::computeNumberOfFragments( + Sint32 numberOfFrames, + Uint32 currentFrame, + Uint32 startItem, + OFBool ignoreOffsetTable, + DcmPixelSequence * pixSeq) +{ + + unsigned long numItems = pixSeq->card(); + DcmPixelItem *pixItem = NULL; + + // We first check the simple cases, that is, a single-frame image, + // the last frame of a multi-frame image and the standard case where we do have + // a single fragment per frame. + if ((numberOfFrames <= 1) || (currentFrame + 1 == OFstatic_cast(Uint32, numberOfFrames))) + { + // single-frame image or last frame. All remaining fragments belong to this frame + return (numItems - startItem); + } + if (OFstatic_cast(Uint32, numberOfFrames + 1) == numItems) + { + // multi-frame image with one fragment per frame + return 1; + } + + OFCondition result = EC_Normal; + if (! ignoreOffsetTable) + { + // We do have a multi-frame image with multiple fragments per frame, and we are + // not working on the last frame. Let's check the offset table if present. + result = pixSeq->getItem(pixItem, 0); + if (result.good() && pixItem) + { + Uint32 offsetTableLength = pixItem->getLength(); + if (offsetTableLength == (OFstatic_cast(Uint32, numberOfFrames) * 4)) + { + // offset table is non-empty and contains one entry per frame + Uint8 *offsetData = NULL; + result = pixItem->getUint8Array(offsetData); + if (result.good() && offsetData) + { + // now we can access the offset table + Uint32 *offsetData32 = OFreinterpret_cast(Uint32 *, offsetData); + + // extract the offset for the NEXT frame. This offset is guaranteed to exist + // because the "last frame/single frame" case is handled above. + Uint32 offset = offsetData32[currentFrame+1]; + + // convert to local endian byte order (always little endian in file) + swapIfNecessary(gLocalByteOrder, EBO_LittleEndian, &offset, sizeof(Uint32), sizeof(Uint32)); + + // determine index of start fragment for next frame + Uint32 byteCount = 0; + Uint32 fragmentIndex = 1; + while ((byteCount < offset) && (fragmentIndex < numItems)) + { + pixItem = NULL; + result = pixSeq->getItem(pixItem, fragmentIndex++); + if (result.good() && pixItem) + { + byteCount += pixItem->getLength() + 8; // add 8 bytes for item tag and length + if ((byteCount == offset) && (fragmentIndex > startItem)) + { + // bingo, we have found the offset for the next frame + return fragmentIndex - startItem; + } + } + else break; /* something went wrong, break out of while loop */ + } /* while */ + } + } + } + } + + // So we have a multi-frame image with multiple fragments per frame and the + // offset table is empty or wrong. Our last chance is to peek into the JPEG-LS + // bistream and identify the start of the next frame. + Uint32 nextItem = startItem; + Uint8 *fragmentData = NULL; + while (++nextItem < numItems) + { + pixItem = NULL; + result = pixSeq->getItem(pixItem, nextItem); + if (result.good() && pixItem) + { + fragmentData = NULL; + result = pixItem->getUint8Array(fragmentData); + if (result.good() && fragmentData && (pixItem->getLength() > 3)) + { + if (isJPEGLSStartOfImage(fragmentData)) + { + // found a JPEG-LS SOI marker. Assume that this is the start of the next frame. + return (nextItem - startItem); + } + } + else break; /* something went wrong, break out of while loop */ + } + else break; /* something went wrong, break out of while loop */ + } + + // We're bust. No way to determine the number of fragments per frame. + return 0; +} + + +OFBool DJLSDecoderBase::isJPEGLSStartOfImage(Uint8 *fragmentData) +{ + // A valid JPEG-LS bitstream will always start with an SOI marker FFD8, followed + // by either an SOF55 (FFF7), COM (FFFE) or APPn (FFE0-FFEF) marker. + if ((*fragmentData++) != 0xFF) return OFFalse; + if ((*fragmentData++) != 0xD8) return OFFalse; + if ((*fragmentData++) != 0xFF) return OFFalse; + if ((*fragmentData == 0xF7)||(*fragmentData == 0xFE)||((*fragmentData & 0xF0) == 0xE0)) + { + return OFTrue; + } + return OFFalse; +} + + +OFCondition DJLSDecoderBase::createPlanarConfiguration1Byte( + Uint8 *imageFrame, + Uint16 columns, + Uint16 rows) +{ + if (imageFrame == NULL) return EC_IllegalCall; + + unsigned long numPixels = columns * rows; + if (numPixels == 0) return EC_IllegalCall; + + Uint8 *buf = new Uint8[3*numPixels + 3]; + if (buf) + { + memcpy(buf, imageFrame, (size_t)(3*numPixels)); + register Uint8 *s = buf; // source + register Uint8 *r = imageFrame; // red plane + register Uint8 *g = imageFrame + numPixels; // green plane + register Uint8 *b = imageFrame + (2*numPixels); // blue plane + for (register unsigned long i=numPixels; i; i--) + { + *r++ = *s++; + *g++ = *s++; + *b++ = *s++; + } + delete[] buf; + } else return EC_MemoryExhausted; + return EC_Normal; +} + + +OFCondition DJLSDecoderBase::createPlanarConfiguration1Word( + Uint16 *imageFrame, + Uint16 columns, + Uint16 rows) +{ + if (imageFrame == NULL) return EC_IllegalCall; + + unsigned long numPixels = columns * rows; + if (numPixels == 0) return EC_IllegalCall; + + Uint16 *buf = new Uint16[3*numPixels + 3]; + if (buf) + { + memcpy(buf, imageFrame, (size_t)(3*numPixels*sizeof(Uint16))); + register Uint16 *s = buf; // source + register Uint16 *r = imageFrame; // red plane + register Uint16 *g = imageFrame + numPixels; // green plane + register Uint16 *b = imageFrame + (2*numPixels); // blue plane + for (register unsigned long i=numPixels; i; i--) + { + *r++ = *s++; + *g++ = *s++; + *b++ = *s++; + } + delete[] buf; + } else return EC_MemoryExhausted; + return EC_Normal; +} + +OFCondition DJLSDecoderBase::createPlanarConfiguration0Byte( + Uint8 *imageFrame, + Uint16 columns, + Uint16 rows) +{ + if (imageFrame == NULL) return EC_IllegalCall; + + unsigned long numPixels = columns * rows; + if (numPixels == 0) return EC_IllegalCall; + + Uint8 *buf = new Uint8[3*numPixels + 3]; + if (buf) + { + memcpy(buf, imageFrame, (size_t)(3*numPixels)); + register Uint8 *t = imageFrame; // target + register Uint8 *r = buf; // red plane + register Uint8 *g = buf + numPixels; // green plane + register Uint8 *b = buf + (2*numPixels); // blue plane + for (register unsigned long i=numPixels; i; i--) + { + *t++ = *r++; + *t++ = *g++; + *t++ = *b++; + } + delete[] buf; + } else return EC_MemoryExhausted; + return EC_Normal; +} + + +OFCondition DJLSDecoderBase::createPlanarConfiguration0Word( + Uint16 *imageFrame, + Uint16 columns, + Uint16 rows) +{ + if (imageFrame == NULL) return EC_IllegalCall; + + unsigned long numPixels = columns * rows; + if (numPixels == 0) return EC_IllegalCall; + + Uint16 *buf = new Uint16[3*numPixels + 3]; + if (buf) + { + memcpy(buf, imageFrame, (size_t)(3*numPixels*sizeof(Uint16))); + register Uint16 *t = imageFrame; // target + register Uint16 *r = buf; // red plane + register Uint16 *g = buf + numPixels; // green plane + register Uint16 *b = buf + (2*numPixels); // blue plane + for (register unsigned long i=numPixels; i; i--) + { + *t++ = *r++; + *t++ = *g++; + *t++ = *b++; + } + delete[] buf; + } else return EC_MemoryExhausted; + return EC_Normal; +} diff --git a/dcmjpls/libsrc/djcodece.cc b/dcmjpls/libsrc/djcodece.cc new file mode 100644 index 00000000..261fec82 --- /dev/null +++ b/dcmjpls/libsrc/djcodece.cc @@ -0,0 +1,1133 @@ +/* + * + * Copyright (C) 2007-2015, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmjpls + * + * Author: Martin Willkomm, Marco Eichelberg, Uli Schlachter + * + * Purpose: codec classes for JPEG-LS encoders. + * + */ + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmjpls/djcodece.h" + +// ofstd includes +#include "dcmtk/ofstd/oflist.h" +#include "dcmtk/ofstd/ofstd.h" +#include "dcmtk/ofstd/ofstream.h" +#include "dcmtk/ofstd/offile.h" /* for class OFFile */ +#include "dcmtk/ofstd/ofbmanip.h" + +#define INCLUDE_CMATH +#include "dcmtk/ofstd/ofstdinc.h" + +// dcmdata includes +#include "dcmtk/dcmdata/dcdatset.h" /* for class DcmDataset */ +#include "dcmtk/dcmdata/dcdeftag.h" /* for tag constants */ +#include "dcmtk/dcmdata/dcovlay.h" /* for class DcmOverlayData */ +#include "dcmtk/dcmdata/dcpixseq.h" /* for class DcmPixelSequence */ +#include "dcmtk/dcmdata/dcpxitem.h" /* for class DcmPixelItem */ +#include "dcmtk/dcmdata/dcuid.h" /* for dcmGenerateUniqueIdentifer()*/ +#include "dcmtk/dcmdata/dcvrcs.h" /* for class DcmCodeString */ +#include "dcmtk/dcmdata/dcvrds.h" /* for class DcmDecimalString */ +#include "dcmtk/dcmdata/dcvrlt.h" /* for class DcmLongText */ +#include "dcmtk/dcmdata/dcvrst.h" /* for class DcmShortText */ +#include "dcmtk/dcmdata/dcvrus.h" /* for class DcmUnsignedShort */ +#include "dcmtk/dcmdata/dcswap.h" /* for swapIfNecessary */ + +// dcmjpls includes +#include "dcmtk/dcmjpls/djcparam.h" /* for class DJLSCodecParameter */ +#include "dcmtk/dcmjpls/djrparam.h" /* for class D2RepresentationParameter */ +#include "djerror.h" /* for private class DJLSError */ + +// dcmimgle includes +#include "dcmtk/dcmimgle/dcmimage.h" /* for class DicomImage */ + +// JPEG-LS library (CharLS) includes +#include "intrface.h" + +BEGIN_EXTERN_C +#ifdef HAVE_FCNTL_H +#include /* for O_RDONLY */ +#endif +#ifdef HAVE_SYS_TYPES_H +#include /* required for sys/stat.h */ +#endif +#ifdef HAVE_SYS_STAT_H +#include /* for stat, fstat */ +#endif +END_EXTERN_C + + +E_TransferSyntax DJLSLosslessEncoder::supportedTransferSyntax() const +{ + return EXS_JPEGLSLossless; +} + +E_TransferSyntax DJLSNearLosslessEncoder::supportedTransferSyntax() const +{ + return EXS_JPEGLSLossy; +} + +// -------------------------------------------------------------------------- + +DJLSEncoderBase::DJLSEncoderBase() +: DcmCodec() +{ +} + + +DJLSEncoderBase::~DJLSEncoderBase() +{ +} + + +OFBool DJLSEncoderBase::canChangeCoding( + const E_TransferSyntax oldRepType, + const E_TransferSyntax newRepType) const +{ + // this codec only handles conversion from uncompressed to JPEG-LS. + DcmXfer oldRep(oldRepType); + return (oldRep.isNotEncapsulated() && (newRepType == supportedTransferSyntax())); +} + + +OFCondition DJLSEncoderBase::decode( + const DcmRepresentationParameter * /* fromRepParam */, + DcmPixelSequence * /* pixSeq */, + DcmPolymorphOBOW& /* uncompressedPixelData */, + const DcmCodecParameter * /* cp */, + const DcmStack& /* objStack */) const +{ + // we are an encoder only + return EC_IllegalCall; +} + + +OFCondition DJLSEncoderBase::decodeFrame( + const DcmRepresentationParameter * /* fromParam */ , + DcmPixelSequence * /* fromPixSeq */ , + const DcmCodecParameter * /* cp */ , + DcmItem * /* dataset */ , + Uint32 /* frameNo */ , + Uint32& /* startFragment */ , + void * /* buffer */ , + Uint32 /* bufSize */ , + OFString& /* decompressedColorModel */ ) const +{ + // we are an encoder only + return EC_IllegalCall; +} + + +OFCondition DJLSEncoderBase::encode( + const E_TransferSyntax /* fromRepType */, + const DcmRepresentationParameter * /* fromRepParam */, + DcmPixelSequence * /* fromPixSeq */, + const DcmRepresentationParameter * /* toRepParam */, + DcmPixelSequence * & /* toPixSeq */, + const DcmCodecParameter * /* cp */, + DcmStack & /* objStack */) const +{ + // we don't support re-coding for now. + return EC_IllegalCall; +} + +OFCondition DJLSEncoderBase::encode( + const Uint16 * pixelData, + const Uint32 length, + const DcmRepresentationParameter * toRepParam, + DcmPixelSequence * & pixSeq, + const DcmCodecParameter *cp, + DcmStack & objStack) const +{ + OFCondition result = EC_Normal; + DJLSRepresentationParameter defRep; + + // retrieve pointer to dataset from parameter stack + DcmStack localStack(objStack); + (void)localStack.pop(); // pop pixel data element from stack + DcmObject *dobject = localStack.pop(); // this is the item in which the pixel data is located + if ((!dobject)||((dobject->ident()!= EVR_dataset) && (dobject->ident()!= EVR_item))) return EC_InvalidTag; + DcmItem *dataset = OFstatic_cast(DcmItem *, dobject); + + // assume we can cast the codec and representation parameters to what we need + const DJLSCodecParameter *djcp = OFreinterpret_cast(const DJLSCodecParameter *, cp); + const DJLSRepresentationParameter *djrp = OFreinterpret_cast(const DJLSRepresentationParameter *, toRepParam); + double compressionRatio = 0.0; + + if (!djrp) + djrp = &defRep; + + if (supportedTransferSyntax() == EXS_JPEGLSLossless || djrp->useLosslessProcess()) + { + if (djcp->cookedEncodingPreferred()) + result = losslessCookedEncode(pixelData, length, dataset, djrp, pixSeq, djcp, compressionRatio, 0); + else result = losslessRawEncode(pixelData, length, dataset, djrp, pixSeq, djcp, compressionRatio); + } + else + { + // near-lossless mode always uses the "cooked" encoder since this one is guaranteed not to "mix" + // overlays and pixel data in one cell subjected to lossy compression. + result = losslessCookedEncode(pixelData, length, dataset, djrp, pixSeq, djcp, compressionRatio, djrp->getnearlosslessDeviation()); + } + + // the following operations do not affect the Image Pixel Module + // but other modules such as SOP Common. We only perform these + // changes if we're on the main level of the dataset, + // which should always identify itself as dataset, not as item. + if (result.good() && dataset->ident() == EVR_dataset) + { + if (result.good()) + { + if (supportedTransferSyntax() == EXS_JPEGLSLossless || djrp->useLosslessProcess()) + { + // lossless process - create new UID if mode is EUC_always or if we're converting to Secondary Capture + if (djcp->getConvertToSC() || (djcp->getUIDCreation() == EJLSUC_always)) + result = DcmCodec::newInstance(dataset, "DCM", "121320", "Uncompressed predecessor"); + } + else + { + // lossy process - create new UID unless mode is EUC_never and we're not converting to Secondary Capture + if (djcp->getConvertToSC() || (djcp->getUIDCreation() != EJLSUC_never)) + result = DcmCodec::newInstance(dataset, "DCM", "121320", "Uncompressed predecessor"); + + // update image type + if (result.good()) result = DcmCodec::updateImageType(dataset); + + // update derivation description + if (result.good()) result = updateDerivationDescription(dataset, djrp, compressionRatio); + + // update lossy compression ratio + if (result.good()) result = updateLossyCompressionRatio(dataset, compressionRatio); + } + } + + // convert to Secondary Capture if requested by user. + // This method creates a new SOP class UID, so it should be executed + // after the call to newInstance() which creates a Source Image Sequence. + if (result.good() && djcp->getConvertToSC()) result = DcmCodec::convertToSecondaryCapture(dataset); + } + + return result; +} + + +OFCondition DJLSEncoderBase::determineDecompressedColorModel( + const DcmRepresentationParameter * /* fromParam */, + DcmPixelSequence * /* fromPixSeq */, + const DcmCodecParameter * /* cp */, + DcmItem * /* dataset */, + OFString & /* decompressedColorModel */) const +{ + return EC_IllegalCall; +} + + +OFCondition DJLSEncoderBase::adjustOverlays( + DcmItem *dataset, + DicomImage& image) const +{ + if (dataset == NULL) return EC_IllegalCall; + + unsigned int overlayCount = image.getOverlayCount(); + if (overlayCount > 0) + { + Uint16 group = 0; + DcmStack stack; + unsigned long bytesAllocated = 0; + Uint8 *buffer = NULL; + unsigned int width = 0; + unsigned int height = 0; + unsigned long frames = 0; + DcmElement *elem = NULL; + OFCondition result = EC_Normal; + + // adjust overlays (prior to grayscale compression) + for (unsigned int i=0; i < overlayCount; i++) + { + // check if current overlay is embedded in pixel data + group = OFstatic_cast(Uint16, image.getOverlayGroupNumber(i)); + stack.clear(); + if ((dataset->search(DcmTagKey(group, 0x3000), stack, ESM_fromHere, OFFalse)).bad()) + { + // separate Overlay Data not found. Assume overlay is embedded. + bytesAllocated = image.create6xxx3000OverlayData(buffer, i, width, height, frames); + if (bytesAllocated > 0) + { + elem = new DcmOverlayData(DcmTagKey(group, 0x3000)); // DCM_OverlayData + if (elem) + { + result = elem->putUint8Array(buffer, bytesAllocated); + delete[] buffer; + if (result.good()) + { + dataset->insert(elem, OFTrue /*replaceOld*/); + // DCM_OverlayBitsAllocated + result = dataset->putAndInsertUint16(DcmTagKey(group, 0x0100), 1); + // DCM_OverlayBitPosition + if (result.good()) result = dataset->putAndInsertUint16(DcmTagKey(group, 0x0102), 0); + } + else + { + delete elem; + return result; + } + } + else + { + delete[] buffer; + return EC_MemoryExhausted; + } + } + else return EC_IllegalCall; + } + } + } + return EC_Normal; +} + + +OFCondition DJLSEncoderBase::updateLossyCompressionRatio( + DcmItem *dataset, + double ratio) const +{ + if (dataset == NULL) return EC_IllegalCall; + + // set Lossy Image Compression to "01" (see DICOM part 3, C.7.6.1.1.5) + OFCondition result = dataset->putAndInsertString(DCM_LossyImageCompression, "01"); + if (result.bad()) return result; + + // set Lossy Image Compression Ratio + OFString s; + const char *oldRatio = NULL; + if ((dataset->findAndGetString(DCM_LossyImageCompressionRatio, oldRatio)).good() && oldRatio) + { + s = oldRatio; + s += "\\"; + } + + // append lossy compression ratio + char buf[64]; + OFStandard::ftoa(buf, sizeof(buf), ratio, OFStandard::ftoa_uppercase, 0, 5); + s += buf; + + result = dataset->putAndInsertString(DCM_LossyImageCompressionRatio, s.c_str()); + if (result.bad()) return result; + + // count VM of lossy image compression ratio + size_t i; + size_t s_vm = 0; + size_t s_sz = s.size(); + for (i = 0; i < s_sz; ++i) + if (s[i] == '\\') ++s_vm; + + // set Lossy Image Compression Method + const char *oldMethod = NULL; + OFString m; + if ((dataset->findAndGetString(DCM_LossyImageCompressionMethod, oldMethod)).good() && oldMethod) + { + m = oldMethod; + m += "\\"; + } + + // count VM of lossy image compression method + size_t m_vm = 0; + size_t m_sz = m.size(); + for (i = 0; i < m_sz; ++i) + if (m[i] == '\\') ++m_vm; + + // make sure that VM of Compression Method is not smaller than VM of Compression Ratio + while (m_vm++ < s_vm) m += "\\"; + + m += "ISO_14495_1"; + return dataset->putAndInsertString(DCM_LossyImageCompressionMethod, m.c_str()); +} + + +OFCondition DJLSEncoderBase::updateDerivationDescription( + DcmItem *dataset, + const DJLSRepresentationParameter *djrp, + double ratio) const +{ + OFString derivationDescription; + char buf[64]; + + derivationDescription = "near lossless JPEG-LS compression, factor "; + OFStandard::ftoa(buf, sizeof(buf), ratio, OFStandard::ftoa_uppercase, 0, 5); + derivationDescription += buf; + sprintf(buf, " (NEAR=%lu)", OFstatic_cast(unsigned long, djrp->getnearlosslessDeviation())); + derivationDescription += buf; + + // append old Derivation Description, if any + const char *oldDerivation = NULL; + if ((dataset->findAndGetString(DCM_DerivationDescription, oldDerivation)).good() && oldDerivation) + { + derivationDescription += " ["; + derivationDescription += oldDerivation; + derivationDescription += "]"; + if (derivationDescription.length() > 1024) + { + // ST is limited to 1024 characters, cut off tail + derivationDescription.erase(1020); + derivationDescription += "...]"; + } + } + + OFCondition result = dataset->putAndInsertString(DCM_DerivationDescription, derivationDescription.c_str()); + if (result.good()) result = DcmCodec::insertCodeSequence(dataset, DCM_DerivationCodeSequence, "DCM", "113040", "Lossy Compression"); + return result; +} + + +OFCondition DJLSEncoderBase::losslessRawEncode( + const Uint16 *pixelData, + const Uint32 length, + DcmItem *dataset, + const DJLSRepresentationParameter *djrp, + DcmPixelSequence * & pixSeq, + const DJLSCodecParameter *djcp, + double& compressionRatio) const +{ + compressionRatio = 0.0; // initialize if something goes wrong + + // determine image properties + Uint16 bitsAllocated = 0; + Uint16 bitsStored = 0; + Uint16 bytesAllocated = 0; + Uint16 samplesPerPixel = 0; + Uint16 planarConfiguration = 0; + Uint16 columns = 0; + Uint16 rows = 0; + Sint32 numberOfFrames = 1; + OFBool byteSwapped = OFFalse; // true if we have byte-swapped the original pixel data + OFString photometricInterpretation; + + OFCondition result = dataset->findAndGetUint16(DCM_BitsAllocated, bitsAllocated); + if (result.good()) result = dataset->findAndGetUint16(DCM_BitsStored, bitsStored); + if (result.good()) result = dataset->findAndGetUint16(DCM_SamplesPerPixel, samplesPerPixel); + if (result.good()) result = dataset->findAndGetUint16(DCM_Columns, columns); + if (result.good()) result = dataset->findAndGetUint16(DCM_Rows, rows); + if (result.good()) result = dataset->findAndGetOFString(DCM_PhotometricInterpretation, photometricInterpretation); + if (result.good()) + { + result = dataset->findAndGetSint32(DCM_NumberOfFrames, numberOfFrames); + if (result.bad() || numberOfFrames < 1) numberOfFrames = 1; + result = EC_Normal; + } + if (result.good() && (samplesPerPixel > 1)) + { + result = dataset->findAndGetUint16(DCM_PlanarConfiguration, planarConfiguration); + } + + if (result.good()) + { + // check if bitsAllocated is 8 or 16 - we don't handle anything else + if (bitsAllocated == 8) + { + bytesAllocated = 1; + } + else if (bitsAllocated == 16) + { + bytesAllocated = 2; + } + else + { + if (photometricInterpretation == "MONOCHROME1" || + photometricInterpretation == "MONOCHROME2" || + photometricInterpretation == "RGB" || + photometricInterpretation == "YBR_FULL") + { + // A bitsAllocated value that we don't handle, but a color model that indicates + // that the cooked encoder could handle this case. Fall back to cooked encoder. + return losslessCookedEncode(pixelData, length, dataset, djrp, pixSeq, djcp, compressionRatio, 0); + } + + // an image that is not supported by either the raw or the cooked encoder. + result = EC_JLSUnsupportedImageType; + } + + // make sure that all the descriptive attributes have sensible values + if ((columns < 1)||(rows < 1)||(samplesPerPixel < 1)) result = EC_JLSUnsupportedImageType; + + // make sure that we have at least as many bytes of pixel data as we expect + if (bytesAllocated * samplesPerPixel * columns * rows * + OFstatic_cast(unsigned long,numberOfFrames) > length) + result = EC_JLSUncompressedBufferTooSmall; + } + + DcmPixelSequence *pixelSequence = NULL; + DcmPixelItem *offsetTable = NULL; + + // create initial pixel sequence + if (result.good()) + { + pixelSequence = new DcmPixelSequence(DCM_PixelSequenceTag); + if (pixelSequence == NULL) result = EC_MemoryExhausted; + else + { + // create empty offset table + offsetTable = new DcmPixelItem(DCM_PixelItemTag); + if (offsetTable == NULL) result = EC_MemoryExhausted; + else pixelSequence->insert(offsetTable); + } + } + + DcmOffsetList offsetList; + unsigned long compressedSize = 0; + unsigned long compressedFrameSize = 0; + double uncompressedSize = 0.0; + + // render and compress each frame + if (result.good()) + { + + // byte swap pixel data to little endian if bits allocate is 8 + if ((gLocalByteOrder == EBO_BigEndian) && (bitsAllocated == 8)) + { + swapIfNecessary(EBO_LittleEndian, gLocalByteOrder, OFstatic_cast(void *, OFconst_cast(Uint16 *, pixelData)), length, sizeof(Uint16)); + byteSwapped = OFTrue; + } + + unsigned long frameCount = OFstatic_cast(unsigned long, numberOfFrames); + unsigned long frameSize = columns * rows * samplesPerPixel * bytesAllocated; + const Uint8 *framePointer = OFreinterpret_cast(const Uint8 *, pixelData); + + // compute original image size in bytes, ignoring any padding bits. + uncompressedSize = columns * rows * samplesPerPixel * bitsStored * frameCount / 8.0; + + for (unsigned long i=0; (igetCreateOffsetTable())) + { + result = offsetTable->createOffsetTable(offsetList); + } + + if (compressedSize > 0) compressionRatio = uncompressedSize / compressedSize; + + // byte swap pixel data back to local endian if necessary + if (byteSwapped) + { + swapIfNecessary(gLocalByteOrder, EBO_LittleEndian, OFstatic_cast(void *, OFconst_cast(Uint16 *, pixelData)), length, sizeof(Uint16)); + } + + return result; +} + +OFCondition DJLSEncoderBase::compressRawFrame( + const Uint8 *framePointer, + Uint16 bitsAllocated, + Uint16 width, + Uint16 height, + Uint16 samplesPerPixel, + Uint16 planarConfiguration, + const OFString& /* photometricInterpretation */, + DcmPixelSequence *pixelSequence, + DcmOffsetList &offsetList, + unsigned long &compressedSize, + const DJLSCodecParameter *djcp) const +{ + OFCondition result = EC_Normal; + Uint16 bytesAllocated = bitsAllocated / 8; + Uint32 frameSize = width*height*bytesAllocated*samplesPerPixel; + Uint32 fragmentSize = djcp->getFragmentSize(); + OFBool opt_use_custom_options = djcp->getUseCustomOptions(); + JlsParameters jls_params; + Uint8 *frameBuffer = NULL; + + // Set up the information structure for CharLS + OFBitmanipTemplate::zeroMem((char *) &jls_params, sizeof(jls_params)); + jls_params.bitspersample = bitsAllocated; + jls_params.height = height; + jls_params.width = width; + jls_params.allowedlossyerror = 0; // must be zero for raw mode + jls_params.outputBgr = false; + // No idea what this one does, but I don't think DICOM says anything about it + jls_params.colorTransform = 0; + + // Unset: jls_params.jfif (thumbnail, dpi) + + if (opt_use_custom_options) + { + jls_params.custom.T1 = djcp->getT1(); + jls_params.custom.T2 = djcp->getT2(); + jls_params.custom.T3 = djcp->getT3(); + jls_params.custom.RESET = djcp->getReset(); + // not set: jls_params.custom.MAXVAL + // MAXVAL is the maximum sample value in the image, it helps the compression + // if it's used (I think...) + } + + // Theoretically we could support any samplesPerPixel value, but for now we + // only accept these (charls is a little picky for other values). + if (samplesPerPixel == 1 || samplesPerPixel == 3) + jls_params.components = samplesPerPixel; + else + return EC_IllegalCall; + + enum interleavemode ilv; + switch (planarConfiguration) + { + // ILV_LINE is not supported by DICOM + case 0: + ilv = ILV_SAMPLE; + break; + case 1: + ilv = ILV_NONE; + break; + default: + return EC_IllegalCall; + } + + switch (djcp->getJplsInterleaveMode()) + { + case DJLSCodecParameter::interleaveSample: + jls_params.ilv = ILV_SAMPLE; + break; + case DJLSCodecParameter::interleaveLine: + jls_params.ilv = ILV_LINE; + break; + case DJLSCodecParameter::interleaveNone: + jls_params.ilv = ILV_NONE; + break; + case DJLSCodecParameter::interleaveDefault: + default: + // In default mode we just never convert the image to another + // interleave-mode. Instead, we use what is already there. + jls_params.ilv = ilv; + break; + } + + // Special case: one component images are always ILV_NONE (Standard requires this) + if (jls_params.components == 1) + { + jls_params.ilv = ILV_NONE; + // Don't try to convert to another interleave mode, not necessary + ilv = ILV_NONE; + } + + // Do we have to convert the image to some other interleave mode? + if ((jls_params.ilv == ILV_NONE && (ilv == ILV_SAMPLE || ilv == ILV_LINE)) || + (ilv == ILV_NONE && (jls_params.ilv == ILV_SAMPLE || jls_params.ilv == ILV_LINE))) + { + DCMJPLS_DEBUG("Converting image from " << (ilv == ILV_NONE ? "color-by-plane" : "color-by-pixel") + << " to " << (jls_params.ilv == ILV_NONE ? "color-by-plane" : "color-by-pixel")); + + frameBuffer = new Uint8[frameSize]; + if (jls_params.ilv == ILV_NONE) + result = convertToUninterleaved(frameBuffer, framePointer, samplesPerPixel, width, height, bitsAllocated); + else + /* For CharLS, sample-interleaved and line-interleaved is both expected to + * be color-by-pixel. + */ + result = convertToSampleInterleaved(frameBuffer, framePointer, samplesPerPixel, width, height, bitsAllocated); + framePointer = frameBuffer; + } + + if (result.good()) + { + // We have no idea how big the compressed pixel data will be and we have no + // way to find out, so we just allocate a buffer large enough for the raw data + // plus a little more for JPEG metadata. + // Yes, this is way too much for just a little JPEG metadata, but some + // test-images showed that the buffer previously was too small. Plus, at some + // places charls fails to do proper bounds checking and writes behind the end + // of the buffer (sometimes way behind its end...). + size_t size = frameSize + 1024; + Uint8 *buffer = new Uint8[size]; + + JLS_ERROR err = JpegLsEncode(buffer, size, &size, framePointer, frameSize, &jls_params); + result = DJLSError::convert(err); + + if (result.good()) + { + // 'size' now contains the size of the compressed data in buffer + compressedSize = size; + result = pixelSequence->storeCompressedFrame(offsetList, buffer, size, fragmentSize); + } + + delete[] buffer; + } + + if (frameBuffer) + delete[] frameBuffer; + + return result; +} + + +OFCondition DJLSEncoderBase::losslessCookedEncode( + const Uint16 *pixelData, + const Uint32 length, + DcmItem *dataset, + const DJLSRepresentationParameter *djrp, + DcmPixelSequence * & pixSeq, + const DJLSCodecParameter *djcp, + double& compressionRatio, + Uint16 nearLosslessDeviation) const +{ + compressionRatio = 0.0; // initialize if something goes wrong + + // determine a few image properties + OFString photometricInterpretation; + Uint16 bitsAllocated = 0; + OFCondition result = dataset->findAndGetOFString(DCM_PhotometricInterpretation, photometricInterpretation); + if (result.good()) result = dataset->findAndGetUint16(DCM_BitsAllocated, bitsAllocated); + if (result.bad()) return result; + + // The cooked encoder only handles the following photometic interpretations + if (photometricInterpretation != "MONOCHROME1" && + photometricInterpretation != "MONOCHROME2" && + photometricInterpretation != "RGB" && + photometricInterpretation != "YBR_FULL") + { + // a photometric interpretation that we don't handle. Fall back to raw encoder (unless in near-lossless mode) + if (nearLosslessDeviation > 0) return EC_JLSUnsupportedPhotometricInterpretation; + else return losslessRawEncode(pixelData, length, dataset, djrp, pixSeq, djcp, compressionRatio); + } + + Uint16 pixelRepresentation = 0; + result = dataset->findAndGetUint16(DCM_PixelRepresentation, pixelRepresentation); + if (result.bad()) return result; + + if (pixelRepresentation > 0) + { + // in near lossless mode we cannot handle signed images because JPEG-LS assumes unsigned pixels + if (nearLosslessDeviation > 0) return EC_JLSUnsupportedPixelRepresentation; + + // The cooked encoder only handles unsigned color images + if (photometricInterpretation == "RGB" || photometricInterpretation == "YBR_FULL") + { + // prevent a loop - only call lossless raw encoder if bitsAllocated is OK for the raw encoder + if ((bitsAllocated == 8) || (bitsAllocated == 16)) + return losslessRawEncode(pixelData, length, dataset, djrp, pixSeq, djcp, compressionRatio); + else return EC_JLSUnsupportedPixelRepresentation; + } + } + + DcmPixelSequence *pixelSequence = NULL; + DcmPixelItem *offsetTable = NULL; + + // ignore modality transformation (rescale slope/intercept or LUT) stored in the dataset + unsigned long flags = CIF_IgnoreModalityTransformation; + // don't convert YCbCr (Full and Full 4:2:2) color images to RGB + flags |= CIF_KeepYCbCrColorModel; + // Don't optimize memory usage, but keep using the same bitsAllocated. + // Without this, the DICOM and the JPEG-LS value for bitsAllocated could + // differ and the decoder would error out. + flags |= CIF_UseAbsolutePixelRange; + + DicomImage *dimage = new DicomImage(dataset, EXS_LittleEndianImplicit, flags); // read all frames + if (dimage == NULL) return EC_MemoryExhausted; + if (dimage->getStatus() != EIS_Normal) + { + delete dimage; + return EC_IllegalCall; + } + + // create overlay data for embedded overlays + result = adjustOverlays(dataset, *dimage); + + // determine number of bits per sample + int bitsPerSample = dimage->getDepth(); + if (result.good() && (bitsPerSample > 16)) result = EC_JLSUnsupportedBitDepth; + + // create initial pixel sequence + if (result.good()) + { + pixelSequence = new DcmPixelSequence(DCM_PixelSequenceTag); + if (pixelSequence == NULL) result = EC_MemoryExhausted; + else + { + // create empty offset table + offsetTable = new DcmPixelItem(DCM_PixelItemTag); + if (offsetTable == NULL) result = EC_MemoryExhausted; + else pixelSequence->insert(offsetTable); + } + } + + DcmOffsetList offsetList; + unsigned long compressedSize = 0; + unsigned long compressedFrameSize = 0; + double uncompressedSize = 0.0; + + // render and compress each frame + if (result.good()) + { + unsigned long frameCount = dimage->getFrameCount(); + + // compute original image size in bytes, ignoring any padding bits. + Uint16 samplesPerPixel = 0; + if ((dataset->findAndGetUint16(DCM_SamplesPerPixel, samplesPerPixel)).bad()) samplesPerPixel = 1; + uncompressedSize = dimage->getWidth() * dimage->getHeight() * + bitsPerSample * frameCount * samplesPerPixel / 8.0; + + for (unsigned long i=0; (igetCreateOffsetTable())) + { + result = offsetTable->createOffsetTable(offsetList); + } + + // adapt attributes in image pixel module + if (result.good()) + { + // adjustments needed for both color and monochrome + if (bitsPerSample > 8) + result = dataset->putAndInsertUint16(DCM_BitsAllocated, 16); + else + result = dataset->putAndInsertUint16(DCM_BitsAllocated, 8); + if (result.good()) result = dataset->putAndInsertUint16(DCM_BitsStored, bitsPerSample); + if (result.good()) result = dataset->putAndInsertUint16(DCM_HighBit, bitsPerSample-1); + } + + if (compressedSize > 0) compressionRatio = uncompressedSize / compressedSize; + delete dimage; + return result; +} + + +OFCondition DJLSEncoderBase::compressCookedFrame( + DcmPixelSequence *pixelSequence, + DicomImage *dimage, + const OFString& /* photometricInterpretation */, + DcmOffsetList &offsetList, + unsigned long &compressedSize, + const DJLSCodecParameter *djcp, + Uint32 frame, + Uint16 nearLosslessDeviation) const +{ + if (dimage == NULL) return EC_IllegalCall; + + // access essential image parameters + int width = dimage->getWidth(); + int height = dimage->getHeight(); + int depth = dimage->getDepth(); + if ((depth < 1) || (depth > 16)) return EC_JLSUnsupportedBitDepth; + + Uint32 fragmentSize = djcp->getFragmentSize(); + OFBool opt_use_custom_options = djcp->getUseCustomOptions(); + + const DiPixel *dinter = dimage->getInterData(); + if (dinter == NULL) return EC_IllegalCall; + + // There should be no other possibilities + int samplesPerPixel = dinter->getPlanes(); + if (samplesPerPixel != 1 && samplesPerPixel != 3) return EC_IllegalCall; + + // get pointer to internal raw representation of image data + const void *draw = dinter->getData(); + if (draw == NULL) return EC_IllegalCall; + + OFCondition result = EC_Normal; + + const void *planes[3] = {NULL, NULL, NULL}; + if (samplesPerPixel == 3) + { + // for color images, dinter->getData() returns a pointer to an array + // of pointers pointing to the real plane data + const void * const * draw_array = OFstatic_cast(const void * const *,draw); + planes[0] = draw_array[0]; + planes[1] = draw_array[1]; + planes[2] = draw_array[2]; + } + else + { + // for monochrome images, dinter->getData() directly returns a pointer + // to the single monochrome plane. + planes[0] = draw; + } + + // This is the buffer with the uncompressed pixel data + Uint8 *buffer; + size_t buffer_size; + + Uint32 framesize = dimage->getWidth() * dimage->getHeight(); + switch(dinter->getRepresentation()) + { + case EPR_Uint8: + case EPR_Sint8: + { + // image representation is 8 bit signed or unsigned + if (samplesPerPixel == 1) + { + const Uint8 *yv = OFreinterpret_cast(const Uint8 *, planes[0]) + framesize * frame; + buffer_size = framesize; + buffer = new Uint8[buffer_size]; + memcpy(buffer, yv, framesize); + } + else + { + const Uint8 *rv = OFreinterpret_cast(const Uint8 *, planes[0]) + framesize * frame; + const Uint8 *gv = OFreinterpret_cast(const Uint8 *, planes[1]) + framesize * frame; + const Uint8 *bv = OFreinterpret_cast(const Uint8 *, planes[2]) + framesize * frame; + + buffer_size = framesize * 3; + buffer = new Uint8[buffer_size]; + + size_t i = 0; + for (int row=height; row; --row) + { + for (int col=width; col; --col) + { + buffer[i++] = *rv; + buffer[i++] = *gv; + buffer[i++] = *bv; + + rv++; + gv++; + bv++; + } + } + } + } + break; + case EPR_Uint16: + case EPR_Sint16: + { + // image representation is 16 bit signed or unsigned + if (samplesPerPixel == 1) + { + const Uint16 *yv = OFreinterpret_cast(const Uint16 *, planes[0]) + framesize * frame; + buffer_size = framesize*sizeof(Uint16); + buffer = new Uint8[buffer_size]; + memcpy(buffer, yv, buffer_size); + } + else + { + const Uint16 *rv = OFreinterpret_cast(const Uint16 *, planes[0]) + framesize * frame; + const Uint16 *gv = OFreinterpret_cast(const Uint16 *, planes[1]) + framesize * frame; + const Uint16 *bv = OFreinterpret_cast(const Uint16 *, planes[2]) + framesize * frame; + + buffer_size = framesize * 3; + Uint16 *buffer16 = new Uint16[buffer_size]; + buffer = OFreinterpret_cast(Uint8 *, buffer16); + + // Convert to byte count + buffer_size *= 2; + + size_t i = 0; + for (int row=height; row; --row) + { + for (int col=width; col; --col) + { + buffer16[i++] = *rv; + buffer16[i++] = *gv; + buffer16[i++] = *bv; + + rv++; + gv++; + bv++; + } + } + } + } + break; + default: + // we don't support images with > 16 bits/sample + return EC_JLSUnsupportedBitDepth; + break; + } + + JlsParameters jls_params; + + // Set up the information structure for CharLS + OFBitmanipTemplate::zeroMem((char *) &jls_params, sizeof(jls_params)); + jls_params.height = height; + jls_params.width = width; + jls_params.allowedlossyerror = nearLosslessDeviation; + jls_params.outputBgr = false; + jls_params.bitspersample = depth; + // No idea what this one does, but I don't think DICOM says anything about it + jls_params.colorTransform = 0; + + // This was already checked for a sane value above + jls_params.components = samplesPerPixel; + switch(dinter->getRepresentation()) + { + case EPR_Uint8: + case EPR_Sint8: + jls_params.bitspersample = 8; + break; + case EPR_Uint16: + case EPR_Sint16: + jls_params.bitspersample = 16; + break; + default: + // Everything else was already handled above and can't happen here + break; + } + + // Unset: jls_params.jfif (thumbnail, dpi) + + if (opt_use_custom_options) + { + jls_params.custom.T1 = djcp->getT1(); + jls_params.custom.T2 = djcp->getT2(); + jls_params.custom.T3 = djcp->getT3(); + jls_params.custom.RESET = djcp->getReset(); + } + + switch (djcp->getJplsInterleaveMode()) + { + case DJLSCodecParameter::interleaveSample: + jls_params.ilv = ILV_SAMPLE; + break; + case DJLSCodecParameter::interleaveLine: + jls_params.ilv = ILV_LINE; + break; + case DJLSCodecParameter::interleaveNone: + jls_params.ilv = ILV_NONE; + break; + case DJLSCodecParameter::interleaveDefault: + default: + // Default for the cooked encoder is always ILV_LINE + jls_params.ilv = ILV_LINE; + break; + } + + // Special case: one component images are always ILV_NONE (Standard requires this) + if (jls_params.components == 1) + { + jls_params.ilv = ILV_NONE; + } + + Uint8 *frameBuffer = NULL; + Uint8 *framePointer = buffer; + // Do we have to convert the image to color-by-plane now? + if (jls_params.ilv == ILV_NONE && jls_params.components != 1) + { + DCMJPLS_DEBUG("Converting image from color-by-pixel to color-by-plane"); + + frameBuffer = new Uint8[buffer_size]; + framePointer = frameBuffer; + result = convertToUninterleaved(frameBuffer, buffer, samplesPerPixel, width, height, jls_params.bitspersample); + } + + // We have no idea how big the compressed pixel data will be and we have no + // way to find out, so we just allocate a buffer large enough for the raw data + // plus a little more for JPEG metadata. + // Yes, this is way too much for just a little JPEG metadata, but some + // test-images showed that the buffer previously was too small. Plus, at some + // places charls fails to do proper bounds checking and writes behind the end + // of the buffer (sometimes way behind its end...). + size_t compressed_buffer_size = buffer_size + 1024; + Uint8 *compressed_buffer = new Uint8[compressed_buffer_size]; + + JLS_ERROR err = JpegLsEncode(compressed_buffer, compressed_buffer_size, + &compressed_buffer_size, framePointer, buffer_size, &jls_params); + result = DJLSError::convert(err); + + if (result.good()) + { + // 'compressed_buffer_size' now contains the size of the compressed data in buffer + compressedSize = compressed_buffer_size; + result = pixelSequence->storeCompressedFrame(offsetList, compressed_buffer, compressed_buffer_size, fragmentSize); + } + + delete[] buffer; + delete[] compressed_buffer; + if (frameBuffer) + delete[] frameBuffer; + + return result; +} + +OFCondition DJLSEncoderBase::convertToUninterleaved( + Uint8 *target, + const Uint8 *source, + Uint16 components, + Uint32 width, + Uint32 height, + Uint16 bitsAllocated) const +{ + Uint8 bytesAllocated = bitsAllocated / 8; + Uint32 planeSize = width * height * bytesAllocated; + + if (bitsAllocated % 8 != 0) + return EC_IllegalCall; + + for (Uint32 pos = 0; pos < width * height; pos++) + { + for (int i = 0; i < components; i++) + { + memcpy(&target[i * planeSize + pos * bytesAllocated], source, bytesAllocated); + source += bytesAllocated; + } + } + return EC_Normal; +} + +OFCondition DJLSEncoderBase::convertToSampleInterleaved( + Uint8 *target, + const Uint8 *source, + Uint16 components, + Uint32 width, + Uint32 height, + Uint16 bitsAllocated) const +{ + Uint8 bytesAllocated = bitsAllocated / 8; + Uint32 planeSize = width * height * bytesAllocated; + + if (bitsAllocated % 8 != 0) + return EC_IllegalCall; + + for (Uint32 pos = 0; pos < width * height; pos++) + { + for (int i = 0; i < components; i++) + { + memcpy(target, &source[i * planeSize + pos * bytesAllocated], bytesAllocated); + target += bytesAllocated; + } + } + return EC_Normal; +} diff --git a/dcmjpls/libsrc/djcparam.cc b/dcmjpls/libsrc/djcparam.cc new file mode 100644 index 00000000..58e0ef7b --- /dev/null +++ b/dcmjpls/libsrc/djcparam.cc @@ -0,0 +1,114 @@ +/* + * + * Copyright (C) 1997-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmjpls + * + * Author: Martin Willkomm, Uli Schlachter + * + * Purpose: codec parameter class for JPEG-LS codecs + * + */ + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmjpls/djcparam.h" +#include "dcmtk/ofstd/ofstd.h" + +DJLSCodecParameter::DJLSCodecParameter( + OFBool jpls_optionsEnabled, + Uint16 jpls_t1, // these are the defaults for 8bpp in lossless mode + Uint16 jpls_t2, + Uint16 jpls_t3, + Uint16 jpls_reset, + Uint16 jpls_limit, + OFBool preferCookedEncoding, + Uint32 fragmentSize, + OFBool createOffsetTable, + JLS_UIDCreation uidCreation, + OFBool convertToSC, + JLS_PlanarConfiguration planarConfiguration, + OFBool ignoreOffsetTble, + interleaveMode jplsInterleaveMode) +: DcmCodecParameter() +, jpls_optionsEnabled_(jpls_optionsEnabled) +, jpls_t1_(jpls_t1) +, jpls_t2_(jpls_t2) +, jpls_t3_(jpls_t3) +, jpls_reset_(jpls_reset) +, jpls_limit_(jpls_limit) +, fragmentSize_(fragmentSize) +, createOffsetTable_(createOffsetTable) +, preferCookedEncoding_(preferCookedEncoding) +, uidCreation_(uidCreation) +, convertToSC_(convertToSC) +, jplsInterleaveMode_(jplsInterleaveMode) +, planarConfiguration_(planarConfiguration) +, ignoreOffsetTable_(ignoreOffsetTble) +{ +} + + +DJLSCodecParameter::DJLSCodecParameter( + JLS_UIDCreation uidCreation, + JLS_PlanarConfiguration planarConfiguration, + OFBool ignoreOffsetTble) +: DcmCodecParameter() +, jpls_optionsEnabled_(OFFalse) +, jpls_t1_(3) +, jpls_t2_(7) +, jpls_t3_(21) +, jpls_reset_(64) +, jpls_limit_(0) +, fragmentSize_(0) +, createOffsetTable_(OFTrue) +, preferCookedEncoding_(OFTrue) +, uidCreation_(uidCreation) +, convertToSC_(OFFalse) +, jplsInterleaveMode_(interleaveDefault) +, planarConfiguration_(planarConfiguration) +, ignoreOffsetTable_(ignoreOffsetTble) +{ +} + +DJLSCodecParameter::DJLSCodecParameter(const DJLSCodecParameter& arg) +: DcmCodecParameter(arg) + +, jpls_optionsEnabled_(arg.jpls_optionsEnabled_) +, jpls_t1_(arg.jpls_t1_) +, jpls_t2_(arg.jpls_t2_) +, jpls_t3_(arg.jpls_t3_) +, jpls_reset_(arg.jpls_reset_) +, jpls_limit_(arg.jpls_limit_) +, fragmentSize_(arg.fragmentSize_) +, createOffsetTable_(arg.createOffsetTable_) +, preferCookedEncoding_(arg.preferCookedEncoding_) +, uidCreation_(arg.uidCreation_) +, convertToSC_(arg.convertToSC_) +, jplsInterleaveMode_(arg.jplsInterleaveMode_) +, planarConfiguration_(arg.planarConfiguration_) +, ignoreOffsetTable_(arg.ignoreOffsetTable_) +{ +} + +DJLSCodecParameter::~DJLSCodecParameter() +{ +} + +DcmCodecParameter *DJLSCodecParameter::clone() const +{ + return new DJLSCodecParameter(*this); +} + +const char *DJLSCodecParameter::className() const +{ + return "DJLSCodecParameter"; +} diff --git a/dcmjpls/libsrc/djdecode.cc b/dcmjpls/libsrc/djdecode.cc new file mode 100644 index 00000000..56996e10 --- /dev/null +++ b/dcmjpls/libsrc/djdecode.cc @@ -0,0 +1,76 @@ +/* + * + * Copyright (C) 1997-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmjpls + * + * Author: Martin Willkomm + * + * Purpose: singleton class that registers decoders for all supported JPEG-LS processes. + * + */ + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmjpls/djdecode.h" +#include "dcmtk/dcmdata/dccodec.h" /* for DcmCodecStruct */ +#include "dcmtk/dcmjpls/djcparam.h" +#include "dcmtk/dcmjpls/djcodecd.h" + +// initialization of static members +OFBool DJLSDecoderRegistration::registered_ = OFFalse; +DJLSCodecParameter *DJLSDecoderRegistration::cp_ = NULL; +DJLSLosslessDecoder *DJLSDecoderRegistration::losslessdecoder_ = NULL; +DJLSNearLosslessDecoder *DJLSDecoderRegistration::nearlosslessdecoder_ = NULL; + +void DJLSDecoderRegistration::registerCodecs( + JLS_UIDCreation uidcreation, + JLS_PlanarConfiguration planarconfig, + OFBool ignoreOffsetTable) +{ + if (! registered_) + { + cp_ = new DJLSCodecParameter(uidcreation, planarconfig, ignoreOffsetTable); + if (cp_) + { + losslessdecoder_ = new DJLSLosslessDecoder(); + if (losslessdecoder_) DcmCodecList::registerCodec(losslessdecoder_, NULL, cp_); + + nearlosslessdecoder_ = new DJLSNearLosslessDecoder(); + if (nearlosslessdecoder_) DcmCodecList::registerCodec(nearlosslessdecoder_, NULL, cp_); + registered_ = OFTrue; + } + } +} + +void DJLSDecoderRegistration::cleanup() +{ + if (registered_) + { + DcmCodecList::deregisterCodec(losslessdecoder_); + DcmCodecList::deregisterCodec(nearlosslessdecoder_); + delete losslessdecoder_; + delete nearlosslessdecoder_; + delete cp_; + registered_ = OFFalse; +#ifdef DEBUG + // not needed but useful for debugging purposes + losslessdecoder_ = NULL; + nearlosslessdecoder_ = NULL; + cp_ = NULL; +#endif + } +} + +OFString DJLSDecoderRegistration::getLibraryVersionString() +{ + return DCMJPLS_CHARLS_VERSION_STRING; +} diff --git a/dcmjpls/libsrc/djencode.cc b/dcmjpls/libsrc/djencode.cc new file mode 100644 index 00000000..e133bb3b --- /dev/null +++ b/dcmjpls/libsrc/djencode.cc @@ -0,0 +1,88 @@ +/* + * + * Copyright (C) 1997-2011, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmjpls + * + * Author: Martin Willkomm, Uli Schlachter + * + * Purpose: singleton class that registers encoders for all supported JPEG processes. + * + */ + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmjpls/djencode.h" +#include "dcmtk/dcmdata/dccodec.h" /* for DcmCodecStruct */ +#include "dcmtk/dcmjpls/djcparam.h" +#include "dcmtk/dcmjpls/djcodece.h" + +// initialization of static members +OFBool DJLSEncoderRegistration::registered_ = OFFalse; +DJLSCodecParameter *DJLSEncoderRegistration::cp_ = NULL; +DJLSLosslessEncoder *DJLSEncoderRegistration::losslessencoder_ = NULL; +DJLSNearLosslessEncoder *DJLSEncoderRegistration::nearlosslessencoder_ = NULL; + + +void DJLSEncoderRegistration::registerCodecs( + OFBool jpls_optionsEnabled, + Uint16 jpls_t1, + Uint16 jpls_t2, + Uint16 jpls_t3, + Uint16 jpls_reset, + Uint16 jpls_limit, + OFBool preferCookedEncoding, + Uint32 fragmentSize, + OFBool createOffsetTable, + JLS_UIDCreation uidCreation, + OFBool convertToSC, + DJLSCodecParameter::interleaveMode jplsInterleaveMode) +{ + if (! registered_) + { + cp_ = new DJLSCodecParameter(jpls_optionsEnabled, jpls_t1, jpls_t2, jpls_t3, jpls_reset, + jpls_limit, preferCookedEncoding, fragmentSize, createOffsetTable, uidCreation, + convertToSC, EJLSPC_restore, OFFalse, jplsInterleaveMode); + + if (cp_) + { + losslessencoder_ = new DJLSLosslessEncoder(); + if (losslessencoder_) DcmCodecList::registerCodec(losslessencoder_, NULL, cp_); + nearlosslessencoder_ = new DJLSNearLosslessEncoder(); + if (nearlosslessencoder_) DcmCodecList::registerCodec(nearlosslessencoder_, NULL, cp_); + registered_ = OFTrue; + } + } +} + +void DJLSEncoderRegistration::cleanup() +{ + if (registered_) + { + DcmCodecList::deregisterCodec(losslessencoder_); + DcmCodecList::deregisterCodec(nearlosslessencoder_); + delete losslessencoder_; + delete nearlosslessencoder_; + delete cp_; + registered_ = OFFalse; +#ifdef DEBUG + // not needed but useful for debugging purposes + losslessencoder_ = NULL; + nearlosslessencoder_ = NULL; + cp_ = NULL; +#endif + } +} + +OFString DJLSEncoderRegistration::getLibraryVersionString() +{ + return DCMJPLS_CHARLS_VERSION_STRING; +} diff --git a/dcmjpls/libsrc/djerror.h b/dcmjpls/libsrc/djerror.h new file mode 100644 index 00000000..d625c48a --- /dev/null +++ b/dcmjpls/libsrc/djerror.h @@ -0,0 +1,73 @@ +/* + * + * Copyright (C) 1997-2012, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmjpls + * + * Author: Uli Schlachter + * + * Purpose: Helper function than converts between CharLS and dcmjpgls errors + * + */ + +#ifndef DJERROR_H +#define DJERROR_H + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmjpls/djlsutil.h" /* For the OFCondition codes */ +#include "intrface.h" /* CharLS include */ + +/** Helper class for converting between dcmjpls and CharLS error codes + */ +class DJLSError +{ +private: + /// private undefined constructor + DJLSError(); + +public: + + /** This method converts a CharLS error code into a dcmjpls OFCondition + * @param error The CharLS error code + * @return The OFCondition + */ + static const OFConditionConst& convert(JLS_ERROR error) + { + switch (error) + { + case OK: + return EC_Normal; + case UncompressedBufferTooSmall: + return EC_JLSUncompressedBufferTooSmall; + case CompressedBufferTooSmall: + return EC_JLSCompressedBufferTooSmall; + case ImageTypeNotSupported: + return EC_JLSCodecUnsupportedImageType; + case InvalidJlsParameters: + return EC_JLSCodecInvalidParameters; + case ParameterValueNotSupported: + return EC_JLSCodecUnsupportedValue; + case InvalidCompressedData: + return EC_JLSInvalidCompressedData; + case UnsupportedBitDepthForTransform: + return EC_JLSUnsupportedBitDepthForTransform; + case UnsupportedColorTransform: + return EC_JLSUnsupportedColorTransform; + case TooMuchCompressedData: + return EC_JLSTooMuchCompressedData; + default: + return EC_IllegalParameter; + } + } +}; + +#endif diff --git a/dcmjpls/libsrc/djrparam.cc b/dcmjpls/libsrc/djrparam.cc new file mode 100644 index 00000000..f00a83db --- /dev/null +++ b/dcmjpls/libsrc/djrparam.cc @@ -0,0 +1,72 @@ +/* + * + * Copyright (C) 1997-2010, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmjpls + * + * Author: Martin Willkomm + * + * Purpose: representation parameter for JPEG-LS + * + */ + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmjpls/djrparam.h" +#include "dcmtk/ofstd/ofstd.h" + +DJLSRepresentationParameter::DJLSRepresentationParameter( + Uint16 nearlosslessDeviation, + OFBool losslessProcess) +: DcmRepresentationParameter() +, nearlosslessDeviation_(nearlosslessDeviation) +, losslessProcess_(losslessProcess) +{ +} + +DJLSRepresentationParameter::DJLSRepresentationParameter(const DJLSRepresentationParameter& arg) +: DcmRepresentationParameter(arg) +, nearlosslessDeviation_(arg.nearlosslessDeviation_) +, losslessProcess_(arg.losslessProcess_) +{ +} + +DJLSRepresentationParameter::~DJLSRepresentationParameter() +{ +} + +DcmRepresentationParameter *DJLSRepresentationParameter::clone() const +{ + return new DJLSRepresentationParameter(*this); +} + +const char *DJLSRepresentationParameter::className() const +{ + return "DJLSRepresentationParameter"; +} + +OFBool DJLSRepresentationParameter::operator==(const DcmRepresentationParameter &arg) const +{ + const char *argname = arg.className(); + if (argname) + { + OFString argstring(argname); + if (argstring == className()) + { + const DJLSRepresentationParameter& argll = OFreinterpret_cast(const DJLSRepresentationParameter &, arg); + if (losslessProcess_ && argll.losslessProcess_) return OFTrue; + else if (losslessProcess_ != argll.losslessProcess_) return OFFalse; + else if (nearlosslessDeviation_ != argll.nearlosslessDeviation_) return OFFalse; + return OFTrue; + } + } + return OFFalse; +} diff --git a/dcmjpls/libsrc/djutils.cc b/dcmjpls/libsrc/djutils.cc new file mode 100644 index 00000000..6224e5d4 --- /dev/null +++ b/dcmjpls/libsrc/djutils.cc @@ -0,0 +1,45 @@ +/* + * + * Copyright (C) 1997-2012, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmjpls + * + * Author: Martin Willkomm, Uli Schlachter + * + * Purpose: Support code for dcmjpls + * + */ + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/dcmjpls/djlsutil.h" +#include "dcmtk/dcmdata/dcerror.h" + +OFLogger DCM_dcmjplsLogger = OFLog::getLogger("dcmtk.dcmjpls"); + +#define MAKE_DCMJPLS_ERROR(number, name, description) \ +makeOFConditionConst(EC_ ## name, OFM_dcmjpls, number, OF_error, description) + +MAKE_DCMJPLS_ERROR( 1, JLSUncompressedBufferTooSmall, "Uncompressed pixel data too short for uncompressed image"); +MAKE_DCMJPLS_ERROR( 2, JLSCompressedBufferTooSmall, "Allocated too small buffer for compressed image data"); +MAKE_DCMJPLS_ERROR( 3, JLSCodecUnsupportedImageType, "Codec does not support this JPEG-LS image"); +MAKE_DCMJPLS_ERROR( 4, JLSCodecInvalidParameters, "Codec received invalid compression parameters"); +MAKE_DCMJPLS_ERROR( 5, JLSCodecUnsupportedValue, "Codec received unsupported compression parameters"); +MAKE_DCMJPLS_ERROR( 6, JLSInvalidCompressedData, "Invalid compressed image data"); +MAKE_DCMJPLS_ERROR( 7, JLSUnsupportedBitDepthForTransform, "Codec does not support the image's color transformation with this bit depth"); +MAKE_DCMJPLS_ERROR( 8, JLSUnsupportedColorTransform, "Codec does not support the image's color transformation"); +MAKE_DCMJPLS_ERROR( 9, JLSUnsupportedBitDepth, "Unsupported bit depth in JPEG-LS transfer syntax"); +MAKE_DCMJPLS_ERROR(10, JLSCannotComputeNumberOfFragments, "Cannot compute number of fragments for JPEG-LS frame"); +MAKE_DCMJPLS_ERROR(11, JLSImageDataMismatch, "Image data mismatch between DICOM header and JPEG-LS bitstream"); +MAKE_DCMJPLS_ERROR(12, JLSUnsupportedPhotometricInterpretation, "Unsupported photometric interpretation for near-lossless JPEG-LS compression"); +MAKE_DCMJPLS_ERROR(13, JLSUnsupportedPixelRepresentation, "Unsupported pixel representation for near-lossless JPEG-LS compression"); +MAKE_DCMJPLS_ERROR(14, JLSUnsupportedImageType, "Unsupported type of image for JPEG-LS compression"); +MAKE_DCMJPLS_ERROR(15, JLSTooMuchCompressedData, "Too much compressed data, trailing data after image"); diff --git a/dcmjpls/tests/Makefile.in b/dcmjpls/tests/Makefile.in new file mode 100644 index 00000000..895210f2 --- /dev/null +++ b/dcmjpls/tests/Makefile.in @@ -0,0 +1,29 @@ +# +# Makefile for dcmjpls/tests +# + +@SET_MAKE@ + +SHELL = /bin/sh +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +configdir = @top_srcdir@/@configdir@ + +include $(configdir)/@common_makefile@ + + +all: + +check: + +check-exhaustive: + +install: + +clean: + rm -f $(TRASH) + +distclean: + rm -f $(DISTTRASH) + +dependencies: diff --git a/dcmnet/CMakeLists.txt b/dcmnet/CMakeLists.txt new file mode 100644 index 00000000..34406332 --- /dev/null +++ b/dcmnet/CMakeLists.txt @@ -0,0 +1,10 @@ +# declare project +PROJECT(dcmnet) + +# declare include directories which hold for all subdirectories +INCLUDE_DIRECTORIES(${dcmnet_SOURCE_DIR}/include ${dcmtls_SOURCE_DIR}/include ${OPENSSL_INCDIR} ${ofstd_SOURCE_DIR}/include ${oflog_SOURCE_DIR}/include ${dcmdata_SOURCE_DIR}/include ${ZLIB_INCDIR}) + +# recurse into subdirectories +FOREACH(SUBDIR libsrc apps include docs etc tests) + ADD_SUBDIRECTORY(${SUBDIR}) +ENDFOREACH(SUBDIR) diff --git a/dcmnet/Makefile.in b/dcmnet/Makefile.in new file mode 100644 index 00000000..805d9147 --- /dev/null +++ b/dcmnet/Makefile.in @@ -0,0 +1,97 @@ +# +# Makefile for dcmnet +# + +@SET_MAKE@ + +SHELL = /bin/sh +VPATH = @srcdir@:@top_srcdir@/include:@top_srcdir@/@configdir@/include +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +configdir = @top_srcdir@/@configdir@ + +include $(configdir)/@common_makefile@ + + +all: include-all libsrc-all apps-all tests-all + +install: install-bin install-doc install-support + +install-bin: apps-install + +install-doc: docs-install + +install-data: data-install + +install-etc: etc-install + +install-include: include-install + +install-lib: libsrc-install install-include + +install-support: install-data install-etc + + +include-all: + (cd include && $(MAKE) ARCH="$(ARCH)" all) + +libsrc-all: include-all + (cd libsrc && $(MAKE) ARCH="$(ARCH)" all) + +apps-all: libsrc-all + (cd apps && $(MAKE) ARCH="$(ARCH)" all) + +tests-all: libsrc-all + (cd tests && $(MAKE) ARCH="$(ARCH)" all) + + +check: tests-all + (cd tests && $(MAKE) check) + +check-exhaustive: tests-all + (cd tests && $(MAKE) check-exhaustive) + + +include-install: + (cd include && $(MAKE) ARCH="$(ARCH)" install) + +libsrc-install: libsrc-all + (cd libsrc && $(MAKE) ARCH="$(ARCH)" install) + +apps-install: apps-all + (cd apps && $(MAKE) ARCH="$(ARCH)" install) + +docs-install: + (cd docs && $(MAKE) install) + +data-install: + (cd data && $(MAKE) install) + +etc-install: + (cd etc && $(MAKE) install) + + +clean: + (cd include && $(MAKE) clean) + (cd libsrc && $(MAKE) clean) + (cd apps && $(MAKE) clean) + (cd tests && $(MAKE) clean) + (cd docs && $(MAKE) clean) + (cd data && $(MAKE) clean) + (cd etc && $(MAKE) clean) + rm -f $(TRASH) + +distclean: + (cd include && $(MAKE) distclean) + (cd libsrc && $(MAKE) distclean) + (cd apps && $(MAKE) distclean) + (cd tests && $(MAKE) distclean) + (cd docs && $(MAKE) distclean) + (cd data && $(MAKE) distclean) + (cd etc && $(MAKE) distclean) + rm -f $(DISTTRASH) + +dependencies: + (cd libsrc && touch $(DEP) && $(MAKE) dependencies) + (cd apps && touch $(DEP) && $(MAKE) dependencies) + (cd tests && touch $(DEP) && $(MAKE) dependencies) diff --git a/dcmnet/apps/CMakeLists.txt b/dcmnet/apps/CMakeLists.txt new file mode 100644 index 00000000..4fe5a674 --- /dev/null +++ b/dcmnet/apps/CMakeLists.txt @@ -0,0 +1,28 @@ +# declare additional include directories needed for compression support +INCLUDE_DIRECTORIES(${dcmjpls_SOURCE_DIR}/include ${dcmjpeg_SOURCE_DIR}/include ${dcmimage_SOURCE_DIR}/include ${dcmimgle_SOURCE_DIR}/include) + +# declare executables +FOREACH(PROGRAM dcmrecv dcmsend echoscu findscu getscu movescu storescp storescu termscu) + DCMTK_ADD_EXECUTABLE(${PROGRAM} ${PROGRAM}) +ENDFOREACH(PROGRAM) + +# declare installation files +IF(WITH_OPENSSL) + IF(WIN32) + INSTALL(FILES ${OPENSSL_BINDIR}/dcmtkeay.dll ${OPENSSL_BINDIR}/dcmtkssl.dll DESTINATION ${DCMTK_INSTALL_BINDIR} COMPONENT bin) + ENDIF(WIN32) +ENDIF(WITH_OPENSSL) + +# make sure executables are linked to the corresponding libraries +FOREACH(PROGRAM dcmrecv dcmsend echoscu findscu getscu movescu storescp storescu termscu) + DCMTK_TARGET_LINK_MODULES(${PROGRAM} dcmnet dcmdata oflog ofstd) +ENDFOREACH(PROGRAM) +FOREACH(PROGRAM echoscu findscu storescp storescu) + DCMTK_TARGET_LINK_MODULES(${PROGRAM} dcmtls) +ENDFOREACH(PROGRAM) + +# uncomment the following line if "storescu" is compiled with ON_THE_FLY_COMPRESSION defined +#DCMTK_TARGET_LINK_MODULES(storescu dcmjpls dcmjpeg dcmimage) + +# "dcmsend" always needs compression support +DCMTK_TARGET_LINK_MODULES(dcmsend dcmjpls dcmjpeg dcmimage) diff --git a/dcmnet/apps/Makefile.dep b/dcmnet/apps/Makefile.dep new file mode 100644 index 00000000..e5cdec24 --- /dev/null +++ b/dcmnet/apps/Makefile.dep @@ -0,0 +1,828 @@ +dcmrecv.o: dcmrecv.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \ + ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ + ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ + ../include/dcmtk/dcmnet/dstorscp.h \ + ../../ofstd/include/dcmtk/ofstd/offname.h ../include/dcmtk/dcmnet/scp.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcostrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicent.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcmetinf.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicdir.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdirrec.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrulup.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrul.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixseq.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcofsetl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrae.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvras.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrda.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrds.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrdt.h \ + ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvris.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrtm.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrur.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcchrstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlt.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpn.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsh.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrst.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvruc.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrut.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixel.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpobw.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcovlay.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrat.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrss.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrus.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfd.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrof.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrod.h \ + ../include/dcmtk/dcmnet/assoc.h ../include/dcmtk/dcmnet/dicom.h \ + ../include/dcmtk/dcmnet/cond.h ../include/dcmtk/dcmnet/dndefine.h \ + ../include/dcmtk/dcmnet/dcompat.h \ + ../../ofstd/include/dcmtk/ofstd/ofbmanip.h ../include/dcmtk/dcmnet/lst.h \ + ../include/dcmtk/dcmnet/dul.h ../include/dcmtk/dcmnet/extneg.h \ + ../include/dcmtk/dcmnet/dcuserid.h ../include/dcmtk/dcmnet/dimse.h \ + ../include/dcmtk/dcmnet/scpcfg.h ../include/dcmtk/dcmnet/dcasccff.h \ + ../include/dcmtk/dcmnet/dcasccfg.h ../include/dcmtk/dcmnet/dccftsmp.h \ + ../include/dcmtk/dcmnet/dccfuidh.h ../include/dcmtk/dcmnet/dccfpcmp.h \ + ../include/dcmtk/dcmnet/dccfrsmp.h ../include/dcmtk/dcmnet/dccfenmp.h \ + ../include/dcmtk/dcmnet/dccfprmp.h \ + ../../ofstd/include/dcmtk/ofstd/ofmem.h +dcmsend.o: dcmsend.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \ + ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ + ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcostrmz.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcostrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../include/dcmtk/dcmnet/dstorscu.h ../include/dcmtk/dcmnet/scu.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicent.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcmetinf.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicdir.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdirrec.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrulup.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrul.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixseq.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcofsetl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrae.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvras.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrda.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrds.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrdt.h \ + ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvris.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrtm.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrur.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcchrstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlt.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpn.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsh.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrst.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvruc.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrut.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixel.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpobw.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcovlay.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrat.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrss.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrus.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfd.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrof.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrod.h \ + ../include/dcmtk/dcmnet/dcompat.h \ + ../../ofstd/include/dcmtk/ofstd/ofbmanip.h \ + ../include/dcmtk/dcmnet/dndefine.h ../include/dcmtk/dcmnet/dimse.h \ + ../include/dcmtk/dcmnet/dicom.h ../include/dcmtk/dcmnet/cond.h \ + ../include/dcmtk/dcmnet/lst.h ../include/dcmtk/dcmnet/dul.h \ + ../include/dcmtk/dcmnet/extneg.h ../include/dcmtk/dcmnet/dcuserid.h \ + ../include/dcmtk/dcmnet/assoc.h ../include/dcmtk/dcmnet/dcasccff.h \ + ../include/dcmtk/dcmnet/dcasccfg.h ../include/dcmtk/dcmnet/dccftsmp.h \ + ../include/dcmtk/dcmnet/dccfuidh.h ../include/dcmtk/dcmnet/dccfpcmp.h \ + ../include/dcmtk/dcmnet/dccfrsmp.h ../include/dcmtk/dcmnet/dccfenmp.h \ + ../include/dcmtk/dcmnet/dccfprmp.h \ + ../../dcmjpeg/include/dcmtk/dcmjpeg/djdecode.h \ + ../../dcmjpeg/include/dcmtk/dcmjpeg/djutils.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diutils.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/didefine.h \ + ../../dcmjpeg/include/dcmtk/dcmjpeg/djdefine.h \ + ../../dcmjpls/include/dcmtk/dcmjpls/djdecode.h \ + ../../dcmjpls/include/dcmtk/dcmjpls/djlsutil.h \ + ../../dcmjpls/include/dcmtk/dcmjpls/dldefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcrledrg.h \ + ../../dcmjpeg/include/dcmtk/dcmjpeg/dipijpeg.h \ + ../../dcmimgle/include/dcmtk/dcmimgle/diplugin.h +echoscu.o: echoscu.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../include/dcmtk/dcmnet/dimse.h ../include/dcmtk/dcmnet/dicom.h \ + ../include/dcmtk/dcmnet/cond.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../include/dcmtk/dcmnet/dndefine.h ../include/dcmtk/dcmnet/dcompat.h \ + ../../ofstd/include/dcmtk/ofstd/ofbmanip.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ + ../include/dcmtk/dcmnet/lst.h ../include/dcmtk/dcmnet/dul.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../include/dcmtk/dcmnet/extneg.h ../include/dcmtk/dcmnet/dcuserid.h \ + ../include/dcmtk/dcmnet/assoc.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../include/dcmtk/dcmnet/diutil.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \ + ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ + ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ + ../../dcmtls/include/dcmtk/dcmtls/tlstrans.h \ + ../include/dcmtk/dcmnet/dcmtrans.h ../include/dcmtk/dcmnet/dcmlayer.h \ + ../../dcmtls/include/dcmtk/dcmtls/tlsdefin.h \ + ../../dcmtls/include/dcmtk/dcmtls/tlslayer.h +findscu.o: findscu.cc ../../config/include/dcmtk/config/osconfig.h \ + ../include/dcmtk/dcmnet/dfindscu.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../include/dcmtk/dcmnet/dimse.h ../include/dcmtk/dcmnet/dicom.h \ + ../include/dcmtk/dcmnet/cond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../include/dcmtk/dcmnet/dndefine.h ../include/dcmtk/dcmnet/dcompat.h \ + ../../ofstd/include/dcmtk/ofstd/ofbmanip.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ + ../include/dcmtk/dcmnet/lst.h ../include/dcmtk/dcmnet/dul.h \ + ../include/dcmtk/dcmnet/extneg.h ../include/dcmtk/dcmnet/dcuserid.h \ + ../include/dcmtk/dcmnet/assoc.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../include/dcmtk/dcmnet/diutil.h \ + ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \ + ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcostrmz.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcostrma.h \ + ../../dcmtls/include/dcmtk/dcmtls/tlstrans.h \ + ../include/dcmtk/dcmnet/dcmtrans.h ../include/dcmtk/dcmnet/dcmlayer.h \ + ../../dcmtls/include/dcmtk/dcmtls/tlsdefin.h \ + ../../dcmtls/include/dcmtk/dcmtls/tlslayer.h +getscu.o: getscu.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h ../include/dcmtk/dcmnet/scu.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctk.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcswap.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcistrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcostrma.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicent.h \ + ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcmetinf.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicdir.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdirrec.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrulup.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrul.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixseq.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcofsetl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrae.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvras.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrda.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrds.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrdt.h \ + ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvris.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrtm.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrur.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcchrstr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrlt.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpn.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsh.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrst.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvruc.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrut.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpixel.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrpobw.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcovlay.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrat.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrss.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrus.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrsl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfl.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrfd.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrof.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvrod.h \ + ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ + ../include/dcmtk/dcmnet/dcompat.h \ + ../../ofstd/include/dcmtk/ofstd/ofbmanip.h \ + ../include/dcmtk/dcmnet/dndefine.h ../include/dcmtk/dcmnet/dimse.h \ + ../include/dcmtk/dcmnet/dicom.h ../include/dcmtk/dcmnet/cond.h \ + ../include/dcmtk/dcmnet/lst.h ../include/dcmtk/dcmnet/dul.h \ + ../include/dcmtk/dcmnet/extneg.h ../include/dcmtk/dcmnet/dcuserid.h \ + ../include/dcmtk/dcmnet/assoc.h ../include/dcmtk/dcmnet/dcasccff.h \ + ../include/dcmtk/dcmnet/dcasccfg.h ../include/dcmtk/dcmnet/dccftsmp.h \ + ../include/dcmtk/dcmnet/dccfuidh.h ../include/dcmtk/dcmnet/dccfpcmp.h \ + ../include/dcmtk/dcmnet/dccfrsmp.h ../include/dcmtk/dcmnet/dccfenmp.h \ + ../include/dcmtk/dcmnet/dccfprmp.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcostrmz.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpath.h +movescu.o: movescu.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h ../include/dcmtk/dcmnet/dicom.h \ + ../include/dcmtk/dcmnet/cond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../include/dcmtk/dcmnet/dndefine.h ../include/dcmtk/dcmnet/dcompat.h \ + ../../ofstd/include/dcmtk/ofstd/ofbmanip.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ + ../include/dcmtk/dcmnet/dimse.h ../include/dcmtk/dcmnet/lst.h \ + ../include/dcmtk/dcmnet/dul.h ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../include/dcmtk/dcmnet/extneg.h ../include/dcmtk/dcmnet/dcuserid.h \ + ../include/dcmtk/dcmnet/assoc.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../include/dcmtk/dcmnet/diutil.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \ + ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ + ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcmetinf.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdicent.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcostrmz.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcostrma.h +storescp.o: storescp.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofdatime.h \ + ../../ofstd/include/dcmtk/ofstd/ofdate.h \ + ../../ofstd/include/dcmtk/ofstd/oftime.h ../include/dcmtk/dcmnet/dicom.h \ + ../include/dcmtk/dcmnet/cond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../include/dcmtk/dcmnet/dndefine.h ../include/dcmtk/dcmnet/dcompat.h \ + ../../ofstd/include/dcmtk/ofstd/ofbmanip.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ + ../include/dcmtk/dcmnet/dimse.h ../include/dcmtk/dcmnet/lst.h \ + ../include/dcmtk/dcmnet/dul.h ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../include/dcmtk/dcmnet/extneg.h ../include/dcmtk/dcmnet/dcuserid.h \ + ../include/dcmtk/dcmnet/assoc.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../include/dcmtk/dcmnet/diutil.h ../include/dcmtk/dcmnet/dcasccfg.h \ + ../include/dcmtk/dcmnet/dccftsmp.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../include/dcmtk/dcmnet/dccfuidh.h ../include/dcmtk/dcmnet/dccfpcmp.h \ + ../include/dcmtk/dcmnet/dccfrsmp.h ../include/dcmtk/dcmnet/dccfenmp.h \ + ../include/dcmtk/dcmnet/dccfprmp.h ../include/dcmtk/dcmnet/dcasccff.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \ + ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ + ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcmetinf.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcostrmz.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcostrma.h \ + ../../dcmtls/include/dcmtk/dcmtls/tlstrans.h \ + ../include/dcmtk/dcmnet/dcmtrans.h ../include/dcmtk/dcmnet/dcmlayer.h \ + ../../dcmtls/include/dcmtk/dcmtls/tlsdefin.h \ + ../../dcmtls/include/dcmtk/dcmtls/tlslayer.h +storescu.o: storescu.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h ../include/dcmtk/dcmnet/dicom.h \ + ../include/dcmtk/dcmnet/cond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../include/dcmtk/dcmnet/dndefine.h ../include/dcmtk/dcmnet/dcompat.h \ + ../../ofstd/include/dcmtk/ofstd/ofbmanip.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ + ../include/dcmtk/dcmnet/dimse.h ../include/dcmtk/dcmnet/lst.h \ + ../include/dcmtk/dcmnet/dul.h ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../include/dcmtk/dcmnet/extneg.h ../include/dcmtk/dcmnet/dcuserid.h \ + ../include/dcmtk/dcmnet/assoc.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \ + ../include/dcmtk/dcmnet/diutil.h ../include/dcmtk/dcmnet/dcasccfg.h \ + ../include/dcmtk/dcmnet/dccftsmp.h \ + ../../ofstd/include/dcmtk/ofstd/ofmap.h \ + ../../ofstd/include/dcmtk/ofstd/ofutil.h \ + ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \ + ../include/dcmtk/dcmnet/dccfuidh.h ../include/dcmtk/dcmnet/dccfpcmp.h \ + ../include/dcmtk/dcmnet/dccfrsmp.h ../include/dcmtk/dcmnet/dccfenmp.h \ + ../include/dcmtk/dcmnet/dccfprmp.h ../include/dcmtk/dcmnet/dcasccff.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcmetinf.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \ + ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \ + ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcostrmz.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcostrma.h \ + ../../dcmtls/include/dcmtk/dcmtls/tlstrans.h \ + ../include/dcmtk/dcmnet/dcmtrans.h ../include/dcmtk/dcmnet/dcmlayer.h \ + ../../dcmtls/include/dcmtk/dcmtls/tlsdefin.h \ + ../../dcmtls/include/dcmtk/dcmtls/tlslayer.h +termscu.o: termscu.cc ../../config/include/dcmtk/config/osconfig.h \ + ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \ + ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \ + ../../ofstd/include/dcmtk/ofstd/oftypes.h \ + ../../ofstd/include/dcmtk/ofstd/ofdefine.h \ + ../../ofstd/include/dcmtk/ofstd/ofcast.h \ + ../../ofstd/include/dcmtk/ofstd/ofexport.h \ + ../../ofstd/include/dcmtk/ofstd/ofstream.h \ + ../../ofstd/include/dcmtk/ofstd/oflist.h \ + ../../ofstd/include/dcmtk/ofstd/ofstring.h \ + ../../ofstd/include/dcmtk/ofstd/ofconsol.h \ + ../../ofstd/include/dcmtk/ofstd/ofthread.h \ + ../../ofstd/include/dcmtk/ofstd/offile.h \ + ../../ofstd/include/dcmtk/ofstd/ofstd.h \ + ../../ofstd/include/dcmtk/ofstd/oftraits.h \ + ../../ofstd/include/dcmtk/ofstd/ofcond.h \ + ../../ofstd/include/dcmtk/ofstd/ofconapp.h \ + ../../dcmdata/include/dcmtk/dcmdata/cmdlnarg.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \ + ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \ + ../include/dcmtk/dcmnet/assoc.h ../include/dcmtk/dcmnet/dicom.h \ + ../include/dcmtk/dcmnet/cond.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \ + ../include/dcmtk/dcmnet/dndefine.h ../include/dcmtk/dcmnet/dcompat.h \ + ../../ofstd/include/dcmtk/ofstd/ofbmanip.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \ + ../../oflog/include/dcmtk/oflog/oflog.h \ + ../../oflog/include/dcmtk/oflog/logger.h \ + ../../oflog/include/dcmtk/oflog/config.h \ + ../../oflog/include/dcmtk/oflog/config/defines.h \ + ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \ + ../../oflog/include/dcmtk/oflog/loglevel.h \ + ../../ofstd/include/dcmtk/ofstd/ofvector.h \ + ../../oflog/include/dcmtk/oflog/tstring.h \ + ../../oflog/include/dcmtk/oflog/tchar.h \ + ../../oflog/include/dcmtk/oflog/spi/apndatch.h \ + ../../oflog/include/dcmtk/oflog/appender.h \ + ../../ofstd/include/dcmtk/ofstd/ofaptr.h \ + ../../oflog/include/dcmtk/oflog/layout.h \ + ../../oflog/include/dcmtk/oflog/streams.h \ + ../../oflog/include/dcmtk/oflog/helpers/pointer.h \ + ../../oflog/include/dcmtk/oflog/thread/syncprim.h \ + ../../oflog/include/dcmtk/oflog/spi/filter.h \ + ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \ + ../../oflog/include/dcmtk/oflog/spi/logfact.h \ + ../../oflog/include/dcmtk/oflog/logmacro.h \ + ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \ + ../../oflog/include/dcmtk/oflog/tracelog.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \ + ../include/dcmtk/dcmnet/lst.h ../include/dcmtk/dcmnet/dul.h \ + ../../ofstd/include/dcmtk/ofstd/ofglobal.h \ + ../include/dcmtk/dcmnet/extneg.h ../include/dcmtk/dcmnet/dcuserid.h \ + ../include/dcmtk/dcmnet/dimse.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctag.h \ + ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \ + ../../dcmdata/include/dcmtk/dcmdata/dclist.h \ + ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h diff --git a/dcmnet/apps/Makefile.in b/dcmnet/apps/Makefile.in new file mode 100644 index 00000000..592d308c --- /dev/null +++ b/dcmnet/apps/Makefile.in @@ -0,0 +1,90 @@ +# +# Makefile for dcmnet/apps +# + +@SET_MAKE@ + +SHELL = /bin/sh +VPATH = @srcdir@:@top_srcdir@/include:@top_srcdir@/@configdir@/include +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +configdir = @top_srcdir@/@configdir@ + +include $(configdir)/@common_makefile@ + +ofstddir = $(top_srcdir)/../ofstd +oflogdir = $(top_srcdir)/../oflog +dcmdatadir = $(top_srcdir)/../dcmdata +dcmtlsdir = $(top_srcdir)/../dcmtls + +# these defines are used when compression support is needed for one of the tools +compr_includes = -I$(top_srcdir)/../dcmimgle/include -I$(top_srcdir)/../dcmimage/include \ + -I$(top_srcdir)/../dcmjpeg/include -I$(top_srcdir)/../dcmjpls/include +compr_libdirs = -L$(top_srcdir)/../dcmimgle/libsrc -L$(top_srcdir)/../dcmimage/libsrc \ + -L$(top_srcdir)/../dcmjpeg/libsrc -L$(top_srcdir)/../dcmjpeg/libijg8 \ + -L$(top_srcdir)/../dcmjpeg/libijg12 -L$(top_srcdir)/../dcmjpeg/libijg16 \ + -L$(top_srcdir)/../dcmjpls/libsrc -L$(top_srcdir)/../dcmjpls/libcharls + +LOCALINCLUDES = -I$(ofstddir)/include -I$(oflogdir)/include \ + -I$(dcmdatadir)/include -I$(dcmtlsdir)/include $(compr_includes) +LIBDIRS = -L$(top_srcdir)/libsrc -L$(ofstddir)/libsrc -L$(oflogdir)/libsrc \ + -L$(dcmdatadir)/libsrc -L$(dcmtlsdir)/libsrc $(compr_libdirs) +LOCALLIBS = -ldcmnet -ldcmdata -loflog -lofstd $(ZLIBLIBS) $(TCPWRAPPERLIBS) \ + $(ICONVLIBS) +DCMTLSLIBS = -ldcmtls +COMPR_LIBS = -ldcmjpls -lcharls -ldcmjpeg -lijg8 -lijg12 -lijg16 -ldcmimage -ldcmimgle + +objs = echoscu.o storescu.o storescp.o findscu.o movescu.o termscu.o getscu.o dcmsend.o \ + dcmrecv.o +progs = echoscu storescu storescp findscu movescu termscu getscu dcmsend dcmrecv + + +all: $(progs) + +echoscu: echoscu.o + $(CXX) $(CXXFLAGS) $(LIBDIRS) $(LDFLAGS) -o $@ $@.o $(LOCALLIBS) $(DCMTLSLIBS) $(OPENSSLLIBS) $(MATHLIBS) $(LIBS) + +# add $(COMPR_LIBS) to the linking instructions if "storescu" is compiled +# with ON_THE_FLY_COMPRESSION defined (see "config/docs/macros.txt") +storescu: storescu.o + $(CXX) $(CXXFLAGS) $(LIBDIRS) $(LDFLAGS) -o $@ $@.o $(LOCALLIBS) $(DCMTLSLIBS) $(OPENSSLLIBS) $(MATHLIBS) $(LIBS) + +storescp: storescp.o + $(CXX) $(CXXFLAGS) $(LIBDIRS) $(LDFLAGS) -o $@ $@.o $(LOCALLIBS) $(DCMTLSLIBS) $(OPENSSLLIBS) $(MATHLIBS) $(LIBS) + +findscu: findscu.o + $(CXX) $(CXXFLAGS) $(LIBDIRS) $(LDFLAGS) -o $@ $@.o $(LOCALLIBS) $(DCMTLSLIBS) $(OPENSSLLIBS) $(MATHLIBS) $(LIBS) + +movescu: movescu.o + $(CXX) $(CXXFLAGS) $(LIBDIRS) $(LDFLAGS) -o $@ $@.o $(LOCALLIBS) $(MATHLIBS) $(LIBS) + +termscu: termscu.o + $(CXX) $(CXXFLAGS) $(LIBDIRS) $(LDFLAGS) -o $@ $@.o $(LOCALLIBS) $(MATHLIBS) $(LIBS) + +getscu: getscu.o + $(CXX) $(CXXFLAGS) $(LIBDIRS) $(LDFLAGS) -o $@ $@.o $(LOCALLIBS) $(MATHLIBS) $(LIBS) + +dcmsend: dcmsend.o + $(CXX) $(CXXFLAGS) $(LIBDIRS) $(LDFLAGS) -o $@ $@.o $(COMPR_LIBS) $(LOCALLIBS) $(TIFFLIBS) $(PNGLIBS) $(MATHLIBS) $(LIBS) + +dcmrecv: dcmrecv.o + $(CXX) $(CXXFLAGS) $(LIBDIRS) $(LDFLAGS) -o $@ $@.o $(LOCALLIBS) $(MATHLIBS) $(LIBS) + +install: all + $(configdir)/mkinstalldirs $(DESTDIR)$(bindir) + for prog in $(progs); do \ + $(INSTALL_PROGRAM) $$prog$(BINEXT) $(DESTDIR)$(bindir) && $(STRIP) $(DESTDIR)$(bindir)/$$prog$(BINEXT) ;\ + done + + +clean: + rm -f $(objs) $(progs) $(TRASH) + +distclean: + rm -f $(objs) $(progs) $(DISTTRASH) + + +dependencies: + $(CXX) -MM $(defines) $(includes) $(CPPFLAGS) $(CXXFLAGS) *.cc > $(DEP) + +include $(DEP) diff --git a/dcmnet/apps/dcmrecv.cc b/dcmnet/apps/dcmrecv.cc new file mode 100644 index 00000000..f281666c --- /dev/null +++ b/dcmnet/apps/dcmrecv.cc @@ -0,0 +1,319 @@ +/* + * + * Copyright (C) 2013-2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmnet + * + * Author: Joerg Riesmeier + * + * Purpose: Simple Storage Service Class Provider + * + */ + + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/ofstd/ofstd.h" /* for OFStandard functions */ +#include "dcmtk/ofstd/ofconapp.h" /* for OFConsoleApplication */ +#include "dcmtk/ofstd/ofstream.h" /* for OFStringStream et al. */ +#include "dcmtk/dcmdata/dcdict.h" /* for global data dictionary */ +#include "dcmtk/dcmdata/dcuid.h" /* for dcmtk version name */ +#include "dcmtk/dcmdata/cmdlnarg.h" /* for prepareCmdLineArgs */ +#include "dcmtk/dcmnet/dstorscp.h" /* for DcmStorageSCP */ + + +/* general definitions */ + +#define OFFIS_CONSOLE_APPLICATION "dcmrecv" + +static OFLogger dcmrecvLogger = OFLog::getLogger("dcmtk.apps." OFFIS_CONSOLE_APPLICATION); + +static char rcsid[] = "$dcmtk: " OFFIS_CONSOLE_APPLICATION " v" + OFFIS_DCMTK_VERSION " " OFFIS_DCMTK_RELEASEDATE " $"; + +/* default application entity title */ +#define APPLICATIONTITLE "DCMRECV" + + +/* exit codes for this command line tool */ +/* (EXIT_SUCCESS and EXIT_FAILURE are standard codes) */ + +// general +#define EXITCODE_NO_ERROR 0 +#define EXITCODE_COMMANDLINE_SYNTAX_ERROR 1 // this code is the default for printError() + +// input file errors +#define EXITCODE_CANNOT_READ_INPUT_FILE 20 // placeholder, currently not used + +// output file errors +#define EXITCODE_CANNOT_WRITE_OUTPUT_FILE 40 // placeholder, currently not used +#define EXITCODE_INVALID_OUTPUT_DIRECTORY 45 + +// network errors +#define EXITCODE_CANNOT_INITIALIZE_NETWORK 60 // placeholder, currently not used +#define EXITCODE_CANNOT_START_SCP_AND_LISTEN 64 +#define EXITCODE_INVALID_ASSOCIATION_CONFIG 66 + + +/* helper macro for converting stream output to a string */ +#define CONVERT_TO_STRING(output, string) \ + optStream.str(""); \ + optStream.clear(); \ + optStream << output << OFStringStream_ends; \ + OFSTRINGSTREAM_GETOFSTRING(optStream, string) + + +/* main program */ + +#define SHORTCOL 4 +#define LONGCOL 21 + +int main(int argc, char *argv[]) +{ + OFOStringStream optStream; + + const char *opt_configFile = NULL; + const char *opt_profileName = NULL; + const char *opt_aeTitle = APPLICATIONTITLE; + const char *opt_outputDirectory = "."; + const char *opt_filenameExtension = ""; + + OFCmdUnsignedInt opt_port = 0; + OFCmdUnsignedInt opt_dimseTimeout = 0; + OFCmdUnsignedInt opt_acseTimeout = 30; + OFCmdUnsignedInt opt_maxPDULength = ASC_DEFAULTMAXPDU; + T_DIMSE_BlockingMode opt_blockingMode = DIMSE_BLOCKING; + + OFBool opt_showPresentationContexts = OFFalse; // default: do not show presentation contexts in verbose mode + OFBool opt_useCalledAETitle = OFFalse; // default: respond with specified application entity title + OFBool opt_HostnameLookup = OFTrue; // default: perform hostname lookup (for log output) + + DcmStorageSCP::E_DirectoryGenerationMode opt_directoryGeneration = DcmStorageSCP::DGM_NoSubdirectory; + DcmStorageSCP::E_FilenameGenerationMode opt_filenameGeneration = DcmStorageSCP::FGM_SOPInstanceUID; + DcmStorageSCP::E_DatasetStorageMode opt_datasetStorage = DcmStorageSCP::DGM_StoreToFile; + + OFConsoleApplication app(OFFIS_CONSOLE_APPLICATION , "Simple DICOM storage SCP (receiver)", rcsid); + OFCommandLine cmd; + + cmd.setParamColumn(LONGCOL + SHORTCOL + 4); + cmd.addParam("port", "tcp/ip port number to listen on"); + + cmd.setOptionColumns(LONGCOL, SHORTCOL); + cmd.addGroup("general options:", LONGCOL, SHORTCOL + 2); + cmd.addOption("--help", "-h", "print this help text and exit", OFCommandLine::AF_Exclusive); + cmd.addOption("--version", "print version information and exit", OFCommandLine::AF_Exclusive); + OFLog::addOptions(cmd); + cmd.addOption("--verbose-pc", "+v", "show presentation contexts in verbose mode"); + + cmd.addGroup("network options:"); + cmd.addSubGroup("association negotiation profile from configuration file:"); + cmd.addOption("--config-file", "-xf", 2, "[f]ilename, [p]rofile: string", + "use profile p from configuration file f"); + cmd.addSubGroup("application entity title:"); + CONVERT_TO_STRING("set my AE title (default: " << opt_aeTitle << ")", optString1); + cmd.addOption("--aetitle", "-aet", 1, "[a]etitle: string", optString1.c_str()); + cmd.addOption("--use-called-aetitle", "-uca", "always respond with called AE title"); + cmd.addSubGroup("other network options:"); + CONVERT_TO_STRING("[s]econds: integer (default: " << opt_acseTimeout << ")", optString2); + cmd.addOption("--acse-timeout", "-ta", 1, optString2.c_str(), + "timeout for ACSE messages"); + cmd.addOption("--dimse-timeout", "-td", 1, "[s]econds: integer (default: unlimited)", + "timeout for DIMSE messages"); + CONVERT_TO_STRING("[n]umber of bytes: integer (" << ASC_MINIMUMPDUSIZE << ".." << ASC_MAXIMUMPDUSIZE << ")", optString3); + CONVERT_TO_STRING("set max receive pdu to n bytes (default: " << opt_maxPDULength << ")", optString4); + cmd.addOption("--max-pdu", "-pdu", 1, optString3.c_str(), + optString4.c_str()); + cmd.addOption("--disable-host-lookup", "-dhl", "disable hostname lookup"); + cmd.addGroup("output options:"); + cmd.addSubGroup("general:"); + CONVERT_TO_STRING("[d]irectory: string (default: \"" << opt_outputDirectory << "\")", optString5); + cmd.addOption("--output-directory", "-od", 1, optString5.c_str(), + "write received objects to existing directory d"); + cmd.addSubGroup("subdirectory generation:"); + cmd.addOption("--no-subdir", "-s", "do not generate any subdirectories (default)"); + cmd.addOption("--series-date-subdir", "+ssd", "generate subdirectories from series date"); + cmd.addSubGroup("filename generation:"); + cmd.addOption("--default-filenames", "+fd", "generate filename from instance UID (default)"); + cmd.addOption("--unique-filenames", "+fu", "generate unique filename based on new UID"); + cmd.addOption("--short-unique-names", "+fsu", "generate short pseudo-random unique filename"); + cmd.addOption("--system-time-names", "+fst", "generate filename from current system time"); + cmd.addOption("--filename-extension", "-fe", 1, "[e]xtension: string (default: none)", + "append e to all generated filenames"); + cmd.addSubGroup("storage mode:"); + cmd.addOption("--normal", "-B", "allow implicit format conversions (default)"); + cmd.addOption("--bit-preserving", "+B", "write dataset exactly as received"); + cmd.addOption("--ignore", "ignore dataset, receive but do not store it"); + + /* evaluate command line */ + prepareCmdLineArgs(argc, argv, OFFIS_CONSOLE_APPLICATION); + if (app.parseCommandLine(cmd, argc, argv)) + { + /* check exclusive options first */ + if (cmd.hasExclusiveOption()) + { + if (cmd.findOption("--version")) + { + app.printHeader(OFTrue /*print host identifier*/); + COUT << OFendl << "External libraries used: none" << OFendl; + return EXITCODE_NO_ERROR; + } + } + + /* general options */ + OFLog::configureFromCommandLine(cmd, app); + if (cmd.findOption("--verbose-pc")) + { + app.checkDependence("--verbose-pc", "verbose mode", dcmrecvLogger.isEnabledFor(OFLogger::INFO_LOG_LEVEL)); + opt_showPresentationContexts = OFTrue; + } + + /* network options */ + if (cmd.findOption("--config-file")) + { + app.checkValue(cmd.getValue(opt_configFile)); + app.checkValue(cmd.getValue(opt_profileName)); + } + + cmd.beginOptionBlock(); + if (cmd.findOption("--aetitle")) + { + app.checkValue(cmd.getValue(opt_aeTitle)); + opt_useCalledAETitle = OFFalse; + } + if (cmd.findOption("--use-called-aetitle")) + opt_useCalledAETitle = OFTrue; + cmd.endOptionBlock(); + + if (cmd.findOption("--acse-timeout")) + app.checkValue(cmd.getValueAndCheckMin(opt_acseTimeout, 1)); + if (cmd.findOption("--dimse-timeout")) + { + app.checkValue(cmd.getValueAndCheckMin(opt_dimseTimeout, 1)); + opt_blockingMode = DIMSE_NONBLOCKING; + } + if (cmd.findOption("--max-pdu")) + app.checkValue(cmd.getValueAndCheckMinMax(opt_maxPDULength, ASC_MINIMUMPDUSIZE, ASC_MAXIMUMPDUSIZE)); + if (cmd.findOption("--disable-host-lookup")) + opt_HostnameLookup = OFFalse; + + /* output options */ + if (cmd.findOption("--output-directory")) + app.checkValue(cmd.getValue(opt_outputDirectory)); + + cmd.beginOptionBlock(); + if (cmd.findOption("--no-subdir")) + opt_directoryGeneration = DcmStorageSCP::DGM_NoSubdirectory; + if (cmd.findOption("--series-date-subdir")) + opt_directoryGeneration = DcmStorageSCP::DGM_SeriesDate; + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--default-filenames")) + opt_filenameGeneration = DcmStorageSCP::FGM_SOPInstanceUID; + if (cmd.findOption("--unique-filenames")) + opt_filenameGeneration = DcmStorageSCP::FGM_UniqueFromNewUID; + if (cmd.findOption("--short-unique-names")) + opt_filenameGeneration = DcmStorageSCP::FGM_ShortUniquePseudoRandom; + if (cmd.findOption("--system-time-names")) + opt_filenameGeneration = DcmStorageSCP::FGM_CurrentSystemTime; + cmd.endOptionBlock(); + + if (cmd.findOption("--filename-extension")) + app.checkValue(cmd.getValue(opt_filenameExtension)); + + cmd.beginOptionBlock(); + if (cmd.findOption("--normal")) + opt_datasetStorage = DcmStorageSCP::DGM_StoreToFile; + if (cmd.findOption("--bit-preserving")) + { + app.checkConflict("--bit-preserving", "--series-date-subdir", opt_directoryGeneration == DcmStorageSCP::DGM_SeriesDate); + opt_datasetStorage = DcmStorageSCP::DGM_StoreBitPreserving; + } + if (cmd.findOption("--ignore")) + opt_datasetStorage = DcmStorageSCP::DSM_Ignore; + cmd.endOptionBlock(); + + /* command line parameters */ + app.checkParam(cmd.getParamAndCheckMinMax(1, opt_port, 1, 65535)); + } + + /* print resource identifier */ + OFLOG_DEBUG(dcmrecvLogger, rcsid << OFendl); + + /* make sure data dictionary is loaded */ + if (!dcmDataDict.isDictionaryLoaded()) + { + OFLOG_WARN(dcmrecvLogger, "no data dictionary loaded, check environment variable: " + << DCM_DICT_ENVIRONMENT_VARIABLE); + } + + /* start with the real work */ + DcmStorageSCP storageSCP; + OFCondition status; + + OFLOG_INFO(dcmrecvLogger, "configuring service class provider ..."); + + /* set general network parameters */ + storageSCP.setPort(OFstatic_cast(Uint16, opt_port)); + storageSCP.setAETitle(opt_aeTitle); + storageSCP.setMaxReceivePDULength(OFstatic_cast(Uint32, opt_maxPDULength)); + storageSCP.setACSETimeout(OFstatic_cast(Uint32, opt_acseTimeout)); + storageSCP.setDIMSETimeout(OFstatic_cast(Uint32, opt_dimseTimeout)); + storageSCP.setDIMSEBlockingMode(opt_blockingMode); + storageSCP.setVerbosePCMode(opt_showPresentationContexts); + storageSCP.setRespondWithCalledAETitle(opt_useCalledAETitle); + storageSCP.setHostLookupEnabled(opt_HostnameLookup); + storageSCP.setDirectoryGenerationMode(opt_directoryGeneration); + storageSCP.setFilenameGenerationMode(opt_filenameGeneration); + storageSCP.setFilenameExtension(opt_filenameExtension); + storageSCP.setDatasetStorageMode(opt_datasetStorage); + + /* load association negotiation profile from configuration file (if specified) */ + if ((opt_configFile != NULL) && (opt_profileName != NULL)) + { + status = storageSCP.loadAssociationConfiguration(opt_configFile, opt_profileName); + if (status.bad()) + { + OFLOG_FATAL(dcmrecvLogger, "cannot load association configuration: " << status.text()); + return EXITCODE_INVALID_ASSOCIATION_CONFIG; + } + } else { + /* report a warning message that the SCP will not accept any Storage SOP Classes */ + OFLOG_WARN(dcmrecvLogger, "no configuration file specified, SCP will only support the Verification SOP Class"); + } + + /* specify the output directory (also checks whether directory exists and is writable) */ + status = storageSCP.setOutputDirectory(opt_outputDirectory); + if (status.bad()) + { + OFLOG_FATAL(dcmrecvLogger, "cannot specify output directory: " << status.text()); + return EXITCODE_INVALID_OUTPUT_DIRECTORY; + } + + OFLOG_INFO(dcmrecvLogger, "starting service class provider and listening ..."); + + /* start SCP and listen on the specified port */ + status = storageSCP.listen(); + if (status.bad()) + { + OFLOG_FATAL(dcmrecvLogger, "cannot start SCP and listen on port " << opt_port << ": " << status.text()); + return EXITCODE_CANNOT_START_SCP_AND_LISTEN; + } + + /* make sure that everything is cleaned up properly */ +#ifdef DEBUG + /* useful for debugging with dmalloc */ + dcmDataDict.clear(); +#endif + + return EXITCODE_NO_ERROR; +} diff --git a/dcmnet/apps/dcmsend.cc b/dcmnet/apps/dcmsend.cc new file mode 100644 index 00000000..51a3d2de --- /dev/null +++ b/dcmnet/apps/dcmsend.cc @@ -0,0 +1,586 @@ +/* + * + * Copyright (C) 2011-2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmnet + * + * Author: Joerg Riesmeier + * + * Purpose: Simple Storage Service Class User + * + */ + + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#include "dcmtk/ofstd/ofstd.h" /* for OFStandard functions */ +#include "dcmtk/ofstd/ofconapp.h" /* for OFConsoleApplication */ +#include "dcmtk/ofstd/ofstream.h" /* for OFStringStream et al. */ +#include "dcmtk/dcmdata/dcdict.h" /* for global data dictionary */ +#include "dcmtk/dcmdata/dcuid.h" /* for dcmtk version name */ +#include "dcmtk/dcmdata/cmdlnarg.h" /* for prepareCmdLineArgs */ +#include "dcmtk/dcmdata/dcostrmz.h" /* for dcmZlibCompressionLevel */ +#include "dcmtk/dcmnet/dstorscu.h" /* for DcmStorageSCU */ + +#include "dcmtk/dcmjpeg/djdecode.h" /* for JPEG decoders */ +#include "dcmtk/dcmjpls/djdecode.h" /* for JPEG-LS decoders */ +#include "dcmtk/dcmdata/dcrledrg.h" /* for RLE decoder */ +#include "dcmtk/dcmjpeg/dipijpeg.h" /* for dcmimage JPEG plugin */ + + +#ifdef WITH_ZLIB +#include /* for zlibVersion() */ +#endif + +#if defined (HAVE_WINDOWS_H) || defined(HAVE_FNMATCH_H) +#define PATTERN_MATCHING_AVAILABLE +#endif + + +/* general definitions */ + +#define OFFIS_CONSOLE_APPLICATION "dcmsend" + +static OFLogger dcmsendLogger = OFLog::getLogger("dcmtk.apps." OFFIS_CONSOLE_APPLICATION); + +static char rcsid[] = "$dcmtk: " OFFIS_CONSOLE_APPLICATION " v" + OFFIS_DCMTK_VERSION " " OFFIS_DCMTK_RELEASEDATE " $"; + +/* default application entity titles */ +#define APPLICATIONTITLE "DCMSEND" +#define PEERAPPLICATIONTITLE "ANY-SCP" + + +/* exit codes for this command line tool */ +/* (EXIT_SUCCESS and EXIT_FAILURE are standard codes) */ + +// general +#define EXITCODE_NO_ERROR 0 +#define EXITCODE_COMMANDLINE_SYNTAX_ERROR 1 // this code is the default for printError() + +// input file errors +#define EXITCODE_CANNOT_READ_INPUT_FILE 20 // placeholder, currently not used +#define EXITCODE_NO_INPUT_FILES 21 +#define EXITCODE_INVALID_INPUT_FILE 22 +#define EXITCODE_NO_VALID_INPUT_FILES 23 + +// output file errors +#define EXITCODE_CANNOT_WRITE_OUTPUT_FILE 40 // placeholder, currently not used +#define EXITCODE_CANNOT_WRITE_REPORT_FILE 43 + +// network errors +#define EXITCODE_CANNOT_INITIALIZE_NETWORK 60 +#define EXITCODE_CANNOT_NEGOTIATE_ASSOCIATION 61 +#define EXITCODE_CANNOT_SEND_REQUEST 62 +#define EXITCODE_CANNOT_ADD_PRESENTATION_CONTEXT 65 + + +/* helper macro for converting stream output to a string */ +#define CONVERT_TO_STRING(output, string) \ + optStream.str(""); \ + optStream.clear(); \ + optStream << output << OFStringStream_ends; \ + OFSTRINGSTREAM_GETOFSTRING(optStream, string) + + +/* static helper functions */ + +// make sure that everything is cleaned up properly +static void cleanup() +{ + // deregister JPEG decoder + DJDecoderRegistration::cleanup(); + // deregister JPEG-LS decoder + DJLSDecoderRegistration::cleanup(); + // deregister RLE decoder + DcmRLEDecoderRegistration::cleanup(); +#ifdef DEBUG + /* useful for debugging with dmalloc */ + dcmDataDict.clear(); +#endif +} + + +/* main program */ + +#define SHORTCOL 4 +#define LONGCOL 21 + +int main(int argc, char *argv[]) +{ + OFOStringStream optStream; + + const char *opt_peer = NULL; + const char *opt_peerTitle = PEERAPPLICATIONTITLE; + const char *opt_ourTitle = APPLICATIONTITLE; + + E_FileReadMode opt_readMode = ERM_fileOnly; + + OFCmdUnsignedInt opt_port = 0; + OFCmdUnsignedInt opt_timeout = 0; + OFCmdUnsignedInt opt_dimseTimeout = 0; + OFCmdUnsignedInt opt_acseTimeout = 30; + OFCmdUnsignedInt opt_maxReceivePDULength = ASC_DEFAULTMAXPDU; + OFCmdUnsignedInt opt_maxSendPDULength = 0; + T_DIMSE_BlockingMode opt_blockMode = DIMSE_BLOCKING; +#ifdef WITH_ZLIB + OFCmdUnsignedInt opt_compressionLevel = 0; +#endif + + OFBool opt_showPresentationContexts = OFFalse; + OFBool opt_haltOnInvalidFile = OFTrue; + OFBool opt_haltOnUnsuccessfulStore = OFTrue; + OFBool opt_allowIllegalProposal = OFTrue; + OFBool opt_checkUIDValues = OFTrue; + OFBool opt_multipleAssociations = OFTrue; + DcmStorageSCU::E_DecompressionMode opt_decompressionMode = DcmStorageSCU::DM_losslessOnly; + + OFBool opt_dicomDir = OFFalse; + OFBool opt_scanDir = OFFalse; + OFBool opt_recurse = OFFalse; + const char *opt_scanPattern = ""; + const char *opt_reportFilename = ""; + + int paramCount = 0; + + OFConsoleApplication app(OFFIS_CONSOLE_APPLICATION , "Simple DICOM storage SCU (sender)", rcsid); + OFCommandLine cmd; + + cmd.setParamColumn(LONGCOL + SHORTCOL + 4); + cmd.addParam("peer", "hostname of DICOM peer"); + cmd.addParam("port", "tcp/ip port number of peer"); + cmd.addParam("dcmfile-in", "DICOM file or directory to be transmitted", OFCmdParam::PM_MultiMandatory); + + cmd.setOptionColumns(LONGCOL, SHORTCOL); + cmd.addGroup("general options:", LONGCOL, SHORTCOL + 2); + cmd.addOption("--help", "-h", "print this help text and exit", OFCommandLine::AF_Exclusive); + cmd.addOption("--version", "print version information and exit", OFCommandLine::AF_Exclusive); + cmd.addOption("--list-decoders", "list transfer syntaxes of decoders and exit", OFCommandLine::AF_Exclusive); + OFLog::addOptions(cmd); + cmd.addOption("--verbose-pc", "+v", "show presentation contexts in verbose mode"); + + cmd.addGroup("input options:"); + cmd.addSubGroup("input file format:"); + cmd.addOption("--read-file", "+f", "read file format or data set"); + cmd.addOption("--read-file-only", "+fo", "read file format only (default)"); + cmd.addOption("--read-dataset", "-f", "read data set without file meta information"); + cmd.addSubGroup("input files:"); + cmd.addOption("--read-from-dicomdir", "+rd", "read information on input files from DICOMDIR"); + cmd.addOption("--scan-directories", "+sd", "scan directories for input files (dcmfile-in)"); +#ifdef PATTERN_MATCHING_AVAILABLE + cmd.addOption("--scan-pattern", "+sp", 1, "[p]attern: string (only w/ --scan-directories)", + "pattern for filename matching (wildcards)"); +#endif + cmd.addOption("--no-recurse", "-r", "do not recurse within directories (default)"); + cmd.addOption("--recurse", "+r", "recurse within specified directories"); + + cmd.addGroup("processing options:"); + cmd.addSubGroup("transfer syntax conversion:"); + cmd.addOption("--decompress-never", "-dn", "never decompress compressed data sets"); + cmd.addOption("--decompress-lossless", "+dls", "only decompress lossless compression (default)"); + cmd.addOption("--decompress-lossy", "+dly", "decompress both lossy and lossless compression"); +#ifdef WITH_ZLIB + cmd.addSubGroup("deflate compression level:"); + cmd.addOption("--compression-level", "+cl", 1, "[l]evel: integer (default: 6)", + "0=uncompressed, 1=fastest, 9=best compression"); +#endif + cmd.addSubGroup("other processing options:"); + cmd.addOption("--no-halt", "-nh", "do not halt on first invalid input file\nor if unsuccessful store encountered"); + cmd.addOption("--no-illegal-proposal", "-nip", "do not propose any presentation context that\ndoes not contain the default TS (if needed)"); + cmd.addOption("--no-uid-checks", "-nuc", "do not check UID values of input files"); + + cmd.addGroup("network options:"); + cmd.addSubGroup("application entity titles:"); + cmd.addOption("--aetitle", "-aet", 1, "[a]etitle: string", + "set my calling AE title (default: " APPLICATIONTITLE ")"); + cmd.addOption("--call", "-aec", 1, "[a]etitle: string", + "set called AE title of peer (default: " PEERAPPLICATIONTITLE ")"); + cmd.addSubGroup("association handling:"); + cmd.addOption("--multi-associations", "+ma", "use multiple associations (one after the other)\nif needed to transfer the instances (default)"); + cmd.addOption("--single-association", "-ma", "always use a single association"); + cmd.addSubGroup("other network options:"); + cmd.addOption("--timeout", "-to", 1, "[s]econds: integer (default: unlimited)", + "timeout for connection requests"); + CONVERT_TO_STRING("[s]econds: integer (default: " << opt_acseTimeout << ")", optString1); + cmd.addOption("--acse-timeout", "-ta", 1, optString1.c_str(), + "timeout for ACSE messages"); + cmd.addOption("--dimse-timeout", "-td", 1, "[s]econds: integer (default: unlimited)", + "timeout for DIMSE messages"); + CONVERT_TO_STRING("[n]umber of bytes: integer (" << ASC_MINIMUMPDUSIZE << ".." << ASC_MAXIMUMPDUSIZE << ")", optString2); + CONVERT_TO_STRING("set max receive pdu to n bytes (default: " << opt_maxReceivePDULength << ")", optString3); + cmd.addOption("--max-pdu", "-pdu", 1, optString2.c_str(), + optString3.c_str()); + cmd.addOption("--max-send-pdu", 1, optString2.c_str(), + "restrict max send pdu to n bytes"); + cmd.addGroup("output options:"); + cmd.addSubGroup("general:"); + cmd.addOption("--create-report-file", "+crf", 1, "[f]ilename: string", + "create a detailed report on the transfer\n(if successful) and write it to text file f"); + + /* evaluate command line */ + prepareCmdLineArgs(argc, argv, OFFIS_CONSOLE_APPLICATION); + if (app.parseCommandLine(cmd, argc, argv)) + { + /* check exclusive options first */ + if (cmd.hasExclusiveOption()) + { + if (cmd.findOption("--version")) + { + app.printHeader(OFTrue /*print host identifier*/); + COUT << OFendl << "External libraries used:" << OFendl; +#ifdef WITH_ZLIB + COUT << "- ZLIB, Version " << zlibVersion() << OFendl; +#endif + COUT << "- " << DiJPEGPlugin::getLibraryVersionString() << OFendl; + COUT << "- " << DJLSDecoderRegistration::getLibraryVersionString() << OFendl; + return EXITCODE_NO_ERROR; + } + if (cmd.findOption("--list-decoders")) + { + app.printHeader(OFFalse /*print host identifier*/); + COUT << OFendl << "Transfer syntaxes supported natively:" << OFendl; + COUT << "- " << DcmXfer(EXS_LittleEndianImplicit).getXferName() << OFendl; + COUT << "- " << DcmXfer(EXS_LittleEndianExplicit).getXferName() << OFendl; + COUT << "- " << DcmXfer(EXS_BigEndianExplicit).getXferName() << OFendl; + COUT << OFendl << "Transfer syntaxes supported by decoders:" << OFendl; +#ifdef WITH_ZLIB + COUT << "- " << DcmXfer(EXS_DeflatedLittleEndianExplicit).getXferName() << OFendl; +#endif + COUT << "- " << DcmXfer(EXS_JPEGProcess1).getXferName() << OFendl; + COUT << "- " << DcmXfer(EXS_JPEGProcess2_4).getXferName() << OFendl; + COUT << "- " << DcmXfer(EXS_JPEGProcess6_8).getXferName() << OFendl; + COUT << "- " << DcmXfer(EXS_JPEGProcess10_12).getXferName() << OFendl; + COUT << "- " << DcmXfer(EXS_JPEGProcess14).getXferName() << OFendl; + COUT << "- " << DcmXfer(EXS_JPEGProcess14SV1).getXferName() << OFendl; + COUT << "- " << DcmXfer(EXS_JPEGLSLossless).getXferName() << OFendl; + COUT << "- " << DcmXfer(EXS_JPEGLSLossy).getXferName() << OFendl; + COUT << "- " << DcmXfer(EXS_RLELossless).getXferName() << OFendl; + return EXITCODE_NO_ERROR; + } + } + + /* general options */ + OFLog::configureFromCommandLine(cmd, app); + if (cmd.findOption("--verbose-pc")) + { + app.checkDependence("--verbose-pc", "verbose mode", dcmsendLogger.isEnabledFor(OFLogger::INFO_LOG_LEVEL)); + opt_showPresentationContexts = OFTrue; + } + + /* input options */ + cmd.beginOptionBlock(); + if (cmd.findOption("--read-file")) opt_readMode = ERM_autoDetect; + if (cmd.findOption("--read-file-only")) opt_readMode = ERM_fileOnly; + if (cmd.findOption("--read-dataset")) opt_readMode = ERM_dataset; + cmd.endOptionBlock(); + + if (cmd.findOption("--read-from-dicomdir")) opt_dicomDir = OFTrue; + if (cmd.findOption("--scan-directories")) opt_scanDir = OFTrue; +#ifdef PATTERN_MATCHING_AVAILABLE + if (cmd.findOption("--scan-pattern")) + { + app.checkDependence("--scan-pattern", "--scan-directories", opt_scanDir); + app.checkValue(cmd.getValue(opt_scanPattern)); + } +#endif + cmd.beginOptionBlock(); + if (cmd.findOption("--no-recurse")) opt_recurse = OFFalse; + if (cmd.findOption("--recurse")) + { + app.checkDependence("--recurse", "--scan-directories", opt_scanDir); + opt_recurse = OFTrue; + } + cmd.endOptionBlock(); + + /* processing options */ + cmd.beginOptionBlock(); + if (cmd.findOption("--decompress-never")) opt_decompressionMode = DcmStorageSCU::DM_never; + if (cmd.findOption("--decompress-lossless")) opt_decompressionMode = DcmStorageSCU::DM_losslessOnly; + if (cmd.findOption("--decompress-lossy")) opt_decompressionMode = DcmStorageSCU::DM_lossyAndLossless; + cmd.endOptionBlock(); +#ifdef WITH_ZLIB + if (cmd.findOption("--compression-level")) + { + app.checkValue(cmd.getValueAndCheckMinMax(opt_compressionLevel, 0, 9)); + dcmZlibCompressionLevel.set(OFstatic_cast(int, opt_compressionLevel)); + } +#endif + if (cmd.findOption("--no-halt")) + { + opt_haltOnInvalidFile = OFFalse; + opt_haltOnUnsuccessfulStore = OFFalse; + } + if (cmd.findOption("--no-illegal-proposal")) opt_allowIllegalProposal = OFFalse; + if (cmd.findOption("--no-uid-checks")) opt_checkUIDValues = OFFalse; + + /* network options */ + if (cmd.findOption("--aetitle")) app.checkValue(cmd.getValue(opt_ourTitle)); + if (cmd.findOption("--call")) app.checkValue(cmd.getValue(opt_peerTitle)); + + cmd.beginOptionBlock(); + if (cmd.findOption("--multi-associations")) opt_multipleAssociations = OFTrue; + if (cmd.findOption("--single-association")) opt_multipleAssociations = OFFalse; + cmd.endOptionBlock(); + + if (cmd.findOption("--timeout")) + { + app.checkValue(cmd.getValueAndCheckMin(opt_timeout, 1)); + dcmConnectionTimeout.set(OFstatic_cast(Sint32, opt_timeout)); + } + if (cmd.findOption("--acse-timeout")) + app.checkValue(cmd.getValueAndCheckMin(opt_acseTimeout, 1)); + if (cmd.findOption("--dimse-timeout")) + { + app.checkValue(cmd.getValueAndCheckMin(opt_dimseTimeout, 1)); + opt_blockMode = DIMSE_NONBLOCKING; + } + if (cmd.findOption("--max-pdu")) + app.checkValue(cmd.getValueAndCheckMinMax(opt_maxReceivePDULength, ASC_MINIMUMPDUSIZE, ASC_MAXIMUMPDUSIZE)); + if (cmd.findOption("--max-send-pdu")) + { + app.checkValue(cmd.getValueAndCheckMinMax(opt_maxSendPDULength, ASC_MINIMUMPDUSIZE, ASC_MAXIMUMPDUSIZE)); + dcmMaxOutgoingPDUSize.set(OFstatic_cast(Uint32, opt_maxSendPDULength)); + } + + /* output options */ + if (cmd.findOption("--create-report-file")) + app.checkValue(cmd.getValue(opt_reportFilename)); + + /* command line parameters */ + paramCount = cmd.getParamCount(); + cmd.getParam(1, opt_peer); + app.checkParam(cmd.getParamAndCheckMinMax(2, opt_port, 1, 65535)); + } + + // register JPEG decoder + DJDecoderRegistration::registerCodecs(); + // register JPEG-LS decoder + DJLSDecoderRegistration::registerCodecs(); + // register RLE decoder + DcmRLEDecoderRegistration::registerCodecs(); + + /* print resource identifier */ + OFLOG_DEBUG(dcmsendLogger, rcsid << OFendl); + + /* make sure data dictionary is loaded */ + if (!dcmDataDict.isDictionaryLoaded()) + { + OFLOG_WARN(dcmsendLogger, "no data dictionary loaded, check environment variable: " + << DCM_DICT_ENVIRONMENT_VARIABLE); + } + + /* start with the real work */ + if (opt_scanDir) + OFLOG_INFO(dcmsendLogger, "determining input files ..."); + /* iterate over all input filenames/directories */ + OFList inputFiles; + const char *paramString = NULL; + for (int i = 3; i <= paramCount; i++) + { + cmd.getParam(i, paramString); + /* search directory recursively (if required) */ + if (OFStandard::dirExists(paramString)) + { + if (opt_scanDir) + OFStandard::searchDirectoryRecursively(paramString, inputFiles, opt_scanPattern, "" /* dirPrefix */, opt_recurse); + else + OFLOG_WARN(dcmsendLogger, "ignoring directory because option --scan-directories is not set: " << paramString); + } else + inputFiles.push_back(paramString); + } + + /* check whether there are any input files at all */ + if (inputFiles.empty()) + { + OFLOG_FATAL(dcmsendLogger, "no input files to be processed"); + cleanup(); + return EXITCODE_NO_INPUT_FILES; + } + + DcmStorageSCU storageSCU; + OFCondition status; + unsigned long numInvalidFiles = 0; + + /* set parameters used for processing the input files */ + storageSCU.setReadFromDICOMDIRMode(opt_dicomDir); + storageSCU.setHaltOnInvalidFileMode(opt_haltOnInvalidFile); + + OFLOG_INFO(dcmsendLogger, "checking input files ..."); + /* iterate over all input filenames */ + const char *currentFilename = NULL; + OFListIterator(OFString) if_iter = inputFiles.begin(); + OFListIterator(OFString) if_last = inputFiles.end(); + while (if_iter != if_last) + { + currentFilename = (*if_iter).c_str(); + /* and add them to the list of instances to be transmitted */ + status = storageSCU.addDicomFile(currentFilename, opt_readMode, opt_checkUIDValues); + if (status.bad()) + { + /* check for empty filename */ + if (strlen(currentFilename) == 0) + currentFilename = ""; + /* if something went wrong, we either terminate or ignore the file */ + if (opt_haltOnInvalidFile) + { + OFLOG_FATAL(dcmsendLogger, "bad DICOM file: " << currentFilename << ": " << status.text()); + cleanup(); + return EXITCODE_INVALID_INPUT_FILE; + } else { + OFLOG_WARN(dcmsendLogger, "bad DICOM file: " << currentFilename << ": " << status.text() << ", ignoring file"); + } + ++numInvalidFiles; + } + ++if_iter; + } + + /* check whether there are any valid input files */ + if (storageSCU.getNumberOfSOPInstances() == 0) + { + OFLOG_FATAL(dcmsendLogger, "no valid input files to be processed"); + cleanup(); + return EXITCODE_NO_VALID_INPUT_FILES; + } else { + OFLOG_DEBUG(dcmsendLogger, "in total, there are " << storageSCU.getNumberOfSOPInstances() + << " SOP instances to be sent, " << numInvalidFiles << " invalid files are ignored"); + } + + /* set network parameters */ + storageSCU.setPeerHostName(opt_peer); + storageSCU.setPeerPort(OFstatic_cast(Uint16, opt_port)); + storageSCU.setPeerAETitle(opt_peerTitle); + storageSCU.setAETitle(opt_ourTitle); + storageSCU.setMaxReceivePDULength(OFstatic_cast(Uint32, opt_maxReceivePDULength)); + storageSCU.setACSETimeout(OFstatic_cast(Uint32, opt_acseTimeout)); + storageSCU.setDIMSETimeout(OFstatic_cast(Uint32, opt_dimseTimeout)); + storageSCU.setDIMSEBlockingMode(opt_blockMode); + storageSCU.setVerbosePCMode(opt_showPresentationContexts); + storageSCU.setDatasetConversionMode(opt_decompressionMode != DcmStorageSCU::DM_never); + storageSCU.setDecompressionMode(opt_decompressionMode); + storageSCU.setHaltOnUnsuccessfulStoreMode(opt_haltOnUnsuccessfulStore); + storageSCU.setAllowIllegalProposalMode(opt_allowIllegalProposal); + + /* output information on the single/multiple associations setting */ + if (opt_multipleAssociations) + { + OFLOG_DEBUG(dcmsendLogger, "multiple associations allowed (option --multi-associations used)"); + } else { + OFLOG_DEBUG(dcmsendLogger, "only a single associations allowed (option --single-association used)"); + } + + /* add presentation contexts to be negotiated (if there are still any) */ + while ((status = storageSCU.addPresentationContexts()).good()) + { + if (opt_multipleAssociations) + { + /* output information on the start of the new association */ + if (dcmsendLogger.isEnabledFor(OFLogger::DEBUG_LOG_LEVEL)) + { + OFLOG_DEBUG(dcmsendLogger, OFString(65, '-') << OFendl + << "starting association #" << (storageSCU.getAssociationCounter() + 1)); + } else { + OFLOG_INFO(dcmsendLogger, "starting association #" << (storageSCU.getAssociationCounter() + 1)); + } + } + OFLOG_INFO(dcmsendLogger, "initializing network ..."); + /* initialize network */ + status = storageSCU.initNetwork(); + if (status.bad()) + { + OFLOG_FATAL(dcmsendLogger, "cannot initialize network: " << status.text()); + cleanup(); + return EXITCODE_CANNOT_INITIALIZE_NETWORK; + } + OFLOG_INFO(dcmsendLogger, "negotiating network association ..."); + /* negotiate network association with peer */ + status = storageSCU.negotiateAssociation(); + if (status.bad()) + { + // check whether we can continue with a new association + if (status == NET_EC_NoAcceptablePresentationContexts) + { + OFLOG_ERROR(dcmsendLogger, "cannot negotiate network association: " << status.text()); + // check whether there are any SOP instances to be sent + const size_t numToBeSent = storageSCU.getNumberOfSOPInstancesToBeSent(); + if (numToBeSent > 0) + { + OFLOG_WARN(dcmsendLogger, "trying to continue with a new association " + << "in order to send the remaining " << numToBeSent << " SOP instances"); + } + } else { + OFLOG_FATAL(dcmsendLogger, "cannot negotiate network association: " << status.text()); + cleanup(); + return EXITCODE_CANNOT_NEGOTIATE_ASSOCIATION; + } + } + if (status.good()) + { + OFLOG_INFO(dcmsendLogger, "sending SOP instances ..."); + /* send SOP instances to be transferred */ + status = storageSCU.sendSOPInstances(); + if (status.bad()) + { + OFLOG_FATAL(dcmsendLogger, "cannot send SOP instance: " << status.text()); + // handle certain error conditions (initiated by the communication peer) + if (status == DUL_PEERREQUESTEDRELEASE) + { + // peer requested release (aborting) + storageSCU.closeAssociation(DCMSCU_PEER_REQUESTED_RELEASE); + } + else if (status == DUL_PEERABORTEDASSOCIATION) + { + // peer aborted the association + storageSCU.closeAssociation(DCMSCU_PEER_ABORTED_ASSOCIATION); + } + cleanup(); + return EXITCODE_CANNOT_SEND_REQUEST; + } + } + /* close current network association */ + storageSCU.releaseAssociation(); + /* check whether multiple associations are permitted */ + if (!opt_multipleAssociations) + break; + } + + /* if anything went wrong, report it to the logger */ + if (status.bad() && (status != NET_EC_NoPresentationContextsDefined)) + { + OFLOG_ERROR(dcmsendLogger, "cannot add presentation contexts: " << status.text()); + cleanup(); + return EXITCODE_CANNOT_ADD_PRESENTATION_CONTEXT; + } + + /* create a detailed report on the transfer of instances ... */ + if ((opt_reportFilename != NULL) && (strlen(opt_reportFilename) > 0)) + { + /* ... and write it to the specified text file */ + status = storageSCU.createReportFile(opt_reportFilename); + if (status.bad()) + { + cleanup(); + return EXITCODE_CANNOT_WRITE_REPORT_FILE; // TODO: do we really want to exit? + } + } + + /* output some status information on the overall sending process */ + if (dcmsendLogger.isEnabledFor(OFLogger::INFO_LOG_LEVEL)) + { + OFString summaryText; + storageSCU.getStatusSummary(summaryText); + OFLOG_INFO(dcmsendLogger, OFendl << summaryText); + } + + /* make sure that everything is cleaned up properly */ + cleanup(); + return EXITCODE_NO_ERROR; +} diff --git a/dcmnet/apps/echoscu.cc b/dcmnet/apps/echoscu.cc new file mode 100644 index 00000000..cd63fb7c --- /dev/null +++ b/dcmnet/apps/echoscu.cc @@ -0,0 +1,741 @@ +/* + * + * Copyright (C) 1994-2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmnet + * + * Author: Andrew Hewett + * + * Purpose: Verification Service Class User (C-ECHO operation) + * + */ + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#define INCLUDE_CSTDLIB +#define INCLUDE_CSTDIO +#define INCLUDE_CSTRING +#define INCLUDE_CSTDARG +#include "dcmtk/ofstd/ofstdinc.h" + +#include "dcmtk/dcmnet/dimse.h" +#include "dcmtk/dcmnet/diutil.h" +#include "dcmtk/dcmdata/dcfilefo.h" +#include "dcmtk/dcmdata/dcdict.h" +#include "dcmtk/dcmdata/dcuid.h" +#include "dcmtk/dcmdata/cmdlnarg.h" +#include "dcmtk/ofstd/ofconapp.h" +#include "dcmtk/dcmdata/dcuid.h" /* for dcmtk version name */ + +#ifdef WITH_OPENSSL +#include "dcmtk/dcmtls/tlstrans.h" +#include "dcmtk/dcmtls/tlslayer.h" +#endif + +#ifdef WITH_ZLIB +#include /* for zlibVersion() */ +#endif + +#ifdef PRIVATE_ECHOSCU_DECLARATIONS +PRIVATE_ECHOSCU_DECLARATIONS +#else +#define OFFIS_CONSOLE_APPLICATION "echoscu" +#endif + +static OFLogger echoscuLogger = OFLog::getLogger("dcmtk.apps." OFFIS_CONSOLE_APPLICATION); + +static char rcsid[] = "$dcmtk: " OFFIS_CONSOLE_APPLICATION " v" + OFFIS_DCMTK_VERSION " " OFFIS_DCMTK_RELEASEDATE " $"; + +/* default application titles */ +#define APPLICATIONTITLE "ECHOSCU" +#define PEERAPPLICATIONTITLE "ANY-SCP" + +static T_DIMSE_BlockingMode opt_blockMode = DIMSE_BLOCKING; +static int opt_dimse_timeout = 0; + +static OFCondition cecho(T_ASC_Association * assoc, unsigned long num_repeat); + +/* DICOM standard transfer syntaxes */ +static const char* transferSyntaxes[] = { + UID_LittleEndianImplicitTransferSyntax, /* default xfer syntax first */ + UID_LittleEndianExplicitTransferSyntax, + UID_BigEndianExplicitTransferSyntax, + UID_JPEGProcess1TransferSyntax, + UID_JPEGProcess2_4TransferSyntax, + UID_JPEGProcess3_5TransferSyntax, + UID_JPEGProcess6_8TransferSyntax, + UID_JPEGProcess7_9TransferSyntax, + UID_JPEGProcess10_12TransferSyntax, + UID_JPEGProcess11_13TransferSyntax, + UID_JPEGProcess14TransferSyntax, + UID_JPEGProcess15TransferSyntax, + UID_JPEGProcess16_18TransferSyntax, + UID_JPEGProcess17_19TransferSyntax, + UID_JPEGProcess20_22TransferSyntax, + UID_JPEGProcess21_23TransferSyntax, + UID_JPEGProcess24_26TransferSyntax, + UID_JPEGProcess25_27TransferSyntax, + UID_JPEGProcess28TransferSyntax, + UID_JPEGProcess29TransferSyntax, + UID_JPEGProcess14SV1TransferSyntax, + UID_RLELosslessTransferSyntax, + UID_JPEGLSLosslessTransferSyntax, + UID_JPEGLSLossyTransferSyntax, + UID_DeflatedExplicitVRLittleEndianTransferSyntax, + UID_JPEG2000LosslessOnlyTransferSyntax, + UID_JPEG2000TransferSyntax, + UID_MPEG2MainProfileAtMainLevelTransferSyntax, + UID_MPEG2MainProfileAtHighLevelTransferSyntax, + UID_JPEG2000Part2MulticomponentImageCompressionLosslessOnlyTransferSyntax, + UID_JPEG2000Part2MulticomponentImageCompressionTransferSyntax, + UID_MPEG4HighProfileLevel4_1TransferSyntax, + UID_MPEG4BDcompatibleHighProfileLevel4_1TransferSyntax, + UID_MPEG4HighProfileLevel4_2_For2DVideoTransferSyntax, + UID_MPEG4HighProfileLevel4_2_For3DVideoTransferSyntax, + UID_MPEG4StereoHighProfileLevel4_2TransferSyntax +}; + +// ******************************************** + +#define SHORTCOL 4 +#define LONGCOL 19 + +int +main(int argc, char *argv[]) +{ + const char * opt_peer = NULL; + OFCmdUnsignedInt opt_port = 104; + const char * opt_peerTitle = PEERAPPLICATIONTITLE; + const char * opt_ourTitle = APPLICATIONTITLE; + OFCmdUnsignedInt opt_maxReceivePDULength = ASC_DEFAULTMAXPDU; + OFCmdUnsignedInt opt_repeatCount = 1; + OFBool opt_abortAssociation = OFFalse; + OFCmdUnsignedInt opt_numXferSyntaxes = 1; + OFCmdUnsignedInt opt_numPresentationCtx = 1; + OFCmdUnsignedInt maxXferSyntaxes = OFstatic_cast(OFCmdUnsignedInt, (DIM_OF(transferSyntaxes))); + OFBool opt_secureConnection = OFFalse; /* default: no secure connection */ + int opt_acse_timeout = 30; + +#ifdef WITH_OPENSSL + int opt_keyFileFormat = SSL_FILETYPE_PEM; + OFBool opt_doAuthenticate = OFFalse; + const char *opt_privateKeyFile = NULL; + const char *opt_certificateFile = NULL; + const char *opt_passwd = NULL; +#if OPENSSL_VERSION_NUMBER >= 0x0090700fL + OFString opt_ciphersuites(TLS1_TXT_RSA_WITH_AES_128_SHA ":" SSL3_TXT_RSA_DES_192_CBC3_SHA); +#else + OFString opt_ciphersuites(SSL3_TXT_RSA_DES_192_CBC3_SHA); +#endif + const char *opt_readSeedFile = NULL; + const char *opt_writeSeedFile = NULL; + DcmCertificateVerification opt_certVerification = DCV_requireCertificate; + const char *opt_dhparam = NULL; +#endif + + T_ASC_Network *net; + T_ASC_Parameters *params; + DIC_NODENAME localHost; + DIC_NODENAME peerHost; + T_ASC_Association *assoc; + OFString temp_str; + +#ifdef HAVE_GUSI_H + /* needed for Macintosh */ + GUSISetup(GUSIwithSIOUXSockets); + GUSISetup(GUSIwithInternetSockets); +#endif + +#ifdef HAVE_WINSOCK_H + WSAData winSockData; + /* we need at least version 1.1 */ + WORD winSockVersionNeeded = MAKEWORD( 1, 1 ); + WSAStartup(winSockVersionNeeded, &winSockData); +#endif + + char tempstr[20]; + OFConsoleApplication app(OFFIS_CONSOLE_APPLICATION , "DICOM verification (C-ECHO) SCU", rcsid); + OFCommandLine cmd; + + cmd.setParamColumn(LONGCOL + SHORTCOL + 4); + cmd.addParam("peer", "hostname of DICOM peer"); + cmd.addParam("port", "tcp/ip port number of peer"); + + cmd.setOptionColumns(LONGCOL, SHORTCOL); + cmd.addGroup("general options:", LONGCOL, SHORTCOL + 2); + cmd.addOption("--help", "-h", "print this help text and exit", OFCommandLine::AF_Exclusive); + cmd.addOption("--version", "print version information and exit", OFCommandLine::AF_Exclusive); + OFLog::addOptions(cmd); + + cmd.addGroup("network options:"); + cmd.addSubGroup("application entity titles:"); + OFString opt1 = "set my calling AE title (default: "; + opt1 += APPLICATIONTITLE; + opt1 += ")"; + cmd.addOption("--aetitle", "-aet", 1, "[a]etitle: string", opt1.c_str()); + OFString opt2 = "set called AE title of peer (default: "; + opt2 += PEERAPPLICATIONTITLE; + opt2 += ")"; + cmd.addOption("--call", "-aec", 1, "[a]etitle: string", opt2.c_str()); + cmd.addSubGroup("association negotiation debugging:"); + OFString opt5 = "[n]umber: integer (1.."; + sprintf(tempstr, "%ld", OFstatic_cast(long, maxXferSyntaxes)); + opt5 += tempstr; + opt5 += ")"; + cmd.addOption("--propose-ts", "-pts", 1, opt5.c_str(), "propose n transfer syntaxes"); + cmd.addOption("--propose-pc", "-ppc", 1, "[n]umber: integer (1..128)", "propose n presentation contexts"); + + cmd.addSubGroup("other network options:"); + cmd.addOption("--timeout", "-to", 1, "[s]econds: integer (default: unlimited)", "timeout for connection requests"); + cmd.addOption("--acse-timeout", "-ta", 1, "[s]econds: integer (default: 30)", "timeout for ACSE messages"); + cmd.addOption("--dimse-timeout", "-td", 1, "[s]econds: integer (default: unlimited)", "timeout for DIMSE messages"); + + OFString opt3 = "set max receive pdu to n bytes (default: "; + sprintf(tempstr, "%ld", OFstatic_cast(long, ASC_DEFAULTMAXPDU)); + opt3 += tempstr; + opt3 += ")"; + OFString opt4 = "[n]umber of bytes: integer ("; + sprintf(tempstr, "%ld", OFstatic_cast(long, ASC_MINIMUMPDUSIZE)); + opt4 += tempstr; + opt4 += ".."; + sprintf(tempstr, "%ld", OFstatic_cast(long, ASC_MAXIMUMPDUSIZE)); + opt4 += tempstr; + opt4 += ")"; + cmd.addOption("--max-pdu", "-pdu", 1, opt4.c_str(), opt3.c_str()); + cmd.addOption("--repeat", 1, "[n]umber: integer", "repeat n times"); + cmd.addOption("--abort", "abort association instead of releasing it"); + +#ifdef WITH_OPENSSL + cmd.addGroup("transport layer security (TLS) options:"); + cmd.addSubGroup("transport protocol stack:"); + cmd.addOption("--disable-tls", "-tls", "use normal TCP/IP connection (default)"); + cmd.addOption("--enable-tls", "+tls", 2, "[p]rivate key file, [c]ertificate file: string", + "use authenticated secure TLS connection"); + cmd.addOption("--anonymous-tls", "+tla", "use secure TLS connection without certificate"); + cmd.addSubGroup("private key password (only with --enable-tls):"); + cmd.addOption("--std-passwd", "+ps", "prompt user to type password on stdin (default)"); + cmd.addOption("--use-passwd", "+pw", 1, "[p]assword: string ", + "use specified password"); + cmd.addOption("--null-passwd", "-pw", "use empty string as password"); + cmd.addSubGroup("key and certificate file format:"); + cmd.addOption("--pem-keys", "-pem", "read keys and certificates as PEM file (default)"); + cmd.addOption("--der-keys", "-der", "read keys and certificates as DER file"); + cmd.addSubGroup("certification authority:"); + cmd.addOption("--add-cert-file", "+cf", 1, "[c]ertificate filename: string", + "add certificate file to list of certificates", OFCommandLine::AF_NoWarning); + cmd.addOption("--add-cert-dir", "+cd", 1, "[c]ertificate directory: string", + "add certificates in d to list of certificates", OFCommandLine::AF_NoWarning); + cmd.addSubGroup("ciphersuite:"); + cmd.addOption("--cipher", "+cs", 1, "[c]iphersuite name: string", + "add ciphersuite to list of negotiated suites"); + cmd.addOption("--dhparam", "+dp", 1, "[f]ilename: string", + "read DH parameters for DH/DSS ciphersuites"); + cmd.addSubGroup("pseudo random generator:"); + cmd.addOption("--seed", "+rs", 1, "[f]ilename: string", + "seed random generator with contents of f"); + cmd.addOption("--write-seed", "+ws", "write back modified seed (only with --seed)"); + cmd.addOption("--write-seed-file", "+wf", 1, "[f]ilename: string (only with --seed)", + "write modified seed to file f"); + cmd.addSubGroup("peer authentication:"); + cmd.addOption("--require-peer-cert", "-rc", "verify peer certificate, fail if absent (default)"); + cmd.addOption("--verify-peer-cert", "-vc", "verify peer certificate if present"); + cmd.addOption("--ignore-peer-cert", "-ic", "don't verify peer certificate"); +#endif + + /* evaluate command line */ + prepareCmdLineArgs(argc, argv, OFFIS_CONSOLE_APPLICATION); + if (app.parseCommandLine(cmd, argc, argv)) + { + /* check exclusive options first */ + if (cmd.hasExclusiveOption()) + { + if (cmd.findOption("--version")) + { + app.printHeader(OFTrue /*print host identifier*/); + COUT << OFendl << "External libraries used:"; +#if !defined(WITH_ZLIB) && !defined(WITH_OPENSSL) + COUT << " none" << OFendl; +#else + COUT << OFendl; +#endif +#ifdef WITH_ZLIB + COUT << "- ZLIB, Version " << zlibVersion() << OFendl; +#endif +#ifdef WITH_OPENSSL + COUT << "- " << OPENSSL_VERSION_TEXT << OFendl; +#endif + return 0; + } + } + + /* command line parameters */ + + cmd.getParam(1, opt_peer); + app.checkParam(cmd.getParamAndCheckMinMax(2, opt_port, 1, 65535)); + + OFLog::configureFromCommandLine(cmd, app); + + if (cmd.findOption("--aetitle")) app.checkValue(cmd.getValue(opt_ourTitle)); + if (cmd.findOption("--call")) app.checkValue(cmd.getValue(opt_peerTitle)); + + if (cmd.findOption("--timeout")) + { + OFCmdSignedInt opt_timeout = 0; + app.checkValue(cmd.getValueAndCheckMin(opt_timeout, 1)); + dcmConnectionTimeout.set(OFstatic_cast(Sint32, opt_timeout)); + } + + if (cmd.findOption("--acse-timeout")) + { + OFCmdSignedInt opt_timeout = 0; + app.checkValue(cmd.getValueAndCheckMin(opt_timeout, 1)); + opt_acse_timeout = OFstatic_cast(int, opt_timeout); + } + + if (cmd.findOption("--dimse-timeout")) + { + OFCmdSignedInt opt_timeout = 0; + app.checkValue(cmd.getValueAndCheckMin(opt_timeout, 1)); + opt_dimse_timeout = OFstatic_cast(int, opt_timeout); + opt_blockMode = DIMSE_NONBLOCKING; + } + + if (cmd.findOption("--max-pdu")) app.checkValue(cmd.getValueAndCheckMinMax(opt_maxReceivePDULength, ASC_MINIMUMPDUSIZE, ASC_MAXIMUMPDUSIZE)); + if (cmd.findOption("--repeat")) app.checkValue(cmd.getValueAndCheckMin(opt_repeatCount, 1)); + if (cmd.findOption("--abort")) opt_abortAssociation=OFTrue; + if (cmd.findOption("--propose-ts")) app.checkValue(cmd.getValueAndCheckMinMax(opt_numXferSyntaxes, 1, maxXferSyntaxes)); + if (cmd.findOption("--propose-pc")) app.checkValue(cmd.getValueAndCheckMinMax(opt_numPresentationCtx, 1, 128)); + +#ifdef WITH_OPENSSL + + cmd.beginOptionBlock(); + if (cmd.findOption("--disable-tls")) opt_secureConnection = OFFalse; + if (cmd.findOption("--enable-tls")) + { + opt_secureConnection = OFTrue; + opt_doAuthenticate = OFTrue; + app.checkValue(cmd.getValue(opt_privateKeyFile)); + app.checkValue(cmd.getValue(opt_certificateFile)); + } + if (cmd.findOption("--anonymous-tls")) + { + opt_secureConnection = OFTrue; + } + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--std-passwd")) + { + app.checkDependence("--std-passwd", "--enable-tls", opt_doAuthenticate); + opt_passwd = NULL; + } + if (cmd.findOption("--use-passwd")) + { + app.checkDependence("--use-passwd", "--enable-tls", opt_doAuthenticate); + app.checkValue(cmd.getValue(opt_passwd)); + } + if (cmd.findOption("--null-passwd")) + { + app.checkDependence("--null-passwd", "--enable-tls", opt_doAuthenticate); + opt_passwd = ""; + } + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--pem-keys")) opt_keyFileFormat = SSL_FILETYPE_PEM; + if (cmd.findOption("--der-keys")) opt_keyFileFormat = SSL_FILETYPE_ASN1; + cmd.endOptionBlock(); + + if (cmd.findOption("--dhparam")) + { + app.checkValue(cmd.getValue(opt_dhparam)); + } + + if (cmd.findOption("--seed")) + { + app.checkValue(cmd.getValue(opt_readSeedFile)); + } + + cmd.beginOptionBlock(); + if (cmd.findOption("--write-seed")) + { + app.checkDependence("--write-seed", "--seed", opt_readSeedFile != NULL); + opt_writeSeedFile = opt_readSeedFile; + } + if (cmd.findOption("--write-seed-file")) + { + app.checkDependence("--write-seed-file", "--seed", opt_readSeedFile != NULL); + app.checkValue(cmd.getValue(opt_writeSeedFile)); + } + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--require-peer-cert")) opt_certVerification = DCV_requireCertificate; + if (cmd.findOption("--verify-peer-cert")) opt_certVerification = DCV_checkCertificate; + if (cmd.findOption("--ignore-peer-cert")) opt_certVerification = DCV_ignoreCertificate; + cmd.endOptionBlock(); + + const char *current = NULL; + const char *currentOpenSSL; + if (cmd.findOption("--cipher", 0, OFCommandLine::FOM_First)) + { + opt_ciphersuites.clear(); + do + { + app.checkValue(cmd.getValue(current)); + if (NULL == (currentOpenSSL = DcmTLSTransportLayer::findOpenSSLCipherSuiteName(current))) + { + OFLOG_FATAL(echoscuLogger, "ciphersuite '" << current << "' is unknown. Known ciphersuites are:"); + unsigned long numSuites = DcmTLSTransportLayer::getNumberOfCipherSuites(); + for (unsigned long cs=0; cs < numSuites; cs++) + { + OFLOG_FATAL(echoscuLogger, " " << DcmTLSTransportLayer::getTLSCipherSuiteName(cs)); + } + return 1; + } else { + if (!opt_ciphersuites.empty()) opt_ciphersuites += ":"; + opt_ciphersuites += currentOpenSSL; + } + } while (cmd.findOption("--cipher", 0, OFCommandLine::FOM_Next)); + } + +#endif + } + + /* print resource identifier */ + OFLOG_DEBUG(echoscuLogger, rcsid << OFendl); + + /* make sure data dictionary is loaded */ + if (!dcmDataDict.isDictionaryLoaded()) + { + OFLOG_WARN(echoscuLogger, "no data dictionary loaded, check environment variable: " + << DCM_DICT_ENVIRONMENT_VARIABLE); + } + + /* initialize network, i.e. create an instance of T_ASC_Network*. */ + OFCondition cond = ASC_initializeNetwork(NET_REQUESTOR, 0, opt_acse_timeout, &net); + if (cond.bad()) { + OFLOG_FATAL(echoscuLogger, DimseCondition::dump(temp_str, cond)); + exit(1); + } + +#ifdef WITH_OPENSSL + + DcmTLSTransportLayer *tLayer = NULL; + if (opt_secureConnection) + { + tLayer = new DcmTLSTransportLayer(DICOM_APPLICATION_REQUESTOR, opt_readSeedFile); + if (tLayer == NULL) + { + OFLOG_FATAL(echoscuLogger, "unable to create TLS transport layer"); + return 1; + } + + if (cmd.findOption("--add-cert-file", 0, OFCommandLine::FOM_First)) + { + const char *current = NULL; + do + { + app.checkValue(cmd.getValue(current)); + if (TCS_ok != tLayer->addTrustedCertificateFile(current, opt_keyFileFormat)) + { + OFLOG_WARN(echoscuLogger, "unable to load certificate file '" << current << "', ignoring"); + } + } while (cmd.findOption("--add-cert-file", 0, OFCommandLine::FOM_Next)); + } + + if (cmd.findOption("--add-cert-dir", 0, OFCommandLine::FOM_First)) + { + const char *current = NULL; + do + { + app.checkValue(cmd.getValue(current)); + if (TCS_ok != tLayer->addTrustedCertificateDir(current, opt_keyFileFormat)) + { + OFLOG_WARN(echoscuLogger, "unable to load certificates from directory '" << current << "', ignoring"); + } + } while (cmd.findOption("--add-cert-dir", 0, OFCommandLine::FOM_Next)); + } + + if (opt_dhparam && ! (tLayer->setTempDHParameters(opt_dhparam))) + { + OFLOG_WARN(echoscuLogger, "unable to load temporary DH parameter file '" << opt_dhparam << "', ignoring"); + } + + if (opt_doAuthenticate) + { + if (opt_passwd) tLayer->setPrivateKeyPasswd(opt_passwd); + + if (TCS_ok != tLayer->setPrivateKeyFile(opt_privateKeyFile, opt_keyFileFormat)) + { + OFLOG_ERROR(echoscuLogger, "unable to load private TLS key from '" << opt_privateKeyFile << "'"); + return 1; + } + if (TCS_ok != tLayer->setCertificateFile(opt_certificateFile, opt_keyFileFormat)) + { + OFLOG_ERROR(echoscuLogger, "unable to load certificate from '" << opt_certificateFile << "'"); + return 1; + } + if (! tLayer->checkPrivateKeyMatchesCertificate()) + { + OFLOG_ERROR(echoscuLogger, "private key '" << opt_privateKeyFile << "' and certificate '" << opt_certificateFile << "' do not match"); + return 1; + } + } + + if (TCS_ok != tLayer->setCipherSuites(opt_ciphersuites.c_str())) + { + OFLOG_ERROR(echoscuLogger, "unable to set selected cipher suites"); + return 1; + } + + tLayer->setCertificateVerification(opt_certVerification); + + + cond = ASC_setTransportLayer(net, tLayer, 0); + if (cond.bad()) + { + OFLOG_FATAL(echoscuLogger, DimseCondition::dump(temp_str, cond)); + return 1; + } + } + +#endif + + /* initialize association parameters, i.e. create an instance of T_ASC_Parameters*. */ + cond = ASC_createAssociationParameters(¶ms, opt_maxReceivePDULength); + if (cond.bad()) { + OFLOG_FATAL(echoscuLogger, DimseCondition::dump(temp_str, cond)); + exit(1); + } + +#ifdef PRIVATE_ECHOSCU_CODE + PRIVATE_ECHOSCU_CODE +#endif + + /* sets this application's title and the called application's title in the params */ + /* structure. The default values to be set here are "STORESCU" and "ANY-SCP". */ + ASC_setAPTitles(params, opt_ourTitle, opt_peerTitle, NULL); + + /* Set the transport layer type (type of network connection) in the params */ + /* structure. The default is an insecure connection; where OpenSSL is */ + /* available the user is able to request an encrypted,secure connection. */ + cond = ASC_setTransportLayerType(params, opt_secureConnection); + if (cond.bad()) { + OFLOG_FATAL(echoscuLogger, DimseCondition::dump(temp_str, cond)); + return 1; + } + + /* Figure out the presentation addresses and copy the */ + /* corresponding values into the association parameters.*/ + gethostname(localHost, sizeof(localHost) - 1); + sprintf(peerHost, "%s:%d", opt_peer, OFstatic_cast(int, opt_port)); + ASC_setPresentationAddresses(params, localHost, peerHost); + + /* Set the presentation contexts which will be negotiated */ + /* when the network connection will be established */ + int presentationContextID = 1; /* odd byte value 1, 3, 5, .. 255 */ + for (unsigned long ii=0; iisendPDVLength << ")"); + + /* do the real work, i.e. send a number of C-ECHO-RQ messages to the DICOM application */ + /* this application is connected with and handle corresponding C-ECHO-RSP messages. */ + cond = cecho(assoc, opt_repeatCount); + + /* tear down association, i.e. terminate network connection to SCP */ + if (cond == EC_Normal) + { + if (opt_abortAssociation) { + OFLOG_INFO(echoscuLogger, "Aborting Association"); + cond = ASC_abortAssociation(assoc); + if (cond.bad()) + { + OFLOG_FATAL(echoscuLogger, "Association Abort Failed: " << DimseCondition::dump(temp_str, cond)); + exit(1); + } + } else { + /* release association */ + OFLOG_INFO(echoscuLogger, "Releasing Association"); + cond = ASC_releaseAssociation(assoc); + if (cond.bad()) + { + OFLOG_FATAL(echoscuLogger, "Association Release Failed: " << DimseCondition::dump(temp_str, cond)); + exit(1); + } + } + } + else if (cond == DUL_PEERREQUESTEDRELEASE) + { + OFLOG_FATAL(echoscuLogger, "Protocol Error: Peer requested release (Aborting)"); + OFLOG_INFO(echoscuLogger, "Aborting Association"); + cond = ASC_abortAssociation(assoc); + if (cond.bad()) { + OFLOG_FATAL(echoscuLogger, "Association Abort Failed: " << DimseCondition::dump(temp_str, cond)); + exit(1); + } + } + else if (cond == DUL_PEERABORTEDASSOCIATION) + { + OFLOG_INFO(echoscuLogger, "Peer Aborted Association"); + } + else + { + OFLOG_ERROR(echoscuLogger, "Echo SCU Failed: " << DimseCondition::dump(temp_str, cond)); + OFLOG_INFO(echoscuLogger, "Aborting Association"); + cond = ASC_abortAssociation(assoc); + if (cond.bad()) { + OFLOG_FATAL(echoscuLogger, "Association Abort Failed: " << DimseCondition::dump(temp_str, cond)); + exit(1); + } + } + + /* destroy the association, i.e. free memory of T_ASC_Association* structure. This */ + /* call is the counterpart of ASC_requestAssociation(...) which was called above. */ + cond = ASC_destroyAssociation(&assoc); + if (cond.bad()) { + OFLOG_FATAL(echoscuLogger, DimseCondition::dump(temp_str, cond)); + exit(1); + } + + /* drop the network, i.e. free memory of T_ASC_Network* structure. This call */ + /* is the counterpart of ASC_initializeNetwork(...) which was called above. */ + cond = ASC_dropNetwork(&net); + if (cond.bad()) { + OFLOG_FATAL(echoscuLogger, DimseCondition::dump(temp_str, cond)); + exit(1); + } + +#ifdef HAVE_WINSOCK_H + WSACleanup(); +#endif + +#ifdef WITH_OPENSSL + if (tLayer && opt_writeSeedFile) + { + if (tLayer->canWriteRandomSeed()) + { + if (!tLayer->writeRandomSeed(opt_writeSeedFile)) + { + OFLOG_ERROR(echoscuLogger, "cannot write random seed file '" << opt_writeSeedFile << "', ignoring"); + } + } else { + OFLOG_ERROR(echoscuLogger, "cannot write random seed, ignoring"); + } + } + delete tLayer; +#endif + + return 0; +} + +static OFCondition +echoSCU(T_ASC_Association * assoc) + /* + * This function will send a C-ECHO-RQ over the network to another DICOM application + * and handle the response. + * + * Parameters: + * assoc - [in] The association (network connection to another DICOM application). + */ +{ + DIC_US msgId = assoc->nextMsgID++; + DIC_US status; + DcmDataset *statusDetail = NULL; + + /* dump information if required */ + OFLOG_INFO(echoscuLogger, "Sending Echo Request (MsgID " << msgId << ")"); + + /* send C-ECHO-RQ and handle response */ + OFCondition cond = DIMSE_echoUser(assoc, msgId, opt_blockMode, opt_dimse_timeout, &status, &statusDetail); + + /* depending on if a response was received, dump some information */ + if (cond.good()) { + OFLOG_INFO(echoscuLogger, "Received Echo Response (" << DU_cechoStatusString(status) << ")"); + } else { + OFString temp_str; + OFLOG_ERROR(echoscuLogger, "Echo Failed: " << DimseCondition::dump(temp_str, cond)); + } + + /* check for status detail information, there should never be any */ + if (statusDetail != NULL) { + OFLOG_DEBUG(echoscuLogger, "Status Detail (should never be any):" << OFendl << DcmObject::PrintHelper(*statusDetail)); + delete statusDetail; + } + + /* return result value */ + return cond; +} + +static OFCondition +cecho(T_ASC_Association * assoc, unsigned long num_repeat) + /* + * This function will send num_repeat C-ECHO-RQ messages to the DICOM application + * this application is connected with and handle corresponding C-ECHO-RSP messages. + * + * Parameters: + * assoc - [in] The association (network connection to another DICOM application). + * num_repeat - [in] The amount of C-ECHO-RQ messages which shall be sent. + */ +{ + OFCondition cond = EC_Normal; + unsigned long n = num_repeat; + + /* as long as no error occurred and the counter does not equal 0 */ + /* send an C-ECHO-RQ and handle the response */ + while (cond.good() && n--) cond = echoSCU(assoc); + + return cond; +} diff --git a/dcmnet/apps/findscu.cc b/dcmnet/apps/findscu.cc new file mode 100644 index 00000000..3a2e1c8b --- /dev/null +++ b/dcmnet/apps/findscu.cc @@ -0,0 +1,660 @@ +/* + * + * Copyright (C) 1994-2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmnet + * + * Author: Andrew Hewett + * + * Purpose: Query/Retrieve Service Class User (C-FIND operation) + * + */ + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ +#include "dcmtk/dcmnet/dfindscu.h" +#include "dcmtk/dcmnet/diutil.h" +#include "dcmtk/dcmdata/cmdlnarg.h" +#include "dcmtk/ofstd/ofconapp.h" +#include "dcmtk/dcmdata/dcdict.h" +#include "dcmtk/dcmdata/dcostrmz.h" /* for dcmZlibCompressionLevel */ + +#ifdef WITH_ZLIB +#include /* for zlibVersion() */ +#endif + +#ifdef WITH_OPENSSL +#include "dcmtk/dcmtls/tlstrans.h" +#include "dcmtk/dcmtls/tlslayer.h" +#endif + +#define OFFIS_CONSOLE_APPLICATION "findscu" + +static OFLogger findscuLogger = OFLog::getLogger("dcmtk.apps." OFFIS_CONSOLE_APPLICATION); + +static char rcsid[] = "$dcmtk: " OFFIS_CONSOLE_APPLICATION " v" + OFFIS_DCMTK_VERSION " " OFFIS_DCMTK_RELEASEDATE " $"; + +/* default application titles */ +#define APPLICATIONTITLE "FINDSCU" +#define PEERAPPLICATIONTITLE "ANY-SCP" + +#define SHORTCOL 4 +#define LONGCOL 20 + +int main(int argc, char *argv[]) +{ + OFList fileNameList; + OFBool opt_abortAssociation = OFFalse; + const char * opt_abstractSyntax = UID_FINDModalityWorklistInformationModel; + int opt_acse_timeout = 30; + T_DIMSE_BlockingMode opt_blockMode = DIMSE_BLOCKING; + OFCmdSignedInt opt_cancelAfterNResponses = -1; + int opt_dimse_timeout = 0; + int opt_outputResponsesToLogger = 0; + OFBool opt_extractResponsesToFile = OFFalse; + OFString opt_outputDirectory = "."; + OFCmdUnsignedInt opt_maxReceivePDULength = ASC_DEFAULTMAXPDU; + E_TransferSyntax opt_networkTransferSyntax = EXS_Unknown; + const char * opt_ourTitle = APPLICATIONTITLE; + const char * opt_peer; + const char * opt_peerTitle = PEERAPPLICATIONTITLE; + OFCmdUnsignedInt opt_port = 104; + OFCmdUnsignedInt opt_repeatCount = 1; + OFBool opt_secureConnection = OFFalse; /* default: no secure connection */ + OFList overrideKeys; + +#ifdef WITH_ZLIB + OFCmdUnsignedInt opt_compressionLevel = 0; +#endif + +#ifdef WITH_OPENSSL + const char * opt_certificateFile = NULL; + OFBool opt_doAuthenticate = OFFalse; + int opt_keyFileFormat = SSL_FILETYPE_PEM; + const char * opt_passwd = NULL; + const char * opt_privateKeyFile = NULL; +#if OPENSSL_VERSION_NUMBER >= 0x0090700fL + OFString opt_ciphersuites(TLS1_TXT_RSA_WITH_AES_128_SHA ":" SSL3_TXT_RSA_DES_192_CBC3_SHA); +#else + OFString opt_ciphersuites(SSL3_TXT_RSA_DES_192_CBC3_SHA); +#endif + const char * opt_dhparam = NULL; + const char * opt_readSeedFile = NULL; + const char * opt_writeSeedFile = NULL; + DcmCertificateVerification opt_certVerification = DCV_requireCertificate; +#endif + + /* + ** By default. don't let "dcmdata" remove trailing padding or + ** perform other manipulations. We want to see the real data. + */ + OFBool opt_automaticDataCorrection = OFFalse; + +#ifdef HAVE_GUSI_H + GUSISetup(GUSIwithSIOUXSockets); + GUSISetup(GUSIwithInternetSockets); +#endif + +#ifdef HAVE_WINSOCK_H + WSAData winSockData; + /* we need at least version 1.1 */ + WORD winSockVersionNeeded = MAKEWORD( 1, 1 ); + WSAStartup(winSockVersionNeeded, &winSockData); +#endif + + char tempstr[20]; + OFString temp_str; + OFConsoleApplication app(OFFIS_CONSOLE_APPLICATION , "DICOM query (C-FIND) SCU", rcsid); + OFCommandLine cmd; + + cmd.setParamColumn(LONGCOL + SHORTCOL + 4); + cmd.addParam("peer", "hostname of DICOM peer"); + cmd.addParam("port", "tcp/ip port number of peer"); + cmd.addParam("dcmfile-in", "DICOM query file(s)", OFCmdParam::PM_MultiOptional); + + cmd.setOptionColumns(LONGCOL, SHORTCOL); + cmd.addGroup("general options:", LONGCOL, SHORTCOL + 2); + cmd.addOption("--help", "-h", "print this help text and exit", OFCommandLine::AF_Exclusive); + cmd.addOption("--version", "print version information and exit", OFCommandLine::AF_Exclusive); + OFLog::addOptions(cmd); + + cmd.addGroup("network options:"); + cmd.addSubGroup("override matching keys:"); + cmd.addOption("--key", "-k", 1, "[k]ey: gggg,eeee=\"str\", path or dict. name=\"str\"", + "override matching key"); + cmd.addSubGroup("query information model:"); + cmd.addOption("--worklist", "-W", "use modality worklist information model (def.)"); + cmd.addOption("--patient", "-P", "use patient root information model"); + cmd.addOption("--study", "-S", "use study root information model"); + cmd.addOption("--psonly", "-O", "use patient/study only information model"); + cmd.addSubGroup("application entity titles:"); + OFString opt1 = "set my calling AE title (default: "; + opt1 += APPLICATIONTITLE; + opt1 += ")"; + cmd.addOption("--aetitle", "-aet", 1, "[a]etitle: string", opt1.c_str()); + OFString opt2 = "set called AE title of peer (default: "; + opt2 += PEERAPPLICATIONTITLE; + opt2 += ")"; + cmd.addOption("--call", "-aec", 1, "[a]etitle: string", opt2.c_str()); + cmd.addSubGroup("post-1993 value representations:"); + cmd.addOption("--enable-new-vr", "+u", "enable support for new VRs (UN/UT) (default)"); + cmd.addOption("--disable-new-vr", "-u", "disable support for new VRs, convert to OB"); + cmd.addSubGroup("proposed transmission transfer syntaxes:"); + cmd.addOption("--propose-uncompr", "-x=", "propose all uncompressed TS, explicit VR\nwith local byte ordering first (default)"); + cmd.addOption("--propose-little", "-xe", "propose all uncompressed TS, explicit VR\nlittle endian first"); + cmd.addOption("--propose-big", "-xb", "propose all uncompressed TS, explicit VR\nbig endian first"); +#ifdef WITH_ZLIB + cmd.addOption("--propose-deflated", "-xd", "propose deflated explicit VR little endian TS\nand all uncompressed transfer syntaxes"); +#endif + cmd.addOption("--propose-implicit", "-xi", "propose implicit VR little endian TS only"); +#ifdef WITH_ZLIB + cmd.addSubGroup("deflate compression level (only with --propose-deflated):"); + cmd.addOption("--compression-level", "+cl", 1, "[l]evel: integer (default: 6)", + "0=uncompressed, 1=fastest, 9=best compression"); +#endif + cmd.addSubGroup("other network options:"); + OFString opt3 = "set max receive pdu to n bytes (default: "; + sprintf(tempstr, "%ld", OFstatic_cast(long, ASC_DEFAULTMAXPDU)); + opt3 += tempstr; + opt3 += ")"; + OFString opt4 = "[n]umber of bytes: integer ("; + sprintf(tempstr, "%ld", OFstatic_cast(long, ASC_MINIMUMPDUSIZE)); + opt4 += tempstr; + opt4 += ".."; + sprintf(tempstr, "%ld", OFstatic_cast(long, ASC_MAXIMUMPDUSIZE)); + opt4 += tempstr; + opt4 += ")"; + cmd.addOption("--timeout", "-to", 1, "[s]econds: integer (default: unlimited)", "timeout for connection requests"); + cmd.addOption("--acse-timeout", "-ta", 1, "[s]econds: integer (default: 30)", "timeout for ACSE messages"); + cmd.addOption("--dimse-timeout", "-td", 1, "[s]econds: integer (default: unlimited)", "timeout for DIMSE messages"); + cmd.addOption("--max-pdu", "-pdu", 1, opt4.c_str(), opt3.c_str()); + cmd.addOption("--repeat", 1, "[n]umber: integer", "repeat n times"); + cmd.addOption("--abort", "abort association instead of releasing it"); + cmd.addOption("--cancel", 1, "[n]umber: integer", + "cancel after n responses (default: never)"); + +#ifdef WITH_OPENSSL + cmd.addGroup("transport layer security (TLS) options:"); + cmd.addSubGroup("transport protocol stack:"); + cmd.addOption("--disable-tls", "-tls", "use normal TCP/IP connection (default)"); + cmd.addOption("--enable-tls", "+tls", 2, "[p]rivate key file, [c]ertificate file: string", + "use authenticated secure TLS connection"); + cmd.addOption("--anonymous-tls", "+tla", "use secure TLS connection without certificate"); + cmd.addSubGroup("private key password (only with --enable-tls):"); + cmd.addOption("--std-passwd", "+ps", "prompt user to type password on stdin (default)"); + cmd.addOption("--use-passwd", "+pw", 1, "[p]assword: string ", + "use specified password"); + cmd.addOption("--null-passwd", "-pw", "use empty string as password"); + cmd.addSubGroup("key and certificate file format:"); + cmd.addOption("--pem-keys", "-pem", "read keys and certificates as PEM file (default)"); + cmd.addOption("--der-keys", "-der", "read keys and certificates as DER file"); + cmd.addSubGroup("certification authority:"); + cmd.addOption("--add-cert-file", "+cf", 1, "[c]ertificate filename: string", + "add certificate file to list of certificates", OFCommandLine::AF_NoWarning); + cmd.addOption("--add-cert-dir", "+cd", 1, "[c]ertificate directory: string", + "add certificates in d to list of certificates", OFCommandLine::AF_NoWarning); + cmd.addSubGroup("ciphersuite:"); + cmd.addOption("--cipher", "+cs", 1, "[c]iphersuite name: string", + "add ciphersuite to list of negotiated suites"); + cmd.addOption("--dhparam", "+dp", 1, "[f]ilename: string", + "read DH parameters for DH/DSS ciphersuites"); + cmd.addSubGroup("pseudo random generator:"); + cmd.addOption("--seed", "+rs", 1, "[f]ilename: string", + "seed random generator with contents of f"); + cmd.addOption("--write-seed", "+ws", "write back modified seed (only with --seed)"); + cmd.addOption("--write-seed-file", "+wf", 1, "[f]ilename: string (only with --seed)", + "write modified seed to file f"); + cmd.addSubGroup("peer authentication:"); + cmd.addOption("--require-peer-cert", "-rc", "verify peer certificate, fail if absent (def.)"); + cmd.addOption("--verify-peer-cert", "-vc", "verify peer certificate if present"); + cmd.addOption("--ignore-peer-cert", "-ic", "don't verify peer certificate"); +#endif + + cmd.addGroup("output options:"); + cmd.addSubGroup("general:"); + cmd.addOption("--output-directory", "-od", 1, "[d]irectory: string (default: \".\")", "write output files to existing directory d"); + cmd.addSubGroup("automatic data correction:"); + cmd.addOption("--enable-correction", "+dc", "enable automatic data correction"); + cmd.addOption("--disable-correction", "-dc", "disable automatic data correction (default)"); + cmd.addSubGroup("C-FIND responses:"); + cmd.addOption("--show-responses", "+sr", "always output responses to the logger"); + cmd.addOption("--hide-responses", "-sr", "do not output responses to the logger"); + cmd.addOption("--extract", "-X", "extract responses to file (rsp0001.dcm, ...)"); + + /* evaluate command line */ + prepareCmdLineArgs(argc, argv, OFFIS_CONSOLE_APPLICATION); + if (app.parseCommandLine(cmd, argc, argv)) + { + /* check exclusive options first */ + if (cmd.hasExclusiveOption()) + { + if (cmd.findOption("--version")) + { + app.printHeader(OFTrue /*print host identifier*/); + COUT << OFendl << "External libraries used:"; +#if !defined(WITH_ZLIB) && !defined(WITH_OPENSSL) + COUT << " none" << OFendl; +#else + COUT << OFendl; +#endif +#ifdef WITH_ZLIB + COUT << "- ZLIB, Version " << zlibVersion() << OFendl; +#endif +#ifdef WITH_OPENSSL + COUT << "- " << OPENSSL_VERSION_TEXT << OFendl; +#endif + return 0; + } + } + + /* command line parameters */ + cmd.getParam(1, opt_peer); + app.checkParam(cmd.getParamAndCheckMinMax(2, opt_port, 1, 65535)); + + OFLog::configureFromCommandLine(cmd, app); + + if (cmd.findOption("--key", 0, OFCommandLine::FOM_FirstFromLeft)) + { + const char *ovKey = NULL; + do { + app.checkValue(cmd.getValue(ovKey)); + overrideKeys.push_back(ovKey); + } while (cmd.findOption("--key", 0, OFCommandLine::FOM_NextFromLeft)); + } + + cmd.beginOptionBlock(); + if (cmd.findOption("--worklist")) opt_abstractSyntax = UID_FINDModalityWorklistInformationModel; + if (cmd.findOption("--patient")) opt_abstractSyntax = UID_FINDPatientRootQueryRetrieveInformationModel; + if (cmd.findOption("--study")) opt_abstractSyntax = UID_FINDStudyRootQueryRetrieveInformationModel; + if (cmd.findOption("--psonly")) opt_abstractSyntax = UID_RETIRED_FINDPatientStudyOnlyQueryRetrieveInformationModel; + cmd.endOptionBlock(); + + if (cmd.findOption("--aetitle")) app.checkValue(cmd.getValue(opt_ourTitle)); + if (cmd.findOption("--call")) app.checkValue(cmd.getValue(opt_peerTitle)); + + cmd.beginOptionBlock(); + if (cmd.findOption("--propose-uncompr")) opt_networkTransferSyntax = EXS_Unknown; + if (cmd.findOption("--propose-little")) opt_networkTransferSyntax = EXS_LittleEndianExplicit; + if (cmd.findOption("--propose-big")) opt_networkTransferSyntax = EXS_BigEndianExplicit; + if (cmd.findOption("--propose-implicit")) opt_networkTransferSyntax = EXS_LittleEndianImplicit; +#ifdef WITH_ZLIB + if (cmd.findOption("--propose-deflated")) opt_networkTransferSyntax = EXS_DeflatedLittleEndianExplicit; +#endif + cmd.endOptionBlock(); + +#ifdef WITH_ZLIB + if (cmd.findOption("--compression-level")) + { + app.checkDependence("--compression-level", "--propose-deflated", + (opt_networkTransferSyntax == EXS_DeflatedLittleEndianExplicit)); + app.checkValue(cmd.getValueAndCheckMinMax(opt_compressionLevel, 0, 9)); + dcmZlibCompressionLevel.set(OFstatic_cast(int, opt_compressionLevel)); + } +#endif + + cmd.beginOptionBlock(); + if (cmd.findOption("--enable-new-vr")) dcmEnableGenerationOfNewVRs(); + if (cmd.findOption("--disable-new-vr")) dcmDisableGenerationOfNewVRs(); + cmd.endOptionBlock(); + + if (cmd.findOption("--timeout")) + { + OFCmdSignedInt opt_timeout = 0; + app.checkValue(cmd.getValueAndCheckMin(opt_timeout, 1)); + dcmConnectionTimeout.set(OFstatic_cast(Sint32, opt_timeout)); + } + + if (cmd.findOption("--acse-timeout")) + { + OFCmdSignedInt opt_timeout = 0; + app.checkValue(cmd.getValueAndCheckMin(opt_timeout, 1)); + opt_acse_timeout = OFstatic_cast(int, opt_timeout); + } + + if (cmd.findOption("--dimse-timeout")) + { + OFCmdSignedInt opt_timeout = 0; + app.checkValue(cmd.getValueAndCheckMin(opt_timeout, 1)); + opt_dimse_timeout = OFstatic_cast(int, opt_timeout); + opt_blockMode = DIMSE_NONBLOCKING; + } + + if (cmd.findOption("--max-pdu")) app.checkValue(cmd.getValueAndCheckMinMax(opt_maxReceivePDULength, ASC_MINIMUMPDUSIZE, ASC_MAXIMUMPDUSIZE)); + if (cmd.findOption("--repeat")) app.checkValue(cmd.getValueAndCheckMin(opt_repeatCount, 1)); + if (cmd.findOption("--abort")) opt_abortAssociation = OFTrue; + if (cmd.findOption("--cancel")) app.checkValue(cmd.getValueAndCheckMin(opt_cancelAfterNResponses, 0)); + + if (cmd.findOption("--output-directory")) app.checkValue(cmd.getValue(opt_outputDirectory)); + + cmd.beginOptionBlock(); + if (cmd.findOption("--enable-correction")) opt_automaticDataCorrection = OFTrue; + if (cmd.findOption("--disable-correction")) opt_automaticDataCorrection = OFFalse; + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--show-responses")) opt_outputResponsesToLogger = 1; + if (cmd.findOption("--hide-responses")) opt_outputResponsesToLogger = 2; + cmd.endOptionBlock(); + + if (cmd.findOption("--extract")) opt_extractResponsesToFile = OFTrue; + /* finally parse filenames */ + int paramCount = cmd.getParamCount(); + const char *currentFilename = NULL; + OFString errormsg; + + for (int i = 3; i <= paramCount; i++) + { + cmd.getParam(i, currentFilename); + if (access(currentFilename, R_OK) < 0) + { + errormsg = "cannot access file: "; + errormsg += currentFilename; + app.printError(errormsg.c_str()); + } + fileNameList.push_back(currentFilename); + } + + if (fileNameList.empty() && overrideKeys.empty()) + { + app.printError("either query file or override keys (or both) must be specified"); + } + +#ifdef WITH_OPENSSL + + cmd.beginOptionBlock(); + if (cmd.findOption("--disable-tls")) opt_secureConnection = OFFalse; + if (cmd.findOption("--enable-tls")) + { + opt_secureConnection = OFTrue; + opt_doAuthenticate = OFTrue; + app.checkValue(cmd.getValue(opt_privateKeyFile)); + app.checkValue(cmd.getValue(opt_certificateFile)); + } + if (cmd.findOption("--anonymous-tls")) + { + opt_secureConnection = OFTrue; + } + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--std-passwd")) + { + app.checkDependence("--std-passwd", "--enable-tls", opt_doAuthenticate); + opt_passwd = NULL; + } + if (cmd.findOption("--use-passwd")) + { + app.checkDependence("--use-passwd", "--enable-tls", opt_doAuthenticate); + app.checkValue(cmd.getValue(opt_passwd)); + } + if (cmd.findOption("--null-passwd")) + { + app.checkDependence("--null-passwd", "--enable-tls", opt_doAuthenticate); + opt_passwd = ""; + } + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--pem-keys")) opt_keyFileFormat = SSL_FILETYPE_PEM; + if (cmd.findOption("--der-keys")) opt_keyFileFormat = SSL_FILETYPE_ASN1; + cmd.endOptionBlock(); + + if (cmd.findOption("--dhparam")) + { + app.checkValue(cmd.getValue(opt_dhparam)); + } + + if (cmd.findOption("--seed")) + { + app.checkValue(cmd.getValue(opt_readSeedFile)); + } + + cmd.beginOptionBlock(); + if (cmd.findOption("--write-seed")) + { + app.checkDependence("--write-seed", "--seed", opt_readSeedFile != NULL); + opt_writeSeedFile = opt_readSeedFile; + } + if (cmd.findOption("--write-seed-file")) + { + app.checkDependence("--write-seed-file", "--seed", opt_readSeedFile != NULL); + app.checkValue(cmd.getValue(opt_writeSeedFile)); + } + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--require-peer-cert")) opt_certVerification = DCV_requireCertificate; + if (cmd.findOption("--verify-peer-cert")) opt_certVerification = DCV_checkCertificate; + if (cmd.findOption("--ignore-peer-cert")) opt_certVerification = DCV_ignoreCertificate; + cmd.endOptionBlock(); + + const char *current = NULL; + const char *currentOpenSSL; + if (cmd.findOption("--cipher", 0, OFCommandLine::FOM_First)) + { + opt_ciphersuites.clear(); + do + { + app.checkValue(cmd.getValue(current)); + if (NULL == (currentOpenSSL = DcmTLSTransportLayer::findOpenSSLCipherSuiteName(current))) + { + OFLOG_FATAL(findscuLogger, "ciphersuite '" << current << "' is unknown. Known ciphersuites are:"); + unsigned long numSuites = DcmTLSTransportLayer::getNumberOfCipherSuites(); + for (unsigned long cs=0; cs < numSuites; cs++) + { + OFLOG_FATAL(findscuLogger, " " << DcmTLSTransportLayer::getTLSCipherSuiteName(cs)); + } + return 1; + } else { + if (!opt_ciphersuites.empty()) opt_ciphersuites += ":"; + opt_ciphersuites += currentOpenSSL; + } + } while (cmd.findOption("--cipher", 0, OFCommandLine::FOM_Next)); + } + +#endif + + } + + if (opt_outputResponsesToLogger == 0) + { + // default configuration for the C-FIND response logger + if (!cmd.findOption("--log-config")) + { + if (cmd.findOption("--extract")) + { + OFLog::getLogger(DCMNET_LOGGER_NAME ".responses").setLogLevel(OFLogger::OFF_LOG_LEVEL); + } + else if (!cmd.findOption("--quiet") && !cmd.findOption("--verbose") && !cmd.findOption("--debug") && !cmd.findOption("--log-level")) + { + OFLog::getLogger(DCMNET_LOGGER_NAME ".responses").setLogLevel(OFLogger::INFO_LOG_LEVEL); + } + } + } + else if (opt_outputResponsesToLogger == 1) + { + // always show C-FIND responses + OFLog::getLogger(DCMNET_LOGGER_NAME ".responses").setLogLevel(OFLogger::INFO_LOG_LEVEL); + } + else if (opt_outputResponsesToLogger == 2) + { + // never show C-FIND responses + OFLog::getLogger(DCMNET_LOGGER_NAME ".responses").setLogLevel(OFLogger::OFF_LOG_LEVEL); + } + + /* print resource identifier */ + OFLOG_DEBUG(findscuLogger, rcsid << OFendl); + + /* make sure data dictionary is loaded */ + if (!dcmDataDict.isDictionaryLoaded()) + { + OFLOG_WARN(findscuLogger, "no data dictionary loaded, check environment variable: " + << DCM_DICT_ENVIRONMENT_VARIABLE); + } + + /* make sure that output directory can be used (if needed) */ + if (opt_extractResponsesToFile) + { + if (!OFStandard::dirExists(opt_outputDirectory)) + { + OFLOG_FATAL(findscuLogger, "specified output directory does not exist"); + return 1; + } + else if (!OFStandard::isWriteable(opt_outputDirectory)) + { + OFLOG_FATAL(findscuLogger, "specified output directory is not writeable"); + return 1; + } + } + + // enabled or disable removal of trailing padding + dcmEnableAutomaticInputDataCorrection.set(opt_automaticDataCorrection); + + // declare findSCU handler and initialize network + DcmFindSCU findscu; + OFCondition cond = findscu.initializeNetwork(opt_acse_timeout); + if (cond.bad()) { + OFLOG_ERROR(findscuLogger, DimseCondition::dump(temp_str, cond)); + return 1; + } + +#ifdef WITH_OPENSSL + + DcmTLSTransportLayer *tLayer = NULL; + if (opt_secureConnection) + { + tLayer = new DcmTLSTransportLayer(DICOM_APPLICATION_REQUESTOR, opt_readSeedFile); + if (tLayer == NULL) + { + OFLOG_FATAL(findscuLogger, "unable to create TLS transport layer"); + return 1; + } + + if (cmd.findOption("--add-cert-file", 0, OFCommandLine::FOM_First)) + { + const char *current = NULL; + do + { + app.checkValue(cmd.getValue(current)); + if (TCS_ok != tLayer->addTrustedCertificateFile(current, opt_keyFileFormat)) + { + OFLOG_WARN(findscuLogger, "unable to load certificate file '" << current << "', ignoring"); + } + } while (cmd.findOption("--add-cert-file", 0, OFCommandLine::FOM_Next)); + } + + if (cmd.findOption("--add-cert-dir", 0, OFCommandLine::FOM_First)) + { + const char *current = NULL; + do + { + app.checkValue(cmd.getValue(current)); + if (TCS_ok != tLayer->addTrustedCertificateDir(current, opt_keyFileFormat)) + { + OFLOG_WARN(findscuLogger, "unable to load certificates from directory '" << current << "', ignoring"); + } + } while (cmd.findOption("--add-cert-dir", 0, OFCommandLine::FOM_Next)); + } + + if (opt_dhparam && ! (tLayer->setTempDHParameters(opt_dhparam))) + { + OFLOG_WARN(findscuLogger, "unable to load temporary DH parameter file '" << opt_dhparam << "', ignoring"); + } + + if (opt_doAuthenticate) + { + if (opt_passwd) tLayer->setPrivateKeyPasswd(opt_passwd); + + if (TCS_ok != tLayer->setPrivateKeyFile(opt_privateKeyFile, opt_keyFileFormat)) + { + OFLOG_FATAL(findscuLogger, "unable to load private TLS key from '" << opt_privateKeyFile << "'"); + return 1; + } + if (TCS_ok != tLayer->setCertificateFile(opt_certificateFile, opt_keyFileFormat)) + { + OFLOG_FATAL(findscuLogger, "unable to load certificate from '" << opt_certificateFile << "'"); + return 1; + } + if (! tLayer->checkPrivateKeyMatchesCertificate()) + { + OFLOG_FATAL(findscuLogger, "private key '" << opt_privateKeyFile << "' and certificate '" << opt_certificateFile << "' do not match"); + return 1; + } + } + + if (TCS_ok != tLayer->setCipherSuites(opt_ciphersuites.c_str())) + { + OFLOG_FATAL(findscuLogger, "unable to set selected cipher suites"); + return 1; + } + + tLayer->setCertificateVerification(opt_certVerification); + + cond = findscu.setTransportLayer(tLayer); + if (cond.bad()) + { + OFLOG_ERROR(findscuLogger, DimseCondition::dump(temp_str, cond)); + return 1; + } + } + +#endif + + // do the main work: negotiate network association, perform C-FIND transaction, + // process results, and finally tear down the association. + cond = findscu.performQuery( + opt_peer, + opt_port, + opt_ourTitle, + opt_peerTitle, + opt_abstractSyntax, + opt_networkTransferSyntax, + opt_blockMode, + opt_dimse_timeout, + opt_maxReceivePDULength, + opt_secureConnection, + opt_abortAssociation, + opt_repeatCount, + opt_extractResponsesToFile, + opt_cancelAfterNResponses, + &overrideKeys, + NULL, /* we want to use the default callback */ + &fileNameList, + opt_outputDirectory.c_str()); + + // destroy network structure + cond = findscu.dropNetwork(); + if (cond.bad()) OFLOG_ERROR(findscuLogger, DimseCondition::dump(temp_str, cond)); + +#ifdef HAVE_WINSOCK_H + WSACleanup(); +#endif + +#ifdef WITH_OPENSSL + if (tLayer && opt_writeSeedFile) + { + if (tLayer->canWriteRandomSeed()) + { + if (!tLayer->writeRandomSeed(opt_writeSeedFile)) + { + OFLOG_ERROR(findscuLogger, "cannot write random seed file '" << opt_writeSeedFile << "', ignoring"); + } + } else { + OFLOG_ERROR(findscuLogger, "cannot write random seed, ignoring"); + } + } + delete tLayer; + +#endif + + return 0; +} diff --git a/dcmnet/apps/getscu.cc b/dcmnet/apps/getscu.cc new file mode 100644 index 00000000..ac0b2174 --- /dev/null +++ b/dcmnet/apps/getscu.cc @@ -0,0 +1,593 @@ +/* + * + * Copyright (C) 2011-2013, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmnet + * + * Author: Michael Onken + * + * Purpose: Query/Retrieve Service Class User (C-GET operation) + * + */ + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#ifdef HAVE_GUSI_H +#include +#endif + +#include "dcmtk/ofstd/ofconapp.h" +#include "dcmtk/ofstd/oflist.h" +#include "dcmtk/dcmnet/scu.h" +#include "dcmtk/dcmdata/dcuid.h" /* for dcmtk version name */ +#include "dcmtk/dcmdata/dcostrmz.h" /* for dcmZlibCompressionLevel */ +#include "dcmtk/dcmdata/dcpath.h" /* for DcmPathProcessor */ + +#ifdef WITH_ZLIB +#include /* for zlibVersion() */ +#endif + +#define OFFIS_CONSOLE_APPLICATION "getscu" + +static OFLogger getscuLogger = OFLog::getLogger("dcmtk.apps." OFFIS_CONSOLE_APPLICATION); + +static char rcsid[] = "$dcmtk: " OFFIS_CONSOLE_APPLICATION " v" + OFFIS_DCMTK_VERSION " " OFFIS_DCMTK_RELEASEDATE " $"; + +/* default application titles */ +#define APPLICATIONTITLE "GETSCU" +#define PEERAPPLICATIONTITLE "ANY-SCP" + +typedef enum { + QMPatientRoot = 0, + QMStudyRoot = 1, + QMPatientStudyOnly = 2 +} QueryModel; + +static const char* querySyntax[3] = { + UID_GETPatientRootQueryRetrieveInformationModel, + UID_GETStudyRootQueryRetrieveInformationModel, + UID_RETIRED_GETPatientStudyOnlyQueryRetrieveInformationModel +}; + +OFCmdUnsignedInt opt_maxPDU = ASC_DEFAULTMAXPDU; +E_TransferSyntax opt_store_networkTransferSyntax = EXS_Unknown; +E_TransferSyntax opt_get_networkTransferSyntax = EXS_Unknown; +DcmStorageMode opt_storageMode = DCMSCU_STORAGE_DISK; +OFBool opt_showPresentationContexts = OFFalse; +OFBool opt_abortAssociation = OFFalse; +OFCmdUnsignedInt opt_repeatCount = 1; +QueryModel opt_queryModel = QMPatientRoot; +T_DIMSE_BlockingMode opt_blockMode = DIMSE_BLOCKING; +int opt_dimse_timeout = 0; +int opt_acse_timeout = 30; +OFString opt_outputDirectory = "."; +static OFList overrideKeys; + +static void prepareTS(E_TransferSyntax ts, + OFList& syntaxes); + +static void applyOverrideKeys(DcmDataset *dataset); + +#define SHORTCOL 4 +#define LONGCOL 21 + +int +main(int argc, char *argv[]) +{ + const char *opt_peer; + OFCmdUnsignedInt opt_port = 104;; + const char *opt_peerTitle = PEERAPPLICATIONTITLE; + const char *opt_ourTitle = APPLICATIONTITLE; + OFList fileNameList; + +#ifdef HAVE_GUSI_H + /* needed for Macintosh */ + GUSISetup(GUSIwithSIOUXSockets); + GUSISetup(GUSIwithInternetSockets); +#endif + + char tempstr[20]; + OFString temp_str; + OFConsoleApplication app(OFFIS_CONSOLE_APPLICATION , "DICOM retrieve (C-GET) SCU", rcsid); + OFCommandLine cmd; + + cmd.setParamColumn(LONGCOL + SHORTCOL + 4); + cmd.addParam("peer", "hostname of DICOM peer"); + cmd.addParam("port", "tcp/ip port number of peer"); + cmd.addParam("dcmfile-in", "DICOM query file(s)", OFCmdParam::PM_MultiOptional); + + cmd.setOptionColumns(LONGCOL, SHORTCOL); + cmd.addGroup("general options:", LONGCOL, SHORTCOL + 2); + cmd.addOption("--help", "-h", "print this help text and exit", OFCommandLine::AF_Exclusive); + cmd.addOption("--version", "print version information and exit", OFCommandLine::AF_Exclusive); + OFLog::addOptions(cmd); + cmd.addOption("--verbose-pc", "+v", "show presentation contexts in verbose mode"); + + cmd.addGroup("network options:"); + cmd.addSubGroup("override matching keys:"); + cmd.addOption("--key", "-k", 1, "[k]ey: gggg,eeee=\"str\", path or dic. name=\"str\"", + "override matching key"); + cmd.addSubGroup("retrieve information model:"); + cmd.addOption("--patient", "-P", "use patient root information model (default)"); + cmd.addOption("--study", "-S", "use study root information model"); + cmd.addOption("--psonly", "-O", "use patient/study only information model"); + cmd.addSubGroup("application entity titles:"); + OFString opt1 = "set my calling AE title (default: "; + opt1 += APPLICATIONTITLE; + opt1 += ")"; + cmd.addOption("--aetitle", "-aet", 1, "[a]etitle: string", opt1.c_str()); + OFString opt2 = "set called AE title of peer (default: "; + opt2 += PEERAPPLICATIONTITLE; + opt2 += ")"; + cmd.addOption("--call", "-aec", 1, "[a]etitle: string", opt2.c_str()); + cmd.addSubGroup("preferred storage transfer syntaxes (incoming associations):"); + cmd.addOption("--prefer-uncompr", "+x=", "prefer explicit VR local byte order (default)"); + cmd.addOption("--prefer-little", "+xe", "prefer explicit VR little endian TS"); + cmd.addOption("--prefer-big", "+xb", "prefer explicit VR big endian TS"); + cmd.addOption("--prefer-lossless", "+xs", "prefer default JPEG lossless TS"); + cmd.addOption("--prefer-jpeg8", "+xy", "prefer default JPEG lossy TS for 8 bit data"); + cmd.addOption("--prefer-jpeg12", "+xx", "prefer default JPEG lossy TS for 12 bit data"); + cmd.addOption("--prefer-j2k-lossless", "+xv", "prefer JPEG 2000 lossless TS"); + cmd.addOption("--prefer-j2k-lossy", "+xw", "prefer JPEG 2000 lossy TS"); + cmd.addOption("--prefer-jls-lossless", "+xt", "prefer JPEG-LS lossless TS"); + cmd.addOption("--prefer-jls-lossy", "+xu", "prefer JPEG-LS lossy TS"); + cmd.addOption("--prefer-mpeg2", "+xm", "prefer MPEG2 Main Profile @ Main Level TS"); + cmd.addOption("--prefer-mpeg2-high", "+xh", "prefer MPEG2 Main Profile @ High Level TS"); + cmd.addOption("--prefer-mpeg4", "+xn", "prefer MPEG4 AVC/H.264 HP / Level 4.1 TS"); + cmd.addOption("--prefer-mpeg4-bd", "+xl", "prefer MPEG4 AVC/H.264 BD-compatible TS"); + cmd.addOption("--prefer-rle", "+xr", "prefer RLE lossless TS"); +#ifdef WITH_ZLIB + cmd.addOption("--prefer-deflated", "+xd", "prefer deflated explicit VR little endian TS"); +#endif + cmd.addOption("--implicit", "+xi", "accept implicit VR little endian TS only"); + cmd.addSubGroup("proposed retrieve transfer syntaxes (outgoing associations):"); + cmd.addOption("--propose-uncompr", "-x=", "propose all uncompressed TS, explicit VR\nwith local byte ordering first (default)"); + cmd.addOption("--propose-little", "-xe", "propose all uncompressed TS, explicit VR\nlittle endian first"); + cmd.addOption("--propose-big", "-xb", "propose all uncompressed TS, explicit VR\nbig endian first"); +#ifdef WITH_ZLIB + cmd.addOption("--propose-deflated", "-xd", "propose deflated explicit VR little endian TS\nand all uncompressed transfer syntaxes"); +#endif + cmd.addOption("--propose-implicit", "-xi", "propose implicit VR little endian TS only"); + cmd.addSubGroup("other network options:"); + cmd.addOption("--timeout", "-to", 1, "[s]econds: integer (default: unlimited)", "timeout for connection requests"); + cmd.addOption("--acse-timeout", "-ta", 1, "[s]econds: integer (default: 30)", "timeout for ACSE messages"); + cmd.addOption("--dimse-timeout", "-td", 1, "[s]econds: integer (default: unlimited)", "timeout for DIMSE messages"); + + OFString opt3 = "set max receive pdu to n bytes (default: "; + sprintf(tempstr, "%ld", OFstatic_cast(long, ASC_DEFAULTMAXPDU)); + opt3 += tempstr; + opt3 += ")"; + OFString opt4 = "[n]umber of bytes: integer ("; + sprintf(tempstr, "%ld", OFstatic_cast(long, ASC_MINIMUMPDUSIZE)); + opt4 += tempstr; + opt4 += ".."; + sprintf(tempstr, "%ld", OFstatic_cast(long, ASC_MAXIMUMPDUSIZE)); + opt4 += tempstr; + opt4 += ")"; + cmd.addOption("--max-pdu", "-pdu", 1, opt4.c_str(), opt3.c_str()); + cmd.addOption("--repeat", 1, "[n]umber: integer", "repeat n times"); + cmd.addOption("--abort", "abort association instead of releasing it"); + cmd.addGroup("output options:"); + cmd.addSubGroup("general:"); + cmd.addOption("--output-directory", "-od", 1, "[d]irectory: string (default: \".\")", "write received objects to existing directory d"); + cmd.addSubGroup("storage mode:"); + cmd.addOption("--normal", "-B", "receive in memory, then write to disk (default)"); + cmd.addOption("--bit-preserving", "+B", "receive directly to disk"); + cmd.addOption("--ignore", "ignore store data, receive but do not store"); + + /* evaluate command line */ + prepareCmdLineArgs(argc, argv, OFFIS_CONSOLE_APPLICATION); + if (app.parseCommandLine(cmd, argc, argv)) + { + /* check exclusive options first */ + if (cmd.hasExclusiveOption()) + { + if (cmd.findOption("--version")) + { + app.printHeader(OFTrue /*print host identifier*/); + COUT << OFendl << "External libraries used:"; + #ifdef WITH_ZLIB + COUT << OFendl << "- ZLIB, Version " << zlibVersion() << OFendl; + #else + COUT << " none" << OFendl; + #endif + return 0; + } + } + + /* general options */ + OFLog::configureFromCommandLine(cmd, app); + if (cmd.findOption("--verbose-pc")) + { + app.checkDependence("--verbose-pc", "verbose mode", getscuLogger.isEnabledFor(OFLogger::INFO_LOG_LEVEL)); + opt_showPresentationContexts = OFTrue; + } + + /* network options */ + if (cmd.findOption("--key", 0, OFCommandLine::FOM_FirstFromLeft)) + { + const char *ovKey = NULL; + do + { + app.checkValue(cmd.getValue(ovKey)); + overrideKeys.push_back(ovKey); + } while (cmd.findOption("--key", 0, OFCommandLine::FOM_NextFromLeft)); + } + + cmd.beginOptionBlock(); + if (cmd.findOption("--patient")) opt_queryModel = QMPatientRoot; + if (cmd.findOption("--study")) opt_queryModel = QMStudyRoot; + if (cmd.findOption("--psonly")) opt_queryModel = QMPatientStudyOnly; + cmd.endOptionBlock(); + + if (cmd.findOption("--aetitle")) app.checkValue(cmd.getValue(opt_ourTitle)); + if (cmd.findOption("--call")) app.checkValue(cmd.getValue(opt_peerTitle)); + + cmd.beginOptionBlock(); + if (cmd.findOption("--prefer-uncompr")) opt_store_networkTransferSyntax = EXS_Unknown; + if (cmd.findOption("--prefer-little")) opt_store_networkTransferSyntax = EXS_LittleEndianExplicit; + if (cmd.findOption("--prefer-big")) opt_store_networkTransferSyntax = EXS_BigEndianExplicit; + if (cmd.findOption("--prefer-lossless")) opt_store_networkTransferSyntax = EXS_JPEGProcess14SV1; + if (cmd.findOption("--prefer-jpeg8")) opt_store_networkTransferSyntax = EXS_JPEGProcess1; + if (cmd.findOption("--prefer-jpeg12")) opt_store_networkTransferSyntax = EXS_JPEGProcess2_4; + if (cmd.findOption("--prefer-j2k-lossless")) opt_store_networkTransferSyntax = EXS_JPEG2000LosslessOnly; + if (cmd.findOption("--prefer-j2k-lossy")) opt_store_networkTransferSyntax = EXS_JPEG2000; + if (cmd.findOption("--prefer-jls-lossless")) opt_store_networkTransferSyntax = EXS_JPEGLSLossless; + if (cmd.findOption("--prefer-jls-lossy")) opt_store_networkTransferSyntax = EXS_JPEGLSLossy; + if (cmd.findOption("--prefer-mpeg2")) opt_store_networkTransferSyntax = EXS_MPEG2MainProfileAtMainLevel; + if (cmd.findOption("--prefer-mpeg2-high")) opt_store_networkTransferSyntax = EXS_MPEG2MainProfileAtHighLevel; + if (cmd.findOption("--prefer-mpeg4")) opt_store_networkTransferSyntax = EXS_MPEG4HighProfileLevel4_1; + if (cmd.findOption("--prefer-mpeg4-bd")) opt_store_networkTransferSyntax = EXS_MPEG4BDcompatibleHighProfileLevel4_1; + if (cmd.findOption("--prefer-rle")) opt_store_networkTransferSyntax = EXS_RLELossless; +#ifdef WITH_ZLIB + if (cmd.findOption("--prefer-deflated")) opt_store_networkTransferSyntax = EXS_DeflatedLittleEndianExplicit; +#endif + if (cmd.findOption("--implicit")) opt_store_networkTransferSyntax = EXS_LittleEndianImplicit; + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--propose-uncompr")) opt_get_networkTransferSyntax = EXS_Unknown; + if (cmd.findOption("--propose-little")) opt_get_networkTransferSyntax = EXS_LittleEndianExplicit; + if (cmd.findOption("--propose-big")) opt_get_networkTransferSyntax = EXS_BigEndianExplicit; + if (cmd.findOption("--propose-implicit")) opt_get_networkTransferSyntax = EXS_LittleEndianImplicit; +#ifdef WITH_ZLIB + if (cmd.findOption("--propose-deflated")) opt_get_networkTransferSyntax = EXS_DeflatedLittleEndianExplicit; +#endif + cmd.endOptionBlock(); + + if (cmd.findOption("--timeout")) + { + OFCmdSignedInt opt_timeout = 0; + app.checkValue(cmd.getValueAndCheckMin(opt_timeout, 1)); + dcmConnectionTimeout.set(OFstatic_cast(Sint32, opt_timeout)); + } + + if (cmd.findOption("--acse-timeout")) + { + OFCmdSignedInt opt_timeout = 0; + app.checkValue(cmd.getValueAndCheckMin(opt_timeout, 1)); + opt_acse_timeout = OFstatic_cast(int, opt_timeout); + } + + if (cmd.findOption("--dimse-timeout")) + { + OFCmdSignedInt opt_timeout = 0; + app.checkValue(cmd.getValueAndCheckMin(opt_timeout, 1)); + opt_dimse_timeout = OFstatic_cast(int, opt_timeout); + opt_blockMode = DIMSE_NONBLOCKING; + } + + if (cmd.findOption("--max-pdu")) app.checkValue(cmd.getValueAndCheckMinMax(opt_maxPDU, ASC_MINIMUMPDUSIZE, ASC_MAXIMUMPDUSIZE)); + if (cmd.findOption("--repeat")) app.checkValue(cmd.getValueAndCheckMin(opt_repeatCount, 1)); + if (cmd.findOption("--abort")) opt_abortAssociation = OFTrue; + if (cmd.findOption("--ignore")) opt_storageMode = DCMSCU_STORAGE_IGNORE; + + /* output options */ + if (cmd.findOption("--output-directory")) + { + app.checkConflict("--output-directory", "--ignore", opt_storageMode == DCMSCU_STORAGE_IGNORE); + app.checkValue(cmd.getValue(opt_outputDirectory)); + } + + cmd.beginOptionBlock(); + if (cmd.findOption("--bit-preserving")) + { + app.checkConflict("--bit-preserving", "--ignore", opt_storageMode == DCMSCU_STORAGE_IGNORE); + opt_storageMode = DCMSCU_STORAGE_BIT_PRESERVING; + } + if (cmd.findOption("--normal")) + { + app.checkConflict("--normal", "--bit-preserving", opt_storageMode == DCMSCU_STORAGE_BIT_PRESERVING); + app.checkConflict("--normal", "--ignore", opt_storageMode == DCMSCU_STORAGE_IGNORE); + opt_storageMode = DCMSCU_STORAGE_DISK; + } + cmd.endOptionBlock(); + + /* command line parameters */ + cmd.getParam(1, opt_peer); + app.checkParam(cmd.getParamAndCheckMinMax(2, opt_port, 1, 65535)); + + /* finally, parse filenames */ + int paramCount = cmd.getParamCount(); + const char *currentFilename = NULL; + OFString errormsg; + + for (int i = 3; i <= paramCount; i++) + { + cmd.getParam(i, currentFilename); + if (access(currentFilename, R_OK) < 0) + { + errormsg = "cannot access file: "; + errormsg += currentFilename; + app.printError(errormsg.c_str()); + } + fileNameList.push_back(currentFilename); + } + + if (fileNameList.empty() && overrideKeys.empty()) + { + app.printError("either query file or override keys (or both) must be specified"); + } + } + + /* print resource identifier */ + OFLOG_DEBUG(getscuLogger, rcsid << OFendl); + + /* make sure data dictionary is loaded */ + if (!dcmDataDict.isDictionaryLoaded()) + { + OFLOG_WARN(getscuLogger, "no data dictionary loaded, check environment variable: " + << DCM_DICT_ENVIRONMENT_VARIABLE); + } + + /* make sure output directory exists and is writeable */ + if (!OFStandard::dirExists(opt_outputDirectory)) + { + OFLOG_FATAL(getscuLogger, "specified output directory does not exist"); + return 1; + } + else if (!OFStandard::isWriteable(opt_outputDirectory)) + { + OFLOG_FATAL(getscuLogger, "specified output directory is not writeable"); + return 1; + } + + /* setup SCU */ + OFList syntaxes; + prepareTS(opt_get_networkTransferSyntax, syntaxes); + DcmSCU scu; + scu.setMaxReceivePDULength(opt_maxPDU); + scu.setACSETimeout(opt_acse_timeout); + scu.setDIMSEBlockingMode(opt_blockMode); + scu.setDIMSETimeout(opt_dimse_timeout); + scu.setAETitle(opt_ourTitle); + scu.setPeerHostName(opt_peer); + scu.setPeerPort(OFstatic_cast(Uint16, opt_port)); + scu.setPeerAETitle(opt_peerTitle); + scu.setVerbosePCMode(opt_showPresentationContexts); + + /* add presentation contexts for get and find (we do not actually need find...) + * (only uncompressed) + */ + scu.addPresentationContext(querySyntax[opt_queryModel], syntaxes); + + /* add storage presentation contexts (long list of storage SOP classes, uncompressed) */ + syntaxes.clear(); + prepareTS(opt_store_networkTransferSyntax, syntaxes); + for (Uint16 j = 0; j < numberOfDcmLongSCUStorageSOPClassUIDs; j++) + { + scu.addPresentationContext(dcmLongSCUStorageSOPClassUIDs[j], syntaxes, ASC_SC_ROLE_SCP); + } + + /* set the storage mode */ + scu.setStorageMode(opt_storageMode); + if (opt_storageMode != DCMSCU_STORAGE_IGNORE) + { + scu.setStorageDir(opt_outputDirectory); + } + + /* initialize network and negotiate association */ + OFCondition cond = scu.initNetwork(); + if (cond.bad()) + { + OFLOG_FATAL(getscuLogger, DimseCondition::dump(temp_str, cond)); + exit(1); + } + cond = scu.negotiateAssociation(); + if (cond.bad()) + { + OFLOG_FATAL(getscuLogger, "No Acceptable Presentation Contexts"); + exit(1); + } + cond = EC_Normal; + T_ASC_PresentationContextID pcid = scu.findPresentationContextID(querySyntax[opt_queryModel], ""); + if (pcid == 0) + { + OFLOG_FATAL(getscuLogger, "No adequate Presentation Contexts for sending C-GET"); + exit(1); + } + + /* do the real work, i.e. send C-GET requests and receive objects */ + for (Uint16 repeat = 0; repeat < opt_repeatCount; repeat++) + { + Uint16 numRuns = 1; + DcmFileFormat dcmff; + DcmDataset *dset = dcmff.getDataset(); + OFListConstIterator(OFString) it; + /* load first file, if there is one */ + if (!fileNameList.empty()) + { + numRuns = fileNameList.size(); + it = fileNameList.begin(); + cond = dcmff.loadFile((*it).c_str()); + if (cond.bad()) + { + OFLOG_FATAL(getscuLogger, DimseCondition::dump(temp_str, cond)); + exit(1); + } + dset = dcmff.getDataset(); + } + OFList responses; + /* for all files (or at least one run from override keys) */ + for (Uint16 i = 0; i < numRuns; i++) + { + applyOverrideKeys(dset); + cond = scu.sendCGETRequest(pcid, dset, &responses); + if (cond.bad()) + { + exit(1); + } + /* load next file if there is one */ + if (numRuns > 1) + { + it++; + cond = dcmff.loadFile((*it).c_str()); + if (cond.bad()) + { + OFLOG_FATAL(getscuLogger, DimseCondition::dump(temp_str, cond)); + exit(1); + } + dset = dcmff.getDataset(); + } + } + if (!responses.empty()) + { + /* output final status report */ + OFLOG_INFO(getscuLogger, "Final status report from last C-GET message:"); + (*(--responses.end()))->print(); + /* delete responses */ + OFListIterator(RetrieveResponse*) iter = responses.begin(); + OFListConstIterator(RetrieveResponse*) last = responses.end(); + while (iter != last) + { + delete (*iter); + iter = responses.erase(iter); + } + } + } + + int status = 0; + /* tear down association */ + if (cond == EC_Normal) + { + if (opt_abortAssociation) + scu.abortAssociation(); + else + scu.releaseAssociation(); + } + else + { + if (cond == DUL_PEERREQUESTEDRELEASE) + scu.closeAssociation(DCMSCU_PEER_REQUESTED_RELEASE); + else if (cond == DUL_PEERABORTEDASSOCIATION) + scu.closeAssociation(DCMSCU_PEER_ABORTED_ASSOCIATION); + else + { + OFLOG_ERROR(getscuLogger, "Get SCU Failed: " << DimseCondition::dump(temp_str, cond)); + scu.abortAssociation(); + } + /* TODO: need to find better exit codes */ + status = 1; + } + + return status; +} + + +static void applyOverrideKeys(DcmDataset *dataset) +{ + /* replace specific keys by those in overrideKeys */ + OFListConstIterator(OFString) path = overrideKeys.begin(); + OFListConstIterator(OFString) endOfList = overrideKeys.end(); + DcmPathProcessor proc; + proc.setItemWildcardSupport(OFFalse); + proc.checkPrivateReservations(OFFalse); + OFCondition cond; + while (path != endOfList) + { + cond = proc.applyPathWithValue(dataset, *path); + if (cond.bad()) + { + OFLOG_ERROR(getscuLogger, "Bad override key/path: " << *path << ": " << cond.text()); + } + path++; + } +} + +static void prepareTS(E_TransferSyntax ts, + OFList& syntaxes) +{ + /* + ** We prefer to use Explicitly encoded transfer syntaxes. + ** If we are running on a Little Endian machine we prefer + ** LittleEndianExplicitTransferSyntax to BigEndianTransferSyntax. + ** Some SCP implementations will just select the first transfer + ** syntax they support (this is not part of the standard) so + ** organize the proposed transfer syntaxes to take advantage + ** of such behavior. + ** + ** The presentation contexts proposed here are only used for + ** C-FIND and C-MOVE, so there is no need to support compressed + ** transmission. + */ + + switch (ts) + { + case EXS_LittleEndianImplicit: + /* we only support Little Endian Implicit */ + syntaxes.push_back(UID_LittleEndianExplicitTransferSyntax); + break; + case EXS_LittleEndianExplicit: + /* we prefer Little Endian Explicit */ + syntaxes.push_back(UID_LittleEndianExplicitTransferSyntax); + syntaxes.push_back(UID_BigEndianExplicitTransferSyntax); + syntaxes.push_back(UID_LittleEndianImplicitTransferSyntax); + break; + case EXS_BigEndianExplicit: + /* we prefer Big Endian Explicit */ + syntaxes.push_back(UID_BigEndianExplicitTransferSyntax); + syntaxes.push_back(UID_LittleEndianExplicitTransferSyntax); + syntaxes.push_back(UID_LittleEndianImplicitTransferSyntax); + break; +#ifdef WITH_ZLIB + case EXS_DeflatedLittleEndianExplicit: + /* we prefer Deflated Little Endian Explicit */ + syntaxes.push_back(UID_DeflatedExplicitVRLittleEndianTransferSyntax); + syntaxes.push_back(UID_LittleEndianExplicitTransferSyntax); + syntaxes.push_back(UID_BigEndianExplicitTransferSyntax); + syntaxes.push_back(UID_LittleEndianImplicitTransferSyntax); + break; +#endif + default: + DcmXfer xfer(ts); + if (xfer.isEncapsulated()) + { + syntaxes.push_back(xfer.getXferID()); + } + /* We prefer explicit transfer syntaxes. + * If we are running on a Little Endian machine we prefer + * LittleEndianExplicitTransferSyntax to BigEndianTransferSyntax. + */ + if (gLocalByteOrder == EBO_LittleEndian) /* defined in dcxfer.h */ + { + syntaxes.push_back(UID_LittleEndianExplicitTransferSyntax); + syntaxes.push_back(UID_BigEndianExplicitTransferSyntax); + } else + { + syntaxes.push_back(UID_BigEndianExplicitTransferSyntax); + syntaxes.push_back(UID_LittleEndianExplicitTransferSyntax); + } + syntaxes.push_back(UID_LittleEndianImplicitTransferSyntax); + break; + } +} diff --git a/dcmnet/apps/movescu.cc b/dcmnet/apps/movescu.cc new file mode 100644 index 00000000..e86bad44 --- /dev/null +++ b/dcmnet/apps/movescu.cc @@ -0,0 +1,1626 @@ +/* + * + * Copyright (C) 1994-2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmnet + * + * Author: Andrew Hewett + * + * Purpose: Query/Retrieve Service Class User (C-MOVE operation) + * + */ + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#define INCLUDE_CSTDLIB +#define INCLUDE_CSTDIO +#define INCLUDE_CSTRING +#define INCLUDE_CSTDARG +#define INCLUDE_CERRNO +#include "dcmtk/ofstd/ofstdinc.h" + +#ifdef HAVE_GUSI_H +#include +#endif + +#include "dcmtk/ofstd/ofstd.h" +#include "dcmtk/ofstd/ofconapp.h" +#include "dcmtk/dcmnet/dicom.h" +#include "dcmtk/dcmnet/dimse.h" +#include "dcmtk/dcmnet/diutil.h" +#include "dcmtk/dcmdata/dcfilefo.h" +#include "dcmtk/dcmdata/dcuid.h" +#include "dcmtk/dcmdata/dcdict.h" +#include "dcmtk/dcmdata/cmdlnarg.h" +#include "dcmtk/dcmdata/dcdeftag.h" +#include "dcmtk/dcmdata/dcmetinf.h" +#include "dcmtk/dcmdata/dcuid.h" /* for dcmtk version name */ +#include "dcmtk/dcmdata/dcdicent.h" +#include "dcmtk/dcmdata/dcostrmz.h" /* for dcmZlibCompressionLevel */ + +#ifdef WITH_ZLIB +#include /* for zlibVersion() */ +#endif + +#define OFFIS_CONSOLE_APPLICATION "movescu" + +static OFLogger movescuLogger = OFLog::getLogger("dcmtk.apps." OFFIS_CONSOLE_APPLICATION); + +static char rcsid[] = "$dcmtk: " OFFIS_CONSOLE_APPLICATION " v" + OFFIS_DCMTK_VERSION " " OFFIS_DCMTK_RELEASEDATE " $"; + +/* default application titles */ +#define APPLICATIONTITLE "MOVESCU" +#define PEERAPPLICATIONTITLE "ANY-SCP" + +typedef enum { + QMPatientRoot = 0, + QMStudyRoot = 1, + QMPatientStudyOnly = 2 +} QueryModel; + +typedef struct { + const char *findSyntax; + const char *moveSyntax; +} QuerySyntax; + +typedef struct { + T_ASC_Association *assoc; + T_ASC_PresentationContextID presId; +} MyCallbackInfo; + +OFCmdUnsignedInt opt_sleepAfter = 0; +OFCmdUnsignedInt opt_sleepDuring = 0; +OFCmdUnsignedInt opt_maxPDU = ASC_DEFAULTMAXPDU; +OFBool opt_useMetaheader = OFTrue; +OFBool opt_acceptAllXfers = OFFalse; +E_TransferSyntax opt_in_networkTransferSyntax = EXS_Unknown; +E_TransferSyntax opt_out_networkTransferSyntax = EXS_Unknown; +E_TransferSyntax opt_writeTransferSyntax = EXS_Unknown; +E_GrpLenEncoding opt_groupLength = EGL_recalcGL; +E_EncodingType opt_sequenceType = EET_ExplicitLength; +E_PaddingEncoding opt_paddingType = EPD_withoutPadding; +OFCmdUnsignedInt opt_filepad = 0; +OFCmdUnsignedInt opt_itempad = 0; +OFBool opt_bitPreserving = OFFalse; +OFBool opt_ignore = OFFalse; +OFBool opt_abortDuringStore = OFFalse; +OFBool opt_abortAfterStore = OFFalse; +OFBool opt_correctUIDPadding = OFFalse; +OFCmdUnsignedInt opt_repeatCount = 1; +OFCmdUnsignedInt opt_retrievePort = 0; +OFBool opt_abortAssociation = OFFalse; +const char * opt_moveDestination = NULL; +OFCmdSignedInt opt_cancelAfterNResponses = -1; +QueryModel opt_queryModel = QMPatientRoot; +T_DIMSE_BlockingMode opt_blockMode = DIMSE_BLOCKING; +int opt_dimse_timeout = 0; +int opt_acse_timeout = 30; +OFBool opt_ignorePendingDatasets = OFTrue; +OFString opt_outputDirectory = "."; + +#ifdef WITH_ZLIB +OFCmdUnsignedInt opt_compressionLevel = 0; +#endif + +static T_ASC_Network *net = NULL; /* the global DICOM network */ +static DcmDataset *overrideKeys = NULL; +static QuerySyntax querySyntax[3] = { + { UID_FINDPatientRootQueryRetrieveInformationModel, + UID_MOVEPatientRootQueryRetrieveInformationModel }, + { UID_FINDStudyRootQueryRetrieveInformationModel, + UID_MOVEStudyRootQueryRetrieveInformationModel }, + { UID_RETIRED_FINDPatientStudyOnlyQueryRetrieveInformationModel, + UID_RETIRED_MOVEPatientStudyOnlyQueryRetrieveInformationModel } +}; + + +static void +addOverrideKey(OFConsoleApplication& app, const char *s) +{ + unsigned int g = 0xffff; + unsigned int e = 0xffff; + int n = 0; + OFString dicName, valStr; + OFString msg; + char msg2[200]; + + // try to parse group and element number + n = sscanf(s, "%x,%x=", &g, &e); + OFString toParse = s; + size_t eqPos = toParse.find('='); + if (n < 2) // if at least no tag could be parsed + { + // if value is given, extract it (and dictionary name) + if (eqPos != OFString_npos) + { + dicName = toParse.substr(0,eqPos).c_str(); + valStr = toParse.substr(eqPos+1,toParse.length()); + } + else // no value given, just dictionary name + dicName = s; // only dictionary name given (without value) + // try to lookup in dictionary + DcmTagKey key(0xffff,0xffff); + const DcmDataDictionary& globalDataDict = dcmDataDict.rdlock(); + const DcmDictEntry *dicent = globalDataDict.findEntry(dicName.c_str()); + dcmDataDict.unlock(); + if (dicent!=NULL) { + // found dictionary name, copy group and element number + key = dicent->getKey(); + g = key.getGroup(); + e = key.getElement(); + } + else { + // not found in dictionary + msg = "bad key format or dictionary name not found in dictionary: "; + msg += dicName; + app.printError(msg.c_str()); + } + } // tag could be parsed, copy value if it exists + else + { + if (eqPos != OFString_npos) + valStr = toParse.substr(eqPos+1,toParse.length()); + } + DcmTag tag(g,e); + if (tag.error() != EC_Normal) { + sprintf(msg2, "unknown tag: (%04x,%04x)", g, e); + app.printError(msg2); + } + DcmElement *elem = newDicomElement(tag); + if (elem == NULL) { + sprintf(msg2, "cannot create element for tag: (%04x,%04x)", g, e); + app.printError(msg2); + } + if (!valStr.empty()) { + if (elem->putString(valStr.c_str()).bad()) + { + sprintf(msg2, "cannot put tag value: (%04x,%04x)=\"", g, e); + msg = msg2; + msg += valStr; + msg += "\""; + app.printError(msg.c_str()); + } + } + + if (overrideKeys == NULL) overrideKeys = new DcmDataset; + if (overrideKeys->insert(elem, OFTrue).bad()) { + sprintf(msg2, "cannot insert tag: (%04x,%04x)", g, e); + app.printError(msg2); + } +} + +static OFCondition cmove(T_ASC_Association *assoc, const char *fname); + +static OFCondition +addPresentationContext(T_ASC_Parameters *params, + T_ASC_PresentationContextID pid, + const char *abstractSyntax); + +#define SHORTCOL 4 +#define LONGCOL 21 + +int +main(int argc, char *argv[]) +{ + T_ASC_Parameters *params = NULL; + const char *opt_peer; + OFCmdUnsignedInt opt_port = 104; + DIC_NODENAME localHost; + DIC_NODENAME peerHost; + T_ASC_Association *assoc = NULL; + const char *opt_peerTitle = PEERAPPLICATIONTITLE; + const char *opt_ourTitle = APPLICATIONTITLE; + OFList fileNameList; + +#ifdef HAVE_GUSI_H + /* needed for Macintosh */ + GUSISetup(GUSIwithSIOUXSockets); + GUSISetup(GUSIwithInternetSockets); +#endif + +#ifdef HAVE_WINSOCK_H + WSAData winSockData; + /* we need at least version 1.1 */ + WORD winSockVersionNeeded = MAKEWORD( 1, 1 ); + WSAStartup(winSockVersionNeeded, &winSockData); +#endif + + char tempstr[20]; + OFString temp_str; + OFConsoleApplication app(OFFIS_CONSOLE_APPLICATION , "DICOM retrieve (C-MOVE) SCU", rcsid); + OFCommandLine cmd; + + cmd.setParamColumn(LONGCOL + SHORTCOL + 4); + cmd.addParam("peer", "hostname of DICOM peer"); + cmd.addParam("port", "tcp/ip port number of peer"); + cmd.addParam("dcmfile-in", "DICOM query file(s)", OFCmdParam::PM_MultiOptional); + + cmd.setOptionColumns(LONGCOL, SHORTCOL); + cmd.addGroup("general options:", LONGCOL, SHORTCOL + 2); + cmd.addOption("--help", "-h", "print this help text and exit", OFCommandLine::AF_Exclusive); + cmd.addOption("--version", "print version information and exit", OFCommandLine::AF_Exclusive); + OFLog::addOptions(cmd); + + cmd.addGroup("network options:"); + cmd.addSubGroup("override matching keys:"); + cmd.addOption("--key", "-k", 1, "[k]ey: gggg,eeee=\"str\" or dict. name=\"str\"", + "override matching key"); + cmd.addSubGroup("query information model:"); + cmd.addOption("--patient", "-P", "use patient root information model (default)"); + cmd.addOption("--study", "-S", "use study root information model"); + cmd.addOption("--psonly", "-O", "use patient/study only information model"); + cmd.addSubGroup("application entity titles:"); + OFString opt1 = "set my calling AE title (default: "; + opt1 += APPLICATIONTITLE; + opt1 += ")"; + cmd.addOption("--aetitle", "-aet", 1, "[a]etitle: string", opt1.c_str()); + OFString opt2 = "set called AE title of peer (default: "; + opt2 += PEERAPPLICATIONTITLE; + opt2 += ")"; + cmd.addOption("--call", "-aec", 1, "[a]etitle: string", opt2.c_str()); + OFString opt5 = "set move destinat. AE title (default: "; + opt5 += APPLICATIONTITLE; + opt5 += ")"; + cmd.addOption("--move", "-aem", 1, "[a]etitle: string", opt5.c_str()); + cmd.addSubGroup("preferred network transfer syntaxes (incoming associations):"); + cmd.addOption("--prefer-uncompr", "+x=", "prefer explicit VR local byte order (default)"); + cmd.addOption("--prefer-little", "+xe", "prefer explicit VR little endian TS"); + cmd.addOption("--prefer-big", "+xb", "prefer explicit VR big endian TS"); + cmd.addOption("--prefer-lossless", "+xs", "prefer default JPEG lossless TS"); + cmd.addOption("--prefer-jpeg8", "+xy", "prefer default JPEG lossy TS for 8 bit data"); + cmd.addOption("--prefer-jpeg12", "+xx", "prefer default JPEG lossy TS for 12 bit data"); + cmd.addOption("--prefer-j2k-lossless", "+xv", "prefer JPEG 2000 lossless TS"); + cmd.addOption("--prefer-j2k-lossy", "+xw", "prefer JPEG 2000 lossy TS"); + cmd.addOption("--prefer-jls-lossless", "+xt", "prefer JPEG-LS lossless TS"); + cmd.addOption("--prefer-jls-lossy", "+xu", "prefer JPEG-LS lossy TS"); + cmd.addOption("--prefer-mpeg2", "+xm", "prefer MPEG2 Main Profile @ Main Level TS"); + cmd.addOption("--prefer-mpeg2-high", "+xh", "prefer MPEG2 Main Profile @ High Level TS"); + cmd.addOption("--prefer-mpeg4", "+xn", "prefer MPEG4 AVC/H.264 HP / Level 4.1 TS"); + cmd.addOption("--prefer-mpeg4-bd", "+xl", "prefer MPEG4 AVC/H.264 BD-compatible TS"); + cmd.addOption("--prefer-rle", "+xr", "prefer RLE lossless TS"); +#ifdef WITH_ZLIB + cmd.addOption("--prefer-deflated", "+xd", "prefer deflated explicit VR little endian TS"); +#endif + cmd.addOption("--implicit", "+xi", "accept implicit VR little endian TS only"); + cmd.addOption("--accept-all", "+xa", "accept all supported transfer syntaxes"); + cmd.addSubGroup("proposed transmission transfer syntaxes (outgoing associations):"); + cmd.addOption("--propose-uncompr", "-x=", "propose all uncompressed TS, explicit VR\nwith local byte ordering first (default)"); + cmd.addOption("--propose-little", "-xe", "propose all uncompressed TS, explicit VR\nlittle endian first"); + cmd.addOption("--propose-big", "-xb", "propose all uncompressed TS, explicit VR\nbig endian first"); +#ifdef WITH_ZLIB + cmd.addOption("--propose-deflated", "-xd", "propose deflated explicit VR little endian TS\nand all uncompressed transfer syntaxes"); +#endif + cmd.addOption("--propose-implicit", "-xi", "propose implicit VR little endian TS only"); +#ifdef WITH_TCPWRAPPER + cmd.addSubGroup("network host access control (tcp wrapper):"); + cmd.addOption("--access-full", "-ac", "accept connections from any host (default)"); + cmd.addOption("--access-control", "+ac", "enforce host access control rules"); +#endif + cmd.addSubGroup("port for incoming network associations:"); + cmd.addOption("--no-port", "no port for incoming associations (default)"); + cmd.addOption("--port", "+P", 1, "[n]umber: integer", + "port number for incoming associations"); + cmd.addSubGroup("handling of illegal datasets following 'pending' move responses:"); + cmd.addOption("--pending-ignore", "-pi", "assume no dataset present (default)"); + cmd.addOption("--pending-read", "-pr", "read and ignore dataset"); + + cmd.addSubGroup("other network options:"); + cmd.addOption("--timeout", "-to", 1, "[s]econds: integer (default: unlimited)", "timeout for connection requests"); + cmd.addOption("--acse-timeout", "-ta", 1, "[s]econds: integer (default: 30)", "timeout for ACSE messages"); + cmd.addOption("--dimse-timeout", "-td", 1, "[s]econds: integer (default: unlimited)", "timeout for DIMSE messages"); + + OFString opt3 = "set max receive pdu to n bytes (default: "; + sprintf(tempstr, "%ld", OFstatic_cast(long, ASC_DEFAULTMAXPDU)); + opt3 += tempstr; + opt3 += ")"; + OFString opt4 = "[n]umber of bytes: integer ("; + sprintf(tempstr, "%ld", OFstatic_cast(long, ASC_MINIMUMPDUSIZE)); + opt4 += tempstr; + opt4 += ".."; + sprintf(tempstr, "%ld", OFstatic_cast(long, ASC_MAXIMUMPDUSIZE)); + opt4 += tempstr; + opt4 += ")"; + cmd.addOption("--max-pdu", "-pdu", 1, opt4.c_str(), opt3.c_str()); + cmd.addOption("--disable-host-lookup", "-dhl", "disable hostname lookup"); + cmd.addOption("--repeat", 1, "[n]umber: integer", "repeat n times"); + cmd.addOption("--abort", "abort association instead of releasing it"); + cmd.addOption("--ignore", "ignore store data, receive but do not store"); + cmd.addOption("--cancel", 1, "[n]umber: integer", + "cancel after n responses (default: never)"); + cmd.addOption("--uid-padding", "-up", "silently correct space-padded UIDs"); + cmd.addGroup("output options:"); + cmd.addSubGroup("general:"); + cmd.addOption("--output-directory", "-od", 1, "[d]irectory: string (default: \".\")", "write received objects to existing directory d"); + cmd.addSubGroup("bit preserving mode:"); + cmd.addOption("--normal", "-B", "allow implicit format conversions (default)"); + cmd.addOption("--bit-preserving", "+B", "write data exactly as read"); + cmd.addSubGroup("output file format:"); + cmd.addOption("--write-file", "+F", "write file format (default)"); + cmd.addOption("--write-dataset", "-F", "write data set without file meta information"); + cmd.addSubGroup("output transfer syntax (not with --bit-preserving or compressed transmission):"); + cmd.addOption("--write-xfer-same", "+t=", "write with same TS as input (default)"); + cmd.addOption("--write-xfer-little", "+te", "write with explicit VR little endian TS"); + cmd.addOption("--write-xfer-big", "+tb", "write with explicit VR big endian TS"); + cmd.addOption("--write-xfer-implicit", "+ti", "write with implicit VR little endian TS"); +#ifdef WITH_ZLIB + cmd.addOption("--write-xfer-deflated", "+td", "write with deflated expl. VR little endian TS"); +#endif + cmd.addSubGroup("post-1993 value representations (not with --bit-preserving):"); + cmd.addOption("--enable-new-vr", "+u", "enable support for new VRs (UN/UT) (default)"); + cmd.addOption("--disable-new-vr", "-u", "disable support for new VRs, convert to OB"); + cmd.addSubGroup("group length encoding (not with --bit-preserving):"); + cmd.addOption("--group-length-recalc", "+g=", "recalculate group lengths if present (default)"); + cmd.addOption("--group-length-create", "+g", "always write with group length elements"); + cmd.addOption("--group-length-remove", "-g", "always write without group length elements"); + cmd.addSubGroup("length encoding in sequences and items (not with --bit-preserving):"); + cmd.addOption("--length-explicit", "+e", "write with explicit lengths (default)"); + cmd.addOption("--length-undefined", "-e", "write with undefined lengths"); + cmd.addSubGroup("data set trailing padding (not with --write-dataset or --bit-preserving):"); + cmd.addOption("--padding-off", "-p", "no padding (default)"); + cmd.addOption("--padding-create", "+p", 2, "[f]ile-pad [i]tem-pad: integer", + "align file on multiple of f bytes\nand items on multiple of i bytes"); +#ifdef WITH_ZLIB + cmd.addSubGroup("deflate compression level (only with -xd or --write-xfer-deflated/same):"); + cmd.addOption("--compression-level", "+cl", 1, "[l]evel: integer (default: 6)", + "0=uncompressed, 1=fastest, 9=best compression"); +#endif + + /* evaluate command line */ + prepareCmdLineArgs(argc, argv, OFFIS_CONSOLE_APPLICATION); + if (app.parseCommandLine(cmd, argc, argv)) + { + /* check exclusive options first */ + if (cmd.hasExclusiveOption()) + { + if (cmd.findOption("--version")) + { + app.printHeader(OFTrue /*print host identifier*/); + COUT << OFendl << "External libraries used:"; +#if !defined(WITH_ZLIB) && !defined(WITH_TCPWRAPPER) + COUT << " none" << OFendl; +#else + COUT << OFendl; +#endif +#ifdef WITH_ZLIB + COUT << "- ZLIB, Version " << zlibVersion() << OFendl; +#endif +#ifdef WITH_TCPWRAPPER + COUT << "- LIBWRAP" << OFendl; +#endif + return 0; + } + } + + /* command line parameters */ + + cmd.getParam(1, opt_peer); + app.checkParam(cmd.getParamAndCheckMinMax(2, opt_port, 1, 65535)); + + OFLog::configureFromCommandLine(cmd, app); + + if (cmd.findOption("--key", 0, OFCommandLine::FOM_First)) + { + const char *ovKey = NULL; + do { + app.checkValue(cmd.getValue(ovKey)); + addOverrideKey(app, ovKey); + } while (cmd.findOption("--key", 0, OFCommandLine::FOM_Next)); + } + cmd.beginOptionBlock(); + if (cmd.findOption("--patient")) opt_queryModel = QMPatientRoot; + if (cmd.findOption("--study")) opt_queryModel = QMStudyRoot; + if (cmd.findOption("--psonly")) opt_queryModel = QMPatientStudyOnly; + cmd.endOptionBlock(); + + if (cmd.findOption("--aetitle")) app.checkValue(cmd.getValue(opt_ourTitle)); + if (cmd.findOption("--call")) app.checkValue(cmd.getValue(opt_peerTitle)); + if (cmd.findOption("--move")) app.checkValue(cmd.getValue(opt_moveDestination)); + + cmd.beginOptionBlock(); + if (cmd.findOption("--prefer-uncompr")) + { + opt_acceptAllXfers = OFFalse; + opt_in_networkTransferSyntax = EXS_Unknown; + } + if (cmd.findOption("--prefer-little")) opt_in_networkTransferSyntax = EXS_LittleEndianExplicit; + if (cmd.findOption("--prefer-big")) opt_in_networkTransferSyntax = EXS_BigEndianExplicit; + if (cmd.findOption("--prefer-lossless")) opt_in_networkTransferSyntax = EXS_JPEGProcess14SV1; + if (cmd.findOption("--prefer-jpeg8")) opt_in_networkTransferSyntax = EXS_JPEGProcess1; + if (cmd.findOption("--prefer-jpeg12")) opt_in_networkTransferSyntax = EXS_JPEGProcess2_4; + if (cmd.findOption("--prefer-j2k-lossless")) opt_in_networkTransferSyntax = EXS_JPEG2000LosslessOnly; + if (cmd.findOption("--prefer-j2k-lossy")) opt_in_networkTransferSyntax = EXS_JPEG2000; + if (cmd.findOption("--prefer-jls-lossless")) opt_in_networkTransferSyntax = EXS_JPEGLSLossless; + if (cmd.findOption("--prefer-jls-lossy")) opt_in_networkTransferSyntax = EXS_JPEGLSLossy; + if (cmd.findOption("--prefer-mpeg2")) opt_in_networkTransferSyntax = EXS_MPEG2MainProfileAtMainLevel; + if (cmd.findOption("--prefer-mpeg2-high")) opt_in_networkTransferSyntax = EXS_MPEG2MainProfileAtHighLevel; + if (cmd.findOption("--prefer-mpeg4")) opt_in_networkTransferSyntax = EXS_MPEG4HighProfileLevel4_1; + if (cmd.findOption("--prefer-mpeg4-bd")) opt_in_networkTransferSyntax = EXS_MPEG4BDcompatibleHighProfileLevel4_1; + if (cmd.findOption("--prefer-rle")) opt_in_networkTransferSyntax = EXS_RLELossless; +#ifdef WITH_ZLIB + if (cmd.findOption("--prefer-deflated")) opt_in_networkTransferSyntax = EXS_DeflatedLittleEndianExplicit; +#endif + if (cmd.findOption("--implicit")) opt_in_networkTransferSyntax = EXS_LittleEndianImplicit; + if (cmd.findOption("--accept-all")) + { + opt_acceptAllXfers = OFTrue; + opt_in_networkTransferSyntax = EXS_Unknown; + } + cmd.endOptionBlock(); + if (opt_in_networkTransferSyntax != EXS_Unknown) opt_acceptAllXfers = OFFalse; + + cmd.beginOptionBlock(); + if (cmd.findOption("--propose-uncompr")) opt_out_networkTransferSyntax = EXS_Unknown; + if (cmd.findOption("--propose-little")) opt_out_networkTransferSyntax = EXS_LittleEndianExplicit; + if (cmd.findOption("--propose-big")) opt_out_networkTransferSyntax = EXS_BigEndianExplicit; + if (cmd.findOption("--propose-implicit")) opt_out_networkTransferSyntax = EXS_LittleEndianImplicit; +#ifdef WITH_ZLIB + if (cmd.findOption("--propose-deflated")) opt_out_networkTransferSyntax = EXS_DeflatedLittleEndianExplicit; +#endif + cmd.endOptionBlock(); + +#ifdef WITH_TCPWRAPPER + cmd.beginOptionBlock(); + if (cmd.findOption("--access-full")) dcmTCPWrapperDaemonName.set(NULL); + if (cmd.findOption("--access-control")) dcmTCPWrapperDaemonName.set(OFFIS_CONSOLE_APPLICATION); + cmd.endOptionBlock(); +#endif + + if (cmd.findOption("--timeout")) + { + OFCmdSignedInt opt_timeout = 0; + app.checkValue(cmd.getValueAndCheckMin(opt_timeout, 1)); + dcmConnectionTimeout.set(OFstatic_cast(Sint32, opt_timeout)); + } + + if (cmd.findOption("--acse-timeout")) + { + OFCmdSignedInt opt_timeout = 0; + app.checkValue(cmd.getValueAndCheckMin(opt_timeout, 1)); + opt_acse_timeout = OFstatic_cast(int, opt_timeout); + } + + if (cmd.findOption("--dimse-timeout")) + { + OFCmdSignedInt opt_timeout = 0; + app.checkValue(cmd.getValueAndCheckMin(opt_timeout, 1)); + opt_dimse_timeout = OFstatic_cast(int, opt_timeout); + opt_blockMode = DIMSE_NONBLOCKING; + } + + cmd.beginOptionBlock(); + if (cmd.findOption("--port")) app.checkValue(cmd.getValueAndCheckMinMax(opt_retrievePort, 1, 65535)); + if (cmd.findOption("--no-port")) { /* do nothing */ } + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--pending-ignore")) opt_ignorePendingDatasets = OFTrue; + if (cmd.findOption("--pending-read")) opt_ignorePendingDatasets = OFFalse; + cmd.endOptionBlock(); + + if (cmd.findOption("--max-pdu")) app.checkValue(cmd.getValueAndCheckMinMax(opt_maxPDU, ASC_MINIMUMPDUSIZE, ASC_MAXIMUMPDUSIZE)); + if (cmd.findOption("--disable-host-lookup")) dcmDisableGethostbyaddr.set(OFTrue); + if (cmd.findOption("--repeat")) app.checkValue(cmd.getValueAndCheckMin(opt_repeatCount, 1)); + if (cmd.findOption("--abort")) opt_abortAssociation = OFTrue; + if (cmd.findOption("--ignore")) opt_ignore = OFTrue; + if (cmd.findOption("--cancel")) app.checkValue(cmd.getValueAndCheckMin(opt_cancelAfterNResponses, 0)); + if (cmd.findOption("--uid-padding")) opt_correctUIDPadding = OFTrue; + + if (cmd.findOption("--output-directory")) app.checkValue(cmd.getValue(opt_outputDirectory)); + + cmd.beginOptionBlock(); + if (cmd.findOption("--normal")) opt_bitPreserving = OFFalse; + if (cmd.findOption("--bit-preserving")) opt_bitPreserving = OFTrue; + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--write-file")) opt_useMetaheader = OFTrue; + if (cmd.findOption("--write-dataset")) opt_useMetaheader = OFFalse; + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--write-xfer-same")) opt_writeTransferSyntax = EXS_Unknown; + if (cmd.findOption("--write-xfer-little")) + { + app.checkConflict("--write-xfer-little", "--accept-all", opt_acceptAllXfers); + app.checkConflict("--write-xfer-little", "--bit-preserving", opt_bitPreserving); + app.checkConflict("--write-xfer-little", "--prefer-lossless", opt_in_networkTransferSyntax == EXS_JPEGProcess14SV1); + app.checkConflict("--write-xfer-little", "--prefer-jpeg8", opt_in_networkTransferSyntax == EXS_JPEGProcess1); + app.checkConflict("--write-xfer-little", "--prefer-jpeg12", opt_in_networkTransferSyntax == EXS_JPEGProcess2_4); + app.checkConflict("--write-xfer-little", "--prefer-j2k-lossless", opt_in_networkTransferSyntax == EXS_JPEG2000LosslessOnly); + app.checkConflict("--write-xfer-little", "--prefer-j2k-lossy", opt_in_networkTransferSyntax == EXS_JPEG2000); + app.checkConflict("--write-xfer-little", "--prefer-jls-lossless", opt_in_networkTransferSyntax == EXS_JPEGLSLossless); + app.checkConflict("--write-xfer-little", "--prefer-jls-lossy", opt_in_networkTransferSyntax == EXS_JPEGLSLossy); + app.checkConflict("--write-xfer-little", "--prefer-mpeg2", opt_in_networkTransferSyntax == EXS_MPEG2MainProfileAtMainLevel); + app.checkConflict("--write-xfer-little", "--prefer-mpeg2-high", opt_in_networkTransferSyntax == EXS_MPEG2MainProfileAtHighLevel); + app.checkConflict("--write-xfer-little", "--prefer-mpeg4", opt_in_networkTransferSyntax == EXS_MPEG4HighProfileLevel4_1); + app.checkConflict("--write-xfer-little", "--prefer-mpeg4-bd", opt_in_networkTransferSyntax == EXS_MPEG4BDcompatibleHighProfileLevel4_1); + app.checkConflict("--write-xfer-little", "--prefer-rle", opt_in_networkTransferSyntax == EXS_RLELossless); + // we don't have to check a conflict for --prefer-deflated because we can always convert that to uncompressed. + opt_writeTransferSyntax = EXS_LittleEndianExplicit; + } + if (cmd.findOption("--write-xfer-big")) + { + app.checkConflict("--write-xfer-big", "--accept-all", opt_acceptAllXfers); + app.checkConflict("--write-xfer-big", "--bit-preserving", opt_bitPreserving); + app.checkConflict("--write-xfer-big", "--prefer-lossless", opt_in_networkTransferSyntax == EXS_JPEGProcess14SV1); + app.checkConflict("--write-xfer-big", "--prefer-jpeg8", opt_in_networkTransferSyntax == EXS_JPEGProcess1); + app.checkConflict("--write-xfer-big", "--prefer-jpeg12", opt_in_networkTransferSyntax == EXS_JPEGProcess2_4); + app.checkConflict("--write-xfer-big", "--prefer-j2k-lossy", opt_in_networkTransferSyntax == EXS_JPEG2000); + app.checkConflict("--write-xfer-big", "--prefer-j2k-lossless", opt_in_networkTransferSyntax == EXS_JPEG2000LosslessOnly); + app.checkConflict("--write-xfer-big", "--prefer-jls-lossless", opt_in_networkTransferSyntax == EXS_JPEGLSLossless); + app.checkConflict("--write-xfer-big", "--prefer-jls-lossy", opt_in_networkTransferSyntax == EXS_JPEGLSLossy); + app.checkConflict("--write-xfer-big", "--prefer-mpeg2", opt_in_networkTransferSyntax == EXS_MPEG2MainProfileAtMainLevel); + app.checkConflict("--write-xfer-big", "--prefer-mpeg2-high", opt_in_networkTransferSyntax == EXS_MPEG2MainProfileAtHighLevel); + app.checkConflict("--write-xfer-big", "--prefer-mpeg4", opt_in_networkTransferSyntax == EXS_MPEG4HighProfileLevel4_1); + app.checkConflict("--write-xfer-big", "--prefer-mpeg4-bd", opt_in_networkTransferSyntax == EXS_MPEG4BDcompatibleHighProfileLevel4_1); + app.checkConflict("--write-xfer-big", "--prefer-rle", opt_in_networkTransferSyntax == EXS_RLELossless); + // we don't have to check a conflict for --prefer-deflated because we can always convert that to uncompressed. + opt_writeTransferSyntax = EXS_BigEndianExplicit; + } + if (cmd.findOption("--write-xfer-implicit")) + { + app.checkConflict("--write-xfer-implicit", "--accept-all", opt_acceptAllXfers); + app.checkConflict("--write-xfer-implicit", "--bit-preserving", opt_bitPreserving); + app.checkConflict("--write-xfer-implicit", "--prefer-lossless", opt_in_networkTransferSyntax == EXS_JPEGProcess14SV1); + app.checkConflict("--write-xfer-implicit", "--prefer-jpeg8", opt_in_networkTransferSyntax == EXS_JPEGProcess1); + app.checkConflict("--write-xfer-implicit", "--prefer-jpeg12", opt_in_networkTransferSyntax == EXS_JPEGProcess2_4); + app.checkConflict("--write-xfer-implicit", "--prefer-j2k-lossy", opt_in_networkTransferSyntax == EXS_JPEG2000); + app.checkConflict("--write-xfer-implicit", "--prefer-j2k-lossless", opt_in_networkTransferSyntax == EXS_JPEG2000LosslessOnly); + app.checkConflict("--write-xfer-implicit", "--prefer-jls-lossless", opt_in_networkTransferSyntax == EXS_JPEGLSLossless); + app.checkConflict("--write-xfer-implicit", "--prefer-jls-lossy", opt_in_networkTransferSyntax == EXS_JPEGLSLossy); + app.checkConflict("--write-xfer-implicit", "--prefer-mpeg2", opt_in_networkTransferSyntax == EXS_MPEG2MainProfileAtMainLevel); + app.checkConflict("--write-xfer-implicit", "--prefer-mpeg2-high", opt_in_networkTransferSyntax == EXS_MPEG2MainProfileAtHighLevel); + app.checkConflict("--write-xfer-implicit", "--prefer-mpeg4", opt_in_networkTransferSyntax == EXS_MPEG4HighProfileLevel4_1); + app.checkConflict("--write-xfer-implicit", "--prefer-mpeg4-bd", opt_in_networkTransferSyntax == EXS_MPEG4BDcompatibleHighProfileLevel4_1); + app.checkConflict("--write-xfer-implicit", "--prefer-rle", opt_in_networkTransferSyntax == EXS_RLELossless); + // we don't have to check a conflict for --prefer-deflated because we can always convert that to uncompressed. + opt_writeTransferSyntax = EXS_LittleEndianImplicit; + } +#ifdef WITH_ZLIB + if (cmd.findOption("--write-xfer-deflated")) + { + app.checkConflict("--write-xfer-deflated", "--accept-all", opt_acceptAllXfers); + app.checkConflict("--write-xfer-deflated", "--bit-preserving", opt_bitPreserving); + app.checkConflict("--write-xfer-deflated", "--prefer-lossless", opt_in_networkTransferSyntax == EXS_JPEGProcess14SV1); + app.checkConflict("--write-xfer-deflated", "--prefer-jpeg8", opt_in_networkTransferSyntax == EXS_JPEGProcess1); + app.checkConflict("--write-xfer-deflated", "--prefer-jpeg12", opt_in_networkTransferSyntax == EXS_JPEGProcess2_4); + app.checkConflict("--write-xfer-deflated", "--prefer-j2k-lossless", opt_in_networkTransferSyntax == EXS_JPEG2000LosslessOnly); + app.checkConflict("--write-xfer-deflated", "--prefer-j2k-lossy", opt_in_networkTransferSyntax == EXS_JPEG2000); + app.checkConflict("--write-xfer-deflated", "--prefer-jls-lossless", opt_in_networkTransferSyntax == EXS_JPEGLSLossless); + app.checkConflict("--write-xfer-deflated", "--prefer-jls-lossy", opt_in_networkTransferSyntax == EXS_JPEGLSLossy); + app.checkConflict("--write-xfer-deflated", "--prefer-mpeg2", opt_in_networkTransferSyntax == EXS_MPEG2MainProfileAtMainLevel); + app.checkConflict("--write-xfer-deflated", "--prefer-mpeg2-high", opt_in_networkTransferSyntax == EXS_MPEG2MainProfileAtHighLevel); + app.checkConflict("--write-xfer-deflated", "--prefer-mpeg4", opt_in_networkTransferSyntax == EXS_MPEG4HighProfileLevel4_1); + app.checkConflict("--write-xfer-deflated", "--prefer-mpeg4-bd", opt_in_networkTransferSyntax == EXS_MPEG4BDcompatibleHighProfileLevel4_1); + app.checkConflict("--write-xfer-deflated", "--prefer-rle", opt_in_networkTransferSyntax == EXS_RLELossless); + opt_writeTransferSyntax = EXS_DeflatedLittleEndianExplicit; + } +#endif + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--enable-new-vr")) + { + app.checkConflict("--enable-new-vr", "--bit-preserving", opt_bitPreserving); + dcmEnableGenerationOfNewVRs(); + } + if (cmd.findOption("--disable-new-vr")) + { + app.checkConflict("--disable-new-vr", "--bit-preserving", opt_bitPreserving); + dcmDisableGenerationOfNewVRs(); + } + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--group-length-recalc")) + { + app.checkConflict("--group-length-recalc", "--bit-preserving", opt_bitPreserving); + opt_groupLength = EGL_recalcGL; + } + if (cmd.findOption("--group-length-create")) + { + app.checkConflict("--group-length-create", "--bit-preserving", opt_bitPreserving); + opt_groupLength = EGL_withGL; + } + if (cmd.findOption("--group-length-remove")) + { + app.checkConflict("--group-length-remove", "--bit-preserving", opt_bitPreserving); + opt_groupLength = EGL_withoutGL; + } + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--length-explicit")) + { + app.checkConflict("--length-explicit", "--bit-preserving", opt_bitPreserving); + opt_sequenceType = EET_ExplicitLength; + } + if (cmd.findOption("--length-undefined")) + { + app.checkConflict("--length-undefined", "--bit-preserving", opt_bitPreserving); + opt_sequenceType = EET_UndefinedLength; + } + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--padding-off")) opt_paddingType = EPD_withoutPadding; + if (cmd.findOption("--padding-create")) + { + app.checkConflict("--padding-create", "--write-dataset", !opt_useMetaheader); + app.checkConflict("--padding-create", "--bit-preserving", opt_bitPreserving); + app.checkValue(cmd.getValueAndCheckMin(opt_filepad, 0)); + app.checkValue(cmd.getValueAndCheckMin(opt_itempad, 0)); + opt_paddingType = EPD_withPadding; + } + cmd.endOptionBlock(); + +#ifdef WITH_ZLIB + if (cmd.findOption("--compression-level")) + { + app.checkDependence("--compression-level", "--propose-deflated, --write-xfer-deflated or --write-xfer-same", + (opt_out_networkTransferSyntax == EXS_DeflatedLittleEndianExplicit) || + (opt_writeTransferSyntax == EXS_DeflatedLittleEndianExplicit) || + (opt_writeTransferSyntax == EXS_Unknown)); + app.checkValue(cmd.getValueAndCheckMinMax(opt_compressionLevel, 0, 9)); + dcmZlibCompressionLevel.set(OFstatic_cast(int, opt_compressionLevel)); + } +#endif + + /* finally parse filenames */ + int paramCount = cmd.getParamCount(); + const char *currentFilename = NULL; + OFString errormsg; + + for (int i=3; i <= paramCount; i++) + { + cmd.getParam(i, currentFilename); + if (access(currentFilename, R_OK) < 0) + { + errormsg = "cannot access file: "; + errormsg += currentFilename; + app.printError(errormsg.c_str()); + } + fileNameList.push_back(currentFilename); + } + + if ((fileNameList.empty()) && (overrideKeys == NULL)) + { + app.printError("either query file or override keys (or both) must be specified"); + } + } + + /* print resource identifier */ + OFLOG_DEBUG(movescuLogger, rcsid << OFendl); + + /* make sure data dictionary is loaded */ + if (!dcmDataDict.isDictionaryLoaded()) + { + OFLOG_WARN(movescuLogger, "no data dictionary loaded, check environment variable: " + << DCM_DICT_ENVIRONMENT_VARIABLE); + } + + /* make sure output directory exists and is writeable */ + if (opt_retrievePort > 0) + { + if (!OFStandard::dirExists(opt_outputDirectory)) + { + OFLOG_FATAL(movescuLogger, "specified output directory does not exist"); + return 1; + } + else if (!OFStandard::isWriteable(opt_outputDirectory)) + { + OFLOG_FATAL(movescuLogger, "specified output directory is not writeable"); + return 1; + } + } + +#ifndef DISABLE_PORT_PERMISSION_CHECK +#ifdef HAVE_GETEUID + /* if retrieve port is privileged we must be as well */ + if ((opt_retrievePort > 0) && (opt_retrievePort < 1024)) { + if (geteuid() != 0) + { + OFLOG_FATAL(movescuLogger, "cannot listen on port " << opt_retrievePort << ", insufficient privileges"); + return 1; + } + } +#endif +#endif + + /* network for move request and responses */ + T_ASC_NetworkRole role = (opt_retrievePort > 0) ? NET_ACCEPTORREQUESTOR : NET_REQUESTOR; + OFCondition cond = ASC_initializeNetwork(role, OFstatic_cast(int, opt_retrievePort), opt_acse_timeout, &net); + if (cond.bad()) + { + OFLOG_FATAL(movescuLogger, "cannot create network: " << DimseCondition::dump(temp_str, cond)); + return 1; + } + + /* drop root privileges now and revert to the calling user id (if we are running as setuid root) */ + if (OFStandard::dropPrivileges().bad()) + { + OFLOG_FATAL(movescuLogger, "setuid() failed, maximum number of processes/threads for uid already running."); + return 1; + } + + /* set up main association */ + cond = ASC_createAssociationParameters(¶ms, opt_maxPDU); + if (cond.bad()) { + OFLOG_FATAL(movescuLogger, DimseCondition::dump(temp_str, cond)); + exit(1); + } + ASC_setAPTitles(params, opt_ourTitle, opt_peerTitle, NULL); + + gethostname(localHost, sizeof(localHost) - 1); + sprintf(peerHost, "%s:%d", opt_peer, OFstatic_cast(int, opt_port)); + ASC_setPresentationAddresses(params, localHost, peerHost); + + /* + * We also add a presentation context for the corresponding + * find sop class. + */ + cond = addPresentationContext(params, 1, + querySyntax[opt_queryModel].findSyntax); + + cond = addPresentationContext(params, 3, + querySyntax[opt_queryModel].moveSyntax); + if (cond.bad()) { + OFLOG_FATAL(movescuLogger, DimseCondition::dump(temp_str, cond)); + exit(1); + } + + OFLOG_DEBUG(movescuLogger, "Request Parameters:" << OFendl << ASC_dumpParameters(temp_str, params, ASC_ASSOC_RQ)); + + /* create association */ + OFLOG_INFO(movescuLogger, "Requesting Association"); + cond = ASC_requestAssociation(net, params, &assoc); + if (cond.bad()) { + if (cond == DUL_ASSOCIATIONREJECTED) { + T_ASC_RejectParameters rej; + + ASC_getRejectParameters(params, &rej); + OFLOG_FATAL(movescuLogger, "Association Rejected:"); + OFLOG_FATAL(movescuLogger, ASC_printRejectParameters(temp_str, &rej)); + exit(1); + } else { + OFLOG_FATAL(movescuLogger, "Association Request Failed:"); + OFLOG_FATAL(movescuLogger, DimseCondition::dump(temp_str, cond)); + exit(1); + } + } + /* what has been accepted/refused ? */ + OFLOG_DEBUG(movescuLogger, "Association Parameters Negotiated:" << OFendl << ASC_dumpParameters(temp_str, params, ASC_ASSOC_AC)); + + if (ASC_countAcceptedPresentationContexts(params) == 0) { + OFLOG_FATAL(movescuLogger, "No Acceptable Presentation Contexts"); + exit(1); + } + + OFLOG_INFO(movescuLogger, "Association Accepted (Max Send PDV: " << assoc->sendPDVLength << ")"); + + /* do the real work */ + cond = EC_Normal; + if (fileNameList.empty()) + { + /* no files provided on command line */ + cond = cmove(assoc, NULL); + } else { + OFListIterator(OFString) iter = fileNameList.begin(); + OFListIterator(OFString) enditer = fileNameList.end(); + while ((iter != enditer) && cond.good()) + { + cond = cmove(assoc, (*iter).c_str()); + ++iter; + } + } + + /* tear down association */ + if (cond == EC_Normal) + { + if (opt_abortAssociation) { + OFLOG_INFO(movescuLogger, "Aborting Association"); + cond = ASC_abortAssociation(assoc); + if (cond.bad()) { + OFLOG_FATAL(movescuLogger, "Association Abort Failed: " << DimseCondition::dump(temp_str, cond)); + exit(1); + } + } else { + /* release association */ + OFLOG_INFO(movescuLogger, "Releasing Association"); + cond = ASC_releaseAssociation(assoc); + if (cond.bad()) + { + OFLOG_FATAL(movescuLogger, "Association Release Failed:"); + OFLOG_FATAL(movescuLogger, DimseCondition::dump(temp_str, cond)); + exit(1); + } + } + } + else if (cond == DUL_PEERREQUESTEDRELEASE) + { + OFLOG_ERROR(movescuLogger, "Protocol Error: Peer requested release (Aborting)"); + OFLOG_INFO(movescuLogger, "Aborting Association"); + cond = ASC_abortAssociation(assoc); + if (cond.bad()) { + OFLOG_FATAL(movescuLogger, "Association Abort Failed: " << DimseCondition::dump(temp_str, cond)); + exit(1); + } + } + else if (cond == DUL_PEERABORTEDASSOCIATION) + { + OFLOG_INFO(movescuLogger, "Peer Aborted Association"); + } + else + { + OFLOG_ERROR(movescuLogger, "Move SCU Failed: " << DimseCondition::dump(temp_str, cond)); + OFLOG_INFO(movescuLogger, "Aborting Association"); + cond = ASC_abortAssociation(assoc); + if (cond.bad()) { + OFLOG_FATAL(movescuLogger, "Association Abort Failed: " << DimseCondition::dump(temp_str, cond)); + exit(1); + } + } + + cond = ASC_destroyAssociation(&assoc); + if (cond.bad()) { + OFLOG_FATAL(movescuLogger, DimseCondition::dump(temp_str, cond)); + exit(1); + } + cond = ASC_dropNetwork(&net); + if (cond.bad()) { + OFLOG_FATAL(movescuLogger, DimseCondition::dump(temp_str, cond)); + exit(1); + } + +#ifdef HAVE_WINSOCK_H + WSACleanup(); +#endif + + return 0; +} + + +static OFCondition +addPresentationContext(T_ASC_Parameters *params, + T_ASC_PresentationContextID pid, + const char *abstractSyntax) +{ + /* + ** We prefer to use Explicitly encoded transfer syntaxes. + ** If we are running on a Little Endian machine we prefer + ** LittleEndianExplicitTransferSyntax to BigEndianTransferSyntax. + ** Some SCP implementations will just select the first transfer + ** syntax they support (this is not part of the standard) so + ** organize the proposed transfer syntaxes to take advantage + ** of such behavior. + ** + ** The presentation contexts proposed here are only used for + ** C-FIND and C-MOVE, so there is no need to support compressed + ** transmission. + */ + + const char *transferSyntaxes[] = { NULL, NULL, NULL, NULL }; + int numTransferSyntaxes = 0; + + switch (opt_out_networkTransferSyntax) { + case EXS_LittleEndianImplicit: + /* we only support Little Endian Implicit */ + transferSyntaxes[0] = UID_LittleEndianImplicitTransferSyntax; + numTransferSyntaxes = 1; + break; + case EXS_LittleEndianExplicit: + /* we prefer Little Endian Explicit */ + transferSyntaxes[0] = UID_LittleEndianExplicitTransferSyntax; + transferSyntaxes[1] = UID_BigEndianExplicitTransferSyntax; + transferSyntaxes[2] = UID_LittleEndianImplicitTransferSyntax; + numTransferSyntaxes = 3; + break; + case EXS_BigEndianExplicit: + /* we prefer Big Endian Explicit */ + transferSyntaxes[0] = UID_BigEndianExplicitTransferSyntax; + transferSyntaxes[1] = UID_LittleEndianExplicitTransferSyntax; + transferSyntaxes[2] = UID_LittleEndianImplicitTransferSyntax; + numTransferSyntaxes = 3; + break; +#ifdef WITH_ZLIB + case EXS_DeflatedLittleEndianExplicit: + /* we prefer Deflated Little Endian Explicit */ + transferSyntaxes[0] = UID_DeflatedExplicitVRLittleEndianTransferSyntax; + transferSyntaxes[1] = UID_LittleEndianExplicitTransferSyntax; + transferSyntaxes[2] = UID_BigEndianExplicitTransferSyntax; + transferSyntaxes[3] = UID_LittleEndianImplicitTransferSyntax; + numTransferSyntaxes = 4; + break; +#endif + default: + /* We prefer explicit transfer syntaxes. + * If we are running on a Little Endian machine we prefer + * LittleEndianExplicitTransferSyntax to BigEndianTransferSyntax. + */ + if (gLocalByteOrder == EBO_LittleEndian) /* defined in dcxfer.h */ + { + transferSyntaxes[0] = UID_LittleEndianExplicitTransferSyntax; + transferSyntaxes[1] = UID_BigEndianExplicitTransferSyntax; + } else { + transferSyntaxes[0] = UID_BigEndianExplicitTransferSyntax; + transferSyntaxes[1] = UID_LittleEndianExplicitTransferSyntax; + } + transferSyntaxes[2] = UID_LittleEndianImplicitTransferSyntax; + numTransferSyntaxes = 3; + break; + } + + return ASC_addPresentationContext( + params, pid, abstractSyntax, + transferSyntaxes, numTransferSyntaxes); +} + +static OFCondition +acceptSubAssoc(T_ASC_Network *aNet, T_ASC_Association **assoc) +{ + const char *knownAbstractSyntaxes[] = { + UID_VerificationSOPClass + }; + const char *transferSyntaxes[] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; + int numTransferSyntaxes; + OFString temp_str; + + OFCondition cond = ASC_receiveAssociation(aNet, assoc, opt_maxPDU); + if (cond.good()) + { + OFLOG_INFO(movescuLogger, "Sub-Association Received"); + OFLOG_DEBUG(movescuLogger, "Parameters:" << OFendl << ASC_dumpParameters(temp_str, (*assoc)->params, ASC_ASSOC_RQ)); + + switch (opt_in_networkTransferSyntax) + { + case EXS_LittleEndianImplicit: + /* we only support Little Endian Implicit */ + transferSyntaxes[0] = UID_LittleEndianImplicitTransferSyntax; + numTransferSyntaxes = 1; + break; + case EXS_LittleEndianExplicit: + /* we prefer Little Endian Explicit */ + transferSyntaxes[0] = UID_LittleEndianExplicitTransferSyntax; + transferSyntaxes[1] = UID_BigEndianExplicitTransferSyntax; + transferSyntaxes[2] = UID_LittleEndianImplicitTransferSyntax; + numTransferSyntaxes = 3; + break; + case EXS_BigEndianExplicit: + /* we prefer Big Endian Explicit */ + transferSyntaxes[0] = UID_BigEndianExplicitTransferSyntax; + transferSyntaxes[1] = UID_LittleEndianExplicitTransferSyntax; + transferSyntaxes[2] = UID_LittleEndianImplicitTransferSyntax; + numTransferSyntaxes = 3; + break; + case EXS_JPEGProcess14SV1: + /* we prefer JPEGLossless:Hierarchical-1stOrderPrediction (default lossless) */ + transferSyntaxes[0] = UID_JPEGProcess14SV1TransferSyntax; + transferSyntaxes[1] = UID_LittleEndianExplicitTransferSyntax; + transferSyntaxes[2] = UID_BigEndianExplicitTransferSyntax; + transferSyntaxes[3] = UID_LittleEndianImplicitTransferSyntax; + numTransferSyntaxes = 4; + break; + case EXS_JPEGProcess1: + /* we prefer JPEGBaseline (default lossy for 8 bit images) */ + transferSyntaxes[0] = UID_JPEGProcess1TransferSyntax; + transferSyntaxes[1] = UID_LittleEndianExplicitTransferSyntax; + transferSyntaxes[2] = UID_BigEndianExplicitTransferSyntax; + transferSyntaxes[3] = UID_LittleEndianImplicitTransferSyntax; + numTransferSyntaxes = 4; + break; + case EXS_JPEGProcess2_4: + /* we prefer JPEGExtended (default lossy for 12 bit images) */ + transferSyntaxes[0] = UID_JPEGProcess2_4TransferSyntax; + transferSyntaxes[1] = UID_LittleEndianExplicitTransferSyntax; + transferSyntaxes[2] = UID_BigEndianExplicitTransferSyntax; + transferSyntaxes[3] = UID_LittleEndianImplicitTransferSyntax; + numTransferSyntaxes = 4; + break; + case EXS_JPEG2000LosslessOnly: + /* we prefer JPEG2000 Lossless */ + transferSyntaxes[0] = UID_JPEG2000LosslessOnlyTransferSyntax; + transferSyntaxes[1] = UID_LittleEndianExplicitTransferSyntax; + transferSyntaxes[2] = UID_BigEndianExplicitTransferSyntax; + transferSyntaxes[3] = UID_LittleEndianImplicitTransferSyntax; + numTransferSyntaxes = 4; + break; + case EXS_JPEG2000: + /* we prefer JPEG2000 Lossy */ + transferSyntaxes[0] = UID_JPEG2000TransferSyntax; + transferSyntaxes[1] = UID_LittleEndianExplicitTransferSyntax; + transferSyntaxes[2] = UID_BigEndianExplicitTransferSyntax; + transferSyntaxes[3] = UID_LittleEndianImplicitTransferSyntax; + numTransferSyntaxes = 4; + break; + case EXS_JPEGLSLossless: + /* we prefer JPEG-LS Lossless */ + transferSyntaxes[0] = UID_JPEGLSLosslessTransferSyntax; + transferSyntaxes[1] = UID_LittleEndianExplicitTransferSyntax; + transferSyntaxes[2] = UID_BigEndianExplicitTransferSyntax; + transferSyntaxes[3] = UID_LittleEndianImplicitTransferSyntax; + numTransferSyntaxes = 4; + break; + case EXS_JPEGLSLossy: + /* we prefer JPEG-LS Lossy */ + transferSyntaxes[0] = UID_JPEGLSLossyTransferSyntax; + transferSyntaxes[1] = UID_LittleEndianExplicitTransferSyntax; + transferSyntaxes[2] = UID_BigEndianExplicitTransferSyntax; + transferSyntaxes[3] = UID_LittleEndianImplicitTransferSyntax; + numTransferSyntaxes = 4; + break; + case EXS_MPEG2MainProfileAtMainLevel: + /* we prefer MPEG2 MP@ML */ + transferSyntaxes[0] = UID_MPEG2MainProfileAtMainLevelTransferSyntax; + transferSyntaxes[1] = UID_LittleEndianExplicitTransferSyntax; + transferSyntaxes[2] = UID_BigEndianExplicitTransferSyntax; + transferSyntaxes[3] = UID_LittleEndianImplicitTransferSyntax; + numTransferSyntaxes = 4; + break; + case EXS_MPEG2MainProfileAtHighLevel: + /* we prefer MPEG2 MP@HL */ + transferSyntaxes[0] = UID_MPEG2MainProfileAtHighLevelTransferSyntax; + transferSyntaxes[1] = UID_LittleEndianExplicitTransferSyntax; + transferSyntaxes[2] = UID_BigEndianExplicitTransferSyntax; + transferSyntaxes[3] = UID_LittleEndianImplicitTransferSyntax; + numTransferSyntaxes = 4; + break; + case EXS_MPEG4HighProfileLevel4_1: + /* we prefer MPEG4 HP/L4.1 */ + transferSyntaxes[0] = UID_MPEG4HighProfileLevel4_1TransferSyntax; + transferSyntaxes[1] = UID_LittleEndianExplicitTransferSyntax; + transferSyntaxes[2] = UID_BigEndianExplicitTransferSyntax; + transferSyntaxes[3] = UID_LittleEndianImplicitTransferSyntax; + numTransferSyntaxes = 4; + break; + case EXS_MPEG4BDcompatibleHighProfileLevel4_1: + /* we prefer MPEG4 BD HP/L4.1 */ + transferSyntaxes[0] = UID_MPEG4BDcompatibleHighProfileLevel4_1TransferSyntax; + transferSyntaxes[1] = UID_LittleEndianExplicitTransferSyntax; + transferSyntaxes[2] = UID_BigEndianExplicitTransferSyntax; + transferSyntaxes[3] = UID_LittleEndianImplicitTransferSyntax; + numTransferSyntaxes = 4; + break; + case EXS_RLELossless: + /* we prefer RLE Lossless */ + transferSyntaxes[0] = UID_RLELosslessTransferSyntax; + transferSyntaxes[1] = UID_LittleEndianExplicitTransferSyntax; + transferSyntaxes[2] = UID_BigEndianExplicitTransferSyntax; + transferSyntaxes[3] = UID_LittleEndianImplicitTransferSyntax; + numTransferSyntaxes = 4; + break; +#ifdef WITH_ZLIB + case EXS_DeflatedLittleEndianExplicit: + /* we prefer Deflated Explicit VR Little Endian */ + transferSyntaxes[0] = UID_DeflatedExplicitVRLittleEndianTransferSyntax; + transferSyntaxes[1] = UID_LittleEndianExplicitTransferSyntax; + transferSyntaxes[2] = UID_BigEndianExplicitTransferSyntax; + transferSyntaxes[3] = UID_LittleEndianImplicitTransferSyntax; + numTransferSyntaxes = 4; + break; +#endif + default: + if (opt_acceptAllXfers) + { + /* we accept all supported transfer syntaxes + * (similar to "AnyTransferSyntax" in "storescp.cfg") + */ + transferSyntaxes[0] = UID_JPEG2000TransferSyntax; + transferSyntaxes[1] = UID_JPEG2000LosslessOnlyTransferSyntax; + transferSyntaxes[2] = UID_JPEGProcess2_4TransferSyntax; + transferSyntaxes[3] = UID_JPEGProcess1TransferSyntax; + transferSyntaxes[4] = UID_JPEGProcess14SV1TransferSyntax; + transferSyntaxes[5] = UID_JPEGLSLossyTransferSyntax; + transferSyntaxes[6] = UID_JPEGLSLosslessTransferSyntax; + transferSyntaxes[7] = UID_RLELosslessTransferSyntax; + transferSyntaxes[8] = UID_MPEG2MainProfileAtMainLevelTransferSyntax; + transferSyntaxes[9] = UID_MPEG2MainProfileAtHighLevelTransferSyntax; + transferSyntaxes[10] = UID_MPEG4HighProfileLevel4_1TransferSyntax; + transferSyntaxes[11] = UID_MPEG4BDcompatibleHighProfileLevel4_1TransferSyntax; + transferSyntaxes[12] = UID_DeflatedExplicitVRLittleEndianTransferSyntax; + if (gLocalByteOrder == EBO_LittleEndian) + { + transferSyntaxes[13] = UID_LittleEndianExplicitTransferSyntax; + transferSyntaxes[14] = UID_BigEndianExplicitTransferSyntax; + } else { + transferSyntaxes[13] = UID_BigEndianExplicitTransferSyntax; + transferSyntaxes[14] = UID_LittleEndianExplicitTransferSyntax; + } + transferSyntaxes[15] = UID_LittleEndianImplicitTransferSyntax; + numTransferSyntaxes = 16; + } else { + /* We prefer explicit transfer syntaxes. + * If we are running on a Little Endian machine we prefer + * LittleEndianExplicitTransferSyntax to BigEndianTransferSyntax. + */ + if (gLocalByteOrder == EBO_LittleEndian) /* defined in dcxfer.h */ + { + transferSyntaxes[0] = UID_LittleEndianExplicitTransferSyntax; + transferSyntaxes[1] = UID_BigEndianExplicitTransferSyntax; + } else { + transferSyntaxes[0] = UID_BigEndianExplicitTransferSyntax; + transferSyntaxes[1] = UID_LittleEndianExplicitTransferSyntax; + } + transferSyntaxes[2] = UID_LittleEndianImplicitTransferSyntax; + numTransferSyntaxes = 3; + } + break; + + } + + /* accept the Verification SOP Class if presented */ + cond = ASC_acceptContextsWithPreferredTransferSyntaxes( + (*assoc)->params, + knownAbstractSyntaxes, DIM_OF(knownAbstractSyntaxes), + transferSyntaxes, numTransferSyntaxes); + + if (cond.good()) + { + /* the array of Storage SOP Class UIDs comes from dcuid.h */ + cond = ASC_acceptContextsWithPreferredTransferSyntaxes( + (*assoc)->params, + dcmAllStorageSOPClassUIDs, numberOfAllDcmStorageSOPClassUIDs, + transferSyntaxes, numTransferSyntaxes); + } + } + if (cond.good()) + cond = ASC_acknowledgeAssociation(*assoc); + if (cond.good()) + { + OFLOG_INFO(movescuLogger, "Sub-Association Acknowledged (Max Send PDV: " << (*assoc)->sendPDVLength << ")"); + if (ASC_countAcceptedPresentationContexts((*assoc)->params) == 0) + OFLOG_INFO(movescuLogger, " (but no valid presentation contexts)"); + /* dump the presentation contexts which have been accepted/refused */ + OFLOG_DEBUG(movescuLogger, ASC_dumpParameters(temp_str, (*assoc)->params, ASC_ASSOC_AC)); + } else { + OFLOG_ERROR(movescuLogger, DimseCondition::dump(temp_str, cond)); + ASC_dropAssociation(*assoc); + ASC_destroyAssociation(assoc); + } + return cond; +} + +static OFCondition echoSCP( + T_ASC_Association *assoc, + T_DIMSE_Message *msg, + T_ASC_PresentationContextID presID) +{ + OFString temp_str; + // assign the actual information of the C-Echo-RQ command to a local variable + T_DIMSE_C_EchoRQ *req = &msg->msg.CEchoRQ; + if (movescuLogger.isEnabledFor(OFLogger::DEBUG_LOG_LEVEL)) + { + OFLOG_INFO(movescuLogger, "Received Echo Request"); + OFLOG_DEBUG(movescuLogger, DIMSE_dumpMessage(temp_str, *req, DIMSE_INCOMING, NULL, presID)); + } else { + OFLOG_INFO(movescuLogger, "Received Echo Request (MsgID " << req->MessageID << ")"); + } + + /* the echo succeeded !! */ + OFCondition cond = DIMSE_sendEchoResponse(assoc, presID, req, STATUS_Success, NULL); + if (cond.bad()) + { + OFLOG_ERROR(movescuLogger, "Echo SCP Failed: " << DimseCondition::dump(temp_str, cond)); + } + return cond; +} + +struct StoreCallbackData +{ + char *imageFileName; + DcmFileFormat *dcmff; + T_ASC_Association *assoc; +}; + +static void +storeSCPCallback( + /* in */ + void *callbackData, + T_DIMSE_StoreProgress *progress, /* progress state */ + T_DIMSE_C_StoreRQ *req, /* original store request */ + char *imageFileName, DcmDataset **imageDataSet, /* being received into */ + /* out */ + T_DIMSE_C_StoreRSP *rsp, /* final store response */ + DcmDataset **statusDetail) +{ + DIC_UI sopClass; + DIC_UI sopInstance; + + if ((opt_abortDuringStore && progress->state != DIMSE_StoreBegin) || + (opt_abortAfterStore && progress->state == DIMSE_StoreEnd)) { + OFLOG_INFO(movescuLogger, "ABORT initiated (due to command line options)"); + ASC_abortAssociation(OFstatic_cast(StoreCallbackData*, callbackData)->assoc); + rsp->DimseStatus = STATUS_STORE_Refused_OutOfResources; + return; + } + + if (opt_sleepDuring > 0) + { + OFStandard::sleep(OFstatic_cast(unsigned int, opt_sleepDuring)); + } + + // dump some information if required (depending on the progress state) + // We can't use oflog for the pdu output, but we use a special logger for + // generating this output. If it is set to level "INFO" we generate the + // output, if it's set to "DEBUG" then we'll assume that there is debug output + // generated for each PDU elsewhere. + OFLogger progressLogger = OFLog::getLogger("dcmtk.apps." OFFIS_CONSOLE_APPLICATION ".progress"); + if (progressLogger.getChainedLogLevel() == OFLogger::INFO_LOG_LEVEL) + { + switch (progress->state) + { + case DIMSE_StoreBegin: + COUT << "RECV: "; + break; + case DIMSE_StoreEnd: + COUT << OFendl; + break; + default: + COUT << '.'; + break; + } + COUT.flush(); + } + + if (progress->state == DIMSE_StoreEnd) + { + *statusDetail = NULL; /* no status detail */ + + /* could save the image somewhere else, put it in database, etc */ + /* + * An appropriate status code is already set in the resp structure, it need not be success. + * For example, if the caller has already detected an out of resources problem then the + * status will reflect this. The callback function is still called to allow cleanup. + */ + // rsp->DimseStatus = STATUS_Success; + + if ((imageDataSet != NULL) && (*imageDataSet != NULL) && !opt_bitPreserving && !opt_ignore) + { + StoreCallbackData *cbdata = OFstatic_cast(StoreCallbackData*, callbackData); + /* create full path name for the output file */ + OFString ofname; + OFStandard::combineDirAndFilename(ofname, opt_outputDirectory, cbdata->imageFileName, OFTrue /* allowEmptyDirName */); + + E_TransferSyntax xfer = opt_writeTransferSyntax; + if (xfer == EXS_Unknown) xfer = (*imageDataSet)->getOriginalXfer(); + + OFCondition cond = cbdata->dcmff->saveFile(ofname.c_str(), xfer, opt_sequenceType, opt_groupLength, + opt_paddingType, OFstatic_cast(Uint32, opt_filepad), OFstatic_cast(Uint32, opt_itempad), + (opt_useMetaheader) ? EWM_fileformat : EWM_dataset); + if (cond.bad()) + { + OFLOG_ERROR(movescuLogger, "cannot write DICOM file: " << ofname); + rsp->DimseStatus = STATUS_STORE_Refused_OutOfResources; + } + + /* should really check the image to make sure it is consistent, + * that its sopClass and sopInstance correspond with those in + * the request. + */ + if ((rsp->DimseStatus == STATUS_Success) && !opt_ignore) + { + /* which SOP class and SOP instance ? */ + if (!DU_findSOPClassAndInstanceInDataSet(*imageDataSet, sopClass, sopInstance, opt_correctUIDPadding)) + { + OFLOG_FATAL(movescuLogger, "bad DICOM file: " << imageFileName); + rsp->DimseStatus = STATUS_STORE_Error_CannotUnderstand; + } + else if (strcmp(sopClass, req->AffectedSOPClassUID) != 0) + { + rsp->DimseStatus = STATUS_STORE_Error_DataSetDoesNotMatchSOPClass; + } + else if (strcmp(sopInstance, req->AffectedSOPInstanceUID) != 0) + { + rsp->DimseStatus = STATUS_STORE_Error_DataSetDoesNotMatchSOPClass; + } + } + } + } +} + +static OFCondition storeSCP( + T_ASC_Association *assoc, + T_DIMSE_Message *msg, + T_ASC_PresentationContextID presID) +{ + OFCondition cond = EC_Normal; + T_DIMSE_C_StoreRQ *req; + char imageFileName[2048]; + + req = &msg->msg.CStoreRQ; + + if (opt_ignore) + { +#ifdef _WIN32 + tmpnam(imageFileName); +#else + strcpy(imageFileName, NULL_DEVICE_NAME); +#endif + } else { + sprintf(imageFileName, "%s.%s", + dcmSOPClassUIDToModality(req->AffectedSOPClassUID), + req->AffectedSOPInstanceUID); + } + + OFString temp_str; + if (movescuLogger.isEnabledFor(OFLogger::DEBUG_LOG_LEVEL)) + { + OFLOG_INFO(movescuLogger, "Received Store Request"); + OFLOG_DEBUG(movescuLogger, DIMSE_dumpMessage(temp_str, *req, DIMSE_INCOMING, NULL, presID)); + } else { + OFLOG_INFO(movescuLogger, "Received Store Request (MsgID " << req->MessageID << ", " + << dcmSOPClassUIDToModality(req->AffectedSOPClassUID, "OT") << ")"); + } + + StoreCallbackData callbackData; + callbackData.assoc = assoc; + callbackData.imageFileName = imageFileName; + DcmFileFormat dcmff; + callbackData.dcmff = &dcmff; + + // store SourceApplicationEntityTitle in metaheader + if (assoc && assoc->params) + { + const char *aet = assoc->params->DULparams.callingAPTitle; + if (aet) dcmff.getMetaInfo()->putAndInsertString(DCM_SourceApplicationEntityTitle, aet); + } + + DcmDataset *dset = dcmff.getDataset(); + + if (opt_bitPreserving) + { + cond = DIMSE_storeProvider(assoc, presID, req, imageFileName, opt_useMetaheader, + NULL, storeSCPCallback, OFreinterpret_cast(void*, &callbackData), opt_blockMode, opt_dimse_timeout); + } else { + cond = DIMSE_storeProvider(assoc, presID, req, NULL, opt_useMetaheader, + &dset, storeSCPCallback, OFreinterpret_cast(void*, &callbackData), opt_blockMode, opt_dimse_timeout); + } + + if (cond.bad()) + { + OFLOG_ERROR(movescuLogger, "Store SCP Failed: " << DimseCondition::dump(temp_str, cond)); + /* remove file */ + if (!opt_ignore) + { + if (strcmp(imageFileName, NULL_DEVICE_NAME) != 0) unlink(imageFileName); + } +#ifdef _WIN32 + } else if (opt_ignore) { + if (strcmp(imageFileName, NULL_DEVICE_NAME) != 0) unlink(imageFileName); // delete the temporary file +#endif + } + + if (opt_sleepAfter > 0) + { + OFStandard::sleep(OFstatic_cast(unsigned int, opt_sleepDuring)); + } + return cond; +} + +static OFCondition +subOpSCP(T_ASC_Association **subAssoc) +{ + T_DIMSE_Message msg; + T_ASC_PresentationContextID presID; + + if (!ASC_dataWaiting(*subAssoc, 0)) /* just in case */ + return DIMSE_NODATAAVAILABLE; + + OFCondition cond = DIMSE_receiveCommand(*subAssoc, opt_blockMode, opt_dimse_timeout, &presID, &msg, NULL); + + if (cond == EC_Normal) { + switch (msg.CommandField) + { + case DIMSE_C_ECHO_RQ: + // process C-ECHO-Request + cond = echoSCP(*subAssoc, &msg, presID); + break; + case DIMSE_C_STORE_RQ: + // process C-STORE-Request + cond = storeSCP(*subAssoc, &msg, presID); + break; + default: + OFString tempStr; + // we cannot handle this kind of message + cond = DIMSE_BADCOMMANDTYPE; + OFLOG_ERROR(movescuLogger, "Expected C-ECHO or C-STORE request but received DIMSE command 0x" + << STD_NAMESPACE hex << STD_NAMESPACE setfill('0') << STD_NAMESPACE setw(4) + << OFstatic_cast(unsigned, msg.CommandField)); + OFLOG_DEBUG(movescuLogger, DIMSE_dumpMessage(tempStr, msg, DIMSE_INCOMING, NULL, presID)); + break; + } + } + /* clean up on association termination */ + if (cond == DUL_PEERREQUESTEDRELEASE) + { + cond = ASC_acknowledgeRelease(*subAssoc); + ASC_dropSCPAssociation(*subAssoc); + ASC_destroyAssociation(subAssoc); + return cond; + } + else if (cond == DUL_PEERABORTEDASSOCIATION) + { + } + else if (cond != EC_Normal) + { + OFString temp_str; + OFLOG_ERROR(movescuLogger, "DIMSE failure (aborting sub-association): " << DimseCondition::dump(temp_str, cond)); + /* some kind of error so abort the association */ + cond = ASC_abortAssociation(*subAssoc); + } + + if (cond != EC_Normal) + { + ASC_dropAssociation(*subAssoc); + ASC_destroyAssociation(subAssoc); + } + return cond; +} + +static void +subOpCallback(void * /*subOpCallbackData*/ , + T_ASC_Network *aNet, T_ASC_Association **subAssoc) +{ + + if (aNet == NULL) return; /* help no net ! */ + + if (*subAssoc == NULL) { + /* negotiate association */ + acceptSubAssoc(aNet, subAssoc); + } else { + /* be a service class provider */ + subOpSCP(subAssoc); + } +} + +static void +moveCallback(void *callbackData, T_DIMSE_C_MoveRQ *request, + int responseCount, T_DIMSE_C_MoveRSP *response) +{ + OFCondition cond = EC_Normal; + MyCallbackInfo *myCallbackData; + OFString temp_str; + + myCallbackData = OFstatic_cast(MyCallbackInfo*, callbackData); + + if (movescuLogger.isEnabledFor(OFLogger::DEBUG_LOG_LEVEL)) { + OFLOG_INFO(movescuLogger, "Received Move Response " << responseCount); + OFLOG_DEBUG(movescuLogger, DIMSE_dumpMessage(temp_str, *response, DIMSE_INCOMING)); + } else { + OFLOG_INFO(movescuLogger, "Received Move Response " << responseCount << " (" + << DU_cmoveStatusString(response->DimseStatus) << ")"); + } + + /* should we send a cancel back ?? */ + if (opt_cancelAfterNResponses == responseCount) { + OFLOG_INFO(movescuLogger, "Sending Cancel Request (MsgID " << request->MessageID + << ", PresID " << OFstatic_cast(unsigned int, myCallbackData->presId) << ")"); + cond = DIMSE_sendCancelRequest(myCallbackData->assoc, + myCallbackData->presId, request->MessageID); + if (cond != EC_Normal) { + OFLOG_ERROR(movescuLogger, "Cancel Request Failed: " << DimseCondition::dump(temp_str, cond)); + } + } +} + + +static void +substituteOverrideKeys(DcmDataset *dset) +{ + if (overrideKeys == NULL) { + return; /* nothing to do */ + } + + /* copy the override keys */ + DcmDataset keys(*overrideKeys); + + /* put the override keys into dset replacing existing tags */ + unsigned long elemCount = keys.card(); + for (unsigned long i = 0; i < elemCount; i++) { + DcmElement *elem = keys.remove(OFstatic_cast(unsigned long, 0)); + + dset->insert(elem, OFTrue); + } +} + + +static OFCondition +moveSCU(T_ASC_Association *assoc, const char *fname) +{ + T_ASC_PresentationContextID presId; + T_DIMSE_C_MoveRQ req; + T_DIMSE_C_MoveRSP rsp; + DIC_US msgId = assoc->nextMsgID++; + DcmDataset *rspIds = NULL; + const char *sopClass; + DcmDataset *statusDetail = NULL; + MyCallbackInfo callbackData; + OFString temp_str; + + DcmFileFormat dcmff; + + if (fname != NULL) { + if (dcmff.loadFile(fname).bad()) { + OFLOG_ERROR(movescuLogger, "bad DICOM file: " << fname << ": " << dcmff.error().text()); + return DIMSE_BADDATA; + } + } + + /* replace specific keys by those in overrideKeys */ + substituteOverrideKeys(dcmff.getDataset()); + + sopClass = querySyntax[opt_queryModel].moveSyntax; + + /* which presentation context should be used */ + presId = ASC_findAcceptedPresentationContextID(assoc, sopClass); + if (presId == 0) return DIMSE_NOVALIDPRESENTATIONCONTEXTID; + + callbackData.assoc = assoc; + callbackData.presId = presId; + + req.MessageID = msgId; + strcpy(req.AffectedSOPClassUID, sopClass); + req.Priority = DIMSE_PRIORITY_MEDIUM; + req.DataSetType = DIMSE_DATASET_PRESENT; + if (opt_moveDestination == NULL) { + /* set the destination to be me */ + ASC_getAPTitles(assoc->params, req.MoveDestination, NULL, NULL); + } else { + strcpy(req.MoveDestination, opt_moveDestination); + } + + if (movescuLogger.isEnabledFor(OFLogger::DEBUG_LOG_LEVEL)) + { + OFLOG_INFO(movescuLogger, "Sending Move Request"); + OFLOG_DEBUG(movescuLogger, DIMSE_dumpMessage(temp_str, req, DIMSE_OUTGOING, NULL, presId)); + } else { + OFLOG_INFO(movescuLogger, "Sending Move Request (MsgID " << msgId << ")"); + } + OFLOG_INFO(movescuLogger, "Request Identifiers:" << OFendl << DcmObject::PrintHelper(*dcmff.getDataset())); + + OFCondition cond = DIMSE_moveUser(assoc, presId, &req, dcmff.getDataset(), + moveCallback, &callbackData, opt_blockMode, opt_dimse_timeout, net, subOpCallback, + NULL, &rsp, &statusDetail, &rspIds, opt_ignorePendingDatasets); + + if (cond == EC_Normal) { + if (movescuLogger.isEnabledFor(OFLogger::DEBUG_LOG_LEVEL)) { + OFLOG_INFO(movescuLogger, "Received Final Move Response"); + OFLOG_DEBUG(movescuLogger, DIMSE_dumpMessage(temp_str, rsp, DIMSE_INCOMING)); + if (rspIds != NULL) { + OFLOG_DEBUG(movescuLogger, "Response Identifiers:" << OFendl << DcmObject::PrintHelper(*rspIds)); + } + } else { + OFLOG_INFO(movescuLogger, "Received Final Move Response (" << DU_cmoveStatusString(rsp.DimseStatus) << ")"); + } + } else { + OFLOG_ERROR(movescuLogger, "Move Request Failed: " << DimseCondition::dump(temp_str, cond)); + } + if (statusDetail != NULL) { + OFLOG_DEBUG(movescuLogger, "Status Detail:" << OFendl << DcmObject::PrintHelper(*statusDetail)); + delete statusDetail; + } + + if (rspIds != NULL) delete rspIds; + + return cond; +} + + +static OFCondition +cmove(T_ASC_Association *assoc, const char *fname) +{ + OFCondition cond = EC_Normal; + int n = OFstatic_cast(int, opt_repeatCount); + while (cond.good() && n--) + cond = moveSCU(assoc, fname); + return cond; +} diff --git a/dcmnet/apps/storescp.cc b/dcmnet/apps/storescp.cc new file mode 100644 index 00000000..368ffd3d --- /dev/null +++ b/dcmnet/apps/storescp.cc @@ -0,0 +1,2751 @@ +/* + * + * Copyright (C) 1994-2014, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmnet + * + * Author: Andrew Hewett + * + * Purpose: Storage Service Class Provider (C-STORE operation) + * + */ + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#define INCLUDE_CSTDLIB +#define INCLUDE_CSTRING +#define INCLUDE_CSTDARG +#define INCLUDE_CCTYPE +#define INCLUDE_CSIGNAL +#include "dcmtk/ofstd/ofstdinc.h" + +BEGIN_EXTERN_C +#ifdef HAVE_SYS_STAT_H +#include +#endif +#ifdef HAVE_FCNTL_H +#include /* needed on Solaris for O_RDONLY */ +#endif +#ifdef HAVE_SIGNAL_H +// On Solaris with Sun Workshop 11, declares signal() but does not +#include +#endif +END_EXTERN_C + +#ifdef HAVE_GUSI_H +#include +#endif + +#ifdef HAVE_WINDOWS_H +#include /* for _mkdir() */ +#endif + +#include "dcmtk/ofstd/ofstd.h" +#include "dcmtk/ofstd/ofconapp.h" +#include "dcmtk/ofstd/ofdatime.h" +#include "dcmtk/dcmnet/dicom.h" /* for DICOM_APPLICATION_ACCEPTOR */ +#include "dcmtk/dcmnet/dimse.h" +#include "dcmtk/dcmnet/diutil.h" +#include "dcmtk/dcmnet/dcasccfg.h" /* for class DcmAssociationConfiguration */ +#include "dcmtk/dcmnet/dcasccff.h" /* for class DcmAssociationConfigurationFile */ +#include "dcmtk/dcmdata/dcfilefo.h" +#include "dcmtk/dcmdata/dcuid.h" +#include "dcmtk/dcmdata/dcdict.h" +#include "dcmtk/dcmdata/cmdlnarg.h" +#include "dcmtk/dcmdata/dcmetinf.h" +#include "dcmtk/dcmdata/dcuid.h" /* for dcmtk version name */ +#include "dcmtk/dcmdata/dcdeftag.h" +#include "dcmtk/dcmdata/dcostrmz.h" /* for dcmZlibCompressionLevel */ + +#ifdef WITH_OPENSSL +#include "dcmtk/dcmtls/tlstrans.h" +#include "dcmtk/dcmtls/tlslayer.h" +#endif + +#ifdef WITH_ZLIB +#include /* for zlibVersion() */ +#endif + +// we assume that the inetd super server is available on all non-Windows systems +#ifndef _WIN32 +#define INETD_AVAILABLE +#endif + + +#ifdef PRIVATE_STORESCP_DECLARATIONS +PRIVATE_STORESCP_DECLARATIONS +#else +#define OFFIS_CONSOLE_APPLICATION "storescp" +#endif + +static OFLogger storescpLogger = OFLog::getLogger("dcmtk.apps." OFFIS_CONSOLE_APPLICATION); + +static char rcsid[] = "$dcmtk: " OFFIS_CONSOLE_APPLICATION " v" OFFIS_DCMTK_VERSION " " OFFIS_DCMTK_RELEASEDATE " $"; + +#define APPLICATIONTITLE "STORESCP" /* our application entity title */ + +#define PATH_PLACEHOLDER "#p" +#define FILENAME_PLACEHOLDER "#f" +#define CALLING_AETITLE_PLACEHOLDER "#a" +#define CALLED_AETITLE_PLACEHOLDER "#c" +#define CALLING_PRESENTATION_ADDRESS_PLACEHOLDER "#r" + +static OFCondition processCommands(T_ASC_Association *assoc); +static OFCondition acceptAssociation(T_ASC_Network *net, DcmAssociationConfiguration& asccfg); +static OFCondition echoSCP(T_ASC_Association * assoc, T_DIMSE_Message * msg, T_ASC_PresentationContextID presID); +static OFCondition storeSCP(T_ASC_Association * assoc, T_DIMSE_Message * msg, T_ASC_PresentationContextID presID); +static void executeOnReception(); +static void executeEndOfStudyEvents(); +static void executeOnEndOfStudy(); +static void renameOnEndOfStudy(); +static OFString replaceChars( const OFString &srcstr, const OFString &pattern, const OFString &substitute ); +static void executeCommand( const OFString &cmd ); +static void cleanChildren(pid_t pid, OFBool synch); +static OFCondition acceptUnknownContextsWithPreferredTransferSyntaxes( + T_ASC_Parameters * params, + const char* transferSyntaxes[], + int transferSyntaxCount, + T_ASC_SC_ROLE acceptedRole = ASC_SC_ROLE_DEFAULT); + +/* sort study mode */ +enum E_SortStudyMode +{ + ESM_None, + ESM_Timestamp, + ESM_StudyInstanceUID, + ESM_PatientName +}; + +OFBool opt_showPresentationContexts = OFFalse; +OFBool opt_uniqueFilenames = OFFalse; +OFString opt_fileNameExtension; +OFBool opt_timeNames = OFFalse; +int timeNameCounter = -1; // "serial number" to differentiate between files with same timestamp +OFCmdUnsignedInt opt_port = 0; +OFBool opt_refuseAssociation = OFFalse; +OFBool opt_rejectWithoutImplementationUID = OFFalse; +OFCmdUnsignedInt opt_sleepAfter = 0; +OFCmdUnsignedInt opt_sleepDuring = 0; +OFCmdUnsignedInt opt_maxPDU = ASC_DEFAULTMAXPDU; +OFBool opt_useMetaheader = OFTrue; +OFBool opt_acceptAllXfers = OFFalse; +E_TransferSyntax opt_networkTransferSyntax = EXS_Unknown; +E_TransferSyntax opt_writeTransferSyntax = EXS_Unknown; +E_GrpLenEncoding opt_groupLength = EGL_recalcGL; +E_EncodingType opt_sequenceType = EET_ExplicitLength; +E_PaddingEncoding opt_paddingType = EPD_withoutPadding; +OFCmdUnsignedInt opt_filepad = 0; +OFCmdUnsignedInt opt_itempad = 0; +OFCmdUnsignedInt opt_compressionLevel = 0; +OFBool opt_bitPreserving = OFFalse; +OFBool opt_ignore = OFFalse; +OFBool opt_abortDuringStore = OFFalse; +OFBool opt_abortAfterStore = OFFalse; +OFBool opt_promiscuous = OFFalse; +OFBool opt_correctUIDPadding = OFFalse; +OFBool opt_inetd_mode = OFFalse; +OFString callingAETitle; // calling application entity title will be stored here +OFString lastCallingAETitle; +OFString calledAETitle; // called application entity title will be stored here +OFString lastCalledAETitle; +OFString callingPresentationAddress; // remote hostname or IP address will be stored here +OFString lastCallingPresentationAddress; +const char * opt_respondingAETitle = APPLICATIONTITLE; +static OFBool opt_secureConnection = OFFalse; // default: no secure connection +static OFString opt_outputDirectory = "."; // default: output directory equals "." +E_SortStudyMode opt_sortStudyMode = ESM_None; // default: no sorting +static const char *opt_sortStudyDirPrefix = NULL; // default: no directory prefix +OFString lastStudyInstanceUID; +OFString subdirectoryPathAndName; +OFList outputFileNameArray; +static const char *opt_execOnReception = NULL; // default: don't execute anything on reception +static const char *opt_execOnEndOfStudy = NULL; // default: don't execute anything on end of study + +OFString lastStudySubdirectoryPathAndName; +static OFBool opt_renameOnEndOfStudy = OFFalse; // default: don't rename any files on end of study +static long opt_endOfStudyTimeout = -1; // default: no end of study timeout +static OFBool endOfStudyThroughTimeoutEvent = OFFalse; +static const char *opt_configFile = NULL; +static const char *opt_profileName = NULL; +T_DIMSE_BlockingMode opt_blockMode = DIMSE_BLOCKING; +int opt_dimse_timeout = 0; +int opt_acse_timeout = 30; + +#if defined(HAVE_FORK) || defined(_WIN32) +OFBool opt_forkMode = OFFalse; +#endif + +OFBool opt_forkedChild = OFFalse; +OFBool opt_execSync = OFFalse; // default: execute in background + +#ifdef WITH_OPENSSL +static int opt_keyFileFormat = SSL_FILETYPE_PEM; +static const char *opt_privateKeyFile = NULL; +static const char *opt_certificateFile = NULL; +static const char *opt_passwd = NULL; +#if OPENSSL_VERSION_NUMBER >= 0x0090700fL +static OFString opt_ciphersuites(TLS1_TXT_RSA_WITH_AES_128_SHA ":" SSL3_TXT_RSA_DES_192_CBC3_SHA); +#else +static OFString opt_ciphersuites(SSL3_TXT_RSA_DES_192_CBC3_SHA); +#endif +static const char *opt_readSeedFile = NULL; +static const char *opt_writeSeedFile = NULL; +static DcmCertificateVerification opt_certVerification = DCV_requireCertificate; +static const char *opt_dhparam = NULL; +#endif + + +#ifdef HAVE_WAITPID +/** signal handler for SIGCHLD signals that immediately cleans up + * terminated children. + */ +#ifdef SIGNAL_HANDLER_WITH_ELLIPSE +extern "C" void sigChildHandler(...) +#else +extern "C" void sigChildHandler(int) +#endif +{ + int status = 0; + waitpid( -1, &status, WNOHANG ); + signal(SIGCHLD, sigChildHandler); +} +#endif + + +#define SHORTCOL 4 +#define LONGCOL 21 + +int main(int argc, char *argv[]) +{ + T_ASC_Network *net; + DcmAssociationConfiguration asccfg; + +#ifdef HAVE_GUSI_H + /* needed for Macintosh */ + GUSISetup(GUSIwithSIOUXSockets); + GUSISetup(GUSIwithInternetSockets); +#endif + +#ifdef HAVE_WINSOCK_H + WSAData winSockData; + /* we need at least version 1.1 */ + WORD winSockVersionNeeded = MAKEWORD( 1, 1 ); + WSAStartup(winSockVersionNeeded, &winSockData); +#endif + + char tempstr[20]; + OFString temp_str; + OFConsoleApplication app(OFFIS_CONSOLE_APPLICATION, "DICOM storage (C-STORE) SCP", rcsid); + OFCommandLine cmd; + + cmd.setParamColumn(LONGCOL + SHORTCOL + 4); + cmd.addParam("port", "tcp/ip port number to listen on", OFCmdParam::PM_Optional); + + cmd.setOptionColumns(LONGCOL, SHORTCOL); + cmd.addGroup("general options:", LONGCOL, SHORTCOL + 2); + cmd.addOption("--help", "-h", "print this help text and exit", OFCommandLine::AF_Exclusive); + cmd.addOption("--version", "print version information and exit", OFCommandLine::AF_Exclusive); + OFLog::addOptions(cmd); + cmd.addOption("--verbose-pc", "+v", "show presentation contexts in verbose mode"); + +#if defined(HAVE_FORK) || defined(_WIN32) + cmd.addGroup("multi-process options:", LONGCOL, SHORTCOL + 2); + cmd.addOption("--single-process", "single process mode (default)"); + cmd.addOption("--fork", "fork child process for each association"); +#ifdef _WIN32 + cmd.addOption("--forked-child", "process is forked child, internal use only", OFCommandLine::AF_Internal); +#endif +#endif + + cmd.addGroup("network options:"); + cmd.addSubGroup("association negotiation profile from configuration file:"); + cmd.addOption("--config-file", "-xf", 2, "[f]ilename, [p]rofile: string", + "use profile p from config file f"); + cmd.addSubGroup("preferred network transfer syntaxes (not with --config-file):"); + cmd.addOption("--prefer-uncompr", "+x=", "prefer explicit VR local byte order (default)"); + cmd.addOption("--prefer-little", "+xe", "prefer explicit VR little endian TS"); + cmd.addOption("--prefer-big", "+xb", "prefer explicit VR big endian TS"); + cmd.addOption("--prefer-lossless", "+xs", "prefer default JPEG lossless TS"); + cmd.addOption("--prefer-jpeg8", "+xy", "prefer default JPEG lossy TS for 8 bit data"); + cmd.addOption("--prefer-jpeg12", "+xx", "prefer default JPEG lossy TS for 12 bit data"); + cmd.addOption("--prefer-j2k-lossless", "+xv", "prefer JPEG 2000 lossless TS"); + cmd.addOption("--prefer-j2k-lossy", "+xw", "prefer JPEG 2000 lossy TS"); + cmd.addOption("--prefer-jls-lossless", "+xt", "prefer JPEG-LS lossless TS"); + cmd.addOption("--prefer-jls-lossy", "+xu", "prefer JPEG-LS lossy TS"); + cmd.addOption("--prefer-mpeg2", "+xm", "prefer MPEG2 Main Profile @ Main Level TS"); + cmd.addOption("--prefer-mpeg2-high", "+xh", "prefer MPEG2 Main Profile @ High Level TS"); + cmd.addOption("--prefer-mpeg4", "+xn", "prefer MPEG4 AVC/H.264 HP / Level 4.1 TS"); + cmd.addOption("--prefer-mpeg4-bd", "+xl", "prefer MPEG4 AVC/H.264 BD-compatible TS"); + cmd.addOption("--prefer-rle", "+xr", "prefer RLE lossless TS"); +#ifdef WITH_ZLIB + cmd.addOption("--prefer-deflated", "+xd", "prefer deflated expl. VR little endian TS"); +#endif + cmd.addOption("--implicit", "+xi", "accept implicit VR little endian TS only"); + cmd.addOption("--accept-all", "+xa", "accept all supported transfer syntaxes"); + +#ifdef WITH_TCPWRAPPER + cmd.addSubGroup("network host access control (tcp wrapper):"); + cmd.addOption("--access-full", "-ac", "accept connections from any host (default)"); + cmd.addOption("--access-control", "+ac", "enforce host access control rules"); +#endif + + cmd.addSubGroup("other network options:"); +#ifdef INETD_AVAILABLE + // this option is only offered on Posix platforms + cmd.addOption("--inetd", "-id", "run from inetd super server (not with --fork)"); +#endif + + cmd.addOption("--acse-timeout", "-ta", 1, "[s]econds: integer (default: 30)", "timeout for ACSE messages"); + cmd.addOption("--dimse-timeout", "-td", 1, "[s]econds: integer (default: unlimited)", "timeout for DIMSE messages"); + + OFString opt1 = "set my AE title (default: "; + opt1 += APPLICATIONTITLE; + opt1 += ")"; + cmd.addOption("--aetitle", "-aet", 1, "[a]etitle: string", opt1.c_str()); + OFString opt3 = "set max receive pdu to n bytes (def.: "; + sprintf(tempstr, "%ld", OFstatic_cast(long, ASC_DEFAULTMAXPDU)); + opt3 += tempstr; + opt3 += ")"; + OFString opt4 = "[n]umber of bytes: integer ("; + sprintf(tempstr, "%ld", OFstatic_cast(long, ASC_MINIMUMPDUSIZE)); + opt4 += tempstr; + opt4 += ".."; + sprintf(tempstr, "%ld", OFstatic_cast(long, ASC_MAXIMUMPDUSIZE)); + opt4 += tempstr; + opt4 += ")"; + cmd.addOption("--max-pdu", "-pdu", 1, opt4.c_str(), opt3.c_str()); + cmd.addOption("--disable-host-lookup", "-dhl", "disable hostname lookup"); + cmd.addOption("--refuse", "refuse association"); + cmd.addOption("--reject", "reject association if no implement. class UID"); + cmd.addOption("--ignore", "ignore store data, receive but do not store"); + cmd.addOption("--sleep-after", 1, "[s]econds: integer", + "sleep s seconds after store (default: 0)"); + cmd.addOption("--sleep-during", 1, "[s]econds: integer", + "sleep s seconds during store (default: 0)"); + cmd.addOption("--abort-after", "abort association after receipt of C-STORE-RQ\n(but before sending response)"); + cmd.addOption("--abort-during", "abort association during receipt of C-STORE-RQ"); + cmd.addOption("--promiscuous", "-pm", "promiscuous mode, accept unknown SOP classes\n(not with --config-file)"); + cmd.addOption("--uid-padding", "-up", "silently correct space-padded UIDs"); + +#ifdef WITH_OPENSSL + cmd.addGroup("transport layer security (TLS) options:"); + cmd.addSubGroup("transport protocol stack:"); + cmd.addOption("--disable-tls", "-tls", "use normal TCP/IP connection (default)"); + cmd.addOption("--enable-tls", "+tls", 2, "[p]rivate key file, [c]ertificate file: string", + "use authenticated secure TLS connection"); + cmd.addSubGroup("private key password (only with --enable-tls):"); + cmd.addOption("--std-passwd", "+ps", "prompt user to type password on stdin (default)"); + cmd.addOption("--use-passwd", "+pw", 1, "[p]assword: string", + "use specified password"); + cmd.addOption("--null-passwd", "-pw", "use empty string as password"); + cmd.addSubGroup("key and certificate file format:"); + cmd.addOption("--pem-keys", "-pem", "read keys and certificates as PEM file (def.)"); + cmd.addOption("--der-keys", "-der", "read keys and certificates as DER file"); + cmd.addSubGroup("certification authority:"); + cmd.addOption("--add-cert-file", "+cf", 1, "[c]ertificate filename: string", + "add certificate file to list of certificates", OFCommandLine::AF_NoWarning); + cmd.addOption("--add-cert-dir", "+cd", 1, "[c]ertificate directory: string", + "add certificates in d to list of certificates", OFCommandLine::AF_NoWarning); + cmd.addSubGroup("ciphersuite:"); + cmd.addOption("--cipher", "+cs", 1, "[c]iphersuite name: string", + "add ciphersuite to list of negotiated suites"); + cmd.addOption("--dhparam", "+dp", 1, "[f]ilename: string", + "read DH parameters for DH/DSS ciphersuites"); + cmd.addSubGroup("pseudo random generator:"); + cmd.addOption("--seed", "+rs", 1, "[f]ilename: string", + "seed random generator with contents of f"); + cmd.addOption("--write-seed", "+ws", "write back modified seed (only with --seed)"); + cmd.addOption("--write-seed-file", "+wf", 1, "[f]ilename: string (only with --seed)", + "write modified seed to file f"); + cmd.addSubGroup("peer authentication"); + cmd.addOption("--require-peer-cert", "-rc", "verify peer certificate, fail if absent (def.)"); + cmd.addOption("--verify-peer-cert", "-vc", "verify peer certificate if present"); + cmd.addOption("--ignore-peer-cert", "-ic", "don't verify peer certificate"); +#endif + + cmd.addGroup("output options:"); + cmd.addSubGroup("general:"); + cmd.addOption("--output-directory", "-od", 1, "[d]irectory: string (default: \".\")", "write received objects to existing directory d"); + cmd.addSubGroup("bit preserving mode:"); + cmd.addOption("--normal", "-B", "allow implicit format conversions (default)"); + cmd.addOption("--bit-preserving", "+B", "write data exactly as read"); + cmd.addSubGroup("output file format:"); + cmd.addOption("--write-file", "+F", "write file format (default)"); + cmd.addOption("--write-dataset", "-F", "write data set without file meta information"); + cmd.addSubGroup("output transfer syntax (not with --bit-preserving or compressed transmission):"); + cmd.addOption("--write-xfer-same", "+t=", "write with same TS as input (default)"); + cmd.addOption("--write-xfer-little", "+te", "write with explicit VR little endian TS"); + cmd.addOption("--write-xfer-big", "+tb", "write with explicit VR big endian TS"); + cmd.addOption("--write-xfer-implicit", "+ti", "write with implicit VR little endian TS"); +#ifdef WITH_ZLIB + cmd.addOption("--write-xfer-deflated", "+td", "write with deflated expl. VR little endian TS"); +#endif + cmd.addSubGroup("post-1993 value representations (not with --bit-preserving):"); + cmd.addOption("--enable-new-vr", "+u", "enable support for new VRs (UN/UT) (default)"); + cmd.addOption("--disable-new-vr", "-u", "disable support for new VRs, convert to OB"); + cmd.addSubGroup("group length encoding (not with --bit-preserving):"); + cmd.addOption("--group-length-recalc", "+g=", "recalculate group lengths if present (default)"); + cmd.addOption("--group-length-create", "+g", "always write with group length elements"); + cmd.addOption("--group-length-remove", "-g", "always write without group length elements"); + cmd.addSubGroup("length encoding in sequences and items (not with --bit-preserving):"); + cmd.addOption("--length-explicit", "+e", "write with explicit lengths (default)"); + cmd.addOption("--length-undefined", "-e", "write with undefined lengths"); + cmd.addSubGroup("data set trailing padding (not with --write-dataset or --bit-preserving):"); + cmd.addOption("--padding-off", "-p", "no padding (default)"); + cmd.addOption("--padding-create", "+p", 2, "[f]ile-pad [i]tem-pad: integer", + "align file on multiple of f bytes and items\non multiple of i bytes"); +#ifdef WITH_ZLIB + cmd.addSubGroup("deflate compression level (only with --write-xfer-deflated/same):"); + cmd.addOption("--compression-level", "+cl", 1, "[l]evel: integer (default: 6)", + "0=uncompressed, 1=fastest, 9=best compression"); +#endif + cmd.addSubGroup("sorting into subdirectories (not with --bit-preserving):"); + cmd.addOption("--sort-conc-studies", "-ss", 1, "[p]refix: string", + "sort studies using prefix p and a timestamp"); + cmd.addOption("--sort-on-study-uid", "-su", 1, "[p]refix: string", + "sort studies using prefix p and the Study\nInstance UID"); + cmd.addOption("--sort-on-patientname", "-sp", "sort studies using the Patient's Name and\na timestamp"); + + cmd.addSubGroup("filename generation:"); + cmd.addOption("--default-filenames", "-uf", "generate filename from instance UID (default)"); + cmd.addOption("--unique-filenames", "+uf", "generate unique filenames"); + cmd.addOption("--timenames", "-tn", "generate filename from creation time"); + cmd.addOption("--filename-extension", "-fe", 1, "[e]xtension: string", + "append e to all filenames"); + + cmd.addGroup("event options:", LONGCOL, SHORTCOL + 2); + cmd.addOption("--exec-on-reception", "-xcr", 1, "[c]ommand: string", + "execute command c after having received and\nprocessed one C-STORE-RQ message"); + cmd.addOption("--exec-on-eostudy", "-xcs", 1, "[c]ommand: string", + "execute command c after having received and\nprocessed all C-STORE-RQ messages that belong\nto one study"); + cmd.addOption("--rename-on-eostudy", "-rns", "having received and processed all C-STORE-RQ\nmessages that belong to one study, rename\noutput files according to certain pattern"); + cmd.addOption("--eostudy-timeout", "-tos", 1, "[t]imeout: integer", + "specifies a timeout of t seconds for\nend-of-study determination"); + cmd.addOption("--exec-sync", "-xs", "execute command synchronously in foreground"); + + /* evaluate command line */ + prepareCmdLineArgs(argc, argv, OFFIS_CONSOLE_APPLICATION); + if (app.parseCommandLine(cmd, argc, argv)) + { + /* print help text and exit */ + if (cmd.getArgCount() == 0) + app.printUsage(); + + /* check exclusive options first */ + if (cmd.hasExclusiveOption()) + { + if (cmd.findOption("--version")) + { + app.printHeader(OFTrue /*print host identifier*/); + COUT << OFendl << "External libraries used:"; +#if !defined(WITH_ZLIB) && !defined(WITH_OPENSSL) && !defined(WITH_TCPWRAPPER) + COUT << " none" << OFendl; +#else + COUT << OFendl; +#endif +#ifdef WITH_ZLIB + COUT << "- ZLIB, Version " << zlibVersion() << OFendl; +#endif +#ifdef WITH_OPENSSL + COUT << "- " << OPENSSL_VERSION_TEXT << OFendl; +#endif +#ifdef WITH_TCPWRAPPER + COUT << "- LIBWRAP" << OFendl; +#endif + return 0; + } + } + +#ifdef INETD_AVAILABLE + if (cmd.findOption("--inetd")) + { + opt_inetd_mode = OFTrue; + opt_forkMode = OFFalse; + + // duplicate stdin, which is the socket passed by inetd + int inetd_fd = dup(0); + if (inetd_fd < 0) exit(99); + + close(0); // close stdin + close(1); // close stdout + close(2); // close stderr + + // open new file descriptor for stdin + int fd = open("/dev/null", O_RDONLY); + if (fd != 0) exit(99); + + // create new file descriptor for stdout + fd = open("/dev/null", O_WRONLY); + if (fd != 1) exit(99); + + // create new file descriptor for stderr + fd = open("/dev/null", O_WRONLY); + if (fd != 2) exit(99); + + dcmExternalSocketHandle.set(inetd_fd); + + // the port number is not really used. Set to non-privileged port number + // to avoid failing the privilege test. + opt_port = 1024; + } +#endif + +#if defined(HAVE_FORK) || defined(_WIN32) + cmd.beginOptionBlock(); + if (cmd.findOption("--single-process")) + opt_forkMode = OFFalse; + if (cmd.findOption("--fork")) + { + app.checkConflict("--inetd", "--fork", opt_inetd_mode); + opt_forkMode = OFTrue; + } + cmd.endOptionBlock(); +#ifdef _WIN32 + if (cmd.findOption("--forked-child")) opt_forkedChild = OFTrue; +#endif +#endif + + if (opt_inetd_mode) + { + // port number is not required in inetd mode + if (cmd.getParamCount() > 0) + OFLOG_WARN(storescpLogger, "Parameter port not required in inetd mode"); + } else { + // omitting the port number is only allowed in inetd mode + if (cmd.getParamCount() == 0) + app.printError("Missing parameter port"); + else + app.checkParam(cmd.getParamAndCheckMinMax(1, opt_port, 1, 65535)); + } + + OFLog::configureFromCommandLine(cmd, app); + if (cmd.findOption("--verbose-pc")) + { + app.checkDependence("--verbose-pc", "verbose mode", storescpLogger.isEnabledFor(OFLogger::INFO_LOG_LEVEL)); + opt_showPresentationContexts = OFTrue; + } + + cmd.beginOptionBlock(); + if (cmd.findOption("--prefer-uncompr")) + { + opt_acceptAllXfers = OFFalse; + opt_networkTransferSyntax = EXS_Unknown; + } + if (cmd.findOption("--prefer-little")) opt_networkTransferSyntax = EXS_LittleEndianExplicit; + if (cmd.findOption("--prefer-big")) opt_networkTransferSyntax = EXS_BigEndianExplicit; + if (cmd.findOption("--prefer-lossless")) opt_networkTransferSyntax = EXS_JPEGProcess14SV1; + if (cmd.findOption("--prefer-jpeg8")) opt_networkTransferSyntax = EXS_JPEGProcess1; + if (cmd.findOption("--prefer-jpeg12")) opt_networkTransferSyntax = EXS_JPEGProcess2_4; + if (cmd.findOption("--prefer-j2k-lossless")) opt_networkTransferSyntax = EXS_JPEG2000LosslessOnly; + if (cmd.findOption("--prefer-j2k-lossy")) opt_networkTransferSyntax = EXS_JPEG2000; + if (cmd.findOption("--prefer-jls-lossless")) opt_networkTransferSyntax = EXS_JPEGLSLossless; + if (cmd.findOption("--prefer-jls-lossy")) opt_networkTransferSyntax = EXS_JPEGLSLossy; + if (cmd.findOption("--prefer-mpeg2")) opt_networkTransferSyntax = EXS_MPEG2MainProfileAtMainLevel; + if (cmd.findOption("--prefer-mpeg2-high")) opt_networkTransferSyntax = EXS_MPEG2MainProfileAtHighLevel; + if (cmd.findOption("--prefer-mpeg4")) opt_networkTransferSyntax = EXS_MPEG4HighProfileLevel4_1; + if (cmd.findOption("--prefer-mpeg4-bd")) opt_networkTransferSyntax = EXS_MPEG4BDcompatibleHighProfileLevel4_1; + if (cmd.findOption("--prefer-rle")) opt_networkTransferSyntax = EXS_RLELossless; +#ifdef WITH_ZLIB + if (cmd.findOption("--prefer-deflated")) opt_networkTransferSyntax = EXS_DeflatedLittleEndianExplicit; +#endif + if (cmd.findOption("--implicit")) opt_networkTransferSyntax = EXS_LittleEndianImplicit; + if (cmd.findOption("--accept-all")) + { + opt_acceptAllXfers = OFTrue; + opt_networkTransferSyntax = EXS_Unknown; + } + cmd.endOptionBlock(); + if (opt_networkTransferSyntax != EXS_Unknown) opt_acceptAllXfers = OFFalse; + + if (cmd.findOption("--acse-timeout")) + { + OFCmdSignedInt opt_timeout = 0; + app.checkValue(cmd.getValueAndCheckMin(opt_timeout, 1)); + opt_acse_timeout = OFstatic_cast(int, opt_timeout); + } + if (cmd.findOption("--dimse-timeout")) + { + OFCmdSignedInt opt_timeout = 0; + app.checkValue(cmd.getValueAndCheckMin(opt_timeout, 1)); + opt_dimse_timeout = OFstatic_cast(int, opt_timeout); + opt_blockMode = DIMSE_NONBLOCKING; + } + + if (cmd.findOption("--aetitle")) app.checkValue(cmd.getValue(opt_respondingAETitle)); + if (cmd.findOption("--max-pdu")) app.checkValue(cmd.getValueAndCheckMinMax(opt_maxPDU, ASC_MINIMUMPDUSIZE, ASC_MAXIMUMPDUSIZE)); + if (cmd.findOption("--disable-host-lookup")) dcmDisableGethostbyaddr.set(OFTrue); + if (cmd.findOption("--refuse")) opt_refuseAssociation = OFTrue; + if (cmd.findOption("--reject")) opt_rejectWithoutImplementationUID = OFTrue; + if (cmd.findOption("--ignore")) opt_ignore = OFTrue; + if (cmd.findOption("--sleep-after")) app.checkValue(cmd.getValueAndCheckMin(opt_sleepAfter, 0)); + if (cmd.findOption("--sleep-during")) app.checkValue(cmd.getValueAndCheckMin(opt_sleepDuring, 0)); + if (cmd.findOption("--abort-after")) opt_abortAfterStore = OFTrue; + if (cmd.findOption("--abort-during")) opt_abortDuringStore = OFTrue; + if (cmd.findOption("--promiscuous")) opt_promiscuous = OFTrue; + if (cmd.findOption("--uid-padding")) opt_correctUIDPadding = OFTrue; + + if (cmd.findOption("--config-file")) + { + // check conflicts with other command line options + app.checkConflict("--config-file", "--prefer-little", opt_networkTransferSyntax == EXS_LittleEndianExplicit); + app.checkConflict("--config-file", "--prefer-big", opt_networkTransferSyntax == EXS_BigEndianExplicit); + app.checkConflict("--config-file", "--prefer-lossless", opt_networkTransferSyntax == EXS_JPEGProcess14SV1); + app.checkConflict("--config-file", "--prefer-jpeg8", opt_networkTransferSyntax == EXS_JPEGProcess1); + app.checkConflict("--config-file", "--prefer-jpeg12", opt_networkTransferSyntax == EXS_JPEGProcess2_4); + app.checkConflict("--config-file", "--prefer-j2k-lossless", opt_networkTransferSyntax == EXS_JPEG2000LosslessOnly); + app.checkConflict("--config-file", "--prefer-j2k-lossy", opt_networkTransferSyntax == EXS_JPEG2000); + app.checkConflict("--config-file", "--prefer-jls-lossless", opt_networkTransferSyntax == EXS_JPEGLSLossless); + app.checkConflict("--config-file", "--prefer-jls-lossy", opt_networkTransferSyntax == EXS_JPEGLSLossy); + app.checkConflict("--config-file", "--prefer-mpeg2", opt_networkTransferSyntax == EXS_MPEG2MainProfileAtMainLevel); + app.checkConflict("--config-file", "--prefer-mpeg2-high", opt_networkTransferSyntax == EXS_MPEG2MainProfileAtHighLevel); + app.checkConflict("--config-file", "--prefer-mpeg4", opt_networkTransferSyntax == EXS_MPEG4HighProfileLevel4_1); + app.checkConflict("--config-file", "--prefer-mpeg4-bd", opt_networkTransferSyntax == EXS_MPEG4BDcompatibleHighProfileLevel4_1); + app.checkConflict("--config-file", "--prefer-rle", opt_networkTransferSyntax == EXS_RLELossless); +#ifdef WITH_ZLIB + app.checkConflict("--config-file", "--prefer-deflated", opt_networkTransferSyntax == EXS_DeflatedLittleEndianExplicit); +#endif + app.checkConflict("--config-file", "--implicit", opt_networkTransferSyntax == EXS_LittleEndianImplicit); + app.checkConflict("--config-file", "--accept-all", opt_acceptAllXfers); + app.checkConflict("--config-file", "--promiscuous", opt_promiscuous); + + app.checkValue(cmd.getValue(opt_configFile)); + app.checkValue(cmd.getValue(opt_profileName)); + + // read configuration file + OFCondition cond = DcmAssociationConfigurationFile::initialize(asccfg, opt_configFile); + if (cond.bad()) + { + OFLOG_FATAL(storescpLogger, "cannot read config file: " << cond.text()); + return 1; + } + + /* perform name mangling for config file key */ + OFString sprofile; + const unsigned char *c = OFreinterpret_cast(const unsigned char *, opt_profileName); + while (*c) + { + if (! isspace(*c)) sprofile += OFstatic_cast(char, toupper(*c)); + ++c; + } + + if (!asccfg.isKnownProfile(sprofile.c_str())) + { + OFLOG_FATAL(storescpLogger, "unknown configuration profile name: " << sprofile); + return 1; + } + + if (!asccfg.isValidSCPProfile(sprofile.c_str())) + { + OFLOG_FATAL(storescpLogger, "profile '" << sprofile << "' is not valid for SCP use, duplicate abstract syntaxes found"); + return 1; + } + + } + +#ifdef WITH_TCPWRAPPER + cmd.beginOptionBlock(); + if (cmd.findOption("--access-full")) dcmTCPWrapperDaemonName.set(NULL); + if (cmd.findOption("--access-control")) dcmTCPWrapperDaemonName.set(OFFIS_CONSOLE_APPLICATION); + cmd.endOptionBlock(); +#endif + + if (cmd.findOption("--output-directory")) app.checkValue(cmd.getValue(opt_outputDirectory)); + + cmd.beginOptionBlock(); + if (cmd.findOption("--normal")) opt_bitPreserving = OFFalse; + if (cmd.findOption("--bit-preserving")) opt_bitPreserving = OFTrue; + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--write-file")) opt_useMetaheader = OFTrue; + if (cmd.findOption("--write-dataset")) opt_useMetaheader = OFFalse; + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--write-xfer-same")) opt_writeTransferSyntax = EXS_Unknown; + if (cmd.findOption("--write-xfer-little")) + { + app.checkConflict("--write-xfer-little", "--accept-all", opt_acceptAllXfers); + app.checkConflict("--write-xfer-little", "--bit-preserving", opt_bitPreserving); + app.checkConflict("--write-xfer-little", "--prefer-lossless", opt_networkTransferSyntax == EXS_JPEGProcess14SV1); + app.checkConflict("--write-xfer-little", "--prefer-jpeg8", opt_networkTransferSyntax == EXS_JPEGProcess1); + app.checkConflict("--write-xfer-little", "--prefer-jpeg12", opt_networkTransferSyntax == EXS_JPEGProcess2_4); + app.checkConflict("--write-xfer-little", "--prefer-j2k-lossless", opt_networkTransferSyntax == EXS_JPEG2000LosslessOnly); + app.checkConflict("--write-xfer-little", "--prefer-j2k-lossy", opt_networkTransferSyntax == EXS_JPEG2000); + app.checkConflict("--write-xfer-little", "--prefer-jls-lossless", opt_networkTransferSyntax == EXS_JPEGLSLossless); + app.checkConflict("--write-xfer-little", "--prefer-jls-lossy", opt_networkTransferSyntax == EXS_JPEGLSLossy); + app.checkConflict("--write-xfer-little", "--prefer-mpeg2", opt_networkTransferSyntax == EXS_MPEG2MainProfileAtMainLevel); + app.checkConflict("--write-xfer-little", "--prefer-mpeg2-high", opt_networkTransferSyntax == EXS_MPEG2MainProfileAtHighLevel); + app.checkConflict("--write-xfer-little", "--prefer-mpeg4", opt_networkTransferSyntax == EXS_MPEG4HighProfileLevel4_1); + app.checkConflict("--write-xfer-little", "--prefer-mpeg4-bd", opt_networkTransferSyntax == EXS_MPEG4BDcompatibleHighProfileLevel4_1); + app.checkConflict("--write-xfer-little", "--prefer-rle", opt_networkTransferSyntax == EXS_RLELossless); + // we don't have to check a conflict for --prefer-deflated because we can always convert that to uncompressed. + opt_writeTransferSyntax = EXS_LittleEndianExplicit; + } + if (cmd.findOption("--write-xfer-big")) + { + app.checkConflict("--write-xfer-big", "--accept-all", opt_acceptAllXfers); + app.checkConflict("--write-xfer-big", "--bit-preserving", opt_bitPreserving); + app.checkConflict("--write-xfer-big", "--prefer-lossless", opt_networkTransferSyntax == EXS_JPEGProcess14SV1); + app.checkConflict("--write-xfer-big", "--prefer-jpeg8", opt_networkTransferSyntax == EXS_JPEGProcess1); + app.checkConflict("--write-xfer-big", "--prefer-jpeg12", opt_networkTransferSyntax == EXS_JPEGProcess2_4); + app.checkConflict("--write-xfer-big", "--prefer-j2k-lossless", opt_networkTransferSyntax == EXS_JPEG2000LosslessOnly); + app.checkConflict("--write-xfer-big", "--prefer-j2k-lossy", opt_networkTransferSyntax == EXS_JPEG2000); + app.checkConflict("--write-xfer-big", "--prefer-jls-lossless", opt_networkTransferSyntax == EXS_JPEGLSLossless); + app.checkConflict("--write-xfer-big", "--prefer-jls-lossy", opt_networkTransferSyntax == EXS_JPEGLSLossy); + app.checkConflict("--write-xfer-big", "--prefer-mpeg2", opt_networkTransferSyntax == EXS_MPEG2MainProfileAtMainLevel); + app.checkConflict("--write-xfer-big", "--prefer-mpeg2-high", opt_networkTransferSyntax == EXS_MPEG2MainProfileAtHighLevel); + app.checkConflict("--write-xfer-big", "--prefer-mpeg4", opt_networkTransferSyntax == EXS_MPEG4HighProfileLevel4_1); + app.checkConflict("--write-xfer-big", "--prefer-mpeg4-bd", opt_networkTransferSyntax == EXS_MPEG4BDcompatibleHighProfileLevel4_1); + app.checkConflict("--write-xfer-big", "--prefer-rle", opt_networkTransferSyntax == EXS_RLELossless); + // we don't have to check a conflict for --prefer-deflated because we can always convert that to uncompressed. + opt_writeTransferSyntax = EXS_BigEndianExplicit; + } + if (cmd.findOption("--write-xfer-implicit")) + { + app.checkConflict("--write-xfer-implicit", "--accept-all", opt_acceptAllXfers); + app.checkConflict("--write-xfer-implicit", "--bit-preserving", opt_bitPreserving); + app.checkConflict("--write-xfer-implicit", "--prefer-lossless", opt_networkTransferSyntax == EXS_JPEGProcess14SV1); + app.checkConflict("--write-xfer-implicit", "--prefer-jpeg8", opt_networkTransferSyntax == EXS_JPEGProcess1); + app.checkConflict("--write-xfer-implicit", "--prefer-jpeg12", opt_networkTransferSyntax == EXS_JPEGProcess2_4); + app.checkConflict("--write-xfer-implicit", "--prefer-j2k-lossless", opt_networkTransferSyntax == EXS_JPEG2000LosslessOnly); + app.checkConflict("--write-xfer-implicit", "--prefer-j2k-lossy", opt_networkTransferSyntax == EXS_JPEG2000); + app.checkConflict("--write-xfer-implicit", "--prefer-jls-lossless", opt_networkTransferSyntax == EXS_JPEGLSLossless); + app.checkConflict("--write-xfer-implicit", "--prefer-jls-lossy", opt_networkTransferSyntax == EXS_JPEGLSLossy); + app.checkConflict("--write-xfer-implicit", "--prefer-mpeg2", opt_networkTransferSyntax == EXS_MPEG2MainProfileAtMainLevel); + app.checkConflict("--write-xfer-implicit", "--prefer-mpeg2-high", opt_networkTransferSyntax == EXS_MPEG2MainProfileAtHighLevel); + app.checkConflict("--write-xfer-implicit", "--prefer-mpeg4", opt_networkTransferSyntax == EXS_MPEG4HighProfileLevel4_1); + app.checkConflict("--write-xfer-implicit", "--prefer-mpeg4-bd", opt_networkTransferSyntax == EXS_MPEG4BDcompatibleHighProfileLevel4_1); + app.checkConflict("--write-xfer-implicit", "--prefer-rle", opt_networkTransferSyntax == EXS_RLELossless); + // we don't have to check a conflict for --prefer-deflated because we can always convert that to uncompressed. + opt_writeTransferSyntax = EXS_LittleEndianImplicit; + } +#ifdef WITH_ZLIB + if (cmd.findOption("--write-xfer-deflated")) + { + app.checkConflict("--write-xfer-deflated", "--accept-all", opt_acceptAllXfers); + app.checkConflict("--write-xfer-deflated", "--bit-preserving", opt_bitPreserving); + app.checkConflict("--write-xfer-deflated", "--prefer-lossless", opt_networkTransferSyntax == EXS_JPEGProcess14SV1); + app.checkConflict("--write-xfer-deflated", "--prefer-jpeg8", opt_networkTransferSyntax == EXS_JPEGProcess1); + app.checkConflict("--write-xfer-deflated", "--prefer-jpeg12", opt_networkTransferSyntax == EXS_JPEGProcess2_4); + app.checkConflict("--write-xfer-deflated", "--prefer-j2k-lossless", opt_networkTransferSyntax == EXS_JPEG2000LosslessOnly); + app.checkConflict("--write-xfer-deflated", "--prefer-j2k-lossy", opt_networkTransferSyntax == EXS_JPEG2000); + app.checkConflict("--write-xfer-deflated", "--prefer-jls-lossless", opt_networkTransferSyntax == EXS_JPEGLSLossless); + app.checkConflict("--write-xfer-deflated", "--prefer-jls-lossy", opt_networkTransferSyntax == EXS_JPEGLSLossy); + app.checkConflict("--write-xfer-deflated", "--prefer-mpeg2", opt_networkTransferSyntax == EXS_MPEG2MainProfileAtMainLevel); + app.checkConflict("--write-xfer-deflated", "--prefer-mpeg2-high", opt_networkTransferSyntax == EXS_MPEG2MainProfileAtHighLevel); + app.checkConflict("--write-xfer-deflated", "--prefer-mpeg4", opt_networkTransferSyntax == EXS_MPEG4HighProfileLevel4_1); + app.checkConflict("--write-xfer-deflated", "--prefer-mpeg4-bd", opt_networkTransferSyntax == EXS_MPEG4BDcompatibleHighProfileLevel4_1); + app.checkConflict("--write-xfer-deflated", "--prefer-rle", opt_networkTransferSyntax == EXS_RLELossless); + opt_writeTransferSyntax = EXS_DeflatedLittleEndianExplicit; + } +#endif + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--enable-new-vr")) + { + app.checkConflict("--enable-new-vr", "--bit-preserving", opt_bitPreserving); + dcmEnableGenerationOfNewVRs(); + } + if (cmd.findOption("--disable-new-vr")) + { + app.checkConflict("--disable-new-vr", "--bit-preserving", opt_bitPreserving); + dcmDisableGenerationOfNewVRs(); + } + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--group-length-recalc")) + { + app.checkConflict("--group-length-recalc", "--bit-preserving", opt_bitPreserving); + opt_groupLength = EGL_recalcGL; + } + if (cmd.findOption("--group-length-create")) + { + app.checkConflict("--group-length-create", "--bit-preserving", opt_bitPreserving); + opt_groupLength = EGL_withGL; + } + if (cmd.findOption("--group-length-remove")) + { + app.checkConflict("--group-length-remove", "--bit-preserving", opt_bitPreserving); + opt_groupLength = EGL_withoutGL; + } + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--length-explicit")) + { + app.checkConflict("--length-explicit", "--bit-preserving", opt_bitPreserving); + opt_sequenceType = EET_ExplicitLength; + } + if (cmd.findOption("--length-undefined")) + { + app.checkConflict("--length-undefined", "--bit-preserving", opt_bitPreserving); + opt_sequenceType = EET_UndefinedLength; + } + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--padding-off")) opt_paddingType = EPD_withoutPadding; + if (cmd.findOption("--padding-create")) + { + app.checkConflict("--padding-create", "--write-dataset", !opt_useMetaheader); + app.checkConflict("--padding-create", "--bit-preserving", opt_bitPreserving); + app.checkValue(cmd.getValueAndCheckMin(opt_filepad, 0)); + app.checkValue(cmd.getValueAndCheckMin(opt_itempad, 0)); + opt_paddingType = EPD_withPadding; + } + cmd.endOptionBlock(); + +#ifdef WITH_ZLIB + if (cmd.findOption("--compression-level")) + { + app.checkDependence("--compression-level", "--write-xfer-deflated or --write-xfer-same", + (opt_writeTransferSyntax == EXS_DeflatedLittleEndianExplicit) || (opt_writeTransferSyntax == EXS_Unknown)); + app.checkValue(cmd.getValueAndCheckMinMax(opt_compressionLevel, 0, 9)); + dcmZlibCompressionLevel.set(OFstatic_cast(int, opt_compressionLevel)); + } +#endif + + cmd.beginOptionBlock(); + if (cmd.findOption("--sort-conc-studies")) + { + app.checkConflict("--sort-conc-studies", "--bit-preserving", opt_bitPreserving); + app.checkValue(cmd.getValue(opt_sortStudyDirPrefix)); + opt_sortStudyMode = ESM_Timestamp; + } + if (cmd.findOption("--sort-on-study-uid")) + { + app.checkConflict("--sort-on-study-uid", "--bit-preserving", opt_bitPreserving); + app.checkValue(cmd.getValue(opt_sortStudyDirPrefix)); + opt_sortStudyMode = ESM_StudyInstanceUID; + } + if (cmd.findOption("--sort-on-patientname")) + { + app.checkConflict("--sort-on-patientname", "--bit-preserving", opt_bitPreserving); + opt_sortStudyDirPrefix = NULL; + opt_sortStudyMode = ESM_PatientName; + } + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--default-filenames")) opt_uniqueFilenames = OFFalse; + if (cmd.findOption("--unique-filenames")) opt_uniqueFilenames = OFTrue; + cmd.endOptionBlock(); + + if (cmd.findOption("--timenames")) opt_timeNames = OFTrue; + if (cmd.findOption("--filename-extension")) + app.checkValue(cmd.getValue(opt_fileNameExtension)); + if (cmd.findOption("--timenames")) + app.checkConflict("--timenames", "--unique-filenames", opt_uniqueFilenames); + + if (cmd.findOption("--exec-on-reception")) app.checkValue(cmd.getValue(opt_execOnReception)); + + if (cmd.findOption("--exec-on-eostudy")) + { + app.checkConflict("--exec-on-eostudy", "--fork", opt_forkMode); + app.checkConflict("--exec-on-eostudy", "--inetd", opt_inetd_mode); + app.checkDependence("--exec-on-eostudy", "--sort-conc-studies, --sort-on-study-uid or --sort-on-patientname", opt_sortStudyMode != ESM_None ); + app.checkValue(cmd.getValue(opt_execOnEndOfStudy)); + } + + if (cmd.findOption("--rename-on-eostudy")) + { + app.checkConflict("--rename-on-eostudy", "--fork", opt_forkMode); + app.checkConflict("--rename-on-eostudy", "--inetd", opt_inetd_mode); + app.checkDependence("--rename-on-eostudy", "--sort-conc-studies, --sort-on-study-uid or --sort-on-patientname", opt_sortStudyMode != ESM_None ); + opt_renameOnEndOfStudy = OFTrue; + } + + if (cmd.findOption("--eostudy-timeout")) + { + app.checkDependence("--eostudy-timeout", "--sort-conc-studies, --sort-on-study-uid, --sort-on-patientname, --exec-on-eostudy or --rename-on-eostudy", + (opt_sortStudyMode != ESM_None) || (opt_execOnEndOfStudy != NULL) || opt_renameOnEndOfStudy); + app.checkValue(cmd.getValueAndCheckMin(opt_endOfStudyTimeout, 0)); + } + + if (cmd.findOption("--exec-sync")) opt_execSync = OFTrue; + } + + /* print resource identifier */ + OFLOG_DEBUG(storescpLogger, rcsid << OFendl); + +#ifdef WITH_OPENSSL + + cmd.beginOptionBlock(); + if (cmd.findOption("--disable-tls")) opt_secureConnection = OFFalse; + if (cmd.findOption("--enable-tls")) + { + opt_secureConnection = OFTrue; + app.checkValue(cmd.getValue(opt_privateKeyFile)); + app.checkValue(cmd.getValue(opt_certificateFile)); + } + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--std-passwd")) + { + app.checkDependence("--std-passwd", "--enable-tls", opt_secureConnection); + opt_passwd = NULL; + } + if (cmd.findOption("--use-passwd")) + { + app.checkDependence("--use-passwd", "--enable-tls", opt_secureConnection); + app.checkValue(cmd.getValue(opt_passwd)); + } + if (cmd.findOption("--null-passwd")) + { + app.checkDependence("--null-passwd", "--enable-tls", opt_secureConnection); + opt_passwd = ""; + } + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--pem-keys")) opt_keyFileFormat = SSL_FILETYPE_PEM; + if (cmd.findOption("--der-keys")) opt_keyFileFormat = SSL_FILETYPE_ASN1; + cmd.endOptionBlock(); + + if (cmd.findOption("--dhparam")) + { + app.checkValue(cmd.getValue(opt_dhparam)); + } + + if (cmd.findOption("--seed")) + { + app.checkValue(cmd.getValue(opt_readSeedFile)); + } + + cmd.beginOptionBlock(); + if (cmd.findOption("--write-seed")) + { + app.checkDependence("--write-seed", "--seed", opt_readSeedFile != NULL); + opt_writeSeedFile = opt_readSeedFile; + } + if (cmd.findOption("--write-seed-file")) + { + app.checkDependence("--write-seed-file", "--seed", opt_readSeedFile != NULL); + app.checkValue(cmd.getValue(opt_writeSeedFile)); + } + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--require-peer-cert")) opt_certVerification = DCV_requireCertificate; + if (cmd.findOption("--verify-peer-cert")) opt_certVerification = DCV_checkCertificate; + if (cmd.findOption("--ignore-peer-cert")) opt_certVerification = DCV_ignoreCertificate; + cmd.endOptionBlock(); + + const char *current = NULL; + const char *currentOpenSSL; + if (cmd.findOption("--cipher", 0, OFCommandLine::FOM_First)) + { + opt_ciphersuites.clear(); + do + { + app.checkValue(cmd.getValue(current)); + if (NULL == (currentOpenSSL = DcmTLSTransportLayer::findOpenSSLCipherSuiteName(current))) + { + OFLOG_FATAL(storescpLogger, "ciphersuite '" << current << "' is unknown, known ciphersuites are:"); + unsigned long numSuites = DcmTLSTransportLayer::getNumberOfCipherSuites(); + for (unsigned long cs = 0; cs < numSuites; cs++) + { + OFLOG_FATAL(storescpLogger, " " << DcmTLSTransportLayer::getTLSCipherSuiteName(cs)); + } + return 1; + } + else + { + if (!opt_ciphersuites.empty()) opt_ciphersuites += ":"; + opt_ciphersuites += currentOpenSSL; + } + } while (cmd.findOption("--cipher", 0, OFCommandLine::FOM_Next)); + } + +#endif + +#ifndef DISABLE_PORT_PERMISSION_CHECK +#ifdef HAVE_GETEUID + /* if port is privileged we must be as well */ + if (opt_port < 1024) + { + if (geteuid() != 0) + { + OFLOG_FATAL(storescpLogger, "cannot listen on port " << opt_port << ", insufficient privileges"); + return 1; + } + } +#endif +#endif + + /* make sure data dictionary is loaded */ + if (!dcmDataDict.isDictionaryLoaded()) + { + OFLOG_WARN(storescpLogger, "no data dictionary loaded, check environment variable: " + << DCM_DICT_ENVIRONMENT_VARIABLE); + } + + /* if the output directory does not equal "." (default directory) */ + if (opt_outputDirectory != ".") + { + /* if there is a path separator at the end of the path, get rid of it */ + OFStandard::normalizeDirName(opt_outputDirectory, opt_outputDirectory); + + /* check if the specified directory exists and if it is a directory. + * If the output directory is invalid, dump an error message and terminate execution. + */ + if (!OFStandard::dirExists(opt_outputDirectory)) + { + OFLOG_FATAL(storescpLogger, "specified output directory does not exist"); + return 1; + } + } + + /* check if the output directory is writeable */ + if (!opt_ignore && !OFStandard::isWriteable(opt_outputDirectory)) + { + OFLOG_FATAL(storescpLogger, "specified output directory is not writeable"); + return 1; + } + +#ifdef HAVE_FORK + if (opt_forkMode) + DUL_requestForkOnTransportConnectionReceipt(argc, argv); +#elif defined(_WIN32) + if (opt_forkedChild) + { + // child process + DUL_markProcessAsForkedChild(); + + char buf[256]; + DWORD bytesRead = 0; + HANDLE hStdIn = GetStdHandle(STD_INPUT_HANDLE); + + // read socket handle number from stdin, i.e. the anonymous pipe + // to which our parent process has written the handle number. + if (ReadFile(hStdIn, buf, sizeof(buf), &bytesRead, NULL)) + { + // make sure buffer is zero terminated + buf[bytesRead] = '\0'; + dcmExternalSocketHandle.set(atoi(buf)); + } + else + { + OFLOG_ERROR(storescpLogger, "cannot read socket handle: " << GetLastError()); + return 1; + } + } + else + { + // parent process + if (opt_forkMode) + DUL_requestForkOnTransportConnectionReceipt(argc, argv); + } +#endif + + /* initialize network, i.e. create an instance of T_ASC_Network*. */ + OFCondition cond = ASC_initializeNetwork(NET_ACCEPTOR, OFstatic_cast(int, opt_port), opt_acse_timeout, &net); + if (cond.bad()) + { + OFLOG_ERROR(storescpLogger, "cannot create network: " << DimseCondition::dump(temp_str, cond)); + return 1; + } + + /* drop root privileges now and revert to the calling user id (if we are running as setuid root) */ + if (OFStandard::dropPrivileges().bad()) + { + OFLOG_FATAL(storescpLogger, "setuid() failed, maximum number of processes/threads for uid already running."); + return 1; + } + +#ifdef WITH_OPENSSL + DcmTLSTransportLayer *tLayer = NULL; + if (opt_secureConnection) + { + tLayer = new DcmTLSTransportLayer(DICOM_APPLICATION_ACCEPTOR, opt_readSeedFile); + if (tLayer == NULL) + { + OFLOG_FATAL(storescpLogger, "unable to create TLS transport layer"); + return 1; + } + + if (cmd.findOption("--add-cert-file", 0, OFCommandLine::FOM_First)) + { + do + { + app.checkValue(cmd.getValue(current)); + if (TCS_ok != tLayer->addTrustedCertificateFile(current, opt_keyFileFormat)) + { + OFLOG_WARN(storescpLogger, "unable to load certificate file '" << current << "', ignoring"); + } + } while (cmd.findOption("--add-cert-file", 0, OFCommandLine::FOM_Next)); + } + + if (cmd.findOption("--add-cert-dir", 0, OFCommandLine::FOM_First)) + { + do + { + app.checkValue(cmd.getValue(current)); + if (TCS_ok != tLayer->addTrustedCertificateDir(current, opt_keyFileFormat)) + { + OFLOG_WARN(storescpLogger, "unable to load certificates from directory '" << current << "', ignoring"); + } + } while (cmd.findOption("--add-cert-dir", 0, OFCommandLine::FOM_Next)); + } + + if (opt_dhparam && !(tLayer->setTempDHParameters(opt_dhparam))) + { + OFLOG_WARN(storescpLogger, "unable to load temporary DH parameter file '" << opt_dhparam << "', ignoring"); + } + + if (opt_passwd) tLayer->setPrivateKeyPasswd(opt_passwd); + + if (TCS_ok != tLayer->setPrivateKeyFile(opt_privateKeyFile, opt_keyFileFormat)) + { + OFLOG_WARN(storescpLogger, "unable to load private TLS key from '" << opt_privateKeyFile << "'"); + return 1; + } + if (TCS_ok != tLayer->setCertificateFile(opt_certificateFile, opt_keyFileFormat)) + { + OFLOG_WARN(storescpLogger, "unable to load certificate from '" << opt_certificateFile << "'"); + return 1; + } + if (! tLayer->checkPrivateKeyMatchesCertificate()) + { + OFLOG_WARN(storescpLogger, "private key '" << opt_privateKeyFile << "' and certificate '" << opt_certificateFile << "' do not match"); + return 1; + } + + if (TCS_ok != tLayer->setCipherSuites(opt_ciphersuites.c_str())) + { + OFLOG_WARN(storescpLogger, "unable to set selected cipher suites"); + return 1; + } + + tLayer->setCertificateVerification(opt_certVerification); + + cond = ASC_setTransportLayer(net, tLayer, 0); + if (cond.bad()) + { + OFLOG_ERROR(storescpLogger, DimseCondition::dump(temp_str, cond)); + return 1; + } + } +#endif + +#ifdef HAVE_WAITPID + // register signal handler + signal(SIGCHLD, sigChildHandler); +#endif + + while (cond.good()) + { + /* receive an association and acknowledge or reject it. If the association was */ + /* acknowledged, offer corresponding services and invoke one or more if required. */ + cond = acceptAssociation(net, asccfg); + + /* remove zombie child processes */ + cleanChildren(-1, OFFalse); +#ifdef WITH_OPENSSL + /* since storescp is usually terminated with SIGTERM or the like, + * we write back an updated random seed after every association handled. + */ + if (tLayer && opt_writeSeedFile) + { + if (tLayer->canWriteRandomSeed()) + { + if (!tLayer->writeRandomSeed(opt_writeSeedFile)) + OFLOG_WARN(storescpLogger, "cannot write random seed file '" << opt_writeSeedFile << "', ignoring"); + } + else + { + OFLOG_WARN(storescpLogger, "cannot write random seed, ignoring"); + } + } +#endif + // if running in inetd mode, we always terminate after one association + if (opt_inetd_mode) break; + + // if running in multi-process mode, always terminate child after one association + if (DUL_processIsForkedChild()) break; + } + + /* drop the network, i.e. free memory of T_ASC_Network* structure. This call */ + /* is the counterpart of ASC_initializeNetwork(...) which was called above. */ + cond = ASC_dropNetwork(&net); + if (cond.bad()) + { + OFLOG_ERROR(storescpLogger, DimseCondition::dump(temp_str, cond)); + return 1; + } + +#ifdef HAVE_WINSOCK_H + WSACleanup(); +#endif + +#ifdef WITH_OPENSSL + delete tLayer; +#endif + + return 0; +} + + +static OFCondition acceptAssociation(T_ASC_Network *net, DcmAssociationConfiguration& asccfg) +{ + char buf[BUFSIZ]; + T_ASC_Association *assoc; + OFCondition cond; + OFString sprofile; + OFString temp_str; + +#ifdef PRIVATE_STORESCP_VARIABLES + PRIVATE_STORESCP_VARIABLES +#endif + + const char* knownAbstractSyntaxes[] = + { + UID_VerificationSOPClass + }; + + const char* transferSyntaxes[] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; + int numTransferSyntaxes = 0; + + // try to receive an association. Here we either want to use blocking or + // non-blocking, depending on if the option --eostudy-timeout is set. + if( opt_endOfStudyTimeout == -1 ) + cond = ASC_receiveAssociation(net, &assoc, opt_maxPDU, NULL, NULL, opt_secureConnection); + else + cond = ASC_receiveAssociation(net, &assoc, opt_maxPDU, NULL, NULL, opt_secureConnection, DUL_NOBLOCK, OFstatic_cast(int, opt_endOfStudyTimeout)); + + if (cond.code() == DULC_FORKEDCHILD) + { + // OFLOG_DEBUG(storescpLogger, DimseCondition::dump(temp_str, cond)); + goto cleanup; + } + + // if some kind of error occurred, take care of it + if (cond.bad()) + { + // check what kind of error occurred. If no association was + // received, check if certain other conditions are met + if( cond == DUL_NOASSOCIATIONREQUEST ) + { + // If in addition to the fact that no association was received also option --eostudy-timeout is set + // and if at the same time there is still a study which is considered to be open (i.e. we were actually + // expecting to receive more objects that belong to this study) (this is the case if lastStudyInstanceUID + // does not equal NULL), we have to consider that all objects for the current study have been received. + // In such an "end-of-study" case, we might have to execute certain optional functions which were specified + // by the user through command line options passed to storescp. + if( opt_endOfStudyTimeout != -1 && !lastStudyInstanceUID.empty() ) + { + // indicate that the end-of-study-event occurred through a timeout event. + // This knowledge will be necessary in function renameOnEndOFStudy(). + endOfStudyThroughTimeoutEvent = OFTrue; + + // before we actually execute those optional functions, we need to determine the path and name + // of the subdirectory into which the DICOM files for the last study were written. + lastStudySubdirectoryPathAndName = subdirectoryPathAndName; + + // now we can finally handle end-of-study events which might have to be executed + executeEndOfStudyEvents(); + + // also, we need to clear lastStudyInstanceUID to indicate + // that the last study is not considered to be open any more. + lastStudyInstanceUID.clear(); + + // also, we need to clear subdirectoryPathAndName + subdirectoryPathAndName.clear(); + + // reset the endOfStudyThroughTimeoutEvent variable. + endOfStudyThroughTimeoutEvent = OFFalse; + } + } + // If something else was wrong we might have to dump an error message. + else + { + OFLOG_ERROR(storescpLogger, "Receiving Association failed: " << DimseCondition::dump(temp_str, cond)); + } + + // no matter what kind of error occurred, we need to do a cleanup + goto cleanup; + } + +#if defined(HAVE_FORK) || defined(_WIN32) + if (opt_forkMode) + OFLOG_INFO(storescpLogger, "Association Received in " << (DUL_processIsForkedChild() ? "child" : "parent") + << " process (pid: " << OFStandard::getProcessID() << ")"); + else +#endif + OFLOG_INFO(storescpLogger, "Association Received"); + + /* dump presentation contexts if required */ + if (opt_showPresentationContexts) + OFLOG_INFO(storescpLogger, "Parameters:" << OFendl << ASC_dumpParameters(temp_str, assoc->params, ASC_ASSOC_RQ)); + else + OFLOG_DEBUG(storescpLogger, "Parameters:" << OFendl << ASC_dumpParameters(temp_str, assoc->params, ASC_ASSOC_RQ)); + + if (opt_refuseAssociation) + { + T_ASC_RejectParameters rej = + { + ASC_RESULT_REJECTEDPERMANENT, + ASC_SOURCE_SERVICEUSER, + ASC_REASON_SU_NOREASON + }; + + OFLOG_INFO(storescpLogger, "Refusing Association (forced via command line)"); + cond = ASC_rejectAssociation(assoc, &rej); + if (cond.bad()) + { + OFLOG_ERROR(storescpLogger, "Association Reject Failed: " << DimseCondition::dump(temp_str, cond)); + } + goto cleanup; + } + + switch (opt_networkTransferSyntax) + { + case EXS_LittleEndianImplicit: + /* we only support Little Endian Implicit */ + transferSyntaxes[0] = UID_LittleEndianImplicitTransferSyntax; + numTransferSyntaxes = 1; + break; + case EXS_LittleEndianExplicit: + /* we prefer Little Endian Explicit */ + transferSyntaxes[0] = UID_LittleEndianExplicitTransferSyntax; + transferSyntaxes[1] = UID_BigEndianExplicitTransferSyntax; + transferSyntaxes[2] = UID_LittleEndianImplicitTransferSyntax; + numTransferSyntaxes = 3; + break; + case EXS_BigEndianExplicit: + /* we prefer Big Endian Explicit */ + transferSyntaxes[0] = UID_BigEndianExplicitTransferSyntax; + transferSyntaxes[1] = UID_LittleEndianExplicitTransferSyntax; + transferSyntaxes[2] = UID_LittleEndianImplicitTransferSyntax; + numTransferSyntaxes = 3; + break; + case EXS_JPEGProcess14SV1: + /* we prefer JPEGLossless:Hierarchical-1stOrderPrediction (default lossless) */ + transferSyntaxes[0] = UID_JPEGProcess14SV1TransferSyntax; + transferSyntaxes[1] = UID_LittleEndianExplicitTransferSyntax; + transferSyntaxes[2] = UID_BigEndianExplicitTransferSyntax; + transferSyntaxes[3] = UID_LittleEndianImplicitTransferSyntax; + numTransferSyntaxes = 4; + break; + case EXS_JPEGProcess1: + /* we prefer JPEGBaseline (default lossy for 8 bit images) */ + transferSyntaxes[0] = UID_JPEGProcess1TransferSyntax; + transferSyntaxes[1] = UID_LittleEndianExplicitTransferSyntax; + transferSyntaxes[2] = UID_BigEndianExplicitTransferSyntax; + transferSyntaxes[3] = UID_LittleEndianImplicitTransferSyntax; + numTransferSyntaxes = 4; + break; + case EXS_JPEGProcess2_4: + /* we prefer JPEGExtended (default lossy for 12 bit images) */ + transferSyntaxes[0] = UID_JPEGProcess2_4TransferSyntax; + transferSyntaxes[1] = UID_LittleEndianExplicitTransferSyntax; + transferSyntaxes[2] = UID_BigEndianExplicitTransferSyntax; + transferSyntaxes[3] = UID_LittleEndianImplicitTransferSyntax; + numTransferSyntaxes = 4; + break; + case EXS_JPEG2000LosslessOnly: + /* we prefer JPEG2000 Lossless */ + transferSyntaxes[0] = UID_JPEG2000LosslessOnlyTransferSyntax; + transferSyntaxes[1] = UID_LittleEndianExplicitTransferSyntax; + transferSyntaxes[2] = UID_BigEndianExplicitTransferSyntax; + transferSyntaxes[3] = UID_LittleEndianImplicitTransferSyntax; + numTransferSyntaxes = 4; + break; + case EXS_JPEG2000: + /* we prefer JPEG2000 Lossy */ + transferSyntaxes[0] = UID_JPEG2000TransferSyntax; + transferSyntaxes[1] = UID_LittleEndianExplicitTransferSyntax; + transferSyntaxes[2] = UID_BigEndianExplicitTransferSyntax; + transferSyntaxes[3] = UID_LittleEndianImplicitTransferSyntax; + numTransferSyntaxes = 4; + break; + case EXS_JPEGLSLossless: + /* we prefer JPEG-LS Lossless */ + transferSyntaxes[0] = UID_JPEGLSLosslessTransferSyntax; + transferSyntaxes[1] = UID_LittleEndianExplicitTransferSyntax; + transferSyntaxes[2] = UID_BigEndianExplicitTransferSyntax; + transferSyntaxes[3] = UID_LittleEndianImplicitTransferSyntax; + numTransferSyntaxes = 4; + break; + case EXS_JPEGLSLossy: + /* we prefer JPEG-LS Lossy */ + transferSyntaxes[0] = UID_JPEGLSLossyTransferSyntax; + transferSyntaxes[1] = UID_LittleEndianExplicitTransferSyntax; + transferSyntaxes[2] = UID_BigEndianExplicitTransferSyntax; + transferSyntaxes[3] = UID_LittleEndianImplicitTransferSyntax; + numTransferSyntaxes = 4; + break; + case EXS_MPEG2MainProfileAtMainLevel: + /* we prefer MPEG2 MP@ML */ + transferSyntaxes[0] = UID_MPEG2MainProfileAtMainLevelTransferSyntax; + transferSyntaxes[1] = UID_LittleEndianExplicitTransferSyntax; + transferSyntaxes[2] = UID_BigEndianExplicitTransferSyntax; + transferSyntaxes[3] = UID_LittleEndianImplicitTransferSyntax; + numTransferSyntaxes = 4; + break; + case EXS_MPEG2MainProfileAtHighLevel: + /* we prefer MPEG2 MP@HL */ + transferSyntaxes[0] = UID_MPEG2MainProfileAtHighLevelTransferSyntax; + transferSyntaxes[1] = UID_LittleEndianExplicitTransferSyntax; + transferSyntaxes[2] = UID_BigEndianExplicitTransferSyntax; + transferSyntaxes[3] = UID_LittleEndianImplicitTransferSyntax; + numTransferSyntaxes = 4; + break; + case EXS_MPEG4HighProfileLevel4_1: + /* we prefer MPEG4 HP/L4.1 */ + transferSyntaxes[0] = UID_MPEG4HighProfileLevel4_1TransferSyntax; + transferSyntaxes[1] = UID_LittleEndianExplicitTransferSyntax; + transferSyntaxes[2] = UID_BigEndianExplicitTransferSyntax; + transferSyntaxes[3] = UID_LittleEndianImplicitTransferSyntax; + numTransferSyntaxes = 4; + break; + case EXS_MPEG4BDcompatibleHighProfileLevel4_1: + /* we prefer MPEG4 BD HP/L4.1 */ + transferSyntaxes[0] = UID_MPEG4BDcompatibleHighProfileLevel4_1TransferSyntax; + transferSyntaxes[1] = UID_LittleEndianExplicitTransferSyntax; + transferSyntaxes[2] = UID_BigEndianExplicitTransferSyntax; + transferSyntaxes[3] = UID_LittleEndianImplicitTransferSyntax; + numTransferSyntaxes = 4; + break; + case EXS_RLELossless: + /* we prefer RLE Lossless */ + transferSyntaxes[0] = UID_RLELosslessTransferSyntax; + transferSyntaxes[1] = UID_LittleEndianExplicitTransferSyntax; + transferSyntaxes[2] = UID_BigEndianExplicitTransferSyntax; + transferSyntaxes[3] = UID_LittleEndianImplicitTransferSyntax; + numTransferSyntaxes = 4; + break; +#ifdef WITH_ZLIB + case EXS_DeflatedLittleEndianExplicit: + /* we prefer Deflated Explicit VR Little Endian */ + transferSyntaxes[0] = UID_DeflatedExplicitVRLittleEndianTransferSyntax; + transferSyntaxes[1] = UID_LittleEndianExplicitTransferSyntax; + transferSyntaxes[2] = UID_BigEndianExplicitTransferSyntax; + transferSyntaxes[3] = UID_LittleEndianImplicitTransferSyntax; + numTransferSyntaxes = 4; + break; +#endif + default: + if (opt_acceptAllXfers) + { + /* we accept all supported transfer syntaxes + * (similar to "AnyTransferSyntax" in "storescp.cfg") + */ + transferSyntaxes[0] = UID_JPEG2000TransferSyntax; + transferSyntaxes[1] = UID_JPEG2000LosslessOnlyTransferSyntax; + transferSyntaxes[2] = UID_JPEGProcess2_4TransferSyntax; + transferSyntaxes[3] = UID_JPEGProcess1TransferSyntax; + transferSyntaxes[4] = UID_JPEGProcess14SV1TransferSyntax; + transferSyntaxes[5] = UID_JPEGLSLossyTransferSyntax; + transferSyntaxes[6] = UID_JPEGLSLosslessTransferSyntax; + transferSyntaxes[7] = UID_RLELosslessTransferSyntax; + transferSyntaxes[8] = UID_MPEG2MainProfileAtMainLevelTransferSyntax; + transferSyntaxes[9] = UID_MPEG2MainProfileAtHighLevelTransferSyntax; + transferSyntaxes[10] = UID_MPEG4HighProfileLevel4_1TransferSyntax; + transferSyntaxes[11] = UID_MPEG4BDcompatibleHighProfileLevel4_1TransferSyntax; + transferSyntaxes[12] = UID_MPEG4HighProfileLevel4_2_For2DVideoTransferSyntax; + transferSyntaxes[13] = UID_MPEG4HighProfileLevel4_2_For3DVideoTransferSyntax; + transferSyntaxes[14] = UID_MPEG4StereoHighProfileLevel4_2TransferSyntax; + transferSyntaxes[15] = UID_DeflatedExplicitVRLittleEndianTransferSyntax; + if (gLocalByteOrder == EBO_LittleEndian) + { + transferSyntaxes[16] = UID_LittleEndianExplicitTransferSyntax; + transferSyntaxes[17] = UID_BigEndianExplicitTransferSyntax; + } else { + transferSyntaxes[16] = UID_BigEndianExplicitTransferSyntax; + transferSyntaxes[17] = UID_LittleEndianExplicitTransferSyntax; + } + transferSyntaxes[18] = UID_LittleEndianImplicitTransferSyntax; + numTransferSyntaxes = 19; + } else { + /* We prefer explicit transfer syntaxes. + * If we are running on a Little Endian machine we prefer + * LittleEndianExplicitTransferSyntax to BigEndianTransferSyntax. + */ + if (gLocalByteOrder == EBO_LittleEndian) /* defined in dcxfer.h */ + { + transferSyntaxes[0] = UID_LittleEndianExplicitTransferSyntax; + transferSyntaxes[1] = UID_BigEndianExplicitTransferSyntax; + } + else + { + transferSyntaxes[0] = UID_BigEndianExplicitTransferSyntax; + transferSyntaxes[1] = UID_LittleEndianExplicitTransferSyntax; + } + transferSyntaxes[2] = UID_LittleEndianImplicitTransferSyntax; + numTransferSyntaxes = 3; + } + break; + } + + if (opt_profileName) + { + /* perform name mangling for config file key */ + const unsigned char *c = OFreinterpret_cast(const unsigned char *, opt_profileName); + while (*c) + { + if (!isspace(*c)) sprofile += OFstatic_cast(char, toupper(*c)); + ++c; + } + + /* set presentation contexts as defined in config file */ + cond = asccfg.evaluateAssociationParameters(sprofile.c_str(), *assoc); + if (cond.bad()) + { + OFLOG_DEBUG(storescpLogger, DimseCondition::dump(temp_str, cond)); + goto cleanup; + } + } + else + { + /* accept the Verification SOP Class if presented */ + cond = ASC_acceptContextsWithPreferredTransferSyntaxes( assoc->params, knownAbstractSyntaxes, DIM_OF(knownAbstractSyntaxes), transferSyntaxes, numTransferSyntaxes); + if (cond.bad()) + { + OFLOG_DEBUG(storescpLogger, DimseCondition::dump(temp_str, cond)); + goto cleanup; + } + + /* the array of Storage SOP Class UIDs comes from dcuid.h */ + cond = ASC_acceptContextsWithPreferredTransferSyntaxes( assoc->params, dcmAllStorageSOPClassUIDs, numberOfAllDcmStorageSOPClassUIDs, transferSyntaxes, numTransferSyntaxes); + if (cond.bad()) + { + OFLOG_DEBUG(storescpLogger, DimseCondition::dump(temp_str, cond)); + goto cleanup; + } + + if (opt_promiscuous) + { + /* accept everything not known not to be a storage SOP class */ + cond = acceptUnknownContextsWithPreferredTransferSyntaxes( + assoc->params, transferSyntaxes, numTransferSyntaxes); + if (cond.bad()) + { + OFLOG_DEBUG(storescpLogger, DimseCondition::dump(temp_str, cond)); + goto cleanup; + } + } + } + + /* set our app title */ + ASC_setAPTitles(assoc->params, NULL, NULL, opt_respondingAETitle); + + /* acknowledge or reject this association */ + cond = ASC_getApplicationContextName(assoc->params, buf); + if ((cond.bad()) || strcmp(buf, UID_StandardApplicationContext) != 0) + { + /* reject: the application context name is not supported */ + T_ASC_RejectParameters rej = + { + ASC_RESULT_REJECTEDPERMANENT, + ASC_SOURCE_SERVICEUSER, + ASC_REASON_SU_APPCONTEXTNAMENOTSUPPORTED + }; + + OFLOG_INFO(storescpLogger, "Association Rejected: Bad Application Context Name: " << buf); + cond = ASC_rejectAssociation(assoc, &rej); + if (cond.bad()) + { + OFLOG_DEBUG(storescpLogger, DimseCondition::dump(temp_str, cond)); + } + goto cleanup; + + } + else if (opt_rejectWithoutImplementationUID && strlen(assoc->params->theirImplementationClassUID) == 0) + { + /* reject: the no implementation Class UID provided */ + T_ASC_RejectParameters rej = + { + ASC_RESULT_REJECTEDPERMANENT, + ASC_SOURCE_SERVICEUSER, + ASC_REASON_SU_NOREASON + }; + + OFLOG_INFO(storescpLogger, "Association Rejected: No Implementation Class UID provided"); + cond = ASC_rejectAssociation(assoc, &rej); + if (cond.bad()) + { + OFLOG_DEBUG(storescpLogger, DimseCondition::dump(temp_str, cond)); + } + goto cleanup; + } + else + { +#ifdef PRIVATE_STORESCP_CODE + PRIVATE_STORESCP_CODE +#endif + cond = ASC_acknowledgeAssociation(assoc); + if (cond.bad()) + { + OFLOG_ERROR(storescpLogger, DimseCondition::dump(temp_str, cond)); + goto cleanup; + } + OFLOG_INFO(storescpLogger, "Association Acknowledged (Max Send PDV: " << assoc->sendPDVLength << ")"); + if (ASC_countAcceptedPresentationContexts(assoc->params) == 0) + OFLOG_INFO(storescpLogger, " (but no valid presentation contexts)"); + /* dump the presentation contexts which have been accepted/refused */ + if (opt_showPresentationContexts) + OFLOG_INFO(storescpLogger, ASC_dumpParameters(temp_str, assoc->params, ASC_ASSOC_AC)); + else + OFLOG_DEBUG(storescpLogger, ASC_dumpParameters(temp_str, assoc->params, ASC_ASSOC_AC)); + } + +#ifdef BUGGY_IMPLEMENTATION_CLASS_UID_PREFIX + /* active the dcmPeerRequiresExactUIDCopy workaround code + * (see comments in dimse.h) for a implementation class UID + * prefix known to exhibit the buggy behaviour. + */ + if (0 == strncmp(assoc->params->theirImplementationClassUID, + BUGGY_IMPLEMENTATION_CLASS_UID_PREFIX, + strlen(BUGGY_IMPLEMENTATION_CLASS_UID_PREFIX))) + { + dcmEnableAutomaticInputDataCorrection.set(OFFalse); + dcmPeerRequiresExactUIDCopy.set(OFTrue); + } +#endif + + // store previous values for later use + lastCallingAETitle = callingAETitle; + lastCalledAETitle = calledAETitle; + lastCallingPresentationAddress = callingPresentationAddress; + // store calling and called aetitle in global variables to enable + // the --exec options using them. Enclose in quotation marks because + // aetitles may contain space characters. + DIC_AE callingTitle; + DIC_AE calledTitle; + if (ASC_getAPTitles(assoc->params, callingTitle, calledTitle, NULL).good()) + { + callingAETitle = "\""; + callingAETitle += OFSTRING_GUARD(callingTitle); + callingAETitle += "\""; + calledAETitle = "\""; + calledAETitle += OFSTRING_GUARD(calledTitle); + calledAETitle += "\""; + } + else + { + // should never happen + callingAETitle.clear(); + calledAETitle.clear(); + } + // store calling presentation address (i.e. remote hostname) + callingPresentationAddress = OFSTRING_GUARD(assoc->params->DULparams.callingPresentationAddress); + + /* now do the real work, i.e. receive DIMSE commands over the network connection */ + /* which was established and handle these commands correspondingly. In case of */ + /* storescp only C-ECHO-RQ and C-STORE-RQ commands can be processed. */ + cond = processCommands(assoc); + + if (cond == DUL_PEERREQUESTEDRELEASE) + { + OFLOG_INFO(storescpLogger, "Association Release"); + cond = ASC_acknowledgeRelease(assoc); + } + else if (cond == DUL_PEERABORTEDASSOCIATION) + { + OFLOG_INFO(storescpLogger, "Association Aborted"); + } + else + { + OFLOG_ERROR(storescpLogger, "DIMSE failure (aborting association): " << DimseCondition::dump(temp_str, cond)); + /* some kind of error so abort the association */ + cond = ASC_abortAssociation(assoc); + } + +cleanup: + + if (cond.code() == DULC_FORKEDCHILD) return cond; + + cond = ASC_dropSCPAssociation(assoc); + if (cond.bad()) + { + OFLOG_FATAL(storescpLogger, DimseCondition::dump(temp_str, cond)); + exit(1); + } + cond = ASC_destroyAssociation(&assoc); + if (cond.bad()) + { + OFLOG_FATAL(storescpLogger, DimseCondition::dump(temp_str, cond)); + exit(1); + } + + return cond; +} + + +static OFCondition +processCommands(T_ASC_Association * assoc) + /* + * This function receives DIMSE commands over the network connection + * and handles these commands correspondingly. Note that in case of + * storescp only C-ECHO-RQ and C-STORE-RQ commands can be processed. + * + * Parameters: + * assoc - [in] The association (network connection to another DICOM application). + */ +{ + OFCondition cond = EC_Normal; + T_DIMSE_Message msg; + T_ASC_PresentationContextID presID = 0; + DcmDataset *statusDetail = NULL; + + // start a loop to be able to receive more than one DIMSE command + while( cond == EC_Normal || cond == DIMSE_NODATAAVAILABLE || cond == DIMSE_OUTOFRESOURCES ) + { + // receive a DIMSE command over the network + if( opt_endOfStudyTimeout == -1 ) + cond = DIMSE_receiveCommand(assoc, DIMSE_BLOCKING, 0, &presID, &msg, &statusDetail); + else + cond = DIMSE_receiveCommand(assoc, DIMSE_NONBLOCKING, OFstatic_cast(int, opt_endOfStudyTimeout), &presID, &msg, &statusDetail); + + // check what kind of error occurred. If no data was + // received, check if certain other conditions are met + if( cond == DIMSE_NODATAAVAILABLE ) + { + // If in addition to the fact that no data was received also option --eostudy-timeout is set and + // if at the same time there is still a study which is considered to be open (i.e. we were actually + // expecting to receive more objects that belong to this study) (this is the case if lastStudyInstanceUID + // does not equal NULL), we have to consider that all objects for the current study have been received. + // In such an "end-of-study" case, we might have to execute certain optional functions which were specified + // by the user through command line options passed to storescp. + if( opt_endOfStudyTimeout != -1 && !lastStudyInstanceUID.empty() ) + { + // indicate that the end-of-study-event occurred through a timeout event. + // This knowledge will be necessary in function renameOnEndOFStudy(). + endOfStudyThroughTimeoutEvent = OFTrue; + + // before we actually execute those optional functions, we need to determine the path and name + // of the subdirectory into which the DICOM files for the last study were written. + lastStudySubdirectoryPathAndName = subdirectoryPathAndName; + + // now we can finally handle end-of-study events which might have to be executed + executeEndOfStudyEvents(); + + // also, we need to clear lastStudyInstanceUID to indicate + // that the last study is not considered to be open any more. + lastStudyInstanceUID.clear(); + + // also, we need to clear subdirectoryPathAndName + subdirectoryPathAndName.clear(); + + // reset the endOfStudyThroughTimeoutEvent variable. + endOfStudyThroughTimeoutEvent = OFFalse; + } + } + + // if the command which was received has extra status + // detail information, dump this information + if (statusDetail != NULL) + { + OFLOG_DEBUG(storescpLogger, "Status Detail:" << OFendl << DcmObject::PrintHelper(*statusDetail)); + delete statusDetail; + } + + // check if peer did release or abort, or if we have a valid message + if (cond == EC_Normal) + { + // in case we received a valid message, process this command + // note that storescp can only process a C-ECHO-RQ and a C-STORE-RQ + switch (msg.CommandField) + { + case DIMSE_C_ECHO_RQ: + // process C-ECHO-Request + cond = echoSCP(assoc, &msg, presID); + break; + case DIMSE_C_STORE_RQ: + // process C-STORE-Request + cond = storeSCP(assoc, &msg, presID); + break; + default: + OFString tempStr; + // we cannot handle this kind of message + cond = DIMSE_BADCOMMANDTYPE; + OFLOG_ERROR(storescpLogger, "Expected C-ECHO or C-STORE request but received DIMSE command 0x" + << STD_NAMESPACE hex << STD_NAMESPACE setfill('0') << STD_NAMESPACE setw(4) + << OFstatic_cast(unsigned, msg.CommandField)); + OFLOG_DEBUG(storescpLogger, DIMSE_dumpMessage(tempStr, msg, DIMSE_INCOMING, NULL, presID)); + break; + } + } + } + return cond; +} + + +static OFCondition echoSCP( T_ASC_Association * assoc, T_DIMSE_Message * msg, T_ASC_PresentationContextID presID) +{ + OFString temp_str; + // assign the actual information of the C-Echo-RQ command to a local variable + T_DIMSE_C_EchoRQ *req = &msg->msg.CEchoRQ; + if (storescpLogger.isEnabledFor(OFLogger::DEBUG_LOG_LEVEL)) + { + OFLOG_INFO(storescpLogger, "Received Echo Request"); + OFLOG_DEBUG(storescpLogger, DIMSE_dumpMessage(temp_str, *req, DIMSE_INCOMING, NULL, presID)); + } else { + OFLOG_INFO(storescpLogger, "Received Echo Request (MsgID " << req->MessageID << ")"); + } + + /* the echo succeeded !! */ + OFCondition cond = DIMSE_sendEchoResponse(assoc, presID, req, STATUS_Success, NULL); + if (cond.bad()) + { + OFLOG_ERROR(storescpLogger, "Echo SCP Failed: " << DimseCondition::dump(temp_str, cond)); + } + return cond; +} + +// substitute non-ASCII characters with ASCII "equivalents" +static void mapCharacterAndAppendToString(Uint8 c, + OFString &output) +{ + static const char *latin1_table[] = + { + "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", // Codes 0-15 + "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", // Codes 16-31 + "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", // Codes 32-47 + "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "_", "_", "_", "_", "_", "_", // Codes 48-63 + "_", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", // Codes 64-79 + "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "_", "_", "_", "_", "_", // Codes 80-95 + "_", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", // Codes 96-111 + "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "_", "_", "_", "_", "_", // Codes 112-127 + "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", // Codes 128-143 + "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", // Codes 144-159 + "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", // Codes 160-175 + "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", // Codes 176-191 + "A", "A", "A", "A", "Ae","A", "A", "C", "E", "E", "E", "E", "I", "I", "I", "I", // Codes 192-107 + "D", "N", "O", "O", "O", "O", "Oe","_", "O", "U", "U", "U", "Ue","Y", "_", "ss",// Codes 108-123 + "a", "a", "a", "a", "ae","a", "a", "c", "e", "e", "e", "e", "i", "i", "i", "i", // Codes 124-141 + "d", "n", "o", "o", "o", "o", "oe","_", "o", "u", "u", "u", "ue","y", "_", "y" // Codes 142-157 + }; + output += latin1_table[c]; +} + +struct StoreCallbackData +{ + char* imageFileName; + DcmFileFormat* dcmff; + T_ASC_Association* assoc; +}; + + +static void +storeSCPCallback( + void *callbackData, + T_DIMSE_StoreProgress *progress, + T_DIMSE_C_StoreRQ *req, + char * /*imageFileName*/, DcmDataset **imageDataSet, + T_DIMSE_C_StoreRSP *rsp, + DcmDataset **statusDetail) + /* + * This function.is used to indicate progress when storescp receives instance data over the + * network. On the final call to this function (identified by progress->state == DIMSE_StoreEnd) + * this function will store the data set which was received over the network to a file. + * Earlier calls to this function will simply cause some information to be dumped to stdout. + * + * Parameters: + * callbackData - [in] data for this callback function + * progress - [in] The state of progress. (identifies if this is the initial or final call + * to this function, or a call in between these two calls. + * req - [in] The original store request message. + * imageFileName - [in] The path to and name of the file the information shall be written to. + * imageDataSet - [in] The data set which shall be stored in the image file + * rsp - [inout] the C-STORE-RSP message (will be sent after the call to this function) + * statusDetail - [inout] This variable can be used to capture detailed information with regard to + * the status information which is captured in the status element (0000,0900). Note + * that this function does specify any such information, the pointer will be set to NULL. + */ +{ + DIC_UI sopClass; + DIC_UI sopInstance; + + // determine if the association shall be aborted + if( (opt_abortDuringStore && progress->state != DIMSE_StoreBegin) || + (opt_abortAfterStore && progress->state == DIMSE_StoreEnd) ) + { + OFLOG_INFO(storescpLogger, "ABORT initiated (due to command line options)"); + ASC_abortAssociation((OFstatic_cast(StoreCallbackData*, callbackData))->assoc); + rsp->DimseStatus = STATUS_STORE_Refused_OutOfResources; + return; + } + + // if opt_sleepAfter is set, the user requires that the application shall + // sleep a certain amount of seconds after having received one PDU. + if (opt_sleepDuring > 0) + { + OFStandard::sleep(OFstatic_cast(unsigned int, opt_sleepDuring)); + } + + // dump some information if required (depending on the progress state) + // We can't use oflog for the PDU output, but we use a special logger for + // generating this output. If it is set to level "INFO" we generate the + // output, if it's set to "DEBUG" then we'll assume that there is debug output + // generated for each PDU elsewhere. + OFLogger progressLogger = OFLog::getLogger("dcmtk.apps." OFFIS_CONSOLE_APPLICATION ".progress"); + if (progressLogger.getChainedLogLevel() == OFLogger::INFO_LOG_LEVEL) + { + switch (progress->state) + { + case DIMSE_StoreBegin: + COUT << "RECV: "; + break; + case DIMSE_StoreEnd: + COUT << OFendl; + break; + default: + COUT << '.'; + break; + } + COUT.flush(); + } + + // if this is the final call of this function, save the data which was received to a file + // (note that we could also save the image somewhere else, put it in database, etc.) + if (progress->state == DIMSE_StoreEnd) + { + OFString tmpStr; + + // do not send status detail information + *statusDetail = NULL; + + // remember callback data + StoreCallbackData *cbdata = OFstatic_cast(StoreCallbackData *, callbackData); + + // Concerning the following line: an appropriate status code is already set in the resp structure, + // it need not be success. For example, if the caller has already detected an out of resources problem + // then the status will reflect this. The callback function is still called to allow cleanup. + //rsp->DimseStatus = STATUS_Success; + + // we want to write the received information to a file only if this information + // is present and the options opt_bitPreserving and opt_ignore are not set. + if ((imageDataSet != NULL) && (*imageDataSet != NULL) && !opt_bitPreserving && !opt_ignore) + { + OFString fileName; + + // in case one of the --sort-xxx options is set, we need to perform some particular steps to + // determine the actual name of the output file + if (opt_sortStudyMode != ESM_None) + { + // determine the study instance UID in the (current) DICOM object that has just been received + OFString currentStudyInstanceUID; + if ((*imageDataSet)->findAndGetOFString(DCM_StudyInstanceUID, currentStudyInstanceUID).bad() || currentStudyInstanceUID.empty()) + { + OFLOG_ERROR(storescpLogger, "element StudyInstanceUID " << DCM_StudyInstanceUID << " absent or empty in data set"); + rsp->DimseStatus = STATUS_STORE_Error_CannotUnderstand; + return; + } + + // if --sort-on-patientname is active, we need to extract the + // patient's name (format: last_name^first_name) + OFString currentPatientName; + if (opt_sortStudyMode == ESM_PatientName) + { + OFString tmpName; + if ((*imageDataSet)->findAndGetOFString(DCM_PatientName, tmpName).bad() || tmpName.empty()) + { + // default if patient name is missing or empty + tmpName = "ANONYMOUS"; + OFLOG_WARN(storescpLogger, "element PatientName " << DCM_PatientName << " absent or empty in data set, using '" + << tmpName << "' instead"); + } + + /* substitute non-ASCII characters in patient name to ASCII "equivalent" */ + const size_t length = tmpName.length(); + for (size_t i = 0; i < length; i++) + mapCharacterAndAppendToString(tmpName[i], currentPatientName); + } + + // if this is the first DICOM object that was received or if the study instance UID in the + // current DICOM object does not equal the last object's study instance UID we need to create + // a new subdirectory in which the current DICOM object will be stored + if (lastStudyInstanceUID.empty() || (lastStudyInstanceUID != currentStudyInstanceUID)) + { + // if lastStudyInstanceUID is non-empty, we have just completed receiving all objects for one + // study. In such a case, we need to set a certain indicator variable (lastStudySubdirectoryPathAndName), + // so that we know that executeOnEndOfStudy() might have to be executed later. In detail, this indicator + // variable will contain the path and name of the last study's subdirectory, so that we can still remember + // this directory, when we execute executeOnEndOfStudy(). The memory that is allocated for this variable + // here will be freed after the execution of executeOnEndOfStudy(). + if (!lastStudyInstanceUID.empty()) + lastStudySubdirectoryPathAndName = subdirectoryPathAndName; + + // create the new lastStudyInstanceUID value according to the value in the current DICOM object + lastStudyInstanceUID = currentStudyInstanceUID; + + // get the current time (needed for subdirectory name) + OFDateTime dateTime; + dateTime.setCurrentDateTime(); + + // create a name for the new subdirectory. + char timestamp[32]; + sprintf(timestamp, "%04u%02u%02u_%02u%02u%02u%03u", + dateTime.getDate().getYear(), dateTime.getDate().getMonth(), dateTime.getDate().getDay(), + dateTime.getTime().getHour(), dateTime.getTime().getMinute(), dateTime.getTime().getIntSecond(), dateTime.getTime().getMilliSecond()); + + OFString subdirectoryName; + switch (opt_sortStudyMode) + { + case ESM_Timestamp: + // pattern: "[prefix]_[YYYYMMDD]_[HHMMSSMMM]" + subdirectoryName = opt_sortStudyDirPrefix; + if (!subdirectoryName.empty()) + subdirectoryName += '_'; + subdirectoryName += timestamp; + break; + case ESM_StudyInstanceUID: + // pattern: "[prefix]_[Study Instance UID]" + subdirectoryName = opt_sortStudyDirPrefix; + if (!subdirectoryName.empty()) + subdirectoryName += '_'; + subdirectoryName += currentStudyInstanceUID; + break; + case ESM_PatientName: + // pattern: "[Patient's Name]_[YYYYMMDD]_[HHMMSSMMM]" + subdirectoryName = currentPatientName; + subdirectoryName += '_'; + subdirectoryName += timestamp; + break; + case ESM_None: + break; + } + + // create subdirectoryPathAndName (string with full path to new subdirectory) + OFStandard::combineDirAndFilename(subdirectoryPathAndName, OFStandard::getDirNameFromPath(tmpStr, cbdata->imageFileName), subdirectoryName); + + // check if the subdirectory already exists + // if it already exists dump a warning + if( OFStandard::dirExists(subdirectoryPathAndName) ) + OFLOG_WARN(storescpLogger, "subdirectory for study already exists: " << subdirectoryPathAndName); + else + { + // if it does not exist create it + OFLOG_INFO(storescpLogger, "creating new subdirectory for study: " << subdirectoryPathAndName); +#ifdef HAVE_WINDOWS_H + if( _mkdir( subdirectoryPathAndName.c_str() ) == -1 ) +#else + if( mkdir( subdirectoryPathAndName.c_str(), S_IRWXU | S_IRWXG | S_IRWXO ) == -1 ) +#endif + { + OFLOG_ERROR(storescpLogger, "could not create subdirectory for study: " << subdirectoryPathAndName); + rsp->DimseStatus = STATUS_STORE_Error_CannotUnderstand; + return; + } + // all objects of a study have been received, so a new subdirectory is started. + // ->timename counter can be reset, because the next filename can't cause a duplicate. + // if no reset would be done, files of a new study (->new directory) would start with a counter in filename + if (opt_timeNames) + timeNameCounter = -1; + } + } + + // integrate subdirectory name into file name (note that cbdata->imageFileName currently contains both + // path and file name; however, the path refers to the output directory captured in opt_outputDirectory) + OFStandard::combineDirAndFilename(fileName, subdirectoryPathAndName, OFStandard::getFilenameFromPath(tmpStr, cbdata->imageFileName)); + + // update global variable outputFileNameArray + // (might be used in executeOnReception() and renameOnEndOfStudy) + outputFileNameArray.push_back(tmpStr); + } + // if no --sort-xxx option is set, the determination of the output file name is simple + else + { + fileName = cbdata->imageFileName; + + // update global variables outputFileNameArray + // (might be used in executeOnReception() and renameOnEndOfStudy) + outputFileNameArray.push_back(OFStandard::getFilenameFromPath(tmpStr, fileName)); + } + + // determine the transfer syntax which shall be used to write the information to the file + E_TransferSyntax xfer = opt_writeTransferSyntax; + if (xfer == EXS_Unknown) xfer = (*imageDataSet)->getOriginalXfer(); + + // store file either with meta header or as pure dataset + OFLOG_INFO(storescpLogger, "storing DICOM file: " << fileName); + if (OFStandard::fileExists(fileName)) + { + OFLOG_WARN(storescpLogger, "DICOM file already exists, overwriting: " << fileName); + } + OFCondition cond = cbdata->dcmff->saveFile(fileName.c_str(), xfer, opt_sequenceType, opt_groupLength, + opt_paddingType, OFstatic_cast(Uint32, opt_filepad), OFstatic_cast(Uint32, opt_itempad), + (opt_useMetaheader) ? EWM_fileformat : EWM_dataset); + if (cond.bad()) + { + OFLOG_ERROR(storescpLogger, "cannot write DICOM file: " << fileName << ": " << cond.text()); + rsp->DimseStatus = STATUS_STORE_Refused_OutOfResources; + } + + // check the image to make sure it is consistent, i.e. that its sopClass and sopInstance correspond + // to those mentioned in the request. If not, set the status in the response message variable. + if (rsp->DimseStatus == STATUS_Success) + { + // which SOP class and SOP instance ? + if (!DU_findSOPClassAndInstanceInDataSet(*imageDataSet, sopClass, sopInstance, opt_correctUIDPadding)) + { + OFLOG_ERROR(storescpLogger, "bad DICOM file: " << fileName); + rsp->DimseStatus = STATUS_STORE_Error_CannotUnderstand; + } + else if (strcmp(sopClass, req->AffectedSOPClassUID) != 0) + { + rsp->DimseStatus = STATUS_STORE_Error_DataSetDoesNotMatchSOPClass; + } + else if (strcmp(sopInstance, req->AffectedSOPInstanceUID) != 0) + { + rsp->DimseStatus = STATUS_STORE_Error_DataSetDoesNotMatchSOPClass; + } + } + } + + // in case opt_bitPreserving is set, do some other things + if( opt_bitPreserving ) + { + // we need to set outputFileNameArray and outputFileNameArrayCnt to be + // able to perform the placeholder substitution in executeOnReception() + outputFileNameArray.push_back(OFStandard::getFilenameFromPath(tmpStr, cbdata->imageFileName)); + } + } +} + + +static OFCondition storeSCP( + T_ASC_Association *assoc, + T_DIMSE_Message *msg, + T_ASC_PresentationContextID presID) + /* + * This function processes a DIMSE C-STORE-RQ command that was + * received over the network connection. + * + * Parameters: + * assoc - [in] The association (network connection to another DICOM application). + * msg - [in] The DIMSE C-STORE-RQ message that was received. + * presID - [in] The ID of the presentation context which was specified in the PDV which contained + * the DIMSE command. + */ +{ + OFCondition cond = EC_Normal; + T_DIMSE_C_StoreRQ *req; + char imageFileName[2048]; + + // assign the actual information of the C-STORE-RQ command to a local variable + req = &msg->msg.CStoreRQ; + + // if opt_ignore is set, the user requires that the data shall be received but not + // stored. in this case, we want to create a corresponding temporary filename for + // a file in which the data shall be stored temporarily. If this is not the case, + // create a real filename (consisting of path and filename) for a real file. + if (opt_ignore) + { +#ifdef _WIN32 + tmpnam(imageFileName); +#else + strcpy(imageFileName, NULL_DEVICE_NAME); +#endif + } + else + { + // 3 possibilities: create unique filenames (fn), create timestamp fn, create fn from SOP Instance UIDs + if (opt_uniqueFilenames) + { + // create unique filename by generating a temporary UID and using ".X." as an infix + char buf[70]; + dcmGenerateUniqueIdentifier(buf); + sprintf(imageFileName, "%s%c%s.X.%s%s", opt_outputDirectory.c_str(), PATH_SEPARATOR, dcmSOPClassUIDToModality(req->AffectedSOPClassUID, "UNKNOWN"), + buf, opt_fileNameExtension.c_str()); + } + else if (opt_timeNames) + { + // create a name for the new file. pattern: "[YYYYMMDDHHMMSSMMM]_[NUMBER].MODALITY[EXTENSION]" (use current datetime) + // get the current time (needed for file name) + OFDateTime dateTime; + dateTime.setCurrentDateTime(); + // used to hold prospective filename + char cmpFileName[2048]; + // next if/else block generates prospective filename, that is compared to last written filename + if (timeNameCounter == -1) + { + // timeNameCounter not set -> last written filename has to be without "serial number" + sprintf(cmpFileName, "%04u%02u%02u%02u%02u%02u%03u.%s%s", + dateTime.getDate().getYear(), dateTime.getDate().getMonth(), dateTime.getDate().getDay(), + dateTime.getTime().getHour(), dateTime.getTime().getMinute(), dateTime.getTime().getIntSecond(), dateTime.getTime().getMilliSecond(), + dcmSOPClassUIDToModality(req->AffectedSOPClassUID, "UNKNOWN"), opt_fileNameExtension.c_str()); + } + else + { + // counter was active before, so generate filename with "serial number" for comparison + sprintf(cmpFileName, "%04u%02u%02u%02u%02u%02u%03u_%04u.%s%s", // millisecond version + dateTime.getDate().getYear(), dateTime.getDate().getMonth(), dateTime.getDate().getDay(), + dateTime.getTime().getHour(), dateTime.getTime().getMinute(), dateTime.getTime().getIntSecond(), dateTime.getTime().getMilliSecond(), + timeNameCounter, dcmSOPClassUIDToModality(req->AffectedSOPClassUID, "UNKNOWN"), opt_fileNameExtension.c_str()); + } + if ( (outputFileNameArray.size()!=0) && (outputFileNameArray.back() == cmpFileName) ) + { + // if this is not the first run and the prospective filename is equal to the last written filename + // generate one with a serial number (incremented by 1) + timeNameCounter++; + sprintf(imageFileName, "%s%c%04u%02u%02u%02u%02u%02u%03u_%04u.%s%s", opt_outputDirectory.c_str(), PATH_SEPARATOR, // millisecond version + dateTime.getDate().getYear(), dateTime.getDate().getMonth(), dateTime.getDate().getDay(), + dateTime.getTime().getHour(), dateTime.getTime().getMinute(), dateTime.getTime().getIntSecond(), dateTime.getTime().getMilliSecond(), + timeNameCounter, dcmSOPClassUIDToModality(req->AffectedSOPClassUID, "UNKNOWN"), opt_fileNameExtension.c_str()); + } + else + { + // first run or filenames are different: create filename without serial number + sprintf(imageFileName, "%s%c%04u%02u%02u%02u%02u%02u%03u.%s%s", opt_outputDirectory.c_str(), PATH_SEPARATOR, // millisecond version + dateTime.getDate().getYear(), dateTime.getDate().getMonth(), dateTime.getDate().getDay(), + dateTime.getTime().getHour(), dateTime.getTime().getMinute(),dateTime.getTime().getIntSecond(), dateTime.getTime().getMilliSecond(), + dcmSOPClassUIDToModality(req->AffectedSOPClassUID, "UNKNOWN"), opt_fileNameExtension.c_str()); + // reset counter, because timestamp and therefore filename has changed + timeNameCounter = -1; + } + } + else + { + // don't create new UID, use the study instance UID as found in object + sprintf(imageFileName, "%s%c%s.%s%s", opt_outputDirectory.c_str(), PATH_SEPARATOR, dcmSOPClassUIDToModality(req->AffectedSOPClassUID, "UNKNOWN"), + req->AffectedSOPInstanceUID, opt_fileNameExtension.c_str()); + } + } + + // dump some information if required + OFString str; + if (storescpLogger.isEnabledFor(OFLogger::DEBUG_LOG_LEVEL)) + { + OFLOG_INFO(storescpLogger, "Received Store Request"); + OFLOG_DEBUG(storescpLogger, DIMSE_dumpMessage(str, *req, DIMSE_INCOMING, NULL, presID)); + } else { + OFLOG_INFO(storescpLogger, "Received Store Request (MsgID " << req->MessageID << ", " + << dcmSOPClassUIDToModality(req->AffectedSOPClassUID, "OT") << ")"); + } + + // initialize some variables + StoreCallbackData callbackData; + callbackData.assoc = assoc; + callbackData.imageFileName = imageFileName; + DcmFileFormat dcmff; + callbackData.dcmff = &dcmff; + + // store SourceApplicationEntityTitle in metaheader + if (assoc && assoc->params) + { + const char *aet = assoc->params->DULparams.callingAPTitle; + if (aet) dcmff.getMetaInfo()->putAndInsertString(DCM_SourceApplicationEntityTitle, aet); + } + + // define an address where the information which will be received over the network will be stored + DcmDataset *dset = dcmff.getDataset(); + + // if opt_bitPreserving is set, the user requires that the data shall be + // written exactly as it was received. Depending on this option, function + // DIMSE_storeProvider must be called with certain parameters. + if (opt_bitPreserving) + { + cond = DIMSE_storeProvider(assoc, presID, req, imageFileName, opt_useMetaheader, NULL, + storeSCPCallback, &callbackData, opt_blockMode, opt_dimse_timeout); + } + else + { + cond = DIMSE_storeProvider(assoc, presID, req, NULL, opt_useMetaheader, &dset, + storeSCPCallback, &callbackData, opt_blockMode, opt_dimse_timeout); + } + + // if some error occurred, dump corresponding information and remove the outfile if necessary + if (cond.bad()) + { + OFString temp_str; + OFLOG_ERROR(storescpLogger, "Store SCP Failed: " << DimseCondition::dump(temp_str, cond)); + // remove file + if (!opt_ignore) + { + if (strcmp(imageFileName, NULL_DEVICE_NAME) != 0) + OFStandard::deleteFile(imageFileName); + } + } +#ifdef _WIN32 + else if (opt_ignore) + { + if (strcmp(imageFileName, NULL_DEVICE_NAME) != 0) + OFStandard::deleteFile(imageFileName); // delete the temporary file + } +#endif + + // if everything was successful so far and option --exec-on-reception is set, + // we want to execute a certain command which was passed to the application + if( cond.good() && opt_execOnReception != NULL ) + executeOnReception(); + + // if everything was successful so far, go ahead and handle possible end-of-study events + if( cond.good() ) + executeEndOfStudyEvents(); + + // if opt_sleepAfter is set, the user requires that the application shall + // sleep a certain amount of seconds after storing the instance data. + if (opt_sleepAfter > 0) + { + OFStandard::sleep(OFstatic_cast(unsigned int, opt_sleepAfter)); + } + + // return return value + return cond; +} + + +static void executeEndOfStudyEvents() + /* + * This function deals with the execution of end-of-study-events. In detail, + * events that need to take place are specified by the user through certain + * command line options. The options that define these end-of-study-events + * are "--rename-on-eostudy" and "--exec-on-eostudy". + * + * Parameters: + * none. + */ +{ + // if option --rename-on-eostudy is set and variable lastStudySubdirectoryPathAndName + // does not equal NULL (i.e. we received all objects that belong to one study, or - in + // other words - it is the end of one study) we want to rename the output files that + // belong to the last study. (Note that these files are captured in outputFileNameArray) + if( opt_renameOnEndOfStudy && !lastStudySubdirectoryPathAndName.empty() ) + renameOnEndOfStudy(); + + // if option --exec-on-eostudy is set and variable lastStudySubdirectoryPathAndName does + // not equal NULL (i.e. we received all objects that belong to one study, or - in other + // words - it is the end of one study) we want to execute a certain command which was + // passed to the application + if( opt_execOnEndOfStudy != NULL && !lastStudySubdirectoryPathAndName.empty() ) + executeOnEndOfStudy(); + + lastStudySubdirectoryPathAndName.clear(); +} + + +static void executeOnReception() + /* + * This function deals with the execution of the command line which was passed + * to option --exec-on-reception of the storescp. This command line is captured + * in opt_execOnReception. Note that the command line can contain the placeholders + * PATH_PLACEHOLDER and FILENAME_PLACEHOLDER which need to be substituted before the command line is actually + * executed. PATH_PLACEHOLDER will be substituted by the path to the output directory into which + * the last file was written; FILENAME_PLACEHOLDER will be substituted by the filename of the last + * file which was written. + * + * Parameters: + * none. + */ +{ + OFString cmd = opt_execOnReception; + + // in case a file was actually written + if( !opt_ignore ) + { + // perform substitution for placeholder #p (depending on presence of any --sort-xxx option) + OFString dir = (opt_sortStudyMode == ESM_None) ? opt_outputDirectory : subdirectoryPathAndName; + cmd = replaceChars( cmd, OFString(PATH_PLACEHOLDER), dir ); + + // perform substitution for placeholder #f; note that outputFileNameArray.back() + // always contains the name of the file (without path) which was written last. + OFString outputFileName = outputFileNameArray.back(); + cmd = replaceChars( cmd, OFString(FILENAME_PLACEHOLDER), outputFileName ); + } + + // perform substitution for placeholder #a + cmd = replaceChars( cmd, OFString(CALLING_AETITLE_PLACEHOLDER), callingAETitle ); + + // perform substitution for placeholder #c + cmd = replaceChars( cmd, OFString(CALLED_AETITLE_PLACEHOLDER), calledAETitle ); + + // perform substitution for placeholder #r + cmd = replaceChars( cmd, OFString(CALLING_PRESENTATION_ADDRESS_PLACEHOLDER), callingPresentationAddress ); + + // Execute command in a new process + executeCommand( cmd ); +} + + +static void renameOnEndOfStudy() + /* + * This function deals with renaming the last study's output files. In detail, these file's + * current filenames will be changed to a filename that corresponds to the pattern [modality- + * prefix][consecutive-numbering]. The current filenames of all files that belong to the study + * are captured in outputFileNameArray. The new filenames will be calculated within this + * function: The [modality-prefix] will be taken from the old filename, + * [consecutive-numbering] is a consecutively numbered, 6 digit number which will be calculated + * starting from 000001. + * + * Parameters: + * none. + */ +{ + int counter = 1; + + OFListIterator(OFString) first = outputFileNameArray.begin(); + OFListIterator(OFString) last = outputFileNameArray.end(); + + // before we deal with all the filenames which are included in the array, we need to distinguish + // two different cases: If endOfStudyThroughTimeoutEvent is not true, the last filename in the array + // refers to a file that belongs to a new study of which the first object was just received. (In this + // case there are at least two filenames in the array). Then, this last filename is - at the end of the + // following loop - not supposed to be deleted from the array. If endOfStudyThroughTimeoutEvent is true, + // all filenames that are captured in the array, refer to files that belong to the same study. Hence, + // all of these files shall be renamed and all of the filenames within the array shall be deleted. + if( !endOfStudyThroughTimeoutEvent ) --last; + + // rename all files that belong to the last study + while (first != last) + { + // determine the new file name: The first two characters of the old file name make up the [modality-prefix]. + // The value for [consecutive-numbering] will be determined using the counter variable. + char modalityId[3]; + char newFileName[9]; + if (opt_timeNames) + { + // modality prefix are the first 2 characters after serial number (if present) + size_t serialPos = (*first).find("_"); + if (serialPos != OFString_npos) + { + //serial present: copy modality prefix (skip serial: 1 digit "_" + 4 digits serial + 1 digit ".") + OFStandard::strlcpy( modalityId, (*first).substr(serialPos+6, 2).c_str(), 3 ); + } + else + { + //serial not present, copy starts directly after first "." (skip 17 for timestamp, one for ".") + OFStandard::strlcpy( modalityId, (*first).substr(18, 2).c_str(), 3 ); + } + } + else + { + OFStandard::strlcpy( modalityId, (*first).c_str(), 3 ); + } + sprintf( newFileName, "%s%06d", modalityId, counter ); + + // create two strings containing path and file name for + // the current filename and the future filename + OFString oldPathAndFileName; + oldPathAndFileName = lastStudySubdirectoryPathAndName; + oldPathAndFileName += PATH_SEPARATOR; + oldPathAndFileName += *first; + + OFString newPathAndFileName; + newPathAndFileName = lastStudySubdirectoryPathAndName; + newPathAndFileName += PATH_SEPARATOR; + newPathAndFileName += newFileName; + + // rename file + if( rename( oldPathAndFileName.c_str(), newPathAndFileName.c_str() ) != 0 ) + OFLOG_WARN(storescpLogger, "cannot rename file '" << oldPathAndFileName << "' to '" << newPathAndFileName << "'"); + + // remove entry from list + first = outputFileNameArray.erase(first); + + // increase counter + counter++; + } +} + + +static void executeOnEndOfStudy() + /* + * This function deals with the execution of the command line which was passed + * to option --exec-on-eostudy of the storescp. This command line is captured + * in opt_execOnEndOfStudy. Note that the command line can contain the placeholder + * PATH_PLACEHOLDER which needs to be substituted before the command line is actually executed. + * In detail, PATH_PLACEHOLDER will be substituted by the path to the output directory into which + * the files of the last study were written. + * + * Parameters: + * none. + */ +{ + OFString cmd = opt_execOnEndOfStudy; + + // perform substitution for placeholder #p; #p will be substituted by lastStudySubdirectoryPathAndName + cmd = replaceChars( cmd, OFString(PATH_PLACEHOLDER), lastStudySubdirectoryPathAndName ); + + // perform substitution for placeholder #a + cmd = replaceChars( cmd, OFString(CALLING_AETITLE_PLACEHOLDER), (endOfStudyThroughTimeoutEvent) ? callingAETitle : lastCallingAETitle ); + + // perform substitution for placeholder #c + cmd = replaceChars( cmd, OFString(CALLED_AETITLE_PLACEHOLDER), (endOfStudyThroughTimeoutEvent) ? calledAETitle : lastCalledAETitle ); + + // perform substitution for placeholder #r + cmd = replaceChars( cmd, OFString(CALLING_PRESENTATION_ADDRESS_PLACEHOLDER), (endOfStudyThroughTimeoutEvent) ? callingPresentationAddress : lastCallingPresentationAddress ); + + // Execute command in a new process + executeCommand( cmd ); +} + + +static OFString replaceChars( const OFString &srcstr, const OFString &pattern, const OFString &substitute ) + /* + * This function replaces all occurrences of pattern in srcstr with substitute and returns + * the result as a new OFString variable. Note that srcstr itself will not be changed, + * + * Parameters: + * srcstr - [in] The source string. + * pattern - [in] The pattern string which shall be substituted. + * substitute - [in] The substitute for pattern in srcstr. + */ +{ + OFString result = srcstr; + size_t pos = 0; + + while( pos != OFString_npos ) + { + pos = result.find( pattern, pos ); + + if( pos != OFString_npos ) + { + result.replace( pos, pattern.size(), substitute ); + pos += substitute.size(); + } + } + + return( result ); +} + + +static void executeCommand( const OFString &cmd ) + /* + * This function executes the given command line. The execution will be + * performed in a new process which can be run in the background + * so that it does not slow down the execution of storescp. + * + * Parameters: + * cmd - [in] The command which shall be executed. + */ +{ +#ifdef HAVE_FORK + pid_t pid = fork(); + if( pid < 0 ) // in case fork failed, dump an error message + OFLOG_ERROR(storescpLogger, "cannot execute command '" << cmd << "' (fork failed)"); + else if (pid > 0) + { + /* we are the parent process */ + /* remove pending zombie child processes */ + cleanChildren(pid, opt_execSync); + } + else // in case we are the child process, execute the command etc. + { + // execute command through execl will terminate the child process. + // Since we only have a single command string and not a list of arguments, + // we 'emulate' a call to system() by passing the command to /bin/sh + // which hopefully exists on all Posix systems. + + if (execl( "/bin/sh", "/bin/sh", "-c", cmd.c_str(), NULL ) < 0) + OFLOG_ERROR(storescpLogger, "cannot execute /bin/sh"); + + // if execl succeeds, this part will not get executed. + // if execl fails, there is not much we can do except bailing out. + abort(); + } +#else + PROCESS_INFORMATION procinfo; + STARTUPINFO sinfo; + OFBitmanipTemplate::zeroMem((char *)&sinfo, sizeof(sinfo)); + sinfo.cb = sizeof(sinfo); + + // execute command (Attention: Do not pass DETACHED_PROCESS as sixth argument to the below + // called function because in such a case the execution of batch-files is not going to work.) + if( !CreateProcess(NULL, OFconst_cast(char *, cmd.c_str()), NULL, NULL, 0, 0, NULL, NULL, &sinfo, &procinfo) ) + OFLOG_ERROR(storescpLogger, "cannot execute command '" << cmd << "'"); + + if (opt_execSync) + { + // Wait until child process exits (makes execution synchronous) + WaitForSingleObject(procinfo.hProcess, INFINITE); + } + + // Close process and thread handles to avoid resource leak + CloseHandle(procinfo.hProcess); + CloseHandle(procinfo.hThread); +#endif +} + + +static void cleanChildren(pid_t pid, OFBool synch) + /* + * This function removes child processes that have terminated, + * i.e. converted to zombies. Should be called now and then. + */ +{ +#ifdef HAVE_WAITPID + int stat_loc; +#elif HAVE_WAIT3 + struct rusage rusage; +#if defined(__NeXT__) + /* some systems need a union wait as argument to wait3 */ + union wait status; +#else + int status; +#endif +#endif + +#if defined(HAVE_WAITPID) || defined(HAVE_WAIT3) + int child = 1; + int options = synch ? 0 : WNOHANG; + while (child > 0) + { +#ifdef HAVE_WAITPID + child = OFstatic_cast(int, waitpid(pid, &stat_loc, options)); +#elif defined(HAVE_WAIT3) + child = wait3(&status, options, &rusage); +#endif + if (child < 0) + { + if (errno != ECHILD) + { + char buf[256]; + OFLOG_WARN(storescpLogger, "wait for child failed: " << OFStandard::strerror(errno, buf, sizeof(buf))); + } + } + + if (synch) child = -1; // break out of loop + } +#endif +} + + +static +DUL_PRESENTATIONCONTEXT * +findPresentationContextID(LST_HEAD * head, + T_ASC_PresentationContextID presentationContextID) +{ + DUL_PRESENTATIONCONTEXT *pc; + LST_HEAD **l; + OFBool found = OFFalse; + + if (head == NULL) + return NULL; + + l = &head; + if (*l == NULL) + return NULL; + + pc = OFstatic_cast(DUL_PRESENTATIONCONTEXT *, LST_Head(l)); + (void)LST_Position(l, OFstatic_cast(LST_NODE *, pc)); + + while (pc && !found) { + if (pc->presentationContextID == presentationContextID) { + found = OFTrue; + } else { + pc = OFstatic_cast(DUL_PRESENTATIONCONTEXT *, LST_Next(l)); + } + } + return pc; +} + + +/** accept all presentation contexts for unknown SOP classes, + * i.e. UIDs appearing in the list of abstract syntaxes + * where no corresponding name is defined in the UID dictionary. + * @param params pointer to association parameters structure + * @param transferSyntax transfer syntax to accept + * @param acceptedRole SCU/SCP role to accept + */ +static OFCondition acceptUnknownContextsWithTransferSyntax( + T_ASC_Parameters * params, + const char* transferSyntax, + T_ASC_SC_ROLE acceptedRole) +{ + OFCondition cond = EC_Normal; + int n, i, k; + DUL_PRESENTATIONCONTEXT *dpc; + T_ASC_PresentationContext pc; + OFBool accepted = OFFalse; + OFBool abstractOK = OFFalse; + + n = ASC_countPresentationContexts(params); + for (i = 0; i < n; i++) + { + cond = ASC_getPresentationContext(params, i, &pc); + if (cond.bad()) return cond; + abstractOK = OFFalse; + accepted = OFFalse; + + if (dcmFindNameOfUID(pc.abstractSyntax) == NULL) + { + abstractOK = OFTrue; + + /* check the transfer syntax */ + for (k = 0; (k < OFstatic_cast(int, pc.transferSyntaxCount)) && !accepted; k++) + { + if (strcmp(pc.proposedTransferSyntaxes[k], transferSyntax) == 0) + { + accepted = OFTrue; + } + } + } + + if (accepted) + { + cond = ASC_acceptPresentationContext( + params, pc.presentationContextID, + transferSyntax, acceptedRole); + if (cond.bad()) return cond; + } else { + T_ASC_P_ResultReason reason; + + /* do not refuse if already accepted */ + dpc = findPresentationContextID(params->DULparams.acceptedPresentationContext, + pc.presentationContextID); + if ((dpc == NULL) || ((dpc != NULL) && (dpc->result != ASC_P_ACCEPTANCE))) + { + + if (abstractOK) { + reason = ASC_P_TRANSFERSYNTAXESNOTSUPPORTED; + } else { + reason = ASC_P_ABSTRACTSYNTAXNOTSUPPORTED; + } + /* + * If previously this presentation context was refused + * because of bad transfer syntax let it stay that way. + */ + if ((dpc != NULL) && (dpc->result == ASC_P_TRANSFERSYNTAXESNOTSUPPORTED)) + reason = ASC_P_TRANSFERSYNTAXESNOTSUPPORTED; + + cond = ASC_refusePresentationContext(params, pc.presentationContextID, reason); + if (cond.bad()) return cond; + } + } + } + return EC_Normal; +} + + +/** accept all presentation contexts for unknown SOP classes, + * i.e. UIDs appearing in the list of abstract syntaxes + * where no corresponding name is defined in the UID dictionary. + * This method is passed a list of "preferred" transfer syntaxes. + * @param params pointer to association parameters structure + * @param transferSyntax transfer syntax to accept + * @param acceptedRole SCU/SCP role to accept + */ +static OFCondition acceptUnknownContextsWithPreferredTransferSyntaxes( + T_ASC_Parameters * params, + const char* transferSyntaxes[], int transferSyntaxCount, + T_ASC_SC_ROLE acceptedRole) +{ + OFCondition cond = EC_Normal; + /* + ** Accept in the order "least wanted" to "most wanted" transfer + ** syntax. Accepting a transfer syntax will override previously + ** accepted transfer syntaxes. + */ + for (int i = transferSyntaxCount - 1; i >= 0; i--) + { + cond = acceptUnknownContextsWithTransferSyntax(params, transferSyntaxes[i], acceptedRole); + if (cond.bad()) return cond; + } + return cond; +} diff --git a/dcmnet/apps/storescu.cc b/dcmnet/apps/storescu.cc new file mode 100644 index 00000000..82a38388 --- /dev/null +++ b/dcmnet/apps/storescu.cc @@ -0,0 +1,1746 @@ +/* + * + * Copyright (C) 1996-2013, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmnet + * + * Author: Andrew Hewett + * + * Purpose: Storage Service Class User (C-STORE operation) + * + */ + +#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ + +#define INCLUDE_CSTDLIB +#define INCLUDE_CSTDIO +#define INCLUDE_CSTRING +#define INCLUDE_CCTYPE +#include "dcmtk/ofstd/ofstdinc.h" + +BEGIN_EXTERN_C +#ifdef HAVE_SYS_FILE_H +#include +#endif +END_EXTERN_C + +#ifdef HAVE_GUSI_H +#include +#endif + +#include "dcmtk/ofstd/ofstd.h" +#include "dcmtk/ofstd/ofconapp.h" +#include "dcmtk/ofstd/ofstring.h" +#include "dcmtk/ofstd/ofstream.h" +#include "dcmtk/dcmnet/dicom.h" /* for DICOM_APPLICATION_REQUESTOR */ +#include "dcmtk/dcmnet/dimse.h" +#include "dcmtk/dcmnet/diutil.h" +#include "dcmtk/dcmnet/dcasccfg.h" /* for class DcmAssociationConfiguration */ +#include "dcmtk/dcmnet/dcasccff.h" /* for class DcmAssociationConfigurationFile */ +#include "dcmtk/dcmdata/dcdatset.h" +#include "dcmtk/dcmdata/dcmetinf.h" +#include "dcmtk/dcmdata/dcfilefo.h" +#include "dcmtk/dcmdata/dcuid.h" +#include "dcmtk/dcmdata/dcdict.h" +#include "dcmtk/dcmdata/dcdeftag.h" +#include "dcmtk/dcmdata/cmdlnarg.h" +#include "dcmtk/dcmdata/dcuid.h" /* for dcmtk version name */ +#include "dcmtk/dcmdata/dcostrmz.h" /* for dcmZlibCompressionLevel */ + +#ifdef ON_THE_FLY_COMPRESSION +#include "dcmtk/dcmjpeg/djdecode.h" /* for JPEG decoders */ +#include "dcmtk/dcmjpeg/djencode.h" /* for JPEG encoders */ +#include "dcmtk/dcmjpls/djdecode.h" /* for JPEG-LS decoders */ +#include "dcmtk/dcmjpls/djencode.h" /* for JPEG-LS encoders */ +#include "dcmtk/dcmdata/dcrledrg.h" /* for RLE decoder */ +#include "dcmtk/dcmdata/dcrleerg.h" /* for RLE encoder */ +#include "dcmtk/dcmjpeg/dipijpeg.h" /* for dcmimage JPEG plugin */ +#endif + +#ifdef WITH_OPENSSL +#include "dcmtk/dcmtls/tlstrans.h" +#include "dcmtk/dcmtls/tlslayer.h" +#endif + +#ifdef WITH_ZLIB +#include /* for zlibVersion() */ +#endif + +#if defined (HAVE_WINDOWS_H) || defined(HAVE_FNMATCH_H) +#define PATTERN_MATCHING_AVAILABLE +#endif + +#define OFFIS_CONSOLE_APPLICATION "storescu" + +static OFLogger storescuLogger = OFLog::getLogger("dcmtk.apps." OFFIS_CONSOLE_APPLICATION); + +static char rcsid[] = "$dcmtk: " OFFIS_CONSOLE_APPLICATION " v" + OFFIS_DCMTK_VERSION " " OFFIS_DCMTK_RELEASEDATE " $"; + +/* default application titles */ +#define APPLICATIONTITLE "STORESCU" +#define PEERAPPLICATIONTITLE "ANY-SCP" + +static OFBool opt_showPresentationContexts = OFFalse; +static OFBool opt_abortAssociation = OFFalse; +static OFCmdUnsignedInt opt_maxReceivePDULength = ASC_DEFAULTMAXPDU; +static OFCmdUnsignedInt opt_maxSendPDULength = 0; +static E_TransferSyntax opt_networkTransferSyntax = EXS_Unknown; +static E_FileReadMode opt_readMode = ERM_autoDetect; + +static OFBool opt_scanDir = OFFalse; +static OFBool opt_recurse = OFFalse; +static const char *opt_scanPattern = ""; + +static OFBool opt_haltOnUnsuccessfulStore = OFTrue; +static OFBool unsuccessfulStoreEncountered = OFFalse; +static int lastStatusCode = STATUS_Success; + +static OFBool opt_proposeOnlyRequiredPresentationContexts = OFFalse; +static OFBool opt_combineProposedTransferSyntaxes = OFFalse; + +static OFCmdUnsignedInt opt_repeatCount = 1; +static OFCmdUnsignedInt opt_inventPatientCount = 25; +static OFCmdUnsignedInt opt_inventStudyCount = 50; +static OFCmdUnsignedInt opt_inventSeriesCount = 100; +static OFBool opt_inventSOPInstanceInformation = OFFalse; +static OFBool opt_correctUIDPadding = OFFalse; +static OFString patientNamePrefix("OFFIS^TEST_PN_"); // PatientName is PN (maximum 16 chars) +static OFString patientIDPrefix("PID_"); // PatientID is LO (maximum 64 chars) +static OFString studyIDPrefix("SID_"); // StudyID is SH (maximum 16 chars) +static OFString accessionNumberPrefix; // AccessionNumber is SH (maximum 16 chars) +static OFBool opt_secureConnection = OFFalse; /* default: no secure connection */ +static const char *opt_configFile = NULL; +static const char *opt_profileName = NULL; +T_DIMSE_BlockingMode opt_blockMode = DIMSE_BLOCKING; +int opt_dimse_timeout = 0; +int opt_acse_timeout = 30; + +#ifdef WITH_ZLIB +static OFCmdUnsignedInt opt_compressionLevel = 0; +#endif + +#ifdef WITH_OPENSSL +static int opt_keyFileFormat = SSL_FILETYPE_PEM; +static OFBool opt_doAuthenticate = OFFalse; +static const char *opt_privateKeyFile = NULL; +static const char *opt_certificateFile = NULL; +static const char *opt_passwd = NULL; +#if OPENSSL_VERSION_NUMBER >= 0x0090700fL +static OFString opt_ciphersuites(TLS1_TXT_RSA_WITH_AES_128_SHA ":" SSL3_TXT_RSA_DES_192_CBC3_SHA); +#else +static OFString opt_ciphersuites(SSL3_TXT_RSA_DES_192_CBC3_SHA); +#endif +static const char *opt_readSeedFile = NULL; +static const char *opt_writeSeedFile = NULL; +static DcmCertificateVerification opt_certVerification = DCV_requireCertificate; +static const char *opt_dhparam = NULL; +#endif + +// User Identity Negotiation +static T_ASC_UserIdentityNegotiationMode opt_identMode = ASC_USER_IDENTITY_NONE; +static OFString opt_user; +static OFString opt_password; +static OFString opt_identFile; +static OFBool opt_identResponse = OFFalse; + +static OFCondition +addStoragePresentationContexts(T_ASC_Parameters *params, OFList &sopClasses); + +static OFCondition +cstore(T_ASC_Association *assoc, const OFString &fname); + +static OFBool +findSOPClassAndInstanceInFile(const char *fname, char *sopClass, char *sopInstance); + +static OFCondition +configureUserIdentityRequest(T_ASC_Parameters *params); + +static OFCondition +checkUserIdentityResponse(T_ASC_Parameters *params); + +/* helper macro for converting stream output to a string */ +#define CONVERT_TO_STRING(output, string) \ + optStream.str(""); \ + optStream.clear(); \ + optStream << output << OFStringStream_ends; \ + OFSTRINGSTREAM_GETOFSTRING(optStream, string) + +#define SHORTCOL 4 +#define LONGCOL 19 + +int main(int argc, char *argv[]) +{ + OFOStringStream optStream; + + const char *opt_peer = NULL; + OFCmdUnsignedInt opt_port = 104; + const char *opt_peerTitle = PEERAPPLICATIONTITLE; + const char *opt_ourTitle = APPLICATIONTITLE; + + OFList fileNameList; // list of files to transfer to SCP + OFList sopClassUIDList; // the list of SOP classes + OFList sopInstanceUIDList; // the list of SOP instances + + T_ASC_Network *net; + T_ASC_Parameters *params; + DIC_NODENAME localHost; + DIC_NODENAME peerHost; + T_ASC_Association *assoc; + DcmAssociationConfiguration asccfg; // handler for association configuration profiles + +#ifdef HAVE_GUSI_H + GUSISetup(GUSIwithSIOUXSockets); + GUSISetup(GUSIwithInternetSockets); +#endif + +#ifdef HAVE_WINSOCK_H + WSAData winSockData; + /* we need at least version 1.1 */ + WORD winSockVersionNeeded = MAKEWORD( 1, 1 ); + WSAStartup(winSockVersionNeeded, &winSockData); +#endif + + OFString temp_str; + OFConsoleApplication app(OFFIS_CONSOLE_APPLICATION , "DICOM storage (C-STORE) SCU", rcsid); + OFCommandLine cmd; + + cmd.setParamColumn(LONGCOL + SHORTCOL + 4); + cmd.addParam("peer", "hostname of DICOM peer"); + cmd.addParam("port", "tcp/ip port number of peer"); + cmd.addParam("dcmfile-in", "DICOM file or directory to be transmitted", OFCmdParam::PM_MultiMandatory); + + cmd.setOptionColumns(LONGCOL, SHORTCOL); + cmd.addGroup("general options:", LONGCOL, SHORTCOL + 2); + cmd.addOption("--help", "-h", "print this help text and exit", OFCommandLine::AF_Exclusive); + cmd.addOption("--version", "print version information and exit", OFCommandLine::AF_Exclusive); + OFLog::addOptions(cmd); + cmd.addOption("--verbose-pc", "+v", "show presentation contexts in verbose mode"); + + cmd.addGroup("input options:"); + cmd.addSubGroup("input file format:"); + cmd.addOption("--read-file", "+f", "read file format or data set (default)"); + cmd.addOption("--read-file-only", "+fo", "read file format only"); + cmd.addOption("--read-dataset", "-f", "read data set without file meta information"); + cmd.addSubGroup("input files:"); + cmd.addOption("--scan-directories", "+sd", "scan directories for input files (dcmfile-in)"); +#ifdef PATTERN_MATCHING_AVAILABLE + cmd.addOption("--scan-pattern", "+sp", 1, "[p]attern: string (only with --scan-directories)", + "pattern for filename matching (wildcards)"); +#endif + cmd.addOption("--no-recurse", "-r", "do not recurse within directories (default)"); + cmd.addOption("--recurse", "+r", "recurse within specified directories"); + cmd.addGroup("network options:"); + cmd.addSubGroup("application entity titles:"); + cmd.addOption("--aetitle", "-aet", 1, "[a]etitle: string", "set my calling AE title (default: " APPLICATIONTITLE ")"); + cmd.addOption("--call", "-aec", 1, "[a]etitle: string", "set called AE title of peer (default: " PEERAPPLICATIONTITLE ")"); + cmd.addSubGroup("association negotiation profile from configuration file:"); + cmd.addOption("--config-file", "-xf", 2, "[f]ilename, [p]rofile: string", + "use profile p from config file f"); + cmd.addSubGroup("proposed transmission transfer syntaxes (not with --config-file):"); + cmd.addOption("--propose-uncompr", "-x=", "propose all uncompressed TS, explicit VR\nwith local byte ordering first (default)"); + cmd.addOption("--propose-little", "-xe", "propose all uncompressed TS, explicit VR\nlittle endian first"); + cmd.addOption("--propose-big", "-xb", "propose all uncompressed TS, explicit VR\nbig endian first"); + cmd.addOption("--propose-implicit", "-xi", "propose implicit VR little endian TS only"); + cmd.addOption("--propose-lossless", "-xs", "propose default JPEG lossless TS\nand all uncompressed transfer syntaxes"); + cmd.addOption("--propose-jpeg8", "-xy", "propose default JPEG lossy TS for 8 bit data\nand all uncompressed transfer syntaxes"); + cmd.addOption("--propose-jpeg12", "-xx", "propose default JPEG lossy TS for 12 bit data\nand all uncompressed transfer syntaxes"); + cmd.addOption("--propose-j2k-lossless", "-xv", "propose JPEG 2000 lossless TS\nand all uncompressed transfer syntaxes"); + cmd.addOption("--propose-j2k-lossy", "-xw", "propose JPEG 2000 lossy TS\nand all uncompressed transfer syntaxes"); + cmd.addOption("--propose-jls-lossless", "-xt", "propose JPEG-LS lossless TS\nand all uncompressed transfer syntaxes"); + cmd.addOption("--propose-jls-lossy", "-xu", "propose JPEG-LS lossy TS\nand all uncompressed transfer syntaxes"); + cmd.addOption("--propose-mpeg2", "-xm", "propose MPEG2 Main Profile @ Main Level TS only"); + cmd.addOption("--propose-mpeg2-high", "-xh", "propose MPEG2 Main Profile @ High Level TS only"); + cmd.addOption("--propose-mpeg4", "-xn", "propose MPEG4 AVC/H.264 HP / Level 4.1 TS only"); + cmd.addOption("--propose-mpeg4-bd", "-xl", "propose MPEG4 AVC/H.264 BD-compatible TS only"); + cmd.addOption("--propose-rle", "-xr", "propose RLE lossless TS\nand all uncompressed transfer syntaxes"); +#ifdef WITH_ZLIB + cmd.addOption("--propose-deflated", "-xd", "propose deflated expl. VR little endian TS\nand all uncompressed transfer syntaxes"); +#endif + cmd.addOption("--required", "-R", "propose only required presentation contexts\n(default: propose all supported)"); + cmd.addOption("--combine", "+C", "combine proposed transfer syntaxes\n(default: separate pres. context for each TS)"); + cmd.addSubGroup("post-1993 value representations:"); + cmd.addOption("--enable-new-vr", "+u", "enable support for new VRs (UN/UT) (default)"); + cmd.addOption("--disable-new-vr", "-u", "disable support for new VRs, convert to OB"); +#ifdef WITH_ZLIB + cmd.addSubGroup("deflate compression level (only with --propose-deflated or --config-file):"); + cmd.addOption("--compression-level", "+cl", 1, "[l]evel: integer (default: 6)", + "0=uncompressed, 1=fastest, 9=best compression"); +#endif + cmd.addSubGroup("user identity negotiation:"); + cmd.addOption("--user", "-usr", 1, "[u]ser name: string", + "authenticate using user name u"); + cmd.addOption("--password", "-pwd", 1, "[p]assword: string (only with --user)", + "authenticate using password p"); + cmd.addOption("--empty-password", "-epw", "send empty password (only with --user)"); + cmd.addOption("--kerberos", "-kt", 1, "[f]ilename: string", + "read kerberos ticket from file f"); + cmd.addOption("--saml", 1, "[f]ilename: string", + "read SAML request from file f"); + cmd.addOption("--pos-response", "-rsp", "expect positive response"); + cmd.addSubGroup("other network options:"); + cmd.addOption("--timeout", "-to", 1, "[s]econds: integer (default: unlimited)", "timeout for connection requests"); + CONVERT_TO_STRING("[s]econds: integer (default: " << opt_acse_timeout << ")", optString1); + cmd.addOption("--acse-timeout", "-ta", 1, optString1.c_str(), "timeout for ACSE messages"); + cmd.addOption("--dimse-timeout", "-td", 1, "[s]econds: integer (default: unlimited)", "timeout for DIMSE messages"); + CONVERT_TO_STRING("[n]umber of bytes: integer (" << ASC_MINIMUMPDUSIZE << ".." << ASC_MAXIMUMPDUSIZE << ")", optString2); + CONVERT_TO_STRING("set max receive pdu to n bytes (default: " << opt_maxReceivePDULength << ")", optString3); + cmd.addOption("--max-pdu", "-pdu", 1, optString2.c_str(), optString3.c_str()); + cmd.addOption("--max-send-pdu", 1, optString2.c_str(), "restrict max send pdu to n bytes"); + cmd.addOption("--repeat", 1, "[n]umber: integer", "repeat n times"); + cmd.addOption("--abort", "abort association instead of releasing it"); + cmd.addOption("--no-halt", "-nh", "do not halt if unsuccessful store encountered\n(default: do halt)"); + cmd.addOption("--uid-padding", "-up", "silently correct space-padded UIDs"); + + cmd.addOption("--invent-instance", "+II", "invent a new SOP instance UID for every image\nsent"); + CONVERT_TO_STRING("invent a new series UID after n images" << OFendl << "have been sent (default: " << opt_inventSeriesCount << ")", optString4); + cmd.addOption("--invent-series", "+IR", 1, "[n]umber: integer (implies --invent-instance)", optString4.c_str()); + CONVERT_TO_STRING("invent a new study UID after n series" << OFendl << "have been sent (default: " << opt_inventStudyCount << ")", optString5); + cmd.addOption("--invent-study", "+IS", 1, "[n]umber: integer (implies --invent-instance)", optString5.c_str()); + CONVERT_TO_STRING("invent a new patient ID and name after n studies" << OFendl << "have been sent (default: " << opt_inventPatientCount << ")", optString6); + cmd.addOption("--invent-patient", "+IP", 1, "[n]umber: integer (implies --invent-instance)", optString6.c_str()); + +#ifdef WITH_OPENSSL + cmd.addGroup("transport layer security (TLS) options:"); + cmd.addSubGroup("transport protocol stack:"); + cmd.addOption("--disable-tls", "-tls", "use normal TCP/IP connection (default)"); + cmd.addOption("--enable-tls", "+tls", 2, "[p]rivate key file, [c]ertificate file: string", + "use authenticated secure TLS connection"); + cmd.addOption("--anonymous-tls", "+tla", "use secure TLS connection without certificate"); + cmd.addSubGroup("private key password (only with --enable-tls):"); + cmd.addOption("--std-passwd", "+ps", "prompt user to type password on stdin (default)"); + cmd.addOption("--use-passwd", "+pw", 1, "[p]assword: string ", + "use specified password"); + cmd.addOption("--null-passwd", "-pw", "use empty string as password"); + cmd.addSubGroup("key and certificate file format:"); + cmd.addOption("--pem-keys", "-pem", "read keys and certificates as PEM file (default)"); + cmd.addOption("--der-keys", "-der", "read keys and certificates as DER file"); + cmd.addSubGroup("certification authority:"); + cmd.addOption("--add-cert-file", "+cf", 1, "[c]ertificate filename: string", + "add certificate file to list of certificates", OFCommandLine::AF_NoWarning); + cmd.addOption("--add-cert-dir", "+cd", 1, "[c]ertificate directory: string", + "add certificates in d to list of certificates", OFCommandLine::AF_NoWarning); + cmd.addSubGroup("ciphersuite:"); + cmd.addOption("--cipher", "+cs", 1, "[c]iphersuite name: string", + "add ciphersuite to list of negotiated suites"); + cmd.addOption("--dhparam", "+dp", 1, "[f]ilename: string", + "read DH parameters for DH/DSS ciphersuites"); + cmd.addSubGroup("pseudo random generator:"); + cmd.addOption("--seed", "+rs", 1, "[f]ilename: string", + "seed random generator with contents of f"); + cmd.addOption("--write-seed", "+ws", "write back modified seed (only with --seed)"); + cmd.addOption("--write-seed-file", "+wf", 1, "[f]ilename: string (only with --seed)", + "write modified seed to file f"); + cmd.addSubGroup("peer authentication:"); + cmd.addOption("--require-peer-cert", "-rc", "verify peer certificate, fail if absent (default)"); + cmd.addOption("--verify-peer-cert", "-vc", "verify peer certificate if present"); + cmd.addOption("--ignore-peer-cert", "-ic", "don't verify peer certificate"); +#endif + + /* evaluate command line */ + prepareCmdLineArgs(argc, argv, OFFIS_CONSOLE_APPLICATION); + if (app.parseCommandLine(cmd, argc, argv)) + { + /* check exclusive options first */ + if (cmd.hasExclusiveOption()) + { + if (cmd.findOption("--version")) + { + app.printHeader(OFTrue /*print host identifier*/); + COUT << OFendl << "External libraries used:"; +#if !defined(WITH_ZLIB) && !(ON_THE_FLY_COMPRESSION) && !defined(WITH_OPENSSL) + COUT << " none" << OFendl; +#else + COUT << OFendl; +#endif +#ifdef WITH_ZLIB + COUT << "- ZLIB, Version " << zlibVersion() << OFendl; +#endif +#ifdef ON_THE_FLY_COMPRESSION + COUT << "- " << DiJPEGPlugin::getLibraryVersionString() << OFendl; + COUT << "- " << DJLSDecoderRegistration::getLibraryVersionString() << OFendl; +#endif +#ifdef WITH_OPENSSL + COUT << "- " << OPENSSL_VERSION_TEXT << OFendl; +#endif + return 0; + } + } + + /* command line parameters */ + + cmd.getParam(1, opt_peer); + app.checkParam(cmd.getParamAndCheckMinMax(2, opt_port, 1, 65535)); + + OFLog::configureFromCommandLine(cmd, app); + if (cmd.findOption("--verbose-pc")) + { + app.checkDependence("--verbose-pc", "verbose mode", storescuLogger.isEnabledFor(OFLogger::INFO_LOG_LEVEL)); + opt_showPresentationContexts = OFTrue; + } + + cmd.beginOptionBlock(); + if (cmd.findOption("--read-file")) opt_readMode = ERM_autoDetect; + if (cmd.findOption("--read-file-only")) opt_readMode = ERM_fileOnly; + if (cmd.findOption("--read-dataset")) opt_readMode = ERM_dataset; + cmd.endOptionBlock(); + + if (cmd.findOption("--scan-directories")) opt_scanDir = OFTrue; +#ifdef PATTERN_MATCHING_AVAILABLE + if (cmd.findOption("--scan-pattern")) + { + app.checkDependence("--scan-pattern", "--scan-directories", opt_scanDir); + app.checkValue(cmd.getValue(opt_scanPattern)); + } +#endif + cmd.beginOptionBlock(); + if (cmd.findOption("--no-recurse")) opt_recurse = OFFalse; + if (cmd.findOption("--recurse")) + { + app.checkDependence("--recurse", "--scan-directories", opt_scanDir); + opt_recurse = OFTrue; + } + cmd.endOptionBlock(); + + if (cmd.findOption("--aetitle")) app.checkValue(cmd.getValue(opt_ourTitle)); + if (cmd.findOption("--call")) app.checkValue(cmd.getValue(opt_peerTitle)); + + cmd.beginOptionBlock(); + if (cmd.findOption("--propose-uncompr")) opt_networkTransferSyntax = EXS_Unknown; + if (cmd.findOption("--propose-little")) opt_networkTransferSyntax = EXS_LittleEndianExplicit; + if (cmd.findOption("--propose-big")) opt_networkTransferSyntax = EXS_BigEndianExplicit; + if (cmd.findOption("--propose-implicit")) opt_networkTransferSyntax = EXS_LittleEndianImplicit; + if (cmd.findOption("--propose-lossless")) opt_networkTransferSyntax = EXS_JPEGProcess14SV1; + if (cmd.findOption("--propose-jpeg8")) opt_networkTransferSyntax = EXS_JPEGProcess1; + if (cmd.findOption("--propose-jpeg12")) opt_networkTransferSyntax = EXS_JPEGProcess2_4; + if (cmd.findOption("--propose-j2k-lossless")) opt_networkTransferSyntax = EXS_JPEG2000LosslessOnly; + if (cmd.findOption("--propose-j2k-lossy")) opt_networkTransferSyntax = EXS_JPEG2000; + if (cmd.findOption("--propose-jls-lossless")) opt_networkTransferSyntax = EXS_JPEGLSLossless; + if (cmd.findOption("--propose-jls-lossy")) opt_networkTransferSyntax = EXS_JPEGLSLossy; + if (cmd.findOption("--propose-mpeg2")) opt_networkTransferSyntax = EXS_MPEG2MainProfileAtMainLevel; + if (cmd.findOption("--propose-mpeg2-high")) opt_networkTransferSyntax = EXS_MPEG2MainProfileAtHighLevel; + if (cmd.findOption("--propose-mpeg4")) opt_networkTransferSyntax = EXS_MPEG4HighProfileLevel4_1; + if (cmd.findOption("--propose-mpeg4-bd")) opt_networkTransferSyntax = EXS_MPEG4BDcompatibleHighProfileLevel4_1; + if (cmd.findOption("--propose-rle")) opt_networkTransferSyntax = EXS_RLELossless; +#ifdef WITH_ZLIB + if (cmd.findOption("--propose-deflated")) opt_networkTransferSyntax = EXS_DeflatedLittleEndianExplicit; +#endif + cmd.endOptionBlock(); + + if (cmd.findOption("--required")) opt_proposeOnlyRequiredPresentationContexts = OFTrue; + if (cmd.findOption("--combine")) opt_combineProposedTransferSyntaxes = OFTrue; + + if (cmd.findOption("--config-file")) + { + // check conflicts with other command line options + app.checkConflict("--config-file", "--propose-little", opt_networkTransferSyntax == EXS_LittleEndianExplicit); + app.checkConflict("--config-file", "--propose-big", opt_networkTransferSyntax == EXS_BigEndianExplicit); + app.checkConflict("--config-file", "--propose-implicit", opt_networkTransferSyntax == EXS_LittleEndianImplicit); + app.checkConflict("--config-file", "--propose-lossless", opt_networkTransferSyntax == EXS_JPEGProcess14SV1); + app.checkConflict("--config-file", "--propose-jpeg8", opt_networkTransferSyntax == EXS_JPEGProcess1); + app.checkConflict("--config-file", "--propose-jpeg12", opt_networkTransferSyntax == EXS_JPEGProcess2_4); + app.checkConflict("--config-file", "--propose-j2k-lossless", opt_networkTransferSyntax == EXS_JPEG2000LosslessOnly); + app.checkConflict("--config-file", "--propose-j2k-lossy", opt_networkTransferSyntax == EXS_JPEG2000); + app.checkConflict("--config-file", "--propose-jls-lossless", opt_networkTransferSyntax == EXS_JPEGLSLossless); + app.checkConflict("--config-file", "--propose-jls-lossy", opt_networkTransferSyntax == EXS_JPEGLSLossy); + app.checkConflict("--config-file", "--propose-mpeg2", opt_networkTransferSyntax == EXS_MPEG2MainProfileAtMainLevel); + app.checkConflict("--config-file", "--propose-mpeg2-high", opt_networkTransferSyntax == EXS_MPEG2MainProfileAtHighLevel); + app.checkConflict("--config-file", "--propose-mpeg4", opt_networkTransferSyntax == EXS_MPEG4HighProfileLevel4_1); + app.checkConflict("--config-file", "--propose-mpeg4-bd", opt_networkTransferSyntax == EXS_MPEG4BDcompatibleHighProfileLevel4_1); + app.checkConflict("--config-file", "--propose-rle", opt_networkTransferSyntax == EXS_RLELossless); +#ifdef WITH_ZLIB + app.checkConflict("--config-file", "--propose-deflated", opt_networkTransferSyntax == EXS_DeflatedLittleEndianExplicit); +#endif + app.checkConflict("--config-file", "--required", opt_proposeOnlyRequiredPresentationContexts); + app.checkConflict("--config-file", "--combine", opt_combineProposedTransferSyntaxes); + + app.checkValue(cmd.getValue(opt_configFile)); + app.checkValue(cmd.getValue(opt_profileName)); + + // read configuration file. The profile name is checked later. + OFCondition cond = DcmAssociationConfigurationFile::initialize(asccfg, opt_configFile); + if (cond.bad()) + { + OFLOG_ERROR(storescuLogger, "reading config file: " << cond.text()); + return 1; + } + } + +#ifdef WITH_ZLIB + if (cmd.findOption("--compression-level")) + { + app.checkDependence("--compression-level", "--propose-deflated or --config-file", + (opt_networkTransferSyntax == EXS_DeflatedLittleEndianExplicit) || (opt_configFile != NULL)); + app.checkValue(cmd.getValueAndCheckMinMax(opt_compressionLevel, 0, 9)); + dcmZlibCompressionLevel.set(OFstatic_cast(int, opt_compressionLevel)); + } +#endif + + cmd.beginOptionBlock(); + if (cmd.findOption("--enable-new-vr")) dcmEnableGenerationOfNewVRs(); + if (cmd.findOption("--disable-new-vr")) dcmDisableGenerationOfNewVRs(); + cmd.endOptionBlock(); + + if (cmd.findOption("--timeout")) + { + OFCmdSignedInt opt_timeout = 0; + app.checkValue(cmd.getValueAndCheckMin(opt_timeout, 1)); + dcmConnectionTimeout.set(OFstatic_cast(Sint32, opt_timeout)); + } + + if (cmd.findOption("--acse-timeout")) + { + OFCmdSignedInt opt_timeout = 0; + app.checkValue(cmd.getValueAndCheckMin(opt_timeout, 1)); + opt_acse_timeout = OFstatic_cast(int, opt_timeout); + } + + if (cmd.findOption("--dimse-timeout")) + { + OFCmdSignedInt opt_timeout = 0; + app.checkValue(cmd.getValueAndCheckMin(opt_timeout, 1)); + opt_dimse_timeout = OFstatic_cast(int, opt_timeout); + opt_blockMode = DIMSE_NONBLOCKING; + } + + if (cmd.findOption("--max-pdu")) + app.checkValue(cmd.getValueAndCheckMinMax(opt_maxReceivePDULength, ASC_MINIMUMPDUSIZE, ASC_MAXIMUMPDUSIZE)); + + if (cmd.findOption("--max-send-pdu")) + { + app.checkValue(cmd.getValueAndCheckMinMax(opt_maxSendPDULength, ASC_MINIMUMPDUSIZE, ASC_MAXIMUMPDUSIZE)); + dcmMaxOutgoingPDUSize.set(OFstatic_cast(Uint32, opt_maxSendPDULength)); + } + + if (cmd.findOption("--repeat")) app.checkValue(cmd.getValueAndCheckMin(opt_repeatCount, 1)); + if (cmd.findOption("--abort")) opt_abortAssociation = OFTrue; + if (cmd.findOption("--no-halt")) opt_haltOnUnsuccessfulStore = OFFalse; + if (cmd.findOption("--uid-padding")) opt_correctUIDPadding = OFTrue; + + if (cmd.findOption("--invent-instance")) opt_inventSOPInstanceInformation = OFTrue; + if (cmd.findOption("--invent-series")) + { + opt_inventSOPInstanceInformation = OFTrue; + app.checkValue(cmd.getValueAndCheckMin(opt_inventSeriesCount, 1)); + } + if (cmd.findOption("--invent-study")) + { + opt_inventSOPInstanceInformation = OFTrue; + app.checkValue(cmd.getValueAndCheckMin(opt_inventStudyCount, 1)); + } + if (cmd.findOption("--invent-patient")) + { + opt_inventSOPInstanceInformation = OFTrue; + app.checkValue(cmd.getValueAndCheckMin(opt_inventPatientCount, 1)); + } + +#ifdef WITH_OPENSSL + + cmd.beginOptionBlock(); + if (cmd.findOption("--disable-tls")) opt_secureConnection = OFFalse; + if (cmd.findOption("--enable-tls")) + { + opt_secureConnection = OFTrue; + opt_doAuthenticate = OFTrue; + app.checkValue(cmd.getValue(opt_privateKeyFile)); + app.checkValue(cmd.getValue(opt_certificateFile)); + } + if (cmd.findOption("--anonymous-tls")) + { + opt_secureConnection = OFTrue; + } + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--std-passwd")) + { + app.checkDependence("--std-passwd", "--enable-tls", opt_doAuthenticate); + opt_passwd = NULL; + } + if (cmd.findOption("--use-passwd")) + { + app.checkDependence("--use-passwd", "--enable-tls", opt_doAuthenticate); + app.checkValue(cmd.getValue(opt_passwd)); + } + if (cmd.findOption("--null-passwd")) + { + app.checkDependence("--null-passwd", "--enable-tls", opt_doAuthenticate); + opt_passwd = ""; + } + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--pem-keys")) opt_keyFileFormat = SSL_FILETYPE_PEM; + if (cmd.findOption("--der-keys")) opt_keyFileFormat = SSL_FILETYPE_ASN1; + cmd.endOptionBlock(); + + if (cmd.findOption("--dhparam")) + { + app.checkValue(cmd.getValue(opt_dhparam)); + } + + if (cmd.findOption("--seed")) + { + app.checkValue(cmd.getValue(opt_readSeedFile)); + } + + cmd.beginOptionBlock(); + if (cmd.findOption("--write-seed")) + { + app.checkDependence("--write-seed", "--seed", opt_readSeedFile != NULL); + opt_writeSeedFile = opt_readSeedFile; + } + if (cmd.findOption("--write-seed-file")) + { + app.checkDependence("--write-seed-file", "--seed", opt_readSeedFile != NULL); + app.checkValue(cmd.getValue(opt_writeSeedFile)); + } + cmd.endOptionBlock(); + + cmd.beginOptionBlock(); + if (cmd.findOption("--require-peer-cert")) opt_certVerification = DCV_requireCertificate; + if (cmd.findOption("--verify-peer-cert")) opt_certVerification = DCV_checkCertificate; + if (cmd.findOption("--ignore-peer-cert")) opt_certVerification = DCV_ignoreCertificate; + cmd.endOptionBlock(); + + const char *current = NULL; + const char *currentOpenSSL; + if (cmd.findOption("--cipher", 0, OFCommandLine::FOM_First)) + { + opt_ciphersuites.clear(); + do + { + app.checkValue(cmd.getValue(current)); + if (NULL == (currentOpenSSL = DcmTLSTransportLayer::findOpenSSLCipherSuiteName(current))) + { + OFLOG_ERROR(storescuLogger, "ciphersuite '" << current << "' is unknown. Known ciphersuites are:"); + unsigned long numSuites = DcmTLSTransportLayer::getNumberOfCipherSuites(); + for (unsigned long cs = 0; cs < numSuites; cs++) + OFLOG_ERROR(storescuLogger, " " << DcmTLSTransportLayer::getTLSCipherSuiteName(cs)); + return 1; + } else { + if (!opt_ciphersuites.empty()) opt_ciphersuites += ":"; + opt_ciphersuites += currentOpenSSL; + } + } while (cmd.findOption("--cipher", 0, OFCommandLine::FOM_Next)); + } + +#endif + + // User Identity Negotiation + cmd.beginOptionBlock(); + if (cmd.findOption("--user")) + { + app.checkValue(cmd.getValue(opt_user)); + opt_identMode = ASC_USER_IDENTITY_USER; + } + if (cmd.findOption("--kerberos")) + { + app.checkValue(cmd.getValue(opt_identFile)); + opt_identMode = ASC_USER_IDENTITY_KERBEROS; + } + if (cmd.findOption("--saml")) + { + app.checkValue(cmd.getValue(opt_identFile)); + opt_identMode = ASC_USER_IDENTITY_SAML; + } + cmd.endOptionBlock(); + cmd.beginOptionBlock(); + if (cmd.findOption("--password")) + { + app.checkDependence("--password", "--user", opt_identMode == ASC_USER_IDENTITY_USER); + app.checkValue(cmd.getValue(opt_password)); + opt_identMode = ASC_USER_IDENTITY_USER_PASSWORD; + } + if (cmd.findOption("--empty-password")) + { + app.checkDependence("--empty-password", "--user", opt_identMode == ASC_USER_IDENTITY_USER); + opt_password= ""; + opt_identMode = ASC_USER_IDENTITY_USER_PASSWORD; + } + cmd.endOptionBlock(); + if (cmd.findOption("--pos-response")) + { + app.checkDependence("--pos-response", "--user, --kerberos or --saml", opt_identMode != ASC_USER_IDENTITY_NONE); + opt_identResponse = OFTrue; + } + } + + /* print resource identifier */ + OFLOG_DEBUG(storescuLogger, rcsid << OFendl); + + /* make sure data dictionary is loaded */ + if (!dcmDataDict.isDictionaryLoaded()) + { + OFLOG_WARN(storescuLogger, "no data dictionary loaded, check environment variable: " + << DCM_DICT_ENVIRONMENT_VARIABLE); + } + + /* finally, create list of input files */ + const char *paramString = NULL; + const int paramCount = cmd.getParamCount(); + OFList inputFiles; + if (opt_scanDir) + OFLOG_INFO(storescuLogger, "determining input files ..."); + /* iterate over all input filenames/directories */ + for (int i = 3; i <= paramCount; i++) + { + cmd.getParam(i, paramString); + /* search directory recursively (if required) */ + if (OFStandard::dirExists(paramString)) + { + if (opt_scanDir) + OFStandard::searchDirectoryRecursively(paramString, inputFiles, opt_scanPattern, "" /*dirPrefix*/, opt_recurse); + else + OFLOG_WARN(storescuLogger, "ignoring directory because option --scan-directories is not set: " << paramString); + } else + inputFiles.push_back(paramString); + } + /* check whether there are any input files at all */ + if (inputFiles.empty()) + { + OFLOG_FATAL(storescuLogger, "no input files to be sent"); + exit(1); + } + + /* check input files */ + OFString errormsg; + DcmFileFormat dfile; + char sopClassUID[128]; + char sopInstanceUID[128]; + OFBool ignoreName; + const char *currentFilename = NULL; + OFListIterator(OFString) if_iter = inputFiles.begin(); + OFListIterator(OFString) if_last = inputFiles.end(); + OFLOG_INFO(storescuLogger, "checking input files ..."); + /* iterate over all input filenames */ + while (if_iter != if_last) + { + ignoreName = OFFalse; + currentFilename = (*if_iter).c_str(); + if (OFStandard::fileExists(currentFilename)) + { + if (opt_proposeOnlyRequiredPresentationContexts) + { + if (!findSOPClassAndInstanceInFile(currentFilename, sopClassUID, sopInstanceUID)) + { + ignoreName = OFTrue; + errormsg = "missing SOP class (or instance) in file: "; + errormsg += currentFilename; + if (opt_haltOnUnsuccessfulStore) + { + OFLOG_FATAL(storescuLogger, errormsg); + exit(1); + } + else + OFLOG_WARN(storescuLogger, errormsg << ", ignoring file"); + } + else if (!dcmIsaStorageSOPClassUID(sopClassUID)) + { + ignoreName = OFTrue; + errormsg = "unknown storage SOP class in file: "; + errormsg += currentFilename; + errormsg += ": "; + errormsg += sopClassUID; + if (opt_haltOnUnsuccessfulStore) + { + OFLOG_FATAL(storescuLogger, errormsg); + exit(1); + } + else + OFLOG_WARN(storescuLogger, errormsg << ", ignoring file"); + } + else + { + sopClassUIDList.push_back(sopClassUID); + sopInstanceUIDList.push_back(sopInstanceUID); + } + } + if (!ignoreName) fileNameList.push_back(currentFilename); + } + else + { + errormsg = "cannot access file: "; + errormsg += currentFilename; + if (opt_haltOnUnsuccessfulStore) + { + OFLOG_FATAL(storescuLogger, errormsg); + exit(1); + } + else + OFLOG_WARN(storescuLogger, errormsg << ", ignoring file"); + } + ++if_iter; + } + +#ifdef ON_THE_FLY_COMPRESSION + // register global JPEG decompression codecs + DJDecoderRegistration::registerCodecs(); + + // register global JPEG compression codecs + DJEncoderRegistration::registerCodecs(); + + // register JPEG-LS decompression codecs + DJLSDecoderRegistration::registerCodecs(); + + // register JPEG-LS compression codecs + DJLSEncoderRegistration::registerCodecs(); + + // register RLE compression codec + DcmRLEEncoderRegistration::registerCodecs(); + + // register RLE decompression codec + DcmRLEDecoderRegistration::registerCodecs(); +#endif + + /* initialize network, i.e. create an instance of T_ASC_Network*. */ + OFCondition cond = ASC_initializeNetwork(NET_REQUESTOR, 0, opt_acse_timeout, &net); + if (cond.bad()) { + OFLOG_FATAL(storescuLogger, DimseCondition::dump(temp_str, cond)); + return 1; + } + +#ifdef WITH_OPENSSL + + DcmTLSTransportLayer *tLayer = NULL; + if (opt_secureConnection) + { + tLayer = new DcmTLSTransportLayer(DICOM_APPLICATION_REQUESTOR, opt_readSeedFile); + if (tLayer == NULL) + { + OFLOG_FATAL(storescuLogger, "unable to create TLS transport layer"); + exit(1); + } + + if (cmd.findOption("--add-cert-file", 0, OFCommandLine::FOM_First)) + { + const char *current = NULL; + do + { + app.checkValue(cmd.getValue(current)); + if (TCS_ok != tLayer->addTrustedCertificateFile(current, opt_keyFileFormat)) + OFLOG_WARN(storescuLogger, "unable to load certificate file '" << current << "', ignoring"); + } while (cmd.findOption("--add-cert-file", 0, OFCommandLine::FOM_Next)); + } + + if (cmd.findOption("--add-cert-dir", 0, OFCommandLine::FOM_First)) + { + const char *current = NULL; + do + { + app.checkValue(cmd.getValue(current)); + if (TCS_ok != tLayer->addTrustedCertificateDir(current, opt_keyFileFormat)) + OFLOG_WARN(storescuLogger, "unable to load certificates from directory '" << current << "', ignoring"); + } while (cmd.findOption("--add-cert-dir", 0, OFCommandLine::FOM_Next)); + } + + if (opt_dhparam && !(tLayer->setTempDHParameters(opt_dhparam))) + OFLOG_WARN(storescuLogger, "unable to load temporary DH parameter file '" << opt_dhparam << "', ignoring"); + + if (opt_doAuthenticate) + { + if (opt_passwd) tLayer->setPrivateKeyPasswd(opt_passwd); + + if (TCS_ok != tLayer->setPrivateKeyFile(opt_privateKeyFile, opt_keyFileFormat)) + { + OFLOG_ERROR(storescuLogger, "unable to load private TLS key from '" << opt_privateKeyFile << "'"); + return 1; + } + if (TCS_ok != tLayer->setCertificateFile(opt_certificateFile, opt_keyFileFormat)) + { + OFLOG_ERROR(storescuLogger, "unable to load certificate from '" << opt_certificateFile << "'"); + return 1; + } + if (! tLayer->checkPrivateKeyMatchesCertificate()) + { + OFLOG_ERROR(storescuLogger, "private key '" << opt_privateKeyFile << "' and certificate '" << opt_certificateFile << "' do not match"); + return 1; + } + } + + if (TCS_ok != tLayer->setCipherSuites(opt_ciphersuites.c_str())) + { + OFLOG_ERROR(storescuLogger, "unable to set selected cipher suites"); + return 1; + } + + tLayer->setCertificateVerification(opt_certVerification); + + + cond = ASC_setTransportLayer(net, tLayer, 0); + if (cond.bad()) + { + OFLOG_FATAL(storescuLogger, DimseCondition::dump(temp_str, cond)); + return 1; + } + } + +#endif + + /* initialize asscociation parameters, i.e. create an instance of T_ASC_Parameters*. */ + cond = ASC_createAssociationParameters(¶ms, opt_maxReceivePDULength); + if (cond.bad()) { + OFLOG_FATAL(storescuLogger, DimseCondition::dump(temp_str, cond)); + return 1; + } + /* sets this application's title and the called application's title in the params */ + /* structure. The default values to be set here are "STORESCU" and "ANY-SCP". */ + ASC_setAPTitles(params, opt_ourTitle, opt_peerTitle, NULL); + + /* Set the transport layer type (type of network connection) in the params */ + /* strucutre. The default is an insecure connection; where OpenSSL is */ + /* available the user is able to request an encrypted,secure connection. */ + cond = ASC_setTransportLayerType(params, opt_secureConnection); + if (cond.bad()) { + OFLOG_FATAL(storescuLogger, DimseCondition::dump(temp_str, cond)); + return 1; + } + + /* Figure out the presentation addresses and copy the */ + /* corresponding values into the association parameters.*/ + gethostname(localHost, sizeof(localHost) - 1); + sprintf(peerHost, "%s:%d", opt_peer, OFstatic_cast(int, opt_port)); + ASC_setPresentationAddresses(params, localHost, peerHost); + + /* Configure User Identity Negotiation*/ + if (opt_identMode != ASC_USER_IDENTITY_NONE) + { + cond = configureUserIdentityRequest(params); + if (cond.bad()) + return 1; + } + + if (opt_profileName) + { + /* perform name mangling for config file key */ + OFString sprofile; + const unsigned char *c = OFreinterpret_cast(const unsigned char *, opt_profileName); + while (*c) + { + if (!isspace(*c)) sprofile += OFstatic_cast(char, toupper(*c)); + ++c; + } + + /* set presentation contexts as defined in config file */ + cond = asccfg.setAssociationParameters(sprofile.c_str(), *params); + } + else + { + /* Set the presentation contexts which will be negotiated */ + /* when the network connection will be established */ + cond = addStoragePresentationContexts(params, sopClassUIDList); + } + + if (cond.bad()) { + OFLOG_FATAL(storescuLogger, DimseCondition::dump(temp_str, cond)); + return 1; + } + + /* dump presentation contexts if required */ + if (opt_showPresentationContexts) + OFLOG_INFO(storescuLogger, "Request Parameters:" << OFendl << ASC_dumpParameters(temp_str, params, ASC_ASSOC_RQ)); + else + OFLOG_DEBUG(storescuLogger, "Request Parameters:" << OFendl << ASC_dumpParameters(temp_str, params, ASC_ASSOC_RQ)); + + /* create association, i.e. try to establish a network connection to another */ + /* DICOM application. This call creates an instance of T_ASC_Association*. */ + OFLOG_INFO(storescuLogger, "Requesting Association"); + cond = ASC_requestAssociation(net, params, &assoc); + if (cond.bad()) { + if (cond == DUL_ASSOCIATIONREJECTED) { + T_ASC_RejectParameters rej; + + ASC_getRejectParameters(params, &rej); + OFLOG_FATAL(storescuLogger, "Association Rejected:" << OFendl << ASC_printRejectParameters(temp_str, &rej)); + return 1; + } else { + OFLOG_FATAL(storescuLogger, "Association Request Failed: " << DimseCondition::dump(temp_str, cond)); + return 1; + } + } + + /* dump the connection parameters if in debug mode*/ + OFLOG_DEBUG(storescuLogger, ASC_dumpConnectionParameters(temp_str, assoc)); + + /* dump the presentation contexts which have been accepted/refused */ + if (opt_showPresentationContexts) + OFLOG_INFO(storescuLogger, "Association Parameters Negotiated:" << OFendl << ASC_dumpParameters(temp_str, params, ASC_ASSOC_AC)); + else + OFLOG_DEBUG(storescuLogger, "Association Parameters Negotiated:" << OFendl << ASC_dumpParameters(temp_str, params, ASC_ASSOC_AC)); + + /* count the presentation contexts which have been accepted by the SCP */ + /* If there are none, finish the execution */ + if (ASC_countAcceptedPresentationContexts(params) == 0) { + OFLOG_FATAL(storescuLogger, "No Acceptable Presentation Contexts"); + return 1; + } + + /* check user authentication response (if applicable) */ + cond = checkUserIdentityResponse(params); + if (cond.bad()) + { + OFLOG_FATAL(storescuLogger, DimseCondition::dump(temp_str, cond)); + return 1; + } + /* dump general information concerning the establishment of the network connection if required */ + OFLOG_INFO(storescuLogger, "Association Accepted (Max Send PDV: " << assoc->sendPDVLength << ")"); + + /* do the real work, i.e. for all files which were specified in the */ + /* command line, transmit the encapsulated DICOM objects to the SCP. */ + cond = EC_Normal; + OFListIterator(OFString) iter = fileNameList.begin(); + OFListIterator(OFString) enditer = fileNameList.end(); + + while ((iter != enditer) && cond.good()) + { + cond = cstore(assoc, *iter); + ++iter; + } + + /* tear down association, i.e. terminate network connection to SCP */ + if (cond == EC_Normal) + { + if (opt_abortAssociation) { + OFLOG_INFO(storescuLogger, "Aborting Association"); + cond = ASC_abortAssociation(assoc); + if (cond.bad()) { + OFLOG_ERROR(storescuLogger, "Association Abort Failed: " << DimseCondition::dump(temp_str, cond)); + return 1; + } + } else { + /* release association */ + OFLOG_INFO(storescuLogger, "Releasing Association"); + cond = ASC_releaseAssociation(assoc); + if (cond.bad()) + { + OFLOG_ERROR(storescuLogger, "Association Release Failed: " << DimseCondition::dump(temp_str, cond)); + return 1; + } + } + } + else if (cond == DUL_PEERREQUESTEDRELEASE) + { + OFLOG_ERROR(storescuLogger, "Protocol Error: Peer requested release (Aborting)"); + OFLOG_INFO(storescuLogger, "Aborting Association"); + cond = ASC_abortAssociation(assoc); + if (cond.bad()) { + OFLOG_ERROR(storescuLogger, "Association Abort Failed: " << DimseCondition::dump(temp_str, cond)); + return 1; + } + } + else if (cond == DUL_PEERABORTEDASSOCIATION) + { + OFLOG_INFO(storescuLogger, "Peer Aborted Association"); + } + else + { + OFLOG_ERROR(storescuLogger, "Store SCU Failed: " << DimseCondition::dump(temp_str, cond)); + OFLOG_INFO(storescuLogger, "Aborting Association"); + cond = ASC_abortAssociation(assoc); + if (cond.bad()) { + OFLOG_ERROR(storescuLogger, "Association Abort Failed: " << DimseCondition::dump(temp_str, cond)); + return 1; + } + } + + /* destroy the association, i.e. free memory of T_ASC_Association* structure. This */ + /* call is the counterpart of ASC_requestAssociation(...) which was called above. */ + cond = ASC_destroyAssociation(&assoc); + if (cond.bad()) { + OFLOG_FATAL(storescuLogger, DimseCondition::dump(temp_str, cond)); + return 1; + } + /* drop the network, i.e. free memory of T_ASC_Network* structure. This call */ + /* is the counterpart of ASC_initializeNetwork(...) which was called above. */ + cond = ASC_dropNetwork(&net); + if (cond.bad()) { + OFLOG_FATAL(storescuLogger, DimseCondition::dump(temp_str, cond)); + return 1; + } + +#ifdef HAVE_WINSOCK_H + WSACleanup(); +#endif + +#ifdef WITH_OPENSSL + if (tLayer && opt_writeSeedFile) + { + if (tLayer->canWriteRandomSeed()) + { + if (!tLayer->writeRandomSeed(opt_writeSeedFile)) + OFLOG_WARN(storescuLogger, "cannot write random seed file '" << opt_writeSeedFile << "', ignoring"); + } else + OFLOG_WARN(storescuLogger, "cannot write random seed, ignoring"); + } + delete tLayer; +#endif + + int exitCode = 0; + if (opt_haltOnUnsuccessfulStore && unsuccessfulStoreEncountered) { + if (lastStatusCode == STATUS_Success) { + // there must have been some kind of general network error + exitCode = 0xff; + } else { + exitCode = (lastStatusCode >> 8); // only the least significant byte is relevant as exit code + } + } + +#ifdef ON_THE_FLY_COMPRESSION + // deregister JPEG codecs + DJDecoderRegistration::cleanup(); + DJEncoderRegistration::cleanup(); + + // deregister JPEG-LS codecs + DJLSDecoderRegistration::cleanup(); + DJLSEncoderRegistration::cleanup(); + + // deregister RLE codecs + DcmRLEDecoderRegistration::cleanup(); + DcmRLEEncoderRegistration::cleanup(); +#endif + +#ifdef DEBUG + dcmDataDict.clear(); /* useful for debugging with dmalloc */ +#endif + return exitCode; +} + + +static OFBool +isaListMember(OFList &lst, OFString &s) +{ + OFListIterator(OFString) cur = lst.begin(); + OFListIterator(OFString) end = lst.end(); + + OFBool found = OFFalse; + while (cur != end && !found) { + found = (s == *cur); + ++cur; + } + + return found; +} + +static OFCondition +addPresentationContext(T_ASC_Parameters *params, + int presentationContextId, + const OFString &abstractSyntax, + const OFString &transferSyntax, + T_ASC_SC_ROLE proposedRole = ASC_SC_ROLE_DEFAULT) +{ + const char *c_p = transferSyntax.c_str(); + OFCondition cond = ASC_addPresentationContext(params, presentationContextId, + abstractSyntax.c_str(), &c_p, 1, proposedRole); + return cond; +} + +static OFCondition +addPresentationContext(T_ASC_Parameters *params, + int presentationContextId, + const OFString &abstractSyntax, + const OFList &transferSyntaxList, + T_ASC_SC_ROLE proposedRole = ASC_SC_ROLE_DEFAULT) +{ + // create an array of supported/possible transfer syntaxes + const char **transferSyntaxes = new const char*[transferSyntaxList.size()]; + int transferSyntaxCount = 0; + OFListConstIterator(OFString) s_cur = transferSyntaxList.begin(); + OFListConstIterator(OFString) s_end = transferSyntaxList.end(); + while (s_cur != s_end) { + transferSyntaxes[transferSyntaxCount++] = (*s_cur).c_str(); + ++s_cur; + } + + OFCondition cond = ASC_addPresentationContext(params, presentationContextId, + abstractSyntax.c_str(), transferSyntaxes, transferSyntaxCount, proposedRole); + + delete[] transferSyntaxes; + return cond; +} + +static OFCondition +addStoragePresentationContexts(T_ASC_Parameters *params, + OFList &sopClasses) +{ + /* + * Each SOP Class will be proposed in two presentation contexts (unless + * the opt_combineProposedTransferSyntaxes global variable is true). + * The command line specified a preferred transfer syntax to use. + * This prefered transfer syntax will be proposed in one + * presentation context and a set of alternative (fallback) transfer + * syntaxes will be proposed in a different presentation context. + * + * Generally, we prefer to use Explicitly encoded transfer syntaxes + * and if running on a Little Endian machine we prefer + * LittleEndianExplicitTransferSyntax to BigEndianTransferSyntax. + * Some SCP implementations will just select the first transfer + * syntax they support (this is not part of the standard) so + * organise the proposed transfer syntaxes to take advantage + * of such behaviour. + */ + + // Which transfer syntax was preferred on the command line + OFString preferredTransferSyntax; + if (opt_networkTransferSyntax == EXS_Unknown) { + /* gLocalByteOrder is defined in dcxfer.h */ + if (gLocalByteOrder == EBO_LittleEndian) { + /* we are on a little endian machine */ + preferredTransferSyntax = UID_LittleEndianExplicitTransferSyntax; + } else { + /* we are on a big endian machine */ + preferredTransferSyntax = UID_BigEndianExplicitTransferSyntax; + } + } else { + DcmXfer xfer(opt_networkTransferSyntax); + preferredTransferSyntax = xfer.getXferID(); + } + + OFListIterator(OFString) s_cur; + OFListIterator(OFString) s_end; + + OFList fallbackSyntaxes; + // - If little endian implicit is preferred, we don't need any fallback syntaxes + // because it is the default transfer syntax and all applications must support it. + // - If MPEG2 or MPEG4 is preferred, we don't want to propose any fallback solution + // because this is not required and we cannot decompress the movie anyway. + if ((opt_networkTransferSyntax != EXS_LittleEndianImplicit) && + (opt_networkTransferSyntax != EXS_MPEG2MainProfileAtMainLevel) && + (opt_networkTransferSyntax != EXS_MPEG2MainProfileAtHighLevel) && + (opt_networkTransferSyntax != EXS_MPEG4HighProfileLevel4_1) && + (opt_networkTransferSyntax != EXS_MPEG4BDcompatibleHighProfileLevel4_1)) + { + fallbackSyntaxes.push_back(UID_LittleEndianExplicitTransferSyntax); + fallbackSyntaxes.push_back(UID_BigEndianExplicitTransferSyntax); + fallbackSyntaxes.push_back(UID_LittleEndianImplicitTransferSyntax); + // Remove the preferred syntax from the fallback list + fallbackSyntaxes.remove(preferredTransferSyntax); + } + + // create a list of transfer syntaxes combined from the preferred and fallback syntaxes + OFList combinedSyntaxes; + s_cur = fallbackSyntaxes.begin(); + s_end = fallbackSyntaxes.end(); + combinedSyntaxes.push_back(preferredTransferSyntax); + while (s_cur != s_end) + { + if (!isaListMember(combinedSyntaxes, *s_cur)) combinedSyntaxes.push_back(*s_cur); + ++s_cur; + } + + if (!opt_proposeOnlyRequiredPresentationContexts) { + // add the (short list of) known storage SOP classes to the list + // the array of Storage SOP Class UIDs comes from dcuid.h + for (int i = 0; i < numberOfDcmShortSCUStorageSOPClassUIDs; i++) + sopClasses.push_back(dcmShortSCUStorageSOPClassUIDs[i]); + } + + // thin out the SOP classes to remove any duplicates + OFList sops; + s_cur = sopClasses.begin(); + s_end = sopClasses.end(); + while (s_cur != s_end) { + if (!isaListMember(sops, *s_cur)) { + sops.push_back(*s_cur); + } + ++s_cur; + } + + // add a presentations context for each SOP class / transfer syntax pair + OFCondition cond = EC_Normal; + int pid = 1; // presentation context id + s_cur = sops.begin(); + s_end = sops.end(); + while (s_cur != s_end && cond.good()) { + + if (pid > 255) { + OFLOG_ERROR(storescuLogger, "Too many presentation contexts"); + return ASC_BADPRESENTATIONCONTEXTID; + } + + if (opt_combineProposedTransferSyntaxes) { + cond = addPresentationContext(params, pid, *s_cur, combinedSyntaxes); + pid += 2; /* only odd presentation context id's */ + } else { + + // SOP class with preferred transfer syntax + cond = addPresentationContext(params, pid, *s_cur, preferredTransferSyntax); + pid += 2; /* only odd presentation context id's */ + + if (fallbackSyntaxes.size() > 0) { + if (pid > 255) { + OFLOG_ERROR(storescuLogger, "Too many presentation contexts"); + return ASC_BADPRESENTATIONCONTEXTID; + } + + // SOP class with fallback transfer syntax + cond = addPresentationContext(params, pid, *s_cur, fallbackSyntaxes); + pid += 2; /* only odd presentation context id's */ + } + } + ++s_cur; + } + + return cond; +} + +static int +secondsSince1970() +{ + time_t t = time(NULL); + return OFstatic_cast(int, t); +} + +static OFString +intToString(int i) +{ + char numbuf[32]; + sprintf(numbuf, "%d", i); + return numbuf; +} + +static OFString +makeUID(OFString basePrefix, int counter) +{ + OFString prefix = basePrefix + "." + intToString(counter); + char uidbuf[65]; + OFString uid = dcmGenerateUniqueIdentifier(uidbuf, prefix.c_str()); + return uid; +} + +static OFBool +updateStringAttributeValue(DcmItem *dataset, const DcmTagKey &key, OFString &value) +{ + DcmStack stack; + DcmTag tag(key); + + OFCondition cond = EC_Normal; + cond = dataset->search(key, stack, ESM_fromHere, OFFalse); + if (cond != EC_Normal) { + OFLOG_ERROR(storescuLogger, "updateStringAttributeValue: cannot find: " << tag.getTagName() + << " " << key << ": " << cond.text()); + return OFFalse; + } + + DcmElement *elem = OFstatic_cast(DcmElement *, stack.top()); + + DcmVR vr(elem->ident()); + if (elem->getLength() > vr.getMaxValueLength()) { + OFLOG_ERROR(storescuLogger, "updateStringAttributeValue: INTERNAL ERROR: " << tag.getTagName() + << " " << key << ": value too large (max " << vr.getMaxValueLength() + << ") for " << vr.getVRName() << " value: " << value); + return OFFalse; + } + + cond = elem->putOFStringArray(value); + if (cond != EC_Normal) { + OFLOG_ERROR(storescuLogger, "updateStringAttributeValue: cannot put string in attribute: " << tag.getTagName() + << " " << key << ": " << cond.text()); + return OFFalse; + } + + return OFTrue; +} + +static void +replaceSOPInstanceInformation(DcmDataset *dataset) +{ + static OFCmdUnsignedInt patientCounter = 0; + static OFCmdUnsignedInt studyCounter = 0; + static OFCmdUnsignedInt seriesCounter = 0; + static OFCmdUnsignedInt imageCounter = 0; + static OFString seriesInstanceUID; + static OFString seriesNumber; + static OFString studyInstanceUID; + static OFString studyID; + static OFString accessionNumber; + static OFString patientID; + static OFString patientName; + + if (seriesInstanceUID.empty()) seriesInstanceUID=makeUID(SITE_SERIES_UID_ROOT, OFstatic_cast(int, seriesCounter)); + if (seriesNumber.empty()) seriesNumber = intToString(OFstatic_cast(int, seriesCounter)); + if (studyInstanceUID.empty()) studyInstanceUID = makeUID(SITE_STUDY_UID_ROOT, OFstatic_cast(int, studyCounter)); + if (studyID.empty()) studyID = studyIDPrefix + intToString(OFstatic_cast(int, secondsSince1970())) + intToString(OFstatic_cast(int, studyCounter)); + if (accessionNumber.empty()) accessionNumber = accessionNumberPrefix + intToString(secondsSince1970()) + intToString(OFstatic_cast(int, studyCounter)); + if (patientID.empty()) patientID = patientIDPrefix + intToString(secondsSince1970()) + intToString(OFstatic_cast(int, patientCounter)); + if (patientName.empty()) patientName = patientNamePrefix + intToString(secondsSince1970()) + intToString(OFstatic_cast(int, patientCounter)); + + if (imageCounter >= opt_inventSeriesCount) { + imageCounter = 0; + seriesCounter++; + seriesInstanceUID = makeUID(SITE_SERIES_UID_ROOT, OFstatic_cast(int, seriesCounter)); + seriesNumber = intToString(OFstatic_cast(int, seriesCounter)); + } + if (seriesCounter >= opt_inventStudyCount) { + seriesCounter = 0; + studyCounter++; + studyInstanceUID = makeUID(SITE_STUDY_UID_ROOT, OFstatic_cast(int, studyCounter)); + studyID = studyIDPrefix + intToString(secondsSince1970()) + intToString(OFstatic_cast(int, studyCounter)); + accessionNumber = accessionNumberPrefix + intToString(secondsSince1970()) + intToString(OFstatic_cast(int, studyCounter)); + } + if (studyCounter >= opt_inventPatientCount) { + // we create as many patients as necessary */ + studyCounter = 0; + patientCounter++; + patientID = patientIDPrefix + intToString(secondsSince1970()) + intToString(OFstatic_cast(int, patientCounter)); + patientName = patientNamePrefix + intToString(secondsSince1970()) + intToString(OFstatic_cast(int, patientCounter)); + } + + OFString sopInstanceUID = makeUID(SITE_INSTANCE_UID_ROOT, OFstatic_cast(int, imageCounter)); + OFString imageNumber = intToString(OFstatic_cast(int, imageCounter)); + + OFLOG_INFO(storescuLogger, "Inventing Identifying Information (" + << "pa" << patientCounter << ", st" << studyCounter + << ", se" << seriesCounter << ", im" << imageCounter << "):"); + OFLOG_INFO(storescuLogger, " PatientName=" << patientName); + OFLOG_INFO(storescuLogger, " PatientID=" << patientID); + OFLOG_INFO(storescuLogger, " StudyInstanceUID=" << studyInstanceUID); + OFLOG_INFO(storescuLogger, " StudyID=" << studyID); + OFLOG_INFO(storescuLogger, " SeriesInstanceUID=" << seriesInstanceUID); + OFLOG_INFO(storescuLogger, " SeriesNumber=" << seriesNumber); + OFLOG_INFO(storescuLogger, " SOPInstanceUID=" << sopInstanceUID); + OFLOG_INFO(storescuLogger, " ImageNumber=" << imageNumber); + + updateStringAttributeValue(dataset, DCM_PatientName, patientName); + updateStringAttributeValue(dataset, DCM_PatientID, patientID); + updateStringAttributeValue(dataset, DCM_StudyInstanceUID, studyInstanceUID); + updateStringAttributeValue(dataset, DCM_StudyID, studyID); + updateStringAttributeValue(dataset, DCM_SeriesInstanceUID, seriesInstanceUID); + updateStringAttributeValue(dataset, DCM_SeriesNumber, seriesNumber); + updateStringAttributeValue(dataset, DCM_SOPInstanceUID, sopInstanceUID); + updateStringAttributeValue(dataset, DCM_InstanceNumber, imageNumber); + + imageCounter++; +} + +static void +progressCallback(void * /*callbackData*/, + T_DIMSE_StoreProgress *progress, + T_DIMSE_C_StoreRQ * req) +{ + if (progress->state == DIMSE_StoreBegin) + { + OFString str; + OFLOG_DEBUG(storescuLogger, DIMSE_dumpMessage(str, *req, DIMSE_OUTGOING)); + } + + // We can't use oflog for the pdu output, but we use a special logger for + // generating this output. If it is set to level "INFO" we generate the + // output, if it's set to "DEBUG" then we'll assume that there is debug output + // generated for each PDU elsewhere. + OFLogger progressLogger = OFLog::getLogger("dcmtk.apps." OFFIS_CONSOLE_APPLICATION ".progress"); + if (progressLogger.getChainedLogLevel() == OFLogger::INFO_LOG_LEVEL) { + switch (progress->state) { + case DIMSE_StoreBegin: + COUT << "XMIT: "; break; + case DIMSE_StoreEnd: + COUT << OFendl; break; + default: + COUT << "."; break; + } + COUT.flush(); + } +} + +static OFCondition +storeSCU(T_ASC_Association *assoc, const char *fname) + /* + * This function will read all the information from the given file, + * figure out a corresponding presentation context which will be used + * to transmit the information over the network to the SCP, and it + * will finally initiate the transmission of all data to the SCP. + * + * Parameters: + * assoc - [in] The association (network connection to another DICOM application). + * fname - [in] Name of the file which shall be processed. + */ +{ + DIC_US msgId = assoc->nextMsgID++; + T_ASC_PresentationContextID presID; + T_DIMSE_C_StoreRQ req; + T_DIMSE_C_StoreRSP rsp; + DIC_UI sopClass; + DIC_UI sopInstance; + DcmDataset *statusDetail = NULL; + + unsuccessfulStoreEncountered = OFTrue; // assumption + + OFLOG_INFO(storescuLogger, "Sending file: " << fname); + + /* read information from file. After the call to DcmFileFormat::loadFile(...) the information */ + /* which is encapsulated in the file will be available through the DcmFileFormat object. */ + /* In detail, it will be available through calls to DcmFileFormat::getMetaInfo() (for */ + /* meta header information) and DcmFileFormat::getDataset() (for data set information). */ + DcmFileFormat dcmff; + OFCondition cond = dcmff.loadFile(fname, EXS_Unknown, EGL_noChange, DCM_MaxReadLength, opt_readMode); + + /* figure out if an error occured while the file was read*/ + if (cond.bad()) { + OFLOG_ERROR(storescuLogger, "Bad DICOM file: " << fname << ": " << cond.text()); + return cond; + } + + /* if required, invent new SOP instance information for the current data set (user option) */ + if (opt_inventSOPInstanceInformation) { + replaceSOPInstanceInformation(dcmff.getDataset()); + } + + /* figure out which SOP class and SOP instance is encapsulated in the file */ + if (!DU_findSOPClassAndInstanceInDataSet(dcmff.getDataset(), + sopClass, sopInstance, opt_correctUIDPadding)) { + OFLOG_ERROR(storescuLogger, "No SOP Class or Instance UID in file: " << fname); + return DIMSE_BADDATA; + } + + /* figure out which of the accepted presentation contexts should be used */ + DcmXfer filexfer(dcmff.getDataset()->getOriginalXfer()); + + /* special case: if the file uses an unencapsulated transfer syntax (uncompressed + * or deflated explicit VR) and we prefer deflated explicit VR, then try + * to find a presentation context for deflated explicit VR first. + */ + if (filexfer.isNotEncapsulated() && + opt_networkTransferSyntax == EXS_DeflatedLittleEndianExplicit) + { + filexfer = EXS_DeflatedLittleEndianExplicit; + } + + if (filexfer.getXfer() != EXS_Unknown) + presID = ASC_findAcceptedPresentationContextID(assoc, sopClass, filexfer.getXferID()); + else + presID = ASC_findAcceptedPresentationContextID(assoc, sopClass); + if (presID == 0) { + const char *modalityName = dcmSOPClassUIDToModality(sopClass); + if (!modalityName) modalityName = dcmFindNameOfUID(sopClass); + if (!modalityName) modalityName = "unknown SOP class"; + OFLOG_ERROR(storescuLogger, "No presentation context for: (" << modalityName << ") " << sopClass); + return DIMSE_NOVALIDPRESENTATIONCONTEXTID; + } + + T_ASC_PresentationContext pc; + ASC_findAcceptedPresentationContext(assoc->params, presID, &pc); + DcmXfer netTransfer(pc.acceptedTransferSyntax); + + /* if required, dump general information concerning transfer syntaxes */ + if (storescuLogger.isEnabledFor(OFLogger::INFO_LOG_LEVEL)) { + DcmXfer fileTransfer(dcmff.getDataset()->getOriginalXfer()); + OFLOG_INFO(storescuLogger, "Converting transfer syntax: " << fileTransfer.getXferName() + << " -> " << netTransfer.getXferName()); + } + +#ifdef ON_THE_FLY_COMPRESSION + dcmff.getDataset()->chooseRepresentation(netTransfer.getXfer(), NULL); +#endif + + /* prepare the transmission of data */ + bzero(OFreinterpret_cast(char *, &req), sizeof(req)); + req.MessageID = msgId; + strcpy(req.AffectedSOPClassUID, sopClass); + strcpy(req.AffectedSOPInstanceUID, sopInstance); + req.DataSetType = DIMSE_DATASET_PRESENT; + req.Priority = DIMSE_PRIORITY_LOW; + + /* if required, dump some more general information */ + OFLOG_INFO(storescuLogger, "Sending Store Request (MsgID " << msgId << ", " + << dcmSOPClassUIDToModality(sopClass, "OT") << ")"); + + /* finally conduct transmission of data */ + cond = DIMSE_storeUser(assoc, presID, &req, + NULL, dcmff.getDataset(), progressCallback, NULL, + opt_blockMode, opt_dimse_timeout, + &rsp, &statusDetail, NULL, OFStandard::getFileSize(fname)); + + /* + * If store command completed normally, with a status + * of success or some warning then the image was accepted. + */ + if (cond == EC_Normal && (rsp.DimseStatus == STATUS_Success || DICOM_WARNING_STATUS(rsp.DimseStatus))) { + unsuccessfulStoreEncountered = OFFalse; + } + + /* remember the response's status for later transmissions of data */ + lastStatusCode = rsp.DimseStatus; + + /* dump some more general information */ + if (cond == EC_Normal) + { + OFString temp_str; + if (storescuLogger.isEnabledFor(OFLogger::DEBUG_LOG_LEVEL)) + { + OFLOG_INFO(storescuLogger, "Received Store Response"); + OFLOG_DEBUG(storescuLogger, DIMSE_dumpMessage(temp_str, rsp, DIMSE_INCOMING, NULL, presID)); + } else { + OFLOG_INFO(storescuLogger, "Received Store Response (" << DU_cstoreStatusString(rsp.DimseStatus) << ")"); + } + } + else + { + OFString temp_str; + OFLOG_ERROR(storescuLogger, "Store Failed, file: " << fname << ":" << OFendl << DimseCondition::dump(temp_str, cond)); + } + + /* dump status detail information if there is some */ + if (statusDetail != NULL) { + OFLOG_DEBUG(storescuLogger, "Status Detail:" << OFendl << DcmObject::PrintHelper(*statusDetail)); + delete statusDetail; + } + /* return */ + return cond; +} + + +static OFCondition +cstore(T_ASC_Association *assoc, const OFString &fname) + /* + * This function will process the given file as often as is specified by opt_repeatCount. + * "Process" in this case means "read file, send C-STORE-RQ, receive C-STORE-RSP". + * + * Parameters: + * assoc - [in] The association (network connection to another DICOM application). + * fname - [in] Name of the file which shall be processed. + */ +{ + OFCondition cond = EC_Normal; + + /* opt_repeatCount specifies how many times a certain file shall be processed */ + int n = OFstatic_cast(int, opt_repeatCount); + + /* as long as no error occured and the counter does not equal 0 */ + while ((cond.good()) && n-- && !(opt_haltOnUnsuccessfulStore && unsuccessfulStoreEncountered)) + { + /* process file (read file, send C-STORE-RQ, receive C-STORE-RSP) */ + cond = storeSCU(assoc, fname.c_str()); + } + + // we don't want to return an error code if --no-halt was specified. + if (!opt_haltOnUnsuccessfulStore) + { + cond = EC_Normal; + } + + /* return result value */ + return cond; +} + + +static OFBool +findSOPClassAndInstanceInFile( + const char *fname, + char *sopClass, + char *sopInstance) +{ + DcmFileFormat ff; + if (!ff.loadFile(fname, EXS_Unknown, EGL_noChange, DCM_MaxReadLength, opt_readMode).good()) + return OFFalse; + + /* look in the meta-header first */ + OFBool found = DU_findSOPClassAndInstanceInDataSet(ff.getMetaInfo(), sopClass, sopInstance, opt_correctUIDPadding); + + if (!found) + found = DU_findSOPClassAndInstanceInDataSet(ff.getDataset(), sopClass, sopInstance, opt_correctUIDPadding); + + return found; +} + + +static OFCondition +configureUserIdentityRequest(T_ASC_Parameters *params) +{ + OFCondition cond = EC_Normal; + switch (opt_identMode) + { + case ASC_USER_IDENTITY_USER: + { + cond = ASC_setIdentRQUserOnly(params, opt_user, opt_identResponse); + return cond; + } + case ASC_USER_IDENTITY_USER_PASSWORD: + { + cond = ASC_setIdentRQUserPassword(params, opt_user, opt_password, opt_identResponse); + return cond; + } + case ASC_USER_IDENTITY_KERBEROS: + case ASC_USER_IDENTITY_SAML: + { + OFFile identFile; + if (!identFile.fopen(opt_identFile.c_str(), "rb")) + { + OFString openerror; + identFile.getLastErrorString(openerror); + OFLOG_ERROR(storescuLogger, "Unable to open Kerberos or SAML file: " << openerror); + return EC_IllegalCall; + } + // determine file size + offile_off_t result = identFile.fseek(0, SEEK_END); + if (result != 0) + return EC_IllegalParameter; + offile_off_t filesize = identFile.ftell(); + identFile.rewind(); + if (filesize > 65535) + { + OFLOG_INFO(storescuLogger, "Kerberos or SAML file is larger than 65535 bytes, bytes after that position are ignored"); + filesize = 65535; + } + + char *buf = new char[OFstatic_cast(unsigned int, filesize)]; + size_t bytesRead = identFile.fread(buf, 1, OFstatic_cast(size_t, filesize)); + identFile.fclose(); + if (bytesRead == 0) + { + OFLOG_ERROR(storescuLogger, "Unable to read Kerberos or SAML info from file: File empty?"); + delete[] buf; + return EC_IllegalCall; + } + if (opt_identMode == ASC_USER_IDENTITY_KERBEROS) + cond = ASC_setIdentRQKerberos(params, buf, bytesRead, opt_identResponse); + else + cond = ASC_setIdentRQSaml(params, buf, bytesRead, opt_identResponse); + delete[] buf; + break; + } + default: + { + cond = EC_IllegalCall; + } + } + if (cond.bad()) + { + OFString temp_str; + OFLOG_FATAL(storescuLogger, DimseCondition::dump(temp_str, cond)); + } + return cond; +} + +static OFCondition +checkUserIdentityResponse(T_ASC_Parameters *params) +{ + if (params == NULL) + return ASC_NULLKEY; + + /* So far it is only checked whether a requested, positive response was + actually received */ + + // In case we sent no user identity request, there are no checks at all + if ((opt_identMode == ASC_USER_IDENTITY_NONE) || (!opt_identResponse)) + return EC_Normal; + + // If positive response was requested, we expect a corresponding response + if ((opt_identMode == ASC_USER_IDENTITY_USER) || (opt_identMode == ASC_USER_IDENTITY_USER_PASSWORD)) + { + UserIdentityNegotiationSubItemAC *rsp = params->DULparams.ackUserIdentNeg; + if (rsp == NULL) + { + OFLOG_ERROR(storescuLogger, "User Identity Negotiation failed: Positive response requested but none received"); + return ASC_USERIDENTIFICATIONFAILED; + } + } + return EC_Normal; +} diff --git a/dcmnet/apps/termscu.cc b/dcmnet/apps/termscu.cc new file mode 100644 index 00000000..3e67b564 --- /dev/null +++ b/dcmnet/apps/termscu.cc @@ -0,0 +1,297 @@ +/* + * + * Copyright (C) 2005-2010, OFFIS e.V. + * All rights reserved. See COPYRIGHT file for details. + * + * This software and supporting documentation were developed by + * + * OFFIS e.V. + * R&D Division Health + * Escherweg 2 + * D-26121 Oldenburg, Germany + * + * + * Module: dcmnet + * + * Author: Thomas Wilkens + * + * Purpose: Termination Service Class User (negotiates the private shutdown + * SOP class in order to shutdown server applications) + * + */ + +// ---------------------------------------------------------------------------- + +#include "dcmtk/config/osconfig.h" + +#define INCLUDE_CSTDLIB +#define INCLUDE_CSTDIO +#define INCLUDE_CSTRING +#define INCLUDE_CSTDARG +#include "dcmtk/ofstd/ofstdinc.h" + +#include "dcmtk/ofstd/ofcmdln.h" +#include "dcmtk/ofstd/ofconapp.h" +#include "dcmtk/dcmdata/cmdlnarg.h" +#include "dcmtk/dcmdata/dcdict.h" +#include "dcmtk/dcmnet/assoc.h" +#include "dcmtk/dcmnet/dimse.h" + +#ifdef WITH_ZLIB +#include +#endif + +// ---------------------------------------------------------------------------- + +#define OFFIS_CONSOLE_APPLICATION "termscu" +#define APPLICATIONTITLE "TERMSCU" +#define PEERAPPLICATIONTITLE "ANY-SCP" +#define SHORTCOL 4 +#define LONGCOL 11 + +static OFLogger termscuLogger = OFLog::getLogger("dcmtk.apps." OFFIS_CONSOLE_APPLICATION); + +// ---------------------------------------------------------------------------- + +int main( int argc, char *argv[] ) +// Date : September 12, 2005 +// Author : Thomas Wilkens +// Task : Main function for this application. +// Parameters : args - [in] Number of command line arguments. +// argv - [in] Command line arguments. +{ + const char *opt_peer = NULL; + OFCmdUnsignedInt opt_port = 104; + const char *opt_peerTitle = PEERAPPLICATIONTITLE; + const char *opt_ourTitle = APPLICATIONTITLE; + OFCmdUnsignedInt opt_maxReceivePDULength = ASC_DEFAULTMAXPDU; + T_ASC_Network *net; + T_ASC_Parameters *params; + T_ASC_Association *assoc; + DIC_NODENAME localHost; + DIC_NODENAME peerHost; + char rcsid[] = "$dcmtk: " OFFIS_CONSOLE_APPLICATION " v" OFFIS_DCMTK_VERSION " " OFFIS_DCMTK_RELEASEDATE " $"; + const char* transferSyntaxes[] = { UID_LittleEndianImplicitTransferSyntax, UID_LittleEndianExplicitTransferSyntax, UID_BigEndianExplicitTransferSyntax }; + int transferSyntaxCount = 3; + +#ifdef HAVE_GUSI_H + // needed for Macintosh + GUSISetup(GUSIwithSIOUXSockets); + GUSISetup(GUSIwithInternetSockets); +#endif + +#ifdef HAVE_WINSOCK_H + WSAData winSockData; + // we need at least version 1.1 + WORD winSockVersionNeeded = MAKEWORD( 1, 1 ); + WSAStartup(winSockVersionNeeded, &winSockData); +#endif + + char tempstr[20]; + OFString temp_str; + OFConsoleApplication app( OFFIS_CONSOLE_APPLICATION , "DICOM termination SCU", rcsid ); + OFCommandLine cmd; + + cmd.setParamColumn( LONGCOL + SHORTCOL + 4 ); + cmd.addParam("peer", "hostname of DICOM peer"); + cmd.addParam("port", "tcp/ip port number of peer"); + + cmd.setOptionColumns( LONGCOL, SHORTCOL ); + cmd.addGroup("general options:", LONGCOL, SHORTCOL + 2); + cmd.addOption("--help", "-h", "print this help text and exit", OFCommandLine::AF_Exclusive); + cmd.addOption("--version", "print version information and exit", OFCommandLine::AF_Exclusive); + OFLog::addOptions(cmd); + + cmd.addGroup("network options:"); + cmd.addSubGroup("application entity titles:"); + OFString opt1 = "set my calling AE title (default: "; + opt1 += APPLICATIONTITLE; + opt1 += ")"; + cmd.addOption("--aetitle", "-aet", 1, "[a]etitle: string", opt1.c_str()); + OFString opt2 = "set called AE title of peer (default: "; + opt2 += PEERAPPLICATIONTITLE; + opt2 += ")"; + cmd.addOption("--call", "-aec", 1, "[a]etitle: string", opt2.c_str()); + cmd.addSubGroup("other network options:"); + OFString opt3 = "set max receive pdu to n bytes (default: "; + sprintf(tempstr, "%ld", OFstatic_cast(long, ASC_DEFAULTMAXPDU)); + opt3 += tempstr; + opt3 += ")"; + OFString opt4 = "[n]umber of bytes: integer ("; + sprintf(tempstr, "%ld", OFstatic_cast(long, ASC_MINIMUMPDUSIZE)); + opt4 += tempstr; + opt4 += ".."; + sprintf(tempstr, "%ld", OFstatic_cast(long, ASC_MAXIMUMPDUSIZE)); + opt4 += tempstr; + opt4 += ")"; + cmd.addOption("--max-pdu", "-pdu", 1, opt4.c_str(), opt3.c_str()); + + // evaluate command line + prepareCmdLineArgs( argc, argv, OFFIS_CONSOLE_APPLICATION ); + if( app.parseCommandLine( cmd, argc, argv ) ) + { + // check exclusive options first + if (cmd.hasExclusiveOption()) + { + if( cmd.findOption("--version") ) + { + app.printHeader( OFTrue /*print host identifier*/ ); + COUT << OFendl << "External libraries used:"; +#ifdef WITH_ZLIB + COUT << OFendl << "- ZLIB, Version " << zlibVersion() << OFendl; +#else + COUT << " none" << OFendl; +#endif + return( 0 ); + } + } + + // command line parameters + cmd.getParam( 1, opt_peer ); + app.checkParam( cmd.getParamAndCheckMinMax( 2, opt_port, 1, 65535 ) ); + + // command line options + OFLog::configureFromCommandLine(cmd, app); + + if( cmd.findOption("--aetitle") ) + app.checkValue( cmd.getValue( opt_ourTitle ) ); + if( cmd.findOption("--call") ) + app.checkValue( cmd.getValue( opt_peerTitle ) ); + if( cmd.findOption("--max-pdu") ) + app.checkValue( cmd.getValueAndCheckMinMax( opt_maxReceivePDULength, ASC_MINIMUMPDUSIZE, ASC_MAXIMUMPDUSIZE ) ); + } + + /* print resource identifier */ + OFLOG_DEBUG(termscuLogger, rcsid << OFendl); + + // make sure data dictionary is loaded + if( !dcmDataDict.isDictionaryLoaded() ) + OFLOG_WARN(termscuLogger, "no data dictionary loaded, check environment variable: " << DCM_DICT_ENVIRONMENT_VARIABLE); + + // initialize network + OFCondition cond = ASC_initializeNetwork( NET_REQUESTOR, 0, 30, &net ); + if( cond.bad() ) + { + OFLOG_FATAL(termscuLogger, DimseCondition::dump(temp_str, cond)); + exit( 1 ); + } + + // initialize asscociation parameters + cond = ASC_createAssociationParameters( ¶ms, opt_maxReceivePDULength ); + if( cond.bad() ) + { + OFLOG_FATAL(termscuLogger, DimseCondition::dump(temp_str, cond)); + exit( 1 ); + } + + // set this application's title and the called application's title in the params structure + ASC_setAPTitles( params, opt_ourTitle, opt_peerTitle, NULL ); + + // set the transport layer type (type of network connection) in the params structure + cond = ASC_setTransportLayerType( params, OFFalse ); + if( cond.bad() ) + { + OFLOG_FATAL(termscuLogger, DimseCondition::dump(temp_str, cond)); + return( 1 ); + } + + // figure out the presentation addresses and copy the + // corresponding values into the association parameters. + gethostname( localHost, sizeof( localHost ) - 1 ); + sprintf( peerHost, "%s:%d", opt_peer, OFstatic_cast(int, opt_port)); + ASC_setPresentationAddresses( params, localHost, peerHost ); + + // set the presentation context which will be negotiated + // when the network connection will be established + cond = ASC_addPresentationContext( params, 1, UID_PrivateShutdownSOPClass, transferSyntaxes, transferSyntaxCount ); + if( cond.bad() ) + { + OFLOG_FATAL(termscuLogger, DimseCondition::dump(temp_str, cond)); + exit(1); + } + + // dump presentation contexts + OFLOG_DEBUG(termscuLogger, "Request Parameters:" << OFendl << ASC_dumpParameters(temp_str, params, ASC_ASSOC_RQ)); + + // dump information + OFLOG_INFO(termscuLogger, "Requesting Association"); + + // create association + cond = ASC_requestAssociation( net, params, &assoc ); + if( cond.bad() ) + { + if( cond == DUL_ASSOCIATIONREJECTED ) + { + T_ASC_RejectParameters rej; + ASC_getRejectParameters( params, &rej ); + OFLOG_FATAL(termscuLogger, "Association Rejected: " << OFendl << ASC_printRejectParameters(temp_str, &rej)); + exit( 1 ); + } + else + { + OFLOG_FATAL(termscuLogger, "Association Request Failed: " << DimseCondition::dump(temp_str, cond)); + exit( 1 ); + } + } + + // dump the presentation contexts which have been accepted/refused + OFLOG_DEBUG(termscuLogger, "Association Parameters Negotiated:" << OFendl << ASC_dumpParameters(temp_str, params, ASC_ASSOC_AC)); + + // count the presentation contexts which have been accepted by the SCP + // If there are none, finish the execution + if( ASC_countAcceptedPresentationContexts( params ) == 0 ) + { + OFLOG_FATAL(termscuLogger, "No Acceptable Presentation Contexts"); + exit( 1 ); + } + + // actually, the execution should never get to this point, because when the + // private shutdown SOP class is negotiated, an association shall always be + // rejected by an SCP; and if this application sends an association request + // to another application which does not know of the private shutdown SOP + // class, the above if-condition should have been met, so that we never + // actually get to this point here; nevertheless, the following code is con- + // tained in this file in order to "do nothing" if an association was accepted + + // dump general information concerning the establishment of the network connection if required + OFLOG_INFO(termscuLogger, "Association Accepted (Max Send PDV: " << assoc->sendPDVLength << ")"); + + // + // do nothing when the association was accepted + // + + // dump information + OFLOG_INFO(termscuLogger, "Releasing Association"); + + // release association + cond = ASC_releaseAssociation( assoc ); + if( cond.bad() ) + { + OFLOG_FATAL(termscuLogger, "Association Release Failed: " << DimseCondition::dump(temp_str, cond)); + exit( 1 ); + } + + // destroy the association + cond = ASC_destroyAssociation( &assoc ); + if( cond.bad() ) + { + OFLOG_FATAL(termscuLogger, DimseCondition::dump(temp_str, cond)); + exit( 1 ); + } + + // drop the network + cond = ASC_dropNetwork( &net ); + if( cond.bad() ) + { + OFLOG_FATAL(termscuLogger, DimseCondition::dump(temp_str, cond)); + exit( 1 ); + } + +#ifdef HAVE_WINSOCK_H + WSACleanup(); +#endif + + return( 0 ); +} + +// ---------------------------------------------------------------------------- diff --git a/dcmnet/configure b/dcmnet/configure new file mode 100755 index 00000000..396668ee --- /dev/null +++ b/dcmnet/configure @@ -0,0 +1,56 @@ +#! /bin/sh + +parentdir=`pwd` +thisdir=$parentdir + +# The following test constructs relative path from the module +# directory to the configuration directory. If you know this path +# you can substitute this with +# configdir= +# It is very important that the configdir path is relative. + +configdir="configdir" + +while test "$parentdir" != "/" -a "$configdir" = "configdir"; do + if test -d "$parentdir/config" ; then + configdir=$parentdir/config + else + parentdir=`echo $parentdir | sed 's/\/[^\/]*$//'` + fi +done + +if test "$configdir" = "configdir" ; then + echo "Cannot find configure directory" + exit 1 +fi + +if test $# != 0; then + case $1 in + -a) + shift + cd "$configdir" + echo "running configure in config-directory" + ./configure $* + cd $thisdir + echo "running configure for this module" + sh "$configdir/confmod" --srcdir=. $* + ;; + -c) + shift + cd "$configdir" + echo "running configure in config-directory" + ./configure $* + ;; + *) + echo "running configure for this module" + sh "$configdir/confmod" --srcdir=. $* + ;; + esac +else + echo "running configure for this module" + sh "$configdir/confmod" --srcdir=. $* +fi + + + + diff --git a/dcmnet/data/Makefile.in b/dcmnet/data/Makefile.in new file mode 100644 index 00000000..c0d3ac06 --- /dev/null +++ b/dcmnet/data/Makefile.in @@ -0,0 +1,23 @@ +# +# Makefile for dcmnet/data +# + +@SET_MAKE@ + +SHELL = /bin/sh +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +configdir = @top_srcdir@/@configdir@ + +include $(configdir)/@common_makefile@ + + +all: + +install: + +clean: + rm -f $(TRASH) + +distclean: + rm -f $(DISTTRASH) diff --git a/dcmnet/docs/CMakeLists.txt b/dcmnet/docs/CMakeLists.txt new file mode 100644 index 00000000..0e7ee00c --- /dev/null +++ b/dcmnet/docs/CMakeLists.txt @@ -0,0 +1,2 @@ +# declare installation files +INSTALL(FILES asconfig.txt testing.txt DESTINATION ${DCMTK_INSTALL_DOCDIR} COMPONENT doc) diff --git a/dcmnet/docs/Makefile.in b/dcmnet/docs/Makefile.in new file mode 100644 index 00000000..06cd2d07 --- /dev/null +++ b/dcmnet/docs/Makefile.in @@ -0,0 +1,29 @@ +# +# Makefile for dcmnet/docs +# + +@SET_MAKE@ + +SHELL = /bin/sh +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +configdir = @top_srcdir@/@configdir@ + +include $(configdir)/@common_makefile@ + +files = asconfig.txt testing.txt + + +all: + +install: + $(configdir)/mkinstalldirs $(DESTDIR)$(docdir) + for file in $(files); do \ + $(INSTALL_DATA) $$file $(DESTDIR)$(docdir) ;\ + done + +clean: + rm -f $(TRASH) + +distclean: + rm -f $(DISTTRASH) diff --git a/dcmnet/docs/asconfig.txt b/dcmnet/docs/asconfig.txt new file mode 100644 index 00000000..53080e94 --- /dev/null +++ b/dcmnet/docs/asconfig.txt @@ -0,0 +1,236 @@ + +ASSOCIATION NEGOTIATION PROFILES AND CONFIGURATION FILES + + Beginning with release 3.5.3, DCMTK provides a flexible mechanism for + specifying the DICOM network association negotiation behaviour of an + application, based on so-called "association negotiation profiles" + which may be read from a configuration file. + + This mechanism is currently enabled in the storescu and storescp + applications. + + +1. CONFIGURATION FILE FORMAT + + The configuration file is a simple text file resembling well-known + "INI" files on the Windows platform. Lines consisting only of + whitespace characters and comment lines starting with a '#' character + in the first column are ignored. Configuration file entries use the + following syntax: + Key = Value + + The key must start in the first column of the line. The case is not + significant for the key, however, it is for the value. Whitespace + characters before and after the '=' separating key and value are + ignored. + + Entries are grouped into sections using section headings, which are + also insensitive to case and whitespace characters: + [Section] + + The well-known "INI" syntax is extended by the definition of + supersections which define a grouping for sections, using the + following syntax: + [[Supersection]] + + The content of the configuration file needs to establish a true tree + structure, i. e. each setting must be part of a section and each + section must be part of one supersection. + + +2. CONFIGURATION FILE STRUCTURE + + A configuration file for association negotiation profiles may contain + the following supersections: + [[TransferSyntaxes]] + [[PresentationContexts]] + [[Profiles]] + [[SCPSCURoleSelection]] + [[ExtendedNegotiation]] + The first three supersections are mandatory, the others are optional. + + +2.1 TRANSFER SYNTAXES + +This supersection contains one or more sections with arbitrary +user-defined but unique section names that are used as symbolic labels. +Within each section, one or more key/value pairs are contained. The key +names are "TransferSyntax1", "TransferSyntax2" etc. (without leading +zeroes before the number!), in increasing order. + +The values may either be DICOM Unique Identifiers (UIDs) in the form +defined by the DICOM standard, or symbolic UID names as used throughout +DCMTK and defined in the "UID Name Map" in file dcmdata/libsrc/dcuid.cc. +Each value must denote a standard or private DICOM transfer syntax. +Within each section (transfer syntax list), no transfer syntax should be +repeated. + +The following example shows two sections (transfer syntax lists), one +using symbolic transfer syntax names, another using a numeric UID. + +[Uncompressed] +TransferSyntax1 = LittleEndianExplicit +TransferSyntax2 = BigEndianExplicit +TransferSyntax3 = LittleEndianImplicit + +[JPEGBaseline] +TransferSyntax1 = 1.2.840.10008.1.2.4.50 + +There are two special symbolic transfer syntax names that are recognized +by the parser: "LocalEndianExplicit" and "OppositeEndianExplicit". These +are interpreted at runtime depending on the byte order of the machine +on which the application is executed: + +On a little endian machine (e.g. x86) + - "LocalEndianExplicit" is interpreted as "LittleEndianExplicit" + - "OppositeEndianExplicit" is interpreted as "BigEndianExplicit" + +On a big endian machine (Sparc, M68K, MIPS) + - "LocalEndianExplicit" is interpreted as "BigEndianExplicit" + - "OppositeEndianExplicit" is interpreted as "LittleEndianExplicit" + + +2.2 PRESENTATION CONTEXTS + +This supersection contains one or more sections with arbitrary +user-defined but unique section names that are used as symbolic labels. +Within each section, one or more key/value pairs are contained. The key +names are "PresentationContext1", "PresentationContext2" etc., in +increasing order. Each list must not contain more than 128 entries, +due to the limitation of the DICOM network protocol to 128 presentation +contexts per association. + +Each value consists of two parts, separated by a single backslash +character ('\'). The first value denotes a DICOM SOP Class UID or +Meta SOP Class UID, standard or private. Again either a numeric UID +or a symbolic value as defined in DCMTK can be used. + +The second part denotes a list of transfer syntaxes defined in the +[[TransferSyntaxes]] supersection. The list is referenced by its +section header, which is used as a symbolic label here. + +The following example shows one presentation context list that could +be used by an association requestor (Store SCU) to negotiate both +lossy-compressed and uncompressed transmission of DICOM ultrasound +images. + +[StorageSCUJPEGBaselineAndUncompressed] +PresentationContext1 = UltrasoundImageStorage\JPEGBaseline +PresentationContext2 = UltrasoundImageStorage\Uncompressed +PresentationContext3 = UltrasoundMultiframeImageStorage\JPEGBaseline +PresentationContext4 = UltrasoundMultiframeImageStorage\Uncompressed + +In the case of an association acceptor (SCP), each SOP class must appear +only once in the list. The following example would be a valid transfer +syntax list for an SCP, accepting only uncompressed ultrasound images: + +[StorageSCPUncompressed] +PresentationContext1 = UltrasoundImageStorage\Uncompressed +PresentationContext2 = UltrasoundMultiframeImageStorage\Uncompressed + +It should be noted that it is the user's responsibility to enforce the +rules defined in the DICOM standard on default transfer syntaxes, i. e. +LittleEndianImplicit has to be offered/accepted for each SOP class in at +least one presentation context unless the image is only available in +lossy compressed form. + + +2.3 SCP/SCU ROLE SELECTION + +This optional supersection contains one or more sections with arbitrary +user-defined but unique section names that are used as symbolic labels. +Within each section, one or more key/value pairs are contained. The key +names are "Role1", "Role2" etc., in increasing order. + +Each value consists of two parts, separated by a single backslash +character ('\'). The first value denotes a DICOM SOP Class UID or +Meta SOP Class UID, standard or private. Again either a numeric UID +or a symbolic value as defined in DCMTK can be used. Each SOP class +should only appear once in the list. + +The second part denotes the roles the application is going to negotiate +for this SOP class. Possible keywords are "SCU", "SCP", or "BOTH", +indicating that the application supports the SCU role, the SCP role or +both roles. Any SOP class that is negotiated but not contained in the +SCP/SCU role selection list will be negotiated with default roles, +i. e. association requestor is SCU and association acceptor is SCP. + +The following example shows a list for SCP/SCU role selection where +an application supports both SCU and SCP roles for transmission +of ultrasound images. + +[USStorageBothRoles] +Role1 = UltrasoundImageStorage\BOTH +Role2 = UltrasoundMultiframeImageStorage\BOTH + +It should be noted that neither storescu nor storescp currently support +SCP/SCU role negotiation, so this functionality should not be used with +these two tools. + + +2.4 EXTENDED NEGOTIATION + +This optional supersection contains one or more sections with arbitrary +user-defined but unique section names that are used as symbolic labels. +Within each section, one or more key/value pairs are contained. The key +names are "ExtendedNegotiation1", "ExtendedNegotiation2" etc., in +increasing order. + +Each value consists of two parts, separated by a single backslash +character ('\'). The first value denotes a DICOM SOP Class UID or +Meta SOP Class UID, standard or private. Again either a numeric UID +or a symbolic value as defined in DCMTK can be used. Each SOP class +should only appear once in the list. + +The second part denotes the SOP class extended negotiation to be +performed for this SOP class. This part contains raw data in hexadecimal +encoding. Any SOP class that is negotiated but not contained in the +extended negotiation list will be negotiated without extended +negotiation. See DICOM standard for a list of SOP classes that support +extended negotiation. + +The following example shows an extended negotiation list for a +storage SCP that accepts Structured Reporting documents as a +"Level 2 SCP", with "Signature Level 3" and no element coercion +(see DICOM part 4, section B.3.1 for details). + +[USSignaturePreservingSCP] +ExtendedNegotiation1 = UltrasoundImageStorage\020003000000 +ExtendedNegotiation2 = UltrasoundMultiframeImageStorage\020003000000 + + +2.5 PROFILES + +This supersection contains one or more sections with arbitrary +user-defined but unique section names that are used as symbolic labels +identifying complete "profiles" for association negotiation that +can be selected by a user or application. + +Each profile consists at least of a reference to one list of +presentation contexts. It may also reference one list of SCP/SCU role +selection items and one list of extended negotiation items, but both of +these are optional. The references use the symbolic section names +defined in the supersections for presentation contexts, role selection +and extended negotiation. + +The following example shows a profile of a hypothetical Storage SCP that +supports the DICOM ultrasound image storage SOP classes both in lossy +JPEG and uncompressed form, supports both SCP and SCU roles for these +SOP classes and also guarantees signature preserving behaviour using +extended negotiation. + +[UltrasoundProfile] +PresentationContexts = StorageSCPJPEGBaselineAndUncompressed +SCPSCURoleSelection = USStorageBothRoles +ExtendedNegotiation = USSignaturePreservingSCP + +A configuration file may contain one or more association negotiation +profiles, but each association request or association negotiation +procedure can use exactly one of these profiles. + + +3. EXAMPLES + +Examples for association negotiation profiles that can be used +with the storescu and storescp tools are provided with DCMTK, as +"storescp.cfg" and "storescu.cfg" in the directory. diff --git a/dcmnet/docs/cptscp.dox b/dcmnet/docs/cptscp.dox new file mode 100644 index 00000000..0b977e3f --- /dev/null +++ b/dcmnet/docs/cptscp.dox @@ -0,0 +1,32 @@ +/** @defgroup SCPThread_Concept SCP Thread Concept + * A SCP object should follow this concept to be used in DcmSCPPool. The + * easiest and recommended way to follow this concept is to derive your + * class from DcmThreadSCP. + * @ingroup Concepts + * @{ + */ + +/** The SCP must be default constructible. + */ +DefaultConstructor(); + +/** The SCP must be configurable by setting it's configuration with + * this method. + * @param config the configuration to be used by the SCP. + * @return EC_Normal if configuration is accepted, error otherwise. + */ +OFCondition setConfig(const DcmSCPConfig& config); + +/** Returns OFTrue if SCP currently runs an association. + * @return OFTrue if currently connected, OFFalse otherwise. + */ +OFBool isConnected(); + +/** Take over incoming association that is in the state that the underlying + * TCP/IP connection is already accepted, while the ACSE negotiation + * is not already done but must be implemented by this method. + * @param assoc The association to run. + */ +OFCondition run( T_ASC_Association* assoc ); + +/// @} diff --git a/dcmnet/docs/dcmnet.dox b/dcmnet/docs/dcmnet.dox new file mode 100644 index 00000000..cb72ca85 --- /dev/null +++ b/dcmnet/docs/dcmnet.dox @@ -0,0 +1,96 @@ +/*! + +\page mod_dcmnet dcmnet: a networking library and utility apps + +This module contains a collection of functions that implement DICOM network +communication, i.e. the DICOM Upper Layer Finite State Machine, the Association +Control Service Element (ACSE) and the DICOM Message Service Element (DIMSE). + +The main interfaces are the structs and functions declared in file assoc.h and +dimse.h. + +There are also two experimental classes for implementing a DICOM Service Class +User and Provider: +\li \b DcmSCU +\li \b DcmSCP + +The following classes are derived from the above experimental classes and +provide a particular DICOM Service: +\li \b DcmStorageSCU +\li \b DcmStorageSCP + +\section Tools + +This module contains the following command line tools: +\li \ref dcmrecv +\li \ref dcmsend +\li \ref echoscu +\li \ref findscu +\li \ref getscu +\li \ref movescu +\li \ref storescp +\li \ref storescu +\li \ref termscu + +\section Files + +The following files provide further documentation: +\li \ref file_asconfig +\li \ref file_testing + +\section Examples + +The following example shows a very simple Echo SCU (Verification Service Class +SCU). Most error handling code has been omitted for brevity, also OS specific +code such as WinSock initialization on Win32 is not shown. + +\code +T_ASC_Network *net; // network struct, contains DICOM upper layer FSM etc. +ASC_initializeNetwork(NET_REQUESTOR, 0, 1000 /* timeout */, &net); + +T_ASC_Parameters *params; // parameters of association request +ASC_createAssociationParameters(¶ms, ASC_DEFAULTMAXPDU); + +// set calling and called AE titles +ASC_setAPTitles(params, "ECHOSCU", "ANY-SCP", NULL); + +// the DICOM server accepts connections at server.nowhere.com port 104 +ASC_setPresentationAddresses(params, "localhost", "server.nowhere.com:104"); + +// list of transfer syntaxes, only a single entry here +const char* ts[] = { UID_LittleEndianImplicitTransferSyntax }; + +// add presentation context to association request +ASC_addPresentationContext(params, 1, UID_VerificationSOPClass, ts, 1); + +// request DICOM association +T_ASC_Association *assoc; +if (ASC_requestAssociation(net, params, &assoc).good()) +{ + if (ASC_countAcceptedPresentationContexts(params) == 1) + { + // the remote SCP has accepted the Verification Service Class + DIC_US id = assoc->nextMsgID++; // generate next message ID + DIC_US status; // DIMSE status of C-ECHO-RSP will be stored here + DcmDataset *sd = NULL; // status detail will be stored here + // send C-ECHO-RQ and handle response + DIMSE_echoUser(assoc, id, DIMSE_BLOCKING, 0, &status, &sd); + delete sd; // we don't care about status detail + } +} +ASC_releaseAssociation(assoc); // release association +ASC_destroyAssociation(&assoc); // delete assoc structure +ASC_dropNetwork(&net); // delete net structure +\endcode + +*/ + +/*! + \page file_asconfig asconfig.txt file + \verbinclude asconfig.txt +*/ + +/*! + \page file_testing testing.txt file + \verbinclude testing.txt +*/ diff --git a/dcmnet/docs/dcmrecv.man b/dcmnet/docs/dcmrecv.man new file mode 100644 index 00000000..e76bfea6 --- /dev/null +++ b/dcmnet/docs/dcmrecv.man @@ -0,0 +1,360 @@ +/*! + +\if MANPAGES +\page dcmrecv Simple DICOM storage SCP (receiver) +\else +\page dcmrecv dcmrecv: Simple DICOM storage SCP (receiver) +\endif + +\section synopsis SYNOPSIS + +\verbatim +dcmrecv [options] port +\endverbatim + +\section description DESCRIPTION + +The \b dcmrecv application implements a Service Class Provider (SCP) for the +Storage Service Class. In contrast to the well-known \b storescp utility, +\b dcmrecv has less options and might, therefore, be easier to use - this also +explains the term "simple" in the title. The main purpose of this application +is to receive a whole bunch of DICOM datasets from a Storage Service Class User +(SCU) and store them to a configurable directory and file structure. + +\section parameters PARAMETERS + +\verbatim +port tcp/ip port number to listen on +\endverbatim + +\section options OPTIONS + +\subsection general_options general options +\verbatim + -h --help + print this help text and exit + + --version + print version information and exit + + --arguments + print expanded command line arguments + + -q --quiet + quiet mode, print no warnings and errors + + -v --verbose + verbose mode, print processing details + + -d --debug + debug mode, print debug information + + -ll --log-level [l]evel: string constant + (fatal, error, warn, info, debug, trace) + use level l for the logger + + -lc --log-config [f]ilename: string + use config file f for the logger + + +v --verbose-pc + show presentation contexts in verbose mode +\endverbatim + + +\subsection network_options network options +\verbatim +association negotiation profile from configuration file: + + -xf --config-file [f]ilename, [p]rofile: string + use profile p from configuration file f + +application entity title: + + -aet --aetitle [a]etitle: string + set my AE title (default: DCMRECV) + + -uca --use-called-aetitle + always respond with called AE title + +other network options: + + -ta --acse-timeout [s]econds: integer (default: 30) + timeout for ACSE messages + + -td --dimse-timeout [s]econds: integer (default: unlimited) + timeout for DIMSE messages + + -pdu --max-pdu [n]umber of bytes: integer (4096..131072) + set max receive pdu to n bytes (default: 16384) + + -dhl --disable-host-lookup disable hostname lookup +\endverbatim + +\subsection output_options output options +\verbatim +general: + + -od --output-directory [d]irectory: string (default: ".") + write received objects to existing directory d + +subdirectory generation: + + -s --no-subdir + do not generate any subdirectories (default) + + +ssd --series-date-subdir + generate subdirectories from series date + +filename generation: + + +fd --default-filenames + generate filename from instance UID (default) + + +fu --unique-filenames + generate unique filename based on new UID + + +fsu --short-unique-names + generate short pseudo-random unique filename + + +fst --system-time-names + generate filename from current system time + + -fe --filename-extension [e]xtension: string (default: none) + append e to all generated filenames + +storage mode: + + -B --normal + allow implicit format conversions (default) + + +B --bit-preserving + write dataset exactly as received + + --ignore + ignore dataset, receive but do not store it +\endverbatim + +\section notes NOTES + +\subsection typical_usage Typical Usage + +A typical use case of \b dcmrecv is to receive SOP instances that are sent from +a storage SCU and save them as DICOM files. The following command does exactly +this: + +\verbatim +dcmrecv --verbose --config-file storescp.cfg default +\endverbatim + +If you prefer some automatically created subdirectory structure, shorter file +names and the extension ".dcm" for all DICOM files, use the following command: + +\verbatim +dcmrecv -v -xf storescp.cfg default --series-date-subdir + --short-unique-names + --filename-extension .dcm +\endverbatim + +In case of very large SOP instances or if the dataset should be written exactly +as received (e.g. for debugging purposes), the "bit preserving mode" could be +used: + +\verbatim +dcmrecv -v -xf storescp.cfg default --bit-preserving +\endverbatim + +The received datasets are always stored as DICOM files with the same Transfer +Syntax as used for the network transmission. + +\subsection dicom_conformance DICOM Conformance + +Basically, the \b dcmrecv application supports all Storage SOP Classes as an +SCP, including private ones. This requires, however, that a corresponding +association negotiation profile is loaded from a configuration file. The format +and semantics of this configuration file are documented in \e asconfig.txt. + +By default, that means if no association negotiation profile is loaded, +\b dcmrecv only supports the Verification SOP Class as an SCP (with default +transfer syntax, i.e. Implicit VR Litte Endian). + +In the future, there might be additional options that allow for specifying the +list of supported Presentation Contexts (i.e. combination of SOP Class and +Transfer Syntaxes) directly, i.e. without loading a configuration file. + +\subsection subdirectory_generation Subdirectory Generation + +The option \e --series-date-subdir allows for generating subdirectories (below +the specified output directory) based on the value of the data element Series +Date (0008,0021) from the received DICOM dataset. If this value could be +retrieved from the dataset and is valid (i.e. consists of a valid DICOM date +field), the subdirectory structure is as follows: + +\verbatim +/data//// +\endverbatim + +If the Series Date (0008,0021) cannot be retrieved or is invalid, the current +system date is used for the following subdirectory structure: + +\verbatim +/undef// +\endverbatim + +In both cases, \ consists of 4 decimal digits and \ as well as +\ of 2 decimal digits. + +\subsection filename_generation Filename Generation + +By default, the filenames for storing the received DICOM datasets are generated +according to the following scheme: + +\verbatim +. +\endverbatim + +If the same SOP instance is received twice, a warning message is reported and +the existing file is overwritten. + +The option \e --unique-filenames makes sure that each received DICOM dataset is +stored as a separate file, i.e. no files should ever be overwritten. This is +done by using a newly created unique identifier (UID) for each generated +filename (and the infix ".X" in order to avoid conflicts with real SOP Instance +UID values). The naming scheme for this option is as follows: + +\verbatim +.X. +\endverbatim + +When option \e --short-unique-names is used, the filenames are generated +by some pseudo-random name generator, which also makes sure that there are +no conflicts (i.e. existing files are not overwritten). This is the naming +scheme: + +\verbatim +_ +\endverbatim + +With \ consisting of 16 digits in hexadecimal notation. + +Finally, option \e --system-time-names allows for generating filenames based +on the current system time: + +\verbatim +